layerchart 2.0.0-next.3 → 2.0.0-next.30

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 (108) hide show
  1. package/dist/components/AnnotationPoint.svelte +16 -9
  2. package/dist/components/AnnotationRange.svelte +3 -3
  3. package/dist/components/Arc.svelte +2 -2
  4. package/dist/components/Axis.svelte +63 -14
  5. package/dist/components/Axis.svelte.d.ts +12 -2
  6. package/dist/components/Blur.svelte +5 -3
  7. package/dist/components/Blur.svelte.d.ts +2 -5
  8. package/dist/components/BrushContext.svelte +1 -1
  9. package/dist/components/Calendar.svelte +10 -6
  10. package/dist/components/Calendar.svelte.d.ts +2 -1
  11. package/dist/components/Chart.svelte +2 -2
  12. package/dist/components/Connector.svelte +2 -2
  13. package/dist/components/Connector.svelte.d.ts +1 -1
  14. package/dist/components/Ellipse.svelte +187 -0
  15. package/dist/components/Ellipse.svelte.d.ts +64 -0
  16. package/dist/components/ForceSimulation.svelte +168 -50
  17. package/dist/components/ForceSimulation.svelte.d.ts +80 -21
  18. package/dist/components/GeoPath.svelte +12 -5
  19. package/dist/components/GeoPoint.svelte +1 -2
  20. package/dist/components/GeoSpline.svelte +4 -4
  21. package/dist/components/GeoSpline.svelte.d.ts +1 -1
  22. package/dist/components/Group.svelte +2 -2
  23. package/dist/components/Highlight.svelte +2 -2
  24. package/dist/components/Hull.svelte +1 -1
  25. package/dist/components/Labels.svelte +3 -2
  26. package/dist/components/Labels.svelte.d.ts +2 -2
  27. package/dist/components/Legend.svelte +19 -12
  28. package/dist/components/Legend.svelte.d.ts +5 -5
  29. package/dist/components/MonthPath.svelte +14 -11
  30. package/dist/components/MonthPath.svelte.d.ts +4 -3
  31. package/dist/components/Polygon.svelte +285 -0
  32. package/dist/components/Polygon.svelte.d.ts +115 -0
  33. package/dist/components/RadialGradient.svelte +1 -3
  34. package/dist/components/Spline.svelte +30 -18
  35. package/dist/components/Spline.svelte.d.ts +12 -4
  36. package/dist/components/Text.svelte +62 -60
  37. package/dist/components/Text.svelte.d.ts +6 -0
  38. package/dist/components/TransformControls.svelte +16 -20
  39. package/dist/components/Treemap.svelte +63 -26
  40. package/dist/components/Treemap.svelte.d.ts +11 -11
  41. package/dist/components/Voronoi.svelte +51 -33
  42. package/dist/components/Voronoi.svelte.d.ts +3 -1
  43. package/dist/components/charts/ArcChart.svelte +5 -3
  44. package/dist/components/charts/AreaChart.svelte +11 -11
  45. package/dist/components/charts/BarChart.svelte +64 -53
  46. package/dist/components/charts/DefaultTooltip.svelte +1 -1
  47. package/dist/components/charts/LineChart.svelte +10 -6
  48. package/dist/components/charts/PieChart.svelte +5 -3
  49. package/dist/components/charts/ScatterChart.svelte +2 -3
  50. package/dist/components/charts/utils.svelte.d.ts +2 -2
  51. package/dist/components/charts/utils.svelte.js +5 -1
  52. package/dist/components/index.d.ts +4 -0
  53. package/dist/components/index.js +5 -1
  54. package/dist/components/layout/Canvas.svelte +67 -49
  55. package/dist/components/layout/Canvas.svelte.d.ts +6 -0
  56. package/dist/components/layout/Layer.svelte +6 -4
  57. package/dist/components/layout/Layer.svelte.d.ts +6 -4
  58. package/dist/components/tooltip/Tooltip.svelte +14 -7
  59. package/dist/components/tooltip/TooltipContext.svelte +78 -34
  60. package/dist/components/tooltip/TooltipContext.svelte.d.ts +3 -3
  61. package/dist/components/tooltip/TooltipHeader.svelte +5 -4
  62. package/dist/components/tooltip/TooltipHeader.svelte.d.ts +3 -3
  63. package/dist/components/tooltip/TooltipItem.svelte +5 -4
  64. package/dist/components/tooltip/TooltipItem.svelte.d.ts +3 -3
  65. package/dist/components/tooltip/TooltipList.svelte +1 -1
  66. package/dist/components/tooltip/tooltipMetaContext.d.ts +2 -2
  67. package/dist/docs/Blockquote.svelte +6 -4
  68. package/dist/docs/Blockquote.svelte.d.ts +4 -19
  69. package/dist/docs/Code.svelte +20 -12
  70. package/dist/docs/Code.svelte.d.ts +9 -23
  71. package/dist/docs/Header1.svelte +4 -2
  72. package/dist/docs/Header1.svelte.d.ts +4 -28
  73. package/dist/docs/Json.svelte +11 -3
  74. package/dist/docs/Json.svelte.d.ts +9 -21
  75. package/dist/docs/Layout.svelte +10 -7
  76. package/dist/docs/Layout.svelte.d.ts +4 -19
  77. package/dist/docs/Link.svelte +7 -3
  78. package/dist/docs/Link.svelte.d.ts +4 -38
  79. package/dist/docs/Preview.svelte +6 -3
  80. package/dist/docs/TilesetField.svelte +20 -19
  81. package/dist/docs/TilesetField.svelte.d.ts +5 -22
  82. package/dist/docs/ViewSourceButton.svelte +9 -6
  83. package/dist/docs/ViewSourceButton.svelte.d.ts +7 -21
  84. package/dist/utils/arcText.svelte.js +4 -4
  85. package/dist/utils/array.d.ts +11 -0
  86. package/dist/utils/array.js +23 -0
  87. package/dist/utils/array.test.d.ts +1 -0
  88. package/dist/utils/array.test.js +200 -0
  89. package/dist/utils/canvas.d.ts +77 -0
  90. package/dist/utils/canvas.js +105 -41
  91. package/dist/utils/genData.d.ts +14 -0
  92. package/dist/utils/genData.js +24 -6
  93. package/dist/utils/index.d.ts +1 -0
  94. package/dist/utils/index.js +1 -0
  95. package/dist/utils/path.d.ts +10 -0
  96. package/dist/utils/path.js +30 -0
  97. package/dist/utils/scales.svelte.d.ts +3 -2
  98. package/dist/utils/scales.svelte.js +7 -3
  99. package/dist/utils/shape.d.ts +43 -0
  100. package/dist/utils/shape.js +59 -0
  101. package/dist/utils/string.d.ts +49 -0
  102. package/dist/utils/string.js +4 -2
  103. package/dist/utils/ticks.d.ts +15 -4
  104. package/dist/utils/ticks.js +140 -159
  105. package/dist/utils/ticks.test.js +6 -16
  106. package/dist/utils/treemap.d.ts +1 -1
  107. package/package.json +27 -25
  108. package/dist/utils/object.js +0 -2
@@ -10,47 +10,47 @@ export type TreemapProps<T> = {
10
10
  *
11
11
  * @default 0
12
12
  */
13
- padding?: number;
13
+ padding?: number | ((node: HierarchyRectangularNode<T>) => number);
14
14
  /**
15
15
  * The inner padding between nodes.
16
16
  *
17
17
  * @default 0
18
18
  */
19
- paddingInner?: number;
19
+ paddingInner?: number | ((node: HierarchyRectangularNode<T>) => number);
20
20
  /**
21
21
  * The outer padding between nodes.
22
22
  *
23
23
  * @default 0
24
24
  */
25
- paddingOuter?: number;
25
+ paddingOuter?: number | ((node: HierarchyRectangularNode<T>) => number);
26
26
  /**
27
27
  * The top padding between nodes.
28
28
  *
29
29
  * @default 0
30
30
  */
31
- paddingTop?: number;
31
+ paddingTop?: number | ((node: HierarchyRectangularNode<T>) => number);
32
32
  /**
33
33
  * The bottom padding between nodes.
34
34
  *
35
35
  * @default 0
36
36
  */
37
- paddingBottom?: number;
37
+ paddingBottom?: number | ((node: HierarchyRectangularNode<T>) => number);
38
38
  /**
39
39
  * The left padding between nodes.
40
40
  *
41
41
  */
42
- paddingLeft?: number;
42
+ paddingLeft?: number | ((node: HierarchyRectangularNode<T>) => number);
43
43
  /**
44
44
  * The right padding between nodes.
45
45
  *
46
46
  */
47
- paddingRight?: number;
47
+ paddingRight?: number | ((node: HierarchyRectangularNode<T>) => number);
48
48
  /**
49
- * The selected node.
49
+ * Modify tiling function for approapriate aspect ratio when treemap is zoomed in
50
50
  *
51
- * @default null
51
+ * @default false
52
52
  */
53
- selected?: HierarchyRectangularNode<T> | null;
53
+ maintainAspectRatio?: boolean;
54
54
  hierarchy?: HierarchyNode<T>;
55
55
  children?: Snippet<[{
56
56
  nodes: HierarchyRectangularNode<T>[];
@@ -62,7 +62,7 @@ declare class __sveltets_Render<T> {
62
62
  props(): TreemapProps<T>;
63
63
  events(): {};
64
64
  slots(): {};
65
- bindings(): "selected";
65
+ bindings(): "";
66
66
  exports(): {};
67
67
  }
68
68
  interface $$IsomorphicComponent {
@@ -1,6 +1,5 @@
1
1
  <script lang="ts" module>
2
2
  import type { Without } from '../utils/types.js';
3
- import type { SVGAttributes } from 'svelte/elements';
4
3
 
5
4
  export type VoronoiPropsWithoutHTML = {
6
5
  /**
@@ -8,6 +7,9 @@
8
7
  */
9
8
  data?: any;
10
9
 
10
+ /** Radius to clip voronoi cells. `0` or `undefined` to disables clipping */
11
+ r?: number;
12
+
11
13
  /**
12
14
  * Classes to apply to the root and path elements
13
15
  *
@@ -56,7 +58,7 @@
56
58
  <script lang="ts">
57
59
  import { min } from 'd3-array';
58
60
  import { Delaunay } from 'd3-delaunay';
59
- import type { GeoPermissibleObjects } from 'd3-geo';
61
+ import { type GeoPermissibleObjects } from 'd3-geo';
60
62
  // @ts-expect-error
61
63
  import { geoVoronoi } from 'd3-geo-voronoi';
62
64
  import { pointRadial } from 'd3-shape';
@@ -67,10 +69,13 @@
67
69
  import Spline from './Spline.svelte';
68
70
  import { getChartContext } from './Chart.svelte';
69
71
  import { getGeoContext } from './GeoContext.svelte';
72
+ import CircleClipPath from './CircleClipPath.svelte';
73
+
70
74
  import { layerClass } from '../utils/attributes.js';
71
75
 
72
76
  let {
73
77
  data,
78
+ r,
74
79
  classes = {},
75
80
  onclick,
76
81
  onpointerenter,
@@ -109,53 +114,66 @@
109
114
  // Width and/or height can sometimes be negative (when loading data remotely and updately)
110
115
  const boundWidth = $derived(Math.max(ctx.width, 0));
111
116
  const boundHeight = $derived(Math.max(ctx.height, 0));
117
+
118
+ const disableClip = $derived(r === 0 || r == null || r === Infinity);
112
119
  </script>
113
120
 
114
121
  <Group {...restProps} class={cls(layerClass('voronoi-g'), classes.root, className)}>
115
122
  {#if geo.projection}
116
123
  {@const polygons = geoVoronoi().polygons(points)}
117
124
  {#each polygons.features as feature}
118
- <GeoPath
119
- geojson={feature}
120
- class={cls(
121
- layerClass('voronoi-geo-path'),
122
- 'fill-transparent stroke-transparent',
123
- classes.path
124
- )}
125
- onclick={(e) => onclick?.(e, { data: feature.properties.site.data, feature })}
126
- onpointerenter={(e) => onpointerenter?.(e, { data: feature.properties.site.data, feature })}
127
- onpointermove={(e) => onpointermove?.(e, { data: feature.properties.site.data, feature })}
128
- onpointerdown={(e) => onpointerdown?.(e, { data: feature.properties.site.data, feature })}
129
- {onpointerleave}
130
- ontouchmove={(e) => {
131
- // Prevent touch to not interfere with pointer
132
- e.preventDefault();
133
- }}
134
- />
135
- {/each}
136
- {:else}
137
- {@const voronoi = Delaunay.from(points).voronoi([0, 0, boundWidth, boundHeight])}
138
- {#each points as point, i}
139
- {@const pathData = voronoi.renderCell(i)}
140
- <!-- Wait to render Spline until pathData is available to fix path artifacts from injected tweened points in Spline -->
141
- {#if pathData}
142
- <Spline
143
- {pathData}
125
+ {@const point = r ? geo.projection?.(feature.properties.sitecoordinates) : null}
126
+ <CircleClipPath
127
+ cx={point?.[0]}
128
+ cy={point?.[1]}
129
+ r={r ?? 0}
130
+ disabled={point == null || disableClip}
131
+ >
132
+ <GeoPath
133
+ geojson={feature}
144
134
  class={cls(
145
- layerClass('voronoi-path'),
135
+ layerClass('voronoi-geo-path'),
146
136
  'fill-transparent stroke-transparent',
147
137
  classes.path
148
138
  )}
149
- onclick={(e) => onclick?.(e, { data: point.data, point })}
150
- onpointerenter={(e) => onpointerenter?.(e, { data: point.data, point })}
151
- onpointermove={(e) => onpointermove?.(e, { data: point.data, point })}
139
+ onclick={(e) => onclick?.(e, { data: feature.properties.site.data, feature })}
140
+ onpointerenter={(e) =>
141
+ onpointerenter?.(e, { data: feature.properties.site.data, feature })}
142
+ onpointermove={(e) => onpointermove?.(e, { data: feature.properties.site.data, feature })}
143
+ onpointerdown={(e) => onpointerdown?.(e, { data: feature.properties.site.data, feature })}
152
144
  {onpointerleave}
153
- onpointerdown={(e) => onpointerdown?.(e, { data: point.data, point })}
154
145
  ontouchmove={(e) => {
155
146
  // Prevent touch to not interfere with pointer
156
147
  e.preventDefault();
157
148
  }}
158
149
  />
150
+ </CircleClipPath>
151
+ {/each}
152
+ {:else}
153
+ {@const voronoi = Delaunay.from(points).voronoi([0, 0, boundWidth, boundHeight])}
154
+ {#each points as point, i}
155
+ {@const pathData = voronoi.renderCell(i)}
156
+ <!-- Wait to render Spline until pathData is available to fix path artifacts from injected tweened points in Spline -->
157
+ {#if pathData}
158
+ <CircleClipPath cx={point[0]} cy={point[1]} r={r ?? 0} disabled={disableClip}>
159
+ <Spline
160
+ {pathData}
161
+ class={cls(
162
+ layerClass('voronoi-path'),
163
+ 'fill-transparent stroke-transparent',
164
+ classes.path
165
+ )}
166
+ onclick={(e) => onclick?.(e, { data: point.data, point })}
167
+ onpointerenter={(e) => onpointerenter?.(e, { data: point.data, point })}
168
+ onpointermove={(e) => onpointermove?.(e, { data: point.data, point })}
169
+ {onpointerleave}
170
+ onpointerdown={(e) => onpointerdown?.(e, { data: point.data, point })}
171
+ ontouchmove={(e) => {
172
+ // Prevent touch to not interfere with pointer
173
+ e.preventDefault();
174
+ }}
175
+ />
176
+ </CircleClipPath>
159
177
  {/if}
160
178
  {/each}
161
179
  {/if}
@@ -4,6 +4,8 @@ export type VoronoiPropsWithoutHTML = {
4
4
  * Override data instead of using context
5
5
  */
6
6
  data?: any;
7
+ /** Radius to clip voronoi cells. `0` or `undefined` to disables clipping */
8
+ r?: number;
7
9
  /**
8
10
  * Classes to apply to the root and path elements
9
11
  *
@@ -35,7 +37,7 @@ export type VoronoiPropsWithoutHTML = {
35
37
  }) => void;
36
38
  };
37
39
  export type VoronoiProps = VoronoiPropsWithoutHTML & Without<Omit<GroupProps, 'children'>, VoronoiPropsWithoutHTML>;
38
- import type { GeoPermissibleObjects } from 'd3-geo';
40
+ import { type GeoPermissibleObjects } from 'd3-geo';
39
41
  import { type GroupProps } from './Group.svelte';
40
42
  declare const Voronoi: import("svelte").Component<VoronoiProps, {}, "">;
41
43
  type Voronoi = ReturnType<typeof Voronoi>;
@@ -264,8 +264,8 @@
264
264
  placement: 'bottom',
265
265
  variant: 'swatches',
266
266
  onclick: (e, item) => {
267
- selectedKeys.toggleSelected(item.value);
268
- selectedSeries.toggleSelected(item.value);
267
+ selectedKeys.toggle(item.value);
268
+ selectedSeries.toggle(item.value);
269
269
  },
270
270
  onpointerenter: (e, item) => (highlightKey.current = item.value),
271
271
  onpointerleave: (e) => (highlightKey.current = null),
@@ -384,7 +384,9 @@
384
384
  ]}
385
385
  padding={{ bottom: legend === true ? 32 : 0 }}
386
386
  {...restProps}
387
- tooltip={tooltip === false ? false : props.tooltip?.context}
387
+ tooltip={tooltip === false
388
+ ? false
389
+ : { ...props.tooltip?.context, ...(typeof tooltip === 'object' ? tooltip : null) }}
388
390
  >
389
391
  {#snippet children({ context })}
390
392
  {@const snippetProps = {
@@ -69,7 +69,6 @@
69
69
  import { onMount, type ComponentProps } from 'svelte';
70
70
  import { scaleLinear, scaleTime } from 'd3-scale';
71
71
  import { stack, stackOffsetDiverging, stackOffsetExpand, stackOffsetNone } from 'd3-shape';
72
- import { format } from '@layerstack/utils';
73
72
  import { cls } from '@layerstack/tailwind';
74
73
 
75
74
  import Area from '../Area.svelte';
@@ -136,7 +135,14 @@
136
135
 
137
136
  const series = $derived(
138
137
  seriesProp === undefined
139
- ? [{ key: 'default', value: y, color: 'var(--color-primary)' }]
138
+ ? [
139
+ {
140
+ key: 'default',
141
+ label: typeof y === 'string' ? y : 'value',
142
+ value: y,
143
+ color: 'var(--color-primary)',
144
+ },
145
+ ]
140
146
  : seriesProp
141
147
  );
142
148
 
@@ -398,13 +404,7 @@
398
404
  if (axisDirection === 'y') {
399
405
  return {
400
406
  placement: radial ? 'radius' : 'left',
401
- format: (value) => {
402
- if (seriesLayout === 'stackExpand') {
403
- return format(value, 'percentRound');
404
- } else {
405
- return format(value, undefined, { variant: 'short' });
406
- }
407
- },
407
+ format: seriesLayout === 'stackExpand' ? 'percentRound' : undefined,
408
408
  ...(typeof axis === 'object' ? axis : null),
409
409
  ...props.yAxis,
410
410
  };
@@ -412,7 +412,6 @@
412
412
 
413
413
  return {
414
414
  placement: radial ? 'angle' : 'bottom',
415
- format: (value) => format(value, undefined, { variant: 'short' }),
416
415
  ...(typeof axis === 'object' ? axis : null),
417
416
  ...props.xAxis,
418
417
  };
@@ -444,10 +443,11 @@
444
443
  tooltip={tooltip === false
445
444
  ? false
446
445
  : {
447
- mode: 'bisect-x',
446
+ mode: 'quadtree-x',
448
447
  onclick: onTooltipClick,
449
448
  debug,
450
449
  ...props.tooltip?.context,
450
+ ...(typeof tooltip === 'object' ? tooltip : null),
451
451
  }}
452
452
  brush={brush && (brush === true || brush.mode == undefined || brush.mode === 'integrated')
453
453
  ? {
@@ -84,9 +84,8 @@
84
84
 
85
85
  <script lang="ts" generics="TData">
86
86
  import { onMount, type ComponentProps } from 'svelte';
87
- import { scaleBand, scaleLinear } from 'd3-scale';
87
+ import { scaleBand, scaleLinear, scaleTime } from 'd3-scale';
88
88
  import { stack, stackOffsetDiverging, stackOffsetExpand, stackOffsetNone } from 'd3-shape';
89
- import { format } from '@layerstack/utils';
90
89
  import { cls } from '@layerstack/tailwind';
91
90
 
92
91
  import Axis from '../Axis.svelte';
@@ -109,7 +108,7 @@
109
108
  import { asAny } from '../../utils/types.js';
110
109
  import type { Insets } from '../../utils/rect.svelte.js';
111
110
  import type { SeriesData, SimplifiedChartProps, SimplifiedChartPropsObject } from './types.js';
112
- import type { AnyScale } from '../../utils/scales.svelte.js';
111
+ import { isScaleTime, type AnyScale } from '../../utils/scales.svelte.js';
113
112
  import { createLegendProps, SeriesState } from './utils.svelte.js';
114
113
  import { setTooltipMetaContext } from '../tooltip/tooltipMetaContext.js';
115
114
  import DefaultTooltip from './DefaultTooltip.svelte';
@@ -160,6 +159,14 @@
160
159
  ? [
161
160
  {
162
161
  key: 'default',
162
+ label:
163
+ orientation === 'vertical'
164
+ ? typeof yProp === 'string'
165
+ ? yProp
166
+ : 'value'
167
+ : typeof xProp === 'string'
168
+ ? xProp
169
+ : 'value',
163
170
  value: orientation === 'vertical' ? yProp : xProp,
164
171
  },
165
172
  ]
@@ -171,15 +178,56 @@
171
178
  const isStackSeries = $derived(seriesLayout.startsWith('stack'));
172
179
  const isGroupSeries = $derived(seriesLayout === 'group');
173
180
 
181
+ const chartData: Array<TData & { stackData?: any }> = $derived.by(() => {
182
+ let _chartData = (
183
+ seriesState.allSeriesData.length ? seriesState.allSeriesData : chartDataArray(data)
184
+ ) as Array<TData & { stackData?: any }>;
185
+ if (isStackSeries) {
186
+ const seriesKeys = seriesState.visibleSeries.map((s) => s.key);
187
+
188
+ const offset =
189
+ seriesLayout === 'stackExpand'
190
+ ? stackOffsetExpand
191
+ : seriesLayout === 'stackDiverging'
192
+ ? stackOffsetDiverging
193
+ : stackOffsetNone;
194
+ const stackData = stack()
195
+ .keys(seriesKeys)
196
+ .value((d, key) => {
197
+ const s = series.find((d) => d.key === key)!;
198
+ return accessor(s.value ?? s.key)(d as any);
199
+ })
200
+ .offset(offset)(chartDataArray(data)) as any[];
201
+
202
+ _chartData = _chartData.map((d, i) => {
203
+ return {
204
+ ...d,
205
+ stackData: stackData.map((sd) => sd[i]),
206
+ };
207
+ });
208
+ }
209
+ return _chartData;
210
+ });
211
+
174
212
  const xScale = $derived(
175
- xScaleProp ?? (isVertical ? scaleBand().padding(bandPadding) : scaleLinear())
213
+ xScaleProp ??
214
+ (isVertical
215
+ ? scaleBand().padding(bandPadding)
216
+ : accessor(xProp)(chartData[0]) instanceof Date // TODO: also check for Array<Date> instances (ex. x={['start', 'end']})
217
+ ? scaleTime()
218
+ : scaleLinear())
176
219
  );
177
- const xBaseline = $derived(isVertical ? undefined : 0);
220
+ const xBaseline = $derived(isVertical || isScaleTime(xScale) ? undefined : 0);
178
221
 
179
222
  const yScale = $derived(
180
- yScaleProp ?? (isVertical ? scaleLinear() : scaleBand().padding(bandPadding))
223
+ yScaleProp ??
224
+ (isVertical
225
+ ? accessor(yProp)(chartData[0]) instanceof Date // TODO: also check for Array<Date> instances (ex. y={['start', 'end']})
226
+ ? scaleTime()
227
+ : scaleLinear()
228
+ : scaleBand().padding(bandPadding))
181
229
  );
182
- const yBaseline = $derived(isVertical ? 0 : undefined);
230
+ const yBaseline = $derived(isVertical || isScaleTime(yScale) ? 0 : undefined);
183
231
 
184
232
  const x1Scale = $derived(
185
233
  isGroupSeries && isVertical ? scaleBand().padding(groupPadding) : undefined
@@ -214,37 +262,6 @@
214
262
  return d && typeof d === 'object' && 'stackData' in d;
215
263
  }
216
264
 
217
- const chartData: Array<TData & { stackData?: any }> = $derived.by(() => {
218
- let _chartData = (
219
- seriesState.allSeriesData.length ? seriesState.allSeriesData : chartDataArray(data)
220
- ) as Array<TData & { stackData?: any }>;
221
- if (isStackSeries) {
222
- const seriesKeys = seriesState.visibleSeries.map((s) => s.key);
223
-
224
- const offset =
225
- seriesLayout === 'stackExpand'
226
- ? stackOffsetExpand
227
- : seriesLayout === 'stackDiverging'
228
- ? stackOffsetDiverging
229
- : stackOffsetNone;
230
- const stackData = stack()
231
- .keys(seriesKeys)
232
- .value((d, key) => {
233
- const s = series.find((d) => d.key === key)!;
234
- return accessor(s.value ?? s.key)(d as any);
235
- })
236
- .offset(offset)(chartDataArray(data)) as any[];
237
-
238
- _chartData = _chartData.map((d, i) => {
239
- return {
240
- ...d,
241
- stackData: stackData.map((sd) => sd[i]),
242
- };
243
- });
244
- }
245
- return _chartData;
246
- });
247
-
248
265
  function getBarsProps(s: SeriesData<TData, typeof Bars>, i: number): ComponentProps<typeof Bars> {
249
266
  const isFirst = i == 0;
250
267
  const isLast = i == seriesState.visibleSeries.length - 1;
@@ -278,7 +295,12 @@
278
295
  y: isVertical ? valueAccessor : undefined,
279
296
  x1: isVertical && isGroupSeries ? (d) => s.value ?? s.key : undefined,
280
297
  y1: !isVertical && isGroupSeries ? (d) => s.value ?? s.key : undefined,
281
- rounded: isStackLayout && i !== seriesState.visibleSeries.length - 1 ? 'none' : 'edge',
298
+ rounded:
299
+ isStackLayout && i !== seriesState.visibleSeries.length - 1
300
+ ? 'none'
301
+ : Array.isArray(xProp) || Array.isArray(yProp)
302
+ ? 'all'
303
+ : 'edge',
282
304
  radius: 4,
283
305
  strokeWidth: 1,
284
306
  insets: stackInsets,
@@ -350,26 +372,14 @@
350
372
  return {
351
373
  placement: radial ? 'radius' : 'left',
352
374
 
353
- format: (value) => {
354
- if (isVertical && seriesLayout === 'stackExpand') {
355
- return format(value, 'percentRound');
356
- } else {
357
- return format(value, undefined, { variant: 'short' });
358
- }
359
- },
375
+ format: isVertical && seriesLayout === 'stackExpand' ? 'percentRound' : undefined,
360
376
  ...(typeof axis === 'object' ? axis : null),
361
377
  ...props.yAxis,
362
378
  };
363
379
  }
364
380
  return {
365
381
  placement: radial ? 'angle' : 'bottom',
366
- format: (value) => {
367
- if (!isVertical && seriesLayout === 'stackExpand') {
368
- return format(value, 'percentRound');
369
- } else {
370
- return format(value, undefined, { variant: 'short' });
371
- }
372
- },
382
+ format: !isVertical && seriesLayout === 'stackExpand' ? 'percentRound' : undefined,
373
383
  ...(typeof axis === 'object' ? axis : null),
374
384
  ...props.xAxis,
375
385
  };
@@ -445,6 +455,7 @@
445
455
  onclick: onTooltipClick,
446
456
  debug,
447
457
  ...props.tooltip?.context,
458
+ ...(typeof tooltip === 'object' ? tooltip : null),
448
459
  }}
449
460
  brush={brush && (brush === true || brush.mode == undefined || brush.mode === 'integrated')
450
461
  ? {
@@ -41,7 +41,7 @@
41
41
  {/each}
42
42
 
43
43
  {#if canHaveTotal && payload.length > 1 && !tooltipProps?.hideTotal}
44
- <Tooltip.Separator {...tooltipProps?.separator} />
44
+ <Tooltip.Separator {...tooltipProps?.separator} children={undefined} />
45
45
 
46
46
  <Tooltip.Item
47
47
  label="total"
@@ -70,7 +70,6 @@
70
70
  <script lang="ts" generics="TData">
71
71
  import { onMount, type ComponentProps } from 'svelte';
72
72
  import { scaleLinear, scaleTime } from 'd3-scale';
73
- import { format } from '@layerstack/utils';
74
73
  import { cls } from '@layerstack/tailwind';
75
74
 
76
75
  import Axis from '../Axis.svelte';
@@ -142,7 +141,14 @@
142
141
 
143
142
  const series = $derived(
144
143
  seriesProp === undefined
145
- ? [{ key: 'default', value: yProp, color: 'var(--color-primary)' }]
144
+ ? [
145
+ {
146
+ key: 'default',
147
+ label: typeof yProp === 'string' ? yProp : 'value',
148
+ value: yProp,
149
+ color: 'var(--color-primary)',
150
+ },
151
+ ]
146
152
  : seriesProp
147
153
  );
148
154
  const seriesState = new SeriesState(() => series);
@@ -284,14 +290,12 @@
284
290
  if (axisDirection === 'y') {
285
291
  return {
286
292
  placement: radial ? 'radius' : 'left',
287
- format: (value) => format(value, undefined, { variant: 'short' }),
288
293
  ...(typeof axis === 'object' ? axis : null),
289
294
  ...props.yAxis,
290
295
  };
291
296
  }
292
297
  return {
293
298
  placement: radial ? 'angle' : 'bottom',
294
- format: (value) => format(value, undefined, { variant: 'short' }),
295
299
  ...(typeof axis === 'object' ? axis : null),
296
300
  ...props.xAxis,
297
301
  };
@@ -339,10 +343,11 @@
339
343
  tooltip={tooltip === false
340
344
  ? false
341
345
  : {
342
- mode: 'bisect-x',
346
+ mode: 'quadtree-x',
343
347
  onclick: onTooltipClick,
344
348
  debug,
345
349
  ...props.tooltip?.context,
350
+ ...(typeof tooltip === 'object' ? tooltip : null),
346
351
  }}
347
352
  brush={brush && (brush === true || brush.mode == undefined || brush.mode === 'integrated')
348
353
  ? {
@@ -377,7 +382,6 @@
377
382
  {@render childrenProp(snippetProps)}
378
383
  {:else}
379
384
  {@render belowContext?.(snippetProps)}
380
- <!-- TODO: Always use `Svg` until `Pattern` supports `Canvas` (issue #307) -->
381
385
 
382
386
  <Layer
383
387
  type={renderContext}
@@ -281,9 +281,9 @@
281
281
  placement: 'bottom',
282
282
  variant: 'swatches',
283
283
  onclick: (e, item) => {
284
- selectedKeys.toggleSelected(item.value);
284
+ selectedKeys.toggle(item.value);
285
285
  // TODO: investigate
286
- // selectedSeries.toggleSelected(item.value);
286
+ // selectedSeries.toggle(item.value);
287
287
  },
288
288
  onpointerenter: (e, item) => (highlightKey.current = item.value),
289
289
  onpointerleave: (e) => (highlightKey.current = null),
@@ -409,7 +409,9 @@
409
409
  ]}
410
410
  padding={{ bottom: legend === true ? 32 : 0 }}
411
411
  {...restProps}
412
- tooltip={tooltip === false ? false : props.tooltip?.context}
412
+ tooltip={tooltip === false
413
+ ? false
414
+ : { ...props.tooltip?.context, ...(typeof tooltip === 'object' ? tooltip : null) }}
413
415
  >
414
416
  {#snippet children({ context })}
415
417
  {@const snippetProps = {
@@ -205,14 +205,12 @@
205
205
  if (axisDirection === 'y') {
206
206
  return {
207
207
  placement: 'left',
208
- format: (value) => format(value, undefined, { variant: 'short' }),
209
208
  ...(typeof axis === 'object' ? axis : null),
210
209
  ...props.yAxis,
211
210
  };
212
211
  }
213
212
  return {
214
213
  placement: 'bottom',
215
- format: (value) => format(value, undefined, { variant: 'short' }),
216
214
  ...(typeof axis === 'object' ? axis : null),
217
215
  ...props.xAxis,
218
216
  };
@@ -255,10 +253,11 @@
255
253
  tooltip={tooltip === false
256
254
  ? false
257
255
  : {
258
- mode: 'voronoi',
256
+ mode: 'quadtree',
259
257
  onclick: onTooltipClick,
260
258
  debug,
261
259
  ...props.tooltip?.context,
260
+ ...(typeof tooltip === 'object' ? tooltip : null),
262
261
  }}
263
262
  brush={brush && (brush === true || brush.mode == undefined || brush.mode === 'integrated')
264
263
  ? {
@@ -8,8 +8,8 @@ export declare class HighlightKey<TData, SeriesComponent extends Component> {
8
8
  }
9
9
  export declare class SeriesState<TData, TComponent extends Component> {
10
10
  #private;
11
- selectedSeries: SelectionState<unknown>;
12
- selectedKeys: SelectionState<unknown>;
11
+ selectedSeries: SelectionState<unknown, false>;
12
+ selectedKeys: SelectionState<unknown, false>;
13
13
  highlightKey: HighlightKey<TData, TComponent>;
14
14
  constructor(getSeries: () => SeriesData<TData, TComponent>[]);
15
15
  get series(): SeriesData<TData, TComponent>[];
@@ -13,6 +13,10 @@ export class SeriesState {
13
13
  highlightKey = new HighlightKey();
14
14
  constructor(getSeries) {
15
15
  this.#series = getSeries();
16
+ $effect.pre(() => {
17
+ // keep series state in sync with the prop
18
+ this.#series = getSeries();
19
+ });
16
20
  }
17
21
  get series() {
18
22
  return this.#series;
@@ -40,7 +44,7 @@ export function createLegendProps(opts) {
40
44
  tickFormat: (key) => opts.seriesState.series.find((s) => s.key === key)?.label ?? key,
41
45
  placement: 'bottom',
42
46
  variant: 'swatches',
43
- onclick: (_, item) => opts.seriesState.selectedSeries.toggleSelected(item.value),
47
+ onclick: (_, item) => opts.seriesState.selectedSeries.toggle(item.value),
44
48
  onpointerenter: (_, item) => (opts.seriesState.highlightKey.current = item.value),
45
49
  onpointerleave: () => (opts.seriesState.highlightKey.current = null),
46
50
  ...opts.props,
@@ -42,6 +42,8 @@ export { default as Connector } from './Connector.svelte';
42
42
  export * from './Connector.svelte';
43
43
  export { default as Dagre } from './Dagre.svelte';
44
44
  export * from './Dagre.svelte';
45
+ export { default as Ellipse } from './Ellipse.svelte';
46
+ export * from './Ellipse.svelte';
45
47
  export { default as Frame } from './Frame.svelte';
46
48
  export * from './Frame.svelte';
47
49
  export { default as ForceSimulation } from './ForceSimulation.svelte';
@@ -102,6 +104,8 @@ export { default as Point } from './Point.svelte';
102
104
  export * from './Point.svelte';
103
105
  export { default as Points } from './Points.svelte';
104
106
  export * from './Points.svelte';
107
+ export { default as Polygon } from './Polygon.svelte';
108
+ export * from './Polygon.svelte';
105
109
  export { default as RadialGradient } from './RadialGradient.svelte';
106
110
  export * from './RadialGradient.svelte';
107
111
  export { default as Rect } from './Rect.svelte';