@exponential_app/eui 0.0.0-stage → 0.2.1

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 (274) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +54 -0
  3. package/README.md +377 -2
  4. package/catalog/a11y.json +705 -0
  5. package/catalog/basic-map.json +104 -0
  6. package/catalog/code.json +58 -0
  7. package/catalog/core.catalog.json +5190 -0
  8. package/catalog/core.schema.json +24542 -0
  9. package/catalog/host.json +95 -0
  10. package/catalog/layout.json +20 -0
  11. package/catalog/limits.json +9 -0
  12. package/catalog/locale.json +48 -0
  13. package/catalog/macros.json +4152 -0
  14. package/catalog/recipes.json +64 -0
  15. package/catalog/strings.json +84 -0
  16. package/catalog/style.json +180 -0
  17. package/catalog/theme.schema.json +47754 -0
  18. package/catalog/tokens.json +47 -0
  19. package/conformance/README.md +218 -0
  20. package/conformance/baseline.ts +101 -0
  21. package/conformance/browser-page.ts +146 -0
  22. package/conformance/browser-suites.ts +699 -0
  23. package/conformance/compare.ts +201 -0
  24. package/conformance/dom.ts +97 -0
  25. package/conformance/dump.ts +163 -0
  26. package/conformance/fonts.json +157 -0
  27. package/conformance/manifest.json +233 -0
  28. package/conformance/parity-compare.ts +191 -0
  29. package/conformance/parity-report.schema.json +73 -0
  30. package/conformance/parity.ts +412 -0
  31. package/conformance/pixel.ts +177 -0
  32. package/conformance/primitives-page.ts +49 -0
  33. package/conformance/report.schema.json +66 -0
  34. package/conformance/run.ts +118 -0
  35. package/conformance/voice-wave-child.ts +102 -0
  36. package/dist/chunks/index-5fmaa0xq.js +8384 -0
  37. package/dist/chunks/index-5fmaa0xq.js.map +10 -0
  38. package/dist/chunks/index-62yzr94z.js +2784 -0
  39. package/dist/chunks/index-62yzr94z.js.map +10 -0
  40. package/dist/chunks/index-bg2jsgjq.js +8541 -0
  41. package/dist/chunks/index-bg2jsgjq.js.map +15 -0
  42. package/dist/chunks/index-fy7y2nz8.js +186 -0
  43. package/dist/chunks/index-fy7y2nz8.js.map +9 -0
  44. package/dist/chunks/index-gtk2gwsb.js +4555 -0
  45. package/dist/chunks/index-gtk2gwsb.js.map +31 -0
  46. package/dist/chunks/index-t6qz1770.js +95 -0
  47. package/dist/chunks/index-t6qz1770.js.map +11 -0
  48. package/dist/conformance.js +230462 -0
  49. package/dist/conformance.js.map +10 -0
  50. package/dist/entries/prompt.js +251 -0
  51. package/dist/entries/prompt.js.map +11 -0
  52. package/dist/entries/schema.js +1725 -0
  53. package/dist/entries/schema.js.map +11 -0
  54. package/dist/host/index.js +194 -0
  55. package/dist/host/index.js.map +9 -0
  56. package/dist/index.js +3851 -0
  57. package/dist/index.js.map +30 -0
  58. package/dist/types/src/a11y.d.ts +21 -0
  59. package/dist/types/src/animation.d.ts +76 -0
  60. package/dist/types/src/basic-map.d.ts +38 -0
  61. package/dist/types/src/builder.d.ts +50 -0
  62. package/dist/types/src/catalog.d.ts +54 -0
  63. package/dist/types/src/catalog.described.d.ts +33 -0
  64. package/dist/types/src/catalog.generated.d.ts +904 -0
  65. package/dist/types/src/chart.d.ts +46 -0
  66. package/dist/types/src/code.d.ts +44 -0
  67. package/dist/types/src/color.d.ts +20 -0
  68. package/dist/types/src/conformance.d.ts +39 -0
  69. package/dist/types/src/connector/app.d.ts +14 -0
  70. package/dist/types/src/connector/connector.d.ts +77 -0
  71. package/dist/types/src/connector/index.d.ts +4 -0
  72. package/dist/types/src/css.d.ts +27 -0
  73. package/dist/types/src/define.d.ts +66 -0
  74. package/dist/types/src/direction.d.ts +16 -0
  75. package/dist/types/src/dynamic.d.ts +161 -0
  76. package/dist/types/src/entries/prompt.d.ts +11 -0
  77. package/dist/types/src/entries/schema.d.ts +8 -0
  78. package/dist/types/src/expr.d.ts +71 -0
  79. package/dist/types/src/extension.d.ts +4 -0
  80. package/dist/types/src/format.d.ts +112 -0
  81. package/dist/types/src/geometry.d.ts +40 -0
  82. package/dist/types/src/host/contract.d.ts +225 -0
  83. package/dist/types/src/host/decoders.d.ts +61 -0
  84. package/dist/types/src/host/index.d.ts +15 -0
  85. package/dist/types/src/host/package.d.ts +102 -0
  86. package/dist/types/src/host/policy.d.ts +107 -0
  87. package/dist/types/src/host/record-store.d.ts +103 -0
  88. package/dist/types/src/host/records.d.ts +45 -0
  89. package/dist/types/src/host/router.d.ts +38 -0
  90. package/dist/types/src/host/runtime.d.ts +213 -0
  91. package/dist/types/src/host/signature.d.ts +52 -0
  92. package/dist/types/src/host/sources.d.ts +22 -0
  93. package/dist/types/src/host/tools.d.ts +42 -0
  94. package/dist/types/src/host/transports.d.ts +109 -0
  95. package/dist/types/src/index.d.ts +70 -0
  96. package/dist/types/src/layout.d.ts +20 -0
  97. package/dist/types/src/limits.d.ts +21 -0
  98. package/dist/types/src/list.d.ts +133 -0
  99. package/dist/types/src/locale.d.ts +22 -0
  100. package/dist/types/src/macros.d.ts +29 -0
  101. package/dist/types/src/overlay.d.ts +27 -0
  102. package/dist/types/src/prompt.d.ts +44 -0
  103. package/dist/types/src/qr-code.d.ts +30 -0
  104. package/dist/types/src/recipes.d.ts +17 -0
  105. package/dist/types/src/reducer.d.ts +41 -0
  106. package/dist/types/src/resizable.d.ts +38 -0
  107. package/dist/types/src/schema.d.ts +7 -0
  108. package/dist/types/src/strings.d.ts +13 -0
  109. package/dist/types/src/style.d.ts +201 -0
  110. package/dist/types/src/test-preload.d.ts +1 -0
  111. package/dist/types/src/text-clusters.d.ts +11 -0
  112. package/dist/types/src/text-shimmer.d.ts +24 -0
  113. package/dist/types/src/theme-types.d.ts +162 -0
  114. package/dist/types/src/theme.d.ts +75 -0
  115. package/dist/types/src/themes.d.ts +22 -0
  116. package/dist/types/src/tree-guides.d.ts +17 -0
  117. package/dist/types/src/types.d.ts +320 -0
  118. package/dist/types/src/validate.d.ts +31 -0
  119. package/dist/types/src/voice-wave.d.ts +181 -0
  120. package/dist/types/src/web/base-css.d.ts +1 -0
  121. package/dist/types/src/web/box-css.d.ts +63 -0
  122. package/dist/types/src/web/coerce.d.ts +32 -0
  123. package/dist/types/src/web/custom-icons.generated.d.ts +4 -0
  124. package/dist/types/src/web/data.d.ts +107 -0
  125. package/dist/types/src/web/dates.d.ts +12 -0
  126. package/dist/types/src/web/form.d.ts +44 -0
  127. package/dist/types/src/web/host-types.d.ts +126 -0
  128. package/dist/types/src/web/index.d.ts +35 -0
  129. package/dist/types/src/web/inputs.d.ts +55 -0
  130. package/dist/types/src/web/list.d.ts +16 -0
  131. package/dist/types/src/web/listbox.d.ts +14 -0
  132. package/dist/types/src/web/markdown.d.ts +96 -0
  133. package/dist/types/src/web/media.d.ts +63 -0
  134. package/dist/types/src/web/parts.d.ts +4 -0
  135. package/dist/types/src/web/primitives/alert-dialog.d.ts +10 -0
  136. package/dist/types/src/web/primitives/alert.d.ts +9 -0
  137. package/dist/types/src/web/primitives/avatar-color.d.ts +2 -0
  138. package/dist/types/src/web/primitives/avatar.d.ts +13 -0
  139. package/dist/types/src/web/primitives/badge.d.ts +10 -0
  140. package/dist/types/src/web/primitives/breadcrumb.d.ts +10 -0
  141. package/dist/types/src/web/primitives/button.d.ts +6 -0
  142. package/dist/types/src/web/primitives/calendar.d.ts +43 -0
  143. package/dist/types/src/web/primitives/card.d.ts +9 -0
  144. package/dist/types/src/web/primitives/checkbox.d.ts +5 -0
  145. package/dist/types/src/web/primitives/choice-tiles.d.ts +32 -0
  146. package/dist/types/src/web/primitives/cn.d.ts +3 -0
  147. package/dist/types/src/web/primitives/code-block.d.ts +24 -0
  148. package/dist/types/src/web/primitives/command.d.ts +134 -0
  149. package/dist/types/src/web/primitives/context-ring.d.ts +24 -0
  150. package/dist/types/src/web/primitives/dialog-arms.d.ts +6 -0
  151. package/dist/types/src/web/primitives/dialog.d.ts +24 -0
  152. package/dist/types/src/web/primitives/disclosure-header.d.ts +5 -0
  153. package/dist/types/src/web/primitives/dock.d.ts +42 -0
  154. package/dist/types/src/web/primitives/dropdown-menu.d.ts +14 -0
  155. package/dist/types/src/web/primitives/empty-state.d.ts +15 -0
  156. package/dist/types/src/web/primitives/glass-card.d.ts +4 -0
  157. package/dist/types/src/web/primitives/hover-card.d.ts +7 -0
  158. package/dist/types/src/web/primitives/icon-disc.d.ts +12 -0
  159. package/dist/types/src/web/primitives/index.d.ts +50 -0
  160. package/dist/types/src/web/primitives/input.d.ts +5 -0
  161. package/dist/types/src/web/primitives/kbd.d.ts +4 -0
  162. package/dist/types/src/web/primitives/label.d.ts +3 -0
  163. package/dist/types/src/web/primitives/measure.d.ts +16 -0
  164. package/dist/types/src/web/primitives/menu-surface.d.ts +17 -0
  165. package/dist/types/src/web/primitives/meter.d.ts +21 -0
  166. package/dist/types/src/web/primitives/popover.d.ts +3 -0
  167. package/dist/types/src/web/primitives/progress-ring.d.ts +5 -0
  168. package/dist/types/src/web/primitives/progress.d.ts +8 -0
  169. package/dist/types/src/web/primitives/scroll-area.d.ts +49 -0
  170. package/dist/types/src/web/primitives/segmented-control.d.ts +5 -0
  171. package/dist/types/src/web/primitives/select.d.ts +47 -0
  172. package/dist/types/src/web/primitives/separator.d.ts +3 -0
  173. package/dist/types/src/web/primitives/sheet-chrome.d.ts +4 -0
  174. package/dist/types/src/web/primitives/sheet.d.ts +20 -0
  175. package/dist/types/src/web/primitives/skeleton.d.ts +3 -0
  176. package/dist/types/src/web/primitives/spinner.d.ts +3 -0
  177. package/dist/types/src/web/primitives/switch.d.ts +4 -0
  178. package/dist/types/src/web/primitives/table.d.ts +11 -0
  179. package/dist/types/src/web/primitives/tabs.d.ts +13 -0
  180. package/dist/types/src/web/primitives/textarea.d.ts +3 -0
  181. package/dist/types/src/web/primitives/toast.d.ts +163 -0
  182. package/dist/types/src/web/primitives/tooltip.d.ts +3 -0
  183. package/dist/types/src/web/primitives/truncate.d.ts +7 -0
  184. package/dist/types/src/web/primitives/typeahead-portal.d.ts +12 -0
  185. package/dist/types/src/web/primitives/voice-wave.d.ts +50 -0
  186. package/dist/types/src/web/round5.d.ts +107 -0
  187. package/dist/types/src/web/share.d.ts +6 -0
  188. package/dist/types/src/web/table.d.ts +20 -0
  189. package/dist/types/src/web/theme-css.d.ts +69 -0
  190. package/dist/types/src/web/urls.d.ts +21 -0
  191. package/dist/web/index.js +2565 -0
  192. package/dist/web/index.js.map +28 -0
  193. package/dist/web/primitives/index.js +1476 -0
  194. package/dist/web/primitives/index.js.map +57 -0
  195. package/docs/components.generated.json +6783 -0
  196. package/docs/package-format.md +182 -0
  197. package/docs/round-1-contract.md +679 -0
  198. package/docs/round-2-contract.md +476 -0
  199. package/docs/round-3-contract.md +174 -0
  200. package/docs/round-5-contract.md +268 -0
  201. package/docs/themes.generated.json +3647 -0
  202. package/fixtures/animations.json +2890 -0
  203. package/fixtures/bench-list.json +58 -0
  204. package/fixtures/bind-time.json +54734 -0
  205. package/fixtures/catalog-basic-map.json +1692 -0
  206. package/fixtures/catalog-components.json +10293 -0
  207. package/fixtures/catalog-extension.json +620 -0
  208. package/fixtures/catalog-macros.json +51805 -0
  209. package/fixtures/code-tokens.json +1993 -0
  210. package/fixtures/conformance-baseline.json +59016 -0
  211. package/fixtures/conformance-cases.json +49 -0
  212. package/fixtures/conformance-known.json +2111 -0
  213. package/fixtures/control-geometry.json +5129 -0
  214. package/fixtures/dashboard.data.json +74 -0
  215. package/fixtures/dashboard.json +781 -0
  216. package/fixtures/demo-surface.json +47 -0
  217. package/fixtures/format.json +870 -0
  218. package/fixtures/host-package.json +1262 -0
  219. package/fixtures/host-policy.json +1209 -0
  220. package/fixtures/host-router.json +2034 -0
  221. package/fixtures/host-transport.json +590 -0
  222. package/fixtures/interactions-round1.json +1058 -0
  223. package/fixtures/kitchen-sink.expanded.json +11972 -0
  224. package/fixtures/kitchen-sink.json +3140 -0
  225. package/fixtures/layout-geometry-round1.json +7278 -0
  226. package/fixtures/layout-geometry.json +2072 -0
  227. package/fixtures/overlay-geometry.json +272 -0
  228. package/fixtures/pointer.json +89 -0
  229. package/fixtures/primitive-specimens.json +59 -0
  230. package/fixtures/prompt-budget.json +33 -0
  231. package/fixtures/qr-code.json +480 -0
  232. package/fixtures/resizable.json +714 -0
  233. package/fixtures/round4-contract.json +2985 -0
  234. package/fixtures/specimens.json +11168 -0
  235. package/fixtures/style-conditions.json +336 -0
  236. package/fixtures/template-items.json +2215 -0
  237. package/fixtures/text-clusters.json +65 -0
  238. package/fixtures/text-direction.json +309 -0
  239. package/fixtures/text-shimmer.json +96 -0
  240. package/fixtures/theme-extends.json +573 -0
  241. package/fixtures/theme-invalid.json +1300 -0
  242. package/fixtures/theme-recipes.json +61762 -0
  243. package/fixtures/theme-resolved.json +25969 -0
  244. package/fixtures/toast-stack.json +215 -0
  245. package/fixtures/tree-guides.json +224 -0
  246. package/fixtures/virtual-list.json +733 -0
  247. package/fixtures/voice-wave.json +19236 -0
  248. package/generated/ExponentialUICatalog.generated.kt +67 -0
  249. package/generated/ExponentialUICatalog.generated.swift +67 -0
  250. package/generated/ExponentialUIThemes.generated.kt +23 -0
  251. package/generated/ExponentialUIThemes.generated.swift +23 -0
  252. package/generated/catalog.descriptions.generated.rs +6 -0
  253. package/generated/catalog.generated.rs +80 -0
  254. package/generated/catalog.themes.generated.rs +34 -0
  255. package/generated/core.descriptions.json +2726 -0
  256. package/generated/core.runtime.json +3944 -0
  257. package/package.json +87 -4
  258. package/themes/exponential.recipes.json +49 -0
  259. package/themes/exponential.theme.json +768 -0
  260. package/themes/neutral.theme.json +6178 -0
  261. package/themes/orange.theme.json +43 -0
  262. package/themes/playful.theme.json +219 -0
  263. package/vendor/a2ui/LICENSE.txt +203 -0
  264. package/vendor/a2ui/README.md +27 -0
  265. package/vendor/a2ui/v0_9/basic_catalog.json +1387 -0
  266. package/vendor/a2ui/v0_9/basic_catalog_rules.txt +5 -0
  267. package/vendor/a2ui/v0_9/client_capabilities.json +97 -0
  268. package/vendor/a2ui/v0_9/client_to_server.json +104 -0
  269. package/vendor/a2ui/v0_9/common_types.json +315 -0
  270. package/vendor/a2ui/v0_9/server_to_client.json +132 -0
  271. package/vendor/json-render/LICENSE.txt +201 -0
  272. package/vendor/json-render/README.md +13 -0
  273. package/vendor/nayuki-qr/LICENSE.txt +20 -0
  274. package/vendor/nayuki-qr/README.md +10 -0
@@ -0,0 +1,6 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ export declare const buttonVariants: (props?: ({
3
+ variant?: "link" | "text" | "default" | "secondary" | "outline" | "ghost" | "destructive" | "glass" | null | undefined;
4
+ size?: "icon" | "default" | "sm" | "lg" | "xs" | "icon-sm" | "icon-xs" | "icon-lg" | "inline" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ export type ButtonVariantProps = VariantProps<typeof buttonVariants>;
@@ -0,0 +1,43 @@
1
+ export declare const CALENDAR_CLASSES: {
2
+ readonly root: string;
3
+ readonly classNames: {
4
+ readonly root: "w-fit";
5
+ readonly months: "relative flex flex-col gap-4 md:flex-row";
6
+ readonly month: "flex w-full flex-col gap-4";
7
+ readonly nav: "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1";
8
+ readonly button_previous: "size-(--cell-size) p-0 select-none aria-disabled:opacity-50";
9
+ readonly button_next: "size-(--cell-size) p-0 select-none aria-disabled:opacity-50";
10
+ readonly month_caption: "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)";
11
+ readonly dropdowns: "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium";
12
+ readonly dropdown_root: "relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50";
13
+ readonly dropdown: "absolute inset-0 bg-popover opacity-0";
14
+ readonly caption_label: "font-medium select-none";
15
+ readonly table: "w-full border-collapse";
16
+ readonly weekdays: "flex";
17
+ readonly weekday: "flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none";
18
+ readonly week: "mt-2 flex w-full";
19
+ readonly week_number_header: "w-(--cell-size) select-none";
20
+ readonly week_number: "text-[0.8rem] text-muted-foreground select-none";
21
+ readonly day: "group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md";
22
+ readonly range_start: "rounded-l-md bg-accent";
23
+ readonly range_middle: "rounded-none";
24
+ readonly range_end: "rounded-r-md bg-accent";
25
+ readonly today: "rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none";
26
+ readonly outside: "text-muted-foreground aria-selected:text-muted-foreground";
27
+ readonly disabled: "text-muted-foreground opacity-50";
28
+ readonly hidden: "invisible";
29
+ };
30
+ /** `caption_label` per `captionLayout`: `label`, else a dropdown. */
31
+ readonly captionLabel: {
32
+ readonly label: "text-sm";
33
+ readonly dropdown: "flex h-8 items-center gap-1 rounded-md pr-1 pl-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground";
34
+ };
35
+ /** The `day` cell's first-selected corner, with or without week numbers. */
36
+ readonly dayFirst: {
37
+ readonly weekNumbers: "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md";
38
+ readonly plain: "[&:first-child[data-selected=true]_button]:rounded-l-md";
39
+ };
40
+ readonly chevron: "size-4";
41
+ readonly weekNumber: "flex size-(--cell-size) items-center justify-center text-center";
42
+ readonly dayButton: "flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70";
43
+ };
@@ -0,0 +1,9 @@
1
+ export declare const CARD_CLASSES: {
2
+ readonly root: "rounded-xl border border-glass-stroke-card bg-glass-card-opaque flex flex-col gap-6 backdrop-blur-md py-6 text-card-foreground shadow-sm";
3
+ readonly header: "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6";
4
+ readonly title: "leading-none font-semibold";
5
+ readonly description: "text-sm text-muted-foreground";
6
+ readonly action: "col-start-2 row-span-2 row-start-1 self-start justify-self-end";
7
+ readonly content: "px-6";
8
+ readonly footer: "flex items-center px-6 [.border-t]:pt-6";
9
+ };
@@ -0,0 +1,5 @@
1
+ export declare const CHECKBOX_CLASSES: {
2
+ readonly root: "peer size-4 shrink-0 rounded-[4px] border border-glass-stroke-strong bg-glass-row shadow-none transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary";
3
+ readonly indicator: "grid place-content-center text-current transition-none";
4
+ readonly icon: "size-3.5";
5
+ };
@@ -0,0 +1,32 @@
1
+ export interface ChoiceTileOption {
2
+ value: string;
3
+ label: string;
4
+ description?: string | null;
5
+ /** The picture's url (a relative `/api/attachments/{id}` resolves in the
6
+ * app through `renderImage`). */
7
+ image?: string | null;
8
+ disabled?: boolean;
9
+ }
10
+ /** `columns` clamped to 1–4 (default 2). */
11
+ export declare function choiceColumns(columns: unknown): number;
12
+ /** The values a comma-joined eUI `value` picks (single: the whole string). */
13
+ export declare function choiceValues(value: unknown, multiple: boolean): string[];
14
+ /** A press on `value`: single picks it; multiple toggles it, the list kept in
15
+ * OPTION order (fixtures/interactions-round1.json `choiceTiles`). */
16
+ export declare function choiceToggle(picked: readonly string[], value: string, multiple: boolean, order: readonly string[]): string[];
17
+ export interface TileState {
18
+ index: number;
19
+ selected: boolean;
20
+ disabled: boolean;
21
+ }
22
+ export declare const CHOICE_TILES_CLASSES: {
23
+ readonly root: "gap-[8px]";
24
+ readonly tile: "flex min-w-0 cursor-pointer flex-col gap-[4px] rounded-[10px] border-[1px] border-border bg-card p-[8px] text-start outline-none transition-colors hover:bg-secondary focus-visible:border-ring disabled:cursor-not-allowed disabled:opacity-50";
25
+ readonly tileSelected: "border-[2px] border-primary bg-accent p-[7px] hover:bg-accent";
26
+ readonly tileInvalid: "border-destructive";
27
+ readonly picture: "relative flex aspect-[1.6] w-full shrink-0 items-center justify-center overflow-hidden rounded-[6px] bg-muted text-muted-foreground";
28
+ readonly image: "absolute inset-0 size-full object-cover";
29
+ readonly placeholder: "size-[20px] opacity-60";
30
+ readonly label: "min-w-0 text-sm leading-5 font-medium text-foreground";
31
+ readonly description: "min-w-0 text-xs leading-4 text-muted-foreground";
32
+ };
@@ -0,0 +1,3 @@
1
+ import { type ClassValue } from "clsx";
2
+ export declare function cn(...inputs: ClassValue[]): string;
3
+ export declare function getInitials(value: string): string;
@@ -0,0 +1,24 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ export declare const codeBlockVariants: (props?: ({
3
+ variant?: "default" | "destructive" | null | undefined;
4
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
+ export type CodeBlockVariantProps = VariantProps<typeof codeBlockVariants>;
6
+ /** The catalog's `codeToken` kinds, painted with the app's code palette
7
+ * (`--hljs-*`, the diff view's and the editor's); a destructive block drops
8
+ * the colours for its own. */
9
+ export declare const CODE_TOKEN_CLASS: Record<string, string>;
10
+ export declare const codeBlockLineVariants: (props?: ({
11
+ variant?: "default" | "added" | "removed" | "highlighted" | null | undefined;
12
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
13
+ export type CodeBlockLineVariantProps = VariantProps<typeof codeBlockLineVariants>;
14
+ export declare const CODE_BLOCK_CLASSES: {
15
+ readonly header: "flex min-w-0 shrink-0 items-center gap-2 px-3 pt-3 text-muted-foreground group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:pt-2.5 group-data-[variant=destructive]/code-block:text-destructive *:has-[>[data-slot=code-block-title]]:min-w-0";
16
+ readonly title: "min-w-0 truncate font-sans text-sm font-medium text-foreground group-data-[size=sm]/code-block:text-xs group-data-[variant=destructive]/code-block:text-destructive [&_svg]:pointer-events-none [&_svg]:inline-block [&_svg]:align-middle [&_svg:not([class*='size-'])]:size-3.5 *:[svg]:me-1.5";
17
+ readonly actions: "-my-1 ms-auto -me-1 flex shrink-0 items-center gap-1 [[data-slot=code-block]>&]:absolute [[data-slot=code-block]>&]:end-2 [[data-slot=code-block]>&]:top-2 [[data-slot=code-block]>&]:z-10 [[data-slot=code-block]>&]:m-0 [[data-slot=code-block]>&]:opacity-0 [[data-slot=code-block]>&]:transition-opacity [[data-slot=code-block]>&]:group-focus-within/code-block:opacity-100 [[data-slot=code-block]>&]:group-hover/code-block:opacity-100 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:end-1.5 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:top-1.5 [[data-slot=code-block]>&]:pointer-coarse:opacity-100 [[data-slot=code-block]>&]:*:[button]:bg-background [[data-slot=code-block]>&]:*:[button]:ring-1 [[data-slot=code-block]>&]:*:[button]:ring-foreground/10";
18
+ readonly srOnly: "sr-only";
19
+ readonly content: "min-h-0 min-w-0 scroll-fade-x overflow-auto overscroll-contain px-3 py-3 text-start font-mono leading-relaxed outline-none [--code-block-pad:calc(var(--spacing)*6)] group-has-data-[slot=code-block-footer]/code-block:pb-2 group-has-data-[slot=code-block-header]/code-block:pt-2 group-has-data-[slot=code-block-header]/code-block:[--code-block-pad:calc(var(--spacing)*5)] group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:py-2.5 group-data-[size=sm]/code-block:[--code-block-pad:calc(var(--spacing)*5)] group-data-[size=sm]/code-block:group-has-data-[slot=code-block-header]/code-block:pt-1.5 group-data-[size=sm]/code-block:group-has-data-[slot=code-block-header]/code-block:[--code-block-pad:calc(var(--spacing)*4)] data-wrap:scroll-fade-y data-wrap:wrap-break-word data-wrap:whitespace-pre-wrap";
20
+ readonly code: "grid min-h-lh min-w-max content-start in-data-numbered:grid-cols-[auto_1fr] in-data-wrap:min-w-0";
21
+ readonly token: "group-data-[variant=destructive]/code-block:text-current";
22
+ readonly lineContent: "min-w-0";
23
+ readonly footer: "flex min-w-0 shrink-0 items-center gap-2 px-3 pb-3 text-muted-foreground group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:pb-2.5";
24
+ };
@@ -0,0 +1,134 @@
1
+ export declare const COMMAND_CLASSES: {
2
+ readonly root: "flex h-full w-full flex-col overflow-hidden rounded-md bg-transparent text-popover-foreground";
3
+ readonly inputWrapper: "flex h-9 items-center gap-2 border-b border-glass-stroke px-3";
4
+ readonly inputGlyph: "size-4 shrink-0 opacity-50";
5
+ readonly input: "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-foreground/50 disabled:cursor-not-allowed disabled:opacity-50";
6
+ readonly inputClear: string;
7
+ readonly list: "max-h-[18.75rem] scroll-py-1 overflow-x-hidden overflow-y-auto";
8
+ readonly empty: "py-6 text-center text-sm";
9
+ readonly group: "overflow-hidden p-(--menu-surface-padding) text-foreground";
10
+ readonly groupHeading: "px-(--menu-item-padding-x) py-1.5 text-xs font-medium text-muted-foreground";
11
+ readonly item: "relative flex min-h-(--menu-item-height) cursor-pointer items-center gap-(--menu-item-gap) rounded-sm px-(--menu-item-padding-x) py-1 text-sm text-foreground/90 outline-hidden select-none data-[disabled=true]:cursor-default data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-glass-active data-[selected=true]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--menu-icon-size) [&_svg:not([class*='text-'])]:text-muted-foreground";
12
+ readonly separator: "-mx-(--menu-surface-padding) my-(--menu-surface-padding) h-px bg-glass-stroke";
13
+ readonly shortcut: "ml-auto text-xs tracking-widest text-muted-foreground";
14
+ };
15
+ /** cmdk's visually hidden `<label>` (its inline style, in its order). */
16
+ export declare const COMMAND_LABEL_STYLE: {
17
+ readonly position: "absolute";
18
+ readonly width: "1px";
19
+ readonly height: "1px";
20
+ readonly padding: "0";
21
+ readonly margin: "-1px";
22
+ readonly overflow: "hidden";
23
+ readonly clip: "rect(0, 0, 0, 0)";
24
+ readonly whiteSpace: "nowrap";
25
+ readonly borderWidth: "0";
26
+ };
27
+ /** cmdk's `command-score`: 1 = exact, prefix > word boundary > fuzzy,
28
+ * 0 = no match. `keywords` extend the value (`value + " " + keywords`). */
29
+ export declare function commandScore(value: string, query: string, keywords?: readonly string[]): number;
30
+ export type CommandFilter = (value: string, query: string, keywords?: readonly string[]) => number;
31
+ export interface CommandFilterItem {
32
+ id: string;
33
+ value: string;
34
+ keywords?: readonly string[];
35
+ /** The group's id; none = an ungrouped item. */
36
+ group?: string;
37
+ disabled?: boolean;
38
+ /** Always visible, never counted (cmdk's `forceMount`). */
39
+ forceMount?: boolean;
40
+ }
41
+ export interface CommandFilterResult {
42
+ /** Matching (non-forced) items: 0 = the empty state. */
43
+ count: number;
44
+ /** Ungrouped items first, then the groups by their best score; ids by score. */
45
+ groups: {
46
+ group: string | undefined;
47
+ ids: string[];
48
+ }[];
49
+ scores: Map<string, number>;
50
+ }
51
+ /** The visible ids per group, in display order. An empty query keeps the
52
+ * registration order and shows everything; otherwise score > 0 shows,
53
+ * items sort by score (stable), groups by their best item. */
54
+ export declare function filterCommandItems(items: readonly CommandFilterItem[], query: string, filter?: CommandFilter): CommandFilterResult;
55
+ export declare const COMMAND_SELECT_EVENT = "command-item-select";
56
+ type Kind = `item` | `group` | `separator`;
57
+ interface Entry {
58
+ id: string;
59
+ kind: Kind;
60
+ seq: number;
61
+ el: HTMLElement | null;
62
+ value: string;
63
+ keywords?: string[];
64
+ group?: string;
65
+ disabled?: boolean;
66
+ forceMount?: boolean;
67
+ }
68
+ export interface CommandStoreOptions {
69
+ /** The root's live props. */
70
+ props: () => {
71
+ value?: string;
72
+ onValueChange?: (value: string) => void;
73
+ filter?: CommandFilter;
74
+ shouldFilter?: boolean;
75
+ loop?: boolean;
76
+ };
77
+ /** Ask the renderer for a flush after the DOM caught up (React: a root
78
+ * re-render + layout effect; Solid: a microtask). */
79
+ schedule: () => void;
80
+ }
81
+ /** The command root's state (cmdk's store), framework-free: the query, the
82
+ * selected value, the registry (items, groups, separators in creation
83
+ * order) and the post-render pass (`flush`: DOM order, first-item
84
+ * selection, the active descendant, scroll). Renderers subscribe and
85
+ * re-render on `emit`. */
86
+ export declare function createCommandStore(o: CommandStoreOptions): {
87
+ readonly version: number;
88
+ readonly search: string;
89
+ readonly value: string;
90
+ readonly selectedId: string | undefined;
91
+ subscribe(listener: () => void): () => undefined;
92
+ nextSeq: () => number;
93
+ /** The query (the input); `silent` = during the first render. */
94
+ setSearch(next: string, silent?: boolean): void;
95
+ setValue: (next: string, opts?: {
96
+ pointer?: boolean;
97
+ }) => void;
98
+ /** Re-read the controlled `value` prop (no callback). */
99
+ syncValue(): boolean;
100
+ setSizer(el: HTMLElement | null): void;
101
+ filtering: () => boolean;
102
+ /** An item's score now (1 when nothing filters). */
103
+ score(itemValue: string, keywords?: readonly string[]): number;
104
+ /** Whether a group shows (some registered item of it matches). */
105
+ groupVisible(groupId: string): boolean;
106
+ /** The empty state: no matching (non-forced) item. */
107
+ empty(): boolean;
108
+ register(entry: {
109
+ id: string;
110
+ kind: Kind;
111
+ seq: number;
112
+ value?: string;
113
+ keywords?: string[];
114
+ group?: string;
115
+ disabled?: boolean;
116
+ forceMount?: boolean;
117
+ }): () => void;
118
+ /** An entry's element (null = not rendered) or item fields. */
119
+ update(id: string, patch: Partial<Pick<Entry, `el` | `value` | `keywords` | `disabled`>>): void;
120
+ /** The post-render pass: DOM order, the first item selected (after a
121
+ * query change or when nothing is selected), the active descendant,
122
+ * the selected item scrolled into view. Idempotent. */
123
+ flush(): void;
124
+ /** cmdk's root keys. */
125
+ onKeyDown(e: KeyboardEvent): void;
126
+ };
127
+ export type CommandStore = ReturnType<typeof createCommandStore>;
128
+ /** An item's value: the `value` prop, else string children, else the
129
+ * rendered text (trimmed), else the last known one. */
130
+ export declare function commandItemValue(value: string | undefined, children: unknown, el: Element | null | undefined, known: string): string;
131
+ /** CommandList's `--cmdk-list-height` (cmdk: the sizer's offsetHeight,
132
+ * ResizeObserver → rAF). Returns the disposer. */
133
+ export declare function observeCommandListHeight(list: HTMLElement, sizer: HTMLElement): () => void;
134
+ export {};
@@ -0,0 +1,24 @@
1
+ /** The ring's box, in px — a footer glyph, the size of a small icon. */
2
+ export declare const RING_SIZE = 16;
3
+ /** Stroke width of both the track and the progress arc. */
4
+ export declare const RING_STROKE = 2;
5
+ /** Radius of the stroked circle: the box minus one stroke, halved, so the
6
+ * stroke sits fully inside the box (`(16 - 2) / 2 = 7`… minus a hair, so the
7
+ * arc's round join never clips). */
8
+ export declare const RING_RADIUS = 6;
9
+ export interface RingGeometry {
10
+ /** The full circle's length — the dash array. */
11
+ circumference: number;
12
+ /** How much of it to hide: the UNfilled remainder. */
13
+ dashOffset: number;
14
+ }
15
+ /** The arc for `percent`, clamped to 0..100 (a NaN reads as empty). */
16
+ export declare function ringGeometry(percent: number): RingGeometry;
17
+ /** The three tones every usage surface shares — the app maps its thresholds
18
+ * (`severity`, lib/agent-usage.ts) onto them, never the other way round. */
19
+ export type RingTone = `normal` | `warning` | `danger`;
20
+ export declare const RING_TONE_CLASS: Record<RingTone, string>;
21
+ export declare const CONTEXT_RING_CLASSES: {
22
+ readonly root: "shrink-0";
23
+ readonly svg: "-rotate-90";
24
+ };
@@ -0,0 +1,6 @@
1
+ export declare const MOBILE_SHEET = "max-sm:inset-x-0 max-sm:bottom-0 max-sm:w-full max-sm:rounded-t-3xl max-sm:border-t max-sm:border-glass-stroke-card max-sm:bg-glass-bottom max-sm:px-4 max-sm:pt-0 max-sm:pb-[max(1rem,env(safe-area-inset-bottom))] max-sm:motion-sheet max-sm:data-[state=closed]:slide-out-to-bottom max-sm:data-[state=open]:slide-in-from-bottom sm:p-6 max-sm:h-auto max-sm:max-h-[90dvh]";
2
+ export declare const MOBILE_SHEET_FULL = "max-sm:inset-x-0 max-sm:bottom-0 max-sm:w-full max-sm:rounded-t-3xl max-sm:border-t max-sm:border-glass-stroke-card max-sm:bg-glass-bottom max-sm:px-4 max-sm:pt-0 max-sm:pb-[max(1rem,env(safe-area-inset-bottom))] max-sm:motion-sheet max-sm:data-[state=closed]:slide-out-to-bottom max-sm:data-[state=open]:slide-in-from-bottom sm:p-6 max-sm:h-[94dvh]";
3
+ export declare const MOBILE_ALERT = "max-sm:top-1/2 max-sm:left-1/2 max-sm:w-[calc(100%-3rem)] max-sm:max-w-sm max-sm:max-h-[calc(100dvh-3rem)] max-sm:-translate-x-1/2 max-sm:-translate-y-1/2 max-sm:rounded-2xl max-sm:border max-sm:border-glass-stroke-card max-sm:bg-glass-bottom max-sm:p-5 sm:p-6";
4
+ export declare const MOBILE_PAGE = "max-sm:inset-0 max-sm:w-full max-sm:bg-background max-sm:p-6 sm:p-6";
5
+ export type DialogMobileArm = `sheet` | `sheet-full` | `alert` | `page`;
6
+ export declare const MOBILE_ARMS: Record<DialogMobileArm, string>;
@@ -0,0 +1,24 @@
1
+ /** Below `sm` a sheet-arm dialog IS the bottom sheet (EXP-687 → the UI
2
+ * cleanup batch's "one phone sheet"). */
3
+ export declare const DIALOG_PHONE_QUERY = "(max-width: 639px)";
4
+ export declare const DIALOG_CLASSES: {
5
+ readonly overlay: "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:duration-fast data-[state=closed]:ease-accelerate data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:duration-standard data-[state=open]:ease-decelerate";
6
+ readonly phoneSheet: "gap-4 overflow-hidden px-4 pt-0 pb-[max(1rem,env(safe-area-inset-bottom))] outline-none";
7
+ readonly phoneSheetFull: "h-[94dvh] max-h-[94dvh]";
8
+ readonly content: "fixed z-50 flex flex-col gap-4 overflow-hidden shadow-lg outline-none motion-dialog sm:inset-auto sm:top-[50%] sm:left-[50%] sm:max-h-[calc(100dvh-2rem)] sm:w-[calc(100%-2rem)] sm:max-w-lg sm:translate-x-[-50%] sm:translate-y-[-50%] sm:rounded-2xl sm:border sm:border-glass-stroke-card sm:bg-card/85 sm:shadow-2xl sm:shadow-black/40 sm:backdrop-blur-2xl";
9
+ /** The sheet arms' grabber on the centred panel: a phone only. */
10
+ readonly grabber: "hidden max-sm:block";
11
+ /** The hidden Close a drag-to-dismiss clicks. */
12
+ readonly dragClose: "hidden";
13
+ readonly close: "absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
14
+ readonly closePhoneHidden: "max-sm:hidden";
15
+ readonly srOnly: "sr-only";
16
+ readonly header: "flex flex-col gap-2 text-left";
17
+ readonly body: "min-h-0 flex-1 overflow-y-auto";
18
+ readonly footer: "flex flex-col-reverse gap-2 max-sm:[&>[data-slot=button]]:h-10 max-sm:[&>[data-slot=button]]:w-full max-sm:[&>[data-slot=button]]:px-6 sm:flex-row sm:justify-end";
19
+ /** The Cancel of a sheet arm on a phone (EXP-687): hidden, a sheet is
20
+ * dismissed by dragging it down or tapping outside; `alert`/`page` keep it. */
21
+ readonly cancelPhoneHidden: "max-sm:hidden";
22
+ readonly title: "text-lg leading-none font-semibold";
23
+ readonly description: "text-sm text-muted-foreground";
24
+ };
@@ -0,0 +1,5 @@
1
+ export declare const DISCLOSURE_HEADER_CLASSES: {
2
+ readonly root: "flex w-full min-w-0 cursor-pointer items-center gap-2 rounded-sm text-left text-muted-foreground transition-colors duration-fast outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50";
3
+ readonly chevron: "size-3 shrink-0";
4
+ readonly chevronTrailing: "ml-auto";
5
+ };
@@ -0,0 +1,42 @@
1
+ import { type StackConstants, type ToastStackItem } from "./toast.js";
2
+ export declare const DOCK_PILE_CONSTANTS: StackConstants;
3
+ export type DockCardTint = `plan` | `question` | `muted` | `warning`;
4
+ export declare const DOCK_CARD_CLASSES: {
5
+ /** THE card: the glass card (ONE gray: the opaque card fill under the
6
+ * card hairline), padded. */
7
+ readonly root: "rounded-xl border border-glass-stroke-card bg-glass-card-opaque block w-full p-3 text-left outline-none";
8
+ /** A card that opens (a press, Enter or Space). */
9
+ readonly pressable: "cursor-pointer transition-colors duration-fast hover:bg-glass-active focus-visible:ring-[3px] focus-visible:ring-ring/50";
10
+ /** The glyph + text row; a card behind the front one hides its words. */
11
+ readonly body: "flex items-start gap-2 data-[hidden=true]:opacity-0";
12
+ readonly icon: "mt-0.5 size-3.5 shrink-0";
13
+ readonly text: "min-w-0 flex-1";
14
+ readonly header: "mb-1 flex items-center gap-2";
15
+ readonly label: "truncate text-xs font-medium";
16
+ readonly caption: "min-w-0 truncate text-xs text-muted-foreground";
17
+ readonly meta: "ml-auto shrink-0 text-xs text-muted-foreground";
18
+ readonly row: "flex min-w-0 items-center gap-2";
19
+ readonly title: "min-w-0 flex-1 truncate text-sm text-foreground/90";
20
+ readonly chevron: "size-3.5 shrink-0 text-muted-foreground";
21
+ readonly trailing: "shrink-0";
22
+ /** The tint sits on the glyph and the label alone. */
23
+ readonly tint: {
24
+ plan: string;
25
+ question: string;
26
+ muted: string;
27
+ warning: string;
28
+ };
29
+ };
30
+ export declare const DOCK_PILE_CLASSES: {
31
+ /** The pile box: its height = the geometry's, animated over `slow`. */
32
+ readonly root: "relative transition-[height] duration-slow ease-standard motion-reduce:transition-none";
33
+ /** One card, placed by `--offset`/`--scale`; it shrinks about the TOP
34
+ * edge (the one that peeks out above the front card). */
35
+ readonly item: "absolute inset-x-0 top-(--offset) origin-top scale-(--scale) transition-[top,scale,opacity] duration-slow ease-standard motion-reduce:transition-none data-[visible=false]:pointer-events-none data-[visible=false]:opacity-0";
36
+ };
37
+ /** The pile's geometry: `stackGeometry` with the Dock's numbers, anchored
38
+ * at the bottom (the front card is the LAST height). */
39
+ export declare function dockPileGeometry(heights: readonly number[], expanded: boolean): {
40
+ height: number;
41
+ items: ToastStackItem[];
42
+ };
@@ -0,0 +1,14 @@
1
+ export declare const DROPDOWN_MENU_CLASSES: {
2
+ readonly content: "z-50 rounded-lg border border-glass-stroke-card bg-glass-card-opaque text-popover-foreground motion-popover min-w-(--menu-min-width) max-w-(--menu-max-width) p-(--menu-surface-padding) max-h-(--radix-dropdown-menu-content-available-height) origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto";
3
+ readonly item: "relative flex min-h-(--menu-item-height) cursor-pointer items-center gap-(--menu-item-gap) rounded-sm px-(--menu-item-padding-x) py-1 text-sm text-foreground/90 outline-hidden select-none focus:bg-glass-active focus:text-foreground data-[disabled]:cursor-default data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--menu-icon-size) [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:text-destructive! data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
4
+ readonly checkItem: "relative flex min-h-(--menu-item-height) cursor-pointer items-center gap-(--menu-item-gap) rounded-sm py-1 pr-(--menu-item-padding-x) pl-8 text-sm text-foreground/90 outline-hidden select-none focus:bg-glass-active focus:text-foreground data-[disabled]:cursor-default data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--menu-icon-size)";
5
+ readonly itemIndicator: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center";
6
+ readonly checkIcon: "size-4";
7
+ readonly radioIcon: "size-2 fill-current";
8
+ readonly label: "px-(--menu-item-padding-x) py-1.5 text-sm font-medium data-[inset]:pl-8";
9
+ readonly separator: "-mx-(--menu-surface-padding) my-(--menu-surface-padding) h-px bg-glass-stroke";
10
+ readonly shortcut: "ml-auto text-xs tracking-widest text-muted-foreground";
11
+ readonly subTrigger: "flex min-h-(--menu-item-height) cursor-pointer items-center gap-(--menu-item-gap) rounded-sm px-(--menu-item-padding-x) py-1 text-sm text-foreground/90 outline-hidden select-none focus:bg-glass-active focus:text-foreground data-[disabled]:cursor-default data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--menu-icon-size) [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:text-destructive! whitespace-nowrap data-[state=open]:bg-glass-active data-[variant=destructive]:data-[state=open]:bg-destructive/10 data-[variant=destructive]:data-[state=open]:text-destructive [&>span+svg:last-child]:ml-0";
12
+ readonly subChevron: "ml-auto size-(--menu-icon-size) shrink-0";
13
+ readonly subContent: "z-50 rounded-lg border border-glass-stroke-card bg-glass-card-opaque text-popover-foreground motion-popover min-w-(--menu-min-width) max-w-(--menu-max-width) p-(--menu-surface-padding) origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden";
14
+ };
@@ -0,0 +1,15 @@
1
+ export declare const EMPTY_STATE_SIZES: readonly ["page", "list"];
2
+ export type EmptyStateSize = (typeof EMPTY_STATE_SIZES)[number];
3
+ export declare const EMPTY_STATE_CLASSES: {
4
+ readonly list: "flex w-full flex-col items-center gap-1.5 px-3 py-6 text-center text-sm text-muted-foreground";
5
+ readonly listIcon: "size-5 shrink-0 text-muted-foreground/60";
6
+ readonly page: "mx-auto flex max-w-md flex-col items-center gap-3 px-6 py-12 text-center";
7
+ readonly pageTitle: "text-lg font-semibold";
8
+ readonly pageDescription: "text-sm text-muted-foreground";
9
+ readonly pageActions: "mt-2 flex flex-wrap items-center justify-center gap-2";
10
+ readonly listEmpty: "px-3 py-6 text-center text-sm text-muted-foreground";
11
+ readonly cta: "flex w-full cursor-pointer flex-col items-start gap-1 rounded-md border border-dashed border-glass-stroke-strong p-3 text-left text-sm text-muted-foreground transition-colors duration-fast outline-none hover:bg-glass-row hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50";
12
+ readonly ctaTitle: "flex items-center gap-2";
13
+ readonly ctaIcon: "size-4 shrink-0";
14
+ readonly ctaDescription: "text-xs";
15
+ };
@@ -0,0 +1,4 @@
1
+ export declare const GLASS_CARD_CLASS = "rounded-xl border border-glass-stroke-card bg-glass-card-opaque";
2
+ export declare const GLASS_CARD_CLASSES: {
3
+ readonly root: "rounded-xl border border-glass-stroke-card bg-glass-card-opaque";
4
+ };
@@ -0,0 +1,7 @@
1
+ export declare const HOVER_CARD_DELAYS: {
2
+ readonly openDelay: 400;
3
+ readonly closeDelay: 100;
4
+ };
5
+ export declare const HOVER_CARD_CLASSES: {
6
+ readonly content: "z-50 rounded-lg border border-glass-stroke-card bg-glass-card-opaque text-popover-foreground motion-popover w-80 origin-(--radix-hover-card-content-transform-origin) p-3 outline-hidden";
7
+ };
@@ -0,0 +1,12 @@
1
+ export declare const ICON_DISC_TONES: readonly ["primary", "success", "danger", "muted"];
2
+ export type IconDiscTone = (typeof ICON_DISC_TONES)[number];
3
+ export declare const ICON_DISC_CLASSES: {
4
+ readonly root: "flex size-12 shrink-0 items-center justify-center rounded-full";
5
+ readonly tones: {
6
+ primary: string;
7
+ success: string;
8
+ danger: string;
9
+ muted: string;
10
+ };
11
+ readonly icon: "size-6";
12
+ };
@@ -0,0 +1,50 @@
1
+ export * from "./alert-dialog.js";
2
+ export * from "./alert.js";
3
+ export * from "./avatar-color.js";
4
+ export * from "./avatar.js";
5
+ export * from "./badge.js";
6
+ export * from "./breadcrumb.js";
7
+ export * from "./button.js";
8
+ export * from "./calendar.js";
9
+ export * from "./card.js";
10
+ export * from "./checkbox.js";
11
+ export * from "./choice-tiles.js";
12
+ export * from "./cn.js";
13
+ export * from "./code-block.js";
14
+ export * from "./command.js";
15
+ export * from "./context-ring.js";
16
+ export * from "./dialog-arms.js";
17
+ export * from "./dialog.js";
18
+ export * from "./disclosure-header.js";
19
+ export * from "./dock.js";
20
+ export * from "./dropdown-menu.js";
21
+ export * from "./empty-state.js";
22
+ export * from "./glass-card.js";
23
+ export * from "./hover-card.js";
24
+ export * from "./icon-disc.js";
25
+ export * from "./input.js";
26
+ export * from "./measure.js";
27
+ export * from "./kbd.js";
28
+ export * from "./label.js";
29
+ export * from "./menu-surface.js";
30
+ export * from "./meter.js";
31
+ export * from "./popover.js";
32
+ export * from "./progress-ring.js";
33
+ export * from "./progress.js";
34
+ export * from "./scroll-area.js";
35
+ export * from "./segmented-control.js";
36
+ export * from "./select.js";
37
+ export * from "./separator.js";
38
+ export * from "./sheet-chrome.js";
39
+ export * from "./sheet.js";
40
+ export * from "./skeleton.js";
41
+ export * from "./spinner.js";
42
+ export * from "./switch.js";
43
+ export * from "./table.js";
44
+ export * from "./tabs.js";
45
+ export * from "./textarea.js";
46
+ export * from "./toast.js";
47
+ export * from "./tooltip.js";
48
+ export * from "./truncate.js";
49
+ export * from "./typeahead-portal.js";
50
+ export * from "./voice-wave.js";
@@ -0,0 +1,5 @@
1
+ export declare const BARE_FIELD_CLASS = "h-auto min-w-0 flex-1 rounded-none border-0 bg-transparent p-0 text-sm shadow-none focus-visible:border-0 focus-visible:ring-0 md:text-sm";
2
+ export declare const FIELD_CHROME_CLASS = "h-9 w-full min-w-0 rounded-lg border border-glass-stroke-card bg-glass-card px-3 py-1 text-base shadow-none transition-[color,border-color] duration-fast outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-foreground/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-glass-stroke-active focus-visible:ring-0";
3
+ export declare const INPUT_CLASSES: {
4
+ readonly root: "h-9 w-full min-w-0 rounded-lg border border-glass-stroke-card bg-glass-card px-3 py-1 text-base shadow-none transition-[color,border-color] duration-fast outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-foreground/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-glass-stroke-active focus-visible:ring-0 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40";
5
+ };
@@ -0,0 +1,4 @@
1
+ export declare const KBD_CLASSES: {
2
+ readonly root: "pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none [&_svg:not([class*='size-'])]:size-3";
3
+ readonly group: "inline-flex items-center gap-1";
4
+ };
@@ -0,0 +1,3 @@
1
+ export declare const LABEL_CLASSES: {
2
+ readonly root: "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50";
3
+ };
@@ -0,0 +1,16 @@
1
+ export interface LayoutSize {
2
+ width: number;
3
+ height: number;
4
+ }
5
+ /** An element's border box in layout (unzoomed, untransformed) CSS px.
6
+ * `entry` = the ResizeObserver entry of this element, when there is one. */
7
+ export declare function layoutSize(el: HTMLElement, entry?: ResizeObserverEntry): LayoutSize;
8
+ /** Visual px per layout px on one axis: 1 when they agree within a pixel
9
+ * (an unscaled element maps byte-identically), else `visual / layout`.
10
+ * Divide a visual delta (a pointer offset, a rect difference) by it. */
11
+ export declare function visualScale(visual: number, layout: number): number;
12
+ /** `visualScale` of an element: its rect over its offset box. */
13
+ export declare function elementScale(el: HTMLElement, rect?: DOMRect): {
14
+ x: number;
15
+ y: number;
16
+ };
@@ -0,0 +1,17 @@
1
+ export declare const MENU_SURFACE_CLASS = "z-50 rounded-lg border border-glass-stroke-card bg-glass-card-opaque text-popover-foreground motion-popover";
2
+ export declare const MENU_CONTENT_CLASS = "min-w-(--menu-min-width) max-w-(--menu-max-width) p-(--menu-surface-padding)";
3
+ export declare const MENU_ITEM_CLASS = "relative flex min-h-(--menu-item-height) cursor-pointer items-center gap-(--menu-item-gap) rounded-sm px-(--menu-item-padding-x) py-1 text-sm text-foreground/90 outline-hidden select-none focus:bg-glass-active focus:text-foreground data-[disabled]:cursor-default data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--menu-icon-size) [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:text-destructive! data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
4
+ /** A submenu's label never wraps: the value beside it truncates instead.
5
+ * The value (a `MENU_VALUE_CLASS` span) and the chevron both push right;
6
+ * with a value present the chevron gives up its auto margin, so every value
7
+ * ends flush against the chevron column instead of floating mid-row. */
8
+ export declare const MENU_SUB_TRIGGER_CLASS = "flex min-h-(--menu-item-height) cursor-pointer items-center gap-(--menu-item-gap) rounded-sm px-(--menu-item-padding-x) py-1 text-sm text-foreground/90 outline-hidden select-none focus:bg-glass-active focus:text-foreground data-[disabled]:cursor-default data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--menu-icon-size) [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:text-destructive! whitespace-nowrap data-[state=open]:bg-glass-active data-[variant=destructive]:data-[state=open]:bg-destructive/10 data-[variant=destructive]:data-[state=open]:text-destructive [&>span+svg:last-child]:ml-0";
9
+ /** The checkbox / radio rows: the indicator sits in the `pl-8` inset. */
10
+ export declare const MENU_CHECK_ITEM_CLASS = "relative flex min-h-(--menu-item-height) cursor-pointer items-center gap-(--menu-item-gap) rounded-sm py-1 pr-(--menu-item-padding-x) pl-8 text-sm text-foreground/90 outline-hidden select-none focus:bg-glass-active focus:text-foreground data-[disabled]:cursor-default data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--menu-icon-size)";
11
+ export declare const MENU_LABEL_CLASS = "px-(--menu-item-padding-x) py-1.5 text-sm font-medium data-[inset]:pl-8";
12
+ export declare const MENU_SEPARATOR_CLASS = "-mx-(--menu-surface-padding) my-(--menu-surface-padding) h-px bg-glass-stroke";
13
+ export declare const MENU_SHORTCUT_CLASS = "ml-auto text-xs tracking-widest text-muted-foreground";
14
+ /** The current VALUE beside a submenu's label ("Status Backlog ›"): takes
15
+ * what is left of the row and truncates, never the label's room. */
16
+ export declare const MENU_VALUE_CLASS = "min-w-0 max-w-[7rem] shrink text-right normal-case tracking-normal truncate";
17
+ export declare const MENU_CHEVRON_CLASS = "ml-auto size-(--menu-icon-size) shrink-0";
@@ -0,0 +1,21 @@
1
+ /** EXP-909: the ONE bar every usage surface draws — the rate-limit windows,
2
+ * the run's context, and the tiny three-bar mini line. Before this there were
3
+ * two: a bare `Progress` (primary fill, no tone) under the Context block and a
4
+ * hand-rolled `<span>` track with its own tone map inside the usage cards, so
5
+ * the same 67% was two different colours two rows apart.
6
+ *
7
+ * It IS `Progress` — the Radix root, its track and its indicator — with the
8
+ * severity tone painted on the indicator (`lib/agent-usage.ts` `severity`,
9
+ * hand-mirrored ×4 with the desktop's `usage_bar::meter`, iOS `AgentUsageTrack`
10
+ * and Android `UsageTrack`). Height comes from `className` (`h-1` for the mini
11
+ * line, `h-1.5` for a full window), never from a prop: the tone is the only
12
+ * thing a caller has to think about. */
13
+ export type MeterTone = `normal` | `warning` | `danger`;
14
+ export declare const METER_CLASSES: {
15
+ readonly root: "h-1.5 bg-glass-stroke-strong";
16
+ readonly tones: {
17
+ normal: string;
18
+ warning: string;
19
+ danger: string;
20
+ };
21
+ };
@@ -0,0 +1,3 @@
1
+ export declare const POPOVER_CLASSES: {
2
+ readonly content: "z-50 rounded-lg border border-glass-stroke-card bg-glass-card-opaque text-popover-foreground motion-popover w-72 origin-(--radix-popover-content-transform-origin) p-4 outline-hidden";
3
+ };
@@ -0,0 +1,5 @@
1
+ /** The filled share of the ring, 0..100 (an empty or nonsensical total = 0). */
2
+ export declare function progressRingPercent(done: number, total: number): number;
3
+ export declare const PROGRESS_RING_CLASSES: {
4
+ readonly root: "shrink-0 -rotate-90";
5
+ };
@@ -0,0 +1,8 @@
1
+ export declare const PROGRESS_CLASSES: {
2
+ readonly root: "bg-primary/20 relative h-2 w-full overflow-hidden rounded-full";
3
+ readonly indicator: "bg-primary h-full flex-1 transition-all";
4
+ readonly indicatorIndeterminate: "w-1/3 motion-safe:animate-progress-indeterminate motion-reduce:opacity-60";
5
+ readonly indicatorDeterminate: "w-full";
6
+ };
7
+ /** The determinate indicator's offset for `value` (0-100). */
8
+ export declare function progressIndicatorTransform(value: number | null | undefined): string;