@teamvortexsoftware/vortex-react
v0.2.24
Published
Vortex Components
Readme
Vortex React Component
High-performance React component for Vortex invitations with intelligent provider integration.
🚀 Quick Start
npm install @teamvortexsoftware/vortex-reactBasic Usage (Standalone)
import { VortexInvite } from '@teamvortexsoftware/vortex-react';
function MyComponent() {
return (
<VortexInvite
componentId="00000000-0000-0000-0000-000000000000"
jwt="eyJhbGciOiJIUzI1NiIs..."
isLoading={false}
scope="team-123"
scopeType="team"
onInvite={handleInvite}
/>
);
}📋 Fetching JWT
You need to fetch a JWT token from your backend before rendering the widget:
import { VortexInvite } from '@teamvortexsoftware/vortex-react';
import { useState, useEffect } from 'react';
function MyComponent() {
const [jwt, setJwt] = useState<string>('');
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
fetch('/api/vortex/jwt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
.then(data => {
setJwt(data.jwt);
setIsLoading(false);
})
.catch(error => {
console.error('Failed to fetch JWT:', error);
setIsLoading(false);
});
}, []);
return (
<VortexInvite
componentId="00000000-0000-0000-0000-000000000000"
jwt={jwt}
isLoading={isLoading}
scope="team-123"
scopeType="team"
onInvite={handleInvite}
/>
);
}🔐 Signature Authentication (Alternative to JWT)
Instead of fetching a JWT token, you can use HMAC signature authentication—a simpler alternative for many use cases:
import { VortexInvite } from '@teamvortexsoftware/vortex-react';
function MyComponent() {
return (
<VortexInvite
componentId="my-widget"
user={{ userId: "user-123", userEmail: "[email protected]" }}
signature={signatureFromBackend}
scope="team-123"
scopeType="team"
/>
);
}Generate the signature on your backend using any Vortex SDK's sign() method. The signature format is kid:hexdigest (e.g., "key-abc123:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08").
See your backend SDK's README for details on generating signatures.
📋 Complete Props Reference
VortexInvite (Traditional)
| Prop | Type | Required | Description | Docs |
| ----------- | --------- | -------- | ---------------------------- | ----------------------------------------------------------------------------- |
| componentId | string | ✅ | Component identifier | docs |
| jwt | string | ✅ | JWT token for authentication | docs |
| scope | string | ✅ | Scope identifier (e.g., team ID) | docs |
| scopeType | string | ✅ | Scope type (e.g., "team") | docs |
| isLoading | boolean | ❌ | Loading state indicator | docs |
VortexInviteSimple (Local Wrapper Pattern)
| Prop | Type | Required | Description | Docs |
| ------------------------- | ------------------------ | -------- | ------------------------------------------- | ------------------------------------------------------------------------------------------- |
| componentId | string | ✅ | Component identifier | docs |
| scope | string | ✅ | Scope identifier (e.g., team ID) | docs |
| scopeType | string | ✅ | Scope type (e.g., "team") | docs |
| jwt | string | ❌ | Auto-provided by your wrapper component | docs |
| isLoading | boolean | ❌ | Auto-provided by your wrapper component | docs |
| onEvent | function | ❌ | Event handler for component events | docs |
| onSubmit | function | ❌ | Form submission handler | |
| onSubmitSuccess | (data: VortexInviteSubmitSuccess) => void | ❌ | Called when the invitation is created successfully. Suppresses the built-in success UI. | |
| onSubmitError | (data: VortexInviteSubmitError) => void | ❌ | Called when submission fails. Suppresses the built-in error UI. data.errorCode is a VortexInviteErrorCode. | |
| onInvite | function | ❌ | Invitation completion handler | docs |
| onError | function | ❌ | Error handler | |
| emailValidationFunction | function | ❌ | Custom email validation | docs |
| analyticsSegmentation | Record<string, any> | ❌ | Analytics tracking data | |
| userEmailsInGroup | string[] | ❌ | Pre-populated email list | docs |
| pymk | PeopleYouMayKnow[] | ❌ | People You May Know suggestions | docs |
| templateVariables | Record<string, string> | ❌ | Template variables | docs |
| googleAppClientId | string | ❌ | Google integration client ID | docs |
| googleAppApiKey | string | ❌ | ⚠️ Deprecated - No longer required. Google Contacts import now uses only OAuth (googleAppClientId). | |
🔄 Backward Compatibility
100% backward compatible - existing implementations work unchanged:
// ✅ This still works exactly as before
<VortexInvite
componentId="00000000-0000-0000-0000-000000000000"
jwt={jwt}
isLoading={loading}
scope="team-123"
scopeType="team"
// ... all other props
/>📖 Advanced Examples
With Custom Submit Callbacks
Use onSubmitSuccess and onSubmitError to handle submission outcomes in your own UI. When either callback is provided the built-in success/error banner inside the widget is suppressed.
import { VortexInvite, VortexInviteErrorCode } from '@teamvortexsoftware/vortex-react';
import type { VortexInviteSubmitSuccess, VortexInviteSubmitError } from '@teamvortexsoftware/vortex-react';
<VortexInvite
componentId="00000000-0000-0000-0000-000000000000"
onSubmitSuccess={(data: VortexInviteSubmitSuccess) => {
console.log('Invitation created:', data.result);
showToast('Invitation sent!');
}}
onSubmitError={(data: VortexInviteSubmitError) => {
if (data.errorCode === VortexInviteErrorCode.alreadyInvited) {
showToast('That person has already been invited.');
} else if (data.errorCode === VortexInviteErrorCode.alreadyAMember) {
showToast('That person is already a member.');
} else if (data.errorCode === VortexInviteErrorCode.emailDomainRestriction) {
showToast('Invitations are restricted to specific domains.');
} else {
showToast(`Error: ${data.message}`);
}
}}
/>With Custom Event Handlers
<VortexInvite
componentId="advanced-widget"
onInvite={(data) => {
console.log('Invitation sent:', data);
trackAnalyticsEvent('invitation_sent', data);
}}
onError={(error) => {
console.error('Invitation error:', error);
showErrorToast(error.message);
}}
/>With Custom Validation
<VortexInvite
componentId="validated-widget"
emailValidationFunction={async (email) => {
const isValid = await validateEmailInSystem(email);
return {
valid: isValid,
message: isValid ? 'Valid' : 'Email not found in system',
};
}}
/>With People You May Know (PYMK)
<VortexInvite
componentId="pymk-widget"
pymk={[
{
internalId: '123',
name: 'John Doe',
mutualContactCount: 5,
avatarUrl: 'https://example.com/avatar1.jpg'
},
{
internalId: '456',
name: 'Jane Smith',
mutualContactCount: 3,
avatarUrl: 'https://example.com/avatar2.jpg'
},
{
internalId: '789',
name: 'Bob Johnson',
mutualContactCount: 1
}
]}
/>The pymk prop allows you to surface suggested connections to users. The widget will automatically sort them by mutualContactCount (descending). The avatarUrl is optional.
Mixed Provider and Explicit Props
<VortexProvider config={{ apiBaseUrl: '/api/vortex' }}>
<VortexInvite
componentId="hybrid-widget"
// jwt, isLoading automatically from provider
scope="workspace-456"
scopeType="workspace"
analyticsSegmentation={customAnalytics} // Custom tracking
onInvite={handleInvite}
/>
</VortexProvider>🛠️ TypeScript Support
Full TypeScript support with exported interfaces:
import type { VortexInviteProps } from '@teamvortexsoftware/vortex-react';
const MyComponent: React.FC<{ config: VortexInviteProps }> = ({ config }) => {
return <VortexInvite {...config} />;
};🚨 Error Handling
The component gracefully handles all scenarios:
- ✅ No Provider: Uses explicit props only
- ✅ Provider Error: Falls back to explicit props
- ✅ Missing Props: Safe defaults applied
- ✅ Mixed Usage: Explicit props override provider
🔧 Best Practices
1. Dead Simple with Provider
<VortexProvider config={{ apiBaseUrl: '/api/vortex' }}>
{/* All components automatically get jwt and isLoading */}
<VortexInviteWithProvider
componentId="widget-1"
scope="team-1"
scopeType="team"
onInvite={handleInvite1}
/>
<VortexInviteWithProvider
componentId="widget-2"
scope="team-2"
scopeType="team"
onInvite={handleInvite2}
/>
<VortexInviteWithProvider
componentId="widget-3"
scope="workspace-1"
scopeType="workspace"
onInvite={handleInvite3}
/>
</VortexProvider>2. Override Provider Data When Needed
<VortexInviteWithProvider
componentId="special-widget"
scope="special-team"
scopeType="team"
jwt={customJWT} // Override provider JWT for this instance
// isLoading still comes from provider automatically
/>3. Standalone for Simple Cases
// No provider needed for simple, one-off usage
<VortexInvite
componentId="simple-widget"
jwt={staticJWT}
isLoading={false}
scope="team-123"
scopeType="team"
onInvite={handleInvite}
/>📦 What's New
- 🎯 Two Component Options - Choose
VortexInvite(traditional) orVortexInviteWithProvider(dead simple) - 🔄 100% Backward Compatible - Existing
VortexInviteusage works unchanged - ⚡ Dead Simple Experience -
VortexInviteWithProvidereliminates jwt and isLoading props - 🛡️ Explicit Override - Your props always override provider values
- 🚀 Zero Configuration - Just wrap with VortexProvider and use
VortexInviteWithProvider - 🔒 Safe Imports - No crashes when provider package isn't installed
🔧 Advanced: Multiple Widgets
If you have multiple Vortex widgets across your app and want to share JWT state, consider using @teamvortexsoftware/vortex-react-provider. However, for most apps with a single widget, the standalone pattern shown above is simpler and recommended.
See the provider package for details (note: in maintenance mode).
🔗 Related Packages
@teamvortexsoftware/vortex-nextjs-15-sdk- Next.js API route handlers@teamvortexsoftware/vortex-react-provider- Context provider (maintenance mode - use only for multiple widgets)
Need help? Check out the demo implementation for complete examples.
