@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.
Files changed (228) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1227 -11
  3. package/dist/InviteFormCore-D4HkMMo0.d.mts +721 -0
  4. package/dist/InviteFormCore-D9oUCbu7.d.ts +721 -0
  5. package/dist/VortexClient.js +192 -0
  6. package/dist/VortexClient.js.map +1 -0
  7. package/dist/VortexDeferredLinks.js +127 -0
  8. package/dist/VortexDeferredLinks.js.map +1 -0
  9. package/dist/clientInfo.js +45 -0
  10. package/dist/clientInfo.js.map +1 -0
  11. package/dist/components/ContactsPickerModal.js +182 -0
  12. package/dist/components/ContactsPickerModal.js.map +1 -0
  13. package/dist/components/InviteFormCore.js +2141 -0
  14. package/dist/components/InviteFormCore.js.map +1 -0
  15. package/dist/components/InviteFormMobile.js +463 -0
  16. package/dist/components/InviteFormMobile.js.map +1 -0
  17. package/dist/components/InviteFormWeb.js +295 -0
  18. package/dist/components/InviteFormWeb.js.map +1 -0
  19. package/dist/components/PlacedItemToolbar.js +147 -0
  20. package/dist/components/PlacedItemToolbar.js.map +1 -0
  21. package/dist/components/ShareButtons.js +1 -0
  22. package/dist/components/ShareButtons.js.map +1 -0
  23. package/dist/components/VrtxContactsImport.js +234 -0
  24. package/dist/components/VrtxContactsImport.js.map +1 -0
  25. package/dist/components/VrtxEmailInvitations.js +341 -0
  26. package/dist/components/VrtxEmailInvitations.js.map +1 -0
  27. package/dist/components/VrtxFindFriends.js +400 -0
  28. package/dist/components/VrtxFindFriends.js.map +1 -0
  29. package/dist/components/VrtxHeading.js +58 -0
  30. package/dist/components/VrtxHeading.js.map +1 -0
  31. package/dist/components/VrtxIncomingInvitations.js +657 -0
  32. package/dist/components/VrtxIncomingInvitations.js.map +1 -0
  33. package/dist/components/VrtxInvitationSuggestions.js +506 -0
  34. package/dist/components/VrtxInvitationSuggestions.js.map +1 -0
  35. package/dist/components/VrtxInviteContacts.js +512 -0
  36. package/dist/components/VrtxInviteContacts.js.map +1 -0
  37. package/dist/components/VrtxOutgoingInvitations.js +572 -0
  38. package/dist/components/VrtxOutgoingInvitations.js.map +1 -0
  39. package/dist/components/VrtxSearchBox.js +487 -0
  40. package/dist/components/VrtxSearchBox.js.map +1 -0
  41. package/dist/components/VrtxSelect.js +27 -0
  42. package/dist/components/VrtxSelect.js.map +1 -0
  43. package/dist/components/VrtxShareOptions.js +435 -0
  44. package/dist/components/VrtxShareOptions.js.map +1 -0
  45. package/dist/components/VrtxSubmit.js +132 -0
  46. package/dist/components/VrtxSubmit.js.map +1 -0
  47. package/dist/components/VrtxText.js +146 -0
  48. package/dist/components/VrtxText.js.map +1 -0
  49. package/dist/constants/mockData.d.mts +7 -0
  50. package/dist/constants/mockData.d.ts +7 -0
  51. package/dist/constants/mockData.js +48 -0
  52. package/dist/constants/mockData.js.map +1 -0
  53. package/dist/constants/mockData.mjs +22 -0
  54. package/dist/constants/mockData.mjs.map +1 -0
  55. package/dist/context/VortexModulesContext.js +135 -0
  56. package/dist/context/VortexModulesContext.js.map +1 -0
  57. package/dist/hooks/useInvitationFormLogic.d.mts +2 -0
  58. package/dist/hooks/useInvitationFormLogic.d.ts +2 -0
  59. package/dist/hooks/useInvitationFormLogic.js +300 -0
  60. package/dist/hooks/useInvitationFormLogic.js.map +1 -0
  61. package/dist/hooks/useInvitationFormLogic.mjs +276 -0
  62. package/dist/hooks/useInvitationFormLogic.mjs.map +1 -0
  63. package/dist/hooks/usePrefetchWidgetConfiguration.js +117 -0
  64. package/dist/hooks/usePrefetchWidgetConfiguration.js.map +1 -0
  65. package/dist/hooks/useThemeStyles.js +2 -0
  66. package/dist/hooks/useThemeStyles.js.map +1 -0
  67. package/dist/hooks/useVortexInvite.js +467 -56
  68. package/dist/hooks/useVortexInvite.js.map +1 -0
  69. package/dist/index-web.d.mts +93 -0
  70. package/dist/index-web.d.ts +93 -0
  71. package/dist/index-web.js +7397 -0
  72. package/dist/index-web.js.map +1 -0
  73. package/dist/index-web.mjs +7445 -0
  74. package/dist/index-web.mjs.map +1 -0
  75. package/dist/index.d.mts +656 -0
  76. package/dist/index.d.ts +656 -0
  77. package/dist/index.js +10205 -4
  78. package/dist/index.js.map +1 -0
  79. package/dist/index.mjs +10244 -0
  80. package/dist/index.mjs.map +1 -0
  81. package/dist/types/VortexClient.d.ts +106 -0
  82. package/dist/types/VortexClient.d.ts.map +1 -0
  83. package/dist/types/VortexDeferredLinks.d.ts +73 -0
  84. package/dist/types/VortexDeferredLinks.d.ts.map +1 -0
  85. package/dist/types/clientInfo.d.ts +5 -0
  86. package/dist/types/clientInfo.d.ts.map +1 -0
  87. package/dist/types/components/ContactsPickerModal.d.ts +18 -0
  88. package/dist/types/components/ContactsPickerModal.d.ts.map +1 -0
  89. package/dist/types/components/InviteFormCore.d.ts +166 -0
  90. package/dist/types/components/InviteFormCore.d.ts.map +1 -0
  91. package/dist/types/components/InviteFormMobile.d.ts +42 -0
  92. package/dist/types/components/InviteFormMobile.d.ts.map +1 -0
  93. package/dist/types/components/InviteFormWeb.d.ts +87 -0
  94. package/dist/types/components/InviteFormWeb.d.ts.map +1 -0
  95. package/dist/types/components/PlacedItemToolbar.d.ts +16 -0
  96. package/dist/types/components/PlacedItemToolbar.d.ts.map +1 -0
  97. package/dist/types/components/VrtxContactsImport.d.ts +14 -0
  98. package/dist/types/components/VrtxContactsImport.d.ts.map +1 -0
  99. package/dist/types/components/VrtxEmailInvitations.d.ts +31 -0
  100. package/dist/types/components/VrtxEmailInvitations.d.ts.map +1 -0
  101. package/dist/types/components/VrtxFindFriends.d.ts +25 -0
  102. package/dist/types/components/VrtxFindFriends.d.ts.map +1 -0
  103. package/dist/types/components/VrtxHeading.d.ts +6 -0
  104. package/dist/types/components/VrtxHeading.d.ts.map +1 -0
  105. package/dist/types/components/VrtxIncomingInvitations.d.ts +27 -0
  106. package/dist/types/components/VrtxIncomingInvitations.d.ts.map +1 -0
  107. package/dist/types/components/VrtxInvitationSuggestions.d.ts +25 -0
  108. package/dist/types/components/VrtxInvitationSuggestions.d.ts.map +1 -0
  109. package/dist/types/components/VrtxInviteContacts.d.ts +24 -0
  110. package/dist/types/components/VrtxInviteContacts.d.ts.map +1 -0
  111. package/dist/types/components/VrtxOutgoingInvitations.d.ts +27 -0
  112. package/dist/types/components/VrtxOutgoingInvitations.d.ts.map +1 -0
  113. package/dist/types/components/VrtxSearchBox.d.ts +28 -0
  114. package/dist/types/components/VrtxSearchBox.d.ts.map +1 -0
  115. package/dist/types/components/VrtxSelect.d.ts +6 -0
  116. package/dist/types/components/VrtxSelect.d.ts.map +1 -0
  117. package/dist/types/components/VrtxShareOptions.d.ts +41 -0
  118. package/dist/types/components/VrtxShareOptions.d.ts.map +1 -0
  119. package/dist/types/components/VrtxSubmit.d.ts +18 -0
  120. package/dist/types/components/VrtxSubmit.d.ts.map +1 -0
  121. package/dist/types/components/VrtxText.d.ts +8 -0
  122. package/dist/types/components/VrtxText.d.ts.map +1 -0
  123. package/dist/types/constants/mockData.d.ts +4 -0
  124. package/dist/types/constants/mockData.d.ts.map +1 -0
  125. package/dist/types/context/VortexModulesContext.d.ts +238 -0
  126. package/dist/types/context/VortexModulesContext.d.ts.map +1 -0
  127. package/dist/types/findFriends.js +10 -0
  128. package/dist/types/findFriends.js.map +1 -0
  129. package/dist/types/hooks/useInvitationFormLogic.d.ts +55 -0
  130. package/dist/types/hooks/useInvitationFormLogic.d.ts.map +1 -0
  131. package/dist/types/hooks/usePrefetchWidgetConfiguration.d.ts +39 -0
  132. package/dist/types/hooks/usePrefetchWidgetConfiguration.d.ts.map +1 -0
  133. package/dist/types/hooks/useThemeStyles.d.ts +1 -0
  134. package/dist/types/hooks/useThemeStyles.d.ts.map +1 -1
  135. package/dist/types/hooks/useVortexInvite.d.ts +48 -6
  136. package/dist/types/hooks/useVortexInvite.d.ts.map +1 -1
  137. package/dist/types/index-web.d.ts +23 -0
  138. package/dist/types/index-web.d.ts.map +1 -0
  139. package/dist/types/index.d.ts +21 -0
  140. package/dist/types/index.d.ts.map +1 -1
  141. package/dist/types/invitations.js +13 -0
  142. package/dist/types/invitations.js.map +1 -0
  143. package/dist/types/inviteContacts.js +14 -0
  144. package/dist/types/inviteContacts.js.map +1 -0
  145. package/dist/{shared/InvitationResult.js → types/platformOperations.js} +1 -0
  146. package/dist/types/platformOperations.js.map +1 -0
  147. package/dist/types/searchBox.js +11 -0
  148. package/dist/types/searchBox.js.map +1 -0
  149. package/dist/types/types/findFriends.d.ts +101 -0
  150. package/dist/types/types/findFriends.d.ts.map +1 -0
  151. package/dist/types/types/invitations.d.ts +301 -0
  152. package/dist/types/types/invitations.d.ts.map +1 -0
  153. package/dist/types/types/inviteContacts.d.ts +86 -0
  154. package/dist/types/types/inviteContacts.d.ts.map +1 -0
  155. package/dist/types/types/platformOperations.d.ts +185 -0
  156. package/dist/types/types/platformOperations.d.ts.map +1 -0
  157. package/dist/types/types/searchBox.d.ts +69 -0
  158. package/dist/types/types/searchBox.d.ts.map +1 -0
  159. package/dist/types/types/unfurlConfig.d.ts +34 -0
  160. package/dist/types/types/unfurlConfig.d.ts.map +1 -0
  161. package/dist/types/unfurlConfig.js +21 -0
  162. package/dist/types/unfurlConfig.js.map +1 -0
  163. package/dist/types/utils/analytics.d.ts +54 -0
  164. package/dist/types/utils/analytics.d.ts.map +1 -0
  165. package/dist/types/utils/configCache.d.ts +34 -0
  166. package/dist/types/utils/configCache.d.ts.map +1 -0
  167. package/dist/types/utils/contactUtils.d.ts +9 -0
  168. package/dist/types/utils/contactUtils.d.ts.map +1 -0
  169. package/dist/types/utils/featureWarnings.d.ts +56 -0
  170. package/dist/types/utils/featureWarnings.d.ts.map +1 -0
  171. package/dist/types/utils/formUtils.d.ts +11 -3
  172. package/dist/types/utils/formUtils.d.ts.map +1 -1
  173. package/dist/types/utils/gradientUtils.d.ts +67 -0
  174. package/dist/types/utils/gradientUtils.d.ts.map +1 -0
  175. package/dist/types/utils/invitationEvents.d.ts +21 -0
  176. package/dist/types/utils/invitationEvents.d.ts.map +1 -0
  177. package/dist/types/utils/moduleLoaders.d.ts +115 -0
  178. package/dist/types/utils/moduleLoaders.d.ts.map +1 -0
  179. package/dist/types/utils/moduleLoaders.web.d.ts +73 -0
  180. package/dist/types/utils/moduleLoaders.web.d.ts.map +1 -0
  181. package/dist/types/utils/nameUtils.d.ts +15 -0
  182. package/dist/types/utils/nameUtils.d.ts.map +1 -0
  183. package/dist/types/utils/themeUtils.d.ts +3 -1
  184. package/dist/types/utils/themeUtils.d.ts.map +1 -1
  185. package/dist/types/vortexInvite.d.ts +145 -5
  186. package/dist/types/vortexInvite.d.ts.map +1 -1
  187. package/dist/useInvitationFormLogic-Ct73M19B.d.mts +242 -0
  188. package/dist/useInvitationFormLogic-Ct73M19B.d.ts +242 -0
  189. package/dist/utils/analytics.js +92 -0
  190. package/dist/utils/analytics.js.map +1 -0
  191. package/dist/utils/configCache.js +68 -0
  192. package/dist/utils/configCache.js.map +1 -0
  193. package/dist/utils/contactUtils.d.mts +12 -0
  194. package/dist/utils/contactUtils.d.ts +12 -0
  195. package/dist/utils/contactUtils.js +37 -0
  196. package/dist/utils/contactUtils.js.map +1 -0
  197. package/dist/utils/contactUtils.mjs +12 -0
  198. package/dist/utils/contactUtils.mjs.map +1 -0
  199. package/dist/utils/featureWarnings.js +214 -0
  200. package/dist/utils/featureWarnings.js.map +1 -0
  201. package/dist/utils/formUtils.js +161 -51
  202. package/dist/utils/formUtils.js.map +1 -0
  203. package/dist/utils/gradientUtils.js +120 -0
  204. package/dist/utils/gradientUtils.js.map +1 -0
  205. package/dist/utils/invitationEvents.js +45 -0
  206. package/dist/utils/invitationEvents.js.map +1 -0
  207. package/dist/utils/moduleLoaders.js +275 -0
  208. package/dist/utils/moduleLoaders.js.map +1 -0
  209. package/dist/utils/moduleLoaders.web.js +72 -0
  210. package/dist/utils/moduleLoaders.web.js.map +1 -0
  211. package/dist/utils/nameUtils.js +51 -0
  212. package/dist/utils/nameUtils.js.map +1 -0
  213. package/dist/utils/themeUtils.js +117 -32
  214. package/dist/utils/themeUtils.js.map +1 -0
  215. package/dist/vortexInvite.js +78 -167
  216. package/dist/vortexInvite.js.map +1 -0
  217. package/package.json +69 -31
  218. package/dist/components/Clipboard.js +0 -64
  219. package/dist/shared/api.js +0 -90
  220. package/dist/tests/TestVortexInvite.js +0 -134
  221. package/dist/types/components/Clipboard.d.ts +0 -16
  222. package/dist/types/components/Clipboard.d.ts.map +0 -1
  223. package/dist/types/shared/InvitationResult.d.ts +0 -24
  224. package/dist/types/shared/InvitationResult.d.ts.map +0 -1
  225. package/dist/types/shared/api.d.ts +0 -14
  226. package/dist/types/shared/api.d.ts.map +0 -1
  227. package/dist/types/tests/TestVortexInvite.d.ts +0 -4
  228. package/dist/types/tests/TestVortexInvite.d.ts.map +0 -1
@@ -0,0 +1,572 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.VrtxOutgoingInvitations = VrtxOutgoingInvitations;
46
+ const react_1 = __importStar(require("react"));
47
+ const react_native_1 = require("react-native");
48
+ const analytics_client_1 = require("@teamvortexsoftware/analytics-client");
49
+ const invitationEvents_1 = require("../utils/invitationEvents");
50
+ const isWeb = react_native_1.Platform.OS === 'web';
51
+ // Parse CSS linear-gradient to extract first color for fallback on native
52
+ function parseGradientFirstColor(gradientString) {
53
+ if (!gradientString || !gradientString.includes('linear-gradient')) {
54
+ return null;
55
+ }
56
+ const stopsRegex = /(rgba?\([^)]+\)|#[0-9a-fA-F]{3,8}|[a-z]+)\s+(\d+)%/i;
57
+ const match = stopsRegex.exec(gradientString);
58
+ if (match) {
59
+ return match[1].trim();
60
+ }
61
+ return null;
62
+ }
63
+ // Animated item wrapper for fade-out effect
64
+ function AnimatedInvitationItem({ item, renderContent, onRemove, }) {
65
+ const fadeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
66
+ const heightAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
67
+ const animateOut = (0, react_1.useCallback)(() => {
68
+ // Use sequential animations to avoid mixing useNativeDriver: true and false
69
+ react_native_1.Animated.timing(fadeAnim, {
70
+ toValue: 0,
71
+ duration: 150,
72
+ useNativeDriver: true,
73
+ }).start(() => {
74
+ onRemove(item.id);
75
+ });
76
+ }, [fadeAnim, item.id, onRemove]);
77
+ return (<react_native_1.Animated.View style={{
78
+ opacity: fadeAnim,
79
+ }}>
80
+ {renderContent(Object.assign(Object.assign({}, item), { metadata: Object.assign(Object.assign({}, item.metadata), { animateOut }) }))}
81
+ </react_native_1.Animated.View>);
82
+ }
83
+ function VrtxOutgoingInvitations({ block, outgoingInvitationsConfig, apiUrl, jwt, triggerHaptic, theme, onAnalyticsEvent, }) {
84
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
85
+ // Extract mock invitations from config (internal preview use only)
86
+ const _mockInvitations = outgoingInvitationsConfig === null || outgoingInvitationsConfig === void 0 ? void 0 : outgoingInvitationsConfig._mockInvitations;
87
+ // Local state for managing the displayed invitations (for animate-out)
88
+ const [displayedInvitations, setDisplayedInvitations] = (0, react_1.useState)([]);
89
+ const [actionInProgress, setActionInProgress] = (0, react_1.useState)(null);
90
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
91
+ const [error, setError] = (0, react_1.useState)(null);
92
+ // Use mock mode if _mockInvitations provided (preview), otherwise API mode
93
+ const isMockMode = !!_mockInvitations;
94
+ // Fetch invitations from API
95
+ const fetchInvitations = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
96
+ var _a;
97
+ if (!apiUrl || !jwt)
98
+ return;
99
+ setIsLoading(true);
100
+ setError(null);
101
+ try {
102
+ const response = yield fetch(`${apiUrl}/api/v1/invitations/sent`, {
103
+ method: 'GET',
104
+ headers: {
105
+ Authorization: `Bearer ${jwt}`,
106
+ 'Content-Type': 'application/json',
107
+ },
108
+ });
109
+ if (!response.ok) {
110
+ throw new Error(`Failed to fetch invitations: ${response.status}`);
111
+ }
112
+ const data = yield response.json();
113
+ // Filter out shareable link invitations (targetType "share") - matches iOS SDK
114
+ const filtered = (((_a = data.data) === null || _a === void 0 ? void 0 : _a.invitations) || []).filter((inv) => {
115
+ var _a, _b;
116
+ const targetType = (_b = (_a = inv.targets) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.targetType;
117
+ return targetType !== 'share';
118
+ });
119
+ const mappedInvitations = filtered.map((inv) => {
120
+ var _a, _b, _c;
121
+ // Extract target (invitee) info from the targets array - matches iOS SDK
122
+ const target = (_a = inv.targets) === null || _a === void 0 ? void 0 : _a[0];
123
+ const targetName = target === null || target === void 0 ? void 0 : target.targetName;
124
+ const targetValue = target === null || target === void 0 ? void 0 : target.targetValue;
125
+ // Use targetName as display name if available, otherwise fall back to targetValue
126
+ const name = (_c = (_b = targetName !== null && targetName !== void 0 ? targetName : targetValue) !== null && _b !== void 0 ? _b : inv.senderIdentifier) !== null && _c !== void 0 ? _c : 'Unknown';
127
+ return {
128
+ id: inv.id,
129
+ name,
130
+ userId: targetValue,
131
+ avatarUrl: target === null || target === void 0 ? void 0 : target.targetAvatarUrl,
132
+ isVortexInvitation: true,
133
+ metadata: inv,
134
+ };
135
+ });
136
+ // Merge config invitations with API invitations, deduplicating by userId.
137
+ const configInvitations = (outgoingInvitationsConfig === null || outgoingInvitationsConfig === void 0 ? void 0 : outgoingInvitationsConfig.invitations) || [];
138
+ const apiUserIds = new Set(mappedInvitations
139
+ .filter((inv) => inv.userId)
140
+ .map((inv) => inv.userId));
141
+ const dedupedConfig = configInvitations.filter((inv) => !inv.userId || !apiUserIds.has(inv.userId));
142
+ setDisplayedInvitations([...dedupedConfig, ...mappedInvitations]);
143
+ }
144
+ catch (err) {
145
+ console.error('[VrtxOutgoingInvitations] Fetch failed:', err);
146
+ setError(err instanceof Error ? err.message : 'Failed to load invitations');
147
+ }
148
+ finally {
149
+ setIsLoading(false);
150
+ }
151
+ }), [apiUrl, jwt, outgoingInvitationsConfig === null || outgoingInvitationsConfig === void 0 ? void 0 : outgoingInvitationsConfig.invitations]);
152
+ // Revoke invitation via API
153
+ const revokeInvitation = (0, react_1.useCallback)((invitationId) => __awaiter(this, void 0, void 0, function* () {
154
+ if (!apiUrl || !jwt)
155
+ return false;
156
+ try {
157
+ const response = yield fetch(`${apiUrl}/api/v1/invitations/${invitationId}`, {
158
+ method: 'DELETE',
159
+ headers: {
160
+ Authorization: `Bearer ${jwt}`,
161
+ 'Content-Type': 'application/json',
162
+ },
163
+ });
164
+ if (!response.ok && response.status !== 204) {
165
+ throw new Error(`Failed to revoke invitation: ${response.status}`);
166
+ }
167
+ return true;
168
+ }
169
+ catch (err) {
170
+ console.error('[VrtxOutgoingInvitations] Revoke failed:', err);
171
+ return false;
172
+ }
173
+ }), [apiUrl, jwt]);
174
+ // Fetch invitations on mount - use mock data in preview mode, otherwise fetch from API
175
+ (0, react_1.useEffect)(() => {
176
+ if (isMockMode) {
177
+ setDisplayedInvitations(_mockInvitations || []);
178
+ }
179
+ else {
180
+ fetchInvitations();
181
+ }
182
+ }, [isMockMode, _mockInvitations, fetchInvitations]);
183
+ // Subscribe to invitation events to refresh the list when new invitations are created
184
+ (0, react_1.useEffect)(() => {
185
+ if (isMockMode)
186
+ return; // Don't subscribe in mock mode
187
+ const unsubscribe = (0, invitationEvents_1.subscribeToInvitationEvent)('invitationCreated', () => {
188
+ console.log('[VrtxOutgoingInvitations] Invitation created event received, refreshing...');
189
+ fetchInvitations();
190
+ });
191
+ return unsubscribe;
192
+ }, [isMockMode, fetchInvitations]);
193
+ // Extract customization from block settings (widget configuration), with defaults
194
+ const blockCustomizations = (_a = block === null || block === void 0 ? void 0 : block.settings) === null || _a === void 0 ? void 0 : _a.customizations;
195
+ const cancelButtonText = (_c = (_b = blockCustomizations === null || blockCustomizations === void 0 ? void 0 : blockCustomizations.cancelButton) === null || _b === void 0 ? void 0 : _b.textContent) !== null && _c !== void 0 ? _c : 'Cancel';
196
+ const emptyStateMessage = (_e = (_d = blockCustomizations === null || blockCustomizations === void 0 ? void 0 : blockCustomizations.emptyStateMessage) === null || _d === void 0 ? void 0 : _d.textContent) !== null && _e !== void 0 ? _e : 'No sent invitations';
197
+ // Confirmation dialog texts from widget configuration
198
+ const cancelConfirmTitle = (_g = (_f = blockCustomizations === null || blockCustomizations === void 0 ? void 0 : blockCustomizations.cancelConfirmTitle) === null || _f === void 0 ? void 0 : _f.textContent) !== null && _g !== void 0 ? _g : 'Cancel Invitation';
199
+ const cancelConfirmMessage = (_j = (_h = blockCustomizations === null || blockCustomizations === void 0 ? void 0 : blockCustomizations.cancelConfirmMessage) === null || _h === void 0 ? void 0 : _h.textContent) !== null && _j !== void 0 ? _j : 'Cancel invitation to {name}?';
200
+ const confirmButtonText = (_l = (_k = blockCustomizations === null || blockCustomizations === void 0 ? void 0 : blockCustomizations.confirmButtonText) === null || _k === void 0 ? void 0 : _k.textContent) !== null && _l !== void 0 ? _l : 'Confirm';
201
+ const dismissButtonText = (_o = (_m = blockCustomizations === null || blockCustomizations === void 0 ? void 0 : blockCustomizations.dismissButtonText) === null || _m === void 0 ? void 0 : _m.textContent) !== null && _o !== void 0 ? _o : 'Keep';
202
+ // Helper to get theme option value from block.theme.options
203
+ const getBlockThemeValue = (key) => {
204
+ var _a;
205
+ const options = (_a = block === null || block === void 0 ? void 0 : block.theme) === null || _a === void 0 ? void 0 : _a.options;
206
+ if (!options || !Array.isArray(options))
207
+ return undefined;
208
+ const option = options.find((opt) => opt.key === key);
209
+ return (option === null || option === void 0 ? void 0 : option.value) || undefined;
210
+ };
211
+ // Theme colors with defaults
212
+ const colors = {
213
+ primaryBackground: (_p = theme === null || theme === void 0 ? void 0 : theme.primaryBackground) !== null && _p !== void 0 ? _p : '#6291d5',
214
+ primaryForeground: (_q = theme === null || theme === void 0 ? void 0 : theme.primaryForeground) !== null && _q !== void 0 ? _q : '#ffffff',
215
+ secondaryBackground: (_r = theme === null || theme === void 0 ? void 0 : theme.secondaryBackground) !== null && _r !== void 0 ? _r : '#ffffff',
216
+ secondaryForeground: (_s = theme === null || theme === void 0 ? void 0 : theme.secondaryForeground) !== null && _s !== void 0 ? _s : '#353e5c',
217
+ foreground: (_t = theme === null || theme === void 0 ? void 0 : theme.foreground) !== null && _t !== void 0 ? _t : '#334153',
218
+ border: (_u = theme === null || theme === void 0 ? void 0 : theme.border) !== null && _u !== void 0 ? _u : '#cccccc',
219
+ };
220
+ // Button styles from block.theme.options (microTheme)
221
+ const cancelButtonStyles = {
222
+ background: getBlockThemeValue('--vrtx-outgoing-invitations-cancel-button-background') ||
223
+ colors.secondaryBackground,
224
+ color: getBlockThemeValue('--vrtx-outgoing-invitations-cancel-button-color') ||
225
+ colors.secondaryForeground,
226
+ borderRadius: getBlockThemeValue('--vrtx-outgoing-invitations-cancel-button-border-radius'),
227
+ border: getBlockThemeValue('--vrtx-outgoing-invitations-cancel-button-border'),
228
+ padding: getBlockThemeValue('--vrtx-outgoing-invitations-cancel-button-padding'),
229
+ fontSize: getBlockThemeValue('--vrtx-outgoing-invitations-cancel-button-font-size'),
230
+ fontWeight: getBlockThemeValue('--vrtx-outgoing-invitations-cancel-button-font-weight'),
231
+ };
232
+ // Avatar/initials styles from block.theme.options (microTheme)
233
+ const avatarStyles = {
234
+ background: getBlockThemeValue('--vrtx-outgoing-invitations-avatar-background') ||
235
+ colors.primaryBackground,
236
+ color: getBlockThemeValue('--vrtx-outgoing-invitations-avatar-color') || colors.primaryForeground,
237
+ };
238
+ // Contact name styles from block.theme.options (microTheme)
239
+ const nameStyles = {
240
+ color: getBlockThemeValue('--vrtx-outgoing-invitations-name-color') || colors.foreground,
241
+ fontFamily: getBlockThemeValue('--vrtx-outgoing-invitations-name-font-family'),
242
+ fontSize: getBlockThemeValue('--vrtx-outgoing-invitations-name-font-size'),
243
+ fontWeight: getBlockThemeValue('--vrtx-outgoing-invitations-name-font-weight'),
244
+ };
245
+ // Subtitle styles from block.theme.options (microTheme)
246
+ const subtitleStyles = {
247
+ color: getBlockThemeValue('--vrtx-outgoing-invitations-subtitle-color') ||
248
+ colors.secondaryForeground,
249
+ fontFamily: getBlockThemeValue('--vrtx-outgoing-invitations-subtitle-font-family'),
250
+ fontSize: getBlockThemeValue('--vrtx-outgoing-invitations-subtitle-font-size'),
251
+ };
252
+ // Title styles from block.theme.options (microTheme)
253
+ const titleStyles = {
254
+ color: getBlockThemeValue('--vrtx-outgoing-invitations-title-color') || colors.foreground,
255
+ fontFamily: getBlockThemeValue('--vrtx-outgoing-invitations-title-font-family'),
256
+ fontSize: getBlockThemeValue('--vrtx-outgoing-invitations-title-font-size'),
257
+ fontWeight: getBlockThemeValue('--vrtx-outgoing-invitations-title-font-weight'),
258
+ };
259
+ // Remove invitation from displayed list (after animation)
260
+ const handleRemoveFromDisplay = (0, react_1.useCallback)((id) => {
261
+ setDisplayedInvitations((prev) => prev.filter((inv) => inv.id !== id));
262
+ }, []);
263
+ // Show confirmation dialog
264
+ const showConfirmation = (0, react_1.useCallback)((title, message, onConfirm) => {
265
+ if (isWeb) {
266
+ // Web: use window.confirm
267
+ const confirmed = window.confirm(message);
268
+ if (confirmed) {
269
+ onConfirm();
270
+ }
271
+ }
272
+ else {
273
+ // Native: use Alert
274
+ react_native_1.Alert.alert(title, message, [
275
+ {
276
+ text: dismissButtonText,
277
+ style: 'cancel',
278
+ },
279
+ {
280
+ text: confirmButtonText,
281
+ onPress: onConfirm,
282
+ },
283
+ ]);
284
+ }
285
+ }, [confirmButtonText, dismissButtonText]);
286
+ // Handle Cancel button press
287
+ const handleCancel = (0, react_1.useCallback)((invitation, animateOut) => __awaiter(this, void 0, void 0, function* () {
288
+ const message = cancelConfirmMessage.replace('{name}', invitation.name);
289
+ showConfirmation(cancelConfirmTitle, message, () => __awaiter(this, void 0, void 0, function* () {
290
+ setActionInProgress(invitation.id);
291
+ yield (triggerHaptic === null || triggerHaptic === void 0 ? void 0 : triggerHaptic('light'));
292
+ // Emit analytics event for delete button click
293
+ onAnalyticsEvent === null || onAnalyticsEvent === void 0 ? void 0 : onAnalyticsEvent({
294
+ name: analytics_client_1.EventNames.OUTBOUND_INVITATION_DELETE_CLICKED,
295
+ payload: { invitationId: invitation.id, inviteeName: invitation.name },
296
+ });
297
+ try {
298
+ // Call the callback if provided and check return value
299
+ let shouldProceed = true;
300
+ if (outgoingInvitationsConfig === null || outgoingInvitationsConfig === void 0 ? void 0 : outgoingInvitationsConfig.onCancel) {
301
+ const result = yield outgoingInvitationsConfig.onCancel(invitation);
302
+ // If callback returns false explicitly, don't proceed
303
+ if (result === false) {
304
+ shouldProceed = false;
305
+ }
306
+ }
307
+ if (!shouldProceed) {
308
+ setActionInProgress(null);
309
+ return;
310
+ }
311
+ // In mock mode (web), skip API call AND don't remove the invitation (no-op)
312
+ if (isMockMode) {
313
+ // No-op in mock mode
314
+ }
315
+ else {
316
+ // Real mode: call DELETE endpoint and remove on success
317
+ const success = yield revokeInvitation(invitation.id);
318
+ if (success) {
319
+ // Animate out after successful action
320
+ if (animateOut) {
321
+ animateOut();
322
+ }
323
+ else {
324
+ handleRemoveFromDisplay(invitation.id);
325
+ }
326
+ }
327
+ }
328
+ }
329
+ catch (err) {
330
+ console.error('[VrtxOutgoingInvitations] Cancel failed:', err);
331
+ }
332
+ finally {
333
+ setActionInProgress(null);
334
+ }
335
+ }));
336
+ }), [
337
+ outgoingInvitationsConfig,
338
+ revokeInvitation,
339
+ triggerHaptic,
340
+ cancelConfirmTitle,
341
+ cancelConfirmMessage,
342
+ showConfirmation,
343
+ handleRemoveFromDisplay,
344
+ onAnalyticsEvent,
345
+ ]);
346
+ // Helper to parse CSS padding string to React Native padding object
347
+ const parsePadding = (paddingStr) => {
348
+ if (!paddingStr)
349
+ return {};
350
+ const parts = paddingStr.trim().split(/\s+/);
351
+ if (parts.length === 1) {
352
+ const val = parseInt(parts[0], 10);
353
+ return isNaN(val) ? {} : { paddingVertical: val, paddingHorizontal: val };
354
+ }
355
+ if (parts.length === 2) {
356
+ const vertical = parseInt(parts[0], 10);
357
+ const horizontal = parseInt(parts[1], 10);
358
+ return Object.assign(Object.assign({}, (isNaN(vertical) ? {} : { paddingVertical: vertical })), (isNaN(horizontal) ? {} : { paddingHorizontal: horizontal }));
359
+ }
360
+ return {};
361
+ };
362
+ // Helper to parse border string (e.g., "1px solid #ccc")
363
+ const parseBorder = (borderStr) => {
364
+ if (!borderStr)
365
+ return {};
366
+ const match = borderStr.match(/^(\d+)px\s+(\w+)\s+(.+)$/);
367
+ if (match) {
368
+ return {
369
+ borderWidth: parseInt(match[1], 10),
370
+ borderColor: match[3],
371
+ };
372
+ }
373
+ return {};
374
+ };
375
+ // Render avatar or initials
376
+ const renderAvatar = (invitation) => {
377
+ if (invitation.avatarUrl) {
378
+ return <react_native_1.Image source={{ uri: invitation.avatarUrl }} style={styles.avatar}/>;
379
+ }
380
+ // Generate initials from name
381
+ const initials = invitation.name
382
+ .split(' ')
383
+ .map((part) => part[0])
384
+ .join('')
385
+ .toUpperCase()
386
+ .slice(0, 2);
387
+ // Handle avatar background with gradient support
388
+ const avatarBackground = avatarStyles.background;
389
+ const isAvatarGradient = avatarBackground === null || avatarBackground === void 0 ? void 0 : avatarBackground.includes('linear-gradient');
390
+ const avatarBgStyle = {};
391
+ if (isWeb && avatarBackground) {
392
+ avatarBgStyle.background = avatarBackground;
393
+ }
394
+ else if (isAvatarGradient && avatarBackground) {
395
+ const fallbackColor = parseGradientFirstColor(avatarBackground);
396
+ avatarBgStyle.backgroundColor = fallbackColor || colors.primaryBackground;
397
+ }
398
+ else {
399
+ avatarBgStyle.backgroundColor = avatarBackground || colors.primaryBackground;
400
+ }
401
+ return (<react_native_1.View style={[styles.avatarPlaceholder, avatarBgStyle]}>
402
+ <react_native_1.Text style={[styles.avatarInitials, { color: avatarStyles.color }]}>{initials}</react_native_1.Text>
403
+ </react_native_1.View>);
404
+ };
405
+ // Build button style with gradient support
406
+ const buildButtonStyle = (buttonStyles, fallbackBg) => {
407
+ const backgroundValue = buttonStyles.background;
408
+ const isGradient = backgroundValue === null || backgroundValue === void 0 ? void 0 : backgroundValue.includes('linear-gradient');
409
+ const dynamicButtonStyle = Object.assign(Object.assign(Object.assign({}, (buttonStyles.borderRadius
410
+ ? { borderRadius: parseInt(buttonStyles.borderRadius, 10) }
411
+ : {})), parsePadding(buttonStyles.padding)), parseBorder(buttonStyles.border));
412
+ if (isWeb && backgroundValue) {
413
+ dynamicButtonStyle.background = backgroundValue;
414
+ }
415
+ else if (isGradient && backgroundValue) {
416
+ const fallbackColor = parseGradientFirstColor(backgroundValue);
417
+ dynamicButtonStyle.backgroundColor = fallbackColor || fallbackBg;
418
+ }
419
+ else {
420
+ dynamicButtonStyle.backgroundColor = backgroundValue || fallbackBg;
421
+ }
422
+ return dynamicButtonStyle;
423
+ };
424
+ // Render a single invitation item
425
+ const renderInvitationContent = (item) => {
426
+ var _a;
427
+ const isLoading = actionInProgress === item.id;
428
+ const animateOut = (_a = item.metadata) === null || _a === void 0 ? void 0 : _a.animateOut;
429
+ // Build dynamic button style
430
+ const cancelButtonDynamicStyle = buildButtonStyle(cancelButtonStyles, colors.secondaryBackground);
431
+ // Build dynamic text style
432
+ const cancelTextStyle = Object.assign(Object.assign({ color: cancelButtonStyles.color }, (cancelButtonStyles.fontSize
433
+ ? { fontSize: parseInt(cancelButtonStyles.fontSize, 10) }
434
+ : {})), (cancelButtonStyles.fontWeight ? { fontWeight: cancelButtonStyles.fontWeight } : {}));
435
+ // Build dynamic name style
436
+ const dynamicNameStyle = Object.assign(Object.assign(Object.assign({ color: nameStyles.color }, (nameStyles.fontFamily ? { fontFamily: nameStyles.fontFamily } : {})), (nameStyles.fontSize ? { fontSize: parseInt(nameStyles.fontSize, 10) } : {})), (nameStyles.fontWeight ? { fontWeight: nameStyles.fontWeight } : {}));
437
+ // Build dynamic subtitle style
438
+ const dynamicSubtitleStyle = Object.assign(Object.assign({ color: subtitleStyles.color }, (subtitleStyles.fontFamily ? { fontFamily: subtitleStyles.fontFamily } : {})), (subtitleStyles.fontSize ? { fontSize: parseInt(subtitleStyles.fontSize, 10) } : {}));
439
+ return (<react_native_1.View style={styles.invitationItem}>
440
+ {renderAvatar(item)}
441
+ <react_native_1.View style={styles.invitationInfo}>
442
+ <react_native_1.Text style={[styles.invitationName, dynamicNameStyle]} numberOfLines={1}>
443
+ {item.name}
444
+ </react_native_1.Text>
445
+ {(() => {
446
+ var _a;
447
+ const displaySubtitle = (_a = outgoingInvitationsConfig === null || outgoingInvitationsConfig === void 0 ? void 0 : outgoingInvitationsConfig.getSubtitle) === null || _a === void 0 ? void 0 : _a.call(outgoingInvitationsConfig, item);
448
+ return displaySubtitle ? (<react_native_1.Text style={[styles.invitationSubtitle, dynamicSubtitleStyle]} numberOfLines={1}>
449
+ {displaySubtitle}
450
+ </react_native_1.Text>) : null;
451
+ })()}
452
+ </react_native_1.View>
453
+ {/* Cancel button */}
454
+ <react_native_1.TouchableOpacity style={[styles.actionButton, cancelButtonDynamicStyle]} onPress={() => handleCancel(item, animateOut)} disabled={isLoading} activeOpacity={0.7}>
455
+ {isLoading ? (<react_native_1.ActivityIndicator size="small" color={cancelButtonStyles.color}/>) : (<react_native_1.Text style={[styles.actionButtonText, cancelTextStyle]}>{cancelButtonText}</react_native_1.Text>)}
456
+ </react_native_1.TouchableOpacity>
457
+ </react_native_1.View>);
458
+ };
459
+ // Render item with animation wrapper
460
+ const renderItem = ({ item }) => {
461
+ return (<AnimatedInvitationItem item={item} renderContent={renderInvitationContent} onRemove={handleRemoveFromDisplay}/>);
462
+ };
463
+ // Loading state (API mode)
464
+ if (isLoading) {
465
+ return (<react_native_1.View style={styles.container}>
466
+ <react_native_1.ActivityIndicator size="large" color={colors.primaryBackground}/>
467
+ </react_native_1.View>);
468
+ }
469
+ // Error state (API mode)
470
+ if (error) {
471
+ return (<react_native_1.View style={styles.container}>
472
+ <react_native_1.Text style={[styles.errorText, { color: '#dc2626' }]}>{error}</react_native_1.Text>
473
+ </react_native_1.View>);
474
+ }
475
+ // Empty state - render nothing (no-op component with no height)
476
+ if (displayedInvitations.length === 0) {
477
+ return null;
478
+ }
479
+ // Get title from block attributes (configured in editor as "Title")
480
+ const title = (_v = block === null || block === void 0 ? void 0 : block.attributes) === null || _v === void 0 ? void 0 : _v.title;
481
+ // Build dynamic title style
482
+ const dynamicTitleStyle = Object.assign(Object.assign(Object.assign({ color: titleStyles.color }, (titleStyles.fontFamily ? { fontFamily: titleStyles.fontFamily } : {})), (titleStyles.fontSize ? { fontSize: parseInt(titleStyles.fontSize, 10) } : {})), (titleStyles.fontWeight ? { fontWeight: titleStyles.fontWeight } : {}));
483
+ // Main view: Invitations list
484
+ // Note: Using View + map instead of FlatList to avoid "VirtualizedLists should never be nested" warning
485
+ // when this component is rendered inside a ScrollView (which InviteFormCore uses)
486
+ return (<react_native_1.View style={styles.listContainer}>
487
+ {title && (<react_native_1.Text style={[styles.title, dynamicTitleStyle]}>{title}</react_native_1.Text>)}
488
+ <react_native_1.View style={styles.listContent}>
489
+ {displayedInvitations.map((item) => (<react_native_1.View key={item.id}>
490
+ {renderItem({ item })}
491
+ </react_native_1.View>))}
492
+ </react_native_1.View>
493
+ </react_native_1.View>);
494
+ }
495
+ const styles = react_native_1.StyleSheet.create({
496
+ container: {
497
+ padding: 16,
498
+ alignItems: 'center',
499
+ justifyContent: 'center',
500
+ minHeight: 120,
501
+ },
502
+ listContainer: {
503
+ flex: 1,
504
+ },
505
+ title: {
506
+ fontSize: 16,
507
+ fontWeight: '600',
508
+ marginBottom: 12,
509
+ },
510
+ placeholderText: {
511
+ fontSize: 14,
512
+ textAlign: 'center',
513
+ },
514
+ emptyText: {
515
+ fontSize: 14,
516
+ textAlign: 'center',
517
+ },
518
+ errorText: {
519
+ fontSize: 14,
520
+ textAlign: 'center',
521
+ },
522
+ listContent: {
523
+ paddingBottom: 16,
524
+ },
525
+ invitationItem: {
526
+ flexDirection: 'row',
527
+ alignItems: 'center',
528
+ paddingVertical: 12,
529
+ },
530
+ avatar: {
531
+ width: 44,
532
+ height: 44,
533
+ borderRadius: 22,
534
+ },
535
+ avatarPlaceholder: {
536
+ width: 44,
537
+ height: 44,
538
+ borderRadius: 22,
539
+ alignItems: 'center',
540
+ justifyContent: 'center',
541
+ },
542
+ avatarInitials: {
543
+ fontSize: 16,
544
+ fontWeight: '600',
545
+ },
546
+ invitationInfo: {
547
+ flex: 1,
548
+ marginLeft: 12,
549
+ marginRight: 12,
550
+ },
551
+ invitationName: {
552
+ fontSize: 16,
553
+ fontWeight: '500',
554
+ },
555
+ invitationSubtitle: {
556
+ fontSize: 13,
557
+ marginTop: 2,
558
+ },
559
+ actionButton: {
560
+ paddingHorizontal: 16,
561
+ paddingVertical: 8,
562
+ borderRadius: 8,
563
+ minWidth: 80,
564
+ alignItems: 'center',
565
+ justifyContent: 'center',
566
+ },
567
+ actionButtonText: {
568
+ fontSize: 14,
569
+ fontWeight: '600',
570
+ },
571
+ });
572
+ //# sourceMappingURL=VrtxOutgoingInvitations.js.map