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
@@ -132,7 +132,6 @@
132
132
  import { getChartContext } from './Chart.svelte';
133
133
  import { createKey } from '../utils/key.svelte.js';
134
134
  import { createId } from '../utils/createId.js';
135
- import { layerClass } from '../utils/attributes.js';
136
135
 
137
136
  const ctx = getChartContext();
138
137
 
@@ -274,7 +273,7 @@
274
273
  ? merge({ styles: { strokeWidth } }, styleOverrides)
275
274
  : {
276
275
  styles: { fill, fillOpacity, stroke, strokeWidth, opacity },
277
- classes: className,
276
+ classes: cls('lc-spline-path', className),
278
277
  }
279
278
  );
280
279
  }
@@ -362,12 +361,7 @@
362
361
  <path
363
362
  d={tweenedState.current}
364
363
  {...restProps}
365
- class={cls(
366
- layerClass('spline-path'),
367
- !fill && 'fill-none',
368
- !stroke && 'stroke-surface-content',
369
- className
370
- )}
364
+ class={cls('lc-spline-path', className)}
371
365
  {fill}
372
366
  fill-opacity={fillOpacity}
373
367
  {stroke}
@@ -384,7 +378,7 @@
384
378
  <MarkerWrapper id={markerEndId} marker={markerEnd} />
385
379
 
386
380
  {#if startContent && startPoint}
387
- <Group x={startPoint.x} y={startPoint.y} class={layerClass('spline-g-start')}>
381
+ <Group x={startPoint.x} y={startPoint.y} class="lc-spline-g-start">
388
382
  {@render startContent({
389
383
  point: startPoint,
390
384
  value: {
@@ -396,7 +390,7 @@
396
390
  {/if}
397
391
 
398
392
  {#if endContent && endPoint.current}
399
- <Group x={endPoint.current.x} y={endPoint.current.y} class={layerClass('spline-g-end')}>
393
+ <Group x={endPoint.current.x} y={endPoint.current.y} class="lc-spline-g-end">
400
394
  {@render endContent({
401
395
  point: endPoint.current,
402
396
  value: {
@@ -408,3 +402,28 @@
408
402
  {/if}
409
403
  {/key}
410
404
  {/if}
405
+
406
+ <style>
407
+ @layer base {
408
+ :global(:where(.lc-spline-path)) {
409
+ --fill-color: none;
410
+ --stroke-color: var(--color-surface-content, currentColor);
411
+ }
412
+
413
+ /* Svg | Canvas layers */
414
+ :global(:where(.lc-layout-svg .lc-spline-path, svg.lc-spline-path):not([fill])) {
415
+ fill: var(--fill-color);
416
+ }
417
+ :global(:where(.lc-layout-svg .lc-spline-path, svg.lc-spline-path):not([stroke])) {
418
+ stroke: var(--stroke-color);
419
+ }
420
+
421
+ /* Html layers */
422
+ :global(:where(.lc-layout-html .lc-spline-path):not([background-color])) {
423
+ background-color: var(--fill-color);
424
+ }
425
+ :global(:where(.lc-layout-html .lc-spline-path):not([border-color])) {
426
+ border-color: var(--stroke-color);
427
+ }
428
+ }
429
+ </style>
@@ -188,7 +188,6 @@
188
188
  import { getComputedStyles, renderText, type ComputedStylesOptions } from '../utils/canvas.js';
189
189
 
190
190
  import { createKey } from '../utils/key.svelte.js';
191
- import { layerClass } from '../utils/attributes.js';
192
191
  import { degreesToRadians } from '../utils/math.js';
193
192
  import { createId } from '../utils/createId.js';
194
193
 
@@ -411,7 +410,7 @@
411
410
  paintOrder: 'stroke',
412
411
  textAnchor,
413
412
  },
414
- classes: cls(fill === undefined && 'fill-surface-content', className),
413
+ classes: cls('lc-text', className),
415
414
  };
416
415
 
417
416
  const computedStyles = getComputedStyles(ctx.canvas, styles);
@@ -473,13 +472,7 @@
473
472
  {#if renderCtx === 'svg'}
474
473
  <!-- `overflow: visible` allow contents to be shown outside element -->
475
474
  <!-- `paint-order: stroke` supports stroke outlining text -->
476
- <svg
477
- x={dx}
478
- y={dy}
479
- {...svgProps}
480
- class={cls(layerClass('text-svg'), 'overflow-visible [paint-order:stroke]', svgProps?.class)}
481
- bind:this={svgRef}
482
- >
475
+ <svg x={dx} y={dy} {...svgProps} class={['lc-text-svg', svgProps?.class]} bind:this={svgRef}>
483
476
  {#if path}
484
477
  <defs>
485
478
  {#key path}
@@ -496,14 +489,14 @@
496
489
  stroke-width={strokeWidth}
497
490
  {opacity}
498
491
  transform={transformProp}
499
- class={cls(layerClass('text'), fill === undefined && 'fill-surface-content', className)}
492
+ class={['lc-text', className]}
500
493
  >
501
494
  <textPath
502
495
  style="text-anchor: {textAnchor};"
503
496
  dominant-baseline={dominantBaseline}
504
497
  href="#{pathId}"
505
498
  {startOffset}
506
- class={cls(layerClass('text-path'))}
499
+ class="lc-text-path"
507
500
  >
508
501
  {wordsByLines.map((line) => line.words.join(' ')).join()}
509
502
  </textPath>
@@ -522,13 +515,13 @@
522
515
  {stroke}
523
516
  stroke-width={strokeWidth}
524
517
  {opacity}
525
- class={cls(layerClass('text'), fill === undefined && 'fill-surface-content', className)}
518
+ class={['lc-text', className]}
526
519
  >
527
520
  {#each wordsByLines as line, index}
528
521
  <tspan
529
522
  x={motionX.current}
530
523
  dy={index === 0 ? startDy : getPixelValue(lineHeight)}
531
- class={layerClass('text-tspan')}
524
+ class="lc-text-tspan"
532
525
  >
533
526
  {line.words.join(' ')}
534
527
  </tspan>
@@ -536,4 +529,57 @@
536
529
  </text>
537
530
  {/if}
538
531
  </svg>
532
+ {:else if renderCtx === 'html'}
533
+ {@const translateX = textAnchor === 'middle' ? '-50%' : textAnchor === 'end' ? '-100%' : '0%'}
534
+ {@const translateY =
535
+ verticalAnchor === 'middle' ? '-50%' : verticalAnchor === 'end' ? '-100%' : '0%'}
536
+ <!-- TODO: How best to handle dx/dy when adjusted for svg style issues? -->
537
+ <!-- style:line-height={lineHeight} -->
538
+ <!-- TODO: How to handle fill-/stroke- vs bg-/text-/border- colors? -->
539
+ <div
540
+ style:position="absolute"
541
+ style:left="{dx + motionX.current}px"
542
+ style:top="{dy + motionY.current}px"
543
+ style:transform="translate({translateX}, {translateY}) rotate({rotate ?? 0}deg)"
544
+ style:transform-origin="{verticalAnchor === 'middle'
545
+ ? 'center'
546
+ : verticalAnchor === 'end'
547
+ ? 'bottom'
548
+ : 'top'}
549
+ {textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'right' : 'left'}"
550
+ class={['lc-text', className]}
551
+ >
552
+ {textValue}
553
+ </div>
539
554
  {/if}
555
+
556
+ <style>
557
+ @layer base {
558
+ :global(:where(.lc-text)) {
559
+ --fill-color: var(--color-surface-content, currentColor);
560
+ --stroke-color: initial;
561
+ }
562
+
563
+ :global(:where(.lc-text-svg)) {
564
+ overflow: visible;
565
+ paint-order: stroke;
566
+ }
567
+
568
+ /* Svg | Canvas layers */
569
+ :global(:where(.lc-layout-svg .lc-text, svg.lc-text):not([fill])) {
570
+ color: var(--fill-color);
571
+ fill: currentColor;
572
+ }
573
+ :global(:where(.lc-layout-svg .lc-text, svg.lc-text):not([stroke])) {
574
+ stroke: var(--stroke-color);
575
+ }
576
+
577
+ /* Html layers */
578
+ :global(:where(.lc-layout-html .lc-text):not([background-color])) {
579
+ color: var(--fill-color);
580
+ }
581
+ :global(:where(.lc-layout-html .lc-text):not([border-color])) {
582
+ border-color: var(--stroke-color);
583
+ }
584
+ }
585
+ </style>
@@ -135,7 +135,7 @@
135
135
  y={(y + ty) * scale - 0.5}
136
136
  width={scale + 1}
137
137
  height={scale + 1}
138
- {...extractLayerProps(restProps, 'tile-image-lower')}
138
+ {...extractLayerProps(restProps, 'lc-tile-image-lower')}
139
139
  />
140
140
  <image
141
141
  {href}
@@ -143,7 +143,7 @@
143
143
  y={(y + ty) * scale}
144
144
  width={scale}
145
145
  height={scale}
146
- {...extractLayerProps(restProps, 'tile-image')}
146
+ {...extractLayerProps(restProps, 'lc-tile-image')}
147
147
  />
148
148
  {/key}
149
149
  {#if debug}
@@ -152,7 +152,7 @@
152
152
  y={(y + ty) * scale}
153
153
  width={scale}
154
154
  height={scale}
155
- class="stroke-danger/50 fill-none"
155
+ class="lc-tile-image-debug-rect"
156
156
  />
157
157
  <Text
158
158
  x={(x + tx) * scale}
@@ -161,6 +161,21 @@
161
161
  dx={2}
162
162
  dy={-2}
163
163
  value="{x}-{y}-{z}"
164
- class="text-[8px] fill-black/50"
164
+ class="lc-tile-image-debug-text"
165
165
  />
166
166
  {/if}
167
+
168
+ <style>
169
+ @layer components {
170
+ :global(:where(.lc-tile-image-debug-rect)) {
171
+ fill: none;
172
+ stroke: var(--color-danger, red);
173
+ }
174
+
175
+ :global(:where(.lc-tile-image-debug-text)) {
176
+ --fill-color: var(--color-danger, red);
177
+ font-size: 14px;
178
+ font-weight: 500;
179
+ }
180
+ }
181
+ </style>
@@ -216,8 +216,6 @@
216
216
  import type { Without } from '../utils/types.js';
217
217
  import { getChartContext } from './Chart.svelte';
218
218
  import type { Snippet } from 'svelte';
219
- import { cls } from '@layerstack/tailwind';
220
- import { layerClass } from '../utils/attributes.js';
221
219
  import {
222
220
  createControlledMotion,
223
221
  createMotionTracker,
@@ -519,9 +517,17 @@
519
517
  onpointerup={onPointerUp}
520
518
  ondblclick={onDoubleClick}
521
519
  onclickcapture={onClick}
522
- class={cls(layerClass('transform-context'), 'h-full', className)}
520
+ class={['lc-transform-context', className]}
523
521
  bind:this={ref}
524
522
  {...restProps}
525
523
  >
526
524
  {@render children?.({ transformContext: transformContext })}
527
525
  </div>
526
+
527
+ <style>
528
+ @layer base {
529
+ :where(.lc-transform-context) {
530
+ height: 100%;
531
+ }
532
+ }
533
+ </style>
@@ -32,7 +32,6 @@
32
32
  <script lang="ts">
33
33
  import { type ComponentProps } from 'svelte';
34
34
  import { Button, Icon, MenuButton, Tooltip } from 'svelte-ux';
35
- import { cls } from '@layerstack/tailwind';
36
35
 
37
36
  import LucideFocus from '~icons/lucide/focus';
38
37
  import LucideChevronDown from '~icons/lucide/chevron-down';
@@ -85,22 +84,9 @@
85
84
 
86
85
  <!-- svelte-ignore a11y_no_static_element_interactions -->
87
86
  <div
88
- class={cls(
89
- 'bg-surface-300/50 border rounded-full m-1 backdrop-blur-sm z-10 flex',
90
- orientation === 'vertical' && 'flex-col',
91
- {
92
- 'top-left': 'absolute top-0 left-0',
93
- top: 'absolute top-0 left-1/2 -translate-x-1/2',
94
- 'top-right': 'absolute top-0 right-0',
95
- left: 'absolute top-1/2 left-0 -translate-y-1/2',
96
- center: 'absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2',
97
- right: 'absolute top-1/2 right-0 -translate-y-1/2',
98
- 'bottom-left': 'absolute bottom-0 left-0',
99
- bottom: 'absolute bottom-0 left-1/2 -translate-x-1/2',
100
- 'bottom-right': 'absolute bottom-0 right-0',
101
- }[placement],
102
- className
103
- )}
87
+ class={['lc-transform-controls', className]}
88
+ data-orientation={orientation}
89
+ data-placement={placement}
104
90
  ondblclick={(e) => {
105
91
  // Stop from propagating to TransformContext
106
92
  e.stopPropagation();
@@ -173,3 +159,72 @@
173
159
  </Tooltip>
174
160
  {/if}
175
161
  </div>
162
+
163
+ <style>
164
+ @layer components {
165
+ :where(.lc-transform-controls) {
166
+ display: flex;
167
+ background: color-mix(
168
+ in oklab,
169
+ var(--color-surface-300, light-dark(white, black)) 50%,
170
+ transparent
171
+ );
172
+ border: 1px solid
173
+ color-mix(in oklab, var(--color-surface-content, currentColor) 20%, transparent);
174
+ border-radius: 9999px;
175
+ margin: 4px;
176
+ backdrop-filter: blur(8px);
177
+ z-index: 10;
178
+
179
+ &[data-orientation='vertical'] {
180
+ flex-direction: column;
181
+ }
182
+
183
+ &[data-placement] {
184
+ position: absolute;
185
+ }
186
+
187
+ &[data-placement='top-left'] {
188
+ top: 0;
189
+ left: 0;
190
+ }
191
+ &[data-placement='top'] {
192
+ top: 0;
193
+ left: 50%;
194
+ transform: translateX(-50%);
195
+ }
196
+ &[data-placement='top-right'] {
197
+ top: 0;
198
+ right: 0;
199
+ }
200
+ &[data-placement='left'] {
201
+ top: 50%;
202
+ left: 0;
203
+ transform: translateY(-50%);
204
+ }
205
+ &[data-placement='center'] {
206
+ top: 50%;
207
+ left: 50%;
208
+ transform: translate(-50%, -50%);
209
+ }
210
+ &[data-placement='right'] {
211
+ top: 50%;
212
+ right: 0;
213
+ transform: translateY(-50%);
214
+ }
215
+ &[data-placement='bottom-left'] {
216
+ bottom: 0;
217
+ left: 0;
218
+ }
219
+ &[data-placement='bottom'] {
220
+ bottom: 0;
221
+ left: 50%;
222
+ transform: translateX(-50%);
223
+ }
224
+ &[data-placement='bottom-right'] {
225
+ bottom: 0;
226
+ right: 0;
227
+ }
228
+ }
229
+ }
230
+ </style>
@@ -25,10 +25,17 @@ export type TreeProps<T> = {
25
25
  };
26
26
  import { type HierarchyPointNode, type HierarchyPointLink, type HierarchyNode } from 'd3-hierarchy';
27
27
  import type { Snippet } from 'svelte';
28
+ declare function $$render<T>(): {
29
+ props: TreeProps<T>;
30
+ exports: {};
31
+ bindings: "";
32
+ slots: {};
33
+ events: {};
34
+ };
28
35
  declare class __sveltets_Render<T> {
29
- props(): TreeProps<T>;
30
- events(): {};
31
- slots(): {};
36
+ props(): ReturnType<typeof $$render<T>>['props'];
37
+ events(): ReturnType<typeof $$render<T>>['events'];
38
+ slots(): ReturnType<typeof $$render<T>>['slots'];
32
39
  bindings(): "";
33
40
  exports(): {};
34
41
  }
@@ -58,10 +58,17 @@ export type TreemapProps<T> = {
58
58
  };
59
59
  import { treemapSquarify, type HierarchyNode, type HierarchyRectangularNode } from 'd3-hierarchy';
60
60
  import type { Snippet } from 'svelte';
61
+ declare function $$render<T>(): {
62
+ props: TreemapProps<T>;
63
+ exports: {};
64
+ bindings: "";
65
+ slots: {};
66
+ events: {};
67
+ };
61
68
  declare class __sveltets_Render<T> {
62
- props(): TreemapProps<T>;
63
- events(): {};
64
- slots(): {};
69
+ props(): ReturnType<typeof $$render<T>>['props'];
70
+ events(): ReturnType<typeof $$render<T>>['events'];
71
+ slots(): ReturnType<typeof $$render<T>>['slots'];
65
72
  bindings(): "";
66
73
  exports(): {};
67
74
  }
@@ -71,8 +71,6 @@
71
71
  import { getGeoContext } from './GeoContext.svelte';
72
72
  import CircleClipPath from './CircleClipPath.svelte';
73
73
 
74
- import { layerClass } from '../utils/attributes.js';
75
-
76
74
  let {
77
75
  data,
78
76
  r,
@@ -118,7 +116,7 @@
118
116
  const disableClip = $derived(r === 0 || r == null || r === Infinity);
119
117
  </script>
120
118
 
121
- <Group {...restProps} class={cls(layerClass('voronoi-g'), classes.root, className)}>
119
+ <Group {...restProps} class={cls('lc-voronoi-g', classes.root, className)}>
122
120
  {#if geo.projection}
123
121
  {@const polygons = geoVoronoi().polygons(points)}
124
122
  {#each polygons.features as feature}
@@ -131,11 +129,7 @@
131
129
  >
132
130
  <GeoPath
133
131
  geojson={feature}
134
- class={cls(
135
- layerClass('voronoi-geo-path'),
136
- 'fill-transparent stroke-transparent',
137
- classes.path
138
- )}
132
+ class={['lc-voronoi-geo-path', classes.path]}
139
133
  onclick={(e) => onclick?.(e, { data: feature.properties.site.data, feature })}
140
134
  onpointerenter={(e) =>
141
135
  onpointerenter?.(e, { data: feature.properties.site.data, feature })}
@@ -158,11 +152,7 @@
158
152
  <CircleClipPath cx={point[0]} cy={point[1]} r={r ?? 0} disabled={disableClip}>
159
153
  <Spline
160
154
  {pathData}
161
- class={cls(
162
- layerClass('voronoi-path'),
163
- 'fill-transparent stroke-transparent',
164
- classes.path
165
- )}
155
+ class={['lc-voronoi-path', classes.path]}
166
156
  onclick={(e) => onclick?.(e, { data: point.data, point })}
167
157
  onpointerenter={(e) => onpointerenter?.(e, { data: point.data, point })}
168
158
  onpointermove={(e) => onpointermove?.(e, { data: point.data, point })}
@@ -178,3 +168,12 @@
178
168
  {/each}
179
169
  {/if}
180
170
  </Group>
171
+
172
+ <style>
173
+ @layer components {
174
+ :global(:where(.lc-voronoi-path, .lc-voronoi-geo-path)) {
175
+ fill: transparent;
176
+ stroke: transparent;
177
+ }
178
+ }
179
+ </style>
@@ -124,7 +124,6 @@
124
124
  import { sum } from 'd3-array';
125
125
  import { format } from '@layerstack/utils';
126
126
  import { cls } from '@layerstack/tailwind';
127
- import { SelectionState } from '@layerstack/svelte-state';
128
127
 
129
128
  import Arc, { type ArcPropsWithoutHTML } from '../Arc.svelte';
130
129
  import Chart from '../Chart.svelte';
@@ -133,7 +132,13 @@
133
132
  import Legend from '../Legend.svelte';
134
133
  import * as Tooltip from '../tooltip/index.js';
135
134
 
136
- import { accessor, chartDataArray, type Accessor } from '../../utils/common.js';
135
+ import {
136
+ accessor,
137
+ chartDataArray,
138
+ getObjectOrNull,
139
+ resolveMaybeFn,
140
+ type Accessor,
141
+ } from '../../utils/common.js';
137
142
  import { asAny } from '../../utils/types.js';
138
143
  import type {
139
144
  SeriesData,
@@ -141,7 +146,8 @@
141
146
  SimplifiedChartPropsObject,
142
147
  SimplifiedChartSnippet,
143
148
  } from './types.js';
144
- import { HighlightKey } from './utils.svelte.js';
149
+ import { SeriesState } from '../../states/series.svelte.js';
150
+ import { createLegendProps } from './utils.svelte.js';
145
151
  import { setTooltipMetaContext } from '../tooltip/tooltipMetaContext.js';
146
152
  import { getColorIfDefined } from '../../utils/color.js';
147
153
 
@@ -223,63 +229,32 @@
223
229
  });
224
230
  });
225
231
 
226
- const selectedSeries = new SelectionState();
227
-
228
- const visibleSeries = $derived(
229
- series.filter((s) => selectedSeries.isEmpty() || selectedSeries.isSelected(s.key))
230
- );
231
-
232
- const allSeriesData = $derived(
233
- visibleSeries
234
- .flatMap((s) =>
235
- s.data?.map((d) => {
236
- return { seriesKey: s.key, ...d };
237
- })
238
- )
239
- .filter((d) => d) as Array<TData & { stackData?: any }>
240
- );
232
+ const seriesState = new SeriesState(() => series);
241
233
 
242
234
  const chartData = $derived(
243
- allSeriesData.length ? allSeriesData : chartDataArray(data)
235
+ seriesState.allSeriesData.length ? seriesState.allSeriesData : chartDataArray(data)
244
236
  ) as Array<TData>;
245
237
 
246
- const seriesColors = $derived(series.map((s) => s.color).filter((d) => d != null));
247
-
248
- const highlightKey = new HighlightKey<TData, typeof Arc>();
249
- const selectedKeys = new SelectionState();
250
-
251
238
  const visibleData = $derived(
252
239
  chartData.filter((d) => {
253
240
  const dataKey = keyAccessor(d);
254
- return selectedKeys.isEmpty() || selectedKeys.isSelected(dataKey);
241
+ return seriesState.selectedKeys.isEmpty() || seriesState.selectedKeys.isSelected(dataKey);
255
242
  })
256
243
  );
257
244
 
258
245
  function getLegendProps(): ComponentProps<typeof Legend> {
259
- return {
260
- tickFormat: (tick) => {
261
- const item = chartData.find((d) => keyAccessor(d) === tick);
262
- return item ? (labelAccessor(item) ?? tick) : tick;
263
- },
264
- placement: 'bottom',
265
- variant: 'swatches',
266
- onclick: (e, item) => {
267
- selectedKeys.toggle(item.value);
268
- selectedSeries.toggle(item.value);
269
- },
270
- onpointerenter: (e, item) => (highlightKey.current = item.value),
271
- onpointerleave: (e) => (highlightKey.current = null),
272
- ...props.legend,
273
- ...(typeof legend === 'object' ? legend : null),
274
- classes: {
275
- item: (item) =>
276
- visibleData.length && !visibleData.some((d) => keyAccessor(d) === item.value)
277
- ? 'opacity-50'
278
- : '',
279
- ...props.legend?.classes,
280
- ...(typeof legend === 'object' ? legend.classes : null),
246
+ return createLegendProps({
247
+ seriesState,
248
+ props: {
249
+ tickFormat: (tick) => {
250
+ // Use data label instead of series label
251
+ const item = chartData.find((d) => keyAccessor(d) === tick);
252
+ return item ? (labelAccessor(item) ?? tick) : tick;
253
+ },
254
+ ...props.legend,
255
+ ...getObjectOrNull(legend),
281
256
  },
282
- };
257
+ });
283
258
  }
284
259
 
285
260
  function getGroupProps(): ComponentProps<typeof Group> {
@@ -317,6 +292,7 @@
317
292
  multiSeries && (trackOuterRadius ?? 0) < 0 ? i * (trackOuterRadius ?? 0) : trackOuterRadius,
318
293
  fill: s.color ?? context.cScale?.(context.c(d)),
319
294
  track: { fill: s.color ?? context.cScale?.(context.c(d)), fillOpacity: 0.1 },
295
+ opacity: seriesState.isHighlighted(keyAccessor(d), true) ? 1 : 0.1,
320
296
  tooltipContext: context.tooltip,
321
297
  data: d,
322
298
  onclick: (e) => {
@@ -326,12 +302,7 @@
326
302
  },
327
303
  ...props.arc,
328
304
  ...s.props,
329
- class: cls(
330
- 'transition-opacity',
331
- highlightKey.current && highlightKey.current !== keyAccessor(d) && 'opacity-50',
332
- props.arc?.class,
333
- s.props?.class
334
- ),
305
+ class: cls(props.arc?.class, s.props?.class),
335
306
  };
336
307
  }
337
308
 
@@ -357,7 +328,7 @@
357
328
  return key;
358
329
  },
359
330
  get visibleSeries() {
360
- return visibleSeries;
331
+ return seriesState.visibleSeries;
361
332
  },
362
333
  });
363
334
  </script>
@@ -369,19 +340,19 @@
369
340
  x={value}
370
341
  {c}
371
342
  cDomain={chartData.map(keyAccessor)}
372
- cRange={seriesColors.length
373
- ? seriesColors
343
+ cRange={seriesState.allSeriesColors.length
344
+ ? seriesState.allSeriesColors
374
345
  : c !== key
375
346
  ? chartData.map((d) => cAccessor(d))
376
347
  : [
377
- 'var(--color-primary)',
378
- 'var(--color-secondary)',
379
- 'var(--color-info)',
380
- 'var(--color-success)',
381
- 'var(--color-warning)',
382
- 'var(--color-danger)',
348
+ 'var(--color-primary, currentColor)',
349
+ 'var(--color-secondary, currentColor)',
350
+ 'var(--color-info, currentColor)',
351
+ 'var(--color-success, currentColor)',
352
+ 'var(--color-warning, currentColor)',
353
+ 'var(--color-danger, currentColor)',
383
354
  ]}
384
- padding={{ bottom: legend === true ? 32 : 0 }}
355
+ padding={{ bottom: legend ? 32 : 0 }}
385
356
  {...restProps}
386
357
  tooltip={tooltip === false
387
358
  ? false
@@ -395,10 +366,10 @@
395
366
  color: cAccessor,
396
367
  context,
397
368
  series,
398
- visibleSeries,
369
+ visibleSeries: seriesState.visibleSeries,
399
370
  visibleData,
400
- highlightKey: highlightKey.current,
401
- setHighlightKey: highlightKey.set,
371
+ highlightKey: seriesState.highlightKey.current,
372
+ setHighlightKey: seriesState.highlightKey.set,
402
373
  getLegendProps,
403
374
  getGroupProps,
404
375
  getArcProps,
@@ -452,8 +423,8 @@
452
423
  value={valueAccessor(data)}
453
424
  color={context.cScale?.(context.c(data))}
454
425
  {format}
455
- onpointerenter={() => (highlightKey.current = keyAccessor(data))}
456
- onpointerleave={() => (highlightKey.current = null)}
426
+ onpointerenter={() => (seriesState.highlightKey.current = keyAccessor(data))}
427
+ onpointerleave={() => (seriesState.highlightKey.current = null)}
457
428
  {...props.tooltip?.item}
458
429
  />
459
430
  </Tooltip.List>