layerchart 2.0.0-next.2 → 2.0.0-next.20

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 (115) hide show
  1. package/dist/components/AnnotationLine.svelte +17 -29
  2. package/dist/components/AnnotationLine.svelte.d.ts +4 -2
  3. package/dist/components/AnnotationPoint.svelte +11 -13
  4. package/dist/components/AnnotationPoint.svelte.d.ts +4 -2
  5. package/dist/components/AnnotationRange.svelte +3 -3
  6. package/dist/components/Arc.svelte +2 -2
  7. package/dist/components/Axis.svelte +52 -24
  8. package/dist/components/Axis.svelte.d.ts +14 -3
  9. package/dist/components/Bar.svelte +7 -4
  10. package/dist/components/Bar.svelte.d.ts +4 -1
  11. package/dist/components/Bars.svelte +9 -6
  12. package/dist/components/Bars.svelte.d.ts +3 -3
  13. package/dist/components/Blur.svelte +20 -12
  14. package/dist/components/Blur.svelte.d.ts +2 -5
  15. package/dist/components/Calendar.svelte +10 -6
  16. package/dist/components/Calendar.svelte.d.ts +2 -1
  17. package/dist/components/Chart.svelte +2 -2
  18. package/dist/components/ClipPath.svelte +14 -9
  19. package/dist/components/Connector.svelte +2 -2
  20. package/dist/components/Connector.svelte.d.ts +1 -1
  21. package/dist/components/Ellipse.svelte +187 -0
  22. package/dist/components/Ellipse.svelte.d.ts +64 -0
  23. package/dist/components/ForceSimulation.svelte +168 -50
  24. package/dist/components/ForceSimulation.svelte.d.ts +80 -21
  25. package/dist/components/GeoEdgeFade.svelte +4 -3
  26. package/dist/components/GeoEdgeFade.svelte.d.ts +2 -2
  27. package/dist/components/GeoPath.svelte +12 -5
  28. package/dist/components/GeoPoint.svelte +1 -2
  29. package/dist/components/GeoSpline.svelte +4 -4
  30. package/dist/components/GeoSpline.svelte.d.ts +1 -1
  31. package/dist/components/Graticule.svelte +3 -2
  32. package/dist/components/Grid.svelte +8 -7
  33. package/dist/components/Grid.svelte.d.ts +2 -1
  34. package/dist/components/Group.svelte +45 -5
  35. package/dist/components/Group.svelte.d.ts +32 -4
  36. package/dist/components/Highlight.svelte +1 -1
  37. package/dist/components/Hull.svelte +4 -4
  38. package/dist/components/Hull.svelte.d.ts +2 -2
  39. package/dist/components/Labels.svelte +6 -4
  40. package/dist/components/Labels.svelte.d.ts +2 -2
  41. package/dist/components/Legend.svelte +8 -5
  42. package/dist/components/Legend.svelte.d.ts +3 -3
  43. package/dist/components/MonthPath.svelte +14 -11
  44. package/dist/components/MonthPath.svelte.d.ts +4 -3
  45. package/dist/components/Polygon.svelte +285 -0
  46. package/dist/components/Polygon.svelte.d.ts +115 -0
  47. package/dist/components/RadialGradient.svelte +1 -3
  48. package/dist/components/Rule.svelte +3 -2
  49. package/dist/components/Spline.svelte +30 -18
  50. package/dist/components/Spline.svelte.d.ts +12 -4
  51. package/dist/components/Text.svelte +60 -48
  52. package/dist/components/Text.svelte.d.ts +6 -0
  53. package/dist/components/Treemap.svelte +63 -26
  54. package/dist/components/Treemap.svelte.d.ts +11 -11
  55. package/dist/components/Voronoi.svelte +55 -36
  56. package/dist/components/Voronoi.svelte.d.ts +5 -3
  57. package/dist/components/charts/ArcChart.svelte +2 -2
  58. package/dist/components/charts/AreaChart.svelte +9 -10
  59. package/dist/components/charts/BarChart.svelte +63 -53
  60. package/dist/components/charts/DefaultTooltip.svelte +1 -1
  61. package/dist/components/charts/LineChart.svelte +8 -5
  62. package/dist/components/charts/PieChart.svelte +2 -2
  63. package/dist/components/charts/ScatterChart.svelte +0 -2
  64. package/dist/components/charts/utils.svelte.d.ts +3 -3
  65. package/dist/components/charts/utils.svelte.js +7 -3
  66. package/dist/components/index.d.ts +4 -0
  67. package/dist/components/index.js +4 -0
  68. package/dist/components/layout/Canvas.svelte +67 -49
  69. package/dist/components/layout/Canvas.svelte.d.ts +6 -0
  70. package/dist/components/layout/Layer.svelte +6 -4
  71. package/dist/components/layout/Layer.svelte.d.ts +6 -4
  72. package/dist/components/tooltip/Tooltip.svelte +14 -7
  73. package/dist/components/tooltip/TooltipContext.svelte +25 -8
  74. package/dist/components/tooltip/TooltipContext.svelte.d.ts +1 -1
  75. package/dist/components/tooltip/TooltipHeader.svelte +5 -4
  76. package/dist/components/tooltip/TooltipHeader.svelte.d.ts +3 -3
  77. package/dist/components/tooltip/TooltipItem.svelte +5 -4
  78. package/dist/components/tooltip/TooltipItem.svelte.d.ts +3 -3
  79. package/dist/components/tooltip/TooltipList.svelte +1 -1
  80. package/dist/components/tooltip/tooltipMetaContext.d.ts +2 -2
  81. package/dist/docs/Blockquote.svelte +3 -1
  82. package/dist/docs/Blockquote.svelte.d.ts +4 -19
  83. package/dist/docs/Code.svelte +20 -12
  84. package/dist/docs/Code.svelte.d.ts +9 -23
  85. package/dist/docs/Header1.svelte +4 -2
  86. package/dist/docs/Header1.svelte.d.ts +4 -28
  87. package/dist/docs/Json.svelte +11 -3
  88. package/dist/docs/Json.svelte.d.ts +9 -21
  89. package/dist/docs/Layout.svelte +10 -7
  90. package/dist/docs/Layout.svelte.d.ts +4 -19
  91. package/dist/docs/Link.svelte +7 -3
  92. package/dist/docs/Link.svelte.d.ts +4 -38
  93. package/dist/docs/TilesetField.svelte +20 -19
  94. package/dist/docs/TilesetField.svelte.d.ts +5 -22
  95. package/dist/docs/ViewSourceButton.svelte +7 -4
  96. package/dist/docs/ViewSourceButton.svelte.d.ts +7 -21
  97. package/dist/utils/arcText.svelte.js +4 -4
  98. package/dist/utils/canvas.d.ts +77 -0
  99. package/dist/utils/canvas.js +105 -41
  100. package/dist/utils/genData.d.ts +14 -0
  101. package/dist/utils/genData.js +24 -6
  102. package/dist/utils/path.d.ts +10 -0
  103. package/dist/utils/path.js +30 -0
  104. package/dist/utils/scales.svelte.d.ts +3 -2
  105. package/dist/utils/scales.svelte.js +7 -3
  106. package/dist/utils/shape.d.ts +43 -0
  107. package/dist/utils/shape.js +59 -0
  108. package/dist/utils/string.d.ts +49 -0
  109. package/dist/utils/string.js +4 -2
  110. package/dist/utils/ticks.d.ts +4 -4
  111. package/dist/utils/ticks.js +106 -159
  112. package/dist/utils/ticks.test.js +6 -16
  113. package/dist/utils/treemap.d.ts +1 -1
  114. package/package.json +25 -22
  115. package/dist/utils/object.js +0 -2
@@ -87,23 +87,23 @@
87
87
  /**
88
88
  * Add additional content at the start of the line.
89
89
  *
90
- * Receives `{ point: DOMPoint }` as a snippet prop.
90
+ * Receives `{ point: DOMPoint; value: { x: number; y: number } }` as a snippet prop.
91
91
  */
92
- startContent?: Snippet<[{ point: DOMPoint }]>;
92
+ startContent?: Snippet<[{ point: DOMPoint; value: { x: number; y: number } }]>;
93
93
 
94
94
  /**
95
95
  * Add additional content at the end of the line.
96
96
  *
97
- * Receives `{ point: DOMPoint }` as a snippet prop.
97
+ * Receives `{ point: DOMPoint; value: { x: number; y: number } }` as a snippet prop.
98
98
  */
99
- endContent?: Snippet<[{ point: DOMPoint }]>;
99
+ endContent?: Snippet<[{ point: DOMPoint; value: { x: number; y: number } }]>;
100
100
 
101
101
  /**
102
102
  * A reference to the `<path>` element.
103
103
  *
104
104
  * @bindable
105
105
  */
106
- splineRef?: SVGPathElement;
106
+ pathRef?: SVGPathElement;
107
107
 
108
108
  motion?: MotionProp;
109
109
  } & CommonStyleProps;
@@ -159,14 +159,14 @@
159
159
  startContent,
160
160
  endContent,
161
161
  opacity,
162
- splineRef: splineRefProp = $bindable(),
162
+ pathRef: pathRefProp = $bindable(),
163
163
  ...restProps
164
164
  }: SplineProps = $props();
165
165
 
166
- let splineRef = $state<SVGPathElement>();
166
+ let pathRef = $state<SVGPathElement>();
167
167
 
168
168
  $effect.pre(() => {
169
- splineRefProp = splineRef;
169
+ pathRefProp = pathRef;
170
170
  });
171
171
 
172
172
  const markerStart = $derived(markerStartProp ?? marker);
@@ -331,8 +331,8 @@
331
331
  easing: typeof draw === 'object' && draw.easing ? draw.easing : cubicInOut,
332
332
  interpolate() {
333
333
  return (t: number) => {
334
- const totalLength = splineRef?.getTotalLength() ?? 0;
335
- const point = splineRef?.getPointAtLength(totalLength * t);
334
+ const totalLength = pathRef?.getTotalLength() ?? 0;
335
+ const point = pathRef?.getPointAtLength(totalLength * t);
336
336
  return point;
337
337
  };
338
338
  },
@@ -343,16 +343,16 @@
343
343
  $effect(() => {
344
344
  if (!startContent && !endContent) return;
345
345
  d;
346
- if (!splineRef || !splineRef.getTotalLength()) return;
347
- startPoint = splineRef.getPointAtLength(0);
348
- const totalLength = splineRef.getTotalLength();
349
- endPoint.target = splineRef.getPointAtLength(totalLength);
346
+ if (!pathRef || !pathRef.getTotalLength()) return;
347
+ startPoint = pathRef.getPointAtLength(0);
348
+ const totalLength = pathRef.getTotalLength();
349
+ endPoint.target = pathRef.getPointAtLength(totalLength);
350
350
  });
351
351
 
352
352
  $effect(() => {
353
353
  if (!draw) return;
354
- [tweenedState.current];
355
354
  // Anytime the path data changes, redraw
355
+ [pathData, data, ctx.data];
356
356
  key = Symbol();
357
357
  });
358
358
  </script>
@@ -377,7 +377,7 @@
377
377
  marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
378
378
  marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
379
379
  in:drawTransition|global={typeof draw === 'object' ? draw : undefined}
380
- bind:this={splineRef}
380
+ bind:this={pathRef}
381
381
  />
382
382
  <MarkerWrapper id={markerStartId} marker={markerStart} />
383
383
  <MarkerWrapper id={markerMidId} marker={markerMid} />
@@ -385,13 +385,25 @@
385
385
 
386
386
  {#if startContent && startPoint}
387
387
  <Group x={startPoint.x} y={startPoint.y} class={layerClass('spline-g-start')}>
388
- {@render startContent({ point: startPoint })}
388
+ {@render startContent({
389
+ point: startPoint,
390
+ value: {
391
+ x: ctx.xScale?.invert?.(startPoint.x),
392
+ y: ctx.yScale?.invert?.(startPoint.y),
393
+ },
394
+ })}
389
395
  </Group>
390
396
  {/if}
391
397
 
392
398
  {#if endContent && endPoint.current}
393
399
  <Group x={endPoint.current.x} y={endPoint.current.y} class={layerClass('spline-g-end')}>
394
- {@render endContent({ point: endPoint.current })}
400
+ {@render endContent({
401
+ point: endPoint.current,
402
+ value: {
403
+ x: ctx.xScale?.invert?.(endPoint.current.x),
404
+ y: ctx.yScale?.invert?.(endPoint.current.y),
405
+ },
406
+ })}
395
407
  </Group>
396
408
  {/if}
397
409
  {/key}
@@ -67,29 +67,37 @@ export type SplinePropsWithoutHTML = {
67
67
  /**
68
68
  * Add additional content at the start of the line.
69
69
  *
70
- * Receives `{ point: DOMPoint }` as a snippet prop.
70
+ * Receives `{ point: DOMPoint; value: { x: number; y: number } }` as a snippet prop.
71
71
  */
72
72
  startContent?: Snippet<[{
73
73
  point: DOMPoint;
74
+ value: {
75
+ x: number;
76
+ y: number;
77
+ };
74
78
  }]>;
75
79
  /**
76
80
  * Add additional content at the end of the line.
77
81
  *
78
- * Receives `{ point: DOMPoint }` as a snippet prop.
82
+ * Receives `{ point: DOMPoint; value: { x: number; y: number } }` as a snippet prop.
79
83
  */
80
84
  endContent?: Snippet<[{
81
85
  point: DOMPoint;
86
+ value: {
87
+ x: number;
88
+ y: number;
89
+ };
82
90
  }]>;
83
91
  /**
84
92
  * A reference to the `<path>` element.
85
93
  *
86
94
  * @bindable
87
95
  */
88
- splineRef?: SVGPathElement;
96
+ pathRef?: SVGPathElement;
89
97
  motion?: MotionProp;
90
98
  } & CommonStyleProps;
91
99
  export type SplineProps = SplinePropsWithoutHTML & Without<SVGAttributes<SVGPathElement>, SplinePropsWithoutHTML>;
92
100
  import { draw as _drawTransition } from 'svelte/transition';
93
- declare const Spline: import("svelte").Component<SplineProps, {}, "splineRef">;
101
+ declare const Spline: import("svelte").Component<SplineProps, {}, "pathRef">;
94
102
  type Spline = ReturnType<typeof Spline>;
95
103
  export default Spline;
@@ -97,6 +97,20 @@
97
97
  */
98
98
  verticalAnchor?: 'start' | 'middle' | 'end' | 'inherit';
99
99
 
100
+ /**
101
+ * The dominant baseline of the text. Useful for aligning text to the baseline of the axis.
102
+ *
103
+ * @default 'auto'
104
+ */
105
+ dominantBaseline?:
106
+ | 'auto'
107
+ | 'text-before-edge'
108
+ | 'text-after-edge'
109
+ | 'middle'
110
+ | 'hanging'
111
+ | 'ideographic'
112
+ | 'mathematical';
113
+
100
114
  /**
101
115
  * Rotational angle of the text
102
116
  */
@@ -178,20 +192,6 @@
178
192
  import { degreesToRadians } from '../utils/math.js';
179
193
  import { createId } from '../utils/createId.js';
180
194
 
181
- /*
182
- TODO:
183
- - [ ] Handle styled text (use <slot /> to measure?)
184
- - [ ] Simplify by using `alignment-baseline` / `dominant-baseline`, rework multiline or drop support, etc
185
- - https://svelte.dev/repl/f12d3003313a43ba8a0be53e5786f1c7?version=3.44.3
186
- - https://observablehq.com/@neocartocnrs/cheat-sheet-on-texts-in-svg
187
-
188
- Reference:
189
- - https://bl.ocks.org/mbostock/7555321
190
- - https://github.com/airbnb/visx/blob/master/packages/visx-text/src/Text.tsx
191
- - https://airbnb.io/visx/text
192
- - https://github.com/airbnb/visx/blob/master/packages/visx-demo/src/pages/text.tsx
193
- */
194
-
195
195
  const uid = $props.id();
196
196
 
197
197
  let {
@@ -208,6 +208,7 @@
208
208
  scaleToFit = false,
209
209
  textAnchor = 'start',
210
210
  verticalAnchor = 'end',
211
+ dominantBaseline = 'auto',
211
212
  rotate,
212
213
  opacity = 1,
213
214
  strokeWidth = 0,
@@ -227,6 +228,8 @@
227
228
  ...restProps
228
229
  }: TextProps = $props();
229
230
 
231
+ const renderCtx = getRenderContext();
232
+
230
233
  let ref = $state<SVGTextElement>();
231
234
  let svgRef = $state<SVGElement>();
232
235
  let pathRef = $state<SVGPathElement>();
@@ -260,49 +263,56 @@
260
263
  };
261
264
  });
262
265
 
263
- const rawText = $derived(value != null ? value.toString() : '');
266
+ // Handle null and convert `\n` strings back to newline characters
267
+ const rawText = $derived(value != null ? value.toString().replace(/\\n/g, '\n') : '');
264
268
 
265
269
  const textValue = $derived.by(() => {
266
270
  if (!truncateConfig) return rawText;
267
271
  return truncateText(rawText, truncateConfig);
268
272
  });
269
273
 
270
- const renderCtx = getRenderContext();
271
-
272
- const words = $derived(textValue ? textValue.split(/(?:(?!\u00A0+)\s+)/) : []);
274
+ const spaceWidth = $derived(getStringWidth('\u00A0', style) || 0);
273
275
 
274
- const wordsWithWidth = $derived(
275
- words.map((word) => ({
276
- word,
277
- width: getStringWidth(word, style) || 0,
278
- }))
279
- );
276
+ const wordsByLines = $derived.by(() => {
277
+ // Split by newlines to preserve explicit line breaks
278
+ const lines = textValue.split('\n');
280
279
 
281
- const spaceWidth = $derived(getStringWidth('\u00A0', style) || 0);
280
+ return lines.flatMap((line) => {
281
+ // Split each line into words
282
+ const words = line.split(/(?:(?!\u00A0+)\s+)/);
282
283
 
283
- const wordsByLines = $derived(
284
- wordsWithWidth.reduce((result: { words: string[]; width?: number }[], item) => {
285
- const currentLine = result[result.length - 1];
286
-
287
- if (
288
- currentLine &&
289
- (width == null || scaleToFit || (currentLine.width || 0) + item.width + spaceWidth < width)
290
- ) {
291
- // Word can be added to an existing line
292
- currentLine.words.push(item.word);
293
- currentLine.width = currentLine.width || 0;
294
- currentLine.width += item.width + spaceWidth;
284
+ if (width == null) {
285
+ // No width specified, only use explicit line breaks (if used)
286
+ return [{ words }];
295
287
  } else {
296
- // Add first word to line or word is too long to scaleToFit on existing line
297
- const newLine = { words: [item.word], width: item.width };
298
- result.push(newLine);
288
+ // Handle word wrapping within each line
289
+ return words.reduce((result: { words: string[]; width?: number }[], item) => {
290
+ const currentLine = result[result.length - 1];
291
+ const itemWidth = getStringWidth(item, style) || 0;
292
+
293
+ if (
294
+ currentLine &&
295
+ (width == null ||
296
+ scaleToFit ||
297
+ (currentLine.width || 0) + itemWidth + spaceWidth < width)
298
+ ) {
299
+ // Word can be added to an existing line
300
+ currentLine.words.push(item);
301
+ currentLine.width = currentLine.width || 0;
302
+ currentLine.width += itemWidth + spaceWidth;
303
+ } else {
304
+ // Add first word to line or word is too long to scaleToFit on existing line
305
+ const newLine = { words: [item], width: itemWidth };
306
+ result.push(newLine);
307
+ }
308
+
309
+ return result;
310
+ }, []);
299
311
  }
312
+ });
313
+ });
300
314
 
301
- return result;
302
- }, [])
303
- );
304
-
305
- const lines = $derived(wordsByLines.length);
315
+ const lineCount = $derived(wordsByLines.length);
306
316
 
307
317
  /**
308
318
  * Convert css value to pixel value (ex. 0.71em => 11.36)
@@ -329,9 +339,9 @@
329
339
  if (verticalAnchor === 'start') {
330
340
  return getPixelValue(capHeight);
331
341
  } else if (verticalAnchor === 'middle') {
332
- return ((lines - 1) / 2) * -getPixelValue(lineHeight) + getPixelValue(capHeight) / 2;
342
+ return ((lineCount - 1) / 2) * -getPixelValue(lineHeight) + getPixelValue(capHeight) / 2;
333
343
  } else {
334
- return (lines - 1) * -getPixelValue(lineHeight);
344
+ return (lineCount - 1) * -getPixelValue(lineHeight);
335
345
  }
336
346
  });
337
347
 
@@ -348,7 +358,7 @@
348
358
  const scaleTransform = $derived.by(() => {
349
359
  if (
350
360
  scaleToFit &&
351
- lines > 0 &&
361
+ lineCount > 0 &&
352
362
  typeof x == 'number' &&
353
363
  typeof y == 'number' &&
354
364
  typeof width == 'number'
@@ -500,6 +510,7 @@
500
510
  >
501
511
  <textPath
502
512
  style="text-anchor: {textAnchor};"
513
+ dominant-baseline={dominantBaseline}
503
514
  href="#{pathId}"
504
515
  {startOffset}
505
516
  class={cls(layerClass('text-path'))}
@@ -514,6 +525,7 @@
514
525
  y={motionY.current}
515
526
  {transform}
516
527
  text-anchor={textAnchor}
528
+ dominant-baseline={dominantBaseline}
517
529
  {...restProps}
518
530
  {fill}
519
531
  fill-opacity={fillOpacity}
@@ -80,6 +80,12 @@ export type TextPropsWithoutHTML = {
80
80
  * @default 'end'
81
81
  */
82
82
  verticalAnchor?: 'start' | 'middle' | 'end' | 'inherit';
83
+ /**
84
+ * The dominant baseline of the text. Useful for aligning text to the baseline of the axis.
85
+ *
86
+ * @default 'auto'
87
+ */
88
+ dominantBaseline?: 'auto' | 'text-before-edge' | 'text-after-edge' | 'middle' | 'hanging' | 'ideographic' | 'mathematical';
83
89
  /**
84
90
  * Rotational angle of the text
85
91
  */
@@ -18,53 +18,53 @@
18
18
  *
19
19
  * @default 0
20
20
  */
21
- padding?: number;
21
+ padding?: number | ((node: HierarchyRectangularNode<T>) => number);
22
22
 
23
23
  /**
24
24
  * The inner padding between nodes.
25
25
  *
26
26
  * @default 0
27
27
  */
28
- paddingInner?: number;
28
+ paddingInner?: number | ((node: HierarchyRectangularNode<T>) => number);
29
29
 
30
30
  /**
31
31
  * The outer padding between nodes.
32
32
  *
33
33
  * @default 0
34
34
  */
35
- paddingOuter?: number;
35
+ paddingOuter?: number | ((node: HierarchyRectangularNode<T>) => number);
36
36
 
37
37
  /**
38
38
  * The top padding between nodes.
39
39
  *
40
40
  * @default 0
41
41
  */
42
- paddingTop?: number;
42
+ paddingTop?: number | ((node: HierarchyRectangularNode<T>) => number);
43
43
 
44
44
  /**
45
45
  * The bottom padding between nodes.
46
46
  *
47
47
  * @default 0
48
48
  */
49
- paddingBottom?: number;
49
+ paddingBottom?: number | ((node: HierarchyRectangularNode<T>) => number);
50
50
  /**
51
51
  * The left padding between nodes.
52
52
  *
53
53
  */
54
- paddingLeft?: number;
54
+ paddingLeft?: number | ((node: HierarchyRectangularNode<T>) => number);
55
55
 
56
56
  /**
57
57
  * The right padding between nodes.
58
58
  *
59
59
  */
60
- paddingRight?: number;
60
+ paddingRight?: number | ((node: HierarchyRectangularNode<T>) => number);
61
61
 
62
62
  /**
63
- * The selected node.
63
+ * Modify tiling function for approapriate aspect ratio when treemap is zoomed in
64
64
  *
65
- * @default null
65
+ * @default false
66
66
  */
67
- selected?: HierarchyRectangularNode<T> | null;
67
+ maintainAspectRatio?: boolean;
68
68
 
69
69
  hierarchy?: HierarchyNode<T>;
70
70
 
@@ -99,7 +99,7 @@
99
99
  paddingBottom = 0,
100
100
  paddingLeft,
101
101
  paddingRight,
102
- selected = $bindable(null),
102
+ maintainAspectRatio = false,
103
103
  children,
104
104
  }: TreemapProps<T> = $props();
105
105
 
@@ -121,45 +121,82 @@
121
121
  : tile
122
122
  );
123
123
 
124
- const treemap = $derived.by(() => {
124
+ const treemapData = $derived.by(() => {
125
125
  const _treemap = d3treemap<T>()
126
126
  .size([ctx.width, ctx.height])
127
- .tile(aspectTile(tileFunc, ctx.width, ctx.height));
127
+ .tile(maintainAspectRatio ? aspectTile(tileFunc, ctx.width, ctx.height) : tileFunc);
128
128
 
129
129
  if (padding) {
130
- _treemap.padding(padding);
130
+ // Make Typescript happy to pick the correct overload
131
+ // TODO: Better way to do this?
132
+ if (typeof padding === 'number') {
133
+ _treemap.padding(padding);
134
+ } else {
135
+ _treemap.padding(padding);
136
+ }
131
137
  }
132
138
 
133
139
  if (paddingInner) {
134
- _treemap.paddingInner(paddingInner);
140
+ if (typeof paddingInner === 'number') {
141
+ _treemap.paddingInner(typeof paddingInner === 'number' ? paddingInner : paddingInner);
142
+ } else {
143
+ _treemap.paddingInner(paddingInner);
144
+ }
135
145
  }
136
146
 
137
147
  if (paddingOuter) {
138
- _treemap.paddingOuter(paddingOuter);
148
+ if (typeof paddingOuter === 'number') {
149
+ _treemap.paddingOuter(paddingOuter);
150
+ } else {
151
+ _treemap.paddingOuter(paddingOuter);
152
+ }
139
153
  }
140
154
 
141
155
  if (paddingTop) {
142
- _treemap.paddingTop(paddingTop);
156
+ if (typeof paddingTop === 'number') {
157
+ _treemap.paddingTop(paddingTop);
158
+ } else {
159
+ _treemap.paddingTop(paddingTop);
160
+ }
143
161
  }
144
162
 
145
163
  if (paddingBottom) {
146
- _treemap.paddingBottom(paddingBottom);
164
+ if (typeof paddingBottom === 'number') {
165
+ _treemap.paddingBottom(paddingBottom);
166
+ } else {
167
+ _treemap.paddingBottom(paddingBottom);
168
+ }
147
169
  }
148
170
 
149
171
  if (paddingLeft) {
150
- _treemap.paddingLeft(paddingLeft);
172
+ if (typeof paddingLeft === 'number') {
173
+ _treemap.paddingLeft(paddingLeft);
174
+ } else {
175
+ _treemap.paddingLeft(paddingLeft);
176
+ }
151
177
  }
152
178
  if (paddingRight) {
153
- _treemap.paddingRight(paddingRight);
179
+ if (typeof paddingRight === 'number') {
180
+ _treemap.paddingRight(paddingRight);
181
+ } else {
182
+ _treemap.paddingRight(paddingRight);
183
+ }
154
184
  }
155
- return _treemap;
156
- });
157
185
 
158
- const treemapData = $derived(hierarchy ? treemap(hierarchy) : null);
186
+ if (hierarchy) {
187
+ const h = hierarchy.copy();
188
+ const treemapData = _treemap(h);
189
+ return {
190
+ links: treemapData.links(),
191
+ nodes: treemapData.descendants(),
192
+ };
193
+ }
159
194
 
160
- $effect.pre(() => {
161
- selected = treemapData;
195
+ return {
196
+ links: [],
197
+ nodes: [],
198
+ };
162
199
  });
163
200
  </script>
164
201
 
165
- {@render children?.({ nodes: treemapData ? treemapData.descendants() : [] })}
202
+ {@render children?.({ nodes: treemapData.nodes })}
@@ -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 {