@trackunit/filters-filter-bar 1.8.38 → 1.8.39

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.
Files changed (3) hide show
  1. package/index.cjs.js +39 -23
  2. package/index.esm.js +40 -24
  3. package/package.json +7 -7
package/index.cjs.js CHANGED
@@ -2384,14 +2384,23 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, loadData: inp
2384
2384
  setFilterBarConfig,
2385
2385
  setValue: setValueMemoized,
2386
2386
  });
2387
+ // Store the latest callback in a ref and update it on every render
2387
2388
  const onValuesChangeRef = react.useRef(onValuesChange);
2388
- react.useEffect(() => {
2389
- onValuesChangeRef.current = onValuesChange;
2390
- }, [onValuesChange]);
2391
- react.useEffect(() => {
2392
- saveData(filterBarConfig, filterBarDefinition);
2393
- onValuesChangeRef.current?.(filterBarConfig.values);
2394
- }, [filterBarConfig, filterBarDefinition, saveData]);
2389
+ onValuesChangeRef.current = onValuesChange;
2390
+ // Create a stable wrapper that always calls the latest callback via ref
2391
+ // useCallback with empty deps is safe here - we only access the ref, not reactive values
2392
+ const stableOnValuesChange = react.useCallback((values) => {
2393
+ onValuesChangeRef.current?.(values);
2394
+ }, []);
2395
+ // Watch for changes in filter values and only save/notify when they actually change
2396
+ reactCoreHooks.useWatch({
2397
+ value: filterBarConfig.values,
2398
+ onChange: currentValues => {
2399
+ saveData(filterBarConfig, filterBarDefinition);
2400
+ stableOnValuesChange(currentValues);
2401
+ },
2402
+ immediate: true,
2403
+ });
2395
2404
  react.useEffect(() => {
2396
2405
  if (lastName.current !== name) {
2397
2406
  setFilterBarConfig(loadData(sharedUtils.objectValues(filterBarDefinition)));
@@ -2403,9 +2412,9 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, loadData: inp
2403
2412
  filterBarConfig: { ...filterBarConfig, ...filterMapActions, ...filterMapGetter },
2404
2413
  filterBarDefinition,
2405
2414
  name,
2406
- onValuesChange,
2415
+ onValuesChange: stableOnValuesChange,
2407
2416
  };
2408
- }, [filterBarConfig, filterMapActions, filterMapGetter, filterBarDefinition, name, onValuesChange]);
2417
+ }, [filterBarConfig, filterMapActions, filterMapGetter, filterBarDefinition, name, stableOnValuesChange]);
2409
2418
  };
2410
2419
 
2411
2420
  /**
@@ -2465,27 +2474,34 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, loadData
2465
2474
  const filterBarConfigMemoed = react.useMemo(() => {
2466
2475
  return { ...filterBarConfig, ...filterMapActions, ...filterMapGetter };
2467
2476
  }, [filterBarConfig, filterMapActions, filterMapGetter]);
2468
- react.useEffect(() => {
2469
- if (isDataLoaded) {
2470
- onValuesChange?.(filterBarConfigMemoed.values);
2471
- saveData(filterBarConfigMemoed, internalFilterBarDefinitions);
2472
- }
2473
- }, [
2474
- filterBarConfigMemoed.values,
2475
- internalFilterBarDefinitions,
2476
- filterBarConfigMemoed,
2477
- onValuesChange,
2478
- saveData,
2479
- isDataLoaded,
2480
- ]);
2477
+ // Store the latest callback in a ref and update it on every render
2478
+ const onValuesChangeRef = react.useRef(onValuesChange);
2479
+ onValuesChangeRef.current = onValuesChange;
2480
+ // Create a stable wrapper that always calls the latest callback via ref
2481
+ // useCallback with empty deps is safe here - we only access the ref, not reactive values
2482
+ const stableOnValuesChange = react.useCallback((values) => {
2483
+ onValuesChangeRef.current?.(values);
2484
+ }, []);
2485
+ // Watch for changes in filter values and only save/notify when they actually change
2486
+ reactCoreHooks.useWatch({
2487
+ value: isDataLoaded ? filterBarConfigMemoed.values : null,
2488
+ onChange: currentValues => {
2489
+ if (currentValues !== null) {
2490
+ saveData(filterBarConfigMemoed, internalFilterBarDefinitions);
2491
+ stableOnValuesChange(currentValues);
2492
+ }
2493
+ },
2494
+ immediate: true,
2495
+ });
2481
2496
  return react.useMemo(() => {
2482
2497
  return {
2483
2498
  filterBarConfig: filterBarConfigMemoed,
2484
2499
  filterBarDefinition: internalFilterBarDefinitions,
2485
2500
  dataLoaded,
2486
2501
  name,
2502
+ onValuesChange: stableOnValuesChange,
2487
2503
  };
2488
- }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name]);
2504
+ }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name, stableOnValuesChange]);
2489
2505
  };
2490
2506
 
2491
2507
  /**
package/index.esm.js CHANGED
@@ -3,7 +3,7 @@ import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-l
3
3
  import { useMemo, useRef, useState, useEffect, useCallback, Fragment as Fragment$1 } from 'react';
4
4
  import { Filter, FilterBody, RadioFilterItem, CheckBoxFilterItem, FilterHeader as FilterHeader$1, FilterFooter } from '@trackunit/react-filter-components';
5
5
  import { Button, Icon, useList, List, Text, Card, CardBody, useViewportBreakpoints, Popover, PopoverTrigger, Tooltip, Badge, PopoverContent, IconButton, MenuList } from '@trackunit/react-components';
6
- import { useAnalytics, useTextSearch, useCurrentUser, useCustomEncoding } from '@trackunit/react-core-hooks';
6
+ import { useAnalytics, useTextSearch, useCurrentUser, useCustomEncoding, useWatch } from '@trackunit/react-core-hooks';
7
7
  import { capitalize } from 'string-ts';
8
8
  import { createEvent } from '@trackunit/react-core-contexts-api';
9
9
  import { Search, NumberField, RadioGroup } from '@trackunit/react-form-components';
@@ -2382,14 +2382,23 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, loadData: inp
2382
2382
  setFilterBarConfig,
2383
2383
  setValue: setValueMemoized,
2384
2384
  });
2385
+ // Store the latest callback in a ref and update it on every render
2385
2386
  const onValuesChangeRef = useRef(onValuesChange);
2386
- useEffect(() => {
2387
- onValuesChangeRef.current = onValuesChange;
2388
- }, [onValuesChange]);
2389
- useEffect(() => {
2390
- saveData(filterBarConfig, filterBarDefinition);
2391
- onValuesChangeRef.current?.(filterBarConfig.values);
2392
- }, [filterBarConfig, filterBarDefinition, saveData]);
2387
+ onValuesChangeRef.current = onValuesChange;
2388
+ // Create a stable wrapper that always calls the latest callback via ref
2389
+ // useCallback with empty deps is safe here - we only access the ref, not reactive values
2390
+ const stableOnValuesChange = useCallback((values) => {
2391
+ onValuesChangeRef.current?.(values);
2392
+ }, []);
2393
+ // Watch for changes in filter values and only save/notify when they actually change
2394
+ useWatch({
2395
+ value: filterBarConfig.values,
2396
+ onChange: currentValues => {
2397
+ saveData(filterBarConfig, filterBarDefinition);
2398
+ stableOnValuesChange(currentValues);
2399
+ },
2400
+ immediate: true,
2401
+ });
2393
2402
  useEffect(() => {
2394
2403
  if (lastName.current !== name) {
2395
2404
  setFilterBarConfig(loadData(objectValues(filterBarDefinition)));
@@ -2401,9 +2410,9 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, loadData: inp
2401
2410
  filterBarConfig: { ...filterBarConfig, ...filterMapActions, ...filterMapGetter },
2402
2411
  filterBarDefinition,
2403
2412
  name,
2404
- onValuesChange,
2413
+ onValuesChange: stableOnValuesChange,
2405
2414
  };
2406
- }, [filterBarConfig, filterMapActions, filterMapGetter, filterBarDefinition, name, onValuesChange]);
2415
+ }, [filterBarConfig, filterMapActions, filterMapGetter, filterBarDefinition, name, stableOnValuesChange]);
2407
2416
  };
2408
2417
 
2409
2418
  /**
@@ -2463,27 +2472,34 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, loadData
2463
2472
  const filterBarConfigMemoed = useMemo(() => {
2464
2473
  return { ...filterBarConfig, ...filterMapActions, ...filterMapGetter };
2465
2474
  }, [filterBarConfig, filterMapActions, filterMapGetter]);
2466
- useEffect(() => {
2467
- if (isDataLoaded) {
2468
- onValuesChange?.(filterBarConfigMemoed.values);
2469
- saveData(filterBarConfigMemoed, internalFilterBarDefinitions);
2470
- }
2471
- }, [
2472
- filterBarConfigMemoed.values,
2473
- internalFilterBarDefinitions,
2474
- filterBarConfigMemoed,
2475
- onValuesChange,
2476
- saveData,
2477
- isDataLoaded,
2478
- ]);
2475
+ // Store the latest callback in a ref and update it on every render
2476
+ const onValuesChangeRef = useRef(onValuesChange);
2477
+ onValuesChangeRef.current = onValuesChange;
2478
+ // Create a stable wrapper that always calls the latest callback via ref
2479
+ // useCallback with empty deps is safe here - we only access the ref, not reactive values
2480
+ const stableOnValuesChange = useCallback((values) => {
2481
+ onValuesChangeRef.current?.(values);
2482
+ }, []);
2483
+ // Watch for changes in filter values and only save/notify when they actually change
2484
+ useWatch({
2485
+ value: isDataLoaded ? filterBarConfigMemoed.values : null,
2486
+ onChange: currentValues => {
2487
+ if (currentValues !== null) {
2488
+ saveData(filterBarConfigMemoed, internalFilterBarDefinitions);
2489
+ stableOnValuesChange(currentValues);
2490
+ }
2491
+ },
2492
+ immediate: true,
2493
+ });
2479
2494
  return useMemo(() => {
2480
2495
  return {
2481
2496
  filterBarConfig: filterBarConfigMemoed,
2482
2497
  filterBarDefinition: internalFilterBarDefinitions,
2483
2498
  dataLoaded,
2484
2499
  name,
2500
+ onValuesChange: stableOnValuesChange,
2485
2501
  };
2486
- }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name]);
2502
+ }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name, stableOnValuesChange]);
2487
2503
  };
2488
2504
 
2489
2505
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/filters-filter-bar",
3
- "version": "1.8.38",
3
+ "version": "1.8.39",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -14,16 +14,16 @@
14
14
  "string-ts": "^2.0.0",
15
15
  "zod": "^3.23.8",
16
16
  "@trackunit/iris-app-api": "1.7.27",
17
- "@trackunit/react-core-hooks": "1.7.30",
18
- "@trackunit/react-filter-components": "1.7.38",
19
- "@trackunit/react-date-and-time-components": "1.10.38",
17
+ "@trackunit/react-core-hooks": "1.7.31",
18
+ "@trackunit/react-filter-components": "1.7.39",
19
+ "@trackunit/react-date-and-time-components": "1.10.39",
20
20
  "@trackunit/shared-utils": "1.9.26",
21
- "@trackunit/react-form-components": "1.8.37",
21
+ "@trackunit/react-form-components": "1.8.38",
22
22
  "@trackunit/react-core-contexts-api": "1.8.28",
23
23
  "@trackunit/geo-json-utils": "1.7.26",
24
- "@trackunit/i18n-library-translation": "1.7.31",
24
+ "@trackunit/i18n-library-translation": "1.7.32",
25
25
  "@trackunit/css-class-variance-utilities": "1.7.26",
26
- "@trackunit/react-components": "1.9.37",
26
+ "@trackunit/react-components": "1.9.38",
27
27
  "@trackunit/react-test-setup": "1.4.26",
28
28
  "@tanstack/react-router": "1.114.29"
29
29
  },