layerchart 0.24.2 → 0.24.4

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.
@@ -0,0 +1,49 @@
1
+ <script>import { getContext } from 'svelte';
2
+ import { createDimensionGetter } from '../utils/rect';
3
+ import Rect from './Rect.svelte';
4
+ const { x: xContext, y: yContext, rGet, config } = getContext('LayerCake');
5
+ export let bar;
6
+ /**
7
+ * Override `x` from context. Useful for multiple Bar instances
8
+ */
9
+ export let x = $xContext;
10
+ /**
11
+ * Override `y` from context. Useful for multiple Bar instances
12
+ */
13
+ export let y = $yContext;
14
+ export let fill = undefined;
15
+ export let stroke = 'black';
16
+ export let strokeWidth = 0;
17
+ export let radius = 0;
18
+ export let getProps = undefined;
19
+ export let padding = 0;
20
+ export let groupBy = undefined;
21
+ export let groupPaddingInner = 0.2;
22
+ export let groupPaddingOuter = 0;
23
+ export let spring = undefined;
24
+ export let tweened = undefined;
25
+ $: if (stroke === null || stroke === undefined)
26
+ stroke = 'black';
27
+ $: getDimensions = createDimensionGetter(getContext('LayerCake'), {
28
+ x,
29
+ y,
30
+ groupBy,
31
+ padding,
32
+ groupPadding: {
33
+ inner: groupPaddingInner,
34
+ outer: groupPaddingOuter,
35
+ },
36
+ });
37
+ </script>
38
+
39
+ <Rect
40
+ {fill}
41
+ {spring}
42
+ {tweened}
43
+ {stroke}
44
+ stroke-width={strokeWidth}
45
+ rx={radius}
46
+ {...$getDimensions(bar)}
47
+ {...$$restProps}
48
+ on:click
49
+ />
@@ -0,0 +1,37 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { spring as springStore, tweened as tweenedStore } from 'svelte/motion';
3
+ declare const __propDef: {
4
+ props: {
5
+ [x: string]: any;
6
+ bar: Object;
7
+ x?: any;
8
+ y?: any;
9
+ fill?: string | undefined;
10
+ stroke?: string | undefined;
11
+ strokeWidth?: number | undefined;
12
+ radius?: number | undefined;
13
+ getProps?: ((obj: {
14
+ value: any;
15
+ item: any;
16
+ index: number;
17
+ }) => any) | undefined;
18
+ padding?: number | undefined;
19
+ groupBy?: string | undefined;
20
+ groupPaddingInner?: number | undefined;
21
+ groupPaddingOuter?: number | undefined;
22
+ spring?: boolean | Parameters<typeof springStore>[1];
23
+ tweened?: boolean | Parameters<typeof tweenedStore>[1];
24
+ };
25
+ events: {
26
+ click: MouseEvent;
27
+ } & {
28
+ [evt: string]: CustomEvent<any>;
29
+ };
30
+ slots: {};
31
+ };
32
+ export type BarProps = typeof __propDef.props;
33
+ export type BarEvents = typeof __propDef.events;
34
+ export type BarSlots = typeof __propDef.slots;
35
+ export default class Bar extends SvelteComponentTyped<BarProps, BarEvents, BarSlots> {
36
+ }
37
+ export {};
@@ -1,22 +1,17 @@
1
1
  <script>import { getContext } from 'svelte';
2
- import Rect from './Rect.svelte';
3
- import { createDimensionGetter } from '../utils/rect';
4
- const { data, xScale, x: xContext, y: yContext, rGet, config } = getContext('LayerCake');
2
+ import Bar from './Bar.svelte';
3
+ const { data, rGet, config } = getContext('LayerCake');
5
4
  /**
6
5
  * Override `x` from context. Useful for multiple Bar instances
7
6
  */
8
- export let x = $xContext;
9
- // Convert x to function
10
- $: _x = x ? (typeof x === 'string' ? (d) => d[x] : x) : $xContext;
7
+ export let x = undefined; // TODO: Update Type
11
8
  /**
12
9
  * Override `y` from context. Useful for multiple Bar instances
13
10
  */
14
- export let y = $yContext;
15
- $: _y = y ? (typeof y === 'string' ? (d) => d[y] : y) : $yContext;
11
+ export let y = undefined; // TODO: Update Type
16
12
  export let stroke = 'black';
17
13
  export let strokeWidth = 0;
18
14
  export let radius = 0;
19
- export let getKey = (item) => $xScale.bandwidth ? _x(item) : _y(item);
20
15
  export let getProps = undefined;
21
16
  /** Inset the rect for amount of padding. Useful with multiple bars (bullet, overlap, etc) */
22
17
  export let padding = 0;
@@ -26,31 +21,27 @@ export let tweened = undefined;
26
21
  export let groupBy = undefined;
27
22
  export let groupPaddingInner = 0.2;
28
23
  export let groupPaddingOuter = 0;
29
- $: getDimensions = createDimensionGetter(getContext('LayerCake'), {
30
- x,
31
- y,
32
- groupBy,
33
- padding,
34
- groupPadding: {
35
- inner: groupPaddingInner,
36
- outer: groupPaddingOuter,
37
- },
38
- });
39
24
  </script>
40
25
 
41
26
  <g class="Bars">
42
- {#each $data as item, index (getKey(item, index))}
43
- <Rect
44
- data-id={index}
45
- fill={$config.r ? $rGet(item) : null}
46
- {stroke}
47
- stroke-width={strokeWidth}
48
- rx={radius}
49
- {spring}
50
- {tweened}
51
- {...$getDimensions(item)}
52
- {...getProps?.({ value: _y(item), item, index })}
53
- {...$$restProps}
54
- />
55
- {/each}
27
+ <slot name="bars">
28
+ {#each $data as item, index}
29
+ <Bar
30
+ bar={item}
31
+ {x}
32
+ {y}
33
+ fill={$config.r ? $rGet(item) : null}
34
+ {stroke}
35
+ {strokeWidth}
36
+ {radius}
37
+ {spring}
38
+ {tweened}
39
+ {groupBy}
40
+ {padding}
41
+ {groupPaddingInner}
42
+ {groupPaddingOuter}
43
+ {...$$restProps}
44
+ />
45
+ {/each}
46
+ </slot>
56
47
  </g>
@@ -8,7 +8,6 @@ declare const __propDef: {
8
8
  stroke?: string | undefined;
9
9
  strokeWidth?: number | undefined;
10
10
  radius?: number | undefined;
11
- getKey?: ((item: any, index: number) => any) | undefined;
12
11
  getProps?: ((obj: {
13
12
  value: any;
14
13
  item: any;
@@ -24,7 +23,9 @@ declare const __propDef: {
24
23
  events: {
25
24
  [evt: string]: CustomEvent<any>;
26
25
  };
27
- slots: {};
26
+ slots: {
27
+ bars: {};
28
+ };
28
29
  };
29
30
  export type BarsProps = typeof __propDef.props;
30
31
  export type BarsEvents = typeof __propDef.events;
@@ -4,6 +4,7 @@ import { cls, notNull } from 'svelte-ux';
4
4
  import { isScaleBand } from '../utils/scales';
5
5
  import Circle from './Circle.svelte';
6
6
  import Line from './Line.svelte';
7
+ import Bar from './Bar.svelte';
7
8
  import Rect from './Rect.svelte';
8
9
  import { tooltipContext } from './TooltipContext.svelte';
9
10
  const { flatData, x, xDomain, xScale, xRange, xGet, y, yDomain, yScale, yRange, yGet, rGet, config, } = getContext('LayerCake');
@@ -15,6 +16,8 @@ export let points = false;
15
16
  export let lines = false;
16
17
  /** Show area and pass props to Rect */
17
18
  export let area = false;
19
+ /** Show bar and pass props to Rect */
20
+ export let bar = false;
18
21
  // TODO: Fix circle points being backwards for stack (see AreaStack)
19
22
  let _points = [];
20
23
  let _lines = [];
@@ -170,6 +173,24 @@ $: if ($tooltip.data) {
170
173
  </slot>
171
174
  {/if}
172
175
 
176
+ {#if bar}
177
+ <slot name="bar" bar={bar}>
178
+ <Bar
179
+ spring
180
+ x={typeof bar === 'object' ? bar.x : null}
181
+ y={typeof bar === 'object' ? bar.y : null}
182
+ padding={typeof bar === 'object' ? bar.padding : null}
183
+ stroke={typeof bar === 'object' ? bar.stroke : null}
184
+ strokeWidth={typeof bar === 'object' ? bar.strokeWidth : null}
185
+ radius={typeof bar === 'object' ? bar.radius : null}
186
+ bar={$tooltip.data}
187
+ class={cls(!bar.fill && 'fill-accent-500', typeof bar === 'object' ? bar.class : null)}
188
+ on:click
189
+ />
190
+ </slot>
191
+ {/if}
192
+
193
+
173
194
  {#if lines}
174
195
  <slot name="lines" lines={_lines}>
175
196
  {#each _lines as line}
@@ -43,6 +43,23 @@ declare const __propDef: {
43
43
  [prop: string]: import("svelte/motion").TweenedOptions<unknown> | undefined;
44
44
  } | undefined;
45
45
  } | undefined;
46
+ /** Show bar and pass props to Rect */ bar?: boolean | {
47
+ [x: string]: any;
48
+ x?: number | undefined;
49
+ initialX?: number | undefined;
50
+ y?: number | undefined;
51
+ initialY?: number | undefined;
52
+ width: number;
53
+ initialWidth?: number | undefined;
54
+ height: number;
55
+ initialHeight?: number | undefined;
56
+ spring?: boolean | import("svelte/motion").SpringOpts | {
57
+ [prop: string]: import("svelte/motion").SpringOpts | undefined;
58
+ } | undefined;
59
+ tweened?: boolean | import("svelte/motion").TweenedOptions<unknown> | {
60
+ [prop: string]: import("svelte/motion").TweenedOptions<unknown> | undefined;
61
+ } | undefined;
62
+ } | undefined;
46
63
  };
47
64
  events: {
48
65
  click: MouseEvent;
@@ -58,6 +75,25 @@ declare const __propDef: {
58
75
  height: number;
59
76
  };
60
77
  };
78
+ bar: {
79
+ bar: boolean | {
80
+ [x: string]: any;
81
+ x?: number | undefined;
82
+ initialX?: number | undefined;
83
+ y?: number | undefined;
84
+ initialY?: number | undefined;
85
+ width: number;
86
+ initialWidth?: number | undefined;
87
+ height: number;
88
+ initialHeight?: number | undefined;
89
+ spring?: boolean | import("svelte/motion").SpringOpts | {
90
+ [prop: string]: import("svelte/motion").SpringOpts | undefined;
91
+ } | undefined;
92
+ tweened?: boolean | import("svelte/motion").TweenedOptions<unknown> | {
93
+ [prop: string]: import("svelte/motion").TweenedOptions<unknown> | undefined;
94
+ } | undefined;
95
+ };
96
+ };
61
97
  lines: {
62
98
  lines: any[];
63
99
  };
@@ -58,9 +58,9 @@ $: endPoint = motionStore(undefined, {
58
58
  const point = pathEl.getPointAtLength(totalLength * t);
59
59
  return point;
60
60
  };
61
- }
61
+ },
62
62
  }
63
- : false
63
+ : false,
64
64
  });
65
65
  $: {
66
66
  if ($$slots.start || $$slots.end) {
@@ -82,7 +82,7 @@ $: {
82
82
  d={$tweened_d}
83
83
  {...$$restProps}
84
84
  class={cls('path-line fill-none', !$$props.stroke && 'stroke-black', $$props.class)}
85
- in:drawTransition={typeof draw === 'object' ? draw : undefined}
85
+ in:drawTransition|global={typeof draw === 'object' ? draw : undefined}
86
86
  on:click
87
87
  on:mousemove
88
88
  on:mouseleave
@@ -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;
@@ -140,7 +140,7 @@ function showTooltip(event, tooltipData) {
140
140
  }
141
141
  case 'bisect-x': {
142
142
  // `x` value at mouse/touch coordinate
143
- const xValueAtPoint = scaleInvert($xScale, localX);
143
+ const xValueAtPoint = scaleInvert($xScale, localX - $padding.left);
144
144
  const index = bisectX($flatData, xValueAtPoint, 1);
145
145
  const previousValue = $flatData[index - 1];
146
146
  const currentValue = $flatData[index];
@@ -149,7 +149,7 @@ function showTooltip(event, tooltipData) {
149
149
  }
150
150
  case 'bisect-y': {
151
151
  // `y` value at mouse/touch coordinate
152
- const yValueAtPoint = scaleInvert($yScale, localY);
152
+ const yValueAtPoint = scaleInvert($yScale, localY - $padding.left);
153
153
  const index = bisectY($flatData, yValueAtPoint, 1);
154
154
  const previousValue = $flatData[index - 1];
155
155
  const currentValue = $flatData[index];
@@ -280,7 +280,7 @@ $: if (mode === 'bounds' || mode === 'band') {
280
280
  {#if ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode)}
281
281
  <Html>
282
282
  <div
283
- class="absolute"
283
+ class="tooltip-trigger absolute"
284
284
  style:width="{$width}px"
285
285
  style:height="{$height}px"
286
286
  style:background={debug ? 'rgba(255 0 0 / .1)' : undefined}
@@ -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
@@ -1,13 +1,23 @@
1
- <script>// TODO: No longer copy from svelte-ux after prismjs is migrated to ESM (commonjs causes issue with Vite from another library)
1
+ <script>import { slide } from 'svelte/transition';
2
+ // TODO: No longer copy from svelte-ux after prismjs is migrated to ESM (commonjs causes issue with Vite from another library)
2
3
  import Prism from 'prismjs';
3
4
  import 'prism-svelte';
4
- import { mdiCodeTags, mdiContentCopy } from '@mdi/js';
5
- import { slide } from 'svelte/transition';
6
- import { Button } from 'svelte-ux';
5
+ import { mdiCodeTags, mdiContentCopy, mdiTable } from '@mdi/js';
6
+ import JsonTree from 'svelte-json-tree';
7
+ import { Button, CopyButton, Dialog, Toggle, Tooltip } from 'svelte-ux';
7
8
  export let code = undefined;
9
+ export let data = undefined;
8
10
  export let language = 'svelte';
9
11
  export let highlightedCode = Prism.highlight(code, Prism.languages.svelte, language);
10
12
  export let showCode = false;
13
+ let copyValue = null;
14
+ try {
15
+ // TODO: Improve handling of circular structures
16
+ copyValue = JSON.stringify(data, null, 2);
17
+ }
18
+ catch (e) {
19
+ console.error('Error capturing value to copy', e);
20
+ }
11
21
  </script>
12
22
 
13
23
  <div class="border border-black/20 rounded bg-white">
@@ -39,7 +49,55 @@ export let showCode = false;
39
49
  </div>
40
50
 
41
51
  {#if code}
42
- <Button icon={mdiCodeTags} class=" text-black/70 py-1" on:click={() => (showCode = !showCode)}>
43
- {showCode ? 'Hide' : 'Show'} Code
52
+ <Button icon={mdiCodeTags} class=" text-black/60 py-1" on:click={() => (showCode = !showCode)}>
53
+ {showCode ? 'Hide' : 'Show'} code
44
54
  </Button>
45
55
  {/if}
56
+
57
+ {#if data}
58
+ <Toggle let:on={open} let:toggle>
59
+ <Button icon={mdiTable} class=" text-black/60 py-1" on:click={toggle}>View data</Button>
60
+ <Dialog
61
+ {open}
62
+ on:close={toggle}
63
+ class="max-h-[98dvh] md:max-h-[90dvh] max-w-[98vw] md:max-w-[90vw] grid grid-rows-[auto,1fr,auto]"
64
+ >
65
+ <div class="grid grid-cols-[1fr,auto] gap-3 items-center p-4">
66
+ <div class="overflow-auto">
67
+ <div class="text-lg font-semibold">Chart data</div>
68
+ </div>
69
+
70
+ {#if copyValue}
71
+ <Tooltip title="Copy">
72
+ <CopyButton value={copyValue} variant="fill-light" color="accent" />
73
+ </Tooltip>
74
+ {/if}
75
+ </div>
76
+
77
+ <div class="overflow-auto px-4 py-2 bg-[#1e1e1e]">
78
+ <JsonTree
79
+ value={data}
80
+ defaultExpandedPaths={['$']}
81
+ shouldTreatIterableAsObject
82
+ --json-tree-property-color="#72a2d3"
83
+ --json-tree-string-color="#6cd1c7"
84
+ --json-tree-symbol-color="#6cd1c7"
85
+ --json-tree-boolean-color="#9681f7"
86
+ --json-tree-function-color="#e59b6f"
87
+ --json-tree-number-color="#9681f7"
88
+ --json-tree-label-color="#9ca0a5"
89
+ --json-tree-arrow-color="#e8eaed"
90
+ --json-tree-null-color="#81868a"
91
+ --json-tree-undefined-color="#81868a"
92
+ --json-tree-date-color="#9ca0a5"
93
+ --json-tree-operator-color="#e8eaed"
94
+ --json-tree-regex-color="#6cd1c7"
95
+ />
96
+ </div>
97
+
98
+ <div slot="actions">
99
+ <Button variant="fill" color="accent">Close</Button>
100
+ </div>
101
+ </Dialog>
102
+ </Toggle>
103
+ {/if}
@@ -3,6 +3,7 @@ import 'prism-svelte';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  code?: string | undefined;
6
+ data?: any | undefined;
6
7
  language?: string | undefined;
7
8
  highlightedCode?: any;
8
9
  showCode?: boolean | 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": "0.24.2",
7
+ "version": "0.24.4",
8
8
  "scripts": {
9
9
  "dev": "vite dev",
10
10
  "build": "vite build",
@@ -46,7 +46,7 @@
46
46
  "@types/topojson-client": "^3.1.2",
47
47
  "autoprefixer": "^10.4.16",
48
48
  "execa": "^8.0.1",
49
- "marked": "^9.1.1",
49
+ "marked": "^9.1.2",
50
50
  "mdsvex": "^0.11.0",
51
51
  "prettier": "^3.0.3",
52
52
  "prettier-plugin-svelte": "^3.0.3",
@@ -54,6 +54,7 @@
54
54
  "rehype-slug": "^6.0.0",
55
55
  "svelte": "^4.2.1",
56
56
  "svelte-check": "^3.5.2",
57
+ "svelte-json-tree": "^2.2.0",
57
58
  "svelte-preprocess": "^5.0.4",
58
59
  "svelte2tsx": "^0.6.23",
59
60
  "tailwindcss": "^3.3.3",
@@ -85,7 +86,7 @@
85
86
  "d3-tile": "^1.0.0",
86
87
  "d3-time": "^3.1.0",
87
88
  "date-fns": "^2.30.0",
88
- "layercake": "^8.0.0",
89
+ "layercake": "^8.0.2",
89
90
  "lodash-es": "^4.17.21",
90
91
  "shapefile": "^0.6.6",
91
92
  "svelte-ux": "^0.53.0",