basalt-ui 1.23.1 → 1.24.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 (63) hide show
  1. package/AGENTS.md +11 -6
  2. package/CHANGELOG.md +14 -0
  3. package/MIGRATING.md +138 -4
  4. package/README.md +123 -32
  5. package/agent/rules/basalt-data.md +45 -13
  6. package/agent/rules/basalt-query.md +57 -0
  7. package/agent/skills/basalt-app/SKILL.md +7 -0
  8. package/dist/cli/index.d.ts +4 -2
  9. package/dist/cli/index.d.ts.map +1 -1
  10. package/dist/cli/index.js +101 -17
  11. package/dist/dashboard/empty-state.d.ts +6 -2
  12. package/dist/dashboard/empty-state.d.ts.map +1 -1
  13. package/dist/dashboard/empty-state.js +1 -1
  14. package/dist/dashboard/index.d.ts +1 -0
  15. package/dist/dashboard/index.d.ts.map +1 -1
  16. package/dist/dashboard/index.js +8 -0
  17. package/dist/dashboard/query-state.d.ts +96 -0
  18. package/dist/dashboard/query-state.d.ts.map +1 -0
  19. package/dist/dashboard/query-state.js +123 -0
  20. package/dist/dashboard/query-state.test.d.ts +2 -0
  21. package/dist/dashboard/query-state.test.d.ts.map +1 -0
  22. package/dist/data/data-table.d.ts +61 -4
  23. package/dist/data/data-table.d.ts.map +1 -1
  24. package/dist/data/data-table.js +41 -4
  25. package/dist/data/data-table.test.d.ts +2 -0
  26. package/dist/data/data-table.test.d.ts.map +1 -0
  27. package/dist/data/table.d.ts +1 -1
  28. package/dist/data/table.d.ts.map +1 -1
  29. package/dist/guard/index.d.ts.map +1 -1
  30. package/dist/guard/index.js +21 -6
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +7 -1
  34. package/dist/query/error-message.d.ts +41 -0
  35. package/dist/query/error-message.d.ts.map +1 -0
  36. package/dist/query/error-message.js +30 -0
  37. package/dist/query/error-message.test.d.ts +2 -0
  38. package/dist/query/error-message.test.d.ts.map +1 -0
  39. package/dist/query/index.d.ts +1 -19
  40. package/dist/query/index.d.ts.map +1 -1
  41. package/dist/query/index.js +2 -14
  42. package/dist/surfaces.d.ts +1 -1
  43. package/dist/surfaces.js +1 -1
  44. package/llms.txt +3 -3
  45. package/package.json +1 -1
  46. package/src/cli/check-theme.test.ts +34 -0
  47. package/src/cli/index.ts +222 -44
  48. package/src/cli/tokens-css.test.ts +73 -6
  49. package/src/cli/toolchain-wiring.test.ts +146 -0
  50. package/src/dashboard/empty-state.tsx +9 -3
  51. package/src/dashboard/index.ts +11 -0
  52. package/src/dashboard/query-state.test.tsx +152 -0
  53. package/src/dashboard/query-state.tsx +272 -0
  54. package/src/data/data-table.test.tsx +158 -0
  55. package/src/data/data-table.tsx +123 -5
  56. package/src/data/table.ts +6 -1
  57. package/src/guard/check-source.test.ts +141 -0
  58. package/src/guard/index.ts +102 -8
  59. package/src/index.ts +9 -0
  60. package/src/query/error-message.test.ts +67 -0
  61. package/src/query/error-message.ts +70 -0
  62. package/src/query/index.ts +2 -34
  63. package/src/surfaces.ts +1 -1
@@ -1,5 +1,29 @@
1
- import type { ColumnDef, ColumnPinningState, PaginationState, SortingState } from '@tanstack/react-table';
1
+ import type { MantineSpacing } from '@mantine/core';
2
+ import type { ColumnDef, ColumnPinningState, PaginationState, RowData, SortingState } from '@tanstack/react-table';
2
3
  import type { ReactNode } from 'react';
4
+ /** Horizontal alignment of a column's header AND its cells. */
5
+ export type DataTableAlign = 'left' | 'center' | 'right';
6
+ /**
7
+ * Alignment lives on the column def's `meta`, not on a parallel prop array, so it travels with the
8
+ * column it describes and survives reordering.
9
+ *
10
+ * Declared as a module augmentation of TanStack's own `ColumnMeta` so `meta: { aling: 'right' }` is
11
+ * a TYPE error (excess-property check on the object literal) rather than a silently ignored key —
12
+ * and a wrong VALUE (`'end'`, `'centre'`) throws at render. A misspelled alignment that quietly
13
+ * left-aligns a money column is the class of defect that looks correct in review.
14
+ */
15
+ declare module '@tanstack/react-table' {
16
+ interface ColumnMeta<TData extends RowData, TValue> {
17
+ align?: DataTableAlign;
18
+ /**
19
+ * Opt OUT of the automatic mono-numeral cell style. The table applies it whenever the cell's
20
+ * raw value is a number — which is right for a plain figure and wrong for a numeric accessor
21
+ * whose `cell` renders its own chrome (a coloured `Text`, a `Badge`, a sparkline), because the
22
+ * `<td>`'s mono font then overrides what the cell asked for.
23
+ */
24
+ numeral?: boolean;
25
+ }
26
+ }
3
27
  /** A single selectable option inside a {@link DataTableFacet}'s Select/MultiSelect. */
4
28
  export type DataTableFacetOption = {
5
29
  /** The raw filter value, compared against the column's stringified cell value. */
@@ -54,8 +78,8 @@ export type BasaltDataTableProps<T> = {
54
78
  * @default true
55
79
  */
56
80
  enableSorting?: boolean;
57
- /** Stripe alternate rows. Forwarded to Mantine `Table`. */
58
- striped?: boolean;
81
+ /** Stripe alternate rows. Forwarded to Mantine `Table` — `'odd'`/`'even'` pick the phase. */
82
+ striped?: boolean | 'odd' | 'even';
59
83
  /** Highlight hovered rows. Forwarded to Mantine `Table`. */
60
84
  highlightOnHover?: boolean;
61
85
  /** Rendered when `data` is empty. Falls back to a simple message when omitted. */
@@ -173,6 +197,39 @@ export type BasaltDataTableProps<T> = {
173
197
  enablePinning?: boolean;
174
198
  /** Initial column-pinning state — which column ids stick to the left/right edge. */
175
199
  initialColumnPinning?: ColumnPinningState;
200
+ /**
201
+ * Caps the scrolling body (px number or CSS length) so a long table cannot blow a card out
202
+ * vertically — the header stays put and the rows scroll under it. Renders Mantine's
203
+ * `Table.ScrollContainer type="native"`, which is the same node the docs sanction as the raw
204
+ * escape for a bespoke table: the blessed lane and the escape hatch produce identical DOM, so
205
+ * adopting one does not contradict the other.
206
+ *
207
+ * `type="native"` is required rather than preferred: `ScrollArea`'s custom viewport is the
208
+ * positioning context a sticky `<thead>` resolves against, so the default `'scrollarea'` type
209
+ * pins the header to the page viewport instead of the table's box.
210
+ */
211
+ maxHeight?: number | string;
212
+ /**
213
+ * `min-width` below which the body scrolls horizontally. Setting either this or `maxHeight`
214
+ * turns on the scroll container; `maxHeight` alone implies `minWidth: 0`.
215
+ */
216
+ minWidth?: number | string;
217
+ /** Sticky header row. Pair with `maxHeight` to stick within the table rather than the page. */
218
+ stickyHeader?: boolean;
219
+ /** Offset for a sticky header sitting under a fixed app header (px number or CSS length). */
220
+ stickyHeaderOffset?: number | string;
221
+ /** Vertical cell padding. Forwarded to Mantine `Table`. */
222
+ verticalSpacing?: MantineSpacing;
223
+ /** Horizontal cell padding. Forwarded to Mantine `Table`. */
224
+ horizontalSpacing?: MantineSpacing;
225
+ /** Row separators. Forwarded to Mantine `Table`. @default true (Mantine's own default) */
226
+ withRowBorders?: boolean;
227
+ /**
228
+ * Outer table border. Turn it OFF for a table that already sits inside a `Card`/`ChartCard`,
229
+ * where the card owns the frame and a second one reads as a nested box.
230
+ * @default true
231
+ */
232
+ withTableBorder?: boolean;
176
233
  };
177
234
  /**
178
235
  * A sortable data table backed by TanStack Table and rendered with Mantine primitives.
@@ -194,5 +251,5 @@ export type BasaltDataTableProps<T> = {
194
251
  * emptyState={<Text c="dimmed">No users found.</Text>}
195
252
  * />
196
253
  */
197
- export declare function BasaltDataTable<T>({ data, columns, enableSorting, striped, highlightOnHover, emptyState, isLoading, skeletonRows, initialSorting, onSortingChange, enableGlobalFilter, globalFilterPlaceholder, searchIcon, initialGlobalFilter, onGlobalFilterChange, facets, toolbarActions, enablePagination, pageSizeOptions, initialPagination, onPaginationChange, manualPagination, rowCount, pageCount, enablePinning, initialColumnPinning, }: BasaltDataTableProps<T>): import("react").JSX.Element;
254
+ export declare function BasaltDataTable<T>({ data, columns, enableSorting, striped, highlightOnHover, emptyState, isLoading, skeletonRows, initialSorting, onSortingChange, enableGlobalFilter, globalFilterPlaceholder, searchIcon, initialGlobalFilter, onGlobalFilterChange, facets, toolbarActions, enablePagination, pageSizeOptions, initialPagination, onPaginationChange, manualPagination, rowCount, pageCount, enablePinning, initialColumnPinning, maxHeight, minWidth, stickyHeader, stickyHeaderOffset, verticalSpacing, horizontalSpacing, withRowBorders, withTableBorder, }: BasaltDataTableProps<T>): import("react").JSX.Element;
198
255
  //# sourceMappingURL=data-table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/data/data-table.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/data/data-table.tsx"],"names":[],"mappings":"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"}
@@ -20,6 +20,17 @@ import {
20
20
  } from "@tanstack/react-table";
21
21
  import { useCallback, useMemo, useState } from "react";
22
22
  import { alpha, VX } from "../tokens/index.js";
23
+ const ALIGNMENTS = /* @__PURE__ */ new Set(["left", "center", "right"]);
24
+ function resolveAlign(column) {
25
+ const align = column.columnDef.meta?.align;
26
+ if (align === void 0) return void 0;
27
+ if (!ALIGNMENTS.has(align)) {
28
+ throw new Error(
29
+ `BasaltDataTable: column "${column.id}" has meta.align=${JSON.stringify(align)} \u2014 expected 'left' | 'center' | 'right'.`
30
+ );
31
+ }
32
+ return align;
33
+ }
23
34
  function SortIndicator({ direction }) {
24
35
  if (!direction) return null;
25
36
  return /* @__PURE__ */ jsx(Box, { component: "span", ml: 4, "aria-hidden": true, children: direction === "asc" ? "\u2191" : "\u2193" });
@@ -100,7 +111,15 @@ function BasaltDataTable({
100
111
  rowCount,
101
112
  pageCount,
102
113
  enablePinning = false,
103
- initialColumnPinning
114
+ initialColumnPinning,
115
+ maxHeight,
116
+ minWidth,
117
+ stickyHeader,
118
+ stickyHeaderOffset,
119
+ verticalSpacing,
120
+ horizontalSpacing,
121
+ withRowBorders,
122
+ withTableBorder = true
104
123
  }) {
105
124
  const [sorting, setSorting] = useState(initialSorting ?? []);
106
125
  const [globalFilter, setGlobalFilter] = useState(initialGlobalFilter ?? "");
@@ -185,13 +204,19 @@ function BasaltDataTable({
185
204
  {
186
205
  ...striped !== void 0 && { striped },
187
206
  ...highlightOnHover !== void 0 && { highlightOnHover },
188
- withTableBorder: true,
207
+ ...stickyHeader !== void 0 && { stickyHeader },
208
+ ...stickyHeaderOffset !== void 0 && { stickyHeaderOffset },
209
+ ...verticalSpacing !== void 0 && { verticalSpacing },
210
+ ...horizontalSpacing !== void 0 && { horizontalSpacing },
211
+ ...withRowBorders !== void 0 && { withRowBorders },
212
+ withTableBorder,
189
213
  children: [
190
214
  /* @__PURE__ */ jsx(Table.Thead, { children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx(Table.Tr, { children: headerGroup.headers.map((header) => {
191
215
  const canSort = enableSorting && header.column.getCanSort();
192
216
  const sorted = header.column.getIsSorted();
193
217
  const toggleSorting = header.column.getToggleSortingHandler();
194
218
  const pinnedStyle = enablePinning ? getPinnedCellStyle(table, header.column) : void 0;
219
+ const align = resolveAlign(header.column);
195
220
  return /* @__PURE__ */ jsxs(
196
221
  Table.Th,
197
222
  {
@@ -205,6 +230,7 @@ function BasaltDataTable({
205
230
  "aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
206
231
  style: {
207
232
  ...canSort ? { cursor: "pointer", userSelect: "none" } : void 0,
233
+ ...align !== void 0 && { textAlign: align },
208
234
  ...pinnedStyle
209
235
  },
210
236
  children: [
@@ -223,11 +249,13 @@ function BasaltDataTable({
223
249
  ] : row.getVisibleCells();
224
250
  return /* @__PURE__ */ jsx(Table.Tr, { children: cells.map((cell) => {
225
251
  const pinnedStyle = enablePinning ? getPinnedCellStyle(table, cell.column) : void 0;
252
+ const align = resolveAlign(cell.column);
226
253
  return /* @__PURE__ */ jsx(
227
254
  Table.Td,
228
255
  {
229
256
  style: {
230
- ...typeof cell.getValue() === "number" ? NUMERIC_CELL_STYLE : void 0,
257
+ ...typeof cell.getValue() === "number" && cell.column.columnDef.meta?.numeral !== false ? NUMERIC_CELL_STYLE : void 0,
258
+ ...align !== void 0 && { textAlign: align },
231
259
  ...pinnedStyle
232
260
  },
233
261
  children: flexRender(cell.column.columnDef.cell, cell.getContext())
@@ -239,6 +267,7 @@ function BasaltDataTable({
239
267
  ]
240
268
  }
241
269
  );
270
+ const scrolls = maxHeight !== void 0 || minWidth !== void 0;
242
271
  const paginationState = table.getState().pagination;
243
272
  const total = table.getRowCount();
244
273
  const rangeStart = total === 0 ? 0 : paginationState.pageIndex * paginationState.pageSize + 1;
@@ -297,7 +326,15 @@ function BasaltDataTable({
297
326
  ] }),
298
327
  toolbarActions
299
328
  ] }),
300
- enablePinning ? /* @__PURE__ */ jsx(Box, { style: { overflowX: "auto" }, children: tableNode }) : tableNode,
329
+ scrolls ? /* @__PURE__ */ jsx(
330
+ Table.ScrollContainer,
331
+ {
332
+ type: "native",
333
+ minWidth: minWidth ?? 0,
334
+ ...maxHeight !== void 0 && { maxHeight },
335
+ children: tableNode
336
+ }
337
+ ) : enablePinning ? /* @__PURE__ */ jsx(Box, { style: { overflowX: "auto" }, children: tableNode }) : tableNode,
301
338
  enablePagination && /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "xs", wrap: "wrap", gap: "xs", align: "center", children: [
302
339
  /* @__PURE__ */ jsxs(Text, { style: RANGE_LABEL_STYLE, children: [
303
340
  "Showing ",
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data-table.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table.test.d.ts","sourceRoot":"","sources":["../../src/data/data-table.test.tsx"],"names":[],"mappings":""}
@@ -19,6 +19,6 @@
19
19
  * <BasaltDataTable data={rows} columns={columns} enableGlobalFilter enablePagination />
20
20
  */
21
21
  export { BasaltDataTable } from './data-table.js';
22
- export type { BasaltDataTableProps, DataTableFacet, DataTableFacetOption } from './data-table.js';
22
+ export type { BasaltDataTableProps, DataTableAlign, DataTableFacet, DataTableFacetOption, } from './data-table.js';
23
23
  export { createColumnHelper, useReactTable, flexRender, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel, type ColumnDef, type SortingState, type ColumnHelper, type PaginationState, type ColumnPinningState, } from '@tanstack/react-table';
24
24
  //# sourceMappingURL=table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/data/table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAS9F,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/data/table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,YAAY,EACV,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,cAAc,CAAA;AASrB,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,uBAAuB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guard/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guard/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- const HEX = /#[0-9a-fA-F]{3,8}\b/g;
1
+ const HEX = /#(?!(?<=&#)\d+;)[0-9a-fA-F]{3,8}\b/g;
2
2
  const FUNC = /\b(?:rgba?|hsla?)\((?!\s*\$\{)/g;
3
3
  const LOCALSTORAGE_THEME = /localStorage\s*\.\s*getItem\s*\(\s*['"]theme['"]\s*\)/g;
4
4
  const RAW_FONT_FAMILY_VAR_ESCAPE = /var\(\s*--/.source;
@@ -272,14 +272,19 @@ function parseAllowAnnotation(rest, scope) {
272
272
  const MAX_CSS_CONTINUATION_LINES = 8;
273
273
  function commentBlockEnd(lines, index, tokenAt, syntax) {
274
274
  const line = lines[index] ?? "";
275
- if (syntax === "ts" && /\/\/\s*$/.test(line.slice(0, tokenAt))) return index;
276
- const closer = syntax === "markup" ? "-->" : "*/";
275
+ const markup = syntax === "markup" || syntax === "sfc" && opensMarkupComment(line, tokenAt);
276
+ if (!markup && syntax !== "css" && /\/\/\s*$/.test(line.slice(0, tokenAt))) return index;
277
+ const closer = markup ? "-->" : "*/";
277
278
  if (line.slice(tokenAt).includes(closer)) return index;
278
279
  for (let ahead = index + 1; ahead < lines.length; ahead++) {
279
280
  if ((lines[ahead] ?? "").includes(closer)) return ahead;
280
281
  }
281
282
  return index;
282
283
  }
284
+ function opensMarkupComment(line, tokenAt) {
285
+ const before = line.slice(0, tokenAt);
286
+ return before.lastIndexOf("<!--") > before.lastIndexOf("/*");
287
+ }
283
288
  const COMMENT_OPENER_BEFORE = /(?:\/\/|\/\*|<!--)\s*$/;
284
289
  const COMMENT_ONLY_LINE = /^\s*(?:\{\s*\/\*|\/\/|\/\*|\*|<!--)/;
285
290
  const JSX_COMMENT_CLOSE = /\*\/\s*\}\s*$/;
@@ -375,8 +380,14 @@ function annotationsCover(annotations, kind) {
375
380
  function guardSyntaxFor(relPath) {
376
381
  if (relPath.endsWith(".css")) return "css";
377
382
  if (/\.(?:html?|webmanifest|json)$/.test(relPath)) return "markup";
383
+ if (/\.(?:astro|vue)$/.test(relPath)) return "sfc";
378
384
  return "ts";
379
385
  }
386
+ function stripGuardComments(text, syntax) {
387
+ if (syntax === "markup") return stripMarkupComments(text);
388
+ if (syntax === "sfc") return stripComments(stripMarkupComments(text), "ts");
389
+ return stripComments(text, syntax);
390
+ }
380
391
  const MARKUP_KINDS = /* @__PURE__ */ new Set(["raw-hex", "raw-color-fn", "raw-font-family"]);
381
392
  function stripMarkupComments(text) {
382
393
  return text.replace(/<!--[\s\S]*?-->/g, (m) => m.replace(/[^\n]/g, " "));
@@ -816,7 +827,7 @@ function checkSource(text, relPath, cfg) {
816
827
  GUARD_RULES["raw-radius"].pattern.flags
817
828
  );
818
829
  const syntax = guardSyntaxFor(relPath);
819
- const codeText = syntax === "markup" ? stripMarkupComments(text) : stripComments(text, syntax);
830
+ const codeText = stripGuardComments(text, syntax);
820
831
  const codeLines = codeText.split("\n");
821
832
  const { waivers, fileScoped, declared } = collectAllowAnnotations(
822
833
  lines,
@@ -934,7 +945,11 @@ function checkSource(text, relPath, cfg) {
934
945
  for (const m of line.matchAll(GUARD_RULES["inline-spacing"].pattern)) {
935
946
  if (syntax === "css" && isSubScaleCssSpacing(line, m.index)) continue;
936
947
  const hasUnit = /^[a-z%]/.test(line.slice(m.index + m[0].length));
937
- if (syntax === "ts" && !hasUnit && !isStyleObjectContext(codeText, lineStarts[i] + m.index, styleIdentifiers))
948
+ if (
949
+ // An SFC's script fence IS TS, so it takes the same gate — without it a unitless
950
+ // `padding: 8` in `.astro`/`.vue` frontmatter reports with no style-object behind it.
951
+ (syntax === "ts" || syntax === "sfc") && !hasUnit && !isStyleObjectContext(codeText, lineStarts[i] + m.index, styleIdentifiers)
952
+ )
938
953
  continue;
939
954
  push("inline-spacing", i + 1, m[0]);
940
955
  }
@@ -1049,7 +1064,7 @@ function checkSource(text, relPath, cfg) {
1049
1064
  function findAllowAnnotations(text, relPath, cfg) {
1050
1065
  const lines = text.split("\n");
1051
1066
  const syntax = guardSyntaxFor(relPath);
1052
- const codeText = syntax === "markup" ? stripMarkupComments(text) : stripComments(text, syntax);
1067
+ const codeText = stripGuardComments(text, syntax);
1053
1068
  const { declared } = collectAllowAnnotations(
1054
1069
  lines,
1055
1070
  codeText.split("\n"),
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export { MOTION_DURATION, MOTION_SPRING, MOTION_EASE_STANDARD } from './motion/i
13
13
  export { BasaltShell, NavCountBadge, AppSidebar, SidebarSearch, type SidebarSearchConfig, SidebarAccount, MobileNav, type MobileNavProps, projectMobileNav, type ProjectMobileNavOptions, MOBILE_MAX_TABS_DEFAULT, MOBILE_MENU_MAX_DEFAULT, MOBILE_MORE_KEY, AppBreadcrumbs, PageHeaderProvider, PageActions, PageActionsOutlet, type SidebarSection, type SidebarItem, type NavAnchor, type NavAnchorProps, type NavMobilePlacement, type NavSectionMobile, type MobileNavConfig, type MobileNavGroup, type MobileNavModel, type MobileNavSlot, type MobileNavSurface, type BasaltShellProps, type BrandConfig, type SettingsMenuItem, type AppSidebarProps, type AccountBadgeTone, type BasaltIdentity, type BasaltRole, type BasaltPlan, type AccountMenuItem, type BasaltAccountState, type BasaltAccountActions, type BasaltAccountProps, } from './shell/index.js';
14
14
  export { type BasaltRegister, type Slot, type Series, type SeriesKey, type AsyncState, assertNever, type StandardSchemaV1, } from './register.js';
15
15
  export { createPersistedState, type PersistedStateOptions, useOnlineStatus, readPersistedValue, } from './state.js';
16
- export { DeltaBadge, type DeltaBadgeProps, StatCard, type StatCardProps, type StatCardTone, EmptyState, type EmptyStateProps, SettingsSection, type SettingsSectionProps, SettingsRow, type SettingsRowProps, DangerZone, type DangerZoneProps, } from './dashboard/index.js';
16
+ export { DeltaBadge, type DeltaBadgeProps, StatCard, type StatCardProps, type StatCardTone, EmptyState, type EmptyStateProps, SettingsSection, type SettingsSectionProps, SettingsRow, type SettingsRowProps, DangerZone, type DangerZoneProps, QueryState, type QueryStateProps, type QueryStateLike, type QueryStateVariant, type QueryEmptyCopy, LoadingState, type LoadingStateProps, ErrorState, type ErrorStateProps, } from './dashboard/index.js';
17
17
  export { ConnectivityProvider, ConnectivityIndicator, useConnectivity } from './connectivity/index.js';
18
18
  export type { ConnectivityStatus, ConnectivitySnapshot, ConnectivityProviderProps, ConnectivityOverride, } from './connectivity/index.js';
19
19
  export type { SurfaceSpec, RuleName, SkillName } from './surfaces.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -35,7 +35,10 @@ import {
35
35
  EmptyState,
36
36
  SettingsSection,
37
37
  SettingsRow,
38
- DangerZone
38
+ DangerZone,
39
+ QueryState,
40
+ LoadingState,
41
+ ErrorState
39
42
  } from "./dashboard/index.js";
40
43
  import { ConnectivityProvider, ConnectivityIndicator, useConnectivity } from "./connectivity/index.js";
41
44
  import {
@@ -68,6 +71,8 @@ export {
68
71
  DangerZone,
69
72
  DeltaBadge,
70
73
  EmptyState,
74
+ ErrorState,
75
+ LoadingState,
71
76
  MOBILE_MAX_TABS_DEFAULT,
72
77
  MOBILE_MENU_MAX_DEFAULT,
73
78
  MOBILE_MORE_KEY,
@@ -79,6 +84,7 @@ export {
79
84
  PageActions,
80
85
  PageActionsOutlet,
81
86
  PageHeaderProvider,
87
+ QueryState,
82
88
  SettingsRow,
83
89
  SettingsSection,
84
90
  SidebarAccount,
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Transport-agnostic error decoding. Deliberately a standalone module with NO
3
+ * `@tanstack/react-query` import — `dashboard/query-state.tsx` renders server messages and must
4
+ * not drag the query peer into the root barrel's graph to do it.
5
+ */
6
+ /**
7
+ * The HTTP status behind a thrown envelope (Eden Treaty's `{ status, value }`, a `Response`-shaped
8
+ * throw), when there is one. Use it to BRANCH — 404 → "not found" copy — rather than to build a
9
+ * message; `toErrorMessage` already folds the status into its text when the body says nothing.
10
+ *
11
+ * @example
12
+ * if (errorStatus(err) === 404) return <EmptyState title="Gone" />
13
+ */
14
+ export declare function errorStatus(err: unknown): number | undefined;
15
+ /**
16
+ * Extract a human-readable message from an unknown thrown value (e.g. the raw Eden envelope
17
+ * thrown by `unwrap`). Removes the 8-line three-branch boilerplate consumers duplicate.
18
+ *
19
+ * Resolution order:
20
+ * 1. `Error` instance → err.message
21
+ * 2. `{ message: string }` → message (Eden / Elysia error shape)
22
+ * 3. `{ value: ... }` → recursively (Eden nested value envelope)
23
+ * 4. plain string → itself
24
+ * 5. anything else → `JSON.stringify`
25
+ *
26
+ * **If that yields nothing a human can read** (`''`, `'{}'`, `'[]'`, `'null'`, `'undefined'`,
27
+ * `'[object Object]'` — the shapes `JSON.stringify` produces for an opaque envelope) the `fallback`
28
+ * is returned instead, with `(HTTP <status>)` appended when the envelope carries one. Without that
29
+ * guard the caller renders a literal `{}` at the user, or — for `toErrorMessage(undefined)` —
30
+ * the actual value `undefined`, since `JSON.stringify(undefined)` is not a string at all.
31
+ *
32
+ * @example
33
+ * try {
34
+ * await unwrap(api.resource.post({ body }))
35
+ * } catch (e) {
36
+ * toast(toErrorMessage(e, 'Could not create share')) // → "slug already in use"
37
+ * // → "Could not create share (HTTP 502)"
38
+ * }
39
+ */
40
+ export declare function toErrorMessage(err: unknown, fallback?: string): string;
41
+ //# sourceMappingURL=error-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-message.d.ts","sourceRoot":"","sources":["../../src/query/error-message.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI5D;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,SAAwB,GAAG,MAAM,CAKrF"}
@@ -0,0 +1,30 @@
1
+ function errorStatus(err) {
2
+ if (err === null || typeof err !== "object") return void 0;
3
+ const status = err.status;
4
+ return typeof status === "number" ? status : void 0;
5
+ }
6
+ const UNUSABLE = /* @__PURE__ */ new Set(["", "{}", "[]", "null", "undefined", "[object Object]"]);
7
+ function decode(err) {
8
+ if (err instanceof Error) return err.message;
9
+ if (typeof err === "string") return err;
10
+ if (typeof err === "object" && err !== null) {
11
+ const obj = err;
12
+ if (typeof obj["message"] === "string") return obj["message"];
13
+ if ("value" in obj) return decode(obj["value"]);
14
+ }
15
+ try {
16
+ return JSON.stringify(err) ?? "";
17
+ } catch {
18
+ return String(err);
19
+ }
20
+ }
21
+ function toErrorMessage(err, fallback = "The request failed.") {
22
+ const message = decode(err).trim();
23
+ if (!UNUSABLE.has(message)) return message;
24
+ const status = errorStatus(err);
25
+ return status === void 0 ? fallback : `${fallback} (HTTP ${status})`;
26
+ }
27
+ export {
28
+ errorStatus,
29
+ toErrorMessage
30
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=error-message.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-message.test.d.ts","sourceRoot":"","sources":["../../src/query/error-message.test.ts"],"names":[],"mappings":""}
@@ -40,25 +40,7 @@ export declare function unwrap<TData>(response: Promise<{
40
40
  data: TData | null;
41
41
  error: unknown;
42
42
  }>): Promise<TData>;
43
- /**
44
- * Extract a human-readable message from an unknown thrown value (e.g. the raw Eden envelope
45
- * thrown by `unwrap`). Removes the 8-line three-branch boilerplate consumers duplicate.
46
- *
47
- * Resolution order:
48
- * 1. `Error` instance → err.message
49
- * 2. `{ message: string }` → message (Eden / Elysia error shape)
50
- * 3. `{ value: ... }` → toErrorMessage(value) recursively (Eden nested value envelope)
51
- * 4. plain string → itself
52
- * 5. anything else → JSON.stringify with safe fallback to String()
53
- *
54
- * @example
55
- * try {
56
- * await unwrap(api.resource.post({ body }))
57
- * } catch (e) {
58
- * toast(toErrorMessage(e))
59
- * }
60
- */
61
- export declare function toErrorMessage(err: unknown): string;
43
+ export { toErrorMessage, errorStatus } from './error-message.js';
62
44
  export { QueryClientProvider, QueryErrorResetBoundary, useQueryErrorResetBoundary, } from '@tanstack/react-query';
63
45
  export { useQuery, useSuspenseQuery, useMutation, useQueryClient, useInfiniteQuery, queryOptions, } from '@tanstack/react-query';
64
46
  export { BasaltQueryDevtools } from './devtools.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/query/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAW9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAQ/E;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAChC,QAAQ,EAAE,OAAO,CAAC;IAAE,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,GACxD,OAAO,CAAC,KAAK,CAAC,CAQhB;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAcnD;AAKD,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,uBAAuB,CAAA;AAI9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/query/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAW9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAQ/E;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAChC,QAAQ,EAAE,OAAO,CAAC;IAAE,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,GACxD,OAAO,CAAC,KAAK,CAAC,CAQhB;AAID,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAK7D,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,uBAAuB,CAAA;AAI9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA"}
@@ -23,20 +23,7 @@ async function unwrap(response) {
23
23
  );
24
24
  return data;
25
25
  }
26
- function toErrorMessage(err) {
27
- if (err instanceof Error) return err.message;
28
- if (typeof err === "string") return err;
29
- if (typeof err === "object" && err !== null) {
30
- const obj = err;
31
- if (typeof obj["message"] === "string") return obj["message"];
32
- if ("value" in obj) return toErrorMessage(obj["value"]);
33
- }
34
- try {
35
- return JSON.stringify(err);
36
- } catch {
37
- return String(err);
38
- }
39
- }
26
+ import { toErrorMessage, errorStatus } from "./error-message.js";
40
27
  import {
41
28
  QueryClientProvider,
42
29
  QueryErrorResetBoundary,
@@ -56,6 +43,7 @@ export {
56
43
  QueryClientProvider,
57
44
  QueryErrorResetBoundary,
58
45
  createBasaltQueryClient,
46
+ errorStatus,
59
47
  queryOptions,
60
48
  toErrorMessage,
61
49
  unwrap,
@@ -131,7 +131,7 @@ export declare const SURFACES: {
131
131
  readonly rule: "mantine";
132
132
  readonly skill: readonly ["basalt-app", "basalt-design"];
133
133
  readonly guardKinds: readonly ["raw-motion-value", "card-with-border", "raw-form-control", "sub-16-input-font", "mantine-shade-index"];
134
- readonly description: "BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)";
134
+ readonly description: "BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone)";
135
135
  readonly optionalPeers: readonly ["react-markdown", "remark-gfm", "rehype-sanitize", "remend", "shiki", "beautiful-mermaid"];
136
136
  readonly forbiddenImports: readonly [];
137
137
  };
package/dist/surfaces.js CHANGED
@@ -29,7 +29,7 @@ const SURFACES = {
29
29
  "sub-16-input-font",
30
30
  "mantine-shade-index"
31
31
  ],
32
- description: "BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)",
32
+ description: "BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone)",
33
33
  optionalPeers: [
34
34
  "react-markdown",
35
35
  "remark-gfm",
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # basalt-ui v1.23.1
1
+ # basalt-ui v1.24.0
2
2
  # Opinionated framework for Mantine-based React apps — theme, app shell, visx charts, toolchain presets
3
3
  #
4
4
  # basalt-ui is an opinionated framework for Mantine-based React apps.
@@ -19,11 +19,11 @@
19
19
  # ./tokens.css subpath. Guide: docs/FRAMEWORK-FREE.md in the repo.
20
20
 
21
21
  Package: basalt-ui
22
- Version: 1.23.1
22
+ Version: 1.24.0
23
23
 
24
24
  ## basalt-ui
25
25
  Import: import { ... } from 'basalt-ui'
26
- Description: BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)
26
+ Description: BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone)
27
27
  Layer: mantine-coupled
28
28
  Rule: basalt-mantine
29
29
  OptionalPeers: react-markdown@^10.1.0, remark-gfm@^4.0.1, rehype-sanitize@^6.0.0, remend@1.3.0, shiki@^4.3.0, beautiful-mermaid@^1.1.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "basalt-ui",
3
- "version": "1.23.1",
3
+ "version": "1.24.0",
4
4
  "description": "Opinionated framework for Mantine-based React apps — theme, app shell, visx charts, toolchain presets",
5
5
  "keywords": [
6
6
  "charts",
@@ -654,6 +654,40 @@ describe('check-theme scans .css', () => {
654
654
  })
655
655
  })
656
656
 
657
+ // Round 9, rollhook: `SCANNABLE_EXT` stopped at `tsx?|css|html?|webmanifest`, so the marketing
658
+ // site's two `.astro` templates — its ENTIRE markup layer — were never opened, and check-theme
659
+ // reported a clean 4-file scan. `.jsx` and `.vue` were missing from the same regex, so a plain-JS
660
+ // or Vue consumer was unguarded end to end.
661
+ describe('check-theme scans the component extensions it was skipping', () => {
662
+ it('flags a raw hex in an .astro template', () => {
663
+ fixtureAt('pages/index.astro', '<style>\n .hero { color: #ff0000; }\n</style>\n')
664
+ const { code, err } = run()
665
+ expect(code).toBe(1)
666
+ expect(err).toContain('raw-hex')
667
+ expect(err).toContain('index.astro')
668
+ })
669
+
670
+ it('flags a raw hex in a .vue single-file component', () => {
671
+ fixtureAt('components/Hero.vue', '<style>\n .hero { color: #ff0000; }\n</style>\n')
672
+ const { code, err } = run()
673
+ expect(code).toBe(1)
674
+ expect(err).toContain('Hero.vue')
675
+ })
676
+
677
+ it('flags a raw inline border in a .jsx component', () => {
678
+ fixtureAt('Card.jsx', `export const C = () => <div style={{ border: '1px solid #ccc' }} />\n`)
679
+ const { code, err } = run()
680
+ expect(code).toBe(1)
681
+ expect(err).toContain('raw-surface')
682
+ expect(err).toContain('Card.jsx')
683
+ })
684
+
685
+ it('stays quiet on a clean .astro file — the extension is scanned, not condemned', () => {
686
+ fixtureAt('pages/index.astro', '<style>\n .hero { color: var(--vx-ink); }\n</style>\n')
687
+ expect(run().code).toBe(0)
688
+ })
689
+ })
690
+
657
691
  describe('check-theme comment skipping', () => {
658
692
  it('does NOT flag a banned element mentioned in a pure line comment', () => {
659
693
  fixtureAt(