semiotic 2.0.2 → 3.0.0-beta.1
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 +530 -0
- package/README.md +190 -37
- package/ai/cli.js +48 -0
- package/ai/dist/ai/componentRegistry.js +45 -0
- package/ai/dist/ai/mcp-server.js +99 -0
- package/ai/dist/ai/renderHOCToSVG.js +77 -0
- package/ai/dist/src/components/Annotation.js +358 -0
- package/ai/dist/src/components/AnnotationLayer/AnnotationLayer.js +369 -0
- package/ai/dist/src/components/Axis/Axis.js +373 -0
- package/ai/dist/src/components/Axis/axisTitle.js +14 -0
- package/ai/dist/src/components/Axis/index.js +7 -0
- package/ai/dist/src/components/Axis/summaryGraphic.js +37 -0
- package/ai/dist/src/components/Brush.js +84 -0
- package/ai/dist/src/components/DividedLine.js +65 -0
- package/ai/dist/src/components/FacetController.js +259 -0
- package/ai/dist/src/components/Frame.js +139 -0
- package/ai/dist/src/components/InteractionLayer.js +328 -0
- package/ai/dist/src/components/Legend.js +140 -0
- package/ai/dist/src/components/MiniMap.js +75 -0
- package/ai/dist/src/components/MinimapXYFrame.js +99 -0
- package/ai/dist/src/components/NetworkFrame.js +335 -0
- package/ai/dist/src/components/OrdinalFrame.js +437 -0
- package/ai/dist/src/components/ResponsiveFrame.js +68 -0
- package/ai/dist/src/components/ResponsiveMinimapXYFrame.js +11 -0
- package/ai/dist/src/components/ResponsiveNetworkFrame.js +11 -0
- package/ai/dist/src/components/ResponsiveOrdinalFrame.js +11 -0
- package/ai/dist/src/components/ResponsiveXYFrame.js +10 -0
- package/ai/dist/src/components/SparkFrame.js +113 -0
- package/ai/dist/src/components/SparkNetworkFrame.js +11 -0
- package/ai/dist/src/components/SparkOrdinalFrame.js +11 -0
- package/ai/dist/src/components/SparkXYFrame.js +11 -0
- package/ai/dist/src/components/Tooltip/Tooltip.js +304 -0
- package/ai/dist/src/components/TooltipPositioner/index.js +132 -0
- package/ai/dist/src/components/VisualizationLayer.js +395 -0
- package/ai/dist/src/components/XYFrame.js +524 -0
- package/ai/dist/src/components/annotationLayerBehavior/annotationHandling.js +73 -0
- package/ai/dist/src/components/annotationLayerBehavior/d3labeler.js +254 -0
- package/ai/dist/src/components/annotationRules/baseRules.js +150 -0
- package/ai/dist/src/components/annotationRules/networkframeRules.js +198 -0
- package/ai/dist/src/components/annotationRules/orframeRules.js +695 -0
- package/ai/dist/src/components/annotationRules/xyframeRules.js +299 -0
- package/ai/dist/src/components/batchWork.js +35 -0
- package/ai/dist/src/components/charts/index.js +96 -0
- package/ai/dist/src/components/charts/network/ChordDiagram.js +245 -0
- package/ai/dist/src/components/charts/network/CirclePack.js +177 -0
- package/ai/dist/src/components/charts/network/ForceDirectedGraph.js +248 -0
- package/ai/dist/src/components/charts/network/SankeyDiagram.js +305 -0
- package/ai/dist/src/components/charts/network/TreeDiagram.js +268 -0
- package/ai/dist/src/components/charts/network/Treemap.js +177 -0
- package/ai/dist/src/components/charts/ordinal/BarChart.js +191 -0
- package/ai/dist/src/components/charts/ordinal/BoxPlot.js +235 -0
- package/ai/dist/src/components/charts/ordinal/DonutChart.js +178 -0
- package/ai/dist/src/components/charts/ordinal/DotPlot.js +194 -0
- package/ai/dist/src/components/charts/ordinal/GroupedBarChart.js +194 -0
- package/ai/dist/src/components/charts/ordinal/PieChart.js +155 -0
- package/ai/dist/src/components/charts/ordinal/StackedBarChart.js +213 -0
- package/ai/dist/src/components/charts/ordinal/SwarmPlot.js +219 -0
- package/ai/dist/src/components/charts/realtime/RealtimeBarChart.js +91 -0
- package/ai/dist/src/components/charts/realtime/RealtimeLineChart.js +73 -0
- package/ai/dist/src/components/charts/realtime/RealtimeSwarmChart.js +85 -0
- package/ai/dist/src/components/charts/realtime/RealtimeWaterfallChart.js +86 -0
- package/ai/dist/src/components/charts/shared/ChartError.js +72 -0
- package/ai/dist/src/components/charts/shared/colorUtils.js +138 -0
- package/ai/dist/src/components/charts/shared/formatUtils.js +176 -0
- package/ai/dist/src/components/charts/shared/hooks.js +49 -0
- package/ai/dist/src/components/charts/shared/legendUtils.js +57 -0
- package/ai/dist/src/components/charts/shared/types.js +2 -0
- package/ai/dist/src/components/charts/shared/validateChartData.js +82 -0
- package/ai/dist/src/components/charts/shared/validateProps.js +640 -0
- package/ai/dist/src/components/charts/xy/AreaChart.js +220 -0
- package/ai/dist/src/components/charts/xy/BubbleChart.js +222 -0
- package/ai/dist/src/components/charts/xy/Heatmap.js +230 -0
- package/ai/dist/src/components/charts/xy/LineChart.js +302 -0
- package/ai/dist/src/components/charts/xy/Scatterplot.js +136 -0
- package/ai/dist/src/components/charts/xy/StackedAreaChart.js +220 -0
- package/ai/dist/src/components/constants/coordinateNames.js +11 -0
- package/ai/dist/src/components/constants/frame_props.js +251 -0
- package/ai/dist/src/components/constants/jsx.js +71 -0
- package/ai/dist/src/components/data/dataFunctions.js +473 -0
- package/ai/dist/src/components/data/multiAccessorUtils.js +14 -0
- package/ai/dist/src/components/data/networkPipelineCache.js +43 -0
- package/ai/dist/src/components/data/ordinalPipelineCache.js +53 -0
- package/ai/dist/src/components/data/unflowedFunctions.js +5 -0
- package/ai/dist/src/components/data/xyPipelineCache.js +49 -0
- package/ai/dist/src/components/generic_utilities/functions.js +5 -0
- package/ai/dist/src/components/index.js +145 -0
- package/ai/dist/src/components/interactionLayerBehavior/InteractionCanvas.js +128 -0
- package/ai/dist/src/components/processing/InteractionItems.js +223 -0
- package/ai/dist/src/components/processing/hierarchyUtils.js +104 -0
- package/ai/dist/src/components/processing/layouts/chordLayout.js +58 -0
- package/ai/dist/src/components/processing/layouts/forceLayout.js +142 -0
- package/ai/dist/src/components/processing/layouts/hierarchyLayout.js +31 -0
- package/ai/dist/src/components/processing/layouts/index.js +32 -0
- package/ai/dist/src/components/processing/layouts/sankeyLayout.js +96 -0
- package/ai/dist/src/components/processing/layouts/simpleLayouts.js +34 -0
- package/ai/dist/src/components/processing/layouts/types.js +2 -0
- package/ai/dist/src/components/processing/network.js +771 -0
- package/ai/dist/src/components/processing/networkDefaults.js +39 -0
- package/ai/dist/src/components/processing/networkLayoutHelpers.js +98 -0
- package/ai/dist/src/components/processing/ordinal.js +889 -0
- package/ai/dist/src/components/processing/ordinalConstants.js +23 -0
- package/ai/dist/src/components/processing/ordinalOverlays.js +88 -0
- package/ai/dist/src/components/processing/ordinalRenderPipeline.js +196 -0
- package/ai/dist/src/components/processing/xyDrawing.js +484 -0
- package/ai/dist/src/components/realtime/BinAccumulator.js +36 -0
- package/ai/dist/src/components/realtime/IncrementalExtent.js +55 -0
- package/ai/dist/src/components/realtime/RealtimeFrame.js +710 -0
- package/ai/dist/src/components/realtime/RingBuffer.js +104 -0
- package/ai/dist/src/components/realtime/renderers/barRenderer.js +133 -0
- package/ai/dist/src/components/realtime/renderers/candlestickRenderer.js +7 -0
- package/ai/dist/src/components/realtime/renderers/lineRenderer.js +164 -0
- package/ai/dist/src/components/realtime/renderers/swarmRenderer.js +91 -0
- package/ai/dist/src/components/realtime/renderers/types.js +2 -0
- package/ai/dist/src/components/realtime/renderers/waterfallRenderer.js +163 -0
- package/ai/dist/src/components/realtime/types.js +2 -0
- package/ai/dist/src/components/semiotic-ai.js +66 -0
- package/ai/dist/src/components/semiotic-network.js +30 -0
- package/ai/dist/src/components/semiotic-ordinal.js +28 -0
- package/ai/dist/src/components/semiotic-realtime.js +37 -0
- package/ai/dist/src/components/semiotic-server.js +8 -0
- package/ai/dist/src/components/semiotic-xy.js +41 -0
- package/ai/dist/src/components/semiotic.js +101 -0
- package/ai/dist/src/components/server/renderToStaticSVG.js +392 -0
- package/ai/dist/src/components/store/TooltipStore.js +13 -0
- package/ai/dist/src/components/store/createStore.js +77 -0
- package/ai/dist/src/components/svg/SvgHelper.js +308 -0
- package/ai/dist/src/components/svg/areaDrawing.js +312 -0
- package/ai/dist/src/components/svg/boxplotRenderer.js +441 -0
- package/ai/dist/src/components/svg/bucketizedRenderer.js +677 -0
- package/ai/dist/src/components/svg/ckbinsRenderer.js +92 -0
- package/ai/dist/src/components/svg/ckmeans.js +238 -0
- package/ai/dist/src/components/svg/contourLayout.js +73 -0
- package/ai/dist/src/components/svg/contourRenderer.js +53 -0
- package/ai/dist/src/components/svg/edgeGenerators.js +181 -0
- package/ai/dist/src/components/svg/frameFunctions.js +579 -0
- package/ai/dist/src/components/svg/graphAlgorithms.js +138 -0
- package/ai/dist/src/components/svg/hexbinLayout.js +163 -0
- package/ai/dist/src/components/svg/lineDrawing.js +427 -0
- package/ai/dist/src/components/svg/networkDrawing.js +207 -0
- package/ai/dist/src/components/svg/nodeGenerators.js +131 -0
- package/ai/dist/src/components/svg/pieceDrawing.js +110 -0
- package/ai/dist/src/components/svg/pieceLayouts.js +588 -0
- package/ai/dist/src/components/svg/sankeyLinks.js +143 -0
- package/ai/dist/src/components/svg/summaryAxis.js +48 -0
- package/ai/dist/src/components/svg/summaryLayouts.js +202 -0
- package/ai/dist/src/components/svg/swarmLayout.js +128 -0
- package/ai/dist/src/components/types/annotationTypes.js +2 -0
- package/ai/dist/src/components/types/canvasTypes.js +2 -0
- package/ai/dist/src/components/types/generalTypes.js +2 -0
- package/ai/dist/src/components/types/interactionTypes.js +2 -0
- package/ai/dist/src/components/types/legendTypes.js +2 -0
- package/ai/dist/src/components/types/networkTypes.js +2 -0
- package/ai/dist/src/components/types/ordinalTypes.js +2 -0
- package/ai/dist/src/components/types/xyTypes.js +2 -0
- package/ai/dist/src/components/useBoundingRect.js +24 -0
- package/ai/dist/src/components/useDerivedStateFromProps.js +25 -0
- package/ai/dist/src/components/useLegacyUnmountCallback.js +21 -0
- package/ai/dist/src/components/visualizationLayerBehavior/axis.js +249 -0
- package/ai/dist/src/components/visualizationLayerBehavior/general.js +435 -0
- package/ai/dist/src/setupTests.js +4 -0
- package/ai/examples.md +394 -0
- package/ai/schema.json +1178 -0
- package/ai/system-prompt.md +38 -0
- package/dist/Annotation.d.ts +3 -0
- package/dist/AnnotationLayer/AnnotationLayer.d.ts +25 -0
- package/dist/Axis/Axis.d.ts +7 -0
- package/dist/Axis/axisTitle.d.ts +10 -0
- package/dist/Axis/index.d.ts +2 -0
- package/dist/Axis/summaryGraphic.d.ts +17 -0
- package/dist/Brush.d.ts +12 -0
- package/dist/DividedLine.d.ts +16 -0
- package/dist/FacetController.d.ts +12 -0
- package/dist/Frame.d.ts +2 -0
- package/dist/InteractionLayer.d.ts +3 -0
- package/dist/Legend.d.ts +3 -0
- package/dist/MiniMap.d.ts +14 -0
- package/dist/MinimapXYFrame.d.ts +10 -0
- package/dist/NetworkFrame.d.ts +8 -0
- package/dist/OrdinalFrame.d.ts +8 -0
- package/dist/ResponsiveFrame.d.ts +22 -0
- package/dist/ResponsiveMinimapXYFrame.d.ts +3 -0
- package/dist/ResponsiveNetworkFrame.d.ts +3 -0
- package/dist/ResponsiveOrdinalFrame.d.ts +3 -0
- package/dist/ResponsiveXYFrame.d.ts +3 -0
- package/dist/SparkFrame.d.ts +14 -0
- package/dist/SparkNetworkFrame.d.ts +5 -0
- package/dist/SparkOrdinalFrame.d.ts +5 -0
- package/dist/SparkXYFrame.d.ts +5 -0
- package/dist/Tooltip/Tooltip.d.ts +141 -0
- package/dist/TooltipPositioner/index.d.ts +7 -0
- package/dist/VisualizationLayer.d.ts +33 -0
- package/dist/XYFrame.d.ts +8 -0
- package/dist/annotationLayerBehavior/annotationHandling.d.ts +19 -0
- package/dist/annotationLayerBehavior/d3labeler.d.ts +9 -0
- package/dist/annotationRules/baseRules.d.ts +25 -0
- package/dist/annotationRules/networkframeRules.d.ts +48 -0
- package/dist/annotationRules/orframeRules.d.ts +103 -0
- package/dist/annotationRules/xyframeRules.d.ts +117 -0
- package/dist/batchWork.d.ts +6 -0
- package/dist/charts/index.d.ts +62 -0
- package/dist/charts/network/ChordDiagram.d.ts +181 -0
- package/dist/charts/network/CirclePack.d.ts +103 -0
- package/dist/charts/network/ForceDirectedGraph.d.ts +192 -0
- package/dist/charts/network/SankeyDiagram.d.ts +195 -0
- package/dist/charts/network/TreeDiagram.d.ts +200 -0
- package/dist/charts/network/Treemap.d.ts +98 -0
- package/dist/charts/ordinal/BarChart.d.ts +119 -0
- package/dist/charts/ordinal/BoxPlot.d.ts +125 -0
- package/dist/charts/ordinal/DonutChart.d.ts +95 -0
- package/dist/charts/ordinal/DotPlot.d.ts +128 -0
- package/dist/charts/ordinal/GroupedBarChart.d.ts +113 -0
- package/dist/charts/ordinal/PieChart.d.ts +83 -0
- package/dist/charts/ordinal/StackedBarChart.d.ts +119 -0
- package/dist/charts/ordinal/SwarmPlot.d.ts +137 -0
- package/dist/charts/realtime/RealtimeBarChart.d.ts +102 -0
- package/dist/charts/realtime/RealtimeLineChart.d.ts +78 -0
- package/dist/charts/realtime/RealtimeSwarmChart.d.ts +88 -0
- package/dist/charts/realtime/RealtimeWaterfallChart.d.ts +85 -0
- package/dist/charts/shared/ChartError.d.ts +19 -0
- package/dist/charts/shared/colorUtils.d.ts +62 -0
- package/dist/charts/shared/formatUtils.d.ts +82 -0
- package/dist/charts/shared/hooks.d.ts +20 -0
- package/dist/charts/shared/legendUtils.d.ts +32 -0
- package/dist/charts/shared/types.d.ts +58 -0
- package/dist/charts/shared/validateChartData.d.ts +41 -0
- package/dist/charts/shared/validateProps.d.ts +18 -0
- package/dist/charts/xy/AreaChart.d.ts +127 -0
- package/dist/charts/xy/BubbleChart.d.ts +157 -0
- package/dist/charts/xy/Heatmap.d.ts +153 -0
- package/dist/charts/xy/LineChart.d.ts +193 -0
- package/dist/charts/xy/Scatterplot.d.ts +50 -0
- package/dist/charts/xy/StackedAreaChart.d.ts +131 -0
- package/dist/constants/coordinateNames.d.ts +8 -0
- package/dist/constants/frame_props.d.ts +13 -0
- package/dist/constants/jsx.d.ts +19 -0
- package/dist/data/dataFunctions.d.ts +45 -0
- package/dist/data/multiAccessorUtils.d.ts +1 -0
- package/dist/data/networkPipelineCache.d.ts +27 -0
- package/dist/data/ordinalPipelineCache.d.ts +33 -0
- package/dist/data/unflowedFunctions.d.ts +1 -0
- package/dist/data/xyPipelineCache.d.ts +35 -0
- package/dist/generic_utilities/functions.d.ts +1 -0
- package/dist/index.d.ts +133 -0
- package/dist/interactionLayerBehavior/InteractionCanvas.d.ts +20 -0
- package/dist/network.js +8520 -0
- package/dist/network.js.map +1 -0
- package/dist/network.min.js +1 -0
- package/dist/network.module.js +8484 -0
- package/dist/network.module.js.map +1 -0
- package/dist/network.module.min.js +1 -0
- package/dist/ordinal.js +9276 -0
- package/dist/ordinal.js.map +1 -0
- package/dist/ordinal.min.js +1 -0
- package/dist/ordinal.module.js +9242 -0
- package/dist/ordinal.module.js.map +1 -0
- package/dist/ordinal.module.min.js +1 -0
- package/dist/processing/InteractionItems.d.ts +13 -0
- package/dist/processing/hierarchyUtils.d.ts +16 -0
- package/dist/processing/layouts/chordLayout.d.ts +2 -0
- package/dist/processing/layouts/forceLayout.d.ts +3 -0
- package/dist/processing/layouts/hierarchyLayout.d.ts +10 -0
- package/dist/processing/layouts/index.d.ts +8 -0
- package/dist/processing/layouts/sankeyLayout.d.ts +8 -0
- package/dist/processing/layouts/simpleLayouts.d.ts +7 -0
- package/dist/processing/layouts/types.d.ts +17 -0
- package/dist/processing/network.d.ts +111 -0
- package/dist/processing/networkDefaults.d.ts +36 -0
- package/dist/processing/networkLayoutHelpers.d.ts +54 -0
- package/dist/processing/ordinal.d.ts +102 -0
- package/dist/processing/ordinalConstants.d.ts +33 -0
- package/dist/processing/ordinalOverlays.d.ts +33 -0
- package/dist/processing/ordinalRenderPipeline.d.ts +148 -0
- package/dist/processing/xyDrawing.d.ts +140 -0
- package/dist/realtime/BinAccumulator.d.ts +8 -0
- package/dist/realtime/IncrementalExtent.d.ts +13 -0
- package/dist/realtime/RealtimeFrame.d.ts +4 -0
- package/dist/realtime/RingBuffer.d.ts +19 -0
- package/dist/realtime/renderers/barRenderer.d.ts +2 -0
- package/dist/realtime/renderers/candlestickRenderer.d.ts +2 -0
- package/dist/realtime/renderers/lineRenderer.d.ts +2 -0
- package/dist/realtime/renderers/swarmRenderer.d.ts +2 -0
- package/dist/realtime/renderers/types.d.ts +9 -0
- package/dist/realtime/renderers/waterfallRenderer.d.ts +3 -0
- package/dist/realtime/types.d.ts +113 -0
- package/dist/realtime.js +1598 -0
- package/dist/realtime.js.map +1 -0
- package/dist/realtime.min.js +1 -0
- package/dist/realtime.module.js +1566 -0
- package/dist/realtime.module.js.map +1 -0
- package/dist/realtime.module.min.js +1 -0
- package/dist/semiotic-ai.d.ts +28 -0
- package/dist/semiotic-ai.js +18722 -0
- package/dist/semiotic-ai.js.map +1 -0
- package/dist/semiotic-ai.min.js +1 -0
- package/dist/semiotic-ai.module.js +18668 -0
- package/dist/semiotic-ai.module.js.map +1 -0
- package/dist/semiotic-ai.module.min.js +1 -0
- package/dist/semiotic-network.d.ts +19 -0
- package/dist/semiotic-ordinal.d.ts +18 -0
- package/dist/semiotic-realtime.d.ts +23 -0
- package/dist/semiotic-server.d.ts +1 -0
- package/dist/semiotic-xy.d.ts +24 -0
- package/dist/semiotic.d.ts +51 -0
- package/dist/semiotic.js +18723 -12996
- package/dist/semiotic.js.map +1 -0
- package/dist/semiotic.min.js +1 -0
- package/dist/semiotic.module.js +18666 -12965
- package/dist/semiotic.module.js.map +1 -0
- package/dist/semiotic.module.min.js +1 -0
- package/dist/server/renderToStaticSVG.d.ts +9 -0
- package/dist/server.js +8360 -0
- package/dist/server.js.map +1 -0
- package/dist/server.min.js +1 -0
- package/dist/server.module.js +8331 -0
- package/dist/server.module.js.map +1 -0
- package/dist/server.module.min.js +1 -0
- package/dist/store/TooltipStore.d.ts +2 -0
- package/dist/store/createStore.d.ts +1 -0
- package/dist/svg/SvgHelper.d.ts +33 -0
- package/dist/svg/areaDrawing.d.ts +21 -0
- package/dist/svg/boxplotRenderer.d.ts +15 -0
- package/dist/svg/bucketizedRenderer.d.ts +16 -0
- package/dist/svg/ckbinsRenderer.d.ts +20 -0
- package/dist/svg/ckmeans.d.ts +69 -0
- package/dist/svg/contourLayout.d.ts +6 -0
- package/dist/svg/contourRenderer.d.ts +12 -0
- package/dist/svg/edgeGenerators.d.ts +51 -0
- package/dist/svg/frameFunctions.d.ts +108 -0
- package/dist/svg/graphAlgorithms.d.ts +14 -0
- package/dist/svg/hexbinLayout.d.ts +7 -0
- package/dist/svg/lineDrawing.d.ts +99 -0
- package/dist/svg/networkDrawing.d.ts +16 -0
- package/dist/svg/nodeGenerators.d.ts +58 -0
- package/dist/svg/pieceDrawing.d.ts +12 -0
- package/dist/svg/pieceLayouts.d.ts +53 -0
- package/dist/svg/sankeyLinks.d.ts +3 -0
- package/dist/svg/summaryAxis.d.ts +6 -0
- package/dist/svg/summaryLayouts.d.ts +53 -0
- package/dist/svg/swarmLayout.d.ts +13 -0
- package/dist/types/annotationTypes.d.ts +135 -0
- package/dist/types/canvasTypes.d.ts +9 -0
- package/dist/types/generalTypes.d.ts +238 -0
- package/dist/types/interactionTypes.d.ts +72 -0
- package/dist/types/legendTypes.d.ts +20 -0
- package/dist/types/networkTypes.d.ts +175 -0
- package/dist/types/ordinalTypes.d.ts +112 -0
- package/dist/types/xyTypes.d.ts +115 -0
- package/dist/useBoundingRect.d.ts +2 -0
- package/dist/useDerivedStateFromProps.d.ts +1 -0
- package/dist/useLegacyUnmountCallback.d.ts +2 -0
- package/dist/visualizationLayerBehavior/axis.d.ts +36 -0
- package/dist/visualizationLayerBehavior/general.d.ts +80 -0
- package/dist/xy.js +7944 -0
- package/dist/xy.js.map +1 -0
- package/dist/xy.min.js +1 -0
- package/dist/xy.module.js +7903 -0
- package/dist/xy.module.js.map +1 -0
- package/dist/xy.module.min.js +1 -0
- package/package.json +116 -65
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const React = __importStar(require("react"));
|
|
38
|
+
const react_1 = require("react");
|
|
39
|
+
const d3_scale_1 = require("d3-scale");
|
|
40
|
+
const RingBuffer_1 = require("./RingBuffer");
|
|
41
|
+
const IncrementalExtent_1 = require("./IncrementalExtent");
|
|
42
|
+
const lineRenderer_1 = require("./renderers/lineRenderer");
|
|
43
|
+
const swarmRenderer_1 = require("./renderers/swarmRenderer");
|
|
44
|
+
const candlestickRenderer_1 = require("./renderers/candlestickRenderer");
|
|
45
|
+
const waterfallRenderer_1 = require("./renderers/waterfallRenderer");
|
|
46
|
+
const barRenderer_1 = require("./renderers/barRenderer");
|
|
47
|
+
const BinAccumulator_1 = require("./BinAccumulator");
|
|
48
|
+
const RENDERERS = {
|
|
49
|
+
line: lineRenderer_1.lineRenderer,
|
|
50
|
+
swarm: swarmRenderer_1.swarmRenderer,
|
|
51
|
+
candlestick: candlestickRenderer_1.candlestickRenderer,
|
|
52
|
+
waterfall: waterfallRenderer_1.waterfallRenderer,
|
|
53
|
+
bar: barRenderer_1.barRenderer
|
|
54
|
+
};
|
|
55
|
+
const DEFAULT_MARGIN = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
56
|
+
const DEFAULT_LINE_STYLE = {};
|
|
57
|
+
function resolveAccessor(accessor, fallback) {
|
|
58
|
+
if (typeof accessor === "function")
|
|
59
|
+
return (d) => +accessor(d);
|
|
60
|
+
const key = accessor || fallback;
|
|
61
|
+
return (d) => +d[key];
|
|
62
|
+
}
|
|
63
|
+
function getTimeAxis(arrowOfTime) {
|
|
64
|
+
return arrowOfTime === "up" || arrowOfTime === "down" ? "y" : "x";
|
|
65
|
+
}
|
|
66
|
+
function buildScales(arrowOfTime, timeExtent, valueExtent, width, height) {
|
|
67
|
+
const timeAxis = getTimeAxis(arrowOfTime);
|
|
68
|
+
let timeRange;
|
|
69
|
+
let valueRange;
|
|
70
|
+
if (timeAxis === "x") {
|
|
71
|
+
timeRange = arrowOfTime === "right" ? [0, width] : [width, 0];
|
|
72
|
+
valueRange = [height, 0];
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
timeRange = arrowOfTime === "down" ? [0, height] : [height, 0];
|
|
76
|
+
valueRange = [0, width];
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
time: (0, d3_scale_1.scaleLinear)().domain(timeExtent).range(timeRange),
|
|
80
|
+
value: (0, d3_scale_1.scaleLinear)().domain(valueExtent).range(valueRange)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function defaultTickFormat(v) {
|
|
84
|
+
return String(Math.round(v * 100) / 100);
|
|
85
|
+
}
|
|
86
|
+
const LIGHT_THEME = {
|
|
87
|
+
axisStroke: "#ccc",
|
|
88
|
+
tickText: "#666",
|
|
89
|
+
crosshair: "rgba(0, 0, 0, 0.25)",
|
|
90
|
+
hoverFill: "rgba(255, 255, 255, 0.3)",
|
|
91
|
+
hoverStroke: "rgba(0, 0, 0, 0.4)",
|
|
92
|
+
pointRing: "white"
|
|
93
|
+
};
|
|
94
|
+
/** Read CSS custom properties from an element to build theme-aware colors */
|
|
95
|
+
function resolveThemeColors(el) {
|
|
96
|
+
if (!el)
|
|
97
|
+
return LIGHT_THEME;
|
|
98
|
+
const style = getComputedStyle(el);
|
|
99
|
+
const textSecondary = style.getPropertyValue("--text-secondary").trim();
|
|
100
|
+
const textPrimary = style.getPropertyValue("--text-primary").trim();
|
|
101
|
+
const surface3 = style.getPropertyValue("--surface-3").trim();
|
|
102
|
+
const surface0 = style.getPropertyValue("--surface-0").trim();
|
|
103
|
+
// If no CSS custom properties are found, fall back to light defaults
|
|
104
|
+
if (!textSecondary && !textPrimary)
|
|
105
|
+
return LIGHT_THEME;
|
|
106
|
+
return {
|
|
107
|
+
axisStroke: surface3 || LIGHT_THEME.axisStroke,
|
|
108
|
+
tickText: textSecondary || LIGHT_THEME.tickText,
|
|
109
|
+
crosshair: textSecondary ? `${textSecondary}66` : LIGHT_THEME.crosshair,
|
|
110
|
+
hoverFill: surface0 ? `${surface0}4D` : LIGHT_THEME.hoverFill,
|
|
111
|
+
hoverStroke: textSecondary ? `${textSecondary}99` : LIGHT_THEME.hoverStroke,
|
|
112
|
+
pointRing: surface0 || LIGHT_THEME.pointRing
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function drawAxes(ctx, arrowOfTime, timeScale, valueScale, width, height, tickFormatTime, tickFormatValue, theme) {
|
|
116
|
+
const timeAxis = getTimeAxis(arrowOfTime);
|
|
117
|
+
const fmtValue = tickFormatValue || defaultTickFormat;
|
|
118
|
+
const colors = theme || LIGHT_THEME;
|
|
119
|
+
ctx.strokeStyle = colors.axisStroke;
|
|
120
|
+
ctx.lineWidth = 1;
|
|
121
|
+
ctx.fillStyle = colors.tickText;
|
|
122
|
+
ctx.font = "10px sans-serif";
|
|
123
|
+
ctx.textAlign = "center";
|
|
124
|
+
ctx.textBaseline = "top";
|
|
125
|
+
if (timeAxis === "x") {
|
|
126
|
+
ctx.beginPath();
|
|
127
|
+
ctx.moveTo(0, height);
|
|
128
|
+
ctx.lineTo(width, height);
|
|
129
|
+
ctx.stroke();
|
|
130
|
+
ctx.beginPath();
|
|
131
|
+
ctx.moveTo(0, 0);
|
|
132
|
+
ctx.lineTo(0, height);
|
|
133
|
+
ctx.stroke();
|
|
134
|
+
const timeTicks = timeScale.ticks(5);
|
|
135
|
+
ctx.textAlign = "center";
|
|
136
|
+
ctx.textBaseline = "top";
|
|
137
|
+
for (const tick of timeTicks) {
|
|
138
|
+
const x = timeScale(tick);
|
|
139
|
+
ctx.beginPath();
|
|
140
|
+
ctx.moveTo(x, height);
|
|
141
|
+
ctx.lineTo(x, height + 5);
|
|
142
|
+
ctx.stroke();
|
|
143
|
+
if (tickFormatTime) {
|
|
144
|
+
ctx.fillText(tickFormatTime(tick), x, height + 7);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
ctx.textAlign = "right";
|
|
148
|
+
ctx.textBaseline = "middle";
|
|
149
|
+
const valueTicks = valueScale.ticks(5);
|
|
150
|
+
for (const tick of valueTicks) {
|
|
151
|
+
const y = valueScale(tick);
|
|
152
|
+
ctx.beginPath();
|
|
153
|
+
ctx.moveTo(-5, y);
|
|
154
|
+
ctx.lineTo(0, y);
|
|
155
|
+
ctx.stroke();
|
|
156
|
+
ctx.fillText(fmtValue(tick), -8, y);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
ctx.beginPath();
|
|
161
|
+
ctx.moveTo(0, 0);
|
|
162
|
+
ctx.lineTo(0, height);
|
|
163
|
+
ctx.stroke();
|
|
164
|
+
ctx.beginPath();
|
|
165
|
+
ctx.moveTo(0, timeAxis === "y" && arrowOfTime === "down" ? 0 : height);
|
|
166
|
+
ctx.lineTo(width, timeAxis === "y" && arrowOfTime === "down" ? 0 : height);
|
|
167
|
+
ctx.stroke();
|
|
168
|
+
ctx.textAlign = "center";
|
|
169
|
+
ctx.textBaseline = "top";
|
|
170
|
+
const valueTicks = valueScale.ticks(5);
|
|
171
|
+
for (const tick of valueTicks) {
|
|
172
|
+
const x = valueScale(tick);
|
|
173
|
+
ctx.beginPath();
|
|
174
|
+
ctx.moveTo(x, height);
|
|
175
|
+
ctx.lineTo(x, height + 5);
|
|
176
|
+
ctx.stroke();
|
|
177
|
+
ctx.fillText(fmtValue(tick), x, height + 7);
|
|
178
|
+
}
|
|
179
|
+
ctx.textAlign = "right";
|
|
180
|
+
ctx.textBaseline = "middle";
|
|
181
|
+
const timeTicks = timeScale.ticks(5);
|
|
182
|
+
for (const tick of timeTicks) {
|
|
183
|
+
const y = timeScale(tick);
|
|
184
|
+
ctx.beginPath();
|
|
185
|
+
ctx.moveTo(-5, y);
|
|
186
|
+
ctx.lineTo(0, y);
|
|
187
|
+
ctx.stroke();
|
|
188
|
+
if (tickFormatTime) {
|
|
189
|
+
ctx.fillText(tickFormatTime(tick), -8, y);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Binary search: find the index of the nearest point by time value
|
|
195
|
+
function findNearestIndex(buf, targetTime, getTime) {
|
|
196
|
+
if (buf.size === 0)
|
|
197
|
+
return -1;
|
|
198
|
+
let lo = 0;
|
|
199
|
+
let hi = buf.size - 1;
|
|
200
|
+
while (lo < hi) {
|
|
201
|
+
const mid = (lo + hi) >> 1;
|
|
202
|
+
const t = getTime(buf.get(mid));
|
|
203
|
+
if (t < targetTime)
|
|
204
|
+
lo = mid + 1;
|
|
205
|
+
else
|
|
206
|
+
hi = mid;
|
|
207
|
+
}
|
|
208
|
+
// lo is first point with time >= targetTime; check if lo-1 is closer
|
|
209
|
+
if (lo > 0) {
|
|
210
|
+
const tLo = getTime(buf.get(lo));
|
|
211
|
+
const tPrev = getTime(buf.get(lo - 1));
|
|
212
|
+
if (Math.abs(tPrev - targetTime) <= Math.abs(tLo - targetTime)) {
|
|
213
|
+
return lo - 1;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return lo;
|
|
217
|
+
}
|
|
218
|
+
function drawCrosshair(ctx, hover, width, height, config, pointColor, theme) {
|
|
219
|
+
const showCrosshair = config.crosshair !== false;
|
|
220
|
+
if (!showCrosshair)
|
|
221
|
+
return;
|
|
222
|
+
const colors = theme || LIGHT_THEME;
|
|
223
|
+
ctx.save();
|
|
224
|
+
const crossStyle = typeof config.crosshair === "object" ? config.crosshair : {};
|
|
225
|
+
ctx.strokeStyle = crossStyle.stroke || colors.crosshair;
|
|
226
|
+
ctx.lineWidth = crossStyle.strokeWidth || 1;
|
|
227
|
+
if (crossStyle.strokeDasharray) {
|
|
228
|
+
ctx.setLineDash(crossStyle.strokeDasharray.split(/[\s,]+/).map(Number));
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
ctx.setLineDash([4, 4]);
|
|
232
|
+
}
|
|
233
|
+
// Vertical guide
|
|
234
|
+
ctx.beginPath();
|
|
235
|
+
ctx.moveTo(hover.x, 0);
|
|
236
|
+
ctx.lineTo(hover.x, height);
|
|
237
|
+
ctx.stroke();
|
|
238
|
+
// Horizontal guide
|
|
239
|
+
ctx.beginPath();
|
|
240
|
+
ctx.moveTo(0, hover.y);
|
|
241
|
+
ctx.lineTo(width, hover.y);
|
|
242
|
+
ctx.stroke();
|
|
243
|
+
ctx.restore();
|
|
244
|
+
// Point indicator
|
|
245
|
+
ctx.beginPath();
|
|
246
|
+
ctx.arc(hover.x, hover.y, 4, 0, Math.PI * 2);
|
|
247
|
+
ctx.fillStyle = pointColor;
|
|
248
|
+
ctx.fill();
|
|
249
|
+
ctx.strokeStyle = colors.pointRing;
|
|
250
|
+
ctx.lineWidth = 2;
|
|
251
|
+
ctx.stroke();
|
|
252
|
+
}
|
|
253
|
+
const defaultTooltipStyle = {
|
|
254
|
+
background: "rgba(0, 0, 0, 0.85)",
|
|
255
|
+
color: "white",
|
|
256
|
+
padding: "6px 10px",
|
|
257
|
+
borderRadius: 4,
|
|
258
|
+
fontSize: 12,
|
|
259
|
+
lineHeight: 1.5,
|
|
260
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
261
|
+
pointerEvents: "none",
|
|
262
|
+
whiteSpace: "nowrap"
|
|
263
|
+
};
|
|
264
|
+
function DefaultTooltip({ hover, formatTime }) {
|
|
265
|
+
const fmtValue = (v) => Number.isInteger(v) ? String(v) : v.toFixed(2);
|
|
266
|
+
const fmtTime = formatTime || fmtValue;
|
|
267
|
+
const colorMap = hover.data.barColors;
|
|
268
|
+
const hoveredCat = hover.data.hoveredCategory;
|
|
269
|
+
const hoveredCatVal = hover.data.hoveredCategoryValue;
|
|
270
|
+
return (React.createElement("div", { className: "semiotic-tooltip", style: defaultTooltipStyle },
|
|
271
|
+
hoveredCat != null && hoveredCatVal != null ? (React.createElement(React.Fragment, null,
|
|
272
|
+
React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 5, fontWeight: 600, marginBottom: 2 } },
|
|
273
|
+
colorMap && colorMap[hoveredCat] && (React.createElement("span", { style: { width: 8, height: 8, borderRadius: "50%", background: colorMap[hoveredCat], flexShrink: 0 } })),
|
|
274
|
+
React.createElement("span", null, hoveredCat),
|
|
275
|
+
React.createElement("span", { style: { marginLeft: "auto" } }, fmtValue(hoveredCatVal))),
|
|
276
|
+
React.createElement("div", { style: { opacity: 0.6, fontSize: 11 } },
|
|
277
|
+
"total ",
|
|
278
|
+
fmtValue(hover.value)))) : (React.createElement("div", { style: { fontWeight: 600, marginBottom: 2 } }, fmtValue(hover.value))),
|
|
279
|
+
React.createElement("div", { style: { opacity: 0.7, fontSize: 11 } }, fmtTime(hover.time))));
|
|
280
|
+
}
|
|
281
|
+
const RealtimeFrame = (0, react_1.forwardRef)(function RealtimeFrame(props, ref) {
|
|
282
|
+
const { chartType = "line", arrowOfTime = "right", windowMode = "sliding", windowSize = 200, data, timeAccessor, valueAccessor, timeExtent: fixedTimeExtent, valueExtent: fixedValueExtent, extentPadding = 0.1, size = [500, 300], margin: marginProp, className, lineStyle = DEFAULT_LINE_STYLE, annotations, svgAnnotationRules, hoverAnnotation, tooltipContent, customHoverBehavior, showAxes = true, background, categoryAccessor, binSize, barColors, barStyle, waterfallStyle, swarmStyle, tickFormatTime, tickFormatValue } = props;
|
|
283
|
+
const margin = { ...DEFAULT_MARGIN, ...marginProp };
|
|
284
|
+
const adjustedWidth = size[0] - margin.left - margin.right;
|
|
285
|
+
const adjustedHeight = size[1] - margin.top - margin.bottom;
|
|
286
|
+
// Memoize accessors so they don't change every render.
|
|
287
|
+
// Without this, the data effect re-runs on every render
|
|
288
|
+
// (new function reference), which triggers cascading re-renders.
|
|
289
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
290
|
+
const getTime = (0, react_1.useMemo)(() => resolveAccessor(timeAccessor, "time"), [timeAccessor]);
|
|
291
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
292
|
+
const getValue = (0, react_1.useMemo)(() => resolveAccessor(valueAccessor, "value"), [valueAccessor]);
|
|
293
|
+
const getCategory = (0, react_1.useMemo)(() => categoryAccessor
|
|
294
|
+
? (typeof categoryAccessor === "function" ? categoryAccessor : (d) => d[categoryAccessor])
|
|
295
|
+
: undefined, [categoryAccessor]);
|
|
296
|
+
const bufferRef = (0, react_1.useRef)(new RingBuffer_1.RingBuffer(windowSize));
|
|
297
|
+
const timeExtentRef = (0, react_1.useRef)(new IncrementalExtent_1.IncrementalExtent());
|
|
298
|
+
const valueExtentRef = (0, react_1.useRef)(new IncrementalExtent_1.IncrementalExtent());
|
|
299
|
+
const canvasRef = (0, react_1.useRef)(null);
|
|
300
|
+
const rafRef = (0, react_1.useRef)(0);
|
|
301
|
+
const dirtyRef = (0, react_1.useRef)(false);
|
|
302
|
+
const scalesRef = (0, react_1.useRef)(null);
|
|
303
|
+
const [annotationFrame, setAnnotationFrame] = (0, react_1.useState)(0);
|
|
304
|
+
const growingCapRef = (0, react_1.useRef)(windowSize);
|
|
305
|
+
// Hover state: ref for canvas (sync), React state for tooltip (async)
|
|
306
|
+
const hoverRef = (0, react_1.useRef)(null);
|
|
307
|
+
const [hoverPoint, setHoverPoint] = (0, react_1.useState)(null);
|
|
308
|
+
// Store the render function in a ref so scheduleRender is stable
|
|
309
|
+
// and never goes stale. The ref is updated every React render
|
|
310
|
+
// (below the hooks) so it always captures fresh props/closures.
|
|
311
|
+
const renderFnRef = (0, react_1.useRef)(() => { });
|
|
312
|
+
// Stable scheduleRender — never recreated, so no stale closure chain
|
|
313
|
+
const scheduleRender = (0, react_1.useCallback)(() => {
|
|
314
|
+
if (rafRef.current)
|
|
315
|
+
return;
|
|
316
|
+
rafRef.current = requestAnimationFrame(() => renderFnRef.current());
|
|
317
|
+
}, []);
|
|
318
|
+
const pushPoint = (0, react_1.useCallback)((point) => {
|
|
319
|
+
const buf = bufferRef.current;
|
|
320
|
+
const t = getTime(point);
|
|
321
|
+
const v = getValue(point);
|
|
322
|
+
if (windowMode === "growing" && buf.full) {
|
|
323
|
+
growingCapRef.current *= 2;
|
|
324
|
+
buf.resize(growingCapRef.current);
|
|
325
|
+
}
|
|
326
|
+
const evicted = buf.push(point);
|
|
327
|
+
timeExtentRef.current.push(t);
|
|
328
|
+
valueExtentRef.current.push(v);
|
|
329
|
+
if (evicted != null) {
|
|
330
|
+
timeExtentRef.current.evict(getTime(evicted));
|
|
331
|
+
valueExtentRef.current.evict(getValue(evicted));
|
|
332
|
+
}
|
|
333
|
+
dirtyRef.current = true;
|
|
334
|
+
scheduleRender();
|
|
335
|
+
}, [windowMode, getTime, getValue, scheduleRender]);
|
|
336
|
+
const pushManyPoints = (0, react_1.useCallback)((points) => {
|
|
337
|
+
for (const p of points) {
|
|
338
|
+
pushPoint(p);
|
|
339
|
+
}
|
|
340
|
+
}, [pushPoint]);
|
|
341
|
+
const clearAll = (0, react_1.useCallback)(() => {
|
|
342
|
+
bufferRef.current.clear();
|
|
343
|
+
timeExtentRef.current.clear();
|
|
344
|
+
valueExtentRef.current.clear();
|
|
345
|
+
dirtyRef.current = true;
|
|
346
|
+
scheduleRender();
|
|
347
|
+
}, [scheduleRender]);
|
|
348
|
+
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
349
|
+
push: pushPoint,
|
|
350
|
+
pushMany: pushManyPoints,
|
|
351
|
+
clear: clearAll,
|
|
352
|
+
getData: () => bufferRef.current.toArray()
|
|
353
|
+
}), [pushPoint, pushManyPoints, clearAll]);
|
|
354
|
+
// Controlled data prop
|
|
355
|
+
(0, react_1.useEffect)(() => {
|
|
356
|
+
if (!data)
|
|
357
|
+
return;
|
|
358
|
+
bufferRef.current.clear();
|
|
359
|
+
timeExtentRef.current.clear();
|
|
360
|
+
valueExtentRef.current.clear();
|
|
361
|
+
for (const d of data) {
|
|
362
|
+
bufferRef.current.push(d);
|
|
363
|
+
timeExtentRef.current.push(getTime(d));
|
|
364
|
+
valueExtentRef.current.push(getValue(d));
|
|
365
|
+
}
|
|
366
|
+
dirtyRef.current = true;
|
|
367
|
+
scheduleRender();
|
|
368
|
+
}, [data, getTime, getValue, scheduleRender]);
|
|
369
|
+
// Hover mouse handler — stored in ref so it always captures fresh closures
|
|
370
|
+
const hoverHandlerRef = (0, react_1.useRef)(() => { });
|
|
371
|
+
const hoverLeaveRef = (0, react_1.useRef)(() => { });
|
|
372
|
+
hoverHandlerRef.current = (e) => {
|
|
373
|
+
if (!hoverAnnotation)
|
|
374
|
+
return;
|
|
375
|
+
const canvas = canvasRef.current;
|
|
376
|
+
if (!canvas)
|
|
377
|
+
return;
|
|
378
|
+
const rect = canvas.getBoundingClientRect();
|
|
379
|
+
// Mouse position in chart coordinates (canvas is full-size, ctx translated by margin)
|
|
380
|
+
const chartX = e.clientX - rect.left - margin.left;
|
|
381
|
+
const chartY = e.clientY - rect.top - margin.top;
|
|
382
|
+
// Outside chart area → clear hover
|
|
383
|
+
if (chartX < 0 || chartX > adjustedWidth || chartY < 0 || chartY > adjustedHeight) {
|
|
384
|
+
if (hoverRef.current) {
|
|
385
|
+
hoverRef.current = null;
|
|
386
|
+
setHoverPoint(null);
|
|
387
|
+
if (customHoverBehavior)
|
|
388
|
+
customHoverBehavior(null);
|
|
389
|
+
scheduleRender();
|
|
390
|
+
}
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const scales = scalesRef.current;
|
|
394
|
+
if (!scales)
|
|
395
|
+
return;
|
|
396
|
+
const buf = bufferRef.current;
|
|
397
|
+
if (buf.size === 0)
|
|
398
|
+
return;
|
|
399
|
+
const timeAxis = getTimeAxis(arrowOfTime);
|
|
400
|
+
const timePixel = timeAxis === "x" ? chartX : chartY;
|
|
401
|
+
const targetTime = scales.time.invert(timePixel);
|
|
402
|
+
let hover;
|
|
403
|
+
if (chartType === "bar" && binSize) {
|
|
404
|
+
// Snap to the bin the cursor is in
|
|
405
|
+
const bins = (0, BinAccumulator_1.computeBins)(buf, getTime, getValue, binSize, getCategory);
|
|
406
|
+
const binStart = Math.floor(targetTime / binSize) * binSize;
|
|
407
|
+
const bin = bins.get(binStart);
|
|
408
|
+
if (!bin)
|
|
409
|
+
return;
|
|
410
|
+
const [domainMin, domainMax] = scales.time.domain();
|
|
411
|
+
const clampedStart = Math.max(bin.start, domainMin);
|
|
412
|
+
const clampedEnd = Math.min(bin.end, domainMax);
|
|
413
|
+
const midTime = clampedStart + (clampedEnd - clampedStart) / 2;
|
|
414
|
+
const tPixel = scales.time(midTime);
|
|
415
|
+
const vPixel = scales.value(bin.total);
|
|
416
|
+
const x = timeAxis === "x" ? tPixel : vPixel;
|
|
417
|
+
const y = timeAxis === "x" ? vPixel : tPixel;
|
|
418
|
+
// Hit-test which category segment the cursor is in
|
|
419
|
+
let hoveredCategory;
|
|
420
|
+
let hoveredCategoryValue;
|
|
421
|
+
if (getCategory && bin.categories.size > 0) {
|
|
422
|
+
const colorKeys = barColors ? Object.keys(barColors) : [];
|
|
423
|
+
const listed = new Set(colorKeys);
|
|
424
|
+
const unlisted = Array.from(bin.categories.keys()).filter(c => !listed.has(c)).sort();
|
|
425
|
+
const catOrder = [...colorKeys.filter(k => bin.categories.has(k)), ...unlisted];
|
|
426
|
+
const valuePixel = timeAxis === "x" ? chartY : chartX;
|
|
427
|
+
let cumBase = 0;
|
|
428
|
+
for (const cat of catOrder) {
|
|
429
|
+
const catVal = bin.categories.get(cat) || 0;
|
|
430
|
+
if (catVal === 0)
|
|
431
|
+
continue;
|
|
432
|
+
const edgeA = scales.value(cumBase);
|
|
433
|
+
const edgeB = scales.value(cumBase + catVal);
|
|
434
|
+
const lo = Math.min(edgeA, edgeB);
|
|
435
|
+
const hi = Math.max(edgeA, edgeB);
|
|
436
|
+
if (valuePixel >= lo && valuePixel <= hi) {
|
|
437
|
+
hoveredCategory = cat;
|
|
438
|
+
hoveredCategoryValue = catVal;
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
cumBase += catVal;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
hover = {
|
|
445
|
+
data: {
|
|
446
|
+
binStart: bin.start, binEnd: bin.end, total: bin.total,
|
|
447
|
+
categories: Object.fromEntries(bin.categories),
|
|
448
|
+
barColors: barColors || {},
|
|
449
|
+
hoveredCategory,
|
|
450
|
+
hoveredCategoryValue
|
|
451
|
+
},
|
|
452
|
+
time: midTime,
|
|
453
|
+
value: bin.total,
|
|
454
|
+
x,
|
|
455
|
+
y
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
const idx = findNearestIndex(buf, targetTime, getTime);
|
|
460
|
+
if (idx < 0)
|
|
461
|
+
return;
|
|
462
|
+
const d = buf.get(idx);
|
|
463
|
+
const t = getTime(d);
|
|
464
|
+
const v = getValue(d);
|
|
465
|
+
const tPixel = scales.time(t);
|
|
466
|
+
const vPixel = scales.value(v);
|
|
467
|
+
const x = timeAxis === "x" ? tPixel : vPixel;
|
|
468
|
+
const y = timeAxis === "x" ? vPixel : tPixel;
|
|
469
|
+
hover = { data: d, time: t, value: v, x, y };
|
|
470
|
+
}
|
|
471
|
+
hoverRef.current = hover;
|
|
472
|
+
setHoverPoint(hover);
|
|
473
|
+
if (customHoverBehavior)
|
|
474
|
+
customHoverBehavior(hover);
|
|
475
|
+
scheduleRender();
|
|
476
|
+
};
|
|
477
|
+
hoverLeaveRef.current = () => {
|
|
478
|
+
if (hoverRef.current) {
|
|
479
|
+
hoverRef.current = null;
|
|
480
|
+
setHoverPoint(null);
|
|
481
|
+
if (customHoverBehavior)
|
|
482
|
+
customHoverBehavior(null);
|
|
483
|
+
scheduleRender();
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
// Stable event handlers that delegate to refs
|
|
487
|
+
const onMouseMove = (0, react_1.useCallback)((e) => hoverHandlerRef.current(e), []);
|
|
488
|
+
const onMouseLeave = (0, react_1.useCallback)(() => hoverLeaveRef.current(), []);
|
|
489
|
+
// Update the render function ref on every React render.
|
|
490
|
+
// This captures the latest props (arrowOfTime, chartType, lineStyle,
|
|
491
|
+
// annotations, etc.) without needing useCallback dependency chains.
|
|
492
|
+
// The rAF loop calls this via renderFnRef, so it always sees fresh values.
|
|
493
|
+
renderFnRef.current = () => {
|
|
494
|
+
rafRef.current = 0;
|
|
495
|
+
const canvas = canvasRef.current;
|
|
496
|
+
if (!canvas)
|
|
497
|
+
return;
|
|
498
|
+
const ctx = canvas.getContext("2d");
|
|
499
|
+
if (!ctx)
|
|
500
|
+
return;
|
|
501
|
+
const buf = bufferRef.current;
|
|
502
|
+
const tExtent = timeExtentRef.current;
|
|
503
|
+
const vExtent = valueExtentRef.current;
|
|
504
|
+
if (tExtent.dirty) {
|
|
505
|
+
tExtent.recalculate(buf, getTime);
|
|
506
|
+
}
|
|
507
|
+
if (vExtent.dirty) {
|
|
508
|
+
vExtent.recalculate(buf, getValue);
|
|
509
|
+
}
|
|
510
|
+
let tDomain = fixedTimeExtent || tExtent.extent;
|
|
511
|
+
let vDomain = fixedValueExtent || vExtent.extent;
|
|
512
|
+
if (chartType === "bar" && binSize && !fixedValueExtent && buf.size > 0) {
|
|
513
|
+
const [, maxTotal] = (0, BinAccumulator_1.computeBinExtent)(buf, getTime, getValue, binSize, getCategory);
|
|
514
|
+
vDomain = [0, maxTotal + maxTotal * extentPadding];
|
|
515
|
+
}
|
|
516
|
+
else if (chartType === "waterfall" && !fixedValueExtent && buf.size > 0) {
|
|
517
|
+
const [minCum, maxCum] = (0, waterfallRenderer_1.computeWaterfallExtent)(buf, getValue);
|
|
518
|
+
const range = maxCum - minCum;
|
|
519
|
+
const pad = range > 0 ? range * extentPadding : 1;
|
|
520
|
+
vDomain = [
|
|
521
|
+
Math.min(0, minCum - Math.abs(pad)),
|
|
522
|
+
Math.max(0, maxCum + Math.abs(pad))
|
|
523
|
+
];
|
|
524
|
+
}
|
|
525
|
+
else if (!fixedValueExtent && vDomain[0] !== Infinity) {
|
|
526
|
+
const range = vDomain[1] - vDomain[0];
|
|
527
|
+
const pad = range > 0 ? range * extentPadding : 1;
|
|
528
|
+
vDomain = [vDomain[0] - pad, vDomain[1] + pad];
|
|
529
|
+
}
|
|
530
|
+
if (tDomain[0] === Infinity || tDomain[1] === -Infinity) {
|
|
531
|
+
tDomain = [0, 1];
|
|
532
|
+
}
|
|
533
|
+
if (vDomain[0] === Infinity || vDomain[1] === -Infinity) {
|
|
534
|
+
vDomain = [0, 1];
|
|
535
|
+
}
|
|
536
|
+
const scales = buildScales(arrowOfTime, tDomain, vDomain, adjustedWidth, adjustedHeight);
|
|
537
|
+
scalesRef.current = scales;
|
|
538
|
+
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
539
|
+
canvas.width = size[0] * dpr;
|
|
540
|
+
canvas.height = size[1] * dpr;
|
|
541
|
+
canvas.style.width = `${size[0]}px`;
|
|
542
|
+
canvas.style.height = `${size[1]}px`;
|
|
543
|
+
ctx.scale(dpr, dpr);
|
|
544
|
+
ctx.translate(margin.left, margin.top);
|
|
545
|
+
ctx.clearRect(-margin.left, -margin.top, size[0], size[1]);
|
|
546
|
+
// Resolve theme colors from CSS custom properties for theme-aware rendering
|
|
547
|
+
const theme = resolveThemeColors(canvas);
|
|
548
|
+
if (background) {
|
|
549
|
+
ctx.fillStyle = background;
|
|
550
|
+
ctx.fillRect(0, 0, adjustedWidth, adjustedHeight);
|
|
551
|
+
}
|
|
552
|
+
if (showAxes) {
|
|
553
|
+
ctx.save();
|
|
554
|
+
drawAxes(ctx, arrowOfTime, scales.time, scales.value, adjustedWidth, adjustedHeight, tickFormatTime, tickFormatValue, theme);
|
|
555
|
+
ctx.restore();
|
|
556
|
+
}
|
|
557
|
+
const renderer = RENDERERS[chartType];
|
|
558
|
+
if (renderer) {
|
|
559
|
+
const layout = {
|
|
560
|
+
width: adjustedWidth,
|
|
561
|
+
height: adjustedHeight,
|
|
562
|
+
timeAxis: getTimeAxis(arrowOfTime)
|
|
563
|
+
};
|
|
564
|
+
renderer(ctx, buf, scales, layout, lineStyle, { time: getTime, value: getValue, category: getCategory }, annotations, chartType === "bar" ? { binSize, barColors, barStyle }
|
|
565
|
+
: chartType === "waterfall" ? { waterfallStyle }
|
|
566
|
+
: chartType === "swarm" ? { swarmStyle, barColors }
|
|
567
|
+
: undefined);
|
|
568
|
+
}
|
|
569
|
+
// Draw bar highlight on hovered bin/segment
|
|
570
|
+
if (hoverAnnotation && hoverRef.current && chartType === "bar" && binSize) {
|
|
571
|
+
const hd = hoverRef.current.data;
|
|
572
|
+
if (hd.binStart != null) {
|
|
573
|
+
const gap = barStyle?.gap ?? 1;
|
|
574
|
+
const tAxis = getTimeAxis(arrowOfTime);
|
|
575
|
+
// Determine which segment to highlight
|
|
576
|
+
const segBase = hd.hoveredCategory != null
|
|
577
|
+
? (() => {
|
|
578
|
+
// Walk categories to find the cumulative base of the hovered segment
|
|
579
|
+
const cats = hd.categories || {};
|
|
580
|
+
const colorKeys = barColors ? Object.keys(barColors) : [];
|
|
581
|
+
const listed = new Set(colorKeys);
|
|
582
|
+
const unlisted = Object.keys(cats).filter((c) => !listed.has(c)).sort();
|
|
583
|
+
const catOrder = [...colorKeys.filter((k) => k in cats), ...unlisted];
|
|
584
|
+
let base = 0;
|
|
585
|
+
for (const cat of catOrder) {
|
|
586
|
+
if (cat === hd.hoveredCategory)
|
|
587
|
+
return base;
|
|
588
|
+
base += cats[cat] || 0;
|
|
589
|
+
}
|
|
590
|
+
return base;
|
|
591
|
+
})()
|
|
592
|
+
: 0;
|
|
593
|
+
const segTop = hd.hoveredCategory != null
|
|
594
|
+
? segBase + (hd.hoveredCategoryValue || 0)
|
|
595
|
+
: hd.total;
|
|
596
|
+
const [domainMin, domainMax] = scales.time.domain();
|
|
597
|
+
const clampedBinStart = Math.max(hd.binStart, domainMin);
|
|
598
|
+
const clampedBinEnd = Math.min(hd.binEnd, domainMax);
|
|
599
|
+
if (tAxis === "x") {
|
|
600
|
+
const rawX0 = scales.time(clampedBinStart);
|
|
601
|
+
const rawX1 = scales.time(clampedBinEnd);
|
|
602
|
+
const x0 = Math.min(rawX0, rawX1) + gap / 2;
|
|
603
|
+
const x1 = Math.max(rawX0, rawX1) - gap / 2;
|
|
604
|
+
const yBot = scales.value(segBase);
|
|
605
|
+
const yTop = scales.value(segTop);
|
|
606
|
+
const ry = Math.min(yBot, yTop);
|
|
607
|
+
const rh = Math.abs(yBot - yTop);
|
|
608
|
+
ctx.fillStyle = theme.hoverFill;
|
|
609
|
+
ctx.fillRect(x0, ry, x1 - x0, rh);
|
|
610
|
+
ctx.strokeStyle = theme.hoverStroke;
|
|
611
|
+
ctx.lineWidth = 1;
|
|
612
|
+
ctx.setLineDash([]);
|
|
613
|
+
ctx.strokeRect(x0, ry, x1 - x0, rh);
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
const rawY0 = scales.time(clampedBinStart);
|
|
617
|
+
const rawY1 = scales.time(clampedBinEnd);
|
|
618
|
+
const y0 = Math.min(rawY0, rawY1) + gap / 2;
|
|
619
|
+
const y1 = Math.max(rawY0, rawY1) - gap / 2;
|
|
620
|
+
const xLeft = scales.value(segBase);
|
|
621
|
+
const xRight = scales.value(segTop);
|
|
622
|
+
const rx = Math.min(xLeft, xRight);
|
|
623
|
+
const rw = Math.abs(xRight - xLeft);
|
|
624
|
+
ctx.fillStyle = theme.hoverFill;
|
|
625
|
+
ctx.fillRect(rx, y0, rw, y1 - y0);
|
|
626
|
+
ctx.strokeStyle = theme.hoverStroke;
|
|
627
|
+
ctx.lineWidth = 1;
|
|
628
|
+
ctx.setLineDash([]);
|
|
629
|
+
ctx.strokeRect(rx, y0, rw, y1 - y0);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
// Draw crosshair after chart data so it renders on top
|
|
634
|
+
if (hoverAnnotation && hoverRef.current) {
|
|
635
|
+
const config = typeof hoverAnnotation === "object" ? hoverAnnotation : {};
|
|
636
|
+
drawCrosshair(ctx, hoverRef.current, adjustedWidth, adjustedHeight, config, lineStyle.stroke || "#007bff", theme);
|
|
637
|
+
}
|
|
638
|
+
const wasDirty = dirtyRef.current;
|
|
639
|
+
dirtyRef.current = false;
|
|
640
|
+
// Trigger React re-render so SVG annotations recompute positions
|
|
641
|
+
// using the scales we just stored in scalesRef.
|
|
642
|
+
// Only do this when data actually changed (wasDirty) to avoid
|
|
643
|
+
// setAnnotationFrame → re-render → effect → scheduleRender → loop.
|
|
644
|
+
if (wasDirty && annotations && annotations.length > 0 && svgAnnotationRules) {
|
|
645
|
+
setAnnotationFrame(f => f + 1);
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
// Initial render and cleanup
|
|
649
|
+
(0, react_1.useEffect)(() => {
|
|
650
|
+
scheduleRender();
|
|
651
|
+
return () => {
|
|
652
|
+
if (rafRef.current) {
|
|
653
|
+
cancelAnimationFrame(rafRef.current);
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}, [scheduleRender]);
|
|
657
|
+
// Re-render canvas when visual props change
|
|
658
|
+
(0, react_1.useEffect)(() => {
|
|
659
|
+
dirtyRef.current = true;
|
|
660
|
+
scheduleRender();
|
|
661
|
+
}, [arrowOfTime, chartType, adjustedWidth, adjustedHeight, showAxes, background, lineStyle, scheduleRender]);
|
|
662
|
+
// Compute annotation elements during React render using latest scales
|
|
663
|
+
const renderedAnnotations = React.useMemo(() => {
|
|
664
|
+
if (!annotations || annotations.length === 0 || !svgAnnotationRules) {
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
const scales = scalesRef.current;
|
|
668
|
+
const timeAxis = getTimeAxis(arrowOfTime);
|
|
669
|
+
return annotations
|
|
670
|
+
.map((annotation, i) => svgAnnotationRules(annotation, i, {
|
|
671
|
+
scales,
|
|
672
|
+
timeAxis,
|
|
673
|
+
width: adjustedWidth,
|
|
674
|
+
height: adjustedHeight
|
|
675
|
+
}))
|
|
676
|
+
.filter(Boolean);
|
|
677
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
678
|
+
}, [annotations, svgAnnotationRules, arrowOfTime, adjustedWidth, adjustedHeight, annotationFrame]);
|
|
679
|
+
const hasAnnotations = renderedAnnotations && renderedAnnotations.length > 0;
|
|
680
|
+
// Tooltip positioning: anchor at the hovered point, flip if near edges
|
|
681
|
+
const tooltipElement = hoverAnnotation && hoverPoint ? (React.createElement("div", { className: "realtime-frame-tooltip", style: {
|
|
682
|
+
position: "absolute",
|
|
683
|
+
left: margin.left + hoverPoint.x,
|
|
684
|
+
top: margin.top + hoverPoint.y,
|
|
685
|
+
transform: `translate(${hoverPoint.x > adjustedWidth * 0.7 ? "calc(-100% - 12px)" : "12px"}, ${hoverPoint.y < adjustedHeight * 0.3 ? "4px" : "calc(-100% - 4px)"})`,
|
|
686
|
+
pointerEvents: "none",
|
|
687
|
+
zIndex: 1
|
|
688
|
+
} }, tooltipContent
|
|
689
|
+
? tooltipContent(hoverPoint)
|
|
690
|
+
: React.createElement(DefaultTooltip, { hover: hoverPoint, formatTime: tickFormatTime }))) : null;
|
|
691
|
+
return (React.createElement("div", { className: `realtime-frame${className ? ` ${className}` : ""}`, style: {
|
|
692
|
+
position: "relative",
|
|
693
|
+
width: size[0],
|
|
694
|
+
height: size[1]
|
|
695
|
+
}, onMouseMove: hoverAnnotation ? onMouseMove : undefined, onMouseLeave: hoverAnnotation ? onMouseLeave : undefined },
|
|
696
|
+
React.createElement("canvas", { ref: canvasRef, style: {
|
|
697
|
+
position: "absolute",
|
|
698
|
+
left: 0,
|
|
699
|
+
top: 0
|
|
700
|
+
} }),
|
|
701
|
+
hasAnnotations && (React.createElement("svg", { width: size[0], height: size[1], style: {
|
|
702
|
+
position: "absolute",
|
|
703
|
+
top: 0,
|
|
704
|
+
left: 0,
|
|
705
|
+
pointerEvents: "none"
|
|
706
|
+
} },
|
|
707
|
+
React.createElement("g", { transform: `translate(${margin.left},${margin.top})` }, renderedAnnotations))),
|
|
708
|
+
tooltipElement));
|
|
709
|
+
});
|
|
710
|
+
exports.default = RealtimeFrame;
|