layerchart 0.34.0 → 0.36.0

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.
@@ -166,9 +166,22 @@ function getDefaultLabelProps(tick) {
166
166
  {/if}
167
167
  {/if}
168
168
 
169
- {#each tickVals as tick (tick)}
169
+ {#each tickVals as tick, index (tick)}
170
170
  {@const tickCoords = getCoords(tick)}
171
171
  {@const radialTickCoords = pointRadial(tickCoords.x, tickCoords.y)}
172
+ {@const textLabelProps = {
173
+ x: orientation === 'angle' ? radialTickCoords[0] : tickCoords.x,
174
+ y: orientation === 'angle' ? radialTickCoords[1] : tickCoords.y,
175
+ value: formatValue(tick, format ?? scale.tickFormat?.() ?? ((v) => v)),
176
+ ...getDefaultLabelProps(tick),
177
+ tweened,
178
+ spring,
179
+ ...labelProps,
180
+ class: cls(
181
+ 'label text-[10px] stroke-surface-100 [stroke-width:2px] font-light',
182
+ labelProps?.class
183
+ ),
184
+ }}
172
185
 
173
186
  <g in:transitionIn={transitionInParams}>
174
187
  {#if grid !== false}
@@ -241,19 +254,9 @@ function getDefaultLabelProps(tick) {
241
254
  />
242
255
  {/if}
243
256
 
244
- <Text
245
- x={orientation === 'angle' ? radialTickCoords[0] : tickCoords.x}
246
- y={orientation === 'angle' ? radialTickCoords[1] : tickCoords.y}
247
- value={formatValue(tick, format ?? scale.tickFormat?.() ?? ((v) => v))}
248
- {...getDefaultLabelProps(tick)}
249
- {tweened}
250
- {spring}
251
- {...labelProps}
252
- class={cls(
253
- 'label text-[10px] stroke-surface-100 [stroke-width:2px] font-light',
254
- labelProps?.class
255
- )}
256
- />
257
+ <slot name="label" labelProps={textLabelProps} {index}>
258
+ <Text {...textLabelProps} />
259
+ </slot>
257
260
  </g>
258
261
  {/each}
259
262
  </g>
@@ -22,7 +22,12 @@ declare const __propDef: {
22
22
  events: {
23
23
  [evt: string]: CustomEvent<any>;
24
24
  };
25
- slots: {};
25
+ slots: {
26
+ label: {
27
+ labelProps: any;
28
+ index: any;
29
+ };
30
+ };
26
31
  };
27
32
  export type AxisProps = typeof __propDef.props;
28
33
  export type AxisEvents = typeof __propDef.events;
@@ -1,13 +1,15 @@
1
1
  <script>import { getContext } from 'svelte';
2
2
  import RectClipPath from './RectClipPath.svelte';
3
3
  const { width, height, padding } = getContext('LayerCake');
4
+ /** Whether clipping should include chart padding (ex. axis) */
5
+ export let includePadding = false;
4
6
  </script>
5
7
 
6
8
  <RectClipPath
7
- x={-$padding.left}
8
- y={-$padding.top}
9
- width={$width + $padding.left + $padding.right}
10
- height={$height + $padding.top + $padding.bottom}
9
+ x={includePadding ? -$padding.left : 0}
10
+ y={includePadding ? -$padding.top : 0}
11
+ width={$width + (includePadding ? $padding.left + $padding.right : 0)}
12
+ height={$height + (includePadding ? $padding.top + $padding.bottom : 0)}
11
13
  on:click
12
14
  {...$$restProps}
13
15
  >
@@ -2,6 +2,7 @@ import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  [x: string]: any;
5
+ includePadding?: boolean | undefined;
5
6
  };
6
7
  events: {
7
8
  click: CustomEvent<any>;
@@ -0,0 +1,49 @@
1
+ <script>import { getContext } from 'svelte';
2
+ import { forceSimulation } from 'd3-force';
3
+ const { data } = getContext('LayerCake');
4
+ export let forces;
5
+ export let alpha = 1;
6
+ export let alphaTarget = 0;
7
+ export let alphaDecay = 1 - Math.pow(0.001, 1 / 300);
8
+ export let alphaMin = 0.001;
9
+ export let velocityDecay = 0.4;
10
+ /** Clone data since simulation mutates original */
11
+ export let cloneData = false;
12
+ let _static = false;
13
+ /** If true, will only update nodes after simulation has completed */
14
+ export { _static as static };
15
+ let simulation = forceSimulation(cloneData ? structuredClone($data) : $data);
16
+ $: {
17
+ simulation
18
+ .alpha(alpha)
19
+ .alphaTarget(alphaTarget)
20
+ .alphaMin(alphaMin)
21
+ .alphaDecay(alphaDecay)
22
+ .velocityDecay(velocityDecay)
23
+ .restart();
24
+ if (_static) {
25
+ // TODO: Not sure why it needs to be recreated when static
26
+ simulation = forceSimulation(cloneData ? structuredClone($data) : $data);
27
+ simulation.stop();
28
+ Object.entries(forces).forEach(([name, force]) => {
29
+ simulation.force(name, force);
30
+ });
31
+ for (let i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
32
+ simulation.tick();
33
+ }
34
+ nodes = simulation.nodes();
35
+ }
36
+ else {
37
+ // When variables change, set forces and restart the simulation
38
+ Object.entries(forces).forEach(([name, force]) => {
39
+ simulation.force(name, force);
40
+ });
41
+ }
42
+ }
43
+ let nodes = [];
44
+ simulation.on('tick', () => {
45
+ nodes = simulation.nodes();
46
+ });
47
+ </script>
48
+
49
+ <slot {nodes} {simulation} />
@@ -0,0 +1,29 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import { type Force } from 'd3-force';
3
+ declare const __propDef: {
4
+ props: {
5
+ forces: Record<string, Force<any, any>>;
6
+ alpha?: number | undefined;
7
+ alphaTarget?: number | undefined;
8
+ alphaDecay?: number | undefined;
9
+ alphaMin?: number | undefined;
10
+ velocityDecay?: number | undefined;
11
+ /** Clone data since simulation mutates original */ cloneData?: boolean | undefined;
12
+ /** If true, will only update nodes after simulation has completed */ static?: boolean | undefined;
13
+ };
14
+ events: {
15
+ [evt: string]: CustomEvent<any>;
16
+ };
17
+ slots: {
18
+ default: {
19
+ nodes: any[];
20
+ simulation: import("d3-force").Simulation<import("d3-force").SimulationNodeDatum, undefined>;
21
+ };
22
+ };
23
+ };
24
+ export type ForceSimulationProps = typeof __propDef.props;
25
+ export type ForceSimulationEvents = typeof __propDef.events;
26
+ export type ForceSimulationSlots = typeof __propDef.slots;
27
+ export default class ForceSimulation extends SvelteComponentTyped<ForceSimulationProps, ForceSimulationEvents, ForceSimulationSlots> {
28
+ }
29
+ export {};
@@ -1,8 +1,10 @@
1
1
  <script>import { createEventDispatcher, getContext } from 'svelte';
2
- import { geoPath as d3geoPath } from 'd3-geo';
2
+ import {} from 'd3-geo';
3
3
  import { scaleCanvas } from 'layercake';
4
4
  import { cls } from 'svelte-ux';
5
5
  import { geoContext } from './GeoContext.svelte';
6
+ import { curveLinearClosed } from 'd3-shape';
7
+ import { geoCurvePath } from '../utils/geo.js';
6
8
  export let geojson;
7
9
  export let fill = undefined;
8
10
  export let stroke = undefined;
@@ -13,29 +15,50 @@ export let render = undefined;
13
15
  * Tooltip context to setup mouse events to show tooltip for related data
14
16
  */
15
17
  export let tooltip = undefined;
18
+ /**
19
+ * Curve of path drawn. Imported via d3-shape.
20
+ *
21
+ * @example
22
+ * import { curveCatmullRom } from 'd3-shape';
23
+ * <GeoPath curve={curveCatmullRom} />
24
+ *
25
+ * @type {CurveFactory | CurveFactoryLineOnly | undefined}
26
+ */
27
+ export let curve = curveLinearClosed;
16
28
  const dispatch = createEventDispatcher();
17
- const { rGet, width, height } = getContext('LayerCake');
29
+ const { width, height } = getContext('LayerCake');
18
30
  const canvas = getContext('canvas');
19
31
  const geo = geoContext();
20
- $: geoPath = d3geoPath($geo);
32
+ $: geoPath = geoCurvePath($geo, curve);
33
+ const DEFAULT_FILL = 'rgb(0, 0, 0)';
21
34
  $: renderContext = canvas ? 'canvas' : 'svg';
22
35
  $: ctx = canvas?.ctx;
23
36
  $: if (renderContext === 'canvas' && $ctx) {
37
+ let computedStyles = {};
38
+ // Transfer classes defined on <GeoPath> to <canvas> to enable window.getComputedStyle() retrieval (Tailwind classes, etc)
39
+ if ($$props.class) {
40
+ $ctx.canvas.classList.add(...$$props.class.split(' '));
41
+ computedStyles = window.getComputedStyle($ctx.canvas);
42
+ }
24
43
  // console.count('render');
25
44
  scaleCanvas($ctx, $width, $height);
26
45
  $ctx.clearRect(0, 0, $width, $height);
27
46
  if (render) {
47
+ geoPath = geoCurvePath($geo, curve, $ctx);
28
48
  render($ctx, { geoPath });
29
49
  }
30
50
  else {
31
51
  $ctx.beginPath();
32
52
  // Set the context here since setting it in `$: geoPath` is a circular reference
33
- geoPath.context($ctx);
53
+ geoPath = geoCurvePath($geo, curve, $ctx);
34
54
  geoPath(geojson);
35
- $ctx.fillStyle = fill || 'transparent';
55
+ $ctx.fillStyle =
56
+ fill ??
57
+ (computedStyles.fill !== DEFAULT_FILL ? computedStyles.fill : undefined) ??
58
+ 'transparent';
36
59
  $ctx.fill();
37
60
  $ctx.lineWidth = strokeWidth;
38
- $ctx.strokeStyle = stroke;
61
+ $ctx.strokeStyle = stroke ?? computedStyles.stroke;
39
62
  $ctx.stroke();
40
63
  }
41
64
  }
@@ -1,6 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import { type GeoPath, type GeoPermissibleObjects } from 'd3-geo';
2
+ import { type GeoPermissibleObjects } from 'd3-geo';
3
3
  import type { TooltipContextValue } from './TooltipContext.svelte';
4
+ import { type CurveFactory, type CurveFactoryLineOnly } from 'd3-shape';
4
5
  declare const __propDef: {
5
6
  props: {
6
7
  [x: string]: any;
@@ -12,6 +13,7 @@ declare const __propDef: {
12
13
  geoPath: any;
13
14
  }) => any) | undefined;
14
15
  tooltip?: TooltipContextValue | undefined;
16
+ curve?: CurveFactory | CurveFactoryLineOnly | undefined;
15
17
  };
16
18
  events: {
17
19
  mousemove: MouseEvent;
@@ -22,7 +24,7 @@ declare const __propDef: {
22
24
  };
23
25
  slots: {
24
26
  default: {
25
- geoPath: GeoPath<any, GeoPermissibleObjects>;
27
+ geoPath: (object: GeoPermissibleObjects) => string | undefined;
26
28
  };
27
29
  };
28
30
  };
@@ -15,9 +15,12 @@ $: [x, y] = $geo([long, lat]) ?? [0, 0];
15
15
  $: renderContext = canvas ? 'canvas' : 'svg';
16
16
  $: ctx = canvas?.ctx;
17
17
  $: if (renderContext === 'canvas' && $ctx) {
18
- // console.count('render');
19
18
  scaleCanvas($ctx, $width, $height);
20
19
  $ctx.clearRect(0, 0, $width, $height);
20
+ // Transfer classes defined on <GeoPoint> to <canvas> to enable window.getComputedStyle() retrieval (Tailwind classes, etc)
21
+ if ($$props.class) {
22
+ $ctx.canvas.classList.add(...$$props.class.split(' '));
23
+ }
21
24
  render($ctx, { x, y });
22
25
  }
23
26
  </script>
@@ -0,0 +1,12 @@
1
+ <script>import { geoContext } from './GeoContext.svelte';
2
+ import { isVisible } from '../utils/geo.js';
3
+ /** Latitude */
4
+ export let lat;
5
+ /** Longitude */
6
+ export let long;
7
+ const geo = geoContext();
8
+ </script>
9
+
10
+ {#if isVisible($geo)([long, lat])}
11
+ <slot />
12
+ {/if}
@@ -0,0 +1,19 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ /** Latitude */ lat: number;
5
+ /** Longitude */ long: number;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {
11
+ default: {};
12
+ };
13
+ };
14
+ export type GeoVisibleProps = typeof __propDef.props;
15
+ export type GeoVisibleEvents = typeof __propDef.events;
16
+ export type GeoVisibleSlots = typeof __propDef.slots;
17
+ export default class GeoVisible extends SvelteComponentTyped<GeoVisibleProps, GeoVisibleEvents, GeoVisibleSlots> {
18
+ }
19
+ export {};
@@ -0,0 +1,53 @@
1
+ <script>import { createEventDispatcher, getContext } from 'svelte';
2
+ import { cls } from 'svelte-ux';
3
+ import { min } from 'd3-array';
4
+ import { Delaunay } from 'd3-delaunay';
5
+ import { geoVoronoi } from 'd3-geo-voronoi';
6
+ import GeoPath from './GeoPath.svelte';
7
+ import { geoContext } from './GeoContext.svelte';
8
+ import Spline from './Spline.svelte';
9
+ import { curveLinearClosed } from 'd3-shape';
10
+ const { flatData, x: xContext, y: yContext } = getContext('LayerCake');
11
+ const geo = geoContext();
12
+ /** Override data instead of using context */
13
+ export let data = undefined;
14
+ export let curve = curveLinearClosed;
15
+ export let classes = {};
16
+ const dispatch = createEventDispatcher();
17
+ $: points = (data ?? $flatData).map((d) => {
18
+ const xValue = $xContext(d);
19
+ const yValue = $yContext(d);
20
+ const x = Array.isArray(xValue) ? min(xValue) : xValue;
21
+ const y = Array.isArray(yValue) ? min(yValue) : yValue;
22
+ const point = [x, y];
23
+ point.data = d;
24
+ return point;
25
+ });
26
+ </script>
27
+
28
+ <g {...$$restProps} class={cls(classes.root, $$props.class)}>
29
+ {#if $geo}
30
+ {@const polygon = geoVoronoi().hull(points)}
31
+ <GeoPath
32
+ geojson={polygon}
33
+ {curve}
34
+ class={cls('fill-transparent', classes.path)}
35
+ on:mousemove={(e) => dispatch('mousemove', { event: e, points, polygon })}
36
+ on:mouseleave
37
+ on:click={(e) => dispatch('click', { points, polygon })}
38
+ />
39
+ {:else}
40
+ {@const delaunay = Delaunay.from(points)}
41
+ {@const polygon = delaunay.hullPolygon()}
42
+ <Spline
43
+ data={polygon}
44
+ x={(d) => d[0]}
45
+ y={(d) => d[1]}
46
+ {curve}
47
+ class={cls('fill-transparent', classes.path)}
48
+ on:mousemove={(e) => dispatch('mousemove', { event: e, points, polygon })}
49
+ on:mouseleave
50
+ on:click={(e) => dispatch('click', { points, polygon })}
51
+ />
52
+ {/if}
53
+ </g>
@@ -0,0 +1,36 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import { type ComponentProps } from 'svelte';
3
+ import { Delaunay } from 'd3-delaunay';
4
+ import Spline from './Spline.svelte';
5
+ declare const __propDef: {
6
+ props: {
7
+ [x: string]: any;
8
+ data?: any;
9
+ curve?: ComponentProps<Spline>['curve'];
10
+ classes?: {
11
+ root?: string | undefined;
12
+ path?: string | undefined;
13
+ } | undefined;
14
+ };
15
+ events: {
16
+ mouseleave: MouseEvent;
17
+ click: CustomEvent<{
18
+ points: [number, number][];
19
+ polygon: Delaunay.Polygon;
20
+ }>;
21
+ mousemove: CustomEvent<{
22
+ event: MouseEvent;
23
+ points: [number, number][];
24
+ polygon: Delaunay.Polygon;
25
+ }>;
26
+ } & {
27
+ [evt: string]: CustomEvent<any>;
28
+ };
29
+ slots: {};
30
+ };
31
+ export type HullProps = typeof __propDef.props;
32
+ export type HullEvents = typeof __propDef.events;
33
+ export type HullSlots = typeof __propDef.slots;
34
+ export default class Hull extends SvelteComponentTyped<HullProps, HullEvents, HullSlots> {
35
+ }
36
+ export {};
@@ -6,7 +6,9 @@ import Link from './Link.svelte';
6
6
  import { isScaleBand } from '../utils/scales.js';
7
7
  import { pointRadial } from 'd3-shape';
8
8
  const context = getContext('LayerCake');
9
- const { data, xGet, y, yGet, xScale, yScale, rGet, config } = context;
9
+ const { data: contextData, xGet, y, yGet, xScale, yScale, rGet, config } = context;
10
+ /** Override data instead of using context */
11
+ export let data = undefined;
10
12
  export let r = 5;
11
13
  export let offsetX = undefined;
12
14
  export let offsetY = undefined;
@@ -28,7 +30,8 @@ function getOffset(value, offset, scale) {
28
30
  return 0;
29
31
  }
30
32
  }
31
- $: points = $data.flatMap((d) => {
33
+ $: pointsData = data ?? $contextData;
34
+ $: points = pointsData.flatMap((d) => {
32
35
  if (Array.isArray($config.x)) {
33
36
  /*
34
37
  x={["prop1" ,"prop2"]}
@@ -71,7 +74,7 @@ $: points = $data.flatMap((d) => {
71
74
  };
72
75
  }
73
76
  });
74
- $: _links = $data.flatMap((d) => {
77
+ $: _links = pointsData.flatMap((d) => {
75
78
  if (Array.isArray($config.x)) {
76
79
  /*
77
80
  x={["prop1" ,"prop2"]}
@@ -2,6 +2,7 @@ import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  [x: string]: any;
5
+ data?: any;
5
6
  r?: number | undefined;
6
7
  offsetX?: number | ((value: number, context: any) => number) | undefined;
7
8
  offsetY?: number | ((value: number, context: any) => number) | undefined;
@@ -1,5 +1,4 @@
1
1
  <script>import { createEventDispatcher, getContext } from 'svelte';
2
- import { draw as _drawTransition } from 'svelte/transition';
3
2
  import { cls } from 'svelte-ux';
4
3
  import { min } from 'd3-array';
5
4
  import { Delaunay } from 'd3-delaunay';
@@ -2,6 +2,7 @@ export { default as Arc } from './Arc.svelte';
2
2
  export { default as Area } from './Area.svelte';
3
3
  export { default as AreaStack } from './AreaStack.svelte';
4
4
  export { default as Axis } from './Axis.svelte';
5
+ export { default as Bar } from './Bar.svelte';
5
6
  export { default as Bars } from './Bars.svelte';
6
7
  export { default as Blur } from './Blur.svelte';
7
8
  export { default as Bounds } from './Bounds.svelte';
@@ -13,6 +14,7 @@ export { default as CircleClipPath } from './CircleClipPath.svelte';
13
14
  export { default as ClipPath } from './ClipPath.svelte';
14
15
  export { default as ColorRamp } from './ColorRamp.svelte';
15
16
  export { default as Frame } from './Frame.svelte';
17
+ export { default as ForceSimulation } from './ForceSimulation.svelte';
16
18
  export { default as GeoCircle } from './GeoCircle.svelte';
17
19
  export { default as GeoContext, geoContext } from './GeoContext.svelte';
18
20
  export { default as GeoEdgeFade } from './GeoEdgeFade.svelte';
@@ -20,9 +22,11 @@ export { default as GeoPath } from './GeoPath.svelte';
20
22
  export { default as GeoPoint } from './GeoPoint.svelte';
21
23
  export { default as GeoSpline } from './GeoSpline.svelte';
22
24
  export { default as GeoTile } from './GeoTile.svelte';
25
+ export { default as GeoVisible } from './GeoVisible.svelte';
23
26
  export { default as Graticule } from './Graticule.svelte';
24
27
  export { default as Group } from './Group.svelte';
25
28
  export { default as Highlight } from './Highlight.svelte';
29
+ export { default as Hull } from './Hull.svelte';
26
30
  export { default as Labels } from './Labels.svelte';
27
31
  export { default as Legend } from './Legend.svelte';
28
32
  export { default as Line } from './Line.svelte';
@@ -2,6 +2,7 @@ export { default as Arc } from './Arc.svelte';
2
2
  export { default as Area } from './Area.svelte';
3
3
  export { default as AreaStack } from './AreaStack.svelte';
4
4
  export { default as Axis } from './Axis.svelte';
5
+ export { default as Bar } from './Bar.svelte';
5
6
  export { default as Bars } from './Bars.svelte';
6
7
  export { default as Blur } from './Blur.svelte';
7
8
  export { default as Bounds } from './Bounds.svelte';
@@ -13,6 +14,7 @@ export { default as CircleClipPath } from './CircleClipPath.svelte';
13
14
  export { default as ClipPath } from './ClipPath.svelte';
14
15
  export { default as ColorRamp } from './ColorRamp.svelte';
15
16
  export { default as Frame } from './Frame.svelte';
17
+ export { default as ForceSimulation } from './ForceSimulation.svelte';
16
18
  export { default as GeoCircle } from './GeoCircle.svelte';
17
19
  export { default as GeoContext, geoContext } from './GeoContext.svelte';
18
20
  export { default as GeoEdgeFade } from './GeoEdgeFade.svelte';
@@ -20,9 +22,11 @@ export { default as GeoPath } from './GeoPath.svelte';
20
22
  export { default as GeoPoint } from './GeoPoint.svelte';
21
23
  export { default as GeoSpline } from './GeoSpline.svelte';
22
24
  export { default as GeoTile } from './GeoTile.svelte';
25
+ export { default as GeoVisible } from './GeoVisible.svelte';
23
26
  export { default as Graticule } from './Graticule.svelte';
24
27
  export { default as Group } from './Group.svelte';
25
28
  export { default as Highlight } from './Highlight.svelte';
29
+ export { default as Hull } from './Hull.svelte';
26
30
  export { default as Labels } from './Labels.svelte';
27
31
  export { default as Legend } from './Legend.svelte';
28
32
  export { default as Line } from './Line.svelte';
@@ -1,20 +1,20 @@
1
- <script>import { onMount } from 'svelte';
2
- import * as d3shapes from 'd3-shape';
3
- import { MenuField } from 'svelte-ux';
4
- export let value = undefined;
5
- const options = Object.keys(d3shapes)
6
- .filter((key) => key.startsWith('curve'))
7
- .filter((key) => !key.endsWith('Open') && !key.endsWith('Closed'))
8
- .filter((key) => !key.includes('Bundle')) // Not compatibile with area
9
- .map((key) => {
1
+ <script>import * as d3shapes from 'd3-shape';
2
+ import { MenuField, entries } from 'svelte-ux';
3
+ export let value = d3shapes['curveLinear'];
4
+ export let showOpenClosed = false;
5
+ const options = entries(d3shapes)
6
+ .filter(([key]) => {
7
+ return (key.startsWith('curve') &&
8
+ (showOpenClosed ? true : !key.endsWith('Open') && !key.endsWith('Closed')) &&
9
+ !key.includes('Bundle') // Not compatibile with area
10
+ );
11
+ })
12
+ .map(([key, value]) => {
10
13
  return {
11
14
  label: key.replace('curve', ''),
12
- value: d3shapes[key]
15
+ value: value,
13
16
  };
14
17
  });
15
- onMount(() => {
16
- value = d3shapes['curveLinear'];
17
- });
18
18
  </script>
19
19
 
20
20
  <MenuField label="Curve" {options} bind:value stepper classes={{ menuIcon: 'hidden' }} />
@@ -2,6 +2,7 @@ import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  value?: any | undefined;
5
+ showOpenClosed?: boolean | undefined;
5
6
  };
6
7
  events: {
7
8
  [evt: string]: CustomEvent<any>;
@@ -1,5 +1,18 @@
1
+ import { type GeoPermissibleObjects, type GeoProjection, type GeoStreamWrapper } from 'd3-geo';
2
+ import { type Path } from 'd3-path';
3
+ import { type CurveFactory, type CurveFactoryLineOnly } from 'd3-shape';
4
+ /**
5
+ * Render a geoPath() using curve factory
6
+ * @see {@link https://observablehq.com/@d3/context-to-curve}
7
+ */
8
+ export declare function geoCurvePath(projection: GeoProjection | GeoStreamWrapper | null, curve: CurveFactory | CurveFactoryLineOnly, context?: CanvasRenderingContext2D | Path): (object: GeoPermissibleObjects) => string | undefined;
1
9
  /**
2
10
  * Return the point on Earth's surface that is diametrically opposite to another point
3
11
  * @see: https://en.wikipedia.org/wiki/Antipodes
4
12
  */
5
13
  export declare function antipode([longitude, latitude]: [number, number]): [number, number];
14
+ /**
15
+ * Check if point ([x, y]) is visible on projection
16
+ * @see: https://observablehq.com/@d3/testing-projection-visibility
17
+ */
18
+ export declare function isVisible(projection: GeoProjection | GeoStreamWrapper): ([x, y]: [any, any]) => boolean;
package/dist/utils/geo.js CHANGED
@@ -1,3 +1,44 @@
1
+ import { geoPath as d3geoPath, } from 'd3-geo';
2
+ import { path } from 'd3-path';
3
+ import {} from 'd3-shape';
4
+ /**
5
+ * Render a geoPath() using curve factory
6
+ * @see {@link https://observablehq.com/@d3/context-to-curve}
7
+ */
8
+ export function geoCurvePath(projection, curve, context) {
9
+ const pathContext = context === undefined ? path() : context;
10
+ const geoPath = d3geoPath(projection, curveContext(curve(pathContext)));
11
+ const fn = (object) => {
12
+ geoPath(object);
13
+ return context === undefined ? pathContext + '' : undefined;
14
+ };
15
+ // Expose geoPath properties such as `.centroid()`
16
+ Object.setPrototypeOf(fn, geoPath);
17
+ return fn;
18
+ }
19
+ /**
20
+ * Translate Curve to GeoContext interface
21
+ */
22
+ function curveContext(curve) {
23
+ return {
24
+ beginPath() {
25
+ // nothing?
26
+ },
27
+ moveTo(x, y) {
28
+ curve.lineStart();
29
+ curve.point(x, y);
30
+ },
31
+ arc(x, y, radius, startAngle, endAngle, anticlockwise) {
32
+ // nothing?
33
+ },
34
+ lineTo(x, y) {
35
+ curve.point(x, y);
36
+ },
37
+ closePath() {
38
+ curve.lineEnd();
39
+ },
40
+ };
41
+ }
1
42
  /**
2
43
  * Return the point on Earth's surface that is diametrically opposite to another point
3
44
  * @see: https://en.wikipedia.org/wiki/Antipodes
@@ -5,3 +46,16 @@
5
46
  export function antipode([longitude, latitude]) {
6
47
  return [longitude + 180, -latitude];
7
48
  }
49
+ /**
50
+ * Check if point ([x, y]) is visible on projection
51
+ * @see: https://observablehq.com/@d3/testing-projection-visibility
52
+ */
53
+ export function isVisible(projection) {
54
+ let visible;
55
+ const stream = projection.stream({
56
+ point() {
57
+ visible = true;
58
+ },
59
+ });
60
+ return ([x, y]) => ((visible = false), stream.point(x, y), visible);
61
+ }
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": "0.34.0",
7
+ "version": "0.36.0",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.1",
10
10
  "@mdi/js": "^7.4.47",
@@ -17,6 +17,7 @@
17
17
  "@types/d3-array": "^3.2.1",
18
18
  "@types/d3-delaunay": "^6.0.4",
19
19
  "@types/d3-dsv": "^3.0.7",
20
+ "@types/d3-force": "^3.0.9",
20
21
  "@types/d3-geo": "^3.1.0",
21
22
  "@types/d3-hierarchy": "^3.1.6",
22
23
  "@types/d3-interpolate": "^3.0.4",
@@ -32,6 +33,7 @@
32
33
  "@types/prismjs": "^1.26.3",
33
34
  "@types/shapefile": "^0.6.4",
34
35
  "@types/topojson-client": "^3.1.4",
36
+ "@types/topojson-simplify": "^3.0.3",
35
37
  "autoprefixer": "^10.4.18",
36
38
  "execa": "^8.0.1",
37
39
  "marked": "^12.0.1",
@@ -52,6 +54,7 @@
52
54
  "svelte2tsx": "^0.7.4",
53
55
  "tailwindcss": "^3.4.1",
54
56
  "topojson-client": "^3.1.0",
57
+ "topojson-simplify": "^3.0.3",
55
58
  "tslib": "^2.6.2",
56
59
  "typescript": "^5.4.2",
57
60
  "unist-util-visit": "^5.0.0",
@@ -65,11 +68,13 @@
65
68
  "d3-color": "^3.1.0",
66
69
  "d3-delaunay": "^6.0.4",
67
70
  "d3-dsv": "^3.0.1",
71
+ "d3-force": "^3.0.0",
68
72
  "d3-geo": "^3.1.1",
69
73
  "d3-geo-voronoi": "^2.0.1",
70
74
  "d3-hierarchy": "^3.1.2",
71
75
  "d3-interpolate": "^3.0.1",
72
76
  "d3-interpolate-path": "^2.3.0",
77
+ "d3-path": "^3.1.0",
73
78
  "d3-quadtree": "^3.0.1",
74
79
  "d3-random": "^3.0.1",
75
80
  "d3-sankey": "^0.12.3",