@redsift/table 12.6.6-alpha.2 → 13.0.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.
@@ -1,6 +1,6 @@
1
1
  import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends } from './_rollupPluginBabelHelpers.js';
2
2
  import * as React from 'react';
3
- import React__default, { useCallback, useEffect, useRef, useMemo, forwardRef, useState } from 'react';
3
+ import React__default, { useCallback, useRef, useEffect, useMemo, forwardRef, useState } from 'react';
4
4
  import { createTheme, ThemeProvider as ThemeProvider$1 } from '@mui/material/styles';
5
5
  import classNames from 'classnames';
6
6
  import { LicenseInfo } from '@mui/x-license';
@@ -22,7 +22,7 @@ const InputNumberInterval = props => {
22
22
  applyValue,
23
23
  focusElementRef = null
24
24
  } = props;
25
- const filterTimeout = React.useRef();
25
+ const filterTimeout = React.useRef(undefined);
26
26
  const [filterValueState, setFilterValueState] = React.useState((_item$value = item.value) !== null && _item$value !== void 0 ? _item$value : '');
27
27
  const [applying, setIsApplying] = React.useState(false);
28
28
  React.useEffect(() => {
@@ -3075,6 +3075,11 @@ function isDeepEqual(a, b) {
3075
3075
  if (aKeys.length !== bKeys.length) return false;
3076
3076
  return aKeys.every(key => isDeepEqual(aObj[key], bObj[key]));
3077
3077
  }
3078
+
3079
+ /** The models one change writes to the URL; everything else comes from the current state. */
3080
+
3081
+ /** What this hook has written to the URL since the router last reported a new `search`. */
3082
+
3078
3083
  const useStatefulTable = props => {
3079
3084
  var _initialState$columns, _initialState$columns2;
3080
3085
  const {
@@ -3099,6 +3104,19 @@ const useStatefulTable = props => {
3099
3104
  pathname,
3100
3105
  historyReplace
3101
3106
  } = useRouter();
3107
+
3108
+ // What this hook has written to the URL since the router last reported a new `search`. Every write
3109
+ // rebuilds the whole URL, so a second change in the same tick, before the router re-renders the grid
3110
+ // with the first, would otherwise start again from the models parsed at this render and drop the
3111
+ // first: `apiRef.setPivotModel(m)` then `setPivotActive(true)` left pivot on with an empty model.
3112
+ // `written` is the URL of the last write: the router has not reported it yet, so it is what the next write
3113
+ // compares itself with (`updateUrl` skips a write that equals the URL it is given), not the `search` this
3114
+ // render saw. A new `search` means the parse below already reflects those writes: `writeUrl` starts over.
3115
+ const pendingWritesRef = useRef({
3116
+ search,
3117
+ overrides: {},
3118
+ written: null
3119
+ });
3102
3120
  const id = pathname;
3103
3121
 
3104
3122
  // States and setters persisted in the local storage for this table
@@ -3246,6 +3264,46 @@ const useStatefulTable = props => {
3246
3264
  }
3247
3265
  const defaultColumnOrder = (_initialState$columns = initialState === null || initialState === void 0 ? void 0 : (_initialState$columns2 = initialState.columns) === null || _initialState$columns2 === void 0 ? void 0 : _initialState$columns2.orderedFields) !== null && _initialState$columns !== void 0 ? _initialState$columns : propsColumns.map(c => c.field);
3248
3266
 
3267
+ // Helper to build the current DataGridModel for updateUrl calls
3268
+ const buildModel = function () {
3269
+ var _apiRef$current$state, _apiRef$current2;
3270
+ let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3271
+ return _objectSpread2({
3272
+ filterModel: filterParsed,
3273
+ sortModel: sortModelParsed,
3274
+ paginationModel: paginationModelParsed,
3275
+ columnsModel: (_apiRef$current$state = (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.state.columns.columnVisibilityModel) !== null && _apiRef$current$state !== void 0 ? _apiRef$current$state : {},
3276
+ pinnedColumnsModel: pinnedColumnsModel,
3277
+ density: densityParsed,
3278
+ columnOrderModel: columnOrderParsed,
3279
+ defaultColumnOrder,
3280
+ rowGroupingModel: rowGroupingParsed,
3281
+ aggregationModel: aggregationParsed,
3282
+ pivotModel: pivotParsed,
3283
+ pivotActive: pivotActiveParsed
3284
+ }, overrides);
3285
+ };
3286
+
3287
+ // Writes the URL: the current models, what this hook has written since the last new `search`, then
3288
+ // this change (see pendingWritesRef).
3289
+ const writeUrl = overrides => {
3290
+ var _pending$written;
3291
+ // Decided here, when a change happens, not while rendering: a render React discards must not reset it.
3292
+ if (pendingWritesRef.current.search !== search) {
3293
+ pendingWritesRef.current = {
3294
+ search,
3295
+ overrides: {},
3296
+ written: null
3297
+ };
3298
+ }
3299
+ const pending = pendingWritesRef.current;
3300
+ pending.overrides = _objectSpread2(_objectSpread2({}, pending.overrides), overrides);
3301
+ updateUrl(buildModel(pending.overrides), (_pending$written = pending.written) !== null && _pending$written !== void 0 ? _pending$written : search, localStorageVersion, newSearch => {
3302
+ pending.written = newSearch;
3303
+ historyReplace(newSearch);
3304
+ }, columns);
3305
+ };
3306
+
3249
3307
  // Subscribe to density changes via stateChange event (MUI v6 has no densityChange event)
3250
3308
  useEffect(() => {
3251
3309
  const api = apiRef.current;
@@ -3255,20 +3313,9 @@ const useStatefulTable = props => {
3255
3313
  const currentDensity = api.state.density;
3256
3314
  if (currentDensity !== prevDensity) {
3257
3315
  prevDensity = currentDensity;
3258
- updateUrl({
3259
- filterModel: filterParsed,
3260
- sortModel: sortModelParsed,
3261
- paginationModel: paginationModelParsed,
3262
- columnsModel: api.state.columns.columnVisibilityModel,
3263
- pinnedColumnsModel: pinnedColumnsModel,
3264
- density: currentDensity,
3265
- columnOrderModel: columnOrderParsed,
3266
- defaultColumnOrder,
3267
- rowGroupingModel: rowGroupingParsed,
3268
- aggregationModel: aggregationParsed,
3269
- pivotModel: pivotParsed,
3270
- pivotActive: pivotActiveParsed
3271
- }, search, localStorageVersion, historyReplace, columns);
3316
+ writeUrl({
3317
+ density: currentDensity
3318
+ });
3272
3319
  }
3273
3320
  });
3274
3321
  return unsub;
@@ -3281,20 +3328,9 @@ const useStatefulTable = props => {
3281
3328
  const handleColumnOrderChange = () => {
3282
3329
  const orderedFields = api.state.columns.orderedFields;
3283
3330
  if (orderedFields && !isDeepEqual(orderedFields, columnOrderParsed)) {
3284
- updateUrl({
3285
- filterModel: filterParsed,
3286
- sortModel: sortModelParsed,
3287
- paginationModel: paginationModelParsed,
3288
- columnsModel: api.state.columns.columnVisibilityModel,
3289
- pinnedColumnsModel,
3290
- density: densityParsed,
3291
- columnOrderModel: orderedFields,
3292
- defaultColumnOrder,
3293
- rowGroupingModel: rowGroupingParsed,
3294
- aggregationModel: aggregationParsed,
3295
- pivotModel: pivotParsed,
3296
- pivotActive: pivotActiveParsed
3297
- }, search, localStorageVersion, historyReplace, columns);
3331
+ writeUrl({
3332
+ columnOrderModel: orderedFields
3333
+ });
3298
3334
  }
3299
3335
  };
3300
3336
  const unsub1 = api.subscribeEvent('columnOrderChange', handleColumnOrderChange);
@@ -3305,26 +3341,6 @@ const useStatefulTable = props => {
3305
3341
  };
3306
3342
  }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, rowGroupingParsed, aggregationParsed, pivotParsed, pivotActiveParsed, search, localStorageVersion, historyReplace, columns]);
3307
3343
 
3308
- // Helper to build the current DataGridModel for updateUrl calls
3309
- const buildModel = function () {
3310
- var _apiRef$current$state, _apiRef$current2;
3311
- let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3312
- return _objectSpread2({
3313
- filterModel: filterParsed,
3314
- sortModel: sortModelParsed,
3315
- paginationModel: paginationModelParsed,
3316
- columnsModel: (_apiRef$current$state = (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.state.columns.columnVisibilityModel) !== null && _apiRef$current$state !== void 0 ? _apiRef$current$state : {},
3317
- pinnedColumnsModel: pinnedColumnsModel,
3318
- density: densityParsed,
3319
- columnOrderModel: columnOrderParsed,
3320
- defaultColumnOrder,
3321
- rowGroupingModel: rowGroupingParsed,
3322
- aggregationModel: aggregationParsed,
3323
- pivotModel: pivotParsed,
3324
- pivotActive: pivotActiveParsed
3325
- }, overrides);
3326
- };
3327
-
3328
3344
  // Stable GridPivotModel identity — only recompute when the simplified value changes.
3329
3345
  // eslint-disable-next-line react-hooks/exhaustive-deps
3330
3346
  const pivotModelMui = useMemo(() => toGridPivotModel(pivotParsed), [JSON.stringify(pivotParsed)]);
@@ -3360,18 +3376,18 @@ const useStatefulTable = props => {
3360
3376
  // next render's URL re-parse reuses that id and the GridFilterForm key — and thus
3361
3377
  // the value input's focus — survives the write→parse roundtrip (DS-81).
3362
3378
  filterIdSourceRef.current = filterModel;
3363
- updateUrl(buildModel({
3379
+ writeUrl({
3364
3380
  filterModel
3365
- }), search, localStorageVersion, historyReplace, columns);
3381
+ });
3366
3382
  propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
3367
3383
  },
3368
3384
  filterModel: filterParsedRef.current,
3369
3385
  onSortModelChange: (model, details) => {
3370
3386
  if (isDeepEqual(model, lastEmittedSortRef.current)) return;
3371
3387
  lastEmittedSortRef.current = model;
3372
- updateUrl(buildModel({
3388
+ writeUrl({
3373
3389
  sortModel: model
3374
- }), search, localStorageVersion, historyReplace, columns);
3390
+ });
3375
3391
  propsOnSortModelChange === null || propsOnSortModelChange === void 0 ? void 0 : propsOnSortModelChange(model, details);
3376
3392
  },
3377
3393
  sortModel: sortModelParsedRef.current,
@@ -3385,9 +3401,9 @@ const useStatefulTable = props => {
3385
3401
  // callbacks are always forwarded so observers can still react.
3386
3402
  const pivotActiveLive = (_apiRef$current$state2 = (_apiRef$current4 = apiRef.current) === null || _apiRef$current4 === void 0 ? void 0 : (_apiRef$current4$stat = _apiRef$current4.state) === null || _apiRef$current4$stat === void 0 ? void 0 : (_apiRef$current4$stat2 = _apiRef$current4$stat.pivoting) === null || _apiRef$current4$stat2 === void 0 ? void 0 : _apiRef$current4$stat2.active) !== null && _apiRef$current$state2 !== void 0 ? _apiRef$current$state2 : pivotActiveParsed;
3387
3403
  if (!pivotActiveLive) {
3388
- updateUrl(buildModel({
3404
+ writeUrl({
3389
3405
  pinnedColumnsModel: pinnedColumns
3390
- }), search, localStorageVersion, historyReplace, columns);
3406
+ });
3391
3407
  }
3392
3408
  propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
3393
3409
  },
@@ -3399,9 +3415,9 @@ const useStatefulTable = props => {
3399
3415
  });
3400
3416
  if (isDeepEqual(paginationModel, lastEmittedPaginationRef.current)) return;
3401
3417
  lastEmittedPaginationRef.current = paginationModel;
3402
- updateUrl(buildModel({
3418
+ writeUrl({
3403
3419
  paginationModel
3404
- }), search, localStorageVersion, historyReplace, columns);
3420
+ });
3405
3421
  propsOnPaginationModelChange === null || propsOnPaginationModelChange === void 0 ? void 0 : propsOnPaginationModelChange(paginationModel, details);
3406
3422
  },
3407
3423
  columnVisibilityModel: visibilityModelRef.current,
@@ -3416,9 +3432,9 @@ const useStatefulTable = props => {
3416
3432
  // callbacks are always forwarded.
3417
3433
  const pivotActiveLive = (_apiRef$current$state3 = (_apiRef$current5 = apiRef.current) === null || _apiRef$current5 === void 0 ? void 0 : (_apiRef$current5$stat = _apiRef$current5.state) === null || _apiRef$current5$stat === void 0 ? void 0 : (_apiRef$current5$stat2 = _apiRef$current5$stat.pivoting) === null || _apiRef$current5$stat2 === void 0 ? void 0 : _apiRef$current5$stat2.active) !== null && _apiRef$current$state3 !== void 0 ? _apiRef$current$state3 : pivotActiveParsed;
3418
3434
  if (!pivotActiveLive) {
3419
- updateUrl(buildModel({
3435
+ writeUrl({
3420
3436
  columnsModel: columnsVisibilityModel
3421
- }), search, localStorageVersion, historyReplace, columns);
3437
+ });
3422
3438
  }
3423
3439
  propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
3424
3440
  },
@@ -3430,31 +3446,31 @@ const useStatefulTable = props => {
3430
3446
  });
3431
3447
  },
3432
3448
  onRowGroupingModelChange: (model, details) => {
3433
- updateUrl(buildModel({
3449
+ writeUrl({
3434
3450
  rowGroupingModel: model
3435
- }), search, localStorageVersion, historyReplace, columns);
3451
+ });
3436
3452
  propsOnRowGroupingModelChange === null || propsOnRowGroupingModelChange === void 0 ? void 0 : propsOnRowGroupingModelChange(model, details);
3437
3453
  },
3438
3454
  onAggregationModelChange: (model, details) => {
3439
- updateUrl(buildModel({
3455
+ writeUrl({
3440
3456
  aggregationModel: model
3441
- }), search, localStorageVersion, historyReplace, columns);
3457
+ });
3442
3458
  propsOnAggregationModelChange === null || propsOnAggregationModelChange === void 0 ? void 0 : propsOnAggregationModelChange(model, details);
3443
3459
  },
3444
3460
  onPivotModelChange: model => {
3445
3461
  const simplified = fromGridPivotModel(model);
3446
3462
  if (isDeepEqual(simplified, lastEmittedPivotRef.current)) return;
3447
3463
  lastEmittedPivotRef.current = simplified;
3448
- updateUrl(buildModel({
3464
+ writeUrl({
3449
3465
  pivotModel: simplified
3450
- }), search, localStorageVersion, historyReplace, columns);
3466
+ });
3451
3467
  propsOnPivotModelChange === null || propsOnPivotModelChange === void 0 ? void 0 : propsOnPivotModelChange(model);
3452
3468
  },
3453
3469
  onPivotActiveChange: active => {
3454
3470
  if (active === pivotActiveParsed) return;
3455
- updateUrl(buildModel({
3471
+ writeUrl({
3456
3472
  pivotActive: active
3457
- }), search, localStorageVersion, historyReplace, columns);
3473
+ });
3458
3474
  }
3459
3475
  };
3460
3476
  };
@@ -3515,7 +3531,7 @@ const CLASSNAME = 'redsift-datagrid';
3515
3531
 
3516
3532
  const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3517
3533
  var _ref7;
3518
- const datagridRef = ref || useRef();
3534
+ const datagridRef = ref || useRef(undefined);
3519
3535
  const {
3520
3536
  apiRef: propsApiRef,
3521
3537
  autoHeight,
@@ -3574,8 +3590,10 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3574
3590
  // write-only onChange handlers for URL/localStorage persistence.
3575
3591
  const isDataSourceMode = Boolean(dataSource);
3576
3592
  const effectivePaginationMode = isDataSourceMode ? 'server' : paginationMode;
3577
- const effectiveFilterMode = isDataSourceMode ? 'server' : propsFilterMode;
3578
- const effectiveSortingMode = isDataSourceMode ? 'server' : propsSortingMode;
3593
+ // Default to 'client' rather than pass `undefined`: an explicit undefined replaces MUI's own default,
3594
+ // and MUI filters rows only when `filterMode === 'client'`, so no client-side filter ever applied.
3595
+ const effectiveFilterMode = isDataSourceMode ? 'server' : propsFilterMode !== null && propsFilterMode !== void 0 ? propsFilterMode : 'client';
3596
+ const effectiveSortingMode = isDataSourceMode ? 'server' : propsSortingMode !== null && propsSortingMode !== void 0 ? propsSortingMode : 'client';
3579
3597
  const {
3580
3598
  onColumnVisibilityModelChange: controlledOnColumnVisibilityModelChange,
3581
3599
  onFilterModelChange: controlledOnFilterModelChange,