@lodev09/react-native-true-sheet 3.10.0 → 3.11.0-beta.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/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +11 -4
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +10 -5
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetStackManager.kt +2 -5
- package/lib/module/TrueSheet.js +3 -0
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +604 -376
- package/lib/module/TrueSheet.web.js.map +1 -1
- package/lib/module/TrueSheetProvider.js.map +1 -1
- package/lib/module/TrueSheetProvider.web.js +141 -100
- package/lib/module/TrueSheetProvider.web.js.map +1 -1
- package/lib/module/mocks/index.js.map +1 -1
- package/lib/module/reanimated/ReanimatedTrueSheet.web.js.map +1 -1
- package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js +2 -3
- package/lib/module/reanimated/useReanimatedPositionChangeHandler.web.js.map +1 -1
- package/lib/module/web/constants.js +16 -0
- package/lib/module/web/constants.js.map +1 -0
- package/lib/module/web/vaul/README.md +9 -0
- package/lib/module/web/vaul/browser.js +30 -0
- package/lib/module/web/vaul/browser.js.map +1 -0
- package/lib/module/web/vaul/constants.js +14 -0
- package/lib/module/web/vaul/constants.js.map +1 -0
- package/lib/module/web/vaul/context.js +57 -0
- package/lib/module/web/vaul/context.js.map +1 -0
- package/lib/module/web/vaul/helpers.js +93 -0
- package/lib/module/web/vaul/helpers.js.map +1 -0
- package/lib/module/web/vaul/index.js +1206 -0
- package/lib/module/web/vaul/index.js.map +1 -0
- package/lib/module/web/vaul/style.css +264 -0
- package/lib/module/web/vaul/types.js +2 -0
- package/lib/module/web/vaul/types.js.map +1 -0
- package/lib/module/web/vaul/use-composed-refs.js +34 -0
- package/lib/module/web/vaul/use-composed-refs.js.map +1 -0
- package/lib/module/web/vaul/use-controllable-state.js +54 -0
- package/lib/module/web/vaul/use-controllable-state.js.map +1 -0
- package/lib/module/web/vaul/use-position-fixed.js +123 -0
- package/lib/module/web/vaul/use-position-fixed.js.map +1 -0
- package/lib/module/web/vaul/use-prevent-scroll.js +258 -0
- package/lib/module/web/vaul/use-prevent-scroll.js.map +1 -0
- package/lib/module/web/vaul/use-scale-background.js +57 -0
- package/lib/module/web/vaul/use-scale-background.js.map +1 -0
- package/lib/module/web/vaul/use-snap-points.js +294 -0
- package/lib/module/web/vaul/use-snap-points.js.map +1 -0
- package/lib/typescript/src/TrueSheet.d.ts +2 -2
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +79 -36
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.web.d.ts +3 -11
- package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheetProvider.d.ts +2 -2
- package/lib/typescript/src/TrueSheetProvider.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheetProvider.web.d.ts +17 -14
- package/lib/typescript/src/TrueSheetProvider.web.d.ts.map +1 -1
- package/lib/typescript/src/mocks/index.d.ts +1 -2
- package/lib/typescript/src/mocks/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/types.d.ts +1 -1
- package/lib/typescript/src/navigation/types.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts +0 -1
- package/lib/typescript/src/reanimated/ReanimatedTrueSheet.web.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts +2 -3
- package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.web.d.ts.map +1 -1
- package/lib/typescript/src/web/constants.d.ts +14 -0
- package/lib/typescript/src/web/constants.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/browser.d.ts +8 -0
- package/lib/typescript/src/web/vaul/browser.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts +12 -0
- package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/context.d.ts +45 -0
- package/lib/typescript/src/web/vaul/context.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/helpers.d.ts +17 -0
- package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/index.d.ts +210 -0
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/types.d.ts +7 -0
- package/lib/typescript/src/web/vaul/types.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-composed-refs.d.ts +14 -0
- package/lib/typescript/src/web/vaul/use-composed-refs.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-controllable-state.d.ts +9 -0
- package/lib/typescript/src/web/vaul/use-controllable-state.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-position-fixed.d.ts +19 -0
- package/lib/typescript/src/web/vaul/use-position-fixed.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts +18 -0
- package/lib/typescript/src/web/vaul/use-prevent-scroll.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-scale-background.d.ts +2 -0
- package/lib/typescript/src/web/vaul/use-scale-background.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts +37 -0
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/TrueSheet.tsx +9 -1
- package/src/TrueSheet.types.ts +88 -38
- package/src/TrueSheet.web.tsx +675 -450
- package/src/TrueSheetProvider.tsx +2 -4
- package/src/TrueSheetProvider.web.tsx +193 -125
- package/src/mocks/index.ts +1 -2
- package/src/navigation/types.ts +0 -1
- package/src/reanimated/ReanimatedTrueSheet.web.tsx +0 -1
- package/src/reanimated/useReanimatedPositionChangeHandler.web.ts +2 -3
- package/src/web/constants.ts +13 -0
- package/src/web/vaul/README.md +9 -0
- package/src/web/vaul/browser.ts +38 -0
- package/src/web/vaul/constants.ts +18 -0
- package/src/web/vaul/context.ts +87 -0
- package/src/web/vaul/helpers.ts +124 -0
- package/src/web/vaul/index.tsx +1590 -0
- package/src/web/vaul/style.css +264 -0
- package/src/web/vaul/types.ts +7 -0
- package/src/web/vaul/use-composed-refs.ts +35 -0
- package/src/web/vaul/use-controllable-state.ts +66 -0
- package/src/web/vaul/use-position-fixed.ts +147 -0
- package/src/web/vaul/use-prevent-scroll.ts +309 -0
- package/src/web/vaul/use-scale-background.ts +64 -0
- package/src/web/vaul/use-snap-points.ts +433 -0
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
import { TrueSheet } from './TrueSheet';
|
|
4
|
+
import type { TrueSheetStaticMethods } from './TrueSheet.types';
|
|
4
5
|
|
|
5
|
-
export type TrueSheetStaticMethods
|
|
6
|
-
typeof TrueSheet,
|
|
7
|
-
'present' | 'dismiss' | 'dismissStack' | 'resize' | 'dismissAll'
|
|
8
|
-
>;
|
|
6
|
+
export type { TrueSheetStaticMethods };
|
|
9
7
|
|
|
10
8
|
export interface TrueSheetProviderProps {
|
|
11
9
|
children: ReactNode;
|
|
@@ -1,143 +1,211 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useLayoutEffect,
|
|
7
|
+
useMemo,
|
|
8
|
+
useRef,
|
|
9
|
+
useSyncExternalStore,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
type RefObject,
|
|
12
|
+
} from 'react';
|
|
13
|
+
|
|
14
|
+
import type { TrueSheetMethods, TrueSheetStaticMethods } from './TrueSheet.types';
|
|
15
|
+
|
|
16
|
+
type SheetRef = RefObject<TrueSheetMethods | null>;
|
|
17
|
+
type NodeRef = RefObject<HTMLDivElement | null>;
|
|
18
|
+
|
|
19
|
+
interface StackEntry {
|
|
20
|
+
ref: SheetRef;
|
|
21
|
+
nodeRef: NodeRef;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
interface SheetContextValue {
|
|
25
|
+
registerByName: (name: string, ref: SheetRef) => () => void;
|
|
26
|
+
resolveByName: (name: string) => TrueSheetMethods;
|
|
27
|
+
pushOpen: (entry: StackEntry) => void;
|
|
28
|
+
popOpen: (entry: StackEntry) => void;
|
|
29
|
+
subscribeStack: (listener: () => void) => () => void;
|
|
30
|
+
getStackSnapshot: () => readonly StackEntry[];
|
|
31
|
+
portalContainer: HTMLElement | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const SheetContext = createContext<SheetContextValue | null>(null);
|
|
35
|
+
|
|
36
|
+
const NO_PROVIDER_ERROR =
|
|
37
|
+
'TrueSheet: useTrueSheet() requires a <TrueSheetProvider> ancestor on web.';
|
|
38
|
+
|
|
39
|
+
const EMPTY_STACK: readonly StackEntry[] = Object.freeze([]);
|
|
21
40
|
|
|
22
41
|
export interface TrueSheetProviderProps {
|
|
23
42
|
children: ReactNode;
|
|
24
43
|
}
|
|
25
44
|
|
|
26
|
-
/**
|
|
27
|
-
* Provider for TrueSheet on web.
|
|
28
|
-
* Required to wrap your app for sheet management via useTrueSheet hook.
|
|
29
|
-
*/
|
|
30
45
|
export function TrueSheetProvider({ children }: TrueSheetProviderProps) {
|
|
31
|
-
const
|
|
32
|
-
const
|
|
46
|
+
const namedSheetsRef = useRef<Map<string, SheetRef>>(new Map());
|
|
47
|
+
const stackRef = useRef<readonly StackEntry[]>(EMPTY_STACK);
|
|
48
|
+
const listenersRef = useRef<Set<() => void>>(new Set());
|
|
49
|
+
|
|
50
|
+
// Stable portal container created once. Attached to an anchor div rendered
|
|
51
|
+
// in this provider's tree so the sheets unmount cleanly with the provider
|
|
52
|
+
// (e.g., when a screen-scoped provider unmounts on navigation).
|
|
53
|
+
const portalContainer = useMemo<HTMLDivElement | null>(
|
|
54
|
+
() => (typeof document !== 'undefined' ? document.createElement('div') : null),
|
|
55
|
+
[]
|
|
56
|
+
);
|
|
57
|
+
const anchorRef = useRef<HTMLDivElement | null>(null);
|
|
58
|
+
|
|
59
|
+
useLayoutEffect(() => {
|
|
60
|
+
const anchor = anchorRef.current;
|
|
61
|
+
if (!anchor || !portalContainer) return;
|
|
62
|
+
anchor.appendChild(portalContainer);
|
|
63
|
+
return () => {
|
|
64
|
+
if (portalContainer.parentNode) {
|
|
65
|
+
portalContainer.parentNode.removeChild(portalContainer);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}, [portalContainer]);
|
|
69
|
+
|
|
70
|
+
const value = useMemo<SheetContextValue>(() => {
|
|
71
|
+
const notify = () => listenersRef.current.forEach((listener) => listener());
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
registerByName: (name, ref) => {
|
|
75
|
+
namedSheetsRef.current.set(name, ref);
|
|
76
|
+
return () => {
|
|
77
|
+
if (namedSheetsRef.current.get(name) === ref) {
|
|
78
|
+
namedSheetsRef.current.delete(name);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
resolveByName: (name) => {
|
|
83
|
+
const ref = namedSheetsRef.current.get(name);
|
|
84
|
+
const methods = ref?.current;
|
|
85
|
+
if (!methods) {
|
|
86
|
+
throw new Error(`TrueSheet: no sheet registered with name "${name}"`);
|
|
87
|
+
}
|
|
88
|
+
return methods;
|
|
89
|
+
},
|
|
90
|
+
pushOpen: (entry) => {
|
|
91
|
+
if (stackRef.current.some((e) => e.ref === entry.ref)) return;
|
|
92
|
+
stackRef.current = [...stackRef.current, entry];
|
|
93
|
+
notify();
|
|
94
|
+
},
|
|
95
|
+
popOpen: (entry) => {
|
|
96
|
+
const idx = stackRef.current.findIndex((e) => e.ref === entry.ref);
|
|
97
|
+
if (idx < 0) return;
|
|
98
|
+
stackRef.current = [...stackRef.current.slice(0, idx), ...stackRef.current.slice(idx + 1)];
|
|
99
|
+
notify();
|
|
100
|
+
},
|
|
101
|
+
subscribeStack: (listener) => {
|
|
102
|
+
listenersRef.current.add(listener);
|
|
103
|
+
return () => {
|
|
104
|
+
listenersRef.current.delete(listener);
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
getStackSnapshot: () => stackRef.current,
|
|
108
|
+
portalContainer,
|
|
109
|
+
};
|
|
110
|
+
}, [portalContainer]);
|
|
33
111
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
112
|
+
return (
|
|
113
|
+
<SheetContext.Provider value={value}>
|
|
114
|
+
{children}
|
|
115
|
+
<div ref={anchorRef} />
|
|
116
|
+
</SheetContext.Provider>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
37
119
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
120
|
+
export function usePortalContainer(): HTMLElement | null {
|
|
121
|
+
const ctx = useContext(SheetContext);
|
|
122
|
+
return ctx?.portalContainer ?? null;
|
|
123
|
+
}
|
|
41
124
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
125
|
+
export function useTrueSheet(): TrueSheetStaticMethods {
|
|
126
|
+
const ctx = useContext(SheetContext);
|
|
127
|
+
|
|
128
|
+
return useMemo<TrueSheetStaticMethods>(() => {
|
|
129
|
+
if (!ctx) {
|
|
130
|
+
const reject = async (): Promise<never> => {
|
|
131
|
+
throw new Error(NO_PROVIDER_ERROR);
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
present: reject,
|
|
135
|
+
resize: reject,
|
|
136
|
+
dismiss: reject,
|
|
137
|
+
dismissStack: reject,
|
|
138
|
+
dismissAll: reject,
|
|
139
|
+
};
|
|
46
140
|
}
|
|
47
|
-
presentedStackRef.current.push(name);
|
|
48
|
-
};
|
|
49
141
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return presentedStackRef.current.slice(index + 1).reverse();
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const present = async (name: string, index: number = 0) => {
|
|
68
|
-
const sheet = sheetsRef.current.get(name);
|
|
69
|
-
if (!sheet?.current) {
|
|
70
|
-
console.warn(`TrueSheet: Could not find sheet with name "${name}"`);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
return sheet.current.present(index);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const dismiss = async (name: string) => {
|
|
77
|
-
const sheet = sheetsRef.current.get(name);
|
|
78
|
-
if (!sheet?.current) {
|
|
79
|
-
console.warn(`TrueSheet: Could not find sheet with name "${name}"`);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
return sheet.current.dismiss();
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const dismissStack = async (name: string) => {
|
|
86
|
-
const sheet = sheetsRef.current.get(name);
|
|
87
|
-
if (!sheet?.current) {
|
|
88
|
-
console.warn(`TrueSheet: Could not find sheet with name "${name}"`);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
return sheet.current.dismissStack();
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const resize = async (name: string, index: number) => {
|
|
95
|
-
const sheet = sheetsRef.current.get(name);
|
|
96
|
-
if (!sheet?.current) {
|
|
97
|
-
console.warn(`TrueSheet: Could not find sheet with name "${name}"`);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
return sheet.current.resize(index);
|
|
101
|
-
};
|
|
142
|
+
return {
|
|
143
|
+
present: (name, index, animated) => ctx.resolveByName(name).present(index, animated),
|
|
144
|
+
resize: (name, index) => ctx.resolveByName(name).resize(index),
|
|
145
|
+
dismiss: (name, animated) => ctx.resolveByName(name).dismiss(animated),
|
|
146
|
+
dismissStack: (name, animated) => ctx.resolveByName(name).dismissStack(animated),
|
|
147
|
+
dismissAll: async (animated) => {
|
|
148
|
+
const stack = ctx.getStackSnapshot();
|
|
149
|
+
await Promise.all(
|
|
150
|
+
[...stack].reverse().map((entry) => entry.ref.current?.dismiss(animated))
|
|
151
|
+
);
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}, [ctx]);
|
|
155
|
+
}
|
|
102
156
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
157
|
+
export function useRegisterSheet(name: string | undefined, ref: SheetRef): void {
|
|
158
|
+
const ctx = useContext(SheetContext);
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
if (!ctx || !name) return;
|
|
161
|
+
return ctx.registerByName(name, ref);
|
|
162
|
+
}, [ctx, name, ref]);
|
|
163
|
+
}
|
|
108
164
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
165
|
+
/**
|
|
166
|
+
* Registers the sheet in the open stack while `isOpen` is true and returns
|
|
167
|
+
* live data used by each sheet to render stacked visuals and dismiss children.
|
|
168
|
+
*/
|
|
169
|
+
export function useSheetStack(ref: SheetRef, nodeRef: NodeRef, isOpen: boolean) {
|
|
170
|
+
const ctx = useContext(SheetContext);
|
|
171
|
+
|
|
172
|
+
const entry = useMemo<StackEntry>(() => ({ ref, nodeRef }), [ref, nodeRef]);
|
|
173
|
+
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
if (!ctx || !isOpen) return;
|
|
176
|
+
ctx.pushOpen(entry);
|
|
177
|
+
return () => ctx.popOpen(entry);
|
|
178
|
+
}, [ctx, entry, isOpen]);
|
|
179
|
+
|
|
180
|
+
const subscribe = useCallback(
|
|
181
|
+
(listener: () => void) => {
|
|
182
|
+
if (!ctx) return () => {};
|
|
183
|
+
return ctx.subscribeStack(listener);
|
|
184
|
+
},
|
|
185
|
+
[ctx]
|
|
126
186
|
);
|
|
127
|
-
}
|
|
128
187
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
188
|
+
const getSnapshot = useCallback(() => (ctx ? ctx.getStackSnapshot() : EMPTY_STACK), [ctx]);
|
|
189
|
+
|
|
190
|
+
const stack = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
191
|
+
const stackIndex = stack.findIndex((e) => e.ref === ref);
|
|
192
|
+
const isNested = stackIndex > 0;
|
|
193
|
+
const descendants = useMemo<readonly StackEntry[]>(
|
|
194
|
+
() => (stackIndex < 0 ? EMPTY_STACK : stack.slice(stackIndex + 1)),
|
|
195
|
+
[stack, stackIndex]
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const dismissAbove = useCallback(
|
|
199
|
+
async (animated?: boolean) => {
|
|
200
|
+
if (!ctx) return;
|
|
201
|
+
const snapshot = ctx.getStackSnapshot();
|
|
202
|
+
const idx = snapshot.findIndex((e) => e.ref === ref);
|
|
203
|
+
if (idx < 0) return;
|
|
204
|
+
const above = snapshot.slice(idx + 1);
|
|
205
|
+
await Promise.all([...above].reverse().map((e) => e.ref.current?.dismiss(animated)));
|
|
206
|
+
},
|
|
207
|
+
[ctx, ref]
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
return { descendants, isNested, dismissAbove };
|
|
143
211
|
}
|
package/src/mocks/index.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React, { createElement, isValidElement, type ReactNode } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import type { TrueSheetProps } from '../TrueSheet.types';
|
|
5
|
-
import type { TrueSheetStaticMethods } from '../TrueSheetProvider';
|
|
4
|
+
import type { TrueSheetProps, TrueSheetStaticMethods } from '../TrueSheet.types';
|
|
6
5
|
|
|
7
6
|
interface TrueSheetState {
|
|
8
7
|
shouldRenderNativeView: boolean;
|
package/src/navigation/types.ts
CHANGED
|
@@ -8,7 +8,6 @@ import { useReanimatedTrueSheet } from './ReanimatedTrueSheetProvider';
|
|
|
8
8
|
interface ReanimatedTrueSheetProps extends TrueSheetProps {
|
|
9
9
|
/**
|
|
10
10
|
* Callback for position changes.
|
|
11
|
-
* On web, this is called with the position data from @gorhom/bottom-sheet.
|
|
12
11
|
*
|
|
13
12
|
* @see {@link TrueSheetProps.onPositionChange}
|
|
14
13
|
*/
|
|
@@ -9,9 +9,8 @@ type PositionChangeHandler = (
|
|
|
9
9
|
/**
|
|
10
10
|
* Web implementation of useReanimatedPositionChangeHandler.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* on web as there's no native UI thread.
|
|
12
|
+
* Returns a simple callback wrapper. The worklet directive is ignored on web
|
|
13
|
+
* since there's no native UI thread.
|
|
15
14
|
*
|
|
16
15
|
* @param handler - The position change handler function
|
|
17
16
|
* @param _dependencies - Unused on web, kept for API compatibility
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const DEFAULT_CORNER_RADIUS = 16;
|
|
2
|
+
export const DEFAULT_MAX_WIDTH = 640;
|
|
3
|
+
export const DEFAULT_FORM_SHEET_WIDTH = 580;
|
|
4
|
+
export const DEFAULT_FORM_SHEET_HEIGHT_RATIO = 0.5;
|
|
5
|
+
export const COLOR_SURFACE_CONTAINER_LOW_LIGHT = '#F7F2FA';
|
|
6
|
+
export const COLOR_SURFACE_CONTAINER_LOW_DARK = '#1D1B20';
|
|
7
|
+
export const DEFAULT_ANCHOR_OFFSET = 16;
|
|
8
|
+
export const DEFAULT_DETACHED_OFFSET = 16;
|
|
9
|
+
export const DEFAULT_GRABBER_COLOR_LIGHT = 'rgba(0, 0, 0, 0.3)';
|
|
10
|
+
export const DEFAULT_GRABBER_COLOR_DARK = 'rgba(255, 255, 255, 0.3)';
|
|
11
|
+
export const DEFAULT_GRABBER_WIDTH = 32;
|
|
12
|
+
export const DEFAULT_GRABBER_HEIGHT = 4;
|
|
13
|
+
export const DEFAULT_GRABBER_TOP_MARGIN = 16;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# vaul
|
|
2
|
+
|
|
3
|
+
Originally forked from [vaul](https://github.com/emilkowalski/vaul) by Emil Kowalski at `v1.1.2`. Upstream is unmaintained; maintained here as part of truesheet's web renderer.
|
|
4
|
+
|
|
5
|
+
Only external runtime dep: `@radix-ui/react-dialog`.
|
|
6
|
+
|
|
7
|
+
## License
|
|
8
|
+
|
|
9
|
+
vaul is MIT-licensed. See the [upstream LICENSE](https://github.com/emilkowalski/vaul/blob/main/LICENSE.md). Original copyright remains with Emil Kowalski.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function isMobileFirefox(): boolean | undefined {
|
|
2
|
+
const userAgent = navigator.userAgent;
|
|
3
|
+
return (
|
|
4
|
+
typeof window !== 'undefined' &&
|
|
5
|
+
((/Firefox/.test(userAgent) && /Mobile/.test(userAgent)) || // Android Firefox
|
|
6
|
+
/FxiOS/.test(userAgent)) // iOS Firefox
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function isMac(): boolean | undefined {
|
|
11
|
+
return testPlatform(/^Mac/);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isIPhone(): boolean | undefined {
|
|
15
|
+
return testPlatform(/^iPhone/);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isSafari(): boolean | undefined {
|
|
19
|
+
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function isIPad(): boolean | undefined {
|
|
23
|
+
return (
|
|
24
|
+
testPlatform(/^iPad/) ||
|
|
25
|
+
// iPadOS 13 lies and says it's a Mac, but we can distinguish by detecting touch support.
|
|
26
|
+
(isMac() && navigator.maxTouchPoints > 1)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isIOS(): boolean | undefined {
|
|
31
|
+
return isIPhone() || isIPad();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function testPlatform(re: RegExp): boolean | undefined {
|
|
35
|
+
return typeof window !== 'undefined' && window.navigator != null
|
|
36
|
+
? re.test(window.navigator.platform)
|
|
37
|
+
: undefined;
|
|
38
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const TRANSITIONS = {
|
|
2
|
+
DURATION: 0.5,
|
|
3
|
+
EASE: [0.32, 0.72, 0, 1],
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export const VELOCITY_THRESHOLD = 0.4;
|
|
7
|
+
|
|
8
|
+
export const CLOSE_THRESHOLD = 0.25;
|
|
9
|
+
|
|
10
|
+
export const SCROLL_LOCK_TIMEOUT = 100;
|
|
11
|
+
|
|
12
|
+
export const BORDER_RADIUS = 8;
|
|
13
|
+
|
|
14
|
+
export const NESTED_DISPLACEMENT = 16;
|
|
15
|
+
|
|
16
|
+
export const WINDOW_TOP_OFFSET = 26;
|
|
17
|
+
|
|
18
|
+
export const DRAG_CLASS = 'vaul-dragging';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { DrawerDirection } from './types';
|
|
3
|
+
|
|
4
|
+
interface DrawerContextValue {
|
|
5
|
+
drawerRef: React.RefObject<HTMLDivElement | null>;
|
|
6
|
+
overlayRef: React.RefObject<HTMLDivElement | null>;
|
|
7
|
+
onPress: (event: React.PointerEvent<HTMLDivElement>) => void;
|
|
8
|
+
onRelease: (event: React.PointerEvent<HTMLDivElement> | null) => void;
|
|
9
|
+
onDrag: (event: React.PointerEvent<HTMLDivElement>) => void;
|
|
10
|
+
onNestedDrag: (event: React.PointerEvent<HTMLDivElement>, percentageDragged: number) => void;
|
|
11
|
+
onNestedOpenChange: (o: boolean) => void;
|
|
12
|
+
onNestedRelease: (event: React.PointerEvent<HTMLDivElement>, open: boolean) => void;
|
|
13
|
+
dismissible: boolean;
|
|
14
|
+
isOpen: boolean;
|
|
15
|
+
isDragging: boolean;
|
|
16
|
+
keyboardIsOpen: React.MutableRefObject<boolean>;
|
|
17
|
+
snapPointsOffset: number[] | null;
|
|
18
|
+
snapPoints?: (number | string)[] | null;
|
|
19
|
+
activeSnapPointIndex?: number | null;
|
|
20
|
+
fadeFromIndex?: number;
|
|
21
|
+
modal: boolean;
|
|
22
|
+
shouldFade: boolean;
|
|
23
|
+
activeSnapPoint?: number | string | null;
|
|
24
|
+
setActiveSnapPoint: (o: number | string | null) => void;
|
|
25
|
+
closeDrawer: () => void;
|
|
26
|
+
openProp?: boolean;
|
|
27
|
+
onOpenChange?: (o: boolean) => void;
|
|
28
|
+
direction: DrawerDirection;
|
|
29
|
+
shouldScaleBackground: boolean;
|
|
30
|
+
setBackgroundColorOnScale: boolean;
|
|
31
|
+
noBodyStyles: boolean;
|
|
32
|
+
handleOnly?: boolean;
|
|
33
|
+
container?: HTMLElement | null;
|
|
34
|
+
autoFocus?: boolean;
|
|
35
|
+
shouldAnimate?: React.RefObject<boolean>;
|
|
36
|
+
onPositionChangeRef: React.RefObject<((position: number) => void) | undefined>;
|
|
37
|
+
setContentHeight: (height: number) => void;
|
|
38
|
+
detached: boolean;
|
|
39
|
+
detachedOffset: number;
|
|
40
|
+
detachedRadius: number;
|
|
41
|
+
detachedWrapperStyle?: React.CSSProperties;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const DrawerContext = React.createContext<DrawerContextValue>({
|
|
45
|
+
drawerRef: { current: null },
|
|
46
|
+
overlayRef: { current: null },
|
|
47
|
+
onPress: () => {},
|
|
48
|
+
onRelease: () => {},
|
|
49
|
+
onDrag: () => {},
|
|
50
|
+
onNestedDrag: () => {},
|
|
51
|
+
onNestedOpenChange: () => {},
|
|
52
|
+
onNestedRelease: () => {},
|
|
53
|
+
openProp: undefined,
|
|
54
|
+
dismissible: false,
|
|
55
|
+
isOpen: false,
|
|
56
|
+
isDragging: false,
|
|
57
|
+
keyboardIsOpen: { current: false },
|
|
58
|
+
snapPointsOffset: null,
|
|
59
|
+
snapPoints: null,
|
|
60
|
+
handleOnly: false,
|
|
61
|
+
modal: false,
|
|
62
|
+
shouldFade: false,
|
|
63
|
+
activeSnapPoint: null,
|
|
64
|
+
onOpenChange: () => {},
|
|
65
|
+
setActiveSnapPoint: () => {},
|
|
66
|
+
closeDrawer: () => {},
|
|
67
|
+
direction: 'bottom',
|
|
68
|
+
shouldAnimate: { current: true },
|
|
69
|
+
shouldScaleBackground: false,
|
|
70
|
+
setBackgroundColorOnScale: true,
|
|
71
|
+
noBodyStyles: false,
|
|
72
|
+
container: null,
|
|
73
|
+
autoFocus: false,
|
|
74
|
+
onPositionChangeRef: { current: undefined },
|
|
75
|
+
setContentHeight: () => {},
|
|
76
|
+
detached: false,
|
|
77
|
+
detachedOffset: 0,
|
|
78
|
+
detachedRadius: 0,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export const useDrawerContext = () => {
|
|
82
|
+
const context = React.useContext(DrawerContext);
|
|
83
|
+
if (!context) {
|
|
84
|
+
throw new Error('useDrawerContext must be used within a Drawer.Root');
|
|
85
|
+
}
|
|
86
|
+
return context;
|
|
87
|
+
};
|