basalt-ui 1.23.1 → 1.25.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.
- package/AGENTS.md +11 -6
- package/CHANGELOG.md +21 -0
- package/MIGRATING.md +138 -4
- package/README.md +123 -32
- package/agent/rules/basalt-data.md +104 -12
- package/agent/rules/basalt-query.md +57 -0
- package/agent/skills/basalt-app/SKILL.md +7 -0
- package/dist/cli/index.d.ts +4 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +101 -17
- package/dist/dashboard/empty-state.d.ts +6 -2
- package/dist/dashboard/empty-state.d.ts.map +1 -1
- package/dist/dashboard/empty-state.js +1 -1
- package/dist/dashboard/index.d.ts +1 -0
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +8 -0
- package/dist/dashboard/query-state.d.ts +96 -0
- package/dist/dashboard/query-state.d.ts.map +1 -0
- package/dist/dashboard/query-state.js +123 -0
- package/dist/dashboard/query-state.test.d.ts +2 -0
- package/dist/dashboard/query-state.test.d.ts.map +1 -0
- package/dist/data/data-table.d.ts +125 -8
- package/dist/data/data-table.d.ts.map +1 -1
- package/dist/data/data-table.js +121 -13
- package/dist/data/data-table.test.d.ts +2 -0
- package/dist/data/data-table.test.d.ts.map +1 -0
- package/dist/data/table.d.ts +2 -2
- package/dist/data/table.d.ts.map +1 -1
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +21 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/query/error-message.d.ts +41 -0
- package/dist/query/error-message.d.ts.map +1 -0
- package/dist/query/error-message.js +30 -0
- package/dist/query/error-message.test.d.ts +2 -0
- package/dist/query/error-message.test.d.ts.map +1 -0
- package/dist/query/index.d.ts +1 -19
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/index.js +2 -14
- package/dist/surfaces.d.ts +1 -1
- package/dist/surfaces.js +1 -1
- package/llms.txt +3 -3
- package/package.json +1 -1
- package/src/cli/check-theme.test.ts +34 -0
- package/src/cli/index.ts +222 -44
- package/src/cli/tokens-css.test.ts +73 -6
- package/src/cli/toolchain-wiring.test.ts +146 -0
- package/src/dashboard/empty-state.tsx +9 -3
- package/src/dashboard/index.ts +11 -0
- package/src/dashboard/query-state.test.tsx +152 -0
- package/src/dashboard/query-state.tsx +272 -0
- package/src/data/data-table.test.tsx +349 -0
- package/src/data/data-table.tsx +359 -42
- package/src/data/table.ts +8 -1
- package/src/guard/check-source.test.ts +141 -0
- package/src/guard/index.ts +102 -8
- package/src/index.ts +9 -0
- package/src/query/error-message.test.ts +67 -0
- package/src/query/error-message.ts +70 -0
- package/src/query/index.ts +2 -34
- 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 @@
|
|
|
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 {
|
|
1
|
+
import type { MantineSpacing } from '@mantine/core';
|
|
2
|
+
import type { ColumnDef, ColumnFiltersState, 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. */
|
|
@@ -50,15 +74,43 @@ export type BasaltDataTableProps<T> = {
|
|
|
50
74
|
*/
|
|
51
75
|
columns: ColumnDef<T, any>[];
|
|
52
76
|
/**
|
|
53
|
-
* Enable column sorting via clickable headers.
|
|
77
|
+
* Enable column sorting via clickable headers. Client-side — the rows in `data` are what get
|
|
78
|
+
* reordered.
|
|
79
|
+
*
|
|
80
|
+
* Under `manualPagination` that is one page, so leaving this on without also passing
|
|
81
|
+
* `manualSorting` is a contract violation and throws in dev — see `manualPagination`.
|
|
54
82
|
* @default true
|
|
55
83
|
*/
|
|
56
84
|
enableSorting?: boolean;
|
|
57
|
-
/**
|
|
58
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Hand sorting to the server: the table stops reordering `data` locally and renders it in the
|
|
87
|
+
* order given, while the headers keep toggling `SortingState` and reporting it through
|
|
88
|
+
* `onSortingChange` — which is where you re-request the sorted page.
|
|
89
|
+
*
|
|
90
|
+
* This is the required companion to `manualPagination` whenever sort headers are live; without
|
|
91
|
+
* it a server-paginated table sorts one page and the "of N" bar presents that as a sort of all N.
|
|
92
|
+
* @default false
|
|
93
|
+
* @example
|
|
94
|
+
* <BasaltDataTable
|
|
95
|
+
* data={page.rows}
|
|
96
|
+
* columns={columns}
|
|
97
|
+
* enablePagination
|
|
98
|
+
* manualPagination
|
|
99
|
+
* manualSorting
|
|
100
|
+
* rowCount={page.total}
|
|
101
|
+
* onSortingChange={(s) => refetch({ sort: s[0] })}
|
|
102
|
+
* />
|
|
103
|
+
*/
|
|
104
|
+
manualSorting?: boolean;
|
|
105
|
+
/** Stripe alternate rows. Forwarded to Mantine `Table` — `'odd'`/`'even'` pick the phase. */
|
|
106
|
+
striped?: boolean | 'odd' | 'even';
|
|
59
107
|
/** Highlight hovered rows. Forwarded to Mantine `Table`. */
|
|
60
108
|
highlightOnHover?: boolean;
|
|
61
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* Rendered when no rows are VISIBLE — `data` is empty, or a filter/page matches none of it.
|
|
111
|
+
* Falls back to a simple message when omitted. (Before 1.25.0 this tracked `data.length` alone,
|
|
112
|
+
* so a search matching nothing rendered a blank `<tbody>` with no message at all.)
|
|
113
|
+
*/
|
|
62
114
|
emptyState?: ReactNode;
|
|
63
115
|
/**
|
|
64
116
|
* When true, renders skeleton placeholder rows instead of the empty-state branch.
|
|
@@ -117,6 +169,18 @@ export type BasaltDataTableProps<T> = {
|
|
|
117
169
|
* facets={[{ columnId: 'department', label: 'Department', options: departmentOptions }]}
|
|
118
170
|
*/
|
|
119
171
|
facets?: DataTableFacet[];
|
|
172
|
+
/** Called whenever the faceted column filters change — the seam for server-side faceting. */
|
|
173
|
+
onColumnFiltersChange?: (filters: ColumnFiltersState) => void;
|
|
174
|
+
/**
|
|
175
|
+
* Hand filtering to the server: the table stops narrowing `data` locally and renders every row
|
|
176
|
+
* given, while the search input and facets keep reporting through `onGlobalFilterChange` /
|
|
177
|
+
* `onColumnFiltersChange` — which is where you re-request the filtered page.
|
|
178
|
+
*
|
|
179
|
+
* Required alongside `manualPagination` whenever `enableGlobalFilter` or `facets` is set;
|
|
180
|
+
* without it the controls narrow one page while "of N" keeps counting the whole set.
|
|
181
|
+
* @default false
|
|
182
|
+
*/
|
|
183
|
+
manualFiltering?: boolean;
|
|
120
184
|
/**
|
|
121
185
|
* Right-aligned toolbar slot (e.g. an "Export" button). Renders the toolbar row even when no
|
|
122
186
|
* search input or facets are configured.
|
|
@@ -145,6 +209,21 @@ export type BasaltDataTableProps<T> = {
|
|
|
145
209
|
* Disables local pagination slicing — pass the already-paginated page of `data` plus `rowCount`
|
|
146
210
|
* (and optionally `pageCount`) for server-driven pagination. `onPaginationChange` is where you
|
|
147
211
|
* fetch the next page.
|
|
212
|
+
*
|
|
213
|
+
* **It imposes a contract, enforced at render.** `data` is now one page, but the pagination bar
|
|
214
|
+
* says "Showing 1–25 of 412" — so every OTHER client-side control becomes a claim about 412 rows
|
|
215
|
+
* that it can only make about 25. Each has to be resolved explicitly, because only the call site
|
|
216
|
+
* knows whether the server does the work:
|
|
217
|
+
*
|
|
218
|
+
* - `rowCount` (or `pageCount`) must be given, or "of N" counts the page and the pager collapses
|
|
219
|
+
* to a single page nobody can leave;
|
|
220
|
+
* - sorting must be handed over with `manualSorting`, or switched off with `enableSorting={false}`;
|
|
221
|
+
* - `enableGlobalFilter` / `facets`, if used, must be handed over with `manualFiltering`;
|
|
222
|
+
* - `enablePagination` must be on, or `manualPagination` is inert and the page renders as if it
|
|
223
|
+
* were the whole table.
|
|
224
|
+
*
|
|
225
|
+
* Unresolved, each throws in dev and degrades to the honest render in production (no sort
|
|
226
|
+
* headers, no filter controls, no "of N") — never to the plausible wrong answer.
|
|
148
227
|
* @default false
|
|
149
228
|
* @example
|
|
150
229
|
* <BasaltDataTable
|
|
@@ -173,13 +252,51 @@ export type BasaltDataTableProps<T> = {
|
|
|
173
252
|
enablePinning?: boolean;
|
|
174
253
|
/** Initial column-pinning state — which column ids stick to the left/right edge. */
|
|
175
254
|
initialColumnPinning?: ColumnPinningState;
|
|
255
|
+
/**
|
|
256
|
+
* Caps the scrolling body (px number or CSS length) so a long table cannot blow a card out
|
|
257
|
+
* vertically — the header stays put and the rows scroll under it. Renders Mantine's
|
|
258
|
+
* `Table.ScrollContainer type="native"`, which is the same node the docs sanction as the raw
|
|
259
|
+
* escape for a bespoke table: the blessed lane and the escape hatch produce identical DOM, so
|
|
260
|
+
* adopting one does not contradict the other.
|
|
261
|
+
*
|
|
262
|
+
* `type="native"` is required rather than preferred: `ScrollArea`'s custom viewport is the
|
|
263
|
+
* positioning context a sticky `<thead>` resolves against, so the default `'scrollarea'` type
|
|
264
|
+
* pins the header to the page viewport instead of the table's box.
|
|
265
|
+
*/
|
|
266
|
+
maxHeight?: number | string;
|
|
267
|
+
/**
|
|
268
|
+
* `min-width` below which the body scrolls horizontally. Setting either this or `maxHeight`
|
|
269
|
+
* turns on the scroll container; `maxHeight` alone implies `minWidth: 0`.
|
|
270
|
+
*/
|
|
271
|
+
minWidth?: number | string;
|
|
272
|
+
/** Sticky header row. Pair with `maxHeight` to stick within the table rather than the page. */
|
|
273
|
+
stickyHeader?: boolean;
|
|
274
|
+
/** Offset for a sticky header sitting under a fixed app header (px number or CSS length). */
|
|
275
|
+
stickyHeaderOffset?: number | string;
|
|
276
|
+
/** Vertical cell padding. Forwarded to Mantine `Table`. */
|
|
277
|
+
verticalSpacing?: MantineSpacing;
|
|
278
|
+
/** Horizontal cell padding. Forwarded to Mantine `Table`. */
|
|
279
|
+
horizontalSpacing?: MantineSpacing;
|
|
280
|
+
/** Row separators. Forwarded to Mantine `Table`. @default true (Mantine's own default) */
|
|
281
|
+
withRowBorders?: boolean;
|
|
282
|
+
/**
|
|
283
|
+
* Outer table border. Turn it OFF for a table that already sits inside a `Card`/`ChartCard`,
|
|
284
|
+
* where the card owns the frame and a second one reads as a nested box.
|
|
285
|
+
* @default true
|
|
286
|
+
*/
|
|
287
|
+
withTableBorder?: boolean;
|
|
176
288
|
};
|
|
177
289
|
/**
|
|
178
290
|
* A sortable data table backed by TanStack Table and rendered with Mantine primitives.
|
|
179
291
|
* Generic over `T` — column types are inferred from `ColumnDef<T>`.
|
|
180
292
|
*
|
|
181
|
-
* Sorting is local/client-side (no `any`)
|
|
182
|
-
* is read-only. An `emptyState` node is rendered
|
|
293
|
+
* Sorting is local/client-side by default (no `any`); `manualSorting` hands it to the server.
|
|
294
|
+
* When `enableSorting` is `false` the table is read-only. An `emptyState` node is rendered
|
|
295
|
+
* whenever no rows are visible — empty `data`, or a filter that matches none of it.
|
|
296
|
+
*
|
|
297
|
+
* `manualPagination` imposes a contract on the rest of the props (see its docblock): every
|
|
298
|
+
* client-side control it would turn into a false claim about the unseen rows must be handed to the
|
|
299
|
+
* server or switched off, and an unresolved one throws in dev rather than misreporting.
|
|
183
300
|
*
|
|
184
301
|
* Toolbar (search + facets), pagination, and column pinning are opt-in chrome layered on top —
|
|
185
302
|
* see the corresponding props below. None of them change rendering unless explicitly enabled.
|
|
@@ -194,5 +311,5 @@ export type BasaltDataTableProps<T> = {
|
|
|
194
311
|
* emptyState={<Text c="dimmed">No users found.</Text>}
|
|
195
312
|
* />
|
|
196
313
|
*/
|
|
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;
|
|
314
|
+
export declare function BasaltDataTable<T>({ data, columns, enableSorting, manualSorting, striped, highlightOnHover, emptyState, isLoading, skeletonRows, initialSorting, onSortingChange, enableGlobalFilter, globalFilterPlaceholder, searchIcon, initialGlobalFilter, onGlobalFilterChange, facets, onColumnFiltersChange, manualFiltering, 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
315
|
//# 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":"AA4CA,OAAO,KAAK,EAEV,SAAS,
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/data/data-table.tsx"],"names":[],"mappings":"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"}
|
package/dist/data/data-table.js
CHANGED
|
@@ -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" });
|
|
@@ -74,10 +85,43 @@ function getPinnedCellStyle(table, column) {
|
|
|
74
85
|
boxShadow: isEdge ? `-4px 0 6px -4px ${alpha(VX.ink, 0.18)}` : void 0
|
|
75
86
|
};
|
|
76
87
|
}
|
|
88
|
+
function isDev() {
|
|
89
|
+
return process.env["NODE_ENV"] !== "production";
|
|
90
|
+
}
|
|
91
|
+
const BREACH_REMEDY = {
|
|
92
|
+
inert: "`enablePagination` is not set, so `manualPagination` never reaches the table and the server page renders as if it were the whole set, with no bar to say otherwise. Pass `enablePagination`, or drop `manualPagination`.",
|
|
93
|
+
total: 'neither `rowCount` nor `pageCount` was given, so "of N" counts only the rows on this page and the pager collapses to one page nobody can leave. Pass `rowCount={total}`.',
|
|
94
|
+
sorting: 'client-side sorting is still armed. It reorders only the rows in `data` \u2014 one page \u2014 while the header chevron and "of N" together present it as a sort of all of them. Pass `manualSorting` and sort in the request you make from `onSortingChange`, or `enableSorting={false}`.',
|
|
95
|
+
filtering: 'the search input / facets still filter client-side. They narrow only the rows in `data` \u2014 one page \u2014 while "of N" keeps counting the whole set. Pass `manualFiltering` and filter in the request you make from `onGlobalFilterChange` / `onColumnFiltersChange`, or drop `enableGlobalFilter` / `facets`.'
|
|
96
|
+
};
|
|
97
|
+
function manualPaginationBreaches(config) {
|
|
98
|
+
if (!config.manualPagination) return [];
|
|
99
|
+
if (!config.enablePagination) return ["inert"];
|
|
100
|
+
const breaches = [];
|
|
101
|
+
if (config.rowCount === void 0 && config.pageCount === void 0) breaches.push("total");
|
|
102
|
+
const anyColumnMaySort = config.columns.some((column) => column.enableSorting !== false);
|
|
103
|
+
if (config.enableSorting && anyColumnMaySort && !config.manualSorting) breaches.push("sorting");
|
|
104
|
+
if ((config.enableGlobalFilter || config.hasFacets) && !config.manualFiltering)
|
|
105
|
+
breaches.push("filtering");
|
|
106
|
+
return breaches;
|
|
107
|
+
}
|
|
108
|
+
function manualPaginationMessage(breaches) {
|
|
109
|
+
return "BasaltDataTable: `manualPagination` is set, so `data` is one server page \u2014 but:\n \xB7 " + breaches.map((breach) => BREACH_REMEDY[breach]).join("\n \xB7 ") + "\nEach has to be resolved explicitly: only the call site knows whether the server does the work, so there is no default that is not a guess about the data.";
|
|
110
|
+
}
|
|
111
|
+
const reportedBreaches = /* @__PURE__ */ new Set();
|
|
112
|
+
function enforceManualPaginationContract(breaches) {
|
|
113
|
+
if (breaches.length === 0) return;
|
|
114
|
+
const message = manualPaginationMessage(breaches);
|
|
115
|
+
if (isDev()) throw new Error(message);
|
|
116
|
+
if (reportedBreaches.has(message)) return;
|
|
117
|
+
reportedBreaches.add(message);
|
|
118
|
+
console.error(message);
|
|
119
|
+
}
|
|
77
120
|
function BasaltDataTable({
|
|
78
121
|
data,
|
|
79
122
|
columns,
|
|
80
123
|
enableSorting = true,
|
|
124
|
+
manualSorting = false,
|
|
81
125
|
striped,
|
|
82
126
|
highlightOnHover,
|
|
83
127
|
emptyState,
|
|
@@ -91,6 +135,8 @@ function BasaltDataTable({
|
|
|
91
135
|
initialGlobalFilter,
|
|
92
136
|
onGlobalFilterChange,
|
|
93
137
|
facets,
|
|
138
|
+
onColumnFiltersChange,
|
|
139
|
+
manualFiltering = false,
|
|
94
140
|
toolbarActions,
|
|
95
141
|
enablePagination = false,
|
|
96
142
|
pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,
|
|
@@ -100,7 +146,15 @@ function BasaltDataTable({
|
|
|
100
146
|
rowCount,
|
|
101
147
|
pageCount,
|
|
102
148
|
enablePinning = false,
|
|
103
|
-
initialColumnPinning
|
|
149
|
+
initialColumnPinning,
|
|
150
|
+
maxHeight,
|
|
151
|
+
minWidth,
|
|
152
|
+
stickyHeader,
|
|
153
|
+
stickyHeaderOffset,
|
|
154
|
+
verticalSpacing,
|
|
155
|
+
horizontalSpacing,
|
|
156
|
+
withRowBorders,
|
|
157
|
+
withTableBorder = true
|
|
104
158
|
}) {
|
|
105
159
|
const [sorting, setSorting] = useState(initialSorting ?? []);
|
|
106
160
|
const [globalFilter, setGlobalFilter] = useState(initialGlobalFilter ?? "");
|
|
@@ -129,6 +183,16 @@ function BasaltDataTable({
|
|
|
129
183
|
},
|
|
130
184
|
[onGlobalFilterChange]
|
|
131
185
|
);
|
|
186
|
+
const handleColumnFiltersChange = useCallback(
|
|
187
|
+
(updater) => {
|
|
188
|
+
setColumnFilters((prev) => {
|
|
189
|
+
const next = typeof updater === "function" ? updater(prev) : updater;
|
|
190
|
+
onColumnFiltersChange?.(next);
|
|
191
|
+
return next;
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
[onColumnFiltersChange]
|
|
195
|
+
);
|
|
132
196
|
const handlePaginationChange = useCallback(
|
|
133
197
|
(updater) => {
|
|
134
198
|
setPagination((prev) => {
|
|
@@ -151,6 +215,23 @@ function BasaltDataTable({
|
|
|
151
215
|
return { ...column, filterFn };
|
|
152
216
|
});
|
|
153
217
|
}, [columns, facets]);
|
|
218
|
+
const hasFacets = Boolean(facets && facets.length > 0);
|
|
219
|
+
const breaches = manualPaginationBreaches({
|
|
220
|
+
columns,
|
|
221
|
+
enablePagination,
|
|
222
|
+
manualPagination,
|
|
223
|
+
rowCount,
|
|
224
|
+
pageCount,
|
|
225
|
+
enableSorting,
|
|
226
|
+
manualSorting,
|
|
227
|
+
enableGlobalFilter,
|
|
228
|
+
hasFacets,
|
|
229
|
+
manualFiltering
|
|
230
|
+
});
|
|
231
|
+
enforceManualPaginationContract(breaches);
|
|
232
|
+
const sortingEnabled = enableSorting && !breaches.includes("sorting");
|
|
233
|
+
const filteringEnabled = !breaches.includes("filtering");
|
|
234
|
+
const totalIsAuthoritative = !breaches.includes("total");
|
|
154
235
|
const table = useReactTable({
|
|
155
236
|
data,
|
|
156
237
|
columns: tableColumns,
|
|
@@ -163,35 +244,51 @@ function BasaltDataTable({
|
|
|
163
244
|
},
|
|
164
245
|
onSortingChange: handleSortingChange,
|
|
165
246
|
onGlobalFilterChange: handleGlobalFilterChange,
|
|
166
|
-
onColumnFiltersChange:
|
|
247
|
+
onColumnFiltersChange: handleColumnFiltersChange,
|
|
167
248
|
onColumnPinningChange: setColumnPinning,
|
|
168
249
|
...enablePagination && { onPaginationChange: handlePaginationChange },
|
|
169
250
|
getCoreRowModel: getCoreRowModel(),
|
|
170
251
|
getSortedRowModel: getSortedRowModel(),
|
|
171
252
|
getFilteredRowModel: getFilteredRowModel(),
|
|
253
|
+
// Both row models stay installed and are BYPASSED by these flags, which is TanStack's own
|
|
254
|
+
// seam — so a degraded table renders `data` in the order and completeness the server sent it.
|
|
255
|
+
// Forced only by a BREACH, never by `enableSorting={false}` on its own: that pair still applies
|
|
256
|
+
// an `initialSorting` today (it disables the header control, not the row model) and a table
|
|
257
|
+
// that is not misreporting has no business losing it.
|
|
258
|
+
manualSorting: manualSorting || breaches.includes("sorting"),
|
|
259
|
+
manualFiltering: manualFiltering || breaches.includes("filtering"),
|
|
172
260
|
...enablePagination && {
|
|
173
261
|
getPaginationRowModel: getPaginationRowModel(),
|
|
174
262
|
manualPagination,
|
|
175
263
|
...manualPagination && rowCount !== void 0 && { rowCount },
|
|
176
264
|
...manualPagination && pageCount !== void 0 && { pageCount }
|
|
177
265
|
},
|
|
178
|
-
enableSorting,
|
|
266
|
+
enableSorting: sortingEnabled,
|
|
179
267
|
enableColumnPinning: enablePinning
|
|
180
268
|
});
|
|
181
|
-
const
|
|
269
|
+
const showSearch = enableGlobalFilter && filteringEnabled;
|
|
270
|
+
const showFacets = hasFacets && filteringEnabled;
|
|
271
|
+
const showToolbar = showSearch || showFacets || Boolean(toolbarActions);
|
|
182
272
|
const headerGroups = enablePinning ? getOrderedHeaderGroups(table) : table.getHeaderGroups();
|
|
273
|
+
const rows = table.getRowModel().rows;
|
|
183
274
|
const tableNode = /* @__PURE__ */ jsxs(
|
|
184
275
|
Table,
|
|
185
276
|
{
|
|
186
277
|
...striped !== void 0 && { striped },
|
|
187
278
|
...highlightOnHover !== void 0 && { highlightOnHover },
|
|
188
|
-
|
|
279
|
+
...stickyHeader !== void 0 && { stickyHeader },
|
|
280
|
+
...stickyHeaderOffset !== void 0 && { stickyHeaderOffset },
|
|
281
|
+
...verticalSpacing !== void 0 && { verticalSpacing },
|
|
282
|
+
...horizontalSpacing !== void 0 && { horizontalSpacing },
|
|
283
|
+
...withRowBorders !== void 0 && { withRowBorders },
|
|
284
|
+
withTableBorder,
|
|
189
285
|
children: [
|
|
190
286
|
/* @__PURE__ */ jsx(Table.Thead, { children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx(Table.Tr, { children: headerGroup.headers.map((header) => {
|
|
191
|
-
const canSort =
|
|
287
|
+
const canSort = sortingEnabled && header.column.getCanSort();
|
|
192
288
|
const sorted = header.column.getIsSorted();
|
|
193
289
|
const toggleSorting = header.column.getToggleSortingHandler();
|
|
194
290
|
const pinnedStyle = enablePinning ? getPinnedCellStyle(table, header.column) : void 0;
|
|
291
|
+
const align = resolveAlign(header.column);
|
|
195
292
|
return /* @__PURE__ */ jsxs(
|
|
196
293
|
Table.Th,
|
|
197
294
|
{
|
|
@@ -205,6 +302,7 @@ function BasaltDataTable({
|
|
|
205
302
|
"aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
|
|
206
303
|
style: {
|
|
207
304
|
...canSort ? { cursor: "pointer", userSelect: "none" } : void 0,
|
|
305
|
+
...align !== void 0 && { textAlign: align },
|
|
208
306
|
...pinnedStyle
|
|
209
307
|
},
|
|
210
308
|
children: [
|
|
@@ -215,7 +313,7 @@ function BasaltDataTable({
|
|
|
215
313
|
header.id
|
|
216
314
|
);
|
|
217
315
|
}) }, headerGroup.id)) }),
|
|
218
|
-
/* @__PURE__ */ jsx(Table.Tbody, { children: isLoading ? Array.from({ length: skeletonRows }, (_, rowIndex) => /* @__PURE__ */ jsx(Table.Tr, { children: columns.map((_2, colIndex) => /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Skeleton, { height: 16, radius: "sm" }) }, `skeleton-${rowIndex}-${colIndex}`)) }, `skeleton-${rowIndex}`)) :
|
|
316
|
+
/* @__PURE__ */ jsx(Table.Tbody, { children: isLoading ? Array.from({ length: skeletonRows }, (_, rowIndex) => /* @__PURE__ */ jsx(Table.Tr, { children: columns.map((_2, colIndex) => /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Skeleton, { height: 16, radius: "sm" }) }, `skeleton-${rowIndex}-${colIndex}`)) }, `skeleton-${rowIndex}`)) : rows.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: columns.length, children: emptyState ?? /* @__PURE__ */ jsx(Text, { c: "dimmed", ta: "center", size: "sm", py: "sm", children: "No data to display." }) }) }) : rows.map((row) => {
|
|
219
317
|
const cells = enablePinning ? [
|
|
220
318
|
...row.getLeftVisibleCells(),
|
|
221
319
|
...row.getCenterVisibleCells(),
|
|
@@ -223,11 +321,13 @@ function BasaltDataTable({
|
|
|
223
321
|
] : row.getVisibleCells();
|
|
224
322
|
return /* @__PURE__ */ jsx(Table.Tr, { children: cells.map((cell) => {
|
|
225
323
|
const pinnedStyle = enablePinning ? getPinnedCellStyle(table, cell.column) : void 0;
|
|
324
|
+
const align = resolveAlign(cell.column);
|
|
226
325
|
return /* @__PURE__ */ jsx(
|
|
227
326
|
Table.Td,
|
|
228
327
|
{
|
|
229
328
|
style: {
|
|
230
|
-
...typeof cell.getValue() === "number" ? NUMERIC_CELL_STYLE : void 0,
|
|
329
|
+
...typeof cell.getValue() === "number" && cell.column.columnDef.meta?.numeral !== false ? NUMERIC_CELL_STYLE : void 0,
|
|
330
|
+
...align !== void 0 && { textAlign: align },
|
|
231
331
|
...pinnedStyle
|
|
232
332
|
},
|
|
233
333
|
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
@@ -239,6 +339,7 @@ function BasaltDataTable({
|
|
|
239
339
|
]
|
|
240
340
|
}
|
|
241
341
|
);
|
|
342
|
+
const scrolls = maxHeight !== void 0 || minWidth !== void 0;
|
|
242
343
|
const paginationState = table.getState().pagination;
|
|
243
344
|
const total = table.getRowCount();
|
|
244
345
|
const rangeStart = total === 0 ? 0 : paginationState.pageIndex * paginationState.pageSize + 1;
|
|
@@ -246,7 +347,7 @@ function BasaltDataTable({
|
|
|
246
347
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
247
348
|
showToolbar && /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-end", wrap: "wrap", gap: "xs", mb: "xs", children: [
|
|
248
349
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "wrap", align: "flex-end", children: [
|
|
249
|
-
|
|
350
|
+
showSearch && /* @__PURE__ */ jsx(
|
|
250
351
|
TextInput,
|
|
251
352
|
{
|
|
252
353
|
size: "xs",
|
|
@@ -258,7 +359,7 @@ function BasaltDataTable({
|
|
|
258
359
|
w: 220
|
|
259
360
|
}
|
|
260
361
|
),
|
|
261
|
-
facets?.map((facet) => {
|
|
362
|
+
showFacets && facets?.map((facet) => {
|
|
262
363
|
const column = table.getColumn(facet.columnId);
|
|
263
364
|
if (!column) return null;
|
|
264
365
|
if (facet.multiple) {
|
|
@@ -297,15 +398,22 @@ function BasaltDataTable({
|
|
|
297
398
|
] }),
|
|
298
399
|
toolbarActions
|
|
299
400
|
] }),
|
|
300
|
-
|
|
401
|
+
scrolls ? /* @__PURE__ */ jsx(
|
|
402
|
+
Table.ScrollContainer,
|
|
403
|
+
{
|
|
404
|
+
type: "native",
|
|
405
|
+
minWidth: minWidth ?? 0,
|
|
406
|
+
...maxHeight !== void 0 && { maxHeight },
|
|
407
|
+
children: tableNode
|
|
408
|
+
}
|
|
409
|
+
) : enablePinning ? /* @__PURE__ */ jsx(Box, { style: { overflowX: "auto" }, children: tableNode }) : tableNode,
|
|
301
410
|
enablePagination && /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "xs", wrap: "wrap", gap: "xs", align: "center", children: [
|
|
302
411
|
/* @__PURE__ */ jsxs(Text, { style: RANGE_LABEL_STYLE, children: [
|
|
303
412
|
"Showing ",
|
|
304
413
|
rangeStart,
|
|
305
414
|
"\u2013",
|
|
306
415
|
rangeEnd,
|
|
307
|
-
|
|
308
|
-
total
|
|
416
|
+
totalIsAuthoritative ? ` of ${total}` : ""
|
|
309
417
|
] }),
|
|
310
418
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", children: [
|
|
311
419
|
/* @__PURE__ */ jsx(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.test.d.ts","sourceRoot":"","sources":["../../src/data/data-table.test.tsx"],"names":[],"mappings":""}
|
package/dist/data/table.d.ts
CHANGED
|
@@ -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';
|
|
23
|
-
export { createColumnHelper, useReactTable, flexRender, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel, type ColumnDef, type SortingState, type ColumnHelper, type PaginationState, type ColumnPinningState, } from '@tanstack/react-table';
|
|
22
|
+
export type { BasaltDataTableProps, DataTableAlign, DataTableFacet, DataTableFacetOption, } from './data-table.js';
|
|
23
|
+
export { createColumnHelper, useReactTable, flexRender, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel, type ColumnDef, type SortingState, type ColumnHelper, type PaginationState, type ColumnPinningState, type ColumnFiltersState, } from '@tanstack/react-table';
|
|
24
24
|
//# sourceMappingURL=table.d.ts.map
|
package/dist/data/table.d.ts.map
CHANGED
|
@@ -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,
|
|
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,EAEvB,KAAK,kBAAkB,GACxB,MAAM,uBAAuB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guard/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE7E,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guard/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE7E,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,CAAA;AAggB9D,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,EAAE,WAoBlC,CAAA;AAkKD,sGAAsG;AACtG,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,UAAU,CAAA;CAC7C,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,WAAW,EAChB,eAAe,EAAE,SAAS,MAAM,EAAE,GACjC,sBAAsB,EAAE,CAc1B;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAkB9C,CAAA;AAgeF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,gGACwD,CAAA;AA8F1F;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,SAAS,CAqB5D,CAAA;AA2NF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;gCA0BL,WAAW;;;;;;;gCAcX,WAAW;;;;;gCAMX,WAAW;;;;;;;gCAaX,WAAW;;;;;;;gCAQX,WAAW;;;;;;gCAOX,WAAW;;;;;;;gCASX,WAAW;;;;;;gCAOX,WAAW;;;;;;;gCAaX,WAAW;;;;;;gCAMX,WAAW;;;;;;;gCAaX,WAAW;;;;;;;gCAUX,WAAW;;;;;;;gCAUX,WAAW;;;;;;;gCASX,WAAW;;;;;;;gCASX,WAAW;;;;;;;gCAUX,WAAW;;;;;;;;;;;;gCAgBX,WAAW;;;;;;gCAOX,WAAW;;;;;;;gCASX,WAAW;;;;;;;;;CAWmB,CAAA;AAEjD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAEvD;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBvD;AAUD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,EAAE,CA0YtF;AAID;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAA;IACzC,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC,oGAAoG;IACpG,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,qGAAqG;IACrG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,iCAAiC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,WAAW,GACf,mBAAmB,EAAE,CAuBvB;AAED,kGAAkG;AAClG,eAAO,MAAM,uBAAuB,6BAA6B,CAAA;AAEjE;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAM9F"}
|