aeon-ui-engine 1.0.3 → 1.2.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 (365) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/CONSUMER.md +82 -40
  3. package/README.md +47 -16
  4. package/package.json +9 -2
  5. package/packages/cli/README.md +17 -0
  6. package/packages/cli/dist/bin.d.ts +1 -0
  7. package/packages/cli/dist/bin.js +35 -0
  8. package/packages/cli/dist/chunk-IW5NT2Z2.js +103 -0
  9. package/packages/cli/dist/index.d.ts +10 -0
  10. package/packages/cli/dist/index.js +6 -0
  11. package/packages/cli/node_modules/.bin/esbuild +21 -0
  12. package/packages/cli/node_modules/.bin/jiti +21 -0
  13. package/packages/cli/node_modules/.bin/tsc +21 -0
  14. package/packages/cli/node_modules/.bin/tsserver +21 -0
  15. package/packages/cli/node_modules/.bin/tsup +21 -0
  16. package/packages/cli/node_modules/.bin/tsup-node +21 -0
  17. package/packages/cli/node_modules/.bin/tsx +21 -0
  18. package/packages/cli/node_modules/.bin/vite +21 -0
  19. package/packages/cli/node_modules/.bin/vitest +21 -0
  20. package/packages/cli/package.json +50 -0
  21. package/packages/cli/src/bin.ts +34 -0
  22. package/packages/cli/src/index.ts +1 -0
  23. package/packages/cli/src/init.ts +107 -0
  24. package/packages/cli/tsconfig.json +10 -0
  25. package/packages/core/README.md +7 -1
  26. package/packages/core/dist/index.d.ts +255 -7
  27. package/packages/core/dist/index.js +372 -2
  28. package/packages/core/node_modules/.bin/esbuild +4 -4
  29. package/packages/core/node_modules/.bin/vite +4 -4
  30. package/packages/core/node_modules/.bin/vitest +2 -2
  31. package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  32. package/packages/core/package.json +17 -5
  33. package/packages/core/src/anatomy.ts +234 -5
  34. package/packages/core/src/brand-theme.ts +172 -0
  35. package/packages/core/src/index.ts +1 -0
  36. package/packages/core/src/machine.test.ts +62 -1
  37. package/packages/core/src/machine.ts +93 -0
  38. package/packages/core/src/theme.ts +105 -0
  39. package/packages/panda/aeon.css +8 -0
  40. package/packages/panda/package.json +1 -1
  41. package/packages/panda/panda.config.ts +58 -1
  42. package/packages/panda/src/recipes/app-shell.ts +137 -0
  43. package/packages/panda/src/recipes/avatar.ts +131 -0
  44. package/packages/panda/src/recipes/bar.ts +206 -0
  45. package/packages/panda/src/recipes/button-group.ts +12 -4
  46. package/packages/panda/src/recipes/button.ts +1 -0
  47. package/packages/panda/src/recipes/combobox.ts +2 -1
  48. package/packages/panda/src/recipes/composer.ts +81 -0
  49. package/packages/panda/src/recipes/content.ts +104 -0
  50. package/packages/panda/src/recipes/conversation.ts +106 -0
  51. package/packages/panda/src/recipes/entry.ts +217 -0
  52. package/packages/panda/src/recipes/field.ts +12 -2
  53. package/packages/panda/src/recipes/floating.ts +26 -13
  54. package/packages/panda/src/recipes/identity.ts +73 -0
  55. package/packages/panda/src/recipes/index.ts +15 -0
  56. package/packages/panda/src/recipes/list-row.ts +109 -0
  57. package/packages/panda/src/recipes/metric-strip.ts +80 -0
  58. package/packages/panda/src/recipes/nav.ts +155 -0
  59. package/packages/panda/src/recipes/panel.ts +156 -0
  60. package/packages/panda/src/recipes/pin-input.ts +3 -2
  61. package/packages/panda/src/recipes/profile-header.ts +120 -0
  62. package/packages/panda/src/recipes/select.ts +2 -1
  63. package/packages/panda/src/recipes/slider.ts +6 -4
  64. package/packages/panda/src/recipes/theme-switcher.ts +110 -0
  65. package/packages/panda/src/recipes/thread.ts +88 -0
  66. package/packages/panda/src/theme/catalog-types.ts +2 -0
  67. package/packages/panda/src/theme/catalog.ts +23 -0
  68. package/packages/panda/src/theme/chrome.css +2 -1
  69. package/packages/panda/src/theme/consumer-shell.css +129 -0
  70. package/packages/panda/src/theme/electron.css +30 -0
  71. package/packages/panda/src/theme/global-theme-css.ts +9 -0
  72. package/packages/panda/src/theme/omarchy.themes.ts +607 -0
  73. package/packages/panda/src/theme/palette.ts +3 -0
  74. package/packages/panda/src/theme/scrollbars.css +58 -21
  75. package/packages/panda/src/theme/themes.config.ts +39 -1
  76. package/packages/panda/styled-system/css/conditions.mjs +1 -1
  77. package/packages/panda/styled-system/css/css.mjs +1 -1
  78. package/packages/panda/styled-system/css/sva.mjs +9 -4
  79. package/packages/panda/styled-system/helpers.mjs +11 -22
  80. package/packages/panda/styled-system/jsx/create-style-context.d.ts +54 -0
  81. package/packages/panda/styled-system/jsx/create-style-context.mjs +121 -0
  82. package/packages/panda/styled-system/jsx/factory.mjs +14 -5
  83. package/packages/panda/styled-system/jsx/index.d.ts +1 -0
  84. package/packages/panda/styled-system/jsx/index.mjs +1 -0
  85. package/packages/panda/styled-system/jsx/is-valid-prop.mjs +2 -2
  86. package/packages/panda/styled-system/patterns/aspect-ratio.d.ts +0 -1
  87. package/packages/panda/styled-system/patterns/bleed.d.ts +0 -1
  88. package/packages/panda/styled-system/patterns/box.d.ts +0 -1
  89. package/packages/panda/styled-system/patterns/center.d.ts +0 -1
  90. package/packages/panda/styled-system/patterns/circle.d.ts +0 -1
  91. package/packages/panda/styled-system/patterns/container.d.ts +0 -1
  92. package/packages/panda/styled-system/patterns/cq.d.ts +0 -1
  93. package/packages/panda/styled-system/patterns/divider.d.ts +0 -1
  94. package/packages/panda/styled-system/patterns/flex.d.ts +0 -1
  95. package/packages/panda/styled-system/patterns/float.d.ts +0 -1
  96. package/packages/panda/styled-system/patterns/grid-item.d.ts +0 -1
  97. package/packages/panda/styled-system/patterns/grid.d.ts +0 -1
  98. package/packages/panda/styled-system/patterns/grid.mjs +1 -1
  99. package/packages/panda/styled-system/patterns/hstack.d.ts +0 -1
  100. package/packages/panda/styled-system/patterns/hstack.mjs +1 -1
  101. package/packages/panda/styled-system/patterns/link-overlay.d.ts +0 -1
  102. package/packages/panda/styled-system/patterns/spacer.d.ts +0 -1
  103. package/packages/panda/styled-system/patterns/spacer.mjs +6 -2
  104. package/packages/panda/styled-system/patterns/square.d.ts +0 -1
  105. package/packages/panda/styled-system/patterns/stack.d.ts +0 -1
  106. package/packages/panda/styled-system/patterns/stack.mjs +1 -1
  107. package/packages/panda/styled-system/patterns/visually-hidden.d.ts +0 -1
  108. package/packages/panda/styled-system/patterns/vstack.d.ts +0 -1
  109. package/packages/panda/styled-system/patterns/vstack.mjs +1 -1
  110. package/packages/panda/styled-system/patterns/wrap.d.ts +0 -1
  111. package/packages/panda/styled-system/patterns/wrap.mjs +1 -1
  112. package/packages/panda/styled-system/recipes/aeon-accordion.d.ts +4 -3
  113. package/packages/panda/styled-system/recipes/aeon-accordion.mjs +1 -0
  114. package/packages/panda/styled-system/recipes/aeon-app-shell.d.ts +34 -0
  115. package/packages/panda/styled-system/recipes/aeon-app-shell.mjs +70 -0
  116. package/packages/panda/styled-system/recipes/aeon-async.d.ts +4 -3
  117. package/packages/panda/styled-system/recipes/aeon-async.mjs +1 -0
  118. package/packages/panda/styled-system/recipes/aeon-avatar.d.ts +36 -0
  119. package/packages/panda/styled-system/recipes/aeon-avatar.mjs +57 -0
  120. package/packages/panda/styled-system/recipes/aeon-badge.d.ts +3 -0
  121. package/packages/panda/styled-system/recipes/aeon-bar.d.ts +40 -0
  122. package/packages/panda/styled-system/recipes/aeon-bar.mjs +77 -0
  123. package/packages/panda/styled-system/recipes/aeon-button-group.d.ts +3 -2
  124. package/packages/panda/styled-system/recipes/aeon-button.d.ts +3 -2
  125. package/packages/panda/styled-system/recipes/aeon-checkbox.d.ts +4 -1
  126. package/packages/panda/styled-system/recipes/aeon-checkbox.mjs +1 -0
  127. package/packages/panda/styled-system/recipes/aeon-combobox.d.ts +4 -3
  128. package/packages/panda/styled-system/recipes/aeon-combobox.mjs +1 -0
  129. package/packages/panda/styled-system/recipes/aeon-composer.d.ts +31 -0
  130. package/packages/panda/styled-system/recipes/aeon-composer.mjs +45 -0
  131. package/packages/panda/styled-system/recipes/aeon-content.d.ts +34 -0
  132. package/packages/panda/styled-system/recipes/aeon-content.mjs +70 -0
  133. package/packages/panda/styled-system/recipes/aeon-conversation.d.ts +31 -0
  134. package/packages/panda/styled-system/recipes/aeon-conversation.mjs +61 -0
  135. package/packages/panda/styled-system/recipes/aeon-dialog.d.ts +4 -1
  136. package/packages/panda/styled-system/recipes/aeon-dialog.mjs +1 -0
  137. package/packages/panda/styled-system/recipes/aeon-entry.d.ts +38 -0
  138. package/packages/panda/styled-system/recipes/aeon-entry.mjs +100 -0
  139. package/packages/panda/styled-system/recipes/aeon-field.d.ts +4 -3
  140. package/packages/panda/styled-system/recipes/aeon-field.mjs +1 -0
  141. package/packages/panda/styled-system/recipes/aeon-identity.d.ts +36 -0
  142. package/packages/panda/styled-system/recipes/aeon-identity.mjs +63 -0
  143. package/packages/panda/styled-system/recipes/aeon-list-row.d.ts +33 -0
  144. package/packages/panda/styled-system/recipes/aeon-list-row.mjs +49 -0
  145. package/packages/panda/styled-system/recipes/aeon-menu.d.ts +4 -1
  146. package/packages/panda/styled-system/recipes/aeon-menu.mjs +1 -0
  147. package/packages/panda/styled-system/recipes/aeon-metric-strip.d.ts +36 -0
  148. package/packages/panda/styled-system/recipes/aeon-metric-strip.mjs +54 -0
  149. package/packages/panda/styled-system/recipes/aeon-nav.d.ts +38 -0
  150. package/packages/panda/styled-system/recipes/aeon-nav.mjs +69 -0
  151. package/packages/panda/styled-system/recipes/aeon-panel.d.ts +34 -0
  152. package/packages/panda/styled-system/recipes/aeon-panel.mjs +58 -0
  153. package/packages/panda/styled-system/recipes/aeon-pin-input.d.ts +4 -1
  154. package/packages/panda/styled-system/recipes/aeon-pin-input.mjs +1 -0
  155. package/packages/panda/styled-system/recipes/aeon-popover.d.ts +4 -1
  156. package/packages/panda/styled-system/recipes/aeon-popover.mjs +1 -0
  157. package/packages/panda/styled-system/recipes/aeon-profile-header.d.ts +36 -0
  158. package/packages/panda/styled-system/recipes/aeon-profile-header.mjs +62 -0
  159. package/packages/panda/styled-system/recipes/aeon-progress.d.ts +4 -1
  160. package/packages/panda/styled-system/recipes/aeon-progress.mjs +1 -0
  161. package/packages/panda/styled-system/recipes/aeon-radio-group.d.ts +4 -1
  162. package/packages/panda/styled-system/recipes/aeon-radio-group.mjs +1 -0
  163. package/packages/panda/styled-system/recipes/aeon-scroll.d.ts +4 -3
  164. package/packages/panda/styled-system/recipes/aeon-scroll.mjs +1 -0
  165. package/packages/panda/styled-system/recipes/aeon-select.d.ts +4 -3
  166. package/packages/panda/styled-system/recipes/aeon-select.mjs +1 -0
  167. package/packages/panda/styled-system/recipes/aeon-separator.d.ts +4 -1
  168. package/packages/panda/styled-system/recipes/aeon-separator.mjs +1 -0
  169. package/packages/panda/styled-system/recipes/aeon-slider.d.ts +4 -1
  170. package/packages/panda/styled-system/recipes/aeon-slider.mjs +1 -0
  171. package/packages/panda/styled-system/recipes/aeon-switch.d.ts +4 -1
  172. package/packages/panda/styled-system/recipes/aeon-switch.mjs +1 -0
  173. package/packages/panda/styled-system/recipes/aeon-tabs.d.ts +4 -1
  174. package/packages/panda/styled-system/recipes/aeon-tabs.mjs +1 -0
  175. package/packages/panda/styled-system/recipes/aeon-theme-switcher.d.ts +34 -0
  176. package/packages/panda/styled-system/recipes/aeon-theme-switcher.mjs +59 -0
  177. package/packages/panda/styled-system/recipes/aeon-thread.d.ts +31 -0
  178. package/packages/panda/styled-system/recipes/aeon-thread.mjs +53 -0
  179. package/packages/panda/styled-system/recipes/aeon-toast.d.ts +4 -1
  180. package/packages/panda/styled-system/recipes/aeon-toast.mjs +1 -0
  181. package/packages/panda/styled-system/recipes/aeon-tooltip.d.ts +4 -1
  182. package/packages/panda/styled-system/recipes/aeon-tooltip.mjs +1 -0
  183. package/packages/panda/styled-system/recipes/index.d.ts +16 -1
  184. package/packages/panda/styled-system/recipes/index.mjs +16 -1
  185. package/packages/panda/styled-system/styles.css +2317 -450
  186. package/packages/panda/styled-system/tokens/index.mjs +43 -7
  187. package/packages/panda/styled-system/tokens/tokens.d.ts +5 -5
  188. package/packages/panda/styled-system/types/composition.d.ts +86 -23
  189. package/packages/panda/styled-system/types/conditions.d.ts +34 -10
  190. package/packages/panda/styled-system/types/csstype.d.ts +6405 -5133
  191. package/packages/panda/styled-system/types/jsx.d.ts +27 -10
  192. package/packages/panda/styled-system/types/pattern.d.ts +4 -4
  193. package/packages/panda/styled-system/types/prop-type.d.ts +11 -1
  194. package/packages/panda/styled-system/types/style-props.d.ts +2763 -2165
  195. package/packages/panda/styled-system/types/system-types.d.ts +38 -80
  196. package/packages/panda/theme-runtime.css +945 -0
  197. package/packages/primitives/dist/chunk-4NOKRUSG.js +81 -0
  198. package/packages/primitives/dist/chunk-R25CUHNF.js +46 -0
  199. package/packages/primitives/dist/chunk-RO2DMFN5.js +89 -0
  200. package/packages/primitives/dist/chunk-V5D7LS4J.js +61 -0
  201. package/packages/primitives/dist/chunk-YBPNI2LI.js +70 -0
  202. package/packages/primitives/dist/index.d.ts +5 -0
  203. package/packages/primitives/dist/index.js +46 -14
  204. package/packages/primitives/dist/machines/app-nav.d.ts +96 -0
  205. package/packages/primitives/dist/machines/app-nav.js +12 -0
  206. package/packages/primitives/dist/machines/app-shell.d.ts +57 -0
  207. package/packages/primitives/dist/machines/app-shell.js +8 -0
  208. package/packages/primitives/dist/machines/async.d.ts +4 -4
  209. package/packages/primitives/dist/machines/content-region.d.ts +72 -0
  210. package/packages/primitives/dist/machines/content-region.js +8 -0
  211. package/packages/primitives/dist/machines/panel.d.ts +50 -0
  212. package/packages/primitives/dist/machines/panel.js +6 -0
  213. package/packages/primitives/dist/machines/sticky-bar.d.ts +62 -0
  214. package/packages/primitives/dist/machines/sticky-bar.js +8 -0
  215. package/packages/primitives/node_modules/.bin/esbuild +21 -0
  216. package/packages/primitives/node_modules/.bin/vite +21 -0
  217. package/packages/primitives/node_modules/.bin/vitest +2 -2
  218. package/packages/primitives/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  219. package/packages/primitives/package.json +15 -5
  220. package/packages/primitives/scripts/xstate-introspect.mjs +35 -0
  221. package/packages/primitives/src/__tests__/app-nav.test.ts +30 -0
  222. package/packages/primitives/src/index.ts +5 -0
  223. package/packages/primitives/src/machines/app-nav.ts +107 -0
  224. package/packages/primitives/src/machines/app-shell.ts +63 -0
  225. package/packages/primitives/src/machines/content-region.ts +107 -0
  226. package/packages/primitives/src/machines/panel.ts +71 -0
  227. package/packages/primitives/src/machines/sticky-bar.ts +89 -0
  228. package/packages/react/dist/index.d.ts +536 -17
  229. package/packages/react/dist/index.js +2163 -479
  230. package/packages/react/node_modules/.bin/esbuild +21 -0
  231. package/packages/react/node_modules/.bin/vite +21 -0
  232. package/packages/react/node_modules/.bin/vitest +2 -2
  233. package/packages/react/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  234. package/packages/react/package.json +18 -7
  235. package/packages/react/src/app-nav/index.tsx +249 -0
  236. package/packages/react/src/app-shell/index.tsx +154 -0
  237. package/packages/react/src/async/index.tsx +6 -1
  238. package/packages/react/src/async/map-content-state.ts +18 -0
  239. package/packages/react/src/avatar/index.tsx +23 -1
  240. package/packages/react/src/bar/index.tsx +101 -0
  241. package/packages/react/src/button/index.tsx +4 -2
  242. package/packages/react/src/composer/index.tsx +75 -0
  243. package/packages/react/src/content/index.tsx +149 -0
  244. package/packages/react/src/conversation/index.tsx +78 -0
  245. package/packages/react/src/entry/index.tsx +85 -0
  246. package/packages/react/src/field/index.tsx +31 -18
  247. package/packages/react/src/hooks/use-fit-text.ts +59 -0
  248. package/packages/react/src/identity/index.tsx +110 -0
  249. package/packages/react/src/index.ts +19 -0
  250. package/packages/react/src/list-row/index.tsx +80 -0
  251. package/packages/react/src/metric-strip/index.tsx +88 -0
  252. package/packages/react/src/nav/index.tsx +155 -0
  253. package/packages/react/src/panel/index.tsx +267 -0
  254. package/packages/react/src/profile-header/index.tsx +91 -0
  255. package/packages/react/src/prompt/index.tsx +161 -0
  256. package/packages/react/src/radio-group/index.tsx +19 -7
  257. package/packages/react/src/slider/index.tsx +3 -1
  258. package/packages/react/src/status-banner/index.tsx +84 -0
  259. package/packages/react/src/sticky-bar/index.tsx +135 -0
  260. package/packages/react/src/switch/index.tsx +7 -1
  261. package/packages/react/src/theme-switcher/index.tsx +227 -0
  262. package/packages/react/src/thread/index.tsx +95 -0
  263. package/packages/react/src/toast/primitives.tsx +2 -2
  264. package/packages/react/src/tooltip/tooltip.test.tsx +9 -1
  265. package/packages/react/tsconfig.json +2 -1
  266. package/packages/schemas/README.md +52 -0
  267. package/packages/schemas/dist/index.d.ts +287 -0
  268. package/packages/schemas/dist/index.js +701 -0
  269. package/packages/schemas/json/accordion.json +132 -0
  270. package/packages/schemas/json/async.json +161 -0
  271. package/packages/schemas/json/button.json +170 -0
  272. package/packages/schemas/json/catalog.json +2299 -0
  273. package/packages/schemas/json/checkbox.json +136 -0
  274. package/packages/schemas/json/combobox.json +130 -0
  275. package/packages/schemas/json/dialog.json +154 -0
  276. package/packages/schemas/json/field.json +171 -0
  277. package/packages/schemas/json/menu.json +138 -0
  278. package/packages/schemas/json/popover.json +133 -0
  279. package/packages/schemas/json/progress.json +137 -0
  280. package/packages/schemas/json/scroll.json +129 -0
  281. package/packages/schemas/json/select.json +140 -0
  282. package/packages/schemas/json/switch.json +136 -0
  283. package/packages/schemas/json/tabs.json +135 -0
  284. package/packages/schemas/json/toast.json +141 -0
  285. package/packages/schemas/json/tooltip.json +123 -0
  286. package/packages/schemas/node_modules/.bin/esbuild +21 -0
  287. package/packages/schemas/node_modules/.bin/jiti +21 -0
  288. package/packages/schemas/node_modules/.bin/tsc +21 -0
  289. package/packages/schemas/node_modules/.bin/tsserver +21 -0
  290. package/packages/schemas/node_modules/.bin/tsup +21 -0
  291. package/packages/schemas/node_modules/.bin/tsup-node +21 -0
  292. package/packages/schemas/node_modules/.bin/tsx +21 -0
  293. package/packages/schemas/node_modules/.bin/vite +21 -0
  294. package/packages/schemas/node_modules/.bin/vitest +21 -0
  295. package/packages/schemas/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  296. package/packages/schemas/package.json +56 -0
  297. package/packages/schemas/prompts/cursorrules.md +64 -0
  298. package/packages/schemas/prompts/statecharts.md +31 -0
  299. package/packages/schemas/prompts/system.md +30 -0
  300. package/packages/schemas/registry/catalog.json +54 -0
  301. package/packages/schemas/registry/components/accordion.json +132 -0
  302. package/packages/schemas/registry/components/async.json +161 -0
  303. package/packages/schemas/registry/components/button.json +170 -0
  304. package/packages/schemas/registry/components/checkbox.json +136 -0
  305. package/packages/schemas/registry/components/combobox.json +130 -0
  306. package/packages/schemas/registry/components/dialog.json +154 -0
  307. package/packages/schemas/registry/components/field.json +171 -0
  308. package/packages/schemas/registry/components/menu.json +138 -0
  309. package/packages/schemas/registry/components/popover.json +133 -0
  310. package/packages/schemas/registry/components/progress.json +137 -0
  311. package/packages/schemas/registry/components/scroll.json +129 -0
  312. package/packages/schemas/registry/components/select.json +140 -0
  313. package/packages/schemas/registry/components/switch.json +136 -0
  314. package/packages/schemas/registry/components/tabs.json +135 -0
  315. package/packages/schemas/registry/components/toast.json +141 -0
  316. package/packages/schemas/registry/components/tooltip.json +123 -0
  317. package/packages/schemas/registry/machines/async.json +219 -0
  318. package/packages/schemas/registry/machines/buttonLifecycle.json +224 -0
  319. package/packages/schemas/registry/machines/dialog.json +143 -0
  320. package/packages/schemas/registry/machines/field.json +275 -0
  321. package/packages/schemas/scripts/emit.ts +61 -0
  322. package/packages/schemas/src/aeon-to-schema.test.ts +70 -0
  323. package/packages/schemas/src/aeon-to-schema.ts +206 -0
  324. package/packages/schemas/src/agent-bridge.ts +82 -0
  325. package/packages/schemas/src/components.ts +307 -0
  326. package/packages/schemas/src/index.test.ts +25 -0
  327. package/packages/schemas/src/index.ts +25 -0
  328. package/packages/schemas/src/prompts.ts +121 -0
  329. package/packages/schemas/src/registry.ts +73 -0
  330. package/packages/schemas/src/schema-builder.ts +87 -0
  331. package/packages/schemas/tsconfig.json +9 -0
  332. package/packages/solid/package.json +2 -2
  333. package/packages/svelte/node_modules/.bin/esbuild +21 -0
  334. package/packages/svelte/node_modules/.bin/vite +4 -4
  335. package/packages/svelte/package.json +15 -5
  336. package/packages/ui/README.md +19 -6
  337. package/packages/ui/dist/index.d.ts +254 -9
  338. package/packages/ui/dist/index.js +690 -139
  339. package/packages/ui/src/app-nav.tsx +2 -0
  340. package/packages/ui/src/app-shell.tsx +44 -0
  341. package/packages/ui/src/async.tsx +2 -1
  342. package/packages/ui/src/avatar.tsx +35 -0
  343. package/packages/ui/src/bar.tsx +34 -0
  344. package/packages/ui/src/composer.tsx +27 -0
  345. package/packages/ui/src/content.tsx +43 -0
  346. package/packages/ui/src/conversation.tsx +43 -0
  347. package/packages/ui/src/entry.tsx +76 -0
  348. package/packages/ui/src/field.tsx +5 -0
  349. package/packages/ui/src/identity.tsx +35 -0
  350. package/packages/ui/src/index.ts +20 -0
  351. package/packages/ui/src/list-row.tsx +30 -0
  352. package/packages/ui/src/metric-strip.tsx +29 -0
  353. package/packages/ui/src/nav.tsx +46 -0
  354. package/packages/ui/src/panel.tsx +39 -0
  355. package/packages/ui/src/profile-header.tsx +35 -0
  356. package/packages/ui/src/prompt.tsx +29 -0
  357. package/packages/ui/src/status-banner.tsx +1 -0
  358. package/packages/ui/src/sticky-bar.tsx +42 -0
  359. package/packages/ui/src/switch.tsx +17 -4
  360. package/packages/ui/src/theme-switcher.tsx +41 -0
  361. package/packages/ui/src/thread.tsx +35 -0
  362. package/packages/vue/package.json +3 -3
  363. package/scripts/vite-aliases.mjs +65 -3
  364. package/scripts/xstate-introspect.mjs +68 -0
  365. package/packages/react/src/async/legacy-region.tsx +0 -38
@@ -0,0 +1,101 @@
1
+ import { barAnatomy, partAttrs, scopeAttrs } from '@aeon-ui/core'
2
+ import { createContext, forwardRef, type HTMLAttributes } from 'react'
3
+ import { mergeProps } from '../utils/merge-props.js'
4
+
5
+ /* ------------------------------------------------------------------ */
6
+ /* Context */
7
+ /* ------------------------------------------------------------------ */
8
+
9
+ interface BarContextValue {
10
+ gap?: string
11
+ }
12
+
13
+ const BarContext = createContext<BarContextValue>({})
14
+
15
+ /* ------------------------------------------------------------------ */
16
+ /* Root */
17
+ /* ------------------------------------------------------------------ */
18
+
19
+ export interface BarRootProps extends HTMLAttributes<HTMLDivElement> {
20
+ /** HTML element to render — defaults to `'header'`. */
21
+ as?: 'header' | 'nav' | 'footer' | 'div'
22
+ /** Flex gap between zones. */
23
+ gap?: string
24
+ }
25
+
26
+ const Root = forwardRef<HTMLDivElement, BarRootProps>(function BarRoot(
27
+ { as: Tag = 'header', gap, children, ...rest },
28
+ ref,
29
+ ) {
30
+ return (
31
+ <BarContext.Provider value={{ gap }}>
32
+ <Tag
33
+ ref={ref as never}
34
+ {...mergeProps(scopeAttrs(barAnatomy.scope, barAnatomy.root), rest)}
35
+ >
36
+ {children}
37
+ </Tag>
38
+ </BarContext.Provider>
39
+ )
40
+ })
41
+
42
+ /* ------------------------------------------------------------------ */
43
+ /* Zone (Leading / Center / Trailing) */
44
+ /* ------------------------------------------------------------------ */
45
+
46
+ type Zone = 'leading' | 'center' | 'trailing'
47
+
48
+ interface ZoneProps extends HTMLAttributes<HTMLDivElement> {
49
+ /** Which zone — controls flex behavior. */
50
+ zone: Zone
51
+ }
52
+
53
+ const Zone = forwardRef<HTMLDivElement, ZoneProps>(function BarZone(
54
+ { zone, children, ...rest },
55
+ ref,
56
+ ) {
57
+ return (
58
+ <div
59
+ ref={ref}
60
+ {...mergeProps(partAttrs(barAnatomy.scope, zone), rest)}
61
+ >
62
+ {children}
63
+ </div>
64
+ )
65
+ })
66
+
67
+ /* ------------------------------------------------------------------ */
68
+ /* Public API */
69
+ /* ------------------------------------------------------------------ */
70
+
71
+ /**
72
+ * Bar — horizontal layout primitive for toolbars, headers, footers.
73
+ *
74
+ * Guarantees no overlap by enforcing a three-zone flex contract:
75
+ * - **Leading** — `flex: 0 1 auto`, shrinks before overflowing.
76
+ * - **Center** — `flex: 1 1 0`, absorbs available space, truncates.
77
+ * - **Trailing** — `flex: 0 1 auto`, shrinks before overflowing.
78
+ *
79
+ * The root is always `display: flex; flex-wrap: nowrap` with
80
+ * `overflow: hidden` so children can never escape the bar boundary.
81
+ * Responsive collapse is handled by the Panda recipe (min-widths, wrap
82
+ * at breakpoints) — never by ad-hoc CSS.
83
+ */
84
+ export const Bar = {
85
+ Root,
86
+ Leading: forwardRef<HTMLDivElement, Omit<ZoneProps, 'zone'>>(
87
+ function BarLeading(props, ref) {
88
+ return <Zone ref={ref} zone="leading" {...props} />
89
+ },
90
+ ),
91
+ Center: forwardRef<HTMLDivElement, Omit<ZoneProps, 'zone'>>(
92
+ function BarCenter(props, ref) {
93
+ return <Zone ref={ref} zone="center" {...props} />
94
+ },
95
+ ),
96
+ Trailing: forwardRef<HTMLDivElement, Omit<ZoneProps, 'zone'>>(
97
+ function BarTrailing(props, ref) {
98
+ return <Zone ref={ref} zone="trailing" {...props} />
99
+ },
100
+ ),
101
+ }
@@ -19,12 +19,14 @@ const Root = forwardRef<HTMLButtonElement, ButtonRootProps>(function ButtonRoot(
19
19
  ) {
20
20
  const resolvedStatus: ButtonStatus = disabled ? 'disabled' : status
21
21
  const isBusy = resolvedStatus === 'pending'
22
+ // Success is terminal until RESET — keep data-aeon-state="success" but block input.
23
+ const isLocked = resolvedStatus === 'success'
22
24
 
23
25
  return (
24
26
  <button
25
27
  ref={ref}
26
28
  type="button"
27
- disabled={disabled || isBusy || resolvedStatus === 'disabled'}
29
+ disabled={disabled || isBusy || isLocked || resolvedStatus === 'disabled'}
28
30
  aria-busy={isBusy || undefined}
29
31
  className={className}
30
32
  data-aeon-variant={variant}
@@ -32,7 +34,7 @@ const Root = forwardRef<HTMLButtonElement, ButtonRootProps>(function ButtonRoot(
32
34
  {...mergeProps(
33
35
  partAttrs(buttonAnatomy.scope, buttonAnatomy.root, {
34
36
  state: resolvedStatus,
35
- disabled: Boolean(disabled || resolvedStatus === 'disabled'),
37
+ disabled: Boolean(disabled || resolvedStatus === 'disabled' || isLocked),
36
38
  }),
37
39
  rest,
38
40
  )}
@@ -0,0 +1,75 @@
1
+ import { composerAnatomy, partAttrs, scopeAttrs } from '@aeon-ui/core'
2
+ import {
3
+ forwardRef,
4
+ type FormHTMLAttributes,
5
+ type HTMLAttributes,
6
+ type ReactNode,
7
+ type TextareaHTMLAttributes,
8
+ } from 'react'
9
+ import { mergeProps } from '../utils/merge-props.js'
10
+
11
+ export type ComposerState = 'idle' | 'sending' | 'disabled' | 'error'
12
+
13
+ export interface ComposerRootProps extends FormHTMLAttributes<HTMLFormElement> {
14
+ state?: ComposerState
15
+ children?: ReactNode
16
+ }
17
+
18
+ /**
19
+ * Composer — bottom compose chrome for threads (input + send).
20
+ * Root state: idle | sending | disabled | error.
21
+ */
22
+ const Root = forwardRef<HTMLFormElement, ComposerRootProps>(function ComposerRoot(
23
+ { state = 'idle', children, ...rest },
24
+ ref,
25
+ ) {
26
+ return (
27
+ <form
28
+ ref={ref}
29
+ {...mergeProps(scopeAttrs(composerAnatomy.scope, composerAnatomy.root, { state }), rest)}
30
+ >
31
+ {children}
32
+ </form>
33
+ )
34
+ })
35
+
36
+ const Input = forwardRef<HTMLTextAreaElement, TextareaHTMLAttributes<HTMLTextAreaElement>>(
37
+ function ComposerInput(props, ref) {
38
+ return (
39
+ <textarea
40
+ ref={ref}
41
+ rows={1}
42
+ {...mergeProps(partAttrs(composerAnatomy.scope, composerAnatomy.input), props)}
43
+ />
44
+ )
45
+ },
46
+ )
47
+
48
+ const Actions = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
49
+ function ComposerActions(props, ref) {
50
+ return (
51
+ <div
52
+ ref={ref}
53
+ {...mergeProps(partAttrs(composerAnatomy.scope, composerAnatomy.actions), props)}
54
+ />
55
+ )
56
+ },
57
+ )
58
+
59
+ const Send = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(
60
+ function ComposerSend(props, ref) {
61
+ return (
62
+ <span
63
+ ref={ref}
64
+ {...mergeProps(partAttrs(composerAnatomy.scope, composerAnatomy.send), props)}
65
+ />
66
+ )
67
+ },
68
+ )
69
+
70
+ export const Composer = {
71
+ Root,
72
+ Input,
73
+ Actions,
74
+ Send,
75
+ }
@@ -0,0 +1,149 @@
1
+ import { contentAnatomy, partAttrs, scopeAttrs } from '@aeon-ui/core'
2
+ import { contentRegionMachine, type ContentRegionState } from '@aeon-ui/primitives'
3
+ import {
4
+ createContext,
5
+ forwardRef,
6
+ useContext,
7
+ useMemo,
8
+ type HTMLAttributes,
9
+ type ReactNode,
10
+ } from 'react'
11
+ import { useAeonMachine } from '../hooks/use-aeon-machine.js'
12
+ import { mergeProps } from '../utils/merge-props.js'
13
+
14
+ interface ContentContextValue {
15
+ state: ContentRegionState
16
+ error: string | null
17
+ send: ReturnType<typeof useAeonMachine<typeof contentRegionMachine>>[1]
18
+ }
19
+
20
+ const ContentCtx = createContext<ContentContextValue | null>(null)
21
+
22
+ export function useContentContext() {
23
+ const ctx = useContext(ContentCtx)
24
+ if (!ctx) throw new Error('Content parts must be used within Content.Root')
25
+ return ctx
26
+ }
27
+
28
+ export interface ContentRootProps extends HTMLAttributes<HTMLDivElement> {
29
+ /**
30
+ * Controlled face — projects parent/app machine onto Content slots
31
+ * (same pattern as Button `status`). When set, slot visibility uses this
32
+ * value instead of the internal contentRegionMachine leaf.
33
+ */
34
+ state?: ContentRegionState
35
+ children?: ReactNode
36
+ }
37
+
38
+ const Root = forwardRef<HTMLDivElement, ContentRootProps>(function ContentRoot(
39
+ { state: stateProp, children, ...rest },
40
+ ref,
41
+ ) {
42
+ const [snapshot, send] = useAeonMachine(contentRegionMachine)
43
+ const machineState = snapshot.value as ContentRegionState
44
+ const state = stateProp ?? machineState
45
+ const value = useMemo(
46
+ () => ({ state, error: snapshot.context.error, send }),
47
+ [state, snapshot.context.error, send],
48
+ )
49
+
50
+ return (
51
+ <ContentCtx.Provider value={value}>
52
+ <div
53
+ ref={ref}
54
+ {...mergeProps(scopeAttrs(contentAnatomy.scope, contentAnatomy.root, { state }), rest)}
55
+ >
56
+ {children}
57
+ </div>
58
+ </ContentCtx.Provider>
59
+ )
60
+ })
61
+
62
+ const Toolbar = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function ContentToolbar(
63
+ props,
64
+ ref,
65
+ ) {
66
+ const { state } = useContentContext()
67
+ return (
68
+ <div
69
+ ref={ref}
70
+ {...mergeProps(partAttrs(contentAnatomy.scope, contentAnatomy.toolbar, { state }), props)}
71
+ />
72
+ )
73
+ })
74
+
75
+ /** Primary body — shown when state is ready | loadingMore | success (and optionally idle). */
76
+ const Body = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function ContentBody(
77
+ { hidden, ...rest },
78
+ ref,
79
+ ) {
80
+ const { state } = useContentContext()
81
+ const show = state === 'ready' || state === 'loadingMore' || state === 'success' || state === 'idle'
82
+ if (!show) return null
83
+ return (
84
+ <div
85
+ ref={ref}
86
+ hidden={hidden}
87
+ {...mergeProps(partAttrs(contentAnatomy.scope, contentAnatomy.body, { state }), rest)}
88
+ />
89
+ )
90
+ })
91
+
92
+ function StatusSlot(
93
+ part: string,
94
+ match: ContentRegionState | ContentRegionState[],
95
+ displayName: string,
96
+ ) {
97
+ const matches = Array.isArray(match) ? match : [match]
98
+ const Comp = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function ContentStatusSlot(
99
+ props,
100
+ ref,
101
+ ) {
102
+ const { state } = useContentContext()
103
+ if (!matches.includes(state)) return null
104
+ return (
105
+ <div
106
+ ref={ref}
107
+ role="status"
108
+ {...mergeProps(partAttrs(contentAnatomy.scope, part, { state }), props)}
109
+ />
110
+ )
111
+ })
112
+ Comp.displayName = displayName
113
+ return Comp
114
+ }
115
+
116
+ const Pending = StatusSlot(contentAnatomy.pending, 'pending', 'Content.Pending')
117
+ const Empty = StatusSlot(contentAnatomy.empty, 'empty', 'Content.Empty')
118
+ const ErrorSlot = StatusSlot(contentAnatomy.error, 'error', 'Content.Error')
119
+ const Success = StatusSlot(contentAnatomy.success, 'success', 'Content.Success')
120
+
121
+ const Sentinel = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function ContentSentinel(
122
+ props,
123
+ ref,
124
+ ) {
125
+ const { state } = useContentContext()
126
+ if (state !== 'ready' && state !== 'loadingMore') return null
127
+ return (
128
+ <div
129
+ ref={ref}
130
+ {...mergeProps(partAttrs(contentAnatomy.scope, contentAnatomy.sentinel, { state }), props)}
131
+ />
132
+ )
133
+ })
134
+
135
+ /**
136
+ * Content — status-slotted region. Machine totality maps 1:1 onto parts.
137
+ * States: idle | pending | empty | error | ready | loadingMore | success
138
+ * Drive via contentRegionMachine events, or project with Root `state` prop.
139
+ */
140
+ export const Content = {
141
+ Root,
142
+ Toolbar,
143
+ Body,
144
+ Pending,
145
+ Empty,
146
+ Error: ErrorSlot,
147
+ Success,
148
+ Sentinel,
149
+ }
@@ -0,0 +1,78 @@
1
+ import { conversationAnatomy, partAttrs, scopeAttrs } from '@aeon-ui/core'
2
+ import { forwardRef, type ButtonHTMLAttributes, type HTMLAttributes, type ReactNode } from 'react'
3
+ import { mergeProps } from '../utils/merge-props.js'
4
+
5
+ export type ConversationItemState = 'idle' | 'unread' | 'selected'
6
+
7
+ export interface ConversationRootProps extends HTMLAttributes<HTMLElement> {
8
+ children?: ReactNode
9
+ }
10
+
11
+ /**
12
+ * Conversation — inbox / DM list (universal messaging chrome).
13
+ * Item states: idle | unread | selected.
14
+ */
15
+ const Root = forwardRef<HTMLElement, ConversationRootProps>(function ConversationRoot(
16
+ { children, ...rest },
17
+ ref,
18
+ ) {
19
+ return (
20
+ <div
21
+ ref={ref as never}
22
+ {...mergeProps(scopeAttrs(conversationAnatomy.scope, conversationAnatomy.root), rest)}
23
+ >
24
+ {children}
25
+ </div>
26
+ )
27
+ })
28
+
29
+ export interface ConversationItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {
30
+ state?: ConversationItemState
31
+ as?: 'button' | 'div' | 'a'
32
+ }
33
+
34
+ const Item = forwardRef<HTMLElement, ConversationItemProps>(function ConversationItem(
35
+ { state = 'idle', as: Tag = 'button', type, children, ...rest },
36
+ ref,
37
+ ) {
38
+ const buttonType = Tag === 'button' ? (type ?? 'button') : undefined
39
+ return (
40
+ <Tag
41
+ ref={ref as never}
42
+ type={buttonType as never}
43
+ {...mergeProps(
44
+ partAttrs(conversationAnatomy.scope, conversationAnatomy.item, { state }),
45
+ rest,
46
+ )}
47
+ >
48
+ {children}
49
+ </Tag>
50
+ )
51
+ })
52
+
53
+ function Part(part: string, displayName: string) {
54
+ const Comp = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(function ConversationPart(
55
+ props,
56
+ ref,
57
+ ) {
58
+ return (
59
+ <span
60
+ ref={ref}
61
+ {...mergeProps(partAttrs(conversationAnatomy.scope, part), props)}
62
+ />
63
+ )
64
+ })
65
+ Comp.displayName = displayName
66
+ return Comp
67
+ }
68
+
69
+ export const Conversation = {
70
+ Root,
71
+ Item,
72
+ Leading: Part(conversationAnatomy.leading, 'Conversation.Leading'),
73
+ Body: Part(conversationAnatomy.body, 'Conversation.Body'),
74
+ Title: Part(conversationAnatomy.title, 'Conversation.Title'),
75
+ Preview: Part(conversationAnatomy.preview, 'Conversation.Preview'),
76
+ Meta: Part(conversationAnatomy.meta, 'Conversation.Meta'),
77
+ Badge: Part(conversationAnatomy.badge, 'Conversation.Badge'),
78
+ }
@@ -0,0 +1,85 @@
1
+ import { entryAnatomy, partAttrs, scopeAttrs } from '@aeon-ui/core'
2
+ import { forwardRef, type HTMLAttributes, type ReactNode } from 'react'
3
+ import { mergeProps } from '../utils/merge-props.js'
4
+
5
+ /** Card face — idle resting · selected highlight · muted de-emphasized. */
6
+ export type EntryState = 'idle' | 'selected' | 'muted'
7
+
8
+ export interface EntryListProps extends HTMLAttributes<HTMLDivElement> {
9
+ children?: ReactNode
10
+ }
11
+
12
+ /**
13
+ * Entry — compact multi-value content card.
14
+ * Compose feed posts, listings, and activity rows from the same zones.
15
+ * Machine: none (layout). Root projects idle | selected | muted.
16
+ */
17
+ const List = forwardRef<HTMLDivElement, EntryListProps>(function EntryList(
18
+ { children, ...rest },
19
+ ref,
20
+ ) {
21
+ return (
22
+ <div
23
+ ref={ref}
24
+ {...mergeProps(scopeAttrs(entryAnatomy.scope, entryAnatomy.list), rest)}
25
+ >
26
+ {children}
27
+ </div>
28
+ )
29
+ })
30
+
31
+ export interface EntryRootProps extends HTMLAttributes<HTMLElement> {
32
+ as?: 'article' | 'div' | 'li' | 'section'
33
+ state?: EntryState
34
+ children?: ReactNode
35
+ }
36
+
37
+ const Root = forwardRef<HTMLElement, EntryRootProps>(function EntryRoot(
38
+ { as: Tag = 'article', state = 'idle', children, ...rest },
39
+ ref,
40
+ ) {
41
+ return (
42
+ <Tag
43
+ ref={ref as never}
44
+ {...mergeProps(scopeAttrs(entryAnatomy.scope, entryAnatomy.root, { state }), rest)}
45
+ >
46
+ {children}
47
+ </Tag>
48
+ )
49
+ })
50
+
51
+ function Part(
52
+ part: string,
53
+ displayName: string,
54
+ defaultTag: 'div' | 'span' | 'header' | 'footer' | 'p' = 'div',
55
+ ) {
56
+ const Comp = forwardRef<HTMLElement, HTMLAttributes<HTMLElement> & { as?: typeof defaultTag }>(
57
+ function EntryPart({ as: Tag = defaultTag, ...props }, ref) {
58
+ return (
59
+ <Tag
60
+ ref={ref as never}
61
+ {...mergeProps(partAttrs(entryAnatomy.scope, part), props)}
62
+ />
63
+ )
64
+ },
65
+ )
66
+ Comp.displayName = displayName
67
+ return Comp
68
+ }
69
+
70
+ export const Entry = {
71
+ List,
72
+ Root,
73
+ Header: Part(entryAnatomy.header, 'Entry.Header', 'header'),
74
+ Leading: Part(entryAnatomy.leading, 'Entry.Leading', 'div'),
75
+ Heading: Part(entryAnatomy.heading, 'Entry.Heading', 'div'),
76
+ Title: Part(entryAnatomy.title, 'Entry.Title', 'div'),
77
+ Subtitle: Part(entryAnatomy.subtitle, 'Entry.Subtitle', 'div'),
78
+ Meta: Part(entryAnatomy.meta, 'Entry.Meta', 'span'),
79
+ Media: Part(entryAnatomy.media, 'Entry.Media', 'div'),
80
+ Body: Part(entryAnatomy.body, 'Entry.Body', 'div'),
81
+ Values: Part(entryAnatomy.values, 'Entry.Values', 'div'),
82
+ Value: Part(entryAnatomy.value, 'Entry.Value', 'span'),
83
+ Actions: Part(entryAnatomy.actions, 'Entry.Actions', 'div'),
84
+ Footer: Part(entryAnatomy.footer, 'Entry.Footer', 'footer'),
85
+ }
@@ -1,4 +1,4 @@
1
- import { fieldAnatomy, partAttrs, partOnlyAttrs, stateToAttr } from '@aeon-ui/core'
1
+ import { fieldAnatomy, fieldFace, fieldRegions, partAttrs, partOnlyAttrs } from '@aeon-ui/core'
2
2
  import { fieldMachine } from '@aeon-ui/primitives'
3
3
  import {
4
4
  createContext,
@@ -16,7 +16,13 @@ import { useAeonMachine } from '../hooks/use-aeon-machine.js'
16
16
  import { mergeProps } from '../utils/merge-props.js'
17
17
 
18
18
  interface FieldContextValue {
19
+ /** Primary visual face — idle | dirty | invalid | pending (same hierarchy as Button). */
20
+ face: ReturnType<typeof fieldFace>
21
+ /** @deprecated Use `face` — kept as an alias for older callers. */
19
22
  stateAttr: string
23
+ interaction: string
24
+ validation: string
25
+ submission: string
20
26
  send: ReturnType<typeof useAeonMachine<typeof fieldMachine>>[1]
21
27
  invalid: boolean
22
28
  pending: boolean
@@ -41,21 +47,23 @@ const Root = forwardRef<HTMLDivElement, FieldRootProps>(function FieldRoot(
41
47
  ref,
42
48
  ) {
43
49
  const [snapshot, send] = useAeonMachine(fieldMachine)
44
- const stateAttr = stateToAttr(snapshot.value)
45
- const invalid =
46
- typeof snapshot.value === 'object' &&
47
- snapshot.value !== null &&
48
- 'validation' in snapshot.value &&
49
- (snapshot.value as { validation: string }).validation === 'invalid'
50
- const pending =
51
- typeof snapshot.value === 'object' &&
52
- snapshot.value !== null &&
53
- 'submission' in snapshot.value &&
54
- (snapshot.value as { submission: string }).submission === 'pending'
50
+ const face = fieldFace(snapshot.value)
51
+ const regions = fieldRegions(snapshot.value)
52
+ const invalid = regions.validation === 'invalid'
53
+ const pending = regions.submission === 'pending'
55
54
 
56
55
  const value = useMemo(
57
- () => ({ stateAttr, send, invalid, pending }),
58
- [stateAttr, send, invalid, pending],
56
+ () => ({
57
+ face,
58
+ stateAttr: face,
59
+ interaction: regions.interaction,
60
+ validation: regions.validation,
61
+ submission: regions.submission,
62
+ send,
63
+ invalid,
64
+ pending,
65
+ }),
66
+ [face, regions.interaction, regions.validation, regions.submission, send, invalid, pending],
59
67
  )
60
68
 
61
69
  return (
@@ -64,7 +72,10 @@ const Root = forwardRef<HTMLDivElement, FieldRootProps>(function FieldRoot(
64
72
  ref={ref}
65
73
  id={id}
66
74
  className={className}
67
- {...partAttrs(fieldAnatomy.scope, fieldAnatomy.root, { state: stateAttr })}
75
+ data-aeon-interaction={regions.interaction}
76
+ data-aeon-validation={regions.validation}
77
+ data-aeon-submission={regions.submission}
78
+ {...partAttrs(fieldAnatomy.scope, fieldAnatomy.root, { state: face })}
68
79
  >
69
80
  {children}
70
81
  </div>
@@ -148,7 +159,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, FieldTextareaProps>(function Fi
148
159
  })
149
160
 
150
161
  const Message = forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
151
- function FieldMessage(props, ref) {
162
+ function FieldMessage({ children, ...props }, ref) {
152
163
  const { invalid } = useFieldContext()
153
164
  if (!invalid) return null
154
165
  return (
@@ -157,7 +168,9 @@ const Message = forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagr
157
168
  role="alert"
158
169
  {...partOnlyAttrs(fieldAnatomy.message, { state: 'invalid' })}
159
170
  {...props}
160
- />
171
+ >
172
+ {children ?? 'Check this field.'}
173
+ </p>
161
174
  )
162
175
  },
163
176
  )
@@ -168,5 +181,5 @@ const Hint = forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraph
168
181
  },
169
182
  )
170
183
 
171
- export const Field = { Root, Label, Control, Textarea, Message, Hint }
184
+ export const Field = { Root, Label, Control, Input: Control, Textarea, Message, Hint }
172
185
  export { fieldMachine }
@@ -0,0 +1,59 @@
1
+ import { useLayoutEffect, type RefObject } from 'react'
2
+
3
+ export type FitTextOptions = {
4
+ maxPx?: number
5
+ minPx?: number
6
+ /** Re-run when this value changes (e.g. display string). */
7
+ watch?: unknown
8
+ }
9
+
10
+ /**
11
+ * Shrink font-size (then scale) so `contentRef` fits inside `slotRef`
12
+ * without expanding parent layout. Universal for balance rows, titles, tickers.
13
+ */
14
+ export function useFitText(
15
+ slotRef: RefObject<HTMLElement | null>,
16
+ contentRef: RefObject<HTMLElement | null>,
17
+ opts: FitTextOptions = {},
18
+ ) {
19
+ const maxPx = opts.maxPx ?? 28
20
+ const minPx = opts.minPx ?? 8
21
+ const watch = opts.watch
22
+
23
+ useLayoutEffect(() => {
24
+ const slot = slotRef.current
25
+ const content = contentRef.current
26
+ if (!slot || !content) return
27
+
28
+ const fit = () => {
29
+ const available = slot.clientWidth
30
+ if (available <= 0) return
31
+
32
+ content.style.transform = ''
33
+ content.style.transformOrigin = ''
34
+ content.style.fontSize = `${maxPx}px`
35
+
36
+ let size = maxPx
37
+ while (size > minPx && content.scrollWidth > available + 0.5) {
38
+ size -= 0.5
39
+ content.style.fontSize = `${size}px`
40
+ }
41
+
42
+ if (content.scrollWidth > available + 0.5) {
43
+ const scale = Math.max(0.35, available / content.scrollWidth)
44
+ content.style.transformOrigin = 'center center'
45
+ content.style.transform = `scale(${scale})`
46
+ }
47
+ }
48
+
49
+ fit()
50
+ const ro = new ResizeObserver(fit)
51
+ ro.observe(slot)
52
+ return () => {
53
+ ro.disconnect()
54
+ content.style.fontSize = ''
55
+ content.style.transform = ''
56
+ content.style.transformOrigin = ''
57
+ }
58
+ }, [slotRef, contentRef, maxPx, minPx, watch])
59
+ }