From 5823f74f81cb8e23827924592979bb652f78d0f7 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 11 Jun 2025 15:02:17 -0400 Subject: [PATCH 01/77] Experiment supporting `` as html `
` (need to fix types and further validate) --- .../layerchart/src/lib/components/Rect.svelte | 22 +++++++++++++++++++ .../routes/docs/components/Calendar/+page.ts | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/layerchart/src/lib/components/Rect.svelte b/packages/layerchart/src/lib/components/Rect.svelte index 3615d76ea..77934d0ee 100644 --- a/packages/layerchart/src/lib/components/Rect.svelte +++ b/packages/layerchart/src/lib/components/Rect.svelte @@ -166,4 +166,26 @@ {onpointerout} bind:this={ref} /> +{:else if renderCtx === 'html'} +
{/if} diff --git a/packages/layerchart/src/routes/docs/components/Calendar/+page.ts b/packages/layerchart/src/routes/docs/components/Calendar/+page.ts index 01ed3d2b5..9e9acd485 100644 --- a/packages/layerchart/src/routes/docs/components/Calendar/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Calendar/+page.ts @@ -8,7 +8,7 @@ export async function load() { api, source, pageSource, - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], }, }; } From 4d5f1c981b85191da56bd92515829086572d4ab8 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 11 Jun 2025 23:24:38 -0400 Subject: [PATCH 02/77] feat: Add `pointsToAngleAndLength()` math util --- packages/layerchart/src/lib/utils/math.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/layerchart/src/lib/utils/math.ts b/packages/layerchart/src/lib/utils/math.ts index 6babcac62..9e48effac 100644 --- a/packages/layerchart/src/lib/utils/math.ts +++ b/packages/layerchart/src/lib/utils/math.ts @@ -44,6 +44,29 @@ export function cartesianToPolar(x: number, y: number) { }; } +/** + * Calculate the angle and length between two points + * @param point1 - First point + * @param point2 - Second point + * @returns Angle in degrees and length + */ +export function pointsToAngleAndLength( + point1: { x: number; y: number }, + point2: { x: number; y: number } +) { + const dx = point2.x - point1.x; + const dy = point2.y - point1.y; + + const radians = Math.atan2(dy, dx); + const length = Math.sqrt(dx * dx + dy * dy); + + return { + radians, + angle: radiansToDegrees(radians), + length, + }; +} + /** Convert celsius temperature to fahrenheit */ export function celsiusToFahrenheit(temperature: number) { return temperature * (9 / 5) + 32; From a3ae56fe82fceb2edc8233c84babfc1a56f04ea9 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 11 Jun 2025 23:25:33 -0400 Subject: [PATCH 03/77] fix(Rect): Support border radius for html --- packages/layerchart/src/lib/components/Rect.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/layerchart/src/lib/components/Rect.svelte b/packages/layerchart/src/lib/components/Rect.svelte index 77934d0ee..e8833410d 100644 --- a/packages/layerchart/src/lib/components/Rect.svelte +++ b/packages/layerchart/src/lib/components/Rect.svelte @@ -178,6 +178,7 @@ style:border-width="{strokeWidth}px" style:border-style="solid" style:border-color={stroke} + style:border-radius="{restProps.rx}px" class={cls(layerClass('rect'), fill == null && 'fill-surface-content', className)} {...restProps} {onclick} From 748795ee4c312e37b4f00c44a0106173fa16989b Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 11 Jun 2025 23:27:32 -0400 Subject: [PATCH 04/77] feat(Text): Initial support for Html context --- .../layerchart/src/lib/components/Text.svelte | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/layerchart/src/lib/components/Text.svelte b/packages/layerchart/src/lib/components/Text.svelte index 4a87c76ee..b4f34bb90 100644 --- a/packages/layerchart/src/lib/components/Text.svelte +++ b/packages/layerchart/src/lib/components/Text.svelte @@ -546,4 +546,19 @@ {/if} +{:else if renderCtx === 'html'} + {@const translateX = textAnchor === 'middle' ? '-50%' : textAnchor === 'end' ? '-100%' : '0%'} + {@const translateY = + verticalAnchor === 'middle' ? '-50%' : verticalAnchor === 'end' ? '-100%' : '0%'} + + +
+ {textValue} +
{/if} From 464d312b1bdf1b53ceb1d6c7d7ff769ec1095a8a Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 11 Jun 2025 23:27:49 -0400 Subject: [PATCH 05/77] feat(Line): Initial support for Html context --- .../layerchart/src/lib/components/Line.svelte | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/layerchart/src/lib/components/Line.svelte b/packages/layerchart/src/lib/components/Line.svelte index 57bf344b2..ac383f4da 100644 --- a/packages/layerchart/src/lib/components/Line.svelte +++ b/packages/layerchart/src/lib/components/Line.svelte @@ -4,6 +4,7 @@ import { renderPathData, type ComputedStylesOptions } from '$lib/utils/canvas.js'; import MarkerWrapper, { type MarkerOptions } from './MarkerWrapper.svelte'; import type { CommonStyleProps, Without } from '$lib/utils/types.js'; + import { pointsToAngleAndLength } from '$lib/utils/math.js'; export type LinePropsWithoutHTML = { /** @@ -201,4 +202,21 @@ +{:else if renderCtx === 'html'} + {@const { angle, length } = pointsToAngleAndLength( + { x: motionX1.current, y: motionY1.current }, + { x: motionX2.current, y: motionY2.current } + )} +
{/if} From ffc022b67d57c928281532cad867708457e60445 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 11 Jun 2025 23:28:04 -0400 Subject: [PATCH 06/77] More html context experimenting --- packages/layerchart/src/lib/components/Axis.svelte | 2 +- packages/layerchart/src/lib/components/Calendar.svelte | 6 +++++- .../layerchart/src/routes/docs/components/Axis/+page.ts | 2 +- .../layerchart/src/routes/docs/components/Grid/+page.ts | 2 +- .../layerchart/src/routes/docs/components/Line/+page.svelte | 6 +++++- .../layerchart/src/routes/docs/components/Line/+page.ts | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/layerchart/src/lib/components/Axis.svelte b/packages/layerchart/src/lib/components/Axis.svelte index 586c17b4a..8057b9de3 100644 --- a/packages/layerchart/src/lib/components/Axis.svelte +++ b/packages/layerchart/src/lib/components/Axis.svelte @@ -384,7 +384,7 @@ y={placement === 'top' || placement === 'bottom' ? placement : placement === 'radius'} {motion} {...ruleProps} - class={cls('stroke-surface-content/50', classes.rule, ruleProps?.class)} + class={cls('stroke-surface-content/50 bg-surface-content/50', classes.rule, ruleProps?.class)} /> {/if} diff --git a/packages/layerchart/src/lib/components/Calendar.svelte b/packages/layerchart/src/lib/components/Calendar.svelte index f67e127f2..c0caf1f31 100644 --- a/packages/layerchart/src/lib/components/Calendar.svelte +++ b/packages/layerchart/src/lib/components/Calendar.svelte @@ -128,7 +128,11 @@ fill={cell.color} onpointermove={(e) => tooltip?.show(e, cell.data)} onpointerleave={(e) => tooltip?.hide()} - {...extractLayerProps(restProps, 'calendar-cell', 'stroke-surface-content/5')} + {...extractLayerProps( + restProps, + 'calendar-cell', + 'stroke-surface-content/5 border border-surface-content/5' + )} /> {/each} {/if} diff --git a/packages/layerchart/src/routes/docs/components/Axis/+page.ts b/packages/layerchart/src/routes/docs/components/Axis/+page.ts index 8fd71a8d7..fd09df389 100644 --- a/packages/layerchart/src/routes/docs/components/Axis/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Axis/+page.ts @@ -8,7 +8,7 @@ export async function load() { api, source, pageSource, - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], related: ['components/Grid', 'components/Rule'], }, }; diff --git a/packages/layerchart/src/routes/docs/components/Grid/+page.ts b/packages/layerchart/src/routes/docs/components/Grid/+page.ts index e53cc6063..77c540900 100644 --- a/packages/layerchart/src/routes/docs/components/Grid/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Grid/+page.ts @@ -8,7 +8,7 @@ export async function load() { api, source, pageSource, - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], related: ['components/Axis', 'components/Rule'], }, }; diff --git a/packages/layerchart/src/routes/docs/components/Line/+page.svelte b/packages/layerchart/src/routes/docs/components/Line/+page.svelte index 8b1cf2ab0..a0c0ccc72 100644 --- a/packages/layerchart/src/routes/docs/components/Line/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/Line/+page.svelte @@ -9,7 +9,11 @@
- + diff --git a/packages/layerchart/src/routes/docs/components/Line/+page.ts b/packages/layerchart/src/routes/docs/components/Line/+page.ts index 3df4dca88..61c7b05a6 100644 --- a/packages/layerchart/src/routes/docs/components/Line/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Line/+page.ts @@ -9,7 +9,7 @@ export async function load() { source, pageSource, description: '`` element with tweened properties using `motionStore`', - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], related: ['components/Rule', 'components/Spline'], }, }; From 484f5df9959eea4bd647db220f4cc25533a84d35 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 24 Jun 2025 12:12:12 -0400 Subject: [PATCH 07/77] docs(Calendar): Fix canvas clipping --- .../src/routes/docs/components/Calendar/+page.svelte | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/layerchart/src/routes/docs/components/Calendar/+page.svelte b/packages/layerchart/src/routes/docs/components/Calendar/+page.svelte index 1a2d3b665..b62e08be2 100644 --- a/packages/layerchart/src/routes/docs/components/Calendar/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/Calendar/+page.svelte @@ -42,7 +42,7 @@ 'var(--color-primary-500)', 'var(--color-primary-700)', ]} - padding={{ top: 13 }} + padding={{ top: 20 }} > {#snippet children({ context })} @@ -91,7 +91,7 @@ 'var(--color-primary-500)', 'var(--color-primary-700)', ]} - padding={{ top: 13 }} + padding={{ top: 20 }} > {#snippet children({ context })} @@ -141,7 +141,7 @@ 'var(--color-primary-500)', 'var(--color-primary-700)', ]} - padding={{ left: 20, top: 13 }} + padding={{ top: 20, left: 20 }} > {#snippet children({ context })} @@ -200,7 +200,7 @@ 'var(--color-primary-500)', 'var(--color-primary-700)', ]} - padding={{ top: 13 }} + padding={{ top: 20 }} > {#snippet children({ context })} @@ -260,7 +260,7 @@ 'var(--color-primary-500)', 'var(--color-primary-700)', ]} - padding={{ top: 13 }} + padding={{ top: 20 }} > {#snippet children({ context })} From d7590b29fd164a64a1e1fd9d2b9cad451b085827 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 24 Jun 2025 12:12:27 -0400 Subject: [PATCH 08/77] feat(Circle): Add html support --- .../layerchart/src/lib/components/Circle.svelte | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/layerchart/src/lib/components/Circle.svelte b/packages/layerchart/src/lib/components/Circle.svelte index 6955c549e..62c05a540 100644 --- a/packages/layerchart/src/lib/components/Circle.svelte +++ b/packages/layerchart/src/lib/components/Circle.svelte @@ -164,4 +164,21 @@ class={cls(layerClass('circle'), fill == null && 'fill-surface-content', className)} {...restProps} /> +{:else if renderCtx === 'html'} +
{/if} From cc06e8eb1a77a1c71a4996b1d4513cfa6b84a0af Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 24 Jun 2025 12:24:09 -0400 Subject: [PATCH 09/77] Document more examples with html support (at least partial) --- .../src/lib/components/Group.svelte | 2 +- .../docs/components/Calendar/+page.svelte | 2 +- .../routes/docs/components/Circle/+page.ts | 2 +- .../src/routes/docs/components/Group/+page.ts | 1 + .../src/routes/docs/components/Point/+page.ts | 2 +- .../src/routes/docs/components/Rect/+page.ts | 2 +- .../routes/docs/components/Text/+page.svelte | 56 +++++++------------ .../src/routes/docs/components/Text/+page.ts | 2 +- 8 files changed, 27 insertions(+), 42 deletions(-) diff --git a/packages/layerchart/src/lib/components/Group.svelte b/packages/layerchart/src/lib/components/Group.svelte index 8d756fd7f..86d770fc9 100644 --- a/packages/layerchart/src/lib/components/Group.svelte +++ b/packages/layerchart/src/lib/components/Group.svelte @@ -187,7 +187,7 @@ > {@render children?.()} -{:else} +{:else if renderCtx === 'html'}
-

Html

+

Html with padding

diff --git a/packages/layerchart/src/routes/docs/components/Circle/+page.ts b/packages/layerchart/src/routes/docs/components/Circle/+page.ts index 962be1ab9..fb388cf28 100644 --- a/packages/layerchart/src/routes/docs/components/Circle/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Circle/+page.ts @@ -9,7 +9,7 @@ export async function load() { source, pageSource, description: '`` element with tweened properties using `motionStore`', - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], related: ['components/Points', 'examples/Pack', 'examples/PunchCard'], }, }; diff --git a/packages/layerchart/src/routes/docs/components/Group/+page.ts b/packages/layerchart/src/routes/docs/components/Group/+page.ts index 7a9a7c36f..8d92f4904 100644 --- a/packages/layerchart/src/routes/docs/components/Group/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Group/+page.ts @@ -13,6 +13,7 @@ export async function load() { supportedContexts: [ 'svg', // 'canvas' // TODO: Supported, but limited use cases + 'html', ], related: [ 'examples/Pack', diff --git a/packages/layerchart/src/routes/docs/components/Point/+page.ts b/packages/layerchart/src/routes/docs/components/Point/+page.ts index 88b528d40..c99343062 100644 --- a/packages/layerchart/src/routes/docs/components/Point/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Point/+page.ts @@ -9,7 +9,7 @@ export async function load() { source, pageSource, description: 'Convenient way to translate a data item to SVG x/y coordinates', - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], related: ['examples/Area'], }, }; diff --git a/packages/layerchart/src/routes/docs/components/Rect/+page.ts b/packages/layerchart/src/routes/docs/components/Rect/+page.ts index 48fe70a36..643927949 100644 --- a/packages/layerchart/src/routes/docs/components/Rect/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Rect/+page.ts @@ -9,7 +9,7 @@ export async function load() { source, pageSource, description: '`` element with tweened properties using `motionStore`', - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], related: [ 'components/Bars', 'components/Highlight', diff --git a/packages/layerchart/src/routes/docs/components/Text/+page.svelte b/packages/layerchart/src/routes/docs/components/Text/+page.svelte index 811600335..98152daef 100644 --- a/packages/layerchart/src/routes/docs/components/Text/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/Text/+page.svelte @@ -5,6 +5,7 @@ import { Field, RangeField, Switch, TextField, ToggleGroup, ToggleOption } from 'svelte-ux'; import Preview from 'layerchart/docs/Preview.svelte'; import { shared } from '../../shared.svelte.js'; + import { toTitleCase } from '@layerstack/utils'; const config = $state({ x: 0, @@ -105,44 +106,27 @@
-
-
-

SVG

-
-
- - - - {#if config.showAnchor} - - {/if} - - -
-
-
- -
-

Canvas

-
-
- - - - {#if config.showAnchor} - - {/if} - - +
+ {#each ['svg', 'canvas', 'html'] as const as type} +
+

{toTitleCase(type)}

+
+
+ + + + {#if config.showAnchor} + + {/if} + + +
-
+ {/each}

Examples

diff --git a/packages/layerchart/src/routes/docs/components/Text/+page.ts b/packages/layerchart/src/routes/docs/components/Text/+page.ts index 4a31bc978..875f03bb0 100644 --- a/packages/layerchart/src/routes/docs/components/Text/+page.ts +++ b/packages/layerchart/src/routes/docs/components/Text/+page.ts @@ -8,7 +8,7 @@ export async function load() { api, source, pageSource, - supportedContexts: ['svg', 'canvas'], + supportedContexts: ['svg', 'canvas', 'html'], features: [ 'Adjustable anchor/origin point (center horizontally and vertically)', 'Rotate (based on origin)', From 1061545c6263a893a6889c3e3a85754ec739559b Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 24 Jun 2025 12:28:31 -0400 Subject: [PATCH 10/77] fix(Text): Support rotate with html context --- packages/layerchart/src/lib/components/Text.svelte | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/layerchart/src/lib/components/Text.svelte b/packages/layerchart/src/lib/components/Text.svelte index 0d11e28e2..cdaad9438 100644 --- a/packages/layerchart/src/lib/components/Text.svelte +++ b/packages/layerchart/src/lib/components/Text.svelte @@ -546,7 +546,13 @@ style:position="absolute" style:left="{dx + motionX.current}px" style:top="{dy + motionY.current}px" - style:transform="translate({translateX}, {translateY})" + style:transform="translate({translateX}, {translateY}) rotate({rotate}deg)" + style:transform-origin="{verticalAnchor === 'middle' + ? 'center' + : verticalAnchor === 'end' + ? 'bottom' + : 'top'} + {textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'right' : 'left'}" class={cls(layerClass('text'), fill === undefined && 'text-surface-content', className)} > {textValue} From 73941aa7dd42ac92fc50eab3e94b433cf415cf50 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 24 Jun 2025 12:34:18 -0400 Subject: [PATCH 11/77] fix(Text): Coalesce rotate to `0` deg --- packages/layerchart/src/lib/components/Text.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/layerchart/src/lib/components/Text.svelte b/packages/layerchart/src/lib/components/Text.svelte index cdaad9438..a21654bad 100644 --- a/packages/layerchart/src/lib/components/Text.svelte +++ b/packages/layerchart/src/lib/components/Text.svelte @@ -546,7 +546,7 @@ style:position="absolute" style:left="{dx + motionX.current}px" style:top="{dy + motionY.current}px" - style:transform="translate({translateX}, {translateY}) rotate({rotate}deg)" + style:transform="translate({translateX}, {translateY}) rotate({rotate ?? 0}deg)" style:transform-origin="{verticalAnchor === 'middle' ? 'center' : verticalAnchor === 'end' From 9ad23ef56f1812f89c63d4b88fbe7bceb3f0c6b3 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 24 Jun 2025 16:48:35 -0400 Subject: [PATCH 12/77] fix(Calendar): Align label Text when using Html with other contexts --- packages/layerchart/src/lib/components/Calendar.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/layerchart/src/lib/components/Calendar.svelte b/packages/layerchart/src/lib/components/Calendar.svelte index c0caf1f31..aed85aaee 100644 --- a/packages/layerchart/src/lib/components/Calendar.svelte +++ b/packages/layerchart/src/lib/components/Calendar.svelte @@ -147,8 +147,8 @@ {#each yearMonths as date} {/each} From de4e495855ab891466b39db7f5de19c7df9e6df2 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Sun, 17 Aug 2025 10:26:14 -0400 Subject: [PATCH 13/77] Add `CommonEvents` type to support Svg/Html contexts and make svelte-check happy --- .../layerchart/src/lib/components/Bar.svelte | 5 +++-- .../layerchart/src/lib/components/Rect.svelte | 11 +++++++---- .../src/lib/components/RectClipPath.svelte | 5 +++-- packages/layerchart/src/lib/utils/types.ts | 19 +++++++++++++++++-- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/packages/layerchart/src/lib/components/Bar.svelte b/packages/layerchart/src/lib/components/Bar.svelte index 1462d328c..8e0986e7a 100644 --- a/packages/layerchart/src/lib/components/Bar.svelte +++ b/packages/layerchart/src/lib/components/Bar.svelte @@ -71,7 +71,8 @@ Without< Omit, 'width' | 'height' | 'x' | 'y' | 'offset'>, BarPropsWithoutHTML - >; + > & + CommonEvents; - + {#if children} {@render children()} {:else} diff --git a/packages/layerchart/src/lib/components/Blur.svelte b/packages/layerchart/src/lib/components/Blur.svelte index fd76b7f31..d7485adb4 100644 --- a/packages/layerchart/src/lib/components/Blur.svelte +++ b/packages/layerchart/src/lib/components/Blur.svelte @@ -24,7 +24,6 @@ import type { Snippet } from 'svelte'; import { getRenderContext } from './Chart.svelte'; import { createId } from '$lib/utils/createId.js'; - import { layerClass } from '$lib/utils/attributes.js'; const uid = $props.id(); @@ -35,13 +34,13 @@ {#if renderContext === 'svg'} - + {#if children} - + {@render children()} {/if} diff --git a/packages/layerchart/src/lib/components/BrushContext.svelte b/packages/layerchart/src/lib/components/BrushContext.svelte index b31e2404c..b307ed1ff 100644 --- a/packages/layerchart/src/lib/components/BrushContext.svelte +++ b/packages/layerchart/src/lib/components/BrushContext.svelte @@ -148,7 +148,6 @@ import type { HTMLAttributes } from 'svelte/elements'; import { getChartContext } from './Chart.svelte'; import type { Snippet } from 'svelte'; - import { layerClass } from '$lib/utils/attributes.js'; const ctx = getChartContext(); @@ -463,7 +462,7 @@ {#if disabled} {@render children?.({ brushContext })} {:else} - {@const handleClass = layerClass('brush-handle')} + {@const handleClass = 'lc-brush-handle'}
selectAll()} >
{#key isMounted} diff --git a/packages/layerchart/src/lib/components/Circle.svelte b/packages/layerchart/src/lib/components/Circle.svelte index 339ae37c5..5fc39965d 100644 --- a/packages/layerchart/src/lib/components/Circle.svelte +++ b/packages/layerchart/src/lib/components/Circle.svelte @@ -68,7 +68,6 @@ import { renderCircle, type ComputedStylesOptions } from '$lib/utils/canvas.js'; import type { SVGAttributes } from 'svelte/elements'; import { createKey } from '$lib/utils/key.svelte.js'; - import { layerClass } from '$lib/utils/attributes.js'; let { cx = 0, @@ -115,7 +114,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, fillOpacity, stroke, strokeWidth, opacity }, - classes: cls(layerClass('circle'), fill == null && 'fill-surface-content', className), + classes: cls('lc-circle', fill == null && 'fill-surface-content', className), } ); } @@ -161,7 +160,7 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls(layerClass('circle'), fill == null && 'fill-surface-content', className)} + class={cls('lc-circle', fill == null && 'fill-surface-content', className)} {...restProps} /> {:else if renderCtx === 'html'} @@ -178,7 +177,7 @@ style:border-color={stroke} style:border-style="solid" style:transform="translate(-50%, -50%)" - class={cls(layerClass('circle'), fill == null && 'bg-surface-content', className)} + class={cls('lc-circle', fill == null && 'bg-surface-content', className)} {...restProps} >
{/if} diff --git a/packages/layerchart/src/lib/components/ClipPath.svelte b/packages/layerchart/src/lib/components/ClipPath.svelte index 64dc9e026..bd19a6891 100644 --- a/packages/layerchart/src/lib/components/ClipPath.svelte +++ b/packages/layerchart/src/lib/components/ClipPath.svelte @@ -1,7 +1,6 @@
(styles = _styles)} >
diff --git a/packages/layerchart/src/lib/components/Ellipse.svelte b/packages/layerchart/src/lib/components/Ellipse.svelte index bafb60167..707e4668d 100644 --- a/packages/layerchart/src/lib/components/Ellipse.svelte +++ b/packages/layerchart/src/lib/components/Ellipse.svelte @@ -82,7 +82,6 @@ import { renderEllipse, type ComputedStylesOptions } from '$lib/utils/canvas.js'; import type { SVGAttributes } from 'svelte/elements'; import { createKey } from '$lib/utils/key.svelte.js'; - import { layerClass } from '$lib/utils/attributes.js'; let { cx = 0, @@ -133,7 +132,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, fillOpacity, stroke, strokeWidth, opacity }, - classes: cls(layerClass('ellipse'), fill == null && 'fill-surface-content', className), + classes: cls('lc-ellipse', fill == null && 'fill-surface-content', className), } ); } @@ -181,7 +180,7 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls(layerClass('ellipse'), fill == null && 'fill-surface-content', className)} + class={cls('lc-ellipse', fill == null && 'fill-surface-content', className)} {...restProps} /> {:else if renderCtx === 'html'} @@ -198,7 +197,7 @@ style:border-color={stroke} style:border-style="solid" style:transform="translate(-50%, -50%)" - class={cls(layerClass('ellipse'), fill == null && 'bg-surface-content', className)} + class={cls('lc-ellipse', fill == null && 'bg-surface-content', className)} {...restProps} >
{/if} diff --git a/packages/layerchart/src/lib/components/GeoPath.svelte b/packages/layerchart/src/lib/components/GeoPath.svelte index 11003b66f..63d41edab 100644 --- a/packages/layerchart/src/lib/components/GeoPath.svelte +++ b/packages/layerchart/src/lib/components/GeoPath.svelte @@ -74,7 +74,6 @@ import { geoCurvePath } from '$lib/utils/geo.js'; import { getGeoContext } from './GeoContext.svelte'; import { createKey } from '$lib/utils/key.svelte.js'; - import { layerClass } from '$lib/utils/attributes.js'; let { fill, @@ -199,6 +198,6 @@ onpointerenter={_onPointerEnter} onpointermove={_onPointerMove} onpointerleave={_onPointerLeave} - class={cls(layerClass('geo-path'), fill == null && 'fill-transparent', className)} + class={cls('lc-geo-path', fill == null && 'fill-transparent', className)} /> {/if} diff --git a/packages/layerchart/src/lib/components/Graticule.svelte b/packages/layerchart/src/lib/components/Graticule.svelte index 67f587925..15ebbb493 100644 --- a/packages/layerchart/src/lib/components/Graticule.svelte +++ b/packages/layerchart/src/lib/components/Graticule.svelte @@ -15,7 +15,7 @@ - + {#if !lines && !outline} diff --git a/packages/layerchart/src/lib/components/Grid.svelte b/packages/layerchart/src/lib/components/Grid.svelte index 5445d8e17..2206b697b 100644 --- a/packages/layerchart/src/lib/components/Grid.svelte +++ b/packages/layerchart/src/lib/components/Grid.svelte @@ -98,7 +98,7 @@ import Rule from './Rule.svelte'; import Spline from './Spline.svelte'; import { getChartContext } from './Chart.svelte'; - import { extractLayerProps, layerClass } from '$lib/utils/attributes.js'; + import { extractLayerProps } from '$lib/utils/attributes.js'; import { autoTickVals, type TicksConfig } from '$lib/utils/ticks.js'; const ctx = getChartContext(); @@ -151,11 +151,11 @@ ); - + {#if x} {@const splineProps = extractLayerProps(x, 'grid-x-line')} - + {#each xTickVals as x (x)} {#if ctx.radial} {@const [x1, y1] = pointRadial(ctx.xScale(x), ctx.yRange[0])} @@ -168,7 +168,7 @@ motion={tweenConfig} {...splineProps} class={cls( - layerClass('grid-x-radial-line'), + 'lc-grid-x-radial-line', 'stroke-surface-content/10', classes.line, splineProps?.class @@ -181,7 +181,7 @@ {motion} {...splineProps} class={cls( - layerClass('grid-x-rule'), + 'lc-grid-x-rule', 'stroke-surface-content/10', classes.line, splineProps?.class @@ -198,7 +198,7 @@ {motion} {...splineProps} class={cls( - layerClass('grid-x-end-rule'), + 'lc-grid-x-end-rule', 'stroke-surface-content/10', classes.line, splineProps?.class @@ -210,7 +210,7 @@ {#if y} {@const splineProps = extractLayerProps(y, 'grid-y-line')} - + {#each yTickVals as y (y)} {#if ctx.radial} {#if radialY === 'circle'} @@ -219,7 +219,7 @@ {motion} {...splineProps} class={cls( - layerClass('grid-y-radial-circle'), + 'lc-grid-y-radial-circle', 'fill-none stroke-surface-content/10', classes.line, splineProps?.class @@ -234,7 +234,7 @@ curve={curveLinearClosed} {...splineProps} class={cls( - layerClass('grid-y-radial-line'), + 'lc-grid-y-radial-line', 'stroke-surface-content/10', classes.line, splineProps?.class @@ -248,7 +248,7 @@ {motion} {...splineProps} class={cls( - layerClass('grid-y-rule'), + 'lc-grid-y-rule', 'stroke-surface-content/10', classes.line, splineProps?.class @@ -265,7 +265,7 @@ {motion} {...splineProps} class={cls( - layerClass('grid-y-radial-circle'), + 'lc-grid-y-radial-circle', 'fill-none stroke-surface-content/10', classes.line, splineProps?.class @@ -278,7 +278,7 @@ {motion} {...splineProps} class={cls( - layerClass('grid-y-end-rule'), + 'lc-grid-y-end-rule', 'stroke-surface-content/10', classes.line, splineProps?.class diff --git a/packages/layerchart/src/lib/components/Group.svelte b/packages/layerchart/src/lib/components/Group.svelte index 86d770fc9..198545d14 100644 --- a/packages/layerchart/src/lib/components/Group.svelte +++ b/packages/layerchart/src/lib/components/Group.svelte @@ -89,7 +89,6 @@ import { registerCanvasComponent } from './layout/Canvas.svelte'; import { getChartContext } from './Chart.svelte'; - import { layerClass } from '$lib/utils/attributes.js'; const ctx = getChartContext(); @@ -178,7 +177,7 @@ {:else if renderCtx === 'svg'} {@render children?.()} diff --git a/packages/layerchart/src/lib/components/Hull.svelte b/packages/layerchart/src/lib/components/Hull.svelte index 48166604d..9bc37aeb8 100644 --- a/packages/layerchart/src/lib/components/Hull.svelte +++ b/packages/layerchart/src/lib/components/Hull.svelte @@ -65,7 +65,6 @@ import Spline from './Spline.svelte'; import { getChartContext } from './Chart.svelte'; import { getGeoContext } from './GeoContext.svelte'; - import { layerClass } from '$lib/utils/attributes.js'; let { data, @@ -104,13 +103,13 @@ ); - + {#if geoCtx.projection} {@const polygon = geoVoronoi().hull(points)} onclick?.(e, { points, polygon })} onpointermove={(e) => onpointermove?.(e, { points, polygon })} {onpointerleave} @@ -123,7 +122,7 @@ x={(d) => d[0]} y={(d) => d[1]} {curve} - class={cls(layerClass('hull-class'), 'fill-transparent', classes.path)} + class={cls('lc-hull-class', 'fill-transparent', classes.path)} onclick={(e) => onclick?.(e, { points, polygon })} onpointermove={(e) => onpointermove?.(e, { points, polygon })} {onpointerleave} diff --git a/packages/layerchart/src/lib/components/Labels.svelte b/packages/layerchart/src/lib/components/Labels.svelte index 3f31ca58f..41a567059 100644 --- a/packages/layerchart/src/lib/components/Labels.svelte +++ b/packages/layerchart/src/lib/components/Labels.svelte @@ -74,7 +74,7 @@ import { isScaleBand } from '$lib/utils/scales.svelte.js'; import { getChartContext } from './Chart.svelte'; import Group from './Group.svelte'; - import { extractLayerProps, layerClass } from '$lib/utils/attributes.js'; + import { extractLayerProps } from '$lib/utils/attributes.js'; const ctx = getChartContext(); @@ -174,7 +174,7 @@ } - + {#snippet children({ points })} {#each points as point, i (key(point.data, i))} diff --git a/packages/layerchart/src/lib/components/Legend.svelte b/packages/layerchart/src/lib/components/Legend.svelte index 35fcd1883..80c7abd5c 100644 --- a/packages/layerchart/src/lib/components/Legend.svelte +++ b/packages/layerchart/src/lib/components/Legend.svelte @@ -116,7 +116,7 @@ import { cls } from '@layerstack/tailwind'; import type { AnyScale } from '$lib/utils/scales.svelte.js'; import { getChartContext } from './Chart.svelte'; - import { extractLayerProps, layerClass } from '$lib/utils/attributes.js'; + import { extractLayerProps } from '$lib/utils/attributes.js'; let { scale: scaleProp, @@ -297,7 +297,7 @@ {...restProps} data-placement={placement} class={cls( - layerClass('legend-container'), + 'lc-legend-container', 'inline-block', 'z-1', // stack above tooltip context layers (band rects, voronoi, ...) placement && [ @@ -318,7 +318,7 @@ classes.root )} > -
+
{title}
{#if children} @@ -331,15 +331,15 @@ {width} height={height + tickLengthProp + tickFontSize} viewBox="0 0 {width} {height + tickLengthProp + tickFontSize}" - class={cls(layerClass('legend-ramp-svg'), 'overflow-visible')} + class={cls('lc-legend-ramp-svg', 'overflow-visible')} > - + {#if scaleConfig.interpolator} {:else if scaleConfig.swatches} {#each scaleConfig.swatches as swatch, i} @@ -348,18 +348,14 @@ {/if} - + {#each tickValuesProp ?? scaleConfig.xScale?.ticks?.(ticks) ?? [] as tick, i} {tickFormatProp ? format(tick, asAny(tickFormatProp)) : tick} @@ -371,7 +367,7 @@ y1={0} x2={scaleConfig.xScale?.(tick)} y2={height + tickLengthProp} - class={cls(layerClass('legend-tick-line'), 'stroke-surface-content', classes.tick)} + class={cls('lc-legend-tick-line', 'stroke-surface-content', classes.tick)} /> {/if} {/each} @@ -380,7 +376,7 @@ {:else if variant === 'swatches'}
onpointerleave?.(e, item)} >
@@ -221,6 +216,6 @@ style:transform-origin="0 50%" style:opacity style:background-color={fill} - class={cls(layerClass('line'), stroke === undefined && 'bg-surface-content', className)} + class={cls('lc-line', stroke === undefined && 'bg-surface-content', className)} >
{/if} diff --git a/packages/layerchart/src/lib/components/LinearGradient.svelte b/packages/layerchart/src/lib/components/LinearGradient.svelte index f3b9f2fba..c750aae0e 100644 --- a/packages/layerchart/src/lib/components/LinearGradient.svelte +++ b/packages/layerchart/src/lib/components/LinearGradient.svelte @@ -81,7 +81,7 @@ import { createLinearGradient, getComputedStyles } from '../utils/canvas.js'; import { parsePercent } from '../utils/math.js'; import { createId } from '$lib/utils/createId.js'; - import { extractLayerProps, layerClass } from '$lib/utils/attributes.js'; + import { extractLayerProps } from '$lib/utils/attributes.js'; import { cls } from '@layerstack/tailwind'; const uid = $props.id(); @@ -180,13 +180,13 @@ {:else} {/if} {/each} diff --git a/packages/layerchart/src/lib/components/Marker.svelte b/packages/layerchart/src/lib/components/Marker.svelte index d3f356eef..c50aa366e 100644 --- a/packages/layerchart/src/lib/components/Marker.svelte +++ b/packages/layerchart/src/lib/components/Marker.svelte @@ -73,7 +73,6 @@ - + {#each lines as line} {@const stroke = line.stroke} @@ -203,18 +202,14 @@ {x2} {y2} {stroke} - class={cls( - layerClass('rule-x-radial-line'), - !stroke && 'stroke-surface-content/10', - className - )} + class={cls('lc-rule-x-radial-line', !stroke && 'stroke-surface-content/10', className)} /> {:else if line.axis === 'y'} {#if startContent && startPoint} - + {@render startContent({ point: startPoint, value: { @@ -401,7 +400,7 @@ {/if} {#if endContent && endPoint.current} - + {@render endContent({ point: endPoint.current, value: { diff --git a/packages/layerchart/src/lib/components/Text.svelte b/packages/layerchart/src/lib/components/Text.svelte index 36b096843..46831332b 100644 --- a/packages/layerchart/src/lib/components/Text.svelte +++ b/packages/layerchart/src/lib/components/Text.svelte @@ -188,7 +188,6 @@ import { getComputedStyles, renderText, type ComputedStylesOptions } from '../utils/canvas.js'; import { createKey } from '$lib/utils/key.svelte.js'; - import { layerClass } from '$lib/utils/attributes.js'; import { degreesToRadians } from '$lib/utils/math.js'; import { createId } from '$lib/utils/createId.js'; @@ -477,7 +476,7 @@ x={dx} y={dy} {...svgProps} - class={cls(layerClass('text-svg'), 'overflow-visible [paint-order:stroke]', svgProps?.class)} + class={cls('lc-text-svg', 'overflow-visible [paint-order:stroke]', svgProps?.class)} bind:this={svgRef} > {#if path} @@ -496,14 +495,14 @@ stroke-width={strokeWidth} {opacity} transform={transformProp} - class={cls(layerClass('text'), fill === undefined && 'fill-surface-content', className)} + class={cls('lc-text', fill === undefined && 'fill-surface-content', className)} > {wordsByLines.map((line) => line.words.join(' ')).join()} @@ -522,17 +521,13 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls( - layerClass('text'), - fill === undefined && 'text-surface-content fill-current', - className - )} + class={cls('lc-text', fill === undefined && 'text-surface-content fill-current', className)} > {#each wordsByLines as line, index} {line.words.join(' ')} @@ -558,7 +553,7 @@ ? 'bottom' : 'top'} {textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'right' : 'left'}" - class={cls(layerClass('text'), fill === undefined && 'text-surface-content', className)} + class={cls('lc-text', fill === undefined && 'text-surface-content', className)} > {textValue}
diff --git a/packages/layerchart/src/lib/components/TransformContext.svelte b/packages/layerchart/src/lib/components/TransformContext.svelte index fdba70095..10a5b2844 100644 --- a/packages/layerchart/src/lib/components/TransformContext.svelte +++ b/packages/layerchart/src/lib/components/TransformContext.svelte @@ -217,7 +217,6 @@ import { getChartContext } from './Chart.svelte'; import type { Snippet } from 'svelte'; import { cls } from '@layerstack/tailwind'; - import { layerClass } from '$lib/utils/attributes.js'; import { createControlledMotion, createMotionTracker, @@ -519,7 +518,7 @@ onpointerup={onPointerUp} ondblclick={onDoubleClick} onclickcapture={onClick} - class={cls(layerClass('transform-context'), 'h-full', className)} + class={cls('lc-transform-context', 'h-full', className)} bind:this={ref} {...restProps} > diff --git a/packages/layerchart/src/lib/components/Voronoi.svelte b/packages/layerchart/src/lib/components/Voronoi.svelte index fd0439fd5..a6c6a008a 100644 --- a/packages/layerchart/src/lib/components/Voronoi.svelte +++ b/packages/layerchart/src/lib/components/Voronoi.svelte @@ -71,8 +71,6 @@ import { getGeoContext } from './GeoContext.svelte'; import CircleClipPath from './CircleClipPath.svelte'; - import { layerClass } from '$lib/utils/attributes.js'; - let { data, r, @@ -118,7 +116,7 @@ const disableClip = $derived(r === 0 || r == null || r === Infinity); - + {#if geo.projection} {@const polygons = geoVoronoi().polygons(points)} {#each polygons.features as feature} @@ -131,11 +129,7 @@ > onclick?.(e, { data: feature.properties.site.data, feature })} onpointerenter={(e) => onpointerenter?.(e, { data: feature.properties.site.data, feature })} @@ -158,11 +152,7 @@ onclick?.(e, { data: point.data, point })} onpointerenter={(e) => onpointerenter?.(e, { data: point.data, point })} onpointermove={(e) => onpointermove?.(e, { data: point.data, point })} diff --git a/packages/layerchart/src/lib/components/charts/LineChart.svelte b/packages/layerchart/src/lib/components/charts/LineChart.svelte index 8907f5424..5cee0481f 100644 --- a/packages/layerchart/src/lib/components/charts/LineChart.svelte +++ b/packages/layerchart/src/lib/components/charts/LineChart.svelte @@ -98,7 +98,6 @@ } from './types.js'; import { createLegendProps, SeriesState } from './utils.svelte.js'; import { setTooltipMetaContext } from '../tooltip/tooltipMetaContext.js'; - import { layerClass } from '$lib/utils/attributes.js'; import DefaultTooltip from './DefaultTooltip.svelte'; import ChartAnnotations from './ChartAnnotations.svelte'; @@ -165,7 +164,7 @@ ...props.spline, ...s.props, class: cls( - layerClass('line-chart-line'), + 'lc-line-chart-line', 'transition-opacity', // Checking `visibleSeries.length > 1` fixes re-animated tweened areas on hover seriesState.visibleSeries.length > 1 && diff --git a/packages/layerchart/src/lib/components/layout/Canvas.svelte b/packages/layerchart/src/lib/components/layout/Canvas.svelte index 36852ea15..0dfd92590 100644 --- a/packages/layerchart/src/lib/components/layout/Canvas.svelte +++ b/packages/layerchart/src/lib/components/layout/Canvas.svelte @@ -166,7 +166,6 @@ } from 'svelte/elements'; import type { Without } from '$lib/utils/types.js'; import { getChartContext } from '../Chart.svelte'; - import { layerClass } from '$lib/utils/attributes.js'; let { ref: refProp = $bindable(), @@ -454,7 +453,7 @@ bind:this={ref} style:z-index={zIndex} class={cls( - layerClass('layout-canvas'), + 'lc-layout-canvas', 'absolute top-0 left-0 w-full h-full', pointerEvents === false && 'pointer-events-none', className @@ -510,7 +509,7 @@ {title} + {title} {/if} @@ -135,11 +134,11 @@ {#if transform} - + {@render children?.({ ref })} {:else} diff --git a/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte b/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte index 218ed34d0..41d8b427c 100644 --- a/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte +++ b/packages/layerchart/src/lib/components/tooltip/Tooltip.svelte @@ -162,7 +162,6 @@ import { getTooltipContext } from './TooltipContext.svelte'; import { createMotion, type MotionProp } from '$lib/utils/motion.svelte.js'; import { untrack, type Snippet } from 'svelte'; - import { layerClass } from '$lib/utils/attributes.js'; let { anchor = 'top-left', @@ -359,7 +358,7 @@ {#if tooltipCtx.data}
{#if children} -
+
{@render children({ data: tooltipCtx.data, payload: tooltipCtx.payload })}
{/if} diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte index c2e90b8fe..ed90a2cd9 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte @@ -144,7 +144,6 @@ getTooltipPayload, type TooltipPayload, } from './tooltipMetaContext.js'; - import { layerClass } from '$lib/utils/attributes.js'; const ctx = getChartContext(); const geoCtx = getGeoContext(); @@ -606,7 +605,7 @@ style:width="{ctx.width}px" style:height="{ctx.height}px" class={cls( - layerClass('tooltip-context'), + 'lc-tooltip-context', 'absolute', debug && triggerPointerEvents && 'bg-danger/10 outline outline-danger' )} @@ -627,7 +626,7 @@ >
{:else if mode === 'bounds' || mode === 'band'} - + {#each rects as rect} {#if ctx.radial} @@ -671,7 +670,7 @@ startAngle={rect.x} endAngle={rect.x + rect.width} class={cls( - layerClass('tooltip-rect'), + 'lc-tooltip-rect', debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent' )} onpointerenter={(e) => showTooltip(e, rect?.data)} @@ -694,7 +693,7 @@ width={rect?.width} height={rect?.height} class={cls( - layerClass('tooltip-rect'), + 'lc-tooltip-rect', debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent' )} onpointerenter={(e) => showTooltip(e, rect?.data)} @@ -717,7 +716,7 @@ {:else if ['quadtree', 'quadtree-x', 'quadtree-y'].includes(mode) && debug} - + {#if quadtree} {#each quadtreeRects(quadtree, false) as rect} diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte index 22e0b90f6..feab67864 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte @@ -56,7 +56,6 @@
import { cls } from '@layerstack/tailwind'; - import { layerClass } from '$lib/utils/attributes.js'; import type { HTMLAttributes } from 'svelte/elements'; let { @@ -21,11 +20,7 @@
{@render children?.()} diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte index 3ebe5e38a..37f00f124 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte @@ -1,6 +1,5 @@ {#if line} - + {/if} {#if renderCtx === 'svg'} @@ -251,6 +259,6 @@ {stroke} stroke-width={strokeWidth} {opacity} - {...extractLayerProps(restProps, 'area-path')} + {...extractLayerProps(restProps, 'lc-area-path')} /> {/if} diff --git a/packages/layerchart/src/lib/components/Axis.svelte b/packages/layerchart/src/lib/components/Axis.svelte index c0f1fef84..2bd60e6c2 100644 --- a/packages/layerchart/src/lib/components/Axis.svelte +++ b/packages/layerchart/src/lib/components/Axis.svelte @@ -437,7 +437,7 @@ class={cls('lc-axis', `placement-${placement}`, classes.root, className)} > {#if rule !== false} - {@const ruleProps = extractLayerProps(rule, 'axis-rule')} + {@const ruleProps = extractLayerProps(rule, 'lc-axis-rule')} {#if grid !== false} - {@const ruleProps = extractLayerProps(grid, 'axis-grid')} + {@const ruleProps = extractLayerProps(grid, 'lc-axis-grid')} {:else if rounded === 'all' || rounded === 'none' || radius === 0} {:else} {@const tweenMotion = extractTweenConfig(motion)} @@ -212,6 +212,6 @@ {strokeWidth} {opacity} motion={tweenMotion} - {...extractLayerProps(restProps, 'bar')} + {...extractLayerProps(restProps, 'lc-bar')} /> {/if} diff --git a/packages/layerchart/src/lib/components/Bars.svelte b/packages/layerchart/src/lib/components/Bars.svelte index c731c4527..66b0f693b 100644 --- a/packages/layerchart/src/lib/components/Bars.svelte +++ b/packages/layerchart/src/lib/components/Bars.svelte @@ -64,7 +64,7 @@ {stroke} fill={fill ?? (ctx.config.c ? ctx.cGet(d) : null)} onclick={(e) => onBarClick(e, { data: d })} - {...extractLayerProps(restProps, 'bars-bar')} + {...extractLayerProps(restProps, 'lc-bars-bar')} /> {/each} {/if} diff --git a/packages/layerchart/src/lib/components/Calendar.svelte b/packages/layerchart/src/lib/components/Calendar.svelte index aed85aaee..6dceb9ad6 100644 --- a/packages/layerchart/src/lib/components/Calendar.svelte +++ b/packages/layerchart/src/lib/components/Calendar.svelte @@ -130,7 +130,7 @@ onpointerleave={(e) => tooltip?.hide()} {...extractLayerProps( restProps, - 'calendar-cell', + 'lc-calendar-cell', 'stroke-surface-content/5 border border-surface-content/5' )} /> @@ -139,7 +139,7 @@ {#if monthPath} {#each yearMonths as date} - + {/each} {/if} @@ -149,7 +149,7 @@ x={timeWeek.count(timeYear.floor(date), timeWeek.ceil(date)) * cellSize[0]} value={format(date, 'month', { variant: 'short' })} capHeight="7px" - {...extractLayerProps(monthLabel, 'calendar-month-label', 'text-xs')} + {...extractLayerProps(monthLabel, 'lc-calendar-month-label', 'text-xs')} /> {/each} {/if} diff --git a/packages/layerchart/src/lib/components/ChartClipPath.svelte b/packages/layerchart/src/lib/components/ChartClipPath.svelte index 0f3799018..e888e7d1f 100644 --- a/packages/layerchart/src/lib/components/ChartClipPath.svelte +++ b/packages/layerchart/src/lib/components/ChartClipPath.svelte @@ -41,5 +41,5 @@ {disabled} height={ctx.height + (full ? (ctx.padding?.top ?? 0) + (ctx.padding?.bottom ?? 0) : 0)} width={ctx.width + (full ? (ctx.padding?.left ?? 0) + (ctx.padding?.right ?? 0) : 0)} - {...extractLayerProps(restProps, 'chart-clip-path')} + {...extractLayerProps(restProps, 'lc-chart-clip-path')} /> diff --git a/packages/layerchart/src/lib/components/CircleClipPath.svelte b/packages/layerchart/src/lib/components/CircleClipPath.svelte index 0b1a52007..144a2627f 100644 --- a/packages/layerchart/src/lib/components/CircleClipPath.svelte +++ b/packages/layerchart/src/lib/components/CircleClipPath.svelte @@ -80,6 +80,13 @@ {#snippet clip()} - + {/snippet} diff --git a/packages/layerchart/src/lib/components/ColorRamp.svelte b/packages/layerchart/src/lib/components/ColorRamp.svelte index c35740c5f..0a50a4c5f 100644 --- a/packages/layerchart/src/lib/components/ColorRamp.svelte +++ b/packages/layerchart/src/lib/components/ColorRamp.svelte @@ -83,5 +83,5 @@ preserveAspectRatio="none" {height} {width} - {...extractLayerProps(restProps, 'color-ramp')} + {...extractLayerProps(restProps, 'lc-color-ramp')} /> diff --git a/packages/layerchart/src/lib/components/Connector.svelte b/packages/layerchart/src/lib/components/Connector.svelte index 9d47fc1b5..8c3dc2b2a 100644 --- a/packages/layerchart/src/lib/components/Connector.svelte +++ b/packages/layerchart/src/lib/components/Connector.svelte @@ -141,7 +141,7 @@ marker-start={markerStartId ? `url(#${markerStartId})` : undefined} marker-mid={markerMidId ? `url(#${markerMidId})` : undefined} marker-end={markerEndId ? `url(#${markerEndId})` : undefined} - {...extractLayerProps(restProps, 'connector')} + {...extractLayerProps(restProps, 'lc-connector')} {...restProps} /> diff --git a/packages/layerchart/src/lib/components/Frame.svelte b/packages/layerchart/src/lib/components/Frame.svelte index 01cc160f4..112ffa0ce 100644 --- a/packages/layerchart/src/lib/components/Frame.svelte +++ b/packages/layerchart/src/lib/components/Frame.svelte @@ -37,5 +37,5 @@ width={ctx.width + (full ? (ctx.padding?.left ?? 0) + (ctx.padding?.right ?? 0) : 0)} height={ctx.height + (full ? (ctx.padding?.top ?? 0) + (ctx.padding?.bottom ?? 0) : 0)} bind:ref - {...extractLayerProps(restProps, 'frame')} + {...extractLayerProps(restProps, 'lc-frame')} /> diff --git a/packages/layerchart/src/lib/components/GeoCircle.svelte b/packages/layerchart/src/lib/components/GeoCircle.svelte index 42a8afe7f..6b4cf7b5a 100644 --- a/packages/layerchart/src/lib/components/GeoCircle.svelte +++ b/packages/layerchart/src/lib/components/GeoCircle.svelte @@ -34,4 +34,4 @@ const geojson = $derived(geoCircle().radius(radius).center(center).precision(precision)()); - + diff --git a/packages/layerchart/src/lib/components/GeoEdgeFade.svelte b/packages/layerchart/src/lib/components/GeoEdgeFade.svelte index 8a5e049ff..ea1c848ab 100644 --- a/packages/layerchart/src/lib/components/GeoEdgeFade.svelte +++ b/packages/layerchart/src/lib/components/GeoEdgeFade.svelte @@ -56,6 +56,6 @@ const opacity = $derived(opacityProp ?? clamper(fade(distance))); - + {@render children?.()} diff --git a/packages/layerchart/src/lib/components/GeoPoint.svelte b/packages/layerchart/src/lib/components/GeoPoint.svelte index b3444e2a2..cf949f9ef 100644 --- a/packages/layerchart/src/lib/components/GeoPoint.svelte +++ b/packages/layerchart/src/lib/components/GeoPoint.svelte @@ -53,11 +53,11 @@ {#if renderContext === 'svg'} {#if children} - + {@render children({ x, y })} {:else} - + {/if} {/if} @@ -68,6 +68,6 @@ {@render children({ x, y })} {:else} - + {/if} {/if} diff --git a/packages/layerchart/src/lib/components/GeoSpline.svelte b/packages/layerchart/src/lib/components/GeoSpline.svelte index cfe75c8c2..dce51d7ba 100644 --- a/packages/layerchart/src/lib/components/GeoSpline.svelte +++ b/packages/layerchart/src/lib/components/GeoSpline.svelte @@ -81,5 +81,5 @@ x={(d) => d[0]} y={(d) => d[1]} {curve} - {...extractLayerProps(restProps, 'geo-spline')} + {...extractLayerProps(restProps, 'lc-geo-spline')} /> diff --git a/packages/layerchart/src/lib/components/GeoTile.svelte b/packages/layerchart/src/lib/components/GeoTile.svelte index f4b9dd8fa..bdcbbebaa 100644 --- a/packages/layerchart/src/lib/components/GeoTile.svelte +++ b/packages/layerchart/src/lib/components/GeoTile.svelte @@ -106,7 +106,7 @@ {#each tiles as [x, y, z] (url(x, y, z))} {#if !lines && !outline} - + {/if} {#if lines} {#each graticule.lines() as line} - + {/each} {/if} {#if outline} {/if} diff --git a/packages/layerchart/src/lib/components/Grid.svelte b/packages/layerchart/src/lib/components/Grid.svelte index 2206b697b..35f0d14a2 100644 --- a/packages/layerchart/src/lib/components/Grid.svelte +++ b/packages/layerchart/src/lib/components/Grid.svelte @@ -153,7 +153,7 @@ {#if x} - {@const splineProps = extractLayerProps(x, 'grid-x-line')} + {@const splineProps = extractLayerProps(x, 'lc-grid-x-line')} {#each xTickVals as x (x)} @@ -209,7 +209,7 @@ {/if} {#if y} - {@const splineProps = extractLayerProps(y, 'grid-y-line')} + {@const splineProps = extractLayerProps(y, 'lc-grid-y-line')} {#each yTickVals as y (y)} {#if ctx.radial} diff --git a/packages/layerchart/src/lib/components/Highlight.svelte b/packages/layerchart/src/lib/components/Highlight.svelte index c8fa85f74..f93e687bc 100644 --- a/packages/layerchart/src/lib/components/Highlight.svelte +++ b/packages/layerchart/src/lib/components/Highlight.svelte @@ -436,10 +436,10 @@ } ); - const areaProps = $derived(extractLayerProps(area, 'highlight-area')); - const barProps = $derived(extractLayerProps(bar, 'highlight-bar')); - const linesProps = $derived(extractLayerProps(linesProp, 'highlight-line')); - const pointsProps = $derived(extractLayerProps(points, 'highlight-point')); + const areaProps = $derived(extractLayerProps(area, 'lc-highlight-area')); + const barProps = $derived(extractLayerProps(bar, 'lc-highlight-bar')); + const linesProps = $derived(extractLayerProps(linesProp, 'lc-highlight-line')); + const pointsProps = $derived(extractLayerProps(points, 'lc-highlight-point')); {#if highlightData} diff --git a/packages/layerchart/src/lib/components/Labels.svelte b/packages/layerchart/src/lib/components/Labels.svelte index 41a567059..d8757f527 100644 --- a/packages/layerchart/src/lib/components/Labels.svelte +++ b/packages/layerchart/src/lib/components/Labels.svelte @@ -178,7 +178,7 @@ {#snippet children({ points })} {#each points as point, i (key(point.data, i))} - {@const textProps = extractLayerProps(getTextProps(point), 'labels-text')} + {@const textProps = extractLayerProps(getTextProps(point), 'lc-labels-text')} {#if childrenProp} {@render childrenProp({ data: point, textProps })} {:else} diff --git a/packages/layerchart/src/lib/components/Legend.svelte b/packages/layerchart/src/lib/components/Legend.svelte index 80c7abd5c..d5af0d0dd 100644 --- a/packages/layerchart/src/lib/components/Legend.svelte +++ b/packages/layerchart/src/lib/components/Legend.svelte @@ -343,7 +343,7 @@ /> {:else if scaleConfig.swatches} {#each scaleConfig.swatches as swatch, i} - + {/each} {/if} diff --git a/packages/layerchart/src/lib/components/LinearGradient.svelte b/packages/layerchart/src/lib/components/LinearGradient.svelte index c750aae0e..ed6e996c4 100644 --- a/packages/layerchart/src/lib/components/LinearGradient.svelte +++ b/packages/layerchart/src/lib/components/LinearGradient.svelte @@ -170,7 +170,7 @@ {y2} gradientTransform={rotate ? `rotate(${rotate})` : ''} gradientUnits={units} - {...extractLayerProps(restProps, 'linear-gradient')} + {...extractLayerProps(restProps, 'lc-linear-gradient')} > {#if stopsContent} {@render stopsContent?.()} diff --git a/packages/layerchart/src/lib/components/Link.svelte b/packages/layerchart/src/lib/components/Link.svelte index 7ce96773d..3b88987d0 100644 --- a/packages/layerchart/src/lib/components/Link.svelte +++ b/packages/layerchart/src/lib/components/Link.svelte @@ -173,5 +173,5 @@ TODO: {type} {curve} {sweep} - {...extractLayerProps(restProps, 'link')} + {...extractLayerProps(restProps, 'lc-link')} /> diff --git a/packages/layerchart/src/lib/components/MotionPath.svelte b/packages/layerchart/src/lib/components/MotionPath.svelte index 05bcbf5c9..0799e15f7 100644 --- a/packages/layerchart/src/lib/components/MotionPath.svelte +++ b/packages/layerchart/src/lib/components/MotionPath.svelte @@ -100,7 +100,7 @@ {fill} {rotate} bind:this={ref} - {...extractLayerProps(restProps, 'motion-path')} + {...extractLayerProps(restProps, 'lc-motion-path')} > diff --git a/packages/layerchart/src/lib/components/Pattern.svelte b/packages/layerchart/src/lib/components/Pattern.svelte index d1b9f0255..190044a51 100644 --- a/packages/layerchart/src/lib/components/Pattern.svelte +++ b/packages/layerchart/src/lib/components/Pattern.svelte @@ -265,7 +265,7 @@ {width} {height} patternUnits="userSpaceOnUse" - {...extractLayerProps(restProps, 'pattern')} + {...extractLayerProps(restProps, 'lc-pattern')} > {#if patternContent} {@render patternContent?.()} diff --git a/packages/layerchart/src/lib/components/Points.svelte b/packages/layerchart/src/lib/components/Points.svelte index 819c1c22f..26347e903 100644 --- a/packages/layerchart/src/lib/components/Points.svelte +++ b/packages/layerchart/src/lib/components/Points.svelte @@ -141,7 +141,7 @@ {stroke} {strokeWidth} {opacity} - {...extractLayerProps(restProps, 'point')} + {...extractLayerProps(restProps, 'lc-point')} /> {/each} {/if} diff --git a/packages/layerchart/src/lib/components/RadialGradient.svelte b/packages/layerchart/src/lib/components/RadialGradient.svelte index 80105a8ed..371977a57 100644 --- a/packages/layerchart/src/lib/components/RadialGradient.svelte +++ b/packages/layerchart/src/lib/components/RadialGradient.svelte @@ -167,7 +167,7 @@ {spreadMethod} gradientTransform={transform} gradientUnits={units} - {...extractLayerProps({ ...restProps, class: className }, 'radial-gradient')} + {...extractLayerProps({ ...restProps, class: className }, 'lc-radial-gradient')} > {#if stopsContent} {@render stopsContent()} diff --git a/packages/layerchart/src/lib/components/RectClipPath.svelte b/packages/layerchart/src/lib/components/RectClipPath.svelte index b27583f88..e9c7d7f09 100644 --- a/packages/layerchart/src/lib/components/RectClipPath.svelte +++ b/packages/layerchart/src/lib/components/RectClipPath.svelte @@ -82,7 +82,7 @@ {#snippet clip()} - + {/snippet} {#snippet children({ url })} {@render childrenProp?.({ id, url })} diff --git a/packages/layerchart/src/lib/components/TileImage.svelte b/packages/layerchart/src/lib/components/TileImage.svelte index 90d2ab822..7008030cf 100644 --- a/packages/layerchart/src/lib/components/TileImage.svelte +++ b/packages/layerchart/src/lib/components/TileImage.svelte @@ -135,7 +135,7 @@ y={(y + ty) * scale - 0.5} width={scale + 1} height={scale + 1} - {...extractLayerProps(restProps, 'tile-image-lower')} + {...extractLayerProps(restProps, 'lc-tile-image-lower')} /> {/key} {#if debug} diff --git a/packages/layerchart/src/lib/components/layout/WebGL.svelte b/packages/layerchart/src/lib/components/layout/WebGL.svelte index 25c90edec..c740b1512 100644 --- a/packages/layerchart/src/lib/components/layout/WebGL.svelte +++ b/packages/layerchart/src/lib/components/layout/WebGL.svelte @@ -123,7 +123,7 @@ style:bottom={ctx.padding.bottom + 'px'} style:left={ctx.padding.left + 'px'} style="width:100%;height:100%;position:absolute;" - {...extractLayerProps(restProps, 'layout-webgl')} + {...extractLayerProps(restProps, 'lc-layout-webgl')} > {#if typeof fallback === 'function'} {@render fallback()} diff --git a/packages/layerchart/src/lib/utils/attributes.ts b/packages/layerchart/src/lib/utils/attributes.ts index 14cfc49a7..c2fbfefff 100644 --- a/packages/layerchart/src/lib/utils/attributes.ts +++ b/packages/layerchart/src/lib/utils/attributes.ts @@ -1,19 +1,5 @@ import { cls } from '@layerstack/tailwind'; -/** - * Creates a string containing a class name that can be used by - * developers to target a specific layer/element within a LayerChart. - * - * This is a function so that the class names remain consistent and the - * prefix/structure can be changed in the future if needed - * - * @param layerName - the name of the layer to be appended to the generated class name - * @returns a string to be used as a class on an element - */ -export function layerClass(layerName: string) { - return `lc-${layerName}`; -} - type ExtractObjectType = T extends object ? (T extends Function ? never : T) : never; type WithClass = T & { class?: string }; type DefaultProps = WithClass<{ [key: string]: any }>; @@ -29,17 +15,15 @@ function isObjectWithClass(val: any): val is { class?: string } { * a class name to its class property to identify the layer for CSS targeting. * * @param props The props to be extracted, can be an object, function or any other type - * @param layerName The name of the layer used to apply a layer classname for targeting styling + * @param className The class name to be applied to the layer for targeting styling (e.g. 'lc-layer') * @param extraClasses Additional classes to be applied to the layer if they don't exist in the props already * @returns a typed spreadable object with props for the layer */ export function extractLayerProps( props: T, - layerName: string, + className: string, extraClasses?: string ): WithClass extends never ? DefaultProps : ExtractObjectType> { - const className = layerClass(layerName); - if (isObjectWithClass(props)) { return { ...props, From a5a57e0ce5dfb71f1d7232ca6e07d4e4118898ca Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Sun, 14 Sep 2025 21:42:22 -0400 Subject: [PATCH 23/77] Update primitives to support css-only (no Tailwind) --- .changeset/whole-women-listen.md | 5 ++ .../layerchart/src/lib/components/Axis.svelte | 57 ++++++++------ .../src/lib/components/Circle.svelte | 31 +++++++- .../src/lib/components/Ellipse.svelte | 31 +++++++- .../layerchart/src/lib/components/Line.svelte | 28 ++++++- .../src/lib/components/Polygon.svelte | 29 +++++++- .../layerchart/src/lib/components/Rect.svelte | 31 +++++++- .../layerchart/src/lib/components/Rule.svelte | 51 ++++++++----- .../layerchart/src/lib/components/Text.svelte | 34 ++++++++- .../layerchart/src/lib/utils/attributes.ts | 6 +- .../docs/components/Circle/+page.svelte | 59 +++++++++++++++ .../docs/components/Ellipse/+page.svelte | 73 ++++++++++++++++++ .../routes/docs/components/Line/+page.svelte | 74 +++++++++++++++++++ .../routes/docs/components/Rect/+page.svelte | 57 ++++++++++++++ 14 files changed, 506 insertions(+), 60 deletions(-) create mode 100644 .changeset/whole-women-listen.md diff --git a/.changeset/whole-women-listen.md b/.changeset/whole-women-listen.md new file mode 100644 index 000000000..279e554f1 --- /dev/null +++ b/.changeset/whole-women-listen.md @@ -0,0 +1,5 @@ +--- +'layerchart': minor +--- + +feat: Support css-only usage (no Tailwind required) while still providing first-class Tailwind support diff --git a/packages/layerchart/src/lib/components/Axis.svelte b/packages/layerchart/src/lib/components/Axis.svelte index 2bd60e6c2..d31bd5257 100644 --- a/packages/layerchart/src/lib/components/Axis.svelte +++ b/packages/layerchart/src/lib/components/Axis.svelte @@ -422,12 +422,7 @@ capHeight: '7px', lineHeight: '11px', ...labelProps, - class: cls( - 'lc-axis-label', - 'text-[10px] stroke-surface-100 [stroke-width:2px] font-light', - classes.label, - labelProps?.class - ), + class: cls('lc-axis-label', classes.label, labelProps?.class), }) satisfies ComponentProps; @@ -437,13 +432,11 @@ class={cls('lc-axis', `placement-${placement}`, classes.root, className)} > {#if rule !== false} - {@const ruleProps = extractLayerProps(rule, 'lc-axis-rule')} {/if} @@ -470,28 +463,21 @@ capHeight: '7px', lineHeight: '11px', ...tickLabelProps, - class: cls( - 'lc-axis-tick-label', - 'text-[10px] stroke-surface-100 [stroke-width:2px] font-light', - classes.tickLabel, - tickLabelProps?.class - ), + class: cls('lc-axis-tick-label', classes.tickLabel, tickLabelProps?.class), }} {#if grid !== false} - {@const ruleProps = extractLayerProps(grid, 'lc-axis-grid')} {/if} {#if tickMarks} - {@const tickClasses = cls('lc-axis-tick', 'stroke-surface-content/50', classes.tick)} + {@const tickClasses = cls('lc-axis-tick', classes.tick)} {#if orientation === 'horizontal'} diff --git a/packages/layerchart/src/lib/components/Circle.svelte b/packages/layerchart/src/lib/components/Circle.svelte index 5fc39965d..eab4c0542 100644 --- a/packages/layerchart/src/lib/components/Circle.svelte +++ b/packages/layerchart/src/lib/components/Circle.svelte @@ -114,7 +114,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, fillOpacity, stroke, strokeWidth, opacity }, - classes: cls('lc-circle', fill == null && 'fill-surface-content', className), + classes: cls('lc-circle', className), } ); } @@ -160,7 +160,7 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls('lc-circle', fill == null && 'fill-surface-content', className)} + class={cls('lc-circle', className)} {...restProps} /> {:else if renderCtx === 'html'} @@ -177,7 +177,32 @@ style:border-color={stroke} style:border-style="solid" style:transform="translate(-50%, -50%)" - class={cls('lc-circle', fill == null && 'bg-surface-content', className)} + class={cls('lc-circle', className)} {...restProps} >
{/if} + + diff --git a/packages/layerchart/src/lib/components/Ellipse.svelte b/packages/layerchart/src/lib/components/Ellipse.svelte index 707e4668d..e3947e2ea 100644 --- a/packages/layerchart/src/lib/components/Ellipse.svelte +++ b/packages/layerchart/src/lib/components/Ellipse.svelte @@ -132,7 +132,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, fillOpacity, stroke, strokeWidth, opacity }, - classes: cls('lc-ellipse', fill == null && 'fill-surface-content', className), + classes: cls('lc-ellipse', className), } ); } @@ -180,7 +180,7 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls('lc-ellipse', fill == null && 'fill-surface-content', className)} + class={cls('lc-ellipse', className)} {...restProps} /> {:else if renderCtx === 'html'} @@ -197,7 +197,32 @@ style:border-color={stroke} style:border-style="solid" style:transform="translate(-50%, -50%)" - class={cls('lc-ellipse', fill == null && 'bg-surface-content', className)} + class={cls('lc-ellipse', className)} {...restProps} >
{/if} + + diff --git a/packages/layerchart/src/lib/components/Line.svelte b/packages/layerchart/src/lib/components/Line.svelte index 126acb46f..66c185915 100644 --- a/packages/layerchart/src/lib/components/Line.svelte +++ b/packages/layerchart/src/lib/components/Line.svelte @@ -148,7 +148,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, stroke, strokeWidth, opacity }, - classes: cls('lc-line', stroke === undefined && 'stroke-surface-content', className), + classes: cls('lc-line', className), } ); } @@ -195,7 +195,7 @@ marker-start={markerStartId ? `url(#${markerStartId})` : undefined} marker-mid={markerMidId ? `url(#${markerMidId})` : undefined} marker-end={markerEndId ? `url(#${markerEndId})` : undefined} - class={cls('lc-line', stroke === undefined && 'stroke-surface-content', className)} + class={cls('lc-line', className)} {...restProps} /> @@ -206,6 +206,7 @@ { x: motionX1.current, y: motionY1.current }, { x: motionX2.current, y: motionY2.current } )} +
{/if} + + diff --git a/packages/layerchart/src/lib/components/Polygon.svelte b/packages/layerchart/src/lib/components/Polygon.svelte index ba9328a7b..24b5dd159 100644 --- a/packages/layerchart/src/lib/components/Polygon.svelte +++ b/packages/layerchart/src/lib/components/Polygon.svelte @@ -233,7 +233,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, fillOpacity, stroke, strokeWidth, opacity }, - classes: cls('lc-polygon', fill == null && 'fill-surface-content', className), + classes: cls('lc-polygon', className), } ); } @@ -277,8 +277,33 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls('lc-polygon', fill == null && 'fill-surface-content', className)} + class={cls('lc-polygon', className)} {...restProps} bind:this={ref} /> {/if} + + diff --git a/packages/layerchart/src/lib/components/Rect.svelte b/packages/layerchart/src/lib/components/Rect.svelte index 9d186da65..813b67c94 100644 --- a/packages/layerchart/src/lib/components/Rect.svelte +++ b/packages/layerchart/src/lib/components/Rect.svelte @@ -107,7 +107,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, fillOpacity, stroke, strokeWidth, opacity }, - classes: cls('lc-rect', fill == null && 'fill-surface-content', className), + classes: cls('lc-rect', className), } ); } @@ -155,7 +155,7 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls('lc-rect', fill == null && 'fill-surface-content', className)} + class={cls('lc-rect', className)} {...restProps} {onclick} {ondblclick} @@ -181,7 +181,7 @@ style:border-style="solid" style:border-color={stroke} style:border-radius="{restProps.rx}px" - class={cls('lc-rect', fill == null && 'bg-surface-content', className)} + class={cls('lc-rect', className)} {...restProps as any} {onclick} {ondblclick} @@ -192,3 +192,28 @@ {onpointerout} >
{/if} + + diff --git a/packages/layerchart/src/lib/components/Rule.svelte b/packages/layerchart/src/lib/components/Rule.svelte index 5f47fa43f..22e452ba1 100644 --- a/packages/layerchart/src/lib/components/Rule.svelte +++ b/packages/layerchart/src/lib/components/Rule.svelte @@ -189,7 +189,7 @@ {#each lines as line} - {@const stroke = line.stroke} + {@const stroke = line.stroke ?? strokeProp} {#if ctx.radial} {#if line.axis === 'x'} @@ -202,19 +202,10 @@ {x2} {y2} {stroke} - class={cls('lc-rule-x-radial-line', !stroke && 'stroke-surface-content/10', className)} + class={cls('lc-rule-x-radial-line', className)} /> {:else if line.axis === 'y'} - + {/if} {:else} {/if} {/each} + + diff --git a/packages/layerchart/src/lib/components/Text.svelte b/packages/layerchart/src/lib/components/Text.svelte index 46831332b..83aa7d490 100644 --- a/packages/layerchart/src/lib/components/Text.svelte +++ b/packages/layerchart/src/lib/components/Text.svelte @@ -410,7 +410,7 @@ paintOrder: 'stroke', textAnchor, }, - classes: cls(fill === undefined && 'fill-surface-content', className), + classes: cls('lc-text', className), }; const computedStyles = getComputedStyles(ctx.canvas, styles); @@ -495,7 +495,7 @@ stroke-width={strokeWidth} {opacity} transform={transformProp} - class={cls('lc-text', fill === undefined && 'fill-surface-content', className)} + class={cls('lc-text', className)} > {#each wordsByLines as line, index} {textValue}
{/if} + + diff --git a/packages/layerchart/src/lib/utils/attributes.ts b/packages/layerchart/src/lib/utils/attributes.ts index c2fbfefff..8254f446c 100644 --- a/packages/layerchart/src/lib/utils/attributes.ts +++ b/packages/layerchart/src/lib/utils/attributes.ts @@ -22,16 +22,16 @@ function isObjectWithClass(val: any): val is { class?: string } { export function extractLayerProps( props: T, className: string, - extraClasses?: string + ...extraClasses: string[] ): WithClass extends never ? DefaultProps : ExtractObjectType> { if (isObjectWithClass(props)) { return { ...props, - class: cls(className, props.class ?? '', extraClasses), + class: cls(className, ...extraClasses, props.class), } as WithClass>; } return { - class: cls(className, extraClasses), + class: cls(className, ...extraClasses), } as WithClass extends never ? DefaultProps : ExtractObjectType>; } diff --git a/packages/layerchart/src/routes/docs/components/Circle/+page.svelte b/packages/layerchart/src/routes/docs/components/Circle/+page.svelte index f5f33cf04..35e4ecd31 100644 --- a/packages/layerchart/src/routes/docs/components/Circle/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/Circle/+page.svelte @@ -6,6 +6,8 @@

Examples

+

Styling using classes

+
+ +

Styling using attributes

+ + +
+ + + + + + + + + + +
+
+ +

Styling using CSS variables

+ + +
+ + + + + + + + + + +
+
diff --git a/packages/layerchart/src/routes/docs/components/Ellipse/+page.svelte b/packages/layerchart/src/routes/docs/components/Ellipse/+page.svelte index 80519a5e1..845a912e3 100644 --- a/packages/layerchart/src/routes/docs/components/Ellipse/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/Ellipse/+page.svelte @@ -6,6 +6,8 @@

Examples

+

Styling using classes

+
+ +

Styling using attributes

+ + +
+ + + + + + + + + + +
+
+ +

Styling using CSS variables

+ + +
+ + + + + + + + + + +
+
diff --git a/packages/layerchart/src/routes/docs/components/Line/+page.svelte b/packages/layerchart/src/routes/docs/components/Line/+page.svelte index 6ab9182e7..b2dc952a3 100644 --- a/packages/layerchart/src/routes/docs/components/Line/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/Line/+page.svelte @@ -7,6 +7,8 @@

Examples

+

Styling using classes

+
+ +

Styling using attributes

+ + +
+ + + + + + + + + +
+
+ +

Styling using CSS variables

+ + +
+ + + + + + + + + +
+
diff --git a/packages/layerchart/src/routes/docs/components/Rect/+page.svelte b/packages/layerchart/src/routes/docs/components/Rect/+page.svelte index 40cc2d6bd..2ed03e59d 100644 --- a/packages/layerchart/src/routes/docs/components/Rect/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/Rect/+page.svelte @@ -6,6 +6,8 @@

Examples

+

Styling using classes

+
+ +

Styling using attributes

+ + +
+ + + + + + + + + +
+
+ +

Styling using CSS variables

+ + +
+ + + + + + + + + +
+
From e8adc049d8a49f5caf8c68e68c259d6d3d82b6f6 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 08:49:18 -0400 Subject: [PATCH 24/77] Add TODO about touch scrolling --- .../layerchart/src/lib/components/tooltip/TooltipContext.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte index ed90a2cd9..0e7f2302e 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte @@ -607,6 +607,7 @@ class={cls( 'lc-tooltip-context', 'absolute', + // 'touch-none', // TODO: Keep page from scrolling on touch devices (useful for transform/geo charts) debug && triggerPointerEvents && 'bg-danger/10 outline outline-danger' )} onmouseenter={onPointerEnter} From 1a21d5cd7b71c6d9bfc379f288e4f7063fff69cb Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 09:15:35 -0400 Subject: [PATCH 25/77] Update Grid and Spline to support css-only (no Tailwind) --- .../layerchart/src/lib/components/Grid.svelte | 86 ++++++++----------- .../src/lib/components/Spline.svelte | 39 ++++++--- 2 files changed, 65 insertions(+), 60 deletions(-) diff --git a/packages/layerchart/src/lib/components/Grid.svelte b/packages/layerchart/src/lib/components/Grid.svelte index 35f0d14a2..f72db00e5 100644 --- a/packages/layerchart/src/lib/components/Grid.svelte +++ b/packages/layerchart/src/lib/components/Grid.svelte @@ -167,12 +167,7 @@ {y2} motion={tweenConfig} {...splineProps} - class={cls( - 'lc-grid-x-radial-line', - 'stroke-surface-content/10', - classes.line, - splineProps?.class - )} + class={cls('lc-grid-x-radial-line', classes.line, splineProps?.class)} /> {:else} {/if} {/each} @@ -197,12 +187,7 @@ xOffset={ctx.xScale.step() + xBandOffset} {motion} {...splineProps} - class={cls( - 'lc-grid-x-end-rule', - 'stroke-surface-content/10', - classes.line, - splineProps?.class - )} + class={cls('lc-grid-x-end-rule', classes.line, splineProps?.class)} /> {/if} @@ -218,12 +203,7 @@ r={ctx.yScale(y) + yBandOffset} {motion} {...splineProps} - class={cls( - 'lc-grid-y-radial-circle', - 'fill-none stroke-surface-content/10', - classes.line, - splineProps?.class - )} + class={cls('lc-grid-y-radial-circle', classes.line, splineProps?.class)} /> {:else} {/if} {:else} @@ -247,12 +222,7 @@ yOffset={yBandOffset} {motion} {...splineProps} - class={cls( - 'lc-grid-y-rule', - 'stroke-surface-content/10', - classes.line, - splineProps?.class - )} + class={cls('lc-grid-y-rule', classes.line, splineProps?.class)} /> {/if} {/each} @@ -264,12 +234,7 @@ r={ctx.yScale(yTickVals[yTickVals.length - 1])! + ctx.yScale.step() + yBandOffset} {motion} {...splineProps} - class={cls( - 'lc-grid-y-radial-circle', - 'fill-none stroke-surface-content/10', - classes.line, - splineProps?.class - )} + class={cls('lc-grid-y-radial-circle', classes.line, splineProps?.class)} /> {:else} {/if} {/if} {/if} + + diff --git a/packages/layerchart/src/lib/components/Spline.svelte b/packages/layerchart/src/lib/components/Spline.svelte index 8ff0f32fd..c5fb4cf0e 100644 --- a/packages/layerchart/src/lib/components/Spline.svelte +++ b/packages/layerchart/src/lib/components/Spline.svelte @@ -273,12 +273,7 @@ ? merge({ styles: { strokeWidth } }, styleOverrides) : { styles: { fill, fillOpacity, stroke, strokeWidth, opacity }, - classes: cls( - 'lc-spline-path', - !fill && 'fill-none', - !stroke && 'stroke-surface-content', - className - ), + classes: cls('lc-spline-path', className), } ); } @@ -366,12 +361,7 @@ + @layer base { + :global(:where(.lc-spline-path)) { + --fill-color: none; + --stroke-color: var(--color-surface-content, currentColor); + } + + /* Svg | Canvas layers */ + :global(:where(.lc-layout-svg .lc-spline-path, svg.lc-spline-path):not([fill])) { + fill: var(--fill-color); + } + :global(:where(.lc-layout-svg .lc-spline-path, svg.lc-spline-path):not([stroke])) { + stroke: var(--stroke-color); + } + + /* Html layers */ + :global(:where(.lc-layout-html .lc-spline-path):not([background-color])) { + background-color: var(--fill-color); + } + :global(:where(.lc-layout-html .lc-spline-path):not([border-color])) { + border-color: var(--stroke-color); + } + } + From 1af5da149094686df557e835b31731a2ac28244a Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 10:27:08 -0400 Subject: [PATCH 26/77] feat(LinearGradient): Support Html context --- .changeset/poor-clocks-occur.md | 5 +++ .../src/lib/components/LinearGradient.svelte | 31 +++++++++++++++++++ .../layerchart/src/lib/components/Rect.svelte | 7 +++-- .../docs/components/LinearGradient/+page.ts | 2 +- 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 .changeset/poor-clocks-occur.md diff --git a/.changeset/poor-clocks-occur.md b/.changeset/poor-clocks-occur.md new file mode 100644 index 000000000..c3da59bfd --- /dev/null +++ b/.changeset/poor-clocks-occur.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +feat(LinearGradient): Support Html context diff --git a/packages/layerchart/src/lib/components/LinearGradient.svelte b/packages/layerchart/src/lib/components/LinearGradient.svelte index ed6e996c4..1e1068a05 100644 --- a/packages/layerchart/src/lib/components/LinearGradient.svelte +++ b/packages/layerchart/src/lib/components/LinearGradient.svelte @@ -113,6 +113,35 @@ let canvasGradient = $state(); + function createCSSGradient(): string { + if (!stops?.length) return ''; + + let direction: string; + if (rotate !== undefined) { + // Convert SVG rotation to CSS linear-gradient angle + // SVG: rotate(0) on horizontal gradient = left-to-right = CSS 90deg + // SVG: rotate(0) on vertical gradient = top-to-bottom = CSS 180deg + const baseAngle = vertical ? 180 : 90; + const cssAngle = baseAngle + rotate; + direction = `${cssAngle}deg`; + } else { + // Use direction keywords when no rotation is specified + direction = vertical ? 'to bottom' : 'to right'; + } + + const cssStops = stops + .map((stop, i) => { + if (Array.isArray(stop)) { + return `${stop[1]} ${stop[0]}`; + } else { + return `${stop} ${i * (100 / (stops.length - 1))}%`; + } + }) + .join(', '); + + return `linear-gradient(${direction}, ${cssStops})`; + } + function render(_ctx: CanvasRenderingContext2D) { // Use `getComputedStyles()` to convert each stop (if using CSS variables and/or classes) to color values const _stops = stops.map((stop, i) => { @@ -195,4 +224,6 @@ {@render children?.({ id, gradient: `url(#${id})` })} +{:else if renderCtx === 'html'} + {@render children?.({ id, gradient: createCSSGradient() })} {/if} diff --git a/packages/layerchart/src/lib/components/Rect.svelte b/packages/layerchart/src/lib/components/Rect.svelte index 813b67c94..d9139d293 100644 --- a/packages/layerchart/src/lib/components/Rect.svelte +++ b/packages/layerchart/src/lib/components/Rect.svelte @@ -169,13 +169,14 @@ {:else if renderCtx === 'html'} + {console.log({ fill })}
Date: Mon, 15 Sep 2025 12:01:47 -0400 Subject: [PATCH 27/77] fix(TooltipContext): Revert back to pointer events (instead of mouse/touch) but with `touch-action: pan-y`. Provides simplified events while allowing horizontal scrubbing with vertical scrolling. Add `touchAction` prop to control. Support css-only usage (no Tailwind) --- .changeset/chilly-games-hide.md | 5 ++ .changeset/late-glasses-itch.md | 5 ++ .../components/tooltip/TooltipContext.svelte | 77 +++++++++++++------ .../docs/examples/AnimatedGlobe/+page.svelte | 1 + 4 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 .changeset/chilly-games-hide.md create mode 100644 .changeset/late-glasses-itch.md diff --git a/.changeset/chilly-games-hide.md b/.changeset/chilly-games-hide.md new file mode 100644 index 000000000..6a20d7b9f --- /dev/null +++ b/.changeset/chilly-games-hide.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(TooltipContext): Revert back to pointer events (instead of mouse/touch) but with `touch-action: pan-y`. Provides simplified events while allowing horizontal scrubbing with vertical scrolling. diff --git a/.changeset/late-glasses-itch.md b/.changeset/late-glasses-itch.md new file mode 100644 index 000000000..899395fb8 --- /dev/null +++ b/.changeset/late-glasses-itch.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +feat(TooltipContext): Add `touchEvents` to control touch event behavior. Defaults to `pan-y` to allow vertical scrolling but horizontal scrubbing. diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte index 0e7f2302e..702478aae 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte @@ -77,6 +77,14 @@ */ locked?: boolean; + /** + * Controls the touch event behavior on the tooltip container. + * By default uses `pan-y` to allow verticle scrolling but horizontal scrubbing. + * Use `none` to disable all touch events (useful for improved transform/geo charts interactions) + * @default 'pan-y' + */ + touchEvents?: 'none' | 'pan-x' | 'pan-y' | 'auto'; + /** * quadtree search or voronoi clip radius * @default Infinity @@ -154,6 +162,7 @@ findTooltipData = 'closest', hideDelay = 0, locked = false, + touchEvents = 'pan-y', mode = 'manual', onclick = () => {}, radius = Infinity, @@ -604,18 +613,11 @@ style:left="{ctx.padding.left}px" style:width="{ctx.width}px" style:height="{ctx.height}px" - class={cls( - 'lc-tooltip-context', - 'absolute', - // 'touch-none', // TODO: Keep page from scrolling on touch devices (useful for transform/geo charts) - debug && triggerPointerEvents && 'bg-danger/10 outline outline-danger' - )} - onmouseenter={onPointerEnter} - ontouchstart={onPointerEnter} - onmousemove={onPointerMove} - ontouchmove={onPointerMove} - onmouseleave={onPointerLeave} - ontouchend={onPointerLeave} + style:--touch-action={touchEvents} + class={cls('lc-tooltip-context', debug && triggerPointerEvents && 'debug')} + onpointerenter={onPointerEnter} + onpointermove={onPointerMove} + onpointerleave={onPointerLeave} onclick={(e) => { // Ignore clicks without data (triggered from Legend clicks, for example) if (triggerPointerEvents && tooltipContext.data != null) { @@ -627,7 +629,7 @@ >
showTooltip(e, rect?.data)} onpointermove={(e) => showTooltip(e, rect?.data)} onpointerleave={() => hideTooltip()} @@ -693,10 +692,7 @@ y={rect?.y} width={rect?.width} height={rect?.height} - class={cls( - 'lc-tooltip-rect', - debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent' - )} + class={cls('lc-tooltip-rect', debug && 'debug')} onpointerenter={(e) => showTooltip(e, rect?.data)} onpointermove={(e) => showTooltip(e, rect?.data)} onpointerleave={() => hideTooltip()} @@ -725,10 +721,7 @@ y={rect.y} width={rect.width} height={rect.height} - class={cls( - 'lc-tooltip-quadtree-rect', - debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent' - )} + class={cls('lc-tooltip-quadtree-rect', debug && 'debug')} /> {/each} {/if} @@ -738,3 +731,37 @@ {/if}
+ + diff --git a/packages/layerchart/src/routes/docs/examples/AnimatedGlobe/+page.svelte b/packages/layerchart/src/routes/docs/examples/AnimatedGlobe/+page.svelte index 1bc23085c..7e6635542 100644 --- a/packages/layerchart/src/routes/docs/examples/AnimatedGlobe/+page.svelte +++ b/packages/layerchart/src/routes/docs/examples/AnimatedGlobe/+page.svelte @@ -145,6 +145,7 @@ transform={{ motion: { type: 'spring', stiffness: 0.04 }, }} + tooltip={{ touchEvents: 'none' }} bind:context > {#snippet children()} From b2f034e04b87075be3bcf9d8e7844475952bf9d4 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 12:05:31 -0400 Subject: [PATCH 28/77] Update AnnotationLine, AnnotationPoint, and AnnotationRange to support css-only (no Tailwind) --- .../src/lib/components/AnnotationLine.svelte | 17 +++++++++++++++-- .../src/lib/components/AnnotationPoint.svelte | 19 +++++++++++++++++-- .../src/lib/components/AnnotationRange.svelte | 18 ++++++++++++++++-- .../layerchart/src/lib/components/Rect.svelte | 1 - .../docs/components/AnnotationLine/+page.ts | 2 +- .../docs/components/AnnotationPoint/+page.ts | 2 +- .../docs/components/AnnotationRange/+page.ts | 2 +- 7 files changed, 51 insertions(+), 10 deletions(-) diff --git a/packages/layerchart/src/lib/components/AnnotationLine.svelte b/packages/layerchart/src/lib/components/AnnotationLine.svelte index e2d35c73c..f2d8f7e93 100644 --- a/packages/layerchart/src/lib/components/AnnotationLine.svelte +++ b/packages/layerchart/src/lib/components/AnnotationLine.svelte @@ -130,7 +130,7 @@ x2={line.x2} y2={line.y2} {...props?.line} - class={cls('stroke-surface-content', props?.line?.class)} + class={cls('lc-annotation-line', props?.line?.class)} /> {#if label} @@ -138,6 +138,19 @@ value={label} {...labelProps} {...props?.label} - class={cls('text-xs pointer-events-none', props?.label?.class)} + class={cls('lc-annotation-line-label', props?.label?.class)} /> {/if} + + diff --git a/packages/layerchart/src/lib/components/AnnotationPoint.svelte b/packages/layerchart/src/lib/components/AnnotationPoint.svelte index d5198915e..91e407315 100644 --- a/packages/layerchart/src/lib/components/AnnotationPoint.svelte +++ b/packages/layerchart/src/lib/components/AnnotationPoint.svelte @@ -108,12 +108,14 @@ cx={point.x} cy={point.y} {r} + onpointermove={onPointerMove} onmousemove={onPointerMove} ontouchmove={onPointerMove} + onpointerleave={onPointerLeave} onmouseleave={onPointerLeave} ontouchend={onPointerLeave} {...props?.circle} - class={cls('stroke-surface-100', props?.circle?.class)} + class={cls('lc-annotation-point', props?.circle?.class)} /> {#if label} @@ -121,6 +123,19 @@ value={label} {...labelProps} {...props?.label} - class={cls('text-xs pointer-events-none', props?.label?.class)} + class={cls('lc-annotation-point-label', props?.label?.class)} /> {/if} + + diff --git a/packages/layerchart/src/lib/components/AnnotationRange.svelte b/packages/layerchart/src/lib/components/AnnotationRange.svelte index f1ba599e6..af2aeba8b 100644 --- a/packages/layerchart/src/lib/components/AnnotationRange.svelte +++ b/packages/layerchart/src/lib/components/AnnotationRange.svelte @@ -118,7 +118,12 @@ {#if fill || className} - + {/if} {#if gradient} @@ -142,6 +147,15 @@ value={label} {...labelProps} {...props?.label} - class={cls('text-xs pointer-events-none', props?.label?.class)} + class={cls('lc-annotation-range-label', props?.label?.class)} /> {/if} + + diff --git a/packages/layerchart/src/lib/components/Rect.svelte b/packages/layerchart/src/lib/components/Rect.svelte index d9139d293..88153923e 100644 --- a/packages/layerchart/src/lib/components/Rect.svelte +++ b/packages/layerchart/src/lib/components/Rect.svelte @@ -169,7 +169,6 @@ {:else if renderCtx === 'html'} - {console.log({ fill })}
Date: Mon, 15 Sep 2025 12:21:58 -0400 Subject: [PATCH 29/77] Update BrushContext to support css-only (no Tailwind) --- .../src/lib/components/BrushContext.svelte | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/packages/layerchart/src/lib/components/BrushContext.svelte b/packages/layerchart/src/lib/components/BrushContext.svelte index b307ed1ff..c397c068f 100644 --- a/packages/layerchart/src/lib/components/BrushContext.svelte +++ b/packages/layerchart/src/lib/components/BrushContext.svelte @@ -462,7 +462,6 @@ {#if disabled} {@render children?.({ brushContext })} {:else} - {@const handleClass = 'lc-brush-handle'}
selectAll()} >
reset()} >
@@ -510,14 +503,7 @@ style:width="{_range.width}px" style:height="{handleSize}px" data-position="top" - class={cls( - handleClass, - 'cursor-ns-resize select-none', - 'range absolute', - 'z-10', - classes.handle, - handle?.class - )} + class={cls('lc-brush-handle', classes.handle, handle?.class)} onpointerdown={adjustTop} ondblclick={(e) => { e.stopPropagation(); @@ -535,15 +521,7 @@ style:width="{_range.width}px" style:height="{handleSize}px" data-position="bottom" - class={cls( - handleClass, - 'handle bottom', - 'cursor-ns-resize select-none', - 'range absolute', - 'z-10', - classes.handle, - handle?.class - )} + class={cls('lc-brush-handle', classes.handle, handle?.class)} onpointerdown={adjustBottom} ondblclick={(e) => { e.stopPropagation(); @@ -563,14 +541,7 @@ style:width="{handleSize}px" style:height="{_range.height}px" data-position="left" - class={cls( - handleClass, - 'cursor-ew-resize select-none', - 'range absolute', - 'z-10', - classes.handle, - handle?.class - )} + class={cls('lc-brush-handle', classes.handle, handle?.class)} onpointerdown={adjustLeft} ondblclick={(e) => { e.stopPropagation(); @@ -588,14 +559,7 @@ style:width="{handleSize}px" style:height="{_range.height}px" data-position="right" - class={cls( - handleClass, - 'cursor-ew-resize select-none', - 'range absolute', - 'z-10', - classes.handle, - handle?.class - )} + class={cls('lc-brush-handle', classes.handle, handle?.class)} onpointerdown={adjustRight} ondblclick={(e) => { e.stopPropagation(); @@ -609,3 +573,40 @@ {/if}
{/if} + + From c7fe36cf77554f0dca3cc120603d72640f783ccf Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 12:22:37 -0400 Subject: [PATCH 30/77] fix(TooltipContext): Place classes in `base` css layer --- .../components/tooltip/TooltipContext.svelte | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte index 702478aae..50a3c1391 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte @@ -733,35 +733,37 @@
From 0fb4c39baeb39310c5dd57389dcffe836eb0c28d Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 12:29:04 -0400 Subject: [PATCH 31/77] Update Calendar to support css-only (no Tailwind) --- .../src/lib/components/Calendar.svelte | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/layerchart/src/lib/components/Calendar.svelte b/packages/layerchart/src/lib/components/Calendar.svelte index 6dceb9ad6..c48ecabe1 100644 --- a/packages/layerchart/src/lib/components/Calendar.svelte +++ b/packages/layerchart/src/lib/components/Calendar.svelte @@ -128,11 +128,8 @@ fill={cell.color} onpointermove={(e) => tooltip?.show(e, cell.data)} onpointerleave={(e) => tooltip?.hide()} - {...extractLayerProps( - restProps, - 'lc-calendar-cell', - 'stroke-surface-content/5 border border-surface-content/5' - )} + strokeWidth={1} + {...extractLayerProps(restProps, 'lc-calendar-cell')} /> {/each} {/if} @@ -149,7 +146,23 @@ x={timeWeek.count(timeYear.floor(date), timeWeek.ceil(date)) * cellSize[0]} value={format(date, 'month', { variant: 'short' })} capHeight="7px" - {...extractLayerProps(monthLabel, 'lc-calendar-month-label', 'text-xs')} + {...extractLayerProps(monthLabel, 'lc-calendar-month-label')} /> {/each} {/if} + + From e1374b1f2c64df49ad1d315fe8bb8349e16fb47a Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 12:31:21 -0400 Subject: [PATCH 32/77] Update MonthPath to support css-only (no Tailwind) --- .../layerchart/src/lib/components/MonthPath.svelte | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/layerchart/src/lib/components/MonthPath.svelte b/packages/layerchart/src/lib/components/MonthPath.svelte index f0311d152..35f38f796 100644 --- a/packages/layerchart/src/lib/components/MonthPath.svelte +++ b/packages/layerchart/src/lib/components/MonthPath.svelte @@ -74,6 +74,18 @@ bind:pathRef {pathData} fill="none" - class={cls('lc-month-path', 'stroke-surface-content/20', className)} + class={cls('lc-month-path', className)} {...restProps} /> + + From e090721b9dc71922b814dcd1707280ae4e0cb272 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 13:33:21 -0400 Subject: [PATCH 33/77] Update Marker to support css-only (no Tailwind) --- .../src/lib/components/Marker.svelte | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/packages/layerchart/src/lib/components/Marker.svelte b/packages/layerchart/src/lib/components/Marker.svelte index c50aa366e..2efb45266 100644 --- a/packages/layerchart/src/lib/components/Marker.svelte +++ b/packages/layerchart/src/lib/components/Marker.svelte @@ -103,28 +103,9 @@ {refX} {refY} {viewBox} + data-type={type} {...restProps} - class={cls( - 'lc-marker', - 'overflow-visible', - // stroke - restProps.stroke == null && - (['arrow', 'circle-stroke', 'line'].includes(type ?? '') - ? 'stroke-[context-stroke]' - : type === 'circle' - ? 'stroke-surface-100' - : 'stroke-none'), - // extra stroke attrs - '[stroke-linecap:round] [stroke-linejoin:round]', - //fill - restProps.fill == null && - (['triangle', 'dot', 'circle'].includes(type ?? '') - ? 'fill-[context-stroke]' - : type === 'circle-stroke' - ? 'fill-surface-100' - : 'fill-none'), - className - )} + class={cls('lc-marker', className)} > {#if children} {@render children()} @@ -139,3 +120,34 @@ {/if} + + From 5b6ca0b2b87c7ba4ca58a266f04d15e66b8ef3a5 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Mon, 15 Sep 2025 14:23:20 -0400 Subject: [PATCH 34/77] Update Highlight and Labels to support css-only (no Tailwind) --- .../src/lib/components/Highlight.svelte | 57 ++++++++++++------- .../src/lib/components/Labels.svelte | 26 ++++++--- .../layerchart/src/lib/utils/attributes.ts | 3 +- .../routes/docs/examples/Bars/+page.svelte | 2 +- 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/packages/layerchart/src/lib/components/Highlight.svelte b/packages/layerchart/src/lib/components/Highlight.svelte index f93e687bc..0a434004a 100644 --- a/packages/layerchart/src/lib/components/Highlight.svelte +++ b/packages/layerchart/src/lib/components/Highlight.svelte @@ -114,7 +114,6 @@ import { max, min } from 'd3-array'; import { pointRadial, type Series, type SeriesPoint } from 'd3-shape'; import { notNull } from '@layerstack/utils'; - import { cls } from '@layerstack/tailwind'; import { isScaleBand, isScaleTime } from '$lib/utils/scales.svelte.js'; import { asAny } from '$lib/utils/types.js'; @@ -435,11 +434,6 @@ return tmpPoints; } ); - - const areaProps = $derived(extractLayerProps(area, 'lc-highlight-area')); - const barProps = $derived(extractLayerProps(bar, 'lc-highlight-bar')); - const linesProps = $derived(extractLayerProps(linesProp, 'lc-highlight-line')); - const pointsProps = $derived(extractLayerProps(points, 'lc-highlight-point')); {#if highlightData} @@ -454,15 +448,14 @@ endAngle={_area.x + _area.width} innerRadius={_area.y} outerRadius={_area.y + _area.height} - class={cls(!areaProps.fill && 'fill-surface-content/5', areaProps.class)} + class="lc-highlight-area" onclick={onAreaClick && ((e) => onAreaClick(e, { data: highlightData }))} /> {:else} onAreaClick(e, { data: highlightData }))} /> {/if} @@ -475,8 +468,7 @@ onBarClick(e, { data: highlightData }))} /> {/if} @@ -493,11 +485,7 @@ y1={line.y1} x2={line.x2} y2={line.y2} - {...linesProps} - class={cls( - 'stroke-surface-content/20 stroke-2 [stroke-dasharray:2,2] pointer-events-none', - linesProps.class - )} + {...extractLayerProps(linesProp, 'lc-highlight-line')} /> {/each} {/if} @@ -515,12 +503,7 @@ fill={point.fill} r={4} strokeWidth={6} - {...pointsProps} - class={cls( - 'stroke-white [paint-order:stroke] drop-shadow-sm', - !point.fill && (typeof points === 'boolean' || !points.fill) && 'fill-primary', - pointsProps.class - )} + {...extractLayerProps(points, 'lc-highlight-point')} onpointerdown={onPointClick && ((e) => { // Do not propagate `pointerdown` event to `BrushContext` if `onclick` is provided @@ -546,3 +529,33 @@ {/if} {/if} {/if} + + diff --git a/packages/layerchart/src/lib/components/Labels.svelte b/packages/layerchart/src/lib/components/Labels.svelte index d8757f527..404ae1b44 100644 --- a/packages/layerchart/src/lib/components/Labels.svelte +++ b/packages/layerchart/src/lib/components/Labels.svelte @@ -183,19 +183,29 @@ {@render childrenProp({ data: point, textProps })} {:else} {/if} {/each} {/snippet} + + diff --git a/packages/layerchart/src/lib/utils/attributes.ts b/packages/layerchart/src/lib/utils/attributes.ts index 8254f446c..b0f696cc4 100644 --- a/packages/layerchart/src/lib/utils/attributes.ts +++ b/packages/layerchart/src/lib/utils/attributes.ts @@ -1,4 +1,5 @@ import { cls } from '@layerstack/tailwind'; +import type { ClassValue } from 'svelte/elements'; type ExtractObjectType = T extends object ? (T extends Function ? never : T) : never; type WithClass = T & { class?: string }; @@ -22,7 +23,7 @@ function isObjectWithClass(val: any): val is { class?: string } { export function extractLayerProps( props: T, className: string, - ...extraClasses: string[] + ...extraClasses: ClassValue[] ): WithClass extends never ? DefaultProps : ExtractObjectType> { if (isObjectWithClass(props)) { return { diff --git a/packages/layerchart/src/routes/docs/examples/Bars/+page.svelte b/packages/layerchart/src/routes/docs/examples/Bars/+page.svelte index 6031943b9..cd551d31d 100644 --- a/packages/layerchart/src/routes/docs/examples/Bars/+page.svelte +++ b/packages/layerchart/src/routes/docs/examples/Bars/+page.svelte @@ -1,6 +1,6 @@ @@ -83,12 +90,7 @@ import Rule from '../Rule.svelte'; import Spline from '../Spline.svelte'; - import { - accessor, - chartDataArray, - defaultChartPadding, - findRelatedData, - } from '../../utils/common.js'; + import { chartDataArray, defaultChartPadding, findRelatedData } from '../../utils/common.js'; import { asAny } from '../../utils/types.js'; import type { SeriesData, @@ -100,13 +102,17 @@ import { setTooltipMetaContext } from '../tooltip/tooltipMetaContext.js'; import DefaultTooltip from './DefaultTooltip.svelte'; import ChartAnnotations from './ChartAnnotations.svelte'; + import { isScaleTime } from 'layerchart/utils/scales.svelte.js'; let { data = [], x: xProp, - y: yProp, + xScale, xDomain, + y: yProp, + yScale, radial = false, + orientation = 'horizontal', series: seriesProp, seriesLayout = 'overlap', axis = true, @@ -136,13 +142,22 @@ ...restProps }: LineChartProps = $props(); + const isVertical = $derived(orientation === 'vertical'); + const series = $derived( seriesProp === undefined ? [ { key: 'default', - label: typeof yProp === 'string' ? yProp : 'value', - value: yProp, + + label: isVertical + ? typeof xProp === 'string' + ? xProp + : 'value' + : typeof yProp === 'string' + ? yProp + : 'value', + value: isVertical ? xProp : yProp, color: 'var(--color-primary)', }, ] @@ -159,7 +174,8 @@ function getSplineProps(s: SeriesData, i: number) { const splineProps: ComponentProps = { data: s.data, - y: s.value ?? (s.data ? undefined : s.key), + x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, + y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, stroke: s.color, ...props.spline, ...s.props, @@ -182,7 +198,8 @@ function getPointsProps(s: SeriesData, i: number) { const pointsProps: ComponentProps = { data: s.data, - y: s.value ?? (s.data ? undefined : s.key), + x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, + y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, fill: s.color, ...props.points, ...(typeof points === 'object' ? points : null), @@ -202,7 +219,8 @@ function getLabelsProps(s: SeriesData, i: number) { const labelsProps: ComponentProps> = { data: s.data, - y: s.value ?? (s.data ? undefined : s.key), + x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, + y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, ...props.labels, ...(typeof labels === 'object' ? labels : null), class: cls( @@ -234,7 +252,8 @@ return { data: seriesTooltipData, - y: s.value ?? (s.data ? undefined : s.key), + x: isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, + y: !isVertical ? (s.value ?? (s.data ? undefined : s.key)) : undefined, lines: i === 0, onPointClick: onPointClick ? (e, detail) => onPointClick(e, { ...detail, series: s }) @@ -323,18 +342,20 @@ s.value ?? s.key) : undefined)} {xDomain} - y={yProp ?? series.map((s) => s.value ?? s.key)} - yBaseline={0} - yNice + xBaseline={!isVertical || (xScale && isScaleTime(xScale)) ? undefined : 0} + xNice={orientation === 'vertical'} + y={yProp ?? (isVertical ? undefined : series.map((s) => s.value ?? s.key))} + yBaseline={isVertical || (yScale && isScaleTime(yScale)) ? undefined : 0} + yNice={orientation === 'horizontal'} {radial} padding={radial ? undefined : defaultChartPadding(axis, legend)} {...restProps} tooltip={tooltip === false ? false : { - mode: 'quadtree-x', + mode: isVertical ? 'quadtree-y' : 'quadtree-x', onclick: onTooltipClick, debug, ...props.tooltip?.context, diff --git a/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte b/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte index 7f6b83996..52b74a03e 100644 --- a/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte @@ -130,6 +130,21 @@
+

Vertical

+ + +
+ +
+
+

Series

@@ -178,6 +193,25 @@
+

Series (vertical)

+ + +
+ +
+
+

Series (individual tooltip with highlight)

diff --git a/packages/layerchart/src/routes/docs/examples/Line/+page.svelte b/packages/layerchart/src/routes/docs/examples/Line/+page.svelte index dfa654388..2621f5265 100644 --- a/packages/layerchart/src/routes/docs/examples/Line/+page.svelte +++ b/packages/layerchart/src/routes/docs/examples/Line/+page.svelte @@ -187,6 +187,37 @@
+

Vertical

+ + +
+ + + + + + + + + + {#snippet children({ data })} + + + + + {/snippet} + + +
+
+

Multiple series

From 9efe2aec9b35cc4a9b39a72fdf3250be6e1c1d46 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 16 Sep 2025 08:59:34 -0400 Subject: [PATCH 36/77] fix(AreaChart|LineChart|DefaultTooltip): Handle per-series data with different length --- .changeset/grumpy-ties-mix.md | 5 + .../lib/components/charts/AreaChart.svelte | 2 +- .../components/charts/DefaultTooltip.svelte | 2 +- .../lib/components/charts/LineChart.svelte | 8 +- .../docs/components/LineChart/+page.svelte | 158 ++++++++++++++++++ 5 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 .changeset/grumpy-ties-mix.md diff --git a/.changeset/grumpy-ties-mix.md b/.changeset/grumpy-ties-mix.md new file mode 100644 index 000000000..3ab91e3a4 --- /dev/null +++ b/.changeset/grumpy-ties-mix.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(AreaChart|LineChart|DefaultTooltip): Handle per-series data with different length diff --git a/packages/layerchart/src/lib/components/charts/AreaChart.svelte b/packages/layerchart/src/lib/components/charts/AreaChart.svelte index 871fa81e9..c243fb979 100644 --- a/packages/layerchart/src/lib/components/charts/AreaChart.svelte +++ b/packages/layerchart/src/lib/components/charts/AreaChart.svelte @@ -316,7 +316,7 @@ if (!context) return {}; const seriesTooltipData = s.data && context.tooltip.data - ? findRelatedData(s.data, context.tooltip.data, context.x) + ? (findRelatedData(s.data, context.tooltip.data, context.x) ?? {}) : null; const highlightPointsProps = typeof props.highlight?.points === 'object' ? props.highlight.points : null; diff --git a/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte b/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte index c6d881512..9aade7956 100644 --- a/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte +++ b/packages/layerchart/src/lib/components/charts/DefaultTooltip.svelte @@ -48,7 +48,7 @@ value={sum(seriesState.visibleSeries, (s) => { const seriesTooltipData = s.data ? findRelatedData(s.data, data, context.x) : data; const valueAccessor = accessor(s.value ?? (s.data ? context.y : s.key)); - return valueAccessor(seriesTooltipData); + return seriesTooltipData ? valueAccessor(seriesTooltipData) : 0; })} format="integer" valueAlign="right" diff --git a/packages/layerchart/src/lib/components/charts/LineChart.svelte b/packages/layerchart/src/lib/components/charts/LineChart.svelte index e4e259d56..a1290368d 100644 --- a/packages/layerchart/src/lib/components/charts/LineChart.svelte +++ b/packages/layerchart/src/lib/components/charts/LineChart.svelte @@ -236,10 +236,6 @@ return labelsProps; } - const highlightPointsProps = $derived( - typeof props.highlight?.points === 'object' ? props.highlight.points : null - ); - function getHighlightProps( s: SeriesData, i: number @@ -247,8 +243,10 @@ if (!context || !context.tooltip.data) return {}; const seriesTooltipData = s.data && context.tooltip.data - ? findRelatedData(s.data, context.tooltip.data, context.x) + ? (findRelatedData(s.data, context.tooltip.data, context.x) ?? {}) : null; + const highlightPointsProps = + typeof props.highlight?.points === 'object' ? props.highlight.points : null; return { data: seriesTooltipData, diff --git a/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte b/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte index 52b74a03e..0921218f8 100644 --- a/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte +++ b/packages/layerchart/src/routes/docs/components/LineChart/+page.svelte @@ -45,6 +45,16 @@ value: 'integer', keys, }); + const multiSeriesDataWithNulls = $derived( + multiSeriesData.map((d) => { + const newItem = { ...d }; + keys.forEach((key) => { + // @ts-expect-error shh + newItem[key] = Math.random() < 0.2 ? null : newItem[key]; + }); + return newItem; + }) + ); const multiSeriesFlatData = pivotLonger(multiSeriesData, keys, 'fruit', 'value'); const multiSeriesDataByFruit = group(multiSeriesFlatData, (d) => d.fruit); @@ -89,6 +99,79 @@ let renderContext = $derived(shared.renderContext as 'svg' | 'canvas'); let debug = $derived(shared.debug); + + const monitorSeries = [ + { + key: 'RespondActivityTaskCompleted', + data: [ + { + date: new Date('2025-09-14T00:00:00.000Z'), + value: 0.05875000000000004, + }, + { + date: new Date('2025-09-14T00:05:00.000Z'), + value: 0.0195, + }, + { + date: new Date('2025-09-14T12:00:00.000Z'), + value: 0.0195, + }, + { + date: new Date('2025-09-15T00:00:00.000Z'), + value: 0.08083333333333337, + }, + { + date: new Date('2025-09-15T00:05:00.000Z'), + value: 0.04592857142857144, + }, + ], + color: 'var(--color-blue-500)', + }, + { + key: 'RespondWorkflowTaskCompleted', + data: [ + { + date: new Date('2025-09-14T00:00:00.000Z'), + value: 0.08999999999999998, + }, + { + date: new Date('2025-09-14T00:05:00.000Z'), + value: 0.03275000000000002, + }, + { + date: new Date('2025-09-14T12:00:00.000Z'), + value: 0.047, + }, + { + date: new Date('2025-09-15T00:00:00.000Z'), + value: 0.08666666666666673, + }, + { + date: new Date('2025-09-15T00:05:00.000Z'), + value: 0.04625, + }, + { + date: new Date('2025-09-15T12:00:00.000Z'), + value: 0.0485, + }, + ], + color: 'var(--color-purple-500)', + }, + { + key: 'StartWorkflowExecution', + data: [ + { + date: new Date('2025-09-14T00:00:00.000Z'), + value: 0.16666666666666669, + }, + { + date: new Date('2025-09-15T00:00:00.000Z'), + value: 0.1300000000000001, + }, + ], + color: 'var(--color-green-500)', + }, + ];

Examples

@@ -163,6 +246,38 @@
+

Series (with nulls)

+ + +
+ + {#snippet belowMarks({ visibleSeries, highlightKey })} + {#each visibleSeries as s} + d[s.key] !== null)} + y={s.key} + stroke={s.color} + class={cls( + '[stroke-dasharray:3,3] transition-opacity', + highlightKey && highlightKey !== s.key && 'opacity-10' + )} + /> + {/each} + {/snippet} + +
+
+

Series (separate data)

@@ -193,6 +308,49 @@
+

Series (separate data with different length)

+ + +
+ Math.random() > 0.3), + color: 'var(--color-danger)', + }, + { + key: 'bananas', + data: multiSeriesDataByFruit.get('bananas')?.filter((d, i) => Math.random() > 0.3), + color: 'var(--color-success)', + }, + { + key: 'oranges', + data: multiSeriesDataByFruit.get('oranges')?.filter((d, i) => Math.random() > 0.3), + color: 'var(--color-warning)', + }, + ]} + {renderContext} + {debug} + /> +
+
+ + +

Series (vertical)

From 1cec888dfe7a44c0cb63610cdd205b869d28a472 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Tue, 16 Sep 2025 09:01:55 -0400 Subject: [PATCH 37/77] Add Dagre docs placeholder --- packages/layerchart/src/routes/_NavMenu.svelte | 2 +- .../src/routes/docs/components/Dagre/+page.svelte | 4 ++++ .../src/routes/docs/components/Dagre/+page.ts | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 packages/layerchart/src/routes/docs/components/Dagre/+page.svelte create mode 100644 packages/layerchart/src/routes/docs/components/Dagre/+page.ts diff --git a/packages/layerchart/src/routes/_NavMenu.svelte b/packages/layerchart/src/routes/_NavMenu.svelte index f3a68f9b8..5faa8e2ac 100644 --- a/packages/layerchart/src/routes/_NavMenu.svelte +++ b/packages/layerchart/src/routes/_NavMenu.svelte @@ -117,7 +117,7 @@ 'Graticule', 'TileImage', ], - Layout: ['ForceSimulation', 'Pack', 'Partition', 'Sankey', 'Tree', 'Treemap'], + Layout: ['Dagre', 'ForceSimulation', 'Pack', 'Partition', 'Sankey', 'Tree', 'Treemap'], Fill: ['LinearGradient', 'RadialGradient', 'Pattern'], Clipping: ['ClipPath', 'ChartClipPath', 'CircleClipPath', 'RectClipPath'], Other: ['Blur', 'Bounds', 'ColorRamp', 'MotionPath'], diff --git a/packages/layerchart/src/routes/docs/components/Dagre/+page.svelte b/packages/layerchart/src/routes/docs/components/Dagre/+page.svelte new file mode 100644 index 000000000..1f3a40471 --- /dev/null +++ b/packages/layerchart/src/routes/docs/components/Dagre/+page.svelte @@ -0,0 +1,4 @@ + diff --git a/packages/layerchart/src/routes/docs/components/Dagre/+page.ts b/packages/layerchart/src/routes/docs/components/Dagre/+page.ts new file mode 100644 index 000000000..16d7e77e8 --- /dev/null +++ b/packages/layerchart/src/routes/docs/components/Dagre/+page.ts @@ -0,0 +1,15 @@ +import api from '$lib/components/Dagre.svelte?raw&sveld'; +import source from '$lib/components/Dagre.svelte?raw'; +import pageSource from './+page.svelte?raw'; + +export async function load() { + return { + meta: { + api, + source, + pageSource, + supportedContexts: ['svg', 'canvas'], + related: ['examples/Dagre'], + }, + }; +} From d75b630228b639a4c1cab5d9526f6053b92e799e Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Wed, 17 Sep 2025 07:51:52 -0400 Subject: [PATCH 38/77] fix(SimplifiedCharts): Properly handle `legend` prop as object when determining bottom padding --- .changeset/cute-donkeys-greet.md | 5 +++++ .../layerchart/src/lib/components/charts/ArcChart.svelte | 2 +- .../layerchart/src/lib/components/charts/PieChart.svelte | 2 +- packages/layerchart/src/lib/utils/common.ts | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/cute-donkeys-greet.md diff --git a/.changeset/cute-donkeys-greet.md b/.changeset/cute-donkeys-greet.md new file mode 100644 index 000000000..68b3ba32a --- /dev/null +++ b/.changeset/cute-donkeys-greet.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +fix(SimplifiedCharts): Properly handle `legend` prop as object when determining bottom padding diff --git a/packages/layerchart/src/lib/components/charts/ArcChart.svelte b/packages/layerchart/src/lib/components/charts/ArcChart.svelte index 06e11d2b1..334b19f57 100644 --- a/packages/layerchart/src/lib/components/charts/ArcChart.svelte +++ b/packages/layerchart/src/lib/components/charts/ArcChart.svelte @@ -381,7 +381,7 @@ 'var(--color-warning)', 'var(--color-danger)', ]} - padding={{ bottom: legend === true ? 32 : 0 }} + padding={{ bottom: legend ? 32 : 0 }} {...restProps} tooltip={tooltip === false ? false diff --git a/packages/layerchart/src/lib/components/charts/PieChart.svelte b/packages/layerchart/src/lib/components/charts/PieChart.svelte index e96549fad..27d6518bb 100644 --- a/packages/layerchart/src/lib/components/charts/PieChart.svelte +++ b/packages/layerchart/src/lib/components/charts/PieChart.svelte @@ -406,7 +406,7 @@ 'var(--color-warning)', 'var(--color-danger)', ]} - padding={{ bottom: legend === true ? 32 : 0 }} + padding={{ bottom: legend ? 32 : 0 }} {...restProps} tooltip={tooltip === false ? false diff --git a/packages/layerchart/src/lib/utils/common.ts b/packages/layerchart/src/lib/utils/common.ts index 8b26a2ce3..ec6d03d63 100644 --- a/packages/layerchart/src/lib/utils/common.ts +++ b/packages/layerchart/src/lib/utils/common.ts @@ -51,7 +51,7 @@ export function defaultChartPadding Date: Thu, 18 Sep 2025 09:48:47 -0400 Subject: [PATCH 39/77] Add `getObjectOrNull` and `resolveMaybeFn` to simplify use cases --- .../layerchart/src/lib/utils/common.test.ts | 32 ++++++++++++++++++- packages/layerchart/src/lib/utils/common.ts | 27 ++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/packages/layerchart/src/lib/utils/common.test.ts b/packages/layerchart/src/lib/utils/common.test.ts index 7f5dad0e6..4f2c3e3e0 100644 --- a/packages/layerchart/src/lib/utils/common.test.ts +++ b/packages/layerchart/src/lib/utils/common.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect } from 'vitest'; -import { accessor } from './common.js'; +import { accessor, resolveMaybeFn, getObjectOrNull } from './common.js'; export const testData = { one: 1, @@ -45,3 +45,33 @@ describe('accessor', () => { expect(actual).toEqual(testData); }); }); + +describe('getObjectOrNull', () => { + it('returns null for non-object values', () => { + expect(getObjectOrNull(5)).toBeNull(); + expect(getObjectOrNull('string')).toBeNull(); + expect(getObjectOrNull(null)).toBeNull(); + expect(getObjectOrNull(undefined)).toBeUndefined(); + }); + + it('returns null for functions', () => { + const fn = () => {}; + expect(getObjectOrNull(fn)).toBeNull(); + }); + + it('returns the object if value is an object', () => { + const obj = { a: 1 }; + expect(getObjectOrNull(obj)).toBe(obj); + }); +}); + +describe('resolveMaybeFn', () => { + it('returns value if not a function', () => { + expect(resolveMaybeFn(5)).toBe(5); + }); + + it('calls function with args', () => { + const fn = (a: number, b: number) => a + b; + expect(resolveMaybeFn(fn, 2, 3)).toBe(5); + }); +}); diff --git a/packages/layerchart/src/lib/utils/common.ts b/packages/layerchart/src/lib/utils/common.ts index ec6d03d63..6983fd93e 100644 --- a/packages/layerchart/src/lib/utils/common.ts +++ b/packages/layerchart/src/lib/utils/common.ts @@ -66,3 +66,30 @@ export function findRelatedData(data: any[], original: any, accessor: Function) return accessor(d)?.valueOf() === accessor(original)?.valueOf(); }); } + +/** + * Return the object if the value is an object, otherwise return null. + * Functions (including Snippet types) are treated as non-objects and return null. + */ +export function getObjectOrNull( + value: T +): T extends object + ? T extends Function + ? null + : T + : T extends null + ? null + : T extends undefined + ? undefined + : null { + if (typeof value === 'object') return value as any; + if (value === undefined) return undefined as any; + return null as any; +} + +/** + * Call with args if function, otherwise return the value. + */ +export function resolveMaybeFn(value: T | ((...args: any[]) => T), ...args: any[]) { + return typeof value === 'function' ? (value as Function)(...args) : value; +} From ee2bd7f870309672f7220afa840a476f6baf01f3 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Thu, 18 Sep 2025 09:50:50 -0400 Subject: [PATCH 40/77] Update PieChart to use SeriesState for series/key selection. Use `createLegendProps` (with some overrides for data/series selection differences). Fix legend selection styling when overrides are provided --- .../src/lib/components/charts/PieChart.svelte | 85 ++++++++++--------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/packages/layerchart/src/lib/components/charts/PieChart.svelte b/packages/layerchart/src/lib/components/charts/PieChart.svelte index 27d6518bb..4f3bf743d 100644 --- a/packages/layerchart/src/lib/components/charts/PieChart.svelte +++ b/packages/layerchart/src/lib/components/charts/PieChart.svelte @@ -172,11 +172,11 @@ @@ -375,8 +357,8 @@ x={value} {c} cDomain={chartData.map(keyAccessor)} - cRange={seriesColors.length - ? seriesColors + cRange={seriesState.allSeriesColors.length + ? seriesState.allSeriesColors : c !== key ? chartData.map((d) => cAccessor(d)) : [ @@ -401,7 +383,7 @@ color: cAccessor, context, series, - visibleSeries, + visibleSeries: seriesState.visibleSeries, visibleData, highlightKey: seriesState.highlightKey.current, setHighlightKey: seriesState.highlightKey.set, diff --git a/packages/layerchart/src/lib/components/charts/PieChart.svelte b/packages/layerchart/src/lib/components/charts/PieChart.svelte index bebae41fb..79a5d62a9 100644 --- a/packages/layerchart/src/lib/components/charts/PieChart.svelte +++ b/packages/layerchart/src/lib/components/charts/PieChart.svelte @@ -245,18 +245,10 @@ const valueAccessor = $derived(accessor(value)); const cAccessor = $derived(accessor(c)); - const allSeriesData = $derived( - series - .flatMap((s) => s.data?.map((d) => ({ seriesKey: s.key, ...d }))) - .filter((d) => d) as Array - ); - const chartData = $derived( - allSeriesData.length ? allSeriesData : chartDataArray(data) + seriesState.allSeriesData.length ? seriesState.allSeriesData : chartDataArray(data) ) as Array; - const seriesColors = $derived(series.map((s) => s.color).filter((d) => d != null)); - const visibleData = $derived( chartData.filter((d) => { const dataKey = keyAccessor(d); @@ -264,14 +256,6 @@ }) ); - // TODO: note, I added this because it wasn't consistent with all the other charts - // unsure if it is correct but will validate with Sean - const visibleSeries = $derived( - series.filter( - (s) => seriesState.selectedSeries.isEmpty() || seriesState.selectedSeries.isSelected(s.key) - ) - ); - function getLegendProps(): ComponentProps { return createLegendProps({ seriesState, @@ -342,7 +326,8 @@ return { startAngle: arc.startAngle, endAngle: arc.endAngle, - outerRadius: visibleSeries.length > 1 ? seriesIndex * (outerRadius ?? 0) : outerRadius, + outerRadius: + seriesState.visibleSeries.length > 1 ? seriesIndex * (outerRadius ?? 0) : outerRadius, innerRadius, cornerRadius, padAngle, @@ -354,7 +339,7 @@ // Workaround for `tooltip={{ mode: 'manual' }} onTooltipClick(e, { data: arc.data }); }, - opacity: seriesState.isHighlighted(keyAccessor(arc.data), true) ? 1 : 0.1, + opacity: seriesState.isHighlighted(keyAccessor(arc.data), true) ? 1 : 0.5, ...props.arc, ...s.props, ...arcDataProps, @@ -383,7 +368,7 @@ return key; }, get visibleSeries() { - return visibleSeries; + return seriesState.visibleSeries; }, }); @@ -395,8 +380,8 @@ x={value} c={key} cDomain={chartData.map(keyAccessor)} - cRange={seriesColors.length - ? seriesColors + cRange={seriesState.allSeriesColors.length + ? seriesState.allSeriesColors : c !== key ? chartData.map((d) => cAccessor(d)) : [ @@ -423,7 +408,7 @@ color: cAccessor, context, series, - visibleSeries, + visibleSeries: seriesState.visibleSeries, visibleData, highlightKey: seriesState.highlightKey.current, setHighlightKey: seriesState.highlightKey.set, @@ -447,7 +432,7 @@ {@render marks(snippetProps)} {:else} - {#each visibleSeries as s, seriesIdx (s.key)} + {#each seriesState.visibleSeries as s, seriesIdx (s.key)} {#if typeof pie === 'function'} {@render pie({ ...snippetProps, diff --git a/packages/layerchart/src/lib/components/charts/utils.svelte.ts b/packages/layerchart/src/lib/components/charts/utils.svelte.ts index 4d7e472ae..ecec442dd 100644 --- a/packages/layerchart/src/lib/components/charts/utils.svelte.ts +++ b/packages/layerchart/src/lib/components/charts/utils.svelte.ts @@ -34,10 +34,10 @@ export function createLegendProps( ...opts.props, classes: { item: (item) => { - const isVisible = - opts.seriesState.visibleSeries.length && - !opts.seriesState.visibleSeries.some((s) => s.key === item.value); - return cls(resolveMaybeFn(opts.props?.classes?.item, item), isVisible && 'opacity-50'); + return cls( + resolveMaybeFn(opts.props?.classes?.item, item), + !opts.seriesState.isVisible(item.value) && 'opacity-50' + ); }, ...opts.props?.classes, }, diff --git a/packages/layerchart/src/lib/states/series.svelte.ts b/packages/layerchart/src/lib/states/series.svelte.ts index 9fefc9c32..8dfbd7605 100644 --- a/packages/layerchart/src/lib/states/series.svelte.ts +++ b/packages/layerchart/src/lib/states/series.svelte.ts @@ -34,16 +34,15 @@ export class SeriesState { return this.#series.length === 1 && this.#series[0].key === 'default'; } - get allSeriesData() { - return this.#series - .flatMap((s) => s.data?.map((d) => ({ seriesKey: s.key, ...d }))) - .filter((d) => d) as Array; + get visibleSeries() { + return this.#series.filter((s) => this.isVisible(s.key)); } - get visibleSeries() { - return this.#series.filter( - (s) => this.selectedSeries.isEmpty() || this.selectedSeries.isSelected(s.key) - ); + /** + * Check if series is visible + */ + isVisible(seriesKey: SeriesData['key']) { + return this.selectedSeries.isEmpty() || this.selectedSeries.isSelected(seriesKey); } /** @@ -57,4 +56,16 @@ export class SeriesState { return this.highlightKey.current === seriesKey; } } + + get allSeriesData() { + return this.#series + .flatMap((s) => s.data?.map((d) => ({ seriesKey: s.key, ...d }))) + .filter((d) => d) as Array; + } + + get allSeriesColors() { + return this.#series.map((s) => s.color).filter((c) => c != null) as Array< + NonNullable['color']> + >; + } } From 3b742ac733600827fc29dd9c8e1ae79e31d0c55f Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Sun, 21 Sep 2025 00:30:15 -0400 Subject: [PATCH 52/77] feat(Legend): Add `selected` prop to fade out unselected items (if passed and non-empty) --- .changeset/huge-regions-live.md | 5 +++++ .../layerchart/src/lib/components/Legend.svelte | 15 +++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 .changeset/huge-regions-live.md diff --git a/.changeset/huge-regions-live.md b/.changeset/huge-regions-live.md new file mode 100644 index 000000000..b77d54599 --- /dev/null +++ b/.changeset/huge-regions-live.md @@ -0,0 +1,5 @@ +--- +'layerchart': patch +--- + +feat(Legend): Add `selected` prop to fade out unselected items (if passed and non-empty) diff --git a/packages/layerchart/src/lib/components/Legend.svelte b/packages/layerchart/src/lib/components/Legend.svelte index 6c3dda208..70f573998 100644 --- a/packages/layerchart/src/lib/components/Legend.svelte +++ b/packages/layerchart/src/lib/components/Legend.svelte @@ -65,10 +65,6 @@ */ orientation?: 'horizontal' | 'vertical'; - onclick?: (e: MouseEvent, detail: LegendItem) => any; - onpointerenter?: (e: MouseEvent, detail: LegendItem) => any; - onpointerleave?: (e: MouseEvent, detail: LegendItem) => any; - /** * Determine display ramp (individual color swatches or continuous ramp) * @@ -76,6 +72,11 @@ */ variant?: 'ramp' | 'swatches'; + /** + * An array of selected items. If provided, the legend fades unselected items. + */ + selected?: string[]; + /** * Classes to apply to the elements. * @@ -91,6 +92,10 @@ item?: string | ((item: LegendItem) => string); }; + onclick?: (e: MouseEvent, detail: LegendItem) => any; + onpointerenter?: (e: MouseEvent, detail: LegendItem) => any; + onpointerleave?: (e: MouseEvent, detail: LegendItem) => any; + /** * A bindable reference to the wrapping `
` element. * @@ -135,6 +140,7 @@ onpointerenter, onpointerleave, variant = 'ramp', + selected = [], classes = {}, ref: refProp = $bindable(), class: className, @@ -361,6 +367,7 @@ {@const item = { value: tick, color }}
diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte index ceff603c4..8fd4b9539 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipContext.svelte @@ -744,14 +744,14 @@ &.debug { outline: 1px solid var(--color-danger); - background-color: color-mix(in oklch, var(--color-danger) 10%, transparent); + background-color: color-mix(in oklab, var(--color-danger) 10%, transparent); } } :global(:where(.lc-tooltip-voronoi-path)) { &.debug { stroke: var(--color-danger); - fill: color-mix(in oklch, var(--color-danger) 10%, transparent); + fill: color-mix(in oklab, var(--color-danger) 10%, transparent); } } @@ -760,7 +760,7 @@ &.debug { stroke: var(--color-danger); - fill: color-mix(in oklch, var(--color-danger) 10%, transparent); + fill: color-mix(in oklab, var(--color-danger) 10%, transparent); } } @@ -769,7 +769,7 @@ &.debug { stroke: var(--color-danger); - fill: color-mix(in oklch, var(--color-danger) 10%, transparent); + fill: color-mix(in oklab, var(--color-danger) 10%, transparent); } } } diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte index feab67864..69582cd4a 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipHeader.svelte @@ -88,25 +88,14 @@
{#if color}
{/if} @@ -117,3 +106,27 @@ {format ? formatUtil(value, asAny(format)) : value} {/if}
+ + diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipItem.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipItem.svelte index a30c57561..b67a3ca2a 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipItem.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipItem.svelte @@ -128,31 +128,19 @@
{#if color}
@@ -167,17 +155,8 @@
{#if children} {@render children()} @@ -187,3 +166,39 @@ {/if}
+ + diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipList.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipList.svelte index 087a2a5c3..c0fdf818d 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipList.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipList.svelte @@ -18,10 +18,17 @@ }); -
+
{@render children?.()}
+ + diff --git a/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte b/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte index 37f00f124..ce78ebb65 100644 --- a/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte +++ b/packages/layerchart/src/lib/components/tooltip/TooltipSeparator.svelte @@ -17,14 +17,23 @@ }); -
+
{@render children?.()}
+ + From ec0ab7934b8dd676a9b78908aa9ca0595b8bdf49 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Sun, 21 Sep 2025 11:52:02 -0400 Subject: [PATCH 60/77] move overlooked .lc-text-svg TW classes to CSS --- .../layerchart/src/lib/components/Text.svelte | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/layerchart/src/lib/components/Text.svelte b/packages/layerchart/src/lib/components/Text.svelte index 83aa7d490..fb09924db 100644 --- a/packages/layerchart/src/lib/components/Text.svelte +++ b/packages/layerchart/src/lib/components/Text.svelte @@ -472,13 +472,7 @@ {#if renderCtx === 'svg'} - + {#if path} {#key path} @@ -495,14 +489,14 @@ stroke-width={strokeWidth} {opacity} transform={transformProp} - class={cls('lc-text', className)} + class={['lc-text', className]} > {wordsByLines.map((line) => line.words.join(' ')).join()} @@ -521,7 +515,7 @@ {stroke} stroke-width={strokeWidth} {opacity} - class={cls('lc-text', className)} + class={['lc-text', className]} > {#each wordsByLines as line, index} {textValue}
@@ -566,6 +560,11 @@ --stroke-color: initial; } + :global(:where(.lc-text-svg)) { + overflow: visible; + paint-order: stroke; + } + /* Svg | Canvas layers */ :global(:where(.lc-layout-svg .lc-text, svg.lc-text):not([fill])) { color: var(--fill-color); From 9a54c90a0ad152245b0562541daceff22f6a7245 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Sun, 21 Sep 2025 16:00:59 -0400 Subject: [PATCH 61/77] Remove remaining tailwind classes --- .../src/lib/components/ComputedStyles.svelte | 10 ++- .../src/lib/components/GeoPath.svelte | 20 ++++- .../lib/components/TransformContext.svelte | 11 ++- .../lib/components/TransformControls.svelte | 89 +++++++++++++++---- .../components/tooltip/TooltipContext.svelte | 3 +- 5 files changed, 110 insertions(+), 23 deletions(-) diff --git a/packages/layerchart/src/lib/components/ComputedStyles.svelte b/packages/layerchart/src/lib/components/ComputedStyles.svelte index 8461d7677..f0c441cd9 100644 --- a/packages/layerchart/src/lib/components/ComputedStyles.svelte +++ b/packages/layerchart/src/lib/components/ComputedStyles.svelte @@ -20,8 +20,16 @@
(styles = _styles)} >
{@render children?.({ styles })} + + diff --git a/packages/layerchart/src/lib/components/GeoPath.svelte b/packages/layerchart/src/lib/components/GeoPath.svelte index 63d41edab..9df491200 100644 --- a/packages/layerchart/src/lib/components/GeoPath.svelte +++ b/packages/layerchart/src/lib/components/GeoPath.svelte @@ -66,7 +66,6 @@ + + + + + +{@render children?.()} diff --git a/examples/standalone/src/routes/+page.svelte b/examples/standalone/src/routes/+page.svelte new file mode 100644 index 000000000..4c8c00fd9 --- /dev/null +++ b/examples/standalone/src/routes/+page.svelte @@ -0,0 +1,33 @@ + + +
+
+ +
+ +
+ +
+
+ + diff --git a/examples/standalone/static/robots.txt b/examples/standalone/static/robots.txt new file mode 100644 index 000000000..b6dd6670c --- /dev/null +++ b/examples/standalone/static/robots.txt @@ -0,0 +1,3 @@ +# allow crawling everything by default +User-agent: * +Disallow: diff --git a/examples/standalone/svelte.config.js b/examples/standalone/svelte.config.js new file mode 100644 index 000000000..612cde971 --- /dev/null +++ b/examples/standalone/svelte.config.js @@ -0,0 +1,12 @@ +import adapter from '@sveltejs/adapter-cloudflare'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + // Consult https://svelte.dev/docs/kit/integrations + // for more information about preprocessors + preprocess: vitePreprocess(), + kit: { adapter: adapter() } +}; + +export default config; diff --git a/examples/standalone/tsconfig.json b/examples/standalone/tsconfig.json new file mode 100644 index 000000000..a5567ee6b --- /dev/null +++ b/examples/standalone/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } + // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias + // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files + // + // To make changes to top-level options such as include and exclude, we recommend extending + // the generated config; see https://svelte.dev/docs/kit/configuration#typescript +} diff --git a/examples/standalone/vite.config.ts b/examples/standalone/vite.config.ts new file mode 100644 index 000000000..a5c0236d3 --- /dev/null +++ b/examples/standalone/vite.config.ts @@ -0,0 +1,7 @@ +import devtoolsJson from 'vite-plugin-devtools-json'; +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [sveltekit(), devtoolsJson()] +}); diff --git a/package.json b/package.json index a0e7a5d58..6ce551594 100644 --- a/package.json +++ b/package.json @@ -23,5 +23,10 @@ "rimraf": "6.0.1", "wrangler": "^4.30.0" }, - "packageManager": "pnpm@9.1.1" -} + "packageManager": "pnpm@9.1.1", + "pnpm": { + "onlyBuiltDependencies": [ + "esbuild" + ] + } +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 740b0e04d..dc806d03e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,6 +21,42 @@ importers: specifier: ^4.30.0 version: 4.30.0(@cloudflare/workers-types@4.20250816.0) + examples/standalone: + devDependencies: + '@sveltejs/adapter-cloudflare': + specifier: ^7.0.0 + version: 7.2.1(@sveltejs/kit@2.31.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.38.2)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(yaml@2.8.1)))(svelte@5.38.2)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(yaml@2.8.1)))(wrangler@4.30.0(@cloudflare/workers-types@4.20250816.0)) + '@sveltejs/kit': + specifier: ^2.22.0 + version: 2.31.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.38.2)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(yaml@2.8.1)))(svelte@5.38.2)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(yaml@2.8.1)) + '@sveltejs/vite-plugin-svelte': + specifier: ^6.0.0 + version: 6.1.2(svelte@5.38.2)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(yaml@2.8.1)) + layerchart: + specifier: workspace:* + version: link:../../packages/layerchart + prettier: + specifier: ^3.4.2 + version: 3.6.2 + prettier-plugin-svelte: + specifier: ^3.3.3 + version: 3.4.0(prettier@3.6.2)(svelte@5.38.2) + svelte: + specifier: ^5.0.0 + version: 5.38.2 + svelte-check: + specifier: ^4.0.0 + version: 4.3.1(picomatch@4.0.3)(svelte@5.38.2)(typescript@5.9.2) + typescript: + specifier: ^5.0.0 + version: 5.9.2 + vite: + specifier: ^7.0.4 + version: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(yaml@2.8.1) + vite-plugin-devtools-json: + specifier: ^1.0.0 + version: 1.0.0(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(yaml@2.8.1)) + packages/layerchart: dependencies: '@dagrejs/dagre': @@ -887,12 +923,6 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/sourcemap-codec@1.5.4': - resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} - '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -3647,16 +3677,12 @@ snapshots: '@jridgewell/set-array@1.2.1': {} - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/sourcemap-codec@1.5.4': {} - '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.29': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping@0.3.30': dependencies: @@ -4683,10 +4709,6 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.4.6(picomatch@4.0.2): - optionalDependencies: - picomatch: 4.0.2 - fdir@6.4.6(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 @@ -4953,7 +4975,7 @@ snapshots: magic-string@0.30.17: dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 mdast-util-to-hast@13.2.0: dependencies: @@ -5488,7 +5510,7 @@ snapshots: svelte-check@4.3.1(picomatch@4.0.3)(svelte@5.38.2)(typescript@5.9.2): dependencies: - '@jridgewell/trace-mapping': 0.3.29 + '@jridgewell/trace-mapping': 0.3.30 chokidar: 4.0.3 fdir: 6.4.6(picomatch@4.0.3) picocolors: 1.1.1 @@ -5609,8 +5631,8 @@ snapshots: tinyglobby@0.2.14: dependencies: - fdir: 6.4.6(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 tinypool@1.1.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index dee51e928..15989339b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,3 @@ packages: - - "packages/*" + - 'packages/*' + - 'examples/*' From 0082e340255ee3056b773f4978244fe78ff89b35 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Sun, 21 Sep 2025 17:07:38 -0400 Subject: [PATCH 63/77] Set default color for --color-primary usage --- .../src/lib/components/charts/ArcChart.svelte | 12 ++++++------ .../src/lib/components/charts/AreaChart.svelte | 2 +- .../src/lib/components/charts/BarChart.svelte | 2 +- .../src/lib/components/charts/LineChart.svelte | 2 +- .../src/lib/components/charts/PieChart.svelte | 12 ++++++------ .../src/lib/components/charts/ScatterChart.svelte | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/layerchart/src/lib/components/charts/ArcChart.svelte b/packages/layerchart/src/lib/components/charts/ArcChart.svelte index fd50ce70e..56bfcb0cd 100644 --- a/packages/layerchart/src/lib/components/charts/ArcChart.svelte +++ b/packages/layerchart/src/lib/components/charts/ArcChart.svelte @@ -349,12 +349,12 @@ : c !== key ? chartData.map((d) => cAccessor(d)) : [ - 'var(--color-primary)', - 'var(--color-secondary)', - 'var(--color-info)', - 'var(--color-success)', - 'var(--color-warning)', - 'var(--color-danger)', + 'var(--color-primary, currentColor)', + 'var(--color-secondary, currentColor)', + 'var(--color-info, currentColor)', + 'var(--color-success, currentColor)', + 'var(--color-warning, currentColor)', + 'var(--color-danger, currentColor)', ]} padding={{ bottom: legend ? 32 : 0 }} {...restProps} diff --git a/packages/layerchart/src/lib/components/charts/AreaChart.svelte b/packages/layerchart/src/lib/components/charts/AreaChart.svelte index ec37135fc..61d1e4c9c 100644 --- a/packages/layerchart/src/lib/components/charts/AreaChart.svelte +++ b/packages/layerchart/src/lib/components/charts/AreaChart.svelte @@ -139,7 +139,7 @@ key: 'default', label: typeof y === 'string' ? y : 'value', value: y, - color: 'var(--color-primary)', + color: 'var(--color-primary, currentColor)', }, ] : seriesProp diff --git a/packages/layerchart/src/lib/components/charts/BarChart.svelte b/packages/layerchart/src/lib/components/charts/BarChart.svelte index 8fa2615e3..e035095e9 100644 --- a/packages/layerchart/src/lib/components/charts/BarChart.svelte +++ b/packages/layerchart/src/lib/components/charts/BarChart.svelte @@ -441,7 +441,7 @@ {y1Range} {yInterval} c={isVertical ? yProp : xProp} - cRange={['var(--color-primary)']} + cRange={['var(--color-primary, currentColor)']} {radial} padding={radial ? undefined : defaultChartPadding(axis, legend)} {...restProps} diff --git a/packages/layerchart/src/lib/components/charts/LineChart.svelte b/packages/layerchart/src/lib/components/charts/LineChart.svelte index aa292f94c..ae7f55310 100644 --- a/packages/layerchart/src/lib/components/charts/LineChart.svelte +++ b/packages/layerchart/src/lib/components/charts/LineChart.svelte @@ -159,7 +159,7 @@ ? yProp : 'value', value: isVertical ? xProp : yProp, - color: 'var(--color-primary)', + color: 'var(--color-primary, currentColor)', }, ] : seriesProp diff --git a/packages/layerchart/src/lib/components/charts/PieChart.svelte b/packages/layerchart/src/lib/components/charts/PieChart.svelte index 59c5164c8..60453e271 100644 --- a/packages/layerchart/src/lib/components/charts/PieChart.svelte +++ b/packages/layerchart/src/lib/components/charts/PieChart.svelte @@ -372,12 +372,12 @@ : c !== key ? chartData.map((d) => cAccessor(d)) : [ - 'var(--color-primary)', - 'var(--color-secondary)', - 'var(--color-info)', - 'var(--color-success)', - 'var(--color-warning)', - 'var(--color-danger)', + 'var(--color-primary, currentColor)', + 'var(--color-secondary, currentColor)', + 'var(--color-info, currentColor)', + 'var(--color-success, currentColor)', + 'var(--color-warning, currentColor)', + 'var(--color-danger, currentColor)', ]} padding={{ bottom: legend === true || getObjectOrNull(legend)?.placement?.includes('bottom') ? 32 : 0, diff --git a/packages/layerchart/src/lib/components/charts/ScatterChart.svelte b/packages/layerchart/src/lib/components/charts/ScatterChart.svelte index c4d8728bb..c15a46ed9 100644 --- a/packages/layerchart/src/lib/components/charts/ScatterChart.svelte +++ b/packages/layerchart/src/lib/components/charts/ScatterChart.svelte @@ -219,7 +219,7 @@ {yDomain} yNice c={yProp} - cRange={['var(--color-primary)']} + cRange={['var(--color-primary, currentColor)']} padding={defaultChartPadding(axis, legend)} {...restProps} tooltip={tooltip === false From eb71f02fda0b63cbcfee7732b5ab8d58fb421948 Mon Sep 17 00:00:00 2001 From: Sean Lynch Date: Sun, 21 Sep 2025 17:33:57 -0400 Subject: [PATCH 64/77] fix(PieChart): Use schemeObservable10 as css variable fallbacks --- .../src/lib/components/charts/PieChart.svelte | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/layerchart/src/lib/components/charts/PieChart.svelte b/packages/layerchart/src/lib/components/charts/PieChart.svelte index 60453e271..b2adf647b 100644 --- a/packages/layerchart/src/lib/components/charts/PieChart.svelte +++ b/packages/layerchart/src/lib/components/charts/PieChart.svelte @@ -174,9 +174,9 @@ @@ -19,11 +38,34 @@
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +