@epilot/spark-ui 0.10.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/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +32 -0
- package/dist/chunk-DY84GLCh.cjs +29 -0
- package/dist/components/accordion.cjs +57 -0
- package/dist/components/accordion.cjs.map +1 -0
- package/dist/components/accordion.d.cts +44 -0
- package/dist/components/accordion.d.ts +44 -0
- package/dist/components/accordion.js +51 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert-dialog.cjs +137 -0
- package/dist/components/alert-dialog.cjs.map +1 -0
- package/dist/components/alert-dialog.d.cts +62 -0
- package/dist/components/alert-dialog.d.ts +62 -0
- package/dist/components/alert-dialog.js +123 -0
- package/dist/components/alert-dialog.js.map +1 -0
- package/dist/components/attachment.cjs +119 -0
- package/dist/components/attachment.cjs.map +1 -0
- package/dist/components/attachment.d.cts +65 -0
- package/dist/components/attachment.d.ts +65 -0
- package/dist/components/attachment.js +108 -0
- package/dist/components/attachment.js.map +1 -0
- package/dist/components/avatar.cjs +56 -0
- package/dist/components/avatar.cjs.map +1 -0
- package/dist/components/avatar.d.cts +26 -0
- package/dist/components/avatar.d.ts +26 -0
- package/dist/components/avatar.js +52 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.cjs +25 -0
- package/dist/components/badge.cjs.map +1 -0
- package/dist/components/badge.d.cts +16 -0
- package/dist/components/badge.d.ts +16 -0
- package/dist/components/badge.js +22 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/bar-chart.cjs +584 -0
- package/dist/components/bar-chart.cjs.map +1 -0
- package/dist/components/bar-chart.d.cts +102 -0
- package/dist/components/bar-chart.d.ts +102 -0
- package/dist/components/bar-chart.js +583 -0
- package/dist/components/bar-chart.js.map +1 -0
- package/dist/components/battery-progress-row.cjs +133 -0
- package/dist/components/battery-progress-row.cjs.map +1 -0
- package/dist/components/battery-progress-row.d.cts +77 -0
- package/dist/components/battery-progress-row.d.ts +77 -0
- package/dist/components/battery-progress-row.js +123 -0
- package/dist/components/battery-progress-row.js.map +1 -0
- package/dist/components/breadcrumbs.cjs +64 -0
- package/dist/components/breadcrumbs.cjs.map +1 -0
- package/dist/components/breadcrumbs.d.cts +42 -0
- package/dist/components/breadcrumbs.d.ts +42 -0
- package/dist/components/breadcrumbs.js +58 -0
- package/dist/components/breadcrumbs.js.map +1 -0
- package/dist/components/bubble.cjs +84 -0
- package/dist/components/bubble.cjs.map +1 -0
- package/dist/components/bubble.d.cts +39 -0
- package/dist/components/bubble.d.ts +39 -0
- package/dist/components/bubble.js +78 -0
- package/dist/components/bubble.js.map +1 -0
- package/dist/components/button-group.cjs +72 -0
- package/dist/components/button-group.cjs.map +1 -0
- package/dist/components/button-group.d.cts +29 -0
- package/dist/components/button-group.d.ts +29 -0
- package/dist/components/button-group.js +64 -0
- package/dist/components/button-group.js.map +1 -0
- package/dist/components/button.cjs +58 -0
- package/dist/components/button.cjs.map +1 -0
- package/dist/components/button.d.cts +29 -0
- package/dist/components/button.d.ts +29 -0
- package/dist/components/button.js +54 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/calendar.cjs +59 -0
- package/dist/components/calendar.cjs.map +1 -0
- package/dist/components/calendar.d.cts +20 -0
- package/dist/components/calendar.d.ts +20 -0
- package/dist/components/calendar.js +56 -0
- package/dist/components/calendar.js.map +1 -0
- package/dist/components/callout.cjs +95 -0
- package/dist/components/callout.cjs.map +1 -0
- package/dist/components/callout.d.cts +42 -0
- package/dist/components/callout.d.ts +42 -0
- package/dist/components/callout.js +88 -0
- package/dist/components/callout.js.map +1 -0
- package/dist/components/card.cjs +100 -0
- package/dist/components/card.cjs.map +1 -0
- package/dist/components/card.d.cts +34 -0
- package/dist/components/card.d.ts +34 -0
- package/dist/components/card.js +90 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/chart.cjs +110 -0
- package/dist/components/chart.cjs.map +1 -0
- package/dist/components/chart.d.cts +92 -0
- package/dist/components/chart.d.ts +92 -0
- package/dist/components/chart.js +104 -0
- package/dist/components/chart.js.map +1 -0
- package/dist/components/checkbox.cjs +44 -0
- package/dist/components/checkbox.cjs.map +1 -0
- package/dist/components/checkbox.d.cts +26 -0
- package/dist/components/checkbox.d.ts +26 -0
- package/dist/components/checkbox.js +41 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/circular-gauge.cjs +74 -0
- package/dist/components/circular-gauge.cjs.map +1 -0
- package/dist/components/circular-gauge.d.cts +37 -0
- package/dist/components/circular-gauge.d.ts +37 -0
- package/dist/components/circular-gauge.js +71 -0
- package/dist/components/circular-gauge.js.map +1 -0
- package/dist/components/day-of-week-picker.cjs +123 -0
- package/dist/components/day-of-week-picker.cjs.map +1 -0
- package/dist/components/day-of-week-picker.d.cts +39 -0
- package/dist/components/day-of-week-picker.d.ts +39 -0
- package/dist/components/day-of-week-picker.js +119 -0
- package/dist/components/day-of-week-picker.js.map +1 -0
- package/dist/components/device-card.cjs +118 -0
- package/dist/components/device-card.cjs.map +1 -0
- package/dist/components/device-card.d.cts +70 -0
- package/dist/components/device-card.d.ts +70 -0
- package/dist/components/device-card.js +104 -0
- package/dist/components/device-card.js.map +1 -0
- package/dist/components/dialog.cjs +115 -0
- package/dist/components/dialog.cjs.map +1 -0
- package/dist/components/dialog.d.cts +44 -0
- package/dist/components/dialog.d.ts +44 -0
- package/dist/components/dialog.js +103 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/donut-chart.cjs +70 -0
- package/dist/components/donut-chart.cjs.map +1 -0
- package/dist/components/donut-chart.d.cts +20 -0
- package/dist/components/donut-chart.d.ts +20 -0
- package/dist/components/donut-chart.js +69 -0
- package/dist/components/donut-chart.js.map +1 -0
- package/dist/components/drawer.cjs +95 -0
- package/dist/components/drawer.cjs.map +1 -0
- package/dist/components/drawer.d.cts +45 -0
- package/dist/components/drawer.d.ts +45 -0
- package/dist/components/drawer.js +83 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/dropdown-menu.cjs +165 -0
- package/dist/components/dropdown-menu.cjs.map +1 -0
- package/dist/components/dropdown-menu.d.cts +92 -0
- package/dist/components/dropdown-menu.d.ts +92 -0
- package/dist/components/dropdown-menu.js +148 -0
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/empty-state.cjs +41 -0
- package/dist/components/empty-state.cjs.map +1 -0
- package/dist/components/empty-state.d.cts +26 -0
- package/dist/components/empty-state.d.ts +26 -0
- package/dist/components/empty-state.js +41 -0
- package/dist/components/empty-state.js.map +1 -0
- package/dist/components/energy-bar-chart.cjs +23 -0
- package/dist/components/energy-bar-chart.cjs.map +1 -0
- package/dist/components/energy-bar-chart.d.cts +43 -0
- package/dist/components/energy-bar-chart.d.ts +43 -0
- package/dist/components/energy-bar-chart.js +22 -0
- package/dist/components/energy-bar-chart.js.map +1 -0
- package/dist/components/energy-breakdown.cjs +80 -0
- package/dist/components/energy-breakdown.cjs.map +1 -0
- package/dist/components/energy-breakdown.d.cts +24 -0
- package/dist/components/energy-breakdown.d.ts +24 -0
- package/dist/components/energy-breakdown.js +79 -0
- package/dist/components/energy-breakdown.js.map +1 -0
- package/dist/components/energy-history-chart.cjs +63 -0
- package/dist/components/energy-history-chart.cjs.map +1 -0
- package/dist/components/energy-history-chart.d.cts +64 -0
- package/dist/components/energy-history-chart.d.ts +64 -0
- package/dist/components/energy-history-chart.js +62 -0
- package/dist/components/energy-history-chart.js.map +1 -0
- package/dist/components/feed-in-hero.cjs +55 -0
- package/dist/components/feed-in-hero.cjs.map +1 -0
- package/dist/components/feed-in-hero.d.cts +32 -0
- package/dist/components/feed-in-hero.d.ts +32 -0
- package/dist/components/feed-in-hero.js +51 -0
- package/dist/components/feed-in-hero.js.map +1 -0
- package/dist/components/field.cjs +257 -0
- package/dist/components/field.cjs.map +1 -0
- package/dist/components/field.d.cts +103 -0
- package/dist/components/field.d.ts +103 -0
- package/dist/components/field.js +243 -0
- package/dist/components/field.js.map +1 -0
- package/dist/components/icon.cjs +35 -0
- package/dist/components/icon.cjs.map +1 -0
- package/dist/components/icon.d.cts +26 -0
- package/dist/components/icon.d.ts +26 -0
- package/dist/components/icon.js +32 -0
- package/dist/components/icon.js.map +1 -0
- package/dist/components/info-block.cjs +75 -0
- package/dist/components/info-block.cjs.map +1 -0
- package/dist/components/info-block.d.cts +19 -0
- package/dist/components/info-block.d.ts +19 -0
- package/dist/components/info-block.js +65 -0
- package/dist/components/info-block.js.map +1 -0
- package/dist/components/input-group.cjs +165 -0
- package/dist/components/input-group.cjs.map +1 -0
- package/dist/components/input-group.d.cts +27 -0
- package/dist/components/input-group.d.ts +27 -0
- package/dist/components/input-group.js +159 -0
- package/dist/components/input-group.js.map +1 -0
- package/dist/components/input-otp.cjs +112 -0
- package/dist/components/input-otp.cjs.map +1 -0
- package/dist/components/input-otp.d.cts +24 -0
- package/dist/components/input-otp.d.ts +24 -0
- package/dist/components/input-otp.js +111 -0
- package/dist/components/input-otp.js.map +1 -0
- package/dist/components/input.cjs +113 -0
- package/dist/components/input.cjs.map +1 -0
- package/dist/components/input.d.cts +14 -0
- package/dist/components/input.d.ts +14 -0
- package/dist/components/input.js +110 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/label.cjs +18 -0
- package/dist/components/label.cjs.map +1 -0
- package/dist/components/label.d.cts +10 -0
- package/dist/components/label.d.ts +10 -0
- package/dist/components/label.js +15 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/layout.cjs +14 -0
- package/dist/components/layout.cjs.map +1 -0
- package/dist/components/layout.d.cts +11 -0
- package/dist/components/layout.d.ts +12 -0
- package/dist/components/layout.js +14 -0
- package/dist/components/layout.js.map +1 -0
- package/dist/components/line-chart.cjs +538 -0
- package/dist/components/line-chart.cjs.map +1 -0
- package/dist/components/line-chart.d.cts +90 -0
- package/dist/components/line-chart.d.ts +90 -0
- package/dist/components/line-chart.js +536 -0
- package/dist/components/line-chart.js.map +1 -0
- package/dist/components/list.cjs +132 -0
- package/dist/components/list.cjs.map +1 -0
- package/dist/components/list.d.cts +71 -0
- package/dist/components/list.d.ts +71 -0
- package/dist/components/list.js +122 -0
- package/dist/components/list.js.map +1 -0
- package/dist/components/marker.cjs +52 -0
- package/dist/components/marker.cjs.map +1 -0
- package/dist/components/marker.d.cts +27 -0
- package/dist/components/marker.d.ts +27 -0
- package/dist/components/marker.js +46 -0
- package/dist/components/marker.js.map +1 -0
- package/dist/components/message-scroller.cjs +73 -0
- package/dist/components/message-scroller.cjs.map +1 -0
- package/dist/components/message-scroller.d.cts +38 -0
- package/dist/components/message-scroller.d.ts +38 -0
- package/dist/components/message-scroller.js +62 -0
- package/dist/components/message-scroller.js.map +1 -0
- package/dist/components/message.cjs +60 -0
- package/dist/components/message.cjs.map +1 -0
- package/dist/components/message.d.cts +35 -0
- package/dist/components/message.d.ts +35 -0
- package/dist/components/message.js +52 -0
- package/dist/components/message.js.map +1 -0
- package/dist/components/metering-row.cjs +42 -0
- package/dist/components/metering-row.cjs.map +1 -0
- package/dist/components/metering-row.d.cts +31 -0
- package/dist/components/metering-row.d.ts +31 -0
- package/dist/components/metering-row.js +38 -0
- package/dist/components/metering-row.js.map +1 -0
- package/dist/components/money-saved-block.cjs +86 -0
- package/dist/components/money-saved-block.cjs.map +1 -0
- package/dist/components/money-saved-block.d.cts +55 -0
- package/dist/components/money-saved-block.d.ts +55 -0
- package/dist/components/money-saved-block.js +79 -0
- package/dist/components/money-saved-block.js.map +1 -0
- package/dist/components/number-flow.cjs +44 -0
- package/dist/components/number-flow.cjs.map +1 -0
- package/dist/components/number-flow.d.cts +4 -0
- package/dist/components/number-flow.d.ts +4 -0
- package/dist/components/number-flow.js +42 -0
- package/dist/components/number-flow.js.map +1 -0
- package/dist/components/on-off-button.cjs +35 -0
- package/dist/components/on-off-button.cjs.map +1 -0
- package/dist/components/on-off-button.d.cts +18 -0
- package/dist/components/on-off-button.d.ts +18 -0
- package/dist/components/on-off-button.js +34 -0
- package/dist/components/on-off-button.js.map +1 -0
- package/dist/components/onboarding-layout.cjs +67 -0
- package/dist/components/onboarding-layout.cjs.map +1 -0
- package/dist/components/onboarding-layout.d.cts +44 -0
- package/dist/components/onboarding-layout.d.ts +44 -0
- package/dist/components/onboarding-layout.js +60 -0
- package/dist/components/onboarding-layout.js.map +1 -0
- package/dist/components/page-header.cjs +50 -0
- package/dist/components/page-header.cjs.map +1 -0
- package/dist/components/page-header.d.cts +25 -0
- package/dist/components/page-header.d.ts +25 -0
- package/dist/components/page-header.js +44 -0
- package/dist/components/page-header.js.map +1 -0
- package/dist/components/page-spinner.cjs +18 -0
- package/dist/components/page-spinner.cjs.map +1 -0
- package/dist/components/page-spinner.d.cts +12 -0
- package/dist/components/page-spinner.d.ts +12 -0
- package/dist/components/page-spinner.js +17 -0
- package/dist/components/page-spinner.js.map +1 -0
- package/dist/components/period-tabs.cjs +78 -0
- package/dist/components/period-tabs.cjs.map +1 -0
- package/dist/components/period-tabs.d.cts +50 -0
- package/dist/components/period-tabs.d.ts +50 -0
- package/dist/components/period-tabs.js +73 -0
- package/dist/components/period-tabs.js.map +1 -0
- package/dist/components/pill.cjs +62 -0
- package/dist/components/pill.cjs.map +1 -0
- package/dist/components/pill.d.cts +29 -0
- package/dist/components/pill.d.ts +29 -0
- package/dist/components/pill.js +59 -0
- package/dist/components/pill.js.map +1 -0
- package/dist/components/popover.cjs +62 -0
- package/dist/components/popover.cjs.map +1 -0
- package/dist/components/popover.d.cts +28 -0
- package/dist/components/popover.d.ts +28 -0
- package/dist/components/popover.js +56 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/power-history-chart.cjs +498 -0
- package/dist/components/power-history-chart.cjs.map +1 -0
- package/dist/components/power-history-chart.d.cts +71 -0
- package/dist/components/power-history-chart.d.ts +71 -0
- package/dist/components/power-history-chart.js +496 -0
- package/dist/components/power-history-chart.js.map +1 -0
- package/dist/components/power-history.cjs +114 -0
- package/dist/components/power-history.cjs.map +1 -0
- package/dist/components/power-history.d.cts +40 -0
- package/dist/components/power-history.d.ts +41 -0
- package/dist/components/power-history.js +114 -0
- package/dist/components/power-history.js.map +1 -0
- package/dist/components/power-network.cjs +562 -0
- package/dist/components/power-network.cjs.map +1 -0
- package/dist/components/power-network.d.cts +80 -0
- package/dist/components/power-network.d.ts +80 -0
- package/dist/components/power-network.js +556 -0
- package/dist/components/power-network.js.map +1 -0
- package/dist/components/progress.cjs +34 -0
- package/dist/components/progress.cjs.map +1 -0
- package/dist/components/progress.d.cts +17 -0
- package/dist/components/progress.d.ts +17 -0
- package/dist/components/progress.js +31 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio-card-group.cjs +94 -0
- package/dist/components/radio-card-group.cjs.map +1 -0
- package/dist/components/radio-card-group.d.cts +21 -0
- package/dist/components/radio-card-group.d.ts +21 -0
- package/dist/components/radio-card-group.js +90 -0
- package/dist/components/radio-card-group.js.map +1 -0
- package/dist/components/radio.cjs +41 -0
- package/dist/components/radio.cjs.map +1 -0
- package/dist/components/radio.d.cts +32 -0
- package/dist/components/radio.d.ts +32 -0
- package/dist/components/radio.js +37 -0
- package/dist/components/radio.js.map +1 -0
- package/dist/components/reparent.cjs +55 -0
- package/dist/components/reparent.cjs.map +1 -0
- package/dist/components/reparent.d.cts +28 -0
- package/dist/components/reparent.d.ts +28 -0
- package/dist/components/reparent.js +49 -0
- package/dist/components/reparent.js.map +1 -0
- package/dist/components/sankey-chart.cjs +187 -0
- package/dist/components/sankey-chart.cjs.map +1 -0
- package/dist/components/sankey-chart.d.cts +66 -0
- package/dist/components/sankey-chart.d.ts +66 -0
- package/dist/components/sankey-chart.js +185 -0
- package/dist/components/sankey-chart.js.map +1 -0
- package/dist/components/schedule-editor.cjs +82 -0
- package/dist/components/schedule-editor.cjs.map +1 -0
- package/dist/components/schedule-editor.d.cts +25 -0
- package/dist/components/schedule-editor.d.ts +25 -0
- package/dist/components/schedule-editor.js +72 -0
- package/dist/components/schedule-editor.js.map +1 -0
- package/dist/components/schedule-list.cjs +110 -0
- package/dist/components/schedule-list.cjs.map +1 -0
- package/dist/components/schedule-list.d.cts +29 -0
- package/dist/components/schedule-list.d.ts +29 -0
- package/dist/components/schedule-list.js +99 -0
- package/dist/components/schedule-list.js.map +1 -0
- package/dist/components/scroll-area.cjs +53 -0
- package/dist/components/scroll-area.cjs.map +1 -0
- package/dist/components/scroll-area.d.cts +24 -0
- package/dist/components/scroll-area.d.ts +24 -0
- package/dist/components/scroll-area.js +44 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/segmented-control.cjs +44 -0
- package/dist/components/segmented-control.cjs.map +1 -0
- package/dist/components/segmented-control.d.cts +32 -0
- package/dist/components/segmented-control.d.ts +32 -0
- package/dist/components/segmented-control.js +40 -0
- package/dist/components/segmented-control.js.map +1 -0
- package/dist/components/select.cjs +136 -0
- package/dist/components/select.cjs.map +1 -0
- package/dist/components/select.d.cts +62 -0
- package/dist/components/select.d.ts +62 -0
- package/dist/components/select.js +124 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/separator.cjs +38 -0
- package/dist/components/separator.cjs.map +1 -0
- package/dist/components/separator.d.cts +13 -0
- package/dist/components/separator.d.ts +13 -0
- package/dist/components/separator.js +35 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/series-legend.cjs +38 -0
- package/dist/components/series-legend.cjs.map +1 -0
- package/dist/components/series-legend.d.cts +29 -0
- package/dist/components/series-legend.d.ts +29 -0
- package/dist/components/series-legend.js +37 -0
- package/dist/components/series-legend.js.map +1 -0
- package/dist/components/sheet.cjs +102 -0
- package/dist/components/sheet.cjs.map +1 -0
- package/dist/components/sheet.d.cts +45 -0
- package/dist/components/sheet.d.ts +45 -0
- package/dist/components/sheet.js +90 -0
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/skeleton.cjs +23 -0
- package/dist/components/skeleton.cjs.map +1 -0
- package/dist/components/skeleton.d.cts +23 -0
- package/dist/components/skeleton.d.ts +23 -0
- package/dist/components/skeleton.js +21 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.cjs +263 -0
- package/dist/components/slider.cjs.map +1 -0
- package/dist/components/slider.d.cts +136 -0
- package/dist/components/slider.d.ts +136 -0
- package/dist/components/slider.js +253 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/smart-toggle-button.cjs +27 -0
- package/dist/components/smart-toggle-button.cjs.map +1 -0
- package/dist/components/smart-toggle-button.d.cts +16 -0
- package/dist/components/smart-toggle-button.d.ts +16 -0
- package/dist/components/smart-toggle-button.js +26 -0
- package/dist/components/smart-toggle-button.js.map +1 -0
- package/dist/components/solar-forecast-chart.cjs +109 -0
- package/dist/components/solar-forecast-chart.cjs.map +1 -0
- package/dist/components/solar-forecast-chart.d.cts +77 -0
- package/dist/components/solar-forecast-chart.d.ts +77 -0
- package/dist/components/solar-forecast-chart.js +104 -0
- package/dist/components/solar-forecast-chart.js.map +1 -0
- package/dist/components/sortable-list.cjs +68 -0
- package/dist/components/sortable-list.cjs.map +1 -0
- package/dist/components/sortable-list.d.cts +45 -0
- package/dist/components/sortable-list.d.ts +45 -0
- package/dist/components/sortable-list.js +67 -0
- package/dist/components/sortable-list.js.map +1 -0
- package/dist/components/spinner.cjs +42 -0
- package/dist/components/spinner.cjs.map +1 -0
- package/dist/components/spinner.d.cts +15 -0
- package/dist/components/spinner.d.ts +15 -0
- package/dist/components/spinner.js +39 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/stat-card.cjs +57 -0
- package/dist/components/stat-card.cjs.map +1 -0
- package/dist/components/stat-card.d.cts +34 -0
- package/dist/components/stat-card.d.ts +34 -0
- package/dist/components/stat-card.js +50 -0
- package/dist/components/stat-card.js.map +1 -0
- package/dist/components/stepper.cjs +79 -0
- package/dist/components/stepper.cjs.map +1 -0
- package/dist/components/stepper.d.cts +33 -0
- package/dist/components/stepper.d.ts +33 -0
- package/dist/components/stepper.js +76 -0
- package/dist/components/stepper.js.map +1 -0
- package/dist/components/switch.cjs +26 -0
- package/dist/components/switch.cjs.map +1 -0
- package/dist/components/switch.d.cts +32 -0
- package/dist/components/switch.d.ts +32 -0
- package/dist/components/switch.js +25 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/tabs.cjs +178 -0
- package/dist/components/tabs.cjs.map +1 -0
- package/dist/components/tabs.d.cts +44 -0
- package/dist/components/tabs.d.ts +44 -0
- package/dist/components/tabs.js +170 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.cjs +128 -0
- package/dist/components/textarea.cjs.map +1 -0
- package/dist/components/textarea.d.cts +15 -0
- package/dist/components/textarea.d.ts +15 -0
- package/dist/components/textarea.js +125 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/theme.cjs +122 -0
- package/dist/components/theme.cjs.map +1 -0
- package/dist/components/theme.d.cts +36 -0
- package/dist/components/theme.d.ts +36 -0
- package/dist/components/theme.js +118 -0
- package/dist/components/theme.js.map +1 -0
- package/dist/components/thumbnail.cjs +54 -0
- package/dist/components/thumbnail.cjs.map +1 -0
- package/dist/components/thumbnail.d.cts +33 -0
- package/dist/components/thumbnail.d.ts +33 -0
- package/dist/components/thumbnail.js +51 -0
- package/dist/components/thumbnail.js.map +1 -0
- package/dist/components/time-picker.cjs +105 -0
- package/dist/components/time-picker.cjs.map +1 -0
- package/dist/components/time-picker.d.cts +43 -0
- package/dist/components/time-picker.d.ts +43 -0
- package/dist/components/time-picker.js +101 -0
- package/dist/components/time-picker.js.map +1 -0
- package/dist/components/toast.cjs +192 -0
- package/dist/components/toast.cjs.map +1 -0
- package/dist/components/toast.d.cts +59 -0
- package/dist/components/toast.d.ts +59 -0
- package/dist/components/toast.js +188 -0
- package/dist/components/toast.js.map +1 -0
- package/dist/components/tooltip.cjs +85 -0
- package/dist/components/tooltip.cjs.map +1 -0
- package/dist/components/tooltip.d.cts +48 -0
- package/dist/components/tooltip.d.ts +48 -0
- package/dist/components/tooltip.js +77 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/typography.cjs +51 -0
- package/dist/components/typography.cjs.map +1 -0
- package/dist/components/typography.d.cts +30 -0
- package/dist/components/typography.d.ts +30 -0
- package/dist/components/typography.js +45 -0
- package/dist/components/typography.js.map +1 -0
- package/dist/generate-radix-colors-Bw-RYaV4.d.cts +33 -0
- package/dist/generate-radix-colors-Bw-RYaV4.d.ts +33 -0
- package/dist/hooks/use-chart-zoom.cjs +236 -0
- package/dist/hooks/use-chart-zoom.cjs.map +1 -0
- package/dist/hooks/use-chart-zoom.d.cts +53 -0
- package/dist/hooks/use-chart-zoom.d.ts +53 -0
- package/dist/hooks/use-chart-zoom.js +234 -0
- package/dist/hooks/use-chart-zoom.js.map +1 -0
- package/dist/hooks/use-container-width.cjs +21 -0
- package/dist/hooks/use-container-width.cjs.map +1 -0
- package/dist/hooks/use-container-width.d.cts +7 -0
- package/dist/hooks/use-container-width.d.ts +7 -0
- package/dist/hooks/use-container-width.js +20 -0
- package/dist/hooks/use-container-width.js.map +1 -0
- package/dist/hooks/use-reduced-motion.cjs +21 -0
- package/dist/hooks/use-reduced-motion.cjs.map +1 -0
- package/dist/hooks/use-reduced-motion.d.cts +7 -0
- package/dist/hooks/use-reduced-motion.d.ts +7 -0
- package/dist/hooks/use-reduced-motion.js +20 -0
- package/dist/hooks/use-reduced-motion.js.map +1 -0
- package/dist/icons/index.cjs +7 -0
- package/dist/icons/index.d.cts +4 -0
- package/dist/icons/index.d.ts +4 -0
- package/dist/icons/index.js +3 -0
- package/dist/icons/material-symbol.cjs +104 -0
- package/dist/icons/material-symbol.cjs.map +1 -0
- package/dist/icons/material-symbol.d.cts +21 -0
- package/dist/icons/material-symbol.d.ts +21 -0
- package/dist/icons/material-symbol.js +100 -0
- package/dist/icons/material-symbol.js.map +1 -0
- package/dist/lib/accent-colors.cjs +14 -0
- package/dist/lib/accent-colors.cjs.map +1 -0
- package/dist/lib/accent-colors.d.cts +8 -0
- package/dist/lib/accent-colors.d.ts +8 -0
- package/dist/lib/accent-colors.js +13 -0
- package/dist/lib/accent-colors.js.map +1 -0
- package/dist/lib/accent-theme.cjs +130 -0
- package/dist/lib/accent-theme.cjs.map +1 -0
- package/dist/lib/accent-theme.d.cts +35 -0
- package/dist/lib/accent-theme.d.ts +35 -0
- package/dist/lib/accent-theme.js +122 -0
- package/dist/lib/accent-theme.js.map +1 -0
- package/dist/lib/generate-radix-colors.cjs +364 -0
- package/dist/lib/generate-radix-colors.cjs.map +1 -0
- package/dist/lib/generate-radix-colors.d.cts +4 -0
- package/dist/lib/generate-radix-colors.d.ts +4 -0
- package/dist/lib/generate-radix-colors.js +357 -0
- package/dist/lib/generate-radix-colors.js.map +1 -0
- package/dist/lib/input-box-variants.cjs +30 -0
- package/dist/lib/input-box-variants.cjs.map +1 -0
- package/dist/lib/input-box-variants.d.cts +10 -0
- package/dist/lib/input-box-variants.d.ts +10 -0
- package/dist/lib/input-box-variants.js +28 -0
- package/dist/lib/input-box-variants.js.map +1 -0
- package/dist/lib/theme-types.cjs +1 -0
- package/dist/lib/theme-types.d.cts +4 -0
- package/dist/lib/theme-types.d.ts +4 -0
- package/dist/lib/theme-types.js +2 -0
- package/dist/lib/tones.cjs +14 -0
- package/dist/lib/tones.cjs.map +1 -0
- package/dist/lib/tones.d.cts +8 -0
- package/dist/lib/tones.d.ts +8 -0
- package/dist/lib/tones.js +13 -0
- package/dist/lib/tones.js.map +1 -0
- package/dist/number-flow-Bch81ixZ.d.cts +14 -0
- package/dist/number-flow-Bch81ixZ.d.ts +14 -0
- package/dist/styles/index.css +447 -0
- package/dist/styles/internal.css +5 -0
- package/dist/styles/material-symbol.css +22 -0
- package/dist/styles/spark-default.css +980 -0
- package/dist/styles/theme.css +623 -0
- package/dist/styles/utilities.css +557 -0
- package/dist/theme-types-8wjgiNA_.d.cts +29 -0
- package/dist/theme-types-8wjgiNA_.d.ts +29 -0
- package/dist/utils/build-sankey-nodes.cjs +72 -0
- package/dist/utils/build-sankey-nodes.cjs.map +1 -0
- package/dist/utils/build-sankey-nodes.d.cts +27 -0
- package/dist/utils/build-sankey-nodes.d.ts +27 -0
- package/dist/utils/build-sankey-nodes.js +71 -0
- package/dist/utils/build-sankey-nodes.js.map +1 -0
- package/dist/utils/chars.cjs +18 -0
- package/dist/utils/chars.cjs.map +1 -0
- package/dist/utils/chars.d.cts +10 -0
- package/dist/utils/chars.d.ts +10 -0
- package/dist/utils/chars.js +14 -0
- package/dist/utils/chars.js.map +1 -0
- package/dist/utils/chart-scale.cjs +54 -0
- package/dist/utils/chart-scale.cjs.map +1 -0
- package/dist/utils/chart-scale.d.cts +29 -0
- package/dist/utils/chart-scale.d.ts +29 -0
- package/dist/utils/chart-scale.js +51 -0
- package/dist/utils/chart-scale.js.map +1 -0
- package/dist/utils/chart-time-ticks.cjs +35 -0
- package/dist/utils/chart-time-ticks.cjs.map +1 -0
- package/dist/utils/chart-time-ticks.d.cts +7 -0
- package/dist/utils/chart-time-ticks.d.ts +7 -0
- package/dist/utils/chart-time-ticks.js +34 -0
- package/dist/utils/chart-time-ticks.js.map +1 -0
- package/dist/utils/chart-zoom.cjs +84 -0
- package/dist/utils/chart-zoom.cjs.map +1 -0
- package/dist/utils/chart-zoom.d.cts +14 -0
- package/dist/utils/chart-zoom.d.ts +14 -0
- package/dist/utils/chart-zoom.js +77 -0
- package/dist/utils/chart-zoom.js.map +1 -0
- package/dist/utils/cn.cjs +9 -0
- package/dist/utils/cn.d.cts +4 -0
- package/dist/utils/cn.d.ts +4 -0
- package/dist/utils/cn.js +3 -0
- package/dist/utils/date-mask.cjs +45 -0
- package/dist/utils/date-mask.cjs.map +1 -0
- package/dist/utils/date-mask.d.cts +17 -0
- package/dist/utils/date-mask.d.ts +17 -0
- package/dist/utils/date-mask.js +41 -0
- package/dist/utils/date-mask.js.map +1 -0
- package/dist/utils/format.cjs +57 -0
- package/dist/utils/format.cjs.map +1 -0
- package/dist/utils/format.d.cts +23 -0
- package/dist/utils/format.d.ts +23 -0
- package/dist/utils/format.js +47 -0
- package/dist/utils/format.js.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
5
|
+
//#region src/components/reparent.tsx
|
|
6
|
+
const supportsMoveBefore = typeof Element !== "undefined" && "moveBefore" in Element.prototype;
|
|
7
|
+
function useReparent() {
|
|
8
|
+
const [host, setHost] = React$1.useState(null);
|
|
9
|
+
React$1.useEffect(() => {
|
|
10
|
+
const el = document.createElement("div");
|
|
11
|
+
el.style.display = "contents";
|
|
12
|
+
setHost(el);
|
|
13
|
+
return () => el.remove();
|
|
14
|
+
}, []);
|
|
15
|
+
const park = React$1.useCallback(() => {
|
|
16
|
+
if (supportsMoveBefore && host?.isConnected) {
|
|
17
|
+
host.style.display = "none";
|
|
18
|
+
document.body.moveBefore(host, null);
|
|
19
|
+
}
|
|
20
|
+
}, [host]);
|
|
21
|
+
return React$1.useMemo(() => ({
|
|
22
|
+
host,
|
|
23
|
+
park
|
|
24
|
+
}), [host, park]);
|
|
25
|
+
}
|
|
26
|
+
function ReparentContent({ handle, children }) {
|
|
27
|
+
if (!handle.host) return null;
|
|
28
|
+
return createPortal(children, handle.host);
|
|
29
|
+
}
|
|
30
|
+
function ReparentSlot({ handle, ...props }) {
|
|
31
|
+
const ref = React$1.useRef(null);
|
|
32
|
+
const host = handle.host;
|
|
33
|
+
React$1.useLayoutEffect(() => {
|
|
34
|
+
const slot = ref.current;
|
|
35
|
+
if (!slot || !host) return;
|
|
36
|
+
host.style.display = "contents";
|
|
37
|
+
if (supportsMoveBefore && host.isConnected) slot.moveBefore(host, null);
|
|
38
|
+
else slot.appendChild(host);
|
|
39
|
+
}, [host]);
|
|
40
|
+
return /* @__PURE__ */ jsx("div", {
|
|
41
|
+
"data-slot": "reparent-slot",
|
|
42
|
+
ref,
|
|
43
|
+
...props
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { ReparentContent, ReparentSlot, supportsMoveBefore, useReparent };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=reparent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reparent.js","names":["React"],"sources":["../../src/components/reparent.tsx"],"sourcesContent":["import * as React from 'react'\nimport { createPortal } from 'react-dom'\n\n// moveBefore ships in Chrome/Edge 133+, Firefox 144+; Safari has no state-preserving move\nconst supportsMoveBefore =\n typeof Element !== 'undefined' && 'moveBefore' in Element.prototype\n\ntype MovableElement = Element & {\n moveBefore: (node: Node, child: Node | null) => void\n}\n\ninterface ReparentHandle {\n host: HTMLElement | null\n park: () => void\n}\n\n// host created after mount so server and client hydrate the same (empty) markup\nfunction useReparent(): ReparentHandle {\n const [host, setHost] = React.useState<HTMLElement | null>(null)\n React.useEffect(() => {\n const el = document.createElement('div')\n el.style.display = 'contents'\n setHost(el)\n return () => el.remove()\n }, [])\n const park = React.useCallback(() => {\n if (supportsMoveBefore && host?.isConnected) {\n host.style.display = 'none'\n ;(document.body as unknown as MovableElement).moveBefore(host, null)\n }\n }, [host])\n return React.useMemo(() => ({ host, park }), [host, park])\n}\n\nfunction ReparentContent({\n handle,\n children,\n}: {\n handle: ReparentHandle\n children: React.ReactNode\n}) {\n if (!handle.host) return null\n return createPortal(children, handle.host)\n}\n\ninterface ReparentSlotProps extends React.ComponentProps<'div'> {\n handle: ReparentHandle\n}\n\nfunction ReparentSlot({ handle, ...props }: ReparentSlotProps) {\n const ref = React.useRef<HTMLDivElement>(null)\n const host = handle.host\n React.useLayoutEffect(() => {\n const slot = ref.current\n if (!slot || !host) return\n host.style.display = 'contents'\n if (supportsMoveBefore && host.isConnected) {\n ;(slot as unknown as MovableElement).moveBefore(host, null)\n } else {\n slot.appendChild(host)\n }\n }, [host])\n return <div data-slot=\"reparent-slot\" ref={ref} {...props} />\n}\n\nexport { ReparentContent, ReparentSlot, supportsMoveBefore, useReparent }\nexport type { ReparentHandle, ReparentSlotProps }\n"],"mappings":";;;;;AAIA,MAAM,qBACJ,OAAO,YAAY,eAAe,gBAAgB,QAAQ;AAY5D,SAAS,cAA8B;CACrC,MAAM,CAAC,MAAM,WAAWA,QAAM,SAA6B,IAAI;CAC/D,QAAM,gBAAgB;EACpB,MAAM,KAAK,SAAS,cAAc,KAAK;EACvC,GAAG,MAAM,UAAU;EACnB,QAAQ,EAAE;EACV,aAAa,GAAG,OAAO;CACzB,GAAG,CAAC,CAAC;CACL,MAAM,OAAOA,QAAM,kBAAkB;EACnC,IAAI,sBAAsB,MAAM,aAAa;GAC3C,KAAK,MAAM,UAAU;GACpB,SAAU,KAAmC,WAAW,MAAM,IAAI;EACrE;CACF,GAAG,CAAC,IAAI,CAAC;CACT,OAAOA,QAAM,eAAe;EAAE;EAAM;CAAK,IAAI,CAAC,MAAM,IAAI,CAAC;AAC3D;AAEA,SAAS,gBAAgB,EACvB,QACA,YAIC;CACD,IAAI,CAAC,OAAO,MAAM,OAAO;CACzB,OAAO,aAAa,UAAU,OAAO,IAAI;AAC3C;AAMA,SAAS,aAAa,EAAE,QAAQ,GAAG,SAA4B;CAC7D,MAAM,MAAMA,QAAM,OAAuB,IAAI;CAC7C,MAAM,OAAO,OAAO;CACpB,QAAM,sBAAsB;EAC1B,MAAM,OAAO,IAAI;EACjB,IAAI,CAAC,QAAQ,CAAC,MAAM;EACpB,KAAK,MAAM,UAAU;EACrB,IAAI,sBAAsB,KAAK,aAC5B,KAAoC,WAAW,MAAM,IAAI;OAE1D,KAAK,YAAY,IAAI;CAEzB,GAAG,CAAC,IAAI,CAAC;CACT,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAqB;EAAK,GAAI;CAAQ,CAAA;AAC9D"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const require_components_typography = require("./typography.cjs");
|
|
4
|
+
const require_components_number_flow = require("./number-flow.cjs");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
+
let _visx_group = require("@visx/group");
|
|
8
|
+
let _visx_sankey = require("@visx/sankey");
|
|
9
|
+
let cnfast = require("cnfast");
|
|
10
|
+
//#region src/components/sankey-chart.tsx
|
|
11
|
+
const SANKEY_CATEGORY_COLORS = {
|
|
12
|
+
solar: "var(--orange-a9)",
|
|
13
|
+
battery: "var(--green-a9)",
|
|
14
|
+
grid: "var(--blue-9)",
|
|
15
|
+
gridFeedIn: "var(--blue-7)",
|
|
16
|
+
home: "var(--spark-9)",
|
|
17
|
+
floor: "var(--neutral-a9)",
|
|
18
|
+
device: "var(--neutral-a8)"
|
|
19
|
+
};
|
|
20
|
+
const DEFAULT_HEIGHT = 260;
|
|
21
|
+
const DEFAULT_NODE_WIDTH = 12;
|
|
22
|
+
const DEFAULT_NODE_PADDING = 10;
|
|
23
|
+
const DEFAULT_LABEL_PADDING = 96;
|
|
24
|
+
const LEFT_INSET = 4;
|
|
25
|
+
const TOP_INSET = 8;
|
|
26
|
+
const LABEL_GAP = 8;
|
|
27
|
+
/** Approx. cap/ascender height of the node name above its alphabetic baseline. */
|
|
28
|
+
const LABEL_NAME_HEIGHT = 11;
|
|
29
|
+
/** Vertical offset of the value box relative to the name baseline. Negative pulls
|
|
30
|
+
* the value up toward the name to tighten the gap between them. */
|
|
31
|
+
const LABEL_VALUE_GAP = -4;
|
|
32
|
+
/** Height of the value box rendered below the node name. */
|
|
33
|
+
const VALUE_HEIGHT = 16;
|
|
34
|
+
const DEFAULT_COLOR = "var(--neutral-a9)";
|
|
35
|
+
function resolveNodeColor(node, categoryColors, defaultColor) {
|
|
36
|
+
if (node.color) return node.color;
|
|
37
|
+
if (node.category && categoryColors?.[node.category]) return categoryColors[node.category];
|
|
38
|
+
return defaultColor;
|
|
39
|
+
}
|
|
40
|
+
function SankeyChart({ nodes, links, categoryColors = SANKEY_CATEGORY_COLORS, defaultColor = DEFAULT_COLOR, valueSuffix, valueFormat, height = DEFAULT_HEIGHT, nodeWidth = DEFAULT_NODE_WIDTH, nodePadding = DEFAULT_NODE_PADDING, labelPadding = DEFAULT_LABEL_PADDING, keepAtDepthIds, title, className }) {
|
|
41
|
+
const containerRef = (0, react.useRef)(null);
|
|
42
|
+
const [width, setWidth] = (0, react.useState)(0);
|
|
43
|
+
(0, react.useEffect)(() => {
|
|
44
|
+
const element = containerRef.current;
|
|
45
|
+
if (!element) return;
|
|
46
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
47
|
+
const entry = entries[0];
|
|
48
|
+
if (!entry) return;
|
|
49
|
+
setWidth(entry.contentRect.width);
|
|
50
|
+
});
|
|
51
|
+
resizeObserver.observe(element);
|
|
52
|
+
return () => resizeObserver.disconnect();
|
|
53
|
+
}, []);
|
|
54
|
+
const nodeIds = (0, react.useMemo)(() => new Set(nodes.map((node) => node.id)), [nodes]);
|
|
55
|
+
const visibleLinks = (0, react.useMemo)(() => links.filter((link) => link.value > 0 && nodeIds.has(link.source) && nodeIds.has(link.target)), [links, nodeIds]);
|
|
56
|
+
const visibleNodes = (0, react.useMemo)(() => {
|
|
57
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
58
|
+
for (const link of visibleLinks) {
|
|
59
|
+
referencedIds.add(link.source);
|
|
60
|
+
referencedIds.add(link.target);
|
|
61
|
+
}
|
|
62
|
+
return nodes.filter((node) => referencedIds.has(node.id));
|
|
63
|
+
}, [nodes, visibleLinks]);
|
|
64
|
+
const colorById = (0, react.useMemo)(() => {
|
|
65
|
+
const map = /* @__PURE__ */ new Map();
|
|
66
|
+
for (const node of nodes) map.set(node.id, resolveNodeColor(node, categoryColors, defaultColor));
|
|
67
|
+
return map;
|
|
68
|
+
}, [
|
|
69
|
+
categoryColors,
|
|
70
|
+
defaultColor,
|
|
71
|
+
nodes
|
|
72
|
+
]);
|
|
73
|
+
const orderById = (0, react.useMemo)(() => {
|
|
74
|
+
const map = /* @__PURE__ */ new Map();
|
|
75
|
+
visibleNodes.forEach((node, index) => map.set(node.id, index));
|
|
76
|
+
return map;
|
|
77
|
+
}, [visibleNodes]);
|
|
78
|
+
const nodeSort = (0, react.useMemo)(() => (a, b) => (orderById.get(a.id) ?? 0) - (orderById.get(b.id) ?? 0), [orderById]);
|
|
79
|
+
const graph = (0, react.useMemo)(() => ({
|
|
80
|
+
nodes: visibleNodes.map((node) => ({ ...node })),
|
|
81
|
+
links: visibleLinks.map((link) => ({ ...link }))
|
|
82
|
+
}), [visibleNodes, visibleLinks]);
|
|
83
|
+
const nodeAlign = (0, react.useMemo)(() => {
|
|
84
|
+
const keep = new Set(keepAtDepthIds);
|
|
85
|
+
return (node, n) => keep.has(node.id) ? node.depth ?? 0 : (0, _visx_sankey.sankeyJustify)(node, n);
|
|
86
|
+
}, [keepAtDepthIds]);
|
|
87
|
+
const innerWidth = Math.max(0, width - labelPadding - LEFT_INSET);
|
|
88
|
+
const innerHeight = Math.max(0, height - TOP_INSET * 2);
|
|
89
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
90
|
+
className: (0, cnfast.cn)("flex w-full flex-col gap-2 py-2", className),
|
|
91
|
+
children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_typography.SectionTitle, { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
92
|
+
ref: containerRef,
|
|
93
|
+
className: "w-full",
|
|
94
|
+
style: { height },
|
|
95
|
+
children: width > 0 && innerWidth > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
96
|
+
width,
|
|
97
|
+
height,
|
|
98
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_group.Group, {
|
|
99
|
+
left: LEFT_INSET,
|
|
100
|
+
top: TOP_INSET,
|
|
101
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_sankey.Sankey, {
|
|
102
|
+
root: graph,
|
|
103
|
+
size: [innerWidth, innerHeight],
|
|
104
|
+
nodeWidth,
|
|
105
|
+
nodePadding,
|
|
106
|
+
nodeAlign,
|
|
107
|
+
nodeId: (node) => node.id,
|
|
108
|
+
nodeSort,
|
|
109
|
+
children: ({ graph: laidOut, createPath }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_group.Group, {
|
|
110
|
+
className: "visx-sankey-links",
|
|
111
|
+
children: laidOut.links.map((link, index) => {
|
|
112
|
+
const sourceId = typeof link.source === "object" ? link.source.id : String(link.source);
|
|
113
|
+
const stroke = link.color ?? colorById.get(sourceId) ?? defaultColor;
|
|
114
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
115
|
+
d: createPath(link) ?? "",
|
|
116
|
+
fill: "none",
|
|
117
|
+
stroke,
|
|
118
|
+
strokeOpacity: .32,
|
|
119
|
+
strokeWidth: Math.max(1, link.width ?? 0)
|
|
120
|
+
}, `sankey-link-${index}`);
|
|
121
|
+
})
|
|
122
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_group.Group, {
|
|
123
|
+
className: "visx-sankey-nodes",
|
|
124
|
+
children: laidOut.nodes.map((node, index) => {
|
|
125
|
+
if (node.x0 === void 0 || node.x1 === void 0 || node.y0 === void 0 || node.y1 === void 0) return null;
|
|
126
|
+
const w = node.x1 - node.x0;
|
|
127
|
+
const h = node.y1 - node.y0;
|
|
128
|
+
const fill = colorById.get(node.id) ?? defaultColor;
|
|
129
|
+
const labelX = node.x1 + LABEL_GAP;
|
|
130
|
+
const labelY = Math.min(Math.max(node.y0 + h / 2 - 4, LABEL_NAME_HEIGHT - TOP_INSET), innerHeight + TOP_INSET - VALUE_HEIGHT);
|
|
131
|
+
const labelAnchor = "start";
|
|
132
|
+
const primaryDy = 0;
|
|
133
|
+
const valueWidth = Math.max(40, labelPadding - LABEL_GAP - 4);
|
|
134
|
+
const valueHeight = VALUE_HEIGHT;
|
|
135
|
+
const valueY = labelY + LABEL_VALUE_GAP;
|
|
136
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_group.Group, { children: [
|
|
137
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
138
|
+
x: node.x0,
|
|
139
|
+
y: node.y0,
|
|
140
|
+
width: w,
|
|
141
|
+
height: Math.max(1, h),
|
|
142
|
+
fill,
|
|
143
|
+
rx: 2
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
146
|
+
x: labelX,
|
|
147
|
+
y: labelY + primaryDy,
|
|
148
|
+
textAnchor: labelAnchor,
|
|
149
|
+
dominantBaseline: "alphabetic",
|
|
150
|
+
fontSize: 11,
|
|
151
|
+
fontWeight: 600,
|
|
152
|
+
fill: "var(--neutral-a12)",
|
|
153
|
+
children: node.label
|
|
154
|
+
}),
|
|
155
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("foreignObject", {
|
|
156
|
+
x: labelX,
|
|
157
|
+
y: valueY,
|
|
158
|
+
width: valueWidth,
|
|
159
|
+
height: valueHeight,
|
|
160
|
+
style: { overflow: "visible" },
|
|
161
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
162
|
+
style: {
|
|
163
|
+
lineHeight: 1.2,
|
|
164
|
+
overflow: "visible"
|
|
165
|
+
},
|
|
166
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_number_flow, {
|
|
167
|
+
value: node.value ?? 0,
|
|
168
|
+
...valueSuffix !== void 0 && { suffix: valueSuffix },
|
|
169
|
+
...valueFormat !== void 0 && { format: valueFormat },
|
|
170
|
+
className: "text-[10px] text-gray-light tabular-nums"
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
] }, `sankey-node-${index}`);
|
|
175
|
+
})
|
|
176
|
+
})] })
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
})]
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
exports.SANKEY_CATEGORY_COLORS = SANKEY_CATEGORY_COLORS;
|
|
185
|
+
exports.SankeyChart = SankeyChart;
|
|
186
|
+
|
|
187
|
+
//# sourceMappingURL=sankey-chart.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sankey-chart.cjs","names":["SectionTitle","Group","Sankey","NumberFlow"],"sources":["../../src/components/sankey-chart.tsx"],"sourcesContent":["import { Group } from '@visx/group'\nimport {\n Sankey,\n sankeyJustify,\n type SankeyLink,\n type SankeyNode,\n} from '@visx/sankey'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { cn } from '../utils/cn'\nimport NumberFlow, { type Format } from './number-flow'\nimport { SectionTitle } from './typography'\n\nconst SANKEY_CATEGORY_COLORS: Record<string, string> = {\n solar: 'var(--orange-a9)',\n battery: 'var(--green-a9)',\n grid: 'var(--blue-9)',\n gridFeedIn: 'var(--blue-7)',\n home: 'var(--spark-9)',\n floor: 'var(--neutral-a9)',\n device: 'var(--neutral-a8)',\n}\n\nexport interface SankeyChartNode {\n id: string\n label: string\n /** Optional category — used to colour the node and any outgoing links. */\n category?: string\n /** Override the colour resolved from `category`. */\n color?: string\n}\n\nexport interface SankeyChartLink {\n source: string\n target: string\n value: number\n /** Override the colour of the link. Defaults to the source node colour. */\n color?: string\n}\n\nexport interface SankeyChartProps {\n nodes: SankeyChartNode[]\n links: SankeyChartLink[]\n /** Resolves a category to a colour. */\n categoryColors?: Record<string, string>\n /** Fallback colour for nodes/links without a category. */\n defaultColor?: string\n /** Suffix appended to each animated value label (e.g. \" W\"). */\n valueSuffix?: string\n /** NumberFlow `format` for value labels. */\n valueFormat?: Format\n height?: number\n nodeWidth?: number\n nodePadding?: number\n /** Reserved horizontal space on the right for labels. */\n labelPadding?: number\n /**\n * Node ids kept at their natural (computed) column instead of being pushed to\n * the last column. By default `sankeyJustify` sends every node with no\n * outgoing link to the right edge; use this to hold a terminal node (e.g. grid\n * feed-in) in a middle column alongside its siblings.\n */\n keepAtDepthIds?: readonly string[]\n title?: string\n className?: string\n}\n\ntype SankeyDatumNode = SankeyChartNode & {\n /** Computed by d3-sankey; present after layout. */\n}\n\ntype SankeyDatumLink = SankeyChartLink\n\nconst DEFAULT_HEIGHT = 260\nconst DEFAULT_NODE_WIDTH = 12\nconst DEFAULT_NODE_PADDING = 10\nconst DEFAULT_LABEL_PADDING = 96\nconst LEFT_INSET = 4\nconst TOP_INSET = 8\nconst LABEL_GAP = 8\n/** Approx. cap/ascender height of the node name above its alphabetic baseline. */\nconst LABEL_NAME_HEIGHT = 11\n/** Vertical offset of the value box relative to the name baseline. Negative pulls\n * the value up toward the name to tighten the gap between them. */\nconst LABEL_VALUE_GAP = -4\n/** Height of the value box rendered below the node name. */\nconst VALUE_HEIGHT = 16\nconst DEFAULT_COLOR = 'var(--neutral-a9)'\n\nfunction resolveNodeColor(\n node: SankeyChartNode,\n categoryColors: Record<string, string> | undefined,\n defaultColor: string,\n) {\n if (node.color) return node.color\n if (node.category && categoryColors?.[node.category]) {\n return categoryColors[node.category] as string\n }\n return defaultColor\n}\n\nfunction SankeyChart({\n nodes,\n links,\n categoryColors = SANKEY_CATEGORY_COLORS,\n defaultColor = DEFAULT_COLOR,\n valueSuffix,\n valueFormat,\n height = DEFAULT_HEIGHT,\n nodeWidth = DEFAULT_NODE_WIDTH,\n nodePadding = DEFAULT_NODE_PADDING,\n labelPadding = DEFAULT_LABEL_PADDING,\n keepAtDepthIds,\n title,\n className,\n}: SankeyChartProps): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const [width, setWidth] = useState(0)\n\n useEffect(() => {\n const element = containerRef.current\n if (!element) return\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n return () => resizeObserver.disconnect()\n }, [])\n\n const nodeIds = useMemo(() => new Set(nodes.map((node) => node.id)), [nodes])\n\n // Drop zero-value links and any whose endpoints aren't in the current node\n // set (a stale link referencing a removed node makes d3-sankey throw\n // `missing: <id>`).\n const visibleLinks = useMemo(\n () =>\n links.filter(\n (link) =>\n link.value > 0 &&\n nodeIds.has(link.source) &&\n nodeIds.has(link.target),\n ),\n [links, nodeIds],\n )\n\n const visibleNodes = useMemo(() => {\n const referencedIds = new Set<string>()\n for (const link of visibleLinks) {\n referencedIds.add(link.source)\n referencedIds.add(link.target)\n }\n return nodes.filter((node) => referencedIds.has(node.id))\n }, [nodes, visibleLinks])\n\n const colorById = useMemo(() => {\n const map = new Map<string, string>()\n for (const node of nodes) {\n map.set(node.id, resolveNodeColor(node, categoryColors, defaultColor))\n }\n return map\n }, [categoryColors, defaultColor, nodes])\n\n const orderById = useMemo(() => {\n const map = new Map<string, number>()\n visibleNodes.forEach((node, index) => map.set(node.id, index))\n return map\n }, [visibleNodes])\n\n const nodeSort = useMemo(\n () =>\n (\n a: SankeyNode<SankeyDatumNode, SankeyDatumLink>,\n b: SankeyNode<SankeyDatumNode, SankeyDatumLink>,\n ) =>\n (orderById.get(a.id) ?? 0) - (orderById.get(b.id) ?? 0),\n [orderById],\n )\n\n const graph = useMemo(\n () => ({\n nodes: visibleNodes.map((node) => ({ ...node })),\n links: visibleLinks.map((link) => ({ ...link })),\n }),\n [visibleNodes, visibleLinks],\n )\n\n const nodeAlign = useMemo(() => {\n const keep = new Set(keepAtDepthIds)\n return (node: SankeyNode<SankeyDatumNode, SankeyDatumLink>, n: number) =>\n keep.has(node.id) ? (node.depth ?? 0) : sankeyJustify(node, n)\n }, [keepAtDepthIds])\n\n const innerWidth = Math.max(0, width - labelPadding - LEFT_INSET)\n const innerHeight = Math.max(0, height - TOP_INSET * 2)\n\n return (\n <div className={cn('flex w-full flex-col gap-2 py-2', className)}>\n {title && <SectionTitle>{title}</SectionTitle>}\n\n <div ref={containerRef} className=\"w-full\" style={{ height }}>\n {width > 0 && innerWidth > 0 && (\n <svg width={width} height={height}>\n <Group left={LEFT_INSET} top={TOP_INSET}>\n <Sankey<SankeyDatumNode, SankeyDatumLink>\n root={graph}\n size={[innerWidth, innerHeight]}\n nodeWidth={nodeWidth}\n nodePadding={nodePadding}\n nodeAlign={nodeAlign}\n nodeId={(node) => node.id}\n nodeSort={nodeSort}\n >\n {({ graph: laidOut, createPath }) => (\n <>\n <Group className=\"visx-sankey-links\">\n {laidOut.links.map((link, index) => {\n const sourceId =\n typeof link.source === 'object'\n ? (\n link.source as SankeyNode<\n SankeyDatumNode,\n SankeyDatumLink\n >\n ).id\n : String(link.source)\n const stroke =\n link.color ?? colorById.get(sourceId) ?? defaultColor\n\n return (\n <path\n key={`sankey-link-${index}`}\n d={createPath(link) ?? ''}\n fill=\"none\"\n stroke={stroke}\n strokeOpacity={0.32}\n strokeWidth={Math.max(1, link.width ?? 0)}\n />\n )\n })}\n </Group>\n\n <Group className=\"visx-sankey-nodes\">\n {laidOut.nodes.map((node, index) => {\n if (\n node.x0 === undefined ||\n node.x1 === undefined ||\n node.y0 === undefined ||\n node.y1 === undefined\n ) {\n return null\n }\n\n const w = node.x1 - node.x0\n const h = node.y1 - node.y0\n const fill = colorById.get(node.id) ?? defaultColor\n\n const labelX = node.x1 + LABEL_GAP\n // Center the name+value label on the node, then clamp it\n // vertically so a node flush against an edge (e.g. a tiny\n // \"grid\" node at the top) doesn't push its name past the\n // chart bounds and get clipped. The name's ascenders sit\n // above labelY; the value box sits below it.\n const labelY = Math.min(\n Math.max(\n node.y0 + h / 2 - 4,\n LABEL_NAME_HEIGHT - TOP_INSET,\n ),\n innerHeight + TOP_INSET - VALUE_HEIGHT,\n )\n const labelAnchor = 'start' as const\n const primaryDy = 0\n const valueWidth = Math.max(\n 40,\n labelPadding - LABEL_GAP - 4,\n )\n const valueHeight = VALUE_HEIGHT\n const valueY = labelY + LABEL_VALUE_GAP\n\n return (\n <Group key={`sankey-node-${index}`}>\n <rect\n x={node.x0}\n y={node.y0}\n width={w}\n height={Math.max(1, h)}\n fill={fill}\n rx={2}\n />\n <text\n x={labelX}\n y={labelY + primaryDy}\n textAnchor={labelAnchor}\n dominantBaseline=\"alphabetic\"\n fontSize={11}\n fontWeight={600}\n fill=\"var(--neutral-a12)\"\n >\n {node.label}\n </text>\n <foreignObject\n x={labelX}\n y={valueY}\n width={valueWidth}\n height={valueHeight}\n style={{ overflow: 'visible' }}\n >\n <div\n style={{\n lineHeight: 1.2,\n overflow: 'visible',\n }}\n >\n <NumberFlow\n value={node.value ?? 0}\n {...(valueSuffix !== undefined && {\n suffix: valueSuffix,\n })}\n {...(valueFormat !== undefined && {\n format: valueFormat,\n })}\n className=\"text-[10px] text-gray-light tabular-nums\"\n />\n </div>\n </foreignObject>\n </Group>\n )\n })}\n </Group>\n </>\n )}\n </Sankey>\n </Group>\n </svg>\n )}\n </div>\n </div>\n )\n}\n\nexport type { SankeyLink, SankeyNode }\nexport { SankeyChart, SANKEY_CATEGORY_COLORS }\n"],"mappings":";;;;;;;;;;AAYA,MAAM,yBAAiD;CACrD,OAAO;CACP,SAAS;CACT,MAAM;CACN,YAAY;CACZ,MAAM;CACN,OAAO;CACP,QAAQ;AACV;AAoDA,MAAM,iBAAiB;AACvB,MAAM,qBAAqB;AAC3B,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,aAAa;AACnB,MAAM,YAAY;AAClB,MAAM,YAAY;;AAElB,MAAM,oBAAoB;;;AAG1B,MAAM,kBAAkB;;AAExB,MAAM,eAAe;AACrB,MAAM,gBAAgB;AAEtB,SAAS,iBACP,MACA,gBACA,cACA;CACA,IAAI,KAAK,OAAO,OAAO,KAAK;CAC5B,IAAI,KAAK,YAAY,iBAAiB,KAAK,WACzC,OAAO,eAAe,KAAK;CAE7B,OAAO;AACT;AAEA,SAAS,YAAY,EACnB,OACA,OACA,iBAAiB,wBACjB,eAAe,eACf,aACA,aACA,SAAS,gBACT,YAAY,oBACZ,cAAc,sBACd,eAAe,uBACf,gBACA,OACA,aACuC;CACvC,MAAM,gBAAA,GAAA,MAAA,QAAsC,IAAI;CAChD,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAqB,CAAC;CAEpC,CAAA,GAAA,MAAA,iBAAgB;EACd,MAAM,UAAU,aAAa;EAC7B,IAAI,CAAC,SAAS;EAEd,MAAM,iBAAiB,IAAI,gBAAgB,YAAY;GACrD,MAAM,QAAQ,QAAQ;GACtB,IAAI,CAAC,OAAO;GACZ,SAAS,MAAM,YAAY,KAAK;EAClC,CAAC;EAED,eAAe,QAAQ,OAAO;EAC9B,aAAa,eAAe,WAAW;CACzC,GAAG,CAAC,CAAC;CAEL,MAAM,WAAA,GAAA,MAAA,eAAwB,IAAI,IAAI,MAAM,KAAK,SAAS,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;CAK5E,MAAM,gBAAA,GAAA,MAAA,eAEF,MAAM,QACH,SACC,KAAK,QAAQ,KACb,QAAQ,IAAI,KAAK,MAAM,KACvB,QAAQ,IAAI,KAAK,MAAM,CAC3B,GACF,CAAC,OAAO,OAAO,CACjB;CAEA,MAAM,gBAAA,GAAA,MAAA,eAA6B;EACjC,MAAM,gCAAgB,IAAI,IAAY;EACtC,KAAK,MAAM,QAAQ,cAAc;GAC/B,cAAc,IAAI,KAAK,MAAM;GAC7B,cAAc,IAAI,KAAK,MAAM;EAC/B;EACA,OAAO,MAAM,QAAQ,SAAS,cAAc,IAAI,KAAK,EAAE,CAAC;CAC1D,GAAG,CAAC,OAAO,YAAY,CAAC;CAExB,MAAM,aAAA,GAAA,MAAA,eAA0B;EAC9B,MAAM,sBAAM,IAAI,IAAoB;EACpC,KAAK,MAAM,QAAQ,OACjB,IAAI,IAAI,KAAK,IAAI,iBAAiB,MAAM,gBAAgB,YAAY,CAAC;EAEvE,OAAO;CACT,GAAG;EAAC;EAAgB;EAAc;CAAK,CAAC;CAExC,MAAM,aAAA,GAAA,MAAA,eAA0B;EAC9B,MAAM,sBAAM,IAAI,IAAoB;EACpC,aAAa,SAAS,MAAM,UAAU,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC;EAC7D,OAAO;CACT,GAAG,CAAC,YAAY,CAAC;CAEjB,MAAM,YAAA,GAAA,MAAA,gBAGA,GACA,OAEC,UAAU,IAAI,EAAE,EAAE,KAAK,MAAM,UAAU,IAAI,EAAE,EAAE,KAAK,IACzD,CAAC,SAAS,CACZ;CAEA,MAAM,SAAA,GAAA,MAAA,gBACG;EACL,OAAO,aAAa,KAAK,UAAU,EAAE,GAAG,KAAK,EAAE;EAC/C,OAAO,aAAa,KAAK,UAAU,EAAE,GAAG,KAAK,EAAE;CACjD,IACA,CAAC,cAAc,YAAY,CAC7B;CAEA,MAAM,aAAA,GAAA,MAAA,eAA0B;EAC9B,MAAM,OAAO,IAAI,IAAI,cAAc;EACnC,QAAQ,MAAoD,MAC1D,KAAK,IAAI,KAAK,EAAE,IAAK,KAAK,SAAS,KAAA,GAAA,aAAA,eAAmB,MAAM,CAAC;CACjE,GAAG,CAAC,cAAc,CAAC;CAEnB,MAAM,aAAa,KAAK,IAAI,GAAG,QAAQ,eAAe,UAAU;CAChE,MAAM,cAAc,KAAK,IAAI,GAAG,SAAS,YAAY,CAAC;CAEtD,OACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;EAAK,YAAA,GAAA,OAAA,IAAc,mCAAmC,SAAS;YAA/D,CACG,SAAS,iBAAA,GAAA,kBAAA,KAACA,8BAAAA,cAAD,EAAA,UAAe,MAAoB,CAAA,GAE7C,iBAAA,GAAA,kBAAA,KAAC,OAAD;GAAK,KAAK;GAAc,WAAU;GAAS,OAAO,EAAE,OAAO;aACxD,QAAQ,KAAK,aAAa,KACzB,iBAAA,GAAA,kBAAA,KAAC,OAAD;IAAY;IAAe;cACzB,iBAAA,GAAA,kBAAA,KAACC,YAAAA,OAAD;KAAO,MAAM;KAAY,KAAK;eAC5B,iBAAA,GAAA,kBAAA,KAACC,aAAAA,QAAD;MACE,MAAM;MACN,MAAM,CAAC,YAAY,WAAW;MACnB;MACE;MACF;MACX,SAAS,SAAS,KAAK;MACb;iBAER,EAAE,OAAO,SAAS,iBAClB,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAACD,YAAAA,OAAD;OAAO,WAAU;iBACd,QAAQ,MAAM,KAAK,MAAM,UAAU;QAClC,MAAM,WACJ,OAAO,KAAK,WAAW,WAEjB,KAAK,OAIL,KACF,OAAO,KAAK,MAAM;QACxB,MAAM,SACJ,KAAK,SAAS,UAAU,IAAI,QAAQ,KAAK;QAE3C,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;SAEE,GAAG,WAAW,IAAI,KAAK;SACvB,MAAK;SACG;SACR,eAAe;SACf,aAAa,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC;QACzC,GANM,eAAe,OAMrB;OAEL,CAAC;MACI,CAAA,GAEP,iBAAA,GAAA,kBAAA,KAACA,YAAAA,OAAD;OAAO,WAAU;iBACd,QAAQ,MAAM,KAAK,MAAM,UAAU;QAClC,IACE,KAAK,OAAO,KAAA,KACZ,KAAK,OAAO,KAAA,KACZ,KAAK,OAAO,KAAA,KACZ,KAAK,OAAO,KAAA,GAEZ,OAAO;QAGT,MAAM,IAAI,KAAK,KAAK,KAAK;QACzB,MAAM,IAAI,KAAK,KAAK,KAAK;QACzB,MAAM,OAAO,UAAU,IAAI,KAAK,EAAE,KAAK;QAEvC,MAAM,SAAS,KAAK,KAAK;QAMzB,MAAM,SAAS,KAAK,IAClB,KAAK,IACH,KAAK,KAAK,IAAI,IAAI,GAClB,oBAAoB,SACtB,GACA,cAAc,YAAY,YAC5B;QACA,MAAM,cAAc;QACpB,MAAM,YAAY;QAClB,MAAM,aAAa,KAAK,IACtB,IACA,eAAe,YAAY,CAC7B;QACA,MAAM,cAAc;QACpB,MAAM,SAAS,SAAS;QAExB,OACE,iBAAA,GAAA,kBAAA,MAACA,YAAAA,OAAD,EAAA,UAAA;SACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;UACE,GAAG,KAAK;UACR,GAAG,KAAK;UACR,OAAO;UACP,QAAQ,KAAK,IAAI,GAAG,CAAC;UACf;UACN,IAAI;SACL,CAAA;SACD,iBAAA,GAAA,kBAAA,KAAC,QAAD;UACE,GAAG;UACH,GAAG,SAAS;UACZ,YAAY;UACZ,kBAAiB;UACjB,UAAU;UACV,YAAY;UACZ,MAAK;oBAEJ,KAAK;SACF,CAAA;SACN,iBAAA,GAAA,kBAAA,KAAC,iBAAD;UACE,GAAG;UACH,GAAG;UACH,OAAO;UACP,QAAQ;UACR,OAAO,EAAE,UAAU,UAAU;oBAE7B,iBAAA,GAAA,kBAAA,KAAC,OAAD;WACE,OAAO;YACL,YAAY;YACZ,UAAU;WACZ;qBAEA,iBAAA,GAAA,kBAAA,KAACE,gCAAD;YACE,OAAO,KAAK,SAAS;YACrB,GAAK,gBAAgB,KAAA,KAAa,EAChC,QAAQ,YACV;YACA,GAAK,gBAAgB,KAAA,KAAa,EAChC,QAAQ,YACV;YACA,WAAU;WACX,CAAA;UACE,CAAA;SACQ,CAAA;QACV,EAAA,GA7CK,eAAe,OA6CpB;OAEX,CAAC;MACI,CAAA,CACP,EAAA,CAAA;KAEE,CAAA;IACH,CAAA;GACJ,CAAA;EAEJ,CAAA,CACF;;AAET"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { t as Format } from "../number-flow-Bch81ixZ.cjs";
|
|
4
|
+
import { SankeyLink, SankeyNode } from "@visx/sankey";
|
|
5
|
+
|
|
6
|
+
//#region src/components/sankey-chart.d.ts
|
|
7
|
+
declare const SANKEY_CATEGORY_COLORS: Record<string, string>;
|
|
8
|
+
interface SankeyChartNode {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
/** Optional category — used to colour the node and any outgoing links. */
|
|
12
|
+
category?: string;
|
|
13
|
+
/** Override the colour resolved from `category`. */
|
|
14
|
+
color?: string;
|
|
15
|
+
}
|
|
16
|
+
interface SankeyChartLink {
|
|
17
|
+
source: string;
|
|
18
|
+
target: string;
|
|
19
|
+
value: number;
|
|
20
|
+
/** Override the colour of the link. Defaults to the source node colour. */
|
|
21
|
+
color?: string;
|
|
22
|
+
}
|
|
23
|
+
interface SankeyChartProps {
|
|
24
|
+
nodes: SankeyChartNode[];
|
|
25
|
+
links: SankeyChartLink[];
|
|
26
|
+
/** Resolves a category to a colour. */
|
|
27
|
+
categoryColors?: Record<string, string>;
|
|
28
|
+
/** Fallback colour for nodes/links without a category. */
|
|
29
|
+
defaultColor?: string;
|
|
30
|
+
/** Suffix appended to each animated value label (e.g. " W"). */
|
|
31
|
+
valueSuffix?: string;
|
|
32
|
+
/** NumberFlow `format` for value labels. */
|
|
33
|
+
valueFormat?: Format;
|
|
34
|
+
height?: number;
|
|
35
|
+
nodeWidth?: number;
|
|
36
|
+
nodePadding?: number;
|
|
37
|
+
/** Reserved horizontal space on the right for labels. */
|
|
38
|
+
labelPadding?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Node ids kept at their natural (computed) column instead of being pushed to
|
|
41
|
+
* the last column. By default `sankeyJustify` sends every node with no
|
|
42
|
+
* outgoing link to the right edge; use this to hold a terminal node (e.g. grid
|
|
43
|
+
* feed-in) in a middle column alongside its siblings.
|
|
44
|
+
*/
|
|
45
|
+
keepAtDepthIds?: readonly string[];
|
|
46
|
+
title?: string;
|
|
47
|
+
className?: string;
|
|
48
|
+
}
|
|
49
|
+
declare function SankeyChart({
|
|
50
|
+
nodes,
|
|
51
|
+
links,
|
|
52
|
+
categoryColors,
|
|
53
|
+
defaultColor,
|
|
54
|
+
valueSuffix,
|
|
55
|
+
valueFormat,
|
|
56
|
+
height,
|
|
57
|
+
nodeWidth,
|
|
58
|
+
nodePadding,
|
|
59
|
+
labelPadding,
|
|
60
|
+
keepAtDepthIds,
|
|
61
|
+
title,
|
|
62
|
+
className
|
|
63
|
+
}: SankeyChartProps): React.ReactElement;
|
|
64
|
+
//#endregion
|
|
65
|
+
export { SANKEY_CATEGORY_COLORS, SankeyChart, SankeyChartLink, SankeyChartNode, SankeyChartProps, type SankeyLink, type SankeyNode };
|
|
66
|
+
//# sourceMappingURL=sankey-chart.d.cts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { t as Format } from "../number-flow-Bch81ixZ.js";
|
|
4
|
+
import { SankeyLink, SankeyNode } from "@visx/sankey";
|
|
5
|
+
|
|
6
|
+
//#region src/components/sankey-chart.d.ts
|
|
7
|
+
declare const SANKEY_CATEGORY_COLORS: Record<string, string>;
|
|
8
|
+
interface SankeyChartNode {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
/** Optional category — used to colour the node and any outgoing links. */
|
|
12
|
+
category?: string;
|
|
13
|
+
/** Override the colour resolved from `category`. */
|
|
14
|
+
color?: string;
|
|
15
|
+
}
|
|
16
|
+
interface SankeyChartLink {
|
|
17
|
+
source: string;
|
|
18
|
+
target: string;
|
|
19
|
+
value: number;
|
|
20
|
+
/** Override the colour of the link. Defaults to the source node colour. */
|
|
21
|
+
color?: string;
|
|
22
|
+
}
|
|
23
|
+
interface SankeyChartProps {
|
|
24
|
+
nodes: SankeyChartNode[];
|
|
25
|
+
links: SankeyChartLink[];
|
|
26
|
+
/** Resolves a category to a colour. */
|
|
27
|
+
categoryColors?: Record<string, string>;
|
|
28
|
+
/** Fallback colour for nodes/links without a category. */
|
|
29
|
+
defaultColor?: string;
|
|
30
|
+
/** Suffix appended to each animated value label (e.g. " W"). */
|
|
31
|
+
valueSuffix?: string;
|
|
32
|
+
/** NumberFlow `format` for value labels. */
|
|
33
|
+
valueFormat?: Format;
|
|
34
|
+
height?: number;
|
|
35
|
+
nodeWidth?: number;
|
|
36
|
+
nodePadding?: number;
|
|
37
|
+
/** Reserved horizontal space on the right for labels. */
|
|
38
|
+
labelPadding?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Node ids kept at their natural (computed) column instead of being pushed to
|
|
41
|
+
* the last column. By default `sankeyJustify` sends every node with no
|
|
42
|
+
* outgoing link to the right edge; use this to hold a terminal node (e.g. grid
|
|
43
|
+
* feed-in) in a middle column alongside its siblings.
|
|
44
|
+
*/
|
|
45
|
+
keepAtDepthIds?: readonly string[];
|
|
46
|
+
title?: string;
|
|
47
|
+
className?: string;
|
|
48
|
+
}
|
|
49
|
+
declare function SankeyChart({
|
|
50
|
+
nodes,
|
|
51
|
+
links,
|
|
52
|
+
categoryColors,
|
|
53
|
+
defaultColor,
|
|
54
|
+
valueSuffix,
|
|
55
|
+
valueFormat,
|
|
56
|
+
height,
|
|
57
|
+
nodeWidth,
|
|
58
|
+
nodePadding,
|
|
59
|
+
labelPadding,
|
|
60
|
+
keepAtDepthIds,
|
|
61
|
+
title,
|
|
62
|
+
className
|
|
63
|
+
}: SankeyChartProps): React.ReactElement;
|
|
64
|
+
//#endregion
|
|
65
|
+
export { SANKEY_CATEGORY_COLORS, SankeyChart, SankeyChartLink, SankeyChartNode, SankeyChartProps, type SankeyLink, type SankeyNode };
|
|
66
|
+
//# sourceMappingURL=sankey-chart.d.ts.map
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../utils/cn.js";
|
|
3
|
+
import { SectionTitle } from "./typography.js";
|
|
4
|
+
import NumberFlow from "./number-flow.js";
|
|
5
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Group } from "@visx/group";
|
|
8
|
+
import { Sankey, sankeyJustify } from "@visx/sankey";
|
|
9
|
+
//#region src/components/sankey-chart.tsx
|
|
10
|
+
const SANKEY_CATEGORY_COLORS = {
|
|
11
|
+
solar: "var(--orange-a9)",
|
|
12
|
+
battery: "var(--green-a9)",
|
|
13
|
+
grid: "var(--blue-9)",
|
|
14
|
+
gridFeedIn: "var(--blue-7)",
|
|
15
|
+
home: "var(--spark-9)",
|
|
16
|
+
floor: "var(--neutral-a9)",
|
|
17
|
+
device: "var(--neutral-a8)"
|
|
18
|
+
};
|
|
19
|
+
const DEFAULT_HEIGHT = 260;
|
|
20
|
+
const DEFAULT_NODE_WIDTH = 12;
|
|
21
|
+
const DEFAULT_NODE_PADDING = 10;
|
|
22
|
+
const DEFAULT_LABEL_PADDING = 96;
|
|
23
|
+
const LEFT_INSET = 4;
|
|
24
|
+
const TOP_INSET = 8;
|
|
25
|
+
const LABEL_GAP = 8;
|
|
26
|
+
/** Approx. cap/ascender height of the node name above its alphabetic baseline. */
|
|
27
|
+
const LABEL_NAME_HEIGHT = 11;
|
|
28
|
+
/** Vertical offset of the value box relative to the name baseline. Negative pulls
|
|
29
|
+
* the value up toward the name to tighten the gap between them. */
|
|
30
|
+
const LABEL_VALUE_GAP = -4;
|
|
31
|
+
/** Height of the value box rendered below the node name. */
|
|
32
|
+
const VALUE_HEIGHT = 16;
|
|
33
|
+
const DEFAULT_COLOR = "var(--neutral-a9)";
|
|
34
|
+
function resolveNodeColor(node, categoryColors, defaultColor) {
|
|
35
|
+
if (node.color) return node.color;
|
|
36
|
+
if (node.category && categoryColors?.[node.category]) return categoryColors[node.category];
|
|
37
|
+
return defaultColor;
|
|
38
|
+
}
|
|
39
|
+
function SankeyChart({ nodes, links, categoryColors = SANKEY_CATEGORY_COLORS, defaultColor = DEFAULT_COLOR, valueSuffix, valueFormat, height = DEFAULT_HEIGHT, nodeWidth = DEFAULT_NODE_WIDTH, nodePadding = DEFAULT_NODE_PADDING, labelPadding = DEFAULT_LABEL_PADDING, keepAtDepthIds, title, className }) {
|
|
40
|
+
const containerRef = useRef(null);
|
|
41
|
+
const [width, setWidth] = useState(0);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const element = containerRef.current;
|
|
44
|
+
if (!element) return;
|
|
45
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
46
|
+
const entry = entries[0];
|
|
47
|
+
if (!entry) return;
|
|
48
|
+
setWidth(entry.contentRect.width);
|
|
49
|
+
});
|
|
50
|
+
resizeObserver.observe(element);
|
|
51
|
+
return () => resizeObserver.disconnect();
|
|
52
|
+
}, []);
|
|
53
|
+
const nodeIds = useMemo(() => new Set(nodes.map((node) => node.id)), [nodes]);
|
|
54
|
+
const visibleLinks = useMemo(() => links.filter((link) => link.value > 0 && nodeIds.has(link.source) && nodeIds.has(link.target)), [links, nodeIds]);
|
|
55
|
+
const visibleNodes = useMemo(() => {
|
|
56
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
57
|
+
for (const link of visibleLinks) {
|
|
58
|
+
referencedIds.add(link.source);
|
|
59
|
+
referencedIds.add(link.target);
|
|
60
|
+
}
|
|
61
|
+
return nodes.filter((node) => referencedIds.has(node.id));
|
|
62
|
+
}, [nodes, visibleLinks]);
|
|
63
|
+
const colorById = useMemo(() => {
|
|
64
|
+
const map = /* @__PURE__ */ new Map();
|
|
65
|
+
for (const node of nodes) map.set(node.id, resolveNodeColor(node, categoryColors, defaultColor));
|
|
66
|
+
return map;
|
|
67
|
+
}, [
|
|
68
|
+
categoryColors,
|
|
69
|
+
defaultColor,
|
|
70
|
+
nodes
|
|
71
|
+
]);
|
|
72
|
+
const orderById = useMemo(() => {
|
|
73
|
+
const map = /* @__PURE__ */ new Map();
|
|
74
|
+
visibleNodes.forEach((node, index) => map.set(node.id, index));
|
|
75
|
+
return map;
|
|
76
|
+
}, [visibleNodes]);
|
|
77
|
+
const nodeSort = useMemo(() => (a, b) => (orderById.get(a.id) ?? 0) - (orderById.get(b.id) ?? 0), [orderById]);
|
|
78
|
+
const graph = useMemo(() => ({
|
|
79
|
+
nodes: visibleNodes.map((node) => ({ ...node })),
|
|
80
|
+
links: visibleLinks.map((link) => ({ ...link }))
|
|
81
|
+
}), [visibleNodes, visibleLinks]);
|
|
82
|
+
const nodeAlign = useMemo(() => {
|
|
83
|
+
const keep = new Set(keepAtDepthIds);
|
|
84
|
+
return (node, n) => keep.has(node.id) ? node.depth ?? 0 : sankeyJustify(node, n);
|
|
85
|
+
}, [keepAtDepthIds]);
|
|
86
|
+
const innerWidth = Math.max(0, width - labelPadding - LEFT_INSET);
|
|
87
|
+
const innerHeight = Math.max(0, height - TOP_INSET * 2);
|
|
88
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
89
|
+
className: cn("flex w-full flex-col gap-2 py-2", className),
|
|
90
|
+
children: [title && /* @__PURE__ */ jsx(SectionTitle, { children: title }), /* @__PURE__ */ jsx("div", {
|
|
91
|
+
ref: containerRef,
|
|
92
|
+
className: "w-full",
|
|
93
|
+
style: { height },
|
|
94
|
+
children: width > 0 && innerWidth > 0 && /* @__PURE__ */ jsx("svg", {
|
|
95
|
+
width,
|
|
96
|
+
height,
|
|
97
|
+
children: /* @__PURE__ */ jsx(Group, {
|
|
98
|
+
left: LEFT_INSET,
|
|
99
|
+
top: TOP_INSET,
|
|
100
|
+
children: /* @__PURE__ */ jsx(Sankey, {
|
|
101
|
+
root: graph,
|
|
102
|
+
size: [innerWidth, innerHeight],
|
|
103
|
+
nodeWidth,
|
|
104
|
+
nodePadding,
|
|
105
|
+
nodeAlign,
|
|
106
|
+
nodeId: (node) => node.id,
|
|
107
|
+
nodeSort,
|
|
108
|
+
children: ({ graph: laidOut, createPath }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Group, {
|
|
109
|
+
className: "visx-sankey-links",
|
|
110
|
+
children: laidOut.links.map((link, index) => {
|
|
111
|
+
const sourceId = typeof link.source === "object" ? link.source.id : String(link.source);
|
|
112
|
+
const stroke = link.color ?? colorById.get(sourceId) ?? defaultColor;
|
|
113
|
+
return /* @__PURE__ */ jsx("path", {
|
|
114
|
+
d: createPath(link) ?? "",
|
|
115
|
+
fill: "none",
|
|
116
|
+
stroke,
|
|
117
|
+
strokeOpacity: .32,
|
|
118
|
+
strokeWidth: Math.max(1, link.width ?? 0)
|
|
119
|
+
}, `sankey-link-${index}`);
|
|
120
|
+
})
|
|
121
|
+
}), /* @__PURE__ */ jsx(Group, {
|
|
122
|
+
className: "visx-sankey-nodes",
|
|
123
|
+
children: laidOut.nodes.map((node, index) => {
|
|
124
|
+
if (node.x0 === void 0 || node.x1 === void 0 || node.y0 === void 0 || node.y1 === void 0) return null;
|
|
125
|
+
const w = node.x1 - node.x0;
|
|
126
|
+
const h = node.y1 - node.y0;
|
|
127
|
+
const fill = colorById.get(node.id) ?? defaultColor;
|
|
128
|
+
const labelX = node.x1 + LABEL_GAP;
|
|
129
|
+
const labelY = Math.min(Math.max(node.y0 + h / 2 - 4, LABEL_NAME_HEIGHT - TOP_INSET), innerHeight + TOP_INSET - VALUE_HEIGHT);
|
|
130
|
+
const labelAnchor = "start";
|
|
131
|
+
const primaryDy = 0;
|
|
132
|
+
const valueWidth = Math.max(40, labelPadding - LABEL_GAP - 4);
|
|
133
|
+
const valueHeight = VALUE_HEIGHT;
|
|
134
|
+
const valueY = labelY + LABEL_VALUE_GAP;
|
|
135
|
+
return /* @__PURE__ */ jsxs(Group, { children: [
|
|
136
|
+
/* @__PURE__ */ jsx("rect", {
|
|
137
|
+
x: node.x0,
|
|
138
|
+
y: node.y0,
|
|
139
|
+
width: w,
|
|
140
|
+
height: Math.max(1, h),
|
|
141
|
+
fill,
|
|
142
|
+
rx: 2
|
|
143
|
+
}),
|
|
144
|
+
/* @__PURE__ */ jsx("text", {
|
|
145
|
+
x: labelX,
|
|
146
|
+
y: labelY + primaryDy,
|
|
147
|
+
textAnchor: labelAnchor,
|
|
148
|
+
dominantBaseline: "alphabetic",
|
|
149
|
+
fontSize: 11,
|
|
150
|
+
fontWeight: 600,
|
|
151
|
+
fill: "var(--neutral-a12)",
|
|
152
|
+
children: node.label
|
|
153
|
+
}),
|
|
154
|
+
/* @__PURE__ */ jsx("foreignObject", {
|
|
155
|
+
x: labelX,
|
|
156
|
+
y: valueY,
|
|
157
|
+
width: valueWidth,
|
|
158
|
+
height: valueHeight,
|
|
159
|
+
style: { overflow: "visible" },
|
|
160
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
161
|
+
style: {
|
|
162
|
+
lineHeight: 1.2,
|
|
163
|
+
overflow: "visible"
|
|
164
|
+
},
|
|
165
|
+
children: /* @__PURE__ */ jsx(NumberFlow, {
|
|
166
|
+
value: node.value ?? 0,
|
|
167
|
+
...valueSuffix !== void 0 && { suffix: valueSuffix },
|
|
168
|
+
...valueFormat !== void 0 && { format: valueFormat },
|
|
169
|
+
className: "text-[10px] text-gray-light tabular-nums"
|
|
170
|
+
})
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
] }, `sankey-node-${index}`);
|
|
174
|
+
})
|
|
175
|
+
})] })
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
})]
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
//#endregion
|
|
183
|
+
export { SANKEY_CATEGORY_COLORS, SankeyChart };
|
|
184
|
+
|
|
185
|
+
//# sourceMappingURL=sankey-chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sankey-chart.js","names":[],"sources":["../../src/components/sankey-chart.tsx"],"sourcesContent":["import { Group } from '@visx/group'\nimport {\n Sankey,\n sankeyJustify,\n type SankeyLink,\n type SankeyNode,\n} from '@visx/sankey'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { cn } from '../utils/cn'\nimport NumberFlow, { type Format } from './number-flow'\nimport { SectionTitle } from './typography'\n\nconst SANKEY_CATEGORY_COLORS: Record<string, string> = {\n solar: 'var(--orange-a9)',\n battery: 'var(--green-a9)',\n grid: 'var(--blue-9)',\n gridFeedIn: 'var(--blue-7)',\n home: 'var(--spark-9)',\n floor: 'var(--neutral-a9)',\n device: 'var(--neutral-a8)',\n}\n\nexport interface SankeyChartNode {\n id: string\n label: string\n /** Optional category — used to colour the node and any outgoing links. */\n category?: string\n /** Override the colour resolved from `category`. */\n color?: string\n}\n\nexport interface SankeyChartLink {\n source: string\n target: string\n value: number\n /** Override the colour of the link. Defaults to the source node colour. */\n color?: string\n}\n\nexport interface SankeyChartProps {\n nodes: SankeyChartNode[]\n links: SankeyChartLink[]\n /** Resolves a category to a colour. */\n categoryColors?: Record<string, string>\n /** Fallback colour for nodes/links without a category. */\n defaultColor?: string\n /** Suffix appended to each animated value label (e.g. \" W\"). */\n valueSuffix?: string\n /** NumberFlow `format` for value labels. */\n valueFormat?: Format\n height?: number\n nodeWidth?: number\n nodePadding?: number\n /** Reserved horizontal space on the right for labels. */\n labelPadding?: number\n /**\n * Node ids kept at their natural (computed) column instead of being pushed to\n * the last column. By default `sankeyJustify` sends every node with no\n * outgoing link to the right edge; use this to hold a terminal node (e.g. grid\n * feed-in) in a middle column alongside its siblings.\n */\n keepAtDepthIds?: readonly string[]\n title?: string\n className?: string\n}\n\ntype SankeyDatumNode = SankeyChartNode & {\n /** Computed by d3-sankey; present after layout. */\n}\n\ntype SankeyDatumLink = SankeyChartLink\n\nconst DEFAULT_HEIGHT = 260\nconst DEFAULT_NODE_WIDTH = 12\nconst DEFAULT_NODE_PADDING = 10\nconst DEFAULT_LABEL_PADDING = 96\nconst LEFT_INSET = 4\nconst TOP_INSET = 8\nconst LABEL_GAP = 8\n/** Approx. cap/ascender height of the node name above its alphabetic baseline. */\nconst LABEL_NAME_HEIGHT = 11\n/** Vertical offset of the value box relative to the name baseline. Negative pulls\n * the value up toward the name to tighten the gap between them. */\nconst LABEL_VALUE_GAP = -4\n/** Height of the value box rendered below the node name. */\nconst VALUE_HEIGHT = 16\nconst DEFAULT_COLOR = 'var(--neutral-a9)'\n\nfunction resolveNodeColor(\n node: SankeyChartNode,\n categoryColors: Record<string, string> | undefined,\n defaultColor: string,\n) {\n if (node.color) return node.color\n if (node.category && categoryColors?.[node.category]) {\n return categoryColors[node.category] as string\n }\n return defaultColor\n}\n\nfunction SankeyChart({\n nodes,\n links,\n categoryColors = SANKEY_CATEGORY_COLORS,\n defaultColor = DEFAULT_COLOR,\n valueSuffix,\n valueFormat,\n height = DEFAULT_HEIGHT,\n nodeWidth = DEFAULT_NODE_WIDTH,\n nodePadding = DEFAULT_NODE_PADDING,\n labelPadding = DEFAULT_LABEL_PADDING,\n keepAtDepthIds,\n title,\n className,\n}: SankeyChartProps): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const [width, setWidth] = useState(0)\n\n useEffect(() => {\n const element = containerRef.current\n if (!element) return\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n return () => resizeObserver.disconnect()\n }, [])\n\n const nodeIds = useMemo(() => new Set(nodes.map((node) => node.id)), [nodes])\n\n // Drop zero-value links and any whose endpoints aren't in the current node\n // set (a stale link referencing a removed node makes d3-sankey throw\n // `missing: <id>`).\n const visibleLinks = useMemo(\n () =>\n links.filter(\n (link) =>\n link.value > 0 &&\n nodeIds.has(link.source) &&\n nodeIds.has(link.target),\n ),\n [links, nodeIds],\n )\n\n const visibleNodes = useMemo(() => {\n const referencedIds = new Set<string>()\n for (const link of visibleLinks) {\n referencedIds.add(link.source)\n referencedIds.add(link.target)\n }\n return nodes.filter((node) => referencedIds.has(node.id))\n }, [nodes, visibleLinks])\n\n const colorById = useMemo(() => {\n const map = new Map<string, string>()\n for (const node of nodes) {\n map.set(node.id, resolveNodeColor(node, categoryColors, defaultColor))\n }\n return map\n }, [categoryColors, defaultColor, nodes])\n\n const orderById = useMemo(() => {\n const map = new Map<string, number>()\n visibleNodes.forEach((node, index) => map.set(node.id, index))\n return map\n }, [visibleNodes])\n\n const nodeSort = useMemo(\n () =>\n (\n a: SankeyNode<SankeyDatumNode, SankeyDatumLink>,\n b: SankeyNode<SankeyDatumNode, SankeyDatumLink>,\n ) =>\n (orderById.get(a.id) ?? 0) - (orderById.get(b.id) ?? 0),\n [orderById],\n )\n\n const graph = useMemo(\n () => ({\n nodes: visibleNodes.map((node) => ({ ...node })),\n links: visibleLinks.map((link) => ({ ...link })),\n }),\n [visibleNodes, visibleLinks],\n )\n\n const nodeAlign = useMemo(() => {\n const keep = new Set(keepAtDepthIds)\n return (node: SankeyNode<SankeyDatumNode, SankeyDatumLink>, n: number) =>\n keep.has(node.id) ? (node.depth ?? 0) : sankeyJustify(node, n)\n }, [keepAtDepthIds])\n\n const innerWidth = Math.max(0, width - labelPadding - LEFT_INSET)\n const innerHeight = Math.max(0, height - TOP_INSET * 2)\n\n return (\n <div className={cn('flex w-full flex-col gap-2 py-2', className)}>\n {title && <SectionTitle>{title}</SectionTitle>}\n\n <div ref={containerRef} className=\"w-full\" style={{ height }}>\n {width > 0 && innerWidth > 0 && (\n <svg width={width} height={height}>\n <Group left={LEFT_INSET} top={TOP_INSET}>\n <Sankey<SankeyDatumNode, SankeyDatumLink>\n root={graph}\n size={[innerWidth, innerHeight]}\n nodeWidth={nodeWidth}\n nodePadding={nodePadding}\n nodeAlign={nodeAlign}\n nodeId={(node) => node.id}\n nodeSort={nodeSort}\n >\n {({ graph: laidOut, createPath }) => (\n <>\n <Group className=\"visx-sankey-links\">\n {laidOut.links.map((link, index) => {\n const sourceId =\n typeof link.source === 'object'\n ? (\n link.source as SankeyNode<\n SankeyDatumNode,\n SankeyDatumLink\n >\n ).id\n : String(link.source)\n const stroke =\n link.color ?? colorById.get(sourceId) ?? defaultColor\n\n return (\n <path\n key={`sankey-link-${index}`}\n d={createPath(link) ?? ''}\n fill=\"none\"\n stroke={stroke}\n strokeOpacity={0.32}\n strokeWidth={Math.max(1, link.width ?? 0)}\n />\n )\n })}\n </Group>\n\n <Group className=\"visx-sankey-nodes\">\n {laidOut.nodes.map((node, index) => {\n if (\n node.x0 === undefined ||\n node.x1 === undefined ||\n node.y0 === undefined ||\n node.y1 === undefined\n ) {\n return null\n }\n\n const w = node.x1 - node.x0\n const h = node.y1 - node.y0\n const fill = colorById.get(node.id) ?? defaultColor\n\n const labelX = node.x1 + LABEL_GAP\n // Center the name+value label on the node, then clamp it\n // vertically so a node flush against an edge (e.g. a tiny\n // \"grid\" node at the top) doesn't push its name past the\n // chart bounds and get clipped. The name's ascenders sit\n // above labelY; the value box sits below it.\n const labelY = Math.min(\n Math.max(\n node.y0 + h / 2 - 4,\n LABEL_NAME_HEIGHT - TOP_INSET,\n ),\n innerHeight + TOP_INSET - VALUE_HEIGHT,\n )\n const labelAnchor = 'start' as const\n const primaryDy = 0\n const valueWidth = Math.max(\n 40,\n labelPadding - LABEL_GAP - 4,\n )\n const valueHeight = VALUE_HEIGHT\n const valueY = labelY + LABEL_VALUE_GAP\n\n return (\n <Group key={`sankey-node-${index}`}>\n <rect\n x={node.x0}\n y={node.y0}\n width={w}\n height={Math.max(1, h)}\n fill={fill}\n rx={2}\n />\n <text\n x={labelX}\n y={labelY + primaryDy}\n textAnchor={labelAnchor}\n dominantBaseline=\"alphabetic\"\n fontSize={11}\n fontWeight={600}\n fill=\"var(--neutral-a12)\"\n >\n {node.label}\n </text>\n <foreignObject\n x={labelX}\n y={valueY}\n width={valueWidth}\n height={valueHeight}\n style={{ overflow: 'visible' }}\n >\n <div\n style={{\n lineHeight: 1.2,\n overflow: 'visible',\n }}\n >\n <NumberFlow\n value={node.value ?? 0}\n {...(valueSuffix !== undefined && {\n suffix: valueSuffix,\n })}\n {...(valueFormat !== undefined && {\n format: valueFormat,\n })}\n className=\"text-[10px] text-gray-light tabular-nums\"\n />\n </div>\n </foreignObject>\n </Group>\n )\n })}\n </Group>\n </>\n )}\n </Sankey>\n </Group>\n </svg>\n )}\n </div>\n </div>\n )\n}\n\nexport type { SankeyLink, SankeyNode }\nexport { SankeyChart, SANKEY_CATEGORY_COLORS }\n"],"mappings":"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"}
|