@trackunit/react-drawer 1.7.103 → 1.7.105

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
@@ -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 = ({ ref, closingThreshold, onCloseGesture, onOpenGesture, onDragEnd, constrainDrag, }) => {
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.useMeasureElement(ref);
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
- const y = getElementYTranslation(ref.current);
338
- const height = geometry?.height ?? 0;
339
- currentY.current = y;
340
- setCurrentHeight(height);
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: drawerRef, ...others, children: [jsxRuntime.jsx(DrawerPuller, { ...handlers }), children] }));
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, useMeasureElement, useMeasure, useScrollBlock } from '@trackunit/react-components';
4
- import { useEffect, useState, useRef, useCallback, useImperativeHandle, useMemo } from 'react';
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 = ({ ref, closingThreshold, onCloseGesture, onOpenGesture, onDragEnd, constrainDrag, }) => {
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 = useMeasureElement(ref);
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
- const y = getElementYTranslation(ref.current);
336
- const height = geometry?.height ?? 0;
337
- currentY.current = y;
338
- setCurrentHeight(height);
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: drawerRef, ...others, children: [jsx(DrawerPuller, { ...handlers }), children] }));
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.103",
3
+ "version": "1.7.105",
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.42",
13
- "@trackunit/css-class-variance-utilities": "1.7.72",
14
- "@trackunit/ui-icons": "1.7.73",
15
- "@trackunit/i18n-library-translation": "1.7.86"
12
+ "@trackunit/react-components": "1.10.44",
13
+ "@trackunit/css-class-variance-utilities": "1.7.73",
14
+ "@trackunit/ui-icons": "1.7.74",
15
+ "@trackunit/i18n-library-translation": "1.7.88"
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: ({ ref, closingThreshold, onCloseGesture, onOpenGesture, onDragEnd, constrainDrag, }: UseSwipeHandlersProps) => {
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 {};