@trackunit/react-drawer 1.7.103 → 1.7.104
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 +55 -40
- package/index.esm.js +57 -42
- package/package.json +5 -5
- package/src/hooks/useSwipeHandlers.d.ts +11 -3
package/index.cjs.js
CHANGED
|
@@ -321,57 +321,72 @@ const isPassedThreshold = (dragDistance, threshold) => {
|
|
|
321
321
|
};
|
|
322
322
|
/**
|
|
323
323
|
* Hook for handling swipe events on the drawer.
|
|
324
|
+
/**
|
|
325
|
+
* Hook for handling swipe events on the drawer.
|
|
326
|
+
*
|
|
327
|
+
* @param closingThreshold - The fraction (0-1) of the drawer's height needed to trigger open/close.
|
|
328
|
+
* @param onCloseGesture - Callback when a close gesture is detected (optional).
|
|
329
|
+
* @param onOpenGesture - Callback when an open gesture is detected (optional).
|
|
330
|
+
* @param onDragEnd - Callback when the drag/swipe gesture ends. Receives drag distance and velocity (optional).
|
|
331
|
+
* @param constrainDrag - Function to constrain/deny drag. Receives drag distance, returns boolean (optional).
|
|
324
332
|
*/
|
|
325
|
-
const useSwipeHandlers = ({
|
|
333
|
+
const useSwipeHandlers = ({ closingThreshold, onCloseGesture, onOpenGesture, onDragEnd, constrainDrag, }) => {
|
|
326
334
|
const [isDragging, setIsDragging] = react.useState(false);
|
|
327
335
|
const [dragDistance, setDragDistance] = react.useState(0);
|
|
328
336
|
const currentY = react.useRef(0);
|
|
329
337
|
const [currentHeight, setCurrentHeight] = react.useState(0);
|
|
330
|
-
const geometry = reactComponents.
|
|
338
|
+
const { geometry, ref, element } = reactComponents.useMeasure();
|
|
331
339
|
const [threshold, setThreshold] = react.useState(0);
|
|
332
340
|
react.useEffect(() => {
|
|
333
341
|
setThreshold(currentHeight * closingThreshold);
|
|
334
342
|
}, [currentHeight, closingThreshold]);
|
|
343
|
+
const handleTouchStartOrMouseDown = react.useCallback(() => {
|
|
344
|
+
const y = getElementYTranslation(element);
|
|
345
|
+
const height = geometry?.height ?? 0;
|
|
346
|
+
currentY.current = y;
|
|
347
|
+
setCurrentHeight(height);
|
|
348
|
+
setDragDistance(y);
|
|
349
|
+
setIsDragging(true);
|
|
350
|
+
}, [element, geometry]);
|
|
351
|
+
const handleSwiping = react.useCallback((e) => {
|
|
352
|
+
const newY = currentY.current + e.deltaY;
|
|
353
|
+
if (constrainDrag && constrainDrag(e.deltaY)) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (newY >= 0) {
|
|
357
|
+
setDragDistance(newY);
|
|
358
|
+
}
|
|
359
|
+
}, [constrainDrag]);
|
|
360
|
+
const handleSwipedDown = react.useCallback((e) => {
|
|
361
|
+
if (isPassedThreshold(e.absY, threshold) && onCloseGesture) {
|
|
362
|
+
onCloseGesture();
|
|
363
|
+
}
|
|
364
|
+
setIsDragging(false);
|
|
365
|
+
setDragDistance(0);
|
|
366
|
+
}, [threshold, onCloseGesture]);
|
|
367
|
+
const handleSwipedUp = react.useCallback((e) => {
|
|
368
|
+
if (isPassedThreshold(e.absY, threshold) && onOpenGesture) {
|
|
369
|
+
onOpenGesture();
|
|
370
|
+
}
|
|
371
|
+
setIsDragging(false);
|
|
372
|
+
setDragDistance(0);
|
|
373
|
+
}, [threshold, onOpenGesture]);
|
|
374
|
+
const handleSwiped = react.useCallback((e) => {
|
|
375
|
+
if (onDragEnd) {
|
|
376
|
+
onDragEnd(e.deltaY, e.velocity);
|
|
377
|
+
}
|
|
378
|
+
}, [onDragEnd]);
|
|
335
379
|
const handlers = reactSwipeable.useSwipeable({
|
|
336
|
-
onTouchStartOrOnMouseDown:
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
setDragDistance(y);
|
|
342
|
-
setIsDragging(true);
|
|
343
|
-
},
|
|
344
|
-
onSwiping: (e) => {
|
|
345
|
-
const newY = currentY.current + e.deltaY;
|
|
346
|
-
if (constrainDrag && constrainDrag(e.deltaY)) {
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
if (newY >= 0) {
|
|
350
|
-
setDragDistance(newY);
|
|
351
|
-
}
|
|
352
|
-
},
|
|
353
|
-
onSwipedDown: (e) => {
|
|
354
|
-
if (isPassedThreshold(e.absY, threshold) && onCloseGesture) {
|
|
355
|
-
onCloseGesture();
|
|
356
|
-
}
|
|
357
|
-
setIsDragging(false);
|
|
358
|
-
setDragDistance(0);
|
|
359
|
-
},
|
|
360
|
-
onSwipedUp: (e) => {
|
|
361
|
-
if (isPassedThreshold(e.absY, threshold) && onOpenGesture) {
|
|
362
|
-
onOpenGesture();
|
|
363
|
-
}
|
|
364
|
-
setIsDragging(false);
|
|
365
|
-
setDragDistance(0);
|
|
366
|
-
},
|
|
367
|
-
onSwiped: (e) => {
|
|
368
|
-
onDragEnd && onDragEnd(e.deltaY, e.velocity);
|
|
369
|
-
},
|
|
380
|
+
onTouchStartOrOnMouseDown: handleTouchStartOrMouseDown,
|
|
381
|
+
onSwiping: handleSwiping,
|
|
382
|
+
onSwipedDown: handleSwipedDown,
|
|
383
|
+
onSwipedUp: handleSwipedUp,
|
|
384
|
+
onSwiped: handleSwiped,
|
|
370
385
|
trackMouse: true,
|
|
371
386
|
trackTouch: true,
|
|
372
387
|
preventScrollOnSwipe: true,
|
|
373
388
|
});
|
|
374
|
-
return { handlers, isDragging, dragDistance };
|
|
389
|
+
return react.useMemo(() => ({ handlers, isDragging, dragDistance, ref, element }), [handlers, isDragging, dragDistance, ref, element]);
|
|
375
390
|
};
|
|
376
391
|
|
|
377
392
|
/**
|
|
@@ -443,8 +458,7 @@ const SwipeableDrawer = ({ open = false, onClose, onOpen, onOpenGesture, onSnapP
|
|
|
443
458
|
setActiveSnapPoint(nextSnapPoint);
|
|
444
459
|
onSnapPointChange?.(nextSnapPoint);
|
|
445
460
|
}, [snapPoints, snapPointOffsets, activeSnapPointIndex, containerGeometry, onSnapPointChange]);
|
|
446
|
-
const { handlers, isDragging, dragDistance } = useSwipeHandlers({
|
|
447
|
-
ref: drawerRef,
|
|
461
|
+
const { handlers, isDragging, dragDistance, ref: swipeHandlersRef, } = useSwipeHandlers({
|
|
448
462
|
closingThreshold: CLOSING_THRESHOLD,
|
|
449
463
|
onCloseGesture: () => {
|
|
450
464
|
if (!snapPoints) {
|
|
@@ -467,6 +481,7 @@ const SwipeableDrawer = ({ open = false, onClose, onOpen, onOpenGesture, onSnapP
|
|
|
467
481
|
return false;
|
|
468
482
|
},
|
|
469
483
|
});
|
|
484
|
+
const mergedRef = reactComponents.useMergeRefs([drawerRef, swipeHandlersRef]);
|
|
470
485
|
const { blockScroll, restoreScroll } = reactComponents.useScrollBlock();
|
|
471
486
|
const { blockScroll: blockScrollContent, restoreScroll: restoreScrollContent } = reactComponents.useScrollBlock(document.getElementById("host-layout-content"));
|
|
472
487
|
react.useEffect(() => {
|
|
@@ -548,7 +563,7 @@ const SwipeableDrawer = ({ open = false, onClose, onOpen, onOpenGesture, onSnapP
|
|
|
548
563
|
restoreScrollContent();
|
|
549
564
|
applyDrawerStyles();
|
|
550
565
|
}, [onClose, restoreScroll, restoreScrollContent, applyDrawerStyles]);
|
|
551
|
-
return (jsxRuntime.jsxs(Drawer, { className: cvaSwipeableDrawer({ className }), keepMountedWhenClosed: keepMountedWhenClosed, onClose: onCloseHandler, onOpen: onOpenHandler, open: open, position: position, ref:
|
|
566
|
+
return (jsxRuntime.jsxs(Drawer, { className: cvaSwipeableDrawer({ className }), keepMountedWhenClosed: keepMountedWhenClosed, onClose: onCloseHandler, onOpen: onOpenHandler, open: open, position: position, ref: mergedRef, ...others, children: [jsxRuntime.jsx(DrawerPuller, { ...handlers }), children] }));
|
|
552
567
|
};
|
|
553
568
|
SwipeableDrawer.displayName = "SwipeableDrawer";
|
|
554
569
|
const cvaSwipeableDrawer = cssClassVarianceUtilities.cvaMerge([]);
|
package/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { registerTranslations } from '@trackunit/i18n-library-translation';
|
|
3
|
-
import { useViewportBreakpoints, Portal, Icon,
|
|
4
|
-
import { useEffect, useState, useRef, useCallback,
|
|
3
|
+
import { useViewportBreakpoints, Portal, Icon, useMeasure, useMergeRefs, useScrollBlock } from '@trackunit/react-components';
|
|
4
|
+
import { useEffect, useState, useRef, useCallback, useMemo, useImperativeHandle } from 'react';
|
|
5
5
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
6
6
|
import { useSwipeable } from 'react-swipeable';
|
|
7
7
|
|
|
@@ -319,57 +319,72 @@ const isPassedThreshold = (dragDistance, threshold) => {
|
|
|
319
319
|
};
|
|
320
320
|
/**
|
|
321
321
|
* Hook for handling swipe events on the drawer.
|
|
322
|
+
/**
|
|
323
|
+
* Hook for handling swipe events on the drawer.
|
|
324
|
+
*
|
|
325
|
+
* @param closingThreshold - The fraction (0-1) of the drawer's height needed to trigger open/close.
|
|
326
|
+
* @param onCloseGesture - Callback when a close gesture is detected (optional).
|
|
327
|
+
* @param onOpenGesture - Callback when an open gesture is detected (optional).
|
|
328
|
+
* @param onDragEnd - Callback when the drag/swipe gesture ends. Receives drag distance and velocity (optional).
|
|
329
|
+
* @param constrainDrag - Function to constrain/deny drag. Receives drag distance, returns boolean (optional).
|
|
322
330
|
*/
|
|
323
|
-
const useSwipeHandlers = ({
|
|
331
|
+
const useSwipeHandlers = ({ closingThreshold, onCloseGesture, onOpenGesture, onDragEnd, constrainDrag, }) => {
|
|
324
332
|
const [isDragging, setIsDragging] = useState(false);
|
|
325
333
|
const [dragDistance, setDragDistance] = useState(0);
|
|
326
334
|
const currentY = useRef(0);
|
|
327
335
|
const [currentHeight, setCurrentHeight] = useState(0);
|
|
328
|
-
const geometry =
|
|
336
|
+
const { geometry, ref, element } = useMeasure();
|
|
329
337
|
const [threshold, setThreshold] = useState(0);
|
|
330
338
|
useEffect(() => {
|
|
331
339
|
setThreshold(currentHeight * closingThreshold);
|
|
332
340
|
}, [currentHeight, closingThreshold]);
|
|
341
|
+
const handleTouchStartOrMouseDown = useCallback(() => {
|
|
342
|
+
const y = getElementYTranslation(element);
|
|
343
|
+
const height = geometry?.height ?? 0;
|
|
344
|
+
currentY.current = y;
|
|
345
|
+
setCurrentHeight(height);
|
|
346
|
+
setDragDistance(y);
|
|
347
|
+
setIsDragging(true);
|
|
348
|
+
}, [element, geometry]);
|
|
349
|
+
const handleSwiping = useCallback((e) => {
|
|
350
|
+
const newY = currentY.current + e.deltaY;
|
|
351
|
+
if (constrainDrag && constrainDrag(e.deltaY)) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (newY >= 0) {
|
|
355
|
+
setDragDistance(newY);
|
|
356
|
+
}
|
|
357
|
+
}, [constrainDrag]);
|
|
358
|
+
const handleSwipedDown = useCallback((e) => {
|
|
359
|
+
if (isPassedThreshold(e.absY, threshold) && onCloseGesture) {
|
|
360
|
+
onCloseGesture();
|
|
361
|
+
}
|
|
362
|
+
setIsDragging(false);
|
|
363
|
+
setDragDistance(0);
|
|
364
|
+
}, [threshold, onCloseGesture]);
|
|
365
|
+
const handleSwipedUp = useCallback((e) => {
|
|
366
|
+
if (isPassedThreshold(e.absY, threshold) && onOpenGesture) {
|
|
367
|
+
onOpenGesture();
|
|
368
|
+
}
|
|
369
|
+
setIsDragging(false);
|
|
370
|
+
setDragDistance(0);
|
|
371
|
+
}, [threshold, onOpenGesture]);
|
|
372
|
+
const handleSwiped = useCallback((e) => {
|
|
373
|
+
if (onDragEnd) {
|
|
374
|
+
onDragEnd(e.deltaY, e.velocity);
|
|
375
|
+
}
|
|
376
|
+
}, [onDragEnd]);
|
|
333
377
|
const handlers = useSwipeable({
|
|
334
|
-
onTouchStartOrOnMouseDown:
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
setDragDistance(y);
|
|
340
|
-
setIsDragging(true);
|
|
341
|
-
},
|
|
342
|
-
onSwiping: (e) => {
|
|
343
|
-
const newY = currentY.current + e.deltaY;
|
|
344
|
-
if (constrainDrag && constrainDrag(e.deltaY)) {
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
if (newY >= 0) {
|
|
348
|
-
setDragDistance(newY);
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
onSwipedDown: (e) => {
|
|
352
|
-
if (isPassedThreshold(e.absY, threshold) && onCloseGesture) {
|
|
353
|
-
onCloseGesture();
|
|
354
|
-
}
|
|
355
|
-
setIsDragging(false);
|
|
356
|
-
setDragDistance(0);
|
|
357
|
-
},
|
|
358
|
-
onSwipedUp: (e) => {
|
|
359
|
-
if (isPassedThreshold(e.absY, threshold) && onOpenGesture) {
|
|
360
|
-
onOpenGesture();
|
|
361
|
-
}
|
|
362
|
-
setIsDragging(false);
|
|
363
|
-
setDragDistance(0);
|
|
364
|
-
},
|
|
365
|
-
onSwiped: (e) => {
|
|
366
|
-
onDragEnd && onDragEnd(e.deltaY, e.velocity);
|
|
367
|
-
},
|
|
378
|
+
onTouchStartOrOnMouseDown: handleTouchStartOrMouseDown,
|
|
379
|
+
onSwiping: handleSwiping,
|
|
380
|
+
onSwipedDown: handleSwipedDown,
|
|
381
|
+
onSwipedUp: handleSwipedUp,
|
|
382
|
+
onSwiped: handleSwiped,
|
|
368
383
|
trackMouse: true,
|
|
369
384
|
trackTouch: true,
|
|
370
385
|
preventScrollOnSwipe: true,
|
|
371
386
|
});
|
|
372
|
-
return { handlers, isDragging, dragDistance };
|
|
387
|
+
return useMemo(() => ({ handlers, isDragging, dragDistance, ref, element }), [handlers, isDragging, dragDistance, ref, element]);
|
|
373
388
|
};
|
|
374
389
|
|
|
375
390
|
/**
|
|
@@ -441,8 +456,7 @@ const SwipeableDrawer = ({ open = false, onClose, onOpen, onOpenGesture, onSnapP
|
|
|
441
456
|
setActiveSnapPoint(nextSnapPoint);
|
|
442
457
|
onSnapPointChange?.(nextSnapPoint);
|
|
443
458
|
}, [snapPoints, snapPointOffsets, activeSnapPointIndex, containerGeometry, onSnapPointChange]);
|
|
444
|
-
const { handlers, isDragging, dragDistance } = useSwipeHandlers({
|
|
445
|
-
ref: drawerRef,
|
|
459
|
+
const { handlers, isDragging, dragDistance, ref: swipeHandlersRef, } = useSwipeHandlers({
|
|
446
460
|
closingThreshold: CLOSING_THRESHOLD,
|
|
447
461
|
onCloseGesture: () => {
|
|
448
462
|
if (!snapPoints) {
|
|
@@ -465,6 +479,7 @@ const SwipeableDrawer = ({ open = false, onClose, onOpen, onOpenGesture, onSnapP
|
|
|
465
479
|
return false;
|
|
466
480
|
},
|
|
467
481
|
});
|
|
482
|
+
const mergedRef = useMergeRefs([drawerRef, swipeHandlersRef]);
|
|
468
483
|
const { blockScroll, restoreScroll } = useScrollBlock();
|
|
469
484
|
const { blockScroll: blockScrollContent, restoreScroll: restoreScrollContent } = useScrollBlock(document.getElementById("host-layout-content"));
|
|
470
485
|
useEffect(() => {
|
|
@@ -546,7 +561,7 @@ const SwipeableDrawer = ({ open = false, onClose, onOpen, onOpenGesture, onSnapP
|
|
|
546
561
|
restoreScrollContent();
|
|
547
562
|
applyDrawerStyles();
|
|
548
563
|
}, [onClose, restoreScroll, restoreScrollContent, applyDrawerStyles]);
|
|
549
|
-
return (jsxs(Drawer, { className: cvaSwipeableDrawer({ className }), keepMountedWhenClosed: keepMountedWhenClosed, onClose: onCloseHandler, onOpen: onOpenHandler, open: open, position: position, ref:
|
|
564
|
+
return (jsxs(Drawer, { className: cvaSwipeableDrawer({ className }), keepMountedWhenClosed: keepMountedWhenClosed, onClose: onCloseHandler, onOpen: onOpenHandler, open: open, position: position, ref: mergedRef, ...others, children: [jsx(DrawerPuller, { ...handlers }), children] }));
|
|
550
565
|
};
|
|
551
566
|
SwipeableDrawer.displayName = "SwipeableDrawer";
|
|
552
567
|
const cvaSwipeableDrawer = cvaMerge([]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-drawer",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.104",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"react": "19.0.0",
|
|
11
11
|
"react-swipeable": "^7.0.1",
|
|
12
|
-
"@trackunit/react-components": "1.10.
|
|
13
|
-
"@trackunit/css-class-variance-utilities": "1.7.
|
|
14
|
-
"@trackunit/ui-icons": "1.7.
|
|
15
|
-
"@trackunit/i18n-library-translation": "1.7.
|
|
12
|
+
"@trackunit/react-components": "1.10.43",
|
|
13
|
+
"@trackunit/css-class-variance-utilities": "1.7.73",
|
|
14
|
+
"@trackunit/ui-icons": "1.7.74",
|
|
15
|
+
"@trackunit/i18n-library-translation": "1.7.87"
|
|
16
16
|
},
|
|
17
17
|
"module": "./index.esm.js",
|
|
18
18
|
"main": "./index.cjs.js",
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { type RefObject } from "react";
|
|
2
1
|
interface UseSwipeHandlersProps {
|
|
3
|
-
ref: RefObject<HTMLDivElement | null>;
|
|
4
2
|
closingThreshold: number;
|
|
5
3
|
onCloseGesture?: () => void;
|
|
6
4
|
onOpenGesture?: () => void;
|
|
@@ -16,10 +14,20 @@ interface UseSwipeHandlersProps {
|
|
|
16
14
|
export declare const getElementYTranslation: (element?: HTMLElement | null) => number;
|
|
17
15
|
/**
|
|
18
16
|
* Hook for handling swipe events on the drawer.
|
|
17
|
+
/**
|
|
18
|
+
* Hook for handling swipe events on the drawer.
|
|
19
|
+
*
|
|
20
|
+
* @param closingThreshold - The fraction (0-1) of the drawer's height needed to trigger open/close.
|
|
21
|
+
* @param onCloseGesture - Callback when a close gesture is detected (optional).
|
|
22
|
+
* @param onOpenGesture - Callback when an open gesture is detected (optional).
|
|
23
|
+
* @param onDragEnd - Callback when the drag/swipe gesture ends. Receives drag distance and velocity (optional).
|
|
24
|
+
* @param constrainDrag - Function to constrain/deny drag. Receives drag distance, returns boolean (optional).
|
|
19
25
|
*/
|
|
20
|
-
export declare const useSwipeHandlers: ({
|
|
26
|
+
export declare const useSwipeHandlers: ({ closingThreshold, onCloseGesture, onOpenGesture, onDragEnd, constrainDrag, }: UseSwipeHandlersProps) => {
|
|
21
27
|
handlers: import("react-swipeable").SwipeableHandlers;
|
|
22
28
|
isDragging: boolean;
|
|
23
29
|
dragDistance: number;
|
|
30
|
+
ref: import("react").RefCallback<HTMLDivElement>;
|
|
31
|
+
element: HTMLDivElement | null;
|
|
24
32
|
};
|
|
25
33
|
export {};
|