zelune 1.6.2 → 1.6.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/bin/cli.mjs +13 -54
  3. package/dist/assets/CheckoutScreen-6IdrpKgm.js +229 -0
  4. package/dist/assets/HomeScreen-Dxe9L4I2.js +316 -0
  5. package/dist/assets/LoginScreen-Dp1awI4F.js +189 -0
  6. package/dist/assets/ProductDetailScreen-Wa5_nlRP.js +196 -0
  7. package/dist/assets/ProfileScreen-riAU6vVh.js +185 -0
  8. package/dist/assets/index-hEzd4JVy.js +44697 -0
  9. package/{index.html → dist/index.html} +3 -7
  10. package/mcp/server.mjs +1370 -34
  11. package/package.json +10 -17
  12. package/plugin.json +1 -1
  13. package/socket.yml +11 -0
  14. package/mcp/server.ts +0 -446
  15. package/plugins/viteReactNativeFallbackPlugin.ts +0 -519
  16. package/plugins/viteRnSourceInject.ts +0 -117
  17. package/plugins/viteVirtualScreensPlugin.ts +0 -216
  18. package/src/canvas/CanvasApp.tsx +0 -1655
  19. package/src/canvas/FlowArrowsLayer.tsx +0 -239
  20. package/src/canvas/InspectorPanel.tsx +0 -1494
  21. package/src/canvas/ScreenArtboard.tsx +0 -1491
  22. package/src/canvas/types.ts +0 -23
  23. package/src/main.tsx +0 -80
  24. package/src/runtime/MockNavigationContext.tsx +0 -1795
  25. package/src/runtime/ScreenErrorBoundary.tsx +0 -86
  26. package/src/runtime/nativewindShim.ts +0 -997
  27. package/src/runtime/reactNativeShim.ts +0 -240
  28. package/src/screens/CheckoutScreen.tsx +0 -229
  29. package/src/screens/HomeScreen.tsx +0 -288
  30. package/src/screens/LoginScreen.tsx +0 -176
  31. package/src/screens/ProductDetailScreen.tsx +0 -207
  32. package/src/screens/ProfileScreen.tsx +0 -172
  33. package/src/screens/index.ts +0 -1
  34. package/src/server/apiMiddleware.ts +0 -375
  35. package/src/server/astEngine.ts +0 -2553
  36. package/src/vite-env.d.ts +0 -7
  37. package/tsconfig.json +0 -23
  38. package/vite.config.ts +0 -340
  39. /package/{src/styles.css → dist/assets/index-C7nrS82N.css} +0 -0
@@ -1,1795 +0,0 @@
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';
14
- import { withNativeWind, resolveTailwindClassNameToStyle } from './nativewindShim';
15
-
16
- declare global {
17
- interface Window {
18
- __ZELUNE_PUBLIC_ENV__?: Record<string, string>;
19
- }
20
- }
21
-
22
- if (typeof window !== 'undefined') {
23
- const baseEnv: Record<string, string> = window.__ZELUNE_PUBLIC_ENV__ ?? {
24
- NODE_ENV: 'development',
25
- EXPO_PUBLIC_PLATFORM: 'web',
26
- };
27
- const envProxy = new Proxy(baseEnv, {
28
- get(target, prop) {
29
- if (typeof prop !== 'string') return Reflect.get(target, prop);
30
- if (prop in target && target[prop] !== undefined && target[prop] !== '') {
31
- return target[prop];
32
- }
33
- return 'zelune-preview';
34
- },
35
- });
36
-
37
- const createAssetStub = (): unknown => {
38
- const fn = () => proxy;
39
- const proxy: unknown = new Proxy(fn, {
40
- get(_t, prop) {
41
- if (prop === Symbol.toPrimitive) return (hint: string) => (hint === 'number' ? 0 : '');
42
- if (prop === 'valueOf') return () => 0;
43
- if (prop === 'toString') return () => '';
44
- if (prop === 'uri' || prop === 'default') return '';
45
- return proxy;
46
- },
47
- });
48
- return proxy;
49
- };
50
-
51
- const win = window as unknown as Record<string, unknown>;
52
- win.global = window;
53
- win.__DEV__ = true;
54
- if (!win.process || typeof win.process !== 'object') {
55
- win.process = {
56
- env: envProxy,
57
- platform: 'browser',
58
- version: '',
59
- cwd: () => '/',
60
- };
61
- } else {
62
- (win.process as Record<string, unknown>).env = envProxy;
63
- }
64
- const reqProp = ['req', 'uire'].join('');
65
- if (typeof win[reqProp] !== 'function') {
66
- win[reqProp] = (modId: unknown) => {
67
- if (typeof modId === 'string' && /\.(png|jpe?g|gif|webp|svg|avif|bmp)$/i.test(modId)) {
68
- return { uri: modId, default: modId };
69
- }
70
- return createAssetStub();
71
- };
72
- }
73
- }
74
-
75
- export interface NavigationController {
76
- navigate: (targetRoute: string, params?: Record<string, unknown>) => void;
77
- goBack: () => void;
78
- push: (targetRoute: string, params?: Record<string, unknown>) => void;
79
- replace: (targetRoute: string, params?: Record<string, unknown>) => void;
80
- back: () => void;
81
- setOptions: (options?: Record<string, unknown>) => void;
82
- canGoBack: () => boolean;
83
- dispatch: (action?: unknown) => void;
84
- reset: (state?: unknown) => void;
85
- addListener: (event: string, callback: () => void) => () => void;
86
- }
87
-
88
- interface MockNavigationContextValue {
89
- currentRoute: string;
90
- params: Record<string, unknown>;
91
- navigation: NavigationController;
92
- }
93
-
94
- function normalizeNavTarget(raw: string): string {
95
- const cleaned = String(raw ?? '')
96
- .replace(/^\/+/, '')
97
- .replace(/\([^)]+\)\/?/g, '')
98
- .replace(/\[\.\.\.([^\]]+)\]/g, 'CatchAll_$1')
99
- .replace(/\[([^\]]+)\]/g, 'By_$1')
100
- .replace(/Screen$/, '')
101
- .replace(/\/index$/, '');
102
- if (!cleaned || cleaned === 'index') return 'Home';
103
- if (cleaned.includes('-') || cleaned.includes('/') || cleaned.includes('_') || cleaned === cleaned.toLowerCase()) {
104
- return cleaned
105
- .split(/[-_/]/)
106
- .filter(Boolean)
107
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
108
- .join('');
109
- }
110
- return cleaned;
111
- }
112
-
113
- const noopNavigation: NavigationController = {
114
- navigate: () => undefined,
115
- goBack: () => undefined,
116
- push: () => undefined,
117
- replace: () => undefined,
118
- back: () => undefined,
119
- setOptions: () => undefined,
120
- canGoBack: () => true,
121
- dispatch: () => undefined,
122
- reset: () => undefined,
123
- addListener: () => () => undefined,
124
- };
125
-
126
- const MockNavigationContext = createContext<MockNavigationContextValue>({
127
- currentRoute: 'Home',
128
- params: {},
129
- navigation: noopNavigation,
130
- });
131
-
132
- export interface MockNavigationProviderProps {
133
- routeName: string;
134
- params?: Record<string, unknown>;
135
- onNavigate?: (fromScreen: string, toScreen: string, params?: Record<string, unknown>) => void;
136
- children: React.ReactNode;
137
- }
138
-
139
- export const MockNavigationProvider: React.FC<MockNavigationProviderProps> = ({
140
- routeName,
141
- params = {},
142
- onNavigate,
143
- children,
144
- }) => {
145
- const value = useMemo<MockNavigationContextValue>(() => {
146
- const trigger = (targetRoute: string, navParams?: Record<string, unknown>) => {
147
- onNavigate?.(routeName, normalizeNavTarget(targetRoute), navParams);
148
- };
149
- return {
150
- currentRoute: routeName,
151
- params,
152
- navigation: {
153
- navigate: trigger,
154
- push: trigger,
155
- replace: trigger,
156
- goBack: () => onNavigate?.(routeName, 'Home'),
157
- back: () => onNavigate?.(routeName, 'Home'),
158
- setOptions: () => undefined,
159
- canGoBack: () => true,
160
- dispatch: () => undefined,
161
- reset: () => undefined,
162
- addListener: () => () => undefined,
163
- },
164
- };
165
- }, [routeName, params, onNavigate]);
166
-
167
- return (
168
- <MockNavigationContext.Provider value={value}>
169
- {children}
170
- </MockNavigationContext.Provider>
171
- );
172
- };
173
-
174
- // ============================================================================
175
- // 1. React Navigation Shims (@react-navigation/native, native-stack, bottom-tabs)
176
- // ============================================================================
177
- export function useNavigation(): NavigationController {
178
- return useContext(MockNavigationContext).navigation;
179
- }
180
-
181
- export function useRoute(): { key: string; name: string; params: Record<string, unknown> } {
182
- const ctx = useContext(MockNavigationContext);
183
- return {
184
- key: ctx.currentRoute,
185
- name: ctx.currentRoute,
186
- params: ctx.params,
187
- };
188
- }
189
-
190
- export function useFocusEffect(effect: () => void | (() => void)): void {
191
- const ctx = useContext(MockNavigationContext);
192
- const effectRef = useRef(effect);
193
- effectRef.current = effect;
194
- useEffect(() => {
195
- try {
196
- const cleanup = effectRef.current();
197
- return typeof cleanup === 'function' ? cleanup : undefined;
198
- } catch {
199
- return undefined;
200
- }
201
- }, [ctx.currentRoute]);
202
- }
203
-
204
- export function useIsFocused(): boolean {
205
- return true;
206
- }
207
-
208
- export function useScrollToTop(): void {}
209
-
210
- export const NavigationContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
211
- <>{children}</>
212
- );
213
-
214
- export const CommonActions = {
215
- navigate: (payload: unknown) => ({ type: 'NAVIGATE', payload }),
216
- reset: (payload: unknown) => ({ type: 'RESET', payload }),
217
- goBack: () => ({ type: 'GO_BACK' }),
218
- };
219
-
220
- export const StackActions = {
221
- push: (routeName: string, params?: unknown) => ({ type: 'PUSH', payload: { routeName, params } }),
222
- replace: (routeName: string, params?: unknown) => ({
223
- type: 'REPLACE',
224
- payload: { routeName, params },
225
- }),
226
- pop: (count = 1) => ({ type: 'POP', payload: { count } }),
227
- popToTop: () => ({ type: 'POP_TO_TOP' }),
228
- };
229
-
230
- function createNavigatorShim() {
231
- const Navigator: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
232
- const Screen: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
233
- const Group: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
234
- return { Navigator, Screen, Group };
235
- }
236
-
237
- export const createNativeStackNavigator = createNavigatorShim;
238
- export const createStackNavigator = createNavigatorShim;
239
- export const createBottomTabNavigator = createNavigatorShim;
240
- export const createDrawerNavigator = createNavigatorShim;
241
- export const createMaterialTopTabNavigator = createNavigatorShim;
242
-
243
- export const DefaultTheme = {
244
- dark: false,
245
- colors: {
246
- primary: '#6366F1',
247
- background: '#F8FAFC',
248
- card: '#FFFFFF',
249
- text: '#0F172A',
250
- border: '#E2E8F0',
251
- notification: '#EF4444',
252
- },
253
- };
254
-
255
- export const DarkTheme = {
256
- dark: true,
257
- colors: {
258
- primary: '#6366F1',
259
- background: '#09090B',
260
- card: '#18181B',
261
- text: '#F8FAFC',
262
- border: '#27272A',
263
- notification: '#EF4444',
264
- },
265
- };
266
-
267
- export const ThemeProvider: React.FC<{ value?: unknown; children?: React.ReactNode }> = ({
268
- children,
269
- }) => <>{children}</>;
270
-
271
- export function useTheme() {
272
- return DarkTheme;
273
- }
274
-
275
- export function useNavigationContainerRef() {
276
- return { current: noopNavigation, isReady: () => true };
277
- }
278
-
279
- // ============================================================================
280
- // 2. Expo Router Shims (expo-router)
281
- // ============================================================================
282
- export function useRouter(): NavigationController {
283
- return useContext(MockNavigationContext).navigation;
284
- }
285
-
286
- export const router: NavigationController = noopNavigation;
287
-
288
- export function useLocalSearchParams<
289
- T extends Record<string, unknown> = Record<string, string>
290
- >(): T {
291
- const ctx = useContext(MockNavigationContext);
292
- return ctx.params as T;
293
- }
294
-
295
- export function useGlobalSearchParams<
296
- T extends Record<string, unknown> = Record<string, string>
297
- >(): T {
298
- const ctx = useContext(MockNavigationContext);
299
- return ctx.params as T;
300
- }
301
-
302
- export function usePathname(): string {
303
- const ctx = useContext(MockNavigationContext);
304
- return `/${ctx.currentRoute.toLowerCase()}`;
305
- }
306
-
307
- export function useSegments(): string[] {
308
- const ctx = useContext(MockNavigationContext);
309
- return useMemo(() => [ctx.currentRoute.toLowerCase()], [ctx.currentRoute]);
310
- }
311
-
312
- export function useRootNavigationState() {
313
- return { key: 'root', stale: false };
314
- }
315
-
316
- export const Link: React.FC<{
317
- href: string | { pathname: string; params?: Record<string, unknown> };
318
- asChild?: boolean;
319
- children?: React.ReactNode;
320
- style?: unknown;
321
- }> = ({ href, children, style }) => {
322
- const nav = useContext(MockNavigationContext).navigation;
323
- const target = typeof href === 'string' ? href : href?.pathname ?? 'Home';
324
- return (
325
- <TouchableOpacity
326
- activeOpacity={0.78}
327
- style={style as never}
328
- onPress={() => nav.push(target)}
329
- >
330
- {children}
331
- </TouchableOpacity>
332
- );
333
- };
334
-
335
- export const Redirect: React.FC<{ href: string }> = () => null;
336
-
337
- const NoopLayoutScreen: React.FC<{ children?: React.ReactNode; screenOptions?: unknown }> & {
338
- Screen: React.FC<{ name?: string; options?: unknown }>;
339
- } = ({ children }) => <>{children}</>;
340
- NoopLayoutScreen.Screen = () => null;
341
-
342
- export const Stack = NoopLayoutScreen;
343
- export const Tabs = NoopLayoutScreen;
344
- export const Drawer = NoopLayoutScreen;
345
- export const Slot: React.FC<{ children?: React.ReactNode }> = ({ children }) => <>{children}</>;
346
- export const SplashScreen = {
347
- preventAutoHideAsync: async () => true,
348
- hideAsync: async () => true,
349
- };
350
-
351
- // ============================================================================
352
- // 3. React Native Safe Area Context Shims (react-native-safe-area-context)
353
- // ============================================================================
354
- export const SafeAreaProvider: React.FC<{
355
- children?: React.ReactNode;
356
- style?: unknown;
357
- className?: string;
358
- }> = ({ children, style, className, ...rest }) => (
359
- <View className={className as never} style={[{ flex: 1 }, style as never]} {...rest}>
360
- {children}
361
- </View>
362
- );
363
-
364
- export const SafeAreaView: React.FC<{
365
- children?: React.ReactNode;
366
- style?: unknown;
367
- className?: string;
368
- edges?: string[];
369
- }> = ({ children, style, className, edges: _edges, ...rest }) => (
370
- <View className={className as never} style={[{ flex: 1 }, style as never]} {...rest}>
371
- {children}
372
- </View>
373
- );
374
-
375
- export function useSafeAreaInsets(): { top: number; right: number; bottom: number; left: number } {
376
- return { top: 0, right: 0, bottom: 0, left: 0 };
377
- }
378
-
379
- export function useSafeAreaFrame(): { x: number; y: number; width: number; height: number } {
380
- return { x: 0, y: 0, width: 393, height: 852 };
381
- }
382
-
383
- export const SafeAreaInsetsContext = createContext({ top: 0, right: 0, bottom: 0, left: 0 });
384
- export const SafeAreaFrameContext = createContext({ x: 0, y: 0, width: 393, height: 852 });
385
-
386
- export function withSafeAreaInsets<P extends object>(Component: React.ComponentType<P>) {
387
- return function WithSafeAreaInsetsWrapper(props: P) {
388
- return <Component {...props} insets={{ top: 0, right: 0, bottom: 0, left: 0 }} />;
389
- };
390
- }
391
-
392
- export const initialWindowMetrics = {
393
- frame: { x: 0, y: 0, width: 393, height: 852 },
394
- insets: { top: 0, right: 0, bottom: 0, left: 0 },
395
- };
396
-
397
- // ============================================================================
398
- // 4. Expo Status Bar Shim (expo-status-bar)
399
- // ============================================================================
400
- export const StatusBar: React.FC<{
401
- style?: string;
402
- hidden?: boolean;
403
- backgroundColor?: string;
404
- translucent?: boolean;
405
- }> = () => null;
406
-
407
- // ============================================================================
408
- // 5. @expo/vector-icons Shims
409
- // ============================================================================
410
- export interface VectorIconProps {
411
- name?: string;
412
- size?: number;
413
- color?: string;
414
- style?: unknown;
415
- onPress?: () => void;
416
- }
417
-
418
- const ICON_GLYPH_MAP: Record<string, string> = {
419
- 'arrow-back': '←',
420
- 'arrow-left': '←',
421
- 'chevron-back': '‹',
422
- 'chevron-left': '‹',
423
- 'arrow-forward': '→',
424
- 'arrow-right': '→',
425
- 'chevron-forward': '›',
426
- 'chevron-right': '›',
427
- 'chevron-down': '▾',
428
- 'chevron-up': '▴',
429
- close: '✕',
430
- 'close-circle': '⊗',
431
- x: '✕',
432
- add: '+',
433
- plus: '+',
434
- 'add-circle': '⊕',
435
- remove: '−',
436
- minus: '−',
437
- check: '✓',
438
- checkmark: '✓',
439
- 'checkmark-circle': '✓',
440
- search: '⌕',
441
- home: '⌂',
442
- person: '◉',
443
- user: '◉',
444
- settings: '⚙',
445
- cog: '⚙',
446
- bell: '🔔',
447
- notifications: '🔔',
448
- heart: '♥',
449
- 'heart-outline': '♡',
450
- star: '★',
451
- 'star-outline': '☆',
452
- cart: '🛒',
453
- 'shopping-cart': '🛒',
454
- bag: '🛍',
455
- lock: '🔒',
456
- 'lock-closed': '🔒',
457
- mail: '✉',
458
- eye: '👁',
459
- 'eye-off': '◡',
460
- trash: '🗑',
461
- edit: '✎',
462
- pencil: '✎',
463
- share: '↗',
464
- info: 'ℹ',
465
- warning: '⚠',
466
- alert: '⚠',
467
- menu: '☰',
468
- filter: '⊶',
469
- calendar: '📅',
470
- time: '⏱',
471
- clock: '⏱',
472
- location: '⌖',
473
- 'map-pin': '⌖',
474
- camera: '📷',
475
- image: '🖼',
476
- send: '➤',
477
- refresh: '↻',
478
- sync: '↻',
479
- wallet: '💳',
480
- card: '💳',
481
- cash: '¤',
482
- 'trending-up': '↗',
483
- 'trending-down': '↘',
484
- };
485
-
486
- export function createVectorIconComponent(familyName: string) {
487
- const IconComp: React.FC<VectorIconProps> & {
488
- glyphMap?: Record<string, number>;
489
- loadFont?: () => Promise<void>;
490
- } = ({ name = '', size = 18, color = '#94A3B8', style, onPress }) => {
491
- const cleanName = String(name)
492
- .toLowerCase()
493
- .replace(/^ios-|^md-|^logo-/, '')
494
- .replace(/-outline$|-sharp$/, '');
495
- const symbol = ICON_GLYPH_MAP[String(name).toLowerCase()] ?? ICON_GLYPH_MAP[cleanName] ?? '◆';
496
- return (
497
- <Text
498
- onPress={onPress}
499
- accessibilityLabel={`${familyName}:${name}`}
500
- style={[
501
- {
502
- fontSize: size * 0.85,
503
- lineHeight: size,
504
- width: size,
505
- height: size,
506
- color,
507
- textAlign: 'center',
508
- includeFontPadding: false,
509
- } as never,
510
- style as never,
511
- ]}
512
- >
513
- {symbol}
514
- </Text>
515
- );
516
- };
517
- IconComp.glyphMap = {};
518
- IconComp.loadFont = async () => undefined;
519
- return IconComp;
520
- }
521
-
522
- export const Ionicons = createVectorIconComponent('Ionicons');
523
- export const Feather = createVectorIconComponent('Feather');
524
- export const MaterialIcons = createVectorIconComponent('MaterialIcons');
525
- export const MaterialCommunityIcons = createVectorIconComponent('MaterialCommunityIcons');
526
- export const FontAwesome = createVectorIconComponent('FontAwesome');
527
- export const FontAwesome5 = createVectorIconComponent('FontAwesome5');
528
- export const FontAwesome6 = createVectorIconComponent('FontAwesome6');
529
- export const AntDesign = createVectorIconComponent('AntDesign');
530
- export const Entypo = createVectorIconComponent('Entypo');
531
- export const EvilIcons = createVectorIconComponent('EvilIcons');
532
- export const Foundation = createVectorIconComponent('Foundation');
533
- export const Octicons = createVectorIconComponent('Octicons');
534
- export const SimpleLineIcons = createVectorIconComponent('SimpleLineIcons');
535
- export const Zocial = createVectorIconComponent('Zocial');
536
- export const Fontisto = createVectorIconComponent('Fontisto');
537
- export function createIconSet() {
538
- return createVectorIconComponent('CustomIcon');
539
- }
540
- export function createIconSetFromIcoMoon() {
541
- return createVectorIconComponent('IcoMoon');
542
- }
543
- export function createIconSetFromFontello() {
544
- return createVectorIconComponent('Fontello');
545
- }
546
-
547
- // ============================================================================
548
- // 6. Expo Linear Gradient, Blur, Image & FlashList Shims
549
- // ============================================================================
550
- export const LinearGradient: React.FC<{
551
- colors?: readonly string[] | string[];
552
- locations?: readonly number[] | number[];
553
- start?: { x: number; y: number } | [number, number];
554
- end?: { x: number; y: number } | [number, number];
555
- style?: unknown;
556
- className?: string;
557
- children?: React.ReactNode;
558
- }> = ({
559
- colors = ['#1E293B', '#0F172A'],
560
- locations: _locations,
561
- start: _start,
562
- end: _end,
563
- style,
564
- className,
565
- children,
566
- ...rest
567
- }) => {
568
- const safeColors = Array.isArray(colors) && colors.length >= 2 ? colors : ['#1E293B', '#0F172A'];
569
- return (
570
- <View
571
- className={className as never}
572
- style={[
573
- {
574
- backgroundColor: safeColors[0],
575
- backgroundImage: `linear-gradient(135deg, ${safeColors.join(', ')})`,
576
- } as never,
577
- style as never,
578
- ]}
579
- {...rest}
580
- >
581
- {children}
582
- </View>
583
- );
584
- };
585
-
586
- export const BlurView: React.FC<{
587
- intensity?: number;
588
- tint?: string;
589
- style?: unknown;
590
- className?: string;
591
- children?: React.ReactNode;
592
- }> = ({ intensity = 40, tint = 'dark', style, className, children, ...rest }) => {
593
- const bg = tint === 'light' ? 'rgba(255, 255, 255, 0.65)' : 'rgba(15, 23, 42, 0.65)';
594
- return (
595
- <View
596
- className={className as never}
597
- style={[
598
- {
599
- backgroundColor: bg,
600
- backdropFilter: `blur(${Math.round(intensity / 4)}px)`,
601
- } as never,
602
- style as never,
603
- ]}
604
- {...rest}
605
- >
606
- {children}
607
- </View>
608
- );
609
- };
610
-
611
- export const Image: React.FC<Record<string, unknown>> = ({
612
- contentFit,
613
- resizeMode,
614
- source,
615
- placeholder,
616
- transition: _transition,
617
- className,
618
- style,
619
- ...rest
620
- }) => {
621
- let uri = '';
622
- if (typeof source === 'string') {
623
- uri = source;
624
- } else if (Array.isArray(source) && source[0] && typeof source[0] === 'object') {
625
- uri = String((source[0] as Record<string, unknown>).uri ?? '');
626
- } else if (source && typeof source === 'object') {
627
- uri = String((source as Record<string, unknown>).uri ?? '');
628
- }
629
- const placeholderBg =
630
- placeholder && typeof placeholder === 'object' && 'color' in placeholder
631
- ? String((placeholder as Record<string, unknown>).color ?? 'transparent')
632
- : undefined;
633
- const fit = String(contentFit ?? resizeMode ?? 'cover') as React.CSSProperties['objectFit'];
634
-
635
- return (
636
- <View
637
- className={className as never}
638
- style={[
639
- {
640
- overflow: 'hidden',
641
- ...(placeholderBg ? { backgroundColor: placeholderBg } : {}),
642
- } as never,
643
- style as never,
644
- ]}
645
- {...(rest as Record<string, unknown>)}
646
- >
647
- {uri ? (
648
- <img
649
- src={uri}
650
- alt=""
651
- draggable={false}
652
- style={{
653
- width: '100%',
654
- height: '100%',
655
- objectFit: fit,
656
- display: 'block',
657
- }}
658
- />
659
- ) : null}
660
- </View>
661
- );
662
- };
663
-
664
- export const ImageBackground = RNImageBackground;
665
- export const FlashList = RNFlatList;
666
-
667
- // ============================================================================
668
- // 7. React Native SVG Shims (react-native-svg)
669
- // ============================================================================
670
- function createSvgDomElement(tagName: string) {
671
- return React.forwardRef< Element, Record<string, unknown>>(({ children, ...props }, ref) =>
672
- React.createElement(tagName, { ...props, ref }, children as React.ReactNode)
673
- );
674
- }
675
-
676
- export const Svg = createSvgDomElement('svg');
677
- export const Circle = createSvgDomElement('circle');
678
- export const Ellipse = createSvgDomElement('ellipse');
679
- export const G = createSvgDomElement('g');
680
- export const SvgText = createSvgDomElement('text');
681
- export const TSpan = createSvgDomElement('tspan');
682
- export const TextPath = createSvgDomElement('textPath');
683
- export const Path = createSvgDomElement('path');
684
- export const Polygon = createSvgDomElement('polygon');
685
- export const Polyline = createSvgDomElement('polyline');
686
- export const Line = createSvgDomElement('line');
687
- export const Rect = createSvgDomElement('rect');
688
- export const Use = createSvgDomElement('use');
689
- export const SvgImage = createSvgDomElement('image');
690
- export const Symbol = createSvgDomElement('symbol');
691
- export const Defs = createSvgDomElement('defs');
692
- export const RadialGradient = createSvgDomElement('radialGradient');
693
- export const Stop = createSvgDomElement('stop');
694
- export const ClipPath = createSvgDomElement('clipPath');
695
- export const Pattern = createSvgDomElement('pattern');
696
- export const Mask = createSvgDomElement('mask');
697
- export const ForeignObject = createSvgDomElement('foreignObject');
698
- export const SvgXml: React.FC<{ xml?: string; width?: number | string; height?: number | string }> =
699
- ({ xml = '', width = 24, height = 24 }) => (
700
- <span
701
- style={{ display: 'inline-flex', width, height }}
702
- dangerouslySetInnerHTML={{ __html: xml }}
703
- />
704
- );
705
- export const SvgUri: React.FC<{ uri?: string; width?: number; height?: number }> = ({
706
- uri,
707
- width = 24,
708
- height = 24,
709
- }) => <RNImage source={{ uri }} style={{ width, height }} />;
710
-
711
- // ============================================================================
712
- // 8. React Native Reanimated & Gesture Handler Shims
713
- // ============================================================================
714
- function createChainableAnimationStub(): Record<string, unknown> {
715
- const proxy: Record<string, unknown> = new Proxy(
716
- {},
717
- {
718
- get(_target, prop) {
719
- if (prop === 'build') return () => ({});
720
- return () => proxy;
721
- },
722
- }
723
- );
724
- return proxy;
725
- }
726
-
727
- export const FadeIn = createChainableAnimationStub();
728
- export const FadeInDown = createChainableAnimationStub();
729
- export const FadeInUp = createChainableAnimationStub();
730
- export const FadeInLeft = createChainableAnimationStub();
731
- export const FadeInRight = createChainableAnimationStub();
732
- export const FadeOut = createChainableAnimationStub();
733
- export const FadeOutDown = createChainableAnimationStub();
734
- export const FadeOutUp = createChainableAnimationStub();
735
- export const SlideInDown = createChainableAnimationStub();
736
- export const SlideInUp = createChainableAnimationStub();
737
- export const SlideInLeft = createChainableAnimationStub();
738
- export const SlideInRight = createChainableAnimationStub();
739
- export const SlideOutDown = createChainableAnimationStub();
740
- export const SlideOutUp = createChainableAnimationStub();
741
- export const SlideOutLeft = createChainableAnimationStub();
742
- export const SlideOutRight = createChainableAnimationStub();
743
- export const ZoomIn = createChainableAnimationStub();
744
- export const ZoomOut = createChainableAnimationStub();
745
- export const Layout = createChainableAnimationStub();
746
- export const LinearTransition = createChainableAnimationStub();
747
- export const SequencedTransition = createChainableAnimationStub();
748
- export const FadingTransition = createChainableAnimationStub();
749
-
750
- export function useSharedValue<T>(initialValue: T): { value: T } {
751
- const ref = useRef<{ value: T }>({ value: initialValue });
752
- return ref.current;
753
- }
754
-
755
- export function useAnimatedStyle<T extends Record<string, unknown>>(
756
- updater: () => T
757
- ): T {
758
- try {
759
- return updater();
760
- } catch {
761
- return {} as T;
762
- }
763
- }
764
-
765
- export function useDerivedValue<T>(updater: () => T): { value: T } {
766
- try {
767
- return { value: updater() };
768
- } catch {
769
- return { value: undefined as unknown as T };
770
- }
771
- }
772
-
773
- export function useAnimatedProps<T extends Record<string, unknown>>(updater: () => T): T {
774
- try {
775
- return updater();
776
- } catch {
777
- return {} as T;
778
- }
779
- }
780
-
781
- export function useAnimatedScrollHandler() {
782
- return () => undefined;
783
- }
784
-
785
- export function useAnimatedRef() {
786
- return useRef(null);
787
- }
788
-
789
- export function useAnimatedGestureHandler() {
790
- return () => undefined;
791
- }
792
-
793
- export function withTiming<T>(toValue: T, _config?: unknown, callback?: (finished: boolean) => void): T {
794
- callback?.(true);
795
- return toValue;
796
- }
797
-
798
- export function withSpring<T>(toValue: T, _config?: unknown, callback?: (finished: boolean) => void): T {
799
- callback?.(true);
800
- return toValue;
801
- }
802
-
803
- export function withDelay<T>(_delayMs: number, animationValue: T): T {
804
- return animationValue;
805
- }
806
-
807
- export function withSequence<T>(...animations: T[]): T {
808
- return animations[animations.length - 1];
809
- }
810
-
811
- export function withRepeat<T>(animationValue: T): T {
812
- return animationValue;
813
- }
814
-
815
- export function cancelAnimation(): void {}
816
-
817
- export function runOnJS<T extends (...args: never[]) => unknown>(fn: T): T {
818
- return fn;
819
- }
820
-
821
- export function runOnUI<T extends (...args: never[]) => unknown>(fn: T): T {
822
- return fn;
823
- }
824
-
825
- export function interpolate(
826
- value: number,
827
- inputRange: number[],
828
- outputRange: number[]
829
- ): number {
830
- if (!inputRange?.length || !outputRange?.length) return value;
831
- if (value <= inputRange[0]) return outputRange[0];
832
- if (value >= inputRange[inputRange.length - 1]) return outputRange[outputRange.length - 1];
833
- return outputRange[0];
834
- }
835
-
836
- export const Extrapolation = {
837
- IDENTITY: 'identity',
838
- CLAMP: 'clamp',
839
- EXTEND: 'extend',
840
- };
841
- export const Extrapolate = Extrapolation;
842
-
843
- export const Easing = {
844
- linear: (t: number) => t,
845
- ease: (t: number) => t,
846
- quad: (t: number) => t * t,
847
- cubic: (t: number) => t * t * t,
848
- bezier: () => (t: number) => t,
849
- in: (fn: (t: number) => number) => fn,
850
- out: (fn: (t: number) => number) => fn,
851
- inOut: (fn: (t: number) => number) => fn,
852
- };
853
-
854
- export function createAnimatedComponent<P extends object>(Component: React.ComponentType<P>) {
855
- return withNativeWind(
856
- Component as unknown as React.ComponentType<Record<string, unknown>>
857
- ) as unknown as React.ComponentType<P>;
858
- }
859
-
860
- export const Animated = {
861
- View,
862
- Text,
863
- Image: RNImage,
864
- ScrollView: RNScrollView,
865
- FlatList: RNFlatList,
866
- createAnimatedComponent,
867
- Value: class {
868
- private _val: number;
869
- constructor(v = 0) {
870
- this._val = v;
871
- }
872
- setValue(v: number) {
873
- this._val = v;
874
- }
875
- interpolate() {
876
- return this._val;
877
- }
878
- },
879
- };
880
-
881
- // React Native Gesture Handler Shims
882
- export const GestureHandlerRootView: React.FC<{
883
- children?: React.ReactNode;
884
- style?: unknown;
885
- className?: string;
886
- }> = ({ children, style, className, ...rest }) => (
887
- <View className={className as never} style={[{ flex: 1 }, style as never]} {...rest}>
888
- {children}
889
- </View>
890
- );
891
-
892
- export const ScrollView = RNScrollView;
893
- export const FlatList = RNFlatList;
894
- export { TouchableOpacity, TouchableHighlight, TouchableWithoutFeedback, Pressable };
895
- export const Swipeable: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
896
- <>{children}</>
897
- );
898
- export const DrawerLayout: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
899
- <>{children}</>
900
- );
901
- export const PanGestureHandler: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
902
- <>{children}</>
903
- );
904
- export const TapGestureHandler: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
905
- <>{children}</>
906
- );
907
- export const LongPressGestureHandler: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
908
- <>{children}</>
909
- );
910
- export const GestureDetector: React.FC<{ gesture?: unknown; children?: React.ReactNode }> = ({
911
- children,
912
- }) => <>{children}</>;
913
- export const Gesture = {
914
- Pan: () => createChainableAnimationStub(),
915
- Tap: () => createChainableAnimationStub(),
916
- LongPress: () => createChainableAnimationStub(),
917
- Pinch: () => createChainableAnimationStub(),
918
- Rotation: () => createChainableAnimationStub(),
919
- Fling: () => createChainableAnimationStub(),
920
- Simultaneous: () => createChainableAnimationStub(),
921
- Exclusive: () => createChainableAnimationStub(),
922
- Race: () => createChainableAnimationStub(),
923
- };
924
- export const State = {
925
- UNDETERMINED: 0,
926
- FAILED: 1,
927
- BEGAN: 2,
928
- CANCELLED: 3,
929
- ACTIVE: 4,
930
- END: 5,
931
- };
932
- export const Directions = {
933
- RIGHT: 1,
934
- LEFT: 2,
935
- UP: 4,
936
- DOWN: 8,
937
- };
938
-
939
- // ============================================================================
940
- // 9. Common Expo SDK Runtime Shims (Haptics, Constants, Font, Storage, etc.)
941
- // ============================================================================
942
- export const ImpactFeedbackStyle = { Light: 'light', Medium: 'medium', Heavy: 'heavy' };
943
- export const NotificationFeedbackType = {
944
- Success: 'success',
945
- Warning: 'warning',
946
- Error: 'error',
947
- };
948
- export async function impactAsync(): Promise<void> {}
949
- export async function notificationAsync(): Promise<void> {}
950
- export async function selectionAsync(): Promise<void> {}
951
-
952
- export const Constants = {
953
- expoConfig: { name: 'Zelune App', slug: 'zelune-app', extra: {} },
954
- manifest: { extra: {} },
955
- statusBarHeight: 0,
956
- systemFonts: [],
957
- appOwnership: 'expo',
958
- executionEnvironment: 'storeClient',
959
- };
960
-
961
- export function useFonts(): [boolean, null] {
962
- return [true, null];
963
- }
964
- export async function loadAsync(): Promise<void> {}
965
- export function isLoaded(): boolean {
966
- return true;
967
- }
968
- export async function preventAutoHideAsync(): Promise<boolean> {
969
- return true;
970
- }
971
- export async function hideAsync(): Promise<boolean> {
972
- return true;
973
- }
974
-
975
- const memoryStorage = new Map<string, string>();
976
- export const AsyncStorage = {
977
- getItem: async (key: string) => memoryStorage.get(key) ?? null,
978
- setItem: async (key: string, value: string) => {
979
- memoryStorage.set(key, value);
980
- },
981
- removeItem: async (key: string) => {
982
- memoryStorage.delete(key);
983
- },
984
- clear: async () => {
985
- memoryStorage.clear();
986
- },
987
- getAllKeys: async () => Array.from(memoryStorage.keys()),
988
- multiGet: async (keys: string[]) => keys.map((k) => [k, memoryStorage.get(k) ?? null]),
989
- multiSet: async (pairs: [string, string][]) => {
990
- pairs.forEach(([k, v]) => memoryStorage.set(k, v));
991
- },
992
- multiRemove: async (keys: string[]) => {
993
- keys.forEach((k) => memoryStorage.delete(k));
994
- },
995
- };
996
-
997
- export async function getItemAsync(key: string): Promise<string | null> {
998
- return memoryStorage.get(key) ?? null;
999
- }
1000
- export async function setItemAsync(key: string, value: string): Promise<void> {
1001
- memoryStorage.set(key, value);
1002
- }
1003
- export async function deleteItemAsync(key: string): Promise<void> {
1004
- memoryStorage.delete(key);
1005
- }
1006
-
1007
- export async function setStringAsync(): Promise<boolean> {
1008
- return true;
1009
- }
1010
- export async function getStringAsync(): Promise<string> {
1011
- return '';
1012
- }
1013
- export async function openURL(url: string): Promise<boolean> {
1014
- if (typeof window !== 'undefined') {
1015
- window.open(url, '_blank', 'noopener,noreferrer');
1016
- }
1017
- return true;
1018
- }
1019
- export function createURL(pathStr = ''): string {
1020
- return `/${String(pathStr).replace(/^\/+/, '')}`;
1021
- }
1022
-
1023
- // ============================================================================
1024
- // 10. State Management, Data Fetching & Backend Client Shims
1025
- // (Zustand, TanStack React Query, Supabase Client)
1026
- // ============================================================================
1027
- export function create(initializer?: unknown): unknown {
1028
- if (typeof initializer !== 'function') {
1029
- return (curriedInitializer: unknown) => create(curriedInitializer);
1030
- }
1031
- let state: Record<string, unknown> = {};
1032
- const setState = (partial: unknown) => {
1033
- try {
1034
- const next =
1035
- typeof partial === 'function' ? (partial as (s: unknown) => unknown)(state) : partial;
1036
- if (next && typeof next === 'object') {
1037
- state = { ...state, ...(next as Record<string, unknown>) };
1038
- }
1039
- } catch {
1040
- // Ignore setter errors in static canvas preview
1041
- }
1042
- };
1043
- const getState = () => state;
1044
- const api = {
1045
- setState,
1046
- getState,
1047
- getInitialState: () => state,
1048
- subscribe: () => () => undefined,
1049
- destroy: () => undefined,
1050
- };
1051
- try {
1052
- const initial = (
1053
- initializer as (
1054
- set: typeof setState,
1055
- get: typeof getState,
1056
- store: typeof api
1057
- ) => Record<string, unknown>
1058
- )(setState, getState, api);
1059
- if (initial && typeof initial === 'object') {
1060
- state = initial;
1061
- }
1062
- } catch {
1063
- state = {};
1064
- }
1065
- const useBoundStore = (selector?: (s: Record<string, unknown>) => unknown) => {
1066
- if (typeof selector === 'function') {
1067
- try {
1068
- return selector(state);
1069
- } catch {
1070
- return undefined;
1071
- }
1072
- }
1073
- return state;
1074
- };
1075
- return Object.assign(useBoundStore, api);
1076
- }
1077
-
1078
- export function useStore(
1079
- store: { getState?: () => Record<string, unknown> } | ((s?: unknown) => unknown),
1080
- selector?: (s: Record<string, unknown>) => unknown
1081
- ) {
1082
- const rawState =
1083
- typeof store === 'function'
1084
- ? (store as () => Record<string, unknown>)()
1085
- : store?.getState?.() ?? {};
1086
- return typeof selector === 'function' ? selector(rawState) : rawState;
1087
- }
1088
-
1089
- export class QueryClient {
1090
- mount() {}
1091
- unmount() {}
1092
- clear() {}
1093
- getQueryData() {
1094
- return undefined;
1095
- }
1096
- setQueryData() {}
1097
- invalidateQueries() {
1098
- return Promise.resolve();
1099
- }
1100
- prefetchQuery() {
1101
- return Promise.resolve();
1102
- }
1103
- }
1104
-
1105
- export const QueryClientProvider: React.FC<{ client?: unknown; children?: React.ReactNode }> = ({
1106
- children,
1107
- }) => <>{children}</>;
1108
-
1109
- const singletonQueryClient = new QueryClient();
1110
-
1111
- export function useQueryClient() {
1112
- return singletonQueryClient;
1113
- }
1114
-
1115
- const STABLE_EMPTY_ARRAY: unknown[] = [];
1116
-
1117
- const STABLE_QUERY_RESULT = {
1118
- data: undefined,
1119
- error: null,
1120
- isLoading: false,
1121
- isPending: false,
1122
- isFetching: false,
1123
- isError: false,
1124
- isSuccess: true,
1125
- status: 'success',
1126
- refetch: async () => ({ data: undefined, error: null }),
1127
- };
1128
-
1129
- export function useQuery() {
1130
- return STABLE_QUERY_RESULT;
1131
- }
1132
-
1133
- const STABLE_INFINITE_QUERY_RESULT = {
1134
- data: { pages: STABLE_EMPTY_ARRAY, pageParams: STABLE_EMPTY_ARRAY },
1135
- error: null,
1136
- isLoading: false,
1137
- isPending: false,
1138
- isFetching: false,
1139
- isFetchingNextPage: false,
1140
- hasNextPage: false,
1141
- fetchNextPage: async () => ({}),
1142
- refetch: async () => ({}),
1143
- };
1144
-
1145
- export function useInfiniteQuery() {
1146
- return STABLE_INFINITE_QUERY_RESULT;
1147
- }
1148
-
1149
- const STABLE_MUTATION_RESULT = {
1150
- mutate: () => undefined,
1151
- mutateAsync: async () => ({}),
1152
- reset: () => undefined,
1153
- data: undefined,
1154
- error: null,
1155
- isLoading: false,
1156
- isPending: false,
1157
- isError: false,
1158
- isSuccess: false,
1159
- status: 'idle',
1160
- };
1161
-
1162
- export function useMutation() {
1163
- return STABLE_MUTATION_RESULT;
1164
- }
1165
-
1166
- // ============================================================================
1167
- // 11. Universal Chainable Proxy, Zod, React Hook Form & Context Fallbacks
1168
- // ============================================================================
1169
- export function createSafeChainableProxy(): unknown {
1170
- const fnTarget = function (..._args: unknown[]) {
1171
- return proxy;
1172
- };
1173
- const proxy: unknown = new Proxy(fnTarget, {
1174
- get(_target, prop) {
1175
- if (prop === Symbol.toPrimitive) {
1176
- return (hint: string) => (hint === 'number' ? 0 : '');
1177
- }
1178
- if (prop === 'valueOf') return () => 0;
1179
- if (prop === 'toString') return () => '';
1180
- if (prop === Symbol.iterator) {
1181
- return function* () {
1182
- yield proxy;
1183
- yield proxy;
1184
- };
1185
- }
1186
- if (prop === 'then') {
1187
- return (onFulfilled?: (v: unknown) => unknown, onRejected?: (e: unknown) => unknown) =>
1188
- Promise.resolve({ data: null, error: null }).then(onFulfilled, onRejected);
1189
- }
1190
- if (prop === 'catch') return () => Promise.resolve({ data: null, error: null });
1191
- if (prop === 'finally')
1192
- return (cb?: () => void) => Promise.resolve({ data: null, error: null }).finally(cb);
1193
- if (prop === 'safeParse' || prop === 'spa' || prop === 'safeParseAsync') {
1194
- return (val?: unknown) => ({ success: true, data: val ?? {}, error: null });
1195
- }
1196
- if (prop === 'parse' || prop === 'parseAsync') {
1197
- return (val?: unknown) => val ?? {};
1198
- }
1199
- if (
1200
- prop === 'isLoading' ||
1201
- prop === 'loading' ||
1202
- prop === 'isPending' ||
1203
- prop === 'isError' ||
1204
- prop === 'disabled' ||
1205
- prop === 'isSubmitting'
1206
- ) {
1207
- return false;
1208
- }
1209
- if (
1210
- prop === 'isReady' ||
1211
- prop === 'granted' ||
1212
- prop === 'isSuccess' ||
1213
- prop === 'isAuthenticated' ||
1214
- prop === 'isValid'
1215
- ) {
1216
- return true;
1217
- }
1218
- if (prop === 'error' || prop === 'errors') return null;
1219
- if (prop === 'status') return 'granted';
1220
- if (prop === 'data' || prop === 'items' || prop === 'results' || prop === 'list') {
1221
- return STABLE_EMPTY_ARRAY;
1222
- }
1223
- if (prop === 'length' || prop === 'size' || prop === 'count' || prop === 'value') return 0;
1224
- if (prop === 'ref') return { current: null };
1225
- if (prop === 'map' || prop === 'filter' || prop === 'slice' || prop === 'flatMap') {
1226
- return () => STABLE_EMPTY_ARRAY;
1227
- }
1228
- if (prop === 'forEach') return () => undefined;
1229
- if (prop === 'reduce') return (_fn: unknown, init: unknown) => init;
1230
- if (prop === 'shape' || prop === '_def') return {};
1231
- return proxy;
1232
- },
1233
- });
1234
- return proxy;
1235
- }
1236
-
1237
- export const SAFE_CHAINABLE_PROXY = createSafeChainableProxy();
1238
-
1239
- // Zod Shims (import { z } from 'zod' or import * as z from 'zod')
1240
- export const z = SAFE_CHAINABLE_PROXY as Record<string, unknown>;
1241
- export const string = () => SAFE_CHAINABLE_PROXY;
1242
- export const number = () => SAFE_CHAINABLE_PROXY;
1243
- export const boolean = () => SAFE_CHAINABLE_PROXY;
1244
- export const object = () => SAFE_CHAINABLE_PROXY;
1245
- export const array = () => SAFE_CHAINABLE_PROXY;
1246
- export const union = () => SAFE_CHAINABLE_PROXY;
1247
- export const literal = () => SAFE_CHAINABLE_PROXY;
1248
- export const record = () => SAFE_CHAINABLE_PROXY;
1249
- export const tuple = () => SAFE_CHAINABLE_PROXY;
1250
- export const any = () => SAFE_CHAINABLE_PROXY;
1251
- export const unknown = () => SAFE_CHAINABLE_PROXY;
1252
- export const optional = () => SAFE_CHAINABLE_PROXY;
1253
- export const nullable = () => SAFE_CHAINABLE_PROXY;
1254
- export const coerce = SAFE_CHAINABLE_PROXY;
1255
- export const zodResolver = () => async (values: unknown) => ({
1256
- values: values ?? {},
1257
- errors: {},
1258
- });
1259
- export const yupResolver = zodResolver;
1260
-
1261
- // Common React Native Sizing & Classname Utility Shims
1262
- export const scale = (size: number) => size;
1263
- export const verticalScale = (size: number) => size;
1264
- export const moderateScale = (size: number) => size;
1265
- export const moderateVerticalScale = (size: number) => size;
1266
- export const s = scale;
1267
- export const vs = verticalScale;
1268
- export const ms = moderateScale;
1269
- export const mvs = moderateVerticalScale;
1270
- export const RFValue = (size: number) => size;
1271
- export const RFPercentage = (pct: number) => Math.round(pct * 8);
1272
- export const widthPercentageToDP = (pct: number | string) =>
1273
- typeof pct === 'number' ? Math.round((393 * pct) / 100) : 100;
1274
- export const heightPercentageToDP = (pct: number | string) =>
1275
- typeof pct === 'number' ? Math.round((852 * pct) / 100) : 100;
1276
- export const wp = widthPercentageToDP;
1277
- export const hp = heightPercentageToDP;
1278
- export const clsx = (...args: unknown[]) =>
1279
- args.filter((a): a is string => typeof a === 'string' && a.length > 0).join(' ');
1280
- export const cn = clsx;
1281
- export const twMerge = clsx;
1282
-
1283
- // NativeWind (v2 / v4) & twrnc Universal Shims
1284
- export function styled<P extends Record<string, unknown>>(
1285
- Component: React.ComponentType<P>,
1286
- baseClassName?: string
1287
- ): React.ComponentType<P> {
1288
- const Wrapped = withNativeWind(Component as unknown as React.ComponentType<Record<string, unknown>>);
1289
- if (!baseClassName) return Wrapped as unknown as React.ComponentType<P>;
1290
- return React.forwardRef<unknown, P>((props, ref) => {
1291
- const combinedClass = [baseClassName, props?.className].filter(Boolean).join(' ');
1292
- return React.createElement(Wrapped, { ...props, className: combinedClass, ref });
1293
- }) as unknown as React.ComponentType<P>;
1294
- }
1295
-
1296
- export function cssInterop<P extends Record<string, unknown>>(
1297
- Component: React.ComponentType<P>
1298
- ): React.ComponentType<P> {
1299
- return withNativeWind(Component as unknown as React.ComponentType<Record<string, unknown>>) as unknown as React.ComponentType<P>;
1300
- }
1301
-
1302
- export const remapProps = cssInterop;
1303
-
1304
- function twFn(stringsOrClass: TemplateStringsArray | string, ...values: unknown[]): Record<string, unknown> {
1305
- if (typeof stringsOrClass === 'string') {
1306
- return resolveTailwindClassNameToStyle(stringsOrClass) ?? {};
1307
- }
1308
- if (Array.isArray(stringsOrClass)) {
1309
- const built = stringsOrClass.reduce(
1310
- (acc, str, idx) => acc + str + (values[idx] !== undefined ? String(values[idx]) : ''),
1311
- ''
1312
- );
1313
- return resolveTailwindClassNameToStyle(built) ?? {};
1314
- }
1315
- return {};
1316
- }
1317
-
1318
- twFn.style = (...args: unknown[]) => {
1319
- const mergedClass = args.filter((a): a is string => typeof a === 'string' && a.length > 0).join(' ');
1320
- return resolveTailwindClassNameToStyle(mergedClass) ?? {};
1321
- };
1322
- twFn.color = (token: string) => {
1323
- const s = resolveTailwindClassNameToStyle(`text-${token}`);
1324
- return (s?.color as string | undefined) ?? '#0F172A';
1325
- };
1326
-
1327
- export const tw = twFn;
1328
- export const createTw = () => twFn;
1329
-
1330
- // React Hook Form Shims (react-hook-form)
1331
- export function useForm(config?: { defaultValues?: Record<string, unknown> }) {
1332
- const defaults = config?.defaultValues ?? {};
1333
- return {
1334
- control: {},
1335
- register: (name: string) => ({
1336
- name,
1337
- onChange: () => undefined,
1338
- onBlur: () => undefined,
1339
- ref: () => undefined,
1340
- }),
1341
- handleSubmit: (onValid?: (data: Record<string, unknown>) => unknown) => () =>
1342
- onValid?.(defaults),
1343
- watch: (name?: string) => (name ? defaults[name] ?? '' : defaults),
1344
- getValues: (name?: string) => (name ? defaults[name] : defaults),
1345
- setValue: () => undefined,
1346
- reset: () => undefined,
1347
- clearErrors: () => undefined,
1348
- setError: () => undefined,
1349
- trigger: async () => true,
1350
- formState: {
1351
- errors: {},
1352
- isDirty: false,
1353
- isLoading: false,
1354
- isSubmitted: false,
1355
- isSubmitting: false,
1356
- isSubmitSuccessful: false,
1357
- isValid: true,
1358
- dirtyFields: {},
1359
- touchedFields: {},
1360
- },
1361
- };
1362
- }
1363
-
1364
- export const useFormContext = () => useForm();
1365
- export const FormProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
1366
- <>{children}</>
1367
- );
1368
- export const useWatch = () => '';
1369
- export const useFieldArray = () => ({
1370
- fields: STABLE_EMPTY_ARRAY,
1371
- append: () => undefined,
1372
- prepend: () => undefined,
1373
- remove: () => undefined,
1374
- insert: () => undefined,
1375
- move: () => undefined,
1376
- update: () => undefined,
1377
- replace: () => undefined,
1378
- });
1379
-
1380
- export const Controller: React.FC<{
1381
- name?: string;
1382
- defaultValue?: unknown;
1383
- render?: (params: {
1384
- field: {
1385
- name: string;
1386
- value: unknown;
1387
- onChange: (...args: unknown[]) => void;
1388
- onBlur: () => void;
1389
- ref: () => void;
1390
- };
1391
- fieldState: { invalid: boolean; isTouched: boolean; isDirty: boolean; error: undefined };
1392
- formState: { errors: Record<string, unknown>; isSubmitting: boolean; isValid: boolean };
1393
- }) => React.ReactNode;
1394
- children?: React.ReactNode;
1395
- }> = ({ name = '', defaultValue = '', render, children }) => {
1396
- if (typeof render === 'function') {
1397
- return (
1398
- <>
1399
- {render({
1400
- field: {
1401
- name,
1402
- value: defaultValue ?? '',
1403
- onChange: () => undefined,
1404
- onBlur: () => undefined,
1405
- ref: () => undefined,
1406
- },
1407
- fieldState: { invalid: false, isTouched: false, isDirty: false, error: undefined },
1408
- formState: { errors: {}, isSubmitting: false, isValid: true },
1409
- })}
1410
- </>
1411
- );
1412
- }
1413
- return <>{children}</>;
1414
- };
1415
-
1416
- // Universal Unmounted Context Fallback (prevents "useAuth must be used within an AuthProvider")
1417
- const previewUserBase: Record<string, unknown> = {
1418
- id: 'usr_preview_01',
1419
- uid: 'usr_preview_01',
1420
- email: 'alex.morgan@example.com',
1421
- name: 'Alex Morgan',
1422
- fullName: 'Alex Morgan',
1423
- full_name: 'Alex Morgan',
1424
- firstName: 'Alex',
1425
- first_name: 'Alex',
1426
- lastName: 'Morgan',
1427
- last_name: 'Morgan',
1428
- displayName: 'Alex Morgan',
1429
- display_name: 'Alex Morgan',
1430
- username: 'alexmorgan',
1431
- phone: '+1 (555) 019-2834',
1432
- phoneNumber: '+1 (555) 019-2834',
1433
- phone_number: '+1 (555) 019-2834',
1434
- role: 'buyer',
1435
- accountType: 'buyer',
1436
- account_type: 'buyer',
1437
- location: 'San Francisco, CA',
1438
- city: 'San Francisco',
1439
- bio: 'Product designer & automotive enthusiast.',
1440
- avatar: '',
1441
- avatarUrl: '',
1442
- avatar_url: '',
1443
- photoURL: '',
1444
- profileImage: '',
1445
- profile_image: '',
1446
- isVerified: true,
1447
- is_verified: true,
1448
- verified: true,
1449
- createdAt: '2025-01-15T10:00:00Z',
1450
- created_at: '2025-01-15T10:00:00Z',
1451
- user_metadata: {
1452
- full_name: 'Alex Morgan',
1453
- name: 'Alex Morgan',
1454
- email: 'alex.morgan@example.com',
1455
- role: 'buyer',
1456
- avatar_url: '',
1457
- },
1458
- app_metadata: {
1459
- provider: 'email',
1460
- role: 'buyer',
1461
- },
1462
- };
1463
-
1464
- const previewUserProxy = new Proxy(previewUserBase, {
1465
- get(target, prop) {
1466
- if (prop in target) return target[prop as keyof typeof target];
1467
- if (prop === Symbol.toPrimitive) return () => 'Alex Morgan';
1468
- if (typeof prop === 'string') return '';
1469
- return undefined;
1470
- },
1471
- });
1472
-
1473
- const previewColorsBase: Record<string, string> = {
1474
- primary: '#2563EB',
1475
- primaryLight: '#DBEAFE',
1476
- secondary: '#64748B',
1477
- accent: '#4F46E5',
1478
- background: '#FFFFFF',
1479
- backgroundSecondary: '#F8FAFC',
1480
- surface: '#F8FAFC',
1481
- card: '#FFFFFF',
1482
- text: '#0F172A',
1483
- textPrimary: '#0F172A',
1484
- textSecondary: '#475569',
1485
- textMuted: '#94A3B8',
1486
- muted: '#94A3B8',
1487
- placeholder: '#94A3B8',
1488
- border: '#E2E8F0',
1489
- divider: '#E2E8F0',
1490
- error: '#EF4444',
1491
- danger: '#EF4444',
1492
- success: '#10B981',
1493
- warning: '#F59E0B',
1494
- info: '#3B82F6',
1495
- white: '#FFFFFF',
1496
- black: '#0F172A',
1497
- tint: '#2563EB',
1498
- icon: '#64748B',
1499
- tabIconDefault: '#94A3B8',
1500
- tabIconSelected: '#2563EB',
1501
- notification: '#EF4444',
1502
- };
1503
-
1504
- const previewColorsProxy = new Proxy(previewColorsBase, {
1505
- get(target, prop) {
1506
- if (prop in target) return target[prop as keyof typeof target];
1507
- return '#64748B';
1508
- },
1509
- });
1510
-
1511
- const safeContextFallbackBase: Record<string, unknown> = {
1512
- user: previewUserProxy,
1513
- currentUser: previewUserProxy,
1514
- profile: previewUserProxy,
1515
- session: {
1516
- access_token: 'preview-access-token',
1517
- refresh_token: 'preview-refresh-token',
1518
- user: previewUserProxy,
1519
- },
1520
- isAuthenticated: true,
1521
- isLoggedIn: true,
1522
- isSignedIn: true,
1523
- isLoading: false,
1524
- loading: false,
1525
- isPending: false,
1526
- isRefreshing: false,
1527
- isInitialized: true,
1528
- isReady: true,
1529
- error: null,
1530
- theme: 'light',
1531
- colorScheme: 'light',
1532
- isDark: false,
1533
- dark: false,
1534
- colors: previewColorsProxy,
1535
- items: STABLE_EMPTY_ARRAY,
1536
- cart: STABLE_EMPTY_ARRAY,
1537
- favorites: STABLE_EMPTY_ARRAY,
1538
- wishlist: STABLE_EMPTY_ARRAY,
1539
- notifications: STABLE_EMPTY_ARRAY,
1540
- bookings: STABLE_EMPTY_ARRAY,
1541
- listings: STABLE_EMPTY_ARRAY,
1542
- vehicles: STABLE_EMPTY_ARRAY,
1543
- cars: STABLE_EMPTY_ARRAY,
1544
- orders: STABLE_EMPTY_ARRAY,
1545
- transactions: STABLE_EMPTY_ARRAY,
1546
- messages: STABLE_EMPTY_ARRAY,
1547
- chats: STABLE_EMPTY_ARRAY,
1548
- unreadCount: 0,
1549
- count: 0,
1550
- total: 0,
1551
- balance: 0,
1552
- signIn: async () => ({ data: { user: previewUserProxy }, error: null }),
1553
- signUp: async () => ({ data: { user: previewUserProxy }, error: null }),
1554
- signOut: async () => ({ error: null }),
1555
- login: async () => ({ data: { user: previewUserProxy }, error: null }),
1556
- logout: async () => undefined,
1557
- register: async () => ({ data: { user: previewUserProxy }, error: null }),
1558
- refresh: async () => undefined,
1559
- refetch: async () => undefined,
1560
- updateProfile: async () => ({ error: null }),
1561
- toggleTheme: () => undefined,
1562
- setTheme: () => undefined,
1563
- };
1564
-
1565
- export const SAFE_CONTEXT_FALLBACK: Record<string, unknown> = new Proxy(safeContextFallbackBase, {
1566
- get(target, prop) {
1567
- if (prop in target) return target[prop as keyof typeof target];
1568
- if (prop === Symbol.iterator) {
1569
- return function* () {
1570
- yield SAFE_CONTEXT_FALLBACK;
1571
- yield () => undefined;
1572
- };
1573
- }
1574
- return SAFE_CHAINABLE_PROXY;
1575
- },
1576
- });
1577
-
1578
- // Install unmounted user-context fallback on React.createContext & React.useContext
1579
- // (runs after react-native-web has already initialized its internal VirtualizedListContext)
1580
- const origCreateContext = React.createContext;
1581
- const origUseContext = React.useContext;
1582
-
1583
- const wrappedCreateContext = function zeluneCreateContext(
1584
- defaultValue: unknown,
1585
- ...rest: unknown[]
1586
- ) {
1587
- const isEmptyDefault =
1588
- defaultValue === undefined ||
1589
- defaultValue === null ||
1590
- (typeof defaultValue === 'object' &&
1591
- defaultValue !== null &&
1592
- Object.keys(defaultValue as object).length === 0);
1593
- const effectiveDefault = isEmptyDefault ? SAFE_CONTEXT_FALLBACK : defaultValue;
1594
- const ctx = (origCreateContext as (...a: unknown[]) => Record<string, unknown>).call(
1595
- React,
1596
- effectiveDefault,
1597
- ...rest
1598
- );
1599
- if (ctx && typeof ctx === 'object' && isEmptyDefault) {
1600
- ctx.__zeluneUserContext = true;
1601
- }
1602
- return ctx;
1603
- } as unknown as typeof React.createContext;
1604
-
1605
- const wrappedUseContext = function zeluneUseContext(
1606
- Context: React.Context<unknown>,
1607
- ...rest: unknown[]
1608
- ) {
1609
- const val = (origUseContext as (...a: unknown[]) => unknown).call(React, Context, ...rest);
1610
- if (
1611
- val === undefined ||
1612
- (val === null &&
1613
- Boolean((Context as unknown as Record<string, unknown>)?.__zeluneUserContext))
1614
- ) {
1615
- return SAFE_CONTEXT_FALLBACK;
1616
- }
1617
- return val;
1618
- } as unknown as typeof React.useContext;
1619
-
1620
- try {
1621
- React.createContext = wrappedCreateContext;
1622
- React.useContext = wrappedUseContext;
1623
- } catch {
1624
- // Ignore if React namespace is frozen in test environment
1625
- }
1626
-
1627
- function createSupabaseQueryBuilder(): Record<string, unknown> {
1628
- const resultPromise = Promise.resolve({ data: [], error: null, count: 0 });
1629
- const builder: Record<string, unknown> = new Proxy(
1630
- {},
1631
- {
1632
- get(_target, prop) {
1633
- if (prop === 'then') return resultPromise.then.bind(resultPromise);
1634
- if (prop === 'catch') return resultPromise.catch.bind(resultPromise);
1635
- if (prop === 'finally') return resultPromise.finally.bind(resultPromise);
1636
- if (prop === 'single' || prop === 'maybeSingle') {
1637
- return async () => ({ data: null, error: null });
1638
- }
1639
- return () => builder;
1640
- },
1641
- }
1642
- );
1643
- return builder;
1644
- }
1645
-
1646
- export function createClient() {
1647
- return {
1648
- auth: {
1649
- getSession: async () => ({ data: { session: null }, error: null }),
1650
- getUser: async () => ({ data: { user: null }, error: null }),
1651
- onAuthStateChange: () => ({
1652
- data: { subscription: { unsubscribe: () => undefined } },
1653
- }),
1654
- signInWithPassword: async () => ({ data: { user: null, session: null }, error: null }),
1655
- signInWithOtp: async () => ({ data: { user: null, session: null }, error: null }),
1656
- signUp: async () => ({ data: { user: null, session: null }, error: null }),
1657
- signOut: async () => ({ error: null }),
1658
- startAutoRefresh: () => undefined,
1659
- stopAutoRefresh: () => undefined,
1660
- },
1661
- from: () => createSupabaseQueryBuilder(),
1662
- rpc: async () => ({ data: null, error: null }),
1663
- storage: {
1664
- from: () => ({
1665
- upload: async () => ({ data: { path: '' }, error: null }),
1666
- getPublicUrl: () => ({ data: { publicUrl: '' } }),
1667
- download: async () => ({ data: null, error: null }),
1668
- remove: async () => ({ data: [], error: null }),
1669
- }),
1670
- },
1671
- channel: () => {
1672
- const ch = {
1673
- on: () => ch,
1674
- subscribe: () => ch,
1675
- unsubscribe: async () => 'ok',
1676
- };
1677
- return ch;
1678
- },
1679
- removeChannel: async () => 'ok',
1680
- functions: {
1681
- invoke: async () => ({ data: null, error: null }),
1682
- },
1683
- };
1684
- }
1685
-
1686
- function UniversalDefaultExportComponent(props: Record<string, unknown> = {}) {
1687
- if (props && typeof props === 'object') {
1688
- if (typeof props.name === 'string') {
1689
- return Ionicons(props as VectorIconProps);
1690
- }
1691
- if ('viewBox' in props || 'xmlns' in props) {
1692
- return React.createElement('svg', props, props.children as React.ReactNode);
1693
- }
1694
- }
1695
- return React.createElement(
1696
- View,
1697
- { style: props?.style as never },
1698
- props?.children as React.ReactNode
1699
- );
1700
- }
1701
-
1702
- const defaultExportProperties = {
1703
- ...Animated,
1704
- ...AsyncStorage,
1705
- ...Constants,
1706
- Ionicons,
1707
- Feather,
1708
- MaterialIcons,
1709
- MaterialCommunityIcons,
1710
- FontAwesome,
1711
- FontAwesome5,
1712
- FontAwesome6,
1713
- AntDesign,
1714
- Entypo,
1715
- EvilIcons,
1716
- Foundation,
1717
- Octicons,
1718
- SimpleLineIcons,
1719
- Zocial,
1720
- Fontisto,
1721
- LinearGradient,
1722
- BlurView,
1723
- Image,
1724
- ImageBackground,
1725
- FlashList,
1726
- Svg,
1727
- ImpactFeedbackStyle,
1728
- NotificationFeedbackType,
1729
- impactAsync,
1730
- notificationAsync,
1731
- selectionAsync,
1732
- useFonts,
1733
- loadAsync,
1734
- isLoaded,
1735
- preventAutoHideAsync,
1736
- hideAsync,
1737
- getItemAsync,
1738
- setItemAsync,
1739
- deleteItemAsync,
1740
- setStringAsync,
1741
- getStringAsync,
1742
- openURL,
1743
- createURL,
1744
- create,
1745
- useStore,
1746
- QueryClient,
1747
- QueryClientProvider,
1748
- useQueryClient,
1749
- useQuery,
1750
- useInfiniteQuery,
1751
- useMutation,
1752
- createClient,
1753
- z,
1754
- string,
1755
- number,
1756
- boolean,
1757
- object,
1758
- array,
1759
- union,
1760
- literal,
1761
- record,
1762
- tuple,
1763
- any,
1764
- unknown,
1765
- optional,
1766
- nullable,
1767
- coerce,
1768
- zodResolver,
1769
- yupResolver,
1770
- useForm,
1771
- useFormContext,
1772
- FormProvider,
1773
- useWatch,
1774
- useFieldArray,
1775
- Controller,
1776
- };
1777
-
1778
- Object.assign(UniversalDefaultExportComponent, defaultExportProperties);
1779
-
1780
- const defaultExportProxy = new Proxy(UniversalDefaultExportComponent, {
1781
- get(target, prop) {
1782
- if (prop in target) {
1783
- return (target as unknown as Record<string | symbol, unknown>)[prop];
1784
- }
1785
- if (prop in defaultExportProperties) {
1786
- return defaultExportProperties[prop as keyof typeof defaultExportProperties];
1787
- }
1788
- if (typeof prop === 'string' && /^[A-Z]/.test(prop)) {
1789
- return createVectorIconComponent(prop);
1790
- }
1791
- return SAFE_CHAINABLE_PROXY;
1792
- },
1793
- });
1794
-
1795
- export default defaultExportProxy;