layerchart 0.75.1 → 0.76.1

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.
@@ -187,6 +187,7 @@ declare class __sveltets_Render<TData> {
187
187
  mode?: "bisect-x" | "bisect-y" | "band" | "bisect-band" | "bounds" | "voronoi" | "quadtree" | "manual";
188
188
  findTooltipData?: "closest" | "left" | "right";
189
189
  raiseTarget?: boolean;
190
+ locked?: boolean;
190
191
  radius?: number;
191
192
  debug?: boolean;
192
193
  onClick?: ({ data }: {
@@ -214,8 +214,8 @@
214
214
  yNice
215
215
  {radial}
216
216
  padding={radial ? undefined : defaultChartPadding(axis, legend)}
217
- tooltip={{ mode: 'bisect-x', onClick: onTooltipClick }}
218
217
  {...$$restProps}
218
+ tooltip={{ mode: 'bisect-x', onClick: onTooltipClick, ...$$props.tooltip, ...props.tooltip }}
219
219
  let:x
220
220
  let:xScale
221
221
  let:y
@@ -342,21 +342,24 @@
342
342
  onClick={(item) => $selectedSeries.toggleSelected(item.value)}
343
343
  onPointerEnter={(item) => (highlightSeriesKey = item.value)}
344
344
  onPointerLeave={(item) => (highlightSeriesKey = null)}
345
+ {...props.legend}
346
+ {...typeof legend === 'object' ? legend : null}
345
347
  classes={{
346
348
  item: (item) =>
347
349
  visibleSeries.length && !visibleSeries.some((s) => s.key === item.value)
348
350
  ? 'opacity-50'
349
351
  : '',
352
+ ...props.legend?.classes,
353
+ ...(typeof legend === 'object' ? legend.classes : null),
350
354
  }}
351
- {...props.legend}
352
- {...typeof legend === 'object' ? legend : null}
353
355
  />
354
356
  {/if}
355
357
  </slot>
356
358
 
357
359
  <slot name="tooltip" {...slotProps}>
358
360
  <Tooltip.Root {...props.tooltip?.root} let:data>
359
- <Tooltip.Header {...props.tooltip?.header}>{format(x(data))}</Tooltip.Header>
361
+ <Tooltip.Header value={x(data)} {format} {...props.tooltip?.header} />
362
+
360
363
  <Tooltip.List {...props.tooltip?.list}>
361
364
  <!-- Reverse series order so tooltip items match stacks -->
362
365
  {@const seriesItems = stackSeries ? [...visibleSeries].reverse() : visibleSeries}
@@ -140,6 +140,7 @@
140
140
  list?: Partial<ComponentProps<Tooltip.List>>;
141
141
  item?: Partial<ComponentProps<Tooltip.Item>>;
142
142
  separator?: Partial<ComponentProps<Tooltip.Separator>>;
143
+ hideTotal?: boolean;
143
144
  };
144
145
  } = {};
145
146
 
@@ -279,8 +280,8 @@
279
280
  c={isVertical ? y : x}
280
281
  cRange={['hsl(var(--color-primary))']}
281
282
  padding={defaultChartPadding(axis, legend)}
282
- tooltip={{ mode: 'band', onClick: onTooltipClick }}
283
283
  {...$$restProps}
284
+ tooltip={{ mode: 'band', onClick: onTooltipClick, ...$$props.tooltip, ...props.tooltip }}
284
285
  let:x
285
286
  let:xScale
286
287
  let:y
@@ -396,23 +397,28 @@
396
397
  onClick={(item) => $selectedSeries.toggleSelected(item.value)}
397
398
  onPointerEnter={(item) => (highlightSeriesKey = item.value)}
398
399
  onPointerLeave={(item) => (highlightSeriesKey = null)}
400
+ {...props.legend}
401
+ {...typeof legend === 'object' ? legend : null}
399
402
  classes={{
400
403
  item: (item) =>
401
404
  visibleSeries.length && !visibleSeries.some((s) => s.key === item.value)
402
405
  ? 'opacity-50'
403
406
  : '',
407
+ ...props.legend?.classes,
408
+ ...(typeof legend === 'object' ? legend.classes : null),
404
409
  }}
405
- {...props.legend}
406
- {...typeof legend === 'object' ? legend : null}
407
410
  />
408
411
  {/if}
409
412
  </slot>
410
413
 
411
414
  <slot name="tooltip" {...slotProps}>
412
415
  <Tooltip.Root {...props.tooltip?.root} let:data>
413
- <Tooltip.Header {...props.tooltip?.header}
414
- >{format(isVertical ? x(data) : y(data))}</Tooltip.Header
415
- >
416
+ <Tooltip.Header
417
+ value={isVertical ? x(data) : y(data)}
418
+ {format}
419
+ {...props.tooltip?.header}
420
+ />
421
+
416
422
  <Tooltip.List {...props.tooltip?.list}>
417
423
  <!-- Reverse series order so tooltip items match stacks -->
418
424
  {@const seriesItems = stackSeries ? [...visibleSeries].reverse() : visibleSeries}
@@ -429,7 +435,7 @@
429
435
  />
430
436
  {/each}
431
437
 
432
- {#if (stackSeries || groupSeries) && visibleSeries.length > 1}
438
+ {#if (stackSeries || groupSeries) && visibleSeries.length > 1 && !props.tooltip?.hideTotal}
433
439
  <Tooltip.Separator {...props.tooltip?.separator} />
434
440
 
435
441
  <Tooltip.Item
@@ -156,8 +156,8 @@
156
156
  yNice
157
157
  {radial}
158
158
  padding={radial ? undefined : defaultChartPadding(axis, legend)}
159
- tooltip={{ mode: 'bisect-x', onClick: onTooltipClick }}
160
159
  {...$$restProps}
160
+ tooltip={{ mode: 'bisect-x', onClick: onTooltipClick, ...$$props.tooltip, ...props.tooltip }}
161
161
  let:x
162
162
  let:xScale
163
163
  let:y
@@ -276,21 +276,23 @@
276
276
  onClick={(item) => $selectedSeries.toggleSelected(item.value)}
277
277
  onPointerEnter={(item) => (highlightSeriesKey = item.value)}
278
278
  onPointerLeave={(item) => (highlightSeriesKey = null)}
279
+ {...props.legend}
280
+ {...typeof legend === 'object' ? legend : null}
279
281
  classes={{
280
282
  item: (item) =>
281
283
  visibleSeries.length && !visibleSeries.some((s) => s.key === item.value)
282
284
  ? 'opacity-50'
283
285
  : '',
286
+ ...props.legend?.classes,
287
+ ...(typeof legend === 'object' ? legend.classes : null),
284
288
  }}
285
- {...props.legend}
286
- {...typeof legend === 'object' ? legend : null}
287
289
  />
288
290
  {/if}
289
291
  </slot>
290
292
 
291
293
  <slot name="tooltip" {...slotProps}>
292
294
  <Tooltip.Root {...props.tooltip?.root} let:data>
293
- <Tooltip.Header {...props.tooltip?.header}>{format(x(data))}</Tooltip.Header>
295
+ <Tooltip.Header value={x(data)} {format} {...props.tooltip?.header} />
294
296
  <Tooltip.List {...props.tooltip?.list}>
295
297
  {#each visibleSeries as s}
296
298
  {@const seriesTooltipData = s.data ? findRelatedData(s.data, data, x) : data}
@@ -294,14 +294,16 @@
294
294
  onClick={(item) => $selectedKeys.toggleSelected(item.value)}
295
295
  onPointerEnter={(item) => (highlightKey = item.value)}
296
296
  onPointerLeave={(item) => (highlightKey = null)}
297
+ {...props.legend}
298
+ {...typeof legend === 'object' ? legend : null}
297
299
  classes={{
298
300
  item: (item) =>
299
301
  visibleData.length && !visibleData.some((d) => keyAccessor(d) === item.value)
300
302
  ? 'opacity-50'
301
303
  : '',
304
+ ...props.legend?.classes,
305
+ ...(typeof legend === 'object' ? legend.classes : null),
302
306
  }}
303
- {...props.legend}
304
- {...typeof legend === 'object' ? legend : null}
305
307
  />
306
308
  {/if}
307
309
  </slot>
@@ -124,6 +124,7 @@ declare class __sveltets_Render<TData> {
124
124
  mode?: "bisect-x" | "bisect-y" | "band" | "bisect-band" | "bounds" | "voronoi" | "quadtree" | "manual";
125
125
  findTooltipData?: "closest" | "left" | "right";
126
126
  raiseTarget?: boolean;
127
+ locked?: boolean;
127
128
  radius?: number;
128
129
  debug?: boolean;
129
130
  onClick?: ({ data }: {
@@ -139,8 +139,8 @@
139
139
  {yScale}
140
140
  yNice
141
141
  padding={defaultChartPadding(axis, legend)}
142
- tooltip={{ mode: 'voronoi', onClick: onTooltipClick }}
143
142
  {...$$restProps}
143
+ tooltip={{ mode: 'voronoi', onClick: onTooltipClick, ...$$props.tooltip, ...props.tooltip }}
144
144
  let:x
145
145
  let:xScale
146
146
  let:y
@@ -231,14 +231,16 @@
231
231
  onClick={(item) => $selectedSeries.toggleSelected(item.value)}
232
232
  onPointerEnter={(item) => (highlightSeriesKey = item.value)}
233
233
  onPointerLeave={(item) => (highlightSeriesKey = null)}
234
+ {...props.legend}
235
+ {...typeof legend === 'object' ? legend : null}
234
236
  classes={{
235
237
  item: (item) =>
236
238
  visibleSeries.length && !visibleSeries.some((s) => s.key === item.value)
237
239
  ? 'opacity-50'
238
240
  : '',
241
+ ...props.legend?.classes,
242
+ ...(typeof legend === 'object' ? legend.classes : null),
239
243
  }}
240
- {...props.legend}
241
- {...typeof legend === 'object' ? legend : null}
242
244
  />
243
245
  {/if}
244
246
  </slot>
@@ -246,9 +248,11 @@
246
248
  <slot name="tooltip" {...slotProps}>
247
249
  <Tooltip.Root {...props.tooltip?.root} let:data>
248
250
  {#if activeSeries?.key !== 'default'}
249
- <Tooltip.Header {...props.tooltip?.header} color={activeSeries?.color}>
250
- {activeSeries?.label ?? activeSeries?.key}
251
- </Tooltip.Header>
251
+ <Tooltip.Header
252
+ value={activeSeries?.label ?? activeSeries?.key}
253
+ color={activeSeries?.color}
254
+ {...props.tooltip?.header}
255
+ />
252
256
  {/if}
253
257
  <Tooltip.List {...props.tooltip?.list}>
254
258
  <Tooltip.Item
@@ -37,6 +37,9 @@
37
37
  /** Set to `false` to disable spring transitions */
38
38
  export let motion = true;
39
39
 
40
+ /** Allow pointer events. Disabled by default to reduce accidental selection, but useful to enable to allow interactdive tooltips (using `locked`) */
41
+ export let pointerEvents = false;
42
+
40
43
  export let classes: {
41
44
  root?: string;
42
45
  container?: string;
@@ -203,7 +206,7 @@
203
206
 
204
207
  {#if $tooltip.data}
205
208
  <div
206
- class={cls('absolute pointer-events-none z-50 select-none', classes.root)}
209
+ class={cls('absolute z-50 select-none', !pointerEvents && 'pointer-events-none', classes.root)}
207
210
  style:top="{$yPos}px"
208
211
  style:left="{$xPos}px"
209
212
  transition:fade={{ duration: 100 }}
@@ -10,6 +10,7 @@ declare const __propDef: {
10
10
  contained?: "container" | "window" | false | undefined;
11
11
  variant?: "default" | "invert" | "none" | undefined;
12
12
  motion?: boolean | undefined;
13
+ pointerEvents?: boolean | undefined;
13
14
  classes?: {
14
15
  root?: string;
15
16
  container?: string;
@@ -97,6 +97,9 @@
97
97
  /** 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 */
98
98
  export let raiseTarget = false;
99
99
 
100
+ /** Lock tooltip (keep open, do not update on mouse movement). Allows for kicking on tooltip */
101
+ export let locked = false;
102
+
100
103
  /** quadtree search radius
101
104
  * @type {number}
102
105
  */
@@ -169,6 +172,11 @@
169
172
  // Cancel hiding tooltip if from previous event loop
170
173
  clearTimeout(hideTimeoutId);
171
174
 
175
+ if (locked) {
176
+ // Ignore (keep current position / data)
177
+ return;
178
+ }
179
+
172
180
  const referenceNode = (e.target as Element).closest('.layercake-container')!;
173
181
  const point = localPoint(referenceNode, e);
174
182
  const pointerX = point?.x ?? 0;
@@ -275,6 +283,11 @@
275
283
  }
276
284
 
277
285
  function hideTooltip() {
286
+ if (locked) {
287
+ // Ignore (keep open)
288
+ return;
289
+ }
290
+
278
291
  // Wait an event loop tick in case `showTooltip` is called immediately on another element, to allow tweeneing (ex. moving between bands/bars)
279
292
  hideTimeoutId = setTimeout(() => {
280
293
  $tooltip = { ...$tooltip, data: null };
@@ -369,7 +382,7 @@
369
382
  .sort(sortFunc('x'));
370
383
  }
371
384
 
372
- $: triggerPointEvents = ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode);
385
+ $: triggerPointerEvents = ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode);
373
386
  </script>
374
387
 
375
388
  <!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -381,13 +394,13 @@
381
394
  style:left="{$padding.left}px"
382
395
  class={cls(
383
396
  'tooltip-trigger absolute touch-none',
384
- debug && triggerPointEvents && 'bg-danger/10 outline outline-danger'
397
+ debug && triggerPointerEvents && 'bg-danger/10 outline outline-danger'
385
398
  )}
386
- on:pointerenter={triggerPointEvents ? showTooltip : undefined}
387
- on:pointermove={triggerPointEvents ? showTooltip : undefined}
388
- on:pointerleave={triggerPointEvents ? hideTooltip : undefined}
399
+ on:pointerenter={triggerPointerEvents ? showTooltip : undefined}
400
+ on:pointermove={triggerPointerEvents ? showTooltip : undefined}
401
+ on:pointerleave={triggerPointerEvents ? hideTooltip : undefined}
389
402
  on:click={(e) => {
390
- if (triggerPointEvents) {
403
+ if (triggerPointerEvents) {
391
404
  onClick({ data: $tooltip?.data });
392
405
  }
393
406
  }}
@@ -19,6 +19,7 @@ declare const __propDef: {
19
19
  * @type {'closest' | 'left' | 'right'}
20
20
  */ findTooltipData?: "closest" | "left" | "right";
21
21
  /** 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;
22
+ /** Lock tooltip (keep open, do not update on mouse movement). Allows for kicking on tooltip */ locked?: boolean;
22
23
  /** quadtree search radius
23
24
  * @type {number}
24
25
  */ radius?: number;
@@ -1,6 +1,9 @@
1
1
  <script lang="ts">
2
+ import { format as formatUtil, type FormatType } from '@layerstack/utils';
2
3
  import { cls } from '@layerstack/tailwind';
3
4
 
5
+ export let value: any = undefined;
6
+ export let format: FormatType | undefined = undefined;
4
7
  export let color: string | undefined = undefined;
5
8
 
6
9
  export let classes: {
@@ -23,5 +26,5 @@
23
26
  style:--color={color}
24
27
  ></div>
25
28
  {/if}
26
- <slot />
29
+ <slot>{format ? formatUtil(value, format) : value}</slot>
27
30
  </div>
@@ -1,7 +1,10 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import { type FormatType } from '@layerstack/utils';
2
3
  declare const __propDef: {
3
4
  props: {
4
5
  [x: string]: any;
6
+ value?: any;
7
+ format?: FormatType | undefined;
5
8
  color?: string | undefined | undefined;
6
9
  classes?: {
7
10
  root?: 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.75.1",
7
+ "version": "0.76.1",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.10",
10
10
  "@mdi/js": "^7.4.47",