@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
|
@@ -1,25 +1,56 @@
|
|
|
1
1
|
import type * as ChartJsModule from 'chart.js';
|
|
2
2
|
import type ZoomPlugin from 'chartjs-plugin-zoom';
|
|
3
3
|
/**
|
|
4
|
-
* Independently loads the mandatory `chart.js` peer dependency and
|
|
5
|
-
* opt-in `chartjs-plugin-zoom` peer dependency
|
|
6
|
-
* (`chart.js` only, which `peerDependenciesMeta`
|
|
7
|
-
* combination) degrades to "charts render, zoom is inert"
|
|
8
|
-
* chart breaking.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* Independently loads the mandatory `chart.js` peer dependency and, only
|
|
5
|
+
* when `needsZoom` is true, the opt-in `chartjs-plugin-zoom` peer dependency
|
|
6
|
+
* — so a partial install (`chart.js` only, which `peerDependenciesMeta`
|
|
7
|
+
* marks as a valid combination) degrades to "charts render, zoom is inert"
|
|
8
|
+
* instead of every chart breaking. `needsZoom` defaults to `false` because
|
|
9
|
+
* most charts never set `zoom`, and `chartjs-plugin-zoom` has a hard
|
|
10
|
+
* dependency on `hammerjs` — no point paying that import cost for every
|
|
11
|
+
* chart on the page. Exported (in addition to `loadChartJs()`/
|
|
12
|
+
* `loadChartJsWithZoom()` below) so both failure paths — and the real caught
|
|
13
|
+
* error each one logs — are directly testable without needing to actually
|
|
14
|
+
* uninstall either package.
|
|
11
15
|
*/
|
|
12
16
|
export declare function loadChartAndZoom(importChart?: () => Promise<typeof ChartJsModule>, importZoom?: () => Promise<{
|
|
13
17
|
default: typeof ZoomPlugin;
|
|
14
|
-
}
|
|
18
|
+
}>, needsZoom?: boolean): Promise<{
|
|
15
19
|
mod: typeof ChartJsModule;
|
|
16
20
|
zoomPlugin: typeof ZoomPlugin | undefined;
|
|
17
21
|
} | null>;
|
|
18
22
|
/**
|
|
19
|
-
* Lazily loads the optional peer dependency `chart.js`
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
23
|
+
* Lazily loads the optional peer dependency `chart.js` once per page,
|
|
24
|
+
* registering only the tree-shaken subset this library uses.
|
|
25
|
+
* `chartjs-plugin-zoom` is *not* loaded here — see `loadChartJsWithZoom()`
|
|
26
|
+
* below, which any chart that actually sets `zoom` should call instead.
|
|
27
|
+
* Resolves to `null` if chart.js isn't installed.
|
|
24
28
|
*/
|
|
25
29
|
export declare function loadChartJs(): Promise<typeof ChartJsModule | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Loads `chart.js` (reusing the cached load above) plus `chartjs-plugin-zoom`,
|
|
32
|
+
* on first actual demand — most charts never set `zoom`, and the plugin has
|
|
33
|
+
* a hard dependency on `hammerjs`. Registers the plugin at most once across
|
|
34
|
+
* the page. Call this instead of `loadChartJs()` from any chart that has
|
|
35
|
+
* `zoom` set (at connect time, or later once `zoom` turns on).
|
|
36
|
+
*
|
|
37
|
+
* The whole operation (chart.js core + the zoom plugin import + its
|
|
38
|
+
* registration) is memoized behind a single `zoomLoad` promise, assigned
|
|
39
|
+
* synchronously before any `await` — mirroring `loadChartJs()`'s own
|
|
40
|
+
* `chartJs` memoization above. A plain boolean "already registered" guard
|
|
41
|
+
* checked before an `await` and only set after would leave a check-then-act
|
|
42
|
+
* race across that `await` boundary: two callers racing to turn `zoom` on
|
|
43
|
+
* close together (e.g. two `<lyra-chart zoom>` elements connecting around
|
|
44
|
+
* the same time) could both pass the check before either sets the flag,
|
|
45
|
+
* each independently re-importing the plugin and calling
|
|
46
|
+
* `mod.Chart.register()`. A single promise assigned up front closes that
|
|
47
|
+
* window — the second caller synchronously observes `zoomLoad` already set
|
|
48
|
+
* and awaits the same in-flight load instead of starting its own.
|
|
49
|
+
*
|
|
50
|
+
* `importZoom` defaults to the real dynamic import; it's a parameter purely
|
|
51
|
+
* so tests can instrument/count the underlying import without needing to
|
|
52
|
+
* actually uninstall the package.
|
|
53
|
+
*/
|
|
54
|
+
export declare function loadChartJsWithZoom(importZoom?: () => Promise<{
|
|
55
|
+
default: typeof ZoomPlugin;
|
|
56
|
+
}>): Promise<typeof ChartJsModule | null>;
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
let chartJs;
|
|
2
|
+
let zoomLoad;
|
|
2
3
|
let registered = false;
|
|
3
4
|
/**
|
|
4
|
-
* Independently loads the mandatory `chart.js` peer dependency and
|
|
5
|
-
* opt-in `chartjs-plugin-zoom` peer dependency
|
|
6
|
-
* (`chart.js` only, which `peerDependenciesMeta`
|
|
7
|
-
* combination) degrades to "charts render, zoom is inert"
|
|
8
|
-
* chart breaking.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* Independently loads the mandatory `chart.js` peer dependency and, only
|
|
6
|
+
* when `needsZoom` is true, the opt-in `chartjs-plugin-zoom` peer dependency
|
|
7
|
+
* — so a partial install (`chart.js` only, which `peerDependenciesMeta`
|
|
8
|
+
* marks as a valid combination) degrades to "charts render, zoom is inert"
|
|
9
|
+
* instead of every chart breaking. `needsZoom` defaults to `false` because
|
|
10
|
+
* most charts never set `zoom`, and `chartjs-plugin-zoom` has a hard
|
|
11
|
+
* dependency on `hammerjs` — no point paying that import cost for every
|
|
12
|
+
* chart on the page. Exported (in addition to `loadChartJs()`/
|
|
13
|
+
* `loadChartJsWithZoom()` below) so both failure paths — and the real caught
|
|
14
|
+
* error each one logs — are directly testable without needing to actually
|
|
15
|
+
* uninstall either package.
|
|
11
16
|
*/
|
|
12
|
-
export async function loadChartAndZoom(importChart = () => import('chart.js'), importZoom = () => import('chartjs-plugin-zoom')) {
|
|
17
|
+
export async function loadChartAndZoom(importChart = () => import('chart.js'), importZoom = () => import('chartjs-plugin-zoom'), needsZoom = false) {
|
|
13
18
|
let mod;
|
|
14
19
|
try {
|
|
15
20
|
mod = await importChart();
|
|
@@ -18,6 +23,8 @@ export async function loadChartAndZoom(importChart = () => import('chart.js'), i
|
|
|
18
23
|
console.warn('<lyra-chart> needs the optional peer dependency `chart.js` — install it with `pnpm add chart.js`:', err);
|
|
19
24
|
return null;
|
|
20
25
|
}
|
|
26
|
+
if (!needsZoom)
|
|
27
|
+
return { mod, zoomPlugin: undefined };
|
|
21
28
|
let zoomPlugin;
|
|
22
29
|
try {
|
|
23
30
|
zoomPlugin = (await importZoom()).default;
|
|
@@ -29,25 +36,65 @@ export async function loadChartAndZoom(importChart = () => import('chart.js'), i
|
|
|
29
36
|
}
|
|
30
37
|
return { mod, zoomPlugin };
|
|
31
38
|
}
|
|
39
|
+
function registerCore(mod) {
|
|
40
|
+
if (registered)
|
|
41
|
+
return;
|
|
42
|
+
mod.Chart.register(mod.LineController, mod.BarController, mod.ScatterController, mod.DoughnutController, mod.PieController, mod.RadarController, mod.PolarAreaController, mod.BubbleController, mod.LineElement, mod.PointElement, mod.BarElement, mod.ArcElement, mod.LinearScale, mod.CategoryScale, mod.RadialLinearScale, mod.Filler, mod.Tooltip, mod.Legend);
|
|
43
|
+
registered = true;
|
|
44
|
+
}
|
|
32
45
|
/**
|
|
33
|
-
* Lazily loads the optional peer dependency `chart.js`
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
46
|
+
* Lazily loads the optional peer dependency `chart.js` once per page,
|
|
47
|
+
* registering only the tree-shaken subset this library uses.
|
|
48
|
+
* `chartjs-plugin-zoom` is *not* loaded here — see `loadChartJsWithZoom()`
|
|
49
|
+
* below, which any chart that actually sets `zoom` should call instead.
|
|
50
|
+
* Resolves to `null` if chart.js isn't installed.
|
|
38
51
|
*/
|
|
39
52
|
export function loadChartJs() {
|
|
40
53
|
if (!chartJs) {
|
|
41
54
|
chartJs = loadChartAndZoom().then((result) => {
|
|
42
55
|
if (!result)
|
|
43
56
|
return null;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
registerCore(result.mod);
|
|
58
|
+
return result.mod;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return chartJs;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Loads `chart.js` (reusing the cached load above) plus `chartjs-plugin-zoom`,
|
|
65
|
+
* on first actual demand — most charts never set `zoom`, and the plugin has
|
|
66
|
+
* a hard dependency on `hammerjs`. Registers the plugin at most once across
|
|
67
|
+
* the page. Call this instead of `loadChartJs()` from any chart that has
|
|
68
|
+
* `zoom` set (at connect time, or later once `zoom` turns on).
|
|
69
|
+
*
|
|
70
|
+
* The whole operation (chart.js core + the zoom plugin import + its
|
|
71
|
+
* registration) is memoized behind a single `zoomLoad` promise, assigned
|
|
72
|
+
* synchronously before any `await` — mirroring `loadChartJs()`'s own
|
|
73
|
+
* `chartJs` memoization above. A plain boolean "already registered" guard
|
|
74
|
+
* checked before an `await` and only set after would leave a check-then-act
|
|
75
|
+
* race across that `await` boundary: two callers racing to turn `zoom` on
|
|
76
|
+
* close together (e.g. two `<lyra-chart zoom>` elements connecting around
|
|
77
|
+
* the same time) could both pass the check before either sets the flag,
|
|
78
|
+
* each independently re-importing the plugin and calling
|
|
79
|
+
* `mod.Chart.register()`. A single promise assigned up front closes that
|
|
80
|
+
* window — the second caller synchronously observes `zoomLoad` already set
|
|
81
|
+
* and awaits the same in-flight load instead of starting its own.
|
|
82
|
+
*
|
|
83
|
+
* `importZoom` defaults to the real dynamic import; it's a parameter purely
|
|
84
|
+
* so tests can instrument/count the underlying import without needing to
|
|
85
|
+
* actually uninstall the package.
|
|
86
|
+
*/
|
|
87
|
+
export function loadChartJsWithZoom(importZoom = () => import('chartjs-plugin-zoom')) {
|
|
88
|
+
if (!zoomLoad) {
|
|
89
|
+
zoomLoad = loadChartJs().then(async (mod) => {
|
|
90
|
+
if (!mod)
|
|
91
|
+
return null;
|
|
92
|
+
const result = await loadChartAndZoom(() => Promise.resolve(mod), importZoom, true);
|
|
93
|
+
if (result?.zoomPlugin) {
|
|
94
|
+
mod.Chart.register(result.zoomPlugin);
|
|
48
95
|
}
|
|
49
96
|
return mod;
|
|
50
97
|
});
|
|
51
98
|
}
|
|
52
|
-
return
|
|
99
|
+
return zoomLoad;
|
|
53
100
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
|
-
import type { ChartConfiguration } from 'chart.js';
|
|
3
2
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
4
3
|
import '../skeleton/skeleton.js';
|
|
5
4
|
export interface Series {
|
|
@@ -73,10 +72,13 @@ export declare class LyraChart extends LyraElement {
|
|
|
73
72
|
* without discarding sibling keys the generated config set), for consumers
|
|
74
73
|
* who need full Chart.js control beyond the simplified `Series` shape.
|
|
75
74
|
*/
|
|
76
|
-
config?: Partial<ChartConfiguration>;
|
|
75
|
+
config?: Partial<import('chart.js').ChartConfiguration>;
|
|
77
76
|
/** True until the lazy-loaded `chart.js` peer dependency has settled (success or failure). */
|
|
78
77
|
private loading;
|
|
79
78
|
private zoomed;
|
|
79
|
+
private visible;
|
|
80
|
+
private intersectionObserver?;
|
|
81
|
+
private lastSignature;
|
|
80
82
|
private canvasEl?;
|
|
81
83
|
private chart?;
|
|
82
84
|
private chartJsModule?;
|
|
@@ -95,6 +97,14 @@ export declare class LyraChart extends LyraElement {
|
|
|
95
97
|
* is called fresh from `buildConfig()` on every draw rather than cached.
|
|
96
98
|
*/
|
|
97
99
|
private themeColors;
|
|
100
|
+
/**
|
|
101
|
+
* A content-affecting-properties fingerprint used by `updated()` to skip a
|
|
102
|
+
* redundant `draw()` when neither visibility nor any of these properties
|
|
103
|
+
* actually changed since the last draw (e.g. an unrelated property/state
|
|
104
|
+
* update, or `requestUpdate()` with nothing changed). Mirrors
|
|
105
|
+
* `lite-chart.ts`'s `computeSignature()`.
|
|
106
|
+
*/
|
|
107
|
+
private computeSignature;
|
|
98
108
|
/**
|
|
99
109
|
* Builds `options.scales` for the effective chart type: no scale at all for
|
|
100
110
|
* pie/doughnut (a proportional-area chart has no axis), the single radial
|
|
@@ -8,7 +8,7 @@ import { html, nothing } from 'lit';
|
|
|
8
8
|
import { property, query, state } from 'lit/decorators.js';
|
|
9
9
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
10
|
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
-
import { loadChartJs } from './chart-loader.js';
|
|
11
|
+
import { loadChartJs, loadChartJsWithZoom } from './chart-loader.js';
|
|
12
12
|
import { styles } from './chart.styles.js';
|
|
13
13
|
import '../skeleton/skeleton.js';
|
|
14
14
|
/**
|
|
@@ -99,6 +99,8 @@ export class LyraChart extends LyraElement {
|
|
|
99
99
|
/** True until the lazy-loaded `chart.js` peer dependency has settled (success or failure). */
|
|
100
100
|
this.loading = true;
|
|
101
101
|
this.zoomed = false;
|
|
102
|
+
this.visible = true;
|
|
103
|
+
this.lastSignature = '';
|
|
102
104
|
// `chartjs-plugin-zoom`'s own `resetZoom()` synchronously re-invokes the
|
|
103
105
|
// `onZoomComplete` callback below as part of its reset, which would emit a
|
|
104
106
|
// stale `{zoomed: true}` right before `resetZoom()` emits the real
|
|
@@ -109,20 +111,46 @@ export class LyraChart extends LyraElement {
|
|
|
109
111
|
static { this.styles = [LyraElement.styles, styles]; }
|
|
110
112
|
connectedCallback() {
|
|
111
113
|
super.connectedCallback();
|
|
112
|
-
|
|
114
|
+
const load = this.zoom ? loadChartJsWithZoom() : loadChartJs();
|
|
115
|
+
void load.then((mod) => {
|
|
116
|
+
if (!this.isConnected)
|
|
117
|
+
return;
|
|
113
118
|
this.loading = false;
|
|
114
119
|
if (!mod)
|
|
115
120
|
return;
|
|
116
121
|
this.chartJsModule = mod;
|
|
117
122
|
this.draw();
|
|
118
123
|
});
|
|
124
|
+
if (typeof IntersectionObserver !== 'undefined') {
|
|
125
|
+
this.intersectionObserver = new IntersectionObserver((entries) => {
|
|
126
|
+
const wasVisible = this.visible;
|
|
127
|
+
this.visible = entries[0]?.isIntersecting ?? true;
|
|
128
|
+
if (this.visible && !wasVisible)
|
|
129
|
+
this.draw();
|
|
130
|
+
});
|
|
131
|
+
this.intersectionObserver.observe(this);
|
|
132
|
+
}
|
|
119
133
|
}
|
|
120
134
|
disconnectedCallback() {
|
|
121
135
|
super.disconnectedCallback();
|
|
122
136
|
this.chart?.destroy();
|
|
123
137
|
this.chart = undefined;
|
|
138
|
+
this.intersectionObserver?.disconnect();
|
|
124
139
|
}
|
|
125
140
|
updated(changed) {
|
|
141
|
+
// Disconnected between the property change that scheduled this update
|
|
142
|
+
// and Lit's (microtask-deferred) processing of it — e.g. a property
|
|
143
|
+
// changes and the element is removed in the same synchronous tick, so
|
|
144
|
+
// `disconnectedCallback()` (which already destroyed `this.chart`) runs
|
|
145
|
+
// *before* this method does. Nothing below should run in that case:
|
|
146
|
+
// this method's own unconditional `draw()` call further down would
|
|
147
|
+
// otherwise construct a brand-new `Chart` bound to the now-detached
|
|
148
|
+
// canvas — `draw()`'s own guard (`!chartJsModule || !canvasEl`) doesn't
|
|
149
|
+
// catch this, since both persist on a disconnected-but-intact element.
|
|
150
|
+
// If the component is reconnected later, `connectedCallback()` re-kicks
|
|
151
|
+
// its own load/draw sequence, so nothing is lost by bailing out here.
|
|
152
|
+
if (!this.isConnected)
|
|
153
|
+
return;
|
|
126
154
|
if (this.loading)
|
|
127
155
|
this.setAttribute('aria-busy', 'true');
|
|
128
156
|
else
|
|
@@ -135,16 +163,59 @@ export class LyraChart extends LyraElement {
|
|
|
135
163
|
if (changed.has('height')) {
|
|
136
164
|
this.style.setProperty('--lyra-chart-height', this.height);
|
|
137
165
|
}
|
|
166
|
+
// While `chart.js` is still loading, `draw()` would no-op anyway (no
|
|
167
|
+
// `chartJsModule`/`canvasEl` yet) — bail before touching `lastSignature`
|
|
168
|
+
// so that phantom "no-op" update doesn't get cached as the baseline and
|
|
169
|
+
// silently swallow the real first draw once loading finishes with no
|
|
170
|
+
// other property having changed in the meantime.
|
|
171
|
+
if (this.loading)
|
|
172
|
+
return;
|
|
173
|
+
// `zoom` can also turn on after connect (it was false at
|
|
174
|
+
// `connectedCallback()` time, so only the core `loadChartJs()` load was
|
|
175
|
+
// kicked off) — load the zoom plugin on demand now and redraw once it's
|
|
176
|
+
// registered. Mirrors the same `isConnected` guard `connectedCallback()`
|
|
177
|
+
// uses: this method already bailed out above if *already* disconnected,
|
|
178
|
+
// but the element can *also* disconnect during the gap while this
|
|
179
|
+
// dynamic import is in flight — without this guard, `draw()` would
|
|
180
|
+
// construct a new, leaked `Chart` bound to the now-detached canvas once
|
|
181
|
+
// the import resolves.
|
|
182
|
+
if (changed.has('zoom') && this.zoom) {
|
|
183
|
+
void loadChartJsWithZoom().then(() => {
|
|
184
|
+
if (!this.isConnected)
|
|
185
|
+
return;
|
|
186
|
+
this.draw();
|
|
187
|
+
});
|
|
188
|
+
}
|
|
138
189
|
const onlyZoomChanged = changed.size === 1 && changed.has('zoomed');
|
|
139
|
-
if (
|
|
140
|
-
|
|
190
|
+
if (onlyZoomChanged)
|
|
191
|
+
return;
|
|
192
|
+
if (!this.visible)
|
|
193
|
+
return; // becoming visible again triggers its own draw() via the observer above
|
|
194
|
+
const signature = this.computeSignature();
|
|
195
|
+
if (signature === this.lastSignature)
|
|
196
|
+
return;
|
|
197
|
+
this.lastSignature = signature;
|
|
198
|
+
this.draw();
|
|
141
199
|
}
|
|
142
200
|
seriesToDataset(s) {
|
|
143
201
|
const colors = Array.isArray(s.color) ? s.color : s.color ? [s.color] : undefined;
|
|
144
202
|
return {
|
|
145
203
|
label: s.label,
|
|
146
204
|
data: s.points ?? s.data ?? [],
|
|
147
|
-
|
|
205
|
+
// Leave unset rather than defaulting to `this.type`: Chart.js already
|
|
206
|
+
// falls back to the chart-level (effective) type for any dataset that
|
|
207
|
+
// doesn't set its own `type`, and forcing `this.type` here unconditionally
|
|
208
|
+
// used to be harmless (it normally matched the effective type anyway) —
|
|
209
|
+
// but it actively breaks a `config.type` override to a different chart
|
|
210
|
+
// family (e.g. attribute `type="line"` + `config.type: 'radar'`): every
|
|
211
|
+
// dataset would carry an explicit `type: 'line'` under a chart whose
|
|
212
|
+
// scales are built for `radar` (a single radial `r` scale, no `x`/`y`),
|
|
213
|
+
// which Chart.js can't reconcile — it hangs the page trying to lay out
|
|
214
|
+
// a cartesian-scale controller against a radial-only scale set. Only
|
|
215
|
+
// `s.type` (an explicit per-series mixed-type override, e.g. a line
|
|
216
|
+
// series over a bar chart of the *same* effective family) is passed
|
|
217
|
+
// through.
|
|
218
|
+
type: s.type,
|
|
148
219
|
fill: s.fill ?? this.area,
|
|
149
220
|
borderWidth: s.width ?? 2,
|
|
150
221
|
borderDash: s.dash ? [4, 4] : undefined,
|
|
@@ -153,7 +224,6 @@ export class LyraChart extends LyraElement {
|
|
|
153
224
|
pointBackgroundColor: s.pointColors,
|
|
154
225
|
pointRadius: s.pointRadius,
|
|
155
226
|
yAxisID: s.axis === 'y2' ? 'y2' : 'y',
|
|
156
|
-
tooltip: s.noTooltip ? { enabled: false } : undefined,
|
|
157
227
|
};
|
|
158
228
|
}
|
|
159
229
|
/**
|
|
@@ -174,6 +244,29 @@ export class LyraChart extends LyraElement {
|
|
|
174
244
|
tooltipText: cs.getPropertyValue('--lyra-chart-tooltip-text').trim() || FALLBACK_TOOLTIP_TEXT,
|
|
175
245
|
};
|
|
176
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* A content-affecting-properties fingerprint used by `updated()` to skip a
|
|
249
|
+
* redundant `draw()` when neither visibility nor any of these properties
|
|
250
|
+
* actually changed since the last draw (e.g. an unrelated property/state
|
|
251
|
+
* update, or `requestUpdate()` with nothing changed). Mirrors
|
|
252
|
+
* `lite-chart.ts`'s `computeSignature()`.
|
|
253
|
+
*/
|
|
254
|
+
computeSignature() {
|
|
255
|
+
return JSON.stringify([
|
|
256
|
+
this.type,
|
|
257
|
+
this.labels,
|
|
258
|
+
this.datasets,
|
|
259
|
+
this.legend,
|
|
260
|
+
this.area,
|
|
261
|
+
this.xLabel,
|
|
262
|
+
this.yLabel,
|
|
263
|
+
this.y2Label,
|
|
264
|
+
this.beginAtZero,
|
|
265
|
+
this.horizontal,
|
|
266
|
+
this.stacked,
|
|
267
|
+
this.config,
|
|
268
|
+
]);
|
|
269
|
+
}
|
|
177
270
|
/**
|
|
178
271
|
* Builds `options.scales` for the effective chart type: no scale at all for
|
|
179
272
|
* pie/doughnut (a proportional-area chart has no axis), the single radial
|
|
@@ -186,10 +279,10 @@ export class LyraChart extends LyraElement {
|
|
|
186
279
|
* scale's `ticks.color`/`grid.color`/axis `title.color` so grid lines and
|
|
187
280
|
* labels retheme instead of sitting at Chart.js's own hardcoded defaults.
|
|
188
281
|
*/
|
|
189
|
-
buildScales(theme) {
|
|
190
|
-
if (
|
|
282
|
+
buildScales(effectiveType, theme) {
|
|
283
|
+
if (effectiveType === 'pie' || effectiveType === 'doughnut')
|
|
191
284
|
return {};
|
|
192
|
-
if (
|
|
285
|
+
if (effectiveType === 'radar' || effectiveType === 'polarArea') {
|
|
193
286
|
return {
|
|
194
287
|
r: {
|
|
195
288
|
beginAtZero: this.beginAtZero,
|
|
@@ -204,10 +297,10 @@ export class LyraChart extends LyraElement {
|
|
|
204
297
|
// `stacked` only applies to bar/line-family charts sharing a categorical
|
|
205
298
|
// axis, per the design spec — scatter/bubble's linear x scale and the
|
|
206
299
|
// radial r scale above are out of scope.
|
|
207
|
-
const stacked = this.stacked && (
|
|
300
|
+
const stacked = this.stacked && (effectiveType === 'bar' || effectiveType === 'line');
|
|
208
301
|
return {
|
|
209
302
|
x: {
|
|
210
|
-
type:
|
|
303
|
+
type: effectiveType === 'scatter' || effectiveType === 'bubble' ? 'linear' : 'category',
|
|
211
304
|
title: { display: !!this.xLabel, text: this.xLabel, color: theme.tick },
|
|
212
305
|
ticks: { color: theme.tick },
|
|
213
306
|
grid: { color: theme.grid },
|
|
@@ -261,8 +354,15 @@ export class LyraChart extends LyraElement {
|
|
|
261
354
|
}
|
|
262
355
|
buildConfig() {
|
|
263
356
|
const theme = this.themeColors();
|
|
357
|
+
// Resolve the effective type up front: `config.type` (if set) overrides
|
|
358
|
+
// the attribute `type` post-merge, so scales/interaction must be built
|
|
359
|
+
// for *that* type, not `this.type` — otherwise a config.type override
|
|
360
|
+
// (e.g. line -> radar) ships with the wrong axis shape (categorical x/y
|
|
361
|
+
// instead of a radial r scale).
|
|
362
|
+
const effectiveType = this.config?.type ??
|
|
363
|
+
this.type;
|
|
264
364
|
const generated = {
|
|
265
|
-
type:
|
|
365
|
+
type: effectiveType,
|
|
266
366
|
data: {
|
|
267
367
|
labels: this.labels,
|
|
268
368
|
datasets: this.datasets.map((s) => this.seriesToDataset(s)),
|
|
@@ -280,7 +380,7 @@ export class LyraChart extends LyraElement {
|
|
|
280
380
|
// canvas-internal animation loop, so `prefersReducedMotion()` is
|
|
281
381
|
// checked here instead and fed into `options.animation`.
|
|
282
382
|
animation: prefersReducedMotion() ? false : undefined,
|
|
283
|
-
interaction: { intersect: false, mode:
|
|
383
|
+
interaction: { intersect: false, mode: effectiveType === 'scatter' ? 'nearest' : 'index' },
|
|
284
384
|
onClick: (event, _elements, chart) => this.handlePointClick(event, chart),
|
|
285
385
|
plugins: {
|
|
286
386
|
legend: { display: this.legend, labels: { color: theme.legend } },
|
|
@@ -288,6 +388,10 @@ export class LyraChart extends LyraElement {
|
|
|
288
388
|
backgroundColor: theme.tooltipBg,
|
|
289
389
|
titleColor: theme.tooltipText,
|
|
290
390
|
bodyColor: theme.tooltipText,
|
|
391
|
+
// Chart.js's tooltip plugin has no per-dataset `tooltip.enabled`
|
|
392
|
+
// — `Series.noTooltip` is implemented here instead, via the one
|
|
393
|
+
// mechanism the core tooltip plugin actually reads.
|
|
394
|
+
filter: (item) => !this.datasets[item.datasetIndex]?.noTooltip,
|
|
291
395
|
},
|
|
292
396
|
zoom: this.zoom
|
|
293
397
|
? {
|
|
@@ -308,7 +412,7 @@ export class LyraChart extends LyraElement {
|
|
|
308
412
|
}
|
|
309
413
|
: undefined,
|
|
310
414
|
},
|
|
311
|
-
scales: this.buildScales(theme),
|
|
415
|
+
scales: this.buildScales(effectiveType, theme),
|
|
312
416
|
},
|
|
313
417
|
};
|
|
314
418
|
if (!this.config)
|
|
@@ -428,6 +532,9 @@ __decorate([
|
|
|
428
532
|
__decorate([
|
|
429
533
|
state()
|
|
430
534
|
], LyraChart.prototype, "zoomed", void 0);
|
|
535
|
+
__decorate([
|
|
536
|
+
state()
|
|
537
|
+
], LyraChart.prototype, "visible", void 0);
|
|
431
538
|
__decorate([
|
|
432
539
|
query('canvas')
|
|
433
540
|
], LyraChart.prototype, "canvasEl", void 0);
|
|
@@ -2,5 +2,8 @@ export interface HistogramBucket {
|
|
|
2
2
|
label: string;
|
|
3
3
|
count: number;
|
|
4
4
|
}
|
|
5
|
-
/** Splits `values` into `binCount` equal-width buckets and counts membership.
|
|
5
|
+
/** Splits `values` into `binCount` equal-width buckets and counts membership.
|
|
6
|
+
* Non-finite `binCount` (or <= 0) yields no buckets; a fractional `binCount`
|
|
7
|
+
* is floored; non-finite samples in `values` are dropped rather than
|
|
8
|
+
* corrupting bucket-index math. */
|
|
6
9
|
export declare function binValues(values: number[], binCount: number): HistogramBucket[];
|
|
@@ -1,29 +1,39 @@
|
|
|
1
|
-
/** Splits `values` into `binCount` equal-width buckets and counts membership.
|
|
1
|
+
/** Splits `values` into `binCount` equal-width buckets and counts membership.
|
|
2
|
+
* Non-finite `binCount` (or <= 0) yields no buckets; a fractional `binCount`
|
|
3
|
+
* is floored; non-finite samples in `values` are dropped rather than
|
|
4
|
+
* corrupting bucket-index math. */
|
|
2
5
|
export function binValues(values, binCount) {
|
|
3
|
-
|
|
6
|
+
const finite = values.filter((v) => Number.isFinite(v));
|
|
7
|
+
if (finite.length === 0 || !Number.isFinite(binCount))
|
|
4
8
|
return [];
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
for (const v of values) {
|
|
9
|
+
const bins = Math.floor(binCount);
|
|
10
|
+
if (bins <= 0)
|
|
11
|
+
return [];
|
|
12
|
+
let lo = finite[0];
|
|
13
|
+
let hi = finite[0];
|
|
14
|
+
for (const v of finite) {
|
|
12
15
|
if (v < lo)
|
|
13
16
|
lo = v;
|
|
14
17
|
if (v > hi)
|
|
15
18
|
hi = v;
|
|
16
19
|
}
|
|
20
|
+
// Constant data (lo === hi) previously fell into the `v === hi` branch
|
|
21
|
+
// below, which places every value in the *last* bucket alone — misleading,
|
|
22
|
+
// since every other bucket reads 0 and the label implies a spread that
|
|
23
|
+
// isn't real. Spread it into the *first* bucket instead so a single-value
|
|
24
|
+
// dataset reads as "N items, one bucket populated" starting from the data's
|
|
25
|
+
// own value, not its synthetic +1 upper edge.
|
|
26
|
+
const constant = hi === lo;
|
|
17
27
|
const span = hi - lo || 1;
|
|
18
|
-
const width = span /
|
|
19
|
-
const buckets = Array.from({ length:
|
|
28
|
+
const width = span / bins;
|
|
29
|
+
const buckets = Array.from({ length: bins }, (_, i) => {
|
|
20
30
|
const bLo = lo + i * width;
|
|
21
31
|
const bHi = lo + (i + 1) * width;
|
|
22
32
|
return { label: `${bLo.toFixed(1)}–${bHi.toFixed(1)}`, count: 0 };
|
|
23
33
|
});
|
|
24
|
-
for (const v of
|
|
25
|
-
const index = v === hi ?
|
|
26
|
-
buckets[Math.min(
|
|
34
|
+
for (const v of finite) {
|
|
35
|
+
const index = constant ? 0 : v === hi ? bins - 1 : Math.floor((v - lo) / width);
|
|
36
|
+
buckets[Math.min(bins - 1, Math.max(0, index))].count++;
|
|
27
37
|
}
|
|
28
38
|
return buckets;
|
|
29
39
|
}
|
|
@@ -7,6 +7,13 @@ export interface LiteSeries {
|
|
|
7
7
|
color?: string;
|
|
8
8
|
}
|
|
9
9
|
export type LyraLiteChartType = 'bar' | 'line';
|
|
10
|
+
/**
|
|
11
|
+
* `'fit'` (default) squeezes the whole plot into the measured host width,
|
|
12
|
+
* exactly as this component always behaved. `'scroll'` gives every bar a
|
|
13
|
+
* fixed `barWidth` instead and lets the plot's content width exceed the
|
|
14
|
+
* host's, making the host horizontally scrollable.
|
|
15
|
+
*/
|
|
16
|
+
export type LyraLiteChartLayout = 'fit' | 'scroll';
|
|
10
17
|
/**
|
|
11
18
|
* `<lyra-lite-chart>` — a dependency-free bar/line chart, plain SVG/DOM
|
|
12
19
|
* rendering with zero peer dependencies (unlike `lyra-chart`, which wraps
|
|
@@ -22,6 +29,17 @@ export type LyraLiteChartType = 'bar' | 'line';
|
|
|
22
29
|
* `getComputedStyle()`-based re-theming step is needed the way `chart.ts`
|
|
23
30
|
* needs one for its canvas.
|
|
24
31
|
*
|
|
32
|
+
* By default (`layout="fit"`) the plot always squeezes to the measured host
|
|
33
|
+
* width. Three independent, opt-in escape hatches for dense/aligned data:
|
|
34
|
+
* `layout="scroll"` (+ `barWidth`) gives every bar a fixed pixel width and
|
|
35
|
+
* lets the plot overflow the host horizontally (scrollable) instead of
|
|
36
|
+
* squeezing; `maxLabels` decimates which x-axis text labels render (bars
|
|
37
|
+
* always still render) once there are more categories than that; and
|
|
38
|
+
* `barX` lets a consumer hand in its own per-category x-coordinate function
|
|
39
|
+
* — e.g. to pixel-align this chart's bars with a sibling `lyra-heatmap`'s
|
|
40
|
+
* calendar columns — overriding the internal slot math for both bars and
|
|
41
|
+
* their labels. All three are additive and no-ops when left unset.
|
|
42
|
+
*
|
|
25
43
|
* @customElement lyra-lite-chart
|
|
26
44
|
* @event lyra-point-click - Fired when a bar/point is activated (click, or
|
|
27
45
|
* Enter/Space while focused). `detail: { datasetIndex: number, index:
|
|
@@ -50,22 +68,67 @@ export declare class LyraLiteChart extends LyraElement {
|
|
|
50
68
|
beginAtZero: boolean;
|
|
51
69
|
/** Stacks each category's bars into one segmented bar. Ignored for `type="line"`. */
|
|
52
70
|
stacked: boolean;
|
|
71
|
+
/** Formats a y-axis tick value for display (e.g. `(v) => \`$${v.toFixed(2)}\``). Falls back to the
|
|
72
|
+
* built-in nice-number formatter when unset. */
|
|
73
|
+
tickFormat?: (value: number) => string;
|
|
74
|
+
/** `'fit'` (default) squeezes the plot into the measured host width, unchanged from before this
|
|
75
|
+
* property existed. `'scroll'` gives every bar a fixed `barWidth` instead, letting the plot's
|
|
76
|
+
* content width exceed the host's — the host becomes horizontally scrollable
|
|
77
|
+
* (`overflow-x: auto`) so every bar stays exactly `barWidth` wide regardless of category count.
|
|
78
|
+
* Reflects to the `layout` attribute (e.g. for `:host([layout='scroll'])` host styling). */
|
|
79
|
+
layout: LyraLiteChartLayout;
|
|
80
|
+
/** Fixed per-category bar width in px, used only when `layout="scroll"`. Ignored (as before this
|
|
81
|
+
* property existed) in `layout="fit"`, the default. */
|
|
82
|
+
barWidth: number;
|
|
83
|
+
/** Caps how many x-axis category labels render text once `this.labels.length` exceeds it,
|
|
84
|
+
* decimating roughly evenly while always keeping the first and last label. Bars themselves
|
|
85
|
+
* always render regardless — only the axis text is decimated. Unset (the default) renders every
|
|
86
|
+
* label, unchanged from before this property existed. Works in either `layout` mode. */
|
|
87
|
+
maxLabels?: number;
|
|
88
|
+
/** Overrides the x-origin `renderBars()`/the category labels would otherwise compute internally
|
|
89
|
+
* for a given category index, for `type="bar"` only (bars and their axis labels stay
|
|
90
|
+
* consistent with each other either way). Lets a consumer pixel-align this chart's bars with,
|
|
91
|
+
* e.g., a sibling `lyra-heatmap`'s calendar columns by handing both components the same
|
|
92
|
+
* coordinate function. Unset (the default) uses the existing internal per-category slot math,
|
|
93
|
+
* unchanged from before this property existed. */
|
|
94
|
+
barX?: (index: number) => number;
|
|
53
95
|
private plotWidth;
|
|
54
96
|
private plotHeight;
|
|
97
|
+
private visible;
|
|
55
98
|
private svgEl?;
|
|
56
99
|
private resizeObserver?;
|
|
100
|
+
private intersectionObserver?;
|
|
101
|
+
private lastSignature;
|
|
102
|
+
private lastResult?;
|
|
57
103
|
connectedCallback(): void;
|
|
58
104
|
disconnectedCallback(): void;
|
|
59
105
|
protected firstUpdated(): void;
|
|
60
106
|
protected updated(changed: PropertyValues): void;
|
|
61
107
|
private colorFor;
|
|
62
108
|
private domain;
|
|
109
|
+
private computeSignature;
|
|
63
110
|
private emitPoint;
|
|
64
111
|
private onPointKeyDown;
|
|
65
112
|
private renderGrid;
|
|
113
|
+
/**
|
|
114
|
+
* `slot` is the per-category width to lay bars out against — either the
|
|
115
|
+
* measured-width-derived `plotW / n` (`layout="fit"`) or the fixed
|
|
116
|
+
* `barWidth` (`layout="scroll"`), computed once by the caller
|
|
117
|
+
* (`renderChart()`) and handed to both this method and the category-label
|
|
118
|
+
* x-position calc so the two can never drift apart from each other.
|
|
119
|
+
*/
|
|
66
120
|
private renderBars;
|
|
67
121
|
private renderLines;
|
|
68
122
|
render(): TemplateResult;
|
|
123
|
+
/**
|
|
124
|
+
* Step size for `maxLabels` decimation: 1 (show every label, today's
|
|
125
|
+
* unchanged default) when `maxLabels` is unset or already >= the label
|
|
126
|
+
* count, otherwise the ceil-divide spacing that lands close to
|
|
127
|
+
* `maxLabels` shown labels while always keeping index 0 and the last
|
|
128
|
+
* index (enforced by the caller, not here).
|
|
129
|
+
*/
|
|
130
|
+
private labelStep;
|
|
131
|
+
private renderChart;
|
|
69
132
|
}
|
|
70
133
|
declare global {
|
|
71
134
|
interface HTMLElementTagNameMap {
|