layerchart 0.43.1 → 0.43.3

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.
@@ -2,6 +2,7 @@
2
2
  import { chartContext } from './ChartContext.svelte';
3
3
  import Area from './Area.svelte';
4
4
  import Spline from './Spline.svelte';
5
+ import { chartDataArray } from '../utils/common.js';
5
6
  const { data, rGet } = chartContext();
6
7
  export let curve = undefined;
7
8
  export let defined = undefined;
@@ -9,7 +10,7 @@ export let opacity = 0.3;
9
10
  export let line = false;
10
11
  export let tweened = undefined;
11
12
  // Render in reverse order so bottom stacks are rendered last (and stack above the upper stacks). Fixes when upper stack has 0 value
12
- $: lineData = [...$data].reverse();
13
+ $: lineData = [...chartDataArray($data)].reverse();
13
14
  </script>
14
15
 
15
16
  {#if line}
@@ -30,7 +31,7 @@ $: lineData = [...$data].reverse();
30
31
 
31
32
  <slot data={$data}>
32
33
  <g class="area-group">
33
- {#each $data as seriesData}
34
+ {#each chartDataArray($data) as seriesData}
34
35
  <Area
35
36
  data={seriesData}
36
37
  y0={(d) => d[0]}
@@ -2,6 +2,7 @@
2
2
  import { chartContext } from './ChartContext.svelte';
3
3
  import Bar from './Bar.svelte';
4
4
  import Rect from './Rect.svelte';
5
+ import { chartDataArray } from '../utils/common.js';
5
6
  const { data, rGet, config } = chartContext();
6
7
  /**
7
8
  * Override `x` from context. Useful for multiple Bar instances
@@ -26,7 +27,7 @@ export let groupPaddingOuter = 0;
26
27
 
27
28
  <g class="Bars">
28
29
  <slot>
29
- {#each $data as item}
30
+ {#each chartDataArray($data) as item}
30
31
  <Bar
31
32
  bar={item}
32
33
  {x}
@@ -1,7 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import { type ComponentProps } from 'svelte';
3
3
  import Rect from './Rect.svelte';
4
- import type { Accessor } from '../utils/common.js';
4
+ import { type Accessor } from '../utils/common.js';
5
5
  declare const __propDef: {
6
6
  props: {
7
7
  [x: string]: any;
@@ -6,6 +6,7 @@ import { chartContext } from './ChartContext.svelte';
6
6
  import Rect from './Rect.svelte';
7
7
  import MonthPath from './MonthPath.svelte';
8
8
  import Text from './Text.svelte';
9
+ import { chartDataArray } from '../utils/common.js';
9
10
  export let start;
10
11
  export let end;
11
12
  /**
@@ -30,7 +31,7 @@ $: [cellWidth, cellHeight] = Array.isArray(cellSize)
30
31
  : typeof cellSize === 'number'
31
32
  ? [cellSize, cellSize]
32
33
  : [chartCellSize, chartCellSize];
33
- $: dataByDate = data && $config.x ? index($data, (d) => $x(d)) : new Map();
34
+ $: dataByDate = data && $config.x ? index(chartDataArray($data), (d) => $x(d)) : new Map();
34
35
  $: cells = yearDays.map((date) => {
35
36
  const cellData = dataByDate.get(date) ?? { date };
36
37
  return {
@@ -286,7 +286,7 @@ declare class __sveltets_Render<TData> {
286
286
  left?: number | undefined;
287
287
  };
288
288
  data: unknown[] | SankeyGraph<any, any> | HierarchyNode<unknown>;
289
- flatData: import("svelte/store").Readable<unknown[] | HierarchyNode<unknown>>;
289
+ flatData: import("svelte/store").Readable<unknown[] | SankeyGraph<any, any> | HierarchyNode<unknown>>;
290
290
  };
291
291
  };
292
292
  }
@@ -21,7 +21,7 @@ type LayerCakeContext<TData> = {
21
21
  z: Readable<(d: TData) => any>;
22
22
  r: Readable<(d: TData) => any>;
23
23
  custom: Readable<Object>;
24
- data: Readable<TData[] | HierarchyNode<TData>>;
24
+ data: Readable<TData[] | HierarchyNode<TData> | SankeyGraph<any, any>>;
25
25
  xNice: Readable<number | boolean>;
26
26
  yNice: Readable<number | boolean>;
27
27
  zNice: Readable<number | boolean>;
@@ -77,7 +77,7 @@ declare class __sveltets_Render<TData> {
77
77
  slots(): {
78
78
  default: {
79
79
  data: SankeyGraph<any, any> | TData[] | HierarchyNode<TData>;
80
- flatData: Readable<TData[] | HierarchyNode<TData>>;
80
+ flatData: Readable<SankeyGraph<any, any> | TData[] | HierarchyNode<TData>>;
81
81
  };
82
82
  };
83
83
  }
@@ -8,7 +8,7 @@ import Bar from './Bar.svelte';
8
8
  import Rect from './Rect.svelte';
9
9
  import { tooltipContext } from './TooltipContext.svelte';
10
10
  import { isScaleBand } from '../utils/scales.js';
11
- const { flatData, x, xDomain, xScale, xRange, xGet, y, yDomain, yScale, yRange, yGet, rGet, config, } = chartContext();
11
+ const { data: contextData, flatData, x, xDomain, xScale, xRange, xGet, y, yDomain, yScale, yRange, yGet, rGet, config, } = chartContext();
12
12
  const tooltip = tooltipContext();
13
13
  /** Highlight specific data (annotate), espect uses tooltip data */
14
14
  export let data = undefined;
@@ -142,24 +142,81 @@ $: if (highlightData) {
142
142
  }
143
143
  // points
144
144
  if (Array.isArray(xCoord)) {
145
- // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
146
- _points = xCoord.filter(notNull).map((xItem, i) => ({
147
- x: xItem + xOffset,
148
- y: $yGet(highlightData) + yOffset,
149
- }));
145
+ // `x` accessor with multiple properties (ex. `x={['start', 'end']}` or `x={[0, 1]}`)
146
+ if (Array.isArray(highlightData)) {
147
+ // Stack series (ex. `y={[['apples', 'bananas', 'oranges']]})`)
148
+ // `highlightData` is a single stack layer/point, which is an 2 element array with an extra `data` property `[number, number, data: any]`.
149
+ const highlightSeriesPoint = highlightData;
150
+ // Ignore non-array data such as hierarchy and graph (make Typescript happy)
151
+ if (Array.isArray($contextData)) {
152
+ // For each series, find the related data point
153
+ const seriesPointsData = $contextData.map((series) => {
154
+ return {
155
+ series,
156
+ point: series.find((d) => $y(d) === $y(highlightSeriesPoint)),
157
+ };
158
+ });
159
+ _points = seriesPointsData.map((seriesPoint, i) => ({
160
+ x: $xScale(seriesPoint.point[1]) + xOffset,
161
+ y: yCoord + yOffset,
162
+ fill: $config.r ? $rGet(seriesPoint.series) : null,
163
+ }));
164
+ }
165
+ }
166
+ else {
167
+ // Multi series / etc (ex. `y={['apples', 'bananas', 'oranges']}`)
168
+ _points = xCoord.filter(notNull).map((xItem, i) => {
169
+ const $key = $config.x[i];
170
+ return {
171
+ x: xItem + xOffset,
172
+ y: $xGet(highlightData) + yOffset,
173
+ // TODO: is there a better way to expose the series key/value?
174
+ fill: $config.r ? $rGet({ ...highlightData, $key }) : null,
175
+ };
176
+ });
177
+ }
150
178
  }
151
- else if (Array.isArray(highlightData)) {
152
- // Stack series
153
- _points = highlightData.map((yValue, i) => ({
154
- x: xCoord + xOffset,
155
- y: $yScale(yValue) + yOffset,
156
- }));
179
+ else if (Array.isArray(yCoord)) {
180
+ // `y` accessor with multiple properties (ex. `y={['apples', 'bananas', 'oranges']}` or `y={[0, 1]})
181
+ if (Array.isArray(highlightData)) {
182
+ // Stack series (ex. `y={[['apples', 'bananas', 'oranges']]})`)
183
+ // `highlightData` is a single stack layer/point, which is an 2 element array with an extra `data` property `[number, number, data: any]`.
184
+ const highlightSeriesPoint = highlightData;
185
+ // Ignore non-array data such as hierarchy and graph (make Typescript happy)
186
+ if (Array.isArray($contextData)) {
187
+ // For each series, find the related data point
188
+ const seriesPointsData = $contextData.map((series) => {
189
+ return {
190
+ series,
191
+ point: series.find((d) => $x(d) === $x(highlightSeriesPoint)),
192
+ };
193
+ });
194
+ _points = seriesPointsData.map((seriesPoint, i) => ({
195
+ x: xCoord + xOffset,
196
+ y: $yScale(seriesPoint.point[1]) + yOffset,
197
+ fill: $config.r ? $rGet(seriesPoint.series) : null,
198
+ }));
199
+ }
200
+ }
201
+ else {
202
+ // Multi series / etc (ex. `y={['apples', 'bananas', 'oranges']}`)
203
+ _points = yCoord.filter(notNull).map((yItem, i) => {
204
+ const $key = $config.y[i];
205
+ return {
206
+ x: $xGet(highlightData) + xOffset,
207
+ y: yItem + yOffset,
208
+ // TODO: is there a better way to expose the series key/value?
209
+ fill: $config.r ? $rGet({ ...highlightData, $key }) : null,
210
+ };
211
+ });
212
+ }
157
213
  }
158
214
  else {
159
215
  _points = [
160
216
  {
161
217
  x: xCoord + xOffset,
162
218
  y: $yGet(highlightData) + yOffset,
219
+ fill: $config.r ? $rGet(highlightData) : null,
163
220
  },
164
221
  ];
165
222
  }
@@ -226,18 +283,16 @@ $: if (highlightData) {
226
283
  {#if points}
227
284
  <slot name="points" points={_points}>
228
285
  {#each _points as point}
229
- <!-- TODO: Improve color with stacked data -->
230
- {@const fill = $config.r ? $rGet(highlightData) : null}
231
286
  <Circle
232
287
  spring={motion}
233
288
  cx={point.x}
234
289
  cy={point.y}
290
+ fill={point.fill}
235
291
  r={4}
236
- {fill}
237
292
  {...typeof points === 'object' ? points : null}
238
293
  class={cls(
239
294
  'stroke-[6] stroke-white [paint-order:stroke] drop-shadow',
240
- !fill && 'fill-primary',
295
+ !point.fill && 'fill-primary',
241
296
  typeof points === 'object' ? points.class : null
242
297
  )}
243
298
  />
@@ -32,8 +32,8 @@ declare const __propDef: {
32
32
  bar: boolean | Partial<{
33
33
  [x: string]: any;
34
34
  bar: Object;
35
- x?: import("../utils/common").Accessor;
36
- y?: import("../utils/common").Accessor;
35
+ x?: import("..").Accessor;
36
+ y?: import("..").Accessor;
37
37
  fill?: string | undefined;
38
38
  stroke?: string;
39
39
  strokeWidth?: number;
@@ -59,6 +59,7 @@ declare const __propDef: {
59
59
  points: {
60
60
  x: number;
61
61
  y: number;
62
+ fill: string;
62
63
  }[];
63
64
  };
64
65
  };
@@ -12,7 +12,7 @@ declare const __propDef: {
12
12
  tickValues?: any[] | undefined;
13
13
  tickFontSize?: number;
14
14
  tickLength?: number;
15
- placement?: ("center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right") | undefined;
15
+ placement?: ("center" | "left" | "right" | "bottom" | "top" | "top-left" | "top-right" | "bottom-left" | "bottom-right") | undefined;
16
16
  classes?: {
17
17
  root?: string;
18
18
  title?: string;
@@ -6,7 +6,7 @@ declare const __propDef: {
6
6
  y?: "pointer" | "data" | number | undefined;
7
7
  xOffset?: number;
8
8
  yOffset?: number;
9
- anchor?: "center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
9
+ anchor?: "center" | "left" | "right" | "bottom" | "top" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
10
10
  contained?: "container" | false;
11
11
  variant?: "default" | "invert" | "none";
12
12
  motion?: boolean;
@@ -133,7 +133,7 @@ function showTooltip(e, tooltipData) {
133
133
  return;
134
134
  }
135
135
  // If tooltipData not provided already (voronoi, etc), attempt to find it
136
- // TODO: When using bisect-x/y/band, values should be sorted. Tyipcally are for `x`, but not `y` (and band depends on if x or y scale)
136
+ // TODO: When using bisect-x/y/band, values should be sorted. Typically they are for `x`, but not `y` (and band depends on if x or y scale)
137
137
  if (tooltipData == null) {
138
138
  switch (mode) {
139
139
  case 'bisect-x': {
@@ -2,7 +2,7 @@ import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  [x: string]: any;
5
- placement?: "center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
5
+ placement?: "center" | "left" | "right" | "bottom" | "top" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
6
6
  orientation?: "horizontal" | "vertical";
7
7
  show?: ("reset" | "center" | "scrollMode" | "zoomIn" | "zoomOut")[];
8
8
  };
@@ -1,2 +1,6 @@
1
+ import type Chart from '../components/Chart.svelte';
2
+ import type { ComponentProps } from 'svelte';
1
3
  export type Accessor<TData = any> = number | string | ((d: TData) => any) | undefined | Accessor<TData>[];
2
4
  export declare function accessor<TData = any>(prop: Accessor<TData>): (d: TData) => any;
5
+ /** Guarantee chart data is an array */
6
+ export declare function chartDataArray<TData = any>(data: ComponentProps<Chart<TData>>['data']): any[];
@@ -8,7 +8,7 @@ export function accessor(prop) {
8
8
  return prop;
9
9
  }
10
10
  else if (typeof prop === 'string') {
11
- // path
11
+ // path string
12
12
  return (d) => get(d, prop);
13
13
  }
14
14
  else {
@@ -16,3 +16,18 @@ export function accessor(prop) {
16
16
  return (d) => d;
17
17
  }
18
18
  }
19
+ /** Guarantee chart data is an array */
20
+ export function chartDataArray(data) {
21
+ if (data == null) {
22
+ return [];
23
+ }
24
+ else if (Array.isArray(data)) {
25
+ return data;
26
+ }
27
+ else if ('nodes' in data) {
28
+ return data.nodes;
29
+ }
30
+ else {
31
+ return data.descendants();
32
+ }
33
+ }
@@ -1,3 +1,4 @@
1
+ export * from './common.js';
1
2
  export * from './geo.js';
2
3
  export * from './graph.js';
3
4
  export * from './hierarchy.js';
@@ -1,3 +1,4 @@
1
+ export * from './common.js';
1
2
  export * from './geo.js';
2
3
  export * from './graph.js';
3
4
  export * from './hierarchy.js';
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.43.1",
7
+ "version": "0.43.3",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.5",
10
10
  "@mdi/js": "^7.4.47",