@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
|
@@ -10,7 +10,7 @@ export type ToolResultStatus = 'pending' | 'running' | 'success' | 'error' | 'de
|
|
|
10
10
|
* other string is whatever a caller passes to `close()` directly (e.g. a
|
|
11
11
|
* consumer's own footer action).
|
|
12
12
|
*/
|
|
13
|
-
export type ToolResultDialogCloseReason = 'escape' | 'backdrop' | 'close-button' | 'api' | string;
|
|
13
|
+
export type ToolResultDialogCloseReason = 'escape' | 'backdrop' | 'close-button' | 'api' | (string & Record<never, never>);
|
|
14
14
|
/**
|
|
15
15
|
* `<lyra-tool-result-dialog>` — a full tool-call detail overlay: a status/
|
|
16
16
|
* duration header plus a `body` slot where a consumer typically places a
|
|
@@ -34,6 +34,10 @@ export type ToolResultDialogCloseReason = 'escape' | 'backdrop' | 'close-button'
|
|
|
34
34
|
* return to, so no separate scroll-lock/focus-trap bookkeeping is needed for
|
|
35
35
|
* the transition itself.
|
|
36
36
|
*
|
|
37
|
+
* Stacking: opening more than one of these dialogs at once is supported --
|
|
38
|
+
* Escape and the Tab focus trap only ever act on the topmost open instance,
|
|
39
|
+
* so instances beneath it stay open and untouched until the one on top closes.
|
|
40
|
+
*
|
|
37
41
|
* @customElement lyra-tool-result-dialog
|
|
38
42
|
* @slot body - The dialog's main content — typically a `<lyra-tabs>` with
|
|
39
43
|
* Input/Preview/JSON/Raw panels, entirely consumer-assembled.
|
|
@@ -58,11 +62,22 @@ export type ToolResultDialogCloseReason = 'escape' | 'backdrop' | 'close-button'
|
|
|
58
62
|
*/
|
|
59
63
|
export declare class LyraToolResultDialog extends LyraElement {
|
|
60
64
|
static styles: import("lit").CSSResultGroup[];
|
|
61
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Whether the dialog is open. Set this (or call `close()`) — there is no
|
|
67
|
+
* separate `show()`/`hide()` pair. Both paths restore focus to the trigger
|
|
68
|
+
* element identically; only `close()` additionally fires
|
|
69
|
+
* `lyra-dialog-close`, since a direct assignment carries no reason string
|
|
70
|
+
* to attach to that event.
|
|
71
|
+
*/
|
|
62
72
|
open: boolean;
|
|
63
73
|
/** The tool's name, rendered prominently in the header. */
|
|
64
74
|
toolName: string;
|
|
65
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* The tool call's current lifecycle state — drives the header's status
|
|
77
|
+
* badge. An out-of-union value (e.g. a stray `status` attribute, or a
|
|
78
|
+
* direct property assignment from an untyped caller) is treated as
|
|
79
|
+
* `'pending'` rather than crashing render.
|
|
80
|
+
*/
|
|
66
81
|
status: ToolResultStatus;
|
|
67
82
|
/** How long the call took, in milliseconds. Omitted from the header entirely when unset. */
|
|
68
83
|
durationMs?: number;
|
|
@@ -70,7 +85,7 @@ export declare class LyraToolResultDialog extends LyraElement {
|
|
|
70
85
|
maximized: boolean;
|
|
71
86
|
private hasFooterSlot;
|
|
72
87
|
private releaseScrollLock?;
|
|
73
|
-
private
|
|
88
|
+
private overlay?;
|
|
74
89
|
private readonly titleId;
|
|
75
90
|
protected willUpdate(changed: PropertyValues): void;
|
|
76
91
|
protected updated(changed: PropertyValues): void;
|
|
@@ -85,14 +100,19 @@ export declare class LyraToolResultDialog extends LyraElement {
|
|
|
85
100
|
* call this directly with its own reason string, so every dismissal path
|
|
86
101
|
* funnels through the same event instead of the consumer having to also
|
|
87
102
|
* toggle `open` itself.
|
|
103
|
+
*
|
|
104
|
+
* Focus restoration follows the `open` lifecycle, so a direct `.open =
|
|
105
|
+
* false` assignment restores focus identically to calling `close()` -- the
|
|
106
|
+
* one thing a direct assignment still can't do is fire
|
|
107
|
+
* `lyra-dialog-close`, since there's no reason string to attach without
|
|
108
|
+
* going through this method.
|
|
88
109
|
*/
|
|
89
110
|
close(reason?: ToolResultDialogCloseReason): void;
|
|
90
111
|
private onBackdropClick;
|
|
91
112
|
private onCloseButtonClick;
|
|
92
113
|
private toggleMaximized;
|
|
93
|
-
private
|
|
94
|
-
private
|
|
95
|
-
private getActiveElement;
|
|
114
|
+
private activateOverlay;
|
|
115
|
+
private deactivateOverlay;
|
|
96
116
|
render(): TemplateResult;
|
|
97
117
|
}
|
|
98
118
|
declare global {
|
|
@@ -4,45 +4,15 @@ 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, svg, nothing } from 'lit';
|
|
7
|
+
import { html, svg, 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 { lockScroll } from '../../internal/scroll-lock.js';
|
|
12
|
+
import { activateOverlay } from '../../internal/overlay-manager.js';
|
|
12
13
|
import { nextId } from '../../internal/a11y.js';
|
|
13
14
|
import { closeIcon, expandIcon } from '../../internal/icons.js';
|
|
14
15
|
import { styles } from './tool-result-dialog.styles.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 (e.g.
|
|
17
|
-
// an <input> inside its own shadow root) is found even though the host tag
|
|
18
|
-
// itself doesn't match FOCUSABLE_SELECTOR. Deliberately duplicated from
|
|
19
|
-
// lyra-dialog's identical helper rather than imported/shared -- this
|
|
20
|
-
// component is its own standalone overlay with its own header chrome and
|
|
21
|
-
// must not depend on lyra-dialog (see this file's authoring notes).
|
|
22
|
-
function collectFocusable(el) {
|
|
23
|
-
const result = [];
|
|
24
|
-
if (el.matches(FOCUSABLE_SELECTOR)) {
|
|
25
|
-
result.push(el);
|
|
26
|
-
}
|
|
27
|
-
if (el instanceof HTMLSlotElement) {
|
|
28
|
-
for (const assigned of el.assignedElements({ flatten: true })) {
|
|
29
|
-
result.push(...collectFocusable(assigned));
|
|
30
|
-
}
|
|
31
|
-
return result;
|
|
32
|
-
}
|
|
33
|
-
const container = el.shadowRoot ?? el;
|
|
34
|
-
for (const child of Array.from(container.children)) {
|
|
35
|
-
result.push(...collectFocusable(child));
|
|
36
|
-
}
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
/** Whether `el` is actually laid out/paintable -- `checkVisibility()` (falling
|
|
40
|
-
* back to `getClientRects().length` where unsupported) correctly follows
|
|
41
|
-
* flattened-tree/slot assignment, unlike `offsetParent`. Mirrors
|
|
42
|
-
* lyra-dialog's/lyra-widget's identical helper. */
|
|
43
|
-
function isRendered(el) {
|
|
44
|
-
return el.checkVisibility ? el.checkVisibility() : el.getClientRects().length > 0;
|
|
45
|
-
}
|
|
46
16
|
// Mirrors the shared icon set's viewBox/stroke conventions
|
|
47
17
|
// (internal/icons.ts's chevronIcon()/closeIcon()/etc.) without adding
|
|
48
18
|
// tool-result-specific glyphs to that module -- it's off limits here -- so
|
|
@@ -121,6 +91,24 @@ const STATUS_LABEL = {
|
|
|
121
91
|
error: 'Error',
|
|
122
92
|
denied: 'Denied',
|
|
123
93
|
};
|
|
94
|
+
const STATUS_VALUES = new Set(Object.keys(STATUS_LABEL));
|
|
95
|
+
/**
|
|
96
|
+
* Normalizes `status` at the attribute boundary -- an out-of-union value
|
|
97
|
+
* (markup a caller doesn't fully control, or a raw string from an untyped
|
|
98
|
+
* consumer) falls back to `'pending'` here rather than reaching
|
|
99
|
+
* STATUS_ICON/STATUS_LABEL as a bad lookup key and crashing `render()`. This
|
|
100
|
+
* only covers attribute parsing; a `.status = ...` assignment made directly
|
|
101
|
+
* as a property bypasses converters entirely, which is why `render()` below
|
|
102
|
+
* also falls back at the STATUS_ICON/STATUS_LABEL lookup itself.
|
|
103
|
+
*/
|
|
104
|
+
const statusConverter = {
|
|
105
|
+
fromAttribute(value) {
|
|
106
|
+
return value !== null && STATUS_VALUES.has(value) ? value : 'pending';
|
|
107
|
+
},
|
|
108
|
+
toAttribute(value) {
|
|
109
|
+
return value;
|
|
110
|
+
},
|
|
111
|
+
};
|
|
124
112
|
/** `820` -> `"820ms"`; `1500` -> `"1.5s"`; `2000` -> `"2s"`. Sub-second
|
|
125
113
|
* durations are the common case for a single tool call, so they get the
|
|
126
114
|
* more precise unit; once a call runs a full second or longer, trimming to
|
|
@@ -157,6 +145,10 @@ function formatDuration(ms) {
|
|
|
157
145
|
* return to, so no separate scroll-lock/focus-trap bookkeeping is needed for
|
|
158
146
|
* the transition itself.
|
|
159
147
|
*
|
|
148
|
+
* Stacking: opening more than one of these dialogs at once is supported --
|
|
149
|
+
* Escape and the Tab focus trap only ever act on the topmost open instance,
|
|
150
|
+
* so instances beneath it stay open and untouched until the one on top closes.
|
|
151
|
+
*
|
|
160
152
|
* @customElement lyra-tool-result-dialog
|
|
161
153
|
* @slot body - The dialog's main content — typically a `<lyra-tabs>` with
|
|
162
154
|
* Input/Preview/JSON/Raw panels, entirely consumer-assembled.
|
|
@@ -182,11 +174,22 @@ function formatDuration(ms) {
|
|
|
182
174
|
export class LyraToolResultDialog extends LyraElement {
|
|
183
175
|
constructor() {
|
|
184
176
|
super(...arguments);
|
|
185
|
-
/**
|
|
177
|
+
/**
|
|
178
|
+
* Whether the dialog is open. Set this (or call `close()`) — there is no
|
|
179
|
+
* separate `show()`/`hide()` pair. Both paths restore focus to the trigger
|
|
180
|
+
* element identically; only `close()` additionally fires
|
|
181
|
+
* `lyra-dialog-close`, since a direct assignment carries no reason string
|
|
182
|
+
* to attach to that event.
|
|
183
|
+
*/
|
|
186
184
|
this.open = false;
|
|
187
185
|
/** The tool's name, rendered prominently in the header. */
|
|
188
186
|
this.toolName = '';
|
|
189
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* The tool call's current lifecycle state — drives the header's status
|
|
189
|
+
* badge. An out-of-union value (e.g. a stray `status` attribute, or a
|
|
190
|
+
* direct property assignment from an untyped caller) is treated as
|
|
191
|
+
* `'pending'` rather than crashing render.
|
|
192
|
+
*/
|
|
190
193
|
this.status = 'pending';
|
|
191
194
|
/** Near-fullscreen presentation of the same open dialog. */
|
|
192
195
|
this.maximized = false;
|
|
@@ -196,7 +199,7 @@ export class LyraToolResultDialog extends LyraElement {
|
|
|
196
199
|
this.hasFooterSlot = e.target.assignedElements({ flatten: true }).length > 0;
|
|
197
200
|
};
|
|
198
201
|
this.onBackdropClick = () => {
|
|
199
|
-
this.
|
|
202
|
+
this.overlay?.dismissBackdrop();
|
|
200
203
|
};
|
|
201
204
|
this.onCloseButtonClick = () => {
|
|
202
205
|
this.close('close-button');
|
|
@@ -205,33 +208,6 @@ export class LyraToolResultDialog extends LyraElement {
|
|
|
205
208
|
this.maximized = !this.maximized;
|
|
206
209
|
this.emit('lyra-maximize-change', this.maximized);
|
|
207
210
|
};
|
|
208
|
-
this.onDocKeyDown = (e) => {
|
|
209
|
-
if (!this.open)
|
|
210
|
-
return;
|
|
211
|
-
if (e.key === 'Escape') {
|
|
212
|
-
e.preventDefault();
|
|
213
|
-
this.close('escape');
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (e.key !== 'Tab')
|
|
217
|
-
return;
|
|
218
|
-
const focusable = this.getFocusableElements();
|
|
219
|
-
if (focusable.length === 0) {
|
|
220
|
-
e.preventDefault();
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
const first = focusable[0];
|
|
224
|
-
const last = focusable[focusable.length - 1];
|
|
225
|
-
const active = this.getActiveElement();
|
|
226
|
-
if (e.shiftKey && active === first) {
|
|
227
|
-
e.preventDefault();
|
|
228
|
-
last.focus();
|
|
229
|
-
}
|
|
230
|
-
else if (!e.shiftKey && active === last) {
|
|
231
|
-
e.preventDefault();
|
|
232
|
-
first.focus();
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
211
|
}
|
|
236
212
|
static { this.styles = [LyraElement.styles, styles]; }
|
|
237
213
|
willUpdate(changed) {
|
|
@@ -240,35 +216,18 @@ export class LyraToolResultDialog extends LyraElement {
|
|
|
240
216
|
}
|
|
241
217
|
if (changed.has('open')) {
|
|
242
218
|
if (this.open) {
|
|
243
|
-
|
|
244
|
-
// some specific internal control -- like lyra-dialog, a trigger
|
|
245
|
-
// typically lives *outside* this component entirely, so "whatever
|
|
246
|
-
// had focus right before open" is the only generally correct
|
|
247
|
-
// definition of "the trigger".
|
|
248
|
-
const active = this.getActiveElement();
|
|
249
|
-
this.lastTrigger = active instanceof HTMLElement ? active : undefined;
|
|
250
|
-
this.releaseScrollLock = lockScroll();
|
|
251
|
-
document.addEventListener('keydown', this.onDocKeyDown);
|
|
219
|
+
this.activateOverlay();
|
|
252
220
|
}
|
|
253
221
|
else {
|
|
254
|
-
this.
|
|
255
|
-
this.releaseScrollLock = undefined;
|
|
256
|
-
document.removeEventListener('keydown', this.onDocKeyDown);
|
|
222
|
+
this.deactivateOverlay();
|
|
257
223
|
}
|
|
258
224
|
}
|
|
259
225
|
}
|
|
260
|
-
// Runs after render
|
|
261
|
-
//
|
|
262
|
-
// mirrors lyra-dialog's identical ordering rationale.
|
|
226
|
+
// Runs after render so the manager can resolve the panel and its composed
|
|
227
|
+
// focus targets, including controls projected through either slot.
|
|
263
228
|
updated(changed) {
|
|
264
229
|
if (changed.has('open') && this.open) {
|
|
265
|
-
|
|
266
|
-
if (first) {
|
|
267
|
-
first.focus();
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
this.shadowRoot?.querySelector('[part="panel"]')?.focus();
|
|
271
|
-
}
|
|
230
|
+
this.overlay?.focusInitial();
|
|
272
231
|
}
|
|
273
232
|
}
|
|
274
233
|
connectedCallback() {
|
|
@@ -277,16 +236,22 @@ export class LyraToolResultDialog extends LyraElement {
|
|
|
277
236
|
// instance) fires disconnectedCallback then connectedCallback
|
|
278
237
|
// synchronously with no update in between, so willUpdate never reruns to
|
|
279
238
|
// notice `open` is still true -- restore the scroll lock/trap it dropped.
|
|
280
|
-
if (this.hasUpdated && this.open
|
|
281
|
-
this.
|
|
282
|
-
|
|
239
|
+
if (this.hasUpdated && this.open) {
|
|
240
|
+
if (this.overlay?.isActive()) {
|
|
241
|
+
this.overlay.resume();
|
|
242
|
+
this.releaseScrollLock ??= lockScroll(this.ownerDocument);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
this.activateOverlay();
|
|
246
|
+
}
|
|
247
|
+
queueMicrotask(() => this.overlay?.focusInitial());
|
|
283
248
|
}
|
|
284
249
|
}
|
|
285
250
|
disconnectedCallback() {
|
|
286
251
|
super.disconnectedCallback();
|
|
287
252
|
this.releaseScrollLock?.();
|
|
288
253
|
this.releaseScrollLock = undefined;
|
|
289
|
-
|
|
254
|
+
this.overlay?.suspend();
|
|
290
255
|
}
|
|
291
256
|
/**
|
|
292
257
|
* Close the dialog and return focus to whatever had it before the dialog
|
|
@@ -296,39 +261,35 @@ export class LyraToolResultDialog extends LyraElement {
|
|
|
296
261
|
* call this directly with its own reason string, so every dismissal path
|
|
297
262
|
* funnels through the same event instead of the consumer having to also
|
|
298
263
|
* toggle `open` itself.
|
|
264
|
+
*
|
|
265
|
+
* Focus restoration follows the `open` lifecycle, so a direct `.open =
|
|
266
|
+
* false` assignment restores focus identically to calling `close()` -- the
|
|
267
|
+
* one thing a direct assignment still can't do is fire
|
|
268
|
+
* `lyra-dialog-close`, since there's no reason string to attach without
|
|
269
|
+
* going through this method.
|
|
299
270
|
*/
|
|
300
271
|
close(reason = 'api') {
|
|
301
272
|
if (!this.open)
|
|
302
273
|
return;
|
|
303
274
|
this.open = false;
|
|
304
275
|
this.emit('lyra-dialog-close', reason);
|
|
305
|
-
this.lastTrigger?.focus();
|
|
306
276
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const slot = root.querySelector(selector);
|
|
318
|
-
return slot ? slot.assignedElements({ flatten: true }).flatMap(collectFocusable) : [];
|
|
319
|
-
};
|
|
320
|
-
const headerButtons = Array.from(root.querySelectorAll('[part="maximize-button"], [part="close-button"]'));
|
|
321
|
-
return [...headerButtons, ...fromSlot('slot[name="body"]'), ...fromSlot('slot[name="footer"]')].filter(isRendered);
|
|
277
|
+
activateOverlay() {
|
|
278
|
+
if (this.overlay?.isActive())
|
|
279
|
+
return;
|
|
280
|
+
this.releaseScrollLock ??= lockScroll(this.ownerDocument);
|
|
281
|
+
this.overlay = activateOverlay({
|
|
282
|
+
host: this,
|
|
283
|
+
panel: () => this.shadowRoot?.querySelector('[part="panel"]') ?? null,
|
|
284
|
+
onEscape: () => this.close('escape'),
|
|
285
|
+
onBackdrop: () => this.close('backdrop'),
|
|
286
|
+
});
|
|
322
287
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
break;
|
|
329
|
-
active = inner;
|
|
330
|
-
}
|
|
331
|
-
return active;
|
|
288
|
+
deactivateOverlay() {
|
|
289
|
+
this.releaseScrollLock?.();
|
|
290
|
+
this.releaseScrollLock = undefined;
|
|
291
|
+
this.overlay?.deactivate();
|
|
292
|
+
this.overlay = undefined;
|
|
332
293
|
}
|
|
333
294
|
render() {
|
|
334
295
|
const hasDuration = this.durationMs != null;
|
|
@@ -344,7 +305,11 @@ export class LyraToolResultDialog extends LyraElement {
|
|
|
344
305
|
<div part="header">
|
|
345
306
|
<div part="title">
|
|
346
307
|
<span part="tool-name" id=${this.titleId}>${this.toolName || 'Tool call'}</span>
|
|
347
|
-
<span part="status"
|
|
308
|
+
<span part="status"
|
|
309
|
+
>${(STATUS_ICON[this.status] ?? STATUS_ICON.pending)()}<span
|
|
310
|
+
>${STATUS_LABEL[this.status] ?? STATUS_LABEL.pending}</span
|
|
311
|
+
></span
|
|
312
|
+
>
|
|
348
313
|
${hasDuration ? html `<span part="duration">${formatDuration(this.durationMs)}</span>` : nothing}
|
|
349
314
|
</div>
|
|
350
315
|
<div part="header-actions">
|
|
@@ -379,7 +344,7 @@ __decorate([
|
|
|
379
344
|
property({ attribute: 'tool-name' })
|
|
380
345
|
], LyraToolResultDialog.prototype, "toolName", void 0);
|
|
381
346
|
__decorate([
|
|
382
|
-
property({ reflect: true })
|
|
347
|
+
property({ reflect: true, converter: statusConverter })
|
|
383
348
|
], LyraToolResultDialog.prototype, "status", void 0);
|
|
384
349
|
__decorate([
|
|
385
350
|
property({ type: Number, attribute: 'duration-ms' })
|
|
@@ -71,11 +71,3 @@ export declare function findToolRenderer(toolName: string, payload: unknown, reg
|
|
|
71
71
|
* failed promise forever.
|
|
72
72
|
*/
|
|
73
73
|
export declare function loadToolRenderer(def: ToolRendererDefinition): Promise<ToolRendererDefinition>;
|
|
74
|
-
/**
|
|
75
|
-
* Test-only utility: empties the default registry and its `load()` cache so
|
|
76
|
-
* one test's `registerToolRenderer()` calls can't leak into the next. Mirrors
|
|
77
|
-
* the fact that this module (like `toaster.ts`'s per-placement region map) is
|
|
78
|
-
* deliberately singleton, module-level state -- there is no per-instance
|
|
79
|
-
* registry to construct fresh in a test's own `fixture()` call instead.
|
|
80
|
-
*/
|
|
81
|
-
export declare function clearToolRenderers(): void;
|
|
@@ -72,11 +72,16 @@ export function loadToolRenderer(def) {
|
|
|
72
72
|
return promise;
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
|
-
* Test-only utility: empties the default registry and its `load()` cache so
|
|
75
|
+
* @internal Test-only utility: empties the default registry and its `load()` cache so
|
|
76
76
|
* one test's `registerToolRenderer()` calls can't leak into the next. Mirrors
|
|
77
77
|
* the fact that this module (like `toaster.ts`'s per-placement region map) is
|
|
78
78
|
* deliberately singleton, module-level state -- there is no per-instance
|
|
79
|
-
* registry to construct fresh in a test's own `fixture()` call instead.
|
|
79
|
+
* registry to construct fresh in a test's own `fixture()` call instead. Not
|
|
80
|
+
* part of the public API; not re-exported from the root barrel -- a
|
|
81
|
+
* consuming app has no legitimate reason to wipe this page's entire
|
|
82
|
+
* registered-renderer registry at runtime, only a test suite resetting
|
|
83
|
+
* state between cases (import directly from this module, as the test suite
|
|
84
|
+
* already does).
|
|
80
85
|
*/
|
|
81
86
|
export function clearToolRenderers() {
|
|
82
87
|
defaultRegistry.clear();
|
|
@@ -7,8 +7,9 @@ import '../json-viewer/json-viewer.js';
|
|
|
7
7
|
* `<lyra-tool-result-view>` — renders a tool call's result via whichever
|
|
8
8
|
* custom renderer a host app has registered for it (see `registerToolRenderer()`
|
|
9
9
|
* in `registry.ts`), falling back to `<lyra-json-viewer>` whenever no
|
|
10
|
-
* renderer matches, a renderer's
|
|
11
|
-
*
|
|
10
|
+
* renderer matches, a candidate renderer's `matches()` predicate throws during
|
|
11
|
+
* dispatch, a renderer's optional `load()` rejects, or its `render()` throws.
|
|
12
|
+
* This component owns none of the actual visual weight of a
|
|
12
13
|
* populated tool result — that's entirely whatever the registered renderer
|
|
13
14
|
* returns; this is just the dispatch + fallback + loading-state shell.
|
|
14
15
|
*
|
|
@@ -25,7 +26,8 @@ import '../json-viewer/json-viewer.js';
|
|
|
25
26
|
* @customElement lyra-tool-result-view
|
|
26
27
|
* @event lyra-render-error - `detail: { toolName, error }` — fired immediately
|
|
27
28
|
* before falling back to `<lyra-json-viewer>`, whether because no renderer
|
|
28
|
-
* matched, a renderer's `
|
|
29
|
+
* matched, a candidate renderer's `matches()` predicate threw during dispatch,
|
|
30
|
+
* a renderer's `load()` rejected, or its `render()` threw.
|
|
29
31
|
* @csspart base - The root wrapper around the resolved renderer's output (or the loading/fallback view).
|
|
30
32
|
*/
|
|
31
33
|
export declare class LyraToolResultView extends LyraElement {
|
|
@@ -42,6 +44,7 @@ export declare class LyraToolResultView extends LyraElement {
|
|
|
42
44
|
fallback: string;
|
|
43
45
|
private renderState;
|
|
44
46
|
private generation;
|
|
47
|
+
private resolvedLazy?;
|
|
45
48
|
protected willUpdate(changed: PropertyValues): void;
|
|
46
49
|
private resolve;
|
|
47
50
|
private renderWith;
|
|
@@ -17,8 +17,9 @@ const FALLBACK_STATE = { kind: 'fallback' };
|
|
|
17
17
|
* `<lyra-tool-result-view>` — renders a tool call's result via whichever
|
|
18
18
|
* custom renderer a host app has registered for it (see `registerToolRenderer()`
|
|
19
19
|
* in `registry.ts`), falling back to `<lyra-json-viewer>` whenever no
|
|
20
|
-
* renderer matches, a renderer's
|
|
21
|
-
*
|
|
20
|
+
* renderer matches, a candidate renderer's `matches()` predicate throws during
|
|
21
|
+
* dispatch, a renderer's optional `load()` rejects, or its `render()` throws.
|
|
22
|
+
* This component owns none of the actual visual weight of a
|
|
22
23
|
* populated tool result — that's entirely whatever the registered renderer
|
|
23
24
|
* returns; this is just the dispatch + fallback + loading-state shell.
|
|
24
25
|
*
|
|
@@ -35,7 +36,8 @@ const FALLBACK_STATE = { kind: 'fallback' };
|
|
|
35
36
|
* @customElement lyra-tool-result-view
|
|
36
37
|
* @event lyra-render-error - `detail: { toolName, error }` — fired immediately
|
|
37
38
|
* before falling back to `<lyra-json-viewer>`, whether because no renderer
|
|
38
|
-
* matched, a renderer's `
|
|
39
|
+
* matched, a candidate renderer's `matches()` predicate threw during dispatch,
|
|
40
|
+
* a renderer's `load()` rejected, or its `render()` threw.
|
|
39
41
|
* @csspart base - The root wrapper around the resolved renderer's output (or the loading/fallback view).
|
|
40
42
|
*/
|
|
41
43
|
export class LyraToolResultView extends LyraElement {
|
|
@@ -64,12 +66,23 @@ export class LyraToolResultView extends LyraElement {
|
|
|
64
66
|
async resolve() {
|
|
65
67
|
const generation = ++this.generation;
|
|
66
68
|
const registry = this.registry ?? getDefaultToolRendererRegistry();
|
|
67
|
-
|
|
69
|
+
let def;
|
|
70
|
+
try {
|
|
71
|
+
def = findToolRenderer(this.toolName, this.result, registry);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
this.fail(error);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
68
77
|
if (!def) {
|
|
69
78
|
this.fail(new Error(`<lyra-tool-result-view>: no renderer registered for tool "${this.toolName}"`));
|
|
70
79
|
return;
|
|
71
80
|
}
|
|
72
81
|
if (def.load) {
|
|
82
|
+
if (this.resolvedLazy?.def === def) {
|
|
83
|
+
this.renderWith(this.resolvedLazy.resolved);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
73
86
|
this.renderState = { kind: 'loading' };
|
|
74
87
|
let resolved;
|
|
75
88
|
try {
|
|
@@ -83,6 +96,7 @@ export class LyraToolResultView extends LyraElement {
|
|
|
83
96
|
}
|
|
84
97
|
if (generation !== this.generation)
|
|
85
98
|
return;
|
|
99
|
+
this.resolvedLazy = { def, resolved };
|
|
86
100
|
this.renderWith(resolved);
|
|
87
101
|
return;
|
|
88
102
|
}
|
|
@@ -39,11 +39,10 @@ export type ToolSelectDialogCloseReason = 'escape' | 'backdrop' | 'api' | string
|
|
|
39
39
|
* tool-enablement dialog for picking which agent tools are available in a
|
|
40
40
|
* conversation.
|
|
41
41
|
*
|
|
42
|
-
* This
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* duplicates that pattern locally instead of composing the previous one.
|
|
42
|
+
* This renders its own dialog panel rather than nesting a `<lyra-dialog>` in
|
|
43
|
+
* its shadow template. Shared overlay infrastructure coordinates stacking,
|
|
44
|
+
* focus trapping, Escape/backdrop dismissal, and focus return with every
|
|
45
|
+
* other overlay in the same document.
|
|
47
46
|
*
|
|
48
47
|
* `useDefaults` is a single top-level switch: while `true`, every per-tool
|
|
49
48
|
* checkbox below renders disabled (still reflecting whatever `selected`
|
|
@@ -81,14 +80,17 @@ export type ToolSelectDialogCloseReason = 'escape' | 'backdrop' | 'api' | string
|
|
|
81
80
|
* @csspart empty - The "no tools" / "no matches" message.
|
|
82
81
|
* @csspart category - A single category's wrapper (`role="group"`).
|
|
83
82
|
* @csspart category-heading - A category's heading.
|
|
84
|
-
* @csspart category-count - The
|
|
83
|
+
* @csspart category-count - The terse, `aria-hidden` tool count next to a category heading
|
|
84
|
+
* (the heading's accessible name gets the full sentence from an sr-only sibling instead).
|
|
85
85
|
* @csspart category-list - The `<ul>` of tool rows within a category.
|
|
86
86
|
* @csspart tool-row - A single tool's `<li>` row.
|
|
87
87
|
* @csspart tool-checkbox - A row's `<lyra-checkbox>`.
|
|
88
88
|
* @csspart tool-name - A row's name text (plus its `icon`, if set).
|
|
89
89
|
* @csspart tool-icon - A row's leading icon glyph, when `icon` is set.
|
|
90
90
|
* @csspart tool-description - A row's optional description text.
|
|
91
|
-
* @csspart tool-disabled-reason - A disabled row's `disabledReason` text
|
|
91
|
+
* @csspart tool-disabled-reason - A disabled row's `disabledReason` text, slotted inside
|
|
92
|
+
* `tool-checkbox` (alongside `tool-name`/`tool-description`) so it contributes to the
|
|
93
|
+
* checkbox's accessible name/description instead of going unannounced.
|
|
92
94
|
* @csspart footer - The wrapper around the `footer` slot.
|
|
93
95
|
*/
|
|
94
96
|
export declare class LyraToolSelectDialog extends LyraElement {
|
|
@@ -109,13 +111,14 @@ export declare class LyraToolSelectDialog extends LyraElement {
|
|
|
109
111
|
private query;
|
|
110
112
|
private hasFooterSlot;
|
|
111
113
|
private releaseScrollLock?;
|
|
112
|
-
private
|
|
114
|
+
private overlay?;
|
|
113
115
|
private readonly titleId;
|
|
114
116
|
private readonly categoryIds;
|
|
115
117
|
protected willUpdate(changed: PropertyValues): void;
|
|
116
118
|
protected updated(changed: PropertyValues): void;
|
|
117
119
|
connectedCallback(): void;
|
|
118
120
|
disconnectedCallback(): void;
|
|
121
|
+
private activateOverlay;
|
|
119
122
|
private onFooterSlotChange;
|
|
120
123
|
/**
|
|
121
124
|
* Close the dialog and return focus to whatever had it before the dialog
|
|
@@ -127,9 +130,6 @@ export declare class LyraToolSelectDialog extends LyraElement {
|
|
|
127
130
|
*/
|
|
128
131
|
close(reason?: ToolSelectDialogCloseReason): void;
|
|
129
132
|
private onBackdropClick;
|
|
130
|
-
private onDocKeyDown;
|
|
131
|
-
private getFocusableElements;
|
|
132
|
-
private getActiveElement;
|
|
133
133
|
private emitChange;
|
|
134
134
|
private onSearchInput;
|
|
135
135
|
private onDefaultsToggle;
|