@trackunit/filters-filter-bar 1.3.66 → 1.3.68

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.cjs.js CHANGED
@@ -1422,35 +1422,50 @@ const getPersistenceKey = (name, clientSideUserId) => `filter-${name}-${clientSi
1422
1422
  const useFilterBarPersistence = ({ name, setValue, }) => {
1423
1423
  const { clientSideUserId } = reactCoreHooks.useCurrentUser();
1424
1424
  const [initialStoredFilters] = react.useState(() => localStorage.getItem(getPersistenceKey(name, clientSideUserId)) || "{}");
1425
- const saveData = react.useCallback((filterBarConfig) => {
1426
- const toPersist = {
1427
- values: filterBarConfig.values ?? {},
1428
- starredFilterKeys: filterBarConfig.starredFilterKeys ?? [],
1429
- };
1430
- localStorage.setItem(getPersistenceKey(name, clientSideUserId), JSON.stringify(toPersist));
1431
- }, [name, clientSideUserId]);
1425
+ const [lastSavedState, setLastSavedState] = react.useState(undefined);
1426
+ const saveData = react.useCallback((filterBarConfig, filterBarDefinitions) => {
1427
+ if (lastSavedState) {
1428
+ const newValues = lastSavedState;
1429
+ if (filterBarConfig.values) {
1430
+ // eslint-disable-next-line no-autofix/local-rules/prefer-custom-object-entries
1431
+ Object.entries(filterBarConfig.values).forEach(([key, value]) => {
1432
+ const typedKey = key;
1433
+ const definition = Object.values(filterBarDefinitions).find(def => def.filterKey === typedKey);
1434
+ if (definition?.persistValue !== false) {
1435
+ newValues[typedKey] = value;
1436
+ }
1437
+ });
1438
+ }
1439
+ const toPersist = {
1440
+ values: newValues,
1441
+ starredFilterKeys: filterBarConfig.starredFilterKeys ?? [],
1442
+ };
1443
+ setLastSavedState(newValues);
1444
+ localStorage.setItem(getPersistenceKey(name, clientSideUserId), JSON.stringify(toPersist));
1445
+ }
1446
+ }, [name, clientSideUserId, lastSavedState]);
1432
1447
  const loadData = react.useCallback((updatedFilterDefinitionsValues) => {
1433
1448
  let initialFilterBarConfig;
1434
1449
  const storedFilters = initialStoredFilters;
1435
- const hasNonVisibleDefaultValues = updatedFilterDefinitionsValues.some(value => value.showInStarredMenu &&
1436
- !value.showInStarredMenu() &&
1437
- value.showInFilterBar &&
1438
- !value.showInFilterBar() &&
1439
- value.defaultValue?.toString &&
1440
- value.defaultValue.toString().length > 0);
1441
1450
  const initialStateValues = createInitialState({
1442
1451
  name,
1443
1452
  mainFilters: updatedFilterDefinitionsValues,
1444
1453
  setValue,
1445
1454
  });
1455
+ let loadedFilterBarConfigValues = {
1456
+ values: {},
1457
+ starredFilterKeys: [],
1458
+ };
1446
1459
  if (storedFilters && storedFilters !== "undefined") {
1447
- const loadedFilterBarConfigValues = JSON.parse(storedFilters);
1460
+ loadedFilterBarConfigValues = JSON.parse(storedFilters);
1448
1461
  if (!loadedFilterBarConfigValues.values) {
1449
1462
  loadedFilterBarConfigValues.values = {};
1450
1463
  }
1451
1464
  if (!loadedFilterBarConfigValues.starredFilterKeys) {
1452
1465
  loadedFilterBarConfigValues.starredFilterKeys = [];
1453
1466
  }
1467
+ // make sure the last saved state is the same as the loaded values no manipulation of values!
1468
+ setLastSavedState(Object.assign({}, loadedFilterBarConfigValues.values));
1454
1469
  if (validateFilter({
1455
1470
  values: loadedFilterBarConfigValues.values,
1456
1471
  starredFilterKeys: loadedFilterBarConfigValues.starredFilterKeys,
@@ -1465,16 +1480,24 @@ const useFilterBarPersistence = ({ name, setValue, }) => {
1465
1480
  };
1466
1481
  }
1467
1482
  }
1468
- if (initialFilterBarConfig === undefined || hasNonVisibleDefaultValues) {
1483
+ if (initialFilterBarConfig === undefined) {
1469
1484
  initialFilterBarConfig = initialStateValues;
1470
1485
  }
1471
- // eslint-disable-next-line no-autofix/local-rules/prefer-custom-object-keys
1472
- Object.keys(initialFilterBarConfig.values).forEach(key => {
1486
+ updatedFilterDefinitionsValues.forEach(value => {
1487
+ if (value.persistValue === false) {
1488
+ // eslint-disable-next-line local-rules/no-typescript-assertion
1489
+ const typedKey = value.filterKey;
1490
+ // eslint-disable-next-line local-rules/no-typescript-assertion
1491
+ initialFilterBarConfig.values[typedKey] = value.defaultValue;
1492
+ }
1493
+ });
1494
+ // eslint-disable-next-line no-autofix/local-rules/prefer-custom-object-entries
1495
+ Object.entries(initialFilterBarConfig.values).forEach(([key, value]) => {
1473
1496
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1474
1497
  initialFilterBarConfig.setters[`set${stringTs.capitalize(key)}`] = (callback) => setValue(key, callback);
1475
1498
  });
1476
1499
  return initialFilterBarConfig;
1477
- }, [name, setValue, initialStoredFilters]);
1500
+ }, [name, initialStoredFilters, setValue]);
1478
1501
  return react.useMemo(() => ({ loadData, saveData }), [loadData, saveData]);
1479
1502
  };
1480
1503
 
@@ -1524,8 +1547,8 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, }) => {
1524
1547
  });
1525
1548
  react.useEffect(() => {
1526
1549
  onValuesChange?.(filterBarConfig.values);
1527
- saveData(filterBarConfig);
1528
- }, [filterBarConfig.values, filterBarConfig, onValuesChange, saveData]);
1550
+ saveData(filterBarConfig, filterBarDefinition);
1551
+ }, [filterBarConfig, filterBarDefinition, onValuesChange, saveData]);
1529
1552
  return react.useMemo(() => {
1530
1553
  return {
1531
1554
  filterBarConfig: { ...filterBarConfig, ...filterMapActions, ...filterMapGetter },
@@ -1552,7 +1575,14 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, }) => {
1552
1575
  setValue: (key, callback) => setValue(setFilterBarConfig, key, callback),
1553
1576
  });
1554
1577
  const [filterBarConfig, setFilterBarConfig] = react.useState(() => {
1555
- return loadData(sharedUtils.objectValues(internalFilterBarDefinitions));
1578
+ const initialConfig = {
1579
+ values: Object.create({}),
1580
+ setters: Object.create({}),
1581
+ name,
1582
+ initialState: Object.create({}),
1583
+ starredFilterKeys: [],
1584
+ };
1585
+ return initialConfig;
1556
1586
  });
1557
1587
  const { filterMapActions, filterMapGetter } = useFilterBarActions({
1558
1588
  name,
@@ -1563,24 +1593,34 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, }) => {
1563
1593
  setValue: (key, callback) => setValue(setFilterBarConfig, key, callback),
1564
1594
  });
1565
1595
  const dataLoaded = react.useCallback((loadedFilterDefinitionsValues) => {
1566
- setIsDataLoaded(true);
1567
- setAsyncLoadedFilterBarDefinitions(loadedFilterDefinitionsValues);
1596
+ setAsyncLoadedFilterBarDefinitions(() => loadedFilterDefinitionsValues);
1568
1597
  setFilterBarConfig(_ => loadData(sharedUtils.objectValues(loadedFilterDefinitionsValues)));
1598
+ setIsDataLoaded(true);
1569
1599
  }, [loadData]);
1600
+ const filterBarConfigMemoed = react.useMemo(() => {
1601
+ return { ...filterBarConfig, ...filterMapActions, ...filterMapGetter };
1602
+ }, [filterBarConfig, filterMapActions, filterMapGetter]);
1570
1603
  react.useEffect(() => {
1571
1604
  if (isDataLoaded) {
1572
- onValuesChange?.(filterBarConfig.values);
1573
- saveData(filterBarConfig);
1605
+ onValuesChange?.(filterBarConfigMemoed.values);
1606
+ saveData(filterBarConfigMemoed, internalFilterBarDefinitions);
1574
1607
  }
1575
- }, [filterBarConfig.values, filterBarConfig, onValuesChange, saveData, isDataLoaded]);
1608
+ }, [
1609
+ filterBarConfigMemoed.values,
1610
+ internalFilterBarDefinitions,
1611
+ filterBarConfigMemoed,
1612
+ onValuesChange,
1613
+ saveData,
1614
+ isDataLoaded,
1615
+ ]);
1576
1616
  return react.useMemo(() => {
1577
1617
  return {
1578
- filterBarConfig: { ...filterBarConfig, ...filterMapActions, ...filterMapGetter },
1618
+ filterBarConfig: filterBarConfigMemoed,
1579
1619
  filterBarDefinition: internalFilterBarDefinitions,
1580
1620
  dataLoaded,
1581
1621
  name,
1582
1622
  };
1583
- }, [filterBarConfig, filterMapActions, filterMapGetter, internalFilterBarDefinitions, dataLoaded, name]);
1623
+ }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name]);
1584
1624
  };
1585
1625
 
1586
1626
  /**
package/index.esm.js CHANGED
@@ -1420,35 +1420,50 @@ const getPersistenceKey = (name, clientSideUserId) => `filter-${name}-${clientSi
1420
1420
  const useFilterBarPersistence = ({ name, setValue, }) => {
1421
1421
  const { clientSideUserId } = useCurrentUser();
1422
1422
  const [initialStoredFilters] = useState(() => localStorage.getItem(getPersistenceKey(name, clientSideUserId)) || "{}");
1423
- const saveData = useCallback((filterBarConfig) => {
1424
- const toPersist = {
1425
- values: filterBarConfig.values ?? {},
1426
- starredFilterKeys: filterBarConfig.starredFilterKeys ?? [],
1427
- };
1428
- localStorage.setItem(getPersistenceKey(name, clientSideUserId), JSON.stringify(toPersist));
1429
- }, [name, clientSideUserId]);
1423
+ const [lastSavedState, setLastSavedState] = useState(undefined);
1424
+ const saveData = useCallback((filterBarConfig, filterBarDefinitions) => {
1425
+ if (lastSavedState) {
1426
+ const newValues = lastSavedState;
1427
+ if (filterBarConfig.values) {
1428
+ // eslint-disable-next-line no-autofix/local-rules/prefer-custom-object-entries
1429
+ Object.entries(filterBarConfig.values).forEach(([key, value]) => {
1430
+ const typedKey = key;
1431
+ const definition = Object.values(filterBarDefinitions).find(def => def.filterKey === typedKey);
1432
+ if (definition?.persistValue !== false) {
1433
+ newValues[typedKey] = value;
1434
+ }
1435
+ });
1436
+ }
1437
+ const toPersist = {
1438
+ values: newValues,
1439
+ starredFilterKeys: filterBarConfig.starredFilterKeys ?? [],
1440
+ };
1441
+ setLastSavedState(newValues);
1442
+ localStorage.setItem(getPersistenceKey(name, clientSideUserId), JSON.stringify(toPersist));
1443
+ }
1444
+ }, [name, clientSideUserId, lastSavedState]);
1430
1445
  const loadData = useCallback((updatedFilterDefinitionsValues) => {
1431
1446
  let initialFilterBarConfig;
1432
1447
  const storedFilters = initialStoredFilters;
1433
- const hasNonVisibleDefaultValues = updatedFilterDefinitionsValues.some(value => value.showInStarredMenu &&
1434
- !value.showInStarredMenu() &&
1435
- value.showInFilterBar &&
1436
- !value.showInFilterBar() &&
1437
- value.defaultValue?.toString &&
1438
- value.defaultValue.toString().length > 0);
1439
1448
  const initialStateValues = createInitialState({
1440
1449
  name,
1441
1450
  mainFilters: updatedFilterDefinitionsValues,
1442
1451
  setValue,
1443
1452
  });
1453
+ let loadedFilterBarConfigValues = {
1454
+ values: {},
1455
+ starredFilterKeys: [],
1456
+ };
1444
1457
  if (storedFilters && storedFilters !== "undefined") {
1445
- const loadedFilterBarConfigValues = JSON.parse(storedFilters);
1458
+ loadedFilterBarConfigValues = JSON.parse(storedFilters);
1446
1459
  if (!loadedFilterBarConfigValues.values) {
1447
1460
  loadedFilterBarConfigValues.values = {};
1448
1461
  }
1449
1462
  if (!loadedFilterBarConfigValues.starredFilterKeys) {
1450
1463
  loadedFilterBarConfigValues.starredFilterKeys = [];
1451
1464
  }
1465
+ // make sure the last saved state is the same as the loaded values no manipulation of values!
1466
+ setLastSavedState(Object.assign({}, loadedFilterBarConfigValues.values));
1452
1467
  if (validateFilter({
1453
1468
  values: loadedFilterBarConfigValues.values,
1454
1469
  starredFilterKeys: loadedFilterBarConfigValues.starredFilterKeys,
@@ -1463,16 +1478,24 @@ const useFilterBarPersistence = ({ name, setValue, }) => {
1463
1478
  };
1464
1479
  }
1465
1480
  }
1466
- if (initialFilterBarConfig === undefined || hasNonVisibleDefaultValues) {
1481
+ if (initialFilterBarConfig === undefined) {
1467
1482
  initialFilterBarConfig = initialStateValues;
1468
1483
  }
1469
- // eslint-disable-next-line no-autofix/local-rules/prefer-custom-object-keys
1470
- Object.keys(initialFilterBarConfig.values).forEach(key => {
1484
+ updatedFilterDefinitionsValues.forEach(value => {
1485
+ if (value.persistValue === false) {
1486
+ // eslint-disable-next-line local-rules/no-typescript-assertion
1487
+ const typedKey = value.filterKey;
1488
+ // eslint-disable-next-line local-rules/no-typescript-assertion
1489
+ initialFilterBarConfig.values[typedKey] = value.defaultValue;
1490
+ }
1491
+ });
1492
+ // eslint-disable-next-line no-autofix/local-rules/prefer-custom-object-entries
1493
+ Object.entries(initialFilterBarConfig.values).forEach(([key, value]) => {
1471
1494
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1472
1495
  initialFilterBarConfig.setters[`set${capitalize(key)}`] = (callback) => setValue(key, callback);
1473
1496
  });
1474
1497
  return initialFilterBarConfig;
1475
- }, [name, setValue, initialStoredFilters]);
1498
+ }, [name, initialStoredFilters, setValue]);
1476
1499
  return useMemo(() => ({ loadData, saveData }), [loadData, saveData]);
1477
1500
  };
1478
1501
 
@@ -1522,8 +1545,8 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, }) => {
1522
1545
  });
1523
1546
  useEffect(() => {
1524
1547
  onValuesChange?.(filterBarConfig.values);
1525
- saveData(filterBarConfig);
1526
- }, [filterBarConfig.values, filterBarConfig, onValuesChange, saveData]);
1548
+ saveData(filterBarConfig, filterBarDefinition);
1549
+ }, [filterBarConfig, filterBarDefinition, onValuesChange, saveData]);
1527
1550
  return useMemo(() => {
1528
1551
  return {
1529
1552
  filterBarConfig: { ...filterBarConfig, ...filterMapActions, ...filterMapGetter },
@@ -1550,7 +1573,14 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, }) => {
1550
1573
  setValue: (key, callback) => setValue(setFilterBarConfig, key, callback),
1551
1574
  });
1552
1575
  const [filterBarConfig, setFilterBarConfig] = useState(() => {
1553
- return loadData(objectValues(internalFilterBarDefinitions));
1576
+ const initialConfig = {
1577
+ values: Object.create({}),
1578
+ setters: Object.create({}),
1579
+ name,
1580
+ initialState: Object.create({}),
1581
+ starredFilterKeys: [],
1582
+ };
1583
+ return initialConfig;
1554
1584
  });
1555
1585
  const { filterMapActions, filterMapGetter } = useFilterBarActions({
1556
1586
  name,
@@ -1561,24 +1591,34 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, }) => {
1561
1591
  setValue: (key, callback) => setValue(setFilterBarConfig, key, callback),
1562
1592
  });
1563
1593
  const dataLoaded = useCallback((loadedFilterDefinitionsValues) => {
1564
- setIsDataLoaded(true);
1565
- setAsyncLoadedFilterBarDefinitions(loadedFilterDefinitionsValues);
1594
+ setAsyncLoadedFilterBarDefinitions(() => loadedFilterDefinitionsValues);
1566
1595
  setFilterBarConfig(_ => loadData(objectValues(loadedFilterDefinitionsValues)));
1596
+ setIsDataLoaded(true);
1567
1597
  }, [loadData]);
1598
+ const filterBarConfigMemoed = useMemo(() => {
1599
+ return { ...filterBarConfig, ...filterMapActions, ...filterMapGetter };
1600
+ }, [filterBarConfig, filterMapActions, filterMapGetter]);
1568
1601
  useEffect(() => {
1569
1602
  if (isDataLoaded) {
1570
- onValuesChange?.(filterBarConfig.values);
1571
- saveData(filterBarConfig);
1603
+ onValuesChange?.(filterBarConfigMemoed.values);
1604
+ saveData(filterBarConfigMemoed, internalFilterBarDefinitions);
1572
1605
  }
1573
- }, [filterBarConfig.values, filterBarConfig, onValuesChange, saveData, isDataLoaded]);
1606
+ }, [
1607
+ filterBarConfigMemoed.values,
1608
+ internalFilterBarDefinitions,
1609
+ filterBarConfigMemoed,
1610
+ onValuesChange,
1611
+ saveData,
1612
+ isDataLoaded,
1613
+ ]);
1574
1614
  return useMemo(() => {
1575
1615
  return {
1576
- filterBarConfig: { ...filterBarConfig, ...filterMapActions, ...filterMapGetter },
1616
+ filterBarConfig: filterBarConfigMemoed,
1577
1617
  filterBarDefinition: internalFilterBarDefinitions,
1578
1618
  dataLoaded,
1579
1619
  name,
1580
1620
  };
1581
- }, [filterBarConfig, filterMapActions, filterMapGetter, internalFilterBarDefinitions, dataLoaded, name]);
1621
+ }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name]);
1582
1622
  };
1583
1623
 
1584
1624
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/filters-filter-bar",
3
- "version": "1.3.66",
3
+ "version": "1.3.68",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -14,12 +14,12 @@
14
14
  "tailwind-merge": "^2.0.0",
15
15
  "string-ts": "^2.0.0",
16
16
  "zod": "3.22.4",
17
- "@trackunit/react-components": "1.4.47",
17
+ "@trackunit/react-components": "1.4.48",
18
18
  "@trackunit/react-core-hooks": "1.3.43",
19
- "@trackunit/react-filter-components": "1.3.54",
20
- "@trackunit/react-date-and-time-components": "1.3.53",
19
+ "@trackunit/react-filter-components": "1.3.55",
20
+ "@trackunit/react-date-and-time-components": "1.3.54",
21
21
  "@trackunit/shared-utils": "1.5.41",
22
- "@trackunit/react-form-components": "1.3.54",
22
+ "@trackunit/react-form-components": "1.3.55",
23
23
  "@trackunit/react-core-contexts-api": "1.4.42",
24
24
  "@trackunit/geo-json-utils": "1.3.42",
25
25
  "@trackunit/i18n-library-translation": "1.3.44"
@@ -12,6 +12,6 @@ type FilterBarPersistenceProps<TFilterBarDefinition extends FilterBarDefinition>
12
12
  */
13
13
  export declare const useFilterBarPersistence: <TFilterBarDefinition extends FilterBarDefinition>({ name, setValue, }: FilterBarPersistenceProps<TFilterBarDefinition>) => {
14
14
  loadData: <TFilterBarDefinitionExtended extends TFilterBarDefinition>(updatedFilterDefinitionsValues: TFilterBarDefinitionExtended[keyof TFilterBarDefinitionExtended][]) => FilterBarConfig<TFilterBarDefinition>;
15
- saveData: (filterBarConfig: Partial<FilterBarConfig<TFilterBarDefinition>>) => void;
15
+ saveData: (filterBarConfig: Partial<FilterBarConfig<TFilterBarDefinition>>, filterBarDefinitions: TFilterBarDefinition) => void;
16
16
  };
17
17
  export {};
@@ -16,9 +16,7 @@ export type MinMaxFilterValue = {
16
16
  };
17
17
  export declare const areaFilterGeoJsonGeometrySchema: z.ZodUnion<[z.ZodObject<{
18
18
  type: z.ZodLiteral<"Polygon">;
19
- coordinates: z.ZodArray<z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber /**
20
- * A function that determines if the filter should be displayed in the filter bar.
21
- */], null>, "many">, [number, number][], [number, number][]>, "many">;
19
+ coordinates: z.ZodArray<z.ZodEffects<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">, [number, number][], [number, number][]>, "many">;
22
20
  }, "strict", z.ZodTypeAny, {
23
21
  type: "Polygon";
24
22
  coordinates: [number, number][][];
@@ -86,6 +84,10 @@ export interface AbstractFilterDefinition {
86
84
  * If the filter should be on the provided filter bar as default
87
85
  */
88
86
  default?: boolean;
87
+ /**
88
+ * If the filter should be persisted this key to localstorage, if not it will not override if it is in the localstorage and not load if it is.
89
+ */
90
+ persistValue?: boolean;
89
91
  /**
90
92
  * The Group the filter will be shown under in the ui.
91
93
  *