@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,121 +0,0 @@
1
- import { render, waitForUpdate } from '@blotch/angular-lynx-testing-library';
2
- import { describe, expect, it, vi } from 'vitest';
3
- import { setInputSignal } from '../../../test-utils/set-input-signal';
4
- import { UiCartesianChart } from '../cartesian-chart/cartesian-chart';
5
- import { UiAreaChart, UiAreaSeries } from './area-chart';
6
-
7
- 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
- });
32
-
33
- it('honors explicit xMin / xMax / yMin / yMax overrides', async () => {
34
- 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);
53
- });
54
-
55
- it('exposes the default tick formatter used by the child cartesian chart', async () => {
56
- 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);
120
- });
121
- });
@@ -1,174 +0,0 @@
1
- import { render, waitForUpdate } from '@blotch/angular-lynx-testing-library';
2
- import { describe, expect, it, vi } from 'vitest';
3
- import { setInputSignal } from '../../../test-utils/set-input-signal';
4
- import { UiCartesianChart } from '../cartesian-chart/cartesian-chart';
5
- import { UiBarChart, UiBarSeries } from './bar-chart';
6
-
7
- describe('UiBarChart', () => {
8
- it('renders with default configuration', async () => {
9
- const { container } = await render(UiBarChart);
10
- expect(container).toBeTruthy();
11
- });
12
-
13
- it('folds the baseline into the y-axis domain', async () => {
14
- const { componentRef } = await render(UiBarChart);
15
- const inst = componentRef.instance as UiBarChart;
16
- setInputSignal(inst.data, [
17
- { x: 0, y: 5 },
18
- { x: 1, y: 10 },
19
- { x: 2, y: 8 },
20
- ]);
21
- setInputSignal(inst.baseline, 0);
22
- await waitForUpdate();
23
- const cast = inst as unknown as {
24
- xAxis: () => { domain: readonly [number, number] };
25
- yAxis: () => { domain: readonly [number, number] };
26
- effectivePadding: () => { left?: number; right?: number };
27
- };
28
- expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(0);
29
- expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(10);
30
- // 3 bars → half-bar inset = 0.5 / (3-1) = 0.25
31
- expect(cast.effectivePadding().left).toBeCloseTo(0.25);
32
- expect(cast.effectivePadding().right).toBeCloseTo(0.25);
33
- });
34
-
35
- it('honors explicit xMin / xMax / yMin / yMax overrides', async () => {
36
- const { componentRef } = await render(UiBarChart);
37
- const inst = componentRef.instance as UiBarChart;
38
- setInputSignal(inst.data, [
39
- { x: 0, y: 0 },
40
- { x: 10, y: 10 },
41
- ]);
42
- setInputSignal(inst.xMin, -5);
43
- setInputSignal(inst.xMax, 20);
44
- setInputSignal(inst.yMin, -1);
45
- setInputSignal(inst.yMax, 15);
46
- await waitForUpdate();
47
- const cast = inst as unknown as {
48
- xAxis: () => { domain: readonly [number, number] };
49
- yAxis: () => { domain: readonly [number, number] };
50
- };
51
- expect(cast.xAxis().domain[0]).toBeLessThanOrEqual(-5);
52
- expect(cast.xAxis().domain[1]).toBeGreaterThanOrEqual(20);
53
- expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(-1);
54
- expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(15);
55
- });
56
-
57
- it('single-datum series drops the half-bar padding', async () => {
58
- const { componentRef } = await render(UiBarChart);
59
- const inst = componentRef.instance as UiBarChart;
60
- setInputSignal(inst.data, [{ x: 0, y: 5 }]);
61
- await waitForUpdate();
62
- const cast = inst as unknown as {
63
- effectivePadding: () => { left?: number; right?: number };
64
- };
65
- // n === 1 → half === 0
66
- expect(cast.effectivePadding().left).toBe(0);
67
- expect(cast.effectivePadding().right).toBe(0);
68
- });
69
-
70
- it('exposes the default tick formatter used by the child cartesian chart', async () => {
71
- const { componentRef } = await render(UiBarChart);
72
- const inst = componentRef.instance as UiBarChart;
73
- expect(inst.xTickFormat()(3.14159)).toBe('3.14');
74
- expect(inst.yTickFormat()(1.005)).toBe('1');
75
- });
76
-
77
- it('user padding overrides the auto half-bar inset per side', async () => {
78
- const { componentRef } = await render(UiBarChart);
79
- const inst = componentRef.instance as UiBarChart;
80
- setInputSignal(inst.data, [
81
- { x: 0, y: 5 },
82
- { x: 1, y: 10 },
83
- ]);
84
- setInputSignal(inst.padding, { left: 0.1 });
85
- await waitForUpdate();
86
- const cast = inst as unknown as {
87
- effectivePadding: () => { left?: number; right?: number };
88
- };
89
- // left explicitly set → wins; right still auto = 0.5
90
- expect(cast.effectivePadding().left).toBeCloseTo(0.1);
91
- expect(cast.effectivePadding().right).toBeCloseTo(0.5);
92
- });
93
- });
94
-
95
- describe('UiBarSeries', () => {
96
- const renderSeries = async () => {
97
- const parentResult = await render(UiCartesianChart);
98
- const parent = parentResult.componentRef.instance as UiCartesianChart;
99
- setInputSignal(parent.xDomain, [0, 10]);
100
- setInputSignal(parent.yDomain, [0, 10]);
101
- await waitForUpdate();
102
- const seriesResult = await render(UiBarSeries, {
103
- providers: [{ provide: UiCartesianChart, useValue: parent }],
104
- });
105
- const series = seriesResult.componentRef.instance as UiBarSeries;
106
- setInputSignal(series.data, [
107
- { x: 0, y: 2 },
108
- { x: 5, y: 8 },
109
- { x: 10, y: 5 },
110
- ]);
111
- await waitForUpdate();
112
- return { parent, series };
113
- };
114
-
115
- it('renders a rectangle per datum with the fallback color', async () => {
116
- const { series } = await renderSeries();
117
- const cast = series as unknown as {
118
- bars: () => { style: string; point: { x: number; y: number } }[];
119
- };
120
- const bars = cast.bars();
121
- expect(bars.length).toBe(3);
122
- for (const b of bars) {
123
- expect(b.style).toContain('background-color: var(--primary)');
124
- }
125
- });
126
-
127
- it('cycles through the per-bar palette when colors are provided', async () => {
128
- const { series } = await renderSeries();
129
- setInputSignal(series.colors, ['#f00', '#0f0']);
130
- await waitForUpdate();
131
- const cast = series as unknown as { bars: () => { style: string }[] };
132
- const bars = cast.bars();
133
- expect(bars[0].style).toContain('#f00');
134
- expect(bars[1].style).toContain('#0f0');
135
- // wraps around
136
- expect(bars[2].style).toContain('#f00');
137
- });
138
-
139
- it('emits barTap with the source point when a bar is tapped', async () => {
140
- const { series } = await renderSeries();
141
- const cb = vi.fn();
142
- series.barTap.subscribe(cb);
143
- (
144
- series as unknown as { onBarTap: (p: { x: number; y: number }) => void }
145
- ).onBarTap({ x: 1, y: 2 });
146
- expect(cb).toHaveBeenCalledWith({ x: 1, y: 2 });
147
- });
148
-
149
- it('single-datum series uses the fallback bar width', async () => {
150
- const parentResult = await render(UiCartesianChart);
151
- const parent = parentResult.componentRef.instance as UiCartesianChart;
152
- setInputSignal(parent.xDomain, [0, 10]);
153
- setInputSignal(parent.yDomain, [0, 10]);
154
- await waitForUpdate();
155
- const seriesResult = await render(UiBarSeries, {
156
- providers: [{ provide: UiCartesianChart, useValue: parent }],
157
- });
158
- const series = seriesResult.componentRef.instance as UiBarSeries;
159
- setInputSignal(series.data, [{ x: 5, y: 5 }]);
160
- await waitForUpdate();
161
- const cast = series as unknown as { bars: () => { style: string }[] };
162
- const [bar] = cast.bars();
163
- // fallback = 24px
164
- expect(bar.style).toContain('width: 24.00px');
165
- });
166
-
167
- it('clamps the baseline into the plot when it lies outside the domain', async () => {
168
- const { series } = await renderSeries();
169
- setInputSignal(series.baseline, 999);
170
- await waitForUpdate();
171
- const cast = series as unknown as { bars: () => { style: string }[] };
172
- expect(cast.bars().length).toBe(3);
173
- });
174
- });
@@ -1,113 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { render, waitForUpdate } from '@blotch/angular-lynx-testing-library';
3
- import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
4
- import { describe, expect, it, vi } from 'vitest';
5
- import { setInputSignal } from '../../../test-utils/set-input-signal';
6
- import { UiButton } from './button';
7
-
8
- @Component({
9
- standalone: true,
10
- imports: [UiButton, LYNX_ELEMENTS],
11
- template: `<ui-button (pressed)="onPressed()"><text>Go</text></ui-button>`,
12
- })
13
- class ButtonHost {
14
- count = 0;
15
- onPressed = () => {
16
- this.count++;
17
- };
18
- }
19
-
20
- describe('UiButton (render)', () => {
21
- it('renders and mounts without throwing', async () => {
22
- const { container } = await render(ButtonHost);
23
- expect(container).toBeTruthy();
24
- });
25
-
26
- it('emits `pressed` from onTap() when not disabled/loading', async () => {
27
- const { componentRef } = await render(UiButton);
28
- const inst = componentRef.instance as unknown as {
29
- onTap: () => void;
30
- pressed: { subscribe: (cb: () => void) => void };
31
- };
32
- const emitted = vi.fn();
33
- inst.pressed.subscribe(emitted);
34
- inst.onTap();
35
- expect(emitted).toHaveBeenCalledTimes(1);
36
- });
37
-
38
- it('onTap() is a no-op when disabled', async () => {
39
- const { componentRef } = await render(UiButton);
40
- const inst = componentRef.instance as unknown as UiButton & {
41
- onTap: () => void;
42
- };
43
- setInputSignal(inst.disabled, true);
44
- const emitted = vi.fn();
45
- inst.pressed.subscribe(emitted);
46
- inst.onTap();
47
- expect(emitted).not.toHaveBeenCalled();
48
- });
49
-
50
- it('onTap() is a no-op when loading', async () => {
51
- const { componentRef } = await render(UiButton);
52
- const inst = componentRef.instance as unknown as UiButton & {
53
- onTap: () => void;
54
- };
55
- setInputSignal(inst.loading, true);
56
- const emitted = vi.fn();
57
- inst.pressed.subscribe(emitted);
58
- inst.onTap();
59
- expect(emitted).not.toHaveBeenCalled();
60
- });
61
-
62
- it('shows the spinner while loading', async () => {
63
- const { componentRef, container } = await render(UiButton);
64
- setInputSignal((componentRef.instance as UiButton).loading, true);
65
- await waitForUpdate();
66
- // Spinner renders as a nested view with an svg — searching for that
67
- // suffices without asserting on the internal Lynx tree.
68
- expect(container.querySelector('svg')).toBeTruthy();
69
- });
70
-
71
- it('applies disabled dim opacity when disabled or loading', async () => {
72
- const { componentRef, container } = await render(UiButton);
73
- setInputSignal((componentRef.instance as UiButton).disabled, true);
74
- await waitForUpdate();
75
- const outer = container.querySelector('view');
76
- expect(outer?.getAttribute('class')).toContain('opacity-50');
77
- });
78
-
79
- it('picks the right spinner size for each button size', async () => {
80
- // spinnerSize returns 'xs' for size='sm' and 'sm' otherwise. Cover both.
81
- const { componentRef } = await render(UiButton);
82
- const inst = componentRef.instance as unknown as UiButton & {
83
- spinnerSize: () => 'xs' | 'sm';
84
- };
85
- setInputSignal(inst.size, 'sm');
86
- await waitForUpdate();
87
- expect(inst.spinnerSize()).toBe('xs');
88
-
89
- setInputSignal(inst.size, 'default');
90
- await waitForUpdate();
91
- expect(inst.spinnerSize()).toBe('sm');
92
- });
93
-
94
- it('press handlers run cleanly (guarded by disabled/loading state)', async () => {
95
- // onPressStart/End are no-ops when the button is disabled/loading; the
96
- // active-press path relies on the ref being wired up on-device — assert
97
- // only that the handlers run without throwing here.
98
- const { componentRef } = await render(UiButton);
99
- const inst = componentRef.instance as unknown as {
100
- onPressStart: () => void;
101
- onPressEnd: () => void;
102
- onPressCancel: () => void;
103
- };
104
- expect(() => inst.onPressStart()).not.toThrow();
105
- expect(() => inst.onPressEnd()).not.toThrow();
106
- expect(() => inst.onPressCancel()).not.toThrow();
107
-
108
- // Disabled path (early return in onPressStart / onPressEnd)
109
- setInputSignal((componentRef.instance as UiButton).disabled, true);
110
- expect(() => inst.onPressStart()).not.toThrow();
111
- expect(() => inst.onPressEnd()).not.toThrow();
112
- });
113
- });
@@ -1,146 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { render, waitForUpdate } from '@blotch/angular-lynx-testing-library';
3
- import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
4
- import { describe, expect, it, vi } from 'vitest';
5
- import { setInputSignal } from '../../../test-utils/set-input-signal';
6
- import { UiButtonGroup, UiButtonGroupItem } from './button-group';
7
-
8
- @Component({
9
- standalone: true,
10
- imports: [UiButtonGroup, UiButtonGroupItem, LYNX_ELEMENTS],
11
- template: `
12
- <ui-button-group [orientation]="orientation">
13
- <ui-button-group-item (pressed)="onPressed()"
14
- ><text>A</text></ui-button-group-item
15
- >
16
- <ui-button-group-item [disabled]="disabled" (pressed)="onPressed()"
17
- ><text>B</text></ui-button-group-item
18
- >
19
- </ui-button-group>
20
- `,
21
- })
22
- class ButtonGroupHost {
23
- orientation: 'horizontal' | 'vertical' = 'horizontal';
24
- disabled = false;
25
- onPressed = () => {};
26
- }
27
-
28
- describe('UiButtonGroup (render)', () => {
29
- it('renders horizontally by default', async () => {
30
- const { container } = await render(ButtonGroupHost);
31
- expect(container).toBeTruthy();
32
- const flexRow = container.querySelector('.flex-row');
33
- expect(flexRow).toBeTruthy();
34
- });
35
-
36
- it('switches to vertical layout when orientation is flipped', async () => {
37
- const { componentRef, container } = await render(UiButtonGroup);
38
- setInputSignal(
39
- (componentRef.instance as UiButtonGroup).orientation,
40
- 'vertical',
41
- );
42
- await waitForUpdate();
43
- expect(container.querySelector('.flex-col')).toBeTruthy();
44
- });
45
-
46
- it('applies a user class from the alias input', async () => {
47
- const { componentRef, container } = await render(UiButtonGroup);
48
- setInputSignal(
49
- (componentRef.instance as UiButtonGroup).userClass,
50
- 'w-full',
51
- );
52
- await waitForUpdate();
53
- const outer = container.querySelector('view');
54
- expect(outer?.getAttribute('class')).toContain('w-full');
55
- });
56
- });
57
-
58
- describe('UiButtonGroupItem', () => {
59
- const renderItem = async (
60
- variant: 'default' | 'outline' = 'default',
61
- size: 'default' | 'sm' | 'lg' = 'default',
62
- disabledGroup = false,
63
- ) => {
64
- const parentResult = await render(UiButtonGroup);
65
- const parent = parentResult.componentRef.instance as UiButtonGroup;
66
- setInputSignal(parent.variant, variant);
67
- setInputSignal(parent.size, size);
68
- setInputSignal(parent.disabled, disabledGroup);
69
- await waitForUpdate();
70
-
71
- const itemResult = await render(UiButtonGroupItem, {
72
- providers: [{ provide: UiButtonGroup, useValue: parent }],
73
- });
74
- await waitForUpdate();
75
- return { parent, itemResult };
76
- };
77
-
78
- it('onTap emits `pressed` when neither the group nor the item is disabled', async () => {
79
- const { itemResult } = await renderItem();
80
- const inst = itemResult.componentRef
81
- .instance as unknown as UiButtonGroupItem & {
82
- onTap: () => void;
83
- };
84
- const emitted = vi.fn();
85
- inst.pressed.subscribe(emitted);
86
- inst.onTap();
87
- expect(emitted).toHaveBeenCalledTimes(1);
88
- });
89
-
90
- it('onTap is a no-op when the group is disabled', async () => {
91
- const { itemResult } = await renderItem('default', 'default', true);
92
- const inst = itemResult.componentRef
93
- .instance as unknown as UiButtonGroupItem & {
94
- onTap: () => void;
95
- };
96
- const emitted = vi.fn();
97
- inst.pressed.subscribe(emitted);
98
- inst.onTap();
99
- expect(emitted).not.toHaveBeenCalled();
100
- });
101
-
102
- it('onTap is a no-op when the item itself is disabled', async () => {
103
- const { itemResult } = await renderItem();
104
- const inst = itemResult.componentRef
105
- .instance as unknown as UiButtonGroupItem & {
106
- onTap: () => void;
107
- };
108
- setInputSignal(inst.disabled, true);
109
- await waitForUpdate();
110
- const emitted = vi.fn();
111
- inst.pressed.subscribe(emitted);
112
- inst.onTap();
113
- expect(emitted).not.toHaveBeenCalled();
114
- });
115
-
116
- it('press handlers run cleanly on both enabled and disabled paths', async () => {
117
- const { itemResult } = await renderItem();
118
- const inst = itemResult.componentRef.instance as unknown as {
119
- onPressStart: () => void;
120
- onPressEnd: () => void;
121
- onPressCancel: () => void;
122
- disabled: unknown;
123
- };
124
- expect(() => inst.onPressStart()).not.toThrow();
125
- expect(() => inst.onPressEnd()).not.toThrow();
126
- expect(() => inst.onPressCancel()).not.toThrow();
127
- setInputSignal((inst as unknown as UiButtonGroupItem).disabled, true);
128
- await waitForUpdate();
129
- expect(() => inst.onPressStart()).not.toThrow();
130
- expect(() => inst.onPressEnd()).not.toThrow();
131
- });
132
-
133
- it('renders label with `outline` group variant classes', async () => {
134
- // Covers the `outline` branch of both buttonGroupItemVariants and
135
- // buttonGroupTextVariants.
136
- const { itemResult } = await renderItem('outline', 'lg');
137
- const view = itemResult.container.querySelector('view');
138
- expect(view?.getAttribute('class')).toContain('bg-background');
139
- });
140
-
141
- it('renders with size sm variant classes', async () => {
142
- const { itemResult } = await renderItem('default', 'sm');
143
- const view = itemResult.container.querySelector('view');
144
- expect(view?.getAttribute('class')).toContain('h-9');
145
- });
146
- });