layerchart 2.0.0-next.3 → 2.0.0-next.31

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 (112) 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 +83 -29
  5. package/dist/components/Axis.svelte.d.ts +13 -3
  6. package/dist/components/Bar.svelte +12 -8
  7. package/dist/components/Blur.svelte +5 -3
  8. package/dist/components/Blur.svelte.d.ts +2 -5
  9. package/dist/components/BrushContext.svelte +1 -1
  10. package/dist/components/Calendar.svelte +10 -6
  11. package/dist/components/Calendar.svelte.d.ts +2 -1
  12. package/dist/components/Chart.svelte +39 -3
  13. package/dist/components/Chart.svelte.d.ts +11 -0
  14. package/dist/components/Connector.svelte +2 -2
  15. package/dist/components/Connector.svelte.d.ts +1 -1
  16. package/dist/components/Ellipse.svelte +187 -0
  17. package/dist/components/Ellipse.svelte.d.ts +64 -0
  18. package/dist/components/ForceSimulation.svelte +184 -50
  19. package/dist/components/ForceSimulation.svelte.d.ts +88 -21
  20. package/dist/components/GeoPath.svelte +12 -5
  21. package/dist/components/GeoPoint.svelte +1 -2
  22. package/dist/components/GeoSpline.svelte +4 -4
  23. package/dist/components/GeoSpline.svelte.d.ts +1 -1
  24. package/dist/components/Group.svelte +2 -2
  25. package/dist/components/Highlight.svelte +9 -6
  26. package/dist/components/Hull.svelte +1 -1
  27. package/dist/components/Labels.svelte +3 -2
  28. package/dist/components/Labels.svelte.d.ts +2 -2
  29. package/dist/components/Legend.svelte +19 -12
  30. package/dist/components/Legend.svelte.d.ts +5 -5
  31. package/dist/components/MonthPath.svelte +14 -11
  32. package/dist/components/MonthPath.svelte.d.ts +4 -3
  33. package/dist/components/Polygon.svelte +285 -0
  34. package/dist/components/Polygon.svelte.d.ts +115 -0
  35. package/dist/components/RadialGradient.svelte +1 -3
  36. package/dist/components/Spline.svelte +30 -18
  37. package/dist/components/Spline.svelte.d.ts +12 -4
  38. package/dist/components/Text.svelte +62 -60
  39. package/dist/components/Text.svelte.d.ts +6 -0
  40. package/dist/components/TransformControls.svelte +16 -20
  41. package/dist/components/Treemap.svelte +63 -26
  42. package/dist/components/Treemap.svelte.d.ts +11 -11
  43. package/dist/components/Voronoi.svelte +51 -33
  44. package/dist/components/Voronoi.svelte.d.ts +3 -1
  45. package/dist/components/charts/ArcChart.svelte +5 -3
  46. package/dist/components/charts/AreaChart.svelte +11 -11
  47. package/dist/components/charts/BarChart.svelte +72 -53
  48. package/dist/components/charts/DefaultTooltip.svelte +1 -1
  49. package/dist/components/charts/LineChart.svelte +10 -6
  50. package/dist/components/charts/PieChart.svelte +5 -3
  51. package/dist/components/charts/ScatterChart.svelte +2 -3
  52. package/dist/components/charts/utils.svelte.d.ts +2 -2
  53. package/dist/components/charts/utils.svelte.js +5 -1
  54. package/dist/components/index.d.ts +4 -0
  55. package/dist/components/index.js +5 -1
  56. package/dist/components/layout/Canvas.svelte +67 -49
  57. package/dist/components/layout/Canvas.svelte.d.ts +6 -0
  58. package/dist/components/layout/Layer.svelte +6 -4
  59. package/dist/components/layout/Layer.svelte.d.ts +6 -4
  60. package/dist/components/tooltip/Tooltip.svelte +14 -7
  61. package/dist/components/tooltip/TooltipContext.svelte +136 -43
  62. package/dist/components/tooltip/TooltipContext.svelte.d.ts +3 -3
  63. package/dist/components/tooltip/TooltipHeader.svelte +5 -4
  64. package/dist/components/tooltip/TooltipHeader.svelte.d.ts +3 -3
  65. package/dist/components/tooltip/TooltipItem.svelte +5 -4
  66. package/dist/components/tooltip/TooltipItem.svelte.d.ts +3 -3
  67. package/dist/components/tooltip/TooltipList.svelte +1 -1
  68. package/dist/components/tooltip/tooltipMetaContext.d.ts +2 -2
  69. package/dist/docs/Blockquote.svelte +6 -4
  70. package/dist/docs/Blockquote.svelte.d.ts +4 -19
  71. package/dist/docs/Code.svelte +20 -12
  72. package/dist/docs/Code.svelte.d.ts +9 -23
  73. package/dist/docs/Header1.svelte +4 -2
  74. package/dist/docs/Header1.svelte.d.ts +4 -28
  75. package/dist/docs/Json.svelte +11 -3
  76. package/dist/docs/Json.svelte.d.ts +9 -21
  77. package/dist/docs/Layout.svelte +10 -7
  78. package/dist/docs/Layout.svelte.d.ts +4 -19
  79. package/dist/docs/Link.svelte +7 -3
  80. package/dist/docs/Link.svelte.d.ts +4 -38
  81. package/dist/docs/Preview.svelte +6 -3
  82. package/dist/docs/TilesetField.svelte +20 -19
  83. package/dist/docs/TilesetField.svelte.d.ts +5 -22
  84. package/dist/docs/ViewSourceButton.svelte +9 -6
  85. package/dist/docs/ViewSourceButton.svelte.d.ts +7 -21
  86. package/dist/utils/arcText.svelte.js +4 -4
  87. package/dist/utils/array.d.ts +11 -0
  88. package/dist/utils/array.js +23 -0
  89. package/dist/utils/array.test.d.ts +1 -0
  90. package/dist/utils/array.test.js +200 -0
  91. package/dist/utils/canvas.d.ts +77 -0
  92. package/dist/utils/canvas.js +105 -41
  93. package/dist/utils/genData.d.ts +14 -0
  94. package/dist/utils/genData.js +24 -6
  95. package/dist/utils/index.d.ts +1 -0
  96. package/dist/utils/index.js +1 -0
  97. package/dist/utils/path.d.ts +10 -0
  98. package/dist/utils/path.js +30 -0
  99. package/dist/utils/rect.svelte.d.ts +2 -2
  100. package/dist/utils/rect.svelte.js +69 -1
  101. package/dist/utils/scales.svelte.d.ts +3 -2
  102. package/dist/utils/scales.svelte.js +7 -3
  103. package/dist/utils/shape.d.ts +43 -0
  104. package/dist/utils/shape.js +59 -0
  105. package/dist/utils/string.d.ts +49 -0
  106. package/dist/utils/string.js +4 -2
  107. package/dist/utils/ticks.d.ts +15 -4
  108. package/dist/utils/ticks.js +144 -158
  109. package/dist/utils/ticks.test.js +11 -16
  110. package/dist/utils/treemap.d.ts +1 -1
  111. package/package.json +27 -25
  112. package/dist/utils/object.js +0 -2
@@ -88,23 +88,30 @@
88
88
  ? 'start'
89
89
  : 'middle',
90
90
  });
91
- </script>
92
91
 
93
- <Circle
94
- cx={point.x}
95
- cy={point.y}
96
- {r}
97
- onpointermove={(e) => {
92
+ function onPointerMove(e: PointerEvent | MouseEvent | TouchEvent) {
98
93
  if (details) {
99
94
  e.stopPropagation();
100
95
  ctx.tooltip.show(e, { annotation: { label, details } });
101
96
  }
102
- }}
103
- onpointerleave={() => {
97
+ }
98
+
99
+ function onPointerLeave(e: PointerEvent | MouseEvent | TouchEvent) {
104
100
  if (details) {
101
+ e.stopPropagation();
105
102
  ctx.tooltip.hide();
106
103
  }
107
- }}
104
+ }
105
+ </script>
106
+
107
+ <Circle
108
+ cx={point.x}
109
+ cy={point.y}
110
+ {r}
111
+ onmousemove={onPointerMove}
112
+ ontouchmove={onPointerMove}
113
+ onmouseleave={onPointerLeave}
114
+ ontouchend={onPointerLeave}
108
115
  {...props?.circle}
109
116
  class={cls('stroke-surface-100', props?.circle?.class)}
110
117
  />
@@ -118,13 +118,13 @@
118
118
  </script>
119
119
 
120
120
  {#if fill || className}
121
- <Rect {...rect} {fill} class={cls(props?.rect?.class, className)} />
121
+ <Rect {...rect} {...props?.rect} {fill} class={cls(props?.rect?.class, className)} />
122
122
  {/if}
123
123
 
124
124
  {#if gradient}
125
125
  <LinearGradient {...gradient}>
126
126
  {#snippet children({ gradient })}
127
- <Rect {...rect} fill={gradient} class={props?.rect?.class} />
127
+ <Rect {...rect} {...props?.rect} fill={gradient} />
128
128
  {/snippet}
129
129
  </LinearGradient>
130
130
  {/if}
@@ -132,7 +132,7 @@
132
132
  {#if pattern}
133
133
  <Pattern {...pattern}>
134
134
  {#snippet children({ pattern })}
135
- <Rect {...rect} fill={pattern} class={props?.rect?.class} />
135
+ <Rect {...rect} {...props?.rect} fill={pattern} />
136
136
  {/snippet}
137
137
  </Pattern>
138
138
  {/if}
@@ -401,13 +401,13 @@
401
401
  <Spline
402
402
  pathData={trackArc()}
403
403
  stroke="none"
404
- bind:splineRef={trackRef}
404
+ bind:pathRef={trackRef}
405
405
  {...extractLayerProps(track, 'arc-track')}
406
406
  />
407
407
  {/if}
408
408
 
409
409
  <Spline
410
- bind:splineRef={ref}
410
+ bind:pathRef={ref}
411
411
  pathData={arc()}
412
412
  transform="translate({xOffset}, {yOffset})"
413
413
  {fill}
@@ -43,6 +43,18 @@
43
43
  */
44
44
  ticks?: TicksConfig;
45
45
 
46
+ /**
47
+ * Width or height of each tick in pixels (enabling responsive count)
48
+ */
49
+ tickSpacing?: number;
50
+
51
+ /**
52
+ * Whether to render tick labels on multiple lines for additional context
53
+ *
54
+ * @default false
55
+ */
56
+ tickMultiline?: boolean;
57
+
46
58
  /**
47
59
  * Length of the tick line
48
60
  * @default 4
@@ -59,7 +71,7 @@
59
71
  /**
60
72
  * Format tick labels
61
73
  */
62
- format?: FormatType;
74
+ format?: FormatType | FormatConfig;
63
75
 
64
76
  /**
65
77
  * Props to apply to each tick label
@@ -84,7 +96,7 @@
84
96
  transitionInParams?: TransitionParams<In>;
85
97
 
86
98
  /**
87
- * Scale for the axis
99
+ * Override scale for the axis
88
100
  */
89
101
  scale?: any;
90
102
 
@@ -114,7 +126,7 @@
114
126
  import { extent } from 'd3-array';
115
127
  import { pointRadial } from 'd3-shape';
116
128
 
117
- import { format as formatValue, type FormatType } from '@layerstack/utils';
129
+ import { type FormatType, type FormatConfig } from '@layerstack/utils';
118
130
  import { cls } from '@layerstack/tailwind';
119
131
 
120
132
  import Group, { type GroupProps } from './Group.svelte';
@@ -126,7 +138,7 @@
126
138
  import { getChartContext } from './Chart.svelte';
127
139
  import { extractLayerProps, layerClass } from '../utils/attributes.js';
128
140
  import { type MotionProp } from '../utils/motion.svelte.js';
129
- import { resolveTickVals, type TicksConfig } from '../utils/ticks.js';
141
+ import { resolveTickFormat, resolveTickVals, type TicksConfig } from '../utils/ticks.js';
130
142
 
131
143
  let {
132
144
  placement,
@@ -136,6 +148,12 @@
136
148
  rule = false,
137
149
  grid = false,
138
150
  ticks,
151
+ tickSpacing = ['top', 'bottom', 'angle'].includes(placement)
152
+ ? 80
153
+ : ['left', 'right', 'radius'].includes(placement)
154
+ ? 50
155
+ : undefined,
156
+ tickMultiline = false,
139
157
  tickLength = 4,
140
158
  tickMarks = true,
141
159
  format,
@@ -165,36 +183,70 @@
165
183
  const scale = $derived(
166
184
  scaleProp ?? (['horizontal', 'angle'].includes(orientation) ? ctx.xScale : ctx.yScale)
167
185
  );
186
+ const interval = $derived(
187
+ ['horizontal', 'angle'].includes(orientation) ? ctx.xInterval : ctx.yInterval
188
+ );
168
189
 
169
190
  const xRangeMinMax = $derived(extent<number>(ctx.xRange)) as [number, number];
170
191
  const yRangeMinMax = $derived(extent<number>(ctx.yRange)) as [number, number];
171
192
 
172
- const tickVals = $derived(resolveTickVals(scale, ticks, placement));
193
+ const ctxSize = $derived(
194
+ orientation === 'vertical'
195
+ ? ctx.height
196
+ : orientation === 'horizontal'
197
+ ? ctx.width
198
+ : orientation === 'radius'
199
+ ? ctx.height / 2
200
+ : orientation === 'angle'
201
+ ? ctx.width
202
+ : null
203
+ );
204
+
205
+ const tickCount = $derived(
206
+ typeof ticks === 'number'
207
+ ? ticks
208
+ : tickSpacing && ctxSize
209
+ ? Math.round(ctxSize / tickSpacing)
210
+ : undefined
211
+ );
212
+ const tickVals = $derived(resolveTickVals(scale, ticks, tickCount, interval));
213
+ const tickFormat = $derived(
214
+ resolveTickFormat({
215
+ scale,
216
+ ticks,
217
+ count: tickCount,
218
+ formatType: format,
219
+ multiline: tickMultiline,
220
+ placement,
221
+ })
222
+ );
173
223
 
174
224
  function getCoords(tick: any) {
175
225
  switch (placement) {
176
226
  case 'top':
177
- return {
178
- x: scale(tick) + (isScaleBand(scale) ? scale.bandwidth() / 2 : 0),
179
- y: yRangeMinMax[0],
180
- };
181
-
182
227
  case 'bottom':
183
228
  return {
184
- x: scale(tick) + (isScaleBand(scale) ? scale.bandwidth() / 2 : 0),
185
- y: yRangeMinMax[1],
229
+ x:
230
+ scale(tick) +
231
+ (isScaleBand(scale)
232
+ ? scale.bandwidth() / 2
233
+ : ctx.xInterval
234
+ ? (scale(ctx.xInterval.offset(tick)) - scale(tick)) / 2 // offset 1/2 width of time interval
235
+ : 0),
236
+ y: placement === 'top' ? yRangeMinMax[0] : yRangeMinMax[1],
186
237
  };
187
238
 
188
239
  case 'left':
189
- return {
190
- x: xRangeMinMax[0],
191
- y: scale(tick) + (isScaleBand(scale) ? scale.bandwidth() / 2 : 0),
192
- };
193
-
194
240
  case 'right':
195
241
  return {
196
- x: xRangeMinMax[1],
197
- y: scale(tick) + (isScaleBand(scale) ? scale.bandwidth() / 2 : 0),
242
+ x: placement === 'left' ? xRangeMinMax[0] : xRangeMinMax[1],
243
+ y:
244
+ scale(tick) +
245
+ (isScaleBand(scale)
246
+ ? scale.bandwidth() / 2
247
+ : ctx.yInterval
248
+ ? (scale(ctx.yInterval.offset(tick)) - scale(tick)) / 2 // offset 1/2 height of time interval
249
+ : 0),
198
250
  };
199
251
 
200
252
  case 'angle':
@@ -217,14 +269,14 @@
217
269
  return {
218
270
  textAnchor: 'middle',
219
271
  verticalAnchor: 'end',
220
- dy: -tickLength - 2, // manually adjusted until Text supports custom styles
272
+ dy: -tickLength,
221
273
  };
222
274
 
223
275
  case 'bottom':
224
276
  return {
225
277
  textAnchor: 'middle',
226
278
  verticalAnchor: 'start',
227
- dy: tickLength, // manually adjusted until Text supports custom styles
279
+ dy: tickLength,
228
280
  };
229
281
 
230
282
  case 'left':
@@ -232,7 +284,6 @@
232
284
  textAnchor: 'end',
233
285
  verticalAnchor: 'middle',
234
286
  dx: -tickLength,
235
- dy: -2, // manually adjusted until Text supports custom styles
236
287
  };
237
288
 
238
289
  case 'right':
@@ -240,7 +291,6 @@
240
291
  textAnchor: 'start',
241
292
  verticalAnchor: 'middle',
242
293
  dx: tickLength,
243
- dy: -2, // manually adjusted until Text supports custom styles
244
294
  };
245
295
 
246
296
  case 'angle':
@@ -255,7 +305,7 @@
255
305
  ? 'end'
256
306
  : 'start',
257
307
  verticalAnchor: 'middle',
258
- dx: Math.sin(xValue) * (tickLength + 2),
308
+ dx: Math.sin(xValue) * tickLength,
259
309
  dy: -Math.cos(xValue) * (tickLength + 4), // manually adjusted until Text supports custom styles
260
310
  };
261
311
 
@@ -264,7 +314,6 @@
264
314
  textAnchor: 'middle',
265
315
  verticalAnchor: 'middle',
266
316
  dx: 2,
267
- dy: -2, // manually adjusted until Text supports custom styles
268
317
  };
269
318
  }
270
319
  }
@@ -317,13 +366,15 @@
317
366
  });
318
367
 
319
368
  const resolvedLabelProps = $derived({
320
- value: typeof label === 'function' ? '' : undefined,
369
+ value: typeof label === 'function' ? '' : label,
321
370
  x: resolvedLabelX,
322
371
  y: resolvedLabelY,
323
372
  textAnchor: resolvedLabelTextAnchor,
324
373
  verticalAnchor: resolvedLabelVerticalAnchor,
325
374
  rotate: orientation === 'vertical' && labelPlacement === 'middle' ? -90 : 0,
326
- capHeight: '.5rem', // text-[10px]
375
+ // complement 10px text (until Text supports custom styles)
376
+ capHeight: '7px',
377
+ lineHeight: '11px',
327
378
  ...labelProps,
328
379
  class: cls(
329
380
  layerClass('axis-label'),
@@ -356,7 +407,7 @@
356
407
  <Text {...resolvedLabelProps} />
357
408
  {/if}
358
409
 
359
- {#each tickVals as tick, index (tick.toString())}
410
+ {#each tickVals as tick, index (tick.valueOf())}
360
411
  {@const tickCoords = getCoords(tick)}
361
412
  {@const [radialTickCoordsX, radialTickCoordsY] = pointRadial(tickCoords.x, tickCoords.y)}
362
413
  {@const [radialTickMarkCoordsX, radialTickMarkCoordsY] = pointRadial(
@@ -366,9 +417,12 @@
366
417
  {@const resolvedTickLabelProps = {
367
418
  x: orientation === 'angle' ? radialTickCoordsX : tickCoords.x,
368
419
  y: orientation === 'angle' ? radialTickCoordsY : tickCoords.y,
369
- value: formatValue(tick, format ?? scale.tickFormat?.() ?? ((v) => v)),
420
+ value: tickFormat(tick, index),
370
421
  ...getDefaultTickLabelProps(tick),
371
422
  motion,
423
+ // complement 10px text (until Text supports custom styles)
424
+ capHeight: '7px',
425
+ lineHeight: '11px',
372
426
  ...tickLabelProps,
373
427
  class: cls(
374
428
  layerClass('axis-tick-label'),
@@ -36,6 +36,16 @@ export type AxisPropsWithoutHTML<In extends Transition = Transition> = {
36
36
  * Control the number of ticks
37
37
  */
38
38
  ticks?: TicksConfig;
39
+ /**
40
+ * Width or height of each tick in pixels (enabling responsive count)
41
+ */
42
+ tickSpacing?: number;
43
+ /**
44
+ * Whether to render tick labels on multiple lines for additional context
45
+ *
46
+ * @default false
47
+ */
48
+ tickMultiline?: boolean;
39
49
  /**
40
50
  * Length of the tick line
41
51
  * @default 4
@@ -50,7 +60,7 @@ export type AxisPropsWithoutHTML<In extends Transition = Transition> = {
50
60
  /**
51
61
  * Format tick labels
52
62
  */
53
- format?: FormatType;
63
+ format?: FormatType | FormatConfig;
54
64
  /**
55
65
  * Props to apply to each tick label
56
66
  */
@@ -73,7 +83,7 @@ export type AxisPropsWithoutHTML<In extends Transition = Transition> = {
73
83
  */
74
84
  transitionInParams?: TransitionParams<In>;
75
85
  /**
76
- * Scale for the axis
86
+ * Override scale for the axis
77
87
  */
78
88
  scale?: any;
79
89
  /**
@@ -92,7 +102,7 @@ export type AxisPropsWithoutHTML<In extends Transition = Transition> = {
92
102
  export type AxisProps<In extends Transition = Transition> = AxisPropsWithoutHTML<In> & Without<GroupProps, AxisPropsWithoutHTML<In>>;
93
103
  import { type ComponentProps, type Snippet } from 'svelte';
94
104
  import type { SVGAttributes } from 'svelte/elements';
95
- import { type FormatType } from '@layerstack/utils';
105
+ import { type FormatType, type FormatConfig } from '@layerstack/utils';
96
106
  import { type GroupProps } from './Group.svelte';
97
107
  import Rule from './Rule.svelte';
98
108
  import Text from './Text.svelte';
@@ -81,7 +81,7 @@
81
81
  import Rect from './Rect.svelte';
82
82
  import Spline from './Spline.svelte';
83
83
 
84
- import { isScaleBand } from '../utils/scales.svelte.js';
84
+ import { isScaleBand, isScaleTime } from '../utils/scales.svelte.js';
85
85
  import { accessor, type Accessor } from '../utils/common.js';
86
86
  import { getChartContext } from './Chart.svelte';
87
87
  import type { CommonStyleProps, Without } from '../utils/types.js';
@@ -127,7 +127,7 @@
127
127
 
128
128
  const dimensions = $derived(getDimensions(data) ?? { x: 0, y: 0, width: 0, height: 0 });
129
129
 
130
- const isVertical = $derived(isScaleBand(ctx.xScale));
130
+ const isVertical = $derived(isScaleBand(ctx.xScale) || isScaleTime(ctx.xScale));
131
131
  const valueAccessor = $derived(accessor(isVertical ? y : x));
132
132
  const value = $derived(valueAccessor(data));
133
133
  const resolvedValue = $derived(Array.isArray(value) ? greatestAbs(value) : value);
@@ -151,16 +151,20 @@
151
151
  const bottomRight = $derived(['all', 'bottom', 'right', 'bottom-right'].includes(rounded));
152
152
  const width = $derived(dimensions.width);
153
153
  const height = $derived(dimensions.height);
154
- const diameter = $derived(2 * radius);
154
+
155
+ // Clamp radius to prevent extending beyond bounding box
156
+ const r = $derived(Math.min(radius, width / 2, height / 2));
157
+ const diameter = $derived(2 * r);
158
+
155
159
  const pathData = $derived(
156
- `M${dimensions.x + radius},${dimensions.y} h${width - diameter}
157
- ${topRight ? `a${radius},${radius} 0 0 1 ${radius},${radius}` : `h${radius}v${radius}`}
160
+ `M${dimensions.x + r},${dimensions.y} h${width - diameter}
161
+ ${topRight ? `a${r},${r} 0 0 1 ${r},${r}` : `h${r}v${r}`}
158
162
  v${height - diameter}
159
- ${bottomRight ? `a${radius},${radius} 0 0 1 ${-radius},${radius}` : `v${radius}h${-radius}`}
163
+ ${bottomRight ? `a${r},${r} 0 0 1 ${-r},${r}` : `v${r}h${-r}`}
160
164
  h${diameter - width}
161
- ${bottomLeft ? `a${radius},${radius} 0 0 1 ${-radius},${-radius}` : `h${-radius}v${-radius}`}
165
+ ${bottomLeft ? `a${r},${r} 0 0 1 ${-r},${-r}` : `h${-r}v${-r}`}
162
166
  v${diameter - height}
163
- ${topLeft ? `a${radius},${radius} 0 0 1 ${radius},${-radius}` : `v${-radius}h${radius}`}
167
+ ${topLeft ? `a${r},${r} 0 0 1 ${r},${-r}` : `v${-r}h${r}`}
164
168
  z`
165
169
  .split('\n')
166
170
  .join('')
@@ -14,9 +14,9 @@
14
14
 
15
15
  /**
16
16
  * The default children snippet which provides
17
- * the id and url for the filter.
17
+ * the id for the filter.
18
18
  */
19
- children?: Snippet<[{ id: string; url: string }]>;
19
+ children?: Snippet;
20
20
  };
21
21
  </script>
22
22
 
@@ -42,7 +42,9 @@
42
42
 
43
43
  {#if children}
44
44
  <g filter="url(#{id})" class={layerClass('blur-g')}>
45
- {@render children({ id, url: `url(#${id})` })}
45
+ {@render children()}
46
46
  </g>
47
47
  {/if}
48
+ {:else if children}
49
+ {@render children()}
48
50
  {/if}
@@ -11,12 +11,9 @@ export type BlurProps = {
11
11
  stdDeviation?: number;
12
12
  /**
13
13
  * The default children snippet which provides
14
- * the id and url for the filter.
14
+ * the id for the filter.
15
15
  */
16
- children?: Snippet<[{
17
- id: string;
18
- url: string;
19
- }]>;
16
+ children?: Snippet;
20
17
  };
21
18
  import type { Snippet } from 'svelte';
22
19
  declare const Blur: import("svelte").Component<BlurProps, {}, "">;
@@ -319,7 +319,7 @@
319
319
  _range.width < RESET_THRESHOLD ||
320
320
  _range.height < RESET_THRESHOLD
321
321
  ) {
322
- // Clicked on frame, or pointer delta was <1
322
+ // Clicked on frame, or pointer delta was less than threshold (default: 1px)
323
323
  if (ignoreResetClick) {
324
324
  logger.debug('ignoring frame click reset');
325
325
  } else {
@@ -36,14 +36,14 @@
36
36
  /**
37
37
  * Props to pass to the `<text>` element for month labels.
38
38
  */
39
- monthLabel?: Partial<ComponentProps<typeof Text>>;
39
+ monthLabel?: boolean | Partial<ComponentProps<typeof Text>>;
40
40
 
41
41
  /**
42
42
  * Tooltip context to setup mouse events to show tooltip for related data
43
43
  */
44
44
  tooltipContext?: TooltipContextValue;
45
45
 
46
- children?: Snippet<[{ cells: CalendarCell[] }]>;
46
+ children?: Snippet<[{ cells: CalendarCell[]; cellSize: [number, number] }]>;
47
47
  } & Omit<
48
48
  RectPropsWithoutHTML,
49
49
  'children' | 'x' | 'y' | 'width' | 'height' | 'fill' | 'onpointermove' | 'onpointerleave'
@@ -57,7 +57,7 @@
57
57
  import { type ComponentProps, type Snippet } from 'svelte';
58
58
  import { timeDays, timeMonths, timeWeek, timeYear } from 'd3-time';
59
59
  import { index } from 'd3-array';
60
- import { format } from 'date-fns';
60
+ import { format } from '@layerstack/utils';
61
61
 
62
62
  import Rect, { type RectPropsWithoutHTML } from './Rect.svelte';
63
63
  import type { TooltipContextValue } from './tooltip/TooltipContext.svelte';
@@ -74,9 +74,9 @@
74
74
  start,
75
75
  cellSize: cellSizeProp,
76
76
  monthPath = false,
77
+ monthLabel = true,
77
78
  tooltipContext: tooltip,
78
79
  children,
79
- monthLabel,
80
80
  ...restProps
81
81
  }: CalendarPropsWithoutHTML = $props();
82
82
 
@@ -117,7 +117,7 @@
117
117
  </script>
118
118
 
119
119
  {#if children}
120
- {@render children({ cells })}
120
+ {@render children({ cells, cellSize })}
121
121
  {:else}
122
122
  {#each cells as cell}
123
123
  <Rect
@@ -136,11 +136,15 @@
136
136
  {#if monthPath}
137
137
  {#each yearMonths as date}
138
138
  <MonthPath {date} {cellSize} {...extractLayerProps(monthPath, 'calendar-month-path')} />
139
+ {/each}
140
+ {/if}
139
141
 
142
+ {#if monthLabel}
143
+ {#each yearMonths as date}
140
144
  <Text
141
145
  x={timeWeek.count(timeYear.floor(date), timeWeek.ceil(date)) * cellSize[0]}
142
146
  y={-4}
143
- value={format(date, 'MMM')}
147
+ value={format(date, 'month', { variant: 'short' })}
144
148
  {...extractLayerProps(monthLabel, 'calendar-month-label', 'text-xs')}
145
149
  />
146
150
  {/each}
@@ -30,13 +30,14 @@ export type CalendarPropsWithoutHTML = {
30
30
  /**
31
31
  * Props to pass to the `<text>` element for month labels.
32
32
  */
33
- monthLabel?: Partial<ComponentProps<typeof Text>>;
33
+ monthLabel?: boolean | Partial<ComponentProps<typeof Text>>;
34
34
  /**
35
35
  * Tooltip context to setup mouse events to show tooltip for related data
36
36
  */
37
37
  tooltipContext?: TooltipContextValue;
38
38
  children?: Snippet<[{
39
39
  cells: CalendarCell[];
40
+ cellSize: [number, number];
40
41
  }]>;
41
42
  } & Omit<RectPropsWithoutHTML, 'children' | 'x' | 'y' | 'width' | 'height' | 'fill' | 'onpointermove' | 'onpointerleave'>;
42
43
  export type CalendarProps = CalendarPropsWithoutHTML & Without<SVGAttributes<SVGRectElement>, CalendarPropsWithoutHTML>;
@@ -7,6 +7,7 @@
7
7
  createScale,
8
8
  getRange,
9
9
  isScaleBand,
10
+ isScaleTime,
10
11
  makeAccessor,
11
12
  type AnyScale,
12
13
  type DomainType,
@@ -40,6 +41,7 @@
40
41
  import TransformContext, { type TransformContextValue } from './TransformContext.svelte';
41
42
  import BrushContext, { type BrushContextValue } from './BrushContext.svelte';
42
43
  import { layerClass } from '../utils/attributes.js';
44
+ import type { TimeInterval } from 'd3-time';
43
45
 
44
46
  const defaultPadding = { top: 0, right: 0, bottom: 0, left: 0 };
45
47
 
@@ -149,6 +151,8 @@
149
151
  cGet: (d: T) => any;
150
152
  x1Get: (d: T) => any;
151
153
  y1Get: (d: T) => any;
154
+ xInterval: TimeInterval | null;
155
+ yInterval: TimeInterval | null;
152
156
  radial: boolean;
153
157
  tooltip: TooltipContextValue<T>;
154
158
  geo: GeoContextValue;
@@ -640,6 +644,16 @@
640
644
  */
641
645
  yBaseline?: number | null;
642
646
 
647
+ /**
648
+ * Time interval to use for the x-axis when using a time scale.
649
+ */
650
+ xInterval?: TimeInterval | null;
651
+
652
+ /**
653
+ * Time interval to use for the y-axis when using a time scale.
654
+ */
655
+ yInterval?: TimeInterval | null;
656
+
643
657
  /* Props passed to ChartContext */
644
658
 
645
659
  /**
@@ -738,6 +752,8 @@
738
752
  rRange: rRangeProp,
739
753
  xBaseline = null,
740
754
  yBaseline = null,
755
+ xInterval = null,
756
+ yInterval = null,
741
757
  meta = {},
742
758
  children: _children,
743
759
  radial = false,
@@ -780,6 +796,12 @@
780
796
 
781
797
  const _xDomain: DomainType | undefined = $derived.by(() => {
782
798
  if (xDomainProp !== undefined) return xDomainProp;
799
+
800
+ if (xInterval != null && Array.isArray(data) && data.length > 0) {
801
+ const lastXValue = accessor(xProp)(data[data.length - 1]);
802
+ return [null, xInterval.offset(lastXValue)];
803
+ }
804
+
783
805
  if (xBaseline != null && Array.isArray(data)) {
784
806
  const xValues = data.flatMap(accessor(xProp));
785
807
  return [min([xBaseline, ...xValues]), max([xBaseline, ...xValues])];
@@ -788,6 +810,12 @@
788
810
 
789
811
  const _yDomain: DomainType | undefined = $derived.by(() => {
790
812
  if (yDomainProp !== undefined) return yDomainProp;
813
+
814
+ if (yInterval != null && Array.isArray(data) && data.length > 0) {
815
+ const lastYValue = accessor(yProp)(data[data.length - 1]);
816
+ return [null, yInterval.offset(lastYValue)];
817
+ }
818
+
791
819
  if (yBaseline != null && Array.isArray(data)) {
792
820
  const yValues = data.flatMap(accessor(yProp));
793
821
  return [min([yBaseline, ...yValues]), max([yBaseline, ...yValues])];
@@ -798,7 +826,9 @@
798
826
  _yRangeProp ?? (radial ? ({ height }: { height: number }) => [0, height / 2] : undefined)
799
827
  );
800
828
 
801
- const yReverse = $derived(yScaleProp ? !isScaleBand(yScaleProp) : true);
829
+ const yReverse = $derived(
830
+ yScaleProp ? !isScaleBand(yScaleProp) && !isScaleTime(yScaleProp) : true
831
+ );
802
832
 
803
833
  const x = $derived(makeAccessor(xProp));
804
834
  const y = $derived(makeAccessor(yProp));
@@ -844,12 +874,12 @@
844
874
  if (verbose === true) {
845
875
  if (width <= 0 && isMounted === true) {
846
876
  console.warn(
847
- '[LayerChart] Target div has zero or negative width. Did you forget to set an explicit width in CSS on the container?'
877
+ `[LayerChart] Target div has zero or negative width (${width}). Did you forget to set an explicit width in CSS on the container?`
848
878
  );
849
879
  }
850
880
  if (height <= 0 && isMounted === true) {
851
881
  console.warn(
852
- '[LayerChart] Target div has zero or negative height. Did you forget to set an explicit height in CSS on the container?'
882
+ `[LayerChart] Target div has zero or negative height (${height}). Did you forget to set an explicit height in CSS on the container?`
853
883
  );
854
884
  }
855
885
  }
@@ -1247,6 +1277,12 @@
1247
1277
  get y1Scale() {
1248
1278
  return y1Scale;
1249
1279
  },
1280
+ get xInterval() {
1281
+ return xInterval;
1282
+ },
1283
+ get yInterval() {
1284
+ return yInterval;
1285
+ },
1250
1286
  get radial() {
1251
1287
  return radial;
1252
1288
  },
@@ -8,6 +8,7 @@ import type { HierarchyNode } from 'd3-hierarchy';
8
8
  import type { SankeyGraph } from 'd3-sankey';
9
9
  import TransformContext, { type TransformContextValue } from './TransformContext.svelte';
10
10
  import BrushContext, { type BrushContextValue } from './BrushContext.svelte';
11
+ import type { TimeInterval } from 'd3-time';
11
12
  export type ChartResizeDetail = {
12
13
  width: number;
13
14
  height: number;
@@ -81,6 +82,8 @@ export type ChartContextValue<T = any, XScale extends AnyScale = AnyScale, YScal
81
82
  cGet: (d: T) => any;
82
83
  x1Get: (d: T) => any;
83
84
  y1Get: (d: T) => any;
85
+ xInterval: TimeInterval | null;
86
+ yInterval: TimeInterval | null;
84
87
  radial: boolean;
85
88
  tooltip: TooltipContextValue<T>;
86
89
  geo: GeoContextValue;
@@ -484,6 +487,14 @@ export type ChartPropsWithoutHTML<T, XScale extends AnyScale = AnyScale, YScale
484
487
  * @default null
485
488
  */
486
489
  yBaseline?: number | null;
490
+ /**
491
+ * Time interval to use for the x-axis when using a time scale.
492
+ */
493
+ xInterval?: TimeInterval | null;
494
+ /**
495
+ * Time interval to use for the y-axis when using a time scale.
496
+ */
497
+ yInterval?: TimeInterval | null;
487
498
  /**
488
499
  * Use radial instead of cartesian coordinates, mapping `x` to `angle` and `y`` to radial.
489
500
  * Radial lines are positioned relative to the origin, use transform (ex. `<Group center>`)