svelteplot 0.2.9-pr-104.2 → 0.2.9-pr-109.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.
@@ -55,9 +55,7 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
55
55
  // we're deliberately checking for !== undefined and not for != null
56
56
  // since the explicit sort transforms like shuffle will set the
57
57
  // sort channel to null to we know that there's an explicit order
58
- if (name === 'y')
59
- console.log(mark.type, mark.options[IS_SORTED]);
60
- if (mark.options[IS_SORTED] != null) {
58
+ if ((name === 'x' || name === 'y') && mark.options[IS_SORTED] != undefined) {
61
59
  sortOrdinalDomain = false;
62
60
  }
63
61
  for (const channel of mark.channels) {
@@ -139,6 +137,12 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
139
137
  }
140
138
  }
141
139
  }
140
+ if ((name === 'x' || name === 'y') && scaleOptions.sort) {
141
+ sortOrdinalDomain = true;
142
+ }
143
+ if ((name === 'x' || name === 'y') && scaleOptions.sort === false) {
144
+ sortOrdinalDomain = false;
145
+ }
142
146
  // construct domain from data values
143
147
  const valueArr = [...dataValues.values(), ...(scaleOptions.domain || [])].filter((d) => d != null);
144
148
  const type = scaleOptions.type === 'auto'
@@ -29,6 +29,7 @@
29
29
  import { maybeCurve } from '../helpers/curves.js';
30
30
  import { isValid } from '../helpers/index.js';
31
31
  import AreaCanvas from './helpers/AreaCanvas.svelte';
32
+ import Anchor from './helpers/Anchor.svelte';
32
33
 
33
34
  import type {
34
35
  CurveName,
@@ -37,7 +38,6 @@
37
38
  BaseMarkProps,
38
39
  ConstantAccessor,
39
40
  ChannelAccessor,
40
- FacetContext,
41
41
  ScaledDataRecord,
42
42
  LinkableMarkProps
43
43
  } from '../types.js';
@@ -113,32 +113,24 @@
113
113
  {:else}
114
114
  <GroupMultiple length={grouped.length}>
115
115
  {#each grouped as areaData, i (i)}
116
- {#snippet el(datum: ScaledDataRecord)}
117
- {@const title = resolveProp(options.title, datum.datum, '')}
118
- {@const [style, styleClass] = resolveStyles(
119
- plot,
120
- datum,
121
- options,
122
- 'fill',
123
- usedScales
124
- )}
125
- <path
126
- class={['svelteplot-area', className, styleClass]}
127
- clip-path={options.clipPath}
128
- d={areaPath(areaData)}
129
- {style}
130
- >{#if title}<title>{title}</title>{/if}</path>
131
- {/snippet}
116
+ {@const datum = areaData[0]}
132
117
  {#if areaData.length > 0}
133
- {#if options.href}
134
- <a
135
- href={resolveProp(options.href, areaData[0].datum, '')}
136
- target={resolveProp(options.target, areaData[0].datum, '_self')}>
137
- {@render el(areaData[0])}
138
- </a>
139
- {:else}
140
- {@render el(areaData[0])}
141
- {/if}
118
+ <Anchor {options} {datum}>
119
+ {@const title = resolveProp(options.title, datum.datum, '')}
120
+ {@const [style, styleClass] = resolveStyles(
121
+ plot,
122
+ datum,
123
+ options,
124
+ 'fill',
125
+ usedScales
126
+ )}
127
+ <path
128
+ class={['svelteplot-area', className, styleClass]}
129
+ clip-path={options.clipPath}
130
+ d={areaPath(areaData)}
131
+ {style}
132
+ >{#if title}<title>{title}</title>{/if}</path>
133
+ </Anchor>
142
134
  {/if}
143
135
  {/each}
144
136
  </GroupMultiple>
@@ -99,7 +99,7 @@
99
99
  const ticks: RawValue[] = $derived(
100
100
  data.length > 0
101
101
  ? // use custom tick values if user passed any as prop
102
- data
102
+ Array.from(new Set(data))
103
103
  : // use custom scale tick values if user passed any as plot scale option
104
104
  autoTicks(
105
105
  plot.scales.x.type,
@@ -7,10 +7,12 @@
7
7
  PlotContext,
8
8
  BaseMarkProps,
9
9
  BaseRectMarkProps,
10
- ChannelAccessor
10
+ ChannelAccessor,
11
+ LinkableMarkProps
11
12
  } from '../types.js';
12
13
 
13
14
  export type BarXMarkProps = BaseMarkProps &
15
+ LinkableMarkProps &
14
16
  BaseRectMarkProps & {
15
17
  data: DataRow[];
16
18
  x?: ChannelAccessor;
@@ -1,5 +1,5 @@
1
- import type { BaseMarkProps, BaseRectMarkProps, ChannelAccessor } from '../types.js';
2
- export type BarXMarkProps = BaseMarkProps & BaseRectMarkProps & {
1
+ import type { BaseMarkProps, BaseRectMarkProps, ChannelAccessor, LinkableMarkProps } from '../types.js';
2
+ export type BarXMarkProps = BaseMarkProps & LinkableMarkProps & BaseRectMarkProps & {
3
3
  data: DataRow[];
4
4
  x?: ChannelAccessor;
5
5
  x1?: ChannelAccessor;
@@ -12,6 +12,7 @@
12
12
  } from '../types.js';
13
13
 
14
14
  export type BarYMarkProps = BaseMarkProps &
15
+ LinkableMarkProps &
15
16
  BaseRectMarkProps & {
16
17
  data: DataRow[];
17
18
  x?: ChannelAccessor;
@@ -1,5 +1,5 @@
1
1
  import type { BaseMarkProps, BaseRectMarkProps, ChannelAccessor, DataRow } from '../types.js';
2
- export type BarYMarkProps = BaseMarkProps & BaseRectMarkProps & {
2
+ export type BarYMarkProps = BaseMarkProps & LinkableMarkProps & BaseRectMarkProps & {
3
3
  data: DataRow[];
4
4
  x?: ChannelAccessor;
5
5
  y?: ChannelAccessor;
@@ -14,6 +14,6 @@ export type BarYMarkProps = BaseMarkProps & BaseRectMarkProps & {
14
14
  };
15
15
  import type { StackOptions } from '../transforms/stack.js';
16
16
  /** For vertical column charts using a band scale as x axis */
17
- declare const BarY: import("svelte").Component<BarYMarkProps, {}, "">;
17
+ declare const BarY: import("svelte").Component<any, {}, "">;
18
18
  type BarY = ReturnType<typeof BarY>;
19
19
  export default BarY;
@@ -1,4 +1,4 @@
1
- <script module type="ts">
1
+ <script module lang="ts">
2
2
  export type BrushXMarkProps = Omit<BrushMarkProps, 'limitDimension'>;
3
3
  </script>
4
4
 
@@ -1,4 +1,4 @@
1
- <script module type="ts">
1
+ <script module lang="ts">
2
2
  export type BrushYMarkProps = Omit<BrushMarkProps, 'limitDimension'>;
3
3
  </script>
4
4
 
@@ -12,6 +12,7 @@
12
12
  } from '../types.js';
13
13
 
14
14
  export type CellMarkProps = BaseMarkProps &
15
+ LinkableMarkProps &
15
16
  BaseRectMarkProps & {
16
17
  data: DataRecord[];
17
18
  x?: ChannelAccessor;
@@ -1,10 +1,10 @@
1
1
  import type { DataRecord, BaseMarkProps, BaseRectMarkProps, ChannelAccessor } from '../types.js';
2
- export type CellMarkProps = BaseMarkProps & BaseRectMarkProps & {
2
+ export type CellMarkProps = BaseMarkProps & LinkableMarkProps & BaseRectMarkProps & {
3
3
  data: DataRecord[];
4
4
  x?: ChannelAccessor;
5
5
  y?: ChannelAccessor;
6
6
  };
7
7
  /** For arbitrary rectangles, requires band x and y scales */
8
- declare const Cell: import("svelte").Component<CellMarkProps, {}, "">;
8
+ declare const Cell: import("svelte").Component<any, {}, "">;
9
9
  type Cell = ReturnType<typeof Cell>;
10
10
  export default Cell;
@@ -10,7 +10,7 @@
10
10
  symbol?: ChannelAccessor | Snippet<[number, string]>;
11
11
  canvas?: boolean;
12
12
  dotClass?: ConstantAccessor<string>;
13
- };
13
+ } & LinkableMarkProps;
14
14
  </script>
15
15
 
16
16
  <script lang="ts">
@@ -21,8 +21,8 @@
21
21
  BaseMarkProps,
22
22
  ConstantAccessor,
23
23
  ChannelAccessor,
24
- FacetContext,
25
- PlotDefaults
24
+ PlotDefaults,
25
+ LinkableMarkProps
26
26
  } from '../types.js';
27
27
  import { resolveProp, resolveStyles } from '../helpers/resolve.js';
28
28
  import { maybeSymbol } from '../helpers/symbols.js';
@@ -33,6 +33,7 @@
33
33
  import { maybeData, isValid } from '../helpers/index.js';
34
34
  import { recordizeXY } from '../transforms/recordize.js';
35
35
  import { addEventHandlers } from './helpers/events.js';
36
+ import Anchor from './helpers/Anchor.svelte';
36
37
 
37
38
  let {
38
39
  data = [{}],
@@ -49,7 +50,6 @@
49
50
  return d3Symbol(maybeSymbol(symbolType), size)();
50
51
  }
51
52
 
52
- const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
53
53
  const { dotRadius } = getContext<PlotDefaults>('svelteplot/_defaults');
54
54
 
55
55
  const args = $derived(
@@ -96,19 +96,21 @@
96
96
  'stroke',
97
97
  usedScales
98
98
  )}
99
- <path
100
- transform="translate({d.x}, {d.y})"
101
- d={getSymbolPath(d.symbol, d.r ** 2 * Math.PI)}
102
- class={[
103
- dotClass ? resolveProp(dotClass, d.datum, null) : null,
104
- styleClass
105
- ]}
106
- {style}
107
- use:addEventHandlers={{
108
- getPlotState,
109
- options: args,
110
- datum: d.datum
111
- }} />
99
+ <Anchor {options} datum={d.datum}>
100
+ <path
101
+ transform="translate({d.x}, {d.y})"
102
+ d={getSymbolPath(d.symbol, d.r ** 2 * Math.PI)}
103
+ class={[
104
+ dotClass ? resolveProp(dotClass, d.datum, null) : null,
105
+ styleClass
106
+ ]}
107
+ {style}
108
+ use:addEventHandlers={{
109
+ getPlotState,
110
+ options: args,
111
+ datum: d.datum
112
+ }} />
113
+ </Anchor>
112
114
  {/if}
113
115
  {/each}
114
116
  {/if}
@@ -6,9 +6,9 @@ export type DotMarkProps = BaseMarkProps & {
6
6
  symbol?: ChannelAccessor | Snippet<[number, string]>;
7
7
  canvas?: boolean;
8
8
  dotClass?: ConstantAccessor<string>;
9
- };
9
+ } & LinkableMarkProps;
10
10
  import { type Snippet } from 'svelte';
11
- import type { DataRecord, BaseMarkProps, ConstantAccessor, ChannelAccessor } from '../types.js';
11
+ import type { DataRecord, BaseMarkProps, ConstantAccessor, ChannelAccessor, LinkableMarkProps } from '../types.js';
12
12
  /** Creates dots or symbols at specified positions with customizable size and appearance */
13
13
  declare const Dot: import("svelte").Component<DotMarkProps, {}, "">;
14
14
  type Dot = ReturnType<typeof Dot>;
@@ -7,6 +7,7 @@
7
7
  BaseMarkProps,
8
8
  'fill' | 'stroke' | 'fillOpacity' | 'strokeOpacity'
9
9
  > &
10
+ LinkableMarkProps &
10
11
  Omit<
11
12
  BaseRectMarkProps,
12
13
  'inset' | 'insetLeft' | 'insetRight' | 'insetTop' | 'insetBottom'
@@ -27,7 +28,7 @@
27
28
  <script lang="ts">
28
29
  import Mark from '../Mark.svelte';
29
30
  import { getContext } from 'svelte';
30
- import type { PlotContext, BaseRectMarkProps } from '../types.js';
31
+ import type { PlotContext, BaseRectMarkProps, LinkableMarkProps } from '../types.js';
31
32
  import type { BaseMarkProps } from '../types.js';
32
33
  import RectPath from './helpers/RectPath.svelte';
33
34
 
@@ -1,4 +1,4 @@
1
- export type FrameMarkProps = Omit<BaseMarkProps, 'fill' | 'stroke' | 'fillOpacity' | 'strokeOpacity'> & Omit<BaseRectMarkProps, 'inset' | 'insetLeft' | 'insetRight' | 'insetTop' | 'insetBottom'> & {
1
+ export type FrameMarkProps = Omit<BaseMarkProps, 'fill' | 'stroke' | 'fillOpacity' | 'strokeOpacity'> & LinkableMarkProps & Omit<BaseRectMarkProps, 'inset' | 'insetLeft' | 'insetRight' | 'insetTop' | 'insetBottom'> & {
2
2
  fill: string;
3
3
  stroke: string;
4
4
  fillOpacity: number;
@@ -10,7 +10,7 @@ export type FrameMarkProps = Omit<BaseMarkProps, 'fill' | 'stroke' | 'fillOpacit
10
10
  insetTop?: number;
11
11
  insetBottom?: number;
12
12
  };
13
- import type { BaseRectMarkProps } from '../types.js';
13
+ import type { BaseRectMarkProps, LinkableMarkProps } from '../types.js';
14
14
  import type { BaseMarkProps } from '../types.js';
15
15
  /** Renders a simple frame around the entire plot domain */
16
16
  declare const Frame: import("svelte").Component<FrameMarkProps, {}, "">;
@@ -7,8 +7,10 @@
7
7
  geoType?: 'sphere' | 'graticule';
8
8
  dragRotate: boolean;
9
9
  canvas: boolean;
10
- href: ConstantAccessor<string>;
11
- target: ConstantAccessor<string>;
10
+ /**
11
+ * simple browser tooltip to be displayed on mouseover
12
+ */
13
+ title: ConstantAccessor<string>;
12
14
  } & BaseMarkProps &
13
15
  LinkableMarkProps;
14
16
  </script>
@@ -31,6 +33,7 @@
31
33
  import GeoCanvas from './helpers/GeoCanvas.svelte';
32
34
  import { recordize } from '../transforms/recordize.js';
33
35
  import { GEOJSON_PREFER_STROKE } from '../helpers/index.js';
36
+ import Anchor from './helpers/Anchor.svelte';
34
37
 
35
38
  const { getPlotState } = getContext<PlotContext>('svelteplot');
36
39
  const plot = $derived(getPlotState());
@@ -68,28 +71,6 @@
68
71
  channels={['fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity', 'r']}
69
72
  {...args}>
70
73
  {#snippet children({ mark, scaledData, usedScales })}
71
- {#snippet el(d)}
72
- {@const title = resolveProp(args.title, d.datum, '')}
73
- {@const geometry = resolveProp(args.geometry, d.datum, d.datum)}
74
- {@const [style, styleClass] = resolveStyles(
75
- plot,
76
- d,
77
- args,
78
- GEOJSON_PREFER_STROKE.has(geometry.type) ? 'stroke' : 'fill',
79
- usedScales
80
- )}
81
- <path
82
- d={path(geometry)}
83
- {style}
84
- class={[styleClass]}
85
- use:addEventHandlers={{
86
- getPlotState,
87
- options: args,
88
- datum: d.datum
89
- }}>
90
- {#if title}<title>{title}</title>{/if}
91
- </path>
92
- {/snippet}
93
74
  <g
94
75
  aria-label="geo"
95
76
  class={['geo', geoType && `geo-${geoType}`, className]}
@@ -99,15 +80,28 @@
99
80
  {:else}
100
81
  {#each scaledData as d, i (i)}
101
82
  {#if d.valid}
102
- {#if options.href}
103
- <a
104
- href={resolveProp(args.href, d.datum, '')}
105
- target={resolveProp(args.target, d.datum, '_self')}>
106
- {@render el(d)}
107
- </a>
108
- {:else}
109
- {@render el(d)}
110
- {/if}
83
+ <Anchor {options} datum={d.datum}>
84
+ {@const title = resolveProp(args.title, d.datum, '')}
85
+ {@const geometry = resolveProp(args.geometry, d.datum, d.datum)}
86
+ {@const [style, styleClass] = resolveStyles(
87
+ plot,
88
+ d,
89
+ args,
90
+ GEOJSON_PREFER_STROKE.has(geometry.type) ? 'stroke' : 'fill',
91
+ usedScales
92
+ )}
93
+ <path
94
+ d={path(geometry)}
95
+ {style}
96
+ class={[styleClass]}
97
+ use:addEventHandlers={{
98
+ getPlotState,
99
+ options: args,
100
+ datum: d.datum
101
+ }}>
102
+ {#if title}<title>{title}</title>{/if}
103
+ </path>
104
+ </Anchor>
111
105
  {/if}
112
106
  {/each}
113
107
  {/if}
@@ -3,8 +3,10 @@ export type GeoMarkProps = {
3
3
  geoType?: 'sphere' | 'graticule';
4
4
  dragRotate: boolean;
5
5
  canvas: boolean;
6
- href: ConstantAccessor<string>;
7
- target: ConstantAccessor<string>;
6
+ /**
7
+ * simple browser tooltip to be displayed on mouseover
8
+ */
9
+ title: ConstantAccessor<string>;
8
10
  } & BaseMarkProps & LinkableMarkProps;
9
11
  import type { DataRecord, BaseMarkProps, ConstantAccessor, LinkableMarkProps } from '../types.js';
10
12
  /** Renders geographical data using projections and GeoJSON geometries */
@@ -13,6 +13,7 @@
13
13
  y2?: ChannelAccessor;
14
14
  interval?: number | string;
15
15
  } & BaseMarkProps &
16
+ LinkableMarkProps &
16
17
  BaseRectMarkProps;
17
18
  </script>
18
19
 
@@ -7,9 +7,9 @@ export type RectMarkProps = {
7
7
  y1?: ChannelAccessor;
8
8
  y2?: ChannelAccessor;
9
9
  interval?: number | string;
10
- } & BaseMarkProps & BaseRectMarkProps;
10
+ } & BaseMarkProps & LinkableMarkProps & BaseRectMarkProps;
11
11
  import type { DataRecord, BaseMarkProps, BaseRectMarkProps, ChannelAccessor } from '../types.js';
12
12
  /** For arbitrary rectangles, requires quantitative x and y scales */
13
- declare const Rect: import("svelte").Component<RectMarkProps, {}, "">;
13
+ declare const Rect: import("svelte").Component<any, {}, "">;
14
14
  type Rect = ReturnType<typeof Rect>;
15
15
  export default Rect;
@@ -2,8 +2,8 @@
2
2
  Geo mark with Sphere geometry object -->
3
3
 
4
4
  <script module lang="ts">
5
- import { type BaseMarkProps } from '../types.js';
6
- export type SphereMarkProps = BaseMarkProps;
5
+ import { type BaseMarkProps, type LinkableMarkProps } from '../types.js';
6
+ export type SphereMarkProps = BaseMarkProps & LinkableMarkProps;
7
7
  </script>
8
8
 
9
9
  <script lang="ts">
@@ -1,6 +1,6 @@
1
- import { type BaseMarkProps } from '../types.js';
2
- export type SphereMarkProps = BaseMarkProps;
1
+ import { type BaseMarkProps, type LinkableMarkProps } from '../types.js';
2
+ export type SphereMarkProps = BaseMarkProps & LinkableMarkProps;
3
3
  /** Geo mark with Sphere geometry object */
4
- declare const Sphere: import("svelte").Component<BaseMarkProps, {}, "">;
4
+ declare const Sphere: import("svelte").Component<any, {}, "">;
5
5
  type Sphere = ReturnType<typeof Sphere>;
6
6
  export default Sphere;
@@ -0,0 +1,37 @@
1
+ <script>
2
+ import { resolveProp } from '../../helpers/resolve';
3
+
4
+ let { datum = {}, options = {}, children } = $props();
5
+
6
+ const href = $derived(resolveProp(options.href, datum, null));
7
+ const target = $derived(resolveProp(options.target, datum, null));
8
+ const rel = $derived(resolveProp(options.rel, datum, null));
9
+ const type = $derived(resolveProp(options.type, datum, null));
10
+ const download = $derived(resolveProp(options.download, datum, null));
11
+
12
+ // filter data attributes from options
13
+ const dataAttributes = $derived(
14
+ Object.fromEntries(
15
+ Object.entries(options).filter(([key]) => key.startsWith('data-sveltekit-'))
16
+ )
17
+ );
18
+ </script>
19
+
20
+ {#if href}
21
+ <!-- we can't use <a> directly here because Svelte confuses it with the
22
+ HTMLAElement which breaks the rendering -->
23
+ <svelte:element
24
+ this={'a'}
25
+ {href}
26
+ {target}
27
+ {rel}
28
+ {type}
29
+ {download}
30
+ {...dataAttributes}
31
+ aria-label="link"
32
+ xmlns="http://www.w3.org/2000/svg">
33
+ {@render children?.()}
34
+ </svelte:element>
35
+ {:else}
36
+ {@render children?.()}
37
+ {/if}
@@ -0,0 +1,15 @@
1
+ export default Anchor;
2
+ type Anchor = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Anchor: import("svelte").Component<{
7
+ datum?: Record<string, any>;
8
+ options?: Record<string, any>;
9
+ children: any;
10
+ }, {}, "">;
11
+ type $$ComponentProps = {
12
+ datum?: Record<string, any>;
13
+ options?: Record<string, any>;
14
+ children: any;
15
+ };
@@ -14,6 +14,7 @@ Helper component for rendering rectangular marks in SVG
14
14
  } from '../../types';
15
15
  import { addEventHandlers } from './events';
16
16
  import { getContext } from 'svelte';
17
+ import Anchor from './Anchor.svelte';
17
18
 
18
19
  let {
19
20
  datum,
@@ -101,33 +102,35 @@ Helper component for rendering rectangular marks in SVG
101
102
  );
102
103
  </script>
103
104
 
104
- {#if hasBorderRadius}
105
- <path
106
- transform="translate({x + dx + insetLeft},{y + insetBottom + dy})"
107
- d={roundedRect(
108
- 0,
109
- 0,
110
- width - insetLeft - insetRight,
111
- height - insetTop - insetBottom,
112
- borderRadius
113
- )}
114
- class={[styleClass, className]}
115
- {style}
116
- use:addEventHandlers={{
117
- getPlotState,
118
- options,
119
- datum: datum?.datum
120
- }} />
121
- {:else}
122
- <rect
123
- transform="translate({x + dx + insetLeft},{y + insetBottom + dy})"
124
- width={width - insetLeft - insetRight}
125
- height={height - insetTop - insetBottom}
126
- class={[styleClass, className]}
127
- {style}
128
- use:addEventHandlers={{
129
- getPlotState,
130
- options,
131
- datum: datum?.datum
132
- }} />
133
- {/if}
105
+ <Anchor {options} datum={datum?.datum}>
106
+ {#if hasBorderRadius}
107
+ <path
108
+ transform="translate({x + dx + insetLeft},{y + insetBottom + dy})"
109
+ d={roundedRect(
110
+ 0,
111
+ 0,
112
+ width - insetLeft - insetRight,
113
+ height - insetTop - insetBottom,
114
+ borderRadius
115
+ )}
116
+ class={[styleClass, className]}
117
+ {style}
118
+ use:addEventHandlers={{
119
+ getPlotState,
120
+ options,
121
+ datum: datum?.datum
122
+ }} />
123
+ {:else}
124
+ <rect
125
+ transform="translate({x + dx + insetLeft},{y + insetBottom + dy})"
126
+ width={width - insetLeft - insetRight}
127
+ height={height - insetTop - insetBottom}
128
+ class={[styleClass, className]}
129
+ {style}
130
+ use:addEventHandlers={{
131
+ getPlotState,
132
+ options,
133
+ datum: datum?.datum
134
+ }} />
135
+ {/if}
136
+ </Anchor>
@@ -5,7 +5,7 @@ export declare function sort({ data, ...channels }: TransformArg<DataRecord>, op
5
5
  reverse?: boolean;
6
6
  }): any;
7
7
  /**
8
- * reverses the data row order
8
+ * shuffles the data row order
9
9
  */
10
10
  export declare function shuffle({ data, ...channels }: TransformArg<DataRow[]>, options?: {
11
11
  seed?: number;
@@ -15,18 +15,24 @@ export function sort({ data, ...channels }, options = {}) {
15
15
  sort.channel = sort.channel.substring(1);
16
16
  sort.order = 'descending';
17
17
  }
18
+ // if sort is a function that does not take exactly one argument, we treat it
19
+ // as comparator function, as you would pass to array.sort
20
+ const isComparator = typeof channels.sort === 'function' && channels.sort.length !== 1;
18
21
  // sort data
19
22
  return {
20
- data: data
21
- .map((d) => ({
22
- ...d,
23
- [SORT_KEY]: resolveChannel('sort', d, { ...channels, sort })
24
- }))
25
- .toSorted((a, b) => (a[SORT_KEY] > b[SORT_KEY] ? 1 : a[SORT_KEY] < b[SORT_KEY] ? -1 : 0) *
26
- (options.reverse || (isDataRecord(sort) && sort?.order === 'descending')
27
- ? -1
28
- : 1))
29
- .map(({ [SORT_KEY]: a, ...rest }) => rest),
23
+ data: isComparator
24
+ ? data.toSorted(channels.sort)
25
+ : data
26
+ .map((d) => ({
27
+ ...d,
28
+ [SORT_KEY]: resolveChannel('sort', d, { ...channels, sort })
29
+ }))
30
+ .toSorted((a, b) => (a[SORT_KEY] > b[SORT_KEY] ? 1 : a[SORT_KEY] < b[SORT_KEY] ? -1 : 0) *
31
+ (options.reverse ||
32
+ (isDataRecord(sort) && sort?.order === 'descending')
33
+ ? -1
34
+ : 1))
35
+ .map(({ [SORT_KEY]: a, ...rest }) => rest),
30
36
  ...channels,
31
37
  [IS_SORTED]: sort,
32
38
  // set the sort channel to null to disable the implicit alphabetical
@@ -41,7 +47,7 @@ export function sort({ data, ...channels }, options = {}) {
41
47
  };
42
48
  }
43
49
  /**
44
- * reverses the data row order
50
+ * shuffles the data row order
45
51
  */
46
52
  export function shuffle({ data, ...channels }, options = {}) {
47
53
  const random = randomLcg(options.seed);
@@ -51,7 +57,8 @@ export function shuffle({ data, ...channels }, options = {}) {
51
57
  ...channels,
52
58
  // set the sort channel to null to disable the implicit
53
59
  // alphabetical ordering of ordinal domains
54
- sort: null
60
+ sort: null,
61
+ [IS_SORTED]: true
55
62
  };
56
63
  }
57
64
  /**
@@ -63,6 +70,7 @@ export function reverse({ data, ...channels }) {
63
70
  ...channels,
64
71
  // set the sort channel to null to disable the implicit
65
72
  // alphabetical ordering of ordinal domains
66
- sort: null
73
+ sort: null,
74
+ [IS_SORTED]: true
67
75
  };
68
76
  }
package/dist/types.d.ts CHANGED
@@ -490,15 +490,30 @@ export type FacetContext = {
490
490
  };
491
491
  export type LinkableMarkProps = {
492
492
  /**
493
- * simple browser tooltip to be displayed on mouseover
493
+ * if set, the mark element will be wrapped in a <a> link element
494
494
  */
495
- title: ConstantAccessor<string>;
495
+ href: ConstantAccessor<string>;
496
496
  /**
497
- * if set, the mark element will be wrapped in a <a> link
498
- * element
497
+ * the relationship of the target object to the link object (e.g. "noopener")
498
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#rel
499
499
  */
500
- href: ConstantAccessor<string>;
501
- target: ConstantAccessor<'_self' | '_blank' | string>;
500
+ rel: ConstantAccessor<string>;
501
+ /**
502
+ * the link target mime type, e.g. "text/csv"
503
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#type
504
+ */
505
+ type: ConstantAccessor<string>;
506
+ /**
507
+ * the target of the link, e.g. "_blank" or "_self"
508
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#target
509
+ */
510
+ target: ConstantAccessor<'_self' | '_blank' | '_parent' | '_top' | string>;
511
+ /**
512
+ * if set to true, the link will be downloaded instead of navigating to it
513
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#download
514
+ */
515
+ download: ConstantAccessor<boolean>;
516
+ [key: `data-sveltekit-${string}`]: string | boolean;
502
517
  };
503
518
  export type BaseMarkProps = Partial<{
504
519
  /**
@@ -512,7 +527,7 @@ export type BaseMarkProps = Partial<{
512
527
  dy: ConstantAccessor<number>;
513
528
  fill: ConstantAccessor<string>;
514
529
  fillOpacity: ConstantAccessor<number>;
515
- sort: string | ConstantAccessor<RawValue> | {
530
+ sort: string | ConstantAccessor<RawValue> | ((a: RawValue, b: RawValue) => number) | {
516
531
  /** sort data using an already defined channel */
517
532
  channel: string;
518
533
  /** sort order */
@@ -583,7 +598,7 @@ export type BaseRectMarkProps = {
583
598
  borderRadius?: BorderRadius;
584
599
  };
585
600
  export type Channels = Record<string, ChannelAccessor | ConstantAccessor<string | number | boolean | symbol>>;
586
- export type TransformArg<K> = Channels & {
601
+ export type TransformArg<K> = Channels & BaseMarkProps & {
587
602
  data: K[];
588
603
  };
589
604
  export type MapArg<K> = Channels & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteplot",
3
- "version": "0.2.9-pr-104.2",
3
+ "version": "0.2.9-pr-109.0",
4
4
  "license": "ISC",
5
5
  "author": {
6
6
  "name": "Gregor Aisch",
@@ -80,15 +80,15 @@
80
80
  "d3-force": "^3.0.0",
81
81
  "eslint": "^9.28.0",
82
82
  "eslint-config-prettier": "^10.1.5",
83
- "eslint-plugin-svelte": "3.9.0",
83
+ "eslint-plugin-svelte": "3.9.1",
84
84
  "jsdom": "^26.1.0",
85
85
  "prettier": "^3.5.3",
86
86
  "prettier-plugin-svelte": "^3.4.0",
87
- "puppeteer": "^24.9.0",
87
+ "puppeteer": "^24.10.0",
88
88
  "remark-code-extra": "^1.0.1",
89
89
  "remark-code-frontmatter": "^1.0.0",
90
90
  "resize-observer-polyfill": "^1.5.1",
91
- "sass": "^1.89.0",
91
+ "sass": "^1.89.1",
92
92
  "svelte-check": "^4.2.1",
93
93
  "svelte-eslint-parser": "1.2.0",
94
94
  "svelte-highlight": "^7.8.3",
@@ -97,7 +97,7 @@
97
97
  "ts-essentials": "^10.0.4",
98
98
  "tslib": "^2.8.1",
99
99
  "typedoc": "^0.28.5",
100
- "typedoc-plugin-markdown": "^4.6.3",
100
+ "typedoc-plugin-markdown": "^4.6.4",
101
101
  "typescript": "^5.8.3",
102
102
  "vite": "^6.3.5",
103
103
  "vitest": "^3.1.4",
@@ -122,6 +122,6 @@
122
122
  "es-toolkit": "^1.38.0",
123
123
  "fast-equals": "^5.2.2",
124
124
  "merge-deep": "^3.0.3",
125
- "svelte": "5.33.10"
125
+ "svelte": "5.33.13"
126
126
  }
127
127
  }