@exponential-at/ui 0.0.0-stage → 0.1.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 (251) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +54 -0
  3. package/README.md +360 -2
  4. package/catalog/a11y.json +668 -0
  5. package/catalog/basic-map.json +104 -0
  6. package/catalog/code.json +58 -0
  7. package/catalog/core.catalog.json +4752 -0
  8. package/catalog/core.schema.json +22667 -0
  9. package/catalog/host.json +64 -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 +3417 -0
  14. package/catalog/recipes.json +61 -0
  15. package/catalog/strings.json +72 -0
  16. package/catalog/style.json +128 -0
  17. package/catalog/theme.schema.json +42543 -0
  18. package/catalog/tokens.json +47 -0
  19. package/conformance/README.md +217 -0
  20. package/conformance/baseline.ts +101 -0
  21. package/conformance/browser-page.ts +146 -0
  22. package/conformance/browser-suites.ts +683 -0
  23. package/conformance/compare.ts +201 -0
  24. package/conformance/dom.ts +96 -0
  25. package/conformance/dump.ts +163 -0
  26. package/conformance/fonts.json +154 -0
  27. package/conformance/manifest.json +224 -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/dist/chunks/index-98npjvsd.js +3940 -0
  36. package/dist/chunks/index-98npjvsd.js.map +27 -0
  37. package/dist/chunks/index-gwkt14w3.js +7314 -0
  38. package/dist/chunks/index-gwkt14w3.js.map +10 -0
  39. package/dist/chunks/index-njt7yzzm.js +134 -0
  40. package/dist/chunks/index-njt7yzzm.js.map +9 -0
  41. package/dist/chunks/index-we7va6v6.js +7984 -0
  42. package/dist/chunks/index-we7va6v6.js.map +15 -0
  43. package/dist/chunks/index-xrm6f7wc.js +2563 -0
  44. package/dist/chunks/index-xrm6f7wc.js.map +10 -0
  45. package/dist/conformance.js +182749 -0
  46. package/dist/conformance.js.map +10 -0
  47. package/dist/entries/prompt.js +251 -0
  48. package/dist/entries/prompt.js.map +11 -0
  49. package/dist/entries/schema.js +1725 -0
  50. package/dist/entries/schema.js.map +11 -0
  51. package/dist/host/index.js +122 -0
  52. package/dist/host/index.js.map +9 -0
  53. package/dist/index.js +3213 -0
  54. package/dist/index.js.map +27 -0
  55. package/dist/types/src/a11y.d.ts +21 -0
  56. package/dist/types/src/animation.d.ts +76 -0
  57. package/dist/types/src/basic-map.d.ts +38 -0
  58. package/dist/types/src/builder.d.ts +50 -0
  59. package/dist/types/src/catalog.d.ts +54 -0
  60. package/dist/types/src/catalog.described.d.ts +33 -0
  61. package/dist/types/src/catalog.generated.d.ts +829 -0
  62. package/dist/types/src/chart.d.ts +46 -0
  63. package/dist/types/src/code.d.ts +44 -0
  64. package/dist/types/src/color.d.ts +20 -0
  65. package/dist/types/src/conformance.d.ts +39 -0
  66. package/dist/types/src/connector/app.d.ts +14 -0
  67. package/dist/types/src/connector/connector.d.ts +77 -0
  68. package/dist/types/src/connector/index.d.ts +4 -0
  69. package/dist/types/src/css.d.ts +29 -0
  70. package/dist/types/src/define.d.ts +66 -0
  71. package/dist/types/src/direction.d.ts +16 -0
  72. package/dist/types/src/dynamic.d.ts +159 -0
  73. package/dist/types/src/entries/prompt.d.ts +11 -0
  74. package/dist/types/src/entries/schema.d.ts +8 -0
  75. package/dist/types/src/expr.d.ts +71 -0
  76. package/dist/types/src/extension.d.ts +4 -0
  77. package/dist/types/src/format.d.ts +112 -0
  78. package/dist/types/src/geometry.d.ts +40 -0
  79. package/dist/types/src/host/contract.d.ts +188 -0
  80. package/dist/types/src/host/decoders.d.ts +61 -0
  81. package/dist/types/src/host/index.d.ts +11 -0
  82. package/dist/types/src/host/package.d.ts +58 -0
  83. package/dist/types/src/host/policy.d.ts +105 -0
  84. package/dist/types/src/host/router.d.ts +34 -0
  85. package/dist/types/src/host/runtime.d.ts +205 -0
  86. package/dist/types/src/host/sources.d.ts +15 -0
  87. package/dist/types/src/host/transports.d.ts +109 -0
  88. package/dist/types/src/index.d.ts +63 -0
  89. package/dist/types/src/layout.d.ts +20 -0
  90. package/dist/types/src/limits.d.ts +21 -0
  91. package/dist/types/src/list.d.ts +133 -0
  92. package/dist/types/src/locale.d.ts +22 -0
  93. package/dist/types/src/macros.d.ts +29 -0
  94. package/dist/types/src/overlay.d.ts +27 -0
  95. package/dist/types/src/prompt.d.ts +44 -0
  96. package/dist/types/src/recipes.d.ts +17 -0
  97. package/dist/types/src/reducer.d.ts +41 -0
  98. package/dist/types/src/resizable.d.ts +38 -0
  99. package/dist/types/src/schema.d.ts +7 -0
  100. package/dist/types/src/strings.d.ts +13 -0
  101. package/dist/types/src/style.d.ts +201 -0
  102. package/dist/types/src/test-preload.d.ts +1 -0
  103. package/dist/types/src/text-shimmer.d.ts +24 -0
  104. package/dist/types/src/theme-types.d.ts +162 -0
  105. package/dist/types/src/theme.d.ts +73 -0
  106. package/dist/types/src/themes.d.ts +22 -0
  107. package/dist/types/src/tree-guides.d.ts +17 -0
  108. package/dist/types/src/types.d.ts +314 -0
  109. package/dist/types/src/validate.d.ts +31 -0
  110. package/dist/types/src/web/base-css.d.ts +1 -0
  111. package/dist/types/src/web/box-css.d.ts +55 -0
  112. package/dist/types/src/web/coerce.d.ts +32 -0
  113. package/dist/types/src/web/data.d.ts +105 -0
  114. package/dist/types/src/web/dates.d.ts +12 -0
  115. package/dist/types/src/web/form.d.ts +44 -0
  116. package/dist/types/src/web/host-types.d.ts +119 -0
  117. package/dist/types/src/web/index.d.ts +28 -0
  118. package/dist/types/src/web/inputs.d.ts +55 -0
  119. package/dist/types/src/web/list.d.ts +13 -0
  120. package/dist/types/src/web/listbox.d.ts +14 -0
  121. package/dist/types/src/web/markdown.d.ts +96 -0
  122. package/dist/types/src/web/media.d.ts +62 -0
  123. package/dist/types/src/web/parts.d.ts +4 -0
  124. package/dist/types/src/web/primitives/alert-dialog.d.ts +10 -0
  125. package/dist/types/src/web/primitives/alert.d.ts +9 -0
  126. package/dist/types/src/web/primitives/avatar-color.d.ts +2 -0
  127. package/dist/types/src/web/primitives/avatar.d.ts +13 -0
  128. package/dist/types/src/web/primitives/badge.d.ts +10 -0
  129. package/dist/types/src/web/primitives/breadcrumb.d.ts +10 -0
  130. package/dist/types/src/web/primitives/button.d.ts +6 -0
  131. package/dist/types/src/web/primitives/calendar.d.ts +43 -0
  132. package/dist/types/src/web/primitives/card.d.ts +9 -0
  133. package/dist/types/src/web/primitives/checkbox.d.ts +5 -0
  134. package/dist/types/src/web/primitives/choice-tiles.d.ts +32 -0
  135. package/dist/types/src/web/primitives/cn.d.ts +3 -0
  136. package/dist/types/src/web/primitives/code-block.d.ts +24 -0
  137. package/dist/types/src/web/primitives/command.d.ts +134 -0
  138. package/dist/types/src/web/primitives/context-ring.d.ts +24 -0
  139. package/dist/types/src/web/primitives/dialog-arms.d.ts +6 -0
  140. package/dist/types/src/web/primitives/dialog.d.ts +24 -0
  141. package/dist/types/src/web/primitives/disclosure-header.d.ts +5 -0
  142. package/dist/types/src/web/primitives/dock.d.ts +42 -0
  143. package/dist/types/src/web/primitives/dropdown-menu.d.ts +14 -0
  144. package/dist/types/src/web/primitives/empty-state.d.ts +15 -0
  145. package/dist/types/src/web/primitives/glass-card.d.ts +4 -0
  146. package/dist/types/src/web/primitives/hover-card.d.ts +7 -0
  147. package/dist/types/src/web/primitives/icon-disc.d.ts +12 -0
  148. package/dist/types/src/web/primitives/index.d.ts +48 -0
  149. package/dist/types/src/web/primitives/input.d.ts +5 -0
  150. package/dist/types/src/web/primitives/kbd.d.ts +4 -0
  151. package/dist/types/src/web/primitives/label.d.ts +3 -0
  152. package/dist/types/src/web/primitives/menu-surface.d.ts +17 -0
  153. package/dist/types/src/web/primitives/meter.d.ts +21 -0
  154. package/dist/types/src/web/primitives/popover.d.ts +3 -0
  155. package/dist/types/src/web/primitives/progress-ring.d.ts +5 -0
  156. package/dist/types/src/web/primitives/progress.d.ts +8 -0
  157. package/dist/types/src/web/primitives/scroll-area.d.ts +49 -0
  158. package/dist/types/src/web/primitives/segmented-control.d.ts +5 -0
  159. package/dist/types/src/web/primitives/select.d.ts +47 -0
  160. package/dist/types/src/web/primitives/separator.d.ts +3 -0
  161. package/dist/types/src/web/primitives/sheet-chrome.d.ts +4 -0
  162. package/dist/types/src/web/primitives/sheet.d.ts +20 -0
  163. package/dist/types/src/web/primitives/skeleton.d.ts +3 -0
  164. package/dist/types/src/web/primitives/spinner.d.ts +3 -0
  165. package/dist/types/src/web/primitives/switch.d.ts +4 -0
  166. package/dist/types/src/web/primitives/table.d.ts +11 -0
  167. package/dist/types/src/web/primitives/tabs.d.ts +13 -0
  168. package/dist/types/src/web/primitives/textarea.d.ts +3 -0
  169. package/dist/types/src/web/primitives/toast.d.ts +163 -0
  170. package/dist/types/src/web/primitives/tooltip.d.ts +3 -0
  171. package/dist/types/src/web/primitives/truncate.d.ts +7 -0
  172. package/dist/types/src/web/primitives/typeahead-portal.d.ts +12 -0
  173. package/dist/types/src/web/share.d.ts +6 -0
  174. package/dist/types/src/web/table.d.ts +20 -0
  175. package/dist/types/src/web/theme-css.d.ts +69 -0
  176. package/dist/types/src/web/urls.d.ts +21 -0
  177. package/dist/web/index.js +2303 -0
  178. package/dist/web/index.js.map +26 -0
  179. package/dist/web/primitives/index.js +1450 -0
  180. package/dist/web/primitives/index.js.map +57 -0
  181. package/docs/components.generated.json +6238 -0
  182. package/docs/round-1-contract.md +679 -0
  183. package/docs/round-2-contract.md +476 -0
  184. package/docs/round-3-contract.md +174 -0
  185. package/docs/themes.generated.json +3503 -0
  186. package/fixtures/animations.json +2890 -0
  187. package/fixtures/bench-list.json +58 -0
  188. package/fixtures/bind-time.json +30664 -0
  189. package/fixtures/catalog-basic-map.json +1692 -0
  190. package/fixtures/catalog-components.json +9323 -0
  191. package/fixtures/catalog-extension.json +620 -0
  192. package/fixtures/catalog-macros.json +36370 -0
  193. package/fixtures/code-tokens.json +1993 -0
  194. package/fixtures/conformance-baseline.json +55544 -0
  195. package/fixtures/conformance-cases.json +49 -0
  196. package/fixtures/conformance-known.json +2123 -0
  197. package/fixtures/control-geometry.json +4200 -0
  198. package/fixtures/dashboard.data.json +74 -0
  199. package/fixtures/dashboard.json +752 -0
  200. package/fixtures/demo-surface.json +47 -0
  201. package/fixtures/format.json +870 -0
  202. package/fixtures/host-policy.json +1067 -0
  203. package/fixtures/host-router.json +1152 -0
  204. package/fixtures/host-transport.json +590 -0
  205. package/fixtures/interactions-round1.json +773 -0
  206. package/fixtures/kitchen-sink.expanded.json +10844 -0
  207. package/fixtures/kitchen-sink.json +3049 -0
  208. package/fixtures/layout-geometry-round1.json +7278 -0
  209. package/fixtures/layout-geometry.json +2072 -0
  210. package/fixtures/overlay-geometry.json +272 -0
  211. package/fixtures/primitive-specimens.json +58 -0
  212. package/fixtures/prompt-budget.json +33 -0
  213. package/fixtures/resizable.json +714 -0
  214. package/fixtures/round4-contract.json +2985 -0
  215. package/fixtures/specimens.json +9832 -0
  216. package/fixtures/style-conditions.json +336 -0
  217. package/fixtures/template-items.json +2215 -0
  218. package/fixtures/text-direction.json +309 -0
  219. package/fixtures/text-shimmer.json +96 -0
  220. package/fixtures/theme-extends.json +573 -0
  221. package/fixtures/theme-invalid.json +1296 -0
  222. package/fixtures/theme-recipes.json +58600 -0
  223. package/fixtures/theme-resolved.json +23949 -0
  224. package/fixtures/toast-stack.json +215 -0
  225. package/fixtures/tree-guides.json +224 -0
  226. package/fixtures/virtual-list.json +733 -0
  227. package/generated/ExponentialUICatalog.generated.kt +67 -0
  228. package/generated/ExponentialUICatalog.generated.swift +67 -0
  229. package/generated/ExponentialUIThemes.generated.kt +23 -0
  230. package/generated/ExponentialUIThemes.generated.swift +23 -0
  231. package/generated/catalog.descriptions.generated.rs +6 -0
  232. package/generated/catalog.generated.rs +80 -0
  233. package/generated/catalog.themes.generated.rs +34 -0
  234. package/generated/core.descriptions.json +2505 -0
  235. package/generated/core.runtime.json +3609 -0
  236. package/package.json +87 -4
  237. package/themes/exponential.recipes.json +49 -0
  238. package/themes/exponential.theme.json +755 -0
  239. package/themes/neutral.theme.json +5676 -0
  240. package/themes/orange.theme.json +43 -0
  241. package/themes/playful.theme.json +219 -0
  242. package/vendor/a2ui/LICENSE.txt +203 -0
  243. package/vendor/a2ui/README.md +27 -0
  244. package/vendor/a2ui/v0_9/basic_catalog.json +1387 -0
  245. package/vendor/a2ui/v0_9/basic_catalog_rules.txt +5 -0
  246. package/vendor/a2ui/v0_9/client_capabilities.json +97 -0
  247. package/vendor/a2ui/v0_9/client_to_server.json +104 -0
  248. package/vendor/a2ui/v0_9/common_types.json +315 -0
  249. package/vendor/a2ui/v0_9/server_to_client.json +132 -0
  250. package/vendor/json-render/LICENSE.txt +201 -0
  251. package/vendor/json-render/README.md +13 -0
@@ -0,0 +1,17 @@
1
+ import type { UiNode } from "./types.js";
2
+ /** Guide geometry for ONE row, in gutter LEVELS (not pixels). */
3
+ export interface TreeGuide {
4
+ /** The gutter level the elbow sits in (`depth - 1`); `null` for a root. */
5
+ elbowAt: number | null;
6
+ /** The elbow's vertical continues past the centre: a later sibling follows. */
7
+ tee: boolean;
8
+ /** Ancestor gutter levels carrying a straight full-height line, ascending. */
9
+ passThrough: number[];
10
+ }
11
+ /** The guides for a flat list of VISIBLE rows, given their depths. */
12
+ export declare function treeGuides(depths: readonly number[]): TreeGuide[];
13
+ /** The expanded root of a `Row` macro. */
14
+ export declare function isRowRoot(node: UiNode): boolean;
15
+ /** Fill every Row's guides from the rows around it. Mutates `root` in place
16
+ * (the expander hands it a fresh tree); returns it for chaining. */
17
+ export declare function applyTreeGuides(root: UiNode): UiNode;
@@ -0,0 +1,314 @@
1
+ export type PropType = `string` | `markdown` | `number` | `boolean` | `enum` | `icon` | `color` | `style` | `array` | `object` | `date` | `url`;
2
+ export interface PropSchema {
3
+ type: PropType;
4
+ /** Model-facing. VAPP-106: ABSENT at runtime on the runtime catalog (`coreCatalog`) until
5
+ * `describeCatalog()` attaches it; typed present because its readers (the prompt, the schema
6
+ * emitter, the docs, an extension's validation) always see it attached. */
7
+ description: string;
8
+ required?: boolean;
9
+ default?: unknown;
10
+ /** Accepts an A2UI data binding `{path}` or a function call instead of a literal. */
11
+ bindable?: boolean;
12
+ /** Round 1: ALSO accepts `{base, sm?, md?, lg?, xl?}` (keys = the
13
+ * `$breakpoint` token names); the macro expander emits the media blocks. */
14
+ responsive?: boolean;
15
+ /** `enum`: the name of a shared list in `enums`, or … */
16
+ enum?: string;
17
+ /** … an inline list of values. */
18
+ values?: readonly (string | number)[];
19
+ /** `number`: the inclusive bounds a literal must respect (R8 F51: a
20
+ * Rating's `max` stops at 100); both validators refuse a value outside. */
21
+ minimum?: number;
22
+ maximum?: number;
23
+ /** `array`: the item schema. */
24
+ items?: PropSchema;
25
+ /** `object`: the name of a shared shape in `defs`; none = any object. */
26
+ shape?: string;
27
+ }
28
+ export interface DefSchema {
29
+ /** Model-facing. VAPP-106: ABSENT at runtime on the runtime catalog (`coreCatalog`) until
30
+ * `describeCatalog()` attaches it; typed present because its readers (the prompt, the schema
31
+ * emitter, the docs, an extension's validation) always see it attached. */
32
+ description: string;
33
+ properties: Record<string, PropSchema>;
34
+ }
35
+ export type ComponentKind = `native` | `macro`;
36
+ export type ChildrenRule = `none` | `one` | `many`;
37
+ export interface ComponentDef {
38
+ kind: ComponentKind;
39
+ group: string;
40
+ lite: boolean;
41
+ children: ChildrenRule;
42
+ /** Named child slots; `["*"]` = any slot name (Table cell templates). */
43
+ slots?: readonly string[];
44
+ /** Round 1: `row` = every slot is a per-ROW cell template (Table): the bind
45
+ * pass leaves it unbound and the painter binds it once per row with the
46
+ * row as its data scope (src/dynamic.ts bindRowSlot). */
47
+ slotScope?: `row`;
48
+ /** Never offered to a model (the Unknown placeholder, TreeGuides = a Row part). */
49
+ hidden?: boolean;
50
+ /** `planned` = in the catalog, painters land later. */
51
+ status?: string;
52
+ /** Model-facing. VAPP-106: ABSENT at runtime on the runtime catalog (`coreCatalog`) until
53
+ * `describeCatalog()` attaches it; typed present because its readers (the prompt, the schema
54
+ * emitter, the docs, an extension's validation) always see it attached. */
55
+ description: string;
56
+ props: Record<string, PropSchema>;
57
+ events?: readonly string[];
58
+ /** The docs' and the fixtures' specimen props; absent on the runtime catalog like `description`. */
59
+ example?: Record<string, unknown>;
60
+ }
61
+ export interface CatalogSource {
62
+ id: string;
63
+ liteId: string;
64
+ name: string;
65
+ version: string;
66
+ unknownComponent: string;
67
+ enums: Record<string, readonly string[]>;
68
+ defs: Record<string, DefSchema>;
69
+ functions: {
70
+ names: readonly string[];
71
+ core: Record<string, CoreFunctionDef>;
72
+ basic: Record<string, FunctionSignature>;
73
+ };
74
+ /** Round 1: `<Component>.<part>[.<variant>]` → the icons.json name a
75
+ * renderer draws for a part it owns (`$comment` aside). */
76
+ builtinIcons: Record<string, string>;
77
+ components: Record<string, ComponentDef>;
78
+ }
79
+ /** Round 4: a basic function's signature (core.catalog.json `functions.basic`). */
80
+ export interface FunctionSignature {
81
+ /** Argument name → its type (`number`, `string`, `boolean`, `array`, `object`, `any`). */
82
+ args: Record<string, string>;
83
+ returns: string;
84
+ }
85
+ /** Round 1: one core function (core.catalog.json `functions.core`). */
86
+ export interface CoreFunctionDef {
87
+ /** Model-facing. VAPP-106: ABSENT at runtime on the runtime catalog (`coreCatalog`) until
88
+ * `describeCatalog()` attaches it; typed present because its readers (the prompt, the schema
89
+ * emitter, the docs, an extension's validation) always see it attached. */
90
+ description: string;
91
+ /** Argument name → its type (`number`, `string`, `boolean`, `array`, `object`, `any`). */
92
+ args: Record<string, string>;
93
+ returns: string;
94
+ }
95
+ /** A child entry of a macro template: a part, the author's children
96
+ * (`$children`) or one of the author's slots spliced in place (`$slot:name`). */
97
+ export type MacroChild = MacroTemplate | `$children` | `$slot:${string}`;
98
+ /** A macro template node (catalog/macros.json). */
99
+ export interface MacroTemplate {
100
+ part: string;
101
+ component: string;
102
+ props?: Record<string, unknown>;
103
+ style?: Record<string, unknown>;
104
+ children?: MacroChild[];
105
+ /** `$slot:name` copies the author's slot; a template node builds a part. */
106
+ slots?: Record<string, string | MacroTemplate>;
107
+ $if?: unknown;
108
+ $any?: unknown[];
109
+ $each?: string;
110
+ $as?: string;
111
+ $on?: Record<string, string>;
112
+ $context?: Record<string, unknown>;
113
+ $recipe?: Record<string, unknown>;
114
+ /** Round 1 two-way binding: per part event, the macro prop a bound author
115
+ * value is written back to (`set`) and the template value it takes. */
116
+ $set?: Record<string, {
117
+ prop: string;
118
+ value: unknown;
119
+ }>;
120
+ /** Round 1 (docs/round-1-contract.md §6): the part's accessibility — a
121
+ * machine-readable `role` (catalog/a11y.json `roles`), its states and an
122
+ * accessible name — evaluated like any template value (bound inputs emit
123
+ * calls) into the expanded node's `accessibility`. */
124
+ $a11y?: Record<string, unknown>;
125
+ }
126
+ export interface MacroDef {
127
+ recipeProps: readonly string[];
128
+ root: MacroTemplate;
129
+ }
130
+ /** An extension catalog: its own id, extending the core, with components and
131
+ * the macro templates for its macro components. */
132
+ export interface ExtensionDef {
133
+ id: string;
134
+ name: string;
135
+ extends: string;
136
+ enums?: Record<string, readonly string[]>;
137
+ defs?: Record<string, DefSchema>;
138
+ components: Record<string, ComponentDef>;
139
+ macros?: Record<string, MacroDef>;
140
+ }
141
+ /** An A2UI v0.9 data binding or function call, passed through untouched. */
142
+ export interface DataBinding {
143
+ path: string;
144
+ }
145
+ export interface FunctionCall {
146
+ call: string;
147
+ args?: Record<string, unknown>;
148
+ returnType?: string;
149
+ }
150
+ /** An A2UI v0.9 Action: a server event or a client function. Round 1: the
151
+ * expander may emit BOTH (a routed event plus a `set` write); a renderer
152
+ * evaluates the function args and the event context first, then runs the
153
+ * function, then dispatches the event. */
154
+ export interface Action {
155
+ event?: {
156
+ name: string;
157
+ context?: Record<string, unknown>;
158
+ };
159
+ /** A2UI v0.9's client function action (round 4: the ONLY key). */
160
+ functionCall?: FunctionCall;
161
+ }
162
+ /** A data-driven child list: one `component` per item at `path`; `key` = a
163
+ * pointer relative to the item that identifies it (reordering keeps the
164
+ * item's state), the index when absent. */
165
+ export interface ChildTemplate {
166
+ component: string;
167
+ path: string;
168
+ key?: string;
169
+ }
170
+ /** The wire form of a template child list (A2UI's `{componentId, path}`,
171
+ * plus round 1's optional `key`). */
172
+ export interface WireChildTemplate {
173
+ componentId: string;
174
+ path: string;
175
+ key?: string;
176
+ }
177
+ /** The common `visible` value: a literal boolean or a dynamic value the
178
+ * renderer resolves (truthiness as `expr.ts truthy`: undefined, null, false
179
+ * and "" hide; 0 shows). Absent = visible. */
180
+ export type Visible = boolean | DataBinding | FunctionCall;
181
+ /** A2UI's AccessibilityAttributes: `label`/`description` are DynamicStrings
182
+ * (a literal, a binding or a call; the bind pass resolves them). */
183
+ export interface AuthoredAccessibility {
184
+ label?: unknown;
185
+ description?: unknown;
186
+ }
187
+ /** Round 1 (docs/round-1-contract.md §6): the accessibility a NORMALIZED node
188
+ * carries: the author's label/description, plus what a macro part's `$a11y`
189
+ * adds (an author's label/description on a macro win over its root's). Every
190
+ * value may be dynamic until the bind pass. A painter maps `role` (one of
191
+ * catalog/a11y.json `roles`) and the states onto the platform: ARIA
192
+ * role/aria-*, SwiftUI traits/values, Compose semantics, AccessKit. */
193
+ export interface NodeAccessibility extends AuthoredAccessibility {
194
+ /** One of `A11Y_ROLES`; absent = the component's own (a11y.json). */
195
+ role?: unknown;
196
+ /** Heading level 1..6 (role heading). */
197
+ level?: unknown;
198
+ /** A disclosure's state (aria-expanded). */
199
+ expanded?: unknown;
200
+ /** `page`, `step` or false (aria-current). */
201
+ current?: unknown;
202
+ /** A selected option, tab or row (aria-selected). */
203
+ selected?: unknown;
204
+ /** A toggle button's state (aria-pressed). */
205
+ pressed?: unknown;
206
+ /** A checkbox/radio state (aria-checked). */
207
+ checked?: unknown;
208
+ /** Progressbar/meter/slider values (aria-valuenow/min/max). */
209
+ valueNow?: unknown;
210
+ valueMin?: unknown;
211
+ valueMax?: unknown;
212
+ /** True = out of the accessibility tree (decorative). */
213
+ hidden?: unknown;
214
+ /** True = focus lands here when the enclosing dialog opens. */
215
+ autoFocus?: unknown;
216
+ }
217
+ /** A node as it rides A2UI's `updateComponents`: props at the top level,
218
+ * children by id. The core catalog keeps that convention. */
219
+ export interface FlatComponent {
220
+ id: string;
221
+ component: string;
222
+ children?: string[] | WireChildTemplate;
223
+ slots?: Record<string, string>;
224
+ on?: Record<string, Action>;
225
+ style?: Record<string, unknown>;
226
+ visible?: Visible;
227
+ accessibility?: AuthoredAccessibility;
228
+ [prop: string]: unknown;
229
+ }
230
+ /** A node of the NORMALIZED tree every painter reads: core vocabulary, props
231
+ * under `props`, children nested, macros expanded (`recipe` names the macro
232
+ * part a theme styles). */
233
+ export interface UiNode {
234
+ id: string;
235
+ component: string;
236
+ props: Record<string, unknown>;
237
+ style?: Record<string, unknown>;
238
+ /** Round 1: falsy once resolved = the node is not rendered and takes no
239
+ * layout space; the expander sets it for a part whose `$if` was bound. */
240
+ visible?: Visible;
241
+ on?: Record<string, Action>;
242
+ accessibility?: NodeAccessibility;
243
+ children: UiNode[];
244
+ slots?: Record<string, UiNode>;
245
+ template?: ChildTemplate;
246
+ recipe?: {
247
+ macro: string;
248
+ part: string;
249
+ props: Record<string, unknown>;
250
+ };
251
+ }
252
+ /** The nested authoring form (fixtures, kitchen sink): the same as UiNode
253
+ * minus what the reducer fills in. */
254
+ export interface NestedNode {
255
+ id: string;
256
+ component: string;
257
+ props?: Record<string, unknown>;
258
+ style?: Record<string, unknown>;
259
+ visible?: Visible;
260
+ on?: Record<string, Action>;
261
+ accessibility?: AuthoredAccessibility;
262
+ children?: NestedNode[];
263
+ slots?: Record<string, NestedNode>;
264
+ template?: ChildTemplate;
265
+ }
266
+ export interface ReduceIssue {
267
+ id: string;
268
+ message: string;
269
+ }
270
+ /** Round 1 (docs/round-1-contract.md §4–6): what a host sets per surface.
271
+ * Every field is optional; the defaults are what a renderer assumes. */
272
+ export interface SurfaceSettings {
273
+ /** BCP 47; drives the format functions, calendar names, the week start
274
+ * and the text direction (catalog/locale.json). Default `en-US`. */
275
+ locale?: string;
276
+ /** Round 2: the IANA zone instants format in (the host Formatter's;
277
+ * default the platform's; the English fallback and the fixtures: UTC). */
278
+ timeZone?: string;
279
+ /** Built-in UI string overrides by id (catalog/strings.json). */
280
+ strings?: Record<string, string>;
281
+ /** `system` (default) = the platform's light/dark preference. */
282
+ mode?: `light` | `dark` | `system`;
283
+ /** Scales `$control.*` and `$spacing.*` by the theme's `$density.*`. */
284
+ density?: `compact` | `default` | `comfortable`;
285
+ /** `system` (default) = the platform's high-contrast setting; `high`
286
+ * forces the theme's `contrast` overlays. */
287
+ contrast?: `normal` | `high` | `system`;
288
+ /** The theme id (a built-in or one the host loaded). */
289
+ theme?: string;
290
+ }
291
+ /** Round 1 (catalog/a11y.json `commands`): what a host may ask of a live
292
+ * surface. */
293
+ export type SurfaceCommand = {
294
+ focus: {
295
+ id: string;
296
+ };
297
+ } | {
298
+ announce: {
299
+ text: string;
300
+ live?: `polite` | `assertive`;
301
+ };
302
+ } | {
303
+ scrollIntoView: {
304
+ id: string;
305
+ };
306
+ }
307
+ /** Round 2: bring item `index` (data order) of List/Table `id` into view. */
308
+ | {
309
+ scrollToIndex: {
310
+ id: string;
311
+ index: number;
312
+ align?: `start` | `center` | `end` | `nearest`;
313
+ };
314
+ };
@@ -0,0 +1,31 @@
1
+ import { isDynamic } from "./expr.js";
2
+ import type { ComponentDef, ExtensionDef } from "./types.js";
3
+ export interface PropIssue {
4
+ path: string;
5
+ message: string;
6
+ }
7
+ export { isDynamic };
8
+ /** A function name a surface may call: a catalog function, or a HOST
9
+ * function, which is always namespaced (`app.toast`, `harness.openIssue`). */
10
+ export declare function isCallableName(name: string): boolean;
11
+ /** What validateProps leaves out, round 4 (VAPP-103): the node's `style`
12
+ * (whitelisted keys, known tokens, `$color.*` colours), every function a
13
+ * prop (along its schema: never inside DATA), `visible` or an `on` action
14
+ * calls, and a Table's slot columns (each `type: slot` column names one of
15
+ * the node's slots). In this order; the Rust core
16
+ * (`validate::validate_node`) reports the same issues. */
17
+ export declare function validateNode(node: {
18
+ component: string;
19
+ props: Record<string, unknown>;
20
+ style?: unknown;
21
+ visible?: unknown;
22
+ on?: Record<string, unknown>;
23
+ slots?: Record<string, unknown>;
24
+ }, options?: {
25
+ extensions?: readonly ExtensionDef[];
26
+ }): PropIssue[];
27
+ /** Every issue in a node's props against its component definition. */
28
+ export declare function validateProps(def: ComponentDef, props: Record<string, unknown>, options?: {
29
+ path?: string;
30
+ extensions?: readonly ExtensionDef[];
31
+ }): PropIssue[];
@@ -0,0 +1 @@
1
+ export declare const BASE_CSS: string;
@@ -0,0 +1,55 @@
1
+ import { type FontSpec, type ResolvedTheme, type UiNode } from "@exponential-at/ui";
2
+ export declare const nodeClass: (id: string) => string;
3
+ export declare const surfaceClass: (surfaceId: string) => string;
4
+ /** Ids are author strings; keep the class usable in a selector. */
5
+ export declare function cssEscape(text: string): string;
6
+ export declare function walkNodes(root: UiNode): Generator<UiNode>;
7
+ /** One dynamic style value of a node: where it sits and its variable. */
8
+ export interface DynamicStyleEntry {
9
+ /** `--xd-<n>`, numbered in walk order (base keys, then each block). */
10
+ name: string;
11
+ /** The condition key (`@media …`, `:hover`) or `` for the base style. */
12
+ block: string;
13
+ key: string;
14
+ value: unknown;
15
+ }
16
+ /** The node's dynamic style values in the order the sheet numbers them. */
17
+ export declare function dynamicStyleEntries(style: Record<string, unknown> | undefined): DynamicStyleEntry[];
18
+ /** A JS-evaluated condition (height / orientation): its `data-xq` token. */
19
+ export declare function queryToken(key: string): string;
20
+ export interface NodeSheet {
21
+ css: string;
22
+ /** The resolved condition keys the surface must evaluate itself and list
23
+ * in `data-xq` when they hold (height, orientation). */
24
+ queries: string[];
25
+ /** VAPP-152: each styled node's rules by id, in walk order (`css` is
26
+ * their concatenation inside the `xui-node` layer). */
27
+ chunks: ReadonlyMap<string, string>;
28
+ }
29
+ /** The key a surface evaluates itself for a `@media` block (size values
30
+ * resolved to px: `@media (min-width: 768px)`); null = never matches. */
31
+ export declare function resolvedMediaKey(key: string, theme: ResolvedTheme | undefined): string | null;
32
+ /** A node's own `direction` (round 2 §2): its base style's, then every
33
+ * MATCHING `@media` block's in source order (later wins), as
34
+ * `resolveConditions` flattens it; `matches` = the surface's `data-xq`. */
35
+ export declare function styleDirection(style: Record<string, unknown> | undefined, theme: ResolvedTheme | undefined, matches: (resolvedKey: string) => boolean): `ltr` | `rtl` | undefined;
36
+ /** The node sheet for one tree (plus the template subtrees it renders). */
37
+ export declare function compileNodeSheet(roots: readonly UiNode[], surfaceId: string, theme?: ResolvedTheme, fonts?: Record<string, FontSpec>): NodeSheet;
38
+ /** VAPP-152: one `<style>` of the node sheet: the rules of some nodes. */
39
+ export interface NodeSheetBatch {
40
+ readonly chunks: ReadonlyMap<string, string>;
41
+ readonly css: string;
42
+ }
43
+ /** VAPP-152: the node sheet as `<style>` batches, the last ones kept. A
44
+ * rewritten stylesheet makes Chromium re-match every node its rules
45
+ * select, so a batch whose rules are all unchanged keeps its OBJECT (the
46
+ * renderers leave its element alone), a batch with a changed or removed
47
+ * node is rewritten in place, and the new nodes' rules land in ONE new
48
+ * batch at the end (a streamed card restyles only itself). A batch at
49
+ * least as large as the one before it merges into it (a binary counter:
50
+ * at most log2(n) batches, each node rewritten O(log n) times). Rules of
51
+ * different nodes never select the same element, so the order of the
52
+ * batches does not change the cascade. */
53
+ export declare function nodeSheetBatches(prev: readonly NodeSheetBatch[], chunks: ReadonlyMap<string, string>): NodeSheetBatch[];
54
+ /** The node sheet's CSS for one tree (the VAPP-87 entry point). */
55
+ export declare function nodeSheet(root: UiNode, surfaceId: string, fontsOrTheme?: Record<string, FontSpec> | ResolvedTheme, extra?: readonly UiNode[]): string;
@@ -0,0 +1,32 @@
1
+ export declare const str: (v: unknown, fallback?: string) => string;
2
+ export declare const num: (v: unknown, fallback?: number) => number;
3
+ export declare const bool: (v: unknown) => boolean;
4
+ export declare const arr: <T>(v: unknown) => T[];
5
+ /** An array of OBJECTS (options, items, tabs, columns, rows…): entries that
6
+ * are not objects (`options: [null]`) are skipped, never painted. */
7
+ export declare const objects: <T>(v: unknown) => T[];
8
+ /** A built-in PHRASE with placeholders (`removeItem` = `Remove {name}`):
9
+ * the surface's string table entry when it carries `id` (word order is the
10
+ * translation's), else `fallback()`, the round-1 composition kept until
11
+ * catalog/strings.json ships the id. */
12
+ export declare function phrase(ctx: {
13
+ strings: Readonly<Record<string, string>>;
14
+ t: (id: string, params?: Record<string, unknown>) => string;
15
+ }, id: string, params: Record<string, unknown>, fallback: () => string): string;
16
+ /** A byte count in the surface locale with a LOCALIZED unit (1024 steps,
17
+ * `Intl.NumberFormat` `style: "unit"`, e.g. `1,5 kB` / `١٫٥ ك.بايت`). */
18
+ export declare function formatFileSize(bytes: number, locale: string): string;
19
+ /** Does a file match an `accept` list (`image/*,.pdf`)? */
20
+ export declare function acceptsFile(accept: string, file: {
21
+ name: string;
22
+ type: string;
23
+ }): boolean;
24
+ /** A control's `checks` evaluated: EVERY failing message, in order (a
25
+ * check without one says `$string.invalidValue`: pass the surface's). */
26
+ export declare function failingChecks(checks: unknown, fallback?: string): string[];
27
+ /** The first failing message, or null (kept for hosts that used it). */
28
+ export declare function failingCheck(checks: unknown, fallback?: string): string | null;
29
+ /** The icons.json name a renderer draws for an owned part. */
30
+ export declare function builtinIconName(slot: string): string;
31
+ /** Space-joined element ids (`aria-describedby`), undefined when none. */
32
+ export declare function joinIds(...ids: (string | undefined | false)[]): string | undefined;
@@ -0,0 +1,105 @@
1
+ import type { CatalogView, ExtensionDef, Formatter } from "@exponential-at/ui";
2
+ export type DataModel = Record<string, unknown> | unknown[];
3
+ export interface DataBinding {
4
+ path: string;
5
+ }
6
+ export interface FunctionCall {
7
+ call: string;
8
+ args?: Record<string, unknown>;
9
+ returnType?: string;
10
+ }
11
+ export declare function isBinding(value: unknown): value is DataBinding;
12
+ export declare function isCall(value: unknown): value is FunctionCall;
13
+ /** A pointer's tokens; `` and `/` are the whole model. */
14
+ export declare function pointerTokens(pointer: string): string[];
15
+ /** `path` made absolute against a template scope (`/items/3`). */
16
+ export declare function absolutePath(path: string, scope?: string): string;
17
+ export declare function getPointer(data: unknown, pointer: string): unknown;
18
+ /** A copy of `data` with the value at `pointer` replaced (or removed when
19
+ * `value` is undefined): the core's `writePointer` (missing containers are
20
+ * OBJECTS, an array index up to its length, `-` appends). A refused write
21
+ * (pointer limits, a non-index token, an index past the end) leaves the
22
+ * data as it is. */
23
+ export declare function setPointer<T extends DataModel>(data: T, pointer: string, value: unknown): T;
24
+ export interface ResolveContext {
25
+ data: unknown;
26
+ /** The template item's pointer, for relative paths. */
27
+ scope?: string;
28
+ functions?: Record<string, ClientFunction>;
29
+ /** `openUrl` and other side effects go to the host. */
30
+ openUrl?: (url: string) => void;
31
+ /** The surface locale (BCP 47) the format functions use; default en-US. */
32
+ locale?: string;
33
+ /** The surface's built-in string table: `$string.<id>` resolves through it. */
34
+ strings?: Readonly<Record<string, string>>;
35
+ /** Round 2: the surface's Formatter (locale + time zone); the format
36
+ * functions, Table cells, charts and pickers format through it. */
37
+ formatter?: Formatter;
38
+ /** The clock `formatRelativeTime` reads without a `now` argument. */
39
+ now?: () => number;
40
+ }
41
+ /** The synthetic root a Table's LITERAL rows are mounted under in a slot
42
+ * cell's read view: never written to the real data model (the table keeps
43
+ * those edits), never reported to the host as a path. */
44
+ export declare const LITERAL_ROWS_ROOT = "/$xuiRows";
45
+ /** A bound path the host may see (`undefined` for a synthetic one). */
46
+ export declare function hostPath(path: string | undefined): string | undefined;
47
+ export type ClientFunction = (args: Record<string, unknown>, ctx: ResolveContext) => unknown;
48
+ /** `intlFormatter` builds a new Intl instance per call (~18 µs for a
49
+ * currency); a windowed Table re-formats every visible cell per scroll
50
+ * step. This wrapper memoises the RESULTS of the pure members (number,
51
+ * currency, percent, date, plural) per formatter, bounded; relativeTime
52
+ * (it reads a clock) passes through. */
53
+ export declare function memoFormatter(base: Formatter, max?: number): Formatter;
54
+ /** The context's Formatter: the surface's (`ctx.formatter`), else an Intl
55
+ * one in its locale and UTC (a bare `resolveValue` call in a test). */
56
+ export declare function formatterOf(ctx: ResolveContext): Formatter;
57
+ export declare const CLIENT_FUNCTIONS: Record<string, ClientFunction>;
58
+ /** A prop value with its bindings and calls resolved for one render. Plain
59
+ * objects recurse (a check's `condition`, a menu item's label). */
60
+ export declare function resolveValue(value: unknown, ctx: ResolveContext): unknown;
61
+ export declare function resolveProps(props: Record<string, unknown>, ctx: ResolveContext): Record<string, unknown>;
62
+ /** The catalog (core + extensions) a node's props resolve along. */
63
+ export declare function viewOf(extensions?: readonly ExtensionDef[]): CatalogView;
64
+ /** A node's props resolved along its component's schema (an unknown
65
+ * component's resolve at any depth); undefined results are dropped. */
66
+ export declare function resolveNodeProps(component: string, props: Record<string, unknown>, ctx: ResolveContext, extensions?: readonly ExtensionDef[]): Record<string, unknown>;
67
+ /** The pointer a bindable prop writes back to (two-way state), if bound. */
68
+ export declare function boundPath(props: Record<string, unknown>, name: string, scope?: string): string | undefined;
69
+ /** A node's `visible`: absent = shown, else its resolved truthiness. */
70
+ export declare function resolveVisible(visible: unknown, ctx: ResolveContext): boolean;
71
+ /** True when a value holds a binding or a call anywhere (a style value the
72
+ * expander left dynamic). */
73
+ export declare function hasDynamic(value: unknown): boolean;
74
+ /** The React renderer's BIND pass as a pure function (round-1 contract §1;
75
+ * `@exponential-at/ui` `bindTree` is the reference, fixtures/bind-time.json
76
+ * locks both): a node whose `visible` resolves falsy is dropped with its
77
+ * subtree, props / style values / recipe props resolve, `visible` goes,
78
+ * actions and templates stay. `NodeView` binds node by node with the same
79
+ * `resolveValue`; this is the whole-tree form for tests and hosts. */
80
+ /** A node's `accessibility` resolved against the data (bindings, calls,
81
+ * `$string`), undefined members dropped; null when nothing is left. */
82
+ export declare function resolveAccessibility(accessibility: unknown, ctx: ResolveContext): Record<string, unknown> | null;
83
+ /** The ARIA attributes of a RESOLVED `accessibility` (contract §6): `role`
84
+ * (`text` = none of its own, `hidden` = aria-hidden), label/description,
85
+ * `level`, `expanded`, `current` (page|step; false = absent), `selected`,
86
+ * `pressed`, `checked`, `valueNow/Min/Max`, `hidden`; `autoFocus` →
87
+ * `data-xui-autofocus` (an opening dialog focuses it). */
88
+ export declare function ariaAttributes(a11y: Record<string, unknown> | null): Record<string, string>;
89
+ export declare function bindTree<T extends {
90
+ id: string;
91
+ component: string;
92
+ props: Record<string, unknown>;
93
+ children: T[];
94
+ style?: Record<string, unknown>;
95
+ visible?: unknown;
96
+ slots?: Record<string, T>;
97
+ recipe?: {
98
+ macro: string;
99
+ part: string;
100
+ props: Record<string, unknown>;
101
+ };
102
+ on?: unknown;
103
+ accessibility?: unknown;
104
+ template?: unknown;
105
+ }>(node: T, ctx: ResolveContext, extensions?: readonly ExtensionDef[]): T | null;
@@ -0,0 +1,12 @@
1
+ export declare const isoDate: (d: Date) => string;
2
+ export declare const parseIsoDate: (s: string) => Date | null;
3
+ export declare const addDays: (d: Date, n: number) => Date;
4
+ /** `n` months on, the day clamped to the target month's last. */
5
+ export declare const addMonths: (d: Date, n: number) => Date;
6
+ export declare const sameDay: (a: Date | null, b: Date | null) => boolean;
7
+ /** The 6×7 days of `view`'s month, starting on `first` (0 = Sunday). */
8
+ export declare function monthGrid(view: Date, first: number): Date[];
9
+ /** The roving tab stop of a month view: the focused day when it is in the
10
+ * visible month and enabled, else the enabled in-month day nearest to it,
11
+ * else none (a disabled day never holds the stop). */
12
+ export declare function calendarStop(days: readonly Date[], view: Date, focus: Date, disabled: (d: Date) => boolean): Date | null;
@@ -0,0 +1,44 @@
1
+ /** One registered field (a renderer's handle onto its control). */
2
+ export interface FormField {
3
+ name: string;
4
+ domId: string;
5
+ value: () => unknown;
6
+ errors: () => string[];
7
+ focus: () => void;
8
+ element: () => Element | null;
9
+ }
10
+ export interface FormError {
11
+ name: string;
12
+ message: string;
13
+ }
14
+ export type FormCheck<F extends FormField = FormField> = {
15
+ ok: false;
16
+ errors: FormError[];
17
+ first: F | null;
18
+ } | {
19
+ ok: true;
20
+ values: Record<string, unknown>;
21
+ };
22
+ /** A component's catalog default `validateOn`, or undefined. */
23
+ export declare function validateOnDefault(component: string): string | undefined;
24
+ /** Whether a field shows its failing messages now. */
25
+ export declare function fieldErrorsVisible(state: {
26
+ validateOn: string;
27
+ submitted: boolean;
28
+ attempts: number;
29
+ dirty: boolean;
30
+ touched: boolean;
31
+ }): boolean;
32
+ /** Fields in document order (unmounted ones keep their place). */
33
+ export declare function documentOrder<F extends FormField>(fields: Iterable<F>): F[];
34
+ export declare class FormRegistry<F extends FormField = FormField> {
35
+ readonly fields: Set<F>;
36
+ /** Adds a field; the returned function removes it. */
37
+ register(field: F): () => void;
38
+ /** Every field's checks: the failures (document order) and the first
39
+ * invalid field, or the values by name. */
40
+ check(): FormCheck<F>;
41
+ /** The summary entries whose field still fails with that message (they
42
+ * clear as their fields become valid). */
43
+ stillFailing(summary: readonly FormError[]): FormError[];
44
+ }