colibri-ui 0.8.86 → 0.8.88

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/Drawer/Drawer.js CHANGED
@@ -3,6 +3,7 @@
3
3
  var tslib = require('tslib');
4
4
  var React = require('react');
5
5
  var ReactDOM = require('react-dom');
6
+ var index = require('../hooks/useLatestRef/index.js');
6
7
  var styles = require('./Drawer.module.css');
7
8
 
8
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -34,17 +35,23 @@ const Drawer = /*#__PURE__*/React.forwardRef(function DrawerRoot(_a, forwardedRe
34
35
  focusAfterRef,
35
36
  portalContainer,
36
37
  onClose,
38
+ onClosed,
37
39
  onEscKeyDown,
38
40
  onOverlayClick,
39
41
  className,
40
42
  style,
41
43
  children
42
44
  } = _a,
43
- rest = tslib.__rest(_a, ["opened", "placement", "width", "height", "offset", "zIndex", "asModal", "withBlur", "closeOnEsc", "closeOnOverlayClick", "borderRadius", "customBackgroundColor", "customContentBackgroundColor", "animationInfo", "initialFocusRef", "focusAfterRef", "portalContainer", "onClose", "onEscKeyDown", "onOverlayClick", "className", "style", "children"]);
45
+ rest = tslib.__rest(_a, ["opened", "placement", "width", "height", "offset", "zIndex", "asModal", "withBlur", "closeOnEsc", "closeOnOverlayClick", "borderRadius", "customBackgroundColor", "customContentBackgroundColor", "animationInfo", "initialFocusRef", "focusAfterRef", "portalContainer", "onClose", "onClosed", "onEscKeyDown", "onOverlayClick", "className", "style", "children"]);
44
46
  const panelRef = React.useRef(null);
45
47
  const previousFocus = React.useRef(null);
46
48
  const [rendered, setRendered] = React.useState(opened);
47
49
  const [closing, setClosing] = React.useState(false);
50
+ // Callbacks from props change on every parent render; effects read them
51
+ // from refs, so focus, scroll lock and the closing timer do not restart.
52
+ const onClosedRef = index.useLatestRef(onClosed);
53
+ const onCloseRef = index.useLatestRef(onClose);
54
+ const onEscKeyDownRef = index.useLatestRef(onEscKeyDown);
48
55
  const setPanelRef = element => {
49
56
  panelRef.current = element;
50
57
  if (typeof forwardedRef === "function") forwardedRef(element);else if (forwardedRef) forwardedRef.current = element;
@@ -58,11 +65,13 @@ const Drawer = /*#__PURE__*/React.forwardRef(function DrawerRoot(_a, forwardedRe
58
65
  if (!rendered) return;
59
66
  setClosing(true);
60
67
  const timeout = window.setTimeout(() => {
68
+ var _a;
61
69
  setRendered(false);
62
70
  setClosing(false);
71
+ (_a = onClosedRef.current) === null || _a === void 0 ? void 0 : _a.call(onClosedRef);
63
72
  }, 200);
64
73
  return () => window.clearTimeout(timeout);
65
- }, [opened, rendered]);
74
+ }, [onClosedRef, opened, rendered]);
66
75
  React.useEffect(() => {
67
76
  if (!opened || typeof document === "undefined") return;
68
77
  previousFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -75,9 +84,10 @@ const Drawer = /*#__PURE__*/React.forwardRef(function DrawerRoot(_a, forwardedRe
75
84
  (_d = (_c = (_b = initialFocusRef === null || initialFocusRef === void 0 ? void 0 : initialFocusRef.current) !== null && _b !== void 0 ? _b : firstFocusable) !== null && _c !== void 0 ? _c : panelRef.current) === null || _d === void 0 ? void 0 : _d.focus();
76
85
  });
77
86
  const handleKeyDown = event => {
87
+ var _a, _b;
78
88
  if (event.key === "Escape" && closeOnEsc) {
79
- onEscKeyDown === null || onEscKeyDown === void 0 ? void 0 : onEscKeyDown(event);
80
- if (!event.defaultPrevented) onClose === null || onClose === void 0 ? void 0 : onClose();
89
+ (_a = onEscKeyDownRef.current) === null || _a === void 0 ? void 0 : _a.call(onEscKeyDownRef, event);
90
+ if (!event.defaultPrevented) (_b = onCloseRef.current) === null || _b === void 0 ? void 0 : _b.call(onCloseRef);
81
91
  return;
82
92
  }
83
93
  if (!asModal || event.key !== "Tab" || !panelRef.current) return;
@@ -105,7 +115,7 @@ const Drawer = /*#__PURE__*/React.forwardRef(function DrawerRoot(_a, forwardedRe
105
115
  if (asModal) document.body.style.overflow = previousOverflow;
106
116
  (_a = focusAfterElement !== null && focusAfterElement !== void 0 ? focusAfterElement : previousFocus.current) === null || _a === void 0 ? void 0 : _a.focus();
107
117
  };
108
- }, [opened, asModal, closeOnEsc, focusAfterRef, initialFocusRef, onClose, onEscKeyDown]);
118
+ }, [opened, asModal, closeOnEsc, focusAfterRef, initialFocusRef, onCloseRef, onEscKeyDownRef]);
109
119
  if (!rendered || typeof document === "undefined") return null;
110
120
  const sidePlacement = placement === "left" || placement === "right";
111
121
  const panelStyle = Object.assign(Object.assign({}, style), {
@@ -24,6 +24,8 @@ export interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "onAni
24
24
  focusAfterRef?: RefObject<HTMLElement | null>;
25
25
  portalContainer?: HTMLElement | null;
26
26
  onClose?: () => void;
27
+ /** Called once the closing animation has finished and the drawer is removed. */
28
+ onClosed?: () => void;
27
29
  onEscKeyDown?: (event: KeyboardEvent) => void;
28
30
  onOverlayClick?: MouseEventHandler<HTMLDivElement>;
29
31
  }
package/Sheet/Sheet.js CHANGED
@@ -4,6 +4,7 @@ var tslib = require('tslib');
4
4
  var React = require('react');
5
5
  var ReactDOM = require('react-dom');
6
6
  var clsx = require('clsx');
7
+ var index$1 = require('../hooks/useLatestRef/index.js');
7
8
  var index = require('../hooks/useModalStack/index.js');
8
9
  var styles = require('./Sheet.module.css');
9
10
 
@@ -32,6 +33,7 @@ const Sheet = /*#__PURE__*/React.forwardRef(function SheetComponent(_a, forwarde
32
33
  var {
33
34
  open,
34
35
  onOpenChange,
36
+ onClosed,
35
37
  title,
36
38
  description,
37
39
  header,
@@ -58,7 +60,7 @@ const Sheet = /*#__PURE__*/React.forwardRef(function SheetComponent(_a, forwarde
58
60
  "aria-labelledby": ariaLabelledBy,
59
61
  "aria-describedby": ariaDescribedBy
60
62
  } = _a,
61
- rest = tslib.__rest(_a, ["open", "onOpenChange", "title", "description", "header", "footer", "snapPoints", "snapPoint", "defaultSnapPoint", "onSnapPointChange", "modal", "blurOverlay", "closeOnOverlayClick", "closeOnEscape", "draggable", "showHandle", "lockBodyScroll", "portalContainer", "initialFocusRef", "returnFocusRef", "zIndex", "className", "style", "children", "aria-label", "aria-labelledby", "aria-describedby"]);
63
+ rest = tslib.__rest(_a, ["open", "onOpenChange", "onClosed", "title", "description", "header", "footer", "snapPoints", "snapPoint", "defaultSnapPoint", "onSnapPointChange", "modal", "blurOverlay", "closeOnOverlayClick", "closeOnEscape", "draggable", "showHandle", "lockBodyScroll", "portalContainer", "initialFocusRef", "returnFocusRef", "zIndex", "className", "style", "children", "aria-label", "aria-labelledby", "aria-describedby"]);
62
64
  const normalizedPoints = snapPoints.length ? snapPoints : defaultSnapPoints;
63
65
  const controlledSnap = snapPoint !== undefined;
64
66
  const [internalSnap, setInternalSnap] = React.useState(() => findPoint(normalizedPoints, defaultSnapPoint));
@@ -88,6 +90,10 @@ const Sheet = /*#__PURE__*/React.forwardRef(function SheetComponent(_a, forwarde
88
90
  if (!controlledSnap) setInternalSnap(next);
89
91
  onSnapPointChange === null || onSnapPointChange === void 0 ? void 0 : onSnapPointChange(next);
90
92
  };
93
+ // Callbacks from props change on every parent render; effects read them
94
+ // from refs, so focus, scroll lock and the closing timer do not restart.
95
+ const onClosedRef = index$1.useLatestRef(onClosed);
96
+ const onOpenChangeRef = index$1.useLatestRef(onOpenChange);
91
97
  React.useEffect(() => {
92
98
  if (open) {
93
99
  setRendered(true);
@@ -98,11 +104,13 @@ const Sheet = /*#__PURE__*/React.forwardRef(function SheetComponent(_a, forwarde
98
104
  setClosing(true);
99
105
  const duration = panelRef.current ? Number.parseFloat(getComputedStyle(panelRef.current).animationDuration) * 1000 : 220;
100
106
  const timer = window.setTimeout(() => {
107
+ var _a;
101
108
  setRendered(false);
102
109
  setClosing(false);
110
+ (_a = onClosedRef.current) === null || _a === void 0 ? void 0 : _a.call(onClosedRef);
103
111
  }, Number.isFinite(duration) ? duration : 220);
104
112
  return () => window.clearTimeout(timer);
105
- }, [open, rendered]);
113
+ }, [onClosedRef, open, rendered]);
106
114
  React.useEffect(() => {
107
115
  var _a;
108
116
  if (!open || typeof document === "undefined") return;
@@ -119,7 +127,7 @@ const Sheet = /*#__PURE__*/React.forwardRef(function SheetComponent(_a, forwarde
119
127
  if (event.defaultPrevented || !isTopmost()) return;
120
128
  if (event.key === "Escape" && closeOnEscape) {
121
129
  event.preventDefault();
122
- onOpenChange(false, "escape");
130
+ onOpenChangeRef.current(false, "escape");
123
131
  return;
124
132
  }
125
133
  if (!modal || event.key !== "Tab" || !panelRef.current) return;
@@ -146,7 +154,7 @@ const Sheet = /*#__PURE__*/React.forwardRef(function SheetComponent(_a, forwarde
146
154
  if (modal && lockBodyScroll) document.body.style.overflow = previousOverflow;
147
155
  returnFocusElement === null || returnFocusElement === void 0 ? void 0 : returnFocusElement.focus();
148
156
  };
149
- }, [open, modal, lockBodyScroll, closeOnEscape, onOpenChange, initialFocusRef, returnFocusRef, isTopmost]);
157
+ }, [open, modal, lockBodyScroll, closeOnEscape, onOpenChangeRef, initialFocusRef, returnFocusRef, isTopmost]);
150
158
  const startDrag = event => {
151
159
  if (!draggable || !panelRef.current) return;
152
160
  event.currentTarget.setPointerCapture(event.pointerId);
@@ -4,6 +4,8 @@ export type SheetCloseReason = "overlay" | "escape" | "drag";
4
4
  export interface SheetProps extends Omit<HTMLAttributes<HTMLDivElement>, "title" | "onChange"> {
5
5
  open: boolean;
6
6
  onOpenChange: (open: boolean, reason?: SheetCloseReason) => void;
7
+ /** Called once the closing animation has finished and the sheet is removed. */
8
+ onClosed?: () => void;
7
9
  title?: ReactNode;
8
10
  description?: ReactNode;
9
11
  header?: ReactNode;