@crystin001/theme-settings-lib 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/README.md ADDED
@@ -0,0 +1,368 @@
1
+ # Theme & Settings Library
2
+
3
+ A reusable library for theme management, settings, and internationalization that can be shared across multiple React Native applications.
4
+
5
+ ## Features
6
+
7
+ - 🎨 **Multiple Theme Families** - 8 theme families with light and dark variants
8
+ - 🌍 **Internationalization** - Built-in i18n support with extensible translations
9
+ - 💾 **Persistent Settings** - Theme and language preferences saved automatically
10
+ - ♿ **Accessibility** - WCAG-compliant contrast utilities
11
+ - 🔧 **Type-Safe** - Full TypeScript support with declaration files
12
+
13
+ ## Installation
14
+
15
+ ### Option A: Git Repository (Recommended)
16
+
17
+ Add to your `package.json`:
18
+
19
+ ```json
20
+ {
21
+ "dependencies": {
22
+ "@crystin001/theme-settings-lib": "git+https://github.com/trial-and-code/theme-settings-lib.git"
23
+ }
24
+ }
25
+ ```
26
+
27
+ Then run `npm install`.
28
+
29
+ To install a specific version or branch:
30
+
31
+ ```json
32
+ {
33
+ "dependencies": {
34
+ "@crystin001/theme-settings-lib": "git+https://github.com/trial-and-code/theme-settings-lib.git#v1.0.0"
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### Option B: Local Package (Monorepo)
40
+
41
+ If the library is in the same repository:
42
+
43
+ ```json
44
+ {
45
+ "dependencies": {
46
+ "@crystin001/theme-settings-lib": "file:../packages/theme-settings-lib"
47
+ }
48
+ }
49
+ ```
50
+
51
+ ### Option C: npm Package (Future)
52
+
53
+ ```bash
54
+ npm install @crystin001/theme-settings-lib
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ### 1. Wrap Your App with SettingsProvider
60
+
61
+ Wrap your root component with `SettingsProvider` to enable theme and settings management:
62
+
63
+ ```tsx
64
+ // app/_layout.tsx or App.tsx
65
+ import { SettingsProvider } from '@crystin001/theme-settings-lib';
66
+ import { Stack } from 'expo-router';
67
+
68
+ export default function RootLayout() {
69
+ return (
70
+ <SettingsProvider>
71
+ <Stack>
72
+ {/* Your app screens */}
73
+ </Stack>
74
+ </SettingsProvider>
75
+ );
76
+ }
77
+ ```
78
+
79
+ ### 2. Use Theme Hooks in Your Components
80
+
81
+ Access theme colors and settings in your components:
82
+
83
+ ```tsx
84
+ import { View, Text, Button } from 'react-native';
85
+ import { useTheme, useSettings } from '@crystin001/theme-settings-lib';
86
+
87
+ function MyComponent() {
88
+ const colors = useTheme();
89
+ const { setThemeFamily } = useSettings();
90
+
91
+ return (
92
+ <View style={{ backgroundColor: colors.background }}>
93
+ <Text style={{ color: colors.text }}>Hello World</Text>
94
+ <Button
95
+ onPress={() => setThemeFamily('neon-surf')}
96
+ title="Change to Neon Surf"
97
+ />
98
+ </View>
99
+ );
100
+ }
101
+ ```
102
+
103
+ ### 3. Use Translations
104
+
105
+ Access translations using the `useTranslation` hook:
106
+
107
+ ```tsx
108
+ import { Text } from 'react-native';
109
+ import { useTranslation } from '@crystin001/theme-settings-lib';
110
+
111
+ function MyComponent() {
112
+ const { t } = useTranslation();
113
+
114
+ return (
115
+ <Text>{t('common.welcome')}</Text>
116
+ );
117
+ }
118
+ ```
119
+
120
+ ### 4. Get Specific Theme Colors
121
+
122
+ Use `useThemeColor` to get specific colors from the current theme:
123
+
124
+ ```tsx
125
+ import { View, Text } from 'react-native';
126
+ import { useThemeColor } from '@crystin001/theme-settings-lib';
127
+
128
+ function MyComponent() {
129
+ const backgroundColor = useThemeColor({}, 'background');
130
+ const textColor = useThemeColor({}, 'text');
131
+ const primaryColor = useThemeColor({}, 'primary');
132
+
133
+ return (
134
+ <View style={{ backgroundColor }}>
135
+ <Text style={{ color: textColor }}>Primary: {primaryColor}</Text>
136
+ </View>
137
+ );
138
+ }
139
+ ```
140
+
141
+ ### 5. Extend Translations
142
+
143
+ Add app-specific translations by extending the i18n instance:
144
+
145
+ ```tsx
146
+ import { i18n } from '@crystin001/theme-settings-lib';
147
+
148
+ // Add custom translations
149
+ i18n.addResourceBundle('en-US', 'translation', {
150
+ myFeature: {
151
+ title: 'My Feature',
152
+ description: 'This is my feature',
153
+ },
154
+ }, true, true);
155
+ ```
156
+
157
+ ### 6. Complete Example: Integration with React Navigation
158
+
159
+ Here's a complete example showing integration with React Navigation:
160
+
161
+ ```tsx
162
+ // app/_layout.tsx
163
+ import { Stack } from 'expo-router';
164
+ import { StatusBar } from 'expo-status-bar';
165
+ import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
166
+ import { SettingsProvider, useSettings } from '@crystin001/theme-settings-lib';
167
+
168
+ function RootLayoutNav() {
169
+ const { currentTheme } = useSettings();
170
+ const isDarkTheme = currentTheme.endsWith('-dark');
171
+
172
+ return (
173
+ <ThemeProvider value={isDarkTheme ? DarkTheme : DefaultTheme}>
174
+ <Stack>
175
+ <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
176
+ </Stack>
177
+ <StatusBar style={isDarkTheme ? 'light' : 'dark'} />
178
+ </ThemeProvider>
179
+ );
180
+ }
181
+
182
+ export default function RootLayout() {
183
+ return (
184
+ <SettingsProvider>
185
+ <RootLayoutNav />
186
+ </SettingsProvider>
187
+ );
188
+ }
189
+ ```
190
+
191
+ ## Available Theme Families
192
+
193
+ - **System** - Follows device theme preference (default)
194
+ - **Neon Surf** - Vibrant neon colors (hot pink, cyan, yellow, orange)
195
+ - **Pink & Purple** - Soft purple and pink tones
196
+ - **Pastel** - Gentle pastel colors
197
+ - **GitHub** - GitHub-inspired theme
198
+ - **High Contrast** - Maximum contrast for accessibility
199
+ - **Solarized** - Solarized color scheme
200
+ - **Dark Plus** - Dark theme with blue accents
201
+
202
+ Each theme family has both light and dark variants that automatically switch based on device settings.
203
+
204
+ ## API Reference
205
+
206
+ ### Hooks
207
+
208
+ #### `useTheme()`
209
+
210
+ Returns all colors from the current theme.
211
+
212
+ ```tsx
213
+ const colors = useTheme();
214
+ // Returns: { text, background, tint, icon, ... }
215
+ ```
216
+
217
+ #### `useThemeColor(props?, colorName?)`
218
+
219
+ Get a specific color from the current theme.
220
+
221
+ ```tsx
222
+ const backgroundColor = useThemeColor({}, 'background');
223
+ const textColor = useThemeColor({ light: '#000', dark: '#fff' }, 'text');
224
+ ```
225
+
226
+ #### `useSettings()`
227
+
228
+ Access theme and language settings.
229
+
230
+ ```tsx
231
+ const {
232
+ selectedThemeFamily,
233
+ currentTheme,
234
+ setThemeFamily,
235
+ language,
236
+ setLanguage,
237
+ availableThemeFamilies,
238
+ availableLanguages
239
+ } = useSettings();
240
+ ```
241
+
242
+ #### `useTranslation()`
243
+
244
+ Get the translation function.
245
+
246
+ ```tsx
247
+ const { t } = useTranslation();
248
+ const welcomeText = t('common.welcome');
249
+ ```
250
+
251
+ ### Settings Context
252
+
253
+ The `useSettings()` hook returns:
254
+
255
+ - `selectedThemeFamily` - Currently selected theme family (e.g., `'neon-surf'`)
256
+ - `currentTheme` - Effective theme being used (includes variant, e.g., `'neon-surf-light'`)
257
+ - `setThemeFamily(family)` - Change theme family
258
+ - `language` - Current language code (e.g., `'en-US'`)
259
+ - `setLanguage(lang)` - Change language
260
+ - `availableThemeFamilies` - Array of all available theme families with metadata
261
+ - `availableLanguages` - Array of all available languages
262
+
263
+ ### Color Utilities
264
+
265
+ #### `getContrastRatio(color1, color2)`
266
+
267
+ Calculate the contrast ratio between two colors (returns 1-21).
268
+
269
+ ```tsx
270
+ import { getContrastRatio } from '@crystin001/theme-settings-lib';
271
+
272
+ const ratio = getContrastRatio('#000000', '#FFFFFF'); // Returns ~21
273
+ ```
274
+
275
+ #### `getContrastTextColor(backgroundColor, lightColor?, darkColor?, minContrast?)`
276
+
277
+ Get a readable text color for a given background.
278
+
279
+ ```tsx
280
+ import { getContrastTextColor } from '@crystin001/theme-settings-lib';
281
+
282
+ const textColor = getContrastTextColor('#000000'); // Returns '#FFFFFF'
283
+ ```
284
+
285
+ #### `meetsContrastRequirement(foreground, background, level?)`
286
+
287
+ Check if a color combination meets WCAG contrast requirements.
288
+
289
+ ```tsx
290
+ import { meetsContrastRequirement } from '@crystin001/theme-settings-lib';
291
+
292
+ const isAccessible = meetsContrastRequirement('#000000', '#FFFFFF', 'AA'); // Returns true
293
+ ```
294
+
295
+ #### `ensureContrast(foreground, background, level?)`
296
+
297
+ Ensure a color combination has readable contrast, adjusting if needed.
298
+
299
+ ```tsx
300
+ import { ensureContrast } from '@crystin001/theme-settings-lib';
301
+
302
+ const readableColor = ensureContrast('#888888', '#FFFFFF', 'AA');
303
+ ```
304
+
305
+ ## Development
306
+
307
+ ### Building the Library
308
+
309
+ ```bash
310
+ npm run build
311
+ ```
312
+
313
+ This compiles TypeScript to JavaScript and generates type declaration files in the `dist/` folder.
314
+
315
+ ### Project Structure
316
+
317
+ ```
318
+ theme-settings-lib/
319
+ ├── src/
320
+ │ ├── hooks/ # React hooks
321
+ │ ├── theme.ts # Theme definitions
322
+ │ ├── i18n.ts # Internationalization setup
323
+ │ ├── settings-context.tsx # Settings provider
324
+ │ ├── color-utils.ts # Color utility functions
325
+ │ └── index.ts # Main exports
326
+ ├── dist/ # Compiled output (generated)
327
+ ├── package.json
328
+ └── tsconfig.json
329
+ ```
330
+
331
+ ## Updating the Library
332
+
333
+ To update themes or translations across all apps:
334
+
335
+ 1. Make changes in `src/` directory
336
+ 2. Run `npm run build` to compile
337
+ 3. Update the version in `package.json`
338
+ 4. Commit and push to the repository
339
+ 5. In each app, update the dependency version and run `npm install`
340
+ 6. Apps will automatically get the latest themes and translations
341
+
342
+ ## Versioning
343
+
344
+ The library follows [Semantic Versioning](https://semver.org/):
345
+
346
+ - **Major** (x.0.0) - Breaking API changes
347
+ - **Minor** (0.x.0) - New themes, features, or languages
348
+ - **Patch** (0.0.x) - Bug fixes and theme adjustments
349
+
350
+ ## Peer Dependencies
351
+
352
+ This library requires the following peer dependencies (installed by your app):
353
+
354
+ - `react` - React library
355
+ - `react-native` - React Native framework
356
+ - `i18next` - Internationalization framework
357
+ - `react-i18next` - React bindings for i18next
358
+ - `expo-localization` - Expo localization utilities
359
+ - `@react-native-async-storage/async-storage` - Async storage for persistence
360
+ - `color` (optional) - Color manipulation library
361
+
362
+ ## License
363
+
364
+ MIT
365
+
366
+ ## Repository
367
+
368
+ [https://github.com/trial-and-code/theme-settings-lib](https://github.com/trial-and-code/theme-settings-lib)
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Calculate the contrast ratio between two colors
3
+ * Returns a value between 1 (no contrast) and 21 (maximum contrast)
4
+ * WCAG requires at least 4.5:1 for normal text and 3:1 for large text
5
+ */
6
+ export declare function getContrastRatio(color1: string, color2: string): number;
7
+ /**
8
+ * Determine if text should be light (white) or dark (black) based on background color
9
+ * Uses WCAG contrast guidelines to ensure readability
10
+ */
11
+ export declare function getContrastTextColor(backgroundColor: string, lightColor?: string, darkColor?: string, minContrast?: number): string;
12
+ /**
13
+ * Check if a color combination meets WCAG contrast requirements
14
+ * @param foreground - Text color
15
+ * @param background - Background color
16
+ * @param level - 'AA' (4.5:1) or 'AAA' (7:1) for normal text, or 'AALarge' (3:1) for large text
17
+ */
18
+ export declare function meetsContrastRequirement(foreground: string, background: string, level?: 'AA' | 'AAA' | 'AALarge'): boolean;
19
+ /**
20
+ * Get a color that meets contrast requirements with a background
21
+ * Tries to find a readable version of the foreground color
22
+ */
23
+ export declare function ensureContrast(foreground: string, background: string, level?: 'AA' | 'AAA' | 'AALarge'): string;
24
+ //# sourceMappingURL=color-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-utils.d.ts","sourceRoot":"","sources":["../src/color-utils.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAavE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EACvB,UAAU,GAAE,MAAkB,EAC9B,SAAS,GAAE,MAAkB,EAC7B,WAAW,GAAE,MAAY,GACxB,MAAM,CAgCR;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,IAAI,GAAG,KAAK,GAAG,SAAgB,GACrC,OAAO,CAQT;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,IAAI,GAAG,KAAK,GAAG,SAAgB,GACrC,MAAM,CAOR"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getContrastRatio = getContrastRatio;
7
+ exports.getContrastTextColor = getContrastTextColor;
8
+ exports.meetsContrastRequirement = meetsContrastRequirement;
9
+ exports.ensureContrast = ensureContrast;
10
+ const color_1 = __importDefault(require("color"));
11
+ /**
12
+ * Calculate the relative luminance of a color (0-1)
13
+ * Based on WCAG 2.1 guidelines
14
+ */
15
+ function getLuminance(color) {
16
+ const rgb = color.rgb().array();
17
+ const [r, g, b] = rgb.map((val) => {
18
+ val = val / 255;
19
+ return val <= 0.03928 ? val / 12.92 : Math.pow((val + 0.055) / 1.055, 2.4);
20
+ });
21
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
22
+ }
23
+ /**
24
+ * Calculate the contrast ratio between two colors
25
+ * Returns a value between 1 (no contrast) and 21 (maximum contrast)
26
+ * WCAG requires at least 4.5:1 for normal text and 3:1 for large text
27
+ */
28
+ function getContrastRatio(color1, color2) {
29
+ try {
30
+ const c1 = (0, color_1.default)(color1);
31
+ const c2 = (0, color_1.default)(color2);
32
+ const l1 = getLuminance(c1);
33
+ const l2 = getLuminance(c2);
34
+ const lighter = Math.max(l1, l2);
35
+ const darker = Math.min(l1, l2);
36
+ return (lighter + 0.05) / (darker + 0.05);
37
+ }
38
+ catch (error) {
39
+ console.warn('Failed to calculate contrast ratio:', error);
40
+ return 1; // Return minimum contrast on error
41
+ }
42
+ }
43
+ /**
44
+ * Determine if text should be light (white) or dark (black) based on background color
45
+ * Uses WCAG contrast guidelines to ensure readability
46
+ */
47
+ function getContrastTextColor(backgroundColor, lightColor = '#FFFFFF', darkColor = '#000000', minContrast = 4.5) {
48
+ try {
49
+ const bgColor = (0, color_1.default)(backgroundColor);
50
+ const lightContrast = getContrastRatio(backgroundColor, lightColor);
51
+ const darkContrast = getContrastRatio(backgroundColor, darkColor);
52
+ // If both meet minimum contrast, choose the one with better contrast
53
+ if (lightContrast >= minContrast && darkContrast >= minContrast) {
54
+ return lightContrast > darkContrast ? lightColor : darkColor;
55
+ }
56
+ // If only one meets minimum contrast, use that one
57
+ if (lightContrast >= minContrast) {
58
+ return lightColor;
59
+ }
60
+ if (darkContrast >= minContrast) {
61
+ return darkColor;
62
+ }
63
+ // If neither meets minimum, choose the one with better contrast anyway
64
+ return lightContrast > darkContrast ? lightColor : darkColor;
65
+ }
66
+ catch (error) {
67
+ console.warn('Failed to determine contrast text color:', error);
68
+ // Fallback: use light text for dark backgrounds, dark text for light backgrounds
69
+ try {
70
+ const bgColor = (0, color_1.default)(backgroundColor);
71
+ const luminance = getLuminance(bgColor);
72
+ return luminance > 0.5 ? darkColor : lightColor;
73
+ }
74
+ catch {
75
+ return lightColor; // Ultimate fallback
76
+ }
77
+ }
78
+ }
79
+ /**
80
+ * Check if a color combination meets WCAG contrast requirements
81
+ * @param foreground - Text color
82
+ * @param background - Background color
83
+ * @param level - 'AA' (4.5:1) or 'AAA' (7:1) for normal text, or 'AALarge' (3:1) for large text
84
+ */
85
+ function meetsContrastRequirement(foreground, background, level = 'AA') {
86
+ const ratio = getContrastRatio(foreground, background);
87
+ const requirements = {
88
+ AA: 4.5,
89
+ AAA: 7,
90
+ AALarge: 3,
91
+ };
92
+ return ratio >= requirements[level];
93
+ }
94
+ /**
95
+ * Get a color that meets contrast requirements with a background
96
+ * Tries to find a readable version of the foreground color
97
+ */
98
+ function ensureContrast(foreground, background, level = 'AA') {
99
+ if (meetsContrastRequirement(foreground, background, level)) {
100
+ return foreground;
101
+ }
102
+ // If contrast is insufficient, return the opposite contrast color
103
+ return getContrastTextColor(background);
104
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hook to get theme colors from the current theme
3
+ * Uses the settings context to get the active theme
4
+ */
5
+ import { ThemeColors } from '../theme';
6
+ export declare function useThemeColor(props?: {
7
+ light?: string;
8
+ dark?: string;
9
+ [key: string]: string | undefined;
10
+ }, colorName?: keyof ThemeColors): string | ThemeColors;
11
+ /**
12
+ * Hook to get all colors from the current theme
13
+ */
14
+ export declare function useTheme(): ThemeColors;
15
+ //# sourceMappingURL=use-theme-color.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-theme-color.d.ts","sourceRoot":"","sources":["../../src/hooks/use-theme-color.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAU,WAAW,EAAE,MAAM,UAAU,CAAC;AAG/C,wBAAgB,aAAa,CAC3B,KAAK,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,EAC5E,SAAS,CAAC,EAAE,MAAM,WAAW,wBAoB9B;AAED;;GAEG;AACH,wBAAgB,QAAQ,gBAGvB"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Hook to get theme colors from the current theme
4
+ * Uses the settings context to get the active theme
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.useThemeColor = useThemeColor;
8
+ exports.useTheme = useTheme;
9
+ const theme_1 = require("../theme");
10
+ const settings_context_1 = require("../settings-context");
11
+ function useThemeColor(props, colorName) {
12
+ const { currentTheme } = (0, settings_context_1.useSettings)();
13
+ const themeColors = theme_1.Themes[currentTheme];
14
+ // If props are provided, check for theme-specific override
15
+ if (props && colorName) {
16
+ const colorFromProps = props[currentTheme] || props[colorName];
17
+ if (colorFromProps) {
18
+ return colorFromProps;
19
+ }
20
+ }
21
+ // Return the color from the current theme
22
+ if (colorName) {
23
+ return themeColors[colorName];
24
+ }
25
+ // If no color name provided, return the theme colors object
26
+ return themeColors;
27
+ }
28
+ /**
29
+ * Hook to get all colors from the current theme
30
+ */
31
+ function useTheme() {
32
+ const { currentTheme } = (0, settings_context_1.useSettings)();
33
+ return theme_1.Themes[currentTheme];
34
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Custom hook for translations with type safety
3
+ * Usage: const t = useTranslation(); t('common.welcome')
4
+ */
5
+ export declare function useTranslation(): {
6
+ t: (key: string, options?: Record<string, string | number>) => string;
7
+ changeLanguage: (language: string) => Promise<import("i18next").TFunction<"translation", undefined>>;
8
+ currentLanguage: string;
9
+ };
10
+ //# sourceMappingURL=use-translation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-translation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-translation.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,cAAc;aAIjB,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;+BAE/B,MAAM;;EAGpC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTranslation = useTranslation;
4
+ const react_i18next_1 = require("react-i18next");
5
+ /**
6
+ * Custom hook for translations with type safety
7
+ * Usage: const t = useTranslation(); t('common.welcome')
8
+ */
9
+ function useTranslation() {
10
+ const { t, i18n } = (0, react_i18next_1.useTranslation)();
11
+ return {
12
+ t: (key, options) => t(key, options),
13
+ changeLanguage: (language) => i18n.changeLanguage(language),
14
+ currentLanguage: i18n.language,
15
+ };
16
+ }
package/dist/i18n.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import i18n from 'i18next';
2
+ export declare const SUPPORTED_LANGUAGES: readonly [{
3
+ readonly code: "en-US";
4
+ readonly name: "English (US)";
5
+ }, {
6
+ readonly code: "es-ES";
7
+ readonly name: "Español (ES)";
8
+ }, {
9
+ readonly code: "fr-FR";
10
+ readonly name: "Français (FR)";
11
+ }, {
12
+ readonly code: "de-DE";
13
+ readonly name: "Deutsch (DE)";
14
+ }, {
15
+ readonly code: "ja-JP";
16
+ readonly name: "日本語 (JP)";
17
+ }, {
18
+ readonly code: "zh-CN";
19
+ readonly name: "中文 (简体)";
20
+ }];
21
+ export type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number]['code'];
22
+ export default i18n;
23
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAK3B,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAOtB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AA+D7E,eAAe,IAAI,CAAC"}
package/dist/i18n.js ADDED
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SUPPORTED_LANGUAGES = void 0;
7
+ const i18next_1 = __importDefault(require("i18next"));
8
+ const react_i18next_1 = require("react-i18next");
9
+ const expo_localization_1 = require("expo-localization");
10
+ // Supported languages
11
+ exports.SUPPORTED_LANGUAGES = [
12
+ { code: 'en-US', name: 'English (US)' },
13
+ { code: 'es-ES', name: 'Español (ES)' },
14
+ { code: 'fr-FR', name: 'Français (FR)' },
15
+ { code: 'de-DE', name: 'Deutsch (DE)' },
16
+ { code: 'ja-JP', name: '日本語 (JP)' },
17
+ { code: 'zh-CN', name: '中文 (简体)' },
18
+ ];
19
+ // Default translations - can be extended by apps
20
+ const defaultTranslations = {
21
+ 'en-US': {
22
+ translation: {
23
+ common: {
24
+ welcome: 'Welcome',
25
+ hello: 'Hello',
26
+ save: 'Save',
27
+ cancel: 'Cancel',
28
+ delete: 'Delete',
29
+ edit: 'Edit',
30
+ done: 'Done',
31
+ loading: 'Loading...',
32
+ error: 'Error',
33
+ success: 'Success',
34
+ },
35
+ settings: {
36
+ title: 'Settings',
37
+ theme: 'Theme',
38
+ language: 'Language',
39
+ selectTheme: 'Select Theme',
40
+ selectLanguage: 'Select Language',
41
+ light: 'Light',
42
+ dark: 'Dark',
43
+ system: 'System',
44
+ themeMode: 'Theme Mode',
45
+ },
46
+ home: {
47
+ title: 'Welcome!',
48
+ step1: 'Step 1: Try it',
49
+ step2: 'Step 2: Explore',
50
+ step3: 'Step 3: Get a fresh start',
51
+ editFile: 'Edit {file} to see changes.',
52
+ pressKey: 'Press {key} to open developer tools.',
53
+ tapExplore: "Tap the Explore tab to learn more about what's included in this starter app.",
54
+ resetProject: "When you're ready, run {command} to get a fresh {directory} directory.",
55
+ },
56
+ errors: {
57
+ somethingWentWrong: 'Something went wrong',
58
+ tryAgain: 'Try again',
59
+ },
60
+ },
61
+ },
62
+ };
63
+ // Initialize i18n
64
+ // Apps can extend translations by calling i18n.addResourceBundle
65
+ i18next_1.default.use(react_i18next_1.initReactI18next).init({
66
+ compatibilityJSON: 'v3',
67
+ resources: defaultTranslations,
68
+ lng: (0, expo_localization_1.getLocales)()[0]?.languageTag || 'en-US',
69
+ fallbackLng: 'en-US',
70
+ interpolation: {
71
+ escapeValue: false, // React already escapes values
72
+ prefix: '{',
73
+ suffix: '}',
74
+ },
75
+ });
76
+ exports.default = i18next_1.default;