@nocoo/basalt 2.0.3 → 2.1.2

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 (295) hide show
  1. package/README.md +134 -15
  2. package/ai/COMPATIBILITY.md +180 -0
  3. package/ai/INTEGRATION.md +1760 -0
  4. package/ai/RECIPES.md +161 -0
  5. package/ai/USAGE.md +99 -0
  6. package/ai/registry.json +38099 -0
  7. package/ai/sources.json +10 -0
  8. package/dist/assets/brand-mark.d.ts +1 -0
  9. package/dist/assets/brand-mark.js +7 -0
  10. package/dist/assets/brand-mark.js.map +1 -0
  11. package/dist/charts/area.d.ts +58 -5
  12. package/dist/charts/area.js +20 -12
  13. package/dist/charts/area.js.map +1 -1
  14. package/dist/charts/bar.d.ts +54 -5
  15. package/dist/charts/bar.js +16 -10
  16. package/dist/charts/bar.js.map +1 -1
  17. package/dist/charts/bullet.d.ts +18 -1
  18. package/dist/charts/bullet.js +6 -3
  19. package/dist/charts/bullet.js.map +1 -1
  20. package/dist/charts/charts.d.ts +58 -5
  21. package/dist/charts/charts.js +13 -2
  22. package/dist/charts/charts.js.map +1 -1
  23. package/dist/charts/config.d.ts +7 -0
  24. package/dist/charts/config.js +5 -1
  25. package/dist/charts/config.js.map +1 -1
  26. package/dist/charts/custom-chart.d.ts +58 -5
  27. package/dist/charts/custom-chart.js +13 -2
  28. package/dist/charts/custom-chart.js.map +1 -1
  29. package/dist/charts/donut.d.ts +18 -1
  30. package/dist/charts/donut.js +6 -3
  31. package/dist/charts/donut.js.map +1 -1
  32. package/dist/charts/frame.d.ts +40 -3
  33. package/dist/charts/frame.js +55 -28
  34. package/dist/charts/frame.js.map +1 -1
  35. package/dist/charts/funnel.d.ts +18 -1
  36. package/dist/charts/funnel.js +5 -1
  37. package/dist/charts/funnel.js.map +1 -1
  38. package/dist/charts/gauge.d.ts +18 -1
  39. package/dist/charts/gauge.js +38 -20
  40. package/dist/charts/gauge.js.map +1 -1
  41. package/dist/charts/grouped-bar.d.ts +54 -5
  42. package/dist/charts/grouped-bar.js +16 -10
  43. package/dist/charts/grouped-bar.js.map +1 -1
  44. package/dist/charts/heatmap-calendar.d.ts +61 -0
  45. package/dist/charts/heatmap-calendar.js +287 -96
  46. package/dist/charts/heatmap-calendar.js.map +1 -1
  47. package/dist/charts/heatmap-matrix.d.ts +99 -0
  48. package/dist/charts/heatmap-matrix.js +249 -0
  49. package/dist/charts/heatmap-matrix.js.map +1 -0
  50. package/dist/charts/line.d.ts +66 -5
  51. package/dist/charts/line.js +37 -30
  52. package/dist/charts/line.js.map +1 -1
  53. package/dist/charts/palette.d.ts +1 -0
  54. package/dist/charts/palette.js +7 -1
  55. package/dist/charts/palette.js.map +1 -1
  56. package/dist/charts/radar.d.ts +18 -1
  57. package/dist/charts/radar.js +26 -19
  58. package/dist/charts/radar.js.map +1 -1
  59. package/dist/charts/sankey.d.ts +18 -1
  60. package/dist/charts/sankey.js +4 -1
  61. package/dist/charts/sankey.js.map +1 -1
  62. package/dist/charts/series.d.ts +5 -7
  63. package/dist/charts/series.js.map +1 -1
  64. package/dist/charts/slot-bar.d.ts +38 -6
  65. package/dist/charts/slot-bar.js +5 -2
  66. package/dist/charts/slot-bar.js.map +1 -1
  67. package/dist/charts/sparkline.d.ts +35 -5
  68. package/dist/charts/sparkline.js +22 -18
  69. package/dist/charts/sparkline.js.map +1 -1
  70. package/dist/charts/stacked-bar.d.ts +58 -5
  71. package/dist/charts/stacked-bar.js +19 -12
  72. package/dist/charts/stacked-bar.js.map +1 -1
  73. package/dist/charts/stat-card.d.ts +51 -1
  74. package/dist/charts/stat-card.js +66 -39
  75. package/dist/charts/stat-card.js.map +1 -1
  76. package/dist/charts/timeline.d.ts +3 -0
  77. package/dist/charts/timeline.js +4 -3
  78. package/dist/charts/timeline.js.map +1 -1
  79. package/dist/charts/timeseries.d.ts +58 -5
  80. package/dist/charts/timeseries.js +13 -2
  81. package/dist/charts/timeseries.js.map +1 -1
  82. package/dist/charts/tooltip.d.ts +57 -0
  83. package/dist/charts/tooltip.js +119 -2
  84. package/dist/charts/tooltip.js.map +1 -1
  85. package/dist/components/accordion.d.ts +117 -2
  86. package/dist/components/accordion.js +20 -13
  87. package/dist/components/accordion.js.map +1 -1
  88. package/dist/components/alert-dialog.d.ts +131 -13
  89. package/dist/components/alert-dialog.js +12 -9
  90. package/dist/components/alert-dialog.js.map +1 -1
  91. package/dist/components/app-header.js +18 -17
  92. package/dist/components/app-header.js.map +1 -1
  93. package/dist/components/app-shell.js +15 -14
  94. package/dist/components/app-shell.js.map +1 -1
  95. package/dist/components/autocomplete.d.ts +4 -0
  96. package/dist/components/autocomplete.js.map +1 -1
  97. package/dist/components/avatar.d.ts +76 -3
  98. package/dist/components/avatar.js.map +1 -1
  99. package/dist/components/badge.d.ts +15 -1
  100. package/dist/components/badge.js +13 -12
  101. package/dist/components/badge.js.map +1 -1
  102. package/dist/components/banner.d.ts +88 -2
  103. package/dist/components/banner.js +41 -40
  104. package/dist/components/banner.js.map +1 -1
  105. package/dist/components/basalt-mark.js +14 -8
  106. package/dist/components/basalt-mark.js.map +1 -1
  107. package/dist/components/battery-meter.d.ts +10 -0
  108. package/dist/components/battery-meter.js +56 -0
  109. package/dist/components/battery-meter.js.map +1 -0
  110. package/dist/components/breadcrumbs.d.ts +27 -7
  111. package/dist/components/breadcrumbs.js +21 -20
  112. package/dist/components/breadcrumbs.js.map +1 -1
  113. package/dist/components/button.d.ts +48 -2
  114. package/dist/components/button.js +87 -36
  115. package/dist/components/button.js.map +1 -1
  116. package/dist/components/chat-bubble.d.ts +7 -0
  117. package/dist/components/chat-bubble.js +14 -13
  118. package/dist/components/chat-bubble.js.map +1 -1
  119. package/dist/components/chat-composer.d.ts +7 -3
  120. package/dist/components/chat-composer.js.map +1 -1
  121. package/dist/components/chat-header.d.ts +6 -1
  122. package/dist/components/chat-header.js +17 -16
  123. package/dist/components/chat-header.js.map +1 -1
  124. package/dist/components/chat-inbox.d.ts +7 -2
  125. package/dist/components/chat-inbox.js.map +1 -1
  126. package/dist/components/checkbox.js +84 -53
  127. package/dist/components/checkbox.js.map +1 -1
  128. package/dist/components/clipboard-text.d.ts +13 -2
  129. package/dist/components/clipboard-text.js +4 -4
  130. package/dist/components/clipboard-text.js.map +1 -1
  131. package/dist/components/collapsible.d.ts +58 -15
  132. package/dist/components/collapsible.js.map +1 -1
  133. package/dist/components/command-palette.d.ts +151 -61
  134. package/dist/components/command-palette.js.map +1 -1
  135. package/dist/components/confirm-dialog.d.ts +1 -1
  136. package/dist/components/confirm-dialog.js +6 -4
  137. package/dist/components/confirm-dialog.js.map +1 -1
  138. package/dist/components/context-menu.d.ts +210 -2
  139. package/dist/components/context-menu.js +7 -4
  140. package/dist/components/context-menu.js.map +1 -1
  141. package/dist/components/data-table.d.ts +40 -2
  142. package/dist/components/data-table.js +168 -120
  143. package/dist/components/data-table.js.map +1 -1
  144. package/dist/components/date-picker.d.ts +53 -2
  145. package/dist/components/date-picker.js +387 -219
  146. package/dist/components/date-picker.js.map +1 -1
  147. package/dist/components/delete-resource.d.ts +7 -1
  148. package/dist/components/delete-resource.js +22 -18
  149. package/dist/components/delete-resource.js.map +1 -1
  150. package/dist/components/description-list.js +16 -15
  151. package/dist/components/description-list.js.map +1 -1
  152. package/dist/components/dialog.d.ts +141 -12
  153. package/dist/components/dialog.js +42 -38
  154. package/dist/components/dialog.js.map +1 -1
  155. package/dist/components/dock.d.ts +1 -1
  156. package/dist/components/dock.js +39 -58
  157. package/dist/components/dock.js.map +1 -1
  158. package/dist/components/dropdown-menu.d.ts +229 -15
  159. package/dist/components/dropdown-menu.js +9 -6
  160. package/dist/components/dropdown-menu.js.map +1 -1
  161. package/dist/components/editable-nav-item.d.ts +33 -0
  162. package/dist/components/editable-nav-item.js +90 -0
  163. package/dist/components/editable-nav-item.js.map +1 -0
  164. package/dist/components/empty.d.ts +22 -2
  165. package/dist/components/empty.js +22 -13
  166. package/dist/components/empty.js.map +1 -1
  167. package/dist/components/field.js +31 -30
  168. package/dist/components/field.js.map +1 -1
  169. package/dist/components/file-dropzone.d.ts +37 -0
  170. package/dist/components/file-dropzone.js +103 -0
  171. package/dist/components/file-dropzone.js.map +1 -0
  172. package/dist/components/filter-bar.d.ts +34 -0
  173. package/dist/components/filter-bar.js +52 -0
  174. package/dist/components/filter-bar.js.map +1 -0
  175. package/dist/components/flow.js +19 -18
  176. package/dist/components/flow.js.map +1 -1
  177. package/dist/components/grid.d.ts +3 -1
  178. package/dist/components/grid.js.map +1 -1
  179. package/dist/components/hover-card.d.ts +111 -1
  180. package/dist/components/hover-card.js +9 -6
  181. package/dist/components/hover-card.js.map +1 -1
  182. package/dist/components/icon-picker.d.ts +34 -0
  183. package/dist/components/icon-picker.js +77 -0
  184. package/dist/components/icon-picker.js.map +1 -0
  185. package/dist/components/inline-editable.d.ts +46 -0
  186. package/dist/components/inline-editable.js +124 -0
  187. package/dist/components/inline-editable.js.map +1 -0
  188. package/dist/components/input-area.js +3 -3
  189. package/dist/components/input-group.js +7 -7
  190. package/dist/components/input.js +3 -3
  191. package/dist/components/label.js +18 -17
  192. package/dist/components/label.js.map +1 -1
  193. package/dist/components/layer-card.d.ts +10 -2
  194. package/dist/components/layer-card.js +71 -68
  195. package/dist/components/layer-card.js.map +1 -1
  196. package/dist/components/loader.d.ts +10 -2
  197. package/dist/components/loader.js.map +1 -1
  198. package/dist/components/menu-bar.d.ts +174 -6
  199. package/dist/components/menu-bar.js +33 -29
  200. package/dist/components/menu-bar.js.map +1 -1
  201. package/dist/components/meter.d.ts +27 -2
  202. package/dist/components/meter.js.map +1 -1
  203. package/dist/components/multi-select.d.ts +64 -0
  204. package/dist/components/multi-select.js +218 -0
  205. package/dist/components/multi-select.js.map +1 -0
  206. package/dist/components/navigation-menu.d.ts +88 -5
  207. package/dist/components/navigation-menu.js.map +1 -1
  208. package/dist/components/overlay.js +6 -5
  209. package/dist/components/overlay.js.map +1 -1
  210. package/dist/components/page-header.js +23 -21
  211. package/dist/components/page-header.js.map +1 -1
  212. package/dist/components/pagination.js +7 -7
  213. package/dist/components/popover.d.ts +136 -16
  214. package/dist/components/popover.js +32 -28
  215. package/dist/components/popover.js.map +1 -1
  216. package/dist/components/radio.js +38 -37
  217. package/dist/components/radio.js.map +1 -1
  218. package/dist/components/resource-list.d.ts +26 -1
  219. package/dist/components/resource-list.js +28 -15
  220. package/dist/components/resource-list.js.map +1 -1
  221. package/dist/components/responsive-master-detail.d.ts +27 -0
  222. package/dist/components/responsive-master-detail.js +85 -0
  223. package/dist/components/responsive-master-detail.js.map +1 -0
  224. package/dist/components/section-rule.js +23 -22
  225. package/dist/components/section-rule.js.map +1 -1
  226. package/dist/components/select.d.ts +27 -3
  227. package/dist/components/select.js +11 -11
  228. package/dist/components/select.js.map +1 -1
  229. package/dist/components/sheet.d.ts +115 -11
  230. package/dist/components/sheet.js +37 -30
  231. package/dist/components/sheet.js.map +1 -1
  232. package/dist/components/sidebar.d.ts +109 -17
  233. package/dist/components/sidebar.js +112 -111
  234. package/dist/components/sidebar.js.map +1 -1
  235. package/dist/components/skeleton-line.d.ts +22 -2
  236. package/dist/components/skeleton-line.js.map +1 -1
  237. package/dist/components/slider.d.ts +61 -1
  238. package/dist/components/slider.js +31 -15
  239. package/dist/components/slider.js.map +1 -1
  240. package/dist/components/stat-strip.js +16 -15
  241. package/dist/components/stat-strip.js.map +1 -1
  242. package/dist/components/switch.js +78 -47
  243. package/dist/components/switch.js.map +1 -1
  244. package/dist/components/table-of-contents.js +18 -17
  245. package/dist/components/table-of-contents.js.map +1 -1
  246. package/dist/components/table-pager.js +20 -19
  247. package/dist/components/table-pager.js.map +1 -1
  248. package/dist/components/table.d.ts +9 -3
  249. package/dist/components/table.js +19 -18
  250. package/dist/components/table.js.map +1 -1
  251. package/dist/components/tabs.js +29 -22
  252. package/dist/components/tabs.js.map +1 -1
  253. package/dist/components/tag-badge.d.ts +58 -0
  254. package/dist/components/tag-badge.js +72 -0
  255. package/dist/components/tag-badge.js.map +1 -0
  256. package/dist/components/tag-color-picker.d.ts +20 -0
  257. package/dist/components/tag-color-picker.js +42 -0
  258. package/dist/components/tag-color-picker.js.map +1 -0
  259. package/dist/components/text.js +17 -16
  260. package/dist/components/text.js.map +1 -1
  261. package/dist/components/toast.d.ts +173 -3
  262. package/dist/components/toast.js +1 -1
  263. package/dist/components/toast.js.map +1 -1
  264. package/dist/components/toggle-group.d.ts +88 -2
  265. package/dist/components/toggle-group.js +32 -31
  266. package/dist/components/toggle-group.js.map +1 -1
  267. package/dist/components/toggle.d.ts +35 -2
  268. package/dist/components/toggle.js +12 -11
  269. package/dist/components/toggle.js.map +1 -1
  270. package/dist/components/tooltip.d.ts +144 -6
  271. package/dist/components/tooltip.js +9 -6
  272. package/dist/components/tooltip.js.map +1 -1
  273. package/dist/components/typeahead-field.js +193 -132
  274. package/dist/components/typeahead-field.js.map +1 -1
  275. package/dist/components/upload-queue.d.ts +51 -0
  276. package/dist/components/upload-queue.js +116 -0
  277. package/dist/components/upload-queue.js.map +1 -0
  278. package/dist/providers/accent.d.ts +46 -2
  279. package/dist/providers/accent.js +358 -172
  280. package/dist/providers/accent.js.map +1 -1
  281. package/dist/providers/link.d.ts +14 -4
  282. package/dist/providers/link.js.map +1 -1
  283. package/dist/providers/theme.d.ts +38 -2
  284. package/dist/providers/theme.js +160 -27
  285. package/dist/providers/theme.js.map +1 -1
  286. package/dist/styles/base.css +83 -0
  287. package/dist/styles/standalone.css +699 -120
  288. package/dist/styles/tailwind.css +21 -7
  289. package/dist/styles/tokens.css +145 -91
  290. package/dist/utils/control-surface.d.ts +2 -1
  291. package/dist/utils/control-surface.js +4 -4
  292. package/dist/utils/control-surface.js.map +1 -1
  293. package/dist/utils/selection-indicator.js +2 -2
  294. package/dist/utils/selection-indicator.js.map +1 -1
  295. package/package.json +8 -4
package/ai/RECIPES.md ADDED
@@ -0,0 +1,161 @@
1
+ # Application recipes
2
+
3
+ These complete modules, included in v2.1.0, use only public Basalt imports and React.
4
+
5
+ Load exactly one CSS mode at the application entry: import `@nocoo/basalt/styles/standalone` for a build without Tailwind, or configure the Tailwind source scan and import `@nocoo/basalt/styles/tailwind` as described in INTEGRATION.md. In Next, import CSS in the root layout and import these modules through a `use client` boundary. Mount ThemeProvider once per application; the standalone recipes include their own root provider. Root pages should set body margin to zero.
6
+
7
+ Replace the local adapters with application routing, authentication and data services. Basalt does not own permissions, backend URLs, credentials, or persistence. The exact modules below are extracted from the installed tarball and exercised in A/B/Next consumers.
8
+
9
+ ## AppFrame
10
+
11
+ Desktop navigation stays in flow; below 768 CSS pixels it becomes a named drawer. Closing or selecting a section restores the menu control. The media listener is removed on unmount.
12
+
13
+ ```tsx compile:recipe-app-frame
14
+ import { AppHeader } from "@nocoo/basalt/components/app-header";
15
+ import { AppMain, AppShell, AppSkipLink } from "@nocoo/basalt/components/app-shell";
16
+ import { Button } from "@nocoo/basalt/components/button";
17
+ import { DialogDescription, DialogTitle } from "@nocoo/basalt/components/dialog";
18
+ import { PageHeader } from "@nocoo/basalt/components/page-header";
19
+ import { Sidebar, SidebarHeader, SidebarItem, SidebarNav, SidebarProvider } from "@nocoo/basalt/components/sidebar";
20
+ import { ThemeToggle } from "@nocoo/basalt/components/theme-toggle";
21
+ import { ThemeProvider } from "@nocoo/basalt/providers/theme";
22
+ import { useEffect, useState } from "react";
23
+
24
+ export default function AppFrameRecipe() {
25
+ const [page, setPage] = useState("Projects");
26
+ const [compact, setCompact] = useState(false);
27
+ const [collapsed, setCollapsed] = useState(true);
28
+ useEffect(() => {
29
+ const media = matchMedia("(max-width: 767px)");
30
+ const update = () => { setCompact(media.matches); setCollapsed(media.matches); };
31
+ update();
32
+ media.addEventListener("change", update);
33
+ return () => media.removeEventListener("change", update);
34
+ }, []);
35
+ // Replace this local state change with your router's navigation adapter.
36
+ function navigate(next: string) { setPage(next); if (compact) setCollapsed(true); }
37
+ return <ThemeProvider><div style={{ position: "fixed", inset: 0 }}>
38
+ <SidebarProvider collapsed={collapsed} onCollapsedChange={setCollapsed} overlay={compact}>
39
+ <AppShell>
40
+ <AppSkipLink href="#recipe-main">Skip to content</AppSkipLink>
41
+ <Sidebar>
42
+ {compact && <><DialogTitle className="sr-only">Workspace navigation</DialogTitle><DialogDescription className="sr-only">Choose an application section.</DialogDescription></>}
43
+ <SidebarHeader><strong>Atlas workspace</strong></SidebarHeader>
44
+ <SidebarNav aria-label="Workspace navigation">
45
+ {["Projects", "Members", "Activity"].map((name) => <SidebarItem key={name} active={page === name} onClick={() => navigate(name)}>{name}</SidebarItem>)}
46
+ </SidebarNav>
47
+ </Sidebar>
48
+ <AppMain id="recipe-main" tabIndex={-1}>
49
+ <AppHeader leading={<Button size="sm" variant="ghost" aria-label="Toggle navigation" onClick={() => setCollapsed(!collapsed)}>Menu</Button>} actions={<ThemeToggle aria-label="Change theme" />} />
50
+ <div style={{ overflow: "auto", flex: 1, padding: 24 }}>
51
+ <PageHeader title={page} description="A reusable application frame with responsive navigation." />
52
+ <p role="status" className="mt-4 text-sm text-basalt-muted-foreground">Opened {page}. Your application supplies routes and page content.</p>
53
+ </div>
54
+ </AppMain>
55
+ </AppShell>
56
+ </SidebarProvider>
57
+ </div></ThemeProvider>;
58
+ }
59
+ ```
60
+
61
+ ## Login
62
+
63
+ Native validation and FormData feed an application-supplied async authenticator. Failed authentication retains the form. Repeated submits are blocked and unmount aborts the request; the application owns the success transition and session.
64
+
65
+ ```tsx compile:recipe-login
66
+ import { Button } from "@nocoo/basalt/components/button";
67
+ import { Field } from "@nocoo/basalt/components/field";
68
+ import { Input } from "@nocoo/basalt/components/input";
69
+ import { SensitiveInput } from "@nocoo/basalt/components/sensitive-input";
70
+ import { ThemeProvider } from "@nocoo/basalt/providers/theme";
71
+ import { useEffect, useRef, useState } from "react";
72
+
73
+ type Credentials = { email: string; password: string };
74
+ export function LoginForm({ authenticate, onSuccess }: {
75
+ authenticate: (credentials: Credentials, signal: AbortSignal) => Promise<void>;
76
+ onSuccess: (email: string) => void;
77
+ }) {
78
+ const [pending, setPending] = useState(false);
79
+ const [error, setError] = useState("");
80
+ const active = useRef<AbortController | null>(null);
81
+ useEffect(() => () => active.current?.abort(), []);
82
+ return <form aria-label="Sign in" className="space-y-4" onSubmit={async (event) => {
83
+ event.preventDefault();
84
+ if (active.current) return;
85
+ const form = new FormData(event.currentTarget);
86
+ const email = String(form.get("email") ?? "");
87
+ const password = String(form.get("password") ?? "");
88
+ const controller = new AbortController();
89
+ active.current = controller; setPending(true); setError("");
90
+ try {
91
+ await authenticate({ email, password }, controller.signal);
92
+ if (!controller.signal.aborted) onSuccess(email);
93
+ } catch (cause) {
94
+ if (!controller.signal.aborted) setError(cause instanceof Error ? cause.message : "Sign in failed. Try again.");
95
+ } finally {
96
+ if (!controller.signal.aborted) { active.current = null; setPending(false); }
97
+ }
98
+ }}>
99
+ <Field label="Email"><Input name="email" type="email" autoComplete="username" required /></Field>
100
+ <Field label="Password"><SensitiveInput name="password" autoComplete="current-password" revealLabel="Show password" hideLabel="Hide password" required /></Field>
101
+ {error && <p role="alert" className="text-sm text-basalt-destructive">{error}</p>}
102
+ <Button className="w-full" type="submit" loading={pending}>Sign in</Button>
103
+ </form>;
104
+ }
105
+
106
+ export default function LoginRecipe() {
107
+ const [account, setAccount] = useState<string | null>(null);
108
+ return <ThemeProvider><main style={{ boxSizing: "border-box", minHeight: "100dvh", display: "grid", placeItems: "center", padding: 16 }}>
109
+ <div className="rounded-basalt-lg border border-basalt-border bg-basalt-card p-6 space-y-4" style={{ boxSizing: "border-box", width: "100%", maxWidth: 380 }}>
110
+ <h1 className="text-xl font-semibold">Welcome to Atlas</h1>
111
+ {account ? <><p role="status">Signed in as {account}</p><Button onClick={() => setAccount(null)}>Sign out</Button></> :
112
+ <><p className="text-sm text-basalt-muted-foreground">Local sign-in demo. Use password demo-pass.</p>
113
+ <LoginForm authenticate={async ({ password }) => { if (password !== "demo-pass") throw new Error("Incorrect demo password."); }} onSuccess={setAccount} /></>}
114
+ </div>
115
+ </main></ThemeProvider>;
116
+ }
117
+ ```
118
+
119
+ ## ResourceList
120
+
121
+ Search, an error with retry, formatted status cells, and a confirmation flow use page-owned state. The first local deletion fails so the retry path can be tested. For remote pagination use the existing DataTable manual-state adapter.
122
+
123
+ ```tsx compile:recipe-resources
124
+ import { Button } from "@nocoo/basalt/components/button";
125
+ import { DataTable, type DataTableColumn } from "@nocoo/basalt/components/data-table";
126
+ import { DeleteResource } from "@nocoo/basalt/components/delete-resource";
127
+ import { Input } from "@nocoo/basalt/components/input";
128
+ import { ResourceList } from "@nocoo/basalt/components/resource-list";
129
+ import { TagBadge } from "@nocoo/basalt/components/tag-badge";
130
+ import { ThemeProvider } from "@nocoo/basalt/providers/theme";
131
+ import { useRef, useState } from "react";
132
+
133
+ type Project = { id: string; name: string; status: "Active" | "Paused" };
134
+ const initial: Project[] = [
135
+ { id: "atlas", name: "Atlas", status: "Active" }, { id: "boreal", name: "Boreal", status: "Paused" },
136
+ { id: "cedar", name: "Cedar", status: "Active" },
137
+ ];
138
+ export default function ResourcesRecipe() {
139
+ const [rows, setRows] = useState(initial);
140
+ const [query, setQuery] = useState("");
141
+ const [error, setError] = useState(true);
142
+ const [message, setMessage] = useState("");
143
+ const failDeletion = useRef(true);
144
+ const filtered = rows.filter((row) => row.name.toLowerCase().includes(query.toLowerCase()));
145
+ const columns: DataTableColumn<Project>[] = [
146
+ { id: "name", header: "Project", accessor: (row) => row.name },
147
+ { id: "status", header: "Status", accessor: (row) => <TagBadge name={row.status} color={row.status === "Active" ? "success" : "warning"} /> },
148
+ { id: "actions", header: "Actions", sortable: false, accessor: (row) => <DeleteResource name={row.name} onDelete={async () => {
149
+ if (failDeletion.current) { failDeletion.current = false; throw new Error("Temporary conflict. Retry this deletion."); }
150
+ setRows((current) => current.filter((item) => item.id !== row.id)); setMessage("Deleted " + row.name);
151
+ }} /> },
152
+ ];
153
+ return <ThemeProvider><main style={{ padding: 24, maxWidth: 960, margin: "auto" }}>
154
+ <ResourceList title="Projects" description="A complete resource-page composition with local service adapters." data={[]}
155
+ toolbar={<div className="flex flex-wrap gap-3"><Input aria-label="Search projects" placeholder="Search projects…" value={query} onChange={(event) => setQuery(event.target.value)} /><Button variant="outline" onClick={() => { setRows(initial); setQuery(""); setMessage(""); }}>Reset projects</Button></div>}
156
+ footer={<p role="status" className="text-sm text-basalt-muted-foreground">{message || (filtered.length + " projects")}</p>}>
157
+ <DataTable aria-label="Projects" data={filtered} columns={columns} error={error ? "The project service is unavailable." : undefined} onRetry={() => setError(false)} />
158
+ </ResourceList>
159
+ </main></ThemeProvider>;
160
+ }
161
+ ```
package/ai/USAGE.md ADDED
@@ -0,0 +1,99 @@
1
+ # Basalt AI & Machine Usage Guide
2
+
3
+ This document describes how AI code assistants, automated agents, and developers can consume `@nocoo/basalt` (v2.1.2).
4
+
5
+ ---
6
+
7
+ ## 1. Machine Registry Entrypoint
8
+
9
+ The complete, machine-readable component registry and API surface is published within the installed npm package at file:
10
+ `node_modules/@nocoo/basalt/ai/registry.json` (relative package path: `ai/registry.json`).
11
+ *(Note: `ai/registry.json` is a published file within the npm package directory, not an imported JavaScript/ESM export subpath.)*
12
+ Document anchors formatted as `ai/registry.json#<slug>` reference specific catalog entries within the `catalogEntries` array by matching the `slug` property (e.g. `ai/registry.json#button` matches the entry where `slug === "button"`).
13
+
14
+ It contains:
15
+ - **122 Exported Modules** (1 root barrel, components, charts, providers)
16
+ - **111 Ready Catalog Entries** with full API definitions
17
+ - **741 Public Symbols** (395 runtime values, 346 TypeScript types)
18
+ - **Detailed Component API**: Props, types, defaults, descriptions, and function callable signatures (including all `toast()` variants)
19
+ - **Exact Peer Dependency Closures**: Identifies optional peers required per subpath (e.g., Recharts)
20
+
21
+ ---
22
+
23
+ ## 2. Reading Original Component Sources From Installed Package
24
+
25
+ Basalt distributes complete TypeScript source code embedded directly inside the published package artifacts:
26
+ - **Compiled Modules**: Full TypeScript source code is embedded in the `sourcesContent` field of individual sourcemaps under `node_modules/@nocoo/basalt/dist/<subpath>.js.map`.
27
+ - **Pure Re-Export Modules**: Modules without an independent sourcemap (such as pure re-export modules) are preserved verbatim with integrity hashes in `node_modules/@nocoo/basalt/ai/sources.json`. The root entrypoint `@nocoo/basalt` still emits full JavaScript exports in `dist/index.js`.
28
+
29
+ Inspect `ai/registry.json` or the component's catalog metadata to identify the exact package read location and expected SHA-256 integrity hash for each module. Do not attempt to read from unbundled repository source paths or unreleased remote git tags.
30
+
31
+ ---
32
+
33
+ ## 3. Component Import Conventions
34
+
35
+ ### Root Import vs. Granular Subpaths
36
+ Basalt supports both lightweight root imports and tree-shakeable granular subpaths:
37
+
38
+ ```tsx compile:usage-import-conventions
39
+ // Root import for standard components
40
+ import { Button, Input, LayerCard, Dialog, Toaster, toast } from "@nocoo/basalt";
41
+
42
+ // Granular subpaths for visualization, calendar pickers, and tables
43
+ import { DatePicker } from "@nocoo/basalt/components/date-picker";
44
+ import { DataTable } from "@nocoo/basalt/components/data-table";
45
+ import { Sparkline } from "@nocoo/basalt/charts/sparkline";
46
+
47
+ export function ImportConventionsDemo() {
48
+ return (
49
+ <div>
50
+ <Button variant="default">Root Button</Button>
51
+ <DatePicker aria-label="Target Date" />
52
+ </div>
53
+ );
54
+ }
55
+ ```
56
+
57
+ ### Optional Peer Dependency Rules
58
+ - **Recharts**: Required ONLY when using chart subpaths (`@nocoo/basalt/charts/*`). Root imports and basic UI do not import Recharts.
59
+ - **DatePicker & DataTable**: Built-in implementations operate standalone without requiring `react-day-picker` or `@tanstack/react-table`.
60
+
61
+ ---
62
+
63
+ ## 4. Styling Setup
64
+
65
+ ### Tailwind CSS v4 Contract
66
+ ```css
67
+ @import "@nocoo/basalt/styles/tailwind";
68
+ @import "tailwindcss";
69
+ ```
70
+
71
+ ### Standalone CSS Contract (No Tailwind)
72
+ ```ts
73
+ import "@nocoo/basalt/styles/standalone";
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 5. Toast Notification Architecture
79
+
80
+ Mount a single `<Toaster />` globally at the root of your application (without an id):
81
+ ```tsx compile:usage-toast-architecture
82
+ import type React from "react";
83
+ import { Toaster, toast, Button } from "@nocoo/basalt";
84
+
85
+ export function App() {
86
+ return (
87
+ <>
88
+ <Toaster />
89
+ <Button onClick={() => toast.success("Project saved")}>Save</Button>
90
+ </>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ## 6. Application recipes and palette preferences
96
+
97
+ Read [RECIPES.md](RECIPES.md) for complete AppFrame, Login, and Resources modules. Each module is compiled and exercised from the installed tarball in standalone, Tailwind, and Next.js consumers. These recipes keep authentication, routing, data and network requests in the application.
98
+
99
+ Read [INTEGRATION.md#accent-provider](INTEGRATION.md#accent-provider) for the twelve control accents, optional `paletteOverrides`, and the fixed five-color chart cycle matching the classic candy swatches with its existing gray retained. Check [COMPATIBILITY.md](COMPATIBILITY.md) before migrating old color indices or stored IDs. The catalog at https://basaltui.com/palette provides an application-owned editor with localStorage persistence.