@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
|
@@ -0,0 +1,352 @@
|
|
|
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 } from 'lit/decorators.js';
|
|
9
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { FormAssociated } from '../../internal/form-associated.js';
|
|
11
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
12
|
+
import { isRtl } from '../../internal/rtl.js';
|
|
13
|
+
import { styles } from './slider.styles.js';
|
|
14
|
+
/** PageUp/PageDown move by a larger increment than a single Arrow step,
|
|
15
|
+
* matching the WAI-ARIA APG slider pattern's expected keyboard interactions
|
|
16
|
+
* (and native `<input type=range>`). Mirrors lyra-time-range's identical
|
|
17
|
+
* constant. */
|
|
18
|
+
const PAGE_STEP_MULTIPLIER = 10;
|
|
19
|
+
function isArrowKey(key) {
|
|
20
|
+
return key === 'ArrowRight' || key === 'ArrowUp' || key === 'ArrowLeft' || key === 'ArrowDown';
|
|
21
|
+
}
|
|
22
|
+
/** Keys that onKeyDown acts on and onKeyUp commits after. */
|
|
23
|
+
function isSliderKey(key) {
|
|
24
|
+
return isArrowKey(key) || key === 'Home' || key === 'End' || key === 'PageUp' || key === 'PageDown';
|
|
25
|
+
}
|
|
26
|
+
/** Number of decimal digits in `n`'s shortest string representation, e.g.
|
|
27
|
+
* `0.1` -> 1, `5` -> 0. Used to round a stepped value back to the precision
|
|
28
|
+
* `step` itself implies, instead of leaving binary floating-point noise in
|
|
29
|
+
* place (e.g. `20.200000000000003`). Mirrors lyra-time-range's identical
|
|
30
|
+
* helper. */
|
|
31
|
+
function decimalPlaces(n) {
|
|
32
|
+
const str = n.toString();
|
|
33
|
+
const dot = str.indexOf('.');
|
|
34
|
+
return dot === -1 ? 0 : str.length - dot - 1;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* `<lyra-slider>` — a numeric range control (e.g. an LLM "temperature"
|
|
38
|
+
* setting), form-associated. Mirrors native `<input type="range">`
|
|
39
|
+
* semantics: `value` is the string form-submitted via `FormAssociated`,
|
|
40
|
+
* `valueAsNumber` is the ergonomic numeric accessor (mirroring the native
|
|
41
|
+
* `<input type=range>` IDL attribute of the same name) kept in sync with it
|
|
42
|
+
* in both directions — reads parse `value`, writes stringify back to it.
|
|
43
|
+
*
|
|
44
|
+
* Unlike the mixin's other consumers, an unset `value` is eagerly defaulted
|
|
45
|
+
* — on connect, and again after `form.reset()` — to the midpoint of
|
|
46
|
+
* `[min, max]` snapped to `step`, the same "range sanitization algorithm"
|
|
47
|
+
* default a native range input applies. A slider always represents *some*
|
|
48
|
+
* number, so `required` (inherited from `FormAssociated`) only has a window
|
|
49
|
+
* to block submission before that default lands, matching how `required`
|
|
50
|
+
* isn't a meaningful constraint on a native range input either.
|
|
51
|
+
*
|
|
52
|
+
* @customElement lyra-slider
|
|
53
|
+
* @event lyra-input - Fired continuously during an active drag or a
|
|
54
|
+
* keyboard step (including OS key-repeat while a key is held), mirroring
|
|
55
|
+
* native `<input type=range>`'s own `input` event. `detail: { value: number }`.
|
|
56
|
+
* @event lyra-change - Fired once an interaction commits: on pointerup for a
|
|
57
|
+
* drag, or on keyup for a keyboard step — so a single Arrow/Home/End/
|
|
58
|
+
* PageUp/PageDown press fires both `lyra-input` and `lyra-change`,
|
|
59
|
+
* mirroring how native `<input type=range>` fires `change` on every
|
|
60
|
+
* committed step too. `detail: { value: number }`.
|
|
61
|
+
* @csspart base - The row wrapping the track and the optional value readout.
|
|
62
|
+
* @csspart track - The full-width background line.
|
|
63
|
+
* @csspart fill - The filled portion of the track from `min` up to the current value.
|
|
64
|
+
* @csspart thumb - The draggable handle (`role="slider"`).
|
|
65
|
+
* @csspart value - The visible numeric readout, rendered when `show-value` is true.
|
|
66
|
+
*/
|
|
67
|
+
export class LyraSlider extends FormAssociated(LyraElement) {
|
|
68
|
+
constructor() {
|
|
69
|
+
super(...arguments);
|
|
70
|
+
this.min = 0;
|
|
71
|
+
this.max = 100;
|
|
72
|
+
this.step = 1;
|
|
73
|
+
/** Accessible name for the slider, used when no visible label context
|
|
74
|
+
* exists around it (e.g. no wrapping `<label>` or adjacent heading). Set
|
|
75
|
+
* as `aria-label` on the interactive `role="slider"` element. A plain
|
|
76
|
+
* `aria-label` attribute on the host itself is honored as a fallback when
|
|
77
|
+
* this is left unset, matching `<lyra-checkbox>`/`<lyra-switch>`. */
|
|
78
|
+
this.label = '';
|
|
79
|
+
/** Whether to render the current numeric value as visible text next to
|
|
80
|
+
* the track. Like `<lyra-markdown>`'s `sanitize`/`gfm`, this is a plain
|
|
81
|
+
* `type: Boolean` property defaulting `true` — turn it off via the
|
|
82
|
+
* `.showValue=${false}` property binding (a bare `show-value="false"`
|
|
83
|
+
* content attribute is still truthy, since presence is all Lit's default
|
|
84
|
+
* boolean converter checks). */
|
|
85
|
+
this.showValue = true;
|
|
86
|
+
// Keyed by pointerId (a Set, not a single scalar) purely for
|
|
87
|
+
// multi-touch/robustness parity with lyra-split and lyra-time-range, even
|
|
88
|
+
// though a single thumb has no per-pointer state of its own to track.
|
|
89
|
+
this.activePointers = new Set();
|
|
90
|
+
this.onKeyDown = (e) => {
|
|
91
|
+
if (this.effectiveDisabled)
|
|
92
|
+
return;
|
|
93
|
+
const current = this.valueAsNumber;
|
|
94
|
+
// Under RTL, physical ArrowRight moves toward inset-inline-start, i.e. a
|
|
95
|
+
// lower value — swap which physical key counts as "forward", matching
|
|
96
|
+
// lyra-split/lyra-time-range's onKeyDown/onPointerMove convention.
|
|
97
|
+
// ArrowUp/ArrowDown are never swapped (direction only affects the
|
|
98
|
+
// horizontal inline axis).
|
|
99
|
+
const rtl = isRtl(this);
|
|
100
|
+
const forwardKey = rtl ? 'ArrowLeft' : 'ArrowRight';
|
|
101
|
+
const backwardKey = rtl ? 'ArrowRight' : 'ArrowLeft';
|
|
102
|
+
if (e.key === forwardKey || e.key === 'ArrowUp') {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
this.setValue(current + this.step, false);
|
|
105
|
+
}
|
|
106
|
+
else if (e.key === backwardKey || e.key === 'ArrowDown') {
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
this.setValue(current - this.step, false);
|
|
109
|
+
}
|
|
110
|
+
else if (e.key === 'PageUp') {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
this.setValue(current + this.step * PAGE_STEP_MULTIPLIER, false);
|
|
113
|
+
}
|
|
114
|
+
else if (e.key === 'PageDown') {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
this.setValue(current - this.step * PAGE_STEP_MULTIPLIER, false);
|
|
117
|
+
}
|
|
118
|
+
else if (e.key === 'Home') {
|
|
119
|
+
e.preventDefault();
|
|
120
|
+
this.setValue(this.domain().lo, false);
|
|
121
|
+
}
|
|
122
|
+
else if (e.key === 'End') {
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
this.setValue(this.domain().hi, false);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
this.onKeyUp = (e) => {
|
|
128
|
+
// Only commit on release of the keys onKeyDown acts on — releasing an
|
|
129
|
+
// unrelated key (Tab, Shift, ...) while the thumb happens to be focused
|
|
130
|
+
// must not emit a spurious lyra-change. For a single discrete press this
|
|
131
|
+
// pairs one onKeyDown (lyra-input) with one onKeyUp (lyra-change); OS
|
|
132
|
+
// key-repeat while a key is held re-fires onKeyDown (and thus
|
|
133
|
+
// lyra-input) repeatedly but still commits only once, on the eventual
|
|
134
|
+
// keyup — the same drag-like "continuous input, single final change"
|
|
135
|
+
// shape a pointer drag has.
|
|
136
|
+
if (this.effectiveDisabled || !isSliderKey(e.key))
|
|
137
|
+
return;
|
|
138
|
+
this.emit('lyra-change', { value: this.valueAsNumber });
|
|
139
|
+
};
|
|
140
|
+
this.onPointerDown = (e) => {
|
|
141
|
+
if (this.effectiveDisabled)
|
|
142
|
+
return;
|
|
143
|
+
this.activePointers.add(e.pointerId);
|
|
144
|
+
e.target.setPointerCapture(e.pointerId);
|
|
145
|
+
window.addEventListener('pointermove', this.onPointerMove);
|
|
146
|
+
window.addEventListener('pointerup', this.onPointerUp);
|
|
147
|
+
// A drag can end without a pointerup: a system gesture / palm rejection
|
|
148
|
+
// can fire `pointercancel`, and losing capture (e.g. element removed)
|
|
149
|
+
// fires `lostpointercapture` — both need the same teardown as pointerup.
|
|
150
|
+
window.addEventListener('pointercancel', this.onPointerUp);
|
|
151
|
+
window.addEventListener('lostpointercapture', this.onPointerUp);
|
|
152
|
+
};
|
|
153
|
+
this.onPointerMove = (e) => {
|
|
154
|
+
if (!this.activePointers.has(e.pointerId))
|
|
155
|
+
return;
|
|
156
|
+
if (this.effectiveDisabled) {
|
|
157
|
+
// These are window-level listeners driven by setPointerCapture, so
|
|
158
|
+
// they keep firing for this pointerId regardless of the `disabled`
|
|
159
|
+
// reflection — a drag already in progress would otherwise keep
|
|
160
|
+
// mutating `value` (and emitting lyra-input) after `disabled` flips
|
|
161
|
+
// true mid-drag. Abort the drag instead of continuing to process it.
|
|
162
|
+
this.endDrag(e.pointerId, false);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const track = this.renderRoot.querySelector('[part="track"]');
|
|
166
|
+
if (!track)
|
|
167
|
+
return;
|
|
168
|
+
const rect = track.getBoundingClientRect();
|
|
169
|
+
const raw = rect.width === 0 ? 0 : (e.clientX - rect.left) / rect.width;
|
|
170
|
+
// The track is positioned with inset-inline-start (0% at the visual
|
|
171
|
+
// right edge under RTL), so the pointer ratio has to mirror that or a
|
|
172
|
+
// rightward drag would move the thumb the wrong way.
|
|
173
|
+
const ratio = Math.min(1, Math.max(0, isRtl(this) ? 1 - raw : raw));
|
|
174
|
+
const { lo, hi } = this.domain();
|
|
175
|
+
this.setValue(lo + ratio * (hi - lo), false);
|
|
176
|
+
};
|
|
177
|
+
this.onPointerUp = (e) => {
|
|
178
|
+
this.endDrag(e.pointerId, true);
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
182
|
+
connectedCallback() {
|
|
183
|
+
super.connectedCallback();
|
|
184
|
+
this.ensureValue();
|
|
185
|
+
}
|
|
186
|
+
disconnectedCallback() {
|
|
187
|
+
super.disconnectedCallback();
|
|
188
|
+
// Mirror lyra-split/lyra-time-range's cleanup: if the element is removed
|
|
189
|
+
// mid-drag (or a pointercancel/alt-tab means pointerup never reaches
|
|
190
|
+
// `window`), these window-level listeners would otherwise leak.
|
|
191
|
+
this.activePointers.clear();
|
|
192
|
+
window.removeEventListener('pointermove', this.onPointerMove);
|
|
193
|
+
window.removeEventListener('pointerup', this.onPointerUp);
|
|
194
|
+
window.removeEventListener('pointercancel', this.onPointerUp);
|
|
195
|
+
window.removeEventListener('lostpointercapture', this.onPointerUp);
|
|
196
|
+
}
|
|
197
|
+
/** The numeric counterpart of `value`, mirroring native `<input
|
|
198
|
+
* type=range>.valueAsNumber`. Reading always returns a finite, clamped,
|
|
199
|
+
* step-snapped number — even if `value` is momentarily `""` (e.g. right
|
|
200
|
+
* after `form.reset()` restores an undeclared default) — by falling back
|
|
201
|
+
* to the midpoint of `[min, max]`. Writing stringifies the clamped result
|
|
202
|
+
* back into `value`. */
|
|
203
|
+
get valueAsNumber() {
|
|
204
|
+
if (this.value === '')
|
|
205
|
+
return this.defaultNumericValue();
|
|
206
|
+
const n = Number(this.value);
|
|
207
|
+
return Number.isFinite(n) ? this.clampValue(n) : this.defaultNumericValue();
|
|
208
|
+
}
|
|
209
|
+
set valueAsNumber(next) {
|
|
210
|
+
this.value = String(this.clampValue(next));
|
|
211
|
+
}
|
|
212
|
+
/** If `value` is still unset, seed it with the sanitized default — the
|
|
213
|
+
* midpoint of `[min, max]`, snapped to `step` — so `value`/`valueAsNumber`
|
|
214
|
+
* and rendering never have to treat "" as a real, distinct state. */
|
|
215
|
+
ensureValue() {
|
|
216
|
+
if (this.value === '')
|
|
217
|
+
this.value = String(this.defaultNumericValue());
|
|
218
|
+
}
|
|
219
|
+
domain() {
|
|
220
|
+
// A caller-supplied min/max that fails Number attribute conversion
|
|
221
|
+
// arrives here as NaN; fall back to this property's own default rather
|
|
222
|
+
// than propagating NaN into every clampValue()/percentOf() caller.
|
|
223
|
+
const min = isNaN(this.min) ? 0 : this.min;
|
|
224
|
+
const max = isNaN(this.max) ? 100 : this.max;
|
|
225
|
+
return { lo: Math.min(min, max), hi: Math.max(min, max) };
|
|
226
|
+
}
|
|
227
|
+
defaultNumericValue() {
|
|
228
|
+
const { lo, hi } = this.domain();
|
|
229
|
+
return this.clampValue(lo + (hi - lo) / 2);
|
|
230
|
+
}
|
|
231
|
+
percentOf(value) {
|
|
232
|
+
if (isNaN(value))
|
|
233
|
+
return 0;
|
|
234
|
+
const { lo, hi } = this.domain();
|
|
235
|
+
const span = hi - lo || 1;
|
|
236
|
+
return ((value - lo) / span) * 100;
|
|
237
|
+
}
|
|
238
|
+
clampValue(raw) {
|
|
239
|
+
const { lo, hi } = this.domain();
|
|
240
|
+
// A non-positive or non-finite step would otherwise divide by zero/NaN
|
|
241
|
+
// below; treat it as "unstepped" instead of propagating NaN.
|
|
242
|
+
const hasStep = Number.isFinite(this.step) && this.step > 0;
|
|
243
|
+
let stepped = raw;
|
|
244
|
+
if (hasStep) {
|
|
245
|
+
// Anchor the step grid at the domain's own `lo` (matching native
|
|
246
|
+
// `<input type=range>`) instead of absolute 0, and round back to
|
|
247
|
+
// `step`'s own decimal precision so repeated steps land on exact
|
|
248
|
+
// values like 0.7 instead of 0.7000000000000001.
|
|
249
|
+
const stepsFromLo = Math.round((raw - lo) / this.step);
|
|
250
|
+
const factor = 10 ** decimalPlaces(this.step);
|
|
251
|
+
stepped = Math.round((lo + stepsFromLo * this.step) * factor) / factor;
|
|
252
|
+
}
|
|
253
|
+
return Math.min(hi, Math.max(lo, stepped));
|
|
254
|
+
}
|
|
255
|
+
formatValue(v) {
|
|
256
|
+
return String(v);
|
|
257
|
+
}
|
|
258
|
+
setValue(raw, commit) {
|
|
259
|
+
const clamped = this.clampValue(raw);
|
|
260
|
+
this.value = String(clamped);
|
|
261
|
+
this.emit('lyra-input', { value: clamped });
|
|
262
|
+
if (commit)
|
|
263
|
+
this.emit('lyra-change', { value: clamped });
|
|
264
|
+
}
|
|
265
|
+
/** Stop the drag owned by `pointerId`, optionally committing a final lyra-change. */
|
|
266
|
+
endDrag(pointerId, commit) {
|
|
267
|
+
if (!this.activePointers.has(pointerId))
|
|
268
|
+
return;
|
|
269
|
+
this.activePointers.delete(pointerId);
|
|
270
|
+
if (commit)
|
|
271
|
+
this.emit('lyra-change', { value: this.valueAsNumber });
|
|
272
|
+
// Only the last concurrent drag to end tears down the shared window
|
|
273
|
+
// listeners — an overlapping second pointer may still be down.
|
|
274
|
+
if (this.activePointers.size === 0) {
|
|
275
|
+
window.removeEventListener('pointermove', this.onPointerMove);
|
|
276
|
+
window.removeEventListener('pointerup', this.onPointerUp);
|
|
277
|
+
window.removeEventListener('pointercancel', this.onPointerUp);
|
|
278
|
+
window.removeEventListener('lostpointercapture', this.onPointerUp);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
willUpdate(changed) {
|
|
282
|
+
// `formResetCallback` (inherited from `FormAssociated`, restoring
|
|
283
|
+
// `value` to whatever default the mixin captured — "" when no `value`
|
|
284
|
+
// attribute was ever declared) isn't part of the mixin's exported
|
|
285
|
+
// `FormAssociatedInterface` type, so it can't be overridden here with a
|
|
286
|
+
// `super` call the way `connectedCallback`/`disconnectedCallback` above
|
|
287
|
+
// are. Catching the resulting empty `value` here instead, in the same
|
|
288
|
+
// pre-render pass that already re-clamps a changed min/max/step below,
|
|
289
|
+
// covers `form.reset()` the same way `connectedCallback` covers first
|
|
290
|
+
// mount — and doing it in `willUpdate` (not `updated`) folds the fix-up
|
|
291
|
+
// into this same update cycle instead of scheduling a second one.
|
|
292
|
+
if (changed.has('value') && this.value === '') {
|
|
293
|
+
this.ensureValue();
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if ((changed.has('min') || changed.has('max') || changed.has('step')) && this.value !== '') {
|
|
297
|
+
// A narrowed/shifted domain (or a changed step grid) after mount must
|
|
298
|
+
// not leave `value` — and the rendered thumb position it drives —
|
|
299
|
+
// outside the current bounds or off the step grid. `min`/`max`/`step`
|
|
300
|
+
// already hold their new values by this point, so the getter itself
|
|
301
|
+
// (which clamps against the live domain) computes the corrected value.
|
|
302
|
+
const next = String(this.valueAsNumber);
|
|
303
|
+
if (next !== this.value)
|
|
304
|
+
this.value = next;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
render() {
|
|
308
|
+
const num = this.valueAsNumber;
|
|
309
|
+
const pct = this.percentOf(num);
|
|
310
|
+
const text = this.formatValue(num);
|
|
311
|
+
const { lo, hi } = this.domain();
|
|
312
|
+
const ariaLabel = this.label || this.getAttribute('aria-label') || nothing;
|
|
313
|
+
return html `
|
|
314
|
+
<div part="base">
|
|
315
|
+
<div part="track"></div>
|
|
316
|
+
<div part="fill" style=${`inline-size:${pct}%`}></div>
|
|
317
|
+
<div
|
|
318
|
+
part="thumb"
|
|
319
|
+
role="slider"
|
|
320
|
+
tabindex=${this.effectiveDisabled ? '-1' : '0'}
|
|
321
|
+
aria-valuemin=${lo}
|
|
322
|
+
aria-valuemax=${hi}
|
|
323
|
+
aria-valuenow=${num}
|
|
324
|
+
aria-valuetext=${text}
|
|
325
|
+
aria-label=${ariaLabel}
|
|
326
|
+
aria-disabled=${this.effectiveDisabled ? 'true' : nothing}
|
|
327
|
+
style=${`inset-inline-start:${pct}%`}
|
|
328
|
+
@pointerdown=${this.onPointerDown}
|
|
329
|
+
@keydown=${this.onKeyDown}
|
|
330
|
+
@keyup=${this.onKeyUp}
|
|
331
|
+
></div>
|
|
332
|
+
</div>
|
|
333
|
+
${this.showValue ? html `<span part="value" aria-hidden="true">${text}</span>` : nothing}
|
|
334
|
+
`;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
__decorate([
|
|
338
|
+
property({ type: Number })
|
|
339
|
+
], LyraSlider.prototype, "min", void 0);
|
|
340
|
+
__decorate([
|
|
341
|
+
property({ type: Number })
|
|
342
|
+
], LyraSlider.prototype, "max", void 0);
|
|
343
|
+
__decorate([
|
|
344
|
+
property({ type: Number })
|
|
345
|
+
], LyraSlider.prototype, "step", void 0);
|
|
346
|
+
__decorate([
|
|
347
|
+
property()
|
|
348
|
+
], LyraSlider.prototype, "label", void 0);
|
|
349
|
+
__decorate([
|
|
350
|
+
property({ type: Boolean, attribute: 'show-value' })
|
|
351
|
+
], LyraSlider.prototype, "showValue", void 0);
|
|
352
|
+
defineElement('slider', LyraSlider);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: var(--lyra-space-s);
|
|
7
|
+
inline-size: 100%;
|
|
8
|
+
}
|
|
9
|
+
[part='base'] {
|
|
10
|
+
position: relative;
|
|
11
|
+
flex: 1 1 auto;
|
|
12
|
+
block-size: 1.5rem;
|
|
13
|
+
}
|
|
14
|
+
[part='track'] {
|
|
15
|
+
position: absolute;
|
|
16
|
+
inset-inline: 0;
|
|
17
|
+
inset-block-start: 50%;
|
|
18
|
+
block-size: 4px;
|
|
19
|
+
transform: translateY(-50%);
|
|
20
|
+
border-radius: 2px;
|
|
21
|
+
background: var(--lyra-color-border);
|
|
22
|
+
}
|
|
23
|
+
[part='fill'] {
|
|
24
|
+
position: absolute;
|
|
25
|
+
inset-inline-start: 0;
|
|
26
|
+
inset-block-start: 50%;
|
|
27
|
+
block-size: 4px;
|
|
28
|
+
transform: translateY(-50%);
|
|
29
|
+
border-radius: 2px;
|
|
30
|
+
background: var(--lyra-color-brand);
|
|
31
|
+
}
|
|
32
|
+
[part='thumb'] {
|
|
33
|
+
position: absolute;
|
|
34
|
+
inset-block-start: 50%;
|
|
35
|
+
inline-size: 16px;
|
|
36
|
+
block-size: 16px;
|
|
37
|
+
border-radius: 50%;
|
|
38
|
+
background: var(--lyra-color-brand);
|
|
39
|
+
border: 2px solid var(--lyra-color-surface);
|
|
40
|
+
box-shadow: var(--lyra-shadow);
|
|
41
|
+
transform: translate(-50%, -50%);
|
|
42
|
+
cursor: grab;
|
|
43
|
+
touch-action: none;
|
|
44
|
+
}
|
|
45
|
+
/* The visible dot is 16px, under the ~24px touch-target minimum. Widen the
|
|
46
|
+
hit/drag area with a transparent ::before instead of growing the thumb
|
|
47
|
+
itself — onPointerMove never reads the thumb's own
|
|
48
|
+
getBoundingClientRect() (only [part="track"]'s rect and e.clientX), and a
|
|
49
|
+
pointerdown inside the ::before still reports e.target as the thumb
|
|
50
|
+
element (pseudo-elements have no separate DOM node/event target), so
|
|
51
|
+
this is purely additive and cannot change the drag math. Mirrors
|
|
52
|
+
lyra-time-range's identical handle::before. */
|
|
53
|
+
[part='thumb']::before {
|
|
54
|
+
content: '';
|
|
55
|
+
position: absolute;
|
|
56
|
+
inset-block-start: 50%;
|
|
57
|
+
inset-inline-start: 50%;
|
|
58
|
+
inline-size: 28px;
|
|
59
|
+
block-size: 28px;
|
|
60
|
+
transform: translate(-50%, -50%);
|
|
61
|
+
border-radius: 50%;
|
|
62
|
+
}
|
|
63
|
+
[part='thumb']:focus-visible {
|
|
64
|
+
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
65
|
+
outline-offset: var(--lyra-focus-ring-offset);
|
|
66
|
+
}
|
|
67
|
+
[part='thumb']:active {
|
|
68
|
+
cursor: grabbing;
|
|
69
|
+
}
|
|
70
|
+
[part='value'] {
|
|
71
|
+
flex: 0 0 auto;
|
|
72
|
+
font-size: 0.8125rem;
|
|
73
|
+
color: var(--lyra-color-text-quiet);
|
|
74
|
+
/* Numeric readout ticks as the thumb moves; tabular-nums keeps its own
|
|
75
|
+
inline-size stable instead of jittering the layout next to it. */
|
|
76
|
+
font-variant-numeric: tabular-nums;
|
|
77
|
+
min-inline-size: 2.5ch;
|
|
78
|
+
text-align: end;
|
|
79
|
+
}
|
|
80
|
+
:host([disabled]) {
|
|
81
|
+
opacity: var(--lyra-opacity-disabled);
|
|
82
|
+
cursor: not-allowed;
|
|
83
|
+
}
|
|
84
|
+
:host([disabled]) [part='thumb'] {
|
|
85
|
+
cursor: not-allowed;
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type TemplateResult } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
export interface SourceCardExpandDetail {
|
|
4
|
+
sourceId: string;
|
|
5
|
+
expanded: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface SourceCardOpenDetail {
|
|
8
|
+
sourceId: string;
|
|
9
|
+
href?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `<lyra-source-card>` — one citation/source entry, meant to be a direct
|
|
13
|
+
* light-DOM child of `<lyra-source-list>` (though it renders and functions
|
|
14
|
+
* fine standalone). Shows a title/page heading, an always-visible `excerpt`
|
|
15
|
+
* slot, and an optional `full` slot revealed behind its own independent
|
|
16
|
+
* "Show more" toggle — unrelated to the parent `<lyra-source-list>`'s own
|
|
17
|
+
* expand/collapse, which only ever hides/shows the *set* of cards, never a
|
|
18
|
+
* single card's own content.
|
|
19
|
+
*
|
|
20
|
+
* `source-id` is this card's stable identity, meant to match a
|
|
21
|
+
* `<lyra-citation-badge>` (a sibling component) elsewhere on the page. This
|
|
22
|
+
* component doesn't implement any scroll-to/highlight behavior itself — that
|
|
23
|
+
* lives at the app level, wiring a citation badge's activation event to this
|
|
24
|
+
* card's `id`/`source-id`. See the `@example` below.
|
|
25
|
+
*
|
|
26
|
+
* @customElement lyra-source-card
|
|
27
|
+
* @slot excerpt - A short preview, always visible.
|
|
28
|
+
* @slot full - The complete source text/chunk, hidden behind the "Show
|
|
29
|
+
* more"/"Show less" toggle. When left empty, no toggle renders at all — a
|
|
30
|
+
* card with no `full` content simply has no expand affordance.
|
|
31
|
+
* @event lyra-expand - The per-card "Show more"/"Show less" toggle was
|
|
32
|
+
* activated. `detail: { sourceId, expanded }`.
|
|
33
|
+
* @event lyra-open - The title was activated. `detail: { sourceId, href }` —
|
|
34
|
+
* `href` may be `undefined`. This component never navigates on its own
|
|
35
|
+
* (staying a controlled component, the same convention
|
|
36
|
+
* `<lyra-tool-call-chip>`'s `lyra-tool-chip-select` follows); a listener
|
|
37
|
+
* decides what "open" means (open `href` in a new tab, open an in-app
|
|
38
|
+
* viewer, etc).
|
|
39
|
+
* @csspart base - The outer container.
|
|
40
|
+
* @csspart title - The clickable title/page heading (`<button>`).
|
|
41
|
+
* @csspart excerpt - The wrapper around the `excerpt` slot.
|
|
42
|
+
* @csspart full - The wrapper around the `full` slot, `hidden` while collapsed.
|
|
43
|
+
* @csspart toggle - The "Show more"/"Show less" button. Only rendered when the `full` slot has content.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```html
|
|
47
|
+
* <lyra-source-list label-plural="2 sources">
|
|
48
|
+
* <lyra-source-card source-id="doc-1" title="annual_report.pdf" page="12">
|
|
49
|
+
* <span slot="excerpt">Revenue grew 12% year over year...</span>
|
|
50
|
+
* <span slot="full">Revenue grew 12% year over year, driven primarily by...</span>
|
|
51
|
+
* </lyra-source-card>
|
|
52
|
+
* </lyra-source-list>
|
|
53
|
+
* ```
|
|
54
|
+
* ```js
|
|
55
|
+
* // Elsewhere, a <lyra-citation-badge>'s activation handler can scroll to
|
|
56
|
+
* // and highlight the matching card -- this component needs no extra API
|
|
57
|
+
* // surface for that, only its existing source-id to be targeted by:
|
|
58
|
+
* document.addEventListener('lyra-citation-activate', (e) => {
|
|
59
|
+
* const card = document.querySelector(`lyra-source-card[source-id="${e.detail.sourceId}"]`);
|
|
60
|
+
* card?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
61
|
+
* card?.classList.add('is-highlighted'); // consumer-defined CSS, e.g. a brief background flash
|
|
62
|
+
* setTimeout(() => card?.classList.remove('is-highlighted'), 2000);
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare class LyraSourceCard extends LyraElement {
|
|
67
|
+
static styles: import("lit").CSSResultGroup[];
|
|
68
|
+
/** Stable identifier matching a `<lyra-citation-badge>` elsewhere on the page. */
|
|
69
|
+
sourceId: string;
|
|
70
|
+
/** The source's display title, e.g. a filename. */
|
|
71
|
+
title: string;
|
|
72
|
+
/** Optional page reference, e.g. `12` or `"iv"` — rendered as-is (never
|
|
73
|
+
* parsed/validated as a number), so a non-numeric page label works too. */
|
|
74
|
+
page?: string | number;
|
|
75
|
+
/** Optional URL, echoed back (unopened) in `lyra-open`'s detail. */
|
|
76
|
+
href?: string;
|
|
77
|
+
private hasFullSlot;
|
|
78
|
+
private fullExpanded;
|
|
79
|
+
private readonly fullId;
|
|
80
|
+
protected willUpdate(): void;
|
|
81
|
+
firstUpdated(): void;
|
|
82
|
+
private onFullSlotChange;
|
|
83
|
+
private get titleText();
|
|
84
|
+
private onTitleClick;
|
|
85
|
+
private toggleFull;
|
|
86
|
+
render(): TemplateResult;
|
|
87
|
+
}
|
|
88
|
+
declare global {
|
|
89
|
+
interface HTMLElementTagNameMap {
|
|
90
|
+
'lyra-source-card': LyraSourceCard;
|
|
91
|
+
}
|
|
92
|
+
}
|