@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
|
@@ -4,13 +4,26 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { html, nothing } from 'lit';
|
|
7
|
+
import { html, nothing, } from 'lit';
|
|
8
8
|
import { property, state } from 'lit/decorators.js';
|
|
9
9
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
10
|
import { defineElement } from '../../internal/prefix.js';
|
|
11
11
|
import { chevronIcon } from '../../internal/icons.js';
|
|
12
|
+
import { nextId } from '../../internal/a11y.js';
|
|
12
13
|
import { styles } from './date-picker.styles.js';
|
|
13
|
-
import { monthMatrix, weekdayLabels, monthTitle, formatISO, parseISO, isSameDay, addMonths, clampDate, resolveFirstDayOfWeek, } from './calendar-core.js';
|
|
14
|
+
import { monthMatrix, weekdayLabels, monthTitle, formatISO, parseISO, isSameDay, addMonths, addMonthsClampingDay, clampDate, dateTimeFormat, normalizeCalendarMode, normalizeCalendarMonths, normalizeWeekdayFormat, resolveFirstDayOfWeek, } from './calendar-core.js';
|
|
15
|
+
const modeConverter = {
|
|
16
|
+
fromAttribute: normalizeCalendarMode,
|
|
17
|
+
toAttribute: normalizeCalendarMode,
|
|
18
|
+
};
|
|
19
|
+
const monthsConverter = {
|
|
20
|
+
fromAttribute: normalizeCalendarMonths,
|
|
21
|
+
toAttribute: normalizeCalendarMonths,
|
|
22
|
+
};
|
|
23
|
+
const weekdayFormatConverter = {
|
|
24
|
+
fromAttribute: normalizeWeekdayFormat,
|
|
25
|
+
toAttribute: normalizeWeekdayFormat,
|
|
26
|
+
};
|
|
14
27
|
/**
|
|
15
28
|
* `<lyra-date-picker>` — an inline month-grid calendar for picking a single date
|
|
16
29
|
* or a date range. Mirrors the core `<wa-date-picker>` API under `lyra-`.
|
|
@@ -20,8 +33,24 @@ import { monthMatrix, weekdayLabels, monthTitle, formatISO, parseISO, isSameDay,
|
|
|
20
33
|
* @customElement lyra-date-picker
|
|
21
34
|
* @event change - The user committed a value.
|
|
22
35
|
* @event input - The value changed during interaction (range: after the first click).
|
|
23
|
-
* @csspart base
|
|
24
|
-
* @csspart
|
|
36
|
+
* @csspart base - The date-picker wrapper.
|
|
37
|
+
* @csspart month - A visible month wrapper.
|
|
38
|
+
* @csspart header - The month header.
|
|
39
|
+
* @csspart title - The month title.
|
|
40
|
+
* @csspart previous - The previous-month button.
|
|
41
|
+
* @csspart next - The next-month button.
|
|
42
|
+
* @csspart weekdays - The weekday header row.
|
|
43
|
+
* @csspart weekday - A weekday label.
|
|
44
|
+
* @csspart grid - A month date grid.
|
|
45
|
+
* @csspart week - A calendar week row.
|
|
46
|
+
* @csspart day - A calendar day button.
|
|
47
|
+
* @csspart day-today - A day representing today.
|
|
48
|
+
* @csspart day-outside - A day outside the active month.
|
|
49
|
+
* @csspart day-selected - A selected day.
|
|
50
|
+
* @csspart day-range-start - The start of a selected range.
|
|
51
|
+
* @csspart day-range-end - The end of a selected range.
|
|
52
|
+
* @csspart day-range-inner - An interior day in a selected range.
|
|
53
|
+
* @csspart day-placeholder - A non-day grid placeholder.
|
|
25
54
|
*/
|
|
26
55
|
export class LyraDatePicker extends LyraElement {
|
|
27
56
|
constructor() {
|
|
@@ -40,9 +69,17 @@ export class LyraDatePicker extends LyraElement {
|
|
|
40
69
|
this.disablePast = false;
|
|
41
70
|
this.disableFuture = false;
|
|
42
71
|
this.withOutsideDays = false;
|
|
72
|
+
/** Accessible label for the previous-month button. Override for a non-English `locale`. */
|
|
73
|
+
this.previousLabel = 'Previous month';
|
|
74
|
+
/** Accessible label for the next-month button. Override for a non-English `locale`. */
|
|
75
|
+
this.nextLabel = 'Next month';
|
|
43
76
|
this.viewDate = new Date(new Date().getFullYear(), new Date().getMonth(), 1);
|
|
44
77
|
this.focusedDate = null;
|
|
45
78
|
this.focusPending = false;
|
|
79
|
+
// Stable per-instance ids for each visible month's title, referenced by
|
|
80
|
+
// that month's grid via aria-labelledby -- `months` only ever renders 1 or
|
|
81
|
+
// 2 months, so two ids always suffice regardless of which is in use.
|
|
82
|
+
this.titleIds = [nextId('date-picker-title'), nextId('date-picker-title')];
|
|
46
83
|
// Set right before `commit()` assigns `value`, so `willUpdate` can tell its
|
|
47
84
|
// own write apart from an external assignment. Internal commits already
|
|
48
85
|
// know the right date is on-screen (it's the cell the user just clicked, or
|
|
@@ -88,10 +125,10 @@ export class LyraDatePicker extends LyraElement {
|
|
|
88
125
|
next = firstEnabledFrom(step(current, 7), 1);
|
|
89
126
|
break;
|
|
90
127
|
case 'PageUp':
|
|
91
|
-
next = firstEnabledFrom(
|
|
128
|
+
next = firstEnabledFrom(addMonthsClampingDay(current, -1), 1);
|
|
92
129
|
break;
|
|
93
130
|
case 'PageDown':
|
|
94
|
-
next = firstEnabledFrom(
|
|
131
|
+
next = firstEnabledFrom(addMonthsClampingDay(current, 1), 1);
|
|
95
132
|
break;
|
|
96
133
|
case 'Home':
|
|
97
134
|
next = firstEnabledFrom(new Date(current.getFullYear(), current.getMonth(), 1), 1);
|
|
@@ -116,13 +153,22 @@ export class LyraDatePicker extends LyraElement {
|
|
|
116
153
|
};
|
|
117
154
|
}
|
|
118
155
|
static { this.styles = [LyraElement.styles, styles]; }
|
|
156
|
+
get effectiveMode() {
|
|
157
|
+
return normalizeCalendarMode(this.mode);
|
|
158
|
+
}
|
|
159
|
+
get visibleMonths() {
|
|
160
|
+
return normalizeCalendarMonths(this.months);
|
|
161
|
+
}
|
|
162
|
+
get effectiveWeekdayFormat() {
|
|
163
|
+
return normalizeWeekdayFormat(this.weekdayFormat);
|
|
164
|
+
}
|
|
119
165
|
get selection() {
|
|
120
166
|
const parts = this.value.split('/');
|
|
121
167
|
return { from: parseISO(parts[0] ?? ''), to: parseISO(parts[1] ?? '') };
|
|
122
168
|
}
|
|
123
169
|
/** Read-only Date view of a single-mode value. */
|
|
124
170
|
get valueAsDate() {
|
|
125
|
-
return this.
|
|
171
|
+
return this.effectiveMode === 'single' ? this.selection.from : null;
|
|
126
172
|
}
|
|
127
173
|
willUpdate(changed) {
|
|
128
174
|
if (changed.has('value')) {
|
|
@@ -159,7 +205,7 @@ export class LyraDatePicker extends LyraElement {
|
|
|
159
205
|
* min/max window). */
|
|
160
206
|
firstEnabledDate(min, max, today) {
|
|
161
207
|
let d = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth(), 1);
|
|
162
|
-
const lastVisibleMonth = addMonths(d, this.
|
|
208
|
+
const lastVisibleMonth = addMonths(d, this.visibleMonths - 1);
|
|
163
209
|
const boundEnd = new Date(lastVisibleMonth.getFullYear(), lastVisibleMonth.getMonth() + 1, 0);
|
|
164
210
|
for (let i = 0; i < 732 && d <= boundEnd; i++) {
|
|
165
211
|
if (!this.isDisabled(d, min, max, today))
|
|
@@ -169,7 +215,7 @@ export class LyraDatePicker extends LyraElement {
|
|
|
169
215
|
return null;
|
|
170
216
|
}
|
|
171
217
|
commit(from, to, fire) {
|
|
172
|
-
const next = this.
|
|
218
|
+
const next = this.effectiveMode === 'range'
|
|
173
219
|
? from && to
|
|
174
220
|
? `${formatISO(from)}/${formatISO(to)}`
|
|
175
221
|
: from
|
|
@@ -196,7 +242,7 @@ export class LyraDatePicker extends LyraElement {
|
|
|
196
242
|
if (this.isDisabled(date, min, max, today))
|
|
197
243
|
return;
|
|
198
244
|
this.focusedDate = date;
|
|
199
|
-
if (this.
|
|
245
|
+
if (this.effectiveMode === 'range') {
|
|
200
246
|
const { from, to } = this.selection;
|
|
201
247
|
if (!from || (from && to)) {
|
|
202
248
|
this.commit(date, null, false);
|
|
@@ -224,9 +270,9 @@ export class LyraDatePicker extends LyraElement {
|
|
|
224
270
|
/** Navigate the view to a date and focus it, clamped to `min`/`max`. */
|
|
225
271
|
goToDate(date) {
|
|
226
272
|
const d = typeof date === 'string' ? parseISO(date) : date;
|
|
227
|
-
if (!d)
|
|
273
|
+
if (!d || !Number.isFinite(d.getTime()))
|
|
228
274
|
return;
|
|
229
|
-
const clamped = clampDate(d, parseISO(this.min), parseISO(this.max));
|
|
275
|
+
const clamped = clampDate(new Date(d.getTime()), parseISO(this.min), parseISO(this.max));
|
|
230
276
|
this.viewDate = new Date(clamped.getFullYear(), clamped.getMonth(), 1);
|
|
231
277
|
this.focusedDate = clamped;
|
|
232
278
|
this.focusPending = true;
|
|
@@ -243,11 +289,11 @@ export class LyraDatePicker extends LyraElement {
|
|
|
243
289
|
viewDateForFocus(next) {
|
|
244
290
|
const firstMonth = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth(), 1);
|
|
245
291
|
const nextMonth = new Date(next.getFullYear(), next.getMonth(), 1);
|
|
246
|
-
const lastMonth = addMonths(firstMonth, this.
|
|
292
|
+
const lastMonth = addMonths(firstMonth, this.visibleMonths - 1);
|
|
247
293
|
if (nextMonth < firstMonth)
|
|
248
294
|
return nextMonth;
|
|
249
295
|
if (nextMonth > lastMonth)
|
|
250
|
-
return addMonths(nextMonth, -(this.
|
|
296
|
+
return addMonths(nextMonth, -(this.visibleMonths - 1));
|
|
251
297
|
return firstMonth;
|
|
252
298
|
}
|
|
253
299
|
updated() {
|
|
@@ -258,7 +304,7 @@ export class LyraDatePicker extends LyraElement {
|
|
|
258
304
|
cell?.focus();
|
|
259
305
|
}
|
|
260
306
|
}
|
|
261
|
-
renderDay(date, shownMonth, selection, min, max, today, rowHasVisibleDay, fallbackFocusDate) {
|
|
307
|
+
renderDay(date, shownMonth, selection, min, max, today, rowHasVisibleDay, fallbackFocusDate, dayLabelFmt) {
|
|
262
308
|
const outside = date.getMonth() !== shownMonth;
|
|
263
309
|
// Outside-month days are empty placeholders by default (matches WA), keeping the
|
|
264
310
|
// 6-row grid aligned without low-contrast faded numbers.
|
|
@@ -279,8 +325,8 @@ export class LyraDatePicker extends LyraElement {
|
|
|
279
325
|
const isToday = isSameDay(date, today);
|
|
280
326
|
const isStart = from && isSameDay(date, from);
|
|
281
327
|
const isEnd = to && isSameDay(date, to);
|
|
282
|
-
const selected = this.
|
|
283
|
-
const inRange = this.
|
|
328
|
+
const selected = this.effectiveMode === 'single' ? isStart : isStart || isEnd;
|
|
329
|
+
const inRange = this.effectiveMode === 'range' && from && to && date > from && date < to;
|
|
284
330
|
// Falls back to the first *enabled* day across the visible month(s) (see
|
|
285
331
|
// firstEnabledDate()) when there's neither a focusedDate nor a selection,
|
|
286
332
|
// so the grid always has exactly one tabbable cell -- otherwise every
|
|
@@ -301,7 +347,7 @@ export class LyraDatePicker extends LyraElement {
|
|
|
301
347
|
parts.push('day-today');
|
|
302
348
|
if (selected)
|
|
303
349
|
parts.push('day-selected');
|
|
304
|
-
if (isStart && this.
|
|
350
|
+
if (isStart && this.effectiveMode === 'range')
|
|
305
351
|
parts.push('day-range-start');
|
|
306
352
|
if (isEnd)
|
|
307
353
|
parts.push('day-range-end');
|
|
@@ -312,12 +358,7 @@ export class LyraDatePicker extends LyraElement {
|
|
|
312
358
|
role="gridcell"
|
|
313
359
|
data-date=${formatISO(date)}
|
|
314
360
|
aria-selected=${selected ? 'true' : 'false'}
|
|
315
|
-
aria-label=${
|
|
316
|
-
weekday: 'long',
|
|
317
|
-
year: 'numeric',
|
|
318
|
-
month: 'long',
|
|
319
|
-
day: 'numeric',
|
|
320
|
-
})}
|
|
361
|
+
aria-label=${dayLabelFmt.format(date)}
|
|
321
362
|
tabindex=${focused ? '0' : '-1'}
|
|
322
363
|
?disabled=${disabled}
|
|
323
364
|
@click=${() => this.selectDate(date)}
|
|
@@ -325,32 +366,33 @@ export class LyraDatePicker extends LyraElement {
|
|
|
325
366
|
${date.getDate()}
|
|
326
367
|
</button>`;
|
|
327
368
|
}
|
|
328
|
-
renderMonth(offset, selection, min, max, today, fdow, labels, fallbackFocusDate) {
|
|
369
|
+
renderMonth(offset, selection, min, max, today, fdow, labels, fallbackFocusDate, dayLabelFmt) {
|
|
329
370
|
const base = addMonths(this.viewDate, offset);
|
|
330
371
|
const year = base.getFullYear();
|
|
331
372
|
const month = base.getMonth();
|
|
332
373
|
const matrix = monthMatrix(year, month, fdow);
|
|
333
374
|
const isFirst = offset === 0;
|
|
334
|
-
const isLast = offset === this.
|
|
375
|
+
const isLast = offset === this.visibleMonths - 1;
|
|
376
|
+
const titleId = this.titleIds[offset];
|
|
335
377
|
return html `<div part="month">
|
|
336
378
|
<div part="header">
|
|
337
379
|
${isFirst
|
|
338
380
|
? html `<button
|
|
339
381
|
part="previous"
|
|
340
382
|
type="button"
|
|
341
|
-
aria-label
|
|
383
|
+
aria-label=${this.previousLabel}
|
|
342
384
|
?disabled=${this.disabled || this.readonly}
|
|
343
385
|
@click=${() => this.nav(-1)}
|
|
344
386
|
>
|
|
345
387
|
${chevronIcon()}
|
|
346
388
|
</button>`
|
|
347
389
|
: html `<span></span>`}
|
|
348
|
-
<div part="title">${monthTitle(year, month, this.locale)}</div>
|
|
390
|
+
<div part="title" id=${titleId}>${monthTitle(year, month, this.locale)}</div>
|
|
349
391
|
${isLast
|
|
350
392
|
? html `<button
|
|
351
393
|
part="next"
|
|
352
394
|
type="button"
|
|
353
|
-
aria-label
|
|
395
|
+
aria-label=${this.nextLabel}
|
|
354
396
|
?disabled=${this.disabled || this.readonly}
|
|
355
397
|
@click=${() => this.nav(1)}
|
|
356
398
|
>
|
|
@@ -359,10 +401,10 @@ export class LyraDatePicker extends LyraElement {
|
|
|
359
401
|
: html `<span></span>`}
|
|
360
402
|
</div>
|
|
361
403
|
<div part="weekdays">${labels.map((l) => html `<span part="weekday">${l}</span>`)}</div>
|
|
362
|
-
<div part="grid" role="grid" @keydown=${this.onGridKey}>
|
|
404
|
+
<div part="grid" role="grid" aria-labelledby=${titleId} @keydown=${this.onGridKey}>
|
|
363
405
|
${matrix.map((week) => {
|
|
364
406
|
const rowHasVisibleDay = week.some((d) => d.getMonth() === month);
|
|
365
|
-
return html `<div part="week" role="row">${week.map((d) => this.renderDay(d, month, selection, min, max, today, rowHasVisibleDay, fallbackFocusDate))}</div>`;
|
|
407
|
+
return html `<div part="week" role="row">${week.map((d) => this.renderDay(d, month, selection, min, max, today, rowHasVisibleDay, fallbackFocusDate, dayLabelFmt))}</div>`;
|
|
366
408
|
})}
|
|
367
409
|
</div>
|
|
368
410
|
</div>`;
|
|
@@ -374,14 +416,24 @@ export class LyraDatePicker extends LyraElement {
|
|
|
374
416
|
const today = new Date();
|
|
375
417
|
today.setHours(0, 0, 0, 0);
|
|
376
418
|
const fdow = this.fdow;
|
|
377
|
-
const labels = weekdayLabels(fdow, this.
|
|
419
|
+
const labels = weekdayLabels(fdow, this.effectiveWeekdayFormat, this.locale);
|
|
420
|
+
// Hoisted once per render and reused across every day cell, rather than
|
|
421
|
+
// each cell constructing its own Intl.DateTimeFormat via
|
|
422
|
+
// toLocaleDateString() -- mirrors how the weekday-header and month-title
|
|
423
|
+
// labels already share a single formatter instead of one per cell.
|
|
424
|
+
const dayLabelFmt = dateTimeFormat(this.locale, {
|
|
425
|
+
weekday: 'long',
|
|
426
|
+
year: 'numeric',
|
|
427
|
+
month: 'long',
|
|
428
|
+
day: 'numeric',
|
|
429
|
+
});
|
|
378
430
|
// Only bother scanning for a fallback focus day when it's actually
|
|
379
431
|
// needed: there's no point walking the visible days if a focusedDate or
|
|
380
432
|
// an existing selection already determines the sole tabbable cell.
|
|
381
433
|
const fallbackFocusDate = this.focusedDate || selection.from ? null : this.firstEnabledDate(min, max, today);
|
|
382
434
|
const monthEls = [];
|
|
383
|
-
for (let i = 0; i < this.
|
|
384
|
-
monthEls.push(this.renderMonth(i, selection, min, max, today, fdow, labels, fallbackFocusDate));
|
|
435
|
+
for (let i = 0; i < this.visibleMonths; i++) {
|
|
436
|
+
monthEls.push(this.renderMonth(i, selection, min, max, today, fdow, labels, fallbackFocusDate, dayLabelFmt));
|
|
385
437
|
}
|
|
386
438
|
return html `<div part="base">${monthEls}</div>`;
|
|
387
439
|
}
|
|
@@ -390,7 +442,7 @@ __decorate([
|
|
|
390
442
|
property()
|
|
391
443
|
], LyraDatePicker.prototype, "value", void 0);
|
|
392
444
|
__decorate([
|
|
393
|
-
property()
|
|
445
|
+
property({ converter: modeConverter })
|
|
394
446
|
], LyraDatePicker.prototype, "mode", void 0);
|
|
395
447
|
__decorate([
|
|
396
448
|
property()
|
|
@@ -405,7 +457,7 @@ __decorate([
|
|
|
405
457
|
property({ type: Boolean, reflect: true })
|
|
406
458
|
], LyraDatePicker.prototype, "readonly", void 0);
|
|
407
459
|
__decorate([
|
|
408
|
-
property({
|
|
460
|
+
property({ converter: monthsConverter })
|
|
409
461
|
], LyraDatePicker.prototype, "months", void 0);
|
|
410
462
|
__decorate([
|
|
411
463
|
property()
|
|
@@ -414,7 +466,7 @@ __decorate([
|
|
|
414
466
|
property({ attribute: 'first-day-of-week' })
|
|
415
467
|
], LyraDatePicker.prototype, "firstDayOfWeek", void 0);
|
|
416
468
|
__decorate([
|
|
417
|
-
property({ attribute: 'weekday-format' })
|
|
469
|
+
property({ attribute: 'weekday-format', converter: weekdayFormatConverter })
|
|
418
470
|
], LyraDatePicker.prototype, "weekdayFormat", void 0);
|
|
419
471
|
__decorate([
|
|
420
472
|
property({ type: Boolean, attribute: 'disable-past' })
|
|
@@ -425,6 +477,12 @@ __decorate([
|
|
|
425
477
|
__decorate([
|
|
426
478
|
property({ type: Boolean, attribute: 'with-outside-days' })
|
|
427
479
|
], LyraDatePicker.prototype, "withOutsideDays", void 0);
|
|
480
|
+
__decorate([
|
|
481
|
+
property({ attribute: 'previous-label' })
|
|
482
|
+
], LyraDatePicker.prototype, "previousLabel", void 0);
|
|
483
|
+
__decorate([
|
|
484
|
+
property({ attribute: 'next-label' })
|
|
485
|
+
], LyraDatePicker.prototype, "nextLabel", void 0);
|
|
428
486
|
__decorate([
|
|
429
487
|
state()
|
|
430
488
|
], LyraDatePicker.prototype, "viewDate", void 0);
|
|
@@ -2,17 +2,14 @@ import './dialog.js';
|
|
|
2
2
|
// Plain inline-styled <button>s, not a shared lyra-button component -- none
|
|
3
3
|
// exists in this library yet. Every value below is still a --lyra-* token
|
|
4
4
|
// reference, never a raw literal, same requirement as a component's own
|
|
5
|
-
// styles.ts.
|
|
6
|
-
//
|
|
7
|
-
// light and dark themes and reads fine over the danger fill too, so the
|
|
8
|
-
// confirm button reuses it rather than introducing a redundant --lyra-color-
|
|
9
|
-
// on-danger token for one call site.
|
|
5
|
+
// styles.ts. Each filled tone uses its matching on-color token so standalone
|
|
6
|
+
// light/dark fallbacks and a consumer's Web Awesome theme stay paired.
|
|
10
7
|
const BUTTON_BASE_STYLE = 'font: inherit; font-size: 0.875rem; padding: var(--lyra-space-xs) var(--lyra-space-m); ' +
|
|
11
8
|
'border-radius: var(--lyra-radius); cursor: pointer; border: 1px solid var(--lyra-color-border);';
|
|
12
9
|
const CANCEL_STYLE = 'background: var(--lyra-color-surface); color: var(--lyra-color-text);';
|
|
13
10
|
const CONFIRM_TONE_STYLE = {
|
|
14
11
|
neutral: 'background: var(--lyra-color-brand); color: var(--lyra-color-on-brand); border-color: var(--lyra-color-brand);',
|
|
15
|
-
danger: 'background: var(--lyra-color-danger); color: var(--lyra-color-on-
|
|
12
|
+
danger: 'background: var(--lyra-color-danger); color: var(--lyra-color-on-danger); border-color: var(--lyra-color-danger);',
|
|
16
13
|
};
|
|
17
14
|
function createButton(label, style, onClick) {
|
|
18
15
|
const button = document.createElement('button');
|
|
@@ -3,45 +3,77 @@ import { LyraElement } from '../../internal/lyra-element.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Reason a dialog was dismissed, forwarded as the `lyra-dialog-close` event
|
|
5
5
|
* detail. `'escape'` and `'backdrop'` are emitted by the dialog's own built-in
|
|
6
|
-
* dismiss triggers;
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* dismiss triggers; `'close-button'` by the built-in header close button
|
|
7
|
+
* (rendered when `closable` is set); `'unmount'` is emitted when the dialog is
|
|
8
|
+
* removed from the DOM while still open by something other than its own
|
|
9
|
+
* `close()` (e.g. a consumer's own cleanup code, or a parent re-render that
|
|
10
|
+
* drops it); any other string is whatever a caller passes to `close()` (e.g. a
|
|
11
|
+
* consumer's own footer close button, or confirm.ts's `'confirm'`/`'cancel'`).
|
|
9
12
|
*/
|
|
10
|
-
export type DialogCloseReason = 'escape' | 'backdrop' | 'api' | string;
|
|
13
|
+
export type DialogCloseReason = 'escape' | 'backdrop' | 'close-button' | 'api' | 'unmount' | string;
|
|
11
14
|
/**
|
|
12
15
|
* `<lyra-dialog>` — a general-purpose modal/overlay. `role="dialog"`,
|
|
13
16
|
* focus-trapped while open, dismissible via Escape or a backdrop click, and
|
|
14
|
-
* scroll-locks the document for as long as it's open. Chrome stays minimal
|
|
15
|
-
* no built-in title bar or close button; a consumer supplies a
|
|
16
|
-
* any close affordance itself via the default/`footer` slots.
|
|
17
|
+
* scroll-locks the document for as long as it's open. Chrome stays minimal by
|
|
18
|
+
* default — no built-in title bar or close button; a consumer supplies a
|
|
19
|
+
* heading and any close affordance itself via the default/`footer` slots.
|
|
20
|
+
* `heading`/`closable` are an opt-in convenience for the common case where
|
|
21
|
+
* hand-building that chrome isn't worth it (see below).
|
|
17
22
|
*
|
|
18
|
-
* Accessible name
|
|
19
|
-
* a
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* is
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Accessible name / visible header, in priority order:
|
|
24
|
+
* 1. If a heading element (`h1`–`h6` or `[role="heading"]`) is a *direct
|
|
25
|
+
* child* (not inside `slot="footer"`), its text content becomes
|
|
26
|
+
* `aria-label` on the panel — unchanged, and takes priority over `heading`
|
|
27
|
+
* below so an existing consumer that already slots its own heading keeps
|
|
28
|
+
* rendering it exactly as before.
|
|
29
|
+
* 2. Otherwise, when `heading` is set, a visible header row (`part="header"`)
|
|
30
|
+
* renders containing that text (`part="heading"`), which becomes the
|
|
31
|
+
* `aria-labelledby` target.
|
|
32
|
+
* 3. Otherwise, when `label` is set, an invisible (`.sr-only`, exposed as the
|
|
33
|
+
* `label` part) element carrying that text is rendered inside the panel
|
|
34
|
+
* and `aria-labelledby` points at it instead.
|
|
35
|
+
* Only one of cases 2/3 ever renders at a time, so exactly one element ever
|
|
36
|
+
* claims `aria-labelledby`. `label` itself never renders visible chrome on
|
|
37
|
+
* its own — `::part(label)` can be restyled to make the sr-only text visible,
|
|
38
|
+
* or `heading` can be set instead, if a consumer wants visible chrome without
|
|
39
|
+
* slotting a real heading element.
|
|
27
40
|
*
|
|
28
|
-
* The heading case deliberately uses `aria-label` (a copied string)
|
|
29
|
-
* than `aria-labelledby` pointing at the heading's `id`: the heading is
|
|
41
|
+
* The slotted-heading case deliberately uses `aria-label` (a copied string)
|
|
42
|
+
* rather than `aria-labelledby` pointing at the heading's `id`: the heading is
|
|
30
43
|
* *light-DOM* content while `[part="panel"]` lives in this element's
|
|
31
44
|
* *shadow* tree, and an ID-reference attribute can't resolve across that
|
|
32
45
|
* boundary (verified against axe's `aria-dialog-name` rule) — unlike the
|
|
33
|
-
* `label`-prop
|
|
34
|
-
* same shadow root it labels, so `aria-labelledby` there is safe.
|
|
46
|
+
* `heading`/`label`-prop cases above, where the target element is rendered
|
|
47
|
+
* inside the same shadow root it labels, so `aria-labelledby` there is safe.
|
|
48
|
+
*
|
|
49
|
+
* `closable` renders a close (X) button in the header row (creating one, with
|
|
50
|
+
* no heading text, if `heading` is unset) that closes the dialog via the same
|
|
51
|
+
* `close()` path as Escape/backdrop-dismiss, with reason `'close-button'`.
|
|
52
|
+
*
|
|
53
|
+
* Stacking: opening one `<lyra-dialog>` while another is already open (e.g. a
|
|
54
|
+
* `confirm()` launched from within an already-open dialog) is supported --
|
|
55
|
+
* Escape and the Tab focus trap only ever act on the topmost open dialog, so
|
|
56
|
+
* dialogs beneath it stay open and untouched until the one on top closes.
|
|
35
57
|
*
|
|
36
58
|
* @customElement lyra-dialog
|
|
37
59
|
* @slot - The dialog body.
|
|
38
60
|
* @slot footer - Action buttons, rendered in a bottom row.
|
|
39
61
|
* @event lyra-dialog-close - `detail: DialogCloseReason`. Fired whenever the
|
|
40
|
-
* dialog is dismissed via Escape, a backdrop click,
|
|
62
|
+
* dialog is dismissed via Escape, a backdrop click, the built-in close
|
|
63
|
+
* button (`closable`), a `close()` call, or (with reason `'unmount'`)
|
|
64
|
+
* removal from the DOM by anything else while still open.
|
|
41
65
|
* @csspart backdrop - The full-viewport scrim behind the panel.
|
|
42
|
-
* @csspart panel - The dialog panel itself (`role="dialog"` while open).
|
|
66
|
+
* @csspart panel - The dialog panel itself (`role="dialog"` while open). Its
|
|
67
|
+
* max-inline-size is controlled by the `--lyra-dialog-max-width` custom
|
|
68
|
+
* property (default `32rem`).
|
|
69
|
+
* @csspart header - The header row, rendered when `heading` is set (and no
|
|
70
|
+
* heading is slotted) and/or `closable` is `true`.
|
|
71
|
+
* @csspart heading - The visible `heading`-text element inside `header`,
|
|
72
|
+
* rendered only when `heading` is set and no heading is slotted.
|
|
73
|
+
* @csspart close-button - The built-in close button, rendered inside `header`
|
|
74
|
+
* only when `closable` is `true`.
|
|
43
75
|
* @csspart label - The invisible `label`-text element used for
|
|
44
|
-
* `aria-labelledby` when no heading is slotted.
|
|
76
|
+
* `aria-labelledby` when no heading is slotted and `heading` is unset.
|
|
45
77
|
* @csspart body - The wrapper around the default slot.
|
|
46
78
|
* @csspart footer - The wrapper around the `footer` slot.
|
|
47
79
|
*/
|
|
@@ -51,11 +83,22 @@ export declare class LyraDialog extends LyraElement {
|
|
|
51
83
|
open: boolean;
|
|
52
84
|
/** Accessible name used when no heading is slotted — see the class doc for the full fallback order. */
|
|
53
85
|
label: string;
|
|
86
|
+
/** Visible header text, rendered when no heading element is slotted into
|
|
87
|
+
* the default slot — see the class doc for the full fallback order. Has
|
|
88
|
+
* no effect (renders nothing) if a light-DOM heading is slotted; that case
|
|
89
|
+
* keeps working completely unchanged whether or not `heading` is set. */
|
|
90
|
+
heading?: string;
|
|
91
|
+
/** Renders a built-in close (X) button in the header row (creating one,
|
|
92
|
+
* with no heading text, if `heading` is unset), wired to the same
|
|
93
|
+
* `close()` path Escape/backdrop-dismiss already use, with reason
|
|
94
|
+
* `'close-button'`. */
|
|
95
|
+
closable: boolean;
|
|
54
96
|
private hasFooterSlot;
|
|
55
97
|
private headingText?;
|
|
56
98
|
private releaseScrollLock?;
|
|
57
|
-
private
|
|
99
|
+
private overlay?;
|
|
58
100
|
private readonly srLabelId;
|
|
101
|
+
private readonly headingId;
|
|
59
102
|
protected willUpdate(changed: PropertyValues): void;
|
|
60
103
|
protected updated(changed: PropertyValues): void;
|
|
61
104
|
connectedCallback(): void;
|
|
@@ -66,16 +109,17 @@ export declare class LyraDialog extends LyraElement {
|
|
|
66
109
|
/**
|
|
67
110
|
* Close the dialog and return focus to whatever had it before the dialog
|
|
68
111
|
* opened. `reason` is forwarded as the `lyra-dialog-close` detail --
|
|
69
|
-
* built-in triggers pass `'escape'`/`'backdrop'`; a
|
|
70
|
-
* affordance (e.g. a footer Cancel button) should
|
|
71
|
-
* its own reason string, so every dismissal path
|
|
72
|
-
* event instead of the consumer having to also
|
|
112
|
+
* built-in triggers pass `'escape'`/`'backdrop'`/`'close-button'`; a
|
|
113
|
+
* consumer's own close affordance (e.g. a footer Cancel button) should
|
|
114
|
+
* call this directly with its own reason string, so every dismissal path
|
|
115
|
+
* funnels through the same event instead of the consumer having to also
|
|
116
|
+
* toggle `open` itself.
|
|
73
117
|
*/
|
|
74
118
|
close(reason?: DialogCloseReason): void;
|
|
75
119
|
private onBackdropClick;
|
|
76
|
-
private
|
|
77
|
-
private
|
|
78
|
-
private
|
|
120
|
+
private onCloseButtonClick;
|
|
121
|
+
private activateOverlay;
|
|
122
|
+
private deactivateOverlay;
|
|
79
123
|
render(): TemplateResult;
|
|
80
124
|
}
|
|
81
125
|
declare global {
|