@exponential_app/eui 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) 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 +3840 -0
  57. package/dist/index.js.map +29 -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 +69 -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-shimmer.d.ts +24 -0
  112. package/dist/types/src/theme-types.d.ts +162 -0
  113. package/dist/types/src/theme.d.ts +75 -0
  114. package/dist/types/src/themes.d.ts +22 -0
  115. package/dist/types/src/tree-guides.d.ts +17 -0
  116. package/dist/types/src/types.d.ts +320 -0
  117. package/dist/types/src/validate.d.ts +31 -0
  118. package/dist/types/src/voice-wave.d.ts +181 -0
  119. package/dist/types/src/web/base-css.d.ts +1 -0
  120. package/dist/types/src/web/box-css.d.ts +63 -0
  121. package/dist/types/src/web/coerce.d.ts +32 -0
  122. package/dist/types/src/web/custom-icons.generated.d.ts +4 -0
  123. package/dist/types/src/web/data.d.ts +107 -0
  124. package/dist/types/src/web/dates.d.ts +12 -0
  125. package/dist/types/src/web/form.d.ts +44 -0
  126. package/dist/types/src/web/host-types.d.ts +126 -0
  127. package/dist/types/src/web/index.d.ts +35 -0
  128. package/dist/types/src/web/inputs.d.ts +55 -0
  129. package/dist/types/src/web/list.d.ts +16 -0
  130. package/dist/types/src/web/listbox.d.ts +14 -0
  131. package/dist/types/src/web/markdown.d.ts +96 -0
  132. package/dist/types/src/web/media.d.ts +63 -0
  133. package/dist/types/src/web/parts.d.ts +4 -0
  134. package/dist/types/src/web/primitives/alert-dialog.d.ts +10 -0
  135. package/dist/types/src/web/primitives/alert.d.ts +9 -0
  136. package/dist/types/src/web/primitives/avatar-color.d.ts +2 -0
  137. package/dist/types/src/web/primitives/avatar.d.ts +13 -0
  138. package/dist/types/src/web/primitives/badge.d.ts +10 -0
  139. package/dist/types/src/web/primitives/breadcrumb.d.ts +10 -0
  140. package/dist/types/src/web/primitives/button.d.ts +6 -0
  141. package/dist/types/src/web/primitives/calendar.d.ts +43 -0
  142. package/dist/types/src/web/primitives/card.d.ts +9 -0
  143. package/dist/types/src/web/primitives/checkbox.d.ts +5 -0
  144. package/dist/types/src/web/primitives/choice-tiles.d.ts +32 -0
  145. package/dist/types/src/web/primitives/cn.d.ts +3 -0
  146. package/dist/types/src/web/primitives/code-block.d.ts +24 -0
  147. package/dist/types/src/web/primitives/command.d.ts +134 -0
  148. package/dist/types/src/web/primitives/context-ring.d.ts +24 -0
  149. package/dist/types/src/web/primitives/dialog-arms.d.ts +6 -0
  150. package/dist/types/src/web/primitives/dialog.d.ts +24 -0
  151. package/dist/types/src/web/primitives/disclosure-header.d.ts +5 -0
  152. package/dist/types/src/web/primitives/dock.d.ts +42 -0
  153. package/dist/types/src/web/primitives/dropdown-menu.d.ts +14 -0
  154. package/dist/types/src/web/primitives/empty-state.d.ts +15 -0
  155. package/dist/types/src/web/primitives/glass-card.d.ts +4 -0
  156. package/dist/types/src/web/primitives/hover-card.d.ts +7 -0
  157. package/dist/types/src/web/primitives/icon-disc.d.ts +12 -0
  158. package/dist/types/src/web/primitives/index.d.ts +50 -0
  159. package/dist/types/src/web/primitives/input.d.ts +5 -0
  160. package/dist/types/src/web/primitives/kbd.d.ts +4 -0
  161. package/dist/types/src/web/primitives/label.d.ts +3 -0
  162. package/dist/types/src/web/primitives/measure.d.ts +16 -0
  163. package/dist/types/src/web/primitives/menu-surface.d.ts +17 -0
  164. package/dist/types/src/web/primitives/meter.d.ts +21 -0
  165. package/dist/types/src/web/primitives/popover.d.ts +3 -0
  166. package/dist/types/src/web/primitives/progress-ring.d.ts +5 -0
  167. package/dist/types/src/web/primitives/progress.d.ts +8 -0
  168. package/dist/types/src/web/primitives/scroll-area.d.ts +49 -0
  169. package/dist/types/src/web/primitives/segmented-control.d.ts +5 -0
  170. package/dist/types/src/web/primitives/select.d.ts +47 -0
  171. package/dist/types/src/web/primitives/separator.d.ts +3 -0
  172. package/dist/types/src/web/primitives/sheet-chrome.d.ts +4 -0
  173. package/dist/types/src/web/primitives/sheet.d.ts +20 -0
  174. package/dist/types/src/web/primitives/skeleton.d.ts +3 -0
  175. package/dist/types/src/web/primitives/spinner.d.ts +3 -0
  176. package/dist/types/src/web/primitives/switch.d.ts +4 -0
  177. package/dist/types/src/web/primitives/table.d.ts +11 -0
  178. package/dist/types/src/web/primitives/tabs.d.ts +13 -0
  179. package/dist/types/src/web/primitives/textarea.d.ts +3 -0
  180. package/dist/types/src/web/primitives/toast.d.ts +163 -0
  181. package/dist/types/src/web/primitives/tooltip.d.ts +3 -0
  182. package/dist/types/src/web/primitives/truncate.d.ts +7 -0
  183. package/dist/types/src/web/primitives/typeahead-portal.d.ts +12 -0
  184. package/dist/types/src/web/primitives/voice-wave.d.ts +50 -0
  185. package/dist/types/src/web/round5.d.ts +107 -0
  186. package/dist/types/src/web/share.d.ts +6 -0
  187. package/dist/types/src/web/table.d.ts +20 -0
  188. package/dist/types/src/web/theme-css.d.ts +69 -0
  189. package/dist/types/src/web/urls.d.ts +21 -0
  190. package/dist/web/index.js +2565 -0
  191. package/dist/web/index.js.map +28 -0
  192. package/dist/web/primitives/index.js +1476 -0
  193. package/dist/web/primitives/index.js.map +57 -0
  194. package/docs/components.generated.json +6783 -0
  195. package/docs/package-format.md +182 -0
  196. package/docs/round-1-contract.md +679 -0
  197. package/docs/round-2-contract.md +476 -0
  198. package/docs/round-3-contract.md +174 -0
  199. package/docs/round-5-contract.md +268 -0
  200. package/docs/themes.generated.json +3647 -0
  201. package/fixtures/animations.json +2890 -0
  202. package/fixtures/bench-list.json +58 -0
  203. package/fixtures/bind-time.json +54734 -0
  204. package/fixtures/catalog-basic-map.json +1692 -0
  205. package/fixtures/catalog-components.json +10293 -0
  206. package/fixtures/catalog-extension.json +620 -0
  207. package/fixtures/catalog-macros.json +51805 -0
  208. package/fixtures/code-tokens.json +1993 -0
  209. package/fixtures/conformance-baseline.json +59016 -0
  210. package/fixtures/conformance-cases.json +49 -0
  211. package/fixtures/conformance-known.json +2111 -0
  212. package/fixtures/control-geometry.json +5129 -0
  213. package/fixtures/dashboard.data.json +74 -0
  214. package/fixtures/dashboard.json +781 -0
  215. package/fixtures/demo-surface.json +47 -0
  216. package/fixtures/format.json +870 -0
  217. package/fixtures/host-package.json +1262 -0
  218. package/fixtures/host-policy.json +1209 -0
  219. package/fixtures/host-router.json +2034 -0
  220. package/fixtures/host-transport.json +590 -0
  221. package/fixtures/interactions-round1.json +1058 -0
  222. package/fixtures/kitchen-sink.expanded.json +11972 -0
  223. package/fixtures/kitchen-sink.json +3140 -0
  224. package/fixtures/layout-geometry-round1.json +7278 -0
  225. package/fixtures/layout-geometry.json +2072 -0
  226. package/fixtures/overlay-geometry.json +272 -0
  227. package/fixtures/pointer.json +89 -0
  228. package/fixtures/primitive-specimens.json +59 -0
  229. package/fixtures/prompt-budget.json +33 -0
  230. package/fixtures/qr-code.json +480 -0
  231. package/fixtures/resizable.json +714 -0
  232. package/fixtures/round4-contract.json +2985 -0
  233. package/fixtures/specimens.json +11168 -0
  234. package/fixtures/style-conditions.json +336 -0
  235. package/fixtures/template-items.json +2215 -0
  236. package/fixtures/text-direction.json +309 -0
  237. package/fixtures/text-shimmer.json +96 -0
  238. package/fixtures/theme-extends.json +573 -0
  239. package/fixtures/theme-invalid.json +1300 -0
  240. package/fixtures/theme-recipes.json +61762 -0
  241. package/fixtures/theme-resolved.json +25969 -0
  242. package/fixtures/toast-stack.json +215 -0
  243. package/fixtures/tree-guides.json +224 -0
  244. package/fixtures/virtual-list.json +733 -0
  245. package/fixtures/voice-wave.json +19236 -0
  246. package/generated/ExponentialUICatalog.generated.kt +67 -0
  247. package/generated/ExponentialUICatalog.generated.swift +67 -0
  248. package/generated/ExponentialUIThemes.generated.kt +23 -0
  249. package/generated/ExponentialUIThemes.generated.swift +23 -0
  250. package/generated/catalog.descriptions.generated.rs +6 -0
  251. package/generated/catalog.generated.rs +80 -0
  252. package/generated/catalog.themes.generated.rs +34 -0
  253. package/generated/core.descriptions.json +2726 -0
  254. package/generated/core.runtime.json +3944 -0
  255. package/package.json +87 -4
  256. package/themes/exponential.recipes.json +49 -0
  257. package/themes/exponential.theme.json +768 -0
  258. package/themes/neutral.theme.json +6178 -0
  259. package/themes/orange.theme.json +43 -0
  260. package/themes/playful.theme.json +219 -0
  261. package/vendor/a2ui/LICENSE.txt +203 -0
  262. package/vendor/a2ui/README.md +27 -0
  263. package/vendor/a2ui/v0_9/basic_catalog.json +1387 -0
  264. package/vendor/a2ui/v0_9/basic_catalog_rules.txt +5 -0
  265. package/vendor/a2ui/v0_9/client_capabilities.json +97 -0
  266. package/vendor/a2ui/v0_9/client_to_server.json +104 -0
  267. package/vendor/a2ui/v0_9/common_types.json +315 -0
  268. package/vendor/a2ui/v0_9/server_to_client.json +132 -0
  269. package/vendor/json-render/LICENSE.txt +201 -0
  270. package/vendor/json-render/README.md +13 -0
  271. package/vendor/nayuki-qr/LICENSE.txt +20 -0
  272. package/vendor/nayuki-qr/README.md +10 -0
@@ -0,0 +1,107 @@
1
+ import type { CatalogView, ExtensionDef, Formatter } from "@exponential_app/eui";
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
+ /** The core's `readPointer`: real indices and OWN keys only, `-` = the
18
+ * last element. */
19
+ export declare const getPointer: (data: unknown, pointer: string) => unknown;
20
+ /** A copy of `data` with the value at `pointer` replaced (or removed when
21
+ * `value` is undefined): the core's `writePointer` (missing containers are
22
+ * OBJECTS, an array index up to its length, `-` appends). A refused write
23
+ * (pointer limits, a non-index token, an index past the end) leaves the
24
+ * data as it is. */
25
+ export declare function setPointer<T extends DataModel>(data: T, pointer: string, value: unknown): T;
26
+ export interface ResolveContext {
27
+ data: unknown;
28
+ /** The template item's pointer, for relative paths. */
29
+ scope?: string;
30
+ functions?: Record<string, ClientFunction>;
31
+ /** `openUrl` and other side effects go to the host. */
32
+ openUrl?: (url: string) => void;
33
+ /** The surface locale (BCP 47) the format functions use; default en-US. */
34
+ locale?: string;
35
+ /** The surface's built-in string table: `$string.<id>` resolves through it. */
36
+ strings?: Readonly<Record<string, string>>;
37
+ /** Round 2: the surface's Formatter (locale + time zone); the format
38
+ * functions, Table cells, charts and pickers format through it. */
39
+ formatter?: Formatter;
40
+ /** The clock `formatRelativeTime` reads without a `now` argument. */
41
+ now?: () => number;
42
+ }
43
+ /** The synthetic root a Table's LITERAL rows are mounted under in a slot
44
+ * cell's read view: never written to the real data model (the table keeps
45
+ * those edits), never reported to the host as a path. */
46
+ export declare const LITERAL_ROWS_ROOT = "/$xuiRows";
47
+ /** A bound path the host may see (`undefined` for a synthetic one). */
48
+ export declare function hostPath(path: string | undefined): string | undefined;
49
+ export type ClientFunction = (args: Record<string, unknown>, ctx: ResolveContext) => unknown;
50
+ /** `intlFormatter` builds a new Intl instance per call (~18 µs for a
51
+ * currency); a windowed Table re-formats every visible cell per scroll
52
+ * step. This wrapper memoises the RESULTS of the pure members (number,
53
+ * currency, percent, date, plural) per formatter, bounded; relativeTime
54
+ * (it reads a clock) passes through. */
55
+ export declare function memoFormatter(base: Formatter, max?: number): Formatter;
56
+ /** The context's Formatter: the surface's (`ctx.formatter`), else an Intl
57
+ * one in its locale and UTC (a bare `resolveValue` call in a test). */
58
+ export declare function formatterOf(ctx: ResolveContext): Formatter;
59
+ export declare const CLIENT_FUNCTIONS: Record<string, ClientFunction>;
60
+ /** A prop value with its bindings and calls resolved for one render. Plain
61
+ * objects recurse (a check's `condition`, a menu item's label). */
62
+ export declare function resolveValue(value: unknown, ctx: ResolveContext): unknown;
63
+ export declare function resolveProps(props: Record<string, unknown>, ctx: ResolveContext): Record<string, unknown>;
64
+ /** The catalog (core + extensions) a node's props resolve along. */
65
+ export declare function viewOf(extensions?: readonly ExtensionDef[]): CatalogView;
66
+ /** A node's props resolved along its component's schema (an unknown
67
+ * component's resolve at any depth); undefined results are dropped. */
68
+ export declare function resolveNodeProps(component: string, props: Record<string, unknown>, ctx: ResolveContext, extensions?: readonly ExtensionDef[]): Record<string, unknown>;
69
+ /** The pointer a bindable prop writes back to (two-way state), if bound. */
70
+ export declare function boundPath(props: Record<string, unknown>, name: string, scope?: string): string | undefined;
71
+ /** A node's `visible`: absent = shown, else its resolved truthiness. */
72
+ export declare function resolveVisible(visible: unknown, ctx: ResolveContext): boolean;
73
+ /** True when a value holds a binding or a call anywhere (a style value the
74
+ * expander left dynamic). */
75
+ export declare function hasDynamic(value: unknown): boolean;
76
+ /** The React renderer's BIND pass as a pure function (round-1 contract §1;
77
+ * `@exponential_app/eui` `bindTree` is the reference, fixtures/bind-time.json
78
+ * locks both): a node whose `visible` resolves falsy is dropped with its
79
+ * subtree, props / style values / recipe props resolve, `visible` goes,
80
+ * actions and templates stay. `NodeView` binds node by node with the same
81
+ * `resolveValue`; this is the whole-tree form for tests and hosts. */
82
+ /** A node's `accessibility` resolved against the data (bindings, calls,
83
+ * `$string`), undefined members dropped; null when nothing is left. */
84
+ export declare function resolveAccessibility(accessibility: unknown, ctx: ResolveContext): Record<string, unknown> | null;
85
+ /** The ARIA attributes of a RESOLVED `accessibility` (contract §6): `role`
86
+ * (`text` = none of its own, `hidden` = aria-hidden), label/description,
87
+ * `level`, `expanded`, `current` (page|step; false = absent), `selected`,
88
+ * `pressed`, `checked`, `valueNow/Min/Max`, `hidden`; `autoFocus` →
89
+ * `data-xui-autofocus` (an opening dialog focuses it). */
90
+ export declare function ariaAttributes(a11y: Record<string, unknown> | null): Record<string, string>;
91
+ export declare function bindTree<T extends {
92
+ id: string;
93
+ component: string;
94
+ props: Record<string, unknown>;
95
+ children: T[];
96
+ style?: Record<string, unknown>;
97
+ visible?: unknown;
98
+ slots?: Record<string, T>;
99
+ recipe?: {
100
+ macro: string;
101
+ part: string;
102
+ props: Record<string, unknown>;
103
+ };
104
+ on?: unknown;
105
+ accessibility?: unknown;
106
+ template?: unknown;
107
+ }>(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
+ }
@@ -0,0 +1,126 @@
1
+ import type { FunctionCallInfo, MediaOptions, MediaRequest, ThemeIssue, UiNode, UrlPolicy } from "@exponential_app/eui";
2
+ import type { ClientFunction } from "./data.js";
3
+ import type { QrScannerHost } from "./round5.js";
4
+ /** A registry name → the renderer's icon component (a map or a lookup). */
5
+ export type IconMap<Icon = unknown> = Record<string, Icon | undefined> | ((name: string) => Icon | undefined);
6
+ /** A user action: a node's `on.<event>` with an `event` action, resolved. */
7
+ export interface SurfaceActionEvent {
8
+ surfaceId: string;
9
+ /** The catalog event (`press`, `change`, `select`, `submit`…). */
10
+ event: string;
11
+ /** The action's `event.name`. */
12
+ name: string;
13
+ componentId: string;
14
+ context: Record<string, unknown>;
15
+ /** What the component adds (a Select's `value`, a Tabs' `value`…). */
16
+ payload?: Record<string, unknown>;
17
+ timestamp: string;
18
+ }
19
+ /** A host-owned input edit. `change` fires debounced while typing with a
20
+ * monotonically increasing `revision`; `commit` on blur / Enter. The host's
21
+ * echo (a data model write at `path`) is applied only while no newer
22
+ * revision is outstanding and the field is not focused. */
23
+ export interface SurfaceInputEvent {
24
+ surfaceId: string;
25
+ componentId: string;
26
+ /** The input's `name` prop. */
27
+ name: string;
28
+ /** The bound data model pointer, when `value` is a binding. */
29
+ path?: string;
30
+ value: unknown;
31
+ revision: number;
32
+ kind: `change` | `commit`;
33
+ }
34
+ /** A painter that failed: the surface, the component, why. */
35
+ export interface PaintError {
36
+ surfaceId: string;
37
+ componentId: string;
38
+ message: string;
39
+ }
40
+ /** One option a host source supplies (the catalog's `option` shape). */
41
+ export interface SourceOption {
42
+ label: string;
43
+ value: string;
44
+ icon?: string;
45
+ disabled?: boolean;
46
+ }
47
+ export interface HostPlugin<Icon = unknown, Markdown = unknown> {
48
+ /** The icon registry: the catalog's `Icon` names → components. */
49
+ icons?: IconMap<Icon>;
50
+ /** Server events. Returning a promise keeps the source control in its
51
+ * optimistic pending state until it settles. */
52
+ onAction?: (event: SurfaceActionEvent) => void | Promise<void>;
53
+ /** Host-owned input edits. Returning a promise acknowledges the revision
54
+ * when it settles; a sync host acknowledges at once. */
55
+ onInput?: (event: SurfaceInputEvent) => void | Promise<void>;
56
+ /** Opens an href the URL policy allowed (`openUrl`, `Link`); default
57
+ * `window.open(url, "_blank")`. */
58
+ openUrl?: (url: string) => void;
59
+ /** The URL policy EVERY href passes (Link, markdown links, FileUpload
60
+ * file urls, openUrl): `catalog/host.json` urls. Unset = the default
61
+ * schemes; relative urls resolve against `baseUrl`, else `media.baseUrl`,
62
+ * else the document's. A denied href paints as text. */
63
+ urls?: UrlPolicy;
64
+ /** The media policy every src passes when there is no `mediaRequest`
65
+ * (schemes, hosts, private opt-ins, base, header rules):
66
+ * `catalog/host.json` media. */
67
+ media?: MediaOptions;
68
+ /** Extra or overriding client functions, web renderers only (`{call,
69
+ * args}` in a prop; an action naming one runs it). Any OTHER action
70
+ * function name goes to onFunctionCall (the portable host functions). */
71
+ functions?: Record<string, ClientFunction>;
72
+ /** An action `functionCall` to a name outside the built-ins (the host
73
+ * function registry + its policy gate, `ExponentialHost.callFunction`).
74
+ * A promise keeps the source control pending until it settles. */
75
+ onFunctionCall?: (call: FunctionCallInfo) => unknown | Promise<unknown>;
76
+ /** The media loader's request for a source (absolute url + headers, e.g.
77
+ * auth for /api/attachments); null = denied. A request WITH headers is
78
+ * fetched (under the media limits) and shown as a blob url; without, its
79
+ * url is used as is. Its url is re-checked against `media`'s schemes,
80
+ * hosts and private opt-ins. */
81
+ mediaRequest?: (src: string) => MediaRequest | null;
82
+ /** Video/Audio (`catalog/host.json` media: the byte limits do not apply,
83
+ * they stream): a url the browser's player loads WITHOUT headers for a
84
+ * request that carries some (a signed or cookie-authed url), so the
85
+ * player streams and seeks. Its result passes the media policy again.
86
+ * Unset = the request is fetched whole into a blob url under the media
87
+ * byte cap and timeout for the WHOLE download (VAPP-107), so a long
88
+ * video needs this hook. */
89
+ mediaStreamUrl?: (request: MediaRequest) => string | Promise<string>;
90
+ /** A richer markdown renderer than the built-in one (a component taking
91
+ * `{text, className}` in the renderer's framework). */
92
+ Markdown?: Markdown;
93
+ /** Rewrites a media src BEFORE the media policy (signed URLs). */
94
+ resolveUrl?: (src: string) => string;
95
+ /** `onPaintError` (`catalog/host.json` paint): a component's painter
96
+ * failed; it paints an empty box. `hostPlugin(host)` forwards it to the
97
+ * agent as an A2UI `RENDER_FAILED` error. */
98
+ onPaintError?: (error: PaintError) => void;
99
+ /** Called with the node for every Unknown placeholder painted. */
100
+ onUnknown?: (node: UiNode) => void;
101
+ /** Round 4 (VAPP-103): the `theme` prop was unusable (an unknown built-in
102
+ * id, a theme file with issues). The surface never throws: it paints
103
+ * with the default theme and reports why here. */
104
+ onThemeIssues?: (issues: ThemeIssue[]) => void;
105
+ /** Round 1, FileUpload: the picked/dropped files' BYTES (the `upload`
106
+ * event carries only `{name, size, type}`). Return a promise to keep the
107
+ * drop zone busy until it settles. */
108
+ onUpload?: (files: File[], target: {
109
+ nodeId: string;
110
+ name: string;
111
+ }) => void | Promise<void>;
112
+ /** Round 1, Select `source`: a host list id (`exp:statuses`) → its
113
+ * options for a query (`""` when not searchable). */
114
+ optionSource?: (source: string, query: string) => SourceOption[] | Promise<SourceOption[]>;
115
+ /** VAPP-162, QrScanner: THE camera (host-owned, like FileUpload's bytes):
116
+ * `start(feed, formats, onValue)` renders the live feed into `feed`,
117
+ * decodes codes of `formats` and calls `onValue` per decoded string;
118
+ * returns the stop. Unset (or `start` returning false) = no camera: the
119
+ * scanner shows its placeholder and `Camera unavailable`. */
120
+ qrScanner?: QrScannerHost;
121
+ }
122
+ /** Any renderer's plugin (what the framework-free helpers take). */
123
+ export type AnyHostPlugin = HostPlugin<unknown, unknown>;
124
+ /** A registry lookup: the host's map (or function) first, then the
125
+ * renderer's own fallbacks. */
126
+ export declare function lookupIcon<Icon>(icons: IconMap<Icon> | undefined, name: string, fallbacks?: Readonly<Record<string, Icon>>): Icon | undefined;
@@ -0,0 +1,35 @@
1
+ export { compileTheme, compiledTheme, globalsCss, themeScope, partClass, propAttribute, tokenVar, tokenVarName, cssValue, declarations, animationDeclarations, shimmerRule, rule, ruleSelectors, isMacroComponent, STATE_SELECTORS, LAYERS } from "./theme-css.js";
2
+ export type { CompiledTheme } from "./theme-css.js";
3
+ export { nodeSheet, compileNodeSheet, nodeSheetBatches, dynamicStyleEntries, queryToken, nodeClass, surfaceClass, walkNodes, cssEscape, resolvedMediaKey, styleDirection } from "./box-css.js";
4
+ export type { NodeSheet, NodeSheetBatch, DynamicStyleEntry } from "./box-css.js";
5
+ export { BASE_CSS } from "./base-css.js";
6
+ export { getPointer, setPointer, pointerTokens, absolutePath, resolveValue, resolveProps, resolveNodeProps, resolveVisible, resolveAccessibility, ariaAttributes, bindTree, boundPath, hostPath, isBinding, isCall, hasDynamic, memoFormatter, formatterOf, viewOf, CLIENT_FUNCTIONS, LITERAL_ROWS_ROOT } from "./data.js";
7
+ export type { DataModel, DataBinding, FunctionCall, ClientFunction, ResolveContext } from "./data.js";
8
+ export { linkHref, mediaRequestOf, mediaUrlAllowed, openAllowed, ownPrivateHosts, urlPolicyOf } from "./urls.js";
9
+ export { lookupIcon } from "./host-types.js";
10
+ export { CUSTOM_ICON_NODES } from "./custom-icons.generated.js";
11
+ export type { CustomIconNode } from "./custom-icons.generated.js";
12
+ export type { HostPlugin, AnyHostPlugin, IconMap, PaintError, SourceOption, SurfaceActionEvent, SurfaceInputEvent } from "./host-types.js";
13
+ export { str, num, bool, arr, objects, phrase, formatFileSize, acceptsFile, failingChecks, failingCheck, builtinIconName, joinIds } from "./coerce.js";
14
+ export { sortRows } from "./table.js";
15
+ export type { TableColumn, TableSort } from "./table.js";
16
+ export { isoDate, parseIsoDate, addDays, addMonths, sameDay, monthGrid, calendarStop } from "./dates.js";
17
+ export { DEBOUNCE_MS, HostOwnedController, parseLocaleNumber } from "./inputs.js";
18
+ export type { HostOwnedControllerOptions, HostOwnedSend } from "./inputs.js";
19
+ export { MEDIA_CACHE_IDLE_MAX, acquireMedia, releaseMedia, mediaCacheKey, mediaCacheStats, clearMediaCache, openMediaSource, streamEntry, fetchStream, fetchLimited } from "./media.js";
20
+ export type { MediaKind, MediaCacheEntry, MediaSourcePlan } from "./media.js";
21
+ export { MAX_LINK_NESTING, MAX_LINK_DEST, MAX_BLOCK_NESTING, LIST_ITEM, linkAt, wholeImage, parseInline, parseList, parseMarkdown } from "./markdown.js";
22
+ export type { MarkdownInline, MarkdownBlock, MarkdownList, MarkdownListItem } from "./markdown.js";
23
+ export { FormRegistry, documentOrder, fieldErrorsVisible, validateOnDefault } from "./form.js";
24
+ export type { FormField, FormError, FormCheck } from "./form.js";
25
+ export { scrollParent, listViewport } from "./list.js";
26
+ export type { ListAxis } from "./list.js";
27
+ export { layoutSize, visualScale, elementScale } from "./primitives/measure.js";
28
+ export type { LayoutSize } from "./primitives/measure.js";
29
+ export { nextEnabledIndex, typeaheadStep, TYPEAHEAD_RESET_MS } from "./listbox.js";
30
+ export type { TypeaheadBuffer } from "./listbox.js";
31
+ export { PLACED, placedPartId } from "./parts.js";
32
+ export { share } from "./share.js";
33
+ export { voiceWaveAnimates, voiceWaveClock, voiceWaveFitChild, voiceWaveName } from "./primitives/voice-wave.js";
34
+ export { qrPaint, qrScanReporter, qrScanFormats, qrCornerPath, qrFeedColour, QR_CORNERS, QR_SCANNER, segmentedBadge, ButtonHold, HOLD_SLOP, withinSlop } from "./round5.js";
35
+ export type { QrPaint, QrScannerHost, QrCorner, HoldEvent, HoldRect } from "./round5.js";
@@ -0,0 +1,55 @@
1
+ export declare const DEBOUNCE_MS = 150;
2
+ export type HostOwnedSend<T> = (value: T, revision: number, kind: `change` | `commit`) => void | Promise<void>;
3
+ export interface HostOwnedControllerOptions<T> {
4
+ /** The value the host holds when the field mounts. */
5
+ initial: T;
6
+ /** Sends an edit; a returned promise acknowledges the revision on settle. */
7
+ send: HostOwnedSend<T>;
8
+ /** Optional local write-through (the bound data model path). */
9
+ writeLocal?: (value: T) => void;
10
+ debounceMs?: number;
11
+ /** Called after every change of `value`, `pending` or `focused`. */
12
+ onChange?: () => void;
13
+ }
14
+ export declare class HostOwnedController<T> {
15
+ /** The field's value (the last edit, or the last adopted host push). */
16
+ value: T;
17
+ /** The newest revision sent or scheduled. */
18
+ revision: number;
19
+ /** True while a revision the host has not acknowledged exists. */
20
+ pending: boolean;
21
+ focused: boolean;
22
+ private acked;
23
+ private timer;
24
+ private live;
25
+ private send;
26
+ private writeLocal?;
27
+ private debounceMs;
28
+ private readonly onChange?;
29
+ constructor(options: HostOwnedControllerOptions<T>);
30
+ /** The latest callbacks (a re-render may hand new closures). */
31
+ configure(options: Pick<HostOwnedControllerOptions<T>, `send` | `writeLocal` | `debounceMs`>): void;
32
+ /** A local edit: bump the revision, write through, debounce a `change`. */
33
+ edit(next: T): void;
34
+ /** Flush the debounce and send a `commit`. */
35
+ commit(): void;
36
+ focus(): void;
37
+ /** Blur commits. */
38
+ blur(): void;
39
+ /** The host's push: adopted only when idle and fully acknowledged.
40
+ * Returns whether it was adopted. */
41
+ push(external: T): boolean;
42
+ /** (Re)attach after `dispose` (a remount). */
43
+ attach(): void;
44
+ /** Unmount: the pending debounce is dropped, acknowledgements no longer
45
+ * notify. */
46
+ dispose(): void;
47
+ private clearTimer;
48
+ private notify;
49
+ private ack;
50
+ private dispatch;
51
+ }
52
+ /** A typed number in the surface locale (its group and decimal separators
53
+ * AND its digits; ASCII digits are always accepted too) → the number, or
54
+ * null. */
55
+ export declare function parseLocaleNumber(text: string, locale: string): number | null;
@@ -0,0 +1,16 @@
1
+ export type ListAxis = `vertical` | `horizontal`;
2
+ /** The nearest ancestor that scrolls on `axis`: overflow auto/scroll AND a
3
+ * box shorter than its content (a content-sized `overflow: auto` box is not
4
+ * a viewport). Null = the document scrolls (the window). */
5
+ export declare function scrollParent(el: HTMLElement | null, axis?: ListAxis): HTMLElement | null;
6
+ /** Where the list's content starts relative to the viewport's start on the
7
+ * axis (the scroll offset in list coordinates) and the viewport length.
8
+ * `known` = the scroller already found (null = the window). NEW-82: both
9
+ * in the LIST's layout px: rect deltas are visual px (CSS zoom,
10
+ * transforms), so they divide by the list's scale; the scroller's
11
+ * client box is in its own layout px, so it multiplies by the scroller's. */
12
+ export declare function listViewport(el: HTMLElement, axis: ListAxis, rtl: boolean, known?: HTMLElement | null): {
13
+ scroll: number;
14
+ viewport: number;
15
+ scroller: HTMLElement | null;
16
+ };
@@ -0,0 +1,14 @@
1
+ /** The TYPE-AHEAD buffer resets after this pause (ms). */
2
+ export declare const TYPEAHEAD_RESET_MS = 700;
3
+ /** The next enabled index `delta` steps from `from` (wrapping), or -1. */
4
+ export declare function nextEnabledIndex(count: number, from: number, delta: number, isDisabled?: (index: number) => boolean): number;
5
+ export interface TypeaheadBuffer {
6
+ text: string;
7
+ at: number;
8
+ }
9
+ /** One printable key typed: the new buffer and the index it lands on (-1 =
10
+ * no label starts with the buffer; the active option stays). */
11
+ export declare function typeaheadStep(buffer: TypeaheadBuffer, key: string, now: number, active: number, count: number, isDisabled: (index: number) => boolean, labelOf: (index: number) => string): {
12
+ buffer: TypeaheadBuffer;
13
+ index: number;
14
+ };
@@ -0,0 +1,96 @@
1
+ /** Link labels nest at most this deep (×4): a link inside 32 enclosing link
2
+ * labels is its text. */
3
+ export declare const MAX_LINK_NESTING = 32;
4
+ /** A link / image destination longer than this (UTF-16 units) is no link. */
5
+ export declare const MAX_LINK_DEST = 8192;
6
+ /** `[label](dest)` / `![alt](dest)` starting at `s[at]` (the `[`): the label
7
+ * (brackets balanced), the destination (`<…>` or balanced parentheses, no
8
+ * whitespace) and the end index. An optional `"title"` is skipped. */
9
+ export declare function linkAt(s: string, at: number): {
10
+ label: string;
11
+ dest: string;
12
+ end: number;
13
+ } | null;
14
+ /** A paragraph that is exactly one `![alt](src)` → its alt + src (a BLOCK
15
+ * image, as every renderer paints it; an image inside running text is its
16
+ * alt text). */
17
+ export declare function wholeImage(text: string): {
18
+ alt: string;
19
+ src: string;
20
+ } | null;
21
+ /** An inline run's tree: text, code, strong/em (nested), strike, a link
22
+ * (raw `dest`, label nested). */
23
+ export type MarkdownInline = string | {
24
+ type: `code`;
25
+ text: string;
26
+ } | {
27
+ type: `strong`;
28
+ children: MarkdownInline[];
29
+ } | {
30
+ type: `em`;
31
+ children: MarkdownInline[];
32
+ } | {
33
+ type: `del`;
34
+ text: string;
35
+ } | {
36
+ type: `link`;
37
+ dest: string;
38
+ children: MarkdownInline[];
39
+ };
40
+ export type MarkdownBlock = {
41
+ type: `paragraph`;
42
+ children: MarkdownInline[];
43
+ }
44
+ /** A paragraph that is exactly one image. */
45
+ | {
46
+ type: `image`;
47
+ alt: string;
48
+ src: string;
49
+ } | {
50
+ type: `codeBlock`;
51
+ lang?: string;
52
+ text: string;
53
+ } | {
54
+ type: `heading`;
55
+ level: number;
56
+ children: MarkdownInline[];
57
+ } | {
58
+ type: `quote`;
59
+ children: MarkdownBlock[];
60
+ } | {
61
+ type: `list`;
62
+ list: MarkdownList;
63
+ } | {
64
+ type: `table`;
65
+ align: (`start` | `center` | `end` | undefined)[];
66
+ head: MarkdownInline[][];
67
+ rows: MarkdownInline[][][];
68
+ } | {
69
+ type: `rule`;
70
+ };
71
+ /** One inline run, linear in its length: the link geometry is precomputed
72
+ * (LinkScanner), the simple spans come off one global regex that never
73
+ * rescans, and link labels recurse at most MAX_LINK_NESTING deep. */
74
+ export declare function parseInline(text: string, depth?: number): MarkdownInline[];
75
+ export declare const LIST_ITEM: RegExp;
76
+ export interface MarkdownListItem {
77
+ /** The item's raw text (its inline markdown). */
78
+ text: string;
79
+ /** `text` parsed. */
80
+ content: MarkdownInline[];
81
+ /** A task item: done (`[x]`) or not (`[ ]`). */
82
+ task?: boolean;
83
+ children: MarkdownList[];
84
+ }
85
+ export interface MarkdownList {
86
+ indent: number;
87
+ ordered: boolean;
88
+ items: MarkdownListItem[];
89
+ }
90
+ /** Consecutive list item lines → a list tree: an item whose marker is
91
+ * indented 2+ columns past its list's nests under the previous item. */
92
+ export declare function parseList(lines: readonly string[]): MarkdownList;
93
+ /** Block quotes and lists nest at most this deep (deeper = text). */
94
+ export declare const MAX_BLOCK_NESTING = 32;
95
+ /** Markdown text → its block tree. */
96
+ export declare function parseMarkdown(text: string): MarkdownBlock[];
@@ -0,0 +1,63 @@
1
+ import type { AnyHostPlugin as HostPlugin } from "./host-types.js";
2
+ /** What a source feeds: an image (the limits hold) or a player stream. */
3
+ export type MediaKind = `image` | `stream`;
4
+ /** How many fetched media nobody shows stay cached (their blob urls live). */
5
+ export declare const MEDIA_CACHE_IDLE_MAX = 64;
6
+ export interface MediaCacheEntry {
7
+ promise: Promise<string>;
8
+ /** Set once the fetch resolved. */
9
+ url?: string;
10
+ /** Mounted consumers. */
11
+ refs: number;
12
+ }
13
+ export declare function mediaCacheKey(url: string, headers: Record<string, string>): string;
14
+ export declare function acquireMedia(k: string, load: () => Promise<string>): MediaCacheEntry;
15
+ export declare function releaseMedia(k: string, e: MediaCacheEntry): void;
16
+ /** The cache's size (tests). */
17
+ export declare function mediaCacheStats(): {
18
+ entries: number;
19
+ inUse: number;
20
+ };
21
+ /** Drop every idle entry and revoke its url (tests, a host that logs out). */
22
+ export declare function clearMediaCache(): void;
23
+ /** One source, planned: `direct` = the url to use as is (no headers, or
24
+ * undefined when the policy denies it), `denied` = the policy refused a
25
+ * non-empty src, `key` = the cache identity of a FETCHED source ('' when
26
+ * direct), `open()` = start (or join) its load: the url promise and the
27
+ * release a consumer calls when it unmounts. */
28
+ export interface MediaSourcePlan {
29
+ fetched: boolean;
30
+ key: string;
31
+ direct: string | undefined;
32
+ denied: boolean;
33
+ open: () => {
34
+ promise: Promise<string>;
35
+ release: () => void;
36
+ };
37
+ }
38
+ export declare function openMediaSource(host: HostPlugin, src: string, kind?: MediaKind): MediaSourcePlan;
39
+ /** A host stream url (never cached here, never revoked: the host owns
40
+ * it), re-checked against the media policy. */
41
+ export declare function streamEntry(host: HostPlugin, req: {
42
+ url: string;
43
+ headers: Record<string, string>;
44
+ }): MediaCacheEntry;
45
+ /** A Video/Audio fetch (no `mediaStreamUrl`): the whole body into a blob
46
+ * under `maxBytes` (Content-Length up front, then as it streams) and
47
+ * `timeoutMs` for the WHOLE download (VAPP-107); no pixel check. */
48
+ export declare function fetchStream(url: string, headers: Record<string, string>, limits?: {
49
+ maxBytes: number;
50
+ timeoutMs: number;
51
+ }, allowed?: (url: string) => boolean): Promise<Blob>;
52
+ /** A fetch under `MEDIA_LIMITS`: the whole request within `timeoutMs`, the
53
+ * body (Content-Length up front, then as it streams) within `maxBytes`, an
54
+ * image's width × height × frames within `maxPixels` before any decode
55
+ * (`mediaImageWithinLimits`: SVG sizes count, an unreadable raster is
56
+ * refused; `image = false` skips that check: a stream's bytes are not
57
+ * an image). A redirected response's final url must pass `allowed` (the
58
+ * host's media policy) or the load fails before a byte is read. */
59
+ export declare function fetchLimited(url: string, headers: Record<string, string>, limits?: {
60
+ maxBytes: number;
61
+ timeoutMs: number;
62
+ maxPixels: number;
63
+ }, image?: boolean, allowed?: (url: string) => boolean): Promise<Blob>;
@@ -0,0 +1,4 @@
1
+ export declare const PLACED: Readonly<Record<string, readonly string[]>>;
2
+ /** The painted id of a SINGLE part (`<domId>.<part>`), or null when the
3
+ * component does not place it. */
4
+ export declare function placedPartId(component: string, part: string, domId: string): string | null;
@@ -0,0 +1,10 @@
1
+ export declare const ALERT_DIALOG_CLASSES: {
2
+ readonly overlay: "fixed inset-0 z-50 bg-black/50 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";
3
+ readonly content: "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg motion-dialog sm:max-w-lg";
4
+ readonly header: "flex flex-col gap-2 text-center sm:text-left";
5
+ readonly footer: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end";
6
+ readonly title: "text-lg font-semibold";
7
+ readonly description: "text-sm text-muted-foreground";
8
+ readonly action: string;
9
+ readonly cancel: string;
10
+ };
@@ -0,0 +1,9 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ export declare const alertVariants: (props?: ({
3
+ variant?: "default" | "destructive" | null | undefined;
4
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
+ export type AlertVariantProps = VariantProps<typeof alertVariants>;
6
+ export declare const ALERT_CLASSES: {
7
+ readonly title: "col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight";
8
+ readonly description: "col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed";
9
+ };
@@ -0,0 +1,2 @@
1
+ export declare const AVATAR_HUE_COUNT = 8;
2
+ export declare function avatarHueIndex(userId: string | null | undefined): number;
@@ -0,0 +1,13 @@
1
+ export declare const AVATAR_CLASSES: {
2
+ readonly root: "relative flex size-8 shrink-0 overflow-hidden rounded-full select-none";
3
+ readonly image: "aspect-square size-full";
4
+ readonly fallback: "flex size-full items-center justify-center rounded-full text-sm";
5
+ /** The fallback without a `userId`: the muted chrome. */
6
+ readonly fallbackMuted: "bg-muted text-muted-foreground";
7
+ };
8
+ export declare function avatarFallbackHue(userId: string | null | undefined): string | undefined;
9
+ /** The inline colours of a hued fallback. */
10
+ export declare function avatarFallbackColors(hue: string): {
11
+ backgroundColor: string;
12
+ color: string;
13
+ };
@@ -0,0 +1,10 @@
1
+ export type BadgeTone = `muted` | `primary`;
2
+ export declare const BADGE_CLASSES: {
3
+ readonly root: "pointer-events-none inline-flex h-4 min-w-4 shrink-0 items-center justify-center rounded-full px-1 text-[10px] leading-none font-semibold tabular-nums";
4
+ readonly tones: {
5
+ readonly primary: "bg-primary text-primary-foreground";
6
+ readonly muted: "bg-muted text-muted-foreground";
7
+ };
8
+ };
9
+ /** What the badge prints for `count` (zero and below render nothing). */
10
+ export declare function badgeLabel(count: number, max?: number): string;
@@ -0,0 +1,10 @@
1
+ export declare const BREADCRUMB_CLASSES: {
2
+ readonly list: "flex list-none flex-wrap items-center gap-1.5 text-sm break-words text-muted-foreground sm:gap-2.5";
3
+ readonly item: "inline-flex items-center gap-1.5";
4
+ readonly link: "transition-colors hover:text-foreground";
5
+ readonly page: "font-normal text-foreground";
6
+ readonly separator: "[&>svg]:size-3.5";
7
+ readonly ellipsis: "flex size-9 items-center justify-center";
8
+ readonly ellipsisIcon: "size-4";
9
+ readonly srOnly: "sr-only";
10
+ };