@krak-stack/registry 0.1.21 → 0.1.23

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.
@@ -1,7 +1,8 @@
1
1
  // ../../src/components/ui/data-table.tsx
2
2
  import { useAtom, useAtomSet } from "@effect/atom-react";
3
- import { Schema as Schema2 } from "effect";
4
- import { Atom } from "effect/unstable/reactivity";
3
+ import { BrowserKeyValueStore } from "@effect/platform-browser";
4
+ import { Schema } from "effect";
5
+ import { AsyncResult, Atom } from "effect/unstable/reactivity";
5
6
  import {
6
7
  ArrowDown,
7
8
  ArrowUp,
@@ -24,8 +25,10 @@ import {
24
25
  import {
25
26
  createContext,
26
27
  isValidElement,
28
+ useCallback as useCallback2,
27
29
  useContext,
28
30
  useLayoutEffect,
31
+ useMemo,
29
32
  useRef as useRef2,
30
33
  useState
31
34
  } from "react";
@@ -1804,125 +1807,14 @@ function VirtualizedCombobox(props) {
1804
1807
  });
1805
1808
  }
1806
1809
 
1807
- // ../../src/lib/query.ts
1808
- import {
1809
- Effect,
1810
- Option,
1811
- Schema,
1812
- SchemaIssue,
1813
- SchemaTransformation
1814
- } from "effect";
1815
- var parseSortParam = (sort) => {
1816
- const id = sort.startsWith("-") ? sort.slice(1) : sort;
1817
- if (!id || id.includes(",") || id.includes(":")) {
1818
- return null;
1819
- }
1820
- return { id, direction: sort.startsWith("-") ? "desc" : "asc" };
1821
- };
1822
- var SortDirection = Schema.Union([
1823
- Schema.Literal("asc"),
1824
- Schema.Literal("desc")
1825
- ]).pipe(Schema.annotate({
1826
- identifier: "SortDirection",
1827
- title: "Sort Direction",
1828
- description: "Sort direction for list query results.",
1829
- examples: ["asc", "desc"]
1830
- }));
1831
- var SortParam = Schema.Struct({
1832
- id: Schema.NonEmptyString,
1833
- direction: SortDirection
1834
- }).pipe(Schema.annotate({
1835
- identifier: "SortParam",
1836
- title: "Sort Parameter",
1837
- description: "Decoded sort parameter with a field id and direction.",
1838
- examples: [{ id: "publicName", direction: "asc" }]
1839
- }));
1840
- var SortParamFromString = Schema.String.pipe(Schema.decodeTo(SortParam, SchemaTransformation.transformOrFail({
1841
- decode: (sort) => {
1842
- const sortParam = parseSortParam(sort);
1843
- if (!sortParam) {
1844
- return Effect.fail(new SchemaIssue.InvalidValue(Option.some(sort), {
1845
- message: 'Expected sort in the format "field" or "-field"'
1846
- }));
1847
- }
1848
- return Effect.succeed(sortParam);
1849
- },
1850
- encode: (sort) => Effect.succeed(sort.direction === "desc" ? `-${sort.id}` : sort.id)
1851
- })), Schema.annotate({
1852
- identifier: "SortParamFromString",
1853
- title: "Sort Parameter From String",
1854
- description: 'URL encoded single sort parameter where descending fields are prefixed with "-".',
1855
- examples: [{ id: "publicName", direction: "asc" }]
1856
- }));
1857
- var SortParamsFromString = Schema.String.pipe(Schema.decodeTo(Schema.Array(SortParam), SchemaTransformation.transformOrFail({
1858
- decode: (sort) => {
1859
- const parts = sort.split(",");
1860
- const sortParams = [];
1861
- for (const part of parts) {
1862
- const sortParam = parseSortParam(part);
1863
- if (!sortParam) {
1864
- return Effect.fail(new SchemaIssue.InvalidValue(Option.some(sort), {
1865
- message: 'Expected sort in the format "field,-otherField"'
1866
- }));
1867
- }
1868
- sortParams.push(sortParam);
1869
- }
1870
- return Effect.succeed(sortParams);
1871
- },
1872
- encode: (sort) => Effect.succeed(sort.map((part) => Schema.encodeSync(SortParamFromString)(part)).join(","))
1873
- })), Schema.annotate({
1874
- identifier: "SortParamsFromString",
1875
- title: "Sort Parameters From String",
1876
- description: 'URL encoded sort parameters where descending fields are prefixed with "-" and multiple fields are comma-separated.',
1877
- examples: [
1878
- [
1879
- { id: "name", direction: "desc" },
1880
- { id: "age", direction: "asc" }
1881
- ]
1882
- ]
1883
- }));
1884
- var SortParamSearch = SortParamsFromString.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transform({
1885
- decode: (sort) => Schema.encodeSync(SortParamsFromString)(sort),
1886
- encode: (sort) => Schema.decodeUnknownSync(SortParamsFromString)(sort)
1887
- })), Schema.annotate({
1888
- identifier: "SortParamSearch",
1889
- title: "Sort Search Parameter",
1890
- description: 'Search parameter sort value normalized to the compact "-field,otherField" URL format.',
1891
- examples: ["-name,age"]
1892
- }));
1893
- var Query = Schema.Struct({
1894
- page: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.withDecodingDefaultKey(Effect.succeed(0))),
1895
- pageSize: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100 })).pipe(Schema.withDecodingDefaultKey(Effect.succeed(10))),
1896
- globalFilter: Schema.optional(Schema.String),
1897
- sort: Schema.optional(SortParamSearch)
1898
- }).annotate({
1899
- identifier: "Query",
1900
- title: "Query",
1901
- description: "Zero-based page request parameters with optional filtering and sorting for list endpoints.",
1902
- examples: [
1903
- {
1904
- page: 0,
1905
- pageSize: 10,
1906
- globalFilter: "housing",
1907
- sort: "-publicName,createdAt"
1908
- }
1909
- ]
1910
- });
1911
- var QueryStandard = Schema.toStandardSchemaV1(Query);
1912
- var PaginationMeta = Schema.Struct({
1913
- page: Schema.Int,
1914
- pageSize: Schema.Int,
1915
- total: Schema.Int,
1916
- pageCount: Schema.Int
1917
- }).pipe(Schema.annotate({
1918
- identifier: "PaginationMeta",
1919
- title: "Pagination Metadata",
1920
- description: "Pagination metadata returned with a paginated list response.",
1921
- examples: [{ page: 0, pageSize: 10, total: 125, pageCount: 13 }]
1922
- }));
1923
-
1924
1810
  // ../../src/components/ui/data-table.tsx
1925
1811
  import { jsx as jsx17, jsxs as jsxs9, Fragment } from "react/jsx-runtime";
1812
+ var DataTablePersistedUiStateSchema = Schema.Struct({
1813
+ columnVisibility: Schema.Record(Schema.String, Schema.Boolean),
1814
+ columnSizing: Schema.Record(Schema.String, Schema.Number),
1815
+ view: Schema.Literals(["table", "gallery"])
1816
+ }).annotate({ identifier: "DataTablePersistedUiState" });
1817
+ var dataTableStorageRuntime = Atom.runtime(BrowserKeyValueStore.layerLocalStorage);
1926
1818
  var messages3 = {
1927
1819
  en: {
1928
1820
  ...paginationMessages("en"),
@@ -1990,10 +1882,11 @@ var dataTableMessages = (overrides) => ({
1990
1882
  var DEFAULT_MIN_WIDTH = 96;
1991
1883
  var DEFAULT_WIDTH = 208;
1992
1884
  var DEFAULT_MAX_WIDTH = 640;
1993
- var DEFAULT_STATE = {
1994
- globalFilter: "",
1995
- sorting: [],
1996
- pagination: { pageIndex: 0, pageSize: 10 },
1885
+ var DEFAULT_QUERY = {
1886
+ page: 0,
1887
+ pageSize: 10
1888
+ };
1889
+ var DEFAULT_UI_STATE = {
1997
1890
  columnVisibility: {},
1998
1891
  columnSizing: {},
1999
1892
  rowSelection: {},
@@ -2001,6 +1894,16 @@ var DEFAULT_STATE = {
2001
1894
  collapsedGroups: {},
2002
1895
  view: "table"
2003
1896
  };
1897
+ var persistedUiFromState = (state) => ({
1898
+ columnVisibility: state.columnVisibility,
1899
+ columnSizing: state.columnSizing,
1900
+ view: state.view
1901
+ });
1902
+ var transientUiFromState = (state) => ({
1903
+ rowSelection: state.rowSelection,
1904
+ grouping: state.grouping,
1905
+ collapsedGroups: state.collapsedGroups
1906
+ });
2004
1907
  var clampWidth = (column, width) => Math.min(column.maxWidth ?? DEFAULT_MAX_WIDTH, Math.max(column.minWidth ?? DEFAULT_MIN_WIDTH, width));
2005
1908
  var normalizeDataTableColumns = (columnDefs, columnSizing = {}) => {
2006
1909
  const ids = new Set;
@@ -2056,9 +1959,9 @@ var sortDataTableRows = (rows, columns, sorting) => {
2056
1959
  continue;
2057
1960
  const leftValue = left.row.values.get(sort.id);
2058
1961
  const rightValue = right.row.values.get(sort.id);
2059
- const comparison = column.colDef.comparator ? column.colDef.comparator(leftValue, rightValue, left.row.data, right.row.data) : Object.is(leftValue, rightValue) ? 0 : leftValue === null || leftValue === undefined ? 1 : rightValue === null || rightValue === undefined ? -1 : Schema2.is(Schema2.Number)(leftValue) && Schema2.is(Schema2.Number)(rightValue) ? leftValue - rightValue : String(leftValue).localeCompare(String(rightValue), undefined, { numeric: true, sensitivity: "base" });
1962
+ const comparison = column.colDef.comparator ? column.colDef.comparator(leftValue, rightValue, left.row.data, right.row.data) : Object.is(leftValue, rightValue) ? 0 : leftValue === null || leftValue === undefined ? 1 : rightValue === null || rightValue === undefined ? -1 : Schema.is(Schema.Number)(leftValue) && Schema.is(Schema.Number)(rightValue) ? leftValue - rightValue : String(leftValue).localeCompare(String(rightValue), undefined, { numeric: true, sensitivity: "base" });
2060
1963
  if (comparison !== 0)
2061
- return sort.desc ? -comparison : comparison;
1964
+ return sort.direction === "desc" ? -comparison : comparison;
2062
1965
  }
2063
1966
  return left.stableIndex - right.stableIndex;
2064
1967
  }).map(({ row }) => row);
@@ -2066,22 +1969,11 @@ var sortDataTableRows = (rows, columns, sorting) => {
2066
1969
  var paginateDataTableRows = (rows, pagination) => {
2067
1970
  const pageSize = Math.max(1, pagination.pageSize);
2068
1971
  const lastPageIndex = Math.max(0, Math.ceil(rows.length / pageSize) - 1);
2069
- const pageIndex = Math.min(lastPageIndex, Math.max(0, pagination.pageIndex));
1972
+ const pageIndex = Math.min(lastPageIndex, Math.max(0, pagination.page));
2070
1973
  const start = pageIndex * pageSize;
2071
1974
  return rows.slice(start, start + pageSize);
2072
1975
  };
2073
- var mergeDataTableState = (state, controlledState = {}) => ({
2074
- globalFilter: controlledState.globalFilter ?? state.globalFilter,
2075
- sorting: controlledState.sorting ?? state.sorting,
2076
- pagination: controlledState.pagination ?? state.pagination,
2077
- columnVisibility: controlledState.columnVisibility ?? state.columnVisibility,
2078
- columnSizing: controlledState.columnSizing ?? state.columnSizing,
2079
- rowSelection: controlledState.rowSelection ?? state.rowSelection,
2080
- grouping: controlledState.grouping ?? state.grouping,
2081
- collapsedGroups: controlledState.collapsedGroups ?? state.collapsedGroups,
2082
- view: controlledState.view ?? state.view
2083
- });
2084
- var sameDataTableState = (left, right) => left.globalFilter === right.globalFilter && left.sorting === right.sorting && left.pagination === right.pagination && left.columnVisibility === right.columnVisibility && left.columnSizing === right.columnSizing && left.rowSelection === right.rowSelection && left.grouping === right.grouping && left.collapsedGroups === right.collapsedGroups && left.view === right.view;
1976
+ var sameDataTableState = (left, right) => left.page === right.page && left.pageSize === right.pageSize && left.globalFilter === right.globalFilter && left.sort === right.sort && left.columnVisibility === right.columnVisibility && left.columnSizing === right.columnSizing && left.rowSelection === right.rowSelection && left.grouping === right.grouping && left.collapsedGroups === right.collapsedGroups && left.view === right.view;
2085
1977
  var reorderDataTableRows = (rows, sourceRowId, targetRowId) => {
2086
1978
  const sourceIndex = rows.findIndex((row) => row.id === sourceRowId);
2087
1979
  const targetIndex = rows.findIndex((row) => row.id === targetRowId);
@@ -2127,7 +2019,7 @@ var clearDragPresentation = (root) => {
2127
2019
  element.removeAttribute("data-drop-position");
2128
2020
  });
2129
2021
  };
2130
- var resolveConfig = (props) => {
2022
+ var resolveConfig = (props, onUiStateChange) => {
2131
2023
  const features = props.features ?? {};
2132
2024
  const selection = features.selection;
2133
2025
  const getRowId = selection && selection.getRowId || props.getRowId || undefined;
@@ -2136,46 +2028,36 @@ var resolveConfig = (props) => {
2136
2028
  }
2137
2029
  return {
2138
2030
  getRowId,
2139
- onQueryChange: props.onQueryChange,
2140
2031
  onStateChange: props.onStateChange,
2032
+ onUiStateChange,
2141
2033
  status: props.status ?? {},
2142
2034
  features,
2143
2035
  onRowClicked: props.onRowClicked,
2144
2036
  labels: dataTableMessages(props.messages)
2145
2037
  };
2146
2038
  };
2147
- var dataTableStateFromQuery = (query) => query ? {
2148
- globalFilter: query.globalFilter ?? "",
2149
- sorting: query.sort ? Schema2.decodeSync(SortParamsFromString)(query.sort).map(({ id, direction }) => ({
2150
- id,
2151
- desc: direction === "desc"
2152
- })) : [],
2153
- pagination: { pageIndex: query.page, pageSize: query.pageSize }
2154
- } : {};
2155
- var queryFromDataTableState = (state) => ({
2156
- page: state.pagination.pageIndex,
2157
- pageSize: state.pagination.pageSize,
2158
- globalFilter: state.globalFilter || undefined,
2159
- sort: state.sorting.length ? Schema2.encodeSync(SortParamsFromString)(state.sorting.map(({ id, desc }) => ({
2160
- id,
2161
- direction: desc ? "desc" : "asc"
2162
- }))) : undefined
2039
+ var queryFromState = (state) => ({
2040
+ page: state.page,
2041
+ pageSize: state.pageSize,
2042
+ globalFilter: state.globalFilter,
2043
+ sort: state.sort
2163
2044
  });
2164
- var sameQuery = (left, right) => left.page === right.page && left.pageSize === right.pageSize && left.globalFilter === right.globalFilter && left.sort === right.sort;
2165
- var controlledStateFromProps = (query, state) => ({
2166
- ...dataTableStateFromQuery(query),
2167
- ...state
2045
+ var uiFromState = (state) => ({
2046
+ columnVisibility: state.columnVisibility,
2047
+ columnSizing: state.columnSizing,
2048
+ rowSelection: state.rowSelection,
2049
+ grouping: state.grouping,
2050
+ collapsedGroups: state.collapsedGroups,
2051
+ view: state.view
2052
+ });
2053
+ var sameUiState = (left, right) => left.columnVisibility === right.columnVisibility && left.columnSizing === right.columnSizing && left.rowSelection === right.rowSelection && left.grouping === right.grouping && left.collapsedGroups === right.collapsedGroups && left.view === right.view;
2054
+ var sameQueryState = (left, right) => left.page === right.page && left.pageSize === right.pageSize && left.globalFilter === right.globalFilter && left.sort === right.sort;
2055
+ var initialPublicState = (props, uiState) => ({
2056
+ ...DEFAULT_QUERY,
2057
+ ...props.initialState,
2058
+ ...props.state,
2059
+ ...uiState
2168
2060
  });
2169
- var initialPublicState = (props) => {
2170
- const grouping = props.features?.grouping;
2171
- const groupingInitial = grouping && grouping.initial ? grouping.initial : [];
2172
- return {
2173
- ...DEFAULT_STATE,
2174
- grouping: groupingInitial,
2175
- ...props.initialState,
2176
- ...controlledStateFromProps(props.query, props.state)
2177
- };
2178
- };
2179
2061
  var buildDataTableModel = (store) => {
2180
2062
  const columns = normalizeDataTableColumns(store.columnDefs, store.state.columnSizing);
2181
2063
  const selection = store.config.features.selection;
@@ -2183,9 +2065,9 @@ var buildDataTableModel = (store) => {
2183
2065
  const rows = buildDataTableRows(store.rowData, columns, rowId);
2184
2066
  const pagination = store.config.features.pagination ?? { mode: "client" };
2185
2067
  const server = pagination !== false && pagination.mode === "server";
2186
- const filteredRows = server ? [...rows] : filterDataTableRows(rows, columns, store.state.globalFilter);
2187
- const sortedRows = server ? filteredRows : sortDataTableRows(filteredRows, columns, store.state.sorting);
2188
- const pageRows = pagination === false || server ? sortedRows : paginateDataTableRows(sortedRows, store.state.pagination);
2068
+ const filteredRows = server ? [...rows] : filterDataTableRows(rows, columns, store.state.globalFilter ?? "");
2069
+ const sortedRows = server ? filteredRows : sortDataTableRows(filteredRows, columns, store.state.sort ?? []);
2070
+ const pageRows = pagination === false || server ? sortedRows : paginateDataTableRows(sortedRows, store.state);
2189
2071
  const totalRows = server ? pagination.rowCount : sortedRows.length;
2190
2072
  return {
2191
2073
  columns,
@@ -2194,7 +2076,7 @@ var buildDataTableModel = (store) => {
2194
2076
  filteredRows,
2195
2077
  sortedRows,
2196
2078
  pageRows,
2197
- pageCount: Math.max(1, Math.ceil(totalRows / Math.max(1, store.state.pagination.pageSize))),
2079
+ pageCount: Math.max(1, Math.ceil(totalRows / Math.max(1, store.state.pageSize))),
2198
2080
  totalRows
2199
2081
  };
2200
2082
  };
@@ -2202,13 +2084,15 @@ var useTableAtom = (tableAtom) => useAtom(tableAtom);
2202
2084
  var changeState = (setStore, update) => {
2203
2085
  setStore((store) => {
2204
2086
  const proposed = update(store.state);
2205
- const previousQuery = queryFromDataTableState(store.state);
2206
- const nextQuery = queryFromDataTableState(proposed);
2207
- if (!sameQuery(previousQuery, nextQuery)) {
2208
- store.config.onQueryChange?.(nextQuery);
2087
+ const query = queryFromState(proposed);
2088
+ if (!sameQueryState(query, store.state)) {
2089
+ store.config.onStateChange?.(query);
2090
+ }
2091
+ const uiState = uiFromState(proposed);
2092
+ if (!sameUiState(uiState, store.state)) {
2093
+ store.config.onUiStateChange(uiState);
2209
2094
  }
2210
- store.config.onStateChange?.(proposed);
2211
- const state = mergeDataTableState(proposed, store.controlledState);
2095
+ const state = store.controlledState ? { ...proposed, ...store.controlledState } : proposed;
2212
2096
  if (sameDataTableState(state, store.state))
2213
2097
  return store;
2214
2098
  const next = { ...store, state };
@@ -2253,7 +2137,7 @@ var getActiveGrouping = (store) => {
2253
2137
  };
2254
2138
  var canReorderRows = (store) => {
2255
2139
  const pagination = store.config.features.pagination;
2256
- return !!store.config.features.reordering && !getActiveGrouping(store).length && !store.state.globalFilter && !store.state.sorting.length && !(pagination && pagination.mode === "server");
2140
+ return !!store.config.features.reordering && !getActiveGrouping(store).length && !store.state.globalFilter && !store.state.sort?.length && !(pagination && pagination.mode === "server");
2257
2141
  };
2258
2142
  var canMoveRowsToGroups = (store) => getActiveGrouping(store).some((field) => !!field.onMoveToGroup);
2259
2143
  var canDragRows = (store) => getActiveGrouping(store).length ? canMoveRowsToGroups(store) : canReorderRows(store);
@@ -2276,11 +2160,11 @@ var renderCell = (row, column) => {
2276
2160
  return column.colDef.valueFormatter?.(params) ?? (value === null || value === undefined ? null : String(value));
2277
2161
  };
2278
2162
  var nodeText = (node) => {
2279
- if (Schema2.is(Schema2.String)(node) || Schema2.is(Schema2.Number)(node))
2163
+ if (Schema.is(Schema.String)(node) || Schema.is(Schema.Number)(node))
2280
2164
  return String(node);
2281
2165
  if (!isValidElement(node))
2282
2166
  return "";
2283
- if (Schema2.is(Schema2.String)(node.props.title))
2167
+ if (Schema.is(Schema.String)(node.props.title))
2284
2168
  return node.props.title;
2285
2169
  return nodeText(node.props.children);
2286
2170
  };
@@ -2427,18 +2311,18 @@ var DataTableToolbar = ({
2427
2311
  onChange: (event) => update((state) => ({
2428
2312
  ...state,
2429
2313
  globalFilter: event.target.value,
2430
- pagination: { ...state.pagination, pageIndex: 0 }
2314
+ page: 0
2431
2315
  })),
2432
2316
  placeholder: labels2.filter,
2433
- value: store.state.globalFilter
2317
+ value: store.state.globalFilter ?? ""
2434
2318
  }),
2435
2319
  store.state.globalFilter ? /* @__PURE__ */ jsx17(Button, {
2436
2320
  "aria-label": labels2.filter,
2437
2321
  className: "absolute top-1/2 right-1 size-7 -translate-y-1/2",
2438
2322
  onClick: () => update((state) => ({
2439
2323
  ...state,
2440
- globalFilter: "",
2441
- pagination: { ...state.pagination, pageIndex: 0 }
2324
+ globalFilter: undefined,
2325
+ page: 0
2442
2326
  })),
2443
2327
  size: "icon",
2444
2328
  variant: "ghost",
@@ -2447,7 +2331,7 @@ var DataTableToolbar = ({
2447
2331
  ]
2448
2332
  }) : null,
2449
2333
  /* @__PURE__ */ jsx17("div", {
2450
- className: "-m-1 flex w-full overflow-x-auto p-1",
2334
+ className: "-m-1 flex overflow-x-auto p-1",
2451
2335
  children: /* @__PURE__ */ jsxs9(Menubar, {
2452
2336
  className: "h-auto w-max min-w-full justify-start bg-transparent shadow-none [&_[data-slot=menubar-trigger]]:gap-2 [&_[data-slot=menubar-trigger]_svg]:size-4",
2453
2337
  children: [
@@ -2597,18 +2481,18 @@ var SortMenu = ({
2597
2481
  const columns = deriveModel(store).columns.filter(({ colDef }) => colDef.sortable !== false);
2598
2482
  if (!columns.length)
2599
2483
  return null;
2600
- const current = store.state.sorting[0];
2601
- const sort = (id, desc) => changeState(setStore, (state) => ({
2484
+ const current = store.state.sort?.[0];
2485
+ const sort = (id, direction) => changeState(setStore, (state) => ({
2602
2486
  ...state,
2603
- sorting: [{ id, desc }],
2604
- pagination: { ...state.pagination, pageIndex: 0 }
2487
+ sort: [{ id, direction }],
2488
+ page: 0
2605
2489
  }));
2606
2490
  return /* @__PURE__ */ jsxs9(MenubarMenu, {
2607
2491
  children: [
2608
2492
  /* @__PURE__ */ jsxs9(MenubarTrigger, {
2609
2493
  "aria-label": store.config.labels.sortBy,
2610
2494
  children: [
2611
- current ? current.desc ? /* @__PURE__ */ jsx17(ArrowDown, {}) : /* @__PURE__ */ jsx17(ArrowUp, {}) : /* @__PURE__ */ jsx17(ChevronsUpDown2, {}),
2495
+ current ? current.direction === "desc" ? /* @__PURE__ */ jsx17(ArrowDown, {}) : /* @__PURE__ */ jsx17(ArrowUp, {}) : /* @__PURE__ */ jsx17(ChevronsUpDown2, {}),
2612
2496
  /* @__PURE__ */ jsx17("span", {
2613
2497
  className: "hidden sm:inline",
2614
2498
  children: store.config.labels.sortBy
@@ -2619,19 +2503,19 @@ var SortMenu = ({
2619
2503
  align: "end",
2620
2504
  className: "w-52",
2621
2505
  children: columns.map((column) => {
2622
- const sortState = store.state.sorting.find(({ id }) => id === column.id);
2506
+ const sortState = store.state.sort?.find(({ id }) => id === column.id);
2623
2507
  return /* @__PURE__ */ jsxs9(MenubarSub, {
2624
2508
  children: [
2625
2509
  /* @__PURE__ */ jsxs9(MenubarSubTrigger, {
2626
2510
  children: [
2627
- sortState ? sortState.desc ? /* @__PURE__ */ jsx17(ArrowDown, {}) : /* @__PURE__ */ jsx17(ArrowUp, {}) : null,
2511
+ sortState ? sortState.direction === "desc" ? /* @__PURE__ */ jsx17(ArrowDown, {}) : /* @__PURE__ */ jsx17(ArrowUp, {}) : null,
2628
2512
  columnLabel(column)
2629
2513
  ]
2630
2514
  }),
2631
2515
  /* @__PURE__ */ jsxs9(MenubarSubContent, {
2632
2516
  children: [
2633
2517
  /* @__PURE__ */ jsxs9(MenubarItem, {
2634
- onClick: () => sort(column.id, false),
2518
+ onClick: () => sort(column.id, "asc"),
2635
2519
  children: [
2636
2520
  /* @__PURE__ */ jsx17(ArrowUp, {}),
2637
2521
  " ",
@@ -2639,7 +2523,7 @@ var SortMenu = ({
2639
2523
  ]
2640
2524
  }),
2641
2525
  /* @__PURE__ */ jsxs9(MenubarItem, {
2642
- onClick: () => sort(column.id, true),
2526
+ onClick: () => sort(column.id, "desc"),
2643
2527
  children: [
2644
2528
  /* @__PURE__ */ jsx17(ArrowDown, {}),
2645
2529
  " ",
@@ -2652,7 +2536,7 @@ var SortMenu = ({
2652
2536
  /* @__PURE__ */ jsxs9(MenubarItem, {
2653
2537
  onClick: () => changeState(setStore, (state) => ({
2654
2538
  ...state,
2655
- sorting: state.sorting.filter(({ id }) => id !== column.id)
2539
+ sort: state.sort?.filter(({ id }) => id !== column.id)
2656
2540
  })),
2657
2541
  children: [
2658
2542
  /* @__PURE__ */ jsx17(X2, {}),
@@ -3063,12 +2947,20 @@ var GroupedTable = ({
3063
2947
  const renderSections = (items) => items.flatMap((section) => {
3064
2948
  const collapsed = !!store.state.collapsedGroups[section.key];
3065
2949
  const targetKey = getGroupDropKey(section.field.id, section.groupId);
2950
+ const toggleCollapsed = () => changeState(setStore, (state) => ({
2951
+ ...state,
2952
+ collapsedGroups: {
2953
+ ...state.collapsedGroups,
2954
+ [section.key]: !collapsed
2955
+ }
2956
+ }));
3066
2957
  const body = /* @__PURE__ */ jsxs9(TableBody, {
3067
2958
  className: "data-[drop-target=true]:outline-primary relative data-[drop-target=true]:z-30 data-[drop-target=true]:outline-2 data-[drop-target=true]:-outline-offset-2 data-[drop-target=true]:[&>tr]:border-transparent data-[drop-target=true]:[&>tr>td:last-child]:z-0",
3068
2959
  "data-table-group": section.field.onMoveToGroup ? targetKey : undefined,
3069
2960
  children: [
3070
2961
  /* @__PURE__ */ jsx17(TableRow, {
3071
- className: "bg-muted/40",
2962
+ className: "bg-muted/40 hover:bg-accent! cursor-pointer",
2963
+ onClick: toggleCollapsed,
3072
2964
  children: /* @__PURE__ */ jsx17(TableCell, {
3073
2965
  colSpan: model.visibleColumns.length + extra,
3074
2966
  children: /* @__PURE__ */ jsxs9("div", {
@@ -3077,14 +2969,7 @@ var GroupedTable = ({
3077
2969
  children: [
3078
2970
  /* @__PURE__ */ jsxs9("button", {
3079
2971
  "aria-expanded": !collapsed,
3080
- className: "flex flex-1 items-center gap-2 text-left",
3081
- onClick: () => changeState(setStore, (state) => ({
3082
- ...state,
3083
- collapsedGroups: {
3084
- ...state.collapsedGroups,
3085
- [section.key]: !collapsed
3086
- }
3087
- })),
2972
+ className: "flex flex-1 cursor-pointer items-center gap-2 text-left font-medium",
3088
2973
  type: "button",
3089
2974
  children: [
3090
2975
  collapsed ? /* @__PURE__ */ jsx17(ChevronRight2, {
@@ -3143,12 +3028,12 @@ var ColumnHeaderMenu = ({
3143
3028
  return null;
3144
3029
  const sortingEnabled = store.config.features.sorting !== false && column.colDef.sortable !== false;
3145
3030
  const hidingEnabled = store.config.features.columnVisibility !== false && column.colDef.hideable !== false;
3146
- const sort = store.state.sorting.find(({ id }) => id === column.id);
3031
+ const sort = store.state.sort?.find(({ id }) => id === column.id);
3147
3032
  const update = (next) => changeState(setStore, next);
3148
- const setSort = (desc) => update((state) => ({
3033
+ const setSort = (direction) => update((state) => ({
3149
3034
  ...state,
3150
- sorting: [{ id: column.id, desc }],
3151
- pagination: { ...state.pagination, pageIndex: 0 }
3035
+ sort: [{ id: column.id, direction }],
3036
+ page: 0
3152
3037
  }));
3153
3038
  const label = columnLabel(column);
3154
3039
  if (!sortingEnabled && !hidingEnabled) {
@@ -3170,7 +3055,7 @@ var ColumnHeaderMenu = ({
3170
3055
  className: "truncate",
3171
3056
  children: column.colDef.headerName
3172
3057
  }),
3173
- sort ? sort.desc ? /* @__PURE__ */ jsx17(ArrowDown, {}) : /* @__PURE__ */ jsx17(ArrowUp, {}) : sortingEnabled ? /* @__PURE__ */ jsx17(ChevronsUpDown2, {}) : null
3058
+ sort ? sort.direction === "desc" ? /* @__PURE__ */ jsx17(ArrowDown, {}) : /* @__PURE__ */ jsx17(ArrowUp, {}) : sortingEnabled ? /* @__PURE__ */ jsx17(ChevronsUpDown2, {}) : null
3174
3059
  ]
3175
3060
  })
3176
3061
  }),
@@ -3182,7 +3067,7 @@ var ColumnHeaderMenu = ({
3182
3067
  sortingEnabled ? /* @__PURE__ */ jsxs9(Fragment, {
3183
3068
  children: [
3184
3069
  /* @__PURE__ */ jsxs9(DropdownMenuItem, {
3185
- onClick: () => setSort(false),
3070
+ onClick: () => setSort("asc"),
3186
3071
  children: [
3187
3072
  /* @__PURE__ */ jsx17(ArrowUp, {}),
3188
3073
  " ",
@@ -3190,7 +3075,7 @@ var ColumnHeaderMenu = ({
3190
3075
  ]
3191
3076
  }),
3192
3077
  /* @__PURE__ */ jsxs9(DropdownMenuItem, {
3193
- onClick: () => setSort(true),
3078
+ onClick: () => setSort("desc"),
3194
3079
  children: [
3195
3080
  /* @__PURE__ */ jsx17(ArrowDown, {}),
3196
3081
  " ",
@@ -3200,7 +3085,7 @@ var ColumnHeaderMenu = ({
3200
3085
  sort ? /* @__PURE__ */ jsxs9(DropdownMenuItem, {
3201
3086
  onClick: () => update((state) => ({
3202
3087
  ...state,
3203
- sorting: state.sorting.filter(({ id }) => id !== column.id)
3088
+ sort: state.sort?.filter(({ id }) => id !== column.id)
3204
3089
  })),
3205
3090
  children: [
3206
3091
  /* @__PURE__ */ jsx17(X2, {}),
@@ -3436,23 +3321,24 @@ var DataTableGallery = ({
3436
3321
  const renderSections = (sections) => sections.map((section) => {
3437
3322
  const collapsed = !!store.state.collapsedGroups[section.key];
3438
3323
  const targetKey = getGroupDropKey(section.field.id, section.groupId);
3324
+ const toggleCollapsed = () => changeState(setStore, (state) => ({
3325
+ ...state,
3326
+ collapsedGroups: {
3327
+ ...state.collapsedGroups,
3328
+ [section.key]: !collapsed
3329
+ }
3330
+ }));
3439
3331
  return /* @__PURE__ */ jsxs9("section", {
3440
3332
  className: "data-[drop-target=true]:ring-primary space-y-3 rounded-lg transition-shadow data-[drop-target=true]:ring-2",
3441
3333
  "data-table-group": section.field.onMoveToGroup ? targetKey : undefined,
3442
3334
  children: [
3443
3335
  /* @__PURE__ */ jsxs9("div", {
3444
- className: "flex items-center gap-2 rounded-lg border p-3",
3336
+ className: "hover:bg-accent flex cursor-pointer items-center gap-2 rounded-lg border p-3 transition-colors",
3337
+ onClick: toggleCollapsed,
3445
3338
  children: [
3446
3339
  /* @__PURE__ */ jsxs9("button", {
3447
3340
  "aria-expanded": !collapsed,
3448
- className: "flex flex-1 items-center gap-2 text-left",
3449
- onClick: () => changeState(setStore, (state) => ({
3450
- ...state,
3451
- collapsedGroups: {
3452
- ...state.collapsedGroups,
3453
- [section.key]: !collapsed
3454
- }
3455
- })),
3341
+ className: "flex flex-1 cursor-pointer items-center gap-2 text-left font-medium",
3456
3342
  type: "button",
3457
3343
  children: [
3458
3344
  collapsed ? /* @__PURE__ */ jsx17(ChevronRight2, {
@@ -3505,45 +3391,63 @@ var DataTablePagination = ({
3505
3391
  const pagination = store.config.features.pagination ?? { mode: "client" };
3506
3392
  const clientGrouping = pagination !== false && pagination.mode === "client" && getActiveGrouping(store).length > 0;
3507
3393
  const paginationVisible = pagination !== false && !clientGrouping;
3508
- const pageIndex = store.state.pagination.pageIndex;
3394
+ const pageIndex = store.state.page;
3509
3395
  const maxPageIndex = model.pageCount - 1;
3510
3396
  useLayoutEffect(() => {
3511
3397
  if (paginationVisible && pageIndex > maxPageIndex) {
3512
3398
  changeState(setStore, (state) => ({
3513
3399
  ...state,
3514
- pagination: { ...state.pagination, pageIndex: maxPageIndex }
3400
+ page: maxPageIndex
3515
3401
  }));
3516
3402
  }
3517
3403
  }, [maxPageIndex, pageIndex, paginationVisible, setStore]);
3518
3404
  if (!paginationVisible)
3519
3405
  return null;
3520
3406
  const selected = model.rows.filter((row) => store.state.rowSelection[row.id]).length;
3521
- const setPagination = (next) => changeState(setStore, (state) => ({ ...state, pagination: next }));
3407
+ const setPagination = (next) => changeState(setStore, (state) => ({ ...state, ...next }));
3522
3408
  return /* @__PURE__ */ jsx17("div", {
3523
3409
  className: "pt-4",
3524
3410
  children: /* @__PURE__ */ jsx17(Pagination, {
3525
3411
  messages: store.config.labels,
3526
- onPageChange: (pageIndex2) => setPagination({ ...store.state.pagination, pageIndex: pageIndex2 }),
3527
- onPageSizeChange: (pageSize) => setPagination({ pageIndex: 0, pageSize }),
3528
- page: Math.min(store.state.pagination.pageIndex, model.pageCount - 1),
3412
+ onPageChange: (page) => setPagination({ page, pageSize: store.state.pageSize }),
3413
+ onPageSizeChange: (pageSize) => setPagination({ page: 0, pageSize }),
3414
+ page: Math.min(store.state.page, model.pageCount - 1),
3529
3415
  pageCount: model.pageCount,
3530
- pageSize: store.state.pagination.pageSize,
3416
+ pageSize: store.state.pageSize,
3531
3417
  pageSizes: pagination.pageSizes,
3532
3418
  selectedRows: selected,
3533
3419
  totalRows: model.totalRows
3534
3420
  })
3535
3421
  });
3536
3422
  };
3537
- var DataTable = (props) => {
3538
- const validatedConfig = resolveConfig(props);
3423
+ var HydratedDataTable = ({
3424
+ persistedUiState,
3425
+ setPersistedUiState,
3426
+ ...props
3427
+ }) => {
3428
+ const transientUiAtomRef = useRef2(null);
3429
+ if (!transientUiAtomRef.current) {
3430
+ const grouping = props.features?.grouping;
3431
+ transientUiAtomRef.current = Atom.make({
3432
+ ...transientUiFromState(DEFAULT_UI_STATE),
3433
+ grouping: grouping && grouping.initial ? grouping.initial : []
3434
+ });
3435
+ }
3436
+ const [transientUiState, setTransientUiState] = useAtom(transientUiAtomRef.current);
3437
+ const uiState = useMemo(() => ({ ...persistedUiState, ...transientUiState }), [persistedUiState, transientUiState]);
3438
+ const setUiState = useCallback2((state) => {
3439
+ setPersistedUiState(persistedUiFromState(state));
3440
+ setTransientUiState(transientUiFromState(state));
3441
+ }, [setPersistedUiState, setTransientUiState]);
3442
+ const validatedConfig = resolveConfig(props, (state) => setUiState(state));
3539
3443
  const atomRef = useRef2(null);
3540
3444
  if (!atomRef.current) {
3541
3445
  const initial = {
3542
3446
  rowData: props.rowData,
3543
3447
  columnDefs: props.columnDefs,
3544
3448
  config: validatedConfig,
3545
- state: initialPublicState(props),
3546
- controlledState: controlledStateFromProps(props.query, props.state)
3449
+ state: initialPublicState(props, uiState),
3450
+ controlledState: props.state
3547
3451
  };
3548
3452
  atomRef.current = Atom.make({
3549
3453
  ...initial,
@@ -3558,22 +3462,21 @@ var DataTable = (props) => {
3558
3462
  const selection = features.selection;
3559
3463
  const config = {
3560
3464
  getRowId: selection && selection.getRowId || props.getRowId || undefined,
3561
- onQueryChange: props.onQueryChange,
3562
3465
  onStateChange: props.onStateChange,
3466
+ onUiStateChange: (state2) => setUiState(state2),
3563
3467
  status: props.status ?? {},
3564
3468
  features,
3565
3469
  onRowClicked: props.onRowClicked,
3566
3470
  labels: dataTableMessages(props.messages)
3567
3471
  };
3568
- const controlledState = controlledStateFromProps(props.query, props.state);
3569
- const state = mergeDataTableState(store.state, controlledState);
3472
+ const state = { ...store.state, ...uiState, ...props.state };
3570
3473
  const modelChanged = store.rowData !== props.rowData || store.columnDefs !== props.columnDefs || !sameDataTableState(store.state, state) || store.config.getRowId !== config.getRowId || store.config.features.pagination !== config.features.pagination;
3571
3474
  const next = {
3572
3475
  ...store,
3573
3476
  rowData: props.rowData,
3574
3477
  columnDefs: props.columnDefs,
3575
3478
  config,
3576
- controlledState,
3479
+ controlledState: props.state,
3577
3480
  state
3578
3481
  };
3579
3482
  return modelChanged ? { ...next, model: buildDataTableModel(next) } : next;
@@ -3584,13 +3487,13 @@ var DataTable = (props) => {
3584
3487
  props.getRowId,
3585
3488
  props.messages,
3586
3489
  props.onRowClicked,
3587
- props.onQueryChange,
3588
3490
  props.onStateChange,
3589
- props.query,
3590
3491
  props.rowData,
3591
3492
  props.state,
3592
3493
  props.status,
3593
- setStore
3494
+ setStore,
3495
+ setUiState,
3496
+ uiState
3594
3497
  ]);
3595
3498
  return /* @__PURE__ */ jsxs9("div", {
3596
3499
  className: "w-full max-w-full min-w-0 rounded-md",
@@ -3608,6 +3511,34 @@ var DataTable = (props) => {
3608
3511
  ]
3609
3512
  });
3610
3513
  };
3514
+ var DataTable = (props) => {
3515
+ const persistedUiAtomRef = useRef2(null);
3516
+ if (!persistedUiAtomRef.current) {
3517
+ const pathname = globalThis.window?.location.pathname ?? "/";
3518
+ const columnIds = normalizeDataTableColumns(props.columnDefs).map(({ id }) => id).join(",");
3519
+ const viewCapability = props.features?.gallery ? "gallery" : "table";
3520
+ persistedUiAtomRef.current = Atom.kvs({
3521
+ mode: "async",
3522
+ runtime: dataTableStorageRuntime,
3523
+ key: `data-table:${pathname}:${columnIds}:${viewCapability}:ui`,
3524
+ schema: DataTablePersistedUiStateSchema,
3525
+ defaultValue: () => persistedUiFromState(DEFAULT_UI_STATE)
3526
+ });
3527
+ }
3528
+ const [persistedUiResult, setPersistedUiState] = useAtom(persistedUiAtomRef.current);
3529
+ if (!AsyncResult.isSuccess(persistedUiResult) || AsyncResult.isWaiting(persistedUiResult)) {
3530
+ return /* @__PURE__ */ jsx17("div", {
3531
+ "aria-busy": "true",
3532
+ className: "invisible w-full max-w-full min-w-0 rounded-md",
3533
+ "data-table-root": ""
3534
+ });
3535
+ }
3536
+ return /* @__PURE__ */ jsx17(HydratedDataTable, {
3537
+ ...props,
3538
+ persistedUiState: persistedUiResult.value,
3539
+ setPersistedUiState
3540
+ });
3541
+ };
3611
3542
  var DataTableContent = ({
3612
3543
  tableAtom
3613
3544
  }) => {
@@ -3690,7 +3621,7 @@ var DataTableListSummary = ({
3690
3621
  visibleCount = 3
3691
3622
  }) => {
3692
3623
  const labels2 = dataTableMessages();
3693
- const normalized = items.map((item) => Schema2.is(Schema2.String)(item) ? { label: item } : item);
3624
+ const normalized = items.map((item) => Schema.is(Schema.String)(item) ? { label: item } : item);
3694
3625
  if (!normalized.length)
3695
3626
  return /* @__PURE__ */ jsx17("span", {
3696
3627
  className: "text-muted-foreground",
@@ -3789,7 +3720,6 @@ export {
3789
3720
  getDataTableSelectableRows,
3790
3721
  getDataTableWidth,
3791
3722
  groupDataTableRows,
3792
- mergeDataTableState,
3793
3723
  normalizeDataTableColumns,
3794
3724
  paginateDataTableRows,
3795
3725
  reorderDataTableRows,