zelune 1.5.1 → 1.5.4
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 +30 -0
- package/README.md +8 -15
- package/bin/cli.mjs +17 -6
- package/index.html +9 -2
- package/package.json +2 -1
- package/plugin.json +1 -1
- package/plugins/viteReactNativeFallbackPlugin.ts +568 -0
- package/plugins/viteVirtualScreensPlugin.ts +139 -8
- package/src/canvas/CanvasApp.tsx +111 -23
- package/src/canvas/FlowArrowsLayer.tsx +5 -5
- package/src/canvas/InspectorPanel.tsx +58 -49
- package/src/canvas/ScreenArtboard.tsx +90 -29
- package/src/main.tsx +70 -1
- package/src/runtime/MockNavigationContext.tsx +1007 -38
- package/src/runtime/reactNativeShim.ts +141 -0
- package/src/screens/ProductDetailScreen.tsx +32 -59
- package/src/server/astEngine.ts +10 -1
- package/src/styles.css +182 -21
- package/vite.config.ts +136 -67
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import React, { createContext, useContext, useMemo, useEffect } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import React, { createContext, useContext, useMemo, useEffect, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
TouchableOpacity,
|
|
4
|
+
TouchableHighlight,
|
|
5
|
+
TouchableWithoutFeedback,
|
|
6
|
+
Pressable,
|
|
7
|
+
View,
|
|
8
|
+
Text,
|
|
9
|
+
Image as RNImage,
|
|
10
|
+
ImageBackground as RNImageBackground,
|
|
11
|
+
ScrollView as RNScrollView,
|
|
12
|
+
FlatList as RNFlatList,
|
|
13
|
+
} from 'react-native';
|
|
3
14
|
|
|
4
15
|
export interface NavigationController {
|
|
5
16
|
navigate: (targetRoute: string, params?: Record<string, unknown>) => void;
|
|
@@ -9,6 +20,9 @@ export interface NavigationController {
|
|
|
9
20
|
back: () => void;
|
|
10
21
|
setOptions: (options?: Record<string, unknown>) => void;
|
|
11
22
|
canGoBack: () => boolean;
|
|
23
|
+
dispatch: (action?: unknown) => void;
|
|
24
|
+
reset: (state?: unknown) => void;
|
|
25
|
+
addListener: (event: string, callback: () => void) => () => void;
|
|
12
26
|
}
|
|
13
27
|
|
|
14
28
|
interface MockNavigationContextValue {
|
|
@@ -21,10 +35,12 @@ function normalizeNavTarget(raw: string): string {
|
|
|
21
35
|
const cleaned = String(raw ?? '')
|
|
22
36
|
.replace(/^\/+/, '')
|
|
23
37
|
.replace(/\([^)]+\)\/?/g, '')
|
|
38
|
+
.replace(/\[\.\.\.([^\]]+)\]/g, 'CatchAll_$1')
|
|
39
|
+
.replace(/\[([^\]]+)\]/g, 'By_$1')
|
|
24
40
|
.replace(/Screen$/, '')
|
|
25
41
|
.replace(/\/index$/, '');
|
|
26
42
|
if (!cleaned || cleaned === 'index') return 'Home';
|
|
27
|
-
if (cleaned.includes('-') || cleaned.includes('/') || cleaned === cleaned.toLowerCase()) {
|
|
43
|
+
if (cleaned.includes('-') || cleaned.includes('/') || cleaned.includes('_') || cleaned === cleaned.toLowerCase()) {
|
|
28
44
|
return cleaned
|
|
29
45
|
.split(/[-_/]/)
|
|
30
46
|
.filter(Boolean)
|
|
@@ -34,18 +50,23 @@ function normalizeNavTarget(raw: string): string {
|
|
|
34
50
|
return cleaned;
|
|
35
51
|
}
|
|
36
52
|
|
|
53
|
+
const noopNavigation: NavigationController = {
|
|
54
|
+
navigate: () => undefined,
|
|
55
|
+
goBack: () => undefined,
|
|
56
|
+
push: () => undefined,
|
|
57
|
+
replace: () => undefined,
|
|
58
|
+
back: () => undefined,
|
|
59
|
+
setOptions: () => undefined,
|
|
60
|
+
canGoBack: () => true,
|
|
61
|
+
dispatch: () => undefined,
|
|
62
|
+
reset: () => undefined,
|
|
63
|
+
addListener: () => () => undefined,
|
|
64
|
+
};
|
|
65
|
+
|
|
37
66
|
const MockNavigationContext = createContext<MockNavigationContextValue>({
|
|
38
67
|
currentRoute: 'Home',
|
|
39
68
|
params: {},
|
|
40
|
-
navigation:
|
|
41
|
-
navigate: () => undefined,
|
|
42
|
-
goBack: () => undefined,
|
|
43
|
-
push: () => undefined,
|
|
44
|
-
replace: () => undefined,
|
|
45
|
-
back: () => undefined,
|
|
46
|
-
setOptions: () => undefined,
|
|
47
|
-
canGoBack: () => true,
|
|
48
|
-
},
|
|
69
|
+
navigation: noopNavigation,
|
|
49
70
|
});
|
|
50
71
|
|
|
51
72
|
export interface MockNavigationProviderProps {
|
|
@@ -76,6 +97,9 @@ export const MockNavigationProvider: React.FC<MockNavigationProviderProps> = ({
|
|
|
76
97
|
back: () => onNavigate?.(routeName, 'Home'),
|
|
77
98
|
setOptions: () => undefined,
|
|
78
99
|
canGoBack: () => true,
|
|
100
|
+
dispatch: () => undefined,
|
|
101
|
+
reset: () => undefined,
|
|
102
|
+
addListener: () => () => undefined,
|
|
79
103
|
},
|
|
80
104
|
};
|
|
81
105
|
}, [routeName, params, onNavigate]);
|
|
@@ -87,7 +111,9 @@ export const MockNavigationProvider: React.FC<MockNavigationProviderProps> = ({
|
|
|
87
111
|
);
|
|
88
112
|
};
|
|
89
113
|
|
|
90
|
-
//
|
|
114
|
+
// ============================================================================
|
|
115
|
+
// 1. React Navigation Shims (@react-navigation/native, native-stack, bottom-tabs)
|
|
116
|
+
// ============================================================================
|
|
91
117
|
export function useNavigation(): NavigationController {
|
|
92
118
|
return useContext(MockNavigationContext).navigation;
|
|
93
119
|
}
|
|
@@ -103,7 +129,11 @@ export function useRoute(): { key: string; name: string; params: Record<string,
|
|
|
103
129
|
|
|
104
130
|
export function useFocusEffect(effect: () => void | (() => void)): void {
|
|
105
131
|
useEffect(() => {
|
|
106
|
-
|
|
132
|
+
try {
|
|
133
|
+
return effect();
|
|
134
|
+
} catch {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
107
137
|
}, [effect]);
|
|
108
138
|
}
|
|
109
139
|
|
|
@@ -111,31 +141,96 @@ export function useIsFocused(): boolean {
|
|
|
111
141
|
return true;
|
|
112
142
|
}
|
|
113
143
|
|
|
144
|
+
export function useScrollToTop(): void {}
|
|
145
|
+
|
|
114
146
|
export const NavigationContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
115
147
|
<>{children}</>
|
|
116
148
|
);
|
|
117
149
|
|
|
118
|
-
|
|
150
|
+
export const CommonActions = {
|
|
151
|
+
navigate: (payload: unknown) => ({ type: 'NAVIGATE', payload }),
|
|
152
|
+
reset: (payload: unknown) => ({ type: 'RESET', payload }),
|
|
153
|
+
goBack: () => ({ type: 'GO_BACK' }),
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export const StackActions = {
|
|
157
|
+
push: (routeName: string, params?: unknown) => ({ type: 'PUSH', payload: { routeName, params } }),
|
|
158
|
+
replace: (routeName: string, params?: unknown) => ({
|
|
159
|
+
type: 'REPLACE',
|
|
160
|
+
payload: { routeName, params },
|
|
161
|
+
}),
|
|
162
|
+
pop: (count = 1) => ({ type: 'POP', payload: { count } }),
|
|
163
|
+
popToTop: () => ({ type: 'POP_TO_TOP' }),
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
function createNavigatorShim() {
|
|
167
|
+
const Navigator: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
|
|
168
|
+
const Screen: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
|
|
169
|
+
const Group: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
|
|
170
|
+
return { Navigator, Screen, Group };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const createNativeStackNavigator = createNavigatorShim;
|
|
174
|
+
export const createStackNavigator = createNavigatorShim;
|
|
175
|
+
export const createBottomTabNavigator = createNavigatorShim;
|
|
176
|
+
export const createDrawerNavigator = createNavigatorShim;
|
|
177
|
+
export const createMaterialTopTabNavigator = createNavigatorShim;
|
|
178
|
+
|
|
179
|
+
export const DefaultTheme = {
|
|
180
|
+
dark: false,
|
|
181
|
+
colors: {
|
|
182
|
+
primary: '#6366F1',
|
|
183
|
+
background: '#F8FAFC',
|
|
184
|
+
card: '#FFFFFF',
|
|
185
|
+
text: '#0F172A',
|
|
186
|
+
border: '#E2E8F0',
|
|
187
|
+
notification: '#EF4444',
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const DarkTheme = {
|
|
192
|
+
dark: true,
|
|
193
|
+
colors: {
|
|
194
|
+
primary: '#6366F1',
|
|
195
|
+
background: '#09090B',
|
|
196
|
+
card: '#18181B',
|
|
197
|
+
text: '#F8FAFC',
|
|
198
|
+
border: '#27272A',
|
|
199
|
+
notification: '#EF4444',
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export const ThemeProvider: React.FC<{ value?: unknown; children?: React.ReactNode }> = ({
|
|
204
|
+
children,
|
|
205
|
+
}) => <>{children}</>;
|
|
206
|
+
|
|
207
|
+
export function useTheme() {
|
|
208
|
+
return DarkTheme;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function useNavigationContainerRef() {
|
|
212
|
+
return { current: noopNavigation, isReady: () => true };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ============================================================================
|
|
216
|
+
// 2. Expo Router Shims (expo-router)
|
|
217
|
+
// ============================================================================
|
|
119
218
|
export function useRouter(): NavigationController {
|
|
120
219
|
return useContext(MockNavigationContext).navigation;
|
|
121
220
|
}
|
|
122
221
|
|
|
123
|
-
export const router: NavigationController =
|
|
124
|
-
navigate: () => undefined,
|
|
125
|
-
push: () => undefined,
|
|
126
|
-
replace: () => undefined,
|
|
127
|
-
goBack: () => undefined,
|
|
128
|
-
back: () => undefined,
|
|
129
|
-
setOptions: () => undefined,
|
|
130
|
-
canGoBack: () => true,
|
|
131
|
-
};
|
|
222
|
+
export const router: NavigationController = noopNavigation;
|
|
132
223
|
|
|
133
|
-
export function useLocalSearchParams<
|
|
224
|
+
export function useLocalSearchParams<
|
|
225
|
+
T extends Record<string, unknown> = Record<string, string>
|
|
226
|
+
>(): T {
|
|
134
227
|
const ctx = useContext(MockNavigationContext);
|
|
135
228
|
return ctx.params as T;
|
|
136
229
|
}
|
|
137
230
|
|
|
138
|
-
export function useGlobalSearchParams<
|
|
231
|
+
export function useGlobalSearchParams<
|
|
232
|
+
T extends Record<string, unknown> = Record<string, string>
|
|
233
|
+
>(): T {
|
|
139
234
|
const ctx = useContext(MockNavigationContext);
|
|
140
235
|
return ctx.params as T;
|
|
141
236
|
}
|
|
@@ -150,6 +245,10 @@ export function useSegments(): string[] {
|
|
|
150
245
|
return [ctx.currentRoute.toLowerCase()];
|
|
151
246
|
}
|
|
152
247
|
|
|
248
|
+
export function useRootNavigationState() {
|
|
249
|
+
return { key: 'root', stale: false };
|
|
250
|
+
}
|
|
251
|
+
|
|
153
252
|
export const Link: React.FC<{
|
|
154
253
|
href: string | { pathname: string; params?: Record<string, unknown> };
|
|
155
254
|
asChild?: boolean;
|
|
@@ -157,7 +256,7 @@ export const Link: React.FC<{
|
|
|
157
256
|
style?: unknown;
|
|
158
257
|
}> = ({ href, children, style }) => {
|
|
159
258
|
const nav = useContext(MockNavigationContext).navigation;
|
|
160
|
-
const target = typeof href === 'string' ? href : href
|
|
259
|
+
const target = typeof href === 'string' ? href : href?.pathname ?? 'Home';
|
|
161
260
|
return (
|
|
162
261
|
<TouchableOpacity
|
|
163
262
|
activeOpacity={0.78}
|
|
@@ -169,31 +268,901 @@ export const Link: React.FC<{
|
|
|
169
268
|
);
|
|
170
269
|
};
|
|
171
270
|
|
|
172
|
-
const
|
|
271
|
+
export const Redirect: React.FC<{ href: string }> = () => null;
|
|
272
|
+
|
|
273
|
+
const NoopLayoutScreen: React.FC<{ children?: React.ReactNode; screenOptions?: unknown }> & {
|
|
173
274
|
Screen: React.FC<{ name?: string; options?: unknown }>;
|
|
174
|
-
} = ({ children }
|
|
275
|
+
} = ({ children }) => <>{children}</>;
|
|
175
276
|
NoopLayoutScreen.Screen = () => null;
|
|
176
277
|
|
|
177
278
|
export const Stack = NoopLayoutScreen;
|
|
178
279
|
export const Tabs = NoopLayoutScreen;
|
|
280
|
+
export const Drawer = NoopLayoutScreen;
|
|
179
281
|
export const Slot: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
|
|
282
|
+
export const SplashScreen = {
|
|
283
|
+
preventAutoHideAsync: async () => true,
|
|
284
|
+
hideAsync: async () => true,
|
|
285
|
+
};
|
|
180
286
|
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
287
|
+
// ============================================================================
|
|
288
|
+
// 3. React Native Safe Area Context Shims (react-native-safe-area-context)
|
|
289
|
+
// ============================================================================
|
|
290
|
+
export const SafeAreaProvider: React.FC<{ children?: React.ReactNode; style?: unknown }> = ({
|
|
291
|
+
children,
|
|
292
|
+
style,
|
|
293
|
+
}) => <View style={[{ flex: 1 }, style as never]}>{children}</View>;
|
|
185
294
|
|
|
186
295
|
export const SafeAreaView: React.FC<{
|
|
187
296
|
children?: React.ReactNode;
|
|
188
297
|
style?: unknown;
|
|
189
298
|
edges?: string[];
|
|
190
|
-
}> = ({ children, style }) =>
|
|
191
|
-
<View style={[{ flex: 1 }, style as never]}>{children}</View>
|
|
192
|
-
);
|
|
299
|
+
}> = ({ children, style }) => <View style={[{ flex: 1 }, style as never]}>{children}</View>;
|
|
193
300
|
|
|
194
301
|
export function useSafeAreaInsets(): { top: number; right: number; bottom: number; left: number } {
|
|
195
302
|
return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
196
303
|
}
|
|
197
304
|
|
|
198
|
-
|
|
199
|
-
|
|
305
|
+
export function useSafeAreaFrame(): { x: number; y: number; width: number; height: number } {
|
|
306
|
+
return { x: 0, y: 0, width: 393, height: 852 };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export const SafeAreaInsetsContext = createContext({ top: 0, right: 0, bottom: 0, left: 0 });
|
|
310
|
+
export const SafeAreaFrameContext = createContext({ x: 0, y: 0, width: 393, height: 852 });
|
|
311
|
+
|
|
312
|
+
export function withSafeAreaInsets<P extends object>(Component: React.ComponentType<P>) {
|
|
313
|
+
return function WithSafeAreaInsetsWrapper(props: P) {
|
|
314
|
+
return <Component {...props} insets={{ top: 0, right: 0, bottom: 0, left: 0 }} />;
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export const initialWindowMetrics = {
|
|
319
|
+
frame: { x: 0, y: 0, width: 393, height: 852 },
|
|
320
|
+
insets: { top: 0, right: 0, bottom: 0, left: 0 },
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// ============================================================================
|
|
324
|
+
// 4. Expo Status Bar Shim (expo-status-bar)
|
|
325
|
+
// ============================================================================
|
|
326
|
+
export const StatusBar: React.FC<{
|
|
327
|
+
style?: string;
|
|
328
|
+
hidden?: boolean;
|
|
329
|
+
backgroundColor?: string;
|
|
330
|
+
translucent?: boolean;
|
|
331
|
+
}> = () => null;
|
|
332
|
+
|
|
333
|
+
// ============================================================================
|
|
334
|
+
// 5. @expo/vector-icons Shims
|
|
335
|
+
// ============================================================================
|
|
336
|
+
export interface VectorIconProps {
|
|
337
|
+
name?: string;
|
|
338
|
+
size?: number;
|
|
339
|
+
color?: string;
|
|
340
|
+
style?: unknown;
|
|
341
|
+
onPress?: () => void;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const ICON_GLYPH_MAP: Record<string, string> = {
|
|
345
|
+
'arrow-back': '←',
|
|
346
|
+
'arrow-left': '←',
|
|
347
|
+
'chevron-back': '‹',
|
|
348
|
+
'chevron-left': '‹',
|
|
349
|
+
'arrow-forward': '→',
|
|
350
|
+
'arrow-right': '→',
|
|
351
|
+
'chevron-forward': '›',
|
|
352
|
+
'chevron-right': '›',
|
|
353
|
+
'chevron-down': '▾',
|
|
354
|
+
'chevron-up': '▴',
|
|
355
|
+
close: '✕',
|
|
356
|
+
'close-circle': '⊗',
|
|
357
|
+
x: '✕',
|
|
358
|
+
add: '+',
|
|
359
|
+
plus: '+',
|
|
360
|
+
'add-circle': '⊕',
|
|
361
|
+
remove: '−',
|
|
362
|
+
minus: '−',
|
|
363
|
+
check: '✓',
|
|
364
|
+
checkmark: '✓',
|
|
365
|
+
'checkmark-circle': '✓',
|
|
366
|
+
search: '⌕',
|
|
367
|
+
home: '⌂',
|
|
368
|
+
person: '◉',
|
|
369
|
+
user: '◉',
|
|
370
|
+
settings: '⚙',
|
|
371
|
+
cog: '⚙',
|
|
372
|
+
bell: '🔔',
|
|
373
|
+
notifications: '🔔',
|
|
374
|
+
heart: '♥',
|
|
375
|
+
'heart-outline': '♡',
|
|
376
|
+
star: '★',
|
|
377
|
+
'star-outline': '☆',
|
|
378
|
+
cart: '🛒',
|
|
379
|
+
'shopping-cart': '🛒',
|
|
380
|
+
bag: '🛍',
|
|
381
|
+
lock: '🔒',
|
|
382
|
+
'lock-closed': '🔒',
|
|
383
|
+
mail: '✉',
|
|
384
|
+
eye: '👁',
|
|
385
|
+
'eye-off': '◡',
|
|
386
|
+
trash: '🗑',
|
|
387
|
+
edit: '✎',
|
|
388
|
+
pencil: '✎',
|
|
389
|
+
share: '↗',
|
|
390
|
+
info: 'ℹ',
|
|
391
|
+
warning: '⚠',
|
|
392
|
+
alert: '⚠',
|
|
393
|
+
menu: '☰',
|
|
394
|
+
filter: '⊶',
|
|
395
|
+
calendar: '📅',
|
|
396
|
+
time: '⏱',
|
|
397
|
+
clock: '⏱',
|
|
398
|
+
location: '⌖',
|
|
399
|
+
'map-pin': '⌖',
|
|
400
|
+
camera: '📷',
|
|
401
|
+
image: '🖼',
|
|
402
|
+
send: '➤',
|
|
403
|
+
refresh: '↻',
|
|
404
|
+
sync: '↻',
|
|
405
|
+
wallet: '💳',
|
|
406
|
+
card: '💳',
|
|
407
|
+
cash: '¤',
|
|
408
|
+
'trending-up': '↗',
|
|
409
|
+
'trending-down': '↘',
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
export function createVectorIconComponent(familyName: string) {
|
|
413
|
+
const IconComp: React.FC<VectorIconProps> & {
|
|
414
|
+
glyphMap?: Record<string, number>;
|
|
415
|
+
loadFont?: () => Promise<void>;
|
|
416
|
+
} = ({ name = '', size = 18, color = '#94A3B8', style, onPress }) => {
|
|
417
|
+
const cleanName = String(name)
|
|
418
|
+
.toLowerCase()
|
|
419
|
+
.replace(/^ios-|^md-|^logo-/, '')
|
|
420
|
+
.replace(/-outline$|-sharp$/, '');
|
|
421
|
+
const symbol = ICON_GLYPH_MAP[String(name).toLowerCase()] ?? ICON_GLYPH_MAP[cleanName] ?? '◆';
|
|
422
|
+
return (
|
|
423
|
+
<Text
|
|
424
|
+
onPress={onPress}
|
|
425
|
+
accessibilityLabel={`${familyName}:${name}`}
|
|
426
|
+
style={[
|
|
427
|
+
{
|
|
428
|
+
fontSize: size * 0.85,
|
|
429
|
+
lineHeight: size,
|
|
430
|
+
width: size,
|
|
431
|
+
height: size,
|
|
432
|
+
color,
|
|
433
|
+
textAlign: 'center',
|
|
434
|
+
includeFontPadding: false,
|
|
435
|
+
} as never,
|
|
436
|
+
style as never,
|
|
437
|
+
]}
|
|
438
|
+
>
|
|
439
|
+
{symbol}
|
|
440
|
+
</Text>
|
|
441
|
+
);
|
|
442
|
+
};
|
|
443
|
+
IconComp.glyphMap = {};
|
|
444
|
+
IconComp.loadFont = async () => undefined;
|
|
445
|
+
return IconComp;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export const Ionicons = createVectorIconComponent('Ionicons');
|
|
449
|
+
export const Feather = createVectorIconComponent('Feather');
|
|
450
|
+
export const MaterialIcons = createVectorIconComponent('MaterialIcons');
|
|
451
|
+
export const MaterialCommunityIcons = createVectorIconComponent('MaterialCommunityIcons');
|
|
452
|
+
export const FontAwesome = createVectorIconComponent('FontAwesome');
|
|
453
|
+
export const FontAwesome5 = createVectorIconComponent('FontAwesome5');
|
|
454
|
+
export const FontAwesome6 = createVectorIconComponent('FontAwesome6');
|
|
455
|
+
export const AntDesign = createVectorIconComponent('AntDesign');
|
|
456
|
+
export const Entypo = createVectorIconComponent('Entypo');
|
|
457
|
+
export const EvilIcons = createVectorIconComponent('EvilIcons');
|
|
458
|
+
export const Foundation = createVectorIconComponent('Foundation');
|
|
459
|
+
export const Octicons = createVectorIconComponent('Octicons');
|
|
460
|
+
export const SimpleLineIcons = createVectorIconComponent('SimpleLineIcons');
|
|
461
|
+
export const Zocial = createVectorIconComponent('Zocial');
|
|
462
|
+
export const Fontisto = createVectorIconComponent('Fontisto');
|
|
463
|
+
export function createIconSet() {
|
|
464
|
+
return createVectorIconComponent('CustomIcon');
|
|
465
|
+
}
|
|
466
|
+
export function createIconSetFromIcoMoon() {
|
|
467
|
+
return createVectorIconComponent('IcoMoon');
|
|
468
|
+
}
|
|
469
|
+
export function createIconSetFromFontello() {
|
|
470
|
+
return createVectorIconComponent('Fontello');
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// ============================================================================
|
|
474
|
+
// 6. Expo Linear Gradient, Blur, Image & FlashList Shims
|
|
475
|
+
// ============================================================================
|
|
476
|
+
export const LinearGradient: React.FC<{
|
|
477
|
+
colors?: string[];
|
|
478
|
+
locations?: number[];
|
|
479
|
+
start?: { x: number; y: number } | [number, number];
|
|
480
|
+
end?: { x: number; y: number } | [number, number];
|
|
481
|
+
style?: unknown;
|
|
482
|
+
children?: React.ReactNode;
|
|
483
|
+
}> = ({ colors = ['#1E293B', '#0F172A'], style, children }) => {
|
|
484
|
+
const safeColors = Array.isArray(colors) && colors.length >= 2 ? colors : ['#1E293B', '#0F172A'];
|
|
485
|
+
return (
|
|
486
|
+
<View
|
|
487
|
+
style={[
|
|
488
|
+
{
|
|
489
|
+
backgroundColor: safeColors[0],
|
|
490
|
+
backgroundImage: `linear-gradient(135deg, ${safeColors.join(', ')})`,
|
|
491
|
+
} as never,
|
|
492
|
+
style as never,
|
|
493
|
+
]}
|
|
494
|
+
>
|
|
495
|
+
{children}
|
|
496
|
+
</View>
|
|
497
|
+
);
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
export const BlurView: React.FC<{
|
|
501
|
+
intensity?: number;
|
|
502
|
+
tint?: string;
|
|
503
|
+
style?: unknown;
|
|
504
|
+
children?: React.ReactNode;
|
|
505
|
+
}> = ({ intensity = 40, tint = 'dark', style, children }) => {
|
|
506
|
+
const bg = tint === 'light' ? 'rgba(255, 255, 255, 0.65)' : 'rgba(15, 23, 42, 0.65)';
|
|
507
|
+
return (
|
|
508
|
+
<View
|
|
509
|
+
style={[
|
|
510
|
+
{
|
|
511
|
+
backgroundColor: bg,
|
|
512
|
+
backdropFilter: `blur(${Math.round(intensity / 4)}px)`,
|
|
513
|
+
} as never,
|
|
514
|
+
style as never,
|
|
515
|
+
]}
|
|
516
|
+
>
|
|
517
|
+
{children}
|
|
518
|
+
</View>
|
|
519
|
+
);
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
export const Image: React.FC<Record<string, unknown>> = ({
|
|
523
|
+
contentFit,
|
|
524
|
+
resizeMode,
|
|
525
|
+
source,
|
|
526
|
+
...rest
|
|
527
|
+
}) => {
|
|
528
|
+
const resolvedSource = typeof source === 'string' ? { uri: source } : source;
|
|
529
|
+
return (
|
|
530
|
+
<RNImage
|
|
531
|
+
source={resolvedSource as never}
|
|
532
|
+
resizeMode={(contentFit ?? resizeMode ?? 'cover') as never}
|
|
533
|
+
{...(rest as Record<string, unknown>)}
|
|
534
|
+
/>
|
|
535
|
+
);
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
export const ImageBackground = RNImageBackground;
|
|
539
|
+
export const FlashList = RNFlatList;
|
|
540
|
+
|
|
541
|
+
// ============================================================================
|
|
542
|
+
// 7. React Native SVG Shims (react-native-svg)
|
|
543
|
+
// ============================================================================
|
|
544
|
+
function createSvgDomElement(tagName: string) {
|
|
545
|
+
return React.forwardRef< Element, Record<string, unknown>>(({ children, ...props }, ref) =>
|
|
546
|
+
React.createElement(tagName, { ...props, ref }, children as React.ReactNode)
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export const Svg = createSvgDomElement('svg');
|
|
551
|
+
export const Circle = createSvgDomElement('circle');
|
|
552
|
+
export const Ellipse = createSvgDomElement('ellipse');
|
|
553
|
+
export const G = createSvgDomElement('g');
|
|
554
|
+
export const SvgText = createSvgDomElement('text');
|
|
555
|
+
export const TSpan = createSvgDomElement('tspan');
|
|
556
|
+
export const TextPath = createSvgDomElement('textPath');
|
|
557
|
+
export const Path = createSvgDomElement('path');
|
|
558
|
+
export const Polygon = createSvgDomElement('polygon');
|
|
559
|
+
export const Polyline = createSvgDomElement('polyline');
|
|
560
|
+
export const Line = createSvgDomElement('line');
|
|
561
|
+
export const Rect = createSvgDomElement('rect');
|
|
562
|
+
export const Use = createSvgDomElement('use');
|
|
563
|
+
export const SvgImage = createSvgDomElement('image');
|
|
564
|
+
export const Symbol = createSvgDomElement('symbol');
|
|
565
|
+
export const Defs = createSvgDomElement('defs');
|
|
566
|
+
export const RadialGradient = createSvgDomElement('radialGradient');
|
|
567
|
+
export const Stop = createSvgDomElement('stop');
|
|
568
|
+
export const ClipPath = createSvgDomElement('clipPath');
|
|
569
|
+
export const Pattern = createSvgDomElement('pattern');
|
|
570
|
+
export const Mask = createSvgDomElement('mask');
|
|
571
|
+
export const ForeignObject = createSvgDomElement('foreignObject');
|
|
572
|
+
export const SvgXml: React.FC<{ xml?: string; width?: number | string; height?: number | string }> =
|
|
573
|
+
({ xml = '', width = 24, height = 24 }) => (
|
|
574
|
+
<span
|
|
575
|
+
style={{ display: 'inline-flex', width, height }}
|
|
576
|
+
dangerouslySetInnerHTML={{ __html: xml }}
|
|
577
|
+
/>
|
|
578
|
+
);
|
|
579
|
+
export const SvgUri: React.FC<{ uri?: string; width?: number; height?: number }> = ({
|
|
580
|
+
uri,
|
|
581
|
+
width = 24,
|
|
582
|
+
height = 24,
|
|
583
|
+
}) => <RNImage source={{ uri }} style={{ width, height }} />;
|
|
584
|
+
|
|
585
|
+
// ============================================================================
|
|
586
|
+
// 8. React Native Reanimated & Gesture Handler Shims
|
|
587
|
+
// ============================================================================
|
|
588
|
+
function createChainableAnimationStub(): Record<string, unknown> {
|
|
589
|
+
const proxy: Record<string, unknown> = new Proxy(
|
|
590
|
+
{},
|
|
591
|
+
{
|
|
592
|
+
get(_target, prop) {
|
|
593
|
+
if (prop === 'build') return () => ({});
|
|
594
|
+
return () => proxy;
|
|
595
|
+
},
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
return proxy;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export const FadeIn = createChainableAnimationStub();
|
|
602
|
+
export const FadeInDown = createChainableAnimationStub();
|
|
603
|
+
export const FadeInUp = createChainableAnimationStub();
|
|
604
|
+
export const FadeInLeft = createChainableAnimationStub();
|
|
605
|
+
export const FadeInRight = createChainableAnimationStub();
|
|
606
|
+
export const FadeOut = createChainableAnimationStub();
|
|
607
|
+
export const FadeOutDown = createChainableAnimationStub();
|
|
608
|
+
export const FadeOutUp = createChainableAnimationStub();
|
|
609
|
+
export const SlideInDown = createChainableAnimationStub();
|
|
610
|
+
export const SlideInUp = createChainableAnimationStub();
|
|
611
|
+
export const SlideInLeft = createChainableAnimationStub();
|
|
612
|
+
export const SlideInRight = createChainableAnimationStub();
|
|
613
|
+
export const SlideOutDown = createChainableAnimationStub();
|
|
614
|
+
export const SlideOutUp = createChainableAnimationStub();
|
|
615
|
+
export const SlideOutLeft = createChainableAnimationStub();
|
|
616
|
+
export const SlideOutRight = createChainableAnimationStub();
|
|
617
|
+
export const ZoomIn = createChainableAnimationStub();
|
|
618
|
+
export const ZoomOut = createChainableAnimationStub();
|
|
619
|
+
export const Layout = createChainableAnimationStub();
|
|
620
|
+
export const LinearTransition = createChainableAnimationStub();
|
|
621
|
+
export const SequencedTransition = createChainableAnimationStub();
|
|
622
|
+
export const FadingTransition = createChainableAnimationStub();
|
|
623
|
+
|
|
624
|
+
export function useSharedValue<T>(initialValue: T): { value: T } {
|
|
625
|
+
const ref = useRef<{ value: T }>({ value: initialValue });
|
|
626
|
+
return ref.current;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
export function useAnimatedStyle<T extends Record<string, unknown>>(
|
|
630
|
+
updater: () => T
|
|
631
|
+
): T {
|
|
632
|
+
try {
|
|
633
|
+
return updater();
|
|
634
|
+
} catch {
|
|
635
|
+
return {} as T;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
export function useDerivedValue<T>(updater: () => T): { value: T } {
|
|
640
|
+
try {
|
|
641
|
+
return { value: updater() };
|
|
642
|
+
} catch {
|
|
643
|
+
return { value: undefined as unknown as T };
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
export function useAnimatedProps<T extends Record<string, unknown>>(updater: () => T): T {
|
|
648
|
+
try {
|
|
649
|
+
return updater();
|
|
650
|
+
} catch {
|
|
651
|
+
return {} as T;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
export function useAnimatedScrollHandler() {
|
|
656
|
+
return () => undefined;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export function useAnimatedRef() {
|
|
660
|
+
return useRef(null);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
export function useAnimatedGestureHandler() {
|
|
664
|
+
return () => undefined;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
export function withTiming<T>(toValue: T, _config?: unknown, callback?: (finished: boolean) => void): T {
|
|
668
|
+
callback?.(true);
|
|
669
|
+
return toValue;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export function withSpring<T>(toValue: T, _config?: unknown, callback?: (finished: boolean) => void): T {
|
|
673
|
+
callback?.(true);
|
|
674
|
+
return toValue;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
export function withDelay<T>(_delayMs: number, animationValue: T): T {
|
|
678
|
+
return animationValue;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
export function withSequence<T>(...animations: T[]): T {
|
|
682
|
+
return animations[animations.length - 1];
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
export function withRepeat<T>(animationValue: T): T {
|
|
686
|
+
return animationValue;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export function cancelAnimation(): void {}
|
|
690
|
+
|
|
691
|
+
export function runOnJS<T extends (...args: never[]) => unknown>(fn: T): T {
|
|
692
|
+
return fn;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
export function runOnUI<T extends (...args: never[]) => unknown>(fn: T): T {
|
|
696
|
+
return fn;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
export function interpolate(
|
|
700
|
+
value: number,
|
|
701
|
+
inputRange: number[],
|
|
702
|
+
outputRange: number[]
|
|
703
|
+
): number {
|
|
704
|
+
if (!inputRange?.length || !outputRange?.length) return value;
|
|
705
|
+
if (value <= inputRange[0]) return outputRange[0];
|
|
706
|
+
if (value >= inputRange[inputRange.length - 1]) return outputRange[outputRange.length - 1];
|
|
707
|
+
return outputRange[0];
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
export const Extrapolation = {
|
|
711
|
+
IDENTITY: 'identity',
|
|
712
|
+
CLAMP: 'clamp',
|
|
713
|
+
EXTEND: 'extend',
|
|
714
|
+
};
|
|
715
|
+
export const Extrapolate = Extrapolation;
|
|
716
|
+
|
|
717
|
+
export const Easing = {
|
|
718
|
+
linear: (t: number) => t,
|
|
719
|
+
ease: (t: number) => t,
|
|
720
|
+
quad: (t: number) => t * t,
|
|
721
|
+
cubic: (t: number) => t * t * t,
|
|
722
|
+
bezier: () => (t: number) => t,
|
|
723
|
+
in: (fn: (t: number) => number) => fn,
|
|
724
|
+
out: (fn: (t: number) => number) => fn,
|
|
725
|
+
inOut: (fn: (t: number) => number) => fn,
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
export function createAnimatedComponent<P extends object>(Component: React.ComponentType<P>) {
|
|
729
|
+
return Component;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
export const Animated = {
|
|
733
|
+
View,
|
|
734
|
+
Text,
|
|
735
|
+
Image: RNImage,
|
|
736
|
+
ScrollView: RNScrollView,
|
|
737
|
+
FlatList: RNFlatList,
|
|
738
|
+
createAnimatedComponent,
|
|
739
|
+
Value: class {
|
|
740
|
+
private _val: number;
|
|
741
|
+
constructor(v = 0) {
|
|
742
|
+
this._val = v;
|
|
743
|
+
}
|
|
744
|
+
setValue(v: number) {
|
|
745
|
+
this._val = v;
|
|
746
|
+
}
|
|
747
|
+
interpolate() {
|
|
748
|
+
return this._val;
|
|
749
|
+
}
|
|
750
|
+
},
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
// React Native Gesture Handler Shims
|
|
754
|
+
export const GestureHandlerRootView: React.FC<{ children?: React.ReactNode; style?: unknown }> = ({
|
|
755
|
+
children,
|
|
756
|
+
style,
|
|
757
|
+
}) => <View style={[{ flex: 1 }, style as never]}>{children}</View>;
|
|
758
|
+
|
|
759
|
+
export const ScrollView = RNScrollView;
|
|
760
|
+
export const FlatList = RNFlatList;
|
|
761
|
+
export { TouchableOpacity, TouchableHighlight, TouchableWithoutFeedback, Pressable };
|
|
762
|
+
export const Swipeable: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
763
|
+
<>{children}</>
|
|
764
|
+
);
|
|
765
|
+
export const DrawerLayout: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
766
|
+
<>{children}</>
|
|
767
|
+
);
|
|
768
|
+
export const PanGestureHandler: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
769
|
+
<>{children}</>
|
|
770
|
+
);
|
|
771
|
+
export const TapGestureHandler: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
772
|
+
<>{children}</>
|
|
773
|
+
);
|
|
774
|
+
export const LongPressGestureHandler: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
|
|
775
|
+
<>{children}</>
|
|
776
|
+
);
|
|
777
|
+
export const GestureDetector: React.FC<{ gesture?: unknown; children?: React.ReactNode }> = ({
|
|
778
|
+
children,
|
|
779
|
+
}) => <>{children}</>;
|
|
780
|
+
export const Gesture = {
|
|
781
|
+
Pan: () => createChainableAnimationStub(),
|
|
782
|
+
Tap: () => createChainableAnimationStub(),
|
|
783
|
+
LongPress: () => createChainableAnimationStub(),
|
|
784
|
+
Pinch: () => createChainableAnimationStub(),
|
|
785
|
+
Rotation: () => createChainableAnimationStub(),
|
|
786
|
+
Fling: () => createChainableAnimationStub(),
|
|
787
|
+
Simultaneous: () => createChainableAnimationStub(),
|
|
788
|
+
Exclusive: () => createChainableAnimationStub(),
|
|
789
|
+
Race: () => createChainableAnimationStub(),
|
|
790
|
+
};
|
|
791
|
+
export const State = {
|
|
792
|
+
UNDETERMINED: 0,
|
|
793
|
+
FAILED: 1,
|
|
794
|
+
BEGAN: 2,
|
|
795
|
+
CANCELLED: 3,
|
|
796
|
+
ACTIVE: 4,
|
|
797
|
+
END: 5,
|
|
798
|
+
};
|
|
799
|
+
export const Directions = {
|
|
800
|
+
RIGHT: 1,
|
|
801
|
+
LEFT: 2,
|
|
802
|
+
UP: 4,
|
|
803
|
+
DOWN: 8,
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
// ============================================================================
|
|
807
|
+
// 9. Common Expo SDK Runtime Shims (Haptics, Constants, Font, Storage, etc.)
|
|
808
|
+
// ============================================================================
|
|
809
|
+
export const ImpactFeedbackStyle = { Light: 'light', Medium: 'medium', Heavy: 'heavy' };
|
|
810
|
+
export const NotificationFeedbackType = {
|
|
811
|
+
Success: 'success',
|
|
812
|
+
Warning: 'warning',
|
|
813
|
+
Error: 'error',
|
|
814
|
+
};
|
|
815
|
+
export async function impactAsync(): Promise<void> {}
|
|
816
|
+
export async function notificationAsync(): Promise<void> {}
|
|
817
|
+
export async function selectionAsync(): Promise<void> {}
|
|
818
|
+
|
|
819
|
+
export const Constants = {
|
|
820
|
+
expoConfig: { name: 'Zelune App', slug: 'zelune-app', extra: {} },
|
|
821
|
+
manifest: { extra: {} },
|
|
822
|
+
statusBarHeight: 0,
|
|
823
|
+
systemFonts: [],
|
|
824
|
+
appOwnership: 'expo',
|
|
825
|
+
executionEnvironment: 'storeClient',
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
export function useFonts(): [boolean, null] {
|
|
829
|
+
return [true, null];
|
|
830
|
+
}
|
|
831
|
+
export async function loadAsync(): Promise<void> {}
|
|
832
|
+
export function isLoaded(): boolean {
|
|
833
|
+
return true;
|
|
834
|
+
}
|
|
835
|
+
export async function preventAutoHideAsync(): Promise<boolean> {
|
|
836
|
+
return true;
|
|
837
|
+
}
|
|
838
|
+
export async function hideAsync(): Promise<boolean> {
|
|
839
|
+
return true;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
const memoryStorage = new Map<string, string>();
|
|
843
|
+
export const AsyncStorage = {
|
|
844
|
+
getItem: async (key: string) => memoryStorage.get(key) ?? null,
|
|
845
|
+
setItem: async (key: string, value: string) => {
|
|
846
|
+
memoryStorage.set(key, value);
|
|
847
|
+
},
|
|
848
|
+
removeItem: async (key: string) => {
|
|
849
|
+
memoryStorage.delete(key);
|
|
850
|
+
},
|
|
851
|
+
clear: async () => {
|
|
852
|
+
memoryStorage.clear();
|
|
853
|
+
},
|
|
854
|
+
getAllKeys: async () => Array.from(memoryStorage.keys()),
|
|
855
|
+
multiGet: async (keys: string[]) => keys.map((k) => [k, memoryStorage.get(k) ?? null]),
|
|
856
|
+
multiSet: async (pairs: [string, string][]) => {
|
|
857
|
+
pairs.forEach(([k, v]) => memoryStorage.set(k, v));
|
|
858
|
+
},
|
|
859
|
+
multiRemove: async (keys: string[]) => {
|
|
860
|
+
keys.forEach((k) => memoryStorage.delete(k));
|
|
861
|
+
},
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
export async function getItemAsync(key: string): Promise<string | null> {
|
|
865
|
+
return memoryStorage.get(key) ?? null;
|
|
866
|
+
}
|
|
867
|
+
export async function setItemAsync(key: string, value: string): Promise<void> {
|
|
868
|
+
memoryStorage.set(key, value);
|
|
869
|
+
}
|
|
870
|
+
export async function deleteItemAsync(key: string): Promise<void> {
|
|
871
|
+
memoryStorage.delete(key);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
export async function setStringAsync(): Promise<boolean> {
|
|
875
|
+
return true;
|
|
876
|
+
}
|
|
877
|
+
export async function getStringAsync(): Promise<string> {
|
|
878
|
+
return '';
|
|
879
|
+
}
|
|
880
|
+
export async function openURL(url: string): Promise<boolean> {
|
|
881
|
+
if (typeof window !== 'undefined') {
|
|
882
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
883
|
+
}
|
|
884
|
+
return true;
|
|
885
|
+
}
|
|
886
|
+
export function createURL(pathStr = ''): string {
|
|
887
|
+
return `/${String(pathStr).replace(/^\/+/, '')}`;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// ============================================================================
|
|
891
|
+
// 10. State Management, Data Fetching & Backend Client Shims
|
|
892
|
+
// (Zustand, TanStack React Query, Supabase Client)
|
|
893
|
+
// ============================================================================
|
|
894
|
+
export function create(initializer?: unknown): unknown {
|
|
895
|
+
if (typeof initializer !== 'function') {
|
|
896
|
+
return (curriedInitializer: unknown) => create(curriedInitializer);
|
|
897
|
+
}
|
|
898
|
+
let state: Record<string, unknown> = {};
|
|
899
|
+
const setState = (partial: unknown) => {
|
|
900
|
+
try {
|
|
901
|
+
const next =
|
|
902
|
+
typeof partial === 'function' ? (partial as (s: unknown) => unknown)(state) : partial;
|
|
903
|
+
if (next && typeof next === 'object') {
|
|
904
|
+
state = { ...state, ...(next as Record<string, unknown>) };
|
|
905
|
+
}
|
|
906
|
+
} catch {
|
|
907
|
+
// Ignore setter errors in static canvas preview
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
const getState = () => state;
|
|
911
|
+
const api = {
|
|
912
|
+
setState,
|
|
913
|
+
getState,
|
|
914
|
+
getInitialState: () => state,
|
|
915
|
+
subscribe: () => () => undefined,
|
|
916
|
+
destroy: () => undefined,
|
|
917
|
+
};
|
|
918
|
+
try {
|
|
919
|
+
const initial = (
|
|
920
|
+
initializer as (
|
|
921
|
+
set: typeof setState,
|
|
922
|
+
get: typeof getState,
|
|
923
|
+
store: typeof api
|
|
924
|
+
) => Record<string, unknown>
|
|
925
|
+
)(setState, getState, api);
|
|
926
|
+
if (initial && typeof initial === 'object') {
|
|
927
|
+
state = initial;
|
|
928
|
+
}
|
|
929
|
+
} catch {
|
|
930
|
+
state = {};
|
|
931
|
+
}
|
|
932
|
+
const useBoundStore = (selector?: (s: Record<string, unknown>) => unknown) => {
|
|
933
|
+
if (typeof selector === 'function') {
|
|
934
|
+
try {
|
|
935
|
+
return selector(state);
|
|
936
|
+
} catch {
|
|
937
|
+
return undefined;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
return state;
|
|
941
|
+
};
|
|
942
|
+
return Object.assign(useBoundStore, api);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
export function useStore(
|
|
946
|
+
store: { getState?: () => Record<string, unknown> } | ((s?: unknown) => unknown),
|
|
947
|
+
selector?: (s: Record<string, unknown>) => unknown
|
|
948
|
+
) {
|
|
949
|
+
const rawState =
|
|
950
|
+
typeof store === 'function'
|
|
951
|
+
? (store as () => Record<string, unknown>)()
|
|
952
|
+
: store?.getState?.() ?? {};
|
|
953
|
+
return typeof selector === 'function' ? selector(rawState) : rawState;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
export class QueryClient {
|
|
957
|
+
mount() {}
|
|
958
|
+
unmount() {}
|
|
959
|
+
clear() {}
|
|
960
|
+
getQueryData() {
|
|
961
|
+
return undefined;
|
|
962
|
+
}
|
|
963
|
+
setQueryData() {}
|
|
964
|
+
invalidateQueries() {
|
|
965
|
+
return Promise.resolve();
|
|
966
|
+
}
|
|
967
|
+
prefetchQuery() {
|
|
968
|
+
return Promise.resolve();
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
export const QueryClientProvider: React.FC<{ client?: unknown; children?: React.ReactNode }> = ({
|
|
973
|
+
children,
|
|
974
|
+
}) => <>{children}</>;
|
|
975
|
+
|
|
976
|
+
export function useQueryClient() {
|
|
977
|
+
return new QueryClient();
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
export function useQuery() {
|
|
981
|
+
return {
|
|
982
|
+
data: undefined,
|
|
983
|
+
error: null,
|
|
984
|
+
isLoading: false,
|
|
985
|
+
isPending: false,
|
|
986
|
+
isFetching: false,
|
|
987
|
+
isError: false,
|
|
988
|
+
isSuccess: true,
|
|
989
|
+
status: 'success',
|
|
990
|
+
refetch: async () => ({ data: undefined, error: null }),
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
export function useInfiniteQuery() {
|
|
995
|
+
return {
|
|
996
|
+
data: { pages: [], pageParams: [] },
|
|
997
|
+
error: null,
|
|
998
|
+
isLoading: false,
|
|
999
|
+
isPending: false,
|
|
1000
|
+
isFetching: false,
|
|
1001
|
+
isFetchingNextPage: false,
|
|
1002
|
+
hasNextPage: false,
|
|
1003
|
+
fetchNextPage: async () => ({}),
|
|
1004
|
+
refetch: async () => ({}),
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
export function useMutation() {
|
|
1009
|
+
return {
|
|
1010
|
+
mutate: () => undefined,
|
|
1011
|
+
mutateAsync: async () => ({}),
|
|
1012
|
+
reset: () => undefined,
|
|
1013
|
+
data: undefined,
|
|
1014
|
+
error: null,
|
|
1015
|
+
isLoading: false,
|
|
1016
|
+
isPending: false,
|
|
1017
|
+
isError: false,
|
|
1018
|
+
isSuccess: false,
|
|
1019
|
+
status: 'idle',
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
function createSupabaseQueryBuilder(): Record<string, unknown> {
|
|
1024
|
+
const resultPromise = Promise.resolve({ data: [], error: null, count: 0 });
|
|
1025
|
+
const builder: Record<string, unknown> = new Proxy(
|
|
1026
|
+
{},
|
|
1027
|
+
{
|
|
1028
|
+
get(_target, prop) {
|
|
1029
|
+
if (prop === 'then') return resultPromise.then.bind(resultPromise);
|
|
1030
|
+
if (prop === 'catch') return resultPromise.catch.bind(resultPromise);
|
|
1031
|
+
if (prop === 'finally') return resultPromise.finally.bind(resultPromise);
|
|
1032
|
+
if (prop === 'single' || prop === 'maybeSingle') {
|
|
1033
|
+
return async () => ({ data: null, error: null });
|
|
1034
|
+
}
|
|
1035
|
+
return () => builder;
|
|
1036
|
+
},
|
|
1037
|
+
}
|
|
1038
|
+
);
|
|
1039
|
+
return builder;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
export function createClient() {
|
|
1043
|
+
return {
|
|
1044
|
+
auth: {
|
|
1045
|
+
getSession: async () => ({ data: { session: null }, error: null }),
|
|
1046
|
+
getUser: async () => ({ data: { user: null }, error: null }),
|
|
1047
|
+
onAuthStateChange: () => ({
|
|
1048
|
+
data: { subscription: { unsubscribe: () => undefined } },
|
|
1049
|
+
}),
|
|
1050
|
+
signInWithPassword: async () => ({ data: { user: null, session: null }, error: null }),
|
|
1051
|
+
signInWithOtp: async () => ({ data: { user: null, session: null }, error: null }),
|
|
1052
|
+
signUp: async () => ({ data: { user: null, session: null }, error: null }),
|
|
1053
|
+
signOut: async () => ({ error: null }),
|
|
1054
|
+
startAutoRefresh: () => undefined,
|
|
1055
|
+
stopAutoRefresh: () => undefined,
|
|
1056
|
+
},
|
|
1057
|
+
from: () => createSupabaseQueryBuilder(),
|
|
1058
|
+
rpc: async () => ({ data: null, error: null }),
|
|
1059
|
+
storage: {
|
|
1060
|
+
from: () => ({
|
|
1061
|
+
upload: async () => ({ data: { path: '' }, error: null }),
|
|
1062
|
+
getPublicUrl: () => ({ data: { publicUrl: '' } }),
|
|
1063
|
+
download: async () => ({ data: null, error: null }),
|
|
1064
|
+
remove: async () => ({ data: [], error: null }),
|
|
1065
|
+
}),
|
|
1066
|
+
},
|
|
1067
|
+
channel: () => {
|
|
1068
|
+
const ch = {
|
|
1069
|
+
on: () => ch,
|
|
1070
|
+
subscribe: () => ch,
|
|
1071
|
+
unsubscribe: async () => 'ok',
|
|
1072
|
+
};
|
|
1073
|
+
return ch;
|
|
1074
|
+
},
|
|
1075
|
+
removeChannel: async () => 'ok',
|
|
1076
|
+
functions: {
|
|
1077
|
+
invoke: async () => ({ data: null, error: null }),
|
|
1078
|
+
},
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
function UniversalDefaultExportComponent(props: Record<string, unknown> = {}) {
|
|
1083
|
+
if (props && typeof props === 'object') {
|
|
1084
|
+
if (typeof props.name === 'string') {
|
|
1085
|
+
return Ionicons(props as VectorIconProps);
|
|
1086
|
+
}
|
|
1087
|
+
if ('viewBox' in props || 'xmlns' in props) {
|
|
1088
|
+
return React.createElement('svg', props, props.children as React.ReactNode);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
return React.createElement(
|
|
1092
|
+
View,
|
|
1093
|
+
{ style: props?.style as never },
|
|
1094
|
+
props?.children as React.ReactNode
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
const defaultExportProperties = {
|
|
1099
|
+
...Animated,
|
|
1100
|
+
...AsyncStorage,
|
|
1101
|
+
...Constants,
|
|
1102
|
+
Ionicons,
|
|
1103
|
+
Feather,
|
|
1104
|
+
MaterialIcons,
|
|
1105
|
+
MaterialCommunityIcons,
|
|
1106
|
+
FontAwesome,
|
|
1107
|
+
FontAwesome5,
|
|
1108
|
+
FontAwesome6,
|
|
1109
|
+
AntDesign,
|
|
1110
|
+
Entypo,
|
|
1111
|
+
EvilIcons,
|
|
1112
|
+
Foundation,
|
|
1113
|
+
Octicons,
|
|
1114
|
+
SimpleLineIcons,
|
|
1115
|
+
Zocial,
|
|
1116
|
+
Fontisto,
|
|
1117
|
+
LinearGradient,
|
|
1118
|
+
BlurView,
|
|
1119
|
+
Image,
|
|
1120
|
+
ImageBackground,
|
|
1121
|
+
FlashList,
|
|
1122
|
+
Svg,
|
|
1123
|
+
ImpactFeedbackStyle,
|
|
1124
|
+
NotificationFeedbackType,
|
|
1125
|
+
impactAsync,
|
|
1126
|
+
notificationAsync,
|
|
1127
|
+
selectionAsync,
|
|
1128
|
+
useFonts,
|
|
1129
|
+
loadAsync,
|
|
1130
|
+
isLoaded,
|
|
1131
|
+
preventAutoHideAsync,
|
|
1132
|
+
hideAsync,
|
|
1133
|
+
getItemAsync,
|
|
1134
|
+
setItemAsync,
|
|
1135
|
+
deleteItemAsync,
|
|
1136
|
+
setStringAsync,
|
|
1137
|
+
getStringAsync,
|
|
1138
|
+
openURL,
|
|
1139
|
+
createURL,
|
|
1140
|
+
create,
|
|
1141
|
+
useStore,
|
|
1142
|
+
QueryClient,
|
|
1143
|
+
QueryClientProvider,
|
|
1144
|
+
useQueryClient,
|
|
1145
|
+
useQuery,
|
|
1146
|
+
useInfiniteQuery,
|
|
1147
|
+
useMutation,
|
|
1148
|
+
createClient,
|
|
1149
|
+
};
|
|
1150
|
+
|
|
1151
|
+
Object.assign(UniversalDefaultExportComponent, defaultExportProperties);
|
|
1152
|
+
|
|
1153
|
+
const defaultExportProxy = new Proxy(UniversalDefaultExportComponent, {
|
|
1154
|
+
get(target, prop) {
|
|
1155
|
+
if (prop in target) {
|
|
1156
|
+
return (target as unknown as Record<string | symbol, unknown>)[prop];
|
|
1157
|
+
}
|
|
1158
|
+
if (prop in defaultExportProperties) {
|
|
1159
|
+
return defaultExportProperties[prop as keyof typeof defaultExportProperties];
|
|
1160
|
+
}
|
|
1161
|
+
if (typeof prop === 'string' && /^[A-Z]/.test(prop)) {
|
|
1162
|
+
return createVectorIconComponent(prop);
|
|
1163
|
+
}
|
|
1164
|
+
return () => undefined;
|
|
1165
|
+
},
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
export default defaultExportProxy;
|