layerchart 2.0.0-next.1 → 2.0.0-next.2
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/dist/actions/movable.d.ts +28 -0
- package/dist/actions/movable.js +91 -0
- package/dist/components/AnnotationLine.svelte +155 -0
- package/dist/components/AnnotationLine.svelte.d.ts +28 -0
- package/dist/components/AnnotationPoint.svelte +121 -0
- package/dist/components/AnnotationPoint.svelte.d.ts +32 -0
- package/dist/components/AnnotationRange.svelte +147 -0
- package/dist/components/AnnotationRange.svelte.d.ts +40 -0
- package/dist/components/Arc.svelte +344 -151
- package/dist/components/Arc.svelte.d.ts +138 -0
- package/dist/components/Area.svelte +165 -149
- package/dist/components/Area.svelte.d.ts +45 -0
- package/dist/components/Axis.svelte +287 -174
- package/dist/components/Axis.svelte.d.ts +116 -0
- package/dist/components/Bar.svelte +163 -107
- package/dist/components/Bar.svelte.d.ts +48 -0
- package/dist/components/Bars.svelte +54 -68
- package/dist/components/Bars.svelte.d.ts +27 -0
- package/dist/components/Blur.svelte +31 -7
- package/dist/components/Blur.svelte.d.ts +23 -21
- package/dist/components/Bounds.svelte +49 -19
- package/dist/components/Bounds.svelte.d.ts +24 -50
- package/dist/components/BrushContext.svelte +296 -168
- package/dist/components/BrushContext.svelte.d.ts +97 -65
- package/dist/components/Calendar.svelte +116 -59
- package/dist/components/Calendar.svelte.d.ts +50 -31
- package/dist/components/Chart.svelte +1289 -398
- package/dist/components/Chart.svelte.d.ts +535 -410
- package/dist/components/ChartClipPath.svelte +37 -15
- package/dist/components/ChartClipPath.svelte.d.ts +21 -19
- package/dist/components/Circle.svelte +124 -85
- package/dist/components/Circle.svelte.d.ts +52 -0
- package/dist/components/CircleClipPath.svelte +76 -16
- package/dist/components/CircleClipPath.svelte.d.ts +46 -0
- package/dist/components/ClipPath.svelte +60 -15
- package/dist/components/ClipPath.svelte.d.ts +40 -27
- package/dist/components/ColorRamp.svelte +75 -9
- package/dist/components/ColorRamp.svelte.d.ts +37 -19
- package/dist/components/ComputedStyles.svelte +17 -5
- package/dist/components/ComputedStyles.svelte.d.ts +11 -19
- package/dist/components/Connector.svelte +149 -0
- package/dist/components/Connector.svelte.d.ts +51 -0
- package/dist/components/Dagre.svelte +211 -122
- package/dist/components/Dagre.svelte.d.ts +119 -56
- package/dist/components/ForceSimulation.svelte +215 -90
- package/dist/components/ForceSimulation.svelte.d.ts +82 -35
- package/dist/components/Frame.svelte +33 -13
- package/dist/components/Frame.svelte.d.ts +13 -17
- package/dist/components/GeoCircle.svelte +29 -16
- package/dist/components/GeoCircle.svelte.d.ts +22 -24
- package/dist/components/GeoContext.svelte +113 -72
- package/dist/components/GeoContext.svelte.d.ts +49 -41
- package/dist/components/GeoEdgeFade.svelte +47 -12
- package/dist/components/GeoEdgeFade.svelte.d.ts +17 -19
- package/dist/components/GeoPath.svelte +157 -127
- package/dist/components/GeoPath.svelte.d.ts +48 -36
- package/dist/components/GeoPoint.svelte +52 -20
- package/dist/components/GeoPoint.svelte.d.ts +25 -22
- package/dist/components/GeoSpline.svelte +75 -26
- package/dist/components/GeoSpline.svelte.d.ts +29 -20
- package/dist/components/GeoTile.svelte +100 -49
- package/dist/components/GeoTile.svelte.d.ts +38 -23
- package/dist/components/GeoVisible.svelte +17 -9
- package/dist/components/GeoVisible.svelte.d.ts +10 -18
- package/dist/components/Graticule.svelte +28 -13
- package/dist/components/Graticule.svelte.d.ts +11 -52
- package/dist/components/Grid.svelte +226 -114
- package/dist/components/Grid.svelte.d.ts +70 -0
- package/dist/components/Group.svelte +132 -105
- package/dist/components/Group.svelte.d.ts +53 -0
- package/dist/components/Highlight.svelte +409 -307
- package/dist/components/Highlight.svelte.d.ts +107 -0
- package/dist/components/Hull.svelte +96 -45
- package/dist/components/Hull.svelte.d.ts +40 -30
- package/dist/components/Labels.svelte +125 -46
- package/dist/components/Labels.svelte.d.ts +70 -27
- package/dist/components/Legend.svelte +374 -190
- package/dist/components/Legend.svelte.d.ts +95 -44
- package/dist/components/Line.svelte +163 -125
- package/dist/components/Line.svelte.d.ts +75 -0
- package/dist/components/LinearGradient.svelte +153 -78
- package/dist/components/LinearGradient.svelte.d.ts +66 -31
- package/dist/components/Link.svelte +160 -104
- package/dist/components/Link.svelte.d.ts +54 -0
- package/dist/components/Marker.svelte +100 -39
- package/dist/components/Marker.svelte.d.ts +59 -27
- package/dist/components/MarkerWrapper.svelte +35 -0
- package/dist/components/MarkerWrapper.svelte.d.ts +18 -0
- package/dist/components/MonthPath.svelte +65 -20
- package/dist/components/MonthPath.svelte.d.ts +23 -17
- package/dist/components/MotionPath.svelte +80 -24
- package/dist/components/MotionPath.svelte.d.ts +46 -27
- package/dist/components/Pack.svelte +53 -17
- package/dist/components/Pack.svelte.d.ts +42 -21
- package/dist/components/Partition.svelte +64 -22
- package/dist/components/Partition.svelte.d.ts +49 -26
- package/dist/components/Pattern.svelte +297 -11
- package/dist/components/Pattern.svelte.d.ts +103 -19
- package/dist/components/Pie.svelte +122 -76
- package/dist/components/Pie.svelte.d.ts +65 -51
- package/dist/components/Point.svelte +20 -9
- package/dist/components/Point.svelte.d.ts +16 -20
- package/dist/components/Points.svelte +148 -137
- package/dist/components/Points.svelte.d.ts +45 -34
- package/dist/components/RadialGradient.svelte +143 -70
- package/dist/components/RadialGradient.svelte.d.ts +69 -31
- package/dist/components/Rect.svelte +121 -102
- package/dist/components/Rect.svelte.d.ts +36 -0
- package/dist/components/RectClipPath.svelte +82 -18
- package/dist/components/RectClipPath.svelte.d.ts +55 -0
- package/dist/components/Rule.svelte +105 -62
- package/dist/components/Rule.svelte.d.ts +40 -19
- package/dist/components/Sankey.svelte +132 -55
- package/dist/components/Sankey.svelte.d.ts +61 -31
- package/dist/components/Spline.svelte +281 -218
- package/dist/components/Spline.svelte.d.ts +95 -0
- package/dist/components/Text.svelte +437 -176
- package/dist/components/Text.svelte.d.ts +130 -0
- package/dist/components/Threshold.svelte +48 -16
- package/dist/components/Threshold.svelte.d.ts +29 -31
- package/dist/components/TileImage.svelte +103 -30
- package/dist/components/TileImage.svelte.d.ts +48 -23
- package/dist/components/TransformContext.svelte +365 -171
- package/dist/components/TransformControls.svelte +50 -26
- package/dist/components/TransformControls.svelte.d.ts +27 -19
- package/dist/components/Tree.svelte +74 -33
- package/dist/components/Tree.svelte.d.ts +42 -30
- package/dist/components/Treemap.svelte +119 -42
- package/dist/components/Treemap.svelte.d.ts +75 -27
- package/dist/components/Voronoi.svelte +106 -75
- package/dist/components/Voronoi.svelte.d.ts +40 -41
- package/dist/components/charts/ArcChart.svelte +464 -0
- package/dist/components/charts/ArcChart.svelte.d.ts +90 -0
- package/dist/components/charts/AreaChart.svelte +450 -393
- package/dist/components/charts/AreaChart.svelte.d.ts +61 -0
- package/dist/components/charts/BarChart.svelte +454 -389
- package/dist/components/charts/BarChart.svelte.d.ts +76 -0
- package/dist/components/charts/ChartAnnotations.svelte +37 -0
- package/dist/components/charts/ChartAnnotations.svelte.d.ts +10 -0
- package/dist/components/charts/DefaultTooltip.svelte +60 -0
- package/dist/components/charts/DefaultTooltip.svelte.d.ts +10 -0
- package/dist/components/charts/LineChart.svelte +369 -314
- package/dist/components/charts/LineChart.svelte.d.ts +53 -0
- package/dist/components/charts/PieChart.svelte +458 -316
- package/dist/components/charts/PieChart.svelte.d.ts +137 -353
- package/dist/components/charts/ScatterChart.svelte +334 -296
- package/dist/components/charts/ScatterChart.svelte.d.ts +39 -0
- package/dist/components/charts/index.d.ts +8 -0
- package/dist/components/charts/index.js +7 -0
- package/dist/components/charts/types.d.ts +253 -0
- package/dist/components/charts/utils.svelte.d.ts +30 -0
- package/dist/components/charts/utils.svelte.js +55 -0
- package/dist/components/index.d.ts +76 -4
- package/dist/components/index.js +76 -5
- package/dist/components/layout/Canvas.svelte +321 -155
- package/dist/components/layout/Canvas.svelte.d.ts +104 -55
- package/dist/components/layout/Html.svelte +82 -42
- package/dist/components/layout/Html.svelte.d.ts +39 -28
- package/dist/components/layout/Layer.svelte +39 -0
- package/dist/components/layout/Layer.svelte.d.ts +17 -0
- package/dist/components/layout/Svg.svelte +122 -70
- package/dist/components/layout/Svg.svelte.d.ts +53 -34
- package/dist/components/layout/WebGL.svelte +135 -0
- package/dist/components/layout/WebGL.svelte.d.ts +50 -0
- package/dist/components/tooltip/Tooltip.svelte +246 -78
- package/dist/components/tooltip/Tooltip.svelte.d.ts +149 -31
- package/dist/components/tooltip/TooltipContext.svelte +409 -271
- package/dist/components/tooltip/TooltipContext.svelte.d.ts +86 -55
- package/dist/components/tooltip/TooltipHeader.svelte +100 -11
- package/dist/components/tooltip/TooltipHeader.svelte.d.ts +43 -23
- package/dist/components/tooltip/TooltipItem.svelte +167 -27
- package/dist/components/tooltip/TooltipItem.svelte.d.ts +63 -31
- package/dist/components/tooltip/TooltipList.svelte +22 -3
- package/dist/components/tooltip/TooltipList.svelte.d.ts +6 -17
- package/dist/components/tooltip/TooltipSeparator.svelte +27 -1
- package/dist/components/tooltip/TooltipSeparator.svelte.d.ts +6 -15
- package/dist/components/tooltip/index.d.ts +6 -0
- package/dist/components/tooltip/index.js +6 -0
- package/dist/components/tooltip/tooltipMetaContext.d.ts +79 -0
- package/dist/components/tooltip/tooltipMetaContext.js +139 -0
- package/dist/components/types.d.ts +1 -0
- package/dist/components/types.js +1 -0
- package/dist/docs/Blockquote.svelte.d.ts +18 -14
- package/dist/docs/Code.svelte.d.ts +26 -22
- package/dist/docs/ConnectorSweepMenuField.svelte +17 -0
- package/dist/docs/ConnectorSweepMenuField.svelte.d.ts +7 -0
- package/dist/docs/ConnectorTypeMenuField.svelte +17 -0
- package/dist/docs/ConnectorTypeMenuField.svelte.d.ts +7 -0
- package/dist/docs/CurveMenuField.svelte +14 -3
- package/dist/docs/CurveMenuField.svelte.d.ts +9 -18
- package/dist/docs/GeoDebug.svelte +47 -42
- package/dist/docs/GeoDebug.svelte.d.ts +4 -16
- package/dist/docs/Header1.svelte.d.ts +27 -16
- package/dist/docs/Json.svelte.d.ts +20 -16
- package/dist/docs/Layout.svelte.d.ts +18 -13
- package/dist/docs/Link.svelte.d.ts +33 -21
- package/dist/docs/PathDataMenuField.svelte +14 -10
- package/dist/docs/PathDataMenuField.svelte.d.ts +8 -18
- package/dist/docs/Preview.svelte +20 -7
- package/dist/docs/Preview.svelte.d.ts +12 -22
- package/dist/docs/TilesetField.svelte.d.ts +21 -17
- package/dist/docs/TransformDebug.svelte +5 -6
- package/dist/docs/TransformDebug.svelte.d.ts +18 -14
- package/dist/docs/ViewSourceButton.svelte.d.ts +21 -17
- package/dist/types/d3-shape-extentions.d.ts +7 -0
- package/dist/utils/afterTick.d.ts +5 -0
- package/dist/utils/afterTick.js +8 -0
- package/dist/utils/arcText.svelte.d.ts +57 -0
- package/dist/utils/arcText.svelte.js +262 -0
- package/dist/utils/array.d.ts +9 -1
- package/dist/utils/array.js +13 -0
- package/dist/utils/attributes.d.ts +29 -0
- package/dist/utils/attributes.js +40 -0
- package/dist/utils/canvas.js +47 -10
- package/dist/utils/chart.d.ts +78 -0
- package/dist/utils/chart.js +512 -0
- package/dist/utils/color.d.ts +1 -0
- package/dist/utils/color.js +8 -0
- package/dist/utils/common.d.ts +3 -5
- package/dist/utils/common.js +3 -2
- package/dist/utils/connectorUtils.d.ts +21 -0
- package/dist/utils/connectorUtils.js +111 -0
- package/dist/utils/createId.d.ts +7 -0
- package/dist/utils/createId.js +9 -0
- package/dist/utils/debug.d.ts +1 -0
- package/dist/utils/debug.js +84 -0
- package/dist/utils/filterObject.d.ts +9 -0
- package/dist/utils/filterObject.js +12 -0
- package/dist/utils/graph/dagre.d.ts +34 -0
- package/dist/utils/graph/dagre.js +78 -0
- package/dist/utils/graph/dagre.test.d.ts +1 -0
- package/dist/utils/{graph.test.js → graph/dagre.test.js} +19 -33
- package/dist/utils/graph/sankey.d.ts +28 -0
- package/dist/utils/{graph.js → graph/sankey.js} +13 -41
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/key.svelte.d.ts +3 -0
- package/dist/utils/key.svelte.js +11 -0
- package/dist/utils/legendPayload.d.ts +7 -0
- package/dist/utils/legendPayload.js +8 -0
- package/dist/utils/motion.svelte.d.ts +140 -0
- package/dist/utils/motion.svelte.js +180 -0
- package/dist/utils/motion.test.d.ts +1 -0
- package/dist/utils/motion.test.js +213 -0
- package/dist/utils/{rect.d.ts → rect.svelte.d.ts} +7 -4
- package/dist/utils/rect.svelte.js +105 -0
- package/dist/utils/scales.svelte.d.ts +90 -0
- package/dist/utils/{scales.js → scales.svelte.js} +100 -39
- package/dist/utils/stack.d.ts +2 -3
- package/dist/utils/stack.js +1 -1
- package/dist/utils/string.js +87 -0
- package/dist/utils/ticks.d.ts +8 -2
- package/dist/utils/ticks.js +28 -0
- package/dist/utils/ticks.test.d.ts +1 -0
- package/dist/utils/ticks.test.js +67 -0
- package/dist/utils/types.d.ts +81 -0
- package/package.json +21 -19
- package/dist/components/ChartContext.svelte +0 -295
- package/dist/components/ChartContext.svelte.d.ts +0 -139
- package/dist/components/TransformContext.svelte.d.ts +0 -158
- package/dist/stores/motionStore.d.ts +0 -30
- package/dist/stores/motionStore.js +0 -62
- package/dist/utils/graph.d.ts +0 -37
- package/dist/utils/rect.js +0 -107
- package/dist/utils/scales.d.ts +0 -66
- /package/dist/{utils/graph.test.d.ts → components/charts/types.js} +0 -0
|
@@ -1,110 +1,217 @@
|
|
|
1
|
-
<script lang="ts"
|
|
2
|
-
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type CanvasPropsWithoutHTML = {
|
|
3
|
+
/**
|
|
4
|
+
* The `<canvas>` tag. Useful for bindings.
|
|
5
|
+
*
|
|
6
|
+
* @bindable
|
|
7
|
+
*/
|
|
8
|
+
ref?: HTMLCanvasElement;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The `<canvas>`'s 2d context. Useful for bindings.
|
|
12
|
+
*
|
|
13
|
+
* @bindable
|
|
14
|
+
*/
|
|
15
|
+
canvasContext?: CanvasRenderingContext2D;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Force the use of a software (instead of hardware accelerated) 2D canvas, which can
|
|
19
|
+
* save memory when calling getImageData() frequently.
|
|
20
|
+
*
|
|
21
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext#willreadfrequently
|
|
22
|
+
*
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
willReadFrequently?: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The `z-index` style to apply to the layer.
|
|
29
|
+
*
|
|
30
|
+
* @default 0
|
|
31
|
+
*/
|
|
32
|
+
zIndex?: number;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* Whether pointer events should be enabled on the canvas.
|
|
37
|
+
*
|
|
38
|
+
* - `false`: `pointer-events: none;` will be set on the entire layer.
|
|
39
|
+
* - `true`: pointer events will operate normally.
|
|
40
|
+
*
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
pointerEvents?: boolean;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The content to display if canvas is not supported or cannot be rendered.
|
|
47
|
+
* This can either be a string or a snippet with custom markup.
|
|
48
|
+
*/
|
|
49
|
+
fallback?: string | Snippet;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Translate children to center of the canvas (useful for radial layouts).
|
|
53
|
+
*
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
center?: boolean | 'x' | 'y';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Ignore TransformContext.
|
|
60
|
+
*
|
|
61
|
+
* Useful to add static elements such as legends.
|
|
62
|
+
*
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
65
|
+
ignoreTransform?: boolean;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Show the hit canvas for debugging purposes.
|
|
69
|
+
*
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
debug?: boolean;
|
|
73
|
+
|
|
74
|
+
children?: Snippet<
|
|
75
|
+
[{ ref: HTMLCanvasElement; canvasContext: CanvasRenderingContext2D | undefined }]
|
|
76
|
+
>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type CanvasProps = CanvasPropsWithoutHTML &
|
|
80
|
+
Without<HTMLCanvasAttributes, CanvasPropsWithoutHTML>;
|
|
3
81
|
|
|
4
|
-
type ComponentRender = {
|
|
82
|
+
type ComponentRender<T extends Element = Element> = {
|
|
5
83
|
name: string;
|
|
6
84
|
render: (ctx: CanvasRenderingContext2D, styleOverrides?: ComputedStylesOptions) => any;
|
|
7
85
|
retainState?: boolean;
|
|
8
86
|
events?: {
|
|
9
|
-
click?:
|
|
10
|
-
dblclick?:
|
|
11
|
-
pointerenter?:
|
|
12
|
-
pointerover?:
|
|
13
|
-
pointermove?:
|
|
14
|
-
pointerleave?:
|
|
15
|
-
pointerout?:
|
|
16
|
-
pointerdown?:
|
|
17
|
-
touchmove?:
|
|
87
|
+
click?: MouseEventHandler<T> | null;
|
|
88
|
+
dblclick?: MouseEventHandler<T> | null;
|
|
89
|
+
pointerenter?: PointerEventHandler<T> | null;
|
|
90
|
+
pointerover?: PointerEventHandler<T> | null;
|
|
91
|
+
pointermove?: PointerEventHandler<T> | null;
|
|
92
|
+
pointerleave?: PointerEventHandler<T> | null;
|
|
93
|
+
pointerout?: PointerEventHandler<T> | null;
|
|
94
|
+
pointerdown?: PointerEventHandler<T> | null;
|
|
95
|
+
touchmove?: TouchEventHandler<T> | null;
|
|
18
96
|
};
|
|
97
|
+
/**
|
|
98
|
+
* Optional dependencies to track and invalidate the canvas context when they change.
|
|
99
|
+
*/
|
|
100
|
+
deps?: () => any[];
|
|
19
101
|
};
|
|
20
102
|
|
|
21
|
-
export type
|
|
22
|
-
/**
|
|
23
|
-
|
|
103
|
+
export type CanvasContextValue = {
|
|
104
|
+
/**
|
|
105
|
+
* Register component to render.
|
|
106
|
+
*
|
|
107
|
+
* Returns method to unregister on component destroy
|
|
108
|
+
*/
|
|
109
|
+
register<T extends Element>(component: ComponentRender<T>): () => void;
|
|
24
110
|
invalidate(): void;
|
|
25
111
|
};
|
|
26
112
|
|
|
27
|
-
|
|
113
|
+
const CanvasContext = new Context<CanvasContextValue>('CanvasContext');
|
|
114
|
+
|
|
115
|
+
const defaultCanvasContext: CanvasContextValue = {
|
|
116
|
+
register: <T extends Element>(_: ComponentRender<T>) => {
|
|
117
|
+
return () => {};
|
|
118
|
+
},
|
|
119
|
+
invalidate: () => {},
|
|
120
|
+
};
|
|
28
121
|
|
|
29
122
|
export function getCanvasContext() {
|
|
30
|
-
return
|
|
123
|
+
return CanvasContext.getOr(defaultCanvasContext);
|
|
31
124
|
}
|
|
32
125
|
|
|
33
|
-
function setCanvasContext(context:
|
|
34
|
-
|
|
126
|
+
function setCanvasContext(context: CanvasContextValue) {
|
|
127
|
+
return CanvasContext.set(context);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Handles the automatic registration of the component to the canvas context,
|
|
132
|
+
* with dependency tracking and cleanup on destroy.
|
|
133
|
+
*/
|
|
134
|
+
export function registerCanvasComponent<T extends Element>(component: ComponentRender<T>) {
|
|
135
|
+
const canvasContext = getCanvasContext();
|
|
136
|
+
|
|
137
|
+
$effect.pre(() => {
|
|
138
|
+
return untrack(() => canvasContext.register(component));
|
|
139
|
+
});
|
|
35
140
|
}
|
|
36
141
|
</script>
|
|
37
142
|
|
|
38
143
|
<script lang="ts">
|
|
39
|
-
import { onMount,
|
|
144
|
+
import { onMount, untrack, type Snippet } from 'svelte';
|
|
40
145
|
import { cls } from '@layerstack/tailwind';
|
|
41
146
|
import { Logger, localPoint } from '@layerstack/utils';
|
|
42
147
|
import { darkColorScheme } from '@layerstack/svelte-stores';
|
|
43
148
|
|
|
44
149
|
import { setRenderContext } from '../Chart.svelte';
|
|
45
|
-
import {
|
|
46
|
-
import { transformContext } from '../TransformContext.svelte';
|
|
150
|
+
import { getTransformContext } from '../TransformContext.svelte';
|
|
47
151
|
import { getPixelColor, scaleCanvas, type ComputedStylesOptions } from '../../utils/canvas.js';
|
|
48
152
|
import { getColorStr, rgbColorGenerator } from '../../utils/color.js';
|
|
153
|
+
import { Context } from 'runed';
|
|
154
|
+
import type {
|
|
155
|
+
HTMLCanvasAttributes,
|
|
156
|
+
MouseEventHandler,
|
|
157
|
+
PointerEventHandler,
|
|
158
|
+
TouchEventHandler,
|
|
159
|
+
} from 'svelte/elements';
|
|
160
|
+
import type { Without } from '../../utils/types.js';
|
|
161
|
+
import { getChartContext } from '../Chart.svelte';
|
|
162
|
+
import { layerClass } from '../../utils/attributes.js';
|
|
163
|
+
|
|
164
|
+
let {
|
|
165
|
+
ref: refProp = $bindable(),
|
|
166
|
+
canvasContext: canvasContextProp = $bindable(),
|
|
167
|
+
willReadFrequently = false,
|
|
168
|
+
debug = false,
|
|
169
|
+
zIndex = 0,
|
|
170
|
+
pointerEvents = true,
|
|
171
|
+
fallback,
|
|
172
|
+
center = false,
|
|
173
|
+
ignoreTransform = false,
|
|
174
|
+
class: className,
|
|
175
|
+
children,
|
|
176
|
+
onclick,
|
|
177
|
+
ondblclick,
|
|
178
|
+
onpointerenter,
|
|
179
|
+
onpointermove,
|
|
180
|
+
onpointerleave,
|
|
181
|
+
onpointerdown,
|
|
182
|
+
ontouchmove,
|
|
183
|
+
...restProps
|
|
184
|
+
}: CanvasProps = $props();
|
|
185
|
+
|
|
186
|
+
let ref = $state<HTMLCanvasElement>();
|
|
187
|
+
let context = $state<CanvasRenderingContext2D>();
|
|
188
|
+
|
|
189
|
+
$effect.pre(() => {
|
|
190
|
+
refProp = ref;
|
|
191
|
+
});
|
|
49
192
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
export let element: HTMLCanvasElement | undefined = undefined;
|
|
54
|
-
|
|
55
|
-
/** The `<canvas>`'s 2d context. Useful for bindings. */
|
|
56
|
-
// @ts-expect-error: set during onMount()
|
|
57
|
-
export let context: CanvasRenderingContext2D = undefined;
|
|
58
|
-
|
|
59
|
-
/** Force the use of a software (instead of hardware accelerated) 2D canvas and can save memory when calling getImageData() frequently.
|
|
60
|
-
* see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext#willreadfrequently */
|
|
61
|
-
export let willReadFrequently = false;
|
|
62
|
-
|
|
63
|
-
/** The layer's z-index. */
|
|
64
|
-
export let zIndex = undefined;
|
|
65
|
-
|
|
66
|
-
/** Set this to `false` to set `pointer-events: none;` on the entire layer. */
|
|
67
|
-
export let pointerEvents: boolean | undefined = undefined;
|
|
68
|
-
|
|
69
|
-
/** Text to display if the browser won't render a canvas tag. You can also set arbitrary HTML via the "fallback" slot but this is fine if you just need text. If you use the "fallback" slot, this prop is ignored. */
|
|
70
|
-
export let fallback = '';
|
|
71
|
-
|
|
72
|
-
/** A string passed to the `aria-label` on the `<canvas>` tag. */
|
|
73
|
-
export let label: string | undefined = undefined;
|
|
74
|
-
|
|
75
|
-
/** A string passed to the `aria-labelledby` on the `<canvas>` tag. */
|
|
76
|
-
export let labelledBy: string | undefined = undefined;
|
|
77
|
-
|
|
78
|
-
/** A string passed to `aria-describedby` property on the `<canvas>` tag. */
|
|
79
|
-
export let describedBy: string | undefined = undefined;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Translate children to center (useful for radial layouts)
|
|
83
|
-
*/
|
|
84
|
-
export let center: boolean | 'x' | 'y' = false;
|
|
85
|
-
|
|
86
|
-
/** Ignore TransformContext. Useful to add static elements such as legends. */
|
|
87
|
-
export let ignoreTransform = false;
|
|
193
|
+
$effect.pre(() => {
|
|
194
|
+
canvasContextProp = context;
|
|
195
|
+
});
|
|
88
196
|
|
|
89
|
-
|
|
90
|
-
|
|
197
|
+
const ctx = getChartContext();
|
|
198
|
+
const transformCtx = getTransformContext();
|
|
91
199
|
|
|
92
200
|
const logger = new Logger('Canvas');
|
|
93
201
|
|
|
94
|
-
let components = new Map<Symbol, ComponentRender
|
|
202
|
+
let components = new Map<Symbol, ComponentRender<Element>>();
|
|
95
203
|
let pendingInvalidation = false;
|
|
96
204
|
let frameId: number | undefined;
|
|
97
205
|
|
|
98
|
-
const { mode, scale, translate, dragging, moving } = transformContext();
|
|
99
|
-
|
|
100
206
|
/**
|
|
101
207
|
* HitCanvas
|
|
102
208
|
*/
|
|
103
|
-
let hitCanvasElement
|
|
104
|
-
let hitCanvasContext
|
|
209
|
+
let hitCanvasElement = $state<HTMLCanvasElement>();
|
|
210
|
+
let hitCanvasContext = $state<CanvasRenderingContext2D>();
|
|
105
211
|
let colorGenerator = rgbColorGenerator();
|
|
106
|
-
let activeCanvas = false;
|
|
107
|
-
let lastActiveComponent: ComponentRender |
|
|
212
|
+
let activeCanvas = $state(false);
|
|
213
|
+
let lastActiveComponent: ComponentRender | null | undefined = null;
|
|
214
|
+
|
|
108
215
|
const componentByColor = new Map<string, ComponentRender>();
|
|
109
216
|
|
|
110
217
|
function getPointerComponent(e: PointerEvent | MouseEvent | TouchEvent) {
|
|
@@ -116,7 +223,7 @@
|
|
|
116
223
|
return component;
|
|
117
224
|
}
|
|
118
225
|
|
|
119
|
-
|
|
226
|
+
const onPointerMove: PointerEventHandler<Element> = (e) => {
|
|
120
227
|
activeCanvas = true;
|
|
121
228
|
const component = getPointerComponent(e);
|
|
122
229
|
|
|
@@ -133,9 +240,9 @@
|
|
|
133
240
|
component?.events?.pointermove?.(e);
|
|
134
241
|
|
|
135
242
|
lastActiveComponent = component;
|
|
136
|
-
}
|
|
243
|
+
};
|
|
137
244
|
|
|
138
|
-
|
|
245
|
+
const onPointerLeave: PointerEventHandler<Element> = (e) => {
|
|
139
246
|
// Pointer outside of canvas
|
|
140
247
|
|
|
141
248
|
// Call last active component `pointerleave` event in case it was not triggered by hit canvas (quickly exiting canvas element before `pointermove` is triggered)
|
|
@@ -144,13 +251,13 @@
|
|
|
144
251
|
|
|
145
252
|
lastActiveComponent = null;
|
|
146
253
|
activeCanvas = false;
|
|
147
|
-
}
|
|
254
|
+
};
|
|
148
255
|
/**
|
|
149
256
|
* end HitCanvas
|
|
150
257
|
*/
|
|
151
258
|
|
|
152
259
|
onMount(() => {
|
|
153
|
-
context =
|
|
260
|
+
context = ref?.getContext('2d', { willReadFrequently }) as CanvasRenderingContext2D;
|
|
154
261
|
|
|
155
262
|
hitCanvasContext = hitCanvasElement?.getContext('2d', {
|
|
156
263
|
willReadFrequently: false, // Explicitly set to `false` to resolve pixel artifacts between fill and stroke with the same color (issue #372)
|
|
@@ -172,142 +279,196 @@
|
|
|
172
279
|
|
|
173
280
|
return () => {
|
|
174
281
|
observer.disconnect();
|
|
282
|
+
if (frameId) {
|
|
283
|
+
cancelAnimationFrame(frameId);
|
|
284
|
+
}
|
|
175
285
|
};
|
|
176
286
|
});
|
|
177
287
|
|
|
178
|
-
onDestroy(() => {
|
|
179
|
-
if (frameId) {
|
|
180
|
-
cancelAnimationFrame(frameId);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
|
|
184
288
|
function update() {
|
|
185
289
|
if (!context) return;
|
|
186
|
-
// TODO: only `scaleCanvas()` when containerWidth/Height change (not all invalidations)
|
|
187
|
-
// scaleCanvas in `update()` to fix `requestAnimationFrame()` timing causing flash of blank canvas
|
|
188
|
-
scaleCanvas(context, $containerWidth, $containerHeight);
|
|
189
290
|
|
|
190
|
-
|
|
291
|
+
// scale main canvas
|
|
292
|
+
scaleCanvas(context, ctx.containerWidth, ctx.containerHeight);
|
|
293
|
+
context.clearRect(0, 0, ctx.containerWidth, ctx.containerHeight);
|
|
294
|
+
|
|
295
|
+
// apply padding translation
|
|
296
|
+
context.translate(ctx.padding.left ?? 0, ctx.padding.top ?? 0);
|
|
191
297
|
|
|
192
|
-
|
|
298
|
+
let newTranslate: undefined | { x: number; y: number };
|
|
193
299
|
|
|
300
|
+
// apply centering or transform
|
|
194
301
|
if (center) {
|
|
195
|
-
|
|
196
|
-
x: center === 'x' || center === true ?
|
|
197
|
-
y: center === 'y' || center === true ?
|
|
302
|
+
newTranslate = {
|
|
303
|
+
x: center === 'x' || center === true ? ctx.width / 2 : 0,
|
|
304
|
+
y: center === 'y' || center === true ? ctx.height / 2 : 0,
|
|
198
305
|
};
|
|
199
306
|
context.translate(newTranslate.x, newTranslate.y);
|
|
200
|
-
} else if (mode === 'canvas' && !ignoreTransform) {
|
|
201
|
-
context.translate(
|
|
202
|
-
context.scale(
|
|
307
|
+
} else if (transformCtx.mode === 'canvas' && !ignoreTransform) {
|
|
308
|
+
context.translate(transformCtx.translate.x, transformCtx.translate.y);
|
|
309
|
+
context.scale(transformCtx.scale, transformCtx.scale);
|
|
203
310
|
}
|
|
204
311
|
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
hitCanvasContext.clearRect(0, 0, $containerWidth, $containerHeight);
|
|
209
|
-
hitCanvasContext.setTransform(context.getTransform());
|
|
312
|
+
// separate components into those that retain state and those that don't
|
|
313
|
+
const retainStateComponents: ComponentRender[] = [];
|
|
314
|
+
const nonRetainStateComponents: ComponentRender[] = [];
|
|
210
315
|
|
|
211
|
-
|
|
212
|
-
colorGenerator = rgbColorGenerator();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
components.forEach((c) => {
|
|
316
|
+
for (const [_, c] of components) {
|
|
216
317
|
if (c.retainState) {
|
|
217
|
-
|
|
218
|
-
c.render(context);
|
|
318
|
+
retainStateComponents.push(c);
|
|
219
319
|
} else {
|
|
220
|
-
|
|
221
|
-
c.render(context);
|
|
222
|
-
context.restore();
|
|
320
|
+
nonRetainStateComponents.push(c);
|
|
223
321
|
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// render retainState components on main canvas first
|
|
325
|
+
for (const c of retainStateComponents) {
|
|
326
|
+
c.render(context);
|
|
327
|
+
}
|
|
224
328
|
|
|
225
|
-
|
|
226
|
-
|
|
329
|
+
// store the main canvas transform after retainState components
|
|
330
|
+
const mainTransformAfterRetain = context.getTransform();
|
|
227
331
|
|
|
228
|
-
|
|
332
|
+
// render non-retainState components on main canvas
|
|
333
|
+
for (const c of nonRetainStateComponents) {
|
|
334
|
+
context.save();
|
|
335
|
+
c.render(context);
|
|
336
|
+
context.restore();
|
|
337
|
+
}
|
|
229
338
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
339
|
+
// sync hit canvas with main canvas
|
|
340
|
+
if (hitCanvasContext) {
|
|
341
|
+
// scale hit canvas to match main canvas
|
|
342
|
+
scaleCanvas(hitCanvasContext, ctx.containerWidth, ctx.containerHeight);
|
|
343
|
+
hitCanvasContext.clearRect(0, 0, ctx.containerWidth, ctx.containerHeight);
|
|
344
|
+
|
|
345
|
+
// reset and sync transform to the state after retainState components
|
|
346
|
+
hitCanvasContext.resetTransform();
|
|
347
|
+
hitCanvasContext.setTransform(mainTransformAfterRetain);
|
|
348
|
+
|
|
349
|
+
// reset color generator
|
|
350
|
+
colorGenerator = rgbColorGenerator();
|
|
351
|
+
|
|
352
|
+
const inactiveMoving = !activeCanvas && transformCtx.moving;
|
|
353
|
+
|
|
354
|
+
// render retainState components on hit canvas (e.g., Group)
|
|
355
|
+
for (const c of retainStateComponents) {
|
|
356
|
+
const componentHasEvents = c.events && Object.values(c.events).filter((d) => d).length > 0;
|
|
357
|
+
|
|
358
|
+
if (componentHasEvents && !inactiveMoving && !transformCtx.dragging) {
|
|
359
|
+
// since the transform was already applied via setTransform, skip rendering
|
|
360
|
+
// the retainState component's transform again; proceed to its children
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// render non-retainState components on hit canvas
|
|
366
|
+
for (const c of nonRetainStateComponents) {
|
|
367
|
+
const componentHasEvents = c.events && Object.values(c.events).filter((d) => d).length > 0;
|
|
368
|
+
|
|
369
|
+
if (componentHasEvents && !inactiveMoving && !transformCtx.dragging) {
|
|
370
|
+
const color = getColorStr(colorGenerator.next().value);
|
|
371
|
+
const styleOverrides = { styles: { fill: color, stroke: color, _fillOpacity: 0.1 } };
|
|
234
372
|
|
|
235
|
-
if (c.retainState) {
|
|
236
|
-
c.render(hitCanvasContext, styleOverrides);
|
|
237
|
-
} else {
|
|
238
373
|
hitCanvasContext.save();
|
|
239
374
|
c.render(hitCanvasContext, styleOverrides);
|
|
240
375
|
hitCanvasContext.restore();
|
|
241
|
-
}
|
|
242
376
|
|
|
243
|
-
|
|
377
|
+
componentByColor.set(color, c);
|
|
378
|
+
}
|
|
244
379
|
}
|
|
245
|
-
}
|
|
380
|
+
}
|
|
246
381
|
|
|
247
382
|
pendingInvalidation = false;
|
|
248
383
|
}
|
|
249
384
|
|
|
250
|
-
|
|
251
|
-
register(component) {
|
|
385
|
+
function createCanvasContext(): CanvasContextValue {
|
|
386
|
+
function register<T extends Element>(component: ComponentRender<T>) {
|
|
252
387
|
const key = Symbol();
|
|
253
|
-
components.set(key, component);
|
|
254
|
-
|
|
388
|
+
components.set(key, component as ComponentRender<Element>);
|
|
389
|
+
invalidate();
|
|
390
|
+
|
|
391
|
+
const cleanupRoot = $effect.root(() => {
|
|
392
|
+
if (component.deps) {
|
|
393
|
+
$effect.pre(() => {
|
|
394
|
+
component.deps?.(); // track deps
|
|
395
|
+
invalidate(); // invalidate when deps change.
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
$effect.pre(() => {
|
|
401
|
+
return cleanupRoot;
|
|
402
|
+
});
|
|
255
403
|
|
|
256
|
-
|
|
404
|
+
/**
|
|
405
|
+
* Removes the component from the registry and cleans up the invalidation
|
|
406
|
+
* effect
|
|
407
|
+
*/
|
|
257
408
|
return () => {
|
|
258
409
|
components.delete(key);
|
|
259
|
-
|
|
410
|
+
cleanupRoot();
|
|
411
|
+
invalidate();
|
|
260
412
|
};
|
|
261
|
-
}
|
|
262
|
-
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function invalidate() {
|
|
263
416
|
if (pendingInvalidation) return;
|
|
264
417
|
pendingInvalidation = true;
|
|
265
418
|
frameId = requestAnimationFrame(update);
|
|
266
|
-
}
|
|
267
|
-
};
|
|
419
|
+
}
|
|
268
420
|
|
|
269
|
-
|
|
270
|
-
// Redraw when resized or transform dragging changes. Note: adding `activeCanvas` (pointer enters/exits canvas) causes initial interactivity issues while canvas is rendering and is not needed
|
|
271
|
-
$containerWidth, $containerHeight && $dragging;
|
|
272
|
-
canvasContext.invalidate();
|
|
421
|
+
return { register, invalidate };
|
|
273
422
|
}
|
|
274
423
|
|
|
424
|
+
const canvasContext = createCanvasContext();
|
|
425
|
+
|
|
426
|
+
$effect.pre(() => {
|
|
427
|
+
[ctx.height, ctx.width, ctx.containerHeight, ctx.containerWidth, transformCtx.dragging];
|
|
428
|
+
canvasContext.invalidate();
|
|
429
|
+
});
|
|
430
|
+
|
|
275
431
|
setCanvasContext(canvasContext);
|
|
276
432
|
setRenderContext('canvas');
|
|
277
433
|
</script>
|
|
278
434
|
|
|
279
435
|
<canvas
|
|
280
|
-
bind:this={
|
|
436
|
+
bind:this={ref}
|
|
281
437
|
style:z-index={zIndex}
|
|
282
438
|
class={cls(
|
|
283
|
-
'
|
|
439
|
+
layerClass('layout-canvas'),
|
|
284
440
|
'absolute top-0 left-0 w-full h-full',
|
|
285
441
|
pointerEvents === false && 'pointer-events-none',
|
|
286
|
-
|
|
442
|
+
className
|
|
287
443
|
)}
|
|
288
|
-
|
|
289
|
-
aria-labelledby={labelledBy}
|
|
290
|
-
aria-describedby={describedBy}
|
|
291
|
-
on:click={(e) => {
|
|
444
|
+
onclick={(e) => {
|
|
292
445
|
const component = getPointerComponent(e);
|
|
293
446
|
component?.events?.click?.(e);
|
|
447
|
+
onclick?.(e);
|
|
294
448
|
}}
|
|
295
|
-
|
|
296
|
-
on:dblclick={(e) => {
|
|
449
|
+
ondblclick={(e) => {
|
|
297
450
|
const component = getPointerComponent(e);
|
|
298
451
|
component?.events?.dblclick?.(e);
|
|
452
|
+
ondblclick?.(e);
|
|
299
453
|
}}
|
|
300
|
-
|
|
454
|
+
onpointerdown={(e) => {
|
|
301
455
|
const component = getPointerComponent(e);
|
|
302
456
|
component?.events?.pointerdown?.(e);
|
|
457
|
+
onpointerdown?.(e);
|
|
458
|
+
}}
|
|
459
|
+
onpointerenter={(e) => {
|
|
460
|
+
onpointerenter?.(e);
|
|
461
|
+
onPointerMove(e);
|
|
462
|
+
}}
|
|
463
|
+
onpointermove={(e) => {
|
|
464
|
+
onpointermove?.(e);
|
|
465
|
+
onPointerMove(e);
|
|
466
|
+
}}
|
|
467
|
+
onpointerleave={(e) => {
|
|
468
|
+
onpointerleave?.(e);
|
|
469
|
+
onPointerLeave(e);
|
|
303
470
|
}}
|
|
304
|
-
|
|
305
|
-
on:pointerenter
|
|
306
|
-
on:pointermove={onPointerMove}
|
|
307
|
-
on:pointermove
|
|
308
|
-
on:pointerleave={onPointerLeave}
|
|
309
|
-
on:pointerleave
|
|
310
|
-
on:touchmove={(e) => {
|
|
471
|
+
ontouchmove={(e) => {
|
|
311
472
|
// Prevent touch from interfering with pointer if over data
|
|
312
473
|
if (lastActiveComponent) {
|
|
313
474
|
e.preventDefault();
|
|
@@ -316,17 +477,22 @@
|
|
|
316
477
|
const component = getPointerComponent(e);
|
|
317
478
|
component?.events?.touchmove?.(e);
|
|
318
479
|
}}
|
|
319
|
-
|
|
480
|
+
{...restProps}
|
|
320
481
|
>
|
|
321
|
-
|
|
322
|
-
{fallback
|
|
323
|
-
|
|
482
|
+
{#if fallback}
|
|
483
|
+
{#if typeof fallback === 'function'}
|
|
484
|
+
{@render fallback()}
|
|
485
|
+
{:else}
|
|
486
|
+
{fallback}
|
|
487
|
+
{/if}
|
|
488
|
+
{/if}
|
|
324
489
|
</canvas>
|
|
325
490
|
|
|
326
491
|
<!-- Hit canvas used for hidden context -->
|
|
327
492
|
<canvas
|
|
328
493
|
bind:this={hitCanvasElement}
|
|
329
494
|
class={cls(
|
|
495
|
+
layerClass('hit-canvas'),
|
|
330
496
|
'layerchart-hitcanvas',
|
|
331
497
|
'absolute top-0 left-0 w-full h-full',
|
|
332
498
|
'pointer-events-none', // events all handled by main canvas
|
|
@@ -336,4 +502,4 @@
|
|
|
336
502
|
)}
|
|
337
503
|
></canvas>
|
|
338
504
|
|
|
339
|
-
|
|
505
|
+
{@render children?.({ ref, canvasContext: context })}
|