@blotch/dolan 22.2.2 → 22.2.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.
- package/dist/commands/add.d.ts +6 -2
- package/dist/commands/add.js +32 -10
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/add.test.js +129 -9
- package/dist/commands/add.test.js.map +1 -1
- package/dist/commands/diff.d.ts +2 -1
- package/dist/commands/diff.js +38 -25
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/diff.test.js +72 -11
- package/dist/commands/diff.test.js.map +1 -1
- package/dist/commands/doctor.js +41 -27
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +93 -9
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/eject.js +7 -0
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/eject.test.js +39 -0
- package/dist/commands/eject.test.js.map +1 -1
- package/dist/commands/info.js +3 -2
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.d.ts +37 -1
- package/dist/commands/init.js +149 -40
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +285 -26
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/install-packages.d.ts +6 -0
- package/dist/commands/install-packages.js +20 -0
- package/dist/commands/install-packages.js.map +1 -0
- package/dist/commands/install-packages.test.d.ts +1 -0
- package/dist/commands/install-packages.test.js +55 -0
- package/dist/commands/install-packages.test.js.map +1 -0
- package/dist/commands/list.js +21 -14
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/list.test.js +62 -5
- package/dist/commands/list.test.js.map +1 -1
- package/dist/commands/outdated.js +11 -10
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/outdated.test.js +20 -5
- package/dist/commands/outdated.test.js.map +1 -1
- package/dist/commands/remove.d.ts +4 -0
- package/dist/commands/remove.js +17 -4
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/remove.test.js +53 -2
- package/dist/commands/remove.test.js.map +1 -1
- package/dist/commands/update.d.ts +6 -0
- package/dist/commands/update.js +59 -24
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/update.test.js +273 -31
- package/dist/commands/update.test.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/registry.d.ts +8 -0
- package/dist/registry.js +32 -24
- package/dist/registry.js.map +1 -1
- package/dist/registry.test.js +76 -37
- package/dist/registry.test.js.map +1 -1
- package/dist/testing/set-input-signal.d.ts +13 -0
- package/dist/testing/set-input-signal.js +20 -0
- package/dist/testing/set-input-signal.js.map +1 -0
- package/dist/testing/set-input-signal.test.d.ts +1 -0
- package/dist/testing/set-input-signal.test.js +20 -0
- package/dist/testing/set-input-signal.test.js.map +1 -0
- package/dist/ui/components/action-sheet/action-sheet.test.ts +48 -1
- package/dist/ui/components/action-sheet/action-sheet.ts +37 -9
- package/dist/ui/components/alert-dialog/alert-dialog.test.ts +49 -2
- package/dist/ui/components/alert-dialog/alert-dialog.ts +43 -12
- package/dist/ui/components/area-chart/area-chart-render.test.ts +52 -110
- package/dist/ui/components/area-chart/area-chart.test.ts +58 -123
- package/dist/ui/components/area-chart/area-chart.ts +100 -315
- package/dist/ui/components/area-chart/index.ts +2 -3
- package/dist/ui/components/bar-chart/bar-chart-render.test.ts +47 -163
- package/dist/ui/components/bar-chart/bar-chart.test.ts +83 -37
- package/dist/ui/components/bar-chart/bar-chart.ts +140 -294
- package/dist/ui/components/bar-chart/index.ts +3 -3
- package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +191 -9
- package/dist/ui/components/bottom-sheet/bottom-sheet.ts +136 -20
- package/dist/ui/components/button/button-render.test.ts +19 -0
- package/dist/ui/components/button/button.ts +18 -2
- package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +48 -163
- package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +106 -62
- package/dist/ui/components/candlestick-chart/candlestick-chart.ts +150 -323
- package/dist/ui/components/candlestick-chart/index.ts +3 -4
- package/dist/ui/components/chart/chart-focus.test.ts +132 -0
- package/dist/ui/components/chart/chart-focus.ts +115 -0
- package/dist/ui/components/chart/chart-presets.test.ts +139 -0
- package/dist/ui/components/chart/chart-presets.ts +271 -0
- package/dist/ui/components/chart/chart-render.test.ts +730 -0
- package/dist/ui/components/chart/chart-scene.test.ts +589 -0
- package/dist/ui/components/chart/chart-scene.ts +483 -0
- package/dist/ui/components/chart/chart-theme.test.ts +85 -0
- package/dist/ui/components/chart/chart-theme.ts +198 -0
- package/dist/ui/components/chart/chart-zoom.test.ts +159 -0
- package/dist/ui/components/chart/chart-zoom.ts +162 -0
- package/dist/ui/components/chart/chart.ts +921 -0
- package/dist/ui/components/chart/index.ts +24 -0
- package/dist/ui/components/dialog/dialog.test.ts +49 -2
- package/dist/ui/components/dialog/dialog.ts +43 -12
- package/dist/ui/components/icon/icon-theme.test.ts +133 -0
- package/dist/ui/components/icon/icon-theme.ts +204 -0
- package/dist/ui/components/icon/icon.test.ts +51 -2
- package/dist/ui/components/icon/icon.ts +38 -21
- package/dist/ui/components/line-chart/index.ts +2 -3
- package/dist/ui/components/line-chart/line-chart-render.test.ts +69 -107
- package/dist/ui/components/line-chart/line-chart.test.ts +63 -45
- package/dist/ui/components/line-chart/line-chart.ts +83 -241
- package/dist/ui/components/list/list.test.ts +69 -2
- package/dist/ui/components/list/list.ts +21 -15
- package/dist/ui/components/nav-drawer/nav-drawer.test.ts +80 -1
- package/dist/ui/components/nav-drawer/nav-drawer.ts +66 -11
- package/dist/ui/components/pagination/pagination.test.ts +62 -0
- package/dist/ui/components/pagination/pagination.ts +55 -8
- package/dist/ui/components/scatter-chart/index.ts +2 -3
- package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +51 -144
- package/dist/ui/components/scatter-chart/scatter-chart.test.ts +57 -25
- package/dist/ui/components/scatter-chart/scatter-chart.ts +104 -250
- package/dist/ui/components/scroll-area/scroll-area.test.ts +37 -2
- package/dist/ui/components/scroll-area/scroll-area.ts +8 -8
- package/dist/ui/components/spinner/spinner.test.ts +27 -0
- package/dist/ui/components/spinner/spinner.ts +33 -23
- package/dist/ui/components/toast/toast.test.ts +37 -0
- package/dist/ui/components/toast/toast.ts +20 -4
- package/dist/ui/theme/chart-colors.test.ts +30 -0
- package/dist/ui/theme/dark.css +8 -0
- package/dist/ui/theme/default.css +8 -0
- package/dist/ui/theme/icon-colors.test.ts +30 -0
- package/dist/ui/theme/tailwind-plugin.ts +10 -1
- package/dist/utils/installed.d.ts +17 -0
- package/dist/utils/installed.js +27 -0
- package/dist/utils/installed.js.map +1 -0
- package/dist/utils/installed.test.d.ts +1 -0
- package/dist/utils/installed.test.js +41 -0
- package/dist/utils/installed.test.js.map +1 -0
- package/dist/utils/interactive.d.ts +9 -0
- package/dist/utils/interactive.js +10 -0
- package/dist/utils/interactive.js.map +1 -0
- package/dist/utils/interactive.test.d.ts +1 -0
- package/dist/utils/interactive.test.js +24 -0
- package/dist/utils/interactive.test.js.map +1 -0
- package/dist/utils/packages.d.ts +36 -0
- package/dist/utils/packages.js +70 -0
- package/dist/utils/packages.js.map +1 -0
- package/dist/utils/packages.test.d.ts +1 -0
- package/dist/utils/packages.test.js +89 -0
- package/dist/utils/packages.test.js.map +1 -0
- package/dist/utils/resolve-paths.d.ts +17 -1
- package/dist/utils/resolve-paths.js +23 -3
- package/dist/utils/resolve-paths.js.map +1 -1
- package/dist/utils/resolve-paths.test.js +34 -2
- package/dist/utils/resolve-paths.test.js.map +1 -1
- package/package.json +5 -1
- package/dist/ui/components/cartesian-chart/cartesian-chart-render.test.ts +0 -188
- package/dist/ui/components/cartesian-chart/cartesian-chart.test.ts +0 -525
- package/dist/ui/components/cartesian-chart/cartesian-chart.ts +0 -1140
- package/dist/ui/components/cartesian-chart/index.ts +0 -18
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Component, ViewEncapsulation, input } from '@angular/core';
|
|
2
2
|
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
|
|
3
3
|
|
|
4
|
+
import { cn } from '../../utils/cn';
|
|
5
|
+
import { injectIconColor } from './icon-theme';
|
|
4
6
|
import { type IconName, ICONS } from './icons';
|
|
5
7
|
|
|
6
8
|
const SIZE_MAP = { xs: 16, sm: 20, md: 24, lg: 32 } as const;
|
|
@@ -16,39 +18,54 @@ const SIZE_MAP = { xs: 16, sm: 20, md: 24, lg: 32 } as const;
|
|
|
16
18
|
imports: [LYNX_ELEMENTS],
|
|
17
19
|
encapsulation: ViewEncapsulation.None,
|
|
18
20
|
template: `
|
|
19
|
-
<svg
|
|
21
|
+
<svg
|
|
22
|
+
[attr.content]="svgContent()"
|
|
23
|
+
[attr.style]="sizeStyle()"
|
|
24
|
+
[class]="svgClass()"
|
|
25
|
+
/>
|
|
20
26
|
`,
|
|
21
27
|
})
|
|
22
28
|
export class UiIcon {
|
|
23
29
|
readonly name = input.required<IconName>();
|
|
24
30
|
readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');
|
|
31
|
+
/**
|
|
32
|
+
* A literal color or a theme token (`var(--primary)`). Without one, the icon
|
|
33
|
+
* takes the color its container sets (see `UI_ICON_COLOR`), then the theme's
|
|
34
|
+
* foreground.
|
|
35
|
+
*/
|
|
25
36
|
readonly color = input<string | undefined>(undefined);
|
|
37
|
+
readonly userClass = input<string>('', { alias: 'class' });
|
|
38
|
+
|
|
39
|
+
readonly #resolveColor = injectIconColor();
|
|
26
40
|
|
|
27
41
|
protected svgContent(): string {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return svg;
|
|
42
|
+
// Lynx SVG elements don't propagate the CSS `color` property into SVG
|
|
43
|
+
// stroke attributes, so we substitute the literal `currentColor` in the
|
|
44
|
+
// markup string rather than relying on `currentColor` CSS propagation.
|
|
45
|
+
// The color is resolved first: the SVG parser can't read `var(--x)` either
|
|
46
|
+
// (see icon-theme.ts).
|
|
47
|
+
//
|
|
48
|
+
// Uses split().join() instead of String.prototype.replaceAll(). replaceAll
|
|
49
|
+
// is ES2021, but Lynx's main thread runs on PrimJS at an ES2019 target;
|
|
50
|
+
// because it's a runtime method (not syntax) the build's down-leveling does
|
|
51
|
+
// not polyfill it, so it simply doesn't exist there. Calling it throws
|
|
52
|
+
// "main-thread.js exception: not a function" from inside Angular change
|
|
53
|
+
// detection, which aborts the whole tick before Lynx flushes the element
|
|
54
|
+
// tree — so NO icon paints (not just a colored one), and the error count
|
|
55
|
+
// climbs on every render/interaction as each tick re-runs and re-throws.
|
|
56
|
+
// split/join is ES2019-safe and is preferred over `replace(/.../g)` here
|
|
57
|
+
// because the search term is a plain literal and needs no regex escaping.
|
|
58
|
+
return ICONS[this.name()]
|
|
59
|
+
.split('currentColor')
|
|
60
|
+
.join(this.#resolveColor(this.color()));
|
|
48
61
|
}
|
|
49
62
|
|
|
50
63
|
protected sizeStyle(): string {
|
|
51
64
|
const px = SIZE_MAP[this.size()];
|
|
52
65
|
return `width: ${px}px; height: ${px}px;`;
|
|
53
66
|
}
|
|
67
|
+
|
|
68
|
+
protected svgClass(): string {
|
|
69
|
+
return cn(this.userClass());
|
|
70
|
+
}
|
|
54
71
|
}
|
|
@@ -1,121 +1,83 @@
|
|
|
1
|
-
import { render
|
|
1
|
+
import { render } from '@blotch/angular-lynx-testing-library';
|
|
2
|
+
import { createChartRuntime } from '@tanstack/charts/runtime';
|
|
3
|
+
import type {
|
|
4
|
+
ChartDefinition,
|
|
5
|
+
ChartPoint,
|
|
6
|
+
SceneNode,
|
|
7
|
+
} from '@tanstack/charts/types';
|
|
2
8
|
import { describe, expect, it, vi } from 'vitest';
|
|
3
9
|
import { setInputSignal } from '../../../test-utils/set-input-signal';
|
|
4
|
-
import {
|
|
5
|
-
import { UiLineChart, UiLineSeries } from './line-chart';
|
|
10
|
+
import { UiLineChart } from './line-chart';
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
it('computes axis domains from data', async () => {
|
|
14
|
-
const { componentRef } = await render(UiLineChart);
|
|
15
|
-
const inst = componentRef.instance as UiLineChart;
|
|
16
|
-
setInputSignal(inst.data, [
|
|
17
|
-
{ x: 0, y: 0 },
|
|
18
|
-
{ x: 5, y: 10 },
|
|
19
|
-
{ x: 10, y: 5 },
|
|
20
|
-
]);
|
|
21
|
-
await waitForUpdate();
|
|
22
|
-
const cast = inst as unknown as {
|
|
23
|
-
xAxis: () => { domain: readonly [number, number]; ticks: number[] };
|
|
24
|
-
yAxis: () => { domain: readonly [number, number]; ticks: number[] };
|
|
25
|
-
};
|
|
26
|
-
expect(cast.xAxis().domain[0]).toBeLessThanOrEqual(0);
|
|
27
|
-
expect(cast.xAxis().domain[1]).toBeGreaterThanOrEqual(10);
|
|
28
|
-
expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(0);
|
|
29
|
-
expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(10);
|
|
30
|
-
});
|
|
12
|
+
const data = [
|
|
13
|
+
{ x: 0, y: 10 },
|
|
14
|
+
{ x: 5, y: 30 },
|
|
15
|
+
{ x: 10, y: 20 },
|
|
16
|
+
];
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
setInputSignal(inst.xMin, -5);
|
|
40
|
-
setInputSignal(inst.xMax, 20);
|
|
41
|
-
setInputSignal(inst.yMin, -1);
|
|
42
|
-
setInputSignal(inst.yMax, 15);
|
|
43
|
-
await waitForUpdate();
|
|
44
|
-
const cast = inst as unknown as {
|
|
45
|
-
xAxis: () => { domain: readonly [number, number] };
|
|
46
|
-
yAxis: () => { domain: readonly [number, number] };
|
|
47
|
-
};
|
|
48
|
-
expect(cast.xAxis().domain[0]).toBeLessThanOrEqual(-5);
|
|
49
|
-
expect(cast.xAxis().domain[1]).toBeGreaterThanOrEqual(20);
|
|
50
|
-
expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(-1);
|
|
51
|
-
expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(15);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('exposes the default tick formatter used by the child cartesian chart', async () => {
|
|
55
|
-
const { componentRef } = await render(UiLineChart);
|
|
56
|
-
const inst = componentRef.instance as UiLineChart;
|
|
57
|
-
// JIT doesn't wire the child cartesian chart's [xTickFormat] input, so the
|
|
58
|
-
// default formatter is never invoked through the template. Invoke it
|
|
59
|
-
// directly to cover its two-decimal rounding branch.
|
|
60
|
-
expect(inst.xTickFormat()(3.14159)).toBe('3.14');
|
|
61
|
-
expect(inst.yTickFormat()(1.005)).toBe('1');
|
|
18
|
+
/**
|
|
19
|
+
* Every drawn shape in a definition's scene, labels excluded.
|
|
20
|
+
*/
|
|
21
|
+
const shapes = (definition: ChartDefinition<any, any, any>) => {
|
|
22
|
+
const scene = createChartRuntime().render(definition, {
|
|
23
|
+
width: 300,
|
|
24
|
+
height: 200,
|
|
62
25
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
setInputSignal(parent.yDomain, [0, 10]);
|
|
71
|
-
await waitForUpdate();
|
|
72
|
-
const seriesResult = await render(UiLineSeries, {
|
|
73
|
-
providers: [{ provide: UiCartesianChart, useValue: parent }],
|
|
74
|
-
});
|
|
75
|
-
const series = seriesResult.componentRef.instance as UiLineSeries;
|
|
76
|
-
setInputSignal(series.data, [
|
|
77
|
-
{ x: 0, y: 0 },
|
|
78
|
-
{ x: 5, y: 5 },
|
|
79
|
-
{ x: 10, y: 10 },
|
|
80
|
-
]);
|
|
81
|
-
await waitForUpdate();
|
|
82
|
-
return { parent, series, seriesResult };
|
|
26
|
+
const found: SceneNode[] = [];
|
|
27
|
+
const walk = (nodes: readonly SceneNode[]) => {
|
|
28
|
+
for (const node of nodes) {
|
|
29
|
+
if (node.kind === 'group') {
|
|
30
|
+
if (!node.focus) walk(node.children);
|
|
31
|
+
} else if (node.kind !== 'label') found.push(node);
|
|
32
|
+
}
|
|
83
33
|
};
|
|
34
|
+
walk(scene.nodes);
|
|
35
|
+
return { scene, found };
|
|
36
|
+
};
|
|
84
37
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
expect(cast.segments().length).toBeGreaterThan(0);
|
|
92
|
-
expect(cast.dots().length).toBe(3);
|
|
93
|
-
});
|
|
38
|
+
describe('UiLineChart', () => {
|
|
39
|
+
type Internals = {
|
|
40
|
+
definition: () => ChartDefinition<any, any, any>;
|
|
41
|
+
onSelect(point: ChartPoint | null): void;
|
|
42
|
+
chart: unknown;
|
|
43
|
+
};
|
|
94
44
|
|
|
95
|
-
it('
|
|
96
|
-
const {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
45
|
+
it('builds its definition from its inputs', async () => {
|
|
46
|
+
const { componentRef } = await render(UiLineChart);
|
|
47
|
+
const chart = componentRef.instance as UiLineChart;
|
|
48
|
+
setInputSignal(chart.data, data);
|
|
49
|
+
setInputSignal(chart.showDots, false);
|
|
50
|
+
setInputSignal(chart.yAxisLabel, 'Revenue');
|
|
51
|
+
const { found, scene } = shapes(
|
|
52
|
+
(chart as unknown as Internals).definition(),
|
|
53
|
+
);
|
|
54
|
+
expect(found.some((n) => n.kind === 'dot')).toBe(false);
|
|
55
|
+
expect(scene.nodes).toBeDefined();
|
|
101
56
|
});
|
|
102
57
|
|
|
103
|
-
it('emits
|
|
104
|
-
const {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
expect(
|
|
58
|
+
it('emits the tapped datum', async () => {
|
|
59
|
+
const { componentRef } = await render(UiLineChart);
|
|
60
|
+
const chart = componentRef.instance as UiLineChart;
|
|
61
|
+
const tapped = vi.fn();
|
|
62
|
+
chart.pointTap.subscribe(tapped);
|
|
63
|
+
const internals = chart as unknown as Internals;
|
|
64
|
+
internals.onSelect({ datum: data[1] } as ChartPoint);
|
|
65
|
+
internals.onSelect(null);
|
|
66
|
+
expect(tapped.mock.calls).toEqual([[data[1]]]);
|
|
112
67
|
});
|
|
113
68
|
|
|
114
|
-
it('
|
|
115
|
-
const {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
69
|
+
it('forwards the zoom API to its chart', async () => {
|
|
70
|
+
const { componentRef } = await render(UiLineChart);
|
|
71
|
+
const chart = componentRef.instance as UiLineChart;
|
|
72
|
+
const inner = { zoomIn: vi.fn(), zoomOut: vi.fn(), resetZoom: vi.fn() };
|
|
73
|
+
// Signal queries aren't wired under plain Vitest (JIT), so stand in for
|
|
74
|
+
// the inner <ui-chart>.
|
|
75
|
+
(chart as unknown as Internals).chart = () => inner;
|
|
76
|
+
chart.zoomIn();
|
|
77
|
+
chart.zoomOut();
|
|
78
|
+
chart.resetZoom();
|
|
79
|
+
expect(inner.zoomIn).toHaveBeenCalled();
|
|
80
|
+
expect(inner.zoomOut).toHaveBeenCalled();
|
|
81
|
+
expect(inner.resetZoom).toHaveBeenCalled();
|
|
120
82
|
});
|
|
121
83
|
});
|
|
@@ -1,59 +1,77 @@
|
|
|
1
|
+
import { createChartRuntime } from '@tanstack/charts/runtime';
|
|
2
|
+
import type { ChartDefinition, SceneNode } from '@tanstack/charts/types';
|
|
1
3
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
4
|
+
import { lineChartDefinition } from './line-chart';
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
const data = [
|
|
7
|
+
{ x: 0, y: 10 },
|
|
8
|
+
{ x: 5, y: 30 },
|
|
9
|
+
{ x: 10, y: 20 },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Every drawn shape in a definition's scene, labels excluded.
|
|
14
|
+
*/
|
|
15
|
+
const shapes = (definition: ChartDefinition<any, any, any>) => {
|
|
16
|
+
const scene = createChartRuntime().render(definition, {
|
|
17
|
+
width: 300,
|
|
18
|
+
height: 200,
|
|
15
19
|
});
|
|
20
|
+
const found: SceneNode[] = [];
|
|
21
|
+
const walk = (nodes: readonly SceneNode[]) => {
|
|
22
|
+
for (const node of nodes) {
|
|
23
|
+
if (node.kind === 'group') {
|
|
24
|
+
if (!node.focus) walk(node.children);
|
|
25
|
+
} else if (node.kind !== 'label') found.push(node);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
walk(scene.nodes);
|
|
29
|
+
return { scene, found };
|
|
30
|
+
};
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
expect(
|
|
32
|
+
describe('lineChartDefinition', () => {
|
|
33
|
+
it('draws the line and a dot per point', () => {
|
|
34
|
+
const { found } = shapes(lineChartDefinition({ data }));
|
|
35
|
+
expect(found.filter((n) => n.kind === 'polyline')).toHaveLength(1);
|
|
36
|
+
expect(found.filter((n) => n.kind === 'dot')).toHaveLength(3);
|
|
37
|
+
const line = found.find((n) => n.kind === 'polyline')!;
|
|
38
|
+
expect(line.style).toMatchObject({
|
|
39
|
+
stroke: 'var(--primary)',
|
|
40
|
+
strokeWidth: 2,
|
|
41
|
+
});
|
|
24
42
|
});
|
|
25
43
|
|
|
26
|
-
it('
|
|
27
|
-
const
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
expect(segments[0].length).toBeCloseTo(Math.sqrt(200));
|
|
32
|
-
expect(segments[0].angle).toBeCloseTo(45);
|
|
44
|
+
it('can leave the dots out', () => {
|
|
45
|
+
for (const options of [{ showDots: false }, { dotRadius: 0 }]) {
|
|
46
|
+
const { found } = shapes(lineChartDefinition({ data, ...options }));
|
|
47
|
+
expect(found.some((n) => n.kind === 'dot')).toBe(false);
|
|
48
|
+
}
|
|
33
49
|
});
|
|
34
50
|
|
|
35
|
-
it('
|
|
36
|
-
const
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
expect(segments).toHaveLength(2);
|
|
51
|
+
it('draws a curve through the points when smooth', () => {
|
|
52
|
+
const { found } = shapes(
|
|
53
|
+
lineChartDefinition({ data, smooth: true, color: 'red' }),
|
|
54
|
+
);
|
|
55
|
+
const line = found.find((n) => n.kind === 'polyline') as { path?: string };
|
|
56
|
+
expect(line.path).toContain('C');
|
|
42
57
|
});
|
|
43
58
|
|
|
44
|
-
it('
|
|
45
|
-
const
|
|
46
|
-
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
it('fits the axes to the data and honors the shared options', () => {
|
|
60
|
+
const { scene } = shapes(
|
|
61
|
+
lineChartDefinition({
|
|
62
|
+
data,
|
|
63
|
+
yMin: 0,
|
|
64
|
+
yMax: 40,
|
|
65
|
+
showGrid: false,
|
|
66
|
+
tooltip: false,
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
expect(scene.scales['y']!.domain).toEqual([0, 40]);
|
|
70
|
+
expect(scene.scales['x']!.domain).toEqual([0, 10]);
|
|
53
71
|
});
|
|
54
72
|
|
|
55
|
-
it('
|
|
56
|
-
expect(
|
|
57
|
-
expect(
|
|
73
|
+
it('includes the tooltip unless turned off', () => {
|
|
74
|
+
expect(lineChartDefinition({ data }).tooltip).toBeTruthy();
|
|
75
|
+
expect(lineChartDefinition({ data, tooltip: false }).tooltip).toBe(false);
|
|
58
76
|
});
|
|
59
77
|
});
|