svelteplot 0.4.2 → 0.4.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.
package/dist/Mark.svelte CHANGED
@@ -135,11 +135,12 @@
135
135
  const resolvedData: ResolvedDataRecord<Datum>[] = $derived(
136
136
  data
137
137
  .map((d, i) => ({ ...d, [INDEX]: i }))
138
- .flatMap((row) => {
138
+ .flatMap((row, index) => {
139
139
  const channels = options as Record<ChannelName, ChannelAccessor<Datum>>;
140
140
  if (!testFacet(row, channels) || !testFilter(row, channels)) return [];
141
141
  const out: ResolvedDataRecord<Datum> = {
142
- datum: row
142
+ datum: row,
143
+ index
143
144
  };
144
145
  for (const [channel] of Object.entries(CHANNEL_SCALE) as [
145
146
  ScaledChannelName,
@@ -208,6 +209,7 @@
208
209
  resolvedData.flatMap((row) => {
209
210
  const out: ScaledDataRecord<Datum> = {
210
211
  datum: row.datum,
212
+ index: row[INDEX],
211
213
  valid: true
212
214
  };
213
215
  // compute dx/dy
@@ -499,8 +499,7 @@
499
499
  width={fixedWidth || width}
500
500
  {height}
501
501
  fill="currentColor"
502
- viewBox="0 0 {width} {height}"
503
- font-family="system-ui, sans-serif">
502
+ viewBox="0 0 {width} {height}">
504
503
  {@render facetAxes?.()}
505
504
  <FacetGrid marks={explicitMarks}>
506
505
  {#if children}
@@ -1,4 +1,4 @@
1
- import type { ChannelName, Channels, DataRecord, RawValue } from '../types/index.js';
1
+ import type { ChannelName, Channels, RawValue } from '../types/index.js';
2
2
  import type { Snippet } from 'svelte';
3
3
  /**
4
4
  * Returns first argument that is not null or undefined
@@ -8,7 +8,6 @@ export declare function testFilter<T>(datum: T, options: Channels<T>): true | T
8
8
  export declare function randomId(): string;
9
9
  export declare function isSnippet(value: unknown): value is Snippet;
10
10
  export declare function isValid(value: RawValue | undefined): value is number | Date | string;
11
- export declare function maybeData(data: DataRecord[]): DataRecord[];
12
11
  export declare function isObject<T>(option: object | T): option is object;
13
12
  export declare function maybeNumber(value: RawValue | null): number | null;
14
13
  export declare const constant: <T>(x: T) => () => T;
@@ -13,8 +13,7 @@ export function coalesce(...args) {
13
13
  return null; // Return null if all arguments are null or undefined
14
14
  }
15
15
  export function testFilter(datum, options) {
16
- return (options.filter == null ||
17
- resolveProp(options.filter, isObject(datum) && datum.hasOwnProperty(RAW_VALUE) ? datum[RAW_VALUE] : datum));
16
+ return options.filter == null || resolveProp(options.filter, datum);
18
17
  }
19
18
  export function randomId() {
20
19
  return Math.ceil(1e9 + Math.random() * 1e9).toString(36);
@@ -28,10 +27,6 @@ export function isValid(value) {
28
27
  !Number.isNaN(value) &&
29
28
  (typeof value !== 'number' || Number.isFinite(value)));
30
29
  }
31
- export function maybeData(data) {
32
- // if (data.type === 'FeatureCollection') return data.features;
33
- return data;
34
- }
35
30
  export function isObject(option) {
36
31
  // doesn't work with Proxies
37
32
  return (typeof option === 'object' && !isDate(option) && !Array.isArray(option) && option !== null);
@@ -1,4 +1,4 @@
1
- import { CHANNEL_SCALE } from '../constants.js';
1
+ import { CHANNEL_SCALE, INDEX } from '../constants.js';
2
2
  import isDataRecord from './isDataRecord.js';
3
3
  import isRawValue from './isRawValue.js';
4
4
  import { isValid } from './index.js';
@@ -11,7 +11,7 @@ export function resolveProp(accessor, datum, _defaultValue = null) {
11
11
  // so we're passing the original value to accessor functions instead of our wrapped record
12
12
  return datum == null
13
13
  ? accessor()
14
- : accessor(datum[RAW_VALUE] != null ? datum[RAW_VALUE] : datum);
14
+ : accessor(datum[RAW_VALUE] != null ? datum[RAW_VALUE] : datum, datum[INDEX]);
15
15
  }
16
16
  else if ((typeof accessor === 'string' || typeof accessor === 'symbol') &&
17
17
  datum &&
@@ -51,7 +51,7 @@ function resolve(datum, accessor, channel, scale) {
51
51
  // datum[RAW_VALUE] exists if an array of raw values was used as dataset and got
52
52
  // "recordized" by the recordize transform. We want to hide this wrapping to the user
53
53
  // so we're passing the original value to accessor functions instead of our wrapped record
54
- return accessor(datum[RAW_VALUE] != null ? datum[RAW_VALUE] : datum);
54
+ return accessor(datum[RAW_VALUE] != null ? datum[RAW_VALUE] : datum, datum?.[INDEX]);
55
55
  // use accessor string
56
56
  if ((typeof accessor === 'string' || typeof accessor === 'symbol') &&
57
57
  datum[accessor] !== undefined)
@@ -69,7 +69,7 @@ function resolve(datum, accessor, channel, scale) {
69
69
  else {
70
70
  // return single value or accessor
71
71
  return typeof accessor === 'function'
72
- ? accessor(datum)
72
+ ? accessor(datum, datum?.[INDEX])
73
73
  : accessor !== null && isRawValue(accessor)
74
74
  ? accessor
75
75
  : !Array.isArray(datum) && (scale === 'x' || scale === 'y')
@@ -136,11 +136,11 @@
136
136
  class={['svelteplot-area', className, styleClass]}
137
137
  clip-path={options.clipPath}
138
138
  d={areaPath(areaData)}
139
- use:addEventHandlers={{
139
+ {@attach addEventHandlers({
140
140
  getPlotState,
141
141
  options,
142
- datum: datum.datum
143
- }}
142
+ datum: datum?.datum
143
+ })}
144
144
  {style}
145
145
  >{#if title}<title>{title}</title>{/if}</path>
146
146
  </Anchor>
@@ -4,7 +4,9 @@
4
4
  <script lang="ts" generics="Datum extends DataRecord">
5
5
  interface ArrowMarkProps extends Omit<BaseMarkProps<Datum>, 'fill' | 'fillOpacity'> {
6
6
  data: Datum[];
7
- sort?: ConstantAccessor<RawValue> | { channel: 'stroke' | 'fill' };
7
+ sort?:
8
+ | ConstantAccessor<RawValue>
9
+ | { channel: 'stroke' | 'fill' | 'x1' | 'y1' | 'x2' | 'y2' };
8
10
  x1: ChannelAccessor<Datum>;
9
11
  y1: ChannelAccessor<Datum>;
10
12
  x2: ChannelAccessor<Datum>;
@@ -46,12 +48,14 @@
46
48
  PlotDefaults
47
49
  } from '../types/index.js';
48
50
  import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
49
- import { coalesce, maybeData, maybeNumber } from '../helpers/index.js';
51
+ import { coalesce, maybeNumber } from '../helpers/index.js';
50
52
  import Mark from '../Mark.svelte';
51
53
  import { arrowPath, maybeSweep, type SweepOption } from '../helpers/arrowPath.js';
52
54
  import { replaceChannels } from '../transforms/rename.js';
53
55
  import { addEventHandlers } from './helpers/events.js';
54
56
  import GroupMultiple from './helpers/GroupMultiple.svelte';
57
+ import { sort } from '../transforms/sort.js';
58
+ import { indexData } from '../transforms/recordize.js';
55
59
 
56
60
  let markProps: ArrowMarkProps = $props();
57
61
 
@@ -74,16 +78,13 @@
74
78
  const { getPlotState } = getContext<PlotContext>('svelteplot');
75
79
  const plot = $derived(getPlotState());
76
80
 
77
- const sorted = $derived(
78
- options.sort
79
- ? maybeData(data).toSorted((a, b) =>
80
- resolveChannel('sort', a, options) > resolveChannel('sort', b, options) ? 1 : -1
81
- )
82
- : maybeData(data)
83
- );
84
-
85
81
  const args: ArrowMarkProps = $derived(
86
- replaceChannels({ data: sorted, ...options }, { y: ['y1', 'y2'], x: ['x1', 'x2'] })
82
+ sort(
83
+ replaceChannels(
84
+ { data: indexData(data), ...options },
85
+ { y: ['y1', 'y2'], x: ['x1', 'x2'] }
86
+ )
87
+ )
87
88
  );
88
89
  </script>
89
90
 
@@ -131,11 +132,11 @@
131
132
  )}
132
133
  <g
133
134
  class={[className]}
134
- use:addEventHandlers={{
135
+ {@attach addEventHandlers({
135
136
  getPlotState,
136
- options: args,
137
- datum: d.datum
138
- }}>
137
+ options,
138
+ datum: d?.datum
139
+ })}>
139
140
  {#if options.onmouseenter || options.onclick}
140
141
  <!-- add invisible path in bg for easier mouse access -->
141
142
  <path
@@ -63,7 +63,7 @@ declare class __sveltets_Render<Datum extends DataRecord> {
63
63
  }>, "fill" | "fillOpacity"> & {
64
64
  data: Datum[];
65
65
  sort?: ConstantAccessor<RawValue> | {
66
- channel: "stroke" | "fill";
66
+ channel: "stroke" | "fill" | "x1" | "y1" | "x2" | "y2";
67
67
  };
68
68
  x1: ChannelAccessor<Datum>;
69
69
  y1: ChannelAccessor<Datum>;
@@ -39,7 +39,7 @@
39
39
  | 'auto'
40
40
  | Intl.DateTimeFormatOptions
41
41
  | Intl.NumberFormatOptions
42
- | ((d: RawValue) => string);
42
+ | ((d: RawValue, i: number) => string);
43
43
  tickClass?: ConstantAccessor<string, Datum>;
44
44
  /** ticks is a shorthand for defining data, tickCount or interval */
45
45
  ticks?: number | string | Datum[];
@@ -71,7 +71,7 @@ declare class __sveltets_Render<Datum extends RawValue> {
71
71
  tickFontSize?: ConstantAccessor<number, Datum>;
72
72
  titleFontSize?: number;
73
73
  tickPadding?: number;
74
- tickFormat?: "auto" | Intl.NumberFormatOptions | Intl.DateTimeFormatOptions | ((d: RawValue) => string) | undefined;
74
+ tickFormat?: "auto" | Intl.NumberFormatOptions | Intl.DateTimeFormatOptions | ((d: RawValue, i: number) => string) | undefined;
75
75
  tickClass?: ConstantAccessor<string, Datum>;
76
76
  /** ticks is a shorthand for defining data, tickCount or interval */
77
77
  ticks?: string | number | Datum[] | undefined;
@@ -28,7 +28,7 @@
28
28
  import { sort } from '../index.js';
29
29
  import Mark from '../Mark.svelte';
30
30
  import DotCanvas from './helpers/DotCanvas.svelte';
31
- import { maybeData, isValid } from '../helpers/index.js';
31
+ import { isValid } from '../helpers/index.js';
32
32
  import { recordizeXY } from '../transforms/recordize.js';
33
33
  import { addEventHandlers } from './helpers/events.js';
34
34
  import Anchor from './helpers/Anchor.svelte';
@@ -58,7 +58,7 @@
58
58
  // todo: move sorting to Mark
59
59
  sort(
60
60
  recordizeXY({
61
- data: maybeData(data),
61
+ data,
62
62
  // sort by descending radius by default
63
63
  ...(options.r ? { sort: { channel: '-r' } } : {}),
64
64
  ...options,
@@ -107,11 +107,11 @@
107
107
  styleClass
108
108
  ]}
109
109
  {style}
110
- use:addEventHandlers={{
110
+ {@attach addEventHandlers({
111
111
  getPlotState,
112
112
  options: args,
113
- datum: d.datum
114
- }} />
113
+ datum: d?.datum
114
+ })} />
115
115
  </Anchor>
116
116
  {/if}
117
117
  {/each}
@@ -111,11 +111,11 @@
111
111
  d={path(geometry)}
112
112
  {style}
113
113
  class={[styleClass]}
114
- use:addEventHandlers={{
114
+ {@attach addEventHandlers({
115
115
  getPlotState,
116
116
  options: args,
117
- datum: d.datum
118
- }}>
117
+ datum: d?.datum
118
+ })}>
119
119
  {#if title}<title>{title}</title>{/if}
120
120
  </path>
121
121
  </Anchor>
@@ -5,14 +5,25 @@
5
5
  interface GridXMarkProps extends Omit<BaseMarkProps<Datum>, 'fill' | 'fillOpacity'> {
6
6
  data?: Datum[];
7
7
  automatic?: boolean;
8
+ y1?: ChannelAccessor<Datum>;
9
+ y2?: ChannelAccessor<Datum>;
8
10
  }
9
11
  import { getContext } from 'svelte';
10
12
  import Mark from '../Mark.svelte';
11
- import type { PlotContext, BaseMarkProps, RawValue, PlotDefaults } from '../types/index.js';
13
+ import type {
14
+ PlotContext,
15
+ BaseMarkProps,
16
+ RawValue,
17
+ PlotDefaults,
18
+ DataRecord,
19
+ ChannelAccessor
20
+ } from '../types/index.js';
12
21
  import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
13
22
  import { autoTicks } from '../helpers/autoTicks.js';
14
23
  import { testFilter } from '../helpers/index.js';
15
24
  import { RAW_VALUE } from '../transforms/recordize.js';
25
+ import isDataRecord from '../helpers/isDataRecord';
26
+ import { INDEX } from '../constants';
16
27
 
17
28
  let markProps: GridXMarkProps = $props();
18
29
 
@@ -37,8 +48,8 @@
37
48
  Math.max(3, Math.round(plot.facetWidth / plot.options.x.tickSpacing))
38
49
  );
39
50
 
40
- const ticks: RawValue[] = $derived(
41
- data.length > 0
51
+ const ticks: DataRecord[] = $derived(
52
+ (data.length > 0
42
53
  ? // use custom tick values if user passed any as prop
43
54
  data
44
55
  : // use custom scale tick values if user passed any as plot scale option
@@ -50,6 +61,9 @@
50
61
  plot.scales.x.fn,
51
62
  autoTickCount
52
63
  )
64
+ ).map((d, i) =>
65
+ isDataRecord(d) ? { ...d, [INDEX]: i } : { [RAW_VALUE]: d, [INDEX]: i }
66
+ ) as DataRecord[]
53
67
  );
54
68
  </script>
55
69
 
@@ -64,17 +78,21 @@
64
78
  {#each ticks as tick, t (t)}
65
79
  {#if testFilter(tick, options)}
66
80
  {@const x =
67
- plot.scales.x.fn(tick) +
81
+ plot.scales.x.fn(tick[RAW_VALUE]) +
68
82
  (plot.scales.x.type === 'band' ? plot.scales.x.fn.bandwidth() * 0.5 : 0)}
69
83
  {@const y1_ = resolveChannel('y1', tick, options)}
70
84
  {@const y2_ = resolveChannel('y2', tick, options)}
71
85
  {@const dx = +resolveProp(options?.dx, tick, 0)}
72
86
  {@const dy = +resolveProp(options?.dy, tick, 0)}
73
- {@const y1 = options.y1 != null ? plot.scales.y.fn(y1_) : 0}
74
- {@const y2 = options.y2 != null ? plot.scales.y.fn(y2_) : plot.facetHeight}
87
+ {@const y1 =
88
+ options.y1 != null ? plot.scales.y.fn(y1_) : plot.options.marginTop}
89
+ {@const y2 =
90
+ options.y2 != null
91
+ ? plot.scales.y.fn(y2_)
92
+ : plot.options.marginTop + plot.facetHeight}
75
93
  {@const [style, styleClass] = resolveStyles(
76
94
  plot,
77
- { datum: { [RAW_VALUE]: tick } },
95
+ { datum: tick },
78
96
  options,
79
97
  'stroke',
80
98
  usedScales,
@@ -82,7 +100,7 @@
82
100
  )}
83
101
  <line
84
102
  class={styleClass}
85
- transform="translate({x + dx},{plot.options.marginTop + dy})"
103
+ transform="translate({x + dx},{dy})"
86
104
  {style}
87
105
  {y1}
88
106
  {y2} />
@@ -1,25 +1,25 @@
1
- import type { RawValue } from '../types/index.js';
1
+ import type { RawValue, ChannelAccessor } from '../types/index.js';
2
2
  declare class __sveltets_Render<Datum = RawValue> {
3
3
  props(): Omit<Partial<{
4
4
  filter?: import("../types/index.js").ConstantAccessor<boolean, Datum>;
5
5
  facet?: "auto" | "include" | "exclude";
6
- fx: import("../types/channel").ChannelAccessor<Datum>;
7
- fy: import("../types/channel").ChannelAccessor<Datum>;
6
+ fx: ChannelAccessor<Datum>;
7
+ fy: ChannelAccessor<Datum>;
8
8
  dx: import("../types/index.js").ConstantAccessor<number, Datum>;
9
9
  dy: import("../types/index.js").ConstantAccessor<number, Datum>;
10
- fill: import("../types/channel").ChannelAccessor<Datum>;
10
+ fill: ChannelAccessor<Datum>;
11
11
  fillOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
12
12
  sort: {
13
13
  channel: string;
14
14
  order?: "ascending" | "descending";
15
15
  } | ((a: RawValue, b: RawValue) => number) | import("../types/index.js").ConstantAccessor<RawValue, Datum>;
16
- stroke: import("../types/channel").ChannelAccessor<Datum>;
16
+ stroke: ChannelAccessor<Datum>;
17
17
  strokeWidth: import("../types/index.js").ConstantAccessor<number, Datum>;
18
18
  strokeOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
19
19
  strokeLinejoin: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinejoin, Datum>;
20
20
  strokeLinecap: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinecap, Datum>;
21
21
  strokeMiterlimit: import("../types/index.js").ConstantAccessor<number, Datum>;
22
- opacity: import("../types/channel").ChannelAccessor<Datum>;
22
+ opacity: ChannelAccessor<Datum>;
23
23
  strokeDasharray: import("../types/index.js").ConstantAccessor<string, Datum>;
24
24
  strokeDashoffset: import("../types/index.js").ConstantAccessor<number, Datum>;
25
25
  mixBlendMode: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Datum>;
@@ -62,6 +62,8 @@ declare class __sveltets_Render<Datum = RawValue> {
62
62
  }>, "fill" | "fillOpacity"> & {
63
63
  data?: Datum[] | undefined;
64
64
  automatic?: boolean;
65
+ y1?: ChannelAccessor<Datum>;
66
+ y2?: ChannelAccessor<Datum>;
65
67
  };
66
68
  events(): {};
67
69
  slots(): {};
@@ -5,10 +5,18 @@
5
5
  interface GridYMarkProps extends Omit<BaseMarkProps<Datum>, 'fill' | 'fillOpacity'> {
6
6
  data?: Datum[];
7
7
  automatic?: boolean;
8
+ x1?: ChannelAccessor<Datum>;
9
+ x2?: ChannelAccessor<Datum>;
8
10
  }
9
11
  import { getContext } from 'svelte';
10
12
  import Mark from '../Mark.svelte';
11
- import type { PlotContext, BaseMarkProps, RawValue, PlotDefaults } from '../types/index.js';
13
+ import type {
14
+ PlotContext,
15
+ BaseMarkProps,
16
+ RawValue,
17
+ PlotDefaults,
18
+ ChannelAccessor
19
+ } from '../types/index.js';
12
20
  import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
13
21
  import { autoTicks } from '../helpers/autoTicks.js';
14
22
  import { testFilter } from '../helpers/index.js';
@@ -68,8 +76,12 @@
68
76
  (plot.scales.y.type === 'band' ? plot.scales.y.fn.bandwidth() * 0.5 : 0)}
69
77
  {@const x1_ = resolveChannel('x1', tick, options)}
70
78
  {@const x2_ = resolveChannel('x2', tick, options)}
71
- {@const x1 = options.x1 != null ? plot.scales.x.fn(x1_) : 0}
72
- {@const x2 = options.x2 != null ? plot.scales.x.fn(x2_) : plot.facetWidth}
79
+ {@const x1 =
80
+ options.x1 != null ? plot.scales.x.fn(x1_) : plot.options.marginLeft}
81
+ {@const x2 =
82
+ options.x2 != null
83
+ ? plot.scales.x.fn(x2_)
84
+ : plot.options.marginLeft + plot.facetWidth}
73
85
  {@const dx = +resolveProp(options?.dx, tick, 0)}
74
86
  {@const dy = +resolveProp(options?.dy, tick, 0)}
75
87
  {@const [style, styleClass] = resolveStyles(
@@ -83,7 +95,7 @@
83
95
  <line
84
96
  {style}
85
97
  class={styleClass}
86
- transform="translate({plot.options.marginLeft + dx},{y + dy})"
98
+ transform="translate({dx},{y + dy})"
87
99
  {x1}
88
100
  {x2} />
89
101
  {/if}
@@ -1,25 +1,25 @@
1
- import type { RawValue } from '../types/index.js';
1
+ import type { RawValue, ChannelAccessor } from '../types/index.js';
2
2
  declare class __sveltets_Render<Datum = RawValue> {
3
3
  props(): Omit<Partial<{
4
4
  filter?: import("../types/index.js").ConstantAccessor<boolean, Datum>;
5
5
  facet?: "auto" | "include" | "exclude";
6
- fx: import("../types/channel").ChannelAccessor<Datum>;
7
- fy: import("../types/channel").ChannelAccessor<Datum>;
6
+ fx: ChannelAccessor<Datum>;
7
+ fy: ChannelAccessor<Datum>;
8
8
  dx: import("../types/index.js").ConstantAccessor<number, Datum>;
9
9
  dy: import("../types/index.js").ConstantAccessor<number, Datum>;
10
- fill: import("../types/channel").ChannelAccessor<Datum>;
10
+ fill: ChannelAccessor<Datum>;
11
11
  fillOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
12
12
  sort: {
13
13
  channel: string;
14
14
  order?: "ascending" | "descending";
15
15
  } | ((a: RawValue, b: RawValue) => number) | import("../types/index.js").ConstantAccessor<RawValue, Datum>;
16
- stroke: import("../types/channel").ChannelAccessor<Datum>;
16
+ stroke: ChannelAccessor<Datum>;
17
17
  strokeWidth: import("../types/index.js").ConstantAccessor<number, Datum>;
18
18
  strokeOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
19
19
  strokeLinejoin: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinejoin, Datum>;
20
20
  strokeLinecap: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinecap, Datum>;
21
21
  strokeMiterlimit: import("../types/index.js").ConstantAccessor<number, Datum>;
22
- opacity: import("../types/channel").ChannelAccessor<Datum>;
22
+ opacity: ChannelAccessor<Datum>;
23
23
  strokeDasharray: import("../types/index.js").ConstantAccessor<string, Datum>;
24
24
  strokeDashoffset: import("../types/index.js").ConstantAccessor<number, Datum>;
25
25
  mixBlendMode: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Datum>;
@@ -62,6 +62,8 @@ declare class __sveltets_Render<Datum = RawValue> {
62
62
  }>, "fill" | "fillOpacity"> & {
63
63
  data?: Datum[] | undefined;
64
64
  automatic?: boolean;
65
+ x1?: ChannelAccessor<Datum>;
66
+ x2?: ChannelAccessor<Datum>;
65
67
  };
66
68
  events(): {};
67
69
  slots(): {};
@@ -48,7 +48,6 @@
48
48
  PlotDefaults
49
49
  } from '../types/index.js';
50
50
  import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
51
- import { maybeData } from '../helpers/index.js';
52
51
  import Mark from '../Mark.svelte';
53
52
  import MarkerPath from './helpers/MarkerPath.svelte';
54
53
  import { replaceChannels } from '../transforms/rename.js';
@@ -57,6 +56,8 @@
57
56
  import { maybeCurve } from '../helpers/curves.js';
58
57
  import { geoPath } from 'd3-geo';
59
58
  import { pick } from 'es-toolkit';
59
+ import { sort } from '../transforms/sort.js';
60
+ import { indexData } from '../transforms/recordize.js';
60
61
 
61
62
  let markProps: LinkMarkProps = $props();
62
63
  const DEFAULTS = {
@@ -77,17 +78,13 @@
77
78
  const { getPlotState } = getContext<PlotContext>('svelteplot');
78
79
  let plot = $derived(getPlotState());
79
80
 
80
- const sorted = $derived(
81
- options.sort
82
- ? maybeData(data).toSorted((a, b) =>
83
- resolveChannel('sort', a, options) > resolveChannel('sort', b, options) ? 1 : -1
84
- )
85
- : maybeData(data)
86
- );
87
-
88
81
  const args = $derived(
89
82
  replaceChannels(
90
- { data: sorted, stroke: 'currentColor', ...options },
83
+ sort({
84
+ data: indexData(data),
85
+ stroke: 'currentColor',
86
+ ...options
87
+ }),
91
88
  { y: ['y1', 'y2'], x: ['x1', 'x2'] }
92
89
  )
93
90
  );
@@ -30,7 +30,7 @@
30
30
  import { quadtree } from 'd3-quadtree';
31
31
  import { projectXY } from '../helpers/scales.js';
32
32
  import isDataRecord from '../helpers/isDataRecord.js';
33
- import { RAW_VALUE } from '../transforms/recordize.js';
33
+ import { indexData, RAW_VALUE } from '../transforms/recordize.js';
34
34
  import { groupFacetsAndZ } from '../helpers/group.js';
35
35
 
36
36
  const { getPlotState } = getContext<PlotContext>('svelteplot');
@@ -116,7 +116,7 @@
116
116
 
117
117
  const groups = $derived.by(() => {
118
118
  const groups = [];
119
- groupFacetsAndZ(data, { x, y, z, fx, fy }, (d) => groups.push(d));
119
+ groupFacetsAndZ(indexData(data), { x, y, z, fx, fy }, (d) => groups.push(d));
120
120
  return groups;
121
121
  });
122
122
 
@@ -3,7 +3,7 @@
3
3
  -->
4
4
  <script lang="ts" generics="Datum = DataRecord | RawValue">
5
5
  interface RuleXMarkProps extends Omit<BaseMarkProps<Datum>, 'fill' | 'fillOpacity'> {
6
- data: Datum[];
6
+ data?: Datum[];
7
7
  x?: ChannelAccessor<Datum>;
8
8
  y1?: ChannelAccessor<Datum>;
9
9
  y2?: ChannelAccessor<Datum>;
@@ -60,7 +60,7 @@ declare class __sveltets_Render<Datum = DataRecord | RawValue> {
60
60
  class: string | null;
61
61
  cursor: ConstantAccessor<import("csstype").Property.Cursor, Datum>;
62
62
  }>, "fill" | "fillOpacity"> & {
63
- data: Datum[];
63
+ data?: Datum[] | undefined;
64
64
  x?: ChannelAccessor<Datum>;
65
65
  y1?: ChannelAccessor<Datum>;
66
66
  y2?: ChannelAccessor<Datum>;
@@ -71,6 +71,7 @@
71
71
  import { sort } from '../index.js';
72
72
 
73
73
  import MultilineText from './helpers/MultilineText.svelte';
74
+ import { indexData } from '../transforms/recordize';
74
75
 
75
76
  const DEFAULTS = {
76
77
  fontSize: 12,
@@ -95,7 +96,7 @@
95
96
 
96
97
  const args = $derived(
97
98
  sort({
98
- data,
99
+ data: indexData(data),
99
100
  ...options
100
101
  })
101
102
  ) as TextMarkProps;
@@ -44,8 +44,9 @@
44
44
  import { sort } from '../index.js';
45
45
  import Mark from '../Mark.svelte';
46
46
  //import DotCanvas from './helpers/DotCanvas.svelte';
47
- import { maybeData, testFilter, isValid } from '../helpers/index.js';
47
+ import { isValid } from '../helpers/index.js';
48
48
  import { addEventHandlers } from './helpers/events.js';
49
+ import { indexData } from '../transforms/recordize.js';
49
50
 
50
51
  const defaultRadius = 3.5;
51
52
 
@@ -145,7 +146,7 @@
145
146
 
146
147
  const args = $derived(
147
148
  sort({
148
- data: maybeData(data),
149
+ data: indexData(data),
149
150
  // sort by descending radius by default
150
151
  ...options
151
152
  })
@@ -201,11 +202,11 @@
201
202
  ? `translate(0, ${d.length})`
202
203
  : `translate(0, ${d.length / 2})`}"
203
204
  {style}
204
- use:addEventHandlers={{
205
+ {@attach addEventHandlers({
205
206
  getPlotState,
206
207
  options: args,
207
- datum: d.datum
208
- }}
208
+ datum: d?.datum
209
+ })}
209
210
  class={[styleClass]} />
210
211
  {/if}
211
212
  {/each}