zelune 1.5.2 → 1.5.4

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