@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,106 @@
|
|
|
1
|
+
/* progress.css — ui-progress, the Display-class thin-rail progress bar (LLD-C1, feed-family.lld.md §2;
|
|
2
|
+
* SPEC-R2/R18/R19/R20; ADR-0112 cl.2). Two sectioned blocks:
|
|
3
|
+
*
|
|
4
|
+
* [1] TOKEN BLOCK — `:where(ui-progress)` declares `--ui-progress-*`: a DENSITY-INVARIANT thin rail
|
|
5
|
+
* thickness (the slider-rail precedent verbatim, slider.css:76-79 — a bar is a rail, NOT a
|
|
6
|
+
* `--md-sys-compact-*` widget box) + the whole-shape floor (SPEC-R18 AC1, the slider-dot collapse
|
|
7
|
+
* lesson) + track/fill color roles (track = `--md-sys-color-neutral-track`, the ADR-0059 solid-track
|
|
8
|
+
* role; fill = the primary role).
|
|
9
|
+
* [2] STYLES BLOCK — `@scope (ui-progress)` consumes ONLY `--ui-progress-*`.
|
|
10
|
+
*
|
|
11
|
+
* Display class (SPEC-R20): no [size]/[scale] control-band lookup, no `--md-sys-height-*`, no `h/2` centering
|
|
12
|
+
* law — the rail is a fixed px constant regardless of [density]/[scale] (SPEC-R18 AC3).
|
|
13
|
+
*
|
|
14
|
+
* RTL (SPEC-R2 AC3): the fill's `inset-inline-start` is a LOGICAL property — the determinate fill and the
|
|
15
|
+
* indeterminate sweep both mirror for free under `dir="rtl"`; no dedicated per-direction rule is needed.
|
|
16
|
+
*
|
|
17
|
+
* Motion (SPEC-R2 AC2): indeterminate animates `inset-inline-start` (a translating sweep). Under
|
|
18
|
+
* `prefers-reduced-motion: reduce` the sweep is replaced by a STATIONARY partial fill with a slow
|
|
19
|
+
* opacity pulse — no translation, no scaling — that stays visually distinct from any determinate state.
|
|
20
|
+
* The keyframes live at stylesheet TOP LEVEL (outside `@scope`) — scoped `@keyframes` name resolution is
|
|
21
|
+
* exactly the kind of engine variance the fleet doesn't need (LLD-C1); names are `ui-progress-*`-prefixed.
|
|
22
|
+
*
|
|
23
|
+
* Forced colors (SPEC-R19): a background-drawn fill vanishes under WHCM (the bar-chart lesson,
|
|
24
|
+
* bar-chart.css:101-107) — an explicit `forced-colors` block repoints the fill to `CanvasText` and keeps
|
|
25
|
+
* the track distinguishable (`Canvas` + a `CanvasText` border).
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/* ════════════════ [1] TOKEN BLOCK — :where(ui-progress) declares --ui-progress-* ════════════════ */
|
|
29
|
+
|
|
30
|
+
:where(ui-progress) {
|
|
31
|
+
--ui-progress-track-size: 4px; /* thin rail — density-invariant constant (slider.css:76-79 kin) */
|
|
32
|
+
--ui-progress-min-inline-size: 8em; /* the whole-shape floor (SPEC-R18 AC1; the slider-dot lesson) */
|
|
33
|
+
--ui-progress-track-ink: var(--md-sys-color-neutral-track); /* the ADR-0059 solid-track role */
|
|
34
|
+
--ui-progress-fill-ink: var(--md-sys-color-primary);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* ════════════════ [2] STYLES BLOCK — @scope (ui-progress) consumes ONLY --ui-progress-* ════════════════ */
|
|
38
|
+
|
|
39
|
+
@scope (ui-progress) {
|
|
40
|
+
:scope {
|
|
41
|
+
display: block;
|
|
42
|
+
min-inline-size: var(--ui-progress-min-inline-size);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:scope [data-part='track'] {
|
|
46
|
+
display: block;
|
|
47
|
+
position: relative;
|
|
48
|
+
overflow: hidden;
|
|
49
|
+
block-size: var(--ui-progress-track-size);
|
|
50
|
+
border-radius: calc(var(--ui-progress-track-size) / 2);
|
|
51
|
+
background: var(--ui-progress-track-ink);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
:scope [data-part='fill'] {
|
|
55
|
+
position: absolute;
|
|
56
|
+
inset-block: 0;
|
|
57
|
+
inset-inline-start: 0;
|
|
58
|
+
inline-size: calc(var(--_pct, 0) * 1%);
|
|
59
|
+
background: var(--ui-progress-fill-ink);
|
|
60
|
+
border-radius: inherit;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:scope [data-part='fill'][data-indeterminate] {
|
|
64
|
+
/* the sweep (SPEC-R2 AC2) — a partial-width fill translating along the track */
|
|
65
|
+
inline-size: 40%;
|
|
66
|
+
animation: ui-progress-sweep 1.5s linear infinite;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@media (prefers-reduced-motion: reduce) {
|
|
70
|
+
:scope [data-part='fill'][data-indeterminate] {
|
|
71
|
+
/* stationary; opacity-only — no translation, no scaling (SPEC-R2 AC2) */
|
|
72
|
+
inset-inline-start: 30%;
|
|
73
|
+
animation: ui-progress-pulse 2s ease-in-out infinite;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@media (forced-colors: active) {
|
|
78
|
+
/* the bar-chart lesson (SPEC-R19) — a background-drawn fill otherwise vanishes */
|
|
79
|
+
:scope [data-part='fill'] {
|
|
80
|
+
background: CanvasText;
|
|
81
|
+
}
|
|
82
|
+
:scope [data-part='track'] {
|
|
83
|
+
background: Canvas;
|
|
84
|
+
border: 1px solid CanvasText;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@keyframes ui-progress-sweep {
|
|
90
|
+
from {
|
|
91
|
+
inset-inline-start: -40%;
|
|
92
|
+
}
|
|
93
|
+
to {
|
|
94
|
+
inset-inline-start: 100%;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@keyframes ui-progress-pulse {
|
|
99
|
+
0%,
|
|
100
|
+
100% {
|
|
101
|
+
opacity: 0.35;
|
|
102
|
+
}
|
|
103
|
+
50% {
|
|
104
|
+
opacity: 1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { UIElement, type ReactiveProps } from '../../dom/index.js';
|
|
2
|
+
declare const props: {
|
|
3
|
+
current: import("../../index.js").PropConfig<number | null>;
|
|
4
|
+
max: import("../../index.js").PropConfig<number | null>;
|
|
5
|
+
label: {
|
|
6
|
+
reflect: true;
|
|
7
|
+
type: import("../../index.js").PropType<string>;
|
|
8
|
+
default: string;
|
|
9
|
+
attribute?: string | false;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export interface UIProgressElement extends ReactiveProps<typeof props> {
|
|
13
|
+
}
|
|
14
|
+
export declare class UIProgressElement extends UIElement {
|
|
15
|
+
#private;
|
|
16
|
+
static props: {
|
|
17
|
+
current: import("../../index.js").PropConfig<number | null>;
|
|
18
|
+
max: import("../../index.js").PropConfig<number | null>;
|
|
19
|
+
label: {
|
|
20
|
+
reflect: true;
|
|
21
|
+
type: import("../../index.js").PropType<string>;
|
|
22
|
+
default: string;
|
|
23
|
+
attribute?: string | false;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
protected connected(): void;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// progress.ts — UIProgressElement, the Display-class thin-rail progress bar (LLD-C1, feed-family.lld.md
|
|
2
|
+
// §2; SPEC-R1/R2/R3/R18/R19/R20; ADR-0112 cl.2). Non-interactive, non-form-associated leaf: no events, no
|
|
3
|
+
// keyboard contract, no [size]/[scale] control geometry — a bar is a rail, not a widget box. Value model
|
|
4
|
+
// mirrors the native <progress> semantic: `value === null` (default) ⇒ INDETERMINATE, never a separate
|
|
5
|
+
// boolean to desync. `render()` stays the inherited no-op — the track/fill pair is built once in
|
|
6
|
+
// `connected()` (survives reconnect via the private field guard) and mutated per-change by two effects.
|
|
7
|
+
//
|
|
8
|
+
// Hardening (SPEC-R1's table) is a pure in-file pair — the math is two clamps, no separate module:
|
|
9
|
+
// `effectiveMax` floors a non-finite/≤0/malformed `max` to the ARIA default (100); `effectiveValue` maps
|
|
10
|
+
// an absent/non-finite `value` to `null` (indeterminate) and clamps a real value into [0, effectiveMax].
|
|
11
|
+
// No case throws — every input, however malformed, resolves to a paintable, announced state.
|
|
12
|
+
import { UIElement, prop } from "../../dom/index.js";
|
|
13
|
+
const props = {
|
|
14
|
+
current: prop.number(null), // null ⇒ indeterminate (the native <progress> semantic — no boolean to desync). Renamed from `value` (TKT-0069 item 1 ruling: `value` = the FACE form value, reserved — this rename spends real native-<progress> parity deliberately; the A2UI catalog keeps wire `value`, mapped in its bespoke factory)
|
|
15
|
+
max: prop.number(100), // the ARIA progressbar default — percent-natural for {value:42} with zero extra props
|
|
16
|
+
label: { ...prop.string(''), reflect: true }, // the accessible name (SPEC-R3); empty ⇒ no internals.ariaLabel
|
|
17
|
+
};
|
|
18
|
+
/** SPEC-R1: non-finite / ≤0 / malformed `max` floors to the ARIA progressbar default. */
|
|
19
|
+
function effectiveMax(max) {
|
|
20
|
+
return max !== null && Number.isFinite(max) && max > 0 ? max : 100;
|
|
21
|
+
}
|
|
22
|
+
/** SPEC-R1: absent/non-finite `value` ⇒ null (indeterminate); else clamped into [0, eMax]. */
|
|
23
|
+
function effectiveValue(value, eMax) {
|
|
24
|
+
return value === null || !Number.isFinite(value) ? null : Math.min(Math.max(value, 0), eMax);
|
|
25
|
+
}
|
|
26
|
+
// Module-memoized (SPEC-R3): the percent reading behind `ariaValueText`, default locale.
|
|
27
|
+
const percentFormat = new Intl.NumberFormat(undefined, { style: 'percent', maximumFractionDigits: 0 });
|
|
28
|
+
export class UIProgressElement extends UIElement {
|
|
29
|
+
static props = props;
|
|
30
|
+
#track = null;
|
|
31
|
+
#fill = null;
|
|
32
|
+
connected() {
|
|
33
|
+
// Built ONCE (LLD-C1) — a private-field guard so a reconnect (children survive removal/re-append)
|
|
34
|
+
// never mints a second track/fill pair.
|
|
35
|
+
if (!this.#track) {
|
|
36
|
+
this.#track = document.createElement('span');
|
|
37
|
+
this.#track.setAttribute('data-part', 'track');
|
|
38
|
+
this.#fill = document.createElement('span');
|
|
39
|
+
this.#fill.setAttribute('data-part', 'fill');
|
|
40
|
+
this.#track.append(this.#fill);
|
|
41
|
+
this.append(this.#track);
|
|
42
|
+
}
|
|
43
|
+
const fill = this.#fill;
|
|
44
|
+
// Mark effect (SPEC-R2): determinate ⇒ the fill's --_pct custom property; indeterminate ⇒
|
|
45
|
+
// data-indeterminate on the fill (an interior node, never a host attribute — CSS drives the sweep).
|
|
46
|
+
this.effect(() => {
|
|
47
|
+
const eMax = effectiveMax(this.max);
|
|
48
|
+
const eValue = effectiveValue(this.current, eMax);
|
|
49
|
+
if (eValue === null) {
|
|
50
|
+
fill.setAttribute('data-indeterminate', '');
|
|
51
|
+
fill.style.removeProperty('--_pct');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
fill.removeAttribute('data-indeterminate');
|
|
55
|
+
fill.style.setProperty('--_pct', String((eValue / eMax) * 100));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
// ARIA effect (SPEC-R3): role=progressbar is ALWAYS set — status data, never silent (the chart
|
|
59
|
+
// inversion, ADR-0112 cl.2). Determinate publishes ariaValueNow/Text; indeterminate omits both while
|
|
60
|
+
// role/min/max persist — the ARIA-native indeterminate signal.
|
|
61
|
+
this.effect(() => {
|
|
62
|
+
const eMax = effectiveMax(this.max);
|
|
63
|
+
const eValue = effectiveValue(this.current, eMax);
|
|
64
|
+
this.internals.role = 'progressbar';
|
|
65
|
+
this.internals.ariaValueMin = '0';
|
|
66
|
+
this.internals.ariaValueMax = String(eMax);
|
|
67
|
+
if (eValue === null) {
|
|
68
|
+
this.internals.ariaValueNow = null;
|
|
69
|
+
this.internals.ariaValueText = null;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.internals.ariaValueNow = String(eValue);
|
|
73
|
+
this.internals.ariaValueText = percentFormat.format(eValue / eMax);
|
|
74
|
+
}
|
|
75
|
+
this.internals.ariaLabel = this.label || null;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!customElements.get('ui-progress'))
|
|
80
|
+
customElements.define('ui-progress', UIProgressElement); // idempotent self-define
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* radio-group.css — ui-radio-group, the radio-button container stylesheet (Wave 1 S3, ADR-0003).
|
|
2
|
+
*
|
|
3
|
+
* The container convention requires a .css even for a small layout footprint (process.md §4,
|
|
4
|
+
* container-family rule): every FACE component ships a stylesheet that at minimum carries the
|
|
5
|
+
* `:where(ui-{name})` token block and the `@scope (ui-{name})` block. The group has no visual surface of
|
|
6
|
+
* its own — its `ui-radio` children carry all visible affordances — but it DOES own its interior layout
|
|
7
|
+
* (ADR-0103); its forced-colors block stays minimal.
|
|
8
|
+
*
|
|
9
|
+
* ADR-0086 previously grew a "segmented" presentation variant here (a joined-button track + one shared
|
|
10
|
+
* moving highlight, keyed off `[variant='segmented']`). ADR-0095 supersedes that architecture: the segmented
|
|
11
|
+
* presentation is now the standalone `ui-segmented-control` (controls/segmented-control/segmented-control.css)
|
|
12
|
+
* — a hard cutover, no alias. This file is restored to its pre-ADR-0086 truth for presentation; ADR-0103
|
|
13
|
+
* then fills the token block's long-reserved seat with the group's OWN layout token (not a variant).
|
|
14
|
+
*
|
|
15
|
+
* ADR-0103 (the spacing pair): a value-owning group whose children must be its DIRECT children
|
|
16
|
+
* (radio-group.ts:194's `[...this.children].filter(...)`) cannot be fixed by composition — wrapping the
|
|
17
|
+
* radios in a `ui-column` would sever discovery. So the group owns the SAME flex structure the site used to
|
|
18
|
+
* hand-author per-page (component-preview.css, now deleted): a vertical stack by default,
|
|
19
|
+
* `[orientation='horizontal']` a wrapping row — with the gap re-based to the `--md-sys-space` ladder (`sm`) so it
|
|
20
|
+
* rides `[density]` for free, rather than the site's hard-coded `0.4rem`/`--md-sys-space-md` duplicates.
|
|
21
|
+
*
|
|
22
|
+
* Standalone stylesheet — linked via the component-styles barrel (s12, after radio.css); NEVER injected
|
|
23
|
+
* from radio-group.ts (behaviour-only `.ts`, no runtime style injection — plan §2).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/* ════════════ [1] TOKEN BLOCK — :where(ui-radio-group) (specificity 0,0,0) ════════════ */
|
|
27
|
+
|
|
28
|
+
:where(ui-radio-group) {
|
|
29
|
+
/* ADR-0103: the group's own interior gap, off the layout ladder (density-responsive for free) — the seat
|
|
30
|
+
this block's comment reserved ("future density/gap props without a cascade-order change"). Page authors
|
|
31
|
+
retune per-instance with one custom property (the ADR-0102 override freedom); no catalog `gap` enum yet
|
|
32
|
+
(a foreseen Lane B extension only if live evidence shows models need magnitude control). */
|
|
33
|
+
--ui-radio-group-gap: var(--md-sys-space-sm);
|
|
34
|
+
|
|
35
|
+
/* user-invalid (ADR-0051) — the danger border repoint reaching into each ui-radio child's own
|
|
36
|
+
::before ring (the group has no visual surface of its own, see the file header). Appears only
|
|
37
|
+
AFTER the first interaction (the trackUserInvalid controller owns that timing; radio-group.ts
|
|
38
|
+
toggles :state(user-invalid) on the group host). */
|
|
39
|
+
--ui-radio-group-border-invalid: var(--md-sys-color-danger);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ════════════ [2] STYLES BLOCK — @scope (ui-radio-group) ════════════ */
|
|
43
|
+
|
|
44
|
+
@scope (ui-radio-group) {
|
|
45
|
+
/* ADR-0103: a vertical stack by default — the roving-focus axis (Arrow Up/Down, radio-group.ts's
|
|
46
|
+
`defaultOrientation()`) and the visual axis are now the SAME source of truth. No explicit block-size or
|
|
47
|
+
inline-size — the group sizes to its content; only the gap is opinionated. */
|
|
48
|
+
:scope {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
gap: var(--ui-radio-group-gap);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* `[orientation='horizontal']` (reflected once at connect, radio-group.ts's connected()) switches to a
|
|
55
|
+
wrapping row — `flex-wrap: wrap` is graceful degradation in a cramped container (the ADR-0016 row-side
|
|
56
|
+
philosophy), and `align-items: center` keeps radios of differing label height on one visual baseline. */
|
|
57
|
+
:scope[orientation='horizontal'] {
|
|
58
|
+
flex-direction: row;
|
|
59
|
+
flex-wrap: wrap;
|
|
60
|
+
align-items: center;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Forced colors (WHCM) — no visual surface of its own: the ui-radio children carry their own
|
|
64
|
+
forced-color treatments. This block is present for fleet discipline (every FACE control's scope
|
|
65
|
+
includes a forced-colors rule). */
|
|
66
|
+
@media (forced-colors: active) {
|
|
67
|
+
:scope {
|
|
68
|
+
/* no group-level WHCM adjustments; the children carry their own forced-color rules */
|
|
69
|
+
forced-color-adjust: none;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* ════════════ user-invalid (ADR-0051) — a cross-boundary reach into ui-radio's own paint ════════════
|
|
75
|
+
* The group carries no visual surface of its own (the [2] block above); the danger repoint must reach
|
|
76
|
+
* INTO each `ui-radio` child's own `::before` ring instead. A plain top-level compound selector,
|
|
77
|
+
* deliberately OUTSIDE `@scope` — the SAME technique segmented-control.css uses to reach `ui-segment`
|
|
78
|
+
* (its own file header explains why: this clears `ui-radio`'s own `@scope (ui-radio) { :scope::before }`
|
|
79
|
+
* rule ((0,1,1)) without `!important`, since `ui-radio-group:state(user-invalid) ui-radio::before` is
|
|
80
|
+
* (0,1,3)). Never co-occurs with `:state(checked)::before` in practice — `formValidity()` only reports
|
|
81
|
+
* `valueMissing` when NO radio is checked, so no specificity race with the checked-fill rule. */
|
|
82
|
+
ui-radio-group:state(user-invalid) ui-radio::before {
|
|
83
|
+
border-color: var(--ui-radio-group-border-invalid);
|
|
84
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { UIFormElement } from '../../dom/form.js';
|
|
2
|
+
import type { FormValue, ValidityResult } from '../../dom/form.js';
|
|
3
|
+
import { type ReactiveProps } from '../../dom/props.js';
|
|
4
|
+
import { type RovingOrientation } from '../../traits/roving-focus.js';
|
|
5
|
+
import { UIRadioElement } from './radio.js';
|
|
6
|
+
declare const groupProps: {
|
|
7
|
+
orientation: {
|
|
8
|
+
reflect: true;
|
|
9
|
+
type: import("../../index.js").PropType<"horizontal" | "vertical">;
|
|
10
|
+
default: "horizontal" | "vertical";
|
|
11
|
+
attribute?: string | false;
|
|
12
|
+
};
|
|
13
|
+
name: {
|
|
14
|
+
reflect: true;
|
|
15
|
+
type: import("../../index.js").PropType<string>;
|
|
16
|
+
default: string;
|
|
17
|
+
attribute?: string | false;
|
|
18
|
+
};
|
|
19
|
+
disabled: {
|
|
20
|
+
reflect: true;
|
|
21
|
+
type: import("../../index.js").PropType<boolean>;
|
|
22
|
+
default: boolean;
|
|
23
|
+
attribute?: string | false;
|
|
24
|
+
};
|
|
25
|
+
required: {
|
|
26
|
+
reflect: true;
|
|
27
|
+
type: import("../../index.js").PropType<boolean>;
|
|
28
|
+
default: boolean;
|
|
29
|
+
attribute?: string | false;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export interface UIRadioGroupElement extends ReactiveProps<typeof groupProps> {
|
|
33
|
+
}
|
|
34
|
+
export declare class UIRadioGroupElement extends UIFormElement {
|
|
35
|
+
#private;
|
|
36
|
+
static props: {
|
|
37
|
+
orientation: {
|
|
38
|
+
reflect: true;
|
|
39
|
+
type: import("../../index.js").PropType<"horizontal" | "vertical">;
|
|
40
|
+
default: "horizontal" | "vertical";
|
|
41
|
+
attribute?: string | false;
|
|
42
|
+
};
|
|
43
|
+
name: {
|
|
44
|
+
reflect: true;
|
|
45
|
+
type: import("../../index.js").PropType<string>;
|
|
46
|
+
default: string;
|
|
47
|
+
attribute?: string | false;
|
|
48
|
+
};
|
|
49
|
+
disabled: {
|
|
50
|
+
reflect: true;
|
|
51
|
+
type: import("../../index.js").PropType<boolean>;
|
|
52
|
+
default: boolean;
|
|
53
|
+
attribute?: string | false;
|
|
54
|
+
};
|
|
55
|
+
required: {
|
|
56
|
+
reflect: true;
|
|
57
|
+
type: import("../../index.js").PropType<boolean>;
|
|
58
|
+
default: boolean;
|
|
59
|
+
attribute?: string | false;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
protected connected(): void;
|
|
63
|
+
/**
|
|
64
|
+
* The group's selected value — the checked `ui-radio` child's `value`, or `null` when none is
|
|
65
|
+
* selected. A public getter/setter pair delegating to the private `#selectedValue` signal (the
|
|
66
|
+
* `UICheckboxElement.indeterminate` precedent, checkbox.ts:39 — a plain accessor over a private
|
|
67
|
+
* signal, not a `prop.*`-declared attribute: the value is DERIVED from child radio state, so it
|
|
68
|
+
* has nothing of its own to reflect).
|
|
69
|
+
*
|
|
70
|
+
* The getter reads the signal directly — a reactive caller (e.g. inside `this.effect`) tracks it
|
|
71
|
+
* exactly like any other signal read.
|
|
72
|
+
*
|
|
73
|
+
* The setter is the PROGRAMMATIC path (e.g. a two-way data-bind write): it selects the child
|
|
74
|
+
* `ui-radio` whose `value` matches (unchecking all others) via `#applySelection` — the SAME state
|
|
75
|
+
* transition `#commit` drives for a user click/keyboard commit — but it does NOT emit `change`.
|
|
76
|
+
* This matches the fleet convention for a programmatic prop write on a value-bearing control
|
|
77
|
+
* (`UICheckboxElement.checked` / `UISelectElement.value` are directly settable and never
|
|
78
|
+
* self-emit on assignment; only the interaction-driven commit path — `#commit` here — emits).
|
|
79
|
+
*
|
|
80
|
+
* `null` clears the selection (unchecks every radio). A value matching NO child radio also CLEARS
|
|
81
|
+
* the selection, rather than a silent no-op — the native `HTMLSelectElement.value` precedent:
|
|
82
|
+
* assigning a `<select>`'s `.value` to a string with no matching `<option>` resolves
|
|
83
|
+
* `selectedIndex` to `-1` (the value reads back as `''`) instead of leaving the prior selection
|
|
84
|
+
* in place.
|
|
85
|
+
*/
|
|
86
|
+
get value(): string | null;
|
|
87
|
+
set value(v: string | null);
|
|
88
|
+
/**
|
|
89
|
+
* ADR-0095 clause 1 — the CLASS-derived default roving-axis orientation, consulted by `connected()`'s
|
|
90
|
+
* resolve-once-and-reflect ONLY when no explicit `orientation` attribute is authored. This base returns
|
|
91
|
+
* `'vertical'` (today's shipped roving, unchanged). `UISegmentedControlElement` overrides this to
|
|
92
|
+
* `'horizontal'` — the ADR-0086 "variant=segmented ⇒ horizontal" default, now class-derived instead of
|
|
93
|
+
* variant-derived.
|
|
94
|
+
*/
|
|
95
|
+
protected defaultOrientation(): RovingOrientation;
|
|
96
|
+
/**
|
|
97
|
+
* ADR-0095 clause 2 — a protected, no-op-in-the-base post-selection hook, fired from every
|
|
98
|
+
* selection-DEFINING event: the connect-time seed, every `#applySelection` (both `#commit`'s user-driven
|
|
99
|
+
* path AND the public `value` setter's programmatic path), and `formReset()`. This is the SAME seam
|
|
100
|
+
* ADR-0086's (now-retired) private `#writeIndexCount` fired from — moved here, as a protected hook,
|
|
101
|
+
* so `UISegmentedControlElement` can write its own `--ui-segmented-control-index`/`-count` moving-
|
|
102
|
+
* indicator state WITHOUT this base class knowing anything about segments or indicators. A no-op here
|
|
103
|
+
* costs nothing for the plain dot-group presentation.
|
|
104
|
+
*/
|
|
105
|
+
protected selectionChanged(_radios: UIRadioElement[], _index: number): void;
|
|
106
|
+
/**
|
|
107
|
+
* The group's form value: the selected radio's `value`, or `null` when nothing is checked.
|
|
108
|
+
* Reads `#selectedValue.value` (a signal) so the UIFormElement base's scope-owned setFormValue
|
|
109
|
+
* effect re-runs automatically when selection changes.
|
|
110
|
+
*/
|
|
111
|
+
protected formValue(): FormValue;
|
|
112
|
+
/**
|
|
113
|
+
* Validity: `required` + no selection → `valueMissing`. Reads `#selectedValue.value` so the
|
|
114
|
+
* UIFormElement base's setValidity effect re-runs when selection changes. An empty, required group
|
|
115
|
+
* stays invalid until a radio is committed; a non-required empty group is always valid.
|
|
116
|
+
*/
|
|
117
|
+
protected formValidity(): ValidityResult;
|
|
118
|
+
/**
|
|
119
|
+
* Form reset — group-level coordination (bug-A fix). Each child radio is its OWN `UIFormElement`
|
|
120
|
+
* participant with its OWN `formResetCallback` (now fixed, indicator-element.ts) that silently restores
|
|
121
|
+
* ITS `checked` to ITS `defaultChecked` — but the GROUP owns a SEPARATE `#selectedValue` signal
|
|
122
|
+
* (`formValue()`/`formValidity()` above), which no radio's own reset can reach. Recompute it here from
|
|
123
|
+
* every child's `defaultChecked` (a stable, native-parity PUBLIC getter — see UIIndicatorElement) rather
|
|
124
|
+
* than each child's live `checked`: the platform resets the group and its radios as INDEPENDENT
|
|
125
|
+
* `UIFormElement`s, in an order this class must not assume (tree order suggests ancestor-first, i.e.
|
|
126
|
+
* this runs BEFORE the radios' own resets — reading live `checked` here would see PRE-reset values).
|
|
127
|
+
* `defaultChecked` sidesteps the ordering question entirely: it is a fixed snapshot from each radio's
|
|
128
|
+
* first connect, unaffected by reset order on either side. Silent — no `change` emitted (a reset is not
|
|
129
|
+
* a user commit; matches `#commit`'s own emit-on-user-action-only discipline).
|
|
130
|
+
*
|
|
131
|
+
* Bug fix (component-reviewer B4, blocking; ADR-0086, preserved verbatim by ADR-0095 clause 2): a reset
|
|
132
|
+
* must ALSO fire the post-selection hook (`selectionChanged`). The hook was previously (ADR-0086) a
|
|
133
|
+
* private `#writeIndexCount` written only at connect and in `#commit` — but a radio's own reset
|
|
134
|
+
* (`indicator-element.ts`) restores its `checked` OUTSIDE `#commit`, so without this the seam desyncs
|
|
135
|
+
* in a subclass that consumes it (e.g. `UISegmentedControlElement`'s moving indicator): the CSS
|
|
136
|
+
* `:not(:has(ui-radio[checked]))`-style gate correctly re-shows the indicator (the DOM `[checked]` is
|
|
137
|
+
* genuinely restored), but a STALE index would still park the moving fill on the pre-reset selection —
|
|
138
|
+
* a visible indicator/ink mismatch. Recomputed from `defaultChecked` for the same reset-order-
|
|
139
|
+
* independence reason as `#selectedValue` above (not live `checked`, which may not have reset yet on
|
|
140
|
+
* this radio's siblings). `findIndex` returns `-1` when no radio was ever default-checked; a consuming
|
|
141
|
+
* subclass's hook is expected to clamp that to `0` the same way ADR-0086's seam did — harmless, since a
|
|
142
|
+
* segmented indicator hides itself whenever nothing is `[checked]`.
|
|
143
|
+
*/
|
|
144
|
+
protected formReset(): void;
|
|
145
|
+
protected disconnected(): void;
|
|
146
|
+
/** Feeds `FormConnectDetail.userInvalid` (ADR-0050) — the `trackUserInvalid` tracker IS the one
|
|
147
|
+
* timing source; this override just exposes its gate. Inherited by `UISegmentedControlElement`
|
|
148
|
+
* unchanged (it never overrides connected()/formReset(), so this base's wiring applies to its
|
|
149
|
+
* own internals directly). */
|
|
150
|
+
protected formUserInvalid(): boolean;
|
|
151
|
+
}
|
|
152
|
+
export {};
|