@spatika/react 1.3.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/AGENTS.md +6 -3
  2. package/README.md +1 -1
  3. package/dist/composites/EventCalendar.d.ts +13 -2
  4. package/dist/composites/EventCalendar.d.ts.map +1 -1
  5. package/dist/composites/EventCalendar.js +13 -27
  6. package/dist/composites/GlassCard.d.ts +1 -1
  7. package/dist/composites/RichTextEditor.d.ts +1 -4
  8. package/dist/composites/RichTextEditor.d.ts.map +1 -1
  9. package/dist/composites/RichTextEditor.js +12 -19
  10. package/dist/composites/SurfaceCard.d.ts +1 -1
  11. package/dist/composites/Tag.d.ts +2 -2
  12. package/dist/composites/cartesian-charts.d.ts +12 -2
  13. package/dist/composites/cartesian-charts.d.ts.map +1 -1
  14. package/dist/composites/cartesian-charts.js +27 -13
  15. package/dist/composites/chart-composition.d.ts +19 -1
  16. package/dist/composites/chart-composition.d.ts.map +1 -1
  17. package/dist/composites/chart-composition.js +124 -62
  18. package/dist/composites/chart-interaction.d.ts +81 -0
  19. package/dist/composites/chart-interaction.d.ts.map +1 -0
  20. package/dist/composites/chart-interaction.js +56 -0
  21. package/dist/composites/chart-ui.d.ts +8 -13
  22. package/dist/composites/chart-ui.d.ts.map +1 -1
  23. package/dist/composites/chart-ui.js +9 -6
  24. package/dist/composites/flow-charts.d.ts +6 -1
  25. package/dist/composites/flow-charts.d.ts.map +1 -1
  26. package/dist/composites/flow-charts.js +28 -14
  27. package/dist/composites/radial-charts.d.ts +11 -1
  28. package/dist/composites/radial-charts.d.ts.map +1 -1
  29. package/dist/composites/radial-charts.js +33 -14
  30. package/dist/composites/scheduler-ui.d.ts +14 -1
  31. package/dist/composites/scheduler-ui.d.ts.map +1 -1
  32. package/dist/composites/scheduler-ui.js +23 -2
  33. package/dist/index.d.ts +14 -26
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +8 -14
  36. package/dist/lib/breakpoints.d.ts +17 -0
  37. package/dist/lib/breakpoints.d.ts.map +1 -0
  38. package/dist/lib/breakpoints.js +23 -0
  39. package/dist/lib/chips.d.ts +3 -0
  40. package/dist/lib/chips.d.ts.map +1 -1
  41. package/dist/lib/chips.js +10 -0
  42. package/dist/lib/create-theme.d.ts +162 -0
  43. package/dist/lib/create-theme.d.ts.map +1 -0
  44. package/dist/lib/create-theme.js +138 -0
  45. package/dist/lib/scheduler.d.ts +12 -0
  46. package/dist/lib/scheduler.d.ts.map +1 -1
  47. package/dist/lib/scheduler.js +24 -2
  48. package/dist/lib/themes.d.ts +17 -7
  49. package/dist/lib/themes.d.ts.map +1 -1
  50. package/dist/lib/themes.js +22 -8
  51. package/dist/lib/use-media-query.d.ts +9 -0
  52. package/dist/lib/use-media-query.d.ts.map +1 -1
  53. package/dist/lib/use-media-query.js +28 -1
  54. package/dist/primitives/Alert.d.ts +1 -1
  55. package/dist/primitives/Badge.d.ts +2 -2
  56. package/dist/primitives/Button.d.ts +2 -2
  57. package/dist/primitives/Container.d.ts +2 -2
  58. package/dist/primitives/Fab.d.ts +4 -4
  59. package/dist/primitives/Grid.d.ts +2 -1
  60. package/dist/primitives/Grid.d.ts.map +1 -1
  61. package/dist/primitives/Grid.js +10 -2
  62. package/dist/primitives/IconButton.d.ts +2 -2
  63. package/dist/primitives/NativeSelect.d.ts +10 -1
  64. package/dist/primitives/NativeSelect.d.ts.map +1 -1
  65. package/dist/primitives/NativeSelect.js +2 -2
  66. package/dist/primitives/ToggleButton.d.ts +1 -1
  67. package/dist/theme/SpatikaThemeProvider.d.ts +4 -5
  68. package/dist/theme/SpatikaThemeProvider.d.ts.map +1 -1
  69. package/dist/theme/SpatikaThemeProvider.js +28 -13
  70. package/package.json +4 -2
  71. package/skills/spatika-ui/SKILL.md +28 -5
  72. package/src/composites/EventCalendar.test.tsx +293 -0
  73. package/src/composites/EventCalendar.tsx +38 -27
  74. package/src/composites/RichTextEditor.test.tsx +51 -0
  75. package/src/composites/RichTextEditor.tsx +20 -84
  76. package/src/composites/chart-ui.test.tsx +21 -0
  77. package/src/composites/scheduler-ui.tsx +128 -26
  78. package/src/composites/scheduler.test.tsx +0 -219
  79. package/src/index.test.ts +10 -0
  80. package/src/index.ts +148 -65
  81. package/src/lib/breakpoints.test.ts +29 -0
  82. package/src/lib/breakpoints.ts +28 -0
  83. package/src/lib/chips.ts +16 -0
  84. package/src/lib/create-theme.test.ts +79 -0
  85. package/src/lib/create-theme.ts +249 -0
  86. package/src/lib/scheduler.test.ts +26 -0
  87. package/src/lib/scheduler.ts +36 -2
  88. package/src/lib/themes.test.ts +17 -0
  89. package/src/lib/themes.ts +43 -12
  90. package/src/lib/use-media-query.test.tsx +80 -0
  91. package/src/lib/use-media-query.ts +35 -1
  92. package/src/primitives/Grid.test.tsx +55 -0
  93. package/src/primitives/Grid.tsx +13 -3
  94. package/src/primitives/NativeSelect.test.tsx +28 -0
  95. package/src/primitives/NativeSelect.tsx +14 -4
  96. package/src/primitives/mui-more.test.tsx +17 -0
  97. package/src/theme/SpatikaThemeProvider.test.tsx +38 -0
  98. package/src/theme/SpatikaThemeProvider.tsx +43 -15
  99. package/src/composites/ChartDataGrid.test.tsx +0 -57
  100. package/src/composites/ChartDataGrid.tsx +0 -196
  101. package/src/composites/MapChart.test.tsx +0 -39
  102. package/src/composites/MapChart.tsx +0 -130
  103. package/src/composites/ScatterWebGL.test.tsx +0 -25
  104. package/src/composites/ScatterWebGL.tsx +0 -79
  105. package/src/composites/cartesian-charts.test.tsx +0 -52
  106. package/src/composites/cartesian-charts.tsx +0 -1287
  107. package/src/composites/chart-composition.test.tsx +0 -53
  108. package/src/composites/chart-composition.tsx +0 -898
  109. package/src/composites/chart-ui.tsx +0 -328
  110. package/src/composites/charts-3d.test.tsx +0 -25
  111. package/src/composites/charts-3d.tsx +0 -318
  112. package/src/composites/charts.test.tsx +0 -254
  113. package/src/composites/flow-charts.test.tsx +0 -79
  114. package/src/composites/flow-charts.tsx +0 -607
  115. package/src/composites/radial-charts.test.tsx +0 -74
  116. package/src/composites/radial-charts.tsx +0 -617
  117. package/src/lib/chart-export.test.ts +0 -20
  118. package/src/lib/chart-export.ts +0 -99
  119. package/src/lib/charts-platform.test.ts +0 -93
  120. package/src/lib/charts.test.ts +0 -132
  121. package/src/lib/charts.ts +0 -1021
  122. package/src/lib/geo.test.ts +0 -42
  123. package/src/lib/geo.ts +0 -138
  124. package/src/lib/iso.test.ts +0 -22
  125. package/src/lib/iso.ts +0 -102
  126. package/src/lib/webgl-scatter.test.ts +0 -36
  127. package/src/lib/webgl-scatter.ts +0 -230
@@ -1,254 +0,0 @@
1
- import { render, screen } from "@testing-library/react";
2
- import userEvent from "@testing-library/user-event";
3
- import { describe, expect, it } from "vitest";
4
- import { ChartContainer } from "./chart-composition";
5
- import { BarChart, LineChart, ScatterChart, SparkLineChart, WaterfallChart } from "./cartesian-charts";
6
- import { Gauge, LinearGauge, PieChart, RadarChart } from "./radial-charts";
7
- import { FunnelChart, Heatmap, SankeyChart, Treemap } from "./flow-charts";
8
- import { MapChart } from "./MapChart";
9
- import { BarChart3D, PieChart3D } from "./charts-3d";
10
- import { ChartDataGrid } from "./ChartDataGrid";
11
-
12
- const months = ["Jan", "Feb", "Mar"];
13
-
14
- describe("charts", () => {
15
- it("renders a grouped bar chart and shows a tooltip on hover", async () => {
16
- const user = userEvent.setup();
17
- render(
18
- <BarChart
19
- width={360}
20
- height={220}
21
- xAxis={[{ data: months }]}
22
- series={[
23
- { label: "Views", data: [4, 3, 5] },
24
- { label: "Signups", data: [1, 2, 2] },
25
- ]}
26
- />,
27
- );
28
- expect(screen.getByRole("img", { name: /bar chart/i })).toBeInTheDocument();
29
- const marks = document.querySelectorAll('[data-slot="bar-plot"] .spk-chart-mark');
30
- expect(marks.length).toBeGreaterThan(0);
31
- await user.hover(marks[0]!);
32
- expect(screen.getByRole("tooltip")).toBeInTheDocument();
33
- });
34
-
35
- it("hides a line series from the legend", async () => {
36
- const user = userEvent.setup();
37
- render(
38
- <LineChart
39
- width={360}
40
- height={220}
41
- xAxis={[{ data: months }]}
42
- series={[
43
- { label: "Revenue", data: [2, 4, 3] },
44
- { label: "Cost", data: [1, 1, 2] },
45
- ]}
46
- />,
47
- );
48
- const paths = () => document.querySelectorAll('[data-slot="line-plot"] path');
49
- const before = paths().length;
50
- await user.click(screen.getByRole("button", { name: "Cost" }));
51
- expect(paths().length).toBeLessThan(before);
52
- });
53
-
54
- it("renders pie, gauge, radar, scatter, sparkline, and linear gauge", () => {
55
- const { container } = render(
56
- <div>
57
- <PieChart
58
- width={200}
59
- height={200}
60
- series={[{ data: [{ value: 10, label: "A" }, { value: 20, label: "B" }] }]}
61
- />
62
- <Gauge value={40} width={160} height={120} />
63
- <Gauge
64
- width={160}
65
- height={120}
66
- startAngle={-90}
67
- endAngle={90}
68
- sections={[
69
- { value: 40, label: "v5" },
70
- { value: 35, label: "v6" },
71
- { value: 25, label: "v7" },
72
- ]}
73
- />
74
- <LinearGauge value={25} width={200} />
75
- <RadarChart
76
- width={220}
77
- height={220}
78
- radar={{ metrics: ["A", "B", "C"] }}
79
- series={[{ label: "One", data: [3, 5, 4] }]}
80
- />
81
- <ScatterChart
82
- width={220}
83
- height={180}
84
- series={[{ label: "Pts", data: [{ x: 1, y: 2, id: 1 }] }]}
85
- />
86
- <SparkLineChart data={[1, 4, 2, 6]} width={160} height={48} />
87
- </div>,
88
- );
89
- expect(container.querySelector('[data-slot="pie-chart"]')).toBeTruthy();
90
- expect(container.querySelector('[data-slot="gauge"]')).toBeTruthy();
91
- expect(screen.getByRole("button", { name: "v5" })).toBeInTheDocument();
92
- expect(container.querySelector('[data-slot="linear-gauge"]')).toBeTruthy();
93
- expect(container.querySelector('[data-slot="radar-chart"]')).toBeTruthy();
94
- expect(container.querySelector('[data-slot="scatter-chart"]')).toBeTruthy();
95
- expect(container.querySelector('[data-slot="sparkline"]')).toBeTruthy();
96
- });
97
-
98
- it("renders heatmap, funnel, sankey, treemap, and waterfall", () => {
99
- const { container } = render(
100
- <div>
101
- <Heatmap
102
- width={240}
103
- height={160}
104
- xAxis={[{ data: ["A", "B"] }]}
105
- yAxis={[{ data: ["1"] }]}
106
- series={[{ data: [{ x: 0, y: 0, value: 2 }, { x: 1, y: 0, value: 5 }] }]}
107
- />
108
- <FunnelChart
109
- width={240}
110
- height={180}
111
- series={[{ data: [{ label: "Visit", value: 10 }, { label: "Paid", value: 3 }] }]}
112
- />
113
- <SankeyChart
114
- width={280}
115
- height={180}
116
- series={{
117
- data: [{ id: "a" }, { id: "b" }],
118
- links: [{ source: "a", target: "b", value: 4 }],
119
- }}
120
- />
121
- <Treemap
122
- width={240}
123
- height={160}
124
- series={[{ data: [{ label: "A", value: 8 }, { label: "B", value: 4 }] }]}
125
- />
126
- <WaterfallChart
127
- width={280}
128
- height={180}
129
- xAxis={[{ data: ["Start", "Up", "End"] }]}
130
- series={[{ data: [10, 4, null] }]}
131
- />
132
- </div>,
133
- );
134
- expect(container.querySelector('[data-slot="heatmap"]')).toBeTruthy();
135
- expect(container.querySelector('[data-slot="funnel-chart"]')).toBeTruthy();
136
- expect(container.querySelector('[data-slot="sankey-chart"]')).toBeTruthy();
137
- expect(container.querySelector('[data-slot="treemap"]')).toBeTruthy();
138
- expect(container.querySelector('[data-slot="waterfall-chart"]')).toBeTruthy();
139
- });
140
-
141
- it("composes bar and line plots from a dataset with a toolbar", async () => {
142
- const user = userEvent.setup();
143
- const { container } = render(
144
- <ChartContainer
145
- width={360}
146
- height={220}
147
- zoom
148
- showToolbar
149
- dataset={[
150
- { month: "Jan", views: 4, conv: 1 },
151
- { month: "Feb", views: 6, conv: 2 },
152
- { month: "Mar", views: 5, conv: 2 },
153
- ]}
154
- xAxis={[{ dataKey: "month" }]}
155
- yAxis={[{ id: "left" }, { id: "right", position: "right" }]}
156
- series={[
157
- { type: "bar", dataKey: "views", label: "Views" },
158
- { type: "line", dataKey: "conv", label: "Conv", yAxisId: "right" },
159
- ]}
160
- />,
161
- );
162
- expect(container.querySelector('[data-slot="bar-plot"]')).toBeTruthy();
163
- expect(container.querySelector('[data-slot="line-plot"]')).toBeTruthy();
164
- expect(container.querySelector('[data-slot="chart-y-axis-right"]')).toBeTruthy();
165
- expect(screen.getByRole("toolbar", { name: "Chart tools" })).toBeInTheDocument();
166
- await user.click(screen.getByRole("button", { name: "Zoom in" }));
167
- expect(container.querySelector("svg")).toBeTruthy();
168
- });
169
-
170
- it("renders a map, isometric 3d charts, and a sparkline bar", () => {
171
- const { container } = render(
172
- <div>
173
- <MapChart
174
- width={240}
175
- height={160}
176
- geoData={{
177
- type: "FeatureCollection",
178
- features: [
179
- {
180
- type: "Feature",
181
- id: "a",
182
- properties: { name: "A" },
183
- geometry: {
184
- type: "Polygon",
185
- coordinates: [
186
- [
187
- [0, 0],
188
- [4, 0],
189
- [4, 3],
190
- [0, 3],
191
- [0, 0],
192
- ],
193
- ],
194
- },
195
- },
196
- ],
197
- }}
198
- series={[{ data: [{ id: "a", value: 12, label: "A" }] }]}
199
- />
200
- <BarChart3D
201
- width={240}
202
- height={160}
203
- xAxis={[{ data: ["A", "B"] }]}
204
- series={[{ label: "Views", data: [3, 5] }]}
205
- />
206
- <PieChart3D
207
- width={200}
208
- height={160}
209
- series={[{ data: [{ value: 2, label: "A" }, { value: 3, label: "B" }] }]}
210
- />
211
- <SparkLineChart data={[1, 3, 2, 5]} plotType="bar" width={120} height={36} />
212
- <ScatterChart
213
- width={200}
214
- height={140}
215
- renderer="webgl"
216
- series={[{ label: "Pts", data: [{ x: 1, y: 2, id: 1 }] }]}
217
- />
218
- </div>,
219
- );
220
- expect(container.querySelector('[data-slot="map-chart"]')).toBeTruthy();
221
- expect(container.querySelector('[data-slot="map-chart"] path')).toBeTruthy();
222
- expect(container.querySelector('[data-slot="bar-chart-3d"]')).toBeTruthy();
223
- expect(container.querySelector('[data-slot="pie-chart-3d"]')).toBeTruthy();
224
- expect(container.querySelector('[data-slot="sparkline"] rect')).toBeTruthy();
225
- expect(container.querySelector('[data-slot="scatter-chart"]')).toBeTruthy();
226
- });
227
-
228
- it("highlights a chart bar from a selected grid row", async () => {
229
- const user = userEvent.setup();
230
- const { container } = render(
231
- <ChartDataGrid
232
- height={140}
233
- categoryField="name"
234
- valueField="views"
235
- rows={[
236
- { id: "web", name: "Web", views: 10, trend: [1, 2, 3] },
237
- { id: "ios", name: "iOS", views: 6, trend: [2, 2, 1] },
238
- ]}
239
- columns={[
240
- { field: "name", headerName: "Channel" },
241
- { field: "views", headerName: "Views", type: "number" },
242
- { field: "trend", headerName: "Trend", type: "sparkline" },
243
- ]}
244
- />,
245
- );
246
- expect(container.querySelector('[data-slot="chart-data-grid"]')).toBeTruthy();
247
- const row = container.querySelector(
248
- '[data-slot="chart-data-grid"] tbody [data-slot="table-row"]:nth-child(2)',
249
- );
250
- expect(row).toBeTruthy();
251
- await user.click(row!);
252
- expect(row).toHaveAttribute("data-state", "selected");
253
- });
254
- });
@@ -1,79 +0,0 @@
1
- import { render, screen } from "@testing-library/react";
2
- import { describe, expect, it } from "vitest";
3
- import { FunnelChart, Heatmap } from "./flow-charts";
4
-
5
- describe("FunnelChart", () => {
6
- it("renders a comparison overlay with inside and outside value labels", () => {
7
- render(
8
- <FunnelChart
9
- width={280}
10
- height={200}
11
- valueFormatter={(value) => `${value}%`}
12
- series={[
13
- {
14
- label: "2000",
15
- data: [
16
- { label: "Primary", value: 85 },
17
- { label: "Secondary", value: 50 },
18
- ],
19
- },
20
- {
21
- label: "2020",
22
- data: [
23
- { label: "Primary", value: 90 },
24
- { label: "Secondary", value: 67 },
25
- ],
26
- },
27
- ]}
28
- />,
29
- );
30
- expect(screen.getByRole("img", { name: /funnel chart/i })).toBeInTheDocument();
31
- expect(screen.getByText("85%")).toBeInTheDocument();
32
- expect(screen.getByText("90%")).toBeInTheDocument();
33
- expect(screen.getByText("67%")).toBeInTheDocument();
34
- expect(document.querySelectorAll('[data-slot="funnel-chart"] path').length).toBe(4);
35
- });
36
-
37
- it("keeps stage names on a single funnel when the legend is hidden", () => {
38
- render(
39
- <FunnelChart
40
- width={240}
41
- height={160}
42
- hideLegend
43
- series={[{ data: [{ label: "Visit", value: 10 }, { label: "Paid", value: 3 }] }]}
44
- />,
45
- );
46
- expect(screen.getByText("Visit")).toBeInTheDocument();
47
- expect(screen.getByText("Paid")).toBeInTheDocument();
48
- });
49
- });
50
-
51
- describe("Heatmap", () => {
52
- it("draws a color scale for the value domain", () => {
53
- const { container } = render(
54
- <Heatmap
55
- width={240}
56
- height={160}
57
- xAxis={[{ data: ["A", "B"] }]}
58
- yAxis={[{ data: ["1"] }]}
59
- series={[{ data: [{ x: 0, y: 0, value: 2 }, { x: 1, y: 0, value: 8 }] }]}
60
- />,
61
- );
62
- expect(container.querySelector('[data-slot="heatmap-color-scale"]')).toBeTruthy();
63
- expect(screen.getByText("8")).toBeInTheDocument();
64
- });
65
-
66
- it("hides the color scale when hideLegend is set", () => {
67
- const { container } = render(
68
- <Heatmap
69
- width={240}
70
- height={160}
71
- hideLegend
72
- xAxis={[{ data: ["A"] }]}
73
- yAxis={[{ data: ["1"] }]}
74
- series={[{ data: [{ x: 0, y: 0, value: 4 }] }]}
75
- />,
76
- );
77
- expect(container.querySelector('[data-slot="heatmap-color-scale"]')).toBeNull();
78
- });
79
- });