@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,184 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
max-inline-size: 100%;
|
|
6
|
+
/* Per-status accent -- one custom property swapped by the :host([status])
|
|
7
|
+
rules below rather than repeating background/border per part per
|
|
8
|
+
status. Mirrors lyra-tool-call-chip's identical
|
|
9
|
+
--lyra-tool-call-chip-accent/-bg/-border trio, so a chip's tone
|
|
10
|
+
vocabulary reads the same everywhere in the library. Defaults to the
|
|
11
|
+
'pending' tone so an unset/unknown status still reads as neutral
|
|
12
|
+
instead of unstyled. */
|
|
13
|
+
--lyra-attachment-chip-accent: var(--lyra-color-text-quiet);
|
|
14
|
+
--lyra-attachment-chip-bg: var(--lyra-color-surface);
|
|
15
|
+
--lyra-attachment-chip-border: var(--lyra-color-border);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
:host([status='uploading']) {
|
|
19
|
+
--lyra-attachment-chip-accent: var(--lyra-color-brand);
|
|
20
|
+
--lyra-attachment-chip-bg: var(--lyra-color-brand-quiet);
|
|
21
|
+
--lyra-attachment-chip-border: transparent;
|
|
22
|
+
}
|
|
23
|
+
:host([status='error']) {
|
|
24
|
+
--lyra-attachment-chip-accent: var(--lyra-color-danger);
|
|
25
|
+
--lyra-attachment-chip-bg: var(--lyra-color-danger-quiet);
|
|
26
|
+
--lyra-attachment-chip-border: transparent;
|
|
27
|
+
}
|
|
28
|
+
/* Optional neutral-positive tint for a finished upload -- subtler than
|
|
29
|
+
'uploading'/'error' since there's nothing left for the user to act on. */
|
|
30
|
+
:host([status='done']) {
|
|
31
|
+
--lyra-attachment-chip-accent: var(--lyra-color-success);
|
|
32
|
+
--lyra-attachment-chip-bg: var(--lyra-color-success-quiet);
|
|
33
|
+
--lyra-attachment-chip-border: transparent;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
[part='base'] {
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: var(--lyra-space-s);
|
|
40
|
+
max-inline-size: 100%;
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
padding: var(--lyra-space-xs) var(--lyra-space-s);
|
|
43
|
+
border: 1px solid var(--lyra-attachment-chip-border);
|
|
44
|
+
border-radius: var(--lyra-radius);
|
|
45
|
+
background: var(--lyra-attachment-chip-bg);
|
|
46
|
+
color: var(--lyra-color-text);
|
|
47
|
+
font-size: 0.8125rem;
|
|
48
|
+
line-height: 1.3;
|
|
49
|
+
transition:
|
|
50
|
+
background-color var(--lyra-transition-fast),
|
|
51
|
+
border-color var(--lyra-transition-fast);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
[part='thumbnail'] {
|
|
55
|
+
display: inline-flex;
|
|
56
|
+
flex: 0 0 auto;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
/* Reuses the shared icon-button box size as a ready-made "small square
|
|
60
|
+
glyph/image slot" token rather than inventing a new one-off dimension. */
|
|
61
|
+
inline-size: var(--lyra-icon-button-size);
|
|
62
|
+
block-size: var(--lyra-icon-button-size);
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
border-radius: calc(var(--lyra-radius) * 0.6);
|
|
65
|
+
background: var(--lyra-color-surface);
|
|
66
|
+
color: var(--lyra-attachment-chip-accent);
|
|
67
|
+
}
|
|
68
|
+
[part='thumbnail'] img {
|
|
69
|
+
inline-size: 100%;
|
|
70
|
+
block-size: 100%;
|
|
71
|
+
object-fit: cover;
|
|
72
|
+
display: block;
|
|
73
|
+
}
|
|
74
|
+
[part='thumbnail'] svg {
|
|
75
|
+
display: block;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[part='meta'] {
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
flex: 1 1 auto;
|
|
82
|
+
min-inline-size: 0;
|
|
83
|
+
gap: 0.125rem;
|
|
84
|
+
}
|
|
85
|
+
[part='name'] {
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
text-overflow: ellipsis;
|
|
88
|
+
white-space: nowrap;
|
|
89
|
+
font-weight: 600;
|
|
90
|
+
color: var(--lyra-color-text);
|
|
91
|
+
}
|
|
92
|
+
[part='size'] {
|
|
93
|
+
/* Full-strength text, not --lyra-color-text-quiet -- this sits on top of
|
|
94
|
+
the per-status *-quiet tint backgrounds above (e.g. danger-quiet), and
|
|
95
|
+
text-quiet's gray fails WCAG AA contrast against several of those
|
|
96
|
+
tints even though it comfortably passes against the plain surface
|
|
97
|
+
background used by the resting state. Same fix, same rationale, as
|
|
98
|
+
lyra-tool-call-chip's identical [part='duration']/[part='category']. */
|
|
99
|
+
color: var(--lyra-color-text);
|
|
100
|
+
font-variant-numeric: tabular-nums;
|
|
101
|
+
}
|
|
102
|
+
[part='status-text'] {
|
|
103
|
+
color: var(--lyra-attachment-chip-accent);
|
|
104
|
+
font-weight: 600;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
[part='progress'] {
|
|
108
|
+
flex: 0 0 auto;
|
|
109
|
+
inline-size: 3.5rem;
|
|
110
|
+
block-size: var(--lyra-space-xs);
|
|
111
|
+
border-radius: 999px;
|
|
112
|
+
background: var(--lyra-color-border);
|
|
113
|
+
overflow: hidden;
|
|
114
|
+
}
|
|
115
|
+
[part='progress-fill'] {
|
|
116
|
+
block-size: 100%;
|
|
117
|
+
border-radius: inherit;
|
|
118
|
+
background: var(--lyra-attachment-chip-accent);
|
|
119
|
+
transition: inline-size var(--lyra-transition-base);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
[part='spinner'] {
|
|
123
|
+
flex: 0 0 auto;
|
|
124
|
+
display: inline-block;
|
|
125
|
+
inline-size: 1rem;
|
|
126
|
+
block-size: 1rem;
|
|
127
|
+
border-radius: 50%;
|
|
128
|
+
border: 2px solid var(--lyra-color-border);
|
|
129
|
+
border-block-start-color: var(--lyra-attachment-chip-accent);
|
|
130
|
+
animation: lyra-attachment-chip-spin 0.8s linear infinite;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
[part='retry-button'],
|
|
134
|
+
[part='remove-button'] {
|
|
135
|
+
flex: 0 0 auto;
|
|
136
|
+
display: inline-flex;
|
|
137
|
+
align-items: center;
|
|
138
|
+
justify-content: center;
|
|
139
|
+
min-inline-size: min(var(--lyra-icon-button-size), 1.75rem);
|
|
140
|
+
min-block-size: min(var(--lyra-icon-button-size), 1.75rem);
|
|
141
|
+
padding: 0;
|
|
142
|
+
border: none;
|
|
143
|
+
border-radius: calc(var(--lyra-radius) * 0.6);
|
|
144
|
+
background: transparent;
|
|
145
|
+
color: var(--lyra-color-text-quiet);
|
|
146
|
+
font: inherit;
|
|
147
|
+
cursor: pointer;
|
|
148
|
+
-webkit-tap-highlight-color: transparent;
|
|
149
|
+
transition: background-color var(--lyra-transition-fast);
|
|
150
|
+
}
|
|
151
|
+
[part='retry-button'] {
|
|
152
|
+
color: var(--lyra-color-danger);
|
|
153
|
+
}
|
|
154
|
+
[part='retry-button']:hover,
|
|
155
|
+
[part='remove-button']:hover {
|
|
156
|
+
background: color-mix(in srgb, var(--lyra-color-text) 8%, transparent);
|
|
157
|
+
}
|
|
158
|
+
[part='retry-button']:focus-visible,
|
|
159
|
+
[part='remove-button']:focus-visible {
|
|
160
|
+
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
161
|
+
outline-offset: var(--lyra-focus-ring-offset);
|
|
162
|
+
}
|
|
163
|
+
[part='retry-button'] svg,
|
|
164
|
+
[part='remove-button'] svg {
|
|
165
|
+
display: block;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@keyframes lyra-attachment-chip-spin {
|
|
169
|
+
to {
|
|
170
|
+
transform: rotate(360deg);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
@media (prefers-reduced-motion: reduce) {
|
|
174
|
+
[part='base'] {
|
|
175
|
+
transition: none !important;
|
|
176
|
+
}
|
|
177
|
+
[part='progress-fill'] {
|
|
178
|
+
transition: none !important;
|
|
179
|
+
}
|
|
180
|
+
[part='spinner'] {
|
|
181
|
+
animation: none !important;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
`;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type TemplateResult } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
import '../menu/menu.js';
|
|
4
|
+
import '../menu/menu-item.js';
|
|
5
|
+
export type AttachmentCapability = 'files' | 'image' | 'camera';
|
|
6
|
+
/** The two capabilities that resolve to a real file selection (as opposed
|
|
7
|
+
* to `camera`, which never touches a file input -- see the class doc). */
|
|
8
|
+
export type FileBackedCapability = Exclude<AttachmentCapability, 'camera'>;
|
|
9
|
+
export interface AttachmentPickDetail {
|
|
10
|
+
capability: FileBackedCapability;
|
|
11
|
+
files: FileList;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `<lyra-attachment-trigger>` — a compact attach affordance designed for a
|
|
15
|
+
* chat composer's leading slot (see `<lyra-chat-composer>`'s own `leading`
|
|
16
|
+
* slot, which this drops straight into, though this component has no code
|
|
17
|
+
* dependency on it). Its shape adapts to how many attachment `capabilities`
|
|
18
|
+
* are configured:
|
|
19
|
+
* - Exactly one capability: a single plain icon button ([part='trigger']).
|
|
20
|
+
* Activating it performs that capability's action directly.
|
|
21
|
+
* - More than one: a small anchored menu ([part='menu'], composed from
|
|
22
|
+
* `<lyra-menu>`/`<lyra-menu-item>`) listing each capability as a row.
|
|
23
|
+
*
|
|
24
|
+
* Two of the three capabilities (`files`, `image`) are file-picker-backed:
|
|
25
|
+
* activating them opens a hidden native `<input type="file">` via a
|
|
26
|
+
* synthetic `.click()`, and the resulting selection is re-emitted as
|
|
27
|
+
* `lyra-pick`. `accept` is shared across both — `image` defaults it to
|
|
28
|
+
* `'image/*'` unless the `accept` prop overrides it, `files` always uses
|
|
29
|
+
* `accept` as-is (empty means "any file type", matching a bare native
|
|
30
|
+
* `<input type="file">` with no `accept` attribute).
|
|
31
|
+
*
|
|
32
|
+
* **`camera` is scope-limited by design.** This component does not
|
|
33
|
+
* implement any camera capture UI itself — no `getUserMedia`, no
|
|
34
|
+
* `<input capture>` — because that's entirely a host/browser concern with
|
|
35
|
+
* no single right answer (a desktop web app, a mobile PWA, and a native
|
|
36
|
+
* wrapper all want different things here). Activating the `camera`
|
|
37
|
+
* capability only fires `lyra-camera-request`; the host owns everything
|
|
38
|
+
* from that point on (opening its own capture UI, then presumably handing
|
|
39
|
+
* the resulting `File` back to something like `<lyra-attachment-chip>`).
|
|
40
|
+
*
|
|
41
|
+
* @customElement lyra-attachment-trigger
|
|
42
|
+
* @event lyra-pick - A file-backed capability's hidden file input produced a
|
|
43
|
+
* real selection. `detail: { capability: 'files' | 'image', files }` — a
|
|
44
|
+
* real `FileList` (not a plain array), matching the native input's own
|
|
45
|
+
* `.files` shape, but an independent snapshot rather than that same live
|
|
46
|
+
* object — see `onInputChange`'s own doc for why a live reference would be
|
|
47
|
+
* unsafe to hand out here.
|
|
48
|
+
* @event lyra-camera-request - The `camera` capability was activated. No
|
|
49
|
+
* detail payload — see the class doc's scope note; the host implements the
|
|
50
|
+
* actual capture flow.
|
|
51
|
+
* @csspart trigger - The single-capability icon button. Only rendered when `capabilities.length === 1`.
|
|
52
|
+
* @csspart menu - The `<lyra-menu>` wrapper. Only rendered when `capabilities.length > 1`.
|
|
53
|
+
*/
|
|
54
|
+
export declare class LyraAttachmentTrigger extends LyraElement {
|
|
55
|
+
static styles: import("lit").CSSResultGroup[];
|
|
56
|
+
/** Which attachment capabilities to offer, in display order. A single
|
|
57
|
+
* entry renders a plain button; more than one renders a menu. */
|
|
58
|
+
capabilities: AttachmentCapability[];
|
|
59
|
+
/** Native-file-input-style accept string (e.g. `'image/*'` or
|
|
60
|
+
* `'.pdf,.docx'`), forwarded to the hidden file input for the
|
|
61
|
+
* `files`/`image` capabilities — see the class doc for how each uses it. */
|
|
62
|
+
accept: string;
|
|
63
|
+
/** Forwarded to the hidden file input's own `multiple` attribute. */
|
|
64
|
+
multiple: boolean;
|
|
65
|
+
disabled: boolean;
|
|
66
|
+
private inputEl?;
|
|
67
|
+
private pendingCapability;
|
|
68
|
+
private get hasFileCapability();
|
|
69
|
+
private effectiveAccept;
|
|
70
|
+
private activateCapability;
|
|
71
|
+
private onTriggerClick;
|
|
72
|
+
private onMenuSelect;
|
|
73
|
+
private onInputChange;
|
|
74
|
+
private renderHiddenInput;
|
|
75
|
+
private renderSingleTrigger;
|
|
76
|
+
private renderMenu;
|
|
77
|
+
render(): TemplateResult;
|
|
78
|
+
}
|
|
79
|
+
declare global {
|
|
80
|
+
interface HTMLElementTagNameMap {
|
|
81
|
+
'lyra-attachment-trigger': LyraAttachmentTrigger;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
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, svg } from 'lit';
|
|
8
|
+
import { property, query } from 'lit/decorators.js';
|
|
9
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
+
import { styles } from './attachment-trigger.styles.js';
|
|
12
|
+
import '../menu/menu.js';
|
|
13
|
+
import '../menu/menu-item.js';
|
|
14
|
+
// Mirrors the shared icon set's viewBox/stroke conventions
|
|
15
|
+
// (internal/icons.ts's chevronIcon()/closeIcon()/etc.) without adding these
|
|
16
|
+
// one-off glyphs to that module -- it's off limits here -- so they still
|
|
17
|
+
// read as part of the same visual language as the rest of the library's
|
|
18
|
+
// inline icons. Same approach as lyra-attachment-chip's local fileGlyph()/
|
|
19
|
+
// retryIcon() and lyra-checkbox's local checkmarkGlyph().
|
|
20
|
+
const ICON_VIEW_BOX = '0 0 24 24';
|
|
21
|
+
const ICON_STROKE_WIDTH = '1.75';
|
|
22
|
+
function icon(paths) {
|
|
23
|
+
return svg `
|
|
24
|
+
<svg
|
|
25
|
+
width="1em"
|
|
26
|
+
height="1em"
|
|
27
|
+
viewBox=${ICON_VIEW_BOX}
|
|
28
|
+
fill="none"
|
|
29
|
+
stroke="currentColor"
|
|
30
|
+
stroke-width=${ICON_STROKE_WIDTH}
|
|
31
|
+
stroke-linecap="round"
|
|
32
|
+
stroke-linejoin="round"
|
|
33
|
+
aria-hidden="true"
|
|
34
|
+
focusable="false"
|
|
35
|
+
>${paths}</svg>
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
/** A paperclip glyph -- the generic "attach" affordance, used for the
|
|
39
|
+
* `files` capability and as the multi-capability menu's own trigger icon
|
|
40
|
+
* (the one glyph a user recognizes regardless of which capabilities the
|
|
41
|
+
* menu underneath actually offers). */
|
|
42
|
+
function paperclipIcon() {
|
|
43
|
+
return icon(svg `
|
|
44
|
+
<path d="M21.44 11.05 12.25 20.24a5.5 5.5 0 0 1-7.78-7.78l9.19-9.19a3.5 3.5 0 0 1 4.95 4.95l-9.2 9.19a1.5 1.5 0 0 1-2.12-2.12l8.49-8.48"></path>
|
|
45
|
+
`);
|
|
46
|
+
}
|
|
47
|
+
/** A picture-frame glyph for the `image` capability. */
|
|
48
|
+
function imageIcon() {
|
|
49
|
+
return icon(svg `
|
|
50
|
+
<rect x="3" y="3" width="18" height="18" rx="2"></rect>
|
|
51
|
+
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
|
52
|
+
<polyline points="21 15 16 10 5 21"></polyline>
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
55
|
+
/** A camera-body glyph for the `camera` capability. */
|
|
56
|
+
function cameraIcon() {
|
|
57
|
+
return icon(svg `
|
|
58
|
+
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2Z"></path>
|
|
59
|
+
<circle cx="12" cy="13" r="4"></circle>
|
|
60
|
+
`);
|
|
61
|
+
}
|
|
62
|
+
const CAPABILITY_META = {
|
|
63
|
+
files: { icon: paperclipIcon, triggerLabel: 'Attach files', menuLabel: 'Upload files' },
|
|
64
|
+
image: { icon: imageIcon, triggerLabel: 'Attach an image', menuLabel: 'Upload a photo' },
|
|
65
|
+
camera: { icon: cameraIcon, triggerLabel: 'Use camera', menuLabel: 'Take a photo' },
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* `<lyra-attachment-trigger>` — a compact attach affordance designed for a
|
|
69
|
+
* chat composer's leading slot (see `<lyra-chat-composer>`'s own `leading`
|
|
70
|
+
* slot, which this drops straight into, though this component has no code
|
|
71
|
+
* dependency on it). Its shape adapts to how many attachment `capabilities`
|
|
72
|
+
* are configured:
|
|
73
|
+
* - Exactly one capability: a single plain icon button ([part='trigger']).
|
|
74
|
+
* Activating it performs that capability's action directly.
|
|
75
|
+
* - More than one: a small anchored menu ([part='menu'], composed from
|
|
76
|
+
* `<lyra-menu>`/`<lyra-menu-item>`) listing each capability as a row.
|
|
77
|
+
*
|
|
78
|
+
* Two of the three capabilities (`files`, `image`) are file-picker-backed:
|
|
79
|
+
* activating them opens a hidden native `<input type="file">` via a
|
|
80
|
+
* synthetic `.click()`, and the resulting selection is re-emitted as
|
|
81
|
+
* `lyra-pick`. `accept` is shared across both — `image` defaults it to
|
|
82
|
+
* `'image/*'` unless the `accept` prop overrides it, `files` always uses
|
|
83
|
+
* `accept` as-is (empty means "any file type", matching a bare native
|
|
84
|
+
* `<input type="file">` with no `accept` attribute).
|
|
85
|
+
*
|
|
86
|
+
* **`camera` is scope-limited by design.** This component does not
|
|
87
|
+
* implement any camera capture UI itself — no `getUserMedia`, no
|
|
88
|
+
* `<input capture>` — because that's entirely a host/browser concern with
|
|
89
|
+
* no single right answer (a desktop web app, a mobile PWA, and a native
|
|
90
|
+
* wrapper all want different things here). Activating the `camera`
|
|
91
|
+
* capability only fires `lyra-camera-request`; the host owns everything
|
|
92
|
+
* from that point on (opening its own capture UI, then presumably handing
|
|
93
|
+
* the resulting `File` back to something like `<lyra-attachment-chip>`).
|
|
94
|
+
*
|
|
95
|
+
* @customElement lyra-attachment-trigger
|
|
96
|
+
* @event lyra-pick - A file-backed capability's hidden file input produced a
|
|
97
|
+
* real selection. `detail: { capability: 'files' | 'image', files }` — a
|
|
98
|
+
* real `FileList` (not a plain array), matching the native input's own
|
|
99
|
+
* `.files` shape, but an independent snapshot rather than that same live
|
|
100
|
+
* object — see `onInputChange`'s own doc for why a live reference would be
|
|
101
|
+
* unsafe to hand out here.
|
|
102
|
+
* @event lyra-camera-request - The `camera` capability was activated. No
|
|
103
|
+
* detail payload — see the class doc's scope note; the host implements the
|
|
104
|
+
* actual capture flow.
|
|
105
|
+
* @csspart trigger - The single-capability icon button. Only rendered when `capabilities.length === 1`.
|
|
106
|
+
* @csspart menu - The `<lyra-menu>` wrapper. Only rendered when `capabilities.length > 1`.
|
|
107
|
+
*/
|
|
108
|
+
export class LyraAttachmentTrigger extends LyraElement {
|
|
109
|
+
constructor() {
|
|
110
|
+
super(...arguments);
|
|
111
|
+
/** Which attachment capabilities to offer, in display order. A single
|
|
112
|
+
* entry renders a plain button; more than one renders a menu. */
|
|
113
|
+
this.capabilities = ['files'];
|
|
114
|
+
/** Native-file-input-style accept string (e.g. `'image/*'` or
|
|
115
|
+
* `'.pdf,.docx'`), forwarded to the hidden file input for the
|
|
116
|
+
* `files`/`image` capabilities — see the class doc for how each uses it. */
|
|
117
|
+
this.accept = '';
|
|
118
|
+
/** Forwarded to the hidden file input's own `multiple` attribute. */
|
|
119
|
+
this.multiple = true;
|
|
120
|
+
this.disabled = false;
|
|
121
|
+
// Which file-backed capability the hidden input's next 'change' event
|
|
122
|
+
// belongs to -- set synchronously right before the synthetic .click(), so
|
|
123
|
+
// one shared <input> can serve both 'files' and 'image' (each wanting a
|
|
124
|
+
// different `accept`) without needing two separate hidden inputs.
|
|
125
|
+
this.pendingCapability = 'files';
|
|
126
|
+
this.onTriggerClick = () => {
|
|
127
|
+
this.activateCapability(this.capabilities[0]);
|
|
128
|
+
};
|
|
129
|
+
this.onMenuSelect = (e) => {
|
|
130
|
+
this.activateCapability(e.detail.value);
|
|
131
|
+
};
|
|
132
|
+
this.onInputChange = (e) => {
|
|
133
|
+
const input = e.target;
|
|
134
|
+
const selected = input.files;
|
|
135
|
+
if (selected && selected.length > 0) {
|
|
136
|
+
// `input.files` is a *live* view of the input's own current
|
|
137
|
+
// selection, not a frozen snapshot -- clearing `.value` below (so
|
|
138
|
+
// re-picking the exact same file still fires another 'change' next
|
|
139
|
+
// time) mutates this very object back to empty in place. A listener
|
|
140
|
+
// that reads `detail.files` synchronously (a plain `addEventListener`
|
|
141
|
+
// callback) would never notice, but anything that reads it even one
|
|
142
|
+
// microtask later (an `async` handler, a queued upload) would see an
|
|
143
|
+
// empty list. Rehoming the selected files into a fresh `DataTransfer`
|
|
144
|
+
// produces an independent `FileList` — still the real `FileList` type
|
|
145
|
+
// the `lyra-pick` contract promises, just no longer tied to this
|
|
146
|
+
// input's own live state.
|
|
147
|
+
const snapshot = new DataTransfer();
|
|
148
|
+
for (const file of selected)
|
|
149
|
+
snapshot.items.add(file);
|
|
150
|
+
this.emit('lyra-pick', {
|
|
151
|
+
capability: this.pendingCapability,
|
|
152
|
+
files: snapshot.files,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Clearing `.value` (not just leaving the stale selection in place)
|
|
156
|
+
// means re-picking the exact same file still fires another 'change'
|
|
157
|
+
// event next time, matching <lyra-file-input>'s identical reset.
|
|
158
|
+
input.value = '';
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
162
|
+
get hasFileCapability() {
|
|
163
|
+
return this.capabilities.includes('files') || this.capabilities.includes('image');
|
|
164
|
+
}
|
|
165
|
+
effectiveAccept(capability) {
|
|
166
|
+
return capability === 'image' ? this.accept || 'image/*' : this.accept;
|
|
167
|
+
}
|
|
168
|
+
activateCapability(capability) {
|
|
169
|
+
if (this.disabled)
|
|
170
|
+
return;
|
|
171
|
+
if (capability === 'camera') {
|
|
172
|
+
this.emit('lyra-camera-request');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.pendingCapability = capability;
|
|
176
|
+
const input = this.inputEl;
|
|
177
|
+
if (!input)
|
|
178
|
+
return;
|
|
179
|
+
input.accept = this.effectiveAccept(capability);
|
|
180
|
+
input.click();
|
|
181
|
+
}
|
|
182
|
+
renderHiddenInput() {
|
|
183
|
+
return html `
|
|
184
|
+
<input
|
|
185
|
+
type="file"
|
|
186
|
+
tabindex="-1"
|
|
187
|
+
aria-hidden="true"
|
|
188
|
+
?multiple=${this.multiple}
|
|
189
|
+
?disabled=${this.disabled}
|
|
190
|
+
@change=${this.onInputChange}
|
|
191
|
+
/>
|
|
192
|
+
`;
|
|
193
|
+
}
|
|
194
|
+
renderSingleTrigger(capability) {
|
|
195
|
+
const meta = CAPABILITY_META[capability];
|
|
196
|
+
return html `
|
|
197
|
+
<button
|
|
198
|
+
part="trigger"
|
|
199
|
+
class="trigger-button"
|
|
200
|
+
type="button"
|
|
201
|
+
aria-label=${meta.triggerLabel}
|
|
202
|
+
?disabled=${this.disabled}
|
|
203
|
+
@click=${this.onTriggerClick}
|
|
204
|
+
>
|
|
205
|
+
${meta.icon()}
|
|
206
|
+
</button>
|
|
207
|
+
`;
|
|
208
|
+
}
|
|
209
|
+
renderMenu() {
|
|
210
|
+
return html `
|
|
211
|
+
<lyra-menu part="menu" label="Add attachment" @lyra-menu-select=${this.onMenuSelect}>
|
|
212
|
+
<button
|
|
213
|
+
slot="trigger"
|
|
214
|
+
class="trigger-button"
|
|
215
|
+
type="button"
|
|
216
|
+
aria-label="Add attachment"
|
|
217
|
+
?disabled=${this.disabled}
|
|
218
|
+
>
|
|
219
|
+
${paperclipIcon()}
|
|
220
|
+
</button>
|
|
221
|
+
${this.capabilities.map((capability) => {
|
|
222
|
+
const meta = CAPABILITY_META[capability];
|
|
223
|
+
return html `
|
|
224
|
+
<lyra-menu-item value=${capability}>
|
|
225
|
+
<span slot="icon">${meta.icon()}</span>
|
|
226
|
+
${meta.menuLabel}
|
|
227
|
+
</lyra-menu-item>
|
|
228
|
+
`;
|
|
229
|
+
})}
|
|
230
|
+
</lyra-menu>
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
render() {
|
|
234
|
+
const single = this.capabilities.length === 1;
|
|
235
|
+
const multi = this.capabilities.length > 1;
|
|
236
|
+
return html `
|
|
237
|
+
${single ? this.renderSingleTrigger(this.capabilities[0]) : nothing}
|
|
238
|
+
${multi ? this.renderMenu() : nothing}
|
|
239
|
+
${this.hasFileCapability ? this.renderHiddenInput() : nothing}
|
|
240
|
+
`;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
__decorate([
|
|
244
|
+
property({ attribute: false })
|
|
245
|
+
], LyraAttachmentTrigger.prototype, "capabilities", void 0);
|
|
246
|
+
__decorate([
|
|
247
|
+
property()
|
|
248
|
+
], LyraAttachmentTrigger.prototype, "accept", void 0);
|
|
249
|
+
__decorate([
|
|
250
|
+
property({ type: Boolean, reflect: true })
|
|
251
|
+
], LyraAttachmentTrigger.prototype, "multiple", void 0);
|
|
252
|
+
__decorate([
|
|
253
|
+
property({ type: Boolean, reflect: true })
|
|
254
|
+
], LyraAttachmentTrigger.prototype, "disabled", void 0);
|
|
255
|
+
__decorate([
|
|
256
|
+
query('input[type="file"]')
|
|
257
|
+
], LyraAttachmentTrigger.prototype, "inputEl", void 0);
|
|
258
|
+
defineElement('attachment-trigger', LyraAttachmentTrigger);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
/* Fully transparent to layout, matching lyra-menu's own :host — the
|
|
4
|
+
visible/clickable surface is entirely the rendered button (or, in the
|
|
5
|
+
multi-capability case, lyra-menu's own display:contents trigger wrapper
|
|
6
|
+
around that same button), so this host never contributes a stray box a
|
|
7
|
+
composer's leading slot would otherwise have to fight with margin/
|
|
8
|
+
inline-block quirks to line up against the textarea. */
|
|
9
|
+
:host {
|
|
10
|
+
display: contents;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Shared visual treatment for both the single-capability button
|
|
14
|
+
([part='trigger']) and the multi-capability button slotted into
|
|
15
|
+
lyra-menu's own trigger slot -- the latter can't itself carry
|
|
16
|
+
part='trigger' (that name is reserved for the single-capability case,
|
|
17
|
+
so a consumer's ::part(trigger) selector unambiguously targets exactly
|
|
18
|
+
one button), so both buttons share this plain class instead of
|
|
19
|
+
duplicating the same declaration block twice. */
|
|
20
|
+
.trigger-button {
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
flex: 0 0 auto;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
box-sizing: border-box;
|
|
26
|
+
/* Compact per the class doc -- capped well below the library's general
|
|
27
|
+
--lyra-icon-button-size (meant for a standalone icon-only button) so
|
|
28
|
+
this sits comfortably inside a composer's leading slot alongside a
|
|
29
|
+
textarea, matching lyra-combobox's clear-button / lyra-select's
|
|
30
|
+
toggle sizing convention. */
|
|
31
|
+
min-inline-size: min(var(--lyra-icon-button-size), 1.75rem);
|
|
32
|
+
min-block-size: min(var(--lyra-icon-button-size), 1.75rem);
|
|
33
|
+
padding: 0;
|
|
34
|
+
border: none;
|
|
35
|
+
border-radius: calc(var(--lyra-radius) * 0.6);
|
|
36
|
+
background: transparent;
|
|
37
|
+
color: var(--lyra-color-text-quiet);
|
|
38
|
+
font: inherit;
|
|
39
|
+
font-size: 1.125rem;
|
|
40
|
+
line-height: 1;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
-webkit-tap-highlight-color: transparent;
|
|
43
|
+
transition:
|
|
44
|
+
background-color var(--lyra-transition-fast),
|
|
45
|
+
color var(--lyra-transition-fast);
|
|
46
|
+
}
|
|
47
|
+
.trigger-button:hover:not(:disabled) {
|
|
48
|
+
background: color-mix(in srgb, var(--lyra-color-text) 8%, transparent);
|
|
49
|
+
color: var(--lyra-color-text);
|
|
50
|
+
}
|
|
51
|
+
.trigger-button:focus-visible {
|
|
52
|
+
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
53
|
+
outline-offset: var(--lyra-focus-ring-offset);
|
|
54
|
+
}
|
|
55
|
+
.trigger-button:disabled {
|
|
56
|
+
cursor: not-allowed;
|
|
57
|
+
opacity: var(--lyra-opacity-disabled);
|
|
58
|
+
}
|
|
59
|
+
.trigger-button svg {
|
|
60
|
+
display: block;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@media (prefers-reduced-motion: reduce) {
|
|
64
|
+
.trigger-button {
|
|
65
|
+
transition: none !important;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
@@ -70,11 +70,21 @@ export class LyraBoxPlot extends LyraElement {
|
|
|
70
70
|
// case, so this must gate on its resolved value — mirroring the correct,
|
|
71
71
|
// established pattern in `LyraChart.connectedCallback()` — instead of
|
|
72
72
|
// unconditionally re-awaiting the already-cached `loadChartJs()` promise.
|
|
73
|
+
//
|
|
74
|
+
// Also guards against a disconnect while either lazy peer import is still
|
|
75
|
+
// in flight: `this.isConnected` is re-checked after each `await` gap, so a
|
|
76
|
+
// `<lyra-box-plot>` removed before the load settles never constructs a
|
|
77
|
+
// `Chart` bound to a (possibly detached) canvas.
|
|
73
78
|
async onBoxPlotPluginLoaded(boxMod) {
|
|
79
|
+
if (!this.isConnected)
|
|
80
|
+
return;
|
|
74
81
|
this.loading = false;
|
|
75
82
|
if (!boxMod)
|
|
76
83
|
return;
|
|
77
|
-
|
|
84
|
+
const chartMod = await loadChartJs();
|
|
85
|
+
if (!this.isConnected)
|
|
86
|
+
return;
|
|
87
|
+
this.chartJsModule = chartMod ?? undefined;
|
|
78
88
|
this.draw();
|
|
79
89
|
}
|
|
80
90
|
disconnectedCallback() {
|