layerchart 0.54.0 → 0.55.0

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 (105) hide show
  1. package/dist/components/Arc.svelte +170 -144
  2. package/dist/components/Area.svelte +96 -67
  3. package/dist/components/Area.svelte.d.ts +1 -0
  4. package/dist/components/Axis.svelte +205 -155
  5. package/dist/components/Bar.svelte +72 -45
  6. package/dist/components/Bars.svelte +45 -34
  7. package/dist/components/Blur.svelte +5 -3
  8. package/dist/components/Bounds.svelte +37 -21
  9. package/dist/components/Brush.svelte +269 -112
  10. package/dist/components/Brush.svelte.d.ts +7 -0
  11. package/dist/components/Calendar.svelte +51 -38
  12. package/dist/components/Chart.svelte +295 -74
  13. package/dist/components/Chart.svelte.d.ts +17 -17
  14. package/dist/components/ChartClipPath.svelte +8 -5
  15. package/dist/components/ChartContext.svelte +243 -93
  16. package/dist/components/ChartContext.svelte.d.ts +15 -23
  17. package/dist/components/Circle.svelte +25 -16
  18. package/dist/components/CircleClipPath.svelte +16 -10
  19. package/dist/components/ClipPath.svelte +11 -7
  20. package/dist/components/ColorRamp.svelte +12 -10
  21. package/dist/components/ForceSimulation.svelte +185 -116
  22. package/dist/components/Frame.svelte +10 -6
  23. package/dist/components/GeoCircle.svelte +15 -9
  24. package/dist/components/GeoContext.svelte +109 -62
  25. package/dist/components/GeoEdgeFade.svelte +20 -14
  26. package/dist/components/GeoPath.svelte +107 -69
  27. package/dist/components/GeoPoint.svelte +32 -18
  28. package/dist/components/GeoSpline.svelte +30 -22
  29. package/dist/components/GeoTile.svelte +40 -30
  30. package/dist/components/GeoVisible.svelte +10 -7
  31. package/dist/components/Graticule.svelte +14 -8
  32. package/dist/components/Grid.svelte +75 -48
  33. package/dist/components/Group.svelte +43 -31
  34. package/dist/components/Highlight.svelte +284 -243
  35. package/dist/components/HitCanvas.svelte +75 -42
  36. package/dist/components/Hull.svelte +40 -20
  37. package/dist/components/Labels.svelte +81 -70
  38. package/dist/components/Legend.svelte +105 -74
  39. package/dist/components/Legend.svelte.d.ts +1 -1
  40. package/dist/components/Line.svelte +65 -19
  41. package/dist/components/Line.svelte.d.ts +13 -1
  42. package/dist/components/LinearGradient.svelte +21 -15
  43. package/dist/components/Link.svelte +94 -22
  44. package/dist/components/Link.svelte.d.ts +17 -1
  45. package/dist/components/Marker.svelte +81 -0
  46. package/dist/components/Marker.svelte.d.ts +28 -0
  47. package/dist/components/MonthPath.svelte +23 -16
  48. package/dist/components/MotionPath.svelte +34 -25
  49. package/dist/components/Pack.svelte +21 -14
  50. package/dist/components/Partition.svelte +35 -20
  51. package/dist/components/Pattern.svelte +8 -6
  52. package/dist/components/Pie.svelte +76 -57
  53. package/dist/components/Point.svelte +11 -7
  54. package/dist/components/Points.svelte +178 -143
  55. package/dist/components/RadialGradient.svelte +25 -18
  56. package/dist/components/Rect.svelte +33 -19
  57. package/dist/components/RectClipPath.svelte +16 -11
  58. package/dist/components/Rule.svelte +50 -42
  59. package/dist/components/Sankey.svelte +55 -30
  60. package/dist/components/Spline.svelte +167 -96
  61. package/dist/components/Spline.svelte.d.ts +15 -0
  62. package/dist/components/Text.svelte +137 -104
  63. package/dist/components/Threshold.svelte +18 -7
  64. package/dist/components/TileImage.svelte +56 -50
  65. package/dist/components/TransformContext.svelte +235 -135
  66. package/dist/components/TransformControls.svelte +57 -29
  67. package/dist/components/TransformControls.svelte.d.ts +1 -1
  68. package/dist/components/Tree.svelte +33 -23
  69. package/dist/components/Treemap.svelte +69 -41
  70. package/dist/components/Voronoi.svelte +55 -28
  71. package/dist/components/charts/AreaChart.svelte +138 -87
  72. package/dist/components/charts/AreaChart.svelte.d.ts +4 -4
  73. package/dist/components/charts/BarChart.svelte +179 -114
  74. package/dist/components/charts/BarChart.svelte.d.ts +4 -4
  75. package/dist/components/charts/LineChart.svelte +97 -53
  76. package/dist/components/charts/LineChart.svelte.d.ts +4 -4
  77. package/dist/components/charts/PieChart.svelte +104 -54
  78. package/dist/components/charts/PieChart.svelte.d.ts +3 -3
  79. package/dist/components/charts/ScatterChart.svelte +83 -48
  80. package/dist/components/charts/ScatterChart.svelte.d.ts +4 -4
  81. package/dist/components/layout/Canvas.svelte +63 -43
  82. package/dist/components/layout/Html.svelte +28 -18
  83. package/dist/components/layout/Svg.svelte +47 -32
  84. package/dist/components/tooltip/Tooltip.svelte +137 -91
  85. package/dist/components/tooltip/Tooltip.svelte.d.ts +1 -1
  86. package/dist/components/tooltip/TooltipContext.svelte +315 -249
  87. package/dist/components/tooltip/TooltipHeader.svelte +9 -3
  88. package/dist/components/tooltip/TooltipItem.svelte +17 -9
  89. package/dist/components/tooltip/TooltipList.svelte +2 -1
  90. package/dist/components/tooltip/TooltipSeparator.svelte +3 -2
  91. package/dist/docs/Blockquote.svelte +4 -3
  92. package/dist/docs/Code.svelte +15 -8
  93. package/dist/docs/CurveMenuField.svelte +17 -12
  94. package/dist/docs/GeoDebug.svelte +13 -9
  95. package/dist/docs/Header1.svelte +2 -1
  96. package/dist/docs/Json.svelte +6 -4
  97. package/dist/docs/Layout.svelte +6 -6
  98. package/dist/docs/PathDataMenuField.svelte +52 -44
  99. package/dist/docs/Preview.svelte +39 -33
  100. package/dist/docs/TilesetField.svelte +80 -62
  101. package/dist/docs/TransformDebug.svelte +8 -5
  102. package/dist/docs/ViewSourceButton.svelte +13 -9
  103. package/dist/stores/motionStore.d.ts +1 -1
  104. package/dist/utils/scales.d.ts +3 -3
  105. package/package.json +29 -30
@@ -1,26 +1,42 @@
1
- <script>import { scaleLinear } from 'd3-scale';
2
- import { chartContext } from './ChartContext.svelte';
3
- import { motionScale } from '../utils/scales.js';
4
- const { width, height } = chartContext();
5
- export let domain = undefined;
6
- export let range = undefined;
7
- export let spring = undefined;
8
- export let tweened = undefined;
9
- function getExtents(extents, axis, fallback) {
10
- const resolvedExtents = typeof extents === 'function' ? extents({ width: $width, height: $height }) : extents;
1
+ <script lang="ts">
2
+ import { scaleLinear } from 'd3-scale';
3
+
4
+ import { chartContext } from './ChartContext.svelte';
5
+ import { motionScale } from '../utils/scales.js';
6
+
7
+ const { width, height } = chartContext();
8
+
9
+ type Extents = Partial<{ x0: number; y0: number; x1: number; y1: number }>;
10
+ type ExtentsAcccessor = (dimensions: { width: number; height: number }) => Extents;
11
+
12
+ export let domain: Extents | ExtentsAcccessor | null | undefined = undefined;
13
+ export let range: Extents | ExtentsAcccessor | null | undefined = undefined;
14
+ export let spring: boolean | Parameters<typeof motionScale>[1]['spring'] = undefined;
15
+ export let tweened: boolean | Parameters<typeof motionScale>[1]['tweened'] = undefined;
16
+
17
+ function getExtents(
18
+ extents: Extents | ExtentsAcccessor | null | undefined,
19
+ axis: 'x' | 'y',
20
+ fallback: number
21
+ ) {
22
+ const resolvedExtents =
23
+ typeof extents === 'function' ? extents({ width: $width, height: $height }) : extents;
24
+
11
25
  return [
12
- // @ts-expect-error
13
- resolvedExtents?.[axis + '0'] ?? 0, // x0 or y0
14
- // @ts-expect-error
15
- resolvedExtents?.[axis + '1'] ?? fallback, // x1 or y1, fallback as $width or $height
26
+ // @ts-expect-error
27
+ resolvedExtents?.[axis + '0'] ?? 0, // x0 or y0
28
+ // @ts-expect-error
29
+ resolvedExtents?.[axis + '1'] ?? fallback, // x1 or y1, fallback as $width or $height
16
30
  ];
17
- }
18
- const xScale = motionScale(scaleLinear, { spring, tweened });
19
- $: xScale.domain(getExtents(domain, 'x', $width));
20
- $: xScale.range(getExtents(range, 'x', $width));
21
- const yScale = motionScale(scaleLinear, { spring, tweened });
22
- $: yScale.domain(getExtents(domain, 'y', $height));
23
- $: yScale.range(getExtents(range, 'y', $height));
31
+ }
32
+
33
+ const xScale = motionScale(scaleLinear as any, { spring, tweened });
34
+ $: xScale.domain(getExtents(domain, 'x', $width));
35
+ $: xScale.range(getExtents(range, 'x', $width));
36
+
37
+ const yScale = motionScale(scaleLinear as any, { spring, tweened });
38
+ $: yScale.domain(getExtents(domain, 'y', $height));
39
+ $: yScale.range(getExtents(range, 'y', $height));
24
40
  </script>
25
41
 
26
42
  <slot xScale={$xScale} yScale={$yScale} />
@@ -1,135 +1,234 @@
1
- <script>import { createEventDispatcher } from 'svelte';
2
- import { extent } from 'd3-array';
3
- import { clamp } from '@layerstack/utils';
4
- import { cls } from '@layerstack/tailwind';
5
- import { chartContext } from './ChartContext.svelte';
6
- import Frame from './Frame.svelte';
7
- import { localPoint } from '../utils/event.js';
8
- import Group from './Group.svelte';
9
- const { xScale, yScale, width, height, padding } = chartContext();
10
- const dispatch = createEventDispatcher();
11
- /** Axis to apply brushing */
12
- export let axis = 'x';
13
- /** Size of draggable handles (width/height) */
14
- export let handleSize = 5;
15
- /** Only show range while actively brushing. Useful with `brushEnd` event */
16
- export let resetOnEnd = false;
17
- export let xDomain = $xScale.domain();
18
- export let yDomain = $yScale.domain();
19
- // Capture original domains for reset()
20
- const originalXDomain = $xScale.domain();
21
- const originalYDomain = $yScale.domain();
22
- $: [xDomainMin, xDomainMax] = extent($xScale.domain());
23
- $: [yDomainMin, yDomainMax] = extent($yScale.domain());
24
- /** Attributes passed to range <rect> element */
25
- export let range = undefined;
26
- /** Attributes passed to handle <rect> elements */
27
- export let handle = undefined;
28
- export let classes = {};
29
- let frameEl;
30
- function handler(fn) {
31
- return (e) => {
32
- const start = {
33
- xDomain: [xDomain[0] ?? xDomainMin, xDomain[1] ?? xDomainMax],
34
- yDomain: [yDomain[0] ?? yDomainMin, yDomain[1] ?? yDomainMax],
35
- value: {
36
- x: $xScale.invert?.((localPoint(frameEl, e)?.x ?? 0) - $padding.left),
37
- y: $yScale.invert?.((localPoint(frameEl, e)?.y ?? 0) - $padding.top),
38
- },
39
- };
40
- dispatch('brushStart', { xDomain, yDomain });
41
- const onPointerMove = (e) => {
42
- fn(start, {
43
- x: $xScale.invert?.((localPoint(frameEl, e)?.x ?? 0) - $padding.left),
44
- y: $yScale.invert?.((localPoint(frameEl, e)?.y ?? 0) - $padding.top),
45
- });
46
- // if (xDomain[0] === xDomain[1] || yDomain[0] === yDomain[1]) {
47
- // // Ignore?
48
- // // TODO: What about when using `x` or `y` axis?
49
- // } else {
50
- dispatch('change', { xDomain, yDomain });
51
- // }
52
- };
53
- const onPointerUp = (e) => {
54
- if (e.target === frameEl) {
55
- reset();
56
- dispatch('change', { xDomain, yDomain });
57
- }
58
- dispatch('brushEnd', { xDomain, yDomain });
59
- if (resetOnEnd) {
60
- reset();
61
- }
62
- window.removeEventListener('pointermove', onPointerMove);
63
- window.removeEventListener('pointerup', onPointerUp);
64
- };
65
- window.addEventListener('pointermove', onPointerMove);
66
- window.addEventListener('pointerup', onPointerUp);
1
+ <script lang="ts">
2
+ import { createEventDispatcher, type ComponentProps } from 'svelte';
3
+ import type { SVGAttributes } from 'svelte/elements';
4
+ import { extent, min, max } from 'd3-array';
5
+ import { clamp } from '@layerstack/utils';
6
+ import { cls } from '@layerstack/tailwind';
7
+ import { format as formatValue, type FormatType } from '@layerstack/utils';
8
+
9
+ import { chartContext } from './ChartContext.svelte';
10
+ import Frame from './Frame.svelte';
11
+ import Group from './Group.svelte';
12
+ import Text from './Text.svelte';
13
+
14
+ import { localPoint } from '../utils/event.js';
15
+
16
+ const { xScale, yScale, width, height, padding } = chartContext();
17
+
18
+ const dispatch = createEventDispatcher<{
19
+ change: { xDomain?: [any, any]; yDomain?: [any, any] };
20
+ brushStart: { xDomain?: [any, any]; yDomain?: [any, any] };
21
+ brushEnd: { xDomain?: [any, any]; yDomain?: [any, any] };
22
+ }>();
23
+
24
+ /** Axis to apply brushing */
25
+ export let axis: 'x' | 'y' | 'both' = 'x';
26
+
27
+ /** Size of draggable handles (width/height) */
28
+ export let handleSize = 5;
29
+
30
+ /** Only show range while actively brushing. Useful with `brushEnd` event */
31
+ export let resetOnEnd = false;
32
+
33
+ export let xDomain: [number | Date | null, number | Date | null] = $xScale.domain() as [
34
+ number,
35
+ number,
36
+ ];
37
+ export let yDomain: [number | Date | null, number | Date | null] = $yScale.domain() as [
38
+ number,
39
+ number,
40
+ ];
41
+
42
+ export let labels: ComponentProps<Text> | boolean = false;
43
+
44
+ // Capture original domains for reset()
45
+ const originalXDomain = $xScale.domain() as [number, number];
46
+ const originalYDomain = $yScale.domain() as [number, number];
47
+
48
+ $: [xDomainMin, xDomainMax] = extent<number>($xScale.domain()) as [number, number];
49
+ $: [yDomainMin, yDomainMax] = extent<number>($yScale.domain()) as [number, number];
50
+
51
+ /** Attributes passed to range <rect> element */
52
+ export let range: SVGAttributes<SVGRectElement> | undefined = undefined;
53
+
54
+ /** Attributes passed to handle <rect> elements */
55
+ export let handle: SVGAttributes<SVGRectElement> | undefined = undefined;
56
+
57
+ /** Apply format to labels, if shown */
58
+ export let format: FormatType | undefined = undefined;
59
+
60
+ export let classes: {
61
+ root?: string;
62
+ frame?: string;
63
+ range?: string;
64
+ handle?: string;
65
+ labels?: string;
66
+ } = {};
67
+
68
+ let frameEl: SVGRectElement;
69
+
70
+ function handler(
71
+ fn: (
72
+ start: {
73
+ xDomain: [number, number];
74
+ yDomain: [number, number];
75
+ value: { x: number; y: number };
76
+ },
77
+ value: { x: number; y: number }
78
+ ) => void
79
+ ) {
80
+ return (e: PointerEvent) => {
81
+ const start = {
82
+ xDomain: [xDomain[0] ?? xDomainMin, xDomain[1] ?? xDomainMax] as [number, number],
83
+ yDomain: [yDomain[0] ?? yDomainMin, yDomain[1] ?? yDomainMax] as [number, number],
84
+ value: {
85
+ x: $xScale.invert?.((localPoint(frameEl, e)?.x ?? 0) - $padding.left),
86
+ y: $yScale.invert?.((localPoint(frameEl, e)?.y ?? 0) - $padding.top),
87
+ },
88
+ };
89
+
90
+ dispatch('brushStart', { xDomain, yDomain });
91
+
92
+ const onPointerMove = (e: PointerEvent) => {
93
+ fn(start, {
94
+ x: $xScale.invert?.((localPoint(frameEl, e)?.x ?? 0) - $padding.left),
95
+ y: $yScale.invert?.((localPoint(frameEl, e)?.y ?? 0) - $padding.top),
96
+ });
97
+
98
+ // if (xDomain[0] === xDomain[1] || yDomain[0] === yDomain[1]) {
99
+ // // Ignore?
100
+ // // TODO: What about when using `x` or `y` axis?
101
+ // } else {
102
+ dispatch('change', { xDomain, yDomain });
103
+ // }
104
+ };
105
+
106
+ const onPointerUp = (e: PointerEvent) => {
107
+ if (e.target === frameEl) {
108
+ reset();
109
+ dispatch('change', { xDomain, yDomain });
110
+ }
111
+
112
+ dispatch('brushEnd', { xDomain, yDomain });
113
+
114
+ if (resetOnEnd) {
115
+ reset();
116
+ }
117
+
118
+ window.removeEventListener('pointermove', onPointerMove);
119
+ window.removeEventListener('pointerup', onPointerUp);
120
+ };
121
+
122
+ window.addEventListener('pointermove', onPointerMove);
123
+ window.addEventListener('pointerup', onPointerUp);
67
124
  };
68
- }
69
- const createRange = handler((start, value) => {
125
+ }
126
+
127
+ /** Add second value while maintaining `Date` or `number` type */
128
+ function add(value1: Date | number, value2: number) {
129
+ if (value1 instanceof Date) {
130
+ return new Date(value1.getTime() + value2);
131
+ } else {
132
+ return value1 + value2;
133
+ }
134
+ }
135
+
136
+ const createRange = handler((start, value) => {
70
137
  isActive = true;
138
+
71
139
  xDomain = [
72
- clamp(Math.min(start.value.x, value.x), xDomainMin, xDomainMax),
73
- clamp(Math.max(start.value.x, value.x), xDomainMin, xDomainMax),
140
+ // @ts-expect-error
141
+ clamp(min([start.value.x, value.x]), xDomainMin, xDomainMax),
142
+ // @ts-expect-error
143
+ clamp(max([start.value.x, value.x]), xDomainMin, xDomainMax),
74
144
  ];
145
+ // xDomain = [start.value.x, value.x];
146
+
75
147
  yDomain = [
76
- clamp(Math.min(start.value.y, value.y), yDomainMin, yDomainMax),
77
- clamp(Math.max(start.value.y, value.y), yDomainMin, yDomainMax),
148
+ // @ts-expect-error
149
+ clamp(min([start.value.y, value.y]), yDomainMin, yDomainMax),
150
+ // @ts-expect-error
151
+ clamp(max([start.value.y, value.y]), yDomainMin, yDomainMax),
78
152
  ];
79
- });
80
- const adjustRange = handler((start, value) => {
81
- const dx = clamp(value.x - start.value.x, xDomainMin - start.xDomain[0], xDomainMax - start.xDomain[1]);
82
- xDomain = [Number(start.xDomain[0]) + dx, Number(start.xDomain[1]) + dx];
83
- const dy = clamp(value.y - start.value.y, yDomainMin - start.yDomain[0], yDomainMax - start.yDomain[1]);
84
- yDomain = [Number(start.yDomain[0]) + dy, Number(start.yDomain[1]) + dy];
85
- });
86
- const adjustBottom = handler((start, value) => {
153
+ });
154
+
155
+ const adjustRange = handler((start, value) => {
156
+ const dx = clamp(
157
+ value.x - start.value.x,
158
+ xDomainMin - start.xDomain[0],
159
+ xDomainMax - start.xDomain[1]
160
+ );
161
+ xDomain = [add(start.xDomain[0], dx), add(start.xDomain[1], dx)];
162
+
163
+ const dy = clamp(
164
+ value.y - start.value.y,
165
+ yDomainMin - start.yDomain[0],
166
+ yDomainMax - start.yDomain[1]
167
+ );
168
+ yDomain = [add(start.yDomain[0], dy), add(start.yDomain[1], dy)];
169
+ });
170
+
171
+ const adjustBottom = handler((start, value) => {
87
172
  yDomain = [
88
- clamp(value.y > start.yDomain[1] ? start.yDomain[1] : value.y, yDomainMin, yDomainMax),
89
- clamp(value.y > start.yDomain[1] ? value.y : start.yDomain[1], yDomainMin, yDomainMax),
173
+ clamp(value.y > start.yDomain[1] ? start.yDomain[1] : value.y, yDomainMin, yDomainMax),
174
+ clamp(value.y > start.yDomain[1] ? value.y : start.yDomain[1], yDomainMin, yDomainMax),
90
175
  ];
91
- });
92
- const adjustTop = handler((start, value) => {
176
+ });
177
+
178
+ const adjustTop = handler((start, value) => {
93
179
  yDomain = [
94
- clamp(value.y < start.yDomain[1] ? value.y : start.yDomain[0], yDomainMin, yDomainMax),
95
- clamp(value.y < start.yDomain[1] ? start.yDomain[0] : value.y, yDomainMin, yDomainMax),
180
+ clamp(value.y < start.yDomain[1] ? value.y : start.yDomain[0], yDomainMin, yDomainMax),
181
+ clamp(value.y < start.yDomain[1] ? start.yDomain[0] : value.y, yDomainMin, yDomainMax),
96
182
  ];
97
- });
98
- const adjustLeft = handler((start, value) => {
183
+ });
184
+
185
+ const adjustLeft = handler((start, value) => {
99
186
  xDomain = [
100
- clamp(value.x > start.xDomain[1] ? start.xDomain[1] : value.x, xDomainMin, xDomainMax),
101
- clamp(value.x > start.xDomain[1] ? value.x : start.xDomain[1], xDomainMin, xDomainMax),
187
+ clamp(value.x > start.xDomain[1] ? start.xDomain[1] : value.x, xDomainMin, xDomainMax),
188
+ clamp(value.x > start.xDomain[1] ? value.x : start.xDomain[1], xDomainMin, xDomainMax),
102
189
  ];
103
- });
104
- const adjustRight = handler((start, value) => {
190
+ });
191
+
192
+ const adjustRight = handler((start, value) => {
105
193
  xDomain = [
106
- clamp(value.x < start.xDomain[0] ? value.x : start.xDomain[0], xDomainMin, xDomainMax),
107
- clamp(value.x < start.xDomain[0] ? start.xDomain[0] : value.x, xDomainMin, xDomainMax),
194
+ clamp(value.x < start.xDomain[0] ? value.x : start.xDomain[0], xDomainMin, xDomainMax),
195
+ clamp(value.x < start.xDomain[0] ? start.xDomain[0] : value.x, xDomainMin, xDomainMax),
108
196
  ];
109
- });
110
- function reset() {
197
+ });
198
+
199
+ function reset() {
111
200
  isActive = false;
201
+
112
202
  xDomain = originalXDomain;
113
203
  yDomain = originalYDomain;
114
- }
115
- function selectAll() {
204
+ }
205
+
206
+ function selectAll() {
116
207
  xDomain = [xDomainMin, xDomainMax];
117
208
  yDomain = [yDomainMin, yDomainMax];
118
- }
119
- $: top = $yScale(yDomain[1]);
120
- $: bottom = $yScale(yDomain[0]);
121
- $: left = $xScale(xDomain[0]);
122
- $: right = $xScale(xDomain[1]);
123
- $: rangeTop = axis === 'both' || axis === 'y' ? top : 0;
124
- $: rangeLeft = axis === 'both' || axis === 'x' ? left : 0;
125
- $: rangeWidth = axis === 'both' || axis === 'x' ? right - left : $width;
126
- $: rangeHeight = axis === 'both' || axis === 'y' ? bottom - top : $height;
127
- // Set reactively to handle cases where xDomain/yDomain are set externally (ex. `bind:xDomain`)
128
- $: isActive =
209
+ }
210
+
211
+ $: top = $yScale(yDomain[1]);
212
+ $: bottom = $yScale(yDomain[0]);
213
+ $: left = $xScale(xDomain[0]);
214
+ $: right = $xScale(xDomain[1]);
215
+
216
+ $: rangeTop = axis === 'both' || axis === 'y' ? top : 0;
217
+ $: rangeLeft = axis === 'both' || axis === 'x' ? left : 0;
218
+ $: rangeWidth = axis === 'both' || axis === 'x' ? right - left : $width;
219
+ $: rangeHeight = axis === 'both' || axis === 'y' ? bottom - top : $height;
220
+
221
+ // Set reactively to handle cases where xDomain/yDomain are set externally (ex. `bind:xDomain`)
222
+ $: isActive =
129
223
  xDomain[0]?.valueOf() !== originalXDomain[0]?.valueOf() ||
130
- xDomain[1]?.valueOf() !== originalXDomain[1]?.valueOf() ||
131
- yDomain[0]?.valueOf() !== originalYDomain[0]?.valueOf() ||
132
- yDomain[1]?.valueOf() !== originalYDomain[1]?.valueOf();
224
+ xDomain[1]?.valueOf() !== originalXDomain[1]?.valueOf() ||
225
+ yDomain[0]?.valueOf() !== originalYDomain[0]?.valueOf() ||
226
+ yDomain[1]?.valueOf() !== originalYDomain[1]?.valueOf();
227
+
228
+ /** TODO: Fix types and remove workaround (Svelte 5)*/
229
+ function any(value: any): any {
230
+ return value;
231
+ }
133
232
  </script>
134
233
 
135
234
  <g class={cls('Brush select-none', classes.root, $$props.class)}>
@@ -242,6 +341,64 @@ $: isActive =
242
341
  </Group>
243
342
  {/if}
244
343
 
344
+ <slot name="labels">
345
+ {#if labels}
346
+ {@const labelClass = cls(
347
+ 'text-xs',
348
+ classes.labels,
349
+ typeof labels === 'object' ? labels.class : null
350
+ )}
351
+
352
+ {#if axis === 'x' || axis === 'both'}
353
+ <Text
354
+ x={left}
355
+ y={rangeTop + rangeHeight / 2}
356
+ dx={-4}
357
+ textAnchor="end"
358
+ verticalAnchor="middle"
359
+ value={formatValue(any(xDomain[0]), format)}
360
+ {...typeof labels === 'object' ? labels : null}
361
+ class={labelClass}
362
+ />
363
+
364
+ <Text
365
+ x={right}
366
+ y={rangeTop + rangeHeight / 2}
367
+ dx={4}
368
+ textAnchor="start"
369
+ verticalAnchor="middle"
370
+ value={formatValue(any(xDomain[1]), format)}
371
+ {...typeof labels === 'object' ? labels : null}
372
+ class={labelClass}
373
+ />
374
+ {/if}
375
+
376
+ {#if axis === 'y' || axis === 'both'}
377
+ <Text
378
+ x={rangeLeft + rangeWidth / 2}
379
+ y={top}
380
+ dy={-4}
381
+ textAnchor="middle"
382
+ verticalAnchor="end"
383
+ value={formatValue(any(yDomain[1]), format)}
384
+ {...typeof labels === 'object' ? labels : null}
385
+ class={labelClass}
386
+ />
387
+
388
+ <Text
389
+ x={rangeLeft + rangeWidth / 2}
390
+ y={bottom}
391
+ dy={4}
392
+ textAnchor="middle"
393
+ verticalAnchor="start"
394
+ value={formatValue(any(yDomain[0]), format)}
395
+ {...typeof labels === 'object' ? labels : null}
396
+ class={labelClass}
397
+ />
398
+ {/if}
399
+ {/if}
400
+ </slot>
401
+
245
402
  <!-- TODO: Add diagonal/corner handles -->
246
403
  {/if}
247
404
  </g>
@@ -1,5 +1,8 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import { type ComponentProps } from 'svelte';
2
3
  import type { SVGAttributes } from 'svelte/elements';
4
+ import { type FormatType } from '@layerstack/utils';
5
+ import Text from './Text.svelte';
3
6
  declare const __propDef: {
4
7
  props: {
5
8
  [x: string]: any;
@@ -8,13 +11,16 @@ declare const __propDef: {
8
11
  resetOnEnd?: boolean | undefined;
9
12
  xDomain?: [number | Date | null, number | Date | null] | undefined;
10
13
  yDomain?: [number | Date | null, number | Date | null] | undefined;
14
+ labels?: (ComponentProps<Text> | boolean) | undefined;
11
15
  range?: SVGAttributes<SVGRectElement> | undefined;
12
16
  handle?: SVGAttributes<SVGRectElement> | undefined;
17
+ format?: FormatType | undefined;
13
18
  classes?: {
14
19
  root?: string;
15
20
  frame?: string;
16
21
  range?: string;
17
22
  handle?: string;
23
+ labels?: string;
18
24
  } | undefined;
19
25
  };
20
26
  events: {
@@ -43,6 +49,7 @@ declare const __propDef: {
43
49
  rangeWidth: any;
44
50
  rangeHeight: any;
45
51
  };
52
+ labels: {};
46
53
  };
47
54
  };
48
55
  export type BrushProps = typeof __propDef.props;
@@ -1,46 +1,59 @@
1
- <script>import {} from 'svelte';
2
- import { timeDays, timeMonths, timeWeek, timeYear } from 'd3-time';
3
- import { index } from 'd3-array';
4
- import { format } from 'date-fns';
5
- import { chartContext } from './ChartContext.svelte';
6
- import Rect from './Rect.svelte';
7
- import MonthPath from './MonthPath.svelte';
8
- import Text from './Text.svelte';
9
- import { chartDataArray } from '../utils/common.js';
10
- export let start;
11
- export let end;
12
- /**
13
- * Size of cell. If `number`, sets width/height as same value (square). If array, sets as [width,height]. If undefined, is derived from Chart width/height
14
- */
15
- export let cellSize = undefined;
16
- /** Enable drawing path around each month. If object, pass as props to underlying <path> */
17
- export let monthPath = false;
18
- /**
19
- * Tooltip context to setup mouse events to show tooltip for related data
20
- */
21
- export let tooltip = undefined;
22
- const { width, height, x, cGet, data, config } = chartContext();
23
- $: yearDays = timeDays(start, end);
24
- $: yearMonths = timeMonths(start, end);
25
- $: yearWeeks = timeWeek.count(start, end);
26
- $: chartCellWidth = $width / (yearWeeks + 1);
27
- $: chartCellHeight = $height / 7;
28
- $: chartCellSize = Math.min(chartCellWidth, chartCellHeight); // Use smallest to fit, and keep square aspect
29
- $: [cellWidth, cellHeight] = Array.isArray(cellSize)
1
+ <script lang="ts">
2
+ import { type ComponentProps } from 'svelte';
3
+ import { timeDays, timeMonths, timeWeek, timeYear } from 'd3-time';
4
+ import { index } from 'd3-array';
5
+ import { format } from 'date-fns';
6
+
7
+ import { chartContext } from './ChartContext.svelte';
8
+ import Rect from './Rect.svelte';
9
+ import type { TooltipContextValue } from './tooltip/TooltipContext.svelte';
10
+ import MonthPath from './MonthPath.svelte';
11
+ import Text from './Text.svelte';
12
+ import { chartDataArray } from '../utils/common.js';
13
+
14
+ export let start: Date;
15
+ export let end: Date;
16
+
17
+ /**
18
+ * Size of cell. If `number`, sets width/height as same value (square). If array, sets as [width,height]. If undefined, is derived from Chart width/height
19
+ */
20
+ export let cellSize: number | [number, number] | undefined = undefined;
21
+
22
+ /** Enable drawing path around each month. If object, pass as props to underlying <path> */
23
+ export let monthPath: boolean | Partial<ComponentProps<MonthPath>> = false;
24
+
25
+ /**
26
+ * Tooltip context to setup mouse events to show tooltip for related data
27
+ */
28
+ export let tooltip: TooltipContextValue | undefined = undefined;
29
+
30
+ const { width, height, x, cGet, data, config } = chartContext();
31
+
32
+ $: yearDays = timeDays(start, end);
33
+ $: yearMonths = timeMonths(start, end);
34
+ $: yearWeeks = timeWeek.count(start, end);
35
+
36
+ $: chartCellWidth = $width / (yearWeeks + 1);
37
+ $: chartCellHeight = $height / 7;
38
+ $: chartCellSize = Math.min(chartCellWidth, chartCellHeight); // Use smallest to fit, and keep square aspect
39
+
40
+ $: [cellWidth, cellHeight] = Array.isArray(cellSize)
30
41
  ? cellSize
31
42
  : typeof cellSize === 'number'
32
- ? [cellSize, cellSize]
33
- : [chartCellSize, chartCellSize];
34
- $: dataByDate = data && $config.x ? index(chartDataArray($data), (d) => $x(d)) : new Map();
35
- $: cells = yearDays.map((date) => {
43
+ ? [cellSize, cellSize]
44
+ : [chartCellSize, chartCellSize];
45
+
46
+ $: dataByDate = data && $config.x ? index(chartDataArray($data), (d) => $x(d)) : new Map();
47
+
48
+ $: cells = yearDays.map((date) => {
36
49
  const cellData = dataByDate.get(date) ?? { date };
37
50
  return {
38
- x: timeWeek.count(timeYear(date), date) * cellWidth,
39
- y: date.getDay() * cellHeight,
40
- color: $config.c ? $cGet(cellData) : 'transparent',
41
- data: cellData,
51
+ x: timeWeek.count(timeYear(date), date) * cellWidth,
52
+ y: date.getDay() * cellHeight,
53
+ color: $config.c ? $cGet(cellData) : 'transparent',
54
+ data: cellData,
42
55
  };
43
- });
56
+ });
44
57
  </script>
45
58
 
46
59
  <slot {cells}>