layerchart 2.0.0-next.50 → 2.0.0-next.52

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 (70) hide show
  1. package/dist/components/Arc.svelte +12 -4
  2. package/dist/components/Arc.svelte.d.ts +4 -0
  3. package/dist/components/ArcLabel.svelte +259 -0
  4. package/dist/components/ArcLabel.svelte.d.ts +73 -0
  5. package/dist/components/ArcLabel.svelte.test.d.ts +1 -0
  6. package/dist/components/ArcLabel.svelte.test.js +235 -0
  7. package/dist/components/Axis.svelte +25 -0
  8. package/dist/components/Axis.svelte.d.ts +10 -0
  9. package/dist/components/Circle.svelte +82 -59
  10. package/dist/components/CircleLegend.svelte +389 -0
  11. package/dist/components/CircleLegend.svelte.d.ts +114 -0
  12. package/dist/components/Ellipse.svelte +83 -64
  13. package/dist/components/GeoLegend.svelte +404 -0
  14. package/dist/components/GeoLegend.svelte.d.ts +106 -0
  15. package/dist/components/GeoRaster.svelte +311 -0
  16. package/dist/components/GeoRaster.svelte.d.ts +61 -0
  17. package/dist/components/Grid.svelte +15 -0
  18. package/dist/components/Grid.svelte.d.ts +5 -0
  19. package/dist/components/Image.svelte +2 -2
  20. package/dist/components/Labels.svelte +46 -11
  21. package/dist/components/Labels.svelte.d.ts +7 -3
  22. package/dist/components/Legend.svelte +58 -3
  23. package/dist/components/Legend.svelte.d.ts +7 -0
  24. package/dist/components/Line.svelte +82 -62
  25. package/dist/components/Points.svelte +2 -2
  26. package/dist/components/Polygon.svelte +92 -56
  27. package/dist/components/Rect.svelte +113 -64
  28. package/dist/components/Rule.svelte +2 -0
  29. package/dist/components/Sankey.svelte +0 -2
  30. package/dist/components/Text.svelte +83 -52
  31. package/dist/components/__screenshots__/ArcLabel.svelte.test.ts/ArcLabel-defaults-placement-to-centroid--x-y-at-the-centroid--middle-anchors--1.png +0 -0
  32. package/dist/components/__screenshots__/ArcLabel.svelte.test.ts/ArcLabel-defaults-placement-to-centroid--x-y-at-the-centroid--middle-anchors--2.png +0 -0
  33. package/dist/components/charts/ArcChart.svelte +39 -2
  34. package/dist/components/charts/ArcChart.svelte.d.ts +12 -1
  35. package/dist/components/charts/PieChart.svelte +40 -2
  36. package/dist/components/charts/PieChart.svelte.d.ts +10 -0
  37. package/dist/components/index.d.ts +8 -0
  38. package/dist/components/index.js +8 -0
  39. package/dist/components/layers/Canvas.svelte +65 -48
  40. package/dist/components/layers/Canvas.svelte.d.ts +10 -0
  41. package/dist/contexts/canvas.d.ts +3 -0
  42. package/dist/server/ContextCapture.svelte +30 -0
  43. package/dist/server/ContextCapture.svelte.d.ts +8 -0
  44. package/dist/server/ServerChart.svelte +26 -0
  45. package/dist/server/ServerChart.svelte.d.ts +11 -0
  46. package/dist/server/TestBarChart.svelte +35 -0
  47. package/dist/server/TestBarChart.svelte.d.ts +14 -0
  48. package/dist/server/TestLineChart.svelte +35 -0
  49. package/dist/server/TestLineChart.svelte.d.ts +14 -0
  50. package/dist/server/captureStore.d.ts +8 -0
  51. package/dist/server/captureStore.js +18 -0
  52. package/dist/server/index.d.ts +137 -0
  53. package/dist/server/index.js +141 -0
  54. package/dist/server/renderChart.ssr.test.d.ts +1 -0
  55. package/dist/server/renderChart.ssr.test.js +205 -0
  56. package/dist/server/renderTree.d.ts +8 -0
  57. package/dist/server/renderTree.js +29 -0
  58. package/dist/states/__screenshots__/chart.svelte.test.ts/ChartState-geo-projection-skips-markInfo-should-not-derive-x-y-accessors-from-marks-when-geo-projection-is-active-1.png +0 -0
  59. package/dist/states/__screenshots__/chart.svelte.test.ts/ChartState-geo-projection-skips-markInfo-should-not-derive-x-y-accessors-from-marks-when-geo-projection-is-active-2.png +0 -0
  60. package/dist/states/chart.svelte.d.ts +5 -1
  61. package/dist/states/chart.svelte.js +18 -3
  62. package/dist/states/chart.svelte.test.js +110 -0
  63. package/dist/states/geo.svelte.d.ts +5 -1
  64. package/dist/states/geo.svelte.js +80 -68
  65. package/dist/utils/arcText.svelte.d.ts +7 -1
  66. package/dist/utils/arcText.svelte.js +8 -4
  67. package/dist/utils/canvas.js +29 -10
  68. package/dist/utils/canvas.svelte.test.js +2 -2
  69. package/dist/utils/motion.svelte.js +14 -0
  70. package/package.json +7 -1
@@ -131,13 +131,20 @@
131
131
  <script lang="ts">
132
132
  import { cls } from '@layerstack/tailwind';
133
133
  import { merge } from '@layerstack/utils';
134
+ import type { HTMLAttributes } from 'svelte/elements';
134
135
 
135
136
  import { untrack } from 'svelte';
136
137
  import { getLayerContext } from '../contexts/layer.js';
137
138
  import { getChartContext } from '../contexts/chart.js';
138
139
  import { createDataMotionMap, type MotionOptions } from '../utils/motion.svelte.js';
139
140
  import { createKey } from '../utils/key.svelte.js';
140
- import { hasAnyDataProp, resolveDataProp, resolveColorProp, resolveGeoDataPair, resolveStyleProp } from '../utils/dataProp.js';
141
+ import {
142
+ hasAnyDataProp,
143
+ resolveDataProp,
144
+ resolveColorProp,
145
+ resolveGeoDataPair,
146
+ resolveStyleProp,
147
+ } from '../utils/dataProp.js';
141
148
  import { getGeoContext } from '../contexts/geo.js';
142
149
  import { chartDataArray } from '../utils/common.js';
143
150
  import { resolveInsets } from '../utils/rect.svelte.js';
@@ -189,9 +196,7 @@
189
196
  const geo = getGeoContext();
190
197
 
191
198
  // Data to iterate over in data mode
192
- const resolvedData: any[] = $derived(
193
- dataMode ? (dataProp ?? chartDataArray(chartCtx.data)) : []
194
- );
199
+ const resolvedData: any[] = $derived(dataMode ? (dataProp ?? chartDataArray(chartCtx.data)) : []);
195
200
 
196
201
  // Resolve a single data item to rect dimensions
197
202
  function resolveRect(d: any) {
@@ -288,8 +293,8 @@
288
293
 
289
294
  const _initialX = initialX ?? (typeof x === 'number' ? x : 0);
290
295
  const _initialY = initialY ?? (typeof y === 'number' ? y : 0);
291
- const _initialWidth = initialWidth ?? (width ?? 0);
292
- const _initialHeight = initialHeight ?? (height ?? 0);
296
+ const _initialWidth = initialWidth ?? width ?? 0;
297
+ const _initialHeight = initialHeight ?? height ?? 0;
293
298
 
294
299
  // Parse motion config once, then pass resolved config to each axis
295
300
  // (avoids 4 separate parseMotionProp calls that re-parse the same prop)
@@ -316,6 +321,20 @@
316
321
 
317
322
  const layerCtx = getLayerContext();
318
323
 
324
+ const staticFill = $derived(typeof fill === 'string' ? fill : undefined);
325
+ const staticFillOpacity = $derived(typeof fillOpacity === 'number' ? fillOpacity : undefined);
326
+ const staticStroke = $derived(typeof stroke === 'string' ? stroke : undefined);
327
+ const staticStrokeOpacity = $derived(
328
+ typeof strokeOpacity === 'number' ? strokeOpacity : undefined
329
+ );
330
+ const staticStrokeWidth = $derived(typeof strokeWidth === 'number' ? strokeWidth : undefined);
331
+ const staticOpacity = $derived(typeof opacity === 'number' ? opacity : undefined);
332
+ const staticClassName = $derived(typeof className === 'string' ? className : undefined);
333
+ const staticBorderWidth = $derived(
334
+ typeof strokeWidth === 'number' ? `${strokeWidth}px` : undefined
335
+ );
336
+ const htmlRestProps = $derived(restProps as unknown as HTMLAttributes<HTMLDivElement>);
337
+
319
338
  function getStyleOptions(
320
339
  styleOverrides: ComputedStylesOptions | undefined,
321
340
  itemFill?: string | undefined,
@@ -327,17 +346,31 @@
327
346
  itemClass?: string | undefined
328
347
  ) {
329
348
  return styleOverrides
330
- ? merge({ styles: { strokeWidth: itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined) } }, styleOverrides)
349
+ ? merge(
350
+ {
351
+ styles: {
352
+ strokeWidth:
353
+ itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined),
354
+ },
355
+ },
356
+ styleOverrides
357
+ )
331
358
  : {
332
359
  styles: {
333
360
  fill: itemFill ?? fill,
334
- fillOpacity: itemFillOpacity ?? (typeof fillOpacity === 'number' ? fillOpacity : undefined),
361
+ fillOpacity:
362
+ itemFillOpacity ?? (typeof fillOpacity === 'number' ? fillOpacity : undefined),
335
363
  stroke: itemStroke ?? stroke,
336
- strokeOpacity: itemStrokeOpacity ?? (typeof strokeOpacity === 'number' ? strokeOpacity : undefined),
337
- strokeWidth: itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined),
364
+ strokeOpacity:
365
+ itemStrokeOpacity ?? (typeof strokeOpacity === 'number' ? strokeOpacity : undefined),
366
+ strokeWidth:
367
+ itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined),
338
368
  opacity: itemOpacity ?? (typeof opacity === 'number' ? opacity : undefined),
339
369
  },
340
- classes: cls('lc-rect', itemClass ?? (typeof className === 'string' ? className : undefined)),
370
+ classes: cls(
371
+ 'lc-rect',
372
+ itemClass ?? (typeof className === 'string' ? className : undefined)
373
+ ),
341
374
  style: restProps.style as string | undefined,
342
375
  };
343
376
  }
@@ -355,15 +388,28 @@
355
388
  const resolvedStrokeWidth = resolveStyleProp(strokeWidth, item.d);
356
389
  const resolvedOpacity = resolveStyleProp(opacity, item.d);
357
390
  const resolvedClass = resolveStyleProp(className, item.d);
358
- const styleOpts = getStyleOptions(styleOverrides, resolvedFill, resolvedStroke, resolvedFillOpacity, resolvedStrokeOpacity, resolvedStrokeWidth, resolvedOpacity, resolvedClass);
359
- renderRect(ctx, {
360
- x: item.x,
361
- y: item.y,
362
- width: item.width,
363
- height: item.height,
364
- rx,
365
- ry,
366
- }, styleOpts);
391
+ const styleOpts = getStyleOptions(
392
+ styleOverrides,
393
+ resolvedFill,
394
+ resolvedStroke,
395
+ resolvedFillOpacity,
396
+ resolvedStrokeOpacity,
397
+ resolvedStrokeWidth,
398
+ resolvedOpacity,
399
+ resolvedClass
400
+ );
401
+ renderRect(
402
+ ctx,
403
+ {
404
+ x: item.x,
405
+ y: item.y,
406
+ width: item.width,
407
+ height: item.height,
408
+ rx,
409
+ ry,
410
+ },
411
+ styleOpts
412
+ );
367
413
  }
368
414
  } else {
369
415
  const styleOpts = getStyleOptions(styleOverrides);
@@ -399,36 +445,39 @@
399
445
  color: typeof fill === 'string' ? fill : typeof stroke === 'string' ? stroke : undefined,
400
446
  };
401
447
  },
402
- canvasRender: layerCtx === 'canvas' ? {
403
- render,
404
- events: {
405
- click: onclick,
406
- dblclick: ondblclick,
407
- pointerenter: onpointerenter,
408
- pointermove: onpointermove,
409
- pointerleave: onpointerleave,
410
- pointerover: onpointerover,
411
- pointerout: onpointerout,
412
- },
413
- deps: () => [
414
- dataMode,
415
- dataMode ? resolvedItems : null,
416
- motionX.current,
417
- motionY.current,
418
- motionWidth.current,
419
- motionHeight.current,
420
- fillKey!.current,
421
- strokeKey!.current,
422
- fillOpacity,
423
- strokeOpacity,
424
- strokeWidth,
425
- opacity,
426
- className,
427
- restProps.style,
428
- rx,
429
- ry,
430
- ],
431
- } : undefined,
448
+ canvasRender:
449
+ layerCtx === 'canvas'
450
+ ? {
451
+ render,
452
+ events: {
453
+ click: onclick,
454
+ dblclick: ondblclick,
455
+ pointerenter: onpointerenter,
456
+ pointermove: onpointermove,
457
+ pointerleave: onpointerleave,
458
+ pointerover: onpointerover,
459
+ pointerout: onpointerout,
460
+ },
461
+ deps: () => [
462
+ dataMode,
463
+ dataMode ? resolvedItems : null,
464
+ motionX.current,
465
+ motionY.current,
466
+ motionWidth.current,
467
+ motionHeight.current,
468
+ fillKey!.current,
469
+ strokeKey!.current,
470
+ fillOpacity,
471
+ strokeOpacity,
472
+ strokeWidth,
473
+ opacity,
474
+ className,
475
+ restProps.style,
476
+ rx,
477
+ ry,
478
+ ],
479
+ }
480
+ : undefined,
432
481
  });
433
482
  </script>
434
483
 
@@ -472,15 +521,15 @@
472
521
  y={motionY.current}
473
522
  width={motionWidth.current}
474
523
  height={motionHeight.current}
475
- fill={fill as string}
476
- fill-opacity={fillOpacity as number}
477
- stroke={stroke as string}
478
- stroke-opacity={strokeOpacity as number}
479
- stroke-width={strokeWidth as number}
480
- opacity={opacity as number}
524
+ fill={staticFill}
525
+ fill-opacity={staticFillOpacity}
526
+ stroke={staticStroke}
527
+ stroke-opacity={staticStrokeOpacity}
528
+ stroke-width={staticStrokeWidth}
529
+ opacity={staticOpacity}
481
530
  {rx}
482
531
  {ry}
483
- class={cls('lc-rect', className as string)}
532
+ class={cls('lc-rect', staticClassName)}
484
533
  {...restProps}
485
534
  {onclick}
486
535
  {ondblclick}
@@ -516,7 +565,7 @@
516
565
  style:border-color={resolvedStroke}
517
566
  style:border-radius="{rx}px"
518
567
  class={cls('lc-rect', resolvedClass)}
519
- {...restProps as any}
568
+ {...htmlRestProps}
520
569
  {onclick}
521
570
  {ondblclick}
522
571
  {onpointerenter}
@@ -535,14 +584,14 @@
535
584
  style:top="{motionY.current}px"
536
585
  style:width="{motionWidth.current}px"
537
586
  style:height="{motionHeight.current}px"
538
- style:background={fill as string}
539
- style:opacity={opacity as number}
540
- style:border-width="{strokeWidth as number}px"
587
+ style:background={staticFill}
588
+ style:opacity={staticOpacity}
589
+ style:border-width={staticBorderWidth}
541
590
  style:border-style="solid"
542
- style:border-color={stroke as string}
591
+ style:border-color={staticStroke}
543
592
  style:border-radius="{rx}px"
544
- class={cls('lc-rect', className as string)}
545
- {...restProps as any}
593
+ class={cls('lc-rect', staticClassName)}
594
+ {...htmlRestProps}
546
595
  {onclick}
547
596
  {ondblclick}
548
597
  {onpointerenter}
@@ -77,6 +77,8 @@
77
77
 
78
78
  const ctx = getChartContext();
79
79
 
80
+ ctx.registerComponent({ name: 'Rule', kind: 'composite-mark' });
81
+
80
82
  const data = $derived(chartDataArray(dataProp ?? ctx.data));
81
83
 
82
84
  const singleX = $derived(
@@ -107,8 +107,6 @@
107
107
  const ctx = getChartContext();
108
108
 
109
109
  const sankeyData = $derived.by(() => {
110
- if (typeof document === 'undefined') return { nodes: [], links: [] };
111
-
112
110
  return (
113
111
  d3Sankey()
114
112
  .size([ctx.width, ctx.height])
@@ -238,7 +238,12 @@
238
238
  import { createDataMotionMap } from '../utils/motion.svelte.js';
239
239
  import { getStringWidth, truncateText, type TruncateTextOptions } from '../utils/string.js';
240
240
  import { getComputedStyles, renderText, type ComputedStylesOptions } from '../utils/canvas.js';
241
- import { resolveDataProp, resolveColorProp, resolveGeoDataPair, resolveStyleProp } from '../utils/dataProp.js';
241
+ import {
242
+ resolveDataProp,
243
+ resolveColorProp,
244
+ resolveGeoDataPair,
245
+ resolveStyleProp,
246
+ } from '../utils/dataProp.js';
242
247
  import { getGeoContext } from '../contexts/geo.js';
243
248
  import { get } from '@layerstack/utils';
244
249
  import { chartDataArray } from '../utils/common.js';
@@ -294,9 +299,7 @@
294
299
  const geo = getGeoContext();
295
300
 
296
301
  // Data to iterate over in data mode
297
- const resolvedData: any[] = $derived(
298
- dataMode ? (dataProp ?? chartDataArray(chartCtx.data)) : []
299
- );
302
+ const resolvedData: any[] = $derived(dataMode ? (dataProp ?? chartDataArray(chartCtx.data)) : []);
300
303
 
301
304
  // Resolve position for a data item
302
305
  function resolveTextPosition(d: any) {
@@ -401,7 +404,11 @@
401
404
  const motionValue = createMotion(
402
405
  typeof value === 'number' ? value : 0,
403
406
  () => (typeof value === 'number' ? value : 0),
404
- typeof value === 'number' && motion ? (typeof motion === 'object' && 'type' in motion ? motion : undefined) : undefined
407
+ typeof value === 'number' && motion
408
+ ? typeof motion === 'object' && 'type' in motion
409
+ ? motion
410
+ : undefined
411
+ : undefined
405
412
  );
406
413
 
407
414
  // Handle null and convert `\n` strings back to newline characters
@@ -549,6 +556,13 @@
549
556
  motion
550
557
  );
551
558
 
559
+ const staticFill = $derived(typeof fill === 'string' ? fill : undefined);
560
+ const staticFillOpacity = $derived(typeof fillOpacity === 'number' ? fillOpacity : undefined);
561
+ const staticStroke = $derived(typeof stroke === 'string' ? stroke : undefined);
562
+ const staticStrokeWidth = $derived(typeof strokeWidth === 'number' ? strokeWidth : undefined);
563
+ const staticOpacity = $derived(typeof opacity === 'number' ? opacity : undefined);
564
+ const staticClassName = $derived(typeof className === 'string' ? className : undefined);
565
+
552
566
  function render(
553
567
  ctx: CanvasRenderingContext2D,
554
568
  styleOverrides: ComputedStylesOptions | undefined
@@ -562,20 +576,33 @@
562
576
  itemClass?: string | undefined
563
577
  ) {
564
578
  return styleOverrides
565
- ? merge({ styles: { strokeWidth: itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined) } }, styleOverrides)
579
+ ? merge(
580
+ {
581
+ styles: {
582
+ strokeWidth:
583
+ itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined),
584
+ },
585
+ },
586
+ styleOverrides
587
+ )
566
588
  : {
567
589
  styles: {
568
590
  fill: itemFill ?? fill,
569
- fillOpacity: itemFillOpacity ?? (typeof fillOpacity === 'number' ? fillOpacity : undefined),
591
+ fillOpacity:
592
+ itemFillOpacity ?? (typeof fillOpacity === 'number' ? fillOpacity : undefined),
570
593
  stroke: itemStroke ?? stroke,
571
- strokeWidth: itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined),
594
+ strokeWidth:
595
+ itemStrokeWidth ?? (typeof strokeWidth === 'number' ? strokeWidth : undefined),
572
596
  opacity: itemOpacity ?? (typeof opacity === 'number' ? opacity : undefined),
573
597
  paintOrder: 'stroke',
574
598
  // Only include textAnchor in constantStyles when explicitly non-default,
575
599
  // so that CSS class-based text-anchor (e.g. [text-anchor:middle]) can take effect
576
600
  ...(textAnchor !== 'start' ? { textAnchor } : {}),
577
601
  },
578
- classes: cls('lc-text', itemClass ?? (typeof className === 'string' ? className : undefined)),
602
+ classes: cls(
603
+ 'lc-text',
604
+ itemClass ?? (typeof className === 'string' ? className : undefined)
605
+ ),
579
606
  style: restProps.style as string | undefined,
580
607
  };
581
608
  }
@@ -584,8 +611,7 @@
584
611
  const baseStyles = getTextStyles();
585
612
  const computedStyles = getComputedStyles(ctx.canvas, baseStyles);
586
613
  ctx.font = `${computedStyles.fontSize} ${computedStyles.fontFamily}`;
587
- const textAlign =
588
- textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'end' : 'start';
614
+ const textAlign = textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'end' : 'start';
589
615
  ctx.textAlign = textAlign;
590
616
 
591
617
  for (const item of resolvedItems) {
@@ -596,7 +622,14 @@
596
622
  const resolvedStrokeWidth = resolveStyleProp(strokeWidth, item.d);
597
623
  const resolvedOpacity = resolveStyleProp(opacity, item.d);
598
624
  const resolvedClass = resolveStyleProp(className, item.d);
599
- const itemStyles = getTextStyles(resolvedFill, resolvedStroke, resolvedFillOpacity, resolvedStrokeWidth, resolvedOpacity, resolvedClass);
625
+ const itemStyles = getTextStyles(
626
+ resolvedFill,
627
+ resolvedStroke,
628
+ resolvedFillOpacity,
629
+ resolvedStrokeWidth,
630
+ resolvedOpacity,
631
+ resolvedClass
632
+ );
600
633
  ctx.save();
601
634
  if (rotate !== undefined) {
602
635
  const radians = degreesToRadians(rotate);
@@ -634,8 +667,7 @@
634
667
 
635
668
  ctx.font = `${computedStyles.fontSize} ${computedStyles.fontFamily}`;
636
669
 
637
- const textAlign =
638
- textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'end' : 'start';
670
+ const textAlign = textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'end' : 'start';
639
671
  ctx.textAlign = textAlign;
640
672
 
641
673
  for (let index = 0; index < wordsByLines.length; index++) {
@@ -668,26 +700,29 @@
668
700
  color: typeof fill === 'string' ? fill : undefined,
669
701
  };
670
702
  },
671
- canvasRender: layerCtx === 'canvas' ? {
672
- render,
673
- deps: () => [
674
- dataMode,
675
- dataMode ? resolvedItems : null,
676
- value,
677
- motionX.current,
678
- motionY.current,
679
- fillKey!.current,
680
- strokeKey!.current,
681
- strokeWidth,
682
- opacity,
683
- className,
684
- truncateConfig,
685
- rotate,
686
- lineHeight,
687
- textAnchor,
688
- verticalAnchor,
689
- ],
690
- } : undefined,
703
+ canvasRender:
704
+ layerCtx === 'canvas'
705
+ ? {
706
+ render,
707
+ deps: () => [
708
+ dataMode,
709
+ dataMode ? resolvedItems : null,
710
+ value,
711
+ motionX.current,
712
+ motionY.current,
713
+ fillKey!.current,
714
+ strokeKey!.current,
715
+ strokeWidth,
716
+ opacity,
717
+ className,
718
+ truncateConfig,
719
+ rotate,
720
+ lineHeight,
721
+ textAnchor,
722
+ verticalAnchor,
723
+ ],
724
+ }
725
+ : undefined,
691
726
  });
692
727
  </script>
693
728
 
@@ -717,11 +752,7 @@
717
752
  opacity={resolvedOpacity}
718
753
  class={['lc-text', resolvedClass]}
719
754
  >
720
- <tspan
721
- x={item.x}
722
- dy={dataModeStartDy}
723
- class="lc-text-tspan"
724
- >
755
+ <tspan x={item.x} dy={dataModeStartDy} class="lc-text-tspan">
725
756
  {text}
726
757
  </tspan>
727
758
  </text>
@@ -741,13 +772,13 @@
741
772
  bind:this={ref}
742
773
  {dy}
743
774
  {...restProps}
744
- fill={fill as string}
745
- fill-opacity={fillOpacity as number}
746
- stroke={stroke as string}
747
- stroke-width={strokeWidth as number}
748
- opacity={opacity as number}
775
+ fill={staticFill}
776
+ fill-opacity={staticFillOpacity}
777
+ stroke={staticStroke}
778
+ stroke-width={staticStrokeWidth}
779
+ opacity={staticOpacity}
749
780
  transform={transformProp}
750
- class={['lc-text', className as string]}
781
+ class={['lc-text', staticClassName]}
751
782
  >
752
783
  <textPath
753
784
  style="text-anchor: {textAnchor};"
@@ -768,12 +799,12 @@
768
799
  text-anchor={textAnchor}
769
800
  dominant-baseline={dominantBaseline}
770
801
  {...restProps}
771
- fill={fill as string}
772
- fill-opacity={fillOpacity as number}
773
- stroke={stroke as string}
774
- stroke-width={strokeWidth as number}
775
- opacity={opacity as number}
776
- class={['lc-text', className as string]}
802
+ fill={staticFill}
803
+ fill-opacity={staticFillOpacity}
804
+ stroke={staticStroke}
805
+ stroke-width={staticStrokeWidth}
806
+ opacity={staticOpacity}
807
+ class={['lc-text', staticClassName]}
777
808
  >
778
809
  {#each wordsByLines as line, index}
779
810
  <tspan
@@ -831,7 +862,7 @@
831
862
  {textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'right' : 'left'}"
832
863
  style:white-space="pre-wrap"
833
864
  style:line-height={lineHeight}
834
- class={['lc-text', className as string]}
865
+ class={['lc-text', staticClassName]}
835
866
  >
836
867
  {textValue}
837
868
  </div>
@@ -7,6 +7,7 @@
7
7
  import type { SeriesData } from './types.js';
8
8
 
9
9
  import Arc from '../Arc.svelte';
10
+ import ArcLabel, { type ArcLabelConfig } from '../ArcLabel.svelte';
10
11
  import Group from '../Group.svelte';
11
12
 
12
13
  export type ArcChartExtraSnippetProps<TData> = {
@@ -28,8 +29,15 @@
28
29
  ChartProps<any>,
29
30
  // Props that don't apply to ArcChart
30
31
  'data' | 'axis' | 'brush' | 'grid' | 'highlight' | 'labels' | 'points' | 'rule'
31
- > &
32
- Pick<
32
+ > & {
33
+ /**
34
+ * Render text labels on each arc.
35
+ *
36
+ * Pass `true` to enable with default placement (`centroid`), or an object
37
+ * to customize via `ArcLabel` props (placement, format, value accessor, etc).
38
+ */
39
+ labels?: boolean | (ArcLabelConfig & { value?: Accessor });
40
+ } & Pick<
33
41
  ArcPropsWithoutHTML,
34
42
  | 'cornerRadius'
35
43
  | 'trackCornerRadius'
@@ -163,6 +171,7 @@
163
171
  marks,
164
172
  tooltip: tooltipProp,
165
173
  arc,
174
+ labels = false,
166
175
  context = $bindable(),
167
176
  trackCornerRadius,
168
177
  trackPadAngle,
@@ -175,6 +184,10 @@
175
184
 
176
185
  const center = $derived(centerProp ?? placement === 'center');
177
186
 
187
+ const labelsConfig = $derived(
188
+ labels === true ? ({} as ArcLabelConfig & { value?: Accessor }) : labels || null
189
+ );
190
+
178
191
  const c = $derived(cProp ?? key);
179
192
 
180
193
  const keyAccessor = $derived(accessor(key));
@@ -359,6 +372,30 @@
359
372
  seriesIndex: i,
360
373
  props: getArcProps(s, i),
361
374
  })}
375
+ {:else if labelsConfig}
376
+ {@const arcProps = getArcProps(s, i)}
377
+ <Arc {...arcProps}>
378
+ {#snippet children({
379
+ centroid,
380
+ startAngle,
381
+ endAngle,
382
+ innerRadius: arcInnerRadius,
383
+ outerRadius: arcOuterRadius,
384
+ getArcTextProps,
385
+ })}
386
+ {@const { value: labelValue, ...labelRest } = labelsConfig}
387
+ <ArcLabel
388
+ {centroid}
389
+ {startAngle}
390
+ {endAngle}
391
+ innerRadius={arcInnerRadius}
392
+ outerRadius={arcOuterRadius}
393
+ {getArcTextProps}
394
+ value={accessor(labelValue ?? value)(s.data?.[0] || chartData[0])}
395
+ {...labelRest}
396
+ />
397
+ {/snippet}
398
+ </Arc>
362
399
  {:else}
363
400
  <Arc {...getArcProps(s, i)} />
364
401
  {/if}
@@ -5,6 +5,7 @@ import type { ArcPropsWithoutHTML } from '../Arc.svelte';
5
5
  import type { Accessor } from '../../utils/common.js';
6
6
  import type { SeriesData } from './types.js';
7
7
  import Arc from '../Arc.svelte';
8
+ import { type ArcLabelConfig } from '../ArcLabel.svelte';
8
9
  import Group from '../Group.svelte';
9
10
  export type ArcChartExtraSnippetProps<TData> = {
10
11
  key: Accessor<TData>;
@@ -19,7 +20,17 @@ export type ArcChartProps<TData> = {
19
20
  * The data for the chart
20
21
  */
21
22
  data?: TData[] | readonly TData[];
22
- } & Omit<ChartProps<any>, 'data' | 'axis' | 'brush' | 'grid' | 'highlight' | 'labels' | 'points' | 'rule'> & Pick<ArcPropsWithoutHTML, 'cornerRadius' | 'trackCornerRadius' | 'padAngle' | 'trackPadAngle' | 'trackStartAngle' | 'trackEndAngle' | 'trackInnerRadius' | 'trackOuterRadius' | 'innerRadius' | 'outerRadius' | 'range'> & {
23
+ } & Omit<ChartProps<any>, 'data' | 'axis' | 'brush' | 'grid' | 'highlight' | 'labels' | 'points' | 'rule'> & {
24
+ /**
25
+ * Render text labels on each arc.
26
+ *
27
+ * Pass `true` to enable with default placement (`centroid`), or an object
28
+ * to customize via `ArcLabel` props (placement, format, value accessor, etc).
29
+ */
30
+ labels?: boolean | (ArcLabelConfig & {
31
+ value?: Accessor;
32
+ });
33
+ } & Pick<ArcPropsWithoutHTML, 'cornerRadius' | 'trackCornerRadius' | 'padAngle' | 'trackPadAngle' | 'trackStartAngle' | 'trackEndAngle' | 'trackInnerRadius' | 'trackOuterRadius' | 'innerRadius' | 'outerRadius' | 'range'> & {
23
34
  /**
24
35
  * The series data to be used for the chart.
25
36
  */