@depup/react-aria-components 1.21.1-depup.0 → 1.22.1-depup.0
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/README.md +4 -3
- package/Sheet/package.json +5 -0
- package/changes.json +6 -2
- package/dist/exports/Sheet.cjs +30 -0
- package/dist/exports/Sheet.cjs.map +1 -0
- package/dist/exports/Sheet.js +21 -0
- package/dist/exports/Sheet.js.map +1 -0
- package/dist/exports/Sheet.mjs +21 -0
- package/dist/exports/Sheet.mjs.map +1 -0
- package/dist/exports/TokenField.cjs +1 -0
- package/dist/exports/TokenField.cjs.map +1 -1
- package/dist/exports/TokenField.js +2 -2
- package/dist/exports/TokenField.js.map +1 -1
- package/dist/exports/TokenField.mjs +2 -2
- package/dist/exports/TokenField.mjs.map +1 -1
- package/dist/exports/index.cjs +7 -0
- package/dist/exports/index.cjs.map +1 -1
- package/dist/exports/index.js +3 -1
- package/dist/exports/index.js.map +1 -1
- package/dist/exports/index.mjs +3 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/private/Breadcrumbs.cjs +1 -1
- package/dist/private/Breadcrumbs.cjs.map +1 -1
- package/dist/private/Breadcrumbs.js +1 -1
- package/dist/private/Breadcrumbs.js.map +1 -1
- package/dist/private/Breadcrumbs.mjs +1 -1
- package/dist/private/Breadcrumbs.mjs.map +1 -1
- package/dist/private/Modal.cjs +56 -11
- package/dist/private/Modal.cjs.map +1 -1
- package/dist/private/Modal.js +61 -14
- package/dist/private/Modal.js.map +1 -1
- package/dist/private/Modal.mjs +58 -14
- package/dist/private/Modal.mjs.map +1 -1
- package/dist/private/NavigationTree.cjs.map +1 -1
- package/dist/private/NavigationTree.js.map +1 -1
- package/dist/private/NavigationTree.mjs.map +1 -1
- package/dist/private/Popover.cjs +10 -2
- package/dist/private/Popover.cjs.map +1 -1
- package/dist/private/Popover.js +10 -2
- package/dist/private/Popover.js.map +1 -1
- package/dist/private/Popover.mjs +10 -2
- package/dist/private/Popover.mjs.map +1 -1
- package/dist/private/Sheet.cjs +827 -0
- package/dist/private/Sheet.cjs.map +1 -0
- package/dist/private/Sheet.js +820 -0
- package/dist/private/Sheet.js.map +1 -0
- package/dist/private/Sheet.mjs +814 -0
- package/dist/private/Sheet.mjs.map +1 -0
- package/dist/types/exports/Sheet.d.ts +3 -0
- package/dist/types/exports/TokenField.d.ts +2 -2
- package/dist/types/exports/index.d.ts +2 -0
- package/dist/types/src/Modal.d.ts +28 -1
- package/dist/types/src/NavigationTree.d.ts +1 -1
- package/dist/types/src/Sheet.d.ts +149 -0
- package/package.json +13 -8
|
@@ -0,0 +1,820 @@
|
|
|
1
|
+
import {useRenderProps as $b7b7a92703138c9b$export$4d86445c2cf5e3} from "./utils.js";
|
|
2
|
+
import {Dialog as $acf8e70c2f419f18$export$3ddf2d174ce01153, DialogTrigger as $acf8e70c2f419f18$export$2e1e1122cf0cba88, OverlayTriggerStateContext as $acf8e70c2f419f18$export$d2f961adcb0afbe} from "./Dialog.js";
|
|
3
|
+
import {InternalModalContext as $46ccb41fa2c44f44$export$6bc057cefccad9c8, Modal as $46ccb41fa2c44f44$export$2b77a92f1a5ad772, ModalOverlay as $46ccb41fa2c44f44$export$8948f78d83984c69} from "./Modal.js";
|
|
4
|
+
import {filterDOMProps as $d0bvy$filterDOMProps} from "react-aria/filterDOMProps";
|
|
5
|
+
import {isIOS as $d0bvy$isIOS, isSafari as $d0bvy$isSafari} from "react-aria/private/utils/platform";
|
|
6
|
+
import {mergeRefs as $d0bvy$mergeRefs} from "react-aria/mergeRefs";
|
|
7
|
+
import {PressResponder as $d0bvy$PressResponder} from "react-aria/private/interactions/PressResponder";
|
|
8
|
+
import $d0bvy$react, {createContext as $d0bvy$createContext, forwardRef as $d0bvy$forwardRef, useContext as $d0bvy$useContext, useMemo as $d0bvy$useMemo, useState as $d0bvy$useState, useRef as $d0bvy$useRef, useCallback as $d0bvy$useCallback} from "react";
|
|
9
|
+
import {useEffectEvent as $d0bvy$useEffectEvent} from "react-aria/private/utils/useEffectEvent";
|
|
10
|
+
import {useId as $d0bvy$useId} from "react-aria/useId";
|
|
11
|
+
import {useLayoutEffect as $d0bvy$useLayoutEffect} from "react-aria/private/utils/useLayoutEffect";
|
|
12
|
+
import {useLocale as $d0bvy$useLocale} from "react-aria/I18nProvider";
|
|
13
|
+
import {useObjectRef as $d0bvy$useObjectRef} from "react-aria/useObjectRef";
|
|
14
|
+
import {useOverlayTriggerState as $d0bvy$useOverlayTriggerState} from "react-stately/useOverlayTriggerState";
|
|
15
|
+
import {useSyncExternalStore as $d0bvy$useSyncExternalStore} from "use-sync-external-store/shim/index.js";
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
19
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
20
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
21
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
24
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
25
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
26
|
+
* governing permissions and limitations under the License.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const $393b9725ff54df2c$var$InternalSheetContext = /*#__PURE__*/ (0, $d0bvy$createContext)(null);
|
|
43
|
+
let $393b9725ff54df2c$var$sheetStack = [];
|
|
44
|
+
let $393b9725ff54df2c$var$stackListeners = new Set();
|
|
45
|
+
function $393b9725ff54df2c$var$emitStackChange() {
|
|
46
|
+
// Hoist every mounted sheet's timeline name to the root so a parent
|
|
47
|
+
// can still resolve the child's timeline by name.
|
|
48
|
+
// TODO: don't override existing timelines declared in CSS or inline styles.
|
|
49
|
+
let names = Array.from({
|
|
50
|
+
length: $393b9725ff54df2c$var$sheetStack.length
|
|
51
|
+
}).map((_, i)=>`--sheet-timeline-${i}`).join(', ');
|
|
52
|
+
document.documentElement.style.setProperty('timeline-scope', names);
|
|
53
|
+
$393b9725ff54df2c$var$stackListeners.forEach((listener)=>listener());
|
|
54
|
+
}
|
|
55
|
+
function $393b9725ff54df2c$var$subscribeStack(listener) {
|
|
56
|
+
$393b9725ff54df2c$var$stackListeners.add(listener);
|
|
57
|
+
return ()=>{
|
|
58
|
+
$393b9725ff54df2c$var$stackListeners.delete(listener);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function $393b9725ff54df2c$var$registerSheet(config) {
|
|
62
|
+
$393b9725ff54df2c$var$sheetStack = [
|
|
63
|
+
...$393b9725ff54df2c$var$sheetStack,
|
|
64
|
+
config
|
|
65
|
+
];
|
|
66
|
+
$393b9725ff54df2c$var$emitStackChange();
|
|
67
|
+
return ()=>{
|
|
68
|
+
$393b9725ff54df2c$var$sheetStack = $393b9725ff54df2c$var$sheetStack.filter((e)=>e.id !== config.id);
|
|
69
|
+
$393b9725ff54df2c$var$emitStackChange();
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function $393b9725ff54df2c$var$getSheetStack() {
|
|
73
|
+
return $393b9725ff54df2c$var$sheetStack;
|
|
74
|
+
}
|
|
75
|
+
const $393b9725ff54df2c$var$supportsViewTimeline = typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('animation-timeline: view()');
|
|
76
|
+
function $393b9725ff54df2c$export$de69b9b0343a1903(props) {
|
|
77
|
+
return /*#__PURE__*/ (0, $d0bvy$react).createElement((0, $acf8e70c2f419f18$export$2e1e1122cf0cba88), props, /*#__PURE__*/ (0, $d0bvy$react).createElement((0, $d0bvy$PressResponder), {
|
|
78
|
+
isPressed: false
|
|
79
|
+
}, props.children));
|
|
80
|
+
}
|
|
81
|
+
// Additional padding added to the viewport to account for browser toolbar.
|
|
82
|
+
// More content than 100lvh is actually visible on iOS, even when the toolbar is collapsed.
|
|
83
|
+
const $393b9725ff54df2c$var$VIEWPORT_PADDING = (0, $d0bvy$isIOS)() && (0, $d0bvy$isSafari)() ? 'calc(100lvh - 100svh + 58px)' : '0px';
|
|
84
|
+
const $393b9725ff54df2c$var$viewportPadding = (after, axis)=>after && axis === 'y' ? $393b9725ff54df2c$var$VIEWPORT_PADDING : '0px';
|
|
85
|
+
const $393b9725ff54df2c$export$48dbb295cbd054d8 = /*#__PURE__*/ (0, $d0bvy$forwardRef)(function SheetOverlay(props, domRef) {
|
|
86
|
+
let { children: children, preventDismissal: preventDismissal = false } = props;
|
|
87
|
+
let { direction: direction } = (0, $d0bvy$useLocale)();
|
|
88
|
+
var _props_position;
|
|
89
|
+
let position = $393b9725ff54df2c$var$resolveDirection((_props_position = props.position) !== null && _props_position !== void 0 ? _props_position : 'bottom', direction);
|
|
90
|
+
let swipeDirection = props.swipeDirection ? $393b9725ff54df2c$var$resolveDirection(props.swipeDirection, direction) : position === 'center' ? 'vertical' : position;
|
|
91
|
+
// Resolve the state the same way ModalOverlay does, so that swiping to close works
|
|
92
|
+
// both inside a SheetTrigger and when the open state is passed directly to SheetOverlay.
|
|
93
|
+
let contextState = (0, $d0bvy$useContext)((0, $acf8e70c2f419f18$export$d2f961adcb0afbe));
|
|
94
|
+
let localState = (0, $d0bvy$useOverlayTriggerState)(props);
|
|
95
|
+
let state = props.isOpen != null || props.defaultOpen != null || !contextState ? localState : contextState;
|
|
96
|
+
let onCloseEvent = (0, $d0bvy$useEffectEvent)(()=>{
|
|
97
|
+
state.close();
|
|
98
|
+
});
|
|
99
|
+
let { axis: axis, before: before, after: after, maxScroll: maxScroll, enteredScroll: enteredScroll, viewRange: viewRange, viewDirection: viewDirection, viewIterations: viewIterations } = $393b9725ff54df2c$var$getSwipeConfig(swipeDirection);
|
|
100
|
+
let id = (0, $d0bvy$useId)();
|
|
101
|
+
let stackItem = (0, $d0bvy$useMemo)(()=>({
|
|
102
|
+
id: id,
|
|
103
|
+
range: viewRange,
|
|
104
|
+
direction: viewDirection,
|
|
105
|
+
iterations: viewIterations
|
|
106
|
+
}), [
|
|
107
|
+
id,
|
|
108
|
+
viewRange,
|
|
109
|
+
viewDirection,
|
|
110
|
+
viewIterations
|
|
111
|
+
]);
|
|
112
|
+
let [isExpanded, setExpanded] = (0, $d0bvy$useState)(false);
|
|
113
|
+
let isVisible = (0, $d0bvy$useRef)(false);
|
|
114
|
+
let ref = (0, $d0bvy$useCallback)((element)=>{
|
|
115
|
+
if (!element) return;
|
|
116
|
+
// Sheets that rest at scroll 0 (top/left) mount already entered. Move them to the exit position
|
|
117
|
+
// before observing, since onEnter may be deferred (e.g. while waiting for the software keyboard),
|
|
118
|
+
// and the observer would otherwise see the sheet as entered and then close it once onEnter
|
|
119
|
+
// jumps to the exit position.
|
|
120
|
+
if (enteredScroll === 0) {
|
|
121
|
+
let scroller = element.querySelector('[data-sheet-scroll]');
|
|
122
|
+
if (scroller) {
|
|
123
|
+
let vp = axis === 'y' ? window.innerHeight : window.innerWidth;
|
|
124
|
+
$393b9725ff54df2c$var$scrollAlongAxis(scroller, axis, maxScroll / 100 * vp);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// iOS displays content outside the reported viewport, e.g. behind the browser toolbar.
|
|
128
|
+
// Add additional margin to account for that so that the sheet disappears only when it is entirely invisible.
|
|
129
|
+
let rootMargin = `0px 0px ${$393b9725ff54df2c$var$calcToPx($393b9725ff54df2c$var$viewportPadding(after, axis))} 0px`;
|
|
130
|
+
let hasEntered = false;
|
|
131
|
+
let observer = new IntersectionObserver((entries)=>{
|
|
132
|
+
let entry = entries[0];
|
|
133
|
+
// Expose whether the sheet is resting at its fully-entered detent (all of it revealed). Apps
|
|
134
|
+
// can use `[data-expanded]` to only make the sheet's inner content scrollable once expanded,
|
|
135
|
+
// so that at a partial detent a swipe on the content expands the sheet instead (like iOS).
|
|
136
|
+
setExpanded(entry.intersectionRatio >= 1);
|
|
137
|
+
isVisible.current = entry.intersectionRatio > 0;
|
|
138
|
+
hasEntered || (hasEntered = entry.intersectionRatio > 0);
|
|
139
|
+
if (hasEntered && entry.intersectionRatio <= 0) {
|
|
140
|
+
// eslint-disable-next-line react/react-compiler
|
|
141
|
+
onCloseEvent();
|
|
142
|
+
element.dispatchEvent(new CustomEvent('react-aria-sheet-close'));
|
|
143
|
+
}
|
|
144
|
+
}, {
|
|
145
|
+
threshold: [
|
|
146
|
+
0,
|
|
147
|
+
1
|
|
148
|
+
],
|
|
149
|
+
rootMargin: rootMargin
|
|
150
|
+
});
|
|
151
|
+
let el = element.querySelector('[data-sheet-content]');
|
|
152
|
+
if (el) observer.observe(el);
|
|
153
|
+
let removeSheet = $393b9725ff54df2c$var$registerSheet(stackItem);
|
|
154
|
+
return ()=>{
|
|
155
|
+
observer.disconnect();
|
|
156
|
+
removeSheet();
|
|
157
|
+
};
|
|
158
|
+
}, [
|
|
159
|
+
stackItem,
|
|
160
|
+
axis,
|
|
161
|
+
maxScroll,
|
|
162
|
+
enteredScroll,
|
|
163
|
+
after
|
|
164
|
+
]);
|
|
165
|
+
let mergedRefs = (0, $d0bvy$useMemo)(()=>(0, $d0bvy$mergeRefs)(ref, domRef), [
|
|
166
|
+
ref,
|
|
167
|
+
domRef
|
|
168
|
+
]);
|
|
169
|
+
let sheetStack = (0, $d0bvy$useSyncExternalStore)($393b9725ff54df2c$var$subscribeStack, $393b9725ff54df2c$var$getSheetStack, $393b9725ff54df2c$var$getSheetStack);
|
|
170
|
+
let index = Math.max(0, sheetStack.findIndex((e)=>e.id === id));
|
|
171
|
+
let descendants = sheetStack.slice(index + 1);
|
|
172
|
+
let values = {
|
|
173
|
+
position: position,
|
|
174
|
+
swipeDirection: swipeDirection,
|
|
175
|
+
isExpanded: isExpanded,
|
|
176
|
+
stackIndex: index,
|
|
177
|
+
hasDescendants: descendants.length > 0
|
|
178
|
+
};
|
|
179
|
+
let sheetProps = $393b9725ff54df2c$var$useSheetRenderProps(props, values, 'react-aria-SheetOverlay', {
|
|
180
|
+
// absolute rather than fixed so the modal is not clipped by iOS Safari.
|
|
181
|
+
position: 'absolute',
|
|
182
|
+
top: 0,
|
|
183
|
+
left: 0,
|
|
184
|
+
width: 'max(var(--page-width), 100vw)',
|
|
185
|
+
height: 'max(var(--page-height), 100dvh)',
|
|
186
|
+
overflow: 'clip',
|
|
187
|
+
// @ts-ignore
|
|
188
|
+
'--sheet-scroll-padding-x': 'calc(100vw - var(--visual-viewport-width))',
|
|
189
|
+
'--sheet-scroll-padding-y': 'calc(100dvh - var(--visual-viewport-height))'
|
|
190
|
+
});
|
|
191
|
+
return /*#__PURE__*/ (0, $d0bvy$react).createElement((0, $46ccb41fa2c44f44$export$8948f78d83984c69), {
|
|
192
|
+
...props,
|
|
193
|
+
isOpen: state.isOpen,
|
|
194
|
+
defaultOpen: undefined,
|
|
195
|
+
onOpenChange: state.setOpen,
|
|
196
|
+
ref: mergedRefs,
|
|
197
|
+
isDismissable: !preventDismissal,
|
|
198
|
+
isKeyboardDismissDisabled: preventDismissal,
|
|
199
|
+
// Moving the VoiceOver cursor into the sheet (via focus, or by making the content behind it
|
|
200
|
+
// inert) scrolls, which interrupts the enter scroll animation on iOS. Wait until it has entered.
|
|
201
|
+
UNSTABLE_deferUntilEntered: true,
|
|
202
|
+
UNSTABLE_overrideFocus: true,
|
|
203
|
+
...sheetProps,
|
|
204
|
+
onEnter: (element)=>{
|
|
205
|
+
// The overlay is the document-anchored wrapper; the swipe gesture scrolls the inner container.
|
|
206
|
+
let scroller = element.querySelector('[data-sheet-scroll]');
|
|
207
|
+
let vp = axis === 'y' ? window.innerHeight + parseFloat($393b9725ff54df2c$var$calcToPx($393b9725ff54df2c$var$viewportPadding(after, axis))) : window.innerWidth;
|
|
208
|
+
// Open at the first custom detent when provided, otherwise the fully-entered position.
|
|
209
|
+
let initial = element.querySelector('[data-sheet-initial]');
|
|
210
|
+
let scrollToRest = (smooth)=>{
|
|
211
|
+
if (initial) $393b9725ff54df2c$var$scrollDetentIntoView(scroller, initial, axis, after ? 'start' : 'end', smooth);
|
|
212
|
+
else $393b9725ff54df2c$var$scrollAlongAxis(scroller, axis, enteredScroll / 100 * vp, smooth);
|
|
213
|
+
};
|
|
214
|
+
if (enteredScroll === 0) {
|
|
215
|
+
// The rest position is at scroll 0, so the sheet mounts already entered. Jump to the exit
|
|
216
|
+
// first, then animate back in on the next frame — doing both in the same task can leave
|
|
217
|
+
// the browser stuck at the jumped-to position instead of running the smooth scroll.
|
|
218
|
+
$393b9725ff54df2c$var$scrollAlongAxis(scroller, axis, maxScroll / 100 * vp);
|
|
219
|
+
requestAnimationFrame(()=>scrollToRest(true));
|
|
220
|
+
} else scrollToRest(true);
|
|
221
|
+
return new Promise((resolve)=>{
|
|
222
|
+
// eslint-disable-next-line rsp-rules/no-non-composing-event-listener
|
|
223
|
+
scroller.addEventListener('scrollend', ()=>resolve(), {
|
|
224
|
+
once: true
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
onExit: (element)=>{
|
|
229
|
+
let scroller = element.querySelector('[data-sheet-scroll]');
|
|
230
|
+
if (!isVisible.current) {
|
|
231
|
+
// Wait for the end of the scroll gesture in Safari to avoid momentum scrolling re-targeting to the sheet behind.
|
|
232
|
+
if ((0, $d0bvy$isSafari)() && !(0, $d0bvy$isIOS)()) return new Promise((resolve)=>{
|
|
233
|
+
// eslint-disable-next-line rsp-rules/no-non-composing-event-listener
|
|
234
|
+
scroller.addEventListener('scrollend', ()=>{
|
|
235
|
+
setTimeout(()=>resolve(), 50);
|
|
236
|
+
}, {
|
|
237
|
+
once: true
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
let vp = axis === 'y' ? window.innerHeight + parseFloat($393b9725ff54df2c$var$calcToPx($393b9725ff54df2c$var$viewportPadding(after, axis))) : window.innerWidth;
|
|
243
|
+
let maxScrollPx = maxScroll / 100 * vp;
|
|
244
|
+
let current = axis === 'y' ? scroller.scrollTop : scroller.scrollLeft;
|
|
245
|
+
let target;
|
|
246
|
+
if (after && !before) target = 0;
|
|
247
|
+
else if (before && !after) target = maxScrollPx;
|
|
248
|
+
else // Dual direction: exit toward whichever edge is nearest the current position.
|
|
249
|
+
target = current > enteredScroll / 100 * vp ? maxScrollPx : 0;
|
|
250
|
+
$393b9725ff54df2c$var$scrollAlongAxis(scroller, axis, target, true);
|
|
251
|
+
// The close event is dispatched on the overlay wrapper by the IntersectionObserver below.
|
|
252
|
+
return new Promise((resolve)=>{
|
|
253
|
+
element.addEventListener('react-aria-sheet-close', ()=>resolve(), {
|
|
254
|
+
once: true
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}, (renderProps)=>/*#__PURE__*/ (0, $d0bvy$react).createElement($393b9725ff54df2c$var$InternalSheetContext.Provider, {
|
|
259
|
+
value: {
|
|
260
|
+
...props,
|
|
261
|
+
position: position,
|
|
262
|
+
swipeDirection: swipeDirection,
|
|
263
|
+
index: index,
|
|
264
|
+
descendants: descendants,
|
|
265
|
+
isEntering: renderProps.isEntering,
|
|
266
|
+
isExiting: renderProps.isExiting,
|
|
267
|
+
values: values
|
|
268
|
+
}
|
|
269
|
+
}, typeof children === 'function' ? children({
|
|
270
|
+
...renderProps,
|
|
271
|
+
...values
|
|
272
|
+
}) : children));
|
|
273
|
+
});
|
|
274
|
+
function $393b9725ff54df2c$var$getDataAttributes(values) {
|
|
275
|
+
return {
|
|
276
|
+
'data-position': values.position,
|
|
277
|
+
'data-swipe-direction': values.swipeDirection,
|
|
278
|
+
'data-expanded': values.isExpanded || undefined,
|
|
279
|
+
'data-stack-index': values.stackIndex,
|
|
280
|
+
'data-has-descendants': values.hasDescendants || undefined
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
// Merges the sheet-specific values into the render props, className, and style of a Modal or ModalOverlay.
|
|
284
|
+
function $393b9725ff54df2c$var$useSheetRenderProps(props, values, defaultClassName, defaultStyle, overrideStyle) {
|
|
285
|
+
return {
|
|
286
|
+
...$393b9725ff54df2c$var$getDataAttributes(values),
|
|
287
|
+
render: props.render ? (domProps, renderProps)=>props.render(domProps, {
|
|
288
|
+
...renderProps,
|
|
289
|
+
...values
|
|
290
|
+
}) : undefined,
|
|
291
|
+
className: (renderProps)=>typeof props.className === 'function' ? props.className({
|
|
292
|
+
...renderProps,
|
|
293
|
+
...values
|
|
294
|
+
}) : props.className || defaultClassName,
|
|
295
|
+
style: (renderProps)=>({
|
|
296
|
+
...defaultStyle,
|
|
297
|
+
...typeof props.style === 'function' ? props.style({
|
|
298
|
+
...renderProps,
|
|
299
|
+
...values
|
|
300
|
+
}) : props.style,
|
|
301
|
+
...overrideStyle
|
|
302
|
+
})
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function $393b9725ff54df2c$var$resolveDirection(value, direction) {
|
|
306
|
+
if (value === 'start') return direction === 'rtl' ? 'right' : 'left';
|
|
307
|
+
if (value === 'end') return direction === 'rtl' ? 'left' : 'right';
|
|
308
|
+
return value;
|
|
309
|
+
}
|
|
310
|
+
// The sheet lives inside an oversized scroll container. Scrolling slides a viewport-sized "stage"
|
|
311
|
+
// (which holds the sheet) on and off screen along the swipe axis, so the browser drives the swipe
|
|
312
|
+
// gesture natively. The container is always 2 viewports along the axis; a fixed 1-viewport window
|
|
313
|
+
// (the actual browser viewport) looks onto it. The stage always sits 1 viewport into the content,
|
|
314
|
+
// and snap markers at the content extremes define the entered/exited resting positions.
|
|
315
|
+
function $393b9725ff54df2c$var$getSwipeConfig(swipeDirection) {
|
|
316
|
+
let axis = swipeDirection === 'top' || swipeDirection === 'bottom' || swipeDirection === 'vertical' ? 'y' : 'x';
|
|
317
|
+
let before = swipeDirection === 'top' || swipeDirection === 'left' || swipeDirection === 'vertical' || swipeDirection === 'horizontal';
|
|
318
|
+
let after = swipeDirection === 'bottom' || swipeDirection === 'right' || swipeDirection === 'vertical' || swipeDirection === 'horizontal';
|
|
319
|
+
// Each exitable side adds a viewport of scroll travel.
|
|
320
|
+
let maxScroll = (Number(before) + Number(after)) * 100;
|
|
321
|
+
// When the sheet can only exit toward the start edge (top/left), it rests at scroll 0 and is
|
|
322
|
+
// swiped toward maxScroll to dismiss. Otherwise it rests 1 viewport in.
|
|
323
|
+
let enteredScroll = before && !after ? 0 : 100;
|
|
324
|
+
// Position the container so the rest position lands in the real viewport.
|
|
325
|
+
let containerOffset = before && !after ? -100 : 0;
|
|
326
|
+
// The sheet crosses a single viewport edge (the swipe edge), so map the animation to just that
|
|
327
|
+
// crossing. In view-timeline terms `entry` is the scrollport's end edge (bottom/right, where the
|
|
328
|
+
// sheet appears from) and `exit` is the start edge (top/left). Direction is chosen so progress 0
|
|
329
|
+
// is the exited state and 1 is entered, matching keyframes authored from exited -> entered:
|
|
330
|
+
// `entry` already runs gone -> entered, while `exit` runs entered -> gone and is reversed.
|
|
331
|
+
//
|
|
332
|
+
// Dual directions cross both edges, so run the same keyframe over the full `cover` range twice
|
|
333
|
+
// (iteration count 2) with `alternate`: the view timeline splits its progress across the two
|
|
334
|
+
// iterations, so it plays exited -> entered -> exited around the centered rest position. This
|
|
335
|
+
// reuses a single exited -> entered keyframe rather than requiring an author to also write a
|
|
336
|
+
// symmetric (0%/50%/100%) variant.
|
|
337
|
+
const viewRange = before && after ? 'cover' : before ? 'exit' : 'entry';
|
|
338
|
+
const viewDirection = before && after ? 'alternate' : before ? 'reverse' : 'normal';
|
|
339
|
+
const viewIterations = before && after ? 2 : 1;
|
|
340
|
+
return {
|
|
341
|
+
axis: axis,
|
|
342
|
+
before: before,
|
|
343
|
+
after: after,
|
|
344
|
+
maxScroll: maxScroll,
|
|
345
|
+
enteredScroll: enteredScroll,
|
|
346
|
+
containerOffset: containerOffset,
|
|
347
|
+
viewRange: viewRange,
|
|
348
|
+
viewDirection: viewDirection,
|
|
349
|
+
viewIterations: viewIterations
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
// The resting [x, y] flex alignment for each sheet position, independent of the swipe direction.
|
|
353
|
+
const $393b9725ff54df2c$var$POSITION_ALIGNMENT = {
|
|
354
|
+
top: [
|
|
355
|
+
'center',
|
|
356
|
+
'flex-start'
|
|
357
|
+
],
|
|
358
|
+
bottom: [
|
|
359
|
+
'center',
|
|
360
|
+
'flex-end'
|
|
361
|
+
],
|
|
362
|
+
left: [
|
|
363
|
+
'flex-start',
|
|
364
|
+
'center'
|
|
365
|
+
],
|
|
366
|
+
right: [
|
|
367
|
+
'flex-end',
|
|
368
|
+
'center'
|
|
369
|
+
],
|
|
370
|
+
center: [
|
|
371
|
+
'center',
|
|
372
|
+
'center'
|
|
373
|
+
]
|
|
374
|
+
};
|
|
375
|
+
// Converts a snap point value to a CSS length: numbers are pixels.
|
|
376
|
+
function $393b9725ff54df2c$var$toLength(point) {
|
|
377
|
+
return typeof point === 'number' ? `${point}px` : point;
|
|
378
|
+
}
|
|
379
|
+
function $393b9725ff54df2c$var$SnapPoint({ point: point, align: align, axis: axis }) {
|
|
380
|
+
let mainUnit = axis === 'y' ? 'dvh' : 'dvw';
|
|
381
|
+
let offset = $393b9725ff54df2c$var$toLength(point);
|
|
382
|
+
return /*#__PURE__*/ (0, $d0bvy$react).createElement("div", {
|
|
383
|
+
style: {
|
|
384
|
+
position: 'absolute',
|
|
385
|
+
top: axis === 'y' ? offset : 0,
|
|
386
|
+
left: axis === 'x' ? offset : 0,
|
|
387
|
+
scrollSnapAlign: align,
|
|
388
|
+
// A full viewport along the swipe axis so its start/end edge lands at the snap position.
|
|
389
|
+
width: axis === 'x' ? `100${mainUnit}` : 1,
|
|
390
|
+
height: axis === 'y' ? `100${mainUnit}` : 1
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
// A snap marker placed inside the sheet, `point` in from its leading edge. Because it moves with
|
|
395
|
+
// the sheet, snapping it with a `scroll-margin` of one viewport rests the marker at the edge of the
|
|
396
|
+
// visible viewport, leaving exactly `point` of the sheet on screen. Since `point` is an inset rather
|
|
397
|
+
// than part of the margin, percentages resolve relative to the sheet's size.
|
|
398
|
+
function $393b9725ff54df2c$var$DetentPoint({ point: point, axis: axis, after: after, isInitial: isInitial }) {
|
|
399
|
+
let viewport = axis === 'y' ? '100dvh' : '100dvw';
|
|
400
|
+
let offset = $393b9725ff54df2c$var$toLength(point);
|
|
401
|
+
let common = {
|
|
402
|
+
position: 'absolute',
|
|
403
|
+
width: 1,
|
|
404
|
+
height: 1,
|
|
405
|
+
scrollSnapAlign: after ? 'start' : 'end'
|
|
406
|
+
};
|
|
407
|
+
let edge = axis === 'y' ? after ? {
|
|
408
|
+
top: offset,
|
|
409
|
+
left: 0,
|
|
410
|
+
scrollMarginTop: viewport
|
|
411
|
+
} : {
|
|
412
|
+
bottom: offset,
|
|
413
|
+
left: 0,
|
|
414
|
+
scrollMarginBottom: viewport
|
|
415
|
+
} : after ? {
|
|
416
|
+
top: 0,
|
|
417
|
+
left: offset,
|
|
418
|
+
scrollMarginLeft: viewport
|
|
419
|
+
} : {
|
|
420
|
+
top: 0,
|
|
421
|
+
right: offset,
|
|
422
|
+
scrollMarginRight: viewport
|
|
423
|
+
};
|
|
424
|
+
return /*#__PURE__*/ (0, $d0bvy$react).createElement("div", {
|
|
425
|
+
"data-sheet-detent": true,
|
|
426
|
+
"data-sheet-initial": isInitial || undefined,
|
|
427
|
+
style: {
|
|
428
|
+
...common,
|
|
429
|
+
...edge
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
const $393b9725ff54df2c$export$a9bf29f8d87ebbee = /*#__PURE__*/ (0, $d0bvy$forwardRef)(function Sheet(props, domRef) {
|
|
434
|
+
var _useContext;
|
|
435
|
+
let ref = (0, $d0bvy$useObjectRef)(domRef);
|
|
436
|
+
let scrollRef = (0, $d0bvy$useRef)(null);
|
|
437
|
+
let stageRef = (0, $d0bvy$useRef)(null);
|
|
438
|
+
let { position: position, swipeDirection: swipeDirection, snapPoints: snapPoints, index: index, descendants: descendants, isEntering: isEntering, isExiting: isExiting, preventDismissal: preventDismissal = false, values: values } = (0, $d0bvy$useContext)($393b9725ff54df2c$var$InternalSheetContext);
|
|
439
|
+
var _useContext_isOpen;
|
|
440
|
+
// The ModalOverlay may defer its enter animation (e.g. until the software keyboard opens), during
|
|
441
|
+
// which isEntering is false. The sheet is not settled until it has opened, so treat it as entering.
|
|
442
|
+
let isOpen = (_useContext_isOpen = (_useContext = (0, $d0bvy$useContext)((0, $46ccb41fa2c44f44$export$6bc057cefccad9c8))) === null || _useContext === void 0 ? void 0 : _useContext.isOpen) !== null && _useContext_isOpen !== void 0 ? _useContext_isOpen : true;
|
|
443
|
+
let isTransitioning = !isOpen || isEntering || isExiting;
|
|
444
|
+
let { direction: direction } = (0, $d0bvy$useLocale)();
|
|
445
|
+
let { axis: axis, after: after, before: before, containerOffset: containerOffset } = $393b9725ff54df2c$var$getSwipeConfig(swipeDirection);
|
|
446
|
+
let viewport = axis === 'y' ? '100dvh' : '100dvw';
|
|
447
|
+
// A non-dismissable sheet can still be swiped between its snap points, but not past the smallest
|
|
448
|
+
// one. Enter/exit animations still need the exit space, so only clamp while settled.
|
|
449
|
+
let hasSnapPoints = !!(snapPoints === null || snapPoints === void 0 ? void 0 : snapPoints.length) && before !== after;
|
|
450
|
+
let isClamped = preventDismissal && !isTransitioning;
|
|
451
|
+
let snapTravel = $393b9725ff54df2c$var$useSnapPointTravel(stageRef, ref, axis, after, preventDismissal && hasSnapPoints ? snapPoints.join(' ') : null);
|
|
452
|
+
// Scroll travel between the smallest snap point and the fully revealed sheet. It is at least 1px
|
|
453
|
+
// so the scroll container remains scrollable, which lets the browser show its native overscroll
|
|
454
|
+
// bounce even when there is nowhere to snap to.
|
|
455
|
+
let clampedTravel = `${hasSnapPoints ? Math.max(1, snapTravel) : 1}px`;
|
|
456
|
+
// The stage normally sits 1 viewport in so the sheet can scroll fully off screen toward the start
|
|
457
|
+
// edge. When clamped, sheets exiting toward the end edge move it so scroll 0 rests at the smallest
|
|
458
|
+
// snap point. Sheets exiting toward the start edge rest at scroll 0 already, so only the end of
|
|
459
|
+
// the scroll content (the smallest snap point) moves. Dual direction sheets get 1px either side.
|
|
460
|
+
// viewportPadding pushes bottom sheets down so that they can scroll beyond the viewport behind the iOS toolbar.
|
|
461
|
+
let stageStart = isClamped && after ? clampedTravel : `calc(${viewport} + ${$393b9725ff54df2c$var$viewportPadding(after, axis)})`;
|
|
462
|
+
let endMarker;
|
|
463
|
+
if (isClamped && before && after) endMarker = `calc(${stageStart} + ${viewport} + 1px)`;
|
|
464
|
+
else if (isClamped && before) endMarker = `calc(${clampedTravel} + ${viewport})`;
|
|
465
|
+
else endMarker = `calc(${stageStart} + ${viewport}${before && after ? ` + ${viewport}` : ''})`;
|
|
466
|
+
// Keep the sheet visually in place when switching between the clamped and unclamped geometry.
|
|
467
|
+
// Scroll snapping is disabled while a non-dismissable sheet enters and exits so the browser
|
|
468
|
+
// doesn't re-snap when the geometry changes, which would otherwise differ between browsers.
|
|
469
|
+
let prevStageOffset = (0, $d0bvy$useRef)(null);
|
|
470
|
+
let prevClamped = (0, $d0bvy$useRef)(isClamped);
|
|
471
|
+
(0, $d0bvy$useLayoutEffect)(()=>{
|
|
472
|
+
let stage = stageRef.current;
|
|
473
|
+
let scroller = scrollRef.current;
|
|
474
|
+
if (!stage || !scroller) return;
|
|
475
|
+
let offset = axis === 'y' ? stage.offsetTop : stage.offsetLeft;
|
|
476
|
+
if (prevClamped.current !== isClamped && prevStageOffset.current != null) {
|
|
477
|
+
let delta = offset - prevStageOffset.current;
|
|
478
|
+
if (delta !== 0) {
|
|
479
|
+
if (axis === 'y') scroller.scrollTop += delta;
|
|
480
|
+
else scroller.scrollLeft += delta;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
prevClamped.current = isClamped;
|
|
484
|
+
prevStageOffset.current = offset;
|
|
485
|
+
});
|
|
486
|
+
let swipeAnimation = $393b9725ff54df2c$var$useSwipeAnimation(props);
|
|
487
|
+
let style = {
|
|
488
|
+
// Positioned so the detent markers below anchor to the sheet's own box.
|
|
489
|
+
position: 'relative',
|
|
490
|
+
...swipeAnimation
|
|
491
|
+
};
|
|
492
|
+
let overscrollInset;
|
|
493
|
+
if (props.overscrollPadding && position === swipeDirection) {
|
|
494
|
+
overscrollInset = axis === 'y' ? '100vh' : '100vw';
|
|
495
|
+
// Extra padding to allow overscrolling, and a negative margin to offset it.
|
|
496
|
+
switch(position){
|
|
497
|
+
case 'top':
|
|
498
|
+
style.paddingTop = '100vh';
|
|
499
|
+
style.marginTop = '-100vh';
|
|
500
|
+
break;
|
|
501
|
+
case 'bottom':
|
|
502
|
+
style.paddingBottom = '100vh';
|
|
503
|
+
style.marginBottom = '-100vh';
|
|
504
|
+
break;
|
|
505
|
+
case 'left':
|
|
506
|
+
style.paddingLeft = '100vw';
|
|
507
|
+
style.marginLeft = '-100vw';
|
|
508
|
+
break;
|
|
509
|
+
case 'right':
|
|
510
|
+
style.paddingRight = '100vw';
|
|
511
|
+
style.marginRight = '-100vw';
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (props.stackAnimation && descendants.length > 0 && $393b9725ff54df2c$var$supportsViewTimeline) {
|
|
516
|
+
// Append one animation per descendant sheet, driven by that descendant's view timeline.
|
|
517
|
+
let stackStyle = {
|
|
518
|
+
animationName: ()=>props.stackAnimation,
|
|
519
|
+
animationTimeline: (_, i)=>`--sheet-timeline-${index + 1 + i}`,
|
|
520
|
+
animationDirection: (d)=>d.direction,
|
|
521
|
+
animationIterationCount: (d)=>String(d.iterations),
|
|
522
|
+
animationFillMode: ()=>'both',
|
|
523
|
+
animationRange: (d)=>d.range,
|
|
524
|
+
animationComposition: ()=>'accumulate',
|
|
525
|
+
animationTimingFunction: ()=>'linear'
|
|
526
|
+
};
|
|
527
|
+
for (let [key, value] of Object.entries(stackStyle))style[key] = [
|
|
528
|
+
style[key],
|
|
529
|
+
...descendants.map(value)
|
|
530
|
+
].filter(Boolean).join(', ');
|
|
531
|
+
}
|
|
532
|
+
let sheetProps = $393b9725ff54df2c$var$useSheetRenderProps(props, values, 'react-aria-Sheet', {
|
|
533
|
+
direction: direction
|
|
534
|
+
}, style);
|
|
535
|
+
let [x, y] = $393b9725ff54df2c$var$POSITION_ALIGNMENT[position];
|
|
536
|
+
let justifyContent = axis === 'y' ? y : x;
|
|
537
|
+
let alignItems = axis === 'y' ? x : y;
|
|
538
|
+
let { scrollX: scrollX, scrollY: scrollY } = typeof window !== 'undefined' ? window : {
|
|
539
|
+
scrollX: 0,
|
|
540
|
+
scrollY: 0
|
|
541
|
+
};
|
|
542
|
+
return /*#__PURE__*/ (0, $d0bvy$react).createElement("div", {
|
|
543
|
+
ref: scrollRef,
|
|
544
|
+
"data-sheet-scroll": true,
|
|
545
|
+
style: {
|
|
546
|
+
position: 'absolute',
|
|
547
|
+
top: axis === 'y' ? `calc(${scrollY}px + ${containerOffset}dvh)` : scrollY,
|
|
548
|
+
left: axis === 'x' ? `calc(${scrollX}px + ${containerOffset}dvw)` : scrollX,
|
|
549
|
+
// The container is 2 viewports along the swipe axis and 1 viewport on the cross axis.
|
|
550
|
+
height: axis === 'y' ? '200dvh' : '100dvh',
|
|
551
|
+
width: axis === 'x' ? '200dvw' : '100dvw',
|
|
552
|
+
overflowX: axis === 'x' ? 'auto' : 'hidden',
|
|
553
|
+
overflowY: axis === 'y' ? 'auto' : 'hidden',
|
|
554
|
+
// Snapping is only disabled when the geometry changes. Changing it during a swipe to dismiss
|
|
555
|
+
// cancels the momentum scroll in Safari without firing scrollend, which onExit waits for.
|
|
556
|
+
scrollSnapType: preventDismissal && isTransitioning ? 'none' : `${axis} mandatory`,
|
|
557
|
+
overscrollBehaviorY: axis === 'y' ? 'contain' : 'none',
|
|
558
|
+
overscrollBehaviorX: axis === 'x' ? 'contain' : 'none',
|
|
559
|
+
scrollbarWidth: 'none',
|
|
560
|
+
// The scroll geometry is physical, so keep the scroll origin and flex alignment
|
|
561
|
+
// left-to-right regardless of the document direction.
|
|
562
|
+
direction: 'ltr'
|
|
563
|
+
}
|
|
564
|
+
}, /*#__PURE__*/ (0, $d0bvy$react).createElement($393b9725ff54df2c$var$SnapPoint, {
|
|
565
|
+
point: 0,
|
|
566
|
+
align: isClamped && after ? 'none' : 'start',
|
|
567
|
+
axis: axis
|
|
568
|
+
}), before && after && /*#__PURE__*/ (0, $d0bvy$react).createElement($393b9725ff54df2c$var$SnapPoint, {
|
|
569
|
+
point: stageStart,
|
|
570
|
+
align: "start",
|
|
571
|
+
axis: axis
|
|
572
|
+
}), /*#__PURE__*/ (0, $d0bvy$react).createElement("div", {
|
|
573
|
+
ref: stageRef,
|
|
574
|
+
style: {
|
|
575
|
+
position: 'absolute',
|
|
576
|
+
// The stage normally sits 1 viewport into the content along the swipe axis.
|
|
577
|
+
top: axis === 'y' ? stageStart : 0,
|
|
578
|
+
left: axis === 'x' ? stageStart : 0,
|
|
579
|
+
height: '100dvh',
|
|
580
|
+
width: '100dvw',
|
|
581
|
+
display: 'flex',
|
|
582
|
+
flexDirection: axis === 'y' ? 'column' : 'row',
|
|
583
|
+
alignItems: alignItems,
|
|
584
|
+
justifyContent: justifyContent
|
|
585
|
+
}
|
|
586
|
+
}, /*#__PURE__*/ (0, $d0bvy$react).createElement((0, $46ccb41fa2c44f44$export$2b77a92f1a5ad772), {
|
|
587
|
+
...props,
|
|
588
|
+
ref: ref,
|
|
589
|
+
...sheetProps
|
|
590
|
+
}, (renderProps)=>/*#__PURE__*/ (0, $d0bvy$react).createElement((0, $d0bvy$react).Fragment, null, snapPoints && // Excludes the overscroll padding so percentages are relative to the visible sheet.
|
|
591
|
+
/*#__PURE__*/ (0, $d0bvy$react).createElement("div", {
|
|
592
|
+
style: {
|
|
593
|
+
position: 'absolute',
|
|
594
|
+
inset: 0,
|
|
595
|
+
...overscrollInset ? {
|
|
596
|
+
[position]: overscrollInset
|
|
597
|
+
} : null,
|
|
598
|
+
pointerEvents: 'none'
|
|
599
|
+
}
|
|
600
|
+
}, snapPoints.map((point, i)=>/*#__PURE__*/ (0, $d0bvy$react).createElement($393b9725ff54df2c$var$DetentPoint, {
|
|
601
|
+
key: i,
|
|
602
|
+
point: point,
|
|
603
|
+
axis: axis,
|
|
604
|
+
after: after,
|
|
605
|
+
isInitial: i === 0
|
|
606
|
+
}))), typeof props.children === 'function' ? props.children({
|
|
607
|
+
...renderProps,
|
|
608
|
+
...values
|
|
609
|
+
}) : props.children))), /*#__PURE__*/ (0, $d0bvy$react).createElement($393b9725ff54df2c$var$SnapPoint, {
|
|
610
|
+
point: endMarker,
|
|
611
|
+
align: isClamped && before ? 'none' : 'end',
|
|
612
|
+
axis: axis
|
|
613
|
+
}));
|
|
614
|
+
});
|
|
615
|
+
// Measures how far the sheet must scroll from its smallest snap point to be fully revealed, i.e. the
|
|
616
|
+
// distance from that snap point's marker to the stage's exit edge. Measuring the rendered markers
|
|
617
|
+
// means snap points can use any CSS length, including percentages of the sheet. Uses layout offsets
|
|
618
|
+
// rather than bounding rects so swipe/stack animation transforms don't affect it.
|
|
619
|
+
function $393b9725ff54df2c$var$useSnapPointTravel(stageRef, sheetRef, axis, after, // Space-separated snap points, so markers are re-measured when they change. Null to disable.
|
|
620
|
+
snapPointsKey) {
|
|
621
|
+
let [travel, setTravel] = (0, $d0bvy$useState)(0);
|
|
622
|
+
(0, $d0bvy$useLayoutEffect)(()=>{
|
|
623
|
+
let stage = stageRef.current;
|
|
624
|
+
let sheet = sheetRef.current;
|
|
625
|
+
if (snapPointsKey == null || !stage || !sheet) return;
|
|
626
|
+
let measure = ()=>{
|
|
627
|
+
let stageSize = axis === 'y' ? stage.clientHeight : stage.clientWidth;
|
|
628
|
+
let max = 0;
|
|
629
|
+
for (let marker of sheet.querySelectorAll('[data-sheet-detent]')){
|
|
630
|
+
let offset = 0;
|
|
631
|
+
let el = marker;
|
|
632
|
+
while(el && el !== stage){
|
|
633
|
+
offset += axis === 'y' ? el.offsetTop : el.offsetLeft;
|
|
634
|
+
el = el.offsetParent;
|
|
635
|
+
}
|
|
636
|
+
// Markers sit at the snap point's start edge for sheets exiting toward the end edge, and at
|
|
637
|
+
// its end edge for sheets exiting toward the start edge. The smallest snap point travels most.
|
|
638
|
+
let size = axis === 'y' ? marker.offsetHeight : marker.offsetWidth;
|
|
639
|
+
max = Math.max(max, after ? stageSize - offset : offset + size);
|
|
640
|
+
}
|
|
641
|
+
setTravel(max);
|
|
642
|
+
};
|
|
643
|
+
measure();
|
|
644
|
+
let observer = new ResizeObserver(measure);
|
|
645
|
+
observer.observe(stage);
|
|
646
|
+
observer.observe(sheet);
|
|
647
|
+
return ()=>observer.disconnect();
|
|
648
|
+
}, [
|
|
649
|
+
stageRef,
|
|
650
|
+
sheetRef,
|
|
651
|
+
axis,
|
|
652
|
+
after,
|
|
653
|
+
snapPointsKey
|
|
654
|
+
]);
|
|
655
|
+
return travel;
|
|
656
|
+
}
|
|
657
|
+
const $393b9725ff54df2c$export$d79867882ea90c57 = /*#__PURE__*/ (0, $d0bvy$forwardRef)(function SheetBackdrop(props, ref) {
|
|
658
|
+
let style = $393b9725ff54df2c$var$useSwipeAnimation(props);
|
|
659
|
+
let { values: values, isEntering: isEntering, isExiting: isExiting } = (0, $d0bvy$useContext)($393b9725ff54df2c$var$InternalSheetContext);
|
|
660
|
+
let state = (0, $d0bvy$useContext)((0, $acf8e70c2f419f18$export$d2f961adcb0afbe));
|
|
661
|
+
let renderProps = (0, $b7b7a92703138c9b$export$4d86445c2cf5e3)({
|
|
662
|
+
...props,
|
|
663
|
+
defaultClassName: 'react-aria-SheetBackdrop',
|
|
664
|
+
defaultStyle: {
|
|
665
|
+
...style,
|
|
666
|
+
position: 'absolute',
|
|
667
|
+
inset: 0
|
|
668
|
+
},
|
|
669
|
+
values: {
|
|
670
|
+
...values,
|
|
671
|
+
isEntering: isEntering,
|
|
672
|
+
isExiting: isExiting,
|
|
673
|
+
state: state
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
return /*#__PURE__*/ (0, $d0bvy$react).createElement("div", {
|
|
677
|
+
ref: ref,
|
|
678
|
+
...(0, $d0bvy$filterDOMProps)(props, {
|
|
679
|
+
global: true
|
|
680
|
+
}),
|
|
681
|
+
...renderProps,
|
|
682
|
+
...$393b9725ff54df2c$var$getDataAttributes(values),
|
|
683
|
+
"data-entering": isEntering || undefined,
|
|
684
|
+
"data-exiting": isExiting || undefined
|
|
685
|
+
});
|
|
686
|
+
});
|
|
687
|
+
function $393b9725ff54df2c$var$useSwipeAnimation(props) {
|
|
688
|
+
let { swipeDirection: swipeDirection, snapPoints: snapPoints, index: index, isEntering: isEntering, isExiting: isExiting } = (0, $d0bvy$useContext)($393b9725ff54df2c$var$InternalSheetContext);
|
|
689
|
+
let { viewRange: viewRange, viewDirection: viewDirection, viewIterations: viewIterations } = $393b9725ff54df2c$var$getSwipeConfig(swipeDirection);
|
|
690
|
+
if (props.swipeAnimation) {
|
|
691
|
+
var _props_swipeAnimationRange, _props_swipeAnimationRange1;
|
|
692
|
+
var _snapPoints_props_swipeAnimationRange_start;
|
|
693
|
+
let rangeStart = ((_props_swipeAnimationRange = props.swipeAnimationRange) === null || _props_swipeAnimationRange === void 0 ? void 0 : _props_swipeAnimationRange.start) != null ? $393b9725ff54df2c$var$toLength((_snapPoints_props_swipeAnimationRange_start = snapPoints === null || snapPoints === void 0 ? void 0 : snapPoints[props.swipeAnimationRange.start]) !== null && _snapPoints_props_swipeAnimationRange_start !== void 0 ? _snapPoints_props_swipeAnimationRange_start : '0%') : '0%';
|
|
694
|
+
var _snapPoints_props_swipeAnimationRange_end;
|
|
695
|
+
let rangeEnd = ((_props_swipeAnimationRange1 = props.swipeAnimationRange) === null || _props_swipeAnimationRange1 === void 0 ? void 0 : _props_swipeAnimationRange1.end) != null ? $393b9725ff54df2c$var$toLength((_snapPoints_props_swipeAnimationRange_end = snapPoints === null || snapPoints === void 0 ? void 0 : snapPoints[props.swipeAnimationRange.end]) !== null && _snapPoints_props_swipeAnimationRange_end !== void 0 ? _snapPoints_props_swipeAnimationRange_end : '100%') : '100%';
|
|
696
|
+
if (swipeDirection === 'top' || swipeDirection === 'left') {
|
|
697
|
+
rangeStart = `calc(100% - ${rangeStart})`;
|
|
698
|
+
rangeEnd = `calc(100% - ${rangeEnd})`;
|
|
699
|
+
[rangeStart, rangeEnd] = [
|
|
700
|
+
rangeEnd,
|
|
701
|
+
rangeStart
|
|
702
|
+
];
|
|
703
|
+
}
|
|
704
|
+
// TODO: fix cover with range
|
|
705
|
+
if ($393b9725ff54df2c$var$supportsViewTimeline) return {
|
|
706
|
+
animationName: props.swipeAnimation,
|
|
707
|
+
animationTimeline: `--sheet-timeline-${index}`,
|
|
708
|
+
animationDirection: viewDirection,
|
|
709
|
+
animationIterationCount: viewIterations,
|
|
710
|
+
animationFillMode: 'both',
|
|
711
|
+
animationRange: `${viewRange} ${rangeStart} ${viewRange} ${rangeEnd}`,
|
|
712
|
+
animationTimingFunction: 'linear',
|
|
713
|
+
animationComposition: 'replace'
|
|
714
|
+
};
|
|
715
|
+
else if (isEntering || isExiting) // Fallback for Firefox, which doesn't support view timelines.
|
|
716
|
+
return {
|
|
717
|
+
animationName: props.swipeAnimation,
|
|
718
|
+
animationDirection: isExiting ? 'reverse' : 'normal',
|
|
719
|
+
animationDuration: '300ms',
|
|
720
|
+
animationIterationCount: '1',
|
|
721
|
+
animationFillMode: 'both',
|
|
722
|
+
animationTimingFunction: 'linear',
|
|
723
|
+
animationComposition: 'replace'
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
return {};
|
|
727
|
+
}
|
|
728
|
+
const $393b9725ff54df2c$export$fe5ec5b76996e2d3 = /*#__PURE__*/ (0, $d0bvy$forwardRef)(function SheetContent(props, ref) {
|
|
729
|
+
let { swipeDirection: swipeDirection, index: index } = (0, $d0bvy$useContext)($393b9725ff54df2c$var$InternalSheetContext);
|
|
730
|
+
let { axis: axis, before: before, after: after } = $393b9725ff54df2c$var$getSwipeConfig(swipeDirection);
|
|
731
|
+
let viewportLength = axis === 'y' ? '100dvh' : '100dvw';
|
|
732
|
+
return /*#__PURE__*/ (0, $d0bvy$react).createElement((0, $acf8e70c2f419f18$export$3ddf2d174ce01153), {
|
|
733
|
+
...props,
|
|
734
|
+
ref: ref,
|
|
735
|
+
className: props.className || 'react-aria-SheetContent',
|
|
736
|
+
"data-sheet-content": true,
|
|
737
|
+
style: {
|
|
738
|
+
...props.style,
|
|
739
|
+
width: '100%',
|
|
740
|
+
height: '100%',
|
|
741
|
+
// The dialog is the subject of the view-progress timeline that drives all sheet animations.
|
|
742
|
+
// It is _not_ the Modal because that may have additional padding for overscroll and therefore never be entirely visible.
|
|
743
|
+
// The inset crops the scroll container's scrollport down to the visible viewport.
|
|
744
|
+
// @ts-ignore
|
|
745
|
+
viewTimelineName: `--sheet-timeline-${index}`,
|
|
746
|
+
viewTimelineAxis: axis,
|
|
747
|
+
viewTimelineInset: before && !after ? `${viewportLength} 0` : `0 ${viewportLength}`
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
});
|
|
751
|
+
function $393b9725ff54df2c$var$reduceMotion() {
|
|
752
|
+
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
753
|
+
}
|
|
754
|
+
function $393b9725ff54df2c$var$scrollAlongAxis(element, axis, value, smooth = false) {
|
|
755
|
+
let behavior = smooth && !$393b9725ff54df2c$var$reduceMotion() ? 'smooth' : undefined;
|
|
756
|
+
element.scrollTo(axis === 'y' ? {
|
|
757
|
+
top: value,
|
|
758
|
+
behavior: behavior
|
|
759
|
+
} : {
|
|
760
|
+
left: value,
|
|
761
|
+
behavior: behavior
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
function $393b9725ff54df2c$var$scrollDetentIntoView(scroller, marker, axis, align, smooth = false) {
|
|
765
|
+
let behavior = smooth && !$393b9725ff54df2c$var$reduceMotion() ? 'smooth' : 'auto';
|
|
766
|
+
let markerRect = marker.getBoundingClientRect();
|
|
767
|
+
let scrollerRect = scroller.getBoundingClientRect();
|
|
768
|
+
let style = getComputedStyle(marker);
|
|
769
|
+
if (axis === 'y') {
|
|
770
|
+
if (align === 'start') {
|
|
771
|
+
let margin = parseFloat(style.scrollMarginTop) || 0;
|
|
772
|
+
// Rest the marker's start edge (less its scroll-margin) at the scrollport's start.
|
|
773
|
+
let top = markerRect.top - scrollerRect.top + scroller.scrollTop - margin;
|
|
774
|
+
scroller.scrollTo({
|
|
775
|
+
top: top,
|
|
776
|
+
behavior: behavior
|
|
777
|
+
});
|
|
778
|
+
} else {
|
|
779
|
+
let margin = parseFloat(style.scrollMarginBottom) || 0;
|
|
780
|
+
// Rest the marker's end edge (plus its scroll-margin) at the scrollport's end.
|
|
781
|
+
let top = markerRect.bottom - scrollerRect.top + scroller.scrollTop + margin - scroller.clientHeight;
|
|
782
|
+
scroller.scrollTo({
|
|
783
|
+
top: top,
|
|
784
|
+
behavior: behavior
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
} else if (align === 'start') {
|
|
788
|
+
let margin = parseFloat(style.scrollMarginLeft) || 0;
|
|
789
|
+
let left = markerRect.left - scrollerRect.left + scroller.scrollLeft - margin;
|
|
790
|
+
scroller.scrollTo({
|
|
791
|
+
left: left,
|
|
792
|
+
behavior: behavior
|
|
793
|
+
});
|
|
794
|
+
} else {
|
|
795
|
+
let margin = parseFloat(style.scrollMarginRight) || 0;
|
|
796
|
+
let left = markerRect.right - scrollerRect.left + scroller.scrollLeft + margin - scroller.clientWidth;
|
|
797
|
+
scroller.scrollTo({
|
|
798
|
+
left: left,
|
|
799
|
+
behavior: behavior
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
function $393b9725ff54df2c$var$calcToPx(calc) {
|
|
804
|
+
if (!calc.startsWith('calc(')) return calc;
|
|
805
|
+
let measure = document.createElement('div');
|
|
806
|
+
measure.inert = true;
|
|
807
|
+
measure.style.position = 'absolute';
|
|
808
|
+
measure.style.top = '0px';
|
|
809
|
+
measure.style.left = '0px';
|
|
810
|
+
measure.style.contain = 'strict';
|
|
811
|
+
measure.style.height = calc;
|
|
812
|
+
document.body.appendChild(measure);
|
|
813
|
+
let height = window.getComputedStyle(measure).height;
|
|
814
|
+
measure.remove();
|
|
815
|
+
return height;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
export {$393b9725ff54df2c$export$de69b9b0343a1903 as SheetTrigger, $393b9725ff54df2c$export$48dbb295cbd054d8 as SheetOverlay, $393b9725ff54df2c$export$a9bf29f8d87ebbee as Sheet, $393b9725ff54df2c$export$d79867882ea90c57 as SheetBackdrop, $393b9725ff54df2c$export$fe5ec5b76996e2d3 as SheetContent};
|
|
820
|
+
//# sourceMappingURL=Sheet.js.map
|