layerchart 0.54.1 → 0.56.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.
@@ -1,14 +1,17 @@
1
1
  <script lang="ts">
2
- import { createEventDispatcher } from 'svelte';
2
+ import { createEventDispatcher, type ComponentProps } from 'svelte';
3
3
  import type { SVGAttributes } from 'svelte/elements';
4
- import { extent } from 'd3-array';
4
+ import { extent, min, max } from 'd3-array';
5
5
  import { clamp } from '@layerstack/utils';
6
6
  import { cls } from '@layerstack/tailwind';
7
+ import { format as formatValue, type FormatType } from '@layerstack/utils';
7
8
 
8
9
  import { chartContext } from './ChartContext.svelte';
9
10
  import Frame from './Frame.svelte';
10
- import { localPoint } from '../utils/event.js';
11
11
  import Group from './Group.svelte';
12
+ import Text from './Text.svelte';
13
+
14
+ import { localPoint } from '../utils/event.js';
12
15
 
13
16
  const { xScale, yScale, width, height, padding } = chartContext();
14
17
 
@@ -36,6 +39,8 @@
36
39
  number,
37
40
  ];
38
41
 
42
+ export let labels: ComponentProps<Text> | boolean = false;
43
+
39
44
  // Capture original domains for reset()
40
45
  const originalXDomain = $xScale.domain() as [number, number];
41
46
  const originalYDomain = $yScale.domain() as [number, number];
@@ -49,11 +54,15 @@
49
54
  /** Attributes passed to handle <rect> elements */
50
55
  export let handle: SVGAttributes<SVGRectElement> | undefined = undefined;
51
56
 
57
+ /** Apply format to labels, if shown */
58
+ export let format: FormatType | undefined = undefined;
59
+
52
60
  export let classes: {
53
61
  root?: string;
54
62
  frame?: string;
55
63
  range?: string;
56
64
  handle?: string;
65
+ labels?: string;
57
66
  } = {};
58
67
 
59
68
  let frameEl: SVGRectElement;
@@ -115,17 +124,31 @@
115
124
  };
116
125
  }
117
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
+
118
136
  const createRange = handler((start, value) => {
119
137
  isActive = true;
120
138
 
121
139
  xDomain = [
122
- clamp(Math.min(start.value.x, value.x), xDomainMin, xDomainMax),
123
- 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),
124
144
  ];
145
+ // xDomain = [start.value.x, value.x];
125
146
 
126
147
  yDomain = [
127
- clamp(Math.min(start.value.y, value.y), yDomainMin, yDomainMax),
128
- 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),
129
152
  ];
130
153
  });
131
154
 
@@ -135,14 +158,14 @@
135
158
  xDomainMin - start.xDomain[0],
136
159
  xDomainMax - start.xDomain[1]
137
160
  );
138
- xDomain = [Number(start.xDomain[0]) + dx, Number(start.xDomain[1]) + dx];
161
+ xDomain = [add(start.xDomain[0], dx), add(start.xDomain[1], dx)];
139
162
 
140
163
  const dy = clamp(
141
164
  value.y - start.value.y,
142
165
  yDomainMin - start.yDomain[0],
143
166
  yDomainMax - start.yDomain[1]
144
167
  );
145
- yDomain = [Number(start.yDomain[0]) + dy, Number(start.yDomain[1]) + dy];
168
+ yDomain = [add(start.yDomain[0], dy), add(start.yDomain[1], dy)];
146
169
  });
147
170
 
148
171
  const adjustBottom = handler((start, value) => {
@@ -201,6 +224,11 @@
201
224
  xDomain[1]?.valueOf() !== originalXDomain[1]?.valueOf() ||
202
225
  yDomain[0]?.valueOf() !== originalYDomain[0]?.valueOf() ||
203
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
+ }
204
232
  </script>
205
233
 
206
234
  <g class={cls('Brush select-none', classes.root, $$props.class)}>
@@ -313,6 +341,64 @@
313
341
  </Group>
314
342
  {/if}
315
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
+
316
402
  <!-- TODO: Add diagonal/corner handles -->
317
403
  {/if}
318
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,9 +1,12 @@
1
1
  <script lang="ts">
2
- import { tick } from 'svelte';
2
+ import { tick, type ComponentProps } from 'svelte';
3
3
  import type { spring as springStore, tweened as tweenedStore } from 'svelte/motion';
4
4
  import { cls } from '@layerstack/tailwind';
5
5
 
6
6
  import { motionStore } from '../stores/motionStore.js';
7
+ import { uniqueId } from '@layerstack/utils';
8
+
9
+ import Marker from './Marker.svelte';
7
10
 
8
11
  export let x1: number;
9
12
  export let initialX1 = x1;
@@ -17,6 +20,19 @@
17
20
  export let y2: number;
18
21
  export let initialY2 = y2;
19
22
 
23
+ /** Marker to attach to start and end points of path */
24
+ export let marker: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
25
+ undefined;
26
+ /** Marker to attach to start point of path */
27
+ export let markerStart: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
28
+ marker;
29
+ /** Marker to attach to end point of path */
30
+ export let markerEnd: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
31
+ marker;
32
+
33
+ $: markerStartId = markerStart || $$slots['markerStart'] ? uniqueId('marker-') : '';
34
+ $: markerEndId = markerEnd || $$slots['markerEnd'] ? uniqueId('marker-') : '';
35
+
20
36
  export let spring: boolean | Parameters<typeof springStore>[1] = undefined;
21
37
  export let tweened: boolean | Parameters<typeof tweenedStore>[1] = undefined;
22
38
 
@@ -39,9 +55,29 @@
39
55
  y1={$tweened_y1}
40
56
  x2={$tweened_x2}
41
57
  y2={$tweened_y2}
58
+ marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
59
+ marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
42
60
  class={cls($$props.stroke === undefined && 'stroke-surface-content')}
43
61
  {...$$restProps}
44
62
  on:click
45
63
  on:pointermove
46
64
  on:pointerleave
47
65
  />
66
+
67
+ <slot name="markerStart" id={markerStartId}>
68
+ {#if markerStart}
69
+ <Marker
70
+ id={markerStartId}
71
+ type={typeof markerStart === 'string' ? markerStart : undefined}
72
+ {...typeof markerStart === 'object' ? markerStart : null}
73
+ />
74
+ {/if}
75
+ </slot>
76
+
77
+ <slot name="markerEnd" id={markerEndId}>
78
+ <Marker
79
+ id={markerEndId}
80
+ type={typeof markerEnd === 'string' ? markerEnd : undefined}
81
+ {...typeof markerEnd === 'object' ? markerEnd : null}
82
+ />
83
+ </slot>
@@ -1,5 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import { type ComponentProps } from 'svelte';
2
3
  import type { spring as springStore, tweened as tweenedStore } from 'svelte/motion';
4
+ import Marker from './Marker.svelte';
3
5
  declare const __propDef: {
4
6
  props: {
5
7
  [x: string]: any;
@@ -11,6 +13,9 @@ declare const __propDef: {
11
13
  initialX2?: number | undefined;
12
14
  y2: number;
13
15
  initialY2?: number | undefined;
16
+ marker?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
17
+ markerStart?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
18
+ markerEnd?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
14
19
  spring?: boolean | Parameters<typeof springStore>[1];
15
20
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
16
21
  };
@@ -21,7 +26,14 @@ declare const __propDef: {
21
26
  } & {
22
27
  [evt: string]: CustomEvent<any>;
23
28
  };
24
- slots: {};
29
+ slots: {
30
+ markerStart: {
31
+ id: string;
32
+ };
33
+ markerEnd: {
34
+ id: string;
35
+ };
36
+ };
25
37
  };
26
38
  export type LineProps = typeof __propDef.props;
27
39
  export type LineEvents = typeof __propDef.events;
@@ -13,11 +13,15 @@
13
13
  - [ ] Investigate: https://observablehq.com/@fil/sankey-link-paths
14
14
  - [ ] Use for annotations - https://github.com/techniq/layerchart/issues/11
15
15
  */
16
+ import type { ComponentProps } from 'svelte';
16
17
  import type { tweened as tweenedStore } from 'svelte/motion';
17
18
  import { link as d3Link, curveBumpX, curveBumpY } from 'd3-shape';
18
19
  import { interpolatePath } from 'd3-interpolate-path';
19
20
 
20
21
  import { motionStore } from '../stores/motionStore.js';
22
+ import { uniqueId } from '@layerstack/utils';
23
+
24
+ import Marker from './Marker.svelte';
21
25
 
22
26
  // Override what is used from context
23
27
  export let data: any = undefined; // TODO: Update Type
@@ -35,6 +39,23 @@
35
39
  export let y = (d: any) => (sankey ? d[1] : orientation === 'horizontal' ? d.x : d.y);
36
40
  export let curve = orientation === 'horizontal' ? curveBumpX : curveBumpY;
37
41
 
42
+ /** Marker to attach to start, mid, and end points of path */
43
+ export let marker: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
44
+ undefined;
45
+ /** Marker to attach to start point of path */
46
+ export let markerStart: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
47
+ marker;
48
+ /** Marker to attach to all mid points of path */
49
+ export let markerMid: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
50
+ marker;
51
+ /** Marker to attach to end point of path */
52
+ export let markerEnd: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
53
+ marker;
54
+
55
+ $: markerStartId = markerStart || $$slots['markerStart'] ? uniqueId('marker-') : '';
56
+ $: markerMidId = markerMid || $$slots['markerMid'] ? uniqueId('marker-') : '';
57
+ $: markerEndId = markerEnd || $$slots['markerEnd'] ? uniqueId('marker-') : '';
58
+
38
59
  export let tweened: boolean | Parameters<typeof tweenedStore>[1] = undefined;
39
60
  // @ts-expect-error
40
61
  $: tweenedOptions = tweened ? { interpolate: interpolatePath, ...tweened } : false;
@@ -54,6 +75,9 @@
54
75
  class="path-link"
55
76
  d={$tweened_d}
56
77
  fill="none"
78
+ marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
79
+ marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
80
+ marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
57
81
  on:click
58
82
  on:pointerover
59
83
  on:pointermove
@@ -61,3 +85,29 @@
61
85
  on:pointerleave
62
86
  {...$$restProps}
63
87
  />
88
+
89
+ <slot name="markerStart" id={markerStartId}>
90
+ {#if markerStart}
91
+ <Marker
92
+ id={markerStartId}
93
+ type={typeof markerStart === 'string' ? markerStart : undefined}
94
+ {...typeof markerStart === 'object' ? markerStart : null}
95
+ />
96
+ {/if}
97
+ </slot>
98
+
99
+ <slot name="markerMid" id={markerMidId}>
100
+ <Marker
101
+ id={markerMidId}
102
+ type={typeof markerMid === 'string' ? markerMid : undefined}
103
+ {...typeof markerMid === 'object' ? markerMid : null}
104
+ />
105
+ </slot>
106
+
107
+ <slot name="markerEnd" id={markerEndId}>
108
+ <Marker
109
+ id={markerEndId}
110
+ type={typeof markerEnd === 'string' ? markerEnd : undefined}
111
+ {...typeof markerEnd === 'object' ? markerEnd : null}
112
+ />
113
+ </slot>
@@ -1,5 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import type { ComponentProps } from 'svelte';
2
3
  import type { tweened as tweenedStore } from 'svelte/motion';
4
+ import Marker from './Marker.svelte';
3
5
  declare const __propDef: {
4
6
  props: {
5
7
  [x: string]: any;
@@ -11,6 +13,10 @@ declare const __propDef: {
11
13
  x?: ((d: any) => any) | undefined;
12
14
  y?: ((d: any) => any) | undefined;
13
15
  curve?: import("d3-shape").CurveFactory | undefined;
16
+ marker?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
17
+ markerStart?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
18
+ markerMid?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
19
+ markerEnd?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
14
20
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
15
21
  };
16
22
  events: {
@@ -22,7 +28,17 @@ declare const __propDef: {
22
28
  } & {
23
29
  [evt: string]: CustomEvent<any>;
24
30
  };
25
- slots: {};
31
+ slots: {
32
+ markerStart: {
33
+ id: string;
34
+ };
35
+ markerMid: {
36
+ id: string;
37
+ };
38
+ markerEnd: {
39
+ id: string;
40
+ };
41
+ };
26
42
  };
27
43
  export type LinkProps = typeof __propDef.props;
28
44
  export type LinkEvents = typeof __propDef.events;
@@ -0,0 +1,81 @@
1
+ <script lang="ts">
2
+ import { cls } from '@layerstack/tailwind';
3
+ import { uniqueId } from '@layerstack/utils';
4
+
5
+ /** Defined the type of a default marker, or define your own in the slot */
6
+ export let type: 'arrow' | 'triangle' | 'line' | 'circle' | 'circle-stroke' | 'dot' | undefined =
7
+ undefined;
8
+
9
+ /** Unique id for marker */
10
+ export let id: string = uniqueId('marker-');
11
+
12
+ /** A number used to determine the size of the bounding box the marker content. */
13
+ export let size = 10;
14
+
15
+ /** The width of the marker viewport */
16
+ export let markerWidth: string | number = size;
17
+
18
+ /** The height of the marker viewport */
19
+ export let markerHeight: string | number = size;
20
+
21
+ /** Set the coordinate system for the markerWidth, markerHeight, and `<marker>` contents */
22
+ export let markerUnits: 'userSpaceOnUse' | 'strokeWidth' = 'userSpaceOnUse';
23
+
24
+ /** The orientation of the marker relative to the shape it is attached to */
25
+ export let orient: 'auto' | 'auto-start-reverse' | number = 'auto-start-reverse';
26
+
27
+ /** The x coordinate for the reference point of the marker */
28
+ export let refX: string | number = ['arrow', 'triangle'].includes(type ?? '') ? 9 : 5;
29
+
30
+ /** The y coordinate for the reference point of the maker */
31
+ export let refY: string | number = 5;
32
+
33
+ /** The bound of the SVG viewport for the current SVG fragment */
34
+ export let viewBox = '0 0 10 10';
35
+ </script>
36
+
37
+ <defs>
38
+ <marker
39
+ {id}
40
+ {markerWidth}
41
+ {markerHeight}
42
+ {markerUnits}
43
+ {orient}
44
+ {refX}
45
+ {refY}
46
+ {viewBox}
47
+ {...$$restProps}
48
+ class={cls(
49
+ 'overflow-visible',
50
+ // stroke
51
+ $$props.stroke == null &&
52
+ (['arrow', 'circle-stroke', 'line'].includes(type ?? '')
53
+ ? 'stroke-[context-stroke]'
54
+ : type === 'circle'
55
+ ? 'stroke-surface-100'
56
+ : 'stroke-none'),
57
+ // extra stroke attrs
58
+ '[stroke-linecap:round] [stroke-linejoin:round]',
59
+ //fill
60
+ $$props.fill == null &&
61
+ (['triangle', 'dot', 'circle'].includes(type ?? '')
62
+ ? 'fill-[context-stroke]'
63
+ : type === 'circle-stroke'
64
+ ? 'fill-surface-100'
65
+ : 'fill-none'),
66
+ $$props.class
67
+ )}
68
+ >
69
+ <slot>
70
+ {#if type === 'triangle'}
71
+ <path d="M 0 0 L 10 5 L 0 10 z" />
72
+ {:else if type === 'arrow'}
73
+ <polyline points="0 0, 10 5, 0 10" />
74
+ {:else if type === 'circle' || type === 'circle-stroke' || type === 'dot'}
75
+ <circle cx={5} cy={5} r={5} />
76
+ {:else if type === 'line'}
77
+ <polyline points="5 0, 5 10" />
78
+ {/if}
79
+ </slot>
80
+ </marker>
81
+ </defs>
@@ -0,0 +1,28 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ [x: string]: any;
5
+ type?: "arrow" | "triangle" | "line" | "circle" | "circle-stroke" | "dot" | undefined;
6
+ id?: string | undefined;
7
+ size?: number | undefined;
8
+ markerWidth?: (string | number) | undefined;
9
+ markerHeight?: (string | number) | undefined;
10
+ markerUnits?: ("userSpaceOnUse" | "strokeWidth") | undefined;
11
+ orient?: ("auto" | "auto-start-reverse" | number) | undefined;
12
+ refX?: (string | number) | undefined;
13
+ refY?: (string | number) | undefined;
14
+ viewBox?: string | undefined;
15
+ };
16
+ events: {
17
+ [evt: string]: CustomEvent<any>;
18
+ };
19
+ slots: {
20
+ default: {};
21
+ };
22
+ };
23
+ export type MarkerProps = typeof __propDef.props;
24
+ export type MarkerEvents = typeof __propDef.events;
25
+ export type MarkerSlots = typeof __propDef.slots;
26
+ export default class Marker extends SvelteComponentTyped<MarkerProps, MarkerEvents, MarkerSlots> {
27
+ }
28
+ export {};
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { tick } from 'svelte';
2
+ import { tick, type ComponentProps } from 'svelte';
3
3
  import { writable } from 'svelte/store';
4
4
  import { tweened as tweenedStore } from 'svelte/motion';
5
5
  import { draw as _drawTransition } from 'svelte/transition';
@@ -11,9 +11,12 @@
11
11
  import { interpolatePath } from 'd3-interpolate-path';
12
12
  import { max } from 'd3-array';
13
13
  import { cls } from '@layerstack/tailwind';
14
+ import { uniqueId } from '@layerstack/utils';
14
15
 
15
16
  import { chartContext } from './ChartContext.svelte';
16
17
  import Group from './Group.svelte';
18
+ import Marker from './Marker.svelte';
19
+
17
20
  import { motionStore } from '../stores/motionStore.js';
18
21
  import { accessor, type Accessor } from '../utils/common.js';
19
22
  import { isScaleBand } from '../utils/scales.js';
@@ -48,6 +51,23 @@
48
51
  export let curve: CurveFactory | CurveFactoryLineOnly | undefined = undefined;
49
52
  export let defined: Parameters<Line<any>['defined']>[0] | undefined = undefined;
50
53
 
54
+ /** Marker to attach to start, mid, and end points of path */
55
+ export let marker: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
56
+ undefined;
57
+ /** Marker to attach to start point of path */
58
+ export let markerStart: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
59
+ marker;
60
+ /** Marker to attach to all mid points of path */
61
+ export let markerMid: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
62
+ marker;
63
+ /** Marker to attach to end point of path */
64
+ export let markerEnd: ComponentProps<Marker>['type'] | ComponentProps<Marker> | undefined =
65
+ marker;
66
+
67
+ $: markerStartId = markerStart || $$slots['markerStart'] ? uniqueId('marker-') : '';
68
+ $: markerMidId = markerMid || $$slots['markerMid'] ? uniqueId('marker-') : '';
69
+ $: markerEndId = markerEnd || $$slots['markerEnd'] ? uniqueId('marker-') : '';
70
+
51
71
  function getScaleValue(data: any, scale: typeof $xScale | typeof $yScale, accessor: Function) {
52
72
  let value = accessor(data);
53
73
 
@@ -145,6 +165,9 @@
145
165
  !$$props.stroke && 'stroke-surface-content',
146
166
  $$props.class
147
167
  )}
168
+ marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
169
+ marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
170
+ marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
148
171
  in:drawTransition|global={typeof draw === 'object' ? draw : undefined}
149
172
  on:click
150
173
  on:pointerenter
@@ -153,6 +176,32 @@
153
176
  bind:this={pathEl}
154
177
  />
155
178
 
179
+ <slot name="markerStart" id={markerStartId}>
180
+ {#if markerStart}
181
+ <Marker
182
+ id={markerStartId}
183
+ type={typeof markerStart === 'string' ? markerStart : undefined}
184
+ {...typeof markerStart === 'object' ? markerStart : null}
185
+ />
186
+ {/if}
187
+ </slot>
188
+
189
+ <slot name="markerMid" id={markerMidId}>
190
+ <Marker
191
+ id={markerMidId}
192
+ type={typeof markerMid === 'string' ? markerMid : undefined}
193
+ {...typeof markerMid === 'object' ? markerMid : null}
194
+ />
195
+ </slot>
196
+
197
+ <slot name="markerEnd" id={markerEndId}>
198
+ <Marker
199
+ id={markerEndId}
200
+ type={typeof markerEnd === 'string' ? markerEnd : undefined}
201
+ {...typeof markerEnd === 'object' ? markerEnd : null}
202
+ />
203
+ </slot>
204
+
156
205
  {#if $$slots.start && $startPoint}
157
206
  <Group x={$startPoint.x} y={$startPoint.y}>
158
207
  <slot name="start" point={$startPoint} />
@@ -1,7 +1,9 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import { type ComponentProps } from 'svelte';
2
3
  import { tweened as tweenedStore } from 'svelte/motion';
3
4
  import { draw as _drawTransition } from 'svelte/transition';
4
5
  import type { CurveFactory, CurveFactoryLineOnly, Line } from 'd3-shape';
6
+ import Marker from './Marker.svelte';
5
7
  import { type Accessor } from '../utils/common.js';
6
8
  declare const __propDef: {
7
9
  props: {
@@ -14,6 +16,10 @@ declare const __propDef: {
14
16
  draw?: boolean | Parameters<typeof _drawTransition>[1];
15
17
  curve?: CurveFactory | CurveFactoryLineOnly | undefined;
16
18
  defined?: Parameters<Line<any>["defined"]>[0] | undefined;
19
+ marker?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
20
+ markerStart?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
21
+ markerMid?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
22
+ markerEnd?: ComponentProps<Marker>["type"] | ComponentProps<Marker> | undefined;
17
23
  };
18
24
  events: {
19
25
  click: MouseEvent;
@@ -24,6 +30,15 @@ declare const __propDef: {
24
30
  [evt: string]: CustomEvent<any>;
25
31
  };
26
32
  slots: {
33
+ markerStart: {
34
+ id: string;
35
+ };
36
+ markerMid: {
37
+ id: string;
38
+ };
39
+ markerEnd: {
40
+ id: string;
41
+ };
27
42
  start: {
28
43
  point: DOMPoint | undefined;
29
44
  };
@@ -192,6 +192,16 @@
192
192
  {/if}
193
193
  </slot>
194
194
 
195
+ <slot name="belowMarks" {...slotProps} />
196
+
197
+ <slot name="marks" {...slotProps}>
198
+ {#each series as s, i}
199
+ <Area {...getAreaProps(s, i)} />
200
+ {/each}
201
+ </slot>
202
+
203
+ <slot name="aboveMarks" {...slotProps} />
204
+
195
205
  <slot name="axis" {...slotProps}>
196
206
  {#if axis}
197
207
  {#if axis !== 'x'}
@@ -224,16 +234,6 @@
224
234
  {/if}
225
235
  </slot>
226
236
 
227
- <slot name="below-marks" {...slotProps} />
228
-
229
- <slot name="marks" {...slotProps}>
230
- {#each series as s, i}
231
- <Area {...getAreaProps(s, i)} />
232
- {/each}
233
- </slot>
234
-
235
- <slot name="above-marks" {...slotProps} />
236
-
237
237
  {#if points}
238
238
  {#each series as s}
239
239
  <Points
@@ -315,10 +315,10 @@ declare class __sveltets_Render<TData> {
315
315
  slots(): {
316
316
  default: any;
317
317
  grid: any;
318
- axis: any;
319
- 'below-marks': any;
318
+ belowMarks: any;
320
319
  marks: any;
321
- 'above-marks': any;
320
+ aboveMarks: any;
321
+ axis: any;
322
322
  highlight: any;
323
323
  legend: any;
324
324
  tooltip: any;
@@ -245,6 +245,16 @@
245
245
  {/if}
246
246
  </slot>
247
247
 
248
+ <slot name="belowMarks" {...slotProps} />
249
+
250
+ <slot name="marks" {...slotProps}>
251
+ {#each series as s, i}
252
+ <Bars {...getBarsProps(s, i)} />
253
+ {/each}
254
+ </slot>
255
+
256
+ <slot name="aboveMarks" {...slotProps} />
257
+
248
258
  <slot name="axis" {...slotProps}>
249
259
  {#if axis}
250
260
  {#if axis !== 'x'}
@@ -288,16 +298,6 @@
288
298
  {/if}
289
299
  </slot>
290
300
 
291
- <slot name="below-marks" {...slotProps} />
292
-
293
- <slot name="marks" {...slotProps}>
294
- {#each series as s, i}
295
- <Bars {...getBarsProps(s, i)} />
296
- {/each}
297
- </slot>
298
-
299
- <slot name="above-marks" {...slotProps} />
300
-
301
301
  <slot name="highlight" {...slotProps}>
302
302
  <Highlight area {...props.highlight} />
303
303
  </slot>
@@ -301,10 +301,10 @@ declare class __sveltets_Render<TData> {
301
301
  slots(): {
302
302
  default: any;
303
303
  grid: any;
304
- axis: any;
305
- 'below-marks': any;
304
+ belowMarks: any;
306
305
  marks: any;
307
- 'above-marks': any;
306
+ aboveMarks: any;
307
+ axis: any;
308
308
  highlight: any;
309
309
  legend: any;
310
310
  tooltip: any;
@@ -139,6 +139,16 @@
139
139
  {/if}
140
140
  </slot>
141
141
 
142
+ <slot name="belowMarks" {...slotProps} />
143
+
144
+ <slot name="marks" {...slotProps}>
145
+ {#each series as s, i}
146
+ <Spline {...getSplineProps(s, i)} />
147
+ {/each}
148
+ </slot>
149
+
150
+ <slot name="aboveMarks" {...slotProps} />
151
+
142
152
  <slot name="axis" {...slotProps}>
143
153
  {#if axis}
144
154
  {#if axis !== 'x'}
@@ -165,16 +175,6 @@
165
175
  {/if}
166
176
  </slot>
167
177
 
168
- <slot name="below-marks" {...slotProps} />
169
-
170
- <slot name="marks" {...slotProps}>
171
- {#each series as s, i}
172
- <Spline {...getSplineProps(s, i)} />
173
- {/each}
174
- </slot>
175
-
176
- <slot name="above-marks" {...slotProps} />
177
-
178
178
  {#if points}
179
179
  {#each series as s}
180
180
  <Points
@@ -312,10 +312,10 @@ declare class __sveltets_Render<TData> {
312
312
  slots(): {
313
313
  default: any;
314
314
  grid: any;
315
- axis: any;
316
- 'below-marks': any;
315
+ belowMarks: any;
317
316
  marks: any;
318
- 'above-marks': any;
317
+ aboveMarks: any;
318
+ axis: any;
319
319
  highlight: any;
320
320
  legend: any;
321
321
  tooltip: any;
@@ -24,6 +24,7 @@
24
24
  maxValue?: typeof maxValue;
25
25
  outerRadius?: typeof outerRadius;
26
26
  padAngle?: typeof padAngle;
27
+ center?: typeof center;
27
28
  props?: typeof props;
28
29
  range?: typeof range;
29
30
  series?: typeof series;
@@ -83,6 +84,9 @@
83
84
  export let cornerRadius = 0;
84
85
  export let padAngle = 0;
85
86
 
87
+ /** Center chart. Override and use `props.group` for more control */
88
+ export let center = true;
89
+
86
90
  export let props: {
87
91
  pie?: Partial<ComponentProps<Pie>>;
88
92
  group?: Partial<ComponentProps<Group>>;
@@ -143,8 +147,8 @@
143
147
  tooltip,
144
148
  }}
145
149
  <slot {...slotProps}>
146
- <Svg center>
147
- <slot name="below-marks" {...slotProps} />
150
+ <Svg {center}>
151
+ <slot name="belowMarks" {...slotProps} />
148
152
 
149
153
  <slot name="marks" {...slotProps}>
150
154
  <Group {...props.group}>
@@ -199,7 +203,7 @@
199
203
  </Group>
200
204
  </slot>
201
205
 
202
- <slot name="above-marks" {...slotProps} />
206
+ <slot name="aboveMarks" {...slotProps} />
203
207
  </Svg>
204
208
 
205
209
  <slot name="legend" {...slotProps}>
@@ -222,6 +222,7 @@ declare class __sveltets_Render<TData> {
222
222
  maxValue?: number | undefined;
223
223
  outerRadius?: number | undefined;
224
224
  padAngle?: number;
225
+ center?: boolean;
225
226
  props?: {
226
227
  pie?: Partial<ComponentProps<Pie>>;
227
228
  group?: Partial<ComponentProps<Group>>;
@@ -247,9 +248,9 @@ declare class __sveltets_Render<TData> {
247
248
  };
248
249
  slots(): {
249
250
  default: any;
250
- 'below-marks': any;
251
+ belowMarks: any;
251
252
  marks: any;
252
- 'above-marks': any;
253
+ aboveMarks: any;
253
254
  legend: any;
254
255
  tooltip: any;
255
256
  };
@@ -116,6 +116,16 @@
116
116
  {/if}
117
117
  </slot>
118
118
 
119
+ <slot name="belowMarks" {...slotProps} />
120
+
121
+ <slot name="marks" {...slotProps}>
122
+ {#each series as s, i}
123
+ <Points {...getPointsProps(s, i)} />
124
+ {/each}
125
+ </slot>
126
+
127
+ <slot name="aboveMarks" {...slotProps} />
128
+
119
129
  <slot name="axis" {...slotProps}>
120
130
  {#if axis}
121
131
  {#if axis !== 'x'}
@@ -142,16 +152,6 @@
142
152
  {/if}
143
153
  </slot>
144
154
 
145
- <slot name="below-marks" {...slotProps} />
146
-
147
- <slot name="marks" {...slotProps}>
148
- {#each series as s, i}
149
- <Points {...getPointsProps(s, i)} />
150
- {/each}
151
- </slot>
152
-
153
- <slot name="above-marks" {...slotProps} />
154
-
155
155
  <slot name="highlight" {...slotProps}>
156
156
  <Highlight points={{ fill: activeSeries?.color }} lines axis="both" {...props.highlight} />
157
157
  </slot>
@@ -288,10 +288,10 @@ declare class __sveltets_Render<TData> {
288
288
  slots(): {
289
289
  default: any;
290
290
  grid: any;
291
- axis: any;
292
- 'below-marks': any;
291
+ belowMarks: any;
293
292
  marks: any;
294
- 'above-marks': any;
293
+ aboveMarks: any;
294
+ axis: any;
295
295
  highlight: any;
296
296
  legend: any;
297
297
  tooltip: any;
@@ -39,6 +39,21 @@
39
39
  // https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/tile/12/1572/1108.pbf
40
40
  };
41
41
 
42
+ // https://github.com/leaflet-extras/leaflet-providers/blob/master/leaflet-providers.js#L79
43
+ // https://www.openstreetmap.org/
44
+ const openStreetMap = (tileset: string) => (x: number, y: number, z: number) => {
45
+ // CyclOSM: https://a.tile-cyclosm.openstreetmap.fr/cyclosm/9/142/197.png
46
+ // Cycle Map: https://b.tile.thunderforest.com/cycle/9/141/199@2x.png?apikey=6e5478c8a4f54c779f85573c0e399391
47
+ // TransportMap: https://b.tile.thunderforest.com/transport/9/136/195@2x.png?apikey=6e5478c8a4f54c779f85573c0e399391
48
+ return `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
49
+ };
50
+
51
+ // opentopomap.org/
52
+ const openTopoMap = (tileset: string) => (x: number, y: number, z: number) => {
53
+ const s = 'a';
54
+ return `https://${s}.tile.opentopomap.org/${z}/${x}/${y}.png`;
55
+ };
56
+
42
57
  $: services = {
43
58
  'mapbox v1': {
44
59
  'streets-v11': mapboxv1('streets-v11'),
@@ -59,6 +74,12 @@
59
74
  traffic: mapboxv4('mapbox.mapbox-traffic-v1'),
60
75
  // 'transit (mapbox v4)': mapboxv4('mapbox.transit-v2'),
61
76
  },
77
+ OpenStreetMap: {
78
+ Stardard: openStreetMap(''),
79
+ },
80
+ OpenTopoMap: {
81
+ Stardard: openTopoMap(''),
82
+ },
62
83
  'National Map Services': {
63
84
  Hydrography: nationalmap('USGSHydroCached'),
64
85
  'USGS Imagery Topo Base Map': nationalmap('USGSImageryTopo'),
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "author": "Sean Lynch <techniq35@gmail.com>",
5
5
  "license": "MIT",
6
6
  "repository": "techniq/layerchart",
7
- "version": "0.54.1",
7
+ "version": "0.56.0",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.9",
10
10
  "@mdi/js": "^7.4.47",