@zaly/tui 0.0.5 → 0.0.7
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/theme.schema.json +272 -270
- package/assets/themes/kanagawa-dragon.json +3 -0
- package/assets/themes/kanagawa-wave.json +3 -0
- package/dist/{actions-CnVzKVID.d.mts → actions-DFboj3g5.d.mts} +4 -4
- package/dist/{actions-CnVzKVID.d.mts.map → actions-DFboj3g5.d.mts.map} +1 -1
- package/dist/ansi.d.mts +10 -11
- package/dist/ansi.d.mts.map +1 -1
- package/dist/{autocomplete-Dfw-yQDa.d.mts → autocomplete-CxzetPOo.d.mts} +4 -4
- package/dist/{autocomplete-Dfw-yQDa.d.mts.map → autocomplete-CxzetPOo.d.mts.map} +1 -1
- package/dist/{box-DepqUtuo.mjs → box-DLEcEvDH.mjs} +18 -11
- package/dist/box-DLEcEvDH.mjs.map +1 -0
- package/dist/{builder-T9oGIWFa.mjs → builder-BgEcjj8Z.mjs} +5 -4
- package/dist/builder-BgEcjj8Z.mjs.map +1 -0
- package/dist/{callbacks-DcMBGQEO.mjs → callbacks-D132G8dy.mjs} +7 -6
- package/dist/callbacks-D132G8dy.mjs.map +1 -0
- package/dist/client-BltmwI6G.mjs +2 -0
- package/dist/{client-BBdtbLp4.mjs → client-xnCHMO2_.mjs} +62 -8
- package/dist/client-xnCHMO2_.mjs.map +1 -0
- package/dist/{clipboard-l_TWxxTf.mjs → clipboard-CNPBTX7j.mjs} +9 -7
- package/dist/{clipboard-l_TWxxTf.mjs.map → clipboard-CNPBTX7j.mjs.map} +1 -1
- package/dist/clipboard.d.mts +6 -7
- package/dist/clipboard.d.mts.map +1 -1
- package/dist/clipboard.mjs +1 -1
- package/dist/{ctx-Ctmvof1N.mjs → ctx-ChO3St_a.mjs} +3 -3
- package/dist/{ctx-Ctmvof1N.mjs.map → ctx-ChO3St_a.mjs.map} +1 -1
- package/dist/ctx-DZHBHjsB.mjs +2 -0
- package/dist/{divider-cclEAdPx.mjs → divider-l0-JPEIm.mjs} +2 -2
- package/dist/{divider-cclEAdPx.mjs.map → divider-l0-JPEIm.mjs.map} +1 -1
- package/dist/{files-Aw3iWpXD.d.mts → files-BUsa-RVl.d.mts} +3 -3
- package/dist/{files-Aw3iWpXD.d.mts.map → files-BUsa-RVl.d.mts.map} +1 -1
- package/dist/{github-DS00VoOj.d.mts → github-D89A3F9U.d.mts} +3 -3
- package/dist/{github-DS00VoOj.d.mts.map → github-D89A3F9U.d.mts.map} +1 -1
- package/dist/{image-BTxDPPiT.d.mts → image-34bU73bW.d.mts} +2 -2
- package/dist/{image-BTxDPPiT.d.mts.map → image-34bU73bW.d.mts.map} +1 -1
- package/dist/image.d.mts +14 -15
- package/dist/image.d.mts.map +1 -1
- package/dist/index.d.mts +13 -13
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/{input-CRBuTrsL.mjs → input-D7fQEUdt.mjs} +3 -3
- package/dist/input-D7fQEUdt.mjs.map +1 -0
- package/dist/{input-B5Vy-iaa.d.mts → input-Dylds_sI.d.mts} +3 -3
- package/dist/input-Dylds_sI.d.mts.map +1 -0
- package/dist/{inspect-D6FW_QUo.d.mts → inspect-DPLRum7L.d.mts} +2 -2
- package/dist/{inspect-D6FW_QUo.d.mts.map → inspect-DPLRum7L.d.mts.map} +1 -1
- package/dist/{inspect-BaKG6cU_.mjs → inspect-xdSq5Hjq.mjs} +3 -3
- package/dist/{inspect-BaKG6cU_.mjs.map → inspect-xdSq5Hjq.mjs.map} +1 -1
- package/dist/kitty-JbCJC0iQ.mjs.map +1 -1
- package/dist/{log-DYHEYX_z.mjs → log-DrYLRdMW.mjs} +4 -4
- package/dist/{log-DYHEYX_z.mjs.map → log-DrYLRdMW.mjs.map} +1 -1
- package/dist/{logger-Ch0LwSG_.mjs → logger-ClSgGf-a.mjs} +3 -3
- package/dist/logger-ClSgGf-a.mjs.map +1 -0
- package/dist/{markdown-CYHHoYu0.mjs → markdown-lRhc_4Cd.mjs} +7 -7
- package/dist/markdown-lRhc_4Cd.mjs.map +1 -0
- package/dist/markdown.d.mts +5 -5
- package/dist/markdown.d.mts.map +1 -1
- package/dist/markdown.mjs +1 -1
- package/dist/md.bun.d.mts +1 -2
- package/dist/md.bun.d.mts.map +1 -1
- package/dist/md.node.d.mts +1 -2
- package/dist/md.node.d.mts.map +1 -1
- package/dist/node-BZ7f6HzU.mjs.map +1 -1
- package/dist/{overlay-9xNgsuuy.mjs → overlay-9WXYiGgW.mjs} +2 -2
- package/dist/{overlay-9xNgsuuy.mjs.map → overlay-9WXYiGgW.mjs.map} +1 -1
- package/dist/{picker-cH-rc7-X.mjs → picker-BqHINl_a.mjs} +4 -4
- package/dist/picker-BqHINl_a.mjs.map +1 -0
- package/dist/{picker-D8OLb6kZ.d.mts → picker-JL8lZfRH.d.mts} +5 -5
- package/dist/{picker-D8OLb6kZ.d.mts.map → picker-JL8lZfRH.d.mts.map} +1 -1
- package/dist/queries-B_lOwEiE.mjs.map +1 -1
- package/dist/{queries-DH3bj74K.d.mts → queries-Cvalgu6P.d.mts} +3 -3
- package/dist/{queries-DH3bj74K.d.mts.map → queries-Cvalgu6P.d.mts.map} +1 -1
- package/dist/reactive-f7NpAi69.mjs.map +1 -1
- package/dist/{registry-CdeLjUo2.mjs → registry-CEpHcTa2.mjs} +2 -2
- package/dist/registry-CEpHcTa2.mjs.map +1 -0
- package/dist/{render-CPUD4yaW.mjs → render-DxIHVH9Y.mjs} +2 -2
- package/dist/{render-CPUD4yaW.mjs.map → render-DxIHVH9Y.mjs.map} +1 -1
- package/dist/{renderer-DJ1pWXSL.mjs → renderer-Bz3tc2IT.mjs} +7 -7
- package/dist/renderer-Bz3tc2IT.mjs.map +1 -0
- package/dist/renderer-CuF4RYBZ.mjs +2 -0
- package/dist/{renderer-qSMVeNSV.mjs → renderer-DesbRwjQ.mjs} +2 -2
- package/dist/renderer-DesbRwjQ.mjs.map +1 -0
- package/dist/select-m7NE6Rwa.mjs.map +1 -1
- package/dist/{select-CbmAZdpt.d.mts → select-zGd5pbiB.d.mts} +3 -3
- package/dist/{select-CbmAZdpt.d.mts.map → select-zGd5pbiB.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 +3 -4
- package/dist/services/notifier.d.mts.map +1 -1
- package/dist/services/notifier.mjs +2 -2
- package/dist/services/notifier.mjs.map +1 -1
- package/dist/services/picker.d.mts +8 -9
- package/dist/services/picker.d.mts.map +1 -1
- package/dist/services/picker.mjs +10 -8
- package/dist/services/picker.mjs.map +1 -1
- package/dist/services/prompt.d.mts +8 -9
- package/dist/services/prompt.d.mts.map +1 -1
- package/dist/services/prompt.mjs +9 -7
- package/dist/services/prompt.mjs.map +1 -1
- package/dist/shiki/server.d.mts +1 -1
- package/dist/shiki/server.mjs +6 -2
- package/dist/shiki/server.mjs.map +1 -1
- package/dist/{shiki-BK-v9CtF.mjs → shiki-CcxiFWEF.mjs} +3 -3
- package/dist/{shiki-BK-v9CtF.mjs.map → shiki-CcxiFWEF.mjs.map} +1 -1
- package/dist/{shiki-B5NwIiot.mjs → shiki-D7l5--zz.mjs} +19 -5
- package/dist/shiki-D7l5--zz.mjs.map +1 -0
- package/dist/show-DR2x1YFc.mjs.map +1 -1
- package/dist/style.d.mts +7 -7
- package/dist/style.d.mts.map +1 -1
- package/dist/style.mjs +2 -2
- package/dist/{text-DILrol9j.mjs → text-BLz1tRoC.mjs} +4 -3
- package/dist/{text-DILrol9j.mjs.map → text-BLz1tRoC.mjs.map} +1 -1
- package/dist/{text-9lwQeqYr.d.mts → text-BefiXAFW.d.mts} +3 -3
- package/dist/{text-9lwQeqYr.d.mts.map → text-BefiXAFW.d.mts.map} +1 -1
- package/dist/{text-q26V6_Sc.mjs → text-CRZD9KTN.mjs} +3 -2
- package/dist/{text-q26V6_Sc.mjs.map → text-CRZD9KTN.mjs.map} +1 -1
- package/dist/text.d.mts +1 -1
- package/dist/text.mjs +1 -1
- package/dist/{theme.config-CU3B50HN.mjs → theme.config-DoW6LIcl.mjs} +250 -242
- package/dist/theme.config-DoW6LIcl.mjs.map +1 -0
- package/dist/themes.d.mts +8 -9
- package/dist/themes.d.mts.map +1 -1
- package/dist/themes.mjs +1 -1
- package/dist/tree-Bo1afYhe.mjs.map +1 -1
- package/dist/{tree-C28QOVIK.d.mts → tree-CArtDRec.d.mts} +3 -3
- package/dist/{tree-C28QOVIK.d.mts.map → tree-CArtDRec.d.mts.map} +1 -1
- package/dist/{types-B9Eh7k2v.d.mts → types-C0EOLZDc.d.mts} +7 -2
- package/dist/types-C0EOLZDc.d.mts.map +1 -0
- package/dist/{widget-M7jD8Rgg.d.mts → widget-DtJU2-BJ.d.mts} +2 -2
- package/dist/{widget-M7jD8Rgg.d.mts.map → widget-DtJU2-BJ.d.mts.map} +1 -1
- package/dist/widgets/autocomplete.d.mts +1 -1
- package/dist/widgets/autocomplete.mjs +2 -2
- package/dist/widgets/autocomplete.mjs.map +1 -1
- package/dist/widgets/box.d.mts +1 -1
- package/dist/widgets/box.mjs +1 -1
- package/dist/widgets/code.d.mts +4 -5
- package/dist/widgets/code.d.mts.map +1 -1
- package/dist/widgets/code.mjs +5 -5
- 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 +5 -6
- package/dist/widgets/diff.d.mts.map +1 -1
- package/dist/widgets/diff.mjs +3 -3
- package/dist/widgets/diff.mjs.map +1 -1
- package/dist/widgets/divider.d.mts +4 -5
- package/dist/widgets/divider.d.mts.map +1 -1
- package/dist/widgets/divider.mjs +1 -1
- package/dist/widgets/image.d.mts +1 -1
- package/dist/widgets/image.mjs +1 -1
- 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 +8 -9
- 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 +5 -6
- package/dist/widgets/progress.d.mts.map +1 -1
- package/dist/widgets/select.d.mts +1 -1
- package/dist/widgets/show.d.mts +7 -7
- package/dist/widgets/show.d.mts.map +1 -1
- package/dist/widgets/spinner.d.mts +7 -8
- package/dist/widgets/spinner.d.mts.map +1 -1
- package/dist/widgets/spinner.mjs.map +1 -1
- 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/dist/worker-T6SdPzUH.mjs.map +1 -1
- package/package.json +9 -10
- package/dist/box-DepqUtuo.mjs.map +0 -1
- package/dist/builder-T9oGIWFa.mjs.map +0 -1
- package/dist/callbacks-DcMBGQEO.mjs.map +0 -1
- package/dist/client-BBdtbLp4.mjs.map +0 -1
- package/dist/client-cIckDgAj.mjs +0 -2
- package/dist/ctx-DhJIKuOX.mjs +0 -2
- package/dist/input-B5Vy-iaa.d.mts.map +0 -1
- package/dist/input-CRBuTrsL.mjs.map +0 -1
- package/dist/logger-Ch0LwSG_.mjs.map +0 -1
- package/dist/markdown-CYHHoYu0.mjs.map +0 -1
- package/dist/picker-cH-rc7-X.mjs.map +0 -1
- package/dist/registry-CdeLjUo2.mjs.map +0 -1
- package/dist/renderer-DJ1pWXSL.mjs.map +0 -1
- package/dist/renderer-Dgj_qEOA.mjs +0 -2
- package/dist/renderer-qSMVeNSV.mjs.map +0 -1
- package/dist/shiki-B5NwIiot.mjs.map +0 -1
- package/dist/theme.config-CU3B50HN.mjs.map +0 -1
- package/dist/types-B9Eh7k2v.d.mts.map +0 -1
package/dist/widgets/divider.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as divider } from "../divider-
|
|
1
|
+
import { t as divider } from "../divider-l0-JPEIm.mjs";
|
|
2
2
|
export { divider };
|
package/dist/widgets/image.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as ImageState, r as image, t as Image } from "../image-
|
|
1
|
+
import { n as ImageState, r as image, t as Image } from "../image-34bU73bW.mjs";
|
|
2
2
|
export { Image, ImageState, image };
|
package/dist/widgets/image.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as unwrap, w as useContext } from "../reactive-f7NpAi69.mjs";
|
|
2
2
|
import { t as Node } from "../node-BZ7f6HzU.mjs";
|
|
3
|
-
import { t as RenderContext } from "../render-
|
|
3
|
+
import { t as RenderContext } from "../render-DxIHVH9Y.mjs";
|
|
4
4
|
import { s as loadKittyGraphics } from "../kitty-JbCJC0iQ.mjs";
|
|
5
5
|
import { fileDetect } from "@zaly/shared/detect";
|
|
6
6
|
import { imageInfo } from "@zaly/shared/image";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.mjs","names":[
|
|
1
|
+
{"version":3,"file":"image.mjs","names":[],"sources":["../../src/widgets/image.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Accessor } from \"../core/reactive.ts\"\nimport type { Layout } from \"../core/state.ts\"\n\nimport { fileDetect } from \"@zaly/shared/detect\"\nimport { imageInfo } from \"@zaly/shared/image\"\nimport { Node } from \"../core/node.ts\"\nimport { unwrap, useContext } from \"../core/reactive.ts\"\nimport { RenderContext } from \"../core/render.ts\"\nimport { loadKittyGraphics } from \"../image/kitty.ts\"\n\nexport interface ImageState {\n /**\n * Path to an image file. PNG passes through with zero decoding; other\n * formats (JPEG/WebP/GIF/AVIF/SVG) are read via image-meta for\n * dimensions and — for KGP terminals — converted once to a cached\n * temp PNG via sharp. iTerm2 accepts all formats natively.\n */\n src: string\n /** Display width in terminal cells. Defaults to `ctx.width`. */\n width?: number\n /**\n * Display height in terminal cells. When omitted, computed from the\n * source aspect ratio + `cellAspect`.\n */\n height?: number\n /** Fallback text shown on terminals without an image protocol. */\n alt?: string\n /**\n * Character cell aspect ratio (cellHeight / cellWidth). Most terminals\n * land around 2.0. Tweak if aspect-preserved images look stretched.\n */\n cellAspect?: number\n}\n\nexport class Image extends Node<ImageState> {\n #delete?: () => void\n #enabled?: Accessor<boolean>\n\n constructor(state: ImageState) {\n super(state)\n this.on(\"unmount\", () => this.#delete?.())\n const context = useContext(RenderContext)\n this.#enabled = context?.images\n }\n\n get fallback(): string[] {\n return [this.state.alt ?? `[Image: ${this.state.src}]`]\n }\n\n override layout(): Layout {\n return { minWidth: 50, width: 100 }\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n if (unwrap(this.#enabled) === false) return this.fallback\n\n const queries = this.ctx?.input.queries\n const kitty = queries ? await loadKittyGraphics(queries) : undefined\n if (!kitty?.supported) return this.fallback\n\n const detected = await fileDetect(this.state.src)\n if (detected?.type !== \"image\") return this.fallback\n const img = await imageInfo(detected)\n\n const { cols, rows } = dims(this.state, img, Math.min(ctx.width, 80))\n\n const t = await kitty.transmitOnce(img)\n if (!t) return this.fallback\n const p = kitty.placement(t.imageId, { cols, rows })\n if (!p) return this.fallback\n this.#delete = () =>\n p.placementId ? kitty.deletePlacement(t.imageId, p.placementId) : undefined\n // Route the transmit bytes through the side-channel queue (mount\n // ctx → terminal). Cached rows then hold pure placement ANSI,\n // which is safe to reuse across repaints. If we're rendering\n // before mount (rare — tests, headless previews), fall back to\n // inlining the transmit into the lead so the picture still\n // shows correctly the first time.\n if (t.transmit) {\n ctx.transmit(t.transmit)\n if (p.inline) ctx.transmit(p.seq)\n }\n\n if (p.inline) return p.data\n\n const ret = [...p.data]\n if (!ret.length) return this.fallback\n ret[0] = p.seq + ret[0]\n return ret\n }\n}\n\nexport function image(src: string, style?: Omit<ImageState, \"src\">): Image\nexport function image(state: ImageState): Image\nexport function image(first: string | ImageState, style?: Omit<ImageState, \"src\">): Image {\n if (typeof first === \"string\") return new Image({ src: first, ...style })\n return new Image(first)\n}\n\nfunction dims(\n state: ImageState,\n meta: { width: number; height: number },\n available: number\n): { cols: number; rows: number } {\n const cellAspect = state.cellAspect ?? 2\n const aspect = meta.height / meta.width\n let cols = state.width\n let rows = state.height\n if (cols === undefined && rows === undefined) cols = Math.max(1, available)\n if (cols !== undefined && rows === undefined) {\n rows = Math.max(1, Math.round((cols * aspect) / cellAspect))\n } else if (rows !== undefined && cols === undefined) {\n cols = Math.max(1, Math.round((rows * cellAspect) / aspect))\n }\n return { cols: cols ?? available, rows: rows ?? 1 }\n}\n"],"mappings":";;;;;;;AAmCA,IAAa,QAAb,cAA2B,KAAiB;CAC1C;CACA;CAEA,YAAY,OAAmB;EAC7B,MAAM,KAAK;EACX,KAAK,GAAG,iBAAiB,KAAK,UAAU,CAAC;EACzC,MAAM,UAAU,WAAW,aAAa;EACxC,KAAK,WAAW,SAAS;CAC3B;CAEA,IAAI,WAAqB;EACvB,OAAO,CAAC,KAAK,MAAM,OAAO,WAAW,KAAK,MAAM,IAAI,EAAE;CACxD;CAEA,SAA0B;EACxB,OAAO;GAAE,UAAU;GAAI,OAAO;EAAI;CACpC;CAEA,MAAgB,QAAQ,KAAmC;EACzD,IAAI,OAAO,KAAK,QAAQ,MAAM,OAAO,OAAO,KAAK;EAEjD,MAAM,UAAU,KAAK,KAAK,MAAM;EAChC,MAAM,QAAQ,UAAU,MAAM,kBAAkB,OAAO,IAAI,KAAA;EAC3D,IAAI,CAAC,OAAO,WAAW,OAAO,KAAK;EAEnC,MAAM,WAAW,MAAM,WAAW,KAAK,MAAM,GAAG;EAChD,IAAI,UAAU,SAAS,SAAS,OAAO,KAAK;EAC5C,MAAM,MAAM,MAAM,UAAU,QAAQ;EAEpC,MAAM,EAAE,MAAM,SAAS,KAAK,KAAK,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,EAAE,CAAC;EAEpE,MAAM,IAAI,MAAM,MAAM,aAAa,GAAG;EACtC,IAAI,CAAC,GAAG,OAAO,KAAK;EACpB,MAAM,IAAI,MAAM,UAAU,EAAE,SAAS;GAAE;GAAM;EAAK,CAAC;EACnD,IAAI,CAAC,GAAG,OAAO,KAAK;EACpB,KAAK,gBACH,EAAE,cAAc,MAAM,gBAAgB,EAAE,SAAS,EAAE,WAAW,IAAI,KAAA;EAOpE,IAAI,EAAE,UAAU;GACd,IAAI,SAAS,EAAE,QAAQ;GACvB,IAAI,EAAE,QAAQ,IAAI,SAAS,EAAE,GAAG;EAClC;EAEA,IAAI,EAAE,QAAQ,OAAO,EAAE;EAEvB,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI;EACtB,IAAI,CAAC,IAAI,QAAQ,OAAO,KAAK;EAC7B,IAAI,KAAK,EAAE,MAAM,IAAI;EACrB,OAAO;CACT;AACF;AAIA,SAAgB,MAAM,OAA4B,OAAwC;CACxF,IAAI,OAAO,UAAU,UAAU,OAAO,IAAI,MAAM;EAAE,KAAK;EAAO,GAAG;CAAM,CAAC;CACxE,OAAO,IAAI,MAAM,KAAK;AACxB;AAEA,SAAS,KACP,OACA,MACA,WACgC;CAChC,MAAM,aAAa,MAAM,cAAc;CACvC,MAAM,SAAS,KAAK,SAAS,KAAK;CAClC,IAAI,OAAO,MAAM;CACjB,IAAI,OAAO,MAAM;CACjB,IAAI,SAAS,KAAA,KAAa,SAAS,KAAA,GAAW,OAAO,KAAK,IAAI,GAAG,SAAS;CAC1E,IAAI,SAAS,KAAA,KAAa,SAAS,KAAA,GACjC,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,OAAO,SAAU,UAAU,CAAC;MACtD,IAAI,SAAS,KAAA,KAAa,SAAS,KAAA,GACxC,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,OAAO,aAAc,MAAM,CAAC;CAE7D,OAAO;EAAE,MAAM,QAAQ;EAAW,MAAM,QAAQ;CAAE;AACpD"}
|
package/dist/widgets/input.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as InputValue, i as InputState, n as InputAttachment, o as input, r as InputEvents, t as Input } from "../input-
|
|
1
|
+
import { a as InputValue, i as InputState, n as InputAttachment, o as input, r as InputEvents, t as Input } from "../input-Dylds_sI.mjs";
|
|
2
2
|
export { Input, InputAttachment, InputEvents, InputState, InputValue, input };
|
package/dist/widgets/input.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as input, t as Input } from "../input-
|
|
1
|
+
import { n as input, t as Input } from "../input-D7fQEUdt.mjs";
|
|
2
2
|
export { Input, input };
|
package/dist/widgets/log.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as LogState, M as log, j as LogStyle } from "../queries-
|
|
1
|
+
import { A as LogState, M as log, j as LogStyle } from "../queries-Cvalgu6P.mjs";
|
|
2
2
|
export { LogState, LogStyle, log };
|
package/dist/widgets/log.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as log } from "../log-
|
|
1
|
+
import { t as log } from "../log-DrYLRdMW.mjs";
|
|
2
2
|
export { log };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { J as Layout, P as RenderCtx, U as TextContent, X as State, p as Node } from "../queries-
|
|
2
|
-
import { o as AnyStyle } from "../types-
|
|
3
|
-
import { t as WrapMode } from "../text-
|
|
1
|
+
import { J as Layout, P as RenderCtx, U as TextContent, X as State, p as Node } from "../queries-Cvalgu6P.mjs";
|
|
2
|
+
import { o as AnyStyle } from "../types-C0EOLZDc.mjs";
|
|
3
|
+
import { t as WrapMode } from "../text-BefiXAFW.mjs";
|
|
4
4
|
import { n as MdOptions } from "../types-D3jk1rtk.mjs";
|
|
5
|
-
import { t as Image } from "../image-
|
|
5
|
+
import { t as Image } from "../image-34bU73bW.mjs";
|
|
6
6
|
//#region src/widgets/markdown.d.ts
|
|
7
|
-
interface MarkdownState {
|
|
7
|
+
export interface MarkdownState {
|
|
8
8
|
/** Markdown source. Accepts a plain string or a reactive accessor —
|
|
9
9
|
* pass `signal()` / `memo()` for streaming content that re-parses on
|
|
10
10
|
* each render and subscribes the node to the signal. */
|
|
@@ -21,7 +21,7 @@ interface MarkdownState {
|
|
|
21
21
|
wrap?: WrapMode;
|
|
22
22
|
style?: AnyStyle;
|
|
23
23
|
}
|
|
24
|
-
declare class Markdown extends Node<MarkdownState> {
|
|
24
|
+
export declare class Markdown extends Node<MarkdownState> {
|
|
25
25
|
#private;
|
|
26
26
|
readonly images: Map<string, Image>;
|
|
27
27
|
constructor(state: State<MarkdownState>);
|
|
@@ -38,8 +38,7 @@ declare class Markdown extends Node<MarkdownState> {
|
|
|
38
38
|
* markdown({ content, wrap: "word", fg: "fg" })
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
|
-
declare function markdown(content: TextContent, style?: Omit<State<MarkdownState>, "content">): Markdown;
|
|
42
|
-
declare function markdown(state: State<MarkdownState>): Markdown;
|
|
41
|
+
export declare function markdown(content: TextContent, style?: Omit<State<MarkdownState>, "content">): Markdown;
|
|
42
|
+
export declare function markdown(state: State<MarkdownState>): Markdown;
|
|
43
43
|
//#endregion
|
|
44
|
-
export { Markdown, MarkdownState, markdown };
|
|
45
44
|
//# sourceMappingURL=markdown.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.mts","names":[],"sources":["../../src/widgets/markdown.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"markdown.d.mts","names":[],"sources":["../../src/widgets/markdown.ts"],"mappings":";;;;;;iBAoBiB;;;;EAIf,SAAS;;EAET,UAAU;;;;;;;EAOV;EACA,OAAO;EACP,QAAQ;;qBAcG,iBAAiB,KAAK;;WAKxB,QAAM,YAAA;EASf,YAAY,OAAO,MAAM;YAwDT,QAAQ,KAAK,YAAY;EA0C1B,OAAO,KAAK,YAAS,QAAT;;;;;;;;;;;;wBAeb,SACd,SAAS,aACT,QAAQ,KAAK,MAAM,6BAClB;wBACa,SAAS,OAAO,MAAM,iBAAiB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as markdown, t as Markdown } from "../markdown-
|
|
1
|
+
import { n as markdown, t as Markdown } from "../markdown-lRhc_4Cd.mjs";
|
|
2
2
|
export { Markdown, markdown };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { F as Overlay, I as OverlayState, L as overlay } from "../queries-
|
|
1
|
+
import { F as Overlay, I as OverlayState, L as overlay } from "../queries-Cvalgu6P.mjs";
|
|
2
2
|
export { Overlay, OverlayState, overlay };
|
package/dist/widgets/overlay.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as overlay } from "../overlay-
|
|
1
|
+
import { t as overlay } from "../overlay-9WXYiGgW.mjs";
|
|
2
2
|
export { overlay };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as picker, i as PickerTreeProps, n as PickerItem, r as PickerSelectProps, t as PickerActions } from "../picker-
|
|
1
|
+
import { a as picker, i as PickerTreeProps, n as PickerItem, r as PickerSelectProps, t as PickerActions } from "../picker-JL8lZfRH.mjs";
|
|
2
2
|
export { PickerActions, PickerItem, PickerSelectProps, PickerTreeProps, picker };
|
package/dist/widgets/picker.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as picker } from "../picker-
|
|
1
|
+
import { t as picker } from "../picker-BqHINl_a.mjs";
|
|
2
2
|
export { picker };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Nt as Size, P as RenderCtx, X as State, nt as Reactive, p as Node } from "../queries-
|
|
2
|
-
import { c as Color } from "../types-
|
|
1
|
+
import { Nt as Size, P as RenderCtx, X as State, nt as Reactive, p as Node } from "../queries-Cvalgu6P.mjs";
|
|
2
|
+
import { c as Color } from "../types-C0EOLZDc.mjs";
|
|
3
3
|
//#region src/widgets/progress.d.ts
|
|
4
|
-
interface ProgressState {
|
|
4
|
+
export interface ProgressState {
|
|
5
5
|
/** Current value. Clamped to `[0, total]`. Accepts a signal accessor
|
|
6
6
|
* so callers can drive the bar from reactive state without manual
|
|
7
7
|
* `state.set` plumbing. */
|
|
@@ -28,7 +28,7 @@ interface ProgressState {
|
|
|
28
28
|
/** Empty glyph. Defaults to `░`. */
|
|
29
29
|
incomplete?: string;
|
|
30
30
|
}
|
|
31
|
-
declare class Progress extends Node<ProgressState> {
|
|
31
|
+
export declare class Progress extends Node<ProgressState> {
|
|
32
32
|
protected _render(ctx: RenderCtx): string[];
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
@@ -42,7 +42,6 @@ declare class Progress extends Node<ProgressState> {
|
|
|
42
42
|
* progress({ value: 0.7, label: (ctx, f) => ctx.style.dim(`${f*100|0}%`) })
|
|
43
43
|
* ```
|
|
44
44
|
*/
|
|
45
|
-
declare function progress(state: State<ProgressState>): Progress;
|
|
45
|
+
export declare function progress(state: State<ProgressState>): Progress;
|
|
46
46
|
//#endregion
|
|
47
|
-
export { Progress, ProgressState, progress };
|
|
48
47
|
//# sourceMappingURL=progress.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress.d.mts","names":[],"sources":["../../src/widgets/progress.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"progress.d.mts","names":[],"sources":["../../src/widgets/progress.ts"],"mappings":";;;iBAWiB;;;;EAIf,OAAO;;EAEP,QAAQ;;;;;EAKR,QAAQ;;;;;;EAMR,mBAAmB,KAAK,WAAW;;EAEnC,QAAQ;;EAER,aAAa;;EAEb;;EAEA;;qBAGW,iBAAiB,KAAK;YACvB,QAAQ,KAAK;;;;;;;;;;;;;wBAwCT,SAAS,OAAO,MAAM,iBAAiB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SelectEvents, i as Select, n as OptionRender, o as SelectState, r as OptionRenderCtx, s as select, t as Option } from "../select-
|
|
1
|
+
import { a as SelectEvents, i as Select, n as OptionRender, o as SelectState, r as OptionRenderCtx, s as select, t as Option } from "../select-zGd5pbiB.mjs";
|
|
2
2
|
export { Option, OptionRender, OptionRenderCtx, Select, SelectEvents, SelectState, select };
|
package/dist/widgets/show.d.mts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { P as RenderCtx, nt as Reactive, p as Node } from "../queries-
|
|
1
|
+
import { P as RenderCtx, nt as Reactive, p as Node } from "../queries-Cvalgu6P.mjs";
|
|
2
2
|
//#region src/widgets/show.d.ts
|
|
3
|
-
type ShowGate = {
|
|
3
|
+
export type ShowGate = {
|
|
4
4
|
when: Reactive<unknown>;
|
|
5
5
|
};
|
|
6
|
-
type ShowBranch = {
|
|
6
|
+
export type ShowBranch = {
|
|
7
7
|
when: Reactive<unknown>;
|
|
8
8
|
use: ShowChildren;
|
|
9
9
|
};
|
|
10
|
-
type ShowChildren = () => Node | Node[];
|
|
11
|
-
type ShowSpec = (ShowGate | ShowBranch)[] | [...(ShowGate | ShowBranch)[], ShowChildren];
|
|
10
|
+
export type ShowChildren = () => Node | Node[];
|
|
11
|
+
export type ShowSpec = (ShowGate | ShowBranch)[] | [...(ShowGate | ShowBranch)[], ShowChildren];
|
|
12
12
|
/** Conditional fragment backing `show()`. Branches are created lazily:
|
|
13
13
|
* a `use` factory only runs the first time its condition wins. Once
|
|
14
14
|
* created, the branch remains mounted and owned; inactive branches simply
|
|
@@ -49,7 +49,7 @@ declare class Show extends Node {
|
|
|
49
49
|
* )
|
|
50
50
|
* ```
|
|
51
51
|
*/
|
|
52
|
-
declare function show(...spec: ShowSpec): Show;
|
|
52
|
+
export declare function show(...spec: ShowSpec): Show;
|
|
53
53
|
//#endregion
|
|
54
|
-
export {
|
|
54
|
+
export type { Show };
|
|
55
55
|
//# sourceMappingURL=show.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.d.mts","names":[],"sources":["../../src/widgets/show.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"show.d.mts","names":[],"sources":["../../src/widgets/show.ts"],"mappings":";;YAMY;EAAa,MAAM;;YACnB;EAAe,MAAM;EAAmB,KAAK;;YAC7C,qBAAqB,OAAO;YAC5B,YAAY,WAAW,qBAAqB,WAAW,eAAe;;;;;;;;;cAkB5E,aAAa;;EAIjB,YAAY,MAAM;EAqBT,2BAA2B;;;;YAepB,QAAQ,KAAK,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;wBA8B3B,QAAQ,MAAM,WAAW"}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { P as RenderCtx, X as State, nt as Reactive, p as Node } from "../queries-
|
|
2
|
-
import { o as AnyStyle } from "../types-
|
|
1
|
+
import { P as RenderCtx, X as State, nt as Reactive, p as Node } from "../queries-Cvalgu6P.mjs";
|
|
2
|
+
import { o as AnyStyle } from "../types-C0EOLZDc.mjs";
|
|
3
3
|
//#region src/widgets/spinner.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Frame sets from the common terminal-spinner vocabulary. Pick one to taste.
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
|
-
declare const spinnerFrames: {
|
|
8
|
+
export declare const spinnerFrames: {
|
|
9
9
|
readonly arrow: readonly ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"];
|
|
10
10
|
readonly bouncingBar: readonly ["[ ]", "[= ]", "[== ]", "[=== ]", "[ ===]", "[ ==]", "[ =]", "[ ]"];
|
|
11
11
|
readonly circle: readonly ["◐", "◓", "◑", "◒"];
|
|
12
12
|
readonly dots: readonly ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
13
13
|
readonly line: readonly ["-", "\\", "|", "/"];
|
|
14
14
|
};
|
|
15
|
-
type SpinnerStyle = keyof typeof spinnerFrames;
|
|
16
|
-
interface SpinnerState {
|
|
15
|
+
export type SpinnerStyle = keyof typeof spinnerFrames;
|
|
16
|
+
export interface SpinnerState {
|
|
17
17
|
/** Frame glyphs, cycled in order. Defaults to `dots`. */
|
|
18
18
|
frames?: SpinnerStyle | readonly string[];
|
|
19
19
|
/** Foreground theme slot or explicit color. Defaults to `primary`. */
|
|
@@ -44,7 +44,7 @@ interface SpinnerState {
|
|
|
44
44
|
* even though invisible nodes skip rendering. Forgetting to `.stop()`
|
|
45
45
|
* is harmless — the unref'd timer doesn't pin the event loop.
|
|
46
46
|
*/
|
|
47
|
-
declare class Spinner extends Node<SpinnerState> {
|
|
47
|
+
export declare class Spinner extends Node<SpinnerState> {
|
|
48
48
|
#private;
|
|
49
49
|
constructor(state: SpinnerState);
|
|
50
50
|
/** Global tick index for a given `speed`. Shared across all callers. */
|
|
@@ -59,7 +59,6 @@ declare class Spinner extends Node<SpinnerState> {
|
|
|
59
59
|
* Factory for `Spinner`. All options are optional — a bare `spinner()`
|
|
60
60
|
* gives you the braille `dots` set at 80ms in the theme's `primary` color.
|
|
61
61
|
*/
|
|
62
|
-
declare function spinner(state?: State<SpinnerState>): Spinner;
|
|
62
|
+
export declare function spinner(state?: State<SpinnerState>): Spinner;
|
|
63
63
|
//#endregion
|
|
64
|
-
export { Spinner, SpinnerState, SpinnerStyle, spinner, spinnerFrames };
|
|
65
64
|
//# sourceMappingURL=spinner.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.mts","names":[],"sources":["../../src/widgets/spinner.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"spinner.d.mts","names":[],"sources":["../../src/widgets/spinner.ts"],"mappings":";;;;;;;qBAaa;WACX;WACA;WACA;WACA;WACA;;YAGU,4BAA4B;iBAEvB;;EAEf,SAAS;;EAET,QAAQ,SAAS;;;;;EAKjB,UAAU;EACV;;;;;;;;;;;;;;;;;;;;;qBA4DW,gBAAgB,KAAK;;EAChC,YAAY,OAAO;;SAYZ,KAAK;;EAKZ;;EAMA;YAcU,QAAQ,KAAK;;;;;;wBAoBT,QAAQ,QAAO,MAAM,gBAAqB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.mjs","names":[
|
|
1
|
+
{"version":3,"file":"spinner.mjs","names":[],"sources":["../../src/widgets/spinner.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Reactive } from \"../core/reactive.ts\"\nimport type { State } from \"../core/state.ts\"\nimport type { AnyStyle } from \"../style/types.ts\"\n\nimport { stringWidth } from \"@zaly/shared/ansi\"\nimport { Node } from \"../core/node.ts\"\nimport { effect, untrack, unwrap } from \"../core/reactive.ts\"\n\n/**\n * Frame sets from the common terminal-spinner vocabulary. Pick one to taste.\n * @internal\n */\nexport const spinnerFrames = {\n arrow: [\"←\", \"↖\", \"↑\", \"↗\", \"→\", \"↘\", \"↓\", \"↙\"],\n bouncingBar: [\"[ ]\", \"[= ]\", \"[== ]\", \"[=== ]\", \"[ ===]\", \"[ ==]\", \"[ =]\", \"[ ]\"],\n circle: [\"◐\", \"◓\", \"◑\", \"◒\"],\n dots: [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"],\n line: [\"-\", \"\\\\\", \"|\", \"/\"],\n} as const\n\nexport type SpinnerStyle = keyof typeof spinnerFrames\n\nexport interface SpinnerState {\n /** Frame glyphs, cycled in order. Defaults to `dots`. */\n frames?: SpinnerStyle | readonly string[]\n /** Foreground theme slot or explicit color. Defaults to `primary`. */\n color?: Reactive<AnyStyle>\n /** Whether the animation is ticking. Defaults to `true`. Accepts a\n * signal accessor so callers can drive the spinner from shared\n * reactive state. Setting `false` stops the interval; setting\n * `true` restarts it. */\n running?: Reactive<boolean>\n idle?: string\n}\n\nconst SPEED = 80\n\nclass Animator {\n #timer?: ReturnType<typeof setInterval>\n #spinners = new Set<Spinner>()\n\n #start(): void {\n if (this.#timer !== undefined) return\n // `untracked` so the interval callback doesn't inherit the render's tracking ctx.\n this.#timer = untrack(() =>\n setInterval(() => this.#spinners.forEach((s) => s.invalidate()), SPEED)\n )\n // Don't pin the event loop — a forgotten spinner should never\n // prevent the process from exiting.\n this.#timer.unref()\n }\n\n #stop(): void {\n if (this.#timer === undefined) return\n clearInterval(this.#timer)\n this.#timer = undefined\n }\n\n add(node: Spinner) {\n if (this.#spinners.has(node)) return\n this.#spinners.add(node)\n this.#start()\n }\n\n del(node: Spinner) {\n if (!this.#spinners.has(node)) return\n this.#spinners.delete(node)\n if (this.#spinners.size === 0) this.#stop()\n }\n}\n\nconst animator = new Animator()\n\n/**\n * An animated spinner. Its *frame* is always a pure function of wall\n * time and `speed`:\n *\n * ```ts\n * const idx = Spinner.tick(speed) % frames.length\n * ```\n *\n * That means the visible frame only depends on how much time has\n * actually elapsed, never on how often you happen to render. Two\n * spinners with the same `speed` stay in lockstep even if only one of\n * them gets invalidated.\n *\n * Each spinner owns an `unref()`'d interval while it is mounted,\n * visible, and running. The interval is reconciled from reactive\n * state/lifecycle, not from `_render`, so hiding a spinner stops it\n * even though invisible nodes skip rendering. Forgetting to `.stop()`\n * is harmless — the unref'd timer doesn't pin the event loop.\n */\nexport class Spinner extends Node<SpinnerState> {\n constructor(state: SpinnerState) {\n super(state)\n // Timer lifecycle is driven by mount + reactive state, not `_render`:\n // invisible nodes skip rendering, but still need their interval stopped.\n // Unmount always clears.\n this.on(\"mount\", () => this.#check())\n this.on(\"unmount\", () => animator.del(this))\n\n effect(() => this.#check())\n }\n\n /** Global tick index for a given `speed`. Shared across all callers. */\n static tick(speed: number): number {\n return Math.floor(performance.now() / speed)\n }\n\n /** Shorthand for `state.set({ running: true })`. */\n start(): this {\n this.state.set({ running: true })\n return this\n }\n\n /** Shorthand for `state.set({ running: false })`. */\n stop(): this {\n this.state.set({ running: false })\n return this\n }\n\n /** Sync the interval to the current `running` state. Reading through\n * `unwrap` during a render subscribes the spinner to a signal\n * accessor so flips from elsewhere in the app retrigger this. */\n #check(): void {\n const enabled = unwrap(this.state.running ?? true) && this.visible && this.mounted // track\n if (!enabled) return animator.del(this)\n animator.add(this)\n }\n\n protected _render(ctx: RenderCtx): string[] {\n const f = this.state.frames\n const frames = (typeof f === \"string\" ? spinnerFrames[f] : f) ?? spinnerFrames.dots\n let frame = frames[Spinner.tick(SPEED) % frames.length]\n // When stopped, hold the slot open with blank space of the same\n // cell width so surrounding layout doesn't jump as the spinner\n // toggles. Stable-width frame sets (dots, line, circle) look the\n // same; variable sets (bouncingBar) pick the longest frame's\n // width so stops after a short frame still hold full space.\n if (!unwrap(this.state.running ?? true))\n frame = (this.state.idle ?? \" \").repeat(stringWidth(frame))\n const color = this.state.color ?? \"primary\"\n return [ctx.style.add(unwrap(color))(frame)]\n }\n}\n\n/**\n * Factory for `Spinner`. All options are optional — a bare `spinner()`\n * gives you the braille `dots` set at 80ms in the theme's `primary` color.\n */\nexport function spinner(state: State<SpinnerState> = {}): Spinner {\n return new Spinner(state)\n}\n"],"mappings":";;;;;;;;AAaA,MAAa,gBAAgB;CAC3B,OAAO;EAAC;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;CAAG;CAC9C,aAAa;EAAC;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;EAAU;CAAQ;CAC5F,QAAQ;EAAC;EAAK;EAAK;EAAK;CAAG;CAC3B,MAAM;EAAC;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;CAAG;CACvD,MAAM;EAAC;EAAK;EAAM;EAAK;CAAG;AAC5B;AAiBA,MAAM,QAAQ;AAEd,IAAM,WAAN,MAAe;CACb;CACA,4BAAY,IAAI,IAAa;CAE7B,SAAe;EACb,IAAI,KAAK,WAAW,KAAA,GAAW;EAE/B,KAAK,SAAS,cACZ,kBAAkB,KAAK,UAAU,SAAS,MAAM,EAAE,WAAW,CAAC,GAAG,KAAK,CACxE;EAGA,KAAK,OAAO,MAAM;CACpB;CAEA,QAAc;EACZ,IAAI,KAAK,WAAW,KAAA,GAAW;EAC/B,cAAc,KAAK,MAAM;EACzB,KAAK,SAAS,KAAA;CAChB;CAEA,IAAI,MAAe;EACjB,IAAI,KAAK,UAAU,IAAI,IAAI,GAAG;EAC9B,KAAK,UAAU,IAAI,IAAI;EACvB,KAAK,OAAO;CACd;CAEA,IAAI,MAAe;EACjB,IAAI,CAAC,KAAK,UAAU,IAAI,IAAI,GAAG;EAC/B,KAAK,UAAU,OAAO,IAAI;EAC1B,IAAI,KAAK,UAAU,SAAS,GAAG,KAAK,MAAM;CAC5C;AACF;AAEA,MAAM,WAAW,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;AAqB9B,IAAa,UAAb,MAAa,gBAAgB,KAAmB;CAC9C,YAAY,OAAqB;EAC/B,MAAM,KAAK;EAIX,KAAK,GAAG,eAAe,KAAK,OAAO,CAAC;EACpC,KAAK,GAAG,iBAAiB,SAAS,IAAI,IAAI,CAAC;EAE3C,aAAa,KAAK,OAAO,CAAC;CAC5B;;CAGA,OAAO,KAAK,OAAuB;EACjC,OAAO,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;CAC7C;;CAGA,QAAc;EACZ,KAAK,MAAM,IAAI,EAAE,SAAS,KAAK,CAAC;EAChC,OAAO;CACT;;CAGA,OAAa;EACX,KAAK,MAAM,IAAI,EAAE,SAAS,MAAM,CAAC;EACjC,OAAO;CACT;;;;CAKA,SAAe;EAEb,IAAI,EADY,OAAO,KAAK,MAAM,WAAW,IAAI,KAAK,KAAK,WAAW,KAAK,UAC7D,OAAO,SAAS,IAAI,IAAI;EACtC,SAAS,IAAI,IAAI;CACnB;CAEA,QAAkB,KAA0B;EAC1C,MAAM,IAAI,KAAK,MAAM;EACrB,MAAM,UAAU,OAAO,MAAM,WAAW,cAAc,KAAK,MAAM,cAAc;EAC/E,IAAI,QAAQ,OAAO,QAAQ,KAAK,KAAK,IAAI,OAAO;EAMhD,IAAI,CAAC,OAAO,KAAK,MAAM,WAAW,IAAI,GACpC,SAAS,KAAK,MAAM,QAAQ,IAAA,CAAK,OAAO,YAAY,KAAK,CAAC;EAC5D,MAAM,QAAQ,KAAK,MAAM,SAAS;EAClC,OAAO,CAAC,IAAI,MAAM,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;CAC7C;AACF;;;;;AAMA,SAAgB,QAAQ,QAA6B,CAAC,GAAY;CAChE,OAAO,IAAI,QAAQ,KAAK;AAC1B"}
|
package/dist/widgets/text.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { G as text, H as Text, K as textContent, U as TextContent, W as TextStyle } from "../queries-
|
|
1
|
+
import { G as text, H as Text, K as textContent, U as TextContent, W as TextStyle } from "../queries-Cvalgu6P.mjs";
|
|
2
2
|
export { Text, TextContent, TextStyle, text, textContent };
|
package/dist/widgets/text.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as text, r as textContent, t as Text } from "../text-
|
|
1
|
+
import { n as text, r as textContent, t as Text } from "../text-BLz1tRoC.mjs";
|
|
2
2
|
export { Text, text, textContent };
|
package/dist/widgets/tree.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as tree, n as TreeNode, r as TreeProps, t as TreeItem } from "../tree-
|
|
1
|
+
import { i as tree, n as TreeNode, r as TreeProps, t as TreeItem } from "../tree-CArtDRec.mjs";
|
|
2
2
|
export { TreeItem, TreeNode, TreeProps, tree };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as Widget, r as widget, t as Props } from "../widget-
|
|
1
|
+
import { n as Widget, r as widget, t as Props } from "../widget-DtJU2-BJ.mjs";
|
|
2
2
|
export { Props, Widget, widget };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-T6SdPzUH.mjs","names":[],"sources":["../src/shiki/worker.ts"],"sourcesContent":["// oxlint-disable typescript/method-signature-style unicorn/require-post-message-target-origin\nimport type { MaybePromise } from \"@zaly/shared\"\n\nexport const workerHost = {\n onMessage: (handler: (message: any) => MaybePromise): void => {\n if (typeof globalThis.addEventListener === \"function\") {\n globalThis.addEventListener(\"message\", (event: MessageEvent) => void handler(event.data))\n return\n }\n void import(\"node:worker_threads\").then(({ parentPort }) => {\n parentPort?.on(\"message\", (message) => void handler(message))\n })\n },\n\n postMessage: (message: unknown): void => {\n if (typeof globalThis.postMessage === \"function\") {\n // oxlint-disable-next-line unicorn/require-post-message-target-origin\n globalThis.postMessage(message)\n return\n }\n void import(\"node:worker_threads\").then(({ parentPort }) => {\n // oxlint-disable-next-line unicorn/require-post-message-target-origin\n parentPort?.postMessage(message)\n })\n },\n}\n\nexport type WorkerInstance<In = unknown, Out = unknown> = {\n on(event: \"message\", handler: (message: Out) => MaybePromise): void\n on(event: \"error\", handler: (error: Error) => MaybePromise): void\n postMessage(message: In): void\n terminate(): void\n}\n\nexport async function createWorker<In = unknown, Out = unknown>(): Promise<\n WorkerInstance<In, Out>\n> {\n const scriptURL = new URL(import.meta.resolve(\"#shiki-worker\"))\n if (typeof globalThis.Worker === \"function\") {\n const w = new Worker(scriptURL, { type: \"module\" })\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n w.unref?.()\n return {\n on: (event, handler) => {\n if (event === \"error\")\n w.addEventListener(event, (e) => void handler(e.error ?? new Error(e.message)))\n else w.addEventListener(event, (e) => void handler(e.data))\n // Registering a listener can re-reference the worker.\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n w.unref?.()\n },\n postMessage: (message) => w.postMessage(message),\n terminate: () => w.terminate(),\n }\n }\n const { Worker: NodeWorker } = await import(\"node:worker_threads\")\n const worker = new NodeWorker(scriptURL)\n worker.unref()\n return {\n on: (event, handler) => {\n worker.on(event, (e) => void handler(e))\n // Registering a listener re-references the worker's MessagePort.\n worker.unref()\n },\n postMessage: (message) => worker.postMessage(message),\n terminate: () => void worker.terminate(),\n }\n}\n"],"mappings":";AAGA,MAAa,aAAa;CACxB,YAAY,YAAkD;EAC5D,IAAI,OAAO,WAAW,qBAAqB,YAAY;GACrD,WAAW,iBAAiB,YAAY,UAAwB,KAAK,QAAQ,MAAM,IAAI,CAAC;GACxF;EACF;EACA,OAAY,sBAAsB,CAAC,MAAM,EAAE,iBAAiB;GAC1D,YAAY,GAAG,YAAY,YAAY,KAAK,QAAQ,OAAO,CAAC;EAC9D,CAAC;CACH;CAEA,cAAc,YAA2B;EACvC,IAAI,OAAO,WAAW,gBAAgB,YAAY;GAEhD,WAAW,YAAY,OAAO;GAC9B;EACF;EACA,OAAY,sBAAsB,CAAC,MAAM,EAAE,iBAAiB;GAE1D,YAAY,YAAY,OAAO;EACjC,CAAC;CACH;AACF;AASA,eAAsB,eAEpB;CACA,MAAM,YAAY,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"worker-T6SdPzUH.mjs","names":[],"sources":["../src/shiki/worker.ts"],"sourcesContent":["// oxlint-disable typescript/method-signature-style unicorn/require-post-message-target-origin\nimport type { MaybePromise } from \"@zaly/shared\"\n\nexport const workerHost = {\n onMessage: (handler: (message: any) => MaybePromise): void => {\n if (typeof globalThis.addEventListener === \"function\") {\n globalThis.addEventListener(\"message\", (event: MessageEvent) => void handler(event.data))\n return\n }\n void import(\"node:worker_threads\").then(({ parentPort }) => {\n parentPort?.on(\"message\", (message) => void handler(message))\n })\n },\n\n postMessage: (message: unknown): void => {\n if (typeof globalThis.postMessage === \"function\") {\n // oxlint-disable-next-line unicorn/require-post-message-target-origin\n globalThis.postMessage(message)\n return\n }\n void import(\"node:worker_threads\").then(({ parentPort }) => {\n // oxlint-disable-next-line unicorn/require-post-message-target-origin\n parentPort?.postMessage(message)\n })\n },\n}\n\nexport type WorkerInstance<In = unknown, Out = unknown> = {\n on(event: \"message\", handler: (message: Out) => MaybePromise): void\n on(event: \"error\", handler: (error: Error) => MaybePromise): void\n postMessage(message: In): void\n terminate(): void\n}\n\nexport async function createWorker<In = unknown, Out = unknown>(): Promise<\n WorkerInstance<In, Out>\n> {\n const scriptURL = new URL(import.meta.resolve(\"#shiki-worker\"))\n if (typeof globalThis.Worker === \"function\") {\n const w = new Worker(scriptURL, { type: \"module\" })\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n w.unref?.()\n return {\n on: (event, handler) => {\n if (event === \"error\")\n w.addEventListener(event, (e) => void handler(e.error ?? new Error(e.message)))\n else w.addEventListener(event, (e) => void handler(e.data))\n // Registering a listener can re-reference the worker.\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n w.unref?.()\n },\n postMessage: (message) => w.postMessage(message),\n terminate: () => w.terminate(),\n }\n }\n const { Worker: NodeWorker } = await import(\"node:worker_threads\")\n const worker = new NodeWorker(scriptURL)\n worker.unref()\n return {\n on: (event, handler) => {\n worker.on(event, (e) => void handler(e))\n // Registering a listener re-references the worker's MessagePort.\n worker.unref()\n },\n postMessage: (message) => worker.postMessage(message),\n terminate: () => void worker.terminate(),\n }\n}\n"],"mappings":";AAGA,MAAa,aAAa;CACxB,YAAY,YAAkD;EAC5D,IAAI,OAAO,WAAW,qBAAqB,YAAY;GACrD,WAAW,iBAAiB,YAAY,UAAwB,KAAK,QAAQ,MAAM,IAAI,CAAC;GACxF;EACF;EACA,OAAY,sBAAsB,CAAC,MAAM,EAAE,iBAAiB;GAC1D,YAAY,GAAG,YAAY,YAAY,KAAK,QAAQ,OAAO,CAAC;EAC9D,CAAC;CACH;CAEA,cAAc,YAA2B;EACvC,IAAI,OAAO,WAAW,gBAAgB,YAAY;GAEhD,WAAW,YAAY,OAAO;GAC9B;EACF;EACA,OAAY,sBAAsB,CAAC,MAAM,EAAE,iBAAiB;GAE1D,YAAY,YAAY,OAAO;EACjC,CAAC;CACH;AACF;AASA,eAAsB,eAEpB;CACA,MAAM,YAAY,IAAI,IAAI,YAAY,QAAQ,eAAe,CAAC;CAC9D,IAAI,OAAO,WAAW,WAAW,YAAY;EAC3C,MAAM,IAAI,IAAI,OAAO,WAAW,EAAE,MAAM,SAAS,CAAC;EAElD,EAAE,QAAQ;EACV,OAAO;GACL,KAAK,OAAO,YAAY;IACtB,IAAI,UAAU,SACZ,EAAE,iBAAiB,QAAQ,MAAM,KAAK,QAAQ,EAAE,SAAS,IAAI,MAAM,EAAE,OAAO,CAAC,CAAC;SAC3E,EAAE,iBAAiB,QAAQ,MAAM,KAAK,QAAQ,EAAE,IAAI,CAAC;IAG1D,EAAE,QAAQ;GACZ;GACA,cAAc,YAAY,EAAE,YAAY,OAAO;GAC/C,iBAAiB,EAAE,UAAU;EAC/B;CACF;CACA,MAAM,EAAE,QAAQ,eAAe,MAAM,OAAO;CAC5C,MAAM,SAAS,IAAI,WAAW,SAAS;CACvC,OAAO,MAAM;CACb,OAAO;EACL,KAAK,OAAO,YAAY;GACtB,OAAO,GAAG,QAAQ,MAAM,KAAK,QAAQ,CAAC,CAAC;GAEvC,OAAO,MAAM;EACf;EACA,cAAc,YAAY,OAAO,YAAY,OAAO;EACpD,iBAAiB,KAAK,OAAO,UAAU;CACzC;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zaly/tui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Terminal UI framework used by zaly.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ansi",
|
|
@@ -80,29 +80,28 @@
|
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"diff": "^9.0.0",
|
|
83
|
-
"marked": "^18.0.
|
|
83
|
+
"marked": "^18.0.12",
|
|
84
84
|
"pathe": "^2.0.3",
|
|
85
|
-
"shiki": "^4.3
|
|
86
|
-
"@zaly/shared": "0.0.
|
|
85
|
+
"shiki": "^4.4.3",
|
|
86
|
+
"@zaly/shared": "0.0.5"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@typia/transform": "^12.1.1",
|
|
90
89
|
"ghostty-web": "^0.4.0",
|
|
91
90
|
"mitata": "^1.0.34",
|
|
92
91
|
"slice-ansi": "^9.0.0",
|
|
93
92
|
"string-width": "^8.2.2",
|
|
94
|
-
"typia": "^
|
|
95
|
-
"wrap-ansi": "^10.0.
|
|
93
|
+
"typia": "^14.0.5",
|
|
94
|
+
"wrap-ansi": "^10.0.1"
|
|
96
95
|
},
|
|
97
96
|
"optionalDependencies": {
|
|
98
|
-
"sharp": "^0.35.
|
|
97
|
+
"sharp": "^0.35.4"
|
|
99
98
|
},
|
|
100
99
|
"engines": {
|
|
101
100
|
"bun": ">=1.2",
|
|
102
|
-
"node": ">=
|
|
101
|
+
"node": ">=22.11"
|
|
103
102
|
},
|
|
104
103
|
"inlinedDependencies": {
|
|
105
|
-
"typia": "
|
|
104
|
+
"typia": "14.0.5"
|
|
106
105
|
},
|
|
107
106
|
"scripts": {
|
|
108
107
|
"bench": "z bench",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"box-DepqUtuo.mjs","names":["#layoutChildren","#layoutRow","#layoutColumn"],"sources":["../src/layout/border.ts","../src/widgets/box.ts"],"sourcesContent":["import type { StyleBuilder } from \"../style/builder.ts\"\n\nimport { sliceAnsi, stringWidth } from \"@zaly/shared/ansi\"\n\n/**\n * Border-character glyphs for drawing a box outline. Any single-cell string\n * is allowed (including multi-byte glyphs like rounded corners).\n */\nexport interface BorderChars {\n h: string\n v: string\n tl: string\n tr: string\n bl: string\n br: string\n}\n\nexport type BorderSpec = boolean | \"single\" | \"double\" | \"rounded\" | BorderChars\n\n/** @internal */\nexport const borders = {\n double: { bl: \"╚\", br: \"╝\", h: \"═\", tl: \"╔\", tr: \"╗\", v: \"║\" },\n rounded: { bl: \"╰\", br: \"╯\", h: \"─\", tl: \"╭\", tr: \"╮\", v: \"│\" },\n single: { bl: \"└\", br: \"┘\", h: \"─\", tl: \"┌\", tr: \"┐\", v: \"│\" },\n} as const satisfies Record<string, BorderChars>\n\n/** Resolve the `border` style value to a concrete BorderChars, or undefined.\n *\n * @internal*/\nexport function resolveBorder(spec: BorderSpec | undefined): BorderChars | undefined {\n if (spec === undefined || spec === false) return undefined\n if (spec === true) return borders.single\n if (typeof spec === \"string\") return borders[spec]\n return spec\n}\n\nexport type TitleAlign = \"left\" | \"center\" | \"right\"\n\nexport interface DrawBorderOpts {\n /**\n * Optional title embedded in the top border, with a single-cell space on\n * each side. Ellipsis-truncated when it overflows the budget.\n */\n title?: string\n /** Placement of `title` along the top border. Defaults to `\"left\"`. */\n titleAlign?: TitleAlign\n /**\n * Styled wrapper applied to the border glyphs (corners, horizontal,\n * vertical). Use `ctx.style.add(slotOrStyle)` at the call site so the\n * theme is resolved once per render.\n */\n borderStyle?: StyleBuilder\n /** Styled wrapper applied to the title text (including the padding spaces). */\n titleStyle?: StyleBuilder\n}\n\n/** Pass-through wrapper used when no style is supplied. */\nconst identity = (s: string): string => s\n\n/**\n * Wrap pre-rendered inner rows with a border, adding top/bottom border rows\n * and left/right border chars to each inner row. Inner rows must be padded\n * to a uniform width; the output rows are `innerWidth + 2` wide.\n *\n * Border glyphs and the optional title can be styled independently via\n * `borderStyle` / `titleStyle` — each is a pre-bound `StyleBuilder`, so\n * this helper stays purely about geometry and never touches SGR itself.\n *\n * @internal\n */\nexport function drawBorder(\n rows: readonly string[],\n chars: BorderChars,\n opts: DrawBorderOpts = {}\n): string[] {\n const { title, titleAlign } = opts\n const inner = rows.length > 0 ? stringWidth(rows[0]) : 0\n const wrapB = opts.borderStyle ?? identity\n const wrapT = opts.titleStyle ?? identity\n\n const out: string[] = []\n out.push(topRow({ align: titleAlign ?? \"left\", chars, inner, title, wrapB, wrapT }))\n const v = wrapB(chars.v)\n for (const row of rows) out.push(v + row + v)\n out.push(wrapB(chars.bl + chars.h.repeat(inner) + chars.br))\n return out\n}\n\ninterface TopRowArgs {\n align: TitleAlign\n chars: BorderChars\n inner: number\n title: string | undefined\n wrapB: (s: string) => string\n wrapT: (s: string) => string\n}\n\nfunction topRow({ align, chars, inner, title, wrapB, wrapT }: TopRowArgs): string {\n if (title === undefined || title === \"\") {\n return wrapB(chars.tl + chars.h.repeat(inner) + chars.tr)\n }\n // Chrome: h + space + title + space + h (4 cells of chrome around the title)\n const budget = inner - 4\n if (budget <= 0) return wrapB(chars.tl + chars.h.repeat(inner) + chars.tr)\n const shown = truncate(title, budget)\n const totalH = inner - 2 - stringWidth(shown)\n const { leading, trailing } = distributeH(totalH, align)\n const prefix = wrapB(`${chars.tl}${chars.h.repeat(leading)}`)\n const titleSeg = wrapT(` ${shown} `)\n const suffix = wrapB(`${chars.h.repeat(trailing)}${chars.tr}`)\n return prefix + titleSeg + suffix\n}\n\nfunction distributeH(totalH: number, align: TitleAlign): { leading: number; trailing: number } {\n if (align === \"left\") return { leading: 1, trailing: totalH - 1 }\n if (align === \"right\") return { leading: totalH - 1, trailing: 1 }\n // center: leading rounds down so odd slack biases the title slightly left.\n const leading = Math.floor(totalH / 2)\n return { leading, trailing: totalH - leading }\n}\n\nfunction truncate(s: string, width: number): string {\n if (stringWidth(s) <= width) return s\n if (width <= 1) return \"…\".repeat(width)\n return `${sliceAnsi(s, 0, width - 1)}…`\n}\n","import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { State } from \"../core/state.ts\"\nimport type { BorderSpec, TitleAlign } from \"../layout/border.ts\"\nimport type { RowItem } from \"../layout/flex.ts\"\nimport type { Style } from \"../style/types.ts\"\nimport type { TextContent } from \"./text.ts\"\n\nimport { stringWidth } from \"@zaly/shared/ansi\"\nimport { Node } from \"../core/node.ts\"\nimport { unwrap } from \"../core/reactive.ts\"\nimport { drawBorder, resolveBorder } from \"../layout/border.ts\"\nimport { allocateRow, isFixedWidth, padRow, stackColumn, zipRow } from \"../layout/flex.ts\"\nimport { clamp, resolveSize } from \"../layout/size.ts\"\nimport { textContent } from \"./text.ts\"\n\nexport type Padding =\n | number\n | readonly [v: number, h: number]\n | readonly [t: number, r: number, b: number, l: number]\n\nexport interface BoxStyle extends Style {\n flexDirection?: \"row\" | \"column\"\n gap?: number\n /** Fixed outer height in rows. When unset, the box's height emerges\n * naturally from its content + padding + border. When set, the\n * content area is truncated or padded with blank rows to land at\n * exactly this many rows of *outer* height. Pair with\n * `verticalAlign` to control which edge is anchored. */\n height?: number\n /** Anchor for the content when `height` truncates or extends.\n * `\"top\"` (default) keeps the top edge: extra rows added at the\n * bottom, overflow truncated from the bottom. `\"bottom\"` keeps the\n * bottom edge: extra rows prepended, overflow truncated from the\n * top. Other CSS-like values (`middle`) are not implemented. */\n verticalAlign?: \"top\" | \"bottom\"\n padding?: Padding\n border?: BorderSpec\n borderTitle?: TextContent\n /** Placement of `borderTitle` along the top border. Defaults to `\"left\"`. */\n borderTitleAlign?: TitleAlign\n /**\n * Style applied to the border glyphs. Either a theme slot name (resolved\n * via the active theme) or an inline `Style`. Defaults to the `\"border\"`\n * theme slot when a border is drawn.\n */\n borderStyle?: string | Style\n /**\n * Style applied to the border title. Defaults to the `\"borderTitle\"` theme\n * slot when a title is set.\n */\n borderTitleStyle?: string | Style\n}\n\nexport class Box<T extends object = {}> extends Node<BoxStyle & T> {\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n const style = this.state\n\n const [padT, padR, padB, padL] = resolvePadding(style.padding)\n const bchars = resolveBorder(style.border)\n const hasBorder = bchars !== undefined\n const chrome = padL + padR + (hasBorder ? 2 : 0)\n\n let outer: number\n let contentRows: string[]\n let inner: number\n\n if (style.width === \"fit\") {\n // `fit`: render children at the parent's max inner width, measure\n // the natural max-row width, then clamp the box to that. Two-pass\n // — the first pass uses the upper bound as a measuring window,\n // the second re-pads each row to the chosen inner width.\n const upper = Math.max(0, ctx.width - chrome)\n const tentative = await this.#layoutChildren(upper, ctx)\n const natural = tentative.reduce((m, r) => Math.max(m, stringWidth(r)), 0)\n const fit = Math.min(ctx.width, natural + chrome)\n outer = clamp(fit, {\n available: ctx.width,\n max: style.maxWidth,\n min: style.minWidth,\n })\n inner = Math.max(0, outer - chrome)\n contentRows = tentative\n } else {\n const requested = resolveSize(style.width ?? \"fill\", ctx.width) ?? ctx.width\n outer = clamp(requested, {\n available: ctx.width,\n max: style.maxWidth,\n min: style.minWidth,\n })\n inner = Math.max(0, outer - chrome)\n contentRows = await this.#layoutChildren(inner, ctx)\n }\n\n const paddedWidth = Math.max(0, outer - (hasBorder ? 2 : 0))\n\n // Ensure each content row is exactly `inner` cells wide (absorbs slack).\n contentRows = contentRows.map((row) => padRow(row, inner))\n\n // Horizontal padding.\n if (padL > 0 || padR > 0) {\n const lp = \" \".repeat(padL)\n const rp = \" \".repeat(padR)\n contentRows = contentRows.map((row) => lp + row + rp)\n }\n\n // Vertical padding.\n const blank = \" \".repeat(paddedWidth)\n const top = Array.from({ length: padT }, () => blank)\n const bot = Array.from({ length: padB }, () => blank)\n let rows = [...top, ...contentRows, ...bot]\n\n // Fixed-height fit. The `height` field is the outer dimension —\n // border takes its 2 rows out before we measure against the\n // content area; padding is already baked into `rows`. `verticalAlign`\n // decides which end gets clipped (when too tall) or padded (when\n // too short). Default `\"top\"` matches the natural reading flow.\n if (style.height !== undefined) {\n const innerH = Math.max(0, style.height - (hasBorder ? 2 : 0))\n if (rows.length > innerH) {\n rows = style.verticalAlign === \"bottom\" ? rows.slice(-innerH) : rows.slice(0, innerH)\n } else if (rows.length < innerH) {\n const filler = Array.from({ length: innerH - rows.length }, () => blank)\n rows = style.verticalAlign === \"bottom\" ? [...filler, ...rows] : [...rows, ...filler]\n }\n }\n\n if (bchars) {\n rows = drawBorder(rows, bchars, {\n borderStyle: ctx.style.add(style.borderStyle ?? \"border\"),\n title: await textContent(style.borderTitle, ctx),\n titleAlign: style.borderTitleAlign,\n titleStyle: ctx.style.add(style.borderTitleStyle ?? \"borderTitle\"),\n })\n }\n\n const wrap = ctx.style.add(style)\n return rows.map((row) => wrap(row))\n }\n\n /**\n * Intrinsic content width derived from children (or the explicit\n * `width` when fixed). Lets parent flex containers size this Box\n * without falling back to a measure-render — important for\n * side-effecting children like `Image` whose first render allocates\n * a KGP placement: rendering twice would emit two placements and the\n * second render's `transmitOnce` returns no bytes, so the bytes from\n * the discarded measure pass would be lost.\n *\n * Row direction → bases sum (plus gaps). Column direction → bases\n * max. Both add chrome (padding + border) at the end.\n *\n * Children without `layout()` contribute 0 — the row allocator's\n * render-measure fallback still kicks in for them at allocation\n * time, but their absence here just means this Box reports a\n * smaller intrinsic. That's the safe direction: under-report and\n * let shrink/grow handle slack, never over-report.\n */\n override async layout(ctx: RenderCtx) {\n const s = this.state\n const [, padR, , padL] = resolvePadding(s.padding)\n const chrome = padL + padR + (resolveBorder(s.border) ? 2 : 0)\n\n // Fixed width wins outright.\n if (isFixedWidth(s.width)) {\n const w = resolveSize(s.width, ctx.width) ?? 0\n return { minWidth: w, width: w }\n }\n\n const kids = layoutNodes(this.children)\n if (kids.length === 0) return { minWidth: chrome, width: chrome }\n\n const isRow = (s.flexDirection ?? \"column\") === \"row\"\n const totalGap = isRow ? (s.gap ?? 0) * Math.max(0, kids.length - 1) : 0\n\n let widthAcc = 0\n let minAcc = 0\n for (const k of kids) {\n // oxlint-disable-next-line no-await-in-loop\n const l = (await k.getLayout(ctx)) ?? { minWidth: 0, width: 0 }\n if (isRow) {\n widthAcc += l.width\n minAcc += l.minWidth\n } else {\n widthAcc = Math.max(widthAcc, l.width)\n minAcc = Math.max(minAcc, l.minWidth)\n }\n }\n\n return { minWidth: minAcc + totalGap + chrome, width: widthAcc + totalGap + chrome }\n }\n\n async #layoutChildren(innerWidth: number, ctx: RenderCtx): Promise<string[]> {\n const children = layoutNodes(this.children)\n if (children.length === 0) return []\n const gap = this.state.gap ?? 0\n return (this.state.flexDirection ?? \"column\") === \"row\"\n ? this.#layoutRow(children, innerWidth, ctx, gap)\n : this.#layoutColumn(children, innerWidth, ctx, gap)\n }\n\n /**\n * Row direction — main axis is horizontal. CSS-style flex:\n * each child sizes to its intrinsic content width unless it claims\n * slack via `flexGrow > 0` or `width: \"fill\"`. Slack distributes by\n * grow weights; deficit distributes by `basis * flexShrink` clamped\n * at each child's `min-content` floor.\n *\n * Sizing strategy per child:\n * 1. `node.layout(ctx)` — sync, content-derived. If implemented,\n * use directly; no render needed for measurement.\n * 2. Otherwise fall back to render-at-innerWidth and measure the\n * widest emitted row. Cached; the paint pass reuses the result\n * whenever the allocated width matches the measurement width.\n *\n * In `fit` mode the parent has no slack to give, so the allocator's\n * available is capped at the natural sum.\n */\n async #layoutRow(\n children: readonly Node[],\n innerWidth: number,\n ctx: RenderCtx,\n gap: number\n ): Promise<string[]> {\n // Phase 1: figure out each child's intrinsic size.\n // - `layout()` short-circuits — sync, no render.\n // - Fallback: render at the upper bound (innerWidth or fixed spec)\n // and measure rows.\n const intrinsics = await Promise.all(children.map((c) => c.getLayout(ctx)))\n // For children with intrinsic sizing, skip the measure render\n // entirely. Others fall back to render-at-upper-bound (their fixed\n // width, or innerWidth if fluid).\n const measureWidths = children.map((c, i) => {\n if (intrinsics[i] !== undefined) return -1\n if (isFixedWidth(c.state.width)) {\n return resolveSize(c.state.width, innerWidth) ?? innerWidth\n }\n return innerWidth\n })\n const measureRows = await Promise.all(\n children.map((c, i): Promise<string[] | undefined> => {\n if (measureWidths[i] === -1) return Promise.resolve(undefined)\n return c.render({ ...ctx, width: measureWidths[i] })\n })\n )\n const naturals = children.map((c, i) => {\n // A fixed `state.width` is what the allocator will actually\n // assign this child — use it directly so the fit-mode\n // `allocAvailable` sum below matches what we'll consume. Falling\n // back to intrinsic when there's no override under-reports a\n // child like `text(\"x\", { width: 2 })` and shrinks every sibling\n // by the missing cells.\n if (isFixedWidth(c.state.width)) {\n return resolveSize(c.state.width, innerWidth) ?? 0\n }\n const intr = intrinsics[i]\n if (intr) return intr.width\n return (measureRows[i] ?? []).reduce((m, r) => Math.max(m, stringWidth(r)), 0)\n })\n const items: RowItem[] = children.map((c, i) => {\n const s = c.state\n return {\n flexGrow: s.flexGrow,\n flexShrink: s.flexShrink,\n intrinsicMin: intrinsics[i]?.minWidth,\n maxWidth: s.maxWidth,\n minWidth: s.minWidth,\n natural: naturals[i],\n width: s.width,\n }\n })\n const allocAvailable =\n this.state.width === \"fit\"\n ? naturals.reduce((a, b) => a + b, 0) + gap * Math.max(0, children.length - 1)\n : innerWidth\n const widths = allocateRow(items, { contentWidth: allocAvailable, gap })\n // Phase 2: paint at allocated widths. Reuse the measure-render when\n // the allocation matches; otherwise render fresh (cached).\n const childRows = await Promise.all(\n children.map((c, i): Promise<string[]> => {\n const cached = measureRows[i]\n if (cached !== undefined && widths[i] === measureWidths[i]) {\n return Promise.resolve(cached)\n }\n return c.render({ ...ctx, width: widths[i] })\n })\n )\n // `zipRow` expects rows to be exactly `widths[i]` wide. Children\n // that emit natural-width rows (text default, code default) get\n // padded here so the contract holds; over-wide rows get clipped.\n const padded = childRows.map((rows, i) => rows.map((row) => padRow(row, widths[i])))\n return zipRow(padded, { gap, widths })\n }\n\n /**\n * Column direction — main axis is vertical, cross axis horizontal.\n * Per CSS `align-items: stretch` (default), children with no\n * explicit `width` fill the cross axis. A child with a fixed `width`\n * (number / `Pct`) takes that width as its cross-axis size, with the\n * leftover padded as right slack (default `flex-start`). `min`/`max`\n * clamp the resolved width.\n *\n * In fit-mode (`width: \"fit\"`), the cross-axis target shrinks to the\n * widest child row instead of stretching to `innerWidth` — symmetric\n * to how row-direction caps allocator-available at the natural sum.\n */\n async #layoutColumn(\n children: readonly Node[],\n innerWidth: number,\n ctx: RenderCtx,\n gap: number\n ): Promise<string[]> {\n const widths = children.map((c) => {\n const s = c.state\n const fixed = isFixedWidth(s.width) ? resolveSize(s.width, innerWidth) : undefined\n const w = fixed ?? innerWidth\n return clamp(w, { available: innerWidth, max: s.maxWidth, min: s.minWidth })\n })\n const childRows = await Promise.all(\n children.map((c, i) => c.render({ ...ctx, width: widths[i] }))\n )\n const target =\n this.state.width === \"fit\"\n ? childRows.reduce((m, rows) => rows.reduce((mm, r) => Math.max(mm, stringWidth(r)), m), 0)\n : innerWidth\n // Pad each child's rows to the cross-axis target. For full-stretch\n // children this absorbs natural-row slack; for fixed-width\n // children it adds right-side slack (default `flex-start`\n // alignment). `stackColumn`'s contract requires uniform width.\n const padded = childRows.map((rows) => rows.map((row) => padRow(row, target)))\n return stackColumn(padded, { gap, width: target })\n }\n}\n\ntype Child = Node | false | null | undefined\n\n/**\n * Factory for `Box`. The style object is required (use `{}` if you don't\n * need any styling) — the previous style-less overload caused TS to fail\n * to discriminate between a Node child and an inferred-empty-state node\n * like `WidgetNode`. Pass `box({}, child1, child2)` for un-styled boxes.\n *\n * Falsy children (`false`, `null`, `undefined`) are filtered out, enabling\n * conditional JSX-like composition: `box({}, cond && child)`.\n */\nexport function box(style: State<BoxStyle>, ...children: Child[]): Box {\n const b = new Box(style)\n for (const c of children) if (c) b.add(c)\n return b\n}\n\n/**\n * Flatten fragment nodes (those that implement the `layoutChildren`\n * protocol — `show`, `errorBoundary`, `suspense`) into their currently\n * active leaves. Recursive: a fragment whose `layoutChildren()`\n * itself contains fragments unfolds completely.\n *\n * The fragment Node still lives in the tree (mounted, propagating\n * invalidates) — layout just sees through it so its children share\n * the parent box's flex distribution, gap, and cross-axis sizing\n * instead of collapsing into a single slot.\n */\nfunction layoutNodes(children: readonly Node[]): readonly Node[] {\n return children.flatMap((c) => c.layoutNodes).filter((c) => unwrap(c.state.visible) ?? true)\n}\n\nfunction resolvePadding(p: Padding | undefined): [t: number, r: number, b: number, l: number] {\n if (p === undefined) return [0, 0, 0, 0]\n if (typeof p === \"number\") return [p, p, p, p]\n if (p.length === 2) return [p[0], p[1], p[0], p[1]]\n return [p[0], p[1], p[2], p[3]]\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"builder-T9oGIWFa.mjs","names":["#cache","#main","#theme","#styleCache","#colorCache"],"sources":["../src/style/oklch.ts","../src/style/style.ts","../src/style/builder.ts"],"sourcesContent":["/**\n * OKLCH-based tonal scale generation for theme colors.\n *\n * Given a base hex color, `variant(hex, step)` returns a hex variant at\n * the Tailwind-v4-ish step (50..950). The base color's hue and chroma\n * are preserved; only lightness moves. When the resulting color falls\n * outside sRGB, chroma is reduced via binary search (CSS Color Level 4\n * \"MinDE chroma reduction\") until the color fits — that avoids the\n * saturation blowout you get from naive HSL lightening at the extremes.\n *\n * Matrix constants come from Björn Ottosson's reference OKLab spec:\n * https://bottosson.github.io/posts/oklab/\n */\n\nimport type { HexColor } from \"./types.ts\"\n\nimport { clamp } from \"@zaly/shared\"\nimport { parseHex, toHex } from \"./color.ts\"\n\nexport interface OKLCH {\n L: number\n C: number\n h: number\n}\n\nconst cache = new Map<string, HexColor>()\n\n// ---------- conversions ----------\n\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4\n}\n\nfunction linearToSrgb(c: number): number {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055\n}\n\nexport function hexToOklch(hex: string): OKLCH {\n const [r8, g8, b8] = parseHex(hex)\n const r = srgbToLinear(r8 / 255)\n const g = srgbToLinear(g8 / 255)\n const b = srgbToLinear(b8 / 255)\n\n const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b\n const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b\n const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b\n const lp = Math.cbrt(l)\n const mp = Math.cbrt(m)\n const sp = Math.cbrt(s)\n const L = 0.2104542553 * lp + 0.793617785 * mp - 0.0040720468 * sp\n const a = 1.9779984951 * lp - 2.428592205 * mp + 0.4505937099 * sp\n const b2 = 0.0259040371 * lp + 0.7827717662 * mp - 0.808675766 * sp\n const C = Math.hypot(a, b2)\n const h = ((Math.atan2(b2, a) * 180) / Math.PI + 360) % 360\n return { C, L, h }\n}\n\n/** Convert OKLCH → linear sRGB (unclamped — callers can test for gamut). */\nfunction oklchToLinearRgb({ L, C, h }: OKLCH): [number, number, number] {\n const hr = (h * Math.PI) / 180\n const a = C * Math.cos(hr)\n const b2 = C * Math.sin(hr)\n const lp = L + 0.3963377774 * a + 0.2158037573 * b2\n const mp = L - 0.1055613458 * a - 0.0638541728 * b2\n const sp = L - 0.0894841775 * a - 1.291485548 * b2\n const l = lp ** 3\n const m = mp ** 3\n const s = sp ** 3\n const r = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s\n const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s\n const b = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s\n return [r, g, b]\n}\n\nfunction inGamut([r, g, b]: [number, number, number], eps = 0.001): boolean {\n return r >= -eps && r <= 1 + eps && g >= -eps && g <= 1 + eps && b >= -eps && b <= 1 + eps\n}\n\n/**\n * Convert OKLCH → hex, reducing chroma via binary search when the\n * straightforward conversion falls outside sRGB. The search keeps `L`\n * and `h` fixed and shrinks `C` toward the achromatic axis until the\n * color fits, which is the CSS Color Level 4-recommended behavior.\n */\nexport function oklchToHex(oklch: OKLCH): HexColor {\n let rgb = oklchToLinearRgb(oklch)\n if (!inGamut(rgb)) {\n // Binary-search on C.\n let lo = 0\n let hi = oklch.C\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2\n if (inGamut(oklchToLinearRgb({ ...oklch, C: mid }))) lo = mid\n else hi = mid\n }\n rgb = oklchToLinearRgb({ ...oklch, C: lo })\n }\n const [r, g, b] = rgb.map((c) => linearToSrgb(Math.max(0, Math.min(1, c)))) as [\n number,\n number,\n number,\n ]\n return toHex(r * 255, g * 255, b * 255)\n}\n\nexport function shiftLightness(hex: HexColor, delta: number): HexColor {\n const key = `${hex}:${delta}`\n let ret = cache.get(key)\n if (ret) return ret\n\n const okl = hexToOklch(hex)\n const L = clamp(okl.L + delta, 0, 1)\n // Pull chroma toward 0 as L approaches an extreme. Keeps near-white\n // and near-black from going out of gamut.\n const margin = Math.min(L, 1 - L)\n const C = okl.C * Math.min(1, margin / 0.1)\n cache.set(key, (ret = oklchToHex({ ...okl, C, L })))\n return ret\n}\n","import type { Theme } from \"../themes/types.ts\"\nimport type { AnsiColor, AnsiStyle, Color, Style } from \"./types.ts\"\n\nimport { openAnsi } from \"./ansi.ts\"\nimport { isHexColor } from \"./color.ts\"\nimport { shiftLightness } from \"./oklch.ts\"\n\n/**\n * Build the opening SGR escape for a style descriptor. Returns '' if nothing\n * would be emitted. Unresolvable colors (invalid or 'inherit') are dropped.\n *\n * When `theme` is provided, `fg`/`bg` values matching a theme color slot\n * (e.g. `\"primary\"`, `\"muted\"`) are resolved against it first. The output\n * ordering is attrs → fg → bg, combined into a single `\\x1b[...m` run.\n *\n * @internal\n */\nexport function openStyle(style: Style, theme?: Theme): string {\n const resolver = ThemeResolver.from(theme)\n const ansiStyle: AnsiStyle = {\n ...style,\n bg: style.bg !== undefined ? resolver.getColor(style.bg, \"bg\") : undefined,\n fg: style.fg !== undefined ? resolver.getColor(style.fg, \"fg\") : undefined,\n }\n return openAnsi(ansiStyle)\n}\n\n/**\n * Resolve a style-slot reference into a `Style` object. A ref is either a\n * theme slot name (string), an inline `Style`, or `undefined`:\n *\n * - Inline `Style` → returned as-is (no slot lookup).\n * - String ref pointing at a **Color** slot → wrapped as `{ fg: <color> }`.\n * - String ref pointing at a **Style** slot → returned directly.\n * - String ref that doesn't match a slot → treated as a fg color\n * (`{ fg: <ref> }`) and resolved downstream by `colorParams`.\n * - `undefined` → `{}` (emits nothing).\n *\n * @internal\n */\nexport function resolveStyle(ref: string | Style | undefined, theme?: Theme): Style {\n return ThemeResolver.from(theme).getStyle(ref)\n}\n\nfunction parseColor(c: string): { base: string; lightness?: number } {\n const m = c.match(/^(.+?)([+-]\\d{1,3})$/)\n if (!m) return { base: c }\n let lightness = Number(m[2])\n if (!Number.isFinite(lightness))\n throw new TypeError(`Invalid color step in color \"${c}\": ${m[2]}`)\n lightness = Math.abs(lightness) < 1 ? lightness : lightness / 100\n return { base: m[1], lightness }\n}\n\nclass ThemeResolver {\n static #cache = new Map<Partial<Theme>, ThemeResolver>()\n static #main = new ThemeResolver()\n #theme: Partial<Theme>\n #styleCache = new Map<string, Style>()\n #colorCache = new Map<string, string>()\n\n private constructor(theme: Partial<Theme> = {}) {\n this.#theme = theme\n }\n\n static from(theme?: Theme): ThemeResolver {\n if (theme === undefined) return this.#main\n let resolver = this.#cache.get(theme)\n if (!resolver) {\n resolver = new ThemeResolver(theme)\n this.#cache.set(theme, resolver)\n }\n return resolver\n }\n\n getStyle(ref?: string | Style, seen?: Set<string>): Style {\n if (ref === undefined) return {}\n if (typeof ref === \"object\")\n return ref.style ? { ...this.getStyle(ref.style, seen), ...ref } : ref\n\n let ret = this.#styleCache.get(ref)\n if (ret) return ret\n\n seen ??= new Set<string>()\n if (seen.has(ref)) throw new TypeError(`Circular dependency for theme slot \"${ref}\".`)\n seen.add(ref)\n\n const value = this.#theme[ref as keyof Theme]\n ret = value === undefined ? { fg: ref as Color } : this.getStyle(value, seen)\n this.#styleCache.set(ref, ret)\n return ret\n }\n\n getColor(ref?: string, kind: \"fg\" | \"bg\" = \"fg\", seen?: Set<string>): AnsiColor {\n if (ref === undefined) return \"inherit\"\n\n const key = `${kind}:${ref}`\n let ret = this.#colorCache.get(key)\n if (ret) return ret as AnsiColor\n\n seen ??= new Set<string>()\n if (seen.has(ref)) throw new TypeError(`Circular dependency for theme slot \"${ref}\".`)\n seen.add(ref)\n\n const { base, lightness } = parseColor(ref)\n\n let value = this.#theme[base as keyof Theme] ?? base\n if (typeof value === \"object\") value = this.getColor(value[kind], kind, seen)\n else if (value !== base) value = this.getColor(value, kind, seen)\n ret = lightness !== undefined && isHexColor(value) ? shiftLightness(value, lightness) : value\n this.#colorCache.set(key, ret)\n return ret as AnsiColor\n }\n}\n","import type { Theme } from \"../themes/types.ts\"\nimport type { AnsiColorName, BrightAnsiColorName, Color, Style } from \"./types.ts\"\n\nimport { defaultTheme } from \"../themes/registry.ts\"\nimport { reapplyStyle, RESET } from \"./ansi.ts\"\nimport { openStyle, resolveStyle } from \"./style.ts\"\n\ntype AttrName = \"bold\" | \"dim\" | \"italic\" | \"underline\" | \"inverse\" | \"strikethrough\"\n\ntype AnyThemeKey = Exclude<keyof Theme, \"shiki\" | \"$schema\"> | (string & {})\n\n// Theme color slots that can chain as fg/bg. `fg`/`bg` become setter methods\n// below, so exclude them here to avoid naming collisions. `dim` is an attr on\n// the chain; users wanting theme-slot-dim for fg use `.fg(\"dim\")`.\ntype ChainSlot = Exclude<keyof Theme, \"fg\" | \"bg\" | AttrName>\n\ntype FgChainKey = AnsiColorName | BrightAnsiColorName | ChainSlot\ntype BgChainKey = `bg${Capitalize<FgChainKey>}`\ntype FgExtractKey = `fg${Capitalize<FgChainKey>}`\n\nexport type StyleBuilder = {\n theme: Theme\n (text: string): string\n fg: (color: Color) => StyleBuilder\n bg: (color: Color) => StyleBuilder\n add: (slot?: AnyThemeKey | Style) => StyleBuilder\n lighten: (n: number) => StyleBuilder\n darken: (n: number) => StyleBuilder\n // oxlint-disable-next-line typescript/consistent-indexed-object-style -- mapped over a key union, not an open string index\n} & {\n readonly [K in AttrName | FgChainKey | BgChainKey | FgExtractKey]: StyleBuilder\n}\n\n/**\n * Build styled strings via chainable property access.\n *\n * ```ts\n * style().red.bold(\"err\") // → \"\\x1b[1;31merr\\x1b[0m\"\n * style().primary.bgAccent(\"x\") // theme slots via the default theme\n * style(myTheme).primary(\"x\") // override the bound theme\n * style().fg(\"#82aaff\")(\"x\") // hex via the escape hatch\n * style().primary[300](\"x\") // tonal variant of the last color\n * style().bgDiffAdd[200].fgDiffAdd(\"x\") // per-channel variants on a Style slot\n * ```\n *\n * Each property access returns a fresh builder, so intermediates can be\n * reused and extended without mutation:\n *\n * ```ts\n * const err = style().red.bold\n * err(\"oops\"); err.underline(\"fatal\")\n * ```\n *\n * Calling an empty builder is a no-op: `styleBuilder()(\"x\")` returns `\"x\"` unchanged.\n */\nexport function styleBuilder(theme: Theme | false = defaultTheme): StyleBuilder {\n return build({\n current: {},\n last: undefined,\n theme: theme === false ? { ...defaultTheme, enabled: false } : theme,\n })\n}\n\nconst ATTRS = new Set<string>([\"bold\", \"dim\", \"italic\", \"underline\", \"inverse\", \"strikethrough\"])\n\n/** Pending \"arg-taking\" op on a chain. Set when the caller accesses\n * `.fg` / `.bg` / `.alpha` / `.add` — the chain is \"parked\" waiting\n * for its argument. Calling the parked chain consumes the arg and\n * produces the real child chain. */\ntype PendingOp = \"fg\" | \"bg\" | \"darken\" | \"add\" | \"lighten\"\n\n/** All the inputs a chain needs to behave correctly, gathered in one\n * object so we can pass it around cheaply instead of closing over\n * four separate vars. `current` is the accumulated Style, `last`\n * tracks which of `fg`/`bg` was most recently touched (for `[step]`\n * and `.alpha()`), `theme` is the resolved theme, `pending` is set\n * on parked arg-taking chains. */\ninterface BuilderState {\n current: Style\n last: \"fg\" | \"bg\" | undefined\n theme: Theme & { enabled?: boolean }\n pending?: PendingOp\n}\n\n/** The function wrapped by every chain's Proxy. Carries its own state\n * so module-level handlers can read it without closure gymnastics. */\ntype BuilderFn = {\n state: BuilderState\n theme: Theme\n} & (((text: string) => string) | ((arg: Color | number | Style | undefined) => StyleBuilder))\n\n// --- module-level handlers (shared across every chain) -----------------\n\nfunction applyStyle(state: BuilderState, text: string): string {\n if (!text || state.theme.enabled === false) return text\n const open = openStyle(state.current, state.theme)\n return open === \"\" ? text : open + reapplyStyle(text, open) + RESET\n}\n\nfunction applyOp(fn: BuilderFn, arg: Color | number | Style | undefined): StyleBuilder {\n // Cache primitive args on the call target itself via `defineProperty`\n // — repeated `.fg(\"#82aaff\")` hits the same child chain after the\n // first call, no rebuild. Object args (e.g. raw Style for `add`)\n // can't be property keys (`\"[object Object]\"` collision), so those\n // always rebuild.\n if (typeof arg === \"string\" || typeof arg === \"number\") {\n const key = String(arg)\n const hit = (fn as unknown as Record<string, unknown>)[key]\n if (hit !== undefined) return hit as StyleBuilder\n const child = fulfill(fn.state, arg)\n Reflect.defineProperty(fn, key, { configurable: false, value: child, writable: false })\n return child\n }\n return fulfill(fn.state, arg)\n}\n\n/** Turn a parked chain + its arg into the real child chain. */\nfunction fulfill(state: BuilderState, arg: unknown): StyleBuilder {\n const { current, last, theme, pending } = state\n switch (pending) {\n case \"fg\": {\n return build({ current: { ...current, fg: arg as Color }, last: \"fg\", theme })\n }\n case \"bg\": {\n return build({ current: { ...current, bg: arg as Color }, last: \"bg\", theme })\n }\n case \"lighten\":\n case \"darken\": {\n if (last === undefined) return build({ current, last, theme })\n const existing = current[last]\n if (typeof existing !== \"string\" || existing === \"inherit\") {\n return build({ current, last, theme })\n }\n const stripped = existing.replace(/[+-]\\d+$/, \"\")\n const n = Math.abs(arg as number)\n const next = `${stripped}${pending === \"lighten\" ? \"+\" : \"-\"}${n}` as Color\n return build({ current: { ...current, [last]: next }, last, theme })\n }\n default: {\n // \"add\" — no pending pending? defaults to rebuild with undef arg.\n return build({\n current: { ...current, ...resolveStyle(arg as string | Style | undefined, theme) },\n last,\n theme,\n })\n }\n }\n}\n\n/** Resolve a single property access on a chain to its child chain. */\nfunction compileKey(state: BuilderState, key: string): StyleBuilder | undefined {\n const { current, last, theme } = state\n\n // Arg-taking ops come back as chains parked in the `pending` state.\n if (key === \"fg\" || key === \"bg\" || key === \"lighten\" || key === \"darken\" || key === \"add\") {\n return build({ current, last, pending: key, theme })\n }\n\n if (ATTRS.has(key)) return build({ current: { ...current, [key]: true }, last, theme })\n\n // `bgFoo` / `fgFoo` → set the channel to the color at slot `foo`.\n // When the slot is a Style, `colorParams` extracts that channel.\n if (key.startsWith(\"bg\") && key.length > 2 && key[2] === key[2].toUpperCase()) {\n const color = (key[2].toLowerCase() + key.slice(3)) as Color\n return build({ current: { ...current, bg: color }, last: \"bg\", theme })\n }\n if (key.startsWith(\"fg\") && key.length > 2 && key[2] === key[2].toUpperCase()) {\n const color = (key[2].toLowerCase() + key.slice(3)) as Color\n return build({ current: { ...current, fg: color }, last: \"fg\", theme })\n }\n\n // Style-valued theme slot → merge its fields into the chain.\n // Anything else (ANSI color names, hex, unresolved slot refs) is\n // treated as a fg color by `colorParams` downstream.\n return build({ current: { ...current, ...resolveStyle(key, theme) }, last: \"fg\", theme })\n}\n\n/** Shared Proxy handler — one instance, used by every chain. Reads\n * state off the target (the `BuilderFn`), so chain construction\n * doesn't allocate a fresh handler object per `build()` call. */\nconst proxyHandler: ProxyHandler<BuilderFn> = {\n get(target, key) {\n if (typeof key !== \"string\") return undefined\n const cached = (target as unknown as Record<string, unknown>)[key]\n if (cached !== undefined) return cached\n // Parked chains can't be chained further — they're waiting for a call.\n if (target.state.pending !== undefined) return undefined\n const child = compileKey(target.state, key)\n if (child === undefined) return undefined\n Reflect.defineProperty(target, key, { configurable: false, value: child, writable: false })\n return child\n },\n}\n\nfunction build(state: BuilderState): StyleBuilder {\n // Two dedicated function shapes so V8 sees a stable signature on\n // each hot path — styling text vs. consuming an op arg are both\n // monomorphic after the build-time ternary.\n const fn = (\n state.pending === undefined\n ? function apply(text: string): string {\n return applyStyle(state, text)\n }\n : function applyOpCall(arg: Color | number | Style | undefined): StyleBuilder {\n return applyOp(fn, arg)\n }\n ) as BuilderFn\n fn.state = state\n fn.theme = state.theme\n return new Proxy(fn, proxyHandler) as unknown as StyleBuilder\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"callbacks-DcMBGQEO.mjs","names":[],"sources":["../src/markdown/code.ts","../src/markdown/list.ts","../src/markdown/table.ts","../src/markdown/callbacks.ts"],"sourcesContent":["import type { MarkdownCtx } from \"./renderer.ts\"\nimport type { MdCallbacks } from \"./types.ts\"\n\nimport { stringWidth } from \"@zaly/shared/ansi\"\nimport { formatText } from \"../layout/text.ts\"\n\n/**\n * Build the `code` callback. The returned closure captures ctx/style/highlighter\n * and renders each fenced block: syntax-highlight (if available), pad lines to\n * widest-content + 1, apply `mdCodeBlock` as a bg-only backdrop, and prefix an\n * optional title line from `title=\"...\"`.\n */\nexport function createCodeCallback(ctx: MarkdownCtx): NonNullable<MdCallbacks[\"code\"]> {\n const s = ctx.style\n return (text, meta) => {\n text = text.replace(/\\n+$/, \"\") // trim to avoid extra blank lines after the block\n const highlighted = ctx.highlight?.(text, meta?.language) ?? text\n\n // For highlighted output the per-token fgs would clash with the slot's\n // fg; override fg with `\"inherit\"` so only bg + attrs wrap each row\n // and shiki's per-token colors show through on top of the backdrop.\n const wrap = highlighted === text ? s.mdCodeBlock : s.mdCodeBlock.fg(\"inherit\")\n const hpad = 2\n const maxWidth = ctx.width\n const lines = formatText(`\\n${highlighted}\\n`, {\n width: maxWidth - hpad * 2,\n wrap: \"word\",\n })\n let width = Math.max(...lines.map(stringWidth)) + hpad * 2\n width = Math.min(width, maxWidth) // leave room for the border\n // Left-align with a fixed `hpad` of leading whitespace; pad the\n // right to fill the bg out to `width`. Centering would push short\n // lines toward the middle, which reads as visually misaligned code.\n // Lines wider than the available room (width − hpad) drop the\n // leading pad so the bg ends at the cap rather than overshooting.\n const padded = lines.map((line) => {\n const w = stringWidth(line)\n if (w >= width - hpad) return wrap(line)\n return wrap(`${\" \".repeat(hpad)}${line}${\" \".repeat(width - w - hpad)}`)\n })\n const titleLine = meta?.title === undefined ? \"\" : `${s.mdCodeBlockTitle(meta.title)}\\n`\n // Leading `\\n` guards against raw-text siblings that don't emit a\n // paragraph-wrap (e.g. some inline-only list items where the parser\n // drops the paragraph). Containers (`listItem`, document) collapse\n // `\\n{3,}` → `\\n\\n` so paragraph + code doesn't double up.\n return `\\n${titleLine}${padded.join(\"\\n\")}\\n\\n`\n }\n}\n","import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { MdCallbacks } from \"./types.ts\"\n\nimport { splitAnsi, stringWidth } from \"@zaly/shared/ansi\"\n\ninterface ListState {\n block: boolean\n items: string[]\n /** Formatted output, set when the list closes. The parent `listItem`\n * pulls it via `stack[depth+1]` and splices it onto its own body. */\n rendered?: string\n}\n\nconst BULLETS = [\"●\", \"○\", \"◆\", \"◇\"] as const\n\ntype ListCallbacks = Pick<MdCallbacks, \"list\" | \"listItem\">\n\n/**\n * Stack-based list renderer. Each depth has its own `ListState`. Inner\n * lists return `\"\"` and stash their formatted output on `state.rendered`;\n * the parent `listItem` pulls + splices, so inner output never reaches\n * the parent's `children` string. That keeps each level's loose-vs-tight\n * verdict independent — `children.endsWith(\"\\n\\n\")` is then the per-item\n * loose signal (parser only emits `<p>` for items in loose lists).\n *\n * Nested list lands at the end of its parent's body — `text, list, more`\n * is rare in real markdown and not worth the extra plumbing.\n */\nexport function createListCallbacks(ctx: RenderCtx): ListCallbacks {\n const s = ctx.style\n // Lazy-pushed on the first `listItem` at a given depth; consumed\n // either by the parent `listItem` (nested) or by `list(0)` (top).\n const stack: (ListState | undefined)[] = []\n\n return {\n list: (_children, meta) => {\n const state = stack[meta.depth]\n if (state === undefined || state.items.length === 0) return \"\"\n state.rendered = state.items.join(state.block ? \"\\n\\n\" : \"\\n\")\n if (meta.depth > 0) return \"\"\n // Top-level: defensive stack reset + block-contract `\\n\\n` trailer.\n stack.length = 0\n return `${state.rendered}\\n\\n`\n },\n\n listItem: (children, meta) => {\n let marker = s.mdListBullet(\n meta.ordered ? `${(meta.start ?? 1) + meta.index}.` : BULLETS[meta.depth % BULLETS.length]\n )\n if (meta.checked !== undefined) {\n const ref = meta.checked ? \"mdListChecked\" : \"mdListUnchecked\"\n marker += ` ${s.add(ref)(meta.checked ? \"[x]\" : \"[ ]\")}`\n }\n const indent = \" \".repeat(stringWidth(marker))\n // Pull nested list output (if any) off the stack.\n const nested = stack[meta.depth + 1]\n stack[meta.depth + 1] = undefined\n // Trailing `\\n\\n` = loose signal. Nested output is in `rendered`,\n // not `children`, so it can't pollute this check.\n const block = children.endsWith(\"\\n\\n\")\n const trimmed = children.replace(/\\s*\\n+$/, \"\").replace(/\\n{3,}/g, \"\\n\\n\")\n // Splice nested after the prose; loose item adds a blank-row gap.\n let body = trimmed\n if (nested?.rendered !== undefined) {\n const sep = block ? \"\\n\\n\" : \"\\n\"\n body = trimmed === \"\" ? nested.rendered : `${trimmed}${sep}${nested.rendered}`\n }\n const lines = splitAnsi(body)\n const content = lines\n .map((line, l) => {\n if (l === 0) return `${marker} ${line}`\n // Bare empty lines so loose `\\n\\n` separators stay clean.\n return line === \"\" ? \"\" : `${indent}${line}`\n })\n .join(\"\\n\")\n\n const state = (stack[meta.depth] ??= { block: false, items: [] })\n state.block ||= block\n state.items.push(content)\n return \"\"\n },\n }\n}\n","import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Layout } from \"../core/state.ts\"\nimport type { RowItem } from \"../layout/flex.ts\"\nimport type { MdCallbacks } from \"./types.ts\"\n\nimport { stringWidth } from \"@zaly/shared/ansi\"\nimport { allocateRow } from \"../layout/flex.ts\"\nimport { calcLayout, formatText } from \"../layout/text.ts\"\n\ntype CellAlign = \"left\" | \"center\" | \"right\"\n\ninterface TableCell {\n text: string\n align: CellAlign | undefined\n}\n\ninterface TableState {\n header: TableCell[][]\n body: TableCell[][]\n pending: TableCell[]\n pendingIsHeader: boolean\n}\n\ntype TableCallbacks = Pick<MdCallbacks, \"table\" | \"tbody\" | \"td\" | \"th\" | \"thead\" | \"tr\">\n\n/**\n * Build the table-related callbacks. They share a closure-local\n * `TableState` accumulator: `th`/`td` push cells, `tr` commits rows into\n * header or body, and `table` runs the final layout + reset. Tables can't\n * nest in markdown, so a single top-level slot is enough.\n */\nexport function createTableCallbacks(ctx: RenderCtx): TableCallbacks {\n const { style } = ctx\n let state: TableState | undefined\n const begin = (): TableState =>\n (state ??= { body: [], header: [], pending: [], pendingIsHeader: false })\n\n return {\n table: () => {\n // Children of th/td/tr/thead/tbody are empty strings; all content is\n // in `state`. Format, reset, emit.\n if (state === undefined) return \"\"\n const out = formatTable(state, ctx)\n state = undefined\n return `${out}\\n\\n`\n },\n\n tbody: () => \"\",\n\n td: (children, meta) => {\n const t = begin()\n t.pending.push({ align: meta?.align, text: children })\n t.pendingIsHeader = false\n return \"\"\n },\n\n th: (children, meta) => {\n const t = begin()\n t.pending.push({ align: meta?.align, text: style.mdTableHeader(children) })\n t.pendingIsHeader = true\n return \"\"\n },\n\n thead: () => \"\",\n\n tr: () => {\n if (state === undefined || state.pending.length === 0) return \"\"\n if (state.pendingIsHeader) state.header.push(state.pending)\n else state.body.push(state.pending)\n state.pending = []\n return \"\"\n },\n }\n}\n\nfunction formatTable(state: TableState, ctx: RenderCtx): string {\n const cols: Layout[] = []\n const cells = [...state.header, ...state.body]\n const colCount = Math.max(...cells.map((r) => r.length))\n\n // 1. Calculate min-content and max-content for each column\n for (let c = 0; c < colCount; c++) {\n for (const row of cells) {\n const cell = row[c] as TableCell | undefined\n if (!cell) continue // Safety guard for ragged rows\n const l = calcLayout(cell.text)\n cols[c] ??= { ...l }\n cols[c].width = Math.max(cols[c].width, l.width)\n cols[c].minWidth = Math.max(cols[c].minWidth, l.minWidth)\n }\n }\n const chromeWidth = 3 * colCount + 1\n\n const items: RowItem[] = cols.map((c) => ({\n flex: 1,\n intrinsicMin: c.minWidth,\n natural: c.width,\n }))\n\n const widths = allocateRow(items, { contentWidth: ctx.width - chromeWidth, gap: 0 })\n\n // 4. Render output string using the exact final Column Widths\n // Pre-style each piece of chrome once. Each column span on a rule row is\n // `widths[i] + 2` dashes (one cell of padding on each side of the cell).\n const style = ctx.style\n const v = style.mdTable(\"│\")\n const ruleRow = (left: string, mid: string, right: string): string =>\n style.mdTable(left + widths.map((w) => \"─\".repeat(w + 2)).join(mid) + right)\n const top = ruleRow(\"┌\", \"┬\", \"┐\")\n const sep = ruleRow(\"├\", \"┼\", \"┤\")\n const bot = ruleRow(\"└\", \"┴\", \"┘\")\n\n const renderRow = (row: TableCell[]): string => {\n const formatted = row.map((cell, c) =>\n formatText(cell.text, { indent: false, width: widths[c], wrapBg: false })\n )\n const rows: string[] = []\n const rowCount = Math.max(...formatted.map((r) => r.length))\n for (let r = 0; r < rowCount; r++) {\n const line: string[] = []\n for (let c = 0; c < colCount; c++) {\n const t = formatted[c]?.[r] ?? \"\"\n line.push(padCell(t, widths[c], row[c]?.align))\n }\n rows.push(`${v} ${line.join(` ${v} `)} ${v}`)\n }\n\n return rows.join(\"\\n\")\n }\n\n const lines: string[] = [top]\n for (const row of state.header) lines.push(renderRow(row))\n if (state.header.length > 0 && state.body.length > 0) lines.push(sep)\n for (const row of state.body) lines.push(renderRow(row))\n lines.push(bot)\n return lines.join(\"\\n\")\n}\n\nfunction padCell(text: string, width: number, align: CellAlign | undefined): string {\n const slack = Math.max(0, width - stringWidth(text))\n if (align === \"right\") return \" \".repeat(slack) + text\n if (align === \"center\") {\n const left = Math.floor(slack / 2)\n return \" \".repeat(left) + text + \" \".repeat(slack - left)\n }\n return text + \" \".repeat(slack)\n}\n","import type { AnyStyle } from \"../style/types.ts\"\nimport type { MarkdownCtx } from \"./renderer.ts\"\nimport type { MdCallbacks } from \"./types.ts\"\n\nimport { stringWidth } from \"@zaly/shared/ansi\"\nimport { capitalize } from \"../layout/text.ts\"\nimport { hyperlink } from \"../style/ansi.ts\"\nimport { createCodeCallback } from \"./code.ts\"\nimport { createListCallbacks } from \"./list.ts\"\nimport { createTableCallbacks } from \"./table.ts\"\n\nconst icons = {\n hr: \"─\",\n quote: \"┃\",\n} as const\n\ntype AlertType = \"NOTE\" | \"TIP\" | \"WARNING\" | \"IMPORTANT\" | \"CAUTION\"\nconst alerts: Record<AlertType, { icon: string; style: AnyStyle }> = {\n CAUTION: { icon: \"✖ \", style: \"error\" },\n IMPORTANT: { icon: \"‼\", style: \"syntaxConstant\" },\n NOTE: { icon: \"ℹ \", style: \"info\" },\n TIP: { icon: \"🛈 \", style: \"success\" },\n WARNING: { icon: \"⚠\", style: \"warn\" },\n}\n\nconst alertRe = /^\\s*\\[!(NOTE|TIP|WARNING|IMPORTANT|CAUTION)\\]\\s*$/\n\n/**\n * Build the `MdCallbacks` that drive the theme-aware rendering. Exposed so\n * callers can invoke `renderMarkdown` directly when they need the string\n * output without the wrapping `Markdown` node (e.g. to embed markdown inside\n * a custom `Text` content function).\n * @internal\n */\nexport function createCallbacks(ctx: MarkdownCtx): MdCallbacks {\n const s = ctx.style\n\n return {\n blockquote: (children) => {\n const lines = children.replace(/\\n+$/, \"\").split(\"\\n\")\n let lineStyle: AnyStyle = \"mdQuote\"\n\n const m = lines.length >= 1 ? lines[0].match(alertRe) : undefined\n if (m) {\n const alertType = m[1] as AlertType\n const alert = alerts[alertType]\n lineStyle = alert.style\n const name = capitalize(alertType.toLowerCase())\n lines[0] = s.add(lineStyle)(`${alert.icon} ${name}`)\n }\n\n // Inner blocks (typically a paragraph) end with trailing newlines; if\n // we prefix those empty lines with \"│ \" they render as styled empty\n // rows between the last line of the quote and the block separator.\n // Trim first so the quote stops cleanly.\n const prefixed = lines.map((line) => `${s.add(lineStyle)(icons.quote)} ${line}`).join(\"\\n\")\n return `${prefixed}\\n\\n`\n },\n\n code: createCodeCallback(ctx),\n\n codespan: (text) => s.mdCode(text),\n\n emphasis: (children) => s.mdItalic(children),\n\n heading: (children, { level }) => {\n const width = ctx.width\n const padded = children\n .split(\"\\n\")\n .map((line) => line + \" \".repeat(Math.max(0, width - stringWidth(line))))\n .join(\"\\n\")\n return `${s.add(`mdHeading${level}`)(padded)}\\n\\n`\n },\n\n hr: () => `${s.mdHr(icons.hr.repeat(ctx.width))}\\n\\n`,\n\n html: (children) => children,\n\n link: (children, { href }) => hyperlink(href, s.mdLink(children)),\n\n paragraph: (children) => `${children}\\n\\n`,\n\n strikethrough: (children) => s.mdStrikethrough(children),\n\n strong: (children) => s.mdBold(children),\n\n ...createListCallbacks(ctx),\n ...createTableCallbacks(ctx),\n }\n}\n"],"mappings":"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"}
|