svelteplot 0.2.1 → 0.2.3

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.
@@ -3,7 +3,7 @@ import type { ScaleName, ChannelName, ScaledChannelName, ChannelAccessor, DataRo
3
3
  type ChannelAlias = {
4
4
  channel: ScaledChannelName;
5
5
  };
6
- export declare function resolveProp<T>(accessor: ConstantAccessor<T>, datum: DataRecord | null, _defaultValue?: T | null): T | null;
6
+ export declare function resolveProp<T>(accessor: ConstantAccessor<T>, datum: DataRecord | null, _defaultValue?: T | null): T | typeof _defaultValue;
7
7
  type ChannelOptions = {
8
8
  value: ChannelAccessor;
9
9
  scale?: ScaleName | null;
package/dist/index.d.ts CHANGED
@@ -58,10 +58,12 @@ export { normalizeX, normalizeY } from './transforms/normalize.js';
58
58
  export { group, groupX, groupY, groupZ } from './transforms/group.js';
59
59
  export { intervalX, intervalY } from './transforms/interval.js';
60
60
  export { recordizeX, recordizeY } from './transforms/recordize.js';
61
- export { renameChannels } from './transforms/rename.js';
61
+ export { renameChannels, replaceChannels } from './transforms/rename.js';
62
62
  export { select, selectFirst, selectLast, selectMaxX, selectMaxY, selectMinX, selectMinY } from './transforms/select.js';
63
63
  export { shiftX, shiftY } from './transforms/shift.js';
64
64
  export { sort, shuffle, reverse } from './transforms/sort.js';
65
65
  export { stackX, stackY } from './transforms/stack.js';
66
66
  export { windowX, windowY } from './transforms/window.js';
67
67
  export { formatMonth } from './helpers/formats.js';
68
+ export { default as LinearGradientX } from './marks/helpers/LinearGradientX.svelte';
69
+ export { default as LinearGradientY } from './marks/helpers/LinearGradientY.svelte';
package/dist/index.js CHANGED
@@ -61,11 +61,13 @@ export { normalizeX, normalizeY } from './transforms/normalize.js';
61
61
  export { group, groupX, groupY, groupZ } from './transforms/group.js';
62
62
  export { intervalX, intervalY } from './transforms/interval.js';
63
63
  export { recordizeX, recordizeY } from './transforms/recordize.js';
64
- export { renameChannels } from './transforms/rename.js';
64
+ export { renameChannels, replaceChannels } from './transforms/rename.js';
65
65
  export { select, selectFirst, selectLast, selectMaxX, selectMaxY, selectMinX, selectMinY } from './transforms/select.js';
66
66
  export { shiftX, shiftY } from './transforms/shift.js';
67
67
  export { sort, shuffle, reverse } from './transforms/sort.js';
68
68
  export { stackX, stackY } from './transforms/stack.js';
69
69
  export { windowX, windowY } from './transforms/window.js';
70
- // format helpers
70
+ // helpers
71
71
  export { formatMonth } from './helpers/formats.js';
72
+ export { default as LinearGradientX } from './marks/helpers/LinearGradientX.svelte';
73
+ export { default as LinearGradientY } from './marks/helpers/LinearGradientY.svelte';
@@ -6,13 +6,11 @@
6
6
  import Mark from '../Mark.svelte';
7
7
  import { getContext } from 'svelte';
8
8
  import { stackX, recordizeX, intervalX, sort } from '../index.js';
9
- import { resolveProp, resolveStyles } from '../helpers/resolve.js';
10
- import { roundedRect } from '../helpers/roundedRect.js';
11
9
  import type { PlotContext, BaseMarkProps, RectMarkProps, ChannelAccessor } from '../types.js';
12
10
  import type { StackOptions } from '../transforms/stack.js';
13
11
  import type { DataRow } from '../types.js';
14
- import { addEventHandlers } from './helpers/events.js';
15
12
  import GroupMultiple from './helpers/GroupMultiple.svelte';
13
+ import RectPath from './helpers/RectPath.svelte';
16
14
 
17
15
  type BarXProps = BaseMarkProps & {
18
16
  data: DataRow[];
@@ -21,14 +19,6 @@
21
19
  x2?: ChannelAccessor;
22
20
  y?: ChannelAccessor;
23
21
  stack?: StackOptions;
24
- borderRadius?:
25
- | number
26
- | {
27
- topLeft?: number;
28
- topRight?: number;
29
- bottomRight?: number;
30
- bottomLeft?: number;
31
- };
32
22
  } & RectMarkProps;
33
23
 
34
24
  let { data = [{}], class: className = null, stack, ...options }: BarXProps = $props();
@@ -59,33 +49,17 @@
59
49
  {@const bw = plot.scales.y.fn.bandwidth()}
60
50
  {@const minx = Math.min(d.x1, d.x2)}
61
51
  {@const maxx = Math.max(d.x1, d.x2)}
62
- {@const insetLeft = resolveProp(args.insetLeft, d.datum, 0)}
63
- {@const insetRight = resolveProp(args.insetRight, d.datum, 0)}
64
- {@const insetTop = resolveProp(args.insetTop || args.inset, d.datum, 0)}
65
- {@const insetBottom = resolveProp(args.insetBottom || args.inset, d.datum, 0)}
66
- {@const dx = resolveProp(args.dx, d.datum, 0)}
67
- {@const dy = resolveProp(args.dy, d.datum, 0)}
68
52
  {#if d.valid}
69
- {@const [style, styleClass] = resolveStyles(plot, d, args, 'fill', usedScales)}
70
- <path
71
- d={roundedRect(
72
- 0,
73
- 0,
74
- maxx - minx - insetLeft - insetRight,
75
- bw - insetTop - insetBottom,
76
- options.borderRadius
77
- )}
78
- class={[styleClass, className]}
79
- {style}
80
- transform="translate({[
81
- minx + dx + insetLeft,
82
- d.y + insetTop + dy - bw * 0.5
83
- ]})"
84
- use:addEventHandlers={{
85
- getPlotState,
86
- options: args,
87
- datum: d.datum
88
- }} />
53
+ <RectPath
54
+ {usedScales}
55
+ class={className}
56
+ {options}
57
+ datum={d}
58
+ x={minx}
59
+ useInsetAsFallbackHorizontally={false}
60
+ y={d.y - bw * 0.5}
61
+ width={maxx - minx}
62
+ height={bw} />
89
63
  {/if}
90
64
  {/each}
91
65
  </GroupMultiple>
@@ -6,40 +6,25 @@
6
6
  import Mark from '../Mark.svelte';
7
7
  import { getContext } from 'svelte';
8
8
  import { intervalY, stackY, recordizeY, sort } from '../index.js';
9
- import { resolveProp, resolveStyles } from '../helpers/resolve.js';
10
- import { roundedRect } from '../helpers/roundedRect.js';
11
- import {
12
- type PlotContext,
13
- type BaseMarkProps,
14
- type ChannelAccessor,
15
- type DataRow
16
- } from '../types.js';
9
+ import type { PlotContext, BaseMarkProps, BaseRectMarkProps } from '../types.js';
17
10
  import type { StackOptions } from '../transforms/stack.js';
18
- import { maybeData } from '../helpers/index.js';
19
- import { addEventHandlers } from './helpers/events.js';
20
11
  import GroupMultiple from './helpers/GroupMultiple.svelte';
12
+ import RectPath from './helpers/RectPath.svelte';
21
13
 
22
- type BarYProps = BaseMarkProps & {
23
- data: DataRow[];
24
- x?: ChannelAccessor;
25
- y?: ChannelAccessor;
26
- y1?: ChannelAccessor;
27
- y2?: ChannelAccessor;
28
- stack?: StackOptions;
29
- /**
30
- * Converts y into y1/y2 ranges based on the provided interval. Disables the
31
- * implicit stacking
32
- */
33
- interval?: number | string;
34
- borderRadius?:
35
- | number
36
- | {
37
- topLeft?: number;
38
- topRight?: number;
39
- bottomRight?: number;
40
- bottomLeft?: number;
41
- };
42
- };
14
+ type BarYProps = BaseMarkProps &
15
+ BaseRectMarkProps & {
16
+ data: DataRow[];
17
+ x?: ChannelAccessor;
18
+ y?: ChannelAccessor;
19
+ y1?: ChannelAccessor;
20
+ y2?: ChannelAccessor;
21
+ stack?: StackOptions;
22
+ /**
23
+ * Converts y into y1/y2 ranges based on the provided interval. Disables the
24
+ * implicit stacking
25
+ */
26
+ interval?: number | string;
27
+ };
43
28
 
44
29
  let { data = [{}], class: className = null, stack, ...options }: BarYProps = $props();
45
30
 
@@ -63,39 +48,23 @@
63
48
  requiredScales={{ x: ['band'] }}
64
49
  channels={['x', 'y1', 'y2', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
65
50
  {...args}>
66
- {#snippet children({ mark, scaledData, usedScales })}
51
+ {#snippet children({ scaledData, usedScales })}
67
52
  <GroupMultiple class="bar-y" length={scaledData.length}>
68
53
  {#each scaledData as d}
69
54
  {@const bw = plot.scales.x.fn.bandwidth()}
70
55
  {@const miny = Math.min(d.y1, d.y2)}
71
56
  {@const maxy = Math.max(d.y1, d.y2)}
72
- {@const insetLeft = resolveProp(args.insetLeft || args.inset, d.datum, 0)}
73
- {@const insetRight = resolveProp(args.insetRight || args.inset, d.datum, 0)}
74
- {@const insetTop = resolveProp(args.insetTop, d.datum, 0)}
75
- {@const insetBottom = resolveProp(args.insetBottom, d.datum, 0)}
76
- {@const dx = resolveProp(args.dx, d.datum, 0)}
77
- {@const dy = resolveProp(args.dy, d.datum, 0)}
78
57
  {#if d.valid}
79
- {@const [style, styleClass] = resolveStyles(plot, d, args, 'fill', usedScales)}
80
- <path
81
- d={roundedRect(
82
- 0,
83
- 0,
84
- bw - insetLeft - insetRight,
85
- maxy - miny - insetTop - insetBottom,
86
- options.borderRadius
87
- )}
88
- class={[styleClass, className]}
89
- {style}
90
- transform="translate({[
91
- d.x + insetLeft + dx - bw * 0.5,
92
- miny + dy + insetTop
93
- ]})"
94
- use:addEventHandlers={{
95
- getPlotState,
96
- options: args,
97
- datum: d.datum
98
- }} />
58
+ <RectPath
59
+ x={d.x - bw * 0.5}
60
+ y={miny}
61
+ options={args}
62
+ class={className}
63
+ width={bw}
64
+ height={maxy - miny}
65
+ datum={d}
66
+ {usedScales}
67
+ useInsetAsFallbackVertically={false} />
99
68
  {/if}
100
69
  {/each}
101
70
  </GroupMultiple>
@@ -1,6 +1,6 @@
1
- import { type BaseMarkProps, type ChannelAccessor, type DataRow } from '../types.js';
1
+ import type { BaseMarkProps, BaseRectMarkProps } from '../types.js';
2
2
  import type { StackOptions } from '../transforms/stack.js';
3
- type BarYProps = BaseMarkProps & {
3
+ type BarYProps = BaseMarkProps & BaseRectMarkProps & {
4
4
  data: DataRow[];
5
5
  x?: ChannelAccessor;
6
6
  y?: ChannelAccessor;
@@ -12,12 +12,6 @@ type BarYProps = BaseMarkProps & {
12
12
  * implicit stacking
13
13
  */
14
14
  interval?: number | string;
15
- borderRadius?: number | {
16
- topLeft?: number;
17
- topRight?: number;
18
- bottomRight?: number;
19
- bottomLeft?: number;
20
- };
21
15
  };
22
16
  /** For vertical column charts using a band scale as x axis */
23
17
  declare const BarY: import("svelte").Component<BarYProps, {}, "">;
@@ -6,9 +6,7 @@
6
6
  import Mark from '../Mark.svelte';
7
7
  import { getContext } from 'svelte';
8
8
  import { recordizeY, sort } from '../index.js';
9
- import { roundedRect } from '../helpers/roundedRect.js';
10
- import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
11
- import { coalesce, maybeNumber } from '../helpers/index.js';
9
+ import { resolveChannel } from '../helpers/resolve.js';
12
10
  import type {
13
11
  PlotContext,
14
12
  DataRecord,
@@ -17,7 +15,7 @@
17
15
  ChannelAccessor
18
16
  } from '../types.js';
19
17
  import { isValid } from '../helpers/isValid.js';
20
- import { addEventHandlers } from './helpers/events.js';
18
+ import RectPath from './helpers/RectPath.svelte';
21
19
 
22
20
  type CellProps = BaseMarkProps & {
23
21
  data: DataRecord[];
@@ -59,43 +57,21 @@
59
57
  requiredScales={{ x: ['band'], y: ['band'] }}
60
58
  channels={['x', 'y', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
61
59
  {...args}>
62
- {#snippet children({ mark, scaledData, usedScales })}
60
+ {#snippet children({ scaledData, usedScales })}
63
61
  {@const bwx = plot.scales.x.fn.bandwidth()}
64
62
  {@const bwy = plot.scales.y.fn.bandwidth()}
65
63
  <g class="cell {className || ''}" data-fill={usedScales.fillOpacity}>
66
64
  {#each scaledData as d}
67
- {@const inset = resolveProp(args.inset, d.datum, 0)}
68
- {@const insetLeft = resolveProp(args.insetLeft, d.datum)}
69
- {@const insetRight = resolveProp(args.insetRight, d.datum)}
70
- {@const insetTop = resolveProp(args.insetTop, d.datum)}
71
- {@const insetBottom = resolveProp(args.insetBottom, d.datum)}
72
- {@const dx = resolveProp(args.dx, d.datum, 0)}
73
- {@const dy = resolveProp(args.dy, d.datum, 0)}
74
- {@const insetL = maybeNumber(coalesce(insetLeft, inset, 0))}
75
- {@const insetT = maybeNumber(coalesce(insetTop, inset, 0))}
76
- {@const insetR = maybeNumber(coalesce(insetRight, inset, 0))}
77
- {@const insetB = maybeNumber(coalesce(insetBottom, inset, 0))}
78
65
  {#if d.valid && (args.fill == null || isValid(resolveChannel('fill', d.datum, args)))}
79
- {@const [style, styleClass] = resolveStyles(plot, d, args, 'fill', usedScales)}
80
- <path
81
- d={roundedRect(
82
- 0,
83
- 0,
84
- bwx - insetL - insetR,
85
- bwy - insetT - insetB,
86
- options.borderRadius
87
- )}
88
- class={[styleClass]}
89
- {style}
90
- transform="translate({[
91
- d.x + insetL + dx - bwx * 0.5,
92
- d.y + insetT + dy - bwy * 0.5
93
- ]})"
94
- use:addEventHandlers={{
95
- getPlotState,
96
- options: args,
97
- datum: d.datum
98
- }} />
66
+ <RectPath
67
+ datum={d}
68
+ class={className}
69
+ {usedScales}
70
+ options={args}
71
+ x={d.x - bwx * 0.5}
72
+ y={d.y - bwy * 0.5}
73
+ width={bwx}
74
+ height={bwy} />
99
75
  {/if}
100
76
  {/each}
101
77
  </g>
@@ -18,8 +18,9 @@
18
18
  data: DataRecord[];
19
19
  z?: ChannelAccessor;
20
20
  stroke?: ChannelAccessor;
21
- outlineStroke?: ConstantAccessor<string>;
22
- outlineStrokeWidth?: ConstantAccessor<number>;
21
+ outlineStroke?: string;
22
+ outlineStrokeWidth?: number;
23
+ outlineStrokeOpacity?: number;
23
24
  dx?: ConstantAccessor<number>;
24
25
  dy?: ConstantAccessor<number>;
25
26
  curve?: CurveName | CurveFactory;
@@ -31,6 +32,7 @@
31
32
  textStartOffset?: ConstantAccessor<string>;
32
33
  textStrokeWidth?: ConstantAccessor<number>;
33
34
  lineClass?: ConstantAccessor<string>;
35
+ canvas?: boolean;
34
36
  } & MarkerOptions;
35
37
  </script>
36
38
 
@@ -39,11 +41,12 @@
39
41
  import MarkerPath from './helpers/MarkerPath.svelte';
40
42
  import { getContext } from 'svelte';
41
43
  import { resolveProp, resolveStyles } from '../helpers/resolve.js';
42
- import { line, type CurveFactory } from 'd3-shape';
44
+ import { line, type CurveFactory, type Line } from 'd3-shape';
43
45
  import { geoPath } from 'd3-geo';
44
46
  import callWithProps from '../helpers/callWithProps.js';
45
47
  import { maybeCurve } from '../helpers/curves.js';
46
48
  import { pick } from 'es-toolkit';
49
+ import LineCanvas from './helpers/LineCanvas.svelte';
47
50
 
48
51
  type LineMarkProps = BaseMarkProps & {
49
52
  x?: ChannelAccessor;
@@ -61,6 +64,7 @@
61
64
  curve = 'auto',
62
65
  tension = 0,
63
66
  text,
67
+ canvas = false,
64
68
  class: className = null,
65
69
  lineClass = null,
66
70
  ...options
@@ -96,9 +100,7 @@
96
100
  const { getPlotState } = getContext<PlotContext>('svelteplot');
97
101
  const plot = $derived(getPlotState());
98
102
 
99
- type LinePath = (dr: DataRecord[]) => string;
100
-
101
- const linePath: LinePath = $derived(
103
+ const linePath: Line<ScaledDataRecord> = $derived(
102
104
  plot.scales.projection && curve === 'auto'
103
105
  ? sphereLine(plot.scales.projection)
104
106
  : callWithProps(line, [], {
@@ -111,7 +113,7 @@
111
113
 
112
114
  function sphereLine(projection) {
113
115
  const path = geoPath(projection);
114
- return (lineData: ScaledDataRecord[]) => {
116
+ const fn = (lineData: ScaledDataRecord[]) => {
115
117
  let line = [];
116
118
  const lines = [line];
117
119
  for (const { x, y } of lineData) {
@@ -125,6 +127,8 @@
125
127
  }
126
128
  return path({ type: 'MultiLineString', coordinates: lines });
127
129
  };
130
+ fn.context = path.context;
131
+ return fn;
128
132
  }
129
133
  </script>
130
134
 
@@ -135,88 +139,102 @@
135
139
  {...args}>
136
140
  {#snippet children({ mark, usedScales, scaledData })}
137
141
  {#if scaledData.length > 0}
138
- <g class={['lines', className]}>
139
- {#each groupIndex(scaledData, groupByKey) as lineData, i}
140
- {@const pathString = linePath(lineData)}
141
- {#if pathString}
142
- <GroupMultiple class={resolveProp(lineClass, lineData[0])}>
143
- {#if options.outlineStroke}
144
- {@const [outlineStyle, outlineStyleClass] = resolveStyles(
142
+ {@const groupedLineData = groupIndex(scaledData, groupByKey)};
143
+ {#if canvas}
144
+ <LineCanvas {groupedLineData} {mark} {usedScales} {linePath} {groupByKey} />
145
+ {:else}
146
+ <g class={['lines', className]}>
147
+ {#each groupedLineData as lineData, i}
148
+ {@const pathString = linePath(lineData)}
149
+ {#if pathString}
150
+ <GroupMultiple class={resolveProp(lineClass, lineData[0])}>
151
+ {#if options.outlineStroke}
152
+ {@const [outlineStyle, outlineStyleClass] = resolveStyles(
153
+ plot,
154
+ { ...lineData[0], stroke: options.outlineStroke },
155
+ {
156
+ strokeLinejoin: 'round',
157
+ ...args,
158
+ stroke: options.outlineStroke,
159
+ strokeOpacity: options.outlineStrokeOpacity ?? 1,
160
+ strokeWidth:
161
+ options.outlineStrokeWidth ||
162
+ resolveProp(
163
+ options.strokeWidth,
164
+ lineData[0].datum,
165
+ 1.4
166
+ ) + 2
167
+ },
168
+ 'stroke',
169
+ usedScales
170
+ )}
171
+ <path
172
+ d={pathString}
173
+ style={outlineStyle}
174
+ class={['is-outline', outlineStyleClass]} />
175
+ {/if}
176
+ {@const [style, styleClass] = resolveStyles(
145
177
  plot,
146
- { ...lineData[0], stroke: options.outlineStroke },
178
+ lineData[0],
147
179
  {
180
+ strokeWidth: 1.4,
148
181
  strokeLinejoin: 'round',
149
182
  ...args,
150
- stroke: options.outlineStroke,
151
- strokeWidth:
152
- options.outlineStrokeWidth ||
153
- (+options.strokeWidth || 1.4) + 2
183
+ stroke: lineData[0].stroke
154
184
  },
155
185
  'stroke',
156
186
  usedScales
157
187
  )}
158
- <path
188
+ {@const [textStyle, textStyleClass] = resolveStyles(
189
+ plot,
190
+ lineData[0],
191
+ {
192
+ textAnchor: 'middle',
193
+ ...pick(args, [
194
+ 'fontSize',
195
+ 'fontWeight',
196
+ 'fontStyle',
197
+ 'textAnchor'
198
+ ]),
199
+ strokeWidth: args.textStrokeWidth
200
+ ? args.textStrokeWidth
201
+ : args.textStroke
202
+ ? 2
203
+ : 0,
204
+ fill: args.textFill || args.stroke,
205
+ stroke: args.textStroke
206
+ },
207
+ 'fill',
208
+ usedScales,
209
+ true
210
+ )}
211
+ <MarkerPath
212
+ {mark}
213
+ scales={plot.scales}
214
+ markerStart={args.markerStart}
215
+ markerMid={args.markerMid}
216
+ markerEnd={args.markerEnd}
217
+ marker={args.marker}
218
+ strokeWidth={args.strokeWidth}
219
+ datum={lineData[0]}
159
220
  d={pathString}
160
- style={outlineStyle}
161
- class={['is-outline', outlineStyleClass]} />
162
- {/if}
163
- {@const [style, styleClass] = resolveStyles(
164
- plot,
165
- lineData[0],
166
- {
167
- strokeWidth: 1.4,
168
- strokeLinejoin: 'round',
169
- ...args,
170
- stroke: lineData[0].stroke
171
- },
172
- 'stroke',
173
- usedScales
174
- )}
175
- {@const [textStyle, textStyleClass] = resolveStyles(
176
- plot,
177
- lineData[0],
178
- {
179
- textAnchor: 'middle',
180
- ...pick(args, [
181
- 'fontSize',
182
- 'fontWeight',
183
- 'fontStyle',
184
- 'textAnchor'
185
- ]),
186
- strokeWidth: args.textStrokeWidth
187
- ? args.textStrokeWidth
188
- : args.textStroke
189
- ? 2
190
- : 0,
191
- fill: args.textFill || args.stroke,
192
- stroke: args.textStroke
193
- },
194
- 'fill',
195
- usedScales,
196
- true
197
- )}
198
- <MarkerPath
199
- {mark}
200
- scales={plot.scales}
201
- markerStart={args.markerStart}
202
- markerMid={args.markerMid}
203
- markerEnd={args.markerEnd}
204
- marker={args.marker}
205
- strokeWidth={args.strokeWidth}
206
- datum={lineData[0]}
207
- d={pathString}
208
- dInv={text ? linePath(lineData.toReversed()) : null}
209
- color={lineData[0].stroke || 'currentColor'}
210
- {style}
211
- class={styleClass}
212
- text={text ? resolveProp(text, lineData[0]) : null}
213
- startOffset={resolveProp(args.textStartOffset, lineData[0], '50%')}
214
- {textStyle}
215
- {textStyleClass} />
216
- </GroupMultiple>
217
- {/if}
218
- {/each}
219
- </g>
221
+ dInv={text ? linePath(lineData.toReversed()) : null}
222
+ color={lineData[0].stroke || 'currentColor'}
223
+ {style}
224
+ class={styleClass}
225
+ text={text ? resolveProp(text, lineData[0]) : null}
226
+ startOffset={resolveProp(
227
+ args.textStartOffset,
228
+ lineData[0],
229
+ '50%'
230
+ )}
231
+ {textStyle}
232
+ {textStyleClass} />
233
+ </GroupMultiple>
234
+ {/if}
235
+ {/each}
236
+ </g>
237
+ {/if}
220
238
  {/if}
221
239
  {/snippet}
222
240
  </Mark>
@@ -3,8 +3,9 @@ export type BaseLineMarkProps = {
3
3
  data: DataRecord[];
4
4
  z?: ChannelAccessor;
5
5
  stroke?: ChannelAccessor;
6
- outlineStroke?: ConstantAccessor<string>;
7
- outlineStrokeWidth?: ConstantAccessor<number>;
6
+ outlineStroke?: string;
7
+ outlineStrokeWidth?: number;
8
+ outlineStrokeOpacity?: number;
8
9
  dx?: ConstantAccessor<number>;
9
10
  dy?: ConstantAccessor<number>;
10
11
  curve?: CurveName | CurveFactory;
@@ -18,8 +19,9 @@ export type BaseLineMarkProps = {
18
19
  textStartOffset?: ConstantAccessor<string>;
19
20
  textStrokeWidth?: ConstantAccessor<number>;
20
21
  lineClass?: ConstantAccessor<string>;
22
+ canvas?: boolean;
21
23
  } & MarkerOptions;
22
- import { type CurveFactory } from 'd3-shape';
24
+ import { type CurveFactory, type Line } from 'd3-shape';
23
25
  import type { RawValue } from '../types.js';
24
26
  type LineMarkProps = BaseMarkProps & {
25
27
  x?: ChannelAccessor;
@@ -17,6 +17,7 @@
17
17
  } from '../types.js';
18
18
  import { addEventHandlers } from './helpers/events.js';
19
19
  import GroupMultiple from './helpers/GroupMultiple.svelte';
20
+ import RectPath from './helpers/RectPath.svelte';
20
21
 
21
22
  type RectMarkProps = BaseMarkProps & {
22
23
  data: DataRecord[];
@@ -57,31 +58,16 @@
57
58
  {@const maxy = Math.max(y1, y2)}
58
59
  {@const minx = Math.min(x1, x2)}
59
60
  {@const maxx = Math.max(x1, x2)}
60
- {@const inset = resolveProp(args.inset, d.datum, 0)}
61
- {@const insetLeft = resolveProp(args.insetLeft, d.datum)}
62
- {@const insetRight = resolveProp(args.insetRight, d.datum)}
63
- {@const insetTop = resolveProp(args.insetTop, d.datum)}
64
- {@const insetBottom = resolveProp(args.insetBottom, d.datum)}
65
- {@const insetL = maybeNumber(coalesce(insetLeft, inset, 0)) ?? 0}
66
- {@const insetT = maybeNumber(coalesce(insetTop, inset, 0)) ?? 0}
67
- {@const insetR = maybeNumber(coalesce(insetRight, inset, 0)) ?? 0}
68
- {@const insetB = maybeNumber(coalesce(insetBottom, inset, 0)) ?? 0}
69
61
 
70
- {@const [style, styleClass] = resolveStyles(plot, d, args, 'fill', usedScales)}
71
- <rect
72
- class={[scaledData.length === 1 && className, styleClass]}
73
- {style}
74
- x={minx + insetL}
75
- y={miny + insetT}
76
- width={maxx - minx - insetL - insetR}
77
- height={maxy - miny - insetT - insetB}
78
- rx={resolveProp(args.rx, d.datum, null)}
79
- ry={resolveProp(args.ry, d.datum, null)}
80
- use:addEventHandlers={{
81
- getPlotState,
82
- options: args,
83
- datum: d.datum
84
- }} />
62
+ <RectPath
63
+ datum={d}
64
+ class={scaledData.length === 1 ? className : null}
65
+ x={minx}
66
+ y={miny}
67
+ width={maxx - minx}
68
+ height={maxy - miny}
69
+ options={args}
70
+ {usedScales} />
85
71
  {/if}
86
72
  {/each}
87
73
  </GroupMultiple>