basalt-ui 1.23.0 → 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 (81) hide show
  1. package/AGENTS.md +31 -17
  2. package/CHANGELOG.md +23 -0
  3. package/MIGRATING.md +222 -6
  4. package/README.md +159 -49
  5. package/agent/rules/basalt-app.md +8 -2
  6. package/agent/rules/basalt-charts.md +38 -2
  7. package/agent/rules/basalt-content.md +3 -3
  8. package/agent/rules/basalt-data.md +45 -13
  9. package/agent/rules/basalt-mantine.md +4 -4
  10. package/agent/rules/basalt-query.md +57 -0
  11. package/agent/rules/basalt-tokens.md +18 -5
  12. package/agent/skills/basalt-app/SKILL.md +32 -12
  13. package/agent/skills/basalt-charts/SKILL.md +4 -2
  14. package/agent/templates/CLAUDE-block.md.tpl +3 -2
  15. package/dist/charts/kinds/BandStrip.d.ts +20 -6
  16. package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
  17. package/dist/charts/kinds/BandStrip.js +59 -6
  18. package/dist/charts/kinds/MirroredBars.d.ts +4 -2
  19. package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
  20. package/dist/charts/kinds/MirroredBars.js +13 -0
  21. package/dist/cli/index.d.ts +4 -2
  22. package/dist/cli/index.d.ts.map +1 -1
  23. package/dist/cli/index.js +269 -27
  24. package/dist/dashboard/empty-state.d.ts +6 -2
  25. package/dist/dashboard/empty-state.d.ts.map +1 -1
  26. package/dist/dashboard/empty-state.js +1 -1
  27. package/dist/dashboard/index.d.ts +1 -0
  28. package/dist/dashboard/index.d.ts.map +1 -1
  29. package/dist/dashboard/index.js +8 -0
  30. package/dist/dashboard/query-state.d.ts +96 -0
  31. package/dist/dashboard/query-state.d.ts.map +1 -0
  32. package/dist/dashboard/query-state.js +123 -0
  33. package/dist/dashboard/query-state.test.d.ts +2 -0
  34. package/dist/dashboard/query-state.test.d.ts.map +1 -0
  35. package/dist/data/data-table.d.ts +61 -4
  36. package/dist/data/data-table.d.ts.map +1 -1
  37. package/dist/data/data-table.js +41 -4
  38. package/dist/data/data-table.test.d.ts +2 -0
  39. package/dist/data/data-table.test.d.ts.map +1 -0
  40. package/dist/data/table.d.ts +1 -1
  41. package/dist/data/table.d.ts.map +1 -1
  42. package/dist/guard/index.d.ts.map +1 -1
  43. package/dist/guard/index.js +50 -9
  44. package/dist/index.d.ts +1 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +7 -1
  47. package/dist/query/error-message.d.ts +41 -0
  48. package/dist/query/error-message.d.ts.map +1 -0
  49. package/dist/query/error-message.js +30 -0
  50. package/dist/query/error-message.test.d.ts +2 -0
  51. package/dist/query/error-message.test.d.ts.map +1 -0
  52. package/dist/query/index.d.ts +1 -19
  53. package/dist/query/index.d.ts.map +1 -1
  54. package/dist/query/index.js +2 -14
  55. package/dist/surfaces.d.ts +1 -1
  56. package/dist/surfaces.js +1 -1
  57. package/llms.txt +3 -3
  58. package/package.json +1 -1
  59. package/src/charts/kinds/BandStrip.test.tsx +87 -5
  60. package/src/charts/kinds/BandStrip.tsx +105 -12
  61. package/src/charts/kinds/MirroredBars.test.tsx +39 -0
  62. package/src/charts/kinds/MirroredBars.tsx +38 -2
  63. package/src/cli/check-theme.test.ts +34 -0
  64. package/src/cli/help.test.ts +74 -1
  65. package/src/cli/index.ts +496 -41
  66. package/src/cli/tokens-css.test.ts +129 -0
  67. package/src/cli/toolchain-wiring.test.ts +146 -0
  68. package/src/dashboard/empty-state.tsx +9 -3
  69. package/src/dashboard/index.ts +11 -0
  70. package/src/dashboard/query-state.test.tsx +152 -0
  71. package/src/dashboard/query-state.tsx +272 -0
  72. package/src/data/data-table.test.tsx +158 -0
  73. package/src/data/data-table.tsx +123 -5
  74. package/src/data/table.ts +6 -1
  75. package/src/guard/check-source.test.ts +214 -0
  76. package/src/guard/index.ts +169 -15
  77. package/src/index.ts +9 -0
  78. package/src/query/error-message.test.ts +67 -0
  79. package/src/query/error-message.ts +70 -0
  80. package/src/query/index.ts +2 -34
  81. package/src/surfaces.ts +1 -1
@@ -0,0 +1,123 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Alert, Button, Center, Group, Loader, Stack, Text } from "@mantine/core";
3
+ import { toErrorMessage } from "../query/error-message.js";
4
+ import { EmptyState } from "./empty-state.js";
5
+ function LoadingState({
6
+ variant = "page",
7
+ label = "Loading"
8
+ }) {
9
+ const loader = /* @__PURE__ */ jsx(Loader, { size: "sm", "aria-label": label });
10
+ if (variant === "section") return loader;
11
+ return /* @__PURE__ */ jsx(Center, { py: 64, children: loader });
12
+ }
13
+ function ErrorState({
14
+ error,
15
+ title = "Something went wrong",
16
+ fallback = "The request failed.",
17
+ onRetry,
18
+ retrying = false,
19
+ variant = "page",
20
+ action
21
+ }) {
22
+ const alert = /* @__PURE__ */ jsx(Alert, { color: "red", variant: "light", title, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
23
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: toErrorMessage(error, fallback) }),
24
+ (onRetry ?? action) !== void 0 && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
25
+ onRetry && /* @__PURE__ */ jsx(Button, { size: "xs", variant: "default", loading: retrying, onClick: onRetry, children: "Retry" }),
26
+ action
27
+ ] })
28
+ ] }) });
29
+ if (variant === "section") return alert;
30
+ return /* @__PURE__ */ jsx(Stack, { py: "md", children: alert });
31
+ }
32
+ function defaultIsEmpty(data) {
33
+ if (data === null || data === void 0) return true;
34
+ if (Array.isArray(data)) return data.length === 0;
35
+ if (typeof data === "object" && Array.isArray(data.data)) {
36
+ return data.data.length === 0;
37
+ }
38
+ return false;
39
+ }
40
+ const FETCH_STATUSES = /* @__PURE__ */ new Set(["fetching", "paused", "idle"]);
41
+ function assertQueryStateLike(query) {
42
+ const bad = (detail) => {
43
+ throw new Error(
44
+ `QueryState: \`query\` ${detail}. It must carry { data, isError, error, fetchStatus, refetch } \u2014 a TanStack UseQueryResult does; a hand-composed one must spell every field, because a missing branch flag renders a false claim about the data instead of an error.`
45
+ );
46
+ };
47
+ if (query === null || typeof query !== "object")
48
+ bad(`is ${query === null ? "null" : typeof query}`);
49
+ const q = query;
50
+ if (!("data" in q)) bad("has no `data` key");
51
+ if (typeof q["isError"] !== "boolean") bad("has no boolean `isError`");
52
+ if (typeof q["fetchStatus"] !== "string" || !FETCH_STATUSES.has(q["fetchStatus"]))
53
+ bad(`has fetchStatus=${JSON.stringify(q["fetchStatus"])}, not 'fetching' | 'paused' | 'idle'`);
54
+ if (typeof q["refetch"] !== "function") bad("has no `refetch()`");
55
+ }
56
+ function QueryState({
57
+ query,
58
+ children,
59
+ empty,
60
+ isEmpty,
61
+ errorTitle = "Could not load",
62
+ errorFallback = "The request failed.",
63
+ errorAction,
64
+ variant = "page",
65
+ loading
66
+ }) {
67
+ assertQueryStateLike(query);
68
+ const { data, isError, error, fetchStatus } = query;
69
+ const retrying = fetchStatus === "fetching";
70
+ const retry = () => void query.refetch();
71
+ if (isError && data === void 0) {
72
+ return /* @__PURE__ */ jsx(
73
+ ErrorState,
74
+ {
75
+ error,
76
+ title: errorTitle,
77
+ fallback: errorFallback,
78
+ onRetry: retry,
79
+ retrying,
80
+ variant,
81
+ ...errorAction !== void 0 && { action: errorAction }
82
+ }
83
+ );
84
+ }
85
+ if (data === void 0) {
86
+ if (fetchStatus === "idle" && !isError) return empty ? renderEmpty(empty, variant) : null;
87
+ return loading ?? /* @__PURE__ */ jsx(LoadingState, { variant });
88
+ }
89
+ const emptyNow = isEmpty ? isEmpty(data) : defaultIsEmpty(data);
90
+ const body = emptyNow ? empty ? renderEmpty(empty, variant) : null : typeof children === "function" ? children(data) : children;
91
+ if (!isError) return body;
92
+ return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
93
+ /* @__PURE__ */ jsx(
94
+ ErrorState,
95
+ {
96
+ error,
97
+ title: "Showing cached data",
98
+ fallback: "The last refresh failed.",
99
+ onRetry: retry,
100
+ retrying,
101
+ variant: "section"
102
+ }
103
+ ),
104
+ body
105
+ ] });
106
+ }
107
+ function renderEmpty(empty, variant) {
108
+ return /* @__PURE__ */ jsx(
109
+ EmptyState,
110
+ {
111
+ title: empty.title,
112
+ variant,
113
+ ...empty.description !== void 0 && { description: empty.description },
114
+ ...empty.icon !== void 0 && { icon: empty.icon },
115
+ ...empty.action !== void 0 && { action: empty.action }
116
+ }
117
+ );
118
+ }
119
+ export {
120
+ ErrorState,
121
+ LoadingState,
122
+ QueryState
123
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=query-state.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-state.test.d.ts","sourceRoot":"","sources":["../../src/dashboard/query-state.test.tsx"],"names":[],"mappings":""}
@@ -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;
@@ -108,8 +108,28 @@ const RADIUS_PROP_RE = /\bradius=(?:\{[0-9]+\}|"[0-9]+")/g;
108
108
  const MOTION_TRANSITION_NUMERIC = /\btransition\s*=\s*\{\{[^}]*\b(?:duration|stiffness|damping|mass)\s*:\s*-?\d/g;
109
109
  const MOTION_TRANSITION_EASE_ARRAY = /\btransition\s*=\s*\{\{[^}]*\bease\s*:\s*\[/g;
110
110
  const RAW_CHART_LEGEND_ARRAY = /<ChartLegend\b[^>]*?\bitems\s*=\s*\{\s*\[/g;
111
- const CHART_ENTRY_POINT_TAG = /<(?:MultiLine|Bars|BandStrip|Donut|DualPanel|Heatmap|MirroredBars|ZonedLine|StackedArea|LineSparkline|BarSparkline)\b(?:<[^<>]*>)?(?:=>|[^>])*?>/g;
111
+ const CHART_ENTRY_POINT_TAG = /<(MultiLine|Bars|BandStrip|Donut|DualPanel|Heatmap|MirroredBars|ZonedLine|StackedArea|LineSparkline|BarSparkline)\b(?:<[^<>]*>)?(?:=>|[^>])*?>/g;
112
112
  const HAS_ARIA_LABEL_PROP = /\bariaLabel\s*=/;
113
+ const LOCAL_COMPONENT_DEF = /(?:^|[\n;}])\s*(?:export\s+)?(?:default\s+)?(?:async\s+)?(?:function|class|const|let|var)\s+([A-Z]\w*)/g;
114
+ const BASALT_NAMED_IMPORT = /import\s+(?:type\s+)?\{([^}]*)\}\s+from\s+['"]basalt-ui(?:\/[^'"]*)?['"]/g;
115
+ function localComponentNames(codeText) {
116
+ const out = /* @__PURE__ */ new Set();
117
+ for (const m of codeText.matchAll(LOCAL_COMPONENT_DEF)) out.add(m[1]);
118
+ return out;
119
+ }
120
+ function basaltImportedNames(codeText) {
121
+ const out = /* @__PURE__ */ new Set();
122
+ for (const m of codeText.matchAll(BASALT_NAMED_IMPORT)) {
123
+ for (const raw of m[1].split(",")) {
124
+ const spec = raw.trim().replace(/^type\s+/, "");
125
+ if (spec.length === 0) continue;
126
+ const parts = spec.split(/\s+as\s+/);
127
+ const bound = parts[parts.length - 1].trim();
128
+ if (bound.length > 0) out.add(bound);
129
+ }
130
+ }
131
+ return out;
132
+ }
113
133
  const RAW_FORM_CONTROL = /<(?:input|select|textarea)\b/g;
114
134
  const RAW_FORM_CONTROL_TAG = /<(?:input|select|textarea)\b(?:=>|[^>])*?>/g;
115
135
  const STYLES_INPUT_PART = /\bstyles\s*=\s*\{\{\s*input\s*:\s*\{([^}]*)\}/g;
@@ -252,14 +272,19 @@ function parseAllowAnnotation(rest, scope) {
252
272
  const MAX_CSS_CONTINUATION_LINES = 8;
253
273
  function commentBlockEnd(lines, index, tokenAt, syntax) {
254
274
  const line = lines[index] ?? "";
255
- if (syntax === "ts" && /\/\/\s*$/.test(line.slice(0, tokenAt))) return index;
256
- 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 ? "-->" : "*/";
257
278
  if (line.slice(tokenAt).includes(closer)) return index;
258
279
  for (let ahead = index + 1; ahead < lines.length; ahead++) {
259
280
  if ((lines[ahead] ?? "").includes(closer)) return ahead;
260
281
  }
261
282
  return index;
262
283
  }
284
+ function opensMarkupComment(line, tokenAt) {
285
+ const before = line.slice(0, tokenAt);
286
+ return before.lastIndexOf("<!--") > before.lastIndexOf("/*");
287
+ }
263
288
  const COMMENT_OPENER_BEFORE = /(?:\/\/|\/\*|<!--)\s*$/;
264
289
  const COMMENT_ONLY_LINE = /^\s*(?:\{\s*\/\*|\/\/|\/\*|\*|<!--)/;
265
290
  const JSX_COMMENT_CLOSE = /\*\/\s*\}\s*$/;
@@ -355,8 +380,14 @@ function annotationsCover(annotations, kind) {
355
380
  function guardSyntaxFor(relPath) {
356
381
  if (relPath.endsWith(".css")) return "css";
357
382
  if (/\.(?:html?|webmanifest|json)$/.test(relPath)) return "markup";
383
+ if (/\.(?:astro|vue)$/.test(relPath)) return "sfc";
358
384
  return "ts";
359
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
+ }
360
391
  const MARKUP_KINDS = /* @__PURE__ */ new Set(["raw-hex", "raw-color-fn", "raw-font-family"]);
361
392
  function stripMarkupComments(text) {
362
393
  return text.replace(/<!--[\s\S]*?-->/g, (m) => m.replace(/[^\n]/g, " "));
@@ -796,7 +827,7 @@ function checkSource(text, relPath, cfg) {
796
827
  GUARD_RULES["raw-radius"].pattern.flags
797
828
  );
798
829
  const syntax = guardSyntaxFor(relPath);
799
- const codeText = syntax === "markup" ? stripMarkupComments(text) : stripComments(text, syntax);
830
+ const codeText = stripGuardComments(text, syntax);
800
831
  const codeLines = codeText.split("\n");
801
832
  const { waivers, fileScoped, declared } = collectAllowAnnotations(
802
833
  lines,
@@ -914,7 +945,11 @@ function checkSource(text, relPath, cfg) {
914
945
  for (const m of line.matchAll(GUARD_RULES["inline-spacing"].pattern)) {
915
946
  if (syntax === "css" && isSubScaleCssSpacing(line, m.index)) continue;
916
947
  const hasUnit = /^[a-z%]/.test(line.slice(m.index + m[0].length));
917
- 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
+ )
918
953
  continue;
919
954
  push("inline-spacing", i + 1, m[0]);
920
955
  }
@@ -964,15 +999,21 @@ function checkSource(text, relPath, cfg) {
964
999
  });
965
1000
  }
966
1001
  }
967
- if (GUARD_RULES["unframed-chart"].enabled(cfg) && ruleApplies("unframed-chart", relPath)) {
1002
+ const unframedChartRuns = GUARD_RULES["unframed-chart"].enabled(cfg) && ruleApplies("unframed-chart", relPath);
1003
+ const ariaLabelRuns = GUARD_RULES["chart-missing-aria-label"].enabled(cfg) && ruleApplies("chart-missing-aria-label", relPath);
1004
+ const localNames = unframedChartRuns || ariaLabelRuns ? localComponentNames(codeText) : /* @__PURE__ */ new Set();
1005
+ const basaltNames = unframedChartRuns || ariaLabelRuns ? basaltImportedNames(codeText) : /* @__PURE__ */ new Set();
1006
+ const isShippedTag = (tag) => basaltNames.has(tag) || !localNames.has(tag);
1007
+ if (unframedChartRuns && isShippedTag("ChartLegend")) {
968
1008
  for (const m of codeText.matchAll(RAW_CHART_LEGEND_ARRAY)) {
969
1009
  const lineNo = codeText.slice(0, (m.index ?? 0) + m[0].length).split("\n").length;
970
1010
  push("unframed-chart", lineNo, "items={[");
971
1011
  }
972
1012
  }
973
- if (GUARD_RULES["chart-missing-aria-label"].enabled(cfg) && ruleApplies("chart-missing-aria-label", relPath)) {
1013
+ if (ariaLabelRuns) {
974
1014
  for (const m of codeText.matchAll(CHART_ENTRY_POINT_TAG)) {
975
1015
  const tagText = m[0];
1016
+ if (!isShippedTag(m[1])) continue;
976
1017
  if (HAS_ARIA_LABEL_PROP.test(tagText)) continue;
977
1018
  const startLine = codeText.slice(0, m.index ?? 0).split("\n").length;
978
1019
  const endLine = startLine + (tagText.split("\n").length - 1);
@@ -1023,7 +1064,7 @@ function checkSource(text, relPath, cfg) {
1023
1064
  function findAllowAnnotations(text, relPath, cfg) {
1024
1065
  const lines = text.split("\n");
1025
1066
  const syntax = guardSyntaxFor(relPath);
1026
- const codeText = syntax === "markup" ? stripMarkupComments(text) : stripComments(text, syntax);
1067
+ const codeText = stripGuardComments(text, syntax);
1027
1068
  const { declared } = collectAllowAnnotations(
1028
1069
  lines,
1029
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":""}