silvery 0.19.2 → 0.21.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 (218) hide show
  1. package/README.md +9 -4
  2. package/dist/Text-Lq0dmj8-.mjs +239 -0
  3. package/dist/Text-Lq0dmj8-.mjs.map +1 -0
  4. package/dist/UPNG-Bo33r8rA.mjs +3 -0
  5. package/dist/UPNG-DosRPdF4.mjs +5075 -0
  6. package/dist/UPNG-DosRPdF4.mjs.map +1 -0
  7. package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs +6 -0
  8. package/dist/__vite-browser-external-2447137e-D_JM6skp.mjs.map +1 -0
  9. package/dist/{animation-Cn64yepo.mjs → animation-ZMN2_XKv.mjs} +2 -2
  10. package/dist/animation-ZMN2_XKv.mjs.map +1 -0
  11. package/dist/{ansi-Cc33mW54.d.mts → ansi-2Xn0yatP.d.mts} +1 -1
  12. package/dist/{ansi-Cc33mW54.d.mts.map → ansi-2Xn0yatP.d.mts.map} +1 -1
  13. package/dist/{ansi-CLOitHKx.mjs → ansi-D1KQMAbf.mjs} +1 -1
  14. package/dist/{ansi-CLOitHKx.mjs.map → ansi-D1KQMAbf.mjs.map} +1 -1
  15. package/dist/ansi-yC4RyBNY.mjs +22441 -0
  16. package/dist/ansi-yC4RyBNY.mjs.map +1 -0
  17. package/dist/apng-CR08rIaH.mjs +58 -0
  18. package/dist/apng-CR08rIaH.mjs.map +1 -0
  19. package/dist/apng-DaHfVaVI.mjs +3 -0
  20. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  21. package/dist/assets/skia.darwin-arm64-DQs5sT6N.node +0 -0
  22. package/dist/backend-B-WYLUib.mjs +13396 -0
  23. package/dist/backend-B-WYLUib.mjs.map +1 -0
  24. package/dist/backends-CUtan80W.mjs +3 -0
  25. package/dist/backends-DIVYzKqd.mjs +1083 -0
  26. package/dist/backends-DIVYzKqd.mjs.map +1 -0
  27. package/dist/bound-term-0sPrrzH1.d.mts +4640 -0
  28. package/dist/bound-term-0sPrrzH1.d.mts.map +1 -0
  29. package/dist/canvas-1v7dPT-_.mjs +3 -0
  30. package/dist/canvas-CSuPOMNt.mjs +1442 -0
  31. package/dist/canvas-CSuPOMNt.mjs.map +1 -0
  32. package/dist/{chunk-Vs_PY4HZ.mjs → chunk-BSw8zbkd.mjs} +1 -1
  33. package/dist/cli-dvo0r2fs.mjs +4 -0
  34. package/dist/compare-CQodSH4G.mjs +376 -0
  35. package/dist/compare-CQodSH4G.mjs.map +1 -0
  36. package/dist/compare-DHlcxEYA.mjs +3 -0
  37. package/dist/context-BU5LkkIy.mjs.map +1 -1
  38. package/dist/devtools-CJdt5H0X.mjs +2 -0
  39. package/dist/{devtools-DxkSLXDA.mjs → devtools-DcQjgyjL.mjs} +5 -4
  40. package/dist/{devtools-DxkSLXDA.mjs.map → devtools-DcQjgyjL.mjs.map} +1 -1
  41. package/dist/easing-BI-ASGMO.d.mts +24 -0
  42. package/dist/easing-BI-ASGMO.d.mts.map +1 -0
  43. package/dist/{eta-Bb3RH3wh.mjs → eta-CJlGH06n.mjs} +1 -1
  44. package/dist/{eta-Bb3RH3wh.mjs.map → eta-CJlGH06n.mjs.map} +1 -1
  45. package/dist/flexily-zero-adapter-C3Vj0fPt.mjs +306 -0
  46. package/dist/flexily-zero-adapter-C3Vj0fPt.mjs.map +1 -0
  47. package/dist/{flexily-zero-adapter-CMxXhdOL.mjs → flexily-zero-adapter-C4lW_Ov5.mjs} +1 -1
  48. package/dist/fonts-BFmhXDv7.mjs +88 -0
  49. package/dist/fonts-BFmhXDv7.mjs.map +1 -0
  50. package/dist/gif-C_AjaT9d.mjs +188 -0
  51. package/dist/gif-C_AjaT9d.mjs.map +1 -0
  52. package/dist/gif-DaC4XrxA.mjs +3 -0
  53. package/dist/gifenc-BOUT-KFB.mjs +730 -0
  54. package/dist/gifenc-BOUT-KFB.mjs.map +1 -0
  55. package/dist/image-C2Birh2x.mjs +1252 -0
  56. package/dist/image-C2Birh2x.mjs.map +1 -0
  57. package/dist/index-BUMxS65f.d.mts +453 -0
  58. package/dist/index-BUMxS65f.d.mts.map +1 -0
  59. package/dist/{index-D3saHouR.d.mts → index-CSQf13CI.d.mts} +1057 -1133
  60. package/dist/index-CSQf13CI.d.mts.map +1 -0
  61. package/dist/{index-BXslOebb.d.mts → index-Cl9KKjQ_.d.mts} +4919 -3921
  62. package/dist/index-Cl9KKjQ_.d.mts.map +1 -0
  63. package/dist/index-XbNrPhWl.d.mts +336 -0
  64. package/dist/index-XbNrPhWl.d.mts.map +1 -0
  65. package/dist/index.d.mts +8 -5
  66. package/dist/index.d.mts.map +1 -1
  67. package/dist/index.mjs +14 -12
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/key-mapping-CS-YD_cD.mjs +132 -0
  70. package/dist/key-mapping-CS-YD_cD.mjs.map +1 -0
  71. package/dist/key-mapping-Yn-Jgrij.mjs +3 -0
  72. package/dist/{layout-engine-B6Cdz1yZ.mjs → layout-engine-C07LEXWT.mjs} +1 -1
  73. package/dist/layout-engine-C2px0RJE.mjs +67 -0
  74. package/dist/layout-engine-C2px0RJE.mjs.map +1 -0
  75. package/dist/layout-signals-Cnw6xk8Q.mjs +988 -0
  76. package/dist/layout-signals-Cnw6xk8Q.mjs.map +1 -0
  77. package/dist/mouse-events-Dki3ISIp.mjs +1044 -0
  78. package/dist/mouse-events-Dki3ISIp.mjs.map +1 -0
  79. package/dist/{multi-progress-Bq9Oi_WI.mjs → multi-progress-CIRjrzma.mjs} +3 -3
  80. package/dist/{multi-progress-Bq9Oi_WI.mjs.map → multi-progress-CIRjrzma.mjs.map} +1 -1
  81. package/dist/{multi-progress-DAQC7eap.d.mts → multi-progress-DHZ2xUT2.d.mts} +2 -2
  82. package/dist/{multi-progress-DAQC7eap.d.mts.map → multi-progress-DHZ2xUT2.d.mts.map} +1 -1
  83. package/dist/{node-BeWlnCPY.mjs → node-CjM5Rt-M.mjs} +4 -4
  84. package/dist/node-CjM5Rt-M.mjs.map +1 -0
  85. package/dist/playwright-D5YiZcNS.mjs +76397 -0
  86. package/dist/playwright-D5YiZcNS.mjs.map +1 -0
  87. package/dist/png-codec-Dp84742B.mjs +36 -0
  88. package/dist/png-codec-Dp84742B.mjs.map +1 -0
  89. package/dist/png-codec-QwOtJ8Zs.mjs +3 -0
  90. package/dist/progress-DB_Xo071.mjs +675 -0
  91. package/dist/progress-DB_Xo071.mjs.map +1 -0
  92. package/dist/{progress-bar-CXE5Qfkd.mjs → progress-bar-oJwq22CR.mjs} +4 -4
  93. package/dist/{progress-bar-CXE5Qfkd.mjs.map → progress-bar-oJwq22CR.mjs.map} +1 -1
  94. package/dist/rasterizer-BRXrDdWx.mjs +3 -0
  95. package/dist/rasterizer-CpEhJvdR.mjs +296 -0
  96. package/dist/rasterizer-CpEhJvdR.mjs.map +1 -0
  97. package/dist/reconciler-DldIJB93.mjs +2083 -0
  98. package/dist/reconciler-DldIJB93.mjs.map +1 -0
  99. package/dist/{render-string-CDCeYkS3.mjs → render-string-BcoCpjCB.mjs} +1 -1
  100. package/dist/{render-string-Darrg7ku.mjs → render-string-DkQacASz.mjs} +2707 -549
  101. package/dist/render-string-DkQacASz.mjs.map +1 -0
  102. package/dist/resvg-js-DkOndZI3.mjs +203 -0
  103. package/dist/resvg-js-DkOndZI3.mjs.map +1 -0
  104. package/dist/runtime.d.mts +3 -2
  105. package/dist/runtime.mjs +3 -3
  106. package/dist/schemes-JjNp4aSl.mjs +2611 -0
  107. package/dist/schemes-JjNp4aSl.mjs.map +1 -0
  108. package/dist/{spinner-CGo34vyR.d.mts → spinner-CZINHpkV.d.mts} +2 -2
  109. package/dist/{spinner-CGo34vyR.d.mts.map → spinner-CZINHpkV.d.mts.map} +1 -1
  110. package/dist/{spinner-CeOmcuw_.mjs → spinner-D9lrHr8s.mjs} +7 -7
  111. package/dist/spinner-D9lrHr8s.mjs.map +1 -0
  112. package/dist/src-5w9QR6_8.mjs +1071 -0
  113. package/dist/src-5w9QR6_8.mjs.map +1 -0
  114. package/dist/src-BNTToU7l.mjs +4387 -0
  115. package/dist/src-BNTToU7l.mjs.map +1 -0
  116. package/dist/{src-CF-6UN01.mjs → src-BR4xNwdG.mjs} +10436 -2622
  117. package/dist/src-BR4xNwdG.mjs.map +1 -0
  118. package/dist/{types-Bk2yw9Qj.mjs → src-DKp-_OFG.mjs} +34 -94
  119. package/dist/src-DKp-_OFG.mjs.map +1 -0
  120. package/dist/src-bt8wSrfJ.mjs +258 -0
  121. package/dist/src-bt8wSrfJ.mjs.map +1 -0
  122. package/dist/src-e33Y6kNJ.mjs +3 -0
  123. package/dist/src-iDwu25UD.mjs +1814 -0
  124. package/dist/src-iDwu25UD.mjs.map +1 -0
  125. package/dist/steps-Bp2uNqnn.d.mts +202 -0
  126. package/dist/steps-Bp2uNqnn.d.mts.map +1 -0
  127. package/dist/svg-15lZZzxq.mjs +486 -0
  128. package/dist/svg-15lZZzxq.mjs.map +1 -0
  129. package/dist/svg-Cz0UXcDj.mjs +255 -0
  130. package/dist/svg-Cz0UXcDj.mjs.map +1 -0
  131. package/dist/svg-DY72a4HK.mjs +3 -0
  132. package/dist/svg-g1D6ErwR.d.mts +82 -0
  133. package/dist/svg-g1D6ErwR.d.mts.map +1 -0
  134. package/dist/term.d.mts +3 -0
  135. package/dist/term.mjs +9 -0
  136. package/dist/term.mjs.map +1 -0
  137. package/dist/theme.d.mts +95 -2
  138. package/dist/theme.d.mts.map +1 -0
  139. package/dist/theme.mjs +9 -3
  140. package/dist/theme.mjs.map +1 -0
  141. package/dist/{types-BH_v3iMT.d.mts → types-kt_fKR37.d.mts} +2 -15
  142. package/dist/types-kt_fKR37.d.mts.map +1 -0
  143. package/dist/ui/animation.d.mts +2 -1
  144. package/dist/ui/animation.mjs +1 -1
  145. package/dist/ui/ansi.d.mts +1 -1
  146. package/dist/ui/ansi.mjs +1 -1
  147. package/dist/ui/cli.d.mts +3 -3
  148. package/dist/ui/cli.mjs +5 -5
  149. package/dist/ui/display.d.mts +1 -1
  150. package/dist/ui/image.d.mts +2 -2
  151. package/dist/ui/image.mjs +2 -2
  152. package/dist/ui/input.d.mts +1 -1
  153. package/dist/ui/input.mjs +4 -2
  154. package/dist/ui/input.mjs.map +1 -1
  155. package/dist/ui/progress.d.mts +5 -249
  156. package/dist/ui/progress.mjs +5 -858
  157. package/dist/ui/react.d.mts +1 -1
  158. package/dist/ui/react.mjs +2 -2
  159. package/dist/ui/recording-chrome-react.d.mts +21 -0
  160. package/dist/ui/recording-chrome-react.d.mts.map +1 -0
  161. package/dist/ui/recording-chrome-react.mjs +105 -0
  162. package/dist/ui/recording-chrome-react.mjs.map +1 -0
  163. package/dist/ui/recording-chrome.d.mts +2 -0
  164. package/dist/ui/recording-chrome.mjs +2 -0
  165. package/dist/ui/utils.mjs +1 -1
  166. package/dist/ui/wrappers.d.mts +3 -3
  167. package/dist/ui/wrappers.mjs +2 -2
  168. package/dist/ui.d.mts +7 -6
  169. package/dist/ui.mjs +8 -7
  170. package/dist/{useLatest-Bg2x4bfP.d.mts → useLatest-DRDDVwjh.d.mts} +5 -25
  171. package/dist/useLatest-DRDDVwjh.d.mts.map +1 -0
  172. package/dist/{with-text-input-CRfoiFFG.d.mts → with-text-input-YeohVLeo.d.mts} +4 -55
  173. package/dist/with-text-input-YeohVLeo.d.mts.map +1 -0
  174. package/dist/wrapper-C70ATkVv.mjs +3527 -0
  175. package/dist/wrapper-C70ATkVv.mjs.map +1 -0
  176. package/dist/{wrappers-UTADQkSY.mjs → wrappers-BCUYITrY.mjs} +5 -157
  177. package/dist/wrappers-BCUYITrY.mjs.map +1 -0
  178. package/dist/{yoga-adapter-8oRGRw8V.mjs → yoga-adapter-BnZX1PAY.mjs} +28 -2
  179. package/dist/yoga-adapter-BnZX1PAY.mjs.map +1 -0
  180. package/dist/yoga-adapter-DxgsQ_gg.mjs +2 -0
  181. package/dist/zipBundle-3nqeDRtm.mjs +3 -0
  182. package/dist/zipBundle-VNAYFmqJ.mjs +2003 -0
  183. package/dist/zipBundle-VNAYFmqJ.mjs.map +1 -0
  184. package/package.json +20 -9
  185. package/dist/animation-Cn64yepo.mjs.map +0 -1
  186. package/dist/cli-BKp0YtBD.mjs +0 -4
  187. package/dist/devtools-9QY4teqI.mjs +0 -2
  188. package/dist/flexily-zero-adapter-BlQa46nr.mjs +0 -3385
  189. package/dist/flexily-zero-adapter-BlQa46nr.mjs.map +0 -1
  190. package/dist/image-CTII5QWI.mjs +0 -477
  191. package/dist/image-CTII5QWI.mjs.map +0 -1
  192. package/dist/index-BXslOebb.d.mts.map +0 -1
  193. package/dist/index-BnA7mNpo.d.mts +0 -175
  194. package/dist/index-BnA7mNpo.d.mts.map +0 -1
  195. package/dist/index-D3saHouR.d.mts.map +0 -1
  196. package/dist/layout-engine-ClUgv6jB.mjs +0 -50
  197. package/dist/layout-engine-ClUgv6jB.mjs.map +0 -1
  198. package/dist/node-BeWlnCPY.mjs.map +0 -1
  199. package/dist/reconciler-Cwgm8hRR.mjs +0 -8459
  200. package/dist/reconciler-Cwgm8hRR.mjs.map +0 -1
  201. package/dist/render-string-Darrg7ku.mjs.map +0 -1
  202. package/dist/spinner-CeOmcuw_.mjs.map +0 -1
  203. package/dist/src-B5GjfG7g.mjs +0 -4305
  204. package/dist/src-B5GjfG7g.mjs.map +0 -1
  205. package/dist/src-CChwjk0Z.mjs +0 -738
  206. package/dist/src-CChwjk0Z.mjs.map +0 -1
  207. package/dist/src-CF-6UN01.mjs.map +0 -1
  208. package/dist/src-NCKb8kE5.mjs +0 -2660
  209. package/dist/src-NCKb8kE5.mjs.map +0 -1
  210. package/dist/types-BH_v3iMT.d.mts.map +0 -1
  211. package/dist/types-Bk2yw9Qj.mjs.map +0 -1
  212. package/dist/ui/progress.d.mts.map +0 -1
  213. package/dist/ui/progress.mjs.map +0 -1
  214. package/dist/useLatest-Bg2x4bfP.d.mts.map +0 -1
  215. package/dist/with-text-input-CRfoiFFG.d.mts.map +0 -1
  216. package/dist/wrappers-UTADQkSY.mjs.map +0 -1
  217. package/dist/yoga-adapter-8oRGRw8V.mjs.map +0 -1
  218. package/dist/yoga-adapter-D_CcxSt5.mjs +0 -2
package/README.md CHANGED
@@ -8,7 +8,7 @@ $ npm install silvery react
8
8
 
9
9
  ```tsx
10
10
  import { useState } from "react"
11
- import { render, Box, Text, useInput } from "silvery"
11
+ import { render, Box, Text, useInput, createTerm } from "silvery"
12
12
 
13
13
  function Counter() {
14
14
  const [count, setCount] = useState(0)
@@ -22,9 +22,14 @@ function Counter() {
22
22
  )
23
23
  }
24
24
 
25
- await render(<Counter />).run()
25
+ using term = createTerm()
26
+ term.modes.altScreen(true)
27
+ term.modes.rawMode(true)
28
+ await render(<Counter />, term).run()
26
29
  ```
27
30
 
31
+ ![Silvery counter rendered in a terminal](docs/public/screenshots/counter.svg)
32
+
28
33
  React 18 + 19 with concurrent mode, Suspense, and flexbox layout. [Drop-in Ink compatible](https://silvery.dev/guide/silvery-vs-ink#compatibility) ([`@silvery/ink`](https://silvery.dev/guide/silvery-vs-ink)) — same `Box`, `Text`, `useInput` API with 918/931 Ink 7.0 tests passing.
29
34
 
30
35
  ### Shiny new stuff
@@ -78,7 +83,7 @@ Along the way, three principles emerged. Take the best from the web, stay true t
78
83
  | `silvery` | Components, hooks, renderer — the one package you need |
79
84
  | `@silvery/ink` / `@silvery/chalk` | Ink compatibility — 918/931 Ink 7.0 tests, 32/32 Chalk tests |
80
85
  | `@silvery/test` | Playwright-style testing — locators, `press()`, buffer assertions |
81
- | `@silvery/create` | Composable app builder — `pipe()` providers |
86
+ | `@silvery/create` | Composable app builder — `pipe()` providers _(coming soon)_ |
82
87
  | `@silvery/theme` | 84 color schemes, semantic tokens, auto-detect |
83
88
  | `@silvery/commander` | **Beautiful CLIs for free** — help renders through Silvery itself |
84
89
  | `@silvery/headless` | Pure state machines — portable, no React |
@@ -99,7 +104,7 @@ Standalone projects Silvery builds on — each stands on its own:
99
104
 
100
105
  - **Renderers** — Canvas 2D, Web DOM (experimental today, production later)
101
106
  - **Frameworks** — Svelte, Solid.js, Vue adapters
102
- - **@silvery/create** — Structured state management with commands, keybindings, effects-as-data
107
+ - **Silvertea** — Structured state management with commands, keybindings, effects-as-data (ships as `@silvery/create`)
103
108
 
104
109
  **Runtimes:** Bun >= 1.0 and Node.js >= 23.6. CLI (`silvery` command) requires Bun.
105
110
 
@@ -0,0 +1,239 @@
1
+ import { r as effect } from "./src-DKp-_OFG.mjs";
2
+ import { a as NodeContext } from "./context-BU5LkkIy.mjs";
3
+ import { r as getLayoutSignals, s as observeLayoutSignal } from "./layout-signals-Cnw6xk8Q.mjs";
4
+ import { s as KNOWN_VARIANTS, t as init_src } from "./src-BNTToU7l.mjs";
5
+ import { a as defaultDarkTheme, l as init_schemes } from "./schemes-JjNp4aSl.mjs";
6
+ import { createContext, forwardRef, useContext, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ //#region packages/ag-react/src/components/Box.tsx
9
+ /**
10
+ * Silvery Box Component
11
+ *
12
+ * The primary layout primitive for Silvery. Box is a flexbox container that can hold
13
+ * other Box or Text components. It supports all standard flexbox properties,
14
+ * dimensions, spacing, and borders.
15
+ *
16
+ * Box renders to an 'silvery-box' host element that the reconciler converts to an
17
+ * SilveryNode with an associated Yoga layout node.
18
+ *
19
+ * Box provides NodeContext to its children, enabling useBoxRect/useScrollRect hooks.
20
+ * It also supports forwardRef for imperative access and onLayout for layout callbacks.
21
+ */
22
+ /**
23
+ * Flexbox container component for terminal UIs.
24
+ *
25
+ * Provides NodeContext to children, enabling useBoxRect/useScrollRect hooks.
26
+ * Supports forwardRef for imperative access and onLayout for layout callbacks.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * // Basic vertical layout (default)
31
+ * <Box>
32
+ * <Text>Line 1</Text>
33
+ * <Text>Line 2</Text>
34
+ * </Box>
35
+ *
36
+ * // Horizontal layout with spacing
37
+ * <Box flexDirection="row" gap={2}>
38
+ * <Box width={10}><Text>Left</Text></Box>
39
+ * <Box flexGrow={1}><Text>Center</Text></Box>
40
+ * <Box width={10}><Text>Right</Text></Box>
41
+ * </Box>
42
+ *
43
+ * // With border
44
+ * <Box borderStyle="single" borderColor="green" padding={1}>
45
+ * <Text>Boxed content</Text>
46
+ * </Box>
47
+ *
48
+ * // With ref and onLayout
49
+ * const boxRef = useRef<BoxHandle>(null);
50
+ * <Box
51
+ * ref={boxRef}
52
+ * onLayout={(layout) => console.log('Size:', layout.width, layout.height)}
53
+ * >
54
+ * <Text>Content</Text>
55
+ * </Box>
56
+ * ```
57
+ */
58
+ const Box = forwardRef(function Box(props, ref) {
59
+ const { children, onLayout, ...restProps } = props;
60
+ const nodeRef = useRef(null);
61
+ const [node, setNode] = useState(null);
62
+ const lastReportedLayout = useRef(null);
63
+ useLayoutEffect(() => {
64
+ if (nodeRef.current) setNode(nodeRef.current);
65
+ }, []);
66
+ useLayoutEffect(() => {
67
+ if (!onLayout || !node) return;
68
+ const releaseObservation = observeLayoutSignal(node, "boxRect");
69
+ const signals = getLayoutSignals(node);
70
+ const onLayoutRef = { current: onLayout };
71
+ onLayoutRef.current = onLayout;
72
+ const dispose = effect(() => {
73
+ const layout = signals.boxRect();
74
+ if (!layout) return;
75
+ const last = lastReportedLayout.current;
76
+ if (!last || last.x !== layout.x || last.y !== layout.y || last.width !== layout.width || last.height !== layout.height) {
77
+ lastReportedLayout.current = layout;
78
+ onLayoutRef.current(layout);
79
+ }
80
+ });
81
+ return () => {
82
+ dispose();
83
+ releaseObservation();
84
+ };
85
+ }, [node, onLayout]);
86
+ useImperativeHandle(ref, () => ({
87
+ getNode: () => nodeRef.current,
88
+ getBoxRect: () => nodeRef.current?.boxRect ?? null,
89
+ getScrollRect: () => nodeRef.current?.scrollRect ?? null
90
+ }), []);
91
+ return /* @__PURE__ */ jsx("silvery-box", {
92
+ ref: nodeRef,
93
+ ...restProps,
94
+ children: /* @__PURE__ */ jsx(NodeContext.Provider, {
95
+ value: node,
96
+ children
97
+ })
98
+ });
99
+ });
100
+ //#endregion
101
+ //#region packages/ag-react/src/ThemeContext.tsx
102
+ /**
103
+ * ThemeContext — delivers a Theme to the component tree.
104
+ *
105
+ * Wrap your app (or a subtree) in `<ThemeProvider theme={…}>` to make
106
+ * `$token` color props resolve against that theme. Components call
107
+ * `useTheme()` to read the current theme.
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * import { ThemeProvider, defaultDarkTheme } from '@silvery/ag-react'
112
+ *
113
+ * <ThemeProvider theme={defaultDarkTheme}>
114
+ * <App />
115
+ * </ThemeProvider>
116
+ * ```
117
+ */
118
+ init_schemes();
119
+ /** @internal Exported for ThemeProvider and Text component — not public API. */
120
+ const ThemeContext = createContext(defaultDarkTheme);
121
+ /**
122
+ * Context that carries scheme detection metadata (name, source, confidence).
123
+ *
124
+ * Separate from ThemeContext because scheme metadata is orthogonal to the
125
+ * theme token bag. Populated by `<ThemeProvider scheme={...}>` when the
126
+ * caller passes detection provenance (e.g. from `runThemed`). Null when
127
+ * no scheme metadata was injected.
128
+ *
129
+ * @internal Exported for ThemeProvider.
130
+ */
131
+ const ActiveSchemeContext = createContext(null);
132
+ /**
133
+ * Read the current theme from context.
134
+ *
135
+ * Returns `defaultDarkTheme` when no `ThemeProvider` is present.
136
+ */
137
+ function useTheme() {
138
+ return useContext(ThemeContext);
139
+ }
140
+ //#endregion
141
+ //#region packages/ag-react/src/components/Text.tsx
142
+ /**
143
+ * Silvery Text Component
144
+ *
145
+ * The primitive for rendering text content in Silvery. Text supports styling
146
+ * (colors, bold, italic, etc.) and text wrapping/truncation modes.
147
+ *
148
+ * Text renders to an 'silvery-text' host element that the reconciler converts
149
+ * to an SilveryNode containing the text content.
150
+ *
151
+ * Supports forwardRef for imperative access to the underlying node.
152
+ */
153
+ init_src();
154
+ /** Per-theme set of variant names that have already triggered a warning. */
155
+ const _warnedVariants = /* @__PURE__ */ new WeakMap();
156
+ function warnOnce(theme, variant) {
157
+ if (process.env.NODE_ENV === "production") return;
158
+ let warned = _warnedVariants.get(theme);
159
+ if (warned === void 0) {
160
+ warned = /* @__PURE__ */ new Set();
161
+ _warnedVariants.set(theme, warned);
162
+ }
163
+ if (warned.has(variant)) return;
164
+ warned.add(variant);
165
+ const known = KNOWN_VARIANTS.join(", ");
166
+ console.warn(`[silvery] <Text variant="${variant}"> — unknown variant, defaulting to bare. Known: ${known}. Register custom variants via <ThemeProvider tokens={{ variants: { ${variant}: {...} } }}>.`);
167
+ }
168
+ /**
169
+ * Text rendering component for terminal UIs.
170
+ *
171
+ * Supports forwardRef for imperative access to the underlying node.
172
+ *
173
+ * @example
174
+ * ```tsx
175
+ * // Basic text
176
+ * <Text>Hello, world!</Text>
177
+ *
178
+ * // Colored text
179
+ * <Text color="green">Success!</Text>
180
+ * <Text color="#ff6600">Orange text</Text>
181
+ *
182
+ * // Styled text
183
+ * <Text bold>Important</Text>
184
+ * <Text italic underline>Emphasized</Text>
185
+ *
186
+ * // Combined styles
187
+ * <Text color="red" bold inverse>Alert!</Text>
188
+ *
189
+ * // Nested text with different styles
190
+ * <Text>
191
+ * Normal <Text bold>bold</Text> normal
192
+ * </Text>
193
+ *
194
+ * // Truncation modes
195
+ * <Text wrap="truncate">This long text will be truncated...</Text>
196
+ * <Text wrap="truncate-middle">Long...text</Text>
197
+ *
198
+ * // With ref
199
+ * const textRef = useRef<TextHandle>(null);
200
+ * <Text ref={textRef}>Hello</Text>
201
+ *
202
+ * // With variant — typography presets from theme
203
+ * <Text variant="h1">Page Title</Text>
204
+ * <Text variant="body-muted">Caption text</Text>
205
+ * <Text variant="h1" color="$fg-success">Done</Text> // caller color wins
206
+ * ```
207
+ */
208
+ const Text = forwardRef(function Text(props, ref) {
209
+ const { children, variant, ...callerProps } = props;
210
+ const theme = useContext(ThemeContext);
211
+ let styleProps = callerProps;
212
+ if (variant != null) {
213
+ const resolved = theme.variants?.[variant];
214
+ if (resolved === void 0) warnOnce(theme, variant);
215
+ const variantDefaults = resolved ?? {};
216
+ const definedCallerProps = {};
217
+ for (const key of Object.keys(callerProps)) {
218
+ const v = callerProps[key];
219
+ if (v !== void 0) definedCallerProps[key] = v;
220
+ }
221
+ styleProps = {
222
+ ...callerProps,
223
+ ...variantDefaults,
224
+ ...definedCallerProps
225
+ };
226
+ }
227
+ return /* @__PURE__ */ jsx("silvery-text", {
228
+ ref: (node) => {
229
+ if (typeof ref === "function") ref(node ? { getNode: () => node } : null);
230
+ else if (ref) ref.current = node ? { getNode: () => node } : null;
231
+ },
232
+ ...styleProps,
233
+ children
234
+ });
235
+ });
236
+ //#endregion
237
+ export { Box as a, useTheme as i, ActiveSchemeContext as n, ThemeContext as r, Text as t };
238
+
239
+ //# sourceMappingURL=Text-Lq0dmj8-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Text-Lq0dmj8-.mjs","names":["signalEffect"],"sources":["../packages/ag-react/src/components/Box.tsx","../packages/ag-react/src/ThemeContext.tsx","../packages/ag-react/src/components/Text.tsx"],"sourcesContent":["/**\n * Silvery Box Component\n *\n * The primary layout primitive for Silvery. Box is a flexbox container that can hold\n * other Box or Text components. It supports all standard flexbox properties,\n * dimensions, spacing, and borders.\n *\n * Box renders to an 'silvery-box' host element that the reconciler converts to an\n * SilveryNode with an associated Yoga layout node.\n *\n * Box provides NodeContext to its children, enabling useBoxRect/useScrollRect hooks.\n * It also supports forwardRef for imperative access and onLayout for layout callbacks.\n */\n\nimport {\n type ForwardedRef,\n type JSX,\n type ReactNode,\n forwardRef,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\"\nimport { effect as signalEffect } from \"@silvery/signals\"\nimport { NodeContext } from \"../context\"\nimport { getLayoutSignals, observeLayoutSignal } from \"@silvery/ag/layout-signals\"\nimport type { BoxProps as BoxPropsType, AgNode, Rect } from \"@silvery/ag/types\"\n\n// ============================================================================\n// Props\n// ============================================================================\n\nexport interface BoxProps extends BoxPropsType {\n /** Child elements */\n children?: ReactNode\n}\n\n/**\n * Methods exposed via ref on Box component.\n */\nexport interface BoxHandle {\n /** Get the underlying SilveryNode */\n getNode(): AgNode | null\n /** Get the current content-relative layout rect */\n getBoxRect(): Rect | null\n /** Get the current screen-relative layout rect */\n getScrollRect(): Rect | null\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Flexbox container component for terminal UIs.\n *\n * Provides NodeContext to children, enabling useBoxRect/useScrollRect hooks.\n * Supports forwardRef for imperative access and onLayout for layout callbacks.\n *\n * @example\n * ```tsx\n * // Basic vertical layout (default)\n * <Box>\n * <Text>Line 1</Text>\n * <Text>Line 2</Text>\n * </Box>\n *\n * // Horizontal layout with spacing\n * <Box flexDirection=\"row\" gap={2}>\n * <Box width={10}><Text>Left</Text></Box>\n * <Box flexGrow={1}><Text>Center</Text></Box>\n * <Box width={10}><Text>Right</Text></Box>\n * </Box>\n *\n * // With border\n * <Box borderStyle=\"single\" borderColor=\"green\" padding={1}>\n * <Text>Boxed content</Text>\n * </Box>\n *\n * // With ref and onLayout\n * const boxRef = useRef<BoxHandle>(null);\n * <Box\n * ref={boxRef}\n * onLayout={(layout) => console.log('Size:', layout.width, layout.height)}\n * >\n * <Text>Content</Text>\n * </Box>\n * ```\n */\nexport const Box = forwardRef(function Box(\n props: BoxProps,\n ref: ForwardedRef<BoxHandle>,\n): JSX.Element {\n const { children, onLayout, ...restProps } = props\n const nodeRef = useRef<AgNode | null>(null)\n const [node, setNode] = useState<AgNode | null>(null)\n\n // Track the last layout we reported to onLayout to avoid duplicate calls\n const lastReportedLayout = useRef<Rect | null>(null)\n\n // After mount, ref points to the SilveryNode. Update state once to provide\n // the node to children via context. Only runs on mount ([] deps).\n useLayoutEffect(() => {\n if (nodeRef.current) {\n setNode(nodeRef.current)\n }\n }, [])\n\n // Wire up onLayout callback - subscribe via layout signals\n useLayoutEffect(() => {\n if (!onLayout || !node) return\n\n const releaseObservation = observeLayoutSignal(node, \"boxRect\")\n const signals = getLayoutSignals(node)\n const onLayoutRef = { current: onLayout }\n onLayoutRef.current = onLayout\n\n const dispose = signalEffect(() => {\n const layout = signals.boxRect()\n if (!layout) return\n\n // Only call onLayout if layout actually changed\n const last = lastReportedLayout.current\n if (\n !last ||\n last.x !== layout.x ||\n last.y !== layout.y ||\n last.width !== layout.width ||\n last.height !== layout.height\n ) {\n lastReportedLayout.current = layout\n onLayoutRef.current(layout)\n }\n })\n\n return () => {\n dispose()\n releaseObservation()\n }\n }, [node, onLayout])\n\n // Expose imperative methods via ref\n useImperativeHandle(\n ref,\n () => ({\n getNode: () => nodeRef.current,\n getBoxRect: () => nodeRef.current?.boxRect ?? null,\n getScrollRect: () => nodeRef.current?.scrollRect ?? null,\n }),\n [],\n )\n\n // Render silvery-box with ref, wrap children in NodeContext\n // The reconciler creates an SilveryNode, ref gives us access to it\n return (\n <silvery-box ref={nodeRef} {...restProps}>\n <NodeContext.Provider value={node}>{children}</NodeContext.Provider>\n </silvery-box>\n )\n})\n","/**\n * ThemeContext — delivers a Theme to the component tree.\n *\n * Wrap your app (or a subtree) in `<ThemeProvider theme={…}>` to make\n * `$token` color props resolve against that theme. Components call\n * `useTheme()` to read the current theme.\n *\n * @example\n * ```tsx\n * import { ThemeProvider, defaultDarkTheme } from '@silvery/ag-react'\n *\n * <ThemeProvider theme={defaultDarkTheme}>\n * <App />\n * </ThemeProvider>\n * ```\n */\n\nimport { createContext, useContext } from \"react\"\nimport type { Theme, ActiveScheme } from \"@silvery/ansi\"\nimport { defaultDarkTheme } from \"@silvery/theme/schemes\"\n\n// ============================================================================\n// Context\n// ============================================================================\n\n/** @internal Exported for ThemeProvider and Text component — not public API. */\nexport const ThemeContext = createContext<Theme>(defaultDarkTheme)\n\n/**\n * Context that carries scheme detection metadata (name, source, confidence).\n *\n * Separate from ThemeContext because scheme metadata is orthogonal to the\n * theme token bag. Populated by `<ThemeProvider scheme={...}>` when the\n * caller passes detection provenance (e.g. from `runThemed`). Null when\n * no scheme metadata was injected.\n *\n * @internal Exported for ThemeProvider.\n */\nexport const ActiveSchemeContext = createContext<ActiveScheme | null>(null)\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Read the current theme from context.\n *\n * Returns `defaultDarkTheme` when no `ThemeProvider` is present.\n */\nexport function useTheme(): Theme {\n return useContext(ThemeContext)\n}\n","/**\n * Silvery Text Component\n *\n * The primitive for rendering text content in Silvery. Text supports styling\n * (colors, bold, italic, etc.) and text wrapping/truncation modes.\n *\n * Text renders to an 'silvery-text' host element that the reconciler converts\n * to an SilveryNode containing the text content.\n *\n * Supports forwardRef for imperative access to the underlying node.\n */\n\nimport { type ForwardedRef, type JSX, type ReactNode, forwardRef, useContext } from \"react\"\nimport type { AgNode, TextProps as TextPropsType } from \"@silvery/ag/types\"\nimport type { KnownVariant, Theme } from \"@silvery/ansi\"\nimport { KNOWN_VARIANTS } from \"@silvery/ansi\"\nimport { ThemeContext } from \"../ThemeContext\"\n\n// ============================================================================\n// Runtime variant warning — fires once per (theme, variantName) pair.\n// Warns the developer that a variant lookup returned undefined (typo, etc.).\n// Does NOT throw — silent no-op rendering is still the correct behavior.\n// Only fires in development/test (process.env.NODE_ENV !== \"production\").\n// ============================================================================\n\n/** Per-theme set of variant names that have already triggered a warning. */\nconst _warnedVariants = new WeakMap<Theme, Set<string>>()\n\nfunction warnOnce(theme: Theme, variant: string): void {\n if (process.env.NODE_ENV === \"production\") return\n let warned = _warnedVariants.get(theme)\n if (warned === undefined) {\n warned = new Set<string>()\n _warnedVariants.set(theme, warned)\n }\n if (warned.has(variant)) return\n warned.add(variant)\n const known = KNOWN_VARIANTS.join(\", \")\n // eslint-disable-next-line no-console\n console.warn(\n `[silvery] <Text variant=\"${variant}\"> — unknown variant, defaulting to bare. ` +\n `Known: ${known}. ` +\n `Register custom variants via <ThemeProvider tokens={{ variants: { ${variant}: {...} } }}>.`,\n )\n}\n\n// ============================================================================\n// Props\n// ============================================================================\n\nexport interface TextProps extends TextPropsType {\n /** Text content (string, number, or nested Text elements) */\n children?: ReactNode\n /**\n * Typography variant — pulls defaults from `theme.variants[variant]`.\n * Caller props always win over variant values (variant is the *default*).\n *\n * @example\n * ```tsx\n * <Text variant=\"h1\">Title</Text>\n * // → uses theme.variants.h1 as defaults ({ color: \"$fg-accent\", bold: true })\n *\n * <Text variant=\"h1\" color=\"$fg-success\">Done</Text>\n * // → color=\"$fg-success\" wins; bold still comes from variant\n * ```\n */\n variant?: KnownVariant\n}\n\n/**\n * Methods exposed via ref on Text component.\n */\nexport interface TextHandle {\n /** Get the underlying SilveryNode */\n getNode(): AgNode | null\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Text rendering component for terminal UIs.\n *\n * Supports forwardRef for imperative access to the underlying node.\n *\n * @example\n * ```tsx\n * // Basic text\n * <Text>Hello, world!</Text>\n *\n * // Colored text\n * <Text color=\"green\">Success!</Text>\n * <Text color=\"#ff6600\">Orange text</Text>\n *\n * // Styled text\n * <Text bold>Important</Text>\n * <Text italic underline>Emphasized</Text>\n *\n * // Combined styles\n * <Text color=\"red\" bold inverse>Alert!</Text>\n *\n * // Nested text with different styles\n * <Text>\n * Normal <Text bold>bold</Text> normal\n * </Text>\n *\n * // Truncation modes\n * <Text wrap=\"truncate\">This long text will be truncated...</Text>\n * <Text wrap=\"truncate-middle\">Long...text</Text>\n *\n * // With ref\n * const textRef = useRef<TextHandle>(null);\n * <Text ref={textRef}>Hello</Text>\n *\n * // With variant — typography presets from theme\n * <Text variant=\"h1\">Page Title</Text>\n * <Text variant=\"body-muted\">Caption text</Text>\n * <Text variant=\"h1\" color=\"$fg-success\">Done</Text> // caller color wins\n * ```\n */\nexport const Text = forwardRef(function Text(\n props: TextProps,\n ref: ForwardedRef<TextHandle>,\n): JSX.Element {\n const { children, variant, ...callerProps } = props\n const theme = useContext(ThemeContext)\n\n // Resolve variant defaults. Variant is the DEFAULT; caller props always win.\n //\n // Merge strategy (three passes):\n // 1. callerProps — base layer: all caller props including undefined values\n // (preserves non-style props like wrap, data-*, etc.)\n // 2. variantDefaults — overwrite only where callerProps was undefined\n // (fills in color/bold/etc when caller didn't specify)\n // 3. definedCallerProps — restore any explicitly provided caller overrides\n // (e.g. color=\"$fg-success\", bold={false} win over variant)\n //\n // Example: `<Text variant=\"h1\">T</Text>` (color not passed → undefined)\n // callerProps = { color: undefined }\n // variantDefaults = { color: \"$fg-accent\", bold: true }\n // definedCallerProps = {} (color=undefined excluded)\n // → { color: \"$fg-accent\", bold: true } ✓\n //\n // Example: `<Text variant=\"h1\" color=\"$fg-success\">T</Text>`\n // callerProps = { color: \"$fg-success\" }\n // variantDefaults = { color: \"$fg-accent\", bold: true }\n // definedCallerProps = { color: \"$fg-success\" }\n // → { color: \"$fg-success\", bold: true } ✓ (caller color wins)\n let styleProps = callerProps\n if (variant != null) {\n const resolved = theme.variants?.[variant]\n if (resolved === undefined) {\n warnOnce(theme, variant)\n }\n const variantDefaults = resolved ?? {}\n const definedCallerProps: Record<string, unknown> = {}\n for (const key of Object.keys(callerProps)) {\n const v = (callerProps as Record<string, unknown>)[key]\n if (v !== undefined) definedCallerProps[key] = v\n }\n styleProps = { ...callerProps, ...variantDefaults, ...definedCallerProps } as typeof callerProps\n }\n\n // For Text, we need to pass the ref through to the host element\n // The reconciler's getPublicInstance will return the SilveryNode\n // We wrap it in a TextHandle for type safety\n return (\n <silvery-text\n ref={(node: AgNode | null) => {\n // Handle both callback refs and RefObjects\n if (typeof ref === \"function\") {\n ref(node ? { getNode: () => node } : null)\n } else if (ref) {\n ref.current = node ? { getNode: () => node } : null\n }\n }}\n {...styleProps}\n >\n {children}\n </silvery-text>\n )\n})\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { t as require_UPNG } from "./UPNG-DosRPdF4.mjs";
2
+ export default require_UPNG();
3
+ export {};