@trackunit/react-components 1.10.16 → 1.10.18

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
@@ -1231,34 +1231,28 @@ const useContinuousTimeout = ({ onTimeout, onMaxRetries, duration, maxRetries, }
1231
1231
  /**
1232
1232
  * The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
1233
1233
  *
1234
- * @param {any} value The value to set
1235
- * @param {number} delay The debounce time
1236
- * @param {"in" | "out" | "both"} direction Considers truthiness of value. If set to "in", the value will only be debounced if it is truthy. If set to "out", the value will only be debounced if it is falsy. If set to "both" or if not defined, the value will be debounced regardless of truthiness.
1237
- * @returns {any} The latest value received
1234
+ * @template TValue
1235
+ * @param {TValue} value The value to set
1236
+ * @param {UseDebounceOptions<TValue>} options The debounce options
1237
+ * @param {(debouncedValue: TValue) => void} options.onBounce Callback when the value is debounced
1238
+ * @param {number} options.delay The debounce time
1239
+ * @returns {TValue} The latest value received
1238
1240
  */
1239
- /**
1240
- *
1241
- */
1242
- const useDebounce = (value, delay = 500, direction, onBounce) => {
1241
+ const useDebounce = (value, { onBounce, delay = 500 } = {}) => {
1243
1242
  const [debouncedValue, setDebouncedValue] = react.useState(value);
1244
1243
  react.useEffect(() => {
1245
- let handler;
1246
- if ((direction === "in" && !Boolean(debouncedValue) && Boolean(value)) ||
1247
- (direction === "out" && Boolean(debouncedValue) && !Boolean(value)) ||
1248
- direction === "both" ||
1249
- direction === undefined) {
1250
- handler = setTimeout(() => {
1251
- setDebouncedValue(value);
1252
- onBounce?.(value);
1253
- }, delay);
1244
+ // Skip if value hasn't changed
1245
+ if (esToolkit.isEqual(value, debouncedValue)) {
1246
+ return;
1254
1247
  }
1255
- else {
1248
+ const handler = setTimeout(() => {
1256
1249
  setDebouncedValue(value);
1257
- }
1250
+ onBounce?.(value);
1251
+ }, delay);
1258
1252
  return () => {
1259
1253
  clearTimeout(handler);
1260
1254
  };
1261
- }, [value, delay, direction, debouncedValue, onBounce]);
1255
+ }, [value, delay, debouncedValue, onBounce]);
1262
1256
  return debouncedValue;
1263
1257
  };
1264
1258
 
@@ -1444,7 +1438,22 @@ const useGeometry = (ref, { skip = false, onChange } = {}) => {
1444
1438
  */
1445
1439
  const useHover = ({ debounced = false, delay = 100, direction = "out" } = { debounced: false }) => {
1446
1440
  const [hovering, setHovering] = react.useState(false);
1447
- const debouncedHovering = useDebounce(hovering, delay, direction);
1441
+ const [debouncedHovering, setDebouncedHovering] = react.useState(false);
1442
+ react.useEffect(() => {
1443
+ if (!debounced) {
1444
+ setDebouncedHovering(hovering);
1445
+ return undefined;
1446
+ }
1447
+ const shouldDebounce = direction === "both" || (direction === "in" && hovering) || (direction === "out" && !hovering);
1448
+ if (shouldDebounce) {
1449
+ const timer = setTimeout(() => {
1450
+ setDebouncedHovering(hovering);
1451
+ }, delay);
1452
+ return () => clearTimeout(timer);
1453
+ }
1454
+ setDebouncedHovering(hovering);
1455
+ return undefined;
1456
+ }, [debounced, direction, delay, hovering]);
1448
1457
  const onMouseEnter = react.useCallback(() => {
1449
1458
  setHovering(true);
1450
1459
  }, []);
@@ -1454,8 +1463,8 @@ const useHover = ({ debounced = false, delay = 100, direction = "out" } = { debo
1454
1463
  return react.useMemo(() => ({
1455
1464
  onMouseEnter,
1456
1465
  onMouseLeave,
1457
- hovering: debounced ? debouncedHovering : hovering,
1458
- }), [onMouseEnter, onMouseLeave, debounced, debouncedHovering, hovering]);
1466
+ hovering: debouncedHovering,
1467
+ }), [onMouseEnter, onMouseLeave, debouncedHovering]);
1459
1468
  };
1460
1469
 
1461
1470
  const OVERSCAN = 10;
package/index.esm.js CHANGED
@@ -1229,34 +1229,28 @@ const useContinuousTimeout = ({ onTimeout, onMaxRetries, duration, maxRetries, }
1229
1229
  /**
1230
1230
  * The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
1231
1231
  *
1232
- * @param {any} value The value to set
1233
- * @param {number} delay The debounce time
1234
- * @param {"in" | "out" | "both"} direction Considers truthiness of value. If set to "in", the value will only be debounced if it is truthy. If set to "out", the value will only be debounced if it is falsy. If set to "both" or if not defined, the value will be debounced regardless of truthiness.
1235
- * @returns {any} The latest value received
1232
+ * @template TValue
1233
+ * @param {TValue} value The value to set
1234
+ * @param {UseDebounceOptions<TValue>} options The debounce options
1235
+ * @param {(debouncedValue: TValue) => void} options.onBounce Callback when the value is debounced
1236
+ * @param {number} options.delay The debounce time
1237
+ * @returns {TValue} The latest value received
1236
1238
  */
1237
- /**
1238
- *
1239
- */
1240
- const useDebounce = (value, delay = 500, direction, onBounce) => {
1239
+ const useDebounce = (value, { onBounce, delay = 500 } = {}) => {
1241
1240
  const [debouncedValue, setDebouncedValue] = useState(value);
1242
1241
  useEffect(() => {
1243
- let handler;
1244
- if ((direction === "in" && !Boolean(debouncedValue) && Boolean(value)) ||
1245
- (direction === "out" && Boolean(debouncedValue) && !Boolean(value)) ||
1246
- direction === "both" ||
1247
- direction === undefined) {
1248
- handler = setTimeout(() => {
1249
- setDebouncedValue(value);
1250
- onBounce?.(value);
1251
- }, delay);
1242
+ // Skip if value hasn't changed
1243
+ if (isEqual(value, debouncedValue)) {
1244
+ return;
1252
1245
  }
1253
- else {
1246
+ const handler = setTimeout(() => {
1254
1247
  setDebouncedValue(value);
1255
- }
1248
+ onBounce?.(value);
1249
+ }, delay);
1256
1250
  return () => {
1257
1251
  clearTimeout(handler);
1258
1252
  };
1259
- }, [value, delay, direction, debouncedValue, onBounce]);
1253
+ }, [value, delay, debouncedValue, onBounce]);
1260
1254
  return debouncedValue;
1261
1255
  };
1262
1256
 
@@ -1442,7 +1436,22 @@ const useGeometry = (ref, { skip = false, onChange } = {}) => {
1442
1436
  */
1443
1437
  const useHover = ({ debounced = false, delay = 100, direction = "out" } = { debounced: false }) => {
1444
1438
  const [hovering, setHovering] = useState(false);
1445
- const debouncedHovering = useDebounce(hovering, delay, direction);
1439
+ const [debouncedHovering, setDebouncedHovering] = useState(false);
1440
+ useEffect(() => {
1441
+ if (!debounced) {
1442
+ setDebouncedHovering(hovering);
1443
+ return undefined;
1444
+ }
1445
+ const shouldDebounce = direction === "both" || (direction === "in" && hovering) || (direction === "out" && !hovering);
1446
+ if (shouldDebounce) {
1447
+ const timer = setTimeout(() => {
1448
+ setDebouncedHovering(hovering);
1449
+ }, delay);
1450
+ return () => clearTimeout(timer);
1451
+ }
1452
+ setDebouncedHovering(hovering);
1453
+ return undefined;
1454
+ }, [debounced, direction, delay, hovering]);
1446
1455
  const onMouseEnter = useCallback(() => {
1447
1456
  setHovering(true);
1448
1457
  }, []);
@@ -1452,8 +1461,8 @@ const useHover = ({ debounced = false, delay = 100, direction = "out" } = { debo
1452
1461
  return useMemo(() => ({
1453
1462
  onMouseEnter,
1454
1463
  onMouseLeave,
1455
- hovering: debounced ? debouncedHovering : hovering,
1456
- }), [onMouseEnter, onMouseLeave, debounced, debouncedHovering, hovering]);
1464
+ hovering: debouncedHovering,
1465
+ }), [onMouseEnter, onMouseLeave, debouncedHovering]);
1457
1466
  };
1458
1467
 
1459
1468
  const OVERSCAN = 10;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "1.10.16",
3
+ "version": "1.10.18",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -16,11 +16,11 @@
16
16
  "@floating-ui/react": "^0.26.25",
17
17
  "string-ts": "^2.0.0",
18
18
  "tailwind-merge": "^2.0.0",
19
- "@trackunit/ui-design-tokens": "1.7.49",
20
- "@trackunit/css-class-variance-utilities": "1.7.49",
21
- "@trackunit/shared-utils": "1.9.49",
22
- "@trackunit/ui-icons": "1.7.50",
23
- "@trackunit/react-test-setup": "1.4.49",
19
+ "@trackunit/ui-design-tokens": "1.7.50",
20
+ "@trackunit/css-class-variance-utilities": "1.7.50",
21
+ "@trackunit/shared-utils": "1.9.50",
22
+ "@trackunit/ui-icons": "1.7.51",
23
+ "@trackunit/react-test-setup": "1.4.50",
24
24
  "@tanstack/react-router": "1.114.29",
25
25
  "es-toolkit": "^1.39.10",
26
26
  "@tanstack/react-virtual": "3.13.12"
@@ -1,13 +1,16 @@
1
- export type DebounceDirection = "in" | "out" | "both";
1
+ type UseDebounceOptions<TValue> = {
2
+ onBounce?: (debouncedValue: TValue) => void;
3
+ delay?: number;
4
+ };
2
5
  /**
3
6
  * The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
4
7
  *
5
- * @param {any} value The value to set
6
- * @param {number} delay The debounce time
7
- * @param {"in" | "out" | "both"} direction Considers truthiness of value. If set to "in", the value will only be debounced if it is truthy. If set to "out", the value will only be debounced if it is falsy. If set to "both" or if not defined, the value will be debounced regardless of truthiness.
8
- * @returns {any} The latest value received
8
+ * @template TValue
9
+ * @param {TValue} value The value to set
10
+ * @param {UseDebounceOptions<TValue>} options The debounce options
11
+ * @param {(debouncedValue: TValue) => void} options.onBounce Callback when the value is debounced
12
+ * @param {number} options.delay The debounce time
13
+ * @returns {TValue} The latest value received
9
14
  */
10
- /**
11
- *
12
- */
13
- export declare const useDebounce: <TValue>(value: TValue, delay?: number, direction?: DebounceDirection, onBounce?: (debouncedValue: TValue) => void) => TValue;
15
+ export declare const useDebounce: <TValue>(value: TValue, { onBounce, delay }?: UseDebounceOptions<TValue>) => TValue;
16
+ export {};
@@ -1,4 +1,4 @@
1
- import { DebounceDirection } from "./useDebounce";
1
+ export type DebounceDirection = "in" | "out" | "both";
2
2
  type UseHoverProps = {
3
3
  debounced: true;
4
4
  delay?: number;