@aceshooting/lyra-ui 3.6.0 → 3.8.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 +109 -3
- package/custom-elements.json +91136 -42119
- package/dist/components/activity-feed/activity-feed.class.d.ts +111 -0
- package/dist/components/activity-feed/activity-feed.class.d.ts.map +1 -0
- package/dist/components/activity-feed/activity-feed.class.js +292 -0
- package/dist/components/activity-feed/activity-feed.class.js.map +1 -0
- package/dist/components/activity-feed/activity-feed.d.ts +2 -0
- package/dist/components/activity-feed/activity-feed.d.ts.map +1 -0
- package/dist/components/activity-feed/activity-feed.js +5 -0
- package/dist/components/activity-feed/activity-feed.js.map +1 -0
- package/dist/components/activity-feed/activity-feed.styles.d.ts +2 -0
- package/dist/components/activity-feed/activity-feed.styles.d.ts.map +1 -0
- package/dist/components/activity-feed/activity-feed.styles.js +147 -0
- package/dist/components/activity-feed/activity-feed.styles.js.map +1 -0
- package/dist/components/animation/animation.class.d.ts +12 -0
- package/dist/components/animation/animation.class.d.ts.map +1 -1
- package/dist/components/animation/animation.class.js +47 -7
- package/dist/components/animation/animation.class.js.map +1 -1
- package/dist/components/app-rail/app-rail.class.d.ts +19 -3
- package/dist/components/app-rail/app-rail.class.d.ts.map +1 -1
- package/dist/components/app-rail/app-rail.class.js +34 -12
- package/dist/components/app-rail/app-rail.class.js.map +1 -1
- package/dist/components/app-rail/app-rail.styles.d.ts.map +1 -1
- package/dist/components/app-rail/app-rail.styles.js +19 -11
- package/dist/components/app-rail/app-rail.styles.js.map +1 -1
- package/dist/components/artifact-panel/artifact-panel.class.d.ts +100 -0
- package/dist/components/artifact-panel/artifact-panel.class.d.ts.map +1 -0
- package/dist/components/artifact-panel/artifact-panel.class.js +254 -0
- package/dist/components/artifact-panel/artifact-panel.class.js.map +1 -0
- package/dist/components/artifact-panel/artifact-panel.d.ts +2 -0
- package/dist/components/artifact-panel/artifact-panel.d.ts.map +1 -0
- package/dist/components/artifact-panel/artifact-panel.js +5 -0
- package/dist/components/artifact-panel/artifact-panel.js.map +1 -0
- package/dist/components/artifact-panel/artifact-panel.styles.d.ts +2 -0
- package/dist/components/artifact-panel/artifact-panel.styles.d.ts.map +1 -0
- package/dist/components/artifact-panel/artifact-panel.styles.js +97 -0
- package/dist/components/artifact-panel/artifact-panel.styles.js.map +1 -0
- package/dist/components/attachment-chip/attachment-chip.class.d.ts +4 -2
- package/dist/components/attachment-chip/attachment-chip.class.d.ts.map +1 -1
- package/dist/components/attachment-chip/attachment-chip.class.js +10 -5
- package/dist/components/attachment-chip/attachment-chip.class.js.map +1 -1
- package/dist/components/attachment-chip/attachment-chip.styles.d.ts.map +1 -1
- package/dist/components/attachment-chip/attachment-chip.styles.js +7 -2
- package/dist/components/attachment-chip/attachment-chip.styles.js.map +1 -1
- package/dist/components/attachment-trigger/attachment-trigger.class.d.ts +17 -12
- package/dist/components/attachment-trigger/attachment-trigger.class.d.ts.map +1 -1
- package/dist/components/attachment-trigger/attachment-trigger.class.js +28 -8
- package/dist/components/attachment-trigger/attachment-trigger.class.js.map +1 -1
- package/dist/components/attachment-trigger/attachment-trigger.styles.d.ts.map +1 -1
- package/dist/components/attachment-trigger/attachment-trigger.styles.js +11 -0
- package/dist/components/attachment-trigger/attachment-trigger.styles.js.map +1 -1
- package/dist/components/audio-visualizer/audio-visualizer.class.d.ts +111 -0
- package/dist/components/audio-visualizer/audio-visualizer.class.d.ts.map +1 -0
- package/dist/components/audio-visualizer/audio-visualizer.class.js +435 -0
- package/dist/components/audio-visualizer/audio-visualizer.class.js.map +1 -0
- package/dist/components/audio-visualizer/audio-visualizer.d.ts +2 -0
- package/dist/components/audio-visualizer/audio-visualizer.d.ts.map +1 -0
- package/dist/components/audio-visualizer/audio-visualizer.js +5 -0
- package/dist/components/audio-visualizer/audio-visualizer.js.map +1 -0
- package/dist/components/audio-visualizer/audio-visualizer.styles.d.ts +2 -0
- package/dist/components/audio-visualizer/audio-visualizer.styles.d.ts.map +1 -0
- package/dist/components/audio-visualizer/audio-visualizer.styles.js +20 -0
- package/dist/components/audio-visualizer/audio-visualizer.styles.js.map +1 -0
- package/dist/components/av-player/av-player.class.d.ts +215 -0
- package/dist/components/av-player/av-player.class.d.ts.map +1 -0
- package/dist/components/av-player/av-player.class.js +590 -0
- package/dist/components/av-player/av-player.class.js.map +1 -0
- package/dist/components/av-player/av-player.d.ts +2 -0
- package/dist/components/av-player/av-player.d.ts.map +1 -0
- package/dist/components/av-player/av-player.js +36 -0
- package/dist/components/av-player/av-player.js.map +1 -0
- package/dist/components/av-player/av-player.styles.d.ts +2 -0
- package/dist/components/av-player/av-player.styles.d.ts.map +1 -0
- package/dist/components/av-player/av-player.styles.js +109 -0
- package/dist/components/av-player/av-player.styles.js.map +1 -0
- package/dist/components/avatar-group/avatar-group.class.d.ts +7 -2
- package/dist/components/avatar-group/avatar-group.class.d.ts.map +1 -1
- package/dist/components/avatar-group/avatar-group.class.js +19 -2
- package/dist/components/avatar-group/avatar-group.class.js.map +1 -1
- package/dist/components/badge/tag.class.d.ts +4 -1
- package/dist/components/badge/tag.class.d.ts.map +1 -1
- package/dist/components/badge/tag.class.js +4 -1
- package/dist/components/badge/tag.class.js.map +1 -1
- package/dist/components/branch-picker/branch-picker.class.d.ts +69 -0
- package/dist/components/branch-picker/branch-picker.class.d.ts.map +1 -0
- package/dist/components/branch-picker/branch-picker.class.js +151 -0
- package/dist/components/branch-picker/branch-picker.class.js.map +1 -0
- package/dist/components/branch-picker/branch-picker.d.ts +3 -0
- package/dist/components/branch-picker/branch-picker.d.ts.map +1 -0
- package/dist/components/branch-picker/branch-picker.js +6 -0
- package/dist/components/branch-picker/branch-picker.js.map +1 -0
- package/dist/components/branch-picker/branch-picker.styles.d.ts +2 -0
- package/dist/components/branch-picker/branch-picker.styles.d.ts.map +1 -0
- package/dist/components/branch-picker/branch-picker.styles.js +64 -0
- package/dist/components/branch-picker/branch-picker.styles.js.map +1 -0
- package/dist/components/browser-frame/browser-frame.class.d.ts +70 -0
- package/dist/components/browser-frame/browser-frame.class.d.ts.map +1 -0
- package/dist/components/browser-frame/browser-frame.class.js +196 -0
- package/dist/components/browser-frame/browser-frame.class.js.map +1 -0
- package/dist/components/browser-frame/browser-frame.d.ts +2 -0
- package/dist/components/browser-frame/browser-frame.d.ts.map +1 -0
- package/dist/components/browser-frame/browser-frame.js +5 -0
- package/dist/components/browser-frame/browser-frame.js.map +1 -0
- package/dist/components/browser-frame/browser-frame.styles.d.ts +2 -0
- package/dist/components/browser-frame/browser-frame.styles.d.ts.map +1 -0
- package/dist/components/browser-frame/browser-frame.styles.js +88 -0
- package/dist/components/browser-frame/browser-frame.styles.js.map +1 -0
- package/dist/components/button/button.class.d.ts +32 -4
- package/dist/components/button/button.class.d.ts.map +1 -1
- package/dist/components/button/button.class.js +43 -7
- package/dist/components/button/button.class.js.map +1 -1
- package/dist/components/button/button.styles.d.ts.map +1 -1
- package/dist/components/button/button.styles.js +33 -0
- package/dist/components/button/button.styles.js.map +1 -1
- package/dist/components/calendar/calendar.class.d.ts +14 -2
- package/dist/components/calendar/calendar.class.d.ts.map +1 -1
- package/dist/components/calendar/calendar.class.js +41 -8
- package/dist/components/calendar/calendar.class.js.map +1 -1
- package/dist/components/calendar/calendar.styles.d.ts.map +1 -1
- package/dist/components/calendar/calendar.styles.js +9 -4
- package/dist/components/calendar/calendar.styles.js.map +1 -1
- package/dist/components/calendar-viewer/calendar-viewer.class.d.ts.map +1 -1
- package/dist/components/calendar-viewer/calendar-viewer.class.js +2 -1
- package/dist/components/calendar-viewer/calendar-viewer.class.js.map +1 -1
- package/dist/components/callout/callout.class.d.ts +5 -1
- package/dist/components/callout/callout.class.d.ts.map +1 -1
- package/dist/components/callout/callout.class.js +6 -2
- package/dist/components/callout/callout.class.js.map +1 -1
- package/dist/components/callout/callout.styles.d.ts.map +1 -1
- package/dist/components/callout/callout.styles.js +11 -3
- package/dist/components/callout/callout.styles.js.map +1 -1
- package/dist/components/carousel/carousel.class.d.ts +9 -1
- package/dist/components/carousel/carousel.class.d.ts.map +1 -1
- package/dist/components/carousel/carousel.class.js +22 -4
- package/dist/components/carousel/carousel.class.js.map +1 -1
- package/dist/components/carousel/carousel.styles.d.ts.map +1 -1
- package/dist/components/carousel/carousel.styles.js +27 -5
- package/dist/components/carousel/carousel.styles.js.map +1 -1
- package/dist/components/chart/box-plot.class.d.ts.map +1 -1
- package/dist/components/chart/box-plot.class.js +3 -2
- package/dist/components/chart/box-plot.class.js.map +1 -1
- package/dist/components/chart/chart.class.d.ts +31 -0
- package/dist/components/chart/chart.class.d.ts.map +1 -1
- package/dist/components/chart/chart.class.js +150 -7
- package/dist/components/chart/chart.class.js.map +1 -1
- package/dist/components/chart/chart.styles.d.ts.map +1 -1
- package/dist/components/chart/chart.styles.js +6 -0
- package/dist/components/chart/chart.styles.js.map +1 -1
- package/dist/components/chart/lite-chart.class.d.ts +15 -1
- package/dist/components/chart/lite-chart.class.d.ts.map +1 -1
- package/dist/components/chart/lite-chart.class.js +87 -26
- package/dist/components/chart/lite-chart.class.js.map +1 -1
- package/dist/components/chart/lite-chart.styles.d.ts.map +1 -1
- package/dist/components/chart/lite-chart.styles.js +4 -0
- package/dist/components/chart/lite-chart.styles.js.map +1 -1
- package/dist/components/chat-composer/chat-composer.class.d.ts +6 -0
- package/dist/components/chat-composer/chat-composer.class.d.ts.map +1 -1
- package/dist/components/chat-composer/chat-composer.class.js +17 -3
- package/dist/components/chat-composer/chat-composer.class.js.map +1 -1
- package/dist/components/chat-message/chat-message.class.d.ts +11 -1
- package/dist/components/chat-message/chat-message.class.d.ts.map +1 -1
- package/dist/components/chat-message/chat-message.class.js +28 -7
- package/dist/components/chat-message/chat-message.class.js.map +1 -1
- package/dist/components/chat-message/chat-message.styles.d.ts.map +1 -1
- package/dist/components/chat-message/chat-message.styles.js +16 -5
- package/dist/components/chat-message/chat-message.styles.js.map +1 -1
- package/dist/components/chat-viewport/chat-viewport.class.d.ts +143 -0
- package/dist/components/chat-viewport/chat-viewport.class.d.ts.map +1 -0
- package/dist/components/chat-viewport/chat-viewport.class.js +521 -0
- package/dist/components/chat-viewport/chat-viewport.class.js.map +1 -0
- package/dist/components/chat-viewport/chat-viewport.d.ts +2 -0
- package/dist/components/chat-viewport/chat-viewport.d.ts.map +1 -0
- package/dist/components/chat-viewport/chat-viewport.js +5 -0
- package/dist/components/chat-viewport/chat-viewport.js.map +1 -0
- package/dist/components/chat-viewport/chat-viewport.styles.d.ts +2 -0
- package/dist/components/chat-viewport/chat-viewport.styles.d.ts.map +1 -0
- package/dist/components/chat-viewport/chat-viewport.styles.js +105 -0
- package/dist/components/chat-viewport/chat-viewport.styles.js.map +1 -0
- package/dist/components/checkbox/checkbox.class.d.ts +2 -1
- package/dist/components/checkbox/checkbox.class.d.ts.map +1 -1
- package/dist/components/checkbox/checkbox.class.js +17 -2
- package/dist/components/checkbox/checkbox.class.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.class.d.ts +32 -3
- package/dist/components/checkbox-group/checkbox-group.class.d.ts.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.class.js +70 -18
- package/dist/components/checkbox-group/checkbox-group.class.js.map +1 -1
- package/dist/components/checkpoint/checkpoint.class.d.ts +71 -0
- package/dist/components/checkpoint/checkpoint.class.d.ts.map +1 -0
- package/dist/components/checkpoint/checkpoint.class.js +219 -0
- package/dist/components/checkpoint/checkpoint.class.js.map +1 -0
- package/dist/components/checkpoint/checkpoint.d.ts +2 -0
- package/dist/components/checkpoint/checkpoint.d.ts.map +1 -0
- package/dist/components/checkpoint/checkpoint.js +5 -0
- package/dist/components/checkpoint/checkpoint.js.map +1 -0
- package/dist/components/checkpoint/checkpoint.styles.d.ts +2 -0
- package/dist/components/checkpoint/checkpoint.styles.d.ts.map +1 -0
- package/dist/components/checkpoint/checkpoint.styles.js +123 -0
- package/dist/components/checkpoint/checkpoint.styles.js.map +1 -0
- package/dist/components/chip/chip-group.class.d.ts +7 -2
- package/dist/components/chip/chip-group.class.d.ts.map +1 -1
- package/dist/components/chip/chip-group.class.js +19 -2
- package/dist/components/chip/chip-group.class.js.map +1 -1
- package/dist/components/chip/chip.styles.d.ts.map +1 -1
- package/dist/components/chip/chip.styles.js +12 -3
- package/dist/components/chip/chip.styles.js.map +1 -1
- package/dist/components/chunk-inspector/chunk-inspector.class.d.ts +131 -0
- package/dist/components/chunk-inspector/chunk-inspector.class.d.ts.map +1 -0
- package/dist/components/chunk-inspector/chunk-inspector.class.js +170 -0
- package/dist/components/chunk-inspector/chunk-inspector.class.js.map +1 -0
- package/dist/components/chunk-inspector/chunk-inspector.d.ts +4 -0
- package/dist/components/chunk-inspector/chunk-inspector.d.ts.map +1 -0
- package/dist/components/chunk-inspector/chunk-inspector.js +7 -0
- package/dist/components/chunk-inspector/chunk-inspector.js.map +1 -0
- package/dist/components/chunk-inspector/chunk-inspector.styles.d.ts +2 -0
- package/dist/components/chunk-inspector/chunk-inspector.styles.d.ts.map +1 -0
- package/dist/components/chunk-inspector/chunk-inspector.styles.js +84 -0
- package/dist/components/chunk-inspector/chunk-inspector.styles.js.map +1 -0
- package/dist/components/citation-badge/citation-badge.class.d.ts +7 -2
- package/dist/components/citation-badge/citation-badge.class.d.ts.map +1 -1
- package/dist/components/citation-badge/citation-badge.class.js +15 -3
- package/dist/components/citation-badge/citation-badge.class.js.map +1 -1
- package/dist/components/code-block/code-block-core.class.d.ts +62 -0
- package/dist/components/code-block/code-block-core.class.d.ts.map +1 -1
- package/dist/components/code-block/code-block-core.class.js +229 -42
- package/dist/components/code-block/code-block-core.class.js.map +1 -1
- package/dist/components/code-block/code-block-shared.d.ts +29 -5
- package/dist/components/code-block/code-block-shared.d.ts.map +1 -1
- package/dist/components/code-block/code-block-shared.js +73 -5
- package/dist/components/code-block/code-block-shared.js.map +1 -1
- package/dist/components/code-block/code-block.class.d.ts +62 -0
- package/dist/components/code-block/code-block.class.d.ts.map +1 -1
- package/dist/components/code-block/code-block.class.js +229 -42
- package/dist/components/code-block/code-block.class.js.map +1 -1
- package/dist/components/code-block/code-block.styles.d.ts.map +1 -1
- package/dist/components/code-block/code-block.styles.js +41 -0
- package/dist/components/code-block/code-block.styles.js.map +1 -1
- package/dist/components/code-editor/code-editor.class.d.ts +17 -1
- package/dist/components/code-editor/code-editor.class.d.ts.map +1 -1
- package/dist/components/code-editor/code-editor.class.js +50 -11
- package/dist/components/code-editor/code-editor.class.js.map +1 -1
- package/dist/components/combobox/combobox.class.d.ts +21 -2
- package/dist/components/combobox/combobox.class.d.ts.map +1 -1
- package/dist/components/combobox/combobox.class.js +41 -12
- package/dist/components/combobox/combobox.class.js.map +1 -1
- package/dist/components/combobox/combobox.styles.d.ts.map +1 -1
- package/dist/components/combobox/combobox.styles.js +29 -7
- package/dist/components/combobox/combobox.styles.js.map +1 -1
- package/dist/components/command-palette/command-palette.class.d.ts +14 -0
- package/dist/components/command-palette/command-palette.class.d.ts.map +1 -1
- package/dist/components/command-palette/command-palette.class.js +33 -6
- package/dist/components/command-palette/command-palette.class.js.map +1 -1
- package/dist/components/commit-card/commit-card.class.d.ts +78 -0
- package/dist/components/commit-card/commit-card.class.d.ts.map +1 -0
- package/dist/components/commit-card/commit-card.class.js +209 -0
- package/dist/components/commit-card/commit-card.class.js.map +1 -0
- package/dist/components/commit-card/commit-card.d.ts +2 -0
- package/dist/components/commit-card/commit-card.d.ts.map +1 -0
- package/dist/components/commit-card/commit-card.js +5 -0
- package/dist/components/commit-card/commit-card.js.map +1 -0
- package/dist/components/commit-card/commit-card.styles.d.ts +2 -0
- package/dist/components/commit-card/commit-card.styles.d.ts.map +1 -0
- package/dist/components/commit-card/commit-card.styles.js +69 -0
- package/dist/components/commit-card/commit-card.styles.js.map +1 -0
- package/dist/components/community-card/community-card.class.d.ts +68 -0
- package/dist/components/community-card/community-card.class.d.ts.map +1 -0
- package/dist/components/community-card/community-card.class.js +109 -0
- package/dist/components/community-card/community-card.class.js.map +1 -0
- package/dist/components/community-card/community-card.d.ts +5 -0
- package/dist/components/community-card/community-card.d.ts.map +1 -0
- package/dist/components/community-card/community-card.js +8 -0
- package/dist/components/community-card/community-card.js.map +1 -0
- package/dist/components/community-card/community-card.styles.d.ts +2 -0
- package/dist/components/community-card/community-card.styles.d.ts.map +1 -0
- package/dist/components/community-card/community-card.styles.js +74 -0
- package/dist/components/community-card/community-card.styles.js.map +1 -0
- package/dist/components/compare-panel/compare-panel.class.d.ts +112 -0
- package/dist/components/compare-panel/compare-panel.class.d.ts.map +1 -0
- package/dist/components/compare-panel/compare-panel.class.js +260 -0
- package/dist/components/compare-panel/compare-panel.class.js.map +1 -0
- package/dist/components/compare-panel/compare-panel.d.ts +3 -0
- package/dist/components/compare-panel/compare-panel.d.ts.map +1 -0
- package/dist/components/compare-panel/compare-panel.js +6 -0
- package/dist/components/compare-panel/compare-panel.js.map +1 -0
- package/dist/components/compare-panel/compare-panel.styles.d.ts +2 -0
- package/dist/components/compare-panel/compare-panel.styles.d.ts.map +1 -0
- package/dist/components/compare-panel/compare-panel.styles.js +97 -0
- package/dist/components/compare-panel/compare-panel.styles.js.map +1 -0
- package/dist/components/confirm-bar/confirm-bar.class.d.ts +81 -0
- package/dist/components/confirm-bar/confirm-bar.class.d.ts.map +1 -0
- package/dist/components/confirm-bar/confirm-bar.class.js +193 -0
- package/dist/components/confirm-bar/confirm-bar.class.js.map +1 -0
- package/dist/components/confirm-bar/confirm-bar.d.ts +5 -0
- package/dist/components/confirm-bar/confirm-bar.d.ts.map +1 -0
- package/dist/components/confirm-bar/confirm-bar.js +8 -0
- package/dist/components/confirm-bar/confirm-bar.js.map +1 -0
- package/dist/components/confirm-bar/confirm-bar.styles.d.ts +2 -0
- package/dist/components/confirm-bar/confirm-bar.styles.d.ts.map +1 -0
- package/dist/components/confirm-bar/confirm-bar.styles.js +96 -0
- package/dist/components/confirm-bar/confirm-bar.styles.js.map +1 -0
- package/dist/components/context-meter/context-meter.class.d.ts +8 -1
- package/dist/components/context-meter/context-meter.class.d.ts.map +1 -1
- package/dist/components/context-meter/context-meter.class.js +25 -4
- package/dist/components/context-meter/context-meter.class.js.map +1 -1
- package/dist/components/context-meter/context-meter.styles.d.ts.map +1 -1
- package/dist/components/context-meter/context-meter.styles.js +6 -0
- package/dist/components/context-meter/context-meter.styles.js.map +1 -1
- package/dist/components/conversation-item/conversation-item.class.d.ts +17 -1
- package/dist/components/conversation-item/conversation-item.class.d.ts.map +1 -1
- package/dist/components/conversation-item/conversation-item.class.js +43 -4
- package/dist/components/conversation-item/conversation-item.class.js.map +1 -1
- package/dist/components/conversation-item/conversation-item.styles.d.ts.map +1 -1
- package/dist/components/conversation-item/conversation-item.styles.js +15 -2
- package/dist/components/conversation-item/conversation-item.styles.js.map +1 -1
- package/dist/components/copy-button/copy-button.class.d.ts.map +1 -1
- package/dist/components/copy-button/copy-button.class.js +4 -3
- package/dist/components/copy-button/copy-button.class.js.map +1 -1
- package/dist/components/csv-viewer/csv-viewer.class.d.ts +83 -3
- package/dist/components/csv-viewer/csv-viewer.class.d.ts.map +1 -1
- package/dist/components/csv-viewer/csv-viewer.class.js +204 -6
- package/dist/components/csv-viewer/csv-viewer.class.js.map +1 -1
- package/dist/components/csv-viewer/csv-viewer.js +10 -1
- package/dist/components/csv-viewer/csv-viewer.js.map +1 -1
- package/dist/components/data-grid/data-grid.class.d.ts +2 -1
- package/dist/components/data-grid/data-grid.class.d.ts.map +1 -1
- package/dist/components/data-grid/data-grid.class.js +10 -1
- package/dist/components/data-grid/data-grid.class.js.map +1 -1
- package/dist/components/dataset-viewer/dataset-viewer.class.d.ts +93 -4
- package/dist/components/dataset-viewer/dataset-viewer.class.d.ts.map +1 -1
- package/dist/components/dataset-viewer/dataset-viewer.class.js +212 -14
- package/dist/components/dataset-viewer/dataset-viewer.class.js.map +1 -1
- package/dist/components/dataset-viewer/dataset-viewer.js +11 -6
- package/dist/components/dataset-viewer/dataset-viewer.js.map +1 -1
- package/dist/components/dataset-viewer/dataset-viewer.styles.d.ts.map +1 -1
- package/dist/components/dataset-viewer/dataset-viewer.styles.js +52 -5
- package/dist/components/dataset-viewer/dataset-viewer.styles.js.map +1 -1
- package/dist/components/date-picker/calendar-core.d.ts.map +1 -1
- package/dist/components/date-picker/calendar-core.js +3 -2
- package/dist/components/date-picker/calendar-core.js.map +1 -1
- package/dist/components/date-picker/date-input.class.d.ts +6 -0
- package/dist/components/date-picker/date-input.class.d.ts.map +1 -1
- package/dist/components/date-picker/date-input.class.js +13 -3
- package/dist/components/date-picker/date-input.class.js.map +1 -1
- package/dist/components/date-picker/date-picker.class.d.ts.map +1 -1
- package/dist/components/date-picker/date-picker.class.js +31 -7
- package/dist/components/date-picker/date-picker.class.js.map +1 -1
- package/dist/components/date-picker/date-picker.styles.d.ts.map +1 -1
- package/dist/components/date-picker/date-picker.styles.js +5 -0
- package/dist/components/date-picker/date-picker.styles.js.map +1 -1
- package/dist/components/details/accordion-item.class.d.ts +4 -1
- package/dist/components/details/accordion-item.class.d.ts.map +1 -1
- package/dist/components/details/accordion-item.class.js +4 -1
- package/dist/components/details/accordion-item.class.js.map +1 -1
- package/dist/components/diff-view/diff-line-diff.d.ts +13 -0
- package/dist/components/diff-view/diff-line-diff.d.ts.map +1 -1
- package/dist/components/diff-view/diff-line-diff.js +33 -0
- package/dist/components/diff-view/diff-line-diff.js.map +1 -1
- package/dist/components/diff-view/diff-view.class.d.ts +27 -1
- package/dist/components/diff-view/diff-view.class.d.ts.map +1 -1
- package/dist/components/diff-view/diff-view.class.js +130 -4
- package/dist/components/diff-view/diff-view.class.js.map +1 -1
- package/dist/components/diff-view/diff-view.styles.d.ts.map +1 -1
- package/dist/components/diff-view/diff-view.styles.js +18 -2
- package/dist/components/diff-view/diff-view.styles.js.map +1 -1
- package/dist/components/dock-panel/dock-panel.class.d.ts.map +1 -1
- package/dist/components/dock-panel/dock-panel.class.js +5 -0
- package/dist/components/dock-panel/dock-panel.class.js.map +1 -1
- package/dist/components/dock-panel/dock-panel.styles.d.ts.map +1 -1
- package/dist/components/dock-panel/dock-panel.styles.js +8 -0
- package/dist/components/dock-panel/dock-panel.styles.js.map +1 -1
- package/dist/components/document-preview/document-preview.class.d.ts +32 -0
- package/dist/components/document-preview/document-preview.class.d.ts.map +1 -1
- package/dist/components/document-preview/document-preview.class.js +93 -5
- package/dist/components/document-preview/document-preview.class.js.map +1 -1
- package/dist/components/document-preview/document-preview.styles.d.ts.map +1 -1
- package/dist/components/document-preview/document-preview.styles.js +18 -0
- package/dist/components/document-preview/document-preview.styles.js.map +1 -1
- package/dist/components/document-viewer/anchors.d.ts +89 -0
- package/dist/components/document-viewer/anchors.d.ts.map +1 -0
- package/dist/components/document-viewer/anchors.js +4 -0
- package/dist/components/document-viewer/anchors.js.map +1 -0
- package/dist/components/document-viewer/document-viewer.class.d.ts +23 -0
- package/dist/components/document-viewer/document-viewer.class.d.ts.map +1 -1
- package/dist/components/document-viewer/document-viewer.class.js +72 -3
- package/dist/components/document-viewer/document-viewer.class.js.map +1 -1
- package/dist/components/document-viewer/registry.d.ts +8 -0
- package/dist/components/document-viewer/registry.d.ts.map +1 -1
- package/dist/components/document-viewer/registry.js.map +1 -1
- package/dist/components/docx-viewer/docx-viewer.class.d.ts +128 -2
- package/dist/components/docx-viewer/docx-viewer.class.d.ts.map +1 -1
- package/dist/components/docx-viewer/docx-viewer.class.js +433 -3
- package/dist/components/docx-viewer/docx-viewer.class.js.map +1 -1
- package/dist/components/docx-viewer/docx-viewer.js +1 -0
- package/dist/components/docx-viewer/docx-viewer.js.map +1 -1
- package/dist/components/docx-viewer/docx-viewer.styles.d.ts.map +1 -1
- package/dist/components/docx-viewer/docx-viewer.styles.js +56 -0
- package/dist/components/docx-viewer/docx-viewer.styles.js.map +1 -1
- package/dist/components/ebook-viewer/ebook-viewer-register.js +1 -0
- package/dist/components/ebook-viewer/ebook-viewer-register.js.map +1 -1
- package/dist/components/ebook-viewer/ebook-viewer.class.d.ts +111 -2
- package/dist/components/ebook-viewer/ebook-viewer.class.d.ts.map +1 -1
- package/dist/components/ebook-viewer/ebook-viewer.class.js +289 -4
- package/dist/components/ebook-viewer/ebook-viewer.class.js.map +1 -1
- package/dist/components/ebook-viewer/ebook-viewer.styles.d.ts.map +1 -1
- package/dist/components/ebook-viewer/ebook-viewer.styles.js +6 -2
- package/dist/components/ebook-viewer/ebook-viewer.styles.js.map +1 -1
- package/dist/components/email-viewer/email-viewer.class.d.ts +26 -1
- package/dist/components/email-viewer/email-viewer.class.d.ts.map +1 -1
- package/dist/components/email-viewer/email-viewer.class.js +110 -3
- package/dist/components/email-viewer/email-viewer.class.js.map +1 -1
- package/dist/components/email-viewer/email-viewer.js +1 -0
- package/dist/components/email-viewer/email-viewer.js.map +1 -1
- package/dist/components/email-viewer/email-viewer.styles.d.ts.map +1 -1
- package/dist/components/email-viewer/email-viewer.styles.js +31 -1
- package/dist/components/email-viewer/email-viewer.styles.js.map +1 -1
- package/dist/components/emoji-picker/emoji-data-loader.d.ts +14 -0
- package/dist/components/emoji-picker/emoji-data-loader.d.ts.map +1 -0
- package/dist/components/emoji-picker/emoji-data-loader.js +78 -0
- package/dist/components/emoji-picker/emoji-data-loader.js.map +1 -0
- package/dist/components/emoji-picker/emoji-picker.class.d.ts +98 -0
- package/dist/components/emoji-picker/emoji-picker.class.d.ts.map +1 -0
- package/dist/components/emoji-picker/emoji-picker.class.js +285 -0
- package/dist/components/emoji-picker/emoji-picker.class.js.map +1 -0
- package/dist/components/emoji-picker/emoji-picker.d.ts +2 -0
- package/dist/components/emoji-picker/emoji-picker.d.ts.map +1 -0
- package/dist/components/emoji-picker/emoji-picker.js +5 -0
- package/dist/components/emoji-picker/emoji-picker.js.map +1 -0
- package/dist/components/emoji-picker/emoji-picker.styles.d.ts +2 -0
- package/dist/components/emoji-picker/emoji-picker.styles.d.ts.map +1 -0
- package/dist/components/emoji-picker/emoji-picker.styles.js +70 -0
- package/dist/components/emoji-picker/emoji-picker.styles.js.map +1 -0
- package/dist/components/entity-card/entity-card.class.d.ts +81 -0
- package/dist/components/entity-card/entity-card.class.d.ts.map +1 -0
- package/dist/components/entity-card/entity-card.class.js +148 -0
- package/dist/components/entity-card/entity-card.class.js.map +1 -0
- package/dist/components/entity-card/entity-card.d.ts +7 -0
- package/dist/components/entity-card/entity-card.d.ts.map +1 -0
- package/dist/components/entity-card/entity-card.js +10 -0
- package/dist/components/entity-card/entity-card.js.map +1 -0
- package/dist/components/entity-card/entity-card.styles.d.ts +2 -0
- package/dist/components/entity-card/entity-card.styles.d.ts.map +1 -0
- package/dist/components/entity-card/entity-card.styles.js +48 -0
- package/dist/components/entity-card/entity-card.styles.js.map +1 -0
- package/dist/components/entity-chip/entity-chip.class.d.ts +72 -0
- package/dist/components/entity-chip/entity-chip.class.d.ts.map +1 -0
- package/dist/components/entity-chip/entity-chip.class.js +200 -0
- package/dist/components/entity-chip/entity-chip.class.js.map +1 -0
- package/dist/components/entity-chip/entity-chip.d.ts +2 -0
- package/dist/components/entity-chip/entity-chip.d.ts.map +1 -0
- package/dist/components/entity-chip/entity-chip.js +5 -0
- package/dist/components/entity-chip/entity-chip.js.map +1 -0
- package/dist/components/entity-chip/entity-chip.styles.d.ts +2 -0
- package/dist/components/entity-chip/entity-chip.styles.d.ts.map +1 -0
- package/dist/components/entity-chip/entity-chip.styles.js +46 -0
- package/dist/components/entity-chip/entity-chip.styles.js.map +1 -0
- package/dist/components/env-list/env-list.class.d.ts +55 -0
- package/dist/components/env-list/env-list.class.d.ts.map +1 -0
- package/dist/components/env-list/env-list.class.js +143 -0
- package/dist/components/env-list/env-list.class.js.map +1 -0
- package/dist/components/env-list/env-list.d.ts +2 -0
- package/dist/components/env-list/env-list.d.ts.map +1 -0
- package/dist/components/env-list/env-list.js +5 -0
- package/dist/components/env-list/env-list.js.map +1 -0
- package/dist/components/env-list/env-list.styles.d.ts +2 -0
- package/dist/components/env-list/env-list.styles.d.ts.map +1 -0
- package/dist/components/env-list/env-list.styles.js +44 -0
- package/dist/components/env-list/env-list.styles.js.map +1 -0
- package/dist/components/file-icon/file-icon.class.d.ts +5 -1
- package/dist/components/file-icon/file-icon.class.d.ts.map +1 -1
- package/dist/components/file-icon/file-icon.class.js +25 -2
- package/dist/components/file-icon/file-icon.class.js.map +1 -1
- package/dist/components/file-icon/file-icon.styles.d.ts.map +1 -1
- package/dist/components/file-icon/file-icon.styles.js +4 -0
- package/dist/components/file-icon/file-icon.styles.js.map +1 -1
- package/dist/components/file-input/file-input.class.d.ts +19 -0
- package/dist/components/file-input/file-input.class.d.ts.map +1 -1
- package/dist/components/file-input/file-input.class.js +27 -1
- package/dist/components/file-input/file-input.class.js.map +1 -1
- package/dist/components/file-tree/file-tree.class.d.ts +68 -0
- package/dist/components/file-tree/file-tree.class.d.ts.map +1 -0
- package/dist/components/file-tree/file-tree.class.js +235 -0
- package/dist/components/file-tree/file-tree.class.js.map +1 -0
- package/dist/components/file-tree/file-tree.d.ts +2 -0
- package/dist/components/file-tree/file-tree.d.ts.map +1 -0
- package/dist/components/file-tree/file-tree.js +5 -0
- package/dist/components/file-tree/file-tree.js.map +1 -0
- package/dist/components/file-tree/file-tree.styles.d.ts +2 -0
- package/dist/components/file-tree/file-tree.styles.d.ts.map +1 -0
- package/dist/components/file-tree/file-tree.styles.js +10 -0
- package/dist/components/file-tree/file-tree.styles.js.map +1 -0
- package/dist/components/flag/flag.class.d.ts.map +1 -1
- package/dist/components/flag/flag.class.js +7 -15
- package/dist/components/flag/flag.class.js.map +1 -1
- package/dist/components/flow-canvas/flow-canvas.class.d.ts +411 -0
- package/dist/components/flow-canvas/flow-canvas.class.d.ts.map +1 -0
- package/dist/components/flow-canvas/flow-canvas.class.js +1570 -0
- package/dist/components/flow-canvas/flow-canvas.class.js.map +1 -0
- package/dist/components/flow-canvas/flow-canvas.d.ts +4 -0
- package/dist/components/flow-canvas/flow-canvas.d.ts.map +1 -0
- package/dist/components/flow-canvas/flow-canvas.js +7 -0
- package/dist/components/flow-canvas/flow-canvas.js.map +1 -0
- package/dist/components/flow-canvas/flow-canvas.styles.d.ts +2 -0
- package/dist/components/flow-canvas/flow-canvas.styles.d.ts.map +1 -0
- package/dist/components/flow-canvas/flow-canvas.styles.js +186 -0
- package/dist/components/flow-canvas/flow-canvas.styles.js.map +1 -0
- package/dist/components/flow-controls/flow-controls.class.d.ts +44 -0
- package/dist/components/flow-controls/flow-controls.class.d.ts.map +1 -0
- package/dist/components/flow-controls/flow-controls.class.js +203 -0
- package/dist/components/flow-controls/flow-controls.class.js.map +1 -0
- package/dist/components/flow-controls/flow-controls.d.ts +2 -0
- package/dist/components/flow-controls/flow-controls.d.ts.map +1 -0
- package/dist/components/flow-controls/flow-controls.js +5 -0
- package/dist/components/flow-controls/flow-controls.js.map +1 -0
- package/dist/components/flow-controls/flow-controls.styles.d.ts +2 -0
- package/dist/components/flow-controls/flow-controls.styles.d.ts.map +1 -0
- package/dist/components/flow-controls/flow-controls.styles.js +55 -0
- package/dist/components/flow-controls/flow-controls.styles.js.map +1 -0
- package/dist/components/flow-minimap/flow-minimap.class.d.ts +62 -0
- package/dist/components/flow-minimap/flow-minimap.class.d.ts.map +1 -0
- package/dist/components/flow-minimap/flow-minimap.class.js +291 -0
- package/dist/components/flow-minimap/flow-minimap.class.js.map +1 -0
- package/dist/components/flow-minimap/flow-minimap.d.ts +2 -0
- package/dist/components/flow-minimap/flow-minimap.d.ts.map +1 -0
- package/dist/components/flow-minimap/flow-minimap.js +5 -0
- package/dist/components/flow-minimap/flow-minimap.js.map +1 -0
- package/dist/components/flow-minimap/flow-minimap.styles.d.ts +2 -0
- package/dist/components/flow-minimap/flow-minimap.styles.d.ts.map +1 -0
- package/dist/components/flow-minimap/flow-minimap.styles.js +48 -0
- package/dist/components/flow-minimap/flow-minimap.styles.js.map +1 -0
- package/dist/components/flow-node/flow-node.class.d.ts +70 -0
- package/dist/components/flow-node/flow-node.class.d.ts.map +1 -0
- package/dist/components/flow-node/flow-node.class.js +187 -0
- package/dist/components/flow-node/flow-node.class.js.map +1 -0
- package/dist/components/flow-node/flow-node.d.ts +2 -0
- package/dist/components/flow-node/flow-node.d.ts.map +1 -0
- package/dist/components/flow-node/flow-node.js +5 -0
- package/dist/components/flow-node/flow-node.js.map +1 -0
- package/dist/components/flow-node/flow-node.styles.d.ts +2 -0
- package/dist/components/flow-node/flow-node.styles.d.ts.map +1 -0
- package/dist/components/flow-node/flow-node.styles.js +127 -0
- package/dist/components/flow-node/flow-node.styles.js.map +1 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.class.d.ts +46 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.class.d.ts.map +1 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.class.js +182 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.class.js.map +1 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.d.ts +2 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.d.ts.map +1 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.js +5 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.js.map +1 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.styles.d.ts +2 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.styles.d.ts.map +1 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.styles.js +38 -0
- package/dist/components/flow-run-overlay/flow-run-overlay.styles.js.map +1 -0
- package/dist/components/format/format-bytes.class.d.ts +8 -0
- package/dist/components/format/format-bytes.class.d.ts.map +1 -1
- package/dist/components/format/format-bytes.class.js +36 -7
- package/dist/components/format/format-bytes.class.js.map +1 -1
- package/dist/components/format/format-date.class.d.ts.map +1 -1
- package/dist/components/format/format-date.class.js +2 -1
- package/dist/components/format/format-date.class.js.map +1 -1
- package/dist/components/format/format-number.class.d.ts +6 -0
- package/dist/components/format/format-number.class.d.ts.map +1 -1
- package/dist/components/format/format-number.class.js +34 -5
- package/dist/components/format/format-number.class.js.map +1 -1
- package/dist/components/format/relative-time.class.d.ts.map +1 -1
- package/dist/components/format/relative-time.class.js +2 -1
- package/dist/components/format/relative-time.class.js.map +1 -1
- package/dist/components/generation-status/generation-status.class.d.ts +3 -0
- package/dist/components/generation-status/generation-status.class.d.ts.map +1 -1
- package/dist/components/generation-status/generation-status.class.js +28 -11
- package/dist/components/generation-status/generation-status.class.js.map +1 -1
- package/dist/components/generation-status/generation-status.styles.d.ts.map +1 -1
- package/dist/components/generation-status/generation-status.styles.js +7 -4
- package/dist/components/generation-status/generation-status.styles.js.map +1 -1
- package/dist/components/geojson-view/geojson-view.class.d.ts +40 -0
- package/dist/components/geojson-view/geojson-view.class.d.ts.map +1 -0
- package/dist/components/geojson-view/geojson-view.class.js +185 -0
- package/dist/components/geojson-view/geojson-view.class.js.map +1 -0
- package/dist/components/geojson-view/geojson-view.d.ts +5 -0
- package/dist/components/geojson-view/geojson-view.d.ts.map +1 -0
- package/dist/components/geojson-view/geojson-view.js +18 -0
- package/dist/components/geojson-view/geojson-view.js.map +1 -0
- package/dist/components/graph/graph-canvas.d.ts +110 -0
- package/dist/components/graph/graph-canvas.d.ts.map +1 -0
- package/dist/components/graph/graph-canvas.js +175 -0
- package/dist/components/graph/graph-canvas.js.map +1 -0
- package/dist/components/graph/graph-hull.d.ts +28 -0
- package/dist/components/graph/graph-hull.d.ts.map +1 -0
- package/dist/components/graph/graph-hull.js +70 -0
- package/dist/components/graph/graph-hull.js.map +1 -0
- package/dist/components/graph/graph-loader.d.ts +6 -0
- package/dist/components/graph/graph-loader.d.ts.map +1 -1
- package/dist/components/graph/graph-loader.js +2 -0
- package/dist/components/graph/graph-loader.js.map +1 -1
- package/dist/components/graph/graph.class.d.ts +447 -2
- package/dist/components/graph/graph.class.d.ts.map +1 -1
- package/dist/components/graph/graph.class.js +1700 -121
- package/dist/components/graph/graph.class.js.map +1 -1
- package/dist/components/graph/graph.styles.d.ts.map +1 -1
- package/dist/components/graph/graph.styles.js +100 -0
- package/dist/components/graph/graph.styles.js.map +1 -1
- package/dist/components/graph-legend/graph-legend.class.d.ts +62 -0
- package/dist/components/graph-legend/graph-legend.class.d.ts.map +1 -0
- package/dist/components/graph-legend/graph-legend.class.js +132 -0
- package/dist/components/graph-legend/graph-legend.class.js.map +1 -0
- package/dist/components/graph-legend/graph-legend.d.ts +2 -0
- package/dist/components/graph-legend/graph-legend.d.ts.map +1 -0
- package/dist/components/graph-legend/graph-legend.js +5 -0
- package/dist/components/graph-legend/graph-legend.js.map +1 -0
- package/dist/components/graph-legend/graph-legend.styles.d.ts +2 -0
- package/dist/components/graph-legend/graph-legend.styles.d.ts.map +1 -0
- package/dist/components/graph-legend/graph-legend.styles.js +59 -0
- package/dist/components/graph-legend/graph-legend.styles.js.map +1 -0
- package/dist/components/handoff-divider/handoff-divider.class.d.ts +46 -0
- package/dist/components/handoff-divider/handoff-divider.class.d.ts.map +1 -0
- package/dist/components/handoff-divider/handoff-divider.class.js +99 -0
- package/dist/components/handoff-divider/handoff-divider.class.js.map +1 -0
- package/dist/components/handoff-divider/handoff-divider.d.ts +2 -0
- package/dist/components/handoff-divider/handoff-divider.d.ts.map +1 -0
- package/dist/components/handoff-divider/handoff-divider.js +5 -0
- package/dist/components/handoff-divider/handoff-divider.js.map +1 -0
- package/dist/components/handoff-divider/handoff-divider.styles.d.ts +2 -0
- package/dist/components/handoff-divider/handoff-divider.styles.d.ts.map +1 -0
- package/dist/components/handoff-divider/handoff-divider.styles.js +48 -0
- package/dist/components/handoff-divider/handoff-divider.styles.js.map +1 -0
- package/dist/components/heatmap/heatmap.class.d.ts +12 -3
- package/dist/components/heatmap/heatmap.class.d.ts.map +1 -1
- package/dist/components/heatmap/heatmap.class.js +88 -50
- package/dist/components/heatmap/heatmap.class.js.map +1 -1
- package/dist/components/highlight-layer/highlight-layer.class.d.ts +60 -0
- package/dist/components/highlight-layer/highlight-layer.class.d.ts.map +1 -0
- package/dist/components/highlight-layer/highlight-layer.class.js +151 -0
- package/dist/components/highlight-layer/highlight-layer.class.js.map +1 -0
- package/dist/components/highlight-layer/highlight-layer.d.ts +2 -0
- package/dist/components/highlight-layer/highlight-layer.d.ts.map +1 -0
- package/dist/components/highlight-layer/highlight-layer.js +5 -0
- package/dist/components/highlight-layer/highlight-layer.js.map +1 -0
- package/dist/components/highlight-layer/highlight-layer.styles.d.ts +2 -0
- package/dist/components/highlight-layer/highlight-layer.styles.d.ts.map +1 -0
- package/dist/components/highlight-layer/highlight-layer.styles.js +68 -0
- package/dist/components/highlight-layer/highlight-layer.styles.js.map +1 -0
- package/dist/components/image-comparer/image-comparer.class.d.ts.map +1 -1
- package/dist/components/image-comparer/image-comparer.class.js +2 -1
- package/dist/components/image-comparer/image-comparer.class.js.map +1 -1
- package/dist/components/image-viewer/image-viewer.class.d.ts +143 -0
- package/dist/components/image-viewer/image-viewer.class.d.ts.map +1 -0
- package/dist/components/image-viewer/image-viewer.class.js +389 -0
- package/dist/components/image-viewer/image-viewer.class.js.map +1 -0
- package/dist/components/image-viewer/image-viewer.d.ts +4 -0
- package/dist/components/image-viewer/image-viewer.d.ts.map +1 -0
- package/dist/components/image-viewer/image-viewer.js +25 -0
- package/dist/components/image-viewer/image-viewer.js.map +1 -0
- package/dist/components/image-viewer/image-viewer.styles.d.ts +2 -0
- package/dist/components/image-viewer/image-viewer.styles.d.ts.map +1 -0
- package/dist/components/image-viewer/image-viewer.styles.js +126 -0
- package/dist/components/image-viewer/image-viewer.styles.js.map +1 -0
- package/dist/components/input/input.class.d.ts +3 -2
- package/dist/components/input/input.class.d.ts.map +1 -1
- package/dist/components/input/input.class.js +2 -1
- package/dist/components/input/input.class.js.map +1 -1
- package/dist/components/input/input.styles.d.ts.map +1 -1
- package/dist/components/input/input.styles.js +5 -0
- package/dist/components/input/input.styles.js.map +1 -1
- package/dist/components/intersection-observer/intersection-observer.class.d.ts +1 -0
- package/dist/components/intersection-observer/intersection-observer.class.d.ts.map +1 -1
- package/dist/components/intersection-observer/intersection-observer.class.js +15 -0
- package/dist/components/intersection-observer/intersection-observer.class.js.map +1 -1
- package/dist/components/json-viewer/json-viewer.class.d.ts +39 -2
- package/dist/components/json-viewer/json-viewer.class.d.ts.map +1 -1
- package/dist/components/json-viewer/json-viewer.class.js +95 -6
- package/dist/components/json-viewer/json-viewer.class.js.map +1 -1
- package/dist/components/known-date/known-date.class.d.ts.map +1 -1
- package/dist/components/known-date/known-date.class.js +2 -1
- package/dist/components/known-date/known-date.class.js.map +1 -1
- package/dist/components/lightbox/lightbox.class.d.ts +2 -2
- package/dist/components/lightbox/lightbox.class.d.ts.map +1 -1
- package/dist/components/lightbox/lightbox.class.js +16 -7
- package/dist/components/lightbox/lightbox.class.js.map +1 -1
- package/dist/components/live-region/live-region.class.d.ts +5 -0
- package/dist/components/live-region/live-region.class.d.ts.map +1 -1
- package/dist/components/live-region/live-region.class.js +10 -2
- package/dist/components/live-region/live-region.class.js.map +1 -1
- package/dist/components/map/map.class.d.ts +33 -3
- package/dist/components/map/map.class.d.ts.map +1 -1
- package/dist/components/map/map.class.js +140 -5
- package/dist/components/map/map.class.js.map +1 -1
- package/dist/components/markdown/katex-loader.d.ts +23 -0
- package/dist/components/markdown/katex-loader.d.ts.map +1 -0
- package/dist/components/markdown/katex-loader.js +33 -0
- package/dist/components/markdown/katex-loader.js.map +1 -0
- package/dist/components/markdown/markdown.class.d.ts +191 -4
- package/dist/components/markdown/markdown.class.d.ts.map +1 -1
- package/dist/components/markdown/markdown.class.js +584 -11
- package/dist/components/markdown/markdown.class.js.map +1 -1
- package/dist/components/markdown/markdown.styles.d.ts.map +1 -1
- package/dist/components/markdown/markdown.styles.js +53 -0
- package/dist/components/markdown/markdown.styles.js.map +1 -1
- package/dist/components/media-card/media-card.styles.d.ts.map +1 -1
- package/dist/components/media-card/media-card.styles.js +6 -2
- package/dist/components/media-card/media-card.styles.js.map +1 -1
- package/dist/components/mention-popover/mention-popover.styles.d.ts.map +1 -1
- package/dist/components/mention-popover/mention-popover.styles.js +6 -3
- package/dist/components/mention-popover/mention-popover.styles.js.map +1 -1
- package/dist/components/message-actions/message-actions.class.d.ts +112 -0
- package/dist/components/message-actions/message-actions.class.d.ts.map +1 -0
- package/dist/components/message-actions/message-actions.class.js +277 -0
- package/dist/components/message-actions/message-actions.class.js.map +1 -0
- package/dist/components/message-actions/message-actions.d.ts +4 -0
- package/dist/components/message-actions/message-actions.d.ts.map +1 -0
- package/dist/components/message-actions/message-actions.js +7 -0
- package/dist/components/message-actions/message-actions.js.map +1 -0
- package/dist/components/message-actions/message-actions.styles.d.ts +2 -0
- package/dist/components/message-actions/message-actions.styles.d.ts.map +1 -0
- package/dist/components/message-actions/message-actions.styles.js +66 -0
- package/dist/components/message-actions/message-actions.styles.js.map +1 -0
- package/dist/components/message-feedback/message-feedback.class.d.ts +91 -0
- package/dist/components/message-feedback/message-feedback.class.d.ts.map +1 -0
- package/dist/components/message-feedback/message-feedback.class.js +266 -0
- package/dist/components/message-feedback/message-feedback.class.js.map +1 -0
- package/dist/components/message-feedback/message-feedback.d.ts +2 -0
- package/dist/components/message-feedback/message-feedback.d.ts.map +1 -0
- package/dist/components/message-feedback/message-feedback.js +5 -0
- package/dist/components/message-feedback/message-feedback.js.map +1 -0
- package/dist/components/message-feedback/message-feedback.styles.d.ts +2 -0
- package/dist/components/message-feedback/message-feedback.styles.d.ts.map +1 -0
- package/dist/components/message-feedback/message-feedback.styles.js +133 -0
- package/dist/components/message-feedback/message-feedback.styles.js.map +1 -0
- package/dist/components/mind-map/mind-map-layout.d.ts +52 -0
- package/dist/components/mind-map/mind-map-layout.d.ts.map +1 -0
- package/dist/components/mind-map/mind-map-layout.js +69 -0
- package/dist/components/mind-map/mind-map-layout.js.map +1 -0
- package/dist/components/mind-map/mind-map.class.d.ts +83 -0
- package/dist/components/mind-map/mind-map.class.d.ts.map +1 -0
- package/dist/components/mind-map/mind-map.class.js +252 -0
- package/dist/components/mind-map/mind-map.class.js.map +1 -0
- package/dist/components/mind-map/mind-map.d.ts +2 -0
- package/dist/components/mind-map/mind-map.d.ts.map +1 -0
- package/dist/components/mind-map/mind-map.js +5 -0
- package/dist/components/mind-map/mind-map.js.map +1 -0
- package/dist/components/mind-map/mind-map.styles.d.ts +2 -0
- package/dist/components/mind-map/mind-map.styles.d.ts.map +1 -0
- package/dist/components/mind-map/mind-map.styles.js +43 -0
- package/dist/components/mind-map/mind-map.styles.js.map +1 -0
- package/dist/components/model-select/model-select.class.d.ts +1 -0
- package/dist/components/model-select/model-select.class.d.ts.map +1 -1
- package/dist/components/model-select/model-select.class.js +13 -0
- package/dist/components/model-select/model-select.class.js.map +1 -1
- package/dist/components/mutation-observer/mutation-observer.class.d.ts +1 -0
- package/dist/components/mutation-observer/mutation-observer.class.d.ts.map +1 -1
- package/dist/components/mutation-observer/mutation-observer.class.js +15 -0
- package/dist/components/mutation-observer/mutation-observer.class.js.map +1 -1
- package/dist/components/neighbor-list/neighbor-list.class.d.ts +70 -0
- package/dist/components/neighbor-list/neighbor-list.class.d.ts.map +1 -0
- package/dist/components/neighbor-list/neighbor-list.class.js +177 -0
- package/dist/components/neighbor-list/neighbor-list.class.js.map +1 -0
- package/dist/components/neighbor-list/neighbor-list.d.ts +4 -0
- package/dist/components/neighbor-list/neighbor-list.d.ts.map +1 -0
- package/dist/components/neighbor-list/neighbor-list.js +7 -0
- package/dist/components/neighbor-list/neighbor-list.js.map +1 -0
- package/dist/components/neighbor-list/neighbor-list.styles.d.ts +2 -0
- package/dist/components/neighbor-list/neighbor-list.styles.d.ts.map +1 -0
- package/dist/components/neighbor-list/neighbor-list.styles.js +79 -0
- package/dist/components/neighbor-list/neighbor-list.styles.js.map +1 -0
- package/dist/components/node-palette/node-palette.class.d.ts +82 -0
- package/dist/components/node-palette/node-palette.class.d.ts.map +1 -0
- package/dist/components/node-palette/node-palette.class.js +213 -0
- package/dist/components/node-palette/node-palette.class.js.map +1 -0
- package/dist/components/node-palette/node-palette.d.ts +2 -0
- package/dist/components/node-palette/node-palette.d.ts.map +1 -0
- package/dist/components/node-palette/node-palette.js +5 -0
- package/dist/components/node-palette/node-palette.js.map +1 -0
- package/dist/components/node-palette/node-palette.styles.d.ts +2 -0
- package/dist/components/node-palette/node-palette.styles.d.ts.map +1 -0
- package/dist/components/node-palette/node-palette.styles.js +74 -0
- package/dist/components/node-palette/node-palette.styles.js.map +1 -0
- package/dist/components/notebook-viewer/dompurify-loader.d.ts +7 -0
- package/dist/components/notebook-viewer/dompurify-loader.d.ts.map +1 -0
- package/dist/components/notebook-viewer/dompurify-loader.js +23 -0
- package/dist/components/notebook-viewer/dompurify-loader.js.map +1 -0
- package/dist/components/notebook-viewer/notebook-viewer.class.d.ts +164 -0
- package/dist/components/notebook-viewer/notebook-viewer.class.d.ts.map +1 -0
- package/dist/components/notebook-viewer/notebook-viewer.class.js +442 -0
- package/dist/components/notebook-viewer/notebook-viewer.class.js.map +1 -0
- package/dist/components/notebook-viewer/notebook-viewer.d.ts +6 -0
- package/dist/components/notebook-viewer/notebook-viewer.d.ts.map +1 -0
- package/dist/components/notebook-viewer/notebook-viewer.js +21 -0
- package/dist/components/notebook-viewer/notebook-viewer.js.map +1 -0
- package/dist/components/notebook-viewer/notebook-viewer.styles.d.ts +2 -0
- package/dist/components/notebook-viewer/notebook-viewer.styles.d.ts.map +1 -0
- package/dist/components/notebook-viewer/notebook-viewer.styles.js +79 -0
- package/dist/components/notebook-viewer/notebook-viewer.styles.js.map +1 -0
- package/dist/components/overlay/overlay.styles.d.ts.map +1 -1
- package/dist/components/overlay/overlay.styles.js +17 -5
- package/dist/components/overlay/overlay.styles.js.map +1 -1
- package/dist/components/overlay/popover.class.d.ts +2 -0
- package/dist/components/overlay/popover.class.d.ts.map +1 -1
- package/dist/components/overlay/popover.class.js +10 -2
- package/dist/components/overlay/popover.class.js.map +1 -1
- package/dist/components/overlay/tooltip.class.d.ts +4 -0
- package/dist/components/overlay/tooltip.class.d.ts.map +1 -1
- package/dist/components/overlay/tooltip.class.js +21 -6
- package/dist/components/overlay/tooltip.class.js.map +1 -1
- package/dist/components/page-rail/page-rail.class.d.ts +99 -0
- package/dist/components/page-rail/page-rail.class.d.ts.map +1 -0
- package/dist/components/page-rail/page-rail.class.js +279 -0
- package/dist/components/page-rail/page-rail.class.js.map +1 -0
- package/dist/components/page-rail/page-rail.d.ts +2 -0
- package/dist/components/page-rail/page-rail.d.ts.map +1 -0
- package/dist/components/page-rail/page-rail.js +5 -0
- package/dist/components/page-rail/page-rail.js.map +1 -0
- package/dist/components/page-rail/page-rail.styles.d.ts +2 -0
- package/dist/components/page-rail/page-rail.styles.d.ts.map +1 -0
- package/dist/components/page-rail/page-rail.styles.js +85 -0
- package/dist/components/page-rail/page-rail.styles.js.map +1 -0
- package/dist/components/pagination/pagination.class.d.ts +5 -0
- package/dist/components/pagination/pagination.class.d.ts.map +1 -1
- package/dist/components/pagination/pagination.class.js +11 -9
- package/dist/components/pagination/pagination.class.js.map +1 -1
- package/dist/components/path-strip/path-strip.class.d.ts +61 -0
- package/dist/components/path-strip/path-strip.class.d.ts.map +1 -0
- package/dist/components/path-strip/path-strip.class.js +164 -0
- package/dist/components/path-strip/path-strip.class.js.map +1 -0
- package/dist/components/path-strip/path-strip.d.ts +3 -0
- package/dist/components/path-strip/path-strip.d.ts.map +1 -0
- package/dist/components/path-strip/path-strip.js +6 -0
- package/dist/components/path-strip/path-strip.js.map +1 -0
- package/dist/components/path-strip/path-strip.styles.d.ts +2 -0
- package/dist/components/path-strip/path-strip.styles.d.ts.map +1 -0
- package/dist/components/path-strip/path-strip.styles.js +62 -0
- package/dist/components/path-strip/path-strip.styles.js.map +1 -0
- package/dist/components/pdf-viewer/pdf-viewer.class.d.ts +145 -6
- package/dist/components/pdf-viewer/pdf-viewer.class.d.ts.map +1 -1
- package/dist/components/pdf-viewer/pdf-viewer.class.js +785 -21
- package/dist/components/pdf-viewer/pdf-viewer.class.js.map +1 -1
- package/dist/components/pdf-viewer/pdf-viewer.js +7 -1
- package/dist/components/pdf-viewer/pdf-viewer.js.map +1 -1
- package/dist/components/pdf-viewer/pdf-viewer.styles.d.ts.map +1 -1
- package/dist/components/pdf-viewer/pdf-viewer.styles.js +4 -0
- package/dist/components/pdf-viewer/pdf-viewer.styles.js.map +1 -1
- package/dist/components/phone-input/phone-input.class.d.ts.map +1 -1
- package/dist/components/phone-input/phone-input.class.js +5 -1
- package/dist/components/phone-input/phone-input.class.js.map +1 -1
- package/dist/components/playback/playback.styles.d.ts.map +1 -1
- package/dist/components/playback/playback.styles.js +7 -0
- package/dist/components/playback/playback.styles.js.map +1 -1
- package/dist/components/poll-status/poll-status.class.d.ts +1 -0
- package/dist/components/poll-status/poll-status.class.d.ts.map +1 -1
- package/dist/components/poll-status/poll-status.class.js +25 -7
- package/dist/components/poll-status/poll-status.class.js.map +1 -1
- package/dist/components/pptx-viewer/pptx-viewer.styles.d.ts.map +1 -1
- package/dist/components/pptx-viewer/pptx-viewer.styles.js +5 -0
- package/dist/components/pptx-viewer/pptx-viewer.styles.js.map +1 -1
- package/dist/components/progress/progress-bar.class.d.ts +5 -0
- package/dist/components/progress/progress-bar.class.d.ts.map +1 -1
- package/dist/components/progress/progress-bar.class.js +16 -2
- package/dist/components/progress/progress-bar.class.js.map +1 -1
- package/dist/components/progress/progress-ring.class.d.ts +5 -0
- package/dist/components/progress/progress-ring.class.d.ts.map +1 -1
- package/dist/components/progress/progress-ring.class.js +16 -2
- package/dist/components/progress/progress-ring.class.js.map +1 -1
- package/dist/components/progress/progress.styles.d.ts.map +1 -1
- package/dist/components/progress/progress.styles.js +6 -0
- package/dist/components/progress/progress.styles.js.map +1 -1
- package/dist/components/provenance-panel/provenance-panel.class.d.ts +71 -0
- package/dist/components/provenance-panel/provenance-panel.class.d.ts.map +1 -0
- package/dist/components/provenance-panel/provenance-panel.class.js +110 -0
- package/dist/components/provenance-panel/provenance-panel.class.js.map +1 -0
- package/dist/components/provenance-panel/provenance-panel.d.ts +7 -0
- package/dist/components/provenance-panel/provenance-panel.d.ts.map +1 -0
- package/dist/components/provenance-panel/provenance-panel.js +10 -0
- package/dist/components/provenance-panel/provenance-panel.js.map +1 -0
- package/dist/components/provenance-panel/provenance-panel.styles.d.ts +2 -0
- package/dist/components/provenance-panel/provenance-panel.styles.d.ts.map +1 -0
- package/dist/components/provenance-panel/provenance-panel.styles.js +45 -0
- package/dist/components/provenance-panel/provenance-panel.styles.js.map +1 -0
- package/dist/components/push-to-talk/push-to-talk.class.d.ts +145 -0
- package/dist/components/push-to-talk/push-to-talk.class.d.ts.map +1 -0
- package/dist/components/push-to-talk/push-to-talk.class.js +478 -0
- package/dist/components/push-to-talk/push-to-talk.class.js.map +1 -0
- package/dist/components/push-to-talk/push-to-talk.d.ts +3 -0
- package/dist/components/push-to-talk/push-to-talk.d.ts.map +1 -0
- package/dist/components/push-to-talk/push-to-talk.js +6 -0
- package/dist/components/push-to-talk/push-to-talk.js.map +1 -0
- package/dist/components/push-to-talk/push-to-talk.styles.d.ts +2 -0
- package/dist/components/push-to-talk/push-to-talk.styles.d.ts.map +1 -0
- package/dist/components/push-to-talk/push-to-talk.styles.js +79 -0
- package/dist/components/push-to-talk/push-to-talk.styles.js.map +1 -0
- package/dist/components/radio/radio.class.d.ts +1 -0
- package/dist/components/radio/radio.class.d.ts.map +1 -1
- package/dist/components/radio/radio.class.js +4 -0
- package/dist/components/radio/radio.class.js.map +1 -1
- package/dist/components/random-content/random-content.class.d.ts +3 -1
- package/dist/components/random-content/random-content.class.d.ts.map +1 -1
- package/dist/components/random-content/random-content.class.js +7 -4
- package/dist/components/random-content/random-content.class.js.map +1 -1
- package/dist/components/rating/rating.class.d.ts +8 -0
- package/dist/components/rating/rating.class.d.ts.map +1 -1
- package/dist/components/rating/rating.class.js +34 -8
- package/dist/components/rating/rating.class.js.map +1 -1
- package/dist/components/rubric-form/rubric-form.class.d.ts +195 -0
- package/dist/components/rubric-form/rubric-form.class.d.ts.map +1 -0
- package/dist/components/rubric-form/rubric-form.class.js +495 -0
- package/dist/components/rubric-form/rubric-form.class.js.map +1 -0
- package/dist/components/rubric-form/rubric-form.d.ts +9 -0
- package/dist/components/rubric-form/rubric-form.d.ts.map +1 -0
- package/dist/components/rubric-form/rubric-form.js +12 -0
- package/dist/components/rubric-form/rubric-form.js.map +1 -0
- package/dist/components/rubric-form/rubric-form.styles.d.ts +2 -0
- package/dist/components/rubric-form/rubric-form.styles.d.ts.map +1 -0
- package/dist/components/rubric-form/rubric-form.styles.js +90 -0
- package/dist/components/rubric-form/rubric-form.styles.js.map +1 -0
- package/dist/components/scroller/scroller.class.d.ts +6 -0
- package/dist/components/scroller/scroller.class.d.ts.map +1 -1
- package/dist/components/scroller/scroller.class.js +14 -4
- package/dist/components/scroller/scroller.class.js.map +1 -1
- package/dist/components/scroller/scroller.styles.d.ts.map +1 -1
- package/dist/components/scroller/scroller.styles.js +18 -0
- package/dist/components/scroller/scroller.styles.js.map +1 -1
- package/dist/components/segmented/segmented.class.d.ts +1 -0
- package/dist/components/segmented/segmented.class.d.ts.map +1 -1
- package/dist/components/segmented/segmented.class.js +1 -0
- package/dist/components/segmented/segmented.class.js.map +1 -1
- package/dist/components/segmented/segmented.styles.d.ts.map +1 -1
- package/dist/components/segmented/segmented.styles.js +21 -3
- package/dist/components/segmented/segmented.styles.js.map +1 -1
- package/dist/components/sequence-strip/sequence-strip.class.d.ts +62 -0
- package/dist/components/sequence-strip/sequence-strip.class.d.ts.map +1 -0
- package/dist/components/sequence-strip/sequence-strip.class.js +102 -0
- package/dist/components/sequence-strip/sequence-strip.class.js.map +1 -0
- package/dist/components/sequence-strip/sequence-strip.d.ts +2 -0
- package/dist/components/sequence-strip/sequence-strip.d.ts.map +1 -0
- package/dist/components/sequence-strip/sequence-strip.js +5 -0
- package/dist/components/sequence-strip/sequence-strip.js.map +1 -0
- package/dist/components/sequence-strip/sequence-strip.styles.d.ts +2 -0
- package/dist/components/sequence-strip/sequence-strip.styles.d.ts.map +1 -0
- package/dist/components/sequence-strip/sequence-strip.styles.js +62 -0
- package/dist/components/sequence-strip/sequence-strip.styles.js.map +1 -0
- package/dist/components/skeleton/skeleton.styles.d.ts.map +1 -1
- package/dist/components/skeleton/skeleton.styles.js +7 -0
- package/dist/components/skeleton/skeleton.styles.js.map +1 -1
- package/dist/components/slider/slider.class.d.ts +6 -1
- package/dist/components/slider/slider.class.d.ts.map +1 -1
- package/dist/components/slider/slider.class.js +23 -6
- package/dist/components/slider/slider.class.js.map +1 -1
- package/dist/components/slider/slider.styles.d.ts.map +1 -1
- package/dist/components/slider/slider.styles.js +15 -0
- package/dist/components/slider/slider.styles.js.map +1 -1
- package/dist/components/source-picker/source-picker.class.d.ts +78 -0
- package/dist/components/source-picker/source-picker.class.d.ts.map +1 -0
- package/dist/components/source-picker/source-picker.class.js +305 -0
- package/dist/components/source-picker/source-picker.class.js.map +1 -0
- package/dist/components/source-picker/source-picker.d.ts +5 -0
- package/dist/components/source-picker/source-picker.d.ts.map +1 -0
- package/dist/components/source-picker/source-picker.js +8 -0
- package/dist/components/source-picker/source-picker.js.map +1 -0
- package/dist/components/source-picker/source-picker.styles.d.ts +2 -0
- package/dist/components/source-picker/source-picker.styles.d.ts.map +1 -0
- package/dist/components/source-picker/source-picker.styles.js +80 -0
- package/dist/components/source-picker/source-picker.styles.js.map +1 -0
- package/dist/components/span-waterfall/span-waterfall.class.d.ts +70 -0
- package/dist/components/span-waterfall/span-waterfall.class.d.ts.map +1 -0
- package/dist/components/span-waterfall/span-waterfall.class.js +307 -0
- package/dist/components/span-waterfall/span-waterfall.class.js.map +1 -0
- package/dist/components/span-waterfall/span-waterfall.d.ts +4 -0
- package/dist/components/span-waterfall/span-waterfall.d.ts.map +1 -0
- package/dist/components/span-waterfall/span-waterfall.js +7 -0
- package/dist/components/span-waterfall/span-waterfall.js.map +1 -0
- package/dist/components/span-waterfall/span-waterfall.styles.d.ts +2 -0
- package/dist/components/span-waterfall/span-waterfall.styles.d.ts.map +1 -0
- package/dist/components/span-waterfall/span-waterfall.styles.js +130 -0
- package/dist/components/span-waterfall/span-waterfall.styles.js.map +1 -0
- package/dist/components/sparkline/sparkline.class.d.ts.map +1 -1
- package/dist/components/sparkline/sparkline.class.js +17 -7
- package/dist/components/sparkline/sparkline.class.js.map +1 -1
- package/dist/components/split/split.class.d.ts +13 -0
- package/dist/components/split/split.class.d.ts.map +1 -1
- package/dist/components/split/split.class.js +24 -4
- package/dist/components/split/split.class.js.map +1 -1
- package/dist/components/spreadsheet-viewer/spreadsheet-loader.js +1 -1
- package/dist/components/spreadsheet-viewer/spreadsheet-loader.js.map +1 -1
- package/dist/components/spreadsheet-viewer/spreadsheet-viewer.class.d.ts +93 -3
- package/dist/components/spreadsheet-viewer/spreadsheet-viewer.class.d.ts.map +1 -1
- package/dist/components/spreadsheet-viewer/spreadsheet-viewer.class.js +241 -9
- package/dist/components/spreadsheet-viewer/spreadsheet-viewer.class.js.map +1 -1
- package/dist/components/spreadsheet-viewer/spreadsheet-viewer.js +10 -1
- package/dist/components/spreadsheet-viewer/spreadsheet-viewer.js.map +1 -1
- package/dist/components/stack-trace/stack-trace-parse.d.ts +22 -0
- package/dist/components/stack-trace/stack-trace-parse.d.ts.map +1 -0
- package/dist/components/stack-trace/stack-trace-parse.js +194 -0
- package/dist/components/stack-trace/stack-trace-parse.js.map +1 -0
- package/dist/components/stack-trace/stack-trace.class.d.ts +68 -0
- package/dist/components/stack-trace/stack-trace.class.d.ts.map +1 -0
- package/dist/components/stack-trace/stack-trace.class.js +193 -0
- package/dist/components/stack-trace/stack-trace.class.js.map +1 -0
- package/dist/components/stack-trace/stack-trace.d.ts +3 -0
- package/dist/components/stack-trace/stack-trace.d.ts.map +1 -0
- package/dist/components/stack-trace/stack-trace.js +6 -0
- package/dist/components/stack-trace/stack-trace.js.map +1 -0
- package/dist/components/stack-trace/stack-trace.styles.d.ts +2 -0
- package/dist/components/stack-trace/stack-trace.styles.d.ts.map +1 -0
- package/dist/components/stack-trace/stack-trace.styles.js +101 -0
- package/dist/components/stack-trace/stack-trace.styles.js.map +1 -0
- package/dist/components/stat/stat.class.d.ts +10 -1
- package/dist/components/stat/stat.class.d.ts.map +1 -1
- package/dist/components/stat/stat.class.js +22 -7
- package/dist/components/stat/stat.class.js.map +1 -1
- package/dist/components/stepper/stepper.class.d.ts +5 -0
- package/dist/components/stepper/stepper.class.d.ts.map +1 -1
- package/dist/components/stepper/stepper.class.js +9 -1
- package/dist/components/stepper/stepper.class.js.map +1 -1
- package/dist/components/stream-status/stream-status.class.d.ts.map +1 -1
- package/dist/components/stream-status/stream-status.class.js +9 -1
- package/dist/components/stream-status/stream-status.class.js.map +1 -1
- package/dist/components/streaming-text/streaming-text.class.d.ts +6 -0
- package/dist/components/streaming-text/streaming-text.class.d.ts.map +1 -1
- package/dist/components/streaming-text/streaming-text.class.js +22 -3
- package/dist/components/streaming-text/streaming-text.class.js.map +1 -1
- package/dist/components/suggestion-chips/suggestion-chips.class.d.ts +54 -0
- package/dist/components/suggestion-chips/suggestion-chips.class.d.ts.map +1 -0
- package/dist/components/suggestion-chips/suggestion-chips.class.js +120 -0
- package/dist/components/suggestion-chips/suggestion-chips.class.js.map +1 -0
- package/dist/components/suggestion-chips/suggestion-chips.d.ts +3 -0
- package/dist/components/suggestion-chips/suggestion-chips.d.ts.map +1 -0
- package/dist/components/suggestion-chips/suggestion-chips.js +6 -0
- package/dist/components/suggestion-chips/suggestion-chips.js.map +1 -0
- package/dist/components/suggestion-chips/suggestion-chips.styles.d.ts +2 -0
- package/dist/components/suggestion-chips/suggestion-chips.styles.d.ts.map +1 -0
- package/dist/components/suggestion-chips/suggestion-chips.styles.js +60 -0
- package/dist/components/suggestion-chips/suggestion-chips.styles.js.map +1 -0
- package/dist/components/svg-viewer/svg-viewer.class.d.ts +34 -0
- package/dist/components/svg-viewer/svg-viewer.class.d.ts.map +1 -1
- package/dist/components/svg-viewer/svg-viewer.class.js +88 -1
- package/dist/components/svg-viewer/svg-viewer.class.js.map +1 -1
- package/dist/components/svg-viewer/svg-viewer.js +1 -0
- package/dist/components/svg-viewer/svg-viewer.js.map +1 -1
- package/dist/components/svg-viewer/svg-viewer.styles.d.ts.map +1 -1
- package/dist/components/svg-viewer/svg-viewer.styles.js +18 -0
- package/dist/components/svg-viewer/svg-viewer.styles.js.map +1 -1
- package/dist/components/swatch-picker/swatch-picker.class.d.ts +71 -0
- package/dist/components/swatch-picker/swatch-picker.class.d.ts.map +1 -0
- package/dist/components/swatch-picker/swatch-picker.class.js +134 -0
- package/dist/components/swatch-picker/swatch-picker.class.js.map +1 -0
- package/dist/components/swatch-picker/swatch-picker.d.ts +2 -0
- package/dist/components/swatch-picker/swatch-picker.d.ts.map +1 -0
- package/dist/components/swatch-picker/swatch-picker.js +5 -0
- package/dist/components/swatch-picker/swatch-picker.js.map +1 -0
- package/dist/components/swatch-picker/swatch-picker.styles.d.ts +2 -0
- package/dist/components/swatch-picker/swatch-picker.styles.d.ts.map +1 -0
- package/dist/components/swatch-picker/swatch-picker.styles.js +131 -0
- package/dist/components/swatch-picker/swatch-picker.styles.js.map +1 -0
- package/dist/components/table/table.class.d.ts +85 -5
- package/dist/components/table/table.class.d.ts.map +1 -1
- package/dist/components/table/table.class.js +254 -41
- package/dist/components/table/table.class.js.map +1 -1
- package/dist/components/table/table.styles.d.ts.map +1 -1
- package/dist/components/table/table.styles.js +35 -0
- package/dist/components/table/table.styles.js.map +1 -1
- package/dist/components/tabs/tabs.class.d.ts +6 -0
- package/dist/components/tabs/tabs.class.d.ts.map +1 -1
- package/dist/components/tabs/tabs.class.js +10 -1
- package/dist/components/tabs/tabs.class.js.map +1 -1
- package/dist/components/tabs/tabs.styles.d.ts.map +1 -1
- package/dist/components/tabs/tabs.styles.js +15 -0
- package/dist/components/tabs/tabs.styles.js.map +1 -1
- package/dist/components/task-list/task-list.class.d.ts +89 -0
- package/dist/components/task-list/task-list.class.d.ts.map +1 -0
- package/dist/components/task-list/task-list.class.js +271 -0
- package/dist/components/task-list/task-list.class.js.map +1 -0
- package/dist/components/task-list/task-list.d.ts +2 -0
- package/dist/components/task-list/task-list.d.ts.map +1 -0
- package/dist/components/task-list/task-list.js +5 -0
- package/dist/components/task-list/task-list.js.map +1 -0
- package/dist/components/task-list/task-list.styles.d.ts +2 -0
- package/dist/components/task-list/task-list.styles.d.ts.map +1 -0
- package/dist/components/task-list/task-list.styles.js +134 -0
- package/dist/components/task-list/task-list.styles.js.map +1 -0
- package/dist/components/terminal/terminal.class.d.ts +150 -0
- package/dist/components/terminal/terminal.class.d.ts.map +1 -0
- package/dist/components/terminal/terminal.class.js +565 -0
- package/dist/components/terminal/terminal.class.js.map +1 -0
- package/dist/components/terminal/terminal.d.ts +2 -0
- package/dist/components/terminal/terminal.d.ts.map +1 -0
- package/dist/components/terminal/terminal.js +5 -0
- package/dist/components/terminal/terminal.js.map +1 -0
- package/dist/components/terminal/terminal.styles.d.ts +2 -0
- package/dist/components/terminal/terminal.styles.d.ts.map +1 -0
- package/dist/components/terminal/terminal.styles.js +77 -0
- package/dist/components/terminal/terminal.styles.js.map +1 -0
- package/dist/components/test-results/test-results.class.d.ts +99 -0
- package/dist/components/test-results/test-results.class.d.ts.map +1 -0
- package/dist/components/test-results/test-results.class.js +276 -0
- package/dist/components/test-results/test-results.class.js.map +1 -0
- package/dist/components/test-results/test-results.d.ts +2 -0
- package/dist/components/test-results/test-results.d.ts.map +1 -0
- package/dist/components/test-results/test-results.js +5 -0
- package/dist/components/test-results/test-results.js.map +1 -0
- package/dist/components/test-results/test-results.styles.d.ts +2 -0
- package/dist/components/test-results/test-results.styles.d.ts.map +1 -0
- package/dist/components/test-results/test-results.styles.js +118 -0
- package/dist/components/test-results/test-results.styles.js.map +1 -0
- package/dist/components/textarea/textarea.class.d.ts.map +1 -1
- package/dist/components/textarea/textarea.class.js +4 -0
- package/dist/components/textarea/textarea.class.js.map +1 -1
- package/dist/components/thinking-panel/thinking-panel.class.d.ts +6 -0
- package/dist/components/thinking-panel/thinking-panel.class.d.ts.map +1 -1
- package/dist/components/thinking-panel/thinking-panel.class.js +12 -2
- package/dist/components/thinking-panel/thinking-panel.class.js.map +1 -1
- package/dist/components/thread-list/thread-list.class.d.ts +130 -0
- package/dist/components/thread-list/thread-list.class.d.ts.map +1 -0
- package/dist/components/thread-list/thread-list.class.js +480 -0
- package/dist/components/thread-list/thread-list.class.js.map +1 -0
- package/dist/components/thread-list/thread-list.d.ts +5 -0
- package/dist/components/thread-list/thread-list.d.ts.map +1 -0
- package/dist/components/thread-list/thread-list.js +8 -0
- package/dist/components/thread-list/thread-list.js.map +1 -0
- package/dist/components/thread-list/thread-list.styles.d.ts +2 -0
- package/dist/components/thread-list/thread-list.styles.d.ts.map +1 -0
- package/dist/components/thread-list/thread-list.styles.js +81 -0
- package/dist/components/thread-list/thread-list.styles.js.map +1 -0
- package/dist/components/time-range/time-range.class.d.ts.map +1 -1
- package/dist/components/time-range/time-range.class.js +3 -3
- package/dist/components/time-range/time-range.class.js.map +1 -1
- package/dist/components/timeline/timeline-item.class.d.ts.map +1 -1
- package/dist/components/timeline/timeline-item.class.js +2 -1
- package/dist/components/timeline/timeline-item.class.js.map +1 -1
- package/dist/components/toast/toast-item.class.d.ts +8 -0
- package/dist/components/toast/toast-item.class.d.ts.map +1 -1
- package/dist/components/toast/toast-item.class.js +14 -2
- package/dist/components/toast/toast-item.class.js.map +1 -1
- package/dist/components/toast/toast-item.styles.d.ts.map +1 -1
- package/dist/components/toast/toast-item.styles.js +2 -0
- package/dist/components/toast/toast-item.styles.js.map +1 -1
- package/dist/components/token-input/token-input.class.d.ts +29 -3
- package/dist/components/token-input/token-input.class.d.ts.map +1 -1
- package/dist/components/token-input/token-input.class.js +41 -13
- package/dist/components/token-input/token-input.class.js.map +1 -1
- package/dist/components/token-input/token-input.styles.d.ts.map +1 -1
- package/dist/components/token-input/token-input.styles.js +6 -1
- package/dist/components/token-input/token-input.styles.js.map +1 -1
- package/dist/components/tool-call-chip/tool-call-chip.class.d.ts +6 -0
- package/dist/components/tool-call-chip/tool-call-chip.class.d.ts.map +1 -1
- package/dist/components/tool-call-chip/tool-call-chip.class.js +15 -4
- package/dist/components/tool-call-chip/tool-call-chip.class.js.map +1 -1
- package/dist/components/tool-result-dialog/tool-result-dialog.class.d.ts +6 -0
- package/dist/components/tool-result-dialog/tool-result-dialog.class.d.ts.map +1 -1
- package/dist/components/tool-result-dialog/tool-result-dialog.class.js +12 -3
- package/dist/components/tool-result-dialog/tool-result-dialog.class.js.map +1 -1
- package/dist/components/tour/tour.class.d.ts +6 -3
- package/dist/components/tour/tour.class.d.ts.map +1 -1
- package/dist/components/tour/tour.class.js +56 -20
- package/dist/components/tour/tour.class.js.map +1 -1
- package/dist/components/trace-tree/span.d.ts +26 -0
- package/dist/components/trace-tree/span.d.ts.map +1 -0
- package/dist/components/trace-tree/span.js +2 -0
- package/dist/components/trace-tree/span.js.map +1 -0
- package/dist/components/trace-tree/trace-tree.class.d.ts +85 -0
- package/dist/components/trace-tree/trace-tree.class.d.ts.map +1 -0
- package/dist/components/trace-tree/trace-tree.class.js +443 -0
- package/dist/components/trace-tree/trace-tree.class.js.map +1 -0
- package/dist/components/trace-tree/trace-tree.d.ts +5 -0
- package/dist/components/trace-tree/trace-tree.d.ts.map +1 -0
- package/dist/components/trace-tree/trace-tree.js +8 -0
- package/dist/components/trace-tree/trace-tree.js.map +1 -0
- package/dist/components/trace-tree/trace-tree.styles.d.ts +2 -0
- package/dist/components/trace-tree/trace-tree.styles.d.ts.map +1 -0
- package/dist/components/trace-tree/trace-tree.styles.js +186 -0
- package/dist/components/trace-tree/trace-tree.styles.js.map +1 -0
- package/dist/components/transcript-feed/transcript-feed.class.d.ts +89 -0
- package/dist/components/transcript-feed/transcript-feed.class.d.ts.map +1 -0
- package/dist/components/transcript-feed/transcript-feed.class.js +188 -0
- package/dist/components/transcript-feed/transcript-feed.class.js.map +1 -0
- package/dist/components/transcript-feed/transcript-feed.d.ts +2 -0
- package/dist/components/transcript-feed/transcript-feed.d.ts.map +1 -0
- package/dist/components/transcript-feed/transcript-feed.js +5 -0
- package/dist/components/transcript-feed/transcript-feed.js.map +1 -0
- package/dist/components/transcript-feed/transcript-feed.styles.d.ts +2 -0
- package/dist/components/transcript-feed/transcript-feed.styles.d.ts.map +1 -0
- package/dist/components/transcript-feed/transcript-feed.styles.js +94 -0
- package/dist/components/transcript-feed/transcript-feed.styles.js.map +1 -0
- package/dist/components/tree/tree-node.class.d.ts +25 -4
- package/dist/components/tree/tree-node.class.d.ts.map +1 -1
- package/dist/components/tree/tree-node.class.js +61 -11
- package/dist/components/tree/tree-node.class.js.map +1 -1
- package/dist/components/tree/tree-node.styles.d.ts.map +1 -1
- package/dist/components/tree/tree-node.styles.js +34 -5
- package/dist/components/tree/tree-node.styles.js.map +1 -1
- package/dist/components/tree/tree.class.d.ts +9 -0
- package/dist/components/tree/tree.class.d.ts.map +1 -1
- package/dist/components/tree/tree.class.js.map +1 -1
- package/dist/components/usage-badge/usage-badge.class.d.ts +78 -0
- package/dist/components/usage-badge/usage-badge.class.d.ts.map +1 -0
- package/dist/components/usage-badge/usage-badge.class.js +237 -0
- package/dist/components/usage-badge/usage-badge.class.js.map +1 -0
- package/dist/components/usage-badge/usage-badge.d.ts +2 -0
- package/dist/components/usage-badge/usage-badge.d.ts.map +1 -0
- package/dist/components/usage-badge/usage-badge.js +5 -0
- package/dist/components/usage-badge/usage-badge.js.map +1 -0
- package/dist/components/usage-badge/usage-badge.styles.d.ts +2 -0
- package/dist/components/usage-badge/usage-badge.styles.d.ts.map +1 -0
- package/dist/components/usage-badge/usage-badge.styles.js +62 -0
- package/dist/components/usage-badge/usage-badge.styles.js.map +1 -0
- package/dist/components/virtual-list/virtual-list.class.d.ts +62 -0
- package/dist/components/virtual-list/virtual-list.class.d.ts.map +1 -1
- package/dist/components/virtual-list/virtual-list.class.js +123 -8
- package/dist/components/virtual-list/virtual-list.class.js.map +1 -1
- package/dist/components/voice-picker/voice-picker.class.d.ts +241 -0
- package/dist/components/voice-picker/voice-picker.class.d.ts.map +1 -0
- package/dist/components/voice-picker/voice-picker.class.js +808 -0
- package/dist/components/voice-picker/voice-picker.class.js.map +1 -0
- package/dist/components/voice-picker/voice-picker.d.ts +2 -0
- package/dist/components/voice-picker/voice-picker.d.ts.map +1 -0
- package/dist/components/voice-picker/voice-picker.js +5 -0
- package/dist/components/voice-picker/voice-picker.js.map +1 -0
- package/dist/components/voice-picker/voice-picker.styles.d.ts +2 -0
- package/dist/components/voice-picker/voice-picker.styles.d.ts.map +1 -0
- package/dist/components/voice-picker/voice-picker.styles.js +272 -0
- package/dist/components/voice-picker/voice-picker.styles.js.map +1 -0
- package/dist/components/widget-renderer/default-registry.d.ts +14 -0
- package/dist/components/widget-renderer/default-registry.d.ts.map +1 -0
- package/dist/components/widget-renderer/default-registry.js +43 -0
- package/dist/components/widget-renderer/default-registry.js.map +1 -0
- package/dist/components/widget-renderer/registry.d.ts +31 -0
- package/dist/components/widget-renderer/registry.d.ts.map +1 -0
- package/dist/components/widget-renderer/registry.js +23 -0
- package/dist/components/widget-renderer/registry.js.map +1 -0
- package/dist/components/widget-renderer/resolve.d.ts +48 -0
- package/dist/components/widget-renderer/resolve.d.ts.map +1 -0
- package/dist/components/widget-renderer/resolve.js +122 -0
- package/dist/components/widget-renderer/resolve.js.map +1 -0
- package/dist/components/widget-renderer/widget-renderer.class.d.ts +67 -0
- package/dist/components/widget-renderer/widget-renderer.class.d.ts.map +1 -0
- package/dist/components/widget-renderer/widget-renderer.class.js +175 -0
- package/dist/components/widget-renderer/widget-renderer.class.js.map +1 -0
- package/dist/components/widget-renderer/widget-renderer.d.ts +5 -0
- package/dist/components/widget-renderer/widget-renderer.d.ts.map +1 -0
- package/dist/components/widget-renderer/widget-renderer.js +10 -0
- package/dist/components/widget-renderer/widget-renderer.js.map +1 -0
- package/dist/components/widget-renderer/widget-renderer.styles.d.ts +2 -0
- package/dist/components/widget-renderer/widget-renderer.styles.d.ts.map +1 -0
- package/dist/components/widget-renderer/widget-renderer.styles.js +14 -0
- package/dist/components/widget-renderer/widget-renderer.styles.js.map +1 -0
- package/dist/components/word-cloud/word-cloud-layout.d.ts +4 -0
- package/dist/components/word-cloud/word-cloud-layout.d.ts.map +1 -1
- package/dist/components/word-cloud/word-cloud-layout.js +3 -2
- package/dist/components/word-cloud/word-cloud-layout.js.map +1 -1
- package/dist/components/word-cloud/word-cloud.class.d.ts.map +1 -1
- package/dist/components/word-cloud/word-cloud.class.js +11 -3
- package/dist/components/word-cloud/word-cloud.class.js.map +1 -1
- package/dist/components/xml-viewer/xml-viewer.class.d.ts +135 -0
- package/dist/components/xml-viewer/xml-viewer.class.d.ts.map +1 -0
- package/dist/components/xml-viewer/xml-viewer.class.js +0 -0
- package/dist/components/xml-viewer/xml-viewer.class.js.map +1 -0
- package/dist/components/xml-viewer/xml-viewer.d.ts +2 -0
- package/dist/components/xml-viewer/xml-viewer.d.ts.map +1 -0
- package/dist/components/xml-viewer/xml-viewer.js +20 -0
- package/dist/components/xml-viewer/xml-viewer.js.map +1 -0
- package/dist/components/xml-viewer/xml-viewer.styles.d.ts +2 -0
- package/dist/components/xml-viewer/xml-viewer.styles.d.ts.map +1 -0
- package/dist/components/xml-viewer/xml-viewer.styles.js +156 -0
- package/dist/components/xml-viewer/xml-viewer.styles.js.map +1 -0
- package/dist/components/zoomable-frame/zoomable-frame.class.d.ts +14 -2
- package/dist/components/zoomable-frame/zoomable-frame.class.d.ts.map +1 -1
- package/dist/components/zoomable-frame/zoomable-frame.class.js +30 -14
- package/dist/components/zoomable-frame/zoomable-frame.class.js.map +1 -1
- package/dist/internal/anchor-target.d.ts +49 -0
- package/dist/internal/anchor-target.d.ts.map +1 -0
- package/dist/internal/anchor-target.js +255 -0
- package/dist/internal/anchor-target.js.map +1 -0
- package/dist/internal/ansi.d.ts +35 -0
- package/dist/internal/ansi.d.ts.map +1 -0
- package/dist/internal/ansi.js +210 -0
- package/dist/internal/ansi.js.map +1 -0
- package/dist/internal/cell-range.d.ts +19 -0
- package/dist/internal/cell-range.d.ts.map +1 -0
- package/dist/internal/cell-range.js +69 -0
- package/dist/internal/cell-range.js.map +1 -0
- package/dist/internal/intl-cache.d.ts +33 -0
- package/dist/internal/intl-cache.d.ts.map +1 -0
- package/dist/internal/intl-cache.js +0 -0
- package/dist/internal/intl-cache.js.map +1 -0
- package/dist/internal/layered-layout.d.ts +44 -0
- package/dist/internal/layered-layout.d.ts.map +1 -0
- package/dist/internal/layered-layout.js +172 -0
- package/dist/internal/layered-layout.js.map +1 -0
- package/dist/internal/localization.d.ts +12 -1
- package/dist/internal/localization.d.ts.map +1 -1
- package/dist/internal/localization.js +367 -4
- package/dist/internal/localization.js.map +1 -1
- package/dist/internal/lyra-element.d.ts +10 -1
- package/dist/internal/lyra-element.d.ts.map +1 -1
- package/dist/internal/lyra-element.js +19 -1
- package/dist/internal/lyra-element.js.map +1 -1
- package/dist/internal/root-registration-allowlist.d.ts +2 -2
- package/dist/internal/root-registration-allowlist.d.ts.map +1 -1
- package/dist/internal/root-registration-allowlist.js +55 -0
- package/dist/internal/root-registration-allowlist.js.map +1 -1
- package/dist/internal/slugger.d.ts +11 -0
- package/dist/internal/slugger.d.ts.map +1 -0
- package/dist/internal/slugger.js +45 -0
- package/dist/internal/slugger.js.map +1 -0
- package/dist/internal/text-highlights.d.ts +21 -0
- package/dist/internal/text-highlights.d.ts.map +1 -0
- package/dist/internal/text-highlights.js +172 -0
- package/dist/internal/text-highlights.js.map +1 -0
- package/dist/internal/text-quote.d.ts +53 -0
- package/dist/internal/text-quote.d.ts.map +1 -0
- package/dist/internal/text-quote.js +326 -0
- package/dist/internal/text-quote.js.map +1 -0
- package/dist/internal/tokens.styles.d.ts.map +1 -1
- package/dist/internal/tokens.styles.js +49 -0
- package/dist/internal/tokens.styles.js.map +1 -1
- package/dist/internal/viewer-search.d.ts +18 -0
- package/dist/internal/viewer-search.d.ts.map +1 -0
- package/dist/internal/viewer-search.js +21 -0
- package/dist/internal/viewer-search.js.map +1 -0
- package/dist/lyra.d.ts +137 -2
- package/dist/lyra.d.ts.map +1 -1
- package/dist/lyra.js +109 -0
- package/dist/lyra.js.map +1 -1
- package/llms-full.txt +2682 -78
- package/llms.txt +28 -2
- package/package.json +157 -31
- package/vscode-css-data.json +231 -0
- package/vscode-html-data.json +5222 -2201
- package/web-types.json +5721 -2508
|
@@ -5,16 +5,30 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { html, nothing, svg } from 'lit';
|
|
8
|
-
import { property, state } from 'lit/decorators.js';
|
|
8
|
+
import { property, state, query } from 'lit/decorators.js';
|
|
9
9
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
10
10
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
11
11
|
import { nextId, srOnly } from '../../internal/a11y.js';
|
|
12
12
|
import { prefersReducedMotion } from '../../internal/motion.js';
|
|
13
13
|
import { isRtl } from '../../internal/rtl.js';
|
|
14
|
+
import { getScratchCtx } from '../../internal/canvas.js';
|
|
14
15
|
import { styles } from './graph.styles.js';
|
|
15
16
|
import { loadD3 } from './graph-loader.js';
|
|
17
|
+
import { convexHull, hullPathD, hullCentroidX, hullTopY } from './graph-hull.js';
|
|
18
|
+
import { drawGraphScene, drawPickingScene, pickColorToIndex } from './graph-canvas.js';
|
|
19
|
+
import { layeredLayout } from '../../internal/layered-layout.js';
|
|
20
|
+
import { finiteNumber, finiteRange, finiteInteger } from '../../internal/numbers.js';
|
|
16
21
|
import '../skeleton/skeleton.class.js';
|
|
17
22
|
const STUB_OFFSET_PX = 14; // matches the length of a typical broken-link stub in comparable UIs
|
|
23
|
+
const EDGE_LABEL_OFFSET_PX = 4; // perpendicular offset from the segment midpoint, in world px
|
|
24
|
+
const EDGE_LABEL_LENGTH_GATE_RATIO = 0.85; // label hides when its measured width exceeds this * edge length
|
|
25
|
+
const EDGE_LABEL_WIDTH_CACHE_MAX = 512; // distinct measured label texts kept before the oldest entry is evicted
|
|
26
|
+
const EXPAND_KEY_INTERVAL_MS = 500; // window for a double-Enter/Space to count as a double-activate
|
|
27
|
+
const EXPAND_BADGE_R = 5; // world px, the "+" badge circle radius
|
|
28
|
+
const EXPAND_BADGE_OFFSET = Math.SQRT1_2; // places the badge at the node's edge, diagonally upper-right
|
|
29
|
+
const FOCUS_HALO_PADDING = 6; // world px added to the node's own radius for the halo ring
|
|
30
|
+
const HULL_PADDING = 24; // world px; CSS mirrors this via stroke-width: 2 * --lyra-size-24px
|
|
31
|
+
const CANVAS_NODE_LABEL_MIN_ZOOM = 0.5; // canvas-only declutter -- node labels draw only at/above this scale
|
|
18
32
|
/**
|
|
19
33
|
* Tiny deterministic PRNG (mulberry32, public-domain) used only when `seed`
|
|
20
34
|
* is set, so a node's initial x/y is reproducible instead of whatever
|
|
@@ -65,6 +79,29 @@ function normalizeLinkDash(dash) {
|
|
|
65
79
|
return undefined;
|
|
66
80
|
return dash.join(' ');
|
|
67
81
|
}
|
|
82
|
+
/** Assigns a typed node with no explicit color a slot from the ordered categorical fallback
|
|
83
|
+
* palette, cycling every 8 entries (`--lyra-graph-cat-1`…`--lyra-graph-cat-8`). `index` is the
|
|
84
|
+
* node's `GraphNodeType`'s position in `nodeTypes`, not the node's own index in `nodes`. */
|
|
85
|
+
function categoricalPaletteColor(index) {
|
|
86
|
+
return `var(--lyra-graph-cat-${(index % 8) + 1})`;
|
|
87
|
+
}
|
|
88
|
+
/** side = r * sqrt(pi), area-matched to a circle of radius r (side^2 = pi*r^2). Half-side is what
|
|
89
|
+
* the path data actually needs, since both shapes are drawn centered on the origin and
|
|
90
|
+
* positioned via a `transform="translate(x,y)"` per tick, never via absolute cx/cy. */
|
|
91
|
+
function shapeHalfSide(r) {
|
|
92
|
+
return (r * Math.sqrt(Math.PI)) / 2;
|
|
93
|
+
}
|
|
94
|
+
/** A square, centered on the origin, side ~= 1.772 * r (area-matched to the circle of radius r). */
|
|
95
|
+
function squarePath(r) {
|
|
96
|
+
const s = shapeHalfSide(r);
|
|
97
|
+
return `M ${-s} ${-s} L ${s} ${-s} L ${s} ${s} L ${-s} ${s} Z`;
|
|
98
|
+
}
|
|
99
|
+
/** The same square as `squarePath()`, rotated 45 degrees: same side length, vertices at the
|
|
100
|
+
* half-diagonal distance (s * sqrt(2)) along each axis instead of the square's own corners. */
|
|
101
|
+
function diamondPath(r) {
|
|
102
|
+
const d = shapeHalfSide(r) * Math.SQRT2;
|
|
103
|
+
return `M 0 ${-d} L ${d} 0 L 0 ${d} L ${-d} 0 Z`;
|
|
104
|
+
}
|
|
68
105
|
/**
|
|
69
106
|
* `<lyra-graph>` — a force-directed node-link diagram with pan/zoom/drag.
|
|
70
107
|
* Requires the optional peer deps `d3-force`/`d3-drag`/`d3-zoom`/`d3-selection`
|
|
@@ -80,26 +117,114 @@ function normalizeLinkDash(dash) {
|
|
|
80
117
|
* already-rendered graph is a no-op; nothing re-derives already-positioned
|
|
81
118
|
* nodes' x/y from the new value.
|
|
82
119
|
*
|
|
120
|
+
* `hiddenTypes` filters nodes/links by `GraphNode.type` without discarding position state --
|
|
121
|
+
* `lastPositionById` remembers every node's last settled x/y across a hide/show round-trip, so
|
|
122
|
+
* toggling a type off and back on restores each node where it was instead of re-randomizing it.
|
|
123
|
+
*
|
|
124
|
+
* `communities` draws one translucent convex-hull blob per entry, behind links/nodes -- a hull's
|
|
125
|
+
* membership is the union of its own `memberIds` and every node whose `communityId` matches its
|
|
126
|
+
* `id`. A community with no currently-visible members (all its nodes hidden by `hiddenTypes`, or
|
|
127
|
+
* simply empty) renders no hull.
|
|
128
|
+
*
|
|
129
|
+
* `layout="layered"` swaps the d3-force simulation for a deterministic layered layout (see
|
|
130
|
+
* `src/internal/layered-layout.ts`) -- node drag is disabled in that mode, and `chargeStrength` is
|
|
131
|
+
* a documented no-op.
|
|
132
|
+
*
|
|
133
|
+
* `renderer="canvas"` swaps the per-node/per-link SVG DOM for a single DPR-aware `<canvas>` --
|
|
134
|
+
* every event/method/property behaves identically to `renderer="svg"` (the default), with hit-
|
|
135
|
+
* testing resolved via an offscreen color-picking canvas instead of DOM event targets. The
|
|
136
|
+
* documented trade-offs: no `::part(node)`/`::part(link)` styling (pixels, not elements -- theme
|
|
137
|
+
* via cssprops instead), no native SVG `<title>` tooltip (replaced by `part="tooltip"`), and a
|
|
138
|
+
* drawn focus ring instead of a CSS one. Keyboard roving/announcements are preserved through an
|
|
139
|
+
* offscreen `part="cursor-item"` button per node/link/hull, driving the identical roving-tabindex
|
|
140
|
+
* logic as `renderer="svg"`.
|
|
141
|
+
*
|
|
83
142
|
* @customElement lyra-graph
|
|
84
|
-
* @event lyra-node-click - `detail: { id }
|
|
143
|
+
* @event lyra-node-click - `detail: { id, x, y }`, where `x` and `y` are the
|
|
144
|
+
* node's current coordinates in the graph's local drawing space.
|
|
85
145
|
* @event lyra-link-click - `detail: { source, target, id? }`.
|
|
146
|
+
* @event lyra-node-enter - A node was hovered. `detail: { id }`. Suppressed while dragging or
|
|
147
|
+
* panning. Also toggles a `data-hovered` attribute on that node's `[part="node"]` element for
|
|
148
|
+
* pure-CSS theming (not a substitute for this event — a consumer computing its own
|
|
149
|
+
* adjacency-based highlight needs the id, which only the event carries).
|
|
150
|
+
* @event lyra-node-leave - The hover from `lyra-node-enter` ended. `detail: { id }`.
|
|
151
|
+
* @event lyra-link-enter - A link was hovered. `detail: { source, target, id? }`. Same
|
|
152
|
+
* suppression/`data-hovered` behavior as `lyra-node-enter`.
|
|
153
|
+
* @event lyra-link-leave - The hover from `lyra-link-enter` ended. `detail: { source, target, id?
|
|
154
|
+
* }`.
|
|
155
|
+
* @event lyra-node-expand - A node was double-activated (native `dblclick`, or two Enter/Space
|
|
156
|
+
* activations of the same focused node within 500ms). `detail: { id }`. Fires for any node
|
|
157
|
+
* regardless of `GraphNode.expandable` -- that flag only controls the visual "+" affordance and
|
|
158
|
+
* spoken "expandable" suffix.
|
|
159
|
+
* @event lyra-selection-change - `detail: { nodeIds, linkIds }`. Fires when `selectionMode` is not
|
|
160
|
+
* `'none'` and the user activates/clears a node or link. The component never assigns
|
|
161
|
+
* `selectedNodeIds`/`selectedLinkIds` itself -- controlled, mirroring `lyra-heatmap.selectedCell`.
|
|
162
|
+
* @event lyra-community-click - A hull was activated. `detail: { id }`.
|
|
86
163
|
* @csspart base - The graph wrapper.
|
|
87
164
|
* @csspart svg - The graph SVG.
|
|
88
165
|
* @csspart node - A graph node.
|
|
89
166
|
* @csspart link - A graph link.
|
|
90
167
|
* @csspart arrowhead - The marker used by directed graph links.
|
|
91
168
|
* @csspart label - A node label.
|
|
169
|
+
* @csspart link-label - A drawn edge label (only rendered when `showEdgeLabels` is set).
|
|
170
|
+
* @csspart expand-indicator - The "+" badge rendered on a node with `expandable: true`.
|
|
171
|
+
* @csspart focus-halo - The persistent ring tracking `focusId`'s node.
|
|
172
|
+
* @csspart hull - A community hull (behind links/nodes; role="button").
|
|
173
|
+
* @csspart community-label - A hull's label text.
|
|
92
174
|
* @csspart live-region - The current graph item announcement.
|
|
93
175
|
* @csspart data-list - A visually hidden list alternative for graph data.
|
|
94
176
|
* @csspart empty - The empty-state message, shown when `nodes` is empty.
|
|
177
|
+
* @csspart canvas - The single canvas surface (`renderer="canvas"` only).
|
|
178
|
+
* @csspart tooltip - The hover tooltip (`renderer="canvas"` only; the SVG `<title>` replacement).
|
|
179
|
+
* @csspart cursor-items - The container of offscreen keyboard-roving items (`renderer="canvas"` only).
|
|
180
|
+
* @csspart cursor-item - An offscreen keyboard-roving item (`renderer="canvas"`'s a11y virtual cursor).
|
|
95
181
|
* @cssprop [--lyra-node-fill=var(--lyra-color-brand)] - Default node fill, overridden per-node by `GraphNode.color`.
|
|
96
182
|
* @cssprop [--lyra-link-color=var(--lyra-color-border)] - Default link stroke, overridden per-link by a link's own `color`.
|
|
183
|
+
* @cssprop [--lyra-graph-cat-1..8] - Ordered categorical fallback palette for a typed node with no
|
|
184
|
+
* `GraphNodeType.color`, assigned by the type's index in `nodeTypes` (wraps every 8 entries).
|
|
185
|
+
* Declared centrally in `tokens.styles.ts` so `<lyra-graph>` and any future `<lyra-graph-legend>`-
|
|
186
|
+
* style component resolve the identical default.
|
|
187
|
+
* @cssprop [--lyra-graph-edge-label-halo=var(--lyra-color-surface)] - Legibility halo (`stroke`)
|
|
188
|
+
* behind a drawn edge label, painted under the fill via `paint-order: stroke`.
|
|
189
|
+
* @cssprop [--lyra-graph-focus-halo-color=var(--lyra-color-brand)] - `focus-halo` stroke color.
|
|
190
|
+
* @cssprop [--lyra-graph-selected-color=var(--lyra-color-success)] - Selected node/link stroke.
|
|
191
|
+
* @cssprop [--lyra-graph-hull-fill=var(--lyra-color-brand)] - Hull fill/stroke color.
|
|
192
|
+
* @cssprop [--lyra-graph-hull-opacity=0.12] - Hull element opacity (composites fill+stroke as one
|
|
193
|
+
* group, avoiding a double-opacity seam at the fill/stroke boundary).
|
|
97
194
|
*/
|
|
98
195
|
export class LyraGraph extends LyraElement {
|
|
99
196
|
constructor() {
|
|
100
197
|
super(...arguments);
|
|
101
198
|
this.nodes = [];
|
|
102
199
|
this.links = [];
|
|
200
|
+
/** Declares each `GraphNode.type` value's legend label, fill color, and shape. A typed node with
|
|
201
|
+
* no matching entry here renders as untyped (default circle, token fill) but still participates
|
|
202
|
+
* in `hiddenTypes` filtering by its raw `type` string. */
|
|
203
|
+
this.nodeTypes = [];
|
|
204
|
+
/** Hides every node whose raw `type` value is listed here (no matching `nodeTypes` entry
|
|
205
|
+
* required), plus every link incident to a hidden node -- removed from the render, the
|
|
206
|
+
* simulation input, the keyboard roving ring, the sr-only data list, and the accessible
|
|
207
|
+
* diagram counts, as if absent. Positions round-trip via `lastPositionById`: toggling a type
|
|
208
|
+
* off and back on restores each node where it was. */
|
|
209
|
+
this.hiddenTypes = [];
|
|
210
|
+
/** Renders one translucent hull per entry, behind links/nodes. Membership is the union of
|
|
211
|
+
* `memberIds` and every node whose `communityId` matches this entry's `id`. */
|
|
212
|
+
this.communities = [];
|
|
213
|
+
/** `'force'` (default) runs the existing d3-force simulation, untouched. `'layered'` computes a
|
|
214
|
+
* deterministic Sugiyama-lite layout (`src/internal/layered-layout.ts`, a shared,
|
|
215
|
+
* dependency-free util suitable for any future layered-diagram consumer) instead -- no settle
|
|
216
|
+
* animation, node drag disabled (dragging would fight a computed layout), `chargeStrength` a
|
|
217
|
+
* documented no-op, `linkDistance` retunes the layer gap. Switching at runtime repositions
|
|
218
|
+
* without a tween. */
|
|
219
|
+
this.layout = 'force';
|
|
220
|
+
/** `'svg'` (default, unchanged) renders the existing per-node/per-link DOM. `'canvas'` swaps to
|
|
221
|
+
* a single `<canvas part="canvas">` -- the scale path (an honest ceiling for `'svg'`: dozens to
|
|
222
|
+
* low hundreds of nodes; `'canvas'` targets roughly 5,000 nodes / 10,000 links). Feature-reduced
|
|
223
|
+
* by design: no `::part(node)`/`::part(link)` styling (pixels, not elements -- theme via
|
|
224
|
+
* cssprops), no SVG `<title>`, a drawn focus ring instead of a CSS one. All events/methods/
|
|
225
|
+
* props otherwise behave identically across renderers. Runtime changes tear down and rebuild
|
|
226
|
+
* the surface; positions survive via `prevById`/`lastPositionById`. */
|
|
227
|
+
this.renderer = 'svg';
|
|
103
228
|
this.width = 800;
|
|
104
229
|
this.height = 600;
|
|
105
230
|
this.chargeStrength = -300;
|
|
@@ -108,12 +233,42 @@ export class LyraGraph extends LyraElement {
|
|
|
108
233
|
this.maxZoom = 8;
|
|
109
234
|
/** Accessible name forwarded from the host to the semantic graph SVG. */
|
|
110
235
|
this.accessibleLabel = null;
|
|
236
|
+
/** Draws each resolved (non-dangling) link's `label` as visible SVG text at the segment
|
|
237
|
+
* midpoint. Off by default — `GraphLink.label` stays spoken/tooltip-only, matching today's
|
|
238
|
+
* behavior, unless this is set. */
|
|
239
|
+
this.showEdgeLabels = false;
|
|
240
|
+
/** Below this zoom scale, every drawn edge label is hidden (a `data-edge-labels-hidden`
|
|
241
|
+
* attribute toggled on the zoomed `<g>`, no Lit re-render). Ignored when `showEdgeLabels` is
|
|
242
|
+
* false. */
|
|
243
|
+
this.edgeLabelMinZoom = 0.6;
|
|
244
|
+
/** Declaratively centers the camera on this node id once, the first time it resolves (on mount
|
|
245
|
+
* or when the id first appears in `nodes`) -- does not re-center on later mutations, so it
|
|
246
|
+
* can't fight a user's panning on a streaming graph. Renders a persistent halo
|
|
247
|
+
* (`part="focus-halo"`) around the node while set. See `focusNode()` for the imperative twin. */
|
|
248
|
+
this.focusId = null;
|
|
249
|
+
/** `'none'` (default) preserves today's behavior exactly -- no `aria-pressed`/`data-selected`,
|
|
250
|
+
* no `lyra-selection-change`. Controlled, mirroring `lyra-heatmap.selectedCell`: the component
|
|
251
|
+
* never mutates `selectedNodeIds`/`selectedLinkIds` itself, only emits intent; the host assigns
|
|
252
|
+
* them back. */
|
|
253
|
+
this.selectionMode = 'none';
|
|
254
|
+
this.selectedNodeIds = [];
|
|
255
|
+
this.selectedLinkIds = [];
|
|
111
256
|
this.arrowMarkerId = nextId('graph-arrow');
|
|
112
257
|
/** True until the lazy-loaded d3 peer dependencies have settled (success or failure). */
|
|
113
258
|
this.loading = true;
|
|
114
259
|
this.simNodes = [];
|
|
115
260
|
this.simLinks = [];
|
|
116
261
|
this.danglingLinks = [];
|
|
262
|
+
/** Every node's last-known settled position, keyed by id, independent of current visibility --
|
|
263
|
+
* consulted by `rebuildSimulation()` (after the existing carried-over-position map) so a
|
|
264
|
+
* `hiddenTypes` toggle restores a node where it was instead of re-randomizing it. Pruned to ids
|
|
265
|
+
* present in `this.nodes` (not just currently-visible ones) on every rebuild. */
|
|
266
|
+
this.lastPositionById = new Map();
|
|
267
|
+
/** The `hiddenNodeCount` computed by the most recent `rebuildSimulation()` -- lets that method
|
|
268
|
+
* tell "nothing has ever been hidden" (never touch `graphLiveText`, so a consumer that never
|
|
269
|
+
* sets `hiddenTypes` keeps today's exact live-region output) apart from "a hide was just
|
|
270
|
+
* cleared" (still announce the resulting "0 of N" count). */
|
|
271
|
+
this.lastHiddenNodeCount = 0;
|
|
117
272
|
/** One roving tab stop across all nodes and links; nodes are the initial entry order. */
|
|
118
273
|
this.activeGraphItem = 0;
|
|
119
274
|
this.graphLiveText = '';
|
|
@@ -126,11 +281,165 @@ export class LyraGraph extends LyraElement {
|
|
|
126
281
|
* simNodes/simLinks properties (see rebuildSimulation()'s doc comment). */
|
|
127
282
|
this.nodeEls = [];
|
|
128
283
|
this.nodeLabelEls = [];
|
|
284
|
+
this.expandIndicatorEls = [];
|
|
285
|
+
/** Tracks the index/time of the last Enter/Space activation, for double-Enter expand detection
|
|
286
|
+
* (mirroring native dblclick semantics for keyboard users). */
|
|
287
|
+
this.lastKeyActivateIndex = null;
|
|
288
|
+
this.lastKeyActivateTime = 0;
|
|
289
|
+
/** The last `focusId` value `focusNode()` was auto-invoked for by `updated()`'s declarative
|
|
290
|
+
* centering branch -- guards against re-centering on every update while `focusId` stays set
|
|
291
|
+
* (see the `focusId` property doc for why it only ever centers once per value). Reset to `null`
|
|
292
|
+
* whenever `focusId` itself is cleared, so the same id can center again later. */
|
|
293
|
+
this.lastAppliedFocusId = null;
|
|
294
|
+
this.communityHullEls = [];
|
|
295
|
+
this.communityLabelEls = [];
|
|
296
|
+
this.pickDirty = true;
|
|
297
|
+
this.canvasCamera = { k: 1, x: 0, y: 0 };
|
|
298
|
+
/** Flat, index-aligned list matching `drawPickingScene()`'s own hulls-then-links-then-nodes pick
|
|
299
|
+
* order -- rebuilt by `redrawPickCanvas()` alongside the pick canvas itself, so a pick color's
|
|
300
|
+
* decoded index always maps back to the exact item it was drawn for. */
|
|
301
|
+
this.pickItems = [];
|
|
302
|
+
/** Whether `canvasScene` was built with edge labels included -- the zoom gate makes the scene
|
|
303
|
+
* camera-dependent at exactly two thresholds (`edgeLabelMinZoom`, `CANVAS_NODE_LABEL_MIN_ZOOM`),
|
|
304
|
+
* so a camera-only draw that crosses either must rebuild instead of reusing the cache. */
|
|
305
|
+
this.canvasSceneHasEdgeLabels = false;
|
|
306
|
+
/** True for a camera tween's whole duration (set before its first frame, cleared on
|
|
307
|
+
* resolution) -- `isPanning` alone doesn't cover this: `applyZoomTransform()`'s per-frame
|
|
308
|
+
* `zoomBehavior.transform()` call on a non-transition selection fires d3-zoom's
|
|
309
|
+
* start/zoom/end synchronously within that single call, so `isPanning` flips true-then-false
|
|
310
|
+
* within one frame rather than staying true for the tween's real duration the way an actual
|
|
311
|
+
* user gesture does. */
|
|
312
|
+
this.isCameraTweening = false;
|
|
129
313
|
this.linkEls = [];
|
|
314
|
+
this.linkLabelEls = [];
|
|
315
|
+
/** Per-simLink-index flip cache for the length declutter gate -- `onTick()` only writes
|
|
316
|
+
* `visibility` when the boolean actually changes, not every tick. */
|
|
317
|
+
this.linkLabelHiddenByLength = [];
|
|
318
|
+
this.edgeLabelWidthCache = new Map();
|
|
130
319
|
/** Dangling-stub `<line>`s, index-aligned with `danglingLinks` -- cached separately from
|
|
131
320
|
* `linkEls` (real, simulated links only) so onTick() can write their positions too; see
|
|
132
321
|
* onTick()'s own comment for why a stub needs this at all. */
|
|
133
322
|
this.danglingLinkEls = [];
|
|
323
|
+
/** Writing a transform on a plain (non-transition) selection makes d3-zoom fire its own
|
|
324
|
+
* start/zoom/end sequence synchronously, in this same call -- `isApplyingZoomTransform` lets
|
|
325
|
+
* the zoom `'start'` handler tell that self-triggered echo apart from a genuine external
|
|
326
|
+
* gesture, so a camera tween's own per-frame write doesn't cancel itself. */
|
|
327
|
+
this.isApplyingZoomTransform = false;
|
|
328
|
+
this.onCanvasDprChange = () => {
|
|
329
|
+
this.watchCanvasDpr();
|
|
330
|
+
this.markCanvasDirty();
|
|
331
|
+
};
|
|
332
|
+
this.onCanvasPointerDown = (e) => {
|
|
333
|
+
if (e.button !== 0)
|
|
334
|
+
return; // primary button only, matching native `click`'s own semantics
|
|
335
|
+
this.canvasPointerDownAt = { x: e.clientX, y: e.clientY };
|
|
336
|
+
if (this.layout === 'layered')
|
|
337
|
+
return; // drag disabled in layered mode, same as svg mode
|
|
338
|
+
const hit = this.hitTest(e.clientX, e.clientY);
|
|
339
|
+
if (hit?.kind === 'node') {
|
|
340
|
+
this.canvasDragNode = hit.node;
|
|
341
|
+
this.canvasPointerId = e.pointerId;
|
|
342
|
+
this.canvasEl.setPointerCapture(e.pointerId);
|
|
343
|
+
hit.node.fx = hit.node.x;
|
|
344
|
+
hit.node.fy = hit.node.y;
|
|
345
|
+
this.simulation?.alphaTarget(0.3).restart();
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
this.onCanvasPointerMove = (e) => {
|
|
349
|
+
if (this.canvasDragNode && this.canvasPointerId === e.pointerId) {
|
|
350
|
+
const rect = this.canvasEl.getBoundingClientRect();
|
|
351
|
+
this.canvasDragNode.fx = (e.clientX - rect.left - this.canvasCamera.x) / this.canvasCamera.k;
|
|
352
|
+
this.canvasDragNode.fy = (e.clientY - rect.top - this.canvasCamera.y) / this.canvasCamera.k;
|
|
353
|
+
this.markCanvasDirty();
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
// Coalesce hover hit-testing to one per animation frame (see pendingHover's doc) -- only the
|
|
357
|
+
// latest position matters, and running the readback-per-pointermove would multiply the cost
|
|
358
|
+
// by however many moves the browser delivers between paints.
|
|
359
|
+
this.pendingHover = { x: e.clientX, y: e.clientY };
|
|
360
|
+
if (this.hoverRafId != null)
|
|
361
|
+
return;
|
|
362
|
+
this.hoverRafId = requestAnimationFrame(() => {
|
|
363
|
+
this.hoverRafId = undefined;
|
|
364
|
+
const pending = this.pendingHover;
|
|
365
|
+
this.pendingHover = undefined;
|
|
366
|
+
if (!pending)
|
|
367
|
+
return;
|
|
368
|
+
// While the force simulation is still ticking, every tick invalidates the pick canvas, so
|
|
369
|
+
// resolving hover here would re-render the full offscreen picking scene once per frame on
|
|
370
|
+
// top of the per-tick visible redraw -- and the result would be stale a frame later anyway,
|
|
371
|
+
// since positions are still moving. Defer hover resolution until the layout settles; the
|
|
372
|
+
// next pointermove after that picks it up.
|
|
373
|
+
if (this.pickDirty && this.simulationIsTicking())
|
|
374
|
+
return;
|
|
375
|
+
const hit = this.hitTest(pending.x, pending.y);
|
|
376
|
+
this.updateCanvasTooltip(hit, pending.x, pending.y);
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
this.onCanvasPointerUp = (e) => {
|
|
380
|
+
// Starting a drag on a node (onCanvasPointerDown) and ending it here without ever crossing the
|
|
381
|
+
// move-distance threshold below is exactly a plain click -- release the drag state first, but
|
|
382
|
+
// keep going into the same click-vs-drag distance check every pointerup goes through, instead
|
|
383
|
+
// of returning early and silently swallowing the click. This mirrors svg mode, where a plain
|
|
384
|
+
// click on a node fires both d3-drag's own start/end (a no-op, since fx/fy never actually
|
|
385
|
+
// moved) and the browser's native `click` event -- the two aren't mutually exclusive there
|
|
386
|
+
// either.
|
|
387
|
+
if (this.canvasDragNode && this.canvasPointerId === e.pointerId) {
|
|
388
|
+
this.simulation?.alphaTarget(0);
|
|
389
|
+
this.canvasDragNode.fx = null;
|
|
390
|
+
this.canvasDragNode.fy = null;
|
|
391
|
+
this.canvasDragNode = undefined;
|
|
392
|
+
this.canvasPointerId = undefined;
|
|
393
|
+
this.markCanvasDirty();
|
|
394
|
+
}
|
|
395
|
+
const down = this.canvasPointerDownAt;
|
|
396
|
+
this.canvasPointerDownAt = undefined;
|
|
397
|
+
if (!down)
|
|
398
|
+
return;
|
|
399
|
+
if (Math.hypot(e.clientX - down.x, e.clientY - down.y) > 5)
|
|
400
|
+
return; // a pan/drag gesture, not a click
|
|
401
|
+
const hit = this.hitTest(e.clientX, e.clientY);
|
|
402
|
+
if (!hit) {
|
|
403
|
+
this.clearSelection();
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (hit.kind === 'node')
|
|
407
|
+
this.onNodeClick(hit.node, e);
|
|
408
|
+
else if (hit.kind === 'link')
|
|
409
|
+
this.onLinkClick(hit.link, e);
|
|
410
|
+
else
|
|
411
|
+
this.onCommunityClick(hit.entry.community);
|
|
412
|
+
};
|
|
413
|
+
this.onCanvasPointerLeave = () => {
|
|
414
|
+
// Drop any coalesced hover still waiting on its frame -- letting it run after the pointer
|
|
415
|
+
// already left would re-show the tooltip this handler is about to hide.
|
|
416
|
+
this.pendingHover = undefined;
|
|
417
|
+
if (this.hoverRafId != null) {
|
|
418
|
+
cancelAnimationFrame(this.hoverRafId);
|
|
419
|
+
this.hoverRafId = undefined;
|
|
420
|
+
}
|
|
421
|
+
this.updateCanvasTooltip(undefined, 0, 0);
|
|
422
|
+
};
|
|
423
|
+
this.onCanvasDblClick = (e) => {
|
|
424
|
+
const hit = this.hitTest(e.clientX, e.clientY);
|
|
425
|
+
const node = hit?.kind === 'node' ? hit.node : this.nodeAtCanvasPoint(e.clientX, e.clientY);
|
|
426
|
+
if (!node)
|
|
427
|
+
return; // background dblclick still reaches d3-zoom's own zoom-in, same as svg mode
|
|
428
|
+
// d3-zoom's own default double-click-to-zoom-in handler is bound to this identical <canvas>
|
|
429
|
+
// element (not an ancestor, so plain stopPropagation() -- which only blocks *bubbling*, not a
|
|
430
|
+
// sibling listener on the very same target -- would not suppress it). Matches svg mode's own
|
|
431
|
+
// onNodeDblClick(), which stops the equivalent bubble-phase echo on the svg one level up.
|
|
432
|
+
e.stopImmediatePropagation();
|
|
433
|
+
this.emit('lyra-node-expand', { id: node.id });
|
|
434
|
+
};
|
|
435
|
+
/** Suppresses hover events/`data-hovered` while a node drag is in progress (tracked from the
|
|
436
|
+
* existing d3-drag `.on('start')`/`.on('end')` handlers in `applyInteractions()`) — a drag
|
|
437
|
+
* crossing over other nodes/links would otherwise spam enter/leave pairs unrelated to genuine
|
|
438
|
+
* pointer hovering. */
|
|
439
|
+
this.isDragging = false;
|
|
440
|
+
/** Same purpose as `isDragging`, for d3-zoom pan/zoom gestures (tracked from `applyInteractions()`'s
|
|
441
|
+
* zoom `.on('start')`/`.on('end')` handlers, added by this same change). */
|
|
442
|
+
this.isPanning = false;
|
|
134
443
|
}
|
|
135
444
|
static { this.styles = [LyraElement.styles, styles, srOnly]; }
|
|
136
445
|
connectedCallback() {
|
|
@@ -146,6 +455,16 @@ export class LyraGraph extends LyraElement {
|
|
|
146
455
|
// the existing simulation in place instead.
|
|
147
456
|
if (this.d3) {
|
|
148
457
|
this.simulation?.restart();
|
|
458
|
+
// renderer="canvas" mode's own resize/DPR watchers are torn down by disconnectedCallback()
|
|
459
|
+
// below on every disconnect (including this reconnect) -- the <canvas> element itself
|
|
460
|
+
// survived the reparent along with the rest of this shadow tree (canvasEl === zoomedEl still
|
|
461
|
+
// holds), so re-arm them in place instead of waiting for a property-driven update that a bare
|
|
462
|
+
// reparent never triggers.
|
|
463
|
+
if (this.renderer === 'canvas' && this.canvasEl && this.canvasEl === this.zoomedEl) {
|
|
464
|
+
this.watchCanvasResize();
|
|
465
|
+
this.watchCanvasDpr();
|
|
466
|
+
this.markCanvasDirty();
|
|
467
|
+
}
|
|
149
468
|
return;
|
|
150
469
|
}
|
|
151
470
|
void loadD3().then((mods) => {
|
|
@@ -162,6 +481,21 @@ export class LyraGraph extends LyraElement {
|
|
|
162
481
|
disconnectedCallback() {
|
|
163
482
|
super.disconnectedCallback();
|
|
164
483
|
this.simulation?.stop();
|
|
484
|
+
// An in-flight focusNode()/fit() tween would otherwise keep scheduling frames and writing
|
|
485
|
+
// zoom transforms against the detached tree -- cancel it (which also settles the caller's
|
|
486
|
+
// pending Promise with `false` instead of leaving it hanging forever).
|
|
487
|
+
this.cancelCameraTween();
|
|
488
|
+
this.canvasResizeObserver?.disconnect();
|
|
489
|
+
this.canvasDprQuery?.removeEventListener('change', this.onCanvasDprChange);
|
|
490
|
+
if (this.canvasDrawRafId != null) {
|
|
491
|
+
cancelAnimationFrame(this.canvasDrawRafId);
|
|
492
|
+
this.canvasDrawRafId = undefined;
|
|
493
|
+
}
|
|
494
|
+
if (this.hoverRafId != null) {
|
|
495
|
+
cancelAnimationFrame(this.hoverRafId);
|
|
496
|
+
this.hoverRafId = undefined;
|
|
497
|
+
}
|
|
498
|
+
this.pendingHover = undefined;
|
|
165
499
|
}
|
|
166
500
|
/**
|
|
167
501
|
* A caller-supplied `radius` is clamped to [MIN_RADIUS, MAX_RADIUS] (and a
|
|
@@ -174,6 +508,630 @@ export class LyraGraph extends LyraElement {
|
|
|
174
508
|
const r = n.radius ?? (MIN_RADIUS + MAX_RADIUS) / 2;
|
|
175
509
|
return Number.isFinite(r) ? Math.min(MAX_RADIUS, Math.max(MIN_RADIUS, r)) : (MIN_RADIUS + MAX_RADIUS) / 2;
|
|
176
510
|
}
|
|
511
|
+
/** `width`/`height` normalized to a finite, positive viewport size — an invalid attribute value
|
|
512
|
+
* would otherwise flow straight into `forceCenter`, the SVG `viewBox`, and the canvas backing
|
|
513
|
+
* store's `width`/`height`, producing `NaN` geometry/transforms that silently render nothing
|
|
514
|
+
* instead of erroring. */
|
|
515
|
+
get safeWidth() {
|
|
516
|
+
return finiteRange(this.width, 800, 1);
|
|
517
|
+
}
|
|
518
|
+
get safeHeight() {
|
|
519
|
+
return finiteRange(this.height, 600, 1);
|
|
520
|
+
}
|
|
521
|
+
/** `minZoom`/`maxZoom` normalized to finite, positive scale bounds before ever reaching
|
|
522
|
+
* d3-zoom's `scaleExtent()` or a camera-clamp `Math.min`/`Math.max` — a non-finite bound would
|
|
523
|
+
* otherwise poison every subsequent zoom/pan computation with `NaN`. */
|
|
524
|
+
get safeMinZoom() {
|
|
525
|
+
return finiteRange(this.minZoom, 0.1, 0.001, 1000);
|
|
526
|
+
}
|
|
527
|
+
get safeMaxZoom() {
|
|
528
|
+
return finiteRange(this.maxZoom, 8, 0.001, 1000);
|
|
529
|
+
}
|
|
530
|
+
/** `edgeLabelMinZoom` is compared directly against the live camera scale (same domain as
|
|
531
|
+
* `minZoom`/`maxZoom`), so it's normalized with the same bounds -- a non-finite value would
|
|
532
|
+
* otherwise make every `>=`/`<` comparison against it silently `false`/`true` forever. */
|
|
533
|
+
get safeEdgeLabelMinZoom() {
|
|
534
|
+
return finiteRange(this.edgeLabelMinZoom, 0.6, 0.001, 1000);
|
|
535
|
+
}
|
|
536
|
+
/** `seed`, normalized to a finite integer when set -- `undefined` (unseeded/random) is left
|
|
537
|
+
* untouched, since it's a meaningful third state, not a missing number. Without this,
|
|
538
|
+
* `hashNodeSeed`/`mulberry32`'s `>>> 0` coercion would silently fold `NaN`/`Infinity` to `0`
|
|
539
|
+
* instead of normalizing an out-of-range attribute value the way every other numeric prop here
|
|
540
|
+
* does. */
|
|
541
|
+
get safeSeed() {
|
|
542
|
+
return this.seed == null ? undefined : finiteInteger(this.seed, 0);
|
|
543
|
+
}
|
|
544
|
+
/** `chargeStrength` is a signed d3-force strength (negative = repulsion, positive = attraction)
|
|
545
|
+
* — only guarded for finiteness, not clamped to a range, since either sign is a legitimate
|
|
546
|
+
* value. */
|
|
547
|
+
get safeChargeStrength() {
|
|
548
|
+
return finiteNumber(this.chargeStrength, -300);
|
|
549
|
+
}
|
|
550
|
+
/** `linkDistance` normalized to a finite, non-negative pixel distance — feeds `forceLink()`'s
|
|
551
|
+
* `distance()`, the layered layout's `gapY`, and the neighbor-jitter spawn radius, none of
|
|
552
|
+
* which have a sane meaning for a negative/non-finite value. */
|
|
553
|
+
get safeLinkDistance() {
|
|
554
|
+
return finiteRange(this.linkDistance, 100, 0);
|
|
555
|
+
}
|
|
556
|
+
resolveNodeType(node) {
|
|
557
|
+
return node.type != null ? this.nodeTypes.find((t) => t.id === node.type) : undefined;
|
|
558
|
+
}
|
|
559
|
+
nodeShape(node) {
|
|
560
|
+
return this.resolveNodeType(node)?.shape ?? 'circle';
|
|
561
|
+
}
|
|
562
|
+
/** Resolution precedence: `node.color` (existing, most specific) > matched `GraphNodeType.color`
|
|
563
|
+
* > the ordered categorical fallback palette by the type's index in `nodeTypes` > (returns
|
|
564
|
+
* `undefined`, letting the untyped `--lyra-node-fill` token default apply). Both data-driven
|
|
565
|
+
* color sources pass the existing `sanitizeNodeColor()`. */
|
|
566
|
+
nodeFill(node) {
|
|
567
|
+
const ownColor = sanitizeNodeColor(node.color);
|
|
568
|
+
if (ownColor)
|
|
569
|
+
return ownColor;
|
|
570
|
+
const type = this.resolveNodeType(node);
|
|
571
|
+
if (!type)
|
|
572
|
+
return undefined;
|
|
573
|
+
const typeColor = sanitizeNodeColor(type.color);
|
|
574
|
+
if (typeColor)
|
|
575
|
+
return typeColor;
|
|
576
|
+
return categoricalPaletteColor(this.nodeTypes.indexOf(type));
|
|
577
|
+
}
|
|
578
|
+
/** `this.nodes` filtered down to the ids `hiddenTypes` doesn't hide -- an untyped node (`type ==
|
|
579
|
+
* null`) is never hidden, regardless of `hiddenTypes`' contents. */
|
|
580
|
+
visibleNodes() {
|
|
581
|
+
if (!this.hiddenTypes.length)
|
|
582
|
+
return this.nodes;
|
|
583
|
+
const hidden = new Set(this.hiddenTypes);
|
|
584
|
+
return this.nodes.filter((n) => n.type == null || !hidden.has(n.type));
|
|
585
|
+
}
|
|
586
|
+
/** Resolves `this.links` against an already-built `byId` node map: a link whose source isn't in
|
|
587
|
+
* `byId` is dropped (hidden source, or a genuinely missing one); a link whose target isn't in
|
|
588
|
+
* `byId` either stubs as a dangling link (target id doesn't exist in `this.nodes` at all) or is
|
|
589
|
+
* dropped (target exists but is hidden by `hiddenTypes`). Shared by both the force and layered
|
|
590
|
+
* layout paths in `rebuildSimulation()`. */
|
|
591
|
+
resolveLinksAgainst(byId) {
|
|
592
|
+
const nodeExists = new Set(this.nodes.map((n) => n.id));
|
|
593
|
+
const resolved = [];
|
|
594
|
+
const dangling = [];
|
|
595
|
+
for (const l of this.links) {
|
|
596
|
+
const source = byId.get(l.source);
|
|
597
|
+
if (!source)
|
|
598
|
+
continue;
|
|
599
|
+
const target = byId.get(l.target);
|
|
600
|
+
if (target) {
|
|
601
|
+
resolved.push({ ...l, source, target });
|
|
602
|
+
}
|
|
603
|
+
else if (!nodeExists.has(l.target)) {
|
|
604
|
+
dangling.push({ ...l, source, target: { id: l.target, x: source.x, y: source.y }, dangling: true });
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return { resolved, dangling };
|
|
608
|
+
}
|
|
609
|
+
/** A community's currently-visible members -- the union of `memberIds` and every currently
|
|
610
|
+
* simulated node (already filtered by `hiddenTypes`) whose `communityId` matches. */
|
|
611
|
+
communityMembers(community) {
|
|
612
|
+
const idSet = new Set(community.memberIds);
|
|
613
|
+
return this.simNodes.filter((n) => idSet.has(n.id) || n.communityId === community.id);
|
|
614
|
+
}
|
|
615
|
+
/** `communities` narrowed to entries with at least one currently-visible member -- a community
|
|
616
|
+
* whose members are all hidden by `hiddenTypes` (or that starts out empty) draws no hull and
|
|
617
|
+
* doesn't occupy a roving-ring slot. */
|
|
618
|
+
visibleCommunities() {
|
|
619
|
+
if (!this.visibleCommunitiesCache) {
|
|
620
|
+
this.visibleCommunitiesCache = this.communities
|
|
621
|
+
.map((community) => ({ community, members: this.communityMembers(community) }))
|
|
622
|
+
.filter((entry) => entry.members.length > 0);
|
|
623
|
+
}
|
|
624
|
+
return this.visibleCommunitiesCache;
|
|
625
|
+
}
|
|
626
|
+
communityHull(members) {
|
|
627
|
+
return convexHull(members.map((n) => ({ x: n.x ?? 0, y: n.y ?? 0 })));
|
|
628
|
+
}
|
|
629
|
+
onCommunityClick(community) {
|
|
630
|
+
this.emit('lyra-community-click', { id: community.id });
|
|
631
|
+
}
|
|
632
|
+
cameraTransitionMs() {
|
|
633
|
+
const parsed = parseFloat(getComputedStyle(this).getPropertyValue('--lyra-transition-base'));
|
|
634
|
+
return Number.isFinite(parsed) ? parsed : 180;
|
|
635
|
+
}
|
|
636
|
+
cancelCameraTween() {
|
|
637
|
+
if (this.cameraTweenId != null) {
|
|
638
|
+
cancelAnimationFrame(this.cameraTweenId);
|
|
639
|
+
this.cameraTweenId = undefined;
|
|
640
|
+
}
|
|
641
|
+
this.isCameraTweening = false;
|
|
642
|
+
const resolve = this.cameraTweenResolve;
|
|
643
|
+
if (resolve) {
|
|
644
|
+
this.cameraTweenResolve = undefined;
|
|
645
|
+
resolve(false);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
applyZoomTransform(transform) {
|
|
649
|
+
if (!this.d3 || !this.zoomedEl || !this.zoomBehavior)
|
|
650
|
+
return;
|
|
651
|
+
this.isApplyingZoomTransform = true;
|
|
652
|
+
try {
|
|
653
|
+
this.zoomBehavior.transform(this.d3.select(this.zoomedEl), transform);
|
|
654
|
+
}
|
|
655
|
+
finally {
|
|
656
|
+
this.isApplyingZoomTransform = false;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
/** Animates from the zoom behavior's current transform toward `computeTarget()`'s result via a
|
|
660
|
+
* rAF tween that calls `zoomBehavior.transform()` every frame -- keeps d3-zoom's own internal
|
|
661
|
+
* state consistent (so the next user pan doesn't jump), unlike writing the `<g>` transform
|
|
662
|
+
* attribute directly. `computeTarget` is re-invoked on every single frame (not read once
|
|
663
|
+
* up-front) so the tween keeps tracking a still-settling force simulation's live node positions
|
|
664
|
+
* instead of tweening toward a stale snapshot from the moment the call was made --
|
|
665
|
+
* `focusNode()`/`fit()` are just as likely to run while the graph is still animating its initial
|
|
666
|
+
* layout as after it's settled. `prefers-reduced-motion` jumps straight to one write of the
|
|
667
|
+
* then-current target. A concurrent call cancels the previous tween -- resolves `true` on
|
|
668
|
+
* genuine arrival, `false` if superseded or interrupted by a user gesture before completing. */
|
|
669
|
+
tweenCamera(computeTarget) {
|
|
670
|
+
return new Promise((resolve) => {
|
|
671
|
+
if (!this.d3 || !this.zoomedEl || !this.zoomBehavior) {
|
|
672
|
+
resolve(false);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
this.cancelCameraTween();
|
|
676
|
+
this.cameraTweenResolve = resolve;
|
|
677
|
+
this.isCameraTweening = true;
|
|
678
|
+
if (prefersReducedMotion()) {
|
|
679
|
+
this.applyZoomTransform(computeTarget());
|
|
680
|
+
this.isCameraTweening = false;
|
|
681
|
+
this.cameraTweenResolve = undefined;
|
|
682
|
+
resolve(true);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
const current = this.d3.zoomTransform(this.zoomedEl);
|
|
686
|
+
const duration = this.cameraTransitionMs();
|
|
687
|
+
const start = performance.now();
|
|
688
|
+
const startK = current.k;
|
|
689
|
+
const startX = current.x;
|
|
690
|
+
const startY = current.y;
|
|
691
|
+
const step = (now) => {
|
|
692
|
+
const t = duration > 0 ? Math.min(1, (now - start) / duration) : 1;
|
|
693
|
+
const target = computeTarget();
|
|
694
|
+
const targetK = target.k;
|
|
695
|
+
const targetX = target.x;
|
|
696
|
+
const targetY = target.y;
|
|
697
|
+
this.applyZoomTransform(this.d3.zoomIdentity
|
|
698
|
+
.translate(startX + (targetX - startX) * t, startY + (targetY - startY) * t)
|
|
699
|
+
.scale(startK + (targetK - startK) * t));
|
|
700
|
+
if (t < 1) {
|
|
701
|
+
this.cameraTweenId = requestAnimationFrame(step);
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
this.cameraTweenId = undefined;
|
|
705
|
+
this.isCameraTweening = false;
|
|
706
|
+
this.cameraTweenResolve = undefined;
|
|
707
|
+
resolve(true);
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
this.cameraTweenId = requestAnimationFrame(step);
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
/** Animates the camera so `id` centers in the viewport (the `width` x `height` viewBox), at
|
|
714
|
+
* `options.zoom` (clamped to `[minZoom, maxZoom]`) or the current scale when omitted. Resolves
|
|
715
|
+
* `true` on arrival; `false` for an id with no matching entry in `simNodes` -- there's nothing
|
|
716
|
+
* to center on. Announces `graphNodeFocused` through the existing live region. Does not move DOM
|
|
717
|
+
* focus -- this is a camera operation, not a roving-focus one. */
|
|
718
|
+
async focusNode(id, options) {
|
|
719
|
+
const node = this.simNodes.find((n) => n.id === id);
|
|
720
|
+
if (!node || !this.d3 || !this.zoomedEl || !this.zoomBehavior)
|
|
721
|
+
return false;
|
|
722
|
+
const current = this.d3.zoomTransform(this.zoomedEl);
|
|
723
|
+
const k = Math.min(this.safeMaxZoom, Math.max(this.safeMinZoom, options?.zoom ?? current.k));
|
|
724
|
+
const arrived = await this.tweenCamera(() => this.d3.zoomIdentity
|
|
725
|
+
.translate(this.safeWidth / 2 - k * (node.x ?? 0), this.safeHeight / 2 - k * (node.y ?? 0))
|
|
726
|
+
.scale(k));
|
|
727
|
+
if (arrived) {
|
|
728
|
+
this.graphLiveText = this.localize('graphNodeFocused', undefined, { label: this.nodeAccessibleText(node) });
|
|
729
|
+
}
|
|
730
|
+
return arrived;
|
|
731
|
+
}
|
|
732
|
+
/** Animates the camera to frame the bounding box of every currently visible node position (plus
|
|
733
|
+
* each node's own radius) at the largest scale that fits within `width` x `height` minus
|
|
734
|
+
* `padding` viewport-px on each side (clamped to `[minZoom, maxZoom]`). Silent -- no data
|
|
735
|
+
* changed, so no announcement. A no-op with no visible nodes. */
|
|
736
|
+
fit(options) {
|
|
737
|
+
if (!this.d3 || !this.zoomedEl || !this.zoomBehavior || !this.simNodes.length)
|
|
738
|
+
return;
|
|
739
|
+
const padding = options?.padding ?? 24;
|
|
740
|
+
void this.tweenCamera(() => {
|
|
741
|
+
let minX = Infinity;
|
|
742
|
+
let minY = Infinity;
|
|
743
|
+
let maxX = -Infinity;
|
|
744
|
+
let maxY = -Infinity;
|
|
745
|
+
for (const n of this.simNodes) {
|
|
746
|
+
const r = this.nodeRadius(n);
|
|
747
|
+
minX = Math.min(minX, (n.x ?? 0) - r);
|
|
748
|
+
maxX = Math.max(maxX, (n.x ?? 0) + r);
|
|
749
|
+
minY = Math.min(minY, (n.y ?? 0) - r);
|
|
750
|
+
maxY = Math.max(maxY, (n.y ?? 0) + r);
|
|
751
|
+
}
|
|
752
|
+
for (const entry of this.visibleCommunities()) {
|
|
753
|
+
for (const p of this.communityHull(entry.members)) {
|
|
754
|
+
minX = Math.min(minX, p.x - HULL_PADDING);
|
|
755
|
+
maxX = Math.max(maxX, p.x + HULL_PADDING);
|
|
756
|
+
minY = Math.min(minY, p.y - HULL_PADDING);
|
|
757
|
+
maxY = Math.max(maxY, p.y + HULL_PADDING);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
const boxW = Math.max(1, maxX - minX);
|
|
761
|
+
const boxH = Math.max(1, maxY - minY);
|
|
762
|
+
const availW = Math.max(1, this.safeWidth - padding * 2);
|
|
763
|
+
const availH = Math.max(1, this.safeHeight - padding * 2);
|
|
764
|
+
const k = Math.min(this.safeMaxZoom, Math.max(this.safeMinZoom, Math.min(availW / boxW, availH / boxH)));
|
|
765
|
+
const cx = (minX + maxX) / 2;
|
|
766
|
+
const cy = (minY + maxY) / 2;
|
|
767
|
+
return this.d3.zoomIdentity.translate(this.safeWidth / 2 - k * cx, this.safeHeight / 2 - k * cy).scale(k);
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
updateFocusHalo() {
|
|
771
|
+
if (!this.focusHaloEl)
|
|
772
|
+
return;
|
|
773
|
+
const node = this.focusId != null ? this.simNodes.find((n) => n.id === this.focusId) : undefined;
|
|
774
|
+
if (node) {
|
|
775
|
+
this.focusHaloEl.setAttribute('cx', String(node.x ?? 0));
|
|
776
|
+
this.focusHaloEl.setAttribute('cy', String(node.y ?? 0));
|
|
777
|
+
this.focusHaloEl.setAttribute('r', String(this.nodeRadius(node) + FOCUS_HALO_PADDING));
|
|
778
|
+
this.focusHaloEl.removeAttribute('hidden');
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
this.focusHaloEl.setAttribute('hidden', '');
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
// ---------------------------------------------------------------------------------------------
|
|
785
|
+
// renderer="canvas": surface setup, DPR/resize watching, scene building, and the static draw.
|
|
786
|
+
// ---------------------------------------------------------------------------------------------
|
|
787
|
+
setUpCanvasSurface() {
|
|
788
|
+
this.canvasCtx = this.canvasEl.getContext('2d') ?? undefined;
|
|
789
|
+
this.pickCanvas = document.createElement('canvas');
|
|
790
|
+
this.pickCtx = this.pickCanvas.getContext('2d', { willReadFrequently: true });
|
|
791
|
+
this.watchCanvasResize();
|
|
792
|
+
this.watchCanvasDpr();
|
|
793
|
+
this.canvasTooltipEl = this.renderRoot.querySelector('[part="tooltip"]') ?? undefined;
|
|
794
|
+
// bindCanvasPointer() (which owns onCanvasDblClick) is bound BEFORE bindCanvasZoom() -- both
|
|
795
|
+
// end up with a 'dblclick' listener on this same <canvas>, and d3-zoom's own default
|
|
796
|
+
// double-click-to-zoom-in handler calls stopImmediatePropagation() unconditionally (see
|
|
797
|
+
// onCanvasDblClick()'s own comment). Registering first means onCanvasDblClick() runs first and
|
|
798
|
+
// gets the chance to itself stop the event (only when it actually hit a node) before d3-zoom's
|
|
799
|
+
// handler would otherwise suppress it from ever being observed at all.
|
|
800
|
+
this.bindCanvasPointer();
|
|
801
|
+
this.bindCanvasZoom();
|
|
802
|
+
}
|
|
803
|
+
watchCanvasResize() {
|
|
804
|
+
// Re-arming replaces the observer instance -- disconnect the previous one first, or a
|
|
805
|
+
// canvas -> svg -> canvas renderer round trip leaves an orphaned observer still watching the
|
|
806
|
+
// host (disconnectedCallback only ever cleans up whichever instance is current).
|
|
807
|
+
this.canvasResizeObserver?.disconnect();
|
|
808
|
+
this.canvasResizeObserver = new ResizeObserver(() => this.markCanvasDirty());
|
|
809
|
+
this.canvasResizeObserver.observe(this);
|
|
810
|
+
}
|
|
811
|
+
watchCanvasDpr() {
|
|
812
|
+
// A MediaQueryList's `matches` is fixed at creation time, so crossing the DPR threshold it was
|
|
813
|
+
// built for means building a fresh one for the new ratio -- remove the previous instance's
|
|
814
|
+
// listener first, or it leaks (disconnectedCallback only ever cleans up whichever is current).
|
|
815
|
+
this.canvasDprQuery?.removeEventListener('change', this.onCanvasDprChange);
|
|
816
|
+
this.canvasDprQuery = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
817
|
+
this.canvasDprQuery.addEventListener('change', this.onCanvasDprChange);
|
|
818
|
+
}
|
|
819
|
+
markCanvasDirty() {
|
|
820
|
+
this.canvasScene = undefined;
|
|
821
|
+
this.pickDirty = true;
|
|
822
|
+
this.scheduleCanvasDraw();
|
|
823
|
+
}
|
|
824
|
+
/** The camera-only sibling of `markCanvasDirty()`: a pan/zoom moves the camera but leaves every
|
|
825
|
+
* world-space scene value (positions, colors, labels) untouched, so the cached `canvasScene`
|
|
826
|
+
* stays valid and only needs redrawing under the new transform. The pick canvas bakes the
|
|
827
|
+
* camera transform into its pixels, though, so it still needs a redraw before the next hit
|
|
828
|
+
* test. */
|
|
829
|
+
markCanvasCameraDirty() {
|
|
830
|
+
this.pickDirty = true;
|
|
831
|
+
this.scheduleCanvasDraw();
|
|
832
|
+
}
|
|
833
|
+
scheduleCanvasDraw() {
|
|
834
|
+
if (this.canvasDrawRafId != null)
|
|
835
|
+
return;
|
|
836
|
+
this.canvasDrawRafId = requestAnimationFrame(() => {
|
|
837
|
+
this.canvasDrawRafId = undefined;
|
|
838
|
+
this.drawCanvas();
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
/** Canvas 2D's `fillStyle`/`strokeStyle` don't accept a raw `var(--x)` string the way an inline
|
|
842
|
+
* SVG `style` attribute does -- resolves it to the actual cascaded color via `getComputedStyle`
|
|
843
|
+
* first (the same "canvas can't consume var() directly" resolution `<lyra-heatmap>` already
|
|
844
|
+
* uses for its own canvas-drawn tokens). `value` untouched when it isn't a bare `var(...)` ref
|
|
845
|
+
* (a literal `GraphNode.color`/`GraphLink.color` hex/rgb string already resolves fine as-is). */
|
|
846
|
+
resolveCssColorValue(value, cs) {
|
|
847
|
+
const match = value.match(/^var\((--[\w-]+)/);
|
|
848
|
+
if (!match)
|
|
849
|
+
return value;
|
|
850
|
+
return cs.getPropertyValue(match[1]).trim() || value;
|
|
851
|
+
}
|
|
852
|
+
buildCanvasScene(cs) {
|
|
853
|
+
const hullFillDefault = cs.getPropertyValue('--lyra-graph-hull-fill').trim() || cs.getPropertyValue('--lyra-color-brand').trim();
|
|
854
|
+
const hulls = this.visibleCommunities().map((entry) => ({
|
|
855
|
+
d: hullPathD(this.communityHull(entry.members)),
|
|
856
|
+
fill: sanitizeNodeColor(entry.community.color) ?? hullFillDefault,
|
|
857
|
+
}));
|
|
858
|
+
const linkColorDefault = cs.getPropertyValue('--lyra-link-color').trim() || cs.getPropertyValue('--lyra-color-border').trim();
|
|
859
|
+
const links = this.simLinks.map((l) => {
|
|
860
|
+
const coords = this.linkCoordinates(l);
|
|
861
|
+
const own = sanitizeNodeColor(l.color);
|
|
862
|
+
return {
|
|
863
|
+
x1: coords.x1,
|
|
864
|
+
y1: coords.y1,
|
|
865
|
+
x2: coords.x2,
|
|
866
|
+
y2: coords.y2,
|
|
867
|
+
color: own ? this.resolveCssColorValue(own, cs) : linkColorDefault,
|
|
868
|
+
width: l.width ?? 1.5,
|
|
869
|
+
dash: l.dash,
|
|
870
|
+
directed: l.directed,
|
|
871
|
+
selected: this.isSelected('link', this.linkKey(l)),
|
|
872
|
+
};
|
|
873
|
+
});
|
|
874
|
+
const edgeLabels = this.showEdgeLabels && this.canvasCamera.k >= this.safeEdgeLabelMinZoom
|
|
875
|
+
? this.simLinks
|
|
876
|
+
.filter((l) => l.label)
|
|
877
|
+
.map((l) => {
|
|
878
|
+
const pos = this.edgeLabelPosition(l);
|
|
879
|
+
const coords = this.linkCoordinates(l);
|
|
880
|
+
const edgeLength = Math.hypot(coords.x2 - coords.x1, coords.y2 - coords.y1);
|
|
881
|
+
const tooLong = this.edgeLabelWidth(l.label) > edgeLength * EDGE_LABEL_LENGTH_GATE_RATIO;
|
|
882
|
+
return { x: pos.x, y: pos.y, text: l.label, tooLong };
|
|
883
|
+
})
|
|
884
|
+
.filter((l) => !l.tooLong)
|
|
885
|
+
.map(({ x, y, text }) => ({ x, y, text }))
|
|
886
|
+
: [];
|
|
887
|
+
const nodeFillDefault = cs.getPropertyValue('--lyra-node-fill').trim() || cs.getPropertyValue('--lyra-color-brand').trim();
|
|
888
|
+
const nodes = this.simNodes.map((n) => {
|
|
889
|
+
const fill = this.nodeFill(n);
|
|
890
|
+
return {
|
|
891
|
+
x: n.x ?? 0,
|
|
892
|
+
y: n.y ?? 0,
|
|
893
|
+
r: this.nodeRadius(n),
|
|
894
|
+
shape: this.nodeShape(n),
|
|
895
|
+
fill: fill ? this.resolveCssColorValue(fill, cs) : nodeFillDefault,
|
|
896
|
+
selected: this.isSelected('node', n.id),
|
|
897
|
+
};
|
|
898
|
+
});
|
|
899
|
+
const nodeLabels = this.simNodes
|
|
900
|
+
.filter((n) => n.label)
|
|
901
|
+
.map((n) => ({ x: (n.x ?? 0) + this.nodeRadius(n) + 2, y: n.y ?? 0, text: n.label }));
|
|
902
|
+
const focusNode = this.focusId != null ? this.simNodes.find((n) => n.id === this.focusId) : undefined;
|
|
903
|
+
const activeNode = this.activeGraphItem >= 0 && this.activeGraphItem < this.simNodes.length
|
|
904
|
+
? this.simNodes[this.activeGraphItem]
|
|
905
|
+
: undefined;
|
|
906
|
+
return {
|
|
907
|
+
hulls,
|
|
908
|
+
links,
|
|
909
|
+
edgeLabels,
|
|
910
|
+
nodes,
|
|
911
|
+
nodeLabels,
|
|
912
|
+
focusHalo: focusNode
|
|
913
|
+
? { x: focusNode.x ?? 0, y: focusNode.y ?? 0, r: this.nodeRadius(focusNode) + FOCUS_HALO_PADDING }
|
|
914
|
+
: undefined,
|
|
915
|
+
keyboardFocusRing: activeNode
|
|
916
|
+
? { x: activeNode.x ?? 0, y: activeNode.y ?? 0, r: this.nodeRadius(activeNode) + 4 }
|
|
917
|
+
: undefined,
|
|
918
|
+
showNodeLabels: this.canvasCamera.k >= CANVAS_NODE_LABEL_MIN_ZOOM,
|
|
919
|
+
haloColor: cs.getPropertyValue('--lyra-graph-focus-halo-color').trim() || cs.getPropertyValue('--lyra-color-brand').trim(),
|
|
920
|
+
selectedColor: cs.getPropertyValue('--lyra-graph-selected-color').trim() || cs.getPropertyValue('--lyra-color-success').trim(),
|
|
921
|
+
labelColor: cs.getPropertyValue('--lyra-color-text').trim(),
|
|
922
|
+
labelHaloColor: cs.getPropertyValue('--lyra-graph-edge-label-halo').trim() || cs.getPropertyValue('--lyra-color-surface').trim(),
|
|
923
|
+
font: `${this.edgeLabelFontPx()}px ${cs.getPropertyValue('--lyra-font').trim() || 'sans-serif'}`,
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
/** Sizes the backing store to the canvas's own rendered CSS box (`clientWidth`/`clientHeight`,
|
|
927
|
+
* themselves stretched to fill the host via `[part="base"]`/`[part="canvas"]`'s `100%` sizing)
|
|
928
|
+
* times `devicePixelRatio`, only touching `width`/`height` when the target actually changed --
|
|
929
|
+
* reassigning either unconditionally would implicitly clear the canvas and reset its transform
|
|
930
|
+
* on every single draw, even a pure pan/zoom repaint. Mirrors `<lyra-heatmap>`'s own DPR-scaled
|
|
931
|
+
* backing-store convention (`watchDpr()`/`onDprChange()`), adapted to `setTransform()` (an
|
|
932
|
+
* absolute reset) rather than a relative `scale()`, since this canvas -- unlike heatmap's, which
|
|
933
|
+
* always resizes its backing store on every draw -- only resizes conditionally. */
|
|
934
|
+
drawCanvas() {
|
|
935
|
+
if (!this.canvasEl || !this.canvasCtx)
|
|
936
|
+
return;
|
|
937
|
+
const dpr = window.devicePixelRatio || 1;
|
|
938
|
+
const w = this.canvasEl.clientWidth || this.safeWidth;
|
|
939
|
+
const h = this.canvasEl.clientHeight || this.safeHeight;
|
|
940
|
+
const backingW = Math.round(w * dpr);
|
|
941
|
+
const backingH = Math.round(h * dpr);
|
|
942
|
+
if (this.canvasEl.width !== backingW || this.canvasEl.height !== backingH) {
|
|
943
|
+
this.canvasEl.width = backingW;
|
|
944
|
+
this.canvasEl.height = backingH;
|
|
945
|
+
}
|
|
946
|
+
const ctx = this.canvasCtx;
|
|
947
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
948
|
+
ctx.clearRect(0, 0, w, h);
|
|
949
|
+
// Reuse the cached scene for a camera-only repaint; rebuild when it was invalidated
|
|
950
|
+
// (markCanvasDirty()) or when the camera crossed one of the two label-visibility zoom gates
|
|
951
|
+
// the scene bakes in (see canvasSceneHasEdgeLabels' doc).
|
|
952
|
+
const edgeLabelsVisible = this.showEdgeLabels && this.canvasCamera.k >= this.safeEdgeLabelMinZoom;
|
|
953
|
+
const nodeLabelsVisible = this.canvasCamera.k >= CANVAS_NODE_LABEL_MIN_ZOOM;
|
|
954
|
+
if (!this.canvasScene ||
|
|
955
|
+
this.canvasScene.showNodeLabels !== nodeLabelsVisible ||
|
|
956
|
+
this.canvasSceneHasEdgeLabels !== edgeLabelsVisible) {
|
|
957
|
+
this.canvasScene = this.buildCanvasScene(getComputedStyle(this));
|
|
958
|
+
this.canvasSceneHasEdgeLabels = edgeLabelsVisible;
|
|
959
|
+
}
|
|
960
|
+
drawGraphScene(ctx, this.canvasCamera, this.canvasScene);
|
|
961
|
+
}
|
|
962
|
+
// ---------------------------------------------------------------------------------------------
|
|
963
|
+
// renderer="canvas": color-picking hit-testing, pointer interaction, and the hover tooltip.
|
|
964
|
+
// ---------------------------------------------------------------------------------------------
|
|
965
|
+
rebuildPickItems() {
|
|
966
|
+
this.pickItems = [
|
|
967
|
+
...this.visibleCommunities().map((entry) => ({ kind: 'hull', entry })),
|
|
968
|
+
...this.simLinks.map((link) => ({ kind: 'link', link })),
|
|
969
|
+
...this.simNodes.map((node) => ({ kind: 'node', node })),
|
|
970
|
+
];
|
|
971
|
+
}
|
|
972
|
+
redrawPickCanvas() {
|
|
973
|
+
if (!this.pickCtx || !this.canvasEl || !this.pickCanvas)
|
|
974
|
+
return;
|
|
975
|
+
if (this.pickCanvas.width !== this.canvasEl.width || this.pickCanvas.height !== this.canvasEl.height) {
|
|
976
|
+
this.pickCanvas.width = this.canvasEl.width;
|
|
977
|
+
this.pickCanvas.height = this.canvasEl.height;
|
|
978
|
+
}
|
|
979
|
+
this.rebuildPickItems();
|
|
980
|
+
const dpr = window.devicePixelRatio || 1;
|
|
981
|
+
this.pickCtx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
982
|
+
drawPickingScene(this.pickCtx, this.canvasCamera, {
|
|
983
|
+
hulls: this.pickItems
|
|
984
|
+
.filter((i) => i.kind === 'hull')
|
|
985
|
+
.map((i) => ({ d: hullPathD(this.communityHull(i.entry.members)) })),
|
|
986
|
+
links: this.pickItems
|
|
987
|
+
.filter((i) => i.kind === 'link')
|
|
988
|
+
.map((i) => {
|
|
989
|
+
const c = this.linkCoordinates(i.link);
|
|
990
|
+
return { x1: c.x1, y1: c.y1, x2: c.x2, y2: c.y2, width: i.link.width ?? 1.5 };
|
|
991
|
+
}),
|
|
992
|
+
nodes: this.pickItems
|
|
993
|
+
.filter((i) => i.kind === 'node')
|
|
994
|
+
.map((i) => ({
|
|
995
|
+
x: i.node.x ?? 0,
|
|
996
|
+
y: i.node.y ?? 0,
|
|
997
|
+
r: this.nodeRadius(i.node) + 2,
|
|
998
|
+
shape: this.nodeShape(i.node),
|
|
999
|
+
})),
|
|
1000
|
+
});
|
|
1001
|
+
this.pickDirty = false;
|
|
1002
|
+
}
|
|
1003
|
+
hitTest(clientX, clientY) {
|
|
1004
|
+
if (!this.canvasEl || !this.pickCtx)
|
|
1005
|
+
return undefined;
|
|
1006
|
+
if (this.pickDirty)
|
|
1007
|
+
this.redrawPickCanvas();
|
|
1008
|
+
const rect = this.canvasEl.getBoundingClientRect();
|
|
1009
|
+
const dpr = window.devicePixelRatio || 1;
|
|
1010
|
+
const px = Math.round((clientX - rect.left) * dpr);
|
|
1011
|
+
const py = Math.round((clientY - rect.top) * dpr);
|
|
1012
|
+
if (px < 0 || py < 0 || px >= this.pickCtx.canvas.width || py >= this.pickCtx.canvas.height)
|
|
1013
|
+
return undefined;
|
|
1014
|
+
const data = this.pickCtx.getImageData(px, py, 1, 1).data;
|
|
1015
|
+
const index = pickColorToIndex(data[0], data[1], data[2]);
|
|
1016
|
+
return index >= 0 ? this.pickItems[index] : undefined;
|
|
1017
|
+
}
|
|
1018
|
+
bindCanvasZoom() {
|
|
1019
|
+
if (!this.d3 || !this.canvasEl)
|
|
1020
|
+
return;
|
|
1021
|
+
this.zoomBehavior = this.d3
|
|
1022
|
+
.zoom()
|
|
1023
|
+
.scaleExtent([this.safeMinZoom, this.safeMaxZoom])
|
|
1024
|
+
.on('start', () => {
|
|
1025
|
+
// Same self-triggered-echo guard as the svg zoom bind's own 'start' handler above (see its
|
|
1026
|
+
// comment) -- a camera tween's per-frame applyZoomTransform() call fires this synchronously,
|
|
1027
|
+
// and without the guard cancelCameraTween() here would cancel that very tween on its own
|
|
1028
|
+
// first frame.
|
|
1029
|
+
if (this.isApplyingZoomTransform)
|
|
1030
|
+
return;
|
|
1031
|
+
this.isPanning = true;
|
|
1032
|
+
this.cancelCameraTween();
|
|
1033
|
+
})
|
|
1034
|
+
.on('zoom', (event) => {
|
|
1035
|
+
this.canvasCamera = { k: event.transform.k, x: event.transform.x, y: event.transform.y };
|
|
1036
|
+
this.markCanvasCameraDirty();
|
|
1037
|
+
})
|
|
1038
|
+
.on('end', () => {
|
|
1039
|
+
this.isPanning = false;
|
|
1040
|
+
});
|
|
1041
|
+
this.d3.select(this.canvasEl).call(this.zoomBehavior);
|
|
1042
|
+
}
|
|
1043
|
+
bindCanvasPointer() {
|
|
1044
|
+
const canvas = this.canvasEl;
|
|
1045
|
+
canvas.addEventListener('pointerdown', this.onCanvasPointerDown);
|
|
1046
|
+
canvas.addEventListener('pointermove', this.onCanvasPointerMove);
|
|
1047
|
+
canvas.addEventListener('pointerup', this.onCanvasPointerUp);
|
|
1048
|
+
canvas.addEventListener('pointerleave', this.onCanvasPointerLeave);
|
|
1049
|
+
canvas.addEventListener('dblclick', this.onCanvasDblClick);
|
|
1050
|
+
}
|
|
1051
|
+
/** `alpha` decays toward `alphaMin` and d3-force stops its internal timer once it crosses below
|
|
1052
|
+
* it, so `alpha > alphaMin` mirrors the simulation's own running condition -- including a drag's
|
|
1053
|
+
* `alphaTarget(0.3)` reheat, and correctly excluding a seeded/reduced-motion graph whose settle
|
|
1054
|
+
* loop already converged synchronously. */
|
|
1055
|
+
simulationIsTicking() {
|
|
1056
|
+
return this.simulation != null && this.simulation.alpha() > this.simulation.alphaMin();
|
|
1057
|
+
}
|
|
1058
|
+
/** Geometric fallback for dblclick: browsers can deliver the event before the offscreen pick
|
|
1059
|
+
* canvas has painted the latest frame, while the simulation coordinates are already current. */
|
|
1060
|
+
nodeAtCanvasPoint(clientX, clientY) {
|
|
1061
|
+
if (!this.canvasEl)
|
|
1062
|
+
return undefined;
|
|
1063
|
+
const rect = this.canvasEl.getBoundingClientRect();
|
|
1064
|
+
const worldX = (clientX - rect.left - this.canvasCamera.x) / this.canvasCamera.k;
|
|
1065
|
+
const worldY = (clientY - rect.top - this.canvasCamera.y) / this.canvasCamera.k;
|
|
1066
|
+
let closest;
|
|
1067
|
+
let closestDistance = Infinity;
|
|
1068
|
+
for (const node of this.simNodes) {
|
|
1069
|
+
const distance = Math.hypot((node.x ?? 0) - worldX, (node.y ?? 0) - worldY);
|
|
1070
|
+
if (distance <= this.nodeRadius(node) + 2 / this.canvasCamera.k && distance < closestDistance) {
|
|
1071
|
+
closest = node;
|
|
1072
|
+
closestDistance = distance;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
return closest;
|
|
1076
|
+
}
|
|
1077
|
+
updateCanvasTooltip(hit, clientX, clientY) {
|
|
1078
|
+
if (!this.canvasTooltipEl)
|
|
1079
|
+
return;
|
|
1080
|
+
if (!hit || hit.kind === 'hull') {
|
|
1081
|
+
this.canvasTooltipEl.setAttribute('hidden', '');
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
const rect = this.canvasEl.getBoundingClientRect();
|
|
1085
|
+
this.canvasTooltipEl.textContent =
|
|
1086
|
+
hit.kind === 'node' ? this.nodeAccessibleText(hit.node) : this.linkAccessibleText(hit.link);
|
|
1087
|
+
// `clientX - rect.left`/`clientY - rect.top` are physical viewport offsets, so they must be
|
|
1088
|
+
// written to the physical `left`/`top` -- a logical `inset-inline-start` maps to `right` under
|
|
1089
|
+
// RTL and would mirror the tooltip across the canvas instead of tracking the cursor.
|
|
1090
|
+
this.canvasTooltipEl.style.left = `${clientX - rect.left}px`;
|
|
1091
|
+
this.canvasTooltipEl.style.top = `${clientY - rect.top}px`;
|
|
1092
|
+
this.canvasTooltipEl.removeAttribute('hidden');
|
|
1093
|
+
}
|
|
1094
|
+
isSelected(kind, id) {
|
|
1095
|
+
return kind === 'node' ? this.selectedNodeIds.includes(id) : this.selectedLinkIds.includes(id);
|
|
1096
|
+
}
|
|
1097
|
+
linkKey(link) {
|
|
1098
|
+
const source = typeof link.source === 'object' ? link.source.id : String(link.source);
|
|
1099
|
+
const target = typeof link.target === 'object' ? link.target.id : String(link.target);
|
|
1100
|
+
return link.id ?? `${source}->${target}`;
|
|
1101
|
+
}
|
|
1102
|
+
/** Computes and emits the selection intent for activating `id`; never assigns
|
|
1103
|
+
* `selectedNodeIds`/`selectedLinkIds` itself -- see the class doc's controlled-selection note. */
|
|
1104
|
+
emitSelectionIntent(kind, id, toggle) {
|
|
1105
|
+
if (this.selectionMode === 'none')
|
|
1106
|
+
return;
|
|
1107
|
+
const selected = this.isSelected(kind, id);
|
|
1108
|
+
if (this.selectionMode === 'single' || !toggle) {
|
|
1109
|
+
if (this.selectionMode === 'single' && selected) {
|
|
1110
|
+
this.emit('lyra-selection-change', { nodeIds: [], linkIds: [] });
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
this.emit('lyra-selection-change', kind === 'node' ? { nodeIds: [id], linkIds: [] } : { nodeIds: [], linkIds: [id] });
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
const nodeIds = kind === 'node'
|
|
1117
|
+
? selected
|
|
1118
|
+
? this.selectedNodeIds.filter((x) => x !== id)
|
|
1119
|
+
: [...this.selectedNodeIds, id]
|
|
1120
|
+
: this.selectedNodeIds;
|
|
1121
|
+
const linkIds = kind === 'link'
|
|
1122
|
+
? selected
|
|
1123
|
+
? this.selectedLinkIds.filter((x) => x !== id)
|
|
1124
|
+
: [...this.selectedLinkIds, id]
|
|
1125
|
+
: this.selectedLinkIds;
|
|
1126
|
+
this.emit('lyra-selection-change', { nodeIds, linkIds });
|
|
1127
|
+
}
|
|
1128
|
+
clearSelection() {
|
|
1129
|
+
if (this.selectionMode === 'none')
|
|
1130
|
+
return;
|
|
1131
|
+
if (!this.selectedNodeIds.length && !this.selectedLinkIds.length)
|
|
1132
|
+
return;
|
|
1133
|
+
this.emit('lyra-selection-change', { nodeIds: [], linkIds: [] });
|
|
1134
|
+
}
|
|
177
1135
|
willUpdate(changed) {
|
|
178
1136
|
// rebuildSimulation() (re)assigns the simNodes/simLinks reactive
|
|
179
1137
|
// properties — doing that from willUpdate() folds them into the render
|
|
@@ -181,9 +1139,27 @@ export class LyraGraph extends LyraElement {
|
|
|
181
1139
|
// instead would set a reactive property *after* the update completed,
|
|
182
1140
|
// which Lit schedules as a whole extra update pass (a dev-mode warning,
|
|
183
1141
|
// and pointless work).
|
|
184
|
-
if (this.d3 &&
|
|
1142
|
+
if (this.d3 &&
|
|
1143
|
+
(changed.has('nodes') ||
|
|
1144
|
+
changed.has('links') ||
|
|
1145
|
+
changed.has('hiddenTypes') ||
|
|
1146
|
+
changed.has('layout') ||
|
|
1147
|
+
(this.layout === 'layered' && changed.has('linkDistance')))) {
|
|
185
1148
|
this.rebuildSimulation();
|
|
186
1149
|
}
|
|
1150
|
+
// rebuildSimulation() above always reassigns simNodes, so checking it here (after that call)
|
|
1151
|
+
// also catches a nodes/links/hiddenTypes-driven rebuild, not just a direct communities set.
|
|
1152
|
+
if (changed.has('simNodes') || changed.has('communities')) {
|
|
1153
|
+
this.visibleCommunitiesCache = undefined;
|
|
1154
|
+
}
|
|
1155
|
+
// Same reasoning as rebuildSimulation() above -- assigning graphLiveText from updated() would
|
|
1156
|
+
// schedule a whole extra update pass instead of landing in the render this update is already
|
|
1157
|
+
// about to perform.
|
|
1158
|
+
if (changed.has('selectedNodeIds') || changed.has('selectedLinkIds')) {
|
|
1159
|
+
this.graphLiveText = this.localize('graphSelectionCount', undefined, {
|
|
1160
|
+
count: this.selectedNodeIds.length + this.selectedLinkIds.length,
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
187
1163
|
}
|
|
188
1164
|
updated(changed) {
|
|
189
1165
|
if (this.loading)
|
|
@@ -192,13 +1168,13 @@ export class LyraGraph extends LyraElement {
|
|
|
192
1168
|
this.removeAttribute('aria-busy');
|
|
193
1169
|
if (!this.d3)
|
|
194
1170
|
return;
|
|
195
|
-
if (!changed.has('nodes') && !changed.has('links')) {
|
|
1171
|
+
if (!changed.has('nodes') && !changed.has('links') && !changed.has('hiddenTypes')) {
|
|
196
1172
|
// These two branches are independent (not else-if): a consumer can set
|
|
197
1173
|
// width/height and chargeStrength/linkDistance in the same reactive
|
|
198
1174
|
// update batch, and both retunes must apply — not just whichever branch
|
|
199
1175
|
// happens to come first.
|
|
200
1176
|
if (changed.has('width') || changed.has('height')) {
|
|
201
|
-
this.simulation?.force('center', this.d3.forceCenter(this.
|
|
1177
|
+
this.simulation?.force('center', this.d3.forceCenter(this.safeWidth / 2, this.safeHeight / 2));
|
|
202
1178
|
this.simulation?.alpha(0.1).restart();
|
|
203
1179
|
}
|
|
204
1180
|
if (changed.has('chargeStrength') || changed.has('linkDistance')) {
|
|
@@ -207,9 +1183,9 @@ export class LyraGraph extends LyraElement {
|
|
|
207
1183
|
// them fresh) — retune the already-created force objects in place
|
|
208
1184
|
// instead of rebuilding the whole simulation.
|
|
209
1185
|
if (changed.has('chargeStrength'))
|
|
210
|
-
this.chargeForce?.strength(this.
|
|
1186
|
+
this.chargeForce?.strength(this.safeChargeStrength);
|
|
211
1187
|
if (changed.has('linkDistance'))
|
|
212
|
-
this.linkForce?.distance(this.
|
|
1188
|
+
this.linkForce?.distance(this.safeLinkDistance);
|
|
213
1189
|
this.simulation?.alpha(0.3).restart();
|
|
214
1190
|
}
|
|
215
1191
|
}
|
|
@@ -218,6 +1194,15 @@ export class LyraGraph extends LyraElement {
|
|
|
218
1194
|
// node/link querySelectorAll scan on that is equivalent to "structurally
|
|
219
1195
|
// changed" without needing a separate flag.
|
|
220
1196
|
this.applyInteractions(changed);
|
|
1197
|
+
this.applyCanvasInteractions();
|
|
1198
|
+
if (this.focusId == null) {
|
|
1199
|
+
this.lastAppliedFocusId = null;
|
|
1200
|
+
}
|
|
1201
|
+
else if (this.focusId !== this.lastAppliedFocusId && this.simNodes.some((n) => n.id === this.focusId)) {
|
|
1202
|
+
this.lastAppliedFocusId = this.focusId;
|
|
1203
|
+
void this.focusNode(this.focusId);
|
|
1204
|
+
}
|
|
1205
|
+
this.updateFocusHalo();
|
|
221
1206
|
}
|
|
222
1207
|
/**
|
|
223
1208
|
* Imperatively wires up d3-zoom (pan/zoom on the `<svg>`) and d3-drag
|
|
@@ -243,58 +1228,115 @@ export class LyraGraph extends LyraElement {
|
|
|
243
1228
|
applyInteractions(changed) {
|
|
244
1229
|
if (!this.d3)
|
|
245
1230
|
return;
|
|
1231
|
+
if (this.renderer !== 'svg')
|
|
1232
|
+
return;
|
|
246
1233
|
const svgEl = this.renderRoot.querySelector('svg');
|
|
247
1234
|
if (svgEl && svgEl !== this.zoomedEl) {
|
|
1235
|
+
// Binding a fresh svg means any previous renderer="canvas" surface is gone -- stop its
|
|
1236
|
+
// resize watcher now (it observes the host, not the removed <canvas>, so it would keep
|
|
1237
|
+
// firing markCanvasDirty() for as long as the element lives in svg mode).
|
|
1238
|
+
this.canvasResizeObserver?.disconnect();
|
|
1239
|
+
this.canvasResizeObserver = undefined;
|
|
248
1240
|
this.zoomedEl = svgEl;
|
|
249
1241
|
this.gEl = this.renderRoot.querySelector('g') ?? undefined;
|
|
1242
|
+
this.focusHaloEl = this.renderRoot.querySelector('[part="focus-halo"]') ?? undefined;
|
|
250
1243
|
this.zoomBehavior = this.d3
|
|
251
1244
|
.zoom()
|
|
252
|
-
.scaleExtent([this.
|
|
1245
|
+
.scaleExtent([this.safeMinZoom, this.safeMaxZoom])
|
|
1246
|
+
.on('start', () => {
|
|
1247
|
+
// A camera tween writes a transform on every frame via applyZoomTransform(), which
|
|
1248
|
+
// itself synchronously replays this same 'start' handler -- ignore that self-triggered
|
|
1249
|
+
// echo so a tween doesn't cancel itself on its own first frame.
|
|
1250
|
+
if (this.isApplyingZoomTransform)
|
|
1251
|
+
return;
|
|
1252
|
+
this.isPanning = true;
|
|
1253
|
+
this.cancelCameraTween();
|
|
1254
|
+
})
|
|
253
1255
|
.on('zoom', (event) => {
|
|
254
1256
|
this.gEl?.setAttribute('transform', event.transform.toString());
|
|
1257
|
+
this.updateEdgeLabelZoomGate(event.transform.k);
|
|
1258
|
+
})
|
|
1259
|
+
.on('end', () => {
|
|
1260
|
+
this.isPanning = false;
|
|
255
1261
|
});
|
|
256
1262
|
this.d3.select(svgEl).call(this.zoomBehavior);
|
|
1263
|
+
// `.call(zoomBehavior)` does not synchronously fire the 'zoom' handler above (only a real
|
|
1264
|
+
// user gesture or an explicit `.transform()` call does, and nothing in this component ever
|
|
1265
|
+
// calls `.transform()`) -- so the initial transform right here is always d3-zoom's own
|
|
1266
|
+
// identity transform, k=1. Apply the edge-label zoom gate against that known value now, or
|
|
1267
|
+
// it stays unset (edge labels wrongly visible) until the user's first pan/zoom, regardless
|
|
1268
|
+
// of what edgeLabelMinZoom actually is.
|
|
1269
|
+
this.updateEdgeLabelZoomGate(1);
|
|
257
1270
|
}
|
|
258
1271
|
else if (this.zoomBehavior && (changed.has('minZoom') || changed.has('maxZoom'))) {
|
|
259
|
-
this.zoomBehavior.scaleExtent([this.
|
|
1272
|
+
this.zoomBehavior.scaleExtent([this.safeMinZoom, this.safeMaxZoom]);
|
|
260
1273
|
}
|
|
261
|
-
if (!(changed.has('simNodes') ||
|
|
1274
|
+
if (!(changed.has('simNodes') ||
|
|
1275
|
+
changed.has('simLinks') ||
|
|
1276
|
+
changed.has('nodeTypes') ||
|
|
1277
|
+
changed.has('showEdgeLabels') ||
|
|
1278
|
+
changed.has('communities')))
|
|
262
1279
|
return;
|
|
263
1280
|
const nodeEls = Array.from(this.renderRoot.querySelectorAll('[part="node"]'));
|
|
264
1281
|
this.nodeEls = nodeEls;
|
|
265
1282
|
this.nodeLabelEls = nodeEls.map((el) => el.parentElement?.querySelector('[part="label"]') ?? null);
|
|
1283
|
+
this.expandIndicatorEls = nodeEls.map((el) => el.parentElement?.querySelector('[part="expand-indicator"]') ?? null);
|
|
266
1284
|
// Dangling stubs also carry part="link" (so they inherit the same themeable styling as a
|
|
267
1285
|
// real edge) -- excluded here explicitly so `linkEls` stays index-aligned with `simLinks`
|
|
268
1286
|
// rather than relying on stubs always sorting after real links in template/DOM order.
|
|
269
1287
|
this.linkEls = Array.from(this.renderRoot.querySelectorAll('[part="link"]:not([data-dangling])'));
|
|
1288
|
+
this.linkLabelEls = this.linkEls.map((el) => el.parentElement?.querySelector('[part="link-label"]') ?? null);
|
|
1289
|
+
this.linkLabelHiddenByLength = [];
|
|
270
1290
|
this.danglingLinkEls = Array.from(this.renderRoot.querySelectorAll('[part="link"][data-dangling]'));
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
this.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
1291
|
+
this.communityHullEls = Array.from(this.renderRoot.querySelectorAll('[part="hull"]'));
|
|
1292
|
+
this.communityLabelEls = Array.from(this.renderRoot.querySelectorAll('[part="community-label"]'));
|
|
1293
|
+
if (this.layout !== 'layered') {
|
|
1294
|
+
nodeEls.forEach((el, i) => {
|
|
1295
|
+
if (this.boundNodeEls.has(el))
|
|
1296
|
+
return;
|
|
1297
|
+
const n = this.simNodes[i];
|
|
1298
|
+
if (!n)
|
|
1299
|
+
return;
|
|
1300
|
+
this.boundNodeEls.add(el);
|
|
1301
|
+
this.d3.select(el).call(this.d3.drag()
|
|
1302
|
+
.on('start', (event) => {
|
|
1303
|
+
this.isDragging = true;
|
|
1304
|
+
// Keep a node drag from also triggering the svg's own pan gesture.
|
|
1305
|
+
event.sourceEvent?.stopPropagation();
|
|
1306
|
+
if (!event.active)
|
|
1307
|
+
this.simulation?.alphaTarget(0.3).restart();
|
|
1308
|
+
n.fx = n.x;
|
|
1309
|
+
n.fy = n.y;
|
|
1310
|
+
})
|
|
1311
|
+
.on('drag', (event) => {
|
|
1312
|
+
n.fx = event.x;
|
|
1313
|
+
n.fy = event.y;
|
|
1314
|
+
})
|
|
1315
|
+
.on('end', (event) => {
|
|
1316
|
+
this.isDragging = false;
|
|
1317
|
+
if (!event.active)
|
|
1318
|
+
this.simulation?.alphaTarget(0);
|
|
1319
|
+
n.fx = null;
|
|
1320
|
+
n.fy = null;
|
|
1321
|
+
}));
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
/** The `renderer="canvas"` twin of `applyInteractions()`'s svg zoom-bind branch -- binds d3-zoom
|
|
1326
|
+
* and the pointer/hit-testing handlers to the just-rendered `<canvas>` once (guarded by the same
|
|
1327
|
+
* `zoomedEl` field `applyInteractions()` uses, so `focusNode()`/`fit()`/`tweenCamera()` keep
|
|
1328
|
+
* working unmodified against whichever element -- svg or canvas -- is currently bound), then
|
|
1329
|
+
* marks the canvas dirty on every call so any structural/style-affecting change (new nodes/
|
|
1330
|
+
* links, a selection change, a hiddenTypes toggle, ...) schedules a fresh draw the same way a
|
|
1331
|
+
* Lit re-render already does for svg mode. */
|
|
1332
|
+
applyCanvasInteractions() {
|
|
1333
|
+
if (this.renderer !== 'canvas' || !this.canvasEl)
|
|
1334
|
+
return;
|
|
1335
|
+
if (this.canvasEl !== this.zoomedEl) {
|
|
1336
|
+
this.zoomedEl = this.canvasEl;
|
|
1337
|
+
this.setUpCanvasSurface();
|
|
1338
|
+
}
|
|
1339
|
+
this.markCanvasDirty();
|
|
298
1340
|
}
|
|
299
1341
|
/**
|
|
300
1342
|
* Runs on every d3-force simulation tick (up to ~300 while a graph settles
|
|
@@ -315,11 +1357,26 @@ export class LyraGraph extends LyraElement {
|
|
|
315
1357
|
target.x = (source.x ?? 0) + STUB_OFFSET_PX;
|
|
316
1358
|
target.y = (source.y ?? 0) + STUB_OFFSET_PX;
|
|
317
1359
|
}
|
|
1360
|
+
// Keep the remembered-position cache current with a position captured mid-settle or mid-drag
|
|
1361
|
+
// (not just the one snapshotted at the end of rebuildSimulation()) -- a hiddenTypes toggle
|
|
1362
|
+
// that lands before the next structural rebuild should still restore a node to where it
|
|
1363
|
+
// actually was, not an earlier, since-superseded snapshot. Plain Map writes, no DOM/no
|
|
1364
|
+
// reactive-property touch, so this stays on the same cheap per-tick path as the rest of this
|
|
1365
|
+
// method.
|
|
1366
|
+
for (const n of this.simNodes) {
|
|
1367
|
+
if (n.x != null && n.y != null)
|
|
1368
|
+
this.lastPositionById.set(n.id, { x: n.x, y: n.y });
|
|
1369
|
+
}
|
|
318
1370
|
this.simNodes.forEach((n, i) => {
|
|
319
|
-
const
|
|
320
|
-
if (
|
|
321
|
-
|
|
322
|
-
|
|
1371
|
+
const el = this.nodeEls[i];
|
|
1372
|
+
if (el) {
|
|
1373
|
+
if (el.tagName === 'circle') {
|
|
1374
|
+
el.setAttribute('cx', String(n.x ?? 0));
|
|
1375
|
+
el.setAttribute('cy', String(n.y ?? 0));
|
|
1376
|
+
}
|
|
1377
|
+
else {
|
|
1378
|
+
el.setAttribute('transform', `translate(${n.x ?? 0},${n.y ?? 0})`);
|
|
1379
|
+
}
|
|
323
1380
|
}
|
|
324
1381
|
const label = this.nodeLabelEls[i];
|
|
325
1382
|
if (label) {
|
|
@@ -337,6 +1394,28 @@ export class LyraGraph extends LyraElement {
|
|
|
337
1394
|
line.setAttribute('x2', String(coordinates.x2));
|
|
338
1395
|
line.setAttribute('y2', String(coordinates.y2));
|
|
339
1396
|
});
|
|
1397
|
+
if (this.showEdgeLabels) {
|
|
1398
|
+
this.simLinks.forEach((l, i) => {
|
|
1399
|
+
const labelEl = this.linkLabelEls[i];
|
|
1400
|
+
if (!labelEl)
|
|
1401
|
+
return;
|
|
1402
|
+
const pos = this.edgeLabelPosition(l);
|
|
1403
|
+
labelEl.setAttribute('x', String(pos.x));
|
|
1404
|
+
labelEl.setAttribute('y', String(pos.y));
|
|
1405
|
+
const { x1, y1, x2, y2 } = this.linkCoordinates(l);
|
|
1406
|
+
const edgeLength = Math.hypot(x2 - x1, y2 - y1);
|
|
1407
|
+
const tooLong = this.edgeLabelWidth(l.label ?? '') > edgeLength * EDGE_LABEL_LENGTH_GATE_RATIO;
|
|
1408
|
+
if (this.linkLabelHiddenByLength[i] !== tooLong) {
|
|
1409
|
+
this.linkLabelHiddenByLength[i] = tooLong;
|
|
1410
|
+
labelEl.setAttribute('visibility', tooLong ? 'hidden' : 'visible');
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
this.simNodes.forEach((n, i) => {
|
|
1415
|
+
const indicator = this.expandIndicatorEls[i];
|
|
1416
|
+
if (indicator)
|
|
1417
|
+
indicator.setAttribute('transform', `translate(${n.x ?? 0},${n.y ?? 0})`);
|
|
1418
|
+
});
|
|
340
1419
|
// Dangling stubs are excluded from d3-force's own simulation input (see
|
|
341
1420
|
// rebuildSimulation()'s "stubs never enter d3-force's own simulation input"), so the
|
|
342
1421
|
// synthetic target position the danglingLinks loop at the top of this method just
|
|
@@ -353,12 +1432,41 @@ export class LyraGraph extends LyraElement {
|
|
|
353
1432
|
line.setAttribute('x2', String(coordinates.x2));
|
|
354
1433
|
line.setAttribute('y2', String(coordinates.y2));
|
|
355
1434
|
});
|
|
1435
|
+
this.updateFocusHalo();
|
|
1436
|
+
this.visibleCommunities().forEach((entry, i) => {
|
|
1437
|
+
const hullEl = this.communityHullEls[i];
|
|
1438
|
+
const labelEl = this.communityLabelEls[i];
|
|
1439
|
+
if (!hullEl && !labelEl)
|
|
1440
|
+
return;
|
|
1441
|
+
const hull = this.communityHull(entry.members);
|
|
1442
|
+
if (hullEl)
|
|
1443
|
+
hullEl.setAttribute('d', hullPathD(hull));
|
|
1444
|
+
if (labelEl) {
|
|
1445
|
+
labelEl.setAttribute('x', String(hullCentroidX(hull)));
|
|
1446
|
+
labelEl.setAttribute('y', String(hullTopY(hull) - HULL_PADDING));
|
|
1447
|
+
}
|
|
1448
|
+
});
|
|
1449
|
+
// renderer="canvas" mode has no DOM to write positions straight to (everything above this line
|
|
1450
|
+
// no-ops there: nodeEls/linkEls/etc. are only ever populated by applyInteractions()'s svg-only
|
|
1451
|
+
// branch) -- schedule a fresh draw off the same simulation tick instead, so the settle
|
|
1452
|
+
// animation and a live node drag actually repaint the canvas rather than freezing at whatever
|
|
1453
|
+
// was last drawn on mount.
|
|
1454
|
+
if (this.renderer === 'canvas')
|
|
1455
|
+
this.markCanvasDirty();
|
|
356
1456
|
}
|
|
357
1457
|
rebuildSimulation() {
|
|
358
1458
|
if (!this.d3)
|
|
359
1459
|
return;
|
|
360
1460
|
this.simulation?.stop();
|
|
361
1461
|
this.boundNodeEls = new WeakSet();
|
|
1462
|
+
// Prune remembered positions for ids no longer present in `this.nodes` at all (not merely
|
|
1463
|
+
// hidden by hiddenTypes) -- otherwise this cache would grow forever across a long-lived,
|
|
1464
|
+
// mutating graph instead of tracking only ids that could plausibly reappear.
|
|
1465
|
+
const liveIds = new Set(this.nodes.map((n) => n.id));
|
|
1466
|
+
for (const id of this.lastPositionById.keys()) {
|
|
1467
|
+
if (!liveIds.has(id))
|
|
1468
|
+
this.lastPositionById.delete(id);
|
|
1469
|
+
}
|
|
362
1470
|
// Carry over each existing SimNode's settled position/velocity (and any
|
|
363
1471
|
// in-progress drag fx/fy) by id instead of starting every node fresh —
|
|
364
1472
|
// otherwise any structural nodes/links change (e.g. appending one new
|
|
@@ -367,60 +1475,98 @@ export class LyraGraph extends LyraElement {
|
|
|
367
1475
|
// start settle animation from scratch. Only nodes with no previous
|
|
368
1476
|
// counterpart (genuinely new ids) get forceSimulation()'s default
|
|
369
1477
|
// fresh random start below.
|
|
1478
|
+
const visible = this.visibleNodes();
|
|
1479
|
+
if (this.layout === 'layered') {
|
|
1480
|
+
this.rebuildLayeredLayout(visible);
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
370
1483
|
const prevById = new Map(this.simNodes.map((n) => [n.id, n]));
|
|
371
|
-
const nodes =
|
|
1484
|
+
const nodes = visible.map((n) => {
|
|
372
1485
|
const prev = prevById.get(n.id);
|
|
373
|
-
|
|
1486
|
+
if (prev)
|
|
1487
|
+
return { ...prev, ...n };
|
|
1488
|
+
// A node hidden by hiddenTypes and now visible again has no prevById entry (it fell out of
|
|
1489
|
+
// simNodes while hidden) but may still have a remembered settled position from before it was
|
|
1490
|
+
// hidden -- restore that instead of leaving it for the neighbor-jitter/seed spawn logic below,
|
|
1491
|
+
// or forceSimulation()'s own random start, to place it as if it were a brand-new node.
|
|
1492
|
+
const remembered = this.lastPositionById.get(n.id);
|
|
1493
|
+
return remembered ? { ...n, x: remembered.x, y: remembered.y } : { ...n };
|
|
374
1494
|
});
|
|
375
1495
|
const byId = new Map(nodes.map((n) => [n.id, n]));
|
|
376
|
-
const resolvedLinks =
|
|
377
|
-
const danglingLinks = [];
|
|
378
|
-
for (const l of this.links) {
|
|
379
|
-
const source = byId.get(l.source);
|
|
380
|
-
if (!source)
|
|
381
|
-
continue; // no real position to draw a stub from -- stays dropped, unchanged
|
|
382
|
-
const target = byId.get(l.target);
|
|
383
|
-
if (target) {
|
|
384
|
-
resolvedLinks.push({ ...l, source, target });
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
danglingLinks.push({
|
|
388
|
-
...l,
|
|
389
|
-
source,
|
|
390
|
-
target: { id: l.target, x: source.x, y: source.y },
|
|
391
|
-
dangling: true,
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
}
|
|
1496
|
+
const { resolved: resolvedLinks, dangling: danglingLinks } = this.resolveLinksAgainst(byId);
|
|
395
1497
|
const links = resolvedLinks; // stubs never enter d3-force's own simulation input
|
|
396
1498
|
this.danglingLinks = danglingLinks;
|
|
397
|
-
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
-
//
|
|
1499
|
+
const seedForSpawn = this.safeSeed;
|
|
1500
|
+
// Give a brand-new node with no carried-over position (from prevById above) a spawn point
|
|
1501
|
+
// near an already-positioned neighbor instead of forceSimulation()'s eventual random start --
|
|
1502
|
+
// expanded neighborhoods bloom around their origin instead of flying in from nowhere. Only
|
|
1503
|
+
// touches nodes with no position yet, so it can't move anything already settled.
|
|
1504
|
+
for (const n of nodes) {
|
|
1505
|
+
if (n.x != null && n.y != null)
|
|
1506
|
+
continue;
|
|
1507
|
+
const neighborLink = resolvedLinks.find((l) => {
|
|
1508
|
+
const source = l.source;
|
|
1509
|
+
const target = l.target;
|
|
1510
|
+
return (source.id === n.id && target.x != null) || (target.id === n.id && source.x != null);
|
|
1511
|
+
});
|
|
1512
|
+
if (!neighborLink)
|
|
1513
|
+
continue;
|
|
1514
|
+
const source = neighborLink.source;
|
|
1515
|
+
const target = neighborLink.target;
|
|
1516
|
+
const neighbor = source.id === n.id ? target : source;
|
|
1517
|
+
const jitterRadius = this.safeLinkDistance / 2;
|
|
1518
|
+
const angle = seedForSpawn != null
|
|
1519
|
+
? (hashNodeSeed(seedForSpawn, n.id) / 4294967296) * Math.PI * 2
|
|
1520
|
+
: Math.random() * Math.PI * 2;
|
|
1521
|
+
n.x = (neighbor.x ?? 0) + Math.cos(angle) * jitterRadius;
|
|
1522
|
+
n.y = (neighbor.y ?? 0) + Math.sin(angle) * jitterRadius;
|
|
1523
|
+
}
|
|
1524
|
+
// Give any remaining brand-new nodes (no carried-over position from prevById above, and no
|
|
1525
|
+
// already-positioned neighbor for the jitter spawn above to anchor to) a deterministic
|
|
1526
|
+
// starting x/y, keyed by node id, instead of leaving them for forceSimulation() below to
|
|
1527
|
+
// randomize. Nodes that already have a position are left untouched — same "only randomize
|
|
1528
|
+
// nodes without x/y" rule forceSimulation() itself follows — so an incremental update to a
|
|
402
1529
|
// seeded, already-settled graph doesn't reshuffle existing nodes.
|
|
403
|
-
|
|
404
|
-
if (seed != null) {
|
|
1530
|
+
if (seedForSpawn != null) {
|
|
405
1531
|
for (const n of nodes) {
|
|
406
1532
|
if (n.x != null && n.y != null)
|
|
407
1533
|
continue;
|
|
408
|
-
const rng = mulberry32(hashNodeSeed(
|
|
409
|
-
n.x = rng() * this.
|
|
410
|
-
n.y = rng() * this.
|
|
1534
|
+
const rng = mulberry32(hashNodeSeed(seedForSpawn, n.id));
|
|
1535
|
+
n.x = rng() * this.safeWidth;
|
|
1536
|
+
n.y = rng() * this.safeHeight;
|
|
411
1537
|
}
|
|
412
1538
|
}
|
|
413
|
-
this.linkForce = this.d3.forceLink(links).distance(this.
|
|
414
|
-
this.chargeForce = this.d3.forceManyBody().strength(this.
|
|
1539
|
+
this.linkForce = this.d3.forceLink(links).distance(this.safeLinkDistance);
|
|
1540
|
+
this.chargeForce = this.d3.forceManyBody().strength(this.safeChargeStrength);
|
|
415
1541
|
const simulation = this.d3
|
|
416
1542
|
.forceSimulation(nodes)
|
|
417
1543
|
.force('link', this.linkForce)
|
|
418
1544
|
.force('charge', this.chargeForce)
|
|
419
|
-
.force('center', this.d3.forceCenter(this.
|
|
1545
|
+
.force('center', this.d3.forceCenter(this.safeWidth / 2, this.safeHeight / 2))
|
|
420
1546
|
.force('collide', this.d3.forceCollide().radius((n) => this.nodeRadius(n) + 10))
|
|
421
1547
|
.on('tick', () => this.onTick());
|
|
422
1548
|
this.simulation = simulation;
|
|
423
|
-
if (prefersReducedMotion() || this.
|
|
1549
|
+
if (prefersReducedMotion() || this.safeSeed != null) {
|
|
1550
|
+
// Pin every node that already had a known position before this rebuild -- either carried
|
|
1551
|
+
// over directly (fx/fy, the same mechanism a user drag uses) or restored from
|
|
1552
|
+
// lastPositionById after being hidden by hiddenTypes -- so introducing a new node/link can't
|
|
1553
|
+
// visibly reposition it during this synchronous settle. Only a genuinely new node (no prior
|
|
1554
|
+
// counterpart in either source) is free to move while the simulation converges. A node whose
|
|
1555
|
+
// fx/fy was already set (an active user drag concurrent with this rebuild) is left alone
|
|
1556
|
+
// entirely -- both the pin and the later release below only apply to a node this loop itself
|
|
1557
|
+
// pinned, so a real in-progress drag's own fx/fy is never clobbered. Everything this loop
|
|
1558
|
+
// does pin gets released again immediately below, so this has no lasting effect on a later
|
|
1559
|
+
// user-initiated drag, nor on the live, async settle a non-seeded/non-reduced-motion graph
|
|
1560
|
+
// still animates over ~300 frames.
|
|
1561
|
+
const pinnedForSettle = new Set();
|
|
1562
|
+
for (const n of nodes) {
|
|
1563
|
+
const hadKnownPosition = prevById.has(n.id) || this.lastPositionById.has(n.id);
|
|
1564
|
+
if (hadKnownPosition && n.x != null && n.y != null && n.fx == null && n.fy == null) {
|
|
1565
|
+
n.fx = n.x;
|
|
1566
|
+
n.fy = n.y;
|
|
1567
|
+
pinnedForSettle.add(n.id);
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
424
1570
|
// Converge synchronously instead of animating the settle over ~300
|
|
425
1571
|
// rendered frames — the simulation is already stopped (alpha at
|
|
426
1572
|
// alphaMin) by the time the DOM for this rebuild is first painted.
|
|
@@ -431,6 +1577,12 @@ export class LyraGraph extends LyraElement {
|
|
|
431
1577
|
simulation.stop();
|
|
432
1578
|
while (simulation.alpha() > simulation.alphaMin())
|
|
433
1579
|
simulation.tick();
|
|
1580
|
+
for (const n of nodes) {
|
|
1581
|
+
if (pinnedForSettle.has(n.id)) {
|
|
1582
|
+
n.fx = null;
|
|
1583
|
+
n.fy = null;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
434
1586
|
}
|
|
435
1587
|
// Assign these SAME array/object references (not copies) exactly once
|
|
436
1588
|
// for this structural rebuild: forceSimulation(nodes) above already
|
|
@@ -442,17 +1594,137 @@ export class LyraGraph extends LyraElement {
|
|
|
442
1594
|
// re-render up to ~300 times on load and continuously while dragging.
|
|
443
1595
|
this.simNodes = nodes;
|
|
444
1596
|
this.simLinks = links;
|
|
1597
|
+
for (const n of nodes) {
|
|
1598
|
+
if (n.x != null && n.y != null)
|
|
1599
|
+
this.lastPositionById.set(n.id, { x: n.x, y: n.y });
|
|
1600
|
+
}
|
|
1601
|
+
this.announceHiddenNodeCount(nodes.length);
|
|
1602
|
+
}
|
|
1603
|
+
/** Announces the current hidden-node count via the live region -- shared by both the force and
|
|
1604
|
+
* layered rebuild paths (each calls this with its own final visible-node count) so `hiddenTypes`
|
|
1605
|
+
* filtering announces identically regardless of `layout`. Called from right here (not from
|
|
1606
|
+
* willUpdate()/updated() gated on a 'hiddenTypes'/'nodes' PropertyValues diff) because
|
|
1607
|
+
* rebuildSimulation() itself is also invoked directly from connectedCallback() once the lazy d3
|
|
1608
|
+
* peer deps resolve -- a call that never goes through Lit's changed-property diffing at all.
|
|
1609
|
+
* Computing it there instead would miss that path entirely: a graph mounted with hiddenTypes
|
|
1610
|
+
* already set would compute this from a still-empty simNodes (0 settled nodes yet) on the
|
|
1611
|
+
* property-driven pass, then never get a chance to correct it once the real simNodes became
|
|
1612
|
+
* available. Only ever touches graphLiveText when there's something to say -- a node is
|
|
1613
|
+
* currently hidden, or one just stopped being hidden -- so a consumer that never sets
|
|
1614
|
+
* hiddenTypes keeps today's exact live-region output. */
|
|
1615
|
+
announceHiddenNodeCount(visibleNodeCount) {
|
|
1616
|
+
const totalNodeCount = this.nodes.length;
|
|
1617
|
+
const hiddenNodeCount = totalNodeCount - visibleNodeCount;
|
|
1618
|
+
if (totalNodeCount > 0 && (hiddenNodeCount > 0 || this.lastHiddenNodeCount > 0)) {
|
|
1619
|
+
this.graphLiveText = this.localize('graphNodesHidden', undefined, {
|
|
1620
|
+
hidden: hiddenNodeCount,
|
|
1621
|
+
total: totalNodeCount,
|
|
1622
|
+
});
|
|
1623
|
+
}
|
|
1624
|
+
this.lastHiddenNodeCount = hiddenNodeCount;
|
|
1625
|
+
}
|
|
1626
|
+
/** The `layout="layered"` path: computes final positions synchronously via the shared
|
|
1627
|
+
* `layeredLayout()` util (2r x 2r boxes, `gapY = linkDistance`, `gapX = 12`), centers the
|
|
1628
|
+
* drawing in `width` x `height`, and skips forceSimulation() entirely -- no `this.simulation`,
|
|
1629
|
+
* no ticking, no `prevById` carry-over (deterministic input -> output makes it unnecessary; a
|
|
1630
|
+
* structural change simply recomputes wholesale). `lyra-graph` never passes `fixedPositions`. */
|
|
1631
|
+
rebuildLayeredLayout(visible) {
|
|
1632
|
+
const boxes = visible.map((n) => {
|
|
1633
|
+
const r = this.nodeRadius(n);
|
|
1634
|
+
return { id: n.id, width: r * 2, height: r * 2 };
|
|
1635
|
+
});
|
|
1636
|
+
const visibleIds = new Set(visible.map((n) => n.id));
|
|
1637
|
+
const edges = this.links
|
|
1638
|
+
.filter((l) => visibleIds.has(l.source) && visibleIds.has(l.target))
|
|
1639
|
+
.map((l) => ({ source: l.source, target: l.target }));
|
|
1640
|
+
const raw = layeredLayout({ nodes: boxes, edges, options: { gapX: 12, gapY: this.safeLinkDistance } });
|
|
1641
|
+
let minX = Infinity;
|
|
1642
|
+
let minY = Infinity;
|
|
1643
|
+
let maxX = -Infinity;
|
|
1644
|
+
let maxY = -Infinity;
|
|
1645
|
+
for (const p of raw.values()) {
|
|
1646
|
+
minX = Math.min(minX, p.x);
|
|
1647
|
+
maxX = Math.max(maxX, p.x);
|
|
1648
|
+
minY = Math.min(minY, p.y);
|
|
1649
|
+
maxY = Math.max(maxY, p.y);
|
|
1650
|
+
}
|
|
1651
|
+
const offsetX = raw.size ? this.safeWidth / 2 - (minX + (maxX - minX) / 2) : this.safeWidth / 2;
|
|
1652
|
+
const offsetY = raw.size ? this.safeHeight / 2 - (minY + (maxY - minY) / 2) : this.safeHeight / 2;
|
|
1653
|
+
const nodes = visible.map((n) => {
|
|
1654
|
+
const p = raw.get(n.id);
|
|
1655
|
+
return { ...n, x: (p?.x ?? this.safeWidth / 2) + offsetX, y: (p?.y ?? this.safeHeight / 2) + offsetY };
|
|
1656
|
+
});
|
|
1657
|
+
const byId = new Map(nodes.map((n) => [n.id, n]));
|
|
1658
|
+
const { resolved, dangling } = this.resolveLinksAgainst(byId);
|
|
1659
|
+
this.danglingLinks = dangling;
|
|
1660
|
+
this.simulation = undefined;
|
|
1661
|
+
this.simNodes = nodes;
|
|
1662
|
+
this.simLinks = resolved;
|
|
1663
|
+
for (const n of nodes) {
|
|
1664
|
+
if (n.x != null && n.y != null)
|
|
1665
|
+
this.lastPositionById.set(n.id, { x: n.x, y: n.y });
|
|
1666
|
+
}
|
|
1667
|
+
this.announceHiddenNodeCount(nodes.length);
|
|
445
1668
|
}
|
|
446
|
-
onNodeClick(node) {
|
|
447
|
-
this.emit('lyra-node-click', { id: node.id });
|
|
1669
|
+
onNodeClick(node, e) {
|
|
1670
|
+
this.emit('lyra-node-click', { id: node.id, x: node.x ?? 0, y: node.y ?? 0 });
|
|
1671
|
+
this.emitSelectionIntent('node', node.id, !!(e?.ctrlKey || e?.metaKey));
|
|
448
1672
|
}
|
|
449
|
-
|
|
1673
|
+
/** Returns a node's current position in the graph's local drawing space. */
|
|
1674
|
+
getNodePosition(id) {
|
|
1675
|
+
const node = this.simNodes.find((candidate) => candidate.id === id);
|
|
1676
|
+
if (!node || !Number.isFinite(node.x) || !Number.isFinite(node.y))
|
|
1677
|
+
return undefined;
|
|
1678
|
+
return { x: node.x, y: node.y };
|
|
1679
|
+
}
|
|
1680
|
+
onLinkClick(link, e) {
|
|
450
1681
|
const source = typeof link.source === 'object' ? link.source.id : String(link.source);
|
|
451
1682
|
const target = typeof link.target === 'object' ? link.target.id : String(link.target);
|
|
452
1683
|
this.emit('lyra-link-click', { source, target, ...(link.id ? { id: link.id } : {}) });
|
|
1684
|
+
this.emitSelectionIntent('link', this.linkKey(link), !!(e?.ctrlKey || e?.metaKey));
|
|
1685
|
+
}
|
|
1686
|
+
onNodeEnter(node, e) {
|
|
1687
|
+
if (this.isDragging || this.isPanning || this.isCameraTweening)
|
|
1688
|
+
return;
|
|
1689
|
+
e.currentTarget.setAttribute('data-hovered', '');
|
|
1690
|
+
this.emit('lyra-node-enter', { id: node.id });
|
|
1691
|
+
}
|
|
1692
|
+
onNodeLeave(node, e) {
|
|
1693
|
+
if (this.isDragging || this.isPanning || this.isCameraTweening)
|
|
1694
|
+
return;
|
|
1695
|
+
e.currentTarget.removeAttribute('data-hovered');
|
|
1696
|
+
this.emit('lyra-node-leave', { id: node.id });
|
|
1697
|
+
}
|
|
1698
|
+
onNodeDblClick(node, e) {
|
|
1699
|
+
// Stops the dblclick from also reaching the svg's own d3-zoom double-click-to-zoom-in
|
|
1700
|
+
// listener -- background double-click (not on a node) keeps that default behavior.
|
|
1701
|
+
e.stopPropagation();
|
|
1702
|
+
this.emit('lyra-node-expand', { id: node.id });
|
|
1703
|
+
}
|
|
1704
|
+
onLinkEnter(link, e) {
|
|
1705
|
+
if (this.isDragging || this.isPanning || this.isCameraTweening)
|
|
1706
|
+
return;
|
|
1707
|
+
e.currentTarget.setAttribute('data-hovered', '');
|
|
1708
|
+
const source = typeof link.source === 'object' ? link.source.id : String(link.source);
|
|
1709
|
+
const target = typeof link.target === 'object' ? link.target.id : String(link.target);
|
|
1710
|
+
this.emit('lyra-link-enter', { source, target, ...(link.id ? { id: link.id } : {}) });
|
|
1711
|
+
}
|
|
1712
|
+
onLinkLeave(link, e) {
|
|
1713
|
+
if (this.isDragging || this.isPanning || this.isCameraTweening)
|
|
1714
|
+
return;
|
|
1715
|
+
e.currentTarget.removeAttribute('data-hovered');
|
|
1716
|
+
const source = typeof link.source === 'object' ? link.source.id : String(link.source);
|
|
1717
|
+
const target = typeof link.target === 'object' ? link.target.id : String(link.target);
|
|
1718
|
+
this.emit('lyra-link-leave', { source, target, ...(link.id ? { id: link.id } : {}) });
|
|
453
1719
|
}
|
|
454
1720
|
nodeAccessibleText(node) {
|
|
455
|
-
|
|
1721
|
+
let text = node.accessibleLabel || node.label || node.id;
|
|
1722
|
+
const type = this.resolveNodeType(node);
|
|
1723
|
+
if (type)
|
|
1724
|
+
text = this.localize('graphTypedNode', undefined, { label: text, type: type.label });
|
|
1725
|
+
if (node.expandable)
|
|
1726
|
+
text = this.localize('graphExpandableItem', undefined, { item: text });
|
|
1727
|
+
return text;
|
|
456
1728
|
}
|
|
457
1729
|
linkAccessibleText(link) {
|
|
458
1730
|
if (link.accessibleLabel)
|
|
@@ -487,8 +1759,69 @@ export class LyraGraph extends LyraElement {
|
|
|
487
1759
|
y2: targetY - (dy / distance) * inset,
|
|
488
1760
|
};
|
|
489
1761
|
}
|
|
1762
|
+
/** World-space midpoint of a link, offset EDGE_LABEL_OFFSET_PX perpendicular to the segment
|
|
1763
|
+
* (horizontal, unrotated text — rotated edge-label text is a readability and RTL hazard). */
|
|
1764
|
+
edgeLabelPosition(link) {
|
|
1765
|
+
const { x1, y1, x2, y2 } = this.linkCoordinates(link);
|
|
1766
|
+
const dx = x2 - x1;
|
|
1767
|
+
const dy = y2 - y1;
|
|
1768
|
+
const len = Math.hypot(dx, dy);
|
|
1769
|
+
const mx = (x1 + x2) / 2;
|
|
1770
|
+
const my = (y1 + y2) / 2;
|
|
1771
|
+
if (len === 0)
|
|
1772
|
+
return { x: mx, y: my };
|
|
1773
|
+
return {
|
|
1774
|
+
x: mx + (-dy / len) * EDGE_LABEL_OFFSET_PX,
|
|
1775
|
+
y: my + (dx / len) * EDGE_LABEL_OFFSET_PX,
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
edgeLabelFontPx() {
|
|
1779
|
+
const raw = getComputedStyle(this).getPropertyValue('--lyra-font-size-2xs').trim();
|
|
1780
|
+
const parsed = parseFloat(raw);
|
|
1781
|
+
if (!Number.isFinite(parsed))
|
|
1782
|
+
return 10;
|
|
1783
|
+
// rem tokens are resolved relative to the root font-size; this is a decluttering heuristic,
|
|
1784
|
+
// not a pixel-perfect layout, so the standard 16px/rem approximation is sufficient.
|
|
1785
|
+
return raw.endsWith('rem') ? parsed * 16 : parsed;
|
|
1786
|
+
}
|
|
1787
|
+
edgeLabelWidth(text) {
|
|
1788
|
+
const cached = this.edgeLabelWidthCache.get(text);
|
|
1789
|
+
if (cached != null)
|
|
1790
|
+
return cached;
|
|
1791
|
+
const ctx = getScratchCtx();
|
|
1792
|
+
let width;
|
|
1793
|
+
if (ctx) {
|
|
1794
|
+
const fontFamily = getComputedStyle(this).getPropertyValue('--lyra-font').trim() || 'sans-serif';
|
|
1795
|
+
ctx.font = `${this.edgeLabelFontPx()}px ${fontFamily}`;
|
|
1796
|
+
width = ctx.measureText(text).width;
|
|
1797
|
+
}
|
|
1798
|
+
else {
|
|
1799
|
+
width = text.length * this.edgeLabelFontPx() * 0.6;
|
|
1800
|
+
}
|
|
1801
|
+
// Bound the cache under label churn (a streaming graph can cycle through unbounded distinct
|
|
1802
|
+
// label texts) -- Map iteration yields insertion order, so evicting the first key drops the
|
|
1803
|
+
// oldest-measured entry.
|
|
1804
|
+
if (this.edgeLabelWidthCache.size >= EDGE_LABEL_WIDTH_CACHE_MAX) {
|
|
1805
|
+
const oldest = this.edgeLabelWidthCache.keys().next().value;
|
|
1806
|
+
if (oldest !== undefined)
|
|
1807
|
+
this.edgeLabelWidthCache.delete(oldest);
|
|
1808
|
+
}
|
|
1809
|
+
this.edgeLabelWidthCache.set(text, width);
|
|
1810
|
+
return width;
|
|
1811
|
+
}
|
|
1812
|
+
/** Toggles `data-edge-labels-hidden` on the cached zoomed `<g>` when crossing `edgeLabelMinZoom`
|
|
1813
|
+
* -- called from the d3-zoom `'zoom'` handler (render-free, CSS hides `[part="link-label"]`
|
|
1814
|
+
* beneath the attribute) so this scales with every pan/zoom event without a Lit re-render. */
|
|
1815
|
+
updateEdgeLabelZoomGate(k) {
|
|
1816
|
+
if (!this.gEl)
|
|
1817
|
+
return;
|
|
1818
|
+
if (k < this.safeEdgeLabelMinZoom)
|
|
1819
|
+
this.gEl.setAttribute('data-edge-labels-hidden', '');
|
|
1820
|
+
else
|
|
1821
|
+
this.gEl.removeAttribute('data-edge-labels-hidden');
|
|
1822
|
+
}
|
|
490
1823
|
graphItemCount() {
|
|
491
|
-
return this.simNodes.length + this.simLinks.length;
|
|
1824
|
+
return this.simNodes.length + this.simLinks.length + this.visibleCommunities().length;
|
|
492
1825
|
}
|
|
493
1826
|
normalizedGraphItem(index = this.activeGraphItem) {
|
|
494
1827
|
const count = this.graphItemCount();
|
|
@@ -499,8 +1832,19 @@ export class LyraGraph extends LyraElement {
|
|
|
499
1832
|
const node = this.simNodes[index];
|
|
500
1833
|
return node ? this.localize('graphNode', undefined, { label: this.nodeAccessibleText(node) }) : '';
|
|
501
1834
|
}
|
|
502
|
-
const
|
|
503
|
-
|
|
1835
|
+
const linkIndex = index - this.simNodes.length;
|
|
1836
|
+
if (linkIndex < this.simLinks.length) {
|
|
1837
|
+
const link = this.simLinks[linkIndex];
|
|
1838
|
+
return link ? this.linkAccessibleText(link) : '';
|
|
1839
|
+
}
|
|
1840
|
+
const hullIndex = linkIndex - this.simLinks.length;
|
|
1841
|
+
const entry = this.visibleCommunities()[hullIndex];
|
|
1842
|
+
return entry
|
|
1843
|
+
? this.localize('graphCommunity', undefined, {
|
|
1844
|
+
label: entry.community.label ?? entry.community.id,
|
|
1845
|
+
count: entry.members.length,
|
|
1846
|
+
})
|
|
1847
|
+
: '';
|
|
504
1848
|
}
|
|
505
1849
|
graphItemAnnouncement(index) {
|
|
506
1850
|
return this.localize('graphItemAnnouncement', undefined, {
|
|
@@ -522,10 +1866,16 @@ export class LyraGraph extends LyraElement {
|
|
|
522
1866
|
this.activeGraphItem = normalized;
|
|
523
1867
|
this.graphLiveText = this.graphItemAnnouncement(normalized);
|
|
524
1868
|
void this.updateComplete.then(() => {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
1869
|
+
// renderer="canvas" has no [part="node"]/[part="link"]/[part="hull"] elements at all -- the
|
|
1870
|
+
// roving tab stop lives on the offscreen [part="cursor-item"] buttons instead (see render()),
|
|
1871
|
+
// in the same flat nodes-then-links-then-hulls order.
|
|
1872
|
+
const items = (this.renderer === 'canvas'
|
|
1873
|
+
? Array.from(this.renderRoot.querySelectorAll('[part="cursor-item"]'))
|
|
1874
|
+
: [
|
|
1875
|
+
...Array.from(this.renderRoot.querySelectorAll('[part="node"]')),
|
|
1876
|
+
...Array.from(this.renderRoot.querySelectorAll('[part="link"]')),
|
|
1877
|
+
...Array.from(this.renderRoot.querySelectorAll('[part="hull"]')),
|
|
1878
|
+
]);
|
|
529
1879
|
items[normalized]?.focus();
|
|
530
1880
|
});
|
|
531
1881
|
}
|
|
@@ -542,7 +1892,20 @@ export class LyraGraph extends LyraElement {
|
|
|
542
1892
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
543
1893
|
e.preventDefault();
|
|
544
1894
|
this.onGraphItemFocus(index);
|
|
545
|
-
activate();
|
|
1895
|
+
activate(e);
|
|
1896
|
+
if (index < this.simNodes.length) {
|
|
1897
|
+
const now = performance.now();
|
|
1898
|
+
if (this.lastKeyActivateIndex === index && now - this.lastKeyActivateTime <= EXPAND_KEY_INTERVAL_MS) {
|
|
1899
|
+
const node = this.simNodes[index];
|
|
1900
|
+
if (node)
|
|
1901
|
+
this.emit('lyra-node-expand', { id: node.id });
|
|
1902
|
+
this.lastKeyActivateIndex = null;
|
|
1903
|
+
}
|
|
1904
|
+
else {
|
|
1905
|
+
this.lastKeyActivateIndex = index;
|
|
1906
|
+
this.lastKeyActivateTime = now;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
546
1909
|
return;
|
|
547
1910
|
}
|
|
548
1911
|
const count = this.graphItemCount();
|
|
@@ -571,7 +1934,7 @@ export class LyraGraph extends LyraElement {
|
|
|
571
1934
|
<div part="base">
|
|
572
1935
|
<lyra-skeleton
|
|
573
1936
|
variant="rect"
|
|
574
|
-
style=${`--lyra-skeleton-w:${this.
|
|
1937
|
+
style=${`--lyra-skeleton-w:${this.safeWidth}px;--lyra-skeleton-h:${this.safeHeight}px`}
|
|
575
1938
|
></lyra-skeleton>
|
|
576
1939
|
</div>
|
|
577
1940
|
`;
|
|
@@ -579,6 +1942,99 @@ export class LyraGraph extends LyraElement {
|
|
|
579
1942
|
if (!this.nodes.length) {
|
|
580
1943
|
return html `<div part="base"><div part="empty">${this.localize('noData')}</div></div>`;
|
|
581
1944
|
}
|
|
1945
|
+
if (this.renderer === 'canvas') {
|
|
1946
|
+
return html `
|
|
1947
|
+
<div part="base">
|
|
1948
|
+
<canvas
|
|
1949
|
+
part="canvas"
|
|
1950
|
+
role="group"
|
|
1951
|
+
aria-label=${this.accessibleLabel ||
|
|
1952
|
+
this.localize('graphDiagram', undefined, {
|
|
1953
|
+
nodeCount: this.simNodes.length,
|
|
1954
|
+
linkCount: this.simLinks.length,
|
|
1955
|
+
})}
|
|
1956
|
+
tabindex=${this.graphItemCount() ? '-1' : '0'}
|
|
1957
|
+
></canvas>
|
|
1958
|
+
<div part="tooltip" hidden></div>
|
|
1959
|
+
<div part="live-region" class="sr-only" role="status" aria-live="polite" aria-atomic="true">
|
|
1960
|
+
${this.graphLiveText ||
|
|
1961
|
+
(this.normalizedGraphItem() >= 0 ? this.graphItemAnnouncement(this.normalizedGraphItem()) : '')}
|
|
1962
|
+
</div>
|
|
1963
|
+
<ul part="data-list" class="sr-only" aria-label=${this.localize('graphDataList')}>
|
|
1964
|
+
${this.simNodes.map((node) => html `<li>${this.localize('graphNode', undefined, { label: this.nodeAccessibleText(node) })}</li>`)}
|
|
1965
|
+
${this.simLinks.map((link) => html `<li>${this.linkAccessibleText(link)}</li>`)}
|
|
1966
|
+
${this.visibleCommunities().map((entry) => html `<li>${this.localize('graphCommunity', undefined, {
|
|
1967
|
+
label: entry.community.label ?? entry.community.id,
|
|
1968
|
+
count: entry.members.length,
|
|
1969
|
+
})}</li>`)}
|
|
1970
|
+
</ul>
|
|
1971
|
+
<div
|
|
1972
|
+
part="cursor-items"
|
|
1973
|
+
class="sr-only"
|
|
1974
|
+
@keydown=${(e) => {
|
|
1975
|
+
// Escape-clears-selection lives here (not on the canvas itself) because keydown from
|
|
1976
|
+
// a focused cursor-item bubbles up through this container, never through the canvas
|
|
1977
|
+
// -- the cursor-items list is canvas's sibling, not its descendant. Mirrors the svg
|
|
1978
|
+
// template's own root-level Escape handler; each cursor-item's own onGraphKeyDown()
|
|
1979
|
+
// (Enter/Space/arrows/Home/End) leaves Escape unhandled the same way a node/link
|
|
1980
|
+
// element does, so it bubbles here.
|
|
1981
|
+
if (e.key === 'Escape')
|
|
1982
|
+
this.clearSelection();
|
|
1983
|
+
}}
|
|
1984
|
+
>
|
|
1985
|
+
${this.simNodes.map((n, i) => html `
|
|
1986
|
+
<!-- hit-area-exempt: this button lives inside [part="cursor-items"]'s
|
|
1987
|
+
class="sr-only" (internal/a11y.ts's clip: rect(0 0 0 0) box) -- it's
|
|
1988
|
+
the offscreen keyboard-roving a11y virtual cursor described in this
|
|
1989
|
+
class's own doc comment, never a visible/pointer-clickable box, so
|
|
1990
|
+
the 40px hit-area floor (meant for on-screen tap targets) doesn't apply. -->
|
|
1991
|
+
<button
|
|
1992
|
+
part="cursor-item"
|
|
1993
|
+
tabindex=${this.normalizedGraphItem() === i ? '0' : '-1'}
|
|
1994
|
+
aria-label=${this.nodeAccessibleText(n)}
|
|
1995
|
+
@focus=${() => this.onGraphItemFocus(i)}
|
|
1996
|
+
@keydown=${(e) => this.onGraphKeyDown(e, i, (ev) => this.onNodeClick(n, ev))}
|
|
1997
|
+
@click=${(e) => this.onNodeClick(n, e)}
|
|
1998
|
+
></button>
|
|
1999
|
+
`)}
|
|
2000
|
+
${this.simLinks.map((l, li) => {
|
|
2001
|
+
const i = this.simNodes.length + li;
|
|
2002
|
+
return html `
|
|
2003
|
+
<!-- hit-area-exempt: see the node cursor-item above -- same offscreen
|
|
2004
|
+
sr-only virtual-cursor button, no visible/pointer-clickable box. -->
|
|
2005
|
+
<button
|
|
2006
|
+
part="cursor-item"
|
|
2007
|
+
tabindex=${this.normalizedGraphItem() === i ? '0' : '-1'}
|
|
2008
|
+
aria-label=${this.linkAccessibleText(l)}
|
|
2009
|
+
@focus=${() => this.onGraphItemFocus(i)}
|
|
2010
|
+
@keydown=${(e) => this.onGraphKeyDown(e, i, (ev) => this.onLinkClick(l, ev))}
|
|
2011
|
+
@click=${(e) => this.onLinkClick(l, e)}
|
|
2012
|
+
></button>
|
|
2013
|
+
`;
|
|
2014
|
+
})}
|
|
2015
|
+
${this.visibleCommunities().map((entry, hi) => {
|
|
2016
|
+
const i = this.simNodes.length + this.simLinks.length + hi;
|
|
2017
|
+
const label = this.localize('graphCommunity', undefined, {
|
|
2018
|
+
label: entry.community.label ?? entry.community.id,
|
|
2019
|
+
count: entry.members.length,
|
|
2020
|
+
});
|
|
2021
|
+
return html `
|
|
2022
|
+
<!-- hit-area-exempt: see the node cursor-item above -- same offscreen
|
|
2023
|
+
sr-only virtual-cursor button, no visible/pointer-clickable box. -->
|
|
2024
|
+
<button
|
|
2025
|
+
part="cursor-item"
|
|
2026
|
+
tabindex=${this.normalizedGraphItem() === i ? '0' : '-1'}
|
|
2027
|
+
aria-label=${label}
|
|
2028
|
+
@focus=${() => this.onGraphItemFocus(i)}
|
|
2029
|
+
@keydown=${(e) => this.onGraphKeyDown(e, i, () => this.onCommunityClick(entry.community))}
|
|
2030
|
+
@click=${() => this.onCommunityClick(entry.community)}
|
|
2031
|
+
></button>
|
|
2032
|
+
`;
|
|
2033
|
+
})}
|
|
2034
|
+
</div>
|
|
2035
|
+
</div>
|
|
2036
|
+
`;
|
|
2037
|
+
}
|
|
582
2038
|
return html `
|
|
583
2039
|
<div part="base">
|
|
584
2040
|
<svg
|
|
@@ -589,8 +2045,16 @@ export class LyraGraph extends LyraElement {
|
|
|
589
2045
|
nodeCount: this.simNodes.length,
|
|
590
2046
|
linkCount: this.simLinks.length,
|
|
591
2047
|
})}
|
|
592
|
-
viewBox="0 0 ${this.
|
|
2048
|
+
viewBox="0 0 ${this.safeWidth} ${this.safeHeight}"
|
|
593
2049
|
tabindex=${this.graphItemCount() ? '-1' : '0'}
|
|
2050
|
+
@click=${(e) => {
|
|
2051
|
+
if (e.target === e.currentTarget)
|
|
2052
|
+
this.clearSelection();
|
|
2053
|
+
}}
|
|
2054
|
+
@keydown=${(e) => {
|
|
2055
|
+
if (e.key === 'Escape')
|
|
2056
|
+
this.clearSelection();
|
|
2057
|
+
}}
|
|
594
2058
|
>
|
|
595
2059
|
<defs>
|
|
596
2060
|
<marker
|
|
@@ -607,28 +2071,63 @@ export class LyraGraph extends LyraElement {
|
|
|
607
2071
|
</marker>
|
|
608
2072
|
</defs>
|
|
609
2073
|
<g transform="">
|
|
2074
|
+
${this.visibleCommunities().map((entry, hullIndex) => {
|
|
2075
|
+
const itemIndex = this.simNodes.length + this.simLinks.length + hullIndex;
|
|
2076
|
+
const hull = this.communityHull(entry.members);
|
|
2077
|
+
const fill = sanitizeNodeColor(entry.community.color);
|
|
2078
|
+
const label = this.localize('graphCommunity', undefined, {
|
|
2079
|
+
label: entry.community.label ?? entry.community.id,
|
|
2080
|
+
count: entry.members.length,
|
|
2081
|
+
});
|
|
2082
|
+
return svg `<g>
|
|
2083
|
+
<path
|
|
2084
|
+
part="hull"
|
|
2085
|
+
role="button"
|
|
2086
|
+
tabindex=${this.normalizedGraphItem() === itemIndex ? '0' : '-1'}
|
|
2087
|
+
aria-label=${label}
|
|
2088
|
+
d=${hullPathD(hull)}
|
|
2089
|
+
style=${styleMap(fill ? { '--lyra-graph-hull-fill': fill } : {})}
|
|
2090
|
+
@click=${() => this.onCommunityClick(entry.community)}
|
|
2091
|
+
@focus=${() => this.onGraphItemFocus(itemIndex)}
|
|
2092
|
+
@keydown=${(e) => this.onGraphKeyDown(e, itemIndex, () => this.onCommunityClick(entry.community))}
|
|
2093
|
+
></path>
|
|
2094
|
+
<text part="community-label" aria-hidden="true" x=${hullCentroidX(hull)} y=${hullTopY(hull) - HULL_PADDING}>${entry.community.label ?? entry.community.id}</text>
|
|
2095
|
+
</g>`;
|
|
2096
|
+
})}
|
|
610
2097
|
${this.simLinks.map((l, linkIndex) => {
|
|
611
2098
|
const itemIndex = this.simNodes.length + linkIndex;
|
|
612
2099
|
const coordinates = this.linkCoordinates(l);
|
|
613
2100
|
const color = sanitizeNodeColor(l.color);
|
|
614
2101
|
const dash = normalizeLinkDash(l.dash);
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
2102
|
+
const labelPos = this.showEdgeLabels && l.label ? this.edgeLabelPosition(l) : undefined;
|
|
2103
|
+
const lineEl = svg `<line
|
|
2104
|
+
part="link"
|
|
2105
|
+
role="button"
|
|
2106
|
+
tabindex=${this.normalizedGraphItem() === itemIndex ? '0' : '-1'}
|
|
2107
|
+
aria-label=${this.linkAccessibleText(l)}
|
|
2108
|
+
aria-pressed=${this.selectionMode !== 'none' ? String(this.isSelected('link', this.linkKey(l))) : nothing}
|
|
2109
|
+
?data-selected=${this.isSelected('link', this.linkKey(l))}
|
|
2110
|
+
stroke-width=${l.width ?? 1.5}
|
|
2111
|
+
stroke-dasharray=${dash ?? nothing}
|
|
2112
|
+
marker-end=${l.directed ? `url(#${this.arrowMarkerId})` : nothing}
|
|
2113
|
+
style=${styleMap(color ? { '--lyra-link-color': color } : {})}
|
|
2114
|
+
x1=${coordinates.x1}
|
|
2115
|
+
y1=${coordinates.y1}
|
|
2116
|
+
x2=${coordinates.x2}
|
|
2117
|
+
y2=${coordinates.y2}
|
|
2118
|
+
@click=${(e) => this.onLinkClick(l, e)}
|
|
2119
|
+
@focus=${() => this.onGraphItemFocus(itemIndex)}
|
|
2120
|
+
@keydown=${(e) => this.onGraphKeyDown(e, itemIndex, (ev) => this.onLinkClick(l, ev))}
|
|
2121
|
+
@mouseenter=${(e) => this.onLinkEnter(l, e)}
|
|
2122
|
+
@mouseleave=${(e) => this.onLinkLeave(l, e)}
|
|
2123
|
+
>${l.description || l.label ? svg `<title>${l.description || l.label}</title>` : nothing}</line>`;
|
|
2124
|
+
// Only wrap in a <g> when a label will actually be drawn -- an unconditional wrapper
|
|
2125
|
+
// would change existing consumers' rendered link DOM (bare <line part="link">) even
|
|
2126
|
+
// when showEdgeLabels is never set, breaking the "existing usage renders byte-for-byte
|
|
2127
|
+
// identical output" contract this drawn-edge-label feature must preserve.
|
|
2128
|
+
return labelPos
|
|
2129
|
+
? svg `<g>${lineEl}<text part="link-label" aria-hidden="true" text-anchor="middle" x=${labelPos.x} y=${labelPos.y}>${l.label}</text></g>`
|
|
2130
|
+
: lineEl;
|
|
632
2131
|
})}
|
|
633
2132
|
${this.danglingLinks.map((l) => {
|
|
634
2133
|
const source = l.source;
|
|
@@ -644,27 +2143,67 @@ export class LyraGraph extends LyraElement {
|
|
|
644
2143
|
></line>`;
|
|
645
2144
|
})}
|
|
646
2145
|
${this.simNodes.map((n, nodeIndex) => {
|
|
647
|
-
const
|
|
2146
|
+
const shape = this.nodeShape(n);
|
|
2147
|
+
const fill = this.nodeFill(n);
|
|
648
2148
|
const itemIndex = nodeIndex;
|
|
2149
|
+
const tabindex = this.normalizedGraphItem() === itemIndex ? '0' : '-1';
|
|
2150
|
+
const label = this.nodeAccessibleText(n);
|
|
2151
|
+
// Unlike link styling below (which always renders style=${styleMap(...)}, even as
|
|
2152
|
+
// an empty string), an untyped/unknown-type node must render with NO style
|
|
2153
|
+
// attribute at all -- not just an empty one -- so hasAttribute('style') distinguishes
|
|
2154
|
+
// "no fill override" from "fill override present" for consumers/tests probing the DOM.
|
|
2155
|
+
const style = fill ? styleMap({ '--lyra-node-fill': fill }) : nothing;
|
|
2156
|
+
const title = n.description ? svg `<title>${n.description}</title>` : nothing;
|
|
2157
|
+
const shapeEl = shape === 'circle'
|
|
2158
|
+
? svg `<circle
|
|
2159
|
+
part="node"
|
|
2160
|
+
role="button"
|
|
2161
|
+
tabindex=${tabindex}
|
|
2162
|
+
aria-label=${label}
|
|
2163
|
+
aria-pressed=${this.selectionMode !== 'none' ? String(this.isSelected('node', n.id)) : nothing}
|
|
2164
|
+
?data-selected=${this.isSelected('node', n.id)}
|
|
2165
|
+
r=${this.nodeRadius(n)}
|
|
2166
|
+
cx=${n.x ?? 0}
|
|
2167
|
+
cy=${n.y ?? 0}
|
|
2168
|
+
style=${style}
|
|
2169
|
+
@click=${(e) => this.onNodeClick(n, e)}
|
|
2170
|
+
@dblclick=${(e) => this.onNodeDblClick(n, e)}
|
|
2171
|
+
@focus=${() => this.onGraphItemFocus(itemIndex)}
|
|
2172
|
+
@keydown=${(e) => this.onGraphKeyDown(e, itemIndex, (ev) => this.onNodeClick(n, ev))}
|
|
2173
|
+
@mouseenter=${(e) => this.onNodeEnter(n, e)}
|
|
2174
|
+
@mouseleave=${(e) => this.onNodeLeave(n, e)}
|
|
2175
|
+
>${title}</circle>`
|
|
2176
|
+
: svg `<path
|
|
2177
|
+
part="node"
|
|
2178
|
+
role="button"
|
|
2179
|
+
tabindex=${tabindex}
|
|
2180
|
+
aria-label=${label}
|
|
2181
|
+
aria-pressed=${this.selectionMode !== 'none' ? String(this.isSelected('node', n.id)) : nothing}
|
|
2182
|
+
?data-selected=${this.isSelected('node', n.id)}
|
|
2183
|
+
d=${shape === 'square' ? squarePath(this.nodeRadius(n)) : diamondPath(this.nodeRadius(n))}
|
|
2184
|
+
transform="translate(${n.x ?? 0},${n.y ?? 0})"
|
|
2185
|
+
style=${style}
|
|
2186
|
+
@click=${(e) => this.onNodeClick(n, e)}
|
|
2187
|
+
@dblclick=${(e) => this.onNodeDblClick(n, e)}
|
|
2188
|
+
@focus=${() => this.onGraphItemFocus(itemIndex)}
|
|
2189
|
+
@keydown=${(e) => this.onGraphKeyDown(e, itemIndex, (ev) => this.onNodeClick(n, ev))}
|
|
2190
|
+
@mouseenter=${(e) => this.onNodeEnter(n, e)}
|
|
2191
|
+
@mouseleave=${(e) => this.onNodeLeave(n, e)}
|
|
2192
|
+
>${title}</path>`;
|
|
649
2193
|
return svg `<g>
|
|
650
|
-
|
|
651
|
-
part="node"
|
|
652
|
-
role="button"
|
|
653
|
-
tabindex=${this.normalizedGraphItem() === itemIndex ? '0' : '-1'}
|
|
654
|
-
aria-label=${this.nodeAccessibleText(n)}
|
|
655
|
-
r=${this.nodeRadius(n)}
|
|
656
|
-
cx=${n.x ?? 0}
|
|
657
|
-
cy=${n.y ?? 0}
|
|
658
|
-
style=${styleMap(fill ? { '--lyra-node-fill': fill } : {})}
|
|
659
|
-
@click=${() => this.onNodeClick(n)}
|
|
660
|
-
@focus=${() => this.onGraphItemFocus(itemIndex)}
|
|
661
|
-
@keydown=${(e) => this.onGraphKeyDown(e, itemIndex, () => this.onNodeClick(n))}
|
|
662
|
-
>${n.description ? svg `<title>${n.description}</title>` : nothing}</circle>
|
|
2194
|
+
${shapeEl}
|
|
663
2195
|
${n.label
|
|
664
2196
|
? svg `<text part="label" aria-hidden="true" x=${(n.x ?? 0) + this.nodeRadius(n) + 2} y=${n.y ?? 0}>${n.label}</text>`
|
|
665
2197
|
: ''}
|
|
2198
|
+
${n.expandable
|
|
2199
|
+
? svg `<g part="expand-indicator" aria-hidden="true" transform="translate(${n.x ?? 0},${n.y ?? 0})">
|
|
2200
|
+
<circle r=${EXPAND_BADGE_R} cx=${this.nodeRadius(n) * EXPAND_BADGE_OFFSET} cy=${-this.nodeRadius(n) * EXPAND_BADGE_OFFSET}></circle>
|
|
2201
|
+
<path d="M ${this.nodeRadius(n) * EXPAND_BADGE_OFFSET - EXPAND_BADGE_R / 2} ${-this.nodeRadius(n) * EXPAND_BADGE_OFFSET} L ${this.nodeRadius(n) * EXPAND_BADGE_OFFSET + EXPAND_BADGE_R / 2} ${-this.nodeRadius(n) * EXPAND_BADGE_OFFSET} M ${this.nodeRadius(n) * EXPAND_BADGE_OFFSET} ${-this.nodeRadius(n) * EXPAND_BADGE_OFFSET - EXPAND_BADGE_R / 2} L ${this.nodeRadius(n) * EXPAND_BADGE_OFFSET} ${-this.nodeRadius(n) * EXPAND_BADGE_OFFSET + EXPAND_BADGE_R / 2}"></path>
|
|
2202
|
+
</g>`
|
|
2203
|
+
: ''}
|
|
666
2204
|
</g>`;
|
|
667
2205
|
})}
|
|
2206
|
+
<circle part="focus-halo" aria-hidden="true" hidden r="0" cx="0" cy="0"></circle>
|
|
668
2207
|
</g>
|
|
669
2208
|
</svg>
|
|
670
2209
|
<div part="live-region" class="sr-only" role="status" aria-live="polite" aria-atomic="true">
|
|
@@ -674,6 +2213,10 @@ export class LyraGraph extends LyraElement {
|
|
|
674
2213
|
<ul part="data-list" class="sr-only" aria-label=${this.localize('graphDataList')}>
|
|
675
2214
|
${this.simNodes.map((node) => html `<li>${this.localize('graphNode', undefined, { label: this.nodeAccessibleText(node) })}</li>`)}
|
|
676
2215
|
${this.simLinks.map((link) => html `<li>${this.linkAccessibleText(link)}</li>`)}
|
|
2216
|
+
${this.visibleCommunities().map((entry) => html `<li>${this.localize('graphCommunity', undefined, {
|
|
2217
|
+
label: entry.community.label ?? entry.community.id,
|
|
2218
|
+
count: entry.members.length,
|
|
2219
|
+
})}</li>`)}
|
|
677
2220
|
</ul>
|
|
678
2221
|
</div>
|
|
679
2222
|
`;
|
|
@@ -685,6 +2228,21 @@ __decorate([
|
|
|
685
2228
|
__decorate([
|
|
686
2229
|
property({ attribute: false })
|
|
687
2230
|
], LyraGraph.prototype, "links", void 0);
|
|
2231
|
+
__decorate([
|
|
2232
|
+
property({ attribute: false })
|
|
2233
|
+
], LyraGraph.prototype, "nodeTypes", void 0);
|
|
2234
|
+
__decorate([
|
|
2235
|
+
property({ attribute: false })
|
|
2236
|
+
], LyraGraph.prototype, "hiddenTypes", void 0);
|
|
2237
|
+
__decorate([
|
|
2238
|
+
property({ attribute: false })
|
|
2239
|
+
], LyraGraph.prototype, "communities", void 0);
|
|
2240
|
+
__decorate([
|
|
2241
|
+
property()
|
|
2242
|
+
], LyraGraph.prototype, "layout", void 0);
|
|
2243
|
+
__decorate([
|
|
2244
|
+
property()
|
|
2245
|
+
], LyraGraph.prototype, "renderer", void 0);
|
|
688
2246
|
__decorate([
|
|
689
2247
|
property({ type: Number })
|
|
690
2248
|
], LyraGraph.prototype, "width", void 0);
|
|
@@ -709,6 +2267,24 @@ __decorate([
|
|
|
709
2267
|
__decorate([
|
|
710
2268
|
property({ type: Number })
|
|
711
2269
|
], LyraGraph.prototype, "seed", void 0);
|
|
2270
|
+
__decorate([
|
|
2271
|
+
property({ type: Boolean, attribute: 'show-edge-labels' })
|
|
2272
|
+
], LyraGraph.prototype, "showEdgeLabels", void 0);
|
|
2273
|
+
__decorate([
|
|
2274
|
+
property({ type: Number, attribute: 'edge-label-min-zoom' })
|
|
2275
|
+
], LyraGraph.prototype, "edgeLabelMinZoom", void 0);
|
|
2276
|
+
__decorate([
|
|
2277
|
+
property({ attribute: 'focus-id' })
|
|
2278
|
+
], LyraGraph.prototype, "focusId", void 0);
|
|
2279
|
+
__decorate([
|
|
2280
|
+
property({ attribute: 'selection-mode' })
|
|
2281
|
+
], LyraGraph.prototype, "selectionMode", void 0);
|
|
2282
|
+
__decorate([
|
|
2283
|
+
property({ attribute: false })
|
|
2284
|
+
], LyraGraph.prototype, "selectedNodeIds", void 0);
|
|
2285
|
+
__decorate([
|
|
2286
|
+
property({ attribute: false })
|
|
2287
|
+
], LyraGraph.prototype, "selectedLinkIds", void 0);
|
|
712
2288
|
__decorate([
|
|
713
2289
|
state()
|
|
714
2290
|
], LyraGraph.prototype, "loading", void 0);
|
|
@@ -724,4 +2300,7 @@ __decorate([
|
|
|
724
2300
|
__decorate([
|
|
725
2301
|
state()
|
|
726
2302
|
], LyraGraph.prototype, "graphLiveText", void 0);
|
|
2303
|
+
__decorate([
|
|
2304
|
+
query('canvas')
|
|
2305
|
+
], LyraGraph.prototype, "canvasEl", void 0);
|
|
727
2306
|
//# sourceMappingURL=graph.class.js.map
|