layerchart 2.0.0-next.37 → 2.0.0-next.39

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.
Files changed (115) hide show
  1. package/dist/components/AnnotationLine.svelte +15 -2
  2. package/dist/components/AnnotationPoint.svelte +13 -2
  3. package/dist/components/AnnotationRange.svelte +16 -2
  4. package/dist/components/Arc.svelte +3 -3
  5. package/dist/components/Area.svelte +10 -2
  6. package/dist/components/Axis.svelte +43 -26
  7. package/dist/components/Axis.svelte.d.ts +10 -3
  8. package/dist/components/Bar.svelte +6 -5
  9. package/dist/components/Bar.svelte.d.ts +2 -2
  10. package/dist/components/Bars.svelte +3 -3
  11. package/dist/components/Blur.svelte +2 -3
  12. package/dist/components/BrushContext.svelte +44 -44
  13. package/dist/components/Calendar.svelte +21 -4
  14. package/dist/components/Chart.svelte +1 -2
  15. package/dist/components/Chart.svelte.d.ts +10 -3
  16. package/dist/components/ChartClipPath.svelte +1 -1
  17. package/dist/components/Circle.svelte +44 -3
  18. package/dist/components/CircleClipPath.svelte +8 -1
  19. package/dist/components/ClipPath.svelte +1 -2
  20. package/dist/components/ColorRamp.svelte +1 -1
  21. package/dist/components/ComputedStyles.svelte +9 -2
  22. package/dist/components/Connector.svelte +1 -1
  23. package/dist/components/Ellipse.svelte +44 -3
  24. package/dist/components/ForceSimulation.svelte.d.ts +10 -3
  25. package/dist/components/Frame.svelte +1 -1
  26. package/dist/components/GeoCircle.svelte +1 -1
  27. package/dist/components/GeoEdgeFade.svelte +1 -1
  28. package/dist/components/GeoPath.svelte +18 -3
  29. package/dist/components/GeoPoint.svelte +3 -3
  30. package/dist/components/GeoSpline.svelte +1 -1
  31. package/dist/components/GeoTile.svelte +1 -1
  32. package/dist/components/Graticule.svelte +5 -5
  33. package/dist/components/Grid.svelte +57 -60
  34. package/dist/components/Group.svelte +11 -6
  35. package/dist/components/Group.svelte.d.ts +10 -3
  36. package/dist/components/Highlight.svelte +46 -22
  37. package/dist/components/Highlight.svelte.d.ts +4 -0
  38. package/dist/components/Hull.svelte +11 -4
  39. package/dist/components/Labels.svelte +21 -11
  40. package/dist/components/Labels.svelte.d.ts +10 -3
  41. package/dist/components/Legend.svelte +133 -67
  42. package/dist/components/Legend.svelte.d.ts +7 -3
  43. package/dist/components/Line.svelte +40 -3
  44. package/dist/components/LinearGradient.svelte +35 -4
  45. package/dist/components/Link.svelte +1 -1
  46. package/dist/components/Marker.svelte +37 -26
  47. package/dist/components/MonthPath.svelte +14 -3
  48. package/dist/components/MotionPath.svelte +1 -1
  49. package/dist/components/Pack.svelte.d.ts +10 -3
  50. package/dist/components/Partition.svelte.d.ts +10 -3
  51. package/dist/components/Pattern.svelte +5 -5
  52. package/dist/components/Pie.svelte +1 -2
  53. package/dist/components/Points.svelte +1 -3
  54. package/dist/components/Polygon.svelte +27 -3
  55. package/dist/components/RadialGradient.svelte +3 -3
  56. package/dist/components/Rect.svelte +55 -5
  57. package/dist/components/Rect.svelte.d.ts +2 -2
  58. package/dist/components/RectClipPath.svelte +4 -3
  59. package/dist/components/RectClipPath.svelte.d.ts +2 -2
  60. package/dist/components/Rule.svelte +30 -23
  61. package/dist/components/Spline.svelte +29 -10
  62. package/dist/components/Text.svelte +59 -13
  63. package/dist/components/TileImage.svelte +19 -4
  64. package/dist/components/TransformContext.svelte +9 -3
  65. package/dist/components/TransformControls.svelte +72 -17
  66. package/dist/components/Tree.svelte.d.ts +10 -3
  67. package/dist/components/Treemap.svelte.d.ts +10 -3
  68. package/dist/components/Voronoi.svelte +12 -13
  69. package/dist/components/charts/ArcChart.svelte +40 -69
  70. package/dist/components/charts/ArcChart.svelte.d.ts +10 -3
  71. package/dist/components/charts/AreaChart.svelte +19 -42
  72. package/dist/components/charts/AreaChart.svelte.d.ts +10 -3
  73. package/dist/components/charts/BarChart.svelte +7 -18
  74. package/dist/components/charts/BarChart.svelte.d.ts +10 -3
  75. package/dist/components/charts/DefaultTooltip.svelte +2 -2
  76. package/dist/components/charts/DefaultTooltip.svelte.d.ts +1 -1
  77. package/dist/components/charts/LineChart.svelte +61 -66
  78. package/dist/components/charts/LineChart.svelte.d.ts +21 -8
  79. package/dist/components/charts/PieChart.svelte +41 -69
  80. package/dist/components/charts/PieChart.svelte.d.ts +10 -3
  81. package/dist/components/charts/ScatterChart.svelte +8 -19
  82. package/dist/components/charts/ScatterChart.svelte.d.ts +10 -3
  83. package/dist/components/charts/utils.svelte.d.ts +1 -19
  84. package/dist/components/charts/utils.svelte.js +7 -39
  85. package/dist/components/layout/Canvas.svelte +29 -20
  86. package/dist/components/layout/Html.svelte +15 -9
  87. package/dist/components/layout/Svg.svelte +19 -11
  88. package/dist/components/layout/WebGL.svelte +26 -6
  89. package/dist/components/layout/WebGL.svelte.d.ts +5 -2
  90. package/dist/components/tooltip/Tooltip.svelte +60 -29
  91. package/dist/components/tooltip/Tooltip.svelte.d.ts +10 -3
  92. package/dist/components/tooltip/TooltipContext.svelte +73 -36
  93. package/dist/components/tooltip/TooltipContext.svelte.d.ts +17 -3
  94. package/dist/components/tooltip/TooltipHeader.svelte +27 -14
  95. package/dist/components/tooltip/TooltipItem.svelte +41 -33
  96. package/dist/components/tooltip/TooltipList.svelte +12 -10
  97. package/dist/components/tooltip/TooltipSeparator.svelte +18 -10
  98. package/dist/states/series.svelte.d.ts +30 -0
  99. package/dist/states/series.svelte.js +54 -0
  100. package/dist/styles/daisyui-5.css +6 -0
  101. package/dist/styles/shadcn-svelte.css +11 -0
  102. package/dist/styles/skeleton-3.css +15 -0
  103. package/dist/utils/attributes.d.ts +3 -13
  104. package/dist/utils/attributes.js +4 -18
  105. package/dist/utils/common.d.ts +9 -0
  106. package/dist/utils/common.js +18 -1
  107. package/dist/utils/common.test.js +26 -1
  108. package/dist/utils/graph/dagre.d.ts +4 -4
  109. package/dist/utils/graph/dagre.js +5 -7
  110. package/dist/utils/math.d.ts +17 -0
  111. package/dist/utils/math.js +17 -0
  112. package/dist/utils/scales.svelte.js +3 -3
  113. package/dist/utils/stack.js +1 -1
  114. package/dist/utils/types.d.ts +15 -2
  115. package/package.json +25 -22
@@ -162,7 +162,6 @@
162
162
  import { getTooltipContext } from './TooltipContext.svelte';
163
163
  import { createMotion, type MotionProp } from '../../utils/motion.svelte.js';
164
164
  import { untrack, type Snippet } from 'svelte';
165
- import { layerClass } from '../../utils/attributes.js';
166
165
 
167
166
  let {
168
167
  anchor = 'top-left',
@@ -359,8 +358,8 @@
359
358
  {#if tooltipCtx.data}
360
359
  <div
361
360
  {...props.root}
362
- class={cls('root', layerClass('tooltip-root'), classes.root, props.root?.class)}
363
- class:pointer-events-none={!pointerEvents}
361
+ class={cls('lc-tooltip-root', classes.root, props.root?.class)}
362
+ class:disablePointerEvents={pointerEvents === false}
364
363
  style:top="{motionY.current}px"
365
364
  style:left="{motionX.current}px"
366
365
  transition:fade={{ duration: 100 }}
@@ -376,27 +375,11 @@
376
375
  >
377
376
  <div
378
377
  {...props.container}
379
- class={cls(
380
- layerClass('tooltip-container'),
381
- variant !== 'none' && ['text-sm py-1 px-2 h-full rounded-sm elevation-1'],
382
- {
383
- default: [
384
- 'bg-surface-100/90 dark:bg-surface-300/90 backdrop-filter backdrop-blur-[2px] text-surface-content',
385
- '[&_.label]:text-surface-content/75',
386
- ],
387
- invert: [
388
- 'bg-surface-content/90 backdrop-filter backdrop-blur-[2px] text-surface-100 border border-surface-content',
389
- '[&_.label]:text-surface-100/50',
390
- ],
391
- none: '',
392
- }[variant],
393
- classes.container,
394
- props.container?.class,
395
- className
396
- )}
378
+ class={cls('lc-tooltip-container', classes.container, props.container?.class, className)}
379
+ data-variant={variant}
397
380
  >
398
381
  {#if children}
399
- <div {...props.content} class={cls(layerClass('tooltip-content'), classes.content)}>
382
+ <div {...props.content} class={cls('lc-tooltip-content', classes.content)}>
400
383
  {@render children({ data: tooltipCtx.data, payload: tooltipCtx.payload })}
401
384
  </div>
402
385
  {/if}
@@ -405,13 +388,61 @@
405
388
  {/if}
406
389
 
407
390
  <style>
408
- .root {
409
- position: absolute;
410
- z-index: 50;
411
- user-select: none;
412
- }
391
+ @layer component {
392
+ :where(.lc-tooltip-root) {
393
+ position: absolute;
394
+ z-index: 50;
395
+ user-select: none;
396
+
397
+ &.disablePointerEvents {
398
+ pointer-events: none;
399
+ }
400
+ }
401
+
402
+ :where(.lc-tooltip-container) {
403
+ &:not([data-variant='none']) {
404
+ font-size: 0.875rem;
405
+ line-height: 1.25rem;
406
+ padding: 4px 8px;
407
+ height: 100%;
408
+ border-radius: 0.25rem; /* rounded-sm */
409
+ box-shadow: /* elevation-1 */
410
+ 0px 2px 1px -1px hsl(0 0% 0% / 20%),
411
+ 0px 1px 1px 0px hsl(0 0% 0% / 14%),
412
+ 0px 1px 3px 0px hsl(0 0% 0% / 12%);
413
+ /* STYLE-TODO: vendor prefix (-webkit?) */
414
+ backdrop-filter: blur(2px);
415
+ }
416
+
417
+ &[data-variant='default'] {
418
+ color: var(--color-surface-content, currentColor);
419
+ background-color: color-mix(
420
+ in oklab,
421
+ light-dark(var(--color-surface-100, white), var(--color-surface-300, black)) 90%,
422
+ transparent
423
+ );
413
424
 
414
- .pointer-events-none {
415
- pointer-events: none;
425
+ :global(& .label) {
426
+ color: color-mix(in oklab, var(--color-surface-content, currentColor) 75%, transparent);
427
+ }
428
+ }
429
+
430
+ &[data-variant='invert'] {
431
+ color: var(--color-surface-100, light-dark(white, black));
432
+ background-color: color-mix(
433
+ in oklab,
434
+ var(--color-surface-content, currentColor) 90%,
435
+ transparent
436
+ );
437
+
438
+ :global(& .label) {
439
+ color: color-mix(
440
+ in oklab,
441
+ var(--color-surface-100, light-dark(white, black)) 50%,
442
+ transparent
443
+ );
444
+ }
445
+ }
446
+ }
416
447
  }
417
448
  </style>
@@ -134,10 +134,17 @@ export type TooltipProps<T = any> = TooltipPropsWithoutHTML<T> & Without<HTMLAtt
134
134
  import { type ChartContextValue } from '../Chart.svelte';
135
135
  import { type MotionProp } from '../../utils/motion.svelte.js';
136
136
  import { type Snippet } from 'svelte';
137
+ declare function $$render<T = any>(): {
138
+ props: TooltipProps<T>;
139
+ exports: {};
140
+ bindings: "rootRef";
141
+ slots: {};
142
+ events: {};
143
+ };
137
144
  declare class __sveltets_Render<T = any> {
138
- props(): TooltipProps<T>;
139
- events(): {};
140
- slots(): {};
145
+ props(): ReturnType<typeof $$render<T>>['props'];
146
+ events(): ReturnType<typeof $$render<T>>['events'];
147
+ slots(): ReturnType<typeof $$render<T>>['slots'];
141
148
  bindings(): "rootRef";
142
149
  exports(): {};
143
150
  }
@@ -77,6 +77,14 @@
77
77
  */
78
78
  locked?: boolean;
79
79
 
80
+ /**
81
+ * Controls the touch event behavior on the tooltip container.
82
+ * By default uses `pan-y` to allow verticle scrolling but horizontal scrubbing.
83
+ * Use `none` to disable all touch events (useful for improved transform/geo charts interactions)
84
+ * @default 'pan-y'
85
+ */
86
+ touchEvents?: 'none' | 'pan-x' | 'pan-y' | 'auto';
87
+
80
88
  /**
81
89
  * quadtree search or voronoi clip radius
82
90
  * @default Infinity
@@ -144,7 +152,6 @@
144
152
  getTooltipPayload,
145
153
  type TooltipPayload,
146
154
  } from './tooltipMetaContext.js';
147
- import { layerClass } from '../../utils/attributes.js';
148
155
 
149
156
  const ctx = getChartContext<any>();
150
157
  const geoCtx = getGeoContext();
@@ -155,6 +162,7 @@
155
162
  findTooltipData = 'closest',
156
163
  hideDelay = 0,
157
164
  locked = false,
165
+ touchEvents = 'pan-y',
158
166
  mode = 'manual',
159
167
  onclick = () => {},
160
168
  radius = Infinity,
@@ -497,16 +505,16 @@
497
505
  // full band width/height regardless of value
498
506
  return {
499
507
  x: x - xOffset,
500
- y: min(ctx.yRange),
508
+ y: isScaleBand(ctx.yScale) ? y - yOffset : min(ctx.yRange),
501
509
  width: ctx.xScale.step(),
502
- height: fullHeight,
510
+ height: isScaleBand(ctx.yScale) ? ctx.yScale.step() : fullHeight,
503
511
  data: d,
504
512
  };
505
513
  } else if (isScaleBand(ctx.yScale)) {
506
514
  return {
507
- x: min(ctx.xRange),
515
+ x: isScaleBand(ctx.xScale) ? x - xOffset : min(ctx.xRange),
508
516
  y: y - yOffset,
509
- width: fullWidth,
517
+ width: isScaleBand(ctx.xScale) ? ctx.xScale.step() : fullWidth,
510
518
  height: ctx.yScale.step(),
511
519
  data: d,
512
520
  };
@@ -522,9 +530,9 @@
522
530
 
523
531
  return {
524
532
  x: x - xOffset,
525
- y: min(ctx.yRange),
533
+ y: isScaleBand(ctx.yScale) ? y - yOffset : min(ctx.yRange),
526
534
  width: (ctx.xScale(nextDataPoint) ?? 0) - (xValue ?? 0),
527
- height: fullHeight,
535
+ height: isScaleBand(ctx.yScale) ? ctx.yScale.step() : fullHeight,
528
536
  data: d,
529
537
  };
530
538
  } else if (isScaleTime(ctx.yScale)) {
@@ -538,9 +546,9 @@
538
546
  : ctx.y(ctx.flatData[index + 1]);
539
547
 
540
548
  return {
541
- x: min(ctx.xRange),
549
+ x: isScaleBand(ctx.xScale) ? x - xOffset : min(ctx.xRange),
542
550
  y: y - yOffset,
543
- width: fullWidth,
551
+ width: isScaleBand(ctx.xScale) ? ctx.xScale.step() : fullWidth,
544
552
  height: (ctx.yScale(nextDataPoint) ?? 0) - (yValue ?? 0),
545
553
  data: d,
546
554
  };
@@ -605,17 +613,12 @@
605
613
  style:left="{ctx.padding.left}px"
606
614
  style:width="{ctx.width}px"
607
615
  style:height="{ctx.height}px"
608
- class={cls(
609
- layerClass('tooltip-context'),
610
- 'absolute',
611
- debug && triggerPointerEvents && 'bg-danger/10 outline outline-danger'
612
- )}
613
- onmouseenter={onPointerEnter}
614
- ontouchstart={onPointerEnter}
615
- onmousemove={onPointerMove}
616
- ontouchmove={onPointerMove}
617
- onmouseleave={onPointerLeave}
618
- ontouchend={onPointerLeave}
616
+ style:--touch-action={touchEvents}
617
+ class="lc-tooltip-context"
618
+ class:debug={debug && triggerPointerEvents}
619
+ onpointerenter={onPointerEnter}
620
+ onpointermove={onPointerMove}
621
+ onpointerleave={onPointerLeave}
619
622
  onclick={(e) => {
620
623
  // Ignore clicks without data (triggered from Legend clicks, for example)
621
624
  if (triggerPointerEvents && tooltipContext.data != null) {
@@ -627,7 +630,7 @@
627
630
  >
628
631
  <!-- Rendering slot within TooltipContext to allow pointer events to bubble up (ex. Brush) -->
629
632
  <div
630
- class={cls(layerClass('tooltip-context-container'), 'absolute')}
633
+ class="lc-tooltip-context-container"
631
634
  style:top="-{ctx.padding.top ?? 0}px"
632
635
  style:left="-{ctx.padding.left ?? 0}px"
633
636
  style:width="{ctx.containerWidth}px"
@@ -656,12 +659,12 @@
656
659
  onclick={(e, { data }) => {
657
660
  onclick(e, { data });
658
661
  }}
659
- classes={{ path: cls(debug && 'fill-danger/10 stroke-danger') }}
662
+ classes={{ path: cls('lc-tooltip-voronoi-path', debug && 'debug') }}
660
663
  />
661
664
  </Svg>
662
665
  {:else if mode === 'bounds' || mode === 'band'}
663
666
  <Svg center={ctx.radial}>
664
- <g class={layerClass('tooltip-rects-g')}>
667
+ <g class="lc-tooltip-rects-g">
665
668
  {#each rects as rect}
666
669
  <!-- svelte-ignore a11y_click_events_have_key_events -->
667
670
  {#if ctx.radial}
@@ -670,10 +673,7 @@
670
673
  outerRadius={rect.y + rect.height}
671
674
  startAngle={rect.x}
672
675
  endAngle={rect.x + rect.width}
673
- class={cls(
674
- layerClass('tooltip-rect'),
675
- debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent'
676
- )}
676
+ class={cls('lc-tooltip-rect', debug && 'debug')}
677
677
  onpointerenter={(e) => showTooltip(e, rect?.data)}
678
678
  onpointermove={(e) => showTooltip(e, rect?.data)}
679
679
  onpointerleave={() => hideTooltip()}
@@ -693,10 +693,7 @@
693
693
  y={rect?.y}
694
694
  width={rect?.width}
695
695
  height={rect?.height}
696
- class={cls(
697
- layerClass('tooltip-rect'),
698
- debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent'
699
- )}
696
+ class={cls('lc-tooltip-rect', debug && 'debug')}
700
697
  onpointerenter={(e) => showTooltip(e, rect?.data)}
701
698
  onpointermove={(e) => showTooltip(e, rect?.data)}
702
699
  onpointerleave={() => hideTooltip()}
@@ -717,7 +714,7 @@
717
714
  {:else if ['quadtree', 'quadtree-x', 'quadtree-y'].includes(mode) && debug}
718
715
  <Svg pointerEvents={false}>
719
716
  <ChartClipPath>
720
- <g class={layerClass('tooltip-quadtree-g')}>
717
+ <g class="lc-tooltip-quadtree-g">
721
718
  {#if quadtree}
722
719
  {#each quadtreeRects(quadtree, false) as rect}
723
720
  <rect
@@ -725,10 +722,7 @@
725
722
  y={rect.y}
726
723
  width={rect.width}
727
724
  height={rect.height}
728
- class={cls(
729
- layerClass('tooltip-quadtree-rect'),
730
- debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent'
731
- )}
725
+ class={cls('lc-tooltip-quadtree-rect', debug && 'debug')}
732
726
  />
733
727
  {/each}
734
728
  {/if}
@@ -738,3 +732,46 @@
738
732
  {/if}
739
733
  </div>
740
734
  </div>
735
+
736
+ <style>
737
+ @layer component {
738
+ :where(.lc-tooltip-context-container) {
739
+ position: absolute;
740
+ }
741
+
742
+ :where(.lc-tooltip-context) {
743
+ position: absolute;
744
+ touch-action: var(--touch-action);
745
+
746
+ &.debug {
747
+ outline: 1px solid var(--color-danger);
748
+ background-color: color-mix(in oklab, var(--color-danger) 10%, transparent);
749
+ }
750
+ }
751
+
752
+ :global(:where(.lc-tooltip-voronoi-path)) {
753
+ &.debug {
754
+ stroke: var(--color-danger);
755
+ fill: color-mix(in oklab, var(--color-danger) 10%, transparent);
756
+ }
757
+ }
758
+
759
+ :where(.lc-tooltip-rect) {
760
+ fill: transparent;
761
+
762
+ &.debug {
763
+ stroke: var(--color-danger);
764
+ fill: color-mix(in oklab, var(--color-danger) 10%, transparent);
765
+ }
766
+ }
767
+
768
+ :where(.lc-tooltip-quadtree-rect) {
769
+ fill: transparent;
770
+
771
+ &.debug {
772
+ stroke: var(--color-danger);
773
+ fill: color-mix(in oklab, var(--color-danger) 10%, transparent);
774
+ }
775
+ }
776
+ }
777
+ </style>
@@ -35,6 +35,13 @@ type TooltipContextPropsWithoutHTML<T = any> = {
35
35
  * @default false
36
36
  */
37
37
  locked?: boolean;
38
+ /**
39
+ * Controls the touch event behavior on the tooltip container.
40
+ * By default uses `pan-y` to allow verticle scrolling but horizontal scrubbing.
41
+ * Use `none` to disable all touch events (useful for improved transform/geo charts interactions)
42
+ * @default 'pan-y'
43
+ */
44
+ touchEvents?: 'none' | 'pan-x' | 'pan-y' | 'auto';
38
45
  /**
39
46
  * quadtree search or voronoi clip radius
40
47
  * @default Infinity
@@ -75,10 +82,17 @@ type TooltipContextPropsWithoutHTML<T = any> = {
75
82
  export type TooltipContextProps<T = any> = TooltipContextPropsWithoutHTML<T> & Without<HTMLAttributes<HTMLElement>, TooltipContextPropsWithoutHTML<T>>;
76
83
  import type { Snippet } from 'svelte';
77
84
  import { type TooltipPayload } from './tooltipMetaContext.js';
85
+ declare function $$render<TData = any>(): {
86
+ props: TooltipContextProps<TData>;
87
+ exports: {};
88
+ bindings: "ref" | "tooltipContext";
89
+ slots: {};
90
+ events: {};
91
+ };
78
92
  declare class __sveltets_Render<TData = any> {
79
- props(): TooltipContextProps<TData>;
80
- events(): {};
81
- slots(): {};
93
+ props(): ReturnType<typeof $$render<TData>>['props'];
94
+ events(): ReturnType<typeof $$render<TData>>['events'];
95
+ slots(): ReturnType<typeof $$render<TData>>['slots'];
82
96
  bindings(): "ref" | "tooltipContext";
83
97
  exports(): {};
84
98
  }
@@ -56,7 +56,6 @@
56
56
  <script lang="ts">
57
57
  import { format as formatUtil, type FormatType, type FormatConfig } from '@layerstack/utils';
58
58
  import { cls } from '@layerstack/tailwind';
59
- import { layerClass } from '../../utils/attributes.js';
60
59
 
61
60
  let {
62
61
  ref: refProp = $bindable(),
@@ -89,25 +88,14 @@
89
88
  </script>
90
89
 
91
90
  <div
92
- class={cls(
93
- layerClass('tooltip-header'),
94
- 'font-semibold whitespace-nowrap border-b mb-1 pb-1 flex items-center gap-2',
95
- classes.root,
96
- props.root?.class,
97
- className
98
- )}
91
+ class={cls('lc-tooltip-header', classes.root, props.root?.class, className)}
99
92
  {...restProps}
100
93
  bind:this={ref}
101
94
  >
102
95
  {#if color}
103
96
  <div
104
97
  bind:this={colorRef}
105
- class={cls(
106
- layerClass('tooltip-header-color'),
107
- 'color',
108
- 'inline-block size-2 rounded-full bg-[var(--color)]',
109
- classes.color
110
- )}
98
+ class={cls('lc-tooltip-header-color', classes.color)}
111
99
  style:--color={color}
112
100
  ></div>
113
101
  {/if}
@@ -118,3 +106,28 @@
118
106
  {format ? formatUtil(value, asAny(format)) : value}
119
107
  {/if}
120
108
  </div>
109
+
110
+ <style>
111
+ @layer component {
112
+ :where(.lc-tooltip-header) {
113
+ font-weight: 600;
114
+ white-space: nowrap;
115
+ border-bottom: 1px solid
116
+ color-mix(in oklab, var(--color-surface-content, currentColor) 20%, transparent);
117
+ margin-bottom: 4px;
118
+ padding-bottom: 4px;
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 8px;
122
+ }
123
+
124
+ :where(.lc-tooltip-header-color) {
125
+ display: inline-block;
126
+ width: 8px;
127
+ height: 8px;
128
+ border-radius: 9999px; /* rounded-full */
129
+ background-color: var(--color);
130
+ flex-shrink: 0;
131
+ }
132
+ }
133
+ </style>
@@ -78,7 +78,6 @@
78
78
  import { format as formatUtil, type FormatType, type FormatConfig } from '@layerstack/utils';
79
79
  import { cls } from '@layerstack/tailwind';
80
80
  import type { Snippet } from 'svelte';
81
- import { layerClass } from '../../utils/attributes.js';
82
81
 
83
82
  let {
84
83
  ref: refProp = $bindable(),
@@ -129,37 +128,19 @@
129
128
 
130
129
  <div
131
130
  {...props.root}
132
- class={cls(
133
- layerClass('tooltip-item-root'),
134
- 'contents',
135
- classes.root,
136
- className,
137
- props.root?.class
138
- )}
131
+ class={cls('lc-tooltip-item-root', classes.root, className, props.root?.class)}
139
132
  {...restProps}
140
133
  bind:this={ref}
141
134
  >
142
135
  <div
143
136
  {...props.label}
144
- class={cls(
145
- layerClass('tooltip-item-label'),
146
- 'label',
147
- 'flex items-center gap-2 whitespace-nowrap',
148
- classes.label,
149
- props.label?.class
150
- )}
137
+ class={cls('lc-tooltip-item-label', 'label', classes.label, props.label?.class)}
151
138
  bind:this={labelRef}
152
139
  >
153
140
  {#if color}
154
141
  <div
155
142
  {...props.color}
156
- class={cls(
157
- layerClass('tooltip-item-color'),
158
- 'color',
159
- 'inline-block size-2 rounded-full bg-[var(--color)]',
160
- classes.color,
161
- props.color?.class
162
- )}
143
+ class={cls('lc-tooltip-item-color', 'color', classes.color, props.color?.class)}
163
144
  style:--color={color}
164
145
  bind:this={colorRef}
165
146
  ></div>
@@ -174,17 +155,8 @@
174
155
  <div
175
156
  bind:this={valueRef}
176
157
  {...props.value}
177
- class={cls(
178
- layerClass('tooltip-item-value'),
179
- 'value',
180
- 'tabular-nums',
181
- {
182
- 'text-right': valueAlign === 'right',
183
- 'text-center': valueAlign === 'center',
184
- },
185
- classes.value,
186
- props.value?.class
187
- )}
158
+ class={cls('lc-tooltip-item-value', 'value', classes.value, props.value?.class)}
159
+ data-align={valueAlign}
188
160
  >
189
161
  {#if children}
190
162
  {@render children()}
@@ -194,3 +166,39 @@
194
166
  {/if}
195
167
  </div>
196
168
  </div>
169
+
170
+ <style>
171
+ @layer component {
172
+ :where(.lc-tooltip-item-root) {
173
+ display: contents;
174
+ }
175
+
176
+ :where(.lc-tooltip-item-color) {
177
+ display: inline-block;
178
+ width: 8px;
179
+ height: 8px;
180
+ border-radius: 9999px; /* full */
181
+ background-color: var(--color);
182
+ }
183
+
184
+ :where(.lc-tooltip-item-label) {
185
+ display: flex;
186
+ align-items: center;
187
+ gap: 8px;
188
+ white-space: nowrap;
189
+ }
190
+
191
+ :where(.lc-tooltip-item-value) {
192
+ /* tabular-nums */
193
+ font-variant-numeric: tabular-nums;
194
+
195
+ &[data-align='right'] {
196
+ text-align: right;
197
+ }
198
+
199
+ &[data-align='center'] {
200
+ text-align: center;
201
+ }
202
+ }
203
+ }
204
+ </style>
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import { cls } from '@layerstack/tailwind';
3
- import { layerClass } from '../../utils/attributes.js';
4
3
  import type { HTMLAttributes } from 'svelte/elements';
5
4
 
6
5
  let {
@@ -19,14 +18,17 @@
19
18
  });
20
19
  </script>
21
20
 
22
- <div
23
- bind:this={ref}
24
- class={cls(
25
- layerClass('tooltip-list'),
26
- 'grid grid-cols-[1fr_auto] gap-x-2 gap-y-1 items-start',
27
- className
28
- )}
29
- {...restProps}
30
- >
21
+ <div bind:this={ref} class={cls('lc-tooltip-list', className)} {...restProps}>
31
22
  {@render children?.()}
32
23
  </div>
24
+
25
+ <style>
26
+ @layer component {
27
+ :where(.lc-tooltip-list) {
28
+ display: grid;
29
+ grid-template-columns: 1fr auto;
30
+ gap: 4px 8px;
31
+ align-items: start;
32
+ }
33
+ }
34
+ </style>
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import { cls } from '@layerstack/tailwind';
3
- import { layerClass } from '../../utils/attributes.js';
4
3
  import type { HTMLAttributes } from 'svelte/elements';
5
4
 
6
5
  let {
@@ -18,14 +17,23 @@
18
17
  });
19
18
  </script>
20
19
 
21
- <div
22
- bind:this={ref}
23
- class={cls(
24
- layerClass('tooltip-separator'),
25
- 'rounded-sm bg-surface-content/20 my-1 col-span-full h-px',
26
- className
27
- )}
28
- {...restProps}
29
- >
20
+ <div bind:this={ref} class={cls('lc-tooltip-separator', className)} {...restProps}>
30
21
  {@render children?.()}
31
22
  </div>
23
+
24
+ <style>
25
+ @layer component {
26
+ :where(.lc-tooltip-separator) {
27
+ height: 1px;
28
+ border-radius: 4px;
29
+ background-color: color-mix(
30
+ in oklab,
31
+ var(--color-surface-content, currentColor) 20%,
32
+ transparent
33
+ );
34
+ margin-top: 4px;
35
+ margin-bottom: 4px;
36
+ grid-column: 1 / -1; /* col-span-full */
37
+ }
38
+ }
39
+ </style>
@@ -0,0 +1,30 @@
1
+ import type { Component } from 'svelte';
2
+ import type { SeriesData } from '../components/charts/types.js';
3
+ import { SelectionState } from '@layerstack/svelte-state';
4
+ declare class HighlightKey<TData, SeriesComponent extends Component> {
5
+ current: string | null;
6
+ set: (seriesKey: typeof this.current) => void;
7
+ }
8
+ export declare class SeriesState<TData, TComponent extends Component> {
9
+ #private;
10
+ selectedKeys: SelectionState<string, false>;
11
+ highlightKey: HighlightKey<TData, TComponent>;
12
+ constructor(getSeries: () => SeriesData<TData, TComponent>[]);
13
+ get series(): SeriesData<TData, TComponent>[];
14
+ get isDefaultSeries(): boolean;
15
+ get visibleSeries(): SeriesData<TData, TComponent>[];
16
+ /**
17
+ * Check if series is visible
18
+ */
19
+ isVisible(seriesKey: SeriesData<TData, TComponent>['key']): boolean;
20
+ /**
21
+ * Check if series is highlighted
22
+ * Changing default to `true` is useful to determine if series should be faded
23
+ */
24
+ isHighlighted(seriesKey: SeriesData<TData, TComponent>['key'], defaultValue?: boolean): boolean;
25
+ get allSeriesData(): Array<TData & {
26
+ seriesKey: string;
27
+ }>;
28
+ get allSeriesColors(): Array<NonNullable<SeriesData<TData, TComponent>["color"]>>;
29
+ }
30
+ export {};