@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
|
@@ -2,44 +2,44 @@ import { css } from 'lit';
|
|
|
2
2
|
export const styles = css `
|
|
3
3
|
:host {
|
|
4
4
|
display: block;
|
|
5
|
-
--accent-width: 4px;
|
|
6
|
-
--show-duration: var(--lyra-transition-base, 180ms ease-out);
|
|
7
|
-
--hide-duration: var(--lyra-transition-base, 180ms ease-out);
|
|
8
|
-
--padding: var(--lyra-space-m);
|
|
9
|
-
--font-size: 1rem;
|
|
10
|
-
--accent-color: var(--lyra-color-border);
|
|
5
|
+
--lyra-toast-accent-width: 4px;
|
|
6
|
+
--lyra-toast-show-duration: var(--lyra-transition-base, 180ms ease-out);
|
|
7
|
+
--lyra-toast-hide-duration: var(--lyra-transition-base, 180ms ease-out);
|
|
8
|
+
--lyra-toast-padding: var(--lyra-space-m);
|
|
9
|
+
--lyra-toast-font-size: 1rem;
|
|
10
|
+
--lyra-toast-accent-color: var(--lyra-color-border);
|
|
11
11
|
}
|
|
12
12
|
:host([variant='brand']) {
|
|
13
|
-
--accent-color: var(--lyra-color-brand);
|
|
13
|
+
--lyra-toast-accent-color: var(--lyra-color-brand);
|
|
14
14
|
}
|
|
15
15
|
:host([variant='success']) {
|
|
16
|
-
--accent-color: var(--lyra-color-success);
|
|
16
|
+
--lyra-toast-accent-color: var(--lyra-color-success);
|
|
17
17
|
}
|
|
18
18
|
:host([variant='warning']) {
|
|
19
|
-
--accent-color: var(--lyra-color-warning);
|
|
19
|
+
--lyra-toast-accent-color: var(--lyra-color-warning);
|
|
20
20
|
}
|
|
21
21
|
:host([variant='danger']) {
|
|
22
|
-
--accent-color: var(--lyra-color-danger);
|
|
22
|
+
--lyra-toast-accent-color: var(--lyra-color-danger);
|
|
23
23
|
}
|
|
24
24
|
:host([size='xs']) {
|
|
25
|
-
--padding: var(--lyra-space-xs);
|
|
26
|
-
--font-size: 0.75rem;
|
|
25
|
+
--lyra-toast-padding: var(--lyra-space-xs);
|
|
26
|
+
--lyra-toast-font-size: 0.75rem;
|
|
27
27
|
}
|
|
28
28
|
:host([size='s']) {
|
|
29
|
-
--padding: var(--lyra-space-s);
|
|
30
|
-
--font-size: 0.875rem;
|
|
29
|
+
--lyra-toast-padding: var(--lyra-space-s);
|
|
30
|
+
--lyra-toast-font-size: 0.875rem;
|
|
31
31
|
}
|
|
32
32
|
:host([size='m']) {
|
|
33
|
-
--padding: var(--lyra-space-m);
|
|
34
|
-
--font-size: 1rem;
|
|
33
|
+
--lyra-toast-padding: var(--lyra-space-m);
|
|
34
|
+
--lyra-toast-font-size: 1rem;
|
|
35
35
|
}
|
|
36
36
|
:host([size='l']) {
|
|
37
|
-
--padding: var(--lyra-space-l);
|
|
38
|
-
--font-size: 1.125rem;
|
|
37
|
+
--lyra-toast-padding: var(--lyra-space-l);
|
|
38
|
+
--lyra-toast-font-size: 1.125rem;
|
|
39
39
|
}
|
|
40
40
|
:host([size='xl']) {
|
|
41
|
-
--padding: calc(var(--lyra-space-l) * 1.5);
|
|
42
|
-
--font-size: 1.25rem;
|
|
41
|
+
--lyra-toast-padding: calc(var(--lyra-space-l) * 1.5);
|
|
42
|
+
--lyra-toast-font-size: 1.25rem;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
[part='toast-item'] {
|
|
@@ -48,9 +48,9 @@ export const styles = css `
|
|
|
48
48
|
align-items: start;
|
|
49
49
|
gap: var(--lyra-space-s);
|
|
50
50
|
inline-size: 100%;
|
|
51
|
-
padding: var(--padding);
|
|
52
|
-
padding-inline-start: calc(var(--padding) + var(--accent-width));
|
|
53
|
-
font-size: var(--font-size);
|
|
51
|
+
padding: var(--lyra-toast-padding);
|
|
52
|
+
padding-inline-start: calc(var(--lyra-toast-padding) + var(--lyra-toast-accent-width));
|
|
53
|
+
font-size: var(--lyra-toast-font-size);
|
|
54
54
|
background: var(--lyra-color-surface);
|
|
55
55
|
color: var(--lyra-color-text);
|
|
56
56
|
border: 1px solid var(--lyra-color-border);
|
|
@@ -59,8 +59,13 @@ export const styles = css `
|
|
|
59
59
|
opacity: 0;
|
|
60
60
|
transform: translateY(-8px);
|
|
61
61
|
transition:
|
|
62
|
-
opacity var(--show-duration),
|
|
63
|
-
transform var(--show-duration);
|
|
62
|
+
opacity var(--lyra-toast-show-duration),
|
|
63
|
+
transform var(--lyra-toast-show-duration);
|
|
64
|
+
}
|
|
65
|
+
:host([data-hiding]) [part='toast-item'] {
|
|
66
|
+
transition:
|
|
67
|
+
opacity var(--lyra-toast-hide-duration),
|
|
68
|
+
transform var(--lyra-toast-hide-duration);
|
|
64
69
|
}
|
|
65
70
|
:host([data-visible]) [part='toast-item'] {
|
|
66
71
|
opacity: 1;
|
|
@@ -76,20 +81,46 @@ export const styles = css `
|
|
|
76
81
|
position: absolute;
|
|
77
82
|
inset-block: 0;
|
|
78
83
|
inset-inline-start: 0;
|
|
79
|
-
inline-size: var(--accent-width);
|
|
80
|
-
background: var(--accent-color);
|
|
84
|
+
inline-size: var(--lyra-toast-accent-width);
|
|
85
|
+
background: var(--lyra-toast-accent-color);
|
|
81
86
|
border-start-start-radius: var(--lyra-radius);
|
|
82
87
|
border-end-start-radius: var(--lyra-radius);
|
|
83
88
|
}
|
|
84
89
|
[part='icon'] {
|
|
85
90
|
display: inline-flex;
|
|
86
91
|
flex: 0 0 auto;
|
|
87
|
-
color: var(--accent-color);
|
|
92
|
+
color: var(--lyra-toast-accent-color);
|
|
88
93
|
}
|
|
89
94
|
[part='content'] {
|
|
90
95
|
flex: 1 1 auto;
|
|
91
96
|
min-inline-size: 0;
|
|
92
97
|
}
|
|
98
|
+
/* toaster.ts's action option (and the WithIcon/Triggers stories) append a
|
|
99
|
+
plain light-DOM button as a sibling of the message text -- without
|
|
100
|
+
this, it renders with the browser's unstyled default button chrome,
|
|
101
|
+
clashing with the rest of the token-driven design. Styled as an inline
|
|
102
|
+
text action (matching the toast's own accent color) rather than a
|
|
103
|
+
boxed button, since it sits directly after the message inside the
|
|
104
|
+
content part rather than in its own layout slot. */
|
|
105
|
+
::slotted(button) {
|
|
106
|
+
display: inline-block;
|
|
107
|
+
margin-inline-start: var(--lyra-space-s);
|
|
108
|
+
padding: 0;
|
|
109
|
+
border: none;
|
|
110
|
+
background: none;
|
|
111
|
+
font: inherit;
|
|
112
|
+
font-weight: bold;
|
|
113
|
+
color: var(--lyra-toast-accent-color);
|
|
114
|
+
text-decoration: underline;
|
|
115
|
+
cursor: pointer;
|
|
116
|
+
}
|
|
117
|
+
::slotted(button:hover) {
|
|
118
|
+
color: var(--lyra-color-text);
|
|
119
|
+
}
|
|
120
|
+
::slotted(button:focus-visible) {
|
|
121
|
+
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
122
|
+
outline-offset: var(--lyra-focus-ring-offset);
|
|
123
|
+
}
|
|
93
124
|
[part='close-button'] {
|
|
94
125
|
flex: 0 0 auto;
|
|
95
126
|
margin-inline-start: auto;
|
|
@@ -29,17 +29,29 @@ export class LyraToast extends LyraElement {
|
|
|
29
29
|
/** Create and append a toast item programmatically; resolves to the item. */
|
|
30
30
|
async create(message, options = {}) {
|
|
31
31
|
const item = document.createElement('lyra-toast-item');
|
|
32
|
-
|
|
33
|
-
item
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
// Only assign what the caller actually specified -- a freshly-created
|
|
33
|
+
// <lyra-toast-item> already carries its own property defaults, so
|
|
34
|
+
// falling back to a literal here (e.g. `?? 5000`) would duplicate those
|
|
35
|
+
// defaults in a second place that has no way of staying in sync if the
|
|
36
|
+
// property declaration in toast-item.ts ever changes.
|
|
37
|
+
if (options.variant !== undefined)
|
|
38
|
+
item.variant = options.variant;
|
|
39
|
+
if (options.duration !== undefined)
|
|
40
|
+
item.duration = options.duration;
|
|
41
|
+
if (options.size !== undefined)
|
|
42
|
+
item.size = options.size;
|
|
43
|
+
if (options.withIcon !== undefined)
|
|
44
|
+
item.withIcon = options.withIcon;
|
|
36
45
|
item.textContent = message;
|
|
37
46
|
this.appendChild(item);
|
|
38
47
|
await item.updateComplete;
|
|
39
48
|
return item;
|
|
40
49
|
}
|
|
41
50
|
render() {
|
|
42
|
-
|
|
51
|
+
// Each toast item owns its own status/alert role. Keeping a live region on
|
|
52
|
+
// the stack as well would nest assertive alerts inside a polite region and
|
|
53
|
+
// can cause duplicate or out-of-order announcements.
|
|
54
|
+
return html `<div part="stack"><slot></slot></div>`;
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
57
|
__decorate([
|
|
@@ -27,8 +27,17 @@ function getRegion(placement = DEFAULT_PLACEMENT) {
|
|
|
27
27
|
*/
|
|
28
28
|
export function toast(input) {
|
|
29
29
|
const opts = typeof input === 'string' ? { message: input } : input;
|
|
30
|
+
// An action must remain available until the user can reach it. Callers can
|
|
31
|
+
// still opt into a finite duration explicitly; the convenience API makes
|
|
32
|
+
// only the omitted-duration/action combination persistent.
|
|
33
|
+
const createOptions = {
|
|
34
|
+
variant: opts.variant,
|
|
35
|
+
duration: opts.duration ?? (opts.action ? 0 : undefined),
|
|
36
|
+
size: opts.size,
|
|
37
|
+
withIcon: opts.withIcon,
|
|
38
|
+
};
|
|
30
39
|
const item = getRegion(opts.placement)
|
|
31
|
-
.create(opts.message,
|
|
40
|
+
.create(opts.message, createOptions)
|
|
32
41
|
.then((el) => {
|
|
33
42
|
if (opts.action) {
|
|
34
43
|
const btn = document.createElement('button');
|
|
@@ -17,11 +17,10 @@ export type ToolApprovalDialogCloseReason = 'escape' | 'backdrop' | 'approve' |
|
|
|
17
17
|
* executing it until a person explicitly approves or denies it, with an
|
|
18
18
|
* optional inline "edit the arguments before approving" step.
|
|
19
19
|
*
|
|
20
|
-
* This
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* duplicates that pattern locally instead of composing the previous one.
|
|
20
|
+
* This renders its own dialog panel rather than nesting a `<lyra-dialog>` in
|
|
21
|
+
* its shadow template. Shared overlay infrastructure coordinates stacking,
|
|
22
|
+
* focus trapping, Escape/backdrop dismissal, and focus return with every
|
|
23
|
+
* other overlay in the same document.
|
|
25
24
|
*
|
|
26
25
|
* Approve/Deny/Edit are built-in chrome (not a `footer` slot a consumer must
|
|
27
26
|
* assemble) — this component's interaction shape is fixed enough (there is
|
|
@@ -43,8 +42,12 @@ export type ToolApprovalDialogCloseReason = 'escape' | 'backdrop' | 'approve' |
|
|
|
43
42
|
* Both `editing` and any in-progress draft reset back to the read-only view
|
|
44
43
|
* every time the dialog transitions from closed to open, so a reused
|
|
45
44
|
* instance never leaks one proposal's half-finished edit into the next.
|
|
45
|
+
* `editable` flipping to `false` mid-edit does the same (see `willUpdate()`)
|
|
46
|
+
* and, if the textarea it unmounts still held focus, `updated()` refocuses
|
|
47
|
+
* Deny so the focus trap keeps engaging instead of silently letting focus
|
|
48
|
+
* fall through to the document.
|
|
46
49
|
*
|
|
47
|
-
* Initial focus deliberately does *not* land on Approve
|
|
50
|
+
* Initial focus deliberately does *not* land on Approve:
|
|
48
51
|
* approving a tool call is a consequential, potentially irreversible action,
|
|
49
52
|
* so a user who opens this dialog and reflexively presses Enter/Space before
|
|
50
53
|
* reading anything should deny, not approve. Deny gets the initial focus
|
|
@@ -95,13 +98,14 @@ export declare class LyraToolApprovalDialog extends LyraElement {
|
|
|
95
98
|
/** `JSON.parse` failure message for `draftText`, or `''` while it parses cleanly. Empty string (not `undefined`) so it can drive `?hidden` directly. */
|
|
96
99
|
private draftError;
|
|
97
100
|
private releaseScrollLock?;
|
|
98
|
-
private
|
|
101
|
+
private overlay?;
|
|
99
102
|
private readonly titleId;
|
|
100
103
|
private readonly errorId;
|
|
101
104
|
protected willUpdate(changed: PropertyValues): void;
|
|
102
105
|
protected updated(changed: PropertyValues): void;
|
|
103
106
|
connectedCallback(): void;
|
|
104
107
|
disconnectedCallback(): void;
|
|
108
|
+
private activateOverlay;
|
|
105
109
|
/**
|
|
106
110
|
* Close the dialog and return focus to whatever had it before the dialog
|
|
107
111
|
* opened. `reason` is forwarded as the `lyra-close` detail — built-in
|
|
@@ -113,9 +117,6 @@ export declare class LyraToolApprovalDialog extends LyraElement {
|
|
|
113
117
|
*/
|
|
114
118
|
close(reason?: ToolApprovalDialogCloseReason): void;
|
|
115
119
|
private onBackdropClick;
|
|
116
|
-
private onDocKeyDown;
|
|
117
|
-
private getFocusableElements;
|
|
118
|
-
private getActiveElement;
|
|
119
120
|
private stringifyArgs;
|
|
120
121
|
private toggleEdit;
|
|
121
122
|
private onDraftInput;
|
|
@@ -7,54 +7,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
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
|
+
import { activateOverlay } from '../../internal/overlay-manager.js';
|
|
10
11
|
import { defineElement } from '../../internal/prefix.js';
|
|
11
12
|
import { lockScroll } from '../../internal/scroll-lock.js';
|
|
12
13
|
import { nextId } from '../../internal/a11y.js';
|
|
13
14
|
import { styles } from './tool-approval-dialog.styles.js';
|
|
14
15
|
import '../json-viewer/json-viewer.js';
|
|
15
|
-
const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
16
|
-
// Shadow-piercing so a slotted custom element's real focusable target, and
|
|
17
|
-
// this component's own directly-rendered <lyra-json-viewer>'s internal
|
|
18
|
-
// toggle/copy buttons, are found even though neither the slotted host tag
|
|
19
|
-
// nor <lyra-json-viewer> itself matches FOCUSABLE_SELECTOR. Deliberately
|
|
20
|
-
// duplicated from lyra-dialog's/lyra-tool-select-dialog's identical helper
|
|
21
|
-
// rather than imported/shared -- this component is its own standalone
|
|
22
|
-
// overlay and must not depend on either (see this file's class doc).
|
|
23
|
-
function collectFocusable(el) {
|
|
24
|
-
const result = [];
|
|
25
|
-
if (el.matches(FOCUSABLE_SELECTOR)) {
|
|
26
|
-
result.push(el);
|
|
27
|
-
}
|
|
28
|
-
if (el instanceof HTMLSlotElement) {
|
|
29
|
-
for (const assigned of el.assignedElements({ flatten: true })) {
|
|
30
|
-
result.push(...collectFocusable(assigned));
|
|
31
|
-
}
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
const container = el.shadowRoot ?? el;
|
|
35
|
-
for (const child of Array.from(container.children)) {
|
|
36
|
-
result.push(...collectFocusable(child));
|
|
37
|
-
}
|
|
38
|
-
return result;
|
|
39
|
-
}
|
|
40
|
-
/** Whether `el` is actually laid out/paintable -- `checkVisibility()` (falling
|
|
41
|
-
* back to `getClientRects().length` where unsupported) correctly follows
|
|
42
|
-
* flattened-tree/slot assignment, unlike `offsetParent`. Mirrors
|
|
43
|
-
* lyra-dialog's/lyra-tool-select-dialog's identical helper. */
|
|
44
|
-
function isRendered(el) {
|
|
45
|
-
return el.checkVisibility ? el.checkVisibility() : el.getClientRects().length > 0;
|
|
46
|
-
}
|
|
47
16
|
/**
|
|
48
17
|
* `<lyra-tool-approval-dialog>` — a human-in-the-loop gate: presents one
|
|
49
18
|
* proposed tool/function call (`toolName` + `args`) and blocks an agent from
|
|
50
19
|
* executing it until a person explicitly approves or denies it, with an
|
|
51
20
|
* optional inline "edit the arguments before approving" step.
|
|
52
21
|
*
|
|
53
|
-
* This
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* duplicates that pattern locally instead of composing the previous one.
|
|
22
|
+
* This renders its own dialog panel rather than nesting a `<lyra-dialog>` in
|
|
23
|
+
* its shadow template. Shared overlay infrastructure coordinates stacking,
|
|
24
|
+
* focus trapping, Escape/backdrop dismissal, and focus return with every
|
|
25
|
+
* other overlay in the same document.
|
|
58
26
|
*
|
|
59
27
|
* Approve/Deny/Edit are built-in chrome (not a `footer` slot a consumer must
|
|
60
28
|
* assemble) — this component's interaction shape is fixed enough (there is
|
|
@@ -76,8 +44,12 @@ function isRendered(el) {
|
|
|
76
44
|
* Both `editing` and any in-progress draft reset back to the read-only view
|
|
77
45
|
* every time the dialog transitions from closed to open, so a reused
|
|
78
46
|
* instance never leaks one proposal's half-finished edit into the next.
|
|
47
|
+
* `editable` flipping to `false` mid-edit does the same (see `willUpdate()`)
|
|
48
|
+
* and, if the textarea it unmounts still held focus, `updated()` refocuses
|
|
49
|
+
* Deny so the focus trap keeps engaging instead of silently letting focus
|
|
50
|
+
* fall through to the document.
|
|
79
51
|
*
|
|
80
|
-
* Initial focus deliberately does *not* land on Approve
|
|
52
|
+
* Initial focus deliberately does *not* land on Approve:
|
|
81
53
|
* approving a tool call is a consequential, potentially irreversible action,
|
|
82
54
|
* so a user who opens this dialog and reflexively presses Enter/Space before
|
|
83
55
|
* reading anything should deny, not approve. Deny gets the initial focus
|
|
@@ -131,34 +103,7 @@ export class LyraToolApprovalDialog extends LyraElement {
|
|
|
131
103
|
this.titleId = nextId('tool-approval-dialog-title');
|
|
132
104
|
this.errorId = nextId('tool-approval-dialog-error');
|
|
133
105
|
this.onBackdropClick = () => {
|
|
134
|
-
this.
|
|
135
|
-
};
|
|
136
|
-
this.onDocKeyDown = (e) => {
|
|
137
|
-
if (!this.open)
|
|
138
|
-
return;
|
|
139
|
-
if (e.key === 'Escape') {
|
|
140
|
-
e.preventDefault();
|
|
141
|
-
this.close('escape');
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
if (e.key !== 'Tab')
|
|
145
|
-
return;
|
|
146
|
-
const focusable = this.getFocusableElements();
|
|
147
|
-
if (focusable.length === 0) {
|
|
148
|
-
e.preventDefault();
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
const first = focusable[0];
|
|
152
|
-
const last = focusable[focusable.length - 1];
|
|
153
|
-
const active = this.getActiveElement();
|
|
154
|
-
if (e.shiftKey && active === first) {
|
|
155
|
-
e.preventDefault();
|
|
156
|
-
last.focus();
|
|
157
|
-
}
|
|
158
|
-
else if (!e.shiftKey && active === last) {
|
|
159
|
-
e.preventDefault();
|
|
160
|
-
first.focus();
|
|
161
|
-
}
|
|
106
|
+
this.overlay?.dismissBackdrop();
|
|
162
107
|
};
|
|
163
108
|
this.toggleEdit = () => {
|
|
164
109
|
if (this.editing) {
|
|
@@ -208,15 +153,8 @@ export class LyraToolApprovalDialog extends LyraElement {
|
|
|
208
153
|
willUpdate(changed) {
|
|
209
154
|
if (changed.has('open')) {
|
|
210
155
|
if (this.open) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
// typically lives *outside* this component entirely, so "whatever
|
|
214
|
-
// had focus right before open" is the only generally correct
|
|
215
|
-
// definition of "the trigger".
|
|
216
|
-
const active = this.getActiveElement();
|
|
217
|
-
this.lastTrigger = active instanceof HTMLElement ? active : undefined;
|
|
218
|
-
this.releaseScrollLock = lockScroll();
|
|
219
|
-
document.addEventListener('keydown', this.onDocKeyDown);
|
|
156
|
+
this.releaseScrollLock ??= lockScroll(this.ownerDocument);
|
|
157
|
+
this.activateOverlay();
|
|
220
158
|
// Every open starts fresh in the read-only view -- a reused instance
|
|
221
159
|
// must never carry a half-finished edit (or its error state) over
|
|
222
160
|
// from whatever the previous proposal was.
|
|
@@ -227,7 +165,8 @@ export class LyraToolApprovalDialog extends LyraElement {
|
|
|
227
165
|
else {
|
|
228
166
|
this.releaseScrollLock?.();
|
|
229
167
|
this.releaseScrollLock = undefined;
|
|
230
|
-
|
|
168
|
+
this.overlay?.deactivate();
|
|
169
|
+
this.overlay = undefined;
|
|
231
170
|
}
|
|
232
171
|
}
|
|
233
172
|
// A consumer flipping editable off mid-edit (e.g. a policy change
|
|
@@ -245,40 +184,53 @@ export class LyraToolApprovalDialog extends LyraElement {
|
|
|
245
184
|
// them -- mirrors lyra-dialog's identical ordering rationale.
|
|
246
185
|
updated(changed) {
|
|
247
186
|
if (changed.has('open') && this.open) {
|
|
248
|
-
|
|
249
|
-
// see the class doc's focus-management paragraph.
|
|
250
|
-
const deny = this.shadowRoot?.querySelector('[part="deny-button"]');
|
|
251
|
-
if (deny) {
|
|
252
|
-
deny.focus();
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
this.shadowRoot?.querySelector('[part="panel"]')?.focus();
|
|
256
|
-
}
|
|
187
|
+
this.overlay?.focusInitial();
|
|
257
188
|
return;
|
|
258
189
|
}
|
|
259
|
-
if (changed.has('editing')
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
190
|
+
if (changed.has('editing')) {
|
|
191
|
+
if (this.editing) {
|
|
192
|
+
// Entering edit mode is a deliberate request to start typing --
|
|
193
|
+
// steering focus into the textarea beats leaving it on the Edit
|
|
194
|
+
// button the click already left it on.
|
|
195
|
+
this.shadowRoot?.querySelector('[part="args-editor"]')?.focus();
|
|
196
|
+
}
|
|
197
|
+
else if (this.open && !this.shadowRoot?.activeElement) {
|
|
198
|
+
// Reached when editing was turned off some way other than clicking
|
|
199
|
+
// Cancel (e.g. `editable` flipping to false while the textarea held
|
|
200
|
+
// focus, in willUpdate above) -- the textarea that held focus was
|
|
201
|
+
// just unmounted without anything else claiming it, which would
|
|
202
|
+
// otherwise drop focus to <body> and silently stop the Tab trap
|
|
203
|
+
// from engaging. Refocus a stable target inside the panel instead.
|
|
204
|
+
this.shadowRoot?.querySelector('[part="deny-button"]')?.focus();
|
|
205
|
+
}
|
|
264
206
|
}
|
|
265
207
|
}
|
|
266
208
|
connectedCallback() {
|
|
267
209
|
super.connectedCallback();
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (this.hasUpdated && this.open && !this.releaseScrollLock) {
|
|
273
|
-
this.releaseScrollLock = lockScroll();
|
|
274
|
-
document.addEventListener('keydown', this.onDocKeyDown);
|
|
210
|
+
if (this.hasUpdated && this.open) {
|
|
211
|
+
this.releaseScrollLock ??= lockScroll(this.ownerDocument);
|
|
212
|
+
this.activateOverlay();
|
|
213
|
+
queueMicrotask(() => this.overlay?.focusInitial());
|
|
275
214
|
}
|
|
276
215
|
}
|
|
277
216
|
disconnectedCallback() {
|
|
278
217
|
super.disconnectedCallback();
|
|
279
218
|
this.releaseScrollLock?.();
|
|
280
219
|
this.releaseScrollLock = undefined;
|
|
281
|
-
|
|
220
|
+
this.overlay?.suspend();
|
|
221
|
+
}
|
|
222
|
+
activateOverlay() {
|
|
223
|
+
if (this.overlay?.isActive()) {
|
|
224
|
+
this.overlay.resume();
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
this.overlay = activateOverlay({
|
|
228
|
+
host: this,
|
|
229
|
+
panel: () => this.shadowRoot?.querySelector('[part="panel"]') ?? null,
|
|
230
|
+
onEscape: () => this.close('escape'),
|
|
231
|
+
onBackdrop: () => this.close('backdrop'),
|
|
232
|
+
preferredInitialFocus: () => this.shadowRoot?.querySelector('[part="deny-button"]') ?? null,
|
|
233
|
+
});
|
|
282
234
|
}
|
|
283
235
|
/**
|
|
284
236
|
* Close the dialog and return focus to whatever had it before the dialog
|
|
@@ -294,32 +246,6 @@ export class LyraToolApprovalDialog extends LyraElement {
|
|
|
294
246
|
return;
|
|
295
247
|
this.open = false;
|
|
296
248
|
this.emit('lyra-close', reason);
|
|
297
|
-
this.lastTrigger?.focus();
|
|
298
|
-
}
|
|
299
|
-
// Bounds Tab/Shift+Tab to the panel while open. Order follows the body
|
|
300
|
-
// (the json-viewer's own toggle/copy buttons, or the textarea, depending
|
|
301
|
-
// on `editing`), then the footer row (the footer slot, then Deny/Edit/
|
|
302
|
-
// Approve) -- the same order the flattened tree already tabs through.
|
|
303
|
-
// collectFocusable()'s own FOCUSABLE_SELECTOR check excludes the Approve
|
|
304
|
-
// button for free while it's `disabled`, so an invalid in-progress edit
|
|
305
|
-
// can't be Tab-trapped into.
|
|
306
|
-
getFocusableElements() {
|
|
307
|
-
const root = this.shadowRoot;
|
|
308
|
-
if (!root)
|
|
309
|
-
return [];
|
|
310
|
-
const body = root.querySelector('[part="body"]');
|
|
311
|
-
const footer = root.querySelector('[part="footer"]');
|
|
312
|
-
return [...(body ? collectFocusable(body) : []), ...(footer ? collectFocusable(footer) : [])].filter(isRendered);
|
|
313
|
-
}
|
|
314
|
-
getActiveElement() {
|
|
315
|
-
let active = document.activeElement;
|
|
316
|
-
while (active) {
|
|
317
|
-
const inner = active.shadowRoot?.activeElement ?? null;
|
|
318
|
-
if (!inner)
|
|
319
|
-
break;
|
|
320
|
-
active = inner;
|
|
321
|
-
}
|
|
322
|
-
return active;
|
|
323
249
|
}
|
|
324
250
|
stringifyArgs() {
|
|
325
251
|
try {
|
|
@@ -23,7 +23,12 @@ export interface ToolChipSelectDetail {
|
|
|
23
23
|
* a short preview) shown in a floating tooltip on hover/focus, positioned
|
|
24
24
|
* with `internal/positioner.js`'s `place()` the same way `<lyra-combobox>`
|
|
25
25
|
* positions its listbox. No tooltip is shown at all when the slot carries no
|
|
26
|
-
* content — hovering an empty chip does nothing.
|
|
26
|
+
* content — hovering an empty chip does nothing. Hover and keyboard focus are
|
|
27
|
+
* tracked as independent reasons to keep the tooltip open (mirrors
|
|
28
|
+
* `<lyra-citation-badge>`'s popover), so releasing one modality while the
|
|
29
|
+
* other is still active doesn't close it, and the trigger button's
|
|
30
|
+
* `aria-describedby` points at the tooltip's id whenever it's open and has
|
|
31
|
+
* content, so the association reaches assistive tech too.
|
|
27
32
|
*
|
|
28
33
|
* The `icon` slot overrides the built-in per-status glyph entirely via the
|
|
29
34
|
* platform's own slot-fallback-content mechanism (`<slot
|
|
@@ -56,7 +61,10 @@ export declare class LyraToolCallChip extends LyraElement {
|
|
|
56
61
|
name: string;
|
|
57
62
|
/** Optional grouping label, e.g. `research`. */
|
|
58
63
|
category: string;
|
|
59
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* The call's current lifecycle state — drives the glyph, color, and
|
|
66
|
+
* `status-text`. Invalid runtime values use the pending presentation.
|
|
67
|
+
*/
|
|
60
68
|
status: ToolCallStatus;
|
|
61
69
|
/** Short human-readable status text, e.g. `Searching web…`. */
|
|
62
70
|
summary: string;
|
|
@@ -70,15 +78,23 @@ export declare class LyraToolCallChip extends LyraElement {
|
|
|
70
78
|
callId: string;
|
|
71
79
|
private hasDetailSlot;
|
|
72
80
|
private tooltipOpen;
|
|
81
|
+
private readonly tooltipId;
|
|
73
82
|
private cleanupPositioner?;
|
|
83
|
+
private hovering;
|
|
84
|
+
private focused;
|
|
74
85
|
protected willUpdate(): void;
|
|
75
86
|
protected updated(changed: PropertyValues): void;
|
|
76
87
|
disconnectedCallback(): void;
|
|
77
88
|
private onDetailSlotChange;
|
|
78
89
|
private showTooltip;
|
|
79
90
|
private hideTooltip;
|
|
91
|
+
private onMouseEnter;
|
|
92
|
+
private onMouseLeave;
|
|
93
|
+
private onFocus;
|
|
94
|
+
private onBlur;
|
|
80
95
|
private onKeyDown;
|
|
81
96
|
private onClick;
|
|
97
|
+
private get effectiveStatus();
|
|
82
98
|
private get accessibleLabel();
|
|
83
99
|
render(): TemplateResult;
|
|
84
100
|
}
|