@redsift/table-pro 12.5.8-muiv8-alpha.3 → 12.5.8
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.
|
@@ -1510,7 +1510,7 @@ const isValueValid = (value, field, columns, operator) => {
|
|
|
1510
1510
|
|
|
1511
1511
|
// example:
|
|
1512
1512
|
// unicodeDomain[contains]=a&unicodeDomain[contains]=dsa&logicOperator=and&tab=ignored
|
|
1513
|
-
const getFilterModelFromString = (searchString, columns) => {
|
|
1513
|
+
const getFilterModelFromString = (searchString, columns, previousModel) => {
|
|
1514
1514
|
if (!searchString) {
|
|
1515
1515
|
return 'invalid';
|
|
1516
1516
|
}
|
|
@@ -1540,6 +1540,21 @@ const getFilterModelFromString = (searchString, columns) => {
|
|
|
1540
1540
|
}
|
|
1541
1541
|
}
|
|
1542
1542
|
let id = 5000;
|
|
1543
|
+
|
|
1544
|
+
// Positional id-reuse map keyed by `${field}|${operator}` (decoded operator, matching
|
|
1545
|
+
// the item we push below). FIFO per key so duplicate field+operator items map by order.
|
|
1546
|
+
// Reusing the id of a previously parsed/emitted item keeps `item.id` stable across the
|
|
1547
|
+
// URL write→parse roundtrip (the URL never carries the id), so MUI's GridFilterForm
|
|
1548
|
+
// React key does not change and the filter panel input keeps focus. (DS-81)
|
|
1549
|
+
const previousIdsByKey = new Map();
|
|
1550
|
+
if (previousModel) {
|
|
1551
|
+
for (const prev of previousModel.items) {
|
|
1552
|
+
if (prev.id === undefined) continue;
|
|
1553
|
+
const key = `${prev.field}|${prev.operator}`;
|
|
1554
|
+
const bucket = previousIdsByKey.get(key);
|
|
1555
|
+
if (bucket) bucket.push(prev.id);else previousIdsByKey.set(key, [prev.id]);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1543
1558
|
const fields = columns.map(column => column.field);
|
|
1544
1559
|
let isInvalid = false;
|
|
1545
1560
|
const items = [];
|
|
@@ -1575,10 +1590,13 @@ const getFilterModelFromString = (searchString, columns) => {
|
|
|
1575
1590
|
isInvalid = true;
|
|
1576
1591
|
return;
|
|
1577
1592
|
}
|
|
1593
|
+
const finalOperator = columnType === 'number' && Object.keys(numberOperatorDecoder).includes(operator) ? numberOperatorDecoder[operator] : operator;
|
|
1594
|
+
const reuseBucket = previousIdsByKey.get(`${field}|${finalOperator}`);
|
|
1595
|
+
const stableId = reuseBucket && reuseBucket.length > 0 ? reuseBucket.shift() : id;
|
|
1578
1596
|
items.push({
|
|
1579
1597
|
field,
|
|
1580
|
-
operator:
|
|
1581
|
-
id,
|
|
1598
|
+
operator: finalOperator,
|
|
1599
|
+
id: stableId,
|
|
1582
1600
|
value: listOperators.includes(operator) && decodedValue === '' ? [] : decodedValue,
|
|
1583
1601
|
type
|
|
1584
1602
|
});
|
|
@@ -1672,7 +1690,7 @@ const getSearchParamsFromFilterModel = filterModel => {
|
|
|
1672
1690
|
// - if we have something in the URL, use that info
|
|
1673
1691
|
// - if we don't have that, use the localStorage and update the URL
|
|
1674
1692
|
// - if we don't have that, return an empty FilterModel
|
|
1675
|
-
const getFilterModel = (search, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion) => {
|
|
1693
|
+
const getFilterModel = (search, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion, previousModel) => {
|
|
1676
1694
|
const defaultValue = initialState && initialState.filter && initialState.filter.filterModel ? initialState.filter.filterModel : {
|
|
1677
1695
|
items: [],
|
|
1678
1696
|
logicOperator: GridLogicOperator.And
|
|
@@ -1690,7 +1708,7 @@ const getFilterModel = (search, columns, localStorageFilters, setLocalStorageFil
|
|
|
1690
1708
|
persistDefaultFilters();
|
|
1691
1709
|
return defaultValue;
|
|
1692
1710
|
}
|
|
1693
|
-
const filterModelFromSearch = getFilterModelFromString(search, columns);
|
|
1711
|
+
const filterModelFromSearch = getFilterModelFromString(search, columns, previousModel);
|
|
1694
1712
|
if (filterModelFromSearch !== 'invalid') {
|
|
1695
1713
|
const searchFromFilterModel = getSearchParamsFromFilterModel(filterModelFromSearch);
|
|
1696
1714
|
const searchString = urlSearchParamsToString(searchFromFilterModel);
|
|
@@ -2279,7 +2297,7 @@ const getFinalSearch = _ref => {
|
|
|
2279
2297
|
return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch]);
|
|
2280
2298
|
};
|
|
2281
2299
|
/** Return the state of the table given the URL and the local storage state */
|
|
2282
|
-
const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage) => {
|
|
2300
|
+
const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage, previousFilterModel) => {
|
|
2283
2301
|
var _initialState$columns6, _initialState$columns7;
|
|
2284
2302
|
// Decompress any compressed params in the search string before processing
|
|
2285
2303
|
const decompressedSearch = decompressSearchParams(search);
|
|
@@ -2318,7 +2336,7 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
|
|
|
2318
2336
|
localStorageColumnOrder,
|
|
2319
2337
|
setLocalStorageColumnOrder
|
|
2320
2338
|
} = localStorage;
|
|
2321
|
-
const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion);
|
|
2339
|
+
const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion, previousFilterModel);
|
|
2322
2340
|
const sortModel = getSortModel(decodedSearch, columns, localStorageSorting, setLocalStorageSorting, initialState, isNewVersion);
|
|
2323
2341
|
const paginationModel = getPaginationModel(decodedSearch, localStoragePagination, setLocalStoragePagination, initialState, isNewVersion);
|
|
2324
2342
|
const columnVisibilityModel = getColumnsVisibility(decodedSearch, columns, localStorageColumnsVisibility, setLocalStorageColumnsVisibility, initialState, isNewVersion);
|
|
@@ -2665,6 +2683,11 @@ const useStatefulTable = props => {
|
|
|
2665
2683
|
[field]: newWidth
|
|
2666
2684
|
}));
|
|
2667
2685
|
}, [dimensionModel, setDimensionModel]);
|
|
2686
|
+
|
|
2687
|
+
// Source of ids for content-matching in the parser, so item.id is stable across the
|
|
2688
|
+
// URL write→parse roundtrip (DS-81). Holds MUI's just-emitted model (random placeholder
|
|
2689
|
+
// id) after onFilterModelChange, then the stabilised parsed model each render.
|
|
2690
|
+
const filterIdSourceRef = useRef(undefined);
|
|
2668
2691
|
const {
|
|
2669
2692
|
filterModel: filterParsed,
|
|
2670
2693
|
sortModel: sortModelParsed,
|
|
@@ -2689,7 +2712,7 @@ const useStatefulTable = props => {
|
|
|
2689
2712
|
setLocalStorageDensity: setDensityModel,
|
|
2690
2713
|
localStorageColumnOrder,
|
|
2691
2714
|
setLocalStorageColumnOrder
|
|
2692
|
-
});
|
|
2715
|
+
}, filterIdSourceRef.current);
|
|
2693
2716
|
|
|
2694
2717
|
// Sync URL in an effect rather than during render to comply with React rules
|
|
2695
2718
|
useEffect(() => {
|
|
@@ -2704,6 +2727,10 @@ const useStatefulTable = props => {
|
|
|
2704
2727
|
if (!isDeepEqual(filterParsedRef.current, filterParsed)) {
|
|
2705
2728
|
filterParsedRef.current = filterParsed;
|
|
2706
2729
|
}
|
|
2730
|
+
// Keep the id source in sync with the stabilised parsed model so re-parses triggered
|
|
2731
|
+
// by unrelated state (pagination/sort/visibility) reuse the same ids (DS-81). The parse
|
|
2732
|
+
// call above reads the ref before this write (read-before-write within the render).
|
|
2733
|
+
filterIdSourceRef.current = filterParsed;
|
|
2707
2734
|
const sortModelParsedRef = useRef(sortModelParsed);
|
|
2708
2735
|
if (!isDeepEqual(sortModelParsedRef.current, sortModelParsed)) {
|
|
2709
2736
|
sortModelParsedRef.current = sortModelParsed;
|
|
@@ -2827,6 +2854,10 @@ const useStatefulTable = props => {
|
|
|
2827
2854
|
});
|
|
2828
2855
|
if (isDeepEqual(filterModel, lastEmittedFilterRef.current)) return;
|
|
2829
2856
|
lastEmittedFilterRef.current = filterModel;
|
|
2857
|
+
// Capture MUI's just-emitted model (carrying the placeholder's random id) so the
|
|
2858
|
+
// next render's URL re-parse reuses that id and the GridFilterForm key — and thus
|
|
2859
|
+
// the value input's focus — survives the write→parse roundtrip (DS-81).
|
|
2860
|
+
filterIdSourceRef.current = filterModel;
|
|
2830
2861
|
updateUrl(buildModel({
|
|
2831
2862
|
filterModel
|
|
2832
2863
|
}), search, localStorageVersion, historyReplace, columns);
|