@redsift/table-pro 12.6.1 → 12.6.3

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/index.d.ts CHANGED
@@ -359,16 +359,53 @@ declare const clearPreviousVersionStorage: (id: string, previousLocalStorageVers
359
359
  * Useful when the consumer wants to wipe all persisted grid state regardless of which version is active.
360
360
  */
361
361
  declare const clearAllVersionStorage: (id: string, maxVersion: number) => void;
362
+ /** Options for `resetStatefulDataGridState` and `resetColumnVisibility`. */
363
+ interface StatefulDataGridResetOptions {
364
+ /** The grid's localStorage id: the `pathname` its `useRouter` returns. */
365
+ id: string;
366
+ /** The localStorage versions to clear. */
367
+ versions: number[];
368
+ /**
369
+ * The router's query string, as the caller captured it. Under a browser
370
+ * router this is only a fallback: `window.location.search` is read instead,
371
+ * because a snapshot captured at render can be stale. It is used as given
372
+ * only when `window.location` is unavailable (SSR, tests without jsdom), and
373
+ * it is ignored when `getSearch` is given.
374
+ */
375
+ search?: string;
376
+ /**
377
+ * Returns the router's live query string, with or without the leading `?`.
378
+ * Called once, at reset time, and used instead of both
379
+ * `window.location.search` and `search`.
380
+ *
381
+ * Pass it under a memory history (`createMemoryHistory`, `MemoryRouter`),
382
+ * for example in a sift rendered in an iframe. There `window.location` is
383
+ * the document's URL, not the router's, so without it the reset would
384
+ * rebuild the router's query string from the wrong URL: it would drop the
385
+ * router's non-grid params and add the document's. Use
386
+ * `() => history.location.search`, or the `getSearch` of a
387
+ * `createReactRouterV5Adapter` router.
388
+ */
389
+ getSearch?: () => string;
390
+ /** Writes the new query string. Called once, with `{ authoritative: true }`. */
391
+ historyReplace: (newSearch: string, options?: {
392
+ authoritative?: boolean;
393
+ }) => void;
394
+ }
362
395
  /**
363
396
  * Fully reset a `StatefulDataGrid` — clear localStorage for the given versions
364
397
  * and strip all grid-owned URL params (`_*` and `v=`), preserving any non-grid params.
365
398
  *
366
- * The function reads `window.location.search` directly so the strip always
367
- * operates on the live URL. This matters because consumers typically call this
368
- * from a component whose captured `search` snapshot may be stale — for example
369
- * when the grid has just written its own keys to the URL via the router adapter
370
- * but the parent hasn't re-rendered yet. Falling back to the supplied `search`
371
- * is only used in non-browser environments (SSR, unit tests without jsdom).
399
+ * The strip always operates on the live URL, because consumers typically call
400
+ * this from a component whose captured `search` snapshot may be stale — for
401
+ * example when the grid has just written its own keys to the URL via the
402
+ * router adapter but the parent hasn't re-rendered yet. The live URL is
403
+ * `getSearch()` when given, otherwise `window.location.search`. The supplied
404
+ * `search` is only used in non-browser environments (SSR, unit tests without
405
+ * jsdom).
406
+ *
407
+ * Under a browser router `window.location` is the router's URL. Under a memory
408
+ * history it is not, so pass `getSearch` (see `StatefulDataGridResetOptions`).
372
409
  *
373
410
  * The write is performed via `historyReplace(newSearch, { authoritative: true })`.
374
411
  * Adapters with delta/coalescing logic (e.g. `createReactRouterV5Adapter`)
@@ -381,20 +418,14 @@ declare const clearAllVersionStorage: (id: string, maxVersion: number) => void;
381
418
  * const { search, historyReplace } = useMyRouter();
382
419
  * resetStatefulDataGridState({ id: 'myGrid', versions: [0, 1, 2], search, historyReplace });
383
420
  * ```
421
+ *
422
+ * Under a memory history, with `createReactRouterV5Adapter`:
423
+ * ```ts
424
+ * const { pathname, getSearch, historyReplace } = useRouter();
425
+ * resetStatefulDataGridState({ id: pathname, versions: [0, 1], getSearch, historyReplace });
426
+ * ```
384
427
  */
385
- declare const resetStatefulDataGridState: ({ id, versions, search, historyReplace, }: {
386
- id: string;
387
- versions: number[];
388
- /**
389
- * Fallback search string used only when `window.location.search` is
390
- * unavailable (SSR, non-jsdom tests). In a browser the live URL is used
391
- * regardless of this value.
392
- */
393
- search: string;
394
- historyReplace: (newSearch: string, options?: {
395
- authoritative?: boolean;
396
- }) => void;
397
- }) => void;
428
+ declare const resetStatefulDataGridState: ({ id, versions, search, getSearch, historyReplace, }: StatefulDataGridResetOptions) => void;
398
429
  /**
399
430
  * Reset only the column-visibility state of a `StatefulDataGrid` back to its
400
431
  * default (all columns visible). Clears the persisted `visibilityModel`
@@ -408,9 +439,10 @@ declare const resetStatefulDataGridState: ({ id, versions, search, historyReplac
408
439
  * params alone it will not clobber a filter the caller is writing in the same
409
440
  * transition.
410
441
  *
411
- * Like `resetStatefulDataGridState`, the URL strip reads `window.location.search`
412
- * directly so it operates on the live URL (the caller's captured snapshot may
413
- * be stale), and writes via `historyReplace(newSearch, { authoritative: true })`.
442
+ * Like `resetStatefulDataGridState`, the URL strip operates on the live URL
443
+ * (the caller's captured snapshot may be stale): `getSearch()` when given,
444
+ * otherwise `window.location.search`. Pass `getSearch` under a memory history.
445
+ * It writes via `historyReplace(newSearch, { authoritative: true })`.
414
446
  *
415
447
  * This clears the *persisted* state only. The caller is responsible for
416
448
  * resetting the *live* grid in the same tick:
@@ -419,19 +451,7 @@ declare const resetStatefulDataGridState: ({ id, versions, search, historyReplac
419
451
  * apiRef.current?.setColumnVisibilityModel?.({});
420
452
  * ```
421
453
  */
422
- declare const resetColumnVisibility: ({ id, versions, search, historyReplace, }: {
423
- id: string;
424
- versions: number[];
425
- /**
426
- * Fallback search string used only when `window.location.search` is
427
- * unavailable (SSR, non-jsdom tests). In a browser the live URL is used
428
- * regardless of this value.
429
- */
430
- search: string;
431
- historyReplace: (newSearch: string, options?: {
432
- authoritative?: boolean;
433
- }) => void;
434
- }) => void;
454
+ declare const resetColumnVisibility: ({ id, versions, search, getSearch, historyReplace, }: StatefulDataGridResetOptions) => void;
435
455
 
436
456
  /**
437
457
  * Type for legacy array-based row selection (v7 and earlier)
@@ -811,16 +831,25 @@ interface StatefulDataGridProps extends DataGridProps {
811
831
  }
812
832
 
813
833
  /**
814
- * StatefulDataGrid extends DataGrid with automatic state persistence to localStorage.
815
- * Preserves filters, sorting, pagination, column visibility, and column widths
816
- * across page refreshes.
834
+ * StatefulDataGrid extends DataGrid with automatic state persistence to the URL and localStorage.
835
+ * Filters, sorting, pagination, column visibility, column order, pinned
836
+ * columns and density are written to the URL query string and to localStorage;
837
+ * column widths are kept in localStorage only. On load the URL wins, then
838
+ * localStorage, then `initialState`, so state survives page refreshes and a
839
+ * copied URL reopens the same view.
817
840
  *
818
- * Use when users need persistent table preferences. Requires unique `localStorageKey`.
841
+ * Use when users need persistent table preferences or shareable filtered views.
842
+ * Requires a `useRouter` hook returning `{ pathname, search, historyReplace }`
843
+ * (`createReactRouterV5Adapter` builds one from a React Router v5 `history`).
844
+ * State is stored in localStorage under the `pathname` it returns, and
845
+ * versioned by `localStorageVersion` (a number, default `1`).
819
846
  *
820
847
  * @example
821
- * // Basic stateful grid (persists to localStorage)
848
+ * // Basic stateful grid (URL + localStorage)
849
+ * const useRouter = createReactRouterV5Adapter(history);
850
+ *
822
851
  * <StatefulDataGrid
823
- * localStorageKey="users-table"
852
+ * useRouter={useRouter}
824
853
  * columns={columns}
825
854
  * rows={users}
826
855
  * pagination
@@ -829,34 +858,24 @@ interface StatefulDataGridProps extends DataGridProps {
829
858
  * @example
830
859
  * // With version migration (clears old preferences)
831
860
  * <StatefulDataGrid
832
- * localStorageKey="reports-table"
833
- * localStorageVersion="v2"
834
- * previousLocalStorageVersions={['v1']}
861
+ * useRouter={useRouter}
862
+ * localStorageVersion={2}
863
+ * previousLocalStorageVersions={[1]}
835
864
  * columns={columns}
836
865
  * rows={reports}
837
866
  * />
838
867
  *
839
868
  * @example
840
- * // With URL state sync (shareable filtered views)
841
- * <StatefulDataGrid
842
- * localStorageKey="domains-table"
843
- * useRouter={true}
844
- * columns={columns}
845
- * rows={domains}
846
- * pagination
847
- * />
848
- *
849
- * @example
850
869
  * // All features combined
851
870
  * <StatefulDataGrid
852
- * localStorageKey="audit-log"
853
- * localStorageVersion="v3"
854
- * previousLocalStorageVersions={['v1', 'v2']}
855
- * useRouter={true}
871
+ * useRouter={useRouter}
872
+ * localStorageVersion={3}
873
+ * previousLocalStorageVersions={[1, 2]}
856
874
  * columns={columns}
857
875
  * rows={logs}
858
876
  * pagination
859
- * pageSize={50}
877
+ * pageSizeOptions={[25, 50, 100]}
878
+ * initialState={{ pagination: { paginationModel: { page: 0, pageSize: 50 } } }}
860
879
  * checkboxSelection
861
880
  * />
862
881
  */
@@ -1060,6 +1079,14 @@ declare const areFilterModelsEquivalent: (filterModel: GridFilterModel, filterMo
1060
1079
  * `historyReplace`. Authoritative writes bypass the delta logic and write
1061
1080
  * synchronously to the live URL.
1062
1081
  *
1082
+ * The router also returns `getSearch`, which reads `history.location.search`
1083
+ * when it is called rather than when `useRouter()` ran. Pass it to
1084
+ * `resetStatefulDataGridState` and `resetColumnVisibility` so that they strip
1085
+ * the router's live URL. Under a memory history (`createMemoryHistory`, e.g.
1086
+ * a sift rendered in an iframe) this is required: without it they read
1087
+ * `window.location.search`, which is the document's URL and not the router's.
1088
+ * Its identity is stable for the adapter's lifetime.
1089
+ *
1063
1090
  * @example
1064
1091
  * ```tsx
1065
1092
  * import { createReactRouterV5Adapter } from '@redsift/table-pro';
@@ -1067,6 +1094,10 @@ declare const areFilterModelsEquivalent: (filterModel: GridFilterModel, filterMo
1067
1094
  * const useRouter = createReactRouterV5Adapter(history);
1068
1095
  *
1069
1096
  * <StatefulDataGrid useRouter={useRouter} … />
1097
+ *
1098
+ * // Reset, reading the router's URL (required under a memory history):
1099
+ * const { pathname, getSearch, historyReplace } = useRouter();
1100
+ * resetStatefulDataGridState({ id: pathname, versions: [0, 1], getSearch, historyReplace });
1070
1101
  * ```
1071
1102
  */
1072
1103
  /** Minimal subset of React Router v5 `history` used by the adapter. */
@@ -1087,6 +1118,8 @@ interface ReactRouterV5History {
1087
1118
  declare const createReactRouterV5Adapter: (history: ReactRouterV5History) => (() => {
1088
1119
  pathname: string;
1089
1120
  search: string;
1121
+ /** Reads the router's live query string, without the leading `?`. */
1122
+ getSearch: () => string;
1090
1123
  historyReplace: (newSearch: string, options?: {
1091
1124
  authoritative?: boolean;
1092
1125
  }) => void;
@@ -1370,4 +1403,4 @@ type ToolbarWrapperProps = {
1370
1403
  */
1371
1404
  declare const ToolbarWrapper: React$1.FC<ToolbarWrapperProps>;
1372
1405
 
1373
- export { ARRAY_IS_EMPTY, ARRAY_IS_NOT_EMPTY, BaseButton, BaseCheckbox, BaseIcon, BaseIconButton, BaseTextField, CATEGORIES, COLUMN_ORDER_MODEL_KEY, CONTAINS_ANY_OF, Category, ColumnOptions, ColumnOrderModel, ColumnType, CompletionResponse, ControlledPagination, ControlledPaginationProps, DATE_IS_BETWEEN, DEFAULT_OPERATORS, DENSITY_MODEL_KEY, DETAIL_PANEL_TOGGLE_COL_DEF, DIMENSION_MODEL_KEY, DOES_NOT_CONTAIN, DOES_NOT_CONTAIN_ANY_OF, DOES_NOT_END_WITH, DOES_NOT_END_WITH_ANY_OF, DOES_NOT_EQUAL, DOES_NOT_HAVE, DOES_NOT_HAVE_ANY_OF, DOES_NOT_HAVE_ANY_OF_WITH_SELECT, DOES_NOT_HAVE_WITH_SELECT, DOES_NOT_START_WITH, DOES_NOT_START_WITH_ANY_OF, DataGrid, DataGridModel, DataGridProps, DateOperatorName, EMPTY_ROW_SELECTION_MODEL, ENDS_WITH_ANY_OF, FILTER_MODEL_KEY, FILTER_SEARCH_KEY, FilterConfig, FilterConfigColumn, GridDensityValue, GridToolbarFilterSemanticField, GridToolbarFilterSemanticFieldProps, HAS, HAS_ALL_OF, HAS_ALL_OF_WITH_SELECT, HAS_ANY_OF, HAS_ANY_OF_WITH_SELECT, HAS_ONLY, HAS_ONLY_WITH_SELECT, HAS_WITH_SELECT, IS, IS_ANY_OF, IS_ANY_OF_I, IS_ANY_OF_I_WITH_SELECT, IS_ANY_OF_WITH_SELECT, IS_BETWEEN, IS_NOT, IS_NOT_ANY_OF, IS_NOT_ANY_OF_WITH_SELECT, IS_NOT_WITH_SELECT, IS_WITH_SELECT, LegacyRowSelectionModel, MultiSelectOperatorName, NumberOperatorName, PAGINATION_MODEL_KEY, PINNED_COLUMNS, PinnedColumns, ReactRouterV5History, RowSelectionModelInput, SORT_MODEL_KEY, STARTS_WITH_ANY_OF, SelectionStatus, ServerSideControlledPagination, ServerSideControlledPaginationProps, SingleSelectOperatorName, StatefulDataGrid, StatefulDataGridProps, StringOperatorName, StyledDataGridProps, TagsOperatorName, TextCell, Toolbar, ToolbarWrapper, ToolbarWrapperProps, UseLinkedFilterModelOptions, UseLinkedFilterModelReturn, VISIBILITY_MODEL_KEY, areFilterModelsEquivalent, areSearchStringsEqual, buildQueryParamsString, buildStorageKey, clearAllVersionStorage, clearPreviousVersionStorage, convertFromDisplayFormat, convertToDisplayFormat, createColumn, createReactRouterV5Adapter, createRowSelectionModel, customColumnTypes, decodeValue, encodeValue, fixServerSideHeaderCheckboxSelection, getColumnOrderFromString, getColumnVisibilityFromString, getCompletion, getDecodedSearchFromUrl, getDensityFromString, getDensityModel, getFilterModelFromString, getFinalSearch, getGridDateOperatorsExtended, getGridNumericOperators, getGridStringArrayOperators, getGridStringArrayOperatorsWithSelect, getGridStringArrayOperatorsWithSelectOnStringArrayColumns, getGridStringOperators, getModelsParsedOrUpdateLocalStorage, getPaginationFromString, getPinnedColumnsFromString, getRsMultipleSelectColumnType, getRsMultipleSelectWithShortOperatorListColumnType, getRsNumberColumnType, getRsSingleSelectColumnType, getRsSingleSelectWithShortOperatorListColumnType, getRsStringColumnType, getSearchParamsFromColumnOrder, getSearchParamsFromColumnVisibility, getSearchParamsFromDensity, getSearchParamsFromFilterModel, getSearchParamsFromPagination, getSearchParamsFromPinnedColumns, getSearchParamsFromSorting, getSearchParamsFromTab, getSearchParamsFromVersion, getSelectableRowIdsInPage, getSelectedIds, getSelectionCount, getSortingFromString, isOperatorValueValid, isRowSelected, isValueValid, makeCaseInsensitive, muiIconToDSIcon, normalizeDateValue, normalizeRowSelectionModel, numberOperatorDecoder, numberOperatorEncoder, onServerSideSelectionStatusChange, operatorList, resetColumnVisibility, resetStatefulDataGridState, updateUrl, urlSearchParamsToString, useLinkedFilterModel, wrapCaseInsensitive };
1406
+ export { ARRAY_IS_EMPTY, ARRAY_IS_NOT_EMPTY, BaseButton, BaseCheckbox, BaseIcon, BaseIconButton, BaseTextField, CATEGORIES, COLUMN_ORDER_MODEL_KEY, CONTAINS_ANY_OF, Category, ColumnOptions, ColumnOrderModel, ColumnType, CompletionResponse, ControlledPagination, ControlledPaginationProps, DATE_IS_BETWEEN, DEFAULT_OPERATORS, DENSITY_MODEL_KEY, DETAIL_PANEL_TOGGLE_COL_DEF, DIMENSION_MODEL_KEY, DOES_NOT_CONTAIN, DOES_NOT_CONTAIN_ANY_OF, DOES_NOT_END_WITH, DOES_NOT_END_WITH_ANY_OF, DOES_NOT_EQUAL, DOES_NOT_HAVE, DOES_NOT_HAVE_ANY_OF, DOES_NOT_HAVE_ANY_OF_WITH_SELECT, DOES_NOT_HAVE_WITH_SELECT, DOES_NOT_START_WITH, DOES_NOT_START_WITH_ANY_OF, DataGrid, DataGridModel, DataGridProps, DateOperatorName, EMPTY_ROW_SELECTION_MODEL, ENDS_WITH_ANY_OF, FILTER_MODEL_KEY, FILTER_SEARCH_KEY, FilterConfig, FilterConfigColumn, GridDensityValue, GridToolbarFilterSemanticField, GridToolbarFilterSemanticFieldProps, HAS, HAS_ALL_OF, HAS_ALL_OF_WITH_SELECT, HAS_ANY_OF, HAS_ANY_OF_WITH_SELECT, HAS_ONLY, HAS_ONLY_WITH_SELECT, HAS_WITH_SELECT, IS, IS_ANY_OF, IS_ANY_OF_I, IS_ANY_OF_I_WITH_SELECT, IS_ANY_OF_WITH_SELECT, IS_BETWEEN, IS_NOT, IS_NOT_ANY_OF, IS_NOT_ANY_OF_WITH_SELECT, IS_NOT_WITH_SELECT, IS_WITH_SELECT, LegacyRowSelectionModel, MultiSelectOperatorName, NumberOperatorName, PAGINATION_MODEL_KEY, PINNED_COLUMNS, PinnedColumns, ReactRouterV5History, RowSelectionModelInput, SORT_MODEL_KEY, STARTS_WITH_ANY_OF, SelectionStatus, ServerSideControlledPagination, ServerSideControlledPaginationProps, SingleSelectOperatorName, StatefulDataGrid, StatefulDataGridProps, StatefulDataGridResetOptions, StringOperatorName, StyledDataGridProps, TagsOperatorName, TextCell, Toolbar, ToolbarWrapper, ToolbarWrapperProps, UseLinkedFilterModelOptions, UseLinkedFilterModelReturn, VISIBILITY_MODEL_KEY, areFilterModelsEquivalent, areSearchStringsEqual, buildQueryParamsString, buildStorageKey, clearAllVersionStorage, clearPreviousVersionStorage, convertFromDisplayFormat, convertToDisplayFormat, createColumn, createReactRouterV5Adapter, createRowSelectionModel, customColumnTypes, decodeValue, encodeValue, fixServerSideHeaderCheckboxSelection, getColumnOrderFromString, getColumnVisibilityFromString, getCompletion, getDecodedSearchFromUrl, getDensityFromString, getDensityModel, getFilterModelFromString, getFinalSearch, getGridDateOperatorsExtended, getGridNumericOperators, getGridStringArrayOperators, getGridStringArrayOperatorsWithSelect, getGridStringArrayOperatorsWithSelectOnStringArrayColumns, getGridStringOperators, getModelsParsedOrUpdateLocalStorage, getPaginationFromString, getPinnedColumnsFromString, getRsMultipleSelectColumnType, getRsMultipleSelectWithShortOperatorListColumnType, getRsNumberColumnType, getRsSingleSelectColumnType, getRsSingleSelectWithShortOperatorListColumnType, getRsStringColumnType, getSearchParamsFromColumnOrder, getSearchParamsFromColumnVisibility, getSearchParamsFromDensity, getSearchParamsFromFilterModel, getSearchParamsFromPagination, getSearchParamsFromPinnedColumns, getSearchParamsFromSorting, getSearchParamsFromTab, getSearchParamsFromVersion, getSelectableRowIdsInPage, getSelectedIds, getSelectionCount, getSortingFromString, isOperatorValueValid, isRowSelected, isValueValid, makeCaseInsensitive, muiIconToDSIcon, normalizeDateValue, normalizeRowSelectionModel, numberOperatorDecoder, numberOperatorEncoder, onServerSideSelectionStatusChange, operatorList, resetColumnVisibility, resetStatefulDataGridState, updateUrl, urlSearchParamsToString, useLinkedFilterModel, wrapCaseInsensitive };
package/index.js CHANGED
@@ -441,6 +441,14 @@ function getOperatorsForType(type, compact) {
441
441
  * `historyReplace`. Authoritative writes bypass the delta logic and write
442
442
  * synchronously to the live URL.
443
443
  *
444
+ * The router also returns `getSearch`, which reads `history.location.search`
445
+ * when it is called rather than when `useRouter()` ran. Pass it to
446
+ * `resetStatefulDataGridState` and `resetColumnVisibility` so that they strip
447
+ * the router's live URL. Under a memory history (`createMemoryHistory`, e.g.
448
+ * a sift rendered in an iframe) this is required: without it they read
449
+ * `window.location.search`, which is the document's URL and not the router's.
450
+ * Its identity is stable for the adapter's lifetime.
451
+ *
444
452
  * @example
445
453
  * ```tsx
446
454
  * import { createReactRouterV5Adapter } from '@redsift/table-pro';
@@ -448,6 +456,10 @@ function getOperatorsForType(type, compact) {
448
456
  * const useRouter = createReactRouterV5Adapter(history);
449
457
  *
450
458
  * <StatefulDataGrid useRouter={useRouter} … />
459
+ *
460
+ * // Reset, reading the router's URL (required under a memory history):
461
+ * const { pathname, getSearch, historyReplace } = useRouter();
462
+ * resetStatefulDataGridState({ id: pathname, versions: [0, 1], getSearch, historyReplace });
451
463
  * ```
452
464
  */
453
465
 
@@ -481,18 +493,23 @@ const createReactRouterV5Adapter = history => {
481
493
  });
482
494
  });
483
495
  };
496
+
497
+ // Read at call time, unlike the `search` snapshot below. Defined once so its
498
+ // identity is stable across renders.
499
+ const getSearch = () => history.location.search.replace(/^\?/, '');
484
500
  return () => {
485
501
  // Capture the search snapshot AT THE TIME useRouter() is called. The
486
502
  // grid hands this string to its change handlers, which build a complete
487
503
  // new search string from it. Diffing the handler's `newSearch` against
488
504
  // this captured snapshot tells us which keys the handler intentionally
489
505
  // changed (vs. which are stale passthrough from sibling handlers' models).
490
- const captured = history.location.search.replace(/^\?/, '');
506
+ const captured = getSearch();
491
507
  const capturedParams = new URLSearchParams(captured);
492
508
  const capturedKeys = new Set(capturedParams.keys());
493
509
  return {
494
510
  pathname: history.location.pathname,
495
511
  search: captured,
512
+ getSearch,
496
513
  historyReplace: (newSearch, options) => {
497
514
  // Authoritative writes (e.g. `resetStatefulDataGridState`) bypass the
498
515
  // delta-vs-captured-snapshot logic. The caller asserts that `newSearch`