@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,228 +1,9 @@
1
1
  import { render, screen } from "@testing-library/react";
2
2
  import userEvent from "@testing-library/user-event";
3
3
  import { describe, expect, it, vi } from "vitest";
4
- import { EventCalendar } from "./EventCalendar";
5
4
  import { EventTimeline } from "./EventTimeline";
6
5
  import type { SchedulerEvent, SchedulerResource } from "../lib/scheduler";
7
6
 
8
- const resources: SchedulerResource[] = [
9
- { id: "work", title: "Work", color: "violet" },
10
- { id: "health", title: "Health", color: "teal" },
11
- ];
12
-
13
- const events: SchedulerEvent[] = [
14
- {
15
- id: "run",
16
- title: "Morning Run",
17
- start: "2026-08-03T07:00:00",
18
- end: "2026-08-03T07:45:00",
19
- resourceId: "health",
20
- },
21
- {
22
- id: "bday",
23
- title: "Alice's Birthday",
24
- start: "2026-08-06",
25
- end: "2026-08-08",
26
- allDay: true,
27
- resourceId: "work",
28
- color: "rose",
29
- },
30
- {
31
- id: "review",
32
- title: "Design Review",
33
- start: "2026-08-09T14:00:00",
34
- end: "2026-08-09T16:00:00",
35
- resourceId: "work",
36
- },
37
- ];
38
-
39
- describe("EventCalendar", () => {
40
- it("renders the month heading, weekday labels, and events", () => {
41
- render(
42
- <EventCalendar
43
- defaultDate={new Date(2026, 7, 15)}
44
- events={events}
45
- resources={resources}
46
- locale="en-US"
47
- />,
48
- );
49
- expect(screen.getByRole("heading", { name: /August 2026/i })).toBeInTheDocument();
50
- expect(screen.getByText(/Sun/)).toBeInTheDocument();
51
- expect(screen.getByText("Morning Run")).toBeInTheDocument();
52
- expect(screen.getByText("Alice's Birthday")).toBeInTheDocument();
53
- expect(screen.getByText("Work")).toBeInTheDocument();
54
- });
55
-
56
- it("jumps to today from the toolbar", async () => {
57
- const user = userEvent.setup();
58
- const onDateChange = vi.fn();
59
- render(
60
- <EventCalendar
61
- defaultDate={new Date(2025, 0, 1)}
62
- onDateChange={onDateChange}
63
- events={events}
64
- />,
65
- );
66
- await user.click(screen.getByRole("button", { name: "Today" }));
67
- expect(onDateChange).toHaveBeenCalled();
68
- const next = onDateChange.mock.calls[0][0] as Date;
69
- const now = new Date();
70
- expect(next.getFullYear()).toBe(now.getFullYear());
71
- expect(next.getMonth()).toBe(now.getMonth());
72
- });
73
-
74
- it("fires onEventClick for a timed event", async () => {
75
- const user = userEvent.setup();
76
- const onEventClick = vi.fn();
77
- render(
78
- <EventCalendar
79
- defaultDate={new Date(2026, 7, 15)}
80
- events={events}
81
- resources={resources}
82
- locale="en-US"
83
- onEventClick={onEventClick}
84
- />,
85
- );
86
- await user.click(screen.getByText("Morning Run"));
87
- expect(onEventClick).toHaveBeenCalledWith(expect.objectContaining({ id: "run" }));
88
- });
89
-
90
- it("switches to week view from the menu", async () => {
91
- const user = userEvent.setup();
92
- render(
93
- <EventCalendar defaultDate={new Date(2026, 7, 15)} events={events} locale="en-US" />,
94
- );
95
- await user.click(screen.getByRole("button", { name: /month/i }));
96
- await user.click(screen.getByRole("menuitem", { name: "Week" }));
97
- expect(screen.getByRole("heading", { name: /2026/ })).toBeInTheDocument();
98
- });
99
-
100
- it("lists events in agenda view", () => {
101
- render(
102
- <EventCalendar
103
- defaultView="agenda"
104
- defaultDate={new Date(2026, 7, 3)}
105
- events={events}
106
- locale="en-US"
107
- />,
108
- );
109
- expect(screen.getByRole("heading", { name: /Aug 3/ })).toBeInTheDocument();
110
- expect(screen.getAllByText("No events").length).toBeGreaterThan(0);
111
- expect(screen.getByText("Morning Run")).toBeInTheDocument();
112
- expect(screen.getAllByText("Alice's Birthday").length).toBeGreaterThan(0);
113
- });
114
-
115
- it("opens the editor and saves title changes", async () => {
116
- const user = userEvent.setup();
117
- const onEventChange = vi.fn();
118
- render(
119
- <EventCalendar
120
- defaultDate={new Date(2026, 7, 15)}
121
- events={events}
122
- resources={resources}
123
- locale="en-US"
124
- onEventChange={onEventChange}
125
- />,
126
- );
127
- await user.click(screen.getByText("Morning Run"));
128
- const title = screen.getByRole("textbox", { name: /title/i });
129
- await user.clear(title);
130
- await user.type(title, "Jog");
131
- await user.click(screen.getByRole("button", { name: "Save" }));
132
- expect(onEventChange).toHaveBeenCalledWith(
133
- expect.objectContaining({ id: "run" }),
134
- expect.objectContaining({ title: "Jog" }),
135
- );
136
- });
137
-
138
- it("creates an event from a day slot", async () => {
139
- const user = userEvent.setup();
140
- const onEventCreate = vi.fn();
141
- render(
142
- <EventCalendar
143
- defaultDate={new Date(2026, 7, 15)}
144
- events={events}
145
- locale="en-US"
146
- onEventCreate={onEventCreate}
147
- />,
148
- );
149
- await user.click(screen.getByRole("button", { name: "15" }));
150
- expect(screen.getByRole("heading", { name: "New event" })).toBeInTheDocument();
151
- await user.type(screen.getByRole("textbox", { name: /title/i }), "Focus time");
152
- await user.click(screen.getByRole("button", { name: "Save" }));
153
- expect(onEventCreate).toHaveBeenCalledWith(expect.objectContaining({ title: "Focus time" }));
154
- });
155
-
156
- it("skips the built-in editor when showEventEditor is false", async () => {
157
- const user = userEvent.setup();
158
- const onEventClick = vi.fn();
159
- const onSlotClick = vi.fn();
160
- render(
161
- <EventCalendar
162
- defaultDate={new Date(2026, 7, 15)}
163
- events={events}
164
- resources={resources}
165
- locale="en-US"
166
- showEventEditor={false}
167
- onEventClick={onEventClick}
168
- onSlotClick={onSlotClick}
169
- />,
170
- );
171
- await user.click(screen.getByText("Morning Run"));
172
- expect(onEventClick).toHaveBeenCalledWith(expect.objectContaining({ id: "run" }));
173
- expect(screen.queryByRole("heading", { name: /event/i })).not.toBeInTheDocument();
174
-
175
- await user.click(screen.getByRole("button", { name: "15" }));
176
- expect(onSlotClick).toHaveBeenCalled();
177
- expect(screen.queryByRole("heading", { name: "New event" })).not.toBeInTheDocument();
178
- });
179
-
180
- it("renders custom event chips and toolbar", async () => {
181
- const user = userEvent.setup();
182
- const onDateChange = vi.fn();
183
- render(
184
- <EventCalendar
185
- defaultDate={new Date(2026, 7, 15)}
186
- events={events}
187
- resources={resources}
188
- locale="en-US"
189
- showEventEditor={false}
190
- showPreferences={false}
191
- toolbarTrailing={<button type="button">Jump year</button>}
192
- renderEvent={(event) => <span>★ {event.title}</span>}
193
- renderToolbar={({ title, onToday }) => (
194
- <div>
195
- <p>{title}</p>
196
- <button type="button" onClick={onToday}>
197
- Jump today
198
- </button>
199
- </div>
200
- )}
201
- onDateChange={onDateChange}
202
- />,
203
- );
204
- expect(screen.getByText("★ Morning Run")).toBeInTheDocument();
205
- expect(screen.queryByRole("button", { name: "Preferences" })).not.toBeInTheDocument();
206
- expect(screen.queryByRole("button", { name: "Jump year" })).not.toBeInTheDocument();
207
- await user.click(screen.getByRole("button", { name: "Jump today" }));
208
- expect(onDateChange).toHaveBeenCalled();
209
- });
210
-
211
- it("keeps toolbarTrailing on the default toolbar", () => {
212
- render(
213
- <EventCalendar
214
- defaultDate={new Date(2026, 7, 15)}
215
- events={events}
216
- locale="en-US"
217
- showPreferences={false}
218
- toolbarTrailing={<button type="button">Jump year</button>}
219
- />,
220
- );
221
- expect(screen.getByRole("button", { name: "Jump year" })).toBeInTheDocument();
222
- expect(screen.getByRole("heading", { name: /August 2026/i })).toBeInTheDocument();
223
- });
224
- });
225
-
226
7
  describe("EventTimeline", () => {
227
8
  const timelineEvents: SchedulerEvent[] = [
228
9
  {
package/src/index.test.ts CHANGED
@@ -7,7 +7,11 @@ import {
7
7
  ChartDataGrid,
8
8
  EventCalendar,
9
9
  MapChart,
10
+ SchedulerDateJump,
10
11
  SchedulerToolbar,
12
+ BREAKPOINTS,
13
+ calendarVisibleRange,
14
+ createTheme,
11
15
  mercator,
12
16
  } from "./index";
13
17
 
@@ -21,6 +25,12 @@ describe("@spatika/react public exports", () => {
21
25
  expect(BarChart3D).toBeTypeOf("function");
22
26
  expect(EventCalendar).toBeTypeOf("function");
23
27
  expect(SchedulerToolbar).toBeTypeOf("function");
28
+ expect(SchedulerDateJump).toBeTypeOf("function");
29
+ expect(calendarVisibleRange).toBeTypeOf("function");
24
30
  expect(mercator([0, 0])[0]).toBeCloseTo(0.5);
31
+ expect(BREAKPOINTS.md).toBe(768);
32
+ expect(createTheme({ id: "brand", palette: { primary: "#7c3aed" } }).vars["--primary"]).toBe(
33
+ "#7c3aed",
34
+ );
25
35
  });
26
36
  });
package/src/index.ts CHANGED
@@ -37,7 +37,9 @@ export {
37
37
  layoutToggleClass,
38
38
  listRowToggleClass,
39
39
  nativeSelectClass,
40
+ nativeSelectSizeClass,
40
41
  } from "./lib/chips";
42
+ export type { NativeSelectSize } from "./lib/chips";
41
43
  export {
42
44
  duration,
43
45
  transition,
@@ -55,8 +57,33 @@ export {
55
57
  applyTheme,
56
58
  isDarkTheme,
57
59
  isThemeId,
60
+ type ApplyThemeCustom,
61
+ type BuiltinThemeId,
58
62
  type ThemeId,
59
63
  } from "./lib/themes";
64
+ export {
65
+ createTheme,
66
+ themeToCss,
67
+ injectCustomThemeStyles,
68
+ findCustomTheme,
69
+ PALETTE_CSS_VARS,
70
+ GLASS_CSS_VARS,
71
+ SHAPE_CSS_VARS,
72
+ type CreateThemeOptions,
73
+ type SpatikaTheme,
74
+ type ThemePalette,
75
+ type ThemeGlass,
76
+ type ThemeShape,
77
+ type ThemeTypography,
78
+ } from "./lib/create-theme";
79
+ export {
80
+ BREAKPOINTS,
81
+ BREAKPOINT_KEYS,
82
+ breakpointUp,
83
+ breakpointDown,
84
+ breakpointBetween,
85
+ type Breakpoint,
86
+ } from "./lib/breakpoints";
60
87
  export { getAvatarColor, getAvatarFallbackHue, getInitials } from "./lib/avatar-utils";
61
88
  export {
62
89
  COVER_PATTERN_KINDS,
@@ -77,7 +104,13 @@ export {
77
104
  coverTitleClass,
78
105
  } from "./lib/cover-chrome";
79
106
  export { useCoverChromeBleed, type CoverChromeInk } from "./lib/use-cover-chrome-bleed";
80
- export { useIsMobile, useMediaQuery } from "./lib/use-media-query";
107
+ export {
108
+ useIsMobile,
109
+ useMediaQuery,
110
+ useBreakpoint,
111
+ useBreakpointUp,
112
+ useBreakpointDown,
113
+ } from "./lib/use-media-query";
81
114
  export {
82
115
  SpatikaThemeProvider,
83
116
  useSpatikaTheme,
@@ -209,7 +242,7 @@ export {
209
242
  SelectTrigger,
210
243
  SelectValue,
211
244
  } from "./primitives/Select";
212
- export { NativeSelect } from "./primitives/NativeSelect";
245
+ export { NativeSelect, type NativeSelectProps } from "./primitives/NativeSelect";
213
246
  export { Spinner } from "./primitives/Spinner";
214
247
  export { Alert, AlertTitle, AlertDescription, alertVariants } from "./primitives/Alert";
215
248
  export { Kbd } from "./primitives/Kbd";
@@ -402,6 +435,36 @@ export {
402
435
  type PhotoViewerItem,
403
436
  } from "./composites/PhotoViewer";
404
437
  export { RichTextEditor, type RichTextEditorProps } from "./composites/RichTextEditor";
438
+ export {
439
+ SpatikaEditor,
440
+ useSpatikaEditor,
441
+ buildSpatikaExtensions,
442
+ EditorToolbar,
443
+ EditorBubbleMenu,
444
+ ImageBubbleMenu,
445
+ SlashCommandMenu,
446
+ MentionMenu,
447
+ AiOverlay,
448
+ ToolbarButton,
449
+ createSlashCommandExtension,
450
+ defaultSlashCommands,
451
+ createMentionExtension,
452
+ ResizableImage,
453
+ createAiActionExtension,
454
+ } from "@spatika/editor";
455
+ export type {
456
+ SpatikaEditorProps,
457
+ SpatikaEditorHandle,
458
+ SpatikaEditorToolbarConfig,
459
+ SlashCommandItem,
460
+ MentionContact,
461
+ AiActionDefinition,
462
+ PlaceholderConfig,
463
+ UseSpatikaEditorOptions,
464
+ SlashCommandStorage,
465
+ MentionStorage,
466
+ ImageAlign,
467
+ } from "@spatika/editor";
405
468
  export { HeaderIconButton, type HeaderIconButtonProps } from "./composites/HeaderIconButton";
406
469
  export {
407
470
  QuickFilterRail,
@@ -500,16 +563,22 @@ export {
500
563
  } from "./composites/EventEditor";
501
564
  export {
502
565
  SchedulerToolbar,
566
+ SchedulerDateJump,
503
567
  SchedulerPreferencesMenu,
504
568
  CALENDAR_VIEW_LABEL,
505
569
  type SchedulerToolbarProps,
570
+ type SchedulerToolbarDensity,
571
+ type SchedulerDateJumpProps,
506
572
  } from "./composites/scheduler-ui";
507
573
  export {
508
574
  DEFAULT_SCHEDULER_PREFERENCES,
509
575
  SCHEDULER_COLOR_TONES,
576
+ CALENDAR_AGENDA_DAYS,
577
+ calendarVisibleRange,
510
578
  } from "./lib/scheduler";
511
579
  export type {
512
580
  CalendarView,
581
+ CalendarVisibleRange,
513
582
  NormalizedEvent,
514
583
  SchedulerColorTone,
515
584
  SchedulerEvent,
@@ -521,26 +590,25 @@ export {
521
590
  CHART_COLOR_VARS,
522
591
  chartColor,
523
592
  formatChartNumber,
593
+ formatAxisNumber,
594
+ resolveChartRadius,
595
+ categoryLabelGutter,
596
+ fitCategoryLabel,
524
597
  seriesDataFromDataset,
525
598
  axisDataFromDataset,
526
599
  clampZoom,
527
600
  DEFAULT_ZOOM,
528
- } from "./lib/charts";
529
- export type {
530
- ChartAxisConfig,
531
- ChartCurve,
532
- ChartDataset,
533
- ChartInteraction,
534
- ChartMargin,
535
- ChartZoom,
536
- HighlightScope,
537
- SankeyLink,
538
- SankeyNode,
539
- TreeNode,
540
- } from "./lib/charts";
541
- export { serializeChartSvg, exportChart, downloadChartSvg, downloadChartPng } from "./lib/chart-export";
542
- export {
601
+ stackSeries,
602
+ errorBarRange,
603
+ pieLabelLine,
604
+ seriesHasPlottableData,
605
+ serializeChartSvg,
606
+ exportChart,
607
+ downloadChartSvg,
608
+ downloadChartPng,
543
609
  ChartContainer,
610
+ ComposedChart,
611
+ ResponsiveContainer,
544
612
  ChartSurface,
545
613
  ChartsGrid,
546
614
  ChartsXAxis,
@@ -548,19 +616,16 @@ export {
548
616
  ChartsLegend,
549
617
  ChartsToolbar,
550
618
  ChartsBrush,
619
+ ChartsCursor,
620
+ ChartsReferenceLine,
621
+ ChartsReferenceArea,
622
+ ChartsReferenceDot,
623
+ ChartsErrorBar,
551
624
  BarPlot,
552
625
  LinePlot,
553
626
  AreaPlot,
554
627
  ScatterPlot,
555
628
  useChartContext,
556
- } from "./composites/chart-composition";
557
- export type {
558
- ChartContainerProps,
559
- ComposedSeries,
560
- ComposedSeriesType,
561
- HighlightedItem,
562
- } from "./composites/chart-composition";
563
- export {
564
629
  AreaChart,
565
630
  BarChart,
566
631
  BoxPlotChart,
@@ -573,8 +638,60 @@ export {
573
638
  ScatterChart,
574
639
  SparkLineChart,
575
640
  WaterfallChart,
576
- } from "./composites/cartesian-charts";
641
+ Gauge,
642
+ LinearGauge,
643
+ PieChart,
644
+ PolarLineChart,
645
+ RadarChart,
646
+ RadialBarChart,
647
+ RadialLineChart,
648
+ ChordChart,
649
+ FunnelChart,
650
+ Heatmap,
651
+ PyramidChart,
652
+ SankeyChart,
653
+ SunburstChart,
654
+ Treemap,
655
+ MapChart,
656
+ BarChart3D,
657
+ PieChart3D,
658
+ ChartDataGrid,
659
+ renderChartCell,
660
+ mercator,
661
+ equirectangular,
662
+ geoPath,
663
+ fitFeatures,
664
+ featureId,
665
+ } from "@spatika/charts";
577
666
  export type {
667
+ ChartAxisConfig,
668
+ ChartCurve,
669
+ ChartDataset,
670
+ ChartErrorValue,
671
+ ChartInteraction,
672
+ ChartLegendPosition,
673
+ ChartMargin,
674
+ ChartRadius,
675
+ ChartZoom,
676
+ HighlightScope,
677
+ SankeyLink,
678
+ SankeyNode,
679
+ StackOffset,
680
+ TreeNode,
681
+ ChartContainerProps,
682
+ ComposedSeries,
683
+ ComposedSeriesType,
684
+ HighlightedItem,
685
+ ResponsiveContainerProps,
686
+ ChartHover,
687
+ ChartItemEvent,
688
+ ChartMarkRenderContext,
689
+ ChartReferenceArea,
690
+ ChartReferenceDot,
691
+ ChartReferenceLine,
692
+ ChartTooltipItem,
693
+ ChartTooltipRenderer,
694
+ ChartTooltipTrigger,
578
695
  BarChartProps,
579
696
  BoxPlotChartProps,
580
697
  CandleDatum,
@@ -591,17 +708,6 @@ export type {
591
708
  ScatterSeries,
592
709
  SparkLineChartProps,
593
710
  WaterfallChartProps,
594
- } from "./composites/cartesian-charts";
595
- export {
596
- Gauge,
597
- LinearGauge,
598
- PieChart,
599
- PolarLineChart,
600
- RadarChart,
601
- RadialBarChart,
602
- RadialLineChart,
603
- } from "./composites/radial-charts";
604
- export type {
605
711
  GaugeProps,
606
712
  GaugeSection,
607
713
  LinearGaugeProps,
@@ -612,17 +718,6 @@ export type {
612
718
  RadarSeries,
613
719
  RadialBarChartProps,
614
720
  RadialLineChartProps,
615
- } from "./composites/radial-charts";
616
- export {
617
- ChordChart,
618
- FunnelChart,
619
- Heatmap,
620
- PyramidChart,
621
- SankeyChart,
622
- SunburstChart,
623
- Treemap,
624
- } from "./composites/flow-charts";
625
- export type {
626
721
  ChordChartProps,
627
722
  FunnelChartProps,
628
723
  FunnelDatum,
@@ -633,28 +728,16 @@ export type {
633
728
  SankeyChartProps,
634
729
  SunburstChartProps,
635
730
  TreemapProps,
636
- } from "./composites/flow-charts";
637
- export { MapChart } from "./composites/MapChart";
638
- export type { MapChartProps, MapShapeDatum } from "./composites/MapChart";
639
- export { BarChart3D, PieChart3D } from "./composites/charts-3d";
640
- export type { BarChart3DProps, PieChart3DProps } from "./composites/charts-3d";
641
- export { ChartDataGrid, renderChartCell } from "./composites/ChartDataGrid";
642
- export type {
731
+ MapChartProps,
732
+ MapShapeDatum,
733
+ BarChart3DProps,
734
+ PieChart3DProps,
643
735
  ChartDataGridProps,
644
736
  ChartDataGridRow,
645
737
  ChartGridColumn,
646
738
  ChartGridColumnType,
647
- } from "./composites/ChartDataGrid";
648
- export {
649
- mercator,
650
- equirectangular,
651
- geoPath,
652
- fitFeatures,
653
- featureId,
654
- } from "./lib/geo";
655
- export type {
656
739
  GeoJsonFeature,
657
740
  GeoJsonFeatureCollection,
658
741
  GeoJsonGeometry,
659
742
  GeoProjectionKind,
660
- } from "./lib/geo";
743
+ } from "@spatika/charts";
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ BREAKPOINTS,
4
+ BREAKPOINT_KEYS,
5
+ breakpointBetween,
6
+ breakpointDown,
7
+ breakpointUp,
8
+ } from "./breakpoints";
9
+
10
+ describe("breakpoints", () => {
11
+ it("matches Tailwind viewport widths", () => {
12
+ expect(BREAKPOINTS).toEqual({ xs: 0, sm: 640, md: 768, lg: 1024, xl: 1280 });
13
+ expect(BREAKPOINT_KEYS).toEqual(["xs", "sm", "md", "lg", "xl"]);
14
+ });
15
+
16
+ it("builds min-width and max-width queries", () => {
17
+ expect(breakpointUp("xs")).toBe("(min-width: 0px)");
18
+ expect(breakpointUp("md")).toBe("(min-width: 768px)");
19
+ expect(breakpointDown("md")).toBe("(max-width: 767px)");
20
+ expect(breakpointDown("xl")).toBe("(max-width: 1279px)");
21
+ });
22
+
23
+ it("builds an inclusive range", () => {
24
+ expect(breakpointBetween("sm", "lg")).toBe(
25
+ "(min-width: 640px) and (max-width: 1023px)",
26
+ );
27
+ expect(breakpointBetween("md")).toBe("(min-width: 768px)");
28
+ });
29
+ });
@@ -0,0 +1,28 @@
1
+ /** Viewport widths (px) that match Tailwind and Spatika `Grid` / `Container`. */
2
+ export const BREAKPOINTS = {
3
+ xs: 0,
4
+ sm: 640,
5
+ md: 768,
6
+ lg: 1024,
7
+ xl: 1280,
8
+ } as const;
9
+
10
+ export type Breakpoint = keyof typeof BREAKPOINTS;
11
+
12
+ export const BREAKPOINT_KEYS = ["xs", "sm", "md", "lg", "xl"] as const satisfies readonly Breakpoint[];
13
+
14
+ /** `(min-width: Npx)` — inclusive start of a breakpoint. `xs` is always true. */
15
+ export function breakpointUp(key: Breakpoint): string {
16
+ return `(min-width: ${BREAKPOINTS[key]}px)`;
17
+ }
18
+
19
+ /** `(max-width: N-1px)` — viewports strictly below a breakpoint. */
20
+ export function breakpointDown(key: Exclude<Breakpoint, "xs">): string {
21
+ return `(max-width: ${BREAKPOINTS[key] - 1}px)`;
22
+ }
23
+
24
+ /** Inclusive range between two breakpoints. `end` omitted means no upper bound. */
25
+ export function breakpointBetween(start: Breakpoint, end?: Exclude<Breakpoint, "xs">): string {
26
+ if (!end) return breakpointUp(start);
27
+ return `${breakpointUp(start)} and ${breakpointDown(end)}`;
28
+ }
package/src/lib/chips.ts CHANGED
@@ -56,3 +56,19 @@ export const nativeSelectClass = cn(
56
56
  "focus:outline-none focus:border-primary/40 focus:ring-2 focus:ring-primary/20",
57
57
  "disabled:cursor-not-allowed disabled:opacity-50",
58
58
  );
59
+
60
+ export type NativeSelectSize = "sm" | "default" | "touch";
61
+
62
+ /** Size recipes for NativeSelect. `sm` is for toolbars (not full width). */
63
+ export function nativeSelectSizeClass(size: NativeSelectSize = "default") {
64
+ if (size === "sm") {
65
+ return cn(
66
+ nativeSelectClass,
67
+ "mt-0 h-8 min-h-8 w-auto rounded-full px-2 text-[11px] font-semibold",
68
+ );
69
+ }
70
+ if (size === "touch") {
71
+ return cn(nativeSelectClass, "mt-0 min-h-11");
72
+ }
73
+ return cn(nativeSelectClass, "mt-0");
74
+ }