@aceshooting/lyra-ui 1.1.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 +12 -1
- package/custom-elements.json +21460 -8489
- 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 +12 -2
- package/dist/components/chart/chart.js +121 -14
- 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 +63 -0
- package/dist/components/chart/lite-chart.js +181 -23
- 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 +42 -5
- package/dist/components/flag/flag.js +70 -3
- 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 +89 -3
- package/dist/components/heatmap/heatmap.js +158 -29
- 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 +45 -1
- package/dist/components/select/select.js +114 -17
- package/dist/components/select/select.styles.js +26 -2
- 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 +22 -1
- package/dist/components/stat/stat.js +49 -3
- package/dist/components/stat/stat.styles.js +20 -0
- 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/widget/widget.d.ts +10 -0
- package/dist/components/widget/widget.js +24 -1
- package/dist/components/widget/widget.styles.js +9 -2
- 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 +4 -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 +3921 -32
- 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 -12
- package/dist/components/chart/lite-chart.stories.js +0 -98
- 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 -5
- package/dist/components/flag/flag.stories.js +0 -17
- 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 -22
- package/dist/components/heatmap/heatmap.stories.js +0 -154
- 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 -19
- package/dist/components/select/select.stories.js +0 -75
- 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 -8
- package/dist/components/stat/stat.stories.js +0 -64
- 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 -7
- package/dist/components/widget/widget.stories.js +0 -41
- package/dist/components/word-cloud/word-cloud.stories.d.ts +0 -10
- package/dist/components/word-cloud/word-cloud.stories.js +0 -55
|
@@ -0,0 +1,209 @@
|
|
|
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 } from 'lit/decorators.js';
|
|
9
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
+
import { Announcer } from '../../internal/announcer.js';
|
|
12
|
+
import '../markdown/markdown.js';
|
|
13
|
+
import { styles } from './streaming-text.styles.js';
|
|
14
|
+
const DEFAULT_COALESCE_MS = 50;
|
|
15
|
+
/**
|
|
16
|
+
* Lightweight, deliberately-imperfect signals that the currently-displayed
|
|
17
|
+
* text contains Markdown syntax worth routing through `<lyra-markdown>`
|
|
18
|
+
* rather than a plain `white-space: pre-wrap` node. Checked in order against
|
|
19
|
+
* the whole string; the first match short-circuits. None of these need to be
|
|
20
|
+
* airtight -- a false positive just renders ordinary prose through
|
|
21
|
+
* `<lyra-markdown>` (which renders plain prose fine); a false negative just
|
|
22
|
+
* renders literal `**`/backticks/etc. as plain text until more of the stream
|
|
23
|
+
* arrives.
|
|
24
|
+
*/
|
|
25
|
+
const MARKDOWN_PATTERNS = [
|
|
26
|
+
/^ {0,3}#{1,6}\s+\S/m, // ATX heading: "# Heading"
|
|
27
|
+
/```/, // fenced code block
|
|
28
|
+
/\*\*[^*\n]+\*\*/, // **bold**
|
|
29
|
+
/(?:^|[^\w])_[^_\n]+_(?:[^\w]|$)/, // _italic_
|
|
30
|
+
/`[^`\n]+`/, // inline code
|
|
31
|
+
/^ {0,3}[-*+]\s+\S/m, // bullet list item
|
|
32
|
+
/^ {0,3}\d+\.\s+\S/m, // numbered list item
|
|
33
|
+
/\[[^\]]+\]\([^)\s]+\)/, // [text](url)
|
|
34
|
+
/^ {0,3}>\s?\S/m, // blockquote
|
|
35
|
+
];
|
|
36
|
+
/** Runs {@link MARKDOWN_PATTERNS} against `text`, used whenever `markdown`
|
|
37
|
+
* is left unset (auto-detect). Exported so the heuristic is directly
|
|
38
|
+
* testable without going through the component's render cycle. */
|
|
39
|
+
export function looksLikeMarkdown(text) {
|
|
40
|
+
if (!text)
|
|
41
|
+
return false;
|
|
42
|
+
return MARKDOWN_PATTERNS.some((pattern) => pattern.test(text));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Tri-state boolean attribute converter for `markdown`. Lit's built-in
|
|
46
|
+
* `type: Boolean` converter is presence-based and can only ever represent
|
|
47
|
+
* two states (attribute present -> `true`, absent -> `false`) -- there's no
|
|
48
|
+
* way for it to also represent "not specified, auto-detect instead", which
|
|
49
|
+
* is the actual default this property needs. `markdown` (no value, or
|
|
50
|
+
* `="true"`) -> `true`; `markdown="false"` -> `false`; attribute entirely
|
|
51
|
+
* absent -> `undefined`.
|
|
52
|
+
*/
|
|
53
|
+
const optionalBooleanConverter = {
|
|
54
|
+
fromAttribute(value) {
|
|
55
|
+
if (value === null)
|
|
56
|
+
return undefined;
|
|
57
|
+
return value !== 'false';
|
|
58
|
+
},
|
|
59
|
+
toAttribute(value) {
|
|
60
|
+
if (value === undefined)
|
|
61
|
+
return null;
|
|
62
|
+
return value ? '' : 'false';
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* `<lyra-streaming-text>` — a token-coalescing incremental text renderer for
|
|
67
|
+
* streaming assistant output, with an optional blinking cursor and
|
|
68
|
+
* auto-detected Markdown rendering.
|
|
69
|
+
*
|
|
70
|
+
* The host is expected to assign the *entire* current text on every update
|
|
71
|
+
* to `content`, not a delta -- this component does no accumulation or
|
|
72
|
+
* ordering of its own. That matches how most streaming-UI state (SSE/
|
|
73
|
+
* WebSocket token accumulation into a growing string in application state)
|
|
74
|
+
* is already managed.
|
|
75
|
+
*
|
|
76
|
+
* Token-by-token streaming can update `content` far faster than a human can
|
|
77
|
+
* usefully perceive a re-render -- dozens of times a second for a fast
|
|
78
|
+
* model. Re-rendering on every single assignment thrashes layout for no
|
|
79
|
+
* visible benefit, so updates funnel through `Announcer`
|
|
80
|
+
* (`../../internal/announcer.js`), reused here purely as the generic
|
|
81
|
+
* "coalesce rapid calls, flush the latest" timing primitive its own class
|
|
82
|
+
* doc says other components should reuse -- with none of its usual
|
|
83
|
+
* DOM/ARIA plumbing (that's `<lyra-live-region>`'s job, not this
|
|
84
|
+
* component's). Within any `coalesce-ms` window, only the *last* `content`
|
|
85
|
+
* value assigned actually reaches the rendered DOM. Two cases always bypass
|
|
86
|
+
* the throttle and flush immediately instead of waiting out the window: the
|
|
87
|
+
* very first `content` assignment after mount (so an already-complete
|
|
88
|
+
* message never shows an artificial startup delay), and any transition of
|
|
89
|
+
* `streaming` from `true` to `false` (so the final chunk of a finished
|
|
90
|
+
* stream can never be left stranded mid-window).
|
|
91
|
+
*
|
|
92
|
+
* `markdown` is a tri-state property, not a plain boolean: left unset (the
|
|
93
|
+
* default), it auto-detects via a lightweight regex heuristic (see
|
|
94
|
+
* `looksLikeMarkdown`) run against whatever text is currently displayed --
|
|
95
|
+
* good enough to route obviously-Markdown output through `<lyra-markdown>`
|
|
96
|
+
* without the host needing to know or declare it up front, at the cost of
|
|
97
|
+
* an occasional one-time mode flip if Markdown syntax only appears partway
|
|
98
|
+
* through a stream. Explicitly setting `markdown` to `true`/`false` always
|
|
99
|
+
* wins over the heuristic. Rendering itself is never reimplemented here:
|
|
100
|
+
* Markdown mode composes `<lyra-markdown>` (`../markdown/markdown.js`)
|
|
101
|
+
* directly, forwarding this component's own `streaming` through as that
|
|
102
|
+
* component's own forward-compatible `streaming` hint prop; plain-text mode
|
|
103
|
+
* renders into a `white-space: pre-wrap` span instead.
|
|
104
|
+
*
|
|
105
|
+
* The blinking cursor (shown only while `streaming` is `true`) degrades to
|
|
106
|
+
* a static, always-visible bar under `prefers-reduced-motion: reduce`
|
|
107
|
+
* rather than disabling the animation into an invisible frozen frame --
|
|
108
|
+
* the same pattern `<lyra-typing-indicator>`'s own `cursor` variant uses. In
|
|
109
|
+
* plain-text mode the cursor sits inline at the tail of the final
|
|
110
|
+
* character, since the text is one continuous inline flow; in Markdown
|
|
111
|
+
* mode it renders as its own trailing block below the rendered content
|
|
112
|
+
* instead of attempting to splice into whatever nested block Markdown
|
|
113
|
+
* happens to end with (a paragraph, a table cell, a list item, a fenced
|
|
114
|
+
* code block, …) -- genuinely interleaving into arbitrary rendered Markdown
|
|
115
|
+
* without reaching across `<lyra-markdown>`'s own shadow boundary isn't a
|
|
116
|
+
* tractable general solution, so this component doesn't attempt it.
|
|
117
|
+
*
|
|
118
|
+
* Purely presentational: no events, driven entirely by its properties. It
|
|
119
|
+
* also doesn't announce anything to assistive tech itself -- a host that
|
|
120
|
+
* needs streamed text announced already has `<lyra-live-region>` for that
|
|
121
|
+
* (composed, for example, inside `<lyra-chat-message>`).
|
|
122
|
+
*
|
|
123
|
+
* @customElement lyra-streaming-text
|
|
124
|
+
* @csspart base - The root container.
|
|
125
|
+
* @csspart cursor - The blinking (or, under reduced motion, static) cursor bar. Only rendered while `streaming` is `true`.
|
|
126
|
+
*/
|
|
127
|
+
export class LyraStreamingText extends LyraElement {
|
|
128
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
129
|
+
constructor() {
|
|
130
|
+
super();
|
|
131
|
+
/** The full current text so far -- always the complete string, never a
|
|
132
|
+
* delta to append. */
|
|
133
|
+
this.content = '';
|
|
134
|
+
/** Shows the blinking cursor after the rendered text. Reflects, so a host
|
|
135
|
+
* can also target `lyra-streaming-text[streaming]` in CSS. */
|
|
136
|
+
this.streaming = false;
|
|
137
|
+
/** Trailing-edge coalesce window, in ms, for `content` updates -- see the
|
|
138
|
+
* class doc. */
|
|
139
|
+
this.coalesceMs = DEFAULT_COALESCE_MS;
|
|
140
|
+
// The coalesced value actually rendered -- lags `content` by up to
|
|
141
|
+
// `coalesceMs` (or zero, for the immediate-flush cases documented above).
|
|
142
|
+
this.displayedContent = '';
|
|
143
|
+
// Built in the constructor (not a class-field initializer) so it reads
|
|
144
|
+
// `this.coalesceMs` only after that property's own field initializer has
|
|
145
|
+
// already run and set the declared default -- same ordering rationale as
|
|
146
|
+
// lyra-live-region's identical constructor-built Announcer.
|
|
147
|
+
this.coalescer = new Announcer({
|
|
148
|
+
throttleMs: this.coalesceMs,
|
|
149
|
+
onFlush: (text) => {
|
|
150
|
+
this.displayedContent = text;
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
willUpdate(changed) {
|
|
155
|
+
if (changed.has('coalesceMs')) {
|
|
156
|
+
this.coalescer.throttleMs = this.coalesceMs;
|
|
157
|
+
}
|
|
158
|
+
if (changed.has('content')) {
|
|
159
|
+
// The very first content assignment after mount always flushes
|
|
160
|
+
// immediately -- an already-complete message (or the first chunk of a
|
|
161
|
+
// new one) shouldn't show an artificial startup delay just because a
|
|
162
|
+
// coalescing window technically applies to it.
|
|
163
|
+
this.coalescer.announce(this.content, { force: !this.hasUpdated });
|
|
164
|
+
}
|
|
165
|
+
// A stream finishing must never leave its final chunk stranded inside an
|
|
166
|
+
// in-progress coalescing window -- force whatever `content` currently
|
|
167
|
+
// holds through immediately. `changed.get('streaming')` is only defined
|
|
168
|
+
// for a real transition (never the initial mount value, per Lit's
|
|
169
|
+
// documented first-change semantics), so this can't misfire on connect.
|
|
170
|
+
if (changed.has('streaming') && changed.get('streaming') === true && !this.streaming) {
|
|
171
|
+
this.coalescer.announce(this.content, { force: true });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
disconnectedCallback() {
|
|
175
|
+
super.disconnectedCallback();
|
|
176
|
+
this.coalescer.cancel();
|
|
177
|
+
}
|
|
178
|
+
/** Whether Markdown mode is actually in effect right now, resolving the
|
|
179
|
+
* tri-state `markdown` property against `looksLikeMarkdown`. */
|
|
180
|
+
get effectiveMarkdown() {
|
|
181
|
+
return this.markdown ?? looksLikeMarkdown(this.displayedContent);
|
|
182
|
+
}
|
|
183
|
+
render() {
|
|
184
|
+
return html `
|
|
185
|
+
<div part="base">
|
|
186
|
+
${this.effectiveMarkdown
|
|
187
|
+
? html `<lyra-markdown .content=${this.displayedContent} .streaming=${this.streaming}></lyra-markdown>`
|
|
188
|
+
: html `<span class="plain">${this.displayedContent}</span>`}
|
|
189
|
+
${this.streaming ? html `<span part="cursor" aria-hidden="true"></span>` : nothing}
|
|
190
|
+
</div>
|
|
191
|
+
`;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
__decorate([
|
|
195
|
+
property()
|
|
196
|
+
], LyraStreamingText.prototype, "content", void 0);
|
|
197
|
+
__decorate([
|
|
198
|
+
property({ type: Boolean, reflect: true })
|
|
199
|
+
], LyraStreamingText.prototype, "streaming", void 0);
|
|
200
|
+
__decorate([
|
|
201
|
+
property({ type: Number, attribute: 'coalesce-ms' })
|
|
202
|
+
], LyraStreamingText.prototype, "coalesceMs", void 0);
|
|
203
|
+
__decorate([
|
|
204
|
+
property({ attribute: 'markdown', converter: optionalBooleanConverter })
|
|
205
|
+
], LyraStreamingText.prototype, "markdown", void 0);
|
|
206
|
+
__decorate([
|
|
207
|
+
state()
|
|
208
|
+
], LyraStreamingText.prototype, "displayedContent", void 0);
|
|
209
|
+
defineElement('streaming-text', LyraStreamingText);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
overflow-wrap: break-word;
|
|
6
|
+
/* Not derived from any --lyra-* token in tokens.styles.ts -- there's no
|
|
7
|
+
shared "inline cursor bar" token to resolve through, so this component
|
|
8
|
+
defines its own scoped custom property, exactly the way
|
|
9
|
+
lyra-typing-indicator's --lyra-typing-cursor-width/-height do for its
|
|
10
|
+
own (near-identical) blinking cursor. */
|
|
11
|
+
--lyra-streaming-text-cursor-width: 0.125rem;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
[part='base'] {
|
|
15
|
+
line-height: 1.6;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Plain-text path only (Markdown mode never renders this element) -- see
|
|
19
|
+
the class doc for why Markdown content can't share this same
|
|
20
|
+
white-space treatment. */
|
|
21
|
+
.plain {
|
|
22
|
+
white-space: pre-wrap;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* inline-block (not inline) so it participates in text layout on the same
|
|
26
|
+
line as the preceding content while still accepting a fixed block-size
|
|
27
|
+
for the bar -- in plain-text mode this sits at the visual tail of the
|
|
28
|
+
final wrapped line, immediately after the last character. */
|
|
29
|
+
[part='cursor'] {
|
|
30
|
+
display: inline-block;
|
|
31
|
+
vertical-align: text-bottom;
|
|
32
|
+
inline-size: var(--lyra-streaming-text-cursor-width);
|
|
33
|
+
block-size: 1em;
|
|
34
|
+
margin-inline-start: var(--lyra-space-xs);
|
|
35
|
+
background: currentColor;
|
|
36
|
+
border-radius: var(--lyra-streaming-text-cursor-width);
|
|
37
|
+
animation: lyra-streaming-text-cursor-blink var(--lyra-transition-base) infinite;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Two adjacent keyframe stops (49% / 50%) either side of an instant flip,
|
|
41
|
+
same shape as lyra-typing-indicator's cursor variant, so the blink still
|
|
42
|
+
reads as a sharp on/off even under the token's own ease-out timing. */
|
|
43
|
+
@keyframes lyra-streaming-text-cursor-blink {
|
|
44
|
+
0%,
|
|
45
|
+
49% {
|
|
46
|
+
opacity: 1;
|
|
47
|
+
}
|
|
48
|
+
50%,
|
|
49
|
+
100% {
|
|
50
|
+
opacity: 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Degrades to a static, fully-visible bar -- never a frozen mid-blink
|
|
55
|
+
(invisible) frame. */
|
|
56
|
+
@media (prefers-reduced-motion: reduce) {
|
|
57
|
+
[part='cursor'] {
|
|
58
|
+
animation: none !important;
|
|
59
|
+
opacity: 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
/**
|
|
4
|
+
* `<lyra-switch>` — a boolean toggle-switch form control. Structurally the
|
|
5
|
+
* same idea as a checkbox (form-associated via `ElementInternals`, click and
|
|
6
|
+
* Space/Enter both toggle) but with switch semantics: `role="switch"` +
|
|
7
|
+
* `aria-checked` read to assistive tech as an on/off state rather than a
|
|
8
|
+
* checked/unchecked one, and there is no indeterminate state.
|
|
9
|
+
*
|
|
10
|
+
* `checked` is not a plain string, so this attaches `ElementInternals`
|
|
11
|
+
* directly and implements its own `updateValidity()` rather than using the
|
|
12
|
+
* `FormAssociated` mixin (that mixin's `value` accessor assumes a string —
|
|
13
|
+
* see `<lyra-combobox>` for the same direct-`ElementInternals` shape with a
|
|
14
|
+
* non-string value).
|
|
15
|
+
*
|
|
16
|
+
* @customElement lyra-switch
|
|
17
|
+
* @slot - Label text, rendered next to the track. Clicking it toggles the
|
|
18
|
+
* switch, the same as clicking a checkbox's associated `<label>`. If left
|
|
19
|
+
* empty, set `aria-label` on the host so the control still has an
|
|
20
|
+
* accessible name.
|
|
21
|
+
* @event lyra-change - The user toggled the switch (click or Space/Enter). `detail: { checked }`.
|
|
22
|
+
* @csspart base - The whole interactive control (`role="switch"`); wraps the track and label.
|
|
23
|
+
* @csspart track - The pill-shaped background.
|
|
24
|
+
* @csspart thumb - The circular knob that slides across the track.
|
|
25
|
+
* @csspart label - The wrapper around the default slot.
|
|
26
|
+
*/
|
|
27
|
+
export declare class LyraSwitch extends LyraElement {
|
|
28
|
+
static styles: import("lit").CSSResultGroup[];
|
|
29
|
+
static formAssociated: boolean;
|
|
30
|
+
checked: boolean;
|
|
31
|
+
disabled: boolean;
|
|
32
|
+
required: boolean;
|
|
33
|
+
name: string;
|
|
34
|
+
value: string;
|
|
35
|
+
private hasLabelSlot;
|
|
36
|
+
private internals;
|
|
37
|
+
private _defaultChecked;
|
|
38
|
+
private _defaultCaptured;
|
|
39
|
+
constructor();
|
|
40
|
+
connectedCallback(): void;
|
|
41
|
+
protected willUpdate(): void;
|
|
42
|
+
private updateValidity;
|
|
43
|
+
protected updated(changed: PropertyValues): void;
|
|
44
|
+
formResetCallback(): void;
|
|
45
|
+
formDisabledCallback(disabled: boolean): void;
|
|
46
|
+
checkValidity(): boolean;
|
|
47
|
+
reportValidity(): boolean;
|
|
48
|
+
private toggle;
|
|
49
|
+
private onClick;
|
|
50
|
+
private onKeyDown;
|
|
51
|
+
private onSlotChange;
|
|
52
|
+
render(): TemplateResult;
|
|
53
|
+
}
|
|
54
|
+
declare global {
|
|
55
|
+
interface HTMLElementTagNameMap {
|
|
56
|
+
'lyra-switch': LyraSwitch;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
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 } from 'lit/decorators.js';
|
|
9
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
+
import { styles } from './switch.styles.js';
|
|
12
|
+
/**
|
|
13
|
+
* `<lyra-switch>` — a boolean toggle-switch form control. Structurally the
|
|
14
|
+
* same idea as a checkbox (form-associated via `ElementInternals`, click and
|
|
15
|
+
* Space/Enter both toggle) but with switch semantics: `role="switch"` +
|
|
16
|
+
* `aria-checked` read to assistive tech as an on/off state rather than a
|
|
17
|
+
* checked/unchecked one, and there is no indeterminate state.
|
|
18
|
+
*
|
|
19
|
+
* `checked` is not a plain string, so this attaches `ElementInternals`
|
|
20
|
+
* directly and implements its own `updateValidity()` rather than using the
|
|
21
|
+
* `FormAssociated` mixin (that mixin's `value` accessor assumes a string —
|
|
22
|
+
* see `<lyra-combobox>` for the same direct-`ElementInternals` shape with a
|
|
23
|
+
* non-string value).
|
|
24
|
+
*
|
|
25
|
+
* @customElement lyra-switch
|
|
26
|
+
* @slot - Label text, rendered next to the track. Clicking it toggles the
|
|
27
|
+
* switch, the same as clicking a checkbox's associated `<label>`. If left
|
|
28
|
+
* empty, set `aria-label` on the host so the control still has an
|
|
29
|
+
* accessible name.
|
|
30
|
+
* @event lyra-change - The user toggled the switch (click or Space/Enter). `detail: { checked }`.
|
|
31
|
+
* @csspart base - The whole interactive control (`role="switch"`); wraps the track and label.
|
|
32
|
+
* @csspart track - The pill-shaped background.
|
|
33
|
+
* @csspart thumb - The circular knob that slides across the track.
|
|
34
|
+
* @csspart label - The wrapper around the default slot.
|
|
35
|
+
*/
|
|
36
|
+
export class LyraSwitch extends LyraElement {
|
|
37
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
38
|
+
static { this.formAssociated = true; }
|
|
39
|
+
constructor() {
|
|
40
|
+
super();
|
|
41
|
+
this.checked = false;
|
|
42
|
+
this.disabled = false;
|
|
43
|
+
this.required = false;
|
|
44
|
+
this.name = '';
|
|
45
|
+
this.value = 'on';
|
|
46
|
+
// Tracks whether the default slot carries any real (non-whitespace)
|
|
47
|
+
// content, so the label wrapper — and the `gap` next to the track — can
|
|
48
|
+
// collapse to nothing for an icon-only/aria-label-only switch instead of
|
|
49
|
+
// leaving a stray empty gap. See combobox/date-input's `hasHintSlot`-style
|
|
50
|
+
// state fields; this one checks `assignedNodes` rather than
|
|
51
|
+
// `assignedElements` because a plain slotted text label (the expected
|
|
52
|
+
// common case here, e.g. `<lyra-switch>Enable notifications</lyra-switch>`)
|
|
53
|
+
// is a text node, which `assignedElements` would silently ignore.
|
|
54
|
+
this.hasLabelSlot = false;
|
|
55
|
+
// What `form.reset()` restores to — captured once, from whatever the
|
|
56
|
+
// `checked` property reads at first connect (i.e. whatever the declarative
|
|
57
|
+
// `checked` attribute parsed to, since attribute parsing happens before
|
|
58
|
+
// `connectedCallback`). `checked` reflects, so unlike
|
|
59
|
+
// `FormAssociated`'s non-reflecting `value` this can't be captured from
|
|
60
|
+
// `attributeChangedCallback` alone — that would also fire (and wrongly
|
|
61
|
+
// redefine the default) every time the property setter itself reflects a
|
|
62
|
+
// later user toggle back into the attribute. Guarding with a one-shot flag
|
|
63
|
+
// instead mirrors `<lyra-combobox>`'s `_defaultCaptured`/`_defaultSelected`.
|
|
64
|
+
this._defaultChecked = false;
|
|
65
|
+
this._defaultCaptured = false;
|
|
66
|
+
this.onClick = () => {
|
|
67
|
+
this.toggle();
|
|
68
|
+
};
|
|
69
|
+
this.onKeyDown = (e) => {
|
|
70
|
+
if (this.disabled)
|
|
71
|
+
return;
|
|
72
|
+
// Space/Enter both activate, matching `<lyra-table>`'s sortable
|
|
73
|
+
// header/row convention (`table.ts`'s `onHeaderKeyDown`/`onRowKeyDown`)
|
|
74
|
+
// for role-based clickable elements — bound to `keydown` rather than
|
|
75
|
+
// `keyup`/native `click`-forwarding like the rest of this library.
|
|
76
|
+
if (e.key === ' ' || e.key === 'Spacebar' || e.key === 'Enter') {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
this.toggle();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
this.onSlotChange = (e) => {
|
|
82
|
+
const nodes = e.target.assignedNodes({ flatten: true });
|
|
83
|
+
this.hasLabelSlot = nodes.some((n) => (n.textContent ?? '').trim().length > 0);
|
|
84
|
+
};
|
|
85
|
+
this.internals = this.attachInternals();
|
|
86
|
+
}
|
|
87
|
+
connectedCallback() {
|
|
88
|
+
super.connectedCallback();
|
|
89
|
+
if (!this._defaultCaptured) {
|
|
90
|
+
this._defaultCaptured = true;
|
|
91
|
+
this._defaultChecked = this.checked;
|
|
92
|
+
}
|
|
93
|
+
this.updateValidity();
|
|
94
|
+
}
|
|
95
|
+
willUpdate() {
|
|
96
|
+
// Seed `hasLabelSlot` from the light-DOM children synchronously before
|
|
97
|
+
// the very first render (same `!hasUpdated` guard as combobox/date-input's
|
|
98
|
+
// `hasHintSlot` etc.) so declaratively-provided label text doesn't flash
|
|
99
|
+
// hidden for one frame while waiting on the first `slotchange` event.
|
|
100
|
+
if (!this.hasUpdated) {
|
|
101
|
+
this.hasLabelSlot = Array.from(this.childNodes).some((n) => (n.textContent ?? '').trim().length > 0);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
updateValidity() {
|
|
105
|
+
if (this.required && !this.checked) {
|
|
106
|
+
this.internals.setValidity({ valueMissing: true }, 'Please turn this on.');
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
this.internals.setValidity({});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
updated(changed) {
|
|
113
|
+
if (changed.has('checked') || changed.has('value')) {
|
|
114
|
+
this.internals.setFormValue(this.checked ? this.value : null);
|
|
115
|
+
}
|
|
116
|
+
if (changed.has('checked') || changed.has('required')) {
|
|
117
|
+
this.updateValidity();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
formResetCallback() {
|
|
121
|
+
this.checked = this._defaultChecked;
|
|
122
|
+
}
|
|
123
|
+
formDisabledCallback(disabled) {
|
|
124
|
+
this.disabled = disabled;
|
|
125
|
+
}
|
|
126
|
+
checkValidity() {
|
|
127
|
+
return this.internals.checkValidity();
|
|
128
|
+
}
|
|
129
|
+
reportValidity() {
|
|
130
|
+
return this.internals.reportValidity();
|
|
131
|
+
}
|
|
132
|
+
toggle() {
|
|
133
|
+
if (this.disabled)
|
|
134
|
+
return;
|
|
135
|
+
this.checked = !this.checked;
|
|
136
|
+
this.emit('lyra-change', { checked: this.checked });
|
|
137
|
+
}
|
|
138
|
+
render() {
|
|
139
|
+
return html `
|
|
140
|
+
<span
|
|
141
|
+
part="base"
|
|
142
|
+
role="switch"
|
|
143
|
+
tabindex=${this.disabled ? '-1' : '0'}
|
|
144
|
+
aria-checked=${this.checked ? 'true' : 'false'}
|
|
145
|
+
aria-required=${this.required ? 'true' : nothing}
|
|
146
|
+
aria-disabled=${this.disabled ? 'true' : nothing}
|
|
147
|
+
aria-label=${this.getAttribute('aria-label') || nothing}
|
|
148
|
+
@click=${this.onClick}
|
|
149
|
+
@keydown=${this.onKeyDown}
|
|
150
|
+
>
|
|
151
|
+
<span part="track">
|
|
152
|
+
<span part="thumb"></span>
|
|
153
|
+
</span>
|
|
154
|
+
<span part="label" ?hidden=${!this.hasLabelSlot}>
|
|
155
|
+
<slot @slotchange=${this.onSlotChange}></slot>
|
|
156
|
+
</span>
|
|
157
|
+
</span>
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
__decorate([
|
|
162
|
+
property({ type: Boolean, reflect: true })
|
|
163
|
+
], LyraSwitch.prototype, "checked", void 0);
|
|
164
|
+
__decorate([
|
|
165
|
+
property({ type: Boolean, reflect: true })
|
|
166
|
+
], LyraSwitch.prototype, "disabled", void 0);
|
|
167
|
+
__decorate([
|
|
168
|
+
property({ type: Boolean, reflect: true })
|
|
169
|
+
], LyraSwitch.prototype, "required", void 0);
|
|
170
|
+
__decorate([
|
|
171
|
+
property()
|
|
172
|
+
], LyraSwitch.prototype, "name", void 0);
|
|
173
|
+
__decorate([
|
|
174
|
+
property()
|
|
175
|
+
], LyraSwitch.prototype, "value", void 0);
|
|
176
|
+
__decorate([
|
|
177
|
+
state()
|
|
178
|
+
], LyraSwitch.prototype, "hasLabelSlot", void 0);
|
|
179
|
+
defineElement('switch', LyraSwitch);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: inline-block;
|
|
5
|
+
/* Component-local geometry knobs (same "define your own on :host"
|
|
6
|
+
pattern as lyra-toast's --gap/--width) — a fully-rounded pill/thumb
|
|
7
|
+
needs a radius well past --lyra-radius's small 0.375rem default, so
|
|
8
|
+
it's expressed here rather than bent onto that shared token. */
|
|
9
|
+
--track-inline-size: 2.25rem;
|
|
10
|
+
--track-block-size: 1.25rem;
|
|
11
|
+
--thumb-offset: 2px;
|
|
12
|
+
}
|
|
13
|
+
[part='base'] {
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: var(--lyra-space-s);
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
-webkit-tap-highlight-color: transparent;
|
|
19
|
+
}
|
|
20
|
+
[part='base']:focus-visible {
|
|
21
|
+
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
22
|
+
outline-offset: var(--lyra-focus-ring-offset);
|
|
23
|
+
}
|
|
24
|
+
:host([disabled]) [part='base'] {
|
|
25
|
+
cursor: not-allowed;
|
|
26
|
+
opacity: var(--lyra-opacity-disabled);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
[part='track'] {
|
|
30
|
+
position: relative;
|
|
31
|
+
flex: 0 0 auto;
|
|
32
|
+
inline-size: var(--track-inline-size);
|
|
33
|
+
block-size: var(--track-block-size);
|
|
34
|
+
border-radius: 999px;
|
|
35
|
+
background: var(--lyra-color-border);
|
|
36
|
+
transition: background-color var(--lyra-transition-fast);
|
|
37
|
+
}
|
|
38
|
+
:host([checked]) [part='track'] {
|
|
39
|
+
background: var(--lyra-color-brand);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[part='thumb'] {
|
|
43
|
+
position: absolute;
|
|
44
|
+
inset-block-start: var(--thumb-offset);
|
|
45
|
+
inset-inline-start: var(--thumb-offset);
|
|
46
|
+
inline-size: calc(var(--track-block-size) - (var(--thumb-offset) * 2));
|
|
47
|
+
block-size: calc(var(--track-block-size) - (var(--thumb-offset) * 2));
|
|
48
|
+
border-radius: 50%;
|
|
49
|
+
background: var(--lyra-color-surface);
|
|
50
|
+
/* Animates the logical 'inset-inline-start' rather than a physical
|
|
51
|
+
'transform: translateX()' so the slide direction mirrors correctly
|
|
52
|
+
under dir="rtl" — consistent with this library's CSS-logical-
|
|
53
|
+
properties approach to RTL (see internal/lyra-element.ts). */
|
|
54
|
+
transition: inset-inline-start var(--lyra-transition-fast);
|
|
55
|
+
}
|
|
56
|
+
:host([checked]) [part='thumb'] {
|
|
57
|
+
inset-inline-start: calc(var(--track-inline-size) - var(--track-block-size) + var(--thumb-offset));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* No explicit "display" here (unlike e.g. lyra-combobox's
|
|
61
|
+
[part='form-control-label']), so the UA stylesheet's default
|
|
62
|
+
"[hidden] { display: none }" rule needs no author-side override to
|
|
63
|
+
take effect when hasLabelSlot is false. */
|
|
64
|
+
[part='label'] {
|
|
65
|
+
font-size: 0.875rem;
|
|
66
|
+
color: var(--lyra-color-text);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@media (prefers-reduced-motion: reduce) {
|
|
70
|
+
[part='track'],
|
|
71
|
+
[part='thumb'] {
|
|
72
|
+
transition: none !important;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
`;
|