@aceshooting/lyra-ui 1.2.0 → 2.0.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 +11 -0
- package/custom-elements.json +23341 -11202
- package/dist/components/app-rail/app-rail.d.ts +171 -0
- package/dist/components/app-rail/app-rail.js +483 -0
- package/dist/components/app-rail/app-rail.styles.d.ts +1 -0
- package/dist/components/app-rail/app-rail.styles.js +125 -0
- package/dist/components/attachment-chip/attachment-chip.d.ts +114 -0
- package/dist/components/attachment-chip/attachment-chip.js +312 -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 +83 -0
- package/dist/components/attachment-trigger/attachment-trigger.js +258 -0
- package/dist/components/attachment-trigger/attachment-trigger.styles.d.ts +1 -0
- package/dist/components/attachment-trigger/attachment-trigger.styles.js +68 -0
- package/dist/components/chart/box-plot.js +11 -1
- 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 +1 -2
- package/dist/components/chart/chart.js +67 -12
- package/dist/components/chart/histogram-bin.d.ts +4 -1
- package/dist/components/chart/histogram-bin.js +24 -14
- package/dist/components/chart/lite-chart.d.ts +54 -0
- package/dist/components/chart/lite-chart.js +140 -22
- package/dist/components/chart/lite-chart.styles.js +9 -0
- package/dist/components/chat-composer/chat-composer.d.ts +92 -0
- package/dist/components/chat-composer/chat-composer.js +285 -0
- package/dist/components/chat-composer/chat-composer.styles.d.ts +1 -0
- package/dist/components/chat-composer/chat-composer.styles.js +135 -0
- package/dist/components/chat-message/chat-message.d.ts +113 -0
- package/dist/components/chat-message/chat-message.js +291 -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 +59 -0
- package/dist/components/checkbox/checkbox.js +230 -0
- package/dist/components/checkbox/checkbox.styles.d.ts +1 -0
- package/dist/components/checkbox/checkbox.styles.js +70 -0
- package/dist/components/chip/chip-group.d.ts +56 -0
- package/dist/components/chip/chip-group.js +124 -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 +115 -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 +300 -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 +89 -0
- package/dist/components/code-block/code-block.js +317 -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 +44 -0
- package/dist/components/code-block/code-loader.js +79 -0
- package/dist/components/combobox/combobox.d.ts +19 -1
- package/dist/components/combobox/combobox.js +84 -14
- 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 +150 -0
- package/dist/components/context-meter/context-meter.styles.d.ts +1 -0
- package/dist/components/context-meter/context-meter.styles.js +120 -0
- package/dist/components/conversation-item/conversation-item.d.ts +128 -0
- package/dist/components/conversation-item/conversation-item.js +322 -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/date-input.d.ts +24 -0
- package/dist/components/date-picker/date-input.js +134 -22
- package/dist/components/date-picker/date-picker.d.ts +7 -0
- package/dist/components/date-picker/date-picker.js +85 -16
- package/dist/components/dialog/confirm.d.ts +40 -0
- package/dist/components/dialog/confirm.js +79 -0
- package/dist/components/dialog/dialog.d.ts +85 -0
- package/dist/components/dialog/dialog.js +272 -0
- package/dist/components/dialog/dialog.styles.d.ts +1 -0
- package/dist/components/dialog/dialog.styles.js +52 -0
- package/dist/components/dock-panel/dock-panel.d.ts +134 -0
- package/dist/components/dock-panel/dock-panel.js +345 -0
- package/dist/components/dock-panel/dock-panel.styles.d.ts +1 -0
- package/dist/components/dock-panel/dock-panel.styles.js +145 -0
- package/dist/components/document-preview/document-preview.d.ts +135 -0
- package/dist/components/document-preview/document-preview.js +372 -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/export-button/csv.js +1 -1
- package/dist/components/export-button/export-button.js +2 -0
- package/dist/components/flag/flag.d.ts +29 -13
- package/dist/components/flag/flag.js +39 -13
- package/dist/components/gauge/gauge.js +19 -10
- package/dist/components/generation-status/generation-status.d.ts +109 -0
- package/dist/components/generation-status/generation-status.js +273 -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/heatmap/calendar-grid.d.ts +4 -1
- package/dist/components/heatmap/calendar-grid.js +25 -12
- package/dist/components/heatmap/heatmap-scale.d.ts +6 -0
- package/dist/components/heatmap/heatmap-scale.js +7 -1
- package/dist/components/heatmap/heatmap.d.ts +74 -0
- package/dist/components/heatmap/heatmap.js +135 -23
- package/dist/components/json-viewer/json-viewer.d.ts +53 -0
- package/dist/components/json-viewer/json-viewer.js +283 -0
- package/dist/components/json-viewer/json-viewer.styles.d.ts +1 -0
- package/dist/components/json-viewer/json-viewer.styles.js +176 -0
- package/dist/components/kbd/kbd.d.ts +77 -0
- package/dist/components/kbd/kbd.js +214 -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 +81 -0
- package/dist/components/live-region/live-region.js +153 -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 +8 -6
- package/dist/components/map/map.js +44 -8
- package/dist/components/markdown/markdown-loader.d.ts +34 -0
- package/dist/components/markdown/markdown-loader.js +43 -0
- package/dist/components/markdown/markdown.d.ts +81 -0
- package/dist/components/markdown/markdown.js +284 -0
- package/dist/components/markdown/markdown.styles.d.ts +1 -0
- package/dist/components/markdown/markdown.styles.js +82 -0
- package/dist/components/media-card/media-card.d.ts +122 -0
- package/dist/components/media-card/media-card.js +295 -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 +200 -0
- package/dist/components/mention-popover/mention-popover.js +475 -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 +62 -0
- package/dist/components/menu/menu-item.js +119 -0
- package/dist/components/menu/menu-item.styles.d.ts +1 -0
- package/dist/components/menu/menu-item.styles.js +67 -0
- package/dist/components/menu/menu.d.ts +143 -0
- package/dist/components/menu/menu.js +365 -0
- package/dist/components/menu/menu.styles.d.ts +1 -0
- package/dist/components/menu/menu.styles.js +66 -0
- package/dist/components/model-select/model-select.d.ts +125 -0
- package/dist/components/model-select/model-select.js +490 -0
- package/dist/components/model-select/model-select.styles.d.ts +1 -0
- package/dist/components/model-select/model-select.styles.js +189 -0
- package/dist/components/model-settings-panel/model-settings-panel.d.ts +69 -0
- package/dist/components/model-settings-panel/model-settings-panel.js +145 -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 +13 -1
- package/dist/components/playback/playback.js +47 -14
- package/dist/components/responsive-panel/responsive-panel.d.ts +150 -0
- package/dist/components/responsive-panel/responsive-panel.js +365 -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 +44 -0
- package/dist/components/result-card/result-card.js +83 -0
- package/dist/components/result-card/result-card.styles.d.ts +1 -0
- package/dist/components/result-card/result-card.styles.js +50 -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 +43 -2
- package/dist/components/select/select.js +150 -17
- package/dist/components/slider/slider.d.ts +89 -0
- package/dist/components/slider/slider.js +352 -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 +92 -0
- package/dist/components/source-card/source-card.js +148 -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 +122 -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 +27 -13
- package/dist/components/split/split.d.ts +93 -1
- package/dist/components/split/split.js +284 -15
- package/dist/components/split/split.styles.js +30 -0
- package/dist/components/stat/stat.d.ts +6 -1
- package/dist/components/stat/stat.js +8 -2
- package/dist/components/stream-status/stream-status.d.ts +110 -0
- package/dist/components/stream-status/stream-status.js +210 -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 +98 -0
- package/dist/components/streaming-text/streaming-text.js +209 -0
- package/dist/components/streaming-text/streaming-text.styles.d.ts +1 -0
- package/dist/components/streaming-text/streaming-text.styles.js +62 -0
- package/dist/components/switch/switch.d.ts +58 -0
- package/dist/components/switch/switch.js +179 -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 +73 -4
- package/dist/components/table/table.js +169 -20
- package/dist/components/table/table.styles.js +6 -1
- package/dist/components/tabs/tabs.d.ts +51 -0
- package/dist/components/tabs/tabs.js +190 -0
- package/dist/components/tabs/tabs.styles.d.ts +1 -0
- package/dist/components/tabs/tabs.styles.js +63 -0
- package/dist/components/thinking-panel/thinking-panel.d.ts +121 -0
- package/dist/components/thinking-panel/thinking-panel.js +235 -0
- package/dist/components/thinking-panel/thinking-panel.styles.d.ts +1 -0
- package/dist/components/thinking-panel/thinking-panel.styles.js +117 -0
- package/dist/components/toast/toast-item.d.ts +1 -0
- package/dist/components/toast/toast-item.js +31 -6
- package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +130 -0
- package/dist/components/tool-approval-dialog/tool-approval-dialog.js +403 -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 +89 -0
- package/dist/components/tool-call-chip/tool-call-chip.js +288 -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 +145 -0
- package/dist/components/tool-param-form/tool-param-form.js +366 -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 +102 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.js +393 -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 +81 -0
- package/dist/components/tool-result-view/registry.js +84 -0
- package/dist/components/tool-result-view/tool-result-view.d.ts +55 -0
- package/dist/components/tool-result-view/tool-result-view.js +138 -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 +439 -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 +182 -0
- package/dist/components/tree/tree-node.d.ts +11 -2
- package/dist/components/tree/tree-node.js +16 -6
- package/dist/components/tree/tree.d.ts +8 -2
- package/dist/components/tree/tree.js +18 -11
- package/dist/components/typing-indicator/typing-indicator.d.ts +60 -0
- package/dist/components/typing-indicator/typing-indicator.js +96 -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 +173 -0
- package/dist/components/virtual-list/virtual-list.js +461 -0
- package/dist/components/virtual-list/virtual-list.styles.d.ts +1 -0
- package/dist/components/virtual-list/virtual-list.styles.js +44 -0
- package/dist/components/word-cloud/word-cloud-layout.js +14 -1
- package/dist/components/word-cloud/word-cloud.d.ts +6 -0
- package/dist/components/word-cloud/word-cloud.js +25 -14
- package/dist/components/word-cloud/word-cloud.styles.js +3 -2
- package/dist/internal/announcer.d.ts +57 -0
- package/dist/internal/announcer.js +71 -0
- package/dist/internal/form-associated.d.ts +1 -0
- package/dist/internal/form-associated.js +55 -11
- package/dist/internal/group-by-recency.d.ts +50 -0
- package/dist/internal/group-by-recency.js +80 -0
- package/dist/internal/rtl.d.ts +23 -0
- package/dist/internal/rtl.js +28 -0
- package/dist/internal/scroll-lock.d.ts +10 -5
- package/dist/internal/scroll-lock.js +30 -14
- package/dist/internal/tokens.styles.js +6 -0
- package/dist/lyra.d.ts +130 -31
- package/dist/lyra.js +94 -26
- package/llms-full.txt +3836 -17
- package/llms.txt +16 -1
- package/package.json +23 -5
- 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,8 +4,8 @@ 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 } from 'lit';
|
|
8
|
-
import { property, state } from 'lit/decorators.js';
|
|
7
|
+
import { html, nothing } from 'lit';
|
|
8
|
+
import { property, state, query } from 'lit/decorators.js';
|
|
9
9
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
10
|
import { defineElement } from '../../internal/prefix.js';
|
|
11
11
|
import { isRtl } from '../../internal/rtl.js';
|
|
@@ -20,11 +20,28 @@ const NO_MAX_PX = 1_000_000;
|
|
|
20
20
|
* `<lyra-split>` — resizable panels for dashboard layouts. Direct light-DOM
|
|
21
21
|
* children are the panels; a divider is auto-inserted between each pair.
|
|
22
22
|
*
|
|
23
|
+
* Optionally, one pane can opt in to responsive collapse via `collapse`
|
|
24
|
+
* (`"start"`/`"end"`, default `"none"` — no behavior change when unset): as
|
|
25
|
+
* the split's own container narrows past `railBreakpoint` that pane clamps
|
|
26
|
+
* to a fixed `railWidth`, and past the narrower `floatBreakpoint` it instead
|
|
27
|
+
* becomes an absolutely-positioned overlay "floating card" above the other
|
|
28
|
+
* pane. This component only handles the width-collapse mechanics and
|
|
29
|
+
* signals the current state — via the `collapseState`-derived
|
|
30
|
+
* `data-collapse-state` attribute (set on both the host and the collapsing
|
|
31
|
+
* panel itself) and the `lyra-split-collapse-change` event — it renders no
|
|
32
|
+
* icon-only/collapsed UI of its own; slotted content is expected to adapt to
|
|
33
|
+
* its own clamped width (e.g. via its own container query).
|
|
34
|
+
*
|
|
23
35
|
* @customElement lyra-split
|
|
24
36
|
* @event lyra-resize - `detail: { sizes }`, fired on every drag step/release
|
|
25
37
|
* and every keyboard step.
|
|
38
|
+
* @event lyra-split-collapse-change - `detail: { state }` (`SplitCollapseChangeDetail`),
|
|
39
|
+
* fired whenever the responsive `collapseState` actually transitions between
|
|
40
|
+
* `'wide'`/`'rail'`/`'floating'`. Only relevant when `collapse` isn't `"none"`;
|
|
41
|
+
* never fires otherwise.
|
|
26
42
|
* @slot - Panels to arrange side by side (or stacked, when `orientation="vertical"`); each direct child becomes one resizable panel.
|
|
27
|
-
* @csspart base
|
|
43
|
+
* @csspart base - The flex layout wrapper (`position: relative`, so the `'floating'` collapse state can anchor to it).
|
|
44
|
+
* @csspart divider - Each divider between two panels; carries `aria-disabled="true"` and is drag/keyboard-inert while its adjacent panel is collapsed (`'rail'`/`'floating'`).
|
|
28
45
|
*/
|
|
29
46
|
export class LyraSplit extends LyraElement {
|
|
30
47
|
constructor() {
|
|
@@ -38,21 +55,55 @@ export class LyraSplit extends LyraElement {
|
|
|
38
55
|
* localStorage persistence stay percent-based regardless — only the
|
|
39
56
|
* effective clamp bounds change for a constrained panel. */
|
|
40
57
|
this.panelConstraints = [];
|
|
58
|
+
/** Opts a pane in to responsive collapse: `'start'` is the first light-DOM
|
|
59
|
+
* panel (index 0), `'end'` is the last. Both are LOGICAL positions, same
|
|
60
|
+
* as CSS `inset-inline-start`/`-end` — see the `collapsingIndex` getter
|
|
61
|
+
* for why that already resolves to the same physical index under RTL for
|
|
62
|
+
* this component (panels are never re-`order`ed for RTL, only the drag
|
|
63
|
+
* delta sign mirrors). Default `'none'`: none of the collapse behavior
|
|
64
|
+
* below applies, and rendering/behavior is identical to before this
|
|
65
|
+
* property existed. */
|
|
66
|
+
this.collapse = 'none';
|
|
67
|
+
/** Fixed CSS length the collapsing pane clamps to in the `'rail'` state. */
|
|
68
|
+
this.railWidth = '3.5rem';
|
|
69
|
+
/** Container width (px, measured on `[part="base"]`) below which the
|
|
70
|
+
* collapsing pane switches from its normal percent width to the fixed
|
|
71
|
+
* `railWidth` (`'rail'` state). Must stay above `floatBreakpoint`. */
|
|
72
|
+
this.railBreakpoint = 640;
|
|
73
|
+
/** Container width (px) below which the collapsing pane instead becomes an
|
|
74
|
+
* absolutely-positioned overlay above the other pane (`'floating'` state). */
|
|
75
|
+
this.floatBreakpoint = 400;
|
|
41
76
|
this.panelCount = 0;
|
|
77
|
+
/** The collapsing pane's current responsive state; always `'wide'` (a
|
|
78
|
+
* no-op) while `collapse === 'none'`. */
|
|
79
|
+
this.collapseState = 'wide';
|
|
42
80
|
// Keyed by pointerId so an interrupted or concurrent (multi-touch) drag on
|
|
43
81
|
// one divider never reads or clobbers another pointer's drag state.
|
|
44
82
|
this.drags = new Map();
|
|
83
|
+
// Panels `updated()` last applied inline flex/order (and, while collapsing,
|
|
84
|
+
// position/inset/inline-size) styles to — tracked so a panel removed from
|
|
85
|
+
// the slot (e.g. a DOM node later reused elsewhere) gets those
|
|
86
|
+
// lyra-split-authored styles cleared instead of carrying them around stale
|
|
87
|
+
// forever.
|
|
88
|
+
this.stylizedPanels = new Set();
|
|
45
89
|
this.onSlotChange = () => {
|
|
46
90
|
this.panelCount = this.children.length;
|
|
47
91
|
this.ensureSizes();
|
|
48
92
|
};
|
|
49
93
|
this.onPointerDown = (e, index) => {
|
|
94
|
+
// The divider adjacent to a currently rail/floating-collapsed pane isn't
|
|
95
|
+
// draggable — mirrors the `[part="divider"][aria-disabled="true"]`
|
|
96
|
+
// `pointer-events: none` in split.styles.ts (belt-and-suspenders: this
|
|
97
|
+
// guard also covers a synthetic/programmatic pointerdown that CSS
|
|
98
|
+
// wouldn't stop).
|
|
99
|
+
if (this.isDividerDisabled(index))
|
|
100
|
+
return;
|
|
50
101
|
const base = this.renderRoot.querySelector('[part="base"]');
|
|
51
102
|
this.drags.set(e.pointerId, {
|
|
52
103
|
index,
|
|
53
104
|
startPos: this.orientation === 'vertical' ? e.clientY : e.clientX,
|
|
54
|
-
startSizes: [...this.sizes],
|
|
55
105
|
base,
|
|
106
|
+
appliedDelta: 0,
|
|
56
107
|
});
|
|
57
108
|
e.target.setPointerCapture(e.pointerId);
|
|
58
109
|
window.addEventListener('pointermove', this.onPointerMove);
|
|
@@ -70,14 +121,40 @@ export class LyraSplit extends LyraElement {
|
|
|
70
121
|
return;
|
|
71
122
|
const total = this.orientation === 'vertical' ? drag.base.clientHeight : drag.base.clientWidth;
|
|
72
123
|
const pos = this.orientation === 'vertical' ? e.clientY : e.clientX;
|
|
73
|
-
let
|
|
124
|
+
let cumulativeDelta = ((pos - drag.startPos) / total) * 100;
|
|
74
125
|
// Panels are ordered along the inline axis via CSS `order`, so under RTL
|
|
75
126
|
// `flex-direction: row` already renders panel[i] to the *right* of
|
|
76
127
|
// panel[i+1] — a physically-rightward drag has to shrink index instead
|
|
77
128
|
// of growing it to keep matching the visible panel under the pointer.
|
|
78
129
|
if (this.orientation === 'horizontal' && isRtl(this))
|
|
79
|
-
|
|
80
|
-
|
|
130
|
+
cumulativeDelta = -cumulativeDelta;
|
|
131
|
+
// Clamp against the *current* live sizes, not this pointer's own drag-start
|
|
132
|
+
// snapshot -- two adjacent dividers dragged concurrently share one panel
|
|
133
|
+
// between them, and each clamp pass must see whatever the other pointer's
|
|
134
|
+
// move has *just* written, or the two independently-clamped pairs can each
|
|
135
|
+
// stay individually valid while their shared panel drifts past what either
|
|
136
|
+
// pair alone would allow, letting the total exceed 100%. Since the clamp
|
|
137
|
+
// basis is now the live, already-partially-applied `this.sizes` instead of
|
|
138
|
+
// a fixed drag-start snapshot, only the *incremental* delta since the last
|
|
139
|
+
// move may be applied here (not the cumulative-since-drag-start delta a
|
|
140
|
+
// snapshot-based clamp would use).
|
|
141
|
+
const incremental = cumulativeDelta - drag.appliedDelta;
|
|
142
|
+
const priorValue = this.sizes[drag.index];
|
|
143
|
+
const paired = this.clampPair(this.sizes, drag.index, incremental, total);
|
|
144
|
+
// Accumulate this move's own *realized* increment (post-clamp) onto the
|
|
145
|
+
// running total, rather than recomputing an absolute "total since
|
|
146
|
+
// drag-start" diff against a fixed startSizes snapshot. clampPair can
|
|
147
|
+
// cap the actual move short of what was requested (e.g. a drag
|
|
148
|
+
// saturating a panel's min/panelConstraints bound), so the realized
|
|
149
|
+
// portion still has to be tracked instead of the raw request -- that
|
|
150
|
+
// part of round 1's fix stands. But an absolute since-start diff also
|
|
151
|
+
// silently absorbs any change a DIFFERENT concurrent pointer's drag
|
|
152
|
+
// makes to this same shared panel between this pointer's own moves
|
|
153
|
+
// (adjacent dividers share one panel: divider i's index+1 panel is
|
|
154
|
+
// divider i+1's index panel), corrupting this pointer's next incremental
|
|
155
|
+
// calculation. Summing only this move's own delta (paired vs. the value
|
|
156
|
+
// immediately prior to *this* clamp) avoids both bugs at once.
|
|
157
|
+
drag.appliedDelta += paired[drag.index] - priorValue;
|
|
81
158
|
// Merge only this drag's pair into the live sizes so a concurrent drag
|
|
82
159
|
// on another divider (different pointerId) isn't clobbered.
|
|
83
160
|
const next = [...this.sizes];
|
|
@@ -99,6 +176,9 @@ export class LyraSplit extends LyraElement {
|
|
|
99
176
|
}
|
|
100
177
|
};
|
|
101
178
|
this.onDividerKeyDown = (e, index) => {
|
|
179
|
+
// Same rail/floating-adjacent guard as onPointerDown.
|
|
180
|
+
if (this.isDividerDisabled(index))
|
|
181
|
+
return;
|
|
102
182
|
// Mirror the same swap as onPointerMove for horizontal+RTL.
|
|
103
183
|
const rtl = this.orientation === 'horizontal' && isRtl(this);
|
|
104
184
|
const forwardKey = this.orientation === 'vertical' ? 'ArrowDown' : rtl ? 'ArrowLeft' : 'ArrowRight';
|
|
@@ -119,6 +199,13 @@ export class LyraSplit extends LyraElement {
|
|
|
119
199
|
this.panelCount = this.children.length;
|
|
120
200
|
this.ensureSizes();
|
|
121
201
|
this.loadPersisted();
|
|
202
|
+
// No-op on first mount (`baseEl` doesn't exist until the first render —
|
|
203
|
+
// `firstUpdated()` below arms it then) but does the real work on a
|
|
204
|
+
// reconnect, whose shadow DOM content survives disconnect. Mirrors
|
|
205
|
+
// lite-chart.ts's identical connectedCallback/firstUpdated split for its
|
|
206
|
+
// own ResizeObserver.
|
|
207
|
+
if (this.collapse !== 'none')
|
|
208
|
+
this.armCollapseObserver();
|
|
122
209
|
}
|
|
123
210
|
disconnectedCallback() {
|
|
124
211
|
super.disconnectedCallback();
|
|
@@ -128,6 +215,11 @@ export class LyraSplit extends LyraElement {
|
|
|
128
215
|
window.removeEventListener('pointerup', this.onPointerUp);
|
|
129
216
|
window.removeEventListener('pointercancel', this.onPointerUp);
|
|
130
217
|
window.removeEventListener('lostpointercapture', this.onPointerUp);
|
|
218
|
+
this.collapseResizeObserver?.disconnect();
|
|
219
|
+
}
|
|
220
|
+
firstUpdated() {
|
|
221
|
+
if (this.collapse !== 'none')
|
|
222
|
+
this.armCollapseObserver();
|
|
131
223
|
}
|
|
132
224
|
get storageFullKey() {
|
|
133
225
|
return this.storageKey ? `lyra-split:${this.storageKey}:${this.panelCount}` : undefined;
|
|
@@ -211,6 +303,84 @@ export class LyraSplit extends LyraElement {
|
|
|
211
303
|
return 0;
|
|
212
304
|
return this.orientation === 'vertical' ? base.clientHeight : base.clientWidth;
|
|
213
305
|
}
|
|
306
|
+
/** The physical panel index `collapse: 'start' | 'end'` resolves to, or
|
|
307
|
+
* `-1` when collapse is off (`'none'`) or there are fewer than 2 panels
|
|
308
|
+
* to collapse one of. Panels are laid out via ascending inline `order`
|
|
309
|
+
* (see `updated()`) and that ordering is never re-swapped for RTL — only
|
|
310
|
+
* the drag/keyboard *delta sign* mirrors for RTL, exactly like
|
|
311
|
+
* `onPointerMove`/`onDividerKeyDown` — so panel index 0 already renders
|
|
312
|
+
* at the logical inline-start edge under both LTR and RTL (confirmed by
|
|
313
|
+
* the pointer-drag RTL test elsewhere in this file: panel 0 renders on
|
|
314
|
+
* the visual *right*, i.e. the RTL inline-start side). `'start'` therefore
|
|
315
|
+
* always resolves to index 0 and `'end'` to `panelCount - 1`, regardless
|
|
316
|
+
* of `isRtl(this)` — consulting it here would swap collapse onto the
|
|
317
|
+
* panel that visually sits at the *other* logical edge, which would be a
|
|
318
|
+
* bug against this component's own RTL rendering, not a fix for one.
|
|
319
|
+
*/
|
|
320
|
+
get collapsingIndex() {
|
|
321
|
+
if (this.collapse === 'none' || this.panelCount < 2)
|
|
322
|
+
return -1;
|
|
323
|
+
return this.collapse === 'start' ? 0 : this.panelCount - 1;
|
|
324
|
+
}
|
|
325
|
+
/** Whether a pane is actually collapsed (rail or floating) right now —
|
|
326
|
+
* `false` whenever `collapse === 'none'`, since `collapseState` then
|
|
327
|
+
* never leaves its `'wide'` default. */
|
|
328
|
+
get collapseActive() {
|
|
329
|
+
return this.collapsingIndex !== -1 && this.collapseState !== 'wide';
|
|
330
|
+
}
|
|
331
|
+
/** Dragging/keyboard-resizing is disabled on the one divider immediately
|
|
332
|
+
* adjacent to the currently-collapsed pane (its other side has nothing
|
|
333
|
+
* meaningful to resize against while the pane is rail/floating-width). */
|
|
334
|
+
isDividerDisabled(index) {
|
|
335
|
+
if (!this.collapseActive)
|
|
336
|
+
return false;
|
|
337
|
+
const adjacent = this.collapsingIndex === 0 ? 0 : this.panelCount - 2;
|
|
338
|
+
return index === adjacent;
|
|
339
|
+
}
|
|
340
|
+
/** Classifies a measured container width into the collapsing pane's
|
|
341
|
+
* responsive state and, only on an actual transition, updates
|
|
342
|
+
* `collapseState` and fires `lyra-split-collapse-change`. */
|
|
343
|
+
updateCollapseState(width) {
|
|
344
|
+
if (this.collapse === 'none')
|
|
345
|
+
return;
|
|
346
|
+
const next = width < this.floatBreakpoint ? 'floating' : width < this.railBreakpoint ? 'rail' : 'wide';
|
|
347
|
+
if (next === this.collapseState)
|
|
348
|
+
return;
|
|
349
|
+
this.collapseState = next;
|
|
350
|
+
this.emit('lyra-split-collapse-change', { state: next });
|
|
351
|
+
}
|
|
352
|
+
/** Creates (idempotently) and (re-)observes `[part="base"]` with the
|
|
353
|
+
* collapse-state `ResizeObserver` — a no-op until `baseEl` exists (see
|
|
354
|
+
* `firstUpdated()`/`connectedCallback()`). Mirrors lite-chart.ts's own
|
|
355
|
+
* ResizeObserver setup, including reading the box size synchronously
|
|
356
|
+
* once so the very first render doesn't sit at the stale `'wide'` default
|
|
357
|
+
* until the (async) first callback fires — same rationale as
|
|
358
|
+
* lyra-virtual-list's `containerResizeObserver` synchronous initial read. */
|
|
359
|
+
armCollapseObserver() {
|
|
360
|
+
if (!this.collapseResizeObserver) {
|
|
361
|
+
this.collapseResizeObserver = new ResizeObserver((entries) => {
|
|
362
|
+
const box = entries[0]?.contentBoxSize?.[0];
|
|
363
|
+
const width = box ? box.inlineSize : (this.baseEl?.getBoundingClientRect().width ?? 0);
|
|
364
|
+
this.updateCollapseState(width);
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
if (this.baseEl) {
|
|
368
|
+
this.collapseResizeObserver.observe(this.baseEl);
|
|
369
|
+
this.updateCollapseState(this.baseEl.clientWidth);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/** Reacts to a live `collapse` property change (as opposed to the
|
|
373
|
+
* connect/first-render arming above): turns the observer on/off, and
|
|
374
|
+
* resets `collapseState` back to its `'wide'` default when collapse is
|
|
375
|
+
* switched off so no stale rail/floating styling survives it. */
|
|
376
|
+
syncCollapseObserver() {
|
|
377
|
+
if (this.collapse === 'none') {
|
|
378
|
+
this.collapseResizeObserver?.disconnect();
|
|
379
|
+
this.collapseState = 'wide';
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
this.armCollapseObserver();
|
|
383
|
+
}
|
|
214
384
|
/** Resolves panel `index`'s effective percent min/max for this clamp pass:
|
|
215
385
|
* a `panelConstraints` entry's px bound converted against the live
|
|
216
386
|
* `containerSize`, or the component's plain percent `min` (no upper
|
|
@@ -257,19 +427,98 @@ export class LyraSplit extends LyraElement {
|
|
|
257
427
|
updated(changed) {
|
|
258
428
|
if (changed.has('sizes') || this.sizes.length === 0)
|
|
259
429
|
this.ensureSizes();
|
|
430
|
+
if (changed.has('collapse'))
|
|
431
|
+
this.syncCollapseObserver();
|
|
260
432
|
const panels = [...this.children];
|
|
433
|
+
const current = new Set(panels);
|
|
434
|
+
// A panel that dropped out of the slot (removed from the light DOM)
|
|
435
|
+
// still carries whatever inline flex/order (and, while collapsing,
|
|
436
|
+
// position/inset/inline-size) this method last applied to it — clear
|
|
437
|
+
// those before that DOM node potentially gets reused elsewhere (e.g.
|
|
438
|
+
// re-slotted into another split/container).
|
|
439
|
+
for (const stale of this.stylizedPanels) {
|
|
440
|
+
if (!current.has(stale)) {
|
|
441
|
+
stale.style.removeProperty('flex');
|
|
442
|
+
stale.style.removeProperty('order');
|
|
443
|
+
stale.style.removeProperty('position');
|
|
444
|
+
stale.style.removeProperty('inset-block');
|
|
445
|
+
stale.style.removeProperty('inset-inline-start');
|
|
446
|
+
stale.style.removeProperty('inset-inline-end');
|
|
447
|
+
stale.style.removeProperty('inline-size');
|
|
448
|
+
delete stale.dataset.collapseState;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
// Resolved once per pass rather than per panel: which physical index (if
|
|
452
|
+
// any) is actually collapsed right now — `-1` covers both `collapse ===
|
|
453
|
+
// 'none'` (the default) and a `collapse !== 'none'` pane that's still in
|
|
454
|
+
// its normal `'wide'` state, so every panel below falls straight through
|
|
455
|
+
// to the exact pre-existing (non-collapse) styling in either case.
|
|
456
|
+
const collapsingIndex = this.collapseActive ? this.collapsingIndex : -1;
|
|
261
457
|
panels.forEach((panel, i) => {
|
|
262
458
|
const percent = this.sizes[i] ?? 0;
|
|
263
459
|
const constraint = this.panelConstraints[i];
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
panel.style.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
460
|
+
// Collapse-only inline styles are always cleared first, then
|
|
461
|
+
// re-applied below only for the panel(s) that need them this pass —
|
|
462
|
+
// simpler than diffing which of the 5 properties changed.
|
|
463
|
+
panel.style.removeProperty('position');
|
|
464
|
+
panel.style.removeProperty('inset-block');
|
|
465
|
+
panel.style.removeProperty('inset-inline-start');
|
|
466
|
+
panel.style.removeProperty('inset-inline-end');
|
|
467
|
+
panel.style.removeProperty('inline-size');
|
|
468
|
+
if (collapsingIndex === i && this.collapseState === 'rail') {
|
|
469
|
+
// Fixed rail width instead of the normal clamp()/percent flex-basis.
|
|
470
|
+
panel.style.flex = `0 0 ${this.railWidth}`;
|
|
471
|
+
}
|
|
472
|
+
else if (collapsingIndex === i && this.collapseState === 'floating') {
|
|
473
|
+
// Lifted out of the flex flow entirely as an overlay card, anchored
|
|
474
|
+
// to its own logical start/end edge, spanning the full cross-axis
|
|
475
|
+
// extent — [part="base"] carries `position: relative` for this to
|
|
476
|
+
// anchor against (see split.styles.ts). Sized at its own normal
|
|
477
|
+
// percent width (i.e. what it would render at in the `'wide'`
|
|
478
|
+
// state), so there's no visual size jump the moment it un-floats.
|
|
479
|
+
panel.style.flex = 'none';
|
|
480
|
+
panel.style.position = 'absolute';
|
|
481
|
+
panel.style.setProperty('inset-block', '0');
|
|
482
|
+
panel.style.setProperty(collapsingIndex === 0 ? 'inset-inline-start' : 'inset-inline-end', '0');
|
|
483
|
+
panel.style.setProperty('inline-size', `${percent}%`);
|
|
484
|
+
}
|
|
485
|
+
else if (collapsingIndex !== -1 && i !== collapsingIndex) {
|
|
486
|
+
// The pane(s) sharing the split with a currently rail/floating
|
|
487
|
+
// collapsed pane: grow to fill whatever space that pane no longer
|
|
488
|
+
// occupies (its full percent-basis space while floating, or
|
|
489
|
+
// percent-basis-minus-railWidth while railed), proportionally to
|
|
490
|
+
// their own relative `sizes` share for a 3+-panel split.
|
|
491
|
+
panel.style.flex = `${percent} 1 0%`;
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
// clamp() mixes units natively, so a constrained panel stays pinned
|
|
495
|
+
// between its px bounds across container resizes with no extra
|
|
496
|
+
// ResizeObserver — the browser re-evaluates it on every layout pass.
|
|
497
|
+
panel.style.flex =
|
|
498
|
+
constraint && (constraint.minPx != null || constraint.maxPx != null)
|
|
499
|
+
? `0 0 clamp(${constraint.minPx ?? NO_MIN_PX}px, ${percent}%, ${constraint.maxPx ?? NO_MAX_PX}px)`
|
|
500
|
+
: `0 0 ${percent}%`;
|
|
501
|
+
}
|
|
271
502
|
panel.style.order = String(i * 2);
|
|
503
|
+
if (collapsingIndex === i) {
|
|
504
|
+
panel.dataset.collapseState = this.collapseState;
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
delete panel.dataset.collapseState;
|
|
508
|
+
}
|
|
272
509
|
});
|
|
510
|
+
this.stylizedPanels = current;
|
|
511
|
+
// Host-level marker (mirrors the per-panel `dataset.collapseState`
|
|
512
|
+
// above) for simple external CSS targeting of the whole component's
|
|
513
|
+
// current state, e.g. `lyra-split[data-collapse-state="rail"] + aside`.
|
|
514
|
+
// Absent whenever there's nothing collapsed to report (`collapse ===
|
|
515
|
+
// 'none'` or still `'wide'`), same as the per-panel marker.
|
|
516
|
+
if (collapsingIndex !== -1) {
|
|
517
|
+
this.setAttribute('data-collapse-state', this.collapseState);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
this.removeAttribute('data-collapse-state');
|
|
521
|
+
}
|
|
273
522
|
}
|
|
274
523
|
render() {
|
|
275
524
|
const dividers = [];
|
|
@@ -278,6 +527,7 @@ export class LyraSplit extends LyraElement {
|
|
|
278
527
|
// panels, not the whole track — pushing past it would starve a panel
|
|
279
528
|
// further down the line even though this pair still has room.
|
|
280
529
|
const valueMax = (this.sizes[i] ?? 0) + (this.sizes[i + 1] ?? 0) - this.min;
|
|
530
|
+
const disabled = this.isDividerDisabled(i);
|
|
281
531
|
dividers.push(html `<div
|
|
282
532
|
part="divider"
|
|
283
533
|
role="separator"
|
|
@@ -286,7 +536,8 @@ export class LyraSplit extends LyraElement {
|
|
|
286
536
|
aria-valuenow=${Math.round(this.sizes[i] ?? 0)}
|
|
287
537
|
aria-valuemin=${this.min}
|
|
288
538
|
aria-valuemax=${Math.round(valueMax)}
|
|
289
|
-
|
|
539
|
+
aria-disabled=${disabled ? 'true' : nothing}
|
|
540
|
+
tabindex=${disabled ? '-1' : '0'}
|
|
290
541
|
style=${`order:${i * 2 + 1}`}
|
|
291
542
|
@pointerdown=${(e) => this.onPointerDown(e, i)}
|
|
292
543
|
@keydown=${(e) => this.onDividerKeyDown(e, i)}
|
|
@@ -310,7 +561,25 @@ __decorate([
|
|
|
310
561
|
__decorate([
|
|
311
562
|
property({ attribute: false })
|
|
312
563
|
], LyraSplit.prototype, "panelConstraints", void 0);
|
|
564
|
+
__decorate([
|
|
565
|
+
property({ reflect: true })
|
|
566
|
+
], LyraSplit.prototype, "collapse", void 0);
|
|
567
|
+
__decorate([
|
|
568
|
+
property({ attribute: 'rail-width' })
|
|
569
|
+
], LyraSplit.prototype, "railWidth", void 0);
|
|
570
|
+
__decorate([
|
|
571
|
+
property({ type: Number, attribute: 'rail-breakpoint' })
|
|
572
|
+
], LyraSplit.prototype, "railBreakpoint", void 0);
|
|
573
|
+
__decorate([
|
|
574
|
+
property({ type: Number, attribute: 'float-breakpoint' })
|
|
575
|
+
], LyraSplit.prototype, "floatBreakpoint", void 0);
|
|
313
576
|
__decorate([
|
|
314
577
|
state()
|
|
315
578
|
], LyraSplit.prototype, "panelCount", void 0);
|
|
579
|
+
__decorate([
|
|
580
|
+
state()
|
|
581
|
+
], LyraSplit.prototype, "collapseState", void 0);
|
|
582
|
+
__decorate([
|
|
583
|
+
query('[part="base"]')
|
|
584
|
+
], LyraSplit.prototype, "baseEl", void 0);
|
|
316
585
|
defineElement('split', LyraSplit);
|
|
@@ -7,6 +7,9 @@ export const styles = css `
|
|
|
7
7
|
}
|
|
8
8
|
[part='base'] {
|
|
9
9
|
display: flex;
|
|
10
|
+
/* Anchor for the 'floating' collapse state's absolutely-positioned
|
|
11
|
+
overlay panel (set inline by split.ts's updated()). */
|
|
12
|
+
position: relative;
|
|
10
13
|
inline-size: 100%;
|
|
11
14
|
block-size: 100%;
|
|
12
15
|
}
|
|
@@ -48,4 +51,31 @@ export const styles = css `
|
|
|
48
51
|
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
49
52
|
outline-offset: var(--lyra-focus-ring-offset);
|
|
50
53
|
}
|
|
54
|
+
/* The divider adjacent to a rail/floating-collapsed pane (see split.ts's
|
|
55
|
+
isDividerDisabled()) — geometry (position/inset/inline-size) for the
|
|
56
|
+
collapsing panel itself is set inline by updated(), same as the
|
|
57
|
+
pre-existing flex/order styling; this only covers the divider's own
|
|
58
|
+
drag/hover affordance and the floating panel's elevation, which read
|
|
59
|
+
more naturally as stylesheet rules than one-off inline styles. */
|
|
60
|
+
[part='divider'][aria-disabled='true'] {
|
|
61
|
+
cursor: default;
|
|
62
|
+
pointer-events: none;
|
|
63
|
+
}
|
|
64
|
+
/* The 'floating' collapse state's overlay "card" look -- geometry
|
|
65
|
+
(position/inset-*/inline-size) is set inline by split.ts's updated(),
|
|
66
|
+
matching how the ordinary flex/order styling is applied; only the
|
|
67
|
+
visual/stacking treatment lives here. */
|
|
68
|
+
::slotted([data-collapse-state='floating']) {
|
|
69
|
+
z-index: 1;
|
|
70
|
+
background: var(--lyra-color-surface);
|
|
71
|
+
border-radius: var(--lyra-radius);
|
|
72
|
+
box-shadow: var(--lyra-shadow);
|
|
73
|
+
}
|
|
74
|
+
/* Rail-clamped content can easily overflow the fixed rail-width — clip it
|
|
75
|
+
rather than letting it blow out the layout; the panel's own content is
|
|
76
|
+
expected to adapt to the narrower width itself (e.g. via a container
|
|
77
|
+
query), this is just a safety net. */
|
|
78
|
+
::slotted([data-collapse-state='rail']) {
|
|
79
|
+
overflow: hidden;
|
|
80
|
+
}
|
|
51
81
|
`;
|
|
@@ -5,6 +5,10 @@ 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
|
|
@@ -29,7 +33,8 @@ export interface StatRow {
|
|
|
29
33
|
* @csspart rows - Container for the `rows` breakdown list.
|
|
30
34
|
* @csspart row - A single breakdown row (one per `rows` entry).
|
|
31
35
|
* @csspart row-label - The label text of a breakdown row.
|
|
32
|
-
* @csspart row-value - The value text of a breakdown row.
|
|
36
|
+
* @csspart row-value - The value text of a breakdown row. Shows the row's `exactValue` (if any) as
|
|
37
|
+
* a hover/focus tooltip, same as the headline `value`.
|
|
33
38
|
*/
|
|
34
39
|
export declare class LyraStat extends LyraElement {
|
|
35
40
|
static styles: import("lit").CSSResultGroup[];
|
|
@@ -34,7 +34,8 @@ import { styles } from './stat.styles.js';
|
|
|
34
34
|
* @csspart rows - Container for the `rows` breakdown list.
|
|
35
35
|
* @csspart row - A single breakdown row (one per `rows` entry).
|
|
36
36
|
* @csspart row-label - The label text of a breakdown row.
|
|
37
|
-
* @csspart row-value - The value text of a breakdown row.
|
|
37
|
+
* @csspart row-value - The value text of a breakdown row. Shows the row's `exactValue` (if any) as
|
|
38
|
+
* a hover/focus tooltip, same as the headline `value`.
|
|
38
39
|
*/
|
|
39
40
|
export class LyraStat extends LyraElement {
|
|
40
41
|
constructor() {
|
|
@@ -147,7 +148,12 @@ export class LyraStat extends LyraElement {
|
|
|
147
148
|
${this.rows.map((row) => html `
|
|
148
149
|
<div part="row">
|
|
149
150
|
<span part="row-label">${row.label}</span>
|
|
150
|
-
<span
|
|
151
|
+
<span
|
|
152
|
+
part="row-value"
|
|
153
|
+
title=${row.exactValue || nothing}
|
|
154
|
+
tabindex=${row.exactValue ? '0' : nothing}
|
|
155
|
+
>${row.value}</span
|
|
156
|
+
>
|
|
151
157
|
</div>
|
|
152
158
|
`)}
|
|
153
159
|
</div>
|
|
@@ -0,0 +1,110 @@
|
|
|
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'`) and on every
|
|
22
|
+
* subsequent `recordActivity()` call while already streaming; it's disarmed
|
|
23
|
+
* the instant `phase` becomes anything else, including a host-driven
|
|
24
|
+
* reassignment away from `'streaming'` — so a stale timer can never fire a
|
|
25
|
+
* stall transition after the host has already moved on. If it ever fires,
|
|
26
|
+
* `phase` becomes `'stalled'` and `lyra-stall` is dispatched.
|
|
27
|
+
*
|
|
28
|
+
* `phase` remains a fully public, directly settable property at all times —
|
|
29
|
+
* a host can assign `'stalled'` (or any other phase) itself as a manual
|
|
30
|
+
* override, and this component never fights that assignment. `lyra-stall`/
|
|
31
|
+
* `lyra-recover` fire on *any* transition into/out of `'stalled'`
|
|
32
|
+
* respectively, whether timer-driven or host-driven, and never for a
|
|
33
|
+
* reassignment to the same value (Lit's default `hasChanged` already skips a
|
|
34
|
+
* no-op set, same as every other reflected `@property` in this library).
|
|
35
|
+
* Like `<lyra-chat-message>`'s `status`, whatever phase this element happens
|
|
36
|
+
* to *mount* with is never itself treated as an eventful transition — only a
|
|
37
|
+
* later change fires an event or an announcement.
|
|
38
|
+
*
|
|
39
|
+
* Accessibility: phase transitions into/out of `'stalled'` are announced
|
|
40
|
+
* through an internal `<lyra-live-region>` (see that component for the
|
|
41
|
+
* throttled/coalesced-announcement machinery this composes) rather than a
|
|
42
|
+
* hand-rolled `aria-live` region. `recordActivity()` itself never announces
|
|
43
|
+
* anything, no matter how often the host calls it — only the *transition*
|
|
44
|
+
* announces, exactly once per transition, which is the entire point of
|
|
45
|
+
* routing through the throttled announcer instead of writing to a live
|
|
46
|
+
* region on every call. Entering `'stalled'` announces with `mode="assertive"`
|
|
47
|
+
* (a stall can need the user's attention, e.g. before they give up and
|
|
48
|
+
* navigate away); recovering back out of `'stalled'` announces with
|
|
49
|
+
* `mode="polite"` (good news doesn't need to interrupt). The decorative
|
|
50
|
+
* indicator dot is `aria-hidden` — it's a color/motion cue only, never the
|
|
51
|
+
* sole carrier of state.
|
|
52
|
+
*
|
|
53
|
+
* Visual: `'stalled'` is styled as a warning, not a danger — a stall is
|
|
54
|
+
* usually recoverable (the stream may resume on its own, or the host's own
|
|
55
|
+
* retry logic may kick in), so treating it as an actionable warning rather
|
|
56
|
+
* than a hard failure keeps the tone proportionate. A host that wants to
|
|
57
|
+
* escalate to danger styling after N stalls can scope its own CSS off
|
|
58
|
+
* `[phase="stalled"]`, or simply stop rendering this component and show its
|
|
59
|
+
* own danger-styled error state instead.
|
|
60
|
+
*
|
|
61
|
+
* @customElement lyra-stream-status
|
|
62
|
+
* @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.
|
|
63
|
+
* @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.
|
|
64
|
+
* @event lyra-stall - Fired whenever `phase` transitions into `'stalled'` from anything else (timer-driven, or a direct host assignment).
|
|
65
|
+
* @event lyra-recover - Fired whenever `phase` transitions out of `'stalled'` to anything else (via `recordActivity()`, or a direct host assignment).
|
|
66
|
+
* @csspart base - The root layout container.
|
|
67
|
+
* @csspart indicator - The decorative (`aria-hidden`) status dot.
|
|
68
|
+
* @csspart message - Wrapper around the default slot; only rendered while `phase="stalled"`.
|
|
69
|
+
* @csspart actions - Wrapper around the `actions` slot.
|
|
70
|
+
*/
|
|
71
|
+
export declare class LyraStreamStatus extends LyraElement {
|
|
72
|
+
static styles: import("lit").CSSResultGroup[];
|
|
73
|
+
/** Current connection phase. Settable directly by the host at any time —
|
|
74
|
+
* see the class doc for how that interacts with the internal stall timer. */
|
|
75
|
+
phase: StreamStatusPhase;
|
|
76
|
+
/** How long `phase` may stay `'streaming'` with no `recordActivity()` call
|
|
77
|
+
* before this component declares it stalled. */
|
|
78
|
+
stallThresholdMs: number;
|
|
79
|
+
private stallTimer?;
|
|
80
|
+
private hasActionsSlot;
|
|
81
|
+
private liveRegion?;
|
|
82
|
+
protected willUpdate(): void;
|
|
83
|
+
protected updated(changed: PropertyValues): void;
|
|
84
|
+
disconnectedCallback(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Call on every semantic (non-heartbeat) frame received while streaming.
|
|
87
|
+
* - While `phase === 'streaming'`: (re)arms the stall timer, pushing the
|
|
88
|
+
* stall deadline `stall-threshold-ms` further out.
|
|
89
|
+
* - While `phase === 'stalled'`: recovers — `phase` becomes `'streaming'`
|
|
90
|
+
* again, `lyra-recover` fires, and the stall timer is armed fresh (same
|
|
91
|
+
* as the bullet above), all via the same `updated()` transition handling
|
|
92
|
+
* a direct host assignment would also go through.
|
|
93
|
+
* - While `phase` is `'idle'` or `'connecting'`: a no-op. A host may call
|
|
94
|
+
* this defensively before formally flipping to `'streaming'`; it must
|
|
95
|
+
* never throw or start a timer early.
|
|
96
|
+
*/
|
|
97
|
+
recordActivity(): void;
|
|
98
|
+
private onPhaseChanged;
|
|
99
|
+
private armStallTimer;
|
|
100
|
+
private disarmStallTimer;
|
|
101
|
+
private announceTransition;
|
|
102
|
+
private hasSlotted;
|
|
103
|
+
private onActionsSlotChange;
|
|
104
|
+
render(): TemplateResult;
|
|
105
|
+
}
|
|
106
|
+
declare global {
|
|
107
|
+
interface HTMLElementTagNameMap {
|
|
108
|
+
'lyra-stream-status': LyraStreamStatus;
|
|
109
|
+
}
|
|
110
|
+
}
|