@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.
Files changed (154) hide show
  1. package/dist/commands/add.d.ts +6 -2
  2. package/dist/commands/add.js +32 -10
  3. package/dist/commands/add.js.map +1 -1
  4. package/dist/commands/add.test.js +129 -9
  5. package/dist/commands/add.test.js.map +1 -1
  6. package/dist/commands/diff.d.ts +2 -1
  7. package/dist/commands/diff.js +38 -25
  8. package/dist/commands/diff.js.map +1 -1
  9. package/dist/commands/diff.test.js +72 -11
  10. package/dist/commands/diff.test.js.map +1 -1
  11. package/dist/commands/doctor.js +41 -27
  12. package/dist/commands/doctor.js.map +1 -1
  13. package/dist/commands/doctor.test.js +93 -9
  14. package/dist/commands/doctor.test.js.map +1 -1
  15. package/dist/commands/eject.js +7 -0
  16. package/dist/commands/eject.js.map +1 -1
  17. package/dist/commands/eject.test.js +39 -0
  18. package/dist/commands/eject.test.js.map +1 -1
  19. package/dist/commands/info.js +3 -2
  20. package/dist/commands/info.js.map +1 -1
  21. package/dist/commands/init.d.ts +37 -1
  22. package/dist/commands/init.js +149 -40
  23. package/dist/commands/init.js.map +1 -1
  24. package/dist/commands/init.test.js +285 -26
  25. package/dist/commands/init.test.js.map +1 -1
  26. package/dist/commands/install-packages.d.ts +6 -0
  27. package/dist/commands/install-packages.js +20 -0
  28. package/dist/commands/install-packages.js.map +1 -0
  29. package/dist/commands/install-packages.test.d.ts +1 -0
  30. package/dist/commands/install-packages.test.js +55 -0
  31. package/dist/commands/install-packages.test.js.map +1 -0
  32. package/dist/commands/list.js +21 -14
  33. package/dist/commands/list.js.map +1 -1
  34. package/dist/commands/list.test.js +62 -5
  35. package/dist/commands/list.test.js.map +1 -1
  36. package/dist/commands/outdated.js +11 -10
  37. package/dist/commands/outdated.js.map +1 -1
  38. package/dist/commands/outdated.test.js +20 -5
  39. package/dist/commands/outdated.test.js.map +1 -1
  40. package/dist/commands/remove.d.ts +4 -0
  41. package/dist/commands/remove.js +17 -4
  42. package/dist/commands/remove.js.map +1 -1
  43. package/dist/commands/remove.test.js +53 -2
  44. package/dist/commands/remove.test.js.map +1 -1
  45. package/dist/commands/update.d.ts +6 -0
  46. package/dist/commands/update.js +59 -24
  47. package/dist/commands/update.js.map +1 -1
  48. package/dist/commands/update.test.js +273 -31
  49. package/dist/commands/update.test.js.map +1 -1
  50. package/dist/index.js +7 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/registry.d.ts +8 -0
  53. package/dist/registry.js +32 -24
  54. package/dist/registry.js.map +1 -1
  55. package/dist/registry.test.js +76 -37
  56. package/dist/registry.test.js.map +1 -1
  57. package/dist/testing/set-input-signal.d.ts +13 -0
  58. package/dist/testing/set-input-signal.js +20 -0
  59. package/dist/testing/set-input-signal.js.map +1 -0
  60. package/dist/testing/set-input-signal.test.d.ts +1 -0
  61. package/dist/testing/set-input-signal.test.js +20 -0
  62. package/dist/testing/set-input-signal.test.js.map +1 -0
  63. package/dist/ui/components/action-sheet/action-sheet.test.ts +48 -1
  64. package/dist/ui/components/action-sheet/action-sheet.ts +37 -9
  65. package/dist/ui/components/alert-dialog/alert-dialog.test.ts +49 -2
  66. package/dist/ui/components/alert-dialog/alert-dialog.ts +43 -12
  67. package/dist/ui/components/area-chart/area-chart-render.test.ts +52 -110
  68. package/dist/ui/components/area-chart/area-chart.test.ts +58 -123
  69. package/dist/ui/components/area-chart/area-chart.ts +100 -315
  70. package/dist/ui/components/area-chart/index.ts +2 -3
  71. package/dist/ui/components/bar-chart/bar-chart-render.test.ts +47 -163
  72. package/dist/ui/components/bar-chart/bar-chart.test.ts +83 -37
  73. package/dist/ui/components/bar-chart/bar-chart.ts +140 -294
  74. package/dist/ui/components/bar-chart/index.ts +3 -3
  75. package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +191 -9
  76. package/dist/ui/components/bottom-sheet/bottom-sheet.ts +136 -20
  77. package/dist/ui/components/button/button-render.test.ts +19 -0
  78. package/dist/ui/components/button/button.ts +18 -2
  79. package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +48 -163
  80. package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +106 -62
  81. package/dist/ui/components/candlestick-chart/candlestick-chart.ts +150 -323
  82. package/dist/ui/components/candlestick-chart/index.ts +3 -4
  83. package/dist/ui/components/chart/chart-focus.test.ts +132 -0
  84. package/dist/ui/components/chart/chart-focus.ts +115 -0
  85. package/dist/ui/components/chart/chart-presets.test.ts +139 -0
  86. package/dist/ui/components/chart/chart-presets.ts +271 -0
  87. package/dist/ui/components/chart/chart-render.test.ts +730 -0
  88. package/dist/ui/components/chart/chart-scene.test.ts +589 -0
  89. package/dist/ui/components/chart/chart-scene.ts +483 -0
  90. package/dist/ui/components/chart/chart-theme.test.ts +85 -0
  91. package/dist/ui/components/chart/chart-theme.ts +198 -0
  92. package/dist/ui/components/chart/chart-zoom.test.ts +159 -0
  93. package/dist/ui/components/chart/chart-zoom.ts +162 -0
  94. package/dist/ui/components/chart/chart.ts +921 -0
  95. package/dist/ui/components/chart/index.ts +24 -0
  96. package/dist/ui/components/dialog/dialog.test.ts +49 -2
  97. package/dist/ui/components/dialog/dialog.ts +43 -12
  98. package/dist/ui/components/icon/icon-theme.test.ts +133 -0
  99. package/dist/ui/components/icon/icon-theme.ts +204 -0
  100. package/dist/ui/components/icon/icon.test.ts +51 -2
  101. package/dist/ui/components/icon/icon.ts +38 -21
  102. package/dist/ui/components/line-chart/index.ts +2 -3
  103. package/dist/ui/components/line-chart/line-chart-render.test.ts +69 -107
  104. package/dist/ui/components/line-chart/line-chart.test.ts +63 -45
  105. package/dist/ui/components/line-chart/line-chart.ts +83 -241
  106. package/dist/ui/components/list/list.test.ts +69 -2
  107. package/dist/ui/components/list/list.ts +21 -15
  108. package/dist/ui/components/nav-drawer/nav-drawer.test.ts +80 -1
  109. package/dist/ui/components/nav-drawer/nav-drawer.ts +66 -11
  110. package/dist/ui/components/pagination/pagination.test.ts +62 -0
  111. package/dist/ui/components/pagination/pagination.ts +55 -8
  112. package/dist/ui/components/scatter-chart/index.ts +2 -3
  113. package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +51 -144
  114. package/dist/ui/components/scatter-chart/scatter-chart.test.ts +57 -25
  115. package/dist/ui/components/scatter-chart/scatter-chart.ts +104 -250
  116. package/dist/ui/components/scroll-area/scroll-area.test.ts +37 -2
  117. package/dist/ui/components/scroll-area/scroll-area.ts +8 -8
  118. package/dist/ui/components/spinner/spinner.test.ts +27 -0
  119. package/dist/ui/components/spinner/spinner.ts +33 -23
  120. package/dist/ui/components/toast/toast.test.ts +37 -0
  121. package/dist/ui/components/toast/toast.ts +20 -4
  122. package/dist/ui/theme/chart-colors.test.ts +30 -0
  123. package/dist/ui/theme/dark.css +8 -0
  124. package/dist/ui/theme/default.css +8 -0
  125. package/dist/ui/theme/icon-colors.test.ts +30 -0
  126. package/dist/ui/theme/tailwind-plugin.ts +10 -1
  127. package/dist/utils/installed.d.ts +17 -0
  128. package/dist/utils/installed.js +27 -0
  129. package/dist/utils/installed.js.map +1 -0
  130. package/dist/utils/installed.test.d.ts +1 -0
  131. package/dist/utils/installed.test.js +41 -0
  132. package/dist/utils/installed.test.js.map +1 -0
  133. package/dist/utils/interactive.d.ts +9 -0
  134. package/dist/utils/interactive.js +10 -0
  135. package/dist/utils/interactive.js.map +1 -0
  136. package/dist/utils/interactive.test.d.ts +1 -0
  137. package/dist/utils/interactive.test.js +24 -0
  138. package/dist/utils/interactive.test.js.map +1 -0
  139. package/dist/utils/packages.d.ts +36 -0
  140. package/dist/utils/packages.js +70 -0
  141. package/dist/utils/packages.js.map +1 -0
  142. package/dist/utils/packages.test.d.ts +1 -0
  143. package/dist/utils/packages.test.js +89 -0
  144. package/dist/utils/packages.test.js.map +1 -0
  145. package/dist/utils/resolve-paths.d.ts +17 -1
  146. package/dist/utils/resolve-paths.js +23 -3
  147. package/dist/utils/resolve-paths.js.map +1 -1
  148. package/dist/utils/resolve-paths.test.js +34 -2
  149. package/dist/utils/resolve-paths.test.js.map +1 -1
  150. package/package.json +5 -1
  151. package/dist/ui/components/cartesian-chart/cartesian-chart-render.test.ts +0 -188
  152. package/dist/ui/components/cartesian-chart/cartesian-chart.test.ts +0 -525
  153. package/dist/ui/components/cartesian-chart/cartesian-chart.ts +0 -1140
  154. package/dist/ui/components/cartesian-chart/index.ts +0 -18
@@ -1,121 +1,63 @@
1
- import { render, waitForUpdate } from '@blotch/angular-lynx-testing-library';
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 { UiCartesianChart } from '../cartesian-chart/cartesian-chart';
5
- import { UiAreaChart, UiAreaSeries } from './area-chart';
10
+ import { UiAreaChart } from './area-chart';
11
+
12
+ const data = [
13
+ { x: 0, y: 4 },
14
+ { x: 1, y: -2 },
15
+ { x: 2, y: 6 },
16
+ ];
17
+
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,
25
+ });
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
+ }
33
+ };
34
+ walk(scene.nodes);
35
+ return { scene, found };
36
+ };
6
37
 
7
38
  describe('UiAreaChart', () => {
8
- it('renders with default configuration', async () => {
9
- const { container } = await render(UiAreaChart);
10
- expect(container).toBeTruthy();
11
- });
12
-
13
- it('folds the baseline into the y-axis domain', async () => {
14
- const { componentRef } = await render(UiAreaChart);
15
- const inst = componentRef.instance as UiAreaChart;
16
- setInputSignal(inst.data, [
17
- { x: 0, y: 5 },
18
- { x: 5, y: 10 },
19
- { x: 10, y: 8 },
20
- ]);
21
- setInputSignal(inst.baseline, 0);
22
- await waitForUpdate();
23
- const cast = inst as unknown as {
24
- xAxis: () => { domain: readonly [number, number]; ticks: number[] };
25
- yAxis: () => { domain: readonly [number, number]; ticks: number[] };
26
- };
27
- expect(cast.xAxis().domain[0]).toBeLessThanOrEqual(0);
28
- expect(cast.xAxis().domain[1]).toBeGreaterThanOrEqual(10);
29
- expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(0);
30
- expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(10);
31
- });
39
+ type Internals = {
40
+ definition: () => ChartDefinition<any, any, any>;
41
+ onSelect(point: ChartPoint | null): void;
42
+ };
32
43
 
33
- it('honors explicit xMin / xMax / yMin / yMax overrides', async () => {
44
+ it('builds its definition from its inputs', async () => {
34
45
  const { componentRef } = await render(UiAreaChart);
35
- const inst = componentRef.instance as UiAreaChart;
36
- setInputSignal(inst.data, [
37
- { x: 0, y: 0 },
38
- { x: 10, y: 10 },
39
- ]);
40
- setInputSignal(inst.xMin, -5);
41
- setInputSignal(inst.xMax, 20);
42
- setInputSignal(inst.yMin, -1);
43
- setInputSignal(inst.yMax, 15);
44
- await waitForUpdate();
45
- const cast = inst as unknown as {
46
- xAxis: () => { domain: readonly [number, number] };
47
- yAxis: () => { domain: readonly [number, number] };
48
- };
49
- expect(cast.xAxis().domain[0]).toBeLessThanOrEqual(-5);
50
- expect(cast.xAxis().domain[1]).toBeGreaterThanOrEqual(20);
51
- expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(-1);
52
- expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(15);
46
+ const chart = componentRef.instance as UiAreaChart;
47
+ setInputSignal(chart.data, data);
48
+ setInputSignal(chart.baseline, -20);
49
+ const { scene } = shapes((chart as unknown as Internals).definition());
50
+ expect(scene.scales['y']!.domain[0]).toBeLessThanOrEqual(-20);
53
51
  });
54
52
 
55
- it('exposes the default tick formatter used by the child cartesian chart', async () => {
53
+ it('emits the tapped datum', async () => {
56
54
  const { componentRef } = await render(UiAreaChart);
57
- const inst = componentRef.instance as UiAreaChart;
58
- // JIT doesn't wire the child cartesian chart's [xTickFormat] input, so the
59
- // default formatter never fires through the template. Invoke it directly.
60
- expect(inst.xTickFormat()(3.14159)).toBe('3.14');
61
- expect(inst.yTickFormat()(1.005)).toBe('1');
62
- });
63
- });
64
-
65
- describe('UiAreaSeries', () => {
66
- const renderSeries = async () => {
67
- const parentResult = await render(UiCartesianChart);
68
- const parent = parentResult.componentRef.instance as UiCartesianChart;
69
- setInputSignal(parent.xDomain, [0, 10]);
70
- setInputSignal(parent.yDomain, [0, 10]);
71
- await waitForUpdate();
72
- const seriesResult = await render(UiAreaSeries, {
73
- providers: [{ provide: UiCartesianChart, useValue: parent }],
74
- });
75
- const series = seriesResult.componentRef.instance as UiAreaSeries;
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 };
83
- };
84
-
85
- it('renders fill columns and a translucent fill layer', async () => {
86
- const { series } = await renderSeries();
87
- const cast = series as unknown as {
88
- columns: () => { style: string }[];
89
- fillLayerStyle: () => string;
90
- };
91
- expect(cast.columns().length).toBeGreaterThan(0);
92
- expect(cast.fillLayerStyle()).toContain('opacity');
93
- });
94
-
95
- it('smooth mode densely resamples the fill columns', async () => {
96
- const { series } = await renderSeries();
97
- const cast = series as unknown as { columns: () => { style: string }[] };
98
- const straight = cast.columns().length;
99
- setInputSignal(series.smooth, true);
100
- await waitForUpdate();
101
- // Smoothed curve produces at least as many columns as the straight one.
102
- expect(cast.columns().length).toBeGreaterThanOrEqual(straight);
103
- });
104
-
105
- it('emits pointTap when the nested line series taps', async () => {
106
- const { series } = await renderSeries();
107
- const cb = vi.fn();
108
- series.pointTap.subscribe(cb);
109
- series.pointTap.emit({ x: 1, y: 2 });
110
- expect(cb).toHaveBeenCalledWith({ x: 1, y: 2 });
111
- });
112
-
113
- it('clamps the baseline into the plot when it lies outside the domain', async () => {
114
- const { series } = await renderSeries();
115
- // baseline > yDomain upper bound → clamp to top of plot; columns still render
116
- setInputSignal(series.baseline, 999);
117
- await waitForUpdate();
118
- const cast = series as unknown as { columns: () => { style: string }[] };
119
- expect(Array.isArray(cast.columns())).toBe(true);
55
+ const chart = componentRef.instance as UiAreaChart;
56
+ const tapped = vi.fn();
57
+ chart.pointTap.subscribe(tapped);
58
+ const internals = chart as unknown as Internals;
59
+ internals.onSelect({ datum: data[0] } as ChartPoint);
60
+ internals.onSelect(null);
61
+ expect(tapped.mock.calls).toEqual([[data[0]]]);
120
62
  });
121
63
  });
@@ -1,136 +1,71 @@
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 { computeAreaColumns } from './area-chart';
4
+ import { areaChartDefinition } from './area-chart';
3
5
 
4
- describe('computeAreaColumns', () => {
5
- it('fills a flat line down to the baseline with uniform columns', () => {
6
- // Horizontal line at pixel y=20, baseline at y=100, 30px plot, 10px strips.
7
- const columns = computeAreaColumns(
8
- [
9
- { x: 0, y: 20 },
10
- { x: 30, y: 20 },
11
- ],
12
- 100,
13
- 30,
14
- 10,
15
- );
16
- expect(columns.map((c) => c.x)).toEqual([0, 10, 20]);
17
- for (const column of columns) {
18
- expect(column.top).toBeCloseTo(20);
19
- expect(column.height).toBeCloseTo(80);
20
- }
21
- });
22
-
23
- it('fills on both sides when the line crosses the baseline', () => {
24
- // Line y = x from (0,0) to (100,100); baseline pixel y = 50.
25
- const columns = computeAreaColumns(
26
- [
27
- { x: 0, y: 0 },
28
- { x: 100, y: 100 },
29
- ],
30
- 50,
31
- 100,
32
- 50,
33
- );
34
- expect(columns).toHaveLength(2);
35
- // Strip centered at x=25 → line above the baseline: top at the line, down to it.
36
- expect(columns[0].top).toBeCloseTo(25);
37
- expect(columns[0].height).toBeCloseTo(25);
38
- // Strip centered at x=75 → line below the baseline: top at the baseline.
39
- expect(columns[1].top).toBeCloseTo(50);
40
- expect(columns[1].height).toBeCloseTo(25);
41
- });
42
-
43
- it('skips strips whose center falls outside the data x-range', () => {
44
- // Data spans x=[40,60] but the plot is 100 wide → only strips inside fill.
45
- const columns = computeAreaColumns(
46
- [
47
- { x: 40, y: 10 },
48
- { x: 60, y: 10 },
49
- ],
50
- 100,
51
- 100,
52
- 10,
53
- );
54
- expect(columns.map((c) => c.x)).toEqual([40, 50]);
55
- expect(columns.every((c) => c.x >= 40 && c.x <= 60)).toBe(true);
56
- });
6
+ const data = [
7
+ { x: 0, y: 4 },
8
+ { x: 1, y: -2 },
9
+ { x: 2, y: 6 },
10
+ ];
57
11
 
58
- it('skips columns where the line sits on the baseline', () => {
59
- // Flat line exactly at the baseline → zero height everywhere, nothing to fill.
60
- const columns = computeAreaColumns(
61
- [
62
- { x: 0, y: 50 },
63
- { x: 30, y: 50 },
64
- ],
65
- 50,
66
- 30,
67
- 10,
68
- );
69
- expect(columns).toEqual([]);
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,
70
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
+ };
71
31
 
72
- it('returns no columns for fewer than two points', () => {
73
- expect(computeAreaColumns([], 100, 100, 10)).toEqual([]);
74
- expect(computeAreaColumns([{ x: 0, y: 0 }], 100, 100, 10)).toEqual([]);
32
+ describe('areaChartDefinition', () => {
33
+ it('fills to the baseline under the line, with dots', () => {
34
+ const { found } = shapes(areaChartDefinition({ data, fillOpacity: 0.3 }));
35
+ const area = found.find((n) => n.kind === 'area')!;
36
+ expect(area.style).toMatchObject({
37
+ fill: 'var(--primary)',
38
+ fillOpacity: 0.3,
39
+ });
40
+ expect(found.filter((n) => n.kind === 'polyline')).toHaveLength(1);
41
+ expect(found.filter((n) => n.kind === 'dot')).toHaveLength(3);
75
42
  });
76
43
 
77
- it('returns no columns for a non-positive plot width', () => {
78
- expect(
79
- computeAreaColumns(
80
- [
81
- { x: 0, y: 0 },
82
- { x: 10, y: 10 },
44
+ it('keeps the baseline in view', () => {
45
+ const { scene } = shapes(
46
+ areaChartDefinition({
47
+ data: [
48
+ { x: 0, y: 5 },
49
+ { x: 1, y: 8 },
83
50
  ],
84
- 100,
85
- 0,
86
- 10,
87
- ),
88
- ).toEqual([]);
89
- });
90
-
91
- it('handles duplicate consecutive x values without dividing by zero', () => {
92
- // Two points share x=10 → span === 0 branch. Choose plotWidth/stripWidth
93
- // so that a strip's center lands exactly on x=10: stripWidth=20 puts the
94
- // very first strip's center at x=0 + 20/2 = 10.
95
- const columns = computeAreaColumns(
96
- [
97
- { x: 10, y: 20 },
98
- { x: 10, y: 40 },
99
- ],
100
- 100,
101
- 21,
102
- 20,
51
+ baseline: -10,
52
+ }),
103
53
  );
104
- // Strip at x=0 has center=10 which is inside the (degenerate) segment.
105
- expect(columns.length).toBeGreaterThan(0);
106
- expect(columns[0].top).toBeCloseTo(20);
54
+ expect(scene.scales['y']!.domain[0]).toBeLessThanOrEqual(-10);
107
55
  });
108
56
 
109
- it('falls back to the final y when interpolation hits the last-point edge', () => {
110
- // Single-point case: points.length - 1 === 0 so the for-loop never runs.
111
- // With x === first.x === last.x, `interpolateY` falls through to the
112
- // defensive `return last.y` branch. Since a single point can't produce a
113
- // fill on its own, `computeAreaColumns` returns [] due to the `< 2` guard —
114
- // so drive the branch via a duplicate-x-at-both-ends 3-point series where
115
- // the intermediate segment is degenerate but sits inside the domain.
116
- // Easier: 3 collinear points where the middle segment has span=0 and the
117
- // sample lands there but is *equal* to the endpoints.
118
- // {x:0}, {x:5}, {x:5}, {x:10} - with samples at x=5.
119
- // Actually the simplest reachable case is: [{x:5,y:1},{x:5,y:2}] with a
120
- // strip whose center = 5. Then first.x=5, last.x=5, x >= first.x && x <= last.x
121
- // enters loop, p1=p2 with span=0 → returns p1.y in the loop. Not the fallback.
122
- // The fallback is only reachable if points contains a "gap": e.g. after the
123
- // duplicate, but that violates the sorted-input contract. Accept as
124
- // defensive — see the v8 ignore in the source.
125
- const columns = computeAreaColumns(
126
- [
127
- { x: 0, y: 0 },
128
- { x: 10, y: 10 },
129
- ],
130
- 100,
131
- 10,
132
- 10,
133
- );
134
- expect(columns.length).toBeGreaterThan(0);
57
+ it('can leave out the dots, curve the line and drop the tooltip', () => {
58
+ const definition = areaChartDefinition({
59
+ data,
60
+ showDots: false,
61
+ smooth: true,
62
+ tooltip: false,
63
+ });
64
+ const { found } = shapes(definition);
65
+ expect(found.some((n) => n.kind === 'dot')).toBe(false);
66
+ expect(
67
+ (found.find((n) => n.kind === 'polyline') as { path?: string }).path,
68
+ ).toContain('C');
69
+ expect(definition.tooltip).toBe(false);
135
70
  });
136
71
  });