@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,119 @@
1
+ import type { FunctionCallInfo, MediaOptions, MediaRequest, ThemeIssue, UiNode, UrlPolicy } from "@exponential-at/ui";
2
+ import type { ClientFunction } from "./data.js";
3
+ /** A registry name → the renderer's icon component (a map or a lookup). */
4
+ export type IconMap<Icon = unknown> = Record<string, Icon | undefined> | ((name: string) => Icon | undefined);
5
+ /** A user action: a node's `on.<event>` with an `event` action, resolved. */
6
+ export interface SurfaceActionEvent {
7
+ surfaceId: string;
8
+ /** The catalog event (`press`, `change`, `select`, `submit`…). */
9
+ event: string;
10
+ /** The action's `event.name`. */
11
+ name: string;
12
+ componentId: string;
13
+ context: Record<string, unknown>;
14
+ /** What the component adds (a Select's `value`, a Tabs' `value`…). */
15
+ payload?: Record<string, unknown>;
16
+ timestamp: string;
17
+ }
18
+ /** A host-owned input edit. `change` fires debounced while typing with a
19
+ * monotonically increasing `revision`; `commit` on blur / Enter. The host's
20
+ * echo (a data model write at `path`) is applied only while no newer
21
+ * revision is outstanding and the field is not focused. */
22
+ export interface SurfaceInputEvent {
23
+ surfaceId: string;
24
+ componentId: string;
25
+ /** The input's `name` prop. */
26
+ name: string;
27
+ /** The bound data model pointer, when `value` is a binding. */
28
+ path?: string;
29
+ value: unknown;
30
+ revision: number;
31
+ kind: `change` | `commit`;
32
+ }
33
+ /** A painter that failed: the surface, the component, why. */
34
+ export interface PaintError {
35
+ surfaceId: string;
36
+ componentId: string;
37
+ message: string;
38
+ }
39
+ /** One option a host source supplies (the catalog's `option` shape). */
40
+ export interface SourceOption {
41
+ label: string;
42
+ value: string;
43
+ icon?: string;
44
+ disabled?: boolean;
45
+ }
46
+ export interface HostPlugin<Icon = unknown, Markdown = unknown> {
47
+ /** The icon registry: the catalog's `Icon` names → components. */
48
+ icons?: IconMap<Icon>;
49
+ /** Server events. Returning a promise keeps the source control in its
50
+ * optimistic pending state until it settles. */
51
+ onAction?: (event: SurfaceActionEvent) => void | Promise<void>;
52
+ /** Host-owned input edits. Returning a promise acknowledges the revision
53
+ * when it settles; a sync host acknowledges at once. */
54
+ onInput?: (event: SurfaceInputEvent) => void | Promise<void>;
55
+ /** Opens an href the URL policy allowed (`openUrl`, `Link`); default
56
+ * `window.open(url, "_blank")`. */
57
+ openUrl?: (url: string) => void;
58
+ /** The URL policy EVERY href passes (Link, markdown links, FileUpload
59
+ * file urls, openUrl): `catalog/host.json` urls. Unset = the default
60
+ * schemes; relative urls resolve against `baseUrl`, else `media.baseUrl`,
61
+ * else the document's. A denied href paints as text. */
62
+ urls?: UrlPolicy;
63
+ /** The media policy every src passes when there is no `mediaRequest`
64
+ * (schemes, hosts, private opt-ins, base, header rules):
65
+ * `catalog/host.json` media. */
66
+ media?: MediaOptions;
67
+ /** Extra or overriding client functions, web renderers only (`{call,
68
+ * args}` in a prop; an action naming one runs it). Any OTHER action
69
+ * function name goes to onFunctionCall (the portable host functions). */
70
+ functions?: Record<string, ClientFunction>;
71
+ /** An action `functionCall` to a name outside the built-ins (the host
72
+ * function registry + its policy gate, `ExponentialHost.callFunction`).
73
+ * A promise keeps the source control pending until it settles. */
74
+ onFunctionCall?: (call: FunctionCallInfo) => unknown | Promise<unknown>;
75
+ /** The media loader's request for a source (absolute url + headers, e.g.
76
+ * auth for /api/attachments); null = denied. A request WITH headers is
77
+ * fetched (under the media limits) and shown as a blob url; without, its
78
+ * url is used as is. Its url is re-checked against `media`'s schemes,
79
+ * hosts and private opt-ins. */
80
+ mediaRequest?: (src: string) => MediaRequest | null;
81
+ /** Video/Audio (`catalog/host.json` media: the byte limits do not apply,
82
+ * they stream): a url the browser's player loads WITHOUT headers for a
83
+ * request that carries some (a signed or cookie-authed url), so the
84
+ * player streams and seeks. Its result passes the media policy again.
85
+ * Unset = the request is fetched whole into a blob url under the media
86
+ * byte cap and timeout for the WHOLE download (VAPP-107), so a long
87
+ * video needs this hook. */
88
+ mediaStreamUrl?: (request: MediaRequest) => string | Promise<string>;
89
+ /** A richer markdown renderer than the built-in one (a component taking
90
+ * `{text, className}` in the renderer's framework). */
91
+ Markdown?: Markdown;
92
+ /** Rewrites a media src BEFORE the media policy (signed URLs). */
93
+ resolveUrl?: (src: string) => string;
94
+ /** `onPaintError` (`catalog/host.json` paint): a component's painter
95
+ * failed; it paints an empty box. `hostPlugin(host)` forwards it to the
96
+ * agent as an A2UI `RENDER_FAILED` error. */
97
+ onPaintError?: (error: PaintError) => void;
98
+ /** Called with the node for every Unknown placeholder painted. */
99
+ onUnknown?: (node: UiNode) => void;
100
+ /** Round 4 (VAPP-103): the `theme` prop was unusable (an unknown built-in
101
+ * id, a theme file with issues). The surface never throws: it paints
102
+ * with the default theme and reports why here. */
103
+ onThemeIssues?: (issues: ThemeIssue[]) => void;
104
+ /** Round 1, FileUpload: the picked/dropped files' BYTES (the `upload`
105
+ * event carries only `{name, size, type}`). Return a promise to keep the
106
+ * drop zone busy until it settles. */
107
+ onUpload?: (files: File[], target: {
108
+ nodeId: string;
109
+ name: string;
110
+ }) => void | Promise<void>;
111
+ /** Round 1, Select `source`: a host list id (`exp:statuses`) → its
112
+ * options for a query (`""` when not searchable). */
113
+ optionSource?: (source: string, query: string) => SourceOption[] | Promise<SourceOption[]>;
114
+ }
115
+ /** Any renderer's plugin (what the framework-free helpers take). */
116
+ export type AnyHostPlugin = HostPlugin<unknown, unknown>;
117
+ /** A registry lookup: the host's map (or function) first, then the
118
+ * renderer's own fallbacks. */
119
+ export declare function lookupIcon<Icon>(icons: IconMap<Icon> | undefined, name: string, fallbacks?: Readonly<Record<string, Icon>>): Icon | undefined;
@@ -0,0 +1,28 @@
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 type { HostPlugin, AnyHostPlugin, IconMap, PaintError, SourceOption, SurfaceActionEvent, SurfaceInputEvent } from "./host-types.js";
11
+ export { str, num, bool, arr, objects, phrase, formatFileSize, acceptsFile, failingChecks, failingCheck, builtinIconName, joinIds } from "./coerce.js";
12
+ export { sortRows } from "./table.js";
13
+ export type { TableColumn, TableSort } from "./table.js";
14
+ export { isoDate, parseIsoDate, addDays, addMonths, sameDay, monthGrid, calendarStop } from "./dates.js";
15
+ export { DEBOUNCE_MS, HostOwnedController, parseLocaleNumber } from "./inputs.js";
16
+ export type { HostOwnedControllerOptions, HostOwnedSend } from "./inputs.js";
17
+ export { MEDIA_CACHE_IDLE_MAX, acquireMedia, releaseMedia, mediaCacheKey, mediaCacheStats, clearMediaCache, openMediaSource, streamEntry, fetchStream, fetchLimited } from "./media.js";
18
+ export type { MediaKind, MediaCacheEntry, MediaSourcePlan } from "./media.js";
19
+ export { MAX_LINK_NESTING, MAX_LINK_DEST, MAX_BLOCK_NESTING, LIST_ITEM, linkAt, wholeImage, parseInline, parseList, parseMarkdown } from "./markdown.js";
20
+ export type { MarkdownInline, MarkdownBlock, MarkdownList, MarkdownListItem } from "./markdown.js";
21
+ export { FormRegistry, documentOrder, fieldErrorsVisible, validateOnDefault } from "./form.js";
22
+ export type { FormField, FormError, FormCheck } from "./form.js";
23
+ export { scrollParent, listViewport } from "./list.js";
24
+ export type { ListAxis } from "./list.js";
25
+ export { nextEnabledIndex, typeaheadStep, TYPEAHEAD_RESET_MS } from "./listbox.js";
26
+ export type { TypeaheadBuffer } from "./listbox.js";
27
+ export { PLACED, placedPartId } from "./parts.js";
28
+ export { share } from "./share.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,13 @@
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). */
9
+ export declare function listViewport(el: HTMLElement, axis: ListAxis, rtl: boolean, known?: HTMLElement | null): {
10
+ scroll: number;
11
+ viewport: number;
12
+ scroller: HTMLElement | null;
13
+ };
@@ -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,62 @@
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
+ }): 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). */
58
+ export declare function fetchLimited(url: string, headers: Record<string, string>, limits?: {
59
+ maxBytes: number;
60
+ timeoutMs: number;
61
+ maxPixels: number;
62
+ }, image?: 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
+ };
@@ -0,0 +1,6 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ export declare const buttonVariants: (props?: ({
3
+ variant?: "link" | "text" | "default" | "secondary" | "outline" | "ghost" | "destructive" | "glass" | null | undefined;
4
+ size?: "icon" | "default" | "sm" | "lg" | "xs" | "icon-sm" | "icon-xs" | "inline" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ export type ButtonVariantProps = VariantProps<typeof buttonVariants>;
@@ -0,0 +1,43 @@
1
+ export declare const CALENDAR_CLASSES: {
2
+ readonly root: string;
3
+ readonly classNames: {
4
+ readonly root: "w-fit";
5
+ readonly months: "relative flex flex-col gap-4 md:flex-row";
6
+ readonly month: "flex w-full flex-col gap-4";
7
+ readonly nav: "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1";
8
+ readonly button_previous: "size-(--cell-size) p-0 select-none aria-disabled:opacity-50";
9
+ readonly button_next: "size-(--cell-size) p-0 select-none aria-disabled:opacity-50";
10
+ readonly month_caption: "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)";
11
+ readonly dropdowns: "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium";
12
+ readonly dropdown_root: "relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50";
13
+ readonly dropdown: "absolute inset-0 bg-popover opacity-0";
14
+ readonly caption_label: "font-medium select-none";
15
+ readonly table: "w-full border-collapse";
16
+ readonly weekdays: "flex";
17
+ readonly weekday: "flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none";
18
+ readonly week: "mt-2 flex w-full";
19
+ readonly week_number_header: "w-(--cell-size) select-none";
20
+ readonly week_number: "text-[0.8rem] text-muted-foreground select-none";
21
+ readonly day: "group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md";
22
+ readonly range_start: "rounded-l-md bg-accent";
23
+ readonly range_middle: "rounded-none";
24
+ readonly range_end: "rounded-r-md bg-accent";
25
+ readonly today: "rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none";
26
+ readonly outside: "text-muted-foreground aria-selected:text-muted-foreground";
27
+ readonly disabled: "text-muted-foreground opacity-50";
28
+ readonly hidden: "invisible";
29
+ };
30
+ /** `caption_label` per `captionLayout`: `label`, else a dropdown. */
31
+ readonly captionLabel: {
32
+ readonly label: "text-sm";
33
+ readonly dropdown: "flex h-8 items-center gap-1 rounded-md pr-1 pl-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground";
34
+ };
35
+ /** The `day` cell's first-selected corner, with or without week numbers. */
36
+ readonly dayFirst: {
37
+ readonly weekNumbers: "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md";
38
+ readonly plain: "[&:first-child[data-selected=true]_button]:rounded-l-md";
39
+ };
40
+ readonly chevron: "size-4";
41
+ readonly weekNumber: "flex size-(--cell-size) items-center justify-center text-center";
42
+ readonly dayButton: "flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70";
43
+ };
@@ -0,0 +1,9 @@
1
+ export declare const CARD_CLASSES: {
2
+ readonly root: "rounded-xl border border-glass-stroke-card bg-glass-card-opaque flex flex-col gap-6 backdrop-blur-md py-6 text-card-foreground shadow-sm";
3
+ readonly header: "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6";
4
+ readonly title: "leading-none font-semibold";
5
+ readonly description: "text-sm text-muted-foreground";
6
+ readonly action: "col-start-2 row-span-2 row-start-1 self-start justify-self-end";
7
+ readonly content: "px-6";
8
+ readonly footer: "flex items-center px-6 [.border-t]:pt-6";
9
+ };
@@ -0,0 +1,5 @@
1
+ export declare const CHECKBOX_CLASSES: {
2
+ readonly root: "peer size-4 shrink-0 rounded-sm border border-glass-stroke-strong bg-glass-row shadow-none transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary";
3
+ readonly indicator: "grid place-content-center text-current transition-none";
4
+ readonly icon: "size-3.5";
5
+ };
@@ -0,0 +1,32 @@
1
+ export interface ChoiceTileOption {
2
+ value: string;
3
+ label: string;
4
+ description?: string | null;
5
+ /** The picture's url (a relative `/api/attachments/{id}` resolves in the
6
+ * app through `renderImage`). */
7
+ image?: string | null;
8
+ disabled?: boolean;
9
+ }
10
+ /** `columns` clamped to 1–4 (default 2). */
11
+ export declare function choiceColumns(columns: unknown): number;
12
+ /** The values a comma-joined eUI `value` picks (single: the whole string). */
13
+ export declare function choiceValues(value: unknown, multiple: boolean): string[];
14
+ /** A press on `value`: single picks it; multiple toggles it, the list kept in
15
+ * OPTION order (fixtures/interactions-round1.json `choiceTiles`). */
16
+ export declare function choiceToggle(picked: readonly string[], value: string, multiple: boolean, order: readonly string[]): string[];
17
+ export interface TileState {
18
+ index: number;
19
+ selected: boolean;
20
+ disabled: boolean;
21
+ }
22
+ export declare const CHOICE_TILES_CLASSES: {
23
+ readonly root: "gap-[8px]";
24
+ readonly tile: "flex min-w-0 cursor-pointer flex-col gap-[4px] rounded-[10px] border-[1px] border-border bg-card p-[8px] text-start outline-none transition-colors hover:bg-secondary focus-visible:border-ring disabled:cursor-not-allowed disabled:opacity-50";
25
+ readonly tileSelected: "border-[2px] border-primary bg-accent p-[7px] hover:bg-accent";
26
+ readonly tileInvalid: "border-destructive";
27
+ readonly picture: "relative flex aspect-[1.6] w-full shrink-0 items-center justify-center overflow-hidden rounded-[6px] bg-muted text-muted-foreground";
28
+ readonly image: "absolute inset-0 size-full object-cover";
29
+ readonly placeholder: "size-[20px] opacity-60";
30
+ readonly label: "min-w-0 text-sm leading-5 font-medium text-foreground";
31
+ readonly description: "min-w-0 text-xs leading-4 text-muted-foreground";
32
+ };
@@ -0,0 +1,3 @@
1
+ import { type ClassValue } from "clsx";
2
+ export declare function cn(...inputs: ClassValue[]): string;
3
+ export declare function getInitials(value: string): string;
@@ -0,0 +1,24 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ export declare const codeBlockVariants: (props?: ({
3
+ variant?: "default" | "destructive" | null | undefined;
4
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
+ export type CodeBlockVariantProps = VariantProps<typeof codeBlockVariants>;
6
+ /** The catalog's `codeToken` kinds, painted with the app's code palette
7
+ * (`--hljs-*`, the diff view's and the editor's); a destructive block drops
8
+ * the colours for its own. */
9
+ export declare const CODE_TOKEN_CLASS: Record<string, string>;
10
+ export declare const codeBlockLineVariants: (props?: ({
11
+ variant?: "default" | "added" | "removed" | "highlighted" | null | undefined;
12
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
13
+ export type CodeBlockLineVariantProps = VariantProps<typeof codeBlockLineVariants>;
14
+ export declare const CODE_BLOCK_CLASSES: {
15
+ readonly header: "flex min-w-0 shrink-0 items-center gap-2 px-3 pt-3 text-muted-foreground group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:pt-2.5 group-data-[variant=destructive]/code-block:text-destructive *:has-[>[data-slot=code-block-title]]:min-w-0";
16
+ readonly title: "min-w-0 truncate font-sans text-sm font-medium text-foreground group-data-[size=sm]/code-block:text-xs group-data-[variant=destructive]/code-block:text-destructive [&_svg]:pointer-events-none [&_svg]:inline-block [&_svg]:align-middle [&_svg:not([class*='size-'])]:size-3.5 *:[svg]:me-1.5";
17
+ readonly actions: "-my-1 ms-auto -me-1 flex shrink-0 items-center gap-1 [[data-slot=code-block]>&]:absolute [[data-slot=code-block]>&]:end-2 [[data-slot=code-block]>&]:top-2 [[data-slot=code-block]>&]:z-10 [[data-slot=code-block]>&]:m-0 [[data-slot=code-block]>&]:opacity-0 [[data-slot=code-block]>&]:transition-opacity [[data-slot=code-block]>&]:group-focus-within/code-block:opacity-100 [[data-slot=code-block]>&]:group-hover/code-block:opacity-100 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:end-1.5 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:top-1.5 [[data-slot=code-block]>&]:pointer-coarse:opacity-100 [[data-slot=code-block]>&]:*:[button]:bg-background [[data-slot=code-block]>&]:*:[button]:ring-1 [[data-slot=code-block]>&]:*:[button]:ring-foreground/10";
18
+ readonly srOnly: "sr-only";
19
+ readonly content: "min-h-0 min-w-0 scroll-fade-x overflow-auto overscroll-contain px-3 py-3 text-start font-mono leading-relaxed outline-none [--code-block-pad:calc(var(--spacing)*6)] group-has-data-[slot=code-block-footer]/code-block:pb-2 group-has-data-[slot=code-block-header]/code-block:pt-2 group-has-data-[slot=code-block-header]/code-block:[--code-block-pad:calc(var(--spacing)*5)] group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:py-2.5 group-data-[size=sm]/code-block:[--code-block-pad:calc(var(--spacing)*5)] group-data-[size=sm]/code-block:group-has-data-[slot=code-block-header]/code-block:pt-1.5 group-data-[size=sm]/code-block:group-has-data-[slot=code-block-header]/code-block:[--code-block-pad:calc(var(--spacing)*4)] data-wrap:scroll-fade-y data-wrap:wrap-break-word data-wrap:whitespace-pre-wrap";
20
+ readonly code: "grid min-h-lh min-w-max content-start in-data-numbered:grid-cols-[auto_1fr] in-data-wrap:min-w-0";
21
+ readonly token: "group-data-[variant=destructive]/code-block:text-current";
22
+ readonly lineContent: "min-w-0";
23
+ readonly footer: "flex min-w-0 shrink-0 items-center gap-2 px-3 pb-3 text-muted-foreground group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:pb-2.5";
24
+ };