@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
|
@@ -22,9 +22,22 @@ const FALLBACK_SCALE_HI = '#0969da';
|
|
|
22
22
|
const FALLBACK_LABEL_FONT = '10px sans-serif';
|
|
23
23
|
const CAL_PAD_LEFT = 28;
|
|
24
24
|
const CAL_LABEL_H = 16;
|
|
25
|
+
/** Calendar mode's original fixed cell size — now also the effective fallback
|
|
26
|
+
* the `cellSize` accessor uses in calendar mode when left unset (see its
|
|
27
|
+
* doc comment), so a consumer who never touches `cellSize` sees no change. */
|
|
25
28
|
const CAL_CELL = 11;
|
|
26
29
|
const CAL_GAP = 2;
|
|
30
|
+
/** Matrix mode's original fixed cell size — the effective fallback the
|
|
31
|
+
* `cellSize` accessor uses in matrix mode when left unset. */
|
|
32
|
+
const DEFAULT_MATRIX_CELL_SIZE = 22;
|
|
27
33
|
const DEFAULT_BUCKET_COUNT = 5;
|
|
34
|
+
/**
|
|
35
|
+
* A linear RGB ramp cannot contain more than 256 visually distinct integer
|
|
36
|
+
* steps on any channel. Keeping the bucket count within that bound avoids an
|
|
37
|
+
* untrusted attribute/property value turning the ramp into an unbounded
|
|
38
|
+
* allocation without discarding any useful color resolution.
|
|
39
|
+
*/
|
|
40
|
+
export const MAX_BUCKET_COUNT = 256;
|
|
28
41
|
/** Ring stroke width for both the annotation overlay and the keyboard focus ring. */
|
|
29
42
|
const RING_LINE_WIDTH = 2;
|
|
30
43
|
const FALLBACK_FOCUS_RING_COLOR = '#0969da';
|
|
@@ -66,30 +79,26 @@ function warnInvalidColor(color) {
|
|
|
66
79
|
console.warn(`<lyra-heatmap> could not parse "${color}" (set via --lyra-heatmap-scale-lo/-hi) as a CSS ` +
|
|
67
80
|
'color; falling back to the default ramp endpoint.');
|
|
68
81
|
}
|
|
69
|
-
const warnedInvalidBucketCounts = new Set();
|
|
70
|
-
function warnInvalidBucketCount(value) {
|
|
71
|
-
if (warnedInvalidBucketCounts.has(value))
|
|
72
|
-
return;
|
|
73
|
-
warnedInvalidBucketCounts.add(value);
|
|
74
|
-
console.warn(`<lyra-heatmap> received a non-finite bucket-count (${value}); falling back to ${DEFAULT_BUCKET_COUNT}.`);
|
|
75
|
-
}
|
|
76
82
|
/**
|
|
77
|
-
* Normalizes
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* is floored rather than passed through as-is, so the ramp array's length
|
|
82
|
-
* (built via `Array.from({ length: buckets }, ...)`, which truncates a
|
|
83
|
-
* fractional `length`) always agrees with the index `quartileBucket` computes
|
|
84
|
-
* from the same `buckets` value.
|
|
83
|
+
* Normalizes a bucket count to the safe, renderable range. Non-finite values
|
|
84
|
+
* restore the public default; finite values are floored and clamped to
|
|
85
|
+
* `[2, MAX_BUCKET_COUNT]`. Flooring keeps the ramp array's length in exact
|
|
86
|
+
* agreement with the count used by `quartileBucket()`.
|
|
85
87
|
*/
|
|
86
|
-
function
|
|
88
|
+
export function normalizeBucketCount(bucketCount) {
|
|
87
89
|
if (!Number.isFinite(bucketCount)) {
|
|
88
|
-
warnInvalidBucketCount(bucketCount);
|
|
89
90
|
return DEFAULT_BUCKET_COUNT;
|
|
90
91
|
}
|
|
91
|
-
return Math.max(2, Math.floor(bucketCount));
|
|
92
|
+
return Math.min(MAX_BUCKET_COUNT, Math.max(2, Math.floor(bucketCount)));
|
|
92
93
|
}
|
|
94
|
+
const bucketCountConverter = {
|
|
95
|
+
fromAttribute(value) {
|
|
96
|
+
return value === null ? DEFAULT_BUCKET_COUNT : normalizeBucketCount(Number(value));
|
|
97
|
+
},
|
|
98
|
+
toAttribute(value) {
|
|
99
|
+
return String(normalizeBucketCount(value));
|
|
100
|
+
},
|
|
101
|
+
};
|
|
93
102
|
/**
|
|
94
103
|
* Resolves any syntactically valid CSS `<color>` — hex, `rgb()`, `hsl()`,
|
|
95
104
|
* `oklch()`, a named color, etc. — to an `[r, g, b]` triple.
|
|
@@ -142,12 +151,16 @@ export function mixColor(fromColor, toColor, t) {
|
|
|
142
151
|
* - `"matrix"` (default): a `rowLabels` x `colLabels` grid of `values`. `-1`
|
|
143
152
|
* (or any non-finite value) is treated as "no data". `scale="sqrt"`
|
|
144
153
|
* compresses the ramp via `sqrtStep()` so one heavy cell doesn't wash out
|
|
145
|
-
* the rest; the default `"linear"` scale maps linearly instead.
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* `
|
|
149
|
-
*
|
|
150
|
-
*
|
|
154
|
+
* the rest; the default `"linear"` scale maps linearly instead.
|
|
155
|
+
* - `"calendar"`: a GitHub-style Sunday-Saturday (or `firstDayOfWeek`-anchored
|
|
156
|
+
* — see below) x week grid built from `days`. `scale` governs its
|
|
157
|
+
* bucketing too: the default `"linear"` buckets by `quartileBucket()`
|
|
158
|
+
* (today's original behavior, unchanged); `"sqrt"` instead compresses via
|
|
159
|
+
* the same `sqrtStep()` magnitude compression matrix mode uses, so one
|
|
160
|
+
* heavy day doesn't wash out the rest. As in matrix mode, a cell whose
|
|
161
|
+
* `value` is negative or non-finite is treated as "no data" rather than
|
|
162
|
+
* being bucketed — as is a grid position with no matching entry in `days`
|
|
163
|
+
* at all (a gap in a sparse calendar).
|
|
151
164
|
*
|
|
152
165
|
* The sequential color ramp's endpoints are read from the
|
|
153
166
|
* `--lyra-heatmap-scale-lo`/`-hi` custom properties (declared in
|
|
@@ -167,13 +180,40 @@ export function mixColor(fromColor, toColor, t) {
|
|
|
167
180
|
* specific cells (e.g. to call out an anomaly), each one optionally
|
|
168
181
|
* surfaced in the legend too via `[part="legend-annotation"]`.
|
|
169
182
|
*
|
|
183
|
+
* `columnX` (calendar mode only) overrides the x-origin computed for each
|
|
184
|
+
* week column — drawing, hit-testing, the focus ring, and month-label
|
|
185
|
+
* positioning all consult it consistently, so a consumer can pixel-align a
|
|
186
|
+
* calendar's week columns with a sibling chart's coordinate system. Unset
|
|
187
|
+
* (the default) keeps the original evenly-spaced formula. `rowY` is its
|
|
188
|
+
* calendar-mode vertical analogue — overrides the y-origin computed for each
|
|
189
|
+
* weekday row, consulted consistently by drawing, hit-testing, and the focus
|
|
190
|
+
* ring via the private `rowYFor()` helper (mirroring `columnXFor()` exactly).
|
|
191
|
+
*
|
|
192
|
+
* `firstDayOfWeek` (calendar mode only, default `0`/Sunday, no-op in matrix
|
|
193
|
+
* mode) anchors the calendar grid at a different weekday — `0`-`6`, same
|
|
194
|
+
* numbering as `CalendarCellPos.weekday` (`0` Sunday .. `6` Saturday) —
|
|
195
|
+
* threaded into `buildCalendarGrid()`.
|
|
196
|
+
*
|
|
197
|
+
* `cellSize`/`fitToWidth` (previously matrix-mode only) also drive calendar
|
|
198
|
+
* mode's per-cell size: unset, calendar mode keeps today's original 11px
|
|
199
|
+
* cell size unchanged; explicitly set, the same fixed size (or, with
|
|
200
|
+
* `fitToWidth`, the same host-width-derived size matrix mode already
|
|
201
|
+
* supports) governs calendar mode's grid too.
|
|
202
|
+
*
|
|
170
203
|
* @customElement lyra-heatmap
|
|
171
204
|
* @event lyra-cell-click - Fired on click, or Enter/Space on the
|
|
172
205
|
* focused/hovered cell. `detail: { row, col, value }` in matrix mode,
|
|
173
206
|
* `detail: { date, value }` in calendar mode. `cellText` overrides the
|
|
174
207
|
* built-in English "Row X, Col Y: value" / "Mon DD: value" template used for
|
|
175
208
|
* both the hover tooltip and the keyboard live-region announcement.
|
|
176
|
-
* @csspart base
|
|
209
|
+
* @csspart base - The heatmap wrapper.
|
|
210
|
+
* @csspart canvas - The heatmap canvas.
|
|
211
|
+
* @csspart tooltip - The hover tooltip.
|
|
212
|
+
* @csspart live-region - The visually hidden keyboard announcement region.
|
|
213
|
+
* @csspart legend - The color legend.
|
|
214
|
+
* @csspart legend-lo - The low legend endpoint.
|
|
215
|
+
* @csspart legend-hi - The high legend endpoint.
|
|
216
|
+
* @csspart legend-annotation - An annotation label.
|
|
177
217
|
*/
|
|
178
218
|
export class LyraHeatmap extends LyraElement {
|
|
179
219
|
constructor() {
|
|
@@ -181,25 +221,57 @@ export class LyraHeatmap extends LyraElement {
|
|
|
181
221
|
this.rowLabels = [];
|
|
182
222
|
this.colLabels = [];
|
|
183
223
|
this.values = [];
|
|
184
|
-
this.cellSize = 22;
|
|
185
224
|
this.valueLabel = 'value';
|
|
225
|
+
/**
|
|
226
|
+
* `"linear"` (default) maps values linearly to the color ramp in matrix
|
|
227
|
+
* mode, and buckets calendar-mode values via `quartileBucket()` — both
|
|
228
|
+
* unchanged from before this property governed calendar mode too.
|
|
229
|
+
* `"sqrt"` compresses via `sqrtStep()`'s square-root magnitude compression
|
|
230
|
+
* instead, in *both* modes, so one heavy cell/day doesn't wash out the
|
|
231
|
+
* rest of a skewed dataset.
|
|
232
|
+
*/
|
|
186
233
|
this.scale = 'linear';
|
|
187
234
|
/**
|
|
188
235
|
* When set, `cellSize` is derived from the host's measured `clientWidth`
|
|
189
236
|
* on every draw (including ResizeObserver-triggered redraws) instead of
|
|
190
237
|
* the fixed `cell-size` attribute, so the grid actually fills the
|
|
191
238
|
* available width. Without this, canvas dimensions are computed purely
|
|
192
|
-
* from `PAD_LEFT + cols * cellSize
|
|
193
|
-
*
|
|
239
|
+
* from `PAD_LEFT + cols * cellSize` (matrix mode) or
|
|
240
|
+
* `CAL_PAD_LEFT + weekCount * cellSize` (calendar mode), so a
|
|
241
|
+
* resize-triggered redraw is a geometric no-op. Originally matrix-mode
|
|
242
|
+
* only; now applies to calendar mode too.
|
|
194
243
|
*/
|
|
195
244
|
this.fitToWidth = false;
|
|
196
245
|
this.mode = 'matrix';
|
|
197
246
|
this.days = [];
|
|
198
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Calendar mode only (no-op in matrix mode): anchors the calendar grid at
|
|
249
|
+
* a different weekday instead of always Sunday — `0`-`6`, same numbering
|
|
250
|
+
* as `CalendarCellPos.weekday` (`0` Sunday .. `6` Saturday, matching
|
|
251
|
+
* `CalendarCell.weekday`'s existing convention). Threaded into
|
|
252
|
+
* `buildCalendarGrid()`. Defaults to `0` (Sunday), unchanged from before
|
|
253
|
+
* this property existed.
|
|
254
|
+
*/
|
|
255
|
+
this.firstDayOfWeek = 0;
|
|
256
|
+
this._bucketCount = DEFAULT_BUCKET_COUNT;
|
|
199
257
|
/** Cells to ring-highlight — `row`/`col` in matrix mode, `date` in calendar mode. See `HeatmapAnnotation`. */
|
|
200
258
|
this.annotations = [];
|
|
259
|
+
this.themeRefreshQueued = false;
|
|
201
260
|
/** The current value range, refreshed once per update cycle by `willUpdate()`. See `computeValueRange()`. */
|
|
202
261
|
this.cachedValueRange = null;
|
|
262
|
+
/**
|
|
263
|
+
* The calendar-mode grid layout, refreshed by `willUpdate()` only when
|
|
264
|
+
* `days` actually changes (see `computeValueRange()`'s twin comment above)
|
|
265
|
+
* — `buildCalendarGrid()` parses every date, filters invalid ones, and does
|
|
266
|
+
* a full `.slice().sort()` for month labels, so recomputing it from
|
|
267
|
+
* `drawCalendar()`, `hitTestCalendar()`, `calendarCellAt()`, and
|
|
268
|
+
* `onCalendarKeyDown()` independently would redo that work 2-4x for a
|
|
269
|
+
* single hover/click/keydown.
|
|
270
|
+
*/
|
|
271
|
+
this.cachedCalendarGrid = buildCalendarGrid(this.days);
|
|
272
|
+
this.cachedCalendarSortedValues = [];
|
|
273
|
+
this.cachedCalendarCellsByPos = new Map();
|
|
274
|
+
this.cachedRamp = null;
|
|
203
275
|
/** The cell currently under the pointer (`null` when not hovering one) — drives `[part="tooltip"]`. */
|
|
204
276
|
this.hoverCell = null;
|
|
205
277
|
/** The roving keyboard-focus cell cursor, moved by arrow keys — drives the
|
|
@@ -207,21 +279,59 @@ export class LyraHeatmap extends LyraElement {
|
|
|
207
279
|
this.focusedCell = null;
|
|
208
280
|
/** Text of the visually-hidden `aria-live="polite"` status announcement, refreshed on every focus move. */
|
|
209
281
|
this.liveText = '';
|
|
282
|
+
/**
|
|
283
|
+
* Whether `role`/`aria-label` were present on the host *before* this
|
|
284
|
+
* element's own code ever wrote to them — snapshotted once, in the very
|
|
285
|
+
* first `willUpdate()` (guarded by `hasUpdated`, which Lit only flips to
|
|
286
|
+
* `true` after that first update commits). Re-checking `hasAttribute()` on
|
|
287
|
+
* every update instead would self-poison: once this element writes its own
|
|
288
|
+
* default `aria-label` on the first render, `hasAttribute('aria-label')`
|
|
289
|
+
* is permanently `true` afterwards, which would wrongly look like an
|
|
290
|
+
* author-supplied value and freeze the label instead of refreshing it as
|
|
291
|
+
* `values`/`days` change on later updates.
|
|
292
|
+
*/
|
|
293
|
+
this.authorSuppliedRole = false;
|
|
294
|
+
this.authorSuppliedAriaLabel = false;
|
|
210
295
|
this.onDprChange = () => {
|
|
211
296
|
this.watchDpr();
|
|
212
297
|
this.draw();
|
|
213
298
|
};
|
|
299
|
+
this.onColorSchemeChange = () => {
|
|
300
|
+
this.refreshTheme();
|
|
301
|
+
};
|
|
302
|
+
this.queueThemeRefresh = () => {
|
|
303
|
+
if (this.themeRefreshQueued)
|
|
304
|
+
return;
|
|
305
|
+
this.themeRefreshQueued = true;
|
|
306
|
+
queueMicrotask(() => {
|
|
307
|
+
this.themeRefreshQueued = false;
|
|
308
|
+
if (this.isConnected)
|
|
309
|
+
this.refreshTheme();
|
|
310
|
+
});
|
|
311
|
+
};
|
|
312
|
+
this.scheduleDraw = () => {
|
|
313
|
+
if (this.drawRafId !== undefined)
|
|
314
|
+
return;
|
|
315
|
+
this.drawRafId = requestAnimationFrame(() => {
|
|
316
|
+
this.drawRafId = undefined;
|
|
317
|
+
if (this.isConnected)
|
|
318
|
+
this.draw();
|
|
319
|
+
});
|
|
320
|
+
};
|
|
214
321
|
this.onPointerMove = (e) => {
|
|
215
|
-
|
|
322
|
+
const next = this.hitTest(e.offsetX, e.offsetY);
|
|
323
|
+
if (!this.samePos(this.hoverCell, next))
|
|
324
|
+
this.hoverCell = next;
|
|
216
325
|
};
|
|
217
326
|
this.onPointerLeave = () => {
|
|
218
327
|
this.hoverCell = null;
|
|
219
328
|
};
|
|
220
329
|
this.onCanvasClick = (e) => {
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
//
|
|
224
|
-
|
|
330
|
+
// Only the click's own hit-tested position counts — a click that lands
|
|
331
|
+
// outside the grid (e.g. on the canvas's own padding) is a genuine
|
|
332
|
+
// out-of-grid click and should do nothing, not fall back to whatever
|
|
333
|
+
// cell happens to still be keyboard-focused from an earlier interaction.
|
|
334
|
+
const pos = this.hitTest(e.offsetX, e.offsetY);
|
|
225
335
|
if (!pos)
|
|
226
336
|
return;
|
|
227
337
|
this.focusedCell = pos;
|
|
@@ -236,16 +346,49 @@ export class LyraHeatmap extends LyraElement {
|
|
|
236
346
|
};
|
|
237
347
|
}
|
|
238
348
|
static { this.styles = [LyraElement.styles, styles, srOnly]; }
|
|
349
|
+
/**
|
|
350
|
+
* Effective per-cell size (CSS px). Originally matrix-mode only; now also
|
|
351
|
+
* governs calendar mode's cell size (replacing the previously hardcoded
|
|
352
|
+
* 11px constant there) once explicitly set. Left unset, each mode keeps
|
|
353
|
+
* its own original default — `DEFAULT_MATRIX_CELL_SIZE` (22) in matrix
|
|
354
|
+
* mode, `CAL_CELL` (11) in calendar mode — so an existing consumer who
|
|
355
|
+
* never touches `cellSize` sees no change in either mode. Set explicitly
|
|
356
|
+
* (attribute or property), the same value governs both modes alike.
|
|
357
|
+
*/
|
|
358
|
+
get cellSize() {
|
|
359
|
+
return this._cellSize ?? (this.mode === 'calendar' ? CAL_CELL : DEFAULT_MATRIX_CELL_SIZE);
|
|
360
|
+
}
|
|
361
|
+
set cellSize(value) {
|
|
362
|
+
const oldValue = this._cellSize;
|
|
363
|
+
this._cellSize = value;
|
|
364
|
+
this.requestUpdate('cellSize', oldValue);
|
|
365
|
+
}
|
|
366
|
+
get bucketCount() {
|
|
367
|
+
return this._bucketCount;
|
|
368
|
+
}
|
|
369
|
+
set bucketCount(value) {
|
|
370
|
+
const oldValue = this._bucketCount;
|
|
371
|
+
this._bucketCount = normalizeBucketCount(value);
|
|
372
|
+
this.requestUpdate('bucketCount', oldValue);
|
|
373
|
+
}
|
|
239
374
|
connectedCallback() {
|
|
240
375
|
super.connectedCallback();
|
|
241
|
-
this.resizeObserver = new ResizeObserver(
|
|
376
|
+
this.resizeObserver = new ResizeObserver(this.scheduleDraw);
|
|
242
377
|
this.resizeObserver.observe(this);
|
|
243
378
|
this.watchDpr();
|
|
379
|
+
this.watchTheme();
|
|
244
380
|
}
|
|
245
381
|
disconnectedCallback() {
|
|
246
382
|
super.disconnectedCallback();
|
|
247
383
|
this.resizeObserver?.disconnect();
|
|
248
384
|
this.dprQuery?.removeEventListener('change', this.onDprChange);
|
|
385
|
+
this.colorSchemeQuery?.removeEventListener('change', this.onColorSchemeChange);
|
|
386
|
+
this.themeObserver?.disconnect();
|
|
387
|
+
this.themeObserver = undefined;
|
|
388
|
+
if (this.drawRafId !== undefined) {
|
|
389
|
+
cancelAnimationFrame(this.drawRafId);
|
|
390
|
+
this.drawRafId = undefined;
|
|
391
|
+
}
|
|
249
392
|
}
|
|
250
393
|
watchDpr() {
|
|
251
394
|
// A MediaQueryList's `matches` is fixed at creation time, so crossing the
|
|
@@ -256,30 +399,89 @@ export class LyraHeatmap extends LyraElement {
|
|
|
256
399
|
this.dprQuery = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
257
400
|
this.dprQuery.addEventListener('change', this.onDprChange);
|
|
258
401
|
}
|
|
402
|
+
watchTheme() {
|
|
403
|
+
const view = this.ownerDocument.defaultView;
|
|
404
|
+
if (!view)
|
|
405
|
+
return;
|
|
406
|
+
this.colorSchemeQuery = view.matchMedia?.('(prefers-color-scheme: dark)');
|
|
407
|
+
this.colorSchemeQuery?.addEventListener('change', this.onColorSchemeChange);
|
|
408
|
+
if (typeof MutationObserver === 'undefined')
|
|
409
|
+
return;
|
|
410
|
+
const targets = [this];
|
|
411
|
+
let parent = this.parentElement;
|
|
412
|
+
while (parent) {
|
|
413
|
+
targets.push(parent);
|
|
414
|
+
parent = parent.parentElement;
|
|
415
|
+
}
|
|
416
|
+
this.themeObserver = new MutationObserver(this.queueThemeRefresh);
|
|
417
|
+
for (const target of targets) {
|
|
418
|
+
this.themeObserver.observe(target, {
|
|
419
|
+
attributes: true,
|
|
420
|
+
attributeFilter: ['class', 'style', 'data-theme', 'data-color-scheme'],
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
259
424
|
willUpdate(changed) {
|
|
260
|
-
if (changed.has('mode') ||
|
|
425
|
+
if (changed.has('mode') ||
|
|
426
|
+
changed.has('rowLabels') ||
|
|
427
|
+
changed.has('colLabels') ||
|
|
428
|
+
changed.has('days') ||
|
|
429
|
+
changed.has('firstDayOfWeek')) {
|
|
261
430
|
// The previous focus/hover cursor may no longer address a real cell
|
|
262
431
|
// once the grid's shape (or mode) changes out from under it —
|
|
263
432
|
// stroking a focus ring at a stale (row, col)/(week, weekday), or
|
|
264
433
|
// leaving the live region announcing a stale value, would be actively
|
|
265
434
|
// misleading, so drop both instead. Reactive-property writes belong in
|
|
266
435
|
// willUpdate() (not updated()), which folds them into this same
|
|
267
|
-
// render rather than scheduling a whole extra update pass.
|
|
436
|
+
// render rather than scheduling a whole extra update pass. A
|
|
437
|
+
// `firstDayOfWeek` change reshuffles every cell's week/weekday the same
|
|
438
|
+
// way a `days` change does, so it resets the cursor too.
|
|
268
439
|
this.focusedCell = null;
|
|
269
440
|
this.hoverCell = null;
|
|
270
441
|
this.liveText = '';
|
|
271
442
|
}
|
|
272
|
-
|
|
443
|
+
// Calendar-mode grid layout depends only on `days`/`firstDayOfWeek` (not
|
|
444
|
+
// `mode`) — rebuilt here, once per cycle, instead of independently by
|
|
445
|
+
// every call site (see `cachedCalendarGrid`'s doc comment).
|
|
446
|
+
if (changed.has('days') || changed.has('firstDayOfWeek') || !this.hasUpdated) {
|
|
447
|
+
this.cachedCalendarGrid = buildCalendarGrid(this.days, this.firstDayOfWeek);
|
|
448
|
+
this.cachedCalendarSortedValues = this.cachedCalendarGrid.cells
|
|
449
|
+
.map((cell) => cell.value)
|
|
450
|
+
.filter((value) => Number.isFinite(value) && value >= 0)
|
|
451
|
+
.sort((a, b) => a - b);
|
|
452
|
+
this.cachedCalendarCellsByPos = new Map(this.cachedCalendarGrid.cells.map((cell) => [`${cell.week}:${cell.weekday}`, cell]));
|
|
453
|
+
}
|
|
454
|
+
if (!this.hasUpdated) {
|
|
455
|
+
this.authorSuppliedRole = this.hasAttribute('role');
|
|
456
|
+
this.authorSuppliedAriaLabel = this.hasAttribute('aria-label');
|
|
457
|
+
}
|
|
458
|
+
// A hover/keyboard-focus @state() change (hoverCell/focusedCell/liveText)
|
|
459
|
+
// triggers this same willUpdate() but never touches values/days/mode, so
|
|
460
|
+
// gating the O(rows*cols) rescan the same way the focus/hover reset above
|
|
461
|
+
// is gated avoids redoing it on every pointer move.
|
|
462
|
+
if (changed.has('values') || changed.has('days') || changed.has('mode') || !this.hasUpdated) {
|
|
463
|
+
this.cachedValueRange = this.computeValueRange();
|
|
464
|
+
}
|
|
273
465
|
const bounds = this.cachedValueRange;
|
|
274
466
|
const range = bounds ? `${bounds[0]}–${bounds[1]}` : 'no data';
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
467
|
+
// Only default role/aria-label when the author hasn't already supplied
|
|
468
|
+
// one — the canvas is a genuinely focusable/interactive control
|
|
469
|
+
// (tabindex="0", click/keydown handlers) plus a live role="status"
|
|
470
|
+
// region, so unconditionally forcing a role here would tell assistive
|
|
471
|
+
// tech to flatten the whole subtree, hiding both from the accessibility
|
|
472
|
+
// tree; it would also silently overwrite any author-supplied
|
|
473
|
+
// role/aria-label on every update.
|
|
474
|
+
if (!this.authorSuppliedRole)
|
|
475
|
+
this.setAttribute('role', 'group');
|
|
476
|
+
if (!this.authorSuppliedAriaLabel) {
|
|
477
|
+
if (this.mode === 'calendar') {
|
|
478
|
+
this.setAttribute('aria-label', `Calendar heatmap of ${this.days.length} days, ${this.valueLabel} range ${range}`);
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
const rows = this.rowLabels.length;
|
|
482
|
+
const cols = this.colLabels.length;
|
|
483
|
+
this.setAttribute('aria-label', `Heatmap of ${rows} × ${cols} cells, ${this.valueLabel} range ${range}`);
|
|
484
|
+
}
|
|
283
485
|
}
|
|
284
486
|
}
|
|
285
487
|
/**
|
|
@@ -295,7 +497,29 @@ export class LyraHeatmap extends LyraElement {
|
|
|
295
497
|
const source = this.mode === 'calendar' ? this.days.map((d) => d.value) : this.values.flat();
|
|
296
498
|
return minMax(source.filter((v) => Number.isFinite(v) && v >= 0));
|
|
297
499
|
}
|
|
298
|
-
updated() {
|
|
500
|
+
updated(changed) {
|
|
501
|
+
if ([
|
|
502
|
+
'values',
|
|
503
|
+
'rowLabels',
|
|
504
|
+
'colLabels',
|
|
505
|
+
'cellSize',
|
|
506
|
+
'valueLabel',
|
|
507
|
+
'scale',
|
|
508
|
+
'fitToWidth',
|
|
509
|
+
'mode',
|
|
510
|
+
'days',
|
|
511
|
+
'bucketCount',
|
|
512
|
+
'annotations',
|
|
513
|
+
'columnX',
|
|
514
|
+
'rowY',
|
|
515
|
+
'firstDayOfWeek',
|
|
516
|
+
'focusedCell',
|
|
517
|
+
].some((name) => changed.has(name))) {
|
|
518
|
+
this.draw();
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
/** Redraws canvas content after an upstream token or theme change. */
|
|
522
|
+
refreshTheme() {
|
|
299
523
|
this.draw();
|
|
300
524
|
}
|
|
301
525
|
/** Reads the customizable ramp endpoints off the host's computed style. */
|
|
@@ -331,12 +555,141 @@ export class LyraHeatmap extends LyraElement {
|
|
|
331
555
|
else
|
|
332
556
|
this.drawMatrix();
|
|
333
557
|
}
|
|
558
|
+
colorRamp(bucketCount) {
|
|
559
|
+
const [scaleLo, scaleHi] = this.scaleEndpoints();
|
|
560
|
+
const normalizedBucketCount = normalizeBucketCount(bucketCount);
|
|
561
|
+
const key = `${scaleLo}\u0000${scaleHi}\u0000${normalizedBucketCount}`;
|
|
562
|
+
if (this.cachedRamp?.key === key)
|
|
563
|
+
return this.cachedRamp;
|
|
564
|
+
const loRgb = resolveRgb(scaleLo, FALLBACK_SCALE_LO);
|
|
565
|
+
const hiRgb = resolveRgb(scaleHi, FALLBACK_SCALE_HI);
|
|
566
|
+
const colors = Array.from({ length: normalizedBucketCount }, (_, i) => mixRgb(loRgb, hiRgb, i / (normalizedBucketCount - 1)));
|
|
567
|
+
this.cachedRamp = { key, colors, loRgb, hiRgb };
|
|
568
|
+
return this.cachedRamp;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Effective per-cell size in calendar mode — mirrors `matrixCellSize()`
|
|
572
|
+
* exactly: `fitToWidth` derives it from the host's measured width,
|
|
573
|
+
* otherwise it's the (possibly explicitly-set) `cellSize` property, which
|
|
574
|
+
* itself falls back to today's original 11px calendar default when left
|
|
575
|
+
* unset (see `cellSize`'s accessor doc comment). Shared by `columnXFor()`,
|
|
576
|
+
* `rowYFor()`, `drawCalendar()`, and the hit-testing below (`weekAtX()`,
|
|
577
|
+
* `weekdayAtY()`, `cellRect()`) so they always agree on exactly the same
|
|
578
|
+
* geometry as what's actually painted.
|
|
579
|
+
*/
|
|
580
|
+
calendarCellSize() {
|
|
581
|
+
const { weekCount } = this.cachedCalendarGrid;
|
|
582
|
+
if (this.fitToWidth && weekCount > 0) {
|
|
583
|
+
// Unlike matrix mode's contiguous cells, calendar columns are spaced
|
|
584
|
+
// `cellSize + CAL_GAP` apart (see `columnXFor()`), so the gap has to be
|
|
585
|
+
// subtracted back out here — otherwise the painted width would overshoot
|
|
586
|
+
// `hostWidth` by `weekCount * CAL_GAP` (every column's gap, once each).
|
|
587
|
+
const hostWidth = this.clientWidth || CAL_PAD_LEFT + weekCount * (this.cellSize + CAL_GAP);
|
|
588
|
+
return Math.max(4, (hostWidth - CAL_PAD_LEFT) / weekCount - CAL_GAP);
|
|
589
|
+
}
|
|
590
|
+
return this.cellSize;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Calendar-mode week-column x-origin (canvas-local CSS px) — `columnX(week)`
|
|
594
|
+
* when set, otherwise the original evenly-spaced formula (now derived from
|
|
595
|
+
* `calendarCellSize()` rather than the fixed `CAL_CELL` constant). Shared
|
|
596
|
+
* by every calendar-mode drawing and hit-testing call site (`drawCalendar()`,
|
|
597
|
+
* `hitTestCalendar()`/`weekAtX()`, `cellRect()`) so painted geometry and
|
|
598
|
+
* interactive hit-testing never disagree — mirrors the existing
|
|
599
|
+
* `matrixCellSize()` invariant for matrix mode's
|
|
600
|
+
* `drawMatrix()`/`hitTestMatrix()`/`cellRect()`.
|
|
601
|
+
*/
|
|
602
|
+
columnXFor(week) {
|
|
603
|
+
return this.columnX ? this.columnX(week) : CAL_PAD_LEFT + week * (this.calendarCellSize() + CAL_GAP);
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Calendar-mode weekday-row y-origin (canvas-local CSS px) — `rowY(weekday)`
|
|
607
|
+
* when set, otherwise the original evenly-spaced formula (now derived from
|
|
608
|
+
* `calendarCellSize()` rather than the fixed `CAL_CELL` constant). The
|
|
609
|
+
* vertical analogue of `columnXFor()`, mirroring its exact
|
|
610
|
+
* dispatch-with-computed-fallback shape and shared by the same
|
|
611
|
+
* drawing/hit-testing/focus-ring call sites.
|
|
612
|
+
*/
|
|
613
|
+
rowYFor(weekday) {
|
|
614
|
+
return this.rowY ? this.rowY(weekday) : CAL_LABEL_H + weekday * (this.calendarCellSize() + CAL_GAP);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Inverse of `columnXFor()`: resolves an x position (canvas-local CSS px)
|
|
618
|
+
* to the week column it falls in, or `null` if it's outside every column
|
|
619
|
+
* (`weekCount` is 0, or `x` doesn't land inside `[0, weekCount)`'s span).
|
|
620
|
+
* The default spacing has a closed-form inverse (division); an arbitrary
|
|
621
|
+
* `columnX` override doesn't, so that case instead scans each column's
|
|
622
|
+
* `[columnXFor(week), columnXFor(week + 1))` span — algebraically the same
|
|
623
|
+
* span the default formula's division derives — so hit-testing always
|
|
624
|
+
* agrees with wherever `columnXFor()` actually painted that column.
|
|
625
|
+
*/
|
|
626
|
+
weekAtX(x, weekCount) {
|
|
627
|
+
if (!this.columnX) {
|
|
628
|
+
const cellSize = this.calendarCellSize();
|
|
629
|
+
const week = Math.floor((x - CAL_PAD_LEFT) / (cellSize + CAL_GAP));
|
|
630
|
+
return week >= 0 && week < weekCount ? week : null;
|
|
631
|
+
}
|
|
632
|
+
for (let week = 0; week < weekCount; week++) {
|
|
633
|
+
const start = this.columnXFor(week);
|
|
634
|
+
const end = week + 1 < weekCount ? this.columnXFor(week + 1) : start + (this.calendarCellSize() + CAL_GAP);
|
|
635
|
+
if (x >= start && x < end)
|
|
636
|
+
return week;
|
|
637
|
+
}
|
|
638
|
+
return null;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Inverse of `rowYFor()`: resolves a y position (canvas-local CSS px) to
|
|
642
|
+
* the weekday row it falls in (0-6), or `null` if it's outside every row.
|
|
643
|
+
* Mirrors `weekAtX()`'s closed-form-vs-scan split for the same reason: the
|
|
644
|
+
* default spacing has a closed-form inverse; an arbitrary `rowY` override
|
|
645
|
+
* doesn't.
|
|
646
|
+
*/
|
|
647
|
+
weekdayAtY(y) {
|
|
648
|
+
if (!this.rowY) {
|
|
649
|
+
const cellSize = this.calendarCellSize();
|
|
650
|
+
const weekday = Math.floor((y - CAL_LABEL_H) / (cellSize + CAL_GAP));
|
|
651
|
+
return weekday >= 0 && weekday < 7 ? weekday : null;
|
|
652
|
+
}
|
|
653
|
+
for (let weekday = 0; weekday < 7; weekday++) {
|
|
654
|
+
const start = this.rowYFor(weekday);
|
|
655
|
+
const end = weekday + 1 < 7 ? this.rowYFor(weekday + 1) : start + (this.calendarCellSize() + CAL_GAP);
|
|
656
|
+
if (y >= start && y < end)
|
|
657
|
+
return weekday;
|
|
658
|
+
}
|
|
659
|
+
return null;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Locale-derived weekday-axis labels for the 7 rows drawn down the left of
|
|
663
|
+
* the calendar grid. Only indices 1, 3, and 5 (relative to `firstWeekStart`)
|
|
664
|
+
* are filled in — matching today's sparse every-other-day label density —
|
|
665
|
+
* the rest stay blank. `firstWeekStart` is always the UTC
|
|
666
|
+
* `firstDayOfWeek`-weekday by construction (see `buildCalendarGrid()`), so
|
|
667
|
+
* weekday index 0..6 is a fixed positional mapping relative to it (with the
|
|
668
|
+
* default `firstDayOfWeek` of 0, that's the original Sun..Sat mapping,
|
|
669
|
+
* unchanged); only the label *text* for indices 1/3/5 is derived here, via
|
|
670
|
+
* `Intl.DateTimeFormat` on a real UTC date that actually falls on that
|
|
671
|
+
* weekday, so it follows the runtime locale instead of a hardcoded English
|
|
672
|
+
* array (see `calendarCellText()`'s tooltip text for the same pattern).
|
|
673
|
+
*/
|
|
674
|
+
weekdayLabels(firstWeekStart) {
|
|
675
|
+
const formatter = new Intl.DateTimeFormat(undefined, { weekday: 'short', timeZone: 'UTC' });
|
|
676
|
+
const labels = ['', '', '', '', '', '', ''];
|
|
677
|
+
for (const weekday of [1, 3, 5]) {
|
|
678
|
+
labels[weekday] = formatter.format(new Date(firstWeekStart.getTime() + weekday * MS_PER_DAY));
|
|
679
|
+
}
|
|
680
|
+
return labels;
|
|
681
|
+
}
|
|
334
682
|
drawCalendar() {
|
|
335
683
|
if (!this.canvas)
|
|
336
684
|
return;
|
|
337
|
-
const { cells, weekCount, monthLabels } =
|
|
338
|
-
const
|
|
339
|
-
const
|
|
685
|
+
const { cells, weekCount, firstWeekStart, monthLabels } = this.cachedCalendarGrid;
|
|
686
|
+
const cellSize = this.calendarCellSize();
|
|
687
|
+
const w = this.columnXFor(Math.max(1, weekCount));
|
|
688
|
+
// Derived from `rowYFor(7)` (one past the last of the 7 weekday rows), the
|
|
689
|
+
// vertical mirror of `w`'s `columnXFor(weekCount)` — so a custom `rowY`
|
|
690
|
+
// that spaces rows out further than the default formula still gets a
|
|
691
|
+
// canvas tall enough to paint every row, instead of clipping them.
|
|
692
|
+
const h = this.rowYFor(7);
|
|
340
693
|
const dpr = window.devicePixelRatio || 1;
|
|
341
694
|
this.canvas.width = w * dpr;
|
|
342
695
|
this.canvas.height = h * dpr;
|
|
@@ -347,24 +700,39 @@ export class LyraHeatmap extends LyraElement {
|
|
|
347
700
|
return;
|
|
348
701
|
ctx.scale(dpr, dpr);
|
|
349
702
|
ctx.clearRect(0, 0, w, h);
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
const [scaleLo, scaleHi] = this.scaleEndpoints();
|
|
355
|
-
const loRgb = resolveRgb(scaleLo, FALLBACK_SCALE_LO);
|
|
356
|
-
const hiRgb = resolveRgb(scaleHi, FALLBACK_SCALE_HI);
|
|
357
|
-
const buckets = resolveBucketCount(this.bucketCount);
|
|
358
|
-
const ramp = Array.from({ length: buckets }, (_, i) => mixRgb(loRgb, hiRgb, i / (buckets - 1)));
|
|
703
|
+
// Normalize at the allocation boundary as a final guard even though the
|
|
704
|
+
// public accessor and attribute converter already normalize their inputs.
|
|
705
|
+
const buckets = normalizeBucketCount(this.bucketCount);
|
|
706
|
+
const ramp = this.colorRamp(buckets).colors;
|
|
359
707
|
const noDataFill = this.noDataFill();
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
708
|
+
// Only consulted when `scale === 'sqrt'` — mirrors `drawMatrix()`'s own
|
|
709
|
+
// `hi` bound, reusing the already-cached value range instead of
|
|
710
|
+
// rescanning `sortedValues` for its max.
|
|
711
|
+
const bounds = this.cachedValueRange;
|
|
712
|
+
const hi = bounds ? bounds[1] : 1;
|
|
713
|
+
// Indexed once per draw so every (week, weekday) grid position can be
|
|
714
|
+
// painted below, not just positions with a matching entry in `cells` — a
|
|
715
|
+
// day missing from `days` entirely (a gap in a sparse calendar) still
|
|
716
|
+
// gets a real grid cell (see `calendarCellAt()`'s doc comment for the
|
|
717
|
+
// same `-1` no-data sentinel used here) instead of being left
|
|
718
|
+
// transparent.
|
|
719
|
+
for (let week = 0; week < weekCount; week++) {
|
|
720
|
+
for (let weekday = 0; weekday < 7; weekday++) {
|
|
721
|
+
const value = this.cachedCalendarCellsByPos.get(`${week}:${weekday}`)?.value ?? -1;
|
|
722
|
+
const x = this.columnXFor(week);
|
|
723
|
+
const y = this.rowYFor(weekday);
|
|
724
|
+
if (value < 0 || !Number.isFinite(value)) {
|
|
725
|
+
ctx.fillStyle = noDataFill;
|
|
726
|
+
}
|
|
727
|
+
else if (this.scale === 'sqrt') {
|
|
728
|
+
const step = sqrtStep(value, hi, buckets);
|
|
729
|
+
ctx.fillStyle = step < 0 ? noDataFill : ramp[step];
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
ctx.fillStyle = ramp[quartileBucket(value, this.cachedCalendarSortedValues, buckets)];
|
|
733
|
+
}
|
|
734
|
+
ctx.fillRect(x, y, cellSize, cellSize);
|
|
735
|
+
}
|
|
368
736
|
}
|
|
369
737
|
// Annotation ring overlay, stroked after the fill pass so it reads
|
|
370
738
|
// clearly over the data-driven cell color — see drawMatrix()'s twin of
|
|
@@ -378,9 +746,9 @@ export class LyraHeatmap extends LyraElement {
|
|
|
378
746
|
const match = cells.find((c) => c.date === ann.date);
|
|
379
747
|
if (!match)
|
|
380
748
|
continue;
|
|
381
|
-
const x =
|
|
382
|
-
const y =
|
|
383
|
-
ctx.strokeRect(x + 0.5, y + 0.5,
|
|
749
|
+
const x = this.columnXFor(match.week);
|
|
750
|
+
const y = this.rowYFor(match.weekday);
|
|
751
|
+
ctx.strokeRect(x + 0.5, y + 0.5, cellSize - 1, cellSize - 1);
|
|
384
752
|
}
|
|
385
753
|
}
|
|
386
754
|
// Keyboard focus ring, redrawn on top of the fill pass (and any
|
|
@@ -390,20 +758,20 @@ export class LyraHeatmap extends LyraElement {
|
|
|
390
758
|
if (week < weekCount && weekday < 7) {
|
|
391
759
|
ctx.lineWidth = RING_LINE_WIDTH;
|
|
392
760
|
ctx.strokeStyle = this.focusRingColor();
|
|
393
|
-
const x =
|
|
394
|
-
const y =
|
|
395
|
-
ctx.strokeRect(x + 0.5, y + 0.5,
|
|
761
|
+
const x = this.columnXFor(week);
|
|
762
|
+
const y = this.rowYFor(weekday);
|
|
763
|
+
ctx.strokeRect(x + 0.5, y + 0.5, cellSize - 1, cellSize - 1);
|
|
396
764
|
}
|
|
397
765
|
}
|
|
398
766
|
ctx.fillStyle = this.labelColor();
|
|
399
767
|
ctx.font = this.labelFont();
|
|
400
768
|
for (const m of monthLabels) {
|
|
401
|
-
ctx.fillText(m.label,
|
|
769
|
+
ctx.fillText(m.label, this.columnXFor(m.week), CAL_LABEL_H - 4);
|
|
402
770
|
}
|
|
403
|
-
const WEEKDAY_LABELS =
|
|
771
|
+
const WEEKDAY_LABELS = this.weekdayLabels(firstWeekStart);
|
|
404
772
|
WEEKDAY_LABELS.forEach((label, weekday) => {
|
|
405
773
|
if (label)
|
|
406
|
-
ctx.fillText(label, 2,
|
|
774
|
+
ctx.fillText(label, 2, this.rowYFor(weekday) + cellSize - 1);
|
|
407
775
|
});
|
|
408
776
|
}
|
|
409
777
|
/**
|
|
@@ -441,10 +809,9 @@ export class LyraHeatmap extends LyraElement {
|
|
|
441
809
|
const bounds = this.cachedValueRange;
|
|
442
810
|
const lo = bounds ? bounds[0] : 0;
|
|
443
811
|
const hi = bounds ? bounds[1] : 1;
|
|
444
|
-
const
|
|
445
|
-
const
|
|
446
|
-
const hiRgb =
|
|
447
|
-
const ramp = Array.from({ length: RAMP_STEPS }, (_, i) => mixRgb(loRgb, hiRgb, i / (RAMP_STEPS - 1)));
|
|
812
|
+
const rampData = this.colorRamp(RAMP_STEPS);
|
|
813
|
+
const ramp = rampData.colors;
|
|
814
|
+
const { loRgb, hiRgb } = rampData;
|
|
448
815
|
const noDataFill = this.noDataFill();
|
|
449
816
|
for (let r = 0; r < rows; r++) {
|
|
450
817
|
for (let c = 0; c < cols; c++) {
|
|
@@ -536,12 +903,12 @@ export class LyraHeatmap extends LyraElement {
|
|
|
536
903
|
return { row, col };
|
|
537
904
|
}
|
|
538
905
|
hitTestCalendar(x, y) {
|
|
539
|
-
const { weekCount } =
|
|
906
|
+
const { weekCount } = this.cachedCalendarGrid;
|
|
540
907
|
if (weekCount === 0)
|
|
541
908
|
return null;
|
|
542
|
-
const week =
|
|
543
|
-
const weekday =
|
|
544
|
-
if (week
|
|
909
|
+
const week = this.weekAtX(x, weekCount);
|
|
910
|
+
const weekday = this.weekdayAtY(y);
|
|
911
|
+
if (week === null || weekday === null)
|
|
545
912
|
return null;
|
|
546
913
|
return { week, weekday };
|
|
547
914
|
}
|
|
@@ -554,7 +921,7 @@ export class LyraHeatmap extends LyraElement {
|
|
|
554
921
|
* sentinel uses in matrix mode), instead of being unresolvable.
|
|
555
922
|
*/
|
|
556
923
|
calendarCellAt(pos) {
|
|
557
|
-
const { cells, firstWeekStart } =
|
|
924
|
+
const { cells, firstWeekStart } = this.cachedCalendarGrid;
|
|
558
925
|
const match = cells.find((c) => c.week === pos.week && c.weekday === pos.weekday);
|
|
559
926
|
if (match)
|
|
560
927
|
return { date: match.date, value: match.value };
|
|
@@ -568,11 +935,12 @@ export class LyraHeatmap extends LyraElement {
|
|
|
568
935
|
*/
|
|
569
936
|
cellRect(pos) {
|
|
570
937
|
if ('week' in pos) {
|
|
938
|
+
const cellSize = this.calendarCellSize();
|
|
571
939
|
return {
|
|
572
|
-
x:
|
|
573
|
-
y:
|
|
574
|
-
w:
|
|
575
|
-
h:
|
|
940
|
+
x: this.columnXFor(pos.week),
|
|
941
|
+
y: this.rowYFor(pos.weekday),
|
|
942
|
+
w: cellSize,
|
|
943
|
+
h: cellSize,
|
|
576
944
|
};
|
|
577
945
|
}
|
|
578
946
|
const cellSize = this.matrixCellSize(this.colLabels.length);
|
|
@@ -630,6 +998,24 @@ export class LyraHeatmap extends LyraElement {
|
|
|
630
998
|
const rect = this.cellRect(pos);
|
|
631
999
|
return { left: `${rect.x + rect.w / 2}px`, top: `${rect.y}px` };
|
|
632
1000
|
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Value-equality check for a `CellPos`, since `hoverCell` is assigned a
|
|
1003
|
+
* fresh object literal on every `pointermove` — Lit's `@state()`
|
|
1004
|
+
* change-detection only no-ops an identical *reference*, so without this,
|
|
1005
|
+
* `{row,col} !== {row,col}` by reference triggers a full canvas clear +
|
|
1006
|
+
* redraw on every pixel of pointer movement, even within the same cell.
|
|
1007
|
+
*/
|
|
1008
|
+
samePos(a, b) {
|
|
1009
|
+
if (a === b)
|
|
1010
|
+
return true;
|
|
1011
|
+
if (!a || !b)
|
|
1012
|
+
return false;
|
|
1013
|
+
if ('week' in a && 'week' in b)
|
|
1014
|
+
return a.week === b.week && a.weekday === b.weekday;
|
|
1015
|
+
if ('row' in a && 'row' in b)
|
|
1016
|
+
return a.row === b.row && a.col === b.col;
|
|
1017
|
+
return false;
|
|
1018
|
+
}
|
|
633
1019
|
onMatrixKeyDown(e) {
|
|
634
1020
|
const rows = this.rowLabels.length;
|
|
635
1021
|
const cols = this.colLabels.length;
|
|
@@ -668,7 +1054,7 @@ export class LyraHeatmap extends LyraElement {
|
|
|
668
1054
|
this.announce(next);
|
|
669
1055
|
}
|
|
670
1056
|
onCalendarKeyDown(e) {
|
|
671
|
-
const { weekCount } =
|
|
1057
|
+
const { weekCount } = this.cachedCalendarGrid;
|
|
672
1058
|
if (weekCount === 0)
|
|
673
1059
|
return;
|
|
674
1060
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
@@ -742,7 +1128,7 @@ __decorate([
|
|
|
742
1128
|
], LyraHeatmap.prototype, "values", void 0);
|
|
743
1129
|
__decorate([
|
|
744
1130
|
property({ type: Number, attribute: 'cell-size' })
|
|
745
|
-
], LyraHeatmap.prototype, "cellSize",
|
|
1131
|
+
], LyraHeatmap.prototype, "cellSize", null);
|
|
746
1132
|
__decorate([
|
|
747
1133
|
property({ attribute: 'value-label' })
|
|
748
1134
|
], LyraHeatmap.prototype, "valueLabel", void 0);
|
|
@@ -759,14 +1145,23 @@ __decorate([
|
|
|
759
1145
|
property({ attribute: false })
|
|
760
1146
|
], LyraHeatmap.prototype, "days", void 0);
|
|
761
1147
|
__decorate([
|
|
762
|
-
property({ attribute: '
|
|
763
|
-
], LyraHeatmap.prototype, "
|
|
1148
|
+
property({ type: Number, attribute: 'first-day-of-week' })
|
|
1149
|
+
], LyraHeatmap.prototype, "firstDayOfWeek", void 0);
|
|
1150
|
+
__decorate([
|
|
1151
|
+
property({ attribute: 'bucket-count', converter: bucketCountConverter })
|
|
1152
|
+
], LyraHeatmap.prototype, "bucketCount", null);
|
|
764
1153
|
__decorate([
|
|
765
1154
|
property({ attribute: false })
|
|
766
1155
|
], LyraHeatmap.prototype, "annotations", void 0);
|
|
767
1156
|
__decorate([
|
|
768
1157
|
property({ attribute: false })
|
|
769
1158
|
], LyraHeatmap.prototype, "cellText", void 0);
|
|
1159
|
+
__decorate([
|
|
1160
|
+
property({ attribute: false })
|
|
1161
|
+
], LyraHeatmap.prototype, "columnX", void 0);
|
|
1162
|
+
__decorate([
|
|
1163
|
+
property({ attribute: false })
|
|
1164
|
+
], LyraHeatmap.prototype, "rowY", void 0);
|
|
770
1165
|
__decorate([
|
|
771
1166
|
query('canvas')
|
|
772
1167
|
], LyraHeatmap.prototype, "canvas", void 0);
|