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,6 @@
1
+ import { n as __esmMin } from "./chunk-BSw8zbkd.mjs";
2
+ //#endregion
3
+ __esmMin((() => {}))();
4
+ export {};
5
+
6
+ //# sourceMappingURL=__vite-browser-external-2447137e-D3GdsvS_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"__vite-browser-external-2447137e-D3GdsvS_.mjs","names":[],"sources":["../../../node_modules/.bun/ghostty-web@0.4.0/node_modules/ghostty-web/dist/__vite-browser-external-2447137e.js"],"sourcesContent":["const e = {};\nexport {\n e as default\n};\n"],"x_google_ignoreList":[0],"mappings":""}
@@ -0,0 +1,304 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ //#region packages/ag-react/src/ui/animation/easing.ts
3
+ const easings = {
4
+ linear: (t) => t,
5
+ ease: (t) => t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
6
+ easeIn: (t) => t * t,
7
+ easeOut: (t) => t * (2 - t),
8
+ easeInOut: (t) => t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
9
+ easeInCubic: (t) => t * t * t,
10
+ easeOutCubic: (t) => --t * t * t + 1
11
+ };
12
+ /** Resolve an easing — accepts a name string or a custom function. */
13
+ function resolveEasing(easing) {
14
+ return typeof easing === "function" ? easing : easings[easing];
15
+ }
16
+ //#endregion
17
+ //#region packages/ag-react/src/ui/animation/useAnimation.ts
18
+ /**
19
+ * useAnimation - Animate a value from 0 to 1 over a duration.
20
+ *
21
+ * Drives a single animation cycle with configurable easing, delay,
22
+ * and completion callback. Targets ~30fps (33ms interval) since
23
+ * terminals don't benefit from higher refresh rates.
24
+ */
25
+ /** ~30fps tick interval for terminal animations */
26
+ const TICK_MS$1 = 33;
27
+ /**
28
+ * Animate a value from 0 to 1 over a duration with easing.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * function FadeIn({ children }) {
33
+ * const { value } = useAnimation({ duration: 300, easing: "easeOut" })
34
+ * return <Text dimColor={value < 1}>{children}</Text>
35
+ * }
36
+ * ```
37
+ */
38
+ function useAnimation(options) {
39
+ const { duration, easing = "linear", delay = 0, onComplete, enabled = true } = options;
40
+ const [value, setValue] = useState(0);
41
+ const [isAnimating, setIsAnimating] = useState(false);
42
+ const startTimeRef = useRef(0);
43
+ const intervalRef = useRef(null);
44
+ const onCompleteRef = useRef(onComplete);
45
+ onCompleteRef.current = onComplete;
46
+ const epochRef = useRef(0);
47
+ const easingFn = resolveEasing(easing);
48
+ const stopInterval = useCallback(() => {
49
+ if (intervalRef.current !== null) {
50
+ clearInterval(intervalRef.current);
51
+ intervalRef.current = null;
52
+ }
53
+ }, []);
54
+ const startAnimation = useCallback(() => {
55
+ stopInterval();
56
+ epochRef.current++;
57
+ const epoch = epochRef.current;
58
+ setValue(0);
59
+ setIsAnimating(true);
60
+ const begin = () => {
61
+ if (epochRef.current !== epoch) return;
62
+ startTimeRef.current = performance.now();
63
+ intervalRef.current = setInterval(() => {
64
+ if (epochRef.current !== epoch) return;
65
+ const elapsed = performance.now() - startTimeRef.current;
66
+ const raw = Math.min(elapsed / duration, 1);
67
+ setValue(easingFn(raw));
68
+ if (raw >= 1) {
69
+ stopInterval();
70
+ setIsAnimating(false);
71
+ onCompleteRef.current?.();
72
+ }
73
+ }, TICK_MS$1);
74
+ };
75
+ if (delay > 0) setTimeout(() => begin(), delay);
76
+ else begin();
77
+ }, [
78
+ duration,
79
+ delay,
80
+ easingFn,
81
+ stopInterval
82
+ ]);
83
+ useEffect(() => {
84
+ if (!enabled) {
85
+ stopInterval();
86
+ setValue(0);
87
+ setIsAnimating(false);
88
+ return;
89
+ }
90
+ startAnimation();
91
+ return () => {
92
+ stopInterval();
93
+ };
94
+ }, [
95
+ enabled,
96
+ startAnimation,
97
+ stopInterval
98
+ ]);
99
+ return {
100
+ value,
101
+ isAnimating,
102
+ reset: useCallback(() => {
103
+ startAnimation();
104
+ }, [startAnimation])
105
+ };
106
+ }
107
+ //#endregion
108
+ //#region packages/ag-react/src/ui/animation/useTransition.ts
109
+ /**
110
+ * useTransition - Smoothly interpolate between numeric values.
111
+ *
112
+ * When the target value changes, animates from the current value toward
113
+ * the new target. If the target changes mid-animation, restarts from
114
+ * the current interpolated position. Targets ~30fps.
115
+ */
116
+ /** ~30fps tick interval for terminal animations */
117
+ const TICK_MS = 33;
118
+ /**
119
+ * Smoothly interpolate when the target value changes.
120
+ *
121
+ * Returns the current interpolated value. On the first render, returns
122
+ * the target value immediately (no animation). Subsequent changes
123
+ * animate from the previous value to the new target.
124
+ *
125
+ * @example
126
+ * ```tsx
127
+ * function ScrollOffset({ target }) {
128
+ * const smooth = useTransition(target, { duration: 200, easing: "easeOut" })
129
+ * return <Box marginTop={Math.round(smooth)}>...</Box>
130
+ * }
131
+ * ```
132
+ */
133
+ function useTransition(targetValue, options) {
134
+ const { duration = 300, easing = "easeOut" } = options ?? {};
135
+ const [currentValue, setCurrentValue] = useState(targetValue);
136
+ const fromRef = useRef(targetValue);
137
+ const toRef = useRef(targetValue);
138
+ const startTimeRef = useRef(0);
139
+ const intervalRef = useRef(null);
140
+ const isFirstRef = useRef(true);
141
+ const easingFn = resolveEasing(easing);
142
+ useEffect(() => {
143
+ if (isFirstRef.current) {
144
+ isFirstRef.current = false;
145
+ return;
146
+ }
147
+ if (targetValue === toRef.current) return;
148
+ fromRef.current = currentValue;
149
+ toRef.current = targetValue;
150
+ startTimeRef.current = performance.now();
151
+ if (intervalRef.current !== null) clearInterval(intervalRef.current);
152
+ intervalRef.current = setInterval(() => {
153
+ const elapsed = performance.now() - startTimeRef.current;
154
+ const raw = Math.min(elapsed / duration, 1);
155
+ const eased = easingFn(raw);
156
+ setCurrentValue(fromRef.current + (toRef.current - fromRef.current) * eased);
157
+ if (raw >= 1) {
158
+ setCurrentValue(toRef.current);
159
+ if (intervalRef.current !== null) {
160
+ clearInterval(intervalRef.current);
161
+ intervalRef.current = null;
162
+ }
163
+ }
164
+ }, TICK_MS);
165
+ return () => {
166
+ if (intervalRef.current !== null) {
167
+ clearInterval(intervalRef.current);
168
+ intervalRef.current = null;
169
+ }
170
+ };
171
+ }, [
172
+ targetValue,
173
+ duration,
174
+ easingFn
175
+ ]);
176
+ return currentValue;
177
+ }
178
+ //#endregion
179
+ //#region packages/ag-react/src/ui/animation/useInterval.ts
180
+ /**
181
+ * useInterval - Run a callback on a fixed interval.
182
+ *
183
+ * Uses Dan Abramov's ref pattern to avoid stale closures.
184
+ * The callback is NOT called on mount — only on subsequent ticks.
185
+ */
186
+ /**
187
+ * Run a callback on a fixed interval.
188
+ *
189
+ * The callback is NOT called on mount — only on ticks after the interval
190
+ * elapses. Uses a ref for the callback to avoid stale closures.
191
+ *
192
+ * @param callback - Function to call on each tick
193
+ * @param ms - Interval in milliseconds
194
+ * @param enabled - Whether the interval is active (default: true)
195
+ */
196
+ function useInterval(callback, ms, enabled = true) {
197
+ const callbackRef = useRef(callback);
198
+ callbackRef.current = callback;
199
+ useEffect(() => {
200
+ if (!enabled) return;
201
+ const id = setInterval(() => {
202
+ callbackRef.current();
203
+ }, ms);
204
+ return () => {
205
+ clearInterval(id);
206
+ };
207
+ }, [ms, enabled]);
208
+ }
209
+ //#endregion
210
+ //#region packages/ag-react/src/ui/animation/useTimeout.ts
211
+ /**
212
+ * useTimeout - Run a callback after a delay.
213
+ *
214
+ * Uses a ref for the callback to avoid stale closures (Dan Abramov pattern).
215
+ * The timer resets when `ms` or `enabled` changes. When `enabled` becomes false,
216
+ * the timer is cleared. Returns a `reset` function to restart the timer.
217
+ *
218
+ * Unlike useInterval, this fires exactly once per enable/reset cycle.
219
+ */
220
+ /**
221
+ * Run a callback after a delay.
222
+ *
223
+ * The callback fires once after `ms` milliseconds. The timer resets when
224
+ * `ms` or `enabled` changes. Returns `{ reset, clear }` for manual control.
225
+ *
226
+ * @param callback - Function to call when the timer fires
227
+ * @param ms - Delay in milliseconds
228
+ * @param enabled - Whether the timer is active (default: true)
229
+ */
230
+ function useTimeout(callback, ms, enabled = true) {
231
+ const callbackRef = useRef(callback);
232
+ callbackRef.current = callback;
233
+ const timerRef = useRef(null);
234
+ const clear = useCallback(() => {
235
+ if (timerRef.current !== null) {
236
+ clearTimeout(timerRef.current);
237
+ timerRef.current = null;
238
+ }
239
+ }, []);
240
+ const reset = useCallback(() => {
241
+ clear();
242
+ if (enabled) timerRef.current = setTimeout(() => {
243
+ timerRef.current = null;
244
+ callbackRef.current();
245
+ }, ms);
246
+ }, [
247
+ ms,
248
+ enabled,
249
+ clear
250
+ ]);
251
+ useEffect(() => {
252
+ if (!enabled) {
253
+ clear();
254
+ return;
255
+ }
256
+ timerRef.current = setTimeout(() => {
257
+ timerRef.current = null;
258
+ callbackRef.current();
259
+ }, ms);
260
+ return clear;
261
+ }, [
262
+ ms,
263
+ enabled,
264
+ clear
265
+ ]);
266
+ return {
267
+ reset,
268
+ clear
269
+ };
270
+ }
271
+ //#endregion
272
+ //#region packages/ag-react/src/ui/animation/useLatest.ts
273
+ /**
274
+ * useLatest - Always-current ref to a value.
275
+ *
276
+ * The classic React pattern for avoiding stale closures in callbacks,
277
+ * timers, and effects. Returns a ref whose `.current` is always the
278
+ * latest value — safe to read from any async context.
279
+ *
280
+ * ```tsx
281
+ * const countRef = useLatest(count)
282
+ * useInterval(() => {
283
+ * console.log(countRef.current) // always fresh
284
+ * }, 1000)
285
+ * ```
286
+ */
287
+ /**
288
+ * Returns a ref that always holds the latest value.
289
+ *
290
+ * Useful when a callback needs access to current state/props without
291
+ * re-creating the callback (which would reset timers, event listeners, etc).
292
+ *
293
+ * @param value - The value to track
294
+ * @returns A ref whose `.current` is always `value`
295
+ */
296
+ function useLatest(value) {
297
+ const ref = useRef(value);
298
+ ref.current = value;
299
+ return ref;
300
+ }
301
+ //#endregion
302
+ export { useAnimation as a, useTransition as i, useTimeout as n, easings as o, useInterval as r, resolveEasing as s, useLatest as t };
303
+
304
+ //# sourceMappingURL=animation-C_PTO0uH.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation-C_PTO0uH.mjs","names":["TICK_MS"],"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"],"sourcesContent":["/**\n * Easing Functions\n *\n * Maps time progress (0-1) to value progress (0-1) for smooth animations.\n * Includes common presets and a resolver for name-or-function usage.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Easing function: maps time progress (0-1) to value progress (0-1) */\nexport type EasingFn = (t: number) => number\n\n// ============================================================================\n// Presets\n// ============================================================================\n\nexport const easings = {\n linear: (t: number) => t,\n ease: (t: number) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),\n easeIn: (t: number) => t * t,\n easeOut: (t: number) => t * (2 - t),\n easeInOut: (t: number) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),\n easeInCubic: (t: number) => t * t * t,\n easeOutCubic: (t: number) => --t * t * t + 1,\n} as const satisfies Record<string, EasingFn>\n\nexport type EasingName = keyof typeof easings\n\n// ============================================================================\n// Resolver\n// ============================================================================\n\n/** Resolve an easing — accepts a name string or a custom function. */\nexport function resolveEasing(easing: EasingName | EasingFn): EasingFn {\n return typeof easing === \"function\" ? easing : easings[easing]\n}\n","/**\n * useAnimation - Animate a value from 0 to 1 over a duration.\n *\n * Drives a single animation cycle with configurable easing, delay,\n * and completion callback. Targets ~30fps (33ms interval) since\n * terminals don't benefit from higher refresh rates.\n */\n\nimport { useState, useEffect, useRef, useCallback } from \"react\"\nimport { resolveEasing, type EasingName, type EasingFn } from \"./easing\"\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseAnimationOptions {\n /** Duration in milliseconds */\n duration: number\n /** Easing function or preset name */\n easing?: EasingName | EasingFn\n /** Delay before starting (ms) */\n delay?: number\n /** Called when animation completes */\n onComplete?: () => void\n /** Whether to run the animation (default: true) */\n enabled?: boolean\n}\n\nexport interface UseAnimationResult {\n /** Current progress value (0 to 1, eased) */\n value: number\n /** Whether the animation is still running */\n isAnimating: boolean\n /** Reset and replay the animation */\n reset: () => void\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** ~30fps tick interval for terminal animations */\nconst TICK_MS = 33\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Animate a value from 0 to 1 over a duration with easing.\n *\n * @example\n * ```tsx\n * function FadeIn({ children }) {\n * const { value } = useAnimation({ duration: 300, easing: \"easeOut\" })\n * return <Text dimColor={value < 1}>{children}</Text>\n * }\n * ```\n */\nexport function useAnimation(options: UseAnimationOptions): UseAnimationResult {\n const { duration, easing = \"linear\", delay = 0, onComplete, enabled = true } = options\n\n const [value, setValue] = useState(0)\n const [isAnimating, setIsAnimating] = useState(false)\n\n const startTimeRef = useRef(0)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n const onCompleteRef = useRef(onComplete)\n onCompleteRef.current = onComplete\n\n // Epoch bumps on each reset to invalidate stale intervals\n const epochRef = useRef(0)\n\n const easingFn = resolveEasing(easing)\n\n const stopInterval = useCallback(() => {\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current)\n intervalRef.current = null\n }\n }, [])\n\n const startAnimation = useCallback(() => {\n stopInterval()\n epochRef.current++\n const epoch = epochRef.current\n\n setValue(0)\n setIsAnimating(true)\n\n const begin = () => {\n // Guard against stale starts after a reset\n if (epochRef.current !== epoch) return\n\n startTimeRef.current = performance.now()\n\n intervalRef.current = setInterval(() => {\n // Guard against stale ticks after a reset\n if (epochRef.current !== epoch) return\n\n const elapsed = performance.now() - startTimeRef.current\n const raw = Math.min(elapsed / duration, 1)\n const eased = easingFn(raw)\n\n setValue(eased)\n\n if (raw >= 1) {\n stopInterval()\n setIsAnimating(false)\n onCompleteRef.current?.()\n }\n }, TICK_MS)\n }\n\n if (delay > 0) {\n setTimeout(() => begin(), delay)\n } else {\n begin()\n }\n }, [duration, delay, easingFn, stopInterval])\n\n // Start on mount (if enabled)\n useEffect(() => {\n if (!enabled) {\n stopInterval()\n setValue(0)\n setIsAnimating(false)\n return\n }\n\n startAnimation()\n\n return () => {\n stopInterval()\n }\n }, [enabled, startAnimation, stopInterval])\n\n const reset = useCallback(() => {\n startAnimation()\n }, [startAnimation])\n\n return { value, isAnimating, reset }\n}\n","/**\n * useTransition - Smoothly interpolate between numeric values.\n *\n * When the target value changes, animates from the current value toward\n * the new target. If the target changes mid-animation, restarts from\n * the current interpolated position. Targets ~30fps.\n */\n\nimport { useState, useEffect, useRef } from \"react\"\nimport { resolveEasing, type EasingName, type EasingFn } from \"./easing\"\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseTransitionOptions {\n /** Duration in milliseconds (default: 300) */\n duration?: number\n /** Easing function or preset name (default: \"easeOut\") */\n easing?: EasingName | EasingFn\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** ~30fps tick interval for terminal animations */\nconst TICK_MS = 33\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Smoothly interpolate when the target value changes.\n *\n * Returns the current interpolated value. On the first render, returns\n * the target value immediately (no animation). Subsequent changes\n * animate from the previous value to the new target.\n *\n * @example\n * ```tsx\n * function ScrollOffset({ target }) {\n * const smooth = useTransition(target, { duration: 200, easing: \"easeOut\" })\n * return <Box marginTop={Math.round(smooth)}>...</Box>\n * }\n * ```\n */\nexport function useTransition(targetValue: number, options?: UseTransitionOptions): number {\n const { duration = 300, easing = \"easeOut\" } = options ?? {}\n\n const [currentValue, setCurrentValue] = useState(targetValue)\n\n const fromRef = useRef(targetValue)\n const toRef = useRef(targetValue)\n const startTimeRef = useRef(0)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n const isFirstRef = useRef(true)\n\n const easingFn = resolveEasing(easing)\n\n useEffect(() => {\n // On first render, snap to target without animation\n if (isFirstRef.current) {\n isFirstRef.current = false\n return\n }\n\n // If target hasn't changed, nothing to do\n if (targetValue === toRef.current) return\n\n // Start from wherever we currently are\n fromRef.current = currentValue\n toRef.current = targetValue\n startTimeRef.current = performance.now()\n\n // Clear any existing interval\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current)\n }\n\n intervalRef.current = setInterval(() => {\n const elapsed = performance.now() - startTimeRef.current\n const raw = Math.min(elapsed / duration, 1)\n const eased = easingFn(raw)\n const interpolated = fromRef.current + (toRef.current - fromRef.current) * eased\n\n setCurrentValue(interpolated)\n\n if (raw >= 1) {\n // Snap to exact target and stop\n setCurrentValue(toRef.current)\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current)\n intervalRef.current = null\n }\n }\n }, TICK_MS)\n\n return () => {\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current)\n intervalRef.current = null\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [targetValue, duration, easingFn])\n\n return currentValue\n}\n","/**\n * useInterval - Run a callback on a fixed interval.\n *\n * Uses Dan Abramov's ref pattern to avoid stale closures.\n * The callback is NOT called on mount — only on subsequent ticks.\n */\n\nimport { useEffect, useRef } from \"react\"\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Run a callback on a fixed interval.\n *\n * The callback is NOT called on mount — only on ticks after the interval\n * elapses. Uses a ref for the callback to avoid stale closures.\n *\n * @param callback - Function to call on each tick\n * @param ms - Interval in milliseconds\n * @param enabled - Whether the interval is active (default: true)\n */\nexport function useInterval(callback: () => void, ms: number, enabled = true): void {\n const callbackRef = useRef(callback)\n callbackRef.current = callback\n\n useEffect(() => {\n if (!enabled) return\n\n const id = setInterval(() => {\n callbackRef.current()\n }, ms)\n\n return () => {\n clearInterval(id)\n }\n }, [ms, enabled])\n}\n","/**\n * useTimeout - Run a callback after a delay.\n *\n * Uses a ref for the callback to avoid stale closures (Dan Abramov pattern).\n * The timer resets when `ms` or `enabled` changes. When `enabled` becomes false,\n * the timer is cleared. Returns a `reset` function to restart the timer.\n *\n * Unlike useInterval, this fires exactly once per enable/reset cycle.\n */\n\nimport { useCallback, useEffect, useRef } from \"react\"\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Run a callback after a delay.\n *\n * The callback fires once after `ms` milliseconds. The timer resets when\n * `ms` or `enabled` changes. Returns `{ reset, clear }` for manual control.\n *\n * @param callback - Function to call when the timer fires\n * @param ms - Delay in milliseconds\n * @param enabled - Whether the timer is active (default: true)\n */\nexport function useTimeout(callback: () => void, ms: number, enabled = true): { reset: () => void; clear: () => void } {\n const callbackRef = useRef(callback)\n callbackRef.current = callback\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const clear = useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current)\n timerRef.current = null\n }\n }, [])\n\n const reset = useCallback(() => {\n clear()\n if (enabled) {\n timerRef.current = setTimeout(() => {\n timerRef.current = null\n callbackRef.current()\n }, ms)\n }\n }, [ms, enabled, clear])\n\n useEffect(() => {\n if (!enabled) {\n clear()\n return\n }\n\n timerRef.current = setTimeout(() => {\n timerRef.current = null\n callbackRef.current()\n }, ms)\n\n return clear\n }, [ms, enabled, clear])\n\n return { reset, clear }\n}\n","/**\n * useLatest - Always-current ref to a value.\n *\n * The classic React pattern for avoiding stale closures in callbacks,\n * timers, and effects. Returns a ref whose `.current` is always the\n * latest value — safe to read from any async context.\n *\n * ```tsx\n * const countRef = useLatest(count)\n * useInterval(() => {\n * console.log(countRef.current) // always fresh\n * }, 1000)\n * ```\n */\n\nimport { useRef } from \"react\"\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Returns a ref that always holds the latest value.\n *\n * Useful when a callback needs access to current state/props without\n * re-creating the callback (which would reset timers, event listeners, etc).\n *\n * @param value - The value to track\n * @returns A ref whose `.current` is always `value`\n */\nexport function useLatest<T>(value: T): { readonly current: T } {\n const ref = useRef(value)\n ref.current = value\n return ref\n}\n"],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ //#region packages/ag-react/src/ui/cli/ansi.ts
2
+ /**
3
+ * ANSI escape code utilities for terminal control
4
+ */
5
+ /** Hide the cursor */
6
+ const CURSOR_HIDE = "\x1B[?25l";
7
+ /** Show the cursor */
8
+ const CURSOR_SHOW = "\x1B[?25h";
9
+ /** Move cursor to beginning of line */
10
+ const CURSOR_TO_START = "\r";
11
+ /** Clear from cursor to end of line */
12
+ const CLEAR_LINE_END = "\x1B[K";
13
+ /** Clear entire line */
14
+ const CLEAR_LINE = "\x1B[2K";
15
+ /** Clear screen and move to top-left */
16
+ const CLEAR_SCREEN = "\x1B[2J\x1B[H";
17
+ /** Move cursor up N lines */
18
+ const cursorUp = (n = 1) => `\x1b[${n}A`;
19
+ /** Move cursor down N lines */
20
+ const cursorDown = (n = 1) => `\x1b[${n}B`;
21
+ /** Save cursor position */
22
+ const CURSOR_SAVE = "\x1B[s";
23
+ /** Restore cursor position */
24
+ const CURSOR_RESTORE = "\x1B[u";
25
+ /**
26
+ * Write to stream with proper handling
27
+ */
28
+ function write(text, stream = process.stdout) {
29
+ stream.write(text);
30
+ }
31
+ /**
32
+ * Clear the current line and write new text
33
+ */
34
+ function writeLine(text, stream = process.stdout) {
35
+ stream.write(`
36
+ }
37
+ /**
38
+ * Wrap a function to handle cursor visibility
39
+ * Hides cursor on start, shows on completion/error
40
+ */
41
+ function withCursor(fn, stream = process.stdout) {
42
+ stream.write(CURSOR_HIDE);
43
+ const restore = () => stream.write(CURSOR_SHOW);
44
+ try {
45
+ const result = fn();
46
+ if (result instanceof Promise) return result.finally(restore);
47
+ restore();
48
+ return Promise.resolve(result);
49
+ } catch (error) {
50
+ restore();
51
+ throw error;
52
+ }
53
+ }
54
+ /**
55
+ * Check if stream is a TTY (supports ANSI codes)
56
+ * Also respects FORCE_TTY environment variable for testing
57
+ */
58
+ function isTTY(stream = process.stdout) {
59
+ if (process.env.FORCE_TTY === "1") return true;
60
+ return stream.isTTY ?? false;
61
+ }
62
+ /**
63
+ * Get terminal width
64
+ */
65
+ function getTerminalWidth(stream = process.stdout) {
66
+ return stream.columns ?? 80;
67
+ }
68
+ //#endregion
69
+ export { CURSOR_RESTORE as a, CURSOR_TO_START as c, getTerminalWidth as d, isTTY as f, writeLine as h, CURSOR_HIDE as i, cursorDown as l, write as m, CLEAR_LINE_END as n, CURSOR_SAVE as o, withCursor as p, CLEAR_SCREEN as r, CURSOR_SHOW as s, CLEAR_LINE as t, cursorUp as u };
70
+
71
+ //# sourceMappingURL=ansi-CXLE_pt1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi-CXLE_pt1.mjs","names":[],"sources":["../packages/ag-react/src/ui/cli/ansi.ts"],"sourcesContent":["/**\n * ANSI escape code utilities for terminal control\n */\n\n/** Hide the cursor */\nexport const CURSOR_HIDE = \"\\x1b[?25l\"\n\n/** Show the cursor */\nexport const CURSOR_SHOW = \"\\x1b[?25h\"\n\n/** Move cursor to beginning of line */\nexport const CURSOR_TO_START = \"\\r\"\n\n/** Clear from cursor to end of line */\nexport const CLEAR_LINE_END = \"\\x1b[K\"\n\n/** Clear entire line */\nexport const CLEAR_LINE = \"\\x1b[2K\"\n\n/** Clear screen and move to top-left */\nexport const CLEAR_SCREEN = \"\\x1b[2J\\x1b[H\"\n\n/** Move cursor up N lines */\nexport const cursorUp = (n: number = 1): string => `\\x1b[${n}A`\n\n/** Move cursor down N lines */\nexport const cursorDown = (n: number = 1): string => `\\x1b[${n}B`\n\n/** Save cursor position */\nexport const CURSOR_SAVE = \"\\x1b[s\"\n\n/** Restore cursor position */\nexport const CURSOR_RESTORE = \"\\x1b[u\"\n\n/**\n * Write to stream with proper handling\n */\nexport function write(text: string, stream: NodeJS.WriteStream = process.stdout): void {\n stream.write(text)\n}\n\n/**\n * Clear the current line and write new text\n */\nexport function writeLine(text: string, stream: NodeJS.WriteStream = process.stdout): void {\n stream.write(`${CURSOR_TO_START}${text}${CLEAR_LINE_END}`)\n}\n\n/**\n * Wrap a function to handle cursor visibility\n * Hides cursor on start, shows on completion/error\n */\nexport function withCursor<T>(fn: () => T | Promise<T>, stream: NodeJS.WriteStream = process.stdout): Promise<T> {\n stream.write(CURSOR_HIDE)\n\n const restore = () => stream.write(CURSOR_SHOW)\n\n try {\n const result = fn()\n if (result instanceof Promise) {\n return result.finally(restore)\n }\n restore()\n return Promise.resolve(result)\n } catch (error) {\n restore()\n throw error\n }\n}\n\n/**\n * Check if stream is a TTY (supports ANSI codes)\n * Also respects FORCE_TTY environment variable for testing\n */\nexport function isTTY(stream: NodeJS.WriteStream = process.stdout): boolean {\n if (process.env.FORCE_TTY === \"1\") return true\n return stream.isTTY ?? false\n}\n\n/**\n * Get terminal width\n */\nexport function getTerminalWidth(stream: NodeJS.WriteStream = process.stdout): number {\n return stream.columns ?? 80\n}\n"],"mappings":";;;;;AAKA,MAAa,cAAc;;AAG3B,MAAa,cAAc;;AAG3B,MAAa,kBAAkB;;AAG/B,MAAa,iBAAiB;;AAG9B,MAAa,aAAa;;AAG1B,MAAa,eAAe;;AAG5B,MAAa,YAAY,IAAY,MAAc,QAAQ,EAAE;;AAG7D,MAAa,cAAc,IAAY,MAAc,QAAQ,EAAE;;AAG/D,MAAa,cAAc;;AAG3B,MAAa,iBAAiB;;;;AAK9B,SAAgB,MAAM,MAAc,SAA6B,QAAQ,QAAc;AACrF,QAAO,MAAM,KAAK;;;;;AAMpB,SAAgB,UAAU,MAAc,SAA6B,QAAQ,QAAc;AACzF,QAAO,MAAM;EAAqB,UAAwB;;;;;;AAO5D,SAAgB,WAAc,IAA0B,SAA6B,QAAQ,QAAoB;AAC/G,QAAO,MAAM,YAAY;CAEzB,MAAM,gBAAgB,OAAO,MAAM,YAAY;AAE/C,KAAI;EACF,MAAM,SAAS,IAAI;AACnB,MAAI,kBAAkB,QACpB,QAAO,OAAO,QAAQ,QAAQ;AAEhC,WAAS;AACT,SAAO,QAAQ,QAAQ,OAAO;UACvB,OAAO;AACd,WAAS;AACT,QAAM;;;;;;;AAQV,SAAgB,MAAM,SAA6B,QAAQ,QAAiB;AAC1E,KAAI,QAAQ,IAAI,cAAc,IAAK,QAAO;AAC1C,QAAO,OAAO,SAAS;;;;;AAMzB,SAAgB,iBAAiB,SAA6B,QAAQ,QAAgB;AACpF,QAAO,OAAO,WAAW"}
@@ -0,0 +1,49 @@
1
+ //#region packages/ag-react/src/ui/cli/ansi.d.ts
2
+ /**
3
+ * ANSI escape code utilities for terminal control
4
+ */
5
+ /** Hide the cursor */
6
+ declare const CURSOR_HIDE = "\u001B[?25l";
7
+ /** Show the cursor */
8
+ declare const CURSOR_SHOW = "\u001B[?25h";
9
+ /** Move cursor to beginning of line */
10
+ declare const CURSOR_TO_START = "\r";
11
+ /** Clear from cursor to end of line */
12
+ declare const CLEAR_LINE_END = "\u001B[K";
13
+ /** Clear entire line */
14
+ declare const CLEAR_LINE = "\u001B[2K";
15
+ /** Clear screen and move to top-left */
16
+ declare const CLEAR_SCREEN = "\u001B[2J\u001B[H";
17
+ /** Move cursor up N lines */
18
+ declare const cursorUp: (n?: number) => string;
19
+ /** Move cursor down N lines */
20
+ declare const cursorDown: (n?: number) => string;
21
+ /** Save cursor position */
22
+ declare const CURSOR_SAVE = "\u001B[s";
23
+ /** Restore cursor position */
24
+ declare const CURSOR_RESTORE = "\u001B[u";
25
+ /**
26
+ * Write to stream with proper handling
27
+ */
28
+ declare function write(text: string, stream?: NodeJS.WriteStream): void;
29
+ /**
30
+ * Clear the current line and write new text
31
+ */
32
+ declare function writeLine(text: string, stream?: NodeJS.WriteStream): void;
33
+ /**
34
+ * Wrap a function to handle cursor visibility
35
+ * Hides cursor on start, shows on completion/error
36
+ */
37
+ declare function withCursor<T>(fn: () => T | Promise<T>, stream?: NodeJS.WriteStream): Promise<T>;
38
+ /**
39
+ * Check if stream is a TTY (supports ANSI codes)
40
+ * Also respects FORCE_TTY environment variable for testing
41
+ */
42
+ declare function isTTY(stream?: NodeJS.WriteStream): boolean;
43
+ /**
44
+ * Get terminal width
45
+ */
46
+ declare function getTerminalWidth(stream?: NodeJS.WriteStream): number;
47
+ //#endregion
48
+ export { CURSOR_RESTORE as a, CURSOR_TO_START as c, getTerminalWidth as d, isTTY as f, writeLine as h, CURSOR_HIDE as i, cursorDown as l, write as m, CLEAR_LINE_END as n, CURSOR_SAVE as o, withCursor as p, CLEAR_SCREEN as r, CURSOR_SHOW as s, CLEAR_LINE as t, cursorUp as u };
49
+ //# sourceMappingURL=ansi-zmNzgkPB.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi-zmNzgkPB.d.mts","names":[],"sources":["../packages/ag-react/src/ui/cli/ansi.ts"],"mappings":";;AAKA;;;cAAa,WAAA;;cAGA,WAAA;;cAGA,eAAA;;cAGA,cAAA;AAHb;AAAA,cAMa,UAAA;;cAGA,YAAA;;cAGA,QAAA,GAAY,CAAA;;cAGZ,UAAA,GAAc,CAAA;;cAGd,WAAA;AAZb;AAAA,cAea,cAAA;;;;iBAKG,KAAA,CAAM,IAAA,UAAc,MAAA,GAAQ,MAAA,CAAO,WAAA;;;;iBAOnC,SAAA,CAAU,IAAA,UAAc,MAAA,GAAQ,MAAA,CAAO,WAAA;AArBvD;;;;AAAA,iBA6BgB,UAAA,GAAA,CAAc,EAAA,QAAU,CAAA,GAAI,OAAA,CAAQ,CAAA,GAAI,MAAA,GAAQ,MAAA,CAAO,WAAA,GAA+B,OAAA,CAAQ,CAAA;AA1B9G;;;;AAAA,iBAgDgB,KAAA,CAAM,MAAA,GAAQ,MAAA,CAAO,WAAA;AA7CrC;;;AAAA,iBAqDgB,gBAAA,CAAiB,MAAA,GAAQ,MAAA,CAAO,WAAA"}
@@ -0,0 +1,3 @@
1
+ import { n as init_apng, t as createApng } from "./apng-ENBAJk-H.mjs";
2
+ init_apng();
3
+ export { createApng };
@@ -0,0 +1,70 @@
1
+ import { n as __esmMin, o as __toESM } from "./chunk-BSw8zbkd.mjs";
2
+ //#region ../termless/src/animation/apng.ts
3
+ async function loadUpng() {
4
+ if (upngModule) return upngModule;
5
+ try {
6
+ upngModule = await import("./UPNG-AVSMjiFE.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
7
+ return upngModule;
8
+ } catch {
9
+ throw new Error("createApng() requires upng-js. Install it:\n bun add upng-js");
10
+ }
11
+ }
12
+ async function loadResvg() {
13
+ if (resvgModule) return resvgModule;
14
+ try {
15
+ resvgModule = await import("./resvg-js-V6oMi8CY.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
16
+ return resvgModule;
17
+ } catch {
18
+ throw new Error("createApng() requires @resvg/resvg-js. Install it:\n bun add @resvg/resvg-js");
19
+ }
20
+ }
21
+ /**
22
+ * Encode animation frames as an animated PNG (APNG).
23
+ *
24
+ * Each SVG frame is rasterized to RGBA pixels via @resvg/resvg-js,
25
+ * then combined into a single APNG file via upng-js.
26
+ *
27
+ * @param frames - SVG frames with durations
28
+ * @param options - Animation options plus optional `scale` for rasterization
29
+ * @returns APNG file as Uint8Array
30
+ */
31
+ async function createApng(frames, options) {
32
+ if (frames.length === 0) throw new Error("createApng requires at least one frame");
33
+ const [UPNG, { Resvg }] = await Promise.all([loadUpng(), loadResvg()]);
34
+ const defaultDuration = options?.defaultDuration ?? 100;
35
+ const scale = options?.scale ?? 2;
36
+ const rgbaBuffers = [];
37
+ const delays = [];
38
+ let width = 0;
39
+ let height = 0;
40
+ for (const frame of frames) {
41
+ const duration = frame.duration || defaultDuration;
42
+ const rendered = new Resvg(frame.svg, {
43
+ fitTo: {
44
+ mode: "zoom",
45
+ value: scale
46
+ },
47
+ font: {
48
+ loadSystemFonts: true,
49
+ defaultFontFamily: "Menlo"
50
+ }
51
+ }).render();
52
+ if (width === 0) {
53
+ width = rendered.width;
54
+ height = rendered.height;
55
+ }
56
+ rgbaBuffers.push(rendered.pixels.buffer);
57
+ delays.push(duration);
58
+ }
59
+ const apng = UPNG.encode(rgbaBuffers, width, height, 0, delays);
60
+ return new Uint8Array(apng);
61
+ }
62
+ var upngModule, resvgModule;
63
+ var init_apng = __esmMin((() => {
64
+ upngModule = null;
65
+ resvgModule = null;
66
+ }));
67
+ //#endregion
68
+ export { init_apng as n, createApng as t };
69
+
70
+ //# sourceMappingURL=apng-ENBAJk-H.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apng-ENBAJk-H.mjs","names":[],"sources":["../../termless/src/animation/apng.ts"],"sourcesContent":["/**\n * Animated PNG (APNG) encoder for termless.\n *\n * Converts SVG frames to an APNG using upng-js for APNG encoding\n * and @resvg/resvg-js for SVG→pixel rasterization.\n *\n * Both are optional/lazy-loaded dependencies — throws clear errors if missing.\n */\n\nimport type { AnimationFrame, AnimationOptions } from \"./types.ts\"\n\n// Lazy-cached imports\nlet upngModule: typeof import(\"upng-js\") | null = null\nlet resvgModule: { Resvg: any } | null = null\n\nasync function loadUpng() {\n if (upngModule) return upngModule\n try {\n upngModule = await import(\"upng-js\")\n return upngModule\n } catch {\n throw new Error(\"createApng() requires upng-js. Install it:\\n bun add upng-js\")\n }\n}\n\nasync function loadResvg() {\n if (resvgModule) return resvgModule\n try {\n resvgModule = await import(\"@resvg/resvg-js\")\n return resvgModule\n } catch {\n throw new Error(\"createApng() requires @resvg/resvg-js. Install it:\\n bun add @resvg/resvg-js\")\n }\n}\n\n/**\n * Encode animation frames as an animated PNG (APNG).\n *\n * Each SVG frame is rasterized to RGBA pixels via @resvg/resvg-js,\n * then combined into a single APNG file via upng-js.\n *\n * @param frames - SVG frames with durations\n * @param options - Animation options plus optional `scale` for rasterization\n * @returns APNG file as Uint8Array\n */\nexport async function createApng(\n frames: AnimationFrame[],\n options?: AnimationOptions & { scale?: number },\n): Promise<Uint8Array> {\n if (frames.length === 0) {\n throw new Error(\"createApng requires at least one frame\")\n }\n\n const [UPNG, { Resvg }] = await Promise.all([loadUpng(), loadResvg()])\n\n const defaultDuration = options?.defaultDuration ?? 100\n const scale = options?.scale ?? 2\n\n const rgbaBuffers: ArrayBuffer[] = []\n const delays: number[] = []\n let width = 0\n let height = 0\n\n for (const frame of frames) {\n const duration = frame.duration || defaultDuration\n\n const resvg = new Resvg(frame.svg, {\n fitTo: { mode: \"zoom\" as const, value: scale },\n font: { loadSystemFonts: true, defaultFontFamily: \"Menlo\" },\n })\n const rendered = resvg.render()\n\n // Use first frame's dimensions as the canvas size\n if (width === 0) {\n width = rendered.width\n height = rendered.height\n }\n\n rgbaBuffers.push(rendered.pixels.buffer as ArrayBuffer)\n delays.push(duration)\n }\n\n // upng-js encode: cnum=0 means lossless (full RGBA, no quantization)\n const apng = UPNG.encode(rgbaBuffers, width, height, 0, delays)\n return new Uint8Array(apng)\n}\n"],"mappings":";;AAeA,eAAe,WAAW;AACxB,KAAI,WAAY,QAAO;AACvB,KAAI;AACF,eAAa,MAAM,OAAO,uBAAA,MAAA,MAAA,wBAAA,EAAA,SAAA,EAAA,CAAA;AAC1B,SAAO;SACD;AACN,QAAM,IAAI,MAAM,gEAAgE;;;AAIpF,eAAe,YAAY;AACzB,KAAI,YAAa,QAAO;AACxB,KAAI;AACF,gBAAc,MAAM,OAAO,2BAAA,MAAA,MAAA,wBAAA,EAAA,SAAA,EAAA,CAAA;AAC3B,SAAO;SACD;AACN,QAAM,IAAI,MAAM,gFAAgF;;;;;;;;;;;;;AAcpG,eAAsB,WACpB,QACA,SACqB;AACrB,KAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MAAM,yCAAyC;CAG3D,MAAM,CAAC,MAAM,EAAE,WAAW,MAAM,QAAQ,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;CAEtE,MAAM,kBAAkB,SAAS,mBAAmB;CACpD,MAAM,QAAQ,SAAS,SAAS;CAEhC,MAAM,cAA6B,EAAE;CACrC,MAAM,SAAmB,EAAE;CAC3B,IAAI,QAAQ;CACZ,IAAI,SAAS;AAEb,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,WAAW,MAAM,YAAY;EAMnC,MAAM,WAJQ,IAAI,MAAM,MAAM,KAAK;GACjC,OAAO;IAAE,MAAM;IAAiB,OAAO;IAAO;GAC9C,MAAM;IAAE,iBAAiB;IAAM,mBAAmB;IAAS;GAC5D,CAAC,CACqB,QAAQ;AAG/B,MAAI,UAAU,GAAG;AACf,WAAQ,SAAS;AACjB,YAAS,SAAS;;AAGpB,cAAY,KAAK,SAAS,OAAO,OAAsB;AACvD,SAAO,KAAK,SAAS;;CAIvB,MAAM,OAAO,KAAK,OAAO,aAAa,OAAO,QAAQ,GAAG,OAAO;AAC/D,QAAO,IAAI,WAAW,KAAK;;;;AAxEzB,cAA8C;AAC9C,eAAqC"}