layerchart 2.0.0-next.6 → 2.0.0-next.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -844,12 +844,12 @@
844
844
  if (verbose === true) {
845
845
  if (width <= 0 && isMounted === true) {
846
846
  console.warn(
847
- '[LayerChart] Target div has zero or negative width. Did you forget to set an explicit width in CSS on the container?'
847
+ `[LayerChart] Target div has zero or negative width (${width}). Did you forget to set an explicit width in CSS on the container?`
848
848
  );
849
849
  }
850
850
  if (height <= 0 && isMounted === true) {
851
851
  console.warn(
852
- '[LayerChart] Target div has zero or negative height. Did you forget to set an explicit height in CSS on the container?'
852
+ `[LayerChart] Target div has zero or negative height (${height}). Did you forget to set an explicit height in CSS on the container?`
853
853
  );
854
854
  }
855
855
  }
@@ -102,6 +102,7 @@
102
102
  fx = cx,
103
103
  fy = cy,
104
104
  r = '50%',
105
+ // fr = '0%'; // TODO: Svelte / Typescript does not know `<radialRadiant fr="...">`
105
106
  spreadMethod = 'pad',
106
107
  transform = undefined,
107
108
  units = 'objectBoundingBox',
@@ -111,9 +112,6 @@
111
112
  ...restProps
112
113
  }: RadialGradientProps = $props();
113
114
 
114
- // TODO: Svelte / Typescript does not know `<radialRadiant fr="...">`
115
- // export let fr = '0%';
116
-
117
115
  const ctx = getChartContext();
118
116
 
119
117
  const renderCtx = getRenderContext();
@@ -351,8 +351,8 @@
351
351
 
352
352
  $effect(() => {
353
353
  if (!draw) return;
354
- [tweenedState.current];
355
354
  // Anytime the path data changes, redraw
355
+ [pathData, data, ctx.data];
356
356
  key = Symbol();
357
357
  });
358
358
  </script>
@@ -264,8 +264,8 @@
264
264
  placement: 'bottom',
265
265
  variant: 'swatches',
266
266
  onclick: (e, item) => {
267
- selectedKeys.toggleSelected(item.value);
268
- selectedSeries.toggleSelected(item.value);
267
+ selectedKeys.toggle(item.value);
268
+ selectedSeries.toggle(item.value);
269
269
  },
270
270
  onpointerenter: (e, item) => (highlightKey.current = item.value),
271
271
  onpointerleave: (e) => (highlightKey.current = null),
@@ -84,7 +84,7 @@
84
84
 
85
85
  <script lang="ts" generics="TData">
86
86
  import { onMount, type ComponentProps } from 'svelte';
87
- import { scaleBand, scaleLinear } from 'd3-scale';
87
+ import { scaleBand, scaleLinear, scaleTime } from 'd3-scale';
88
88
  import { stack, stackOffsetDiverging, stackOffsetExpand, stackOffsetNone } from 'd3-shape';
89
89
  import { format } from '@layerstack/utils';
90
90
  import { cls } from '@layerstack/tailwind';
@@ -109,7 +109,7 @@
109
109
  import { asAny } from '../../utils/types.js';
110
110
  import type { Insets } from '../../utils/rect.svelte.js';
111
111
  import type { SeriesData, SimplifiedChartProps, SimplifiedChartPropsObject } from './types.js';
112
- import type { AnyScale } from '../../utils/scales.svelte.js';
112
+ import { isScaleTime, type AnyScale } from '../../utils/scales.svelte.js';
113
113
  import { createLegendProps, SeriesState } from './utils.svelte.js';
114
114
  import { setTooltipMetaContext } from '../tooltip/tooltipMetaContext.js';
115
115
  import DefaultTooltip from './DefaultTooltip.svelte';
@@ -171,15 +171,56 @@
171
171
  const isStackSeries = $derived(seriesLayout.startsWith('stack'));
172
172
  const isGroupSeries = $derived(seriesLayout === 'group');
173
173
 
174
+ const chartData: Array<TData & { stackData?: any }> = $derived.by(() => {
175
+ let _chartData = (
176
+ seriesState.allSeriesData.length ? seriesState.allSeriesData : chartDataArray(data)
177
+ ) as Array<TData & { stackData?: any }>;
178
+ if (isStackSeries) {
179
+ const seriesKeys = seriesState.visibleSeries.map((s) => s.key);
180
+
181
+ const offset =
182
+ seriesLayout === 'stackExpand'
183
+ ? stackOffsetExpand
184
+ : seriesLayout === 'stackDiverging'
185
+ ? stackOffsetDiverging
186
+ : stackOffsetNone;
187
+ const stackData = stack()
188
+ .keys(seriesKeys)
189
+ .value((d, key) => {
190
+ const s = series.find((d) => d.key === key)!;
191
+ return accessor(s.value ?? s.key)(d as any);
192
+ })
193
+ .offset(offset)(chartDataArray(data)) as any[];
194
+
195
+ _chartData = _chartData.map((d, i) => {
196
+ return {
197
+ ...d,
198
+ stackData: stackData.map((sd) => sd[i]),
199
+ };
200
+ });
201
+ }
202
+ return _chartData;
203
+ });
204
+
174
205
  const xScale = $derived(
175
- xScaleProp ?? (isVertical ? scaleBand().padding(bandPadding) : scaleLinear())
206
+ xScaleProp ??
207
+ (isVertical
208
+ ? scaleBand().padding(bandPadding)
209
+ : accessor(xProp)(chartData[0]) instanceof Date // TODO: also check for Array<Date> instances (ex. x={['start', 'end']})
210
+ ? scaleTime()
211
+ : scaleLinear())
176
212
  );
177
- const xBaseline = $derived(isVertical ? undefined : 0);
213
+ const xBaseline = $derived(isVertical || isScaleTime(xScale) ? undefined : 0);
178
214
 
179
215
  const yScale = $derived(
180
- yScaleProp ?? (isVertical ? scaleLinear() : scaleBand().padding(bandPadding))
216
+ yScaleProp ??
217
+ (isVertical
218
+ ? accessor(yProp)(chartData[0]) instanceof Date // TODO: also check for Array<Date> instances (ex. y={['start', 'end']})
219
+ ? scaleTime()
220
+ : scaleLinear()
221
+ : scaleBand().padding(bandPadding))
181
222
  );
182
- const yBaseline = $derived(isVertical ? 0 : undefined);
223
+ const yBaseline = $derived(isVertical || isScaleTime(yScale) ? 0 : undefined);
183
224
 
184
225
  const x1Scale = $derived(
185
226
  isGroupSeries && isVertical ? scaleBand().padding(groupPadding) : undefined
@@ -214,37 +255,6 @@
214
255
  return d && typeof d === 'object' && 'stackData' in d;
215
256
  }
216
257
 
217
- const chartData: Array<TData & { stackData?: any }> = $derived.by(() => {
218
- let _chartData = (
219
- seriesState.allSeriesData.length ? seriesState.allSeriesData : chartDataArray(data)
220
- ) as Array<TData & { stackData?: any }>;
221
- if (isStackSeries) {
222
- const seriesKeys = seriesState.visibleSeries.map((s) => s.key);
223
-
224
- const offset =
225
- seriesLayout === 'stackExpand'
226
- ? stackOffsetExpand
227
- : seriesLayout === 'stackDiverging'
228
- ? stackOffsetDiverging
229
- : stackOffsetNone;
230
- const stackData = stack()
231
- .keys(seriesKeys)
232
- .value((d, key) => {
233
- const s = series.find((d) => d.key === key)!;
234
- return accessor(s.value ?? s.key)(d as any);
235
- })
236
- .offset(offset)(chartDataArray(data)) as any[];
237
-
238
- _chartData = _chartData.map((d, i) => {
239
- return {
240
- ...d,
241
- stackData: stackData.map((sd) => sd[i]),
242
- };
243
- });
244
- }
245
- return _chartData;
246
- });
247
-
248
258
  function getBarsProps(s: SeriesData<TData, typeof Bars>, i: number): ComponentProps<typeof Bars> {
249
259
  const isFirst = i == 0;
250
260
  const isLast = i == seriesState.visibleSeries.length - 1;
@@ -278,7 +288,12 @@
278
288
  y: isVertical ? valueAccessor : undefined,
279
289
  x1: isVertical && isGroupSeries ? (d) => s.value ?? s.key : undefined,
280
290
  y1: !isVertical && isGroupSeries ? (d) => s.value ?? s.key : undefined,
281
- rounded: isStackLayout && i !== seriesState.visibleSeries.length - 1 ? 'none' : 'edge',
291
+ rounded:
292
+ isStackLayout && i !== seriesState.visibleSeries.length - 1
293
+ ? 'none'
294
+ : Array.isArray(xProp) || Array.isArray(yProp)
295
+ ? 'all'
296
+ : 'edge',
282
297
  radius: 4,
283
298
  strokeWidth: 1,
284
299
  insets: stackInsets,
@@ -281,9 +281,9 @@
281
281
  placement: 'bottom',
282
282
  variant: 'swatches',
283
283
  onclick: (e, item) => {
284
- selectedKeys.toggleSelected(item.value);
284
+ selectedKeys.toggle(item.value);
285
285
  // TODO: investigate
286
- // selectedSeries.toggleSelected(item.value);
286
+ // selectedSeries.toggle(item.value);
287
287
  },
288
288
  onpointerenter: (e, item) => (highlightKey.current = item.value),
289
289
  onpointerleave: (e) => (highlightKey.current = null),
@@ -44,7 +44,7 @@ export function createLegendProps(opts) {
44
44
  tickFormat: (key) => opts.seriesState.series.find((s) => s.key === key)?.label ?? key,
45
45
  placement: 'bottom',
46
46
  variant: 'swatches',
47
- onclick: (_, item) => opts.seriesState.selectedSeries.toggleSelected(item.value),
47
+ onclick: (_, item) => opts.seriesState.selectedSeries.toggle(item.value),
48
48
  onpointerenter: (_, item) => (opts.seriesState.highlightKey.current = item.value),
49
49
  onpointerleave: () => (opts.seriesState.highlightKey.current = null),
50
50
  ...opts.props,
@@ -64,6 +64,13 @@
64
64
  */
65
65
  ignoreTransform?: boolean;
66
66
 
67
+ /**
68
+ * Disable the hit canvas (useful when animations are playing)
69
+ *
70
+ * @default false
71
+ */
72
+ disableHitCanvas?: boolean;
73
+
67
74
  /**
68
75
  * Show the hit canvas for debugging purposes.
69
76
  *
@@ -144,13 +151,13 @@
144
151
  import { onMount, untrack, type Snippet } from 'svelte';
145
152
  import { cls } from '@layerstack/tailwind';
146
153
  import { Logger, localPoint } from '@layerstack/utils';
147
- import { darkColorScheme } from '@layerstack/svelte-stores';
154
+ import { MediaQueryPresets } from '@layerstack/svelte-state';
148
155
 
149
156
  import { setRenderContext } from '../Chart.svelte';
150
157
  import { getTransformContext } from '../TransformContext.svelte';
151
158
  import { getPixelColor, scaleCanvas, type ComputedStylesOptions } from '../../utils/canvas.js';
152
159
  import { getColorStr, rgbColorGenerator } from '../../utils/color.js';
153
- import { Context } from 'runed';
160
+ import { Context, useMutationObserver, watch } from 'runed';
154
161
  import type {
155
162
  HTMLCanvasAttributes,
156
163
  MouseEventHandler,
@@ -171,6 +178,7 @@
171
178
  fallback,
172
179
  center = false,
173
180
  ignoreTransform = false,
181
+ disableHitCanvas = false,
174
182
  class: className,
175
183
  children,
176
184
  onclick,
@@ -256,6 +264,23 @@
256
264
  * end HitCanvas
257
265
  */
258
266
 
267
+ // Invalidate/redraw if color scheme changes, either via browser `prefers-color-scheme` (including emulation) or by changing `<html class="dark">` or `<html data-theme="...">`
268
+ const { dark } = new MediaQueryPresets();
269
+ watch(
270
+ () => dark.current,
271
+ () => {
272
+ canvasContext.invalidate();
273
+ }
274
+ );
275
+ useMutationObserver(
276
+ () => document.documentElement,
277
+ () => canvasContext.invalidate(),
278
+ {
279
+ attributes: true,
280
+ attributeFilter: ['class', 'data-theme'],
281
+ }
282
+ );
283
+
259
284
  onMount(() => {
260
285
  context = ref?.getContext('2d', { willReadFrequently }) as CanvasRenderingContext2D;
261
286
 
@@ -263,22 +288,7 @@
263
288
  willReadFrequently: false, // Explicitly set to `false` to resolve pixel artifacts between fill and stroke with the same color (issue #372)
264
289
  }) as CanvasRenderingContext2D;
265
290
 
266
- // Invalidate/redraw if color scheme changes, either via browser `prefers-color-scheme` (including emulation) or by changing `<html class="dark">` or `<html data-theme="...">`
267
- darkColorScheme.subscribe(() => {
268
- canvasContext.invalidate();
269
- });
270
-
271
- const observer = new MutationObserver(() => {
272
- canvasContext.invalidate();
273
- });
274
-
275
- observer.observe(document.documentElement, {
276
- attributes: true,
277
- attributeFilter: ['class', 'data-theme'],
278
- });
279
-
280
291
  return () => {
281
- observer.disconnect();
282
292
  if (frameId) {
283
293
  cancelAnimationFrame(frameId);
284
294
  }
@@ -366,7 +376,7 @@
366
376
  for (const c of nonRetainStateComponents) {
367
377
  const componentHasEvents = c.events && Object.values(c.events).filter((d) => d).length > 0;
368
378
 
369
- if (componentHasEvents && !inactiveMoving && !transformCtx.dragging) {
379
+ if (componentHasEvents && !inactiveMoving && !transformCtx.dragging && !disableHitCanvas) {
370
380
  const color = getColorStr(colorGenerator.next().value);
371
381
  const styleOverrides = { styles: { fill: color, stroke: color, _fillOpacity: 0.1 } };
372
382
 
@@ -55,6 +55,12 @@ export type CanvasPropsWithoutHTML = {
55
55
  * @default false
56
56
  */
57
57
  ignoreTransform?: boolean;
58
+ /**
59
+ * Disable the hit canvas (useful when animations are playing)
60
+ *
61
+ * @default false
62
+ */
63
+ disableHitCanvas?: boolean;
58
64
  /**
59
65
  * Show the hit canvas for debugging purposes.
60
66
  *
@@ -2,6 +2,8 @@
2
2
  import { mdiInformation } from '@mdi/js';
3
3
  import { Icon } from 'svelte-ux';
4
4
  import { cls } from '@layerstack/tailwind';
5
+
6
+ const { children } = $props();
5
7
  </script>
6
8
 
7
9
  <div
@@ -11,5 +13,5 @@
11
13
  )}
12
14
  >
13
15
  <Icon data={mdiInformation} class="text-primary" />
14
- <slot />
16
+ {@render children()}
15
17
  </div>
@@ -1,20 +1,5 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const Blockquote: $$__sveltets_2_IsomorphicComponent<any, {
15
- [evt: string]: CustomEvent<any>;
16
- }, {
17
- default: {};
18
- }, {}, string>;
19
- type Blockquote = InstanceType<typeof Blockquote>;
1
+ declare const Blockquote: import("svelte").Component<{
2
+ children: any;
3
+ }, {}, "">;
4
+ type Blockquote = ReturnType<typeof Blockquote>;
20
5
  export default Blockquote;
@@ -4,20 +4,28 @@
4
4
  import { CopyButton } from 'svelte-ux';
5
5
  import { cls } from '@layerstack/tailwind';
6
6
 
7
- export let source: string | null = null;
8
- export let language = 'svelte';
9
- export let highlightedSource = source
10
- ? Prism.highlight(source, Prism.languages[language] ?? Prism.languages.text, language)
11
- : '';
12
-
13
- export let classes: {
14
- root?: string;
15
- pre?: string;
16
- code?: string;
17
- } = {};
7
+ const {
8
+ source = null,
9
+ language = 'svelte',
10
+ highlightedSource = source
11
+ ? Prism.highlight(source, Prism.languages[language] ?? Prism.languages.text, language)
12
+ : '',
13
+ classes = {},
14
+ class: className,
15
+ }: {
16
+ source: string | null;
17
+ language?: string;
18
+ highlightedSource?: string;
19
+ classes?: {
20
+ root?: string;
21
+ pre?: string;
22
+ code?: string;
23
+ };
24
+ class?: string;
25
+ } = $props();
18
26
  </script>
19
27
 
20
- <div class={cls('Code', 'rounded-sm', classes.root, $$props.class)}>
28
+ <div class={cls('Code', 'rounded-sm', classes.root, className)}>
21
29
  {#if source}
22
30
  <div class="relative">
23
31
  <pre
@@ -1,29 +1,15 @@
1
1
  import 'prism-svelte';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
12
- };
13
- z_$$bindings?: Bindings;
14
- }
15
- declare const Code: $$__sveltets_2_IsomorphicComponent<{
16
- [x: string]: any;
17
- source?: string | null | undefined;
18
- language?: string | undefined;
19
- highlightedSource?: string | undefined;
2
+ type $$ComponentProps = {
3
+ source: string | null;
4
+ language?: string;
5
+ highlightedSource?: string;
20
6
  classes?: {
21
7
  root?: string;
22
8
  pre?: string;
23
9
  code?: string;
24
- } | undefined;
25
- }, {
26
- [evt: string]: CustomEvent<any>;
27
- }, {}, {}, string>;
28
- type Code = InstanceType<typeof Code>;
10
+ };
11
+ class?: string;
12
+ };
13
+ declare const Code: import("svelte").Component<$$ComponentProps, {}, "">;
14
+ type Code = ReturnType<typeof Code>;
29
15
  export default Code;
@@ -1,5 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { SectionDivider } from 'svelte-ux';
3
+
4
+ let { children, ...restProps } = $props();
3
5
  </script>
4
6
 
5
7
  <!--
@@ -9,6 +11,6 @@
9
11
  - Maybe possible to set/get props from markdown/mdsvex
10
12
  - Example: `#API { id: 'api' }
11
13
  -->
12
- <SectionDivider {...$$restProps}>
13
- <slot />
14
+ <SectionDivider {...restProps}>
15
+ {@render children()}
14
16
  </SectionDivider>
@@ -1,29 +1,5 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: Props & {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
15
- default: any;
16
- } ? Props extends Record<string, never> ? any : {
17
- children?: any;
18
- } : {});
19
- declare const Header1: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
20
- [x: string]: any;
21
- }, {
22
- default: {};
23
- }>, {
24
- [evt: string]: CustomEvent<any>;
25
- }, {
26
- default: {};
27
- }, {}, string>;
28
- type Header1 = InstanceType<typeof Header1>;
1
+ declare const Header1: import("svelte").Component<{
2
+ children: any;
3
+ } & Record<string, any>, {}, "">;
4
+ type Header1 = ReturnType<typeof Header1>;
29
5
  export default Header1;
@@ -1,12 +1,20 @@
1
1
  <script lang="ts">
2
+ import { type ComponentProps } from 'svelte';
2
3
  import JsonTree from 'svelte-json-tree';
3
4
  import { cls } from '@layerstack/tailwind';
4
5
 
5
- export let value: any;
6
- export let defaultExpandedPaths = ['$'];
6
+ const {
7
+ value,
8
+ defaultExpandedPaths = ['$'],
9
+ class: className,
10
+ }: {
11
+ value: ComponentProps<JsonTree>['value'];
12
+ defaultExpandedPaths?: ComponentProps<JsonTree>['defaultExpandedPaths'];
13
+ class?: string;
14
+ } = $props();
7
15
  </script>
8
16
 
9
- <div class={cls('overflow-auto px-4 py-2 bg-[#1e1e1e]', $$props.class)}>
17
+ <div class={cls('overflow-auto px-4 py-2 bg-[#1e1e1e]', className)}>
10
18
  <JsonTree
11
19
  {value}
12
20
  {defaultExpandedPaths}
@@ -1,22 +1,10 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: Props & {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const Json: $$__sveltets_2_IsomorphicComponent<{
15
- [x: string]: any;
16
- value: any;
17
- defaultExpandedPaths?: string[] | undefined;
18
- }, {
19
- [evt: string]: CustomEvent<any>;
20
- }, {}, {}, string>;
21
- type Json = InstanceType<typeof Json>;
1
+ import { type ComponentProps } from 'svelte';
2
+ import JsonTree from 'svelte-json-tree';
3
+ type $$ComponentProps = {
4
+ value: ComponentProps<JsonTree>['value'];
5
+ defaultExpandedPaths?: ComponentProps<JsonTree>['defaultExpandedPaths'];
6
+ class?: string;
7
+ };
8
+ declare const Json: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type Json = ReturnType<typeof Json>;
22
10
  export default Json;
@@ -1,4 +1,4 @@
1
- <script context="module">
1
+ <script module>
2
2
  // Custom components: https://mdsvex.com/docs#custom-components
3
3
  import blockquote from './Blockquote.svelte';
4
4
  import a from './Link.svelte';
@@ -8,11 +8,14 @@
8
8
  </script>
9
9
 
10
10
  <script lang="ts">
11
- // frontmatter: https://mdsvex.com/docs#frontmatter-1
12
- // export let name = undefined;
13
- // export let sourceUrl = undefined;
14
- // export let docUrl = undefined;
15
- // export let description = undefined;
11
+ let {
12
+ // frontmatter: https://mdsvex.com/docs#frontmatter-1
13
+ // name,
14
+ // sourceUrl,
15
+ // docUrl,
16
+ // description,
17
+ children,
18
+ } = $props();
16
19
  </script>
17
20
 
18
- <slot />
21
+ {@render children()}
@@ -1,23 +1,8 @@
1
1
  import blockquote from './Blockquote.svelte';
2
2
  import a from './Link.svelte';
3
3
  export { a, blockquote };
4
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
5
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
6
- $$bindings?: Bindings;
7
- } & Exports;
8
- (internal: unknown, props: {
9
- $$events?: Events;
10
- $$slots?: Slots;
11
- }): Exports & {
12
- $set?: any;
13
- $on?: any;
14
- };
15
- z_$$bindings?: Bindings;
16
- }
17
- declare const Layout: $$__sveltets_2_IsomorphicComponent<any, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {
20
- default: {};
21
- }, {}, string>;
22
- type Layout = InstanceType<typeof Layout>;
4
+ declare const Layout: import("svelte").Component<{
5
+ children: any;
6
+ }, {}, "">;
7
+ type Layout = ReturnType<typeof Layout>;
23
8
  export default Layout;
@@ -1,5 +1,9 @@
1
+ <script lang="ts">
2
+ let { children, ...restProps } = $props();
3
+ </script>
4
+
1
5
  <!-- href provided by markdown/mdsvex -->
2
- <!-- svelte-ignore a11y-missing-attribute -->
3
- <a class="text-primary font-medium" {...$$restProps}>
4
- <slot />
6
+ <!-- svelte-ignore a11y_missing_attribute -->
7
+ <a class="text-primary font-medium" {...restProps}>
8
+ {@render children()}
5
9
  </a>
@@ -1,39 +1,5 @@
1
+ declare const Link: import("svelte").Component<{
2
+ children: any;
3
+ } & Record<string, any>, {}, "">;
4
+ type Link = ReturnType<typeof Link>;
1
5
  export default Link;
2
- type Link = SvelteComponent<$$__sveltets_2_PropsWithChildren<{
3
- [x: string]: any;
4
- }, {
5
- default: {};
6
- }>, {
7
- [evt: string]: CustomEvent<any>;
8
- }, {
9
- default: {};
10
- }> & {
11
- $$bindings?: string | undefined;
12
- };
13
- declare const Link: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
14
- [x: string]: any;
15
- }, {
16
- default: {};
17
- }>, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {
20
- default: {};
21
- }, {}, string>;
22
- type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
23
- default: any;
24
- } ? Props extends Record<string, never> ? any : {
25
- children?: any;
26
- } : {});
27
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
28
- new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
29
- $$bindings?: Bindings;
30
- } & Exports;
31
- (internal: unknown, props: Props & {
32
- $$events?: Events;
33
- $$slots?: Slots;
34
- }): Exports & {
35
- $set?: any;
36
- $on?: any;
37
- };
38
- z_$$bindings?: Bindings;
39
- }
@@ -1,26 +1,26 @@
1
1
  <script lang="ts">
2
2
  import { SelectField, Switch } from 'svelte-ux';
3
3
 
4
- export let doubleScale = devicePixelRatio > 1;
4
+ let { doubleScale = $bindable(devicePixelRatio > 1), serviceUrl = $bindable() } = $props();
5
5
 
6
6
  // TODO: Access via context, or possibly global state
7
7
  const ACCESS_TOKEN =
8
8
  'pk.eyJ1IjoidGVjaG5pcTM1IiwiYSI6ImNsZTR5cDd0ZjAyNm8zdnFvczhzdnFpcXkifQ.-LAr8sl5BZ3y-H0pDyD1qA';
9
9
 
10
10
  // https://docs.mapbox.com/api/maps/styles/
11
- $: mapboxv1 = (style: string) => (x: number, y: number, z: number) => {
11
+ const mapboxv1 = $derived((style: string) => (x: number, y: number, z: number) => {
12
12
  return `https://api.mapbox.com/styles/v1/mapbox/${style}/tiles/${z}/${x}/${y}${
13
13
  doubleScale ? '@2x' : ''
14
14
  }?access_token=${ACCESS_TOKEN}`;
15
- };
15
+ });
16
16
 
17
17
  // https://docs.mapbox.com/api/maps/raster-tiles/
18
18
  // https://docs.mapbox.com/data/tilesets/reference/mapbox-streets-v8/
19
- $: mapboxv4 = (tileset: string) => (x: number, y: number, z: number) => {
19
+ const mapboxv4 = $derived((tileset: string) => (x: number, y: number, z: number) => {
20
20
  return `https://${'abc'[Math.abs(x + y) % 3]}.tiles.mapbox.com/v4/${tileset}/${z}/${x}/${y}${
21
21
  doubleScale ? '@2x' : ''
22
22
  }.png?access_token=${ACCESS_TOKEN}`;
23
- };
23
+ });
24
24
 
25
25
  // https://apps.nationalmap.gov/services/
26
26
  const nationalmap = (tileset: string) => (x: number, y: number, z: number) => {
@@ -54,7 +54,7 @@
54
54
  return `https://${s}.tile.opentopomap.org/${z}/${x}/${y}.png`;
55
55
  };
56
56
 
57
- $: services = {
57
+ const services = $derived<Record<string, Record<string, Function>>>({
58
58
  'mapbox v1': {
59
59
  'streets-v11': mapboxv1('streets-v11'),
60
60
  'light-v10': mapboxv1('light-v10'),
@@ -100,24 +100,25 @@
100
100
  // 'ArcGIS Vector': {
101
101
  // 'Community Map', url: arcgisVector('World_Basemap_v2'),
102
102
  // }
103
- } as Record<string, Record<string, Function>>;
104
-
105
- $: serviceOptions = Object.entries(services).flatMap(([group, service]) => {
106
- return Object.entries(service).map(([label, value]) => {
107
- return { label, value: `${group}:${label}`, group, serviceUrl: value };
108
- });
109
103
  });
110
104
 
111
- $: defaultServiceUrl = services['mapbox v1']['streets-v11'];
112
- export let serviceUrl = defaultServiceUrl;
105
+ const serviceOptions = $derived(
106
+ Object.entries(services).flatMap(([group, service]) => {
107
+ return Object.entries(service).map(([label, value]) => {
108
+ return { label, value: `${group}:${label}`, group, serviceUrl: value };
109
+ });
110
+ })
111
+ );
113
112
 
114
- $: getServiceUrl = (option: string) => {
113
+ const getServiceUrl = $derived((option: string) => {
115
114
  const [selectedService, selectedTileset] = selected.split(':');
116
115
  return services[selectedService][selectedTileset];
117
- };
116
+ });
118
117
 
119
- let selected = 'mapbox v1:streets-v11';
120
- $: serviceUrl = getServiceUrl(selected);
118
+ let selected = $state('mapbox v1:streets-v11');
119
+ $effect(() => {
120
+ serviceUrl = getServiceUrl(selected);
121
+ });
121
122
  </script>
122
123
 
123
124
  <SelectField
@@ -128,7 +129,7 @@
128
129
  toggleIcon={null}
129
130
  stepper
130
131
  >
131
- <div slot="append" on:click|stopPropagation role="none">
132
+ <div slot="append" onclick={(e) => e.stopPropagation()} role="none">
132
133
  <div class="text-[10px] text-surface-content/50 text-center">2x</div>
133
134
  <Switch bind:checked={doubleScale} size="md" />
134
135
  </div>
@@ -1,23 +1,6 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: Props & {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const TilesetField: $$__sveltets_2_IsomorphicComponent<{
15
- doubleScale?: boolean;
16
- serviceUrl?: Function;
17
- }, {
18
- click: MouseEvent;
19
- } & {
20
- [evt: string]: CustomEvent<any>;
21
- }, {}, {}, string>;
22
- type TilesetField = InstanceType<typeof TilesetField>;
1
+ declare const TilesetField: import("svelte").Component<{
2
+ doubleScale?: any;
3
+ serviceUrl?: any;
4
+ }, {}, "doubleScale" | "serviceUrl">;
5
+ type TilesetField = ReturnType<typeof TilesetField>;
23
6
  export default TilesetField;
@@ -5,10 +5,13 @@
5
5
 
6
6
  import Code from './Code.svelte';
7
7
 
8
- export let label: string;
9
- export let source: string | undefined = undefined;
10
- export let href: string | undefined = undefined;
11
- export let icon: ComponentProps<Button>['icon'];
8
+ const {
9
+ label,
10
+ source,
11
+ href,
12
+ icon,
13
+ }: { label: string; source?: string; href?: string; icon: ComponentProps<Button>['icon'] } =
14
+ $props();
12
15
  </script>
13
16
 
14
17
  {#if source}
@@ -1,25 +1,11 @@
1
1
  import type { ComponentProps } from 'svelte';
2
2
  import { Button } from 'svelte-ux';
3
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
4
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
5
- $$bindings?: Bindings;
6
- } & Exports;
7
- (internal: unknown, props: Props & {
8
- $$events?: Events;
9
- $$slots?: Slots;
10
- }): Exports & {
11
- $set?: any;
12
- $on?: any;
13
- };
14
- z_$$bindings?: Bindings;
15
- }
16
- declare const ViewSourceButton: $$__sveltets_2_IsomorphicComponent<{
3
+ type $$ComponentProps = {
17
4
  label: string;
18
- source?: string | undefined;
19
- href?: string | undefined;
20
- icon: ComponentProps<Button>["icon"];
21
- }, {
22
- [evt: string]: CustomEvent<any>;
23
- }, {}, {}, string>;
24
- type ViewSourceButton = InstanceType<typeof ViewSourceButton>;
5
+ source?: string;
6
+ href?: string;
7
+ icon: ComponentProps<Button>['icon'];
8
+ };
9
+ declare const ViewSourceButton: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type ViewSourceButton = ReturnType<typeof ViewSourceButton>;
25
11
  export default ViewSourceButton;
@@ -1,4 +1,4 @@
1
- import { type ScaleBand } from 'd3-scale';
1
+ import { type ScaleBand, type ScaleTime } from 'd3-scale';
2
2
  import { type MotionProp, type MotionOptions, type SpringOptions, type TweenOptions } from './motion.svelte.js';
3
3
  import type { Accessor } from './common.js';
4
4
  import type { OnlyObjects } from './types.js';
@@ -23,6 +23,8 @@ export type AnyScale<TInput extends SingleDomainType = any, TOutput extends Sing
23
23
  thresholds?: () => TInput[];
24
24
  quantiles?: () => TInput[];
25
25
  };
26
+ export declare function isScaleBand(scale: AnyScale<any, any>): scale is ScaleBand<any>;
27
+ export declare function isScaleTime(scale: AnyScale<any, any>): scale is ScaleTime<any, any>;
26
28
  export declare function getRange(scale: any): any[];
27
29
  export type SingleDomainType = number | string | Date | null | undefined;
28
30
  export type DomainType = (number | string | Date | null | undefined)[] | null | undefined;
@@ -45,7 +47,6 @@ export declare function createMotionScale<Domain, Range>(scale: AnyScale, motion
45
47
  * https://gist.github.com/LuisSevillano/d53a1dc529eef518780c6df99613e2fd
46
48
  */
47
49
  export declare function scaleBandInvert(scale: ScaleBand<any>): (value: number) => any;
48
- export declare function isScaleBand(scale: AnyScale<any, any>): scale is ScaleBand<any>;
49
50
  /**
50
51
  * Generic way to invert a scale value, handling scaleBand and continuous scales (linear, time, etc).
51
52
  * Useful to map mouse event location (x,y) to domain value
@@ -5,6 +5,13 @@ import { Spring, Tween } from 'svelte/motion';
5
5
  function isAnyScale(scale) {
6
6
  return typeof scale === 'function' && typeof scale.range === 'function';
7
7
  }
8
+ export function isScaleBand(scale) {
9
+ return typeof scale.bandwidth === 'function';
10
+ }
11
+ export function isScaleTime(scale) {
12
+ const domain = scale.domain();
13
+ return domain[0] instanceof Date || domain[1] instanceof Date;
14
+ }
8
15
  export function getRange(scale) {
9
16
  if (isAnyScale(scale)) {
10
17
  return scale.range();
@@ -54,9 +61,6 @@ export function scaleBandInvert(scale) {
54
61
  return domain[Math.max(0, Math.min(index, domain.length - 1))];
55
62
  };
56
63
  }
57
- export function isScaleBand(scale) {
58
- return typeof scale.bandwidth === 'function';
59
- }
60
64
  /**
61
65
  * Generic way to invert a scale value, handling scaleBand and continuous scales (linear, time, etc).
62
66
  * Useful to map mouse event location (x,y) to domain value
@@ -1,7 +1,7 @@
1
1
  import { timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeMillisecond, } from 'd3-time';
2
2
  import { format } from 'date-fns';
3
3
  import { formatDate, PeriodType, getDuration, fail } from '@layerstack/utils';
4
- import { isScaleBand } from './scales.svelte.js';
4
+ import { isScaleBand, isScaleTime } from './scales.svelte.js';
5
5
  // TODO: Use PeriodType along with Duration to format (and possibly select intervals)
6
6
  const majorTicks = [
7
7
  {
@@ -170,6 +170,12 @@ export function resolveTickVals(scale, ticks, placement) {
170
170
  ? scale.domain().filter((_, i) => i % ticks === 0)
171
171
  : scale.domain();
172
172
  }
173
+ // if (isScaleTime(scale)) {
174
+ // const interval = getMajorTicks(scale.domain()[0], scale.domain()[1])!;
175
+ // // const interval = getMinorTicks(scale.domain()[0], scale.domain()[1]);
176
+ // return scale.ticks(interval);
177
+ // }
178
+ // Ticks from scale
173
179
  if (scale.ticks && typeof scale.ticks === 'function') {
174
180
  if (placement) {
175
181
  return scale.ticks(ticks ?? (placement === 'left' || placement === 'right' ? 4 : undefined));
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "author": "Sean Lynch <techniq35@gmail.com>",
5
5
  "license": "MIT",
6
6
  "repository": "techniq/layerchart",
7
- "version": "2.0.0-next.6",
7
+ "version": "2.0.0-next.8",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.29.4",
10
10
  "@iconify-json/lucide": "^1.2.42",
@@ -16,7 +16,7 @@
16
16
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
17
17
  "@svitejs/changesets-changelog-github-compact": "^1.2.0",
18
18
  "@tailwindcss/typography": "^0.5.16",
19
- "@tailwindcss/vite": "^4.1.5",
19
+ "@tailwindcss/vite": "^4.1.7",
20
20
  "@types/d3": "^7.4.3",
21
21
  "@types/d3-array": "^3.2.1",
22
22
  "@types/d3-color": "^3.1.3",
@@ -43,7 +43,7 @@
43
43
  "@types/topojson-specification": "^1.0.5",
44
44
  "marked": "^15.0.11",
45
45
  "mdsvex": "^0.12.3",
46
- "posthog-js": "^1.242.1",
46
+ "posthog-js": "^1.242.2",
47
47
  "prettier": "^3.5.3",
48
48
  "prettier-plugin-svelte": "^3.4.0",
49
49
  "prism-svelte": "^0.5.0",
@@ -52,12 +52,12 @@
52
52
  "rehype-slug": "^6.0.0",
53
53
  "shapefile": "^0.6.6",
54
54
  "solar-calculator": "^0.3.0",
55
- "svelte": "5.29.0",
56
- "svelte-check": "^4.2.0",
55
+ "svelte": "5.30.1",
56
+ "svelte-check": "^4.2.1",
57
57
  "svelte-json-tree": "^2.2.0",
58
58
  "svelte-ux": "2.0.0-next.2",
59
- "svelte2tsx": "^0.7.38",
60
- "tailwindcss": "^4.1.5",
59
+ "svelte2tsx": "^0.7.39",
60
+ "tailwindcss": "^4.1.7",
61
61
  "topojson-client": "^3.1.0",
62
62
  "topojson-simplify": "^3.0.3",
63
63
  "tslib": "^2.8.1",
@@ -72,8 +72,7 @@
72
72
  "dependencies": {
73
73
  "@dagrejs/dagre": "^1.1.4",
74
74
  "@layerstack/svelte-actions": "1.0.1-next.2",
75
- "@layerstack/svelte-state": "0.1.0-next.3",
76
- "@layerstack/svelte-stores": "1.0.2-next.2",
75
+ "@layerstack/svelte-state": "0.1.0-next.4",
77
76
  "@layerstack/tailwind": "2.0.0-next.4",
78
77
  "@layerstack/utils": "1.1.0-next.2",
79
78
  "d3-array": "^3.2.4",
@@ -97,7 +96,7 @@
97
96
  "d3-time": "^3.1.0",
98
97
  "date-fns": "^4.1.0",
99
98
  "lodash-es": "^4.17.21",
100
- "runed": "^0.27.0"
99
+ "runed": "^0.28.0"
101
100
  },
102
101
  "peerDependencies": {
103
102
  "svelte": "^5.0.0"