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.
- package/dist/components/AnnotationPoint.svelte +16 -9
- package/dist/components/AnnotationRange.svelte +3 -3
- package/dist/components/Arc.svelte +2 -2
- package/dist/components/Axis.svelte +83 -29
- package/dist/components/Axis.svelte.d.ts +13 -3
- package/dist/components/Bar.svelte +12 -8
- package/dist/components/Blur.svelte +5 -3
- package/dist/components/Blur.svelte.d.ts +2 -5
- package/dist/components/BrushContext.svelte +1 -1
- package/dist/components/Calendar.svelte +10 -6
- package/dist/components/Calendar.svelte.d.ts +2 -1
- package/dist/components/Chart.svelte +39 -3
- package/dist/components/Chart.svelte.d.ts +11 -0
- package/dist/components/Connector.svelte +2 -2
- package/dist/components/Connector.svelte.d.ts +1 -1
- package/dist/components/Ellipse.svelte +187 -0
- package/dist/components/Ellipse.svelte.d.ts +64 -0
- package/dist/components/ForceSimulation.svelte +184 -50
- package/dist/components/ForceSimulation.svelte.d.ts +88 -21
- package/dist/components/GeoPath.svelte +12 -5
- package/dist/components/GeoPoint.svelte +1 -2
- package/dist/components/GeoSpline.svelte +4 -4
- package/dist/components/GeoSpline.svelte.d.ts +1 -1
- package/dist/components/Group.svelte +2 -2
- package/dist/components/Highlight.svelte +9 -6
- package/dist/components/Hull.svelte +1 -1
- package/dist/components/Labels.svelte +3 -2
- package/dist/components/Labels.svelte.d.ts +2 -2
- package/dist/components/Legend.svelte +19 -12
- package/dist/components/Legend.svelte.d.ts +5 -5
- package/dist/components/MonthPath.svelte +14 -11
- package/dist/components/MonthPath.svelte.d.ts +4 -3
- package/dist/components/Polygon.svelte +285 -0
- package/dist/components/Polygon.svelte.d.ts +115 -0
- package/dist/components/RadialGradient.svelte +1 -3
- package/dist/components/Spline.svelte +30 -18
- package/dist/components/Spline.svelte.d.ts +12 -4
- package/dist/components/Text.svelte +62 -60
- package/dist/components/Text.svelte.d.ts +6 -0
- package/dist/components/TransformControls.svelte +16 -20
- package/dist/components/Treemap.svelte +63 -26
- package/dist/components/Treemap.svelte.d.ts +11 -11
- package/dist/components/Voronoi.svelte +51 -33
- package/dist/components/Voronoi.svelte.d.ts +3 -1
- package/dist/components/charts/ArcChart.svelte +5 -3
- package/dist/components/charts/AreaChart.svelte +11 -11
- package/dist/components/charts/BarChart.svelte +72 -53
- package/dist/components/charts/DefaultTooltip.svelte +1 -1
- package/dist/components/charts/LineChart.svelte +10 -6
- package/dist/components/charts/PieChart.svelte +5 -3
- package/dist/components/charts/ScatterChart.svelte +2 -3
- package/dist/components/charts/utils.svelte.d.ts +2 -2
- package/dist/components/charts/utils.svelte.js +5 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +5 -1
- package/dist/components/layout/Canvas.svelte +67 -49
- package/dist/components/layout/Canvas.svelte.d.ts +6 -0
- package/dist/components/layout/Layer.svelte +6 -4
- package/dist/components/layout/Layer.svelte.d.ts +6 -4
- package/dist/components/tooltip/Tooltip.svelte +14 -7
- package/dist/components/tooltip/TooltipContext.svelte +136 -43
- package/dist/components/tooltip/TooltipContext.svelte.d.ts +3 -3
- package/dist/components/tooltip/TooltipHeader.svelte +5 -4
- package/dist/components/tooltip/TooltipHeader.svelte.d.ts +3 -3
- package/dist/components/tooltip/TooltipItem.svelte +5 -4
- package/dist/components/tooltip/TooltipItem.svelte.d.ts +3 -3
- package/dist/components/tooltip/TooltipList.svelte +1 -1
- package/dist/components/tooltip/tooltipMetaContext.d.ts +2 -2
- package/dist/docs/Blockquote.svelte +6 -4
- package/dist/docs/Blockquote.svelte.d.ts +4 -19
- package/dist/docs/Code.svelte +20 -12
- package/dist/docs/Code.svelte.d.ts +9 -23
- package/dist/docs/Header1.svelte +4 -2
- package/dist/docs/Header1.svelte.d.ts +4 -28
- package/dist/docs/Json.svelte +11 -3
- package/dist/docs/Json.svelte.d.ts +9 -21
- package/dist/docs/Layout.svelte +10 -7
- package/dist/docs/Layout.svelte.d.ts +4 -19
- package/dist/docs/Link.svelte +7 -3
- package/dist/docs/Link.svelte.d.ts +4 -38
- package/dist/docs/Preview.svelte +6 -3
- package/dist/docs/TilesetField.svelte +20 -19
- package/dist/docs/TilesetField.svelte.d.ts +5 -22
- package/dist/docs/ViewSourceButton.svelte +9 -6
- package/dist/docs/ViewSourceButton.svelte.d.ts +7 -21
- package/dist/utils/arcText.svelte.js +4 -4
- package/dist/utils/array.d.ts +11 -0
- package/dist/utils/array.js +23 -0
- package/dist/utils/array.test.d.ts +1 -0
- package/dist/utils/array.test.js +200 -0
- package/dist/utils/canvas.d.ts +77 -0
- package/dist/utils/canvas.js +105 -41
- package/dist/utils/genData.d.ts +14 -0
- package/dist/utils/genData.js +24 -6
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/path.d.ts +10 -0
- package/dist/utils/path.js +30 -0
- package/dist/utils/rect.svelte.d.ts +2 -2
- package/dist/utils/rect.svelte.js +69 -1
- package/dist/utils/scales.svelte.d.ts +3 -2
- package/dist/utils/scales.svelte.js +7 -3
- package/dist/utils/shape.d.ts +43 -0
- package/dist/utils/shape.js +59 -0
- package/dist/utils/string.d.ts +49 -0
- package/dist/utils/string.js +4 -2
- package/dist/utils/ticks.d.ts +15 -4
- package/dist/utils/ticks.js +144 -158
- package/dist/utils/ticks.test.js +11 -16
- package/dist/utils/treemap.d.ts +1 -1
- package/package.json +27 -25
- package/dist/utils/object.js +0 -2
|
@@ -88,23 +88,30 @@
|
|
|
88
88
|
? 'start'
|
|
89
89
|
: 'middle',
|
|
90
90
|
});
|
|
91
|
-
</script>
|
|
92
91
|
|
|
93
|
-
|
|
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
|
-
|
|
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}
|
|
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}
|
|
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:
|
|
404
|
+
bind:pathRef={trackRef}
|
|
405
405
|
{...extractLayerProps(track, 'arc-track')}
|
|
406
406
|
/>
|
|
407
407
|
{/if}
|
|
408
408
|
|
|
409
409
|
<Spline
|
|
410
|
-
bind:
|
|
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
|
-
*
|
|
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 {
|
|
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
|
|
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:
|
|
185
|
-
|
|
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:
|
|
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
|
|
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,
|
|
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) *
|
|
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' ? '' :
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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
|
-
*
|
|
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
|
-
|
|
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 +
|
|
157
|
-
${topRight ? `a${
|
|
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${
|
|
163
|
+
${bottomRight ? `a${r},${r} 0 0 1 ${-r},${r}` : `v${r}h${-r}`}
|
|
160
164
|
h${diameter - width}
|
|
161
|
-
${bottomLeft ? `a${
|
|
165
|
+
${bottomLeft ? `a${r},${r} 0 0 1 ${-r},${-r}` : `h${-r}v${-r}`}
|
|
162
166
|
v${diameter - height}
|
|
163
|
-
${topLeft ? `a${
|
|
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
|
|
17
|
+
* the id for the filter.
|
|
18
18
|
*/
|
|
19
|
-
children?: Snippet
|
|
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(
|
|
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
|
|
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
|
|
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 '
|
|
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, '
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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>`)
|