@mr.dj2u/library-registry 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/THIRD_PARTY_NOTICES.md +90 -0
  4. package/assets/create-expo-app/sdk-56/assets/images/expo-badge-white.png +0 -0
  5. package/assets/create-expo-app/sdk-56/assets/images/expo-badge.png +0 -0
  6. package/assets/create-expo-app/sdk-56/assets/images/expo-logo.png +0 -0
  7. package/assets/create-expo-app/sdk-56/assets/images/logo-glow.png +0 -0
  8. package/assets/create-expo-app/sdk-56/assets/images/react-logo.png +0 -0
  9. package/assets/create-expo-app/sdk-56/assets/images/react-logo@2x.png +0 -0
  10. package/assets/create-expo-app/sdk-56/assets/images/react-logo@3x.png +0 -0
  11. package/assets/create-expo-app/sdk-56/assets/images/tabIcons/explore.png +0 -0
  12. package/assets/create-expo-app/sdk-56/assets/images/tabIcons/explore@2x.png +0 -0
  13. package/assets/create-expo-app/sdk-56/assets/images/tabIcons/explore@3x.png +0 -0
  14. package/assets/create-expo-app/sdk-56/assets/images/tabIcons/home.png +0 -0
  15. package/assets/create-expo-app/sdk-56/assets/images/tabIcons/home@2x.png +0 -0
  16. package/assets/create-expo-app/sdk-56/assets/images/tabIcons/home@3x.png +0 -0
  17. package/assets/create-expo-app/sdk-56/assets/images/tutorial-web.png +0 -0
  18. package/assets/create-expo-app/sdk-56/src/app/_layout.tsx +15 -0
  19. package/assets/create-expo-app/sdk-56/src/app/explore.tsx +180 -0
  20. package/assets/create-expo-app/sdk-56/src/app/index.tsx +98 -0
  21. package/assets/create-expo-app/sdk-56/src/components/animated-icon.module.css +6 -0
  22. package/assets/create-expo-app/sdk-56/src/components/animated-icon.tsx +132 -0
  23. package/assets/create-expo-app/sdk-56/src/components/animated-icon.web.tsx +108 -0
  24. package/assets/create-expo-app/sdk-56/src/components/app-tabs.tsx +32 -0
  25. package/assets/create-expo-app/sdk-56/src/components/app-tabs.web.tsx +115 -0
  26. package/assets/create-expo-app/sdk-56/src/components/external-link.tsx +25 -0
  27. package/assets/create-expo-app/sdk-56/src/components/hint-row.tsx +35 -0
  28. package/assets/create-expo-app/sdk-56/src/components/themed-text.tsx +73 -0
  29. package/assets/create-expo-app/sdk-56/src/components/themed-view.tsx +16 -0
  30. package/assets/create-expo-app/sdk-56/src/components/ui/collapsible.tsx +65 -0
  31. package/assets/create-expo-app/sdk-56/src/components/web-badge.tsx +43 -0
  32. package/assets/create-expo-app/sdk-56/src/constants/theme.ts +65 -0
  33. package/assets/create-expo-app/sdk-56/src/global.css +9 -0
  34. package/assets/create-expo-app/sdk-56/src/hooks/use-color-scheme.ts +1 -0
  35. package/assets/create-expo-app/sdk-56/src/hooks/use-color-scheme.web.ts +21 -0
  36. package/assets/create-expo-app/sdk-56/src/hooks/use-theme.ts +14 -0
  37. package/assets/create-expo-stack/2.21.3/base/components/BackButton.tsx +23 -0
  38. package/assets/create-expo-stack/2.21.3/base/components/Button.tsx +42 -0
  39. package/assets/create-expo-stack/2.21.3/base/components/Container.tsx +14 -0
  40. package/assets/create-expo-stack/2.21.3/base/components/EditScreenInfo.tsx +36 -0
  41. package/assets/create-expo-stack/2.21.3/base/components/HeaderButton.tsx +31 -0
  42. package/assets/create-expo-stack/2.21.3/base/components/ScreenContent.tsx +40 -0
  43. package/assets/create-expo-stack/2.21.3/base/components/TabBarIcon.tsx +15 -0
  44. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/ActivityIndicator.tsx +10 -0
  45. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Avatar.tsx +32 -0
  46. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Button.tsx +141 -0
  47. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/DatePicker/DatePicker.android.tsx +77 -0
  48. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/DatePicker/DatePicker.tsx +23 -0
  49. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/DatePicker/index.ts +1 -0
  50. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Icon/Icon.ios.tsx +55 -0
  51. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Icon/Icon.tsx +58 -0
  52. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Icon/index.ts +16 -0
  53. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Icon/types.ts +19 -0
  54. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Picker.tsx +42 -0
  55. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/ProgressIndicator.tsx +68 -0
  56. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Slider.tsx +28 -0
  57. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Text.tsx +55 -0
  58. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/ThemeToggle.tsx +33 -0
  59. package/assets/create-expo-stack/2.21.3-mrdj.2/src/components/nativewindui/Toggle.tsx +20 -0
  60. package/assets/create-expo-stack/2.21.3-mrdj.2/src/lib/cn.ts +6 -0
  61. package/assets/create-expo-stack/2.21.3-mrdj.2/src/lib/useColorScheme.tsx +21 -0
  62. package/assets/create-expo-stack/2.21.3-mrdj.2/src/lib/useHeaderSearchBar.tsx +33 -0
  63. package/assets/create-expo-stack/2.21.3-mrdj.2/src/theme/colors.ts +123 -0
  64. package/assets/create-expo-stack/2.21.3-mrdj.2/src/theme/index.ts +32 -0
  65. package/assets/create-expo-stack/2.21.3-mrdj.2/src/theme/with-opacity.ts +155 -0
  66. package/assets/mds/routes/drawer-tabs/data.tsx +1 -0
  67. package/assets/mds/routes/drawer-tabs/index.tsx +1 -0
  68. package/assets/mds/routes/drawer-tabs/nativewindui.tsx +1 -0
  69. package/assets/mds/routes/drawer-tabs/sdk-56.tsx +1 -0
  70. package/assets/mds/routes/drawer-tabs/stylist.tsx +1 -0
  71. package/assets/mds/scripts/stylist-sync-android.mjs +39 -0
  72. package/assets/mds/src/app/exposition/data.tsx +1 -0
  73. package/assets/mds/src/app/exposition/index.tsx +1 -0
  74. package/assets/mds/src/app/exposition/nativewindui.tsx +1 -0
  75. package/assets/mds/src/app/exposition/sdk-56.tsx +1 -0
  76. package/assets/mds/src/app/exposition/stylist-sync+api.ts +241 -0
  77. package/assets/mds/src/app/exposition/stylist.tsx +1 -0
  78. package/assets/mds/src/app/onboarding/account-setup.tsx +1 -0
  79. package/assets/mds/src/app/onboarding/agreement.tsx +1 -0
  80. package/assets/mds/src/app/onboarding/terms.tsx +1 -0
  81. package/assets/mds/src/app/onboarding.tsx +1 -0
  82. package/assets/mds/src/app/settings.tsx +1 -0
  83. package/assets/mds/src/components/exposition/index.ts +8 -0
  84. package/assets/mds/src/components/exposition/notice.tsx +3 -0
  85. package/assets/mds/src/components/exposition/package-card.tsx +76 -0
  86. package/assets/mds/src/components/swmansion/animated-pressable.tsx +54 -0
  87. package/assets/mds/src/components/swmansion/gesture-card.tsx +54 -0
  88. package/assets/mds/src/components/swmansion/keyboard-form.tsx +73 -0
  89. package/assets/mds/src/components/swmansion/screens-card.tsx +40 -0
  90. package/assets/mds/src/components/swmansion/software-mansion-logo.tsx +15 -0
  91. package/assets/mds/src/components/swmansion/svg-mark.tsx +16 -0
  92. package/assets/mds/src/data/mock-app.ts +21 -0
  93. package/assets/mds/src/features/exposition/data-screen.tsx +152 -0
  94. package/assets/mds/src/features/exposition/embedded-fonts.ts +72 -0
  95. package/assets/mds/src/features/exposition/expo-sdk-56-screen.tsx +709 -0
  96. package/assets/mds/src/features/exposition/exposition-screen.tsx +191 -0
  97. package/assets/mds/src/features/exposition/nativewindui-screen.tsx +125 -0
  98. package/assets/mds/src/features/exposition/stylist-screen.tsx +3456 -0
  99. package/assets/mds/src/features/onboarding/account-setup-screen.tsx +54 -0
  100. package/assets/mds/src/features/onboarding/agreement-screen.tsx +6 -0
  101. package/assets/mds/src/features/onboarding/components/legal-document-view.tsx +103 -0
  102. package/assets/mds/src/features/onboarding/legal-documents.ts +80 -0
  103. package/assets/mds/src/features/onboarding/onboarding-screen.tsx +167 -0
  104. package/assets/mds/src/features/onboarding/terms-screen.tsx +6 -0
  105. package/assets/mds/src/features/settings/settings-screen.tsx +57 -0
  106. package/assets/mds/src/services/local-data.native.ts +103 -0
  107. package/assets/mds/src/services/local-data.ts +38 -0
  108. package/assets/mds/src/theme/font-assets.ts +3 -0
  109. package/assets/mds/src/theme/provider.tsx +59 -0
  110. package/assets/mds/src/theme/tokens.ts +180 -0
  111. package/dist/catalog.d.ts +3 -0
  112. package/dist/catalog.d.ts.map +1 -0
  113. package/dist/catalog.js +1110 -0
  114. package/dist/catalog.js.map +1 -0
  115. package/dist/index.d.ts +5 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +4 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/registry.d.ts +7 -0
  120. package/dist/registry.d.ts.map +1 -0
  121. package/dist/registry.js +479 -0
  122. package/dist/registry.js.map +1 -0
  123. package/dist/types.d.ts +169 -0
  124. package/dist/types.d.ts.map +1 -0
  125. package/dist/types.js +2 -0
  126. package/dist/types.js.map +1 -0
  127. package/dist/validation.d.ts +6 -0
  128. package/dist/validation.d.ts.map +1 -0
  129. package/dist/validation.js +209 -0
  130. package/dist/validation.js.map +1 -0
  131. package/package.json +51 -0
@@ -0,0 +1,108 @@
1
+ import { Image } from 'expo-image';
2
+ import { StyleSheet, View } from 'react-native';
3
+ import Animated, { Keyframe, Easing } from 'react-native-reanimated';
4
+
5
+ import classes from './animated-icon.module.css';
6
+ const DURATION = 300;
7
+
8
+ export function AnimatedSplashOverlay() {
9
+ return null;
10
+ }
11
+
12
+ const keyframe = new Keyframe({
13
+ 0: {
14
+ transform: [{ scale: 0 }],
15
+ },
16
+ 60: {
17
+ transform: [{ scale: 1.2 }],
18
+ easing: Easing.elastic(1.2),
19
+ },
20
+ 100: {
21
+ transform: [{ scale: 1 }],
22
+ easing: Easing.elastic(1.2),
23
+ },
24
+ });
25
+
26
+ const logoKeyframe = new Keyframe({
27
+ 0: {
28
+ opacity: 0,
29
+ },
30
+ 60: {
31
+ transform: [{ scale: 1.2 }],
32
+ opacity: 0,
33
+ easing: Easing.elastic(1.2),
34
+ },
35
+ 100: {
36
+ transform: [{ scale: 1 }],
37
+ opacity: 1,
38
+ easing: Easing.elastic(1.2),
39
+ },
40
+ });
41
+
42
+ const glowKeyframe = new Keyframe({
43
+ 0: {
44
+ transform: [{ rotateZ: '-180deg' }, { scale: 0.8 }],
45
+ opacity: 0,
46
+ },
47
+ [DURATION / 1000]: {
48
+ transform: [{ rotateZ: '0deg' }, { scale: 1 }],
49
+ opacity: 1,
50
+ easing: Easing.elastic(0.7),
51
+ },
52
+ 100: {
53
+ transform: [{ rotateZ: '7200deg' }],
54
+ },
55
+ });
56
+
57
+ export function AnimatedIcon() {
58
+ return (
59
+ <View style={styles.iconContainer}>
60
+ <Animated.View entering={glowKeyframe.duration(60 * 1000 * 4)} style={styles.glow}>
61
+ <Image style={styles.glow} source={require('@/assets/images/logo-glow.png')} />
62
+ </Animated.View>
63
+
64
+ <Animated.View style={styles.background} entering={keyframe.duration(DURATION)}>
65
+ <div className={classes.expoLogoBackground} />
66
+ </Animated.View>
67
+
68
+ <Animated.View style={styles.imageContainer} entering={logoKeyframe.duration(DURATION)}>
69
+ <Image style={styles.image} source={require('@/assets/images/expo-logo.png')} />
70
+ </Animated.View>
71
+ </View>
72
+ );
73
+ }
74
+
75
+ const styles = StyleSheet.create({
76
+ container: {
77
+ alignItems: 'center',
78
+ width: '100%',
79
+ zIndex: 1000,
80
+ position: 'absolute',
81
+ top: 128 / 2 + 138,
82
+ },
83
+ imageContainer: {
84
+ justifyContent: 'center',
85
+ alignItems: 'center',
86
+ },
87
+ glow: {
88
+ width: 201,
89
+ height: 201,
90
+ position: 'absolute',
91
+ },
92
+ iconContainer: {
93
+ justifyContent: 'center',
94
+ alignItems: 'center',
95
+ width: 128,
96
+ height: 128,
97
+ },
98
+ image: {
99
+ position: 'absolute',
100
+ width: 76,
101
+ height: 71,
102
+ },
103
+ background: {
104
+ width: 128,
105
+ height: 128,
106
+ position: 'absolute',
107
+ },
108
+ });
@@ -0,0 +1,32 @@
1
+ import { NativeTabs } from 'expo-router/unstable-native-tabs';
2
+ import { useColorScheme } from 'react-native';
3
+
4
+ import { Colors } from '@/constants/theme';
5
+
6
+ export default function AppTabs() {
7
+ const scheme = useColorScheme();
8
+ const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
9
+
10
+ return (
11
+ <NativeTabs
12
+ backgroundColor={colors.background}
13
+ indicatorColor={colors.backgroundElement}
14
+ labelStyle={{ selected: { color: colors.text } }}>
15
+ <NativeTabs.Trigger name="index">
16
+ <NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label>
17
+ <NativeTabs.Trigger.Icon
18
+ src={require('@/assets/images/tabIcons/home.png')}
19
+ renderingMode="template"
20
+ />
21
+ </NativeTabs.Trigger>
22
+
23
+ <NativeTabs.Trigger name="explore">
24
+ <NativeTabs.Trigger.Label>Explore</NativeTabs.Trigger.Label>
25
+ <NativeTabs.Trigger.Icon
26
+ src={require('@/assets/images/tabIcons/explore.png')}
27
+ renderingMode="template"
28
+ />
29
+ </NativeTabs.Trigger>
30
+ </NativeTabs>
31
+ );
32
+ }
@@ -0,0 +1,115 @@
1
+ import {
2
+ Tabs,
3
+ TabList,
4
+ TabTrigger,
5
+ TabSlot,
6
+ TabTriggerSlotProps,
7
+ TabListProps,
8
+ } from 'expo-router/ui';
9
+ import { SymbolView } from 'expo-symbols';
10
+ import { Pressable, useColorScheme, View, StyleSheet } from 'react-native';
11
+
12
+ import { ExternalLink } from './external-link';
13
+ import { ThemedText } from './themed-text';
14
+ import { ThemedView } from './themed-view';
15
+
16
+ import { Colors, MaxContentWidth, Spacing } from '@/constants/theme';
17
+
18
+ export default function AppTabs() {
19
+ return (
20
+ <Tabs>
21
+ <TabSlot style={{ height: '100%' }} />
22
+ <TabList asChild>
23
+ <CustomTabList>
24
+ <TabTrigger name="home" href="/" asChild>
25
+ <TabButton>Home</TabButton>
26
+ </TabTrigger>
27
+ <TabTrigger name="explore" href="/explore" asChild>
28
+ <TabButton>Explore</TabButton>
29
+ </TabTrigger>
30
+ </CustomTabList>
31
+ </TabList>
32
+ </Tabs>
33
+ );
34
+ }
35
+
36
+ export function TabButton({ children, isFocused, ...props }: TabTriggerSlotProps) {
37
+ return (
38
+ <Pressable {...props} style={({ pressed }) => pressed && styles.pressed}>
39
+ <ThemedView
40
+ type={isFocused ? 'backgroundSelected' : 'backgroundElement'}
41
+ style={styles.tabButtonView}>
42
+ <ThemedText type="small" themeColor={isFocused ? 'text' : 'textSecondary'}>
43
+ {children}
44
+ </ThemedText>
45
+ </ThemedView>
46
+ </Pressable>
47
+ );
48
+ }
49
+
50
+ export function CustomTabList(props: TabListProps) {
51
+ const scheme = useColorScheme();
52
+ const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
53
+
54
+ return (
55
+ <View {...props} style={styles.tabListContainer}>
56
+ <ThemedView type="backgroundElement" style={styles.innerContainer}>
57
+ <ThemedText type="smallBold" style={styles.brandText}>
58
+ Expo Starter
59
+ </ThemedText>
60
+
61
+ {props.children}
62
+
63
+ <ExternalLink href="https://docs.expo.dev" asChild>
64
+ <Pressable style={styles.externalPressable}>
65
+ <ThemedText type="link">Docs</ThemedText>
66
+ <SymbolView
67
+ tintColor={colors.text}
68
+ name={{ ios: 'arrow.up.right.square', web: 'link' }}
69
+ size={12}
70
+ />
71
+ </Pressable>
72
+ </ExternalLink>
73
+ </ThemedView>
74
+ </View>
75
+ );
76
+ }
77
+
78
+ const styles = StyleSheet.create({
79
+ tabListContainer: {
80
+ position: 'absolute',
81
+ width: '100%',
82
+ padding: Spacing.three,
83
+ justifyContent: 'center',
84
+ alignItems: 'center',
85
+ flexDirection: 'row',
86
+ },
87
+ innerContainer: {
88
+ paddingVertical: Spacing.two,
89
+ paddingHorizontal: Spacing.five,
90
+ borderRadius: Spacing.five,
91
+ flexDirection: 'row',
92
+ alignItems: 'center',
93
+ flexGrow: 1,
94
+ gap: Spacing.two,
95
+ maxWidth: MaxContentWidth,
96
+ },
97
+ brandText: {
98
+ marginRight: 'auto',
99
+ },
100
+ pressed: {
101
+ opacity: 0.7,
102
+ },
103
+ tabButtonView: {
104
+ paddingVertical: Spacing.one,
105
+ paddingHorizontal: Spacing.three,
106
+ borderRadius: Spacing.three,
107
+ },
108
+ externalPressable: {
109
+ flexDirection: 'row',
110
+ justifyContent: 'center',
111
+ alignItems: 'center',
112
+ gap: Spacing.one,
113
+ marginLeft: Spacing.three,
114
+ },
115
+ });
@@ -0,0 +1,25 @@
1
+ import { Href, Link } from 'expo-router';
2
+ import { openBrowserAsync, WebBrowserPresentationStyle } from 'expo-web-browser';
3
+ import { type ComponentProps } from 'react';
4
+
5
+ type Props = Omit<ComponentProps<typeof Link>, 'href'> & { href: Href & string };
6
+
7
+ export function ExternalLink({ href, ...rest }: Props) {
8
+ return (
9
+ <Link
10
+ target="_blank"
11
+ {...rest}
12
+ href={href}
13
+ onPress={async (event) => {
14
+ if (process.env.EXPO_OS !== 'web') {
15
+ // Prevent the default behavior of linking to the default browser on native.
16
+ event.preventDefault();
17
+ // Open the link in an in-app browser.
18
+ await openBrowserAsync(href, {
19
+ presentationStyle: WebBrowserPresentationStyle.AUTOMATIC,
20
+ });
21
+ }
22
+ }}
23
+ />
24
+ );
25
+ }
@@ -0,0 +1,35 @@
1
+ import type { ReactNode } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+
4
+ import { ThemedText } from './themed-text';
5
+ import { ThemedView } from './themed-view';
6
+
7
+ import { Spacing } from '@/constants/theme';
8
+
9
+ type HintRowProps = {
10
+ title?: string;
11
+ hint?: ReactNode;
12
+ };
13
+
14
+ export function HintRow({ title = 'Try editing', hint = 'app/index.tsx' }: HintRowProps) {
15
+ return (
16
+ <View style={styles.stepRow}>
17
+ <ThemedText type="small">{title}</ThemedText>
18
+ <ThemedView type="backgroundSelected" style={styles.codeSnippet}>
19
+ <ThemedText themeColor="textSecondary">{hint}</ThemedText>
20
+ </ThemedView>
21
+ </View>
22
+ );
23
+ }
24
+
25
+ const styles = StyleSheet.create({
26
+ stepRow: {
27
+ flexDirection: 'row',
28
+ justifyContent: 'space-between',
29
+ },
30
+ codeSnippet: {
31
+ borderRadius: Spacing.two,
32
+ paddingVertical: Spacing.half,
33
+ paddingHorizontal: Spacing.two,
34
+ },
35
+ });
@@ -0,0 +1,73 @@
1
+ import { Platform, StyleSheet, Text, type TextProps } from 'react-native';
2
+
3
+ import { Fonts, ThemeColor } from '@/constants/theme';
4
+ import { useTheme } from '@/hooks/use-theme';
5
+
6
+ export type ThemedTextProps = TextProps & {
7
+ type?: 'default' | 'title' | 'small' | 'smallBold' | 'subtitle' | 'link' | 'linkPrimary' | 'code';
8
+ themeColor?: ThemeColor;
9
+ };
10
+
11
+ export function ThemedText({ style, type = 'default', themeColor, ...rest }: ThemedTextProps) {
12
+ const theme = useTheme();
13
+
14
+ return (
15
+ <Text
16
+ style={[
17
+ { color: theme[themeColor ?? 'text'] },
18
+ type === 'default' && styles.default,
19
+ type === 'title' && styles.title,
20
+ type === 'small' && styles.small,
21
+ type === 'smallBold' && styles.smallBold,
22
+ type === 'subtitle' && styles.subtitle,
23
+ type === 'link' && styles.link,
24
+ type === 'linkPrimary' && styles.linkPrimary,
25
+ type === 'code' && styles.code,
26
+ style,
27
+ ]}
28
+ {...rest}
29
+ />
30
+ );
31
+ }
32
+
33
+ const styles = StyleSheet.create({
34
+ small: {
35
+ fontSize: 14,
36
+ lineHeight: 20,
37
+ fontWeight: 500,
38
+ },
39
+ smallBold: {
40
+ fontSize: 14,
41
+ lineHeight: 20,
42
+ fontWeight: 700,
43
+ },
44
+ default: {
45
+ fontSize: 16,
46
+ lineHeight: 24,
47
+ fontWeight: 500,
48
+ },
49
+ title: {
50
+ fontSize: 48,
51
+ fontWeight: 600,
52
+ lineHeight: 52,
53
+ },
54
+ subtitle: {
55
+ fontSize: 32,
56
+ lineHeight: 44,
57
+ fontWeight: 600,
58
+ },
59
+ link: {
60
+ lineHeight: 30,
61
+ fontSize: 14,
62
+ },
63
+ linkPrimary: {
64
+ lineHeight: 30,
65
+ fontSize: 14,
66
+ color: '#3c87f7',
67
+ },
68
+ code: {
69
+ fontFamily: Fonts.mono,
70
+ fontWeight: Platform.select({ android: 700 }) ?? 500,
71
+ fontSize: 12,
72
+ },
73
+ });
@@ -0,0 +1,16 @@
1
+ import { View, type ViewProps } from 'react-native';
2
+
3
+ import { ThemeColor } from '@/constants/theme';
4
+ import { useTheme } from '@/hooks/use-theme';
5
+
6
+ export type ThemedViewProps = ViewProps & {
7
+ lightColor?: string;
8
+ darkColor?: string;
9
+ type?: ThemeColor;
10
+ };
11
+
12
+ export function ThemedView({ style, lightColor, darkColor, type, ...otherProps }: ThemedViewProps) {
13
+ const theme = useTheme();
14
+
15
+ return <View style={[{ backgroundColor: theme[type ?? 'background'] }, style]} {...otherProps} />;
16
+ }
@@ -0,0 +1,65 @@
1
+ import { SymbolView } from 'expo-symbols';
2
+ import { PropsWithChildren, useState } from 'react';
3
+ import { Pressable, StyleSheet } from 'react-native';
4
+ import Animated, { FadeIn } from 'react-native-reanimated';
5
+
6
+ import { ThemedText } from '@/components/themed-text';
7
+ import { ThemedView } from '@/components/themed-view';
8
+ import { Spacing } from '@/constants/theme';
9
+ import { useTheme } from '@/hooks/use-theme';
10
+
11
+ export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
12
+ const [isOpen, setIsOpen] = useState(false);
13
+ const theme = useTheme();
14
+
15
+ return (
16
+ <ThemedView>
17
+ <Pressable
18
+ style={({ pressed }) => [styles.heading, pressed && styles.pressedHeading]}
19
+ onPress={() => setIsOpen((value) => !value)}>
20
+ <ThemedView type="backgroundElement" style={styles.button}>
21
+ <SymbolView
22
+ name={{ ios: 'chevron.right', android: 'chevron_right', web: 'chevron_right' }}
23
+ size={14}
24
+ weight="bold"
25
+ tintColor={theme.text}
26
+ style={{ transform: [{ rotate: isOpen ? '-90deg' : '90deg' }] }}
27
+ />
28
+ </ThemedView>
29
+
30
+ <ThemedText type="small">{title}</ThemedText>
31
+ </Pressable>
32
+ {isOpen && (
33
+ <Animated.View entering={FadeIn.duration(200)}>
34
+ <ThemedView type="backgroundElement" style={styles.content}>
35
+ {children}
36
+ </ThemedView>
37
+ </Animated.View>
38
+ )}
39
+ </ThemedView>
40
+ );
41
+ }
42
+
43
+ const styles = StyleSheet.create({
44
+ heading: {
45
+ flexDirection: 'row',
46
+ alignItems: 'center',
47
+ gap: Spacing.two,
48
+ },
49
+ pressedHeading: {
50
+ opacity: 0.7,
51
+ },
52
+ button: {
53
+ width: Spacing.four,
54
+ height: Spacing.four,
55
+ borderRadius: 12,
56
+ justifyContent: 'center',
57
+ alignItems: 'center',
58
+ },
59
+ content: {
60
+ marginTop: Spacing.three,
61
+ borderRadius: Spacing.three,
62
+ marginLeft: Spacing.four,
63
+ padding: Spacing.four,
64
+ },
65
+ });
@@ -0,0 +1,43 @@
1
+ import { version } from 'expo/package.json';
2
+ import { Image } from 'expo-image';
3
+ import { useColorScheme, StyleSheet } from 'react-native';
4
+
5
+ import { ThemedText } from './themed-text';
6
+ import { ThemedView } from './themed-view';
7
+
8
+ import { Spacing } from '@/constants/theme';
9
+
10
+ export function WebBadge() {
11
+ const scheme = useColorScheme();
12
+
13
+ return (
14
+ <ThemedView style={styles.container}>
15
+ <ThemedText type="code" themeColor="textSecondary" style={styles.versionText}>
16
+ v{version}
17
+ </ThemedText>
18
+ <Image
19
+ source={
20
+ scheme === 'dark'
21
+ ? require('@/assets/images/expo-badge-white.png')
22
+ : require('@/assets/images/expo-badge.png')
23
+ }
24
+ style={styles.badgeImage}
25
+ />
26
+ </ThemedView>
27
+ );
28
+ }
29
+
30
+ const styles = StyleSheet.create({
31
+ container: {
32
+ padding: Spacing.five,
33
+ alignItems: 'center',
34
+ gap: Spacing.two,
35
+ },
36
+ versionText: {
37
+ textAlign: 'center',
38
+ },
39
+ badgeImage: {
40
+ width: 123,
41
+ aspectRatio: 123 / 24,
42
+ },
43
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
3
+ * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
4
+ */
5
+
6
+ import '@/global.css';
7
+
8
+ import { Platform } from 'react-native';
9
+
10
+ export const Colors = {
11
+ light: {
12
+ text: '#000000',
13
+ background: '#ffffff',
14
+ backgroundElement: '#F0F0F3',
15
+ backgroundSelected: '#E0E1E6',
16
+ textSecondary: '#60646C',
17
+ },
18
+ dark: {
19
+ text: '#ffffff',
20
+ background: '#000000',
21
+ backgroundElement: '#212225',
22
+ backgroundSelected: '#2E3135',
23
+ textSecondary: '#B0B4BA',
24
+ },
25
+ } as const;
26
+
27
+ export type ThemeColor = keyof typeof Colors.light & keyof typeof Colors.dark;
28
+
29
+ export const Fonts = Platform.select({
30
+ ios: {
31
+ /** iOS `UIFontDescriptorSystemDesignDefault` */
32
+ sans: 'system-ui',
33
+ /** iOS `UIFontDescriptorSystemDesignSerif` */
34
+ serif: 'ui-serif',
35
+ /** iOS `UIFontDescriptorSystemDesignRounded` */
36
+ rounded: 'ui-rounded',
37
+ /** iOS `UIFontDescriptorSystemDesignMonospaced` */
38
+ mono: 'ui-monospace',
39
+ },
40
+ default: {
41
+ sans: 'normal',
42
+ serif: 'serif',
43
+ rounded: 'normal',
44
+ mono: 'monospace',
45
+ },
46
+ web: {
47
+ sans: 'var(--font-display)',
48
+ serif: 'var(--font-serif)',
49
+ rounded: 'var(--font-rounded)',
50
+ mono: 'var(--font-mono)',
51
+ },
52
+ });
53
+
54
+ export const Spacing = {
55
+ half: 2,
56
+ one: 4,
57
+ two: 8,
58
+ three: 16,
59
+ four: 24,
60
+ five: 32,
61
+ six: 64,
62
+ } as const;
63
+
64
+ export const BottomTabInset = Platform.select({ ios: 50, android: 80 }) ?? 0;
65
+ export const MaxContentWidth = 800;
@@ -0,0 +1,9 @@
1
+ :root {
2
+ --font-display:
3
+ Spline Sans, Inter, ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji,
4
+ Segoe UI Symbol, Noto Color Emoji;
5
+ --font-mono:
6
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
7
+ --font-rounded: 'SF Pro Rounded', 'Hiragino Maru Gothic ProN', Meiryo, 'MS PGothic', sans-serif;
8
+ --font-serif: Georgia, 'Times New Roman', serif;
9
+ }
@@ -0,0 +1 @@
1
+ export { useColorScheme } from 'react-native';
@@ -0,0 +1,21 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useColorScheme as useRNColorScheme } from 'react-native';
3
+
4
+ /**
5
+ * To support static rendering, this value needs to be re-calculated on the client side for web
6
+ */
7
+ export function useColorScheme() {
8
+ const [hasHydrated, setHasHydrated] = useState(false);
9
+
10
+ useEffect(() => {
11
+ setHasHydrated(true);
12
+ }, []);
13
+
14
+ const colorScheme = useRNColorScheme();
15
+
16
+ if (hasHydrated) {
17
+ return colorScheme;
18
+ }
19
+
20
+ return 'light';
21
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Learn more about light and dark modes:
3
+ * https://docs.expo.dev/guides/color-schemes/
4
+ */
5
+
6
+ import { Colors } from '@/constants/theme';
7
+ import { useColorScheme } from '@/hooks/use-color-scheme';
8
+
9
+ export function useTheme() {
10
+ const scheme = useColorScheme();
11
+ const theme = scheme === 'unspecified' ? 'light' : scheme;
12
+
13
+ return Colors[theme];
14
+ }
@@ -0,0 +1,23 @@
1
+ import { Feather } from '@expo/vector-icons';
2
+ import { Text, View, StyleSheet } from 'react-native';
3
+
4
+ export const BackButton = ({ onPress }: { onPress: () => void }) => {
5
+ return (
6
+ <View style={styles.backButton}>
7
+ <Feather name="chevron-left" size={16} color="#007AFF" />
8
+ <Text style={styles.backButtonText} onPress={onPress}>
9
+ Back
10
+ </Text>
11
+ </View>
12
+ );
13
+ };
14
+ const styles = StyleSheet.create({
15
+ backButton: {
16
+ flexDirection: 'row',
17
+ paddingLeft: 20,
18
+ },
19
+ backButtonText: {
20
+ color: '#007AFF',
21
+ marginLeft: 4,
22
+ },
23
+ });