@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.
- package/dist/base-styles.css +8 -0
- package/dist/component-styles.css +147 -0
- package/dist/controls/_base/index.d.ts +3 -0
- package/dist/controls/_base/index.js +9 -0
- package/dist/controls/_base/indicator-element.d.ts +132 -0
- package/dist/controls/_base/indicator-element.js +158 -0
- package/dist/controls/_base/listbox-element.d.ts +70 -0
- package/dist/controls/_base/listbox-element.js +74 -0
- package/dist/controls/_base/range-element.d.ts +120 -0
- package/dist/controls/_base/range-element.js +158 -0
- package/dist/controls/_surface/container-box.css +301 -0
- package/dist/controls/_surface/container.css +156 -0
- package/dist/controls/_token-surface/token-surface.d.ts +35 -0
- package/dist/controls/_token-surface/token-surface.js +97 -0
- package/dist/controls/attachment/attachment-meta.d.ts +8 -0
- package/dist/controls/attachment/attachment-meta.js +84 -0
- package/dist/controls/attachment/attachment.css +91 -0
- package/dist/controls/attachment/attachment.d.ts +40 -0
- package/dist/controls/attachment/attachment.js +70 -0
- package/dist/controls/avatar/avatar-initials.d.ts +4 -0
- package/dist/controls/avatar/avatar-initials.js +30 -0
- package/dist/controls/avatar/avatar.css +87 -0
- package/dist/controls/avatar/avatar.d.ts +40 -0
- package/dist/controls/avatar/avatar.js +77 -0
- package/dist/controls/badge/badge.css +175 -0
- package/dist/controls/badge/badge.d.ts +36 -0
- package/dist/controls/badge/badge.js +71 -0
- package/dist/controls/bar-chart/bar-chart.css +110 -0
- package/dist/controls/bar-chart/bar-chart.d.ts +26 -0
- package/dist/controls/bar-chart/bar-chart.js +80 -0
- package/dist/controls/bar-chart/bar-math.d.ts +31 -0
- package/dist/controls/bar-chart/bar-math.js +106 -0
- package/dist/controls/button/button.css +263 -0
- package/dist/controls/button/button.d.ts +61 -0
- package/dist/controls/button/button.js +115 -0
- package/dist/controls/calendar/calendar.css +495 -0
- package/dist/controls/calendar/calendar.d.ts +161 -0
- package/dist/controls/calendar/calendar.js +1004 -0
- package/dist/controls/card/card-content.d.ts +24 -0
- package/dist/controls/card/card-content.js +133 -0
- package/dist/controls/card/card-footer.d.ts +3 -0
- package/dist/controls/card/card-footer.js +16 -0
- package/dist/controls/card/card-header.d.ts +3 -0
- package/dist/controls/card/card-header.js +18 -0
- package/dist/controls/card/card.css +445 -0
- package/dist/controls/card/card.d.ts +51 -0
- package/dist/controls/card/card.js +61 -0
- package/dist/controls/checkbox/checkbox.css +204 -0
- package/dist/controls/checkbox/checkbox.d.ts +114 -0
- package/dist/controls/checkbox/checkbox.js +130 -0
- package/dist/controls/code/code.css +72 -0
- package/dist/controls/code/code.d.ts +23 -0
- package/dist/controls/code/code.js +40 -0
- package/dist/controls/color-picker/color-picker.css +209 -0
- package/dist/controls/color-picker/color-picker.d.ts +84 -0
- package/dist/controls/color-picker/color-picker.js +545 -0
- package/dist/controls/color-picker/color.d.ts +40 -0
- package/dist/controls/color-picker/color.js +159 -0
- package/dist/controls/column/column.css +151 -0
- package/dist/controls/column/column.d.ts +107 -0
- package/dist/controls/column/column.js +57 -0
- package/dist/controls/combo-box/combo-box.css +397 -0
- package/dist/controls/combo-box/combo-box.d.ts +133 -0
- package/dist/controls/combo-box/combo-box.js +680 -0
- package/dist/controls/command-modal/command-modal.css +226 -0
- package/dist/controls/command-modal/command-modal.d.ts +42 -0
- package/dist/controls/command-modal/command-modal.js +315 -0
- package/dist/controls/disclosure/disclosure.css +162 -0
- package/dist/controls/disclosure/disclosure.d.ts +37 -0
- package/dist/controls/disclosure/disclosure.js +207 -0
- package/dist/controls/field/field.css +140 -0
- package/dist/controls/field/field.d.ts +27 -0
- package/dist/controls/field/field.js +228 -0
- package/dist/controls/form-provider/form-provider.css +40 -0
- package/dist/controls/form-provider/form-provider.d.ts +42 -0
- package/dist/controls/form-provider/form-provider.js +105 -0
- package/dist/controls/grid/grid.css +72 -0
- package/dist/controls/grid/grid.d.ts +60 -0
- package/dist/controls/grid/grid.js +56 -0
- package/dist/controls/icon/icon.css +37 -0
- package/dist/controls/icon/icon.d.ts +25 -0
- package/dist/controls/icon/icon.js +55 -0
- package/dist/controls/index.d.ts +57 -0
- package/dist/controls/index.js +136 -0
- package/dist/controls/ladder/ladder.css +89 -0
- package/dist/controls/ladder/ladder.d.ts +27 -0
- package/dist/controls/ladder/ladder.js +78 -0
- package/dist/controls/list/list.css +118 -0
- package/dist/controls/list/list.d.ts +84 -0
- package/dist/controls/list/list.js +48 -0
- package/dist/controls/menu/menu.css +195 -0
- package/dist/controls/menu/menu.d.ts +44 -0
- package/dist/controls/menu/menu.js +248 -0
- package/dist/controls/modal/modal.css +99 -0
- package/dist/controls/modal/modal.d.ts +61 -0
- package/dist/controls/modal/modal.js +155 -0
- package/dist/controls/popover/popover.css +83 -0
- package/dist/controls/popover/popover.d.ts +44 -0
- package/dist/controls/popover/popover.js +164 -0
- package/dist/controls/progress/progress.css +106 -0
- package/dist/controls/progress/progress.d.ts +28 -0
- package/dist/controls/progress/progress.js +80 -0
- package/dist/controls/radio/radio-group.css +84 -0
- package/dist/controls/radio/radio-group.d.ts +152 -0
- package/dist/controls/radio/radio-group.js +350 -0
- package/dist/controls/radio/radio.css +219 -0
- package/dist/controls/radio/radio.d.ts +19 -0
- package/dist/controls/radio/radio.js +75 -0
- package/dist/controls/ramp/ramp.css +75 -0
- package/dist/controls/ramp/ramp.d.ts +29 -0
- package/dist/controls/ramp/ramp.js +72 -0
- package/dist/controls/row/row.css +152 -0
- package/dist/controls/row/row.d.ts +95 -0
- package/dist/controls/row/row.js +45 -0
- package/dist/controls/segment/segment.css +66 -0
- package/dist/controls/segment/segment.d.ts +3 -0
- package/dist/controls/segment/segment.js +26 -0
- package/dist/controls/segmented-control/segmented-control.css +189 -0
- package/dist/controls/segmented-control/segmented-control.d.ts +20 -0
- package/dist/controls/segmented-control/segmented-control.js +64 -0
- package/dist/controls/select/select.css +467 -0
- package/dist/controls/select/select.d.ts +147 -0
- package/dist/controls/select/select.js +538 -0
- package/dist/controls/slider/slider.css +231 -0
- package/dist/controls/slider/slider.d.ts +111 -0
- package/dist/controls/slider/slider.js +60 -0
- package/dist/controls/slider-multi/slider-multi.css +197 -0
- package/dist/controls/slider-multi/slider-multi.d.ts +149 -0
- package/dist/controls/slider-multi/slider-multi.js +380 -0
- package/dist/controls/sparkline/sparkline-math.d.ts +23 -0
- package/dist/controls/sparkline/sparkline-math.js +79 -0
- package/dist/controls/sparkline/sparkline.css +61 -0
- package/dist/controls/sparkline/sparkline.d.ts +27 -0
- package/dist/controls/sparkline/sparkline.js +74 -0
- package/dist/controls/split/constrain.d.ts +44 -0
- package/dist/controls/split/constrain.js +126 -0
- package/dist/controls/split/split-pane.css +63 -0
- package/dist/controls/split/split-pane.d.ts +49 -0
- package/dist/controls/split/split-pane.js +42 -0
- package/dist/controls/split/split.css +127 -0
- package/dist/controls/split/split.d.ts +42 -0
- package/dist/controls/split/split.js +364 -0
- package/dist/controls/stat/stat-model.d.ts +22 -0
- package/dist/controls/stat/stat-model.js +69 -0
- package/dist/controls/stat/stat.css +101 -0
- package/dist/controls/stat/stat.d.ts +30 -0
- package/dist/controls/stat/stat.js +73 -0
- package/dist/controls/status-stream/status-stream.css +151 -0
- package/dist/controls/status-stream/status-stream.d.ts +108 -0
- package/dist/controls/status-stream/status-stream.js +417 -0
- package/dist/controls/swatch/swatch.css +66 -0
- package/dist/controls/swatch/swatch.d.ts +28 -0
- package/dist/controls/swatch/swatch.js +74 -0
- package/dist/controls/swiper/swiper-item.css +17 -0
- package/dist/controls/swiper/swiper-item.d.ts +31 -0
- package/dist/controls/swiper/swiper-item.js +47 -0
- package/dist/controls/swiper/swiper-label.css +10 -0
- package/dist/controls/swiper/swiper-label.d.ts +4 -0
- package/dist/controls/swiper/swiper-label.js +20 -0
- package/dist/controls/swiper/swiper-paddles.css +26 -0
- package/dist/controls/swiper/swiper-paddles.d.ts +10 -0
- package/dist/controls/swiper/swiper-paddles.js +62 -0
- package/dist/controls/swiper/swiper-pagination.css +60 -0
- package/dist/controls/swiper/swiper-pagination.d.ts +31 -0
- package/dist/controls/swiper/swiper-pagination.js +78 -0
- package/dist/controls/swiper/swiper.css +153 -0
- package/dist/controls/swiper/swiper.d.ts +158 -0
- package/dist/controls/swiper/swiper.js +659 -0
- package/dist/controls/switch/switch.css +194 -0
- package/dist/controls/switch/switch.d.ts +5 -0
- package/dist/controls/switch/switch.js +18 -0
- package/dist/controls/table/table-model.d.ts +43 -0
- package/dist/controls/table/table-model.js +124 -0
- package/dist/controls/table/table.css +90 -0
- package/dist/controls/table/table.d.ts +29 -0
- package/dist/controls/table/table.js +178 -0
- package/dist/controls/tabs/tab-panel.d.ts +10 -0
- package/dist/controls/tabs/tab-panel.js +89 -0
- package/dist/controls/tabs/tab.d.ts +26 -0
- package/dist/controls/tabs/tab.js +67 -0
- package/dist/controls/tabs/tabs.css +181 -0
- package/dist/controls/tabs/tabs.d.ts +61 -0
- package/dist/controls/tabs/tabs.js +176 -0
- package/dist/controls/text/href.d.ts +26 -0
- package/dist/controls/text/href.js +48 -0
- package/dist/controls/text/text.css +328 -0
- package/dist/controls/text/text.d.ts +85 -0
- package/dist/controls/text/text.js +273 -0
- package/dist/controls/text-field/text-field.css +498 -0
- package/dist/controls/text-field/text-field.d.ts +226 -0
- package/dist/controls/text-field/text-field.js +905 -0
- package/dist/controls/textarea/textarea.css +251 -0
- package/dist/controls/textarea/textarea.d.ts +136 -0
- package/dist/controls/textarea/textarea.js +312 -0
- package/dist/controls/theme-provider/theme-provider.css +48 -0
- package/dist/controls/theme-provider/theme-provider.d.ts +59 -0
- package/dist/controls/theme-provider/theme-provider.js +40 -0
- package/dist/controls/timeline/timeline.css +33 -0
- package/dist/controls/timeline/timeline.d.ts +39 -0
- package/dist/controls/timeline/timeline.js +52 -0
- package/dist/controls/timeline-item/timeline-item.css +495 -0
- package/dist/controls/timeline-item/timeline-item.d.ts +79 -0
- package/dist/controls/timeline-item/timeline-item.js +360 -0
- package/dist/controls/toast/toast-region.css +56 -0
- package/dist/controls/toast/toast-region.d.ts +20 -0
- package/dist/controls/toast/toast-region.js +113 -0
- package/dist/controls/toast/toast.css +96 -0
- package/dist/controls/toast/toast.d.ts +28 -0
- package/dist/controls/toast/toast.js +191 -0
- package/dist/controls/toolbar/toolbar.css +125 -0
- package/dist/controls/toolbar/toolbar.d.ts +108 -0
- package/dist/controls/toolbar/toolbar.js +68 -0
- package/dist/controls/tooltip/tooltip.css +80 -0
- package/dist/controls/tooltip/tooltip.d.ts +57 -0
- package/dist/controls/tooltip/tooltip.js +205 -0
- package/dist/descriptor/component-descriptor.d.ts +112 -0
- package/dist/descriptor/component-descriptor.js +492 -0
- package/dist/descriptor/index.d.ts +1 -0
- package/dist/descriptor/index.js +5 -0
- package/dist/dom/container.d.ts +45 -0
- package/dist/dom/container.js +60 -0
- package/dist/dom/element.d.ts +98 -0
- package/dist/dom/element.js +221 -0
- package/dist/dom/form.d.ts +240 -0
- package/dist/dom/form.js +399 -0
- package/dist/dom/index.d.ts +10 -0
- package/dist/dom/index.js +31 -0
- package/dist/dom/props.d.ts +56 -0
- package/dist/dom/props.js +231 -0
- package/dist/dom/repeat.d.ts +10 -0
- package/dist/dom/repeat.js +202 -0
- package/dist/dom/template.d.ts +161 -0
- package/dist/dom/template.js +634 -0
- package/dist/dom/watch.d.ts +11 -0
- package/dist/dom/watch.js +82 -0
- package/dist/foundation-styles.css +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/reactive/graph.d.ts +65 -0
- package/dist/reactive/graph.js +310 -0
- package/dist/reactive/index.d.ts +3 -0
- package/dist/reactive/index.js +4 -0
- package/dist/reactive/scheduler.d.ts +13 -0
- package/dist/reactive/scheduler.js +49 -0
- package/dist/traits/area-drag.d.ts +12 -0
- package/dist/traits/area-drag.js +70 -0
- package/dist/traits/form-registry.d.ts +36 -0
- package/dist/traits/form-registry.js +108 -0
- package/dist/traits/index.d.ts +24 -0
- package/dist/traits/index.js +19 -0
- package/dist/traits/overlay.d.ts +50 -0
- package/dist/traits/overlay.js +277 -0
- package/dist/traits/pane-resize.d.ts +26 -0
- package/dist/traits/pane-resize.js +103 -0
- package/dist/traits/press-activation.d.ts +11 -0
- package/dist/traits/press-activation.js +55 -0
- package/dist/traits/roving-focus.d.ts +52 -0
- package/dist/traits/roving-focus.js +214 -0
- package/dist/traits/scroll-fade.d.ts +28 -0
- package/dist/traits/scroll-fade.js +120 -0
- package/dist/traits/selection-commit.d.ts +30 -0
- package/dist/traits/selection-commit.js +146 -0
- package/dist/traits/tabbable.d.ts +12 -0
- package/dist/traits/tabbable.js +59 -0
- package/dist/traits/track-user-invalid.d.ts +36 -0
- package/dist/traits/track-user-invalid.js +52 -0
- package/dist/traits/value-codec.d.ts +120 -0
- package/dist/traits/value-codec.js +497 -0
- package/dist/traits/value-drag.d.ts +18 -0
- package/dist/traits/value-drag.js +84 -0
- package/package.json +263 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* base-styles.css — the DOCUMENT BASE barrel (the foundation-styles.css pattern): the foundational theme
|
|
2
|
+
* any host page loads to get the document basics — typeface (--md-sys-typeface-sans), body leading, ambient
|
|
3
|
+
* surface/ink, font rendering — from @agent-ui-kit/shared's base.css. Load AFTER foundation-styles.css (base
|
|
4
|
+
* consumes the roles/constants foundation declares) and BEFORE page-local sheets. A page composing the
|
|
5
|
+
* docs shell does NOT need this (the shell's _page.css sets its own document rule); a SHELL-LESS page
|
|
6
|
+
* (agent-admin-app.html is the shape) does, or it renders in the UA serif.
|
|
7
|
+
*/
|
|
8
|
+
@import '@agent-ui-kit/shared/base.css';
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/* component-styles.css — the per-component stylesheet barrel (ADR-0003). Aggregates every FACE control's
|
|
2
|
+
* single `{name}.css` (each = a `:where(ui-{name})` token block + an `@scope (ui-{name})` styles block).
|
|
3
|
+
* A host page links this AFTER foundation-styles.css so the foundation (the `--md-sys-color-*` colour roles + the
|
|
4
|
+
* `--ui-{height,font,gap,space}-*` ramp + `--md-sys-shape-corner-base`) is already declared when a control's `:where()`
|
|
5
|
+
* block reads it. Exposed as the package `./component-styles.css` export. Pure CSS — NEVER injected from a
|
|
6
|
+
* control's `.ts` (behaviour-only `.ts`, no runtime style injection — plan §2). Grows one `@import` per control.
|
|
7
|
+
*
|
|
8
|
+
* DO NOT REORDER — the imports are append-only in control-addition order. Each control's sheet is fully
|
|
9
|
+
* self-scoped (a `:where(ui-{name})` token block + an `@scope (ui-{name})` styles block), so the controls do
|
|
10
|
+
* not interact across the cascade; the stable order keeps any future shared/global rule deterministic. New
|
|
11
|
+
* controls APPEND after the last import.
|
|
12
|
+
*
|
|
13
|
+
* THE ONE SHARED SEAM (decomp s12): `_surface/container.css` is NOT a control sheet — it is the cross-family
|
|
14
|
+
* surface mapping (the `--ui-container-bg`/`-tint` consumption seam, ADR-0015) that the whole G9
|
|
15
|
+
* container/layout family sits on. It is imported FIRST, before any element sheet, so its `:where()` surface
|
|
16
|
+
* tokens are declared when a container element's own `@scope` block consumes them. It does NOT establish
|
|
17
|
+
* `container-type` on any element (ADR-0100 deleted that blanket rule — a layout primitive is never a size
|
|
18
|
+
* query container by default; establishment now belongs to externally-sized composition boundaries, e.g. an
|
|
19
|
+
* A2UI mount surface or app-shell). The container element sheets follow it in a stable, annotated order (also
|
|
20
|
+
* do-not-reorder).
|
|
21
|
+
*/
|
|
22
|
+
@import './controls/_surface/container.css';
|
|
23
|
+
/* The shared container BOX-MODEL (margin inset + sticky-region pattern) — a surface opts in with [data-box].
|
|
24
|
+
* After the surface PAINT layer above, before any element sheet (so an element's @scope can override it). */
|
|
25
|
+
@import './controls/_surface/container-box.css';
|
|
26
|
+
|
|
27
|
+
/* form controls (G5/G6) */
|
|
28
|
+
@import './controls/button/button.css';
|
|
29
|
+
@import './controls/text-field/text-field.css';
|
|
30
|
+
|
|
31
|
+
/* display controls (ADR-0025) */
|
|
32
|
+
@import './controls/text/text.css';
|
|
33
|
+
|
|
34
|
+
/* the icon adapter's declarative consumer (ADR-0065/0066) */
|
|
35
|
+
@import './controls/icon/icon.css';
|
|
36
|
+
|
|
37
|
+
/* Indicator controls — Wave 1 (ADR-0041/0042: widget-box geometry + UIIndicatorElement base) */
|
|
38
|
+
@import './controls/checkbox/checkbox.css';
|
|
39
|
+
@import './controls/switch/switch.css';
|
|
40
|
+
@import './controls/radio/radio.css';
|
|
41
|
+
@import './controls/radio/radio-group.css';
|
|
42
|
+
|
|
43
|
+
/* Range controls — Wave 2 (ADR-0042 Range half): single + dual-thumb slider. */
|
|
44
|
+
@import './controls/slider/slider.css';
|
|
45
|
+
@import './controls/slider-multi/slider-multi.css';
|
|
46
|
+
|
|
47
|
+
/* Pattern controls — ADR-0095 (supersedes ADR-0086's ui-radio-group[variant='segmented'], hard cutover):
|
|
48
|
+
* the standalone segmented control. segment.css FIRST (the leaf, no dot to suppress — its own base layout +
|
|
49
|
+
* focus ring), segmented-control.css SECOND (the host's compound selectors consume ui-segment by tag). */
|
|
50
|
+
@import './controls/segment/segment.css';
|
|
51
|
+
@import './controls/segmented-control/segmented-control.css';
|
|
52
|
+
|
|
53
|
+
/* G9 container / layout family — each sheet consumes the shared `_surface/container.css` seam above. */
|
|
54
|
+
@import './controls/row/row.css';
|
|
55
|
+
@import './controls/column/column.css';
|
|
56
|
+
@import './controls/list/list.css';
|
|
57
|
+
@import './controls/grid/grid.css';
|
|
58
|
+
@import './controls/card/card.css';
|
|
59
|
+
@import './controls/tabs/tabs.css';
|
|
60
|
+
@import './controls/modal/modal.css';
|
|
61
|
+
|
|
62
|
+
/* Overlay controls — Wave 4 (ADR-0043): each is self-scoped (a `:where(ui-{name})` token block + an
|
|
63
|
+
* `@scope (ui-{name})` styles block); the popup panels are Container/surface, the triggers Control-class. */
|
|
64
|
+
@import './controls/popover/popover.css';
|
|
65
|
+
@import './controls/tooltip/tooltip.css';
|
|
66
|
+
@import './controls/menu/menu.css';
|
|
67
|
+
@import './controls/select/select.css';
|
|
68
|
+
@import './controls/combo-box/combo-box.css';
|
|
69
|
+
|
|
70
|
+
/* Picker controls — Wave 5B (ADR-0048): standalone month-grid date picker. */
|
|
71
|
+
@import './controls/calendar/calendar.css';
|
|
72
|
+
|
|
73
|
+
/* Coordination controls — G7 (ADR-0050/ADR-0051): the label/description/error wrapper + the aggregation
|
|
74
|
+
* provider. form-provider.css declares no --ui-form-provider-* tokens (LLD-C8 — pure coordination, no paint). */
|
|
75
|
+
@import './controls/field/field.css';
|
|
76
|
+
@import './controls/form-provider/form-provider.css';
|
|
77
|
+
|
|
78
|
+
/* Coordination/carrier controls — ADR-0117: the fleet's second pure UIElement coordination primitive.
|
|
79
|
+
* theme-provider.css declares no --ui-theme-provider-* tokens (SPEC-R6 — pure coordination, no paint). */
|
|
80
|
+
@import './controls/theme-provider/theme-provider.css';
|
|
81
|
+
|
|
82
|
+
/* Chart family — Wave M1 (ADR-0107, chart-family.lld.md LLD-C8): Display-class, axis-free chart marks. */
|
|
83
|
+
@import './controls/sparkline/sparkline.css';
|
|
84
|
+
@import './controls/bar-chart/bar-chart.css';
|
|
85
|
+
|
|
86
|
+
/* Report family — Wave M1 (ADR-0111, report-family.lld.md LLD-C10): the native table, the metric tile,
|
|
87
|
+
* and the compact-realm intent badge. All Display-class, non-interactive, non-form-associated leaves. */
|
|
88
|
+
@import './controls/table/table.css';
|
|
89
|
+
@import './controls/stat/stat.css';
|
|
90
|
+
@import './controls/badge/badge.css';
|
|
91
|
+
|
|
92
|
+
/* Content family — Wave M1 (ADR-0113, content-family.lld.md LLD-C11): the zero-machinery code leaf and
|
|
93
|
+
* the native details/summary disclosure. (The ui-text hyperlink extension lives in text/text.css, above.) */
|
|
94
|
+
@import './controls/code/code.css';
|
|
95
|
+
@import './controls/disclosure/disclosure.css';
|
|
96
|
+
|
|
97
|
+
/* ADR-0124 — the ui-swiper family: a CSS-native scroll-snap carousel (swiper-family.lld.md). Five files —
|
|
98
|
+
* swiper.css is the PRIMARY sheet (declares the family --ui-swiper-* token table + the host's own anatomy)
|
|
99
|
+
* and MUST load before the four leaf sheets, which consume that prefix (the family-root rule, ADR-0124
|
|
100
|
+
* Consequences). */
|
|
101
|
+
@import './controls/swiper/swiper.css';
|
|
102
|
+
@import './controls/swiper/swiper-item.css';
|
|
103
|
+
@import './controls/swiper/swiper-pagination.css';
|
|
104
|
+
@import './controls/swiper/swiper-paddles.css';
|
|
105
|
+
@import './controls/swiper/swiper-label.css';
|
|
106
|
+
|
|
107
|
+
/* Token-surface family — M1 (ADR-0118, token-surfaces.lld.md LLD-C9): show-never-edit color/dimension
|
|
108
|
+
* primitives (swatch/ramp/ladder). All Display-class, non-interactive, non-form-associated leaves. */
|
|
109
|
+
@import './controls/swatch/swatch.css';
|
|
110
|
+
@import './controls/ramp/ramp.css';
|
|
111
|
+
@import './controls/ladder/ladder.css';
|
|
112
|
+
|
|
113
|
+
/* Feed family — Wave M1 (ADR-0112, feed-family.lld.md LLD-C11): agent-activity primitives — the thin-rail
|
|
114
|
+
* progress bar, the compact identity mark, the FilePart-aligned file card, and the toast pair (a fixed
|
|
115
|
+
* notification card + its top-layer stacking host). */
|
|
116
|
+
@import './controls/progress/progress.css';
|
|
117
|
+
@import './controls/avatar/avatar.css';
|
|
118
|
+
@import './controls/attachment/attachment.css';
|
|
119
|
+
@import './controls/toast/toast.css';
|
|
120
|
+
@import './controls/toast/toast-region.css';
|
|
121
|
+
|
|
122
|
+
/* M4 Phase 1 — the split primitive (ADR-0120 cl.2, app-surfaces-m4.lld.md LLD-C5): ui-split (the
|
|
123
|
+
* separator/divider geometry) + ui-split-pane (the axis-oblique pane geometry it drives via a JS seam). */
|
|
124
|
+
@import './controls/split/split.css';
|
|
125
|
+
@import './controls/split/split-pane.css';
|
|
126
|
+
|
|
127
|
+
/* ADR-0121 — ui-toolbar, a Pattern-class action bar (host-as-flex + role=toolbar + roving focus, decoupled
|
|
128
|
+
* from selection; posture via the existing elevation/brightness surface axis, no positioning machine). */
|
|
129
|
+
@import './controls/toolbar/toolbar.css';
|
|
130
|
+
|
|
131
|
+
/* ADR-0122 — the timeline family: the shared marker-system rail row (ui-timeline-item), its durable
|
|
132
|
+
* authored-children host (ui-timeline), and its live imperatively-fed sibling (ui-status-stream). */
|
|
133
|
+
@import './controls/timeline-item/timeline-item.css';
|
|
134
|
+
@import './controls/timeline/timeline.css';
|
|
135
|
+
@import './controls/status-stream/status-stream.css';
|
|
136
|
+
|
|
137
|
+
/* ADR-0125 — ui-command-modal, the CMD-K command palette (command-modal.lld.md): nests ui-modal for the
|
|
138
|
+
* surface (already imported above) and paints only its own search/list/status/empty parts. */
|
|
139
|
+
@import './controls/command-modal/command-modal.css';
|
|
140
|
+
|
|
141
|
+
/* ADR-0123 — ui-color-picker, the OKLCH-internal 2-axis color-input control (color-picker.lld.md): the
|
|
142
|
+
* pad + channel-row/readout geometry; composes ui-slider/ui-text-field/ui-swatch (already imported above). */
|
|
143
|
+
@import './controls/color-picker/color-picker.css';
|
|
144
|
+
|
|
145
|
+
/* ADR-0134 — ui-textarea, the multi-line FACE sibling of ui-text-field (a SEPARATE geometry law, not the
|
|
146
|
+
* single-line (scale×size)→§1-row lookup text-field.css uses — see textarea.css's own header). */
|
|
147
|
+
@import './controls/textarea/textarea.css';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// controls/_base/ — the shared control-base sub-layer (analogous to _surface/ for layout primitives).
|
|
2
|
+
// Exports the abstract bases leaf controls extend; NOT re-exported from the top-level controls/index.ts
|
|
3
|
+
// (the ui-* family barrel) — only the leaf controls that extend these classes are the public surface.
|
|
4
|
+
//
|
|
5
|
+
// Import these in leaf control files:
|
|
6
|
+
// import { UIIndicatorElement } from '../_base/index.ts' // (from controls/{name}/)
|
|
7
|
+
export { UIIndicatorElement } from "./indicator-element.js";
|
|
8
|
+
export { UIRangeElement } from "./range-element.js";
|
|
9
|
+
export { UIListboxElement } from "./listbox-element.js";
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { UIFormElement, type ReactiveProps } from '../../dom/index.js';
|
|
2
|
+
import type { FormValue } from '../../dom/index.js';
|
|
3
|
+
declare const indicatorProps: {
|
|
4
|
+
checked: {
|
|
5
|
+
reflect: true;
|
|
6
|
+
type: import("../../index.js").PropType<boolean>;
|
|
7
|
+
default: boolean;
|
|
8
|
+
attribute?: string | false;
|
|
9
|
+
};
|
|
10
|
+
value: {
|
|
11
|
+
reflect: true;
|
|
12
|
+
type: import("../../index.js").PropType<string>;
|
|
13
|
+
default: string;
|
|
14
|
+
attribute?: string | false;
|
|
15
|
+
};
|
|
16
|
+
size: {
|
|
17
|
+
reflect: true;
|
|
18
|
+
type: import("../../index.js").PropType<"sm" | "md" | "lg">;
|
|
19
|
+
default: "sm" | "md" | "lg";
|
|
20
|
+
attribute?: string | false;
|
|
21
|
+
};
|
|
22
|
+
name: {
|
|
23
|
+
reflect: true;
|
|
24
|
+
type: import("../../index.js").PropType<string>;
|
|
25
|
+
default: string;
|
|
26
|
+
attribute?: string | false;
|
|
27
|
+
};
|
|
28
|
+
disabled: {
|
|
29
|
+
reflect: true;
|
|
30
|
+
type: import("../../index.js").PropType<boolean>;
|
|
31
|
+
default: boolean;
|
|
32
|
+
attribute?: string | false;
|
|
33
|
+
};
|
|
34
|
+
required: {
|
|
35
|
+
reflect: true;
|
|
36
|
+
type: import("../../index.js").PropType<boolean>;
|
|
37
|
+
default: boolean;
|
|
38
|
+
attribute?: string | false;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export interface UIIndicatorElement extends ReactiveProps<typeof indicatorProps> {
|
|
42
|
+
}
|
|
43
|
+
export declare class UIIndicatorElement extends UIFormElement {
|
|
44
|
+
#private;
|
|
45
|
+
static props: {
|
|
46
|
+
checked: {
|
|
47
|
+
reflect: true;
|
|
48
|
+
type: import("../../index.js").PropType<boolean>;
|
|
49
|
+
default: boolean;
|
|
50
|
+
attribute?: string | false;
|
|
51
|
+
};
|
|
52
|
+
value: {
|
|
53
|
+
reflect: true;
|
|
54
|
+
type: import("../../index.js").PropType<string>;
|
|
55
|
+
default: string;
|
|
56
|
+
attribute?: string | false;
|
|
57
|
+
};
|
|
58
|
+
size: {
|
|
59
|
+
reflect: true;
|
|
60
|
+
type: import("../../index.js").PropType<"sm" | "md" | "lg">;
|
|
61
|
+
default: "sm" | "md" | "lg";
|
|
62
|
+
attribute?: string | false;
|
|
63
|
+
};
|
|
64
|
+
name: {
|
|
65
|
+
reflect: true;
|
|
66
|
+
type: import("../../index.js").PropType<string>;
|
|
67
|
+
default: string;
|
|
68
|
+
attribute?: string | false;
|
|
69
|
+
};
|
|
70
|
+
disabled: {
|
|
71
|
+
reflect: true;
|
|
72
|
+
type: import("../../index.js").PropType<boolean>;
|
|
73
|
+
default: boolean;
|
|
74
|
+
attribute?: string | false;
|
|
75
|
+
};
|
|
76
|
+
required: {
|
|
77
|
+
reflect: true;
|
|
78
|
+
type: import("../../index.js").PropType<boolean>;
|
|
79
|
+
default: boolean;
|
|
80
|
+
attribute?: string | false;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* LLD-C2: the ARIA role this indicator carries — declared by each leaf subclass (LLD-C2).
|
|
85
|
+
* `'checkbox'` / `'switch'` / `'radio'`; the base sets `internals.role` from it in `connected()`.
|
|
86
|
+
*/
|
|
87
|
+
static role: string;
|
|
88
|
+
/**
|
|
89
|
+
* LLD-C1: platform checkbox semantics — unchecked submits nothing; checked submits `this.value`.
|
|
90
|
+
*/
|
|
91
|
+
protected formValue(): FormValue;
|
|
92
|
+
/**
|
|
93
|
+
* The reset baseline — native `HTMLInputElement.defaultChecked` parity: a PUBLIC, read-only reflection
|
|
94
|
+
* of the checked state this control was upgraded/connected with (see `#defaultChecked` above). Exposed
|
|
95
|
+
* so a coordinating ancestor (`ui-radio-group`) can recompute ITS OWN post-reset state from every
|
|
96
|
+
* child's default WITHOUT depending on `formResetCallback` invocation order between the group and its
|
|
97
|
+
* radios (both are separate `UIFormElement` participants the platform resets independently) — reading
|
|
98
|
+
* this getter is stable regardless of whether the group's or the radio's own reset runs first.
|
|
99
|
+
*/
|
|
100
|
+
get defaultChecked(): boolean;
|
|
101
|
+
protected connected(): void;
|
|
102
|
+
/**
|
|
103
|
+
* LLD-C3: pre-toggle hook — called immediately before `this.checked` is flipped in the click handler.
|
|
104
|
+
* The base is a no-op. `UICheckboxElement` overrides this to clear `indeterminate` (so clicking an
|
|
105
|
+
* indeterminate checkbox clears the indeterminate visual and then toggles checked — platform parity).
|
|
106
|
+
* Switch and radio are binary; they do not override this.
|
|
107
|
+
*/
|
|
108
|
+
protected beforeToggle(): void;
|
|
109
|
+
/**
|
|
110
|
+
* LLD-C5: grouping hook — the radio subclass overrides this to wire roving-focus + exclusive
|
|
111
|
+
* selection within a name-scoped group. Called from `connected()` after all base wiring is in place.
|
|
112
|
+
* Checkbox/switch leave it a no-op.
|
|
113
|
+
*/
|
|
114
|
+
protected grouped(): void;
|
|
115
|
+
/**
|
|
116
|
+
* Form reset → checked ← `defaultChecked` (native `<input type=checkbox/radio>.defaultChecked` parity;
|
|
117
|
+
* the bug-A fix — this was missing entirely, so every Indicator control ignored BOTH reset paths:
|
|
118
|
+
* native `form.reset()` and a form-less provider's direct `formResetCallback()` call). Silent — no
|
|
119
|
+
* `input`/`change` emitted, matching text-field's own `formReset()` (a reset is not a user edit).
|
|
120
|
+
* `indeterminate` (checkbox-only) is untouched here — a reset restores the boolean `checked` value;
|
|
121
|
+
* native `<input type=checkbox>` does not reset `indeterminate` either (it is never form-serialized and
|
|
122
|
+
* carries no default of its own).
|
|
123
|
+
*
|
|
124
|
+
* A `ui-radio` inside a `ui-radio-group`: this restores THIS radio's own visual `checked` correctly, but
|
|
125
|
+
* the GROUP is a SEPARATE `UIFormElement` participant with its OWN `#selectedValue` signal — this reset
|
|
126
|
+
* alone cannot update it (no click/change event fires). `UIRadioGroupElement` carries its own
|
|
127
|
+
* `formReset()` override (radio-group.ts) that recomputes `#selectedValue` from every child's
|
|
128
|
+
* `defaultChecked` getter (above) — stable regardless of which of the two resets the platform runs first.
|
|
129
|
+
*/
|
|
130
|
+
protected formReset(): void;
|
|
131
|
+
}
|
|
132
|
+
export {};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// indicator-element.ts — UIIndicatorElement, the shared base for the Indicator class
|
|
2
|
+
// (ui-checkbox · ui-switch · ui-radio). indicator-element.lld.md.
|
|
3
|
+
//
|
|
4
|
+
// Owns: the boolean form value (LLD-C1), the checked-state machine + ARIA (LLD-C2), the toggle via
|
|
5
|
+
// pressActivation + click (LLD-C3), and the widget-box geometry seam (LLD-C4, CSS in the subclass).
|
|
6
|
+
// The subclass declares `static role` (LLD-C2), the glyph in its `.css` (LLD-C4), and (radio) the
|
|
7
|
+
// group wiring via `grouped()` (LLD-C5).
|
|
8
|
+
//
|
|
9
|
+
// `indeterminate` is deliberately NOT in the base — it is checkbox-specific tri-state (checkbox overrides
|
|
10
|
+
// `beforeToggle()` to clear it and runs its own supplemental effect). Switch and radio are binary; they
|
|
11
|
+
// should not carry an indeterminate property at all.
|
|
12
|
+
//
|
|
13
|
+
// Layer: controls/_base/ — imports dom + traits (inward-only ✓).
|
|
14
|
+
// Inward-only ✓ (controls ← traits ← dom ← reactive).
|
|
15
|
+
import { UIFormElement, prop } from "../../dom/index.js";
|
|
16
|
+
import { tabbable } from "../../traits/tabbable.js";
|
|
17
|
+
import { pressActivation } from "../../traits/press-activation.js";
|
|
18
|
+
const indicatorProps = {
|
|
19
|
+
...UIFormElement.formProps,
|
|
20
|
+
// LLD-C1: the boolean form value; reflected so `[checked]` drives CSS + is observable as an attribute.
|
|
21
|
+
checked: { ...prop.boolean(false), reflect: true },
|
|
22
|
+
// LLD-C1: the submitted string when checked (HTML checkbox semantics, default 'on'); reflected.
|
|
23
|
+
value: { ...prop.string('on'), reflect: true },
|
|
24
|
+
// LLD-C4: the widget-box size axis — selects --md-sys-compact-{size} via [size] in the leaf's CSS (ADR-0041).
|
|
25
|
+
// All Indicator controls share this axis; each leaf's stylesheet rewires the token.
|
|
26
|
+
size: { ...prop.enum(['sm', 'md', 'lg'], 'md'), reflect: true },
|
|
27
|
+
};
|
|
28
|
+
export class UIIndicatorElement extends UIFormElement {
|
|
29
|
+
static props = indicatorProps;
|
|
30
|
+
/**
|
|
31
|
+
* LLD-C2: the ARIA role this indicator carries — declared by each leaf subclass (LLD-C2).
|
|
32
|
+
* `'checkbox'` / `'switch'` / `'radio'`; the base sets `internals.role` from it in `connected()`.
|
|
33
|
+
*/
|
|
34
|
+
static role = '';
|
|
35
|
+
// LLD-C3: suppress the next click when it originated from an Enter keydown.
|
|
36
|
+
// Platform parity: Enter does NOT toggle a checkbox; but pressActivation fires host.click() on Enter,
|
|
37
|
+
// so a keydown guard registered BEFORE pressActivation marks the pending Enter-click for suppression.
|
|
38
|
+
#suppressNextClick = false;
|
|
39
|
+
// The native-parity reset baseline — `defaultChecked` (LLD-C1 extended, the bug-A fix). Captured ONCE
|
|
40
|
+
// at the FIRST connect (guarded — a later reconnect must not re-snapshot an already-toggled value; the
|
|
41
|
+
// text-field `#defaultValue`/`#defaultCaptured` precedent). Reading `this.checked` here is equivalent to
|
|
42
|
+
// reading the `checked` ATTRIBUTE (native `<input type=checkbox>.defaultChecked` parity): `checked`
|
|
43
|
+
// REFLECTS (props.ts's outbound reflect fires synchronously on every property write, including the
|
|
44
|
+
// ADR-0005 property-wins upgrade replay), so `this.hasAttribute('checked') === this.checked` holds at
|
|
45
|
+
// every point `connected()` can observe it — reading the resolved prop is equivalent and avoids
|
|
46
|
+
// re-parsing the attribute string.
|
|
47
|
+
#defaultChecked = false;
|
|
48
|
+
#defaultCaptured = false;
|
|
49
|
+
/**
|
|
50
|
+
* LLD-C1: platform checkbox semantics — unchecked submits nothing; checked submits `this.value`.
|
|
51
|
+
*/
|
|
52
|
+
formValue() {
|
|
53
|
+
return this.checked ? this.value : null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The reset baseline — native `HTMLInputElement.defaultChecked` parity: a PUBLIC, read-only reflection
|
|
57
|
+
* of the checked state this control was upgraded/connected with (see `#defaultChecked` above). Exposed
|
|
58
|
+
* so a coordinating ancestor (`ui-radio-group`) can recompute ITS OWN post-reset state from every
|
|
59
|
+
* child's default WITHOUT depending on `formResetCallback` invocation order between the group and its
|
|
60
|
+
* radios (both are separate `UIFormElement` participants the platform resets independently) — reading
|
|
61
|
+
* this getter is stable regardless of whether the group's or the radio's own reset runs first.
|
|
62
|
+
*/
|
|
63
|
+
get defaultChecked() {
|
|
64
|
+
return this.#defaultChecked;
|
|
65
|
+
}
|
|
66
|
+
connected() {
|
|
67
|
+
// Seed the reset baseline ONCE from the checked state at first connect (see `#defaultChecked` above).
|
|
68
|
+
if (!this.#defaultCaptured) {
|
|
69
|
+
this.#defaultChecked = this.checked;
|
|
70
|
+
this.#defaultCaptured = true;
|
|
71
|
+
}
|
|
72
|
+
const ctor = this.constructor;
|
|
73
|
+
// LLD-C2: set the ARIA role from the subclass's static declaration. Never a host attribute (FACE).
|
|
74
|
+
this.internals.role = ctor.role;
|
|
75
|
+
// LLD-C3: tabbable — tabindex=0 while enabled, removed from the tab order while disabled (ADR-0010).
|
|
76
|
+
tabbable(this, { disabled: () => this.effectiveDisabled() });
|
|
77
|
+
// LLD-C3: Enter suppressor — must register BEFORE pressActivation so this keydown handler runs
|
|
78
|
+
// first. pressActivation fires host.click() on Enter keydown; that synthetic click is suppressed
|
|
79
|
+
// in the click handler below. Disabled-guarded: pressActivation also early-returns while disabled,
|
|
80
|
+
// so a disabled-Enter must not arm the flag (else the next enabled mouse-click would be swallowed).
|
|
81
|
+
this.listen(this, 'keydown', (event) => {
|
|
82
|
+
if (!this.effectiveDisabled() && event.key === 'Enter') {
|
|
83
|
+
this.#suppressNextClick = true;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
// LLD-C3: pressActivation — Space activates on keyup; Enter fires host.click() (suppressed below).
|
|
87
|
+
pressActivation(this, { disabled: () => this.effectiveDisabled() });
|
|
88
|
+
// LLD-C3: click → toggle checked (mouse clicks + Space-activated synthetic clicks; Enter suppressed).
|
|
89
|
+
// `beforeToggle()` is called first so subclasses can hook in pre-toggle side effects (checkbox clears
|
|
90
|
+
// its `indeterminate` here; switch/radio leave it a no-op via the base implementation).
|
|
91
|
+
this.listen(this, 'click', () => {
|
|
92
|
+
if (this.#suppressNextClick) {
|
|
93
|
+
this.#suppressNextClick = false;
|
|
94
|
+
return; // Enter-click: no toggle (platform checkbox parity)
|
|
95
|
+
}
|
|
96
|
+
if (this.effectiveDisabled())
|
|
97
|
+
return;
|
|
98
|
+
this.beforeToggle();
|
|
99
|
+
this.checked = !this.checked;
|
|
100
|
+
this.emit('input');
|
|
101
|
+
this.emit('change');
|
|
102
|
+
});
|
|
103
|
+
// LLD-C2: checked-state effect — reactive on `checked`, publishes:
|
|
104
|
+
// · custom state :state(checked) (CustomStateSet, absent in jsdom)
|
|
105
|
+
// · internals.ariaChecked ("true" / "false") — the jsdom-accessible ARIA proxy.
|
|
106
|
+
// NOTE: `indeterminate` is NOT tracked here — checkbox adds its own supplemental effect (which runs
|
|
107
|
+
// after this one) to override ariaChecked="mixed" and :state(indeterminate) when needed.
|
|
108
|
+
this.effect(() => {
|
|
109
|
+
const checked = this.checked;
|
|
110
|
+
const states = this.internals.states; // CustomStateSet; absent in jsdom (optional-chained below)
|
|
111
|
+
if (checked) {
|
|
112
|
+
states?.add('checked');
|
|
113
|
+
this.internals.ariaChecked = 'true';
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
states?.delete('checked');
|
|
117
|
+
this.internals.ariaChecked = 'false';
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
// LLD-C3: ariaDisabled mirrors effectiveDisabled() — reactive, scope-owned (same form as button.ts).
|
|
121
|
+
this.effect(() => {
|
|
122
|
+
this.internals.ariaDisabled = this.effectiveDisabled() ? 'true' : null;
|
|
123
|
+
});
|
|
124
|
+
// LLD-C5: delegate to the subclass's group wiring (radio overrides; checkbox/switch leave it no-op).
|
|
125
|
+
this.grouped();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* LLD-C3: pre-toggle hook — called immediately before `this.checked` is flipped in the click handler.
|
|
129
|
+
* The base is a no-op. `UICheckboxElement` overrides this to clear `indeterminate` (so clicking an
|
|
130
|
+
* indeterminate checkbox clears the indeterminate visual and then toggles checked — platform parity).
|
|
131
|
+
* Switch and radio are binary; they do not override this.
|
|
132
|
+
*/
|
|
133
|
+
beforeToggle() { }
|
|
134
|
+
/**
|
|
135
|
+
* LLD-C5: grouping hook — the radio subclass overrides this to wire roving-focus + exclusive
|
|
136
|
+
* selection within a name-scoped group. Called from `connected()` after all base wiring is in place.
|
|
137
|
+
* Checkbox/switch leave it a no-op.
|
|
138
|
+
*/
|
|
139
|
+
grouped() { }
|
|
140
|
+
/**
|
|
141
|
+
* Form reset → checked ← `defaultChecked` (native `<input type=checkbox/radio>.defaultChecked` parity;
|
|
142
|
+
* the bug-A fix — this was missing entirely, so every Indicator control ignored BOTH reset paths:
|
|
143
|
+
* native `form.reset()` and a form-less provider's direct `formResetCallback()` call). Silent — no
|
|
144
|
+
* `input`/`change` emitted, matching text-field's own `formReset()` (a reset is not a user edit).
|
|
145
|
+
* `indeterminate` (checkbox-only) is untouched here — a reset restores the boolean `checked` value;
|
|
146
|
+
* native `<input type=checkbox>` does not reset `indeterminate` either (it is never form-serialized and
|
|
147
|
+
* carries no default of its own).
|
|
148
|
+
*
|
|
149
|
+
* A `ui-radio` inside a `ui-radio-group`: this restores THIS radio's own visual `checked` correctly, but
|
|
150
|
+
* the GROUP is a SEPARATE `UIFormElement` participant with its OWN `#selectedValue` signal — this reset
|
|
151
|
+
* alone cannot update it (no click/change event fires). `UIRadioGroupElement` carries its own
|
|
152
|
+
* `formReset()` override (radio-group.ts) that recomputes `#selectedValue` from every child's
|
|
153
|
+
* `defaultChecked` getter (above) — stable regardless of which of the two resets the platform runs first.
|
|
154
|
+
*/
|
|
155
|
+
formReset() {
|
|
156
|
+
this.checked = this.#defaultChecked;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { UIFormElement, type ReactiveProps } from '../../dom/index.js';
|
|
2
|
+
import type { FormValue, ValidityResult } from '../../dom/index.js';
|
|
3
|
+
declare const listboxProps: {
|
|
4
|
+
multiple: {
|
|
5
|
+
reflect: true;
|
|
6
|
+
type: import("../../index.js").PropType<boolean>;
|
|
7
|
+
default: boolean;
|
|
8
|
+
attribute?: string | false;
|
|
9
|
+
};
|
|
10
|
+
name: {
|
|
11
|
+
reflect: true;
|
|
12
|
+
type: import("../../index.js").PropType<string>;
|
|
13
|
+
default: string;
|
|
14
|
+
attribute?: string | false;
|
|
15
|
+
};
|
|
16
|
+
disabled: {
|
|
17
|
+
reflect: true;
|
|
18
|
+
type: import("../../index.js").PropType<boolean>;
|
|
19
|
+
default: boolean;
|
|
20
|
+
attribute?: string | false;
|
|
21
|
+
};
|
|
22
|
+
required: {
|
|
23
|
+
reflect: true;
|
|
24
|
+
type: import("../../index.js").PropType<boolean>;
|
|
25
|
+
default: boolean;
|
|
26
|
+
attribute?: string | false;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export interface UIListboxElement extends ReactiveProps<typeof listboxProps> {
|
|
30
|
+
}
|
|
31
|
+
export declare class UIListboxElement extends UIFormElement {
|
|
32
|
+
#private;
|
|
33
|
+
static props: {
|
|
34
|
+
multiple: {
|
|
35
|
+
reflect: true;
|
|
36
|
+
type: import("../../index.js").PropType<boolean>;
|
|
37
|
+
default: boolean;
|
|
38
|
+
attribute?: string | false;
|
|
39
|
+
};
|
|
40
|
+
name: {
|
|
41
|
+
reflect: true;
|
|
42
|
+
type: import("../../index.js").PropType<string>;
|
|
43
|
+
default: string;
|
|
44
|
+
attribute?: string | false;
|
|
45
|
+
};
|
|
46
|
+
disabled: {
|
|
47
|
+
reflect: true;
|
|
48
|
+
type: import("../../index.js").PropType<boolean>;
|
|
49
|
+
default: boolean;
|
|
50
|
+
attribute?: string | false;
|
|
51
|
+
};
|
|
52
|
+
required: {
|
|
53
|
+
reflect: true;
|
|
54
|
+
type: import("../../index.js").PropType<boolean>;
|
|
55
|
+
default: boolean;
|
|
56
|
+
attribute?: string | false;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* LLD-C3: the selected option's `value` attribute (single mode), or a newline-joined list
|
|
61
|
+
* (multi mode), or `null` when nothing is selected.
|
|
62
|
+
*/
|
|
63
|
+
protected formValue(): FormValue;
|
|
64
|
+
/**
|
|
65
|
+
* LLD-C3: `required` + nothing selected → `{ valid: false, flags: { valueMissing: true } }`.
|
|
66
|
+
*/
|
|
67
|
+
protected formValidity(): ValidityResult;
|
|
68
|
+
protected connected(): void;
|
|
69
|
+
}
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// listbox-element.ts — UIListboxElement, the form-associated listbox base
|
|
2
|
+
// (ui-listbox · ui-select options popup · ui-combo-box options popup). listbox-roving LLD-C3.
|
|
3
|
+
//
|
|
4
|
+
// Owns: `role=listbox` (via internals), the form value (the selected option's `value` string, or
|
|
5
|
+
// a `\n`-joined list for multi), `required` → `valueMissing`, and the wiring of `rovingFocus` +
|
|
6
|
+
// `selectionCommit` over its `[role=option]` children.
|
|
7
|
+
//
|
|
8
|
+
// The options are light-DOM children (`ui-option` or `<li role=option>`); the host carries no role
|
|
9
|
+
// attribute (FACE internals). ui-menu is NOT this class — it is a plain UIElement + rovingFocus
|
|
10
|
+
// (no form value; role=menu; LLD-C4 in listbox-roving.lld.md).
|
|
11
|
+
//
|
|
12
|
+
// Layer: controls/_base/ — imports dom + traits (inward-only ✓).
|
|
13
|
+
// Inward-only ✓ (controls ← traits ← dom ← reactive).
|
|
14
|
+
import { signal } from "../../reactive/index.js";
|
|
15
|
+
import { UIFormElement, prop } from "../../dom/index.js";
|
|
16
|
+
import { rovingFocus } from "../../traits/roving-focus.js";
|
|
17
|
+
import { selectionCommit } from "../../traits/selection-commit.js";
|
|
18
|
+
const listboxProps = {
|
|
19
|
+
...UIFormElement.formProps,
|
|
20
|
+
// multi-select: a Set of selected keys vs. at most one. Reflected so `[multiple]` drives CSS.
|
|
21
|
+
multiple: { ...prop.boolean(false), reflect: true },
|
|
22
|
+
};
|
|
23
|
+
export class UIListboxElement extends UIFormElement {
|
|
24
|
+
static props = listboxProps;
|
|
25
|
+
// LLD-C3: the committed selection, updated by selectionCommit's `onSelect` callback.
|
|
26
|
+
// Single mode: a string key ('' = nothing selected).
|
|
27
|
+
// Multi mode: a ReadonlySet<string> (empty Set = nothing selected).
|
|
28
|
+
// Both empty cases return null from formValue(). The codec is value-agnostic — formValue() /
|
|
29
|
+
// formValidity() handle both union arms uniformly.
|
|
30
|
+
#selection = signal('');
|
|
31
|
+
/**
|
|
32
|
+
* LLD-C3: the selected option's `value` attribute (single mode), or a newline-joined list
|
|
33
|
+
* (multi mode), or `null` when nothing is selected.
|
|
34
|
+
*/
|
|
35
|
+
formValue() {
|
|
36
|
+
const sel = this.#selection.value;
|
|
37
|
+
if (typeof sel === 'string')
|
|
38
|
+
return sel === '' ? null : sel;
|
|
39
|
+
if (sel.size === 0)
|
|
40
|
+
return null;
|
|
41
|
+
return [...sel].join('\n');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* LLD-C3: `required` + nothing selected → `{ valid: false, flags: { valueMissing: true } }`.
|
|
45
|
+
*/
|
|
46
|
+
formValidity() {
|
|
47
|
+
const sel = this.#selection.value;
|
|
48
|
+
const empty = typeof sel === 'string' ? sel === '' : sel.size === 0;
|
|
49
|
+
if (this.required && empty) {
|
|
50
|
+
return { valid: false, flags: { valueMissing: true }, message: 'Please select an option.' };
|
|
51
|
+
}
|
|
52
|
+
return { valid: true };
|
|
53
|
+
}
|
|
54
|
+
connected() {
|
|
55
|
+
// LLD-C3: set ARIA role via internals — never a host attribute (FACE).
|
|
56
|
+
this.internals.role = 'listbox';
|
|
57
|
+
// LLD-C3: live accessor for [role=option] children (re-read per event for dynamic item sets).
|
|
58
|
+
const items = () => [...this.querySelectorAll('[role=option]')];
|
|
59
|
+
// LLD-C3: key extractor — the option's `value` attribute ('' = no key, skipped by selectionCommit).
|
|
60
|
+
const keyOf = (el) => el.getAttribute('value') ?? '';
|
|
61
|
+
// LLD-C3: roving-focus over the option set (vertical orientation, looping, type-ahead on by default).
|
|
62
|
+
rovingFocus(this, { items });
|
|
63
|
+
// LLD-C3: selection-commit — mode from the `multiple` prop at connect time; onSelect updates
|
|
64
|
+
// #selection, which drives formValue() + formValidity() reactively via the UIFormElement effects.
|
|
65
|
+
selectionCommit(this, {
|
|
66
|
+
mode: this.multiple ? 'multi' : 'single',
|
|
67
|
+
items,
|
|
68
|
+
keyOf,
|
|
69
|
+
onSelect: (selection) => {
|
|
70
|
+
this.#selection.value = selection;
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|