layerchart 0.73.0 → 0.74.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.
@@ -5,7 +5,7 @@
5
5
  import Rect from './Rect.svelte';
6
6
  import Spline from './Spline.svelte';
7
7
 
8
- import { createDimensionGetter } from '../utils/rect.js';
8
+ import { createDimensionGetter, type Insets } from '../utils/rect.js';
9
9
  import { isScaleBand } from '../utils/scales.js';
10
10
  import { accessor, type Accessor } from '../utils/common.js';
11
11
  import { greatestAbs } from '@layerstack/utils';
@@ -54,7 +54,7 @@
54
54
  | 'bottom-left'
55
55
  | 'bottom-right' = 'all';
56
56
 
57
- export let inset = 0;
57
+ export let insets: Insets | undefined = undefined;
58
58
 
59
59
  export let spring: ComponentProps<Rect>['spring'] = undefined;
60
60
  export let tweened: ComponentProps<Rect>['tweened'] = undefined;
@@ -66,7 +66,7 @@
66
66
  y,
67
67
  x1,
68
68
  y1,
69
- inset,
69
+ insets,
70
70
  });
71
71
  $: dimensions = $getDimensions(bar) ?? { x: 0, y: 0, width: 0, height: 0 };
72
72
 
@@ -5,6 +5,7 @@
5
5
  import Bar from './Bar.svelte';
6
6
  import Rect from './Rect.svelte';
7
7
  import { chartDataArray, type Accessor } from '../utils/common.js';
8
+ import type { Insets } from '../index.js/utils/rect.js';
8
9
 
9
10
  const { data: contextData, cGet, config } = chartContext();
10
11
 
@@ -39,7 +40,7 @@
39
40
  export let fill: string | undefined = undefined;
40
41
 
41
42
  /** Inset the rect for amount of padding. Useful with multiple bars (bullet, overlap, etc) */
42
- export let inset = 0;
43
+ export let insets: Insets | undefined = undefined;
43
44
 
44
45
  /** Define unique value for {#each} `(key)` expressions to improve transitions. `index` position used by default */
45
46
  export let key: (d: any, index: number) => any = (d, i) => i;
@@ -66,7 +67,7 @@
66
67
  {stroke}
67
68
  {strokeWidth}
68
69
  {radius}
69
- {inset}
70
+ {insets}
70
71
  {spring}
71
72
  {tweened}
72
73
  on:click={() => onBarClick({ data: d })}
@@ -361,7 +361,7 @@
361
361
  spring={motion}
362
362
  x={typeof bar === 'object' ? bar.x : undefined}
363
363
  y={typeof bar === 'object' ? bar.y : undefined}
364
- inset={typeof bar === 'object' ? bar.inset : undefined}
364
+ insets={typeof bar === 'object' ? bar.insets : undefined}
365
365
  stroke={typeof bar === 'object' ? bar.stroke : undefined}
366
366
  strokeWidth={typeof bar === 'object' ? bar.strokeWidth : undefined}
367
367
  radius={typeof bar === 'object' ? bar.radius : undefined}
@@ -25,6 +25,7 @@
25
25
  type Accessor,
26
26
  } from '../../utils/common.js';
27
27
  import { asAny } from '../../utils/types.js';
28
+ import type { Insets } from '../../index.js/utils/rect.js';
28
29
 
29
30
  type ChartProps = ComponentProps<Chart<TData>>;
30
31
 
@@ -33,6 +34,7 @@
33
34
  grid?: typeof grid;
34
35
  bandPadding?: typeof bandPadding;
35
36
  groupPadding?: typeof groupPadding;
37
+ stackPadding?: typeof stackPadding;
36
38
  labels?: typeof labels;
37
39
  legend?: typeof legend;
38
40
  orientation?: typeof orientation;
@@ -84,6 +86,8 @@
84
86
  export let bandPadding = 0.4;
85
87
  /** Padding between group/series items when using 'seriesLayout="group"', applied to scaleBand().padding() */
86
88
  export let groupPadding = 0;
89
+ /** Padding between series items within bars when using 'seriesLayout="stack"' */
90
+ export let stackPadding = 0;
87
91
 
88
92
  /** Event dispatched with current tooltip data */
89
93
  export let onTooltipClick: (e: { data: any }) => void = () => {};
@@ -177,18 +181,41 @@
177
181
  }
178
182
 
179
183
  function getBarsProps(s: (typeof series)[number], i: number) {
180
- const valueAccesor = stackSeries
184
+ const isFirst = i == 0;
185
+ const isLast = i == series.length - 1;
186
+
187
+ const isStackLayout = seriesLayout.startsWith('stack');
188
+
189
+ let stackInsets: Insets | undefined = undefined;
190
+
191
+ if (isStackLayout) {
192
+ const stackInset = stackPadding / 2;
193
+ if (isVertical) {
194
+ stackInsets = {
195
+ bottom: isFirst ? undefined : stackInset,
196
+ top: isLast ? undefined : stackInset,
197
+ };
198
+ } else {
199
+ stackInsets = {
200
+ left: isFirst ? undefined : stackInset,
201
+ right: isLast ? undefined : stackInset,
202
+ };
203
+ }
204
+ }
205
+
206
+ const valueAccessor = stackSeries
181
207
  ? (d: any) => d.stackData[i]
182
208
  : (s.value ?? (s.data ? undefined : s.key));
183
209
  const barsProps: ComponentProps<Bars> = {
184
210
  data: s.data,
185
- x: !isVertical ? valueAccesor : undefined,
186
- y: isVertical ? valueAccesor : undefined,
211
+ x: !isVertical ? valueAccessor : undefined,
212
+ y: isVertical ? valueAccessor : undefined,
187
213
  x1: isVertical && groupSeries ? (d) => s.value ?? s.key : undefined,
188
214
  y1: !isVertical && groupSeries ? (d) => s.value ?? s.key : undefined,
189
- rounded: seriesLayout.startsWith('stack') && i !== series.length - 1 ? 'none' : 'edge',
215
+ rounded: isStackLayout && i !== series.length - 1 ? 'none' : 'edge',
190
216
  radius: 4,
191
217
  strokeWidth: 1,
218
+ insets: stackInsets,
192
219
  fill: s.color,
193
220
  onBarClick: (e) => onBarClick({ data: e.data, series: s }),
194
221
  ...props.bars,
@@ -1,5 +1,22 @@
1
1
  import type { ChartContext } from '../components/ChartContext.svelte';
2
2
  import { type Accessor } from './common.js';
3
+ /** A set of inset distances, applied to a rectangle to shrink or expand the area represented by that rectangle. */
4
+ export type Insets = {
5
+ /** Applies an inset all sides of a rectangle: `left`, `right`, `bottom`, and `top` */
6
+ all?: number;
7
+ /** Applies an inset all horizontal sides of a rectangle: `left`, and `right`, overriding `all` */
8
+ x?: number;
9
+ /** Applies an inset all vertical sides of a rectangle: `top`, and `bottom`, overriding `all` */
10
+ y?: number;
11
+ /** Applies an inset the left side of a rectangle, overriding `x` */
12
+ left?: number;
13
+ /** Applies an inset the right side of a rectangle, overriding `x` */
14
+ right?: number;
15
+ /** Applies an inset the top side of a rectangle, overriding `y` */
16
+ top?: number;
17
+ /** Applies an inset the bottom side of a rectangle, overriding `y` */
18
+ bottom?: number;
19
+ };
3
20
  type DimensionGetterOptions = {
4
21
  /** Override `x` accessor from context */
5
22
  x?: Accessor;
@@ -9,7 +26,7 @@ type DimensionGetterOptions = {
9
26
  x1?: Accessor;
10
27
  /** Override `y1` accessor from context */
11
28
  y1?: Accessor;
12
- inset?: number;
29
+ insets?: Insets;
13
30
  };
14
31
  export declare function createDimensionGetter<TData>(context: ChartContext<TData>, options?: DimensionGetterOptions): import("svelte/store").Readable<(item: any) => {
15
32
  x: any;
@@ -4,8 +4,8 @@ import { isScaleBand } from './scales.js';
4
4
  import { accessor } from './common.js';
5
5
  export function createDimensionGetter(context, options) {
6
6
  const { xScale, yScale, x: xAccessor, y: yAccessor, x1: x1Accessor, y1: y1Accessor, x1Scale, y1Scale, } = context;
7
- const inset = options?.inset ?? 0;
8
7
  return derived([xScale, x1Scale, yScale, y1Scale, xAccessor, yAccessor, x1Accessor, y1Accessor], ([$xScale, $x1Scale, $yScale, $y1Scale, $xAccessor, $yAccessor, $x1Accessor, $y1Accessor]) => {
8
+ const insets = resolveInsets(options?.insets);
9
9
  // Use `xscale.domain()` instead of `$xDomain` to include `nice()` being applied
10
10
  const [minXDomain, maxXDomain] = $xScale.domain();
11
11
  const [minYDomain, maxYDomain] = $yScale.domain();
@@ -17,9 +17,11 @@ export function createDimensionGetter(context, options) {
17
17
  return function getter(item) {
18
18
  if (isScaleBand($yScale)) {
19
19
  // Horizontal band
20
- const y = firstValue($yScale(_y(item)) ?? 0) + ($y1Scale ? $y1Scale(_y1(item)) : 0) + inset / 2;
20
+ const y = firstValue($yScale(_y(item)) ?? 0) + ($y1Scale ? $y1Scale(_y1(item)) : 0) + insets.top;
21
21
  const height = Math.max(0, $yScale.bandwidth
22
- ? ($y1Scale ? ($y1Scale.bandwidth?.() ?? 0) : $yScale.bandwidth()) - inset
22
+ ? ($y1Scale ? ($y1Scale.bandwidth?.() ?? 0) : $yScale.bandwidth()) -
23
+ insets.bottom -
24
+ insets.top
23
25
  : 0);
24
26
  const xValue = _x(item);
25
27
  let left = 0;
@@ -44,18 +46,17 @@ export function createDimensionGetter(context, options) {
44
46
  left = xValue;
45
47
  right = min([0, maxXDomain]);
46
48
  }
47
- return {
48
- x: $xScale(left),
49
- y,
50
- width: $xScale(right) - $xScale(left),
51
- height,
52
- };
49
+ const x = $xScale(left) + insets.left;
50
+ const width = Math.max(0, $xScale(right) - $xScale(left) - insets.left - insets.right);
51
+ return { x, y, width, height };
53
52
  }
54
53
  else {
55
54
  // Vertical band or linear
56
- const x = firstValue($xScale(_x(item))) + ($x1Scale ? $x1Scale(_x1(item)) : 0) + inset / 2;
55
+ const x = firstValue($xScale(_x(item))) + ($x1Scale ? $x1Scale(_x1(item)) : 0) + insets.left;
57
56
  const width = Math.max(0, $xScale.bandwidth
58
- ? ($x1Scale ? ($x1Scale.bandwidth?.() ?? 0) : $xScale.bandwidth()) - inset
57
+ ? ($x1Scale ? ($x1Scale.bandwidth?.() ?? 0) : $xScale.bandwidth()) -
58
+ insets.left -
59
+ insets.right
59
60
  : 0);
60
61
  const yValue = _y(item);
61
62
  let top = 0;
@@ -80,12 +81,9 @@ export function createDimensionGetter(context, options) {
80
81
  top = min([0, maxYDomain]);
81
82
  bottom = yValue;
82
83
  }
83
- return {
84
- x,
85
- y: $yScale(top),
86
- width,
87
- height: $yScale(bottom) - $yScale(top),
88
- };
84
+ const y = $yScale(top) + insets.top;
85
+ const height = $yScale(bottom) - $yScale(top) - insets.bottom - insets.top;
86
+ return { x, y, width, height };
89
87
  }
90
88
  };
91
89
  });
@@ -97,3 +95,13 @@ export function createDimensionGetter(context, options) {
97
95
  export function firstValue(value) {
98
96
  return Array.isArray(value) ? value[0] : value;
99
97
  }
98
+ function resolveInsets(insets) {
99
+ const all = insets?.all ?? 0;
100
+ const x = insets?.x ?? all;
101
+ const y = insets?.y ?? all;
102
+ const left = insets?.left ?? x;
103
+ const right = insets?.right ?? x;
104
+ const top = insets?.top ?? y;
105
+ const bottom = insets?.bottom ?? y;
106
+ return { left, right, bottom, top };
107
+ }
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.73.0",
7
+ "version": "0.74.0",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.10",
10
10
  "@mdi/js": "^7.4.47",