layerchart 0.44.0 → 0.51.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.
Files changed (116) hide show
  1. package/dist/components/Arc.svelte +18 -1
  2. package/dist/components/Arc.svelte.d.ts +3 -0
  3. package/dist/components/Area.svelte +49 -18
  4. package/dist/components/Area.svelte.d.ts +0 -1
  5. package/dist/components/Axis.svelte +2 -1
  6. package/dist/components/Axis.svelte.d.ts +2 -1
  7. package/dist/components/Bar.svelte +18 -8
  8. package/dist/components/Bar.svelte.d.ts +6 -3
  9. package/dist/components/Bars.svelte +18 -11
  10. package/dist/components/Bars.svelte.d.ts +3 -3
  11. package/dist/components/Blur.svelte +1 -1
  12. package/dist/components/Brush.svelte +2 -1
  13. package/dist/components/Calendar.svelte +2 -2
  14. package/dist/components/Calendar.svelte.d.ts +1 -1
  15. package/dist/components/Chart.svelte +85 -25
  16. package/dist/components/Chart.svelte.d.ts +77 -37
  17. package/dist/components/ChartContext.svelte +124 -6
  18. package/dist/components/ChartContext.svelte.d.ts +50 -2
  19. package/dist/components/Circle.svelte +1 -1
  20. package/dist/components/CircleClipPath.svelte +1 -1
  21. package/dist/components/ClipPath.svelte +1 -1
  22. package/dist/components/GeoPath.svelte +1 -1
  23. package/dist/components/GeoPath.svelte.d.ts +1 -1
  24. package/dist/components/Highlight.svelte +45 -19
  25. package/dist/components/Highlight.svelte.d.ts +2 -3
  26. package/dist/components/HitCanvas.svelte +1 -1
  27. package/dist/components/Hull.svelte +1 -1
  28. package/dist/components/Labels.svelte +39 -73
  29. package/dist/components/Labels.svelte.d.ts +2 -5
  30. package/dist/components/Legend.svelte +5 -5
  31. package/dist/components/Legend.svelte.d.ts +2 -2
  32. package/dist/components/Line.svelte +1 -1
  33. package/dist/components/LinearGradient.svelte +1 -1
  34. package/dist/components/MotionPath.svelte +1 -1
  35. package/dist/components/Pie.svelte +18 -41
  36. package/dist/components/Pie.svelte.d.ts +2 -3
  37. package/dist/components/Points.svelte +110 -56
  38. package/dist/components/Points.svelte.d.ts +20 -2
  39. package/dist/components/RadialGradient.svelte +1 -1
  40. package/dist/components/Rect.svelte +2 -1
  41. package/dist/components/Rect.svelte.d.ts +1 -0
  42. package/dist/components/RectClipPath.svelte +1 -1
  43. package/dist/components/Rule.svelte +1 -1
  44. package/dist/components/Spline.svelte +26 -18
  45. package/dist/components/Spline.svelte.d.ts +1 -1
  46. package/dist/components/Text.svelte +1 -1
  47. package/dist/components/Threshold.svelte +19 -81
  48. package/dist/components/Threshold.svelte.d.ts +13 -20
  49. package/dist/components/TransformContext.svelte.d.ts +2 -2
  50. package/dist/components/TransformControls.svelte +2 -1
  51. package/dist/components/TransformControls.svelte.d.ts +2 -2
  52. package/dist/components/Voronoi.svelte +15 -5
  53. package/dist/components/Voronoi.svelte.d.ts +6 -1
  54. package/dist/components/charts/AreaChart.svelte +182 -0
  55. package/dist/components/charts/AreaChart.svelte.d.ts +261 -0
  56. package/dist/components/charts/BarChart.svelte +207 -0
  57. package/dist/components/charts/BarChart.svelte.d.ts +241 -0
  58. package/dist/components/charts/LineChart.svelte +138 -0
  59. package/dist/components/charts/LineChart.svelte.d.ts +260 -0
  60. package/dist/components/charts/PieChart.svelte +146 -0
  61. package/dist/components/charts/PieChart.svelte.d.ts +220 -0
  62. package/dist/components/charts/ScatterChart.svelte +133 -0
  63. package/dist/components/charts/ScatterChart.svelte.d.ts +236 -0
  64. package/dist/components/charts/index.d.ts +5 -0
  65. package/dist/components/charts/index.js +5 -0
  66. package/dist/components/index.d.ts +2 -6
  67. package/dist/components/index.js +3 -6
  68. package/dist/components/layout/Canvas.svelte +1 -1
  69. package/dist/components/layout/Html.svelte +1 -1
  70. package/dist/components/layout/Svg.svelte +14 -4
  71. package/dist/components/layout/Svg.svelte.d.ts +1 -0
  72. package/dist/components/{Tooltip.svelte → tooltip/Tooltip.svelte} +5 -28
  73. package/dist/components/{Tooltip.svelte.d.ts → tooltip/Tooltip.svelte.d.ts} +1 -5
  74. package/dist/components/{TooltipContext.svelte → tooltip/TooltipContext.svelte} +20 -12
  75. package/dist/components/tooltip/TooltipHeader.svelte +21 -0
  76. package/dist/components/tooltip/TooltipHeader.svelte.d.ts +23 -0
  77. package/dist/components/tooltip/TooltipItem.svelte +37 -0
  78. package/dist/components/{TooltipItem.svelte.d.ts → tooltip/TooltipItem.svelte.d.ts} +4 -1
  79. package/dist/components/tooltip/TooltipList.svelte +12 -0
  80. package/dist/components/tooltip/TooltipList.svelte.d.ts +18 -0
  81. package/dist/components/tooltip/TooltipSeparator.svelte +4 -0
  82. package/dist/components/tooltip/index.d.ts +6 -0
  83. package/dist/components/tooltip/index.js +6 -0
  84. package/dist/docs/Blockquote.svelte +2 -1
  85. package/dist/docs/Code.svelte +2 -1
  86. package/dist/docs/CurveMenuField.svelte +2 -1
  87. package/dist/docs/GeoDebug.svelte +3 -1
  88. package/dist/docs/Json.svelte +1 -1
  89. package/dist/docs/Preview.svelte +2 -1
  90. package/dist/docs/TransformDebug.svelte +2 -1
  91. package/dist/utils/common.d.ts +1 -1
  92. package/dist/utils/common.js +2 -2
  93. package/dist/utils/common.test.d.ts +8 -0
  94. package/dist/utils/common.test.js +38 -0
  95. package/dist/utils/event.js +1 -1
  96. package/dist/utils/genData.d.ts +2 -2
  97. package/dist/utils/genData.js +20 -20
  98. package/dist/utils/math.d.ts +2 -2
  99. package/dist/utils/math.js +8 -2
  100. package/dist/utils/rect.d.ts +4 -10
  101. package/dist/utils/rect.js +15 -19
  102. package/dist/utils/scales.d.ts +8 -2
  103. package/dist/utils/scales.js +15 -1
  104. package/dist/utils/stack.d.ts +2 -2
  105. package/dist/utils/stack.js +37 -20
  106. package/dist/utils/stack.test.d.ts +6 -0
  107. package/dist/utils/stack.test.js +136 -0
  108. package/dist/utils/string.js +41 -0
  109. package/dist/utils/ticks.js +1 -2
  110. package/package.json +9 -3
  111. package/dist/components/AreaStack.svelte +0 -47
  112. package/dist/components/AreaStack.svelte.d.ts +0 -28
  113. package/dist/components/TooltipItem.svelte +0 -26
  114. package/dist/components/TooltipSeparator.svelte +0 -4
  115. /package/dist/components/{TooltipContext.svelte.d.ts → tooltip/TooltipContext.svelte.d.ts} +0 -0
  116. /package/dist/components/{TooltipSeparator.svelte.d.ts → tooltip/TooltipSeparator.svelte.d.ts} +0 -0
@@ -0,0 +1,23 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ [x: string]: any;
5
+ color?: string | undefined;
6
+ classes?: {
7
+ root?: string;
8
+ color?: string;
9
+ } | undefined;
10
+ };
11
+ events: {
12
+ [evt: string]: CustomEvent<any>;
13
+ };
14
+ slots: {
15
+ default: {};
16
+ };
17
+ };
18
+ export type TooltipHeaderProps = typeof __propDef.props;
19
+ export type TooltipHeaderEvents = typeof __propDef.events;
20
+ export type TooltipHeaderSlots = typeof __propDef.slots;
21
+ export default class TooltipHeader extends SvelteComponentTyped<TooltipHeaderProps, TooltipHeaderEvents, TooltipHeaderSlots> {
22
+ }
23
+ export {};
@@ -0,0 +1,37 @@
1
+ <script>import { format as formatUtil } from '@layerstack/utils';
2
+ import { cls } from '@layerstack/tailwind';
3
+ export let label;
4
+ /** Value to be formatted and displayed. Can also be passed as default slot */
5
+ export let value = undefined;
6
+ export let format = undefined;
7
+ export let valueAlign = 'left';
8
+ export let color = undefined;
9
+ export let classes = {};
10
+ </script>
11
+
12
+ <div class={cls('contents', classes.root, $$props.class)} {...$$restProps}>
13
+ <div class={cls('label', 'flex items-center gap-2 whitespace-nowrap', classes.label)}>
14
+ {#if color}
15
+ <div
16
+ class={cls('color', 'inline-block size-2 rounded-full bg-[--color]', classes.color)}
17
+ style:--color={color}
18
+ ></div>
19
+ {/if}
20
+ <slot name="label">{label}</slot>
21
+ </div>
22
+
23
+ <div
24
+ class={cls(
25
+ 'value',
26
+ 'tabular-nums',
27
+ {
28
+ 'text-right': valueAlign === 'right',
29
+ 'text-center': valueAlign === 'center',
30
+ },
31
+ classes.value,
32
+ $$props.class
33
+ )}
34
+ >
35
+ <slot>{format ? formatUtil(value, format) : value}</slot>
36
+ </div>
37
+ </div>
@@ -1,5 +1,5 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import { type FormatType } from 'svelte-ux';
2
+ import { type FormatType } from '@layerstack/utils';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  [x: string]: any;
@@ -7,9 +7,12 @@ declare const __propDef: {
7
7
  value?: any;
8
8
  format?: FormatType | undefined;
9
9
  valueAlign?: ("left" | "right" | "center") | undefined;
10
+ color?: string | undefined;
10
11
  classes?: {
12
+ root?: string;
11
13
  label?: string;
12
14
  value?: string;
15
+ color?: string;
13
16
  } | undefined;
14
17
  };
15
18
  events: {
@@ -0,0 +1,12 @@
1
+ <script>import { cls } from '@layerstack/tailwind';
2
+ </script>
3
+
4
+ <div
5
+ class={cls(
6
+ 'TooltipList',
7
+ 'grid grid-cols-[1fr,auto] gap-x-2 gap-y-1 items-center',
8
+ $$props.class
9
+ )}
10
+ >
11
+ <slot />
12
+ </div>
@@ -0,0 +1,18 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ [x: string]: any;
5
+ };
6
+ events: {
7
+ [evt: string]: CustomEvent<any>;
8
+ };
9
+ slots: {
10
+ default: {};
11
+ };
12
+ };
13
+ export type TooltipListProps = typeof __propDef.props;
14
+ export type TooltipListEvents = typeof __propDef.events;
15
+ export type TooltipListSlots = typeof __propDef.slots;
16
+ export default class TooltipList extends SvelteComponentTyped<TooltipListProps, TooltipListEvents, TooltipListSlots> {
17
+ }
18
+ export {};
@@ -0,0 +1,4 @@
1
+ <script>import { cls } from '@layerstack/tailwind';
2
+ </script>
3
+
4
+ <div class={cls('rounded bg-surface-content/20 my-1 col-span-full h-px', $$props.class)} />
@@ -0,0 +1,6 @@
1
+ export { default as Context } from './TooltipContext.svelte';
2
+ export { default as Header } from './TooltipHeader.svelte';
3
+ export { default as Item } from './TooltipItem.svelte';
4
+ export { default as List } from './TooltipList.svelte';
5
+ export { default as Separator } from './TooltipSeparator.svelte';
6
+ export { default as Root } from './Tooltip.svelte';
@@ -0,0 +1,6 @@
1
+ export { default as Context } from './TooltipContext.svelte';
2
+ export { default as Header } from './TooltipHeader.svelte';
3
+ export { default as Item } from './TooltipItem.svelte';
4
+ export { default as List } from './TooltipList.svelte';
5
+ export { default as Separator } from './TooltipSeparator.svelte';
6
+ export { default as Root } from './Tooltip.svelte';
@@ -1,5 +1,6 @@
1
1
  <script>import { mdiInformation } from '@mdi/js';
2
- import { Icon, cls } from 'svelte-ux';
2
+ import { Icon } from 'svelte-ux';
3
+ import { cls } from '@layerstack/tailwind';
3
4
  </script>
4
5
 
5
6
  <div
@@ -1,6 +1,7 @@
1
1
  <script>import Prism from 'prismjs';
2
2
  import 'prism-svelte';
3
- import { CopyButton, cls } from 'svelte-ux';
3
+ import { CopyButton } from 'svelte-ux';
4
+ import { cls } from '@layerstack/tailwind';
4
5
  export let source = null;
5
6
  export let language = 'svelte';
6
7
  export let highlightedSource = source
@@ -1,5 +1,6 @@
1
1
  <script>import * as d3shapes from 'd3-shape';
2
- import { MenuField, entries } from 'svelte-ux';
2
+ import { MenuField } from 'svelte-ux';
3
+ import { entries } from '@layerstack/utils';
3
4
  export let value = d3shapes['curveLinear'];
4
5
  export let showOpenClosed = false;
5
6
  const options = entries(d3shapes)
@@ -1,4 +1,6 @@
1
- <script>import { format, Checkbox, cls } from 'svelte-ux';
1
+ <script>import { Checkbox } from 'svelte-ux';
2
+ import { cls } from '@layerstack/tailwind';
3
+ import { format } from '@layerstack/utils';
2
4
  import { chartContext } from '../components/ChartContext.svelte';
3
5
  import { geoContext } from '../components/GeoContext.svelte';
4
6
  const { width, height } = chartContext();
@@ -1,5 +1,5 @@
1
1
  <script>import JsonTree from 'svelte-json-tree';
2
- import { cls } from 'svelte-ux';
2
+ import { cls } from '@layerstack/tailwind';
3
3
  export let value;
4
4
  export let defaultExpandedPaths = ['$'];
5
5
  </script>
@@ -3,7 +3,8 @@
3
3
  import Prism from 'prismjs';
4
4
  import 'prism-svelte';
5
5
  import { mdiCodeTags, mdiTable } from '@mdi/js';
6
- import { Button, CopyButton, Dialog, Toggle, Tooltip, cls } from 'svelte-ux';
6
+ import { Button, CopyButton, Dialog, Toggle, Tooltip } from 'svelte-ux';
7
+ import { cls } from '@layerstack/tailwind';
7
8
  import Code from './Code.svelte';
8
9
  import Json from './Json.svelte';
9
10
  export let code = undefined;
@@ -1,4 +1,5 @@
1
- <script>import { format, cls } from 'svelte-ux';
1
+ <script>import { cls } from '@layerstack/tailwind';
2
+ import { format } from '@layerstack/utils';
2
3
  import { transformContext } from '../components/TransformContext.svelte';
3
4
  const transform = transformContext();
4
5
  const { translate, scale } = transform;
@@ -1,6 +1,6 @@
1
1
  import type Chart from '../components/Chart.svelte';
2
2
  import type { ComponentProps } from 'svelte';
3
- export type Accessor<TData = any> = number | string | ((d: TData) => any) | undefined | Accessor<TData>[];
3
+ export type Accessor<TData = any> = number | string | ((d: TData) => any) | undefined | null | Accessor<TData>[];
4
4
  export declare function accessor<TData = any>(prop: Accessor<TData>): (d: TData) => any;
5
5
  /** Guarantee chart data is an array */
6
6
  export declare function chartDataArray<TData = any>(data: ComponentProps<Chart<TData>>['data']): any[];
@@ -7,8 +7,8 @@ export function accessor(prop) {
7
7
  // function
8
8
  return prop;
9
9
  }
10
- else if (typeof prop === 'string') {
11
- // path string
10
+ else if (typeof prop === 'string' || typeof prop === 'number') {
11
+ // path string or number (array index)
12
12
  return (d) => get(d, prop);
13
13
  }
14
14
  else {
@@ -0,0 +1,8 @@
1
+ export declare const testData: {
2
+ one: number;
3
+ two: number;
4
+ obj: {
5
+ value: number;
6
+ };
7
+ arr: string[];
8
+ };
@@ -0,0 +1,38 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { accessor } from './common.js';
3
+ export const testData = {
4
+ one: 1,
5
+ two: 2,
6
+ obj: { value: 2 },
7
+ arr: ['one', 'two', 'three'],
8
+ };
9
+ describe('accessor', () => {
10
+ it('string path', () => {
11
+ const actual = accessor('one')(testData);
12
+ expect(actual).toEqual(testData.one);
13
+ });
14
+ it('nested path', () => {
15
+ const actual = accessor('obj.value')(testData);
16
+ expect(actual).toEqual(testData.obj.value);
17
+ });
18
+ it('multiple properties', () => {
19
+ const actual = accessor(['one', 'two', 'obj.value', (d) => d.arr[0]])(testData);
20
+ expect(actual).toEqual([testData.one, testData.two, testData.obj.value, testData.arr[0]]);
21
+ });
22
+ it('multiple properties as numbers (index)', () => {
23
+ const actual = accessor([0, 1])(testData.arr);
24
+ expect(actual).toEqual([testData.arr[0], testData.arr[1]]);
25
+ });
26
+ it('function', () => {
27
+ const actual = accessor((d) => d.obj.value)(testData);
28
+ expect(actual).toEqual(testData.obj.value);
29
+ });
30
+ it('string path with array value', () => {
31
+ const actual = accessor('arr[0]')(testData);
32
+ expect(actual).toEqual(testData.arr[0]);
33
+ });
34
+ it('null returns full object', () => {
35
+ const actual = accessor(null)(testData);
36
+ expect(actual).toEqual(testData);
37
+ });
38
+ });
@@ -1,4 +1,4 @@
1
- import { isSVGElement, isSVGGraphicsElement, isSVGSVGElement, isTouchEvent } from 'svelte-ux';
1
+ import { isSVGElement, isSVGGraphicsElement, isSVGSVGElement, isTouchEvent, } from '@layerstack/utils';
2
2
  // See: https://github.com/airbnb/visx/blob/master/packages/visx-event/src/localPointGeneric.ts
3
3
  // TODO: Matches event.layerX/Y, but are deprecated (https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/layerX).
4
4
  // Similar and could be replaced by event.offsetX/Y (but not identical)
@@ -44,14 +44,14 @@ export declare function createTimeSeries<TKey extends string>(options: {
44
44
  endDate: Date;
45
45
  } & { [K in TKey]: number; })[];
46
46
  export declare const wideData: {
47
- year: string;
47
+ year: number;
48
48
  apples: number;
49
49
  bananas: number;
50
50
  cherries: number;
51
51
  dates: number;
52
52
  }[];
53
53
  export declare const longData: {
54
- year: string;
54
+ year: number;
55
55
  basket: number;
56
56
  fruit: string;
57
57
  value: number;
@@ -86,28 +86,28 @@ export function createTimeSeries(options) {
86
86
  return timeSeries;
87
87
  }
88
88
  export const wideData = [
89
- { year: '2019', apples: 3840, bananas: 1920, cherries: 960, dates: 400 },
90
- { year: '2018', apples: 1600, bananas: 1440, cherries: 960, dates: 400 },
91
- { year: '2017', apples: 820, bananas: 1000, cherries: 640, dates: 400 },
92
- { year: '2016', apples: 820, bananas: 560, cherries: 720, dates: 400 },
89
+ { year: 2019, apples: 3840, bananas: 1920, cherries: 960, dates: 400 },
90
+ { year: 2018, apples: 1600, bananas: 1440, cherries: 960, dates: 400 },
91
+ { year: 2017, apples: 820, bananas: 1000, cherries: 640, dates: 400 },
92
+ { year: 2016, apples: 820, bananas: 560, cherries: 720, dates: 400 },
93
93
  ];
94
94
  export const longData = [
95
- { year: '2019', basket: 1, fruit: 'apples', value: 3840 },
96
- { year: '2019', basket: 1, fruit: 'bananas', value: 1920 },
97
- { year: '2019', basket: 2, fruit: 'cherries', value: 960 },
98
- { year: '2019', basket: 2, fruit: 'dates', value: 400 },
99
- { year: '2018', basket: 1, fruit: 'apples', value: 1600 },
100
- { year: '2018', basket: 1, fruit: 'bananas', value: 1440 },
101
- { year: '2018', basket: 2, fruit: 'cherries', value: 960 },
102
- { year: '2018', basket: 2, fruit: 'dates', value: 400 },
103
- { year: '2017', basket: 1, fruit: 'apples', value: 820 },
104
- { year: '2017', basket: 1, fruit: 'bananas', value: 1000 },
105
- { year: '2017', basket: 2, fruit: 'cherries', value: 640 },
106
- { year: '2017', basket: 2, fruit: 'dates', value: 400 },
107
- { year: '2016', basket: 1, fruit: 'apples', value: 820 },
108
- { year: '2016', basket: 1, fruit: 'bananas', value: 560 },
109
- { year: '2016', basket: 2, fruit: 'cherries', value: 720 },
110
- { year: '2016', basket: 2, fruit: 'dates', value: 400 },
95
+ { year: 2019, basket: 1, fruit: 'apples', value: 3840 },
96
+ { year: 2019, basket: 1, fruit: 'bananas', value: 1920 },
97
+ { year: 2019, basket: 2, fruit: 'cherries', value: 960 },
98
+ { year: 2019, basket: 2, fruit: 'dates', value: 400 },
99
+ { year: 2018, basket: 1, fruit: 'apples', value: 1600 },
100
+ { year: 2018, basket: 1, fruit: 'bananas', value: 1440 },
101
+ { year: 2018, basket: 2, fruit: 'cherries', value: 960 },
102
+ { year: 2018, basket: 2, fruit: 'dates', value: 400 },
103
+ { year: 2017, basket: 1, fruit: 'apples', value: 820 },
104
+ { year: 2017, basket: 1, fruit: 'bananas', value: 1000 },
105
+ { year: 2017, basket: 2, fruit: 'cherries', value: 640 },
106
+ { year: 2017, basket: 2, fruit: 'dates', value: 400 },
107
+ { year: 2016, basket: 1, fruit: 'apples', value: 820 },
108
+ { year: 2016, basket: 1, fruit: 'bananas', value: 560 },
109
+ { year: 2016, basket: 2, fruit: 'cherries', value: 720 },
110
+ { year: 2016, basket: 2, fruit: 'dates', value: 400 },
111
111
  ];
112
112
  export function getPhyllotaxis({ radius, count, width, height, }) {
113
113
  // Phyllotaxis: https://www.youtube.com/watch?v=KWoJgHFYWxY
@@ -17,11 +17,11 @@ export declare function polarToCartesian(angle: number, radius: number): {
17
17
  y: number;
18
18
  };
19
19
  /**
20
- * Convert cartesian to polar coordinate system. Angle in radians
20
+ * Convert cartesian to polar coordinate system. Angle in radians with 0 at the 12 o'clock position
21
21
  */
22
22
  export declare function cartesianToPolar(x: number, y: number): {
23
23
  radius: number;
24
- angle: number;
24
+ radians: number;
25
25
  };
26
26
  /** Convert celsius temperature to fahrenheit */
27
27
  export declare function celsiusToFahrenheit(temperature: number): number;
@@ -23,12 +23,18 @@ export function polarToCartesian(angle, radius) {
23
23
  };
24
24
  }
25
25
  /**
26
- * Convert cartesian to polar coordinate system. Angle in radians
26
+ * Convert cartesian to polar coordinate system. Angle in radians with 0 at the 12 o'clock position
27
27
  */
28
28
  export function cartesianToPolar(x, y) {
29
+ let radians = Math.atan2(y, x);
30
+ radians += Math.PI / 2;
31
+ // Ensure the result is between 0 and 2π
32
+ if (radians < 0) {
33
+ radians += 2 * Math.PI;
34
+ }
29
35
  return {
30
36
  radius: Math.sqrt(x ** 2 + y ** 2),
31
- angle: Math.atan(y / x),
37
+ radians,
32
38
  };
33
39
  }
34
40
  /** Convert celsius temperature to fahrenheit */
@@ -5,20 +5,14 @@ type DimensionGetterOptions = {
5
5
  x?: Accessor;
6
6
  /** Override `y` accessor from context */
7
7
  y?: Accessor;
8
- groupBy?: string;
8
+ /** Override `x1` accessor from context */
9
+ x1?: Accessor;
10
+ /** Override `y1` accessor from context */
11
+ y1?: Accessor;
9
12
  inset?: number;
10
- groupPadding?: {
11
- inner?: number;
12
- outer?: number;
13
- };
14
13
  };
15
14
  export declare function createDimensionGetter<TData>(context: ChartContext<TData>, options?: DimensionGetterOptions): import("svelte/store").Readable<(item: any) => {
16
15
  x: any;
17
- y: number;
18
- width: number;
19
- height: number;
20
- } | {
21
- x: number;
22
16
  y: any;
23
17
  width: number;
24
18
  height: number;
@@ -1,27 +1,26 @@
1
1
  import { derived } from 'svelte/store';
2
2
  import { max, min } from 'd3-array';
3
- import { groupScaleBand, isScaleBand } from './scales.js';
3
+ import { isScaleBand } from './scales.js';
4
4
  import { accessor } from './common.js';
5
- // TOOD: Pass in overrides for `x` and `y` accessors
6
5
  export function createDimensionGetter(context, options) {
7
- const { flatData, xGet, yGet, xScale, yScale, x: xAccessor, y: yAccessor } = context;
8
- const groupBy = options?.groupBy;
6
+ const { xScale, yScale, x: xAccessor, y: yAccessor, x1: x1Accessor, y1: y1Accessor, x1Scale, y1Scale, } = context;
9
7
  const inset = options?.inset ?? 0;
10
- return derived([flatData, xGet, yGet, xScale, yScale, xAccessor, yAccessor], ([$flatData, $xGet, $yGet, $xScale, $yScale, $xAccessor, $yAccessor]) => {
8
+ return derived([xScale, x1Scale, yScale, y1Scale, xAccessor, yAccessor, x1Accessor, y1Accessor], ([$xScale, $x1Scale, $yScale, $y1Scale, $xAccessor, $yAccessor, $x1Accessor, $y1Accessor]) => {
11
9
  // Use `xscale.domain()` instead of `$xDomain` to include `nice()` being applied
12
10
  const [minXDomain, maxXDomain] = $xScale.domain();
13
11
  const [minYDomain, maxYDomain] = $yScale.domain();
12
+ const _x = accessor(options?.x ?? $xAccessor);
13
+ const _y = accessor(options?.y ?? $yAccessor);
14
+ const _x1 = accessor(options?.x1 ?? $x1Accessor);
15
+ const _y1 = accessor(options?.y1 ?? $y1Accessor);
14
16
  // @ts-expect-error
15
17
  return function getter(item) {
16
18
  if (isScaleBand($yScale)) {
17
19
  // Horizontal band
18
- const y1Scale = groupBy
19
- ? groupScaleBand($yScale, $flatData, groupBy, options?.groupPadding)
20
- : null;
21
- // @ts-expect-error
22
- const y = firstValue($yGet(item)) + (y1Scale ? y1Scale(item[groupBy]) : 0) + inset / 2;
23
- const height = Math.max(0, $yScale.bandwidth ? (y1Scale ? y1Scale.bandwidth() : $yScale.bandwidth()) - inset : 0);
24
- const _x = accessor(options?.x ?? $xAccessor);
20
+ const y = firstValue($yScale(_y(item)) ?? 0) + ($y1Scale ? $y1Scale(_y1(item)) : 0) + inset / 2;
21
+ const height = Math.max(0, $yScale.bandwidth
22
+ ? ($y1Scale ? ($y1Scale.bandwidth?.() ?? 0) : $yScale.bandwidth()) - inset
23
+ : 0);
25
24
  const xValue = _x(item);
26
25
  let left = 0;
27
26
  let right = 0;
@@ -54,13 +53,10 @@ export function createDimensionGetter(context, options) {
54
53
  }
55
54
  else {
56
55
  // Vertical band or linear
57
- const x1Scale = groupBy && isScaleBand($xScale)
58
- ? groupScaleBand($xScale, $flatData, groupBy, options?.groupPadding)
59
- : null;
60
- // @ts-expect-error
61
- const x = firstValue($xGet(item)) + (x1Scale ? x1Scale(item[groupBy]) : 0) + inset / 2;
62
- const width = Math.max(0, $xScale.bandwidth ? (x1Scale ? x1Scale.bandwidth() : $xScale.bandwidth()) - inset : 0);
63
- const _y = accessor(options?.y ?? $yAccessor);
56
+ const x = firstValue($xScale(_x(item))) + ($x1Scale ? $x1Scale(_x1(item)) : 0) + inset / 2;
57
+ const width = Math.max(0, $xScale.bandwidth
58
+ ? ($x1Scale ? ($x1Scale.bandwidth?.() ?? 0) : $xScale.bandwidth()) - inset
59
+ : 0);
64
60
  const yValue = _y(item);
65
61
  let top = 0;
66
62
  let bottom = 0;
@@ -1,15 +1,19 @@
1
1
  import { tweened, spring } from 'svelte/motion';
2
2
  import { type MotionOptions } from '../stores/motionStore.js';
3
3
  import { type ScaleBand } from 'd3-scale';
4
- export type AnyScale<Domain = any, Range = any, Input = Domain, Output = any> = {
4
+ export interface AnyScale<Domain = any, Range = any, Input = Domain, Output = any> {
5
5
  (value: Input): Output;
6
6
  invert?: (value: Output) => Input;
7
7
  domain(): Domain[];
8
+ domain(domain: Iterable<Domain>): this;
8
9
  range(): Range[];
10
+ range(range: Iterable<Range>): this;
9
11
  bandwidth?: Function;
10
12
  ticks?: Function;
11
13
  tickFormat?: Function;
12
- };
14
+ copy(): Function;
15
+ }
16
+ export type DomainType = (number | string | Date | null | undefined)[] | null;
13
17
  /**
14
18
  * Implemenation for missing `scaleBand().invert()`
15
19
  *
@@ -27,6 +31,8 @@ export declare function isScaleBand(scale: AnyScale<any, any>): scale is ScaleBa
27
31
  * Useful to map mouse event location (x,y) to domain value
28
32
  */
29
33
  export declare function scaleInvert(scale: AnyScale<any, any>, value: number): any;
34
+ /** Create new copy of scale with domain and range */
35
+ export declare function createScale(scale: AnyScale, domain: DomainType, range: any[] | Function, context?: Record<any, any>): AnyScale<any, any, any, any>;
30
36
  /** Create a `scaleBand()` within another scaleBand()'s bandwidth (typically a x1 of an x0 scale, used for grouping) */
31
37
  export declare function groupScaleBand<Domain extends {
32
38
  toString(): string;
@@ -2,7 +2,7 @@ import { derived } from 'svelte/store';
2
2
  import { tweened, spring } from 'svelte/motion';
3
3
  import { motionStore } from '../stores/motionStore.js';
4
4
  import { scaleBand } from 'd3-scale';
5
- import { unique } from 'svelte-ux/utils/array';
5
+ import { unique } from '@layerstack/utils/array';
6
6
  /**
7
7
  * Implemenation for missing `scaleBand().invert()`
8
8
  *
@@ -37,6 +37,20 @@ export function scaleInvert(scale, value) {
37
37
  return scale.invert?.(value);
38
38
  }
39
39
  }
40
+ /** Create new copy of scale with domain and range */
41
+ export function createScale(scale, domain, range, context) {
42
+ const scaleCopy = scale.copy();
43
+ if (domain) {
44
+ scaleCopy.domain(domain);
45
+ }
46
+ if (typeof range === 'function') {
47
+ scaleCopy.range(range(context));
48
+ }
49
+ else {
50
+ scaleCopy.range(range);
51
+ }
52
+ return scaleCopy;
53
+ }
40
54
  /** Create a `scaleBand()` within another scaleBand()'s bandwidth (typically a x1 of an x0 scale, used for grouping) */
41
55
  export function groupScaleBand(scale, flatData, groupBy, padding) {
42
56
  //
@@ -1,14 +1,14 @@
1
1
  import { stackOffsetNone, stackOrderNone } from 'd3-shape';
2
2
  type OrderType = typeof stackOrderNone;
3
3
  type OffsetType = typeof stackOffsetNone;
4
- export declare function createStackData<TData>(data: TData[], options: {
4
+ export declare function groupStackData<TData>(data: TData[], options: {
5
5
  xKey: string;
6
6
  groupBy?: string;
7
7
  stackBy?: string;
8
8
  order?: OrderType;
9
9
  offset?: OffsetType;
10
10
  }): {
11
- keys: (string | number)[];
11
+ keys: Record<string, any>;
12
12
  values: number[];
13
13
  }[];
14
14
  /**
@@ -1,29 +1,36 @@
1
- import { flatGroup, max, rollup, sum } from 'd3-array';
1
+ import { flatGroup, group, max, rollup, sum } from 'd3-array';
2
2
  import { stack, stackOffsetNone, stackOrderNone } from 'd3-shape';
3
3
  import { pivotWider } from './pivot.js';
4
- export function createStackData(data, options) {
4
+ export function groupStackData(data, options) {
5
+ const dataByKey = group(data, (d) => d[options.xKey]);
5
6
  if (options.groupBy) {
6
7
  // Group then Stack (if needed)
7
- const groupedData = flatGroup(data,
8
- // @ts-expect-error
9
- (d) => d[options.xKey],
10
- // @ts-expect-error
11
- (d) => d[options.groupBy ?? '']);
8
+ const groupedData = flatGroup(data, (d) => d[options.xKey], (d) => d[options.groupBy ?? '']);
12
9
  const result = groupedData.flatMap((d, i) => {
13
10
  const groupKeys = d.slice(0, -1); // all but last item
14
- const itemData = d.slice(-1)[0]; // last item
15
- const pivotData = pivotWider(itemData, options.xKey, options.stackBy ?? '', 'value');
11
+ const groupData = d.slice(-1)[0]; // last item
12
+ const pivotData = pivotWider(groupData, options.xKey, options.stackBy ?? '', 'value');
16
13
  const stackKeys = [
17
- ...new Set(itemData.map((d) => d[options.stackBy ?? ''])),
14
+ ...new Set(groupData.map((d) => d[options.stackBy ?? ''])),
18
15
  ];
19
16
  // @ts-expect-error
20
17
  const stackData = stack().keys(stackKeys).order(options.order).offset(options.offset)(pivotData);
21
18
  return stackData.flatMap((series) => {
22
19
  return series.flatMap((s) => {
20
+ const keys = {
21
+ [options.xKey]: groupKeys[0],
22
+ [options.groupBy ?? '']: groupKeys[1],
23
+ };
24
+ if (options.stackBy) {
25
+ keys[options.stackBy] = series.key;
26
+ }
27
+ const value = sum(groupData, (d) => d.value);
23
28
  return {
24
- ...itemData[0], // TODO: More than one should use stacks or aggregate values?
25
- keys: options.stackBy ? [...groupKeys, series.key] : groupKeys,
26
- values: options.stackBy ? [s[0], s[1]] : [0, sum(itemData, (d) => d.value)],
29
+ ...keys,
30
+ keys,
31
+ value,
32
+ values: options.stackBy ? [s[0], s[1]] : [0, value],
33
+ data: dataByKey.get(keys[options.xKey]),
27
34
  };
28
35
  });
29
36
  });
@@ -39,10 +46,16 @@ export function createStackData(data, options) {
39
46
  const stackData = stack().keys(stackKeys).order(options.order).offset(options.offset)(pivotData);
40
47
  const result = stackData.flatMap((series) => {
41
48
  return series.flatMap((s) => {
49
+ const keys = {
50
+ [options.xKey]: s.data[options.xKey],
51
+ [options.stackBy ?? '']: series.key,
52
+ };
42
53
  return {
43
- ...s.data,
44
- keys: [s.data[options.xKey], series.key],
54
+ ...keys,
55
+ keys,
56
+ value: s[1] - s[0],
45
57
  values: [s[0], s[1]],
58
+ data: dataByKey.get(keys[options.xKey]),
46
59
  };
47
60
  });
48
61
  });
@@ -51,11 +64,15 @@ export function createStackData(data, options) {
51
64
  else {
52
65
  // No grouping or stacking. Aggregate based on `xKey`
53
66
  return Array.from(rollup(data, (items) => {
67
+ // @ts-expect-error
68
+ const keys = { [options.xKey]: items[0][options.xKey] };
69
+ const value = sum(items, (d) => d.value);
54
70
  return {
55
- // @ts-expect-error
56
- keys: [items[0][options.xKey]],
57
- // @ts-expect-error
58
- values: [0, sum(items, (d) => d.value)],
71
+ ...keys,
72
+ keys,
73
+ value,
74
+ values: [0, value],
75
+ data: dataByKey.get(keys[options.xKey]),
59
76
  };
60
77
  },
61
78
  // @ts-expect-error
@@ -66,7 +83,7 @@ export function createStackData(data, options) {
66
83
  * Function to offset each layer by the maximum of the previous layer
67
84
  * - see: https://observablehq.com/@mkfreeman/separated-bar-chart
68
85
  */
69
- // TODO: Try to find way to support separated with createStackData() (which has isolated stacked per group)
86
+ // TODO: Try to find way to support separated with groupStackData() (which has isolated stacked per group)
70
87
  // @ts-expect-error
71
88
  export function stackOffsetSeparated(series, order) {
72
89
  const gap = 200; // TODO: Determine way to pass in as option (curry?)