@pushframe/sdk 0.1.4 → 0.1.8
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/lib/commonjs/PushframeProvider.js +69 -0
- package/lib/commonjs/PushframeProvider.js.map +1 -0
- package/lib/commonjs/PushframeScreen.js +69 -0
- package/lib/commonjs/PushframeScreen.js.map +1 -0
- package/lib/commonjs/bindings.js +73 -0
- package/lib/commonjs/bindings.js.map +1 -0
- package/lib/commonjs/components/ButtonComponent.js +72 -0
- package/lib/commonjs/components/ButtonComponent.js.map +1 -0
- package/lib/commonjs/components/FlatListComponent.js +73 -0
- package/lib/commonjs/components/FlatListComponent.js.map +1 -0
- package/lib/commonjs/components/ImageComponent.js +67 -0
- package/lib/commonjs/components/ImageComponent.js.map +1 -0
- package/lib/commonjs/components/PushFrameComponent.js +179 -0
- package/lib/commonjs/components/PushFrameComponent.js.map +1 -0
- package/lib/commonjs/components/PushFrameProvider.js +115 -0
- package/lib/commonjs/components/PushFrameProvider.js.map +1 -0
- package/lib/commonjs/components/PushFrameScreen.js +39 -0
- package/lib/commonjs/components/PushFrameScreen.js.map +1 -0
- package/lib/commonjs/components/ScrollViewComponent.js +64 -0
- package/lib/commonjs/components/ScrollViewComponent.js.map +1 -0
- package/lib/commonjs/components/StackComponent.js +61 -0
- package/lib/commonjs/components/StackComponent.js.map +1 -0
- package/lib/commonjs/components/TextComponent.js +62 -0
- package/lib/commonjs/components/TextComponent.js.map +1 -0
- package/lib/commonjs/conditions.js +44 -0
- package/lib/commonjs/conditions.js.map +1 -0
- package/lib/commonjs/context/PushFrameContext.js +33 -0
- package/lib/commonjs/context/PushFrameContext.js.map +1 -0
- package/lib/commonjs/index.js +200 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/overlays/BottomSheetHost.js +144 -0
- package/lib/commonjs/overlays/BottomSheetHost.js.map +1 -0
- package/lib/commonjs/overlays/ToastHost.js +135 -0
- package/lib/commonjs/overlays/ToastHost.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/primitives/ActivityIndicator.js +24 -0
- package/lib/commonjs/primitives/ActivityIndicator.js.map +1 -0
- package/lib/commonjs/primitives/FlatList.js +34 -0
- package/lib/commonjs/primitives/FlatList.js.map +1 -0
- package/lib/commonjs/primitives/Image.js +33 -0
- package/lib/commonjs/primitives/Image.js.map +1 -0
- package/lib/commonjs/primitives/KeyboardAvoidingView.js +24 -0
- package/lib/commonjs/primitives/KeyboardAvoidingView.js.map +1 -0
- package/lib/commonjs/primitives/Modal.js +24 -0
- package/lib/commonjs/primitives/Modal.js.map +1 -0
- package/lib/commonjs/primitives/Pressable.js +26 -0
- package/lib/commonjs/primitives/Pressable.js.map +1 -0
- package/lib/commonjs/primitives/SafeAreaView.js +38 -0
- package/lib/commonjs/primitives/SafeAreaView.js.map +1 -0
- package/lib/commonjs/primitives/ScrollView.js +26 -0
- package/lib/commonjs/primitives/ScrollView.js.map +1 -0
- package/lib/commonjs/primitives/StatusBar.js +24 -0
- package/lib/commonjs/primitives/StatusBar.js.map +1 -0
- package/lib/commonjs/primitives/Switch.js +28 -0
- package/lib/commonjs/primitives/Switch.js.map +1 -0
- package/lib/commonjs/primitives/Text.js +37 -0
- package/lib/commonjs/primitives/Text.js.map +1 -0
- package/lib/commonjs/primitives/TextInput.js +31 -0
- package/lib/commonjs/primitives/TextInput.js.map +1 -0
- package/lib/commonjs/primitives/View.js +24 -0
- package/lib/commonjs/primitives/View.js.map +1 -0
- package/lib/commonjs/primitives/index.js +97 -0
- package/lib/commonjs/primitives/index.js.map +1 -0
- package/lib/commonjs/registry/ComponentRegistry.js +70 -0
- package/lib/commonjs/registry/ComponentRegistry.js.map +1 -0
- package/lib/commonjs/registry.js +94 -0
- package/lib/commonjs/registry.js.map +1 -0
- package/lib/commonjs/renderer/RecursiveRenderer.js +202 -0
- package/lib/commonjs/renderer/RecursiveRenderer.js.map +1 -0
- package/lib/commonjs/renderer/bindingResolver.js +98 -0
- package/lib/commonjs/renderer/bindingResolver.js.map +1 -0
- package/lib/commonjs/renderer/conditionalEvaluator.js +31 -0
- package/lib/commonjs/renderer/conditionalEvaluator.js.map +1 -0
- package/lib/commonjs/renderer.js +107 -0
- package/lib/commonjs/renderer.js.map +1 -0
- package/lib/commonjs/schema.js +79 -0
- package/lib/commonjs/schema.js.map +1 -0
- package/lib/commonjs/transformer/index.js +1055 -0
- package/lib/commonjs/transformer/index.js.map +1 -0
- package/lib/commonjs/transport.js +86 -0
- package/lib/commonjs/transport.js.map +1 -0
- package/lib/module/PushframeProvider.js +62 -0
- package/lib/module/PushframeProvider.js.map +1 -0
- package/lib/module/PushframeScreen.js +65 -0
- package/lib/module/PushframeScreen.js.map +1 -0
- package/lib/module/bindings.js +68 -0
- package/lib/module/bindings.js.map +1 -0
- package/lib/module/components/ButtonComponent.js +67 -0
- package/lib/module/components/ButtonComponent.js.map +1 -0
- package/lib/module/components/FlatListComponent.js +68 -0
- package/lib/module/components/FlatListComponent.js.map +1 -0
- package/lib/module/components/ImageComponent.js +62 -0
- package/lib/module/components/ImageComponent.js.map +1 -0
- package/lib/module/components/PushFrameComponent.js +174 -0
- package/lib/module/components/PushFrameComponent.js.map +1 -0
- package/lib/module/components/PushFrameProvider.js +110 -0
- package/lib/module/components/PushFrameProvider.js.map +1 -0
- package/lib/module/components/PushFrameScreen.js +34 -0
- package/lib/module/components/PushFrameScreen.js.map +1 -0
- package/lib/module/components/ScrollViewComponent.js +59 -0
- package/lib/module/components/ScrollViewComponent.js.map +1 -0
- package/lib/module/components/StackComponent.js +56 -0
- package/lib/module/components/StackComponent.js.map +1 -0
- package/lib/module/components/TextComponent.js +57 -0
- package/lib/module/components/TextComponent.js.map +1 -0
- package/lib/module/conditions.js +40 -0
- package/lib/module/conditions.js.map +1 -0
- package/lib/module/context/PushFrameContext.js +29 -0
- package/lib/module/context/PushFrameContext.js.map +1 -0
- package/lib/module/index.js +99 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/overlays/BottomSheetHost.js +139 -0
- package/lib/module/overlays/BottomSheetHost.js.map +1 -0
- package/lib/module/overlays/ToastHost.js +130 -0
- package/lib/module/overlays/ToastHost.js.map +1 -0
- package/lib/module/primitives/ActivityIndicator.js +19 -0
- package/lib/module/primitives/ActivityIndicator.js.map +1 -0
- package/lib/module/primitives/FlatList.js +29 -0
- package/lib/module/primitives/FlatList.js.map +1 -0
- package/lib/module/primitives/Image.js +28 -0
- package/lib/module/primitives/Image.js.map +1 -0
- package/lib/module/primitives/KeyboardAvoidingView.js +19 -0
- package/lib/module/primitives/KeyboardAvoidingView.js.map +1 -0
- package/lib/module/primitives/Modal.js +19 -0
- package/lib/module/primitives/Modal.js.map +1 -0
- package/lib/module/primitives/Pressable.js +21 -0
- package/lib/module/primitives/Pressable.js.map +1 -0
- package/lib/module/primitives/SafeAreaView.js +33 -0
- package/lib/module/primitives/SafeAreaView.js.map +1 -0
- package/lib/module/primitives/ScrollView.js +21 -0
- package/lib/module/primitives/ScrollView.js.map +1 -0
- package/lib/module/primitives/StatusBar.js +19 -0
- package/lib/module/primitives/StatusBar.js.map +1 -0
- package/lib/module/primitives/Switch.js +23 -0
- package/lib/module/primitives/Switch.js.map +1 -0
- package/lib/module/primitives/Text.js +32 -0
- package/lib/module/primitives/Text.js.map +1 -0
- package/lib/module/primitives/TextInput.js +26 -0
- package/lib/module/primitives/TextInput.js.map +1 -0
- package/lib/module/primitives/View.js +19 -0
- package/lib/module/primitives/View.js.map +1 -0
- package/lib/module/primitives/index.js +16 -0
- package/lib/module/primitives/index.js.map +1 -0
- package/lib/module/registry/ComponentRegistry.js +66 -0
- package/lib/module/registry/ComponentRegistry.js.map +1 -0
- package/lib/module/registry.js +88 -0
- package/lib/module/registry.js.map +1 -0
- package/lib/module/renderer/RecursiveRenderer.js +197 -0
- package/lib/module/renderer/RecursiveRenderer.js.map +1 -0
- package/lib/module/renderer/bindingResolver.js +92 -0
- package/lib/module/renderer/bindingResolver.js.map +1 -0
- package/lib/module/renderer/conditionalEvaluator.js +28 -0
- package/lib/module/renderer/conditionalEvaluator.js.map +1 -0
- package/lib/module/renderer.js +103 -0
- package/lib/module/renderer.js.map +1 -0
- package/lib/module/schema.js +74 -0
- package/lib/module/schema.js.map +1 -0
- package/lib/module/transformer/index.js +1051 -0
- package/lib/module/transformer/index.js.map +1 -0
- package/lib/module/transport.js +82 -0
- package/lib/module/transport.js.map +1 -0
- package/lib/typescript/PushframeProvider.d.ts +58 -0
- package/lib/typescript/PushframeProvider.d.ts.map +1 -0
- package/lib/typescript/PushframeScreen.d.ts +36 -0
- package/lib/typescript/PushframeScreen.d.ts.map +1 -0
- package/lib/typescript/bindings.d.ts +29 -0
- package/lib/typescript/bindings.d.ts.map +1 -0
- package/lib/typescript/components/ButtonComponent.d.ts +11 -0
- package/lib/typescript/components/ButtonComponent.d.ts.map +1 -0
- package/lib/typescript/components/FlatListComponent.d.ts +28 -0
- package/lib/typescript/components/FlatListComponent.d.ts.map +1 -0
- package/lib/typescript/components/ImageComponent.d.ts +12 -0
- package/lib/typescript/components/ImageComponent.d.ts.map +1 -0
- package/lib/typescript/components/PushFrameComponent.d.ts +48 -0
- package/lib/typescript/components/PushFrameComponent.d.ts.map +1 -0
- package/lib/typescript/components/PushFrameProvider.d.ts +51 -0
- package/lib/typescript/components/PushFrameProvider.d.ts.map +1 -0
- package/lib/typescript/components/PushFrameScreen.d.ts +15 -0
- package/lib/typescript/components/PushFrameScreen.d.ts.map +1 -0
- package/lib/typescript/components/ScrollViewComponent.d.ts +19 -0
- package/lib/typescript/components/ScrollViewComponent.d.ts.map +1 -0
- package/lib/typescript/components/StackComponent.d.ts +16 -0
- package/lib/typescript/components/StackComponent.d.ts.map +1 -0
- package/lib/typescript/components/TextComponent.d.ts +13 -0
- package/lib/typescript/components/TextComponent.d.ts.map +1 -0
- package/lib/typescript/conditions.d.ts +12 -0
- package/lib/typescript/conditions.d.ts.map +1 -0
- package/lib/typescript/context/PushFrameContext.d.ts +57 -0
- package/lib/typescript/context/PushFrameContext.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +74 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/overlays/BottomSheetHost.d.ts +21 -0
- package/lib/typescript/overlays/BottomSheetHost.d.ts.map +1 -0
- package/lib/typescript/overlays/ToastHost.d.ts +12 -0
- package/lib/typescript/overlays/ToastHost.d.ts.map +1 -0
- package/lib/typescript/primitives/ActivityIndicator.d.ts +12 -0
- package/lib/typescript/primitives/ActivityIndicator.d.ts.map +1 -0
- package/lib/typescript/primitives/FlatList.d.ts +29 -0
- package/lib/typescript/primitives/FlatList.d.ts.map +1 -0
- package/lib/typescript/primitives/Image.d.ts +20 -0
- package/lib/typescript/primitives/Image.d.ts.map +1 -0
- package/lib/typescript/primitives/KeyboardAvoidingView.d.ts +12 -0
- package/lib/typescript/primitives/KeyboardAvoidingView.d.ts.map +1 -0
- package/lib/typescript/primitives/Modal.d.ts +12 -0
- package/lib/typescript/primitives/Modal.d.ts.map +1 -0
- package/lib/typescript/primitives/Pressable.d.ts +14 -0
- package/lib/typescript/primitives/Pressable.d.ts.map +1 -0
- package/lib/typescript/primitives/SafeAreaView.d.ts +20 -0
- package/lib/typescript/primitives/SafeAreaView.d.ts.map +1 -0
- package/lib/typescript/primitives/ScrollView.d.ts +15 -0
- package/lib/typescript/primitives/ScrollView.d.ts.map +1 -0
- package/lib/typescript/primitives/StatusBar.d.ts +12 -0
- package/lib/typescript/primitives/StatusBar.d.ts.map +1 -0
- package/lib/typescript/primitives/Switch.d.ts +19 -0
- package/lib/typescript/primitives/Switch.d.ts.map +1 -0
- package/lib/typescript/primitives/Text.d.ts +25 -0
- package/lib/typescript/primitives/Text.d.ts.map +1 -0
- package/lib/typescript/primitives/TextInput.d.ts +25 -0
- package/lib/typescript/primitives/TextInput.d.ts.map +1 -0
- package/lib/typescript/primitives/View.d.ts +12 -0
- package/lib/typescript/primitives/View.d.ts.map +1 -0
- package/lib/typescript/primitives/index.d.ts +27 -0
- package/lib/typescript/primitives/index.d.ts.map +1 -0
- package/lib/typescript/registry/ComponentRegistry.d.ts +21 -0
- package/lib/typescript/registry/ComponentRegistry.d.ts.map +1 -0
- package/lib/typescript/registry.d.ts +57 -0
- package/lib/typescript/registry.d.ts.map +1 -0
- package/lib/typescript/renderer/RecursiveRenderer.d.ts +32 -0
- package/lib/typescript/renderer/RecursiveRenderer.d.ts.map +1 -0
- package/lib/typescript/renderer/bindingResolver.d.ts +26 -0
- package/lib/typescript/renderer/bindingResolver.d.ts.map +1 -0
- package/lib/typescript/renderer/conditionalEvaluator.d.ts +15 -0
- package/lib/typescript/renderer/conditionalEvaluator.d.ts.map +1 -0
- package/lib/typescript/renderer.d.ts +29 -0
- package/lib/typescript/renderer.d.ts.map +1 -0
- package/lib/typescript/schema.d.ts +84 -0
- package/lib/typescript/schema.d.ts.map +1 -0
- package/lib/typescript/transformer/index.d.ts +49 -0
- package/lib/typescript/transformer/index.d.ts.map +1 -0
- package/lib/typescript/transport.d.ts +19 -0
- package/lib/typescript/transport.d.ts.map +1 -0
- package/package.json +20 -18
- package/src/PushframeProvider.tsx +119 -0
- package/src/PushframeScreen.tsx +107 -0
- package/src/bindings.ts +72 -0
- package/src/components/ButtonComponent.tsx +87 -0
- package/src/components/FlatListComponent.tsx +86 -0
- package/src/components/ImageComponent.tsx +70 -0
- package/src/components/PushFrameComponent.tsx +221 -0
- package/src/components/PushFrameProvider.tsx +177 -0
- package/src/components/PushFrameScreen.tsx +30 -0
- package/src/components/ScrollViewComponent.tsx +65 -0
- package/src/components/StackComponent.tsx +69 -0
- package/src/components/TextComponent.tsx +60 -0
- package/src/conditions.ts +46 -0
- package/src/context/PushFrameContext.ts +89 -0
- package/src/index.ts +119 -0
- package/src/overlays/BottomSheetHost.tsx +175 -0
- package/src/overlays/ToastHost.tsx +147 -0
- package/src/primitives/ActivityIndicator.tsx +21 -0
- package/src/primitives/FlatList.tsx +49 -0
- package/src/primitives/Image.tsx +26 -0
- package/src/primitives/KeyboardAvoidingView.tsx +21 -0
- package/src/primitives/Modal.tsx +17 -0
- package/src/primitives/Pressable.tsx +19 -0
- package/src/primitives/SafeAreaView.tsx +42 -0
- package/src/primitives/ScrollView.tsx +21 -0
- package/src/primitives/StatusBar.tsx +17 -0
- package/src/primitives/Switch.tsx +24 -0
- package/src/primitives/Text.tsx +43 -0
- package/src/primitives/TextInput.tsx +42 -0
- package/src/primitives/View.tsx +17 -0
- package/src/primitives/index.ts +38 -0
- package/src/registry/ComponentRegistry.ts +99 -0
- package/src/registry.ts +99 -0
- package/src/renderer/RecursiveRenderer.tsx +242 -0
- package/src/renderer/bindingResolver.ts +94 -0
- package/src/renderer/conditionalEvaluator.ts +29 -0
- package/src/renderer.tsx +124 -0
- package/src/schema.ts +132 -0
- package/src/transformer/index.ts +1016 -0
- package/src/transport.ts +104 -0
- package/dist/index.d.mts +0 -534
- package/dist/index.d.ts +0 -534
- package/dist/index.js +0 -1572
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -1541
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useImperativeHandle,
|
|
4
|
+
useState,
|
|
5
|
+
useEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
useCallback,
|
|
8
|
+
} from 'react';
|
|
9
|
+
import { View, Text, StyleSheet, Animated } from 'react-native';
|
|
10
|
+
import type { ToastPayload } from '../context/PushFrameContext';
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Imperative handle
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
export interface ToastHostHandle {
|
|
17
|
+
show(payload: ToastPayload): void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Internal state
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
interface ToastState {
|
|
25
|
+
id: number;
|
|
26
|
+
message: string;
|
|
27
|
+
duration: number;
|
|
28
|
+
type: ToastPayload['type'];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Style helpers
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
const TYPE_COLORS: Record<NonNullable<ToastPayload['type']>, string> = {
|
|
36
|
+
success: '#22c55e',
|
|
37
|
+
error: '#ef4444',
|
|
38
|
+
info: '#3b82f6',
|
|
39
|
+
warning: '#f59e0b',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// ToastHost
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Rendered by PushFrameProvider at the root level.
|
|
48
|
+
* Exposes an imperative `show()` handle for displaying toast messages.
|
|
49
|
+
* Zero third-party dependencies — built with Animated API.
|
|
50
|
+
*/
|
|
51
|
+
export const ToastHost = forwardRef<ToastHostHandle>(function ToastHost(_props, ref) {
|
|
52
|
+
const [toast, setToast] = useState<ToastState | null>(null);
|
|
53
|
+
const opacity = useRef(new Animated.Value(0)).current;
|
|
54
|
+
const idRef = useRef(0);
|
|
55
|
+
|
|
56
|
+
const hide = useCallback(() => {
|
|
57
|
+
Animated.timing(opacity, {
|
|
58
|
+
toValue: 0,
|
|
59
|
+
duration: 200,
|
|
60
|
+
useNativeDriver: true,
|
|
61
|
+
}).start(() => {
|
|
62
|
+
setToast(null);
|
|
63
|
+
});
|
|
64
|
+
}, [opacity]);
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!toast) return;
|
|
68
|
+
|
|
69
|
+
// Fade in
|
|
70
|
+
Animated.timing(opacity, {
|
|
71
|
+
toValue: 1,
|
|
72
|
+
duration: 200,
|
|
73
|
+
useNativeDriver: true,
|
|
74
|
+
}).start();
|
|
75
|
+
|
|
76
|
+
// Auto-dismiss after duration
|
|
77
|
+
const timer = setTimeout(() => {
|
|
78
|
+
hide();
|
|
79
|
+
}, toast.duration);
|
|
80
|
+
|
|
81
|
+
return () => {
|
|
82
|
+
clearTimeout(timer);
|
|
83
|
+
};
|
|
84
|
+
}, [toast, opacity, hide]);
|
|
85
|
+
|
|
86
|
+
useImperativeHandle(
|
|
87
|
+
ref,
|
|
88
|
+
() => ({
|
|
89
|
+
show(payload: ToastPayload) {
|
|
90
|
+
idRef.current += 1;
|
|
91
|
+
setToast({
|
|
92
|
+
id: idRef.current,
|
|
93
|
+
message: payload.message,
|
|
94
|
+
duration: payload.duration ?? 3000,
|
|
95
|
+
type: payload.type ?? 'info',
|
|
96
|
+
});
|
|
97
|
+
// Reset opacity for new toast
|
|
98
|
+
opacity.setValue(0);
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
[opacity],
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
if (!toast) return null;
|
|
105
|
+
|
|
106
|
+
const backgroundColor = TYPE_COLORS[toast.type ?? 'info'] ?? TYPE_COLORS.info;
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<View style={styles.container} pointerEvents="none">
|
|
110
|
+
<Animated.View style={[styles.toast, { backgroundColor, opacity }]}>
|
|
111
|
+
<Text style={styles.message}>{toast.message}</Text>
|
|
112
|
+
</Animated.View>
|
|
113
|
+
</View>
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Styles
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
const styles = StyleSheet.create({
|
|
122
|
+
container: {
|
|
123
|
+
position: 'absolute',
|
|
124
|
+
bottom: 60,
|
|
125
|
+
left: 16,
|
|
126
|
+
right: 16,
|
|
127
|
+
alignItems: 'center',
|
|
128
|
+
zIndex: 9999,
|
|
129
|
+
},
|
|
130
|
+
toast: {
|
|
131
|
+
paddingVertical: 12,
|
|
132
|
+
paddingHorizontal: 20,
|
|
133
|
+
borderRadius: 8,
|
|
134
|
+
maxWidth: 400,
|
|
135
|
+
shadowColor: '#000',
|
|
136
|
+
shadowOffset: { width: 0, height: 2 },
|
|
137
|
+
shadowOpacity: 0.2,
|
|
138
|
+
shadowRadius: 4,
|
|
139
|
+
elevation: 6,
|
|
140
|
+
},
|
|
141
|
+
message: {
|
|
142
|
+
color: '#fff',
|
|
143
|
+
fontSize: 14,
|
|
144
|
+
fontWeight: '500',
|
|
145
|
+
textAlign: 'center',
|
|
146
|
+
},
|
|
147
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ActivityIndicator as RNActivityIndicator } from 'react-native';
|
|
3
|
+
import type { ActivityIndicatorProps as RNActivityIndicatorProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameActivityIndicatorProps extends RNActivityIndicatorProps {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper over React Native ActivityIndicator.
|
|
13
|
+
* Strips `if`, `actions` before forwarding to RN.
|
|
14
|
+
*/
|
|
15
|
+
export function ActivityIndicator({
|
|
16
|
+
if: _if,
|
|
17
|
+
actions: _actions,
|
|
18
|
+
...rest
|
|
19
|
+
}: PushFrameActivityIndicatorProps) {
|
|
20
|
+
return <RNActivityIndicator {...rest} />;
|
|
21
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FlatList as RNFlatList } from 'react-native';
|
|
3
|
+
import type { FlatListProps as RNFlatListProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameFlatListProps<T = unknown>
|
|
7
|
+
extends Omit<RNFlatListProps<T>, 'data' | 'horizontal'> {
|
|
8
|
+
if?: string;
|
|
9
|
+
actions?: Action[];
|
|
10
|
+
/**
|
|
11
|
+
* Resolved array of items. Populated by RecursiveRenderer from the
|
|
12
|
+
* `items` binding expression on the schema node.
|
|
13
|
+
*/
|
|
14
|
+
items?: T[];
|
|
15
|
+
/**
|
|
16
|
+
* "vertical" (default) or "horizontal". Maps to RN `horizontal` boolean.
|
|
17
|
+
*/
|
|
18
|
+
direction?: 'vertical' | 'horizontal';
|
|
19
|
+
/**
|
|
20
|
+
* Number of columns for grid layouts. Forwarded directly to RN FlatList.
|
|
21
|
+
*/
|
|
22
|
+
numColumns?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Thin wrapper over React Native FlatList.
|
|
27
|
+
* RecursiveRenderer handles this type specially — it resolves `items` from
|
|
28
|
+
* a binding expression and constructs the `renderItem` per-item context.
|
|
29
|
+
*
|
|
30
|
+
* This component maps Pushframe props to RN FlatList props and strips
|
|
31
|
+
* Pushframe-specific props before forwarding.
|
|
32
|
+
*/
|
|
33
|
+
export function FlatList<T = unknown>({
|
|
34
|
+
if: _if,
|
|
35
|
+
actions: _actions,
|
|
36
|
+
items,
|
|
37
|
+
direction,
|
|
38
|
+
numColumns,
|
|
39
|
+
...rest
|
|
40
|
+
}: PushFrameFlatListProps<T>) {
|
|
41
|
+
return (
|
|
42
|
+
<RNFlatList<T>
|
|
43
|
+
data={items}
|
|
44
|
+
horizontal={direction === 'horizontal'}
|
|
45
|
+
numColumns={numColumns}
|
|
46
|
+
{...rest}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Image as RNImage } from 'react-native';
|
|
3
|
+
import type { ImageProps as RNImageProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameImageProps extends Omit<RNImageProps, 'source'> {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
/**
|
|
10
|
+
* URI string for the image source. Maps to RN `source={{ uri: src }}`.
|
|
11
|
+
* Takes precedence over the base `source` prop.
|
|
12
|
+
*/
|
|
13
|
+
src?: string;
|
|
14
|
+
/** Pass-through for cases where a static require() source is needed. */
|
|
15
|
+
source?: RNImageProps['source'];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Thin wrapper over React Native Image.
|
|
20
|
+
* `src` maps to `source={{ uri: src }}`.
|
|
21
|
+
* Strips `if`, `actions`, `src` before forwarding to RN.
|
|
22
|
+
*/
|
|
23
|
+
export function Image({ if: _if, actions: _actions, src, source, ...rest }: PushFrameImageProps) {
|
|
24
|
+
const resolvedSource = src ? { uri: src } : source ?? { uri: '' };
|
|
25
|
+
return <RNImage source={resolvedSource} {...rest} />;
|
|
26
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { KeyboardAvoidingView as RNKeyboardAvoidingView } from 'react-native';
|
|
3
|
+
import type { KeyboardAvoidingViewProps as RNKeyboardAvoidingViewProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameKeyboardAvoidingViewProps extends RNKeyboardAvoidingViewProps {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper over React Native KeyboardAvoidingView.
|
|
13
|
+
* Strips `if`, `actions` before forwarding to RN.
|
|
14
|
+
*/
|
|
15
|
+
export function KeyboardAvoidingView({
|
|
16
|
+
if: _if,
|
|
17
|
+
actions: _actions,
|
|
18
|
+
...rest
|
|
19
|
+
}: PushFrameKeyboardAvoidingViewProps) {
|
|
20
|
+
return <RNKeyboardAvoidingView {...rest} />;
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Modal as RNModal } from 'react-native';
|
|
3
|
+
import type { ModalProps as RNModalProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameModalProps extends RNModalProps {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper over React Native Modal.
|
|
13
|
+
* Strips `if`, `actions` before forwarding to RN.
|
|
14
|
+
*/
|
|
15
|
+
export function Modal({ if: _if, actions: _actions, ...rest }: PushFrameModalProps) {
|
|
16
|
+
return <RNModal {...rest} />;
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Pressable as RNPressable } from 'react-native';
|
|
3
|
+
import type { PressableProps as RNPressableProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFramePressableProps extends RNPressableProps {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper over React Native Pressable.
|
|
13
|
+
* Actions with trigger "onPress" and "onLongPress" are wired by RecursiveRenderer
|
|
14
|
+
* and forwarded through as standard RN props.
|
|
15
|
+
* Strips `if`, `actions` before forwarding to RN.
|
|
16
|
+
*/
|
|
17
|
+
export function Pressable({ if: _if, actions: _actions, ...rest }: PushFramePressableProps) {
|
|
18
|
+
return <RNPressable {...rest} />;
|
|
19
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import type { Action } from '../context/PushFrameContext';
|
|
4
|
+
|
|
5
|
+
export interface PushFrameSafeAreaViewProps extends ViewProps {
|
|
6
|
+
if?: string;
|
|
7
|
+
actions?: Action[];
|
|
8
|
+
/**
|
|
9
|
+
* Edges to apply safe-area insets on.
|
|
10
|
+
* Forwarded to react-native-safe-area-context's SafeAreaView when available.
|
|
11
|
+
* Example: ['top', 'bottom']
|
|
12
|
+
*/
|
|
13
|
+
edges?: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Prefer react-native-safe-area-context (standard Expo dependency) when available;
|
|
17
|
+
// fall back to RN core SafeAreaView otherwise.
|
|
18
|
+
// Both are typed to accept `edges` so the prop flows through without stripping;
|
|
19
|
+
// the RN core fallback will silently ignore the unknown prop at runtime.
|
|
20
|
+
let NativeSafeAreaView: React.ComponentType<ViewProps & { edges?: string[] }>;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
24
|
+
NativeSafeAreaView = (require('react-native-safe-area-context') as {
|
|
25
|
+
SafeAreaView: React.ComponentType<ViewProps & { edges?: string[] }>;
|
|
26
|
+
}).SafeAreaView;
|
|
27
|
+
} catch {
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
29
|
+
NativeSafeAreaView = (require('react-native') as {
|
|
30
|
+
SafeAreaView: React.ComponentType<ViewProps & { edges?: string[] }>;
|
|
31
|
+
}).SafeAreaView;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Thin wrapper over SafeAreaView.
|
|
36
|
+
* Uses react-native-safe-area-context when available, RN core otherwise.
|
|
37
|
+
* Strips `if`, `actions` before forwarding; passes `edges` through to
|
|
38
|
+
* react-native-safe-area-context (ignored gracefully in the RN core fallback).
|
|
39
|
+
*/
|
|
40
|
+
export function SafeAreaView({ if: _if, actions: _actions, ...rest }: PushFrameSafeAreaViewProps) {
|
|
41
|
+
return <NativeSafeAreaView {...rest} />;
|
|
42
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { ScrollView as RNScrollView } from 'react-native';
|
|
3
|
+
import type { ScrollViewProps as RNScrollViewProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameScrollViewProps extends RNScrollViewProps {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper over React Native ScrollView.
|
|
13
|
+
* Forwards ref to support programmatic scrolling (e.g. scroll-to action).
|
|
14
|
+
* Strips `if`, `actions` before forwarding to RN.
|
|
15
|
+
*/
|
|
16
|
+
export const ScrollView = forwardRef<RNScrollView, PushFrameScrollViewProps>(function ScrollView(
|
|
17
|
+
{ if: _if, actions: _actions, ...rest },
|
|
18
|
+
ref,
|
|
19
|
+
) {
|
|
20
|
+
return <RNScrollView ref={ref} {...rest} />;
|
|
21
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StatusBar as RNStatusBar } from 'react-native';
|
|
3
|
+
import type { StatusBarProps as RNStatusBarProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameStatusBarProps extends RNStatusBarProps {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper over React Native StatusBar.
|
|
13
|
+
* Strips `if`, `actions` before forwarding to RN.
|
|
14
|
+
*/
|
|
15
|
+
export function StatusBar({ if: _if, actions: _actions, ...rest }: PushFrameStatusBarProps) {
|
|
16
|
+
return <RNStatusBar {...rest} />;
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Switch as RNSwitch } from 'react-native';
|
|
3
|
+
import type { SwitchProps as RNSwitchProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameSwitchProps extends Omit<RNSwitchProps, 'onValueChange' | 'onChange'> {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
/**
|
|
10
|
+
* Schema trigger "onChange" — wired by RecursiveRenderer.
|
|
11
|
+
* Mapped to RN `onValueChange` by this component.
|
|
12
|
+
*/
|
|
13
|
+
onChange?: (value: boolean) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Thin wrapper over React Native Switch.
|
|
18
|
+
* Maps Pushframe schema trigger to RN event prop:
|
|
19
|
+
* onChange → onValueChange
|
|
20
|
+
* Strips `if`, `actions`, `onChange` before forwarding to RN.
|
|
21
|
+
*/
|
|
22
|
+
export function Switch({ if: _if, actions: _actions, onChange, ...rest }: PushFrameSwitchProps) {
|
|
23
|
+
return <RNSwitch onValueChange={onChange} {...rest} />;
|
|
24
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text as RNText } from 'react-native';
|
|
3
|
+
import type { TextProps as RNTextProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameTextProps extends RNTextProps {
|
|
7
|
+
/** Pushframe: hidden by RecursiveRenderer before component renders. */
|
|
8
|
+
if?: string;
|
|
9
|
+
/** Pushframe: converted to handlers by RecursiveRenderer before component renders. */
|
|
10
|
+
actions?: Action[];
|
|
11
|
+
/**
|
|
12
|
+
* Text content. Takes precedence over `children`.
|
|
13
|
+
* Pushframe schema convention: use `value`.
|
|
14
|
+
*/
|
|
15
|
+
value?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Alias for `value`. The transformer outputs the Craft editor's `content`
|
|
18
|
+
* field here. `value` takes precedence when both are present.
|
|
19
|
+
*/
|
|
20
|
+
content?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Thin wrapper over React Native Text.
|
|
25
|
+
* Strips `if`, `actions`, `content` before forwarding to RN.
|
|
26
|
+
* Display priority: value > content > children (children remain in rest).
|
|
27
|
+
*/
|
|
28
|
+
export function Text({
|
|
29
|
+
if: _if,
|
|
30
|
+
actions: _actions,
|
|
31
|
+
value,
|
|
32
|
+
content,
|
|
33
|
+
...rest
|
|
34
|
+
}: PushFrameTextProps) {
|
|
35
|
+
// When value or content is provided it takes precedence over JSX children
|
|
36
|
+
// (which are part of rest via RNTextProps inheritance).
|
|
37
|
+
const textContent = value !== undefined ? value : content;
|
|
38
|
+
if (textContent !== undefined) {
|
|
39
|
+
return <RNText {...rest}>{textContent}</RNText>;
|
|
40
|
+
}
|
|
41
|
+
// No explicit text content — forward rest as-is (includes any children prop)
|
|
42
|
+
return <RNText {...rest} />;
|
|
43
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TextInput as RNTextInput } from 'react-native';
|
|
3
|
+
import type { TextInputProps as RNTextInputProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameTextInputProps extends Omit<RNTextInputProps, 'onChange'> {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
/**
|
|
10
|
+
* Schema trigger "onChange" — wired by RecursiveRenderer.
|
|
11
|
+
* Mapped to RN `onChangeText` by this component.
|
|
12
|
+
*/
|
|
13
|
+
onChange?: (text: string) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Schema trigger "onSubmit" — wired by RecursiveRenderer.
|
|
16
|
+
* Mapped to RN `onSubmitEditing` by this component.
|
|
17
|
+
*/
|
|
18
|
+
onSubmit?: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Thin wrapper over React Native TextInput.
|
|
23
|
+
* Maps Pushframe schema triggers to RN event props:
|
|
24
|
+
* onChange → onChangeText
|
|
25
|
+
* onSubmit → onSubmitEditing
|
|
26
|
+
* Strips `if`, `actions`, `onChange`, `onSubmit` before forwarding to RN.
|
|
27
|
+
*/
|
|
28
|
+
export function TextInput({
|
|
29
|
+
if: _if,
|
|
30
|
+
actions: _actions,
|
|
31
|
+
onChange,
|
|
32
|
+
onSubmit,
|
|
33
|
+
...rest
|
|
34
|
+
}: PushFrameTextInputProps) {
|
|
35
|
+
return (
|
|
36
|
+
<RNTextInput
|
|
37
|
+
onChangeText={onChange}
|
|
38
|
+
onSubmitEditing={onSubmit ? () => onSubmit() : undefined}
|
|
39
|
+
{...rest}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View as RNView } from 'react-native';
|
|
3
|
+
import type { ViewProps as RNViewProps } from 'react-native';
|
|
4
|
+
import type { Action } from '../context/PushFrameContext';
|
|
5
|
+
|
|
6
|
+
export interface PushFrameViewProps extends RNViewProps {
|
|
7
|
+
if?: string;
|
|
8
|
+
actions?: Action[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper over React Native View.
|
|
13
|
+
* Strips `if`, `actions` before forwarding to RN.
|
|
14
|
+
*/
|
|
15
|
+
export function View({ if: _if, actions: _actions, ...rest }: PushFrameViewProps) {
|
|
16
|
+
return <RNView {...rest} />;
|
|
17
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export { Text } from './Text';
|
|
2
|
+
export type { PushFrameTextProps } from './Text';
|
|
3
|
+
|
|
4
|
+
export { View } from './View';
|
|
5
|
+
export type { PushFrameViewProps } from './View';
|
|
6
|
+
|
|
7
|
+
export { ScrollView } from './ScrollView';
|
|
8
|
+
export type { PushFrameScrollViewProps } from './ScrollView';
|
|
9
|
+
|
|
10
|
+
export { Image } from './Image';
|
|
11
|
+
export type { PushFrameImageProps } from './Image';
|
|
12
|
+
|
|
13
|
+
export { Pressable } from './Pressable';
|
|
14
|
+
export type { PushFramePressableProps } from './Pressable';
|
|
15
|
+
|
|
16
|
+
export { TextInput } from './TextInput';
|
|
17
|
+
export type { PushFrameTextInputProps } from './TextInput';
|
|
18
|
+
|
|
19
|
+
export { FlatList } from './FlatList';
|
|
20
|
+
export type { PushFrameFlatListProps } from './FlatList';
|
|
21
|
+
|
|
22
|
+
export { Modal } from './Modal';
|
|
23
|
+
export type { PushFrameModalProps } from './Modal';
|
|
24
|
+
|
|
25
|
+
export { ActivityIndicator } from './ActivityIndicator';
|
|
26
|
+
export type { PushFrameActivityIndicatorProps } from './ActivityIndicator';
|
|
27
|
+
|
|
28
|
+
export { Switch } from './Switch';
|
|
29
|
+
export type { PushFrameSwitchProps } from './Switch';
|
|
30
|
+
|
|
31
|
+
export { KeyboardAvoidingView } from './KeyboardAvoidingView';
|
|
32
|
+
export type { PushFrameKeyboardAvoidingViewProps } from './KeyboardAvoidingView';
|
|
33
|
+
|
|
34
|
+
export { SafeAreaView } from './SafeAreaView';
|
|
35
|
+
export type { PushFrameSafeAreaViewProps } from './SafeAreaView';
|
|
36
|
+
|
|
37
|
+
export { StatusBar } from './StatusBar';
|
|
38
|
+
export type { PushFrameStatusBarProps } from './StatusBar';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { Text } from '../primitives/Text';
|
|
3
|
+
import { View } from '../primitives/View';
|
|
4
|
+
import { ScrollView } from '../primitives/ScrollView';
|
|
5
|
+
import { Image } from '../primitives/Image';
|
|
6
|
+
import { Pressable } from '../primitives/Pressable';
|
|
7
|
+
import { TextInput } from '../primitives/TextInput';
|
|
8
|
+
import { FlatList } from '../primitives/FlatList';
|
|
9
|
+
import { Modal } from '../primitives/Modal';
|
|
10
|
+
import { ActivityIndicator } from '../primitives/ActivityIndicator';
|
|
11
|
+
import { Switch } from '../primitives/Switch';
|
|
12
|
+
import { KeyboardAvoidingView } from '../primitives/KeyboardAvoidingView';
|
|
13
|
+
import { SafeAreaView } from '../primitives/SafeAreaView';
|
|
14
|
+
import { StatusBar } from '../primitives/StatusBar';
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Built-in type → component mappings (cannot be overridden)
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
const BUILT_IN_TYPES: ReadonlySet<string> = new Set([
|
|
21
|
+
'text',
|
|
22
|
+
'view',
|
|
23
|
+
'scrollview',
|
|
24
|
+
'image',
|
|
25
|
+
'pressable',
|
|
26
|
+
'textinput',
|
|
27
|
+
'flatlist',
|
|
28
|
+
'modal',
|
|
29
|
+
'activityindicator',
|
|
30
|
+
'switch',
|
|
31
|
+
'keyboardavoidingview',
|
|
32
|
+
'safeareaview',
|
|
33
|
+
'statusbar',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const BUILT_IN_COMPONENTS: ReadonlyMap<string, React.ComponentType<Record<string, unknown>>> =
|
|
37
|
+
new Map([
|
|
38
|
+
['text', Text as React.ComponentType<Record<string, unknown>>],
|
|
39
|
+
['view', View as React.ComponentType<Record<string, unknown>>],
|
|
40
|
+
['scrollview', ScrollView as React.ComponentType<Record<string, unknown>>],
|
|
41
|
+
['image', Image as React.ComponentType<Record<string, unknown>>],
|
|
42
|
+
['pressable', Pressable as React.ComponentType<Record<string, unknown>>],
|
|
43
|
+
['textinput', TextInput as React.ComponentType<Record<string, unknown>>],
|
|
44
|
+
['flatlist', FlatList as unknown as React.ComponentType<Record<string, unknown>>],
|
|
45
|
+
['modal', Modal as React.ComponentType<Record<string, unknown>>],
|
|
46
|
+
['activityindicator', ActivityIndicator as React.ComponentType<Record<string, unknown>>],
|
|
47
|
+
['switch', Switch as React.ComponentType<Record<string, unknown>>],
|
|
48
|
+
['keyboardavoidingview', KeyboardAvoidingView as React.ComponentType<Record<string, unknown>>],
|
|
49
|
+
['safeareaview', SafeAreaView as React.ComponentType<Record<string, unknown>>],
|
|
50
|
+
['statusbar', StatusBar as React.ComponentType<Record<string, unknown>>],
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// ComponentRegistry
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Maps component type strings to React components.
|
|
59
|
+
*
|
|
60
|
+
* Built-ins are always present and cannot be overridden.
|
|
61
|
+
* Developer-registered components are merged on top for non-conflicting types.
|
|
62
|
+
*/
|
|
63
|
+
export class ComponentRegistry {
|
|
64
|
+
private readonly components: Map<string, React.ComponentType<Record<string, unknown>>>;
|
|
65
|
+
|
|
66
|
+
constructor(developerComponents?: Record<string, React.ComponentType<unknown>>) {
|
|
67
|
+
// Start with built-ins
|
|
68
|
+
this.components = new Map(BUILT_IN_COMPONENTS);
|
|
69
|
+
|
|
70
|
+
// Merge developer components, skipping any that conflict with built-ins
|
|
71
|
+
if (developerComponents) {
|
|
72
|
+
for (const [type, component] of Object.entries(developerComponents)) {
|
|
73
|
+
if (BUILT_IN_TYPES.has(type)) {
|
|
74
|
+
console.warn(
|
|
75
|
+
`[PushFrame] ComponentRegistry: "${type}" is a built-in type and cannot be overridden. ` +
|
|
76
|
+
`Registration skipped.`,
|
|
77
|
+
);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
this.components.set(type, component as React.ComponentType<Record<string, unknown>>);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Resolve a type string to its React component.
|
|
87
|
+
* Returns null if no component is registered for the type.
|
|
88
|
+
*/
|
|
89
|
+
resolve(type: string): React.ComponentType<Record<string, unknown>> | null {
|
|
90
|
+
return this.components.get(type) ?? null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Returns all registered type strings (useful for debugging).
|
|
95
|
+
*/
|
|
96
|
+
types(): string[] {
|
|
97
|
+
return Array.from(this.components.keys());
|
|
98
|
+
}
|
|
99
|
+
}
|