silvery 0.17.0 → 0.17.2

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.
Files changed (171) hide show
  1. package/dist/UPNG-AVSMjiFE.mjs +5076 -0
  2. package/dist/UPNG-AVSMjiFE.mjs.map +1 -0
  3. package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs +6 -0
  4. package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs.map +1 -0
  5. package/dist/animation-C_PTO0uH.mjs +304 -0
  6. package/dist/animation-C_PTO0uH.mjs.map +1 -0
  7. package/dist/ansi-CXLE_pt1.mjs +71 -0
  8. package/dist/ansi-CXLE_pt1.mjs.map +1 -0
  9. package/dist/ansi-zmNzgkPB.d.mts +49 -0
  10. package/dist/ansi-zmNzgkPB.d.mts.map +1 -0
  11. package/dist/apng-DCWY913R.mjs +3 -0
  12. package/dist/apng-ENBAJk-H.mjs +70 -0
  13. package/dist/apng-ENBAJk-H.mjs.map +1 -0
  14. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  15. package/dist/backend-CkIkIHR-.mjs +13396 -0
  16. package/dist/backend-CkIkIHR-.mjs.map +1 -0
  17. package/dist/backends-CkvbG3js.mjs +1181 -0
  18. package/dist/backends-CkvbG3js.mjs.map +1 -0
  19. package/dist/backends-CyJqNLeK.mjs +3 -0
  20. package/dist/chunk-BSw8zbkd.mjs +37 -0
  21. package/dist/cli-B-k7Bm56.mjs +4 -0
  22. package/dist/context-QreF3UHr.mjs +64 -0
  23. package/dist/context-QreF3UHr.mjs.map +1 -0
  24. package/dist/derive-D7bFJdfU.d.mts +28 -0
  25. package/dist/derive-D7bFJdfU.d.mts.map +1 -0
  26. package/dist/devtools-CscuKaDK.mjs +89 -0
  27. package/dist/devtools-CscuKaDK.mjs.map +1 -0
  28. package/dist/devtools-D4oGc6LY.mjs +2 -0
  29. package/dist/eta-DLiVPaSD.mjs +110 -0
  30. package/dist/eta-DLiVPaSD.mjs.map +1 -0
  31. package/dist/flexily-zero-adapter-DmG4Ge8t.mjs +3376 -0
  32. package/dist/flexily-zero-adapter-DmG4Ge8t.mjs.map +1 -0
  33. package/dist/flexily-zero-adapter-GHwEW11s.mjs +2 -0
  34. package/dist/gif-BaJNREpP.mjs +3 -0
  35. package/dist/gif-Bp6fIyN3.mjs +73 -0
  36. package/dist/gif-Bp6fIyN3.mjs.map +1 -0
  37. package/dist/gifenc-GiVCZ9-3.mjs +730 -0
  38. package/dist/gifenc-GiVCZ9-3.mjs.map +1 -0
  39. package/dist/image-Dx7gYjkq.mjs +346 -0
  40. package/dist/image-Dx7gYjkq.mjs.map +1 -0
  41. package/dist/index-CBcSpGSM.d.mts +3416 -0
  42. package/dist/index-CBcSpGSM.d.mts.map +1 -0
  43. package/dist/index-DCVL3jHo.d.mts +634 -0
  44. package/dist/index-DCVL3jHo.d.mts.map +1 -0
  45. package/dist/index-p-wBs_wH.d.mts +175 -0
  46. package/dist/index-p-wBs_wH.d.mts.map +1 -0
  47. package/dist/index.d.mts +7296 -0
  48. package/dist/index.d.mts.map +1 -0
  49. package/dist/index.mjs +9399 -0
  50. package/dist/index.mjs.map +1 -0
  51. package/dist/key-mapping-BsUHe_nk.mjs +3 -0
  52. package/dist/key-mapping-DsyfLEdC.mjs +132 -0
  53. package/dist/key-mapping-DsyfLEdC.mjs.map +1 -0
  54. package/dist/layout-engine-B3dsnVLU.mjs +50 -0
  55. package/dist/layout-engine-B3dsnVLU.mjs.map +1 -0
  56. package/dist/layout-engine-D_lSR4i9.mjs +2 -0
  57. package/dist/multi-progress-C0-rkn86.d.mts +180 -0
  58. package/dist/multi-progress-C0-rkn86.d.mts.map +1 -0
  59. package/dist/multi-progress-CQVB9lES.mjs +219 -0
  60. package/dist/multi-progress-CQVB9lES.mjs.map +1 -0
  61. package/dist/node-Dedx-6xF.mjs +1085 -0
  62. package/dist/node-Dedx-6xF.mjs.map +1 -0
  63. package/dist/pipeline-DDOPrjuY.mjs +4387 -0
  64. package/dist/pipeline-DDOPrjuY.mjs.map +1 -0
  65. package/dist/progress-bar-COPSBlT9.mjs +155 -0
  66. package/dist/progress-bar-COPSBlT9.mjs.map +1 -0
  67. package/dist/reconciler-2lp5VXK7.mjs +16506 -0
  68. package/dist/reconciler-2lp5VXK7.mjs.map +1 -0
  69. package/dist/render-string-BXvxTg5P.mjs +201 -0
  70. package/dist/render-string-BXvxTg5P.mjs.map +1 -0
  71. package/dist/render-string-hvfpVtoP.mjs +2 -0
  72. package/dist/resvg-js-V6oMi8CY.mjs +203 -0
  73. package/dist/resvg-js-V6oMi8CY.mjs.map +1 -0
  74. package/dist/runtime-BjDHNTxJ.mjs +8723 -0
  75. package/dist/runtime-BjDHNTxJ.mjs.map +1 -0
  76. package/dist/runtime.d.mts +2 -0
  77. package/dist/runtime.mjs +3 -0
  78. package/dist/spinner-Cgej6Vnb.d.mts +127 -0
  79. package/dist/spinner-Cgej6Vnb.d.mts.map +1 -0
  80. package/dist/spinner-DSByknyx.mjs +298 -0
  81. package/dist/spinner-DSByknyx.mjs.map +1 -0
  82. package/dist/src-9B5k0JmY.mjs +1629 -0
  83. package/dist/src-9B5k0JmY.mjs.map +1 -0
  84. package/dist/src-C9f3hiVG.mjs +3620 -0
  85. package/dist/src-C9f3hiVG.mjs.map +1 -0
  86. package/dist/src-fJVbhdn-.mjs +816 -0
  87. package/dist/src-fJVbhdn-.mjs.map +1 -0
  88. package/dist/theme.d.mts +115 -0
  89. package/dist/theme.d.mts.map +1 -0
  90. package/dist/theme.mjs +8 -0
  91. package/dist/theme.mjs.map +1 -0
  92. package/dist/types-Bhj5QkIQ.mjs +13 -0
  93. package/dist/types-Bhj5QkIQ.mjs.map +1 -0
  94. package/dist/types-CDgkE-Rw.d.mts +241 -0
  95. package/dist/types-CDgkE-Rw.d.mts.map +1 -0
  96. package/dist/ui/animation.d.mts +2 -0
  97. package/dist/ui/animation.mjs +2 -0
  98. package/dist/ui/ansi.d.mts +2 -0
  99. package/dist/ui/ansi.mjs +2 -0
  100. package/dist/ui/cli.d.mts +5 -0
  101. package/dist/ui/cli.mjs +7 -0
  102. package/dist/ui/display.d.mts +35 -0
  103. package/dist/ui/display.d.mts.map +1 -0
  104. package/dist/ui/display.mjs +123 -0
  105. package/dist/ui/display.mjs.map +1 -0
  106. package/dist/ui/image.d.mts +2 -0
  107. package/dist/ui/image.mjs +2 -0
  108. package/dist/ui/input.d.mts +184 -0
  109. package/dist/ui/input.d.mts.map +1 -0
  110. package/dist/ui/input.mjs +285 -0
  111. package/dist/ui/input.mjs.map +1 -0
  112. package/dist/ui/progress.d.mts +249 -0
  113. package/dist/ui/progress.d.mts.map +1 -0
  114. package/dist/ui/progress.mjs +858 -0
  115. package/dist/ui/progress.mjs.map +1 -0
  116. package/dist/ui/react.d.mts +280 -0
  117. package/dist/ui/react.d.mts.map +1 -0
  118. package/dist/ui/react.mjs +413 -0
  119. package/dist/ui/react.mjs.map +1 -0
  120. package/dist/ui/utils.d.mts +86 -0
  121. package/dist/ui/utils.d.mts.map +1 -0
  122. package/dist/ui/utils.mjs +2 -0
  123. package/dist/ui/wrappers.d.mts +3 -0
  124. package/dist/ui/wrappers.mjs +2 -0
  125. package/dist/ui.d.mts +6 -0
  126. package/dist/ui.mjs +7 -0
  127. package/dist/useLatest-BMIYXd6e.d.mts +154 -0
  128. package/dist/useLatest-BMIYXd6e.d.mts.map +1 -0
  129. package/dist/useLayout-BG2cGl15.mjs +139 -0
  130. package/dist/useLayout-BG2cGl15.mjs.map +1 -0
  131. package/dist/with-text-input-CmHf_9d6.d.mts +284 -0
  132. package/dist/with-text-input-CmHf_9d6.d.mts.map +1 -0
  133. package/dist/wrapper-Dqh0zi2W.mjs +3527 -0
  134. package/dist/wrapper-Dqh0zi2W.mjs.map +1 -0
  135. package/dist/wrappers-hhL8EQ_n.mjs +810 -0
  136. package/dist/wrappers-hhL8EQ_n.mjs.map +1 -0
  137. package/dist/yoga-adapter-BJ9SOhTY.mjs +245 -0
  138. package/dist/yoga-adapter-BJ9SOhTY.mjs.map +1 -0
  139. package/dist/yoga-adapter-Daq6-dw1.mjs +2 -0
  140. package/package.json +48 -75
  141. package/CHANGELOG.md +0 -319
  142. package/dist/chalk.js +0 -4
  143. package/dist/index.js +0 -270
  144. package/dist/ink.js +0 -142
  145. package/dist/runtime.js +0 -135
  146. package/dist/theme.js +0 -7
  147. package/dist/ui/animation.js +0 -3
  148. package/dist/ui/ansi.js +0 -3
  149. package/dist/ui/cli.js +0 -9
  150. package/dist/ui/display.js +0 -4
  151. package/dist/ui/image.js +0 -4
  152. package/dist/ui/input.js +0 -3
  153. package/dist/ui/progress.js +0 -9
  154. package/dist/ui/react.js +0 -4
  155. package/dist/ui/utils.js +0 -3
  156. package/dist/ui/wrappers.js +0 -15
  157. package/dist/ui.js +0 -18
  158. package/src/index.ts +0 -73
  159. package/src/runtime.ts +0 -4
  160. package/src/theme.ts +0 -4
  161. package/src/ui/animation.ts +0 -2
  162. package/src/ui/ansi.ts +0 -2
  163. package/src/ui/cli.ts +0 -3
  164. package/src/ui/display.ts +0 -2
  165. package/src/ui/image.ts +0 -2
  166. package/src/ui/input.ts +0 -2
  167. package/src/ui/progress.ts +0 -2
  168. package/src/ui/react.ts +0 -2
  169. package/src/ui/utils.ts +0 -2
  170. package/src/ui/wrappers.ts +0 -2
  171. package/src/ui.ts +0 -4
@@ -0,0 +1,154 @@
1
+ //#region packages/ag-react/src/ui/animation/easing.d.ts
2
+ /**
3
+ * Easing Functions
4
+ *
5
+ * Maps time progress (0-1) to value progress (0-1) for smooth animations.
6
+ * Includes common presets and a resolver for name-or-function usage.
7
+ */
8
+ /** Easing function: maps time progress (0-1) to value progress (0-1) */
9
+ type EasingFn = (t: number) => number;
10
+ declare const easings: {
11
+ readonly linear: (t: number) => number;
12
+ readonly ease: (t: number) => number;
13
+ readonly easeIn: (t: number) => number;
14
+ readonly easeOut: (t: number) => number;
15
+ readonly easeInOut: (t: number) => number;
16
+ readonly easeInCubic: (t: number) => number;
17
+ readonly easeOutCubic: (t: number) => number;
18
+ };
19
+ type EasingName = keyof typeof easings;
20
+ /** Resolve an easing — accepts a name string or a custom function. */
21
+ declare function resolveEasing(easing: EasingName | EasingFn): EasingFn;
22
+ //#endregion
23
+ //#region packages/ag-react/src/ui/animation/useAnimation.d.ts
24
+ interface UseAnimationOptions {
25
+ /** Duration in milliseconds */
26
+ duration: number;
27
+ /** Easing function or preset name */
28
+ easing?: EasingName | EasingFn;
29
+ /** Delay before starting (ms) */
30
+ delay?: number;
31
+ /** Called when animation completes */
32
+ onComplete?: () => void;
33
+ /** Whether to run the animation (default: true) */
34
+ enabled?: boolean;
35
+ }
36
+ interface UseAnimationResult {
37
+ /** Current progress value (0 to 1, eased) */
38
+ value: number;
39
+ /** Whether the animation is still running */
40
+ isAnimating: boolean;
41
+ /** Reset and replay the animation */
42
+ reset: () => void;
43
+ }
44
+ /**
45
+ * Animate a value from 0 to 1 over a duration with easing.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * function FadeIn({ children }) {
50
+ * const { value } = useAnimation({ duration: 300, easing: "easeOut" })
51
+ * return <Text dimColor={value < 1}>{children}</Text>
52
+ * }
53
+ * ```
54
+ */
55
+ declare function useAnimation(options: UseAnimationOptions): UseAnimationResult;
56
+ //#endregion
57
+ //#region packages/ag-react/src/ui/animation/useTransition.d.ts
58
+ interface UseTransitionOptions {
59
+ /** Duration in milliseconds (default: 300) */
60
+ duration?: number;
61
+ /** Easing function or preset name (default: "easeOut") */
62
+ easing?: EasingName | EasingFn;
63
+ }
64
+ /**
65
+ * Smoothly interpolate when the target value changes.
66
+ *
67
+ * Returns the current interpolated value. On the first render, returns
68
+ * the target value immediately (no animation). Subsequent changes
69
+ * animate from the previous value to the new target.
70
+ *
71
+ * @example
72
+ * ```tsx
73
+ * function ScrollOffset({ target }) {
74
+ * const smooth = useTransition(target, { duration: 200, easing: "easeOut" })
75
+ * return <Box marginTop={Math.round(smooth)}>...</Box>
76
+ * }
77
+ * ```
78
+ */
79
+ declare function useTransition(targetValue: number, options?: UseTransitionOptions): number;
80
+ //#endregion
81
+ //#region packages/ag-react/src/ui/animation/useInterval.d.ts
82
+ /**
83
+ * useInterval - Run a callback on a fixed interval.
84
+ *
85
+ * Uses Dan Abramov's ref pattern to avoid stale closures.
86
+ * The callback is NOT called on mount — only on subsequent ticks.
87
+ */
88
+ /**
89
+ * Run a callback on a fixed interval.
90
+ *
91
+ * The callback is NOT called on mount — only on ticks after the interval
92
+ * elapses. Uses a ref for the callback to avoid stale closures.
93
+ *
94
+ * @param callback - Function to call on each tick
95
+ * @param ms - Interval in milliseconds
96
+ * @param enabled - Whether the interval is active (default: true)
97
+ */
98
+ declare function useInterval(callback: () => void, ms: number, enabled?: boolean): void;
99
+ //#endregion
100
+ //#region packages/ag-react/src/ui/animation/useTimeout.d.ts
101
+ /**
102
+ * useTimeout - Run a callback after a delay.
103
+ *
104
+ * Uses a ref for the callback to avoid stale closures (Dan Abramov pattern).
105
+ * The timer resets when `ms` or `enabled` changes. When `enabled` becomes false,
106
+ * the timer is cleared. Returns a `reset` function to restart the timer.
107
+ *
108
+ * Unlike useInterval, this fires exactly once per enable/reset cycle.
109
+ */
110
+ /**
111
+ * Run a callback after a delay.
112
+ *
113
+ * The callback fires once after `ms` milliseconds. The timer resets when
114
+ * `ms` or `enabled` changes. Returns `{ reset, clear }` for manual control.
115
+ *
116
+ * @param callback - Function to call when the timer fires
117
+ * @param ms - Delay in milliseconds
118
+ * @param enabled - Whether the timer is active (default: true)
119
+ */
120
+ declare function useTimeout(callback: () => void, ms: number, enabled?: boolean): {
121
+ reset: () => void;
122
+ clear: () => void;
123
+ };
124
+ //#endregion
125
+ //#region packages/ag-react/src/ui/animation/useLatest.d.ts
126
+ /**
127
+ * useLatest - Always-current ref to a value.
128
+ *
129
+ * The classic React pattern for avoiding stale closures in callbacks,
130
+ * timers, and effects. Returns a ref whose `.current` is always the
131
+ * latest value — safe to read from any async context.
132
+ *
133
+ * ```tsx
134
+ * const countRef = useLatest(count)
135
+ * useInterval(() => {
136
+ * console.log(countRef.current) // always fresh
137
+ * }, 1000)
138
+ * ```
139
+ */
140
+ /**
141
+ * Returns a ref that always holds the latest value.
142
+ *
143
+ * Useful when a callback needs access to current state/props without
144
+ * re-creating the callback (which would reset timers, event listeners, etc).
145
+ *
146
+ * @param value - The value to track
147
+ * @returns A ref whose `.current` is always `value`
148
+ */
149
+ declare function useLatest<T>(value: T): {
150
+ readonly current: T;
151
+ };
152
+ //#endregion
153
+ export { useTransition as a, useAnimation as c, easings as d, resolveEasing as f, UseTransitionOptions as i, EasingFn as l, useTimeout as n, UseAnimationOptions as o, useInterval as r, UseAnimationResult as s, useLatest as t, EasingName as u };
154
+ //# sourceMappingURL=useLatest-BMIYXd6e.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLatest-BMIYXd6e.d.mts","names":[],"sources":["../packages/ag-react/src/ui/animation/easing.ts","../packages/ag-react/src/ui/animation/useAnimation.ts","../packages/ag-react/src/ui/animation/useTransition.ts","../packages/ag-react/src/ui/animation/useInterval.ts","../packages/ag-react/src/ui/animation/useTimeout.ts","../packages/ag-react/src/ui/animation/useLatest.ts"],"mappings":";;AAYA;;;;;AAMA;AAAA,KANY,QAAA,IAAY,CAAA;AAAA,cAMX,OAAA;EAAA;;;;;;;;KAUD,UAAA,gBAA0B,OAAA;;iBAOtB,aAAA,CAAc,MAAA,EAAQ,UAAA,GAAa,QAAA,GAAW,QAAA;;;UCpB7C,mBAAA;EDW4B;ECT3C,QAAA;;EAEA,MAAA,GAAS,UAAA,GAAa,QAAA;;EAEtB,KAAA;;EAEA,UAAA;;EAEA,OAAA;AAAA;AAAA,UAGe,kBAAA;;EAEf,KAAA;;EAEA,WAAA;EDPwB;ECSxB,KAAA;AAAA;;;;ADCF;;;;;;;;iBCwBgB,YAAA,CAAa,OAAA,EAAS,mBAAA,GAAsB,kBAAA;;;UC5C3C,oBAAA;EFW4B;EET3C,QAAA;;EAEA,MAAA,GAAS,UAAA,GAAa,QAAA;AAAA;;;;;;;;;;;;;AFSxB;;;iBEoBgB,aAAA,CAAc,WAAA,UAAqB,OAAA,GAAU,oBAAA;;;;AFpC7D;;;;;AAMA;;;;;;;;;;AAAA,iBGKgB,WAAA,CAAY,QAAA,cAAsB,EAAA,UAAY,OAAA;;;;AHX9D;;;;;AAMA;;;;;;;;;;;;;iBIQgB,UAAA,CAAW,QAAA,cAAsB,EAAA,UAAY,OAAA;EAAmB,KAAA;EAAmB,KAAA;AAAA;;;;AJdnG;;;;;AAMA;;;;;;;;;;;;;;;;;iBKYgB,SAAA,GAAA,CAAa,KAAA,EAAO,CAAA;EAAA,SAAe,OAAA,EAAS,CAAA;AAAA"}
@@ -0,0 +1,139 @@
1
+ import { i as NodeContext } from "./context-QreF3UHr.mjs";
2
+ import { t as rectEqual } from "./types-Bhj5QkIQ.mjs";
3
+ import { useContext, useLayoutEffect, useReducer, useRef } from "react";
4
+ //#region packages/ag-react/src/hooks/useLayout.ts
5
+ /**
6
+ * Layout Hooks — three coordinate systems for positioning in silvery.
7
+ *
8
+ * Every silvery node has three rects that differ only by how scroll and
9
+ * sticky offsets are applied. Pick the one that matches your use case:
10
+ *
11
+ * - `useBoxRect()` — layout position (border-box sized). Use for responsive
12
+ * sizing inside a component. Matches CSS offset-like
13
+ * semantics for the content area.
14
+ * - `useScrollRect()` — scroll-adjusted position, **pre** sticky clamping.
15
+ * Use when you need the "natural" position of a node
16
+ * in scrolled coordinates (can go off-screen).
17
+ * - `useScreenRect()` — actual paint position on the terminal screen.
18
+ * Use for hit testing, cursor positioning, and
19
+ * cross-component visual navigation. The CSS
20
+ * `getBoundingClientRect()` analogue.
21
+ *
22
+ * Each hook has two call signatures:
23
+ *
24
+ * const rect = useBoxRect() // reactive — re-renders on change
25
+ * useBoxRect((rect) => register(id, rect)) // callback — zero re-renders
26
+ *
27
+ * The callback form is the right choice for hot paths like large lists where
28
+ * re-rendering on every layout change is prohibitive.
29
+ */
30
+ const EMPTY_RECT = {
31
+ x: 0,
32
+ y: 0,
33
+ width: 0,
34
+ height: 0
35
+ };
36
+ /**
37
+ * Get the inner content dimensions of a node (border-box minus padding and border).
38
+ * This is the space available for the node's children.
39
+ */
40
+ function getInnerRect(node) {
41
+ const rect = node.boxRect;
42
+ if (!rect) return EMPTY_RECT;
43
+ const props = node.props;
44
+ if (!props || node.type === "silvery-text") return rect;
45
+ const pTop = props.paddingTop ?? props.paddingY ?? props.padding ?? 0;
46
+ const pBottom = props.paddingBottom ?? props.paddingY ?? props.padding ?? 0;
47
+ const pLeft = props.paddingLeft ?? props.paddingX ?? props.padding ?? 0;
48
+ const pRight = props.paddingRight ?? props.paddingX ?? props.padding ?? 0;
49
+ let bTop = 0;
50
+ let bBottom = 0;
51
+ let bLeft = 0;
52
+ let bRight = 0;
53
+ if (props.borderStyle) {
54
+ bTop = props.borderTop !== false ? 1 : 0;
55
+ bBottom = props.borderBottom !== false ? 1 : 0;
56
+ bLeft = props.borderLeft !== false ? 1 : 0;
57
+ bRight = props.borderRight !== false ? 1 : 0;
58
+ }
59
+ return {
60
+ x: rect.x + pLeft + bLeft,
61
+ y: rect.y + pTop + bTop,
62
+ width: Math.max(0, rect.width - pLeft - pRight - bLeft - bRight),
63
+ height: Math.max(0, rect.height - pTop - pBottom - bTop - bBottom)
64
+ };
65
+ }
66
+ /**
67
+ * Reactive rect hook: subscribes to the node's layoutSubscribers and forces a
68
+ * re-render whenever the selected rect changes. `getRect` pulls the current
69
+ * rect from the node for each render and change check.
70
+ */
71
+ function useReactiveRect(getRect) {
72
+ const node = useContext(NodeContext);
73
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
74
+ const prevRef = useRef(null);
75
+ useLayoutEffect(() => {
76
+ if (!node) return;
77
+ const handleLayoutComplete = () => {
78
+ const next = getRect(node) ?? null;
79
+ if (!rectEqual(prevRef.current, next)) {
80
+ prevRef.current = next;
81
+ forceUpdate();
82
+ }
83
+ };
84
+ node.layoutSubscribers.add(handleLayoutComplete);
85
+ return () => {
86
+ node.layoutSubscribers.delete(handleLayoutComplete);
87
+ };
88
+ }, [node]);
89
+ if (!node) return EMPTY_RECT;
90
+ return getRect(node) ?? EMPTY_RECT;
91
+ }
92
+ /**
93
+ * Callback rect hook: subscribes without triggering re-renders. The callback
94
+ * is invoked after layout completes whenever the selected rect is available.
95
+ * Uses a ref so the hook doesn't re-subscribe when the caller passes a fresh
96
+ * function each render.
97
+ *
98
+ * `getRectRef` is wrapped in a ref to keep the subscription stable across
99
+ * renders — the `getRect` function is typically created inline as
100
+ * `(node) => node.scrollRect` and would otherwise invalidate the effect on
101
+ * every render, missing layout notifications in tests that re-render the
102
+ * same tree with a fresh registry.
103
+ */
104
+ function useCallbackRect(getRect, callback) {
105
+ const node = useContext(NodeContext);
106
+ const callbackRef = useRef(callback);
107
+ callbackRef.current = callback;
108
+ const getRectRef = useRef(getRect);
109
+ getRectRef.current = getRect;
110
+ useLayoutEffect(() => {
111
+ if (!node) return;
112
+ const handleLayoutComplete = () => {
113
+ const rect = getRectRef.current(node);
114
+ if (rect) callbackRef.current(rect);
115
+ };
116
+ node.layoutSubscribers.add(handleLayoutComplete);
117
+ const rect = getRectRef.current(node);
118
+ if (rect) callbackRef.current(rect);
119
+ return () => {
120
+ node.layoutSubscribers.delete(handleLayoutComplete);
121
+ };
122
+ }, [node]);
123
+ }
124
+ function useBoxRect(callback) {
125
+ if (callback) return useCallbackRect((node) => getInnerRect(node), callback);
126
+ return useReactiveRect((node) => getInnerRect(node));
127
+ }
128
+ function useScrollRect(callback) {
129
+ if (callback) return useCallbackRect((node) => node.scrollRect, callback);
130
+ return useReactiveRect((node) => node.scrollRect);
131
+ }
132
+ function useScreenRect(callback) {
133
+ if (callback) return useCallbackRect((node) => node.screenRect, callback);
134
+ return useReactiveRect((node) => node.screenRect);
135
+ }
136
+ //#endregion
137
+ export { useScreenRect as n, useScrollRect as r, useBoxRect as t };
138
+
139
+ //# sourceMappingURL=useLayout-BG2cGl15.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLayout-BG2cGl15.mjs","names":[],"sources":["../packages/ag-react/src/hooks/useLayout.ts"],"sourcesContent":["/**\n * Layout Hooks — three coordinate systems for positioning in silvery.\n *\n * Every silvery node has three rects that differ only by how scroll and\n * sticky offsets are applied. Pick the one that matches your use case:\n *\n * - `useBoxRect()` — layout position (border-box sized). Use for responsive\n * sizing inside a component. Matches CSS offset-like\n * semantics for the content area.\n * - `useScrollRect()` — scroll-adjusted position, **pre** sticky clamping.\n * Use when you need the \"natural\" position of a node\n * in scrolled coordinates (can go off-screen).\n * - `useScreenRect()` — actual paint position on the terminal screen.\n * Use for hit testing, cursor positioning, and\n * cross-component visual navigation. The CSS\n * `getBoundingClientRect()` analogue.\n *\n * Each hook has two call signatures:\n *\n * const rect = useBoxRect() // reactive — re-renders on change\n * useBoxRect((rect) => register(id, rect)) // callback — zero re-renders\n *\n * The callback form is the right choice for hot paths like large lists where\n * re-rendering on every layout change is prohibitive.\n */\n\nimport { useContext, useLayoutEffect, useReducer, useRef } from \"react\"\nimport { NodeContext } from \"../context\"\nimport { type AgNode, type BoxProps, type Rect, rectEqual } from \"@silvery/ag/types\"\n\nexport type { Rect }\n\nconst EMPTY_RECT: Rect = { x: 0, y: 0, width: 0, height: 0 }\n\n/**\n * Get the inner content dimensions of a node (border-box minus padding and border).\n * This is the space available for the node's children.\n */\nfunction getInnerRect(node: AgNode): Rect {\n const rect = node.boxRect\n if (!rect) return EMPTY_RECT\n\n const props = node.props as BoxProps\n if (!props || node.type === \"silvery-text\") return rect\n\n // Compute padding\n const pTop = props.paddingTop ?? props.paddingY ?? props.padding ?? 0\n const pBottom = props.paddingBottom ?? props.paddingY ?? props.padding ?? 0\n const pLeft = props.paddingLeft ?? props.paddingX ?? props.padding ?? 0\n const pRight = props.paddingRight ?? props.paddingX ?? props.padding ?? 0\n\n // Compute border (1px per side if borderStyle is set)\n let bTop = 0\n let bBottom = 0\n let bLeft = 0\n let bRight = 0\n if (props.borderStyle) {\n bTop = props.borderTop !== false ? 1 : 0\n bBottom = props.borderBottom !== false ? 1 : 0\n bLeft = props.borderLeft !== false ? 1 : 0\n bRight = props.borderRight !== false ? 1 : 0\n }\n\n return {\n x: rect.x + pLeft + bLeft,\n y: rect.y + pTop + bTop,\n width: Math.max(0, rect.width - pLeft - pRight - bLeft - bRight),\n height: Math.max(0, rect.height - pTop - pBottom - bTop - bBottom),\n }\n}\n\ntype RectCallback = (rect: Rect) => void\n\n/**\n * Reactive rect hook: subscribes to the node's layoutSubscribers and forces a\n * re-render whenever the selected rect changes. `getRect` pulls the current\n * rect from the node for each render and change check.\n */\nfunction useReactiveRect(getRect: (node: AgNode) => Rect | null | undefined): Rect {\n const node = useContext(NodeContext)\n const [, forceUpdate] = useReducer((x: number) => x + 1, 0)\n const prevRef = useRef<Rect | null>(null)\n\n useLayoutEffect(() => {\n if (!node) return\n\n const handleLayoutComplete = () => {\n const next = getRect(node) ?? null\n if (!rectEqual(prevRef.current, next)) {\n prevRef.current = next\n forceUpdate()\n }\n }\n\n node.layoutSubscribers.add(handleLayoutComplete)\n return () => {\n node.layoutSubscribers.delete(handleLayoutComplete)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [node])\n\n if (!node) return EMPTY_RECT\n return getRect(node) ?? EMPTY_RECT\n}\n\n/**\n * Callback rect hook: subscribes without triggering re-renders. The callback\n * is invoked after layout completes whenever the selected rect is available.\n * Uses a ref so the hook doesn't re-subscribe when the caller passes a fresh\n * function each render.\n *\n * `getRectRef` is wrapped in a ref to keep the subscription stable across\n * renders — the `getRect` function is typically created inline as\n * `(node) => node.scrollRect` and would otherwise invalidate the effect on\n * every render, missing layout notifications in tests that re-render the\n * same tree with a fresh registry.\n */\nfunction useCallbackRect(getRect: (node: AgNode) => Rect | null | undefined, callback: RectCallback): void {\n const node = useContext(NodeContext)\n\n const callbackRef = useRef(callback)\n callbackRef.current = callback\n const getRectRef = useRef(getRect)\n getRectRef.current = getRect\n\n useLayoutEffect(() => {\n if (!node) return\n\n const handleLayoutComplete = () => {\n const rect = getRectRef.current(node)\n if (rect) callbackRef.current(rect)\n }\n\n node.layoutSubscribers.add(handleLayoutComplete)\n\n // Call immediately if the rect is already computed\n const rect = getRectRef.current(node)\n if (rect) callbackRef.current(rect)\n\n return () => {\n node.layoutSubscribers.delete(handleLayoutComplete)\n }\n }, [node])\n}\n\n// ============================================================================\n// boxRect — layout position (border-box)\n// ============================================================================\n\n/**\n * Returns the inner content dimensions for the current component's nearest Box.\n * Width and height reflect the space available for children (border-box minus\n * padding and border), like CSS `clientWidth`/`clientHeight`.\n *\n * Two signatures:\n *\n * ```tsx\n * // Reactive — re-renders when the rect changes\n * function Header() {\n * const { width } = useBoxRect()\n * return <Text>{'='.repeat(width)}</Text>\n * }\n *\n * // Callback — zero re-renders, use for hot paths like large lists\n * function Card({ id, onLayout }) {\n * useBoxRect((rect) => onLayout(id, rect))\n * return <Box>...</Box>\n * }\n * ```\n *\n * On first render (reactive form), returns `{ x: 0, y: 0, width: 0, height: 0 }`.\n * After layout completes, automatically re-renders with actual dimensions.\n */\nexport function useBoxRect(): Rect\nexport function useBoxRect(callback: RectCallback): void\nexport function useBoxRect(callback?: RectCallback): Rect | void {\n if (callback) {\n return useCallbackRect((node) => getInnerRect(node), callback)\n }\n return useReactiveRect((node) => getInnerRect(node))\n}\n\n// ============================================================================\n// scrollRect — scroll-adjusted position (pre-sticky clamping)\n// ============================================================================\n\n/**\n * Returns the scroll-adjusted position for the current component.\n *\n * This is the node's position in scroll coordinates, *before* sticky clamping.\n * For non-sticky nodes it equals `useScreenRect()`. For sticky nodes, the\n * scrollRect reflects where the node would be without sticky adjustment —\n * so it can go off-screen (negative y, etc.) when scrolled past.\n *\n * Use this when you need to reason about the node's \"natural\" position in the\n * scrolled document. For hit testing or cursor positioning, use\n * `useScreenRect()` instead.\n *\n * Two signatures:\n *\n * ```tsx\n * // Reactive — re-renders when scroll changes\n * function Card({ id }) {\n * const { y } = useScrollRect()\n * return <Box>Scroll y: {y}</Box>\n * }\n *\n * // Callback — zero re-renders\n * function Card({ id, onLayout }) {\n * useScrollRect((rect) => onLayout(id, rect.y))\n * return <Box>...</Box>\n * }\n * ```\n */\nexport function useScrollRect(): Rect\nexport function useScrollRect(callback: RectCallback): void\nexport function useScrollRect(callback?: RectCallback): Rect | void {\n if (callback) {\n return useCallbackRect((node) => node.scrollRect, callback)\n }\n return useReactiveRect((node) => node.scrollRect)\n}\n\n// ============================================================================\n// screenRect — actual paint position on the terminal screen\n// ============================================================================\n\n/**\n * Returns the actual paint position on the terminal screen — the silvery\n * analogue of `getBoundingClientRect()`.\n *\n * For non-sticky nodes this equals `useScrollRect()`. For sticky nodes\n * (`position=\"sticky\"`), it reflects the clamped position where pixels\n * actually land on screen.\n *\n * Use this for hit testing, cursor positioning, and any feature that needs\n * to know where a node visually appears on the terminal.\n *\n * Two signatures:\n *\n * ```tsx\n * // Reactive — re-renders when the screen position changes\n * function StickyHeader() {\n * const { y } = useScreenRect()\n * return <Box position=\"sticky\" stickyTop={0}>Header at row {y}</Box>\n * }\n *\n * // Callback — zero re-renders, recommended for cross-component visual\n * // navigation (e.g. registering card positions for arrow-key navigation\n * // across columns with independent scroll state).\n * function Card({ id, onLayout }) {\n * useScreenRect((rect) => onLayout(id, rect.y))\n * return <Box>...</Box>\n * }\n * ```\n */\nexport function useScreenRect(): Rect\nexport function useScreenRect(callback: RectCallback): void\nexport function useScreenRect(callback?: RectCallback): Rect | void {\n if (callback) {\n return useCallbackRect((node) => node.screenRect, callback)\n }\n return useReactiveRect((node) => node.screenRect)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAM,aAAmB;CAAE,GAAG;CAAG,GAAG;CAAG,OAAO;CAAG,QAAQ;CAAG;;;;;AAM5D,SAAS,aAAa,MAAoB;CACxC,MAAM,OAAO,KAAK;AAClB,KAAI,CAAC,KAAM,QAAO;CAElB,MAAM,QAAQ,KAAK;AACnB,KAAI,CAAC,SAAS,KAAK,SAAS,eAAgB,QAAO;CAGnD,MAAM,OAAO,MAAM,cAAc,MAAM,YAAY,MAAM,WAAW;CACpE,MAAM,UAAU,MAAM,iBAAiB,MAAM,YAAY,MAAM,WAAW;CAC1E,MAAM,QAAQ,MAAM,eAAe,MAAM,YAAY,MAAM,WAAW;CACtE,MAAM,SAAS,MAAM,gBAAgB,MAAM,YAAY,MAAM,WAAW;CAGxE,IAAI,OAAO;CACX,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,IAAI,SAAS;AACb,KAAI,MAAM,aAAa;AACrB,SAAO,MAAM,cAAc,QAAQ,IAAI;AACvC,YAAU,MAAM,iBAAiB,QAAQ,IAAI;AAC7C,UAAQ,MAAM,eAAe,QAAQ,IAAI;AACzC,WAAS,MAAM,gBAAgB,QAAQ,IAAI;;AAG7C,QAAO;EACL,GAAG,KAAK,IAAI,QAAQ;EACpB,GAAG,KAAK,IAAI,OAAO;EACnB,OAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,SAAS,QAAQ,OAAO;EAChE,QAAQ,KAAK,IAAI,GAAG,KAAK,SAAS,OAAO,UAAU,OAAO,QAAQ;EACnE;;;;;;;AAUH,SAAS,gBAAgB,SAA0D;CACjF,MAAM,OAAO,WAAW,YAAY;CACpC,MAAM,GAAG,eAAe,YAAY,MAAc,IAAI,GAAG,EAAE;CAC3D,MAAM,UAAU,OAAoB,KAAK;AAEzC,uBAAsB;AACpB,MAAI,CAAC,KAAM;EAEX,MAAM,6BAA6B;GACjC,MAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,OAAI,CAAC,UAAU,QAAQ,SAAS,KAAK,EAAE;AACrC,YAAQ,UAAU;AAClB,iBAAa;;;AAIjB,OAAK,kBAAkB,IAAI,qBAAqB;AAChD,eAAa;AACX,QAAK,kBAAkB,OAAO,qBAAqB;;IAGpD,CAAC,KAAK,CAAC;AAEV,KAAI,CAAC,KAAM,QAAO;AAClB,QAAO,QAAQ,KAAK,IAAI;;;;;;;;;;;;;;AAe1B,SAAS,gBAAgB,SAAoD,UAA8B;CACzG,MAAM,OAAO,WAAW,YAAY;CAEpC,MAAM,cAAc,OAAO,SAAS;AACpC,aAAY,UAAU;CACtB,MAAM,aAAa,OAAO,QAAQ;AAClC,YAAW,UAAU;AAErB,uBAAsB;AACpB,MAAI,CAAC,KAAM;EAEX,MAAM,6BAA6B;GACjC,MAAM,OAAO,WAAW,QAAQ,KAAK;AACrC,OAAI,KAAM,aAAY,QAAQ,KAAK;;AAGrC,OAAK,kBAAkB,IAAI,qBAAqB;EAGhD,MAAM,OAAO,WAAW,QAAQ,KAAK;AACrC,MAAI,KAAM,aAAY,QAAQ,KAAK;AAEnC,eAAa;AACX,QAAK,kBAAkB,OAAO,qBAAqB;;IAEpD,CAAC,KAAK,CAAC;;AAiCZ,SAAgB,WAAW,UAAsC;AAC/D,KAAI,SACF,QAAO,iBAAiB,SAAS,aAAa,KAAK,EAAE,SAAS;AAEhE,QAAO,iBAAiB,SAAS,aAAa,KAAK,CAAC;;AAqCtD,SAAgB,cAAc,UAAsC;AAClE,KAAI,SACF,QAAO,iBAAiB,SAAS,KAAK,YAAY,SAAS;AAE7D,QAAO,iBAAiB,SAAS,KAAK,WAAW;;AAsCnD,SAAgB,cAAc,UAAsC;AAClE,KAAI,SACF,QAAO,iBAAiB,SAAS,KAAK,YAAY,SAAS;AAE7D,QAAO,iBAAiB,SAAS,KAAK,WAAW"}
@@ -0,0 +1,284 @@
1
+ import { _ as TextInputOptions, b as WithSelectOptions, i as ProgressGenerator, o as SelectOption, r as ProgressCallback, x as WithSpinnerOptions, y as WithProgressOptions } from "./types-CDgkE-Rw.mjs";
2
+ import { r as Spinner } from "./spinner-Cgej6Vnb.mjs";
3
+ import { EventEmitter } from "events";
4
+
5
+ //#region packages/ag-react/src/ui/wrappers/with-spinner.d.ts
6
+ /**
7
+ * Wrap a promise with an animated spinner
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // Simple usage
12
+ * const data = await withSpinner(fetchData(), "Loading data...");
13
+ *
14
+ * // With options
15
+ * const result = await withSpinner(
16
+ * processFiles(),
17
+ * "Processing...",
18
+ * { style: "arc", clearOnComplete: true }
19
+ * );
20
+ *
21
+ * // With dynamic text
22
+ * const result = await withSpinner(
23
+ * longOperation(),
24
+ * (elapsed) => `Processing... (${elapsed}s)`
25
+ * );
26
+ * ```
27
+ */
28
+ declare function withSpinner<T>(promise: Promise<T> | (() => T | Promise<T>), text: string | ((elapsedSeconds: number) => string), options?: WithSpinnerOptions): Promise<T>;
29
+ /**
30
+ * Attach a spinner to a promise for manual control
31
+ * Returns [result, spinner] tuple for custom control
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const [promise, spinner] = attachSpinner(fetchData(), "Loading...");
36
+ * spinner.text = "Still loading...";
37
+ * const result = await promise;
38
+ * spinner.succeed("Loaded!");
39
+ * ```
40
+ */
41
+ declare function attachSpinner<T>(promise: Promise<T>, text: string, options?: WithSpinnerOptions): [Promise<T>, Spinner];
42
+ //#endregion
43
+ //#region packages/ag-react/src/ui/wrappers/with-progress.d.ts
44
+ /**
45
+ * Wrap a function that takes a progress callback
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * // Wrap existing km sync API
50
+ * const result = await withProgress(
51
+ * (onProgress) => manager.syncFromFs(onProgress),
52
+ * {
53
+ * phases: {
54
+ * scanning: "Scanning files",
55
+ * reconciling: "Reconciling changes",
56
+ * rules: "Evaluating rules"
57
+ * }
58
+ * }
59
+ * );
60
+ *
61
+ * // Simple usage without phases
62
+ * await withProgress((onProgress) => rebuildState(onProgress));
63
+ *
64
+ * // With custom format
65
+ * await withProgress(
66
+ * (p) => processFiles(p),
67
+ * { format: ":phase :bar :percent" }
68
+ * );
69
+ *
70
+ * // Show loading immediately (showAfter: 0) or after delay
71
+ * await withProgress(
72
+ * (p) => slowOperation(p),
73
+ * { showAfter: 1000, initialMessage: "Loading..." }
74
+ * );
75
+ * ```
76
+ */
77
+ declare function withProgress<T>(fn: (onProgress: ProgressCallback) => T | Promise<T>, options?: WithProgressOptions): Promise<T>;
78
+ /**
79
+ * Create a progress callback that can be passed to existing APIs
80
+ * Returns [callback, complete] tuple
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const [onProgress, complete] = createProgressCallback({
85
+ * phases: { scanning: "Scanning", reconciling: "Reconciling" }
86
+ * });
87
+ *
88
+ * const result = await manager.syncFromFs(onProgress);
89
+ * complete();
90
+ * ```
91
+ */
92
+ declare function createProgressCallback(options?: WithProgressOptions): [ProgressCallback, () => void];
93
+ //#endregion
94
+ //#region packages/ag-react/src/ui/wrappers/wrap-generator.d.ts
95
+ /**
96
+ * Consume a progress generator while displaying progress
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * // Wrap existing generator (like evaluateAllRules())
101
+ * await wrapGenerator(evaluateAllRules(), "Evaluating rules");
102
+ *
103
+ * // With custom format
104
+ * await wrapGenerator(
105
+ * processItems(),
106
+ * ({ current, total }) => `Processing: ${current}/${total}`
107
+ * );
108
+ *
109
+ * // Get the generator's return value
110
+ * const result = await wrapGenerator(generatorWithReturn(), "Processing");
111
+ * ```
112
+ */
113
+ declare function wrapGenerator<T>(generator: ProgressGenerator<T>, textOrFormat: string | ((progress: {
114
+ current: number;
115
+ total: number;
116
+ }) => string), options?: {
117
+ clearOnComplete?: boolean;
118
+ }): Promise<T>;
119
+ /**
120
+ * Create an async iterable wrapper that shows progress
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * const items = [1, 2, 3, 4, 5];
125
+ * for await (const item of withIterableProgress(items, "Processing")) {
126
+ * await processItem(item);
127
+ * }
128
+ * ```
129
+ */
130
+ declare function withIterableProgress<T>(iterable: Iterable<T> | AsyncIterable<T>, label: string, options?: {
131
+ clearOnComplete?: boolean;
132
+ }): AsyncGenerator<T, void, unknown>;
133
+ //#endregion
134
+ //#region packages/ag-react/src/ui/wrappers/wrap-emitter.d.ts
135
+ /** Event handler configuration */
136
+ interface EventConfig {
137
+ /** Display text for this event */
138
+ text?: string;
139
+ /** Dynamic text based on event data */
140
+ getText?: (data: unknown) => string;
141
+ /** Mark spinner as succeeded */
142
+ succeed?: boolean;
143
+ /** Mark spinner as failed */
144
+ fail?: boolean;
145
+ /** Stop tracking */
146
+ stop?: boolean;
147
+ }
148
+ /** Configuration for wrapEmitter */
149
+ interface WrapEmitterConfig {
150
+ /** Event handlers */
151
+ events: Record<string, EventConfig>;
152
+ /** Initial text */
153
+ initialText?: string;
154
+ }
155
+ /**
156
+ * Track EventEmitter state changes with a spinner
157
+ *
158
+ * @example
159
+ * ```ts
160
+ * const stop = wrapEmitter(syncManager, {
161
+ * initialText: "Starting sync...",
162
+ * events: {
163
+ * 'ready': { text: "Watcher ready", succeed: true },
164
+ * 'state-change': { getText: (s) => `State: ${s}` },
165
+ * 'error': { fail: true },
166
+ * 'idle': { stop: true }
167
+ * }
168
+ * });
169
+ *
170
+ * // Later, to stop manually
171
+ * stop();
172
+ * ```
173
+ */
174
+ declare function wrapEmitter(emitter: EventEmitter, config: WrapEmitterConfig): () => void;
175
+ /**
176
+ * Wait for an EventEmitter to emit a specific event
177
+ * Shows a spinner while waiting
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * await waitForEvent(syncManager, "ready", "Waiting for watcher...");
182
+ * ```
183
+ */
184
+ declare function waitForEvent(emitter: EventEmitter, eventName: string, text: string, options?: {
185
+ errorEvent?: string;
186
+ timeout?: number;
187
+ }): Promise<unknown>;
188
+ //#endregion
189
+ //#region packages/ag-react/src/ui/wrappers/with-select.d.ts
190
+ /**
191
+ * Display an interactive selection list in the terminal
192
+ *
193
+ * @example
194
+ * ```ts
195
+ * // Simple usage
196
+ * const color = await withSelect("Choose a color:", [
197
+ * { label: "Red", value: "red" },
198
+ * { label: "Green", value: "green" },
199
+ * { label: "Blue", value: "blue" },
200
+ * ]);
201
+ *
202
+ * // With options
203
+ * const result = await withSelect(
204
+ * "Select item:",
205
+ * options,
206
+ * { initial: 2, maxVisible: 5 }
207
+ * );
208
+ * ```
209
+ */
210
+ declare function withSelect<T>(prompt: string, options: SelectOption<T>[], selectOptions?: WithSelectOptions): Promise<T>;
211
+ /**
212
+ * Create a reusable select instance for multiple selections
213
+ *
214
+ * @example
215
+ * ```ts
216
+ * const select = createSelect({
217
+ * maxVisible: 5,
218
+ * });
219
+ *
220
+ * const first = await select("Choose first:", options1);
221
+ * const second = await select("Choose second:", options2);
222
+ * ```
223
+ */
224
+ declare function createSelect(defaultOptions?: WithSelectOptions): <T>(prompt: string, options: SelectOption<T>[], overrides?: WithSelectOptions) => Promise<T>;
225
+ //#endregion
226
+ //#region packages/ag-react/src/ui/wrappers/with-text-input.d.ts
227
+ /**
228
+ * Prompt for text input in the terminal
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * // Simple usage
233
+ * const name = await withTextInput("What is your name?");
234
+ *
235
+ * // With options
236
+ * const password = await withTextInput("Password:", { mask: "*" });
237
+ *
238
+ * // With validation
239
+ * const email = await withTextInput("Email:", {
240
+ * validate: (v) => v.includes("@") ? undefined : "Invalid email"
241
+ * });
242
+ *
243
+ * // With autocomplete
244
+ * const fruit = await withTextInput("Pick a fruit:", {
245
+ * autocomplete: ["apple", "banana", "cherry"]
246
+ * });
247
+ * ```
248
+ */
249
+ declare function withTextInput(prompt: string, options?: TextInputOptions): Promise<string>;
250
+ /**
251
+ * Create a text input instance for manual control
252
+ *
253
+ * @example
254
+ * ```ts
255
+ * const input = createTextInput("Name:", { placeholder: "Enter name" });
256
+ * input.render();
257
+ *
258
+ * // Later, get the value
259
+ * const value = await input.waitForSubmit();
260
+ * ```
261
+ */
262
+ declare function createTextInput(prompt: string, options?: TextInputOptions): TextInputInstance;
263
+ /** Instance returned by createTextInput for manual control */
264
+ interface TextInputInstance {
265
+ /** Current input value */
266
+ value: string;
267
+ /** Current cursor position */
268
+ cursorPosition: number;
269
+ /** Render the current state */
270
+ render(): void;
271
+ /** Insert text at cursor */
272
+ insert(char: string): void;
273
+ /** Delete character before cursor */
274
+ backspace(): void;
275
+ /** Delete character at cursor */
276
+ delete(): void;
277
+ /** Clear all input */
278
+ clear(): void;
279
+ /** Accept autocomplete suggestion */
280
+ acceptSuggestion(): void;
281
+ }
282
+ //#endregion
283
+ export { waitForEvent as a, wrapGenerator as c, attachSpinner as d, withSpinner as f, withSelect as i, createProgressCallback as l, withTextInput as n, wrapEmitter as o, createSelect as r, withIterableProgress as s, createTextInput as t, withProgress as u };
284
+ //# sourceMappingURL=with-text-input-CmHf_9d6.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-text-input-CmHf_9d6.d.mts","names":[],"sources":["../packages/ag-react/src/ui/wrappers/with-spinner.ts","../packages/ag-react/src/ui/wrappers/with-progress.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"],"mappings":";;;;;AA6BA;;;;;;;;;;;;;;;;;;;;;;AAAA,iBAAsB,WAAA,GAAA,CACpB,OAAA,EAAS,OAAA,CAAQ,CAAA,WAAY,CAAA,GAAI,OAAA,CAAQ,CAAA,IACzC,IAAA,aAAiB,cAAA,sBACjB,OAAA,GAAS,kBAAA,GACR,OAAA,CAAQ,CAAA;;;;;;AAmDX;;;;;;;iBAAgB,aAAA,GAAA,CACd,OAAA,EAAS,OAAA,CAAQ,CAAA,GACjB,IAAA,UACA,OAAA,GAAS,kBAAA,IACP,OAAA,CAAQ,CAAA,GAAI,OAAA;;;;;;;;;;;;;;;;AAJhB;;;;;;;;;;;;;;;;;;;;iBCnBsB,YAAA,GAAA,CACpB,EAAA,GAAK,UAAA,EAAY,gBAAA,KAAqB,CAAA,GAAI,OAAA,CAAQ,CAAA,GAClD,OAAA,GAAS,mBAAA,GACR,OAAA,CAAQ,CAAA;;;;;;AAHX;;;;;;;;;iBAqIgB,sBAAA,CAAuB,OAAA,GAAS,mBAAA,IAA4B,gBAAA;;;;ADzK5E;;;;;;;;;;;;;;;;;iBEHsB,aAAA,GAAA,CACpB,SAAA,EAAW,iBAAA,CAAkB,CAAA,GAC7B,YAAA,aAAyB,QAAA;EAAY,OAAA;EAAiB,KAAA;AAAA,eACtD,OAAA;EAAW,eAAA;AAAA,IACV,OAAA,CAAQ,CAAA;;;;;;AFsDX;;;;;;iBEeuB,oBAAA,GAAA,CACrB,QAAA,EAAU,QAAA,CAAS,CAAA,IAAK,aAAA,CAAc,CAAA,GACtC,KAAA,UACA,OAAA;EAAW,eAAA;AAAA,IACV,cAAA,CAAe,CAAA;;;;UC/FR,WAAA;EHqBuB;EGnB/B,IAAA;EHoBiB;EGlBjB,OAAA,IAAW,IAAA;EHkBkB;EGhB7B,OAAA;EHgBiC;EGdjC,IAAA;EHiBS;EGfT,IAAA;AAAA;;UAIQ,iBAAA;EHQC;EGNT,MAAA,EAAQ,MAAA,SAAe,WAAA;EHMM;EGJ7B,WAAA;AAAA;;;;;;;;;;AH0DF;;;;;;;;;;iBGpCgB,WAAA,CAAY,OAAA,EAAS,YAAA,EAAc,MAAA,EAAQ,iBAAA;;;;;;;;;;iBA0DrC,YAAA,CACpB,OAAA,EAAS,YAAA,EACT,SAAA,UACA,IAAA,UACA,OAAA;EACE,UAAA;EACA,OAAA;AAAA,IAED,OAAA;;;;AHrFH;;;;;;;;;;;;;;;;;;;iBIDsB,UAAA,GAAA,CACpB,MAAA,UACA,OAAA,EAAS,YAAA,CAAa,CAAA,KACtB,aAAA,GAAe,iBAAA,GACd,OAAA,CAAQ,CAAA;;;;;;;;;AJoDX;;;;;iBIwGgB,YAAA,CACd,cAAA,GAAgB,iBAAA,OACX,MAAA,UAAgB,OAAA,EAAS,YAAA,CAAa,CAAA,KAAM,SAAA,GAAY,iBAAA,KAAsB,OAAA,CAAQ,CAAA;;;;AJjK7F;;;;;;;;;;;;;;;;;;;;;iBKCsB,aAAA,CAAc,MAAA,UAAgB,OAAA,GAAS,gBAAA,GAAwB,OAAA;;;;;;;ALsDrF;;;;;;iBKwMgB,eAAA,CAAgB,MAAA,UAAgB,OAAA,GAAS,gBAAA,GAAwB,iBAAA;;UA0EhE,iBAAA;EL9QM;EKgRrB,KAAA;ELpR4B;EKsR5B,cAAA;ELrRiB;EKuRjB,MAAA;ELtRA;EKwRA,MAAA,CAAO,IAAA;ELvRP;EKyRA,SAAA;ELxRU;EK0RV,MAAA;EL1RqB;EK4RrB,KAAA;;EAEA,gBAAA;AAAA"}