@aceshooting/lyra-ui 1.2.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 +98 -14
- package/custom-elements.json +30279 -12124
- 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 +168 -0
- package/dist/components/app-rail/app-rail.js +419 -0
- package/dist/components/app-rail/app-rail.styles.d.ts +1 -0
- package/dist/components/app-rail/app-rail.styles.js +128 -0
- package/dist/components/attachment-chip/attachment-chip.d.ts +141 -0
- package/dist/components/attachment-chip/attachment-chip.js +356 -0
- package/dist/components/attachment-chip/attachment-chip.styles.d.ts +1 -0
- package/dist/components/attachment-chip/attachment-chip.styles.js +184 -0
- package/dist/components/attachment-trigger/attachment-trigger.d.ts +96 -0
- package/dist/components/attachment-trigger/attachment-trigger.js +270 -0
- package/dist/components/attachment-trigger/attachment-trigger.styles.d.ts +1 -0
- package/dist/components/attachment-trigger/attachment-trigger.styles.js +90 -0
- 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 +147 -7
- package/dist/components/chart/box-plot.styles.js +13 -0
- package/dist/components/chart/bubble-chart.js +2 -18
- package/dist/components/chart/chart-loader.d.ts +44 -13
- package/dist/components/chart/chart-loader.js +65 -18
- package/dist/components/chart/chart.d.ts +55 -12
- package/dist/components/chart/chart.js +247 -49
- package/dist/components/chart/doughnut-chart.js +2 -18
- package/dist/components/chart/histogram-bin.d.ts +7 -1
- package/dist/components/chart/histogram-bin.js +32 -14
- 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 +134 -3
- package/dist/components/chart/lite-chart.js +382 -67
- package/dist/components/chart/lite-chart.styles.js +9 -0
- 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 +133 -0
- package/dist/components/chat-composer/chat-composer.js +366 -0
- package/dist/components/chat-composer/chat-composer.styles.d.ts +1 -0
- package/dist/components/chat-composer/chat-composer.styles.js +145 -0
- package/dist/components/chat-message/chat-message.d.ts +141 -0
- package/dist/components/chat-message/chat-message.js +331 -0
- package/dist/components/chat-message/chat-message.styles.d.ts +1 -0
- package/dist/components/chat-message/chat-message.styles.js +203 -0
- package/dist/components/checkbox/checkbox.d.ts +117 -0
- package/dist/components/checkbox/checkbox.js +353 -0
- package/dist/components/checkbox/checkbox.styles.d.ts +1 -0
- package/dist/components/checkbox/checkbox.styles.js +77 -0
- package/dist/components/chip/chip-group.d.ts +56 -0
- package/dist/components/chip/chip-group.js +130 -0
- package/dist/components/chip/chip-group.styles.d.ts +1 -0
- package/dist/components/chip/chip-group.styles.js +57 -0
- package/dist/components/chip/chip.d.ts +64 -0
- package/dist/components/chip/chip.js +122 -0
- package/dist/components/chip/chip.styles.d.ts +1 -0
- package/dist/components/chip/chip.styles.js +115 -0
- package/dist/components/citation-badge/citation-badge.d.ts +113 -0
- package/dist/components/citation-badge/citation-badge.js +318 -0
- package/dist/components/citation-badge/citation-badge.styles.d.ts +1 -0
- package/dist/components/citation-badge/citation-badge.styles.js +96 -0
- package/dist/components/code-block/code-block.d.ts +127 -0
- package/dist/components/code-block/code-block.js +382 -0
- package/dist/components/code-block/code-block.styles.d.ts +1 -0
- package/dist/components/code-block/code-block.styles.js +187 -0
- package/dist/components/code-block/code-loader.d.ts +87 -0
- package/dist/components/code-block/code-loader.js +142 -0
- package/dist/components/combobox/combobox.d.ts +65 -6
- package/dist/components/combobox/combobox.js +258 -48
- package/dist/components/combobox/combobox.styles.js +3 -3
- package/dist/components/combobox/option.d.ts +5 -1
- package/dist/components/combobox/option.js +35 -0
- package/dist/components/context-meter/context-meter.d.ts +53 -0
- package/dist/components/context-meter/context-meter.js +159 -0
- package/dist/components/context-meter/context-meter.styles.d.ts +1 -0
- package/dist/components/context-meter/context-meter.styles.js +114 -0
- package/dist/components/conversation-item/conversation-item.d.ts +125 -0
- package/dist/components/conversation-item/conversation-item.js +331 -0
- package/dist/components/conversation-item/conversation-item.styles.d.ts +1 -0
- package/dist/components/conversation-item/conversation-item.styles.js +155 -0
- 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 +100 -9
- package/dist/components/date-picker/date-input.js +383 -66
- package/dist/components/date-picker/date-picker.d.ts +35 -4
- package/dist/components/date-picker/date-picker.js +171 -44
- package/dist/components/dialog/confirm.d.ts +40 -0
- package/dist/components/dialog/confirm.js +76 -0
- package/dist/components/dialog/dialog.d.ts +129 -0
- package/dist/components/dialog/dialog.js +288 -0
- package/dist/components/dialog/dialog.styles.d.ts +1 -0
- package/dist/components/dialog/dialog.styles.js +96 -0
- package/dist/components/dock-panel/dock-panel.d.ts +142 -0
- package/dist/components/dock-panel/dock-panel.js +359 -0
- package/dist/components/dock-panel/dock-panel.styles.d.ts +1 -0
- package/dist/components/dock-panel/dock-panel.styles.js +159 -0
- package/dist/components/document-preview/document-preview.d.ts +143 -0
- package/dist/components/document-preview/document-preview.js +388 -0
- package/dist/components/document-preview/document-preview.styles.d.ts +1 -0
- package/dist/components/document-preview/document-preview.styles.js +191 -0
- 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/csv.js +1 -1
- package/dist/components/export-button/export-button.d.ts +12 -0
- package/dist/components/export-button/export-button.js +35 -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 +29 -13
- package/dist/components/flag/flag.js +54 -14
- 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 +41 -13
- package/dist/components/generation-status/generation-status.d.ts +117 -0
- package/dist/components/generation-status/generation-status.js +327 -0
- package/dist/components/generation-status/generation-status.styles.d.ts +1 -0
- package/dist/components/generation-status/generation-status.styles.js +84 -0
- 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 +19 -7
- package/dist/components/heatmap/calendar-grid.js +42 -18
- package/dist/components/heatmap/heatmap-scale.d.ts +11 -1
- package/dist/components/heatmap/heatmap-scale.js +14 -2
- package/dist/components/heatmap/heatmap.d.ts +227 -12
- package/dist/components/heatmap/heatmap.js +488 -93
- package/dist/components/json-viewer/json-viewer.d.ts +70 -0
- package/dist/components/json-viewer/json-viewer.js +361 -0
- package/dist/components/json-viewer/json-viewer.styles.d.ts +1 -0
- package/dist/components/json-viewer/json-viewer.styles.js +177 -0
- package/dist/components/kbd/kbd.d.ts +77 -0
- package/dist/components/kbd/kbd.js +231 -0
- package/dist/components/kbd/kbd.styles.d.ts +1 -0
- package/dist/components/kbd/kbd.styles.js +52 -0
- package/dist/components/live-region/live-region.d.ts +90 -0
- package/dist/components/live-region/live-region.js +189 -0
- package/dist/components/live-region/live-region.styles.d.ts +1 -0
- package/dist/components/live-region/live-region.styles.js +10 -0
- package/dist/components/map/map.d.ts +32 -7
- package/dist/components/map/map.js +133 -32
- package/dist/components/markdown/markdown-loader.d.ts +58 -0
- package/dist/components/markdown/markdown-loader.js +77 -0
- package/dist/components/markdown/markdown.d.ts +119 -0
- package/dist/components/markdown/markdown.js +389 -0
- package/dist/components/markdown/markdown.styles.d.ts +1 -0
- package/dist/components/markdown/markdown.styles.js +88 -0
- package/dist/components/media-card/media-card.d.ts +130 -0
- package/dist/components/media-card/media-card.js +273 -0
- package/dist/components/media-card/media-card.styles.d.ts +1 -0
- package/dist/components/media-card/media-card.styles.js +132 -0
- package/dist/components/mention-popover/mention-popover.d.ts +203 -0
- package/dist/components/mention-popover/mention-popover.js +493 -0
- package/dist/components/mention-popover/mention-popover.styles.d.ts +1 -0
- package/dist/components/mention-popover/mention-popover.styles.js +101 -0
- package/dist/components/menu/menu-item.d.ts +91 -0
- package/dist/components/menu/menu-item.js +206 -0
- package/dist/components/menu/menu-item.styles.d.ts +1 -0
- package/dist/components/menu/menu-item.styles.js +75 -0
- package/dist/components/menu/menu.d.ts +167 -0
- package/dist/components/menu/menu.js +461 -0
- package/dist/components/menu/menu.styles.d.ts +1 -0
- package/dist/components/menu/menu.styles.js +67 -0
- package/dist/components/model-select/model-select.d.ts +170 -0
- package/dist/components/model-select/model-select.js +588 -0
- package/dist/components/model-select/model-select.styles.d.ts +1 -0
- package/dist/components/model-select/model-select.styles.js +203 -0
- package/dist/components/model-settings-panel/model-settings-panel.d.ts +93 -0
- package/dist/components/model-settings-panel/model-settings-panel.js +209 -0
- package/dist/components/model-settings-panel/model-settings-panel.styles.d.ts +1 -0
- package/dist/components/model-settings-panel/model-settings-panel.styles.js +82 -0
- package/dist/components/playback/playback.d.ts +19 -3
- package/dist/components/playback/playback.js +109 -33
- package/dist/components/playback/playback.styles.js +6 -1
- package/dist/components/responsive-panel/responsive-panel.d.ts +163 -0
- package/dist/components/responsive-panel/responsive-panel.js +363 -0
- package/dist/components/responsive-panel/responsive-panel.styles.d.ts +1 -0
- package/dist/components/responsive-panel/responsive-panel.styles.js +103 -0
- package/dist/components/result-card/result-card.d.ts +50 -0
- package/dist/components/result-card/result-card.js +89 -0
- package/dist/components/result-card/result-card.styles.d.ts +1 -0
- package/dist/components/result-card/result-card.styles.js +49 -0
- package/dist/components/result-card/result-field.d.ts +36 -0
- package/dist/components/result-card/result-field.js +87 -0
- package/dist/components/result-card/result-field.styles.d.ts +1 -0
- package/dist/components/result-card/result-field.styles.js +32 -0
- package/dist/components/select/select.d.ts +84 -4
- package/dist/components/select/select.js +251 -36
- 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 +141 -0
- package/dist/components/slider/slider.js +467 -0
- package/dist/components/slider/slider.styles.d.ts +1 -0
- package/dist/components/slider/slider.styles.js +87 -0
- package/dist/components/source-card/source-card.d.ts +104 -0
- package/dist/components/source-card/source-card.js +195 -0
- package/dist/components/source-card/source-card.styles.d.ts +1 -0
- package/dist/components/source-card/source-card.styles.js +69 -0
- package/dist/components/source-list/source-list.d.ts +63 -0
- package/dist/components/source-list/source-list.js +130 -0
- package/dist/components/source-list/source-list.styles.d.ts +1 -0
- package/dist/components/source-list/source-list.styles.js +59 -0
- package/dist/components/sparkline/sparkline.js +58 -20
- package/dist/components/split/split.d.ts +224 -5
- package/dist/components/split/split.js +617 -43
- package/dist/components/split/split.styles.js +47 -0
- package/dist/components/stat/stat.d.ts +15 -4
- package/dist/components/stat/stat.js +53 -12
- package/dist/components/stream-status/stream-status.d.ts +126 -0
- package/dist/components/stream-status/stream-status.js +292 -0
- package/dist/components/stream-status/stream-status.styles.d.ts +1 -0
- package/dist/components/stream-status/stream-status.styles.js +103 -0
- package/dist/components/streaming-text/streaming-text.d.ts +104 -0
- package/dist/components/streaming-text/streaming-text.js +224 -0
- package/dist/components/streaming-text/streaming-text.styles.d.ts +1 -0
- package/dist/components/streaming-text/streaming-text.styles.js +63 -0
- package/dist/components/switch/switch.d.ts +103 -0
- package/dist/components/switch/switch.js +250 -0
- package/dist/components/switch/switch.styles.d.ts +1 -0
- package/dist/components/switch/switch.styles.js +75 -0
- package/dist/components/table/table.d.ts +89 -5
- package/dist/components/table/table.js +243 -26
- package/dist/components/table/table.styles.js +6 -1
- package/dist/components/tabs/tabs.d.ts +74 -0
- package/dist/components/tabs/tabs.js +254 -0
- package/dist/components/tabs/tabs.styles.d.ts +1 -0
- package/dist/components/tabs/tabs.styles.js +74 -0
- package/dist/components/thinking-panel/thinking-panel.d.ts +123 -0
- package/dist/components/thinking-panel/thinking-panel.js +260 -0
- package/dist/components/thinking-panel/thinking-panel.styles.d.ts +1 -0
- package/dist/components/thinking-panel/thinking-panel.styles.js +123 -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 -2
- package/dist/components/toast/toast-item.js +106 -44
- 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 +131 -0
- package/dist/components/tool-approval-dialog/tool-approval-dialog.js +329 -0
- package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.d.ts +1 -0
- package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +160 -0
- package/dist/components/tool-call-chip/tool-call-chip.d.ts +105 -0
- package/dist/components/tool-call-chip/tool-call-chip.js +349 -0
- package/dist/components/tool-call-chip/tool-call-chip.styles.d.ts +1 -0
- package/dist/components/tool-call-chip/tool-call-chip.styles.js +203 -0
- package/dist/components/tool-param-form/tool-param-form.d.ts +206 -0
- package/dist/components/tool-param-form/tool-param-form.js +610 -0
- package/dist/components/tool-param-form/tool-param-form.styles.d.ts +1 -0
- package/dist/components/tool-param-form/tool-param-form.styles.js +75 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +122 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.js +358 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.styles.d.ts +1 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +176 -0
- package/dist/components/tool-result-view/registry.d.ts +73 -0
- package/dist/components/tool-result-view/registry.js +89 -0
- package/dist/components/tool-result-view/tool-result-view.d.ts +58 -0
- package/dist/components/tool-result-view/tool-result-view.js +152 -0
- package/dist/components/tool-result-view/tool-result-view.styles.d.ts +1 -0
- package/dist/components/tool-result-view/tool-result-view.styles.js +13 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +151 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.js +350 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.styles.d.ts +1 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +191 -0
- package/dist/components/tree/tree-node.d.ts +15 -3
- package/dist/components/tree/tree-node.js +20 -7
- package/dist/components/tree/tree.d.ts +25 -10
- package/dist/components/tree/tree.js +39 -31
- package/dist/components/typing-indicator/typing-indicator.d.ts +70 -0
- package/dist/components/typing-indicator/typing-indicator.js +108 -0
- package/dist/components/typing-indicator/typing-indicator.styles.d.ts +1 -0
- package/dist/components/typing-indicator/typing-indicator.styles.js +132 -0
- package/dist/components/virtual-list/virtual-list.d.ts +210 -0
- package/dist/components/virtual-list/virtual-list.js +607 -0
- package/dist/components/virtual-list/virtual-list.styles.d.ts +1 -0
- package/dist/components/virtual-list/virtual-list.styles.js +56 -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 +29 -2
- package/dist/components/word-cloud/word-cloud.d.ts +28 -2
- package/dist/components/word-cloud/word-cloud.js +69 -19
- package/dist/components/word-cloud/word-cloud.styles.js +16 -3
- package/dist/internal/anchored-validity.d.ts +1 -0
- package/dist/internal/anchored-validity.js +86 -0
- package/dist/internal/announcer.d.ts +57 -0
- package/dist/internal/announcer.js +71 -0
- package/dist/internal/form-associated.d.ts +8 -0
- package/dist/internal/form-associated.js +98 -15
- package/dist/internal/group-by-recency.d.ts +50 -0
- package/dist/internal/group-by-recency.js +80 -0
- 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/rtl.d.ts +23 -0
- package/dist/internal/rtl.js +28 -0
- package/dist/internal/safe-url.d.ts +12 -0
- package/dist/internal/safe-url.js +41 -0
- package/dist/internal/scroll-lock.d.ts +10 -5
- package/dist/internal/scroll-lock.js +30 -14
- package/dist/internal/tokens.styles.js +22 -10
- package/dist/lyra.d.ts +133 -31
- package/dist/lyra.js +96 -26
- package/llms-full.txt +4546 -183
- package/llms.txt +21 -5
- package/package.json +41 -6
- package/dist/components/chart/bar-chart.stories.d.ts +0 -5
- package/dist/components/chart/bar-chart.stories.js +0 -20
- package/dist/components/chart/box-plot.stories.d.ts +0 -5
- package/dist/components/chart/box-plot.stories.js +0 -29
- package/dist/components/chart/bubble-chart.stories.d.ts +0 -5
- package/dist/components/chart/bubble-chart.stories.js +0 -26
- package/dist/components/chart/chart.stories.d.ts +0 -32
- package/dist/components/chart/chart.stories.js +0 -141
- package/dist/components/chart/doughnut-chart.stories.d.ts +0 -5
- package/dist/components/chart/doughnut-chart.stories.js +0 -26
- package/dist/components/chart/histogram.stories.d.ts +0 -5
- package/dist/components/chart/histogram.stories.js +0 -17
- package/dist/components/chart/line-chart.stories.d.ts +0 -22
- package/dist/components/chart/line-chart.stories.js +0 -99
- package/dist/components/chart/lite-chart.stories.d.ts +0 -14
- package/dist/components/chart/lite-chart.stories.js +0 -114
- package/dist/components/chart/pie-chart.stories.d.ts +0 -5
- package/dist/components/chart/pie-chart.stories.js +0 -26
- package/dist/components/chart/polar-area-chart.stories.d.ts +0 -5
- package/dist/components/chart/polar-area-chart.stories.js +0 -20
- package/dist/components/chart/radar-chart.stories.d.ts +0 -5
- package/dist/components/chart/radar-chart.stories.js +0 -20
- package/dist/components/chart/scatter-chart.stories.d.ts +0 -5
- package/dist/components/chart/scatter-chart.stories.js +0 -31
- package/dist/components/combobox/combobox.stories.d.ts +0 -24
- package/dist/components/combobox/combobox.stories.js +0 -102
- package/dist/components/date-picker/date-input.stories.d.ts +0 -10
- package/dist/components/date-picker/date-input.stories.js +0 -48
- package/dist/components/date-picker/date-picker.stories.d.ts +0 -10
- package/dist/components/date-picker/date-picker.stories.js +0 -25
- package/dist/components/empty/empty.stories.d.ts +0 -7
- package/dist/components/empty/empty.stories.js +0 -34
- package/dist/components/export-button/export-button.stories.d.ts +0 -7
- package/dist/components/export-button/export-button.stories.js +0 -37
- package/dist/components/file-input/file-input.stories.d.ts +0 -7
- package/dist/components/file-input/file-input.stories.js +0 -19
- package/dist/components/flag/flag.stories.d.ts +0 -6
- package/dist/components/flag/flag.stories.js +0 -31
- package/dist/components/gauge/gauge.stories.d.ts +0 -8
- package/dist/components/gauge/gauge.stories.js +0 -19
- package/dist/components/graph/graph.stories.d.ts +0 -8
- package/dist/components/graph/graph.stories.js +0 -68
- package/dist/components/heatmap/heatmap.stories.d.ts +0 -27
- package/dist/components/heatmap/heatmap.stories.js +0 -179
- package/dist/components/map/map.stories.d.ts +0 -15
- package/dist/components/map/map.stories.js +0 -135
- package/dist/components/playback/playback.stories.d.ts +0 -7
- package/dist/components/playback/playback.stories.js +0 -16
- package/dist/components/select/select.stories.d.ts +0 -21
- package/dist/components/select/select.stories.js +0 -91
- package/dist/components/skeleton/skeleton.stories.d.ts +0 -5
- package/dist/components/skeleton/skeleton.stories.js +0 -16
- package/dist/components/sparkline/sparkline.stories.d.ts +0 -11
- package/dist/components/sparkline/sparkline.stories.js +0 -39
- package/dist/components/split/split.stories.d.ts +0 -7
- package/dist/components/split/split.stories.js +0 -36
- package/dist/components/stat/stat.stories.d.ts +0 -9
- package/dist/components/stat/stat.stories.js +0 -81
- package/dist/components/table/table.stories.d.ts +0 -12
- package/dist/components/table/table.stories.js +0 -67
- package/dist/components/time-range/time-range.stories.d.ts +0 -8
- package/dist/components/time-range/time-range.stories.js +0 -26
- package/dist/components/toast/toast.stories.d.ts +0 -8
- package/dist/components/toast/toast.stories.js +0 -72
- package/dist/components/tree/tree.stories.d.ts +0 -9
- package/dist/components/tree/tree.stories.js +0 -52
- package/dist/components/widget/widget.stories.d.ts +0 -9
- package/dist/components/widget/widget.stories.js +0 -74
- package/dist/components/word-cloud/word-cloud.stories.d.ts +0 -10
- package/dist/components/word-cloud/word-cloud.stories.js +0 -55
|
@@ -4,9 +4,16 @@ export const styles = css `
|
|
|
4
4
|
display: block;
|
|
5
5
|
inline-size: 100%;
|
|
6
6
|
block-size: 100%;
|
|
7
|
+
/* Component-specific -- not a shared design token, so a consumer can
|
|
8
|
+
retheme it without a raw literal leaking into the public API (same
|
|
9
|
+
rationale as lyra-app-rail's --lyra-app-rail-overlay-color). */
|
|
10
|
+
--lyra-split-overlay-color: rgb(0 0 0 / 0.5);
|
|
7
11
|
}
|
|
8
12
|
[part='base'] {
|
|
9
13
|
display: flex;
|
|
14
|
+
/* Anchor for the 'floating' collapse state's absolutely-positioned
|
|
15
|
+
overlay panel (set inline by split.ts's updated()). */
|
|
16
|
+
position: relative;
|
|
10
17
|
inline-size: 100%;
|
|
11
18
|
block-size: 100%;
|
|
12
19
|
}
|
|
@@ -48,4 +55,44 @@ export const styles = css `
|
|
|
48
55
|
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
49
56
|
outline-offset: var(--lyra-focus-ring-offset);
|
|
50
57
|
}
|
|
58
|
+
/* The divider adjacent to a rail/floating-collapsed pane (see split.ts's
|
|
59
|
+
isDividerDisabled()) — geometry (position/inset/inline-size) for the
|
|
60
|
+
collapsing panel itself is set inline by updated(), same as the
|
|
61
|
+
pre-existing flex/order styling; this only covers the divider's own
|
|
62
|
+
drag/hover affordance and the floating panel's elevation, which read
|
|
63
|
+
more naturally as stylesheet rules than one-off inline styles. */
|
|
64
|
+
[part='divider'][aria-disabled='true'] {
|
|
65
|
+
cursor: default;
|
|
66
|
+
pointer-events: none;
|
|
67
|
+
}
|
|
68
|
+
/* The 'floating' collapse state's overlay "card" look -- geometry
|
|
69
|
+
(position/inset-*/inline-size) is set inline by split.ts's updated(),
|
|
70
|
+
matching how the ordinary flex/order styling is applied; only the
|
|
71
|
+
visual/stacking treatment lives here. z-index is above [part="backdrop"]
|
|
72
|
+
(below), so the drawer renders on top of its own scrim. */
|
|
73
|
+
::slotted([data-collapse-state='floating']) {
|
|
74
|
+
z-index: 1;
|
|
75
|
+
background: var(--lyra-color-surface);
|
|
76
|
+
border-radius: var(--lyra-radius);
|
|
77
|
+
box-shadow: var(--lyra-shadow);
|
|
78
|
+
}
|
|
79
|
+
/* The 'floating' drawer's scrim -- only rendered while collapseState is
|
|
80
|
+
'floating' and open (see split.ts's render()). Scoped to [part="base"]
|
|
81
|
+
(position: absolute against its position: relative ancestor) rather than
|
|
82
|
+
a viewport-fixed overlay like lyra-app-rail's mobile backdrop: the
|
|
83
|
+
floating panel itself is only ever positioned relative to this
|
|
84
|
+
component's own box, never the full page. */
|
|
85
|
+
[part='backdrop'] {
|
|
86
|
+
position: absolute;
|
|
87
|
+
inset: 0;
|
|
88
|
+
z-index: 0;
|
|
89
|
+
background: var(--lyra-split-overlay-color);
|
|
90
|
+
}
|
|
91
|
+
/* Rail-clamped content can easily overflow the fixed rail-width — clip it
|
|
92
|
+
rather than letting it blow out the layout; the panel's own content is
|
|
93
|
+
expected to adapt to the narrower width itself (e.g. via a container
|
|
94
|
+
query), this is just a safety net. */
|
|
95
|
+
::slotted([data-collapse-state='rail']) {
|
|
96
|
+
overflow: hidden;
|
|
97
|
+
}
|
|
51
98
|
`;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { type TemplateResult } from 'lit';
|
|
1
|
+
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
2
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
3
|
export type StatVariant = 'neutral' | 'success' | 'warning' | 'danger';
|
|
4
4
|
export type StatGoodDirection = 'up' | 'down';
|
|
5
5
|
export interface StatRow {
|
|
6
6
|
label: string;
|
|
7
7
|
value: string;
|
|
8
|
+
/** Exact value shown as a hover/focus tooltip on this row's `row-value` (mirrors the headline
|
|
9
|
+
* `exactValue`/`exact-value` behavior). Also makes this row's `[part='row-value']`
|
|
10
|
+
* keyboard-focusable so the tooltip is reachable without a pointer. */
|
|
11
|
+
exactValue?: string;
|
|
8
12
|
}
|
|
9
13
|
/**
|
|
10
14
|
* `<lyra-stat>` — a KPI/stat card. First-party invention consolidating the
|
|
@@ -20,7 +24,9 @@ export interface StatRow {
|
|
|
20
24
|
* @csspart icon - Container for the leading icon slot.
|
|
21
25
|
* @csspart label - The label text.
|
|
22
26
|
* @csspart value-row - Wrapper around the value and unit.
|
|
23
|
-
* @csspart value - The value text.
|
|
27
|
+
* @csspart value - The value text. Accessibly labelled by the `label` part (via
|
|
28
|
+
* `aria-labelledby`) whenever `label` is set, so tabbing directly to this
|
|
29
|
+
* (focusable when `exactValue` is set) control still announces which metric it is.
|
|
24
30
|
* @csspart unit - The unit text.
|
|
25
31
|
* @csspart trend - The trend pill.
|
|
26
32
|
* @csspart sub - Container for the `sub` attribute/slot.
|
|
@@ -29,7 +35,9 @@ export interface StatRow {
|
|
|
29
35
|
* @csspart rows - Container for the `rows` breakdown list.
|
|
30
36
|
* @csspart row - A single breakdown row (one per `rows` entry).
|
|
31
37
|
* @csspart row-label - The label text of a breakdown row.
|
|
32
|
-
* @csspart row-value - The value text of a breakdown row.
|
|
38
|
+
* @csspart row-value - The value text of a breakdown row. Shows the row's `exactValue` (if any) as
|
|
39
|
+
* a hover/focus tooltip, same as the headline `value`, and is accessibly labelled by its
|
|
40
|
+
* `row-label` (via `aria-labelledby`) the same way the headline `value` is.
|
|
33
41
|
*/
|
|
34
42
|
export declare class LyraStat extends LyraElement {
|
|
35
43
|
static styles: import("lit").CSSResultGroup[];
|
|
@@ -64,7 +72,10 @@ export declare class LyraStat extends LyraElement {
|
|
|
64
72
|
private hasCaptionSlot;
|
|
65
73
|
private hasSparkSlot;
|
|
66
74
|
private hasSubSlot;
|
|
67
|
-
|
|
75
|
+
private readonly labelId;
|
|
76
|
+
private readonly valueId;
|
|
77
|
+
private rowLabelIds;
|
|
78
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
68
79
|
private onIconSlotChange;
|
|
69
80
|
private onCaptionSlotChange;
|
|
70
81
|
private onSparkSlotChange;
|
|
@@ -9,7 +9,7 @@ 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 { srOnly } from '../../internal/a11y.js';
|
|
12
|
+
import { nextId, srOnly } from '../../internal/a11y.js';
|
|
13
13
|
import { styles } from './stat.styles.js';
|
|
14
14
|
/**
|
|
15
15
|
* `<lyra-stat>` — a KPI/stat card. First-party invention consolidating the
|
|
@@ -25,7 +25,9 @@ import { styles } from './stat.styles.js';
|
|
|
25
25
|
* @csspart icon - Container for the leading icon slot.
|
|
26
26
|
* @csspart label - The label text.
|
|
27
27
|
* @csspart value-row - Wrapper around the value and unit.
|
|
28
|
-
* @csspart value - The value text.
|
|
28
|
+
* @csspart value - The value text. Accessibly labelled by the `label` part (via
|
|
29
|
+
* `aria-labelledby`) whenever `label` is set, so tabbing directly to this
|
|
30
|
+
* (focusable when `exactValue` is set) control still announces which metric it is.
|
|
29
31
|
* @csspart unit - The unit text.
|
|
30
32
|
* @csspart trend - The trend pill.
|
|
31
33
|
* @csspart sub - Container for the `sub` attribute/slot.
|
|
@@ -34,7 +36,9 @@ import { styles } from './stat.styles.js';
|
|
|
34
36
|
* @csspart rows - Container for the `rows` breakdown list.
|
|
35
37
|
* @csspart row - A single breakdown row (one per `rows` entry).
|
|
36
38
|
* @csspart row-label - The label text of a breakdown row.
|
|
37
|
-
* @csspart row-value - The value text of a breakdown row.
|
|
39
|
+
* @csspart row-value - The value text of a breakdown row. Shows the row's `exactValue` (if any) as
|
|
40
|
+
* a hover/focus tooltip, same as the headline `value`, and is accessibly labelled by its
|
|
41
|
+
* `row-label` (via `aria-labelledby`) the same way the headline `value` is.
|
|
38
42
|
*/
|
|
39
43
|
export class LyraStat extends LyraElement {
|
|
40
44
|
constructor() {
|
|
@@ -73,6 +77,16 @@ export class LyraStat extends LyraElement {
|
|
|
73
77
|
this.hasCaptionSlot = false;
|
|
74
78
|
this.hasSparkSlot = false;
|
|
75
79
|
this.hasSubSlot = false;
|
|
80
|
+
// Stable id pairing `[part='label']` with `[part='value']` via
|
|
81
|
+
// aria-labelledby, so a keyboard user tabbing straight to the (focusable,
|
|
82
|
+
// tooltip-bearing) value still gets an accessible name like "Revenue
|
|
83
|
+
// $1.2K" instead of the bare value.
|
|
84
|
+
this.labelId = nextId('stat-label');
|
|
85
|
+
this.valueId = `${this.labelId}-value`;
|
|
86
|
+
// One id per `rows` entry, regenerated only when the `rows` array itself is
|
|
87
|
+
// reassigned (not on every render) so `aria-labelledby` references stay
|
|
88
|
+
// stable across unrelated re-renders.
|
|
89
|
+
this.rowLabelIds = [];
|
|
76
90
|
this.onIconSlotChange = (e) => {
|
|
77
91
|
this.hasIcon = e.target.assignedElements({ flatten: true }).length > 0;
|
|
78
92
|
};
|
|
@@ -87,16 +101,24 @@ export class LyraStat extends LyraElement {
|
|
|
87
101
|
};
|
|
88
102
|
}
|
|
89
103
|
static { this.styles = [LyraElement.styles, styles, srOnly]; }
|
|
90
|
-
willUpdate() {
|
|
104
|
+
willUpdate(changed) {
|
|
91
105
|
if (!this.hasUpdated) {
|
|
92
106
|
this.hasIcon = Array.from(this.children).some((el) => !el.hasAttribute('slot'));
|
|
93
107
|
this.hasCaptionSlot = Array.from(this.children).some((el) => el.getAttribute('slot') === 'caption');
|
|
94
108
|
this.hasSparkSlot = Array.from(this.children).some((el) => el.getAttribute('slot') === 'spark');
|
|
95
109
|
this.hasSubSlot = Array.from(this.children).some((el) => el.getAttribute('slot') === 'sub');
|
|
96
110
|
}
|
|
111
|
+
if (changed.has('rows')) {
|
|
112
|
+
this.rowLabelIds = this.rows.map(() => nextId('stat-row-label'));
|
|
113
|
+
}
|
|
97
114
|
}
|
|
98
115
|
render() {
|
|
99
|
-
|
|
116
|
+
// Lit's built-in Number converter maps a removed/absent attribute to
|
|
117
|
+
// `null`, not NaN, even though the property is typed `number` — so
|
|
118
|
+
// `isNaN(this.trend)` alone is false for a cleared attribute and the pill
|
|
119
|
+
// would reappear showing a fabricated "unchanged, 0%". Treat null/undefined
|
|
120
|
+
// the same as NaN here instead of trusting the static type.
|
|
121
|
+
const hasTrend = this.trend != null && !isNaN(this.trend);
|
|
100
122
|
const rawDirection = this.trend > 0 ? 'up' : this.trend < 0 ? 'down' : 'flat';
|
|
101
123
|
const isGood = rawDirection === 'flat' ? null : rawDirection === this.goodDirection;
|
|
102
124
|
// The trend pill previously rendered literal ▲/▼ glyphs — font-dependent
|
|
@@ -117,9 +139,14 @@ export class LyraStat extends LyraElement {
|
|
|
117
139
|
<span part="icon" ?hidden=${!this.hasIcon}
|
|
118
140
|
><slot @slotchange=${this.onIconSlotChange}></slot
|
|
119
141
|
></span>
|
|
120
|
-
<span part="label">${this.label}</span>
|
|
142
|
+
<span part="label" id=${this.labelId}>${this.label}</span>
|
|
121
143
|
<div part="value-row">
|
|
122
|
-
<span
|
|
144
|
+
<span
|
|
145
|
+
part="value"
|
|
146
|
+
id=${this.valueId}
|
|
147
|
+
title=${this.exactValue || nothing}
|
|
148
|
+
tabindex=${this.exactValue ? '0' : nothing}
|
|
149
|
+
aria-labelledby=${this.label ? `${this.labelId} ${this.valueId}` : nothing}
|
|
123
150
|
>${this.value}</span
|
|
124
151
|
>
|
|
125
152
|
<span part="unit">${this.unit}</span>
|
|
@@ -135,7 +162,7 @@ export class LyraStat extends LyraElement {
|
|
|
135
162
|
</span>`
|
|
136
163
|
: nothing}
|
|
137
164
|
<div part="sub" ?hidden=${!hasSub}>
|
|
138
|
-
|
|
165
|
+
<slot name="sub" @slotchange=${this.onSubSlotChange}>${this.sub}</slot>
|
|
139
166
|
</div>
|
|
140
167
|
<div part="spark" ?hidden=${!this.hasSparkSlot}>
|
|
141
168
|
<slot name="spark" @slotchange=${this.onSparkSlotChange}></slot>
|
|
@@ -144,12 +171,23 @@ export class LyraStat extends LyraElement {
|
|
|
144
171
|
<slot name="caption" @slotchange=${this.onCaptionSlotChange}>${this.caption}</slot>
|
|
145
172
|
</div>
|
|
146
173
|
<div part="rows" ?hidden=${this.rows.length === 0}>
|
|
147
|
-
${this.rows.map((row) =>
|
|
174
|
+
${this.rows.map((row, i) => {
|
|
175
|
+
const rowLabelId = this.rowLabelIds[i];
|
|
176
|
+
const rowValueId = `${rowLabelId}-value`;
|
|
177
|
+
return html `
|
|
148
178
|
<div part="row">
|
|
149
|
-
<span part="row-label">${row.label}</span>
|
|
150
|
-
<span
|
|
179
|
+
<span part="row-label" id=${rowLabelId}>${row.label}</span>
|
|
180
|
+
<span
|
|
181
|
+
part="row-value"
|
|
182
|
+
id=${rowValueId}
|
|
183
|
+
title=${row.exactValue || nothing}
|
|
184
|
+
tabindex=${row.exactValue ? '0' : nothing}
|
|
185
|
+
aria-labelledby=${row.label ? `${rowLabelId} ${rowValueId}` : nothing}
|
|
186
|
+
>${row.value}</span
|
|
187
|
+
>
|
|
151
188
|
</div>
|
|
152
|
-
|
|
189
|
+
`;
|
|
190
|
+
})}
|
|
153
191
|
</div>
|
|
154
192
|
</div>
|
|
155
193
|
`;
|
|
@@ -206,4 +244,7 @@ __decorate([
|
|
|
206
244
|
__decorate([
|
|
207
245
|
state()
|
|
208
246
|
], LyraStat.prototype, "hasSubSlot", void 0);
|
|
247
|
+
__decorate([
|
|
248
|
+
state()
|
|
249
|
+
], LyraStat.prototype, "rowLabelIds", void 0);
|
|
209
250
|
defineElement('stat', LyraStat);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
import '../live-region/live-region.js';
|
|
4
|
+
export type StreamStatusPhase = 'idle' | 'connecting' | 'streaming' | 'stalled';
|
|
5
|
+
/**
|
|
6
|
+
* `<lyra-stream-status>` — a compact status indicator for a single streaming
|
|
7
|
+
* connection (SSE, WebSocket, long-poll, …), with built-in heartbeat-aware
|
|
8
|
+
* stall detection.
|
|
9
|
+
*
|
|
10
|
+
* The host drives `phase` directly for `idle`/`connecting`/`streaming`, and
|
|
11
|
+
* calls `recordActivity()` on every *semantic* frame received while
|
|
12
|
+
* streaming — a real content chunk, never a transport-level keep-alive ping.
|
|
13
|
+
* This component has no payload-inspection logic of its own: "ignore
|
|
14
|
+
* heartbeats" is entirely a call-site discipline — the host simply never
|
|
15
|
+
* calls `recordActivity()` for a ping, so pings never reset the stall timer
|
|
16
|
+
* and a connection that's only sending keep-alives (no real content) for
|
|
17
|
+
* longer than `stall-threshold-ms` correctly reads as stalled.
|
|
18
|
+
*
|
|
19
|
+
* Internally, an inactivity timer runs only while `phase === 'streaming'`.
|
|
20
|
+
* It's (re)armed whenever the phase transitions to `'streaming'` (directly,
|
|
21
|
+
* or via `recordActivity()` recovering from `'stalled'`), on every
|
|
22
|
+
* subsequent `recordActivity()` call while already streaming, whenever
|
|
23
|
+
* `stall-threshold-ms` itself changes while already streaming (the new
|
|
24
|
+
* value takes effect immediately, the same way `<lyra-toast-item>`'s
|
|
25
|
+
* `duration` re-applies mid-flight, rather than waiting for the next
|
|
26
|
+
* `recordActivity()`/phase change), and whenever this element (re)connects
|
|
27
|
+
* to the DOM while `phase` is still `'streaming'` (a disconnect always
|
|
28
|
+
* disarms it, so moving the element elsewhere in the page — disconnect then
|
|
29
|
+
* reconnect with `phase` unchanged — must resume detection rather than
|
|
30
|
+
* silently disabling it for the rest of the streaming session). It's
|
|
31
|
+
* disarmed the instant `phase` becomes anything else, including a
|
|
32
|
+
* host-driven reassignment away from `'streaming'` — so a stale timer can
|
|
33
|
+
* never fire a stall transition after the host has already moved on. If it
|
|
34
|
+
* ever fires, `phase` becomes `'stalled'` and `lyra-stall` is dispatched.
|
|
35
|
+
*
|
|
36
|
+
* `phase` remains a fully public, directly settable property at all times —
|
|
37
|
+
* a host can assign `'stalled'` (or any other phase) itself as a manual
|
|
38
|
+
* override, and this component never fights that assignment. `lyra-stall`/
|
|
39
|
+
* `lyra-recover` fire on *any* transition into/out of `'stalled'`
|
|
40
|
+
* respectively, whether timer-driven or host-driven, and never for a
|
|
41
|
+
* reassignment to the same value (Lit's default `hasChanged` already skips a
|
|
42
|
+
* no-op set, same as every other reflected `@property` in this library).
|
|
43
|
+
* Like `<lyra-chat-message>`'s `status`, whatever phase this element happens
|
|
44
|
+
* to *mount* with is never itself treated as an eventful transition — only a
|
|
45
|
+
* later change fires an event or an announcement.
|
|
46
|
+
*
|
|
47
|
+
* Accessibility: phase transitions into/out of `'stalled'` are announced
|
|
48
|
+
* through an internal `<lyra-live-region>` (see that component for the
|
|
49
|
+
* throttled/coalesced-announcement machinery this composes) rather than a
|
|
50
|
+
* hand-rolled `aria-live` region. `recordActivity()` itself never announces
|
|
51
|
+
* anything, no matter how often the host calls it — only the *transition*
|
|
52
|
+
* announces, exactly once per transition, which is the entire point of
|
|
53
|
+
* routing through the throttled announcer instead of writing to a live
|
|
54
|
+
* region on every call. Entering `'stalled'` announces with `mode="assertive"`
|
|
55
|
+
* (a stall can need the user's attention, e.g. before they give up and
|
|
56
|
+
* navigate away); leaving `'stalled'` always announces with `mode="polite"`
|
|
57
|
+
* (good news doesn't need to interrupt), but the *wording* depends on where
|
|
58
|
+
* it lands: `"Connection restored."` only when the destination is
|
|
59
|
+
* `'streaming'` (a genuine recovery), or a neutral `"No longer stalled."`
|
|
60
|
+
* when the destination is `'idle'`/`'connecting'` instead — that's the host
|
|
61
|
+
* giving up on the stream, not the stream recovering, and a screen-reader
|
|
62
|
+
* user must never be told the opposite of what a sighted user sees on
|
|
63
|
+
* screen. The decorative indicator dot is `aria-hidden` — it's a
|
|
64
|
+
* color/motion cue only, never the sole carrier of state.
|
|
65
|
+
*
|
|
66
|
+
* Visual: `'stalled'` is styled as a warning, not a danger — a stall is
|
|
67
|
+
* usually recoverable (the stream may resume on its own, or the host's own
|
|
68
|
+
* retry logic may kick in), so treating it as an actionable warning rather
|
|
69
|
+
* than a hard failure keeps the tone proportionate. A host that wants to
|
|
70
|
+
* escalate to danger styling after N stalls can scope its own CSS off
|
|
71
|
+
* `[phase="stalled"]`, or simply stop rendering this component and show its
|
|
72
|
+
* own danger-styled error state instead.
|
|
73
|
+
*
|
|
74
|
+
* @customElement lyra-stream-status
|
|
75
|
+
* @slot - Custom copy shown only while `phase="stalled"` (e.g. "Taking longer than usual…"). A sensible built-in default is used when nothing is slotted.
|
|
76
|
+
* @slot actions - A stop/retry button row. Always present in the template regardless of `phase` — visibility is driven purely by whether anything is slotted, not by `phase`; what to put here, and when, is entirely the host's call.
|
|
77
|
+
* @event lyra-stall - Fired whenever `phase` transitions into `'stalled'` from anything else (timer-driven, or a direct host assignment).
|
|
78
|
+
* @event lyra-recover - Fired whenever `phase` transitions out of `'stalled'` to anything else (via `recordActivity()`, or a direct host assignment) — fired unconditionally regardless of destination phase, even though the accompanying announcement's wording varies (see the class doc's "Accessibility" section).
|
|
79
|
+
* @csspart base - The root layout container.
|
|
80
|
+
* @csspart indicator - The decorative (`aria-hidden`) status dot.
|
|
81
|
+
* @csspart message - Wrapper around the default slot; only rendered while `phase="stalled"`.
|
|
82
|
+
* @csspart actions - Wrapper around the `actions` slot.
|
|
83
|
+
*/
|
|
84
|
+
export declare class LyraStreamStatus extends LyraElement {
|
|
85
|
+
static styles: import("lit").CSSResultGroup[];
|
|
86
|
+
/** Current connection phase. Settable directly by the host at any time —
|
|
87
|
+
* see the class doc for how that interacts with the internal stall timer. */
|
|
88
|
+
phase: StreamStatusPhase;
|
|
89
|
+
/** How long `phase` may stay `'streaming'` with no `recordActivity()` call
|
|
90
|
+
* before this component declares it stalled. */
|
|
91
|
+
stallThresholdMs: number;
|
|
92
|
+
private stallTimer?;
|
|
93
|
+
private hasActionsSlot;
|
|
94
|
+
private hasMessageContent;
|
|
95
|
+
private liveRegion?;
|
|
96
|
+
protected willUpdate(): void;
|
|
97
|
+
protected updated(changed: PropertyValues): void;
|
|
98
|
+
connectedCallback(): void;
|
|
99
|
+
disconnectedCallback(): void;
|
|
100
|
+
/**
|
|
101
|
+
* Call on every semantic (non-heartbeat) frame received while streaming.
|
|
102
|
+
* - While `phase === 'streaming'`: (re)arms the stall timer, pushing the
|
|
103
|
+
* stall deadline `stall-threshold-ms` further out.
|
|
104
|
+
* - While `phase === 'stalled'`: recovers — `phase` becomes `'streaming'`
|
|
105
|
+
* again, `lyra-recover` fires, and the stall timer is armed fresh (same
|
|
106
|
+
* as the bullet above), all via the same `updated()` transition handling
|
|
107
|
+
* a direct host assignment would also go through.
|
|
108
|
+
* - While `phase` is `'idle'` or `'connecting'`: a no-op. A host may call
|
|
109
|
+
* this defensively before formally flipping to `'streaming'`; it must
|
|
110
|
+
* never throw or start a timer early.
|
|
111
|
+
*/
|
|
112
|
+
recordActivity(): void;
|
|
113
|
+
private onPhaseChanged;
|
|
114
|
+
private armStallTimer;
|
|
115
|
+
private disarmStallTimer;
|
|
116
|
+
private announceTransition;
|
|
117
|
+
private hasSlotted;
|
|
118
|
+
private onActionsSlotChange;
|
|
119
|
+
private onMessageSlotChange;
|
|
120
|
+
render(): TemplateResult;
|
|
121
|
+
}
|
|
122
|
+
declare global {
|
|
123
|
+
interface HTMLElementTagNameMap {
|
|
124
|
+
'lyra-stream-status': LyraStreamStatus;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, nothing } from 'lit';
|
|
8
|
+
import { property, state, query } from 'lit/decorators.js';
|
|
9
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
+
import '../live-region/live-region.js';
|
|
12
|
+
import { styles } from './stream-status.styles.js';
|
|
13
|
+
const DEFAULT_STALL_MESSAGE = 'Taking longer than usual…';
|
|
14
|
+
const STALL_ANNOUNCEMENT = 'Connection stalled.';
|
|
15
|
+
const RECOVER_ANNOUNCEMENT = 'Connection restored.';
|
|
16
|
+
// Used instead of RECOVER_ANNOUNCEMENT when a stall is left behind by moving
|
|
17
|
+
// to 'idle'/'connecting' rather than back to 'streaming' -- see
|
|
18
|
+
// announceTransition()'s caller in onPhaseChanged() for why "restored" would
|
|
19
|
+
// be actively misleading in that case.
|
|
20
|
+
const STALL_CLEARED_ANNOUNCEMENT = 'No longer stalled.';
|
|
21
|
+
// The default slot's stalled-message content is often plain text with no
|
|
22
|
+
// wrapping element at all (see the CustomStalledMessage story), so an
|
|
23
|
+
// Element-only check never counts it, and ordinary indented-markup
|
|
24
|
+
// whitespace (a newline + indentation before a slotted `actions` button, as
|
|
25
|
+
// in the DefaultStalledMessage story) must not count either -- native <slot>
|
|
26
|
+
// fallback content is suppressed by *any* assigned node, whitespace or not,
|
|
27
|
+
// which previously left the message area blank in exactly that common case.
|
|
28
|
+
// Mirrors lyra-citation-badge's identical isRealPreviewNode: a node counts as
|
|
29
|
+
// real message content if it's an element not assigned to some other named
|
|
30
|
+
// slot (e.g. `actions`), or non-whitespace text.
|
|
31
|
+
function isRealMessageNode(n) {
|
|
32
|
+
return n.nodeType === Node.ELEMENT_NODE
|
|
33
|
+
? !n.hasAttribute('slot')
|
|
34
|
+
: (n.textContent ?? '').trim().length > 0;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* `<lyra-stream-status>` — a compact status indicator for a single streaming
|
|
38
|
+
* connection (SSE, WebSocket, long-poll, …), with built-in heartbeat-aware
|
|
39
|
+
* stall detection.
|
|
40
|
+
*
|
|
41
|
+
* The host drives `phase` directly for `idle`/`connecting`/`streaming`, and
|
|
42
|
+
* calls `recordActivity()` on every *semantic* frame received while
|
|
43
|
+
* streaming — a real content chunk, never a transport-level keep-alive ping.
|
|
44
|
+
* This component has no payload-inspection logic of its own: "ignore
|
|
45
|
+
* heartbeats" is entirely a call-site discipline — the host simply never
|
|
46
|
+
* calls `recordActivity()` for a ping, so pings never reset the stall timer
|
|
47
|
+
* and a connection that's only sending keep-alives (no real content) for
|
|
48
|
+
* longer than `stall-threshold-ms` correctly reads as stalled.
|
|
49
|
+
*
|
|
50
|
+
* Internally, an inactivity timer runs only while `phase === 'streaming'`.
|
|
51
|
+
* It's (re)armed whenever the phase transitions to `'streaming'` (directly,
|
|
52
|
+
* or via `recordActivity()` recovering from `'stalled'`), on every
|
|
53
|
+
* subsequent `recordActivity()` call while already streaming, whenever
|
|
54
|
+
* `stall-threshold-ms` itself changes while already streaming (the new
|
|
55
|
+
* value takes effect immediately, the same way `<lyra-toast-item>`'s
|
|
56
|
+
* `duration` re-applies mid-flight, rather than waiting for the next
|
|
57
|
+
* `recordActivity()`/phase change), and whenever this element (re)connects
|
|
58
|
+
* to the DOM while `phase` is still `'streaming'` (a disconnect always
|
|
59
|
+
* disarms it, so moving the element elsewhere in the page — disconnect then
|
|
60
|
+
* reconnect with `phase` unchanged — must resume detection rather than
|
|
61
|
+
* silently disabling it for the rest of the streaming session). It's
|
|
62
|
+
* disarmed the instant `phase` becomes anything else, including a
|
|
63
|
+
* host-driven reassignment away from `'streaming'` — so a stale timer can
|
|
64
|
+
* never fire a stall transition after the host has already moved on. If it
|
|
65
|
+
* ever fires, `phase` becomes `'stalled'` and `lyra-stall` is dispatched.
|
|
66
|
+
*
|
|
67
|
+
* `phase` remains a fully public, directly settable property at all times —
|
|
68
|
+
* a host can assign `'stalled'` (or any other phase) itself as a manual
|
|
69
|
+
* override, and this component never fights that assignment. `lyra-stall`/
|
|
70
|
+
* `lyra-recover` fire on *any* transition into/out of `'stalled'`
|
|
71
|
+
* respectively, whether timer-driven or host-driven, and never for a
|
|
72
|
+
* reassignment to the same value (Lit's default `hasChanged` already skips a
|
|
73
|
+
* no-op set, same as every other reflected `@property` in this library).
|
|
74
|
+
* Like `<lyra-chat-message>`'s `status`, whatever phase this element happens
|
|
75
|
+
* to *mount* with is never itself treated as an eventful transition — only a
|
|
76
|
+
* later change fires an event or an announcement.
|
|
77
|
+
*
|
|
78
|
+
* Accessibility: phase transitions into/out of `'stalled'` are announced
|
|
79
|
+
* through an internal `<lyra-live-region>` (see that component for the
|
|
80
|
+
* throttled/coalesced-announcement machinery this composes) rather than a
|
|
81
|
+
* hand-rolled `aria-live` region. `recordActivity()` itself never announces
|
|
82
|
+
* anything, no matter how often the host calls it — only the *transition*
|
|
83
|
+
* announces, exactly once per transition, which is the entire point of
|
|
84
|
+
* routing through the throttled announcer instead of writing to a live
|
|
85
|
+
* region on every call. Entering `'stalled'` announces with `mode="assertive"`
|
|
86
|
+
* (a stall can need the user's attention, e.g. before they give up and
|
|
87
|
+
* navigate away); leaving `'stalled'` always announces with `mode="polite"`
|
|
88
|
+
* (good news doesn't need to interrupt), but the *wording* depends on where
|
|
89
|
+
* it lands: `"Connection restored."` only when the destination is
|
|
90
|
+
* `'streaming'` (a genuine recovery), or a neutral `"No longer stalled."`
|
|
91
|
+
* when the destination is `'idle'`/`'connecting'` instead — that's the host
|
|
92
|
+
* giving up on the stream, not the stream recovering, and a screen-reader
|
|
93
|
+
* user must never be told the opposite of what a sighted user sees on
|
|
94
|
+
* screen. The decorative indicator dot is `aria-hidden` — it's a
|
|
95
|
+
* color/motion cue only, never the sole carrier of state.
|
|
96
|
+
*
|
|
97
|
+
* Visual: `'stalled'` is styled as a warning, not a danger — a stall is
|
|
98
|
+
* usually recoverable (the stream may resume on its own, or the host's own
|
|
99
|
+
* retry logic may kick in), so treating it as an actionable warning rather
|
|
100
|
+
* than a hard failure keeps the tone proportionate. A host that wants to
|
|
101
|
+
* escalate to danger styling after N stalls can scope its own CSS off
|
|
102
|
+
* `[phase="stalled"]`, or simply stop rendering this component and show its
|
|
103
|
+
* own danger-styled error state instead.
|
|
104
|
+
*
|
|
105
|
+
* @customElement lyra-stream-status
|
|
106
|
+
* @slot - Custom copy shown only while `phase="stalled"` (e.g. "Taking longer than usual…"). A sensible built-in default is used when nothing is slotted.
|
|
107
|
+
* @slot actions - A stop/retry button row. Always present in the template regardless of `phase` — visibility is driven purely by whether anything is slotted, not by `phase`; what to put here, and when, is entirely the host's call.
|
|
108
|
+
* @event lyra-stall - Fired whenever `phase` transitions into `'stalled'` from anything else (timer-driven, or a direct host assignment).
|
|
109
|
+
* @event lyra-recover - Fired whenever `phase` transitions out of `'stalled'` to anything else (via `recordActivity()`, or a direct host assignment) — fired unconditionally regardless of destination phase, even though the accompanying announcement's wording varies (see the class doc's "Accessibility" section).
|
|
110
|
+
* @csspart base - The root layout container.
|
|
111
|
+
* @csspart indicator - The decorative (`aria-hidden`) status dot.
|
|
112
|
+
* @csspart message - Wrapper around the default slot; only rendered while `phase="stalled"`.
|
|
113
|
+
* @csspart actions - Wrapper around the `actions` slot.
|
|
114
|
+
*/
|
|
115
|
+
export class LyraStreamStatus extends LyraElement {
|
|
116
|
+
constructor() {
|
|
117
|
+
super(...arguments);
|
|
118
|
+
/** Current connection phase. Settable directly by the host at any time —
|
|
119
|
+
* see the class doc for how that interacts with the internal stall timer. */
|
|
120
|
+
this.phase = 'idle';
|
|
121
|
+
/** How long `phase` may stay `'streaming'` with no `recordActivity()` call
|
|
122
|
+
* before this component declares it stalled. */
|
|
123
|
+
this.stallThresholdMs = 10000;
|
|
124
|
+
this.hasActionsSlot = false;
|
|
125
|
+
// Seeded from light-DOM childNodes in willUpdate() (mirrors hasActionsSlot
|
|
126
|
+
// above), then kept current via onMessageSlotChange() -- see
|
|
127
|
+
// isRealMessageNode()'s doc comment for why native <slot> fallback content
|
|
128
|
+
// can't be relied on for the default stalled-message text.
|
|
129
|
+
this.hasMessageContent = false;
|
|
130
|
+
this.onActionsSlotChange = (e) => {
|
|
131
|
+
this.hasActionsSlot = e.target.assignedElements({ flatten: true }).length > 0;
|
|
132
|
+
};
|
|
133
|
+
this.onMessageSlotChange = (e) => {
|
|
134
|
+
this.hasMessageContent = e.target.assignedNodes({ flatten: true }).some(isRealMessageNode);
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
138
|
+
willUpdate() {
|
|
139
|
+
if (!this.hasUpdated) {
|
|
140
|
+
this.hasActionsSlot = this.hasSlotted('actions');
|
|
141
|
+
this.hasMessageContent = Array.from(this.childNodes).some(isRealMessageNode);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// `changed.get('phase')` is `undefined` on the very first update, for the
|
|
145
|
+
// same reason documented on lyra-chat-message's identical `updated()`
|
|
146
|
+
// guard: Lit only records the *first* old value seen since the last
|
|
147
|
+
// completed update, and the constructor's field-initializer assignment is
|
|
148
|
+
// that first change, from the truly-unset internal slot. That naturally
|
|
149
|
+
// skips firing an event/announcement for whatever phase this element
|
|
150
|
+
// happens to mount with, while still arming the stall timer below if it
|
|
151
|
+
// mounts already `'streaming'`.
|
|
152
|
+
//
|
|
153
|
+
// The `else if` below only matters while `phase` itself didn't also change
|
|
154
|
+
// in this same update -- if it did, onPhaseChanged() above already
|
|
155
|
+
// (re)armed the timer with the current `stallThresholdMs`, so re-arming it
|
|
156
|
+
// again here would just be redundant, not wrong, but the `else` skips that
|
|
157
|
+
// double work.
|
|
158
|
+
updated(changed) {
|
|
159
|
+
if (changed.has('phase')) {
|
|
160
|
+
this.onPhaseChanged(changed.get('phase'));
|
|
161
|
+
}
|
|
162
|
+
else if (changed.has('stallThresholdMs') && this.phase === 'streaming') {
|
|
163
|
+
// Unlike `phase` itself, `stallThresholdMs` has no dedicated handler --
|
|
164
|
+
// the already-armed timer was scheduled against the *old* value and
|
|
165
|
+
// keeps counting down against it otherwise, so a shortened (or
|
|
166
|
+
// lengthened) threshold would silently have no effect until the next
|
|
167
|
+
// recordActivity() call or phase transition happened to re-arm it.
|
|
168
|
+
this.armStallTimer();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
connectedCallback() {
|
|
172
|
+
super.connectedCallback();
|
|
173
|
+
// A disconnect always disarms the timer (see disconnectedCallback()
|
|
174
|
+
// below), but reparenting this element elsewhere in the page while still
|
|
175
|
+
// `'streaming'` fires disconnectedCallback then connectedCallback with
|
|
176
|
+
// `phase` unchanged -- no `updated()` cycle runs in between, so nothing
|
|
177
|
+
// else would ever re-arm it. Without this, a reparent mid-stream would
|
|
178
|
+
// permanently disable stall detection for the rest of that streaming
|
|
179
|
+
// session.
|
|
180
|
+
if (this.phase === 'streaming')
|
|
181
|
+
this.armStallTimer();
|
|
182
|
+
}
|
|
183
|
+
disconnectedCallback() {
|
|
184
|
+
super.disconnectedCallback();
|
|
185
|
+
this.disarmStallTimer();
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Call on every semantic (non-heartbeat) frame received while streaming.
|
|
189
|
+
* - While `phase === 'streaming'`: (re)arms the stall timer, pushing the
|
|
190
|
+
* stall deadline `stall-threshold-ms` further out.
|
|
191
|
+
* - While `phase === 'stalled'`: recovers — `phase` becomes `'streaming'`
|
|
192
|
+
* again, `lyra-recover` fires, and the stall timer is armed fresh (same
|
|
193
|
+
* as the bullet above), all via the same `updated()` transition handling
|
|
194
|
+
* a direct host assignment would also go through.
|
|
195
|
+
* - While `phase` is `'idle'` or `'connecting'`: a no-op. A host may call
|
|
196
|
+
* this defensively before formally flipping to `'streaming'`; it must
|
|
197
|
+
* never throw or start a timer early.
|
|
198
|
+
*/
|
|
199
|
+
recordActivity() {
|
|
200
|
+
if (this.phase === 'streaming') {
|
|
201
|
+
this.armStallTimer();
|
|
202
|
+
}
|
|
203
|
+
else if (this.phase === 'stalled') {
|
|
204
|
+
this.phase = 'streaming';
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
onPhaseChanged(previous) {
|
|
208
|
+
if (this.phase === 'streaming') {
|
|
209
|
+
this.armStallTimer();
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
this.disarmStallTimer();
|
|
213
|
+
}
|
|
214
|
+
if (previous === undefined)
|
|
215
|
+
return;
|
|
216
|
+
if (this.phase === 'stalled' && previous !== 'stalled') {
|
|
217
|
+
this.emit('lyra-stall');
|
|
218
|
+
this.announceTransition('assertive', STALL_ANNOUNCEMENT);
|
|
219
|
+
}
|
|
220
|
+
else if (previous === 'stalled' && this.phase !== 'stalled') {
|
|
221
|
+
// `lyra-recover` fires unconditionally -- a host may still want the
|
|
222
|
+
// event for any exit from 'stalled' -- but the *announced text* must
|
|
223
|
+
// not claim the connection was "restored" when the destination is
|
|
224
|
+
// 'idle'/'connecting': that's the host abandoning the stream, not it
|
|
225
|
+
// recovering, and telling a screen-reader user otherwise would be the
|
|
226
|
+
// opposite of what a sighted user sees on screen.
|
|
227
|
+
this.emit('lyra-recover');
|
|
228
|
+
const text = this.phase === 'streaming' ? RECOVER_ANNOUNCEMENT : STALL_CLEARED_ANNOUNCEMENT;
|
|
229
|
+
this.announceTransition('polite', text);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
armStallTimer() {
|
|
233
|
+
this.disarmStallTimer();
|
|
234
|
+
const threshold = this.stallThresholdMs;
|
|
235
|
+
if (!Number.isFinite(threshold) || threshold <= 0)
|
|
236
|
+
return;
|
|
237
|
+
this.stallTimer = setTimeout(() => {
|
|
238
|
+
this.stallTimer = undefined;
|
|
239
|
+
this.phase = 'stalled';
|
|
240
|
+
}, threshold);
|
|
241
|
+
}
|
|
242
|
+
disarmStallTimer() {
|
|
243
|
+
if (this.stallTimer !== undefined) {
|
|
244
|
+
clearTimeout(this.stallTimer);
|
|
245
|
+
this.stallTimer = undefined;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
announceTransition(mode, text) {
|
|
249
|
+
const region = this.liveRegion;
|
|
250
|
+
if (!region)
|
|
251
|
+
return;
|
|
252
|
+
region.mode = mode;
|
|
253
|
+
region.announce(text, { force: true });
|
|
254
|
+
}
|
|
255
|
+
hasSlotted(name) {
|
|
256
|
+
return Array.from(this.children).some((el) => el.getAttribute('slot') === name);
|
|
257
|
+
}
|
|
258
|
+
render() {
|
|
259
|
+
return html `
|
|
260
|
+
<div part="base">
|
|
261
|
+
<span part="indicator" aria-hidden="true"></span>
|
|
262
|
+
${this.phase === 'stalled'
|
|
263
|
+
? html `<div part="message">
|
|
264
|
+
<slot @slotchange=${this.onMessageSlotChange}></slot>${this.hasMessageContent
|
|
265
|
+
? nothing
|
|
266
|
+
: DEFAULT_STALL_MESSAGE}
|
|
267
|
+
</div>`
|
|
268
|
+
: nothing}
|
|
269
|
+
<div part="actions" ?hidden=${!this.hasActionsSlot}>
|
|
270
|
+
<slot name="actions" @slotchange=${this.onActionsSlotChange}></slot>
|
|
271
|
+
</div>
|
|
272
|
+
<lyra-live-region></lyra-live-region>
|
|
273
|
+
</div>
|
|
274
|
+
`;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
__decorate([
|
|
278
|
+
property({ reflect: true })
|
|
279
|
+
], LyraStreamStatus.prototype, "phase", void 0);
|
|
280
|
+
__decorate([
|
|
281
|
+
property({ type: Number, attribute: 'stall-threshold-ms' })
|
|
282
|
+
], LyraStreamStatus.prototype, "stallThresholdMs", void 0);
|
|
283
|
+
__decorate([
|
|
284
|
+
state()
|
|
285
|
+
], LyraStreamStatus.prototype, "hasActionsSlot", void 0);
|
|
286
|
+
__decorate([
|
|
287
|
+
state()
|
|
288
|
+
], LyraStreamStatus.prototype, "hasMessageContent", void 0);
|
|
289
|
+
__decorate([
|
|
290
|
+
query('lyra-live-region')
|
|
291
|
+
], LyraStreamStatus.prototype, "liveRegion", void 0);
|
|
292
|
+
defineElement('stream-status', LyraStreamStatus);
|