layerchart 0.24.3 → 0.25.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.
package/README.md CHANGED
@@ -1,4 +1,11 @@
1
- # layerchart
1
+ # LayerChart
2
+
3
+ ![](https://img.shields.io/github/license/techniq/svelte-ux?style=flat)
4
+ [![](https://img.shields.io/npm/v/layerchart?style=flat)](https://www.npmjs.com/package/layerchart)
5
+ ![npm](https://img.shields.io/npm/dw/layerchart?style=flat&color=orange)
6
+
7
+ ![](https://img.shields.io/github/license/layerchart?style=flat)
8
+ [![](https://dcbadge.vercel.app/api/server/b94Kmm88?style=flat)](https://discord.gg/b94Kmm88)
2
9
 
3
10
  A large collection of composable Svelte chart components to build a wide range of visualizations
4
11
 
@@ -15,8 +15,7 @@ export let fill = undefined;
15
15
  export let stroke = 'black';
16
16
  export let strokeWidth = 0;
17
17
  export let radius = 0;
18
- export let getProps = undefined;
19
- export let padding = 0;
18
+ export let inset = 0;
20
19
  export let groupBy = undefined;
21
20
  export let groupPaddingInner = 0.2;
22
21
  export let groupPaddingOuter = 0;
@@ -28,7 +27,7 @@ $: getDimensions = createDimensionGetter(getContext('LayerCake'), {
28
27
  x,
29
28
  y,
30
29
  groupBy,
31
- padding,
30
+ inset,
32
31
  groupPadding: {
33
32
  inner: groupPaddingInner,
34
33
  outer: groupPaddingOuter,
@@ -46,4 +45,4 @@ $: getDimensions = createDimensionGetter(getContext('LayerCake'), {
46
45
  {...$getDimensions(bar)}
47
46
  {...$$restProps}
48
47
  on:click
49
- />
48
+ />
@@ -10,12 +10,7 @@ declare const __propDef: {
10
10
  stroke?: string | undefined;
11
11
  strokeWidth?: number | undefined;
12
12
  radius?: number | undefined;
13
- getProps?: ((obj: {
14
- value: any;
15
- item: any;
16
- index: number;
17
- }) => any) | undefined;
18
- padding?: number | undefined;
13
+ inset?: number | undefined;
19
14
  groupBy?: string | undefined;
20
15
  groupPaddingInner?: number | undefined;
21
16
  groupPaddingOuter?: number | undefined;
@@ -12,9 +12,8 @@ export let y = undefined; // TODO: Update Type
12
12
  export let stroke = 'black';
13
13
  export let strokeWidth = 0;
14
14
  export let radius = 0;
15
- export let getProps = undefined;
16
15
  /** Inset the rect for amount of padding. Useful with multiple bars (bullet, overlap, etc) */
17
- export let padding = 0;
16
+ export let inset = 0;
18
17
  export let spring = undefined;
19
18
  export let tweened = undefined;
20
19
  // See: https://svelte.dev/repl/7000c5ce05b84cd98ccbfb2768b4be3d?version=3.38.3
@@ -25,7 +24,7 @@ export let groupPaddingOuter = 0;
25
24
 
26
25
  <g class="Bars">
27
26
  <slot name="bars">
28
- {#each $data as item, index}
27
+ {#each $data as item}
29
28
  <Bar
30
29
  bar={item}
31
30
  {x}
@@ -37,7 +36,7 @@ export let groupPaddingOuter = 0;
37
36
  {spring}
38
37
  {tweened}
39
38
  {groupBy}
40
- {padding}
39
+ {inset}
41
40
  {groupPaddingInner}
42
41
  {groupPaddingOuter}
43
42
  {...$$restProps}
@@ -8,12 +8,7 @@ declare const __propDef: {
8
8
  stroke?: string | undefined;
9
9
  strokeWidth?: number | undefined;
10
10
  radius?: number | undefined;
11
- getProps?: ((obj: {
12
- value: any;
13
- item: any;
14
- index: number;
15
- }) => any) | undefined;
16
- padding?: number | undefined;
11
+ inset?: number | undefined;
17
12
  spring?: boolean | Parameters<typeof springStore>[1];
18
13
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
19
14
  groupBy?: string | undefined;
@@ -174,12 +174,12 @@ $: if ($tooltip.data) {
174
174
  {/if}
175
175
 
176
176
  {#if bar}
177
- <slot name="bar" bar={bar}>
177
+ <slot name="bar" {bar}>
178
178
  <Bar
179
179
  spring
180
180
  x={typeof bar === 'object' ? bar.x : null}
181
181
  y={typeof bar === 'object' ? bar.y : null}
182
- padding={typeof bar === 'object' ? bar.padding : null}
182
+ inset={typeof bar === 'object' ? bar.inset : null}
183
183
  stroke={typeof bar === 'object' ? bar.stroke : null}
184
184
  strokeWidth={typeof bar === 'object' ? bar.strokeWidth : null}
185
185
  radius={typeof bar === 'object' ? bar.radius : null}
@@ -190,7 +190,6 @@ $: if ($tooltip.data) {
190
190
  </slot>
191
191
  {/if}
192
192
 
193
-
194
193
  {#if lines}
195
194
  <slot name="lines" lines={_lines}>
196
195
  {#each _lines as line}
@@ -12,6 +12,7 @@ export let topOffset = top ? 0 : 10;
12
12
  export let leftOffset = left ? 0 : 10;
13
13
  export let contained = 'container'; // TODO: Support 'window' using getBoundingClientRect()
14
14
  export let animate = true;
15
+ export let variant = 'dark';
15
16
  export let header = undefined;
16
17
  export let classes = {};
17
18
  const { containerWidth, containerHeight } = getContext('LayerCake');
@@ -59,13 +60,30 @@ $: if ($tooltip) {
59
60
  >
60
61
  <div
61
62
  class={cls(
62
- 'bg-gray-900/90 backdrop-filter backdrop-blur-[2px] text-white rounded elevation-1 px-2 py-1 h-full',
63
+ variant !== 'none' && [
64
+ 'px-2 py-1 h-full rounded elevation-1',
65
+ '[&_.label]:text-xs [&_.label]:text-right [&_.label]:whitespace-nowrap',
66
+ ['[&_.value]:text-sm [&_.value]:tabular-nums'],
67
+ ],
68
+ {
69
+ dark: [
70
+ 'bg-gray-900/90 backdrop-filter backdrop-blur-[2px] text-white',
71
+ '[&_.label]:text-white/75',
72
+ ],
73
+ light: ['bg-white text-gray-800 border border-gray-500', '[&_.label]:text-black/50'],
74
+ none: '',
75
+ }[variant],
63
76
  classes.container,
64
77
  $$props.class
65
78
  )}
66
79
  >
67
80
  {#if header || $$slots.header}
68
- <div class={cls('text-center font-semibold whitespace-nowrap', classes.header)}>
81
+ <div
82
+ class={cls(
83
+ variant !== 'none' && 'text-center font-semibold whitespace-nowrap',
84
+ classes.header
85
+ )}
86
+ >
69
87
  <slot name="header" data={$tooltip.data}>
70
88
  {header?.($tooltip.data)}
71
89
  </slot>
@@ -75,7 +93,7 @@ $: if ($tooltip) {
75
93
  {#if $$slots.default}
76
94
  <div
77
95
  class={cls(
78
- 'grid grid-cols-[1fr,auto] gap-x-2 gap-y-1 items-center pt-1',
96
+ variant !== 'none' && 'grid grid-cols-[1fr,auto] gap-x-2 gap-y-1 items-center pt-1',
79
97
  classes.content
80
98
  )}
81
99
  >
@@ -8,6 +8,7 @@ declare const __propDef: {
8
8
  leftOffset?: number | undefined;
9
9
  contained?: false | "container" | undefined;
10
10
  animate?: boolean | undefined;
11
+ variant?: "none" | "dark" | "light" | undefined;
11
12
  header?: ((data: any) => any) | undefined;
12
13
  classes?: {
13
14
  root?: string | undefined;
@@ -39,13 +39,23 @@ const { flatData, x, xScale, xGet, xRange, y, yScale, yGet, yRange, width, heigh
39
39
  - scaleBand, scaleLinear: band (or bounds) - multiple (overlapping) bars
40
40
  - scaleLinear, scaleLinear: voronoi (or quadtree)
41
41
  */
42
+ /**
43
+ * @type {'bisect-x' | 'bisect-y' | 'band' | 'bisect-band' | 'bounds' | 'voronoi' | 'quadtree' | 'manual'}
44
+ */
42
45
  export let mode = 'bisect-x';
43
46
  export let snapToDataX = false;
44
47
  export let snapToDataY = false;
48
+ /**
49
+ * @type {'closest' | 'left' | 'right'}
50
+ */
45
51
  export let findTooltipData = 'closest';
46
52
  /** Similar to d3-selection's raise, re-insert the event.target as the last child of its parent, so to be the top-most element */
47
53
  export let raiseTarget = false;
54
+ /** quadtree search radius
55
+ * @type {number}
56
+ */
48
57
  export let radius = Infinity;
58
+ /** Enable debug view (show hit targets, etc) */
49
59
  export let debug = false;
50
60
  const tooltip = writable({ top: 0, left: 0, data: null, show: showTooltip, hide: hideTooltip });
51
61
  setTooltipContext(tooltip);
@@ -140,7 +150,7 @@ function showTooltip(event, tooltipData) {
140
150
  }
141
151
  case 'bisect-x': {
142
152
  // `x` value at mouse/touch coordinate
143
- const xValueAtPoint = scaleInvert($xScale, localX);
153
+ const xValueAtPoint = scaleInvert($xScale, localX - $padding.left);
144
154
  const index = bisectX($flatData, xValueAtPoint, 1);
145
155
  const previousValue = $flatData[index - 1];
146
156
  const currentValue = $flatData[index];
@@ -149,7 +159,7 @@ function showTooltip(event, tooltipData) {
149
159
  }
150
160
  case 'bisect-y': {
151
161
  // `y` value at mouse/touch coordinate
152
- const yValueAtPoint = scaleInvert($yScale, localY);
162
+ const yValueAtPoint = scaleInvert($yScale, localY - $padding.top);
153
163
  const index = bisectY($flatData, yValueAtPoint, 1);
154
164
  const previousValue = $flatData[index - 1];
155
165
  const currentValue = $flatData[index];
@@ -280,7 +290,7 @@ $: if (mode === 'bounds' || mode === 'band') {
280
290
  {#if ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode)}
281
291
  <Html>
282
292
  <div
283
- class="absolute"
293
+ class="tooltip-trigger absolute"
284
294
  style:width="{$width}px"
285
295
  style:height="{$height}px"
286
296
  style:background={debug ? 'rgba(255 0 0 / .1)' : undefined}
@@ -12,13 +12,19 @@ export type TooltipContext = Readable<TooltipContextValue>;
12
12
  export declare function tooltipContext(): TooltipContext;
13
13
  declare const __propDef: {
14
14
  props: {
15
- mode?: "bisect-x" | "bisect-y" | "band" | "bisect-band" | "bounds" | "voronoi" | "quadtree" | "manual" | undefined;
15
+ /**
16
+ * @type {'bisect-x' | 'bisect-y' | 'band' | 'bisect-band' | 'bounds' | 'voronoi' | 'quadtree' | 'manual'}
17
+ */ mode?: "bisect-x" | "bisect-y" | "band" | "bisect-band" | "bounds" | "voronoi" | "quadtree" | "manual" | undefined;
16
18
  snapToDataX?: boolean | undefined;
17
19
  snapToDataY?: boolean | undefined;
18
- findTooltipData?: "left" | "right" | "closest" | undefined;
20
+ /**
21
+ * @type {'closest' | 'left' | 'right'}
22
+ */ findTooltipData?: "left" | "right" | "closest" | undefined;
19
23
  /** Similar to d3-selection's raise, re-insert the event.target as the last child of its parent, so to be the top-most element */ raiseTarget?: boolean | undefined;
20
- radius?: number | undefined;
21
- debug?: boolean | undefined;
24
+ /** quadtree search radius
25
+ * @type {number}
26
+ */ radius?: number | undefined;
27
+ /** Enable debug view (show hit targets, etc) */ debug?: boolean | undefined;
22
28
  };
23
29
  events: {
24
30
  click: CustomEvent<{
@@ -7,16 +7,16 @@ export let valueAlign = 'left';
7
7
  export let classes = {};
8
8
  </script>
9
9
 
10
- <div class={cls('text-xs text-white/75 text-right whitespace-nowrap', classes.label)}>
10
+ <div class={cls('label', classes.label)}>
11
11
  <slot name="label">{label}:</slot>
12
12
  </div>
13
13
 
14
14
  <div
15
15
  class={cls(
16
- 'text-sm tabular-nums',
16
+ 'value',
17
17
  {
18
18
  'text-right': valueAlign === 'right',
19
- 'text-center': valueAlign === 'center'
19
+ 'text-center': valueAlign === 'center',
20
20
  },
21
21
  classes.value,
22
22
  $$props.class
@@ -78,6 +78,7 @@ catch (e) {
78
78
  <JsonTree
79
79
  value={data}
80
80
  defaultExpandedPaths={['$']}
81
+ shouldTreatIterableAsObject
81
82
  --json-tree-property-color="#72a2d3"
82
83
  --json-tree-string-color="#6cd1c7"
83
84
  --json-tree-symbol-color="#6cd1c7"
@@ -5,7 +5,7 @@ type DimensionGetterOptions = {
5
5
  /** Override `y` accessor from context */
6
6
  y?: (item: any) => any;
7
7
  groupBy?: string;
8
- padding?: number;
8
+ inset?: number;
9
9
  groupPadding?: {
10
10
  inner?: number;
11
11
  outer?: number;
@@ -5,7 +5,7 @@ import { groupScaleBand, isScaleBand } from './scales';
5
5
  export function createDimensionGetter(context, options) {
6
6
  const { flatData, xGet, yGet, xRange, yRange, xScale, yScale, x: xAccessor, y: yAccessor, } = context;
7
7
  const groupBy = options?.groupBy;
8
- const padding = options?.padding ?? 0;
8
+ const inset = options?.inset ?? 0;
9
9
  return derived([flatData, xGet, yGet, xRange, yRange, xScale, yScale, xAccessor, yAccessor], ([$flatData, $xGet, $yGet, $xRange, $yRange, $xScale, $yScale, $xAccessor, $yAccessor]) => {
10
10
  return function getter(item) {
11
11
  if (isScaleBand($yScale)) {
@@ -13,8 +13,8 @@ export function createDimensionGetter(context, options) {
13
13
  const y1Scale = groupBy
14
14
  ? groupScaleBand($yScale, $flatData, groupBy, options?.groupPadding)
15
15
  : null;
16
- const y = firstValue($yGet(item)) + (y1Scale ? y1Scale(item[groupBy]) : 0) + padding / 2;
17
- const height = Math.max(0, $yScale.bandwidth ? (y1Scale ? y1Scale.bandwidth() : $yScale.bandwidth()) - padding : 0);
16
+ const y = firstValue($yGet(item)) + (y1Scale ? y1Scale(item[groupBy]) : 0) + inset / 2;
17
+ const height = Math.max(0, $yScale.bandwidth ? (y1Scale ? y1Scale.bandwidth() : $yScale.bandwidth()) - inset : 0);
18
18
  const _x = options?.x
19
19
  ? typeof options.x === 'string'
20
20
  ? (d) => d[options.x]
@@ -55,8 +55,8 @@ export function createDimensionGetter(context, options) {
55
55
  const x1Scale = groupBy
56
56
  ? groupScaleBand($xScale, $flatData, groupBy, options?.groupPadding)
57
57
  : null;
58
- const x = firstValue($xGet(item)) + (x1Scale ? x1Scale(item[groupBy]) : 0) + padding / 2;
59
- const width = Math.max(0, $xScale.bandwidth ? (x1Scale ? x1Scale.bandwidth() : $xScale.bandwidth()) - padding : 0);
58
+ const x = firstValue($xGet(item)) + (x1Scale ? x1Scale(item[groupBy]) : 0) + inset / 2;
59
+ const width = Math.max(0, $xScale.bandwidth ? (x1Scale ? x1Scale.bandwidth() : $xScale.bandwidth()) - inset : 0);
60
60
  const _y = options?.y
61
61
  ? typeof options.y === 'string'
62
62
  ? (d) => d[options.y]
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.24.3",
7
+ "version": "0.25.0",
8
8
  "scripts": {
9
9
  "dev": "vite dev",
10
10
  "build": "vite build",
@@ -23,52 +23,52 @@
23
23
  "devDependencies": {
24
24
  "@rollup/plugin-dsv": "^3.0.4",
25
25
  "@sveltejs/adapter-vercel": "^3.0.3",
26
- "@sveltejs/kit": "^1.25.2",
26
+ "@sveltejs/kit": "^1.27.2",
27
27
  "@sveltejs/package": "^2.2.2",
28
28
  "@svitejs/changesets-changelog-github-compact": "^1.1.0",
29
29
  "@tailwindcss/typography": "^0.5.10",
30
- "@types/d3-array": "^3.0.8",
31
- "@types/d3-delaunay": "^6.0.2",
32
- "@types/d3-dsv": "^3.0.4",
33
- "@types/d3-geo": "^3.0.5",
34
- "@types/d3-hierarchy": "^3.1.4",
35
- "@types/d3-interpolate": "^3.0.2",
36
- "@types/d3-interpolate-path": "^2.0.1",
37
- "@types/d3-quadtree": "^3.0.3",
38
- "@types/d3-random": "^3.0.1",
39
- "@types/d3-sankey": "^0.12.2",
40
- "@types/d3-scale": "^4.0.5",
41
- "@types/d3-scale-chromatic": "^3.0.0",
42
- "@types/d3-shape": "^3.1.3",
43
- "@types/lodash-es": "^4.17.9",
30
+ "@types/d3-array": "^3.0.9",
31
+ "@types/d3-delaunay": "^6.0.3",
32
+ "@types/d3-dsv": "^3.0.5",
33
+ "@types/d3-geo": "^3.0.6",
34
+ "@types/d3-hierarchy": "^3.1.5",
35
+ "@types/d3-interpolate": "^3.0.3",
36
+ "@types/d3-interpolate-path": "^2.0.2",
37
+ "@types/d3-quadtree": "^3.0.4",
38
+ "@types/d3-random": "^3.0.2",
39
+ "@types/d3-sankey": "^0.12.3",
40
+ "@types/d3-scale": "^4.0.6",
41
+ "@types/d3-scale-chromatic": "^3.0.1",
42
+ "@types/d3-shape": "^3.1.4",
43
+ "@types/lodash-es": "^4.17.10",
44
44
  "@types/marked": "^6.0.0",
45
- "@types/shapefile": "^0.6.2",
46
- "@types/topojson-client": "^3.1.2",
45
+ "@types/shapefile": "^0.6.3",
46
+ "@types/topojson-client": "^3.1.3",
47
47
  "autoprefixer": "^10.4.16",
48
48
  "execa": "^8.0.1",
49
- "marked": "^9.1.2",
49
+ "marked": "^9.1.3",
50
50
  "mdsvex": "^0.11.0",
51
51
  "prettier": "^3.0.3",
52
52
  "prettier-plugin-svelte": "^3.0.3",
53
53
  "prism-themes": "^1.9.0",
54
54
  "rehype-slug": "^6.0.0",
55
- "svelte": "^4.2.1",
55
+ "svelte": "^4.2.2",
56
56
  "svelte-check": "^3.5.2",
57
- "svelte-json-tree": "^2.1.0",
57
+ "svelte-json-tree": "^2.2.0",
58
58
  "svelte-preprocess": "^5.0.4",
59
59
  "svelte2tsx": "^0.6.23",
60
- "tailwindcss": "^3.3.3",
60
+ "tailwindcss": "^3.3.5",
61
61
  "tslib": "^2.6.2",
62
62
  "typescript": "^5.2.2",
63
63
  "unist-util-visit": "^5.0.0",
64
64
  "us-atlas": "^3.0.1",
65
- "vite": "^4.4.11"
65
+ "vite": "^4.5.0"
66
66
  },
67
67
  "type": "module",
68
68
  "dependencies": {
69
69
  "@changesets/cli": "^2.26.2",
70
70
  "@mdi/js": "^7.3.67",
71
- "@types/d3-time": "^3.0.1",
71
+ "@types/d3-time": "^3.0.2",
72
72
  "@vercel/analytics": "^1.1.1",
73
73
  "d3-array": "^3.2.4",
74
74
  "d3-delaunay": "^6.0.4",
@@ -89,7 +89,7 @@
89
89
  "layercake": "^8.0.2",
90
90
  "lodash-es": "^4.17.21",
91
91
  "shapefile": "^0.6.6",
92
- "svelte-ux": "^0.53.0",
92
+ "svelte-ux": "^0.53.6",
93
93
  "topojson-client": "^3.1.0"
94
94
  },
95
95
  "peerDependencies": {
@@ -1,34 +0,0 @@
1
- <script>import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
2
- import { Button, Field } from 'svelte-ux';
3
- export let value;
4
- export let min = 0;
5
- export let max = 100;
6
- export let step = 1;
7
- </script>
8
-
9
- <Field let:id classes={{ input: 'mt-2 mb-1' }} {...$$restProps}>
10
- <span slot="prepend">
11
- <Button
12
- icon={mdiChevronLeft}
13
- on:click={() => (value -= value > min ? step : 0)}
14
- class="mr-2"
15
- size="sm"
16
- />
17
- </span>
18
-
19
- <input type="range" bind:value {min} {max} {step} {id} class="h-6 w-full" />
20
- <span class="ml-2 text-sm text-black/50 tabular-nums text-right inline-grid">
21
- <span class="col-span-full row-span-full invisible">{min}</span>
22
- <span class="col-span-full row-span-full">{value}</span>
23
- <span class="col-span-full row-span-full invisible">{max}</span>
24
- </span>
25
-
26
- <span slot="append">
27
- <Button
28
- icon={mdiChevronRight}
29
- on:click={() => (value += value < max ? step : 0)}
30
- class="ml-2"
31
- size="sm"
32
- />
33
- </span>
34
- </Field>
@@ -1,20 +0,0 @@
1
- import { SvelteComponentTyped } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- [x: string]: any;
5
- value: number;
6
- min?: number | undefined;
7
- max?: number | undefined;
8
- step?: number | undefined;
9
- };
10
- events: {
11
- [evt: string]: CustomEvent<any>;
12
- };
13
- slots: {};
14
- };
15
- export type RangeFieldProps = typeof __propDef.props;
16
- export type RangeFieldEvents = typeof __propDef.events;
17
- export type RangeFieldSlots = typeof __propDef.slots;
18
- export default class RangeField extends SvelteComponentTyped<RangeFieldProps, RangeFieldEvents, RangeFieldSlots> {
19
- }
20
- export {};