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.
- package/dist/UPNG-AVSMjiFE.mjs +5076 -0
- package/dist/UPNG-AVSMjiFE.mjs.map +1 -0
- package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs +6 -0
- package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs.map +1 -0
- package/dist/animation-C_PTO0uH.mjs +304 -0
- package/dist/animation-C_PTO0uH.mjs.map +1 -0
- package/dist/ansi-CXLE_pt1.mjs +71 -0
- package/dist/ansi-CXLE_pt1.mjs.map +1 -0
- package/dist/ansi-zmNzgkPB.d.mts +49 -0
- package/dist/ansi-zmNzgkPB.d.mts.map +1 -0
- package/dist/apng-DCWY913R.mjs +3 -0
- package/dist/apng-ENBAJk-H.mjs +70 -0
- package/dist/apng-ENBAJk-H.mjs.map +1 -0
- package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
- package/dist/backend-CkIkIHR-.mjs +13396 -0
- package/dist/backend-CkIkIHR-.mjs.map +1 -0
- package/dist/backends-CkvbG3js.mjs +1181 -0
- package/dist/backends-CkvbG3js.mjs.map +1 -0
- package/dist/backends-CyJqNLeK.mjs +3 -0
- package/dist/chunk-BSw8zbkd.mjs +37 -0
- package/dist/cli-B-k7Bm56.mjs +4 -0
- package/dist/context-QreF3UHr.mjs +64 -0
- package/dist/context-QreF3UHr.mjs.map +1 -0
- package/dist/derive-D7bFJdfU.d.mts +28 -0
- package/dist/derive-D7bFJdfU.d.mts.map +1 -0
- package/dist/devtools-CscuKaDK.mjs +89 -0
- package/dist/devtools-CscuKaDK.mjs.map +1 -0
- package/dist/devtools-D4oGc6LY.mjs +2 -0
- package/dist/eta-DLiVPaSD.mjs +110 -0
- package/dist/eta-DLiVPaSD.mjs.map +1 -0
- package/dist/flexily-zero-adapter-DmG4Ge8t.mjs +3376 -0
- package/dist/flexily-zero-adapter-DmG4Ge8t.mjs.map +1 -0
- package/dist/flexily-zero-adapter-GHwEW11s.mjs +2 -0
- package/dist/gif-BaJNREpP.mjs +3 -0
- package/dist/gif-Bp6fIyN3.mjs +73 -0
- package/dist/gif-Bp6fIyN3.mjs.map +1 -0
- package/dist/gifenc-GiVCZ9-3.mjs +730 -0
- package/dist/gifenc-GiVCZ9-3.mjs.map +1 -0
- package/dist/image-Dx7gYjkq.mjs +346 -0
- package/dist/image-Dx7gYjkq.mjs.map +1 -0
- package/dist/index-CBcSpGSM.d.mts +3416 -0
- package/dist/index-CBcSpGSM.d.mts.map +1 -0
- package/dist/index-DCVL3jHo.d.mts +634 -0
- package/dist/index-DCVL3jHo.d.mts.map +1 -0
- package/dist/index-p-wBs_wH.d.mts +175 -0
- package/dist/index-p-wBs_wH.d.mts.map +1 -0
- package/dist/index.d.mts +7296 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +9399 -0
- package/dist/index.mjs.map +1 -0
- package/dist/key-mapping-BsUHe_nk.mjs +3 -0
- package/dist/key-mapping-DsyfLEdC.mjs +132 -0
- package/dist/key-mapping-DsyfLEdC.mjs.map +1 -0
- package/dist/layout-engine-B3dsnVLU.mjs +50 -0
- package/dist/layout-engine-B3dsnVLU.mjs.map +1 -0
- package/dist/layout-engine-D_lSR4i9.mjs +2 -0
- package/dist/multi-progress-C0-rkn86.d.mts +180 -0
- package/dist/multi-progress-C0-rkn86.d.mts.map +1 -0
- package/dist/multi-progress-CQVB9lES.mjs +219 -0
- package/dist/multi-progress-CQVB9lES.mjs.map +1 -0
- package/dist/node-Dedx-6xF.mjs +1085 -0
- package/dist/node-Dedx-6xF.mjs.map +1 -0
- package/dist/pipeline-DDOPrjuY.mjs +4387 -0
- package/dist/pipeline-DDOPrjuY.mjs.map +1 -0
- package/dist/progress-bar-COPSBlT9.mjs +155 -0
- package/dist/progress-bar-COPSBlT9.mjs.map +1 -0
- package/dist/reconciler-2lp5VXK7.mjs +16506 -0
- package/dist/reconciler-2lp5VXK7.mjs.map +1 -0
- package/dist/render-string-BXvxTg5P.mjs +201 -0
- package/dist/render-string-BXvxTg5P.mjs.map +1 -0
- package/dist/render-string-hvfpVtoP.mjs +2 -0
- package/dist/resvg-js-V6oMi8CY.mjs +203 -0
- package/dist/resvg-js-V6oMi8CY.mjs.map +1 -0
- package/dist/runtime-BjDHNTxJ.mjs +8723 -0
- package/dist/runtime-BjDHNTxJ.mjs.map +1 -0
- package/dist/runtime.d.mts +2 -0
- package/dist/runtime.mjs +3 -0
- package/dist/spinner-Cgej6Vnb.d.mts +127 -0
- package/dist/spinner-Cgej6Vnb.d.mts.map +1 -0
- package/dist/spinner-DSByknyx.mjs +298 -0
- package/dist/spinner-DSByknyx.mjs.map +1 -0
- package/dist/src-9B5k0JmY.mjs +1629 -0
- package/dist/src-9B5k0JmY.mjs.map +1 -0
- package/dist/src-C9f3hiVG.mjs +3620 -0
- package/dist/src-C9f3hiVG.mjs.map +1 -0
- package/dist/src-fJVbhdn-.mjs +816 -0
- package/dist/src-fJVbhdn-.mjs.map +1 -0
- package/dist/theme.d.mts +115 -0
- package/dist/theme.d.mts.map +1 -0
- package/dist/theme.mjs +8 -0
- package/dist/theme.mjs.map +1 -0
- package/dist/types-Bhj5QkIQ.mjs +13 -0
- package/dist/types-Bhj5QkIQ.mjs.map +1 -0
- package/dist/types-CDgkE-Rw.d.mts +241 -0
- package/dist/types-CDgkE-Rw.d.mts.map +1 -0
- package/dist/ui/animation.d.mts +2 -0
- package/dist/ui/animation.mjs +2 -0
- package/dist/ui/ansi.d.mts +2 -0
- package/dist/ui/ansi.mjs +2 -0
- package/dist/ui/cli.d.mts +5 -0
- package/dist/ui/cli.mjs +7 -0
- package/dist/ui/display.d.mts +35 -0
- package/dist/ui/display.d.mts.map +1 -0
- package/dist/ui/display.mjs +123 -0
- package/dist/ui/display.mjs.map +1 -0
- package/dist/ui/image.d.mts +2 -0
- package/dist/ui/image.mjs +2 -0
- package/dist/ui/input.d.mts +184 -0
- package/dist/ui/input.d.mts.map +1 -0
- package/dist/ui/input.mjs +285 -0
- package/dist/ui/input.mjs.map +1 -0
- package/dist/ui/progress.d.mts +249 -0
- package/dist/ui/progress.d.mts.map +1 -0
- package/dist/ui/progress.mjs +858 -0
- package/dist/ui/progress.mjs.map +1 -0
- package/dist/ui/react.d.mts +280 -0
- package/dist/ui/react.d.mts.map +1 -0
- package/dist/ui/react.mjs +413 -0
- package/dist/ui/react.mjs.map +1 -0
- package/dist/ui/utils.d.mts +86 -0
- package/dist/ui/utils.d.mts.map +1 -0
- package/dist/ui/utils.mjs +2 -0
- package/dist/ui/wrappers.d.mts +3 -0
- package/dist/ui/wrappers.mjs +2 -0
- package/dist/ui.d.mts +6 -0
- package/dist/ui.mjs +7 -0
- package/dist/useLatest-BMIYXd6e.d.mts +154 -0
- package/dist/useLatest-BMIYXd6e.d.mts.map +1 -0
- package/dist/useLayout-BG2cGl15.mjs +139 -0
- package/dist/useLayout-BG2cGl15.mjs.map +1 -0
- package/dist/with-text-input-CmHf_9d6.d.mts +284 -0
- package/dist/with-text-input-CmHf_9d6.d.mts.map +1 -0
- package/dist/wrapper-Dqh0zi2W.mjs +3527 -0
- package/dist/wrapper-Dqh0zi2W.mjs.map +1 -0
- package/dist/wrappers-hhL8EQ_n.mjs +810 -0
- package/dist/wrappers-hhL8EQ_n.mjs.map +1 -0
- package/dist/yoga-adapter-BJ9SOhTY.mjs +245 -0
- package/dist/yoga-adapter-BJ9SOhTY.mjs.map +1 -0
- package/dist/yoga-adapter-Daq6-dw1.mjs +2 -0
- package/package.json +48 -75
- package/CHANGELOG.md +0 -319
- package/dist/chalk.js +0 -4
- package/dist/index.js +0 -270
- package/dist/ink.js +0 -142
- package/dist/runtime.js +0 -135
- package/dist/theme.js +0 -7
- package/dist/ui/animation.js +0 -3
- package/dist/ui/ansi.js +0 -3
- package/dist/ui/cli.js +0 -9
- package/dist/ui/display.js +0 -4
- package/dist/ui/image.js +0 -4
- package/dist/ui/input.js +0 -3
- package/dist/ui/progress.js +0 -9
- package/dist/ui/react.js +0 -4
- package/dist/ui/utils.js +0 -3
- package/dist/ui/wrappers.js +0 -15
- package/dist/ui.js +0 -18
- package/src/index.ts +0 -73
- package/src/runtime.ts +0 -4
- package/src/theme.ts +0 -4
- package/src/ui/animation.ts +0 -2
- package/src/ui/ansi.ts +0 -2
- package/src/ui/cli.ts +0 -3
- package/src/ui/display.ts +0 -2
- package/src/ui/image.ts +0 -2
- package/src/ui/input.ts +0 -2
- package/src/ui/progress.ts +0 -2
- package/src/ui/react.ts +0 -2
- package/src/ui/utils.ts +0 -2
- package/src/ui/wrappers.ts +0 -2
- 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"}
|