@aceshooting/lyra-ui 1.2.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -14
- package/custom-elements.json +30279 -12124
- package/dist/components/app-rail/app-rail-item.d.ts +30 -0
- package/dist/components/app-rail/app-rail-item.js +68 -0
- package/dist/components/app-rail/app-rail-item.styles.d.ts +1 -0
- package/dist/components/app-rail/app-rail-item.styles.js +65 -0
- package/dist/components/app-rail/app-rail.d.ts +168 -0
- package/dist/components/app-rail/app-rail.js +419 -0
- package/dist/components/app-rail/app-rail.styles.d.ts +1 -0
- package/dist/components/app-rail/app-rail.styles.js +128 -0
- package/dist/components/attachment-chip/attachment-chip.d.ts +141 -0
- package/dist/components/attachment-chip/attachment-chip.js +356 -0
- package/dist/components/attachment-chip/attachment-chip.styles.d.ts +1 -0
- package/dist/components/attachment-chip/attachment-chip.styles.js +184 -0
- package/dist/components/attachment-trigger/attachment-trigger.d.ts +96 -0
- package/dist/components/attachment-trigger/attachment-trigger.js +270 -0
- package/dist/components/attachment-trigger/attachment-trigger.styles.d.ts +1 -0
- package/dist/components/attachment-trigger/attachment-trigger.styles.js +90 -0
- package/dist/components/chart/bar-chart.js +2 -18
- package/dist/components/chart/box-plot.d.ts +25 -1
- package/dist/components/chart/box-plot.js +147 -7
- package/dist/components/chart/box-plot.styles.js +13 -0
- package/dist/components/chart/bubble-chart.js +2 -18
- package/dist/components/chart/chart-loader.d.ts +44 -13
- package/dist/components/chart/chart-loader.js +65 -18
- package/dist/components/chart/chart.d.ts +55 -12
- package/dist/components/chart/chart.js +247 -49
- package/dist/components/chart/doughnut-chart.js +2 -18
- package/dist/components/chart/histogram-bin.d.ts +7 -1
- package/dist/components/chart/histogram-bin.js +32 -14
- package/dist/components/chart/histogram.js +8 -16
- package/dist/components/chart/line-chart.js +2 -18
- package/dist/components/chart/lite-chart.d.ts +134 -3
- package/dist/components/chart/lite-chart.js +382 -67
- package/dist/components/chart/lite-chart.styles.js +9 -0
- package/dist/components/chart/pie-chart.js +2 -18
- package/dist/components/chart/polar-area-chart.js +2 -18
- package/dist/components/chart/radar-chart.js +2 -18
- package/dist/components/chart/scatter-chart.js +2 -18
- package/dist/components/chat-composer/chat-composer.d.ts +133 -0
- package/dist/components/chat-composer/chat-composer.js +366 -0
- package/dist/components/chat-composer/chat-composer.styles.d.ts +1 -0
- package/dist/components/chat-composer/chat-composer.styles.js +145 -0
- package/dist/components/chat-message/chat-message.d.ts +141 -0
- package/dist/components/chat-message/chat-message.js +331 -0
- package/dist/components/chat-message/chat-message.styles.d.ts +1 -0
- package/dist/components/chat-message/chat-message.styles.js +203 -0
- package/dist/components/checkbox/checkbox.d.ts +117 -0
- package/dist/components/checkbox/checkbox.js +353 -0
- package/dist/components/checkbox/checkbox.styles.d.ts +1 -0
- package/dist/components/checkbox/checkbox.styles.js +77 -0
- package/dist/components/chip/chip-group.d.ts +56 -0
- package/dist/components/chip/chip-group.js +130 -0
- package/dist/components/chip/chip-group.styles.d.ts +1 -0
- package/dist/components/chip/chip-group.styles.js +57 -0
- package/dist/components/chip/chip.d.ts +64 -0
- package/dist/components/chip/chip.js +122 -0
- package/dist/components/chip/chip.styles.d.ts +1 -0
- package/dist/components/chip/chip.styles.js +115 -0
- package/dist/components/citation-badge/citation-badge.d.ts +113 -0
- package/dist/components/citation-badge/citation-badge.js +318 -0
- package/dist/components/citation-badge/citation-badge.styles.d.ts +1 -0
- package/dist/components/citation-badge/citation-badge.styles.js +96 -0
- package/dist/components/code-block/code-block.d.ts +127 -0
- package/dist/components/code-block/code-block.js +382 -0
- package/dist/components/code-block/code-block.styles.d.ts +1 -0
- package/dist/components/code-block/code-block.styles.js +187 -0
- package/dist/components/code-block/code-loader.d.ts +87 -0
- package/dist/components/code-block/code-loader.js +142 -0
- package/dist/components/combobox/combobox.d.ts +65 -6
- package/dist/components/combobox/combobox.js +258 -48
- package/dist/components/combobox/combobox.styles.js +3 -3
- package/dist/components/combobox/option.d.ts +5 -1
- package/dist/components/combobox/option.js +35 -0
- package/dist/components/context-meter/context-meter.d.ts +53 -0
- package/dist/components/context-meter/context-meter.js +159 -0
- package/dist/components/context-meter/context-meter.styles.d.ts +1 -0
- package/dist/components/context-meter/context-meter.styles.js +114 -0
- package/dist/components/conversation-item/conversation-item.d.ts +125 -0
- package/dist/components/conversation-item/conversation-item.js +331 -0
- package/dist/components/conversation-item/conversation-item.styles.d.ts +1 -0
- package/dist/components/conversation-item/conversation-item.styles.js +155 -0
- package/dist/components/date-picker/calendar-core.d.ts +24 -0
- package/dist/components/date-picker/calendar-core.js +51 -4
- package/dist/components/date-picker/date-input.d.ts +100 -9
- package/dist/components/date-picker/date-input.js +383 -66
- package/dist/components/date-picker/date-picker.d.ts +35 -4
- package/dist/components/date-picker/date-picker.js +171 -44
- package/dist/components/dialog/confirm.d.ts +40 -0
- package/dist/components/dialog/confirm.js +76 -0
- package/dist/components/dialog/dialog.d.ts +129 -0
- package/dist/components/dialog/dialog.js +288 -0
- package/dist/components/dialog/dialog.styles.d.ts +1 -0
- package/dist/components/dialog/dialog.styles.js +96 -0
- package/dist/components/dock-panel/dock-panel.d.ts +142 -0
- package/dist/components/dock-panel/dock-panel.js +359 -0
- package/dist/components/dock-panel/dock-panel.styles.d.ts +1 -0
- package/dist/components/dock-panel/dock-panel.styles.js +159 -0
- package/dist/components/document-preview/document-preview.d.ts +143 -0
- package/dist/components/document-preview/document-preview.js +388 -0
- package/dist/components/document-preview/document-preview.styles.d.ts +1 -0
- package/dist/components/document-preview/document-preview.styles.js +191 -0
- package/dist/components/empty/empty.d.ts +1 -2
- package/dist/components/empty/empty.js +18 -12
- package/dist/components/empty/empty.styles.js +0 -3
- package/dist/components/export-button/csv.js +1 -1
- package/dist/components/export-button/export-button.d.ts +12 -0
- package/dist/components/export-button/export-button.js +35 -5
- package/dist/components/export-button/export-button.styles.js +5 -1
- package/dist/components/file-input/accept.js +2 -0
- package/dist/components/file-input/file-input.d.ts +10 -1
- package/dist/components/file-input/file-input.js +36 -5
- package/dist/components/flag/flag.d.ts +29 -13
- package/dist/components/flag/flag.js +54 -14
- package/dist/components/flag/flag.styles.js +1 -1
- package/dist/components/flag/language-map.d.ts +4 -1
- package/dist/components/flag/language-map.js +6 -3
- package/dist/components/gauge/gauge.d.ts +10 -1
- package/dist/components/gauge/gauge.js +41 -13
- package/dist/components/generation-status/generation-status.d.ts +117 -0
- package/dist/components/generation-status/generation-status.js +327 -0
- package/dist/components/generation-status/generation-status.styles.d.ts +1 -0
- package/dist/components/generation-status/generation-status.styles.js +84 -0
- package/dist/components/graph/graph.d.ts +37 -3
- package/dist/components/graph/graph.js +132 -20
- package/dist/components/heatmap/calendar-grid.d.ts +19 -7
- package/dist/components/heatmap/calendar-grid.js +42 -18
- package/dist/components/heatmap/heatmap-scale.d.ts +11 -1
- package/dist/components/heatmap/heatmap-scale.js +14 -2
- package/dist/components/heatmap/heatmap.d.ts +227 -12
- package/dist/components/heatmap/heatmap.js +488 -93
- package/dist/components/json-viewer/json-viewer.d.ts +70 -0
- package/dist/components/json-viewer/json-viewer.js +361 -0
- package/dist/components/json-viewer/json-viewer.styles.d.ts +1 -0
- package/dist/components/json-viewer/json-viewer.styles.js +177 -0
- package/dist/components/kbd/kbd.d.ts +77 -0
- package/dist/components/kbd/kbd.js +231 -0
- package/dist/components/kbd/kbd.styles.d.ts +1 -0
- package/dist/components/kbd/kbd.styles.js +52 -0
- package/dist/components/live-region/live-region.d.ts +90 -0
- package/dist/components/live-region/live-region.js +189 -0
- package/dist/components/live-region/live-region.styles.d.ts +1 -0
- package/dist/components/live-region/live-region.styles.js +10 -0
- package/dist/components/map/map.d.ts +32 -7
- package/dist/components/map/map.js +133 -32
- package/dist/components/markdown/markdown-loader.d.ts +58 -0
- package/dist/components/markdown/markdown-loader.js +77 -0
- package/dist/components/markdown/markdown.d.ts +119 -0
- package/dist/components/markdown/markdown.js +389 -0
- package/dist/components/markdown/markdown.styles.d.ts +1 -0
- package/dist/components/markdown/markdown.styles.js +88 -0
- package/dist/components/media-card/media-card.d.ts +130 -0
- package/dist/components/media-card/media-card.js +273 -0
- package/dist/components/media-card/media-card.styles.d.ts +1 -0
- package/dist/components/media-card/media-card.styles.js +132 -0
- package/dist/components/mention-popover/mention-popover.d.ts +203 -0
- package/dist/components/mention-popover/mention-popover.js +493 -0
- package/dist/components/mention-popover/mention-popover.styles.d.ts +1 -0
- package/dist/components/mention-popover/mention-popover.styles.js +101 -0
- package/dist/components/menu/menu-item.d.ts +91 -0
- package/dist/components/menu/menu-item.js +206 -0
- package/dist/components/menu/menu-item.styles.d.ts +1 -0
- package/dist/components/menu/menu-item.styles.js +75 -0
- package/dist/components/menu/menu.d.ts +167 -0
- package/dist/components/menu/menu.js +461 -0
- package/dist/components/menu/menu.styles.d.ts +1 -0
- package/dist/components/menu/menu.styles.js +67 -0
- package/dist/components/model-select/model-select.d.ts +170 -0
- package/dist/components/model-select/model-select.js +588 -0
- package/dist/components/model-select/model-select.styles.d.ts +1 -0
- package/dist/components/model-select/model-select.styles.js +203 -0
- package/dist/components/model-settings-panel/model-settings-panel.d.ts +93 -0
- package/dist/components/model-settings-panel/model-settings-panel.js +209 -0
- package/dist/components/model-settings-panel/model-settings-panel.styles.d.ts +1 -0
- package/dist/components/model-settings-panel/model-settings-panel.styles.js +82 -0
- package/dist/components/playback/playback.d.ts +19 -3
- package/dist/components/playback/playback.js +109 -33
- package/dist/components/playback/playback.styles.js +6 -1
- package/dist/components/responsive-panel/responsive-panel.d.ts +163 -0
- package/dist/components/responsive-panel/responsive-panel.js +363 -0
- package/dist/components/responsive-panel/responsive-panel.styles.d.ts +1 -0
- package/dist/components/responsive-panel/responsive-panel.styles.js +103 -0
- package/dist/components/result-card/result-card.d.ts +50 -0
- package/dist/components/result-card/result-card.js +89 -0
- package/dist/components/result-card/result-card.styles.d.ts +1 -0
- package/dist/components/result-card/result-card.styles.js +49 -0
- package/dist/components/result-card/result-field.d.ts +36 -0
- package/dist/components/result-card/result-field.js +87 -0
- package/dist/components/result-card/result-field.styles.d.ts +1 -0
- package/dist/components/result-card/result-field.styles.js +32 -0
- package/dist/components/select/select.d.ts +84 -4
- package/dist/components/select/select.js +251 -36
- package/dist/components/skeleton/skeleton.d.ts +3 -0
- package/dist/components/skeleton/skeleton.js +7 -1
- package/dist/components/skeleton/skeleton.styles.js +5 -4
- package/dist/components/slider/slider.d.ts +141 -0
- package/dist/components/slider/slider.js +467 -0
- package/dist/components/slider/slider.styles.d.ts +1 -0
- package/dist/components/slider/slider.styles.js +87 -0
- package/dist/components/source-card/source-card.d.ts +104 -0
- package/dist/components/source-card/source-card.js +195 -0
- package/dist/components/source-card/source-card.styles.d.ts +1 -0
- package/dist/components/source-card/source-card.styles.js +69 -0
- package/dist/components/source-list/source-list.d.ts +63 -0
- package/dist/components/source-list/source-list.js +130 -0
- package/dist/components/source-list/source-list.styles.d.ts +1 -0
- package/dist/components/source-list/source-list.styles.js +59 -0
- package/dist/components/sparkline/sparkline.js +58 -20
- package/dist/components/split/split.d.ts +224 -5
- package/dist/components/split/split.js +617 -43
- package/dist/components/split/split.styles.js +47 -0
- package/dist/components/stat/stat.d.ts +15 -4
- package/dist/components/stat/stat.js +53 -12
- package/dist/components/stream-status/stream-status.d.ts +126 -0
- package/dist/components/stream-status/stream-status.js +292 -0
- package/dist/components/stream-status/stream-status.styles.d.ts +1 -0
- package/dist/components/stream-status/stream-status.styles.js +103 -0
- package/dist/components/streaming-text/streaming-text.d.ts +104 -0
- package/dist/components/streaming-text/streaming-text.js +224 -0
- package/dist/components/streaming-text/streaming-text.styles.d.ts +1 -0
- package/dist/components/streaming-text/streaming-text.styles.js +63 -0
- package/dist/components/switch/switch.d.ts +103 -0
- package/dist/components/switch/switch.js +250 -0
- package/dist/components/switch/switch.styles.d.ts +1 -0
- package/dist/components/switch/switch.styles.js +75 -0
- package/dist/components/table/table.d.ts +89 -5
- package/dist/components/table/table.js +243 -26
- package/dist/components/table/table.styles.js +6 -1
- package/dist/components/tabs/tabs.d.ts +74 -0
- package/dist/components/tabs/tabs.js +254 -0
- package/dist/components/tabs/tabs.styles.d.ts +1 -0
- package/dist/components/tabs/tabs.styles.js +74 -0
- package/dist/components/thinking-panel/thinking-panel.d.ts +123 -0
- package/dist/components/thinking-panel/thinking-panel.js +260 -0
- package/dist/components/thinking-panel/thinking-panel.styles.d.ts +1 -0
- package/dist/components/thinking-panel/thinking-panel.styles.js +123 -0
- package/dist/components/time-range/time-range.d.ts +59 -2
- package/dist/components/time-range/time-range.js +163 -67
- package/dist/components/toast/toast-item.d.ts +12 -2
- package/dist/components/toast/toast-item.js +106 -44
- package/dist/components/toast/toast-item.styles.js +59 -28
- package/dist/components/toast/toast.js +17 -5
- package/dist/components/toast/toaster.js +10 -1
- package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +131 -0
- package/dist/components/tool-approval-dialog/tool-approval-dialog.js +329 -0
- package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.d.ts +1 -0
- package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +160 -0
- package/dist/components/tool-call-chip/tool-call-chip.d.ts +105 -0
- package/dist/components/tool-call-chip/tool-call-chip.js +349 -0
- package/dist/components/tool-call-chip/tool-call-chip.styles.d.ts +1 -0
- package/dist/components/tool-call-chip/tool-call-chip.styles.js +203 -0
- package/dist/components/tool-param-form/tool-param-form.d.ts +206 -0
- package/dist/components/tool-param-form/tool-param-form.js +610 -0
- package/dist/components/tool-param-form/tool-param-form.styles.d.ts +1 -0
- package/dist/components/tool-param-form/tool-param-form.styles.js +75 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +122 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.js +358 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.styles.d.ts +1 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +176 -0
- package/dist/components/tool-result-view/registry.d.ts +73 -0
- package/dist/components/tool-result-view/registry.js +89 -0
- package/dist/components/tool-result-view/tool-result-view.d.ts +58 -0
- package/dist/components/tool-result-view/tool-result-view.js +152 -0
- package/dist/components/tool-result-view/tool-result-view.styles.d.ts +1 -0
- package/dist/components/tool-result-view/tool-result-view.styles.js +13 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +151 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.js +350 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.styles.d.ts +1 -0
- package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +191 -0
- package/dist/components/tree/tree-node.d.ts +15 -3
- package/dist/components/tree/tree-node.js +20 -7
- package/dist/components/tree/tree.d.ts +25 -10
- package/dist/components/tree/tree.js +39 -31
- package/dist/components/typing-indicator/typing-indicator.d.ts +70 -0
- package/dist/components/typing-indicator/typing-indicator.js +108 -0
- package/dist/components/typing-indicator/typing-indicator.styles.d.ts +1 -0
- package/dist/components/typing-indicator/typing-indicator.styles.js +132 -0
- package/dist/components/virtual-list/virtual-list.d.ts +210 -0
- package/dist/components/virtual-list/virtual-list.js +607 -0
- package/dist/components/virtual-list/virtual-list.styles.d.ts +1 -0
- package/dist/components/virtual-list/virtual-list.styles.js +56 -0
- package/dist/components/widget/widget.d.ts +5 -4
- package/dist/components/widget/widget.js +54 -120
- package/dist/components/widget/widget.styles.js +8 -2
- package/dist/components/word-cloud/word-cloud-layout.d.ts +7 -0
- package/dist/components/word-cloud/word-cloud-layout.js +29 -2
- package/dist/components/word-cloud/word-cloud.d.ts +28 -2
- package/dist/components/word-cloud/word-cloud.js +69 -19
- package/dist/components/word-cloud/word-cloud.styles.js +16 -3
- package/dist/internal/anchored-validity.d.ts +1 -0
- package/dist/internal/anchored-validity.js +86 -0
- package/dist/internal/announcer.d.ts +57 -0
- package/dist/internal/announcer.js +71 -0
- package/dist/internal/form-associated.d.ts +8 -0
- package/dist/internal/form-associated.js +98 -15
- package/dist/internal/group-by-recency.d.ts +50 -0
- package/dist/internal/group-by-recency.js +80 -0
- package/dist/internal/numbers.d.ts +12 -0
- package/dist/internal/numbers.js +26 -0
- package/dist/internal/overlay-manager.d.ts +51 -0
- package/dist/internal/overlay-manager.js +523 -0
- package/dist/internal/positioner.js +27 -3
- package/dist/internal/rtl.d.ts +23 -0
- package/dist/internal/rtl.js +28 -0
- package/dist/internal/safe-url.d.ts +12 -0
- package/dist/internal/safe-url.js +41 -0
- package/dist/internal/scroll-lock.d.ts +10 -5
- package/dist/internal/scroll-lock.js +30 -14
- package/dist/internal/tokens.styles.js +22 -10
- package/dist/lyra.d.ts +133 -31
- package/dist/lyra.js +96 -26
- package/llms-full.txt +4546 -183
- package/llms.txt +21 -5
- package/package.json +41 -6
- package/dist/components/chart/bar-chart.stories.d.ts +0 -5
- package/dist/components/chart/bar-chart.stories.js +0 -20
- package/dist/components/chart/box-plot.stories.d.ts +0 -5
- package/dist/components/chart/box-plot.stories.js +0 -29
- package/dist/components/chart/bubble-chart.stories.d.ts +0 -5
- package/dist/components/chart/bubble-chart.stories.js +0 -26
- package/dist/components/chart/chart.stories.d.ts +0 -32
- package/dist/components/chart/chart.stories.js +0 -141
- package/dist/components/chart/doughnut-chart.stories.d.ts +0 -5
- package/dist/components/chart/doughnut-chart.stories.js +0 -26
- package/dist/components/chart/histogram.stories.d.ts +0 -5
- package/dist/components/chart/histogram.stories.js +0 -17
- package/dist/components/chart/line-chart.stories.d.ts +0 -22
- package/dist/components/chart/line-chart.stories.js +0 -99
- package/dist/components/chart/lite-chart.stories.d.ts +0 -14
- package/dist/components/chart/lite-chart.stories.js +0 -114
- package/dist/components/chart/pie-chart.stories.d.ts +0 -5
- package/dist/components/chart/pie-chart.stories.js +0 -26
- package/dist/components/chart/polar-area-chart.stories.d.ts +0 -5
- package/dist/components/chart/polar-area-chart.stories.js +0 -20
- package/dist/components/chart/radar-chart.stories.d.ts +0 -5
- package/dist/components/chart/radar-chart.stories.js +0 -20
- package/dist/components/chart/scatter-chart.stories.d.ts +0 -5
- package/dist/components/chart/scatter-chart.stories.js +0 -31
- package/dist/components/combobox/combobox.stories.d.ts +0 -24
- package/dist/components/combobox/combobox.stories.js +0 -102
- package/dist/components/date-picker/date-input.stories.d.ts +0 -10
- package/dist/components/date-picker/date-input.stories.js +0 -48
- package/dist/components/date-picker/date-picker.stories.d.ts +0 -10
- package/dist/components/date-picker/date-picker.stories.js +0 -25
- package/dist/components/empty/empty.stories.d.ts +0 -7
- package/dist/components/empty/empty.stories.js +0 -34
- package/dist/components/export-button/export-button.stories.d.ts +0 -7
- package/dist/components/export-button/export-button.stories.js +0 -37
- package/dist/components/file-input/file-input.stories.d.ts +0 -7
- package/dist/components/file-input/file-input.stories.js +0 -19
- package/dist/components/flag/flag.stories.d.ts +0 -6
- package/dist/components/flag/flag.stories.js +0 -31
- package/dist/components/gauge/gauge.stories.d.ts +0 -8
- package/dist/components/gauge/gauge.stories.js +0 -19
- package/dist/components/graph/graph.stories.d.ts +0 -8
- package/dist/components/graph/graph.stories.js +0 -68
- package/dist/components/heatmap/heatmap.stories.d.ts +0 -27
- package/dist/components/heatmap/heatmap.stories.js +0 -179
- package/dist/components/map/map.stories.d.ts +0 -15
- package/dist/components/map/map.stories.js +0 -135
- package/dist/components/playback/playback.stories.d.ts +0 -7
- package/dist/components/playback/playback.stories.js +0 -16
- package/dist/components/select/select.stories.d.ts +0 -21
- package/dist/components/select/select.stories.js +0 -91
- package/dist/components/skeleton/skeleton.stories.d.ts +0 -5
- package/dist/components/skeleton/skeleton.stories.js +0 -16
- package/dist/components/sparkline/sparkline.stories.d.ts +0 -11
- package/dist/components/sparkline/sparkline.stories.js +0 -39
- package/dist/components/split/split.stories.d.ts +0 -7
- package/dist/components/split/split.stories.js +0 -36
- package/dist/components/stat/stat.stories.d.ts +0 -9
- package/dist/components/stat/stat.stories.js +0 -81
- package/dist/components/table/table.stories.d.ts +0 -12
- package/dist/components/table/table.stories.js +0 -67
- package/dist/components/time-range/time-range.stories.d.ts +0 -8
- package/dist/components/time-range/time-range.stories.js +0 -26
- package/dist/components/toast/toast.stories.d.ts +0 -8
- package/dist/components/toast/toast.stories.js +0 -72
- package/dist/components/tree/tree.stories.d.ts +0 -9
- package/dist/components/tree/tree.stories.js +0 -52
- package/dist/components/widget/widget.stories.d.ts +0 -9
- package/dist/components/widget/widget.stories.js +0 -74
- package/dist/components/word-cloud/word-cloud.stories.d.ts +0 -10
- package/dist/components/word-cloud/word-cloud.stories.js +0 -55
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
-
import type { Map as MaplibreMap, StyleSpecification } from 'maplibre-gl';
|
|
3
2
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
4
3
|
import '../skeleton/skeleton.js';
|
|
5
4
|
export interface LegendEntry {
|
|
@@ -30,20 +29,34 @@ export interface MapMarker {
|
|
|
30
29
|
/**
|
|
31
30
|
* Rendered as the marker's popup content via maplibre-gl's
|
|
32
31
|
* `Popup.setHTML()` -- parsed as raw markup, inline event handlers
|
|
33
|
-
* included.
|
|
34
|
-
*
|
|
32
|
+
* included. This is the library's one explicit unsafe-HTML escape hatch:
|
|
33
|
+
* only ever pass trusted content, and sanitize anything derived from user
|
|
34
|
+
* input before assigning it here. Prefer `label` (rendered via the safe
|
|
35
|
+
* `Popup.setText()`) whenever the content is plain text.
|
|
35
36
|
*/
|
|
36
|
-
|
|
37
|
+
unsafeHtml?: string;
|
|
37
38
|
}
|
|
38
39
|
/**
|
|
39
40
|
* `<lyra-map>` — a maplibre-gl wrapper with a declarative legend and
|
|
40
41
|
* choropleth GeoJSON layer, plus a raw `map` escape hatch. Requires the
|
|
41
42
|
* optional peer dep `maplibre-gl` (consumers also import its CSS once).
|
|
42
43
|
*
|
|
44
|
+
* The underlying `maplibregl.Map` — and the WebGL context it opens — isn't
|
|
45
|
+
* constructed until this element is first visible in the viewport (tracked
|
|
46
|
+
* via `IntersectionObserver`), even once the `maplibre-gl` peer dependency
|
|
47
|
+
* has finished loading. Browsers hard-cap concurrent WebGL contexts per
|
|
48
|
+
* page, so a grid/dashboard of many `<lyra-map>` instances only constructs
|
|
49
|
+
* the ones actually on-screen instead of racing to exhaust that budget the
|
|
50
|
+
* instant each one mounts. `map` stays `undefined` (and `lyra-map-load`
|
|
51
|
+
* doesn't fire) until construction actually happens.
|
|
52
|
+
*
|
|
43
53
|
* @customElement lyra-map
|
|
44
54
|
* @event lyra-map-load - Fired once the underlying maplibregl.Map loads.
|
|
45
55
|
* @event lyra-map-click - `detail: { lngLat, feature? }`.
|
|
46
|
-
* @csspart base
|
|
56
|
+
* @csspart base - The map wrapper.
|
|
57
|
+
* @csspart container - The maplibre container.
|
|
58
|
+
* @csspart legend - The map legend.
|
|
59
|
+
* @csspart legend-swatch - A legend color swatch.
|
|
47
60
|
*
|
|
48
61
|
* ⚠️ The default `mapStyle` (when unset) uses OpenStreetMap's demo tile
|
|
49
62
|
* server, which is not suitable for production traffic — see the
|
|
@@ -54,12 +67,14 @@ export declare class LyraMap extends LyraElement {
|
|
|
54
67
|
static styles: import("lit").CSSResultGroup[];
|
|
55
68
|
center: [number, number];
|
|
56
69
|
zoom: number;
|
|
57
|
-
mapStyle: StyleSpecification | string;
|
|
70
|
+
mapStyle: import('maplibre-gl').StyleSpecification | string;
|
|
58
71
|
legend: LegendEntry[];
|
|
59
72
|
choropleth?: ChoroplethLayer;
|
|
60
73
|
markers: MapMarker[];
|
|
61
74
|
/** True until the lazy-loaded `maplibre-gl` peer dependency has settled (success or failure). */
|
|
62
75
|
private loading;
|
|
76
|
+
private visible;
|
|
77
|
+
private intersectionObserver?;
|
|
63
78
|
private containerEl?;
|
|
64
79
|
private _map?;
|
|
65
80
|
private _styleLoaded;
|
|
@@ -67,11 +82,21 @@ export declare class LyraMap extends LyraElement {
|
|
|
67
82
|
private _appliedFillLayerId?;
|
|
68
83
|
private _maplibreModule?;
|
|
69
84
|
private _markerInstances;
|
|
85
|
+
private _markerColors;
|
|
70
86
|
private _connectGeneration;
|
|
71
87
|
/** The raw `maplibregl.Map` instance — escape hatch for anything this wrapper doesn't expose. */
|
|
72
|
-
get map():
|
|
88
|
+
get map(): import('maplibre-gl').Map | undefined;
|
|
73
89
|
connectedCallback(): void;
|
|
74
90
|
disconnectedCallback(): void;
|
|
91
|
+
/**
|
|
92
|
+
* Constructs the underlying `maplibregl.Map` — called once both the
|
|
93
|
+
* lazy-loaded `maplibre-gl` module has resolved and this element has been
|
|
94
|
+
* observed intersecting the viewport, whichever settles last. Idempotent
|
|
95
|
+
* (a no-op once `_map` already exists), so it's safe to call from both the
|
|
96
|
+
* `connectedCallback()` load path and the visibility path in `updated()`
|
|
97
|
+
* below without risking a double construction.
|
|
98
|
+
*/
|
|
99
|
+
private tryConstructMap;
|
|
75
100
|
protected updated(changed: PropertyValues): void;
|
|
76
101
|
private applyChoropleth;
|
|
77
102
|
/** Removes whatever choropleth layer/source is currently applied, if any. */
|
|
@@ -65,10 +65,22 @@ function sanitizeSwatchColor(color) {
|
|
|
65
65
|
* choropleth GeoJSON layer, plus a raw `map` escape hatch. Requires the
|
|
66
66
|
* optional peer dep `maplibre-gl` (consumers also import its CSS once).
|
|
67
67
|
*
|
|
68
|
+
* The underlying `maplibregl.Map` — and the WebGL context it opens — isn't
|
|
69
|
+
* constructed until this element is first visible in the viewport (tracked
|
|
70
|
+
* via `IntersectionObserver`), even once the `maplibre-gl` peer dependency
|
|
71
|
+
* has finished loading. Browsers hard-cap concurrent WebGL contexts per
|
|
72
|
+
* page, so a grid/dashboard of many `<lyra-map>` instances only constructs
|
|
73
|
+
* the ones actually on-screen instead of racing to exhaust that budget the
|
|
74
|
+
* instant each one mounts. `map` stays `undefined` (and `lyra-map-load`
|
|
75
|
+
* doesn't fire) until construction actually happens.
|
|
76
|
+
*
|
|
68
77
|
* @customElement lyra-map
|
|
69
78
|
* @event lyra-map-load - Fired once the underlying maplibregl.Map loads.
|
|
70
79
|
* @event lyra-map-click - `detail: { lngLat, feature? }`.
|
|
71
|
-
* @csspart base
|
|
80
|
+
* @csspart base - The map wrapper.
|
|
81
|
+
* @csspart container - The maplibre container.
|
|
82
|
+
* @csspart legend - The map legend.
|
|
83
|
+
* @csspart legend-swatch - A legend color swatch.
|
|
72
84
|
*
|
|
73
85
|
* ⚠️ The default `mapStyle` (when unset) uses OpenStreetMap's demo tile
|
|
74
86
|
* server, which is not suitable for production traffic — see the
|
|
@@ -85,6 +97,14 @@ export class LyraMap extends LyraElement {
|
|
|
85
97
|
this.markers = [];
|
|
86
98
|
/** True until the lazy-loaded `maplibre-gl` peer dependency has settled (success or failure). */
|
|
87
99
|
this.loading = true;
|
|
100
|
+
// Gates the actual `new mod.Map(...)` construction (see `tryConstructMap()`)
|
|
101
|
+
// -- starts `false` so a `<lyra-map>` mounted off-screen doesn't open a
|
|
102
|
+
// WebGL context before it's ever seen, and only flips `true` once the
|
|
103
|
+
// IntersectionObserver below reports this element actually intersecting
|
|
104
|
+
// the viewport. Defaults `true` outright when `IntersectionObserver` isn't
|
|
105
|
+
// available at all (fail open, matching `lyra-chart`'s own fallback)
|
|
106
|
+
// rather than gating construction on an observer that will never fire.
|
|
107
|
+
this.visible = typeof IntersectionObserver === 'undefined';
|
|
88
108
|
// Tracks whether the style has fired its initial 'load' (i.e. addSource/
|
|
89
109
|
// addLayer/setPaintProperty are now safe to call), rather than re-querying
|
|
90
110
|
// `this._map.isStyleLoaded()`: that also reflects in-flight *tile* loading
|
|
@@ -93,6 +113,14 @@ export class LyraMap extends LyraElement {
|
|
|
93
113
|
// choropleth updates from ever re-running.
|
|
94
114
|
this._styleLoaded = false;
|
|
95
115
|
this._markerInstances = new Map();
|
|
116
|
+
// The installed maplibre-gl's `Marker` class has no `setColor()` (verified
|
|
117
|
+
// against its shipped `.d.ts` -- `color` is only ever consumed by the
|
|
118
|
+
// constructor), so an id-matched marker whose `color` changes can't be
|
|
119
|
+
// mutated in place; it has to be torn down and reconstructed instead. This
|
|
120
|
+
// tracks the color each currently-live marker instance was last
|
|
121
|
+
// constructed with, keyed the same as `_markerInstances`, so `applyMarkers`
|
|
122
|
+
// can detect that mismatch without re-deriving it from the DOM.
|
|
123
|
+
this._markerColors = new Map();
|
|
96
124
|
// Bumped on every connectedCallback and captured by value in its
|
|
97
125
|
// loadMaplibre().then() closure below. A disconnect immediately followed
|
|
98
126
|
// by a reconnect (fast remounts, route/tab switches, etc.) before that
|
|
@@ -113,6 +141,17 @@ export class LyraMap extends LyraElement {
|
|
|
113
141
|
connectedCallback() {
|
|
114
142
|
super.connectedCallback();
|
|
115
143
|
const generation = ++this._connectGeneration;
|
|
144
|
+
// A reconnect always tears the map down in disconnectedCallback() below,
|
|
145
|
+
// so it needs its own fresh visibility read rather than trusting
|
|
146
|
+
// whatever `visible` was left at from before the previous disconnect.
|
|
147
|
+
this.visible = typeof IntersectionObserver === 'undefined';
|
|
148
|
+
if (typeof IntersectionObserver !== 'undefined') {
|
|
149
|
+
this.intersectionObserver = new IntersectionObserver((entries) => {
|
|
150
|
+
if (entries[0]?.isIntersecting)
|
|
151
|
+
this.visible = true;
|
|
152
|
+
});
|
|
153
|
+
this.intersectionObserver.observe(this);
|
|
154
|
+
}
|
|
116
155
|
void loadMaplibre().then(async (mod) => {
|
|
117
156
|
// A newer connectedCallback (disconnect + reconnect) already
|
|
118
157
|
// superseded this attempt while loadMaplibre()'s cached promise was
|
|
@@ -136,28 +175,7 @@ export class LyraMap extends LyraElement {
|
|
|
136
175
|
// cycle that happened during the `await` above.
|
|
137
176
|
if (generation !== this._connectGeneration || !this.containerEl || !this.isConnected)
|
|
138
177
|
return;
|
|
139
|
-
this.
|
|
140
|
-
container: this.containerEl,
|
|
141
|
-
style: this.mapStyle,
|
|
142
|
-
center: this.center,
|
|
143
|
-
zoom: this.zoom,
|
|
144
|
-
});
|
|
145
|
-
this._map.on('load', () => {
|
|
146
|
-
this._styleLoaded = true;
|
|
147
|
-
this.applyChoropleth();
|
|
148
|
-
this.applyMarkers();
|
|
149
|
-
this.emit('lyra-map-load');
|
|
150
|
-
});
|
|
151
|
-
this._map.on('click', (e) => {
|
|
152
|
-
const fillLayerId = this._appliedFillLayerId;
|
|
153
|
-
const features = fillLayerId && this._map.getLayer(fillLayerId)
|
|
154
|
-
? this._map.queryRenderedFeatures(e.point, { layers: [fillLayerId] })
|
|
155
|
-
: [];
|
|
156
|
-
this.emit('lyra-map-click', {
|
|
157
|
-
lngLat: [e.lngLat.lng, e.lngLat.lat],
|
|
158
|
-
feature: features[0],
|
|
159
|
-
});
|
|
160
|
-
});
|
|
178
|
+
this.tryConstructMap();
|
|
161
179
|
});
|
|
162
180
|
}
|
|
163
181
|
disconnectedCallback() {
|
|
@@ -167,15 +185,59 @@ export class LyraMap extends LyraElement {
|
|
|
167
185
|
this._styleLoaded = false;
|
|
168
186
|
this._appliedChoroplethSourceId = undefined;
|
|
169
187
|
this._appliedFillLayerId = undefined;
|
|
188
|
+
this.intersectionObserver?.disconnect();
|
|
189
|
+
this.intersectionObserver = undefined;
|
|
170
190
|
for (const marker of this._markerInstances.values())
|
|
171
191
|
marker.remove();
|
|
172
192
|
this._markerInstances.clear();
|
|
193
|
+
this._markerColors.clear();
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Constructs the underlying `maplibregl.Map` — called once both the
|
|
197
|
+
* lazy-loaded `maplibre-gl` module has resolved and this element has been
|
|
198
|
+
* observed intersecting the viewport, whichever settles last. Idempotent
|
|
199
|
+
* (a no-op once `_map` already exists), so it's safe to call from both the
|
|
200
|
+
* `connectedCallback()` load path and the visibility path in `updated()`
|
|
201
|
+
* below without risking a double construction.
|
|
202
|
+
*/
|
|
203
|
+
tryConstructMap() {
|
|
204
|
+
if (this._map || !this._maplibreModule || !this.containerEl || !this.visible || !this.isConnected)
|
|
205
|
+
return;
|
|
206
|
+
const mod = this._maplibreModule;
|
|
207
|
+
this._map = new mod.Map({
|
|
208
|
+
container: this.containerEl,
|
|
209
|
+
style: this.mapStyle,
|
|
210
|
+
center: this.center,
|
|
211
|
+
zoom: this.zoom,
|
|
212
|
+
});
|
|
213
|
+
this._map.on('load', () => {
|
|
214
|
+
this._styleLoaded = true;
|
|
215
|
+
this.applyChoropleth();
|
|
216
|
+
this.applyMarkers();
|
|
217
|
+
this.emit('lyra-map-load');
|
|
218
|
+
});
|
|
219
|
+
this._map.on('click', (e) => {
|
|
220
|
+
const fillLayerId = this._appliedFillLayerId;
|
|
221
|
+
const features = fillLayerId && this._map.getLayer(fillLayerId)
|
|
222
|
+
? this._map.queryRenderedFeatures(e.point, { layers: [fillLayerId] })
|
|
223
|
+
: [];
|
|
224
|
+
this.emit('lyra-map-click', {
|
|
225
|
+
lngLat: [e.lngLat.lng, e.lngLat.lat],
|
|
226
|
+
feature: features[0],
|
|
227
|
+
});
|
|
228
|
+
});
|
|
173
229
|
}
|
|
174
230
|
updated(changed) {
|
|
175
231
|
if (this.loading)
|
|
176
232
|
this.setAttribute('aria-busy', 'true');
|
|
177
233
|
else
|
|
178
234
|
this.removeAttribute('aria-busy');
|
|
235
|
+
// Became visible after the maplibre-gl module had already loaded (the
|
|
236
|
+
// reverse order — module loads first, visibility follows — is the
|
|
237
|
+
// common case and is instead handled at the end of the
|
|
238
|
+
// `loadMaplibre().then()` chain in connectedCallback() above).
|
|
239
|
+
if (changed.has('visible') && this.visible)
|
|
240
|
+
this.tryConstructMap();
|
|
179
241
|
if (changed.has('mapStyle') && this._map) {
|
|
180
242
|
// A style change wipes every layer/source maplibre-gl knows about, so
|
|
181
243
|
// the previously-applied choropleth bookkeeping is stale the instant
|
|
@@ -224,7 +286,16 @@ export class LyraMap extends LyraElement {
|
|
|
224
286
|
existingSource.setData(geojson);
|
|
225
287
|
}
|
|
226
288
|
else {
|
|
227
|
-
|
|
289
|
+
// No `promoteId` -- maplibre-gl falls back to its own default id
|
|
290
|
+
// resolution (the standard top-level GeoJSON `Feature.id`, when
|
|
291
|
+
// present). A hardcoded `promoteId: 'id'` here would instead require
|
|
292
|
+
// every feature to *also* duplicate its id inside `properties.id`,
|
|
293
|
+
// silently discarding the real top-level `id` otherwise and breaking
|
|
294
|
+
// `feature.id` on `lyra-map-click` for the common case. Nothing in this
|
|
295
|
+
// component actually needs feature-state promotion today; if that's
|
|
296
|
+
// added later it should be driven by an explicit, documented
|
|
297
|
+
// `ChoroplethLayer` option (e.g. `idField`), not a silent default.
|
|
298
|
+
this._map.addSource(sourceId, { type: 'geojson', data: geojson });
|
|
228
299
|
}
|
|
229
300
|
this._appliedChoroplethSourceId = sourceId;
|
|
230
301
|
// An `interpolate` expression needs at least one [value, color] stop pair
|
|
@@ -281,31 +352,57 @@ export class LyraMap extends LyraElement {
|
|
|
281
352
|
if (!map || !mod)
|
|
282
353
|
return;
|
|
283
354
|
const visible = new Set();
|
|
355
|
+
// Markers with no `id` used to key solely by `lngLat`, so two different
|
|
356
|
+
// id-less markers placed at the exact same coordinates collided onto one
|
|
357
|
+
// `_markerInstances` entry. An occurrence index (reset per render, per
|
|
358
|
+
// coordinate) makes same-coordinate id-less markers distinct while
|
|
359
|
+
// staying stable/consistent across re-renders as long as their relative
|
|
360
|
+
// order in `this.markers` doesn't change.
|
|
361
|
+
const coordCounts = new Map();
|
|
284
362
|
for (const m of this.markers) {
|
|
285
|
-
|
|
363
|
+
let key = m.id;
|
|
364
|
+
if (key == null) {
|
|
365
|
+
const coordKey = `${m.lngLat[0]},${m.lngLat[1]}`;
|
|
366
|
+
const occurrence = coordCounts.get(coordKey) ?? 0;
|
|
367
|
+
coordCounts.set(coordKey, occurrence + 1);
|
|
368
|
+
key = `${coordKey}#${occurrence}`;
|
|
369
|
+
}
|
|
286
370
|
visible.add(key);
|
|
287
|
-
|
|
371
|
+
let existing = this._markerInstances.get(key);
|
|
372
|
+
if (existing && this._markerColors.get(key) !== m.color) {
|
|
373
|
+
// `color` is baked into the marker's SVG at construction time with
|
|
374
|
+
// no way to mutate it afterwards -- fall through to the "no existing
|
|
375
|
+
// marker" branch below to reconstruct it instead. Note: this closes
|
|
376
|
+
// any popup the user currently has open on this marker (a fresh,
|
|
377
|
+
// closed Popup is built for the new instance) -- an accepted, narrow
|
|
378
|
+
// side effect of the reconstruction fallback, not a bug.
|
|
379
|
+
existing.remove();
|
|
380
|
+
this._markerInstances.delete(key);
|
|
381
|
+
this._markerColors.delete(key);
|
|
382
|
+
existing = undefined;
|
|
383
|
+
}
|
|
288
384
|
if (!existing) {
|
|
289
385
|
const marker = new mod.Marker(m.color ? { color: m.color } : undefined).setLngLat(m.lngLat);
|
|
290
|
-
if (m.
|
|
386
|
+
if (m.unsafeHtml || m.label) {
|
|
291
387
|
const popup = new mod.Popup({ offset: 12 });
|
|
292
|
-
if (m.
|
|
293
|
-
popup.setHTML(m.
|
|
388
|
+
if (m.unsafeHtml)
|
|
389
|
+
popup.setHTML(m.unsafeHtml);
|
|
294
390
|
else if (m.label)
|
|
295
391
|
popup.setText(m.label);
|
|
296
392
|
marker.setPopup(popup);
|
|
297
393
|
}
|
|
298
394
|
marker.addTo(map);
|
|
299
395
|
this._markerInstances.set(key, marker);
|
|
396
|
+
this._markerColors.set(key, m.color);
|
|
300
397
|
}
|
|
301
398
|
else {
|
|
302
399
|
existing.setLngLat(m.lngLat);
|
|
303
400
|
const popup = existing.getPopup();
|
|
304
|
-
if (m.
|
|
401
|
+
if (m.unsafeHtml) {
|
|
305
402
|
if (popup)
|
|
306
|
-
popup.setHTML(m.
|
|
403
|
+
popup.setHTML(m.unsafeHtml);
|
|
307
404
|
else
|
|
308
|
-
existing.setPopup(new mod.Popup({ offset: 12 }).setHTML(m.
|
|
405
|
+
existing.setPopup(new mod.Popup({ offset: 12 }).setHTML(m.unsafeHtml));
|
|
309
406
|
}
|
|
310
407
|
else if (m.label) {
|
|
311
408
|
if (popup)
|
|
@@ -322,6 +419,7 @@ export class LyraMap extends LyraElement {
|
|
|
322
419
|
if (!visible.has(key)) {
|
|
323
420
|
marker.remove();
|
|
324
421
|
this._markerInstances.delete(key);
|
|
422
|
+
this._markerColors.delete(key);
|
|
325
423
|
}
|
|
326
424
|
}
|
|
327
425
|
}
|
|
@@ -372,6 +470,9 @@ __decorate([
|
|
|
372
470
|
__decorate([
|
|
373
471
|
state()
|
|
374
472
|
], LyraMap.prototype, "loading", void 0);
|
|
473
|
+
__decorate([
|
|
474
|
+
state()
|
|
475
|
+
], LyraMap.prototype, "visible", void 0);
|
|
375
476
|
__decorate([
|
|
376
477
|
query('[part="container"]')
|
|
377
478
|
], LyraMap.prototype, "containerEl", void 0);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type * as MarkedModule from 'marked';
|
|
2
|
+
import type DOMPurifyApi from 'dompurify';
|
|
3
|
+
/**
|
|
4
|
+
* The two optional peers `<lyra-markdown>` needs, loaded independently (see
|
|
5
|
+
* `loadMarkdownAndSanitizer()`). Either half can be `undefined` on its own —
|
|
6
|
+
* a consumer who only installs `marked` (having explicitly opted out of
|
|
7
|
+
* sanitization via `sanitize="false"`) is a valid, supported combination.
|
|
8
|
+
*/
|
|
9
|
+
export interface MarkdownDeps {
|
|
10
|
+
marked: typeof MarkedModule | undefined;
|
|
11
|
+
DOMPurify: typeof DOMPurifyApi | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Independently loads the optional peer dependencies `marked` (Markdown
|
|
15
|
+
* parsing) and `dompurify` (HTML sanitizing), mirroring `chart-loader.ts`'s
|
|
16
|
+
* `loadChartAndZoom()` shape for two independent optional peers. A partial
|
|
17
|
+
* install — most usefully `marked` alone, for a consumer who has explicitly
|
|
18
|
+
* set `sanitize="false"` and doesn't need `dompurify` at all — degrades to
|
|
19
|
+
* "that one half is missing" rather than failing outright. Exported (in
|
|
20
|
+
* addition to the cached `loadMarkdownDeps()` below) so both failure paths —
|
|
21
|
+
* and the real caught error each one logs — are directly testable without
|
|
22
|
+
* needing to actually uninstall either package.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadMarkdownAndSanitizer(importMarked?: () => Promise<typeof MarkedModule>, importDompurify?: () => Promise<{
|
|
25
|
+
default: typeof DOMPurifyApi;
|
|
26
|
+
}>): Promise<MarkdownDeps>;
|
|
27
|
+
/**
|
|
28
|
+
* Lazily loads `marked` + `dompurify` once per page (see
|
|
29
|
+
* `loadMarkdownAndSanitizer()` for why each is loaded and caught
|
|
30
|
+
* independently). Cached the same way `chart-loader.ts`/`map-loader.ts`
|
|
31
|
+
* cache their promise, so every `<lyra-markdown>` instance on a page shares
|
|
32
|
+
* one load.
|
|
33
|
+
*
|
|
34
|
+
* The dynamic `import()` inside `loadMarkdownAndSanitizer()` is always
|
|
35
|
+
* asynchronous — even when both peers are already installed and resolve
|
|
36
|
+
* without error — so every `<lyra-markdown>` that calls this from
|
|
37
|
+
* `connectedCallback()` paints its plain-text fallback (`data-fallback` on
|
|
38
|
+
* the `content` part) for at least one microtask before the real rendered
|
|
39
|
+
* output replaces it. That window is unconditional, not just a failure
|
|
40
|
+
* path: it ends only once this promise settles. A consumer that wants to
|
|
41
|
+
* skip it can set `eager-load` on `<lyra-markdown>`, which calls
|
|
42
|
+
* `getMarkdownDepsIfLoaded()` below instead of awaiting this function —
|
|
43
|
+
* see that property's doc for what "already warm" means in practice.
|
|
44
|
+
*/
|
|
45
|
+
export declare function loadMarkdownDeps(): Promise<MarkdownDeps>;
|
|
46
|
+
/**
|
|
47
|
+
* Synchronous companion to `loadMarkdownDeps()`: returns the same
|
|
48
|
+
* module-level cached `MarkdownDeps` if some earlier call to
|
|
49
|
+
* `loadMarkdownDeps()` — from any `<lyra-markdown>` instance on the page, or
|
|
50
|
+
* a consumer priming it directly at startup — has already settled by the
|
|
51
|
+
* time this is called, or `undefined` if the cache isn't warm yet (nothing
|
|
52
|
+
* has called `loadMarkdownDeps()` before, or it's still in flight). Used by
|
|
53
|
+
* `eager-load` to skip the dynamic `import()`'s async hop in the common case
|
|
54
|
+
* where the peers are already loaded; it cannot make the *very first*
|
|
55
|
+
* `<lyra-markdown>` on a page synchronous, since that first call is what
|
|
56
|
+
* populates the cache in the first place.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getMarkdownDepsIfLoaded(): MarkdownDeps | undefined;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
let deps;
|
|
2
|
+
// Populated the instant `deps` settles (inside `loadMarkdownDeps()` below) so
|
|
3
|
+
// `getMarkdownDepsIfLoaded()` can hand one back synchronously -- the whole
|
|
4
|
+
// point of that function, since `deps` itself is a Promise and awaiting it
|
|
5
|
+
// always costs at least one microtask, even once already resolved.
|
|
6
|
+
let resolvedDeps;
|
|
7
|
+
/**
|
|
8
|
+
* Independently loads the optional peer dependencies `marked` (Markdown
|
|
9
|
+
* parsing) and `dompurify` (HTML sanitizing), mirroring `chart-loader.ts`'s
|
|
10
|
+
* `loadChartAndZoom()` shape for two independent optional peers. A partial
|
|
11
|
+
* install — most usefully `marked` alone, for a consumer who has explicitly
|
|
12
|
+
* set `sanitize="false"` and doesn't need `dompurify` at all — degrades to
|
|
13
|
+
* "that one half is missing" rather than failing outright. Exported (in
|
|
14
|
+
* addition to the cached `loadMarkdownDeps()` below) so both failure paths —
|
|
15
|
+
* and the real caught error each one logs — are directly testable without
|
|
16
|
+
* needing to actually uninstall either package.
|
|
17
|
+
*/
|
|
18
|
+
export async function loadMarkdownAndSanitizer(importMarked = () => import('marked'), importDompurify = () => import('dompurify')) {
|
|
19
|
+
let marked;
|
|
20
|
+
try {
|
|
21
|
+
marked = await importMarked();
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
console.warn('<lyra-markdown> needs the optional peer dependency `marked` to parse Markdown — install it with `pnpm add marked`:', err);
|
|
25
|
+
}
|
|
26
|
+
let DOMPurify;
|
|
27
|
+
try {
|
|
28
|
+
DOMPurify = (await importDompurify()).default;
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
console.warn('<lyra-markdown> needs the optional peer dependency `dompurify` to sanitize rendered HTML — install it ' +
|
|
32
|
+
'with `pnpm add dompurify`. Until then, content only renders when `sanitize="false"` is explicitly set:', err);
|
|
33
|
+
}
|
|
34
|
+
return { marked, DOMPurify };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Lazily loads `marked` + `dompurify` once per page (see
|
|
38
|
+
* `loadMarkdownAndSanitizer()` for why each is loaded and caught
|
|
39
|
+
* independently). Cached the same way `chart-loader.ts`/`map-loader.ts`
|
|
40
|
+
* cache their promise, so every `<lyra-markdown>` instance on a page shares
|
|
41
|
+
* one load.
|
|
42
|
+
*
|
|
43
|
+
* The dynamic `import()` inside `loadMarkdownAndSanitizer()` is always
|
|
44
|
+
* asynchronous — even when both peers are already installed and resolve
|
|
45
|
+
* without error — so every `<lyra-markdown>` that calls this from
|
|
46
|
+
* `connectedCallback()` paints its plain-text fallback (`data-fallback` on
|
|
47
|
+
* the `content` part) for at least one microtask before the real rendered
|
|
48
|
+
* output replaces it. That window is unconditional, not just a failure
|
|
49
|
+
* path: it ends only once this promise settles. A consumer that wants to
|
|
50
|
+
* skip it can set `eager-load` on `<lyra-markdown>`, which calls
|
|
51
|
+
* `getMarkdownDepsIfLoaded()` below instead of awaiting this function —
|
|
52
|
+
* see that property's doc for what "already warm" means in practice.
|
|
53
|
+
*/
|
|
54
|
+
export function loadMarkdownDeps() {
|
|
55
|
+
if (!deps) {
|
|
56
|
+
deps = loadMarkdownAndSanitizer().then((resolved) => {
|
|
57
|
+
resolvedDeps = resolved;
|
|
58
|
+
return resolved;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return deps;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Synchronous companion to `loadMarkdownDeps()`: returns the same
|
|
65
|
+
* module-level cached `MarkdownDeps` if some earlier call to
|
|
66
|
+
* `loadMarkdownDeps()` — from any `<lyra-markdown>` instance on the page, or
|
|
67
|
+
* a consumer priming it directly at startup — has already settled by the
|
|
68
|
+
* time this is called, or `undefined` if the cache isn't warm yet (nothing
|
|
69
|
+
* has called `loadMarkdownDeps()` before, or it's still in flight). Used by
|
|
70
|
+
* `eager-load` to skip the dynamic `import()`'s async hop in the common case
|
|
71
|
+
* where the peers are already loaded; it cannot make the *very first*
|
|
72
|
+
* `<lyra-markdown>` on a page synchronous, since that first call is what
|
|
73
|
+
* populates the cache in the first place.
|
|
74
|
+
*/
|
|
75
|
+
export function getMarkdownDepsIfLoaded() {
|
|
76
|
+
return resolvedDeps;
|
|
77
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
/**
|
|
4
|
+
* `<lyra-markdown>` — sanitized Markdown-to-HTML rendering (GFM tables,
|
|
5
|
+
* fenced code blocks, links, blockquotes) built on the optional peer
|
|
6
|
+
* dependencies `marked` (parsing) and `dompurify` (sanitizing), both
|
|
7
|
+
* lazy-loaded via `markdown-loader.ts` on first connect.
|
|
8
|
+
*
|
|
9
|
+
* Rendering never ships unsanitized or broken markup silently:
|
|
10
|
+
* - If `marked` fails to load, or throws while parsing malformed input, the
|
|
11
|
+
* component falls back to plain text (`white-space: pre-wrap`, no HTML
|
|
12
|
+
* parsing at all) and fires `lyra-render-error`.
|
|
13
|
+
* - If `sanitize` is `true` (the default) and `dompurify` fails to load, the
|
|
14
|
+
* component *also* falls back to plain text + `lyra-render-error` — it
|
|
15
|
+
* never renders marked's raw HTML output when sanitization was requested
|
|
16
|
+
* (or defaulted to) but is unavailable, even though `marked` itself loaded
|
|
17
|
+
* fine.
|
|
18
|
+
* - If `sanitize` is explicitly `false`, marked's raw output renders as-is
|
|
19
|
+
* regardless of whether `dompurify` is installed — the consumer opted out
|
|
20
|
+
* of sanitization, so `dompurify`'s absence is irrelevant to that path.
|
|
21
|
+
*
|
|
22
|
+
* That same plain-text fallback rendering (`data-fallback` on the `content`
|
|
23
|
+
* part) is also, unconditionally and by default, a brief *transient* state on
|
|
24
|
+
* every connect, not just a failure path: `connectedCallback()`'s dynamic
|
|
25
|
+
* `import()` of `marked`/`dompurify` (see `markdown-loader.ts`) is
|
|
26
|
+
* asynchronous, so the very first paint of any `<lyra-markdown>` on a page
|
|
27
|
+
* shows plain text for at least one microtask — even when both peers are
|
|
28
|
+
* already installed and load without error — until that import resolves and
|
|
29
|
+
* a second render replaces it with the real Markdown output. Set
|
|
30
|
+
* `eager-load` to skip that window once the shared dependency cache is
|
|
31
|
+
* already warm; see that property's doc for exactly what "warm" requires.
|
|
32
|
+
*
|
|
33
|
+
* `heading`/`code`/`blockquote`/`table`/`link`/`image` tokens are rendered
|
|
34
|
+
* through a `marked` renderer override that injects `part="..."` attributes
|
|
35
|
+
* directly into the produced HTML — a single pass, not a second DOM walk
|
|
36
|
+
* after insertion.
|
|
37
|
+
*
|
|
38
|
+
* @customElement lyra-markdown
|
|
39
|
+
* @event lyra-link-click - Fired (and the click prevented) when a rendered
|
|
40
|
+
* link's `href` starts with `internal-link-prefix`. `detail: { href:
|
|
41
|
+
* string, internal: true }`. Ordinary external links navigate normally
|
|
42
|
+
* (in `link-target`) and never fire this event.
|
|
43
|
+
* @event lyra-render-error - Fired whenever rendering falls back to plain
|
|
44
|
+
* text. `detail: { error: unknown }`.
|
|
45
|
+
* @csspart content - The wrapper around the rendered (or plain-text
|
|
46
|
+
* fallback) output.
|
|
47
|
+
* @csspart heading - Every rendered `<h1>`–`<h6>` (shifted by
|
|
48
|
+
* `heading-offset`).
|
|
49
|
+
* @csspart code-block - Every rendered fenced/indented `<pre>`.
|
|
50
|
+
* @csspart link - Every rendered `<a>`.
|
|
51
|
+
* @csspart table - Every rendered `<table>`.
|
|
52
|
+
* @csspart blockquote - Every rendered `<blockquote>`.
|
|
53
|
+
* @csspart img - Every rendered `<img>`.
|
|
54
|
+
*/
|
|
55
|
+
export declare class LyraMarkdown extends LyraElement {
|
|
56
|
+
static styles: import("lit").CSSResultGroup[];
|
|
57
|
+
/** The Markdown source to render. */
|
|
58
|
+
content: string;
|
|
59
|
+
/** Sanitize marked's HTML output with DOMPurify before rendering. See the
|
|
60
|
+
* class doc for what happens when this is `true` (the default) but the
|
|
61
|
+
* `dompurify` peer isn't installed. */
|
|
62
|
+
sanitize: boolean;
|
|
63
|
+
/** Enable GitHub-flavored Markdown (tables, strikethrough, autolinks, task lists). */
|
|
64
|
+
gfm: boolean;
|
|
65
|
+
/** `target` applied to every rendered `<a>`, with `rel="noopener
|
|
66
|
+
* noreferrer"` always added alongside it whenever a `target` is emitted.
|
|
67
|
+
* `'_blank'` (the default) preserves today's exact output. Set to `null`
|
|
68
|
+
* (or the empty string, e.g. via the `link-target=""` attribute) to omit
|
|
69
|
+
* `target`/`rel` entirely, so rendered links open in the same tab. */
|
|
70
|
+
linkTarget: string | null;
|
|
71
|
+
/** When set, a rendered link whose `href` starts with this prefix is
|
|
72
|
+
* treated as internal — its click is intercepted and reported via
|
|
73
|
+
* `lyra-link-click` instead of navigating. Empty (the default) means
|
|
74
|
+
* every link is treated as external. */
|
|
75
|
+
internalLinkPrefix: string;
|
|
76
|
+
/** Added to every rendered heading's source `token.depth` before emitting
|
|
77
|
+
* `<h${depth}>` — e.g. `heading-offset="2"` renders a source `#` as
|
|
78
|
+
* `<h3>` and a source `##` as `<h4>`. The result is clamped to `[1, 6]`
|
|
79
|
+
* (a source `######` with a positive offset stays at `<h6>` rather than
|
|
80
|
+
* overflowing past the HTML heading levels; the floor at `1` is
|
|
81
|
+
* defensive, since this property is meant to be additive-only). `0`
|
|
82
|
+
* (the default) preserves today's exact `<h${token.depth}>` output. */
|
|
83
|
+
headingOffset: number;
|
|
84
|
+
/** When `true`, `connectedCallback()` skips awaiting `loadMarkdownDeps()`'s
|
|
85
|
+
* dynamic `import()` if the shared `marked`/`dompurify` module cache (see
|
|
86
|
+
* `markdown-loader.ts`'s `getMarkdownDepsIfLoaded()`) has *already*
|
|
87
|
+
* resolved — e.g. because an earlier `<lyra-markdown>` instance on the
|
|
88
|
+
* page already finished loading, or the consumer primed the cache
|
|
89
|
+
* directly by calling `loadMarkdownDeps()` themselves at startup — and
|
|
90
|
+
* renders synchronously instead. When the cache isn't warm yet (most
|
|
91
|
+
* notably: the very first `<lyra-markdown>` ever connected on a page,
|
|
92
|
+
* since nothing has called `loadMarkdownDeps()` before it), this still
|
|
93
|
+
* falls back to the normal async path — a dynamic `import()` can't be
|
|
94
|
+
* made synchronous, so this is a fast path for the common "already warm"
|
|
95
|
+
* case, not a hard guarantee. `false` (the default) is byte-identical to
|
|
96
|
+
* today: always the async `import()`, fallback-text window included. */
|
|
97
|
+
eagerLoad: boolean;
|
|
98
|
+
/** Forward-compatible hint for a dedicated streaming renderer expected to
|
|
99
|
+
* build on this component later (coalescing partial tokens as they
|
|
100
|
+
* arrive) — setting it has no rendering effect yet. Reflects so a
|
|
101
|
+
* consumer can already target `lyra-markdown[streaming]` in CSS ahead of
|
|
102
|
+
* that behavior landing. */
|
|
103
|
+
streaming: boolean;
|
|
104
|
+
private renderedHtml;
|
|
105
|
+
private deps?;
|
|
106
|
+
connectedCallback(): void;
|
|
107
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
108
|
+
protected updated(): void;
|
|
109
|
+
private renderMarkdown;
|
|
110
|
+
private applyFallback;
|
|
111
|
+
private parseMarkdown;
|
|
112
|
+
private onContentClick;
|
|
113
|
+
render(): TemplateResult;
|
|
114
|
+
}
|
|
115
|
+
declare global {
|
|
116
|
+
interface HTMLElementTagNameMap {
|
|
117
|
+
'lyra-markdown': LyraMarkdown;
|
|
118
|
+
}
|
|
119
|
+
}
|