silvery 0.21.1 → 0.23.1
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/dist/{Text-BRf-59j2.mjs → Text-4tWKabKH.mjs} +46 -46
- package/dist/Text-4tWKabKH.mjs.map +1 -0
- package/dist/{ag-BeFC4S2N.mjs → ag-B-7XAHL8.mjs} +42 -19
- package/dist/ag-B-7XAHL8.mjs.map +1 -0
- package/dist/{animation-N8MFybTk.mjs → animation-CZ4x2R7C.mjs} +1 -1
- package/dist/{animation-N8MFybTk.mjs.map → animation-CZ4x2R7C.mjs.map} +1 -1
- package/dist/{ansi-C6Qs1Wn2.mjs → ansi-CLmIMnop.mjs} +1 -1
- package/dist/{ansi-C6Qs1Wn2.mjs.map → ansi-CLmIMnop.mjs.map} +1 -1
- package/dist/{ansi-CBkam1ty.d.mts → ansi-qYRTDp5m.d.mts} +1 -1
- package/dist/{ansi-CBkam1ty.d.mts.map → ansi-qYRTDp5m.d.mts.map} +1 -1
- package/dist/chain-bridge-B7LNJwVF.mjs +4149 -0
- package/dist/chain-bridge-B7LNJwVF.mjs.map +1 -0
- package/dist/cli-CuNV0hTE.mjs +4 -0
- package/dist/{context-BU5LkkIy.mjs → context-CEhuD1R_.mjs} +1 -1
- package/dist/{context-BU5LkkIy.mjs.map → context-CEhuD1R_.mjs.map} +1 -1
- package/dist/devtools-BuTq07Zb.mjs +2 -0
- package/dist/{devtools-9zfhpFyG.mjs → devtools-akTjVxxX.mjs} +3 -3
- package/dist/{devtools-9zfhpFyG.mjs.map → devtools-akTjVxxX.mjs.map} +1 -1
- package/dist/{easing-B0oZKDki.d.mts → easing-8OlNopWv.d.mts} +1 -1
- package/dist/{easing-B0oZKDki.d.mts.map → easing-8OlNopWv.d.mts.map} +1 -1
- package/dist/{eta-DGOuC8yU.mjs → eta-CPZ45g_P.mjs} +1 -1
- package/dist/{eta-DGOuC8yU.mjs.map → eta-CPZ45g_P.mjs.map} +1 -1
- package/dist/{flexily-zero-adapter-D6hcFgrH.mjs → flexily-zero-adapter-DktX3HsX.mjs} +1 -1
- package/dist/{flexily-zero-adapter-CEJOcbNp.mjs → flexily-zero-adapter-VoBGHG14.mjs} +1 -1
- package/dist/{flexily-zero-adapter-CEJOcbNp.mjs.map → flexily-zero-adapter-VoBGHG14.mjs.map} +1 -1
- package/dist/hit-registry-DRV2ig-Y.d.mts +71 -0
- package/dist/hit-registry-DRV2ig-Y.d.mts.map +1 -0
- package/dist/{image-1nRyKa60.mjs → image-o2WpbrD1.mjs} +7 -7
- package/dist/{image-1nRyKa60.mjs.map → image-o2WpbrD1.mjs.map} +1 -1
- package/dist/{index-2E1jYgak.d.mts → index-3vAxA_EQ.d.mts} +35 -12
- package/dist/index-3vAxA_EQ.d.mts.map +1 -0
- package/dist/{index-DnuadDNL.d.mts → index-BKujGENR.d.mts} +8590 -11173
- package/dist/index-BKujGENR.d.mts.map +1 -0
- package/dist/{index-Bi4Jdz5g.d.mts → index-C6oOd9eE.d.mts} +2 -2
- package/dist/{index-Bi4Jdz5g.d.mts.map → index-C6oOd9eE.d.mts.map} +1 -1
- package/dist/{index-Dg1YaeJb.d.mts → index-DhYF3m7V.d.mts} +2 -2
- package/dist/{index-Dg1YaeJb.d.mts.map → index-DhYF3m7V.d.mts.map} +1 -1
- package/dist/index.d.mts +12 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +18 -17
- package/dist/index.mjs.map +1 -1
- package/dist/{layout-engine-Ca_nbtfL.mjs → layout-engine-BYp49XPD.mjs} +3 -3
- package/dist/{layout-engine-Ca_nbtfL.mjs.map → layout-engine-BYp49XPD.mjs.map} +1 -1
- package/dist/{layout-engine-CgsoBRIn.mjs → layout-engine-D0dXw5fr.mjs} +1 -1
- package/dist/{layout-signals-Dch2EiCy.mjs → layout-signals-uQadGDmO.mjs} +2 -2
- package/dist/layout-signals-uQadGDmO.mjs.map +1 -0
- package/dist/{mouse-events-hnbJZRwK.mjs → mouse-events-Pg-XKR3T.mjs} +35 -6
- package/dist/mouse-events-Pg-XKR3T.mjs.map +1 -0
- package/dist/{bound-term-BumfuXXW.d.mts → mouse-events-UoUWNIdS.d.mts} +559 -401
- package/dist/mouse-events-UoUWNIdS.d.mts.map +1 -0
- package/dist/{multi-progress-CaXTuL9G.mjs → multi-progress-Bvd1BYED.mjs} +3 -3
- package/dist/{multi-progress-CaXTuL9G.mjs.map → multi-progress-Bvd1BYED.mjs.map} +1 -1
- package/dist/{multi-progress-Bg4ngK80.d.mts → multi-progress-DPOCjomS.d.mts} +2 -2
- package/dist/{multi-progress-Bg4ngK80.d.mts.map → multi-progress-DPOCjomS.d.mts.map} +1 -1
- package/dist/{node-BiFu8I9Y.mjs → node-Cl-kzQcl.mjs} +1 -1
- package/dist/{node-BiFu8I9Y.mjs.map → node-Cl-kzQcl.mjs.map} +1 -1
- package/dist/{progress-B_UPy6zk.mjs → progress-1r6M_ZAP.mjs} +4 -4
- package/dist/{progress-B_UPy6zk.mjs.map → progress-1r6M_ZAP.mjs.map} +1 -1
- package/dist/{progress-bar-DmIMPdL0.mjs → progress-bar-DzW1DzNj.mjs} +4 -4
- package/dist/{progress-bar-DmIMPdL0.mjs.map → progress-bar-DzW1DzNj.mjs.map} +1 -1
- package/dist/{reconciler-NBDSEm8k.mjs → reconciler-lsTL1y8i.mjs} +111 -110
- package/dist/reconciler-lsTL1y8i.mjs.map +1 -0
- package/dist/{render-string-B4h4SmK7.mjs → render-string-2ZcV8n3B.mjs} +15 -11
- package/dist/render-string-2ZcV8n3B.mjs.map +1 -0
- package/dist/{render-string-BntLj7Xq.mjs → render-string-BJZqo5Rr.mjs} +1 -1
- package/dist/runtime.d.mts +3 -2
- package/dist/runtime.mjs +3 -2
- package/dist/{schemes-DYt2ushj.mjs → schemes-C4SUgVea.mjs} +2 -2
- package/dist/{schemes-DYt2ushj.mjs.map → schemes-C4SUgVea.mjs.map} +1 -1
- package/dist/{spinner-Py8_-hn9.mjs → spinner-Ck3SdCpW.mjs} +3 -3
- package/dist/{spinner-Py8_-hn9.mjs.map → spinner-Ck3SdCpW.mjs.map} +1 -1
- package/dist/{spinner-CLgzJ_QF.d.mts → spinner-CpcGtQ9L.d.mts} +2 -2
- package/dist/{spinner-CLgzJ_QF.d.mts.map → spinner-CpcGtQ9L.d.mts.map} +1 -1
- package/dist/{src-WeA_J4BV.mjs → src-B6MuVlOK.mjs} +88 -45
- package/dist/src-B6MuVlOK.mjs.map +1 -0
- package/dist/{src-CbhWmUnF.mjs → src-BZOfzNeo.mjs} +1484 -1488
- package/dist/src-BZOfzNeo.mjs.map +1 -0
- package/dist/{src-B9S_woYc.mjs → src-ChuXo--x.mjs} +20290 -23261
- package/dist/src-ChuXo--x.mjs.map +1 -0
- package/dist/{src-Dvq-s8iD.mjs → src-DdGaRDi9.mjs} +3 -3
- package/dist/{src-Dvq-s8iD.mjs.map → src-DdGaRDi9.mjs.map} +1 -1
- package/dist/{src-Oe6x5PrS.mjs → src-DorsnS70.mjs} +190 -76
- package/dist/src-DorsnS70.mjs.map +1 -0
- package/dist/{steps-DYrzCUCK.d.mts → steps-DV34gm_Z.d.mts} +1 -1
- package/dist/{steps-DYrzCUCK.d.mts.map → steps-DV34gm_Z.d.mts.map} +1 -1
- package/dist/{svg-DhxQkz-O.mjs → svg-NmV9dgB9.mjs} +1 -1
- package/dist/{svg-DhxQkz-O.mjs.map → svg-NmV9dgB9.mjs.map} +1 -1
- package/dist/{svg-Hk7lIl4F.d.mts → svg-wvIEu-RS.d.mts} +1 -1
- package/dist/{svg-Hk7lIl4F.d.mts.map → svg-wvIEu-RS.d.mts.map} +1 -1
- package/dist/term.d.mts +3 -3
- package/dist/term.mjs +4 -4
- package/dist/test.d.mts +673 -0
- package/dist/test.d.mts.map +1 -0
- package/dist/test.mjs +2829 -0
- package/dist/test.mjs.map +1 -0
- package/dist/theme.d.mts +2 -2
- package/dist/theme.d.mts.map +1 -1
- package/dist/theme.mjs +3 -3
- package/dist/{types-Bx-XZNbE.d.mts → types-VyreAPAB.d.mts} +1 -1
- package/dist/{types-Bx-XZNbE.d.mts.map → types-VyreAPAB.d.mts.map} +1 -1
- package/dist/ui/animation.d.mts +2 -2
- package/dist/ui/animation.mjs +1 -1
- package/dist/ui/ansi.d.mts +1 -1
- package/dist/ui/ansi.mjs +1 -1
- package/dist/ui/cli.d.mts +3 -3
- package/dist/ui/cli.mjs +5 -5
- package/dist/ui/image.d.mts +1 -1
- package/dist/ui/image.mjs +1 -1
- package/dist/ui/progress.d.mts +4 -4
- package/dist/ui/progress.mjs +4 -4
- package/dist/ui/react.d.mts +1 -1
- package/dist/ui/react.mjs +2 -2
- package/dist/ui/recording-chrome-react.d.mts +1 -1
- package/dist/ui/recording-chrome-react.mjs +2 -2
- package/dist/ui/recording-chrome.d.mts +1 -1
- package/dist/ui/recording-chrome.mjs +1 -1
- package/dist/ui/utils.mjs +1 -1
- package/dist/ui/wrappers.d.mts +2 -2
- package/dist/ui/wrappers.mjs +1 -1
- package/dist/ui.d.mts +6 -6
- package/dist/ui.mjs +7 -7
- package/dist/{ansi-OYRLxxZQ.mjs → unicode-X43-fdGF.mjs} +7317 -6909
- package/dist/unicode-X43-fdGF.mjs.map +1 -0
- package/dist/{useLatest-DC8i7guK.d.mts → useLatest-D9p0ZDAC.d.mts} +2 -2
- package/dist/{useLatest-DC8i7guK.d.mts.map → useLatest-D9p0ZDAC.d.mts.map} +1 -1
- package/dist/{useLayout-BKsQl2Or.mjs → useLayout-Cx01rHVI.mjs} +4 -4
- package/dist/{useLayout-BKsQl2Or.mjs.map → useLayout-Cx01rHVI.mjs.map} +1 -1
- package/dist/{with-text-input-DG4f7JII.d.mts → with-text-input-CW8MR9Th.d.mts} +3 -3
- package/dist/{with-text-input-DG4f7JII.d.mts.map → with-text-input-CW8MR9Th.d.mts.map} +1 -1
- package/dist/wrap-measurer-registration-DNBmtFNM.d.mts +3106 -0
- package/dist/wrap-measurer-registration-DNBmtFNM.d.mts.map +1 -0
- package/dist/{wrapper-D7gNSsgf.mjs → wrapper-DpMauwdI.mjs} +15 -17
- package/dist/wrapper-DpMauwdI.mjs.map +1 -0
- package/dist/{wrappers-CypAzrMO.mjs → wrappers-DHMzvbRo.mjs} +6 -6
- package/dist/{wrappers-CypAzrMO.mjs.map → wrappers-DHMzvbRo.mjs.map} +1 -1
- package/dist/yoga-adapter-B-DCP4Bx.mjs +2 -0
- package/dist/{yoga-adapter-SsEIqMc1.mjs → yoga-adapter-CB_7pLyl.mjs} +2 -2
- package/dist/{yoga-adapter-SsEIqMc1.mjs.map → yoga-adapter-CB_7pLyl.mjs.map} +1 -1
- package/package.json +21 -16
- package/dist/Text-BRf-59j2.mjs.map +0 -1
- package/dist/ag-BeFC4S2N.mjs.map +0 -1
- package/dist/ansi-OYRLxxZQ.mjs.map +0 -1
- package/dist/bound-term-BumfuXXW.d.mts.map +0 -1
- package/dist/cli-DG6zsfsS.mjs +0 -4
- package/dist/devtools-nmPUmYU_.mjs +0 -2
- package/dist/index-2E1jYgak.d.mts.map +0 -1
- package/dist/index-DnuadDNL.d.mts.map +0 -1
- package/dist/layout-signals-Dch2EiCy.mjs.map +0 -1
- package/dist/mouse-events-hnbJZRwK.mjs.map +0 -1
- package/dist/reconciler-NBDSEm8k.mjs.map +0 -1
- package/dist/render-string-B4h4SmK7.mjs.map +0 -1
- package/dist/src-B9S_woYc.mjs.map +0 -1
- package/dist/src-CbhWmUnF.mjs.map +0 -1
- package/dist/src-Oe6x5PrS.mjs.map +0 -1
- package/dist/src-WeA_J4BV.mjs.map +0 -1
- package/dist/ui/display.d.mts +0 -35
- package/dist/ui/display.d.mts.map +0 -1
- package/dist/ui/display.mjs +0 -123
- package/dist/ui/display.mjs.map +0 -1
- package/dist/ui/input.d.mts +0 -184
- package/dist/ui/input.d.mts.map +0 -1
- package/dist/ui/input.mjs +0 -283
- package/dist/ui/input.mjs.map +0 -1
- package/dist/wrapper-D7gNSsgf.mjs.map +0 -1
- package/dist/yoga-adapter-1ex8r0ws.mjs +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrappers-CypAzrMO.mjs","names":[],"sources":["../packages/ag-react/src/ui/wrappers/with-spinner.ts","../packages/ag-react/src/ui/wrappers/wrap-generator.ts","../packages/ag-react/src/ui/wrappers/wrap-emitter.ts","../packages/ag-react/src/ui/wrappers/with-select.ts","../packages/ag-react/src/ui/wrappers/with-text-input.ts"],"sourcesContent":["/**\n * withSpinner - Wrap promises with an animated spinner\n */\n\nimport type { WithSpinnerOptions } from \"../types.js\"\nimport { Spinner } from \"../cli/spinner\"\n\n/**\n * Wrap a promise with an animated spinner\n *\n * @example\n * ```ts\n * // Simple usage\n * const data = await withSpinner(fetchData(), \"Loading data...\");\n *\n * // With options\n * const result = await withSpinner(\n * processFiles(),\n * \"Processing...\",\n * { style: \"arc\", clearOnComplete: true }\n * );\n *\n * // With dynamic text\n * const result = await withSpinner(\n * longOperation(),\n * (elapsed) => `Processing... (${elapsed}s)`\n * );\n * ```\n */\nexport async function withSpinner<T>(\n promise: Promise<T> | (() => T | Promise<T>),\n text: string | ((elapsedSeconds: number) => string),\n options: WithSpinnerOptions = {},\n): Promise<T> {\n const spinner = new Spinner({\n text: typeof text === \"string\" ? text : text(0),\n style: options.style,\n color: options.color,\n })\n\n let timer: ReturnType<typeof setInterval> | null = null\n const startTime = Date.now()\n\n spinner.start()\n\n // Update text if dynamic\n if (typeof text === \"function\") {\n timer = setInterval(() => {\n const elapsed = Math.floor((Date.now() - startTime) / 1000)\n spinner.currentText = text(elapsed)\n }, 1000)\n }\n\n try {\n const result = await (typeof promise === \"function\" ? promise() : promise)\n\n if (timer) clearInterval(timer)\n\n if (options.clearOnComplete) {\n spinner.stop()\n } else {\n spinner.succeed()\n }\n\n return result\n } catch (error) {\n if (timer) clearInterval(timer)\n spinner.fail(error instanceof Error ? error.message : \"Failed\")\n throw error\n }\n}\n\n/**\n * Attach a spinner to a promise for manual control\n * Returns [result, spinner] tuple for custom control\n *\n * @example\n * ```ts\n * const [promise, spinner] = attachSpinner(fetchData(), \"Loading...\");\n * spinner.text = \"Still loading...\";\n * const result = await promise;\n * spinner.succeed(\"Loaded!\");\n * ```\n */\nexport function attachSpinner<T>(\n promise: Promise<T>,\n text: string,\n options: WithSpinnerOptions = {},\n): [Promise<T>, Spinner] {\n const spinner = new Spinner({\n text,\n style: options.style,\n color: options.color,\n })\n\n spinner.start()\n\n async function wrapPromise(): Promise<T> {\n try {\n return await promise\n } catch (error) {\n spinner.fail(error instanceof Error ? error.message : \"Failed\")\n throw error\n }\n }\n\n return [wrapPromise(), spinner]\n}\n","/**\n * wrapGenerator - Consume a generator while showing progress\n */\n\nimport type { ProgressGenerator } from \"../types.js\"\nimport { ProgressBar } from \"../cli/progress-bar\"\nimport { CURSOR_HIDE, CURSOR_SHOW, write, isTTY } from \"../cli/ansi\"\n\n/**\n * Consume a progress generator while displaying progress\n *\n * @example\n * ```ts\n * // Wrap existing generator (like evaluateAllRules())\n * await wrapGenerator(evaluateAllRules(), \"Evaluating rules\");\n *\n * // With custom format\n * await wrapGenerator(\n * processItems(),\n * ({ current, total }) => `Processing: ${current}/${total}`\n * );\n *\n * // Get the generator's return value\n * const result = await wrapGenerator(generatorWithReturn(), \"Processing\");\n * ```\n */\nexport async function wrapGenerator<T>(\n generator: ProgressGenerator<T>,\n textOrFormat: string | ((progress: { current: number; total: number }) => string),\n options: { clearOnComplete?: boolean } = {},\n): Promise<T> {\n const stream = process.stdout\n const isTty = isTTY(stream)\n\n const isCustomFormat = typeof textOrFormat === \"function\"\n const label = isCustomFormat ? \"\" : textOrFormat\n\n const bar = new ProgressBar({\n format: label ? `${label} [:bar] :current/:total :percent` : \":bar :current/:total :percent\",\n hideCursor: true,\n })\n\n if (isTty) {\n write(CURSOR_HIDE, stream)\n }\n\n let started = false\n let result: IteratorResult<{ current: number; total: number }, T>\n\n try {\n // Consume the generator\n while (true) {\n result = generator.next()\n\n if (result.done) {\n break\n }\n\n const { current, total } = result.value\n\n if (!started) {\n bar.start(current, total)\n started = true\n } else {\n bar.update(current)\n }\n }\n\n // Stop bar\n if (started) {\n bar.stop(options.clearOnComplete)\n }\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n\n return result.value\n } catch (error) {\n if (started) {\n bar.stop()\n }\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n throw error\n }\n}\n\n/**\n * Create an async iterable wrapper that shows progress\n *\n * @example\n * ```ts\n * const items = [1, 2, 3, 4, 5];\n * for await (const item of withIterableProgress(items, \"Processing\")) {\n * await processItem(item);\n * }\n * ```\n */\nexport async function* withIterableProgress<T>(\n iterable: Iterable<T> | AsyncIterable<T>,\n label: string,\n options: { clearOnComplete?: boolean } = {},\n): AsyncGenerator<T, void, unknown> {\n const stream = process.stdout\n const isTty = isTTY(stream)\n\n // Try to get length if array\n const items = Array.isArray(iterable) ? iterable : null\n const total = items?.length ?? 0\n\n const bar = new ProgressBar({\n format: `${label} [:bar] :current/:total :percent`,\n total,\n hideCursor: true,\n })\n\n if (isTty) {\n write(CURSOR_HIDE, stream)\n }\n\n let current = 0\n bar.start(0, total)\n\n try {\n for await (const item of iterable as AsyncIterable<T>) {\n yield item\n current++\n bar.update(current)\n }\n\n bar.stop(options.clearOnComplete)\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n } catch (error) {\n bar.stop()\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n throw error\n }\n}\n","/**\n * wrapEmitter - Track EventEmitter state changes with progress indicators\n */\n\nimport type { EventEmitter } from \"events\"\nimport { Spinner } from \"../cli/spinner\"\n\n/** Event handler configuration */\ninterface EventConfig {\n /** Display text for this event */\n text?: string\n /** Dynamic text based on event data */\n getText?: (data: unknown) => string\n /** Mark spinner as succeeded */\n succeed?: boolean\n /** Mark spinner as failed */\n fail?: boolean\n /** Stop tracking */\n stop?: boolean\n}\n\n/** Configuration for wrapEmitter */\ninterface WrapEmitterConfig {\n /** Event handlers */\n events: Record<string, EventConfig>\n /** Initial text */\n initialText?: string\n}\n\n/**\n * Track EventEmitter state changes with a spinner\n *\n * @example\n * ```ts\n * const stop = wrapEmitter(syncManager, {\n * initialText: \"Starting sync...\",\n * events: {\n * 'ready': { text: \"Watcher ready\", succeed: true },\n * 'state-change': { getText: (s) => `State: ${s}` },\n * 'error': { fail: true },\n * 'idle': { stop: true }\n * }\n * });\n *\n * // Later, to stop manually\n * stop();\n * ```\n */\nexport function wrapEmitter(emitter: EventEmitter, config: WrapEmitterConfig): () => void {\n const spinner = new Spinner(config.initialText ?? \"\")\n const handlers: Map<string, (...args: unknown[]) => void> = new Map()\n\n spinner.start()\n\n // Set up event handlers\n for (const [eventName, eventConfig] of Object.entries(config.events)) {\n const handler = (data: unknown) => {\n // Update text\n if (eventConfig.getText) {\n spinner.currentText = eventConfig.getText(data)\n } else if (eventConfig.text) {\n spinner.currentText = eventConfig.text\n }\n\n // Handle terminal states\n if (eventConfig.succeed) {\n spinner.succeed()\n cleanup()\n } else if (eventConfig.fail) {\n const message = data instanceof Error ? data.message : String(data ?? \"Failed\")\n spinner.fail(message)\n cleanup()\n } else if (eventConfig.stop) {\n spinner.stop()\n cleanup()\n }\n }\n\n handlers.set(eventName, handler)\n emitter.on(eventName, handler)\n }\n\n // Cleanup function\n function cleanup() {\n for (const [eventName, handler] of handlers) {\n emitter.off(eventName, handler)\n }\n handlers.clear()\n }\n\n // Return stop function\n return () => {\n spinner.stop()\n cleanup()\n }\n}\n\n/**\n * Wait for an EventEmitter to emit a specific event\n * Shows a spinner while waiting\n *\n * @example\n * ```ts\n * await waitForEvent(syncManager, \"ready\", \"Waiting for watcher...\");\n * ```\n */\nexport async function waitForEvent(\n emitter: EventEmitter,\n eventName: string,\n text: string,\n options: {\n errorEvent?: string\n timeout?: number\n } = {},\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const spinner = new Spinner(text)\n spinner.start()\n\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const cleanup = () => {\n emitter.off(eventName, successHandler)\n if (options.errorEvent) {\n emitter.off(options.errorEvent, errorHandler)\n }\n if (timer) {\n clearTimeout(timer)\n }\n }\n\n const successHandler = (data: unknown) => {\n cleanup()\n spinner.succeed()\n resolve(data)\n }\n\n const errorHandler = (error: unknown) => {\n cleanup()\n spinner.fail(error instanceof Error ? error.message : \"Error\")\n reject(error instanceof Error ? error : new Error(String(error)))\n }\n\n emitter.once(eventName, successHandler)\n\n if (options.errorEvent) {\n emitter.once(options.errorEvent, errorHandler)\n }\n\n if (options.timeout) {\n timer = setTimeout(() => {\n cleanup()\n spinner.fail(\"Timeout\")\n reject(new Error(`Timeout waiting for ${eventName}`))\n }, options.timeout)\n }\n })\n}\n","/**\n * withSelect - Interactive CLI selection list\n */\n\nimport chalk from \"@silvery/ink/chalk\"\nimport { createModes } from \"@silvery/ag-term\"\nimport type { SelectOption, WithSelectOptions } from \"../types.js\"\nimport {\n CURSOR_HIDE,\n CURSOR_SHOW,\n CURSOR_TO_START,\n CLEAR_LINE_END,\n cursorUp,\n write,\n isTTY,\n} from \"../cli/ansi\"\n\n/**\n * Display an interactive selection list in the terminal\n *\n * @example\n * ```ts\n * // Simple usage\n * const color = await withSelect(\"Choose a color:\", [\n * { label: \"Red\", value: \"red\" },\n * { label: \"Green\", value: \"green\" },\n * { label: \"Blue\", value: \"blue\" },\n * ]);\n *\n * // With options\n * const result = await withSelect(\n * \"Select item:\",\n * options,\n * { initial: 2, maxVisible: 5 }\n * );\n * ```\n */\nexport async function withSelect<T>(\n prompt: string,\n options: SelectOption<T>[],\n selectOptions: WithSelectOptions = {},\n): Promise<T> {\n const { initial = 0, maxVisible = 10 } = selectOptions\n const stream = process.stdout\n const stdin = process.stdin\n\n if (!isTTY(stream) || !stdin.isTTY) {\n // Non-interactive mode: return first option or initial\n return options[initial]?.value ?? options[0]!.value\n }\n\n return new Promise((resolve, reject) => {\n let highlightIndex = Math.min(Math.max(0, initial), options.length - 1)\n let linesRendered = 0\n\n // Raw mode via the Modes owner — its per-stream refcount composes with\n // any host session owner on this stdin; never stdin.setRawMode directly\n // (CLAUDE.md \"Anti-pattern: wasRaw\").\n const modes = createModes({ write: (data) => write(data, stream), stdin })\n modes.rawMode(true)\n stdin.resume()\n stdin.setEncoding(\"utf8\")\n\n // Hide cursor\n write(CURSOR_HIDE, stream)\n\n function render() {\n // Clear previously rendered lines\n if (linesRendered > 0) {\n write(cursorUp(linesRendered), stream)\n }\n\n // Calculate scroll window\n const scrollOffset = Math.max(\n 0,\n Math.min(highlightIndex - Math.floor(maxVisible / 2), options.length - maxVisible),\n )\n const visibleCount = Math.min(maxVisible, options.length)\n const visibleOptions = options.slice(scrollOffset, scrollOffset + visibleCount)\n const hasMoreAbove = scrollOffset > 0\n const hasMoreBelow = scrollOffset + visibleCount < options.length\n\n // Render prompt\n write(`${CURSOR_TO_START}${chalk.bold(prompt)}${CLEAR_LINE_END}\\n`, stream)\n\n let lines = 1\n\n // Render scroll indicator (above)\n if (hasMoreAbove) {\n write(`${CURSOR_TO_START} ${chalk.dim(\"...\")}${CLEAR_LINE_END}\\n`, stream)\n lines++\n }\n\n // Render options\n for (let i = 0; i < visibleOptions.length; i++) {\n const option = visibleOptions[i]\n const actualIndex = scrollOffset + i\n const isHighlighted = actualIndex === highlightIndex\n\n const indicator = isHighlighted ? chalk.cyan(\">\") : \" \"\n const label = isHighlighted ? chalk.cyan(option!.label) : option!.label\n\n write(`${CURSOR_TO_START}${indicator} ${label}${CLEAR_LINE_END}\\n`, stream)\n lines++\n }\n\n // Render scroll indicator (below)\n if (hasMoreBelow) {\n write(`${CURSOR_TO_START} ${chalk.dim(\"...\")}${CLEAR_LINE_END}\\n`, stream)\n lines++\n }\n\n linesRendered = lines\n }\n\n function cleanup() {\n modes[Symbol.dispose]()\n stdin.pause()\n stdin.removeListener(\"data\", onKeypress)\n write(CURSOR_SHOW, stream)\n }\n\n function onKeypress(key: string) {\n // Handle key sequences\n const keyCode = key.charCodeAt(0)\n\n // Ctrl+C\n if (key === \"\\x03\") {\n cleanup()\n reject(new Error(\"User cancelled\"))\n return\n }\n\n // Enter/Return\n if (key === \"\\r\" || key === \"\\n\") {\n cleanup()\n resolve(options[highlightIndex]!.value)\n return\n }\n\n // Escape\n if (key === \"\\x1b\" && key.length === 1) {\n cleanup()\n reject(new Error(\"User cancelled\"))\n return\n }\n\n // Arrow keys (escape sequences)\n if (key.startsWith(\"\\x1b[\")) {\n const code = key.slice(2)\n if (code === \"A\") {\n // Up arrow\n highlightIndex = Math.max(0, highlightIndex - 1)\n render()\n } else if (code === \"B\") {\n // Down arrow\n highlightIndex = Math.min(options.length - 1, highlightIndex + 1)\n render()\n }\n return\n }\n\n // j/k vim keys\n if (key === \"j\" || key === \"J\") {\n highlightIndex = Math.min(options.length - 1, highlightIndex + 1)\n render()\n return\n }\n if (key === \"k\" || key === \"K\") {\n highlightIndex = Math.max(0, highlightIndex - 1)\n render()\n return\n }\n\n // Space to select (optional alternative to Enter)\n if (key === \" \") {\n cleanup()\n resolve(options[highlightIndex]!.value)\n return\n }\n }\n\n stdin.on(\"data\", onKeypress)\n render()\n })\n}\n\n/**\n * Create a reusable select instance for multiple selections\n *\n * @example\n * ```ts\n * const select = createSelect({\n * maxVisible: 5,\n * });\n *\n * const first = await select(\"Choose first:\", options1);\n * const second = await select(\"Choose second:\", options2);\n * ```\n */\nexport function createSelect(\n defaultOptions: WithSelectOptions = {},\n): <T>(prompt: string, options: SelectOption<T>[], overrides?: WithSelectOptions) => Promise<T> {\n return <T>(prompt: string, options: SelectOption<T>[], overrides: WithSelectOptions = {}) =>\n withSelect(prompt, options, { ...defaultOptions, ...overrides })\n}\n","/**\n * withTextInput - CLI wrapper for text input prompts\n */\n\nimport chalk from \"@silvery/ink/chalk\"\nimport { createModes } from \"@silvery/ag-term\"\nimport type { TextInputOptions } from \"../types.js\"\nimport {\n CURSOR_HIDE,\n CURSOR_SHOW,\n CURSOR_TO_START,\n CLEAR_LINE_END,\n write,\n isTTY,\n} from \"../cli/ansi\"\n\n/**\n * Prompt for text input in the terminal\n *\n * @example\n * ```ts\n * // Simple usage\n * const name = await withTextInput(\"What is your name?\");\n *\n * // With options\n * const password = await withTextInput(\"Password:\", { mask: \"*\" });\n *\n * // With validation\n * const email = await withTextInput(\"Email:\", {\n * validate: (v) => v.includes(\"@\") ? undefined : \"Invalid email\"\n * });\n *\n * // With autocomplete\n * const fruit = await withTextInput(\"Pick a fruit:\", {\n * autocomplete: [\"apple\", \"banana\", \"cherry\"]\n * });\n * ```\n */\nexport async function withTextInput(\n prompt: string,\n options: TextInputOptions = {},\n): Promise<string> {\n const stream = options.stream ?? process.stdout\n const inputStream = options.inputStream ?? process.stdin\n const isTty = isTTY(stream)\n\n // Initialize state\n let value = options.defaultValue ?? \"\"\n let cursorPosition = value.length\n let errorMessage: string | undefined\n\n // Raw mode via the Modes owner — its per-stream refcount composes with\n // any host session owner on this stdin (TTY-guarded internally); never\n // inputStream.setRawMode directly (CLAUDE.md \"Anti-pattern: wasRaw\").\n const modes = createModes({ write: (data) => write(data, stream), stdin: inputStream })\n modes.rawMode(true)\n inputStream.resume()\n\n // Render the current state\n const render = () => {\n const displayValue = options.mask ? options.mask.repeat(value.length) : value\n\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n const suggestionSuffix = suggestion ? chalk.dim(suggestion.slice(value.length)) : \"\"\n\n // Build cursor display\n const beforeCursor = displayValue.slice(0, cursorPosition)\n const cursorChar = displayValue[cursorPosition] ?? \" \"\n const afterCursor = displayValue.slice(cursorPosition + 1)\n\n // Placeholder when empty\n const showPlaceholder = !value && options.placeholder\n const inputDisplay = showPlaceholder\n ? chalk.dim(options.placeholder) + chalk.inverse(\" \")\n : beforeCursor + chalk.inverse(cursorChar) + afterCursor + suggestionSuffix\n\n // Error message\n const errorDisplay = errorMessage ? chalk.red(` (${errorMessage})`) : \"\"\n\n const line = `${chalk.cyan(\"?\")} ${chalk.bold(prompt)} ${inputDisplay}${errorDisplay}`\n\n if (isTty) {\n write(`${CURSOR_TO_START}${line}${CLEAR_LINE_END}`, stream)\n }\n }\n\n // Hide cursor during input (we show our own)\n if (isTty) {\n write(CURSOR_HIDE, stream)\n }\n\n render()\n\n return new Promise<string>((resolve, reject) => {\n const cleanup = () => {\n inputStream.removeListener(\"data\", onData)\n inputStream.removeListener(\"error\", onError)\n modes[Symbol.dispose]()\n inputStream.pause()\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n }\n\n const submit = () => {\n // Validate before accepting\n if (options.validate) {\n const error = options.validate(value)\n if (error) {\n errorMessage = error\n render()\n return\n }\n }\n\n cleanup()\n\n // Show final value\n const displayValue = options.mask ? options.mask.repeat(value.length) : value\n write(\n `${CURSOR_TO_START}${chalk.green(\"✔\")} ${chalk.bold(prompt)} ${chalk.dim(displayValue)}${CLEAR_LINE_END}\\n`,\n stream,\n )\n\n resolve(value)\n }\n\n const onError = (err: Error) => {\n cleanup()\n reject(err)\n }\n\n const onData = (data: Buffer) => {\n const input = data.toString()\n errorMessage = undefined // Clear error on any input\n\n // Handle special keys\n for (let i = 0; i < input.length; i++) {\n const char = input[i]!\n const code = char.charCodeAt(0)\n\n // Enter (CR or LF)\n if (code === 13 || code === 10) {\n submit()\n return\n }\n\n // Ctrl+C - abort\n if (code === 3) {\n cleanup()\n write(\"\\n\", stream)\n reject(new Error(\"User aborted\"))\n return\n }\n\n // Escape - clear or abort\n if (code === 27) {\n // Check for arrow key sequences\n if (input[i + 1] === \"[\") {\n const arrowCode = input[i + 2]\n if (arrowCode === \"D\") {\n // Left arrow\n cursorPosition = Math.max(0, cursorPosition - 1)\n i += 2\n continue\n }\n if (arrowCode === \"C\") {\n // Right arrow\n cursorPosition = Math.min(value.length, cursorPosition + 1)\n i += 2\n continue\n }\n if (arrowCode === \"H\") {\n // Home\n cursorPosition = 0\n i += 2\n continue\n }\n if (arrowCode === \"F\") {\n // End\n cursorPosition = value.length\n i += 2\n continue\n }\n // Skip other escape sequences\n i += 2\n continue\n }\n // Plain escape - clear input\n value = \"\"\n cursorPosition = 0\n continue\n }\n\n // Backspace (127 or 8)\n if (code === 127 || code === 8) {\n if (cursorPosition > 0) {\n value = value.slice(0, cursorPosition - 1) + value.slice(cursorPosition)\n cursorPosition--\n }\n continue\n }\n\n // Delete (escape sequence handled above)\n if (code === 4) {\n // Ctrl+D acts as delete\n if (cursorPosition < value.length) {\n value = value.slice(0, cursorPosition) + value.slice(cursorPosition + 1)\n }\n continue\n }\n\n // Tab - accept autocomplete suggestion\n if (code === 9) {\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n if (suggestion) {\n value = suggestion\n cursorPosition = value.length\n }\n continue\n }\n\n // Ctrl+A - beginning of line\n if (code === 1) {\n cursorPosition = 0\n continue\n }\n\n // Ctrl+E - end of line\n if (code === 5) {\n cursorPosition = value.length\n continue\n }\n\n // Ctrl+U - clear to beginning\n if (code === 21) {\n value = value.slice(cursorPosition)\n cursorPosition = 0\n continue\n }\n\n // Ctrl+K - clear to end\n if (code === 11) {\n value = value.slice(0, cursorPosition)\n continue\n }\n\n // Ctrl+W - delete word backward\n if (code === 23) {\n const before = value.slice(0, cursorPosition)\n const after = value.slice(cursorPosition)\n const trimmed = before.trimEnd()\n const lastSpace = trimmed.lastIndexOf(\" \")\n const newBefore = lastSpace === -1 ? \"\" : trimmed.slice(0, lastSpace + 1)\n value = newBefore + after\n cursorPosition = newBefore.length\n continue\n }\n\n // Regular printable character\n if (code >= 32 && code < 127) {\n value = value.slice(0, cursorPosition) + char + value.slice(cursorPosition)\n cursorPosition++\n continue\n }\n\n // Handle UTF-8 characters (multi-byte)\n if (code > 127) {\n value = value.slice(0, cursorPosition) + char + value.slice(cursorPosition)\n cursorPosition++\n continue\n }\n }\n\n render()\n }\n\n inputStream.on(\"data\", onData)\n inputStream.on(\"error\", onError)\n })\n}\n\n/**\n * Create a text input instance for manual control\n *\n * @example\n * ```ts\n * const input = createTextInput(\"Name:\", { placeholder: \"Enter name\" });\n * input.render();\n *\n * // Later, get the value\n * const value = await input.waitForSubmit();\n * ```\n */\nexport function createTextInput(prompt: string, options: TextInputOptions = {}): TextInputInstance {\n const stream = options.stream ?? process.stdout\n const isTty = isTTY(stream)\n\n let value = options.defaultValue ?? \"\"\n let cursorPosition = value.length\n\n const render = () => {\n const displayValue = options.mask ? options.mask.repeat(value.length) : value\n\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n const suggestionSuffix = suggestion ? chalk.dim(suggestion.slice(value.length)) : \"\"\n\n const beforeCursor = displayValue.slice(0, cursorPosition)\n const cursorChar = displayValue[cursorPosition] ?? \" \"\n const afterCursor = displayValue.slice(cursorPosition + 1)\n\n const showPlaceholder = !value && options.placeholder\n const inputDisplay = showPlaceholder\n ? chalk.dim(options.placeholder) + chalk.inverse(\" \")\n : beforeCursor + chalk.inverse(cursorChar) + afterCursor + suggestionSuffix\n\n const line = `${chalk.cyan(\"?\")} ${chalk.bold(prompt)} ${inputDisplay}`\n\n if (isTty) {\n write(`${CURSOR_TO_START}${line}${CLEAR_LINE_END}`, stream)\n }\n }\n\n return {\n get value() {\n return value\n },\n set value(v: string) {\n value = v\n cursorPosition = Math.min(cursorPosition, v.length)\n },\n get cursorPosition() {\n return cursorPosition\n },\n set cursorPosition(pos: number) {\n cursorPosition = Math.max(0, Math.min(value.length, pos))\n },\n render,\n insert(char: string) {\n value = value.slice(0, cursorPosition) + char + value.slice(cursorPosition)\n cursorPosition += char.length\n },\n backspace() {\n if (cursorPosition > 0) {\n value = value.slice(0, cursorPosition - 1) + value.slice(cursorPosition)\n cursorPosition--\n }\n },\n delete() {\n if (cursorPosition < value.length) {\n value = value.slice(0, cursorPosition) + value.slice(cursorPosition + 1)\n }\n },\n clear() {\n value = \"\"\n cursorPosition = 0\n },\n acceptSuggestion() {\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n if (suggestion) {\n value = suggestion\n cursorPosition = value.length\n }\n },\n }\n}\n\n/** Instance returned by createTextInput for manual control */\nexport interface TextInputInstance {\n /** Current input value */\n value: string\n /** Current cursor position */\n cursorPosition: number\n /** Render the current state */\n render(): void\n /** Insert text at cursor */\n insert(char: string): void\n /** Delete character before cursor */\n backspace(): void\n /** Delete character at cursor */\n delete(): void\n /** Clear all input */\n clear(): void\n /** Accept autocomplete suggestion */\n acceptSuggestion(): void\n}\n\n/**\n * Find a matching autocomplete suggestion for the current input\n */\nfunction getAutocompleteSuggestion(value: string, autocomplete?: string[]): string | undefined {\n if (!value || !autocomplete?.length) {\n return undefined\n }\n\n const lowerValue = value.toLowerCase()\n return autocomplete.find(\n (item) => item.toLowerCase().startsWith(lowerValue) && item.length > value.length,\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,eAAsB,YACpB,SACA,MACA,UAA8B,EAAE,EACpB;CACZ,MAAM,UAAU,IAAI,QAAQ;EAC1B,MAAM,OAAO,SAAS,WAAW,OAAO,KAAK,EAAE;EAC/C,OAAO,QAAQ;EACf,OAAO,QAAQ;EAChB,CAAC;CAEF,IAAI,QAA+C;CACnD,MAAM,YAAY,KAAK,KAAK;AAE5B,SAAQ,OAAO;AAGf,KAAI,OAAO,SAAS,WAClB,SAAQ,kBAAkB;AAExB,UAAQ,cAAc,KADN,KAAK,OAAO,KAAK,KAAK,GAAG,aAAa,IACpB,CAAC;IAClC,IAAK;AAGV,KAAI;EACF,MAAM,SAAS,OAAO,OAAO,YAAY,aAAa,SAAS,GAAG;AAElE,MAAI,MAAO,eAAc,MAAM;AAE/B,MAAI,QAAQ,gBACV,SAAQ,MAAM;MAEd,SAAQ,SAAS;AAGnB,SAAO;UACA,OAAO;AACd,MAAI,MAAO,eAAc,MAAM;AAC/B,UAAQ,KAAK,iBAAiB,QAAQ,MAAM,UAAU,SAAS;AAC/D,QAAM;;;;;;;;;;;;;;;AAgBV,SAAgB,cACd,SACA,MACA,UAA8B,EAAE,EACT;CACvB,MAAM,UAAU,IAAI,QAAQ;EAC1B;EACA,OAAO,QAAQ;EACf,OAAO,QAAQ;EAChB,CAAC;AAEF,SAAQ,OAAO;CAEf,eAAe,cAA0B;AACvC,MAAI;AACF,UAAO,MAAM;WACN,OAAO;AACd,WAAQ,KAAK,iBAAiB,QAAQ,MAAM,UAAU,SAAS;AAC/D,SAAM;;;AAIV,QAAO,CAAC,aAAa,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;AChFjC,eAAsB,cACpB,WACA,cACA,UAAyC,EAAE,EAC/B;CACZ,MAAM,SAAS,QAAQ;CACvB,MAAM,QAAQ,MAAM,OAAO;CAG3B,MAAM,QADiB,OAAO,iBAAiB,aAChB,KAAK;CAEpC,MAAM,MAAM,IAAI,YAAY;EAC1B,QAAQ,QAAQ,GAAG,MAAM,oCAAoC;EAC7D,YAAY;EACb,CAAC;AAEF,KAAI,MACF,OAAM,aAAa,OAAO;CAG5B,IAAI,UAAU;CACd,IAAI;AAEJ,KAAI;AAEF,SAAO,MAAM;AACX,YAAS,UAAU,MAAM;AAEzB,OAAI,OAAO,KACT;GAGF,MAAM,EAAE,SAAS,UAAU,OAAO;AAElC,OAAI,CAAC,SAAS;AACZ,QAAI,MAAM,SAAS,MAAM;AACzB,cAAU;SAEV,KAAI,OAAO,QAAQ;;AAKvB,MAAI,QACF,KAAI,KAAK,QAAQ,gBAAgB;AAEnC,MAAI,MACF,OAAM,aAAa,OAAO;AAG5B,SAAO,OAAO;UACP,OAAO;AACd,MAAI,QACF,KAAI,MAAM;AAEZ,MAAI,MACF,OAAM,aAAa,OAAO;AAE5B,QAAM;;;;;;;;;;;;;;AAeV,gBAAuB,qBACrB,UACA,OACA,UAAyC,EAAE,EACT;CAClC,MAAM,SAAS,QAAQ;CACvB,MAAM,QAAQ,MAAM,OAAO;CAI3B,MAAM,SADQ,MAAM,QAAQ,SAAS,GAAG,WAAW,OAC9B,UAAU;CAE/B,MAAM,MAAM,IAAI,YAAY;EAC1B,QAAQ,GAAG,MAAM;EACjB;EACA,YAAY;EACb,CAAC;AAEF,KAAI,MACF,OAAM,aAAa,OAAO;CAG5B,IAAI,UAAU;AACd,KAAI,MAAM,GAAG,MAAM;AAEnB,KAAI;AACF,aAAW,MAAM,QAAQ,UAA8B;AACrD,SAAM;AACN;AACA,OAAI,OAAO,QAAQ;;AAGrB,MAAI,KAAK,QAAQ,gBAAgB;AACjC,MAAI,MACF,OAAM,aAAa,OAAO;UAErB,OAAO;AACd,MAAI,MAAM;AACV,MAAI,MACF,OAAM,aAAa,OAAO;AAE5B,QAAM;;;;;;;;;;;;;;;;;;;;;;;;AC5FV,SAAgB,YAAY,SAAuB,QAAuC;CACxF,MAAM,UAAU,IAAI,QAAQ,OAAO,eAAe,GAAG;CACrD,MAAM,2BAAsD,IAAI,KAAK;AAErE,SAAQ,OAAO;AAGf,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,OAAO,OAAO,EAAE;EACpE,MAAM,WAAW,SAAkB;AAEjC,OAAI,YAAY,QACd,SAAQ,cAAc,YAAY,QAAQ,KAAK;YACtC,YAAY,KACrB,SAAQ,cAAc,YAAY;AAIpC,OAAI,YAAY,SAAS;AACvB,YAAQ,SAAS;AACjB,aAAS;cACA,YAAY,MAAM;IAC3B,MAAM,UAAU,gBAAgB,QAAQ,KAAK,UAAU,OAAO,QAAQ,SAAS;AAC/E,YAAQ,KAAK,QAAQ;AACrB,aAAS;cACA,YAAY,MAAM;AAC3B,YAAQ,MAAM;AACd,aAAS;;;AAIb,WAAS,IAAI,WAAW,QAAQ;AAChC,UAAQ,GAAG,WAAW,QAAQ;;CAIhC,SAAS,UAAU;AACjB,OAAK,MAAM,CAAC,WAAW,YAAY,SACjC,SAAQ,IAAI,WAAW,QAAQ;AAEjC,WAAS,OAAO;;AAIlB,cAAa;AACX,UAAQ,MAAM;AACd,WAAS;;;;;;;;;;;;AAab,eAAsB,aACpB,SACA,WACA,MACA,UAGI,EAAE,EACY;AAClB,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,UAAU,IAAI,QAAQ,KAAK;AACjC,UAAQ,OAAO;EAEf,IAAI,QAA8C;EAElD,MAAM,gBAAgB;AACpB,WAAQ,IAAI,WAAW,eAAe;AACtC,OAAI,QAAQ,WACV,SAAQ,IAAI,QAAQ,YAAY,aAAa;AAE/C,OAAI,MACF,cAAa,MAAM;;EAIvB,MAAM,kBAAkB,SAAkB;AACxC,YAAS;AACT,WAAQ,SAAS;AACjB,WAAQ,KAAK;;EAGf,MAAM,gBAAgB,UAAmB;AACvC,YAAS;AACT,WAAQ,KAAK,iBAAiB,QAAQ,MAAM,UAAU,QAAQ;AAC9D,UAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,CAAC;;AAGnE,UAAQ,KAAK,WAAW,eAAe;AAEvC,MAAI,QAAQ,WACV,SAAQ,KAAK,QAAQ,YAAY,aAAa;AAGhD,MAAI,QAAQ,QACV,SAAQ,iBAAiB;AACvB,YAAS;AACT,WAAQ,KAAK,UAAU;AACvB,0BAAO,IAAI,MAAM,uBAAuB,YAAY,CAAC;KACpD,QAAQ,QAAQ;GAErB;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvHJ,eAAsB,WACpB,QACA,SACA,gBAAmC,EAAE,EACzB;CACZ,MAAM,EAAE,UAAU,GAAG,aAAa,OAAO;CACzC,MAAM,SAAS,QAAQ;CACvB,MAAM,QAAQ,QAAQ;AAEtB,KAAI,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,MAE3B,QAAO,QAAQ,UAAU,SAAS,QAAQ,GAAI;AAGhD,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI,iBAAiB,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,EAAE,QAAQ,SAAS,EAAE;EACvE,IAAI,gBAAgB;EAKpB,MAAM,QAAQ,YAAY;GAAE,QAAQ,SAAS,MAAM,MAAM,OAAO;GAAE;GAAO,CAAC;AAC1E,QAAM,QAAQ,KAAK;AACnB,QAAM,QAAQ;AACd,QAAM,YAAY,OAAO;AAGzB,QAAM,aAAa,OAAO;EAE1B,SAAS,SAAS;AAEhB,OAAI,gBAAgB,EAClB,OAAM,SAAS,cAAc,EAAE,OAAO;GAIxC,MAAM,eAAe,KAAK,IACxB,GACA,KAAK,IAAI,iBAAiB,KAAK,MAAM,aAAa,EAAE,EAAE,QAAQ,SAAS,WAAW,CACnF;GACD,MAAM,eAAe,KAAK,IAAI,YAAY,QAAQ,OAAO;GACzD,MAAM,iBAAiB,QAAQ,MAAM,cAAc,eAAe,aAAa;GAC/E,MAAM,eAAe,eAAe;GACpC,MAAM,eAAe,eAAe,eAAe,QAAQ;AAG3D,SAAM;EAAqB,MAAM,KAAK,OAAO,SAAuB,OAAO;GAE3E,IAAI,QAAQ;AAGZ,OAAI,cAAc;AAChB,UAAM;IAAuB,MAAM,IAAI,MAAM,SAAuB,OAAO;AAC3E;;AAIF,QAAK,IAAI,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;IAC9C,MAAM,SAAS,eAAe;IAE9B,MAAM,gBADc,eAAe,MACG;AAKtC,UAAM;EAHY,gBAAgB,MAAM,KAAK,IAAI,GAAG,IAGf,GAFvB,gBAAgB,MAAM,KAAK,OAAQ,MAAM,GAAG,OAAQ,cAEE,OAAO;AAC3E;;AAIF,OAAI,cAAc;AAChB,UAAM;IAAuB,MAAM,IAAI,MAAM,SAAuB,OAAO;AAC3E;;AAGF,mBAAgB;;EAGlB,SAAS,UAAU;AACjB,SAAM,OAAO,UAAU;AACvB,SAAM,OAAO;AACb,SAAM,eAAe,QAAQ,WAAW;AACxC,SAAM,aAAa,OAAO;;EAG5B,SAAS,WAAW,KAAa;AAEf,OAAI,WAAW,EAAE;AAGjC,OAAI,QAAQ,KAAQ;AAClB,aAAS;AACT,2BAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC;;AAIF,OAAI,QAAQ,QAAQ,QAAQ,MAAM;AAChC,aAAS;AACT,YAAQ,QAAQ,gBAAiB,MAAM;AACvC;;AAIF,OAAI,QAAQ,UAAU,IAAI,WAAW,GAAG;AACtC,aAAS;AACT,2BAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC;;AAIF,OAAI,IAAI,WAAW,QAAQ,EAAE;IAC3B,MAAM,OAAO,IAAI,MAAM,EAAE;AACzB,QAAI,SAAS,KAAK;AAEhB,sBAAiB,KAAK,IAAI,GAAG,iBAAiB,EAAE;AAChD,aAAQ;eACC,SAAS,KAAK;AAEvB,sBAAiB,KAAK,IAAI,QAAQ,SAAS,GAAG,iBAAiB,EAAE;AACjE,aAAQ;;AAEV;;AAIF,OAAI,QAAQ,OAAO,QAAQ,KAAK;AAC9B,qBAAiB,KAAK,IAAI,QAAQ,SAAS,GAAG,iBAAiB,EAAE;AACjE,YAAQ;AACR;;AAEF,OAAI,QAAQ,OAAO,QAAQ,KAAK;AAC9B,qBAAiB,KAAK,IAAI,GAAG,iBAAiB,EAAE;AAChD,YAAQ;AACR;;AAIF,OAAI,QAAQ,KAAK;AACf,aAAS;AACT,YAAQ,QAAQ,gBAAiB,MAAM;AACvC;;;AAIJ,QAAM,GAAG,QAAQ,WAAW;AAC5B,UAAQ;GACR;;;;;;;;;;;;;;;AAgBJ,SAAgB,aACd,iBAAoC,EAAE,EACwD;AAC9F,SAAW,QAAgB,SAA4B,YAA+B,EAAE,KACtF,WAAW,QAAQ,SAAS;EAAE,GAAG;EAAgB,GAAG;EAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtKpE,eAAsB,cACpB,QACA,UAA4B,EAAE,EACb;CACjB,MAAM,SAAS,QAAQ,UAAU,QAAQ;CACzC,MAAM,cAAc,QAAQ,eAAe,QAAQ;CACnD,MAAM,QAAQ,MAAM,OAAO;CAG3B,IAAI,QAAQ,QAAQ,gBAAgB;CACpC,IAAI,iBAAiB,MAAM;CAC3B,IAAI;CAKJ,MAAM,QAAQ,YAAY;EAAE,QAAQ,SAAS,MAAM,MAAM,OAAO;EAAE,OAAO;EAAa,CAAC;AACvF,OAAM,QAAQ,KAAK;AACnB,aAAY,QAAQ;CAGpB,MAAM,eAAe;EACnB,MAAM,eAAe,QAAQ,OAAO,QAAQ,KAAK,OAAO,MAAM,OAAO,GAAG;EAExE,MAAM,aAAa,0BAA0B,OAAO,QAAQ,aAAa;EACzE,MAAM,mBAAmB,aAAa,MAAM,IAAI,WAAW,MAAM,MAAM,OAAO,CAAC,GAAG;EAGlF,MAAM,eAAe,aAAa,MAAM,GAAG,eAAe;EAC1D,MAAM,aAAa,aAAa,mBAAmB;EACnD,MAAM,cAAc,aAAa,MAAM,iBAAiB,EAAE;EAI1D,MAAM,eADkB,CAAC,SAAS,QAAQ,cAEtC,MAAM,IAAI,QAAQ,YAAY,GAAG,MAAM,QAAQ,IAAI,GACnD,eAAe,MAAM,QAAQ,WAAW,GAAG,cAAc;EAG7D,MAAM,eAAe,eAAe,MAAM,IAAI,KAAK,aAAa,GAAG,GAAG;EAEtE,MAAM,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,OAAO,CAAC,GAAG,eAAe;AAExE,MAAI,MACF,OAAM;EAAqB,WAAyB,OAAO;;AAK/D,KAAI,MACF,OAAM,aAAa,OAAO;AAG5B,SAAQ;AAER,QAAO,IAAI,SAAiB,SAAS,WAAW;EAC9C,MAAM,gBAAgB;AACpB,eAAY,eAAe,QAAQ,OAAO;AAC1C,eAAY,eAAe,SAAS,QAAQ;AAC5C,SAAM,OAAO,UAAU;AACvB,eAAY,OAAO;AACnB,OAAI,MACF,OAAM,aAAa,OAAO;;EAI9B,MAAM,eAAe;AAEnB,OAAI,QAAQ,UAAU;IACpB,MAAM,QAAQ,QAAQ,SAAS,MAAM;AACrC,QAAI,OAAO;AACT,oBAAe;AACf,aAAQ;AACR;;;AAIJ,YAAS;GAGT,MAAM,eAAe,QAAQ,OAAO,QAAQ,KAAK,OAAO,MAAM,OAAO,GAAG;AACxE,SACE;EAAqB,MAAM,MAAM,IAAI,CAAC,GAAG,MAAM,KAAK,OAAO,CAAC,GAAG,MAAM,IAAI,aAAa,SACtF,OACD;AAED,WAAQ,MAAM;;EAGhB,MAAM,WAAW,QAAe;AAC9B,YAAS;AACT,UAAO,IAAI;;EAGb,MAAM,UAAU,SAAiB;GAC/B,MAAM,QAAQ,KAAK,UAAU;AAC7B,kBAAe,KAAA;AAGf,QAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,OAAO,MAAM;IACnB,MAAM,OAAO,KAAK,WAAW,EAAE;AAG/B,QAAI,SAAS,MAAM,SAAS,IAAI;AAC9B,aAAQ;AACR;;AAIF,QAAI,SAAS,GAAG;AACd,cAAS;AACT,WAAM,MAAM,OAAO;AACnB,4BAAO,IAAI,MAAM,eAAe,CAAC;AACjC;;AAIF,QAAI,SAAS,IAAI;AAEf,SAAI,MAAM,IAAI,OAAO,KAAK;MACxB,MAAM,YAAY,MAAM,IAAI;AAC5B,UAAI,cAAc,KAAK;AAErB,wBAAiB,KAAK,IAAI,GAAG,iBAAiB,EAAE;AAChD,YAAK;AACL;;AAEF,UAAI,cAAc,KAAK;AAErB,wBAAiB,KAAK,IAAI,MAAM,QAAQ,iBAAiB,EAAE;AAC3D,YAAK;AACL;;AAEF,UAAI,cAAc,KAAK;AAErB,wBAAiB;AACjB,YAAK;AACL;;AAEF,UAAI,cAAc,KAAK;AAErB,wBAAiB,MAAM;AACvB,YAAK;AACL;;AAGF,WAAK;AACL;;AAGF,aAAQ;AACR,sBAAiB;AACjB;;AAIF,QAAI,SAAS,OAAO,SAAS,GAAG;AAC9B,SAAI,iBAAiB,GAAG;AACtB,cAAQ,MAAM,MAAM,GAAG,iBAAiB,EAAE,GAAG,MAAM,MAAM,eAAe;AACxE;;AAEF;;AAIF,QAAI,SAAS,GAAG;AAEd,SAAI,iBAAiB,MAAM,OACzB,SAAQ,MAAM,MAAM,GAAG,eAAe,GAAG,MAAM,MAAM,iBAAiB,EAAE;AAE1E;;AAIF,QAAI,SAAS,GAAG;KACd,MAAM,aAAa,0BAA0B,OAAO,QAAQ,aAAa;AACzE,SAAI,YAAY;AACd,cAAQ;AACR,uBAAiB,MAAM;;AAEzB;;AAIF,QAAI,SAAS,GAAG;AACd,sBAAiB;AACjB;;AAIF,QAAI,SAAS,GAAG;AACd,sBAAiB,MAAM;AACvB;;AAIF,QAAI,SAAS,IAAI;AACf,aAAQ,MAAM,MAAM,eAAe;AACnC,sBAAiB;AACjB;;AAIF,QAAI,SAAS,IAAI;AACf,aAAQ,MAAM,MAAM,GAAG,eAAe;AACtC;;AAIF,QAAI,SAAS,IAAI;KACf,MAAM,SAAS,MAAM,MAAM,GAAG,eAAe;KAC7C,MAAM,QAAQ,MAAM,MAAM,eAAe;KACzC,MAAM,UAAU,OAAO,SAAS;KAChC,MAAM,YAAY,QAAQ,YAAY,IAAI;KAC1C,MAAM,YAAY,cAAc,KAAK,KAAK,QAAQ,MAAM,GAAG,YAAY,EAAE;AACzE,aAAQ,YAAY;AACpB,sBAAiB,UAAU;AAC3B;;AAIF,QAAI,QAAQ,MAAM,OAAO,KAAK;AAC5B,aAAQ,MAAM,MAAM,GAAG,eAAe,GAAG,OAAO,MAAM,MAAM,eAAe;AAC3E;AACA;;AAIF,QAAI,OAAO,KAAK;AACd,aAAQ,MAAM,MAAM,GAAG,eAAe,GAAG,OAAO,MAAM,MAAM,eAAe;AAC3E;AACA;;;AAIJ,WAAQ;;AAGV,cAAY,GAAG,QAAQ,OAAO;AAC9B,cAAY,GAAG,SAAS,QAAQ;GAChC;;;;;;;;;;;;;;AAeJ,SAAgB,gBAAgB,QAAgB,UAA4B,EAAE,EAAqB;CACjG,MAAM,SAAS,QAAQ,UAAU,QAAQ;CACzC,MAAM,QAAQ,MAAM,OAAO;CAE3B,IAAI,QAAQ,QAAQ,gBAAgB;CACpC,IAAI,iBAAiB,MAAM;CAE3B,MAAM,eAAe;EACnB,MAAM,eAAe,QAAQ,OAAO,QAAQ,KAAK,OAAO,MAAM,OAAO,GAAG;EAExE,MAAM,aAAa,0BAA0B,OAAO,QAAQ,aAAa;EACzE,MAAM,mBAAmB,aAAa,MAAM,IAAI,WAAW,MAAM,MAAM,OAAO,CAAC,GAAG;EAElF,MAAM,eAAe,aAAa,MAAM,GAAG,eAAe;EAC1D,MAAM,aAAa,aAAa,mBAAmB;EACnD,MAAM,cAAc,aAAa,MAAM,iBAAiB,EAAE;EAG1D,MAAM,eADkB,CAAC,SAAS,QAAQ,cAEtC,MAAM,IAAI,QAAQ,YAAY,GAAG,MAAM,QAAQ,IAAI,GACnD,eAAe,MAAM,QAAQ,WAAW,GAAG,cAAc;EAE7D,MAAM,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,OAAO,CAAC,GAAG;AAEzD,MAAI,MACF,OAAM;EAAqB,WAAyB,OAAO;;AAI/D,QAAO;EACL,IAAI,QAAQ;AACV,UAAO;;EAET,IAAI,MAAM,GAAW;AACnB,WAAQ;AACR,oBAAiB,KAAK,IAAI,gBAAgB,EAAE,OAAO;;EAErD,IAAI,iBAAiB;AACnB,UAAO;;EAET,IAAI,eAAe,KAAa;AAC9B,oBAAiB,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,QAAQ,IAAI,CAAC;;EAE3D;EACA,OAAO,MAAc;AACnB,WAAQ,MAAM,MAAM,GAAG,eAAe,GAAG,OAAO,MAAM,MAAM,eAAe;AAC3E,qBAAkB,KAAK;;EAEzB,YAAY;AACV,OAAI,iBAAiB,GAAG;AACtB,YAAQ,MAAM,MAAM,GAAG,iBAAiB,EAAE,GAAG,MAAM,MAAM,eAAe;AACxE;;;EAGJ,SAAS;AACP,OAAI,iBAAiB,MAAM,OACzB,SAAQ,MAAM,MAAM,GAAG,eAAe,GAAG,MAAM,MAAM,iBAAiB,EAAE;;EAG5E,QAAQ;AACN,WAAQ;AACR,oBAAiB;;EAEnB,mBAAmB;GACjB,MAAM,aAAa,0BAA0B,OAAO,QAAQ,aAAa;AACzE,OAAI,YAAY;AACd,YAAQ;AACR,qBAAiB,MAAM;;;EAG5B;;;;;AA0BH,SAAS,0BAA0B,OAAe,cAA6C;AAC7F,KAAI,CAAC,SAAS,CAAC,cAAc,OAC3B;CAGF,MAAM,aAAa,MAAM,aAAa;AACtC,QAAO,aAAa,MACjB,SAAS,KAAK,aAAa,CAAC,WAAW,WAAW,IAAI,KAAK,SAAS,MAAM,OAC5E"}
|
|
1
|
+
{"version":3,"file":"wrappers-DHMzvbRo.mjs","names":[],"sources":["../packages/ag-react/src/ui/wrappers/with-spinner.ts","../packages/ag-react/src/ui/wrappers/wrap-generator.ts","../packages/ag-react/src/ui/wrappers/wrap-emitter.ts","../packages/ag-react/src/ui/wrappers/with-select.ts","../packages/ag-react/src/ui/wrappers/with-text-input.ts"],"sourcesContent":["/**\n * withSpinner - Wrap promises with an animated spinner\n */\n\nimport type { WithSpinnerOptions } from \"../types.js\"\nimport { Spinner } from \"../cli/spinner\"\n\n/**\n * Wrap a promise with an animated spinner\n *\n * @example\n * ```ts\n * // Simple usage\n * const data = await withSpinner(fetchData(), \"Loading data...\");\n *\n * // With options\n * const result = await withSpinner(\n * processFiles(),\n * \"Processing...\",\n * { style: \"arc\", clearOnComplete: true }\n * );\n *\n * // With dynamic text\n * const result = await withSpinner(\n * longOperation(),\n * (elapsed) => `Processing... (${elapsed}s)`\n * );\n * ```\n */\nexport async function withSpinner<T>(\n promise: Promise<T> | (() => T | Promise<T>),\n text: string | ((elapsedSeconds: number) => string),\n options: WithSpinnerOptions = {},\n): Promise<T> {\n const spinner = new Spinner({\n text: typeof text === \"string\" ? text : text(0),\n style: options.style,\n color: options.color,\n })\n\n let timer: ReturnType<typeof setInterval> | null = null\n const startTime = Date.now()\n\n spinner.start()\n\n // Update text if dynamic\n if (typeof text === \"function\") {\n timer = setInterval(() => {\n const elapsed = Math.floor((Date.now() - startTime) / 1000)\n spinner.currentText = text(elapsed)\n }, 1000)\n }\n\n try {\n const result = await (typeof promise === \"function\" ? promise() : promise)\n\n if (timer) clearInterval(timer)\n\n if (options.clearOnComplete) {\n spinner.stop()\n } else {\n spinner.succeed()\n }\n\n return result\n } catch (error) {\n if (timer) clearInterval(timer)\n spinner.fail(error instanceof Error ? error.message : \"Failed\")\n throw error\n }\n}\n\n/**\n * Attach a spinner to a promise for manual control\n * Returns [result, spinner] tuple for custom control\n *\n * @example\n * ```ts\n * const [promise, spinner] = attachSpinner(fetchData(), \"Loading...\");\n * spinner.text = \"Still loading...\";\n * const result = await promise;\n * spinner.succeed(\"Loaded!\");\n * ```\n */\nexport function attachSpinner<T>(\n promise: Promise<T>,\n text: string,\n options: WithSpinnerOptions = {},\n): [Promise<T>, Spinner] {\n const spinner = new Spinner({\n text,\n style: options.style,\n color: options.color,\n })\n\n spinner.start()\n\n async function wrapPromise(): Promise<T> {\n try {\n return await promise\n } catch (error) {\n spinner.fail(error instanceof Error ? error.message : \"Failed\")\n throw error\n }\n }\n\n return [wrapPromise(), spinner]\n}\n","/**\n * wrapGenerator - Consume a generator while showing progress\n */\n\nimport type { ProgressGenerator } from \"../types.js\"\nimport { ProgressBar } from \"../cli/progress-bar\"\nimport { CURSOR_HIDE, CURSOR_SHOW, write, isTTY } from \"../cli/ansi\"\n\n/**\n * Consume a progress generator while displaying progress\n *\n * @example\n * ```ts\n * // Wrap existing generator (like evaluateAllRules())\n * await wrapGenerator(evaluateAllRules(), \"Evaluating rules\");\n *\n * // With custom format\n * await wrapGenerator(\n * processItems(),\n * ({ current, total }) => `Processing: ${current}/${total}`\n * );\n *\n * // Get the generator's return value\n * const result = await wrapGenerator(generatorWithReturn(), \"Processing\");\n * ```\n */\nexport async function wrapGenerator<T>(\n generator: ProgressGenerator<T>,\n textOrFormat: string | ((progress: { current: number; total: number }) => string),\n options: { clearOnComplete?: boolean } = {},\n): Promise<T> {\n const stream = process.stdout\n const isTty = isTTY(stream)\n\n const isCustomFormat = typeof textOrFormat === \"function\"\n const label = isCustomFormat ? \"\" : textOrFormat\n\n const bar = new ProgressBar({\n format: label ? `${label} [:bar] :current/:total :percent` : \":bar :current/:total :percent\",\n hideCursor: true,\n })\n\n if (isTty) {\n write(CURSOR_HIDE, stream)\n }\n\n let started = false\n let result: IteratorResult<{ current: number; total: number }, T>\n\n try {\n // Consume the generator\n while (true) {\n result = generator.next()\n\n if (result.done) {\n break\n }\n\n const { current, total } = result.value\n\n if (!started) {\n bar.start(current, total)\n started = true\n } else {\n bar.update(current)\n }\n }\n\n // Stop bar\n if (started) {\n bar.stop(options.clearOnComplete)\n }\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n\n return result.value\n } catch (error) {\n if (started) {\n bar.stop()\n }\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n throw error\n }\n}\n\n/**\n * Create an async iterable wrapper that shows progress\n *\n * @example\n * ```ts\n * const items = [1, 2, 3, 4, 5];\n * for await (const item of withIterableProgress(items, \"Processing\")) {\n * await processItem(item);\n * }\n * ```\n */\nexport async function* withIterableProgress<T>(\n iterable: Iterable<T> | AsyncIterable<T>,\n label: string,\n options: { clearOnComplete?: boolean } = {},\n): AsyncGenerator<T, void, unknown> {\n const stream = process.stdout\n const isTty = isTTY(stream)\n\n // Try to get length if array\n const items = Array.isArray(iterable) ? iterable : null\n const total = items?.length ?? 0\n\n const bar = new ProgressBar({\n format: `${label} [:bar] :current/:total :percent`,\n total,\n hideCursor: true,\n })\n\n if (isTty) {\n write(CURSOR_HIDE, stream)\n }\n\n let current = 0\n bar.start(0, total)\n\n try {\n for await (const item of iterable as AsyncIterable<T>) {\n yield item\n current++\n bar.update(current)\n }\n\n bar.stop(options.clearOnComplete)\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n } catch (error) {\n bar.stop()\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n throw error\n }\n}\n","/**\n * wrapEmitter - Track EventEmitter state changes with progress indicators\n */\n\nimport type { EventEmitter } from \"events\"\nimport { Spinner } from \"../cli/spinner\"\n\n/** Event handler configuration */\ninterface EventConfig {\n /** Display text for this event */\n text?: string\n /** Dynamic text based on event data */\n getText?: (data: unknown) => string\n /** Mark spinner as succeeded */\n succeed?: boolean\n /** Mark spinner as failed */\n fail?: boolean\n /** Stop tracking */\n stop?: boolean\n}\n\n/** Configuration for wrapEmitter */\ninterface WrapEmitterConfig {\n /** Event handlers */\n events: Record<string, EventConfig>\n /** Initial text */\n initialText?: string\n}\n\n/**\n * Track EventEmitter state changes with a spinner\n *\n * @example\n * ```ts\n * const stop = wrapEmitter(syncManager, {\n * initialText: \"Starting sync...\",\n * events: {\n * 'ready': { text: \"Watcher ready\", succeed: true },\n * 'state-change': { getText: (s) => `State: ${s}` },\n * 'error': { fail: true },\n * 'idle': { stop: true }\n * }\n * });\n *\n * // Later, to stop manually\n * stop();\n * ```\n */\nexport function wrapEmitter(emitter: EventEmitter, config: WrapEmitterConfig): () => void {\n const spinner = new Spinner(config.initialText ?? \"\")\n const handlers: Map<string, (...args: unknown[]) => void> = new Map()\n\n spinner.start()\n\n // Set up event handlers\n for (const [eventName, eventConfig] of Object.entries(config.events)) {\n const handler = (data: unknown) => {\n // Update text\n if (eventConfig.getText) {\n spinner.currentText = eventConfig.getText(data)\n } else if (eventConfig.text) {\n spinner.currentText = eventConfig.text\n }\n\n // Handle terminal states\n if (eventConfig.succeed) {\n spinner.succeed()\n cleanup()\n } else if (eventConfig.fail) {\n const message = data instanceof Error ? data.message : String(data ?? \"Failed\")\n spinner.fail(message)\n cleanup()\n } else if (eventConfig.stop) {\n spinner.stop()\n cleanup()\n }\n }\n\n handlers.set(eventName, handler)\n emitter.on(eventName, handler)\n }\n\n // Cleanup function\n function cleanup() {\n for (const [eventName, handler] of handlers) {\n emitter.off(eventName, handler)\n }\n handlers.clear()\n }\n\n // Return stop function\n return () => {\n spinner.stop()\n cleanup()\n }\n}\n\n/**\n * Wait for an EventEmitter to emit a specific event\n * Shows a spinner while waiting\n *\n * @example\n * ```ts\n * await waitForEvent(syncManager, \"ready\", \"Waiting for watcher...\");\n * ```\n */\nexport async function waitForEvent(\n emitter: EventEmitter,\n eventName: string,\n text: string,\n options: {\n errorEvent?: string\n timeout?: number\n } = {},\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const spinner = new Spinner(text)\n spinner.start()\n\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const cleanup = () => {\n emitter.off(eventName, successHandler)\n if (options.errorEvent) {\n emitter.off(options.errorEvent, errorHandler)\n }\n if (timer) {\n clearTimeout(timer)\n }\n }\n\n const successHandler = (data: unknown) => {\n cleanup()\n spinner.succeed()\n resolve(data)\n }\n\n const errorHandler = (error: unknown) => {\n cleanup()\n spinner.fail(error instanceof Error ? error.message : \"Error\")\n reject(error instanceof Error ? error : new Error(String(error)))\n }\n\n emitter.once(eventName, successHandler)\n\n if (options.errorEvent) {\n emitter.once(options.errorEvent, errorHandler)\n }\n\n if (options.timeout) {\n timer = setTimeout(() => {\n cleanup()\n spinner.fail(\"Timeout\")\n reject(new Error(`Timeout waiting for ${eventName}`))\n }, options.timeout)\n }\n })\n}\n","/**\n * withSelect - Interactive CLI selection list\n */\n\nimport chalk from \"@silvery/ink/chalk\"\nimport { createModes } from \"@silvery/ag-term\"\nimport type { SelectOption, WithSelectOptions } from \"../types.js\"\nimport {\n CURSOR_HIDE,\n CURSOR_SHOW,\n CURSOR_TO_START,\n CLEAR_LINE_END,\n cursorUp,\n write,\n isTTY,\n} from \"../cli/ansi\"\n\n/**\n * Display an interactive selection list in the terminal\n *\n * @example\n * ```ts\n * // Simple usage\n * const color = await withSelect(\"Choose a color:\", [\n * { label: \"Red\", value: \"red\" },\n * { label: \"Green\", value: \"green\" },\n * { label: \"Blue\", value: \"blue\" },\n * ]);\n *\n * // With options\n * const result = await withSelect(\n * \"Select item:\",\n * options,\n * { initial: 2, maxVisible: 5 }\n * );\n * ```\n */\nexport async function withSelect<T>(\n prompt: string,\n options: SelectOption<T>[],\n selectOptions: WithSelectOptions = {},\n): Promise<T> {\n const { initial = 0, maxVisible = 10 } = selectOptions\n const stream = process.stdout\n const stdin = process.stdin\n\n if (!isTTY(stream) || !stdin.isTTY) {\n // Non-interactive mode: return first option or initial\n return options[initial]?.value ?? options[0]!.value\n }\n\n return new Promise((resolve, reject) => {\n let highlightIndex = Math.min(Math.max(0, initial), options.length - 1)\n let linesRendered = 0\n\n // Raw mode via the Modes owner — its per-stream refcount composes with\n // any host session owner on this stdin; never stdin.setRawMode directly\n // (CLAUDE.md \"Anti-pattern: wasRaw\").\n const modes = createModes({ write: (data) => write(data, stream), stdin })\n modes.rawMode(true)\n stdin.resume()\n stdin.setEncoding(\"utf8\")\n\n // Hide cursor\n write(CURSOR_HIDE, stream)\n\n function render() {\n // Clear previously rendered lines\n if (linesRendered > 0) {\n write(cursorUp(linesRendered), stream)\n }\n\n // Calculate scroll window\n const scrollOffset = Math.max(\n 0,\n Math.min(highlightIndex - Math.floor(maxVisible / 2), options.length - maxVisible),\n )\n const visibleCount = Math.min(maxVisible, options.length)\n const visibleOptions = options.slice(scrollOffset, scrollOffset + visibleCount)\n const hasMoreAbove = scrollOffset > 0\n const hasMoreBelow = scrollOffset + visibleCount < options.length\n\n // Render prompt\n write(`${CURSOR_TO_START}${chalk.bold(prompt)}${CLEAR_LINE_END}\\n`, stream)\n\n let lines = 1\n\n // Render scroll indicator (above)\n if (hasMoreAbove) {\n write(`${CURSOR_TO_START} ${chalk.dim(\"...\")}${CLEAR_LINE_END}\\n`, stream)\n lines++\n }\n\n // Render options\n for (let i = 0; i < visibleOptions.length; i++) {\n const option = visibleOptions[i]\n const actualIndex = scrollOffset + i\n const isHighlighted = actualIndex === highlightIndex\n\n const indicator = isHighlighted ? chalk.cyan(\">\") : \" \"\n const label = isHighlighted ? chalk.cyan(option!.label) : option!.label\n\n write(`${CURSOR_TO_START}${indicator} ${label}${CLEAR_LINE_END}\\n`, stream)\n lines++\n }\n\n // Render scroll indicator (below)\n if (hasMoreBelow) {\n write(`${CURSOR_TO_START} ${chalk.dim(\"...\")}${CLEAR_LINE_END}\\n`, stream)\n lines++\n }\n\n linesRendered = lines\n }\n\n function cleanup() {\n modes[Symbol.dispose]()\n stdin.pause()\n stdin.removeListener(\"data\", onKeypress)\n write(CURSOR_SHOW, stream)\n }\n\n function onKeypress(key: string) {\n // Handle key sequences\n const keyCode = key.charCodeAt(0)\n\n // Ctrl+C\n if (key === \"\\x03\") {\n cleanup()\n reject(new Error(\"User cancelled\"))\n return\n }\n\n // Enter/Return\n if (key === \"\\r\" || key === \"\\n\") {\n cleanup()\n resolve(options[highlightIndex]!.value)\n return\n }\n\n // Escape\n if (key === \"\\x1b\" && key.length === 1) {\n cleanup()\n reject(new Error(\"User cancelled\"))\n return\n }\n\n // Arrow keys (escape sequences)\n if (key.startsWith(\"\\x1b[\")) {\n const code = key.slice(2)\n if (code === \"A\") {\n // Up arrow\n highlightIndex = Math.max(0, highlightIndex - 1)\n render()\n } else if (code === \"B\") {\n // Down arrow\n highlightIndex = Math.min(options.length - 1, highlightIndex + 1)\n render()\n }\n return\n }\n\n // j/k vim keys\n if (key === \"j\" || key === \"J\") {\n highlightIndex = Math.min(options.length - 1, highlightIndex + 1)\n render()\n return\n }\n if (key === \"k\" || key === \"K\") {\n highlightIndex = Math.max(0, highlightIndex - 1)\n render()\n return\n }\n\n // Space to select (optional alternative to Enter)\n if (key === \" \") {\n cleanup()\n resolve(options[highlightIndex]!.value)\n return\n }\n }\n\n stdin.on(\"data\", onKeypress)\n render()\n })\n}\n\n/**\n * Create a reusable select instance for multiple selections\n *\n * @example\n * ```ts\n * const select = createSelect({\n * maxVisible: 5,\n * });\n *\n * const first = await select(\"Choose first:\", options1);\n * const second = await select(\"Choose second:\", options2);\n * ```\n */\nexport function createSelect(\n defaultOptions: WithSelectOptions = {},\n): <T>(prompt: string, options: SelectOption<T>[], overrides?: WithSelectOptions) => Promise<T> {\n return <T>(prompt: string, options: SelectOption<T>[], overrides: WithSelectOptions = {}) =>\n withSelect(prompt, options, { ...defaultOptions, ...overrides })\n}\n","/**\n * withTextInput - CLI wrapper for text input prompts\n */\n\nimport chalk from \"@silvery/ink/chalk\"\nimport { createModes } from \"@silvery/ag-term\"\nimport type { TextInputOptions } from \"../types.js\"\nimport {\n CURSOR_HIDE,\n CURSOR_SHOW,\n CURSOR_TO_START,\n CLEAR_LINE_END,\n write,\n isTTY,\n} from \"../cli/ansi\"\n\n/**\n * Prompt for text input in the terminal\n *\n * @example\n * ```ts\n * // Simple usage\n * const name = await withTextInput(\"What is your name?\");\n *\n * // With options\n * const password = await withTextInput(\"Password:\", { mask: \"*\" });\n *\n * // With validation\n * const email = await withTextInput(\"Email:\", {\n * validate: (v) => v.includes(\"@\") ? undefined : \"Invalid email\"\n * });\n *\n * // With autocomplete\n * const fruit = await withTextInput(\"Pick a fruit:\", {\n * autocomplete: [\"apple\", \"banana\", \"cherry\"]\n * });\n * ```\n */\nexport async function withTextInput(\n prompt: string,\n options: TextInputOptions = {},\n): Promise<string> {\n const stream = options.stream ?? process.stdout\n const inputStream = options.inputStream ?? process.stdin\n const isTty = isTTY(stream)\n\n // Initialize state\n let value = options.defaultValue ?? \"\"\n let cursorPosition = value.length\n let errorMessage: string | undefined\n\n // Raw mode via the Modes owner — its per-stream refcount composes with\n // any host session owner on this stdin (TTY-guarded internally); never\n // inputStream.setRawMode directly (CLAUDE.md \"Anti-pattern: wasRaw\").\n const modes = createModes({ write: (data) => write(data, stream), stdin: inputStream })\n modes.rawMode(true)\n inputStream.resume()\n\n // Render the current state\n const render = () => {\n const displayValue = options.mask ? options.mask.repeat(value.length) : value\n\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n const suggestionSuffix = suggestion ? chalk.dim(suggestion.slice(value.length)) : \"\"\n\n // Build cursor display\n const beforeCursor = displayValue.slice(0, cursorPosition)\n const cursorChar = displayValue[cursorPosition] ?? \" \"\n const afterCursor = displayValue.slice(cursorPosition + 1)\n\n // Placeholder when empty\n const showPlaceholder = !value && options.placeholder\n const inputDisplay = showPlaceholder\n ? chalk.dim(options.placeholder) + chalk.inverse(\" \")\n : beforeCursor + chalk.inverse(cursorChar) + afterCursor + suggestionSuffix\n\n // Error message\n const errorDisplay = errorMessage ? chalk.red(` (${errorMessage})`) : \"\"\n\n const line = `${chalk.cyan(\"?\")} ${chalk.bold(prompt)} ${inputDisplay}${errorDisplay}`\n\n if (isTty) {\n write(`${CURSOR_TO_START}${line}${CLEAR_LINE_END}`, stream)\n }\n }\n\n // Hide cursor during input (we show our own)\n if (isTty) {\n write(CURSOR_HIDE, stream)\n }\n\n render()\n\n return new Promise<string>((resolve, reject) => {\n const cleanup = () => {\n inputStream.removeListener(\"data\", onData)\n inputStream.removeListener(\"error\", onError)\n modes[Symbol.dispose]()\n inputStream.pause()\n if (isTty) {\n write(CURSOR_SHOW, stream)\n }\n }\n\n const submit = () => {\n // Validate before accepting\n if (options.validate) {\n const error = options.validate(value)\n if (error) {\n errorMessage = error\n render()\n return\n }\n }\n\n cleanup()\n\n // Show final value\n const displayValue = options.mask ? options.mask.repeat(value.length) : value\n write(\n `${CURSOR_TO_START}${chalk.green(\"✔\")} ${chalk.bold(prompt)} ${chalk.dim(displayValue)}${CLEAR_LINE_END}\\n`,\n stream,\n )\n\n resolve(value)\n }\n\n const onError = (err: Error) => {\n cleanup()\n reject(err)\n }\n\n const onData = (data: Buffer) => {\n const input = data.toString()\n errorMessage = undefined // Clear error on any input\n\n // Handle special keys\n for (let i = 0; i < input.length; i++) {\n const char = input[i]!\n const code = char.charCodeAt(0)\n\n // Enter (CR or LF)\n if (code === 13 || code === 10) {\n submit()\n return\n }\n\n // Ctrl+C - abort\n if (code === 3) {\n cleanup()\n write(\"\\n\", stream)\n reject(new Error(\"User aborted\"))\n return\n }\n\n // Escape - clear or abort\n if (code === 27) {\n // Check for arrow key sequences\n if (input[i + 1] === \"[\") {\n const arrowCode = input[i + 2]\n if (arrowCode === \"D\") {\n // Left arrow\n cursorPosition = Math.max(0, cursorPosition - 1)\n i += 2\n continue\n }\n if (arrowCode === \"C\") {\n // Right arrow\n cursorPosition = Math.min(value.length, cursorPosition + 1)\n i += 2\n continue\n }\n if (arrowCode === \"H\") {\n // Home\n cursorPosition = 0\n i += 2\n continue\n }\n if (arrowCode === \"F\") {\n // End\n cursorPosition = value.length\n i += 2\n continue\n }\n // Skip other escape sequences\n i += 2\n continue\n }\n // Plain escape - clear input\n value = \"\"\n cursorPosition = 0\n continue\n }\n\n // Backspace (127 or 8)\n if (code === 127 || code === 8) {\n if (cursorPosition > 0) {\n value = value.slice(0, cursorPosition - 1) + value.slice(cursorPosition)\n cursorPosition--\n }\n continue\n }\n\n // Delete (escape sequence handled above)\n if (code === 4) {\n // Ctrl+D acts as delete\n if (cursorPosition < value.length) {\n value = value.slice(0, cursorPosition) + value.slice(cursorPosition + 1)\n }\n continue\n }\n\n // Tab - accept autocomplete suggestion\n if (code === 9) {\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n if (suggestion) {\n value = suggestion\n cursorPosition = value.length\n }\n continue\n }\n\n // Ctrl+A - beginning of line\n if (code === 1) {\n cursorPosition = 0\n continue\n }\n\n // Ctrl+E - end of line\n if (code === 5) {\n cursorPosition = value.length\n continue\n }\n\n // Ctrl+U - clear to beginning\n if (code === 21) {\n value = value.slice(cursorPosition)\n cursorPosition = 0\n continue\n }\n\n // Ctrl+K - clear to end\n if (code === 11) {\n value = value.slice(0, cursorPosition)\n continue\n }\n\n // Ctrl+W - delete word backward\n if (code === 23) {\n const before = value.slice(0, cursorPosition)\n const after = value.slice(cursorPosition)\n const trimmed = before.trimEnd()\n const lastSpace = trimmed.lastIndexOf(\" \")\n const newBefore = lastSpace === -1 ? \"\" : trimmed.slice(0, lastSpace + 1)\n value = newBefore + after\n cursorPosition = newBefore.length\n continue\n }\n\n // Regular printable character\n if (code >= 32 && code < 127) {\n value = value.slice(0, cursorPosition) + char + value.slice(cursorPosition)\n cursorPosition++\n continue\n }\n\n // Handle UTF-8 characters (multi-byte)\n if (code > 127) {\n value = value.slice(0, cursorPosition) + char + value.slice(cursorPosition)\n cursorPosition++\n continue\n }\n }\n\n render()\n }\n\n inputStream.on(\"data\", onData)\n inputStream.on(\"error\", onError)\n })\n}\n\n/**\n * Create a text input instance for manual control\n *\n * @example\n * ```ts\n * const input = createTextInput(\"Name:\", { placeholder: \"Enter name\" });\n * input.render();\n *\n * // Later, get the value\n * const value = await input.waitForSubmit();\n * ```\n */\nexport function createTextInput(prompt: string, options: TextInputOptions = {}): TextInputInstance {\n const stream = options.stream ?? process.stdout\n const isTty = isTTY(stream)\n\n let value = options.defaultValue ?? \"\"\n let cursorPosition = value.length\n\n const render = () => {\n const displayValue = options.mask ? options.mask.repeat(value.length) : value\n\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n const suggestionSuffix = suggestion ? chalk.dim(suggestion.slice(value.length)) : \"\"\n\n const beforeCursor = displayValue.slice(0, cursorPosition)\n const cursorChar = displayValue[cursorPosition] ?? \" \"\n const afterCursor = displayValue.slice(cursorPosition + 1)\n\n const showPlaceholder = !value && options.placeholder\n const inputDisplay = showPlaceholder\n ? chalk.dim(options.placeholder) + chalk.inverse(\" \")\n : beforeCursor + chalk.inverse(cursorChar) + afterCursor + suggestionSuffix\n\n const line = `${chalk.cyan(\"?\")} ${chalk.bold(prompt)} ${inputDisplay}`\n\n if (isTty) {\n write(`${CURSOR_TO_START}${line}${CLEAR_LINE_END}`, stream)\n }\n }\n\n return {\n get value() {\n return value\n },\n set value(v: string) {\n value = v\n cursorPosition = Math.min(cursorPosition, v.length)\n },\n get cursorPosition() {\n return cursorPosition\n },\n set cursorPosition(pos: number) {\n cursorPosition = Math.max(0, Math.min(value.length, pos))\n },\n render,\n insert(char: string) {\n value = value.slice(0, cursorPosition) + char + value.slice(cursorPosition)\n cursorPosition += char.length\n },\n backspace() {\n if (cursorPosition > 0) {\n value = value.slice(0, cursorPosition - 1) + value.slice(cursorPosition)\n cursorPosition--\n }\n },\n delete() {\n if (cursorPosition < value.length) {\n value = value.slice(0, cursorPosition) + value.slice(cursorPosition + 1)\n }\n },\n clear() {\n value = \"\"\n cursorPosition = 0\n },\n acceptSuggestion() {\n const suggestion = getAutocompleteSuggestion(value, options.autocomplete)\n if (suggestion) {\n value = suggestion\n cursorPosition = value.length\n }\n },\n }\n}\n\n/** Instance returned by createTextInput for manual control */\nexport interface TextInputInstance {\n /** Current input value */\n value: string\n /** Current cursor position */\n cursorPosition: number\n /** Render the current state */\n render(): void\n /** Insert text at cursor */\n insert(char: string): void\n /** Delete character before cursor */\n backspace(): void\n /** Delete character at cursor */\n delete(): void\n /** Clear all input */\n clear(): void\n /** Accept autocomplete suggestion */\n acceptSuggestion(): void\n}\n\n/**\n * Find a matching autocomplete suggestion for the current input\n */\nfunction getAutocompleteSuggestion(value: string, autocomplete?: string[]): string | undefined {\n if (!value || !autocomplete?.length) {\n return undefined\n }\n\n const lowerValue = value.toLowerCase()\n return autocomplete.find(\n (item) => item.toLowerCase().startsWith(lowerValue) && item.length > value.length,\n )\n}\n"],"mappings":"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"}
|
|
@@ -271,10 +271,10 @@ function createYogaEngine(yoga) {
|
|
|
271
271
|
* Uses yoga-wasm-web/auto which automatically selects the right implementation.
|
|
272
272
|
*/
|
|
273
273
|
async function initYogaEngine() {
|
|
274
|
-
const { default: yoga } = await import("./node-
|
|
274
|
+
const { default: yoga } = await import("./node-Cl-kzQcl.mjs");
|
|
275
275
|
return new YogaLayoutEngine(yoga);
|
|
276
276
|
}
|
|
277
277
|
//#endregion
|
|
278
278
|
export { createYogaEngine as n, initYogaEngine as r, YogaLayoutEngine as t };
|
|
279
279
|
|
|
280
|
-
//# sourceMappingURL=yoga-adapter-
|
|
280
|
+
//# sourceMappingURL=yoga-adapter-CB_7pLyl.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yoga-adapter-SsEIqMc1.mjs","names":[],"sources":["../packages/ag-term/src/adapters/yoga-adapter.ts"],"sourcesContent":["/**\n * Yoga Layout Engine Adapter\n *\n * Wraps yoga-wasm-web to implement the LayoutEngine interface.\n */\n\nimport type {\n Align,\n Direction,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n Yoga,\n Node as YogaNode,\n} from \"yoga-wasm-web\"\nimport type { FitWidthLane, LayoutNode, MeasureFunc, MeasureMode } from \"@silvery/ag/layout-types\"\nimport type {\n AlignValue,\n DirectionValue,\n DisplayValue,\n EdgeValue,\n EngineCapabilities,\n FlexDirectionValue,\n GutterValue,\n JustifyValue,\n LayoutConstants,\n LayoutEngine,\n MeasureModeValue,\n OverflowValue,\n PositionTypeValue,\n WrapValue,\n} from \"../layout-engine\"\n\n/**\n * Capabilities advertised by the yoga adapter.\n *\n * **All flags stay `false`.** yoga's WASM boundary doesn't expose the inter-pass\n * child-style mutation hook that engine-native container queries, fitWidth, and the\n * cq*-unit / style-math-function primitives require. Consumers that need those\n * primitives must switch to flexily via `SILVERY_ENGINE=flexily` or\n * `ensureDefaultLayoutEngine(\"flexily\")`.\n *\n * The existing CSS-flexbox surface (Box/Text declarative props, useResponsiveBoxProps,\n * etc.) remains FULLY SUPPORTED under yoga — only the reframe's new primitives are gated.\n */\nconst YOGA_CAPABILITIES: EngineCapabilities = Object.freeze({\n containerQueries: false, // yoga has no CQ resolution; flexily-only\n containSize: false, // yoga has no contain:size; flexily-only\n containerQueryUnits: false, // yoga has no cq* parser; flexily-only\n fitWidth: false, // yoga has no fitWidth Box prop; flexily-only\n styleMathFunctions: false, // yoga has no late-bound math; flexily-only\n childStyleMutation: false, // yoga's WASM boundary blocks the hook\n})\n\n// ============================================================================\n// Yoga Node Adapter\n// ============================================================================\n\n/**\n * Wraps a Yoga node to implement LayoutNode interface.\n */\nclass YogaNodeAdapter implements LayoutNode {\n private node: YogaNode\n private yoga: Yoga\n private hasMeasureFunc = false\n\n constructor(node: YogaNode, yoga: Yoga) {\n this.node = node\n this.yoga = yoga\n }\n\n /** Get the underlying Yoga node (for tree operations) */\n getYogaNode(): YogaNode {\n return this.node\n }\n\n // Tree operations\n insertChild(child: LayoutNode, index: number): void {\n const yogaChild = (child as YogaNodeAdapter).getYogaNode()\n this.node.insertChild(yogaChild, index)\n }\n\n removeChild(child: LayoutNode): void {\n const yogaChild = (child as YogaNodeAdapter).getYogaNode()\n this.node.removeChild(yogaChild)\n }\n\n free(): void {\n this.node.free()\n }\n\n // Measure function\n setMeasureFunc(measureFunc: MeasureFunc): void {\n this.hasMeasureFunc = true\n this.node.setMeasureFunc((width, widthMode, height, heightMode) => {\n const widthModeStr = this.measureModeToString(widthMode)\n const heightModeStr = this.measureModeToString(heightMode)\n return measureFunc(width, widthModeStr, height, heightModeStr)\n })\n }\n\n // Dirty tracking - forces layout recalculation\n // Yoga only allows markDirty() on leaf nodes with measure functions\n markDirty(): void {\n if (this.hasMeasureFunc) {\n this.node.markDirty()\n }\n }\n isDirty(): boolean {\n return this.node.isDirty()\n }\n\n private measureModeToString(mode: number): MeasureMode {\n if (mode === this.yoga.MEASURE_MODE_EXACTLY) return \"exactly\"\n if (mode === this.yoga.MEASURE_MODE_AT_MOST) return \"at-most\"\n return \"undefined\"\n }\n\n // Dimension setters\n setWidth(value: number): void {\n this.node.setWidth(value)\n }\n setWidthPercent(value: number): void {\n this.node.setWidthPercent(value)\n }\n setWidthAuto(): void {\n this.node.setWidthAuto()\n }\n setWidthFitContent(): void {\n // Yoga doesn't support fit-content natively — fall back to auto\n this.node.setWidthAuto()\n }\n setWidthSnugContent(): void {\n // Yoga doesn't support snug-content natively — fall back to auto\n this.node.setWidthAuto()\n }\n setHeight(value: number): void {\n this.node.setHeight(value)\n }\n setHeightPercent(value: number): void {\n this.node.setHeightPercent(value)\n }\n setHeightAuto(): void {\n this.node.setHeightAuto()\n }\n setMinWidth(value: number): void {\n this.node.setMinWidth(value)\n }\n setMinWidthPercent(value: number): void {\n this.node.setMinWidthPercent(value)\n }\n setMinHeight(value: number): void {\n this.node.setMinHeight(value)\n }\n setMinHeightPercent(value: number): void {\n this.node.setMinHeightPercent(value)\n }\n setMaxWidth(value: number): void {\n this.node.setMaxWidth(value)\n }\n setMaxWidthPercent(value: number): void {\n this.node.setMaxWidthPercent(value)\n }\n setMaxHeight(value: number): void {\n this.node.setMaxHeight(value)\n }\n setMaxHeightPercent(value: number): void {\n this.node.setMaxHeightPercent(value)\n }\n\n // Flex properties\n setFlexGrow(value: number): void {\n this.node.setFlexGrow(value)\n }\n setFlexShrink(value: number): void {\n this.node.setFlexShrink(value)\n }\n setFlexBasis(value: number): void {\n this.node.setFlexBasis(value)\n }\n setFlexBasisPercent(value: number): void {\n this.node.setFlexBasisPercent(value)\n }\n setFlexBasisAuto(): void {\n this.node.setFlexBasisAuto()\n }\n setFlexDirection(direction: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded FlexDirection type\n this.node.setFlexDirection(direction as FlexDirection)\n }\n setFlexWrap(wrap: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Wrap type\n this.node.setFlexWrap(wrap as Wrap)\n }\n\n // Alignment\n setAlignItems(align: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Align type\n this.node.setAlignItems(align as Align)\n }\n setAlignSelf(align: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Align type\n this.node.setAlignSelf(align as Align)\n }\n setAlignContent(align: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Align type\n this.node.setAlignContent(align as Align)\n }\n setJustifyContent(justify: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Justify type\n this.node.setJustifyContent(justify as Justify)\n }\n\n // Spacing\n setPadding(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setPadding(edge as Edge, value)\n }\n setMargin(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setMargin(edge as Edge, value)\n }\n setBorder(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setBorder(edge as Edge, value)\n }\n setGap(gutter: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Gutter type\n this.node.setGap(gutter as Gutter, value)\n }\n\n // Display & Position\n setDisplay(display: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Display type\n this.node.setDisplay(display as Display)\n }\n setPositionType(positionType: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded PositionType type\n this.node.setPositionType(positionType as PositionType)\n }\n setPosition(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setPosition(edge as Edge, value)\n }\n setPositionPercent(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setPositionPercent(edge as Edge, value)\n }\n setOverflow(overflow: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Overflow type\n this.node.setOverflow(overflow as Overflow)\n }\n\n // Container queries (A0.1) — yoga does NOT support these primitives. The\n // setters are no-ops; user-level guards via requireCapability(\"containerQueries\", ...)\n // at the React layer throw at first paint when consumers ask for CQ on yoga.\n setContainerType(_containerType: number): void {\n // no-op (yoga has no CQ support; capability is false)\n }\n setContainSize(_value: boolean): void {\n // no-op (yoga has no contain:size; capability is false)\n }\n\n // Fit-width (A0.2) — yoga has no equivalent primitive. No-op stub; React\n // layer's requireCapability(\"fitWidth\", ...) catches the user-level use.\n setFitWidth(_lanes: readonly FitWidthLane[] | undefined): void {\n // no-op (yoga has no fitWidth; capability is false)\n }\n\n // Aspect Ratio\n setAspectRatio(value: number): void {\n this.node.setAspectRatio(value)\n }\n\n // Layout calculation\n calculateLayout(width: number, height: number, direction?: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Direction type\n this.node.calculateLayout(width, height, (direction ?? this.yoga.DIRECTION_LTR) as Direction)\n }\n\n // Layout results\n getComputedLeft(): number {\n return this.node.getComputedLeft()\n }\n getComputedTop(): number {\n return this.node.getComputedTop()\n }\n getComputedWidth(): number {\n return this.node.getComputedWidth()\n }\n getComputedHeight(): number {\n return this.node.getComputedHeight()\n }\n}\n\n// ============================================================================\n// Yoga Layout Engine\n// ============================================================================\n\n/**\n * Layout engine implementation using Yoga (WASM).\n */\nexport class YogaLayoutEngine implements LayoutEngine {\n private yoga: Yoga\n private _constants: LayoutConstants\n\n constructor(yoga: Yoga) {\n this.yoga = yoga\n // Cast Yoga's branded types to our LayoutEngine branded types at the adapter boundary\n this._constants = {\n // Flex Direction\n FLEX_DIRECTION_COLUMN: yoga.FLEX_DIRECTION_COLUMN as unknown as FlexDirectionValue,\n FLEX_DIRECTION_COLUMN_REVERSE:\n yoga.FLEX_DIRECTION_COLUMN_REVERSE as unknown as FlexDirectionValue,\n FLEX_DIRECTION_ROW: yoga.FLEX_DIRECTION_ROW as unknown as FlexDirectionValue,\n FLEX_DIRECTION_ROW_REVERSE: yoga.FLEX_DIRECTION_ROW_REVERSE as unknown as FlexDirectionValue,\n\n // Wrap\n WRAP_NO_WRAP: yoga.WRAP_NO_WRAP as unknown as WrapValue,\n WRAP_WRAP: yoga.WRAP_WRAP as unknown as WrapValue,\n WRAP_WRAP_REVERSE: yoga.WRAP_WRAP_REVERSE as unknown as WrapValue,\n\n // Align\n ALIGN_AUTO: yoga.ALIGN_AUTO as unknown as AlignValue,\n ALIGN_FLEX_START: yoga.ALIGN_FLEX_START as unknown as AlignValue,\n ALIGN_CENTER: yoga.ALIGN_CENTER as unknown as AlignValue,\n ALIGN_FLEX_END: yoga.ALIGN_FLEX_END as unknown as AlignValue,\n ALIGN_STRETCH: yoga.ALIGN_STRETCH as unknown as AlignValue,\n ALIGN_BASELINE: yoga.ALIGN_BASELINE as unknown as AlignValue,\n ALIGN_SPACE_BETWEEN: yoga.ALIGN_SPACE_BETWEEN as unknown as AlignValue,\n ALIGN_SPACE_AROUND: yoga.ALIGN_SPACE_AROUND as unknown as AlignValue,\n ALIGN_SPACE_EVENLY: (yoga as any).ALIGN_SPACE_EVENLY as unknown as AlignValue,\n\n // Justify\n JUSTIFY_FLEX_START: yoga.JUSTIFY_FLEX_START as unknown as JustifyValue,\n JUSTIFY_CENTER: yoga.JUSTIFY_CENTER as unknown as JustifyValue,\n JUSTIFY_FLEX_END: yoga.JUSTIFY_FLEX_END as unknown as JustifyValue,\n JUSTIFY_SPACE_BETWEEN: yoga.JUSTIFY_SPACE_BETWEEN as unknown as JustifyValue,\n JUSTIFY_SPACE_AROUND: yoga.JUSTIFY_SPACE_AROUND as unknown as JustifyValue,\n JUSTIFY_SPACE_EVENLY: yoga.JUSTIFY_SPACE_EVENLY as unknown as JustifyValue,\n\n // Edge\n EDGE_LEFT: yoga.EDGE_LEFT as unknown as EdgeValue,\n EDGE_TOP: yoga.EDGE_TOP as unknown as EdgeValue,\n EDGE_RIGHT: yoga.EDGE_RIGHT as unknown as EdgeValue,\n EDGE_BOTTOM: yoga.EDGE_BOTTOM as unknown as EdgeValue,\n EDGE_HORIZONTAL: yoga.EDGE_HORIZONTAL as unknown as EdgeValue,\n EDGE_VERTICAL: yoga.EDGE_VERTICAL as unknown as EdgeValue,\n EDGE_ALL: yoga.EDGE_ALL as unknown as EdgeValue,\n\n // Gutter\n GUTTER_COLUMN: yoga.GUTTER_COLUMN as unknown as GutterValue,\n GUTTER_ROW: yoga.GUTTER_ROW as unknown as GutterValue,\n GUTTER_ALL: yoga.GUTTER_ALL as unknown as GutterValue,\n\n // Display\n DISPLAY_FLEX: yoga.DISPLAY_FLEX as unknown as DisplayValue,\n DISPLAY_NONE: yoga.DISPLAY_NONE as unknown as DisplayValue,\n\n // Position Type\n POSITION_TYPE_STATIC: yoga.POSITION_TYPE_STATIC as unknown as PositionTypeValue,\n POSITION_TYPE_RELATIVE: yoga.POSITION_TYPE_RELATIVE as unknown as PositionTypeValue,\n POSITION_TYPE_ABSOLUTE: yoga.POSITION_TYPE_ABSOLUTE as unknown as PositionTypeValue,\n\n // Overflow\n OVERFLOW_VISIBLE: yoga.OVERFLOW_VISIBLE as unknown as OverflowValue,\n OVERFLOW_HIDDEN: yoga.OVERFLOW_HIDDEN as unknown as OverflowValue,\n OVERFLOW_SCROLL: yoga.OVERFLOW_SCROLL as unknown as OverflowValue,\n\n // Direction\n DIRECTION_LTR: yoga.DIRECTION_LTR as unknown as DirectionValue,\n\n // Measure Mode\n MEASURE_MODE_UNDEFINED: yoga.MEASURE_MODE_UNDEFINED as unknown as MeasureModeValue,\n MEASURE_MODE_EXACTLY: yoga.MEASURE_MODE_EXACTLY as unknown as MeasureModeValue,\n MEASURE_MODE_AT_MOST: yoga.MEASURE_MODE_AT_MOST as unknown as MeasureModeValue,\n }\n }\n\n createNode(): LayoutNode {\n return new YogaNodeAdapter(this.yoga.Node.create(), this.yoga)\n }\n\n get constants(): LayoutConstants {\n return this._constants\n }\n\n get name(): string {\n return \"yoga\"\n }\n\n get capabilities(): EngineCapabilities {\n return YOGA_CAPABILITIES\n }\n}\n\n// ============================================================================\n// Initialization Helper\n// ============================================================================\n\n/**\n * Create a Yoga layout engine from an initialized Yoga instance.\n */\nexport function createYogaEngine(yoga: Yoga): YogaLayoutEngine {\n return new YogaLayoutEngine(yoga)\n}\n\n/**\n * Initialize Yoga and create a layout engine.\n * Uses yoga-wasm-web/auto which automatically selects the right implementation.\n */\nexport async function initYogaEngine(): Promise<YogaLayoutEngine> {\n const { default: yoga } = (await import(\"yoga-wasm-web/auto\")) as {\n default: Yoga\n }\n return new YogaLayoutEngine(yoga)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"yoga-adapter-CB_7pLyl.mjs","names":[],"sources":["../packages/ag-term/src/adapters/yoga-adapter.ts"],"sourcesContent":["/**\n * Yoga Layout Engine Adapter\n *\n * Wraps yoga-wasm-web to implement the LayoutEngine interface.\n */\n\nimport type {\n Align,\n Direction,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n Yoga,\n Node as YogaNode,\n} from \"yoga-wasm-web\"\nimport type { FitWidthLane, LayoutNode, MeasureFunc, MeasureMode } from \"@silvery/ag/layout-types\"\nimport type {\n AlignValue,\n DirectionValue,\n DisplayValue,\n EdgeValue,\n EngineCapabilities,\n FlexDirectionValue,\n GutterValue,\n JustifyValue,\n LayoutConstants,\n LayoutEngine,\n MeasureModeValue,\n OverflowValue,\n PositionTypeValue,\n WrapValue,\n} from \"../layout-engine\"\n\n/**\n * Capabilities advertised by the yoga adapter.\n *\n * **All flags stay `false`.** yoga's WASM boundary doesn't expose the inter-pass\n * child-style mutation hook that engine-native container queries, fitWidth, and the\n * cq*-unit / style-math-function primitives require. Consumers that need those\n * primitives must switch to flexily via `SILVERY_ENGINE=flexily` or\n * `ensureDefaultLayoutEngine(\"flexily\")`.\n *\n * The existing CSS-flexbox surface (Box/Text declarative props, useResponsiveBoxProps,\n * etc.) remains FULLY SUPPORTED under yoga — only the reframe's new primitives are gated.\n */\nconst YOGA_CAPABILITIES: EngineCapabilities = Object.freeze({\n containerQueries: false, // yoga has no CQ resolution; flexily-only\n containSize: false, // yoga has no contain:size; flexily-only\n containerQueryUnits: false, // yoga has no cq* parser; flexily-only\n fitWidth: false, // yoga has no fitWidth Box prop; flexily-only\n styleMathFunctions: false, // yoga has no late-bound math; flexily-only\n childStyleMutation: false, // yoga's WASM boundary blocks the hook\n})\n\n// ============================================================================\n// Yoga Node Adapter\n// ============================================================================\n\n/**\n * Wraps a Yoga node to implement LayoutNode interface.\n */\nclass YogaNodeAdapter implements LayoutNode {\n private node: YogaNode\n private yoga: Yoga\n private hasMeasureFunc = false\n\n constructor(node: YogaNode, yoga: Yoga) {\n this.node = node\n this.yoga = yoga\n }\n\n /** Get the underlying Yoga node (for tree operations) */\n getYogaNode(): YogaNode {\n return this.node\n }\n\n // Tree operations\n insertChild(child: LayoutNode, index: number): void {\n const yogaChild = (child as YogaNodeAdapter).getYogaNode()\n this.node.insertChild(yogaChild, index)\n }\n\n removeChild(child: LayoutNode): void {\n const yogaChild = (child as YogaNodeAdapter).getYogaNode()\n this.node.removeChild(yogaChild)\n }\n\n free(): void {\n this.node.free()\n }\n\n // Measure function\n setMeasureFunc(measureFunc: MeasureFunc): void {\n this.hasMeasureFunc = true\n this.node.setMeasureFunc((width, widthMode, height, heightMode) => {\n const widthModeStr = this.measureModeToString(widthMode)\n const heightModeStr = this.measureModeToString(heightMode)\n return measureFunc(width, widthModeStr, height, heightModeStr)\n })\n }\n\n // Dirty tracking - forces layout recalculation\n // Yoga only allows markDirty() on leaf nodes with measure functions\n markDirty(): void {\n if (this.hasMeasureFunc) {\n this.node.markDirty()\n }\n }\n isDirty(): boolean {\n return this.node.isDirty()\n }\n\n private measureModeToString(mode: number): MeasureMode {\n if (mode === this.yoga.MEASURE_MODE_EXACTLY) return \"exactly\"\n if (mode === this.yoga.MEASURE_MODE_AT_MOST) return \"at-most\"\n return \"undefined\"\n }\n\n // Dimension setters\n setWidth(value: number): void {\n this.node.setWidth(value)\n }\n setWidthPercent(value: number): void {\n this.node.setWidthPercent(value)\n }\n setWidthAuto(): void {\n this.node.setWidthAuto()\n }\n setWidthFitContent(): void {\n // Yoga doesn't support fit-content natively — fall back to auto\n this.node.setWidthAuto()\n }\n setWidthSnugContent(): void {\n // Yoga doesn't support snug-content natively — fall back to auto\n this.node.setWidthAuto()\n }\n setHeight(value: number): void {\n this.node.setHeight(value)\n }\n setHeightPercent(value: number): void {\n this.node.setHeightPercent(value)\n }\n setHeightAuto(): void {\n this.node.setHeightAuto()\n }\n setMinWidth(value: number): void {\n this.node.setMinWidth(value)\n }\n setMinWidthPercent(value: number): void {\n this.node.setMinWidthPercent(value)\n }\n setMinHeight(value: number): void {\n this.node.setMinHeight(value)\n }\n setMinHeightPercent(value: number): void {\n this.node.setMinHeightPercent(value)\n }\n setMaxWidth(value: number): void {\n this.node.setMaxWidth(value)\n }\n setMaxWidthPercent(value: number): void {\n this.node.setMaxWidthPercent(value)\n }\n setMaxHeight(value: number): void {\n this.node.setMaxHeight(value)\n }\n setMaxHeightPercent(value: number): void {\n this.node.setMaxHeightPercent(value)\n }\n\n // Flex properties\n setFlexGrow(value: number): void {\n this.node.setFlexGrow(value)\n }\n setFlexShrink(value: number): void {\n this.node.setFlexShrink(value)\n }\n setFlexBasis(value: number): void {\n this.node.setFlexBasis(value)\n }\n setFlexBasisPercent(value: number): void {\n this.node.setFlexBasisPercent(value)\n }\n setFlexBasisAuto(): void {\n this.node.setFlexBasisAuto()\n }\n setFlexDirection(direction: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded FlexDirection type\n this.node.setFlexDirection(direction as FlexDirection)\n }\n setFlexWrap(wrap: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Wrap type\n this.node.setFlexWrap(wrap as Wrap)\n }\n\n // Alignment\n setAlignItems(align: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Align type\n this.node.setAlignItems(align as Align)\n }\n setAlignSelf(align: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Align type\n this.node.setAlignSelf(align as Align)\n }\n setAlignContent(align: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Align type\n this.node.setAlignContent(align as Align)\n }\n setJustifyContent(justify: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Justify type\n this.node.setJustifyContent(justify as Justify)\n }\n\n // Spacing\n setPadding(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setPadding(edge as Edge, value)\n }\n setMargin(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setMargin(edge as Edge, value)\n }\n setBorder(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setBorder(edge as Edge, value)\n }\n setGap(gutter: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Gutter type\n this.node.setGap(gutter as Gutter, value)\n }\n\n // Display & Position\n setDisplay(display: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Display type\n this.node.setDisplay(display as Display)\n }\n setPositionType(positionType: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded PositionType type\n this.node.setPositionType(positionType as PositionType)\n }\n setPosition(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setPosition(edge as Edge, value)\n }\n setPositionPercent(edge: number, value: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Edge type\n this.node.setPositionPercent(edge as Edge, value)\n }\n setOverflow(overflow: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Overflow type\n this.node.setOverflow(overflow as Overflow)\n }\n\n // Container queries (A0.1) — yoga does NOT support these primitives. The\n // setters are no-ops; user-level guards via requireCapability(\"containerQueries\", ...)\n // at the React layer throw at first paint when consumers ask for CQ on yoga.\n setContainerType(_containerType: number): void {\n // no-op (yoga has no CQ support; capability is false)\n }\n setContainSize(_value: boolean): void {\n // no-op (yoga has no contain:size; capability is false)\n }\n\n // Fit-width (A0.2) — yoga has no equivalent primitive. No-op stub; React\n // layer's requireCapability(\"fitWidth\", ...) catches the user-level use.\n setFitWidth(_lanes: readonly FitWidthLane[] | undefined): void {\n // no-op (yoga has no fitWidth; capability is false)\n }\n\n // Aspect Ratio\n setAspectRatio(value: number): void {\n this.node.setAspectRatio(value)\n }\n\n // Layout calculation\n calculateLayout(width: number, height: number, direction?: number): void {\n // LayoutEngine uses plain numbers; Yoga uses branded Direction type\n this.node.calculateLayout(width, height, (direction ?? this.yoga.DIRECTION_LTR) as Direction)\n }\n\n // Layout results\n getComputedLeft(): number {\n return this.node.getComputedLeft()\n }\n getComputedTop(): number {\n return this.node.getComputedTop()\n }\n getComputedWidth(): number {\n return this.node.getComputedWidth()\n }\n getComputedHeight(): number {\n return this.node.getComputedHeight()\n }\n}\n\n// ============================================================================\n// Yoga Layout Engine\n// ============================================================================\n\n/**\n * Layout engine implementation using Yoga (WASM).\n */\nexport class YogaLayoutEngine implements LayoutEngine {\n private yoga: Yoga\n private _constants: LayoutConstants\n\n constructor(yoga: Yoga) {\n this.yoga = yoga\n // Cast Yoga's branded types to our LayoutEngine branded types at the adapter boundary\n this._constants = {\n // Flex Direction\n FLEX_DIRECTION_COLUMN: yoga.FLEX_DIRECTION_COLUMN as unknown as FlexDirectionValue,\n FLEX_DIRECTION_COLUMN_REVERSE:\n yoga.FLEX_DIRECTION_COLUMN_REVERSE as unknown as FlexDirectionValue,\n FLEX_DIRECTION_ROW: yoga.FLEX_DIRECTION_ROW as unknown as FlexDirectionValue,\n FLEX_DIRECTION_ROW_REVERSE: yoga.FLEX_DIRECTION_ROW_REVERSE as unknown as FlexDirectionValue,\n\n // Wrap\n WRAP_NO_WRAP: yoga.WRAP_NO_WRAP as unknown as WrapValue,\n WRAP_WRAP: yoga.WRAP_WRAP as unknown as WrapValue,\n WRAP_WRAP_REVERSE: yoga.WRAP_WRAP_REVERSE as unknown as WrapValue,\n\n // Align\n ALIGN_AUTO: yoga.ALIGN_AUTO as unknown as AlignValue,\n ALIGN_FLEX_START: yoga.ALIGN_FLEX_START as unknown as AlignValue,\n ALIGN_CENTER: yoga.ALIGN_CENTER as unknown as AlignValue,\n ALIGN_FLEX_END: yoga.ALIGN_FLEX_END as unknown as AlignValue,\n ALIGN_STRETCH: yoga.ALIGN_STRETCH as unknown as AlignValue,\n ALIGN_BASELINE: yoga.ALIGN_BASELINE as unknown as AlignValue,\n ALIGN_SPACE_BETWEEN: yoga.ALIGN_SPACE_BETWEEN as unknown as AlignValue,\n ALIGN_SPACE_AROUND: yoga.ALIGN_SPACE_AROUND as unknown as AlignValue,\n ALIGN_SPACE_EVENLY: (yoga as any).ALIGN_SPACE_EVENLY as unknown as AlignValue,\n\n // Justify\n JUSTIFY_FLEX_START: yoga.JUSTIFY_FLEX_START as unknown as JustifyValue,\n JUSTIFY_CENTER: yoga.JUSTIFY_CENTER as unknown as JustifyValue,\n JUSTIFY_FLEX_END: yoga.JUSTIFY_FLEX_END as unknown as JustifyValue,\n JUSTIFY_SPACE_BETWEEN: yoga.JUSTIFY_SPACE_BETWEEN as unknown as JustifyValue,\n JUSTIFY_SPACE_AROUND: yoga.JUSTIFY_SPACE_AROUND as unknown as JustifyValue,\n JUSTIFY_SPACE_EVENLY: yoga.JUSTIFY_SPACE_EVENLY as unknown as JustifyValue,\n\n // Edge\n EDGE_LEFT: yoga.EDGE_LEFT as unknown as EdgeValue,\n EDGE_TOP: yoga.EDGE_TOP as unknown as EdgeValue,\n EDGE_RIGHT: yoga.EDGE_RIGHT as unknown as EdgeValue,\n EDGE_BOTTOM: yoga.EDGE_BOTTOM as unknown as EdgeValue,\n EDGE_HORIZONTAL: yoga.EDGE_HORIZONTAL as unknown as EdgeValue,\n EDGE_VERTICAL: yoga.EDGE_VERTICAL as unknown as EdgeValue,\n EDGE_ALL: yoga.EDGE_ALL as unknown as EdgeValue,\n\n // Gutter\n GUTTER_COLUMN: yoga.GUTTER_COLUMN as unknown as GutterValue,\n GUTTER_ROW: yoga.GUTTER_ROW as unknown as GutterValue,\n GUTTER_ALL: yoga.GUTTER_ALL as unknown as GutterValue,\n\n // Display\n DISPLAY_FLEX: yoga.DISPLAY_FLEX as unknown as DisplayValue,\n DISPLAY_NONE: yoga.DISPLAY_NONE as unknown as DisplayValue,\n\n // Position Type\n POSITION_TYPE_STATIC: yoga.POSITION_TYPE_STATIC as unknown as PositionTypeValue,\n POSITION_TYPE_RELATIVE: yoga.POSITION_TYPE_RELATIVE as unknown as PositionTypeValue,\n POSITION_TYPE_ABSOLUTE: yoga.POSITION_TYPE_ABSOLUTE as unknown as PositionTypeValue,\n\n // Overflow\n OVERFLOW_VISIBLE: yoga.OVERFLOW_VISIBLE as unknown as OverflowValue,\n OVERFLOW_HIDDEN: yoga.OVERFLOW_HIDDEN as unknown as OverflowValue,\n OVERFLOW_SCROLL: yoga.OVERFLOW_SCROLL as unknown as OverflowValue,\n\n // Direction\n DIRECTION_LTR: yoga.DIRECTION_LTR as unknown as DirectionValue,\n\n // Measure Mode\n MEASURE_MODE_UNDEFINED: yoga.MEASURE_MODE_UNDEFINED as unknown as MeasureModeValue,\n MEASURE_MODE_EXACTLY: yoga.MEASURE_MODE_EXACTLY as unknown as MeasureModeValue,\n MEASURE_MODE_AT_MOST: yoga.MEASURE_MODE_AT_MOST as unknown as MeasureModeValue,\n }\n }\n\n createNode(): LayoutNode {\n return new YogaNodeAdapter(this.yoga.Node.create(), this.yoga)\n }\n\n get constants(): LayoutConstants {\n return this._constants\n }\n\n get name(): string {\n return \"yoga\"\n }\n\n get capabilities(): EngineCapabilities {\n return YOGA_CAPABILITIES\n }\n}\n\n// ============================================================================\n// Initialization Helper\n// ============================================================================\n\n/**\n * Create a Yoga layout engine from an initialized Yoga instance.\n */\nexport function createYogaEngine(yoga: Yoga): YogaLayoutEngine {\n return new YogaLayoutEngine(yoga)\n}\n\n/**\n * Initialize Yoga and create a layout engine.\n * Uses yoga-wasm-web/auto which automatically selects the right implementation.\n */\nexport async function initYogaEngine(): Promise<YogaLayoutEngine> {\n const { default: yoga } = (await import(\"yoga-wasm-web/auto\")) as {\n default: Yoga\n }\n return new YogaLayoutEngine(yoga)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "silvery",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"description": "React for modern terminal apps — powerful apps, polished UIs, proudly terminal",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ansi",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
},
|
|
33
33
|
"workspaces": [
|
|
34
34
|
"packages/*",
|
|
35
|
-
"!packages/examples",
|
|
36
35
|
"!examples"
|
|
37
36
|
],
|
|
38
37
|
"files": [
|
|
@@ -56,6 +55,10 @@
|
|
|
56
55
|
"types": "./dist/theme.d.mts",
|
|
57
56
|
"import": "./dist/theme.mjs"
|
|
58
57
|
},
|
|
58
|
+
"./test": {
|
|
59
|
+
"types": "./dist/test.d.mts",
|
|
60
|
+
"import": "./dist/test.mjs"
|
|
61
|
+
},
|
|
59
62
|
"./ui": {
|
|
60
63
|
"types": "./dist/ui.d.mts",
|
|
61
64
|
"import": "./dist/ui.mjs"
|
|
@@ -69,9 +72,9 @@
|
|
|
69
72
|
"access": "public"
|
|
70
73
|
},
|
|
71
74
|
"dependencies": {
|
|
72
|
-
"@chenglou/pretext": "^0.0.
|
|
73
|
-
"@silvery/color": "0.
|
|
74
|
-
"@silvery/commander": "0.
|
|
75
|
+
"@chenglou/pretext": "^0.0.8",
|
|
76
|
+
"@silvery/color": "0.23.0",
|
|
77
|
+
"@silvery/commander": "0.23.0",
|
|
75
78
|
"@termless/core": "^0.8.1",
|
|
76
79
|
"css-select": "^7.0.0",
|
|
77
80
|
"css-what": "^8.0.0",
|
|
@@ -79,16 +82,15 @@
|
|
|
79
82
|
"loggily": "^0.10.2",
|
|
80
83
|
"react-reconciler": "^0.33.0",
|
|
81
84
|
"slice-ansi": "^8.0.0",
|
|
82
|
-
"string-width": "^8.2.
|
|
85
|
+
"string-width": "^8.2.2"
|
|
83
86
|
},
|
|
84
87
|
"devDependencies": {
|
|
85
88
|
"@braintree/sanitize-url": "^7.1.2",
|
|
86
|
-
"@silvery/ag": "0.
|
|
87
|
-
"@silvery/ag-react": "0.
|
|
88
|
-
"@silvery/ag-term": "0.
|
|
89
|
-
"@silvery/ansi": "0.
|
|
90
|
-
"@silvery/theme": "0.
|
|
91
|
-
"@termless/core": "^0.8.1",
|
|
89
|
+
"@silvery/ag": "0.23.0",
|
|
90
|
+
"@silvery/ag-react": "0.23.0",
|
|
91
|
+
"@silvery/ag-term": "0.23.0",
|
|
92
|
+
"@silvery/ansi": "0.23.0",
|
|
93
|
+
"@silvery/theme": "0.23.0",
|
|
92
94
|
"@termless/ghostty": "^0.8.2",
|
|
93
95
|
"@termless/ghostty-native": "^0.8.1",
|
|
94
96
|
"@termless/test": "^0.8.1",
|
|
@@ -111,6 +113,7 @@
|
|
|
111
113
|
"playwright": "^1.58.2",
|
|
112
114
|
"react": "^19.0.0",
|
|
113
115
|
"rolldown": "^1.0.0-rc.15",
|
|
116
|
+
"silvery": "link:.",
|
|
114
117
|
"ts-morph": "^24.0.0",
|
|
115
118
|
"tsdown": "^0.21.7",
|
|
116
119
|
"typescript": "^5.5.0",
|
|
@@ -122,7 +125,7 @@
|
|
|
122
125
|
"vitepress-plugin-diagrams": "^1.2.2",
|
|
123
126
|
"vitepress-plugin-llms": "^1.0.0",
|
|
124
127
|
"vitepress-plugin-mermaid": "^2.0.17",
|
|
125
|
-
"vitest": "4.1.
|
|
128
|
+
"vitest": "4.1.10",
|
|
126
129
|
"vue": "^3.5.31",
|
|
127
130
|
"yoga-wasm-web": "^0.3.3"
|
|
128
131
|
},
|
|
@@ -163,6 +166,7 @@
|
|
|
163
166
|
"src/runtime.ts",
|
|
164
167
|
"src/term.ts",
|
|
165
168
|
"src/theme.ts",
|
|
169
|
+
"src/test.ts",
|
|
166
170
|
"src/ui.ts",
|
|
167
171
|
"src/ui/*.ts"
|
|
168
172
|
],
|
|
@@ -174,19 +178,20 @@
|
|
|
174
178
|
},
|
|
175
179
|
"scripts": {
|
|
176
180
|
"build": "tsdown",
|
|
177
|
-
"build:all": "tsdown && tsdown -W -F '@silvery/ag' -F '@silvery/ag-react' -F '@silvery/ag-term' -F '@silvery/ansi' -F '@silvery/color' -F '@silvery/command' -F '@silvery/commander' -F '@silvery/commands' -F '@silvery/config' -F '@silvery/create' -F '@silvery/headless' -F '@silvery/ink' -F '@silvery/
|
|
181
|
+
"build:all": "tsdown && tsdown -W -F '@silvery/ag' -F '@silvery/ag-react' -F '@silvery/ag-term' -F '@silvery/ansi' -F '@silvery/color' -F '@silvery/command' -F '@silvery/commander' -F '@silvery/commands' -F '@silvery/config' -F '@silvery/create' -F '@silvery/headless' -F '@silvery/ink' -F '@silvery/scope' -F '@silvery/selection' -F '@silvery/signals' -F '@silvery/syntax' -F '@silvery/theme'",
|
|
178
182
|
"test": "NODE_ENV=test bunx --bun vitest run",
|
|
179
183
|
"test:fast": "NODE_ENV=test bunx --bun vitest run --reporter=dot",
|
|
180
184
|
"typecheck": "tsc --noEmit",
|
|
181
|
-
"lint": "oxlint . && oxfmt --check . && bun scripts/lint-env-reads.ts && bun scripts/lint-no-raw-mode.ts && bun scripts/lint-no-async-unmount.ts",
|
|
185
|
+
"lint": "oxlint . && oxfmt --check . && bun scripts/lint-env-reads.ts && bun scripts/lint-no-raw-mode.ts && bun scripts/lint-no-async-unmount.ts && bun scripts/lint-no-in-flight-rect-in-app.ts",
|
|
182
186
|
"lint:env-reads": "bun scripts/lint-env-reads.ts",
|
|
183
187
|
"lint:raw-mode": "bun scripts/lint-no-raw-mode.ts",
|
|
184
188
|
"lint:async-unmount": "bun scripts/lint-no-async-unmount.ts",
|
|
189
|
+
"lint:in-flight-rect": "bun scripts/lint-no-in-flight-rect-in-app.ts",
|
|
185
190
|
"fix": "oxlint --fix . && oxfmt --write .",
|
|
186
191
|
"docs:dev": "vitepress dev docs",
|
|
187
192
|
"docs:build": "vitepress build docs",
|
|
188
193
|
"docs:preview": "vitepress preview docs",
|
|
189
|
-
"docs:gen": "bun scripts/gen-token-docs.ts",
|
|
194
|
+
"docs:gen": "bun scripts/gen-token-docs.ts && oxfmt docs/reference/tokens.md",
|
|
190
195
|
"docs:check": "bun run docs:gen && git diff --exit-code docs/reference/tokens.md",
|
|
191
196
|
"theme": "bun packages/theme/src/cli.ts",
|
|
192
197
|
"demo": "bun examples/bin/cli.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Text-BRf-59j2.mjs","names":["signalEffect"],"sources":["../packages/ag-react/src/components/Box.tsx","../packages/ag-react/src/ThemeContext.tsx","../packages/ag-react/src/components/Text.tsx"],"sourcesContent":["/**\n * Silvery Box Component\n *\n * The primary layout primitive for Silvery. Box is a flexbox container that can hold\n * other Box or Text components. It supports all standard flexbox properties,\n * dimensions, spacing, and borders.\n *\n * Box renders to an 'silvery-box' host element that the reconciler converts to an\n * SilveryNode with an associated Yoga layout node.\n *\n * Box provides NodeContext to its children, enabling useBoxRect/useScrollRect hooks.\n * It also supports forwardRef for imperative access and onLayout for layout callbacks.\n */\n\nimport {\n type ForwardedRef,\n type JSX,\n type ReactNode,\n forwardRef,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\"\nimport { effect as signalEffect } from \"@silvery/signals\"\nimport { NodeContext } from \"../context\"\nimport { getLayoutSignals, observeLayoutSignal } from \"@silvery/ag/layout-signals\"\nimport type { BoxProps as BoxPropsType, AgNode, Rect } from \"@silvery/ag/types\"\n\n// ============================================================================\n// Props\n// ============================================================================\n\nexport interface BoxProps extends BoxPropsType {\n /** Child elements */\n children?: ReactNode\n}\n\n/**\n * Methods exposed via ref on Box component.\n */\nexport interface BoxHandle {\n /** Get the underlying SilveryNode */\n getNode(): AgNode | null\n /** Get the current content-relative layout rect */\n getBoxRect(): Rect | null\n /** Get the current screen-relative layout rect */\n getScrollRect(): Rect | null\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Flexbox container component for terminal UIs.\n *\n * Provides NodeContext to children, enabling useBoxRect/useScrollRect hooks.\n * Supports forwardRef for imperative access and onLayout for layout callbacks.\n *\n * @example\n * ```tsx\n * // Basic vertical layout (default)\n * <Box>\n * <Text>Line 1</Text>\n * <Text>Line 2</Text>\n * </Box>\n *\n * // Horizontal layout with spacing\n * <Box flexDirection=\"row\" gap={2}>\n * <Box width={10}><Text>Left</Text></Box>\n * <Box flexGrow={1}><Text>Center</Text></Box>\n * <Box width={10}><Text>Right</Text></Box>\n * </Box>\n *\n * // With border\n * <Box borderStyle=\"single\" borderColor=\"green\" padding={1}>\n * <Text>Boxed content</Text>\n * </Box>\n *\n * // With ref and onLayout\n * const boxRef = useRef<BoxHandle>(null);\n * <Box\n * ref={boxRef}\n * onLayout={(layout) => console.log('Size:', layout.width, layout.height)}\n * >\n * <Text>Content</Text>\n * </Box>\n * ```\n */\nexport const Box = forwardRef(function Box(\n props: BoxProps,\n ref: ForwardedRef<BoxHandle>,\n): JSX.Element {\n const { children, onLayout, ...restProps } = props\n const nodeRef = useRef<AgNode | null>(null)\n const [node, setNode] = useState<AgNode | null>(null)\n\n // Track the last layout we reported to onLayout to avoid duplicate calls\n const lastReportedLayout = useRef<Rect | null>(null)\n\n // After mount, ref points to the SilveryNode. Update state once to provide\n // the node to children via context. Only runs on mount ([] deps).\n useLayoutEffect(() => {\n if (nodeRef.current) {\n setNode(nodeRef.current)\n }\n }, [])\n\n // Wire up onLayout callback - subscribe via layout signals\n useLayoutEffect(() => {\n if (!onLayout || !node) return\n\n const releaseObservation = observeLayoutSignal(node, \"boxRect\")\n const signals = getLayoutSignals(node)\n const onLayoutRef = { current: onLayout }\n onLayoutRef.current = onLayout\n\n const dispose = signalEffect(() => {\n const layout = signals.boxRect()\n if (!layout) return\n\n // Only call onLayout if layout actually changed\n const last = lastReportedLayout.current\n if (\n !last ||\n last.x !== layout.x ||\n last.y !== layout.y ||\n last.width !== layout.width ||\n last.height !== layout.height\n ) {\n lastReportedLayout.current = layout\n onLayoutRef.current(layout)\n }\n })\n\n return () => {\n dispose()\n releaseObservation()\n }\n }, [node, onLayout])\n\n // Expose imperative methods via ref\n useImperativeHandle(\n ref,\n () => ({\n getNode: () => nodeRef.current,\n getBoxRect: () => nodeRef.current?.boxRect ?? null,\n getScrollRect: () => nodeRef.current?.scrollRect ?? null,\n }),\n [],\n )\n\n // Render silvery-box with ref, wrap children in NodeContext\n // The reconciler creates an SilveryNode, ref gives us access to it\n return (\n <silvery-box ref={nodeRef} {...restProps}>\n <NodeContext.Provider value={node}>{children}</NodeContext.Provider>\n </silvery-box>\n )\n})\n","/**\n * ThemeContext — delivers a Theme to the component tree.\n *\n * Wrap your app (or a subtree) in `<ThemeProvider theme={…}>` to make\n * `$token` color props resolve against that theme. Components call\n * `useTheme()` to read the current theme.\n *\n * @example\n * ```tsx\n * import { ThemeProvider, defaultDarkTheme } from '@silvery/ag-react'\n *\n * <ThemeProvider theme={defaultDarkTheme}>\n * <App />\n * </ThemeProvider>\n * ```\n */\n\nimport { createContext, useContext } from \"react\"\nimport type { Theme, ActiveScheme } from \"@silvery/ansi\"\nimport { defaultDarkTheme } from \"@silvery/theme/schemes\"\n\n// ============================================================================\n// Context\n// ============================================================================\n\n/** @internal Exported for ThemeProvider and Text component — not public API. */\nexport const ThemeContext = createContext<Theme>(defaultDarkTheme)\n\n/**\n * Context that carries scheme detection metadata (name, source, confidence).\n *\n * Separate from ThemeContext because scheme metadata is orthogonal to the\n * theme token bag. Populated by `<ThemeProvider scheme={...}>` when the\n * caller passes detection provenance (e.g. from `runThemed`). Null when\n * no scheme metadata was injected.\n *\n * @internal Exported for ThemeProvider.\n */\nexport const ActiveSchemeContext = createContext<ActiveScheme | null>(null)\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Read the current theme from context.\n *\n * Returns `defaultDarkTheme` when no `ThemeProvider` is present.\n */\nexport function useTheme(): Theme {\n return useContext(ThemeContext)\n}\n","/**\n * Silvery Text Component\n *\n * The primitive for rendering text content in Silvery. Text supports styling\n * (colors, bold, italic, etc.) and text wrapping/truncation modes.\n *\n * Text renders to an 'silvery-text' host element that the reconciler converts\n * to an SilveryNode containing the text content.\n *\n * Supports forwardRef for imperative access to the underlying node.\n */\n\nimport { type ForwardedRef, type JSX, type ReactNode, forwardRef, useContext } from \"react\"\nimport type { AgNode, TextProps as TextPropsType } from \"@silvery/ag/types\"\nimport type { KnownVariant, Theme } from \"@silvery/ansi\"\nimport { KNOWN_VARIANTS } from \"@silvery/ansi\"\nimport { ThemeContext } from \"../ThemeContext\"\n\n// ============================================================================\n// Runtime variant warning — fires once per (theme, variantName) pair.\n// Warns the developer that a variant lookup returned undefined (typo, etc.).\n// Does NOT throw — silent no-op rendering is still the correct behavior.\n// Only fires in development/test (process.env.NODE_ENV !== \"production\").\n// ============================================================================\n\n/** Per-theme set of variant names that have already triggered a warning. */\nconst _warnedVariants = new WeakMap<Theme, Set<string>>()\n\nfunction warnOnce(theme: Theme, variant: string): void {\n if (process.env.NODE_ENV === \"production\") return\n let warned = _warnedVariants.get(theme)\n if (warned === undefined) {\n warned = new Set<string>()\n _warnedVariants.set(theme, warned)\n }\n if (warned.has(variant)) return\n warned.add(variant)\n const known = KNOWN_VARIANTS.join(\", \")\n // eslint-disable-next-line no-console\n console.warn(\n `[silvery] <Text variant=\"${variant}\"> — unknown variant, defaulting to bare. ` +\n `Known: ${known}. ` +\n `Register custom variants via <ThemeProvider tokens={{ variants: { ${variant}: {...} } }}>.`,\n )\n}\n\n// ============================================================================\n// Props\n// ============================================================================\n\nexport interface TextProps extends TextPropsType {\n /** Text content (string, number, or nested Text elements) */\n children?: ReactNode\n /**\n * Typography variant — pulls defaults from `theme.variants[variant]`.\n * Caller props always win over variant values (variant is the *default*).\n *\n * @example\n * ```tsx\n * <Text variant=\"h1\">Title</Text>\n * // → uses theme.variants.h1 as defaults ({ color: \"$fg-accent\", bold: true })\n *\n * <Text variant=\"h1\" color=\"$fg-success\">Done</Text>\n * // → color=\"$fg-success\" wins; bold still comes from variant\n * ```\n */\n variant?: KnownVariant\n}\n\n/**\n * Methods exposed via ref on Text component.\n */\nexport interface TextHandle {\n /** Get the underlying SilveryNode */\n getNode(): AgNode | null\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Text rendering component for terminal UIs.\n *\n * Supports forwardRef for imperative access to the underlying node.\n *\n * @example\n * ```tsx\n * // Basic text\n * <Text>Hello, world!</Text>\n *\n * // Colored text\n * <Text color=\"green\">Success!</Text>\n * <Text color=\"#ff6600\">Orange text</Text>\n *\n * // Styled text\n * <Text bold>Important</Text>\n * <Text italic underline>Emphasized</Text>\n *\n * // Combined styles\n * <Text color=\"red\" bold inverse>Alert!</Text>\n *\n * // Nested text with different styles\n * <Text>\n * Normal <Text bold>bold</Text> normal\n * </Text>\n *\n * // Truncation modes\n * <Text wrap=\"truncate\">This long text will be truncated...</Text>\n * <Text wrap=\"truncate-middle\">Long...text</Text>\n *\n * // With ref\n * const textRef = useRef<TextHandle>(null);\n * <Text ref={textRef}>Hello</Text>\n *\n * // With variant — typography presets from theme\n * <Text variant=\"h1\">Page Title</Text>\n * <Text variant=\"body-muted\">Caption text</Text>\n * <Text variant=\"h1\" color=\"$fg-success\">Done</Text> // caller color wins\n * ```\n */\nexport const Text = forwardRef(function Text(\n props: TextProps,\n ref: ForwardedRef<TextHandle>,\n): JSX.Element {\n const { children, variant, ...callerProps } = props\n const theme = useContext(ThemeContext)\n\n // Resolve variant defaults. Variant is the DEFAULT; caller props always win.\n //\n // Merge strategy (three passes):\n // 1. callerProps — base layer: all caller props including undefined values\n // (preserves non-style props like wrap, data-*, etc.)\n // 2. variantDefaults — overwrite only where callerProps was undefined\n // (fills in color/bold/etc when caller didn't specify)\n // 3. definedCallerProps — restore any explicitly provided caller overrides\n // (e.g. color=\"$fg-success\", bold={false} win over variant)\n //\n // Example: `<Text variant=\"h1\">T</Text>` (color not passed → undefined)\n // callerProps = { color: undefined }\n // variantDefaults = { color: \"$fg-accent\", bold: true }\n // definedCallerProps = {} (color=undefined excluded)\n // → { color: \"$fg-accent\", bold: true } ✓\n //\n // Example: `<Text variant=\"h1\" color=\"$fg-success\">T</Text>`\n // callerProps = { color: \"$fg-success\" }\n // variantDefaults = { color: \"$fg-accent\", bold: true }\n // definedCallerProps = { color: \"$fg-success\" }\n // → { color: \"$fg-success\", bold: true } ✓ (caller color wins)\n let styleProps = callerProps\n if (variant != null) {\n const resolved = theme.variants?.[variant]\n if (resolved === undefined) {\n warnOnce(theme, variant)\n }\n const variantDefaults = resolved ?? {}\n const definedCallerProps: Record<string, unknown> = {}\n for (const key of Object.keys(callerProps)) {\n const v = (callerProps as Record<string, unknown>)[key]\n if (v !== undefined) definedCallerProps[key] = v\n }\n styleProps = { ...callerProps, ...variantDefaults, ...definedCallerProps } as typeof callerProps\n }\n\n // For Text, we need to pass the ref through to the host element\n // The reconciler's getPublicInstance will return the SilveryNode\n // We wrap it in a TextHandle for type safety\n return (\n <silvery-text\n ref={(node: AgNode | null) => {\n // Handle both callback refs and RefObjects\n if (typeof ref === \"function\") {\n ref(node ? { getNode: () => node } : null)\n } else if (ref) {\n ref.current = node ? { getNode: () => node } : null\n }\n }}\n {...styleProps}\n >\n {children}\n </silvery-text>\n )\n})\n"],"mappings":"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"}
|