@zaly/tui 0.0.12 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/schemas/shiki-language.schema.json +352 -0
- package/assets/schemas/shiki-theme.schema.json +71 -0
- package/assets/schemas/theme.schema.json +226 -1046
- package/assets/themes/andromeeda.json +97 -0
- package/assets/themes/ayu-dark.json +31 -25
- package/assets/themes/ayu-light.json +106 -0
- package/assets/themes/ayu-mirage.json +106 -0
- package/assets/themes/catppuccin-frappe.json +43 -40
- package/assets/themes/catppuccin-latte.json +43 -40
- package/assets/themes/catppuccin-macchiato.json +43 -40
- package/assets/themes/catppuccin-mocha.json +43 -40
- package/assets/themes/dark-plus.json +99 -0
- package/assets/themes/dracula.json +47 -47
- package/assets/themes/everforest-dark.json +28 -26
- package/assets/themes/everforest-light.json +28 -26
- package/assets/themes/github-dark-default.json +107 -0
- package/assets/themes/github-dark-dimmed.json +107 -0
- package/assets/themes/github-light-default.json +107 -0
- package/assets/themes/gruvbox-dark-hard.json +98 -0
- package/assets/themes/gruvbox-dark-medium.json +34 -29
- package/assets/themes/gruvbox-light-medium.json +98 -0
- package/assets/themes/horizon-bright.json +101 -0
- package/assets/themes/horizon.json +101 -0
- package/assets/themes/iterm2/LICENSE +25 -0
- package/assets/themes/iterm2/README.md +28 -0
- package/assets/themes/iterm2/catppuccin-latte.json +140 -0
- package/assets/themes/iterm2/catppuccin-mocha.json +140 -0
- package/assets/themes/iterm2/github-dark.json +140 -0
- package/assets/themes/iterm2/github.json +140 -0
- package/assets/themes/iterm2/gruvbox-dark.json +140 -0
- package/assets/themes/iterm2/gruvbox-light.json +140 -0
- package/assets/themes/iterm2/nord.json +140 -0
- package/assets/themes/iterm2/tokyonight-day.json +140 -0
- package/assets/themes/iterm2/tokyonight-moon.json +140 -0
- package/assets/themes/kanagawa-dragon.json +55 -49
- package/assets/themes/kanagawa-lotus.json +105 -0
- package/assets/themes/kanagawa-wave.json +56 -50
- package/assets/themes/light-plus.json +99 -0
- package/assets/themes/material-theme-lighter.json +102 -0
- package/assets/themes/material-theme-palenight.json +52 -45
- package/assets/themes/material-theme.json +102 -0
- package/assets/themes/min-dark.json +69 -14
- package/assets/themes/min-light.json +68 -17
- package/assets/themes/monokai.json +54 -47
- package/assets/themes/night-owl-light.json +105 -0
- package/assets/themes/night-owl.json +57 -49
- package/assets/themes/nord.json +53 -39
- package/assets/themes/one-dark-pro.json +46 -38
- package/assets/themes/one-light.json +52 -41
- package/assets/themes/poimandres.json +51 -49
- package/assets/themes/rose-pine-dawn.json +99 -0
- package/assets/themes/rose-pine-moon.json +99 -0
- package/assets/themes/rose-pine.json +50 -33
- package/assets/themes/solarized-dark.json +38 -31
- package/assets/themes/solarized-light.json +40 -33
- package/assets/themes/synthwave-84.json +47 -30
- package/assets/themes/tokyonight-day.json +3 -3
- package/assets/themes/tokyonight-moon.json +3 -2
- package/assets/themes/tokyonight-night.json +3 -2
- package/assets/themes/tokyonight-storm.json +3 -2
- package/assets/themes/vesper.json +50 -42
- package/assets/themes/vitesse-black.json +103 -0
- package/assets/themes/vitesse-dark.json +26 -30
- package/assets/themes/vitesse-light.json +26 -30
- package/dist/{actions-Dc4D4uSf.d.mts → actions--ODlgCQ5.d.mts} +4 -4
- package/dist/{actions-Dc4D4uSf.d.mts.map → actions--ODlgCQ5.d.mts.map} +1 -1
- package/dist/{ansi-DZlXaItJ.mjs → ansi-CMv71xVr.mjs} +3 -31
- package/dist/ansi-CMv71xVr.mjs.map +1 -0
- package/dist/ansi.d.mts +1 -1
- package/dist/ansi.mjs +1 -1
- package/dist/{autocomplete-StW1QJZJ.d.mts → autocomplete-CD30kSe_.d.mts} +4 -4
- package/dist/{autocomplete-StW1QJZJ.d.mts.map → autocomplete-CD30kSe_.d.mts.map} +1 -1
- package/dist/{box-BkP4MF82.mjs → box-C_N_7ChP.mjs} +2 -2
- package/dist/{box-BkP4MF82.mjs.map → box-C_N_7ChP.mjs.map} +1 -1
- package/dist/builder-Chwtk0nQ.mjs +196 -0
- package/dist/builder-Chwtk0nQ.mjs.map +1 -0
- package/dist/{callbacks-BwWTCqPJ.mjs → callbacks-DLecWn7G.mjs} +4 -4
- package/dist/{callbacks-BwWTCqPJ.mjs.map → callbacks-DLecWn7G.mjs.map} +1 -1
- package/dist/client-CNGt-dOt.mjs +1 -0
- package/dist/{client-C2GXKfJ1.mjs → client-D7qz4TZt.mjs} +7 -3
- package/dist/client-D7qz4TZt.mjs.map +1 -0
- package/dist/color-DBMQLv4Y.mjs +37 -0
- package/dist/color-DBMQLv4Y.mjs.map +1 -0
- package/dist/{ctx-B7BmPUCD.mjs → ctx-BaQ2hP5u.mjs} +3 -3
- package/dist/{ctx-B7BmPUCD.mjs.map → ctx-BaQ2hP5u.mjs.map} +1 -1
- package/dist/ctx-CndlTp1T.mjs +1 -0
- package/dist/{divider-TSx9NhI_.mjs → divider-BlNNN2OS.mjs} +2 -2
- package/dist/{divider-TSx9NhI_.mjs.map → divider-BlNNN2OS.mjs.map} +1 -1
- package/dist/{files-7DUYSeNc.d.mts → files-B_5HDBPp.d.mts} +3 -3
- package/dist/{files-7DUYSeNc.d.mts.map → files-B_5HDBPp.d.mts.map} +1 -1
- package/dist/{github-C1KfXk98.d.mts → github-CyRwUQ3y.d.mts} +3 -3
- package/dist/{github-C1KfXk98.d.mts.map → github-CyRwUQ3y.d.mts.map} +1 -1
- package/dist/{image-VaT7AN-S.d.mts → image-BLls2F4t.d.mts} +2 -2
- package/dist/{image-VaT7AN-S.d.mts.map → image-BLls2F4t.d.mts.map} +1 -1
- package/dist/image-Cqtj3yRA.mjs +178 -0
- package/dist/image-Cqtj3yRA.mjs.map +1 -0
- package/dist/image.d.mts +1 -1
- package/dist/index.d.mts +13 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -7
- package/dist/index.mjs.map +1 -1
- package/dist/{input-BGTTujDN.mjs → input-ET2YEMcl.mjs} +2 -2
- package/dist/{input-BGTTujDN.mjs.map → input-ET2YEMcl.mjs.map} +1 -1
- package/dist/{input-BAYux7qo.d.mts → input-NuD8TH8N.d.mts} +3 -3
- package/dist/{input-BAYux7qo.d.mts.map → input-NuD8TH8N.d.mts.map} +1 -1
- package/dist/{inspect-CfNydMgO.d.mts → inspect-B1uXxdKC.d.mts} +2 -2
- package/dist/{inspect-CfNydMgO.d.mts.map → inspect-B1uXxdKC.d.mts.map} +1 -1
- package/dist/{inspect-jG_W4njH.mjs → inspect-Cxzs-W0g.mjs} +2 -2
- package/dist/{inspect-jG_W4njH.mjs.map → inspect-Cxzs-W0g.mjs.map} +1 -1
- package/dist/kitty-DKQYsQfH.mjs +1 -0
- package/dist/{log-ByKlM4iI.mjs → log-B4djzy2m.mjs} +4 -4
- package/dist/{log-ByKlM4iI.mjs.map → log-B4djzy2m.mjs.map} +1 -1
- package/dist/{logger-DSQb0sLP.mjs → logger-CvJCITzP.mjs} +3 -3
- package/dist/{logger-DSQb0sLP.mjs.map → logger-CvJCITzP.mjs.map} +1 -1
- package/dist/{markdown-CwRmWuU6.mjs → markdown-D3ZtRn6C.mjs} +9 -8
- package/dist/markdown-D3ZtRn6C.mjs.map +1 -0
- package/dist/markdown.d.mts +1 -1
- package/dist/markdown.d.mts.map +1 -1
- package/dist/markdown.mjs +1 -1
- package/dist/math-CU0wmC9N.mjs +1 -0
- package/dist/math-Dd7a1irv.mjs +206 -0
- package/dist/math-Dd7a1irv.mjs.map +1 -0
- package/dist/oklch-Bsh5swbC.mjs +99 -0
- package/dist/oklch-Bsh5swbC.mjs.map +1 -0
- package/dist/{overlay-BnvOKtGT.mjs → overlay-LvOjG7kn.mjs} +2 -2
- package/dist/{overlay-BnvOKtGT.mjs.map → overlay-LvOjG7kn.mjs.map} +1 -1
- package/dist/{picker-DQs_IW77.d.mts → picker-B-OxKKnD.d.mts} +5 -5
- package/dist/{picker-DQs_IW77.d.mts.map → picker-B-OxKKnD.d.mts.map} +1 -1
- package/dist/{picker-Dh5IUrTk.mjs → picker-f6xjgACX.mjs} +2 -2
- package/dist/{picker-Dh5IUrTk.mjs.map → picker-f6xjgACX.mjs.map} +1 -1
- package/dist/{queries-B_lOwEiE.mjs → queries-BUkBxkuM.mjs} +66 -3
- package/dist/queries-BUkBxkuM.mjs.map +1 -0
- package/dist/{queries-BDX8mcl5.d.mts → queries-C75-wG1B.d.mts} +19 -4
- package/dist/{queries-BDX8mcl5.d.mts.map → queries-C75-wG1B.d.mts.map} +1 -1
- package/dist/{registry-D-suU3g0.mjs → registry-DUWpSPoo.mjs} +202 -57
- package/dist/registry-DUWpSPoo.mjs.map +1 -0
- package/dist/{render-DEIUNLkh.mjs → render-B7LfNM5K.mjs} +2 -2
- package/dist/{render-DEIUNLkh.mjs.map → render-B7LfNM5K.mjs.map} +1 -1
- package/dist/{renderer-zDNlAovy.mjs → renderer-BLsd-wrG.mjs} +110 -14
- package/dist/renderer-BLsd-wrG.mjs.map +1 -0
- package/dist/renderer-YHbR7JZ4.mjs +1 -0
- package/dist/{renderer-MQue4Da5.mjs → renderer-aAtkFgll.mjs} +8 -7
- package/dist/renderer-aAtkFgll.mjs.map +1 -0
- package/dist/{select-J2KtwxyK.d.mts → select-BKE5LzdN.d.mts} +3 -3
- package/dist/{select-J2KtwxyK.d.mts.map → select-BKE5LzdN.d.mts.map} +1 -1
- package/dist/services/logger.d.mts +1 -1
- package/dist/services/logger.mjs +1 -1
- package/dist/services/notifier.d.mts +1 -1
- package/dist/services/notifier.mjs +2 -2
- package/dist/services/picker.d.mts +5 -5
- package/dist/services/picker.mjs +6 -6
- package/dist/services/prompt.d.mts +4 -4
- package/dist/services/prompt.mjs +5 -5
- package/dist/shiki/server.mjs +37 -14
- package/dist/shiki/server.mjs.map +1 -1
- package/dist/shiki-B4U0s8jT.mjs +635 -0
- package/dist/shiki-B4U0s8jT.mjs.map +1 -0
- package/dist/shiki-CJauRusM.mjs +20 -0
- package/dist/shiki-CJauRusM.mjs.map +1 -0
- package/dist/style-DslRHzI4.mjs +109 -0
- package/dist/style-DslRHzI4.mjs.map +1 -0
- package/dist/style.d.mts +4 -3
- package/dist/style.d.mts.map +1 -1
- package/dist/style.mjs +4 -4
- package/dist/{text-CkQ7Irmt.mjs → text-BoJdKXLU.mjs} +2 -2
- package/dist/{text-CkQ7Irmt.mjs.map → text-BoJdKXLU.mjs.map} +1 -1
- package/dist/{text-CCYs9RB2.d.mts → text-CmxbA8lk.d.mts} +3 -3
- package/dist/{text-CCYs9RB2.d.mts.map → text-CmxbA8lk.d.mts.map} +1 -1
- package/dist/{text-XvPfweeg.mjs → text-DPrhma4x.mjs} +2 -2
- package/dist/{text-XvPfweeg.mjs.map → text-DPrhma4x.mjs.map} +1 -1
- package/dist/text.d.mts +1 -1
- package/dist/text.mjs +1 -1
- package/dist/theme-C8LkcoaK.mjs +61 -0
- package/dist/theme-C8LkcoaK.mjs.map +1 -0
- package/dist/theme-DVX8dvGG.mjs +1794 -0
- package/dist/theme-DVX8dvGG.mjs.map +1 -0
- package/dist/themes.d.mts +213 -73
- package/dist/themes.d.mts.map +1 -1
- package/dist/themes.mjs +1 -1
- package/dist/{tree-DJl5W_B7.d.mts → tree-CTvSpF9b.d.mts} +3 -3
- package/dist/{tree-DJl5W_B7.d.mts.map → tree-CTvSpF9b.d.mts.map} +1 -1
- package/dist/{types-D2EYlzmK.d.mts → types-C9ceMsbJ.d.mts} +136 -128
- package/dist/types-C9ceMsbJ.d.mts.map +1 -0
- package/dist/{widget-DPqBbB57.d.mts → widget-DlF32PRp.d.mts} +2 -2
- package/dist/{widget-DPqBbB57.d.mts.map → widget-DlF32PRp.d.mts.map} +1 -1
- package/dist/widgets/autocomplete.d.mts +1 -1
- package/dist/widgets/autocomplete.mjs +2 -2
- package/dist/widgets/box.d.mts +1 -1
- package/dist/widgets/box.mjs +1 -1
- package/dist/widgets/code.d.mts +4 -2
- package/dist/widgets/code.d.mts.map +1 -1
- package/dist/widgets/code.mjs +8 -7
- package/dist/widgets/code.mjs.map +1 -1
- package/dist/widgets/completions/actions.d.mts +1 -1
- package/dist/widgets/completions/files.d.mts +1 -1
- package/dist/widgets/completions/github.d.mts +1 -1
- package/dist/widgets/completions/index.d.mts +3 -3
- package/dist/widgets/diff.d.mts +2 -2
- package/dist/widgets/diff.d.mts.map +1 -1
- package/dist/widgets/diff.mjs +35 -12
- package/dist/widgets/diff.mjs.map +1 -1
- package/dist/widgets/divider.d.mts +2 -2
- package/dist/widgets/divider.mjs +1 -1
- package/dist/widgets/image.d.mts +1 -1
- package/dist/widgets/image.mjs +4 -4
- package/dist/widgets/image.mjs.map +1 -1
- package/dist/widgets/input.d.mts +1 -1
- package/dist/widgets/input.mjs +1 -1
- package/dist/widgets/log.d.mts +1 -1
- package/dist/widgets/log.mjs +1 -1
- package/dist/widgets/markdown.d.mts +4 -4
- package/dist/widgets/markdown.d.mts.map +1 -1
- package/dist/widgets/markdown.mjs +1 -1
- package/dist/widgets/overlay.d.mts +1 -1
- package/dist/widgets/overlay.mjs +1 -1
- package/dist/widgets/picker.d.mts +1 -1
- package/dist/widgets/picker.mjs +1 -1
- package/dist/widgets/progress.d.mts +2 -2
- package/dist/widgets/select.d.mts +1 -1
- package/dist/widgets/show.d.mts +1 -1
- package/dist/widgets/spinner.d.mts +2 -2
- package/dist/widgets/text.d.mts +1 -1
- package/dist/widgets/text.mjs +1 -1
- package/dist/widgets/tree.d.mts +1 -1
- package/dist/widgets/widget.d.mts +1 -1
- package/package.json +5 -7
- package/assets/themes/dracula-soft.json +0 -100
- package/assets/themes/github-dark.json +0 -104
- package/assets/themes/github-light.json +0 -104
- package/dist/ansi-DZlXaItJ.mjs.map +0 -1
- package/dist/builder-1z5ewEWK.mjs +0 -386
- package/dist/builder-1z5ewEWK.mjs.map +0 -1
- package/dist/client-C2GXKfJ1.mjs.map +0 -1
- package/dist/client-bzdHIDL2.mjs +0 -1
- package/dist/ctx-D_JgJ8Eo.mjs +0 -1
- package/dist/image-Cm5T-uw-.mjs +0 -108
- package/dist/image-Cm5T-uw-.mjs.map +0 -1
- package/dist/markdown-CwRmWuU6.mjs.map +0 -1
- package/dist/queries-B_lOwEiE.mjs.map +0 -1
- package/dist/registry-D-suU3g0.mjs.map +0 -1
- package/dist/renderer-DhqbEVVR.mjs +0 -1
- package/dist/renderer-MQue4Da5.mjs.map +0 -1
- package/dist/renderer-zDNlAovy.mjs.map +0 -1
- package/dist/shiki--ASSYv4_.mjs +0 -12
- package/dist/shiki--ASSYv4_.mjs.map +0 -1
- package/dist/shiki-D7l5--zz.mjs +0 -432
- package/dist/shiki-D7l5--zz.mjs.map +0 -1
- package/dist/theme.config-B3Yx--C2.mjs +0 -855
- package/dist/theme.config-B3Yx--C2.mjs.map +0 -1
- package/dist/types-D2EYlzmK.d.mts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ctx-
|
|
1
|
+
{"version":3,"file":"ctx-BaQ2hP5u.mjs","names":[],"sources":["../src/core/ctx.ts"],"sourcesContent":["import type { Emitter } from \"@zaly/shared\"\nimport type { Logger } from \"@zaly/shared/logger\"\nimport type { Actions } from \"../input/actions.ts\"\nimport type { TerminalQueries } from \"../input/queries.ts\"\nimport type { InputRouterEvents } from \"../input/router.ts\"\nimport type { SurfaceType } from \"../renderer/renderer.ts\"\nimport type { StyleBuilder } from \"../style/builder.ts\"\nimport type { Theme } from \"../themes/types.ts\"\nimport type { Overlay } from \"../widgets/overlay.ts\"\nimport type { Node } from \"./node.ts\"\n\nimport { styleBuilder } from \"../style/builder.ts\"\nimport { defaultTheme } from \"../themes/registry.ts\"\n\n/**\n * Passed to every `render(ctx)` call. Width flows in; height emerges from\n * the returned row count. Theme is ambient — children share the parent's.\n *\n * `style` is a theme-bound chainable builder made available to components so\n * they can produce inline-styled strings without re-binding the theme.\n *\n * `version` is a monotonic cache-key bumped by the `Renderer` whenever any\n * identity-relevant ctx field changes (resize, theme swap). Node caches\n * compare this integer — no hashing, no string keys.\n */\nexport interface RenderCtx {\n width: number\n style: StyleBuilder\n version: number\n /** Queue a side-channel ANSI payload (e.g. KGP image transmit) for\n * the renderer to flush before the next paint. Use this to keep\n * side-effecting bytes out of cached row strings — what `_render`\n * returns should be safe to reuse across paints, and transmit\n * bytes shouldn't be. */\n readonly transmit: (seq: string) => void\n}\n\n/**\n * Context handed to a node when it mounts onto a surface. Gives widget\n * authors a scoped handle to the services they legitimately need —\n * focus, overlays, tree lookups, out-of-band repaints — without\n * exposing the full Renderer.\n *\n * MountCtx is *per-lifetime*: set once when `mount()` is called and\n * cleared on `unmount()`. Distinct from `RenderCtx` (per-tick, carries\n * width/theme/version). If a node moves between surfaces, it receives\n * a fresh MountCtx via the subsequent `mount()` call.\n */\nexport interface MountCtx {\n /** Which surface owns this subtree. */\n readonly surface: SurfaceType\n\n /** Overlay capabilities — open/close an Overlay node from inside a\n * widget (e.g. a confirm dialog, autocomplete popover, tooltip). */\n readonly overlay: {\n readonly add: (o: () => Overlay) => void\n readonly remove: (o: Overlay) => void\n }\n\n /** Input capabilities — a narrow slice of the router. We deliberately\n * don't expose the full `InputRouter`: `setKeymap` / `dispatch` are\n * app-level concerns. Widgets legitimately need to install direct\n * global key bindings (autocomplete) and move focus. */\n readonly input: {\n readonly terminalFocus: boolean\n readonly events: Emitter<InputRouterEvents>\n readonly bind: Actions[\"bind\"]\n /** Move focus to `node`. Mirrors `router.focus(node)`. */\n readonly focus: (node: Node) => void\n /** Clear focus. */\n readonly blur: (node: Node) => void\n readonly queries: TerminalQueries\n }\n\n /** Action registry — widgets and plugins can `register` catalog\n * entries (with desc + default keys + optional `fn`) and `dispatch`\n * actions by id. The Router feeds key-triggered dispatches through\n * here; programmatic callers do the same. */\n readonly actions: Actions\n\n /** Look up a node anywhere in the tree by its `id`. First match\n * wins; `undefined` when nothing matches. Same semantics as\n * `Renderer.getNode`. */\n readonly getNode: (id: string) => Node | undefined\n /** Find every node matching a predicate. Strings match `node.type`;\n * pass a function for richer predicates. Same semantics as\n * `Renderer.findNode`. */\n readonly findNode: (match: string | ((n: Node) => boolean)) => Node[]\n\n logger: Logger\n}\n\n/**\n * Current terminal width in cells. Returns `undefined` when stdout isn't a\n * TTY (piped output, tests, non-Node/Bun runtimes) — callers should fall\n * back to a sensible default when this is `undefined`.\n *\n * @internal\n */\nfunction termWidth(): number | undefined {\n if (typeof process === \"undefined\") return undefined\n const cols = process.stdout.columns\n return typeof cols === \"number\" && cols > 0 ? cols : undefined\n}\n\n/**\n * Build a fresh `RenderCtx` from a resolved theme + width. Binds a `style`\n * builder to the theme so components can use `ctx.style.primary(...)`\n * without constructing their own.\n *\n * Width is clamped to the terminal's current column count (falling back to\n * 80 when stdout isn't a TTY). No width passed → terminal width is used\n * directly; an explicit `width` wider than the terminal is capped so\n * components never produce rows that wrap the display. Narrower explicit\n * widths (e.g. for fixed-layout tests) pass through unchanged.\n *\n * Dynamic theme loading (from a string name) lives in `themes/loadTheme`\n * — resolve the name first, then pass the `Theme` object here.\n */\nexport function createCtx(opts: Partial<RenderCtx> & { theme?: Theme } = {}): RenderCtx {\n const tw = termWidth() ?? 80\n return {\n style: opts.style ?? styleBuilder(opts.theme ?? defaultTheme),\n transmit: (data) => process.stdout.write(data),\n version: opts.version ?? 0,\n width: Math.min(opts.width ?? tw, tw),\n ...opts,\n }\n}\n"],"mappings":";;;;;;;;;;AAmGA,SAAS,YAAgC;CACvC,IAAI,OAAO,YAAY,aAAa,OAAO,KAAA;CAC3C,MAAM,OAAO,QAAQ,OAAO;CAC5B,OAAO,OAAO,SAAS,YAAY,OAAO,IAAI,OAAO,KAAA;AACvD;;;;;;;;;;;;;;;AAgBA,SAAgB,UAAU,OAA+C,CAAC,GAAc;CACtF,MAAM,KAAK,UAAU,KAAK;CAC1B,OAAO;EACL,OAAO,KAAK,SAAS,aAAa,KAAK,SAAS,YAAY;EAC5D,WAAW,SAAS,QAAQ,OAAO,MAAM,IAAI;EAC7C,SAAS,KAAK,WAAW;EACzB,OAAO,KAAK,IAAI,KAAK,SAAS,IAAI,EAAE;EACpC,GAAG;CACL;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as createCtx } from "./ctx-BaQ2hP5u.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as text } from "./text-
|
|
1
|
+
import { n as text } from "./text-DPrhma4x.mjs";
|
|
2
2
|
//#region src/widgets/divider.ts
|
|
3
3
|
function divider(state = { style: "divider" }) {
|
|
4
4
|
return text((ctx) => (state.char ?? "─").repeat(state.length ?? ctx.width), state);
|
|
@@ -6,4 +6,4 @@ function divider(state = { style: "divider" }) {
|
|
|
6
6
|
//#endregion
|
|
7
7
|
export { divider as t };
|
|
8
8
|
|
|
9
|
-
//# sourceMappingURL=divider-
|
|
9
|
+
//# sourceMappingURL=divider-BlNNN2OS.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"divider-
|
|
1
|
+
{"version":3,"file":"divider-BlNNN2OS.mjs","names":[],"sources":["../src/widgets/divider.ts"],"sourcesContent":["import type { Style } from \"../style/types.ts\"\nimport type { Text } from \"./text.ts\"\n\nimport { text } from \"./text.ts\"\n\nexport type DividerState = Style<false> & {\n char?: string\n length?: number\n}\n\nexport function divider(state: DividerState = { style: \"divider\" }): Text {\n return text((ctx) => (state.char ?? \"─\").repeat(state.length ?? ctx.width), state)\n}\n"],"mappings":";;AAUA,SAAgB,QAAQ,QAAsB,EAAE,OAAO,UAAU,GAAS;CACxE,OAAO,MAAM,SAAS,MAAM,QAAQ,IAAA,CAAK,OAAO,MAAM,UAAU,IAAI,KAAK,GAAG,KAAK;AACnF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as PickerItem } from "./picker-
|
|
2
|
-
import { o as CompletionSource } from "./autocomplete-
|
|
1
|
+
import { n as PickerItem } from "./picker-B-OxKKnD.mjs";
|
|
2
|
+
import { o as CompletionSource } from "./autocomplete-CD30kSe_.mjs";
|
|
3
3
|
import { FindOptions } from "@zaly/shared/find";
|
|
4
4
|
//#region src/widgets/completions/files.d.ts
|
|
5
5
|
interface FilesSourceOptions extends FindOptions {
|
|
@@ -26,4 +26,4 @@ type File = PickerItem & {
|
|
|
26
26
|
declare function filesSource(opts?: FilesSourceOptions): CompletionSource<File>;
|
|
27
27
|
//#endregion
|
|
28
28
|
export { filesSource as n, FilesSourceOptions as t };
|
|
29
|
-
//# sourceMappingURL=files-
|
|
29
|
+
//# sourceMappingURL=files-B_5HDBPp.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-
|
|
1
|
+
{"version":3,"file":"files-B_5HDBPp.d.mts","names":[],"sources":["../src/widgets/completions/files.ts"],"mappings":";;;;UAQiB,2BAA2B;;;EAG1C;;;;EAIA,UAAU;;;;;;EAMV;EACA;;KAGG,OAAO;EAAe;;;;iBAIX,YAAY,OAAM,qBAA0B,iBAAiB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as PickerItem } from "./picker-
|
|
2
|
-
import { o as CompletionSource } from "./autocomplete-
|
|
1
|
+
import { n as PickerItem } from "./picker-B-OxKKnD.mjs";
|
|
2
|
+
import { o as CompletionSource } from "./autocomplete-CD30kSe_.mjs";
|
|
3
3
|
//#region src/widgets/completions/github.d.ts
|
|
4
4
|
/** A GitHub issue or pull request returned by `githubSource`. Shape
|
|
5
5
|
* mirrors the `gh` CLI's `--json number,title,state,author,url`
|
|
@@ -61,4 +61,4 @@ interface GithubSourceOptions {
|
|
|
61
61
|
declare function githubSource(opts?: GithubSourceOptions): CompletionSource<GithubItem>;
|
|
62
62
|
//#endregion
|
|
63
63
|
export { githubSource as a, GithubState as i, GithubItem as n, GithubSourceOptions as r, GithubFetcher as t };
|
|
64
|
-
//# sourceMappingURL=github-
|
|
64
|
+
//# sourceMappingURL=github-CyRwUQ3y.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-
|
|
1
|
+
{"version":3,"file":"github-CyRwUQ3y.d.mts","names":[],"sources":["../src/widgets/completions/github.ts"],"mappings":";;;;;;KAWY,aAAa;EACvB;EACA;;;EAGA;EACA;EACA;EACA;IAAW;;;KAGD;KAEA,iBAAiB,aAAa,OAAO,gBAAgB,QAAQ;UAExD;;;EAGf;;;EAGA,UAAU;;;EAGV;;EAEA,QAAQ;;EAER;;;;EAIA,UAAU;;;;;;;;;;;;;;;;;;;;;;;iBAwBI,aAAa,OAAM,sBAA2B,iBAAiB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I as RenderCtx, X as Layout, h as Node } from "./queries-C75-wG1B.mjs";
|
|
2
2
|
//#region src/widgets/image.d.ts
|
|
3
3
|
interface ImageState {
|
|
4
4
|
/**
|
|
@@ -34,4 +34,4 @@ declare function image(src: string, style?: Omit<ImageState, "src">): Image;
|
|
|
34
34
|
declare function image(state: ImageState): Image;
|
|
35
35
|
//#endregion
|
|
36
36
|
export { ImageState as n, image as r, Image as t };
|
|
37
|
-
//# sourceMappingURL=image-
|
|
37
|
+
//# sourceMappingURL=image-BLls2F4t.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-
|
|
1
|
+
{"version":3,"file":"image-BLls2F4t.d.mts","names":[],"sources":["../src/widgets/image.ts"],"mappings":";;UAWiB;;;;;;;EAOf;;EAEA;;;;;EAKA;;EAEA;;;;;EAKA;;cAGW,cAAc,KAAK;;EAI9B,YAAY,OAAO;MAOf;EAIK,UAAU;YAIH,QAAQ,KAAK,YAAY;;iBAuC3B,MAAM,aAAa,QAAQ,KAAK,qBAAqB;iBACrD,MAAM,OAAO,aAAa"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { n as resolveAnsiStyle } from "./style-DslRHzI4.mjs";
|
|
2
|
+
import { n as replaceMath } from "./math-Dd7a1irv.mjs";
|
|
3
|
+
import { stringWidth, stripAnsi } from "@zaly/shared/ansi";
|
|
4
|
+
import { basename } from "pathe";
|
|
5
|
+
//#region src/markdown/image.ts
|
|
6
|
+
/**
|
|
7
|
+
* Image callback + post-processor for the markdown pipeline.
|
|
8
|
+
*
|
|
9
|
+
* The markdown renderer is synchronous (callbacks return strings), but
|
|
10
|
+
* image preparation is async (sharp metadata, KGP transmit, format
|
|
11
|
+
* conversion). Math shares the same markers and placement path:
|
|
12
|
+
*
|
|
13
|
+
* 1. Before rendering, `prepare` collects math expressions and protects
|
|
14
|
+
* their markers from ordinary Markdown escaping.
|
|
15
|
+
* 2. During rendering, the `image` callback pushes `{ src, alt }` into
|
|
16
|
+
* the entries array and emits a compact `<img id=N>` marker where
|
|
17
|
+
* `N` is the entry's index. The marker is plain text so any
|
|
18
|
+
* renderer (marked or `Bun.markdown.render`) emits it verbatim.
|
|
19
|
+
* 3. After rendering, `resolve(ctx, rendered)` typesets math to cached
|
|
20
|
+
* SVG files, renders every unique
|
|
21
|
+
* src concurrently via cached `Image` nodes, then replaces each
|
|
22
|
+
* marker with rendered rows. Inline images share a top-aligned row
|
|
23
|
+
* band, with continuation rows padded to each image's terminal column.
|
|
24
|
+
*
|
|
25
|
+
* The caller passes in a persistent `cache: Map<src, Image>` owned by
|
|
26
|
+
* the Markdown instance so re-renders reuse the same Image node (and
|
|
27
|
+
* therefore the same KGP placement id, which the spec guarantees is a
|
|
28
|
+
* flicker-free move/resize).
|
|
29
|
+
*/
|
|
30
|
+
function createImageCallback(host) {
|
|
31
|
+
const entries = [];
|
|
32
|
+
const cache = host.images;
|
|
33
|
+
return {
|
|
34
|
+
cb(alt, meta) {
|
|
35
|
+
const id = entries.length;
|
|
36
|
+
entries.push({
|
|
37
|
+
alt,
|
|
38
|
+
src: meta.src
|
|
39
|
+
});
|
|
40
|
+
return `<img id=${id}>`;
|
|
41
|
+
},
|
|
42
|
+
prepare(source) {
|
|
43
|
+
return replaceMath(source, (math) => {
|
|
44
|
+
const id = entries.length;
|
|
45
|
+
entries.push({
|
|
46
|
+
alt: math.source,
|
|
47
|
+
math,
|
|
48
|
+
src: ""
|
|
49
|
+
});
|
|
50
|
+
return `\`<img id=${id}>\``;
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
async resolve(ctx, rendered) {
|
|
54
|
+
if (entries.length === 0) {
|
|
55
|
+
for (const img of cache.values()) host.remove(img);
|
|
56
|
+
cache.clear();
|
|
57
|
+
return rendered;
|
|
58
|
+
}
|
|
59
|
+
const { Image } = await import("./widgets/image.mjs");
|
|
60
|
+
const { loadKittyGraphics } = await import("./kitty-DKQYsQfH.mjs");
|
|
61
|
+
const graphics = entries.some((entry) => entry.math) && host.queries ? await loadKittyGraphics(host.queries) : void 0;
|
|
62
|
+
const fg = resolveAnsiStyle("mdMath", ctx.style.theme).fg;
|
|
63
|
+
const color = typeof fg === "string" && fg.startsWith("#") ? fg : void 0;
|
|
64
|
+
const ordinals = /* @__PURE__ */ new Map();
|
|
65
|
+
const rowsByEntry = [];
|
|
66
|
+
const used = /* @__PURE__ */ new Set();
|
|
67
|
+
await Promise.all(entries.map(async (entry, idx) => {
|
|
68
|
+
if (entry.math && (!graphics?.supported || !color)) {
|
|
69
|
+
rowsByEntry[idx] = [entry.alt];
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const identity = entry.math ? `math:${JSON.stringify([
|
|
73
|
+
entry.math.tex,
|
|
74
|
+
entry.math.display,
|
|
75
|
+
color
|
|
76
|
+
])}` : entry.src;
|
|
77
|
+
const ord = ordinals.get(identity) ?? 0;
|
|
78
|
+
ordinals.set(identity, ord + 1);
|
|
79
|
+
const key = `${identity}\u0000${ord}`;
|
|
80
|
+
used.add(key);
|
|
81
|
+
let img = cache.get(key);
|
|
82
|
+
if (img === void 0) {
|
|
83
|
+
let src = entry.src;
|
|
84
|
+
let width;
|
|
85
|
+
if (entry.math) try {
|
|
86
|
+
const { mathImage } = await import("./math-CU0wmC9N.mjs");
|
|
87
|
+
src = await mathImage(entry.math, color);
|
|
88
|
+
const { fileDetect } = await import("@zaly/shared/detect");
|
|
89
|
+
const { imageInfo } = await import("@zaly/shared/image");
|
|
90
|
+
const detected = await fileDetect(src);
|
|
91
|
+
if (detected?.type !== "image") throw new Error("Expected a math SVG");
|
|
92
|
+
const info = await imageInfo(detected);
|
|
93
|
+
width = Math.max(1, Math.ceil(info.width / 24));
|
|
94
|
+
} catch {
|
|
95
|
+
rowsByEntry[idx] = [entry.alt];
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
img = new Image({
|
|
99
|
+
alt: entry.alt,
|
|
100
|
+
src,
|
|
101
|
+
width
|
|
102
|
+
});
|
|
103
|
+
host.add(img);
|
|
104
|
+
cache.set(key, img);
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
rowsByEntry[idx] = await img.render(ctx);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
if (!entry.math) throw error;
|
|
110
|
+
rowsByEntry[idx] = [entry.alt];
|
|
111
|
+
}
|
|
112
|
+
}));
|
|
113
|
+
for (const [key] of cache) if (!used.has(key)) {
|
|
114
|
+
const img = cache.get(key);
|
|
115
|
+
if (img) {
|
|
116
|
+
host.remove(img);
|
|
117
|
+
cache.delete(key);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const out = [];
|
|
121
|
+
for (const line of rendered.split("\n")) {
|
|
122
|
+
const matched = /* @__PURE__ */ new Map();
|
|
123
|
+
for (const m of line.matchAll(MARKER_RE)) {
|
|
124
|
+
const idx = Number(m[1]);
|
|
125
|
+
if (entries[idx]) matched.set(idx, {
|
|
126
|
+
entry: entries[idx],
|
|
127
|
+
rows: rowsByEntry[idx] ?? []
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (matched.size === 0) {
|
|
131
|
+
out.push(line);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (matched.size === 1 && stripAnsi(line.replace(MARKER_RE, "")).trim() === "") {
|
|
135
|
+
const img = matched.values().next().value;
|
|
136
|
+
if (img && img.rows.length > 0) {
|
|
137
|
+
out.push(...img.rows);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const band = [""];
|
|
142
|
+
let cursor = 0;
|
|
143
|
+
for (const marker of line.matchAll(MARKER_RE)) {
|
|
144
|
+
band[0] += line.slice(cursor, marker.index);
|
|
145
|
+
const image = matched.get(Number(marker[1]));
|
|
146
|
+
if (!image) band[0] += marker[0];
|
|
147
|
+
else {
|
|
148
|
+
const column = stringWidth(band[0]);
|
|
149
|
+
const rows = image.rows.length ? image.rows : [labelOf(image.entry)];
|
|
150
|
+
band[0] += rows[0];
|
|
151
|
+
for (let row = 1; row < rows.length; row++) {
|
|
152
|
+
band[row] ??= "";
|
|
153
|
+
band[row] += " ".repeat(Math.max(0, column - stringWidth(band[row]))) + rows[row];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
cursor = marker.index + marker[0].length;
|
|
157
|
+
}
|
|
158
|
+
band[0] += line.slice(cursor);
|
|
159
|
+
out.push(...band);
|
|
160
|
+
}
|
|
161
|
+
return out.join("\n");
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/** Friendly inline placeholder for an image that can't render at this
|
|
166
|
+
* position. Math keeps its original source. Otherwise prefers the markdown alt text;
|
|
167
|
+
* falls back to the basename
|
|
168
|
+
* of the source path (so `[clip.png]` instead of `[/tmp/long/path/clip.png]`),
|
|
169
|
+
* and "image" for anything weirder. */
|
|
170
|
+
function labelOf(entry) {
|
|
171
|
+
if (entry.math) return entry.alt;
|
|
172
|
+
return `[${entry.alt !== "" ? entry.alt : basename(entry.src) || "image"}]`;
|
|
173
|
+
}
|
|
174
|
+
const MARKER_RE = /<img id=(\d+)>/g;
|
|
175
|
+
//#endregion
|
|
176
|
+
export { createImageCallback };
|
|
177
|
+
|
|
178
|
+
//# sourceMappingURL=image-Cqtj3yRA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-Cqtj3yRA.mjs","names":[],"sources":["../src/markdown/image.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Node } from \"../core/node.ts\"\nimport type { TerminalQueries } from \"../input/queries.ts\"\nimport type { Image } from \"../widgets/image.ts\"\nimport type { MathExpression } from \"./math.ts\"\nimport type { MdCallbacks, MdImageMeta } from \"./types.ts\"\n\nimport { stringWidth, stripAnsi } from \"@zaly/shared/ansi\"\nimport { basename } from \"pathe\"\nimport { resolveAnsiStyle } from \"../style/style.ts\"\nimport { MATH_PIXELS_PER_CELL, replaceMath } from \"./math.ts\"\n\n/** Minimal host shape the image callback needs. Any Node-like parent\n * with a per-src `Image` cache satisfies it — the `Markdown` widget is\n * the primary caller but the interface keeps this file decoupled from\n * widget internals (and breaks the widgets↔markdown import loop). */\nexport interface ImageHost {\n /** Per-src cache so re-renders reuse the same `Image` — same KGP\n * placement id, which the spec guarantees is a flicker-free\n * move/resize. */\n images: Map<string, Image>\n queries?: TerminalQueries\n /** Attach a freshly-created `Image` as a child so mount/unmount\n * propagate. */\n add: (child: Node) => unknown\n remove: (child: Node) => unknown\n}\n\n/** Per-occurrence image metadata collected during markdown rendering. */\ninterface ImageEntry {\n src: string\n alt: string\n math?: MathExpression\n}\n\n/**\n * Image callback + post-processor for the markdown pipeline.\n *\n * The markdown renderer is synchronous (callbacks return strings), but\n * image preparation is async (sharp metadata, KGP transmit, format\n * conversion). Math shares the same markers and placement path:\n *\n * 1. Before rendering, `prepare` collects math expressions and protects\n * their markers from ordinary Markdown escaping.\n * 2. During rendering, the `image` callback pushes `{ src, alt }` into\n * the entries array and emits a compact `<img id=N>` marker where\n * `N` is the entry's index. The marker is plain text so any\n * renderer (marked or `Bun.markdown.render`) emits it verbatim.\n * 3. After rendering, `resolve(ctx, rendered)` typesets math to cached\n * SVG files, renders every unique\n * src concurrently via cached `Image` nodes, then replaces each\n * marker with rendered rows. Inline images share a top-aligned row\n * band, with continuation rows padded to each image's terminal column.\n *\n * The caller passes in a persistent `cache: Map<src, Image>` owned by\n * the Markdown instance so re-renders reuse the same Image node (and\n * therefore the same KGP placement id, which the spec guarantees is a\n * flicker-free move/resize).\n */\nexport function createImageCallback(host: ImageHost): {\n cb: MdCallbacks[\"image\"]\n prepare: (source: string) => string\n resolve: (ctx: RenderCtx, rendered: string) => Promise<string>\n} {\n const entries: ImageEntry[] = []\n const cache = host.images\n\n return {\n cb(alt: string, meta: MdImageMeta): string {\n const id = entries.length\n entries.push({ alt, src: meta.src })\n return `<img id=${id}>`\n },\n\n prepare(source: string): string {\n return replaceMath(source, (math) => {\n const id = entries.length\n entries.push({ alt: math.source, math, src: \"\" })\n // A bare tag on its own line starts an HTML block and swallows following Markdown.\n return `\\`<img id=${id}>\\``\n })\n },\n\n async resolve(ctx: RenderCtx, rendered: string): Promise<string> {\n if (entries.length === 0) {\n for (const img of cache.values()) host.remove(img)\n cache.clear()\n return rendered\n }\n\n // `Image` is heavy (pulls image-meta, sharp lazy loaders, KGP\n // encoder) and 99% of markdown has no images. Load it only when\n // we have something to place.\n const { Image } = await import(\"../widgets/image.ts\")\n\n // One Image (and therefore one KGP `placementId`) per occurrence\n // so multiple references to the same `src` show up as distinct\n // placements on screen. Cache key is `${src}\\0${ordinal-within-src}`\n // — the ordinal makes each repeated reference stable across\n // re-renders (slot 0 is always slot 0, so the placementId stays\n // pinned and KGP gives a flicker-free move/resize). Image bytes\n // are de-duped at a different layer (`transmitOnce` in kitty.ts),\n // so multiple occurrences cost N placements but only one transmit.\n const { loadKittyGraphics } = await import(\"../image/kitty.ts\")\n const graphics =\n entries.some((entry) => entry.math) && host.queries\n ? await loadKittyGraphics(host.queries)\n : undefined\n const fg = resolveAnsiStyle(\"mdMath\", ctx.style.theme).fg\n const color = typeof fg === \"string\" && fg.startsWith(\"#\") ? fg : undefined\n const ordinals = new Map<string, number>()\n const rowsByEntry: string[][] = []\n const used = new Set<string>()\n await Promise.all(\n entries.map(async (entry, idx) => {\n if (entry.math && (!graphics?.supported || !color)) {\n rowsByEntry[idx] = [entry.alt]\n return\n }\n const identity = entry.math\n ? `math:${JSON.stringify([entry.math.tex, entry.math.display, color])}`\n : entry.src\n const ord = ordinals.get(identity) ?? 0\n ordinals.set(identity, ord + 1)\n const key = `${identity}\\u0000${ord}`\n used.add(key)\n let img = cache.get(key)\n if (img === undefined) {\n let src = entry.src\n let width: number | undefined\n if (entry.math) {\n try {\n const { mathImage } = await import(\"./math.ts\")\n src = await mathImage(entry.math, color!)\n const { fileDetect } = await import(\"@zaly/shared/detect\")\n const { imageInfo } = await import(\"@zaly/shared/image\")\n const detected = await fileDetect(src)\n if (detected?.type !== \"image\") throw new Error(\"Expected a math SVG\")\n const info = await imageInfo(detected)\n width = Math.max(1, Math.ceil(info.width / MATH_PIXELS_PER_CELL))\n } catch {\n rowsByEntry[idx] = [entry.alt]\n return\n }\n }\n img = new Image({ alt: entry.alt, src, width })\n host.add(img)\n cache.set(key, img)\n }\n try {\n rowsByEntry[idx] = await img.render(ctx)\n } catch (error) {\n if (!entry.math) throw error\n rowsByEntry[idx] = [entry.alt]\n }\n })\n )\n\n for (const [key] of cache) {\n if (!used.has(key)) {\n const img = cache.get(key)\n if (img) {\n host.remove(img)\n cache.delete(key)\n }\n }\n }\n\n // Walk the rendered output line by line:\n // - Marker alone on its line (whitespace + ANSI tolerated) →\n // replace the line with the full image rows.\n // - Marker mid-line → top-align image rows in a shared band.\n // Coordinates are terminal cells, not string offsets. As with tables,\n // subsequent wrapping to a narrower width can invalidate this layout.\n const out: string[] = []\n for (const line of rendered.split(\"\\n\")) {\n const matched = new Map<number, { entry: ImageEntry; rows: string[] }>()\n for (const m of line.matchAll(MARKER_RE)) {\n const idx = Number(m[1])\n if (entries[idx]) matched.set(idx, { entry: entries[idx], rows: rowsByEntry[idx] ?? [] })\n }\n\n if (matched.size === 0) {\n out.push(line)\n continue\n }\n\n if (matched.size === 1 && stripAnsi(line.replace(MARKER_RE, \"\")).trim() === \"\") {\n const img = matched.values().next().value\n if (img && img.rows.length > 0) {\n out.push(...img.rows)\n continue\n }\n }\n\n const band = [\"\"]\n let cursor = 0\n for (const marker of line.matchAll(MARKER_RE)) {\n band[0] += line.slice(cursor, marker.index)\n const image = matched.get(Number(marker[1]))\n if (!image) {\n band[0] += marker[0]\n } else {\n const column = stringWidth(band[0])\n const rows = image.rows.length ? image.rows : [labelOf(image.entry)]\n band[0] += rows[0]\n for (let row = 1; row < rows.length; row++) {\n band[row] ??= \"\"\n band[row] += \" \".repeat(Math.max(0, column - stringWidth(band[row]))) + rows[row]\n }\n }\n cursor = marker.index + marker[0].length\n }\n band[0] += line.slice(cursor)\n out.push(...band)\n }\n return out.join(\"\\n\")\n },\n }\n}\n\n/** Friendly inline placeholder for an image that can't render at this\n * position. Math keeps its original source. Otherwise prefers the markdown alt text;\n * falls back to the basename\n * of the source path (so `[clip.png]` instead of `[/tmp/long/path/clip.png]`),\n * and \"image\" for anything weirder. */\nfunction labelOf(entry: ImageEntry): string {\n if (entry.math) return entry.alt\n const label = entry.alt !== \"\" ? entry.alt : basename(entry.src) || \"image\"\n return `[${label}]`\n}\n\nconst MARKER_RE = /<img id=(\\d+)>/g\n"],"mappings":"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"}
|
package/dist/image.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { n as TerminalQueries, r as TerminalQuery } from "./queries-C75-wG1B.mjs";
|
|
2
2
|
import { MaybePromise } from "@zaly/shared";
|
|
3
3
|
import { ImageInfo } from "@zaly/shared/image";
|
|
4
4
|
//#region src/image/kitty.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as
|
|
3
|
-
import { a as StyleBuilder, i as isMarkdown, n as inspect, r as inspectFormat, t as InspectOpts } from "./inspect-
|
|
1
|
+
import { C as ShikiThemeInput, S as ShikiTheme, T as ShikiWorkerRequest, _ as ShikiLanguage, a as BrightAnsiColorName, b as ShikiResult, c as HexColor, d as ThemeKey, f as Theme, g as ShikiJob, h as GeneratedShikiTheme, i as AnyStyle, l as RGB, m as ThemeValue, n as AnsiColorName, o as Color, p as ThemeStyle, r as AnsiStyle, s as ColorLightness, t as AnsiColor, u as Style, v as ShikiOpts, w as ShikiWorkerMessage, x as ShikiSelection, y as ShikiRequest } from "./types-C9ceMsbJ.mjs";
|
|
2
|
+
import { $ as StyleState, $t as keyMatches, At as unwrap, Bt as ActionFn, C as UI, Ct as memo, Dt as signal, E as Terminal, Et as provideContext, F as MountCtx, Gt as NodeActionMap, Ht as Actions, I as RenderCtx, It as Action, Jt as KeyPattern, Kt as KeyEvent, Lt as ActionCtx, Mt as useContext, Nt as withActiveNode, Ot as toAccessor, Pt as withOwner, Q as State, Qt as isKeyPattern, Rt as ActionDef, S as SurfaceType, St as isAccessor, T as OverlaySurface, Tt as peek, Ut as KeyBinding, Vt as ActionMap, Wt as NodeAction, X as Layout, Xt as SpecialKeyName, Y as FlexState, Yt as KeyPatternError, Z as LayoutState, Zt as canonical, _ as NodeVisitor, _t as createRoot, a as parseAttrs, at as Ref, b as Renderer, bt as effect, c as InputRouterEvents, ct as SignalStore, d as KeymapEntry, dt as createAsync, et as Accessor, f as RoutedKey, ft as createContext, g as isNode, gt as createRef, h as Node, ht as createProgressive, i as TerminalQueryOpts, it as Reactive, jt as useActiveOwner, kt as untrack, l as KeyHandler, lt as SuspenseBoundary, m as BaseEvents, mt as createNode, n as TerminalQueries, nt as Owner, o as parseTerminalColor, ot as Setter, p as RoutedPaste, pt as createIterable, qt as KeyModifier, r as TerminalQuery, rt as Progressive, s as InputRouter, st as Signal, t as TerminalPaletteSnapshot, tt as Context, u as KeyPatterns, ut as SuspenseContext, v as RenderEvents, vt as createStore, w as Stream, wt as onCleanup, x as RendererOptions, xt as inRenderContextOf, y as RenderStats, yt as createSuspenseBoundary, zt as ActionFilter } from "./queries-C75-wG1B.mjs";
|
|
3
|
+
import { a as StyleBuilder, i as isMarkdown, n as inspect, r as inspectFormat, t as InspectOpts } from "./inspect-B1uXxdKC.mjs";
|
|
4
4
|
import { ArgsOpts } from "@zaly/shared/args";
|
|
5
5
|
//#region src/input/index.d.ts
|
|
6
6
|
export declare function defineAction<T extends ArgsOpts = ArgsOpts>(action: ActionDef<T>): ActionDef<T>;
|
|
@@ -58,7 +58,16 @@ export declare function createCtx(opts?: Partial<RenderCtx> & {
|
|
|
58
58
|
export declare function createRenderer(opts?: RendererOptions): Promise<Renderer>;
|
|
59
59
|
//#endregion
|
|
60
60
|
//#region src/shiki/shiki.d.ts
|
|
61
|
+
/** List bundled highlighting themes without loading their color definitions. */
|
|
62
|
+
export declare function shikiThemes(): Promise<{
|
|
63
|
+
id: ShikiTheme;
|
|
64
|
+
name: string;
|
|
65
|
+
}[]>;
|
|
61
66
|
export declare function codeToAnsi(code: string, lang: string, opts?: ShikiOpts): Promise<string>;
|
|
62
67
|
//#endregion
|
|
63
|
-
|
|
68
|
+
//#region src/shiki/theme.d.ts
|
|
69
|
+
/** Resolve highlighting independently of a theme's display name or origin. */
|
|
70
|
+
export declare function shikiTheme(theme: Theme, selection?: ShikiSelection): ShikiThemeInput;
|
|
71
|
+
//#endregion
|
|
72
|
+
export { Accessor, type Action, type ActionCtx, type ActionDef, type ActionFilter, type ActionFn, type ActionMap, type Actions, type AnsiColor, type AnsiColorName, type AnsiStyle, type AnyStyle, type BaseEvents, type BrightAnsiColorName, type Color, type ColorLightness, Context, type FlexState, type GeneratedShikiTheme, type HexColor, type InputRouter, type InputRouterEvents, InspectOpts, type KeyBinding, KeyEvent, type KeyHandler, KeyModifier, KeyPattern, KeyPatternError, type KeyPatterns, type KeymapEntry, type Layout, type LayoutState, type MountCtx, type Node, type NodeAction, type NodeActionMap, type NodeVisitor, type OverlaySurface, Owner, Progressive, type RGB, Reactive, Ref, type RenderCtx, type RenderEvents, type RenderStats, type Renderer, type RendererOptions, type RoutedKey, type RoutedPaste, Setter, type ShikiJob, type ShikiLanguage, type ShikiOpts, type ShikiRequest, type ShikiResult, type ShikiSelection, type ShikiTheme, type ShikiThemeInput, type ShikiWorkerMessage, type ShikiWorkerRequest, Signal, SignalStore, SpecialKeyName, type State, type Stream, type Style, type StyleState, type SurfaceType, SuspenseBoundary, SuspenseContext, type Terminal, TerminalPaletteSnapshot, TerminalQueries, TerminalQuery, TerminalQueryOpts, type Theme, type ThemeKey, type ThemeStyle, type ThemeValue, type UI, canonical, createAsync, createContext, createIterable, createNode, createProgressive, createRef, createRoot, createStore, createSuspenseBoundary, effect, inRenderContextOf, inspect, inspectFormat, isAccessor, isKeyPattern, isMarkdown, type isNode, keyMatches, memo, onCleanup, parseAttrs, parseTerminalColor, peek, provideContext, signal, toAccessor, untrack, unwrap, useActiveOwner, useContext, withActiveNode, withOwner };
|
|
64
73
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":["_$__reactive_ts0.Context"],"sources":["../src/input/index.ts","../src/core/render.ts","../src/core/index.ts","../src/renderer/index.ts","../src/shiki/shiki.ts"],"mappings":";;;;;wBAGgB,aAAa,UAAU,WAAW,UAAU,QAAQ,UAAU,KAAK,UAAU;wBAC7E,aAAa,UAAU,WAAW,UAAU,QAAQ,OAAO,KAAK,OAAO;;;;;;;;;YCmB3E;;EAEV,OAAO,SAAS;;EAEhB,OAAO,SAAS;;EAEhB,QAAQ;EACR,SAAS;;qBAEE,eAAaA,QAAA;;;;;;;;;;;;;;;;;;;;;wBAsBJ,aACpB,MAAM,MACN,KAAK;EAAc,UAAU;IAC5B;wBACmB,aAAa,YAAY,MAAM,MAAM,YAAY;;;wBC/CjD,UACpB,OAAM,QAAQ;EAAe,QAAQ;IACpC,QAAQ;;;;wBCJW,eAAe,OAAM,kBAAuB,QAAQ;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["_$__reactive_ts0.Context"],"sources":["../src/input/index.ts","../src/core/render.ts","../src/core/index.ts","../src/renderer/index.ts","../src/shiki/shiki.ts","../src/shiki/theme.ts"],"mappings":";;;;;wBAGgB,aAAa,UAAU,WAAW,UAAU,QAAQ,UAAU,KAAK,UAAU;wBAC7E,aAAa,UAAU,WAAW,UAAU,QAAQ,OAAO,KAAK,OAAO;;;;;;;;;YCmB3E;;EAEV,OAAO,SAAS;;EAEhB,OAAO,SAAS;;EAEhB,QAAQ;EACR,SAAS;;qBAEE,eAAaA,QAAA;;;;;;;;;;;;;;;;;;;;;wBAsBJ,aACpB,MAAM,MACN,KAAK;EAAc,UAAU;IAC5B;wBACmB,aAAa,YAAY,MAAM,MAAM,YAAY;;;wBC/CjD,UACpB,OAAM,QAAQ;EAAe,QAAQ;IACpC,QAAQ;;;;wBCJW,eAAe,OAAM,kBAAuB,QAAQ;;;;wBCHpD,eAAW;EAGnB,IAAA;;;wBAKQ,WAAW,cAAc,cAAc,OAAO,YAAY;;;;wBC+BhE,WAAW,OAAO,OAAO,YAAW,iBAA0B"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { C as useActiveOwner, E as withOwner, S as unwrap, T as withActiveNode, _ as peek, a as createIterable, b as toAccessor, c as createRef, d as createSuspenseBoundary, f as effect, g as onCleanup, h as memo, i as createContext, l as createRoot, m as isAccessor, n as SuspenseContext, o as createNode, p as inRenderContextOf, r as createAsync, s as createProgressive, t as Owner, u as createStore, v as provideContext, w as useContext, x as untrack, y as signal } from "./reactive-f7NpAi69.mjs";
|
|
2
|
-
import { n as inspectFormat, r as isMarkdown, t as inspect } from "./inspect-
|
|
3
|
-
import { n as createRender, t as RenderContext } from "./render-
|
|
4
|
-
import { t as codeToAnsi } from "./shiki
|
|
5
|
-
import {
|
|
2
|
+
import { n as inspectFormat, r as isMarkdown, t as inspect } from "./inspect-Cxzs-W0g.mjs";
|
|
3
|
+
import { n as createRender, t as RenderContext } from "./render-B7LfNM5K.mjs";
|
|
4
|
+
import { n as shikiThemes, t as codeToAnsi } from "./shiki-CJauRusM.mjs";
|
|
5
|
+
import { t as shikiTheme } from "./theme-C8LkcoaK.mjs";
|
|
6
|
+
import { a as canonical, i as KeyPatternError, n as parseAttrs, o as isKeyPattern, r as parseTerminalColor, s as keyMatches, t as TerminalQueries } from "./queries-BUkBxkuM.mjs";
|
|
6
7
|
//#region src/input/index.ts
|
|
7
8
|
function defineAction(action) {
|
|
8
9
|
return action;
|
|
@@ -10,17 +11,17 @@ function defineAction(action) {
|
|
|
10
11
|
//#endregion
|
|
11
12
|
//#region src/core/index.ts
|
|
12
13
|
async function createCtx(opts = {}) {
|
|
13
|
-
const { createCtx: create } = await import("./ctx-
|
|
14
|
+
const { createCtx: create } = await import("./ctx-CndlTp1T.mjs");
|
|
14
15
|
return create(opts);
|
|
15
16
|
}
|
|
16
17
|
//#endregion
|
|
17
18
|
//#region src/renderer/index.ts
|
|
18
19
|
/** Factory shorthand for `new Renderer(opts)`. */
|
|
19
20
|
async function createRenderer(opts = {}) {
|
|
20
|
-
const { Renderer } = await import("./renderer-
|
|
21
|
+
const { Renderer } = await import("./renderer-BLsd-wrG.mjs");
|
|
21
22
|
return new Renderer(opts);
|
|
22
23
|
}
|
|
23
24
|
//#endregion
|
|
24
|
-
export { KeyPatternError, Owner, RenderContext, SuspenseContext, TerminalQueries, canonical, codeToAnsi, createAsync, createContext, createCtx, createIterable, createNode, createProgressive, createRef, createRender, createRenderer, createRoot, createStore, createSuspenseBoundary, defineAction, effect, inRenderContextOf, inspect, inspectFormat, isAccessor, isKeyPattern, isMarkdown, keyMatches, memo, onCleanup, parseAttrs, peek, provideContext, signal, toAccessor, untrack, unwrap, useActiveOwner, useContext, withActiveNode, withOwner };
|
|
25
|
+
export { KeyPatternError, Owner, RenderContext, SuspenseContext, TerminalQueries, canonical, codeToAnsi, createAsync, createContext, createCtx, createIterable, createNode, createProgressive, createRef, createRender, createRenderer, createRoot, createStore, createSuspenseBoundary, defineAction, effect, inRenderContextOf, inspect, inspectFormat, isAccessor, isKeyPattern, isMarkdown, keyMatches, memo, onCleanup, parseAttrs, parseTerminalColor, peek, provideContext, shikiTheme, shikiThemes, signal, toAccessor, untrack, unwrap, useActiveOwner, useContext, withActiveNode, withOwner };
|
|
25
26
|
|
|
26
27
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/input/index.ts","../src/core/index.ts","../src/renderer/index.ts"],"sourcesContent":["import type { ArgsOpts } from \"@zaly/shared/args\"\nimport type { Action, ActionDef } from \"./actions.ts\"\n\nexport function defineAction<T extends ArgsOpts = ArgsOpts>(action: ActionDef<T>): ActionDef<T>\nexport function defineAction<T extends ArgsOpts = ArgsOpts>(action: Action<T>): Action<T>\nexport function defineAction<T extends ArgsOpts = ArgsOpts>(\n action: ActionDef<T> | Action<T>\n): ActionDef<T> | Action<T> {\n return action\n}\n","import type { Theme } from \"../themes/types.ts\"\nimport type { RenderCtx } from \"./ctx.ts\"\n\nexport type { RenderCtx, MountCtx } from \"./ctx.ts\"\n\nexport type * from \"./node.ts\"\nexport type * from \"./state.ts\"\n\nexport * from \"./reactive.ts\"\nexport * from \"./render.ts\"\n\nexport async function createCtx(\n opts: Partial<RenderCtx> & { theme?: Theme } = {}\n): Promise<RenderCtx> {\n const { createCtx: create } = await import(\"./ctx.ts\")\n return create(opts)\n}\n","import type { Renderer, RendererOptions } from \"./renderer.ts\"\n\nexport type * from \"./renderer.ts\"\nexport type { OverlaySurface } from \"./overlay.ts\"\nexport type { Stream } from \"./stream.ts\"\nexport type { Terminal } from \"./terminal.ts\"\nexport type { UI } from \"./ui.ts\"\n\n/** Factory shorthand for `new Renderer(opts)`. */\nexport async function createRenderer(opts: RendererOptions = {}): Promise<Renderer> {\n const { Renderer } = await import(\"./renderer.ts\")\n return new Renderer(opts)\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/input/index.ts","../src/core/index.ts","../src/renderer/index.ts"],"sourcesContent":["import type { ArgsOpts } from \"@zaly/shared/args\"\nimport type { Action, ActionDef } from \"./actions.ts\"\n\nexport function defineAction<T extends ArgsOpts = ArgsOpts>(action: ActionDef<T>): ActionDef<T>\nexport function defineAction<T extends ArgsOpts = ArgsOpts>(action: Action<T>): Action<T>\nexport function defineAction<T extends ArgsOpts = ArgsOpts>(\n action: ActionDef<T> | Action<T>\n): ActionDef<T> | Action<T> {\n return action\n}\n","import type { Theme } from \"../themes/types.ts\"\nimport type { RenderCtx } from \"./ctx.ts\"\n\nexport type { RenderCtx, MountCtx } from \"./ctx.ts\"\n\nexport type * from \"./node.ts\"\nexport type * from \"./state.ts\"\n\nexport * from \"./reactive.ts\"\nexport * from \"./render.ts\"\n\nexport async function createCtx(\n opts: Partial<RenderCtx> & { theme?: Theme } = {}\n): Promise<RenderCtx> {\n const { createCtx: create } = await import(\"./ctx.ts\")\n return create(opts)\n}\n","import type { Renderer, RendererOptions } from \"./renderer.ts\"\n\nexport type * from \"./renderer.ts\"\nexport type { OverlaySurface } from \"./overlay.ts\"\nexport type { Stream } from \"./stream.ts\"\nexport type { Terminal } from \"./terminal.ts\"\nexport type { UI } from \"./ui.ts\"\n\n/** Factory shorthand for `new Renderer(opts)`. */\nexport async function createRenderer(opts: RendererOptions = {}): Promise<Renderer> {\n const { Renderer } = await import(\"./renderer.ts\")\n return new Renderer(opts)\n}\n"],"mappings":";;;;;;;AAKA,SAAgB,aACd,QAC0B;CAC1B,OAAO;AACT;;;ACEA,eAAsB,UACpB,OAA+C,CAAC,GAC5B;CACpB,MAAM,EAAE,WAAW,WAAW,MAAM,OAAO;CAC3C,OAAO,OAAO,IAAI;AACpB;;;;ACPA,eAAsB,eAAe,OAAwB,CAAC,GAAsB;CAClF,MAAM,EAAE,aAAa,MAAM,OAAO;CAClC,OAAO,IAAI,SAAS,IAAI;AAC1B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as unwrap, x as untrack } from "./reactive-f7NpAi69.mjs";
|
|
2
2
|
import { t as Node } from "./node-BZ7f6HzU.mjs";
|
|
3
|
-
import { o as formatText } from "./text-
|
|
3
|
+
import { o as formatText } from "./text-BoJdKXLU.mjs";
|
|
4
4
|
import { t as clipboard } from "./clipboard-CNPBTX7j.mjs";
|
|
5
5
|
import { hash, isPromiseLike } from "@zaly/shared";
|
|
6
6
|
import { sliceAnsi, splitAnsi, stringWidth } from "@zaly/shared/ansi";
|
|
@@ -499,4 +499,4 @@ function countLines(value) {
|
|
|
499
499
|
//#endregion
|
|
500
500
|
export { input as n, Input as t };
|
|
501
501
|
|
|
502
|
-
//# sourceMappingURL=input-
|
|
502
|
+
//# sourceMappingURL=input-ET2YEMcl.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-BGTTujDN.mjs","names":[],"sources":["../src/widgets/input.ts"],"sourcesContent":["import type { MaybePromise } from \"@zaly/shared\"\nimport type { DetectedFile } from \"@zaly/shared/detect\"\nimport type { RenderCtx } from \"../core/ctx.ts\"\nimport type { BaseEvents } from \"../core/node.ts\"\nimport type { Reactive } from \"../core/reactive.ts\"\nimport type { StyleState } from \"../core/state.ts\"\nimport type { NodeActionMap } from \"../input/actions.ts\"\nimport type { RoutedKey } from \"../input/router.ts\"\nimport type { Size } from \"../layout/size.ts\"\nimport type { StyleBuilder } from \"../style/builder.ts\"\n\nimport { hash, isPromiseLike } from \"@zaly/shared\"\nimport { sliceAnsi, splitAnsi, stringWidth } from \"@zaly/shared/ansi\"\nimport { fileDetect } from \"@zaly/shared/detect\"\nimport { basename } from \"pathe\"\nimport { Node } from \"../core/node.ts\"\nimport { untrack, unwrap } from \"../core/reactive.ts\"\nimport { clipboard } from \"../input/clipboard.ts\"\nimport { formatText } from \"../layout/text.ts\"\n\nexport interface InputState extends StyleState {\n /** Current text content. May include `\\n` for multi-line input. */\n value?: string\n /** Shown dim when `value` is empty. */\n placeholder?: Reactive<string | undefined>\n /** Cursor position as a char index in `value`. Clamped to `[0, value.length]`. */\n cursor?: number\n /** Render width. Defaults to `fill`. */\n width?: Size\n /** Submitted input history, newest last. */\n history?: readonly string[]\n /** Threshold for showing pasted content as an attachment rather than raw text */\n pasteMaxLines?: number\n pasteMaxChars?: number\n canAttach?: (file: InputAttachment) => boolean\n format?: (value: string, ctx: { style: StyleBuilder }) => MaybePromise<string>\n validate?: (value: string) => boolean\n}\n\nexport type InputValue = { value: string; attachments: InputAttachment[] }\n\nconst PASTE_MAX_LINES = 5\nconst PASTE_MAX_CHARS = 1000\nconst graphemes = new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n\n/** A clipboard or bracketed paste that exceeds the `pasteMax*` thresholds. **/\ntype Paste = { type: \"paste\"; text: string }\n\n/** A file or image attachment detected from the clipboard. */\nexport type InputAttachment = DetectedFile & { path: string }\n\nexport type InputEvents = BaseEvents & {\n /** Fired when the submitted history changes. */\n history: { history: string[]; added: string }\n /** Fired when plain Enter is pressed. Payload is the current value. */\n submit: { value: string; attachments: InputAttachment[] }\n /** Fired when the user pastes a non-text resource via the\n * `input.paste` action. Images and file references both land here,\n * discriminated by `attachment.kind`. One event fires per image\n * paste; one per file in a multi-file paste.\n *\n * Wrapped under `attachment` because `InputAttachment` carries its\n * own `type` field (MIME) that would shadow the envelope's `type`\n * discriminator if spread directly. */\n attach: { attachment: InputAttachment }\n}\n\ntype FormatEntry = { promise?: Promise<void>; result?: string; input: string }\n\n/**\n * Multi-line text input with auto-grow.\n *\n * Editing commands (`cursorLeft`, `deleteWordBack`, `submit`, …) live on\n * `this.actions` as zero-arg methods. The input router maps keymap\n * bindings like `\"input.cursorLeft\"` onto those methods — users bind\n * different keys by configuring the keymap, not by patching the class.\n * The methods are also callable directly (`input.actions.submit()`),\n * which is handy in tests or for higher-level macros.\n *\n * What this class *still* handles via its `key` event listener:\n * - **Printable character insertion.** An unbound keystroke whose\n * `text` is set and has no ctrl/alt/meta modifier becomes a literal\n * insert at the cursor. There's no action for every printable char\n * in the keymap; the raw-key fallback handles them.\n * - **Paste events.** Whole payload inserted at cursor; always.\n *\n * Everything else (navigation, editing, submit/newline) goes through\n * the router → actions pipeline. Unbound non-printable keys fall back\n * to `emit(\"key\", …)` and bubble to the parent chain.\n *\n * Rendering word-wraps each logical line to `ctx.width`, so long\n * messages naturally grow vertically. The UI surface resizes its\n * reserved footer when the Input's row count changes, so the stream\n * above shifts accordingly.\n */\nexport class Input extends Node<InputState, InputEvents> {\n /** Class-level scope tag used by the input router to bind keymaps. */\n static readonly type = \"input\"\n\n override readonly type = Input.type\n #focused = false\n #history: string[] = []\n #historyDraft = \"\"\n #historyIndex: number | undefined\n #preferredCol: number | undefined\n #staged: ((InputAttachment | Paste) & { id: number; marker: string })[] = []\n #formatCache: Map<string, FormatEntry> & { version?: number } = new Map<string, FormatEntry>()\n #formatGen = 0\n\n /**\n * Editing actions. Parameterless — they close over `this` — so both\n * the router (via keymap dispatch) and application code can invoke\n * them. Add to the keymap in `src/input/actions.ts` to give them\n * default key bindings.\n */\n override actions = {\n \"input.cursorDown\": (): void => {\n const v = this.state.value ?? \"\"\n const { col, line } = posToLineCol(v, this.#cursor())\n if (line >= countLines(v) - 1) {\n this.#historyNext()\n return\n }\n this.#preferredCol ??= col\n this.state.cursor = lineColToPos(v, line + 1, this.#preferredCol)\n },\n \"input.cursorLeft\": (): void => {\n const c = this.#cursor()\n this.#preferredCol = undefined\n this.state.cursor = c > 0 ? c - 1 : c\n },\n \"input.cursorLineEnd\": (): void => {\n const v = this.state.value ?? \"\"\n this.#preferredCol = undefined\n this.state.cursor = lineEndPos(v, this.#cursor())\n },\n \"input.cursorLineStart\": (): void => {\n const v = this.state.value ?? \"\"\n const { line } = posToLineCol(v, this.#cursor())\n this.#preferredCol = undefined\n this.state.cursor = lineColToPos(v, line, 0)\n },\n \"input.cursorRight\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n this.state.cursor = c < v.length ? c + 1 : c\n },\n \"input.cursorUp\": (): void => {\n const v = this.state.value ?? \"\"\n const { col, line } = posToLineCol(v, this.#cursor())\n if (line === 0) {\n this.#historyPrev()\n return\n }\n this.#preferredCol ??= col\n this.state.cursor = lineColToPos(v, line - 1, this.#preferredCol)\n },\n \"input.deleteCharBack\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n if (c === 0) return\n this.#historyEdit()\n const marker = this.#markerRange(c, \"back\")\n if (marker) return this.#deleteRange(marker.start, marker.end)\n this.state.set({ cursor: c - 1, value: v.slice(0, c - 1) + v.slice(c) })\n },\n \"input.deleteCharForward\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n if (c >= v.length) return\n this.#historyEdit()\n const marker = this.#markerRange(c, \"forward\")\n if (marker) return this.#deleteRange(marker.start, marker.end)\n this.state.value = v.slice(0, c) + v.slice(c + 1)\n },\n \"input.deleteWordBack\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n let i = c\n while (i > 0 && isWhitespace(v[i - 1])) i--\n while (i > 0 && !isWhitespace(v[i - 1])) i--\n if (i === c) return\n this.#historyEdit()\n this.state.set({ cursor: i, value: v.slice(0, i) + v.slice(c) })\n },\n \"input.insertNewline\": (): void => {\n // Smart indent: copy the leading whitespace of the current\n // logical line onto the new line so continuations stay aligned\n // with the bullet / quote / prefix the user typed.\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n let lineStart = c\n while (lineStart > 0 && v[lineStart - 1] !== \"\\n\") lineStart--\n let indent = \"\"\n for (let i = lineStart; i < c; i++) {\n const ch = v[i]\n if (ch === \" \" || ch === \"\\t\") indent += ch\n else break\n }\n const insert = `\\n${indent}`\n this.#historyEdit()\n this.state.set({\n cursor: c + insert.length,\n value: v.slice(0, c) + insert + v.slice(c),\n })\n },\n \"input.insertTab\": (): void => {\n // Two spaces rather than `\\t` — terminal tab stops are\n // unpredictable (often 8 cells) and play badly with our per-row\n // layout. Soft tabs are the safer default; users wanting real\n // tabs can override the action.\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n const tab = \" \"\n this.#historyEdit()\n this.state.set({ cursor: c + tab.length, value: v.slice(0, c) + tab + v.slice(c) })\n },\n // `ctrl-v` queries the OS clipboard (via xclip / wl-paste / pbpaste /\n // PowerShell depending on platform). The richest content wins:\n //\n // - **image bytes** → one `attach` event with a temp PNG path.\n // - **file references** → one `attach` event per file.\n // - **plain text** → inserted at the cursor like a regular paste.\n //\n // Fire-and-forget async — we await the probe and commit the\n // result in a microtask.\n \"input.paste\": (): void => {\n void (async (): Promise<void> => {\n const content = await clipboard.read()\n if (!content) return\n\n // Route through the regular paste handler\n if (content.kind === \"text\") {\n void this.emit(\"paste\", {\n paste: {\n stop: () => void 0,\n stopped: false,\n text: content.text,\n },\n })\n return\n }\n\n const paths: string[] = content.kind === \"image\" ? [content.path] : content.paths\n const files = await Promise.all(paths.map((path) => fileDetect({ path })))\n for (let i = 0; i < paths.length; i++) {\n const path = paths[i]\n const file = files[i]\n if (!file) continue\n this.attach({ ...file, path })\n }\n })()\n },\n \"input.submit\": (): void => {\n const value = this.state.value ?? \"\"\n if (this.state.validate?.(value) === false) return\n const ret = this.consume()\n this.#historyAdd(ret.value)\n void this.emit(\"submit\", ret)\n },\n } satisfies NodeActionMap\n\n constructor(initial: InputState = {}) {\n const value = initial.value ?? \"\"\n super({ cursor: value.length, value, ...initial })\n this.#history = [...(initial.history ?? [])]\n this.on(\"key\", ({ key }) => {\n this.#handleKey(key)\n })\n this.on(\"paste\", ({ paste }) => {\n this.paste(paste.text)\n paste.stop()\n })\n this.on(\"focus\", () => {\n this.#focused = true\n this.invalidate()\n })\n this.on(\"blur\", () => {\n this.#focused = false\n this.invalidate()\n })\n\n this.on(\"mount\", () => {\n this.ctx?.input.events.on(\"terminal-focus\", () => this.invalidate(), {\n signal: this.mountSignal,\n })\n })\n }\n\n get history(): readonly string[] {\n return this.#history\n }\n\n set history(v: readonly string[]) {\n this.#history = [...v]\n this.#historyIndex = undefined\n }\n\n attach(att: InputAttachment | Paste): void {\n if (att.type !== \"paste\" && this.state.canAttach?.(att) === false) {\n // Caller doesn't want this attachment (e.g. model doesn't support it) — fall\n // back to pasting the path as plain text\n return this.insert(att.path)\n }\n\n const id = this.#staged.length + 1\n let prefix = att.type[0].toUpperCase() + att.type.slice(1)\n let suffix = \"\"\n if (att.type === \"paste\") {\n prefix = \"Pasted text\"\n suffix = ` +${countLines(att.text)} lines`\n } else if (![\"image\", \"pdf\"].includes(att.type)) suffix = ` ${basename(att.path)}`\n const marker = `[${prefix} #${id}${suffix}]`\n this.#staged.push({ ...att, id, marker })\n this.insert(marker)\n\n if (att.type !== \"paste\") void this.emit(\"attach\", { attachment: att })\n }\n\n paste(text: string): void {\n if (\n countLines(text) > (this.state.pasteMaxLines ?? PASTE_MAX_LINES) ||\n stringWidth(text) > (this.state.pasteMaxChars ?? PASTE_MAX_CHARS)\n )\n return this.attach({ text, type: \"paste\" })\n this.insert(text)\n }\n\n insert(text: string): void {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#historyEdit()\n this.#preferredCol = undefined\n this.state.set({\n cursor: c + text.length,\n value: v.slice(0, c) + text + v.slice(c),\n })\n }\n\n replace(text: string): void {\n this.state.value = \"\"\n this.insert(text)\n }\n\n /** Consume the input's current value and attachments.\n * Pastes are replaced inline with their text; file/image\n * attachments are returned in the `attachments` array and removed from the value. */\n consume(): InputValue {\n let value = this.state.value ?? \"\"\n const atts: InputAttachment[] = []\n for (const att of this.#staged) {\n if (!value.includes(att.marker)) continue\n if (att.type === \"paste\") {\n value = value.replace(att.marker, att.text)\n } else atts.push(att)\n }\n this.#staged = []\n this.#preferredCol = undefined\n this.state.set({ cursor: 0, value: \"\" })\n return { attachments: atts, value }\n }\n\n #cursor(): number {\n const v = this.state.value ?? \"\"\n return Math.max(0, Math.min(v.length, this.state.cursor ?? 0))\n }\n\n #deleteRange(start: number, end: number): void {\n const v = this.state.value ?? \"\"\n this.#historyEdit()\n this.#preferredCol = undefined\n this.state.set({ cursor: start, value: v.slice(0, start) + v.slice(end) })\n }\n\n historyAdd(value: string): void {\n this.#historyAdd(value)\n }\n\n #historyAdd(value: string): void {\n if (value.trim() === \"\") return\n if (this.#history.at(-1) !== value) {\n this.#history.push(value)\n void this.emit(\"history\", { added: value, history: [...this.#history] })\n }\n this.#historyDraft = \"\"\n this.#historyIndex = undefined\n }\n\n #historyEdit(): void {\n this.#historyDraft = \"\"\n this.#historyIndex = undefined\n }\n\n #historyNext(): void {\n if (this.#historyIndex === undefined) return\n const next = this.#historyIndex + 1\n if (next >= this.#history.length) {\n this.#historySet(this.#historyDraft)\n this.#historyDraft = \"\"\n this.#historyIndex = undefined\n return\n }\n this.#historyIndex = next\n this.#historySet(this.#history[next])\n }\n\n #historyPrev(): void {\n if (this.#history.length === 0) return\n if (this.#historyIndex === undefined) {\n this.#historyDraft = this.state.value ?? \"\"\n this.#historyIndex = this.#history.length - 1\n } else if (this.#historyIndex > 0) this.#historyIndex--\n this.#historySet(this.#history[this.#historyIndex])\n }\n\n #historySet(value: string): void {\n this.#preferredCol = undefined\n this.state.set({ cursor: value.length, value })\n }\n\n #markerRange(pos: number, dir: \"back\" | \"forward\"): { start: number; end: number } | undefined {\n const value = this.state.value ?? \"\"\n for (const att of this.#staged) {\n const start = value.indexOf(att.marker)\n if (start === -1) continue\n const end = start + att.marker.length\n if (dir === \"back\" && pos > start && pos <= end) return { end, start }\n if (dir === \"forward\" && pos >= start && pos < end) return { end, start }\n }\n }\n\n // Fallback path for anything the router couldn't resolve to a named\n // action: printable characters go straight into the value. Any other\n // unbound key (f7, unclaimed ctrl-combos, etc.) bubbles untouched.\n #handleKey(ev: RoutedKey): void {\n if (ev.text === undefined || ev.ctrl || ev.alt || ev.meta) return\n this.insert(ev.text)\n ev.stop()\n }\n\n #format(value: string, ctx: RenderCtx): string {\n const format = this.state.format\n if (!format) return value\n\n if (ctx.version !== this.#formatCache.version) {\n this.#formatCache.clear()\n this.#formatCache.version = ctx.version\n }\n\n const key = hash(value)\n const cached = this.#formatCache.get(key)\n if (cached?.result !== undefined) return cached.result\n const streaming = this.#streamingFormat(value)\n if (cached?.promise) return streaming ?? value\n\n const ret = format(value, { style: ctx.style })\n if (!isPromiseLike(ret)) return ret\n\n const gen = ++this.#formatGen\n const entry: FormatEntry = { input: value }\n entry.promise = ret.then(\n (result) => {\n if (this.#formatCache.get(key) !== entry) return\n entry.result = result\n entry.promise = undefined\n if (this.#formatGen === gen && result !== value) untrack(() => this.invalidate())\n },\n () => {\n if (this.#formatCache.get(key) === entry) this.#formatCache.delete(key)\n }\n )\n this.#formatCache.set(key, entry)\n while (this.#formatCache.size > 100)\n this.#formatCache.delete(this.#formatCache.keys().next().value!)\n return streaming ?? value\n }\n\n /** Reuse a highlighted prefix while async formatting catches up. */\n #streamingFormat(value: string): string | undefined {\n let ret: [string, FormatEntry] | undefined\n for (const [key, cached] of this.#formatCache) {\n if (cached.result === undefined) continue\n if (value.startsWith(cached.input) && cached.input.length > (ret?.[1].input.length ?? 0))\n ret = [key, cached]\n }\n if (ret === undefined) return\n this.#formatCache.delete(ret[0])\n this.#formatCache.set(ret[0], ret[1]) // bump to end of LRU\n return ret[1].result + value.slice(ret[1].input.length)\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n const value = this.state.value ?? \"\"\n const placeholder = this.state.placeholder ?? \"\"\n const cursor = this.#cursor()\n const focused = this.#focused\n\n // Build the styled content string. Layout (word-wrap, split into\n // rows, pad to width) is delegated to `Text` below — wrap-ansi knows\n // how to close+reopen SGR across line breaks, so the inverse-cursor\n // span survives wrapping.\n let content: string\n if (value === \"\") {\n const ph = unwrap(placeholder)\n content = ph ? ` ${ctx.style.quiet(ph)}` : \"\"\n } else {\n content = value\n for (const att of this.#staged) {\n if (!content.includes(att.marker)) continue\n content = content.replace(att.marker, ctx.style.accent(att.marker))\n }\n content = this.#format(content, ctx)\n }\n\n // Fake cursor. `cursor` is an absolute index in the raw value, while\n // rendering is line-oriented: newlines consume string indices but not\n // cells in any rendered row. Project the cursor to line/column before\n // slicing the formatted line.\n if (focused && this.ctx?.input.terminalFocus) {\n const { col, line } = posToLineCol(value, cursor)\n const lines = splitAnsi(content)\n const target = Math.max(0, Math.min(line, lines.length - 1))\n const row = lines[target] ?? \"\"\n const head = sliceAnsi(row, 0, col)\n const at = sliceAnsi(row, col, col + 1) || \" \"\n const tail = sliceAnsi(row, col + 1)\n lines[target] = head + ctx.style.inverse(at) + tail\n content = lines.join(\"\\n\")\n }\n\n return formatText(content, {\n style: ctx.style.add(this.state),\n width: ctx.width,\n wrap: \"word\",\n })\n }\n}\n\n/**\n * Factory for `Input`. All fields optional; default is an empty,\n * focusable input that fills `ctx.width` and has no placeholder.\n *\n * ```ts\n * input({ placeholder: \"type a message…\" })\n * const i = input({ value: \"draft\" })\n * i.on(\"submit\", (text) => console.log(\"user typed\", text))\n * ```\n */\nexport function input(state: InputState = {}): Input {\n return new Input(state)\n}\n\n// ---------- helpers ----------\n\nfunction isWhitespace(ch: string | undefined): boolean {\n return ch !== undefined && (ch === \" \" || ch === \"\\t\" || ch === \"\\n\")\n}\n\nfunction posToLineCol(value: string, cursor: number): { line: number; col: number } {\n const prefix = value.slice(0, cursor)\n const lineStart = prefix.lastIndexOf(\"\\n\") + 1\n return {\n col: stringWidth(prefix.slice(lineStart)),\n line: prefix.split(\"\\n\").length - 1,\n }\n}\n\nfunction lineColToPos(value: string, line: number, col: number): number {\n const lines = value.split(\"\\n\")\n const clampLine = Math.max(0, Math.min(line, lines.length - 1))\n let abs = 0\n for (let i = 0; i < clampLine; i++) abs += lines[i].length + 1\n\n let cells = 0\n let offset = 0\n for (const { segment } of graphemes.segment(lines[clampLine])) {\n const width = stringWidth(segment)\n if (cells + width > col) break\n cells += width\n offset += segment.length\n }\n return abs + offset\n}\n\nfunction lineEndPos(value: string, cursor: number): number {\n let i = cursor\n while (i < value.length && value[i] !== \"\\n\") i++\n return i\n}\n\nfunction countLines(value: string): number {\n let n = 1\n for (const ch of value) if (ch === \"\\n\") n++\n return n\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"input-ET2YEMcl.mjs","names":[],"sources":["../src/widgets/input.ts"],"sourcesContent":["import type { MaybePromise } from \"@zaly/shared\"\nimport type { DetectedFile } from \"@zaly/shared/detect\"\nimport type { RenderCtx } from \"../core/ctx.ts\"\nimport type { BaseEvents } from \"../core/node.ts\"\nimport type { Reactive } from \"../core/reactive.ts\"\nimport type { StyleState } from \"../core/state.ts\"\nimport type { NodeActionMap } from \"../input/actions.ts\"\nimport type { RoutedKey } from \"../input/router.ts\"\nimport type { Size } from \"../layout/size.ts\"\nimport type { StyleBuilder } from \"../style/builder.ts\"\n\nimport { hash, isPromiseLike } from \"@zaly/shared\"\nimport { sliceAnsi, splitAnsi, stringWidth } from \"@zaly/shared/ansi\"\nimport { fileDetect } from \"@zaly/shared/detect\"\nimport { basename } from \"pathe\"\nimport { Node } from \"../core/node.ts\"\nimport { untrack, unwrap } from \"../core/reactive.ts\"\nimport { clipboard } from \"../input/clipboard.ts\"\nimport { formatText } from \"../layout/text.ts\"\n\nexport interface InputState extends StyleState {\n /** Current text content. May include `\\n` for multi-line input. */\n value?: string\n /** Shown dim when `value` is empty. */\n placeholder?: Reactive<string | undefined>\n /** Cursor position as a char index in `value`. Clamped to `[0, value.length]`. */\n cursor?: number\n /** Render width. Defaults to `fill`. */\n width?: Size\n /** Submitted input history, newest last. */\n history?: readonly string[]\n /** Threshold for showing pasted content as an attachment rather than raw text */\n pasteMaxLines?: number\n pasteMaxChars?: number\n canAttach?: (file: InputAttachment) => boolean\n format?: (value: string, ctx: { style: StyleBuilder }) => MaybePromise<string>\n validate?: (value: string) => boolean\n}\n\nexport type InputValue = { value: string; attachments: InputAttachment[] }\n\nconst PASTE_MAX_LINES = 5\nconst PASTE_MAX_CHARS = 1000\nconst graphemes = new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n\n/** A clipboard or bracketed paste that exceeds the `pasteMax*` thresholds. **/\ntype Paste = { type: \"paste\"; text: string }\n\n/** A file or image attachment detected from the clipboard. */\nexport type InputAttachment = DetectedFile & { path: string }\n\nexport type InputEvents = BaseEvents & {\n /** Fired when the submitted history changes. */\n history: { history: string[]; added: string }\n /** Fired when plain Enter is pressed. Payload is the current value. */\n submit: { value: string; attachments: InputAttachment[] }\n /** Fired when the user pastes a non-text resource via the\n * `input.paste` action. Images and file references both land here,\n * discriminated by `attachment.kind`. One event fires per image\n * paste; one per file in a multi-file paste.\n *\n * Wrapped under `attachment` because `InputAttachment` carries its\n * own `type` field (MIME) that would shadow the envelope's `type`\n * discriminator if spread directly. */\n attach: { attachment: InputAttachment }\n}\n\ntype FormatEntry = { promise?: Promise<void>; result?: string; input: string }\n\n/**\n * Multi-line text input with auto-grow.\n *\n * Editing commands (`cursorLeft`, `deleteWordBack`, `submit`, …) live on\n * `this.actions` as zero-arg methods. The input router maps keymap\n * bindings like `\"input.cursorLeft\"` onto those methods — users bind\n * different keys by configuring the keymap, not by patching the class.\n * The methods are also callable directly (`input.actions.submit()`),\n * which is handy in tests or for higher-level macros.\n *\n * What this class *still* handles via its `key` event listener:\n * - **Printable character insertion.** An unbound keystroke whose\n * `text` is set and has no ctrl/alt/meta modifier becomes a literal\n * insert at the cursor. There's no action for every printable char\n * in the keymap; the raw-key fallback handles them.\n * - **Paste events.** Whole payload inserted at cursor; always.\n *\n * Everything else (navigation, editing, submit/newline) goes through\n * the router → actions pipeline. Unbound non-printable keys fall back\n * to `emit(\"key\", …)` and bubble to the parent chain.\n *\n * Rendering word-wraps each logical line to `ctx.width`, so long\n * messages naturally grow vertically. The UI surface resizes its\n * reserved footer when the Input's row count changes, so the stream\n * above shifts accordingly.\n */\nexport class Input extends Node<InputState, InputEvents> {\n /** Class-level scope tag used by the input router to bind keymaps. */\n static readonly type = \"input\"\n\n override readonly type = Input.type\n #focused = false\n #history: string[] = []\n #historyDraft = \"\"\n #historyIndex: number | undefined\n #preferredCol: number | undefined\n #staged: ((InputAttachment | Paste) & { id: number; marker: string })[] = []\n #formatCache: Map<string, FormatEntry> & { version?: number } = new Map<string, FormatEntry>()\n #formatGen = 0\n\n /**\n * Editing actions. Parameterless — they close over `this` — so both\n * the router (via keymap dispatch) and application code can invoke\n * them. Add to the keymap in `src/input/actions.ts` to give them\n * default key bindings.\n */\n override actions = {\n \"input.cursorDown\": (): void => {\n const v = this.state.value ?? \"\"\n const { col, line } = posToLineCol(v, this.#cursor())\n if (line >= countLines(v) - 1) {\n this.#historyNext()\n return\n }\n this.#preferredCol ??= col\n this.state.cursor = lineColToPos(v, line + 1, this.#preferredCol)\n },\n \"input.cursorLeft\": (): void => {\n const c = this.#cursor()\n this.#preferredCol = undefined\n this.state.cursor = c > 0 ? c - 1 : c\n },\n \"input.cursorLineEnd\": (): void => {\n const v = this.state.value ?? \"\"\n this.#preferredCol = undefined\n this.state.cursor = lineEndPos(v, this.#cursor())\n },\n \"input.cursorLineStart\": (): void => {\n const v = this.state.value ?? \"\"\n const { line } = posToLineCol(v, this.#cursor())\n this.#preferredCol = undefined\n this.state.cursor = lineColToPos(v, line, 0)\n },\n \"input.cursorRight\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n this.state.cursor = c < v.length ? c + 1 : c\n },\n \"input.cursorUp\": (): void => {\n const v = this.state.value ?? \"\"\n const { col, line } = posToLineCol(v, this.#cursor())\n if (line === 0) {\n this.#historyPrev()\n return\n }\n this.#preferredCol ??= col\n this.state.cursor = lineColToPos(v, line - 1, this.#preferredCol)\n },\n \"input.deleteCharBack\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n if (c === 0) return\n this.#historyEdit()\n const marker = this.#markerRange(c, \"back\")\n if (marker) return this.#deleteRange(marker.start, marker.end)\n this.state.set({ cursor: c - 1, value: v.slice(0, c - 1) + v.slice(c) })\n },\n \"input.deleteCharForward\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n if (c >= v.length) return\n this.#historyEdit()\n const marker = this.#markerRange(c, \"forward\")\n if (marker) return this.#deleteRange(marker.start, marker.end)\n this.state.value = v.slice(0, c) + v.slice(c + 1)\n },\n \"input.deleteWordBack\": (): void => {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n let i = c\n while (i > 0 && isWhitespace(v[i - 1])) i--\n while (i > 0 && !isWhitespace(v[i - 1])) i--\n if (i === c) return\n this.#historyEdit()\n this.state.set({ cursor: i, value: v.slice(0, i) + v.slice(c) })\n },\n \"input.insertNewline\": (): void => {\n // Smart indent: copy the leading whitespace of the current\n // logical line onto the new line so continuations stay aligned\n // with the bullet / quote / prefix the user typed.\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n let lineStart = c\n while (lineStart > 0 && v[lineStart - 1] !== \"\\n\") lineStart--\n let indent = \"\"\n for (let i = lineStart; i < c; i++) {\n const ch = v[i]\n if (ch === \" \" || ch === \"\\t\") indent += ch\n else break\n }\n const insert = `\\n${indent}`\n this.#historyEdit()\n this.state.set({\n cursor: c + insert.length,\n value: v.slice(0, c) + insert + v.slice(c),\n })\n },\n \"input.insertTab\": (): void => {\n // Two spaces rather than `\\t` — terminal tab stops are\n // unpredictable (often 8 cells) and play badly with our per-row\n // layout. Soft tabs are the safer default; users wanting real\n // tabs can override the action.\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#preferredCol = undefined\n const tab = \" \"\n this.#historyEdit()\n this.state.set({ cursor: c + tab.length, value: v.slice(0, c) + tab + v.slice(c) })\n },\n // `ctrl-v` queries the OS clipboard (via xclip / wl-paste / pbpaste /\n // PowerShell depending on platform). The richest content wins:\n //\n // - **image bytes** → one `attach` event with a temp PNG path.\n // - **file references** → one `attach` event per file.\n // - **plain text** → inserted at the cursor like a regular paste.\n //\n // Fire-and-forget async — we await the probe and commit the\n // result in a microtask.\n \"input.paste\": (): void => {\n void (async (): Promise<void> => {\n const content = await clipboard.read()\n if (!content) return\n\n // Route through the regular paste handler\n if (content.kind === \"text\") {\n void this.emit(\"paste\", {\n paste: {\n stop: () => void 0,\n stopped: false,\n text: content.text,\n },\n })\n return\n }\n\n const paths: string[] = content.kind === \"image\" ? [content.path] : content.paths\n const files = await Promise.all(paths.map((path) => fileDetect({ path })))\n for (let i = 0; i < paths.length; i++) {\n const path = paths[i]\n const file = files[i]\n if (!file) continue\n this.attach({ ...file, path })\n }\n })()\n },\n \"input.submit\": (): void => {\n const value = this.state.value ?? \"\"\n if (this.state.validate?.(value) === false) return\n const ret = this.consume()\n this.#historyAdd(ret.value)\n void this.emit(\"submit\", ret)\n },\n } satisfies NodeActionMap\n\n constructor(initial: InputState = {}) {\n const value = initial.value ?? \"\"\n super({ cursor: value.length, value, ...initial })\n this.#history = [...(initial.history ?? [])]\n this.on(\"key\", ({ key }) => {\n this.#handleKey(key)\n })\n this.on(\"paste\", ({ paste }) => {\n this.paste(paste.text)\n paste.stop()\n })\n this.on(\"focus\", () => {\n this.#focused = true\n this.invalidate()\n })\n this.on(\"blur\", () => {\n this.#focused = false\n this.invalidate()\n })\n\n this.on(\"mount\", () => {\n this.ctx?.input.events.on(\"terminal-focus\", () => this.invalidate(), {\n signal: this.mountSignal,\n })\n })\n }\n\n get history(): readonly string[] {\n return this.#history\n }\n\n set history(v: readonly string[]) {\n this.#history = [...v]\n this.#historyIndex = undefined\n }\n\n attach(att: InputAttachment | Paste): void {\n if (att.type !== \"paste\" && this.state.canAttach?.(att) === false) {\n // Caller doesn't want this attachment (e.g. model doesn't support it) — fall\n // back to pasting the path as plain text\n return this.insert(att.path)\n }\n\n const id = this.#staged.length + 1\n let prefix = att.type[0].toUpperCase() + att.type.slice(1)\n let suffix = \"\"\n if (att.type === \"paste\") {\n prefix = \"Pasted text\"\n suffix = ` +${countLines(att.text)} lines`\n } else if (![\"image\", \"pdf\"].includes(att.type)) suffix = ` ${basename(att.path)}`\n const marker = `[${prefix} #${id}${suffix}]`\n this.#staged.push({ ...att, id, marker })\n this.insert(marker)\n\n if (att.type !== \"paste\") void this.emit(\"attach\", { attachment: att })\n }\n\n paste(text: string): void {\n if (\n countLines(text) > (this.state.pasteMaxLines ?? PASTE_MAX_LINES) ||\n stringWidth(text) > (this.state.pasteMaxChars ?? PASTE_MAX_CHARS)\n )\n return this.attach({ text, type: \"paste\" })\n this.insert(text)\n }\n\n insert(text: string): void {\n const v = this.state.value ?? \"\"\n const c = this.#cursor()\n this.#historyEdit()\n this.#preferredCol = undefined\n this.state.set({\n cursor: c + text.length,\n value: v.slice(0, c) + text + v.slice(c),\n })\n }\n\n replace(text: string): void {\n this.state.value = \"\"\n this.insert(text)\n }\n\n /** Consume the input's current value and attachments.\n * Pastes are replaced inline with their text; file/image\n * attachments are returned in the `attachments` array and removed from the value. */\n consume(): InputValue {\n let value = this.state.value ?? \"\"\n const atts: InputAttachment[] = []\n for (const att of this.#staged) {\n if (!value.includes(att.marker)) continue\n if (att.type === \"paste\") {\n value = value.replace(att.marker, att.text)\n } else atts.push(att)\n }\n this.#staged = []\n this.#preferredCol = undefined\n this.state.set({ cursor: 0, value: \"\" })\n return { attachments: atts, value }\n }\n\n #cursor(): number {\n const v = this.state.value ?? \"\"\n return Math.max(0, Math.min(v.length, this.state.cursor ?? 0))\n }\n\n #deleteRange(start: number, end: number): void {\n const v = this.state.value ?? \"\"\n this.#historyEdit()\n this.#preferredCol = undefined\n this.state.set({ cursor: start, value: v.slice(0, start) + v.slice(end) })\n }\n\n historyAdd(value: string): void {\n this.#historyAdd(value)\n }\n\n #historyAdd(value: string): void {\n if (value.trim() === \"\") return\n if (this.#history.at(-1) !== value) {\n this.#history.push(value)\n void this.emit(\"history\", { added: value, history: [...this.#history] })\n }\n this.#historyDraft = \"\"\n this.#historyIndex = undefined\n }\n\n #historyEdit(): void {\n this.#historyDraft = \"\"\n this.#historyIndex = undefined\n }\n\n #historyNext(): void {\n if (this.#historyIndex === undefined) return\n const next = this.#historyIndex + 1\n if (next >= this.#history.length) {\n this.#historySet(this.#historyDraft)\n this.#historyDraft = \"\"\n this.#historyIndex = undefined\n return\n }\n this.#historyIndex = next\n this.#historySet(this.#history[next])\n }\n\n #historyPrev(): void {\n if (this.#history.length === 0) return\n if (this.#historyIndex === undefined) {\n this.#historyDraft = this.state.value ?? \"\"\n this.#historyIndex = this.#history.length - 1\n } else if (this.#historyIndex > 0) this.#historyIndex--\n this.#historySet(this.#history[this.#historyIndex])\n }\n\n #historySet(value: string): void {\n this.#preferredCol = undefined\n this.state.set({ cursor: value.length, value })\n }\n\n #markerRange(pos: number, dir: \"back\" | \"forward\"): { start: number; end: number } | undefined {\n const value = this.state.value ?? \"\"\n for (const att of this.#staged) {\n const start = value.indexOf(att.marker)\n if (start === -1) continue\n const end = start + att.marker.length\n if (dir === \"back\" && pos > start && pos <= end) return { end, start }\n if (dir === \"forward\" && pos >= start && pos < end) return { end, start }\n }\n }\n\n // Fallback path for anything the router couldn't resolve to a named\n // action: printable characters go straight into the value. Any other\n // unbound key (f7, unclaimed ctrl-combos, etc.) bubbles untouched.\n #handleKey(ev: RoutedKey): void {\n if (ev.text === undefined || ev.ctrl || ev.alt || ev.meta) return\n this.insert(ev.text)\n ev.stop()\n }\n\n #format(value: string, ctx: RenderCtx): string {\n const format = this.state.format\n if (!format) return value\n\n if (ctx.version !== this.#formatCache.version) {\n this.#formatCache.clear()\n this.#formatCache.version = ctx.version\n }\n\n const key = hash(value)\n const cached = this.#formatCache.get(key)\n if (cached?.result !== undefined) return cached.result\n const streaming = this.#streamingFormat(value)\n if (cached?.promise) return streaming ?? value\n\n const ret = format(value, { style: ctx.style })\n if (!isPromiseLike(ret)) return ret\n\n const gen = ++this.#formatGen\n const entry: FormatEntry = { input: value }\n entry.promise = ret.then(\n (result) => {\n if (this.#formatCache.get(key) !== entry) return\n entry.result = result\n entry.promise = undefined\n if (this.#formatGen === gen && result !== value) untrack(() => this.invalidate())\n },\n () => {\n if (this.#formatCache.get(key) === entry) this.#formatCache.delete(key)\n }\n )\n this.#formatCache.set(key, entry)\n while (this.#formatCache.size > 100)\n this.#formatCache.delete(this.#formatCache.keys().next().value!)\n return streaming ?? value\n }\n\n /** Reuse a highlighted prefix while async formatting catches up. */\n #streamingFormat(value: string): string | undefined {\n let ret: [string, FormatEntry] | undefined\n for (const [key, cached] of this.#formatCache) {\n if (cached.result === undefined) continue\n if (value.startsWith(cached.input) && cached.input.length > (ret?.[1].input.length ?? 0))\n ret = [key, cached]\n }\n if (ret === undefined) return\n this.#formatCache.delete(ret[0])\n this.#formatCache.set(ret[0], ret[1]) // bump to end of LRU\n return ret[1].result + value.slice(ret[1].input.length)\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n const value = this.state.value ?? \"\"\n const placeholder = this.state.placeholder ?? \"\"\n const cursor = this.#cursor()\n const focused = this.#focused\n\n // Build the styled content string. Layout (word-wrap, split into\n // rows, pad to width) is delegated to `Text` below — wrap-ansi knows\n // how to close+reopen SGR across line breaks, so the inverse-cursor\n // span survives wrapping.\n let content: string\n if (value === \"\") {\n const ph = unwrap(placeholder)\n content = ph ? ` ${ctx.style.quiet(ph)}` : \"\"\n } else {\n content = value\n for (const att of this.#staged) {\n if (!content.includes(att.marker)) continue\n content = content.replace(att.marker, ctx.style.accent(att.marker))\n }\n content = this.#format(content, ctx)\n }\n\n // Fake cursor. `cursor` is an absolute index in the raw value, while\n // rendering is line-oriented: newlines consume string indices but not\n // cells in any rendered row. Project the cursor to line/column before\n // slicing the formatted line.\n if (focused && this.ctx?.input.terminalFocus) {\n const { col, line } = posToLineCol(value, cursor)\n const lines = splitAnsi(content)\n const target = Math.max(0, Math.min(line, lines.length - 1))\n const row = lines[target] ?? \"\"\n const head = sliceAnsi(row, 0, col)\n const at = sliceAnsi(row, col, col + 1) || \" \"\n const tail = sliceAnsi(row, col + 1)\n lines[target] = head + ctx.style.inverse(at) + tail\n content = lines.join(\"\\n\")\n }\n\n return formatText(content, {\n style: ctx.style.add(this.state),\n width: ctx.width,\n wrap: \"word\",\n })\n }\n}\n\n/**\n * Factory for `Input`. All fields optional; default is an empty,\n * focusable input that fills `ctx.width` and has no placeholder.\n *\n * ```ts\n * input({ placeholder: \"type a message…\" })\n * const i = input({ value: \"draft\" })\n * i.on(\"submit\", (text) => console.log(\"user typed\", text))\n * ```\n */\nexport function input(state: InputState = {}): Input {\n return new Input(state)\n}\n\n// ---------- helpers ----------\n\nfunction isWhitespace(ch: string | undefined): boolean {\n return ch !== undefined && (ch === \" \" || ch === \"\\t\" || ch === \"\\n\")\n}\n\nfunction posToLineCol(value: string, cursor: number): { line: number; col: number } {\n const prefix = value.slice(0, cursor)\n const lineStart = prefix.lastIndexOf(\"\\n\") + 1\n return {\n col: stringWidth(prefix.slice(lineStart)),\n line: prefix.split(\"\\n\").length - 1,\n }\n}\n\nfunction lineColToPos(value: string, line: number, col: number): number {\n const lines = value.split(\"\\n\")\n const clampLine = Math.max(0, Math.min(line, lines.length - 1))\n let abs = 0\n for (let i = 0; i < clampLine; i++) abs += lines[i].length + 1\n\n let cells = 0\n let offset = 0\n for (const { segment } of graphemes.segment(lines[clampLine])) {\n const width = stringWidth(segment)\n if (cells + width > col) break\n cells += width\n offset += segment.length\n }\n return abs + offset\n}\n\nfunction lineEndPos(value: string, cursor: number): number {\n let i = cursor\n while (i < value.length && value[i] !== \"\\n\") i++\n return i\n}\n\nfunction countLines(value: string): number {\n let n = 1\n for (const ch of value) if (ch === \"\\n\") n++\n return n\n}\n"],"mappings":"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"}
|