Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
56f1046
Setup shared state to track selected `renderContext` to use for all e…
techniq Jun 7, 2025
f25d19c
Add `supportedContexts` for all primatives and use `Layer` for exampl…
techniq Jun 7, 2025
c528902
Add `supportedContexts` for all common components (Axis, Grid, etc) a…
techniq Jun 7, 2025
d8e28a7
Add `supportedContexts` for all simplified charts (AreaChart, BarChar…
techniq Jun 7, 2025
d3e72fb
breaking(Spline): Rename `splineRef` to `pathRef`
techniq Jun 7, 2025
2043d3a
fix(Calendar|MonthPath): Support canvas by using `Spline` instead of …
techniq Jun 7, 2025
f09f112
Add `supportedContexts` for all data marks (Area, Bars, etc) and use …
techniq Jun 7, 2025
3db07fd
Add `supportedContexts` for all annotations and use `Layer` for examp…
techniq Jun 7, 2025
86dbda9
Add `supportedContexts` for all interactions and use `Layer` for exam…
techniq Jun 7, 2025
579971b
Add `supportedContexts` for all layout components and use `Layer` for…
techniq Jun 7, 2025
2aba93f
Add `supportedContexts` for all clip path and other components and us…
techniq Jun 7, 2025
bcc2e7c
Fix types. Add changeset
techniq Jun 7, 2025
7053518
Add `supportedContexts` for force examples and a few others
techniq Jun 7, 2025
85b25bb
fix(GeoPath): Do not register with hit canavs unless pointer events (…
techniq Jun 8, 2025
f849a28
Add `supportedContexts` for GeoPath example
techniq Jun 8, 2025
10b2e26
Add `supportedContexts` for GeoPoint example
techniq Jun 8, 2025
5d16dd4
Fix Layer onpointermove type
techniq Jun 8, 2025
34cd3b1
Add `supportedContexts` for more geo examples
techniq Jun 8, 2025
c8e2fd0
Add `supportedContexts` for zoomable map example
techniq Jun 8, 2025
99dc2b8
Add `supportedContexts` for zoomable tile map example
techniq Jun 8, 2025
d45f971
Add `supportedContexts` for timezomes example
techniq Jun 8, 2025
bb90be9
breaking(Blur): Remove children snippet props (not needed and easier …
techniq Jun 8, 2025
79e2539
Add `supportedContexts` for remaining geo examples
techniq Jun 8, 2025
0c6fec9
Cleanup
techniq Jun 8, 2025
442a697
Add `supportedContexts` for remaining examples
techniq Jun 8, 2025
bc39c53
fix(Layer): Pass `onpointermove` via `restProps`
techniq Jun 8, 2025
729f982
Update remaining usage of Svg/Canvas to Layer
techniq Jun 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bumpy-breads-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': patch
---

fix(GeoPath): Do not register with hit canavs unless pointer events (onclick, onpointermove, etc) or tooltipContext are defined
5 changes: 5 additions & 0 deletions .changeset/huge-boats-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': patch
---

docs: Document each component's context support (svg, canvas, html) with interactive toggle
5 changes: 5 additions & 0 deletions .changeset/ninety-ghosts-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': patch
---

breaking(Blur): Remove children snippet props (not needed and easier to support canvas in the future)
5 changes: 5 additions & 0 deletions .changeset/pink-flies-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': patch
---

fix(Calendar|MonthPath): Support canvas by using `Spline` instead of `path`
5 changes: 5 additions & 0 deletions .changeset/tangy-lies-strive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': patch
---

breaking(Spline): Rename `splineRef` to `pathRef`
1 change: 1 addition & 0 deletions packages/layerchart/src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ declare namespace App {
hideUsage?: boolean;
hideTableOfContents?: boolean;
status?: string;
supportedContexts?: Array<'svg' | 'canvas' | 'html'>;
};
}

Expand Down
4 changes: 2 additions & 2 deletions packages/layerchart/src/lib/components/Arc.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -401,13 +401,13 @@
<Spline
pathData={trackArc()}
stroke="none"
bind:splineRef={trackRef}
bind:pathRef={trackRef}
{...extractLayerProps(track, 'arc-track')}
/>
{/if}

<Spline
bind:splineRef={ref}
bind:pathRef={ref}
pathData={arc()}
transform="translate({xOffset}, {yOffset})"
{fill}
Expand Down
8 changes: 5 additions & 3 deletions packages/layerchart/src/lib/components/Blur.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

/**
* The default children snippet which provides
* the id and url for the filter.
* the id for the filter.
*/
children?: Snippet<[{ id: string; url: string }]>;
children?: Snippet;
};
</script>

Expand All @@ -42,7 +42,9 @@

{#if children}
<g filter="url(#{id})" class={layerClass('blur-g')}>
{@render children({ id, url: `url(#${id})` })}
{@render children()}
</g>
{/if}
{:else if children}
{@render children()}
{/if}
4 changes: 2 additions & 2 deletions packages/layerchart/src/lib/components/Connector.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
type = 'rounded',
radius = 20,
curve = curveLinear,
splineRef = $bindable(),
pathRef = $bindable(),
pathData: pathDataProp,
marker,
markerStart,
Expand Down Expand Up @@ -137,7 +137,7 @@

<Spline
pathData={motionPath.current}
bind:splineRef
bind:pathRef
marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
Expand Down
9 changes: 5 additions & 4 deletions packages/layerchart/src/lib/components/GeoPath.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,11 @@
name: 'GeoPath',
render,
events: {
click: _onClick,
pointerenter: _onPointerEnter,
pointermove: _onPointerMove,
pointerleave: _onPointerLeave,
// Only register events if they are defined (so they are not registered with hit canvas unnecessarily)
click: onclick ? _onClick : undefined,
pointerenter: restProps.onpointerenter || tooltipContext ? _onPointerEnter : undefined,
pointermove: restProps.onpointermove || tooltipContext ? _onPointerMove : undefined,
pointerleave: restProps.onpointerleave || tooltipContext ? _onPointerLeave : undefined,
pointerdown: restProps.onpointerdown,
touchmove: restProps.ontouchmove,
},
Expand Down
3 changes: 1 addition & 2 deletions packages/layerchart/src/lib/components/GeoPoint.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script lang="ts" module>
import type { Snippet } from 'svelte';
import type { SVGAttributes } from 'svelte/elements';
import Circle, { type CircleProps, type CirclePropsWithoutHTML } from './Circle.svelte';
import Circle, { type CircleProps } from './Circle.svelte';
import type { Without } from '$lib/utils/types.js';

export type GeoPointPropsWithoutHTML = {
Expand Down
8 changes: 4 additions & 4 deletions packages/layerchart/src/lib/components/GeoSpline.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@
link,
loft = 1.0,
curve = curveNatural,
splineRef: splineRefProp = $bindable(),
pathRef: pathRefProp = $bindable(),
...restProps
}: GeoSplineProps = $props();

let splineRef = $state<SVGPathElement>();
let pathRef = $state<SVGPathElement>();
$effect.pre(() => {
splineRefProp = splineRef;
pathRefProp = pathRef;
});

const geoCtx = getGeoContext();
Expand Down Expand Up @@ -76,7 +76,7 @@
</script>

<Spline
bind:splineRef
bind:pathRef
data={[source, middle, target]}
x={(d) => d[0]}
y={(d) => d[1]}
Expand Down
19 changes: 11 additions & 8 deletions packages/layerchart/src/lib/components/MonthPath.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,33 @@
*
* @bindable
*/
ref?: SVGPathElement;
pathRef?: SVGPathElement;
};

export type MonthPathProps = MonthPathPropsWithoutHTML &
Without<SVGAttributes<SVGPathElement>, MonthPathPropsWithoutHTML>;
// we omit the spline props to avoid conflicts with attribute names since we are
// passing them through to `<Spline />`
Without<SVGAttributes<SVGPathElement>, MonthPathPropsWithoutHTML & SplinePropsWithoutHTML>;
</script>

<script lang="ts">
import { timeWeek, timeYear } from 'd3-time';
import { endOfMonth } from 'date-fns';
import { cls } from '@layerstack/tailwind';
import { layerClass } from '$lib/utils/attributes.js';
import Spline, { type SplinePropsWithoutHTML } from './Spline.svelte';

let {
date,
cellSize: cellSizeProp,
ref: refProp = $bindable(),
pathRef: pathRefProp = $bindable(),
class: className,
...restProps
}: MonthPathProps = $props();

let ref = $state<SVGPathElement>();
let pathRef = $state<SVGPathElement>();
$effect.pre(() => {
refProp = ref;
pathRefProp = pathRef;
});

const cellSize = $derived(
Expand All @@ -68,9 +71,9 @@
`);
</script>

<path
bind:this={ref}
d={pathData}
<Spline
bind:pathRef
{pathData}
fill="none"
class={cls(layerClass('month-path'), 'stroke-surface-content/20', className)}
{...restProps}
Expand Down
22 changes: 11 additions & 11 deletions packages/layerchart/src/lib/components/Spline.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
*
* @bindable
*/
splineRef?: SVGPathElement;
pathRef?: SVGPathElement;

motion?: MotionProp;
} & CommonStyleProps;
Expand Down Expand Up @@ -159,14 +159,14 @@
startContent,
endContent,
opacity,
splineRef: splineRefProp = $bindable(),
pathRef: pathRefProp = $bindable(),
...restProps
}: SplineProps = $props();

let splineRef = $state<SVGPathElement>();
let pathRef = $state<SVGPathElement>();

$effect.pre(() => {
splineRefProp = splineRef;
pathRefProp = pathRef;
});

const markerStart = $derived(markerStartProp ?? marker);
Expand Down Expand Up @@ -331,8 +331,8 @@
easing: typeof draw === 'object' && draw.easing ? draw.easing : cubicInOut,
interpolate() {
return (t: number) => {
const totalLength = splineRef?.getTotalLength() ?? 0;
const point = splineRef?.getPointAtLength(totalLength * t);
const totalLength = pathRef?.getTotalLength() ?? 0;
const point = pathRef?.getPointAtLength(totalLength * t);
return point;
};
},
Expand All @@ -343,10 +343,10 @@
$effect(() => {
if (!startContent && !endContent) return;
d;
if (!splineRef || !splineRef.getTotalLength()) return;
startPoint = splineRef.getPointAtLength(0);
const totalLength = splineRef.getTotalLength();
endPoint.target = splineRef.getPointAtLength(totalLength);
if (!pathRef || !pathRef.getTotalLength()) return;
startPoint = pathRef.getPointAtLength(0);
const totalLength = pathRef.getTotalLength();
endPoint.target = pathRef.getPointAtLength(totalLength);
});

$effect(() => {
Expand Down Expand Up @@ -377,7 +377,7 @@
marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
in:drawTransition|global={typeof draw === 'object' ? draw : undefined}
bind:this={splineRef}
bind:this={pathRef}
/>
<MarkerWrapper id={markerStartId} marker={markerStart} />
<MarkerWrapper id={markerMidId} marker={markerMid} />
Expand Down
10 changes: 6 additions & 4 deletions packages/layerchart/src/lib/components/layout/Layer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@

export type CanvasLayerProps = {
type: 'canvas';
} & Omit<ComponentProps<typeof Canvas>, 'type'>;
} & Omit<ComponentProps<typeof Canvas>, 'type' | 'onpointermove'>;

export type HtmlLayerProps = {
type: 'html';
} & Omit<ComponentProps<typeof Html>, 'type'>;
} & Omit<ComponentProps<typeof Html>, 'type' | 'onpointermove'>;

export type SvgLayerProps = {
type: 'svg';
} & Omit<ComponentProps<typeof Svg>, 'type'>;
} & Omit<ComponentProps<typeof Svg>, 'type' | 'onpointermove'>;

export type LayerProps = CanvasLayerProps | HtmlLayerProps | SvgLayerProps;
export type LayerProps = (CanvasLayerProps | HtmlLayerProps | SvgLayerProps) & {
onpointermove?: (e: PointerEvent) => void;
};
</script>

<script lang="ts">
Expand Down
2 changes: 2 additions & 0 deletions packages/layerchart/src/lib/utils/canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export function getComputedStyles(
if (styles) {
Object.assign(svg.style, styles);
}
// Make sure `<svg>` is not visible
svg.style.display = 'none';

if (classes) {
svg.setAttribute(
Expand Down
40 changes: 34 additions & 6 deletions packages/layerchart/src/routes/docs/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@
mdiLink,
} from '@mdi/js';

import { ApiDocs, Button, Dialog, Icon, ListItem, TableOfContents } from 'svelte-ux';
import {
ApiDocs,
Button,
Dialog,
Icon,
ListItem,
TableOfContents,
ToggleGroup,
ToggleOption,
} from 'svelte-ux';

import { MediaQueryPresets } from '@layerstack/svelte-state';
import { cls } from '@layerstack/tailwind';
Expand All @@ -24,6 +33,7 @@
import Code from '$lib/docs/Code.svelte';
import ViewSourceButton from '$lib/docs/ViewSourceButton.svelte';
import { page } from '$app/state';
import { shared } from './shared.svelte.js';

const { children } = $props();

Expand Down Expand Up @@ -51,6 +61,7 @@
pageSource,
api,
status,
supportedContexts,
} = $derived(page.data.meta ?? {});

const { xlScreen } = new MediaQueryPresets();
Expand Down Expand Up @@ -96,11 +107,28 @@
</div>
</div>

<div class="text-2xl font-bold">
{#if type === 'examples' || type === 'tools'}
{title.replace(/([a-z])([A-Z])/g, '$1 $2')}
{:else}
{title}
<div class="flex items-center gap-4">
<span class="text-2xl font-bold">
{#if type === 'examples' || type === 'tools'}
{title.replace(/([a-z])([A-Z])/g, '$1 $2')}
{:else}
{title}
{/if}
</span>

{#if supportedContexts}
<ToggleGroup
bind:value={shared.renderContext}
variant="fill"
color="primary"
inset
gap="px"
size="sm"
>
{#each supportedContexts as context}
<ToggleOption value={context}>{toTitleCase(context)}</ToggleOption>
{/each}
</ToggleGroup>
{/if}

{#if status}
Expand Down
Loading