aport-tools 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- package/.babelrc +8 -0
- package/.expo/README.md +15 -0
- package/.expo/devices.json +3 -0
- package/.expo/settings.json +8 -0
- package/App.tsx +41 -0
- package/dist/Button.d.ts +12 -0
- package/dist/Theme/ThemeContext.d.ts +13 -0
- package/dist/Theme/ThemeToggle.d.ts +3 -0
- package/dist/Theme/index.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +257 -0
- package/dist/index.js +261 -0
- package/dist/styles/colors.d.ts +17 -0
- package/dist/styles/theme.d.ts +4 -0
- package/index.ts +1 -0
- package/package.json +27 -8
- package/rollup.config.mjs +55 -0
- package/rollup.config.js +0 -31
- package/src/Button.tsx +0 -104
- package/src/components/ThemeToggle.tsx +0 -39
- package/src/context/ThemeContext.tsx +0 -70
- package/src/index.ts +0 -1
- package/src/styles/colors.ts +0 -60
- package/src/styles/theme.ts +0 -50
- package/tsconfig.json +0 -30
package/.babelrc
ADDED
package/.expo/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
> Why do I have a folder named ".expo" in my project?
|
2
|
+
|
3
|
+
The ".expo" folder is created when an Expo project is started using "expo start" command.
|
4
|
+
|
5
|
+
> What do the files contain?
|
6
|
+
|
7
|
+
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
|
8
|
+
- "packager-info.json": contains port numbers and process PIDs that are used to serve the application to the mobile device/simulator.
|
9
|
+
- "settings.json": contains the server configuration that is used to serve the application manifest.
|
10
|
+
|
11
|
+
> Should I commit the ".expo" folder?
|
12
|
+
|
13
|
+
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
|
14
|
+
|
15
|
+
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
|
package/App.tsx
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
// src/App.tsx
|
2
|
+
|
3
|
+
import React from 'react';
|
4
|
+
import { SafeAreaView, StatusBar, Text, StyleSheet, AppRegistry } from 'react-native';
|
5
|
+
import { ThemeProvider, ThemeContext } from './src/Theme/ThemeContext';
|
6
|
+
import ThemeToggle from './src/Theme/ThemeToggle'; // Import ThemeToggle
|
7
|
+
import { name as appName } from './app.json'; // Ensure this path is correct
|
8
|
+
|
9
|
+
const App: React.FC = () => {
|
10
|
+
return (
|
11
|
+
<ThemeProvider>
|
12
|
+
<ThemeContext.Consumer>
|
13
|
+
{({ theme }) => (
|
14
|
+
<SafeAreaView style={[styles.container, { backgroundColor: theme.colors.background.hex }]}>
|
15
|
+
<StatusBar barStyle={theme.colors.text.hex === '#FFFFFF' ? 'light-content' : 'dark-content'} />
|
16
|
+
<Text style={[styles.text, { color: theme.colors.text.hex }]}>
|
17
|
+
Current Theme: {theme.colors.primary.hex === '#1A73E8' ? 'Light' : 'Dark'}
|
18
|
+
</Text>
|
19
|
+
<ThemeToggle />
|
20
|
+
</SafeAreaView>
|
21
|
+
)}
|
22
|
+
</ThemeContext.Consumer>
|
23
|
+
</ThemeProvider>
|
24
|
+
);
|
25
|
+
};
|
26
|
+
|
27
|
+
const styles = StyleSheet.create({
|
28
|
+
container: {
|
29
|
+
flex: 1,
|
30
|
+
alignItems: 'center',
|
31
|
+
justifyContent: 'center',
|
32
|
+
padding: 20,
|
33
|
+
},
|
34
|
+
text: {
|
35
|
+
fontSize: 24,
|
36
|
+
marginBottom: 20,
|
37
|
+
},
|
38
|
+
});
|
39
|
+
|
40
|
+
|
41
|
+
export default App;
|
package/dist/Button.d.ts
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
interface ButtonProps {
|
3
|
+
disabled?: boolean;
|
4
|
+
isFullWidth?: boolean;
|
5
|
+
children?: string;
|
6
|
+
onPress?: () => void;
|
7
|
+
rounded?: boolean;
|
8
|
+
borderRadius?: number;
|
9
|
+
type?: 'submit' | 'button' | 'cancel';
|
10
|
+
}
|
11
|
+
declare const Button: React.FC<ButtonProps>;
|
12
|
+
export default Button;
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import React, { ReactNode } from 'react';
|
2
|
+
import { Theme } from '../styles/theme';
|
3
|
+
interface ThemeContextProps {
|
4
|
+
theme: Theme;
|
5
|
+
toggleTheme: () => void;
|
6
|
+
}
|
7
|
+
export declare const ThemeContext: React.Context<ThemeContextProps>;
|
8
|
+
interface ThemeProviderProps {
|
9
|
+
children: ReactNode;
|
10
|
+
initialTheme?: 'light' | 'dark';
|
11
|
+
}
|
12
|
+
export declare const ThemeProvider: React.FC<ThemeProviderProps>;
|
13
|
+
export {};
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export * from './Theme';
|
package/dist/index.es.js
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
/*! aport-tools v1.0.2 | ISC */
|
2
|
+
import React, { createContext, useState, useEffect, useContext } from 'react';
|
3
|
+
import { Appearance, StyleSheet, View, Text, Switch } from 'react-native';
|
4
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
5
|
+
|
6
|
+
/******************************************************************************
|
7
|
+
Copyright (c) Microsoft Corporation.
|
8
|
+
|
9
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
10
|
+
purpose with or without fee is hereby granted.
|
11
|
+
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
13
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
14
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
15
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
16
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
17
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
18
|
+
PERFORMANCE OF THIS SOFTWARE.
|
19
|
+
***************************************************************************** */
|
20
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
21
|
+
|
22
|
+
|
23
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
24
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
25
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
26
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
27
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
28
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
29
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
30
|
+
});
|
31
|
+
}
|
32
|
+
|
33
|
+
function __generator(thisArg, body) {
|
34
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
35
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
36
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
37
|
+
function step(op) {
|
38
|
+
if (f) throw new TypeError("Generator is already executing.");
|
39
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
40
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
41
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
42
|
+
switch (op[0]) {
|
43
|
+
case 0: case 1: t = op; break;
|
44
|
+
case 4: _.label++; return { value: op[1], done: false };
|
45
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
46
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
47
|
+
default:
|
48
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
49
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
50
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
51
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
52
|
+
if (t[2]) _.ops.pop();
|
53
|
+
_.trys.pop(); continue;
|
54
|
+
}
|
55
|
+
op = body.call(thisArg, _);
|
56
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
57
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
62
|
+
var e = new Error(message);
|
63
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
64
|
+
};
|
65
|
+
|
66
|
+
// src/styles/colors.ts
|
67
|
+
var lightTheme = {
|
68
|
+
primary: {
|
69
|
+
hex: '#1A73E8',
|
70
|
+
rgb: {
|
71
|
+
r: 26,
|
72
|
+
g: 115,
|
73
|
+
b: 232
|
74
|
+
}
|
75
|
+
},
|
76
|
+
secondary: {
|
77
|
+
hex: '#F0F6FF',
|
78
|
+
rgb: {
|
79
|
+
r: 240,
|
80
|
+
g: 246,
|
81
|
+
b: 255
|
82
|
+
}
|
83
|
+
},
|
84
|
+
background: {
|
85
|
+
hex: '#FFFFFF',
|
86
|
+
rgb: {
|
87
|
+
r: 255,
|
88
|
+
g: 255,
|
89
|
+
b: 255
|
90
|
+
}
|
91
|
+
},
|
92
|
+
text: {
|
93
|
+
hex: '#000000',
|
94
|
+
rgb: {
|
95
|
+
r: 0,
|
96
|
+
g: 0,
|
97
|
+
b: 0
|
98
|
+
}
|
99
|
+
}
|
100
|
+
// Add more categories as needed
|
101
|
+
};
|
102
|
+
var darkTheme = {
|
103
|
+
primary: {
|
104
|
+
hex: '#BB86FC',
|
105
|
+
rgb: {
|
106
|
+
r: 187,
|
107
|
+
g: 134,
|
108
|
+
b: 252
|
109
|
+
}
|
110
|
+
},
|
111
|
+
secondary: {
|
112
|
+
hex: '#03DAC6',
|
113
|
+
rgb: {
|
114
|
+
r: 3,
|
115
|
+
g: 218,
|
116
|
+
b: 198
|
117
|
+
}
|
118
|
+
},
|
119
|
+
background: {
|
120
|
+
hex: '#121212',
|
121
|
+
rgb: {
|
122
|
+
r: 18,
|
123
|
+
g: 18,
|
124
|
+
b: 18
|
125
|
+
}
|
126
|
+
},
|
127
|
+
text: {
|
128
|
+
hex: '#FFFFFF',
|
129
|
+
rgb: {
|
130
|
+
r: 255,
|
131
|
+
g: 255,
|
132
|
+
b: 255
|
133
|
+
}
|
134
|
+
}
|
135
|
+
// Add more categories as needed
|
136
|
+
};
|
137
|
+
|
138
|
+
var ThemeContext = /*#__PURE__*/createContext({
|
139
|
+
theme: {
|
140
|
+
colors: lightTheme
|
141
|
+
},
|
142
|
+
toggleTheme: function toggleTheme() {}
|
143
|
+
});
|
144
|
+
var ThemeProvider = function ThemeProvider(_a) {
|
145
|
+
var children = _a.children,
|
146
|
+
initialTheme = _a.initialTheme;
|
147
|
+
var _b = useState(null),
|
148
|
+
colorScheme = _b[0],
|
149
|
+
setColorScheme = _b[1];
|
150
|
+
useEffect(function () {
|
151
|
+
var loadTheme = function loadTheme() {
|
152
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
153
|
+
var storedTheme, systemTheme, error_1;
|
154
|
+
return __generator(this, function (_a) {
|
155
|
+
switch (_a.label) {
|
156
|
+
case 0:
|
157
|
+
_a.trys.push([0, 2,, 3]);
|
158
|
+
return [4 /*yield*/, AsyncStorage.getItem('theme')];
|
159
|
+
case 1:
|
160
|
+
storedTheme = _a.sent();
|
161
|
+
if (storedTheme === 'dark' || storedTheme === 'light') {
|
162
|
+
setColorScheme(storedTheme);
|
163
|
+
} else if (initialTheme) {
|
164
|
+
setColorScheme(initialTheme); // Use initialTheme if provided
|
165
|
+
} else {
|
166
|
+
systemTheme = Appearance.getColorScheme();
|
167
|
+
setColorScheme(systemTheme);
|
168
|
+
}
|
169
|
+
return [3 /*break*/, 3];
|
170
|
+
case 2:
|
171
|
+
error_1 = _a.sent();
|
172
|
+
console.error('Failed to load theme.', error_1);
|
173
|
+
setColorScheme(Appearance.getColorScheme());
|
174
|
+
return [3 /*break*/, 3];
|
175
|
+
case 3:
|
176
|
+
return [2 /*return*/];
|
177
|
+
}
|
178
|
+
});
|
179
|
+
});
|
180
|
+
};
|
181
|
+
loadTheme();
|
182
|
+
var subscription = Appearance.addChangeListener(function (_a) {
|
183
|
+
var colorScheme = _a.colorScheme;
|
184
|
+
setColorScheme(colorScheme);
|
185
|
+
});
|
186
|
+
return function () {
|
187
|
+
return subscription.remove();
|
188
|
+
};
|
189
|
+
}, [initialTheme]);
|
190
|
+
var toggleTheme = function toggleTheme() {
|
191
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
192
|
+
var newTheme, error_2;
|
193
|
+
return __generator(this, function (_a) {
|
194
|
+
switch (_a.label) {
|
195
|
+
case 0:
|
196
|
+
_a.trys.push([0, 2,, 3]);
|
197
|
+
newTheme = colorScheme === 'dark' ? 'light' : 'dark';
|
198
|
+
setColorScheme(newTheme);
|
199
|
+
return [4 /*yield*/, AsyncStorage.setItem('theme', newTheme)];
|
200
|
+
case 1:
|
201
|
+
_a.sent();
|
202
|
+
return [3 /*break*/, 3];
|
203
|
+
case 2:
|
204
|
+
error_2 = _a.sent();
|
205
|
+
console.error('Failed to toggle theme.', error_2);
|
206
|
+
return [3 /*break*/, 3];
|
207
|
+
case 3:
|
208
|
+
return [2 /*return*/];
|
209
|
+
}
|
210
|
+
});
|
211
|
+
});
|
212
|
+
};
|
213
|
+
var theme = {
|
214
|
+
colors: colorScheme === 'dark' ? darkTheme : lightTheme
|
215
|
+
};
|
216
|
+
return /*#__PURE__*/React.createElement(ThemeContext.Provider, {
|
217
|
+
value: {
|
218
|
+
theme: theme,
|
219
|
+
toggleTheme: toggleTheme
|
220
|
+
}
|
221
|
+
}, children);
|
222
|
+
};
|
223
|
+
|
224
|
+
var ThemeToggle = function ThemeToggle() {
|
225
|
+
var _a = useContext(ThemeContext),
|
226
|
+
theme = _a.theme,
|
227
|
+
toggleTheme = _a.toggleTheme;
|
228
|
+
var isDarkMode = theme.colors === darkTheme;
|
229
|
+
return /*#__PURE__*/React.createElement(View, {
|
230
|
+
style: styles.container
|
231
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
232
|
+
style: [styles.text, {
|
233
|
+
color: theme.colors.text.hex
|
234
|
+
}]
|
235
|
+
}, "Dark Mode"), /*#__PURE__*/React.createElement(Switch, {
|
236
|
+
value: isDarkMode,
|
237
|
+
onValueChange: toggleTheme,
|
238
|
+
trackColor: {
|
239
|
+
"false": lightTheme.secondary.hex,
|
240
|
+
"true": darkTheme.primary.hex
|
241
|
+
},
|
242
|
+
thumbColor: isDarkMode ? darkTheme.secondary.hex : lightTheme.primary.hex
|
243
|
+
}));
|
244
|
+
};
|
245
|
+
var styles = StyleSheet.create({
|
246
|
+
container: {
|
247
|
+
marginTop: 20,
|
248
|
+
flexDirection: 'row',
|
249
|
+
alignItems: 'center'
|
250
|
+
},
|
251
|
+
text: {
|
252
|
+
marginRight: 10,
|
253
|
+
fontSize: 16
|
254
|
+
}
|
255
|
+
});
|
256
|
+
|
257
|
+
export { ThemeContext, ThemeProvider, ThemeToggle };
|
package/dist/index.js
ADDED
@@ -0,0 +1,261 @@
|
|
1
|
+
/*! aport-tools v1.0.2 | ISC */
|
2
|
+
'use strict';
|
3
|
+
|
4
|
+
var React = require('react');
|
5
|
+
var reactNative = require('react-native');
|
6
|
+
var AsyncStorage = require('@react-native-async-storage/async-storage');
|
7
|
+
|
8
|
+
/******************************************************************************
|
9
|
+
Copyright (c) Microsoft Corporation.
|
10
|
+
|
11
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
12
|
+
purpose with or without fee is hereby granted.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
15
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
16
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
17
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
18
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
19
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
20
|
+
PERFORMANCE OF THIS SOFTWARE.
|
21
|
+
***************************************************************************** */
|
22
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
23
|
+
|
24
|
+
|
25
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
32
|
+
});
|
33
|
+
}
|
34
|
+
|
35
|
+
function __generator(thisArg, body) {
|
36
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
37
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
38
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
39
|
+
function step(op) {
|
40
|
+
if (f) throw new TypeError("Generator is already executing.");
|
41
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
42
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
43
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
44
|
+
switch (op[0]) {
|
45
|
+
case 0: case 1: t = op; break;
|
46
|
+
case 4: _.label++; return { value: op[1], done: false };
|
47
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
48
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
49
|
+
default:
|
50
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
51
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
52
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
53
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
54
|
+
if (t[2]) _.ops.pop();
|
55
|
+
_.trys.pop(); continue;
|
56
|
+
}
|
57
|
+
op = body.call(thisArg, _);
|
58
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
59
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
64
|
+
var e = new Error(message);
|
65
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
66
|
+
};
|
67
|
+
|
68
|
+
// src/styles/colors.ts
|
69
|
+
var lightTheme = {
|
70
|
+
primary: {
|
71
|
+
hex: '#1A73E8',
|
72
|
+
rgb: {
|
73
|
+
r: 26,
|
74
|
+
g: 115,
|
75
|
+
b: 232
|
76
|
+
}
|
77
|
+
},
|
78
|
+
secondary: {
|
79
|
+
hex: '#F0F6FF',
|
80
|
+
rgb: {
|
81
|
+
r: 240,
|
82
|
+
g: 246,
|
83
|
+
b: 255
|
84
|
+
}
|
85
|
+
},
|
86
|
+
background: {
|
87
|
+
hex: '#FFFFFF',
|
88
|
+
rgb: {
|
89
|
+
r: 255,
|
90
|
+
g: 255,
|
91
|
+
b: 255
|
92
|
+
}
|
93
|
+
},
|
94
|
+
text: {
|
95
|
+
hex: '#000000',
|
96
|
+
rgb: {
|
97
|
+
r: 0,
|
98
|
+
g: 0,
|
99
|
+
b: 0
|
100
|
+
}
|
101
|
+
}
|
102
|
+
// Add more categories as needed
|
103
|
+
};
|
104
|
+
var darkTheme = {
|
105
|
+
primary: {
|
106
|
+
hex: '#BB86FC',
|
107
|
+
rgb: {
|
108
|
+
r: 187,
|
109
|
+
g: 134,
|
110
|
+
b: 252
|
111
|
+
}
|
112
|
+
},
|
113
|
+
secondary: {
|
114
|
+
hex: '#03DAC6',
|
115
|
+
rgb: {
|
116
|
+
r: 3,
|
117
|
+
g: 218,
|
118
|
+
b: 198
|
119
|
+
}
|
120
|
+
},
|
121
|
+
background: {
|
122
|
+
hex: '#121212',
|
123
|
+
rgb: {
|
124
|
+
r: 18,
|
125
|
+
g: 18,
|
126
|
+
b: 18
|
127
|
+
}
|
128
|
+
},
|
129
|
+
text: {
|
130
|
+
hex: '#FFFFFF',
|
131
|
+
rgb: {
|
132
|
+
r: 255,
|
133
|
+
g: 255,
|
134
|
+
b: 255
|
135
|
+
}
|
136
|
+
}
|
137
|
+
// Add more categories as needed
|
138
|
+
};
|
139
|
+
|
140
|
+
var ThemeContext = /*#__PURE__*/React.createContext({
|
141
|
+
theme: {
|
142
|
+
colors: lightTheme
|
143
|
+
},
|
144
|
+
toggleTheme: function toggleTheme() {}
|
145
|
+
});
|
146
|
+
var ThemeProvider = function ThemeProvider(_a) {
|
147
|
+
var children = _a.children,
|
148
|
+
initialTheme = _a.initialTheme;
|
149
|
+
var _b = React.useState(null),
|
150
|
+
colorScheme = _b[0],
|
151
|
+
setColorScheme = _b[1];
|
152
|
+
React.useEffect(function () {
|
153
|
+
var loadTheme = function loadTheme() {
|
154
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
155
|
+
var storedTheme, systemTheme, error_1;
|
156
|
+
return __generator(this, function (_a) {
|
157
|
+
switch (_a.label) {
|
158
|
+
case 0:
|
159
|
+
_a.trys.push([0, 2,, 3]);
|
160
|
+
return [4 /*yield*/, AsyncStorage.getItem('theme')];
|
161
|
+
case 1:
|
162
|
+
storedTheme = _a.sent();
|
163
|
+
if (storedTheme === 'dark' || storedTheme === 'light') {
|
164
|
+
setColorScheme(storedTheme);
|
165
|
+
} else if (initialTheme) {
|
166
|
+
setColorScheme(initialTheme); // Use initialTheme if provided
|
167
|
+
} else {
|
168
|
+
systemTheme = reactNative.Appearance.getColorScheme();
|
169
|
+
setColorScheme(systemTheme);
|
170
|
+
}
|
171
|
+
return [3 /*break*/, 3];
|
172
|
+
case 2:
|
173
|
+
error_1 = _a.sent();
|
174
|
+
console.error('Failed to load theme.', error_1);
|
175
|
+
setColorScheme(reactNative.Appearance.getColorScheme());
|
176
|
+
return [3 /*break*/, 3];
|
177
|
+
case 3:
|
178
|
+
return [2 /*return*/];
|
179
|
+
}
|
180
|
+
});
|
181
|
+
});
|
182
|
+
};
|
183
|
+
loadTheme();
|
184
|
+
var subscription = reactNative.Appearance.addChangeListener(function (_a) {
|
185
|
+
var colorScheme = _a.colorScheme;
|
186
|
+
setColorScheme(colorScheme);
|
187
|
+
});
|
188
|
+
return function () {
|
189
|
+
return subscription.remove();
|
190
|
+
};
|
191
|
+
}, [initialTheme]);
|
192
|
+
var toggleTheme = function toggleTheme() {
|
193
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
194
|
+
var newTheme, error_2;
|
195
|
+
return __generator(this, function (_a) {
|
196
|
+
switch (_a.label) {
|
197
|
+
case 0:
|
198
|
+
_a.trys.push([0, 2,, 3]);
|
199
|
+
newTheme = colorScheme === 'dark' ? 'light' : 'dark';
|
200
|
+
setColorScheme(newTheme);
|
201
|
+
return [4 /*yield*/, AsyncStorage.setItem('theme', newTheme)];
|
202
|
+
case 1:
|
203
|
+
_a.sent();
|
204
|
+
return [3 /*break*/, 3];
|
205
|
+
case 2:
|
206
|
+
error_2 = _a.sent();
|
207
|
+
console.error('Failed to toggle theme.', error_2);
|
208
|
+
return [3 /*break*/, 3];
|
209
|
+
case 3:
|
210
|
+
return [2 /*return*/];
|
211
|
+
}
|
212
|
+
});
|
213
|
+
});
|
214
|
+
};
|
215
|
+
var theme = {
|
216
|
+
colors: colorScheme === 'dark' ? darkTheme : lightTheme
|
217
|
+
};
|
218
|
+
return /*#__PURE__*/React.createElement(ThemeContext.Provider, {
|
219
|
+
value: {
|
220
|
+
theme: theme,
|
221
|
+
toggleTheme: toggleTheme
|
222
|
+
}
|
223
|
+
}, children);
|
224
|
+
};
|
225
|
+
|
226
|
+
var ThemeToggle = function ThemeToggle() {
|
227
|
+
var _a = React.useContext(ThemeContext),
|
228
|
+
theme = _a.theme,
|
229
|
+
toggleTheme = _a.toggleTheme;
|
230
|
+
var isDarkMode = theme.colors === darkTheme;
|
231
|
+
return /*#__PURE__*/React.createElement(reactNative.View, {
|
232
|
+
style: styles.container
|
233
|
+
}, /*#__PURE__*/React.createElement(reactNative.Text, {
|
234
|
+
style: [styles.text, {
|
235
|
+
color: theme.colors.text.hex
|
236
|
+
}]
|
237
|
+
}, "Dark Mode"), /*#__PURE__*/React.createElement(reactNative.Switch, {
|
238
|
+
value: isDarkMode,
|
239
|
+
onValueChange: toggleTheme,
|
240
|
+
trackColor: {
|
241
|
+
"false": lightTheme.secondary.hex,
|
242
|
+
"true": darkTheme.primary.hex
|
243
|
+
},
|
244
|
+
thumbColor: isDarkMode ? darkTheme.secondary.hex : lightTheme.primary.hex
|
245
|
+
}));
|
246
|
+
};
|
247
|
+
var styles = reactNative.StyleSheet.create({
|
248
|
+
container: {
|
249
|
+
marginTop: 20,
|
250
|
+
flexDirection: 'row',
|
251
|
+
alignItems: 'center'
|
252
|
+
},
|
253
|
+
text: {
|
254
|
+
marginRight: 10,
|
255
|
+
fontSize: 16
|
256
|
+
}
|
257
|
+
});
|
258
|
+
|
259
|
+
exports.ThemeContext = ThemeContext;
|
260
|
+
exports.ThemeProvider = ThemeProvider;
|
261
|
+
exports.ThemeToggle = ThemeToggle;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
export interface RGB {
|
2
|
+
r: number;
|
3
|
+
g: number;
|
4
|
+
b: number;
|
5
|
+
}
|
6
|
+
export interface Color {
|
7
|
+
hex: string;
|
8
|
+
rgb: RGB;
|
9
|
+
}
|
10
|
+
export interface ThemeColors {
|
11
|
+
primary: Color;
|
12
|
+
secondary: Color;
|
13
|
+
background: Color;
|
14
|
+
text: Color;
|
15
|
+
}
|
16
|
+
export declare const lightTheme: ThemeColors;
|
17
|
+
export declare const darkTheme: ThemeColors;
|
package/index.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export { default as ButtonComponent } from "./src/Button";
|
package/package.json
CHANGED
@@ -1,16 +1,36 @@
|
|
1
1
|
{
|
2
2
|
"name": "aport-tools",
|
3
|
-
"version": "1.0.
|
4
|
-
"description": "",
|
5
|
-
|
3
|
+
"version": "1.0.2",
|
4
|
+
"description": "Aport mobile Tools with modern and minimalistic design",
|
5
|
+
"main": "dist/index.js",
|
6
|
+
"type": "module",
|
7
|
+
"react-native": "dist/index.js",
|
8
|
+
"source": "src/index.ts",
|
9
|
+
"types": "dist/index.d.ts",
|
6
10
|
"scripts": {
|
11
|
+
"build": "rollup -c rollup.config.mjs",
|
12
|
+
"prepare": "npm run build",
|
7
13
|
"test": "echo \"Error: no test specified\" && exit 1"
|
8
14
|
},
|
9
|
-
"keywords": [
|
15
|
+
"keywords": [
|
16
|
+
"react-native",
|
17
|
+
"theme",
|
18
|
+
"provider",
|
19
|
+
"context",
|
20
|
+
"toggle",
|
21
|
+
"mobile",
|
22
|
+
"tools"
|
23
|
+
],
|
10
24
|
"author": "EvansGxz",
|
11
25
|
"license": "ISC",
|
12
26
|
"devDependencies": {
|
27
|
+
"@babel/core": "^7.25.2",
|
28
|
+
"@babel/preset-env": "^7.25.4",
|
29
|
+
"@babel/preset-react": "^7.24.7",
|
30
|
+
"@babel/preset-typescript": "^7.24.7",
|
31
|
+
"@rollup/plugin-babel": "^6.0.4",
|
13
32
|
"@rollup/plugin-commonjs": "^28.0.0",
|
33
|
+
"@rollup/plugin-json": "^6.1.0",
|
14
34
|
"@rollup/plugin-node-resolve": "^15.3.0",
|
15
35
|
"@rollup/plugin-typescript": "^12.1.0",
|
16
36
|
"@types/react": "^18.3.10",
|
@@ -20,11 +40,10 @@
|
|
20
40
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
21
41
|
"typescript": "^5.6.2"
|
22
42
|
},
|
23
|
-
"
|
43
|
+
"peerDependencies": {
|
24
44
|
"@react-native-async-storage/async-storage": "^2.0.0",
|
25
|
-
"
|
26
|
-
"react": "
|
27
|
-
"react-native": "^0.75.3",
|
45
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
46
|
+
"react-native": ">=0.60",
|
28
47
|
"styled-components": "^6.1.13"
|
29
48
|
}
|
30
49
|
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
// rollup.config.js
|
2
|
+
|
3
|
+
import babel from '@rollup/plugin-babel';
|
4
|
+
import typescript from '@rollup/plugin-typescript';
|
5
|
+
import commonjs from '@rollup/plugin-commonjs';
|
6
|
+
import resolve from '@rollup/plugin-node-resolve';
|
7
|
+
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
8
|
+
import pkg from './package.json' assert { type: 'json' };
|
9
|
+
|
10
|
+
export default {
|
11
|
+
input: 'src/index.ts', // Entry point
|
12
|
+
output: [
|
13
|
+
{
|
14
|
+
file: 'dist/index.js',
|
15
|
+
format: 'cjs',
|
16
|
+
name: pkg.name, // Use package name
|
17
|
+
banner: `/*! ${pkg.name} v${pkg.version} | ${pkg.license} */`, // Add banner comment with package info
|
18
|
+
},
|
19
|
+
{
|
20
|
+
file: 'dist/index.es.js',
|
21
|
+
format: 'es',
|
22
|
+
name: pkg.name,
|
23
|
+
banner: `/*! ${pkg.name} v${pkg.version} | ${pkg.license} */`,
|
24
|
+
},
|
25
|
+
],
|
26
|
+
plugins: [
|
27
|
+
peerDepsExternal(),
|
28
|
+
resolve({
|
29
|
+
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
30
|
+
}),
|
31
|
+
commonjs(),
|
32
|
+
babel({
|
33
|
+
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
34
|
+
include: ['src/**/*'],
|
35
|
+
babelHelpers: 'bundled',
|
36
|
+
presets: [
|
37
|
+
'@babel/preset-env',
|
38
|
+
'@babel/preset-react',
|
39
|
+
'@babel/preset-typescript',
|
40
|
+
],
|
41
|
+
}),
|
42
|
+
typescript({
|
43
|
+
tsconfig: './tsconfig.json',
|
44
|
+
declaration: true,
|
45
|
+
declarationDir: 'dist',
|
46
|
+
emitDeclarationOnly: false, // Set to true if you want TypeScript to only emit declarations and let Babel handle the JS transpilation
|
47
|
+
}),
|
48
|
+
],
|
49
|
+
external: [
|
50
|
+
'react',
|
51
|
+
'react-native',
|
52
|
+
'@react-native-async-storage/async-storage',
|
53
|
+
'styled-components',
|
54
|
+
], // Dependencies not to bundle
|
55
|
+
};
|
package/rollup.config.js
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
// rollup.config.js
|
2
|
-
|
3
|
-
import typescript from '@rollup/plugin-typescript';
|
4
|
-
import resolve from '@rollup/plugin-node-resolve';
|
5
|
-
import commonjs from '@rollup/plugin-commonjs';
|
6
|
-
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
7
|
-
|
8
|
-
export default {
|
9
|
-
input: 'src/index.ts', // Entry point of your library
|
10
|
-
output: [
|
11
|
-
{
|
12
|
-
file: 'dist/index.js', // CommonJS format
|
13
|
-
format: 'cjs',
|
14
|
-
sourcemap: true,
|
15
|
-
},
|
16
|
-
{
|
17
|
-
file: 'dist/index.es.js', // ES Module format
|
18
|
-
format: 'esm',
|
19
|
-
sourcemap: true,
|
20
|
-
},
|
21
|
-
],
|
22
|
-
plugins: [
|
23
|
-
peerDepsExternal(), // Automatically externalize peer dependencies
|
24
|
-
resolve({
|
25
|
-
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
26
|
-
}), // So Rollup can find node_modules
|
27
|
-
commonjs(), // So Rollup can convert commonjs to ES modules
|
28
|
-
typescript({ tsconfig: './tsconfig.json' }), // So Rollup can handle TypeScript
|
29
|
-
],
|
30
|
-
external: ['react', 'react-native'], // Explicitly externalize dependencies
|
31
|
-
};
|
package/src/Button.tsx
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
// src/components/Button.tsx
|
2
|
-
|
3
|
-
import React, { useMemo, useContext } from 'react';
|
4
|
-
import { Text, ViewStyle, StyleSheet, TouchableOpacity } from 'react-native';
|
5
|
-
import { ThemeContext } from './context/ThemeContext'; // Adjust path to your ThemeContext
|
6
|
-
import { ThemeColors } from './styles/colors';
|
7
|
-
|
8
|
-
// Define the interface for the props that the Button component will accept
|
9
|
-
interface ButtonProps {
|
10
|
-
disabled?: boolean; // Optional: Disables the button if true
|
11
|
-
isFullWidth?: boolean; // Optional: Expands the button to full width if true
|
12
|
-
children?: string; // Optional: Text content of the button
|
13
|
-
onPress?: () => void; // Optional: Function to call when the button is pressed
|
14
|
-
rounded?: boolean; // Optional: Adds border radius if true
|
15
|
-
borderRadius?: number; // Optional: Custom border radius value
|
16
|
-
type?: 'submit' | 'button' | 'cancel'; // Optional: Specifies the button type for styling
|
17
|
-
}
|
18
|
-
|
19
|
-
// Function to determine the styles based on the button type and whether it is disabled
|
20
|
-
function typeStyles(type?: string, disabled?: boolean, themeColors?: ThemeColors): ViewStyle {
|
21
|
-
switch (type) {
|
22
|
-
case 'submit':
|
23
|
-
return {
|
24
|
-
backgroundColor: `rgba(${themeColors?.primary.rgb.r}, ${themeColors?.primary.rgb.g}, ${themeColors?.primary.rgb.b}, ${
|
25
|
-
disabled ? 0.5 : 1
|
26
|
-
})`,
|
27
|
-
borderWidth: 2,
|
28
|
-
borderColor: themeColors?.primary.hex,
|
29
|
-
};
|
30
|
-
case 'button':
|
31
|
-
return {
|
32
|
-
backgroundColor: themeColors?.primary.hex,
|
33
|
-
borderColor: themeColors?.secondary.hex,
|
34
|
-
opacity: disabled ? 0.5 : 1,
|
35
|
-
borderWidth: 2,
|
36
|
-
};
|
37
|
-
case 'cancel':
|
38
|
-
return {
|
39
|
-
backgroundColor: themeColors?.background.hex,
|
40
|
-
borderWidth: 0,
|
41
|
-
};
|
42
|
-
default:
|
43
|
-
return {};
|
44
|
-
}
|
45
|
-
}
|
46
|
-
|
47
|
-
// Button component definition
|
48
|
-
const Button: React.FC<ButtonProps> = ({
|
49
|
-
children,
|
50
|
-
disabled = false,
|
51
|
-
type = 'button',
|
52
|
-
rounded = true,
|
53
|
-
borderRadius = 30,
|
54
|
-
isFullWidth = false,
|
55
|
-
onPress,
|
56
|
-
}) => {
|
57
|
-
// Access the current theme from ThemeContext
|
58
|
-
const { theme } = useContext(ThemeContext);
|
59
|
-
const { colors } = theme; // Extract colors from the theme
|
60
|
-
|
61
|
-
// Use useMemo to memoize the computed styles
|
62
|
-
const computedStyles = useMemo(() => {
|
63
|
-
return StyleSheet.flatten([
|
64
|
-
styles.button,
|
65
|
-
typeStyles(type, disabled, colors), // Use colors directly
|
66
|
-
rounded && { borderRadius },
|
67
|
-
isFullWidth && { width: '100%' },
|
68
|
-
disabled && styles.disabled,
|
69
|
-
]);
|
70
|
-
}, [type, disabled, rounded, borderRadius, isFullWidth, colors]);
|
71
|
-
|
72
|
-
// Determine text color based on button type and theme
|
73
|
-
const textColor = useMemo(() => {
|
74
|
-
return { color: colors.text.hex }; // Access text color from the theme
|
75
|
-
}, [type, colors]);
|
76
|
-
|
77
|
-
return (
|
78
|
-
<TouchableOpacity
|
79
|
-
style={computedStyles as ViewStyle}
|
80
|
-
disabled={disabled}
|
81
|
-
onPress={onPress}
|
82
|
-
activeOpacity={0.7}
|
83
|
-
>
|
84
|
-
<Text style={textColor}>
|
85
|
-
{Array.isArray(children) ? children.join('').toUpperCase() : children?.toUpperCase()}
|
86
|
-
</Text>
|
87
|
-
</TouchableOpacity>
|
88
|
-
);
|
89
|
-
};
|
90
|
-
|
91
|
-
// Define basic styles for the button
|
92
|
-
const styles = StyleSheet.create({
|
93
|
-
button: {
|
94
|
-
justifyContent: 'center',
|
95
|
-
alignItems: 'center',
|
96
|
-
paddingVertical: 10,
|
97
|
-
paddingHorizontal: 20,
|
98
|
-
},
|
99
|
-
disabled: {
|
100
|
-
opacity: 0.6,
|
101
|
-
},
|
102
|
-
});
|
103
|
-
|
104
|
-
export default Button;
|
@@ -1,39 +0,0 @@
|
|
1
|
-
// src/components/ThemeToggle.tsx
|
2
|
-
|
3
|
-
import React, { useContext } from 'react';
|
4
|
-
import { Switch, View, Text, StyleSheet } from 'react-native';
|
5
|
-
import { ThemeContext } from '../context/ThemeContext';
|
6
|
-
import { darkTheme, lightTheme } from '../styles/colors';
|
7
|
-
|
8
|
-
const ThemeToggle: React.FC = () => {
|
9
|
-
const { theme, toggleTheme } = useContext(ThemeContext);
|
10
|
-
|
11
|
-
// Determine if the current theme is dark by checking the colors property
|
12
|
-
const isDarkMode = theme.colors === darkTheme;
|
13
|
-
|
14
|
-
return (
|
15
|
-
<View style={styles.container}>
|
16
|
-
<Text style={[styles.text, { color: theme.colors.text.hex }]}>Dark Mode</Text>
|
17
|
-
<Switch
|
18
|
-
value={isDarkMode}
|
19
|
-
onValueChange={toggleTheme}
|
20
|
-
trackColor={{ false: lightTheme.secondary.hex, true: darkTheme.primary.hex }}
|
21
|
-
thumbColor={isDarkMode ? darkTheme.secondary.hex : lightTheme.primary.hex}
|
22
|
-
/>
|
23
|
-
</View>
|
24
|
-
);
|
25
|
-
};
|
26
|
-
|
27
|
-
const styles = StyleSheet.create({
|
28
|
-
container: {
|
29
|
-
marginTop: 20,
|
30
|
-
flexDirection: 'row',
|
31
|
-
alignItems: 'center',
|
32
|
-
},
|
33
|
-
text: {
|
34
|
-
marginRight: 10,
|
35
|
-
fontSize: 16,
|
36
|
-
},
|
37
|
-
});
|
38
|
-
|
39
|
-
export default ThemeToggle;
|
@@ -1,70 +0,0 @@
|
|
1
|
-
// src/context/ThemeContext.tsx
|
2
|
-
|
3
|
-
import React, { createContext, useState, useEffect, ReactNode } from 'react';
|
4
|
-
import { Appearance, ColorSchemeName } from 'react-native';
|
5
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
6
|
-
import { lightTheme, darkTheme, ThemeColors } from '../styles/colors';
|
7
|
-
import { Theme } from '../styles/theme';
|
8
|
-
|
9
|
-
interface ThemeContextProps {
|
10
|
-
theme: Theme;
|
11
|
-
toggleTheme: () => void;
|
12
|
-
}
|
13
|
-
|
14
|
-
export const ThemeContext = createContext<ThemeContextProps>({
|
15
|
-
theme: { colors: lightTheme },
|
16
|
-
toggleTheme: () => {},
|
17
|
-
});
|
18
|
-
|
19
|
-
interface ThemeProviderProps {
|
20
|
-
children: ReactNode;
|
21
|
-
}
|
22
|
-
|
23
|
-
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
|
24
|
-
const [colorScheme, setColorScheme] = useState<ColorSchemeName | null>(null);
|
25
|
-
|
26
|
-
useEffect(() => {
|
27
|
-
const loadTheme = async () => {
|
28
|
-
try {
|
29
|
-
const storedTheme = await AsyncStorage.getItem('theme');
|
30
|
-
if (storedTheme === 'dark' || storedTheme === 'light') {
|
31
|
-
setColorScheme(storedTheme);
|
32
|
-
} else {
|
33
|
-
const systemTheme = Appearance.getColorScheme();
|
34
|
-
setColorScheme(systemTheme);
|
35
|
-
}
|
36
|
-
} catch (error) {
|
37
|
-
console.error('Failed to load theme.', error);
|
38
|
-
setColorScheme(Appearance.getColorScheme());
|
39
|
-
}
|
40
|
-
};
|
41
|
-
|
42
|
-
loadTheme();
|
43
|
-
|
44
|
-
const subscription = Appearance.addChangeListener(({ colorScheme }) => {
|
45
|
-
setColorScheme(colorScheme);
|
46
|
-
});
|
47
|
-
|
48
|
-
return () => subscription.remove();
|
49
|
-
}, []);
|
50
|
-
|
51
|
-
const toggleTheme = async () => {
|
52
|
-
try {
|
53
|
-
const newTheme = colorScheme === 'dark' ? 'light' : 'dark';
|
54
|
-
setColorScheme(newTheme);
|
55
|
-
await AsyncStorage.setItem('theme', newTheme);
|
56
|
-
} catch (error) {
|
57
|
-
console.error('Failed to toggle theme.', error);
|
58
|
-
}
|
59
|
-
};
|
60
|
-
|
61
|
-
const theme: Theme = {
|
62
|
-
colors: colorScheme === 'dark' ? darkTheme : lightTheme,
|
63
|
-
};
|
64
|
-
|
65
|
-
return (
|
66
|
-
<ThemeContext.Provider value={{ theme, toggleTheme }}>
|
67
|
-
{children}
|
68
|
-
</ThemeContext.Provider>
|
69
|
-
);
|
70
|
-
};
|
package/src/index.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export { default as ButtonComponent } from "./Button";
|
package/src/styles/colors.ts
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
// src/styles/colors.ts
|
2
|
-
|
3
|
-
export interface RGB {
|
4
|
-
r: number;
|
5
|
-
g: number;
|
6
|
-
b: number;
|
7
|
-
}
|
8
|
-
|
9
|
-
export interface Color {
|
10
|
-
hex: string;
|
11
|
-
rgb: RGB;
|
12
|
-
}
|
13
|
-
|
14
|
-
export interface ThemeColors {
|
15
|
-
primary: Color;
|
16
|
-
secondary: Color;
|
17
|
-
background: Color;
|
18
|
-
text: Color;
|
19
|
-
// Add more categories as needed
|
20
|
-
}
|
21
|
-
|
22
|
-
export const lightTheme: ThemeColors = {
|
23
|
-
primary: {
|
24
|
-
hex: '#1A73E8',
|
25
|
-
rgb: { r: 26, g: 115, b: 232 },
|
26
|
-
},
|
27
|
-
secondary: {
|
28
|
-
hex: '#F0F6FF',
|
29
|
-
rgb: { r: 240, g: 246, b: 255 },
|
30
|
-
},
|
31
|
-
background: {
|
32
|
-
hex: '#FFFFFF',
|
33
|
-
rgb: { r: 255, g: 255, b: 255 },
|
34
|
-
},
|
35
|
-
text: {
|
36
|
-
hex: '#000000',
|
37
|
-
rgb: { r: 0, g: 0, b: 0 },
|
38
|
-
},
|
39
|
-
// Add more categories as needed
|
40
|
-
};
|
41
|
-
|
42
|
-
export const darkTheme: ThemeColors = {
|
43
|
-
primary: {
|
44
|
-
hex: '#BB86FC',
|
45
|
-
rgb: { r: 187, g: 134, b: 252 },
|
46
|
-
},
|
47
|
-
secondary: {
|
48
|
-
hex: '#03DAC6',
|
49
|
-
rgb: { r: 3, g: 218, b: 198 },
|
50
|
-
},
|
51
|
-
background: {
|
52
|
-
hex: '#121212',
|
53
|
-
rgb: { r: 18, g: 18, b: 18 },
|
54
|
-
},
|
55
|
-
text: {
|
56
|
-
hex: '#FFFFFF',
|
57
|
-
rgb: { r: 255, g: 255, b: 255 },
|
58
|
-
},
|
59
|
-
// Add more categories as needed
|
60
|
-
};
|
package/src/styles/theme.ts
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
// src/styles/theme.ts
|
2
|
-
|
3
|
-
import { ThemeColors } from "./colors";
|
4
|
-
|
5
|
-
// Define the light theme with full ThemeColors structure
|
6
|
-
export const lightTheme: ThemeColors = {
|
7
|
-
primary: {
|
8
|
-
hex: "#1A73E8",
|
9
|
-
rgb: { r: 26, g: 115, b: 232 },
|
10
|
-
},
|
11
|
-
secondary: {
|
12
|
-
hex: "#F0F6FF",
|
13
|
-
rgb: { r: 240, g: 246, b: 255 },
|
14
|
-
},
|
15
|
-
background: {
|
16
|
-
hex: "#FFFFFF",
|
17
|
-
rgb: { r: 255, g: 255, b: 255 },
|
18
|
-
},
|
19
|
-
text: {
|
20
|
-
hex: "#000000",
|
21
|
-
rgb: { r: 0, g: 0, b: 0 },
|
22
|
-
},
|
23
|
-
};
|
24
|
-
|
25
|
-
// Define the dark theme with full ThemeColors structure
|
26
|
-
export const darkTheme: ThemeColors = {
|
27
|
-
primary: {
|
28
|
-
hex: "#BB86FC",
|
29
|
-
rgb: { r: 187, g: 134, b: 252 },
|
30
|
-
},
|
31
|
-
secondary: {
|
32
|
-
hex: "#03DAC6",
|
33
|
-
rgb: { r: 3, g: 218, b: 198 },
|
34
|
-
},
|
35
|
-
background: {
|
36
|
-
hex: "#121212",
|
37
|
-
rgb: { r: 18, g: 18, b: 18 },
|
38
|
-
},
|
39
|
-
text: {
|
40
|
-
hex: "#FFFFFF",
|
41
|
-
rgb: { r: 255, g: 255, b: 255 },
|
42
|
-
},
|
43
|
-
};
|
44
|
-
|
45
|
-
// src/styles/theme.ts
|
46
|
-
|
47
|
-
export interface Theme {
|
48
|
-
colors: ThemeColors;
|
49
|
-
}
|
50
|
-
|
package/tsconfig.json
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"compilerOptions": {
|
3
|
-
"outDir": "dist",
|
4
|
-
"module": "ES6",
|
5
|
-
"target": "ES5",
|
6
|
-
"lib": [
|
7
|
-
"ES2015",
|
8
|
-
"DOM"
|
9
|
-
],
|
10
|
-
"jsx": "react-native",
|
11
|
-
"declaration": true,
|
12
|
-
"esModuleInterop": true,
|
13
|
-
"forceConsistentCasingInFileNames": true,
|
14
|
-
"strict": true,
|
15
|
-
"skipLibCheck": true,
|
16
|
-
"moduleResolution": "node",
|
17
|
-
"types": [
|
18
|
-
"react",
|
19
|
-
"react-native"
|
20
|
-
]
|
21
|
-
},
|
22
|
-
"include": [
|
23
|
-
"src" ],
|
24
|
-
"exclude": [
|
25
|
-
"node_modules",
|
26
|
-
"dist",
|
27
|
-
"App.tsx"
|
28
|
-
],
|
29
|
-
"extends": "expo/tsconfig.base"
|
30
|
-
}
|