@mediacubeco/expo-template-fsd 1.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.
- package/.claude/mcp.json +0 -0
- package/.claude/rules/abstract-skills-agents.mdc +25 -0
- package/.claude/rules/app-routing.mdc +47 -0
- package/.claude/rules/exports-at-end.mdc +55 -0
- package/.claude/rules/kebab-case-naming.mdc +29 -0
- package/.claude/rules/prettier-eslint-typescript.mdc +24 -0
- package/.claude/settings.json +0 -0
- package/.claude/skills/generate-api-model/SKILL.md +98 -0
- package/.claude/skills/generate-api-model-mock/SKILL.md +56 -0
- package/.env +1 -0
- package/.env.example +1 -0
- package/.husky/pre-commit +6 -0
- package/.secret/README.md +26 -0
- package/README.md +36 -0
- package/app.config.js +54 -0
- package/env.d.ts +7 -0
- package/eslint.config.js +14 -0
- package/i18next.d.ts +12 -0
- package/package.json +76 -0
- package/prettier.config.js +9 -0
- package/src/app/_app.tsx +18 -0
- package/src/app/_layout.tsx +20 -0
- package/src/app/_splash.tsx +22 -0
- package/src/entities/.gitkeep +0 -0
- package/src/features/.gitkeep +0 -0
- package/src/screens/.gitkeep +0 -0
- package/src/shared/assets/fonts/index.ts +7 -0
- package/src/shared/assets/icons/index.ts +3 -0
- package/src/shared/assets/icons/like.tsx +17 -0
- package/src/shared/assets/icons/type.ts +6 -0
- package/src/shared/assets/images/default.png +0 -0
- package/src/shared/assets/images/index.ts +11 -0
- package/src/shared/assets/images/logo-android-background.png +0 -0
- package/src/shared/assets/images/logo-android-foreground.png +0 -0
- package/src/shared/assets/images/logo-android-monochrome.png +0 -0
- package/src/shared/assets/images/logo-ios.png +0 -0
- package/src/shared/assets/images/logo-web.png +0 -0
- package/src/shared/assets/images/splash-dark.png +0 -0
- package/src/shared/assets/images/splash.png +0 -0
- package/src/shared/assets/index.ts +4 -0
- package/src/shared/assets/translations/en.ts +3 -0
- package/src/shared/assets/translations/index.ts +9 -0
- package/src/shared/assets/translations/ru.ts +3 -0
- package/src/shared/constants/environment.ts +13 -0
- package/src/shared/constants/index.ts +1 -0
- package/src/shared/hooks/index.ts +4 -0
- package/src/shared/hooks/use-animated.ts +194 -0
- package/src/shared/hooks/use-breakpoints.ts +25 -0
- package/src/shared/hooks/use-mixins.ts +36 -0
- package/src/shared/hooks/use-safe-area.ts +56 -0
- package/src/shared/lib/api/api.provider.tsx +47 -0
- package/src/shared/lib/api/api.ts +7 -0
- package/src/shared/lib/api/api.types.ts +9 -0
- package/src/shared/lib/api/constants/index.ts +6 -0
- package/src/shared/lib/api/entities/common.ts +28 -0
- package/src/shared/lib/api/entities/index.ts +1 -0
- package/src/shared/lib/api/hooks/common.ts +31 -0
- package/src/shared/lib/api/hooks/index.ts +0 -0
- package/src/shared/lib/api/index.ts +4 -0
- package/src/shared/lib/api/models/api-instance/api-instance.constants.ts +9 -0
- package/src/shared/lib/api/models/api-instance/api-instance.ts +118 -0
- package/src/shared/lib/api/models/api-instance/api-instance.types.ts +31 -0
- package/src/shared/lib/api/models/api-instance/api-instance.utils.ts +22 -0
- package/src/shared/lib/api/models/api-instance/index.ts +1 -0
- package/src/shared/lib/api/models/index.ts +1 -0
- package/src/shared/lib/api/repositories/auth/auth.ts +18 -0
- package/src/shared/lib/api/repositories/auth/auth.types.ts +22 -0
- package/src/shared/lib/api/repositories/auth/index.ts +1 -0
- package/src/shared/lib/api/repositories/index.ts +1 -0
- package/src/shared/lib/api/resources/common.ts +8 -0
- package/src/shared/lib/api/resources/index.ts +1 -0
- package/src/shared/lib/api/utils/index.ts +1 -0
- package/src/shared/lib/api/utils/storage.ts +9 -0
- package/src/shared/lib/index.ts +4 -0
- package/src/shared/lib/localization/components/index.ts +1 -0
- package/src/shared/lib/localization/components/localization-translate/index.ts +1 -0
- package/src/shared/lib/localization/components/localization-translate/localization-translate.tsx +5 -0
- package/src/shared/lib/localization/components/localization-translate/localization-translate.types.ts +0 -0
- package/src/shared/lib/localization/constants/index.ts +54 -0
- package/src/shared/lib/localization/hooks/index.ts +2 -0
- package/src/shared/lib/localization/hooks/use-localization-setup.ts +34 -0
- package/src/shared/lib/localization/hooks/use-localization-text.ts +9 -0
- package/src/shared/lib/localization/hooks/use-localization.ts +23 -0
- package/src/shared/lib/localization/index.ts +4 -0
- package/src/shared/lib/localization/localization.provider.tsx +30 -0
- package/src/shared/lib/localization/localization.types.ts +5 -0
- package/src/shared/lib/localization/utils/index.ts +1 -0
- package/src/shared/lib/localization/utils/storage.ts +11 -0
- package/src/shared/lib/navigation/components/index.ts +1 -0
- package/src/shared/lib/navigation/components/navigation-logger/index.ts +1 -0
- package/src/shared/lib/navigation/components/navigation-logger/navigation-logger.ts +17 -0
- package/src/shared/lib/navigation/components/navigation-logger/navigation-logger.types.ts +0 -0
- package/src/shared/lib/navigation/hooks/index.ts +3 -0
- package/src/shared/lib/navigation/hooks/use-navigation-options.ts +94 -0
- package/src/shared/lib/navigation/hooks/use-navigation-params.ts +9 -0
- package/src/shared/lib/navigation/hooks/use-navigation.ts +9 -0
- package/src/shared/lib/navigation/index.ts +7 -0
- package/src/shared/lib/navigation/navigation.provider.tsx +26 -0
- package/src/shared/lib/navigation/navigation.types.ts +5 -0
- package/src/shared/lib/theme/constants/borders.ts +8 -0
- package/src/shared/lib/theme/constants/colors.ts +57 -0
- package/src/shared/lib/theme/constants/delays.ts +8 -0
- package/src/shared/lib/theme/constants/durations.ts +8 -0
- package/src/shared/lib/theme/constants/fonts.ts +7 -0
- package/src/shared/lib/theme/constants/index.ts +54 -0
- package/src/shared/lib/theme/constants/shadows.ts +40 -0
- package/src/shared/lib/theme/constants/sizes.ts +32 -0
- package/src/shared/lib/theme/constants/transparencies.ts +10 -0
- package/src/shared/lib/theme/constants/weights.ts +13 -0
- package/src/shared/lib/theme/hooks/index.ts +2 -0
- package/src/shared/lib/theme/hooks/use-theme-mode.ts +9 -0
- package/src/shared/lib/theme/hooks/use-theme-setup.ts +49 -0
- package/src/shared/lib/theme/hooks/use-theme.ts +15 -0
- package/src/shared/lib/theme/index.ts +4 -0
- package/src/shared/lib/theme/theme.context.ts +6 -0
- package/src/shared/lib/theme/theme.provider.tsx +60 -0
- package/src/shared/lib/theme/theme.types.ts +15 -0
- package/src/shared/lib/theme/utils/index.ts +1 -0
- package/src/shared/lib/theme/utils/storage.ts +11 -0
- package/src/shared/ui/atoms/index.ts +1 -0
- package/src/shared/ui/index.ts +4 -0
- package/src/shared/ui/molecules/index.ts +2 -0
- package/src/shared/ui/molecules/keyboard-area/index.ts +2 -0
- package/src/shared/ui/molecules/keyboard-area/keyboard-area.styles.ts +20 -0
- package/src/shared/ui/molecules/keyboard-area/keyboard-area.tsx +34 -0
- package/src/shared/ui/molecules/keyboard-area/keyboard-area.types.ts +3 -0
- package/src/shared/ui/molecules/refresh-control/index.ts +2 -0
- package/src/shared/ui/molecules/refresh-control/refresh-control.tsx +32 -0
- package/src/shared/ui/molecules/refresh-control/refresh-control.types.ts +6 -0
- package/src/shared/ui/organisms/index.ts +1 -0
- package/src/shared/ui/templates/index.ts +1 -0
- package/src/shared/ui/templates/screen-container/index.ts +12 -0
- package/src/shared/ui/templates/screen-container/screen-container-list.tsx +23 -0
- package/src/shared/ui/templates/screen-container/screen-container-scroll.tsx +23 -0
- package/src/shared/ui/templates/screen-container/screen-container-section-list.tsx +24 -0
- package/src/shared/ui/templates/screen-container/screen-container.hooks.tsx +72 -0
- package/src/shared/ui/templates/screen-container/screen-container.styles.ts +45 -0
- package/src/shared/ui/templates/screen-container/screen-container.types.tsx +75 -0
- package/src/shared/utils/generators.ts +11 -0
- package/src/shared/utils/index.ts +1 -0
- package/src/widgets/.gitkeep +0 -0
- package/svg.d.ts +7 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const PALETTE = {
|
|
2
|
+
'LIGHT/WHITE': '#FFFFFF',
|
|
3
|
+
'LIGHT/BLACK': '#111416',
|
|
4
|
+
'LIGHT/GRAY': '#D4D4D4',
|
|
5
|
+
|
|
6
|
+
'LIGHT/NEUTRAL': '#57626F',
|
|
7
|
+
'LIGHT/DISABLED': '#C3CAD1',
|
|
8
|
+
'LIGHT/SURFACE': '#F5F8FD',
|
|
9
|
+
'LIGHT/FAINT': '#EFF2F7',
|
|
10
|
+
|
|
11
|
+
'LIGHT/PRIMARY': '#6115CD',
|
|
12
|
+
'LIGHT/PRIMARY_ACTIVE': '#4E11A4',
|
|
13
|
+
'LIGHT/PRIMARY_DISABLED': '#D5C9FF',
|
|
14
|
+
|
|
15
|
+
'LIGHT/ACCENT': '#FF2B75',
|
|
16
|
+
'LIGHT/ACCENT_ACTIVE': '#E62464',
|
|
17
|
+
'LIGHT/ACCENT_DISABLED': '#FFBAD2',
|
|
18
|
+
|
|
19
|
+
'TRANSPARENT': '#FFFFFF00',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const LIGHT_COLORS_COMMON = {
|
|
23
|
+
PRIMARY: PALETTE['LIGHT/PRIMARY'],
|
|
24
|
+
PRIMARY_ACTIVE: PALETTE['LIGHT/PRIMARY_ACTIVE'],
|
|
25
|
+
PRIMARY_DISABLED: PALETTE['LIGHT/PRIMARY_DISABLED'],
|
|
26
|
+
|
|
27
|
+
ACCENT: PALETTE['LIGHT/ACCENT'],
|
|
28
|
+
ACCENT_ACTIVE: PALETTE['LIGHT/ACCENT_ACTIVE'],
|
|
29
|
+
ACCENT_DISABLED: PALETTE['LIGHT/ACCENT_DISABLED'],
|
|
30
|
+
|
|
31
|
+
TRANSPARENT: PALETTE['TRANSPARENT'],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const LIGHT_COLORS = {
|
|
35
|
+
FILL: {
|
|
36
|
+
BASE: PALETTE['LIGHT/SURFACE'],
|
|
37
|
+
NEUTRAL: PALETTE['LIGHT/FAINT'],
|
|
38
|
+
CONTRAST: PALETTE['LIGHT/WHITE'],
|
|
39
|
+
DISABLED: PALETTE['LIGHT/GRAY'],
|
|
40
|
+
...LIGHT_COLORS_COMMON,
|
|
41
|
+
},
|
|
42
|
+
STROKE: {
|
|
43
|
+
BASE: PALETTE['LIGHT/FAINT'],
|
|
44
|
+
...LIGHT_COLORS_COMMON,
|
|
45
|
+
},
|
|
46
|
+
TYPOGRAPHY: {
|
|
47
|
+
BASE: PALETTE['LIGHT/BLACK'],
|
|
48
|
+
NEUTRAL: PALETTE['LIGHT/NEUTRAL'],
|
|
49
|
+
CONTRAST: PALETTE['LIGHT/WHITE'],
|
|
50
|
+
DISABLED: PALETTE['LIGHT/DISABLED'],
|
|
51
|
+
...LIGHT_COLORS_COMMON,
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const DARK_COLORS = LIGHT_COLORS
|
|
56
|
+
|
|
57
|
+
export { LIGHT_COLORS, DARK_COLORS }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { BORDERS } from './borders'
|
|
2
|
+
import { DARK_COLORS, LIGHT_COLORS } from './colors'
|
|
3
|
+
import { DELAYS } from './delays'
|
|
4
|
+
import { DURATIONS } from './durations'
|
|
5
|
+
import { FONTS } from './fonts'
|
|
6
|
+
import { SHADOWS } from './shadows'
|
|
7
|
+
import { SIZES } from './sizes'
|
|
8
|
+
import { TRANSPARENCIES } from './transparencies'
|
|
9
|
+
import { WEIGHTS } from './weights'
|
|
10
|
+
|
|
11
|
+
const common = {
|
|
12
|
+
BORDERS,
|
|
13
|
+
// COLORS,
|
|
14
|
+
DELAYS,
|
|
15
|
+
DURATIONS,
|
|
16
|
+
FONTS,
|
|
17
|
+
SHADOWS,
|
|
18
|
+
SIZES,
|
|
19
|
+
TRANSPARENCIES,
|
|
20
|
+
WEIGHTS,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const lightTheme = {
|
|
24
|
+
...common,
|
|
25
|
+
COLORS: LIGHT_COLORS,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const darkTheme = {
|
|
29
|
+
...common,
|
|
30
|
+
COLORS: DARK_COLORS,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
enum ThemeMode {
|
|
34
|
+
Light = 'light',
|
|
35
|
+
Dark = 'dark',
|
|
36
|
+
System = 'system',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
enum ThemeModeSystem {
|
|
40
|
+
Light = 'light',
|
|
41
|
+
Dark = 'dark',
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
enum ThemeModeStatusBar {
|
|
45
|
+
Dark = 'dark-content',
|
|
46
|
+
Light = 'light-content',
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const themes = {
|
|
50
|
+
[ThemeModeSystem.Light]: lightTheme,
|
|
51
|
+
[ThemeModeSystem.Dark]: darkTheme,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { ThemeMode, ThemeModeSystem, ThemeModeStatusBar, themes }
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const SHADOWS = {
|
|
2
|
+
EMPTY: {
|
|
3
|
+
elevation: 0,
|
|
4
|
+
shadowOpacity: 0,
|
|
5
|
+
shadowRadius: 0,
|
|
6
|
+
shadowOffset: {
|
|
7
|
+
width: 0,
|
|
8
|
+
height: 0,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
THIN: {
|
|
12
|
+
elevation: 2,
|
|
13
|
+
shadowOpacity: 0.2,
|
|
14
|
+
shadowRadius: 1.5,
|
|
15
|
+
shadowOffset: {
|
|
16
|
+
width: 0,
|
|
17
|
+
height: 1,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
BASE: {
|
|
21
|
+
elevation: 12,
|
|
22
|
+
shadowOpacity: 0.4,
|
|
23
|
+
shadowRadius: 6,
|
|
24
|
+
shadowOffset: {
|
|
25
|
+
width: 0,
|
|
26
|
+
height: 6,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
FAT: {
|
|
30
|
+
elevation: 24,
|
|
31
|
+
shadowRadius: 16,
|
|
32
|
+
shadowOpacity: 0.6,
|
|
33
|
+
shadowOffset: {
|
|
34
|
+
width: 0,
|
|
35
|
+
height: 12,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { SHADOWS }
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const SIZES = {
|
|
2
|
+
'EMPTY': 0,
|
|
3
|
+
'2XS': 0.5,
|
|
4
|
+
'XS': 1,
|
|
5
|
+
'S': 2,
|
|
6
|
+
'M': 4,
|
|
7
|
+
'L': 8,
|
|
8
|
+
'XL': 12,
|
|
9
|
+
'2XL': 16,
|
|
10
|
+
'3XL': 20,
|
|
11
|
+
'4XL': 24,
|
|
12
|
+
'5XL': 28,
|
|
13
|
+
'6XL': 32,
|
|
14
|
+
'7XL': 36,
|
|
15
|
+
'8XL': 40,
|
|
16
|
+
'9XL': 44,
|
|
17
|
+
'10XL': 48,
|
|
18
|
+
'11XL': 52,
|
|
19
|
+
'12XL': 56,
|
|
20
|
+
'13XL': 60,
|
|
21
|
+
'14XL': 64,
|
|
22
|
+
'15XL': 68,
|
|
23
|
+
'16XL': 72,
|
|
24
|
+
'17XL': 76,
|
|
25
|
+
'18XL': 80,
|
|
26
|
+
'19XL': 84,
|
|
27
|
+
'20XL': 88,
|
|
28
|
+
'MAX': '100%' as const,
|
|
29
|
+
'INFINITY': Number.MAX_SAFE_INTEGER,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { SIZES }
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Log } from '@mediacubeco/base/helpers'
|
|
2
|
+
import { useCallback } from 'react'
|
|
3
|
+
import { ThemeMode, ThemeModeSystem } from '../constants'
|
|
4
|
+
import { useTheme } from './use-theme'
|
|
5
|
+
|
|
6
|
+
const useThemeSetup = () => {
|
|
7
|
+
const { themeMode, themeModeSystem, setThemeMode } = useTheme()
|
|
8
|
+
|
|
9
|
+
const isThemeModeSystem = themeMode === ThemeMode.System
|
|
10
|
+
const isThemeModeSystemLight = isThemeModeSystem && themeModeSystem === ThemeModeSystem.Light
|
|
11
|
+
const isThemeModeSystemDark = isThemeModeSystem && themeModeSystem === ThemeModeSystem.Dark
|
|
12
|
+
|
|
13
|
+
const isThemeModeLight = themeMode === ThemeMode.Light || isThemeModeSystemLight
|
|
14
|
+
const isThemeModeDark = themeMode === ThemeMode.Dark || isThemeModeSystemDark
|
|
15
|
+
|
|
16
|
+
const setThemeModeLight = useCallback(() => {
|
|
17
|
+
setThemeMode(ThemeMode.Light)
|
|
18
|
+
|
|
19
|
+
Log.formatted.info('light', 'theme mode')
|
|
20
|
+
}, [setThemeMode])
|
|
21
|
+
|
|
22
|
+
const setThemeModeDark = useCallback(() => {
|
|
23
|
+
setThemeMode(ThemeMode.Dark)
|
|
24
|
+
|
|
25
|
+
Log.formatted.info('dark', 'theme mode')
|
|
26
|
+
}, [setThemeMode])
|
|
27
|
+
|
|
28
|
+
const setThemeModeSystem = useCallback(() => {
|
|
29
|
+
setThemeMode(ThemeMode.System)
|
|
30
|
+
|
|
31
|
+
Log.formatted.info('system', 'theme mode')
|
|
32
|
+
}, [setThemeMode])
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
themeMode,
|
|
36
|
+
themeModeSystem,
|
|
37
|
+
isThemeModeSystem,
|
|
38
|
+
isThemeModeSystemLight,
|
|
39
|
+
isThemeModeSystemDark,
|
|
40
|
+
isThemeModeLight,
|
|
41
|
+
isThemeModeDark,
|
|
42
|
+
setThemeMode,
|
|
43
|
+
setThemeModeLight,
|
|
44
|
+
setThemeModeDark,
|
|
45
|
+
setThemeModeSystem,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { useThemeSetup }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ErrorHandler } from '@mediacubeco/base/helpers'
|
|
2
|
+
import { useContext } from 'react'
|
|
3
|
+
import { ThemeContext } from '../theme.context'
|
|
4
|
+
|
|
5
|
+
const useTheme = () => {
|
|
6
|
+
const context = useContext(ThemeContext)
|
|
7
|
+
|
|
8
|
+
if (!context) {
|
|
9
|
+
ErrorHandler.throw('useTheme can not be used outside ThemeProvider')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return context
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { useTheme }
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react'
|
|
2
|
+
import { StatusBar, useColorScheme } from 'react-native'
|
|
3
|
+
import { themeStorage } from './utils'
|
|
4
|
+
import { ThemeMode, ThemeModeStatusBar, ThemeModeSystem, themes } from './constants'
|
|
5
|
+
import { ThemeContext } from './theme.context'
|
|
6
|
+
import { ThemeProviderProps } from './theme.types'
|
|
7
|
+
|
|
8
|
+
const ThemeProvider = ({ children }: ThemeProviderProps) => {
|
|
9
|
+
const didDefine = useRef(false)
|
|
10
|
+
const [themeMode, setThemeMode] = useState(ThemeMode.System)
|
|
11
|
+
const themeModeSystem = (useColorScheme() as ThemeModeSystem) ?? ThemeModeSystem.Light
|
|
12
|
+
|
|
13
|
+
const currentThemeMode = {
|
|
14
|
+
[ThemeMode.Light]: ThemeModeSystem.Light,
|
|
15
|
+
[ThemeMode.Dark]: ThemeModeSystem.Dark,
|
|
16
|
+
[ThemeMode.System]: themeModeSystem,
|
|
17
|
+
}[themeMode]
|
|
18
|
+
|
|
19
|
+
const theme = useMemo(() => {
|
|
20
|
+
return themes[currentThemeMode]
|
|
21
|
+
}, [currentThemeMode])
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const defineThemeMode = async () => {
|
|
25
|
+
const storageThemeMode = await themeStorage.mode.get()
|
|
26
|
+
|
|
27
|
+
if (storageThemeMode) {
|
|
28
|
+
setThemeMode(storageThemeMode as ThemeMode)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
didDefine.current = true
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
defineThemeMode()
|
|
35
|
+
}, [])
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const updateThemeMode = async () => {
|
|
39
|
+
if (didDefine.current) {
|
|
40
|
+
await themeStorage.mode.set(themeMode)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
updateThemeMode()
|
|
45
|
+
}, [themeMode])
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
StatusBar.setBarStyle(
|
|
49
|
+
currentThemeMode === ThemeModeSystem.Dark ? ThemeModeStatusBar.Light : ThemeModeStatusBar.Dark
|
|
50
|
+
)
|
|
51
|
+
}, [currentThemeMode])
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<ThemeContext.Provider value={{ theme, themeMode, themeModeSystem, setThemeMode }}>
|
|
55
|
+
{children}
|
|
56
|
+
</ThemeContext.Provider>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default ThemeProvider
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Dispatch, PropsWithChildren, SetStateAction } from 'react'
|
|
2
|
+
import { ThemeMode, ThemeModeSystem, themes } from './constants'
|
|
3
|
+
|
|
4
|
+
type Theme = (typeof themes)[ThemeModeSystem]
|
|
5
|
+
|
|
6
|
+
interface ThemeContextValue {
|
|
7
|
+
theme: Theme
|
|
8
|
+
themeMode: ThemeMode
|
|
9
|
+
themeModeSystem: ThemeModeSystem
|
|
10
|
+
setThemeMode: Dispatch<SetStateAction<ThemeMode>>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type ThemeProviderProps = PropsWithChildren
|
|
14
|
+
|
|
15
|
+
export type { Theme, ThemeContextValue, ThemeProviderProps }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './storage'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Storage } from '@mediacubeco/base/services'
|
|
2
|
+
import * as SecureStore from 'expo-secure-store'
|
|
3
|
+
import { ThemeMode } from '../constants'
|
|
4
|
+
|
|
5
|
+
const themeStorage = new Storage({
|
|
6
|
+
get: SecureStore.getItemAsync,
|
|
7
|
+
set: SecureStore.setItemAsync,
|
|
8
|
+
delete: SecureStore.deleteItemAsync,
|
|
9
|
+
}).create<'mode', ThemeMode>('mode')
|
|
10
|
+
|
|
11
|
+
export { themeStorage }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const atoms = {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useAnimated, useAnimatedStyle, useSafeArea } from '../../../hooks'
|
|
2
|
+
|
|
3
|
+
const useKeyboardAreaStyles = () => {
|
|
4
|
+
const { BOTTOM } = useSafeArea()
|
|
5
|
+
const [safeAreaHeight] = useAnimated(BOTTOM)
|
|
6
|
+
const [keyboardHeight] = useAnimated<number>(0)
|
|
7
|
+
|
|
8
|
+
const keyboardAnimatedStyle = useAnimatedStyle(() => {
|
|
9
|
+
return {
|
|
10
|
+
height: keyboardHeight.value - safeAreaHeight.value,
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
keyboardHeight,
|
|
16
|
+
keyboardAnimatedStyle,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { useKeyboardAreaStyles }
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { View } from 'react-native'
|
|
2
|
+
import { useKeyboardHandler } from 'react-native-keyboard-controller'
|
|
3
|
+
import { animate } from '../../../hooks'
|
|
4
|
+
import { useKeyboardAreaStyles } from './keyboard-area.styles'
|
|
5
|
+
import { KeyboardAreaProps } from './keyboard-area.types'
|
|
6
|
+
|
|
7
|
+
const KeyboardAnimatedArea = animate(View)
|
|
8
|
+
|
|
9
|
+
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
|
+
)
|
|
30
|
+
|
|
31
|
+
return <KeyboardAnimatedArea style={keyboardAnimatedStyle} />
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default KeyboardArea
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { runCallback } from '@mediacubeco/base/utils'
|
|
2
|
+
import { useCallback, useState } from 'react'
|
|
3
|
+
import { RefreshControl as NativeRefreshControl } from 'react-native'
|
|
4
|
+
import { useSafeArea } from '../../../hooks'
|
|
5
|
+
import { useThemeMode } from '../../../lib'
|
|
6
|
+
import { RefreshControlProps } from './refresh-control.types'
|
|
7
|
+
|
|
8
|
+
const RefreshControl = ({ withOffset = true, onRefresh, ...props }: RefreshControlProps) => {
|
|
9
|
+
const [isRefreshing, setIsRefreshing] = useState(false)
|
|
10
|
+
const { TOP } = useSafeArea()
|
|
11
|
+
const { COLORS } = useThemeMode()
|
|
12
|
+
|
|
13
|
+
const handleRefresh = useCallback(async () => {
|
|
14
|
+
setIsRefreshing(true)
|
|
15
|
+
|
|
16
|
+
await runCallback(onRefresh)
|
|
17
|
+
|
|
18
|
+
setIsRefreshing(false)
|
|
19
|
+
}, [onRefresh])
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<NativeRefreshControl
|
|
23
|
+
refreshing={isRefreshing}
|
|
24
|
+
onRefresh={handleRefresh}
|
|
25
|
+
progressViewOffset={withOffset ? TOP : 0}
|
|
26
|
+
tintColor={COLORS.TYPOGRAPHY.PRIMARY}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default RefreshControl
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const organisms = {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './screen-container'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default as ScreenContainerScroll } from './screen-container-scroll'
|
|
2
|
+
export { default as ScreenContainerList } from './screen-container-list'
|
|
3
|
+
export { default as ScreenContainerSectionList } from './screen-container-section-list'
|
|
4
|
+
export type {
|
|
5
|
+
ScreenContainerListProps,
|
|
6
|
+
ScreenContainerScrollProps,
|
|
7
|
+
ScreenContainerSectionListProps,
|
|
8
|
+
ScreenContainerListRenderItemInfo,
|
|
9
|
+
ScreenContainerSectionListRenderItemInfo,
|
|
10
|
+
ScreenContainerSectionListRenderHeaderInfo,
|
|
11
|
+
ScreenContainerSectionListRenderFooterInfo,
|
|
12
|
+
} from './screen-container.types'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FlatList, View } from 'react-native'
|
|
2
|
+
import { useScreenContainerProps } from './screen-container.hooks'
|
|
3
|
+
import { ScreenContainerListProps } from './screen-container.types'
|
|
4
|
+
|
|
5
|
+
const ScreenContainerList = <Item,>(props: ScreenContainerListProps<Item>) => {
|
|
6
|
+
const { reference, header, footer, wrapperStyle, outerStyle, innerStyle, ...flatListProps } =
|
|
7
|
+
useScreenContainerProps<ScreenContainerListProps<Item>>(props)
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<View style={wrapperStyle}>
|
|
11
|
+
{header}
|
|
12
|
+
<FlatList
|
|
13
|
+
ref={reference}
|
|
14
|
+
style={outerStyle}
|
|
15
|
+
contentContainerStyle={innerStyle}
|
|
16
|
+
{...flatListProps}
|
|
17
|
+
/>
|
|
18
|
+
{footer}
|
|
19
|
+
</View>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default ScreenContainerList
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ScrollView, View } from 'react-native'
|
|
2
|
+
import { useScreenContainerProps } from './screen-container.hooks'
|
|
3
|
+
import { ScreenContainerScrollProps } from './screen-container.types'
|
|
4
|
+
|
|
5
|
+
const ScreenContainerScroll = (props: ScreenContainerScrollProps) => {
|
|
6
|
+
const { reference, header, footer, wrapperStyle, outerStyle, innerStyle, ...scrollViewProps } =
|
|
7
|
+
useScreenContainerProps<ScreenContainerScrollProps>(props)
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<View style={wrapperStyle}>
|
|
11
|
+
{header}
|
|
12
|
+
<ScrollView
|
|
13
|
+
ref={reference}
|
|
14
|
+
style={outerStyle}
|
|
15
|
+
contentContainerStyle={innerStyle}
|
|
16
|
+
{...scrollViewProps}
|
|
17
|
+
/>
|
|
18
|
+
{footer}
|
|
19
|
+
</View>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default ScreenContainerScroll
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SectionList, View } from 'react-native'
|
|
2
|
+
import { useScreenContainerProps } from './screen-container.hooks'
|
|
3
|
+
import { ScreenContainerSectionListProps } from './screen-container.types'
|
|
4
|
+
|
|
5
|
+
const ScreenContainerSectionList = <Item,>(props: ScreenContainerSectionListProps<Item>) => {
|
|
6
|
+
const { reference, header, footer, wrapperStyle, outerStyle, innerStyle, ...sectionListProps } =
|
|
7
|
+
useScreenContainerProps<ScreenContainerSectionListProps<Item>>(props)
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<View style={wrapperStyle}>
|
|
11
|
+
{header}
|
|
12
|
+
<SectionList
|
|
13
|
+
ref={reference}
|
|
14
|
+
style={outerStyle}
|
|
15
|
+
contentContainerStyle={innerStyle}
|
|
16
|
+
stickySectionHeadersEnabled={false}
|
|
17
|
+
{...sectionListProps}
|
|
18
|
+
/>
|
|
19
|
+
{footer}
|
|
20
|
+
</View>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default ScreenContainerSectionList
|