@expofp/ui 3.35.0 → 3.35.2
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.
|
@@ -52,6 +52,15 @@ const Overlay = ({ children, open, size = 'medium', particles, className, onChan
|
|
|
52
52
|
const overlayPanelRef = useRef(null);
|
|
53
53
|
const scrollRef = useRef(null);
|
|
54
54
|
const openedAtRef = useRef(undefined);
|
|
55
|
+
// The scroll container is published to descendants through context, and context is read during
|
|
56
|
+
// render — where a ref is still null on the render that mounts the element. Held as state as
|
|
57
|
+
// well, written from the ref callback: that write lands in the mount commit, so consumers see the
|
|
58
|
+
// element as soon as it exists rather than on whichever later render happens to come by.
|
|
59
|
+
const [scrollElement, setScrollElement] = useState(null);
|
|
60
|
+
const attachScroll = useCallback((node) => {
|
|
61
|
+
scrollRef.current = node;
|
|
62
|
+
setScrollElement(node);
|
|
63
|
+
}, []);
|
|
55
64
|
// The snap point the sheet actually sits on. The prop may be undefined
|
|
56
65
|
// before the host has chosen one, and a drag needs a value to start from.
|
|
57
66
|
const [currentSnap, setCurrentSnap] = useState(size);
|
|
@@ -164,26 +173,35 @@ const Overlay = ({ children, open, size = 'medium', particles, className, onChan
|
|
|
164
173
|
setShouldRender(true);
|
|
165
174
|
setIsAnimating(true);
|
|
166
175
|
openedAtRef.current = performance.now();
|
|
167
|
-
|
|
168
|
-
setSize(sizeRef.current);
|
|
169
|
-
setIsAnimating(false);
|
|
170
|
-
}, 10);
|
|
171
|
-
return () => clearTimeout(timer);
|
|
176
|
+
return;
|
|
172
177
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
setCollapsed(true);
|
|
178
|
-
}
|
|
179
|
-
const timer = setTimeout(() => {
|
|
180
|
-
setShouldRender(false);
|
|
181
|
-
setIsAnimating(false);
|
|
182
|
-
setIsScrolled(false);
|
|
183
|
-
}, parseFloat(TRANSITION_DURATION) * 1000);
|
|
184
|
-
return () => clearTimeout(timer);
|
|
178
|
+
setIsAnimating(true);
|
|
179
|
+
openedAtRef.current = undefined;
|
|
180
|
+
if (mobile) {
|
|
181
|
+
setCollapsed(true);
|
|
185
182
|
}
|
|
186
|
-
|
|
183
|
+
const timer = setTimeout(() => {
|
|
184
|
+
setShouldRender(false);
|
|
185
|
+
setIsAnimating(false);
|
|
186
|
+
setIsScrolled(false);
|
|
187
|
+
}, parseFloat(TRANSITION_DURATION) * 1000);
|
|
188
|
+
return () => clearTimeout(timer);
|
|
189
|
+
}, [open, mobile]);
|
|
190
|
+
// The step after the mount: the sheet mounts at zero height and takes its size a tick later, so
|
|
191
|
+
// the height transition has a frame to start from. Keyed on `shouldRender` rather than run from
|
|
192
|
+
// the effect above, which fires on the render that only *asked* for the mount and returned null:
|
|
193
|
+
// a timer started there raced the mount render, and when it won, React batched the size flip
|
|
194
|
+
// into the mount itself — no transition, and no second render for anything the mount render
|
|
195
|
+
// could not yet know.
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
if (!open || !shouldRender)
|
|
198
|
+
return;
|
|
199
|
+
const timer = setTimeout(() => {
|
|
200
|
+
setSize(sizeRef.current);
|
|
201
|
+
setIsAnimating(false);
|
|
202
|
+
}, 10);
|
|
203
|
+
return () => clearTimeout(timer);
|
|
204
|
+
}, [open, shouldRender, setSize]);
|
|
187
205
|
// Host-driven size changes (details open at full, the planner at medium).
|
|
188
206
|
// The sheet's own reports come back through here too, already applied.
|
|
189
207
|
useEffect(() => {
|
|
@@ -198,7 +216,7 @@ const Overlay = ({ children, open, size = 'medium', particles, className, onChan
|
|
|
198
216
|
}, [open, isAnimating, onScrollStateChange, scrollResetKey]);
|
|
199
217
|
if (!shouldRender)
|
|
200
218
|
return null;
|
|
201
|
-
return (_jsx(OverlayScrollContext, { value:
|
|
219
|
+
return (_jsx(OverlayScrollContext, { value: scrollElement, children: _jsxs("div", { className: cn('efp-overlay', {
|
|
202
220
|
'efp-overlay--draggable': dragging,
|
|
203
221
|
'efp-overlay--keyboard': mobile && keyboardInset > 0,
|
|
204
222
|
'efp-overlay--full': currentSnap === 'full',
|
|
@@ -207,7 +225,7 @@ const Overlay = ({ children, open, size = 'medium', particles, className, onChan
|
|
|
207
225
|
'efp-overlay--hidden': !mobile && !open,
|
|
208
226
|
'efp-overlay--scrolled': isScrolled,
|
|
209
227
|
'efp-overlay--forced-full': forceFull && mobile,
|
|
210
|
-
}, className), style: positioningStyles, ref: overlayPanelRef, onPointerDown: onPointerDown, children: [!disableDrag && _jsx("div", { className: "efp-overlay__draghandle", "data-sheet-handle": true }), _jsxs("div", { className: "efp-overlay__scroll", ref:
|
|
228
|
+
}, className), style: positioningStyles, ref: overlayPanelRef, onPointerDown: onPointerDown, children: [!disableDrag && _jsx("div", { className: "efp-overlay__draghandle", "data-sheet-handle": true }), _jsxs("div", { className: "efp-overlay__scroll", ref: attachScroll, onScroll: () => {
|
|
211
229
|
handleScroll();
|
|
212
230
|
debouncedScrollActivity();
|
|
213
231
|
}, children: [particles, _jsx("div", { className: "efp-overlay__content", children: children ? children : noContentLabel })] })] }) }));
|