silvery 0.18.1 → 0.19.0

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 (156) hide show
  1. package/dist/{animation-DhINOJk8.mjs → animation-Cn64yepo.mjs} +1 -1
  2. package/dist/{animation-DhINOJk8.mjs.map → animation-Cn64yepo.mjs.map} +1 -1
  3. package/dist/{ansi-C6Qs1Wn2.mjs → ansi-CLOitHKx.mjs} +1 -1
  4. package/dist/ansi-CLOitHKx.mjs.map +1 -0
  5. package/dist/{ansi-CsjnZtAw.d.mts → ansi-Cc33mW54.d.mts} +1 -1
  6. package/dist/{ansi-CsjnZtAw.d.mts.map → ansi-Cc33mW54.d.mts.map} +1 -1
  7. package/dist/{chunk-BSw8zbkd.mjs → chunk-Vs_PY4HZ.mjs} +1 -1
  8. package/dist/cli-BKp0YtBD.mjs +4 -0
  9. package/dist/{context-BjWgrikx.mjs → context-BU5LkkIy.mjs} +8 -7
  10. package/dist/context-BU5LkkIy.mjs.map +1 -0
  11. package/dist/devtools-9QY4teqI.mjs +2 -0
  12. package/dist/{devtools-CeO9X_uv.mjs → devtools-DxkSLXDA.mjs} +4 -5
  13. package/dist/devtools-DxkSLXDA.mjs.map +1 -0
  14. package/dist/{eta-BnQSZcWf.mjs → eta-Bb3RH3wh.mjs} +1 -1
  15. package/dist/{eta-BnQSZcWf.mjs.map → eta-Bb3RH3wh.mjs.map} +1 -1
  16. package/dist/{flexily-zero-adapter-BOM0cl8R.mjs → flexily-zero-adapter-BlQa46nr.mjs} +21 -64
  17. package/dist/flexily-zero-adapter-BlQa46nr.mjs.map +1 -0
  18. package/dist/{flexily-zero-adapter-V8R3HQtK.mjs → flexily-zero-adapter-CMxXhdOL.mjs} +1 -1
  19. package/dist/{image-B0zMbVUr.mjs → image-CTII5QWI.mjs} +3 -3
  20. package/dist/image-CTII5QWI.mjs.map +1 -0
  21. package/dist/{index-Bh3U1K09.d.mts → index-BXslOebb.d.mts} +547 -137
  22. package/dist/index-BXslOebb.d.mts.map +1 -0
  23. package/dist/{index-C4vrhbud.d.mts → index-BnA7mNpo.d.mts} +1 -1
  24. package/dist/{index-C4vrhbud.d.mts.map → index-BnA7mNpo.d.mts.map} +1 -1
  25. package/dist/index-D3saHouR.d.mts +1392 -0
  26. package/dist/index-D3saHouR.d.mts.map +1 -0
  27. package/dist/index.d.mts +5 -33
  28. package/dist/index.d.mts.map +1 -1
  29. package/dist/index.mjs +13 -13
  30. package/dist/{layout-engine--drvrWjD.mjs → layout-engine-B6Cdz1yZ.mjs} +1 -1
  31. package/dist/{layout-engine-Dr3cY5U4.mjs → layout-engine-ClUgv6jB.mjs} +3 -3
  32. package/dist/{layout-engine-Dr3cY5U4.mjs.map → layout-engine-ClUgv6jB.mjs.map} +1 -1
  33. package/dist/{multi-progress-CcdqJFlf.mjs → multi-progress-Bq9Oi_WI.mjs} +3 -3
  34. package/dist/{multi-progress-CcdqJFlf.mjs.map → multi-progress-Bq9Oi_WI.mjs.map} +1 -1
  35. package/dist/{multi-progress-DQ-uUzLf.d.mts → multi-progress-DAQC7eap.d.mts} +2 -2
  36. package/dist/{multi-progress-DQ-uUzLf.d.mts.map → multi-progress-DAQC7eap.d.mts.map} +1 -1
  37. package/dist/{node-CP5WChgr.mjs → node-BeWlnCPY.mjs} +4 -4
  38. package/dist/node-BeWlnCPY.mjs.map +1 -0
  39. package/dist/{progress-bar-IrUjkLfU.mjs → progress-bar-CXE5Qfkd.mjs} +4 -4
  40. package/dist/progress-bar-CXE5Qfkd.mjs.map +1 -0
  41. package/dist/reconciler-Cwgm8hRR.mjs +8459 -0
  42. package/dist/reconciler-Cwgm8hRR.mjs.map +1 -0
  43. package/dist/{render-string-DVfgc8xr.mjs → render-string-Cbuf63Ya.mjs} +936 -136
  44. package/dist/render-string-Cbuf63Ya.mjs.map +1 -0
  45. package/dist/{render-string-BwLG7rIX.mjs → render-string-Tv-jqM16.mjs} +1 -1
  46. package/dist/runtime.d.mts +2 -2
  47. package/dist/runtime.mjs +3 -3
  48. package/dist/{spinner-BRkaJI0N.d.mts → spinner-CGo34vyR.d.mts} +2 -2
  49. package/dist/{spinner-BRkaJI0N.d.mts.map → spinner-CGo34vyR.d.mts.map} +1 -1
  50. package/dist/{spinner-BmldKx0M.mjs → spinner-CeOmcuw_.mjs} +3 -3
  51. package/dist/spinner-CeOmcuw_.mjs.map +1 -0
  52. package/dist/src-B5GjfG7g.mjs +4305 -0
  53. package/dist/src-B5GjfG7g.mjs.map +1 -0
  54. package/dist/{src-CJPXf3fC.mjs → src-C2uvC-r0.mjs} +7535 -6467
  55. package/dist/src-C2uvC-r0.mjs.map +1 -0
  56. package/dist/{src-D8kLrQBT.mjs → src-CChwjk0Z.mjs} +8 -86
  57. package/dist/src-CChwjk0Z.mjs.map +1 -0
  58. package/dist/{src-D_BS-as7.mjs → src-NCKb8kE5.mjs} +777 -776
  59. package/dist/src-NCKb8kE5.mjs.map +1 -0
  60. package/dist/theme.d.mts +2 -130
  61. package/dist/theme.mjs +3 -8
  62. package/dist/{types-B4A8Ebba.d.mts → types-BH_v3iMT.d.mts} +1 -1
  63. package/dist/{types-B4A8Ebba.d.mts.map → types-BH_v3iMT.d.mts.map} +1 -1
  64. package/dist/{types-e4dpfbSa.mjs → types-Bk2yw9Qj.mjs} +3 -3
  65. package/dist/types-Bk2yw9Qj.mjs.map +1 -0
  66. package/dist/ui/animation.d.mts +1 -1
  67. package/dist/ui/animation.mjs +1 -1
  68. package/dist/ui/ansi.d.mts +1 -1
  69. package/dist/ui/ansi.mjs +1 -1
  70. package/dist/ui/cli.d.mts +3 -3
  71. package/dist/ui/cli.mjs +5 -5
  72. package/dist/ui/display.d.mts +1 -1
  73. package/dist/ui/display.mjs.map +1 -1
  74. package/dist/ui/image.d.mts +1 -1
  75. package/dist/ui/image.mjs +1 -1
  76. package/dist/ui/input.d.mts +1 -1
  77. package/dist/ui/input.d.mts.map +1 -1
  78. package/dist/ui/input.mjs +2 -4
  79. package/dist/ui/input.mjs.map +1 -1
  80. package/dist/ui/progress.d.mts +3 -3
  81. package/dist/ui/progress.d.mts.map +1 -1
  82. package/dist/ui/progress.mjs +3 -3
  83. package/dist/ui/progress.mjs.map +1 -1
  84. package/dist/ui/react.d.mts +1 -1
  85. package/dist/ui/react.d.mts.map +1 -1
  86. package/dist/ui/react.mjs +2 -2
  87. package/dist/ui/react.mjs.map +1 -1
  88. package/dist/ui/utils.mjs +1 -1
  89. package/dist/ui/wrappers.d.mts +2 -2
  90. package/dist/ui/wrappers.mjs +1 -1
  91. package/dist/ui.d.mts +5 -5
  92. package/dist/ui.mjs +6 -6
  93. package/dist/{useLatest-6xqnGIU6.d.mts → useLatest-Bg2x4bfP.d.mts} +1 -1
  94. package/dist/{useLatest-6xqnGIU6.d.mts.map → useLatest-Bg2x4bfP.d.mts.map} +1 -1
  95. package/dist/{with-text-input-lUh9gYAG.d.mts → with-text-input-CRfoiFFG.d.mts} +3 -3
  96. package/dist/with-text-input-CRfoiFFG.d.mts.map +1 -0
  97. package/dist/{wrappers-JrEYTuKA.mjs → wrappers-UTADQkSY.mjs} +4 -4
  98. package/dist/wrappers-UTADQkSY.mjs.map +1 -0
  99. package/dist/{yoga-adapter-Bc8XT9cN.mjs → yoga-adapter-8oRGRw8V.mjs} +2 -2
  100. package/dist/{yoga-adapter-Bc8XT9cN.mjs.map → yoga-adapter-8oRGRw8V.mjs.map} +1 -1
  101. package/dist/yoga-adapter-D_CcxSt5.mjs +2 -0
  102. package/package.json +54 -45
  103. package/dist/UPNG-DvKjM6wE.mjs +0 -5076
  104. package/dist/UPNG-DvKjM6wE.mjs.map +0 -1
  105. package/dist/__vite-browser-external-2447137e-DPKHHqQK.mjs +0 -6
  106. package/dist/__vite-browser-external-2447137e-DPKHHqQK.mjs.map +0 -1
  107. package/dist/ansi-C6Qs1Wn2.mjs.map +0 -1
  108. package/dist/apng-CvSlLBtc.mjs +0 -3
  109. package/dist/apng-DFFVOItr.mjs +0 -70
  110. package/dist/apng-DFFVOItr.mjs.map +0 -1
  111. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  112. package/dist/backend-DU0Y938U.mjs +0 -13396
  113. package/dist/backend-DU0Y938U.mjs.map +0 -1
  114. package/dist/backends-BihMKFY_.mjs +0 -1181
  115. package/dist/backends-BihMKFY_.mjs.map +0 -1
  116. package/dist/backends-Dk_5G_gC.mjs +0 -3
  117. package/dist/cli-GwJ0S2In.mjs +0 -4
  118. package/dist/context-BjWgrikx.mjs.map +0 -1
  119. package/dist/derive-O_Kb1Bk_.d.mts +0 -28
  120. package/dist/derive-O_Kb1Bk_.d.mts.map +0 -1
  121. package/dist/devtools-CeO9X_uv.mjs.map +0 -1
  122. package/dist/devtools-nX4tj6OH.mjs +0 -2
  123. package/dist/flexily-zero-adapter-BOM0cl8R.mjs.map +0 -1
  124. package/dist/gif-B9Uq4qZA.mjs +0 -73
  125. package/dist/gif-B9Uq4qZA.mjs.map +0 -1
  126. package/dist/gif-BdrLRBmM.mjs +0 -3
  127. package/dist/gifenc-DfhOb4xr.mjs +0 -730
  128. package/dist/gifenc-DfhOb4xr.mjs.map +0 -1
  129. package/dist/image-B0zMbVUr.mjs.map +0 -1
  130. package/dist/index-Bh3U1K09.d.mts.map +0 -1
  131. package/dist/index-dehZ18K-.d.mts +0 -679
  132. package/dist/index-dehZ18K-.d.mts.map +0 -1
  133. package/dist/key-mapping-7k2ufK2b.mjs +0 -3
  134. package/dist/key-mapping-WLUmxjx1.mjs +0 -132
  135. package/dist/key-mapping-WLUmxjx1.mjs.map +0 -1
  136. package/dist/node-CP5WChgr.mjs.map +0 -1
  137. package/dist/progress-bar-IrUjkLfU.mjs.map +0 -1
  138. package/dist/reconciler-B8uxQxaU.mjs +0 -16482
  139. package/dist/reconciler-B8uxQxaU.mjs.map +0 -1
  140. package/dist/render-string-DVfgc8xr.mjs.map +0 -1
  141. package/dist/resvg-js-Cwipz-_J.mjs +0 -203
  142. package/dist/resvg-js-Cwipz-_J.mjs.map +0 -1
  143. package/dist/spinner-BmldKx0M.mjs.map +0 -1
  144. package/dist/src-C0sOQW-t.mjs +0 -3866
  145. package/dist/src-C0sOQW-t.mjs.map +0 -1
  146. package/dist/src-CJPXf3fC.mjs.map +0 -1
  147. package/dist/src-D8kLrQBT.mjs.map +0 -1
  148. package/dist/src-D_BS-as7.mjs.map +0 -1
  149. package/dist/theme.d.mts.map +0 -1
  150. package/dist/theme.mjs.map +0 -1
  151. package/dist/types-e4dpfbSa.mjs.map +0 -1
  152. package/dist/with-text-input-lUh9gYAG.d.mts.map +0 -1
  153. package/dist/wrapper-CE6GQ27z.mjs +0 -3527
  154. package/dist/wrapper-CE6GQ27z.mjs.map +0 -1
  155. package/dist/wrappers-JrEYTuKA.mjs.map +0 -1
  156. package/dist/yoga-adapter-B8LZpQcE.mjs +0 -2
@@ -301,4 +301,4 @@ function useLatest(value) {
301
301
  //#endregion
302
302
  export { useAnimation as a, useTransition as i, useTimeout as n, easings as o, useInterval as r, resolveEasing as s, useLatest as t };
303
303
 
304
- //# sourceMappingURL=animation-DhINOJk8.mjs.map
304
+ //# sourceMappingURL=animation-Cn64yepo.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"animation-DhINOJk8.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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"}
1
+ {"version":3,"file":"animation-Cn64yepo.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(\n callback: () => void,\n ms: number,\n enabled = true,\n): { 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":";;AAkBA,MAAa,UAAU;CACrB,SAAS,MAAc;CACvB,OAAO,MAAe,IAAI,KAAM,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK;CAC/D,SAAS,MAAc,IAAI;CAC3B,UAAU,MAAc,KAAK,IAAI;CACjC,YAAY,MAAe,IAAI,KAAM,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK;CACpE,cAAc,MAAc,IAAI,IAAI;CACpC,eAAe,MAAc,EAAE,IAAI,IAAI,IAAI;CAC5C;;AASD,SAAgB,cAAc,QAAyC;AACrE,QAAO,OAAO,WAAW,aAAa,SAAS,QAAQ;;;;;;;;;;;;ACMzD,MAAMA,YAAU;;;;;;;;;;;;AAiBhB,SAAgB,aAAa,SAAkD;CAC7E,MAAM,EAAE,UAAU,SAAS,UAAU,QAAQ,GAAG,YAAY,UAAU,SAAS;CAE/E,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CACrC,MAAM,CAAC,aAAa,kBAAkB,SAAS,MAAM;CAErD,MAAM,eAAe,OAAO,EAAE;CAC9B,MAAM,cAAc,OAA8C,KAAK;CACvE,MAAM,gBAAgB,OAAO,WAAW;AACxC,eAAc,UAAU;CAGxB,MAAM,WAAW,OAAO,EAAE;CAE1B,MAAM,WAAW,cAAc,OAAO;CAEtC,MAAM,eAAe,kBAAkB;AACrC,MAAI,YAAY,YAAY,MAAM;AAChC,iBAAc,YAAY,QAAQ;AAClC,eAAY,UAAU;;IAEvB,EAAE,CAAC;CAEN,MAAM,iBAAiB,kBAAkB;AACvC,gBAAc;AACd,WAAS;EACT,MAAM,QAAQ,SAAS;AAEvB,WAAS,EAAE;AACX,iBAAe,KAAK;EAEpB,MAAM,cAAc;AAElB,OAAI,SAAS,YAAY,MAAO;AAEhC,gBAAa,UAAU,YAAY,KAAK;AAExC,eAAY,UAAU,kBAAkB;AAEtC,QAAI,SAAS,YAAY,MAAO;IAEhC,MAAM,UAAU,YAAY,KAAK,GAAG,aAAa;IACjD,MAAM,MAAM,KAAK,IAAI,UAAU,UAAU,EAAE;AAG3C,aAFc,SAAS,IAAI,CAEZ;AAEf,QAAI,OAAO,GAAG;AACZ,mBAAc;AACd,oBAAe,MAAM;AACrB,mBAAc,WAAW;;MAE1BA,UAAQ;;AAGb,MAAI,QAAQ,EACV,kBAAiB,OAAO,EAAE,MAAM;MAEhC,QAAO;IAER;EAAC;EAAU;EAAO;EAAU;EAAa,CAAC;AAG7C,iBAAgB;AACd,MAAI,CAAC,SAAS;AACZ,iBAAc;AACd,YAAS,EAAE;AACX,kBAAe,MAAM;AACrB;;AAGF,kBAAgB;AAEhB,eAAa;AACX,iBAAc;;IAEf;EAAC;EAAS;EAAgB;EAAa,CAAC;AAM3C,QAAO;EAAE;EAAO;EAAa,OAJf,kBAAkB;AAC9B,mBAAgB;KACf,CAAC,eAAe,CAAC;EAEgB;;;;;;;;;;;;AClHtC,MAAM,UAAU;;;;;;;;;;;;;;;;AAqBhB,SAAgB,cAAc,aAAqB,SAAwC;CACzF,MAAM,EAAE,WAAW,KAAK,SAAS,cAAc,WAAW,EAAE;CAE5D,MAAM,CAAC,cAAc,mBAAmB,SAAS,YAAY;CAE7D,MAAM,UAAU,OAAO,YAAY;CACnC,MAAM,QAAQ,OAAO,YAAY;CACjC,MAAM,eAAe,OAAO,EAAE;CAC9B,MAAM,cAAc,OAA8C,KAAK;CACvE,MAAM,aAAa,OAAO,KAAK;CAE/B,MAAM,WAAW,cAAc,OAAO;AAEtC,iBAAgB;AAEd,MAAI,WAAW,SAAS;AACtB,cAAW,UAAU;AACrB;;AAIF,MAAI,gBAAgB,MAAM,QAAS;AAGnC,UAAQ,UAAU;AAClB,QAAM,UAAU;AAChB,eAAa,UAAU,YAAY,KAAK;AAGxC,MAAI,YAAY,YAAY,KAC1B,eAAc,YAAY,QAAQ;AAGpC,cAAY,UAAU,kBAAkB;GACtC,MAAM,UAAU,YAAY,KAAK,GAAG,aAAa;GACjD,MAAM,MAAM,KAAK,IAAI,UAAU,UAAU,EAAE;GAC3C,MAAM,QAAQ,SAAS,IAAI;AAG3B,mBAFqB,QAAQ,WAAW,MAAM,UAAU,QAAQ,WAAW,MAE9C;AAE7B,OAAI,OAAO,GAAG;AAEZ,oBAAgB,MAAM,QAAQ;AAC9B,QAAI,YAAY,YAAY,MAAM;AAChC,mBAAc,YAAY,QAAQ;AAClC,iBAAY,UAAU;;;KAGzB,QAAQ;AAEX,eAAa;AACX,OAAI,YAAY,YAAY,MAAM;AAChC,kBAAc,YAAY,QAAQ;AAClC,gBAAY,UAAU;;;IAIzB;EAAC;EAAa;EAAU;EAAS,CAAC;AAErC,QAAO;;;;;;;;;;;;;;;;;;;;ACrFT,SAAgB,YAAY,UAAsB,IAAY,UAAU,MAAY;CAClF,MAAM,cAAc,OAAO,SAAS;AACpC,aAAY,UAAU;AAEtB,iBAAgB;AACd,MAAI,CAAC,QAAS;EAEd,MAAM,KAAK,kBAAkB;AAC3B,eAAY,SAAS;KACpB,GAAG;AAEN,eAAa;AACX,iBAAc,GAAG;;IAElB,CAAC,IAAI,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;ACXnB,SAAgB,WACd,UACA,IACA,UAAU,MACgC;CAC1C,MAAM,cAAc,OAAO,SAAS;AACpC,aAAY,UAAU;CAEtB,MAAM,WAAW,OAA6C,KAAK;CAEnE,MAAM,QAAQ,kBAAkB;AAC9B,MAAI,SAAS,YAAY,MAAM;AAC7B,gBAAa,SAAS,QAAQ;AAC9B,YAAS,UAAU;;IAEpB,EAAE,CAAC;CAEN,MAAM,QAAQ,kBAAkB;AAC9B,SAAO;AACP,MAAI,QACF,UAAS,UAAU,iBAAiB;AAClC,YAAS,UAAU;AACnB,eAAY,SAAS;KACpB,GAAG;IAEP;EAAC;EAAI;EAAS;EAAM,CAAC;AAExB,iBAAgB;AACd,MAAI,CAAC,SAAS;AACZ,UAAO;AACP;;AAGF,WAAS,UAAU,iBAAiB;AAClC,YAAS,UAAU;AACnB,eAAY,SAAS;KACpB,GAAG;AAEN,SAAO;IACN;EAAC;EAAI;EAAS;EAAM,CAAC;AAExB,QAAO;EAAE;EAAO;EAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrCzB,SAAgB,UAAa,OAAmC;CAC9D,MAAM,MAAM,OAAO,MAAM;AACzB,KAAI,UAAU;AACd,QAAO"}
@@ -68,4 +68,4 @@ function getTerminalWidth(stream = process.stdout) {
68
68
  //#endregion
69
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
70
 
71
- //# sourceMappingURL=ansi-C6Qs1Wn2.mjs.map
71
+ //# sourceMappingURL=ansi-CLOitHKx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi-CLOitHKx.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>(\n fn: () => T | Promise<T>,\n stream: NodeJS.WriteStream = process.stdout,\n): 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,WACd,IACA,SAA6B,QAAQ,QACzB;AACZ,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"}
@@ -46,4 +46,4 @@ declare function isTTY(stream?: NodeJS.WriteStream): boolean;
46
46
  declare function getTerminalWidth(stream?: NodeJS.WriteStream): number;
47
47
  //#endregion
48
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-CsjnZtAw.d.mts.map
49
+ //# sourceMappingURL=ansi-Cc33mW54.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ansi-CsjnZtAw.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"}
1
+ {"version":3,"file":"ansi-Cc33mW54.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,CACd,EAAA,QAAU,CAAA,GAAI,OAAA,CAAQ,CAAA,GACtB,MAAA,GAAQ,MAAA,CAAO,WAAA,GACd,OAAA,CAAQ,CAAA;AA7BX;;;;AAAA,iBAmDgB,KAAA,CAAM,MAAA,GAAQ,MAAA,CAAO,WAAA;AAhDrC;;;AAAA,iBAwDgB,gBAAA,CAAiB,MAAA,GAAQ,MAAA,CAAO,WAAA"}
@@ -7,7 +7,7 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
9
  var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
10
- var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
10
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
11
11
  var __exportAll = (all, no_symbols) => {
12
12
  let target = {};
13
13
  for (var name in all) __defProp(target, name, {
@@ -0,0 +1,4 @@
1
+ import "./spinner-CeOmcuw_.mjs";
2
+ import "./progress-bar-CXE5Qfkd.mjs";
3
+ import "./multi-progress-Bq9Oi_WI.mjs";
4
+ export {};
@@ -24,15 +24,16 @@ const StdoutContext = createContext(null);
24
24
  */
25
25
  const StderrContext = createContext(null);
26
26
  /**
27
- * Context that provides the typed runtime event bus.
27
+ * Context that provides the trimmed runtime handle.
28
28
  *
29
- * When non-null: interactive mode — useInput works, components can subscribe
30
- * to events via rt.on() and emit via rt.emit().
29
+ * When non-null: interactive mode — `useExit()` works. Input / paste /
30
+ * focus subscriptions use `ChainAppContext`.
31
31
  *
32
- * When null: static mode — useInput throws (by design), use useRuntime()
33
- * for components that need to work in both modes.
32
+ * When null: static mode — `useExit()` throws. Hooks subscribe through
33
+ * `ChainAppContext` when present, otherwise no-op.
34
34
  */
35
35
  const RuntimeContext = createContext(null);
36
+ const ChainAppContext = createContext(null);
36
37
  /**
37
38
  * Context that provides the cache backend to ListView.
38
39
  * Set by the runtime based on rendering mode:
@@ -59,6 +60,6 @@ const FocusManagerContext = createContext(null);
59
60
  */
60
61
  const CapabilityRegistryContext = createContext(null);
61
62
  //#endregion
62
- export { RuntimeContext as a, TermContext as c, NodeContext as i, CapabilityRegistryContext as n, StderrContext as o, FocusManagerContext as r, StdoutContext as s, CacheBackendContext as t };
63
+ export { NodeContext as a, StdoutContext as c, FocusManagerContext as i, TermContext as l, CapabilityRegistryContext as n, RuntimeContext as o, ChainAppContext as r, StderrContext as s, CacheBackendContext as t };
63
64
 
64
- //# sourceMappingURL=context-BjWgrikx.mjs.map
65
+ //# sourceMappingURL=context-BU5LkkIy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-BU5LkkIy.mjs","names":[],"sources":["../packages/ag-react/src/context.ts"],"sourcesContent":["/**\n * Silvery React Contexts\n *\n * Provides contexts for:\n * - TermContext: Access to Term instance (for styling/detection)\n * - NodeContext: Access to the current SilveryNode (for useBoxRect)\n * - RuntimeContext: Unified input/app controls (replaces Events/Input/Stdin/App contexts)\n * - StdoutContext: Access to stdout\n * - StderrContext: Access to stderr\n */\n\nimport type { Term } from \"@silvery/ag-term/ansi\"\nimport { createContext } from \"react\"\nimport type { FocusManager } from \"@silvery/ag/focus-manager\"\nimport type { Key } from \"@silvery/ag/keys\"\nimport type { AgNode } from \"@silvery/ag/types\"\n\n// ============================================================================\n// Term Context\n// ============================================================================\n\n/**\n * Context that provides access to the Term instance.\n * Used by useTerm() hook to access terminal capabilities and styling.\n */\nexport const TermContext = createContext<Term | null>(null)\n\n// ============================================================================\n// Node Context\n// ============================================================================\n\n/**\n * Context that provides access to the current SilveryNode.\n * Used by useBoxRect() to subscribe to layout changes.\n *\n * Each Box component wraps its children in a NodeContext.Provider\n * with its corresponding SilveryNode.\n */\nexport const NodeContext = createContext<AgNode | null>(null)\n\n// ============================================================================\n// Stdio Context\n// ============================================================================\n\nexport interface StdoutContextValue {\n /** Standard output stream */\n stdout: NodeJS.WriteStream\n /** Write to stdout */\n write: (data: string) => void\n /**\n * Notify the scheduler that lines were written to stdout externally.\n * Used by useScrollback to report lines written between renders so that\n * inline mode cursor positioning accounts for the displacement.\n */\n notifyScrollback?: (lines: number) => void\n /**\n * Reset inline cursor state in the output phase.\n * Used by useScrollback on resize to clear cursor tracking before\n * re-emitting frozen items at the new width.\n */\n resetInlineCursor?: () => void\n /**\n * Get inline cursor row relative to render region start. -1 if unknown.\n * Used by useScrollback to position frozen items at the render region start.\n */\n getInlineCursorRow?: () => number\n /**\n * Promote frozen content to scrollback via the output phase.\n * Instead of writing directly to stdout (which causes flicker),\n * this passes the content to the output phase which writes frozen content\n * + live content in a single target.write() — no blanking, no cursor desync.\n */\n promoteScrollback?: (frozenContent: string, frozenLineCount: number) => void\n}\n\n/**\n * Context for stdout access.\n * Used by useStdout() hook.\n */\nexport const StdoutContext = createContext<StdoutContextValue | null>(null)\n\nexport interface StderrContextValue {\n /** Standard error stream */\n stderr: NodeJS.WriteStream\n /** Write to stderr */\n write: (data: string) => void\n}\n\n/**\n * Context for stderr access.\n * Used by useStderr() hook.\n */\nexport const StderrContext = createContext<StderrContextValue | null>(null)\n\n// ============================================================================\n// Runtime Context (typed bidirectional event bus — TEA)\n// ============================================================================\n\n/**\n * Base events every runtime provides.\n *\n * Retained for backwards compatibility (legacy `useRuntime<E>()` generic\n * slot). The canonical subscription surface is {@link ChainAppContextValue}\n * — input / paste / focus flow through the apply-chain plugin stores and\n * app-defined events ride on {@link ChainCustomEvents}.\n */\nexport interface BaseRuntimeEvents {\n /** Keyboard input: [parsedInput, keyMetadata] */\n input: [input: string, key: Key]\n /** Bracketed paste: [pastedText] */\n paste: [text: string]\n /** Terminal window focus change: [isFocused] */\n focus: [focused: boolean]\n}\n\n/**\n * Minimal runtime handle — the trimmed RuntimeContextValue exposes only\n * app-lifecycle controls (`exit`, and the opt-in pause / resume pair\n * used by console-mode suspension). Input / paste / focus subscriptions\n * live on {@link ChainAppContextValue}; custom view ↔ runtime events\n * live on {@link ChainCustomEvents} (`chain.events.emit / on`).\n *\n * The generic parameter is retained for source compatibility with\n * callers of `useRuntime<LinkEvents>()`; it has no effect on the type\n * surface below.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport interface RuntimeContextValue<_E extends BaseRuntimeEvents = BaseRuntimeEvents> {\n /** Exit the application with optional error. */\n exit: (error?: Error) => void\n /** Pause rendering output (used by console suspend). */\n pause?: () => void\n /** Resume rendering after a pause. Forces a full redraw. */\n resume?: () => void\n}\n\n/**\n * Context that provides the trimmed runtime handle.\n *\n * When non-null: interactive mode — `useExit()` works. Input / paste /\n * focus subscriptions use `ChainAppContext`.\n *\n * When null: static mode — `useExit()` throws. Hooks subscribe through\n * `ChainAppContext` when present, otherwise no-op.\n */\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n// ============================================================================\n// Chain App Context (TEA Phase 2 — apply-chain plugin stores)\n// ============================================================================\n\n/**\n * Minimal key shape forwarded to chain handlers. Kept structural (not\n * imported from @silvery/ag/keys) so this context stays dependency-free;\n * consumers narrow to `Key` at the call site.\n */\nexport interface ChainKey {\n ctrl?: boolean\n shift?: boolean\n meta?: boolean\n super?: boolean\n hyper?: boolean\n alt?: boolean\n eventType?: \"press\" | \"repeat\" | \"release\" | undefined\n}\n\n/** Handler registered with the fallback useInput store. */\nexport type ChainInputHandler = (input: string, key: ChainKey) => void | \"exit\"\n\n/** Handler registered with the paste store. */\nexport type ChainPasteHandler = (text: string) => void\n\n/** Handler registered with the terminal focus store. */\nexport type ChainFocusHandler = (focused: boolean) => void\n\n/** Raw-key observer handler — fires for every input:key op (press/repeat/release/modifier-only). */\nexport type ChainRawKeyHandler = (input: string, key: ChainKey) => void\n\n/** Handler registered with the custom-events store — payload is app-defined. */\nexport type ChainCustomEventHandler = (...args: unknown[]) => void\n\n/** Input-fallback store slice exposed by withInputChain. */\nexport interface ChainInputStore {\n register(handler: ChainInputHandler, active?: boolean): () => void\n setActive(handler: ChainInputHandler, active: boolean): void\n}\n\n/** Raw-key observer slice — sees every key event before focus/useInput filters. */\nexport interface ChainRawKeyObserver {\n register(handler: ChainRawKeyHandler): () => void\n}\n\n/** Paste store slice exposed by withPasteChain. */\nexport interface ChainPasteStore {\n register(handler: ChainPasteHandler): () => void\n}\n\n/** Window focus slice exposed alongside the chain for createApp. */\nexport interface ChainFocusEvents {\n register(handler: ChainFocusHandler): () => void\n}\n\n/**\n * Custom-events slice — app-defined view ↔ runtime events (e.g.\n * `link:open` fired by `<Link>` and consumed by km-tui's\n * `useLinkOpen`). Channels are arbitrary strings chosen by the app;\n * payloads are untyped at the bus layer.\n */\nexport interface ChainCustomEvents {\n on(channel: string, handler: ChainCustomEventHandler): () => void\n emit(channel: string, ...args: unknown[]): void\n}\n\n/**\n * Context that exposes the apply-chain plugin stores.\n *\n * Provided by `createApp()` (and `run()` eventually) when an apply-chain\n * runtime is present. Hooks prefer this context; they fall back to\n * {@link RuntimeContext} when the chain is absent (e.g. children inside\n * an `InputBoundary`, which provides its own isolated RuntimeContext but\n * no chain).\n */\nexport interface ChainAppContextValue {\n readonly input: ChainInputStore\n readonly paste: ChainPasteStore\n readonly focusEvents: ChainFocusEvents\n /**\n * Raw-key observer — sees every `input:key` op (press/repeat/release/\n * modifier-only), unfiltered by focus or useInput. Used by hooks like\n * `useModifierKeys` that need to track sub-press state regardless of\n * whether a focused element consumed the key.\n */\n readonly rawKeys: ChainRawKeyObserver\n /**\n * Custom event bus — replaces the legacy `RuntimeContextValue.on /\n * emit` surface for app-defined channels. Consumers subscribe via\n * `events.on(\"channel\", handler)` and producers fire via\n * `events.emit(\"channel\", …payload)`.\n */\n readonly events: ChainCustomEvents\n}\n\nexport const ChainAppContext = createContext<ChainAppContextValue | null>(null)\n\n// ============================================================================\n// Cache Backend Context (mode-agnostic cache selection)\n// ============================================================================\n\n/**\n * Cache backend type — determines where ListView stores cached items.\n * - \"terminal\": Write to stdout as native scrollback (inline mode)\n * - \"virtual\": In-memory HistoryBuffer ring buffer (fullscreen + virtualInline)\n * - \"retain\": Cache items but keep them in the render tree (plain fullscreen\n * without virtual scrollback — the virtualizer handles windowing)\n */\nexport type CacheBackend = \"terminal\" | \"virtual\" | \"retain\"\n\n/**\n * Context that provides the cache backend to ListView.\n * Set by the runtime based on rendering mode:\n * - alternateScreen: false (inline) → \"terminal\"\n * - alternateScreen: true + virtualInline → \"virtual\"\n * - alternateScreen: true (plain fullscreen) → \"retain\"\n *\n * Default: \"virtual\" (safe fallback for test renderers — items unmount as expected)\n */\nexport const CacheBackendContext = createContext<CacheBackend>(\"virtual\")\n\n// ============================================================================\n// Focus Manager Context (tree-based focus system)\n// ============================================================================\n\n/**\n * Context for the tree-based focus manager.\n * Provides the FocusManager instance to useFocusable(), useFocusWithin(), and useFocusManager() hooks.\n */\nexport const FocusManagerContext = createContext<FocusManager | null>(null)\n\n// ============================================================================\n// Capability Registry Context\n// ============================================================================\n\n/**\n * Minimal capability lookup interface — matches CapabilityRegistry.get().\n * Defined here to avoid a dependency from ag-react → @silvery/create internals.\n */\nexport interface CapabilityLookup {\n get<T>(key: symbol): T | undefined\n}\n\n/**\n * Context for the capability registry (from @silvery/create composition).\n *\n * Provided by createApp() when a capabilityRegistry exists on the app object.\n * Hooks like useSelection() use this to discover interaction features\n * (e.g., SelectionFeature) without coupling to the composition layer.\n *\n * Returns null in simple `run()` or `render()` apps that don't use pipe() composition.\n */\nexport const CapabilityRegistryContext = createContext<CapabilityLookup | null>(null)\n"],"mappings":";;;;;;AAyBA,MAAa,cAAc,cAA2B,KAAK;;;;;;;;AAa3D,MAAa,cAAc,cAA6B,KAAK;;;;;AAyC7D,MAAa,gBAAgB,cAAyC,KAAK;;;;;AAa3E,MAAa,gBAAgB,cAAyC,KAAK;;;;;;;;;;AAqD3E,MAAa,iBAAiB,cAA0C,KAAK;AAiG7E,MAAa,kBAAkB,cAA2C,KAAK;;;;;;;;;;AAwB/E,MAAa,sBAAsB,cAA4B,UAAU;;;;;AAUzE,MAAa,sBAAsB,cAAmC,KAAK;;;;;;;;;;AAuB3E,MAAa,4BAA4B,cAAuC,KAAK"}
@@ -0,0 +1,2 @@
1
+ import { t as autoConnectDevTools } from "./devtools-DxkSLXDA.mjs";
2
+ export { autoConnectDevTools };
@@ -1,5 +1,4 @@
1
- import { o as __toESM } from "./chunk-BSw8zbkd.mjs";
2
- import { i as reconciler } from "./reconciler-B8uxQxaU.mjs";
1
+ import { i as reconciler } from "./reconciler-Cwgm8hRR.mjs";
3
2
  import { createLogger } from "loggily";
4
3
  //#region packages/ag-term/src/devtools.ts
5
4
  /**
@@ -40,7 +39,7 @@ async function connectDevTools() {
40
39
  if (connected) return true;
41
40
  try {
42
41
  if (typeof globalThis.WebSocket === "undefined") try {
43
- const ws = await import("./wrapper-CE6GQ27z.mjs");
42
+ const ws = await import("ws");
44
43
  globalThis.WebSocket = ws.default ?? ws;
45
44
  } catch {
46
45
  log.warn?.("WebSocket polyfill (ws) not available. Install ws for DevTools support: bun add -d ws");
@@ -57,7 +56,7 @@ async function connectDevTools() {
57
56
  isEnabled: true,
58
57
  isValid: true
59
58
  }];
60
- const devtools = await import("./backend-DU0Y938U.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
59
+ const devtools = await import("react-devtools-core");
61
60
  devtools.initialize();
62
61
  devtools.connectToDevTools();
63
62
  reconciler.injectIntoDevTools();
@@ -86,4 +85,4 @@ async function autoConnectDevTools() {
86
85
  //#endregion
87
86
  export { connectDevTools as n, isDevToolsConnected as r, autoConnectDevTools as t };
88
87
 
89
- //# sourceMappingURL=devtools-CeO9X_uv.mjs.map
88
+ //# sourceMappingURL=devtools-DxkSLXDA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools-DxkSLXDA.mjs","names":[],"sources":["../packages/ag-term/src/devtools.ts"],"sourcesContent":["/**\n * React DevTools integration for silvery.\n *\n * Provides optional connection to React DevTools standalone app for\n * debugging TUI component trees. Requires `react-devtools-core` to be\n * installed (optional peer dependency).\n *\n * Usage:\n * 1. Install: `bun add -d react-devtools-core`\n * 2. Run devtools: `npx react-devtools`\n * 3. Launch app with: `DEBUG_DEVTOOLS=1 bun run app.ts`\n *\n * Or call `connectDevTools()` manually from your app code.\n *\n * @module\n */\n\nimport { reconciler } from \"@silvery/ag-react/reconciler\"\nimport { createLogger } from \"loggily\"\n\nconst log = createLogger(\"silvery:devtools\")\n\nlet connected = false\n\n/**\n * Connect to React DevTools standalone app.\n *\n * This lazy-loads `react-devtools-core` so it has zero impact on\n * production bundles. The connection is established via WebSocket\n * to the devtools electron app (default: ws://localhost:8097).\n *\n * Safe to call multiple times -- subsequent calls are no-ops.\n *\n * @example\n * ```ts\n * import { connectDevTools } from '@silvery/ag-react';\n * await connectDevTools();\n * // Now open React DevTools standalone to inspect the component tree\n * ```\n */\nexport async function connectDevTools(): Promise<boolean> {\n if (connected) return true\n\n try {\n // Polyfill WebSocket for Node.js environments (required by react-devtools-core)\n if (typeof globalThis.WebSocket === \"undefined\") {\n try {\n // @ts-expect-error -- ws is an optional peer dependency\n const ws = await import(\"ws\")\n globalThis.WebSocket = ws.default ?? ws\n } catch {\n // ws not available -- devtools won't be able to connect\n log.warn?.(\n \"WebSocket polyfill (ws) not available. \" +\n \"Install ws for DevTools support: bun add -d ws\",\n )\n return false\n }\n }\n\n // Ensure window/self exist for react-devtools-core internals\n if (typeof globalThis.window === \"undefined\") {\n // @ts-expect-error -- polyfill for devtools\n globalThis.window = globalThis\n }\n\n // Configure component filters to hide silvery internals from the DevTools tree.\n // Filter types from react-devtools-shared/src/types.js:\n // 1 = ComponentFilterElementType, value 7 = HostComponent\n // 2 = ComponentFilterDisplayName (regex on displayName)\n if (!globalThis.__REACT_DEVTOOLS_COMPONENT_FILTERS__) {\n globalThis.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = [\n { type: 1, value: 7, isEnabled: true },\n { type: 2, value: \"SilveryApp\", isEnabled: true, isValid: true },\n ]\n }\n\n // @ts-expect-error -- react-devtools-core has no type declarations\n const devtools = await import(\"react-devtools-core\")\n devtools.initialize()\n devtools.connectToDevTools()\n\n // Inject renderer info so DevTools can identify silvery.\n // rendererPackageName and rendererVersion are read from the host config\n // passed to Reconciler() -- see reconciler/host-config.ts.\n reconciler.injectIntoDevTools()\n\n connected = true\n return true\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n log.warn?.(\n `Failed to connect to React DevTools. ` +\n `Install react-devtools-core: bun add -d react-devtools-core\\n` +\n ` Error: ${message}`,\n )\n return false\n }\n}\n\n/**\n * Check if DevTools are currently connected.\n */\nexport function isDevToolsConnected(): boolean {\n return connected\n}\n\n/**\n * Auto-connect to DevTools if DEBUG_DEVTOOLS=1 environment variable is set.\n * Called internally during render initialization.\n */\nexport async function autoConnectDevTools(): Promise<void> {\n if (process.env.DEBUG_DEVTOOLS === \"1\" || process.env.DEBUG_DEVTOOLS === \"true\") {\n await connectDevTools()\n }\n}\n\n// Global type augmentation for devtools polyfills\ndeclare global {\n var __REACT_DEVTOOLS_COMPONENT_FILTERS__: Array<{\n type: number\n value: number | string\n isEnabled: boolean\n isValid?: boolean\n }>\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoBA,MAAM,MAAM,aAAa,mBAAmB;AAE5C,IAAI,YAAY;;;;;;;;;;;;;;;;;AAkBhB,eAAsB,kBAAoC;AACxD,KAAI,UAAW,QAAO;AAEtB,KAAI;AAEF,MAAI,OAAO,WAAW,cAAc,YAClC,KAAI;GAEF,MAAM,KAAK,MAAM,OAAO;AACxB,cAAW,YAAY,GAAG,WAAW;UAC/B;AAEN,OAAI,OACF,wFAED;AACD,UAAO;;AAKX,MAAI,OAAO,WAAW,WAAW,YAE/B,YAAW,SAAS;AAOtB,MAAI,CAAC,WAAW,qCACd,YAAW,uCAAuC,CAChD;GAAE,MAAM;GAAG,OAAO;GAAG,WAAW;GAAM,EACtC;GAAE,MAAM;GAAG,OAAO;GAAc,WAAW;GAAM,SAAS;GAAM,CACjE;EAIH,MAAM,WAAW,MAAM,OAAO;AAC9B,WAAS,YAAY;AACrB,WAAS,mBAAmB;AAK5B,aAAW,oBAAoB;AAE/B,cAAY;AACZ,SAAO;UACA,OAAgB;EACvB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,MAAI,OACF;WAEc,UACf;AACD,SAAO;;;;;;AAOX,SAAgB,sBAA+B;AAC7C,QAAO;;;;;;AAOT,eAAsB,sBAAqC;AACzD,KAAI,QAAQ,IAAI,mBAAmB,OAAO,QAAQ,IAAI,mBAAmB,OACvE,OAAM,iBAAiB"}
@@ -107,4 +107,4 @@ function createETATracker(bufferSize = 10) {
107
107
  //#endregion
108
108
  export { getETA as a, formatETA as i, calculateETA as n, createETATracker as r, DEFAULT_ETA_BUFFER_SIZE as t };
109
109
 
110
- //# sourceMappingURL=eta-BnQSZcWf.mjs.map
110
+ //# sourceMappingURL=eta-Bb3RH3wh.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"eta-BnQSZcWf.mjs","names":[],"sources":["../packages/ag-react/src/ui/utils/eta.ts"],"sourcesContent":["/**\n * Shared ETA calculation utilities\n */\n\n/** Sample point for ETA calculation */\nexport interface ETASample {\n time: number\n value: number\n}\n\n/** ETA calculation result */\nexport interface ETAResult {\n /** Estimated seconds remaining, or null if insufficient data */\n seconds: number | null\n /** Formatted ETA string (e.g., \"1:30\", \"2:15:30\", \"--:--\") */\n formatted: string\n}\n\n/**\n * Calculate ETA from a buffer of samples\n *\n * @param buffer - Array of {time, value} samples\n * @param current - Current progress value\n * @param total - Total target value\n * @returns ETA in seconds (null if insufficient data)\n *\n * @example\n * ```ts\n * const buffer = [\n * { time: 1000, value: 0 },\n * { time: 2000, value: 10 },\n * ];\n * const eta = calculateETA(buffer, 10, 100);\n * // eta = 9 (9 seconds remaining at 10 items/sec)\n * ```\n */\nexport function calculateETA(buffer: ETASample[], current: number, total: number): number | null {\n if (buffer.length < 2) {\n return null\n }\n\n const first = buffer[0]!\n const last = buffer[buffer.length - 1]!\n\n const elapsed = (last.time - first.time) / 1000 // seconds\n const progress = last.value - first.value\n\n if (elapsed <= 0 || progress <= 0) {\n return null\n }\n\n const rate = progress / elapsed // items per second\n const remaining = total - current\n\n return remaining / rate\n}\n\n/**\n * Format ETA seconds as human-readable string\n *\n * @param eta - ETA in seconds (null for unknown)\n * @returns Formatted string (e.g., \"1:30\", \"2:15:30\", \"--:--\", \">1d\")\n *\n * @example\n * ```ts\n * formatETA(90) // \"1:30\"\n * formatETA(3665) // \"1:01:05\"\n * formatETA(null) // \"--:--\"\n * formatETA(100000) // \">1d\"\n * ```\n */\nexport function formatETA(eta: number | null): string {\n if (eta === null || !isFinite(eta)) {\n return \"--:--\"\n }\n\n if (eta > 86400) {\n // > 24 hours\n return \">1d\"\n }\n\n const hours = Math.floor(eta / 3600)\n const minutes = Math.floor((eta % 3600) / 60)\n const seconds = Math.floor(eta % 60)\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\n }\n\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`\n}\n\n/**\n * Calculate and format ETA in one call\n *\n * @param buffer - Array of {time, value} samples\n * @param current - Current progress value\n * @param total - Total target value\n * @returns Object with seconds (number|null) and formatted string\n */\nexport function getETA(buffer: ETASample[], current: number, total: number): ETAResult {\n const seconds = calculateETA(buffer, current, total)\n return {\n seconds,\n formatted: formatETA(seconds),\n }\n}\n\n/** Default buffer size for ETA smoothing */\nexport const DEFAULT_ETA_BUFFER_SIZE = 10\n\n/**\n * Create an ETA tracker with automatic buffer management\n *\n * @param bufferSize - Number of samples to keep (default: 10)\n * @returns ETA tracker object\n *\n * @example\n * ```ts\n * const tracker = createETATracker();\n * tracker.record(0);\n * // ... later ...\n * tracker.record(50);\n * const eta = tracker.getETA(50, 100);\n * console.log(eta.formatted); // \"0:30\"\n * ```\n */\nexport function createETATracker(bufferSize = DEFAULT_ETA_BUFFER_SIZE) {\n const buffer: ETASample[] = []\n\n return {\n /** Record a new sample */\n record(value: number): void {\n buffer.push({ time: Date.now(), value })\n if (buffer.length > bufferSize) {\n buffer.shift()\n }\n },\n\n /** Get current ETA */\n getETA(current: number, total: number): ETAResult {\n return getETA(buffer, current, total)\n },\n\n /** Reset the buffer */\n reset(): void {\n buffer.length = 0\n },\n\n /** Get buffer for external use */\n getBuffer(): readonly ETASample[] {\n return buffer\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,aAAa,QAAqB,SAAiB,OAA8B;AAC/F,KAAI,OAAO,SAAS,EAClB,QAAO;CAGT,MAAM,QAAQ,OAAO;CACrB,MAAM,OAAO,OAAO,OAAO,SAAS;CAEpC,MAAM,WAAW,KAAK,OAAO,MAAM,QAAQ;CAC3C,MAAM,WAAW,KAAK,QAAQ,MAAM;AAEpC,KAAI,WAAW,KAAK,YAAY,EAC9B,QAAO;CAGT,MAAM,OAAO,WAAW;AAGxB,SAFkB,QAAQ,WAEP;;;;;;;;;;;;;;;;AAiBrB,SAAgB,UAAU,KAA4B;AACpD,KAAI,QAAQ,QAAQ,CAAC,SAAS,IAAI,CAChC,QAAO;AAGT,KAAI,MAAM,MAER,QAAO;CAGT,MAAM,QAAQ,KAAK,MAAM,MAAM,KAAK;CACpC,MAAM,UAAU,KAAK,MAAO,MAAM,OAAQ,GAAG;CAC7C,MAAM,UAAU,KAAK,MAAM,MAAM,GAAG;AAEpC,KAAI,QAAQ,EACV,QAAO,GAAG,MAAM,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI;AAG/F,QAAO,GAAG,QAAQ,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI;;;;;;;;;;AAW1D,SAAgB,OAAO,QAAqB,SAAiB,OAA0B;CACrF,MAAM,UAAU,aAAa,QAAQ,SAAS,MAAM;AACpD,QAAO;EACL;EACA,WAAW,UAAU,QAAQ;EAC9B;;;AAIH,MAAa,0BAA0B;;;;;;;;;;;;;;;;;AAkBvC,SAAgB,iBAAiB,aAAA,IAAsC;CACrE,MAAM,SAAsB,EAAE;AAE9B,QAAO;EAEL,OAAO,OAAqB;AAC1B,UAAO,KAAK;IAAE,MAAM,KAAK,KAAK;IAAE;IAAO,CAAC;AACxC,OAAI,OAAO,SAAS,WAClB,QAAO,OAAO;;EAKlB,OAAO,SAAiB,OAA0B;AAChD,UAAO,OAAO,QAAQ,SAAS,MAAM;;EAIvC,QAAc;AACZ,UAAO,SAAS;;EAIlB,YAAkC;AAChC,UAAO;;EAEV"}
1
+ {"version":3,"file":"eta-Bb3RH3wh.mjs","names":[],"sources":["../packages/ag-react/src/ui/utils/eta.ts"],"sourcesContent":["/**\n * Shared ETA calculation utilities\n */\n\n/** Sample point for ETA calculation */\nexport interface ETASample {\n time: number\n value: number\n}\n\n/** ETA calculation result */\nexport interface ETAResult {\n /** Estimated seconds remaining, or null if insufficient data */\n seconds: number | null\n /** Formatted ETA string (e.g., \"1:30\", \"2:15:30\", \"--:--\") */\n formatted: string\n}\n\n/**\n * Calculate ETA from a buffer of samples\n *\n * @param buffer - Array of {time, value} samples\n * @param current - Current progress value\n * @param total - Total target value\n * @returns ETA in seconds (null if insufficient data)\n *\n * @example\n * ```ts\n * const buffer = [\n * { time: 1000, value: 0 },\n * { time: 2000, value: 10 },\n * ];\n * const eta = calculateETA(buffer, 10, 100);\n * // eta = 9 (9 seconds remaining at 10 items/sec)\n * ```\n */\nexport function calculateETA(buffer: ETASample[], current: number, total: number): number | null {\n if (buffer.length < 2) {\n return null\n }\n\n const first = buffer[0]!\n const last = buffer[buffer.length - 1]!\n\n const elapsed = (last.time - first.time) / 1000 // seconds\n const progress = last.value - first.value\n\n if (elapsed <= 0 || progress <= 0) {\n return null\n }\n\n const rate = progress / elapsed // items per second\n const remaining = total - current\n\n return remaining / rate\n}\n\n/**\n * Format ETA seconds as human-readable string\n *\n * @param eta - ETA in seconds (null for unknown)\n * @returns Formatted string (e.g., \"1:30\", \"2:15:30\", \"--:--\", \">1d\")\n *\n * @example\n * ```ts\n * formatETA(90) // \"1:30\"\n * formatETA(3665) // \"1:01:05\"\n * formatETA(null) // \"--:--\"\n * formatETA(100000) // \">1d\"\n * ```\n */\nexport function formatETA(eta: number | null): string {\n if (eta === null || !isFinite(eta)) {\n return \"--:--\"\n }\n\n if (eta > 86400) {\n // > 24 hours\n return \">1d\"\n }\n\n const hours = Math.floor(eta / 3600)\n const minutes = Math.floor((eta % 3600) / 60)\n const seconds = Math.floor(eta % 60)\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\n }\n\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`\n}\n\n/**\n * Calculate and format ETA in one call\n *\n * @param buffer - Array of {time, value} samples\n * @param current - Current progress value\n * @param total - Total target value\n * @returns Object with seconds (number|null) and formatted string\n */\nexport function getETA(buffer: ETASample[], current: number, total: number): ETAResult {\n const seconds = calculateETA(buffer, current, total)\n return {\n seconds,\n formatted: formatETA(seconds),\n }\n}\n\n/** Default buffer size for ETA smoothing */\nexport const DEFAULT_ETA_BUFFER_SIZE = 10\n\n/**\n * Create an ETA tracker with automatic buffer management\n *\n * @param bufferSize - Number of samples to keep (default: 10)\n * @returns ETA tracker object\n *\n * @example\n * ```ts\n * const tracker = createETATracker();\n * tracker.record(0);\n * // ... later ...\n * tracker.record(50);\n * const eta = tracker.getETA(50, 100);\n * console.log(eta.formatted); // \"0:30\"\n * ```\n */\nexport function createETATracker(bufferSize = DEFAULT_ETA_BUFFER_SIZE) {\n const buffer: ETASample[] = []\n\n return {\n /** Record a new sample */\n record(value: number): void {\n buffer.push({ time: Date.now(), value })\n if (buffer.length > bufferSize) {\n buffer.shift()\n }\n },\n\n /** Get current ETA */\n getETA(current: number, total: number): ETAResult {\n return getETA(buffer, current, total)\n },\n\n /** Reset the buffer */\n reset(): void {\n buffer.length = 0\n },\n\n /** Get buffer for external use */\n getBuffer(): readonly ETASample[] {\n return buffer\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,aAAa,QAAqB,SAAiB,OAA8B;AAC/F,KAAI,OAAO,SAAS,EAClB,QAAO;CAGT,MAAM,QAAQ,OAAO;CACrB,MAAM,OAAO,OAAO,OAAO,SAAS;CAEpC,MAAM,WAAW,KAAK,OAAO,MAAM,QAAQ;CAC3C,MAAM,WAAW,KAAK,QAAQ,MAAM;AAEpC,KAAI,WAAW,KAAK,YAAY,EAC9B,QAAO;CAGT,MAAM,OAAO,WAAW;AAGxB,SAFkB,QAAQ,WAEP;;;;;;;;;;;;;;;;AAiBrB,SAAgB,UAAU,KAA4B;AACpD,KAAI,QAAQ,QAAQ,CAAC,SAAS,IAAI,CAChC,QAAO;AAGT,KAAI,MAAM,MAER,QAAO;CAGT,MAAM,QAAQ,KAAK,MAAM,MAAM,KAAK;CACpC,MAAM,UAAU,KAAK,MAAO,MAAM,OAAQ,GAAG;CAC7C,MAAM,UAAU,KAAK,MAAM,MAAM,GAAG;AAEpC,KAAI,QAAQ,EACV,QAAO,GAAG,MAAM,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI;AAG/F,QAAO,GAAG,QAAQ,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI;;;;;;;;;;AAW1D,SAAgB,OAAO,QAAqB,SAAiB,OAA0B;CACrF,MAAM,UAAU,aAAa,QAAQ,SAAS,MAAM;AACpD,QAAO;EACL;EACA,WAAW,UAAU,QAAQ;EAC9B;;;AAIH,MAAa,0BAA0B;;;;;;;;;;;;;;;;;AAkBvC,SAAgB,iBAAiB,aAAA,IAAsC;CACrE,MAAM,SAAsB,EAAE;AAE9B,QAAO;EAEL,OAAO,OAAqB;AAC1B,UAAO,KAAK;IAAE,MAAM,KAAK,KAAK;IAAE;IAAO,CAAC;AACxC,OAAI,OAAO,SAAS,WAClB,QAAO,OAAO;;EAKlB,OAAO,SAAiB,OAA0B;AAChD,UAAO,OAAO,QAAQ,SAAS,MAAM;;EAIvC,QAAc;AACZ,UAAO,SAAS;;EAIlB,YAAkC;AAChC,UAAO;;EAEV"}
@@ -1,5 +1,5 @@
1
- import { o as __toESM } from "./chunk-BSw8zbkd.mjs";
2
- //#region ../flexily/src/utils.ts
1
+ import { o as __toESM } from "./chunk-Vs_PY4HZ.mjs";
2
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/utils.ts
3
3
  /**
4
4
  * Flexily Utility Functions
5
5
  *
@@ -165,11 +165,11 @@ function applyMinMax(size, min, max, available) {
165
165
  return result;
166
166
  }
167
167
  //#endregion
168
- //#region ../flexily/src/logger.ts
168
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/logger.ts
169
169
  let _logger = null;
170
170
  async function createFallbackLogger(namespace) {
171
171
  try {
172
- const { default: createDebug } = await import("./src-D8kLrQBT.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
172
+ const { default: createDebug } = await import("./src-CChwjk0Z.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
173
173
  const debug = createDebug(namespace);
174
174
  return { debug: debug.enabled ? debug : void 0 };
175
175
  } catch {
@@ -204,14 +204,14 @@ const log = { get debug() {
204
204
  return _logger?.debug;
205
205
  } };
206
206
  //#endregion
207
- //#region ../flexily/src/trace.ts
207
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/trace.ts
208
208
  let _trace = null;
209
209
  /** Get the current trace recorder (null when tracing is disabled). */
210
210
  function getTrace() {
211
211
  return _trace;
212
212
  }
213
213
  //#endregion
214
- //#region ../flexily/src/layout-helpers.ts
214
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-helpers.ts
215
215
  /**
216
216
  * Layout Helper Functions
217
217
  *
@@ -300,7 +300,7 @@ function resolveEdgeBorderValue(arr, physicalIndex, _flexDirection, direction =
300
300
  return arr[physicalIndex];
301
301
  }
302
302
  //#endregion
303
- //#region ../flexily/src/layout-traversal.ts
303
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-traversal.ts
304
304
  /**
305
305
  * Mark subtree as having new layout and clear dirty flags (iterative to avoid stack overflow).
306
306
  * This is called after layout completes to reset dirty tracking for all nodes.
@@ -349,7 +349,7 @@ function propagatePositionDelta(node, deltaX, deltaY) {
349
349
  }
350
350
  }
351
351
  //#endregion
352
- //#region ../flexily/src/layout-stats.ts
352
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-stats.ts
353
353
  /**
354
354
  * Layout Statistics Counters
355
355
  *
@@ -384,7 +384,7 @@ function incLayoutCacheHits() {
384
384
  layoutCacheHits++;
385
385
  }
386
386
  //#endregion
387
- //#region ../flexily/src/layout-measure.ts
387
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-measure.ts
388
388
  /**
389
389
  * Node Measurement (Intrinsic Sizing)
390
390
  *
@@ -535,7 +535,7 @@ function measureNode(node, availableWidth, availableHeight, direction = 1) {
535
535
  layout.height = Math.round(nodeHeight);
536
536
  }
537
537
  //#endregion
538
- //#region ../flexily/src/layout-flex-lines.ts
538
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-flex-lines.ts
539
539
  /**
540
540
  * Flex Line Breaking and Space Distribution
541
541
  *
@@ -808,7 +808,7 @@ function distributeFlexSpaceForLine(lineChildren, initialFreeSpace) {
808
808
  }
809
809
  }
810
810
  //#endregion
811
- //#region ../flexily/src/layout-zero.ts
811
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/layout-zero.ts
812
812
  /**
813
813
  * Flexily Layout Algorithm — Main Entry Point
814
814
  *
@@ -898,7 +898,6 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
898
898
  const borderRight = resolveEdgeBorderValue(style.border, 2, style.flexDirection, direction);
899
899
  const borderBottom = resolveEdgeBorderValue(style.border, 3, style.flexDirection, direction);
900
900
  let nodeWidth;
901
- const isFitContentWidth = style.width.unit === 4 || style.width.unit === 5;
902
901
  if (style.width.unit === 1) nodeWidth = style.width.value;
903
902
  else if (style.width.unit === 2) nodeWidth = resolveValue(style.width, availableWidth);
904
903
  else if (Number.isNaN(availableWidth)) nodeWidth = NaN;
@@ -943,14 +942,13 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
943
942
  }
944
943
  if (node.hasMeasureFunc() && node.children.length === 0) {
945
944
  const widthIsAuto = style.width.unit === 3 || style.width.unit === 0 || Number.isNaN(nodeWidth);
946
- const widthIsFitContent = isFitContentWidth;
947
945
  const heightIsAuto = style.height.unit === 3 || style.height.unit === 0 || Number.isNaN(nodeHeight);
948
- const widthMode = widthIsAuto || widthIsFitContent ? 2 : 1;
946
+ const widthMode = widthIsAuto ? 2 : 1;
949
947
  const heightMode = heightIsAuto ? 0 : 1;
950
948
  const measureWidth = Number.isNaN(contentWidth) ? Infinity : contentWidth;
951
949
  const measureHeight = Number.isNaN(contentHeight) ? Infinity : contentHeight;
952
950
  const measured = node.cachedMeasure(measureWidth, widthMode, measureHeight, heightMode);
953
- if (widthIsAuto || widthIsFitContent) nodeWidth = measured.width + innerLeft + innerRight;
951
+ if (widthIsAuto) nodeWidth = measured.width + innerLeft + innerRight;
954
952
  if (heightIsAuto) nodeHeight = measured.height + innerTop + innerBottom;
955
953
  layout.width = Math.round(nodeWidth);
956
954
  layout.height = Math.round(nodeHeight);
@@ -959,7 +957,7 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
959
957
  return;
960
958
  }
961
959
  if (node.children.length === 0) {
962
- if (Number.isNaN(nodeWidth) || isFitContentWidth) nodeWidth = innerLeft + innerRight;
960
+ if (Number.isNaN(nodeWidth)) nodeWidth = innerLeft + innerRight;
963
961
  if (Number.isNaN(nodeHeight)) nodeHeight = innerTop + innerBottom;
964
962
  layout.width = Math.round(nodeWidth);
965
963
  layout.height = Math.round(nodeHeight);
@@ -1046,8 +1044,6 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
1046
1044
  let shrink = childStyle.flexShrink;
1047
1045
  if (childStyle.overflow !== 0) shrink = Math.max(shrink, 1);
1048
1046
  if (child.hasMeasureFunc() && childStyle.flexGrow > 0) shrink = Math.max(shrink, 1);
1049
- const mainDim = isRow ? childStyle.width : childStyle.height;
1050
- if (mainDim.unit === 4 || mainDim.unit === 5) shrink = Math.max(shrink, 1);
1051
1047
  cflex.flexShrink = shrink;
1052
1048
  cflex.baseSize = baseSize;
1053
1049
  cflex.mainSize = baseSize;
@@ -1361,7 +1357,6 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
1361
1357
  const parentHasDefiniteCross = parentCrossDim.unit === 1 || parentCrossDim.unit === 2 || !Number.isNaN(crossAxisSize);
1362
1358
  if (crossDim.unit === 1) childCrossSize = crossDim.value;
1363
1359
  else if (crossDim.unit === 2) childCrossSize = resolveValue(crossDim, crossAxisSize);
1364
- else if (crossDim.unit === 4 || crossDim.unit === 5) childCrossSize = NaN;
1365
1360
  else if (parentHasDefiniteCross && alignment === 4) childCrossSize = (numLines > 1 ? savedLineCrossSizes ? savedLineCrossSizes[childLineIdx] : _lineCrossSizes[childLineIdx] : crossAxisSize) - crossMargin;
1366
1361
  else childCrossSize = NaN;
1367
1362
  const crossMinVal = isRow ? childStyle.minHeight : childStyle.minWidth;
@@ -1456,13 +1451,12 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
1456
1451
  const childLeft = posRound(fractionalLeft + posOffsetX);
1457
1452
  const childTop = posRound(fractionalTop + posOffsetY);
1458
1453
  const crossDimForLayoutCall = isRow ? childStyle.height : childStyle.width;
1459
- const crossIsAutoForLayoutCall = crossDimForLayoutCall.unit === 3 || crossDimForLayoutCall.unit === 0 || crossDimForLayoutCall.unit === 4 || crossDimForLayoutCall.unit === 5;
1454
+ const crossIsAutoForLayoutCall = crossDimForLayoutCall.unit === 3 || crossDimForLayoutCall.unit === 0;
1460
1455
  const mainIsPercentForLayoutCall = (isRow ? childStyle.width : childStyle.height).unit === 2;
1461
1456
  const crossIsPercentForLayoutCall = crossDimForLayoutCall.unit === 2;
1462
1457
  const flexDistChanged = child.flex.mainSize !== child.flex.baseSize;
1463
1458
  const hasMeasureLeaf = child.hasMeasureFunc() && child.children.length === 0;
1464
- const crossIsFitContent = crossDimForLayoutCall.unit === 4 || crossDimForLayoutCall.unit === 5;
1465
- layoutNode(child, isRow && mainIsAutoChild && !hasFlexGrow && !flexDistChanged && !hasMeasureLeaf ? NaN : !isRow && crossIsAutoForLayoutCall && !parentHasDefiniteCross && !crossIsFitContent ? NaN : isRow && mainIsPercentForLayoutCall ? mainAxisSize : !isRow && crossIsPercentForLayoutCall ? crossAxisSize : !isRow && crossIsFitContent ? crossAxisSize : childWidth, !isRow && mainIsAutoChild && !hasFlexGrow && !flexDistChanged && !hasMeasureLeaf ? NaN : isRow && crossIsAutoForLayoutCall && !parentHasDefiniteCross && !crossIsFitContent ? NaN : !isRow && mainIsPercentForLayoutCall ? mainAxisSize : isRow && crossIsPercentForLayoutCall ? crossAxisSize : isRow && crossIsFitContent ? crossAxisSize : childHeight, childLeft, childTop, absChildLeft - childMarginLeft, absChildTop - childMarginTop, direction);
1459
+ layoutNode(child, isRow && mainIsAutoChild && !hasFlexGrow && !flexDistChanged && !hasMeasureLeaf ? NaN : !isRow && crossIsAutoForLayoutCall && !parentHasDefiniteCross ? NaN : isRow && mainIsPercentForLayoutCall ? mainAxisSize : !isRow && crossIsPercentForLayoutCall ? crossAxisSize : childWidth, !isRow && mainIsAutoChild && !hasFlexGrow && !flexDistChanged && !hasMeasureLeaf ? NaN : isRow && crossIsAutoForLayoutCall && !parentHasDefiniteCross ? NaN : !isRow && mainIsPercentForLayoutCall ? mainAxisSize : isRow && crossIsPercentForLayoutCall ? crossAxisSize : childHeight, childLeft, childTop, absChildLeft - childMarginLeft, absChildTop - childMarginTop, direction);
1466
1460
  if (childWidth < childMinW) childWidth = childMinW;
1467
1461
  if (childHeight < childMinH) childHeight = childMinH;
1468
1462
  const hasMeasure = child.hasMeasureFunc() && child.children.length === 0;
@@ -1475,11 +1469,10 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
1475
1469
  child.layout.height = edgeBasedMainSize;
1476
1470
  }
1477
1471
  const crossDimForCheck = isRow ? childStyle.height : childStyle.width;
1478
- const crossDimIsFitContent = crossDimForCheck.unit === 4 || crossDimForCheck.unit === 5;
1479
- const crossIsAuto = crossDimForCheck.unit === 3 || crossDimForCheck.unit === 0 || crossDimIsFitContent;
1472
+ const crossIsAuto = crossDimForCheck.unit === 3 || crossDimForCheck.unit === 0;
1480
1473
  const parentCrossIsAuto = !parentHasDefiniteCross;
1481
1474
  const hasCrossMinMax = crossMinVal.unit !== 0 || crossMaxVal.unit !== 0;
1482
- if (!crossIsAuto || !crossDimIsFitContent && !parentCrossIsAuto && alignment === 4 || hasCrossMinMax && !Number.isNaN(childCrossSize)) if (isRow) child.layout.height = Math.round(childHeight);
1475
+ if (!crossIsAuto || !parentCrossIsAuto && alignment === 4 || hasCrossMinMax && !Number.isNaN(childCrossSize)) if (isRow) child.layout.height = Math.round(childHeight);
1483
1476
  else child.layout.width = Math.round(childWidth);
1484
1477
  child.layout.left = childLeft;
1485
1478
  child.layout.top = childTop;
@@ -1548,10 +1541,6 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
1548
1541
  if (isRow && style.height.unit !== 1 && style.height.unit !== 2 && Number.isNaN(availableHeight) && !hasAR) nodeHeight = totalCrossSize + innerTop + innerBottom;
1549
1542
  if (!isRow && style.width.unit !== 1 && style.width.unit !== 2 && Number.isNaN(availableWidth) && !hasAR) nodeWidth = totalCrossSize + innerLeft + innerRight;
1550
1543
  }
1551
- if (isFitContentWidth && !Number.isNaN(nodeWidth) && !Number.isNaN(availableWidth)) {
1552
- const availForNode = availableWidth - marginLeft - marginRight;
1553
- if (availForNode >= 0 && nodeWidth > availForNode) nodeWidth = availForNode;
1554
- }
1555
1544
  nodeWidth = applyMinMax(nodeWidth, style.minWidth, style.maxWidth, availableWidth);
1556
1545
  nodeHeight = applyMinMax(nodeHeight, style.minHeight, style.maxHeight, availableHeight);
1557
1546
  if (!Number.isNaN(nodeWidth) && nodeWidth < minInnerWidth) nodeWidth = minInnerWidth;
@@ -1789,7 +1778,7 @@ function layoutNode(node, availableWidth, availableHeight, offsetX, offsetY, abs
1789
1778
  _t?.layoutExit(_tn, layout.width, layout.height);
1790
1779
  }
1791
1780
  //#endregion
1792
- //#region ../flexily/src/types.ts
1781
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/types.ts
1793
1782
  /**
1794
1783
  * Create a default Value (undefined).
1795
1784
  */
@@ -1862,7 +1851,7 @@ function createDefaultStyle() {
1862
1851
  };
1863
1852
  }
1864
1853
  //#endregion
1865
- //#region ../flexily/src/node-zero.ts
1854
+ //#region node_modules/.bun/flexily@0.5.2/node_modules/flexily/src/node-zero.ts
1866
1855
  /**
1867
1856
  * Flexily Node
1868
1857
  *
@@ -2523,38 +2512,6 @@ var Node = class Node {
2523
2512
  this.markDirty();
2524
2513
  }
2525
2514
  /**
2526
- * Set the width to fit-content mode.
2527
- *
2528
- * CSS fit-content = min(max-content, max(min-content, available-width)).
2529
- * For terminals: min(max-content, available-width) since min-content
2530
- * floor is rarely relevant.
2531
- *
2532
- * The layout algorithm measures unconstrained content width (max-content),
2533
- * then clamps to the available width from the parent.
2534
- */
2535
- setWidthFitContent() {
2536
- this._style.width = {
2537
- value: 0,
2538
- unit: 4
2539
- };
2540
- this.markDirty();
2541
- }
2542
- /**
2543
- * Set the width to snug-content mode.
2544
- *
2545
- * Like fit-content but signals that the consumer wants the tightest
2546
- * possible width (binary-search shrinkwrap). The layout engine treats
2547
- * this identically to fit-content for sizing; the consuming framework
2548
- * (e.g., silvery) can further tighten via its own binary search.
2549
- */
2550
- setWidthSnugContent() {
2551
- this._style.width = {
2552
- value: 0,
2553
- unit: 5
2554
- };
2555
- this.markDirty();
2556
- }
2557
- /**
2558
2515
  * Set the height to a fixed value in points.
2559
2516
  *
2560
2517
  * @param value - Height in points
@@ -3425,4 +3382,4 @@ function createFlexilyZeroEngine() {
3425
3382
  //#endregion
3426
3383
  export { createFlexilyZeroEngine as n, FlexilyZeroLayoutEngine as t };
3427
3384
 
3428
- //# sourceMappingURL=flexily-zero-adapter-BOM0cl8R.mjs.map
3385
+ //# sourceMappingURL=flexily-zero-adapter-BlQa46nr.mjs.map