@blotch/dolan 22.2.2 → 22.2.4

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 (259) hide show
  1. package/dist/commands/add.d.ts +6 -2
  2. package/dist/commands/add.js +41 -11
  3. package/dist/commands/add.js.map +1 -1
  4. package/dist/commands/add.test.js +162 -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 +228 -34
  12. package/dist/commands/doctor.js.map +1 -1
  13. package/dist/commands/doctor.test.js +367 -10
  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 +169 -40
  23. package/dist/commands/init.js.map +1 -1
  24. package/dist/commands/init.test.js +392 -27
  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/theme.js +1 -1
  46. package/dist/commands/theme.js.map +1 -1
  47. package/dist/commands/update.d.ts +11 -0
  48. package/dist/commands/update.js +174 -58
  49. package/dist/commands/update.js.map +1 -1
  50. package/dist/commands/update.test.js +587 -33
  51. package/dist/commands/update.test.js.map +1 -1
  52. package/dist/index.js +7 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/lockfile.d.ts +7 -0
  55. package/dist/lockfile.js +36 -0
  56. package/dist/lockfile.js.map +1 -1
  57. package/dist/lockfile.test.d.ts +1 -0
  58. package/dist/lockfile.test.js +25 -0
  59. package/dist/lockfile.test.js.map +1 -0
  60. package/dist/registry.d.ts +14 -0
  61. package/dist/registry.js +78 -24
  62. package/dist/registry.js.map +1 -1
  63. package/dist/registry.test.js +119 -38
  64. package/dist/registry.test.js.map +1 -1
  65. package/dist/test-utils.d.ts +5 -0
  66. package/dist/test-utils.js +6 -1
  67. package/dist/test-utils.js.map +1 -1
  68. package/dist/testing/fire-lynx-event.d.ts +14 -0
  69. package/dist/testing/fire-lynx-event.js +19 -0
  70. package/dist/testing/fire-lynx-event.js.map +1 -0
  71. package/dist/testing/fire-lynx-event.test.d.ts +1 -0
  72. package/dist/testing/fire-lynx-event.test.js +44 -0
  73. package/dist/testing/fire-lynx-event.test.js.map +1 -0
  74. package/dist/testing/lynx-main-thread.d.ts +22 -0
  75. package/dist/testing/lynx-main-thread.js +11 -0
  76. package/dist/testing/lynx-main-thread.js.map +1 -0
  77. package/dist/testing/lynx-main-thread.test.d.ts +1 -0
  78. package/dist/testing/lynx-main-thread.test.js +24 -0
  79. package/dist/testing/lynx-main-thread.test.js.map +1 -0
  80. package/dist/testing/set-input-signal.d.ts +14 -0
  81. package/dist/testing/set-input-signal.js +21 -0
  82. package/dist/testing/set-input-signal.js.map +1 -0
  83. package/dist/testing/set-input-signal.test.d.ts +1 -0
  84. package/dist/testing/set-input-signal.test.js +20 -0
  85. package/dist/testing/set-input-signal.test.js.map +1 -0
  86. package/dist/ui/components/accordion/accordion.test.ts +158 -144
  87. package/dist/ui/components/accordion/accordion.ts +19 -14
  88. package/dist/ui/components/action-sheet/action-sheet.test.ts +283 -151
  89. package/dist/ui/components/action-sheet/action-sheet.ts +77 -43
  90. package/dist/ui/components/alert/alert.test.ts +67 -19
  91. package/dist/ui/components/alert/alert.ts +14 -16
  92. package/dist/ui/components/alert-dialog/alert-dialog.test.ts +208 -94
  93. package/dist/ui/components/alert-dialog/alert-dialog.ts +75 -38
  94. package/dist/ui/components/area-chart/area-chart.test.ts +134 -119
  95. package/dist/ui/components/area-chart/area-chart.ts +100 -315
  96. package/dist/ui/components/area-chart/index.ts +2 -3
  97. package/dist/ui/components/avatar/avatar.test.ts +89 -45
  98. package/dist/ui/components/badge/badge.test.ts +57 -23
  99. package/dist/ui/components/badge/badge.ts +12 -14
  100. package/dist/ui/components/bar-chart/bar-chart.test.ts +172 -45
  101. package/dist/ui/components/bar-chart/bar-chart.ts +140 -294
  102. package/dist/ui/components/bar-chart/index.ts +3 -3
  103. package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +386 -128
  104. package/dist/ui/components/bottom-sheet/bottom-sheet.ts +170 -53
  105. package/dist/ui/components/button/button.test.ts +611 -2
  106. package/dist/ui/components/button/button.ts +434 -49
  107. package/dist/ui/components/button/index.ts +2 -0
  108. package/dist/ui/components/button-group/button-group.test.ts +484 -2
  109. package/dist/ui/components/button-group/button-group.ts +380 -68
  110. package/dist/ui/components/button-group/index.ts +3 -0
  111. package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +183 -58
  112. package/dist/ui/components/candlestick-chart/candlestick-chart.ts +150 -323
  113. package/dist/ui/components/candlestick-chart/index.ts +3 -4
  114. package/dist/ui/components/card/card.test.ts +82 -62
  115. package/dist/ui/components/chart/chart-focus.test.ts +132 -0
  116. package/dist/ui/components/chart/chart-focus.ts +115 -0
  117. package/dist/ui/components/chart/chart-presets.test.ts +335 -0
  118. package/dist/ui/components/chart/chart-presets.ts +278 -0
  119. package/dist/ui/components/chart/chart-scene.test.ts +589 -0
  120. package/dist/ui/components/chart/chart-scene.ts +483 -0
  121. package/dist/ui/components/chart/chart-theme.test.ts +85 -0
  122. package/dist/ui/components/chart/chart-theme.ts +210 -0
  123. package/dist/ui/components/chart/chart-zoom.test.ts +159 -0
  124. package/dist/ui/components/chart/chart-zoom.ts +162 -0
  125. package/dist/ui/components/chart/chart.test.ts +1017 -0
  126. package/dist/ui/components/chart/chart.ts +934 -0
  127. package/dist/ui/components/chart/index.ts +24 -0
  128. package/dist/ui/components/checkbox/checkbox.test.ts +124 -42
  129. package/dist/ui/components/checkbox/checkbox.ts +23 -23
  130. package/dist/ui/components/collapsible/collapsible.test.ts +158 -81
  131. package/dist/ui/components/collapsible/collapsible.ts +19 -14
  132. package/dist/ui/components/context-menu/context-menu.test.ts +224 -0
  133. package/dist/ui/components/context-menu/context-menu.ts +110 -0
  134. package/dist/ui/components/context-menu/index.ts +1 -0
  135. package/dist/ui/components/dialog/dialog.test.ts +213 -108
  136. package/dist/ui/components/dialog/dialog.ts +72 -35
  137. package/dist/ui/components/dock/dock-scroll.test.ts +130 -0
  138. package/dist/ui/components/dock/dock-scroll.ts +133 -0
  139. package/dist/ui/components/dock/dock.test.ts +749 -0
  140. package/dist/ui/components/dock/dock.ts +960 -0
  141. package/dist/ui/components/dock/index.ts +2 -0
  142. package/dist/ui/components/empty-state/empty-state.test.ts +28 -39
  143. package/dist/ui/components/glass/concentric-radius.test.ts +13 -0
  144. package/dist/ui/components/glass/concentric-radius.ts +17 -0
  145. package/dist/ui/components/glass/glass-design.test.ts +78 -0
  146. package/dist/ui/components/glass/glass-design.ts +119 -0
  147. package/dist/ui/components/glass/glass.test.ts +338 -0
  148. package/dist/ui/components/glass/glass.ts +360 -0
  149. package/dist/ui/components/glass/index.ts +18 -0
  150. package/dist/ui/components/icon/icon-theme.test.ts +169 -0
  151. package/dist/ui/components/icon/icon-theme.ts +227 -0
  152. package/dist/ui/components/icon/icon.test.ts +85 -25
  153. package/dist/ui/components/icon/icon.ts +38 -21
  154. package/dist/ui/components/input/input.test.ts +178 -101
  155. package/dist/ui/components/input/input.ts +15 -12
  156. package/dist/ui/components/label/label.test.ts +11 -24
  157. package/dist/ui/components/line-chart/index.ts +2 -3
  158. package/dist/ui/components/line-chart/line-chart.test.ts +149 -56
  159. package/dist/ui/components/line-chart/line-chart.ts +83 -241
  160. package/dist/ui/components/list/list.test.ts +119 -21
  161. package/dist/ui/components/list/list.ts +21 -15
  162. package/dist/ui/components/menu/index.ts +25 -0
  163. package/dist/ui/components/menu/menu-placement.test.ts +153 -0
  164. package/dist/ui/components/menu/menu-placement.ts +159 -0
  165. package/dist/ui/components/menu/menu-popup.test.ts +632 -0
  166. package/dist/ui/components/menu/menu-popup.ts +544 -0
  167. package/dist/ui/components/menu/menu.test.ts +429 -0
  168. package/dist/ui/components/menu/menu.ts +415 -0
  169. package/dist/ui/components/nav-drawer/nav-drawer.test.ts +435 -191
  170. package/dist/ui/components/nav-drawer/nav-drawer.ts +127 -56
  171. package/dist/ui/components/pagination/pagination.test.ts +177 -65
  172. package/dist/ui/components/pagination/pagination.ts +55 -8
  173. package/dist/ui/components/progress/progress.test.ts +102 -46
  174. package/dist/ui/components/progress/progress.ts +52 -54
  175. package/dist/ui/components/radio-group/radio-group.test.ts +128 -83
  176. package/dist/ui/components/radio-group/radio-group.ts +24 -24
  177. package/dist/ui/components/scatter-chart/index.ts +2 -3
  178. package/dist/ui/components/scatter-chart/scatter-chart.test.ts +131 -26
  179. package/dist/ui/components/scatter-chart/scatter-chart.ts +104 -250
  180. package/dist/ui/components/scroll-area/scroll-area.test.ts +95 -24
  181. package/dist/ui/components/scroll-area/scroll-area.ts +8 -8
  182. package/dist/ui/components/select/select.test.ts +138 -78
  183. package/dist/ui/components/select/select.ts +17 -11
  184. package/dist/ui/components/separator/separator.test.ts +18 -17
  185. package/dist/ui/components/sheet/sheet.test.ts +64 -11
  186. package/dist/ui/components/sheet/sheet.ts +9 -1
  187. package/dist/ui/components/skeleton/skeleton.test.ts +24 -7
  188. package/dist/ui/components/skeleton/skeleton.ts +10 -16
  189. package/dist/ui/components/spinner/spinner.test.ts +67 -22
  190. package/dist/ui/components/spinner/spinner.ts +48 -41
  191. package/dist/ui/components/switch/switch.test.ts +116 -46
  192. package/dist/ui/components/switch/switch.ts +8 -13
  193. package/dist/ui/components/tab-bar/index.ts +1 -0
  194. package/dist/ui/components/tab-bar/tab-bar.test.ts +280 -0
  195. package/dist/ui/components/tab-bar/tab-bar.ts +230 -0
  196. package/dist/ui/components/tabs/tabs.test.ts +215 -157
  197. package/dist/ui/components/tabs/tabs.ts +110 -118
  198. package/dist/ui/components/textarea/textarea.test.ts +206 -100
  199. package/dist/ui/components/textarea/textarea.ts +14 -12
  200. package/dist/ui/components/toast/toast.test.ts +436 -315
  201. package/dist/ui/components/toast/toast.ts +62 -55
  202. package/dist/ui/components/toggle/toggle.test.ts +247 -140
  203. package/dist/ui/theme/chart-colors.test.ts +35 -0
  204. package/dist/ui/theme/dark.css +46 -2
  205. package/dist/ui/theme/default.css +63 -7
  206. package/dist/ui/theme/icon-colors.test.ts +35 -0
  207. package/dist/ui/theme/rgb-channels.test.ts +84 -0
  208. package/dist/ui/theme/tailwind-build.test.ts +114 -0
  209. package/dist/ui/theme/tailwind-css.test.ts +83 -0
  210. package/dist/ui/theme/tailwind-plugin.test.ts +42 -2
  211. package/dist/ui/theme/tailwind-plugin.ts +98 -25
  212. package/dist/ui/theme/tailwind.css +113 -0
  213. package/dist/ui/utils/animate.test.ts +13 -1
  214. package/dist/utils/analyze.d.ts +14 -0
  215. package/dist/utils/analyze.js +15 -0
  216. package/dist/utils/analyze.js.map +1 -1
  217. package/dist/utils/analyze.test.js +14 -1
  218. package/dist/utils/analyze.test.js.map +1 -1
  219. package/dist/utils/installed.d.ts +29 -0
  220. package/dist/utils/installed.js +43 -0
  221. package/dist/utils/installed.js.map +1 -0
  222. package/dist/utils/installed.test.d.ts +1 -0
  223. package/dist/utils/installed.test.js +57 -0
  224. package/dist/utils/installed.test.js.map +1 -0
  225. package/dist/utils/interactive.d.ts +9 -0
  226. package/dist/utils/interactive.js +10 -0
  227. package/dist/utils/interactive.js.map +1 -0
  228. package/dist/utils/interactive.test.d.ts +1 -0
  229. package/dist/utils/interactive.test.js +24 -0
  230. package/dist/utils/interactive.test.js.map +1 -0
  231. package/dist/utils/packages.d.ts +36 -0
  232. package/dist/utils/packages.js +70 -0
  233. package/dist/utils/packages.js.map +1 -0
  234. package/dist/utils/packages.test.d.ts +1 -0
  235. package/dist/utils/packages.test.js +89 -0
  236. package/dist/utils/packages.test.js.map +1 -0
  237. package/dist/utils/resolve-paths.d.ts +17 -1
  238. package/dist/utils/resolve-paths.js +21 -3
  239. package/dist/utils/resolve-paths.js.map +1 -1
  240. package/dist/utils/resolve-paths.test.js +38 -2
  241. package/dist/utils/resolve-paths.test.js.map +1 -1
  242. package/dist/utils/tailwind.d.ts +25 -0
  243. package/dist/utils/tailwind.js +51 -0
  244. package/dist/utils/tailwind.js.map +1 -0
  245. package/dist/utils/tailwind.test.d.ts +1 -0
  246. package/dist/utils/tailwind.test.js +71 -0
  247. package/dist/utils/tailwind.test.js.map +1 -0
  248. package/package.json +13 -1
  249. package/dist/ui/components/area-chart/area-chart-render.test.ts +0 -121
  250. package/dist/ui/components/bar-chart/bar-chart-render.test.ts +0 -174
  251. package/dist/ui/components/button/button-render.test.ts +0 -113
  252. package/dist/ui/components/button-group/button-group-render.test.ts +0 -146
  253. package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +0 -174
  254. package/dist/ui/components/cartesian-chart/cartesian-chart-render.test.ts +0 -188
  255. package/dist/ui/components/cartesian-chart/cartesian-chart.test.ts +0 -525
  256. package/dist/ui/components/cartesian-chart/cartesian-chart.ts +0 -1140
  257. package/dist/ui/components/cartesian-chart/index.ts +0 -18
  258. package/dist/ui/components/line-chart/line-chart-render.test.ts +0 -121
  259. package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +0 -157
@@ -1,136 +1,151 @@
1
+ import { Component, signal } from '@angular/core';
2
+ import {
3
+ fireEvent,
4
+ render,
5
+ waitForUpdate,
6
+ } from '@blotch/angular-lynx-testing-library';
7
+ import { createChartRuntime } from '@tanstack/charts/runtime';
8
+ import type { ChartDefinition, SceneNode } from '@tanstack/charts/types';
1
9
  import { describe, expect, it } from 'vitest';
2
- import { computeAreaColumns } from './area-chart';
10
+ import type { XYDatum } from '../chart/chart-presets';
11
+ import { UiAreaChart, areaChartDefinition } from './area-chart';
3
12
 
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
- });
13
+ const data = [
14
+ { x: 0, y: 4 },
15
+ { x: 1, y: -2 },
16
+ { x: 2, y: 6 },
17
+ ];
22
18
 
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);
19
+ /**
20
+ * Every drawn shape in a definition's scene, labels excluded.
21
+ */
22
+ const shapes = (definition: ChartDefinition<any, any, any>) => {
23
+ const scene = createChartRuntime().render(definition, {
24
+ width: 300,
25
+ height: 200,
41
26
  });
27
+ const found: SceneNode[] = [];
28
+ const walk = (nodes: readonly SceneNode[]) => {
29
+ for (const node of nodes) {
30
+ if (node.kind === 'group') {
31
+ if (!node.focus) walk(node.children);
32
+ } else if (node.kind !== 'label') found.push(node);
33
+ }
34
+ };
35
+ walk(scene.nodes);
36
+ return { scene, found };
37
+ };
42
38
 
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);
39
+ describe('areaChartDefinition', () => {
40
+ it('fills to the baseline under the line, with dots', () => {
41
+ const { found } = shapes(areaChartDefinition({ data, fillOpacity: 0.3 }));
42
+ const area = found.find((n) => n.kind === 'area')!;
43
+ expect(area.style).toMatchObject({
44
+ fill: 'var(--primary)',
45
+ fillOpacity: 0.3,
46
+ });
47
+ expect(found.filter((n) => n.kind === 'polyline')).toHaveLength(1);
48
+ expect(found.filter((n) => n.kind === 'dot')).toHaveLength(3);
56
49
  });
57
50
 
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,
51
+ it('keeps the baseline in view', () => {
52
+ const { scene } = shapes(
53
+ areaChartDefinition({
54
+ data: [
55
+ { x: 0, y: 5 },
56
+ { x: 1, y: 8 },
57
+ ],
58
+ baseline: -10,
59
+ }),
68
60
  );
69
- expect(columns).toEqual([]);
61
+ expect(scene.scales['y']!.domain[0]).toBeLessThanOrEqual(-10);
70
62
  });
71
63
 
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([]);
75
- });
76
-
77
- it('returns no columns for a non-positive plot width', () => {
64
+ it('can leave out the dots, curve the line and drop the tooltip', () => {
65
+ const definition = areaChartDefinition({
66
+ data,
67
+ showDots: false,
68
+ smooth: true,
69
+ tooltip: false,
70
+ });
71
+ const { found } = shapes(definition);
72
+ expect(found.some((n) => n.kind === 'dot')).toBe(false);
78
73
  expect(
79
- computeAreaColumns(
80
- [
81
- { x: 0, y: 0 },
82
- { x: 10, y: 10 },
83
- ],
84
- 100,
85
- 0,
86
- 10,
87
- ),
88
- ).toEqual([]);
74
+ (found.find((n) => n.kind === 'polyline') as { path?: string }).path,
75
+ ).toContain('C');
76
+ expect(definition.tooltip).toBe(false);
89
77
  });
78
+ });
90
79
 
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,
103
- );
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);
80
+ @Component({
81
+ imports: [UiAreaChart],
82
+ template: `
83
+ <ui-area-chart
84
+ [data]="data"
85
+ [width]="300"
86
+ [baseline]="baseline()"
87
+ [fillOpacity]="0.3"
88
+ (pointTap)="tapped.push($event)"
89
+ />
90
+ `,
91
+ })
92
+ class AreaChartHost {
93
+ readonly data = data;
94
+ readonly baseline = signal(0);
95
+ /** Every `pointTap`, in order. */
96
+ readonly tapped: XYDatum[] = [];
97
+ }
98
+
99
+ /**
100
+ * The SVG the chart's marks layer draws.
101
+ */
102
+ const marksSvg = (container: Element) =>
103
+ container.querySelectorAll('svg')[1]!.getAttribute('content')!;
104
+
105
+ /**
106
+ * Where the chart drew each dot.
107
+ */
108
+ const dotsDrawn = (container: Element) =>
109
+ [
110
+ ...marksSvg(container).matchAll(/<circle cx="([\d.-]+)" cy="([\d.-]+)"/g),
111
+ ].map(([, x, y]) => ({ x: Number(x), y: Number(y) }));
112
+
113
+ /**
114
+ * Touches a spot of the chart and lifts the finger right there: a tap.
115
+ */
116
+ const tap = async (container: Element, at: { x: number; y: number }) => {
117
+ const root = container.querySelector('[accessibility-label]')!;
118
+ fireEvent.touchstart(root, { touches: [at] });
119
+ fireEvent.touchend(root, { touches: [at] });
120
+ await waitForUpdate();
121
+ };
122
+
123
+ /**
124
+ * The texts of the chart's labels, such as its ticks.
125
+ */
126
+ const labelTexts = (container: Element) =>
127
+ [...container.querySelectorAll('text')].map((text) => text.textContent);
128
+
129
+ describe('UiAreaChart', () => {
130
+ it('fills under its line with its inputs, keeping the baseline in view', async () => {
131
+ const { componentRef, container } = await render(AreaChartHost);
132
+ expect(marksSvg(container)).toContain('fill-opacity="0.3"');
133
+ expect(dotsDrawn(container)).toHaveLength(3);
134
+ expect(labelTexts(container)).not.toContain('-20');
135
+
136
+ (componentRef.instance as AreaChartHost).baseline.set(-20);
137
+ await waitForUpdate();
138
+ expect(labelTexts(container)).toContain('-20');
107
139
  });
108
140
 
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);
141
+ it("emits a tapped point's datum, and nothing for a tap off the points", async () => {
142
+ const { componentRef, container } = await render(AreaChartHost);
143
+ const host = componentRef.instance as AreaChartHost;
144
+ const first = dotsDrawn(container)[0]!;
145
+ await tap(container, { x: first.x + 1, y: first.y + 1 });
146
+ expect(host.tapped).toEqual([data[0]]);
147
+
148
+ await tap(container, { x: -100, y: -100 });
149
+ expect(host.tapped).toEqual([data[0]]);
135
150
  });
136
151
  });