@evinvest/uikit 0.30.0 → 0.32.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 (403) hide show
  1. package/README.md +267 -73
  2. package/dist/{chunk-3IPB4QQJ.js → chunk-35SPIU4U.js} +10 -6
  3. package/dist/chunk-35SPIU4U.js.map +1 -0
  4. package/dist/components/{accordion.js → atomic/accordion.js} +3 -3
  5. package/dist/components/atomic/accordion.js.map +1 -0
  6. package/dist/components/{alert-dialog.js → atomic/alert-dialog.js} +11 -10
  7. package/dist/components/atomic/alert-dialog.js.map +1 -0
  8. package/dist/components/{alert.js → atomic/alert.js} +2 -2
  9. package/dist/components/atomic/alert.js.map +1 -0
  10. package/dist/components/atomic/animated-number-columns.js +105 -0
  11. package/dist/components/atomic/animated-number-columns.js.map +1 -0
  12. package/dist/components/{avatar.js → atomic/avatar.js} +2 -2
  13. package/dist/components/atomic/avatar.js.map +1 -0
  14. package/dist/components/{badge.js → atomic/badge.js} +4 -4
  15. package/dist/components/atomic/badge.js.map +1 -0
  16. package/dist/components/{band.js → atomic/band.js} +2 -2
  17. package/dist/components/atomic/band.js.map +1 -0
  18. package/dist/components/{breadcrumb.js → atomic/breadcrumb.js} +3 -3
  19. package/dist/components/atomic/breadcrumb.js.map +1 -0
  20. package/dist/components/{button-group.js → atomic/button-group.js} +3 -3
  21. package/dist/components/atomic/button-group.js.map +1 -0
  22. package/dist/components/{button.js → atomic/button.js} +7 -15
  23. package/dist/components/atomic/button.js.map +1 -0
  24. package/dist/components/{calendar.js → atomic/calendar.js} +2 -2
  25. package/dist/components/atomic/calendar.js.map +1 -0
  26. package/dist/components/{card.js → atomic/card.js} +2 -2
  27. package/dist/components/atomic/card.js.map +1 -0
  28. package/dist/components/{checkbox.js → atomic/checkbox.js} +4 -4
  29. package/dist/components/atomic/checkbox.js.map +1 -0
  30. package/dist/components/{collapsible.js → atomic/collapsible.js} +1 -1
  31. package/dist/components/atomic/collapsible.js.map +1 -0
  32. package/dist/components/{command.js → atomic/command.js} +9 -7
  33. package/dist/components/atomic/command.js.map +1 -0
  34. package/dist/components/{container.js → atomic/container.js} +2 -2
  35. package/dist/components/atomic/container.js.map +1 -0
  36. package/dist/components/{context-menu.js → atomic/context-menu.js} +62 -14
  37. package/dist/components/atomic/context-menu.js.map +1 -0
  38. package/dist/components/{dialog.js → atomic/dialog.js} +11 -10
  39. package/dist/components/atomic/dialog.js.map +1 -0
  40. package/dist/components/{drawer.js → atomic/drawer.js} +10 -8
  41. package/dist/components/atomic/drawer.js.map +1 -0
  42. package/dist/components/{dropdown-menu.js → atomic/dropdown-menu.js} +74 -15
  43. package/dist/components/atomic/dropdown-menu.js.map +1 -0
  44. package/dist/components/{empty.js → atomic/empty.js} +2 -2
  45. package/dist/components/atomic/empty.js.map +1 -0
  46. package/dist/components/atomic/field-context.js.map +1 -0
  47. package/dist/components/atomic/form-row.js +51 -0
  48. package/dist/components/atomic/form-row.js.map +1 -0
  49. package/dist/components/{hover-card.js → atomic/hover-card.js} +8 -8
  50. package/dist/components/atomic/hover-card.js.map +1 -0
  51. package/dist/components/{info-tip.js → atomic/info-tip.js} +10 -10
  52. package/dist/components/atomic/info-tip.js.map +1 -0
  53. package/dist/components/{input-otp.js → atomic/input-otp.js} +3 -3
  54. package/dist/components/atomic/input-otp.js.map +1 -0
  55. package/dist/components/{input.js → atomic/input.js} +3 -3
  56. package/dist/components/atomic/input.js.map +1 -0
  57. package/dist/components/{kbd.js → atomic/kbd.js} +2 -2
  58. package/dist/components/atomic/kbd.js.map +1 -0
  59. package/dist/components/atomic/key-value.js +68 -0
  60. package/dist/components/atomic/key-value.js.map +1 -0
  61. package/dist/components/{label.js → atomic/label.js} +2 -2
  62. package/dist/components/atomic/label.js.map +1 -0
  63. package/dist/components/{menubar.js → atomic/menubar.js} +48 -14
  64. package/dist/components/atomic/menubar.js.map +1 -0
  65. package/dist/components/{native-select.js → atomic/native-select.js} +6 -7
  66. package/dist/components/atomic/native-select.js.map +1 -0
  67. package/dist/components/{navigation-menu.js → atomic/navigation-menu.js} +11 -12
  68. package/dist/components/atomic/navigation-menu.js.map +1 -0
  69. package/dist/components/{pagination.js → atomic/pagination.js} +1 -1
  70. package/dist/components/atomic/pagination.js.map +1 -0
  71. package/dist/components/{popover.js → atomic/popover.js} +10 -10
  72. package/dist/components/atomic/popover.js.map +1 -0
  73. package/dist/components/{progress.js → atomic/progress.js} +2 -2
  74. package/dist/components/atomic/progress.js.map +1 -0
  75. package/dist/components/{radio-group.js → atomic/radio-group.js} +4 -4
  76. package/dist/components/atomic/radio-group.js.map +1 -0
  77. package/dist/components/{scroll-area.js → atomic/scroll-area.js} +2 -2
  78. package/dist/components/atomic/scroll-area.js.map +1 -0
  79. package/dist/components/{section-descriptor.js → atomic/section-descriptor.js} +2 -2
  80. package/dist/components/atomic/section-descriptor.js.map +1 -0
  81. package/dist/components/{select-listbox.js → atomic/select-listbox.js} +1 -1
  82. package/dist/components/atomic/select-listbox.js.map +1 -0
  83. package/dist/components/{select.js → atomic/select.js} +26 -16
  84. package/dist/components/atomic/select.js.map +1 -0
  85. package/dist/components/{separator.js → atomic/separator.js} +2 -2
  86. package/dist/components/atomic/separator.js.map +1 -0
  87. package/dist/components/{sheet.js → atomic/sheet.js} +11 -10
  88. package/dist/components/atomic/sheet.js.map +1 -0
  89. package/dist/components/{sidebar.js → atomic/sidebar.js} +5 -5
  90. package/dist/components/atomic/sidebar.js.map +1 -0
  91. package/dist/components/{skeleton.js → atomic/skeleton.js} +2 -2
  92. package/dist/components/atomic/skeleton.js.map +1 -0
  93. package/dist/components/{slider.js → atomic/slider.js} +3 -3
  94. package/dist/components/atomic/slider.js.map +1 -0
  95. package/dist/components/{sonner.js → atomic/sonner.js} +2 -2
  96. package/dist/components/atomic/sonner.js.map +1 -0
  97. package/dist/components/{spinner.js → atomic/spinner.js} +1 -1
  98. package/dist/components/atomic/spinner.js.map +1 -0
  99. package/dist/components/atomic/status-item.js +42 -0
  100. package/dist/components/atomic/status-item.js.map +1 -0
  101. package/dist/components/{switch.js → atomic/switch.js} +4 -4
  102. package/dist/components/atomic/switch.js.map +1 -0
  103. package/dist/components/{table.js → atomic/table.js} +2 -2
  104. package/dist/components/atomic/table.js.map +1 -0
  105. package/dist/components/{tabs.js → atomic/tabs.js} +4 -4
  106. package/dist/components/atomic/tabs.js.map +1 -0
  107. package/dist/components/{textarea.js → atomic/textarea.js} +3 -3
  108. package/dist/components/atomic/textarea.js.map +1 -0
  109. package/dist/components/{toggle-group.js → atomic/toggle-group.js} +2 -2
  110. package/dist/components/atomic/toggle-group.js.map +1 -0
  111. package/dist/components/{toggle.js → atomic/toggle.js} +3 -3
  112. package/dist/components/atomic/toggle.js.map +1 -0
  113. package/dist/components/{tooltip.js → atomic/tooltip.js} +8 -8
  114. package/dist/components/atomic/tooltip.js.map +1 -0
  115. package/dist/components/atomic/use-count-tween.js +42 -0
  116. package/dist/components/atomic/use-count-tween.js.map +1 -0
  117. package/dist/components/derived/animated-number.js +157 -0
  118. package/dist/components/derived/animated-number.js.map +1 -0
  119. package/dist/components/{carousel.js → derived/carousel.js} +4 -4
  120. package/dist/components/derived/carousel.js.map +1 -0
  121. package/dist/components/derived/command-palette.js +119 -0
  122. package/dist/components/derived/command-palette.js.map +1 -0
  123. package/dist/components/derived/confirm-dialog.js +123 -0
  124. package/dist/components/derived/confirm-dialog.js.map +1 -0
  125. package/dist/components/{date-time-picker.js → derived/date-time-picker.js} +8 -8
  126. package/dist/components/derived/date-time-picker.js.map +1 -0
  127. package/dist/components/{field.js → derived/field.js} +6 -6
  128. package/dist/components/derived/field.js.map +1 -0
  129. package/dist/components/{form.js → derived/form.js} +4 -4
  130. package/dist/components/derived/form.js.map +1 -0
  131. package/dist/components/derived/icon-button.js +35 -0
  132. package/dist/components/derived/icon-button.js.map +1 -0
  133. package/dist/components/{input-group.js → derived/input-group.js} +5 -5
  134. package/dist/components/derived/input-group.js.map +1 -0
  135. package/dist/components/{item.js → derived/item.js} +4 -4
  136. package/dist/components/derived/item.js.map +1 -0
  137. package/dist/components/derived/popover-form.js +60 -0
  138. package/dist/components/derived/popover-form.js.map +1 -0
  139. package/dist/components/derived/settings.js +94 -0
  140. package/dist/components/derived/settings.js.map +1 -0
  141. package/dist/components/shell/account-list.js +128 -0
  142. package/dist/components/shell/account-list.js.map +1 -0
  143. package/dist/components/shell/account-menu-profile.js +114 -0
  144. package/dist/components/shell/account-menu-profile.js.map +1 -0
  145. package/dist/components/shell/account-menu.js +97 -0
  146. package/dist/components/shell/account-menu.js.map +1 -0
  147. package/dist/components/shell/account-settings-dialog.js +84 -0
  148. package/dist/components/shell/account-settings-dialog.js.map +1 -0
  149. package/dist/components/{app-shell.js → shell/app-shell.js} +10 -1
  150. package/dist/components/shell/app-shell.js.map +1 -0
  151. package/dist/components/shell/aside.js +140 -0
  152. package/dist/components/shell/aside.js.map +1 -0
  153. package/dist/components/{auth-wall.js → shell/auth-wall.js} +1 -1
  154. package/dist/components/shell/auth-wall.js.map +1 -0
  155. package/dist/components/{bottom-tab-bar.js → shell/bottom-tab-bar.js} +1 -1
  156. package/dist/components/shell/bottom-tab-bar.js.map +1 -0
  157. package/dist/components/shell/chat-composer.js +141 -0
  158. package/dist/components/shell/chat-composer.js.map +1 -0
  159. package/dist/components/shell/chat-message.js +195 -0
  160. package/dist/components/shell/chat-message.js.map +1 -0
  161. package/dist/components/shell/chat-panel.js +137 -0
  162. package/dist/components/shell/chat-panel.js.map +1 -0
  163. package/dist/components/shell/chat-stream-text.js +69 -0
  164. package/dist/components/shell/chat-stream-text.js.map +1 -0
  165. package/dist/components/shell/chat-typing.js +26 -0
  166. package/dist/components/shell/chat-typing.js.map +1 -0
  167. package/dist/components/{footer.js → shell/footer.js} +1 -1
  168. package/dist/components/shell/footer.js.map +1 -0
  169. package/dist/components/shell/header-controls.js +149 -0
  170. package/dist/components/shell/header-controls.js.map +1 -0
  171. package/dist/components/{list-rows.js → shell/list-rows.js} +1 -1
  172. package/dist/components/shell/list-rows.js.map +1 -0
  173. package/dist/components/{logo.js → shell/logo.js} +1 -1
  174. package/dist/components/shell/logo.js.map +1 -0
  175. package/dist/components/{mobile-app-bar.js → shell/mobile-app-bar.js} +1 -1
  176. package/dist/components/shell/mobile-app-bar.js.map +1 -0
  177. package/dist/components/{nav-badge.js → shell/nav-badge.js} +1 -1
  178. package/dist/components/shell/nav-badge.js.map +1 -0
  179. package/dist/components/shell/nav-collapse.js +142 -0
  180. package/dist/components/shell/nav-collapse.js.map +1 -0
  181. package/dist/components/shell/nav-link.js.map +1 -0
  182. package/dist/components/shell/nav-model.js.map +1 -0
  183. package/dist/components/{page-frame.js → shell/page-frame.js} +3 -6
  184. package/dist/components/shell/page-frame.js.map +1 -0
  185. package/dist/components/{resource-error.js → shell/resource-error.js} +4 -4
  186. package/dist/components/shell/resource-error.js.map +1 -0
  187. package/dist/components/shell/section-nav.js +139 -0
  188. package/dist/components/shell/section-nav.js.map +1 -0
  189. package/dist/components/shell/settled.js.map +1 -0
  190. package/dist/components/shell/shell-icons.js.map +1 -0
  191. package/dist/components/{shell-nav.js → shell/shell-nav.js} +81 -39
  192. package/dist/components/shell/shell-nav.js.map +1 -0
  193. package/dist/components/shell/smart-header.js +53 -0
  194. package/dist/components/shell/smart-header.js.map +1 -0
  195. package/dist/components/{status-screen.js → shell/status-screen.js} +3 -3
  196. package/dist/components/shell/status-screen.js.map +1 -0
  197. package/dist/components/{system-banner.js → shell/system-banner.js} +23 -13
  198. package/dist/components/shell/system-banner.js.map +1 -0
  199. package/dist/components/{top-bar.js → shell/top-bar.js} +5 -4
  200. package/dist/components/shell/top-bar.js.map +1 -0
  201. package/dist/components/shell/use-shell-nav.js.map +1 -0
  202. package/dist/components/shell/workspace-tab.js +140 -0
  203. package/dist/components/shell/workspace-tab.js.map +1 -0
  204. package/dist/generated/accent.js +2 -2
  205. package/dist/generated/accent.js.map +1 -1
  206. package/dist/generated/account-list.js +35 -0
  207. package/dist/generated/account-list.js.map +1 -0
  208. package/dist/generated/account-settings-dialog.js +27 -0
  209. package/dist/generated/account-settings-dialog.js.map +1 -0
  210. package/dist/generated/alert-dialog.js +1 -1
  211. package/dist/generated/alert-dialog.js.map +1 -1
  212. package/dist/generated/alert.js +2 -2
  213. package/dist/generated/alert.js.map +1 -1
  214. package/dist/generated/aside.js +36 -0
  215. package/dist/generated/aside.js.map +1 -0
  216. package/dist/generated/badge.js +7 -6
  217. package/dist/generated/badge.js.map +1 -1
  218. package/dist/generated/band.js +1 -1
  219. package/dist/generated/band.js.map +1 -1
  220. package/dist/generated/breadcrumb.js +2 -2
  221. package/dist/generated/breadcrumb.js.map +1 -1
  222. package/dist/generated/button-group.js +2 -2
  223. package/dist/generated/button-group.js.map +1 -1
  224. package/dist/generated/button.js +4 -4
  225. package/dist/generated/button.js.map +1 -1
  226. package/dist/generated/card.js +6 -6
  227. package/dist/generated/card.js.map +1 -1
  228. package/dist/generated/chat-composer.js +21 -0
  229. package/dist/generated/chat-composer.js.map +1 -0
  230. package/dist/generated/chat-message.js +86 -0
  231. package/dist/generated/chat-message.js.map +1 -0
  232. package/dist/generated/chat-typing.js +9 -0
  233. package/dist/generated/chat-typing.js.map +1 -0
  234. package/dist/generated/command-palette.js +17 -0
  235. package/dist/generated/command-palette.js.map +1 -0
  236. package/dist/generated/command.js +2 -2
  237. package/dist/generated/command.js.map +1 -1
  238. package/dist/generated/confirm-dialog.js +28 -0
  239. package/dist/generated/confirm-dialog.js.map +1 -0
  240. package/dist/generated/context-menu.js +1 -1
  241. package/dist/generated/context-menu.js.map +1 -1
  242. package/dist/generated/date-time-picker.js +1 -1
  243. package/dist/generated/date-time-picker.js.map +1 -1
  244. package/dist/generated/dialog.js +1 -1
  245. package/dist/generated/dialog.js.map +1 -1
  246. package/dist/generated/drawer.js +1 -1
  247. package/dist/generated/drawer.js.map +1 -1
  248. package/dist/generated/dropdown-menu.js +1 -1
  249. package/dist/generated/dropdown-menu.js.map +1 -1
  250. package/dist/generated/form-row.js +17 -0
  251. package/dist/generated/form-row.js.map +1 -0
  252. package/dist/generated/header-controls.js +56 -0
  253. package/dist/generated/header-controls.js.map +1 -0
  254. package/dist/generated/icon-button.js +13 -0
  255. package/dist/generated/icon-button.js.map +1 -0
  256. package/dist/generated/key-value.js +15 -0
  257. package/dist/generated/key-value.js.map +1 -0
  258. package/dist/generated/menubar.js +1 -1
  259. package/dist/generated/menubar.js.map +1 -1
  260. package/dist/generated/navigation-menu.js +1 -1
  261. package/dist/generated/navigation-menu.js.map +1 -1
  262. package/dist/generated/popover-form.js +13 -0
  263. package/dist/generated/popover-form.js.map +1 -0
  264. package/dist/generated/section-label.js +10 -0
  265. package/dist/generated/section-label.js.map +1 -0
  266. package/dist/generated/select.js +15 -3
  267. package/dist/generated/select.js.map +1 -1
  268. package/dist/generated/settings.js +36 -0
  269. package/dist/generated/settings.js.map +1 -0
  270. package/dist/generated/sheet.js +1 -1
  271. package/dist/generated/sheet.js.map +1 -1
  272. package/dist/generated/slider.js +1 -1
  273. package/dist/generated/slider.js.map +1 -1
  274. package/dist/generated/smart-header.js +11 -0
  275. package/dist/generated/smart-header.js.map +1 -0
  276. package/dist/generated/sonner.js +4 -4
  277. package/dist/generated/sonner.js.map +1 -1
  278. package/dist/generated/status-item.js +17 -0
  279. package/dist/generated/status-item.js.map +1 -0
  280. package/dist/generated/system-banner.js +33 -0
  281. package/dist/generated/system-banner.js.map +1 -0
  282. package/dist/generated/top-bar.js +9 -0
  283. package/dist/generated/top-bar.js.map +1 -0
  284. package/dist/generated/workspace-tab.js +17 -0
  285. package/dist/generated/workspace-tab.js.map +1 -0
  286. package/dist/icons/select-chevron.js.map +1 -0
  287. package/dist/icons/ui-icons.js +77 -0
  288. package/dist/icons/ui-icons.js.map +1 -0
  289. package/dist/index.d.ts +852 -156
  290. package/dist/index.js +96 -76
  291. package/dist/lib/cn.js +8 -1
  292. package/dist/lib/cn.js.map +1 -1
  293. package/dist/lib/number-parts.js +90 -0
  294. package/dist/lib/number-parts.js.map +1 -0
  295. package/dist/palette-cli.js +1 -1
  296. package/dist/palette.d.ts +6 -4
  297. package/dist/palette.js +3 -1
  298. package/dist/primitives/dismissable-layer.js +76 -4
  299. package/dist/primitives/dismissable-layer.js.map +1 -1
  300. package/dist/primitives/focus-scope.js +20 -5
  301. package/dist/primitives/focus-scope.js.map +1 -1
  302. package/dist/primitives/use-floating.js +16 -1
  303. package/dist/primitives/use-floating.js.map +1 -1
  304. package/dist/primitives/use-reduced-motion.js +20 -0
  305. package/dist/primitives/use-reduced-motion.js.map +1 -0
  306. package/package.json +2 -2
  307. package/styles/ev.css +281 -49
  308. package/styles/theme.css +335 -39
  309. package/styles/tokens.css +643 -103
  310. package/dist/chunk-3IPB4QQJ.js.map +0 -1
  311. package/dist/components/accordion.js.map +0 -1
  312. package/dist/components/account-menu.js +0 -70
  313. package/dist/components/account-menu.js.map +0 -1
  314. package/dist/components/alert-dialog.js.map +0 -1
  315. package/dist/components/alert.js.map +0 -1
  316. package/dist/components/app-shell.js.map +0 -1
  317. package/dist/components/auth-wall.js.map +0 -1
  318. package/dist/components/avatar.js.map +0 -1
  319. package/dist/components/badge.js.map +0 -1
  320. package/dist/components/band.js.map +0 -1
  321. package/dist/components/bottom-tab-bar.js.map +0 -1
  322. package/dist/components/breadcrumb.js.map +0 -1
  323. package/dist/components/button-group.js.map +0 -1
  324. package/dist/components/button.js.map +0 -1
  325. package/dist/components/calendar.js.map +0 -1
  326. package/dist/components/card.js.map +0 -1
  327. package/dist/components/carousel.js.map +0 -1
  328. package/dist/components/checkbox.js.map +0 -1
  329. package/dist/components/collapsible.js.map +0 -1
  330. package/dist/components/command.js.map +0 -1
  331. package/dist/components/container.js.map +0 -1
  332. package/dist/components/context-menu.js.map +0 -1
  333. package/dist/components/date-time-picker.js.map +0 -1
  334. package/dist/components/dialog.js.map +0 -1
  335. package/dist/components/drawer.js.map +0 -1
  336. package/dist/components/dropdown-menu.js.map +0 -1
  337. package/dist/components/empty.js.map +0 -1
  338. package/dist/components/field-context.js.map +0 -1
  339. package/dist/components/field.js.map +0 -1
  340. package/dist/components/footer.js.map +0 -1
  341. package/dist/components/form.js.map +0 -1
  342. package/dist/components/hover-card.js.map +0 -1
  343. package/dist/components/info-tip.js.map +0 -1
  344. package/dist/components/input-group.js.map +0 -1
  345. package/dist/components/input-otp.js.map +0 -1
  346. package/dist/components/input.js.map +0 -1
  347. package/dist/components/item.js.map +0 -1
  348. package/dist/components/kbd.js.map +0 -1
  349. package/dist/components/label.js.map +0 -1
  350. package/dist/components/list-rows.js.map +0 -1
  351. package/dist/components/logo.js.map +0 -1
  352. package/dist/components/menubar.js.map +0 -1
  353. package/dist/components/mobile-app-bar.js.map +0 -1
  354. package/dist/components/native-select.js.map +0 -1
  355. package/dist/components/nav-badge.js.map +0 -1
  356. package/dist/components/nav-link.js.map +0 -1
  357. package/dist/components/nav-model.js.map +0 -1
  358. package/dist/components/navigation-menu.js.map +0 -1
  359. package/dist/components/page-frame.js.map +0 -1
  360. package/dist/components/pagination.js.map +0 -1
  361. package/dist/components/popover.js.map +0 -1
  362. package/dist/components/progress.js.map +0 -1
  363. package/dist/components/radio-group.js.map +0 -1
  364. package/dist/components/resource-error.js.map +0 -1
  365. package/dist/components/scroll-area.js.map +0 -1
  366. package/dist/components/section-descriptor.js.map +0 -1
  367. package/dist/components/section-nav.js +0 -86
  368. package/dist/components/section-nav.js.map +0 -1
  369. package/dist/components/select-chevron.js.map +0 -1
  370. package/dist/components/select-listbox.js.map +0 -1
  371. package/dist/components/select.js.map +0 -1
  372. package/dist/components/separator.js.map +0 -1
  373. package/dist/components/settled.js.map +0 -1
  374. package/dist/components/sheet.js.map +0 -1
  375. package/dist/components/shell-icons.js.map +0 -1
  376. package/dist/components/shell-nav.js.map +0 -1
  377. package/dist/components/sidebar.js.map +0 -1
  378. package/dist/components/skeleton.js.map +0 -1
  379. package/dist/components/slider.js.map +0 -1
  380. package/dist/components/sonner.js.map +0 -1
  381. package/dist/components/spinner.js.map +0 -1
  382. package/dist/components/status-screen.js.map +0 -1
  383. package/dist/components/switch.js.map +0 -1
  384. package/dist/components/system-banner.js.map +0 -1
  385. package/dist/components/table.js.map +0 -1
  386. package/dist/components/tabs.js.map +0 -1
  387. package/dist/components/terminal.js +0 -206
  388. package/dist/components/terminal.js.map +0 -1
  389. package/dist/components/textarea.js.map +0 -1
  390. package/dist/components/toggle-group.js.map +0 -1
  391. package/dist/components/toggle.js.map +0 -1
  392. package/dist/components/tooltip.js.map +0 -1
  393. package/dist/components/top-bar.js.map +0 -1
  394. package/dist/components/use-shell-nav.js.map +0 -1
  395. package/dist/generated/terminal.js +0 -70
  396. package/dist/generated/terminal.js.map +0 -1
  397. /package/dist/components/{field-context.js → atomic/field-context.js} +0 -0
  398. /package/dist/components/{nav-link.js → shell/nav-link.js} +0 -0
  399. /package/dist/components/{nav-model.js → shell/nav-model.js} +0 -0
  400. /package/dist/components/{settled.js → shell/settled.js} +0 -0
  401. /package/dist/components/{shell-icons.js → shell/shell-icons.js} +0 -0
  402. /package/dist/components/{use-shell-nav.js → shell/use-shell-nav.js} +0 -0
  403. /package/dist/{components → icons}/select-chevron.js +0 -0
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @evinvest/uikit
2
2
 
3
3
  A **dep-light** React UI kit with shadcn-style semantics — the TypeScript mirror
4
- of the UI kit of the [`ev_lib`](https://github.com/EV-invest/lib) Rust crate,
4
+ of the UI kit of the [`ev_lib`](https://github.com/EV-Main/web_std) Rust crate,
5
5
  which ships it for Dioxus (`ev_lib::uikit_dioxus`) and Leptos
6
6
  (`ev_lib::uikit_leptos`) over one framework-free core. All three are driven from
7
7
  the same canonical class strings and the same design tokens, so a component
@@ -60,14 +60,23 @@ your Tailwind v4 entrypoint — this is the load-bearing part of the kit:
60
60
 
61
61
  | group | names |
62
62
  |---|---|
63
- | scope | `:root` · `[data-brand="…"]` — a theme root; `.light` · `.dark` — a polarity beneath it |
64
- | surfaces | `background` `card` `popover` `muted` `hover` |
65
- | ink | `ink` `ink-mid` `ink-soft` — hierarchy, loudest first |
66
- | lines | `border` `input` `ring` |
67
- | roles | `brand` `primary` `secondary` `positive` `accent-trace` `accent-debug` `accent-info` `accent-warn` `accent-error`, each with `on-*` where it gets filled; `primary-ink` — the primary role as ink on a surface (`#128377` fill under a white `on-primary`, `#2a9d8f` ink); `accent-error-ink` — the error role as text on its own tint (derived, a palette may pin it) |
68
- | scalars | `radius` `control-radius` `control-py` `display-scale` `band-py` `page-max` `page-px` `shell-rail-w` `shell-tab-bar-h` `shadow-*` `font-*` |
63
+ | scope | `:root` · `[data-brand="…"]` — a theme root; `.light` · `.dark` — a polarity beneath it; `[data-theme="oldschool"]` — EV's navy look |
64
+ | surfaces | `background` (page) · `card` (surface) · `secondary` (raised) · `popover` (overlay) · `muted` (inset, input fill) |
65
+ | states | `hover` · `active` · `selected` — translucent tints; `scrim` — behind a modal |
66
+ | ink | `ink` · `ink-mid` · `ink-soft` — hierarchy, loudest first; `ink-faint` — disabled only |
67
+ | lines | `border-subtle` (row rule) · `border` (hairline, 14 %) · `border-strong` (state and overlay edges) · `input` (control edge, ≥ 3:1) · `ring` |
68
+ | roles | `brand` `primary` `secondary` `positive` `accent-trace` `accent-debug` `accent-info` `accent-warn` `accent-error`, each with `on-*` where it gets filled; `primary-ink` — the primary role as ink on a surface; `primary-hover` · `primary-border` — the primary button's states |
69
+ | status inks | `positive-ink` · `accent-info-ink` — a quiet status role as text on a surface (derived, a palette may pin them); warn and error text wears `accent-warn` · `accent-error` itself, held to 3:1 |
70
+ | faces | `button-danger-*` (`bg` `hover` `border` `ink`) — the destructive `Button`; `chip-{neutral,primary,positive,info,warn,error}-{bg,border}` — the `Badge`; `button-primary-*` — no kit component paints it; derived for a brand, pinned per theme by EV |
71
+ | type | `text-caption` 11/14 · `body-s` 12/16 · `body` 13/18 · `body-l` 14/20 · `h3` 14/20 · `h2` 24/30 · `h1` 32/38 · `figure-m` 20/24 · `figure-l` 28/32 (size and line height each) |
72
+ | scalars | `radius` (panel, 6 px) · `control-radius` (4 px) · `chip-radius` (4 px) · `depth-card` `depth-elevated` `depth-overlay` · `control-py` `display-scale` `band-py` `page-max` `page-px` `shell-rail-w` `shell-tab-bar-h` · `font-*` |
69
73
  | motion | `ev-ease-out` `ev-ease-in-out` `ev-dur-fast` `ev-dur-base` `ev-dur-slow` `ev-rise` `ev-stagger` `ev-stagger-section` |
70
- | charts | `chart-1` … `chart-5` |
74
+ | charts | `chart-1` … `chart-6` |
75
+
76
+ A palette owes **29 names**: the colours that are not derived, which is every
77
+ role and surface above plus `chart-1` … `chart-6`. The states, lines, inks,
78
+ status inks, faces and chips are derived from them with formulas, so a brand
79
+ file that pins none of them still renders.
71
80
 
72
81
  Custom properties inherit, so a scope class on a `<section>` re-themes its
73
82
  subtree — `bg-card text-ink` is correct on both polarities with no prop. That is
@@ -81,14 +90,38 @@ polarity — so `on-{role}` exists exactly there.
81
90
 
82
91
  A fill and an ink are different jobs, and `primary` is the one role that
83
92
  names them separately: `primary` is the fill (`bg-primary text-on-primary` on
84
- a button, a checked switch or checkbox — `#128377`, white reads on it at
85
- 4.63:1 and it clears 3:1 against `background`, `secondary`, `card` and
86
- `popover`) and `primary-ink` is the same hue as ink (`text-primary-ink` on a
87
- link or eyebrow, a radio dot, a slider range, `border-primary-ink` on a checked
88
- outline, the focus `ring` — `#2a9d8f`, 5.85:1 on `background`, 4.72:1 on
89
- `card`). Every other role holds its own label and reads as ink with one value.
90
- A consumer sheet must define `--primary-ink`; see
91
- [`docs/spec/accents.md`](../../docs/spec/accents.md).
93
+ a primary button, a checked switch or checkbox — `#138377`, white reads on it at
94
+ 4.62:1 and it clears 3:1 against every plane) and `primary-ink` is the same hue
95
+ as ink (`text-primary-ink` on a link or eyebrow, a radio dot, a slider range,
96
+ the focus `ring` — `#35a395` in Dark, `#116f65` in Light). The status roles
97
+ follow the same rule with their `-ink` values. A consumer sheet must define
98
+ `--primary-ink`; see [`docs/spec/accents.md`](../../docs/spec/accents.md).
99
+
100
+ ### Themes
101
+
102
+ EV ships three, each a zero-specificity rule that pins every EV token:
103
+
104
+ | theme | how to switch | look |
105
+ |---|---|---|
106
+ | **Dark** (default) | nothing: no class, no attribute | near-black neutrals, warm ink, one teal accent, flat |
107
+ | **Light** | `class="light"` on `<html>` or on any wrapper | warm paper planes, same shapes |
108
+ | **Oldschool** | `data-theme="oldschool"` on `<html>` or on any wrapper | the navy look: radius 8 / control 6 / pill chips, tinted chips, real shadows |
109
+
110
+ Dark and Light are flat: depth is surface steps and hairlines, and the
111
+ `--depth-*` tiers behind `shadow-card`, `shadow-elevated` and `shadow-overlay`
112
+ are a zero shadow. Oldschool gives them back.
113
+
114
+ Scoping works the way the polarity classes always did. A `.light` or
115
+ `[data-theme="oldschool"]` wrapper inside a Dark page takes its own full token
116
+ set; a `.light` or `.dark` inside an Oldschool region also takes Oldschool.
117
+ EV's rules do not match inside a `[data-brand]` scope or on its element, so a
118
+ brand's own `.light` and `.dark` never pick EV's values up. Keep `data-theme`
119
+ and `data-brand` on separate elements. For a side-by-side view give each scoped
120
+ wrapper its own `PortalProvider` container so overlays stay inside the scope.
121
+
122
+ The planes sit only 1.04–1.14:1 apart on purpose, so what separates them is the
123
+ `--border` hairline (measured 1.37–1.46:1 on Dark, 1.35:1 on Light). Do not lift
124
+ a plane to chase the ratio; see [`docs/spec/accents.md`](../../docs/spec/accents.md).
92
125
 
93
126
  Accents are decorative and **ordered by significance**, quiet to loud. Pick a
94
127
  rung by how loud the thing should be, never by what it means; see
@@ -106,29 +139,29 @@ It has two halves, each also shipped as a flat sheet of its own —
106
139
  `styles/theme.css` (the contract) and `styles/ev.css` (EV's palette):
107
140
 
108
141
  - **the contract** — the `@theme inline` mapping, the geometry, and the tokens
109
- *derived* from a palette (`hover`, `ink-mid`, `ink-soft`, `border`, `input`
110
- from `ink`; `ring` from `primary-ink`; `accent-error-ink` from `accent-error`
111
- and `ink`). The derived ones are redeclared on
112
- `:root`, `[data-brand]`, `.light` and `.dark` at zero specificity, so a brand
113
- scope gets its own borders, hover and focus ring rather than inheriting the
114
- root's, and a palette may still pin any of them outright. The geometry
115
- (`radius`, `page-px`, `band-py`, …) and its responsive scale-ups restart on
116
- every `[data-brand]` the same way.
117
- - **EV's palette** — a single dark palette on `:where(:root, [data-brand="ev"])`.
118
- It binds neither polarity class, so a `.dark` section inside another brand
119
- never picks EV's values up, and `<Section polarity="light">` under EV is a
120
- no-op (EV is single-polarity).
142
+ *derived* from a palette (`hover` `active` `selected` `border-*` `ink-mid`
143
+ `ink-soft` `ink-faint` `input` from `ink`; `scrim`; `ring` from `primary-ink`;
144
+ `primary-hover` `primary-border`; the status inks; the button faces and
145
+ chips). The derived ones are redeclared on `:root`, `[data-brand]`, `.light`,
146
+ `.dark` and `[data-theme]` at zero specificity, so a brand scope gets its own
147
+ borders, hover and focus ring rather than inheriting the root's, and a
148
+ palette may still pin any of them outright. The geometry (`radius`,
149
+ `page-px`, `band-py`, …) and its responsive scale-ups restart on every
150
+ `[data-brand]` the same way.
151
+ - **EV's palette** — Dark on `:root`, `[data-brand="ev"]` and `.dark`; Light on
152
+ `.light`; Oldschool on `[data-theme="oldschool"]`. None of them matches inside
153
+ another brand's scope.
121
154
 
122
155
  ### Brand palettes
123
156
 
124
- A second brand is a palette against the same names, scoped to
157
+ A second brand is a palette against the same names (29 of them, `chart-6` among them), scoped to
125
158
  `[data-brand="<slug>"]`; light is its default and `.light` / `.dark` beneath it
126
159
  pick a polarity, so a `<Section polarity="dark">` inside the brand takes the
127
160
  brand's dark values. The package ships a generator for it, reading the
128
161
  `brand.toml` shape (`[colors.light]` and `[colors.dark]`, keyed by token name;
129
162
  optional top-level `mark` and `mark-aspect` become `--brand-mark` and
130
163
  `--brand-aspect`; the family names in `[fonts]` — `sans` (or aquafix's `text`),
131
- `display`, `mono` — become the [font parameters](#fonts); other keys and tables
164
+ `serif`, `mono` — become the [font parameters](#fonts); other keys and tables
132
165
  are ignored). Each polarity block also declares `--scheme: light | dark`, which
133
166
  the platform-drawn parts of the kit read (a `NativeSelect`'s popup):
134
167
 
@@ -193,13 +226,16 @@ under a brand under another brand may match either.
193
226
 
194
227
  ### Fonts
195
228
 
196
- The families are parameters, one per role; unset, each is EV's:
229
+ The families are parameters, one per role, and not part of the 29 colour names:
230
+ a palette is complete without them, and the generator only carries what a
231
+ brand file's `[fonts]` declares. Unset, each is EV's, and Oldschool carries the
232
+ families the navy look shipped with:
197
233
 
198
- | parameter | utilities | default (EV) |
199
- |---|---|---|
200
- | `--brand-font-sans` | `font-sans`, the page's base family | `--font-inter`, else `"Inter"` |
201
- | `--brand-font-display` | `font-display`, `font-serif` | `--font-playfair`, else `"Playfair Display"` |
202
- | `--brand-font-mono` | `font-mono` | `--font-inter`, else `"Inter"` |
234
+ | parameter | utilities | default (EV) | Oldschool |
235
+ |---|---|---|---|
236
+ | `--brand-font-sans` | `font-sans`, the page's base family | `--font-inter`, else `"Inter"` | same |
237
+ | `--brand-font-serif` | `font-serif` | `--font-inter-tight`, else `"Inter Tight"` | `--font-playfair`, else `"Playfair Display"` |
238
+ | `--brand-font-mono` | `font-mono` | `--font-jetbrains-mono`, else `"JetBrains Mono"` | `--font-inter`, else `"Inter"` |
203
239
 
204
240
  Declare them on the brand scope (the palette generator writes them from
205
241
  `[fonts]`) and load the files yourself — `next/font`, or your own `@font-face`;
@@ -207,10 +243,13 @@ the kit ships no font files:
207
243
 
208
244
  ```css
209
245
  [data-brand="aquafix"] {
210
- --brand-font-display: "Archivo";
246
+ --brand-font-serif: "Archivo";
211
247
  }
212
248
  ```
213
249
 
250
+ The serif role is the second face, for headings, figures, wordmarks, italic
251
+ accents and the avatar initial; it need not have serifs.
252
+
214
253
  The utilities resolve the chain on the element, so a scope re-fonts everything
215
254
  under it that carries one. The page's base family resolves once, on `<html>`: a
216
255
  brand scoped lower than `<html>` puts `font-sans` on its own element so plain
@@ -306,12 +345,12 @@ through hydration. Three parts of the kit make that hold:
306
345
  ```
307
346
 
308
347
  **Focus.** A control that paints a fill — `Button` `primary` / `secondary` /
309
- `destructive` or any accent fill, a filled `Badge`, `Switch`, `Checkbox` —
310
- shows focus as the solid `ring` standing 2px off it, so both edges of the
311
- indicator are against the surface: the ring reads on every surface at ≥ 3:1
312
- and so does the fill, on every palette and polarity `test/tokens.test.ts`
348
+ `destructive` or any accent fill, a `Badge` link, `Switch`, `Checkbox`,
349
+ `Toggle` — shows focus as the solid `ring` standing 2px off it, so both edges of
350
+ the indicator are against the surface: the ring reads on every surface at
351
+ ≥ 3:1 and so does the fill, on every palette and polarity `test/tokens.test.ts`
313
352
  measures. Controls that sit on the surface (`outline`, `ghost`, inputs) keep
314
- the `ring` border plus its halo.
353
+ the `ring` border plus its halo; list rows draw an inset ring.
315
354
 
316
355
  ## App shell
317
356
 
@@ -319,7 +358,8 @@ The frame a signed-in app sits in — a rail beside the page on a wide screen, a
319
358
  tab bar under it on a phone, one page inset and title scale, and the motion
320
359
  between screens. It knows nothing about routes, roles or data: the nav is a
321
360
  list you build, visibility is a list you filter, and the router comes in as two
322
- props. TS-only (see [Limitations](#limitations)).
361
+ props. TS-only (see [Limitations](#limitations)), except `TopBar`,
362
+ `SystemBanner` and `SectionLabel`, which have Dioxus twins.
323
363
 
324
364
  ```tsx
325
365
  // app/(app)/layout.tsx — the layout stays a Server Component; the nav is a client leaf
@@ -394,6 +434,15 @@ export function Nav() {
394
434
  middle click does not. One marker per group slides between rows on a CSS
395
435
  `transform` transition — it is placed by measurement, so until hydration the
396
436
  marked row carries the fill itself.
437
+ *Collapsible sections* are opt-in: set `collapsible` on a group (or on
438
+ `ShellNav` for every labelled group; a group's own value wins) and its label
439
+ becomes a header with a chevron. `defaultOpen`, controlled `open` /
440
+ `onOpenChange`, and `href` (the label links to a landing page, only the
441
+ chevron toggles) go on the group; the group holding the current route opens
442
+ when the route moves into it. Height runs on a `0fr → 1fr` grid track with a
443
+ 180 ms fade and chevron turn (`--ev-dur-fast`, `--ev-ease-in-out`), none under
444
+ reduced motion; closed rows are `inert`. `labels` also takes `expand` /
445
+ `collapse` (the chevron reads "Expand Guides"). `SectionNav` takes the same.
397
446
  - **`BottomTabBar`** — `items` (five fit a phone), the same router props,
398
447
  callbacks and optimistic mark, `labels` `{ nav, badge(n) }`. One rule slides by
399
448
  whole tab widths and fades on a route no tab claims; a numeric `badge` sits
@@ -416,8 +465,8 @@ export function Nav() {
416
465
  onValueChange?, linkComponent?, labels: { nav } }` — a page's own section
417
466
  rail (settings panes); items are buttons, or links when they have an `href`.
418
467
  - **`ResourceError`** `{ message, variant: "inline" (onRetry?, retrying?) |
419
- "alert" (title?), labels: { retry } }` and **`SystemBanner`** `{ tone: "warn" |
420
- "info", title?, icon?, onDismiss?, labels: { dismiss } }` — presentation
468
+ "alert" (title?), labels: { retry } }` and **`SystemBanner`** `{ tone: "neutral" |
469
+ "primary" | "info" | "warn", title?, icon?, onDismiss?, labels: { dismiss } }` — presentation
421
470
  only; what failed and whether a dismissal sticks are yours.
422
471
  - **`Settled`** `{ loading, skeleton, children }` — the skeleton → content
423
472
  handover: the content fades and rises in after a skeleton was shown, and cuts
@@ -464,6 +513,57 @@ The timing is tokens on every theme root, for your own transitions too
464
513
  `--ev-rise` (8px), `--ev-stagger` (35ms), `--ev-stagger-section` (50ms). The
465
514
  shell's geometry is `--shell-rail-w` (248px) and `--shell-tab-bar-h` (64px).
466
515
 
516
+
517
+ ### Animated numbers
518
+
519
+ `AnimatedNumber` shows a number that moves to its new value. It needs no
520
+ animation library: the digits are CSS transforms and transitions, and the
521
+ count-up is `requestAnimationFrame`.
522
+
523
+ ```tsx
524
+ <AnimatedNumber value={balance} format={{ style: "currency", currency: "USD" }} />
525
+ <AnimatedNumber value={change} format={{ style: "percent", signDisplay: "exceptZero" }} />
526
+ <AnimatedNumber value={volume} format={{ notation: "compact" }} mode="count" animateOnMount />
527
+ ```
528
+
529
+ | prop | |
530
+ |---|---|
531
+ | `value` | the number |
532
+ | `format`, `locales` | passed to `Intl.NumberFormat` |
533
+ | `mode` | `roll` (default): digit columns spin. `count`: the number is tweened and re-formatted each frame |
534
+ | `trend` | roll only. `1` every column spins up, `-1` down, `0` each column takes its shorter way. Default: the way the value moved |
535
+ | `duration` | ms per change: spin 750 (roll), whole tween 800 (count) |
536
+ | `prefix`, `suffix` | React nodes beside the figure, not animated |
537
+ | `live` | announce each new value politely; off by default |
538
+ | `animateOnMount`, `from` | animate the first render from `from` (default 0) |
539
+
540
+ It inherits font, size and colour, so it fits `text-figure-l font-serif
541
+ font-light` as well as a `text-body` table cell. `tabular-nums` is on.
542
+ `useCountTween(value, { duration, easing, from, animateOnMount })` returns the
543
+ in-flight number for a chart or a label of your own. `HeaderBalance` takes
544
+ `amount` (USD unless `format` says otherwise); any `figure`, `value` or other
545
+ `ReactNode` slot takes an `<AnimatedNumber />` as is.
546
+
547
+ **How roll works.** `formatToParts` splits the value. Integer digits are keyed
548
+ by place value from the right, fraction digits by position, so `9 -> 10` keeps
549
+ the existing column and only a new one enters. Symbols (currency, sign, group,
550
+ decimal, percent, compact suffix) are keyed by type. A digit is a clipped
551
+ one-line window over a strip moved with `translateY` on a spring-shaped
552
+ `linear()` easing (~4 % overshoot), with soft top and bottom edges. The strip
553
+ is unbounded, so a forced direction wraps (9 to 0 going up). Entering and leaving
554
+ parts animate width (`0fr` to `1fr`) and opacity in 350 ms, so their neighbours
555
+ slide.
556
+
557
+ **Accessibility.** The final formatted value is in the DOM once, as
558
+ visually hidden text; the moving glyphs are `aria-hidden` and not selectable,
559
+ so a copy gives the formatted text.
560
+
561
+ **Reduced motion.** Under `prefers-reduced-motion: reduce` a new value swaps in
562
+ at once: no spin, no width animation, no tween frames.
563
+
564
+ **SSR.** The server prints the final formatted value, also with `animateOnMount`,
565
+ so hydration does not jump; the count-up starts after hydration.
566
+
467
567
  ## Usage
468
568
 
469
569
  ```tsx
@@ -474,7 +574,7 @@ export function Example() {
474
574
  <Card>
475
575
  <CardHeader>
476
576
  <CardTitle>Portfolio</CardTitle>
477
- <Badge variant="success">+12.4%</Badge>
577
+ <Badge variant="positive">+12.4%</Badge>
478
578
  </CardHeader>
479
579
  <CardContent>
480
580
  <Button onClick={() => {}}>Invest</Button>
@@ -602,8 +702,13 @@ the cell says so.
602
702
  | optional slot present | an explicit prop, never read off `children`: `FieldSeparator { content: true, "or" }` renders the copy pill; `FormMessage { error, .. }` renders only while `error` (the same flag as `FormControl`'s) | `!!children` / `if (!children) return null` |
603
703
  | option label | `SelectItem { value, text_value, .. }`: the text type-ahead matches, an explicit prop in both ports — never read off `children` | `SelectItem`'s `textValue`, else the text of its children |
604
704
  | toasts | `ToasterProvider` + `use_toaster()` → `ToasterHandle` (`.toast` `.positive` `.error` `.info` `.warn` `.show` `.dismiss`), same in both ports | global `toast(...)` / `toast.dismiss` |
705
+ | children present | `SettingsSection` and `SystemBanner`: Dioxus checks that the children render something, Leptos that children were passed | `children !== undefined` |
706
+ | `SystemBanner` glyph | `icon` replaces the tone's glyph; Dioxus drops it with an empty `icon: rsx! {}`, Leptos with `icon=None` | `icon={null}` |
707
+ | `KeyValue` label | Dioxus: an `Element`; Leptos: `KeyValueLabel::{Text, View}` (`.into()` from a string), since only text names the copy button | `label` (`ReactNode`) |
708
+ | time-varying props | Dioxus: plain values; Leptos: signals — `HeaderBalance`, `NotificationBell`, `ModelChip`, `ChatComposer` `streaming` / `disabled`, `ConfirmDialog` `pending` / `error`, `ChatAttachment` `progress`, `AsidePanel` `open` | props |
709
+ | Ctrl+K hook | `use_command_palette_shortcut(on_trigger, enabled)`: `enabled` is a `bool` in Dioxus, a `Signal<bool>` in Leptos | `useCommandPaletteShortcut` |
605
710
 
606
- ### Component inventory (all 75 bricks)
711
+ ### Component inventory (all bricks)
607
712
 
608
713
  - **Tier A — static (23):** badge, button, button-group, card, input, textarea,
609
714
  label, field, separator, skeleton, spinner, kbd, table, container, alert,
@@ -621,27 +726,99 @@ the cell says so.
621
726
  / `Forbidden` / `ServerError` presets (404 / 403 / 500). The kit ships no
622
727
  artwork: `Logo` masks whatever `--brand-mark` / `--brand-aspect` the consumer
623
728
  declares beside the palette, and the status pages use it for their mark.
624
- - **App shell — TS-only (12):** app-shell, shell-nav, bottom-tab-bar,
625
- nav-badge (`NavBadge` / `NavDot`), top-bar, account-menu, mobile-app-bar, page-frame (`PageFrame` /
626
- `PageHeading` / `SectionLabel`), section-nav, resource-error, system-banner,
627
- settled — see [App shell](#app-shell).
628
- - **Features — composed screens (1):** terminal — a trading terminal over an
629
- investment product's shares (`Terminal` grid placing each `TerminalPane` by
630
- `TerminalArea`; `TerminalTicker` / `TickerStat`; `OrderBook` with
631
- `OrderBookHead` / `OrderBookRow` / `OrderBookSpread`; `TradesTapeRow`;
632
- `OrderForm` / `OrderFormRow` / `OrderFormSubmit`; `OpenOrdersEmpty`). Column
633
- captions and every figure are the consumer's strings — the kit knows no
634
- locale and no number format.
729
+ - **App shell — TS-only (10):** app-shell, shell-nav, bottom-tab-bar,
730
+ nav-badge (`NavBadge` / `NavDot`), account-menu, mobile-app-bar, page-frame
731
+ (`PageFrame` / `PageHeading`), section-nav, resource-error, settled — see
732
+ [App shell](#app-shell). `TopBar`, `SystemBanner` and `SectionLabel` have
733
+ Dioxus twins (next item).
734
+ - **Composed parts — Rust and TS:** the class strings live once in
735
+ `rust/classes/src/<name>.rs`, and `nix run .#gen` writes them to
736
+ `ts/uikit/src/generated/<name>.ts`.
737
+ - *elements:* `IconButton` (required `aria-label`), `StatusItem` / `StatusDot`,
738
+ `WorkspaceTabs` / `WorkspaceTab`, `KeyValue` (copy button), `FormRow`,
739
+ `SystemBanner`, `SectionLabel`;
740
+ - *settings:* `SettingsLayout` / `SettingsSection` / `SettingsRow`,
741
+ `AccountSettingsDialog`, `ConfirmDialog` (async confirm), `AccountList` /
742
+ `AccountListItem`, `PopoverForm`, `CommandPalette` and
743
+ `useCommandPaletteShortcut` (Rust: `use_command_palette_shortcut`);
744
+ - *header and asides:* `TopBar`, `SmartHeader` (`default`, `collapsed`,
745
+ `banner`, `search`), `HeaderBalance`, `HeaderSearch`, `NotificationBell`,
746
+ `AsideHeader`, `AsideRail`, `AsidePanel` (`docked` or `overlay`);
747
+ - *AI chat:* `ChatMessage`, `ChatBubble` (`streaming` shows a caret),
748
+ `ChatMarker`, `ChatAttachment`, `ChatComposer`, `ModelChip` and `ChatTyping`
749
+ (the "thinking" indicator).
750
+ - **Composed parts — TS-only:** `AnimatedNumber` / `useCountTween`,
751
+ `ChatPanel`, `ChatDock`, `ChatStreamText` (pass the whole growing string; only
752
+ the new words fade in), the `AppShell` `aside` slot, and the profile form on
753
+ `AccountMenu`. How the Rust twins differ is in [Limitations](#limitations).
754
+
755
+ ### Variant vocabulary
756
+
757
+ A variant names the state ([`docs/spec/variants.md`](../../docs/spec/variants.md)).
758
+
759
+ | component | values |
760
+ |---|---|
761
+ | `Button` | `primary` (the filled call to action, default) · `secondary` · `outline` · `ghost` · `destructive` · `link` |
762
+ | `Badge` | `neutral` (default) · `primary` · `positive` · `info` · `warn` · `error` |
763
+ | `Alert` | `neutral` (default) · `destructive` · `success` · `info` |
764
+ | menu item (`DropdownMenuItem`, `ContextMenuItem`, `MenubarItem`) | `neutral` · `destructive` |
765
+ | `SystemBanner` | `neutral` · `primary` · `info` (default) · `warn` |
635
766
 
636
767
  The canonical variant set is the **superset** of the original cabinet (Rust) and
637
- landing (TS) sources — e.g. `Badge` keeps cabinet's `success` variant, and
638
- `Button` keeps landing's square icon shape at every size, as the separate `icon`
639
- boolean it always was in Rust (see [docs/spec/variants.md](../../docs/spec/variants.md)).
768
+ landing (TS) sources: `Button` keeps landing's square icon shape at every size,
769
+ as the separate `icon` boolean it always was in Rust. A `destructive` button
770
+ wears the `button-danger-*` face: an outline in Dark and Light, a fill in
771
+ Oldschool.
640
772
 
641
773
  `size="touch"` is the 44 px pointer-target floor (WCAG 2.5.5) for touch-first
642
774
  screens: `min-h-11` with `lg`'s padding, and a 44 × 44 square with `icon`. It is
643
775
  a button step only — `Input` and `SelectTrigger` already clear it at `lg`.
644
776
 
777
+ ## Upgrading from 0.30
778
+
779
+ **Renames and removals**
780
+
781
+ | 0.30 | now |
782
+ |---|---|
783
+ | `Badge variant="outline"` · `"secondary"` | `neutral` |
784
+ | `Badge variant="destructive"` · `"success"` | `error` · `positive` (new: `primary`, `info`, `warn`) |
785
+ | `SystemBanner` tones `warn`, `info` | the same, plus `neutral` and `primary`; `info` draws its icon in `accent-info-ink` |
786
+ | `accent-error-ink` (`text-accent-error-ink`, a brand file's `accent-error-ink`) | `accent-error`; destructive menu rows read in it, and `evinvest-palette` refuses the key |
787
+ | `Terminal`, `TerminalPane*`, `TerminalChart`, `TerminalTicker`, `TickerStat`, `OrderBook*`, `TradesTapeRow`, `OrderForm*`, `OpenOrdersEmpty` and their types | removed from the kit; a trading view owns its terminal |
788
+
789
+ **Silent changes: the compiler does not flag these.**
790
+
791
+ - A `Badge` with no `variant` was filled `primary` and is now `neutral`:
792
+ `rg -n '<Badge(\s|>)' --glob '*.tsx' | rg -v 'variant='`.
793
+ - A `destructive` `Button` wears the theme's `button-danger-*` face, an outline
794
+ in Dark and Light; an `outline` one is raised (`secondary` fill and a hairline).
795
+
796
+ **Tokens and themes**
797
+
798
+ - EV's navy palette is opt-in: `data-theme="oldschool"`. Dark is the default
799
+ and is a different colour set; `.light` is Light.
800
+ - Font defaults are Inter (sans), Inter Tight (serif role) and JetBrains Mono
801
+ (mono). `data-theme="oldschool"` sets Playfair Display and Inter for the serif
802
+ and mono roles, as the navy look shipped. Load the families a theme uses
803
+ (`--font-inter-tight`, `--font-jetbrains-mono`, or `--font-playfair` for
804
+ Oldschool); the kit ships no font files.
805
+ - The font role `display` is `serif`: `--brand-font-display` / `font-display`
806
+ become `--brand-font-serif` / `font-serif` (see [Fonts](#fonts)).
807
+ - A brand file must add `chart-6` (29 names now); `evinvest-palette` names it.
808
+ - Panel radius is 6 px at every width (the `sm` bump to 8 px is gone), controls
809
+ and chips 4 px, and the depth tiers are flat. **Aquafix, vifnet and any other
810
+ brand take these and lose their card shadow** unless their scope overrides
811
+ `--radius`, `--control-radius`, `--chip-radius` and `--depth-card`,
812
+ `--depth-elevated`, `--depth-overlay`. Check each brand before releasing.
813
+
814
+ **Layers across bundles**
815
+
816
+ - The shared layer stack (Escape order, outside clicks, the one shared scrim)
817
+ keeps its global key `@1`, so a micro-frontend bundling uikit 0.30 and a newer
818
+ host still share one stack. A 0.30 copy never notifies, so a newer modal's
819
+ shared scrim may not update when a 0.30 layer opens or closes under it; move
820
+ hosts and the MFEs they mount together to get the full behaviour.
821
+
645
822
  ## Limitations
646
823
 
647
824
  Reproducing everything dep-light means some behaviour is intentionally reduced,
@@ -684,11 +861,6 @@ measuring needs host-only `web-sys`). Known gaps:
684
861
  `onkeydown` — and `AlertDialog`, `Sheet`, `Drawer`, `ContextMenu`, `Menubar`,
685
862
  `NavigationMenu`, `HoverCard`, `Tooltip`, `InfoTip`, `DateTimePicker`,
686
863
  `CommandDialog` and `DropdownMenuSub` are not on the stack yet.
687
- - **terminal:** no plotting engine and no state. `TerminalChart` is a sized
688
- `relative` host that hands its element out (`ref` in TS, `id` in Rust) for a
689
- consumer-chosen charting library to mount into; `OrderForm` only prevents the
690
- submit's default — inputs, validation and the order itself are the
691
- consumer's. The open-orders pane reuses `Table` and `Tabs`.
692
864
  - **calendar:** single month, single-date selection (no range/multi-month, no
693
865
  dropdown captions). The grid is always six fixed weeks of 36px cells, so its
694
866
  size never changes with the month or the locale's weekday labels, and it
@@ -700,7 +872,7 @@ measuring needs host-only `web-sys`). Known gaps:
700
872
  locale whose short form contains whitespace (vi's "Thứ 2" → "T2", he's
701
873
  "יום ב׳" → "ב׳") as long as narrow still yields seven distinct labels. Rust has no `Intl`, so its captions
702
874
  stay English. Rust does manual date math; TS uses the built-in `Date`.
703
- - **date-time-picker:** the kit's own bricks only — an outline trigger, a
875
+ - **date-time-picker:** the kit's own bricks only — a raised trigger, a
704
876
  `Popover` with the `Calendar` and two numeric 24-hour hours/minutes fields (no
705
877
  native `datetime-local` / `time` input, so the browser's locale popup never
706
878
  appears). Its ARIA and button strings are `labels` overrides with English
@@ -748,12 +920,34 @@ measuring needs host-only `web-sys`). Known gaps:
748
920
  The lock-up is composed from `mark` + `brand` (display family) + `tagline`,
749
921
  or passed whole as `lockup`. Brand-coloured text reads `primary-ink`.
750
922
  - **TS-only for now:** `NativeSelect`, the `Field` id hand-off,
751
- `SelectValue` labels, `ListRows` / `ListRow` (a table's phone form), and the whole [app shell](#app-shell) (`AppShell`,
752
- `ShellNav`, `BottomTabBar`, `NavBadge` / `NavDot`, `TopBar`, `AccountMenu`, `MobileAppBar`, `PageFrame` /
753
- `PageHeading` / `SectionLabel`, `SectionNav`, `ResourceError`, `SystemBanner`,
754
- `Settled`) — no Dioxus twin. Its CSS (the entrances, the markers, the motion
755
- and shell tokens) ships in the shared sheet, so a Rust app can use the
756
- `data-enter` contract today.
923
+ `SelectValue` labels, `ListRows` / `ListRow` (a table's phone form), the
924
+ rest of the [app shell](#app-shell) (`AppShell`, `ShellNav`, `BottomTabBar`,
925
+ `NavBadge` / `NavDot`, `AccountMenu` and its profile form, `MobileAppBar`,
926
+ `PageFrame` / `PageHeading`, `SectionNav`, `ResourceError`, `Settled`) and
927
+ the parts that need a browser API Rust does not wrap: `AnimatedNumber` /
928
+ `useCountTween` (a frame loop and `Intl`), `ChatStreamText` (word diffing and
929
+ timers), and `ChatPanel` / `ChatDock` (`ResizeObserver`, scroll pinning).
930
+ Collapsible `ShellNav` / `SectionNav` groups are TS-only too. Their CSS (the
931
+ entrances, the markers, the motion and shell tokens) ships in the shared
932
+ sheet, so a Rust app can use the `data-enter` contract today.
933
+ - **Rust twins of the composed parts:** they keep the TS markup and class strings, with
934
+ these differences. Overlays keep the limits of the older Rust overlays (inline
935
+ `position: fixed`, no portal, no focus trap, not on the layer stack).
936
+ `HeaderBalance` takes a formatted `String` (no rolling digits, no `Settled`).
937
+ `ConfirmDialog` has `pending` and `error` props in place of a promise, and a
938
+ `pending` dialog ignores Esc, the scrim and the buttons. `KeyValue` takes a
939
+ `copy` callback; with the `wasm` feature and no callback it writes through
940
+ `web-sys`. `CommandPalette` is controllable (`open`, `default_open`,
941
+ `on_open_change`), and `use_command_palette_shortcut` listens for Ctrl or Cmd
942
+ K by key code on the `wasm` feature only, so it does nothing in an SSR build.
943
+ `AsidePanel` has no `matchMedia`: with `AsideCollapse::Md` it renders the
944
+ docked or sheet form and the drawer form together, and breakpoint classes show
945
+ one, so its children mount twice. Dialogs, popovers and menus do not name
946
+ themselves: pass `aria_labelledby` and the title `id`, or `aria_label`. The
947
+ TS tests that stub `matchMedia`, or that need `SectionNav` or `AppShell`, are
948
+ ported as markup checks or not at all. `dioxus-ssr` runs no effects, so the
949
+ clipboard write, the Ctrl+K listener and focus moves are checked in the
950
+ gallery only.
757
951
  - **app shell:** `ShellNav`'s marker is measured (one forced layout read per
758
952
  navigation); the tab bar's rule is arithmetic and assumes equal tabs. A
759
953
  `data-enter` nested inside another still entering composes both rises (the
@@ -2,7 +2,8 @@
2
2
  function references(value) {
3
3
  return [...value.matchAll(/var\(--([A-Za-z0-9-]+)/g)].flatMap((m) => m[1] ? [m[1]] : []);
4
4
  }
5
- var DERIVED_SCOPE = ":where(:root, .dark, .light, [data-brand])";
5
+ var DERIVED_SCOPE = ":where(:root, .dark, .light, [data-brand], [data-theme])";
6
+ var FACES_SCOPE = ":where([data-theme], [data-brand], .light, .dark, :root)";
6
7
  function readRules(css) {
7
8
  const rules = [];
8
9
  const src = css.replace(/\/\*[\s\S]*?\*\//g, "");
@@ -48,10 +49,12 @@ function readContract(css) {
48
49
  }
49
50
  const derivedRule = rules.find((r) => r.selector === DERIVED_SCOPE);
50
51
  if (!derivedRule) throw new Error(`token sheet has no \`${DERIVED_SCOPE}\` rule \u2014 not the kit's contract`);
51
- const derived = [...derivedRule.declarations.keys()];
52
+ const facesRule = rules.find((r) => r.selector === FACES_SCOPE);
53
+ const formulas = new Map([...derivedRule.declarations, ...facesRule?.declarations ?? []]);
54
+ const derived = [...formulas.keys()];
52
55
  const stray = derived.filter((d) => !painted.includes(d));
53
56
  if (stray.length > 0) throw new Error(`derived tokens with no @theme mapping: ${stray.join(", ")}`);
54
- const derivedFrom = Object.fromEntries([...derivedRule.declarations].map(([name, value]) => [name, references(value)]));
57
+ const derivedFrom = Object.fromEntries([...formulas].map(([name, value]) => [name, references(value)]));
55
58
  return { required: painted.filter((p) => !derived.includes(p)), derived, derivedFrom };
56
59
  }
57
60
 
@@ -144,8 +147,8 @@ function splitTopLevel(inner) {
144
147
 
145
148
  // src/palette/brand.ts
146
149
  var POLARITIES = ["light", "dark"];
147
- var FONT_ROLES = ["sans", "display", "mono"];
148
- var FONT_KEYS = { sans: "sans", text: "sans", display: "display", mono: "mono" };
150
+ var FONT_ROLES = ["sans", "serif", "mono"];
151
+ var FONT_KEYS = { sans: "sans", text: "sans", serif: "serif", mono: "mono" };
149
152
  var PaletteError = class extends Error {
150
153
  constructor(problems) {
151
154
  super(`invalid brand palette:
@@ -293,6 +296,7 @@ ${extras.join("")}}
293
296
 
294
297
  export {
295
298
  DERIVED_SCOPE,
299
+ FACES_SCOPE,
296
300
  readRules,
297
301
  readContract,
298
302
  parseToml,
@@ -303,4 +307,4 @@ export {
303
307
  validateBrand,
304
308
  renderPalette
305
309
  };
306
- //# sourceMappingURL=chunk-3IPB4QQJ.js.map
310
+ //# sourceMappingURL=chunk-35SPIU4U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/palette/contract.ts","../src/palette/toml.ts","../src/palette/brand.ts"],"sourcesContent":["/**\n * The colour contract, read out of the kit's own token sheet rather than\n * restated here: `@theme inline` maps every name the class tables can paint\n * (`--color-X: var(--X)`), and the derived rule lists the ones the contract\n * computes from the rest. A palette owes the difference.\n */\nexport interface Contract {\n /** Names every palette scope must declare. */\n required: readonly string[];\n /** Names the contract derives from the palette; a palette may override them. */\n derived: readonly string[];\n /** The tokens each derived default reads, so a palette's references can be checked for cycles through them. */\n derivedFrom: Readonly<Record<string, readonly string[]>>;\n}\n\n/** The `--name`s a value reads through `var()`. */\nexport function references(value: string): string[] {\n return [...value.matchAll(/var\\(--([A-Za-z0-9-]+)/g)].flatMap((m) => (m[1] ? [m[1]] : []));\n}\n\n/** The rule the derived tokens live on — see `theme.css`, the contract half of `tokens.css`. */\nexport const DERIVED_SCOPE = \":where(:root, .dark, .light, [data-brand], [data-theme])\";\n\n/** The same scopes in another order: the button faces and chips, derived the same way. */\nexport const FACES_SCOPE = \":where([data-theme], [data-brand], .light, .dark, :root)\";\n\nexport interface CssRule {\n selector: string;\n /** Custom properties declared directly in the rule, in source order. */\n declarations: Map<string, string>;\n}\n\n/**\n * Top-level and `@media`-nested rules of a flat sheet, comments stripped. Only\n * as much CSS as a token sheet is made of: no strings containing braces.\n */\nexport function readRules(css: string): CssRule[] {\n const rules: CssRule[] = [];\n const src = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const stack: string[] = [];\n let start = 0;\n for (let i = 0; i < src.length; i++) {\n const c = src[i];\n if (c === \"{\") {\n stack.push(src.slice(start, i).trim());\n start = i + 1;\n } else if (c === \"}\") {\n const selector = stack.pop();\n if (selector === undefined) throw new Error(\"unbalanced `}` in token sheet\");\n const body = src.slice(start, i);\n if (!body.includes(\"{\")) rules.push({ selector: normalise(selector), declarations: declarations(body) });\n start = i + 1;\n } else if (c === \";\" && stack.length === 0) {\n start = i + 1;\n }\n }\n if (stack.length > 0) throw new Error(\"unbalanced `{` in token sheet\");\n return rules;\n}\n\nfunction declarations(body: string): Map<string, string> {\n const out = new Map<string, string>();\n for (const decl of body.split(\";\")) {\n const match = /^\\s*--([A-Za-z0-9-]+)\\s*:\\s*([\\s\\S]+?)\\s*$/.exec(decl);\n if (match?.[1] && match[2]) out.set(match[1], match[2]);\n }\n return out;\n}\n\nexport function normalise(selector: string): string {\n return selector.replace(/\\s+/g, \" \").replace(/\\s*,\\s*/g, \", \").trim();\n}\n\nexport function readContract(css: string): Contract {\n const rules = readRules(css);\n const theme = rules.find((r) => r.selector === \"@theme inline\");\n if (!theme) throw new Error(\"token sheet has no `@theme inline` block — not the kit's contract\");\n const painted: string[] = [];\n for (const [name, value] of theme.declarations) {\n const match = /^color-(.+)$/.exec(name);\n if (match?.[1] && value === `var(--${match[1]})`) painted.push(match[1]);\n }\n const derivedRule = rules.find((r) => r.selector === DERIVED_SCOPE);\n if (!derivedRule) throw new Error(`token sheet has no \\`${DERIVED_SCOPE}\\` rule — not the kit's contract`);\n const facesRule = rules.find((r) => r.selector === FACES_SCOPE);\n const formulas = new Map([...derivedRule.declarations, ...(facesRule?.declarations ?? [])]);\n const derived = [...formulas.keys()];\n const stray = derived.filter((d) => !painted.includes(d));\n if (stray.length > 0) throw new Error(`derived tokens with no @theme mapping: ${stray.join(\", \")}`);\n const derivedFrom = Object.fromEntries([...formulas].map(([name, value]) => [name, references(value)]));\n return { required: painted.filter((p) => !derived.includes(p)), derived, derivedFrom };\n}\n","/**\n * The subset of TOML a brand file is written in: `[table.headers]`, bare keys,\n * and single-line values that are a basic string, a number, a boolean, or a\n * flat array of those. Anything else is an error naming the line, rather than a\n * silent misread — the kit stays dependency-free, and a brand file has no use\n * for the rest of the language.\n */\n\nexport type TomlValue = string | number | boolean | TomlValue[];\nexport interface TomlTable {\n [key: string]: TomlValue | TomlTable;\n}\n\nconst BARE_KEY = /^[A-Za-z0-9_-]+$/;\n\nexport function parseToml(text: string): TomlTable {\n const root: TomlTable = {};\n let table = root;\n const headers = new Set<string>();\n text.split(/\\r?\\n/).forEach((raw, index) => {\n const line = stripComment(raw).trim();\n if (line === \"\") return;\n const fail = (why: string): never => {\n throw new Error(`TOML line ${index + 1}: ${why}: ${raw.trim()}`);\n };\n\n if (line.startsWith(\"[\")) {\n if (!line.endsWith(\"]\") || line.startsWith(\"[[\")) fail(\"only plain [table] headers are supported\");\n const path = line.slice(1, -1).trim().split(\".\").map((part) => part.trim());\n // Re-opening a table would merge two halves of it silently.\n if (headers.has(path.join(\".\"))) fail(\"duplicate table header\");\n headers.add(path.join(\".\"));\n table = descend(root, path, fail);\n return;\n }\n\n const eq = line.indexOf(\"=\");\n if (eq < 0) fail(\"expected `key = value`\");\n const key = line.slice(0, eq).trim();\n if (!BARE_KEY.test(key)) fail(\"only bare keys are supported\");\n if (key in table) fail(`duplicate key \\`${key}\\``);\n table[key] = parseValue(line.slice(eq + 1).trim(), fail);\n });\n return root;\n}\n\nfunction descend(root: TomlTable, path: string[], fail: (why: string) => never): TomlTable {\n let table = root;\n for (const part of path) {\n const key = part.trim();\n if (!BARE_KEY.test(key)) fail(\"only bare keys are supported in a header\");\n const next = table[key] ?? {};\n if (typeof next !== \"object\" || Array.isArray(next)) fail(`\\`${key}\\` is already a value`);\n table[key] = next;\n table = next as TomlTable;\n }\n return table;\n}\n\n// A `#` inside a string is not a comment; the brand files carry `\"#rrggbb\"`.\nfunction stripComment(line: string): string {\n let quoted = false;\n for (let i = 0; i < line.length; i++) {\n const c = line[i];\n if (c === \"\\\\\" && quoted) i++;\n else if (c === '\"') quoted = !quoted;\n else if (c === \"#\" && !quoted) return line.slice(0, i);\n }\n return line;\n}\n\nfunction parseValue(src: string, fail: (why: string) => never): TomlValue {\n if (src.startsWith('\"')) {\n if (src.length < 2 || !src.endsWith('\"')) fail(\"unterminated string\");\n const body = src.slice(1, -1);\n if (/(^|[^\\\\])(\\\\\\\\)*\"/.test(body)) fail(\"one string per value\");\n // Only the escapes decoded below; `\\u…` and friends would otherwise pass through as literal text.\n if (/\\\\(?![\"\\\\nt])/.test(body.replace(/\\\\\\\\/g, \"\"))) fail(\"unsupported escape\");\n return body.replace(/\\\\([\"\\\\nt])/g, (_, c: string) => ({ n: \"\\n\", t: \"\\t\" })[c] ?? c);\n }\n if (src.startsWith(\"[\")) {\n if (!src.endsWith(\"]\")) fail(\"arrays must close on the same line\");\n const inner = src.slice(1, -1).trim();\n if (inner === \"\") return [];\n return splitTopLevel(inner).map((item) => parseValue(item.trim(), fail));\n }\n if (src === \"true\" || src === \"false\") return src === \"true\";\n if (/^[+-]?\\d+(\\.\\d+)?$/.test(src)) return Number(src);\n return fail(\"unsupported value\");\n}\n\nfunction splitTopLevel(inner: string): string[] {\n const items: string[] = [];\n let quoted = false;\n let start = 0;\n for (let i = 0; i < inner.length; i++) {\n const c = inner[i];\n if (c === \"\\\\\" && quoted) i++;\n else if (c === '\"') quoted = !quoted;\n else if (c === \",\" && !quoted) {\n items.push(inner.slice(start, i));\n start = i + 1;\n }\n }\n const last = inner.slice(start);\n if (last.trim() !== \"\") items.push(last);\n return items;\n}\n","import { references, type Contract } from \"./contract\";\nimport { parseToml, type TomlTable, type TomlValue } from \"./toml\";\n\nexport type PolarityName = \"light\" | \"dark\";\nexport const POLARITIES: readonly PolarityName[] = [\"light\", \"dark\"];\n\n/** A brand's palette: one value per contract name, for each polarity. */\nexport interface BrandConfig {\n colors: Record<PolarityName, Record<string, string>>;\n /** `--brand-mark`: the URL `<Logo>` masks. */\n mark?: string;\n /** `--brand-aspect`: the mark's width / height, e.g. `\"387 / 335\"`. */\n markAspect?: string;\n /** `--brand-font-<role>`: a family name per role; unset roles keep the kit's. */\n fonts?: Partial<Record<FontRole, string>>;\n}\n\nexport type FontRole = \"sans\" | \"serif\" | \"mono\";\nexport const FONT_ROLES: readonly FontRole[] = [\"sans\", \"serif\", \"mono\"];\n// aquafix's file calls the body family `text`.\nconst FONT_KEYS: Record<string, FontRole> = { sans: \"sans\", text: \"sans\", serif: \"serif\", mono: \"mono\" };\n\n/** Every problem with a brand file at once, so one run fixes them all. */\nexport class PaletteError extends Error {\n constructor(readonly problems: readonly string[]) {\n super(`invalid brand palette:\\n - ${problems.join(\"\\n - \")}`);\n this.name = \"PaletteError\";\n }\n}\n\n// Written into CSS verbatim, so a value is held to a shape that cannot close\n// the declaration: a hex colour, or a reference to another token.\nconst COLOUR = /^(#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}|var\\(--[a-z0-9-]+\\))$/;\nconst SLUG = /^[a-z0-9][a-z0-9-]*$/;\nconst ASPECT = /^\\d+(\\.\\d+)?\\s*\\/\\s*\\d+(\\.\\d+)?$/;\n// Written inside `url(\"…\")`: nothing that closes the string or the function,\n// and no markup characters for a sheet that ends up inlined in HTML.\nconst MARK_URL = /^[^\"'`\\\\\\s()<>]+$/;\nconst FAMILY = /^[A-Za-z0-9][A-Za-z0-9 _-]*$/;\n\n/**\n * Reads the aquafix `brand.toml` shape: `[colors.light]` and `[colors.dark]`\n * keyed by contract name, optional top-level `mark` / `mark-aspect`, and the\n * family names in `[fonts]` (`sans` or `text`, `serif`, `mono`). The rest of\n * `[fonts]` and every other table (`[print]`, …) belong to other tools and are\n * ignored — loading the font files is the site's job, not the palette's.\n */\nexport function brandFromToml(text: string): BrandConfig {\n const doc = parseToml(text);\n const problems: string[] = [];\n const colors = table(doc[\"colors\"]);\n if (!colors) problems.push(\"no [colors] table\");\n const scope = (name: PolarityName): Record<string, string> => {\n const t = colors ? table(colors[name]) : undefined;\n if (colors && !t) problems.push(`no [colors.${name}] table`);\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(t ?? {})) {\n if (typeof value === \"string\") out[key] = value;\n else problems.push(`colors.${name}.${key} is not a string`);\n }\n return out;\n };\n for (const key of Object.keys(colors ?? {})) {\n if (!(POLARITIES as readonly string[]).includes(key)) problems.push(`[colors.${key}] is not a polarity (light, dark)`);\n }\n const config: BrandConfig = { colors: { light: scope(\"light\"), dark: scope(\"dark\") } };\n const mark = optionalString(doc[\"mark\"], \"mark\", problems);\n const markAspect = optionalString(doc[\"mark-aspect\"], \"mark-aspect\", problems);\n if (mark !== undefined) config.mark = mark;\n if (markAspect !== undefined) config.markAspect = markAspect;\n const fonts = table(doc[\"fonts\"]);\n for (const [key, role] of Object.entries(FONT_KEYS)) {\n const family = optionalString(fonts?.[key], `fonts.${key}`, problems);\n if (family !== undefined) config.fonts = { ...config.fonts, [role]: family };\n }\n if (problems.length > 0) throw new PaletteError(problems);\n return config;\n}\n\nfunction table(value: TomlValue | TomlTable | undefined): TomlTable | undefined {\n return typeof value === \"object\" && !Array.isArray(value) ? value : undefined;\n}\n\nfunction optionalString(value: TomlValue | TomlTable | undefined, key: string, problems: string[]) {\n if (value === undefined || typeof value === \"string\") return value;\n problems.push(`${key} is not a string`);\n return undefined;\n}\n\n/** The problems with `config` against `contract`; empty when it is complete. */\nexport function validateBrand(config: BrandConfig, contract: Contract): string[] {\n const problems: string[] = [];\n const known = new Set([...contract.required, ...contract.derived]);\n for (const polarity of POLARITIES) {\n const values = config.colors[polarity];\n const missing = contract.required.filter((t) => !(t in values));\n if (missing.length > 0) problems.push(`${polarity} is missing ${missing.join(\", \")}`);\n for (const [key, value] of Object.entries(values)) {\n if (!known.has(key)) problems.push(`${polarity}.${key} is not a token of the contract`);\n else if (!COLOUR.test(value)) problems.push(`${polarity}.${key} = ${JSON.stringify(value)} is not #hex or var(--token)`);\n else {\n for (const ref of references(value)) {\n if (!known.has(ref)) problems.push(`${polarity}.${key} refers to --${ref}, which is not a token of the contract`);\n }\n }\n }\n const cycle = findCycle(values, contract, known);\n if (cycle) problems.push(`${polarity} has a reference cycle: ${cycle.map((t) => `--${t}`).join(\" → \")}`);\n }\n if (config.mark !== undefined && !MARK_URL.test(config.mark)) problems.push(`mark ${JSON.stringify(config.mark)} is not a plain URL`);\n if (config.markAspect !== undefined && !ASPECT.test(config.markAspect)) {\n problems.push(`mark-aspect ${JSON.stringify(config.markAspect)} is not \"width / height\"`);\n }\n for (const [role, family] of Object.entries(config.fonts ?? {})) {\n if (!FAMILY.test(family)) problems.push(`fonts.${role} ${JSON.stringify(family)} is not a plain family name`);\n }\n return problems;\n}\n\n/**\n * A `var()` cycle makes every token on it invalid at computed-value time — the\n * same silent hole as a missing token. Edges are the palette's own references,\n * and for a derived token it leaves to the contract, the contract's formula\n * (`border` reads `ink`), so `ink = \"var(--border)\"` is caught too.\n */\nfunction findCycle(values: Record<string, string>, contract: Contract, known: Set<string>): string[] | undefined {\n const edges = (name: string): readonly string[] => {\n const value = values[name];\n if (value !== undefined) return references(value).filter((r) => known.has(r));\n return contract.derivedFrom[name] ?? [];\n };\n const done = new Set<string>();\n const path: string[] = [];\n const visit = (name: string): string[] | undefined => {\n const at = path.indexOf(name);\n if (at >= 0) return [...path.slice(at), name];\n if (done.has(name)) return undefined;\n path.push(name);\n for (const next of edges(name)) {\n const cycle = visit(next);\n if (cycle) return cycle;\n }\n path.pop();\n done.add(name);\n return undefined;\n };\n for (const name of known) {\n const cycle = visit(name);\n if (cycle) return cycle;\n }\n return undefined;\n}\n\n/**\n * A flat sheet scoping `config` under `[data-brand=\"<brand>\"]`: light is the\n * brand's default and `.light` / `.dark` beneath it pick a polarity. Selectors\n * outrank the zero-specificity EV palette, so import order does not matter.\n * Throws a {@link PaletteError} when a scope is incomplete — Tailwind answers an\n * undefined token with no rule at all, so a hole would be silent on the page.\n */\nexport function renderPalette(brand: string, config: BrandConfig, contract: Contract, source = \"a brand file\"): string {\n const problems = SLUG.test(brand) ? [] : [`brand ${JSON.stringify(brand)} is not a lowercase slug`];\n problems.push(...validateBrand(config, contract));\n if (problems.length > 0) throw new PaletteError(problems);\n\n const at = `[data-brand=\"${brand}\"]`;\n const order = [...contract.required, ...contract.derived];\n const block = (selectors: string[], polarity: PolarityName) => {\n const values = config.colors[polarity];\n const body = order.filter((t) => t in values).map((t) => ` --${t}: ${values[t]};\\n`);\n return `${selectors.join(\",\\n\")} {\\n --scheme: ${polarity};\\n${body.join(\"\")}}\\n`;\n };\n const extras: string[] = [];\n if (config.mark !== undefined) extras.push(` --brand-mark: url(\"${config.mark}\");\\n`);\n if (config.markAspect !== undefined) extras.push(` --brand-aspect: ${config.markAspect};\\n`);\n for (const role of FONT_ROLES) {\n const family = config.fonts?.[role];\n if (family !== undefined) extras.push(` --brand-font-${role}: \"${family}\";\\n`);\n }\n\n return [\n // `source` is a file name, free text as far as CSS is concerned: it must not close the comment.\n `/* GENERATED by evinvest-palette from ${source.replaceAll(\"*/\", \"*\\\\/\")} — do not edit. */\\n`,\n block([at, `${at}.light`, `${at} .light`], \"light\"),\n block([`${at}.dark`, `${at} .dark`], \"dark\"),\n ...(extras.length > 0 ? [`${at} {\\n${extras.join(\"\")}}\\n`] : []),\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":["table"]}
@@ -1,15 +1,15 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import { cn } from "../lib/cn.js";
5
- import { useControllableState } from "../primitives/use-controllable-state.js";
4
+ import { cn } from "../../lib/cn.js";
5
+ import { useControllableState } from "../../primitives/use-controllable-state.js";
6
6
  import {
7
7
  ACCORDION_CONTENT,
8
8
  ACCORDION_CONTENT_INNER,
9
9
  ACCORDION_HEADER,
10
10
  ACCORDION_ITEM,
11
11
  ACCORDION_TRIGGER
12
- } from "../generated/accordion.js";
12
+ } from "../../generated/accordion.js";
13
13
  const AccordionContext = React.createContext(null);
14
14
  function useAccordion() {
15
15
  const ctx = React.useContext(AccordionContext);