@teamvortexsoftware/vortex-react-native 0.0.3 → 0.0.5
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 +42 -0
- package/eslint.config.mjs +4 -0
- package/package.json +27 -20
- package/src/components/ShareButtons.tsx +172 -0
- package/src/hooks/useThemeStyles.ts +42 -0
- package/src/hooks/useVortexInvite.ts +299 -0
- package/src/index.tsx +2 -0
- package/src/shared/api.ts +73 -0
- package/src/utils/themeUtils.ts +85 -0
- package/src/vortexInvite.tsx +193 -0
- package/tsconfig.json +9 -0
- package/dist/index.d.mts +0 -24
- package/dist/index.d.ts +0 -24
- package/dist/index.js +0 -177
- package/dist/index.mjs +0 -143
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @teamvortexsoftware/vortex-react-native
|
|
2
|
+
|
|
3
|
+
React Native components for Vortex applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @teamvortexsoftware/vortex-react-native
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install dependencies
|
|
15
|
+
pnpm install
|
|
16
|
+
|
|
17
|
+
# Build the package
|
|
18
|
+
pnpm run build
|
|
19
|
+
|
|
20
|
+
# Run type checking
|
|
21
|
+
pnpm run type-check
|
|
22
|
+
|
|
23
|
+
# Run linting
|
|
24
|
+
pnpm run lint
|
|
25
|
+
|
|
26
|
+
# Watch mode for development
|
|
27
|
+
pnpm run dev
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { VortexInvite } from '@teamvortexsoftware/vortex-react-native';
|
|
34
|
+
|
|
35
|
+
// Your component code here
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Requirements
|
|
39
|
+
|
|
40
|
+
- React 18.3.1 or higher
|
|
41
|
+
- React Native 0.74.5 or higher
|
|
42
|
+
- pnpm 10.8.1 or higher
|
package/package.json
CHANGED
|
@@ -2,36 +2,43 @@
|
|
|
2
2
|
"name": "@teamvortexsoftware/vortex-react-native",
|
|
3
3
|
"description": "",
|
|
4
4
|
"author": "@teamvortexsoftware",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.5",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "restricted"
|
|
8
8
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"exports": {
|
|
13
|
-
".": {
|
|
14
|
-
"import": "./dist/index.js",
|
|
15
|
-
"require": "./dist/index.js",
|
|
16
|
-
"types": "./dist/index.d.ts"
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"main": "./dist/index.js",
|
|
20
|
-
"types": "./dist/index.d.ts",
|
|
9
|
+
"main": "src/index.tsx",
|
|
10
|
+
"types": "src/index.tsx",
|
|
11
|
+
"react-native": "src/index.tsx",
|
|
21
12
|
"devDependencies": {
|
|
13
|
+
"@eslint/js": "^9.24.0",
|
|
22
14
|
"@types/react": "18.2.14",
|
|
15
|
+
"@types/react-native-vector-icons": "^6.4.18",
|
|
16
|
+
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
|
17
|
+
"@typescript-eslint/parser": "^7.3.1",
|
|
18
|
+
"eslint": "^9.24.0",
|
|
19
|
+
"eslint-plugin-react-native": "^4.1.0",
|
|
23
20
|
"tsup": "8.0.1",
|
|
24
|
-
"typescript": "5.
|
|
21
|
+
"typescript": "5.8.3",
|
|
22
|
+
"typescript-eslint": "^8.30.1",
|
|
23
|
+
"@teamvortexsoftware/eslint-config": "0.0.0",
|
|
25
24
|
"@teamvortexsoftware/typescript-config": "0.0.0"
|
|
26
25
|
},
|
|
27
26
|
"dependencies": {
|
|
28
|
-
"react": "18.
|
|
29
|
-
"react-native": "0.
|
|
27
|
+
"react": "18.3.1",
|
|
28
|
+
"react-native": "0.76.9",
|
|
29
|
+
"react-native-vector-icons": "^10.2.0",
|
|
30
|
+
"@teamvortexsoftware/vortex-core": "0.0.1"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": "*",
|
|
34
|
+
"react-native": "*",
|
|
35
|
+
"react-native-qrcode-svg": "*",
|
|
36
|
+
"react-native-svg": "*"
|
|
30
37
|
},
|
|
31
38
|
"scripts": {
|
|
32
|
-
"build": "
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
39
|
+
"build": "echo \"no build\"",
|
|
40
|
+
"prepublish": "pnpm run build",
|
|
41
|
+
"lint": "eslint src/",
|
|
42
|
+
"type-check": "tsc --noEmit"
|
|
36
43
|
}
|
|
37
44
|
}
|
|
@@ -0,0 +1,172 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { WidgetConfiguration } from "@teamvortexsoftware/vortex-core";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { Animated, Share, Clipboard } from "react-native";
|
|
4
|
+
import VortexClient from "../shared/api";
|
|
5
|
+
import { extractFeatureFlags, extractThemeColors } from "../utils/themeUtils";
|
|
6
|
+
import { useThemeStyles } from "./useThemeStyles";
|
|
7
|
+
|
|
8
|
+
export type VortexActionType = "invite" | "share" | string;
|
|
9
|
+
|
|
10
|
+
export interface VortexActionResult {
|
|
11
|
+
type: VortexActionType;
|
|
12
|
+
data: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface UseVortexInviteOptions {
|
|
16
|
+
widgetId: string;
|
|
17
|
+
environmentId: string;
|
|
18
|
+
vortexApiHost: string;
|
|
19
|
+
isLoading?: boolean;
|
|
20
|
+
jwt?: string;
|
|
21
|
+
onSuccess?: (result: VortexActionResult) => void;
|
|
22
|
+
onError?: (error: Error, type: VortexActionType) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useVortexInvite({
|
|
26
|
+
widgetId,
|
|
27
|
+
environmentId,
|
|
28
|
+
vortexApiHost,
|
|
29
|
+
isLoading = false,
|
|
30
|
+
jwt,
|
|
31
|
+
onSuccess,
|
|
32
|
+
onError,
|
|
33
|
+
}: UseVortexInviteOptions) {
|
|
34
|
+
const vortexClient = useMemo(
|
|
35
|
+
() => new VortexClient(vortexApiHost),
|
|
36
|
+
[vortexApiHost],
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const [widgetConfiguration, setWidgetConfiguration] = useState<
|
|
40
|
+
WidgetConfiguration | undefined
|
|
41
|
+
>();
|
|
42
|
+
const [error, setError] = useState<{ message: string } | null>(null);
|
|
43
|
+
const [fetching, setFetching] = useState(isLoading);
|
|
44
|
+
const [loading, setLoading] = useState(true);
|
|
45
|
+
const [email, setEmail] = useState("");
|
|
46
|
+
const opacity = new Animated.Value(0.3);
|
|
47
|
+
|
|
48
|
+
// Extract theme colors and feature flags using utility functions
|
|
49
|
+
const themeColors = useMemo(
|
|
50
|
+
() => extractThemeColors(widgetConfiguration),
|
|
51
|
+
[widgetConfiguration],
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Get theme styles based on theme colors
|
|
55
|
+
const themeStyles = useThemeStyles(themeColors);
|
|
56
|
+
|
|
57
|
+
const options = useMemo(() => {
|
|
58
|
+
return widgetConfiguration?.configuration?.props || {};
|
|
59
|
+
}, [widgetConfiguration]);
|
|
60
|
+
|
|
61
|
+
const has = useMemo(() => {
|
|
62
|
+
const flags = extractFeatureFlags(widgetConfiguration);
|
|
63
|
+
console.log("[Vortex] Invite has", flags);
|
|
64
|
+
return flags;
|
|
65
|
+
}, [widgetConfiguration]);
|
|
66
|
+
|
|
67
|
+
// Log the host only once when the hook mounts
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (vortexApiHost.indexOf("localhost") > -1) {
|
|
70
|
+
console.warn("[Vortex] Invite Using localhost as host");
|
|
71
|
+
}
|
|
72
|
+
}, [vortexApiHost]);
|
|
73
|
+
|
|
74
|
+
// Loading animation effect
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
const animation = Animated.loop(
|
|
77
|
+
Animated.sequence([
|
|
78
|
+
Animated.timing(opacity, {
|
|
79
|
+
toValue: 1,
|
|
80
|
+
duration: 1000,
|
|
81
|
+
useNativeDriver: false,
|
|
82
|
+
}),
|
|
83
|
+
Animated.timing(opacity, {
|
|
84
|
+
toValue: 0.3,
|
|
85
|
+
duration: 1000,
|
|
86
|
+
useNativeDriver: false,
|
|
87
|
+
}),
|
|
88
|
+
]),
|
|
89
|
+
);
|
|
90
|
+
animation.start();
|
|
91
|
+
|
|
92
|
+
setTimeout(() => {
|
|
93
|
+
setLoading(false);
|
|
94
|
+
animation.stop();
|
|
95
|
+
}, 2000);
|
|
96
|
+
}, []);
|
|
97
|
+
|
|
98
|
+
// Fetch widget configuration if needed
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
// Case: If `widgetConfiguration` is already set, do nothing
|
|
101
|
+
if (widgetConfiguration) {
|
|
102
|
+
console.log(
|
|
103
|
+
"[Vortex] Invite Already has widgetConfiguration, skipping fetch",
|
|
104
|
+
);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (!jwt) {
|
|
108
|
+
console.log("[Vortex] Invite JWT is required");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const fetchData = async () => {
|
|
113
|
+
console.log("[Vortex] Invite Fetching Data...");
|
|
114
|
+
setFetching(true);
|
|
115
|
+
setLoading(true);
|
|
116
|
+
setError(null);
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const result = await vortexClient.getWidgetConfiguration(
|
|
120
|
+
widgetId,
|
|
121
|
+
jwt,
|
|
122
|
+
environmentId,
|
|
123
|
+
);
|
|
124
|
+
if (result?.data?.widgetConfiguration) {
|
|
125
|
+
setWidgetConfiguration(result.data.widgetConfiguration);
|
|
126
|
+
console.log(
|
|
127
|
+
"[Vortex] Invite Successfully fetched widgetConfiguration",
|
|
128
|
+
JSON.stringify(result.data.widgetConfiguration),
|
|
129
|
+
);
|
|
130
|
+
} else {
|
|
131
|
+
const error = result?.error || "No configuration data found.";
|
|
132
|
+
console.error(`[Vortex] Invite ${error}`);
|
|
133
|
+
throw new Error(error);
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
if (err instanceof Error) {
|
|
137
|
+
const fetchError = err as any;
|
|
138
|
+
console.error("[Vortex] Invite Error Details:", {
|
|
139
|
+
message: fetchError.message,
|
|
140
|
+
status: fetchError.status || "unknown",
|
|
141
|
+
statusText: fetchError.statusText,
|
|
142
|
+
body: fetchError.body,
|
|
143
|
+
stack: fetchError.stack,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
console.error("[Vortex] Invite Error", err);
|
|
148
|
+
setError({
|
|
149
|
+
message: (err as Error).message || "Something went wrong!",
|
|
150
|
+
});
|
|
151
|
+
} finally {
|
|
152
|
+
setFetching(false);
|
|
153
|
+
setLoading(false);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
fetchData();
|
|
158
|
+
}, [widgetId, jwt, environmentId]);
|
|
159
|
+
|
|
160
|
+
const handleInviteClick = async () => {
|
|
161
|
+
try {
|
|
162
|
+
if (!widgetConfiguration?.id) {
|
|
163
|
+
console.log("[Vortex Invite] Widget configuration ID is required");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// const url = `${host}/api/v1/no-auth/components/widget-configuration/${widgetConfigurationId}/invite`; // TODO should we use options.widgetHost?.value ?
|
|
167
|
+
console.log("[Vortex] Invite Sending invitation", {
|
|
168
|
+
email,
|
|
169
|
+
widgetId,
|
|
170
|
+
environmentId,
|
|
171
|
+
});
|
|
172
|
+
if (!jwt) {
|
|
173
|
+
throw new Error("[Vortex Invite] JWT is required");
|
|
174
|
+
}
|
|
175
|
+
const body = await vortexClient.createInvite(
|
|
176
|
+
jwt,
|
|
177
|
+
widgetConfiguration?.id,
|
|
178
|
+
environmentId,
|
|
179
|
+
{
|
|
180
|
+
email: {
|
|
181
|
+
value: email,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
// const response = await fetch(url, {
|
|
186
|
+
// method: "POST",
|
|
187
|
+
// headers: {
|
|
188
|
+
// "Content-Type": "application/json",
|
|
189
|
+
// },
|
|
190
|
+
// body: JSON.stringify({ to: [{ email }] }),
|
|
191
|
+
// });
|
|
192
|
+
// if (!response.ok) {
|
|
193
|
+
// const body = await response.json();
|
|
194
|
+
// console.error("[Vortex] Invite Error", body);
|
|
195
|
+
// const error = body?.message || body?.error || "Something went wrong!";
|
|
196
|
+
// onError?.(new Error(error), "invite");
|
|
197
|
+
// return;
|
|
198
|
+
// }
|
|
199
|
+
// const body = await response.json();
|
|
200
|
+
console.log("[Vortex] Invite Response", body);
|
|
201
|
+
if (onSuccess) {
|
|
202
|
+
onSuccess({
|
|
203
|
+
type: "invite",
|
|
204
|
+
data: "Email invite sent",
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.error("[Vortex]", error);
|
|
209
|
+
if (onError) {
|
|
210
|
+
onError(
|
|
211
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
212
|
+
"invite",
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const getShareableLink = (): string | undefined => {
|
|
219
|
+
const result =
|
|
220
|
+
widgetConfiguration?.slug != null
|
|
221
|
+
? vortexClient.getShareableLinkFormatted(widgetConfiguration.slug)
|
|
222
|
+
: undefined;
|
|
223
|
+
return result;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const handleShareLink = async () => {
|
|
227
|
+
try {
|
|
228
|
+
const shareableLink = getShareableLink();
|
|
229
|
+
if (!shareableLink) {
|
|
230
|
+
throw new Error("No shareable link available");
|
|
231
|
+
}
|
|
232
|
+
await Share.share({
|
|
233
|
+
message: shareableLink,
|
|
234
|
+
title: "Share Invite Link",
|
|
235
|
+
});
|
|
236
|
+
console.log("[Vortex] Link Shared", "The invite link has been shared.");
|
|
237
|
+
if (onSuccess) {
|
|
238
|
+
onSuccess({
|
|
239
|
+
type: "share",
|
|
240
|
+
data: "Sharable link used",
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.error("[Vortex] Failed to share link:", error);
|
|
245
|
+
if (onError) {
|
|
246
|
+
onError(
|
|
247
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
248
|
+
"share",
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const handleCopyLink = async () => {
|
|
255
|
+
try {
|
|
256
|
+
const shareableLink = getShareableLink();
|
|
257
|
+
if (!shareableLink) {
|
|
258
|
+
throw new Error("No shareable link available");
|
|
259
|
+
}
|
|
260
|
+
await Clipboard.setString(shareableLink);
|
|
261
|
+
console.log(
|
|
262
|
+
"[Vortex] Link Copied to clipboard",
|
|
263
|
+
"The invite link has been copied.",
|
|
264
|
+
);
|
|
265
|
+
if (onSuccess) {
|
|
266
|
+
onSuccess({
|
|
267
|
+
type: "share",
|
|
268
|
+
data: "Sharable copied",
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
} catch (error) {
|
|
272
|
+
console.error("[Vortex] Failed to copy link:", error);
|
|
273
|
+
if (onError) {
|
|
274
|
+
onError(
|
|
275
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
276
|
+
"share",
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
widgetConfiguration,
|
|
284
|
+
error,
|
|
285
|
+
fetching,
|
|
286
|
+
loading,
|
|
287
|
+
email,
|
|
288
|
+
setEmail,
|
|
289
|
+
opacity,
|
|
290
|
+
themeColors,
|
|
291
|
+
themeStyles,
|
|
292
|
+
has,
|
|
293
|
+
options,
|
|
294
|
+
handleInviteClick,
|
|
295
|
+
handleShareLink,
|
|
296
|
+
handleCopyLink,
|
|
297
|
+
getShareableLink,
|
|
298
|
+
};
|
|
299
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
class VortexClient {
|
|
2
|
+
private baseUrl: string;
|
|
3
|
+
|
|
4
|
+
constructor(baseUrl: string) {
|
|
5
|
+
// trim ending /
|
|
6
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async getWidgetConfiguration(
|
|
10
|
+
widgetId: string,
|
|
11
|
+
jwt: string,
|
|
12
|
+
environmentId: string,
|
|
13
|
+
) {
|
|
14
|
+
const url = `${this.baseUrl}/api/v1/environment/${environmentId}/widgets/${widgetId}`;
|
|
15
|
+
console.log("[VortexClient] getWidgetConfiguration", { url });
|
|
16
|
+
|
|
17
|
+
const response = await fetch(url, {
|
|
18
|
+
headers: { Authorization: `Bearer ${jwt}` },
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
const body = await response.text();
|
|
23
|
+
console.error("[VortexClient] getWidgetConfiguration", { status: response.status, body });
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Error fetching widget configuration from ${url}: ${response.status}`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
console.log("[VortexClient] getWidgetConfiguration", { data });
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async createInvite(
|
|
35
|
+
jwt: string,
|
|
36
|
+
widgetConfigurationId: string,
|
|
37
|
+
environmentId: string,
|
|
38
|
+
payload: any,
|
|
39
|
+
) {
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const response = await fetch(
|
|
43
|
+
`${this.baseUrl}/api/v1/environment/${environmentId}/widget-configuration/${widgetConfigurationId}/invite`,
|
|
44
|
+
{
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: {
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
Authorization: `Bearer ${jwt}`,
|
|
49
|
+
},
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
data: {
|
|
52
|
+
payload,
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const body = await response.text();
|
|
59
|
+
console.error("[VortexClient] createInvite", { status: response.status, body });
|
|
60
|
+
throw new Error(`Error POSTing widget invite: ${response.status}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
console.log("[VortexClient] createInvite", data);
|
|
65
|
+
return data;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getShareableLinkFormatted(slug: string) {
|
|
69
|
+
return `${this.baseUrl}/api/v1/no-auth/components/share/${slug}`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export default VortexClient;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { WidgetConfiguration } from "@teamvortexsoftware/vortex-core";
|
|
2
|
+
|
|
3
|
+
export interface ThemeColors {
|
|
4
|
+
containerBackground: string;
|
|
5
|
+
containerForeground: string;
|
|
6
|
+
containerBorder: string;
|
|
7
|
+
primaryButtonBackground: string;
|
|
8
|
+
primaryButtonForeground: string;
|
|
9
|
+
primaryButtonBorder: string;
|
|
10
|
+
secondaryButtonBackground: string;
|
|
11
|
+
secondaryButtonForeground: string;
|
|
12
|
+
secondaryButtonBorder: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface FeatureFlags {
|
|
16
|
+
shareableLinks: boolean;
|
|
17
|
+
emailInvitations: boolean;
|
|
18
|
+
shareOptionsCopyLink: boolean;
|
|
19
|
+
shareOptionsSms: boolean;
|
|
20
|
+
shareOptionsFacebookMessenger: boolean;
|
|
21
|
+
shareOptionsInstagramDms: boolean;
|
|
22
|
+
shareOptionsLinkedInMessaging: boolean;
|
|
23
|
+
shareOptionsTwitterDms: boolean;
|
|
24
|
+
shareOptionsWhatsApp: boolean;
|
|
25
|
+
shareOptionsNativeShareSheet: boolean;
|
|
26
|
+
shareOptionsQrCode: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Extracts theme colors from widget configuration
|
|
31
|
+
*/
|
|
32
|
+
export function extractThemeColors(widgetConfiguration?: WidgetConfiguration): ThemeColors {
|
|
33
|
+
const options = widgetConfiguration?.configuration?.props;
|
|
34
|
+
const colors = options?.["vortex.theme.colors"]?.value || [];
|
|
35
|
+
const colorMap: Record<string, string> = {};
|
|
36
|
+
|
|
37
|
+
colors.forEach((color: any) => {
|
|
38
|
+
if (color.key && color.value) {
|
|
39
|
+
colorMap[color.key] = color.value;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
containerBackground: colorMap["--container-background"] || "#ffffff",
|
|
45
|
+
containerForeground: colorMap["--container-foreground-color"] || "#666666",
|
|
46
|
+
containerBorder: colorMap["--container-border-color"] || "#c4c4c4",
|
|
47
|
+
primaryButtonBackground: colorMap["--primary-button-background"] || "#197af3",
|
|
48
|
+
primaryButtonForeground: colorMap["--primary-button-foreground-color"] || "#ffffff",
|
|
49
|
+
primaryButtonBorder: colorMap["--primary-button-border-color"] || "#000000",
|
|
50
|
+
secondaryButtonBackground: colorMap["--secondary-button-background"] || "#dfdfdf",
|
|
51
|
+
secondaryButtonForeground: colorMap["--secondary-button-foreground-color"] || "#000000",
|
|
52
|
+
secondaryButtonBorder: colorMap["--secondary-button-border-color"] || "#c4c4c4",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Extracts feature flags from widget configuration
|
|
58
|
+
*/
|
|
59
|
+
export function extractFeatureFlags(widgetConfiguration?: WidgetConfiguration): FeatureFlags {
|
|
60
|
+
const features: string[] = Array.isArray(
|
|
61
|
+
widgetConfiguration?.configuration?.props?.["vortex.components"]?.value,
|
|
62
|
+
)
|
|
63
|
+
? widgetConfiguration?.configuration?.props?.["vortex.components"]?.value
|
|
64
|
+
: [];
|
|
65
|
+
|
|
66
|
+
const shareOptions: string[] = Array.isArray(
|
|
67
|
+
widgetConfiguration?.configuration?.props?.["vortex.components.share.options"]?.value,
|
|
68
|
+
)
|
|
69
|
+
? widgetConfiguration?.configuration?.props?.["vortex.components.share.options"]?.value
|
|
70
|
+
: [];
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
shareableLinks: features.includes("vortex.components.emailinvitations"),
|
|
74
|
+
emailInvitations: features.includes("vortex.components.share"),
|
|
75
|
+
shareOptionsCopyLink: shareOptions.includes("copyLink"),
|
|
76
|
+
shareOptionsFacebookMessenger: shareOptions.includes("facebookMessenger"),
|
|
77
|
+
shareOptionsInstagramDms: shareOptions.includes("instagramDms"),
|
|
78
|
+
shareOptionsLinkedInMessaging: shareOptions.includes("linkedInMessaging"),
|
|
79
|
+
shareOptionsNativeShareSheet: shareOptions.includes("nativeShareSheet"),
|
|
80
|
+
shareOptionsQrCode: shareOptions.includes("qrCode"),
|
|
81
|
+
shareOptionsSms: shareOptions.includes("sms"),
|
|
82
|
+
shareOptionsTwitterDms: shareOptions.includes("twitterDms"),
|
|
83
|
+
shareOptionsWhatsApp: shareOptions.includes("whatsApp"),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Animated,
|
|
4
|
+
Pressable,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
Text,
|
|
7
|
+
TextInput,
|
|
8
|
+
View,
|
|
9
|
+
} from "react-native";
|
|
10
|
+
import {
|
|
11
|
+
useVortexInvite,
|
|
12
|
+
VortexActionResult,
|
|
13
|
+
VortexActionType,
|
|
14
|
+
} from "./hooks/useVortexInvite";
|
|
15
|
+
import { ShareButtons } from "./components/ShareButtons";
|
|
16
|
+
|
|
17
|
+
export interface VortexInviteProps {
|
|
18
|
+
environmentId: string;
|
|
19
|
+
widgetId: string;
|
|
20
|
+
vortexApiHost: string;
|
|
21
|
+
isLoading: boolean;
|
|
22
|
+
jwt?: string;
|
|
23
|
+
onSuccess?: (result: VortexActionResult) => void;
|
|
24
|
+
onError?: (error: Error, type: VortexActionType) => void;
|
|
25
|
+
// host: string;
|
|
26
|
+
// widgetConfigurationId?: string;
|
|
27
|
+
// widgetConfiguration?: WidgetConfiguration;
|
|
28
|
+
// isLoading?: boolean;
|
|
29
|
+
// onSuccess?: (result: VortexActionResult) => void;
|
|
30
|
+
// onError?: (error: Error, type: VortexActionType) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function VortexInvite({
|
|
34
|
+
widgetId,
|
|
35
|
+
environmentId,
|
|
36
|
+
vortexApiHost,
|
|
37
|
+
isLoading = false,
|
|
38
|
+
jwt,
|
|
39
|
+
onSuccess,
|
|
40
|
+
onError,
|
|
41
|
+
}: VortexInviteProps) {
|
|
42
|
+
const {
|
|
43
|
+
error,
|
|
44
|
+
fetching,
|
|
45
|
+
loading,
|
|
46
|
+
email,
|
|
47
|
+
setEmail,
|
|
48
|
+
opacity,
|
|
49
|
+
themeColors,
|
|
50
|
+
themeStyles,
|
|
51
|
+
has,
|
|
52
|
+
handleInviteClick,
|
|
53
|
+
handleShareLink,
|
|
54
|
+
handleCopyLink,
|
|
55
|
+
getShareableLink,
|
|
56
|
+
} = useVortexInvite({
|
|
57
|
+
widgetId,
|
|
58
|
+
environmentId,
|
|
59
|
+
vortexApiHost,
|
|
60
|
+
isLoading,
|
|
61
|
+
jwt,
|
|
62
|
+
onSuccess,
|
|
63
|
+
onError,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (error?.message) {
|
|
67
|
+
return <Text data-testid="error">{error.message}</Text>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (fetching || loading) {
|
|
71
|
+
return <Animated.View style={[styles.skeleton, { opacity }]} />;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Theme styles are now provided by the hook
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<View style={[styles.container, themeStyles.containerStyles]}>
|
|
78
|
+
{has?.emailInvitations && (
|
|
79
|
+
<View style={styles.inviteContainer}>
|
|
80
|
+
<Text style={[styles.introText, themeStyles.textStyles]}>
|
|
81
|
+
Invite People
|
|
82
|
+
</Text>
|
|
83
|
+
<TextInput
|
|
84
|
+
style={[styles.input, themeStyles.inputStyles]}
|
|
85
|
+
placeholder="Enter email"
|
|
86
|
+
placeholderTextColor={themeColors.containerForeground}
|
|
87
|
+
value={email}
|
|
88
|
+
onChangeText={setEmail}
|
|
89
|
+
autoCapitalize="none"
|
|
90
|
+
/>
|
|
91
|
+
<View style={styles.buttonContainer}>
|
|
92
|
+
<Pressable
|
|
93
|
+
style={[styles.submitButton, themeStyles.primaryButton]}
|
|
94
|
+
onPress={handleInviteClick}
|
|
95
|
+
>
|
|
96
|
+
<Text
|
|
97
|
+
style={[styles.submitButtonText, themeStyles.primaryButtonText]}
|
|
98
|
+
>
|
|
99
|
+
Invite
|
|
100
|
+
</Text>
|
|
101
|
+
</Pressable>
|
|
102
|
+
</View>
|
|
103
|
+
</View>
|
|
104
|
+
)}
|
|
105
|
+
|
|
106
|
+
{has?.shareableLinks && (
|
|
107
|
+
<View style={styles.shareContainer}>
|
|
108
|
+
{has?.emailInvitations && (
|
|
109
|
+
<Text style={[styles.divider, themeStyles.textStyles]}>OR</Text>
|
|
110
|
+
)}
|
|
111
|
+
|
|
112
|
+
<View style={styles.shareButtonsContainer}>
|
|
113
|
+
<ShareButtons
|
|
114
|
+
has={has}
|
|
115
|
+
themeColors={themeColors}
|
|
116
|
+
themeStyles={themeStyles}
|
|
117
|
+
handleShareLink={handleShareLink}
|
|
118
|
+
handleCopyLink={handleCopyLink}
|
|
119
|
+
shareableLink={getShareableLink()}
|
|
120
|
+
/>
|
|
121
|
+
</View>
|
|
122
|
+
</View>
|
|
123
|
+
)}
|
|
124
|
+
</View>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const styles = StyleSheet.create({
|
|
129
|
+
container: {
|
|
130
|
+
padding: 15,
|
|
131
|
+
display: "flex",
|
|
132
|
+
flexDirection: "column",
|
|
133
|
+
borderRadius: 8,
|
|
134
|
+
borderWidth: 1,
|
|
135
|
+
},
|
|
136
|
+
inviteContainer: {
|
|
137
|
+
display: "flex",
|
|
138
|
+
flexDirection: "column",
|
|
139
|
+
justifyContent: "center",
|
|
140
|
+
alignItems: "center",
|
|
141
|
+
marginTop: 8,
|
|
142
|
+
},
|
|
143
|
+
introText: {
|
|
144
|
+
marginBottom: 8,
|
|
145
|
+
fontSize: 24,
|
|
146
|
+
fontWeight: "bold",
|
|
147
|
+
textAlign: "center",
|
|
148
|
+
},
|
|
149
|
+
input: {
|
|
150
|
+
width: "100%",
|
|
151
|
+
borderWidth: 1,
|
|
152
|
+
padding: 10,
|
|
153
|
+
borderRadius: 5,
|
|
154
|
+
marginBottom: 8,
|
|
155
|
+
},
|
|
156
|
+
buttonContainer: {
|
|
157
|
+
marginTop: 16,
|
|
158
|
+
marginBottom: 8,
|
|
159
|
+
width: "100%",
|
|
160
|
+
},
|
|
161
|
+
submitButton: {
|
|
162
|
+
padding: 12,
|
|
163
|
+
borderRadius: 5,
|
|
164
|
+
alignItems: "center",
|
|
165
|
+
borderWidth: 1,
|
|
166
|
+
},
|
|
167
|
+
submitButtonText: {
|
|
168
|
+
fontWeight: "500",
|
|
169
|
+
textTransform: "none",
|
|
170
|
+
},
|
|
171
|
+
skeleton: {
|
|
172
|
+
width: "100%",
|
|
173
|
+
height: 50,
|
|
174
|
+
backgroundColor: "#e0e0e0",
|
|
175
|
+
borderRadius: 5,
|
|
176
|
+
},
|
|
177
|
+
shareContainer: {
|
|
178
|
+
marginTop: 16,
|
|
179
|
+
alignItems: "center",
|
|
180
|
+
},
|
|
181
|
+
divider: {
|
|
182
|
+
marginVertical: 10,
|
|
183
|
+
fontSize: 16,
|
|
184
|
+
fontWeight: "bold",
|
|
185
|
+
textAlign: "center",
|
|
186
|
+
},
|
|
187
|
+
shareButtonsContainer: {
|
|
188
|
+
flexDirection: "row",
|
|
189
|
+
flexWrap: "wrap",
|
|
190
|
+
justifyContent: "center",
|
|
191
|
+
},
|
|
192
|
+
// Share button styles moved to ShareButtons.tsx
|
|
193
|
+
});
|
package/tsconfig.json
ADDED
package/dist/index.d.mts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
interface ButtonProps {
|
|
4
|
-
text: string;
|
|
5
|
-
onClick?: (e: any) => void;
|
|
6
|
-
}
|
|
7
|
-
declare function Button({ text, onClick }: ButtonProps): React.JSX.Element;
|
|
8
|
-
|
|
9
|
-
interface WidgetConfiguration {
|
|
10
|
-
configuration?: {
|
|
11
|
-
props?: any;
|
|
12
|
-
styles?: any;
|
|
13
|
-
};
|
|
14
|
-
slug?: string;
|
|
15
|
-
[key: string]: any;
|
|
16
|
-
}
|
|
17
|
-
interface VortexInviteProps {
|
|
18
|
-
widgetConfigurationId?: string;
|
|
19
|
-
widgetConfiguration?: WidgetConfiguration;
|
|
20
|
-
isLoading?: boolean;
|
|
21
|
-
}
|
|
22
|
-
declare function VortexInvite({ widgetConfigurationId, widgetConfiguration, isLoading, }: VortexInviteProps): React.JSX.Element;
|
|
23
|
-
|
|
24
|
-
export { Button, type ButtonProps, VortexInvite, type VortexInviteProps };
|
package/dist/index.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
interface ButtonProps {
|
|
4
|
-
text: string;
|
|
5
|
-
onClick?: (e: any) => void;
|
|
6
|
-
}
|
|
7
|
-
declare function Button({ text, onClick }: ButtonProps): React.JSX.Element;
|
|
8
|
-
|
|
9
|
-
interface WidgetConfiguration {
|
|
10
|
-
configuration?: {
|
|
11
|
-
props?: any;
|
|
12
|
-
styles?: any;
|
|
13
|
-
};
|
|
14
|
-
slug?: string;
|
|
15
|
-
[key: string]: any;
|
|
16
|
-
}
|
|
17
|
-
interface VortexInviteProps {
|
|
18
|
-
widgetConfigurationId?: string;
|
|
19
|
-
widgetConfiguration?: WidgetConfiguration;
|
|
20
|
-
isLoading?: boolean;
|
|
21
|
-
}
|
|
22
|
-
declare function VortexInvite({ widgetConfigurationId, widgetConfiguration, isLoading, }: VortexInviteProps): React.JSX.Element;
|
|
23
|
-
|
|
24
|
-
export { Button, type ButtonProps, VortexInvite, type VortexInviteProps };
|
package/dist/index.js
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __export = (target, all) => {
|
|
10
|
-
for (var name in all)
|
|
11
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
-
};
|
|
13
|
-
var __copyProps = (to, from, except, desc) => {
|
|
14
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
-
for (let key of __getOwnPropNames(from))
|
|
16
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
-
}
|
|
19
|
-
return to;
|
|
20
|
-
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
-
mod
|
|
28
|
-
));
|
|
29
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
-
|
|
31
|
-
// src/index.tsx
|
|
32
|
-
var src_exports = {};
|
|
33
|
-
__export(src_exports, {
|
|
34
|
-
Button: () => Button,
|
|
35
|
-
VortexInvite: () => VortexInvite
|
|
36
|
-
});
|
|
37
|
-
module.exports = __toCommonJS(src_exports);
|
|
38
|
-
|
|
39
|
-
// src/button.tsx
|
|
40
|
-
var import_react = __toESM(require("react"));
|
|
41
|
-
var import_react_native = require("react-native");
|
|
42
|
-
function Button({ text, onClick }) {
|
|
43
|
-
const [count, setCount] = (0, import_react.useState)(0);
|
|
44
|
-
(0, import_react.useEffect)(() => {
|
|
45
|
-
console.log("Current count:", count);
|
|
46
|
-
}, [count]);
|
|
47
|
-
const handlePress = (e) => {
|
|
48
|
-
console.log("handlePress called");
|
|
49
|
-
setCount((prevCount) => prevCount + 1);
|
|
50
|
-
if (onClick) {
|
|
51
|
-
onClick(e);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
return /* @__PURE__ */ import_react.default.createElement(import_react_native.Text, { style: styles.text }, text);
|
|
55
|
-
}
|
|
56
|
-
var styles = import_react_native.StyleSheet.create({
|
|
57
|
-
button: {
|
|
58
|
-
maxWidth: 200,
|
|
59
|
-
textAlign: "center",
|
|
60
|
-
borderRadius: 10,
|
|
61
|
-
paddingTop: 14,
|
|
62
|
-
paddingBottom: 14,
|
|
63
|
-
paddingLeft: 30,
|
|
64
|
-
paddingRight: 30,
|
|
65
|
-
fontSize: 15,
|
|
66
|
-
backgroundColor: "#2f80ed"
|
|
67
|
-
},
|
|
68
|
-
text: {
|
|
69
|
-
color: "white"
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// src/vortexInvite.tsx
|
|
74
|
-
var import_react2 = __toESM(require("react"));
|
|
75
|
-
var import_react_native2 = require("react-native");
|
|
76
|
-
function VortexInvite({
|
|
77
|
-
widgetConfigurationId,
|
|
78
|
-
widgetConfiguration,
|
|
79
|
-
isLoading = false
|
|
80
|
-
}) {
|
|
81
|
-
return /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement("pre", null, "Chupacabra"));
|
|
82
|
-
}
|
|
83
|
-
var styles2 = import_react_native2.StyleSheet.create({
|
|
84
|
-
container: {
|
|
85
|
-
padding: 15,
|
|
86
|
-
display: "flex",
|
|
87
|
-
flexDirection: "column"
|
|
88
|
-
},
|
|
89
|
-
inviteContainer: {
|
|
90
|
-
display: "flex",
|
|
91
|
-
flexDirection: "column",
|
|
92
|
-
justifyContent: "center",
|
|
93
|
-
alignItems: "center",
|
|
94
|
-
marginTop: 8
|
|
95
|
-
},
|
|
96
|
-
introText: {
|
|
97
|
-
marginBottom: 8,
|
|
98
|
-
fontSize: 24,
|
|
99
|
-
fontWeight: "bold",
|
|
100
|
-
textAlign: "center"
|
|
101
|
-
},
|
|
102
|
-
input: {
|
|
103
|
-
width: "100%",
|
|
104
|
-
borderWidth: 1,
|
|
105
|
-
borderColor: "#ccc",
|
|
106
|
-
padding: 10,
|
|
107
|
-
borderRadius: 5,
|
|
108
|
-
marginBottom: 8
|
|
109
|
-
},
|
|
110
|
-
buttonContainer: {
|
|
111
|
-
marginTop: 16,
|
|
112
|
-
marginBottom: 8,
|
|
113
|
-
width: "100%"
|
|
114
|
-
},
|
|
115
|
-
submitButton: {
|
|
116
|
-
// backgroundColor: "#007bff",
|
|
117
|
-
padding: 12,
|
|
118
|
-
borderRadius: 5,
|
|
119
|
-
alignItems: "center",
|
|
120
|
-
shadowColor: "rgba(0, 0, 0, 0.2)",
|
|
121
|
-
shadowOffset: { width: 0, height: 2 },
|
|
122
|
-
shadowOpacity: 0.5,
|
|
123
|
-
shadowRadius: 2
|
|
124
|
-
},
|
|
125
|
-
submitButtonText: {
|
|
126
|
-
color: "white",
|
|
127
|
-
fontWeight: "500",
|
|
128
|
-
textTransform: "none"
|
|
129
|
-
},
|
|
130
|
-
skeleton: {
|
|
131
|
-
width: "100%",
|
|
132
|
-
height: 50,
|
|
133
|
-
backgroundColor: "#e0e0e0",
|
|
134
|
-
borderRadius: 5
|
|
135
|
-
},
|
|
136
|
-
shareContainer: {
|
|
137
|
-
marginTop: 16,
|
|
138
|
-
alignItems: "center"
|
|
139
|
-
},
|
|
140
|
-
divider: {
|
|
141
|
-
marginVertical: 10,
|
|
142
|
-
fontSize: 16,
|
|
143
|
-
fontWeight: "bold",
|
|
144
|
-
textAlign: "center"
|
|
145
|
-
},
|
|
146
|
-
shareButtonsContainer: {
|
|
147
|
-
flexDirection: "row",
|
|
148
|
-
flexWrap: "wrap",
|
|
149
|
-
justifyContent: "center"
|
|
150
|
-
},
|
|
151
|
-
shareButtonWrapper: {
|
|
152
|
-
width: "48%",
|
|
153
|
-
margin: 5
|
|
154
|
-
},
|
|
155
|
-
centeredShareButton: {
|
|
156
|
-
width: "100%",
|
|
157
|
-
alignItems: "center"
|
|
158
|
-
},
|
|
159
|
-
shareButton: {
|
|
160
|
-
flexDirection: "row",
|
|
161
|
-
alignItems: "center",
|
|
162
|
-
padding: 10,
|
|
163
|
-
borderWidth: 1,
|
|
164
|
-
borderColor: "#007bff",
|
|
165
|
-
borderRadius: 5,
|
|
166
|
-
justifyContent: "center"
|
|
167
|
-
},
|
|
168
|
-
shareButtonText: {
|
|
169
|
-
paddingLeft: 10,
|
|
170
|
-
color: "#007bff"
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
174
|
-
0 && (module.exports = {
|
|
175
|
-
Button,
|
|
176
|
-
VortexInvite
|
|
177
|
-
});
|
package/dist/index.mjs
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
// src/button.tsx
|
|
4
|
-
import React, { useEffect, useState } from "react";
|
|
5
|
-
import { StyleSheet, Text } from "react-native";
|
|
6
|
-
function Button({ text, onClick }) {
|
|
7
|
-
const [count, setCount] = useState(0);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
console.log("Current count:", count);
|
|
10
|
-
}, [count]);
|
|
11
|
-
const handlePress = (e) => {
|
|
12
|
-
console.log("handlePress called");
|
|
13
|
-
setCount((prevCount) => prevCount + 1);
|
|
14
|
-
if (onClick) {
|
|
15
|
-
onClick(e);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
return /* @__PURE__ */ React.createElement(Text, { style: styles.text }, text);
|
|
19
|
-
}
|
|
20
|
-
var styles = StyleSheet.create({
|
|
21
|
-
button: {
|
|
22
|
-
maxWidth: 200,
|
|
23
|
-
textAlign: "center",
|
|
24
|
-
borderRadius: 10,
|
|
25
|
-
paddingTop: 14,
|
|
26
|
-
paddingBottom: 14,
|
|
27
|
-
paddingLeft: 30,
|
|
28
|
-
paddingRight: 30,
|
|
29
|
-
fontSize: 15,
|
|
30
|
-
backgroundColor: "#2f80ed"
|
|
31
|
-
},
|
|
32
|
-
text: {
|
|
33
|
-
color: "white"
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// src/vortexInvite.tsx
|
|
38
|
-
import React2 from "react";
|
|
39
|
-
import {
|
|
40
|
-
View,
|
|
41
|
-
StyleSheet as StyleSheet2
|
|
42
|
-
} from "react-native";
|
|
43
|
-
function VortexInvite({
|
|
44
|
-
widgetConfigurationId,
|
|
45
|
-
widgetConfiguration,
|
|
46
|
-
isLoading = false
|
|
47
|
-
}) {
|
|
48
|
-
return /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement("pre", null, "Chupacabra"));
|
|
49
|
-
}
|
|
50
|
-
var styles2 = StyleSheet2.create({
|
|
51
|
-
container: {
|
|
52
|
-
padding: 15,
|
|
53
|
-
display: "flex",
|
|
54
|
-
flexDirection: "column"
|
|
55
|
-
},
|
|
56
|
-
inviteContainer: {
|
|
57
|
-
display: "flex",
|
|
58
|
-
flexDirection: "column",
|
|
59
|
-
justifyContent: "center",
|
|
60
|
-
alignItems: "center",
|
|
61
|
-
marginTop: 8
|
|
62
|
-
},
|
|
63
|
-
introText: {
|
|
64
|
-
marginBottom: 8,
|
|
65
|
-
fontSize: 24,
|
|
66
|
-
fontWeight: "bold",
|
|
67
|
-
textAlign: "center"
|
|
68
|
-
},
|
|
69
|
-
input: {
|
|
70
|
-
width: "100%",
|
|
71
|
-
borderWidth: 1,
|
|
72
|
-
borderColor: "#ccc",
|
|
73
|
-
padding: 10,
|
|
74
|
-
borderRadius: 5,
|
|
75
|
-
marginBottom: 8
|
|
76
|
-
},
|
|
77
|
-
buttonContainer: {
|
|
78
|
-
marginTop: 16,
|
|
79
|
-
marginBottom: 8,
|
|
80
|
-
width: "100%"
|
|
81
|
-
},
|
|
82
|
-
submitButton: {
|
|
83
|
-
// backgroundColor: "#007bff",
|
|
84
|
-
padding: 12,
|
|
85
|
-
borderRadius: 5,
|
|
86
|
-
alignItems: "center",
|
|
87
|
-
shadowColor: "rgba(0, 0, 0, 0.2)",
|
|
88
|
-
shadowOffset: { width: 0, height: 2 },
|
|
89
|
-
shadowOpacity: 0.5,
|
|
90
|
-
shadowRadius: 2
|
|
91
|
-
},
|
|
92
|
-
submitButtonText: {
|
|
93
|
-
color: "white",
|
|
94
|
-
fontWeight: "500",
|
|
95
|
-
textTransform: "none"
|
|
96
|
-
},
|
|
97
|
-
skeleton: {
|
|
98
|
-
width: "100%",
|
|
99
|
-
height: 50,
|
|
100
|
-
backgroundColor: "#e0e0e0",
|
|
101
|
-
borderRadius: 5
|
|
102
|
-
},
|
|
103
|
-
shareContainer: {
|
|
104
|
-
marginTop: 16,
|
|
105
|
-
alignItems: "center"
|
|
106
|
-
},
|
|
107
|
-
divider: {
|
|
108
|
-
marginVertical: 10,
|
|
109
|
-
fontSize: 16,
|
|
110
|
-
fontWeight: "bold",
|
|
111
|
-
textAlign: "center"
|
|
112
|
-
},
|
|
113
|
-
shareButtonsContainer: {
|
|
114
|
-
flexDirection: "row",
|
|
115
|
-
flexWrap: "wrap",
|
|
116
|
-
justifyContent: "center"
|
|
117
|
-
},
|
|
118
|
-
shareButtonWrapper: {
|
|
119
|
-
width: "48%",
|
|
120
|
-
margin: 5
|
|
121
|
-
},
|
|
122
|
-
centeredShareButton: {
|
|
123
|
-
width: "100%",
|
|
124
|
-
alignItems: "center"
|
|
125
|
-
},
|
|
126
|
-
shareButton: {
|
|
127
|
-
flexDirection: "row",
|
|
128
|
-
alignItems: "center",
|
|
129
|
-
padding: 10,
|
|
130
|
-
borderWidth: 1,
|
|
131
|
-
borderColor: "#007bff",
|
|
132
|
-
borderRadius: 5,
|
|
133
|
-
justifyContent: "center"
|
|
134
|
-
},
|
|
135
|
-
shareButtonText: {
|
|
136
|
-
paddingLeft: 10,
|
|
137
|
-
color: "#007bff"
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
export {
|
|
141
|
-
Button,
|
|
142
|
-
VortexInvite
|
|
143
|
-
};
|