@trackunit/react-components 1.10.15 → 1.10.17
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 +43 -29
- package/index.esm.js +43 -29
- package/package.json +1 -1
- package/src/hooks/useDebounce.d.ts +12 -9
- package/src/hooks/useHover.d.ts +1 -1
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
|
-
* @
|
|
1235
|
-
* @param {
|
|
1236
|
-
* @param {
|
|
1237
|
-
* @
|
|
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
|
-
|
|
1246
|
-
if ((
|
|
1247
|
-
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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:
|
|
1458
|
-
}), [onMouseEnter, onMouseLeave,
|
|
1466
|
+
hovering: debouncedHovering,
|
|
1467
|
+
}), [onMouseEnter, onMouseLeave, debouncedHovering]);
|
|
1459
1468
|
};
|
|
1460
1469
|
|
|
1461
1470
|
const OVERSCAN = 10;
|
|
@@ -3803,6 +3812,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3803
3812
|
const containerRef = react.useRef(null);
|
|
3804
3813
|
const listRef = react.useRef(null);
|
|
3805
3814
|
const rowRefsMap = react.useRef(new Map());
|
|
3815
|
+
const virtualizerRef = react.useRef(null);
|
|
3816
|
+
const hasMeasuredOnMount = react.useRef(false);
|
|
3806
3817
|
// Resolve loading indicator once to avoid unnecessary re-renders
|
|
3807
3818
|
const resolvedLoadingIndicator = react.useMemo(() => getResolvedLoadingIndicator(loadingIndicator), [loadingIndicator]);
|
|
3808
3819
|
// Calculate total count including header
|
|
@@ -3906,13 +3917,16 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3906
3917
|
onChange?.(instance);
|
|
3907
3918
|
},
|
|
3908
3919
|
});
|
|
3909
|
-
//
|
|
3920
|
+
// Keep ref updated with latest virtualizer instance
|
|
3921
|
+
react.useEffect(() => {
|
|
3922
|
+
virtualizerRef.current = virtualizer;
|
|
3923
|
+
}, [virtualizer]);
|
|
3924
|
+
// Measure the list on mount only (not on subsequent virtualizer updates)
|
|
3910
3925
|
react.useLayoutEffect(() => {
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3926
|
+
if (!hasMeasuredOnMount.current) {
|
|
3927
|
+
virtualizerRef.current?.measure();
|
|
3928
|
+
hasMeasuredOnMount.current = true;
|
|
3929
|
+
}
|
|
3916
3930
|
}, []);
|
|
3917
3931
|
// Scroll to top when total count changes (filtering applied)
|
|
3918
3932
|
// Don't scroll when just loading more items (infinite scroll - total stays the same)
|
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
|
-
* @
|
|
1233
|
-
* @param {
|
|
1234
|
-
* @param {
|
|
1235
|
-
* @
|
|
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
|
-
|
|
1244
|
-
if ((
|
|
1245
|
-
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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:
|
|
1456
|
-
}), [onMouseEnter, onMouseLeave,
|
|
1464
|
+
hovering: debouncedHovering,
|
|
1465
|
+
}), [onMouseEnter, onMouseLeave, debouncedHovering]);
|
|
1457
1466
|
};
|
|
1458
1467
|
|
|
1459
1468
|
const OVERSCAN = 10;
|
|
@@ -3801,6 +3810,8 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3801
3810
|
const containerRef = useRef(null);
|
|
3802
3811
|
const listRef = useRef(null);
|
|
3803
3812
|
const rowRefsMap = useRef(new Map());
|
|
3813
|
+
const virtualizerRef = useRef(null);
|
|
3814
|
+
const hasMeasuredOnMount = useRef(false);
|
|
3804
3815
|
// Resolve loading indicator once to avoid unnecessary re-renders
|
|
3805
3816
|
const resolvedLoadingIndicator = useMemo(() => getResolvedLoadingIndicator(loadingIndicator), [loadingIndicator]);
|
|
3806
3817
|
// Calculate total count including header
|
|
@@ -3904,13 +3915,16 @@ const useList = ({ count, pagination, header, getItem, loadingIndicator = DEFAUL
|
|
|
3904
3915
|
onChange?.(instance);
|
|
3905
3916
|
},
|
|
3906
3917
|
});
|
|
3907
|
-
//
|
|
3918
|
+
// Keep ref updated with latest virtualizer instance
|
|
3919
|
+
useEffect(() => {
|
|
3920
|
+
virtualizerRef.current = virtualizer;
|
|
3921
|
+
}, [virtualizer]);
|
|
3922
|
+
// Measure the list on mount only (not on subsequent virtualizer updates)
|
|
3908
3923
|
useLayoutEffect(() => {
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3924
|
+
if (!hasMeasuredOnMount.current) {
|
|
3925
|
+
virtualizerRef.current?.measure();
|
|
3926
|
+
hasMeasuredOnMount.current = true;
|
|
3927
|
+
}
|
|
3914
3928
|
}, []);
|
|
3915
3929
|
// Scroll to top when total count changes (filtering applied)
|
|
3916
3930
|
// Don't scroll when just loading more items (infinite scroll - total stays the same)
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
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
|
-
* @
|
|
6
|
-
* @param {
|
|
7
|
-
* @param {
|
|
8
|
-
* @
|
|
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 {};
|
package/src/hooks/useHover.d.ts
CHANGED