@krak-stack/registry 0.1.20 → 0.1.21

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,5 +1,6 @@
1
1
  import { type ReactNode } from "react";
2
2
  import { type PaginationMessages } from "./pagination.js";
3
+ import { type QueryType } from "../../lib/query.js";
3
4
  type RowData = object;
4
5
  export type DataTableSorting = readonly {
5
6
  id: string;
@@ -156,6 +157,8 @@ export type DataTableMessages = PaginationMessages & {
156
157
  sortBy: string;
157
158
  hideColumn: string;
158
159
  reorder: string;
160
+ moveUp: string;
161
+ moveDown: string;
159
162
  resizeColumn: (column: string) => string;
160
163
  listOthers: (count: number) => string;
161
164
  selectAllRows: string;
@@ -191,6 +194,8 @@ export declare const dataTableMessages: (overrides?: DataTableMessageOverrides)
191
194
  sortBy: string;
192
195
  hideColumn: string;
193
196
  reorder: string;
197
+ moveUp: string;
198
+ moveDown: string;
194
199
  resizeColumn: (column: string) => string;
195
200
  listOthers: (count: number) => string;
196
201
  selectAllRows: string;
@@ -224,6 +229,8 @@ export declare const dataTableMessages: (overrides?: DataTableMessageOverrides)
224
229
  sortBy: string;
225
230
  hideColumn: string;
226
231
  reorder: string;
232
+ moveUp: string;
233
+ moveDown: string;
227
234
  resizeColumn: (column: string) => string;
228
235
  listOthers: (count: number) => string;
229
236
  selectAllRows: string;
@@ -237,6 +244,8 @@ export interface DataTableProps<TData extends RowData> {
237
244
  state?: Partial<DataTablePublicState>;
238
245
  initialState?: Partial<DataTablePublicState>;
239
246
  onStateChange?: (state: DataTablePublicState) => void;
247
+ query?: QueryType;
248
+ onQueryChange?: (query: QueryType) => void;
240
249
  status?: DataTableStatus;
241
250
  features?: DataTableFeatures<TData>;
242
251
  onRowClicked?: (row: TData) => void;
@@ -1,6 +1,6 @@
1
1
  // ../../src/components/ui/data-table.tsx
2
2
  import { useAtom, useAtomSet } from "@effect/atom-react";
3
- import { Schema } from "effect";
3
+ import { Schema as Schema2 } from "effect";
4
4
  import { Atom } from "effect/unstable/reactivity";
5
5
  import {
6
6
  ArrowDown,
@@ -1804,6 +1804,123 @@ function VirtualizedCombobox(props) {
1804
1804
  });
1805
1805
  }
1806
1806
 
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
+
1807
1924
  // ../../src/components/ui/data-table.tsx
1808
1925
  import { jsx as jsx17, jsxs as jsxs9, Fragment } from "react/jsx-runtime";
1809
1926
  var messages3 = {
@@ -1828,6 +1945,8 @@ var messages3 = {
1828
1945
  sortBy: "Sort by",
1829
1946
  hideColumn: "Hide column",
1830
1947
  reorder: "Drag to reorder",
1948
+ moveUp: "Move up",
1949
+ moveDown: "Move down",
1831
1950
  resizeColumn: (column) => `Resize ${column} column`,
1832
1951
  listOthers: (count) => count === 1 ? "and 1 other" : `and ${count} others`,
1833
1952
  selectAllRows: "Select all rows on this page",
@@ -1855,6 +1974,8 @@ var messages3 = {
1855
1974
  sortBy: "Trier par",
1856
1975
  hideColumn: "Masquer la colonne",
1857
1976
  reorder: "Glisser pour réordonner",
1977
+ moveUp: "Déplacer vers le haut",
1978
+ moveDown: "Déplacer vers le bas",
1858
1979
  resizeColumn: (column) => `Redimensionner la colonne ${column}`,
1859
1980
  listOthers: (count) => count === 1 ? "et 1 autre" : `et ${count} autres`,
1860
1981
  selectAllRows: "Sélectionner toutes les lignes de cette page",
@@ -1935,7 +2056,7 @@ var sortDataTableRows = (rows, columns, sorting) => {
1935
2056
  continue;
1936
2057
  const leftValue = left.row.values.get(sort.id);
1937
2058
  const rightValue = right.row.values.get(sort.id);
1938
- 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" });
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" });
1939
2060
  if (comparison !== 0)
1940
2061
  return sort.desc ? -comparison : comparison;
1941
2062
  }
@@ -2015,6 +2136,7 @@ var resolveConfig = (props) => {
2015
2136
  }
2016
2137
  return {
2017
2138
  getRowId,
2139
+ onQueryChange: props.onQueryChange,
2018
2140
  onStateChange: props.onStateChange,
2019
2141
  status: props.status ?? {},
2020
2142
  features,
@@ -2022,6 +2144,28 @@ var resolveConfig = (props) => {
2022
2144
  labels: dataTableMessages(props.messages)
2023
2145
  };
2024
2146
  };
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
2163
+ });
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
2168
+ });
2025
2169
  var initialPublicState = (props) => {
2026
2170
  const grouping = props.features?.grouping;
2027
2171
  const groupingInitial = grouping && grouping.initial ? grouping.initial : [];
@@ -2029,7 +2173,7 @@ var initialPublicState = (props) => {
2029
2173
  ...DEFAULT_STATE,
2030
2174
  grouping: groupingInitial,
2031
2175
  ...props.initialState,
2032
- ...props.state
2176
+ ...controlledStateFromProps(props.query, props.state)
2033
2177
  };
2034
2178
  };
2035
2179
  var buildDataTableModel = (store) => {
@@ -2058,6 +2202,11 @@ var useTableAtom = (tableAtom) => useAtom(tableAtom);
2058
2202
  var changeState = (setStore, update) => {
2059
2203
  setStore((store) => {
2060
2204
  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);
2209
+ }
2061
2210
  store.config.onStateChange?.(proposed);
2062
2211
  const state = mergeDataTableState(proposed, store.controlledState);
2063
2212
  if (sameDataTableState(state, store.state))
@@ -2108,6 +2257,7 @@ var canReorderRows = (store) => {
2108
2257
  };
2109
2258
  var canMoveRowsToGroups = (store) => getActiveGrouping(store).some((field) => !!field.onMoveToGroup);
2110
2259
  var canDragRows = (store) => getActiveGrouping(store).length ? canMoveRowsToGroups(store) : canReorderRows(store);
2260
+ var hasRowActionMenu = (store) => !!store.config.features.rowActions || canReorderRows(store);
2111
2261
  var getSelectedRows = (store, model) => model.rows.filter((row) => store.state.rowSelection[row.id]).map((row) => row.data);
2112
2262
  var renderCell = (row, column) => {
2113
2263
  const value = row.values.get(column.id);
@@ -2126,11 +2276,11 @@ var renderCell = (row, column) => {
2126
2276
  return column.colDef.valueFormatter?.(params) ?? (value === null || value === undefined ? null : String(value));
2127
2277
  };
2128
2278
  var nodeText = (node) => {
2129
- if (Schema.is(Schema.String)(node) || Schema.is(Schema.Number)(node))
2279
+ if (Schema2.is(Schema2.String)(node) || Schema2.is(Schema2.Number)(node))
2130
2280
  return String(node);
2131
2281
  if (!isValidElement(node))
2132
2282
  return "";
2133
- if (Schema.is(Schema.String)(node.props.title))
2283
+ if (Schema2.is(Schema2.String)(node.props.title))
2134
2284
  return node.props.title;
2135
2285
  return nodeText(node.props.children);
2136
2286
  };
@@ -2209,6 +2359,45 @@ var DataTableRowActions = ({
2209
2359
  ]
2210
2360
  });
2211
2361
  };
2362
+ var DataTableRowActionMenu = ({
2363
+ tableAtom
2364
+ }) => {
2365
+ const [store] = useTableAtom(tableAtom);
2366
+ const rowId = useRequiredId(RowIdContext);
2367
+ const model = deriveModel(store);
2368
+ const row = model.sortedRows.find((candidate) => candidate.id === rowId);
2369
+ if (!row)
2370
+ return null;
2371
+ const rowActions = store.config.features.rowActions || undefined;
2372
+ const visibleRows = model.pageRows;
2373
+ const rowIndex = visibleRows.findIndex((candidate) => candidate.id === rowId);
2374
+ const reordering = store.config.features.reordering;
2375
+ const reorderActions = [];
2376
+ if (reordering && canReorderRows(store)) {
2377
+ const move = (targetIndex) => reordering.onReorder(reorderDataTableRows(model.rows, rowId, visibleRows[targetIndex].id));
2378
+ if (rowIndex > 0) {
2379
+ reorderActions.push({
2380
+ id: "data-table-move-up",
2381
+ name: store.config.labels.moveUp,
2382
+ icon: /* @__PURE__ */ jsx17(ArrowUp, {}),
2383
+ onClick: () => move(rowIndex - 1)
2384
+ });
2385
+ }
2386
+ if (rowIndex !== -1 && rowIndex < visibleRows.length - 1) {
2387
+ reorderActions.push({
2388
+ id: "data-table-move-down",
2389
+ name: store.config.labels.moveDown,
2390
+ icon: /* @__PURE__ */ jsx17(ArrowDown, {}),
2391
+ onClick: () => move(rowIndex + 1)
2392
+ });
2393
+ }
2394
+ }
2395
+ return /* @__PURE__ */ jsx17(DataTableRowActions, {
2396
+ actions: [...reorderActions, ...rowActions ? rowActions.items : []],
2397
+ row: row.data,
2398
+ title: rowActions?.label ?? store.config.labels.actions
2399
+ });
2400
+ };
2212
2401
  var DataTableToolbar = ({
2213
2402
  tableAtom
2214
2403
  }) => {
@@ -2772,7 +2961,6 @@ var TableDataRow = ({
2772
2961
  return null;
2773
2962
  const selection = store.config.features.selection;
2774
2963
  const selectable = !!selection && (selection.isRowSelectable?.(row.data) ?? true);
2775
- const rowActions = store.config.features.rowActions;
2776
2964
  const draggable = canDragRows(store);
2777
2965
  return /* @__PURE__ */ jsxs9(TableRow, {
2778
2966
  className: cn("group/row h-16 data-[drag-source=true]:opacity-40 data-[drop-position=before]:[&>td]:border-t-2 data-[drop-position=before]:[&>td]:border-primary data-[drop-position=after]:[&>td]:border-b-2 data-[drop-position=after]:[&>td]:border-primary", store.config.onRowClicked && "cursor-pointer"),
@@ -2811,15 +2999,13 @@ var TableDataRow = ({
2811
2999
  children: renderCell(row, column)
2812
3000
  })
2813
3001
  }, column.id)),
2814
- rowActions ? /* @__PURE__ */ jsx17(TableCell, {
3002
+ hasRowActionMenu(store) ? /* @__PURE__ */ jsx17(TableCell, {
2815
3003
  className: "bg-background group-data-[state=selected]/row:bg-muted sticky right-0 z-20 w-10 min-w-10 cursor-default p-0 transition-colors group-hover/row:bg-[color-mix(in_oklab,var(--muted)_50%,var(--background))]",
2816
3004
  onClick: (event) => event.stopPropagation(),
2817
3005
  children: /* @__PURE__ */ jsx17("div", {
2818
3006
  className: "flex h-16 items-center justify-center",
2819
- children: /* @__PURE__ */ jsx17(DataTableRowActions, {
2820
- actions: rowActions.items,
2821
- row: row.data,
2822
- title: rowActions.label ?? store.config.labels.actions
3007
+ children: /* @__PURE__ */ jsx17(DataTableRowActionMenu, {
3008
+ tableAtom
2823
3009
  })
2824
3010
  })
2825
3011
  }) : null
@@ -2873,7 +3059,7 @@ var GroupedTable = ({
2873
3059
  const [store, setStore] = useTableAtom(tableAtom);
2874
3060
  const model = deriveModel(store);
2875
3061
  const sections = groupDataTableRows(model.sortedRows, getActiveGrouping(store));
2876
- const extra = (store.config.features.selection ? 1 : 0) + (store.config.features.rowActions ? 1 : 0) + (canDragRows(store) ? 1 : 0);
3062
+ const extra = (store.config.features.selection ? 1 : 0) + (hasRowActionMenu(store) ? 1 : 0) + (canDragRows(store) ? 1 : 0);
2877
3063
  const renderSections = (items) => items.flatMap((section) => {
2878
3064
  const collapsed = !!store.state.collapsedGroups[section.key];
2879
3065
  const targetKey = getGroupDropKey(section.field.id, section.groupId);
@@ -3095,7 +3281,7 @@ var DataTableHeader = ({
3095
3281
  })
3096
3282
  }, column.id);
3097
3283
  }),
3098
- store.config.features.rowActions ? /* @__PURE__ */ jsx17(TableHead, {
3284
+ hasRowActionMenu(store) ? /* @__PURE__ */ jsx17(TableHead, {
3099
3285
  className: "w-10"
3100
3286
  }) : null
3101
3287
  ]
@@ -3109,7 +3295,7 @@ var DataTableBody = ({
3109
3295
  const model = deriveModel(store);
3110
3296
  const grouped = getActiveGrouping(store).length > 0;
3111
3297
  const rows = grouped ? model.sortedRows : model.pageRows;
3112
- const colSpan = model.visibleColumns.length + (store.config.features.selection ? 1 : 0) + (store.config.features.rowActions ? 1 : 0) + (canDragRows(store) ? 1 : 0);
3298
+ const colSpan = model.visibleColumns.length + (store.config.features.selection ? 1 : 0) + (hasRowActionMenu(store) ? 1 : 0) + (canDragRows(store) ? 1 : 0);
3113
3299
  if (grouped && rows.length && !store.config.status.error) {
3114
3300
  return /* @__PURE__ */ jsx17(GroupedTable, {
3115
3301
  tableAtom
@@ -3154,7 +3340,6 @@ var GalleryCard = ({
3154
3340
  const tag = find(gallery.tag);
3155
3341
  const selection = store.config.features.selection;
3156
3342
  const selectable = !!selection && (selection.isRowSelectable?.(row.data) ?? true);
3157
- const rowActions = store.config.features.rowActions;
3158
3343
  const draggable = canDragRows(store);
3159
3344
  return /* @__PURE__ */ jsx17(Card, {
3160
3345
  className: cn("relative gap-3 data-[drag-source=true]:opacity-40 data-[drop-position=before]:border-t-2 data-[drop-position=before]:border-t-primary data-[drop-position=after]:border-b-2 data-[drop-position=after]:border-b-primary", store.config.onRowClicked && "cursor-pointer"),
@@ -3199,13 +3384,11 @@ var GalleryCard = ({
3199
3384
  className: "text-muted-foreground line-clamp-3 text-sm",
3200
3385
  children: renderCell(row, description)
3201
3386
  }) : null,
3202
- rowActions ? /* @__PURE__ */ jsx17("div", {
3387
+ hasRowActionMenu(store) ? /* @__PURE__ */ jsx17("div", {
3203
3388
  className: "absolute top-4 right-4",
3204
3389
  onClick: (event) => event.stopPropagation(),
3205
- children: /* @__PURE__ */ jsx17(DataTableRowActions, {
3206
- actions: rowActions.items,
3207
- row: row.data,
3208
- title: rowActions.label ?? store.config.labels.actions
3390
+ children: /* @__PURE__ */ jsx17(DataTableRowActionMenu, {
3391
+ tableAtom
3209
3392
  })
3210
3393
  }) : null
3211
3394
  ]
@@ -3360,7 +3543,7 @@ var DataTable = (props) => {
3360
3543
  columnDefs: props.columnDefs,
3361
3544
  config: validatedConfig,
3362
3545
  state: initialPublicState(props),
3363
- controlledState: props.state ?? {}
3546
+ controlledState: controlledStateFromProps(props.query, props.state)
3364
3547
  };
3365
3548
  atomRef.current = Atom.make({
3366
3549
  ...initial,
@@ -3375,20 +3558,22 @@ var DataTable = (props) => {
3375
3558
  const selection = features.selection;
3376
3559
  const config = {
3377
3560
  getRowId: selection && selection.getRowId || props.getRowId || undefined,
3561
+ onQueryChange: props.onQueryChange,
3378
3562
  onStateChange: props.onStateChange,
3379
3563
  status: props.status ?? {},
3380
3564
  features,
3381
3565
  onRowClicked: props.onRowClicked,
3382
3566
  labels: dataTableMessages(props.messages)
3383
3567
  };
3384
- const state = mergeDataTableState(store.state, props.state);
3568
+ const controlledState = controlledStateFromProps(props.query, props.state);
3569
+ const state = mergeDataTableState(store.state, controlledState);
3385
3570
  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;
3386
3571
  const next = {
3387
3572
  ...store,
3388
3573
  rowData: props.rowData,
3389
3574
  columnDefs: props.columnDefs,
3390
3575
  config,
3391
- controlledState: props.state ?? {},
3576
+ controlledState,
3392
3577
  state
3393
3578
  };
3394
3579
  return modelChanged ? { ...next, model: buildDataTableModel(next) } : next;
@@ -3399,7 +3584,9 @@ var DataTable = (props) => {
3399
3584
  props.getRowId,
3400
3585
  props.messages,
3401
3586
  props.onRowClicked,
3587
+ props.onQueryChange,
3402
3588
  props.onStateChange,
3589
+ props.query,
3403
3590
  props.rowData,
3404
3591
  props.state,
3405
3592
  props.status,
@@ -3431,7 +3618,7 @@ var DataTableContent = ({
3431
3618
  });
3432
3619
  }
3433
3620
  const model = deriveModel(store);
3434
- const width = getDataTableWidth(model.visibleColumns, (store.config.features.selection ? 1 : 0) + (store.config.features.rowActions ? 1 : 0) + (canDragRows(store) ? 1 : 0));
3621
+ const width = getDataTableWidth(model.visibleColumns, (store.config.features.selection ? 1 : 0) + (hasRowActionMenu(store) ? 1 : 0) + (canDragRows(store) ? 1 : 0));
3435
3622
  return /* @__PURE__ */ jsxs9(ScrollArea, {
3436
3623
  className: "max-w-full min-w-0",
3437
3624
  children: [
@@ -3503,7 +3690,7 @@ var DataTableListSummary = ({
3503
3690
  visibleCount = 3
3504
3691
  }) => {
3505
3692
  const labels2 = dataTableMessages();
3506
- const normalized = items.map((item) => Schema.is(Schema.String)(item) ? { label: item } : item);
3693
+ const normalized = items.map((item) => Schema2.is(Schema2.String)(item) ? { label: item } : item);
3507
3694
  if (!normalized.length)
3508
3695
  return /* @__PURE__ */ jsx17("span", {
3509
3696
  className: "text-muted-foreground",
@@ -22,8 +22,8 @@ export declare const SortParamsFromString: Schema.decodeTo<Schema.$Array<Schema.
22
22
  readonly direction: Schema.Union<readonly [Schema.Literal<"asc">, Schema.Literal<"desc">]>;
23
23
  }>>, Schema.String, never, never>;
24
24
  export declare const Query: Schema.Struct<{
25
- readonly page: Schema.Int;
26
- readonly pageSize: Schema.Int;
25
+ readonly page: Schema.withDecodingDefaultKey<Schema.Int, never>;
26
+ readonly pageSize: Schema.withDecodingDefaultKey<Schema.Int, never>;
27
27
  readonly globalFilter: Schema.optional<Schema.String>;
28
28
  readonly sort: Schema.optional<Schema.decodeTo<Schema.String, Schema.decodeTo<Schema.$Array<Schema.Struct<{
29
29
  readonly id: Schema.NonEmptyString;
@@ -31,6 +31,7 @@ export declare const Query: Schema.Struct<{
31
31
  }>>, Schema.String, never, never>, never, never>>;
32
32
  }>;
33
33
  export type QueryType = typeof Query.Type;
34
+ export declare const QueryStandard: ReturnType<typeof Schema.toStandardSchemaV1<typeof Query>>;
34
35
  export declare const PaginationMeta: Schema.Struct<{
35
36
  readonly page: Schema.Int;
36
37
  readonly pageSize: Schema.Int;
package/dist/lib/query.js CHANGED
@@ -85,8 +85,8 @@ var SortParamSearch = SortParamsFromString.pipe(Schema.decodeTo(Schema.String, S
85
85
  examples: ["-name,age"]
86
86
  }));
87
87
  var Query = Schema.Struct({
88
- page: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
89
- pageSize: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100 })),
88
+ page: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.withDecodingDefaultKey(Effect.succeed(0))),
89
+ pageSize: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100 })).pipe(Schema.withDecodingDefaultKey(Effect.succeed(10))),
90
90
  globalFilter: Schema.optional(Schema.String),
91
91
  sort: Schema.optional(SortParamSearch)
92
92
  }).annotate({
@@ -102,6 +102,7 @@ var Query = Schema.Struct({
102
102
  }
103
103
  ]
104
104
  });
105
+ var QueryStandard = Schema.toStandardSchemaV1(Query);
105
106
  var PaginationMeta = Schema.Struct({
106
107
  page: Schema.Int,
107
108
  pageSize: Schema.Int,
@@ -121,6 +122,7 @@ export {
121
122
  PaginatedResponse,
122
123
  PaginationMeta,
123
124
  Query,
125
+ QueryStandard,
124
126
  SortDirection,
125
127
  SortParam,
126
128
  SortParamFromString,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krak-stack/registry",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Tree-shakable KrakStack components and Effect services.",
5
5
  "license": "MIT",
6
6
  "repository": {