@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, closeIcon } from '../../internal/icons.js';
|
|
14
|
+
import { AnchoredValidityController, VALIDITY_ANCHOR } from '../../internal/anchored-validity.js';
|
|
14
15
|
import { styles } from './combobox.styles.js';
|
|
15
16
|
import { LyraOption } from './option.js';
|
|
16
17
|
import './option.js';
|
|
@@ -26,8 +27,11 @@ import './option.js';
|
|
|
26
27
|
* @slot label - Custom label content.
|
|
27
28
|
* @slot hint - Custom hint content.
|
|
28
29
|
* @slot error - Custom error content.
|
|
29
|
-
* @event change - The selection changed.
|
|
30
|
-
*
|
|
30
|
+
* @event {Event} change - The selection changed through user interaction. A bubbling,
|
|
31
|
+
* composed, non-cancelable Event.
|
|
32
|
+
* @event {InputEvent | Event} input - The user typed in the filter or changed the selection. Text
|
|
33
|
+
* edits expose the original InputEvent; selection changes emit a bubbling,
|
|
34
|
+
* composed, non-cancelable Event.
|
|
31
35
|
* @event lyra-show - The listbox opened.
|
|
32
36
|
* @event lyra-hide - The listbox closed.
|
|
33
37
|
* @event lyra-clear - The value was cleared.
|
|
@@ -53,15 +57,15 @@ export class LyraCombobox extends LyraElement {
|
|
|
53
57
|
static { this.formAssociated = true; }
|
|
54
58
|
static { this.styles = [LyraElement.styles, styles]; }
|
|
55
59
|
static { this.properties = {
|
|
60
|
+
multiple: { type: Boolean, reflect: true, noAccessor: true },
|
|
61
|
+
disabled: { type: Boolean, reflect: true, noAccessor: true },
|
|
62
|
+
required: { type: Boolean, reflect: true, noAccessor: true },
|
|
56
63
|
value: { noAccessor: true },
|
|
57
64
|
name: { reflect: true, noAccessor: true },
|
|
58
65
|
}; }
|
|
59
66
|
constructor() {
|
|
60
67
|
super();
|
|
61
|
-
this.multiple = false;
|
|
62
68
|
this.placeholder = '';
|
|
63
|
-
this.disabled = false;
|
|
64
|
-
this.required = false;
|
|
65
69
|
this.label = '';
|
|
66
70
|
this.hint = '';
|
|
67
71
|
this.errorText = '';
|
|
@@ -69,6 +73,10 @@ export class LyraCombobox extends LyraElement {
|
|
|
69
73
|
this.withClear = false;
|
|
70
74
|
this.maxOptionsVisible = 3;
|
|
71
75
|
this.emptyText = 'No results';
|
|
76
|
+
/** Status copy shown in the listbox while a `source` fetch is in flight. */
|
|
77
|
+
this.loadingText = 'Loading…';
|
|
78
|
+
/** Status copy shown when `maxRender` caps the row list; `{n}` is replaced with the hidden count. */
|
|
79
|
+
this.overflowText = '+{n} more — refine your search';
|
|
72
80
|
this.filter = null;
|
|
73
81
|
this.source = null;
|
|
74
82
|
this.maxRender = 200;
|
|
@@ -91,6 +99,11 @@ export class LyraCombobox extends LyraElement {
|
|
|
91
99
|
this.loading = false;
|
|
92
100
|
this.asyncRows = [];
|
|
93
101
|
this.sourceToken = 0;
|
|
102
|
+
// Guards the proactive `asyncRows` warm-up in `willUpdate()` below so it
|
|
103
|
+
// fires at most once per mount instead of re-running (and endlessly
|
|
104
|
+
// resetting the debounce timer) on every subsequent render while the fetch
|
|
105
|
+
// is still in flight.
|
|
106
|
+
this._sourceWarmed = false;
|
|
94
107
|
this._selectedLabelCache = new Map();
|
|
95
108
|
// Rebuilt once per render (in render(), before renderRows()) from the
|
|
96
109
|
// currently-visible row set -- backs the delegated listbox click/mousedown
|
|
@@ -106,6 +119,9 @@ export class LyraCombobox extends LyraElement {
|
|
|
106
119
|
this.inputId = nextId('combobox-input');
|
|
107
120
|
this._isFirstUpdate = true;
|
|
108
121
|
this._selected = [];
|
|
122
|
+
this._multiple = false;
|
|
123
|
+
this._disabled = false;
|
|
124
|
+
this._required = false;
|
|
109
125
|
// What `form.reset()` restores to. Captured exactly once, from whatever
|
|
110
126
|
// `<lyra-option selected>` markup was present the first time slotted
|
|
111
127
|
// options are collected (mirrors native `<select><option selected>`) —
|
|
@@ -116,6 +132,9 @@ export class LyraCombobox extends LyraElement {
|
|
|
116
132
|
// property assignment never does).
|
|
117
133
|
this._defaultSelected = [];
|
|
118
134
|
this._defaultCaptured = false;
|
|
135
|
+
// A restored value must win over declarative selected markup collected by
|
|
136
|
+
// the first asynchronous slotchange. Cleared by the next ordinary value write.
|
|
137
|
+
this._restoredStateActive = false;
|
|
119
138
|
// Hand-written accessor (mirrors the `value` accessor below, and Task 2's
|
|
120
139
|
// `FormAssociated.name` in `../../internal/form-associated.ts`): a
|
|
121
140
|
// form-associated custom element's submitted entry name is resolved by the
|
|
@@ -142,7 +161,7 @@ export class LyraCombobox extends LyraElement {
|
|
|
142
161
|
// after the user has picked something.
|
|
143
162
|
const declared = this.options.filter((o) => o.selected).map((o) => o.value);
|
|
144
163
|
this._defaultSelected = [...declared];
|
|
145
|
-
if (declared.length) {
|
|
164
|
+
if (declared.length && !this._restoredStateActive) {
|
|
146
165
|
this.value = this.multiple ? declared : declared[0];
|
|
147
166
|
return; // `value=`'s setter already called reflectSelected()
|
|
148
167
|
}
|
|
@@ -154,7 +173,7 @@ export class LyraCombobox extends LyraElement {
|
|
|
154
173
|
// into the live selection instead of letting reflectSelected() below
|
|
155
174
|
// strip their `selected` attribute back off.
|
|
156
175
|
const newlySelected = this.options.filter((o) => !previous.has(o) && o.selected).map((o) => o.value);
|
|
157
|
-
if (newlySelected.length) {
|
|
176
|
+
if (newlySelected.length && !this._restoredStateActive) {
|
|
158
177
|
this.value = this.multiple
|
|
159
178
|
? [...new Set([...this._selected, ...newlySelected])]
|
|
160
179
|
: newlySelected[newlySelected.length - 1];
|
|
@@ -181,7 +200,6 @@ export class LyraCombobox extends LyraElement {
|
|
|
181
200
|
this.show();
|
|
182
201
|
if (this.source)
|
|
183
202
|
this.runSource(this.query);
|
|
184
|
-
this.emit('input');
|
|
185
203
|
};
|
|
186
204
|
this.onInputBlur = () => {
|
|
187
205
|
this.touched = true;
|
|
@@ -273,6 +291,26 @@ export class LyraCombobox extends LyraElement {
|
|
|
273
291
|
this.pickRow(row);
|
|
274
292
|
};
|
|
275
293
|
this.internals = this.attachInternals();
|
|
294
|
+
this.validityController = new AnchoredValidityController(this, this.internals, () => this[VALIDITY_ANCHOR]());
|
|
295
|
+
}
|
|
296
|
+
get form() {
|
|
297
|
+
return this.internals.form;
|
|
298
|
+
}
|
|
299
|
+
get labels() {
|
|
300
|
+
return this.internals.labels;
|
|
301
|
+
}
|
|
302
|
+
get validity() {
|
|
303
|
+
return this.internals.validity;
|
|
304
|
+
}
|
|
305
|
+
get validationMessage() {
|
|
306
|
+
return this.internals.validationMessage;
|
|
307
|
+
}
|
|
308
|
+
get willValidate() {
|
|
309
|
+
return this.internals.willValidate;
|
|
310
|
+
}
|
|
311
|
+
/** @internal */
|
|
312
|
+
[VALIDITY_ANCHOR]() {
|
|
313
|
+
return this.renderRoot?.querySelector('[part="combobox-input"]') ?? null;
|
|
276
314
|
}
|
|
277
315
|
connectedCallback() {
|
|
278
316
|
super.connectedCallback();
|
|
@@ -289,6 +327,16 @@ export class LyraCombobox extends LyraElement {
|
|
|
289
327
|
this.hasErrorSlot = Array.from(this.children).some((el) => el.getAttribute('slot') === 'error');
|
|
290
328
|
this.hasLabelSlot = Array.from(this.children).some((el) => el.getAttribute('slot') === 'label');
|
|
291
329
|
}
|
|
330
|
+
// In source (async) mode, `labelFor()` can only resolve a programmatically
|
|
331
|
+
// -set value's label from `asyncRows` -- and nothing normally populates
|
|
332
|
+
// `asyncRows` until the listbox is actually opened. Fire the fetch once,
|
|
333
|
+
// independent of `open`, so the closed input / multi-select tag chips can
|
|
334
|
+
// already show the real label the very first time they render (the
|
|
335
|
+
// common "edit an existing record" case) instead of the raw value string.
|
|
336
|
+
if (!this._sourceWarmed && this.source && this._selected.length && this.asyncRows.length === 0) {
|
|
337
|
+
this._sourceWarmed = true;
|
|
338
|
+
this.runSource('');
|
|
339
|
+
}
|
|
292
340
|
}
|
|
293
341
|
get name() {
|
|
294
342
|
return this._name;
|
|
@@ -302,14 +350,47 @@ export class LyraCombobox extends LyraElement {
|
|
|
302
350
|
else {
|
|
303
351
|
this.removeAttribute('name');
|
|
304
352
|
}
|
|
353
|
+
this.syncFormValue();
|
|
305
354
|
this.requestUpdate('name', old);
|
|
306
355
|
}
|
|
356
|
+
get multiple() {
|
|
357
|
+
return this._multiple;
|
|
358
|
+
}
|
|
359
|
+
set multiple(next) {
|
|
360
|
+
const old = this._multiple;
|
|
361
|
+
this._multiple = Boolean(next);
|
|
362
|
+
this.toggleAttribute('multiple', this._multiple);
|
|
363
|
+
this.syncFormValue();
|
|
364
|
+
this.requestUpdate('multiple', old);
|
|
365
|
+
}
|
|
366
|
+
get disabled() {
|
|
367
|
+
return this._disabled;
|
|
368
|
+
}
|
|
369
|
+
set disabled(next) {
|
|
370
|
+
const old = this._disabled;
|
|
371
|
+
this._disabled = Boolean(next);
|
|
372
|
+
this.toggleAttribute('disabled', this._disabled);
|
|
373
|
+
if (this._disabled)
|
|
374
|
+
this.hide();
|
|
375
|
+
this.requestUpdate('disabled', old);
|
|
376
|
+
}
|
|
377
|
+
get required() {
|
|
378
|
+
return this._required;
|
|
379
|
+
}
|
|
380
|
+
set required(next) {
|
|
381
|
+
const old = this._required;
|
|
382
|
+
this._required = Boolean(next);
|
|
383
|
+
this.toggleAttribute('required', this._required);
|
|
384
|
+
this.updateValidity();
|
|
385
|
+
this.requestUpdate('required', old);
|
|
386
|
+
}
|
|
307
387
|
/** The selected value(s): a string in single mode, a string[] in `multiple` mode. */
|
|
308
388
|
get value() {
|
|
309
389
|
return this.multiple ? [...this._selected] : (this._selected[0] ?? '');
|
|
310
390
|
}
|
|
311
391
|
set value(next) {
|
|
312
392
|
const old = this._selected;
|
|
393
|
+
this._restoredStateActive = false;
|
|
313
394
|
this._selected = Array.isArray(next) ? [...next] : next ? [next] : [];
|
|
314
395
|
this.syncFormValue();
|
|
315
396
|
this.reflectSelected();
|
|
@@ -318,13 +399,14 @@ export class LyraCombobox extends LyraElement {
|
|
|
318
399
|
}
|
|
319
400
|
updateValidity() {
|
|
320
401
|
if (this.required && this._selected.length === 0) {
|
|
321
|
-
this.
|
|
402
|
+
this.validityController.setValidity({ valueMissing: true }, 'Please select an option.');
|
|
322
403
|
}
|
|
323
404
|
else {
|
|
324
|
-
this.
|
|
405
|
+
this.validityController.setValidity({});
|
|
325
406
|
}
|
|
326
407
|
}
|
|
327
408
|
syncFormValue() {
|
|
409
|
+
const state = JSON.stringify(this._selected);
|
|
328
410
|
if (this.multiple) {
|
|
329
411
|
// A FormData form value submits under the keys baked into the FormData
|
|
330
412
|
// itself, bypassing the element's own `name` the way a plain string
|
|
@@ -333,16 +415,16 @@ export class LyraCombobox extends LyraElement {
|
|
|
333
415
|
// inventing a shared key that would merge with any other unnamed
|
|
334
416
|
// combobox in the same form.
|
|
335
417
|
if (!this.name) {
|
|
336
|
-
this.internals.setFormValue(null);
|
|
418
|
+
this.internals.setFormValue(null, state);
|
|
337
419
|
return;
|
|
338
420
|
}
|
|
339
421
|
const fd = new FormData();
|
|
340
422
|
for (const v of this._selected)
|
|
341
423
|
fd.append(this.name, v);
|
|
342
|
-
this.internals.setFormValue(fd);
|
|
424
|
+
this.internals.setFormValue(fd, state);
|
|
343
425
|
}
|
|
344
426
|
else {
|
|
345
|
-
this.internals.setFormValue(this._selected[0] ?? '');
|
|
427
|
+
this.internals.setFormValue(this._selected[0] ?? '', state);
|
|
346
428
|
}
|
|
347
429
|
}
|
|
348
430
|
/** Effective disabled state: this element's own `disabled` OR an ancestor
|
|
@@ -355,6 +437,21 @@ export class LyraCombobox extends LyraElement {
|
|
|
355
437
|
this.value = [...this._defaultSelected];
|
|
356
438
|
this.query = '';
|
|
357
439
|
}
|
|
440
|
+
formStateRestoreCallback(state, _mode) {
|
|
441
|
+
let selected = [];
|
|
442
|
+
if (typeof state === 'string') {
|
|
443
|
+
try {
|
|
444
|
+
const parsed = JSON.parse(state);
|
|
445
|
+
if (Array.isArray(parsed) && parsed.every((value) => typeof value === 'string'))
|
|
446
|
+
selected = parsed;
|
|
447
|
+
}
|
|
448
|
+
catch {
|
|
449
|
+
// Malformed persisted state restores an empty selection.
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
this.value = this.multiple ? selected : (selected[0] ?? '');
|
|
453
|
+
this._restoredStateActive = true;
|
|
454
|
+
}
|
|
358
455
|
/**
|
|
359
456
|
* Called by the browser when an ancestor `<fieldset disabled>` toggles.
|
|
360
457
|
* Tracked separately from the consumer's own `disabled` (see
|
|
@@ -363,6 +460,8 @@ export class LyraCombobox extends LyraElement {
|
|
|
363
460
|
*/
|
|
364
461
|
formDisabledCallback(disabled) {
|
|
365
462
|
this._fieldsetDisabled = disabled;
|
|
463
|
+
if (disabled)
|
|
464
|
+
this.hide();
|
|
366
465
|
this.requestUpdate();
|
|
367
466
|
}
|
|
368
467
|
checkValidity() {
|
|
@@ -390,7 +489,17 @@ export class LyraCombobox extends LyraElement {
|
|
|
390
489
|
o.selected = sel.has(o.value);
|
|
391
490
|
}
|
|
392
491
|
labelFor(value) {
|
|
393
|
-
|
|
492
|
+
// Checked in order: an explicit pick's own label (works even after the
|
|
493
|
+
// source rows backing it have since changed), a slotted `<lyra-option>`
|
|
494
|
+
// (local mode), then the last-fetched async row set (source mode) -- a
|
|
495
|
+
// value set programmatically (e.g. `el.value = 'b'` before the listbox
|
|
496
|
+
// has ever been opened) has no chance to have populated the first two,
|
|
497
|
+
// so without this last fallback it would render as the raw value string
|
|
498
|
+
// instead of its label.
|
|
499
|
+
return (this._selectedLabelCache.get(value) ??
|
|
500
|
+
this.options.find((o) => o.value === value)?.label ??
|
|
501
|
+
this.asyncRows.find((r) => r.value === value)?.label ??
|
|
502
|
+
value);
|
|
394
503
|
}
|
|
395
504
|
/** The current row set in a source-agnostic shape, before capping. */
|
|
396
505
|
get effectiveRows() {
|
|
@@ -410,15 +519,27 @@ export class LyraCombobox extends LyraElement {
|
|
|
410
519
|
const all = this.effectiveRows;
|
|
411
520
|
if (all.length <= this.maxRender)
|
|
412
521
|
return { rows: all, overflow: 0 };
|
|
522
|
+
const originalIndex = new Map(all.map((r, i) => [r, i]));
|
|
413
523
|
const capped = all.slice(0, this.maxRender);
|
|
414
524
|
const cappedValues = new Set(capped.map((r) => r.value));
|
|
525
|
+
let appendedOutOfCap = false;
|
|
415
526
|
for (const v of this._selected) {
|
|
416
527
|
if (!cappedValues.has(v)) {
|
|
417
528
|
const selectedRow = all.find((r) => r.value === v);
|
|
418
|
-
if (selectedRow)
|
|
529
|
+
if (selectedRow) {
|
|
419
530
|
capped.push(selectedRow);
|
|
531
|
+
appendedOutOfCap = true;
|
|
532
|
+
}
|
|
420
533
|
}
|
|
421
534
|
}
|
|
535
|
+
if (appendedOutOfCap) {
|
|
536
|
+
// A preserved out-of-cap selection was just tacked onto the very end,
|
|
537
|
+
// regardless of its own `group` -- stable-sort back by each row's
|
|
538
|
+
// original position so it lands among its own group's other rows
|
|
539
|
+
// instead of forcing renderRows() to emit that group's label a second
|
|
540
|
+
// time after whatever group happens to trail the cap.
|
|
541
|
+
capped.sort((a, b) => originalIndex.get(a) - originalIndex.get(b));
|
|
542
|
+
}
|
|
422
543
|
return { rows: capped, overflow: all.length - capped.length };
|
|
423
544
|
}
|
|
424
545
|
get filtered() {
|
|
@@ -446,6 +567,15 @@ export class LyraCombobox extends LyraElement {
|
|
|
446
567
|
return;
|
|
447
568
|
this.open = false;
|
|
448
569
|
this.activeIndex = -1;
|
|
570
|
+
// Single-select mode only shows `query` while `open` (see `displayValue`
|
|
571
|
+
// above) -- but dismissing without picking a row (blur, Escape, or an
|
|
572
|
+
// outside click) previously left an abandoned filter string sitting in
|
|
573
|
+
// `query` forever, so the *next* reopen would reappear with stale text
|
|
574
|
+
// and re-filter the list from it. Multiple mode is unaffected: its input
|
|
575
|
+
// always shows `query` regardless of `open`, by design (a persistent
|
|
576
|
+
// search box next to the tags).
|
|
577
|
+
if (!this.multiple)
|
|
578
|
+
this.query = '';
|
|
449
579
|
}
|
|
450
580
|
updated(changed) {
|
|
451
581
|
if (changed.has('open')) {
|
|
@@ -476,17 +606,25 @@ export class LyraCombobox extends LyraElement {
|
|
|
476
606
|
this.emit('lyra-hide');
|
|
477
607
|
}
|
|
478
608
|
}
|
|
479
|
-
if (changed.has('
|
|
480
|
-
this.updateValidity();
|
|
481
|
-
if (changed.has('name') || changed.has('multiple'))
|
|
609
|
+
if (changed.has('name'))
|
|
482
610
|
this.syncFormValue();
|
|
483
611
|
if (changed.has('touched') || changed.has('required') || changed.has('value')) {
|
|
484
612
|
this.toggleAttribute('data-invalid', this.touched && !this.internals.validity.valid);
|
|
485
613
|
}
|
|
486
614
|
}
|
|
615
|
+
/** Dispatches the platform-style value-event pair used by non-text user
|
|
616
|
+
* interactions. Text editing keeps and exposes the original InputEvent
|
|
617
|
+
* from the shadow input so its data/inputType metadata is not lost. */
|
|
618
|
+
emitValueEvents() {
|
|
619
|
+
const EventConstructor = this.ownerDocument.defaultView?.Event ?? Event;
|
|
620
|
+
const init = { bubbles: true, composed: true };
|
|
621
|
+
this.dispatchEvent(new EventConstructor('input', init));
|
|
622
|
+
this.dispatchEvent(new EventConstructor('change', init));
|
|
623
|
+
}
|
|
487
624
|
pickRow(row) {
|
|
488
|
-
if (row.disabled)
|
|
625
|
+
if (this.effectiveDisabled || row.disabled)
|
|
489
626
|
return;
|
|
627
|
+
const selectionChanged = this.multiple || this._selected[0] !== row.value;
|
|
490
628
|
this._selectedLabelCache.set(row.value, row.label);
|
|
491
629
|
if (this.multiple) {
|
|
492
630
|
const set = new Set(this._selected);
|
|
@@ -505,20 +643,25 @@ export class LyraCombobox extends LyraElement {
|
|
|
505
643
|
// mode) matches the now-empty input instead of the stale prior query.
|
|
506
644
|
if (this.source)
|
|
507
645
|
this.runSource(this.query);
|
|
508
|
-
|
|
509
|
-
|
|
646
|
+
if (selectionChanged)
|
|
647
|
+
this.emitValueEvents();
|
|
510
648
|
}
|
|
511
649
|
removeValue(value) {
|
|
512
|
-
|
|
513
|
-
this.
|
|
650
|
+
const next = this._selected.filter((v) => v !== value);
|
|
651
|
+
if (next.length === this._selected.length)
|
|
652
|
+
return;
|
|
653
|
+
this.value = next;
|
|
654
|
+
this.emitValueEvents();
|
|
514
655
|
}
|
|
515
656
|
clear() {
|
|
657
|
+
if (this._selected.length === 0)
|
|
658
|
+
return;
|
|
516
659
|
this.value = [];
|
|
517
660
|
this.query = '';
|
|
518
661
|
if (this.source)
|
|
519
662
|
this.runSource(this.query);
|
|
663
|
+
this.emitValueEvents();
|
|
520
664
|
this.emit('lyra-clear');
|
|
521
|
-
this.emit('change');
|
|
522
665
|
}
|
|
523
666
|
runSource(query) {
|
|
524
667
|
if (!this.source)
|
|
@@ -662,12 +805,12 @@ export class LyraCombobox extends LyraElement {
|
|
|
662
805
|
@click=${this.onListboxClick}
|
|
663
806
|
>
|
|
664
807
|
${this.loading
|
|
665
|
-
? html `<div class="loading" role="option" aria-selected="false" aria-disabled="true"
|
|
808
|
+
? html `<div class="loading" role="option" aria-selected="false" aria-disabled="true">${this.loadingText}</div>`
|
|
666
809
|
: rows.length === 0
|
|
667
810
|
? html `<div class="empty" role="option" aria-selected="false" aria-disabled="true">${this.emptyText}</div>`
|
|
668
811
|
: html `${this.renderRows(rows, activeId)}
|
|
669
812
|
${overflow > 0
|
|
670
|
-
? html `<div part="option-overflow"
|
|
813
|
+
? html `<div part="option-overflow">${this.overflowText.replace('{n}', String(overflow))}</div>`
|
|
671
814
|
: ''}`}
|
|
672
815
|
</div>
|
|
673
816
|
<div id="combobox-error" part="error" ?hidden=${!hasError}>
|
|
@@ -681,18 +824,9 @@ export class LyraCombobox extends LyraElement {
|
|
|
681
824
|
`;
|
|
682
825
|
}
|
|
683
826
|
}
|
|
684
|
-
__decorate([
|
|
685
|
-
property({ type: Boolean, reflect: true })
|
|
686
|
-
], LyraCombobox.prototype, "multiple", void 0);
|
|
687
827
|
__decorate([
|
|
688
828
|
property()
|
|
689
829
|
], LyraCombobox.prototype, "placeholder", void 0);
|
|
690
|
-
__decorate([
|
|
691
|
-
property({ type: Boolean, reflect: true })
|
|
692
|
-
], LyraCombobox.prototype, "disabled", void 0);
|
|
693
|
-
__decorate([
|
|
694
|
-
property({ type: Boolean, reflect: true })
|
|
695
|
-
], LyraCombobox.prototype, "required", void 0);
|
|
696
830
|
__decorate([
|
|
697
831
|
property()
|
|
698
832
|
], LyraCombobox.prototype, "label", void 0);
|
|
@@ -714,6 +848,12 @@ __decorate([
|
|
|
714
848
|
__decorate([
|
|
715
849
|
property({ attribute: 'empty-text' })
|
|
716
850
|
], LyraCombobox.prototype, "emptyText", void 0);
|
|
851
|
+
__decorate([
|
|
852
|
+
property({ attribute: 'loading-text' })
|
|
853
|
+
], LyraCombobox.prototype, "loadingText", void 0);
|
|
854
|
+
__decorate([
|
|
855
|
+
property({ attribute: 'overflow-text' })
|
|
856
|
+
], LyraCombobox.prototype, "overflowText", void 0);
|
|
717
857
|
__decorate([
|
|
718
858
|
property({ attribute: false })
|
|
719
859
|
], LyraCombobox.prototype, "filter", void 0);
|
|
@@ -111,11 +111,11 @@ export const styles = css `
|
|
|
111
111
|
position: fixed;
|
|
112
112
|
z-index: 900;
|
|
113
113
|
box-sizing: border-box;
|
|
114
|
-
max-block-size: 18rem;
|
|
114
|
+
max-block-size: min(18rem, var(--lyra-positioner-available-block-size, 18rem));
|
|
115
115
|
overflow-y: auto;
|
|
116
116
|
inline-size: max-content;
|
|
117
|
-
min-inline-size: 12rem;
|
|
118
|
-
max-inline-size: min(92vw, 28rem);
|
|
117
|
+
min-inline-size: min(12rem, var(--lyra-positioner-available-inline-size, 12rem));
|
|
118
|
+
max-inline-size: min(92vw, 28rem, var(--lyra-positioner-available-inline-size, 100vw));
|
|
119
119
|
padding: var(--lyra-space-xs);
|
|
120
120
|
background: var(--lyra-color-surface);
|
|
121
121
|
border: 1px solid var(--lyra-color-border);
|
|
@@ -9,15 +9,19 @@ import { property } from 'lit/decorators.js';
|
|
|
9
9
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
10
10
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
11
11
|
import { defineElement } from '../../internal/prefix.js';
|
|
12
|
+
import { finiteNumber } from '../../internal/numbers.js';
|
|
12
13
|
import { styles } from './context-meter.styles.js';
|
|
13
|
-
// Ring geometry
|
|
14
|
-
//
|
|
14
|
+
// Ring geometry: RADIUS/CENTER match lyra-gauge's radial numbers, so both
|
|
15
|
+
// components' rings sit on the same circle within their viewBox. STROKE is
|
|
16
|
+
// intentionally heavier than the gauge's (12 vs. 10) -- tightly-packed
|
|
17
|
+
// multi-tone arcs need more width to stay visually distinct than a gauge's
|
|
18
|
+
// single fill arc, so it isn't shared.
|
|
15
19
|
const RADIUS = 40;
|
|
16
20
|
const CENTER = 50;
|
|
17
21
|
const STROKE = 12;
|
|
18
22
|
const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
19
23
|
function formatCount(n) {
|
|
20
|
-
return
|
|
24
|
+
return Math.round(finiteNumber(n, 0)).toLocaleString();
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* `<lyra-context-meter>` — a segmented occupancy meter (bar or ring) for
|
|
@@ -50,19 +54,19 @@ export class LyraContextMeter extends LyraElement {
|
|
|
50
54
|
static { this.styles = [LyraElement.styles, styles]; }
|
|
51
55
|
/** Sum of segment values, clamped so a negative/NaN entry can't produce a negative total. */
|
|
52
56
|
get usedTotal() {
|
|
53
|
-
return this.segments.reduce((sum, s) => sum +
|
|
57
|
+
return this.segments.reduce((sum, s) => sum + Math.max(0, finiteNumber(s.value, 0)), 0);
|
|
54
58
|
}
|
|
55
59
|
/** Per-segment ratio of `value` to `total`, clamped to [0,1] and capped so the
|
|
56
60
|
* running sum across all segments never overflows past 1 — a `segments` array
|
|
57
61
|
* that sums to more than `total` still renders a fully (not over-) filled meter. */
|
|
58
62
|
ratios() {
|
|
59
|
-
const total =
|
|
63
|
+
const total = Math.max(0, finiteNumber(this.total, 0));
|
|
60
64
|
if (total <= 0)
|
|
61
65
|
return [];
|
|
62
66
|
const out = [];
|
|
63
67
|
let cumulative = 0;
|
|
64
68
|
for (const segment of this.segments) {
|
|
65
|
-
const raw =
|
|
69
|
+
const raw = Math.max(0, finiteNumber(segment.value, 0));
|
|
66
70
|
const available = Math.max(0, 1 - cumulative);
|
|
67
71
|
const ratio = Math.min(raw / total, available);
|
|
68
72
|
cumulative += ratio;
|
|
@@ -71,8 +75,13 @@ export class LyraContextMeter extends LyraElement {
|
|
|
71
75
|
return out;
|
|
72
76
|
}
|
|
73
77
|
get summary() {
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
// Clamp the announced figure the same way ratios() clamps the visual fill --
|
|
79
|
+
// a segments array that sums past total must not report an impossible
|
|
80
|
+
// "160 of 100 used" to assistive tech while the bar/ring visibly caps at 100%.
|
|
81
|
+
const totalValue = Math.max(0, finiteNumber(this.total, 0));
|
|
82
|
+
const usedForSummary = totalValue > 0 ? Math.min(this.usedTotal, totalValue) : this.usedTotal;
|
|
83
|
+
const used = formatCount(usedForSummary);
|
|
84
|
+
const total = totalValue > 0 ? formatCount(totalValue) : null;
|
|
76
85
|
const phrase = total ? `${used} of ${total} used` : `${used} used`;
|
|
77
86
|
return this.label ? `${this.label} — ${phrase}` : phrase;
|
|
78
87
|
}
|
|
@@ -67,9 +67,6 @@ export const styles = css `
|
|
|
67
67
|
[part='segment'][data-tone='danger'] {
|
|
68
68
|
background: var(--lyra-color-danger);
|
|
69
69
|
}
|
|
70
|
-
[part='segment'][data-tone='neutral'] {
|
|
71
|
-
background: var(--lyra-color-border);
|
|
72
|
-
}
|
|
73
70
|
|
|
74
71
|
/* --- ring variant -------------------------------------------------- */
|
|
75
72
|
:host([variant='ring']) svg[part='base'] {
|
|
@@ -102,9 +99,6 @@ export const styles = css `
|
|
|
102
99
|
:host([variant='ring']) [part='segment'][data-tone='danger'] {
|
|
103
100
|
stroke: var(--lyra-color-danger);
|
|
104
101
|
}
|
|
105
|
-
:host([variant='ring']) [part='segment'][data-tone='neutral'] {
|
|
106
|
-
stroke: var(--lyra-color-border);
|
|
107
|
-
}
|
|
108
102
|
:host([variant='ring']) [part='label'] {
|
|
109
103
|
text-anchor: middle;
|
|
110
104
|
fill: var(--lyra-color-text-quiet);
|
|
@@ -24,16 +24,12 @@ export interface ConversationItemRenameDetail {
|
|
|
24
24
|
* identically-shaped choice. `lyra-select` therefore carries no detail
|
|
25
25
|
* payload at all.
|
|
26
26
|
*
|
|
27
|
-
* `role="
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* standalone -- with no listbox/group ancestor -- it's still fully
|
|
32
|
-
* operable, just technically missing that ARIA parent context; wrap it in a
|
|
33
|
-
* `role="listbox"` (or `role="group"`) container to satisfy that when
|
|
34
|
-
* accessibility-auditing a standalone usage.
|
|
27
|
+
* `role="button"` on `[part="option"]` so the item has valid semantics both
|
|
28
|
+
* standalone and when placed in a larger history-list layout. A conversation
|
|
29
|
+
* row activates one current session; it is not itself a listbox option and
|
|
30
|
+
* therefore does not require a particular owner role.
|
|
35
31
|
*
|
|
36
|
-
* `role="
|
|
32
|
+
* `role="button"` forbids focusable
|
|
37
33
|
* descendants -- verified against axe-core's `nested-interactive` rule,
|
|
38
34
|
* which flags it. That's why the rename button and the `actions` slot are
|
|
39
35
|
* rendered as DOM *siblings* of `[part="option"]` (both inside
|
|
@@ -41,10 +37,9 @@ export interface ConversationItemRenameDetail {
|
|
|
41
37
|
* contains plain text/`<time>` content. The in-place rename `<input>` is the
|
|
42
38
|
* same problem one level deeper -- it replaces the title *inside*
|
|
43
39
|
* `[part="option"]` while renaming -- so `[part="option"]` sheds its
|
|
44
|
-
* `role`/`tabindex`/`aria-
|
|
45
|
-
* of an edit.
|
|
46
|
-
*
|
|
47
|
-
* field, so suspending the option semantics is also the more accurate
|
|
40
|
+
* `role`/`tabindex`/`aria-current`/`aria-label` entirely for the duration
|
|
41
|
+
* of an edit. A row mid-edit is a text field, so suspending the button
|
|
42
|
+
* semantics is also the more accurate
|
|
48
43
|
* description of what's on screen.
|
|
49
44
|
*
|
|
50
45
|
* Inline rename is a dedicated pencil/edit icon button (not a double-click
|
|
@@ -70,7 +65,7 @@ export interface ConversationItemRenameDetail {
|
|
|
70
65
|
* when the trimmed draft is empty or unchanged from the original `title`
|
|
71
66
|
* (that's treated as an implicit cancel).
|
|
72
67
|
* @csspart base - The outer row wrapper (plain, no ARIA role) laying out `[part="option"]`, the rename button, and `actions`.
|
|
73
|
-
* @csspart option - The selectable region (`role="
|
|
68
|
+
* @csspart option - The selectable region (`role="button"`, removed while renaming -- see the class doc). Wraps `content` and `timestamp`.
|
|
74
69
|
* @csspart content - Wrapper around the title and excerpt.
|
|
75
70
|
* @csspart title - The title text, shown while not renaming.
|
|
76
71
|
* @csspart title-input - The in-place rename `<input>`, shown only while renaming.
|
|
@@ -99,13 +94,15 @@ export declare class LyraConversationItem extends LyraElement {
|
|
|
99
94
|
* brand-quiet background treatment. */
|
|
100
95
|
active: boolean;
|
|
101
96
|
/** Whether inline-rename is available at all. When `false`, the rename
|
|
102
|
-
* button never renders and the row can never enter its editing state.
|
|
97
|
+
* button never renders and the row can never enter its editing state. If
|
|
98
|
+
* flipped to `false` while a rename is already open, the in-progress edit
|
|
99
|
+
* is cancelled (discarded, like Escape) rather than left committable. */
|
|
103
100
|
editable: boolean;
|
|
104
101
|
private renaming;
|
|
105
102
|
private draftTitle;
|
|
106
103
|
private hasActionsSlot;
|
|
107
104
|
private titleInput?;
|
|
108
|
-
protected willUpdate(): void;
|
|
105
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
109
106
|
protected updated(changed: PropertyValues): void;
|
|
110
107
|
private get normalizedTimestamp();
|
|
111
108
|
private select;
|