Compare commits
4 commits
dev
...
claude/var
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10516cc4cb |
||
|
|
e38e24f743 |
||
|
|
8bff03f833 |
||
|
|
0b6d955560 |
3 changed files with 75 additions and 33 deletions
4
bun.lock
4
bun.lock
|
|
@ -1915,7 +1915,7 @@
|
||||||
|
|
||||||
"@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="],
|
"@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="],
|
||||||
|
|
||||||
"@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@dfb2020", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }, "sha512-7JjjA49VGNOsMRI8QRUhVudZmv0CnJ18SliSgK1ojszs/c3ijftgVkzvXdkSLN4miDTzbkXewf65D6ZBo6W+GQ=="],
|
"@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@dfb2020", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }],
|
||||||
|
|
||||||
"@speed-highlight/core": ["@speed-highlight/core@1.2.14", "", {}, "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA=="],
|
"@speed-highlight/core": ["@speed-highlight/core@1.2.14", "", {}, "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA=="],
|
||||||
|
|
||||||
|
|
@ -3041,7 +3041,7 @@
|
||||||
|
|
||||||
"get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],
|
"get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],
|
||||||
|
|
||||||
"ghostty-web": ["ghostty-web@github:anomalyco/ghostty-web#4af877d", {}, "anomalyco-ghostty-web-4af877d", "sha512-fbEK8mtr7ar4ySsF+JUGjhaZrane7dKphanN+SxHt5XXI6yLMAh/Hpf6sNCOyyVa2UlGCd7YpXG/T2v2RUAX+A=="],
|
"ghostty-web": ["ghostty-web@github:anomalyco/ghostty-web#4af877d", {}, "anomalyco-ghostty-web-4af877d"],
|
||||||
|
|
||||||
"gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="],
|
"gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ export function DialogVariant() {
|
||||||
title={"Select variant"}
|
title={"Select variant"}
|
||||||
current={local.model.variant.selected()}
|
current={local.model.variant.selected()}
|
||||||
flat={true}
|
flat={true}
|
||||||
|
hideFilter={true}
|
||||||
|
numbered={true}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ export interface DialogSelectProps<T> {
|
||||||
onFilter?: (query: string) => void
|
onFilter?: (query: string) => void
|
||||||
onSelect?: (option: DialogSelectOption<T>) => void
|
onSelect?: (option: DialogSelectOption<T>) => void
|
||||||
skipFilter?: boolean
|
skipFilter?: boolean
|
||||||
|
hideFilter?: boolean
|
||||||
|
numbered?: boolean
|
||||||
keybind?: {
|
keybind?: {
|
||||||
keybind?: Keybind.Info
|
keybind?: Keybind.Info
|
||||||
title: string
|
title: string
|
||||||
|
|
@ -194,6 +196,21 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||||
if (evt.name === "home") moveTo(0)
|
if (evt.name === "home") moveTo(0)
|
||||||
if (evt.name === "end") moveTo(flat().length - 1)
|
if (evt.name === "end") moveTo(flat().length - 1)
|
||||||
|
|
||||||
|
if (props.numbered && !evt.ctrl) {
|
||||||
|
const num = parseInt(evt.name, 10)
|
||||||
|
if (num >= 1 && num <= 9 && num <= flat().length) {
|
||||||
|
evt.preventDefault()
|
||||||
|
evt.stopPropagation()
|
||||||
|
const index = num - 1
|
||||||
|
const option = flat()[index]
|
||||||
|
if (option) {
|
||||||
|
if (option.onSelect) option.onSelect(dialog)
|
||||||
|
props.onSelect?.(option)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (evt.name === "return") {
|
if (evt.name === "return") {
|
||||||
const option = selected()
|
const option = selected()
|
||||||
if (option) {
|
if (option) {
|
||||||
|
|
@ -240,29 +257,31 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||||
esc
|
esc
|
||||||
</text>
|
</text>
|
||||||
</box>
|
</box>
|
||||||
<box paddingTop={1}>
|
<Show when={!props.hideFilter}>
|
||||||
<input
|
<box paddingTop={1}>
|
||||||
onInput={(e) => {
|
<input
|
||||||
batch(() => {
|
onInput={(e) => {
|
||||||
setStore("filter", e)
|
batch(() => {
|
||||||
props.onFilter?.(e)
|
setStore("filter", e)
|
||||||
})
|
props.onFilter?.(e)
|
||||||
}}
|
})
|
||||||
focusedBackgroundColor={theme.backgroundPanel}
|
}}
|
||||||
cursorColor={theme.primary}
|
focusedBackgroundColor={theme.backgroundPanel}
|
||||||
focusedTextColor={theme.textMuted}
|
cursorColor={theme.primary}
|
||||||
ref={(r) => {
|
focusedTextColor={theme.textMuted}
|
||||||
input = r
|
ref={(r) => {
|
||||||
setTimeout(() => {
|
input = r
|
||||||
if (!input) return
|
setTimeout(() => {
|
||||||
if (input.isDestroyed) return
|
if (!input) return
|
||||||
input.focus()
|
if (input.isDestroyed) return
|
||||||
}, 1)
|
input.focus()
|
||||||
}}
|
}, 1)
|
||||||
placeholder={props.placeholder ?? "Search"}
|
}}
|
||||||
placeholderColor={theme.textMuted}
|
placeholder={props.placeholder ?? "Search"}
|
||||||
/>
|
placeholderColor={theme.textMuted}
|
||||||
</box>
|
/>
|
||||||
|
</box>
|
||||||
|
</Show>
|
||||||
</box>
|
</box>
|
||||||
<Show
|
<Show
|
||||||
when={grouped().length > 0}
|
when={grouped().length > 0}
|
||||||
|
|
@ -293,6 +312,27 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||||
{(option) => {
|
{(option) => {
|
||||||
const active = createMemo(() => isDeepEqual(option.value, selected()?.value))
|
const active = createMemo(() => isDeepEqual(option.value, selected()?.value))
|
||||||
const current = createMemo(() => isDeepEqual(option.value, props.current))
|
const current = createMemo(() => isDeepEqual(option.value, props.current))
|
||||||
|
const flatIndex = createMemo(() => flat().findIndex((x) => isDeepEqual(x.value, option.value)))
|
||||||
|
const numberLabel = createMemo(() => {
|
||||||
|
if (!props.numbered) return undefined
|
||||||
|
const idx = flatIndex()
|
||||||
|
return idx >= 0 && idx < 9 ? `${idx + 1}` : undefined
|
||||||
|
})
|
||||||
|
const gutter = createMemo(() => {
|
||||||
|
if (numberLabel()) {
|
||||||
|
return (
|
||||||
|
<box flexDirection="row" flexShrink={0}>
|
||||||
|
<text
|
||||||
|
fg={active() ? selectedForeground(theme) : current() ? theme.primary : theme.textMuted}
|
||||||
|
flexShrink={0}
|
||||||
|
>
|
||||||
|
{numberLabel()}
|
||||||
|
</text>
|
||||||
|
</box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return option.gutter
|
||||||
|
})
|
||||||
return (
|
return (
|
||||||
<box
|
<box
|
||||||
id={JSON.stringify(option.value)}
|
id={JSON.stringify(option.value)}
|
||||||
|
|
@ -316,7 +356,7 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||||
moveTo(index)
|
moveTo(index)
|
||||||
}}
|
}}
|
||||||
backgroundColor={active() ? (option.bg ?? theme.primary) : RGBA.fromInts(0, 0, 0, 0)}
|
backgroundColor={active() ? (option.bg ?? theme.primary) : RGBA.fromInts(0, 0, 0, 0)}
|
||||||
paddingLeft={current() || option.gutter ? 1 : 3}
|
paddingLeft={current() || gutter() ? 1 : 3}
|
||||||
paddingRight={3}
|
paddingRight={3}
|
||||||
gap={1}
|
gap={1}
|
||||||
>
|
>
|
||||||
|
|
@ -326,7 +366,7 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||||
description={option.description !== category ? option.description : undefined}
|
description={option.description !== category ? option.description : undefined}
|
||||||
active={active()}
|
active={active()}
|
||||||
current={current()}
|
current={current()}
|
||||||
gutter={option.gutter}
|
gutter={gutter()}
|
||||||
/>
|
/>
|
||||||
</box>
|
</box>
|
||||||
)
|
)
|
||||||
|
|
@ -369,16 +409,16 @@ function Option(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Show when={props.current}>
|
<Show when={props.gutter}>
|
||||||
<text flexShrink={0} fg={props.active ? fg : props.current ? theme.primary : theme.text} marginRight={0}>
|
|
||||||
●
|
|
||||||
</text>
|
|
||||||
</Show>
|
|
||||||
<Show when={!props.current && props.gutter}>
|
|
||||||
<box flexShrink={0} marginRight={0}>
|
<box flexShrink={0} marginRight={0}>
|
||||||
{props.gutter}
|
{props.gutter}
|
||||||
</box>
|
</box>
|
||||||
</Show>
|
</Show>
|
||||||
|
<Show when={props.current && !props.gutter}>
|
||||||
|
<text flexShrink={0} fg={props.active ? fg : props.current ? theme.primary : theme.text} marginRight={0}>
|
||||||
|
●
|
||||||
|
</text>
|
||||||
|
</Show>
|
||||||
<text
|
<text
|
||||||
flexGrow={1}
|
flexGrow={1}
|
||||||
fg={props.active ? fg : props.current ? theme.primary : theme.text}
|
fg={props.active ? fg : props.current ? theme.primary : theme.text}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue