layerchart 0.94.3 → 0.96.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.
@@ -203,6 +203,7 @@ declare class __sveltets_Render<TData> {
203
203
  hide: () => void;
204
204
  mode: "manual" | "bisect-x" | "bisect-y" | "band" | "bisect-band" | "bounds" | "voronoi" | "quadtree";
205
205
  }>;
206
+ hideDelay?: number;
206
207
  }> | undefined;
207
208
  /** Exposed via bind: to support `bind:tooltipContext` for external access (ex. `tooltipContext.data) */
208
209
  tooltipContext?: import("svelte/store").Writable<{
@@ -83,6 +83,9 @@
83
83
  export let points: ComponentProps<Points> | boolean = false;
84
84
  export let rule: ComponentProps<Rule> | boolean = true;
85
85
 
86
+ /** Expose tooltip context for external access */
87
+ export let tooltipContext: ComponentProps<Tooltip.Context>['tooltip'] = undefined;
88
+
86
89
  /** Event dispatched with current tooltip data */
87
90
  export let ontooltipclick: (e: MouseEvent, details: { data: any }) => void = () => {};
88
91
 
@@ -166,6 +169,10 @@
166
169
 
167
170
  let highlightSeriesKey: (typeof series)[number]['key'] | null = null;
168
171
 
172
+ function setHighlightSeriesKey(seriesKey: typeof highlightSeriesKey) {
173
+ highlightSeriesKey = seriesKey;
174
+ }
175
+
169
176
  function getAreaProps(s: (typeof series)[number], i: number) {
170
177
  const lineProps = {
171
178
  ...props.line,
@@ -297,6 +304,7 @@
297
304
  ...props.tooltip?.context,
298
305
  ...$$props.tooltip,
299
306
  }}
307
+ bind:tooltipContext
300
308
  brush={brush && (brush === true || brush.mode == undefined || brush.mode === 'integrated')
301
309
  ? {
302
310
  axis: 'x',
@@ -336,6 +344,7 @@
336
344
  getAreaProps,
337
345
  getLabelsProps,
338
346
  getPointsProps,
347
+ setHighlightSeriesKey,
339
348
  }}
340
349
 
341
350
  <slot {...slotProps}>
@@ -486,6 +495,8 @@
486
495
  color={s.color}
487
496
  {format}
488
497
  valueAlign="right"
498
+ onpointerenter={() => (highlightSeriesKey = s.key)}
499
+ onpointerleave={() => (highlightSeriesKey = null)}
489
500
  {...props.tooltip?.item}
490
501
  />
491
502
  {/each}
@@ -93,6 +93,9 @@
93
93
  /** Padding between series items within bars when using 'seriesLayout="stack"' */
94
94
  export let stackPadding = 0;
95
95
 
96
+ /** Expose tooltip context for external access */
97
+ export let tooltipContext: ComponentProps<Tooltip.Context>['tooltip'] = undefined;
98
+
96
99
  /** Event dispatched with current tooltip data */
97
100
  export let ontooltipclick: (e: MouseEvent, detail: { data: any }) => void = () => {};
98
101
 
@@ -196,6 +199,10 @@
196
199
 
197
200
  let highlightSeriesKey: (typeof series)[number]['key'] | null = null;
198
201
 
202
+ function setHighlightSeriesKey(seriesKey: typeof highlightSeriesKey) {
203
+ highlightSeriesKey = seriesKey;
204
+ }
205
+
199
206
  function getBarsProps(s: (typeof series)[number], i: number) {
200
207
  const isFirst = i == 0;
201
208
  const isLast = i == visibleSeries.length - 1;
@@ -317,6 +324,7 @@
317
324
  ...props.tooltip?.context,
318
325
  ...$$props.tooltip,
319
326
  }}
327
+ bind:tooltipContext
320
328
  let:x
321
329
  let:xScale
322
330
  let:y
@@ -343,6 +351,7 @@
343
351
  visibleSeries,
344
352
  getBarsProps,
345
353
  getLabelsProps,
354
+ setHighlightSeriesKey,
346
355
  }}
347
356
  <slot {...slotProps}>
348
357
  <slot name="belowContext" {...slotProps} />
@@ -474,6 +483,8 @@
474
483
  color={s.color ?? cScale?.(c(data))}
475
484
  {format}
476
485
  valueAlign="right"
486
+ onpointerenter={() => (highlightSeriesKey = s.key)}
487
+ onpointerleave={() => (highlightSeriesKey = null)}
477
488
  {...props.tooltip?.item}
478
489
  />
479
490
  {/each}
@@ -75,6 +75,9 @@
75
75
  export let points: ComponentProps<Points> | boolean = false;
76
76
  export let rule: ComponentProps<Rule> | boolean = true;
77
77
 
78
+ /** Expose tooltip context for external access */
79
+ export let tooltipContext: ComponentProps<Tooltip.Context>['tooltip'] = undefined;
80
+
78
81
  /** Event dispatched with current tooltip data */
79
82
  export let ontooltipclick: (e: MouseEvent, details: { data: any }) => void = () => {};
80
83
 
@@ -132,6 +135,10 @@
132
135
 
133
136
  let highlightSeriesKey: (typeof series)[number]['key'] | null = null;
134
137
 
138
+ function setHighlightSeriesKey(seriesKey: typeof highlightSeriesKey) {
139
+ highlightSeriesKey = seriesKey;
140
+ }
141
+
135
142
  function getSplineProps(s: (typeof series)[number], i: number) {
136
143
  const splineProps: ComponentProps<Spline> = {
137
144
  data: s.data,
@@ -228,6 +235,7 @@
228
235
  ...props.tooltip?.context,
229
236
  ...$$props.tooltip,
230
237
  }}
238
+ bind:tooltipContext
231
239
  brush={brush && (brush === true || brush.mode == undefined || brush.mode === 'integrated')
232
240
  ? {
233
241
  axis: 'x',
@@ -267,6 +275,7 @@
267
275
  getLabelsProps,
268
276
  getPointsProps,
269
277
  getSplineProps,
278
+ setHighlightSeriesKey,
270
279
  }}
271
280
  <slot {...slotProps}>
272
281
  <slot name="belowContext" {...slotProps} />
@@ -406,6 +415,8 @@
406
415
  value={seriesTooltipData ? valueAccessor(seriesTooltipData) : null}
407
416
  color={s.color}
408
417
  {format}
418
+ onpointerenter={() => (highlightSeriesKey = s.key)}
419
+ onpointerleave={() => (highlightSeriesKey = null)}
409
420
  {...props.tooltip?.item}
410
421
  />
411
422
  {/each}
@@ -97,6 +97,9 @@
97
97
  /** Center chart. Override and use `props.group` for more control */
98
98
  export let center = placement === 'center';
99
99
 
100
+ /** Expose tooltip context for external access */
101
+ export let tooltipContext: ComponentProps<Tooltip.Context>['tooltip'] = undefined;
102
+
100
103
  // TODO: Not usable with manual tooltip / arc path. Use `onarcclick`?
101
104
  /** Event dispatched with current tooltip data */
102
105
  export let ontooltipclick: (e: MouseEvent, detail: { data: any }) => void = () => {};
@@ -140,6 +143,10 @@
140
143
 
141
144
  let highlightKey: (typeof series)[number]['key'] | null = null;
142
145
 
146
+ function setHighlightKey(key: typeof highlightKey) {
147
+ highlightKey = key ?? null;
148
+ }
149
+
143
150
  const selectedKeys = selectionStore();
144
151
  $: visibleData = chartData.filter((d) => {
145
152
  const dataKey = keyAccessor(d);
@@ -177,6 +184,7 @@
177
184
  padding={{ bottom: legend === true ? 32 : 0 }}
178
185
  {...$$restProps}
179
186
  tooltip={props.tooltip?.context}
187
+ bind:tooltipContext
180
188
  let:x
181
189
  let:xScale
182
190
  let:y
@@ -204,6 +212,7 @@
204
212
  tooltip,
205
213
  series,
206
214
  visibleData,
215
+ setHighlightKey,
207
216
  }}
208
217
  <slot {...slotProps}>
209
218
  <slot name="belowContext" {...slotProps} />
@@ -331,6 +340,8 @@
331
340
  value={valueAccessor(data)}
332
341
  color={cScale?.(c(data))}
333
342
  {format}
343
+ onpointerenter={() => (highlightKey = keyAccessor(data))}
344
+ onpointerleave={() => (highlightKey = null)}
334
345
  {...props.tooltip?.item}
335
346
  />
336
347
  </Tooltip.List>
@@ -139,6 +139,7 @@ declare class __sveltets_Render<TData> {
139
139
  hide: () => void;
140
140
  mode: "manual" | "bisect-x" | "bisect-y" | "band" | "bisect-band" | "bounds" | "voronoi" | "quadtree";
141
141
  }>;
142
+ hideDelay?: number;
142
143
  }> | undefined;
143
144
  tooltipContext?: import("svelte/store").Writable<{
144
145
  x: number;
@@ -64,6 +64,9 @@
64
64
  export let legend: ComponentProps<Legend> | boolean = false;
65
65
  export let rule: ComponentProps<Rule> | boolean = true;
66
66
 
67
+ /** Expose tooltip context for external access */
68
+ export let tooltipContext: ComponentProps<Tooltip.Context>['tooltip'] = undefined;
69
+
67
70
  /** Event dispatched with current tooltip data */
68
71
  export let ontooltipclick: (e: MouseEvent, detail: { data: any }) => void = () => {};
69
72
 
@@ -113,6 +116,10 @@
113
116
 
114
117
  let highlightSeriesKey: (typeof series)[number]['key'] | null = null;
115
118
 
119
+ function setHighlightSeriesKey(seriesKey: typeof highlightSeriesKey) {
120
+ highlightSeriesKey = seriesKey ?? null;
121
+ }
122
+
116
123
  function getPointsProps(s: (typeof series)[number], i: number) {
117
124
  const pointsProps: ComponentProps<Points> = {
118
125
  data: s.data,
@@ -187,6 +194,7 @@
187
194
  ...props.tooltip?.context,
188
195
  ...$$props.tooltip,
189
196
  }}
197
+ bind:tooltipContext
190
198
  brush={brush && (brush === true || brush.mode == undefined || brush.mode === 'integrated')
191
199
  ? {
192
200
  axis: 'both',
@@ -229,6 +237,7 @@
229
237
  visibleSeries,
230
238
  getLabelsProps,
231
239
  getPointsProps,
240
+ setHighlightSeriesKey,
232
241
  }}
233
242
  {@const activeSeries = tooltip.data
234
243
  ? (series.find((s) => s.key === tooltip.data.seriesKey) ?? series[0])
@@ -349,12 +358,16 @@
349
358
  label={typeof config.x === 'string' ? config.x : 'x'}
350
359
  value={x(data)}
351
360
  {format}
361
+ onpointerenter={() => (highlightSeriesKey = activeSeries?.key ?? null)}
362
+ onpointerleave={() => (highlightSeriesKey = null)}
352
363
  {...props.tooltip?.item}
353
364
  />
354
365
  <Tooltip.Item
355
366
  label={typeof config.y === 'string' ? config.y : 'y'}
356
367
  value={y(data)}
357
368
  {format}
369
+ onpointerenter={() => (highlightSeriesKey = activeSeries?.key ?? null)}
370
+ onpointerleave={() => (highlightSeriesKey = null)}
358
371
  {...props.tooltip?.item}
359
372
  />
360
373
  {#if config.r}
@@ -362,6 +375,8 @@
362
375
  label={typeof config.r === 'string' ? config.r : 'r'}
363
376
  value={r(data)}
364
377
  {format}
378
+ onpointerenter={() => (highlightSeriesKey = activeSeries?.key ?? null)}
379
+ onpointerleave={() => (highlightSeriesKey = null)}
365
380
  {...props.tooltip?.item}
366
381
  />
367
382
  {/if}
@@ -101,7 +101,7 @@
101
101
  /** Similar to d3-selection's raise, re-insert the e.target as the last child of its parent, so to be the top-most element */
102
102
  export let raiseTarget = false;
103
103
 
104
- /** Lock tooltip (keep open, do not update on mouse movement). Allows for kicking on tooltip */
104
+ /** Lock tooltip (keep open, do not update on mouse movement). Allows for clicking on tooltip */
105
105
  export let locked = false;
106
106
 
107
107
  /** quadtree search radius
@@ -124,6 +124,10 @@
124
124
  });
125
125
  setTooltipContext(tooltip);
126
126
 
127
+ /** Delay in ms before hiding tooltip */
128
+ export let hideDelay = 0;
129
+
130
+ let isHoveringTooltip = false;
127
131
  let hideTimeoutId: NodeJS.Timeout;
128
132
 
129
133
  $: bisectX = bisector((d: any) => {
@@ -175,7 +179,9 @@
175
179
 
176
180
  function showTooltip(e: PointerEvent, tooltipData?: any) {
177
181
  // Cancel hiding tooltip if from previous event loop
178
- clearTimeout(hideTimeoutId);
182
+ if (hideTimeoutId) {
183
+ clearTimeout(hideTimeoutId);
184
+ }
179
185
 
180
186
  if (locked) {
181
187
  // Ignore (keep current position / data)
@@ -294,9 +300,12 @@
294
300
  }
295
301
 
296
302
  // Wait an event loop tick in case `showTooltip` is called immediately on another element, to allow tweeneing (ex. moving between bands/bars)
303
+ // Additional hideDelay can be configured to extend this delay further
297
304
  hideTimeoutId = setTimeout(() => {
298
- $tooltip = { ...$tooltip, data: null };
299
- });
305
+ if (!isHoveringTooltip) {
306
+ $tooltip = { ...$tooltip, data: null };
307
+ }
308
+ }, hideDelay);
300
309
  }
301
310
 
302
311
  let quadtree: Quadtree<[number, number]>;
@@ -401,9 +410,19 @@
401
410
  'TooltipContext absolute touch-none',
402
411
  debug && triggerPointerEvents && 'bg-danger/10 outline outline-danger'
403
412
  )}
404
- on:pointerenter={triggerPointerEvents ? showTooltip : undefined}
413
+ on:pointerenter={(e) => {
414
+ isHoveringTooltip = true;
415
+ if (triggerPointerEvents) {
416
+ showTooltip(e);
417
+ }
418
+ }}
405
419
  on:pointermove={triggerPointerEvents ? showTooltip : undefined}
406
- on:pointerleave={triggerPointerEvents ? hideTooltip : undefined}
420
+ on:pointerleave={(e) => {
421
+ isHoveringTooltip = false;
422
+ if (triggerPointerEvents) {
423
+ hideTooltip();
424
+ }
425
+ }}
407
426
  on:click={(e) => {
408
427
  if (triggerPointerEvents) {
409
428
  onclick(e, { data: $tooltip?.data });
@@ -21,7 +21,7 @@ declare const __propDef: {
21
21
  * @type {'closest' | 'left' | 'right'}
22
22
  */ findTooltipData?: "closest" | "left" | "right";
23
23
  /** Similar to d3-selection's raise, re-insert the e.target as the last child of its parent, so to be the top-most element */ raiseTarget?: boolean;
24
- /** Lock tooltip (keep open, do not update on mouse movement). Allows for kicking on tooltip */ locked?: boolean;
24
+ /** Lock tooltip (keep open, do not update on mouse movement). Allows for clicking on tooltip */ locked?: boolean;
25
25
  /** quadtree search radius
26
26
  * @type {number}
27
27
  */ radius?: number;
@@ -37,6 +37,7 @@ declare const __propDef: {
37
37
  hide: () => void;
38
38
  mode: TooltipMode;
39
39
  }>;
40
+ /** Delay in ms before hiding tooltip */ hideDelay?: number;
40
41
  };
41
42
  events: {
42
43
  [evt: string]: CustomEvent<any>;
@@ -22,7 +22,7 @@
22
22
  >
23
23
  {#if color}
24
24
  <div
25
- class={cls('color', 'inline-block size-2 rounded-full bg-[--color]', classes.color)}
25
+ class={cls('color', 'inline-block size-2 rounded-full bg-[var(--color)]', classes.color)}
26
26
  style:--color={color}
27
27
  ></div>
28
28
  {/if}
@@ -9,6 +9,10 @@
9
9
  export let valueAlign: 'left' | 'right' | 'center' = 'left';
10
10
  export let color: string | undefined = undefined;
11
11
 
12
+ export let onclick: ((e: MouseEvent) => void) | undefined = undefined;
13
+ export let onpointerenter: ((e: PointerEvent) => void) | undefined = undefined;
14
+ export let onpointerleave: ((e: PointerEvent) => void) | undefined = undefined;
15
+
12
16
  export let classes: {
13
17
  root?: string;
14
18
  label?: string;
@@ -17,11 +21,17 @@
17
21
  } = {};
18
22
  </script>
19
23
 
20
- <div class={cls('contents', classes.root, $$props.class)} {...$$restProps}>
24
+ <div
25
+ class={cls('contents', classes.root, $$props.class)}
26
+ on:click={onclick}
27
+ on:pointerenter={onpointerenter}
28
+ on:pointerleave={onpointerleave}
29
+ {...$$restProps}
30
+ >
21
31
  <div class={cls('label', 'flex items-center gap-2 whitespace-nowrap', classes.label)}>
22
32
  {#if color}
23
33
  <div
24
- class={cls('color', 'inline-block size-2 rounded-full bg-[--color]', classes.color)}
34
+ class={cls('color', 'inline-block size-2 rounded-full bg-[var(--color)]', classes.color)}
25
35
  style:--color={color}
26
36
  ></div>
27
37
  {/if}
@@ -8,6 +8,9 @@ declare const __propDef: {
8
8
  format?: FormatType | undefined;
9
9
  valueAlign?: "left" | "right" | "center" | undefined;
10
10
  color?: string | undefined | undefined;
11
+ onclick?: ((e: MouseEvent) => void) | undefined | undefined;
12
+ onpointerenter?: ((e: PointerEvent) => void) | undefined | undefined;
13
+ onpointerleave?: ((e: PointerEvent) => void) | undefined | undefined;
11
14
  classes?: {
12
15
  root?: string;
13
16
  label?: string;
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.94.3",
7
+ "version": "0.96.0",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.12",
10
10
  "@mdi/js": "^7.4.47",
@@ -39,10 +39,10 @@
39
39
  "@types/topojson-simplify": "^3.0.3",
40
40
  "@types/topojson-specification": "^1.0.5",
41
41
  "autoprefixer": "^10.4.20",
42
- "marked": "^15.0.6",
42
+ "marked": "^15.0.7",
43
43
  "mdsvex": "^0.12.3",
44
- "posthog-js": "^1.215.5",
45
- "prettier": "^3.4.2",
44
+ "posthog-js": "^1.217.0",
45
+ "prettier": "^3.5.0",
46
46
  "prettier-plugin-svelte": "^3.3.3",
47
47
  "prism-svelte": "^0.5.0",
48
48
  "prism-themes": "^1.9.0",
@@ -50,10 +50,10 @@
50
50
  "rehype-slug": "^6.0.0",
51
51
  "shapefile": "^0.6.6",
52
52
  "solar-calculator": "^0.3.0",
53
- "svelte": "^5.19.9",
53
+ "svelte": "5.19.10",
54
54
  "svelte-check": "^4.1.4",
55
55
  "svelte-json-tree": "^2.2.0",
56
- "svelte-ux": "^0.90.0",
56
+ "svelte-ux": "^0.90.1",
57
57
  "svelte2tsx": "^0.7.34",
58
58
  "tailwindcss": "^3.4.16",
59
59
  "topojson-client": "^3.1.0",
@@ -69,7 +69,7 @@
69
69
  "dependencies": {
70
70
  "@dagrejs/dagre": "^1.1.4",
71
71
  "@layerstack/svelte-actions": "^0.0.11",
72
- "@layerstack/svelte-stores": "^0.0.9",
72
+ "@layerstack/svelte-stores": "^0.0.10",
73
73
  "@layerstack/tailwind": "^0.0.11",
74
74
  "@layerstack/utils": "^0.0.7",
75
75
  "d3-array": "^3.2.4",