layerchart 2.0.0-next.44 → 2.0.0-next.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/components/AnnotationLine.svelte +1 -1
- package/dist/components/AnnotationPoint.svelte +1 -1
- package/dist/components/AnnotationRange.svelte +16 -15
- package/dist/components/Arc.svelte +10 -10
- package/dist/components/Arc.svelte.d.ts +4 -4
- package/dist/components/Arc.svelte.test.d.ts +1 -0
- package/dist/components/Arc.svelte.test.js +868 -0
- package/dist/components/Area.svelte +9 -7
- package/dist/components/Axis.svelte +2 -1
- package/dist/components/Axis.svelte.d.ts +1 -0
- package/dist/components/Bar.svelte +3 -3
- package/dist/components/Bars.svelte +1 -1
- package/dist/components/Blur.svelte +3 -3
- package/dist/components/Bounds.svelte +1 -1
- package/dist/components/BrushContext.svelte +1 -1
- package/dist/components/Calendar.svelte +2 -2
- package/dist/components/Calendar.svelte.d.ts +1 -1
- package/dist/components/Chart.svelte +63 -137
- package/dist/components/Chart.svelte.d.ts +23 -88
- package/dist/components/ChartClipPath.svelte +1 -1
- package/dist/components/Circle.svelte +17 -8
- package/dist/components/Circle.svelte.d.ts +3 -0
- package/dist/components/ClipPath.svelte +4 -4
- package/dist/components/Connector.svelte +4 -4
- package/dist/components/Connector.svelte.d.ts +3 -3
- package/dist/components/Ellipse.svelte +7 -7
- package/dist/components/Frame.svelte +1 -1
- package/dist/components/GeoContext.svelte +4 -20
- package/dist/components/GeoContext.svelte.d.ts +2 -6
- package/dist/components/GeoEdgeFade.svelte +1 -1
- package/dist/components/GeoPath.svelte +42 -107
- package/dist/components/GeoPath.svelte.d.ts +5 -4
- package/dist/components/GeoPoint.svelte +5 -5
- package/dist/components/GeoSpline.svelte +2 -14
- package/dist/components/GeoSpline.svelte.d.ts +1 -1
- package/dist/components/GeoTile.svelte +7 -6
- package/dist/components/GeoVisible.svelte +1 -1
- package/dist/components/Graticule.svelte +4 -7
- package/dist/components/Graticule.svelte.d.ts +2 -1
- package/dist/components/Grid.svelte +1 -1
- package/dist/components/Group.svelte +8 -8
- package/dist/components/Highlight.svelte +18 -16
- package/dist/components/Hull.svelte +2 -2
- package/dist/components/Labels.svelte +1 -1
- package/dist/components/Legend.svelte +1 -1
- package/dist/components/Line.svelte +9 -7
- package/dist/components/LinearGradient.svelte +8 -7
- package/dist/components/MonthPath.svelte +5 -11
- package/dist/components/MonthPath.svelte.d.ts +2 -2
- package/dist/components/Pack.svelte +4 -6
- package/dist/components/Pack.svelte.d.ts +2 -4
- package/dist/components/Partition.svelte +4 -3
- package/dist/components/Partition.svelte.d.ts +2 -1
- package/dist/components/Path.svelte +344 -0
- package/dist/components/Path.svelte.d.ts +72 -0
- package/dist/components/Pattern.svelte +6 -6
- package/dist/components/Pie.svelte +2 -2
- package/dist/components/Pie.svelte.d.ts +1 -1
- package/dist/components/Point.svelte +1 -1
- package/dist/components/Points.svelte +1 -1
- package/dist/components/Polygon.svelte +8 -6
- package/dist/components/RadialGradient.svelte +7 -7
- package/dist/components/Rect.svelte +32 -10
- package/dist/components/Rect.svelte.d.ts +4 -1
- package/dist/components/Rule.svelte +1 -1
- package/dist/components/Sankey.svelte +1 -1
- package/dist/components/Spline.svelte +13 -337
- package/dist/components/Spline.svelte.d.ts +10 -73
- package/dist/components/Text.svelte +9 -7
- package/dist/components/Threshold.svelte +3 -3
- package/dist/components/TransformContext.svelte +10 -143
- package/dist/components/TransformControls.svelte +2 -2
- package/dist/components/TransformControls.svelte.d.ts +1 -1
- package/dist/components/Tree.svelte +4 -3
- package/dist/components/Tree.svelte.d.ts +2 -1
- package/dist/components/Treemap.svelte +4 -3
- package/dist/components/Treemap.svelte.d.ts +2 -1
- package/dist/components/Voronoi.svelte +5 -5
- package/dist/components/charts/ArcChart.svelte +14 -6
- package/dist/components/charts/ArcChart.svelte.d.ts +1 -1
- package/dist/components/charts/AreaChart.svelte +12 -6
- package/dist/components/charts/BarChart.svelte +12 -6
- package/dist/components/charts/DefaultTooltip.svelte +1 -1
- package/dist/components/charts/LineChart.svelte +12 -6
- package/dist/components/charts/PieChart.svelte +14 -6
- package/dist/components/charts/PieChart.svelte.d.ts +1 -1
- package/dist/components/charts/ScatterChart.svelte +11 -9
- package/dist/components/charts/types.d.ts +7 -6
- package/dist/components/index.d.ts +14 -12
- package/dist/components/index.js +14 -12
- package/dist/components/{layout → layers}/Canvas.svelte +13 -60
- package/dist/components/{layout → layers}/Canvas.svelte.d.ts +2 -32
- package/dist/components/{layout → layers}/Html.svelte +18 -3
- package/dist/components/{layout → layers}/Html.svelte.d.ts +7 -0
- package/dist/components/layers/Layer.svelte +85 -0
- package/dist/components/{layout → layers}/Layer.svelte.d.ts +7 -3
- package/dist/components/{layout → layers}/Svg.svelte +18 -3
- package/dist/components/{layout → layers}/Svg.svelte.d.ts +7 -0
- package/dist/components/{layout → layers}/WebGL.svelte +1 -1
- package/dist/components/{layout → layers}/WebGL.svelte.d.ts +3 -3
- package/dist/components/tests/TestHarness.svelte +76 -0
- package/dist/components/tests/TestHarness.svelte.d.ts +19 -0
- package/dist/components/tooltip/Tooltip.svelte +3 -3
- package/dist/components/tooltip/Tooltip.svelte.d.ts +1 -1
- package/dist/components/tooltip/TooltipContext.svelte +13 -45
- package/dist/components/tooltip/TooltipContext.svelte.d.ts +2 -14
- package/dist/components/tooltip/tooltipMetaContext.d.ts +2 -2
- package/dist/components/tooltip/tooltipMetaContext.js +2 -2
- package/dist/contexts/canvas.d.ts +33 -0
- package/dist/contexts/canvas.js +14 -0
- package/dist/contexts/chart.d.ts +84 -0
- package/dist/contexts/chart.js +10 -0
- package/dist/contexts/geo.d.ts +6 -0
- package/dist/contexts/geo.js +12 -0
- package/dist/contexts/index.d.ts +6 -0
- package/dist/contexts/index.js +6 -0
- package/dist/contexts/layer.d.ts +3 -0
- package/dist/contexts/layer.js +8 -0
- package/dist/contexts/settings.d.ts +4 -0
- package/dist/contexts/settings.js +10 -0
- package/dist/contexts/tooltip.d.ts +15 -0
- package/dist/contexts/tooltip.js +8 -0
- package/dist/contexts/transform.d.ts +95 -0
- package/dist/contexts/transform.js +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/states/settings.svelte.d.ts +12 -0
- package/dist/states/settings.svelte.js +10 -0
- package/dist/states/transform.svelte.d.ts +9 -0
- package/dist/states/transform.svelte.js +31 -0
- package/dist/utils/arcText.svelte.d.ts +1 -1
- package/dist/utils/canvas.d.ts +7 -3
- package/dist/utils/canvas.js +78 -11
- package/dist/utils/common.d.ts +8 -1
- package/dist/utils/common.js +9 -10
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/motion.svelte.js +0 -1
- package/dist/utils/rect.svelte.d.ts +1 -1
- package/dist/utils/rect.svelte.js +17 -9
- package/dist/utils/scales.svelte.js +2 -2
- package/dist/utils/string.d.ts +3 -1
- package/package.json +32 -54
- package/README.md +0 -41
- package/dist/components/layout/Layer.svelte +0 -41
- package/dist/docs/Blockquote.svelte +0 -17
- package/dist/docs/Blockquote.svelte.d.ts +0 -5
- package/dist/docs/Code.svelte +0 -80
- package/dist/docs/Code.svelte.d.ts +0 -14
- package/dist/docs/ConnectorSweepMenuField.svelte +0 -17
- package/dist/docs/ConnectorSweepMenuField.svelte.d.ts +0 -7
- package/dist/docs/ConnectorTypeMenuField.svelte +0 -17
- package/dist/docs/ConnectorTypeMenuField.svelte.d.ts +0 -7
- package/dist/docs/CurveMenuField.svelte +0 -44
- package/dist/docs/CurveMenuField.svelte.d.ts +0 -9
- package/dist/docs/GeoDebug.svelte +0 -60
- package/dist/docs/GeoDebug.svelte.d.ts +0 -4
- package/dist/docs/Header1.svelte +0 -16
- package/dist/docs/Header1.svelte.d.ts +0 -5
- package/dist/docs/Json.svelte +0 -36
- package/dist/docs/Json.svelte.d.ts +0 -10
- package/dist/docs/Layout.svelte +0 -21
- package/dist/docs/Layout.svelte.d.ts +0 -8
- package/dist/docs/Link.svelte +0 -9
- package/dist/docs/Link.svelte.d.ts +0 -5
- package/dist/docs/PathDataMenuField.svelte +0 -78
- package/dist/docs/PathDataMenuField.svelte.d.ts +0 -9
- package/dist/docs/Preview.svelte +0 -104
- package/dist/docs/Preview.svelte.d.ts +0 -13
- package/dist/docs/TilesetField.svelte +0 -136
- package/dist/docs/TilesetField.svelte.d.ts +0 -6
- package/dist/docs/TransformDebug.svelte +0 -22
- package/dist/docs/TransformDebug.svelte.d.ts +0 -20
- package/dist/docs/ViewSourceButton.svelte +0 -53
- package/dist/docs/ViewSourceButton.svelte.d.ts +0 -11
- package/dist/utils/graph/dagre.d.ts +0 -34
- /package/dist/{utils → contexts}/legendPayload.d.ts +0 -0
- /package/dist/{utils → contexts}/legendPayload.js +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type TransformMode, type TransformScrollMode } from '../states/transform.svelte.js';
|
|
2
|
+
import type { MotionProp } from '../utils/motion.svelte.js';
|
|
3
|
+
export type TransformContextValue = {
|
|
4
|
+
/**
|
|
5
|
+
* The current transform mode.
|
|
6
|
+
*
|
|
7
|
+
* - `canvas`: The transform is applied to the canvas element.
|
|
8
|
+
* - `manual`: The transform is applied manually.
|
|
9
|
+
* - `none`: No transform is applied.
|
|
10
|
+
*/
|
|
11
|
+
mode: TransformMode;
|
|
12
|
+
/**
|
|
13
|
+
* The current scale of the transform.
|
|
14
|
+
*/
|
|
15
|
+
scale: number;
|
|
16
|
+
/**
|
|
17
|
+
* Set the scale of the transform
|
|
18
|
+
* @param value - the scale value to set
|
|
19
|
+
* @param options - motion options to apply to the transform (defaults to the motion options passed to the component)
|
|
20
|
+
*/
|
|
21
|
+
setScale(value: number, options?: MotionProp): void;
|
|
22
|
+
/**
|
|
23
|
+
* The current translate of the transform.
|
|
24
|
+
*/
|
|
25
|
+
translate: {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Set the translate of the transform
|
|
31
|
+
* @param point - the point to translate to
|
|
32
|
+
* @param options - motion options to apply to the transform (defaults to the motion options passed to the component)
|
|
33
|
+
*/
|
|
34
|
+
setTranslate(point: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
}, options?: MotionProp): void;
|
|
38
|
+
/**
|
|
39
|
+
* Whether the transform is currently being moved
|
|
40
|
+
*/
|
|
41
|
+
moving: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the transform is currently being dragged
|
|
44
|
+
*/
|
|
45
|
+
dragging: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* The scroll mode of the transform.
|
|
48
|
+
*
|
|
49
|
+
* - `scale`: Scrolling will zoom in/out the canvas.
|
|
50
|
+
* - `translate`: Scrolling will pan the canvas.
|
|
51
|
+
* - `none`: No scroll mode is applied.
|
|
52
|
+
*/
|
|
53
|
+
scrollMode: TransformScrollMode;
|
|
54
|
+
/**
|
|
55
|
+
* Set the scroll mode of the transform
|
|
56
|
+
*
|
|
57
|
+
* @param mode - the scroll mode to set
|
|
58
|
+
*/
|
|
59
|
+
setScrollMode(mode: TransformScrollMode): void;
|
|
60
|
+
/**
|
|
61
|
+
* Reset the transform to its initial state
|
|
62
|
+
*/
|
|
63
|
+
reset(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Zoom in the transform
|
|
66
|
+
*/
|
|
67
|
+
zoomIn(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Zoom out the transform
|
|
70
|
+
*
|
|
71
|
+
*/
|
|
72
|
+
zoomOut(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Translate the transform to the center of the canvas
|
|
75
|
+
*/
|
|
76
|
+
translateCenter(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Zoom to a specific point in the canvas
|
|
79
|
+
*
|
|
80
|
+
* @param center - The point (in chart coordinates) that should become the new
|
|
81
|
+
* center of the view after zooming.
|
|
82
|
+
*
|
|
83
|
+
* @param rect - A rectangular region (in chart coordinates) that the view should scale to fit.
|
|
84
|
+
* If omitted, the scale defaults to 1 (no zoom).
|
|
85
|
+
*/
|
|
86
|
+
zoomTo(center: {
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
}, rect?: {
|
|
90
|
+
width: number;
|
|
91
|
+
height: number;
|
|
92
|
+
}): void;
|
|
93
|
+
};
|
|
94
|
+
export declare function getTransformContext(): TransformContextValue;
|
|
95
|
+
export declare function setTransformContext(transform: TransformContextValue): TransformContextValue;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from 'runed';
|
|
2
|
+
import {} from '../components/TransformContext.svelte';
|
|
3
|
+
import { createDefaultTransformContext, } from '../states/transform.svelte.js';
|
|
4
|
+
const _TransformContext = new Context('TransformContext');
|
|
5
|
+
export function getTransformContext() {
|
|
6
|
+
return _TransformContext.getOr(createDefaultTransformContext());
|
|
7
|
+
}
|
|
8
|
+
export function setTransformContext(transform) {
|
|
9
|
+
return _TransformContext.set(transform);
|
|
10
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LayerContext } from '../contexts/layer.js';
|
|
2
|
+
export type SettingsOptions = {
|
|
3
|
+
layer?: LayerContext;
|
|
4
|
+
debug?: boolean;
|
|
5
|
+
};
|
|
6
|
+
/** Global settings context for charts */
|
|
7
|
+
export declare class Settings {
|
|
8
|
+
layer: LayerContext;
|
|
9
|
+
debug: boolean;
|
|
10
|
+
constructor(options?: SettingsOptions);
|
|
11
|
+
}
|
|
12
|
+
export declare const defaultSettings: Settings;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Global settings context for charts */
|
|
2
|
+
export class Settings {
|
|
3
|
+
layer;
|
|
4
|
+
debug;
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.layer = $state(options.layer ?? 'svg');
|
|
7
|
+
this.debug = $state(options.debug ?? false);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export const defaultSettings = new Settings();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TransformContextValue } from '../contexts/transform.js';
|
|
2
|
+
export type TransformMode = 'canvas' | 'manual' | 'none';
|
|
3
|
+
export type TransformScrollMode = 'scale' | 'translate' | 'none';
|
|
4
|
+
export declare const DEFAULT_TRANSLATE: {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const DEFAULT_SCALE = 1;
|
|
9
|
+
export declare function createDefaultTransformContext(): TransformContextValue;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const DEFAULT_TRANSLATE = { x: 0, y: 0 };
|
|
2
|
+
export const DEFAULT_SCALE = 1;
|
|
3
|
+
export function createDefaultTransformContext() {
|
|
4
|
+
let defaultTranslate = $state(DEFAULT_TRANSLATE);
|
|
5
|
+
let defaultScale = $state(DEFAULT_SCALE);
|
|
6
|
+
const defaultContext = {
|
|
7
|
+
mode: 'none',
|
|
8
|
+
get scale() {
|
|
9
|
+
return defaultScale;
|
|
10
|
+
},
|
|
11
|
+
setScale: (value) => {
|
|
12
|
+
defaultScale = value;
|
|
13
|
+
},
|
|
14
|
+
get translate() {
|
|
15
|
+
return defaultTranslate;
|
|
16
|
+
},
|
|
17
|
+
setTranslate: (value) => {
|
|
18
|
+
defaultTranslate = value;
|
|
19
|
+
},
|
|
20
|
+
moving: false,
|
|
21
|
+
dragging: false,
|
|
22
|
+
scrollMode: 'none',
|
|
23
|
+
setScrollMode: () => { },
|
|
24
|
+
reset: () => { },
|
|
25
|
+
zoomIn: () => { },
|
|
26
|
+
zoomOut: () => { },
|
|
27
|
+
translateCenter: () => { },
|
|
28
|
+
zoomTo: () => { },
|
|
29
|
+
};
|
|
30
|
+
return defaultContext;
|
|
31
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Getter, GetterValues } from './types.js';
|
|
8
8
|
import type { ComponentProps } from 'svelte';
|
|
9
|
-
import type
|
|
9
|
+
import type Text from '../components/Text.svelte';
|
|
10
10
|
export type ArcTextProps = GetterValues<{
|
|
11
11
|
innerRadius: number;
|
|
12
12
|
outerRadius: number;
|
package/dist/utils/canvas.d.ts
CHANGED
|
@@ -9,12 +9,14 @@ type StyleOptions = Partial<Omit<CSSStyleDeclaration, 'fillOpacity' | 'strokeWid
|
|
|
9
9
|
export type ComputedStylesOptions = {
|
|
10
10
|
styles?: StyleOptions;
|
|
11
11
|
classes?: ClassValue | null;
|
|
12
|
+
/** Inline style string (e.g., 'stroke-dasharray: 6 4') - will be parsed and merged with styles */
|
|
13
|
+
style?: string | null;
|
|
12
14
|
};
|
|
13
15
|
/**
|
|
14
16
|
* Appends or reuses `<svg>` element below `<canvas>` to resolve CSS variables and classes (ex. `stroke: var(--color-primary)` => `stroke: rgb(...)` )
|
|
15
17
|
*/
|
|
16
18
|
export declare function _getComputedStyles(canvas: HTMLCanvasElement, { styles, classes }?: ComputedStylesOptions): CSSStyleDeclaration;
|
|
17
|
-
export declare const getComputedStyles:
|
|
19
|
+
export declare const getComputedStyles: typeof _getComputedStyles;
|
|
18
20
|
/** Render SVG path data onto canvas context. Supports CSS variables and classes by tranferring to hidden `<svg>` element before retrieval) */
|
|
19
21
|
export declare function renderPathData(ctx: CanvasRenderingContext2D, pathData: string | null | undefined, styleOptions?: ComputedStylesOptions): void;
|
|
20
22
|
export declare function renderText(ctx: CanvasRenderingContext2D, text: string | number | null | undefined, coords: {
|
|
@@ -26,6 +28,8 @@ export declare function renderRect(ctx: CanvasRenderingContext2D, coords: {
|
|
|
26
28
|
y: number;
|
|
27
29
|
width: number;
|
|
28
30
|
height: number;
|
|
31
|
+
rx?: number;
|
|
32
|
+
ry?: number;
|
|
29
33
|
}, styleOptions?: ComputedStylesOptions): void;
|
|
30
34
|
export declare function renderCircle(ctx: CanvasRenderingContext2D, coords: {
|
|
31
35
|
cx: number;
|
|
@@ -70,8 +74,8 @@ export declare function _createLinearGradient(ctx: CanvasRenderingContext2D, x0:
|
|
|
70
74
|
color: string;
|
|
71
75
|
}[]): CanvasGradient;
|
|
72
76
|
/** Create linear gradient and memoize result to fix reactivity */
|
|
73
|
-
export declare const createLinearGradient:
|
|
77
|
+
export declare const createLinearGradient: typeof _createLinearGradient;
|
|
74
78
|
export declare function _createPattern(ctx: CanvasRenderingContext2D, width: number, height: number, shapes: PatternShape[], background?: string): CanvasPattern | null;
|
|
75
79
|
/** Create pattern and memoize result to fix reactivity */
|
|
76
|
-
export declare const createPattern:
|
|
80
|
+
export declare const createPattern: typeof _createPattern;
|
|
77
81
|
export {};
|
package/dist/utils/canvas.js
CHANGED
|
@@ -2,11 +2,36 @@ import memoize from 'memoize';
|
|
|
2
2
|
import { cls } from '@layerstack/tailwind';
|
|
3
3
|
export const DEFAULT_FILL = 'rgb(0, 0, 0)';
|
|
4
4
|
const CANVAS_STYLES_ELEMENT_ID = '__layerchart_canvas_styles_id';
|
|
5
|
+
/**
|
|
6
|
+
* Parse an inline CSS style string into a StyleOptions object.
|
|
7
|
+
* Converts kebab-case properties to camelCase (e.g., 'stroke-dasharray' -> 'strokeDasharray')
|
|
8
|
+
*/
|
|
9
|
+
function parseStyleString(styleString) {
|
|
10
|
+
if (!styleString)
|
|
11
|
+
return {};
|
|
12
|
+
const styles = {};
|
|
13
|
+
// Split by semicolons and process each declaration
|
|
14
|
+
const declarations = styleString.split(';').filter((s) => s.trim());
|
|
15
|
+
for (const declaration of declarations) {
|
|
16
|
+
const colonIndex = declaration.indexOf(':');
|
|
17
|
+
if (colonIndex === -1)
|
|
18
|
+
continue;
|
|
19
|
+
const property = declaration.slice(0, colonIndex).trim();
|
|
20
|
+
const value = declaration.slice(colonIndex + 1).trim();
|
|
21
|
+
if (!property || !value)
|
|
22
|
+
continue;
|
|
23
|
+
// Convert kebab-case to camelCase (e.g., 'stroke-dasharray' -> 'strokeDasharray')
|
|
24
|
+
const camelProperty = property.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
25
|
+
styles[camelProperty] = value;
|
|
26
|
+
}
|
|
27
|
+
return styles;
|
|
28
|
+
}
|
|
5
29
|
const supportedStyles = [
|
|
6
30
|
'fill',
|
|
7
31
|
'fillOpacity',
|
|
8
32
|
'stroke',
|
|
9
33
|
'strokeWidth',
|
|
34
|
+
'strokeDasharray',
|
|
10
35
|
'opacity',
|
|
11
36
|
'fontWeight',
|
|
12
37
|
'fontSize',
|
|
@@ -69,16 +94,19 @@ export const getComputedStyles = memoize(_getComputedStyles, {
|
|
|
69
94
|
/** Render onto canvas context. Supports CSS variables and classes by tranferring to hidden `<svg>` element before retrieval) */
|
|
70
95
|
function render(ctx, render, styleOptions = {}, { applyText, } = {}) {
|
|
71
96
|
// console.count('render');
|
|
97
|
+
// Parse inline style string and merge with styles object
|
|
98
|
+
const parsedInlineStyles = parseStyleString(styleOptions.style);
|
|
99
|
+
const mergedStyles = { ...styleOptions.styles, ...parsedInlineStyles };
|
|
72
100
|
// TODO: Consider memoizing? How about reactiving to CSS variable changes (light/dark mode toggle)
|
|
73
101
|
let resolvedStyles;
|
|
74
102
|
if (styleOptions.classes == null &&
|
|
75
|
-
!Object.values(
|
|
103
|
+
!Object.values(mergedStyles).some((v) => typeof v === 'string' && v.includes('var('))) {
|
|
76
104
|
// Skip resolving styles if no classes are provided and no styles are using CSS variables
|
|
77
|
-
resolvedStyles =
|
|
105
|
+
resolvedStyles = mergedStyles;
|
|
78
106
|
}
|
|
79
107
|
else {
|
|
80
108
|
// Remove constant non-css variable properties (ex. `strokeWidth: 0.5`, `fill: #123456`) as not needed and improves memoization cache hit
|
|
81
|
-
const { constantStyles, variableStyles } = Object.entries(
|
|
109
|
+
const { constantStyles, variableStyles } = Object.entries(mergedStyles).reduce((acc, [key, value]) => {
|
|
82
110
|
if (typeof value === 'number' || (typeof value === 'string' && !value.includes('var('))) {
|
|
83
111
|
acc.constantStyles[key] = value;
|
|
84
112
|
}
|
|
@@ -120,12 +148,15 @@ function render(ctx, render, styleOptions = {}, { applyText, } = {}) {
|
|
|
120
148
|
// ctx.textBaseline = 'hanging';
|
|
121
149
|
// ctx.textBaseline = 'ideographic';
|
|
122
150
|
}
|
|
123
|
-
// Dashed lines
|
|
124
|
-
if (resolvedStyles.strokeDasharray
|
|
151
|
+
// Dashed lines (supports both comma and space separators, e.g., "2,2" or "2 2")
|
|
152
|
+
if (resolvedStyles.strokeDasharray && resolvedStyles.strokeDasharray !== 'none') {
|
|
125
153
|
const dashArray = resolvedStyles.strokeDasharray
|
|
126
|
-
.split(
|
|
154
|
+
.split(/[\s,]+/)
|
|
155
|
+
.filter((s) => s.length > 0)
|
|
127
156
|
.map((s) => Number(s.replace('px', '')));
|
|
128
|
-
|
|
157
|
+
if (dashArray.length > 0 && dashArray.every((n) => !isNaN(n))) {
|
|
158
|
+
ctx.setLineDash(dashArray);
|
|
159
|
+
}
|
|
129
160
|
}
|
|
130
161
|
for (const attr of paintOrder) {
|
|
131
162
|
if (attr === 'fill') {
|
|
@@ -180,10 +211,46 @@ export function renderText(ctx, text, coords, styleOptions = {}) {
|
|
|
180
211
|
}
|
|
181
212
|
}
|
|
182
213
|
export function renderRect(ctx, coords, styleOptions = {}) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
214
|
+
const { x, y, width, height } = coords;
|
|
215
|
+
const rx = coords.rx ?? 0;
|
|
216
|
+
const ry = coords.ry ?? rx; // Default ry to rx if not provided (SVG behavior)
|
|
217
|
+
// No rounding - use simple rect methods
|
|
218
|
+
if (rx === 0 && ry === 0) {
|
|
219
|
+
render(ctx, {
|
|
220
|
+
fill: (ctx) => ctx.fillRect(x, y, width, height),
|
|
221
|
+
stroke: (ctx) => ctx.strokeRect(x, y, width, height),
|
|
222
|
+
}, styleOptions);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
// Try native roundRect if available (modern browsers)
|
|
226
|
+
if (typeof ctx.roundRect === 'function') {
|
|
227
|
+
ctx.beginPath();
|
|
228
|
+
ctx.roundRect(x, y, width, height, [rx, ry]);
|
|
229
|
+
render(ctx, {
|
|
230
|
+
fill: (ctx) => ctx.fill(),
|
|
231
|
+
stroke: (ctx) => ctx.stroke(),
|
|
232
|
+
}, styleOptions);
|
|
233
|
+
ctx.closePath();
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
// Fallback: use path rendering for rounded corners
|
|
237
|
+
// Clamp radii to half the width/height
|
|
238
|
+
const clampedRx = Math.min(rx, width / 2);
|
|
239
|
+
const clampedRy = Math.min(ry, height / 2);
|
|
240
|
+
// Build rounded rect path: start at top-left (after corner), go clockwise
|
|
241
|
+
const pathData = [
|
|
242
|
+
`M${x + clampedRx},${y}`, // Move to top-left (after corner)
|
|
243
|
+
`h${width - 2 * clampedRx}`, // Top edge
|
|
244
|
+
`a${clampedRx},${clampedRy} 0 0 1 ${clampedRx},${clampedRy}`, // Top-right corner
|
|
245
|
+
`v${height - 2 * clampedRy}`, // Right edge
|
|
246
|
+
`a${clampedRx},${clampedRy} 0 0 1 ${-clampedRx},${clampedRy}`, // Bottom-right corner
|
|
247
|
+
`h${2 * clampedRx - width}`, // Bottom edge
|
|
248
|
+
`a${clampedRx},${clampedRy} 0 0 1 ${-clampedRx},${-clampedRy}`, // Bottom-left corner
|
|
249
|
+
`v${2 * clampedRy - height}`, // Left edge
|
|
250
|
+
`a${clampedRx},${clampedRy} 0 0 1 ${clampedRx},${-clampedRy}`, // Top-left corner
|
|
251
|
+
'z', // Close path
|
|
252
|
+
].join(' ');
|
|
253
|
+
renderPathData(ctx, pathData, styleOptions);
|
|
187
254
|
}
|
|
188
255
|
export function renderCircle(ctx, coords, styleOptions = {}) {
|
|
189
256
|
ctx.beginPath();
|
package/dist/utils/common.d.ts
CHANGED
|
@@ -5,7 +5,14 @@ export type Accessor<TData = any> = number | string | ((d: TData) => any) | unde
|
|
|
5
5
|
export declare function accessor<TData = any>(prop: Accessor<TData>): (d: TData) => any;
|
|
6
6
|
/** Guarantee chart data is an array */
|
|
7
7
|
export declare function chartDataArray<TData = any>(data: ComponentProps<Chart<TData>>['data']): any[];
|
|
8
|
-
export declare function defaultChartPadding<TData, SeriesComponent extends Component, TSnippetProps>(
|
|
8
|
+
export declare function defaultChartPadding<TData, SeriesComponent extends Component, TSnippetProps>(options?: {
|
|
9
|
+
axis?: SimplifiedChartProps<TData, SeriesComponent, TSnippetProps>['axis'];
|
|
10
|
+
legend?: SimplifiedChartProps<TData, SeriesComponent, TSnippetProps>['legend'];
|
|
11
|
+
top?: number;
|
|
12
|
+
left?: number;
|
|
13
|
+
bottom?: number;
|
|
14
|
+
right?: number;
|
|
15
|
+
} | undefined): {
|
|
9
16
|
top: number;
|
|
10
17
|
left: number;
|
|
11
18
|
bottom: number;
|
package/dist/utils/common.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { get } from '
|
|
1
|
+
import { get } from '@layerstack/utils';
|
|
2
2
|
export function accessor(prop) {
|
|
3
3
|
if (Array.isArray(prop)) {
|
|
4
4
|
return (d) => prop.map((p) => accessor(p)(d));
|
|
@@ -32,18 +32,17 @@ export function chartDataArray(data) {
|
|
|
32
32
|
}
|
|
33
33
|
return [];
|
|
34
34
|
}
|
|
35
|
-
export function defaultChartPadding(
|
|
35
|
+
export function defaultChartPadding(options = {}) {
|
|
36
|
+
const { axis = true, legend = false, top, left, bottom, right } = options;
|
|
36
37
|
if (axis === false) {
|
|
37
38
|
return undefined;
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
};
|
|
46
|
-
}
|
|
40
|
+
return {
|
|
41
|
+
top: top ?? (axis === true || axis === 'y' ? 4 : 0),
|
|
42
|
+
left: left ?? (axis === true || axis === 'y' ? 20 : 0),
|
|
43
|
+
bottom: (bottom ?? (axis === true || axis === 'x' ? 20 : 0)) + (legend ? 32 : 0),
|
|
44
|
+
right: right ?? (axis === true || axis === 'x' ? 4 : 0),
|
|
45
|
+
};
|
|
47
46
|
}
|
|
48
47
|
/**
|
|
49
48
|
* Find the first instance within `data` with the same value as `original` using prop accessor.
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -6,8 +6,10 @@ export * from './hierarchy.js';
|
|
|
6
6
|
export * from './math.js';
|
|
7
7
|
export * from './path.js';
|
|
8
8
|
export * from './pivot.js';
|
|
9
|
+
export * from './scales.svelte.js';
|
|
9
10
|
export * from './stack.js';
|
|
10
11
|
export * from './ticks.js';
|
|
12
|
+
export * from './treemap.js';
|
|
11
13
|
export * from './threshold.js';
|
|
12
14
|
export * from './types.js';
|
|
13
15
|
export * from './graph/dagre.js';
|
package/dist/utils/index.js
CHANGED
|
@@ -6,8 +6,10 @@ export * from './hierarchy.js';
|
|
|
6
6
|
export * from './math.js';
|
|
7
7
|
export * from './path.js';
|
|
8
8
|
export * from './pivot.js';
|
|
9
|
+
export * from './scales.svelte.js';
|
|
9
10
|
export * from './stack.js';
|
|
10
11
|
export * from './ticks.js';
|
|
12
|
+
export * from './treemap.js';
|
|
11
13
|
export * from './threshold.js';
|
|
12
14
|
export * from './types.js';
|
|
13
15
|
export * from './graph/dagre.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { max, min } from 'd3-array';
|
|
1
2
|
import { accessor } from './common.js';
|
|
2
3
|
import { isScaleBand } from './scales.svelte.js';
|
|
3
|
-
import { max, min } from 'd3-array';
|
|
4
4
|
function resolveInsets(insets) {
|
|
5
5
|
const all = insets?.all ?? 0;
|
|
6
6
|
const x = insets?.x ?? all;
|
|
@@ -22,13 +22,15 @@ export function createDimensionGetter(ctx, getOptions) {
|
|
|
22
22
|
const _y = accessor(options?.y ?? ctx.y);
|
|
23
23
|
const _x1 = accessor(options?.x1 ?? ctx.x1);
|
|
24
24
|
const _y1 = accessor(options?.y1 ?? ctx.y1);
|
|
25
|
+
const hasX1 = (options?.x1 ?? ctx.config.x1) != null;
|
|
26
|
+
const hasY1 = (options?.y1 ?? ctx.config.y1) != null;
|
|
25
27
|
if (isScaleBand(ctx.yScale)) {
|
|
26
28
|
// Horizontal band
|
|
27
29
|
const y = firstValue(ctx.yScale(_y(item)) ?? 0) +
|
|
28
|
-
(ctx.y1Scale ? ctx.y1Scale(_y1(item)) : 0) +
|
|
30
|
+
(hasY1 && ctx.y1Scale ? ctx.y1Scale(_y1(item)) : 0) +
|
|
29
31
|
insets.top;
|
|
30
32
|
const height = Math.max(0, ctx.yScale.bandwidth
|
|
31
|
-
? (ctx.y1Scale ? (ctx.y1Scale.bandwidth?.() ?? 0) : ctx.yScale.bandwidth()) -
|
|
33
|
+
? (hasY1 && ctx.y1Scale ? (ctx.y1Scale.bandwidth?.() ?? 0) : ctx.yScale.bandwidth()) -
|
|
32
34
|
insets.bottom -
|
|
33
35
|
insets.top
|
|
34
36
|
: 0);
|
|
@@ -61,9 +63,11 @@ export function createDimensionGetter(ctx, getOptions) {
|
|
|
61
63
|
}
|
|
62
64
|
else if (isScaleBand(ctx.xScale)) {
|
|
63
65
|
// Vertical band or linear
|
|
64
|
-
const x = firstValue(ctx.xScale(_x(item))) +
|
|
66
|
+
const x = firstValue(ctx.xScale(_x(item))) +
|
|
67
|
+
(hasX1 && ctx.x1Scale ? ctx.x1Scale(_x1(item)) : 0) +
|
|
68
|
+
insets.left;
|
|
65
69
|
const width = Math.max(0, ctx.xScale.bandwidth
|
|
66
|
-
? (ctx.x1Scale ? (ctx.x1Scale.bandwidth?.() ?? 0) : ctx.xScale.bandwidth()) -
|
|
70
|
+
? (hasX1 && ctx.x1Scale ? (ctx.x1Scale.bandwidth?.() ?? 0) : ctx.xScale.bandwidth()) -
|
|
67
71
|
insets.left -
|
|
68
72
|
insets.right
|
|
69
73
|
: 0);
|
|
@@ -103,8 +107,10 @@ export function createDimensionGetter(ctx, getOptions) {
|
|
|
103
107
|
const xValue = _x(item);
|
|
104
108
|
const start = ctx.xInterval.floor(xValue);
|
|
105
109
|
const end = ctx.xInterval.offset(start);
|
|
106
|
-
const
|
|
107
|
-
const
|
|
110
|
+
const xStart = ctx.xScale(start);
|
|
111
|
+
const xEnd = ctx.xScale(end);
|
|
112
|
+
const x = Math.min(xStart, xEnd) + insets.left;
|
|
113
|
+
const width = Math.abs(xEnd - xStart) - insets.left - insets.right;
|
|
108
114
|
const yValue = _y(item);
|
|
109
115
|
let top = 0;
|
|
110
116
|
let bottom = 0;
|
|
@@ -137,8 +143,10 @@ export function createDimensionGetter(ctx, getOptions) {
|
|
|
137
143
|
const yValue = _y(item);
|
|
138
144
|
const start = ctx.yInterval.floor(yValue);
|
|
139
145
|
const end = ctx.yInterval.offset(start);
|
|
140
|
-
const
|
|
141
|
-
const
|
|
146
|
+
const yStart = ctx.yScale(start);
|
|
147
|
+
const yEnd = ctx.yScale(end);
|
|
148
|
+
const y = Math.min(yStart, yEnd) + insets.top;
|
|
149
|
+
const height = Math.abs(yEnd - yStart) - insets.top - insets.bottom;
|
|
142
150
|
const xValue = _x(item);
|
|
143
151
|
let left = 0;
|
|
144
152
|
let right = 0;
|
|
@@ -150,7 +150,7 @@ export function groupScaleBand(scale, flatData, groupBy, padding) {
|
|
|
150
150
|
export function tweenedScale(scale, tweenedOptions = {}) {
|
|
151
151
|
const tweenedDomain = new Tween(undefined, tweenedOptions);
|
|
152
152
|
const tweenedRange = new Tween(undefined, tweenedOptions);
|
|
153
|
-
const
|
|
153
|
+
const _tweenedScale = $derived.by(() => {
|
|
154
154
|
const scaledInstance = scale.domain ? scale : scale();
|
|
155
155
|
if (tweenedDomain.current) {
|
|
156
156
|
scaledInstance.domain(tweenedDomain.current);
|
|
@@ -162,7 +162,7 @@ export function tweenedScale(scale, tweenedOptions = {}) {
|
|
|
162
162
|
});
|
|
163
163
|
return {
|
|
164
164
|
get current() {
|
|
165
|
-
return
|
|
165
|
+
return _tweenedScale;
|
|
166
166
|
},
|
|
167
167
|
domain: (values) => tweenedDomain.set(values),
|
|
168
168
|
range: (values) => tweenedRange.set(values),
|
package/dist/utils/string.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
declare function _getStringWidth(str: string, style?: CSSStyleDeclaration): number | null;
|
|
2
|
+
export declare const getStringWidth: typeof _getStringWidth;
|
|
2
3
|
export type RasterizeTextOptions = {
|
|
3
4
|
fontSize?: string;
|
|
4
5
|
fontWeight?: number;
|
|
@@ -47,3 +48,4 @@ export type TruncateTextOptions = {
|
|
|
47
48
|
* The ellipsis can be placed at the start, middle, or end of the string.
|
|
48
49
|
*/
|
|
49
50
|
export declare function truncateText(text: string, { position, ellipsis, maxWidth, style, maxChars }: TruncateTextOptions): string;
|
|
51
|
+
export {};
|