@teamvortexsoftware/vortex-react-native 0.0.7 → 0.0.9
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/dist/components/ShareButtons.js +170 -0
- package/dist/hooks/useThemeStyles.js +39 -0
- package/dist/hooks/useVortexInvite.js +281 -0
- package/dist/index.js +5 -0
- package/dist/shared/InvitationResult.js +2 -0
- package/dist/shared/api.js +90 -0
- package/dist/tests/TestVortexInvite.js +134 -0
- package/dist/types/components/ShareButtons.d.ts +27 -0
- package/dist/types/components/ShareButtons.d.ts.map +1 -0
- package/dist/types/hooks/useThemeStyles.d.ts +34 -0
- package/dist/types/hooks/useThemeStyles.d.ts.map +1 -0
- package/dist/types/hooks/useVortexInvite.d.ts +41 -0
- package/dist/types/hooks/useVortexInvite.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/shared/InvitationResult.d.ts +24 -0
- package/dist/types/shared/InvitationResult.d.ts.map +1 -0
- package/dist/types/shared/api.d.ts +14 -0
- package/dist/types/shared/api.d.ts.map +1 -0
- package/dist/types/tests/TestVortexInvite.d.ts +4 -0
- package/dist/types/tests/TestVortexInvite.d.ts.map +1 -0
- package/dist/types/utils/formUtils.d.ts +85 -0
- package/dist/types/utils/formUtils.d.ts.map +1 -0
- package/dist/types/utils/themeUtils.d.ts +35 -0
- package/dist/types/utils/themeUtils.d.ts.map +1 -0
- package/dist/types/vortexInvite.d.ts +25 -0
- package/dist/types/vortexInvite.d.ts.map +1 -0
- package/dist/utils/formUtils.js +174 -0
- package/dist/utils/themeUtils.js +55 -0
- package/dist/vortexInvite.js +172 -0
- package/package.json +21 -9
- package/plugin/withVortexReactNative.js +74 -0
- package/plugin.js +2 -0
- package/eslint.config.mjs +0 -4
- package/src/components/ShareButtons.tsx +0 -172
- package/src/hooks/useThemeStyles.ts +0 -42
- package/src/hooks/useVortexInvite.ts +0 -278
- package/src/index.tsx +0 -2
- package/src/shared/api.ts +0 -67
- package/src/utils/themeUtils.ts +0 -85
- package/src/vortexInvite.tsx +0 -188
- package/tsconfig.json +0 -9
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractThemeColors = extractThemeColors;
|
|
4
|
+
exports.extractFeatureFlags = extractFeatureFlags;
|
|
5
|
+
/**
|
|
6
|
+
* Extracts theme colors from widget configuration
|
|
7
|
+
*/
|
|
8
|
+
function extractThemeColors(widgetConfiguration) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
const options = (_a = widgetConfiguration === null || widgetConfiguration === void 0 ? void 0 : widgetConfiguration.configuration) === null || _a === void 0 ? void 0 : _a.props;
|
|
11
|
+
const colors = ((_b = options === null || options === void 0 ? void 0 : options['vortex.theme.colors']) === null || _b === void 0 ? void 0 : _b.value) || [];
|
|
12
|
+
const colorMap = {};
|
|
13
|
+
colors.forEach((color) => {
|
|
14
|
+
if (color.key && color.value) {
|
|
15
|
+
colorMap[color.key] = color.value;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return {
|
|
19
|
+
containerBackground: colorMap['--container-background'] || '#ffffff',
|
|
20
|
+
containerForeground: colorMap['--container-foreground-color'] || '#666666',
|
|
21
|
+
containerBorder: colorMap['--container-border-color'] || '#c4c4c4',
|
|
22
|
+
primaryButtonBackground: colorMap['--primary-button-background'] || '#197af3',
|
|
23
|
+
primaryButtonForeground: colorMap['--primary-button-foreground-color'] || '#ffffff',
|
|
24
|
+
primaryButtonBorder: colorMap['--primary-button-border-color'] || '#000000',
|
|
25
|
+
secondaryButtonBackground: colorMap['--secondary-button-background'] || '#dfdfdf',
|
|
26
|
+
secondaryButtonForeground: colorMap['--secondary-button-foreground-color'] || '#000000',
|
|
27
|
+
secondaryButtonBorder: colorMap['--secondary-button-border-color'] || '#c4c4c4',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Extracts feature flags from widget configuration
|
|
32
|
+
*/
|
|
33
|
+
function extractFeatureFlags(widgetConfiguration) {
|
|
34
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
35
|
+
const features = Array.isArray((_c = (_b = (_a = widgetConfiguration === null || widgetConfiguration === void 0 ? void 0 : widgetConfiguration.configuration) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b['vortex.components']) === null || _c === void 0 ? void 0 : _c.value)
|
|
36
|
+
? (_f = (_e = (_d = widgetConfiguration === null || widgetConfiguration === void 0 ? void 0 : widgetConfiguration.configuration) === null || _d === void 0 ? void 0 : _d.props) === null || _e === void 0 ? void 0 : _e['vortex.components']) === null || _f === void 0 ? void 0 : _f.value
|
|
37
|
+
: [];
|
|
38
|
+
const shareOptions = Array.isArray((_j = (_h = (_g = widgetConfiguration === null || widgetConfiguration === void 0 ? void 0 : widgetConfiguration.configuration) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h['vortex.components.share.options']) === null || _j === void 0 ? void 0 : _j.value)
|
|
39
|
+
? (_m = (_l = (_k = widgetConfiguration === null || widgetConfiguration === void 0 ? void 0 : widgetConfiguration.configuration) === null || _k === void 0 ? void 0 : _k.props) === null || _l === void 0 ? void 0 : _l['vortex.components.share.options']) === null || _m === void 0 ? void 0 : _m.value
|
|
40
|
+
: [];
|
|
41
|
+
return {
|
|
42
|
+
shareableLinks: features.includes("vortex.components.emailinvitations"),
|
|
43
|
+
emailInvitations: features.includes("vortex.components.share"),
|
|
44
|
+
shareEnabled: features.includes("vortex.components.share"),
|
|
45
|
+
shareOptionsCopyLink: shareOptions.includes("copyLink"),
|
|
46
|
+
shareOptionsFacebookMessenger: shareOptions.includes("facebookMessenger"),
|
|
47
|
+
shareOptionsInstagramDms: shareOptions.includes("instagramDms"),
|
|
48
|
+
shareOptionsLinkedInMessaging: shareOptions.includes("linkedInMessaging"),
|
|
49
|
+
shareOptionsNativeShareSheet: shareOptions.includes("nativeShareSheet"),
|
|
50
|
+
shareOptionsQrCode: shareOptions.includes("qrCode"), // Only true if specifically included
|
|
51
|
+
shareOptionsSms: shareOptions.includes("sms"),
|
|
52
|
+
shareOptionsTwitterDms: shareOptions.includes("twitterDms"),
|
|
53
|
+
shareOptionsWhatsApp: shareOptions.includes("whatsApp"),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
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.VortexInvite = VortexInvite;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
const useVortexInvite_1 = require("./hooks/useVortexInvite");
|
|
10
|
+
const ShareButtons_1 = require("./components/ShareButtons");
|
|
11
|
+
function VortexInvite({ widgetId, environmentId, vortexApiHost, isLoading = false, jwt, onSuccess, onError, contentTokens, }) {
|
|
12
|
+
const { error, fetching, loading, email, setEmail, opacity, themeColors, themeStyles, has, inviteLoading, showSuccessMessage, handleInviteClick, handleShareLink, handleCopyLink, getShareableLink, formLayout, } = (0, useVortexInvite_1.useVortexInvite)({
|
|
13
|
+
widgetId,
|
|
14
|
+
environmentId,
|
|
15
|
+
vortexApiHost,
|
|
16
|
+
isLoading,
|
|
17
|
+
jwt,
|
|
18
|
+
onSuccess,
|
|
19
|
+
onError,
|
|
20
|
+
});
|
|
21
|
+
if (error === null || error === void 0 ? void 0 : error.message) {
|
|
22
|
+
return <react_native_1.Text data-testid="error">{error.message}</react_native_1.Text>;
|
|
23
|
+
}
|
|
24
|
+
if (fetching || loading) {
|
|
25
|
+
return <react_native_1.Animated.View style={[styles.skeleton, { opacity }]}/>;
|
|
26
|
+
}
|
|
27
|
+
// Theme styles are now provided by the hook
|
|
28
|
+
// If we have a grid layout with separate columns for email and share, we'll use that layout
|
|
29
|
+
if ((formLayout === null || formLayout === void 0 ? void 0 : formLayout.isGridLayout) && (formLayout === null || formLayout === void 0 ? void 0 : formLayout.hasSeparateColumns)) {
|
|
30
|
+
return (<react_native_1.View style={[styles.container, themeStyles.containerStyles]}>
|
|
31
|
+
<react_native_1.View style={styles.gridContainer}>
|
|
32
|
+
{/* Email invitation column */}
|
|
33
|
+
{(has === null || has === void 0 ? void 0 : has.emailInvitations) && (<react_native_1.View style={styles.gridItem}>
|
|
34
|
+
<react_native_1.Text style={[styles.introText, themeStyles.textStyles]}>Invite People</react_native_1.Text>
|
|
35
|
+
<react_native_1.TextInput style={[styles.input, themeStyles.inputStyles]} placeholder={formLayout.emailPlaceholder} placeholderTextColor={themeColors.containerForeground} value={email} onChangeText={setEmail} autoCapitalize="none"/>
|
|
36
|
+
<react_native_1.View style={styles.buttonContainer}>
|
|
37
|
+
<react_native_1.Pressable style={[styles.submitButton, themeStyles.primaryButton, inviteLoading && styles.disabledButton]} onPress={() => handleInviteClick(contentTokens)} disabled={inviteLoading}>
|
|
38
|
+
{inviteLoading ? (<react_native_1.ActivityIndicator size="small" color={themeColors.containerBackground}/>) : (<react_native_1.Text style={[styles.submitButtonText, themeStyles.primaryButtonText]}>
|
|
39
|
+
{formLayout.submitButtonLabel}
|
|
40
|
+
</react_native_1.Text>)}
|
|
41
|
+
</react_native_1.Pressable>
|
|
42
|
+
{showSuccessMessage && (<react_native_1.View style={styles.successMessageContainer}>
|
|
43
|
+
<react_native_1.Text style={styles.successMessage}>Success!</react_native_1.Text>
|
|
44
|
+
</react_native_1.View>)}
|
|
45
|
+
</react_native_1.View>
|
|
46
|
+
</react_native_1.View>)}
|
|
47
|
+
|
|
48
|
+
{/* Share buttons column */}
|
|
49
|
+
{(has === null || has === void 0 ? void 0 : has.shareableLinks) && (<react_native_1.View style={styles.gridItem}>
|
|
50
|
+
<react_native_1.View style={styles.shareButtonsContainer}>
|
|
51
|
+
<ShareButtons_1.ShareButtons has={has} themeColors={themeColors} themeStyles={themeStyles} handleShareLink={handleShareLink} handleCopyLink={handleCopyLink} shareableLink={getShareableLink()}/>
|
|
52
|
+
</react_native_1.View>
|
|
53
|
+
</react_native_1.View>)}
|
|
54
|
+
</react_native_1.View>
|
|
55
|
+
</react_native_1.View>);
|
|
56
|
+
}
|
|
57
|
+
// Default stacked layout
|
|
58
|
+
return (<react_native_1.View style={[styles.container, themeStyles.containerStyles]}>
|
|
59
|
+
{(has === null || has === void 0 ? void 0 : has.emailInvitations) && (<react_native_1.View style={styles.inviteContainer}>
|
|
60
|
+
<react_native_1.Text style={[styles.introText, themeStyles.textStyles]}>Invite People</react_native_1.Text>
|
|
61
|
+
<react_native_1.TextInput style={[styles.input, themeStyles.inputStyles]} placeholder={(formLayout === null || formLayout === void 0 ? void 0 : formLayout.emailPlaceholder) || 'Enter email'} placeholderTextColor={themeColors.containerForeground} value={email} onChangeText={setEmail} autoCapitalize="none"/>
|
|
62
|
+
<react_native_1.View style={styles.buttonContainer}>
|
|
63
|
+
<react_native_1.Pressable style={[styles.submitButton, themeStyles.primaryButton, inviteLoading && styles.disabledButton]} onPress={() => handleInviteClick(contentTokens)} disabled={inviteLoading}>
|
|
64
|
+
{inviteLoading ? (<react_native_1.ActivityIndicator size="small" color={themeColors.containerBackground}/>) : (<react_native_1.Text style={[styles.submitButtonText, themeStyles.primaryButtonText]}>
|
|
65
|
+
{(formLayout === null || formLayout === void 0 ? void 0 : formLayout.submitButtonLabel) || 'Invite'}
|
|
66
|
+
</react_native_1.Text>)}
|
|
67
|
+
</react_native_1.Pressable>
|
|
68
|
+
{showSuccessMessage && (<react_native_1.View style={styles.successMessageContainer}>
|
|
69
|
+
<react_native_1.Text style={styles.successMessage}>Success!</react_native_1.Text>
|
|
70
|
+
</react_native_1.View>)}
|
|
71
|
+
</react_native_1.View>
|
|
72
|
+
</react_native_1.View>)}
|
|
73
|
+
|
|
74
|
+
{(has === null || has === void 0 ? void 0 : has.shareableLinks) && (<react_native_1.View style={styles.shareContainer}>
|
|
75
|
+
{(has === null || has === void 0 ? void 0 : has.emailInvitations) && <react_native_1.Text style={[styles.divider, themeStyles.textStyles]}>OR</react_native_1.Text>}
|
|
76
|
+
|
|
77
|
+
<react_native_1.View style={styles.shareButtonsContainer}>
|
|
78
|
+
<ShareButtons_1.ShareButtons has={has} themeColors={themeColors} themeStyles={themeStyles} handleShareLink={handleShareLink} handleCopyLink={handleCopyLink} shareableLink={getShareableLink()}/>
|
|
79
|
+
</react_native_1.View>
|
|
80
|
+
</react_native_1.View>)}
|
|
81
|
+
</react_native_1.View>);
|
|
82
|
+
}
|
|
83
|
+
const styles = react_native_1.StyleSheet.create({
|
|
84
|
+
container: {
|
|
85
|
+
padding: 15,
|
|
86
|
+
display: 'flex',
|
|
87
|
+
flexDirection: 'column',
|
|
88
|
+
borderRadius: 8,
|
|
89
|
+
borderWidth: 1,
|
|
90
|
+
},
|
|
91
|
+
gridContainer: {
|
|
92
|
+
flexDirection: 'row',
|
|
93
|
+
flexWrap: 'wrap',
|
|
94
|
+
justifyContent: 'space-between',
|
|
95
|
+
},
|
|
96
|
+
gridItem: {
|
|
97
|
+
flex: 1,
|
|
98
|
+
padding: 8,
|
|
99
|
+
minWidth: 250, // Ensure items have minimum width for smaller screens
|
|
100
|
+
},
|
|
101
|
+
disabledButton: {
|
|
102
|
+
opacity: 0.7,
|
|
103
|
+
},
|
|
104
|
+
successMessageContainer: {
|
|
105
|
+
marginTop: 8,
|
|
106
|
+
padding: 8,
|
|
107
|
+
alignItems: 'center',
|
|
108
|
+
width: '100%',
|
|
109
|
+
},
|
|
110
|
+
successMessage: {
|
|
111
|
+
color: 'green',
|
|
112
|
+
fontWeight: 'bold',
|
|
113
|
+
fontSize: 16,
|
|
114
|
+
},
|
|
115
|
+
inviteContainer: {
|
|
116
|
+
display: 'flex',
|
|
117
|
+
flexDirection: 'column',
|
|
118
|
+
justifyContent: 'center',
|
|
119
|
+
alignItems: 'center',
|
|
120
|
+
marginTop: 8,
|
|
121
|
+
},
|
|
122
|
+
introText: {
|
|
123
|
+
marginBottom: 8,
|
|
124
|
+
fontSize: 24,
|
|
125
|
+
fontWeight: 'bold',
|
|
126
|
+
textAlign: 'center',
|
|
127
|
+
},
|
|
128
|
+
input: {
|
|
129
|
+
width: '100%',
|
|
130
|
+
borderWidth: 1,
|
|
131
|
+
padding: 10,
|
|
132
|
+
borderRadius: 5,
|
|
133
|
+
marginBottom: 8,
|
|
134
|
+
},
|
|
135
|
+
buttonContainer: {
|
|
136
|
+
marginTop: 16,
|
|
137
|
+
marginBottom: 8,
|
|
138
|
+
width: '100%',
|
|
139
|
+
},
|
|
140
|
+
submitButton: {
|
|
141
|
+
padding: 12,
|
|
142
|
+
borderRadius: 5,
|
|
143
|
+
alignItems: 'center',
|
|
144
|
+
borderWidth: 1,
|
|
145
|
+
},
|
|
146
|
+
submitButtonText: {
|
|
147
|
+
fontWeight: '500',
|
|
148
|
+
textTransform: 'none',
|
|
149
|
+
},
|
|
150
|
+
skeleton: {
|
|
151
|
+
width: '100%',
|
|
152
|
+
height: 50,
|
|
153
|
+
backgroundColor: 'lightgray',
|
|
154
|
+
borderRadius: 5,
|
|
155
|
+
},
|
|
156
|
+
shareContainer: {
|
|
157
|
+
marginTop: 16,
|
|
158
|
+
alignItems: 'center',
|
|
159
|
+
},
|
|
160
|
+
divider: {
|
|
161
|
+
marginVertical: 10,
|
|
162
|
+
fontSize: 16,
|
|
163
|
+
fontWeight: 'bold',
|
|
164
|
+
textAlign: 'center',
|
|
165
|
+
},
|
|
166
|
+
shareButtonsContainer: {
|
|
167
|
+
flexDirection: 'row',
|
|
168
|
+
flexWrap: 'wrap',
|
|
169
|
+
justifyContent: 'center',
|
|
170
|
+
},
|
|
171
|
+
// Share button styles moved to ShareButtons.tsx
|
|
172
|
+
});
|
package/package.json
CHANGED
|
@@ -2,23 +2,35 @@
|
|
|
2
2
|
"name": "@teamvortexsoftware/vortex-react-native",
|
|
3
3
|
"description": "",
|
|
4
4
|
"author": "@teamvortexsoftware",
|
|
5
|
-
"version": "0.0.
|
|
6
|
-
"
|
|
7
|
-
"
|
|
5
|
+
"version": "0.0.9",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"plugin",
|
|
9
|
+
"plugin.js"
|
|
10
|
+
],
|
|
11
|
+
"main": "./plugin/withVortexReactNative.js",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./plugin.js",
|
|
14
|
+
"./runtime": "./dist/index.js"
|
|
8
15
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
"expo": {
|
|
17
|
+
"plugins": [
|
|
18
|
+
"@teamvortexsoftware/vortex-react-native"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"types": "dist/types/index.d.ts",
|
|
22
|
+
"react-native": "dist/index.js",
|
|
12
23
|
"devDependencies": {
|
|
13
24
|
"@eslint/js": "^9.24.0",
|
|
25
|
+
"@expo/config-plugins": "^10.0.2",
|
|
14
26
|
"@types/react": "18.2.14",
|
|
15
27
|
"@types/react-native-vector-icons": "^6.4.18",
|
|
16
28
|
"eslint": "^9.24.0",
|
|
17
29
|
"eslint-plugin-react-native": "^4.1.0",
|
|
18
30
|
"typescript": "5.8.3",
|
|
19
31
|
"typescript-eslint": "^8.30.1",
|
|
20
|
-
"@teamvortexsoftware/
|
|
21
|
-
"@teamvortexsoftware/
|
|
32
|
+
"@teamvortexsoftware/typescript-config": "0.0.0",
|
|
33
|
+
"@teamvortexsoftware/eslint-config": "0.0.0"
|
|
22
34
|
},
|
|
23
35
|
"dependencies": {
|
|
24
36
|
"expo-standard-web-crypto": "^2.1.4",
|
|
@@ -35,7 +47,7 @@
|
|
|
35
47
|
"react-native-svg": "*"
|
|
36
48
|
},
|
|
37
49
|
"scripts": {
|
|
38
|
-
"build": "
|
|
50
|
+
"build": "tsc",
|
|
39
51
|
"prepublish": "pnpm run build",
|
|
40
52
|
"lint": "eslint src/",
|
|
41
53
|
"type-check": "tsc --noEmit"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const { withInfoPlist, withProjectBuildGradle, IOSConfig, withDangerousMod } = require('@expo/config-plugins');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const customFonts = [
|
|
6
|
+
"FontAwesome6_Brands.ttf",
|
|
7
|
+
"FontAwesome6_Regular.ttf",
|
|
8
|
+
"FontAwesome6_Solid.ttf",
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
// iOS integration
|
|
12
|
+
const withIosFonts = (config) => {
|
|
13
|
+
return withInfoPlist(config, (modConfig) => {
|
|
14
|
+
console.log('[withVortexReactNative] Adding custom fonts to iOS Info.plist');
|
|
15
|
+
|
|
16
|
+
const existingFonts = Array.isArray(modConfig.modResults.UIAppFonts)
|
|
17
|
+
? modConfig.modResults.UIAppFonts
|
|
18
|
+
: [];
|
|
19
|
+
|
|
20
|
+
modConfig.modResults.UIAppFonts = Array.from(new Set([...existingFonts, ...customFonts]));
|
|
21
|
+
|
|
22
|
+
return modConfig;
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Android integration
|
|
27
|
+
const withAndroidFonts = (config) => {
|
|
28
|
+
// Copy fonts to Android assets directory
|
|
29
|
+
return withDangerousMod(config, [
|
|
30
|
+
'android',
|
|
31
|
+
async (config) => {
|
|
32
|
+
console.log('[withVortexReactNative] Setting up fonts for Android');
|
|
33
|
+
|
|
34
|
+
const projectRoot = config.modRequest.projectRoot;
|
|
35
|
+
const fontsDirectory = path.resolve(projectRoot, 'node_modules/react-native-vector-icons/Fonts');
|
|
36
|
+
const assetsDirectory = path.resolve(projectRoot, 'android/app/src/main/assets/fonts');
|
|
37
|
+
|
|
38
|
+
// Ensure the assets directory exists
|
|
39
|
+
if (!fs.existsSync(assetsDirectory)) {
|
|
40
|
+
fs.mkdirSync(assetsDirectory, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Copy each font file to the assets directory
|
|
44
|
+
for (const font of customFonts) {
|
|
45
|
+
const sourcePath = path.resolve(fontsDirectory, font);
|
|
46
|
+
const destPath = path.resolve(assetsDirectory, font);
|
|
47
|
+
|
|
48
|
+
if (fs.existsSync(sourcePath)) {
|
|
49
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
50
|
+
console.log(`[withVortexReactNative] Copied ${font} to Android assets`);
|
|
51
|
+
} else {
|
|
52
|
+
console.warn(`[withVortexReactNative] Font file not found: ${sourcePath}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return config;
|
|
57
|
+
},
|
|
58
|
+
]);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Main plugin function
|
|
62
|
+
const withVortexReactNative = (config) => {
|
|
63
|
+
console.log('[withVortexReactNative] plugin running');
|
|
64
|
+
|
|
65
|
+
// Apply iOS configuration
|
|
66
|
+
config = withIosFonts(config);
|
|
67
|
+
|
|
68
|
+
// Apply Android configuration
|
|
69
|
+
config = withAndroidFonts(config);
|
|
70
|
+
|
|
71
|
+
return config;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
module.exports = withVortexReactNative;
|
package/plugin.js
ADDED
package/eslint.config.mjs
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { Pressable, StyleSheet, Text, View } from "react-native";
|
|
3
|
-
import Icon from "react-native-vector-icons/FontAwesome6";
|
|
4
|
-
import { ThemeColors } from "../utils/themeUtils";
|
|
5
|
-
import QRCode from "react-native-qrcode-svg";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* ShareButton component for rendering a single share option button
|
|
9
|
-
*/
|
|
10
|
-
interface ShareButtonProps {
|
|
11
|
-
iconName: string;
|
|
12
|
-
label: string;
|
|
13
|
-
onPress: () => void;
|
|
14
|
-
themeColors: ThemeColors;
|
|
15
|
-
themeStyles: any;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function ShareButton({
|
|
19
|
-
iconName,
|
|
20
|
-
label,
|
|
21
|
-
onPress,
|
|
22
|
-
themeColors,
|
|
23
|
-
themeStyles,
|
|
24
|
-
}: ShareButtonProps) {
|
|
25
|
-
return (
|
|
26
|
-
<View style={styles.shareButtonWrapper}>
|
|
27
|
-
<Pressable
|
|
28
|
-
style={[styles.shareButton, themeStyles.secondaryButton]}
|
|
29
|
-
onPress={onPress}
|
|
30
|
-
>
|
|
31
|
-
<View style={styles.buttonContentContainer}>
|
|
32
|
-
<Icon
|
|
33
|
-
name={iconName}
|
|
34
|
-
size={24}
|
|
35
|
-
color={themeColors.secondaryButtonForeground}
|
|
36
|
-
/>
|
|
37
|
-
<Text
|
|
38
|
-
style={[styles.shareButtonText, themeStyles.secondaryButtonText]}
|
|
39
|
-
>
|
|
40
|
-
{label}
|
|
41
|
-
</Text>
|
|
42
|
-
</View>
|
|
43
|
-
</Pressable>
|
|
44
|
-
</View>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* ShareButtons component for rendering all available share options
|
|
50
|
-
*/
|
|
51
|
-
export interface ShareButtonsProps {
|
|
52
|
-
has: any;
|
|
53
|
-
themeColors: ThemeColors;
|
|
54
|
-
themeStyles: any;
|
|
55
|
-
handleShareLink: () => void;
|
|
56
|
-
handleCopyLink: () => void;
|
|
57
|
-
shareableLink?: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function ShareButtons({
|
|
61
|
-
has,
|
|
62
|
-
themeColors,
|
|
63
|
-
themeStyles,
|
|
64
|
-
handleShareLink,
|
|
65
|
-
handleCopyLink,
|
|
66
|
-
shareableLink,
|
|
67
|
-
}: ShareButtonsProps) {
|
|
68
|
-
const [showQRCode, setShowQRCode] = useState(false);
|
|
69
|
-
// Define button configurations
|
|
70
|
-
const buttonConfigs = [
|
|
71
|
-
{
|
|
72
|
-
key: "shareOptionsNativeShareSheet",
|
|
73
|
-
iconName: "share",
|
|
74
|
-
label: "Share",
|
|
75
|
-
onPress: handleShareLink,
|
|
76
|
-
isAvailable: has.shareOptionsNativeShareSheet,
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
key: "shareOptionsCopyLink",
|
|
80
|
-
iconName: "copy",
|
|
81
|
-
label: "Copy Link",
|
|
82
|
-
onPress: handleCopyLink,
|
|
83
|
-
isAvailable: has.shareOptionsCopyLink,
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
key: "shareOptionsQRCode",
|
|
87
|
-
iconName: "qrcode",
|
|
88
|
-
label: "QR Code",
|
|
89
|
-
onPress: () => setShowQRCode(!showQRCode),
|
|
90
|
-
isAvailable: true,
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
key: "shareOptionsWhatsApp",
|
|
94
|
-
iconName: "whatsapp",
|
|
95
|
-
label: "WhatsApp",
|
|
96
|
-
onPress: () => {},
|
|
97
|
-
isAvailable: has.shareOptionsWhatsApp,
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
key: "shareOptionsSms",
|
|
101
|
-
iconName: "message",
|
|
102
|
-
label: "SMS",
|
|
103
|
-
onPress: () => {},
|
|
104
|
-
isAvailable: has.shareOptionsSms,
|
|
105
|
-
},
|
|
106
|
-
// Add more share options as needed
|
|
107
|
-
// Example:
|
|
108
|
-
// {
|
|
109
|
-
// key: 'shareOptionsFacebookMessenger',
|
|
110
|
-
// iconName: 'facebook-messenger',
|
|
111
|
-
// label: 'Messenger',
|
|
112
|
-
// onPress: () => {},
|
|
113
|
-
// isAvailable: has.shareOptionsFacebookMessenger,
|
|
114
|
-
// },
|
|
115
|
-
];
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<>
|
|
119
|
-
{showQRCode && shareableLink && (
|
|
120
|
-
<View style={styles.qrCodeContainer}>
|
|
121
|
-
<QRCode
|
|
122
|
-
value={shareableLink}
|
|
123
|
-
size={200}
|
|
124
|
-
color={themeColors.containerForeground}
|
|
125
|
-
backgroundColor={themeColors.containerBackground}
|
|
126
|
-
/>
|
|
127
|
-
</View>
|
|
128
|
-
)}
|
|
129
|
-
{buttonConfigs
|
|
130
|
-
.filter((config) => config.isAvailable)
|
|
131
|
-
.map((config) => (
|
|
132
|
-
<ShareButton
|
|
133
|
-
key={config.key}
|
|
134
|
-
iconName={config.iconName}
|
|
135
|
-
label={config.label}
|
|
136
|
-
onPress={config.onPress}
|
|
137
|
-
themeColors={themeColors}
|
|
138
|
-
themeStyles={themeStyles}
|
|
139
|
-
/>
|
|
140
|
-
))}
|
|
141
|
-
</>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const styles = StyleSheet.create({
|
|
146
|
-
shareButtonWrapper: {
|
|
147
|
-
width: "48%",
|
|
148
|
-
margin: 5,
|
|
149
|
-
},
|
|
150
|
-
shareButton: {
|
|
151
|
-
flexDirection: "row",
|
|
152
|
-
alignItems: "center",
|
|
153
|
-
padding: 10,
|
|
154
|
-
borderWidth: 1,
|
|
155
|
-
borderRadius: 5,
|
|
156
|
-
justifyContent: "center",
|
|
157
|
-
},
|
|
158
|
-
buttonContentContainer: {
|
|
159
|
-
flexDirection: "row",
|
|
160
|
-
alignItems: "center",
|
|
161
|
-
},
|
|
162
|
-
shareButtonText: {
|
|
163
|
-
marginLeft: 10,
|
|
164
|
-
},
|
|
165
|
-
qrCodeContainer: {
|
|
166
|
-
width: "100%",
|
|
167
|
-
alignItems: "center",
|
|
168
|
-
justifyContent: "center",
|
|
169
|
-
marginBottom: 20,
|
|
170
|
-
padding: 10,
|
|
171
|
-
},
|
|
172
|
-
});
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
import { ThemeColors } from "../utils/themeUtils";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Hook to generate dynamic styles based on theme colors
|
|
6
|
-
* @param themeColors The theme colors object
|
|
7
|
-
* @returns Object containing styled components based on the theme
|
|
8
|
-
*/
|
|
9
|
-
export function useThemeStyles(themeColors: ThemeColors) {
|
|
10
|
-
const themeStyles = useMemo(
|
|
11
|
-
() => ({
|
|
12
|
-
primaryButton: {
|
|
13
|
-
backgroundColor: themeColors.primaryButtonBackground,
|
|
14
|
-
borderColor: themeColors.primaryButtonBorder,
|
|
15
|
-
},
|
|
16
|
-
primaryButtonText: {
|
|
17
|
-
color: themeColors.primaryButtonForeground,
|
|
18
|
-
},
|
|
19
|
-
secondaryButton: {
|
|
20
|
-
backgroundColor: themeColors.secondaryButtonBackground,
|
|
21
|
-
borderColor: themeColors.secondaryButtonBorder,
|
|
22
|
-
},
|
|
23
|
-
secondaryButtonText: {
|
|
24
|
-
color: themeColors.secondaryButtonForeground,
|
|
25
|
-
},
|
|
26
|
-
containerStyles: {
|
|
27
|
-
backgroundColor: themeColors.containerBackground,
|
|
28
|
-
},
|
|
29
|
-
textStyles: {
|
|
30
|
-
color: themeColors.containerForeground,
|
|
31
|
-
},
|
|
32
|
-
inputStyles: {
|
|
33
|
-
borderColor: themeColors.containerBorder,
|
|
34
|
-
color: themeColors.containerForeground,
|
|
35
|
-
backgroundColor: themeColors.containerBackground,
|
|
36
|
-
},
|
|
37
|
-
}),
|
|
38
|
-
[themeColors],
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
return themeStyles;
|
|
42
|
-
}
|