zelune 1.5.2 → 1.5.5

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