@aceshooting/lyra-ui 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -14
- package/custom-elements.json +11555 -5539
- package/dist/components/app-rail/app-rail-item.d.ts +30 -0
- package/dist/components/app-rail/app-rail-item.js +68 -0
- package/dist/components/app-rail/app-rail-item.styles.d.ts +1 -0
- package/dist/components/app-rail/app-rail-item.styles.js +65 -0
- package/dist/components/app-rail/app-rail.d.ts +21 -24
- package/dist/components/app-rail/app-rail.js +68 -132
- package/dist/components/app-rail/app-rail.styles.js +5 -2
- package/dist/components/attachment-chip/attachment-chip.d.ts +38 -11
- package/dist/components/attachment-chip/attachment-chip.js +73 -29
- package/dist/components/attachment-trigger/attachment-trigger.d.ts +13 -0
- package/dist/components/attachment-trigger/attachment-trigger.js +13 -1
- package/dist/components/attachment-trigger/attachment-trigger.styles.js +28 -6
- package/dist/components/chart/bar-chart.js +2 -18
- package/dist/components/chart/box-plot.d.ts +25 -1
- package/dist/components/chart/box-plot.js +136 -6
- package/dist/components/chart/box-plot.styles.js +13 -0
- package/dist/components/chart/bubble-chart.js +2 -18
- package/dist/components/chart/chart.d.ts +54 -10
- package/dist/components/chart/chart.js +182 -39
- package/dist/components/chart/doughnut-chart.js +2 -18
- package/dist/components/chart/histogram-bin.d.ts +5 -2
- package/dist/components/chart/histogram-bin.js +12 -4
- package/dist/components/chart/histogram.js +8 -16
- package/dist/components/chart/line-chart.js +2 -18
- package/dist/components/chart/lite-chart.d.ts +80 -3
- package/dist/components/chart/lite-chart.js +250 -53
- package/dist/components/chart/pie-chart.js +2 -18
- package/dist/components/chart/polar-area-chart.js +2 -18
- package/dist/components/chart/radar-chart.js +2 -18
- package/dist/components/chart/scatter-chart.js +2 -18
- package/dist/components/chat-composer/chat-composer.d.ts +42 -1
- package/dist/components/chat-composer/chat-composer.js +84 -3
- package/dist/components/chat-composer/chat-composer.styles.js +11 -1
- package/dist/components/chat-message/chat-message.d.ts +32 -4
- package/dist/components/chat-message/chat-message.js +57 -17
- package/dist/components/checkbox/checkbox.d.ts +66 -8
- package/dist/components/checkbox/checkbox.js +173 -50
- package/dist/components/checkbox/checkbox.styles.js +9 -2
- package/dist/components/chip/chip-group.js +8 -2
- package/dist/components/chip/chip.js +9 -2
- package/dist/components/citation-badge/citation-badge.js +21 -3
- package/dist/components/code-block/code-block.d.ts +38 -0
- package/dist/components/code-block/code-block.js +72 -7
- package/dist/components/code-block/code-loader.d.ts +44 -1
- package/dist/components/code-block/code-loader.js +63 -0
- package/dist/components/combobox/combobox.d.ts +46 -5
- package/dist/components/combobox/combobox.js +175 -35
- package/dist/components/combobox/combobox.styles.js +3 -3
- package/dist/components/context-meter/context-meter.js +17 -8
- package/dist/components/context-meter/context-meter.styles.js +0 -6
- package/dist/components/conversation-item/conversation-item.d.ts +13 -16
- package/dist/components/conversation-item/conversation-item.js +29 -20
- package/dist/components/date-picker/calendar-core.d.ts +24 -0
- package/dist/components/date-picker/calendar-core.js +51 -4
- package/dist/components/date-picker/date-input.d.ts +77 -10
- package/dist/components/date-picker/date-input.js +278 -73
- package/dist/components/date-picker/date-picker.d.ts +28 -4
- package/dist/components/date-picker/date-picker.js +95 -37
- package/dist/components/dialog/confirm.js +3 -6
- package/dist/components/dialog/dialog.d.ts +75 -31
- package/dist/components/dialog/dialog.js +147 -131
- package/dist/components/dialog/dialog.styles.js +46 -2
- package/dist/components/dock-panel/dock-panel.d.ts +8 -0
- package/dist/components/dock-panel/dock-panel.js +15 -1
- package/dist/components/dock-panel/dock-panel.styles.js +15 -1
- package/dist/components/document-preview/document-preview.d.ts +15 -7
- package/dist/components/document-preview/document-preview.js +29 -13
- package/dist/components/empty/empty.d.ts +1 -2
- package/dist/components/empty/empty.js +18 -12
- package/dist/components/empty/empty.styles.js +0 -3
- package/dist/components/export-button/export-button.d.ts +12 -0
- package/dist/components/export-button/export-button.js +33 -5
- package/dist/components/export-button/export-button.styles.js +5 -1
- package/dist/components/file-input/accept.js +2 -0
- package/dist/components/file-input/file-input.d.ts +10 -1
- package/dist/components/file-input/file-input.js +36 -5
- package/dist/components/flag/flag.d.ts +1 -1
- package/dist/components/flag/flag.js +15 -1
- package/dist/components/flag/flag.styles.js +1 -1
- package/dist/components/flag/language-map.d.ts +4 -1
- package/dist/components/flag/language-map.js +6 -3
- package/dist/components/gauge/gauge.d.ts +10 -1
- package/dist/components/gauge/gauge.js +28 -9
- package/dist/components/generation-status/generation-status.d.ts +13 -5
- package/dist/components/generation-status/generation-status.js +59 -5
- package/dist/components/graph/graph.d.ts +37 -3
- package/dist/components/graph/graph.js +132 -20
- package/dist/components/heatmap/calendar-grid.d.ts +15 -6
- package/dist/components/heatmap/calendar-grid.js +17 -6
- package/dist/components/heatmap/heatmap-scale.d.ts +5 -1
- package/dist/components/heatmap/heatmap-scale.js +8 -2
- package/dist/components/heatmap/heatmap.d.ts +166 -25
- package/dist/components/heatmap/heatmap.js +372 -89
- package/dist/components/json-viewer/json-viewer.d.ts +22 -5
- package/dist/components/json-viewer/json-viewer.js +115 -37
- package/dist/components/json-viewer/json-viewer.styles.js +2 -1
- package/dist/components/kbd/kbd.js +24 -7
- package/dist/components/live-region/live-region.d.ts +10 -1
- package/dist/components/live-region/live-region.js +42 -6
- package/dist/components/map/map.d.ts +24 -1
- package/dist/components/map/map.js +89 -24
- package/dist/components/markdown/markdown-loader.d.ts +24 -0
- package/dist/components/markdown/markdown-loader.js +35 -1
- package/dist/components/markdown/markdown.d.ts +46 -8
- package/dist/components/markdown/markdown.js +136 -31
- package/dist/components/markdown/markdown.styles.js +7 -1
- package/dist/components/media-card/media-card.d.ts +25 -17
- package/dist/components/media-card/media-card.js +43 -65
- package/dist/components/mention-popover/mention-popover.d.ts +4 -1
- package/dist/components/mention-popover/mention-popover.js +23 -5
- package/dist/components/menu/menu-item.d.ts +32 -3
- package/dist/components/menu/menu-item.js +94 -7
- package/dist/components/menu/menu-item.styles.js +8 -0
- package/dist/components/menu/menu.d.ts +25 -1
- package/dist/components/menu/menu.js +99 -3
- package/dist/components/menu/menu.styles.js +3 -2
- package/dist/components/model-select/model-select.d.ts +48 -3
- package/dist/components/model-select/model-select.js +120 -22
- package/dist/components/model-select/model-select.styles.js +17 -3
- package/dist/components/model-settings-panel/model-settings-panel.d.ts +25 -1
- package/dist/components/model-settings-panel/model-settings-panel.js +65 -1
- package/dist/components/playback/playback.d.ts +6 -2
- package/dist/components/playback/playback.js +72 -29
- package/dist/components/playback/playback.styles.js +6 -1
- package/dist/components/responsive-panel/responsive-panel.d.ts +29 -16
- package/dist/components/responsive-panel/responsive-panel.js +130 -132
- package/dist/components/responsive-panel/responsive-panel.styles.js +1 -1
- package/dist/components/result-card/result-card.d.ts +8 -2
- package/dist/components/result-card/result-card.js +9 -3
- package/dist/components/result-card/result-card.styles.js +0 -1
- package/dist/components/select/select.d.ts +59 -20
- package/dist/components/select/select.js +125 -43
- package/dist/components/skeleton/skeleton.d.ts +3 -0
- package/dist/components/skeleton/skeleton.js +7 -1
- package/dist/components/skeleton/skeleton.styles.js +5 -4
- package/dist/components/slider/slider.d.ts +57 -5
- package/dist/components/slider/slider.js +195 -80
- package/dist/components/source-card/source-card.d.ts +17 -5
- package/dist/components/source-card/source-card.js +55 -8
- package/dist/components/source-card/source-card.styles.js +1 -1
- package/dist/components/source-list/source-list.js +9 -1
- package/dist/components/sparkline/sparkline.js +34 -10
- package/dist/components/split/split.d.ts +141 -14
- package/dist/components/split/split.js +357 -52
- package/dist/components/split/split.styles.js +18 -1
- package/dist/components/stat/stat.d.ts +10 -4
- package/dist/components/stat/stat.js +46 -11
- package/dist/components/stream-status/stream-status.d.ts +27 -11
- package/dist/components/stream-status/stream-status.js +95 -13
- package/dist/components/streaming-text/streaming-text.d.ts +9 -3
- package/dist/components/streaming-text/streaming-text.js +25 -10
- package/dist/components/streaming-text/streaming-text.styles.js +3 -2
- package/dist/components/switch/switch.d.ts +52 -7
- package/dist/components/switch/switch.js +111 -40
- package/dist/components/switch/switch.styles.js +1 -1
- package/dist/components/table/table.d.ts +18 -3
- package/dist/components/table/table.js +88 -20
- package/dist/components/tabs/tabs.d.ts +23 -0
- package/dist/components/tabs/tabs.js +76 -12
- package/dist/components/tabs/tabs.styles.js +11 -0
- package/dist/components/thinking-panel/thinking-panel.d.ts +3 -1
- package/dist/components/thinking-panel/thinking-panel.js +34 -9
- package/dist/components/thinking-panel/thinking-panel.styles.js +6 -0
- package/dist/components/time-range/time-range.d.ts +59 -2
- package/dist/components/time-range/time-range.js +163 -67
- package/dist/components/toast/toast-item.d.ts +12 -3
- package/dist/components/toast/toast-item.js +90 -53
- package/dist/components/toast/toast-item.styles.js +59 -28
- package/dist/components/toast/toast.js +17 -5
- package/dist/components/toast/toaster.js +10 -1
- package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +11 -10
- package/dist/components/tool-approval-dialog/tool-approval-dialog.js +50 -124
- package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +1 -1
- package/dist/components/tool-call-chip/tool-call-chip.d.ts +18 -2
- package/dist/components/tool-call-chip/tool-call-chip.js +86 -25
- package/dist/components/tool-param-form/tool-param-form.d.ts +89 -28
- package/dist/components/tool-param-form/tool-param-form.js +350 -106
- package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +27 -7
- package/dist/components/tool-result-dialog/tool-result-dialog.js +80 -115
- package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +1 -1
- package/dist/components/tool-result-view/registry.d.ts +0 -8
- package/dist/components/tool-result-view/registry.js +7 -2
- package/dist/components/tool-result-view/tool-result-view.d.ts +6 -3
- package/dist/components/tool-result-view/tool-result-view.js +18 -4
- package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +11 -11
- package/dist/components/tool-select-dialog/tool-select-dialog.js +44 -133
- package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +13 -4
- package/dist/components/tree/tree-node.d.ts +4 -1
- package/dist/components/tree/tree-node.js +4 -1
- package/dist/components/tree/tree.d.ts +17 -8
- package/dist/components/tree/tree.js +21 -20
- package/dist/components/typing-indicator/typing-indicator.d.ts +12 -2
- package/dist/components/typing-indicator/typing-indicator.js +16 -4
- package/dist/components/typing-indicator/typing-indicator.styles.js +2 -2
- package/dist/components/virtual-list/virtual-list.d.ts +56 -19
- package/dist/components/virtual-list/virtual-list.js +184 -38
- package/dist/components/virtual-list/virtual-list.styles.js +12 -0
- package/dist/components/widget/widget.d.ts +5 -4
- package/dist/components/widget/widget.js +54 -120
- package/dist/components/widget/widget.styles.js +8 -2
- package/dist/components/word-cloud/word-cloud-layout.d.ts +7 -0
- package/dist/components/word-cloud/word-cloud-layout.js +20 -6
- package/dist/components/word-cloud/word-cloud.d.ts +22 -2
- package/dist/components/word-cloud/word-cloud.js +45 -6
- package/dist/components/word-cloud/word-cloud.styles.js +13 -1
- package/dist/internal/anchored-validity.d.ts +1 -0
- package/dist/internal/anchored-validity.js +86 -0
- package/dist/internal/form-associated.d.ts +7 -0
- package/dist/internal/form-associated.js +43 -4
- package/dist/internal/numbers.d.ts +12 -0
- package/dist/internal/numbers.js +26 -0
- package/dist/internal/overlay-manager.d.ts +51 -0
- package/dist/internal/overlay-manager.js +523 -0
- package/dist/internal/positioner.js +27 -3
- package/dist/internal/safe-url.d.ts +12 -0
- package/dist/internal/safe-url.js +41 -0
- package/dist/internal/tokens.styles.js +17 -11
- package/dist/lyra.d.ts +5 -2
- package/dist/lyra.js +3 -1
- package/llms-full.txt +970 -426
- package/llms.txt +5 -4
- package/package.json +19 -2
|
@@ -11,6 +11,7 @@ import { defineElement } from '../../internal/prefix.js';
|
|
|
11
11
|
import { place } from '../../internal/positioner.js';
|
|
12
12
|
import { nextId } from '../../internal/a11y.js';
|
|
13
13
|
import { chevronIcon } from '../../internal/icons.js';
|
|
14
|
+
import { AnchoredValidityController, VALIDITY_ANCHOR } from '../../internal/anchored-validity.js';
|
|
14
15
|
import { styles } from './select.styles.js';
|
|
15
16
|
import { LyraOption } from '../combobox/option.js';
|
|
16
17
|
import '../combobox/option.js';
|
|
@@ -33,16 +34,21 @@ import '../combobox/option.js';
|
|
|
33
34
|
* "active" row is conveyed via `aria-activedescendant`, never actual focus),
|
|
34
35
|
* matching the WAI-ARIA "select-only combobox" pattern.
|
|
35
36
|
*
|
|
36
|
-
* When exactly one option is enabled
|
|
37
|
-
* exist alongside it), the popup never
|
|
38
|
-
* ArrowDown, or ArrowUp on the trigger
|
|
39
|
-
* and the trigger renders as a plain
|
|
40
|
-
* `aria-haspopup`/`aria-expanded` rather than
|
|
41
|
-
* inert popup state — opening a one-row list to
|
|
42
|
-
* choice is pure friction with no real decision
|
|
43
|
-
* changes `value`/validity defaults on its own — an
|
|
44
|
-
* select stays unselected (and a `required` one
|
|
45
|
-
* the multi-option case, until the trigger is
|
|
37
|
+
* When `autoCommitSingleOption` is set and exactly one option is enabled
|
|
38
|
+
* (regardless of how many disabled ones exist alongside it), the popup never
|
|
39
|
+
* opens at all: a click, Enter, Space, ArrowDown, or ArrowUp on the trigger
|
|
40
|
+
* commits that sole option directly, and the trigger renders as a plain
|
|
41
|
+
* `role="button"` with no chevron/`aria-haspopup`/`aria-expanded` rather than
|
|
42
|
+
* a combobox with a permanently inert popup state — opening a one-row list to
|
|
43
|
+
* pick the only available choice is pure friction with no real decision
|
|
44
|
+
* behind it. This never changes `value`/validity defaults on its own — an
|
|
45
|
+
* unselected single-option select stays unselected (and a `required` one
|
|
46
|
+
* stays invalid) exactly like the multi-option case, until the trigger is
|
|
47
|
+
* actually activated. `autoCommitSingleOption` defaults to `false`: by
|
|
48
|
+
* default a select always renders the normal combobox/listbox/chevron
|
|
49
|
+
* trigger no matter how many options are enabled, matching pre-1.3.0
|
|
50
|
+
* behavior — opt in explicitly if a narrowing-to-one option list should
|
|
51
|
+
* auto-commit.
|
|
46
52
|
*
|
|
47
53
|
* @customElement lyra-select
|
|
48
54
|
* @slot - `<lyra-option>` elements.
|
|
@@ -70,20 +76,30 @@ export class LyraSelect extends LyraElement {
|
|
|
70
76
|
static { this.formAssociated = true; }
|
|
71
77
|
static { this.styles = [LyraElement.styles, styles]; }
|
|
72
78
|
static { this.properties = {
|
|
79
|
+
disabled: { type: Boolean, reflect: true, noAccessor: true },
|
|
80
|
+
required: { type: Boolean, reflect: true, noAccessor: true },
|
|
73
81
|
value: { noAccessor: true },
|
|
74
82
|
name: { reflect: true, noAccessor: true },
|
|
75
83
|
}; }
|
|
76
84
|
constructor() {
|
|
77
85
|
super();
|
|
78
86
|
this.placeholder = '';
|
|
79
|
-
this.disabled = false;
|
|
80
|
-
this.required = false;
|
|
81
87
|
this.label = '';
|
|
82
88
|
this.hint = '';
|
|
83
89
|
this.errorText = '';
|
|
84
90
|
this.open = false;
|
|
85
91
|
/** Visual size — same `xs`–`xl` scale as `lyra-toast-item`'s `size`. */
|
|
86
92
|
this.size = 'm';
|
|
93
|
+
/**
|
|
94
|
+
* Opt-in: when `true` and exactly one `<lyra-option>` is enabled, the
|
|
95
|
+
* trigger commits that option directly (click/Enter/Space/ArrowDown/
|
|
96
|
+
* ArrowUp) instead of opening the listbox, and renders as a plain
|
|
97
|
+
* `role="button"` with no chevron. Defaults to `false`, which always
|
|
98
|
+
* renders the normal combobox/listbox/chevron trigger regardless of how
|
|
99
|
+
* many options are enabled — the pre-1.3.0 behavior. See the class doc
|
|
100
|
+
* above and `onlyOption` below for the full rationale.
|
|
101
|
+
*/
|
|
102
|
+
this.autoCommitSingleOption = false;
|
|
87
103
|
this.activeIndex = -1;
|
|
88
104
|
this.options = [];
|
|
89
105
|
// Set on the trigger button's first `blur`; gates the `data-invalid`
|
|
@@ -105,6 +121,8 @@ export class LyraSelect extends LyraElement {
|
|
|
105
121
|
this.triggerId = nextId('select-trigger');
|
|
106
122
|
this._isFirstUpdate = true;
|
|
107
123
|
this._selected = '';
|
|
124
|
+
this._disabled = false;
|
|
125
|
+
this._required = false;
|
|
108
126
|
// What `form.reset()` restores to. Captured exactly once, from whatever
|
|
109
127
|
// `<lyra-option selected>` markup was present the first time slotted
|
|
110
128
|
// options are collected (mirrors native `<select><option selected>`) --
|
|
@@ -113,6 +131,9 @@ export class LyraSelect extends LyraElement {
|
|
|
113
131
|
// the reset default. See lyra-combobox's identical `_defaultSelected`.
|
|
114
132
|
this._defaultSelected = '';
|
|
115
133
|
this._defaultCaptured = false;
|
|
134
|
+
// A restored value must win over declarative selected markup collected by
|
|
135
|
+
// the first asynchronous slotchange. Cleared by the next ordinary value write.
|
|
136
|
+
this._restoredStateActive = false;
|
|
116
137
|
// Standard listbox type-ahead: printable keystrokes accumulate into this
|
|
117
138
|
// buffer and reset ~500ms after the last one, so "b" then "a" narrows to
|
|
118
139
|
// "ba" instead of restarting the search on every keystroke.
|
|
@@ -143,7 +164,7 @@ export class LyraSelect extends LyraElement {
|
|
|
143
164
|
// the reset default.
|
|
144
165
|
const declared = this.options.filter((o) => o.selected).map((o) => o.value);
|
|
145
166
|
this._defaultSelected = declared[0] ?? '';
|
|
146
|
-
if (declared.length) {
|
|
167
|
+
if (declared.length && !this._restoredStateActive) {
|
|
147
168
|
this.value = declared[0];
|
|
148
169
|
return; // `value=`'s setter already called reflectSelected()
|
|
149
170
|
}
|
|
@@ -155,7 +176,7 @@ export class LyraSelect extends LyraElement {
|
|
|
155
176
|
// into the live selection instead of letting reflectSelected() below
|
|
156
177
|
// strip its `selected` attribute back off.
|
|
157
178
|
const newlySelected = this.options.filter((o) => !previous.has(o) && o.selected).map((o) => o.value);
|
|
158
|
-
if (newlySelected.length) {
|
|
179
|
+
if (newlySelected.length && !this._restoredStateActive) {
|
|
159
180
|
this.value = newlySelected[newlySelected.length - 1];
|
|
160
181
|
return; // `value=`'s setter already called reflectSelected()
|
|
161
182
|
}
|
|
@@ -276,6 +297,27 @@ export class LyraSelect extends LyraElement {
|
|
|
276
297
|
this.selectOption(option);
|
|
277
298
|
};
|
|
278
299
|
this.internals = this.attachInternals();
|
|
300
|
+
this.validityController = new AnchoredValidityController(this, this.internals, () => this[VALIDITY_ANCHOR]());
|
|
301
|
+
this.syncFormValue();
|
|
302
|
+
}
|
|
303
|
+
get form() {
|
|
304
|
+
return this.internals.form;
|
|
305
|
+
}
|
|
306
|
+
get labels() {
|
|
307
|
+
return this.internals.labels;
|
|
308
|
+
}
|
|
309
|
+
get validity() {
|
|
310
|
+
return this.internals.validity;
|
|
311
|
+
}
|
|
312
|
+
get validationMessage() {
|
|
313
|
+
return this.internals.validationMessage;
|
|
314
|
+
}
|
|
315
|
+
get willValidate() {
|
|
316
|
+
return this.internals.willValidate;
|
|
317
|
+
}
|
|
318
|
+
/** @internal */
|
|
319
|
+
[VALIDITY_ANCHOR]() {
|
|
320
|
+
return this.renderRoot?.querySelector('[part="trigger"]') ?? null;
|
|
279
321
|
}
|
|
280
322
|
connectedCallback() {
|
|
281
323
|
super.connectedCallback();
|
|
@@ -307,12 +349,34 @@ export class LyraSelect extends LyraElement {
|
|
|
307
349
|
}
|
|
308
350
|
this.requestUpdate('name', old);
|
|
309
351
|
}
|
|
352
|
+
get disabled() {
|
|
353
|
+
return this._disabled;
|
|
354
|
+
}
|
|
355
|
+
set disabled(next) {
|
|
356
|
+
const old = this._disabled;
|
|
357
|
+
this._disabled = Boolean(next);
|
|
358
|
+
this.toggleAttribute('disabled', this._disabled);
|
|
359
|
+
if (this._disabled)
|
|
360
|
+
this.hide();
|
|
361
|
+
this.requestUpdate('disabled', old);
|
|
362
|
+
}
|
|
363
|
+
get required() {
|
|
364
|
+
return this._required;
|
|
365
|
+
}
|
|
366
|
+
set required(next) {
|
|
367
|
+
const old = this._required;
|
|
368
|
+
this._required = Boolean(next);
|
|
369
|
+
this.toggleAttribute('required', this._required);
|
|
370
|
+
this.updateValidity();
|
|
371
|
+
this.requestUpdate('required', old);
|
|
372
|
+
}
|
|
310
373
|
/** The selected value: a single string (empty when nothing is selected). */
|
|
311
374
|
get value() {
|
|
312
375
|
return this._selected;
|
|
313
376
|
}
|
|
314
377
|
set value(next) {
|
|
315
378
|
const old = this._selected;
|
|
379
|
+
this._restoredStateActive = false;
|
|
316
380
|
this._selected = next ?? '';
|
|
317
381
|
this.syncFormValue();
|
|
318
382
|
this.reflectSelected();
|
|
@@ -321,10 +385,10 @@ export class LyraSelect extends LyraElement {
|
|
|
321
385
|
}
|
|
322
386
|
updateValidity() {
|
|
323
387
|
if (this.required && !this._selected) {
|
|
324
|
-
this.
|
|
388
|
+
this.validityController.setValidity({ valueMissing: true }, 'Please select an option.');
|
|
325
389
|
}
|
|
326
390
|
else {
|
|
327
|
-
this.
|
|
391
|
+
this.validityController.setValidity({});
|
|
328
392
|
}
|
|
329
393
|
}
|
|
330
394
|
syncFormValue() {
|
|
@@ -339,6 +403,10 @@ export class LyraSelect extends LyraElement {
|
|
|
339
403
|
formResetCallback() {
|
|
340
404
|
this.value = this._defaultSelected;
|
|
341
405
|
}
|
|
406
|
+
formStateRestoreCallback(state, _mode) {
|
|
407
|
+
this.value = typeof state === 'string' ? state : '';
|
|
408
|
+
this._restoredStateActive = true;
|
|
409
|
+
}
|
|
342
410
|
/**
|
|
343
411
|
* Called by the browser when an ancestor `<fieldset disabled>` toggles.
|
|
344
412
|
* Tracked separately from the consumer's own `disabled` (see
|
|
@@ -347,6 +415,8 @@ export class LyraSelect extends LyraElement {
|
|
|
347
415
|
*/
|
|
348
416
|
formDisabledCallback(disabled) {
|
|
349
417
|
this._fieldsetDisabled = disabled;
|
|
418
|
+
if (disabled)
|
|
419
|
+
this.hide();
|
|
350
420
|
this.requestUpdate();
|
|
351
421
|
}
|
|
352
422
|
checkValidity() {
|
|
@@ -373,17 +443,21 @@ export class LyraSelect extends LyraElement {
|
|
|
373
443
|
o.selected = o.value === this._selected;
|
|
374
444
|
}
|
|
375
445
|
/**
|
|
376
|
-
* The sole navigable (non-disabled) option, when
|
|
377
|
-
* popup to pick the only available choice is pure
|
|
378
|
-
* it, so
|
|
379
|
-
* which commit this option directly on
|
|
380
|
-
* `render()`, which drops the popup-trigger
|
|
381
|
-
* `aria-haspopup`, `aria-expanded`, the chevron) in favor
|
|
382
|
-
* popup can ever appear while this getter returns a value.
|
|
383
|
-
*
|
|
446
|
+
* The sole navigable (non-disabled) option, when `autoCommitSingleOption` is set and
|
|
447
|
+
* there's exactly one. Opening a one-row popup to pick the only available choice is pure
|
|
448
|
+
* friction with no real decision behind it, so an opted-in single-option select skips the
|
|
449
|
+
* popup entirely -- see `onTriggerClick`/`onKeyDown`, which commit this option directly on
|
|
450
|
+
* activation instead of opening the listbox, and `render()`, which drops the popup-trigger
|
|
451
|
+
* ARIA semantics (`role="combobox"`, `aria-haspopup`, `aria-expanded`, the chevron) in favor
|
|
452
|
+
* of a plain button's, since no popup can ever appear while this getter returns a value.
|
|
453
|
+
* Returns `undefined` whenever `autoCommitSingleOption` is `false` (the default), regardless
|
|
454
|
+
* of option count, so the normal combobox trigger renders unconditionally. Does not affect
|
|
455
|
+
* `value`/validity defaults in any way -- an unselected single-option select stays unselected
|
|
384
456
|
* until the trigger is actually activated, exactly like the multi-option case.
|
|
385
457
|
*/
|
|
386
458
|
get onlyOption() {
|
|
459
|
+
if (!this.autoCommitSingleOption)
|
|
460
|
+
return undefined;
|
|
387
461
|
const navigable = this.options.filter((o) => !o.disabled);
|
|
388
462
|
return navigable.length === 1 ? navigable[0] : undefined;
|
|
389
463
|
}
|
|
@@ -425,19 +499,26 @@ export class LyraSelect extends LyraElement {
|
|
|
425
499
|
this.emit('lyra-hide');
|
|
426
500
|
}
|
|
427
501
|
}
|
|
428
|
-
if (changed.has('required'))
|
|
429
|
-
this.updateValidity();
|
|
430
502
|
if (changed.has('touched') || changed.has('required') || changed.has('value')) {
|
|
431
503
|
this.toggleAttribute('data-invalid', this.touched && !this.internals.validity.valid);
|
|
432
504
|
}
|
|
433
505
|
}
|
|
434
506
|
selectOption(option) {
|
|
435
|
-
if (option.disabled)
|
|
507
|
+
if (this.effectiveDisabled || option.disabled)
|
|
436
508
|
return;
|
|
509
|
+
// Reopening the listbox (or, on a single-option select, simply
|
|
510
|
+
// reactivating the trigger) and landing back on the already-selected
|
|
511
|
+
// row is not a selection change -- `change`/`input` are documented as
|
|
512
|
+
// firing when "the selection changed", so only emit them when the
|
|
513
|
+
// value actually moves, matching a native <select> (which never fires
|
|
514
|
+
// `change` for re-picking the currently-selected <option>).
|
|
515
|
+
const changed = option.value !== this._selected;
|
|
437
516
|
this.value = option.value;
|
|
438
517
|
this.hide();
|
|
439
|
-
|
|
440
|
-
|
|
518
|
+
if (changed) {
|
|
519
|
+
this.emit('input');
|
|
520
|
+
this.emit('change');
|
|
521
|
+
}
|
|
441
522
|
}
|
|
442
523
|
/**
|
|
443
524
|
* Standard listbox type-ahead: moves to the next non-disabled option whose
|
|
@@ -515,12 +596,15 @@ export class LyraSelect extends LyraElement {
|
|
|
515
596
|
const hasHint = this.hasHintSlot || this.hint.length > 0;
|
|
516
597
|
const hasError = this.hasErrorSlot || this.errorText.length > 0;
|
|
517
598
|
const hasLabel = this.hasLabelSlot || this.label.length > 0;
|
|
518
|
-
|
|
519
|
-
//
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
//
|
|
523
|
-
|
|
599
|
+
const describedBy = [hasError ? 'select-error' : '', hasHint ? 'select-hint' : ''].filter(Boolean).join(' ');
|
|
600
|
+
// A single navigable option has no popup to expand into -- when opted in via
|
|
601
|
+
// autoCommitSingleOption, the trigger commits it directly on activation (see
|
|
602
|
+
// onTriggerClick/onKeyDown) instead of opening the listbox, so it's exposed as a plain
|
|
603
|
+
// button rather than a combobox with a permanently-closed popup: no aria-haspopup/
|
|
604
|
+
// aria-expanded/aria-controls/aria-activedescendant (all meaningless without a popup that
|
|
605
|
+
// can ever appear) and no chevron. Without the opt-in (the default), this is always
|
|
606
|
+
// `false` and the normal combobox/listbox/chevron trigger renders regardless of option count.
|
|
607
|
+
const isSingleOption = this.autoCommitSingleOption && navigable.length === 1;
|
|
524
608
|
return html `
|
|
525
609
|
<div part="form-control">
|
|
526
610
|
<label part="form-control-label" for=${this.triggerId} ?hidden=${!hasLabel}>
|
|
@@ -536,6 +620,7 @@ export class LyraSelect extends LyraElement {
|
|
|
536
620
|
aria-controls=${isSingleOption ? nothing : this.listId}
|
|
537
621
|
aria-activedescendant=${isSingleOption ? nothing : activeId}
|
|
538
622
|
aria-label=${this.getAttribute('aria-label') || (hasLabel ? nothing : this.placeholder || 'Select')}
|
|
623
|
+
aria-describedby=${describedBy || nothing}
|
|
539
624
|
aria-required=${this.required ? 'true' : 'false'}
|
|
540
625
|
aria-invalid=${this.touched && !this.internals.validity.valid ? 'true' : 'false'}
|
|
541
626
|
?disabled=${this.effectiveDisabled}
|
|
@@ -557,10 +642,10 @@ export class LyraSelect extends LyraElement {
|
|
|
557
642
|
>
|
|
558
643
|
${this.renderRows(options, activeId)}
|
|
559
644
|
</div>
|
|
560
|
-
<div part="error" ?hidden=${!hasError}>
|
|
645
|
+
<div id="select-error" part="error" ?hidden=${!hasError}>
|
|
561
646
|
${this.errorText}<slot name="error" @slotchange=${this.onErrorSlotChange}></slot>
|
|
562
647
|
</div>
|
|
563
|
-
<div part="hint" ?hidden=${!hasHint}>
|
|
648
|
+
<div id="select-hint" part="hint" ?hidden=${!hasHint}>
|
|
564
649
|
${this.hint}<slot name="hint" @slotchange=${this.onHintSlotChange}></slot>
|
|
565
650
|
</div>
|
|
566
651
|
</div>
|
|
@@ -571,12 +656,6 @@ export class LyraSelect extends LyraElement {
|
|
|
571
656
|
__decorate([
|
|
572
657
|
property()
|
|
573
658
|
], LyraSelect.prototype, "placeholder", void 0);
|
|
574
|
-
__decorate([
|
|
575
|
-
property({ type: Boolean, reflect: true })
|
|
576
|
-
], LyraSelect.prototype, "disabled", void 0);
|
|
577
|
-
__decorate([
|
|
578
|
-
property({ type: Boolean, reflect: true })
|
|
579
|
-
], LyraSelect.prototype, "required", void 0);
|
|
580
659
|
__decorate([
|
|
581
660
|
property()
|
|
582
661
|
], LyraSelect.prototype, "label", void 0);
|
|
@@ -592,6 +671,9 @@ __decorate([
|
|
|
592
671
|
__decorate([
|
|
593
672
|
property({ reflect: true })
|
|
594
673
|
], LyraSelect.prototype, "size", void 0);
|
|
674
|
+
__decorate([
|
|
675
|
+
property({ type: Boolean, attribute: 'auto-commit-single-option' })
|
|
676
|
+
], LyraSelect.prototype, "autoCommitSingleOption", void 0);
|
|
595
677
|
__decorate([
|
|
596
678
|
state()
|
|
597
679
|
], LyraSelect.prototype, "activeIndex", void 0);
|
|
@@ -15,6 +15,9 @@ export declare class LyraSkeleton extends LyraElement {
|
|
|
15
15
|
effect: SkeletonEffect;
|
|
16
16
|
width?: string;
|
|
17
17
|
height?: string;
|
|
18
|
+
/** Accessible name announced via `role="status"`. Override with a
|
|
19
|
+
* description of what is actually loading (e.g. "Loading chart"). */
|
|
20
|
+
label: string;
|
|
18
21
|
protected willUpdate(): void;
|
|
19
22
|
protected updated(changed: PropertyValues): void;
|
|
20
23
|
render(): TemplateResult;
|
|
@@ -22,6 +22,9 @@ export class LyraSkeleton extends LyraElement {
|
|
|
22
22
|
super(...arguments);
|
|
23
23
|
this.variant = 'text';
|
|
24
24
|
this.effect = 'pulse';
|
|
25
|
+
/** Accessible name announced via `role="status"`. Override with a
|
|
26
|
+
* description of what is actually loading (e.g. "Loading chart"). */
|
|
27
|
+
this.label = 'Loading…';
|
|
25
28
|
}
|
|
26
29
|
static { this.styles = [LyraElement.styles, styles, srOnly]; }
|
|
27
30
|
willUpdate() {
|
|
@@ -44,7 +47,7 @@ export class LyraSkeleton extends LyraElement {
|
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
render() {
|
|
47
|
-
return html `<span part="base"><span class="sr-only"
|
|
50
|
+
return html `<span part="base"><span class="sr-only">${this.label}</span></span>`;
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
__decorate([
|
|
@@ -59,4 +62,7 @@ __decorate([
|
|
|
59
62
|
__decorate([
|
|
60
63
|
property()
|
|
61
64
|
], LyraSkeleton.prototype, "height", void 0);
|
|
65
|
+
__decorate([
|
|
66
|
+
property()
|
|
67
|
+
], LyraSkeleton.prototype, "label", void 0);
|
|
62
68
|
defineElement('skeleton', LyraSkeleton);
|
|
@@ -10,15 +10,13 @@ export const styles = css `
|
|
|
10
10
|
block-size: 100%;
|
|
11
11
|
background: var(--lyra-color-border);
|
|
12
12
|
}
|
|
13
|
-
:host([variant='text']) [part='base']
|
|
13
|
+
:host([variant='text']) [part='base'],
|
|
14
|
+
:host([variant='rect']) [part='base'] {
|
|
14
15
|
border-radius: var(--lyra-radius);
|
|
15
16
|
}
|
|
16
17
|
:host([variant='circle']) [part='base'] {
|
|
17
18
|
border-radius: 50%;
|
|
18
19
|
}
|
|
19
|
-
:host([variant='rect']) [part='base'] {
|
|
20
|
-
border-radius: var(--lyra-radius);
|
|
21
|
-
}
|
|
22
20
|
:host([effect='pulse']) [part='base'] {
|
|
23
21
|
animation: lyra-skeleton-pulse 1.5s ease-in-out infinite;
|
|
24
22
|
}
|
|
@@ -53,5 +51,8 @@ export const styles = css `
|
|
|
53
51
|
[part='base'] {
|
|
54
52
|
animation: none !important;
|
|
55
53
|
}
|
|
54
|
+
:host([effect='sheen']) [part='base'] {
|
|
55
|
+
background-image: none;
|
|
56
|
+
}
|
|
56
57
|
}
|
|
57
58
|
`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type TemplateResult
|
|
1
|
+
import { type TemplateResult } from 'lit';
|
|
2
2
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
3
|
declare const LyraSlider_base: typeof LyraElement & (new (...args: any[]) => import("../../internal/form-associated.js").FormAssociatedInterface);
|
|
4
4
|
/**
|
|
@@ -17,6 +17,10 @@ declare const LyraSlider_base: typeof LyraElement & (new (...args: any[]) => imp
|
|
|
17
17
|
* to block submission before that default lands, matching how `required`
|
|
18
18
|
* isn't a meaningful constraint on a native range input either.
|
|
19
19
|
*
|
|
20
|
+
* Clicking anywhere on the track (not just the 16px thumb) jumps the thumb
|
|
21
|
+
* to that point and continues the same gesture as a drag, matching native
|
|
22
|
+
* `<input type=range>` click-to-seek.
|
|
23
|
+
*
|
|
20
24
|
* @customElement lyra-slider
|
|
21
25
|
* @event lyra-input - Fired continuously during an active drag or a
|
|
22
26
|
* keyboard step (including OS key-repeat while a key is held), mirroring
|
|
@@ -34,9 +38,30 @@ declare const LyraSlider_base: typeof LyraElement & (new (...args: any[]) => imp
|
|
|
34
38
|
*/
|
|
35
39
|
export declare class LyraSlider extends LyraSlider_base {
|
|
36
40
|
static styles: import("lit").CSSResultGroup[];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
static properties: {
|
|
42
|
+
min: {
|
|
43
|
+
type: NumberConstructor;
|
|
44
|
+
noAccessor: boolean;
|
|
45
|
+
};
|
|
46
|
+
max: {
|
|
47
|
+
type: NumberConstructor;
|
|
48
|
+
noAccessor: boolean;
|
|
49
|
+
};
|
|
50
|
+
step: {
|
|
51
|
+
type: NumberConstructor;
|
|
52
|
+
noAccessor: boolean;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
private _min;
|
|
56
|
+
private _max;
|
|
57
|
+
private _step;
|
|
58
|
+
private pendingValue;
|
|
59
|
+
get min(): number;
|
|
60
|
+
set min(next: number);
|
|
61
|
+
get max(): number;
|
|
62
|
+
set max(next: number);
|
|
63
|
+
get step(): number;
|
|
64
|
+
set step(next: number);
|
|
40
65
|
/** Accessible name for the slider, used when no visible label context
|
|
41
66
|
* exists around it (e.g. no wrapping `<label>` or adjacent heading). Set
|
|
42
67
|
* as `aria-label` on the interactive `role="slider"` element. A plain
|
|
@@ -51,6 +76,8 @@ export declare class LyraSlider extends LyraSlider_base {
|
|
|
51
76
|
* boolean converter checks). */
|
|
52
77
|
showValue: boolean;
|
|
53
78
|
private activePointers;
|
|
79
|
+
private changedPointers;
|
|
80
|
+
private keyboardChanged;
|
|
54
81
|
connectedCallback(): void;
|
|
55
82
|
disconnectedCallback(): void;
|
|
56
83
|
/** The numeric counterpart of `value`, mirroring native `<input
|
|
@@ -61,10 +88,20 @@ export declare class LyraSlider extends LyraSlider_base {
|
|
|
61
88
|
* back into `value`. */
|
|
62
89
|
get valueAsNumber(): number;
|
|
63
90
|
set valueAsNumber(next: number);
|
|
91
|
+
/**
|
|
92
|
+
* `FormAssociated` provides the form plumbing; this override adds the
|
|
93
|
+
* slider's native-range sanitization at the IDL boundary so invalid direct
|
|
94
|
+
* assignments cannot briefly submit a literal `NaN`/`Infinity`.
|
|
95
|
+
*/
|
|
96
|
+
get value(): string;
|
|
97
|
+
set value(next: string);
|
|
98
|
+
formResetCallback(): void;
|
|
64
99
|
/** If `value` is still unset, seed it with the sanitized default — the
|
|
65
100
|
* midpoint of `[min, max]`, snapped to `step` — so `value`/`valueAsNumber`
|
|
66
101
|
* and rendering never have to treat "" as a real, distinct state. */
|
|
67
102
|
private ensureValue;
|
|
103
|
+
/** Re-sanitize an already assigned value immediately after range settings change. */
|
|
104
|
+
private sanitizeCurrentValue;
|
|
68
105
|
private domain;
|
|
69
106
|
private defaultNumericValue;
|
|
70
107
|
private percentOf;
|
|
@@ -73,12 +110,27 @@ export declare class LyraSlider extends LyraSlider_base {
|
|
|
73
110
|
private setValue;
|
|
74
111
|
private onKeyDown;
|
|
75
112
|
private onKeyUp;
|
|
113
|
+
/** Start tracking `pointerId` as an active drag, transferring pointer
|
|
114
|
+
* capture to `captureTarget` and wiring the shared window-level move/end
|
|
115
|
+
* listeners. Shared by a pointerdown that starts on the thumb itself and
|
|
116
|
+
* one that starts elsewhere on the track (see `onBasePointerDown`), so
|
|
117
|
+
* both gestures continue identically from here on. */
|
|
118
|
+
private beginDrag;
|
|
76
119
|
private onPointerDown;
|
|
120
|
+
/** A pointerdown anywhere on `[part="base"]` other than the thumb itself
|
|
121
|
+
* (the vast majority of the control's clickable area) jumps the thumb to
|
|
122
|
+
* that point and continues the same gesture as a drag, mirroring native
|
|
123
|
+
* `<input type=range>` click-to-seek. A pointerdown that started on the
|
|
124
|
+
* thumb bubbles up to this same listener too — already fully handled by
|
|
125
|
+
* `onPointerDown` above, so it's ignored here via the `e.target === thumb`
|
|
126
|
+
* check. Unlike the two-handle `lyra-time-range` (where a track click is
|
|
127
|
+
* ambiguous about which handle should move), a single thumb has no such
|
|
128
|
+
* ambiguity. */
|
|
129
|
+
private onBasePointerDown;
|
|
77
130
|
private onPointerMove;
|
|
78
131
|
private onPointerUp;
|
|
79
132
|
/** Stop the drag owned by `pointerId`, optionally committing a final lyra-change. */
|
|
80
133
|
private endDrag;
|
|
81
|
-
protected willUpdate(changed: PropertyValues): void;
|
|
82
134
|
render(): TemplateResult;
|
|
83
135
|
}
|
|
84
136
|
declare global {
|