layerchart 2.0.0-next.53 → 2.0.0-next.55

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.
Files changed (80) hide show
  1. package/dist/components/Arc.svelte +8 -7
  2. package/dist/components/Arc.svelte.test.js +1 -1
  3. package/dist/components/ArcLabel.svelte +1 -1
  4. package/dist/components/Axis.svelte +10 -2
  5. package/dist/components/Axis.svelte.d.ts +8 -2
  6. package/dist/components/Bar.svelte +10 -38
  7. package/dist/components/Circle.svelte +23 -3
  8. package/dist/components/Circle.svelte.d.ts +6 -0
  9. package/dist/components/CircleClipPath.svelte +13 -31
  10. package/dist/components/CircleClipPath.svelte.d.ts +7 -1
  11. package/dist/components/ClipPath.svelte +64 -21
  12. package/dist/components/ClipPath.svelte.d.ts +21 -12
  13. package/dist/components/Connector.svelte +18 -0
  14. package/dist/components/Connector.svelte.d.ts +5 -0
  15. package/dist/components/GeoClipPath.svelte +72 -0
  16. package/dist/components/GeoClipPath.svelte.d.ts +35 -0
  17. package/dist/components/Grid.svelte +15 -4
  18. package/dist/components/Grid.svelte.d.ts +14 -4
  19. package/dist/components/Highlight.svelte +1 -0
  20. package/dist/components/Hull.svelte +20 -2
  21. package/dist/components/Hull.svelte.d.ts +2 -2
  22. package/dist/components/Line.svelte +30 -3
  23. package/dist/components/Line.svelte.d.ts +7 -0
  24. package/dist/components/Link.svelte +9 -0
  25. package/dist/components/Pie.svelte +8 -2
  26. package/dist/components/Rect.svelte +98 -7
  27. package/dist/components/Rect.svelte.d.ts +13 -1
  28. package/dist/components/RectClipPath.svelte +11 -15
  29. package/dist/components/RectClipPath.svelte.d.ts +6 -0
  30. package/dist/components/Text.svelte +70 -16
  31. package/dist/components/Text.svelte.d.ts +10 -0
  32. package/dist/components/Tree.svelte +7 -3
  33. package/dist/components/charts/BarChart.svelte.test.js +1 -1
  34. package/dist/components/charts/DefaultTooltip.svelte.test.js +18 -18
  35. package/dist/components/charts/LineChart.svelte.test.js +1 -1
  36. package/dist/components/charts/PieChart.svelte.test.js +2 -2
  37. package/dist/components/charts/__screenshots__/BarChart.svelte.test.ts/BarChart-series-tooltip-should-use-explicit-series-colors--not-color-scale-1.png +0 -0
  38. package/dist/components/charts/__screenshots__/BarChart.svelte.test.ts/BarChart-series-tooltip-should-use-explicit-series-colors--not-color-scale-2.png +0 -0
  39. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-fade-non-highlighted-tooltip-series-items-on-hover-1.png +0 -0
  40. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-fade-non-highlighted-tooltip-series-items-on-hover-2.png +0 -0
  41. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-1.png +0 -0
  42. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-2.png +0 -0
  43. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-series-colors-in-tooltip-items-1.png +0 -0
  44. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-series-colors-in-tooltip-items-2.png +0 -0
  45. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-single-series-without-total-1.png +0 -0
  46. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-single-series-without-total-2.png +0 -0
  47. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-LineChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-1.png +0 -0
  48. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-LineChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-2.png +0 -0
  49. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-series-header-for-multi-series-1.png +0 -0
  50. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-series-header-for-multi-series-2.png +0 -0
  51. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x--y--and-r-items-when-r-is-configured-1.png +0 -0
  52. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x--y--and-r-items-when-r-is-configured-2.png +0 -0
  53. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x-and-y-items-in-tooltip-1.png +0 -0
  54. package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x-and-y-items-in-tooltip-2.png +0 -0
  55. package/dist/components/charts/__screenshots__/LineChart.svelte.test.ts/LineChart-tooltip-should-prefer-cScale-color-over-default-series-color-when-cScale-is-explicitly-provided-1.png +0 -0
  56. package/dist/components/charts/__screenshots__/LineChart.svelte.test.ts/LineChart-tooltip-should-prefer-cScale-color-over-default-series-color-when-cScale-is-explicitly-provided-2.png +0 -0
  57. package/dist/components/charts/__screenshots__/PieChart.svelte.test.ts/PieChart-uses-hovered-slice-identity-for-implicit-tooltip-series-1.png +0 -0
  58. package/dist/components/charts/__screenshots__/PieChart.svelte.test.ts/PieChart-uses-hovered-slice-identity-for-implicit-tooltip-series-2.png +0 -0
  59. package/dist/components/index.d.ts +2 -0
  60. package/dist/components/index.js +2 -0
  61. package/dist/components/tooltip/Tooltip.svelte +145 -29
  62. package/dist/components/tooltip/Tooltip.svelte.d.ts +16 -0
  63. package/dist/components/tooltip/Tooltip.svelte.test.d.ts +1 -0
  64. package/dist/components/tooltip/Tooltip.svelte.test.js +294 -0
  65. package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-portal-tooltip-to-a-custom-selector-target-1.png +0 -0
  66. package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-portal-tooltip-to-a-custom-selector-target-2.png +0 -0
  67. package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-render-tooltip-inline-when-portal-is-false-1.png +0 -0
  68. package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-render-tooltip-inline-when-portal-is-false-2.png +0 -0
  69. package/dist/utils/__screenshots__/canvas.svelte.test.ts/renderPathData-composes-element-opacity-with-inherited-globalAlpha--Group-opacity--1.png +0 -0
  70. package/dist/utils/__screenshots__/canvas.svelte.test.ts/renderPathData-composes-element-opacity-with-inherited-globalAlpha--Group-opacity--2.png +0 -0
  71. package/dist/utils/canvas.d.ts +2 -0
  72. package/dist/utils/canvas.js +13 -7
  73. package/dist/utils/canvas.svelte.test.js +55 -0
  74. package/dist/utils/connectorUtils.d.ts +13 -0
  75. package/dist/utils/connectorUtils.js +120 -1
  76. package/dist/utils/path.d.ts +19 -0
  77. package/dist/utils/path.js +72 -0
  78. package/dist/utils/rect.svelte.d.ts +18 -0
  79. package/dist/utils/rect.svelte.js +33 -0
  80. package/package.json +13 -13
@@ -0,0 +1,72 @@
1
+ <script lang="ts" module>
2
+ import type { GeoPermissibleObjects } from 'd3-geo';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ import type { ClipPathPropsWithoutHTML } from './ClipPath.svelte';
6
+ import type { GeoPathPropsWithoutHTML } from './GeoPath.svelte';
7
+ import type { Without } from '../utils/types.js';
8
+
9
+ export type BaseGeoClipPathPropsWithoutHTML = {
10
+ /**
11
+ * A unique id for the clipPath.
12
+ */
13
+ id?: string;
14
+
15
+ /**
16
+ * GeoJSON data defining the clip boundary.
17
+ */
18
+ geojson: GeoPermissibleObjects;
19
+
20
+ /**
21
+ * Whether to disable clipping (show all).
22
+ *
23
+ * @default false
24
+ */
25
+ disabled?: boolean;
26
+
27
+ /**
28
+ * Invert the clip — content renders *outside* the geojson shape.
29
+ *
30
+ * @default false
31
+ */
32
+ invert?: boolean;
33
+
34
+ /**
35
+ * The children snippet to render content inside the clipPath.
36
+ */
37
+ children?: ClipPathPropsWithoutHTML['children'];
38
+ };
39
+
40
+ export type GeoClipPathPropsWithoutHTML = BaseGeoClipPathPropsWithoutHTML &
41
+ Without<GeoPathPropsWithoutHTML, BaseGeoClipPathPropsWithoutHTML>;
42
+
43
+ export type GeoClipPathProps = GeoClipPathPropsWithoutHTML;
44
+ </script>
45
+
46
+ <script lang="ts">
47
+ import { geoPath as d3GeoPath } from 'd3-geo';
48
+
49
+ import ClipPath from './ClipPath.svelte';
50
+ import { createId } from '../utils/createId.js';
51
+ import { getGeoContext } from '../contexts/geo.js';
52
+
53
+ const uid = $props.id();
54
+
55
+ let {
56
+ id = createId('clipPath-', uid),
57
+ geojson,
58
+ disabled = false,
59
+ invert = false,
60
+ children,
61
+ }: GeoClipPathProps = $props();
62
+
63
+ const geo = getGeoContext();
64
+
65
+ // d3-geo-path emits an SVG path `d` string that Path2D and
66
+ // `clip-path: path()` also accept — single source of truth for all layers.
67
+ const path = $derived(
68
+ geo.projection && geojson ? (d3GeoPath(geo.projection)(geojson) ?? undefined) : undefined
69
+ );
70
+ </script>
71
+
72
+ <ClipPath {id} {disabled} {invert} {children} {path} />
@@ -0,0 +1,35 @@
1
+ import type { GeoPermissibleObjects } from 'd3-geo';
2
+ import type { ClipPathPropsWithoutHTML } from './ClipPath.svelte';
3
+ import type { GeoPathPropsWithoutHTML } from './GeoPath.svelte';
4
+ import type { Without } from '../utils/types.js';
5
+ export type BaseGeoClipPathPropsWithoutHTML = {
6
+ /**
7
+ * A unique id for the clipPath.
8
+ */
9
+ id?: string;
10
+ /**
11
+ * GeoJSON data defining the clip boundary.
12
+ */
13
+ geojson: GeoPermissibleObjects;
14
+ /**
15
+ * Whether to disable clipping (show all).
16
+ *
17
+ * @default false
18
+ */
19
+ disabled?: boolean;
20
+ /**
21
+ * Invert the clip — content renders *outside* the geojson shape.
22
+ *
23
+ * @default false
24
+ */
25
+ invert?: boolean;
26
+ /**
27
+ * The children snippet to render content inside the clipPath.
28
+ */
29
+ children?: ClipPathPropsWithoutHTML['children'];
30
+ };
31
+ export type GeoClipPathPropsWithoutHTML = BaseGeoClipPathPropsWithoutHTML & Without<GeoPathPropsWithoutHTML, BaseGeoClipPathPropsWithoutHTML>;
32
+ export type GeoClipPathProps = GeoClipPathPropsWithoutHTML;
33
+ declare const GeoClipPath: import("svelte").Component<GeoClipPathPropsWithoutHTML, {}, "">;
34
+ type GeoClipPath = ReturnType<typeof GeoClipPath>;
35
+ export default GeoClipPath;
@@ -3,20 +3,31 @@
3
3
  import { extractTweenConfig, type MotionProp } from '../utils/motion.svelte.js';
4
4
  import type { SVGAttributes } from 'svelte/elements';
5
5
 
6
+ /** Props forwarded onto the underlying grid line (`<Line>`, `<Circle>`, or `<Spline>`). */
7
+ type GridLineProps = Pick<SVGAttributes<SVGElement>, 'class' | 'style'> & {
8
+ stroke?: string;
9
+ strokeWidth?: number;
10
+ opacity?: number;
11
+ /** Dashed-line pattern. See `Line.dashArray`. */
12
+ dashArray?: number | number[] | string;
13
+ };
14
+
6
15
  export type GridPropsWithoutHTML<In extends Transition = Transition> = {
7
16
  /**
8
- * Draw a x-axis lines
17
+ * Draw a x-axis lines. Pass props (class, style, stroke, strokeWidth,
18
+ * opacity, dashArray) to forward onto the underlying line.
9
19
  *
10
20
  * @default false
11
21
  */
12
- x?: boolean | Pick<SVGAttributes<SVGElement>, 'class' | 'style'>;
22
+ x?: boolean | GridLineProps;
13
23
 
14
24
  /**
15
- * Draw a y-axis lines
25
+ * Draw a y-axis lines. Pass props (class, style, stroke, strokeWidth,
26
+ * opacity, dashArray) to forward onto the underlying line.
16
27
  *
17
28
  * @default false
18
29
  */
19
- y?: boolean | Pick<SVGAttributes<SVGElement>, 'class' | 'style'>;
30
+ y?: boolean | GridLineProps;
20
31
 
21
32
  /**
22
33
  * Control the number of x-axis ticks
@@ -1,19 +1,29 @@
1
1
  import type { Transition, TransitionParams, Without } from '../utils/types.js';
2
2
  import { type MotionProp } from '../utils/motion.svelte.js';
3
3
  import type { SVGAttributes } from 'svelte/elements';
4
+ /** Props forwarded onto the underlying grid line (`<Line>`, `<Circle>`, or `<Spline>`). */
5
+ type GridLineProps = Pick<SVGAttributes<SVGElement>, 'class' | 'style'> & {
6
+ stroke?: string;
7
+ strokeWidth?: number;
8
+ opacity?: number;
9
+ /** Dashed-line pattern. See `Line.dashArray`. */
10
+ dashArray?: number | number[] | string;
11
+ };
4
12
  export type GridPropsWithoutHTML<In extends Transition = Transition> = {
5
13
  /**
6
- * Draw a x-axis lines
14
+ * Draw a x-axis lines. Pass props (class, style, stroke, strokeWidth,
15
+ * opacity, dashArray) to forward onto the underlying line.
7
16
  *
8
17
  * @default false
9
18
  */
10
- x?: boolean | Pick<SVGAttributes<SVGElement>, 'class' | 'style'>;
19
+ x?: boolean | GridLineProps;
11
20
  /**
12
- * Draw a y-axis lines
21
+ * Draw a y-axis lines. Pass props (class, style, stroke, strokeWidth,
22
+ * opacity, dashArray) to forward onto the underlying line.
13
23
  *
14
24
  * @default false
15
25
  */
16
- y?: boolean | Pick<SVGAttributes<SVGElement>, 'class' | 'style'>;
26
+ y?: boolean | GridLineProps;
17
27
  /**
18
28
  * Control the number of x-axis ticks
19
29
  */
@@ -681,6 +681,7 @@
681
681
  y1={line.y1}
682
682
  x2={line.x2}
683
683
  y2={line.y2}
684
+ dashArray={[2, 2]}
684
685
  {opacity}
685
686
  {...extractLayerProps(linesProp, 'lc-highlight-line')}
686
687
  />
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" module>
2
- import type { Without } from '../utils/types.js';
2
+ import type { Without, CommonStyleProps } from '../utils/types.js';
3
3
  import type { SVGAttributes } from 'svelte/elements';
4
4
  import type { ComponentProps } from 'svelte';
5
5
 
@@ -47,7 +47,7 @@
47
47
  * @bindable
48
48
  */
49
49
  ref?: SVGGElement;
50
- };
50
+ } & CommonStyleProps;
51
51
 
52
52
  export type HullProps = HullPropsWithoutHTML & Without<GroupProps, HullPropsWithoutHTML>;
53
53
  </script>
@@ -79,6 +79,12 @@
79
79
  onpointermove,
80
80
  onclick,
81
81
  onpointerleave,
82
+ fill,
83
+ fillOpacity,
84
+ stroke,
85
+ strokeOpacity,
86
+ strokeWidth,
87
+ opacity,
82
88
  class: className,
83
89
  ref: refProp = $bindable(),
84
90
  ...restProps
@@ -112,6 +118,12 @@
112
118
  <GeoPath
113
119
  geojson={polygon}
114
120
  {curve}
121
+ {fill}
122
+ {fillOpacity}
123
+ {stroke}
124
+ {strokeOpacity}
125
+ {strokeWidth}
126
+ {opacity}
115
127
  class={['lc-hull-path', classes.path]}
116
128
  onclick={(e) => onclick?.(e, { points, polygon })}
117
129
  onpointermove={(e) => onpointermove?.(e, { points, polygon })}
@@ -125,6 +137,12 @@
125
137
  x={(d) => d[0]}
126
138
  y={(d) => d[1]}
127
139
  {curve}
140
+ {fill}
141
+ {fillOpacity}
142
+ {stroke}
143
+ {strokeOpacity}
144
+ {strokeWidth}
145
+ {opacity}
128
146
  class={['lc-hull-class', classes.path]}
129
147
  onclick={(e) => onclick?.(e, { points, polygon })}
130
148
  onpointermove={(e) => onpointermove?.(e, { points, polygon })}
@@ -1,4 +1,4 @@
1
- import type { Without } from '../utils/types.js';
1
+ import type { Without, CommonStyleProps } from '../utils/types.js';
2
2
  import type { ComponentProps } from 'svelte';
3
3
  export type HullPropsWithoutHTML = {
4
4
  /**
@@ -32,7 +32,7 @@ export type HullPropsWithoutHTML = {
32
32
  * @bindable
33
33
  */
34
34
  ref?: SVGGElement;
35
- };
35
+ } & CommonStyleProps;
36
36
  export type HullProps = HullPropsWithoutHTML & Without<GroupProps, HullPropsWithoutHTML>;
37
37
  import { Delaunay } from 'd3-delaunay';
38
38
  import { type GroupProps } from './Group.svelte';
@@ -111,6 +111,14 @@
111
111
 
112
112
  /** Motion configuration (pixel mode only). */
113
113
  motion?: MotionProp;
114
+
115
+ /**
116
+ * Dashed-line pattern. Accepts a number (single dash length), a
117
+ * `[dash, gap, ...]` array, or a string (same syntax as SVG
118
+ * `stroke-dasharray`). Works across `<Svg>`, `<Canvas>`, and `<Html>`
119
+ * layers — HTML approximates the pattern via `repeating-linear-gradient`.
120
+ */
121
+ dashArray?: number | number[] | string;
114
122
  } & DataDrivenStyleProps;
115
123
 
116
124
  export type LineProps = LinePropsWithoutHTML &
@@ -137,6 +145,7 @@
137
145
 
138
146
  import { createKey } from '../utils/key.svelte.js';
139
147
  import { createId } from '../utils/createId.js';
148
+ import { parseDashArray, dashArrayToGradient } from '../utils/path.js';
140
149
 
141
150
  const uid = $props.id();
142
151
 
@@ -162,9 +171,13 @@
162
171
  markerMid,
163
172
  motion,
164
173
  fillOpacity,
174
+ dashArray,
165
175
  ...restProps
166
176
  }: LineProps = $props();
167
177
 
178
+ const dashArrayResolved = $derived(parseDashArray(dashArray));
179
+ const dashArrayAttr = $derived(dashArrayResolved ? dashArrayResolved.join(' ') : undefined);
180
+
168
181
  // Data mode detection
169
182
  const dataMode = $derived(hasAnyDataProp(x1, y1, x2, y2));
170
183
 
@@ -285,7 +298,12 @@
285
298
  'lc-line',
286
299
  itemClass ?? (typeof className === 'string' ? className : undefined)
287
300
  ),
288
- style: restProps.style as string | undefined,
301
+ style: [
302
+ restProps.style as string | undefined,
303
+ dashArrayAttr ? `stroke-dasharray: ${dashArrayAttr}` : undefined,
304
+ ]
305
+ .filter(Boolean)
306
+ .join('; ') || undefined,
289
307
  };
290
308
  }
291
309
 
@@ -358,6 +376,7 @@
358
376
  opacity,
359
377
  className,
360
378
  restProps.style,
379
+ dashArrayAttr,
361
380
  ],
362
381
  }
363
382
  : undefined,
@@ -390,6 +409,7 @@
390
409
  marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
391
410
  marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
392
411
  marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
412
+ stroke-dasharray={dashArrayAttr}
393
413
  class={cls('lc-line', resolvedClass)}
394
414
  {...restProps}
395
415
  />
@@ -408,6 +428,7 @@
408
428
  marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
409
429
  marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
410
430
  marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
431
+ stroke-dasharray={dashArrayAttr}
411
432
  class={cls('lc-line', staticClassName)}
412
433
  {...restProps}
413
434
  />
@@ -435,7 +456,10 @@
435
456
  style:transform="translateY(-50%) rotate({angle}deg)"
436
457
  style:transform-origin="0 50%"
437
458
  style:opacity={resolvedOpacity}
438
- style:background-color={resolvedStroke}
459
+ style:background={dashArrayResolved
460
+ ? dashArrayToGradient(dashArrayResolved, resolvedStroke ?? 'var(--stroke-color)')
461
+ : undefined}
462
+ style:background-color={dashArrayResolved ? undefined : resolvedStroke}
439
463
  class={cls('lc-line', resolvedClass)}
440
464
  style={restProps.style}
441
465
  ></div>
@@ -455,7 +479,10 @@
455
479
  style:transform="translateY(-50%) rotate({angle}deg)"
456
480
  style:transform-origin="0 50%"
457
481
  style:opacity={staticOpacity}
458
- style:background-color={staticStroke}
482
+ style:background={dashArrayResolved
483
+ ? dashArrayToGradient(dashArrayResolved, staticStroke ?? 'var(--stroke-color)')
484
+ : undefined}
485
+ style:background-color={dashArrayResolved ? undefined : staticStroke}
459
486
  class={cls('lc-line', staticClassName)}
460
487
  style={restProps.style}
461
488
  ></div>
@@ -93,6 +93,13 @@ export type LinePropsWithoutHTML = {
93
93
  markerEnd?: MarkerOptions;
94
94
  /** Motion configuration (pixel mode only). */
95
95
  motion?: MotionProp;
96
+ /**
97
+ * Dashed-line pattern. Accepts a number (single dash length), a
98
+ * `[dash, gap, ...]` array, or a string (same syntax as SVG
99
+ * `stroke-dasharray`). Works across `<Svg>`, `<Canvas>`, and `<Html>`
100
+ * layers — HTML approximates the pattern via `repeating-linear-gradient`.
101
+ */
102
+ dashArray?: number | number[] | string;
96
103
  } & DataDrivenStyleProps;
97
104
  export type LineProps = LinePropsWithoutHTML & Without<SVGAttributes<SVGPathElement>, LinePropsWithoutHTML>;
98
105
  declare const Line: import("svelte").Component<LineProps, {}, "">;
@@ -82,6 +82,9 @@ TODO:
82
82
  */
83
83
  import Connector, { type ConnectorProps } from './Connector.svelte';
84
84
  import { extractLayerProps } from '../utils/attributes.js';
85
+ import { getChartContext } from '../contexts/chart.js';
86
+
87
+ const ctx = getChartContext();
85
88
 
86
89
  let {
87
90
  data,
@@ -95,6 +98,7 @@ TODO:
95
98
  explicitCoords,
96
99
  type = 'd3',
97
100
  sweep = 'none',
101
+ radius = 20,
98
102
  ...restProps
99
103
  }: LinkProps = $props();
100
104
 
@@ -125,12 +129,14 @@ TODO:
125
129
  const xAccessor = $derived.by(() => {
126
130
  if (xProp) return xProp;
127
131
  if (sankey) return (d: any) => (d.isSource ? d.node.x1 : d.node.x0);
132
+ if (ctx.radial) return (d: any) => d.x;
128
133
  return (d: any) => (orientation === 'horizontal' ? d.y : d.x);
129
134
  });
130
135
 
131
136
  const yAccessor = $derived.by(() => {
132
137
  if (yProp) return yProp;
133
138
  if (sankey) return (d: any) => d.y;
139
+ if (ctx.radial) return (d: any) => d.y;
134
140
  return (d: any) => (orientation === 'horizontal' ? d.x : d.y);
135
141
  });
136
142
 
@@ -165,6 +171,7 @@ TODO:
165
171
  return FALLBACK_COORDS;
166
172
  }
167
173
  });
174
+
168
175
  </script>
169
176
 
170
177
  <Connector
@@ -173,5 +180,7 @@ TODO:
173
180
  {type}
174
181
  {curve}
175
182
  {sweep}
183
+ {radius}
184
+ radial={ctx.radial}
176
185
  {...extractLayerProps(restProps, 'lc-link')}
177
186
  />
@@ -108,7 +108,10 @@
108
108
  const ctx = getChartContext();
109
109
 
110
110
  const endAngle = $derived(
111
- endAngleProp ?? degreesToRadians(ctx.config.xRange ? max(ctx.xRange) : max(range))
111
+ endAngleProp ??
112
+ degreesToRadians(
113
+ (ctx.config.xRange ? max(ctx.config.xRange as number[]) : max(range))!
114
+ )
112
115
  );
113
116
 
114
117
  const motionEndAngle = createMotion(0, () => endAngle, motion);
@@ -116,7 +119,10 @@
116
119
  const pie = $derived.by(() => {
117
120
  let _pie = d3pie<any>()
118
121
  .startAngle(
119
- startAngleProp ?? degreesToRadians(ctx.config.xRange ? min(ctx.xRange) : min(range))
122
+ startAngleProp ??
123
+ degreesToRadians(
124
+ (ctx.config.xRange ? min(ctx.config.xRange as number[]) : min(range))!
125
+ )
120
126
  )
121
127
  .endAngle(motionEndAngle.current)
122
128
  .padAngle(padAngle)
@@ -5,7 +5,13 @@
5
5
  import { createMotion, parseMotionProp, type MotionProp } from '../utils/motion.svelte.js';
6
6
  import { renderRect, type ComputedStylesOptions } from '../utils/canvas.js';
7
7
  import type { DataProp, DataDrivenStyleProps } from '../utils/dataProp.js';
8
- import type { Insets } from '../utils/rect.svelte.js';
8
+ import {
9
+ resolveCorners,
10
+ cornersUniform,
11
+ type Corners,
12
+ type Insets,
13
+ } from '../utils/rect.svelte.js';
14
+ import { roundedRectPath, parseDashArray } from '../utils/path.js';
9
15
 
10
16
  export type RectPropsWithoutHTML = {
11
17
  /**
@@ -119,6 +125,20 @@
119
125
  /** Motion configuration (pixel mode only). */
120
126
  motion?: MotionProp<'x' | 'y' | 'width' | 'height'>;
121
127
 
128
+ /**
129
+ * Dashed-border pattern. Accepts a number (single dash length), a
130
+ * `[dash, gap, ...]` array, or a string (same syntax as SVG
131
+ * `stroke-dasharray`). HTML layer approximates via `border-style: dashed`.
132
+ */
133
+ dashArray?: number | number[] | string;
134
+
135
+ /**
136
+ * Per-corner radii. Accepts a number (all corners equal — same as `rx`),
137
+ * a `[tl, tr, br, bl]` tuple, or `{ topLeft, topRight, bottomRight, bottomLeft }`.
138
+ * Takes precedence over `rx`/`ry` when corners differ.
139
+ */
140
+ corners?: Corners;
141
+
122
142
  /** Children content to render. Note: Only works for Html layers */
123
143
  children?: Snippet;
124
144
  } & DataDrivenStyleProps;
@@ -175,6 +195,8 @@
175
195
  key: keyFn = (_: any, i: number) => i,
176
196
  ref: refProp = $bindable(),
177
197
  motion,
198
+ corners,
199
+ dashArray,
178
200
  class: className,
179
201
  onclick,
180
202
  ondblclick,
@@ -279,10 +301,26 @@
279
301
  });
280
302
  });
281
303
 
304
+ // Fold a uniform `corners` value into rx/ry so SVG `<rect>` renders rounded
305
+ // corners without needing a `<path>`. When corners are per-corner different,
306
+ // `pixelPathData` kicks in below and SVG emits a `<path>` instead.
307
+ const dashArrayResolved = $derived(parseDashArray(dashArray));
308
+ const dashArrayAttr = $derived(dashArrayResolved ? dashArrayResolved.join(' ') : undefined);
309
+
310
+ const cornersUniformValue = $derived.by(() => {
311
+ if (corners === undefined) return undefined;
312
+ if (typeof corners === 'number') return corners;
313
+ const resolved = resolveCorners(corners, Infinity, Infinity);
314
+ return cornersUniform(resolved) ? resolved[0] : undefined;
315
+ });
316
+ const cornersNonUniform = $derived(
317
+ corners !== undefined && cornersUniformValue === undefined
318
+ );
319
+
282
320
  // Normalize rx/ry - if only one is provided, use it for both (SVG behavior)
283
321
  // Coerce to number for canvas rendering (SVG allows string like "50%")
284
- const rx = $derived(Number(rxProp ?? ryProp) || 0);
285
- const ry = $derived(Number(ryProp ?? rxProp) || 0);
322
+ const rx = $derived(Number(rxProp ?? ryProp ?? cornersUniformValue) || 0);
323
+ const ry = $derived(Number(ryProp ?? rxProp ?? cornersUniformValue) || 0);
286
324
 
287
325
  // --- Pixel mode ---
288
326
  let ref = $state<SVGRectElement>();
@@ -335,6 +373,27 @@
335
373
  );
336
374
  const htmlRestProps = $derived(restProps as unknown as HTMLAttributes<HTMLDivElement>);
337
375
 
376
+ // Resolved per-corner radii for the static (pixel-mode) rect, clamped to bounds.
377
+ const resolvedCorners = $derived(
378
+ corners !== undefined
379
+ ? resolveCorners(corners, motionWidth.current, motionHeight.current)
380
+ : undefined
381
+ );
382
+ const borderRadiusStyle = $derived(
383
+ resolvedCorners ? resolvedCorners.map((c) => `${c}px`).join(' ') : undefined
384
+ );
385
+ const pixelPathData = $derived(
386
+ resolvedCorners && cornersNonUniform
387
+ ? roundedRectPath(
388
+ motionX.current,
389
+ motionY.current,
390
+ motionWidth.current,
391
+ motionHeight.current,
392
+ resolvedCorners
393
+ )
394
+ : undefined
395
+ );
396
+
338
397
  function getStyleOptions(
339
398
  styleOverrides: ComputedStylesOptions | undefined,
340
399
  itemFill?: string | undefined,
@@ -371,7 +430,12 @@
371
430
  'lc-rect',
372
431
  itemClass ?? (typeof className === 'string' ? className : undefined)
373
432
  ),
374
- style: restProps.style as string | undefined,
433
+ style: [
434
+ restProps.style as string | undefined,
435
+ dashArrayAttr ? `stroke-dasharray: ${dashArrayAttr}` : undefined,
436
+ ]
437
+ .filter(Boolean)
438
+ .join('; ') || undefined,
375
439
  };
376
440
  }
377
441
 
@@ -422,6 +486,7 @@
422
486
  height: motionHeight.current,
423
487
  rx,
424
488
  ry,
489
+ corners: resolvedCorners,
425
490
  },
426
491
  styleOpts
427
492
  );
@@ -475,6 +540,8 @@
475
540
  restProps.style,
476
541
  rx,
477
542
  ry,
543
+ resolvedCorners,
544
+ dashArrayAttr,
478
545
  ],
479
546
  }
480
547
  : undefined,
@@ -504,6 +571,7 @@
504
571
  opacity={resolvedOpacity}
505
572
  {rx}
506
573
  {ry}
574
+ stroke-dasharray={dashArrayAttr}
507
575
  class={cls('lc-rect', resolvedClass)}
508
576
  {...restProps}
509
577
  {onclick}
@@ -515,6 +583,28 @@
515
583
  {onpointerout}
516
584
  />
517
585
  {/each}
586
+ {:else if pixelPathData}
587
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
588
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
589
+ <path
590
+ d={pixelPathData}
591
+ fill={staticFill}
592
+ fill-opacity={staticFillOpacity}
593
+ stroke={staticStroke}
594
+ stroke-opacity={staticStrokeOpacity}
595
+ stroke-width={staticStrokeWidth}
596
+ opacity={staticOpacity}
597
+ stroke-dasharray={dashArrayAttr}
598
+ class={cls('lc-rect', staticClassName)}
599
+ {...(restProps as unknown as SVGAttributes<SVGPathElement>)}
600
+ {onclick}
601
+ {ondblclick}
602
+ {onpointerenter}
603
+ {onpointermove}
604
+ {onpointerleave}
605
+ {onpointerover}
606
+ {onpointerout}
607
+ />
518
608
  {:else}
519
609
  <rect
520
610
  x={motionX.current}
@@ -529,6 +619,7 @@
529
619
  opacity={staticOpacity}
530
620
  {rx}
531
621
  {ry}
622
+ stroke-dasharray={dashArrayAttr}
532
623
  class={cls('lc-rect', staticClassName)}
533
624
  {...restProps}
534
625
  {onclick}
@@ -561,7 +652,7 @@
561
652
  style:background={resolvedFill}
562
653
  style:opacity={resolvedOpacity}
563
654
  style:border-width="{resolvedStrokeWidth}px"
564
- style:border-style="solid"
655
+ style:border-style={dashArrayResolved ? 'dashed' : 'solid'}
565
656
  style:border-color={resolvedStroke}
566
657
  style:border-radius="{rx}px"
567
658
  class={cls('lc-rect', resolvedClass)}
@@ -587,9 +678,9 @@
587
678
  style:background={staticFill}
588
679
  style:opacity={staticOpacity}
589
680
  style:border-width={staticBorderWidth}
590
- style:border-style="solid"
681
+ style:border-style={dashArrayResolved ? 'dashed' : 'solid'}
591
682
  style:border-color={staticStroke}
592
- style:border-radius="{rx}px"
683
+ style:border-radius={borderRadiusStyle ?? `${rx}px`}
593
684
  class={cls('lc-rect', staticClassName)}
594
685
  {...htmlRestProps}
595
686
  {onclick}
@@ -3,7 +3,7 @@ import type { SVGAttributes } from 'svelte/elements';
3
3
  import type { CommonEvents, Without } from '../utils/types.js';
4
4
  import { type MotionProp } from '../utils/motion.svelte.js';
5
5
  import type { DataProp, DataDrivenStyleProps } from '../utils/dataProp.js';
6
- import type { Insets } from '../utils/rect.svelte.js';
6
+ import { type Corners, type Insets } from '../utils/rect.svelte.js';
7
7
  export type RectPropsWithoutHTML = {
8
8
  /**
9
9
  * The x position of the rectangle.
@@ -101,6 +101,18 @@ export type RectPropsWithoutHTML = {
101
101
  ref?: SVGRectElement;
102
102
  /** Motion configuration (pixel mode only). */
103
103
  motion?: MotionProp<'x' | 'y' | 'width' | 'height'>;
104
+ /**
105
+ * Dashed-border pattern. Accepts a number (single dash length), a
106
+ * `[dash, gap, ...]` array, or a string (same syntax as SVG
107
+ * `stroke-dasharray`). HTML layer approximates via `border-style: dashed`.
108
+ */
109
+ dashArray?: number | number[] | string;
110
+ /**
111
+ * Per-corner radii. Accepts a number (all corners equal — same as `rx`),
112
+ * a `[tl, tr, br, bl]` tuple, or `{ topLeft, topRight, bottomRight, bottomLeft }`.
113
+ * Takes precedence over `rx`/`ry` when corners differ.
114
+ */
115
+ corners?: Corners;
104
116
  /** Children content to render. Note: Only works for Html layers */
105
117
  children?: Snippet;
106
118
  } & DataDrivenStyleProps;