diff --git a/bun.lock b/bun.lock index 7812986..83316c1 100644 --- a/bun.lock +++ b/bun.lock @@ -9,6 +9,7 @@ "zod": "^4.5.4", }, "devDependencies": { + "@opentui/core": "^0.5.9", "@opentui/keymap": "^0.5.9", "@opentui/solid": "^0.5.9", "@types/bun": "^1.3.14", @@ -24,6 +25,7 @@ "solid-js": ">=1.9.0", }, "optionalPeers": [ + "@opentui/core", "@opentui/keymap", "@opentui/solid", "opentui-spinner", diff --git a/dist/chunk-ydf2rnsn.js b/dist/chunk-2n7bvge9.js similarity index 98% rename from dist/chunk-ydf2rnsn.js rename to dist/chunk-2n7bvge9.js index 28f1caa..0a5d899 100644 --- a/dist/chunk-ydf2rnsn.js +++ b/dist/chunk-2n7bvge9.js @@ -1,7 +1,7 @@ // @bun import { Modal -} from "./chunk-840y6ygm.js"; +} from "./chunk-4j2gzwtd.js"; import { helpOpen, toggleHelp diff --git a/dist/chunk-840y6ygm.js b/dist/chunk-4j2gzwtd.js similarity index 92% rename from dist/chunk-840y6ygm.js rename to dist/chunk-4j2gzwtd.js index b18ab61..5ea7ebb 100644 --- a/dist/chunk-840y6ygm.js +++ b/dist/chunk-4j2gzwtd.js @@ -37,7 +37,7 @@ function Modal(props) { _$setProp(_el$2, "paddingBottom", 1); _$insert(_el$2, () => props.children); _$effect((_p$) => { - var _v$ = dimensions().width, _v$2 = dimensions().height, _v$3 = Math.floor(dimensions().height / 4), _v$4 = props.backdropColor ?? RGBA.fromInts(0, 0, 0, 150), _v$5 = theme.mouse ? props.onDismiss : undefined, _v$6 = props.width ?? 50, _v$7 = theme.borderStyle, _v$8 = props.accentColor ?? theme.primary, _v$9 = props.backgroundColor ?? theme.background; + var _v$ = dimensions().width, _v$2 = dimensions().height, _v$3 = Math.floor(dimensions().height / 4), _v$4 = props.backdropColor ?? RGBA.fromInts(0, 0, 0, 150), _v$5 = theme.mouse ? props.onDismiss : undefined, _v$6 = props.width ?? 50, _v$7 = theme.borderStyle, _v$8 = props.accentColor ?? theme.primary, _v$9 = props.backgroundColor ?? theme.background, _v$0 = theme.mouse ? (event) => event.stopPropagation() : undefined; _v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e)); _v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "height", _v$2, _p$.t)); _v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "paddingTop", _v$3, _p$.a)); @@ -47,6 +47,7 @@ function Modal(props) { _v$7 !== _p$.s && (_p$.s = _$setProp(_el$2, "borderStyle", _v$7, _p$.s)); _v$8 !== _p$.h && (_p$.h = _$setProp(_el$2, "borderColor", _v$8, _p$.h)); _v$9 !== _p$.r && (_p$.r = _$setProp(_el$2, "backgroundColor", _v$9, _p$.r)); + _v$0 !== _p$.d && (_p$.d = _$setProp(_el$2, "onMouseDown", _v$0, _p$.d)); return _p$; }, { e: undefined, @@ -57,7 +58,8 @@ function Modal(props) { n: undefined, s: undefined, h: undefined, - r: undefined + r: undefined, + d: undefined }); return _el$; } diff --git a/dist/chunk-d2tt920p.js b/dist/chunk-4jy6s3k0.js similarity index 73% rename from dist/chunk-d2tt920p.js rename to dist/chunk-4jy6s3k0.js index 9668401..8eba58b 100644 --- a/dist/chunk-d2tt920p.js +++ b/dist/chunk-4jy6s3k0.js @@ -4,7 +4,6 @@ import { } from "./chunk-57mam43k.js"; // src/components/Tabs.tsx -import { createTextNode as _$createTextNode } from "@opentui/solid"; import { effect as _$effect } from "@opentui/solid"; import { insertNode as _$insertNode } from "@opentui/solid"; import { createComponent as _$createComponent } from "@opentui/solid"; @@ -12,7 +11,7 @@ import { insert as _$insert } from "@opentui/solid"; import { use as _$use } from "@opentui/solid"; import { setProp as _$setProp } from "@opentui/solid"; import { createElement as _$createElement } from "@opentui/solid"; -import { CliRenderEvents, TextAttributes } from "@opentui/core"; +import { BorderChars, CliRenderEvents, TextAttributes } from "@opentui/core"; import { onResize, useRenderer } from "@opentui/solid"; import { createMemo, createSignal, For } from "solid-js"; function stepTabValue(items, value, delta) { @@ -27,21 +26,21 @@ function innerWidth(label) { function segmentWidth(label) { return innerWidth(label) + 2; } -function topEdge(label) { - return `\u256D${"\u2500".repeat(innerWidth(label))}\u256E`; +function topEdge(chars, label) { + return `${chars.topLeft}${chars.horizontal.repeat(innerWidth(label))}${chars.topRight}`; } -function bottomEdge(label, isFirst, isLast, isActive) { - const left = isFirst ? isActive ? "\u2502" : "\u251C" : isActive ? "\u256F" : "\u2534"; - const right = isLast ? isActive ? "\u2502" : "\u2524" : isActive ? "\u2570" : "\u2534"; - const fill = isActive ? " " : "\u2500"; +function bottomEdge(chars, label, isFirst, isLast, isActive) { + const left = isFirst ? isActive ? chars.vertical : chars.leftT : isActive ? chars.bottomRight : chars.bottomT; + const right = isLast ? isActive ? chars.vertical : chars.rightT : isActive ? chars.bottomLeft : chars.bottomT; + const fill = isActive ? " " : chars.horizontal; return left + fill.repeat(innerWidth(label)) + right; } -function buildBottomRow(segments, available) { +function buildBottomRow(chars, segments, available) { const tabsWidth = segments.reduce((sum, s) => sum + segmentWidth(s.label), 0); const remainder = available - tabsWidth; const extending = remainder > 0; - const tabs = segments.map((s, i) => bottomEdge(s.label, i === 0, i === segments.length - 1 && !extending, s.isActive)).join(""); - return extending ? tabs + "\u2500".repeat(remainder - 1) + "\u256E" : tabs; + const tabs = segments.map((s, i) => bottomEdge(chars, s.label, i === 0, i === segments.length - 1 && !extending, s.isActive)).join(""); + return extending ? tabs + chars.horizontal.repeat(remainder - 1) + chars.topRight : tabs; } function fitCount(items, start, available) { const hiddenBefore = start; @@ -102,6 +101,7 @@ function Tabs(props) { const accent = () => props.accentColor ?? theme.primary; const muted = () => props.mutedColor ?? theme.muted; const borderColor = () => props.focused ? accent() : muted(); + const chars = BorderChars[theme.borderStyle]; return (() => { var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("box"), _el$4 = _$createElement("text"); _$insertNode(_el$, _el$2); @@ -112,7 +112,8 @@ function Tabs(props) { remeasureNextFrame(); }, _el$); _$setProp(_el$, "flexDirection", "column"); - _$insert(_el$2, () => segments().map((s) => topEdge(s.label)).join("")); + _$setProp(_el$2, "selectable", false); + _$insert(_el$2, () => segments().map((s) => topEdge(chars, s.label)).join("")); _$setProp(_el$3, "flexDirection", "row"); _$insert(_el$3, _$createComponent(For, { get each() { @@ -120,32 +121,36 @@ function Tabs(props) { }, children: (s) => [(() => { var _el$5 = _$createElement("text"); - _$insertNode(_el$5, _$createTextNode(`\u2502`)); + _$setProp(_el$5, "selectable", false); + _$insert(_el$5, () => chars.vertical); _$effect((_$p) => _$setProp(_el$5, "fg", borderColor(), _$p)); return _el$5; })(), (() => { - var _el$7 = _$createElement("text"); - _$insert(_el$7, () => ` ${s.label} `); + var _el$6 = _$createElement("text"); + _$setProp(_el$6, "selectable", false); + _$insert(_el$6, () => ` ${s.label} `); _$effect((_p$) => { var _v$3 = s.isActive ? accent() : muted(), _v$4 = s.isActive ? TextAttributes.BOLD : undefined, _v$5 = theme.mouse && s.value !== undefined ? () => props.onChange(s.value) : undefined; - _v$3 !== _p$.e && (_p$.e = _$setProp(_el$7, "fg", _v$3, _p$.e)); - _v$4 !== _p$.t && (_p$.t = _$setProp(_el$7, "attributes", _v$4, _p$.t)); - _v$5 !== _p$.a && (_p$.a = _$setProp(_el$7, "onMouseDown", _v$5, _p$.a)); + _v$3 !== _p$.e && (_p$.e = _$setProp(_el$6, "fg", _v$3, _p$.e)); + _v$4 !== _p$.t && (_p$.t = _$setProp(_el$6, "attributes", _v$4, _p$.t)); + _v$5 !== _p$.a && (_p$.a = _$setProp(_el$6, "onMouseDown", _v$5, _p$.a)); return _p$; }, { e: undefined, t: undefined, a: undefined }); - return _el$7; + return _el$6; })(), (() => { - var _el$8 = _$createElement("text"); - _$insertNode(_el$8, _$createTextNode(`\u2502`)); - _$effect((_$p) => _$setProp(_el$8, "fg", borderColor(), _$p)); - return _el$8; + var _el$7 = _$createElement("text"); + _$setProp(_el$7, "selectable", false); + _$insert(_el$7, () => chars.vertical); + _$effect((_$p) => _$setProp(_el$7, "fg", borderColor(), _$p)); + return _el$7; })()] })); - _$insert(_el$4, () => buildBottomRow(segments(), width())); + _$setProp(_el$4, "selectable", false); + _$insert(_el$4, () => buildBottomRow(chars, segments(), width())); _$effect((_p$) => { var _v$ = borderColor(), _v$2 = borderColor(); _v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "fg", _v$, _p$.e)); diff --git a/dist/chunk-nr74cgcr.js b/dist/chunk-nr74cgcr.js new file mode 100644 index 0000000..15e1edc --- /dev/null +++ b/dist/chunk-nr74cgcr.js @@ -0,0 +1,54 @@ +// @bun +import { + theme +} from "./chunk-57mam43k.js"; + +// src/components/MinSizeGuard.tsx +import { createComponent as _$createComponent } from "@opentui/solid"; +import { effect as _$effect } from "@opentui/solid"; +import { insertNode as _$insertNode } from "@opentui/solid"; +import { insert as _$insert } from "@opentui/solid"; +import { setProp as _$setProp } from "@opentui/solid"; +import { createElement as _$createElement } from "@opentui/solid"; +import { memo as _$memo } from "@opentui/solid"; +import { useTerminalDimensions } from "@opentui/solid"; +import { Show } from "solid-js"; +function MinSizeGuard(props) { + const dimensions = useTerminalDimensions(); + const minWidth = () => props.minWidth ?? 80; + const minHeight = () => props.minHeight ?? 24; + const tooSmall = () => dimensions().width < minWidth() || dimensions().height < minHeight(); + return [_$memo(() => props.children), _$createComponent(Show, { + get when() { + return tooSmall(); + }, + get children() { + var _el$ = _$createElement("box"), _el$2 = _$createElement("text"); + _$insertNode(_el$, _el$2); + _$setProp(_el$, "position", "absolute"); + _$setProp(_el$, "top", 0); + _$setProp(_el$, "left", 0); + _$setProp(_el$, "alignItems", "center"); + _$setProp(_el$, "justifyContent", "center"); + _$setProp(_el$, "zIndex", 9999); + _$insert(_el$2, () => `Terminal too small +Minimum size: ${minWidth()}x${minHeight()} \u2014 current: ${dimensions().width}x${dimensions().height}`); + _$effect((_p$) => { + var _v$ = dimensions().width, _v$2 = dimensions().height, _v$3 = props.backgroundColor ?? theme.background, _v$4 = props.textColor ?? theme.muted; + _v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e)); + _v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "height", _v$2, _p$.t)); + _v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "backgroundColor", _v$3, _p$.a)); + _v$4 !== _p$.o && (_p$.o = _$setProp(_el$2, "fg", _v$4, _p$.o)); + return _p$; + }, { + e: undefined, + t: undefined, + a: undefined, + o: undefined + }); + return _el$; + } + })]; +} + +export { MinSizeGuard }; diff --git a/dist/chunk-syn54rcq.js b/dist/chunk-syn54rcq.js deleted file mode 100644 index 305f23f..0000000 --- a/dist/chunk-syn54rcq.js +++ /dev/null @@ -1,60 +0,0 @@ -// @bun -import { - theme -} from "./chunk-57mam43k.js"; - -// src/components/MinSizeGuard.tsx -import { createComponent as _$createComponent } from "@opentui/solid"; -import { effect as _$effect } from "@opentui/solid"; -import { insertNode as _$insertNode } from "@opentui/solid"; -import { insert as _$insert } from "@opentui/solid"; -import { setProp as _$setProp } from "@opentui/solid"; -import { createElement as _$createElement } from "@opentui/solid"; -import { useTerminalDimensions } from "@opentui/solid"; -import { Match, Switch } from "solid-js"; -function MinSizeGuard(props) { - const dimensions = useTerminalDimensions(); - const minWidth = () => props.minWidth ?? 80; - const minHeight = () => props.minHeight ?? 24; - const tooSmall = () => dimensions().width < minWidth() || dimensions().height < minHeight(); - return _$createComponent(Switch, { - get children() { - return [_$createComponent(Match, { - get when() { - return tooSmall(); - }, - get children() { - var _el$ = _$createElement("box"), _el$2 = _$createElement("text"); - _$insertNode(_el$, _el$2); - _$setProp(_el$, "alignItems", "center"); - _$setProp(_el$, "justifyContent", "center"); - _$insert(_el$2, () => `Terminal too small -Minimum size: ${minWidth()}x${minHeight()} \u2014 current: ${dimensions().width}x${dimensions().height}`); - _$effect((_p$) => { - var _v$ = dimensions().width, _v$2 = dimensions().height, _v$3 = props.backgroundColor ?? theme.background, _v$4 = props.textColor ?? theme.muted; - _v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e)); - _v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "height", _v$2, _p$.t)); - _v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "backgroundColor", _v$3, _p$.a)); - _v$4 !== _p$.o && (_p$.o = _$setProp(_el$2, "fg", _v$4, _p$.o)); - return _p$; - }, { - e: undefined, - t: undefined, - a: undefined, - o: undefined - }); - return _el$; - } - }), _$createComponent(Match, { - get when() { - return !tooSmall(); - }, - get children() { - return props.children; - } - })]; - } - }); -} - -export { MinSizeGuard }; diff --git a/dist/chunk-vve1k0ax.js b/dist/chunk-vve1k0ax.js new file mode 100644 index 0000000..48c66a0 --- /dev/null +++ b/dist/chunk-vve1k0ax.js @@ -0,0 +1,128 @@ +// @bun +import { + presets, + theme +} from "./chunk-57mam43k.js"; + +// src/components/Sidebar.tsx +import { use as _$use } from "@opentui/solid"; +import { createComponent as _$createComponent } from "@opentui/solid"; +import { createTextNode as _$createTextNode } from "@opentui/solid"; +import { insertNode as _$insertNode } from "@opentui/solid"; +import { effect as _$effect } from "@opentui/solid"; +import { insert as _$insert } from "@opentui/solid"; +import { setProp as _$setProp } from "@opentui/solid"; +import { createElement as _$createElement } from "@opentui/solid"; +import { TextAttributes } from "@opentui/core"; +import { Show } from "solid-js"; +function itemIndexAtScreenY(el, screenY) { + const internals = el; + if (!internals.linesPerItem) + return null; + const localY = screenY - el.screenY; + if (localY < 0) + return null; + const index = internals.scrollOffset + Math.floor(localY / internals.linesPerItem); + return index >= 0 && index < el.options.length ? index : null; +} +function Sidebar(props) { + let select; + const handleMouseDown = (event) => { + if (!select) + return; + const index = itemIndexAtScreenY(select, event.y); + if (index !== null) + select.setSelectedIndex(index); + }; + const handleMouseScroll = (event) => { + if (!select || !event.scroll) + return; + const steps = Math.max(1, event.scroll.delta); + if (event.scroll.direction === "down") + select.moveDown(steps); + else if (event.scroll.direction === "up") + select.moveUp(steps); + }; + return (() => { + var _el$ = _$createElement("box"), _el$5 = _$createElement("select"); + _$insertNode(_el$, _el$5); + _$setProp(_el$, "border", true); + _$setProp(_el$, "flexDirection", "column"); + _$insert(_el$, _$createComponent(Show, { + get when() { + return props.title; + }, + get children() { + return [(() => { + var _el$2 = _$createElement("text"); + _$insert(_el$2, () => props.title); + _$effect((_$p) => _$setProp(_el$2, "attributes", TextAttributes.BOLD, _$p)); + return _el$2; + })(), (() => { + var _el$3 = _$createElement("text"); + _$insertNode(_el$3, _$createTextNode(` `)); + return _el$3; + })()]; + } + }), _el$5); + _$use((el) => { + select = el ?? undefined; + props.ref?.(el && { + moveUp: () => el.moveUp(), + moveDown: () => el.moveDown(), + selectCurrent: () => el.selectCurrent(), + focus: () => el.focus() + }); + }, _el$5); + _$setProp(_el$5, "flexGrow", 1); + _$setProp(_el$5, "showScrollIndicator", true); + _$setProp(_el$5, "onChange", (_index, option) => { + if (!option) + return; + props.onSelect(option); + }); + _$setProp(_el$5, "onSelect", (_index, option) => { + if (!option) + return; + props.onConfirm?.(option); + }); + _$effect((_p$) => { + var _v$ = props.width ?? 24, _v$2 = theme.borderStyle, _v$3 = props.focused ? props.accentColor ?? theme.primary : props.mutedColor ?? theme.muted, _v$4 = props.focused, _v$5 = props.items, _v$6 = theme.mouse ? handleMouseDown : undefined, _v$7 = theme.mouse ? handleMouseScroll : undefined, _v$8 = props.backgroundColor ?? "transparent", _v$9 = props.textColor ?? presets.select.textColor, _v$0 = props.focusedBackgroundColor ?? "transparent", _v$1 = props.focusedTextColor ?? presets.select.focusedTextColor, _v$10 = props.selectedBackgroundColor ?? presets.select.selectedBackgroundColor, _v$11 = props.selectedTextColor ?? presets.select.selectedTextColor, _v$12 = props.descriptionColor ?? presets.select.descriptionColor, _v$13 = props.selectedDescriptionColor ?? presets.select.selectedDescriptionColor; + _v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e)); + _v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "borderStyle", _v$2, _p$.t)); + _v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "borderColor", _v$3, _p$.a)); + _v$4 !== _p$.o && (_p$.o = _$setProp(_el$5, "focused", _v$4, _p$.o)); + _v$5 !== _p$.i && (_p$.i = _$setProp(_el$5, "options", _v$5, _p$.i)); + _v$6 !== _p$.n && (_p$.n = _$setProp(_el$5, "onMouseDown", _v$6, _p$.n)); + _v$7 !== _p$.s && (_p$.s = _$setProp(_el$5, "onMouseScroll", _v$7, _p$.s)); + _v$8 !== _p$.h && (_p$.h = _$setProp(_el$5, "backgroundColor", _v$8, _p$.h)); + _v$9 !== _p$.r && (_p$.r = _$setProp(_el$5, "textColor", _v$9, _p$.r)); + _v$0 !== _p$.d && (_p$.d = _$setProp(_el$5, "focusedBackgroundColor", _v$0, _p$.d)); + _v$1 !== _p$.l && (_p$.l = _$setProp(_el$5, "focusedTextColor", _v$1, _p$.l)); + _v$10 !== _p$.u && (_p$.u = _$setProp(_el$5, "selectedBackgroundColor", _v$10, _p$.u)); + _v$11 !== _p$.c && (_p$.c = _$setProp(_el$5, "selectedTextColor", _v$11, _p$.c)); + _v$12 !== _p$.w && (_p$.w = _$setProp(_el$5, "descriptionColor", _v$12, _p$.w)); + _v$13 !== _p$.m && (_p$.m = _$setProp(_el$5, "selectedDescriptionColor", _v$13, _p$.m)); + return _p$; + }, { + e: undefined, + t: undefined, + a: undefined, + o: undefined, + i: undefined, + n: undefined, + s: undefined, + h: undefined, + r: undefined, + d: undefined, + l: undefined, + u: undefined, + c: undefined, + w: undefined, + m: undefined + }); + return _el$; + })(); +} + +export { Sidebar }; diff --git a/dist/chunk-wkg33t3z.js b/dist/chunk-wkg33t3z.js deleted file mode 100644 index 9be64e3..0000000 --- a/dist/chunk-wkg33t3z.js +++ /dev/null @@ -1,78 +0,0 @@ -// @bun -import { - theme -} from "./chunk-57mam43k.js"; - -// src/components/Sidebar.tsx -import { effect as _$effect } from "@opentui/solid"; -import { insertNode as _$insertNode } from "@opentui/solid"; -import { use as _$use } from "@opentui/solid"; -import { insert as _$insert } from "@opentui/solid"; -import { setProp as _$setProp } from "@opentui/solid"; -import { createElement as _$createElement } from "@opentui/solid"; -import { TextAttributes } from "@opentui/core"; -function Sidebar(props) { - return (() => { - var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("select"); - _$insertNode(_el$, _el$2); - _$insertNode(_el$, _el$3); - _$setProp(_el$, "border", true); - _$setProp(_el$, "flexDirection", "column"); - _$insert(_el$2, () => props.title); - _$use((el) => { - props.ref?.(el && { - moveUp: () => el.moveUp(), - moveDown: () => el.moveDown(), - selectCurrent: () => el.selectCurrent() - }); - }, _el$3); - _$setProp(_el$3, "flexGrow", 1); - _$setProp(_el$3, "showScrollIndicator", true); - _$setProp(_el$3, "onChange", (_index, option) => { - if (!option) - return; - props.onSelect(option); - }); - _$setProp(_el$3, "onSelect", (_index, option) => { - if (!option) - return; - props.onConfirm?.(option); - }); - _$effect((_p$) => { - var _v$ = props.width ?? 24, _v$2 = theme.borderStyle, _v$3 = props.focused ? props.accentColor ?? theme.primary : props.mutedColor ?? theme.muted, _v$4 = TextAttributes.BOLD, _v$5 = props.focused, _v$6 = props.items, _v$7 = props.backgroundColor, _v$8 = props.textColor, _v$9 = props.focusedBackgroundColor, _v$0 = props.focusedTextColor, _v$1 = props.selectedBackgroundColor, _v$10 = props.selectedTextColor, _v$11 = props.descriptionColor, _v$12 = props.selectedDescriptionColor; - _v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e)); - _v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "borderStyle", _v$2, _p$.t)); - _v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "borderColor", _v$3, _p$.a)); - _v$4 !== _p$.o && (_p$.o = _$setProp(_el$2, "attributes", _v$4, _p$.o)); - _v$5 !== _p$.i && (_p$.i = _$setProp(_el$3, "focused", _v$5, _p$.i)); - _v$6 !== _p$.n && (_p$.n = _$setProp(_el$3, "options", _v$6, _p$.n)); - _v$7 !== _p$.s && (_p$.s = _$setProp(_el$3, "backgroundColor", _v$7, _p$.s)); - _v$8 !== _p$.h && (_p$.h = _$setProp(_el$3, "textColor", _v$8, _p$.h)); - _v$9 !== _p$.r && (_p$.r = _$setProp(_el$3, "focusedBackgroundColor", _v$9, _p$.r)); - _v$0 !== _p$.d && (_p$.d = _$setProp(_el$3, "focusedTextColor", _v$0, _p$.d)); - _v$1 !== _p$.l && (_p$.l = _$setProp(_el$3, "selectedBackgroundColor", _v$1, _p$.l)); - _v$10 !== _p$.u && (_p$.u = _$setProp(_el$3, "selectedTextColor", _v$10, _p$.u)); - _v$11 !== _p$.c && (_p$.c = _$setProp(_el$3, "descriptionColor", _v$11, _p$.c)); - _v$12 !== _p$.w && (_p$.w = _$setProp(_el$3, "selectedDescriptionColor", _v$12, _p$.w)); - return _p$; - }, { - e: undefined, - t: undefined, - a: undefined, - o: undefined, - i: undefined, - n: undefined, - s: undefined, - h: undefined, - r: undefined, - d: undefined, - l: undefined, - u: undefined, - c: undefined, - w: undefined - }); - return _el$; - })(); -} - -export { Sidebar }; diff --git a/dist/components/HelpModal.js b/dist/components/HelpModal.js index cca0435..18d9286 100644 --- a/dist/components/HelpModal.js +++ b/dist/components/HelpModal.js @@ -1,8 +1,8 @@ // @bun import { HelpModal -} from "../chunk-ydf2rnsn.js"; -import"../chunk-840y6ygm.js"; +} from "../chunk-2n7bvge9.js"; +import"../chunk-4j2gzwtd.js"; import"../chunk-57mam43k.js"; import"../chunk-ergc99dh.js"; import"../chunk-7f8jagy5.js"; diff --git a/dist/components/MinSizeGuard.js b/dist/components/MinSizeGuard.js index a3c53e7..c06b6ba 100644 --- a/dist/components/MinSizeGuard.js +++ b/dist/components/MinSizeGuard.js @@ -1,7 +1,7 @@ // @bun import { MinSizeGuard -} from "../chunk-syn54rcq.js"; +} from "../chunk-nr74cgcr.js"; import"../chunk-57mam43k.js"; import"../chunk-ergc99dh.js"; import"../chunk-7f8jagy5.js"; diff --git a/dist/components/Modal.js b/dist/components/Modal.js index 2ccca98..4ac1345 100644 --- a/dist/components/Modal.js +++ b/dist/components/Modal.js @@ -1,7 +1,7 @@ // @bun import { Modal -} from "../chunk-840y6ygm.js"; +} from "../chunk-4j2gzwtd.js"; import"../chunk-57mam43k.js"; import"../chunk-ergc99dh.js"; import"../chunk-7f8jagy5.js"; diff --git a/dist/components/Sidebar.js b/dist/components/Sidebar.js index 384a273..0004fa8 100644 --- a/dist/components/Sidebar.js +++ b/dist/components/Sidebar.js @@ -1,7 +1,7 @@ // @bun import { Sidebar -} from "../chunk-wkg33t3z.js"; +} from "../chunk-vve1k0ax.js"; import"../chunk-57mam43k.js"; import"../chunk-ergc99dh.js"; import"../chunk-7f8jagy5.js"; diff --git a/dist/components/Tabs.js b/dist/components/Tabs.js index 312935b..1714b17 100644 --- a/dist/components/Tabs.js +++ b/dist/components/Tabs.js @@ -2,7 +2,7 @@ import { Tabs, stepTabValue -} from "../chunk-d2tt920p.js"; +} from "../chunk-4jy6s3k0.js"; import"../chunk-57mam43k.js"; import"../chunk-ergc99dh.js"; import"../chunk-7f8jagy5.js"; diff --git a/dist/components/help.js b/dist/components/help.js index 018d516..e78f376 100644 --- a/dist/components/help.js +++ b/dist/components/help.js @@ -1,8 +1,8 @@ // @bun import { HelpModal -} from "../chunk-ydf2rnsn.js"; -import"../chunk-840y6ygm.js"; +} from "../chunk-2n7bvge9.js"; +import"../chunk-4j2gzwtd.js"; import { HelpBar } from "../chunk-dv2w3sfk.js"; diff --git a/dist/components/index.js b/dist/components/index.js index 1fcf669..05fa14d 100644 --- a/dist/components/index.js +++ b/dist/components/index.js @@ -1,10 +1,7 @@ // @bun -import { - ProgressBar -} from "../chunk-ae0jkf2z.js"; import { Sidebar -} from "../chunk-wkg33t3z.js"; +} from "../chunk-vve1k0ax.js"; import { SignalBars } from "../chunk-xab9ag99.js"; @@ -14,19 +11,22 @@ import { import { Toggle } from "../chunk-zs53wnet.js"; +import { + MinSizeGuard +} from "../chunk-nr74cgcr.js"; import { Tabs, stepTabValue -} from "../chunk-d2tt920p.js"; +} from "../chunk-4jy6s3k0.js"; import { Modal -} from "../chunk-840y6ygm.js"; +} from "../chunk-4j2gzwtd.js"; import { Badge } from "../chunk-shxcerba.js"; import { - MinSizeGuard -} from "../chunk-syn54rcq.js"; + ProgressBar +} from "../chunk-ae0jkf2z.js"; import"../chunk-57mam43k.js"; import"../chunk-ergc99dh.js"; import"../chunk-7f8jagy5.js"; diff --git a/src/components/MinSizeGuard.tsx b/src/components/MinSizeGuard.tsx index 73d268f..bb88c03 100644 --- a/src/components/MinSizeGuard.tsx +++ b/src/components/MinSizeGuard.tsx @@ -1,6 +1,6 @@ import type { ColorInput } from "@opentui/core"; import { useTerminalDimensions } from "@opentui/solid"; -import { Match, Switch, type ParentProps } from "solid-js"; +import { Show, type ParentProps } from "solid-js"; import { theme } from "../index.ts"; export interface MinSizeGuardProps extends ParentProps { @@ -17,21 +17,25 @@ export function MinSizeGuard(props: MinSizeGuardProps) { const tooSmall = () => dimensions().width < minWidth() || dimensions().height < minHeight(); return ( - - + <> + {props.children} + {`Terminal too small\nMinimum size: ${minWidth()}x${minHeight()} — current: ${dimensions().width}x${dimensions().height}`} - - {props.children} - + + ); } diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index c1a4323..e839242 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -1,4 +1,4 @@ -import { type ColorInput, RGBA } from "@opentui/core"; +import { type ColorInput, type MouseEvent, RGBA } from "@opentui/core"; import { Portal, useTerminalDimensions } from "@opentui/solid"; import { Show, type ParentProps } from "solid-js"; import { theme } from "../index.ts"; @@ -41,6 +41,7 @@ export function Modal(props: ModalProps) { paddingRight={2} paddingTop={1} paddingBottom={1} + onMouseDown={theme.mouse ? (event: MouseEvent) => event.stopPropagation() : undefined} > {props.children} diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index de03a90..4fbefe5 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,14 +1,25 @@ -import { type ColorInput, type SelectOption, TextAttributes } from "@opentui/core"; -import { theme } from "../index.ts"; +import { type ColorInput, type MouseEvent, type SelectOption, type SelectRenderable, TextAttributes } from "@opentui/core"; +import { Show } from "solid-js"; +import { presets, theme } from "../index.ts"; export interface SidebarHandle { moveUp(): void; moveDown(): void; selectCurrent(): void; + focus(): void; +} + +function itemIndexAtScreenY(el: SelectRenderable, screenY: number): number | null { + const internals = el as unknown as { scrollOffset: number; linesPerItem: number }; + if (!internals.linesPerItem) return null; + const localY = screenY - el.screenY; + if (localY < 0) return null; + const index = internals.scrollOffset + Math.floor(localY / internals.linesPerItem); + return index >= 0 && index < el.options.length ? index : null; } export interface SidebarProps { - title: string; + title?: string; items: SelectOption[]; width?: number; focused?: boolean; @@ -30,6 +41,21 @@ export interface SidebarProps { } export function Sidebar(props: SidebarProps) { + let select: SelectRenderable | undefined; + + const handleMouseDown = (event: MouseEvent) => { + if (!select) return; + const index = itemIndexAtScreenY(select, event.y); + if (index !== null) select.setSelectedIndex(index); + }; + + const handleMouseScroll = (event: MouseEvent) => { + if (!select || !event.scroll) return; + const steps = Math.max(1, event.scroll.delta); + if (event.scroll.direction === "down") select.moveDown(steps); + else if (event.scroll.direction === "up") select.moveUp(steps); + }; + return ( - {props.title} + + {props.title} + +