@teamvortexsoftware/vortex-react-native 0.0.13 → 1.0.1
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/LICENSE +201 -0
- package/README.md +1227 -11
- package/dist/InviteFormCore-D4HkMMo0.d.mts +721 -0
- package/dist/InviteFormCore-D9oUCbu7.d.ts +721 -0
- package/dist/VortexClient.js +192 -0
- package/dist/VortexClient.js.map +1 -0
- package/dist/VortexDeferredLinks.js +127 -0
- package/dist/VortexDeferredLinks.js.map +1 -0
- package/dist/clientInfo.js +45 -0
- package/dist/clientInfo.js.map +1 -0
- package/dist/components/ContactsPickerModal.js +182 -0
- package/dist/components/ContactsPickerModal.js.map +1 -0
- package/dist/components/InviteFormCore.js +2141 -0
- package/dist/components/InviteFormCore.js.map +1 -0
- package/dist/components/InviteFormMobile.js +463 -0
- package/dist/components/InviteFormMobile.js.map +1 -0
- package/dist/components/InviteFormWeb.js +295 -0
- package/dist/components/InviteFormWeb.js.map +1 -0
- package/dist/components/PlacedItemToolbar.js +147 -0
- package/dist/components/PlacedItemToolbar.js.map +1 -0
- package/dist/components/ShareButtons.js +1 -0
- package/dist/components/ShareButtons.js.map +1 -0
- package/dist/components/VrtxContactsImport.js +234 -0
- package/dist/components/VrtxContactsImport.js.map +1 -0
- package/dist/components/VrtxEmailInvitations.js +341 -0
- package/dist/components/VrtxEmailInvitations.js.map +1 -0
- package/dist/components/VrtxFindFriends.js +400 -0
- package/dist/components/VrtxFindFriends.js.map +1 -0
- package/dist/components/VrtxHeading.js +58 -0
- package/dist/components/VrtxHeading.js.map +1 -0
- package/dist/components/VrtxIncomingInvitations.js +657 -0
- package/dist/components/VrtxIncomingInvitations.js.map +1 -0
- package/dist/components/VrtxInvitationSuggestions.js +506 -0
- package/dist/components/VrtxInvitationSuggestions.js.map +1 -0
- package/dist/components/VrtxInviteContacts.js +512 -0
- package/dist/components/VrtxInviteContacts.js.map +1 -0
- package/dist/components/VrtxOutgoingInvitations.js +572 -0
- package/dist/components/VrtxOutgoingInvitations.js.map +1 -0
- package/dist/components/VrtxSearchBox.js +487 -0
- package/dist/components/VrtxSearchBox.js.map +1 -0
- package/dist/components/VrtxSelect.js +27 -0
- package/dist/components/VrtxSelect.js.map +1 -0
- package/dist/components/VrtxShareOptions.js +435 -0
- package/dist/components/VrtxShareOptions.js.map +1 -0
- package/dist/components/VrtxSubmit.js +132 -0
- package/dist/components/VrtxSubmit.js.map +1 -0
- package/dist/components/VrtxText.js +146 -0
- package/dist/components/VrtxText.js.map +1 -0
- package/dist/constants/mockData.d.mts +7 -0
- package/dist/constants/mockData.d.ts +7 -0
- package/dist/constants/mockData.js +48 -0
- package/dist/constants/mockData.js.map +1 -0
- package/dist/constants/mockData.mjs +22 -0
- package/dist/constants/mockData.mjs.map +1 -0
- package/dist/context/VortexModulesContext.js +135 -0
- package/dist/context/VortexModulesContext.js.map +1 -0
- package/dist/hooks/useInvitationFormLogic.d.mts +2 -0
- package/dist/hooks/useInvitationFormLogic.d.ts +2 -0
- package/dist/hooks/useInvitationFormLogic.js +300 -0
- package/dist/hooks/useInvitationFormLogic.js.map +1 -0
- package/dist/hooks/useInvitationFormLogic.mjs +276 -0
- package/dist/hooks/useInvitationFormLogic.mjs.map +1 -0
- package/dist/hooks/usePrefetchWidgetConfiguration.js +117 -0
- package/dist/hooks/usePrefetchWidgetConfiguration.js.map +1 -0
- package/dist/hooks/useThemeStyles.js +2 -0
- package/dist/hooks/useThemeStyles.js.map +1 -0
- package/dist/hooks/useVortexInvite.js +467 -56
- package/dist/hooks/useVortexInvite.js.map +1 -0
- package/dist/index-web.d.mts +93 -0
- package/dist/index-web.d.ts +93 -0
- package/dist/index-web.js +7397 -0
- package/dist/index-web.js.map +1 -0
- package/dist/index-web.mjs +7445 -0
- package/dist/index-web.mjs.map +1 -0
- package/dist/index.d.mts +656 -0
- package/dist/index.d.ts +656 -0
- package/dist/index.js +10205 -4
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +10244 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types/VortexClient.d.ts +106 -0
- package/dist/types/VortexClient.d.ts.map +1 -0
- package/dist/types/VortexDeferredLinks.d.ts +73 -0
- package/dist/types/VortexDeferredLinks.d.ts.map +1 -0
- package/dist/types/clientInfo.d.ts +5 -0
- package/dist/types/clientInfo.d.ts.map +1 -0
- package/dist/types/components/ContactsPickerModal.d.ts +18 -0
- package/dist/types/components/ContactsPickerModal.d.ts.map +1 -0
- package/dist/types/components/InviteFormCore.d.ts +166 -0
- package/dist/types/components/InviteFormCore.d.ts.map +1 -0
- package/dist/types/components/InviteFormMobile.d.ts +42 -0
- package/dist/types/components/InviteFormMobile.d.ts.map +1 -0
- package/dist/types/components/InviteFormWeb.d.ts +87 -0
- package/dist/types/components/InviteFormWeb.d.ts.map +1 -0
- package/dist/types/components/PlacedItemToolbar.d.ts +16 -0
- package/dist/types/components/PlacedItemToolbar.d.ts.map +1 -0
- package/dist/types/components/VrtxContactsImport.d.ts +14 -0
- package/dist/types/components/VrtxContactsImport.d.ts.map +1 -0
- package/dist/types/components/VrtxEmailInvitations.d.ts +31 -0
- package/dist/types/components/VrtxEmailInvitations.d.ts.map +1 -0
- package/dist/types/components/VrtxFindFriends.d.ts +25 -0
- package/dist/types/components/VrtxFindFriends.d.ts.map +1 -0
- package/dist/types/components/VrtxHeading.d.ts +6 -0
- package/dist/types/components/VrtxHeading.d.ts.map +1 -0
- package/dist/types/components/VrtxIncomingInvitations.d.ts +27 -0
- package/dist/types/components/VrtxIncomingInvitations.d.ts.map +1 -0
- package/dist/types/components/VrtxInvitationSuggestions.d.ts +25 -0
- package/dist/types/components/VrtxInvitationSuggestions.d.ts.map +1 -0
- package/dist/types/components/VrtxInviteContacts.d.ts +24 -0
- package/dist/types/components/VrtxInviteContacts.d.ts.map +1 -0
- package/dist/types/components/VrtxOutgoingInvitations.d.ts +27 -0
- package/dist/types/components/VrtxOutgoingInvitations.d.ts.map +1 -0
- package/dist/types/components/VrtxSearchBox.d.ts +28 -0
- package/dist/types/components/VrtxSearchBox.d.ts.map +1 -0
- package/dist/types/components/VrtxSelect.d.ts +6 -0
- package/dist/types/components/VrtxSelect.d.ts.map +1 -0
- package/dist/types/components/VrtxShareOptions.d.ts +41 -0
- package/dist/types/components/VrtxShareOptions.d.ts.map +1 -0
- package/dist/types/components/VrtxSubmit.d.ts +18 -0
- package/dist/types/components/VrtxSubmit.d.ts.map +1 -0
- package/dist/types/components/VrtxText.d.ts +8 -0
- package/dist/types/components/VrtxText.d.ts.map +1 -0
- package/dist/types/constants/mockData.d.ts +4 -0
- package/dist/types/constants/mockData.d.ts.map +1 -0
- package/dist/types/context/VortexModulesContext.d.ts +238 -0
- package/dist/types/context/VortexModulesContext.d.ts.map +1 -0
- package/dist/types/findFriends.js +10 -0
- package/dist/types/findFriends.js.map +1 -0
- package/dist/types/hooks/useInvitationFormLogic.d.ts +55 -0
- package/dist/types/hooks/useInvitationFormLogic.d.ts.map +1 -0
- package/dist/types/hooks/usePrefetchWidgetConfiguration.d.ts +39 -0
- package/dist/types/hooks/usePrefetchWidgetConfiguration.d.ts.map +1 -0
- package/dist/types/hooks/useThemeStyles.d.ts +1 -0
- package/dist/types/hooks/useThemeStyles.d.ts.map +1 -1
- package/dist/types/hooks/useVortexInvite.d.ts +48 -6
- package/dist/types/hooks/useVortexInvite.d.ts.map +1 -1
- package/dist/types/index-web.d.ts +23 -0
- package/dist/types/index-web.d.ts.map +1 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/invitations.js +13 -0
- package/dist/types/invitations.js.map +1 -0
- package/dist/types/inviteContacts.js +14 -0
- package/dist/types/inviteContacts.js.map +1 -0
- package/dist/{shared/InvitationResult.js → types/platformOperations.js} +1 -0
- package/dist/types/platformOperations.js.map +1 -0
- package/dist/types/searchBox.js +11 -0
- package/dist/types/searchBox.js.map +1 -0
- package/dist/types/types/findFriends.d.ts +101 -0
- package/dist/types/types/findFriends.d.ts.map +1 -0
- package/dist/types/types/invitations.d.ts +301 -0
- package/dist/types/types/invitations.d.ts.map +1 -0
- package/dist/types/types/inviteContacts.d.ts +86 -0
- package/dist/types/types/inviteContacts.d.ts.map +1 -0
- package/dist/types/types/platformOperations.d.ts +185 -0
- package/dist/types/types/platformOperations.d.ts.map +1 -0
- package/dist/types/types/searchBox.d.ts +69 -0
- package/dist/types/types/searchBox.d.ts.map +1 -0
- package/dist/types/types/unfurlConfig.d.ts +34 -0
- package/dist/types/types/unfurlConfig.d.ts.map +1 -0
- package/dist/types/unfurlConfig.js +21 -0
- package/dist/types/unfurlConfig.js.map +1 -0
- package/dist/types/utils/analytics.d.ts +54 -0
- package/dist/types/utils/analytics.d.ts.map +1 -0
- package/dist/types/utils/configCache.d.ts +34 -0
- package/dist/types/utils/configCache.d.ts.map +1 -0
- package/dist/types/utils/contactUtils.d.ts +9 -0
- package/dist/types/utils/contactUtils.d.ts.map +1 -0
- package/dist/types/utils/featureWarnings.d.ts +56 -0
- package/dist/types/utils/featureWarnings.d.ts.map +1 -0
- package/dist/types/utils/formUtils.d.ts +11 -3
- package/dist/types/utils/formUtils.d.ts.map +1 -1
- package/dist/types/utils/gradientUtils.d.ts +67 -0
- package/dist/types/utils/gradientUtils.d.ts.map +1 -0
- package/dist/types/utils/invitationEvents.d.ts +21 -0
- package/dist/types/utils/invitationEvents.d.ts.map +1 -0
- package/dist/types/utils/moduleLoaders.d.ts +115 -0
- package/dist/types/utils/moduleLoaders.d.ts.map +1 -0
- package/dist/types/utils/moduleLoaders.web.d.ts +73 -0
- package/dist/types/utils/moduleLoaders.web.d.ts.map +1 -0
- package/dist/types/utils/nameUtils.d.ts +15 -0
- package/dist/types/utils/nameUtils.d.ts.map +1 -0
- package/dist/types/utils/themeUtils.d.ts +3 -1
- package/dist/types/utils/themeUtils.d.ts.map +1 -1
- package/dist/types/vortexInvite.d.ts +145 -5
- package/dist/types/vortexInvite.d.ts.map +1 -1
- package/dist/useInvitationFormLogic-Ct73M19B.d.mts +242 -0
- package/dist/useInvitationFormLogic-Ct73M19B.d.ts +242 -0
- package/dist/utils/analytics.js +92 -0
- package/dist/utils/analytics.js.map +1 -0
- package/dist/utils/configCache.js +68 -0
- package/dist/utils/configCache.js.map +1 -0
- package/dist/utils/contactUtils.d.mts +12 -0
- package/dist/utils/contactUtils.d.ts +12 -0
- package/dist/utils/contactUtils.js +37 -0
- package/dist/utils/contactUtils.js.map +1 -0
- package/dist/utils/contactUtils.mjs +12 -0
- package/dist/utils/contactUtils.mjs.map +1 -0
- package/dist/utils/featureWarnings.js +214 -0
- package/dist/utils/featureWarnings.js.map +1 -0
- package/dist/utils/formUtils.js +161 -51
- package/dist/utils/formUtils.js.map +1 -0
- package/dist/utils/gradientUtils.js +120 -0
- package/dist/utils/gradientUtils.js.map +1 -0
- package/dist/utils/invitationEvents.js +45 -0
- package/dist/utils/invitationEvents.js.map +1 -0
- package/dist/utils/moduleLoaders.js +275 -0
- package/dist/utils/moduleLoaders.js.map +1 -0
- package/dist/utils/moduleLoaders.web.js +72 -0
- package/dist/utils/moduleLoaders.web.js.map +1 -0
- package/dist/utils/nameUtils.js +51 -0
- package/dist/utils/nameUtils.js.map +1 -0
- package/dist/utils/themeUtils.js +117 -32
- package/dist/utils/themeUtils.js.map +1 -0
- package/dist/vortexInvite.js +78 -167
- package/dist/vortexInvite.js.map +1 -0
- package/package.json +69 -31
- package/dist/components/Clipboard.js +0 -64
- package/dist/shared/api.js +0 -90
- package/dist/tests/TestVortexInvite.js +0 -134
- package/dist/types/components/Clipboard.d.ts +0 -16
- package/dist/types/components/Clipboard.d.ts.map +0 -1
- package/dist/types/shared/InvitationResult.d.ts +0 -24
- package/dist/types/shared/InvitationResult.d.ts.map +0 -1
- package/dist/types/shared/api.d.ts +0 -14
- package/dist/types/shared/api.d.ts.map +0 -1
- package/dist/types/tests/TestVortexInvite.d.ts +0 -4
- package/dist/types/tests/TestVortexInvite.d.ts.map +0 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_ANALYTICS_URL = void 0;
|
|
4
|
+
exports.getDeviceInfo = getDeviceInfo;
|
|
5
|
+
exports.extractForeignUserId = extractForeignUserId;
|
|
6
|
+
const react_native_1 = require("react-native");
|
|
7
|
+
// SDK version - should match package.json version
|
|
8
|
+
const SDK_VERSION = '0.0.15';
|
|
9
|
+
// Default production analytics URL
|
|
10
|
+
exports.DEFAULT_ANALYTICS_URL = 'https://collector.vortexsoftware.com';
|
|
11
|
+
/**
|
|
12
|
+
* Generates a device info / user agent string for analytics
|
|
13
|
+
* Format: VortexSDK-RN/{version} ({OS} {osVersion})
|
|
14
|
+
*/
|
|
15
|
+
function getDeviceInfo() {
|
|
16
|
+
const osName = react_native_1.Platform.OS === 'ios' ? 'iOS' : 'Android';
|
|
17
|
+
const osVersion = react_native_1.Platform.Version;
|
|
18
|
+
return `VortexSDK-RN/${SDK_VERSION} (${osName} ${osVersion})`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Extracts the foreign user ID from a JWT token
|
|
22
|
+
* Checks claims in order: userId, sub, user_id
|
|
23
|
+
* Handles both standard JWTs and raw-data format (insecure development JWTs)
|
|
24
|
+
*/
|
|
25
|
+
function extractForeignUserId(jwt) {
|
|
26
|
+
if (!jwt)
|
|
27
|
+
return undefined;
|
|
28
|
+
// Handle raw-data format (insecure JWT for development)
|
|
29
|
+
if (jwt.startsWith('raw-data:')) {
|
|
30
|
+
try {
|
|
31
|
+
const base64Part = jwt.replace('raw-data:', '');
|
|
32
|
+
// Use a cross-platform base64 decode
|
|
33
|
+
const decoded = decodeBase64(base64Part);
|
|
34
|
+
const json = JSON.parse(decoded);
|
|
35
|
+
return json.userId || json.user_id;
|
|
36
|
+
}
|
|
37
|
+
catch (_a) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Standard JWT: header.payload.signature
|
|
42
|
+
const parts = jwt.split('.');
|
|
43
|
+
if (parts.length < 2)
|
|
44
|
+
return undefined;
|
|
45
|
+
try {
|
|
46
|
+
// Base64 URL decode
|
|
47
|
+
const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
48
|
+
const decoded = decodeBase64(base64);
|
|
49
|
+
const payload = JSON.parse(decoded);
|
|
50
|
+
// Try common user ID claims in order:
|
|
51
|
+
return payload.userId || payload.sub || payload.user_id;
|
|
52
|
+
}
|
|
53
|
+
catch (_b) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Cross-platform base64 decode function
|
|
59
|
+
* Works in both React Native and web environments
|
|
60
|
+
*/
|
|
61
|
+
function decodeBase64(base64) {
|
|
62
|
+
// Add padding if needed
|
|
63
|
+
const padded = base64 + '==='.slice(0, (4 - (base64.length % 4)) % 4);
|
|
64
|
+
// Try using Buffer (Node.js / React Native with polyfill)
|
|
65
|
+
if (typeof Buffer !== 'undefined') {
|
|
66
|
+
return Buffer.from(padded, 'base64').toString('utf-8');
|
|
67
|
+
}
|
|
68
|
+
// Fallback to atob (web)
|
|
69
|
+
if (typeof atob !== 'undefined') {
|
|
70
|
+
return atob(padded);
|
|
71
|
+
}
|
|
72
|
+
// Manual decode as last resort
|
|
73
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
74
|
+
let output = '';
|
|
75
|
+
let i = 0;
|
|
76
|
+
while (i < padded.length) {
|
|
77
|
+
const enc1 = chars.indexOf(padded.charAt(i++));
|
|
78
|
+
const enc2 = chars.indexOf(padded.charAt(i++));
|
|
79
|
+
const enc3 = chars.indexOf(padded.charAt(i++));
|
|
80
|
+
const enc4 = chars.indexOf(padded.charAt(i++));
|
|
81
|
+
const chr1 = (enc1 << 2) | (enc2 >> 4);
|
|
82
|
+
const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
|
83
|
+
const chr3 = ((enc3 & 3) << 6) | enc4;
|
|
84
|
+
output += String.fromCharCode(chr1);
|
|
85
|
+
if (enc3 !== 64)
|
|
86
|
+
output += String.fromCharCode(chr2);
|
|
87
|
+
if (enc4 !== 64)
|
|
88
|
+
output += String.fromCharCode(chr3);
|
|
89
|
+
}
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/utils/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform } from 'react-native';\nimport type { EventName } from '@teamvortexsoftware/analytics-client';\n\n// SDK version - should match package.json version\nconst SDK_VERSION = '0.0.15';\n\n// Default production analytics URL\nexport const DEFAULT_ANALYTICS_URL = 'https://collector.vortexsoftware.com';\n\n/**\n * Analytics event interface for React Native SDK\n * Based on AnalyticsEvent from analytics-client with additional mobile-specific fields\n */\nexport interface VortexAnalyticsEvent {\n // Core fields from AnalyticsEvent\n name: EventName;\n widgetConfigurationId: string;\n deploymentId: string;\n environmentId: string;\n platform: string;\n segmentation?: Record<string, any>;\n payload?: Record<string, any>;\n groups?: Array<{\n type: string;\n id: string;\n name: string;\n }>;\n // Additional mobile-specific fields\n timestamp: number; // Unix timestamp in seconds\n sessionId?: string; // Generated UUID per session\n useragent?: string; // Device info string\n foreignUserId?: string; // Extracted from JWT\n}\n\n/**\n * Simplified analytics event for components that emit minimal events.\n * These components emit (name + segmentation) and the parent\n * is responsible for enriching with widgetConfigurationId, deploymentId, etc.\n */\nexport interface SimpleAnalyticsEvent {\n name: EventName;\n segmentation?: Record<string, any>;\n payload?: Record<string, any>;\n}\n\n/**\n * Group DTO for analytics events\n */\nexport interface GroupDTO {\n type: string;\n id: string;\n name: string;\n}\n\n/**\n * Generates a device info / user agent string for analytics\n * Format: VortexSDK-RN/{version} ({OS} {osVersion})\n */\nexport function getDeviceInfo(): string {\n const osName = Platform.OS === 'ios' ? 'iOS' : 'Android';\n const osVersion = Platform.Version;\n\n return `VortexSDK-RN/${SDK_VERSION} (${osName} ${osVersion})`;\n}\n\n/**\n * Extracts the foreign user ID from a JWT token\n * Checks claims in order: userId, sub, user_id\n * Handles both standard JWTs and raw-data format (insecure development JWTs)\n */\nexport function extractForeignUserId(jwt?: string): string | undefined {\n if (!jwt) return undefined;\n\n // Handle raw-data format (insecure JWT for development)\n if (jwt.startsWith('raw-data:')) {\n try {\n const base64Part = jwt.replace('raw-data:', '');\n // Use a cross-platform base64 decode\n const decoded = decodeBase64(base64Part);\n const json = JSON.parse(decoded);\n return json.userId || json.user_id;\n } catch {\n return undefined;\n }\n }\n\n // Standard JWT: header.payload.signature\n const parts = jwt.split('.');\n if (parts.length < 2) return undefined;\n\n try {\n // Base64 URL decode\n const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n const decoded = decodeBase64(base64);\n const payload = JSON.parse(decoded);\n\n // Try common user ID claims in order:\n return payload.userId || payload.sub || payload.user_id;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Cross-platform base64 decode function\n * Works in both React Native and web environments\n */\nfunction decodeBase64(base64: string): string {\n // Add padding if needed\n const padded = base64 + '==='.slice(0, (4 - (base64.length % 4)) % 4);\n\n // Try using Buffer (Node.js / React Native with polyfill)\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(padded, 'base64').toString('utf-8');\n }\n\n // Fallback to atob (web)\n if (typeof atob !== 'undefined') {\n return atob(padded);\n }\n\n // Manual decode as last resort\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n let output = '';\n let i = 0;\n\n while (i < padded.length) {\n const enc1 = chars.indexOf(padded.charAt(i++));\n const enc2 = chars.indexOf(padded.charAt(i++));\n const enc3 = chars.indexOf(padded.charAt(i++));\n const enc4 = chars.indexOf(padded.charAt(i++));\n\n const chr1 = (enc1 << 2) | (enc2 >> 4);\n const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n const chr3 = ((enc3 & 3) << 6) | enc4;\n\n output += String.fromCharCode(chr1);\n if (enc3 !== 64) output += String.fromCharCode(chr2);\n if (enc4 !== 64) output += String.fromCharCode(chr3);\n }\n\n return output;\n}\n\n\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configCache = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Module-level cache for widget configurations.
|
|
6
|
+
* This cache is shared across all hooks and components to ensure
|
|
7
|
+
* configuration updates persist between component mount/unmount cycles.
|
|
8
|
+
*
|
|
9
|
+
* Benefits:
|
|
10
|
+
* - Single source of truth for widget configurations
|
|
11
|
+
* - Persists between modal open/close cycles
|
|
12
|
+
* - Automatic synchronization between prefetch and main hooks
|
|
13
|
+
* - No React Context overhead
|
|
14
|
+
*/
|
|
15
|
+
const cache = new Map();
|
|
16
|
+
exports.configCache = {
|
|
17
|
+
/**
|
|
18
|
+
* Get a cached widget configuration by component ID.
|
|
19
|
+
* @param componentId - The widget component ID
|
|
20
|
+
* @returns The cached configuration, or undefined if not found
|
|
21
|
+
*/
|
|
22
|
+
get: (componentId) => {
|
|
23
|
+
return cache.get(componentId);
|
|
24
|
+
},
|
|
25
|
+
/**
|
|
26
|
+
* Store a widget configuration in the cache.
|
|
27
|
+
* @param componentId - The widget component ID
|
|
28
|
+
* @param config - The widget configuration to cache
|
|
29
|
+
*/
|
|
30
|
+
set: (componentId, config) => {
|
|
31
|
+
cache.set(componentId, config);
|
|
32
|
+
console.log('[Vortex] Configuration cached', {
|
|
33
|
+
componentId,
|
|
34
|
+
configId: config.id,
|
|
35
|
+
cacheSize: cache.size,
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* Clear cached configuration(s).
|
|
40
|
+
* @param componentId - Optional component ID to clear specific config. If omitted, clears all.
|
|
41
|
+
*/
|
|
42
|
+
clear: (componentId) => {
|
|
43
|
+
if (componentId) {
|
|
44
|
+
cache.delete(componentId);
|
|
45
|
+
console.log('[Vortex] Configuration cache cleared', { componentId });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
cache.clear();
|
|
49
|
+
console.log('[Vortex] All configuration cache cleared');
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Check if a configuration exists in the cache.
|
|
54
|
+
* @param componentId - The widget component ID
|
|
55
|
+
* @returns True if configuration is cached, false otherwise
|
|
56
|
+
*/
|
|
57
|
+
has: (componentId) => {
|
|
58
|
+
return cache.has(componentId);
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* Get cache statistics for debugging.
|
|
62
|
+
*/
|
|
63
|
+
stats: () => ({
|
|
64
|
+
size: cache.size,
|
|
65
|
+
keys: Array.from(cache.keys()),
|
|
66
|
+
}),
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=configCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configCache.js","sourceRoot":"","sources":["../../src/utils/configCache.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;GAUG;AACH,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;AAExC,QAAA,WAAW,GAAG;IACzB;;;;OAIG;IACH,GAAG,EAAE,CAAC,WAAmB,EAAmC,EAAE;QAC5D,OAAO,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,GAAG,EAAE,CAAC,WAAmB,EAAE,MAA2B,EAAQ,EAAE;QAC9D,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE;YAC3C,WAAW;YACX,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,SAAS,EAAE,KAAK,CAAC,IAAI;SACtB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,EAAE,CAAC,WAAoB,EAAQ,EAAE;QACpC,IAAI,WAAW,EAAE,CAAC;YAChB,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;QACvE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,GAAG,EAAE,CAAC,WAAmB,EAAW,EAAE;QACpC,OAAO,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;KAC/B,CAAC;CACH,CAAC","sourcesContent":["import { WidgetConfiguration } from '@teamvortexsoftware/vortex-types';\n\n/**\n * Module-level cache for widget configurations.\n * This cache is shared across all hooks and components to ensure\n * configuration updates persist between component mount/unmount cycles.\n * \n * Benefits:\n * - Single source of truth for widget configurations\n * - Persists between modal open/close cycles\n * - Automatic synchronization between prefetch and main hooks\n * - No React Context overhead\n */\nconst cache = new Map<string, WidgetConfiguration>();\n\nexport const configCache = {\n /**\n * Get a cached widget configuration by component ID.\n * @param componentId - The widget component ID\n * @returns The cached configuration, or undefined if not found\n */\n get: (componentId: string): WidgetConfiguration | undefined => {\n return cache.get(componentId);\n },\n\n /**\n * Store a widget configuration in the cache.\n * @param componentId - The widget component ID\n * @param config - The widget configuration to cache\n */\n set: (componentId: string, config: WidgetConfiguration): void => {\n cache.set(componentId, config);\n console.log('[Vortex] Configuration cached', {\n componentId,\n configId: config.id,\n cacheSize: cache.size,\n });\n },\n\n /**\n * Clear cached configuration(s).\n * @param componentId - Optional component ID to clear specific config. If omitted, clears all.\n */\n clear: (componentId?: string): void => {\n if (componentId) {\n cache.delete(componentId);\n console.log('[Vortex] Configuration cache cleared', { componentId });\n } else {\n cache.clear();\n console.log('[Vortex] All configuration cache cleared');\n }\n },\n\n /**\n * Check if a configuration exists in the cache.\n * @param componentId - The widget component ID\n * @returns True if configuration is cached, false otherwise\n */\n has: (componentId: string): boolean => {\n return cache.has(componentId);\n },\n\n /**\n * Get cache statistics for debugging.\n */\n stats: () => ({\n size: cache.size,\n keys: Array.from(cache.keys()),\n }),\n};\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { C as Contact } from '../useInvitationFormLogic-Ct73M19B.mjs';
|
|
2
|
+
import 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Filters contacts based on a search query
|
|
6
|
+
* @param contacts Array of contacts to filter
|
|
7
|
+
* @param searchQuery Query string to filter by
|
|
8
|
+
* @returns Filtered array of contacts
|
|
9
|
+
*/
|
|
10
|
+
declare function filterContacts(contacts: Contact[], searchQuery: string): Contact[];
|
|
11
|
+
|
|
12
|
+
export { filterContacts };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { C as Contact } from '../useInvitationFormLogic-Ct73M19B.js';
|
|
2
|
+
import 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Filters contacts based on a search query
|
|
6
|
+
* @param contacts Array of contacts to filter
|
|
7
|
+
* @param searchQuery Query string to filter by
|
|
8
|
+
* @returns Filtered array of contacts
|
|
9
|
+
*/
|
|
10
|
+
declare function filterContacts(contacts: Contact[], searchQuery: string): Contact[];
|
|
11
|
+
|
|
12
|
+
export { filterContacts };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/utils/contactUtils.ts
|
|
21
|
+
var contactUtils_exports = {};
|
|
22
|
+
__export(contactUtils_exports, {
|
|
23
|
+
filterContacts: () => filterContacts
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(contactUtils_exports);
|
|
26
|
+
function filterContacts(contacts, searchQuery) {
|
|
27
|
+
const query = searchQuery.toLowerCase().trim();
|
|
28
|
+
if (!query) return contacts;
|
|
29
|
+
return contacts.filter(
|
|
30
|
+
(contact) => contact.name.toLowerCase().includes(query) || contact.email.toLowerCase().includes(query)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
34
|
+
0 && (module.exports = {
|
|
35
|
+
filterContacts
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=contactUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/contactUtils.ts"],"sourcesContent":["import type { Contact } from '../hooks/useInvitationFormLogic';\n\n/**\n * Filters contacts based on a search query\n * @param contacts Array of contacts to filter\n * @param searchQuery Query string to filter by\n * @returns Filtered array of contacts\n */\nexport function filterContacts(contacts: Contact[], searchQuery: string): Contact[] {\n const query = searchQuery.toLowerCase().trim();\n if (!query) return contacts;\n \n return contacts.filter(contact =>\n contact.name.toLowerCase().includes(query) ||\n contact.email.toLowerCase().includes(query)\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQO,SAAS,eAAe,UAAqB,aAAgC;AAClF,QAAM,QAAQ,YAAY,YAAY,EAAE,KAAK;AAC7C,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAO,SAAS;AAAA,IAAO,aACrB,QAAQ,KAAK,YAAY,EAAE,SAAS,KAAK,KACzC,QAAQ,MAAM,YAAY,EAAE,SAAS,KAAK;AAAA,EAC5C;AACF;","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/utils/contactUtils.ts
|
|
2
|
+
function filterContacts(contacts, searchQuery) {
|
|
3
|
+
const query = searchQuery.toLowerCase().trim();
|
|
4
|
+
if (!query) return contacts;
|
|
5
|
+
return contacts.filter(
|
|
6
|
+
(contact) => contact.name.toLowerCase().includes(query) || contact.email.toLowerCase().includes(query)
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
filterContacts
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=contactUtils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/contactUtils.ts"],"sourcesContent":["import type { Contact } from '../hooks/useInvitationFormLogic';\n\n/**\n * Filters contacts based on a search query\n * @param contacts Array of contacts to filter\n * @param searchQuery Query string to filter by\n * @returns Filtered array of contacts\n */\nexport function filterContacts(contacts: Contact[], searchQuery: string): Contact[] {\n const query = searchQuery.toLowerCase().trim();\n if (!query) return contacts;\n \n return contacts.filter(contact =>\n contact.name.toLowerCase().includes(query) ||\n contact.email.toLowerCase().includes(query)\n );\n}\n"],"mappings":";AAQO,SAAS,eAAe,UAAqB,aAAgC;AAClF,QAAM,QAAQ,YAAY,YAAY,EAAE,KAAK;AAC7C,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAO,SAAS;AAAA,IAAO,aACrB,QAAQ,KAAK,YAAY,EAAE,SAAS,KAAK,KACzC,QAAQ,MAAM,YAAY,EAAE,SAAS,KAAK;AAAA,EAC5C;AACF;","names":[]}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Feature Warnings
|
|
4
|
+
*
|
|
5
|
+
* This module provides feature detection and helpful warnings for missing module configurations.
|
|
6
|
+
* It scans widget configuration to detect which features are required and prints actionable
|
|
7
|
+
* warnings when the corresponding module props are not specified.
|
|
8
|
+
*
|
|
9
|
+
* Warnings are only printed in development mode (__DEV__) and on native platforms.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.detectRequiredFeatures = detectRequiredFeatures;
|
|
13
|
+
exports.printFeatureWarnings = printFeatureWarnings;
|
|
14
|
+
exports.printWarningOnce = printWarningOnce;
|
|
15
|
+
exports.printInfoOnce = printInfoOnce;
|
|
16
|
+
exports.clearWarningsCache = clearWarningsCache;
|
|
17
|
+
const react_native_1 = require("react-native");
|
|
18
|
+
/**
|
|
19
|
+
* Recursively scans a node tree for gradient backgrounds.
|
|
20
|
+
*/
|
|
21
|
+
function scanForGradients(node) {
|
|
22
|
+
var _a, _b, _c, _d, _e, _f;
|
|
23
|
+
if (!node)
|
|
24
|
+
return false;
|
|
25
|
+
// Check style.background for linear-gradient
|
|
26
|
+
if ((_c = (_b = (_a = node.style) === null || _a === void 0 ? void 0 : _a.background) === null || _b === void 0 ? void 0 : _b.includes) === null || _c === void 0 ? void 0 : _c.call(_b, 'linear-gradient')) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
// Check theme options for gradients
|
|
30
|
+
if (((_d = node.theme) === null || _d === void 0 ? void 0 : _d.options) && Array.isArray(node.theme.options)) {
|
|
31
|
+
for (const option of node.theme.options) {
|
|
32
|
+
if ((_f = (_e = option.value) === null || _e === void 0 ? void 0 : _e.includes) === null || _f === void 0 ? void 0 : _f.call(_e, 'linear-gradient')) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Recursively check children
|
|
38
|
+
if (node.children && Array.isArray(node.children)) {
|
|
39
|
+
for (const child of node.children) {
|
|
40
|
+
if (scanForGradients(child))
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Recursively scans a node tree for QR code elements.
|
|
48
|
+
*/
|
|
49
|
+
function scanForQRCode(node) {
|
|
50
|
+
if (!node)
|
|
51
|
+
return false;
|
|
52
|
+
if (node.type === 'vrtx-qr-code' || node.tagName === 'vrtx-qr-code') {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (node.children && Array.isArray(node.children)) {
|
|
56
|
+
for (const child of node.children) {
|
|
57
|
+
if (scanForQRCode(child))
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Recursively scans a node tree for share options (which need clipboard).
|
|
65
|
+
*/
|
|
66
|
+
function scanForShareOptions(node) {
|
|
67
|
+
if (!node)
|
|
68
|
+
return false;
|
|
69
|
+
if (node.type === 'vrtx-share-options' || node.tagName === 'vrtx-share-options') {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (node.children && Array.isArray(node.children)) {
|
|
73
|
+
for (const child of node.children) {
|
|
74
|
+
if (scanForShareOptions(child))
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Detects which features are required based on widget configuration.
|
|
82
|
+
*
|
|
83
|
+
* @param widgetConfiguration - The widget configuration from the API
|
|
84
|
+
* @returns Object indicating which features are needed
|
|
85
|
+
*/
|
|
86
|
+
function detectRequiredFeatures(widgetConfiguration) {
|
|
87
|
+
var _a;
|
|
88
|
+
const requirements = {
|
|
89
|
+
needsGradient: false,
|
|
90
|
+
needsQRCode: false,
|
|
91
|
+
needsHaptics: true, // Always nice to have for buttons
|
|
92
|
+
needsClipboard: false,
|
|
93
|
+
};
|
|
94
|
+
if (!widgetConfiguration)
|
|
95
|
+
return requirements;
|
|
96
|
+
const rootElement = ((_a = widgetConfiguration.data) === null || _a === void 0 ? void 0 : _a.rootElement) || widgetConfiguration.rootElement;
|
|
97
|
+
requirements.needsGradient = scanForGradients(rootElement);
|
|
98
|
+
requirements.needsQRCode = scanForQRCode(rootElement);
|
|
99
|
+
requirements.needsClipboard = scanForShareOptions(rootElement);
|
|
100
|
+
return requirements;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Prints helpful warnings for missing module configurations.
|
|
104
|
+
* Only prints in development mode and on native platforms.
|
|
105
|
+
* Uses deduplication helpers to prevent warnings from printing on every render.
|
|
106
|
+
*
|
|
107
|
+
* @param requirements - The detected feature requirements
|
|
108
|
+
* @param moduleConfig - The current module configuration from props
|
|
109
|
+
*/
|
|
110
|
+
function printFeatureWarnings(requirements, moduleConfig) {
|
|
111
|
+
var _a, _b, _c, _d;
|
|
112
|
+
// Only warn in development and on native platforms
|
|
113
|
+
if (!__DEV__ || react_native_1.Platform.OS === 'web')
|
|
114
|
+
return;
|
|
115
|
+
// Check for module configuration
|
|
116
|
+
const hasGradientModule = (_a = moduleConfig.modules) === null || _a === void 0 ? void 0 : _a.gradient;
|
|
117
|
+
const hasQRCodeModule = (_b = moduleConfig.modules) === null || _b === void 0 ? void 0 : _b.qrCode;
|
|
118
|
+
const hasHapticsModule = (_c = moduleConfig.modules) === null || _c === void 0 ? void 0 : _c.haptics;
|
|
119
|
+
const hasClipboardModule = (_d = moduleConfig.modules) === null || _d === void 0 ? void 0 : _d.clipboard;
|
|
120
|
+
// Gradient warning
|
|
121
|
+
if (requirements.needsGradient && !hasGradientModule) {
|
|
122
|
+
printWarningOnce('vortex-gradient-module', `[Vortex] ⚠️ Gradient backgrounds detected in widget configuration, but no gradient module specified.
|
|
123
|
+
|
|
124
|
+
To enable gradients on native platforms, add the modules prop to <VortexInvite>:
|
|
125
|
+
|
|
126
|
+
For Expo projects:
|
|
127
|
+
<VortexInvite modules={{ gradient: 'expo-linear-gradient' }} ... />
|
|
128
|
+
Then run: npx expo install expo-linear-gradient
|
|
129
|
+
|
|
130
|
+
For bare React Native:
|
|
131
|
+
<VortexInvite modules={{ gradient: 'react-native-linear-gradient' }} ... />
|
|
132
|
+
Then run: npm install react-native-linear-gradient
|
|
133
|
+
|
|
134
|
+
Without a gradient module, gradient backgrounds will fall back to solid colors.
|
|
135
|
+
`);
|
|
136
|
+
}
|
|
137
|
+
// QR Code warning
|
|
138
|
+
if (requirements.needsQRCode && !hasQRCodeModule) {
|
|
139
|
+
printWarningOnce('vortex-qrcode-module', `[Vortex] ⚠️ QR Code feature detected in widget configuration, but no QR code module specified.
|
|
140
|
+
|
|
141
|
+
To enable QR codes, add the modules prop to <VortexInvite>:
|
|
142
|
+
|
|
143
|
+
For native apps:
|
|
144
|
+
<VortexInvite modules={{ qrCode: 'react-native-qrcode-svg' }} ... />
|
|
145
|
+
Then run: npm install react-native-qrcode-svg react-native-svg
|
|
146
|
+
|
|
147
|
+
For web preview:
|
|
148
|
+
<VortexInvite modules={{ qrCode: 'react-qr-code' }} ... />
|
|
149
|
+
Then run: npm install react-qr-code
|
|
150
|
+
|
|
151
|
+
Without a QR code module, QR codes will show a placeholder message.
|
|
152
|
+
`);
|
|
153
|
+
}
|
|
154
|
+
// Haptics info (less critical)
|
|
155
|
+
if (requirements.needsHaptics && !hasHapticsModule) {
|
|
156
|
+
printInfoOnce('vortex-haptics-module', `[Vortex] 💡 Tip: Add haptic feedback for better UX:
|
|
157
|
+
|
|
158
|
+
<VortexInvite modules={{ haptics: 'expo-haptics' }} ... />
|
|
159
|
+
Then run: npx expo install expo-haptics
|
|
160
|
+
`);
|
|
161
|
+
}
|
|
162
|
+
// Clipboard info (only if share options are present)
|
|
163
|
+
if (requirements.needsClipboard && !hasClipboardModule) {
|
|
164
|
+
printInfoOnce('vortex-clipboard-module', `[Vortex] 💡 Tip: For clipboard support (Copy Link), add:
|
|
165
|
+
|
|
166
|
+
For Expo projects:
|
|
167
|
+
<VortexInvite modules={{ clipboard: 'expo-clipboard' }} ... />
|
|
168
|
+
Then run: npx expo install expo-clipboard
|
|
169
|
+
|
|
170
|
+
For bare React Native:
|
|
171
|
+
<VortexInvite modules={{ clipboard: '@react-native-clipboard/clipboard' }} ... />
|
|
172
|
+
Then run: npm install @react-native-clipboard/clipboard
|
|
173
|
+
|
|
174
|
+
Without a clipboard module, the SDK will use React Native's built-in Clipboard API.
|
|
175
|
+
`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Tracks which warnings have been printed to avoid duplicate warnings.
|
|
180
|
+
*/
|
|
181
|
+
const printedWarnings = new Set();
|
|
182
|
+
/**
|
|
183
|
+
* Prints a warning only once per session.
|
|
184
|
+
* Useful for warnings that shouldn't spam the console on every render.
|
|
185
|
+
*
|
|
186
|
+
* @param key - Unique key for this warning
|
|
187
|
+
* @param message - The warning message to print
|
|
188
|
+
*/
|
|
189
|
+
function printWarningOnce(key, message) {
|
|
190
|
+
if (!__DEV__ || printedWarnings.has(key))
|
|
191
|
+
return;
|
|
192
|
+
printedWarnings.add(key);
|
|
193
|
+
console.warn(message);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Prints an info message only once per session.
|
|
197
|
+
*
|
|
198
|
+
* @param key - Unique key for this message
|
|
199
|
+
* @param message - The info message to print
|
|
200
|
+
*/
|
|
201
|
+
function printInfoOnce(key, message) {
|
|
202
|
+
if (!__DEV__ || printedWarnings.has(key))
|
|
203
|
+
return;
|
|
204
|
+
printedWarnings.add(key);
|
|
205
|
+
console.info(message);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Clears the printed warnings cache.
|
|
209
|
+
* Useful for testing or when you want warnings to be printed again.
|
|
210
|
+
*/
|
|
211
|
+
function clearWarningsCache() {
|
|
212
|
+
printedWarnings.clear();
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=featureWarnings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"featureWarnings.js","sourceRoot":"","sources":["../../src/utils/featureWarnings.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAyFH,wDAkBC;AAUD,oDAqFC;AAcD,4CAKC;AAQD,sCAKC;AAMD,gDAEC;AAhPD,+CAAwC;AAaxC;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAS;;IACjC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAExB,6CAA6C;IAC7C,IAAI,MAAA,MAAA,MAAA,IAAI,CAAC,KAAK,0CAAE,UAAU,0CAAE,QAAQ,mDAAG,iBAAiB,CAAC,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oCAAoC;IACpC,IAAI,CAAA,MAAA,IAAI,CAAC,KAAK,0CAAE,OAAO,KAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,MAAA,MAAA,MAAM,CAAC,KAAK,0CAAE,QAAQ,mDAAG,iBAAiB,CAAC,EAAE,CAAC;gBAChD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,IAAI,gBAAgB,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,IAAS;IAC9B,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAExB,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,OAAO,KAAK,cAAc,EAAE,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,IAAI,aAAa,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,IAAS;IACpC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAExB,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB,IAAI,IAAI,CAAC,OAAO,KAAK,oBAAoB,EAAE,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,IAAI,mBAAmB,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,mBAAwB;;IAC7D,MAAM,YAAY,GAAwB;QACxC,aAAa,EAAE,KAAK;QACpB,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,IAAI,EAAE,kCAAkC;QACtD,cAAc,EAAE,KAAK;KACtB,CAAC;IAEF,IAAI,CAAC,mBAAmB;QAAE,OAAO,YAAY,CAAC;IAE9C,MAAM,WAAW,GACf,CAAA,MAAA,mBAAmB,CAAC,IAAI,0CAAE,WAAW,KAAI,mBAAmB,CAAC,WAAW,CAAC;IAE3E,YAAY,CAAC,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC3D,YAAY,CAAC,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IACtD,YAAY,CAAC,cAAc,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAE/D,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,oBAAoB,CAClC,YAAiC,EACjC,YAAiC;;IAEjC,mDAAmD;IACnD,IAAI,CAAC,OAAO,IAAI,uBAAQ,CAAC,EAAE,KAAK,KAAK;QAAE,OAAO;IAE9C,iCAAiC;IACjC,MAAM,iBAAiB,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,QAAQ,CAAC;IACzD,MAAM,eAAe,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,MAAM,CAAC;IACrD,MAAM,gBAAgB,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,OAAO,CAAC;IACvD,MAAM,kBAAkB,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,SAAS,CAAC;IAE3D,mBAAmB;IACnB,IAAI,YAAY,CAAC,aAAa,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACrD,gBAAgB,CACd,wBAAwB,EACxB;;;;;;;;;;;;;CAaL,CACI,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,IAAI,YAAY,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE,CAAC;QACjD,gBAAgB,CACd,sBAAsB,EACtB;;;;;;;;;;;;;CAaL,CACI,CAAC;IACJ,CAAC;IAED,+BAA+B;IAC/B,IAAI,YAAY,CAAC,YAAY,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACnD,aAAa,CACX,uBAAuB,EACvB;;;;CAIL,CACI,CAAC;IACJ,CAAC;IAED,qDAAqD;IACrD,IAAI,YAAY,CAAC,cAAc,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACvD,aAAa,CACX,yBAAyB,EACzB;;;;;;;;;;;CAWL,CACI,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;AAE1C;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,GAAW,EAAE,OAAe;IAC3D,IAAI,CAAC,OAAO,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO;IAEjD,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,GAAW,EAAE,OAAe;IACxD,IAAI,CAAC,OAAO,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO;IAEjD,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB;IAChC,eAAe,CAAC,KAAK,EAAE,CAAC;AAC1B,CAAC","sourcesContent":["/**\n * Feature Warnings\n *\n * This module provides feature detection and helpful warnings for missing module configurations.\n * It scans widget configuration to detect which features are required and prints actionable\n * warnings when the corresponding module props are not specified.\n *\n * Warnings are only printed in development mode (__DEV__) and on native platforms.\n */\n\nimport { Platform } from 'react-native';\nimport type { VortexModulesConfig } from '../context/VortexModulesContext';\n\n/**\n * Features that may be required based on widget configuration\n */\nexport interface FeatureRequirements {\n needsGradient: boolean;\n needsQRCode: boolean;\n needsHaptics: boolean;\n needsClipboard: boolean;\n}\n\n/**\n * Recursively scans a node tree for gradient backgrounds.\n */\nfunction scanForGradients(node: any): boolean {\n if (!node) return false;\n\n // Check style.background for linear-gradient\n if (node.style?.background?.includes?.('linear-gradient')) {\n return true;\n }\n\n // Check theme options for gradients\n if (node.theme?.options && Array.isArray(node.theme.options)) {\n for (const option of node.theme.options) {\n if (option.value?.includes?.('linear-gradient')) {\n return true;\n }\n }\n }\n\n // Recursively check children\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n if (scanForGradients(child)) return true;\n }\n }\n\n return false;\n}\n\n/**\n * Recursively scans a node tree for QR code elements.\n */\nfunction scanForQRCode(node: any): boolean {\n if (!node) return false;\n\n if (node.type === 'vrtx-qr-code' || node.tagName === 'vrtx-qr-code') {\n return true;\n }\n\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n if (scanForQRCode(child)) return true;\n }\n }\n\n return false;\n}\n\n/**\n * Recursively scans a node tree for share options (which need clipboard).\n */\nfunction scanForShareOptions(node: any): boolean {\n if (!node) return false;\n\n if (node.type === 'vrtx-share-options' || node.tagName === 'vrtx-share-options') {\n return true;\n }\n\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n if (scanForShareOptions(child)) return true;\n }\n }\n\n return false;\n}\n\n/**\n * Detects which features are required based on widget configuration.\n *\n * @param widgetConfiguration - The widget configuration from the API\n * @returns Object indicating which features are needed\n */\nexport function detectRequiredFeatures(widgetConfiguration: any): FeatureRequirements {\n const requirements: FeatureRequirements = {\n needsGradient: false,\n needsQRCode: false,\n needsHaptics: true, // Always nice to have for buttons\n needsClipboard: false,\n };\n\n if (!widgetConfiguration) return requirements;\n\n const rootElement =\n widgetConfiguration.data?.rootElement || widgetConfiguration.rootElement;\n\n requirements.needsGradient = scanForGradients(rootElement);\n requirements.needsQRCode = scanForQRCode(rootElement);\n requirements.needsClipboard = scanForShareOptions(rootElement);\n\n return requirements;\n}\n\n/**\n * Prints helpful warnings for missing module configurations.\n * Only prints in development mode and on native platforms.\n * Uses deduplication helpers to prevent warnings from printing on every render.\n *\n * @param requirements - The detected feature requirements\n * @param moduleConfig - The current module configuration from props\n */\nexport function printFeatureWarnings(\n requirements: FeatureRequirements,\n moduleConfig: VortexModulesConfig\n): void {\n // Only warn in development and on native platforms\n if (!__DEV__ || Platform.OS === 'web') return;\n\n // Check for module configuration\n const hasGradientModule = moduleConfig.modules?.gradient;\n const hasQRCodeModule = moduleConfig.modules?.qrCode;\n const hasHapticsModule = moduleConfig.modules?.haptics;\n const hasClipboardModule = moduleConfig.modules?.clipboard;\n\n // Gradient warning\n if (requirements.needsGradient && !hasGradientModule) {\n printWarningOnce(\n 'vortex-gradient-module',\n `[Vortex] ⚠️ Gradient backgrounds detected in widget configuration, but no gradient module specified.\n\nTo enable gradients on native platforms, add the modules prop to <VortexInvite>:\n\n For Expo projects:\n <VortexInvite modules={{ gradient: 'expo-linear-gradient' }} ... />\n Then run: npx expo install expo-linear-gradient\n\n For bare React Native:\n <VortexInvite modules={{ gradient: 'react-native-linear-gradient' }} ... />\n Then run: npm install react-native-linear-gradient\n\nWithout a gradient module, gradient backgrounds will fall back to solid colors.\n`\n );\n }\n\n // QR Code warning\n if (requirements.needsQRCode && !hasQRCodeModule) {\n printWarningOnce(\n 'vortex-qrcode-module',\n `[Vortex] ⚠️ QR Code feature detected in widget configuration, but no QR code module specified.\n\nTo enable QR codes, add the modules prop to <VortexInvite>:\n\n For native apps:\n <VortexInvite modules={{ qrCode: 'react-native-qrcode-svg' }} ... />\n Then run: npm install react-native-qrcode-svg react-native-svg\n\n For web preview:\n <VortexInvite modules={{ qrCode: 'react-qr-code' }} ... />\n Then run: npm install react-qr-code\n\nWithout a QR code module, QR codes will show a placeholder message.\n`\n );\n }\n\n // Haptics info (less critical)\n if (requirements.needsHaptics && !hasHapticsModule) {\n printInfoOnce(\n 'vortex-haptics-module',\n `[Vortex] 💡 Tip: Add haptic feedback for better UX:\n\n <VortexInvite modules={{ haptics: 'expo-haptics' }} ... />\n Then run: npx expo install expo-haptics\n`\n );\n }\n\n // Clipboard info (only if share options are present)\n if (requirements.needsClipboard && !hasClipboardModule) {\n printInfoOnce(\n 'vortex-clipboard-module',\n `[Vortex] 💡 Tip: For clipboard support (Copy Link), add:\n\n For Expo projects:\n <VortexInvite modules={{ clipboard: 'expo-clipboard' }} ... />\n Then run: npx expo install expo-clipboard\n\n For bare React Native:\n <VortexInvite modules={{ clipboard: '@react-native-clipboard/clipboard' }} ... />\n Then run: npm install @react-native-clipboard/clipboard\n\nWithout a clipboard module, the SDK will use React Native's built-in Clipboard API.\n`\n );\n }\n}\n\n/**\n * Tracks which warnings have been printed to avoid duplicate warnings.\n */\nconst printedWarnings = new Set<string>();\n\n/**\n * Prints a warning only once per session.\n * Useful for warnings that shouldn't spam the console on every render.\n *\n * @param key - Unique key for this warning\n * @param message - The warning message to print\n */\nexport function printWarningOnce(key: string, message: string): void {\n if (!__DEV__ || printedWarnings.has(key)) return;\n\n printedWarnings.add(key);\n console.warn(message);\n}\n\n/**\n * Prints an info message only once per session.\n *\n * @param key - Unique key for this message\n * @param message - The info message to print\n */\nexport function printInfoOnce(key: string, message: string): void {\n if (!__DEV__ || printedWarnings.has(key)) return;\n\n printedWarnings.add(key);\n console.info(message);\n}\n\n/**\n * Clears the printed warnings cache.\n * Useful for testing or when you want warnings to be printed again.\n */\nexport function clearWarningsCache(): void {\n printedWarnings.clear();\n}\n"]}
|