@astryxdesign/core 0.4.3 → 0.4.4-canary.0f4d45f
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/CHANGELOG.md +60 -0
- package/README.md +79 -45
- package/dist/Banner/Banner.d.ts +3 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +13 -3
- package/dist/BottomSheet/BottomSheet.d.ts +66 -0
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheet.js +392 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts +60 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheetPanel.js +398 -0
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts +61 -0
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheetSwitcher.js +410 -0
- package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts +21 -0
- package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheetSwitcherContext.js +13 -0
- package/dist/BottomSheet/index.d.ts +11 -0
- package/dist/BottomSheet/index.d.ts.map +1 -0
- package/dist/BottomSheet/index.js +12 -0
- package/dist/BottomSheet/snapOffsets.d.ts +72 -0
- package/dist/BottomSheet/snapOffsets.d.ts.map +1 -0
- package/dist/BottomSheet/snapOffsets.js +130 -0
- package/dist/BottomSheet/useMobileKeyboard.d.ts +35 -0
- package/dist/BottomSheet/useMobileKeyboard.d.ts.map +1 -0
- package/dist/BottomSheet/useMobileKeyboard.js +373 -0
- package/dist/BottomSheet/useSheetGestures.d.ts +180 -0
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -0
- package/dist/BottomSheet/useSheetGestures.js +989 -0
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +3 -4
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +12 -6
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +9 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +31 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +2 -1
- package/dist/Field/InputClearButton.d.ts +2 -1
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +6 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +9 -3
- package/dist/MobileNav/MobileNav.d.ts +12 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +102 -30
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +21 -7
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +9 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +14 -3
- package/dist/StatusDot/StatusDot.d.ts +43 -3
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +42 -5
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +5 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +8 -1
- package/dist/Tokenizer/Tokenizer.js +11 -5
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +4 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +5 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +10 -1
- package/dist/astryx.css +21 -0
- package/dist/hooks/index.d.ts +8 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +8 -1
- package/dist/hooks/useFocusTrap.d.ts +0 -11
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +1 -11
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/defineTheme.d.ts +22 -4
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/expandColorScale.d.ts +17 -2
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +63 -33
- package/dist/utils/ime.d.ts +5 -0
- package/dist/utils/ime.d.ts.map +1 -0
- package/dist/utils/ime.js +63 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/locales/af-ZA.json +958 -0
- package/locales/ar-SA.json +998 -0
- package/locales/ca-ES.json +974 -0
- package/locales/cs-CZ.json +990 -0
- package/locales/da-DK.json +966 -0
- package/locales/de-DE.json +966 -0
- package/locales/el-GR.json +990 -0
- package/locales/en.json +48 -0
- package/locales/es-ES.json +978 -0
- package/locales/fi-FI.json +990 -0
- package/locales/fr-FR.json +928 -0
- package/locales/he-IL.json +990 -0
- package/locales/hu-HU.json +990 -0
- package/locales/it-IT.json +978 -0
- package/locales/ja-JP.json +998 -0
- package/locales/ko-KR.json +990 -0
- package/locales/nl-NL.json +954 -0
- package/locales/no-NO.json +978 -0
- package/locales/pl-PL.json +982 -0
- package/locales/pseudo.json +36 -0
- package/locales/pt-BR.json +982 -0
- package/locales/pt-PT.json +982 -0
- package/locales/ro-RO.json +982 -0
- package/locales/ru-RU.json +990 -0
- package/locales/sr-SP.json +990 -0
- package/locales/sv-SE.json +986 -0
- package/locales/tr-TR.json +990 -0
- package/locales/uk-UA.json +990 -0
- package/locales/vi-VN.json +986 -0
- package/locales/zh-CN.json +998 -0
- package/locales/zh-TW.json +998 -0
- package/package.json +9 -8
- package/src/Banner/Banner.doc.mjs +3 -3
- package/src/Banner/Banner.test.tsx +40 -0
- package/src/Banner/Banner.tsx +27 -2
- package/src/BottomSheet/BottomSheet.doc.mjs +266 -0
- package/src/BottomSheet/BottomSheet.test.tsx +2114 -0
- package/src/BottomSheet/BottomSheet.tsx +545 -0
- package/src/BottomSheet/BottomSheetPanel.test.tsx +240 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +547 -0
- package/src/BottomSheet/BottomSheetSwitcher.doc.mjs +219 -0
- package/src/BottomSheet/BottomSheetSwitcher.test.tsx +850 -0
- package/src/BottomSheet/BottomSheetSwitcher.tsx +628 -0
- package/src/BottomSheet/BottomSheetSwitcherContext.ts +51 -0
- package/src/BottomSheet/index.ts +15 -0
- package/src/BottomSheet/snapOffsets.test.ts +187 -0
- package/src/BottomSheet/snapOffsets.ts +159 -0
- package/src/BottomSheet/useMobileKeyboard.ts +499 -0
- package/src/BottomSheet/useSheetGestures.test.ts +1059 -0
- package/src/BottomSheet/useSheetGestures.ts +1459 -0
- package/src/Chat/ChatComposerInput.tsx +3 -4
- package/src/ComplexSelector/ComplexSelector.tsx +12 -5
- package/src/ContextMenu/ContextMenu.tsx +4 -2
- package/src/DateInput/DateInput.test.tsx +21 -0
- package/src/DateInput/DateInput.tsx +9 -1
- package/src/DateTimeInput/DateTimeInput.doc.mjs +4 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +137 -0
- package/src/DateTimeInput/DateTimeInput.tsx +39 -2
- package/src/Dialog/Dialog.tsx +2 -1
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/InputClearButton.test.tsx +25 -0
- package/src/Field/InputClearButton.tsx +4 -1
- package/src/FileInput/FileInput.test.tsx +53 -9
- package/src/Lightbox/Lightbox.test.tsx +49 -28
- package/src/Lightbox/Lightbox.tsx +7 -3
- package/src/MobileNav/MobileNav.tsx +128 -37
- package/src/MobileNav/MobileNavCloseEdgeCases.test.tsx +426 -0
- package/src/MobileNav/MobileNavCloseTiming.test.ts +58 -0
- package/src/MobileNav/MobileNavCloseVisibility.test.tsx +172 -0
- package/src/MultiSelector/MultiSelector.test.tsx +195 -51
- package/src/MultiSelector/MultiSelector.tsx +22 -8
- package/src/NumberInput/NumberInput.test.tsx +18 -0
- package/src/NumberInput/NumberInput.tsx +9 -1
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/Selector/Selector.test.tsx +85 -26
- package/src/Selector/Selector.tsx +13 -4
- package/src/StatusDot/StatusDot.doc.mjs +13 -0
- package/src/StatusDot/StatusDot.test.tsx +115 -8
- package/src/StatusDot/StatusDot.tsx +74 -9
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +7 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +20 -2
- package/src/TimeInput/TimeInput.test.tsx +23 -0
- package/src/TimeInput/TimeInput.tsx +8 -0
- package/src/Tokenizer/Tokenizer.test.tsx +50 -32
- package/src/Tokenizer/Tokenizer.tsx +5 -5
- package/src/Tooltip/useTooltip.tsx +4 -1
- package/src/Typeahead/BaseTypeahead.tsx +10 -3
- package/src/Typeahead/Typeahead.test.tsx +116 -7
- package/src/Typeahead/Typeahead.tsx +10 -1
- package/src/__tests__/stubMatchMedia.test.ts +79 -0
- package/src/__tests__/stubMatchMedia.ts +95 -0
- package/src/hooks/index.ts +9 -5
- package/src/hooks/useFocusTrap.ts +1 -14
- package/src/hooks/useInputStatusIcon.test.tsx +19 -0
- package/src/hooks/useInputStatusIcon.tsx +7 -0
- package/src/index.ts +1 -0
- package/src/theme/defineTheme.ts +22 -4
- package/src/theme/expandColorScale.test.ts +138 -0
- package/src/theme/expandColorScale.ts +89 -44
- package/src/utils/ime.test.ts +32 -0
- package/src/utils/ime.ts +69 -0
- package/src/utils/index.ts +2 -0
- package/dist/astryx.umd.js +0 -147
- package/dist/astryx.umd.js.map +0 -7
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file BottomSheetSwitcher.tsx
|
|
7
|
+
* @input Uses React context, StyleX, theme tokens, focus/scroll-lock hooks, BottomSheetSwitcherContext
|
|
8
|
+
* @output Exports BottomSheetSwitcher and BottomSheetSwitcherProps
|
|
9
|
+
* @position Core switcher for mutually exclusive BottomSheet flows
|
|
10
|
+
*
|
|
11
|
+
* The switcher turns a set of declaratively nested BottomSheets into a
|
|
12
|
+
* controlled single-selection group: `activeSheet` names the one interactive
|
|
13
|
+
* child, or is null when the flow is closed. During a handoff the new sheet
|
|
14
|
+
* enters above the previous sheet. If it is shorter, the previous sheet moves
|
|
15
|
+
* down at the same time until their top edges align; otherwise it stays
|
|
16
|
+
* stationary. The previous sheet fades only after both motions complete.
|
|
17
|
+
*
|
|
18
|
+
* All child sheets render as panels inside one switcher-owned `<dialog>`. A
|
|
19
|
+
* scrim flow calls showModal() once and keeps that native top-layer dialog open
|
|
20
|
+
* across every handoff. A no-scrim flow calls show() on the same non-modal shell.
|
|
21
|
+
* This keeps one modal boundary and one native ::backdrop without a portal.
|
|
22
|
+
*
|
|
23
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
24
|
+
* - /packages/core/src/BottomSheet/BottomSheet.tsx
|
|
25
|
+
* - /packages/core/src/BottomSheet/BottomSheetSwitcher.doc.mjs
|
|
26
|
+
* - /packages/core/src/BottomSheet/BottomSheetSwitcher.test.tsx
|
|
27
|
+
* - /packages/core/src/BottomSheet/index.ts
|
|
28
|
+
* - /apps/storybook/stories/BottomSheetSwitcher.stories.tsx
|
|
29
|
+
* - /packages/cli/assets/templates/blocks/components/BottomSheet/BottomSheetSwitcherShowcase.tsx
|
|
30
|
+
*/
|
|
31
|
+
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
32
|
+
import * as stylex from '@stylexjs/stylex';
|
|
33
|
+
import "../theme/tokens.stylex.js";
|
|
34
|
+
import { colorVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
|
|
35
|
+
import { hasActiveFocusTrapEscape, isImeKeyEvent, useFocusTrap, useScrollLock } from "../hooks/index.js";
|
|
36
|
+
import { composeEventHandlers, mergeProps, mergeRefs } from "../utils/index.js";
|
|
37
|
+
import { BottomSheetSwitcherContext } from "./BottomSheetSwitcherContext.js";
|
|
38
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
39
|
+
const styles = {
|
|
40
|
+
dialog: {
|
|
41
|
+
kVAEAm: "xixxii4",
|
|
42
|
+
kpwlN0: "x10a8y8t",
|
|
43
|
+
kzqmXN: "x1o6l61p",
|
|
44
|
+
kZKoxP: "xtdtrs8",
|
|
45
|
+
ks0D6T: "x1x1rfll",
|
|
46
|
+
kskxy: "x7ab17h",
|
|
47
|
+
kogj98: "x1ghz6dp",
|
|
48
|
+
kmVPX3: "x1717udv",
|
|
49
|
+
kWkggS: "xjbqb8w",
|
|
50
|
+
kVQacm: "x1rea2x4",
|
|
51
|
+
k1xSpc: "x1s85apg",
|
|
52
|
+
kI3sdo: "x1a2a7pz",
|
|
53
|
+
$$css: true
|
|
54
|
+
},
|
|
55
|
+
dialogOpen: {
|
|
56
|
+
k1xSpc: "x1lliihq",
|
|
57
|
+
$$css: true
|
|
58
|
+
},
|
|
59
|
+
dialogNonModal: {
|
|
60
|
+
kfzvcC: "x47corl",
|
|
61
|
+
kY2c9j: "xfo81ep",
|
|
62
|
+
kzqmXN: "xh8yej3",
|
|
63
|
+
kZKoxP: "x5yr21d",
|
|
64
|
+
$$css: true
|
|
65
|
+
},
|
|
66
|
+
scrim: {
|
|
67
|
+
kGyWv1: "xnixb3f",
|
|
68
|
+
k5sjJv: "xni466t xxiuuzi",
|
|
69
|
+
kND0Po: "xc0dz0a",
|
|
70
|
+
k9an0g: "xft5bk6",
|
|
71
|
+
kb4ib: "x15h3t91",
|
|
72
|
+
kwHxkk: "x142juwg",
|
|
73
|
+
k4oj2o: "x1viac0w",
|
|
74
|
+
$$css: true
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const IDLE_TRANSITION = {
|
|
78
|
+
enteringSheet: null,
|
|
79
|
+
retainedSheet: null,
|
|
80
|
+
retainedPhase: null,
|
|
81
|
+
alignmentOffset: 0,
|
|
82
|
+
isAlignmentComplete: false
|
|
83
|
+
};
|
|
84
|
+
const ALIGNMENT_THRESHOLD_PX = 1;
|
|
85
|
+
function transitionForActiveSheetChange(previousSheet, nextSheet) {
|
|
86
|
+
if (previousSheet == null) {
|
|
87
|
+
return IDLE_TRANSITION;
|
|
88
|
+
}
|
|
89
|
+
if (nextSheet == null) {
|
|
90
|
+
return {
|
|
91
|
+
enteringSheet: null,
|
|
92
|
+
retainedSheet: previousSheet,
|
|
93
|
+
retainedPhase: 'exiting',
|
|
94
|
+
alignmentOffset: 0,
|
|
95
|
+
isAlignmentComplete: false
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
enteringSheet: nextSheet,
|
|
100
|
+
retainedSheet: previousSheet,
|
|
101
|
+
retainedPhase: 'covered',
|
|
102
|
+
alignmentOffset: 0,
|
|
103
|
+
isAlignmentComplete: false
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function alignmentOffsetForElements(enteringElement, retainedElement) {
|
|
107
|
+
if (enteringElement == null || retainedElement == null) {
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
const enteringPositioner = enteringElement.parentElement;
|
|
111
|
+
const enteringTop = enteringPositioner?.getBoundingClientRect().top ?? enteringElement.getBoundingClientRect().top;
|
|
112
|
+
return Math.max(0, enteringTop - retainedElement.getBoundingClientRect().top);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Coordinates a set of BottomSheets so zero or one is active at a time inside
|
|
116
|
+
* one shared native dialog. During a handoff the previous panel stays visible
|
|
117
|
+
* and inert beneath the entering panel, then fades after motion completes.
|
|
118
|
+
*/
|
|
119
|
+
export function BottomSheetSwitcher({
|
|
120
|
+
activeSheet,
|
|
121
|
+
onActiveSheetChange,
|
|
122
|
+
hasScrim = true,
|
|
123
|
+
children,
|
|
124
|
+
ref,
|
|
125
|
+
xstyle,
|
|
126
|
+
className,
|
|
127
|
+
style,
|
|
128
|
+
onCancel,
|
|
129
|
+
onClick,
|
|
130
|
+
onKeyDown,
|
|
131
|
+
...props
|
|
132
|
+
}) {
|
|
133
|
+
const dialogRef = useRef(null);
|
|
134
|
+
const dialogModeRef = useRef(null);
|
|
135
|
+
const triggerRef = useRef(null);
|
|
136
|
+
const sheetElementsRef = useRef(new Map());
|
|
137
|
+
const committedActiveSheetRef = useRef(activeSheet);
|
|
138
|
+
const [sheetLabels, setSheetLabels] = useState(() => new Map());
|
|
139
|
+
const [sheetPurposes, setSheetPurposes] = useState(() => new Map());
|
|
140
|
+
const [unmountedSheetIds, setUnmountedSheetIds] = useState(() => new Set());
|
|
141
|
+
const [transition, setTransition] = useState(IDLE_TRANSITION);
|
|
142
|
+
const activeSheetChanged = committedActiveSheetRef.current !== activeSheet;
|
|
143
|
+
const visibleTransition = activeSheetChanged ? transitionForActiveSheetChange(committedActiveSheetRef.current, activeSheet) : transition;
|
|
144
|
+
const isFlowVisible = activeSheet != null && !unmountedSheetIds.has(activeSheet) || visibleTransition.retainedSheet != null && !unmountedSheetIds.has(visibleTransition.retainedSheet);
|
|
145
|
+
const isModal = hasScrim && isFlowVisible;
|
|
146
|
+
const activeSheetPurpose = (activeSheet == null ? null : sheetPurposes.get(activeSheet)) ?? 'info';
|
|
147
|
+
const allowsEscapeDismiss = activeSheetPurpose !== 'required';
|
|
148
|
+
const allowsLightDismiss = activeSheetPurpose === 'info';
|
|
149
|
+
useLayoutEffect(() => {
|
|
150
|
+
const previousActiveSheet = committedActiveSheetRef.current;
|
|
151
|
+
if (previousActiveSheet === activeSheet) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
committedActiveSheetRef.current = activeSheet;
|
|
155
|
+
const nextTransition = transitionForActiveSheetChange(previousActiveSheet, activeSheet);
|
|
156
|
+
setTransition(nextTransition.retainedSheet != null && !sheetElementsRef.current.has(nextTransition.retainedSheet) ? IDLE_TRANSITION : nextTransition);
|
|
157
|
+
}, [activeSheet]);
|
|
158
|
+
const dismissOnEscape = useCallback(() => {
|
|
159
|
+
if (allowsEscapeDismiss) {
|
|
160
|
+
onActiveSheetChange(null);
|
|
161
|
+
}
|
|
162
|
+
}, [allowsEscapeDismiss, onActiveSheetChange]);
|
|
163
|
+
const dismissOnLightInteraction = useCallback(() => {
|
|
164
|
+
if (allowsLightDismiss) {
|
|
165
|
+
onActiveSheetChange(null);
|
|
166
|
+
}
|
|
167
|
+
}, [allowsLightDismiss, onActiveSheetChange]);
|
|
168
|
+
const {
|
|
169
|
+
containerRef
|
|
170
|
+
} = useFocusTrap({
|
|
171
|
+
isActive: isModal,
|
|
172
|
+
onEscape: dismissOnEscape
|
|
173
|
+
});
|
|
174
|
+
useScrollLock(isModal);
|
|
175
|
+
|
|
176
|
+
// Open one shared shell for the complete flow. Modal flows enter the native
|
|
177
|
+
// top layer once; handoffs only swap panels inside it. The final panel owns
|
|
178
|
+
// the exit timing, so isFlowVisible becomes false only when it is safe to
|
|
179
|
+
// close the dialog and restore focus.
|
|
180
|
+
useLayoutEffect(() => {
|
|
181
|
+
const dialog = dialogRef.current;
|
|
182
|
+
if (dialog == null) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (isFlowVisible) {
|
|
186
|
+
const nextMode = hasScrim ? 'modal' : 'non-modal';
|
|
187
|
+
if (dialog.open && dialogModeRef.current !== nextMode) {
|
|
188
|
+
dialog.close();
|
|
189
|
+
}
|
|
190
|
+
if (!dialog.open) {
|
|
191
|
+
if (hasScrim && triggerRef.current == null) {
|
|
192
|
+
triggerRef.current = document.activeElement;
|
|
193
|
+
}
|
|
194
|
+
if (hasScrim) {
|
|
195
|
+
dialog.showModal();
|
|
196
|
+
} else {
|
|
197
|
+
dialog.show();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
dialogModeRef.current = nextMode;
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (dialog.open) {
|
|
204
|
+
dialog.close();
|
|
205
|
+
}
|
|
206
|
+
if (dialogModeRef.current === 'modal') {
|
|
207
|
+
triggerRef.current?.focus();
|
|
208
|
+
}
|
|
209
|
+
triggerRef.current = null;
|
|
210
|
+
dialogModeRef.current = null;
|
|
211
|
+
}, [hasScrim, isFlowVisible]);
|
|
212
|
+
const getSheetPhase = useCallback(sheetId => {
|
|
213
|
+
if (sheetId === activeSheet) {
|
|
214
|
+
return sheetId === visibleTransition.enteringSheet ? 'entering' : 'active';
|
|
215
|
+
}
|
|
216
|
+
if (sheetId === visibleTransition.retainedSheet) {
|
|
217
|
+
return visibleTransition.retainedPhase ?? 'hidden';
|
|
218
|
+
}
|
|
219
|
+
return 'hidden';
|
|
220
|
+
}, [activeSheet, visibleTransition]);
|
|
221
|
+
const getSheetAlignmentOffset = useCallback(sheetId => visibleTransition.retainedSheet === sheetId ? visibleTransition.alignmentOffset : 0, [visibleTransition]);
|
|
222
|
+
const registerSheetElement = useCallback((sheetId, element) => {
|
|
223
|
+
if (element == null) {
|
|
224
|
+
sheetElementsRef.current.delete(sheetId);
|
|
225
|
+
setUnmountedSheetIds(current => {
|
|
226
|
+
if (current.has(sheetId)) {
|
|
227
|
+
return current;
|
|
228
|
+
}
|
|
229
|
+
const next = new Set(current);
|
|
230
|
+
next.add(sheetId);
|
|
231
|
+
return next;
|
|
232
|
+
});
|
|
233
|
+
setTransition(current => current.retainedSheet === sheetId ? IDLE_TRANSITION : current);
|
|
234
|
+
} else {
|
|
235
|
+
sheetElementsRef.current.set(sheetId, element);
|
|
236
|
+
setUnmountedSheetIds(current => {
|
|
237
|
+
if (!current.has(sheetId)) {
|
|
238
|
+
return current;
|
|
239
|
+
}
|
|
240
|
+
const next = new Set(current);
|
|
241
|
+
next.delete(sheetId);
|
|
242
|
+
return next;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}, []);
|
|
246
|
+
const registerSheetLabel = useCallback((sheetId, label) => {
|
|
247
|
+
setSheetLabels(current => {
|
|
248
|
+
if (label == null) {
|
|
249
|
+
if (!current.has(sheetId)) {
|
|
250
|
+
return current;
|
|
251
|
+
}
|
|
252
|
+
const next = new Map(current);
|
|
253
|
+
next.delete(sheetId);
|
|
254
|
+
return next;
|
|
255
|
+
}
|
|
256
|
+
if (current.get(sheetId) === label) {
|
|
257
|
+
return current;
|
|
258
|
+
}
|
|
259
|
+
const next = new Map(current);
|
|
260
|
+
next.set(sheetId, label);
|
|
261
|
+
return next;
|
|
262
|
+
});
|
|
263
|
+
}, []);
|
|
264
|
+
const registerSheetPurpose = useCallback((sheetId, purpose) => {
|
|
265
|
+
setSheetPurposes(current => {
|
|
266
|
+
if (purpose == null) {
|
|
267
|
+
if (!current.has(sheetId)) {
|
|
268
|
+
return current;
|
|
269
|
+
}
|
|
270
|
+
const next = new Map(current);
|
|
271
|
+
next.delete(sheetId);
|
|
272
|
+
return next;
|
|
273
|
+
}
|
|
274
|
+
if (current.get(sheetId) === purpose) {
|
|
275
|
+
return current;
|
|
276
|
+
}
|
|
277
|
+
const next = new Map(current);
|
|
278
|
+
next.set(sheetId, purpose);
|
|
279
|
+
return next;
|
|
280
|
+
});
|
|
281
|
+
}, []);
|
|
282
|
+
useLayoutEffect(() => {
|
|
283
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect -- clear a retained sheet after its panel unmounts
|
|
284
|
+
setTransition(current => current.retainedSheet != null && unmountedSheetIds.has(current.retainedSheet) ? IDLE_TRANSITION : current);
|
|
285
|
+
}, [unmountedSheetIds]);
|
|
286
|
+
const onSheetEnterStart = useCallback(sheetId => {
|
|
287
|
+
setTransition(current => {
|
|
288
|
+
if (current.enteringSheet !== sheetId || current.retainedSheet == null || current.retainedPhase !== 'covered') {
|
|
289
|
+
return current;
|
|
290
|
+
}
|
|
291
|
+
const alignmentOffset = alignmentOffsetForElements(sheetElementsRef.current.get(sheetId), sheetElementsRef.current.get(current.retainedSheet));
|
|
292
|
+
if (alignmentOffset <= ALIGNMENT_THRESHOLD_PX) {
|
|
293
|
+
return current;
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
...current,
|
|
297
|
+
retainedPhase: 'aligning',
|
|
298
|
+
alignmentOffset,
|
|
299
|
+
isAlignmentComplete: false
|
|
300
|
+
};
|
|
301
|
+
});
|
|
302
|
+
}, []);
|
|
303
|
+
const onSheetTransitionComplete = useCallback(({
|
|
304
|
+
sheetId,
|
|
305
|
+
phase
|
|
306
|
+
}) => {
|
|
307
|
+
setTransition(current => {
|
|
308
|
+
if (phase === 'entering') {
|
|
309
|
+
if (current.enteringSheet !== sheetId) {
|
|
310
|
+
return current;
|
|
311
|
+
}
|
|
312
|
+
if (current.retainedSheet == null) {
|
|
313
|
+
return IDLE_TRANSITION;
|
|
314
|
+
}
|
|
315
|
+
if (current.retainedPhase === 'aligning' && !current.isAlignmentComplete) {
|
|
316
|
+
return {
|
|
317
|
+
...current,
|
|
318
|
+
enteringSheet: null
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
...current,
|
|
323
|
+
enteringSheet: null,
|
|
324
|
+
retainedPhase: 'fading'
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
if (phase === 'aligning' && current.retainedSheet === sheetId && current.retainedPhase === 'aligning') {
|
|
328
|
+
return current.enteringSheet == null ? {
|
|
329
|
+
...current,
|
|
330
|
+
retainedPhase: 'fading'
|
|
331
|
+
} : {
|
|
332
|
+
...current,
|
|
333
|
+
isAlignmentComplete: true
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
if ((phase === 'fading' || phase === 'exiting') && current.retainedSheet === sheetId && current.retainedPhase === phase) {
|
|
337
|
+
return IDLE_TRANSITION;
|
|
338
|
+
}
|
|
339
|
+
return current;
|
|
340
|
+
});
|
|
341
|
+
}, []);
|
|
342
|
+
const setScrimOpacity = useCallback(opacity => {
|
|
343
|
+
dialogRef.current?.style.setProperty('--_sheet-scrim-opacity', String(opacity));
|
|
344
|
+
}, []);
|
|
345
|
+
const onSheetScrimOpacityChange = useCallback((sheetId, opacity) => {
|
|
346
|
+
// A pointer captured by the outgoing sheet can keep delivering gesture
|
|
347
|
+
// events after a handoff. Only the currently committed sheet owns the
|
|
348
|
+
// shared backdrop, so stale gesture updates must not reach the dialog.
|
|
349
|
+
if (sheetId !== committedActiveSheetRef.current) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
setScrimOpacity(opacity);
|
|
353
|
+
}, [setScrimOpacity]);
|
|
354
|
+
useLayoutEffect(() => {
|
|
355
|
+
setScrimOpacity(activeSheet == null ? 0 : 1);
|
|
356
|
+
}, [activeSheet, setScrimOpacity]);
|
|
357
|
+
const contextValue = useMemo(() => ({
|
|
358
|
+
activeSheet,
|
|
359
|
+
hasScrim,
|
|
360
|
+
onActiveSheetChange,
|
|
361
|
+
getSheetPhase,
|
|
362
|
+
getSheetAlignmentOffset,
|
|
363
|
+
registerSheetElement,
|
|
364
|
+
registerSheetLabel,
|
|
365
|
+
registerSheetPurpose,
|
|
366
|
+
onSheetEnterStart,
|
|
367
|
+
onSheetTransitionComplete,
|
|
368
|
+
onSheetScrimOpacityChange
|
|
369
|
+
}), [activeSheet, getSheetAlignmentOffset, getSheetPhase, hasScrim, onActiveSheetChange, onSheetEnterStart, onSheetScrimOpacityChange, onSheetTransitionComplete, registerSheetElement, registerSheetLabel, registerSheetPurpose]);
|
|
370
|
+
const activeLabel = (activeSheet == null ? null : sheetLabels.get(activeSheet)) ?? (visibleTransition.retainedSheet == null ? undefined : sheetLabels.get(visibleTransition.retainedSheet));
|
|
371
|
+
const handleCancel = useCallback(event => {
|
|
372
|
+
event.preventDefault();
|
|
373
|
+
dismissOnEscape();
|
|
374
|
+
}, [dismissOnEscape]);
|
|
375
|
+
const handleKeyDown = useCallback(event => {
|
|
376
|
+
// Modal Escape is owned by useFocusTrap so nested traps can win. A
|
|
377
|
+
// non-modal switcher has no outer trap, so retain local dismissal while
|
|
378
|
+
// deferring to an active nested layer and ignoring IME cancellation.
|
|
379
|
+
if (!isModal && event.key === 'Escape' && !isImeKeyEvent(event.nativeEvent) && !hasActiveFocusTrapEscape()) {
|
|
380
|
+
event.preventDefault();
|
|
381
|
+
dismissOnEscape();
|
|
382
|
+
}
|
|
383
|
+
}, [dismissOnEscape, isModal]);
|
|
384
|
+
const handleClick = useCallback(event => {
|
|
385
|
+
if (hasScrim && event.target === event.currentTarget) {
|
|
386
|
+
dismissOnLightInteraction();
|
|
387
|
+
}
|
|
388
|
+
}, [dismissOnLightInteraction, hasScrim]);
|
|
389
|
+
const dialogStyleProps = stylex.props(styles.dialog, isFlowVisible && styles.dialogOpen, hasScrim && styles.scrim, !hasScrim && styles.dialogNonModal, xstyle);
|
|
390
|
+
const dialogPresentationProps = mergeProps(dialogStyleProps, className, style);
|
|
391
|
+
const ariaLabel = props['aria-label'] ?? (props['aria-labelledby'] == null ? activeLabel : undefined);
|
|
392
|
+
return /*#__PURE__*/_jsx(BottomSheetSwitcherContext, {
|
|
393
|
+
value: contextValue,
|
|
394
|
+
children: /*#__PURE__*/_jsx("dialog", {
|
|
395
|
+
...props,
|
|
396
|
+
...dialogPresentationProps,
|
|
397
|
+
ref: mergeRefs(ref, dialogRef, containerRef),
|
|
398
|
+
"aria-label": ariaLabel,
|
|
399
|
+
"aria-modal": isModal ? 'true' : undefined,
|
|
400
|
+
onCancel: composeEventHandlers(onCancel, handleCancel),
|
|
401
|
+
onClick: composeEventHandlers(onClick, handleClick),
|
|
402
|
+
onKeyDown: composeEventHandlers(onKeyDown, handleKeyDown),
|
|
403
|
+
...(activeSheetPurpose === 'required' ? {
|
|
404
|
+
role: 'alertdialog'
|
|
405
|
+
} : undefined),
|
|
406
|
+
children: children
|
|
407
|
+
})
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
BottomSheetSwitcher.displayName = 'BottomSheetSwitcher';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DialogPurpose } from '../Dialog';
|
|
2
|
+
export type BottomSheetSwitcherPhase = 'entering' | 'active' | 'covered' | 'aligning' | 'fading' | 'exiting' | 'hidden';
|
|
3
|
+
export interface BottomSheetSwitcherTransitionEvent {
|
|
4
|
+
sheetId: string;
|
|
5
|
+
phase: 'entering' | 'aligning' | 'fading' | 'exiting';
|
|
6
|
+
}
|
|
7
|
+
export interface BottomSheetSwitcherContextValue {
|
|
8
|
+
activeSheet: string | null;
|
|
9
|
+
hasScrim: boolean;
|
|
10
|
+
onActiveSheetChange: (sheetId: string | null) => void;
|
|
11
|
+
getSheetPhase: (sheetId: string) => BottomSheetSwitcherPhase;
|
|
12
|
+
getSheetAlignmentOffset: (sheetId: string) => number;
|
|
13
|
+
registerSheetElement: (sheetId: string, element: HTMLElement | null) => void;
|
|
14
|
+
registerSheetLabel: (sheetId: string, label: string | null) => void;
|
|
15
|
+
registerSheetPurpose: (sheetId: string, purpose: DialogPurpose | null) => void;
|
|
16
|
+
onSheetEnterStart: (sheetId: string) => void;
|
|
17
|
+
onSheetTransitionComplete: (event: BottomSheetSwitcherTransitionEvent) => void;
|
|
18
|
+
onSheetScrimOpacityChange: (sheetId: string, opacity: number) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare const BottomSheetSwitcherContext: import("react").Context<BottomSheetSwitcherContextValue | null>;
|
|
21
|
+
//# sourceMappingURL=BottomSheetSwitcherContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BottomSheetSwitcherContext.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetSwitcherContext.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAE7C,MAAM,MAAM,wBAAwB,GAChC,UAAU,GACV,QAAQ,GACR,SAAS,GACT,UAAU,GACV,QAAQ,GACR,SAAS,GACT,QAAQ,CAAC;AAEb,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;CACvD;AAED,MAAM,WAAW,+BAA+B;IAC9C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACtD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,wBAAwB,CAAC;IAC7D,uBAAuB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IACrD,oBAAoB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7E,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACpE,oBAAoB,EAAE,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,GAAG,IAAI,KAC1B,IAAI,CAAC;IACV,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,yBAAyB,EAAE,CACzB,KAAK,EAAE,kCAAkC,KACtC,IAAI,CAAC;IACV,yBAAyB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvE;AAED,eAAO,MAAM,0BAA0B,iEACsB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file BottomSheetSwitcherContext.ts
|
|
7
|
+
* @input Uses React context
|
|
8
|
+
* @output Internal phase and lifecycle context shared by BottomSheetSwitcher and BottomSheet
|
|
9
|
+
* @position Private coordination layer for mutually exclusive BottomSheets
|
|
10
|
+
*/
|
|
11
|
+
import { createContext } from 'react';
|
|
12
|
+
export const BottomSheetSwitcherContext = /*#__PURE__*/createContext(null);
|
|
13
|
+
BottomSheetSwitcherContext.displayName = 'BottomSheetSwitcherContext';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @input BottomSheet.tsx, BottomSheetSwitcher.tsx
|
|
4
|
+
* @output Re-exports the BottomSheet public API
|
|
5
|
+
* @position Component entry point; re-exported by /packages/core/src/index.ts
|
|
6
|
+
*/
|
|
7
|
+
export { BottomSheet } from './BottomSheet';
|
|
8
|
+
export type { BottomSheetHeight, BottomSheetProps } from './BottomSheet';
|
|
9
|
+
export { BottomSheetSwitcher } from './BottomSheetSwitcher';
|
|
10
|
+
export type { BottomSheetSwitcherProps } from './BottomSheetSwitcher';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/index.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAC,iBAAiB,EAAE,gBAAgB,EAAC,MAAM,eAAe,CAAC;AACvE,OAAO,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC1D,YAAY,EAAC,wBAAwB,EAAC,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file index.ts
|
|
7
|
+
* @input BottomSheet.tsx, BottomSheetSwitcher.tsx
|
|
8
|
+
* @output Re-exports the BottomSheet public API
|
|
9
|
+
* @position Component entry point; re-exported by /packages/core/src/index.ts
|
|
10
|
+
*/
|
|
11
|
+
export { BottomSheet } from "./BottomSheet.js";
|
|
12
|
+
export { BottomSheetSwitcher } from "./BottomSheetSwitcher.js";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file snapOffsets.ts
|
|
3
|
+
* @input Pure geometry helpers — no React, no DOM.
|
|
4
|
+
* @output Converts snap points to translateY offsets for the sheet surface.
|
|
5
|
+
* @position Internal to BottomSheet; consumed by useSheetGestures, tested by
|
|
6
|
+
* snapOffsets.test.ts.
|
|
7
|
+
*
|
|
8
|
+
* A detent is represented as an offset in px from the fully-open position
|
|
9
|
+
* (0 = fully open, larger = more collapsed). The panel may render that offset
|
|
10
|
+
* as a translate or as a reduction in layout height. These
|
|
11
|
+
* helpers turn snap points into the shared offset list; they are pure so the
|
|
12
|
+
* geometry can be unit-tested without a DOM.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Detents whose resting offsets land within this many px of each other are
|
|
16
|
+
* treated as the same stop (the taller one wins). Stops the sheet from having
|
|
17
|
+
* two near-identical rest positions — e.g. when a content-hugging height sits
|
|
18
|
+
* a hair away from a fractional snap point.
|
|
19
|
+
*/
|
|
20
|
+
export declare const DETENT_DEDUP_PX = 48;
|
|
21
|
+
/** Resolve snap points given as viewport fractions (0, 1] to px heights. */
|
|
22
|
+
export declare function snapFractionsToHeights(fractions: ReadonlyArray<number>, viewportPx: number): number[];
|
|
23
|
+
/**
|
|
24
|
+
* Given the sheet's full height (px, as rendered fully open) and a set of
|
|
25
|
+
* candidate detent *visible heights* (px), return the resting offsets from
|
|
26
|
+
* fully-open, ascending and de-duplicated.
|
|
27
|
+
*
|
|
28
|
+
* - `0` (fully open) is always the first detent.
|
|
29
|
+
* - Only heights strictly shorter than the sheet become collapsed detents; a
|
|
30
|
+
* height >= the sheet is already covered by the fully-open stop.
|
|
31
|
+
* - Offsets closer than `dedupPx` collapse to the smaller (taller) offset, so
|
|
32
|
+
* near-identical detents — e.g. a hug height ≈ a snap point — become one stop.
|
|
33
|
+
*/
|
|
34
|
+
export declare function computeDetentOffsets(sheetHeight: number, detentHeights: ReadonlyArray<number>, dedupPx?: number): number[];
|
|
35
|
+
/** Nearest value in `offsets` to `value` (offsets must be non-empty). */
|
|
36
|
+
export declare function nearestOffset(value: number, offsets: ReadonlyArray<number>): number;
|
|
37
|
+
/**
|
|
38
|
+
* Minimum scrim opacity at the peek detent. The scrim thins to a glance state
|
|
39
|
+
* but never fully vanishes, because a modal sheet keeps the background inert —
|
|
40
|
+
* a fully clear backdrop would read as "interactive" when it isn't. (For a
|
|
41
|
+
* genuinely interactive, undimmed peek, use a non-modal sheet, `hasScrim=false`.)
|
|
42
|
+
*/
|
|
43
|
+
export declare const MIN_PEEK_SCRIM_OPACITY = 0.3;
|
|
44
|
+
/**
|
|
45
|
+
* Whether `offset` is the peek detent: the shortest stop, where the sheet is a
|
|
46
|
+
* glance rather than a working surface. A sheet with no collapsed stop at all
|
|
47
|
+
* has no peek — the same rule `scrimOpacityForOffset` thins the scrim by.
|
|
48
|
+
*
|
|
49
|
+
* The peek is the one detent the sheet does NOT express as layout height: at a
|
|
50
|
+
* sliver of viewport there is nothing useful to lay out, and reflowing the
|
|
51
|
+
* content into it (then back out on the way up) is churn the user sees. It
|
|
52
|
+
* keeps the full layout height and slides below the viewport instead.
|
|
53
|
+
*/
|
|
54
|
+
export declare function isPeekOffset(offset: number, offsets: ReadonlyArray<number>, tolerancePx?: number): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Scrim opacity (1 = fully visible) for a drag/settle `offset`.
|
|
57
|
+
* The scrim stays full while the sheet is at or above its second-shortest
|
|
58
|
+
* detent, then fades as it collapses onto the shortest ("peek") detent — a
|
|
59
|
+
* glance state that thins the backdrop to `MIN_PEEK_SCRIM_OPACITY` (not fully
|
|
60
|
+
* gone, since the sheet is still modal) and holds there below it.
|
|
61
|
+
* A single-detent sheet has no peek, so it instead fades all the way to 0
|
|
62
|
+
* across the dismiss overshoot toward `dismissOffset` (the sheet is leaving).
|
|
63
|
+
*/
|
|
64
|
+
export declare function scrimOpacityForOffset(offset: number, offsets: ReadonlyArray<number>, dismissOffset: number): number;
|
|
65
|
+
/**
|
|
66
|
+
* Settle target for a released drag. Restricts candidates to the drag
|
|
67
|
+
* direction so a committed drag never snaps *back past* where it started
|
|
68
|
+
* (a down-drag settles at/below the start, an up-drag at/above), then picks
|
|
69
|
+
* the nearest remaining detent. `dir`: 1 = dragged down, -1 = up, 0 = neither.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveSettleOffset(value: number, offsets: ReadonlyArray<number>, dir: number, baseOffset: number): number;
|
|
72
|
+
//# sourceMappingURL=snapOffsets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapOffsets.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/snapOffsets.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,4EAA4E;AAC5E,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,EAChC,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAEV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,EACpC,OAAO,GAAE,MAAwB,GAChC,MAAM,EAAE,CAcV;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAC7B,MAAM,CAKR;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,WAAW,GAAE,MAAY,GACxB,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,aAAa,EAAE,MAAM,GACpB,MAAM,CAeR;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GACjB,MAAM,CAcR"}
|