@mediacubeco/expo-template-fsd 2.0.2 → 2.1.1

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 (47) hide show
  1. package/.agents/README.md +8 -0
  2. package/.claude/README.md +8 -0
  3. package/.claude/settings.local.json +1 -7
  4. package/.claude/skills/generate-api-model/references/entities/common.ts +1 -1
  5. package/.gitignore +36 -0
  6. package/.husky/README.md +8 -0
  7. package/.secret/README.md +1 -1
  8. package/README.md +1 -1
  9. package/app.json +9 -7
  10. package/package.json +45 -16
  11. package/skills-lock.json +3 -3
  12. package/src/app/(root)/_layout.tsx +17 -11
  13. package/src/app/_app.tsx +1 -1
  14. package/src/app/_layout.tsx +19 -11
  15. package/src/shared/assets/images/index.ts +2 -1
  16. package/src/shared/assets/images/splash-dark.png +0 -0
  17. package/src/shared/assets/images/splash-light.png +0 -0
  18. package/src/shared/hooks/use-safe-area.ts +31 -12
  19. package/src/shared/lib/api/api.provider.tsx +2 -2
  20. package/src/shared/lib/api/entities/common.ts +1 -1
  21. package/src/shared/lib/index.ts +1 -0
  22. package/src/shared/lib/localization/utils/storage.ts +2 -6
  23. package/src/shared/lib/navigation/hooks/index.ts +1 -0
  24. package/src/shared/lib/navigation/hooks/use-navigation-native-tabs.ts +10 -0
  25. package/src/shared/lib/navigation/hooks/use-navigation-options.ts +2 -2
  26. package/src/shared/lib/navigation/index.ts +2 -0
  27. package/src/shared/lib/navigation/navigation-native-tabs.context.tsx +5 -0
  28. package/src/shared/lib/navigation/navigation-native-tabs.provider.tsx +12 -0
  29. package/src/shared/lib/storage/index.ts +2 -0
  30. package/src/shared/lib/storage/storage.provider.tsx +7 -0
  31. package/src/shared/lib/storage/storage.ts +27 -0
  32. package/src/shared/lib/storage/storage.types.ts +5 -0
  33. package/src/shared/lib/theme/theme.provider.tsx +10 -11
  34. package/src/shared/lib/theme/utils/index.ts +1 -1
  35. package/src/shared/lib/theme/utils/storage.ts +2 -6
  36. package/src/shared/ui/atoms/blur/blur.tsx +27 -0
  37. package/src/shared/ui/atoms/blur/blur.types.ts +9 -0
  38. package/src/shared/ui/atoms/blur/index.ts +2 -0
  39. package/src/shared/ui/atoms/glass/glass.tsx +26 -0
  40. package/src/shared/ui/atoms/glass/glass.types.ts +9 -0
  41. package/src/shared/ui/atoms/glass/index.ts +2 -0
  42. package/src/shared/ui/atoms/index.ts +2 -1
  43. package/src/shared/ui/molecules/keyboard-area/keyboard-area.styles.ts +5 -5
  44. package/src/shared/ui/molecules/keyboard-area/keyboard-area.tsx +1 -21
  45. package/src/shared/assets/images/splash.png +0 -0
  46. package/src/shared/lib/api/utils/index.ts +0 -1
  47. package/src/shared/lib/api/utils/storage.ts +0 -9
@@ -0,0 +1,8 @@
1
+ # `.agents`
2
+
3
+ This folder stores independent agent definitions and related assets. They must stay isolated and should not pollute the main project context.
4
+
5
+ ## What should be stored here
6
+
7
+ - Agent-specific skills, rules, prompts, and helper files.
8
+ - Context-isolated assets that are not part of the app runtime flow.
@@ -0,0 +1,8 @@
1
+ # `.claude`
2
+
3
+ This folder stores Claude-specific independent agents and related configuration. They must stay isolated and should not pollute the main project context.
4
+
5
+ ## What should be stored here
6
+
7
+ - Claude rules, settings, skills, and supporting files.
8
+ - Context-isolated configuration that is separate from app runtime logic.
@@ -1,11 +1,5 @@
1
1
  {
2
2
  "permissions": {
3
- "allow": [
4
- "Read(//Users/alkhimenok/Public/Programing/Work/kit/**)",
5
- "Bash(npm view *)",
6
- "Bash(npx expo *)",
7
- "Bash(npx expo-doctor *)",
8
- "Bash(pnpm install *)"
9
- ]
3
+ "allow": ["Bash(npm *)", "Bash(npx *)"]
10
4
  }
11
5
  }
@@ -1,4 +1,4 @@
1
- import { generateIdFactory } from '@mediacontent/base/utils'
1
+ import { generateIdFactory } from '@mediacubeco/base/utils'
2
2
  import { type BaseResource } from '../resources'
3
3
 
4
4
  const generateId = generateIdFactory()
package/.gitignore ADDED
@@ -0,0 +1,36 @@
1
+ # dependencies
2
+ node_modules/
3
+ yarn-debug.*
4
+ yarn-error.*
5
+
6
+ # expo
7
+ .expo/
8
+ dist/
9
+ web-build/
10
+
11
+ # native
12
+ /ios
13
+ /android
14
+ .kotlin/
15
+ .DS_Store
16
+ .metro-health-check*
17
+ *.orig.*
18
+ *.pem
19
+ *.jks
20
+ *.p8
21
+ *.p12
22
+ *.key
23
+ *.mobileprovision
24
+
25
+ # typescript
26
+ *.tsbuildinfo
27
+
28
+ # secret
29
+ /.secret/*
30
+ !/.secret/README.md
31
+
32
+ # env
33
+ .env*.local
34
+
35
+ # ai
36
+ .agents/skills/
@@ -0,0 +1,8 @@
1
+ # `.husky`
2
+
3
+ This folder stores Git hooks used to enforce repository checks before commit or push.
4
+
5
+ ## What should be stored here
6
+
7
+ - Husky hook scripts (for example, `pre-commit`, `commit-msg`, `pre-push`).
8
+ - Hook-related helper scripts that validate code quality and commit hygiene.
package/.secret/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # `.secret` Folder
1
+ # `.secret`
2
2
 
3
3
  This folder stores **secret and sensitive** files that must never be committed to the repository. The folder is included in `.gitignore`.
4
4
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Expo Template FSD
1
+ # Expo-Template-FSD
2
2
 
3
3
  This project is built on top of the `@mediacubeco/expo-template-fsd` template.
4
4
 
package/app.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "expo": {
3
3
  "name": "expo-template-fsd",
4
4
  "slug": "expo-template-fsd",
5
- "scheme": "expotemplatefsd",
5
+ "scheme": "expo-template-fsd",
6
6
  "version": "1.0.0",
7
7
  "orientation": "portrait",
8
8
  "userInterfaceStyle": "automatic",
@@ -12,14 +12,14 @@
12
12
  },
13
13
  "ios": {
14
14
  "supportsTablet": true,
15
- "bundleIdentifier": "com.mediacube.expotemplatefsd",
15
+ "bundleIdentifier": "com.mediacube.expo-template-fsd",
16
16
  "icon": "./src/shared/assets/images/logo-ios.png"
17
17
  },
18
18
  "android": {
19
19
  "predictiveBackGestureEnabled": false,
20
- "package": "com.mediacube.expotemplatefsd",
20
+ "package": "com.mediacube.expo-template-fsd",
21
21
  "adaptiveIcon": {
22
- "backgroundColor": "#E6F4FE",
22
+ "backgroundColor": "#ffffff00",
23
23
  "foregroundImage": "./src/shared/assets/images/logo-android-foreground.png",
24
24
  "backgroundImage": "./src/shared/assets/images/logo-android-background.png",
25
25
  "monochromeImage": "./src/shared/assets/images/logo-android-monochrome.png"
@@ -36,10 +36,12 @@
36
36
  [
37
37
  "expo-splash-screen",
38
38
  {
39
- "backgroundColor": "#208AEF",
39
+ "backgroundColor": "#ffffff00",
40
40
  "android": {
41
- "image": "./assets/images/splash-icon.png",
42
- "imageWidth": 76
41
+ "image": "./src/shared/assets/images/splash-light.png",
42
+ "dark": {
43
+ "image": "./src/shared/assets/images/splash-dark.png"
44
+ }
43
45
  }
44
46
  }
45
47
  ]
package/package.json CHANGED
@@ -1,11 +1,40 @@
1
1
  {
2
2
  "private": false,
3
- "version": "2.0.2",
3
+ "version": "2.1.1",
4
4
  "name": "@mediacubeco/expo-template-fsd",
5
5
  "description": "Application by Mediacube developers",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
8
  "main": "expo-router/entry",
9
+ "files": [
10
+ ".agents",
11
+ ".claude",
12
+ ".husky",
13
+ ".secret",
14
+ "src",
15
+ ".env",
16
+ ".env.example",
17
+ ".gitignore",
18
+ "AGENTS.md",
19
+ "app.json",
20
+ "CLAUDE.md",
21
+ "env.d.ts",
22
+ "eslint.config.js",
23
+ "expo-env.d.ts",
24
+ "i18next.d.ts",
25
+ "package-lock.json",
26
+ "package.json",
27
+ "prettier.config.js",
28
+ "README.md",
29
+ "skills-lock.json",
30
+ "svg.d.ts",
31
+ "tsconfig.json"
32
+ ],
33
+ "keywords": [
34
+ "mediacube",
35
+ "mediacubeco",
36
+ "application"
37
+ ],
9
38
  "dependencies": {
10
39
  "@tanstack/query-async-storage-persister": "^5.99.0",
11
40
  "@tanstack/react-query": "^5.99.0",
@@ -41,9 +70,9 @@
41
70
  "react-native-svg": "15.15.4",
42
71
  "react-native-web": "^0.21.0",
43
72
  "react-native-worklets": "0.8.3",
44
- "@mediacubeco/base-react-native": "2.0.2",
45
- "@mediacubeco/base-react": "2.0.2",
46
- "@mediacubeco/base": "2.0.2"
73
+ "@mediacubeco/base-react-native": "2.1.0",
74
+ "@mediacubeco/base": "2.1.0",
75
+ "@mediacubeco/base-react": "2.1.0"
47
76
  },
48
77
  "devDependencies": {
49
78
  "@types/react": "^19.2.0",
@@ -52,24 +81,24 @@
52
81
  "husky": "^9.1.7",
53
82
  "prettier": "^3.8.1",
54
83
  "typescript": "^6.0.3",
55
- "@mediacubeco/eslint-config-react": "2.0.2",
56
- "@mediacubeco/eslint-config": "2.0.2",
57
- "@mediacubeco/prettier-config": "2.0.2",
58
- "@mediacubeco/eslint-config-react-native": "2.0.2",
59
- "@mediacubeco/prettier-config-fsd": "2.0.2",
60
- "@mediacubeco/eslint-config-fsd": "2.0.2",
61
- "@mediacubeco/typescript-config": "2.0.2",
62
- "@mediacubeco/typescript-config-react": "2.0.2",
63
- "@mediacubeco/typescript-config-react-native": "2.0.2",
64
- "@mediacubeco/typescript-config-fsd": "2.0.2"
84
+ "@mediacubeco/eslint-config-fsd": "2.1.0",
85
+ "@mediacubeco/eslint-config": "2.1.0",
86
+ "@mediacubeco/eslint-config-react": "2.1.0",
87
+ "@mediacubeco/eslint-config-react-native": "2.1.0",
88
+ "@mediacubeco/prettier-config-fsd": "2.1.0",
89
+ "@mediacubeco/prettier-config": "2.1.0",
90
+ "@mediacubeco/typescript-config": "2.1.0",
91
+ "@mediacubeco/typescript-config-fsd": "2.1.0",
92
+ "@mediacubeco/typescript-config-react": "2.1.0",
93
+ "@mediacubeco/typescript-config-react-native": "2.1.0"
65
94
  },
66
95
  "scripts": {
67
96
  "postinstall": "npx husky && npx skills update",
68
97
  "prebuild": "expo prebuild",
69
98
  "start": "expo start",
70
- "android": "expo start --android",
99
+ "android": "expo run:android",
71
100
  "android:device": "expo run:android -d",
72
- "ios": "expo start --ios",
101
+ "ios": "expo run:ios",
73
102
  "ios:device": "expo run:ios -d",
74
103
  "web": "expo start --web",
75
104
  "format": "prettier --write ./src",
package/skills-lock.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "source": "pbakaus/impeccable",
6
6
  "sourceType": "github",
7
7
  "skillPath": ".agents/skills/impeccable/SKILL.md",
8
- "computedHash": "2f248d7db158d32acb8d52e688444de1edbaccf7344ac5288634cbe427bc8a8a"
8
+ "computedHash": "5e8c66eeffba8dc0c5e0941afbf4aecd6359184f8b0ea08cfc60a33f2e328e49"
9
9
  },
10
10
  "react-native-best-practices": {
11
11
  "source": "callstackincubator/agent-skills",
@@ -17,13 +17,13 @@
17
17
  "source": "vercel-labs/agent-skills",
18
18
  "sourceType": "github",
19
19
  "skillPath": "skills/react-best-practices/SKILL.md",
20
- "computedHash": "ca7b0c0c6e5f2750043f7f0cd72d16ac4e2abc48f9b5500d047a4b77a2506212"
20
+ "computedHash": "3219a1944e404ffc14d1d9d6aef6dd2e3855b81387ee0a044ccbfe14d34c2357"
21
21
  },
22
22
  "vercel-react-native-skills": {
23
23
  "source": "vercel-labs/agent-skills",
24
24
  "sourceType": "github",
25
25
  "skillPath": "skills/react-native-skills/SKILL.md",
26
- "computedHash": "41d24eafa7c3d82e270439808f7cfbc4d51aeb2d14f2809a2267c16275784d06"
26
+ "computedHash": "2e9088a7333666d8c2833b8ff58bd51b955501c42b4c7244f72b4cbf22dafcc4"
27
27
  }
28
28
  }
29
29
  }
@@ -1,5 +1,9 @@
1
1
  import { NativeTabs } from 'expo-router/build/native-tabs'
2
- import { useLocalizationText, useNavigationTabBarOptions } from '~shared/lib'
2
+ import {
3
+ NavigationNativeTabsProvider,
4
+ useLocalizationText,
5
+ useNavigationTabBarOptions,
6
+ } from '~shared/lib'
3
7
 
4
8
  const Layout = () => {
5
9
  const { createTabBarOptions, createTabOptions } = useNavigationTabBarOptions()
@@ -22,16 +26,18 @@ const Layout = () => {
22
26
  })
23
27
 
24
28
  return (
25
- <NativeTabs {...tabBarOptions}>
26
- <NativeTabs.Trigger {...homeTabOptions.triggerProps}>
27
- <NativeTabs.Trigger.Label {...homeTabOptions.triggerLabelProps} />
28
- <NativeTabs.Trigger.Icon {...homeTabOptions.triggerIconProps} />
29
- </NativeTabs.Trigger>
30
- <NativeTabs.Trigger {...settingsTabOptions.triggerProps}>
31
- <NativeTabs.Trigger.Label {...settingsTabOptions.triggerLabelProps} />
32
- <NativeTabs.Trigger.Icon {...settingsTabOptions.triggerIconProps} />
33
- </NativeTabs.Trigger>
34
- </NativeTabs>
29
+ <NavigationNativeTabsProvider>
30
+ <NativeTabs {...tabBarOptions}>
31
+ <NativeTabs.Trigger {...homeTabOptions.triggerProps}>
32
+ <NativeTabs.Trigger.Label {...homeTabOptions.triggerLabelProps} />
33
+ <NativeTabs.Trigger.Icon {...homeTabOptions.triggerIconProps} />
34
+ </NativeTabs.Trigger>
35
+ <NativeTabs.Trigger {...settingsTabOptions.triggerProps}>
36
+ <NativeTabs.Trigger.Label {...settingsTabOptions.triggerLabelProps} />
37
+ <NativeTabs.Trigger.Icon {...settingsTabOptions.triggerIconProps} />
38
+ </NativeTabs.Trigger>
39
+ </NativeTabs>
40
+ </NavigationNativeTabsProvider>
35
41
  )
36
42
  }
37
43
 
package/src/app/_app.tsx CHANGED
@@ -10,7 +10,7 @@ const App = () => {
10
10
  <>
11
11
  <StatusBar style={'auto'} />
12
12
  <NavigationBar style={'auto'} />
13
- <Stack screenOptions={createStackOptions()}>
13
+ <Stack initialRouteName={'(root)'} screenOptions={createStackOptions()}>
14
14
  <Stack.Screen name={'(root)'} />
15
15
  </Stack>
16
16
  </>
@@ -1,19 +1,27 @@
1
- import { ApiProvider, LocalizationProvider, NavigationProvider, ThemeProvider } from '~shared/lib'
1
+ import {
2
+ ApiProvider,
3
+ LocalizationProvider,
4
+ NavigationProvider,
5
+ StorageProvider,
6
+ ThemeProvider,
7
+ } from '~shared/lib'
2
8
  import App from './_app'
3
9
  import Splash from './_splash'
4
10
 
5
11
  const Layout = () => {
6
12
  return (
7
- <ApiProvider>
8
- <ThemeProvider>
9
- <LocalizationProvider>
10
- <NavigationProvider>
11
- <App />
12
- <Splash />
13
- </NavigationProvider>
14
- </LocalizationProvider>
15
- </ThemeProvider>
16
- </ApiProvider>
13
+ <StorageProvider>
14
+ <ApiProvider>
15
+ <ThemeProvider>
16
+ <LocalizationProvider>
17
+ <NavigationProvider>
18
+ <App />
19
+ <Splash />
20
+ </NavigationProvider>
21
+ </LocalizationProvider>
22
+ </ThemeProvider>
23
+ </ApiProvider>
24
+ </StorageProvider>
17
25
  )
18
26
  }
19
27
 
@@ -4,7 +4,8 @@ const IMAGES = {
4
4
  LOGO_ANDROID_BACKGROUND: require('./logo-android-background.png'),
5
5
  LOGO_ANDROID_FOREGROUND: require('./logo-android-foreground.png'),
6
6
  LOGO_ANDROID_MONOCHROME: require('./logo-android-monochrome.png'),
7
- SPLASH: require('./splash.png'),
7
+ SPLASH_LIGHT: require('./splash-light.png'),
8
+ SPLASH_DARK: require('./splash-dark.png'),
8
9
  DEFAULT: require('./default.png'),
9
10
  }
10
11
 
@@ -1,7 +1,8 @@
1
- import { Platform } from 'react-native'
1
+ import { Platform } from '@mediacubeco/base-react-native'
2
2
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
3
3
  import { useBottomTabBarHeight } from 'expo-router/js-tabs'
4
4
  import { useHeaderHeight } from 'expo-router/react-navigation'
5
+ import { useNavigationNativeTabs } from '../lib'
5
6
 
6
7
  const ANDROID_TAB_BAR_DEFAULT_HEIGHT = 56
7
8
  const IOS_TAB_BAR_DEFAULT_HEIGHT = 50
@@ -10,7 +11,7 @@ const useNavigationHeaderHeight = (safeArea: number = 0) => {
10
11
  try {
11
12
  const height = useHeaderHeight()
12
13
 
13
- return Platform.select({
14
+ return Platform.by({
14
15
  android: height ? 0 : safeArea,
15
16
  ios: height || safeArea,
16
17
  default: safeArea,
@@ -21,19 +22,36 @@ const useNavigationHeaderHeight = (safeArea: number = 0) => {
21
22
  }
22
23
 
23
24
  const useNavigationFooterHeight = (safeArea: number = 0) => {
25
+ const isNativeTabs = useNavigationNativeTabs()
26
+
24
27
  try {
25
28
  const height = useBottomTabBarHeight()
26
29
 
27
- return Platform.select({
28
- android: (height || ANDROID_TAB_BAR_DEFAULT_HEIGHT) + safeArea,
29
- ios: (height || IOS_TAB_BAR_DEFAULT_HEIGHT) + safeArea,
30
- default: safeArea,
31
- })
30
+ return {
31
+ bottom: Platform.by({
32
+ android: height ? 0 : safeArea,
33
+ ios: height ? 0 : safeArea,
34
+ default: safeArea,
35
+ }),
36
+ value: Platform.by({
37
+ android: height,
38
+ ios: height,
39
+ default: safeArea,
40
+ }),
41
+ }
32
42
  } catch (_) {
33
- return Platform.select({
34
- android: 0,
35
- default: safeArea,
36
- })
43
+ return {
44
+ bottom: Platform.by({
45
+ android: isNativeTabs ? 0 : safeArea,
46
+ ios: safeArea,
47
+ default: safeArea,
48
+ }),
49
+ value: Platform.by({
50
+ android: isNativeTabs ? safeArea * 2 + ANDROID_TAB_BAR_DEFAULT_HEIGHT : safeArea,
51
+ ios: isNativeTabs ? safeArea + IOS_TAB_BAR_DEFAULT_HEIGHT : safeArea,
52
+ default: safeArea,
53
+ }),
54
+ }
37
55
  }
38
56
  }
39
57
 
@@ -44,7 +62,8 @@ const useSafeArea = () => {
44
62
 
45
63
  return {
46
64
  TOP: header,
47
- BOTTOM: footer,
65
+ BOTTOM: footer.bottom,
66
+ FOOTER: footer.value,
48
67
  LEFT: left,
49
68
  RIGHT: right,
50
69
  }
@@ -5,7 +5,7 @@ import {
5
5
  PersistQueryClientProvider,
6
6
  type PersistQueryClientProviderProps,
7
7
  } from '@tanstack/react-query-persist-client'
8
- import { apiAsyncStorage } from './utils'
8
+ import { storageAsync } from '../storage'
9
9
  import { type ApiProviderProps } from './api.types'
10
10
 
11
11
  const client = new QueryClient({
@@ -25,7 +25,7 @@ const persistOptions = {
25
25
  },
26
26
  },
27
27
  persister: createAsyncStoragePersister({
28
- storage: apiAsyncStorage,
28
+ storage: storageAsync,
29
29
  throttleTime: 1000,
30
30
  }),
31
31
  } satisfies PersistQueryClientProviderProps['persistOptions']
@@ -1,4 +1,4 @@
1
- import { generateIdFactory } from '@mediacontent/base/utils'
1
+ import { generateIdFactory } from '@mediacubeco/base/utils'
2
2
  import { type BaseResource } from '../resources'
3
3
 
4
4
  const generateId = generateIdFactory()
@@ -1,4 +1,5 @@
1
1
  export * from './api'
2
2
  export * from './localization'
3
3
  export * from './navigation'
4
+ export * from './storage'
4
5
  export * from './theme'
@@ -1,11 +1,7 @@
1
1
  import { Storage } from '@mediacubeco/base/services'
2
- import * as SecureStore from 'expo-secure-store'
2
+ import { storageModel } from '../../storage'
3
3
  import { type LocalizationCode } from '../constants'
4
4
 
5
- const localizationStorage = new Storage({
6
- get: SecureStore.getItemAsync,
7
- set: SecureStore.setItemAsync,
8
- delete: SecureStore.deleteItemAsync,
9
- }).create<'code', LocalizationCode>('code')
5
+ const localizationStorage = new Storage(storageModel).create<'code', LocalizationCode>('code')
10
6
 
11
7
  export { localizationStorage }
@@ -1,3 +1,4 @@
1
1
  export * from './use-navigation'
2
2
  export * from './use-navigation-params'
3
3
  export * from './use-navigation-options'
4
+ export * from './use-navigation-native-tabs'
@@ -0,0 +1,10 @@
1
+ import { useContext } from 'react'
2
+ import { NavigationNativeTabsContext } from '../navigation-native-tabs.context'
3
+
4
+ const useNavigationNativeTabs = () => {
5
+ const isNativeTabs = useContext(NavigationNativeTabsContext)
6
+
7
+ return isNativeTabs
8
+ }
9
+
10
+ export { useNavigationNativeTabs }
@@ -1,5 +1,5 @@
1
+ import { Platform } from '@mediacubeco/base-react-native'
1
2
  import { useCallback } from 'react'
2
- import { Platform } from 'react-native'
3
3
  import { isGlassEffectAPIAvailable } from 'expo-glass-effect'
4
4
  import { type StackScreenProps } from 'expo-router'
5
5
  import {
@@ -43,7 +43,7 @@ const useNavigationStackOptions = () => {
43
43
  headerBlurEffect: isGlassEffectAPIAvailable() ? 'none' : themeModeSystem,
44
44
  headerTintColor: COLORS.TYPOGRAPHY.BASE,
45
45
  headerStyle: {
46
- backgroundColor: Platform.select({
46
+ backgroundColor: Platform.by({
47
47
  ios: COLORS.FILL.TRANSPARENT,
48
48
  default: COLORS.FILL.CONTRAST,
49
49
  }),
@@ -3,5 +3,7 @@ export {
3
3
  useNavigationParams,
4
4
  useNavigationStackOptions,
5
5
  useNavigationTabBarOptions,
6
+ useNavigationNativeTabs,
6
7
  } from './hooks'
7
8
  export { default as NavigationProvider } from './navigation.provider'
9
+ export { default as NavigationNativeTabsProvider } from './navigation-native-tabs.provider'
@@ -0,0 +1,5 @@
1
+ import { createContext } from 'react'
2
+
3
+ const NavigationNativeTabsContext = createContext(false)
4
+
5
+ export { NavigationNativeTabsContext }
@@ -0,0 +1,12 @@
1
+ import { NavigationNativeTabsContext } from './navigation-native-tabs.context'
2
+ import { type NavigationProviderProps } from './navigation.types'
3
+
4
+ const NavigationNativeTabsProvider = ({ children }: NavigationProviderProps) => {
5
+ return (
6
+ <NavigationNativeTabsContext.Provider value={true}>
7
+ {children}
8
+ </NavigationNativeTabsContext.Provider>
9
+ )
10
+ }
11
+
12
+ export default NavigationNativeTabsProvider
@@ -0,0 +1,2 @@
1
+ export { default as StorageProvider } from './storage.provider'
2
+ export { storageAsync, storageModel } from './storage'
@@ -0,0 +1,7 @@
1
+ import { type StorageProviderProps } from './storage.types'
2
+
3
+ const StorageProvider = ({ children }: StorageProviderProps) => {
4
+ return <>{children}</>
5
+ }
6
+
7
+ export default StorageProvider
@@ -0,0 +1,27 @@
1
+ import { Platform } from '@mediacubeco/base-react-native'
2
+ import * as SecureStore from 'expo-secure-store'
3
+
4
+ const storageModelNative = {
5
+ getItem: SecureStore.getItemAsync,
6
+ setItem: SecureStore.setItemAsync,
7
+ removeItem: SecureStore.deleteItemAsync,
8
+ }
9
+
10
+ const storageModelWeb = {
11
+ getItem: (key: string) => Promise.resolve(localStorage.getItem(key)),
12
+ setItem: (key: string, value: string) => Promise.resolve(localStorage.setItem(key, value)),
13
+ removeItem: (key: string) => Promise.resolve(localStorage.removeItem(key)),
14
+ }
15
+
16
+ const storageAsync = Platform.by({
17
+ web: storageModelWeb,
18
+ default: storageModelNative,
19
+ })
20
+
21
+ const storageModel = {
22
+ get: storageAsync.getItem,
23
+ set: storageAsync.setItem,
24
+ delete: storageAsync.removeItem,
25
+ }
26
+
27
+ export { storageAsync, storageModel }
@@ -0,0 +1,5 @@
1
+ import { type PropsWithChildren } from 'react'
2
+
3
+ type StorageProviderProps = PropsWithChildren
4
+
5
+ export type { StorageProviderProps }
@@ -1,4 +1,3 @@
1
- import { Platform } from '@mediacubeco/base-react-native'
2
1
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
3
2
  import { Appearance, StatusBar, useColorScheme } from 'react-native'
4
3
  import { themeStorage } from './utils'
@@ -22,15 +21,15 @@ const ThemeProvider = ({ children }: ThemeProviderProps) => {
22
21
  }, [currentThemeMode])
23
22
 
24
23
  const updateThemeModeSystem = useCallback((themeMode: ThemeMode) => {
25
- if (Platform.isIos) {
26
- if (!hasDarkMode) {
27
- Appearance.setColorScheme('light')
28
- } else if (themeMode === ThemeMode.System) {
29
- Appearance.setColorScheme('unspecified')
30
- } else {
31
- Appearance.setColorScheme(themeMode)
32
- }
24
+ // if (Platform.isIos) {
25
+ if (!hasDarkMode) {
26
+ Appearance.setColorScheme('light')
27
+ } else if (themeMode === ThemeMode.System) {
28
+ Appearance.setColorScheme('unspecified')
29
+ } else {
30
+ Appearance.setColorScheme(themeMode)
33
31
  }
32
+ // }
34
33
  }, [])
35
34
 
36
35
  useEffect(() => {
@@ -53,9 +52,9 @@ const ThemeProvider = ({ children }: ThemeProviderProps) => {
53
52
  const updateThemeMode = async () => {
54
53
  if (didDefine.current) {
55
54
  await themeStorage.mode.set(themeMode)
56
-
57
- updateThemeModeSystem(themeMode)
58
55
  }
56
+
57
+ updateThemeModeSystem(themeMode)
59
58
  }
60
59
 
61
60
  updateThemeMode()
@@ -1 +1 @@
1
- export * from './storage'
1
+ export { themeStorage } from './storage'
@@ -1,11 +1,7 @@
1
1
  import { Storage } from '@mediacubeco/base/services'
2
- import * as SecureStore from 'expo-secure-store'
2
+ import { storageModel } from '../../storage'
3
3
  import { type ThemeMode } from '../constants'
4
4
 
5
- const themeStorage = new Storage({
6
- get: SecureStore.getItemAsync,
7
- set: SecureStore.setItemAsync,
8
- delete: SecureStore.deleteItemAsync,
9
- }).create<'mode', ThemeMode>('mode')
5
+ const themeStorage = new Storage(storageModel).create<'mode', ThemeMode>('mode')
10
6
 
11
7
  export { themeStorage }
@@ -0,0 +1,27 @@
1
+ import { type Ref } from 'react'
2
+ import { BlurView } from 'expo-blur'
3
+ import { type BlurProps } from './blur.types'
4
+
5
+ const Blur = ({
6
+ reference,
7
+ blurTarget,
8
+ tint,
9
+ intensity,
10
+ blurReductionFactor,
11
+ blurMethod,
12
+ ...props
13
+ }: BlurProps) => {
14
+ return (
15
+ <BlurView
16
+ ref={reference as Ref<BlurView>}
17
+ blurTarget={blurTarget}
18
+ tint={tint}
19
+ intensity={intensity}
20
+ blurReductionFactor={blurReductionFactor}
21
+ blurMethod={blurMethod}
22
+ {...props}
23
+ />
24
+ )
25
+ }
26
+
27
+ export default Blur
@@ -0,0 +1,9 @@
1
+ import { type Ref } from 'react'
2
+ import { type View } from 'react-native'
3
+ import { type BlurViewProps } from 'expo-blur'
4
+
5
+ type BlurProps = BlurViewProps & {
6
+ reference?: Ref<View>
7
+ }
8
+
9
+ export type { BlurProps }
@@ -0,0 +1,2 @@
1
+ export { default as Blur } from './blur'
2
+ export type { BlurProps } from './blur.types'
@@ -0,0 +1,26 @@
1
+ import { GlassView, isGlassEffectAPIAvailable } from 'expo-glass-effect'
2
+ import { Blur } from '../blur'
3
+ import { type GlassProps } from './glass.types'
4
+
5
+ const Glass = ({
6
+ reference,
7
+ glassEffectStyle = 'clear',
8
+ tintColor,
9
+ colorScheme,
10
+ isInteractive = true,
11
+ ...props
12
+ }: GlassProps) => {
13
+ return isGlassEffectAPIAvailable() ? (
14
+ <GlassView
15
+ ref={reference}
16
+ glassEffectStyle={glassEffectStyle}
17
+ tintColor={tintColor}
18
+ colorScheme={colorScheme}
19
+ isInteractive={isInteractive}
20
+ {...props}
21
+ />
22
+ ) : (
23
+ <Blur reference={reference} {...props} />
24
+ )
25
+ }
26
+ export default Glass
@@ -0,0 +1,9 @@
1
+ import { type Ref } from 'react'
2
+ import { type View } from 'react-native'
3
+ import { type GlassViewProps } from 'expo-glass-effect'
4
+
5
+ type GlassProps = GlassViewProps & {
6
+ reference?: Ref<View>
7
+ }
8
+
9
+ export type { GlassProps }
@@ -0,0 +1,2 @@
1
+ export { default as Glass } from './glass'
2
+ export type { GlassProps } from './glass.types'
@@ -1 +1,2 @@
1
- export const atoms = {}
1
+ export * from './blur'
2
+ export * from './glass'
@@ -1,18 +1,18 @@
1
+ import { useAnimatedKeyboard } from 'react-native-keyboard-controller'
1
2
  import { useAnimated, useAnimatedStyle, useSafeArea } from '../../../hooks'
2
3
 
3
4
  const useKeyboardAreaStyles = () => {
4
- const { BOTTOM } = useSafeArea()
5
- const [safeAreaHeight] = useAnimated(BOTTOM)
6
- const [keyboardHeight] = useAnimated<number>(0)
5
+ const { FOOTER } = useSafeArea()
6
+ const { height } = useAnimatedKeyboard()
7
+ const [safeAreaHeight] = useAnimated(FOOTER)
7
8
 
8
9
  const keyboardAnimatedStyle = useAnimatedStyle(() => {
9
10
  return {
10
- height: keyboardHeight.value - safeAreaHeight.value,
11
+ height: height.value - safeAreaHeight.value,
11
12
  }
12
13
  })
13
14
 
14
15
  return {
15
- keyboardHeight,
16
16
  keyboardAnimatedStyle,
17
17
  }
18
18
  }
@@ -1,5 +1,4 @@
1
1
  import { View } from 'react-native'
2
- import { useKeyboardHandler } from 'react-native-keyboard-controller'
3
2
  import { animate } from '../../../hooks'
4
3
  import { useKeyboardAreaStyles } from './keyboard-area.styles'
5
4
  import { type KeyboardAreaProps } from './keyboard-area.types'
@@ -7,26 +6,7 @@ import { type KeyboardAreaProps } from './keyboard-area.types'
7
6
  const KeyboardAnimatedArea = animate(View)
8
7
 
9
8
  const KeyboardArea = ({}: KeyboardAreaProps) => {
10
- const { keyboardHeight, keyboardAnimatedStyle } = useKeyboardAreaStyles()
11
-
12
- useKeyboardHandler(
13
- {
14
- onStart: () => {
15
- 'worklet'
16
- },
17
- onMove: (event) => {
18
- 'worklet'
19
-
20
- keyboardHeight.set(event.height)
21
- },
22
- onEnd: (event) => {
23
- 'worklet'
24
-
25
- keyboardHeight.set(event.height)
26
- },
27
- },
28
- []
29
- )
9
+ const { keyboardAnimatedStyle } = useKeyboardAreaStyles()
30
10
 
31
11
  return <KeyboardAnimatedArea style={keyboardAnimatedStyle} />
32
12
  }
Binary file
@@ -1 +0,0 @@
1
- export * from './storage'
@@ -1,9 +0,0 @@
1
- import * as SecureStore from 'expo-secure-store'
2
-
3
- const apiAsyncStorage = {
4
- getItem: SecureStore.getItemAsync,
5
- setItem: SecureStore.setItemAsync,
6
- removeItem: SecureStore.deleteItemAsync,
7
- }
8
-
9
- export { apiAsyncStorage }