semiotic 3.0.0-beta.2 → 3.0.0-beta.4
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/CLAUDE.md +93 -753
- package/README.md +92 -7
- package/ai/dist/componentRegistry.js +26 -0
- package/ai/dist/{ai/mcp-server.js → mcp-server.js} +1 -1
- package/ai/dist/{ai/renderHOCToSVG.js → renderHOCToSVG.js} +2 -2
- package/dist/ChartContainer.d.ts +60 -0
- package/dist/DetailsPanel.d.ts +37 -0
- package/dist/LinkedCharts.d.ts +2 -0
- package/dist/Tooltip/Tooltip.d.ts +2 -2
- package/dist/charts/index.d.ts +1 -1
- package/dist/charts/ordinal/BarChart.d.ts +1 -0
- package/dist/charts/ordinal/BoxPlot.d.ts +1 -0
- package/dist/charts/ordinal/DonutChart.d.ts +1 -0
- package/dist/charts/ordinal/DotPlot.d.ts +1 -0
- package/dist/charts/ordinal/GroupedBarChart.d.ts +1 -0
- package/dist/charts/ordinal/Histogram.d.ts +1 -0
- package/dist/charts/ordinal/PieChart.d.ts +1 -0
- package/dist/charts/ordinal/RidgelinePlot.d.ts +1 -0
- package/dist/charts/ordinal/StackedBarChart.d.ts +1 -0
- package/dist/charts/ordinal/SwarmPlot.d.ts +1 -0
- package/dist/charts/ordinal/ViolinPlot.d.ts +1 -0
- package/dist/charts/realtime/RealtimeHeatmap.d.ts +11 -0
- package/dist/charts/realtime/RealtimeHistogram.d.ts +15 -1
- package/dist/charts/realtime/RealtimeLineChart.d.ts +6 -0
- package/dist/charts/realtime/RealtimeSwarmChart.d.ts +6 -0
- package/dist/charts/realtime/RealtimeWaterfallChart.d.ts +6 -0
- package/dist/charts/shared/annotationRules.d.ts +3 -0
- package/dist/charts/shared/colorUtils.d.ts +17 -11
- package/dist/charts/shared/hooks.d.ts +96 -1
- package/dist/charts/shared/loess.d.ts +13 -0
- package/dist/charts/shared/networkUtils.d.ts +31 -0
- package/dist/charts/shared/tooltipUtils.d.ts +16 -0
- package/dist/charts/shared/types.d.ts +17 -2
- package/dist/charts/shared/validateChartData.d.ts +2 -3
- package/dist/charts/shared/validateProps.d.ts +18 -0
- package/dist/charts/xy/AreaChart.d.ts +4 -0
- package/dist/charts/xy/BubbleChart.d.ts +6 -0
- package/dist/charts/xy/Heatmap.d.ts +4 -0
- package/dist/charts/xy/LineChart.d.ts +6 -0
- package/dist/charts/xy/Scatterplot.d.ts +4 -0
- package/dist/charts/xy/StackedAreaChart.d.ts +4 -0
- package/dist/data/fromVegaLite.d.ts +48 -0
- package/dist/export/chartConfig.d.ts +29 -0
- package/dist/export/selectionSerializer.d.ts +20 -0
- package/dist/geometry/sankeyLinks.d.ts +1 -1
- package/dist/network.min.js +1 -1
- package/dist/network.module.min.js +1 -1
- package/dist/ordinal.min.js +1 -1
- package/dist/ordinal.module.min.js +1 -1
- package/dist/realtime/types.d.ts +20 -6
- package/dist/realtime.min.js +1 -1
- package/dist/realtime.module.min.js +1 -1
- package/dist/semiotic-ai.d.ts +14 -0
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-data.d.ts +2 -0
- package/dist/semiotic-data.min.js +1 -1
- package/dist/semiotic-data.module.min.js +1 -1
- package/dist/semiotic-network.d.ts +9 -19
- package/dist/semiotic-ordinal.d.ts +12 -14
- package/dist/semiotic-xy.d.ts +12 -18
- package/dist/semiotic.d.ts +16 -13
- package/dist/semiotic.min.js +1 -1
- package/dist/semiotic.module.min.js +1 -1
- package/dist/server.min.js +1 -1
- package/dist/server.module.min.js +1 -1
- package/dist/store/ObservationStore.d.ts +61 -0
- package/dist/store/SelectionStore.d.ts +9 -1
- package/dist/store/ThemeStore.d.ts +6 -1
- package/dist/store/TooltipStore.d.ts +3 -1
- package/dist/store/createStore.d.ts +4 -1
- package/dist/store/useObservation.d.ts +18 -0
- package/dist/stream/MarginalGraphics.d.ts +1 -1
- package/dist/stream/NetworkPipelineStore.d.ts +44 -0
- package/dist/stream/OrdinalCanvasHitTester.d.ts +1 -0
- package/dist/stream/OrdinalSVGOverlay.d.ts +6 -2
- package/dist/stream/ParticlePool.d.ts +2 -1
- package/dist/stream/PipelineStore.d.ts +11 -0
- package/dist/stream/SVGOverlay.d.ts +21 -2
- package/dist/stream/SceneGraph.d.ts +1 -1
- package/dist/stream/networkTypes.d.ts +58 -1
- package/dist/stream/ordinalTypes.d.ts +13 -0
- package/dist/stream/types.d.ts +14 -0
- package/dist/types/annotationTypes.d.ts +10 -0
- package/dist/types/networkTypes.d.ts +1 -2
- package/dist/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +30 -42
- package/ai/dist/ai/componentRegistry.js +0 -45
- package/ai/dist/src/components/Annotation.js +0 -358
- package/ai/dist/src/components/AnnotationLayer/AnnotationLayer.js +0 -369
- package/ai/dist/src/components/Axis/Axis.js +0 -374
- package/ai/dist/src/components/Axis/axisTitle.js +0 -14
- package/ai/dist/src/components/Axis/index.js +0 -7
- package/ai/dist/src/components/Axis/summaryGraphic.js +0 -37
- package/ai/dist/src/components/Brush.js +0 -84
- package/ai/dist/src/components/ChartErrorBoundary.js +0 -91
- package/ai/dist/src/components/DividedLine.js +0 -65
- package/ai/dist/src/components/Legend.js +0 -140
- package/ai/dist/src/components/LinkedCharts.js +0 -95
- package/ai/dist/src/components/ThemeProvider.js +0 -79
- package/ai/dist/src/components/Tooltip/Tooltip.js +0 -309
- package/ai/dist/src/components/TooltipPositioner/index.js +0 -132
- package/ai/dist/src/components/annotationLayerBehavior/annotationHandling.js +0 -73
- package/ai/dist/src/components/annotationLayerBehavior/d3labeler.js +0 -254
- package/ai/dist/src/components/annotationRules/baseRules.js +0 -150
- package/ai/dist/src/components/annotationRules/networkframeRules.js +0 -196
- package/ai/dist/src/components/annotationRules/xyframeRules.js +0 -297
- package/ai/dist/src/components/batchWork.js +0 -35
- package/ai/dist/src/components/charts/index.js +0 -109
- package/ai/dist/src/components/charts/network/ChordDiagram.js +0 -142
- package/ai/dist/src/components/charts/network/CirclePack.js +0 -108
- package/ai/dist/src/components/charts/network/ForceDirectedGraph.js +0 -121
- package/ai/dist/src/components/charts/network/SankeyDiagram.js +0 -155
- package/ai/dist/src/components/charts/network/TreeDiagram.js +0 -110
- package/ai/dist/src/components/charts/network/Treemap.js +0 -106
- package/ai/dist/src/components/charts/ordinal/BarChart.js +0 -156
- package/ai/dist/src/components/charts/ordinal/BoxPlot.js +0 -139
- package/ai/dist/src/components/charts/ordinal/DonutChart.js +0 -130
- package/ai/dist/src/components/charts/ordinal/DotPlot.js +0 -126
- package/ai/dist/src/components/charts/ordinal/GroupedBarChart.js +0 -129
- package/ai/dist/src/components/charts/ordinal/Histogram.js +0 -132
- package/ai/dist/src/components/charts/ordinal/PieChart.js +0 -128
- package/ai/dist/src/components/charts/ordinal/RidgelinePlot.js +0 -130
- package/ai/dist/src/components/charts/ordinal/StackedBarChart.js +0 -130
- package/ai/dist/src/components/charts/ordinal/SwarmPlot.js +0 -147
- package/ai/dist/src/components/charts/ordinal/ViolinPlot.js +0 -138
- package/ai/dist/src/components/charts/realtime/RealtimeHeatmap.js +0 -79
- package/ai/dist/src/components/charts/realtime/RealtimeHistogram.js +0 -114
- package/ai/dist/src/components/charts/realtime/RealtimeLineChart.js +0 -93
- package/ai/dist/src/components/charts/realtime/RealtimeSwarmChart.js +0 -105
- package/ai/dist/src/components/charts/realtime/RealtimeWaterfallChart.js +0 -106
- package/ai/dist/src/components/charts/shared/ChartError.js +0 -72
- package/ai/dist/src/components/charts/shared/colorUtils.js +0 -138
- package/ai/dist/src/components/charts/shared/formatUtils.js +0 -213
- package/ai/dist/src/components/charts/shared/hooks.js +0 -49
- package/ai/dist/src/components/charts/shared/legendUtils.js +0 -57
- package/ai/dist/src/components/charts/shared/selectionUtils.js +0 -67
- package/ai/dist/src/components/charts/shared/tooltipUtils.js +0 -79
- package/ai/dist/src/components/charts/shared/types.js +0 -2
- package/ai/dist/src/components/charts/shared/validateChartData.js +0 -82
- package/ai/dist/src/components/charts/shared/validateProps.js +0 -736
- package/ai/dist/src/components/charts/xy/AreaChart.js +0 -230
- package/ai/dist/src/components/charts/xy/BubbleChart.js +0 -251
- package/ai/dist/src/components/charts/xy/Heatmap.js +0 -235
- package/ai/dist/src/components/charts/xy/LineChart.js +0 -307
- package/ai/dist/src/components/charts/xy/MinimapChart.js +0 -298
- package/ai/dist/src/components/charts/xy/Scatterplot.js +0 -172
- package/ai/dist/src/components/charts/xy/ScatterplotMatrix.js +0 -426
- package/ai/dist/src/components/charts/xy/StackedAreaChart.js +0 -231
- package/ai/dist/src/components/constants/coordinateNames.js +0 -11
- package/ai/dist/src/components/constants/frame_props.js +0 -251
- package/ai/dist/src/components/data/dataFunctions.js +0 -487
- package/ai/dist/src/components/data/multiAccessorUtils.js +0 -14
- package/ai/dist/src/components/data/transforms.js +0 -143
- package/ai/dist/src/components/data/unflowedFunctions.js +0 -5
- package/ai/dist/src/components/export/exportChart.js +0 -121
- package/ai/dist/src/components/generic_utilities/functions.js +0 -5
- package/ai/dist/src/components/geometry/areaDrawing.js +0 -312
- package/ai/dist/src/components/geometry/contourLayout.js +0 -73
- package/ai/dist/src/components/geometry/hexbinLayout.js +0 -163
- package/ai/dist/src/components/geometry/lineDrawing.js +0 -356
- package/ai/dist/src/components/geometry/sankeyLinks.js +0 -331
- package/ai/dist/src/components/geometry/summaryLayouts.js +0 -136
- package/ai/dist/src/components/index.js +0 -18
- package/ai/dist/src/components/processing/InteractionItems.js +0 -223
- package/ai/dist/src/components/processing/hierarchyUtils.js +0 -104
- package/ai/dist/src/components/processing/layouts/chordLayout.js +0 -58
- package/ai/dist/src/components/processing/layouts/forceLayout.js +0 -142
- package/ai/dist/src/components/processing/layouts/hierarchyLayout.js +0 -31
- package/ai/dist/src/components/processing/layouts/index.js +0 -32
- package/ai/dist/src/components/processing/layouts/sankeyLayout.js +0 -96
- package/ai/dist/src/components/processing/layouts/simpleLayouts.js +0 -34
- package/ai/dist/src/components/processing/layouts/types.js +0 -2
- package/ai/dist/src/components/processing/networkDefaults.js +0 -39
- package/ai/dist/src/components/realtime/BinAccumulator.js +0 -36
- package/ai/dist/src/components/realtime/IncrementalExtent.js +0 -55
- package/ai/dist/src/components/realtime/RingBuffer.js +0 -104
- package/ai/dist/src/components/realtime/renderers/barRenderer.js +0 -133
- package/ai/dist/src/components/realtime/renderers/candlestickRenderer.js +0 -7
- package/ai/dist/src/components/realtime/renderers/lineRenderer.js +0 -164
- package/ai/dist/src/components/realtime/renderers/swarmRenderer.js +0 -91
- package/ai/dist/src/components/realtime/renderers/types.js +0 -2
- package/ai/dist/src/components/realtime/renderers/waterfallRenderer.js +0 -163
- package/ai/dist/src/components/realtime/types.js +0 -2
- package/ai/dist/src/components/semiotic-ai.js +0 -89
- package/ai/dist/src/components/semiotic-data.js +0 -12
- package/ai/dist/src/components/semiotic-network.js +0 -38
- package/ai/dist/src/components/semiotic-ordinal.js +0 -28
- package/ai/dist/src/components/semiotic-realtime.js +0 -30
- package/ai/dist/src/components/semiotic-server.js +0 -8
- package/ai/dist/src/components/semiotic-xy.js +0 -35
- package/ai/dist/src/components/semiotic.js +0 -109
- package/ai/dist/src/components/server/renderToStaticSVG.js +0 -594
- package/ai/dist/src/components/store/SelectionStore.js +0 -91
- package/ai/dist/src/components/store/ThemeStore.js +0 -78
- package/ai/dist/src/components/store/TooltipStore.js +0 -13
- package/ai/dist/src/components/store/createStore.js +0 -81
- package/ai/dist/src/components/store/useSelection.js +0 -133
- package/ai/dist/src/components/stream/CanvasHitTester.js +0 -164
- package/ai/dist/src/components/stream/DataSourceAdapter.js +0 -99
- package/ai/dist/src/components/stream/MarginalGraphics.js +0 -266
- package/ai/dist/src/components/stream/NetworkCanvasHitTester.js +0 -228
- package/ai/dist/src/components/stream/NetworkPipelineStore.js +0 -498
- package/ai/dist/src/components/stream/NetworkSVGOverlay.js +0 -70
- package/ai/dist/src/components/stream/NetworkSceneGraph.js +0 -38
- package/ai/dist/src/components/stream/OrdinalCanvasHitTester.js +0 -146
- package/ai/dist/src/components/stream/OrdinalPipelineStore.js +0 -786
- package/ai/dist/src/components/stream/OrdinalSVGOverlay.js +0 -130
- package/ai/dist/src/components/stream/ParticlePool.js +0 -174
- package/ai/dist/src/components/stream/PipelineStore.js +0 -1243
- package/ai/dist/src/components/stream/SVGOverlay.js +0 -129
- package/ai/dist/src/components/stream/SceneGraph.js +0 -132
- package/ai/dist/src/components/stream/StreamNetworkFrame.js +0 -561
- package/ai/dist/src/components/stream/StreamOrdinalFrame.js +0 -492
- package/ai/dist/src/components/stream/StreamXYFrame.js +0 -590
- package/ai/dist/src/components/stream/accessorUtils.js +0 -20
- package/ai/dist/src/components/stream/index.js +0 -32
- package/ai/dist/src/components/stream/layouts/chordLayoutPlugin.js +0 -352
- package/ai/dist/src/components/stream/layouts/forceLayoutPlugin.js +0 -230
- package/ai/dist/src/components/stream/layouts/hierarchyLayoutPlugin.js +0 -568
- package/ai/dist/src/components/stream/layouts/index.js +0 -28
- package/ai/dist/src/components/stream/layouts/sankeyLayoutPlugin.js +0 -245
- package/ai/dist/src/components/stream/networkTypes.js +0 -17
- package/ai/dist/src/components/stream/ordinalSceneBuilders/barScene.js +0 -126
- package/ai/dist/src/components/stream/ordinalSceneBuilders/connectorScene.js +0 -62
- package/ai/dist/src/components/stream/ordinalSceneBuilders/pieScene.js +0 -33
- package/ai/dist/src/components/stream/ordinalSceneBuilders/pointScene.js +0 -63
- package/ai/dist/src/components/stream/ordinalSceneBuilders/statisticalScene.js +0 -278
- package/ai/dist/src/components/stream/ordinalSceneBuilders/timelineScene.js +0 -30
- package/ai/dist/src/components/stream/ordinalSceneBuilders/types.js +0 -2
- package/ai/dist/src/components/stream/ordinalTypes.js +0 -2
- package/ai/dist/src/components/stream/renderers/areaCanvasRenderer.js +0 -48
- package/ai/dist/src/components/stream/renderers/barCanvasRenderer.js +0 -70
- package/ai/dist/src/components/stream/renderers/boxplotCanvasRenderer.js +0 -75
- package/ai/dist/src/components/stream/renderers/candlestickCanvasRenderer.js +0 -28
- package/ai/dist/src/components/stream/renderers/connectorCanvasRenderer.js +0 -47
- package/ai/dist/src/components/stream/renderers/heatmapCanvasRenderer.js +0 -31
- package/ai/dist/src/components/stream/renderers/lineCanvasRenderer.js +0 -140
- package/ai/dist/src/components/stream/renderers/networkArcRenderer.js +0 -38
- package/ai/dist/src/components/stream/renderers/networkCircleRenderer.js +0 -37
- package/ai/dist/src/components/stream/renderers/networkEdgeRenderer.js +0 -102
- package/ai/dist/src/components/stream/renderers/networkParticleRenderer.js +0 -63
- package/ai/dist/src/components/stream/renderers/networkRectRenderer.js +0 -35
- package/ai/dist/src/components/stream/renderers/pointCanvasRenderer.js +0 -38
- package/ai/dist/src/components/stream/renderers/swarmCanvasRenderer.js +0 -10
- package/ai/dist/src/components/stream/renderers/types.js +0 -2
- package/ai/dist/src/components/stream/renderers/violinCanvasRenderer.js +0 -47
- package/ai/dist/src/components/stream/renderers/waterfallCanvasRenderer.js +0 -38
- package/ai/dist/src/components/stream/renderers/wedgeCanvasRenderer.js +0 -33
- package/ai/dist/src/components/stream/types.js +0 -2
- package/ai/dist/src/components/types/annotationTypes.js +0 -2
- package/ai/dist/src/components/types/canvasTypes.js +0 -2
- package/ai/dist/src/components/types/generalTypes.js +0 -2
- package/ai/dist/src/components/types/interactionTypes.js +0 -2
- package/ai/dist/src/components/types/legendTypes.js +0 -2
- package/ai/dist/src/components/types/networkTypes.js +0 -2
- package/ai/dist/src/components/types/ordinalTypes.js +0 -2
- package/ai/dist/src/components/types/xyTypes.js +0 -2
- package/ai/dist/src/components/useBoundingRect.js +0 -24
- package/ai/dist/src/components/visualizationLayerBehavior/axis.js +0 -301
- package/ai/dist/src/components/visualizationLayerBehavior/general.js +0 -435
- package/ai/dist/src/setupTests.js +0 -4
- package/dist/AnnotationLayer/AnnotationLayer.d.ts +0 -25
- package/dist/Axis/Axis.d.ts +0 -7
- package/dist/Axis/axisTitle.d.ts +0 -10
- package/dist/Axis/index.d.ts +0 -2
- package/dist/Axis/summaryGraphic.d.ts +0 -17
- package/dist/Brush.d.ts +0 -12
- package/dist/DividedLine.d.ts +0 -16
- package/dist/TooltipPositioner/index.d.ts +0 -7
- package/dist/annotationLayerBehavior/annotationHandling.d.ts +0 -19
- package/dist/annotationLayerBehavior/d3labeler.d.ts +0 -9
- package/dist/annotationRules/baseRules.d.ts +0 -25
- package/dist/annotationRules/networkframeRules.d.ts +0 -48
- package/dist/annotationRules/xyframeRules.d.ts +0 -117
- package/dist/batchWork.d.ts +0 -6
- package/dist/constants/coordinateNames.d.ts +0 -8
- package/dist/constants/frame_props.d.ts +0 -13
- package/dist/data/dataFunctions.d.ts +0 -45
- package/dist/data/multiAccessorUtils.d.ts +0 -1
- package/dist/data/unflowedFunctions.d.ts +0 -1
- package/dist/generic_utilities/functions.d.ts +0 -1
- package/dist/geometry/areaDrawing.d.ts +0 -21
- package/dist/geometry/contourLayout.d.ts +0 -6
- package/dist/geometry/hexbinLayout.d.ts +0 -7
- package/dist/geometry/lineDrawing.d.ts +0 -71
- package/dist/geometry/summaryLayouts.d.ts +0 -45
- package/dist/index.d.ts +0 -1
- package/dist/network.js +0 -7495
- package/dist/network.js.map +0 -1
- package/dist/network.module.js +0 -7458
- package/dist/network.module.js.map +0 -1
- package/dist/ordinal.js +0 -6497
- package/dist/ordinal.js.map +0 -1
- package/dist/ordinal.module.js +0 -6465
- package/dist/ordinal.module.js.map +0 -1
- package/dist/processing/InteractionItems.d.ts +0 -13
- package/dist/processing/hierarchyUtils.d.ts +0 -16
- package/dist/processing/layouts/chordLayout.d.ts +0 -2
- package/dist/processing/layouts/forceLayout.d.ts +0 -3
- package/dist/processing/layouts/hierarchyLayout.d.ts +0 -10
- package/dist/processing/layouts/index.d.ts +0 -8
- package/dist/processing/layouts/sankeyLayout.d.ts +0 -8
- package/dist/processing/layouts/simpleLayouts.d.ts +0 -7
- package/dist/processing/layouts/types.d.ts +0 -17
- package/dist/processing/networkDefaults.d.ts +0 -36
- package/dist/realtime/renderers/barRenderer.d.ts +0 -2
- package/dist/realtime/renderers/candlestickRenderer.d.ts +0 -2
- package/dist/realtime/renderers/lineRenderer.d.ts +0 -2
- package/dist/realtime/renderers/swarmRenderer.d.ts +0 -2
- package/dist/realtime.js +0 -7072
- package/dist/realtime.js.map +0 -1
- package/dist/realtime.module.js +0 -7043
- package/dist/realtime.module.js.map +0 -1
- package/dist/semiotic-ai.js +0 -13323
- package/dist/semiotic-ai.js.map +0 -1
- package/dist/semiotic-ai.module.js +0 -13264
- package/dist/semiotic-ai.module.js.map +0 -1
- package/dist/semiotic-data.js +0 -141
- package/dist/semiotic-data.js.map +0 -1
- package/dist/semiotic-data.module.js +0 -136
- package/dist/semiotic-data.module.js.map +0 -1
- package/dist/semiotic.js +0 -16351
- package/dist/semiotic.js.map +0 -1
- package/dist/semiotic.module.js +0 -16265
- package/dist/semiotic.module.js.map +0 -1
- package/dist/server.js +0 -5191
- package/dist/server.js.map +0 -1
- package/dist/server.module.js +0 -5166
- package/dist/server.module.js.map +0 -1
- package/dist/stream/NetworkSceneGraph.d.ts +0 -14
- package/dist/stream/index.d.ts +0 -16
- package/dist/types/canvasTypes.d.ts +0 -9
- package/dist/types/xyTypes.d.ts +0 -24
- package/dist/useBoundingRect.d.ts +0 -2
- package/dist/visualizationLayerBehavior/axis.d.ts +0 -36
- package/dist/visualizationLayerBehavior/general.d.ts +0 -80
- package/dist/xy.js +0 -6993
- package/dist/xy.js.map +0 -1
- package/dist/xy.module.js +0 -6957
- package/dist/xy.module.js.map +0 -1
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.chordLayoutPlugin = void 0;
|
|
4
|
-
const d3_chord_1 = require("d3-chord");
|
|
5
|
-
const d3_shape_1 = require("d3-shape");
|
|
6
|
-
const d3_scale_chromatic_1 = require("d3-scale-chromatic");
|
|
7
|
-
const DEFAULT_PALETTE = d3_scale_chromatic_1.schemeCategory10;
|
|
8
|
-
/**
|
|
9
|
-
* Chord layout plugin — uses d3-chord for layout computation.
|
|
10
|
-
*
|
|
11
|
-
* Produces arc scene nodes for chord group arcs and ribbon scene edges
|
|
12
|
-
* for the chord ribbons. Labels are positioned outside arcs.
|
|
13
|
-
*/
|
|
14
|
-
exports.chordLayoutPlugin = {
|
|
15
|
-
supportsStreaming: false,
|
|
16
|
-
hierarchical: false,
|
|
17
|
-
computeLayout(nodes, edges, config, size) {
|
|
18
|
-
if (nodes.length === 0)
|
|
19
|
-
return;
|
|
20
|
-
const { padAngle = 0.01, groupWidth = 20, sortGroups } = config;
|
|
21
|
-
const radius = Math.min(size[0], size[1]) / 2;
|
|
22
|
-
const innerRadius = radius - groupWidth;
|
|
23
|
-
const cx = size[0] / 2;
|
|
24
|
-
const cy = size[1] / 2;
|
|
25
|
-
const valueAccessorFn = resolveValueAccessor(config.valueAccessor);
|
|
26
|
-
// ── Build node index map ──────────────────────────────────────────
|
|
27
|
-
const nodeIndex = new Map();
|
|
28
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
29
|
-
nodeIndex.set(nodes[i].id, i);
|
|
30
|
-
}
|
|
31
|
-
// ── Build NxN matrix from edges ───────────────────────────────────
|
|
32
|
-
const n = nodes.length;
|
|
33
|
-
const matrix = Array.from({ length: n }, () => Array.from({ length: n }, () => 0));
|
|
34
|
-
for (const edge of edges) {
|
|
35
|
-
const sourceId = typeof edge.source === "string" ? edge.source : edge.source.id;
|
|
36
|
-
const targetId = typeof edge.target === "string" ? edge.target : edge.target.id;
|
|
37
|
-
const si = nodeIndex.get(sourceId);
|
|
38
|
-
const ti = nodeIndex.get(targetId);
|
|
39
|
-
if (si === undefined || ti === undefined)
|
|
40
|
-
continue;
|
|
41
|
-
const value = valueAccessorFn(edge);
|
|
42
|
-
matrix[si][ti] = value;
|
|
43
|
-
}
|
|
44
|
-
// ── Run chord generator ───────────────────────────────────────────
|
|
45
|
-
const chordGenerator = (0, d3_chord_1.chord)().padAngle(padAngle);
|
|
46
|
-
if (sortGroups) {
|
|
47
|
-
chordGenerator.sortGroups(sortGroups);
|
|
48
|
-
}
|
|
49
|
-
const chords = chordGenerator(matrix);
|
|
50
|
-
const groups = chords.groups;
|
|
51
|
-
// ── Arc generator for centroid calculation ────────────────────────
|
|
52
|
-
const arcGenerator = (0, d3_shape_1.arc)()
|
|
53
|
-
.innerRadius(innerRadius)
|
|
54
|
-
.outerRadius(radius);
|
|
55
|
-
// ── Set node positions from arc centroids ────────────────────────
|
|
56
|
-
for (const group of groups) {
|
|
57
|
-
const node = nodes[group.index];
|
|
58
|
-
const centroid = arcGenerator.centroid(group);
|
|
59
|
-
node.x = centroid[0] + cx;
|
|
60
|
-
node.y = centroid[1] + cy;
|
|
61
|
-
node.arcData = {
|
|
62
|
-
startAngle: group.startAngle,
|
|
63
|
-
endAngle: group.endAngle
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
// ── Resolve edge source/target to node references ─────────────────
|
|
67
|
-
// The HOC edge style functions need d.source/d.target as node objects
|
|
68
|
-
// (not string IDs) so they can look up colors via d.source.data.
|
|
69
|
-
for (const edge of edges) {
|
|
70
|
-
const srcId = typeof edge.source === "string" ? edge.source : edge.source.id;
|
|
71
|
-
const tgtId = typeof edge.target === "string" ? edge.target : edge.target.id;
|
|
72
|
-
const srcNode = nodes.find((n) => n.id === srcId);
|
|
73
|
-
const tgtNode = nodes.find((n) => n.id === tgtId);
|
|
74
|
-
if (srcNode)
|
|
75
|
-
edge.source = srcNode;
|
|
76
|
-
if (tgtNode)
|
|
77
|
-
edge.target = tgtNode;
|
|
78
|
-
}
|
|
79
|
-
// ── Stash chord data on edges for buildScene ─────────────────────
|
|
80
|
-
for (const generatedChord of chords) {
|
|
81
|
-
const sourceId = nodes[generatedChord.source.index].id;
|
|
82
|
-
const targetId = nodes[generatedChord.target.index].id;
|
|
83
|
-
// d3-chord always emits source.index < target.index, which may
|
|
84
|
-
// not match the original edge direction. Try both key orders.
|
|
85
|
-
const matchedEdge = edges.find((e) => {
|
|
86
|
-
const eSrc = typeof e.source === "string" ? e.source : e.source.id;
|
|
87
|
-
const eTgt = typeof e.target === "string" ? e.target : e.target.id;
|
|
88
|
-
return ((eSrc === sourceId && eTgt === targetId) ||
|
|
89
|
-
(eSrc === targetId && eTgt === sourceId));
|
|
90
|
-
});
|
|
91
|
-
if (matchedEdge) {
|
|
92
|
-
;
|
|
93
|
-
matchedEdge.chordData = generatedChord;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
buildScene(nodes, edges, config, size) {
|
|
98
|
-
const { groupWidth = 20, edgeOpacity = 0.5 } = config;
|
|
99
|
-
const radius = Math.min(size[0], size[1]) / 2;
|
|
100
|
-
const innerRadius = radius - groupWidth;
|
|
101
|
-
const cx = size[0] / 2;
|
|
102
|
-
const cy = size[1] / 2;
|
|
103
|
-
const nodeStyleFn = config.nodeStyle;
|
|
104
|
-
const edgeStyleFn = config.edgeStyle;
|
|
105
|
-
const edgeColorBy = config.edgeColorBy || "source";
|
|
106
|
-
// Auto-color palette: used when no nodeStyle is provided
|
|
107
|
-
const palette = Array.isArray(config.colorScheme)
|
|
108
|
-
? config.colorScheme
|
|
109
|
-
: DEFAULT_PALETTE;
|
|
110
|
-
// Build a node-id → color map for consistent coloring
|
|
111
|
-
const nodeColorMap = new Map();
|
|
112
|
-
nodes.forEach((n, i) => {
|
|
113
|
-
nodeColorMap.set(n.id, palette[i % palette.length]);
|
|
114
|
-
});
|
|
115
|
-
const ribbonGenerator = (0, d3_chord_1.ribbon)().radius(innerRadius);
|
|
116
|
-
const sceneNodes = [];
|
|
117
|
-
const sceneEdges = [];
|
|
118
|
-
const labels = [];
|
|
119
|
-
// ── Build arc nodes ──────────────────────────────────────────────
|
|
120
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
121
|
-
const node = nodes[i];
|
|
122
|
-
const arcData = node.arcData;
|
|
123
|
-
if (!arcData)
|
|
124
|
-
continue;
|
|
125
|
-
let fill;
|
|
126
|
-
if (nodeStyleFn) {
|
|
127
|
-
const userStyle = nodeStyleFn(node);
|
|
128
|
-
fill = userStyle.fill || nodeColorMap.get(node.id) || palette[i % palette.length];
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
fill = nodeColorMap.get(node.id) || palette[i % palette.length];
|
|
132
|
-
}
|
|
133
|
-
const userStyle = nodeStyleFn ? nodeStyleFn(node) : {};
|
|
134
|
-
const style = {
|
|
135
|
-
fill,
|
|
136
|
-
stroke: userStyle.stroke || "black",
|
|
137
|
-
strokeWidth: userStyle.strokeWidth ?? 1,
|
|
138
|
-
opacity: userStyle.opacity
|
|
139
|
-
};
|
|
140
|
-
// d3-chord angles start at 12 o'clock; canvas arc() starts at 3 o'clock
|
|
141
|
-
// Offset by -PI/2 to align arcs with labels and ribbons
|
|
142
|
-
sceneNodes.push({
|
|
143
|
-
type: "arc",
|
|
144
|
-
cx,
|
|
145
|
-
cy,
|
|
146
|
-
innerR: innerRadius,
|
|
147
|
-
outerR: radius,
|
|
148
|
-
startAngle: arcData.startAngle - Math.PI / 2,
|
|
149
|
-
endAngle: arcData.endAngle - Math.PI / 2,
|
|
150
|
-
style,
|
|
151
|
-
datum: node,
|
|
152
|
-
id: node.id,
|
|
153
|
-
label: node.id
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
// ── Build ribbon edges ───────────────────────────────────────────
|
|
157
|
-
// d3-chord ribbon paths are centered at (0,0). Offset every
|
|
158
|
-
// coordinate by (cx, cy) so they align with the arc nodes.
|
|
159
|
-
for (const edge of edges) {
|
|
160
|
-
const chordData = edge.chordData;
|
|
161
|
-
if (!chordData)
|
|
162
|
-
continue;
|
|
163
|
-
// Offset chord angles by -PI/2 to match arc offset (12 o'clock → 3 o'clock)
|
|
164
|
-
const offsetChord = {
|
|
165
|
-
source: { ...chordData.source, startAngle: chordData.source.startAngle - Math.PI / 2, endAngle: chordData.source.endAngle - Math.PI / 2 },
|
|
166
|
-
target: { ...chordData.target, startAngle: chordData.target.startAngle - Math.PI / 2, endAngle: chordData.target.endAngle - Math.PI / 2 }
|
|
167
|
-
};
|
|
168
|
-
const rawPath = ribbonGenerator(offsetChord);
|
|
169
|
-
if (!rawPath)
|
|
170
|
-
continue;
|
|
171
|
-
const pathD = translateSvgPath(rawPath, cx, cy);
|
|
172
|
-
// Resolve edge fill — use edgeStyle if provided, otherwise
|
|
173
|
-
// inherit from source or target node color
|
|
174
|
-
let fill = "#999";
|
|
175
|
-
if (edgeStyleFn) {
|
|
176
|
-
const userStyle = edgeStyleFn(edge);
|
|
177
|
-
fill = userStyle.fill || fill;
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
// Auto-color by source or target node
|
|
181
|
-
const srcNode = typeof edge.source === "object" ? edge.source : null;
|
|
182
|
-
const tgtNode = typeof edge.target === "object" ? edge.target : null;
|
|
183
|
-
if (edgeColorBy === "target" && tgtNode) {
|
|
184
|
-
fill = nodeColorMap.get(tgtNode.id) || fill;
|
|
185
|
-
}
|
|
186
|
-
else if (srcNode) {
|
|
187
|
-
fill = nodeColorMap.get(srcNode.id) || fill;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
const userStyle = edgeStyleFn ? edgeStyleFn(edge) : {};
|
|
191
|
-
const style = {
|
|
192
|
-
fill,
|
|
193
|
-
fillOpacity: userStyle.fillOpacity ?? edgeOpacity,
|
|
194
|
-
stroke: userStyle.stroke || "none",
|
|
195
|
-
strokeWidth: userStyle.strokeWidth,
|
|
196
|
-
opacity: userStyle.opacity
|
|
197
|
-
};
|
|
198
|
-
sceneEdges.push({
|
|
199
|
-
type: "ribbon",
|
|
200
|
-
pathD,
|
|
201
|
-
style,
|
|
202
|
-
datum: edge
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
// ── Build labels ─────────────────────────────────────────────────
|
|
206
|
-
if (config.showLabels !== false) {
|
|
207
|
-
const labelFn = resolveLabelFn(config.nodeLabel);
|
|
208
|
-
const labelRadius = radius + 12;
|
|
209
|
-
for (const node of nodes) {
|
|
210
|
-
const arcData = node.arcData;
|
|
211
|
-
if (!arcData)
|
|
212
|
-
continue;
|
|
213
|
-
const text = labelFn ? labelFn(node) : node.id;
|
|
214
|
-
if (!text)
|
|
215
|
-
continue;
|
|
216
|
-
const midAngle = (arcData.startAngle + arcData.endAngle) / 2;
|
|
217
|
-
// Angles in d3-chord start from 12 o'clock (top), going clockwise.
|
|
218
|
-
// Convert to standard x/y: subtract PI/2.
|
|
219
|
-
const angle = midAngle - Math.PI / 2;
|
|
220
|
-
const lx = cx + Math.cos(angle) * labelRadius;
|
|
221
|
-
const ly = cy + Math.sin(angle) * labelRadius;
|
|
222
|
-
// Anchor depends on which side of the circle the label is on
|
|
223
|
-
const anchor = midAngle > Math.PI ? "end" : "start";
|
|
224
|
-
labels.push({
|
|
225
|
-
x: lx,
|
|
226
|
-
y: ly,
|
|
227
|
-
text: String(text),
|
|
228
|
-
anchor,
|
|
229
|
-
baseline: "middle",
|
|
230
|
-
fontSize: 11
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
return { sceneNodes, sceneEdges, labels };
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
function resolveLabelFn(nodeLabel) {
|
|
238
|
-
if (!nodeLabel)
|
|
239
|
-
return null;
|
|
240
|
-
if (typeof nodeLabel === "function")
|
|
241
|
-
return nodeLabel;
|
|
242
|
-
return (d) => d[nodeLabel] || d.id;
|
|
243
|
-
}
|
|
244
|
-
function resolveValueAccessor(valueAccessor) {
|
|
245
|
-
if (!valueAccessor)
|
|
246
|
-
return (d) => d.value ?? 1;
|
|
247
|
-
if (typeof valueAccessor === "function")
|
|
248
|
-
return valueAccessor;
|
|
249
|
-
return (d) => d[valueAccessor] ?? 1;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Translate all absolute coordinates in an SVG path string by (dx, dy).
|
|
253
|
-
*
|
|
254
|
-
* d3-chord ribbon() produces paths using only M, C, Q, L, A, and Z commands
|
|
255
|
-
* with absolute coordinates. We parse the numeric values and offset the
|
|
256
|
-
* positional ones. For arc (A) commands the positional values are the last
|
|
257
|
-
* two numbers in each 7-parameter group.
|
|
258
|
-
*/
|
|
259
|
-
function translateSvgPath(d, dx, dy) {
|
|
260
|
-
// Tokenize: split into command letters and number tokens
|
|
261
|
-
const tokens = d.match(/[a-zA-Z]|[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?/g);
|
|
262
|
-
if (!tokens)
|
|
263
|
-
return d;
|
|
264
|
-
const out = [];
|
|
265
|
-
let i = 0;
|
|
266
|
-
while (i < tokens.length) {
|
|
267
|
-
const cmd = tokens[i];
|
|
268
|
-
if (cmd === "M" || cmd === "L") {
|
|
269
|
-
out.push(cmd);
|
|
270
|
-
i++;
|
|
271
|
-
// Pairs of (x, y) follow
|
|
272
|
-
while (i < tokens.length && !isNaN(Number(tokens[i]))) {
|
|
273
|
-
out.push(String(Number(tokens[i]) + dx));
|
|
274
|
-
i++;
|
|
275
|
-
if (i < tokens.length && !isNaN(Number(tokens[i]))) {
|
|
276
|
-
out.push(String(Number(tokens[i]) + dy));
|
|
277
|
-
i++;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
else if (cmd === "C") {
|
|
282
|
-
out.push(cmd);
|
|
283
|
-
i++;
|
|
284
|
-
// Triplets of (x,y) control points
|
|
285
|
-
while (i < tokens.length && !isNaN(Number(tokens[i]))) {
|
|
286
|
-
for (let p = 0; p < 3 && i < tokens.length; p++) {
|
|
287
|
-
if (isNaN(Number(tokens[i])))
|
|
288
|
-
break;
|
|
289
|
-
out.push(String(Number(tokens[i]) + dx));
|
|
290
|
-
i++;
|
|
291
|
-
if (i < tokens.length && !isNaN(Number(tokens[i]))) {
|
|
292
|
-
out.push(String(Number(tokens[i]) + dy));
|
|
293
|
-
i++;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
else if (cmd === "Q") {
|
|
299
|
-
out.push(cmd);
|
|
300
|
-
i++;
|
|
301
|
-
// Pairs of (x,y) — 2 pairs per Q
|
|
302
|
-
while (i < tokens.length && !isNaN(Number(tokens[i]))) {
|
|
303
|
-
for (let p = 0; p < 2 && i < tokens.length; p++) {
|
|
304
|
-
if (isNaN(Number(tokens[i])))
|
|
305
|
-
break;
|
|
306
|
-
out.push(String(Number(tokens[i]) + dx));
|
|
307
|
-
i++;
|
|
308
|
-
if (i < tokens.length && !isNaN(Number(tokens[i]))) {
|
|
309
|
-
out.push(String(Number(tokens[i]) + dy));
|
|
310
|
-
i++;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
else if (cmd === "A") {
|
|
316
|
-
out.push(cmd);
|
|
317
|
-
i++;
|
|
318
|
-
// Arc: rx ry x-rotation large-arc-flag sweep-flag x y
|
|
319
|
-
while (i < tokens.length && !isNaN(Number(tokens[i]))) {
|
|
320
|
-
// rx, ry — no offset
|
|
321
|
-
out.push(tokens[i++]);
|
|
322
|
-
if (i < tokens.length)
|
|
323
|
-
out.push(tokens[i++]); // ry
|
|
324
|
-
if (i < tokens.length)
|
|
325
|
-
out.push(tokens[i++]); // x-rotation
|
|
326
|
-
if (i < tokens.length)
|
|
327
|
-
out.push(tokens[i++]); // large-arc-flag
|
|
328
|
-
if (i < tokens.length)
|
|
329
|
-
out.push(tokens[i++]); // sweep-flag
|
|
330
|
-
// x, y — offset
|
|
331
|
-
if (i < tokens.length) {
|
|
332
|
-
out.push(String(Number(tokens[i]) + dx));
|
|
333
|
-
i++;
|
|
334
|
-
}
|
|
335
|
-
if (i < tokens.length) {
|
|
336
|
-
out.push(String(Number(tokens[i]) + dy));
|
|
337
|
-
i++;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
else if (cmd === "Z" || cmd === "z") {
|
|
342
|
-
out.push(cmd);
|
|
343
|
-
i++;
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
// Unknown or lowercase relative command — pass through
|
|
347
|
-
out.push(tokens[i]);
|
|
348
|
-
i++;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
return out.join(" ");
|
|
352
|
-
}
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.forceLayoutPlugin = void 0;
|
|
4
|
-
const d3_force_1 = require("d3-force");
|
|
5
|
-
const d3_scale_1 = require("d3-scale");
|
|
6
|
-
const d3_array_1 = require("d3-array");
|
|
7
|
-
const d3_scale_chromatic_1 = require("d3-scale-chromatic");
|
|
8
|
-
/**
|
|
9
|
-
* Force-directed layout plugin — uses d3-force for physics-based node positioning.
|
|
10
|
-
*
|
|
11
|
-
* Produces circle scene nodes and line scene edges. Runs the force simulation
|
|
12
|
-
* synchronously for a configurable number of iterations, using phyllotaxis
|
|
13
|
-
* spiral for deterministic initial positions.
|
|
14
|
-
*/
|
|
15
|
-
exports.forceLayoutPlugin = {
|
|
16
|
-
supportsStreaming: false,
|
|
17
|
-
hierarchical: false,
|
|
18
|
-
computeLayout(nodes, edges, config, size) {
|
|
19
|
-
if (nodes.length === 0)
|
|
20
|
-
return;
|
|
21
|
-
// Adaptive iteration count: reduce iterations for large networks
|
|
22
|
-
const nodeCount = nodes.length;
|
|
23
|
-
const adaptiveIterations = Math.max(50, Math.min(300, Math.floor(300 - (nodeCount - 30) * 2)));
|
|
24
|
-
const iterations = config.iterations ?? adaptiveIterations;
|
|
25
|
-
const forceStrength = config.forceStrength ?? 0.1;
|
|
26
|
-
// Set deterministic initial positions using phyllotaxis spiral.
|
|
27
|
-
// d3-force uses Math.random() for unpositioned nodes which produces
|
|
28
|
-
// different layouts on every render. A phyllotaxis spiral gives
|
|
29
|
-
// evenly-distributed starting positions based on index alone.
|
|
30
|
-
// RealtimeNode initialises x/y to 0, so we treat (0,0) as "unpositioned".
|
|
31
|
-
const cx = size[0] / 2;
|
|
32
|
-
const cy = size[1] / 2;
|
|
33
|
-
const goldenAngle = Math.PI * (3 - Math.sqrt(5));
|
|
34
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
35
|
-
const node = nodes[i];
|
|
36
|
-
if (node.x == null || node.y == null || (node.x === 0 && node.y === 0)) {
|
|
37
|
-
const r = Math.sqrt(i + 0.5) * 10;
|
|
38
|
-
const theta = i * goldenAngle;
|
|
39
|
-
node.x = cx + r * Math.cos(theta);
|
|
40
|
-
node.y = cy + r * Math.sin(theta);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// Build node size accessor for charge strength
|
|
44
|
-
const nodeSizeFn = resolveNodeSizeFn(config.nodeSize, config.nodeSizeRange, nodes);
|
|
45
|
-
const nodeRadius = (d) => nodeSizeFn(d);
|
|
46
|
-
// Configure link force
|
|
47
|
-
const linkForce = (0, d3_force_1.forceLink)()
|
|
48
|
-
.strength((d) => Math.min(2.5, d.weight ? d.weight * forceStrength : forceStrength))
|
|
49
|
-
.id((d) => d.id);
|
|
50
|
-
// Build simulation
|
|
51
|
-
const forceMod = size[1] / size[0];
|
|
52
|
-
const simulation = (0, d3_force_1.forceSimulation)()
|
|
53
|
-
.force("charge", (0, d3_force_1.forceManyBody)().strength((d) => -25 * nodeRadius(d)))
|
|
54
|
-
.force("x", (0, d3_force_1.forceX)(size[0] / 2).strength(forceMod * 0.1))
|
|
55
|
-
.force("y", (0, d3_force_1.forceY)(size[1] / 2).strength(0.1));
|
|
56
|
-
simulation.nodes(nodes);
|
|
57
|
-
if (edges.length > 0) {
|
|
58
|
-
// Resolve edge source/target to id strings for d3-force linking
|
|
59
|
-
const linkData = edges.map((e) => ({
|
|
60
|
-
...e,
|
|
61
|
-
source: typeof e.source === "string" ? e.source : e.source.id,
|
|
62
|
-
target: typeof e.target === "string" ? e.target : e.target.id
|
|
63
|
-
}));
|
|
64
|
-
simulation.force("link", linkForce);
|
|
65
|
-
simulation.force("link").links(linkData);
|
|
66
|
-
}
|
|
67
|
-
// Reset alpha if too cold
|
|
68
|
-
if (simulation.alpha() < 0.1) {
|
|
69
|
-
simulation.alpha(1);
|
|
70
|
-
}
|
|
71
|
-
simulation.stop();
|
|
72
|
-
// Run synchronously
|
|
73
|
-
for (let i = 0; i < iterations; ++i) {
|
|
74
|
-
simulation.tick();
|
|
75
|
-
}
|
|
76
|
-
// Resolve edge source/target to node object references so that
|
|
77
|
-
// HOC style functions can access d.source.data for color lookups.
|
|
78
|
-
for (const edge of edges) {
|
|
79
|
-
if (typeof edge.source === "string") {
|
|
80
|
-
const n = nodes.find((nd) => nd.id === edge.source);
|
|
81
|
-
if (n)
|
|
82
|
-
edge.source = n;
|
|
83
|
-
}
|
|
84
|
-
if (typeof edge.target === "string") {
|
|
85
|
-
const n = nodes.find((nd) => nd.id === edge.target);
|
|
86
|
-
if (n)
|
|
87
|
-
edge.target = n;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
buildScene(nodes, edges, config, size) {
|
|
92
|
-
const nodeStyleFn = config.nodeStyle;
|
|
93
|
-
const edgeStyleFn = config.edgeStyle;
|
|
94
|
-
const nodeSizeFn = resolveNodeSizeFn(config.nodeSize, config.nodeSizeRange, nodes);
|
|
95
|
-
// Auto-color palette for when no nodeStyle is provided
|
|
96
|
-
const palette = Array.isArray(config.colorScheme)
|
|
97
|
-
? config.colorScheme
|
|
98
|
-
: d3_scale_chromatic_1.schemeCategory10;
|
|
99
|
-
const nodeColorMap = new Map();
|
|
100
|
-
nodes.forEach((n, i) => {
|
|
101
|
-
nodeColorMap.set(n.id, palette[i % palette.length]);
|
|
102
|
-
});
|
|
103
|
-
const sceneNodes = [];
|
|
104
|
-
const sceneEdges = [];
|
|
105
|
-
const labels = [];
|
|
106
|
-
// Build circle nodes
|
|
107
|
-
for (const node of nodes) {
|
|
108
|
-
if (node.x == null || node.y == null)
|
|
109
|
-
continue;
|
|
110
|
-
const r = nodeSizeFn(node);
|
|
111
|
-
const userStyle = nodeStyleFn ? nodeStyleFn(node) : {};
|
|
112
|
-
const style = {
|
|
113
|
-
fill: userStyle.fill || nodeColorMap.get(node.id) || "#007bff",
|
|
114
|
-
stroke: userStyle.stroke || "#fff",
|
|
115
|
-
strokeWidth: userStyle.strokeWidth ?? 2,
|
|
116
|
-
opacity: userStyle.opacity
|
|
117
|
-
};
|
|
118
|
-
sceneNodes.push({
|
|
119
|
-
type: "circle",
|
|
120
|
-
cx: node.x,
|
|
121
|
-
cy: node.y,
|
|
122
|
-
r,
|
|
123
|
-
style,
|
|
124
|
-
datum: node,
|
|
125
|
-
id: node.id,
|
|
126
|
-
label: node.id
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
// Build line edges
|
|
130
|
-
for (const edge of edges) {
|
|
131
|
-
const sourceNode = typeof edge.source === "object" ? edge.source : findNode(nodes, edge.source);
|
|
132
|
-
const targetNode = typeof edge.target === "object" ? edge.target : findNode(nodes, edge.target);
|
|
133
|
-
if (!sourceNode || !targetNode)
|
|
134
|
-
continue;
|
|
135
|
-
if (sourceNode.x == null || sourceNode.y == null)
|
|
136
|
-
continue;
|
|
137
|
-
if (targetNode.x == null || targetNode.y == null)
|
|
138
|
-
continue;
|
|
139
|
-
const userStyle = edgeStyleFn ? edgeStyleFn(edge) : {};
|
|
140
|
-
const style = {
|
|
141
|
-
stroke: userStyle.stroke || "#999",
|
|
142
|
-
strokeWidth: userStyle.strokeWidth ?? 1,
|
|
143
|
-
opacity: userStyle.opacity ?? 0.6
|
|
144
|
-
};
|
|
145
|
-
sceneEdges.push({
|
|
146
|
-
type: "line",
|
|
147
|
-
x1: sourceNode.x,
|
|
148
|
-
y1: sourceNode.y,
|
|
149
|
-
x2: targetNode.x,
|
|
150
|
-
y2: targetNode.y,
|
|
151
|
-
style,
|
|
152
|
-
datum: edge
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
// Build labels
|
|
156
|
-
if (config.showLabels !== false) {
|
|
157
|
-
const labelFn = resolveLabelFn(config.nodeLabel);
|
|
158
|
-
for (const node of nodes) {
|
|
159
|
-
if (node.x == null || node.y == null)
|
|
160
|
-
continue;
|
|
161
|
-
const text = labelFn ? labelFn(node) : node.id;
|
|
162
|
-
if (!text)
|
|
163
|
-
continue;
|
|
164
|
-
const r = nodeSizeFn(node);
|
|
165
|
-
labels.push({
|
|
166
|
-
x: node.x,
|
|
167
|
-
y: node.y - r - 4,
|
|
168
|
-
text: String(text),
|
|
169
|
-
anchor: "middle",
|
|
170
|
-
baseline: "auto",
|
|
171
|
-
fontSize: 11
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return { sceneNodes, sceneEdges, labels };
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
179
|
-
function findNode(nodes, id) {
|
|
180
|
-
return nodes.find((n) => n.id === id);
|
|
181
|
-
}
|
|
182
|
-
function resolveLabelFn(nodeLabel) {
|
|
183
|
-
if (!nodeLabel)
|
|
184
|
-
return null;
|
|
185
|
-
if (typeof nodeLabel === "function")
|
|
186
|
-
return nodeLabel;
|
|
187
|
-
return (d) => d[nodeLabel] || d.id;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Build a function that returns a node radius. If `nodeSize` is a number,
|
|
191
|
-
* use it directly. If it is a string accessor, look up `node.data[nodeSize]`
|
|
192
|
-
* and scale the result to `nodeSizeRange`. If it is a function, call it.
|
|
193
|
-
* Falls back to a default radius of 8.
|
|
194
|
-
*/
|
|
195
|
-
function resolveNodeSizeFn(nodeSize, nodeSizeRange, allNodes) {
|
|
196
|
-
if (nodeSize == null) {
|
|
197
|
-
return () => 8;
|
|
198
|
-
}
|
|
199
|
-
if (typeof nodeSize === "number") {
|
|
200
|
-
return () => nodeSize;
|
|
201
|
-
}
|
|
202
|
-
if (typeof nodeSize === "function") {
|
|
203
|
-
return (node) => nodeSize(node) || 8;
|
|
204
|
-
}
|
|
205
|
-
// String accessor: look up value on node.data and scale to range
|
|
206
|
-
const range = nodeSizeRange || [5, 20];
|
|
207
|
-
// Extract all numeric values to compute domain
|
|
208
|
-
const values = allNodes
|
|
209
|
-
.map((n) => n.data?.[nodeSize])
|
|
210
|
-
.filter((v) => v != null && typeof v === "number");
|
|
211
|
-
if (values.length === 0) {
|
|
212
|
-
return () => range[0];
|
|
213
|
-
}
|
|
214
|
-
const domainMin = (0, d3_array_1.min)(values) ?? 0;
|
|
215
|
-
const domainMax = (0, d3_array_1.max)(values) ?? 1;
|
|
216
|
-
// If all values are the same, return the midpoint of the range
|
|
217
|
-
if (domainMin === domainMax) {
|
|
218
|
-
return () => (range[0] + range[1]) / 2;
|
|
219
|
-
}
|
|
220
|
-
const scale = (0, d3_scale_1.scaleLinear)()
|
|
221
|
-
.domain([domainMin, domainMax])
|
|
222
|
-
.range(range)
|
|
223
|
-
.clamp(true);
|
|
224
|
-
return (node) => {
|
|
225
|
-
const raw = node.data?.[nodeSize];
|
|
226
|
-
if (raw == null || typeof raw !== "number")
|
|
227
|
-
return range[0];
|
|
228
|
-
return scale(raw);
|
|
229
|
-
};
|
|
230
|
-
}
|