@agent-ui-kit/components 0.0.3

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 (271) hide show
  1. package/dist/base-styles.css +8 -0
  2. package/dist/component-styles.css +147 -0
  3. package/dist/controls/_base/index.d.ts +3 -0
  4. package/dist/controls/_base/index.js +9 -0
  5. package/dist/controls/_base/indicator-element.d.ts +132 -0
  6. package/dist/controls/_base/indicator-element.js +158 -0
  7. package/dist/controls/_base/listbox-element.d.ts +70 -0
  8. package/dist/controls/_base/listbox-element.js +74 -0
  9. package/dist/controls/_base/range-element.d.ts +120 -0
  10. package/dist/controls/_base/range-element.js +158 -0
  11. package/dist/controls/_surface/container-box.css +301 -0
  12. package/dist/controls/_surface/container.css +156 -0
  13. package/dist/controls/_token-surface/token-surface.d.ts +35 -0
  14. package/dist/controls/_token-surface/token-surface.js +97 -0
  15. package/dist/controls/attachment/attachment-meta.d.ts +8 -0
  16. package/dist/controls/attachment/attachment-meta.js +84 -0
  17. package/dist/controls/attachment/attachment.css +91 -0
  18. package/dist/controls/attachment/attachment.d.ts +40 -0
  19. package/dist/controls/attachment/attachment.js +70 -0
  20. package/dist/controls/avatar/avatar-initials.d.ts +4 -0
  21. package/dist/controls/avatar/avatar-initials.js +30 -0
  22. package/dist/controls/avatar/avatar.css +87 -0
  23. package/dist/controls/avatar/avatar.d.ts +40 -0
  24. package/dist/controls/avatar/avatar.js +77 -0
  25. package/dist/controls/badge/badge.css +175 -0
  26. package/dist/controls/badge/badge.d.ts +36 -0
  27. package/dist/controls/badge/badge.js +71 -0
  28. package/dist/controls/bar-chart/bar-chart.css +110 -0
  29. package/dist/controls/bar-chart/bar-chart.d.ts +26 -0
  30. package/dist/controls/bar-chart/bar-chart.js +80 -0
  31. package/dist/controls/bar-chart/bar-math.d.ts +31 -0
  32. package/dist/controls/bar-chart/bar-math.js +106 -0
  33. package/dist/controls/button/button.css +263 -0
  34. package/dist/controls/button/button.d.ts +61 -0
  35. package/dist/controls/button/button.js +115 -0
  36. package/dist/controls/calendar/calendar.css +495 -0
  37. package/dist/controls/calendar/calendar.d.ts +161 -0
  38. package/dist/controls/calendar/calendar.js +1004 -0
  39. package/dist/controls/card/card-content.d.ts +24 -0
  40. package/dist/controls/card/card-content.js +133 -0
  41. package/dist/controls/card/card-footer.d.ts +3 -0
  42. package/dist/controls/card/card-footer.js +16 -0
  43. package/dist/controls/card/card-header.d.ts +3 -0
  44. package/dist/controls/card/card-header.js +18 -0
  45. package/dist/controls/card/card.css +445 -0
  46. package/dist/controls/card/card.d.ts +51 -0
  47. package/dist/controls/card/card.js +61 -0
  48. package/dist/controls/checkbox/checkbox.css +204 -0
  49. package/dist/controls/checkbox/checkbox.d.ts +114 -0
  50. package/dist/controls/checkbox/checkbox.js +130 -0
  51. package/dist/controls/code/code.css +72 -0
  52. package/dist/controls/code/code.d.ts +23 -0
  53. package/dist/controls/code/code.js +40 -0
  54. package/dist/controls/color-picker/color-picker.css +209 -0
  55. package/dist/controls/color-picker/color-picker.d.ts +84 -0
  56. package/dist/controls/color-picker/color-picker.js +545 -0
  57. package/dist/controls/color-picker/color.d.ts +40 -0
  58. package/dist/controls/color-picker/color.js +159 -0
  59. package/dist/controls/column/column.css +151 -0
  60. package/dist/controls/column/column.d.ts +107 -0
  61. package/dist/controls/column/column.js +57 -0
  62. package/dist/controls/combo-box/combo-box.css +397 -0
  63. package/dist/controls/combo-box/combo-box.d.ts +133 -0
  64. package/dist/controls/combo-box/combo-box.js +680 -0
  65. package/dist/controls/command-modal/command-modal.css +226 -0
  66. package/dist/controls/command-modal/command-modal.d.ts +42 -0
  67. package/dist/controls/command-modal/command-modal.js +315 -0
  68. package/dist/controls/disclosure/disclosure.css +162 -0
  69. package/dist/controls/disclosure/disclosure.d.ts +37 -0
  70. package/dist/controls/disclosure/disclosure.js +207 -0
  71. package/dist/controls/field/field.css +140 -0
  72. package/dist/controls/field/field.d.ts +27 -0
  73. package/dist/controls/field/field.js +228 -0
  74. package/dist/controls/form-provider/form-provider.css +40 -0
  75. package/dist/controls/form-provider/form-provider.d.ts +42 -0
  76. package/dist/controls/form-provider/form-provider.js +105 -0
  77. package/dist/controls/grid/grid.css +72 -0
  78. package/dist/controls/grid/grid.d.ts +60 -0
  79. package/dist/controls/grid/grid.js +56 -0
  80. package/dist/controls/icon/icon.css +37 -0
  81. package/dist/controls/icon/icon.d.ts +25 -0
  82. package/dist/controls/icon/icon.js +55 -0
  83. package/dist/controls/index.d.ts +57 -0
  84. package/dist/controls/index.js +136 -0
  85. package/dist/controls/ladder/ladder.css +89 -0
  86. package/dist/controls/ladder/ladder.d.ts +27 -0
  87. package/dist/controls/ladder/ladder.js +78 -0
  88. package/dist/controls/list/list.css +118 -0
  89. package/dist/controls/list/list.d.ts +84 -0
  90. package/dist/controls/list/list.js +48 -0
  91. package/dist/controls/menu/menu.css +195 -0
  92. package/dist/controls/menu/menu.d.ts +44 -0
  93. package/dist/controls/menu/menu.js +248 -0
  94. package/dist/controls/modal/modal.css +99 -0
  95. package/dist/controls/modal/modal.d.ts +61 -0
  96. package/dist/controls/modal/modal.js +155 -0
  97. package/dist/controls/popover/popover.css +83 -0
  98. package/dist/controls/popover/popover.d.ts +44 -0
  99. package/dist/controls/popover/popover.js +164 -0
  100. package/dist/controls/progress/progress.css +106 -0
  101. package/dist/controls/progress/progress.d.ts +28 -0
  102. package/dist/controls/progress/progress.js +80 -0
  103. package/dist/controls/radio/radio-group.css +84 -0
  104. package/dist/controls/radio/radio-group.d.ts +152 -0
  105. package/dist/controls/radio/radio-group.js +350 -0
  106. package/dist/controls/radio/radio.css +219 -0
  107. package/dist/controls/radio/radio.d.ts +19 -0
  108. package/dist/controls/radio/radio.js +75 -0
  109. package/dist/controls/ramp/ramp.css +75 -0
  110. package/dist/controls/ramp/ramp.d.ts +29 -0
  111. package/dist/controls/ramp/ramp.js +72 -0
  112. package/dist/controls/row/row.css +152 -0
  113. package/dist/controls/row/row.d.ts +95 -0
  114. package/dist/controls/row/row.js +45 -0
  115. package/dist/controls/segment/segment.css +66 -0
  116. package/dist/controls/segment/segment.d.ts +3 -0
  117. package/dist/controls/segment/segment.js +26 -0
  118. package/dist/controls/segmented-control/segmented-control.css +189 -0
  119. package/dist/controls/segmented-control/segmented-control.d.ts +20 -0
  120. package/dist/controls/segmented-control/segmented-control.js +64 -0
  121. package/dist/controls/select/select.css +467 -0
  122. package/dist/controls/select/select.d.ts +147 -0
  123. package/dist/controls/select/select.js +538 -0
  124. package/dist/controls/slider/slider.css +231 -0
  125. package/dist/controls/slider/slider.d.ts +111 -0
  126. package/dist/controls/slider/slider.js +60 -0
  127. package/dist/controls/slider-multi/slider-multi.css +197 -0
  128. package/dist/controls/slider-multi/slider-multi.d.ts +149 -0
  129. package/dist/controls/slider-multi/slider-multi.js +380 -0
  130. package/dist/controls/sparkline/sparkline-math.d.ts +23 -0
  131. package/dist/controls/sparkline/sparkline-math.js +79 -0
  132. package/dist/controls/sparkline/sparkline.css +61 -0
  133. package/dist/controls/sparkline/sparkline.d.ts +27 -0
  134. package/dist/controls/sparkline/sparkline.js +74 -0
  135. package/dist/controls/split/constrain.d.ts +44 -0
  136. package/dist/controls/split/constrain.js +126 -0
  137. package/dist/controls/split/split-pane.css +63 -0
  138. package/dist/controls/split/split-pane.d.ts +49 -0
  139. package/dist/controls/split/split-pane.js +42 -0
  140. package/dist/controls/split/split.css +127 -0
  141. package/dist/controls/split/split.d.ts +42 -0
  142. package/dist/controls/split/split.js +364 -0
  143. package/dist/controls/stat/stat-model.d.ts +22 -0
  144. package/dist/controls/stat/stat-model.js +69 -0
  145. package/dist/controls/stat/stat.css +101 -0
  146. package/dist/controls/stat/stat.d.ts +30 -0
  147. package/dist/controls/stat/stat.js +73 -0
  148. package/dist/controls/status-stream/status-stream.css +151 -0
  149. package/dist/controls/status-stream/status-stream.d.ts +108 -0
  150. package/dist/controls/status-stream/status-stream.js +417 -0
  151. package/dist/controls/swatch/swatch.css +66 -0
  152. package/dist/controls/swatch/swatch.d.ts +28 -0
  153. package/dist/controls/swatch/swatch.js +74 -0
  154. package/dist/controls/swiper/swiper-item.css +17 -0
  155. package/dist/controls/swiper/swiper-item.d.ts +31 -0
  156. package/dist/controls/swiper/swiper-item.js +47 -0
  157. package/dist/controls/swiper/swiper-label.css +10 -0
  158. package/dist/controls/swiper/swiper-label.d.ts +4 -0
  159. package/dist/controls/swiper/swiper-label.js +20 -0
  160. package/dist/controls/swiper/swiper-paddles.css +26 -0
  161. package/dist/controls/swiper/swiper-paddles.d.ts +10 -0
  162. package/dist/controls/swiper/swiper-paddles.js +62 -0
  163. package/dist/controls/swiper/swiper-pagination.css +60 -0
  164. package/dist/controls/swiper/swiper-pagination.d.ts +31 -0
  165. package/dist/controls/swiper/swiper-pagination.js +78 -0
  166. package/dist/controls/swiper/swiper.css +153 -0
  167. package/dist/controls/swiper/swiper.d.ts +158 -0
  168. package/dist/controls/swiper/swiper.js +659 -0
  169. package/dist/controls/switch/switch.css +194 -0
  170. package/dist/controls/switch/switch.d.ts +5 -0
  171. package/dist/controls/switch/switch.js +18 -0
  172. package/dist/controls/table/table-model.d.ts +43 -0
  173. package/dist/controls/table/table-model.js +124 -0
  174. package/dist/controls/table/table.css +90 -0
  175. package/dist/controls/table/table.d.ts +29 -0
  176. package/dist/controls/table/table.js +178 -0
  177. package/dist/controls/tabs/tab-panel.d.ts +10 -0
  178. package/dist/controls/tabs/tab-panel.js +89 -0
  179. package/dist/controls/tabs/tab.d.ts +26 -0
  180. package/dist/controls/tabs/tab.js +67 -0
  181. package/dist/controls/tabs/tabs.css +181 -0
  182. package/dist/controls/tabs/tabs.d.ts +61 -0
  183. package/dist/controls/tabs/tabs.js +176 -0
  184. package/dist/controls/text/href.d.ts +26 -0
  185. package/dist/controls/text/href.js +48 -0
  186. package/dist/controls/text/text.css +328 -0
  187. package/dist/controls/text/text.d.ts +85 -0
  188. package/dist/controls/text/text.js +273 -0
  189. package/dist/controls/text-field/text-field.css +498 -0
  190. package/dist/controls/text-field/text-field.d.ts +226 -0
  191. package/dist/controls/text-field/text-field.js +905 -0
  192. package/dist/controls/textarea/textarea.css +251 -0
  193. package/dist/controls/textarea/textarea.d.ts +136 -0
  194. package/dist/controls/textarea/textarea.js +312 -0
  195. package/dist/controls/theme-provider/theme-provider.css +48 -0
  196. package/dist/controls/theme-provider/theme-provider.d.ts +59 -0
  197. package/dist/controls/theme-provider/theme-provider.js +40 -0
  198. package/dist/controls/timeline/timeline.css +33 -0
  199. package/dist/controls/timeline/timeline.d.ts +39 -0
  200. package/dist/controls/timeline/timeline.js +52 -0
  201. package/dist/controls/timeline-item/timeline-item.css +495 -0
  202. package/dist/controls/timeline-item/timeline-item.d.ts +79 -0
  203. package/dist/controls/timeline-item/timeline-item.js +360 -0
  204. package/dist/controls/toast/toast-region.css +56 -0
  205. package/dist/controls/toast/toast-region.d.ts +20 -0
  206. package/dist/controls/toast/toast-region.js +113 -0
  207. package/dist/controls/toast/toast.css +96 -0
  208. package/dist/controls/toast/toast.d.ts +28 -0
  209. package/dist/controls/toast/toast.js +191 -0
  210. package/dist/controls/toolbar/toolbar.css +125 -0
  211. package/dist/controls/toolbar/toolbar.d.ts +108 -0
  212. package/dist/controls/toolbar/toolbar.js +68 -0
  213. package/dist/controls/tooltip/tooltip.css +80 -0
  214. package/dist/controls/tooltip/tooltip.d.ts +57 -0
  215. package/dist/controls/tooltip/tooltip.js +205 -0
  216. package/dist/descriptor/component-descriptor.d.ts +112 -0
  217. package/dist/descriptor/component-descriptor.js +492 -0
  218. package/dist/descriptor/index.d.ts +1 -0
  219. package/dist/descriptor/index.js +5 -0
  220. package/dist/dom/container.d.ts +45 -0
  221. package/dist/dom/container.js +60 -0
  222. package/dist/dom/element.d.ts +98 -0
  223. package/dist/dom/element.js +221 -0
  224. package/dist/dom/form.d.ts +240 -0
  225. package/dist/dom/form.js +399 -0
  226. package/dist/dom/index.d.ts +10 -0
  227. package/dist/dom/index.js +31 -0
  228. package/dist/dom/props.d.ts +56 -0
  229. package/dist/dom/props.js +231 -0
  230. package/dist/dom/repeat.d.ts +10 -0
  231. package/dist/dom/repeat.js +202 -0
  232. package/dist/dom/template.d.ts +161 -0
  233. package/dist/dom/template.js +634 -0
  234. package/dist/dom/watch.d.ts +11 -0
  235. package/dist/dom/watch.js +82 -0
  236. package/dist/foundation-styles.css +9 -0
  237. package/dist/index.d.ts +2 -0
  238. package/dist/index.js +3 -0
  239. package/dist/reactive/graph.d.ts +65 -0
  240. package/dist/reactive/graph.js +310 -0
  241. package/dist/reactive/index.d.ts +3 -0
  242. package/dist/reactive/index.js +4 -0
  243. package/dist/reactive/scheduler.d.ts +13 -0
  244. package/dist/reactive/scheduler.js +49 -0
  245. package/dist/traits/area-drag.d.ts +12 -0
  246. package/dist/traits/area-drag.js +70 -0
  247. package/dist/traits/form-registry.d.ts +36 -0
  248. package/dist/traits/form-registry.js +108 -0
  249. package/dist/traits/index.d.ts +24 -0
  250. package/dist/traits/index.js +19 -0
  251. package/dist/traits/overlay.d.ts +50 -0
  252. package/dist/traits/overlay.js +277 -0
  253. package/dist/traits/pane-resize.d.ts +26 -0
  254. package/dist/traits/pane-resize.js +103 -0
  255. package/dist/traits/press-activation.d.ts +11 -0
  256. package/dist/traits/press-activation.js +55 -0
  257. package/dist/traits/roving-focus.d.ts +52 -0
  258. package/dist/traits/roving-focus.js +214 -0
  259. package/dist/traits/scroll-fade.d.ts +28 -0
  260. package/dist/traits/scroll-fade.js +120 -0
  261. package/dist/traits/selection-commit.d.ts +30 -0
  262. package/dist/traits/selection-commit.js +146 -0
  263. package/dist/traits/tabbable.d.ts +12 -0
  264. package/dist/traits/tabbable.js +59 -0
  265. package/dist/traits/track-user-invalid.d.ts +36 -0
  266. package/dist/traits/track-user-invalid.js +52 -0
  267. package/dist/traits/value-codec.d.ts +120 -0
  268. package/dist/traits/value-codec.js +497 -0
  269. package/dist/traits/value-drag.d.ts +18 -0
  270. package/dist/traits/value-drag.js +84 -0
  271. package/package.json +263 -0
@@ -0,0 +1,73 @@
1
+ // stat.ts — UIStatElement, the Display-class metric tile (LLD-C5, report-family.lld.md §3; SPEC-R7..R10;
2
+ // ADR-0111). Real, selectable DOM text — label + value + optional delta + optional caption — in a small
3
+ // component-built grid; deliberately NO heading stamp (SPEC-R8 — a stat's value is not a document
4
+ // heading; this retires the fake-`h3`-in-a-card idiom the whole intake was forced by,
5
+ // `a2ui/src/examples/patterns.ts:183-187` / `catalog-coverage.ts:319-323`). Non-interactive,
6
+ // non-form-associated: no events, no keyboard contract, no focus, no `size`/`scale` geometry (Display
7
+ // class, SPEC-R17). No child/slot seam (ADR-0111 fork F2, binding — composing a Sparkline beside a stat
8
+ // is pure composition in a Row, OUTSIDE this component; never a slot here).
9
+ //
10
+ // ONE render effect (reads label/value/delta/caption): a full `replaceChildren` rebuild per change —
11
+ // unlike ui-table there is no interior user state worth preserving on a four-span tile (no scroll, no
12
+ // selection), so the simple whole-swap is correct (LLD-C5). No internals ARIA is minted: real text
13
+ // carries the tile's whole meaning, including the delta's DIRECTION (SPEC-R9) — the direction word is
14
+ // real, visually-hidden-but-announced text preceding the signed number; the glyph is `aria-hidden` and
15
+ // text-free; direction never travels by color (ADR-0057 — no `[data-dir]` rule in stat.css touches ink).
16
+ import { UIElement, prop } from "../../dom/index.js";
17
+ import { deltaParts, formatStatValue, statDeltaProp, statValueProp } from "./stat-model.js";
18
+ const props = {
19
+ label: { ...prop.string(''), reflect: true },
20
+ figure: statValueProp, // string | number · number → Intl-formatted, string passes through (stat-model.ts). Renamed from `value` (TKT-0069 item 1 ruling: `value` = the FACE form value, reserved; the A2UI catalog keeps wire `value`, mapped in its bespoke factory)
21
+ delta: statDeltaProp, // number | null · absent/non-finite → the delta region is not rendered (SPEC-R7)
22
+ caption: prop.string(''),
23
+ };
24
+ export class UIStatElement extends UIElement {
25
+ static props = props;
26
+ connected() {
27
+ this.effect(() => {
28
+ const label = this.label;
29
+ const value = formatStatValue(this.figure);
30
+ const caption = this.caption;
31
+ const delta = deltaParts(this.delta);
32
+ // Reading order label → value → delta → caption is DOM order (SPEC-R8) — the array below IS that
33
+ // order; one replaceChildren commits the whole tile (whole-swap semantics, no incremental patching).
34
+ const nodes = [this.#part('label', label), this.#part('value', value)];
35
+ if (delta !== null)
36
+ nodes.push(this.#deltaNode(delta));
37
+ if (caption !== '')
38
+ nodes.push(this.#part('caption', caption));
39
+ this.replaceChildren(...nodes);
40
+ });
41
+ }
42
+ /** One `<span data-part="{part}">{text}</span>` — the tile's plain text cells (label/value/caption). */
43
+ #part(part, text) {
44
+ const span = document.createElement('span');
45
+ span.setAttribute('data-part', part);
46
+ span.textContent = text;
47
+ return span;
48
+ }
49
+ /**
50
+ * The delta region (SPEC-R9): `data-dir` carries direction for the CSS glyph orientation; a
51
+ * component-drawn `aria-hidden` glyph (omitted when `dir === 'flat'` — no arrow for "unchanged"); a
52
+ * visually-hidden-but-announced direction WORD precedes the signed number, so the direction is real,
53
+ * readable text — never color, never a bare glyph codepoint (ADR-0111 cl.4, ADR-0057).
54
+ */
55
+ #deltaNode(delta) {
56
+ const region = document.createElement('span');
57
+ region.setAttribute('data-part', 'delta');
58
+ region.setAttribute('data-dir', delta.dir);
59
+ if (delta.dir !== 'flat') {
60
+ const glyph = document.createElement('span');
61
+ glyph.setAttribute('data-part', 'delta-glyph');
62
+ glyph.setAttribute('aria-hidden', 'true');
63
+ region.append(glyph);
64
+ }
65
+ const word = document.createElement('span');
66
+ word.setAttribute('data-part', 'delta-word');
67
+ word.textContent = `${delta.word} `;
68
+ region.append(word, document.createTextNode(delta.text));
69
+ return region;
70
+ }
71
+ }
72
+ if (!customElements.get('ui-stat'))
73
+ customElements.define('ui-stat', UIStatElement); // idempotent self-define
@@ -0,0 +1,151 @@
1
+ /* status-stream.css — ui-status-stream, the single-file component stylesheet (ADR-0003;
2
+ * timeline-family.lld.md §4 · SPEC-R10/R14/R15). Like ui-timeline, the rail geometry/rhythm belongs
3
+ * entirely to the authored `ui-timeline-item` children this host creates via its own API
4
+ * (status-stream.ts) — this file owns ONLY the live strip's scroll region (the one-owned-scroll-region
5
+ * law, SPEC-R10) and its bounded viewport.
6
+ *
7
+ * [1] TOKEN BLOCK — `:where(ui-status-stream)` declares the strip's OWN dimensional facts: the
8
+ * bare-host `min-inline-size` floor (the ui-slider whole-shape lesson) and a bounded
9
+ * `max-block-size` so the strip is a genuine scrollable "now" viewport, not an ever-growing page.
10
+ * [2] STYLES BLOCK — `@scope (ui-status-stream)` lays out the imperatively-appended `ui-timeline-item`
11
+ * children as a vertical flex stack and OWNS its scroll region (`overflow-y: auto` — the fleet's
12
+ * physical-property convention for a scroll viewport, card.css/menu.css/combo-box.css precedent).
13
+ */
14
+
15
+ /* ════════════════ [1] TOKEN BLOCK — :where(ui-status-stream) declares --ui-status-stream-* ════════════════ */
16
+
17
+ :where(ui-status-stream) {
18
+ --ui-status-stream-min-inline-size: 16rem;
19
+ --ui-status-stream-max-block-size: 20rem;
20
+
21
+ /* the opt-in streaming header (ADR-0146 F8) — chrome pinned above the scroll region. Marker sizes are
22
+ em/rem (never raw px), so the header rides the ambient type scale with no per-scale ramp of its own. */
23
+ --ui-status-stream-header-marker-box: 1em;
24
+ --ui-status-stream-header-dot-size: 0.5em;
25
+ --ui-status-stream-header-gap: var(--md-sys-space-sm);
26
+ --ui-status-stream-header-pad: var(--md-sys-space-xs) var(--md-sys-space-sm);
27
+ --ui-status-stream-header-surface: var(--md-sys-color-neutral-surface);
28
+ --ui-status-stream-header-border: var(--md-sys-color-neutral-outline-variant);
29
+ --ui-status-stream-header-ink: var(--md-sys-color-neutral-on-surface);
30
+ /* the overall-status ink — the SHAPE (glyph/dot/ring) is the primary ADR-0057 signifier; this is the
31
+ redundant secondary channel, keyed by [data-status] in the styles block below. */
32
+ --ui-status-stream-header-status-ink: var(--md-sys-color-neutral-on-surface-variant);
33
+ }
34
+ :where(ui-status-stream [data-part='header'][data-status='active']) {
35
+ --ui-status-stream-header-status-ink: var(--md-sys-color-primary);
36
+ }
37
+ :where(ui-status-stream [data-part='header'][data-status='done']) {
38
+ --ui-status-stream-header-status-ink: var(--md-sys-color-success);
39
+ }
40
+ :where(ui-status-stream [data-part='header'][data-status='error']) {
41
+ --ui-status-stream-header-status-ink: var(--md-sys-color-danger);
42
+ }
43
+ :where(ui-status-stream [data-part='header'][data-status='warning']) {
44
+ --ui-status-stream-header-status-ink: var(--md-sys-color-warning);
45
+ }
46
+
47
+ /* ════════════════ [2] STYLES BLOCK — @scope (ui-status-stream) consumes ONLY --ui-status-stream-* ════════════════ */
48
+
49
+ @scope (ui-status-stream) {
50
+ :scope {
51
+ display: flex;
52
+ flex-direction: column;
53
+ min-inline-size: var(--ui-status-stream-min-inline-size);
54
+ max-block-size: var(--ui-status-stream-max-block-size);
55
+ overflow-y: auto; /* the stream OWNS its scroll region (SPEC-R10) — the one-owned-scroll-region law */
56
+ overscroll-behavior: contain; /* a nested strip's scroll never chains into the page behind it */
57
+ }
58
+
59
+ /* ── the opt-in streaming header (ADR-0146 F8) — chrome PINNED above the scroll region ── */
60
+ /* `position: sticky; inset-block-start: 0` keeps the header at the scroll viewport's top while entries
61
+ overflow under it — the realization of F8's "chrome outside the scroll region, never scrolls away"
62
+ without restructuring the host's single-scroll-region model (entries stay direct flex children). An
63
+ opaque surface + a bottom hairline keep scrolled entries from bleeding through. */
64
+ :scope > [data-part='header'] {
65
+ position: sticky;
66
+ inset-block-start: 0;
67
+ z-index: 1;
68
+ display: flex;
69
+ align-items: center;
70
+ gap: var(--ui-status-stream-header-gap);
71
+ padding: var(--ui-status-stream-header-pad);
72
+ background: var(--ui-status-stream-header-surface);
73
+ border-block-end: 1px solid var(--ui-status-stream-header-border); /* 1px hairline — the annotated exception */
74
+ color: var(--ui-status-stream-header-ink);
75
+ font-weight: 500;
76
+ }
77
+ :scope > [data-part='header'] [data-part='header-label'] {
78
+ flex: 1 1 auto;
79
+ min-inline-size: 0;
80
+ overflow: hidden;
81
+ text-overflow: ellipsis;
82
+ white-space: nowrap;
83
+ }
84
+
85
+ /* the overall-status marker — mirrors the ui-timeline-item marker's SHAPE law (ADR-0057): done/error/
86
+ warning show their injected glyph (currentColor); '' / active paint a filled dot, pending a hollow
87
+ ring — each a distinct SHAPE, the status ink the redundant secondary channel. */
88
+ :scope > [data-part='header'] [data-part='header-marker'] {
89
+ position: relative;
90
+ flex: 0 0 auto;
91
+ inline-size: var(--ui-status-stream-header-marker-box);
92
+ block-size: var(--ui-status-stream-header-marker-box);
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ color: var(--ui-status-stream-header-status-ink);
97
+ }
98
+ /* the injected done/error/warning glyph — sizes to the marker box, inherits the status ink. */
99
+ :scope > [data-part='header'] [data-part='header-marker'] [data-role='marker'] {
100
+ inline-size: var(--ui-status-stream-header-marker-box);
101
+ block-size: var(--ui-status-stream-header-marker-box);
102
+ }
103
+ /* the dot/ring — painted for the in-progress statuses (no injected glyph present). '' / active = filled
104
+ dot; pending = hollow ring. Suppressed when a glyph is present (done/error/warning). */
105
+ :scope > [data-part='header'] [data-part='header-marker']:not(:has([data-role='marker']))::before {
106
+ content: '';
107
+ position: absolute;
108
+ inline-size: var(--ui-status-stream-header-dot-size);
109
+ block-size: var(--ui-status-stream-header-dot-size);
110
+ border-radius: 50%;
111
+ background: currentColor;
112
+ }
113
+ :scope > [data-part='header'][data-status='pending'] [data-part='header-marker']::before {
114
+ background: transparent;
115
+ border: 1px solid currentColor; /* 1px hairline ring — the annotated exception */
116
+ }
117
+ /* active — a pulse ping (box-shadow, so the dot box never resizes — the centering law); static under
118
+ reduced-motion (ADR-0122 F4 / SPEC-R4 AC3). */
119
+ :scope > [data-part='header'][data-status='active'] [data-part='header-marker']::before {
120
+ animation: ui-status-stream-header-pulse 1.6s ease-out infinite;
121
+ }
122
+ @media (prefers-reduced-motion: reduce) {
123
+ :scope > [data-part='header'][data-status='active'] [data-part='header-marker']::before {
124
+ animation: none;
125
+ }
126
+ }
127
+ @keyframes ui-status-stream-header-pulse {
128
+ 0% {
129
+ box-shadow: 0 0 0 0 currentColor;
130
+ }
131
+ 100% {
132
+ box-shadow: 0 0 0 calc(var(--ui-status-stream-header-dot-size) / 1.5) transparent;
133
+ }
134
+ }
135
+
136
+ /* forced-colors (WHCM) — keep the header legible by SHAPE when fills flatten. The glyph/dot resolve to
137
+ CanvasText; the hairline separators to CanvasText so the chrome stays delineated. */
138
+ @media (forced-colors: active) {
139
+ :scope > [data-part='header'] {
140
+ border-block-end-color: CanvasText;
141
+ color: CanvasText;
142
+ }
143
+ :scope > [data-part='header'] [data-part='header-marker'] {
144
+ color: CanvasText;
145
+ }
146
+ :scope > [data-part='header'] [data-part='header-marker']::before {
147
+ background: CanvasText;
148
+ border-color: CanvasText;
149
+ }
150
+ }
151
+ }
@@ -0,0 +1,108 @@
1
+ import { UIContainerElement, type ReactiveProps } from '../../dom/index.js';
2
+ import { UITimelineItemElement } from '../timeline-item/timeline-item.js';
3
+ import '../timeline/timeline.js';
4
+ /** The closed lifecycle-status vocabulary (ADR-0122 F3 + ADR-0146 F7's `warning`). Mirrors
5
+ * ui-timeline-item's own `status` enum exactly — the entry projects 1:1 onto the item's typed prop. */
6
+ export type ItemStatus = '' | 'pending' | 'active' | 'done' | 'error' | 'warning';
7
+ /** The structured entry a consumer pushes as its stream yields (F4). NOT parsed — a plain record. */
8
+ export interface StatusEntry {
9
+ key: string;
10
+ status?: ItemStatus;
11
+ label?: string;
12
+ description?: string;
13
+ timestamp?: string;
14
+ icon?: string;
15
+ /** Streamed chain-of-thought text — appended/replaced in place, NEVER tokenized/parsed. */
16
+ text?: string;
17
+ /** ADR-0146 F5 — an existing entry's key: when set (and known), this entry NESTS under that group (a
18
+ * nested `<ui-timeline>` in the parent item's `[data-role="nested"]` slot) instead of as a top-level
19
+ * sibling. A routing fact consumed by `appendEntry`, NEVER a timeline-item prop; an unknown parent key
20
+ * degrades to a flat top-level append (never a throw). Set once at append time — `update` does not re-parent. */
21
+ parent?: string;
22
+ }
23
+ /**
24
+ * Worst-child-wins over the closed ADR-0146 F6 ladder — the single reduce both the (future) group header
25
+ * and the stream header use. Monotone-truthful: the result never reads calmer than the worst contributor
26
+ * (a group with one `error` child and one still-`active` child reads `error`, the truth that something
27
+ * already failed outranking "still working"). Neutral '' entries contribute nothing. Pure + exported so
28
+ * it is directly unit-tested (the ladder's `error`-beats-`active` and `done`+`warning`→`warning` cases).
29
+ */
30
+ export declare function escalateStatus(statuses: readonly ItemStatus[]): ItemStatus;
31
+ declare const props: {
32
+ size: {
33
+ reflect: true;
34
+ type: import("../../index.js").PropType<"sm" | "md" | "lg">;
35
+ default: "sm" | "md" | "lg";
36
+ attribute?: string | false;
37
+ };
38
+ label: {
39
+ reflect: true;
40
+ type: import("../../index.js").PropType<string>;
41
+ default: string;
42
+ attribute?: string | false;
43
+ };
44
+ header: {
45
+ reflect: true;
46
+ type: import("../../index.js").PropType<boolean>;
47
+ default: boolean;
48
+ attribute?: string | false;
49
+ };
50
+ };
51
+ export interface UIStatusStreamElement extends ReactiveProps<typeof props> {
52
+ }
53
+ export declare class UIStatusStreamElement extends UIContainerElement {
54
+ #private;
55
+ static props: {
56
+ size: {
57
+ reflect: true;
58
+ type: import("../../index.js").PropType<"sm" | "md" | "lg">;
59
+ default: "sm" | "md" | "lg";
60
+ attribute?: string | false;
61
+ };
62
+ label: {
63
+ reflect: true;
64
+ type: import("../../index.js").PropType<string>;
65
+ default: string;
66
+ attribute?: string | false;
67
+ };
68
+ header: {
69
+ reflect: true;
70
+ type: import("../../index.js").PropType<boolean>;
71
+ default: boolean;
72
+ attribute?: string | false;
73
+ };
74
+ };
75
+ constructor();
76
+ protected connected(): void;
77
+ /** Append a new entry, tail-follow to it, return the created item (the toast-region.show() return
78
+ * precedent). Named `appendEntry`, NOT `append` — the native Node.prototype.append() every element
79
+ * inherits is incompatible; see the file-header NAMED LLD DEVIATION note. ADR-0146 F5: an entry carrying
80
+ * a KNOWN `parent` nests under that group's `[data-role="nested"]` slot instead of as a flat sibling.
81
+ *
82
+ * Duplicate-key guard (issue #37): a key already in `#byKey` is REJECTED — returns the EXISTING item
83
+ * untouched, never creating a second element. This is the same "graceful, never throw, no-op the
84
+ * invalid case" posture the rest of this file already applies to creation-adjacent edge cases (an
85
+ * unknown `parent` degrades to a flat append rather than throwing; a self-referencing `parent` does the
86
+ * same) — appendEntry's contract is to CREATE, so a key collision is the invalid case here, symmetric
87
+ * with update()'s own no-op on an UNKNOWN key. The alternative (tear down the old item and re-key it)
88
+ * was rejected: the old item may itself be a GROUP PARENT with live nested children (#childrenOf/
89
+ * #nestedByParent), and re-parenting those children's DOM + registry links onto a freshly-created
90
+ * replacement item is a second, much larger surgery this fix does not need — silently keeping the
91
+ * first-registered item is sufficient to close the acceptance criteria (never two live elements for one
92
+ * key) without inventing a re-parent path the design never specified. A consumer that truly needs to
93
+ * replace an entry's fields still can, via `update(key, patch)` on the SAME key. */
94
+ appendEntry(entry: StatusEntry): UITimelineItemElement;
95
+ /** Keyed, in-place mutation — transition status / grow text / reveal detail. No-op if the key is unknown.
96
+ * Reaches a NESTED entry identically (the flat registry), and a status transition re-escalates its
97
+ * enclosing group chain + the header (ADR-0146 F6, mediated — every child status change flows through here). */
98
+ update(key: string, patch: Partial<StatusEntry>): void;
99
+ /** The completion invariant — mark every still-pending/active entry TRUNCATED (SPEC-R11), then settle the
100
+ * header to the escalated FINAL status (ADR-0146 F8). */
101
+ finalize(): void;
102
+ /** A failed stream (ADR-0146 F8): the completion invariant PLUS a header forced to `error` — the
103
+ * completion invariant now has a header-level face. Marks still-pending/active entries truncated exactly
104
+ * as `finalize()` does (a failed turn is also torn), then paints the header `error` regardless of the
105
+ * entries' own escalation. */
106
+ fail(): void;
107
+ }
108
+ export {};