@sparrowengg/integrations-templates-frontend
v7.0.0-bulkify.7
Published
A comprehensive React component library for building integration templates with field mapping, triggers, and data import functionality. Built with TypeScript and Twigs React components.
Downloads
4,144
Maintainers
Keywords
Readme
AppNest Templates - Integration Frontend Components
A comprehensive React component library for building integration templates with field mapping, triggers, and data import functionality. Built with TypeScript and Twigs React components.
📦 Installation
npm install @sparrowengg/integrations-templates-frontend
# or
yarn add @sparrowengg/integrations-templates-frontend🚀 Quick Start
import { Mapping, IntegrationTemplate } from '@sparrowengg/integrations-templates-frontend';
import '@sparrowengg/integrations-templates-frontend/dist/es/index.css';
// Basic mapping example
function MyMappingComponent() {
return (
<Mapping
integrationName="Salesforce"
// ... mapping props
/>
);
}🏗️ Architecture
The library is organized into several main modules:
- Mapping - Complex field mapping between survey data and integration fields
- Single Mapping - Simplified single-step mapping with configuration
- Triggers - Conditional trigger setup with filter conditions
- Contact Import - Contact data import with scheduling and mapping
- Dynamic Mapping - Dynamic field mapping capabilities
- Filter - Filter components for data filtering
- Cascader Dropdown - Hierarchical dropdown navigation
- Integration Template - Main wrapper component that orchestrates all modules
📚 Components Documentation
Mapping Component
The Mapping component provides a comprehensive interface for mapping survey fields to integration fields with support for complex configurations, event setup, and field validation.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| havingTypeDropdown | boolean | ✅ | Whether to show integration field type dropdown |
| onSaveMappingLoader | boolean | ✅ | Loading state for save operation |
| surveyDetails | SurveyDetails | ✅ | Survey information object |
| integrationName | string | ✅ | Name of the target integration |
| fields | FieldType[] | ✅ | Array of mapping field configurations |
| setFields | React.Dispatch<React.SetStateAction<FieldType[]>> | ✅ | State setter for fields |
| integrationFields | IntegrationFieldType[] | ✅ | Available integration fields |
| setIntegrationFields | React.Dispatch<React.SetStateAction<IntegrationFieldType[]>> | ✅ | State setter for integration fields |
| apiURL | string | ❌ | API endpoint URL (defaults to SurveySparrow URL) |
| token | string | ✅ | Authentication token |
| accounts | AccountsFieldType | ✅ | Account selection configuration |
| events | EventFieldType | ✅ | Event selection configuration |
| actions | ActionsFieldType | ✅ | Action selection configuration |
| isMappingPage | boolean | ✅ | Current page state (event setup vs mapping) |
| surveyType | string | ✅ | Type of survey |
| navigateMappingPage | (value?: boolean) => void | ✅ | Navigation handler |
| customList | CustomListFieldType | ✅ | Custom list configuration |
| oldResponse | OldResponseFieldType | ✅ | Old response handling configuration |
| hasPreviousMapping | boolean | ✅ | Whether previous mapping exists |
| onSaveHandler | () => void | ✅ | Save operation handler |
| editField | EditField \| null | ✅ | Field being edited |
| previousMappingHandler | (value?: boolean) => void | ✅ | Previous mapping navigation handler |
| onDeleteHandler | (id: string \| number) => void | ❌ | Delete field handler |
| draftHandler | (type: string \| null, editFieldId?: string \| number) => void | ✅ | Draft save handler |
| configuration | ConfigurationObject | ✅ | Configuration setup object |
FieldType
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| id | string | ✅ | Unique field identifier |
| surveySparrowField | SelectOption \| null | ✅ | Selected survey field |
| integrationField | SelectOption \| null | ✅ | Selected integration field |
| integrationFieldType | SelectOption \| null | ✅ | Integration field type |
| isEssentialField | boolean | ✅ | Whether field is required for integration |
| essentialFieldLabel | string | ❌ | Label for essential field |
| mappedType | SelectOption | ✅ | Field mapping type |
| defaultValue | FormFieldValue | ❌ | Default field value |
| dependency | Record<string, unknown> \| null | ✅ | Field dependencies |
Example
import { Mapping } from '@sparrowengg/integrations-templates-frontend';
function MappingExample() {
const [fields, setFields] = useState([
{
id: "email_field",
surveySparrowField: null,
integrationField: null,
integrationFieldType: null,
isEssentialField: true,
essentialFieldLabel: "Email",
mappedType: { label: "Email", value: "email" },
defaultValue: null,
dependency: null
}
]);
const [integrationFields, setIntegrationFields] = useState([
{
id: "email",
label: "Email Address",
value: "email",
type: "string"
}
]);
return (
<Mapping
havingTypeDropdown={true}
onSaveMappingLoader={false}
surveyDetails={{
surveyName: "Customer Feedback Survey",
surveyId: "survey_123"
}}
integrationName="Salesforce"
fields={fields}
setFields={setFields}
integrationFields={integrationFields}
setIntegrationFields={setIntegrationFields}
token="your_auth_token"
accounts={{
hasAccounts: true,
options: [{ label: "Main Account", value: "acc_1" }],
value: null,
onChangeHandler: (value) => console.log('Account selected:', value)
}}
events={{
hasEvents: true,
options: [{ label: "Contact Update", value: "contact_update" }],
value: null,
onChangeHandler: (value) => console.log('Event selected:', value)
}}
actions={{
hasActions: true,
options: [{ label: "Create Contact", value: "create_contact" }],
value: null,
onChangeHandler: (value) => console.log('Action selected:', value)
}}
isMappingPage={false}
surveyType="standard"
navigateMappingPage={(value) => console.log('Navigate to mapping:', value)}
customList={{ hasCustomList: false, value: null, onChangeHandler: () => {} }}
oldResponse={{ hasOldResponse: false, value: null, onChangeHandler: () => {} }}
hasPreviousMapping={false}
onSaveHandler={() => console.log('Mapping saved')}
editField={null}
previousMappingHandler={() => console.log('Go back')}
draftHandler={(type, id) => console.log('Save draft:', type, id)}
configuration={{
hasConfiguration: false,
configurationFields: [],
configuredFields: {},
title: "Event Configuration"
}}
/>
);
}SingleMapping Component
The SingleMapping component provides a simplified mapping interface with configuration steps, ideal for straightforward integration scenarios.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| hasPreviousMapping | boolean | ❌ | Whether previous mapping exists |
| integrationFields | IntegrationField[] | ✅ | Available integration fields |
| configuration | SingleMappingConfiguration | ✅ | Configuration object |
| token | string | ❌ | Authentication token |
| isMappingPage | boolean | ✅ | Current page state |
| navigateMappingPage | (value?: boolean) => void | ✅ | Navigation handler |
| apiURL | string | ❌ | API endpoint URL |
| surveyDetails | SurveyDetails | ✅ | Survey information |
| onSaveHandler | (fields: any) => void | ✅ | Save handler |
| setIntegrationFields | React.Dispatch<React.SetStateAction<any>> | ✅ | Integration fields setter |
| hasExistingMapping | boolean | ✅ | Whether existing mapping is present |
| importResponse | ImportResponse | ✅ | Import response configuration |
| editField | any | ❌ | Field being edited |
| previousMappingHandler | (value?: boolean) => void | ❌ | Previous mapping handler |
Example
import { SingleMapping } from '@sparrowengg/integrations-templates-frontend';
function SingleMappingExample() {
const [integrationFields, setIntegrationFields] = useState([
{ id: 1, label: "Name", value: "name", type: "string" },
{ id: 2, label: "Email", value: "email", type: "email" }
]);
return (
<SingleMapping
integrationFields={integrationFields}
setIntegrationFields={setIntegrationFields}
configuration={{
importOptions: {
showImportOptions: true,
excludeResponse: {
id: "exclude",
label: "Exclude existing responses",
ifChecked: () => "Existing responses will be excluded",
ifUnchecked: () => "All responses will be included",
fieldType: "checkbox",
value: false,
onChangeHandler: (value) => console.log('Exclude changed:', value)
},
options: [
{
id: 1,
label: "Import All Data",
value: "all",
description: "Import all available data",
type: null
}
],
onChangeHandler: (value) => console.log('Import option changed:', value)
},
hasConfiguration: true,
configuredFields: {},
configurationFields: [],
onSaveHandler: () => console.log('Configuration saved')
}}
isMappingPage={false}
navigateMappingPage={(value) => console.log('Navigate:', value)}
surveyDetails={{
surveyName: "Product Feedback",
surveyId: "prod_survey_1"
}}
onSaveHandler={(fields) => console.log('Single mapping saved:', fields)}
hasExistingMapping={false}
importResponse={{
hasImportResponse: true,
value: { importMethod: "SEND_ALL_DATA" },
onChangeHandler: (value) => console.log('Import response changed:', value)
}}
/>
);
}Triggers Component
The Triggers component provides a comprehensive interface for setting up conditional triggers with filter conditions and notification settings.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| draftHandler | (type: string \| null, editFieldId?: string) => void | ✅ | Draft save handler |
| onSaveTriggerLoader | boolean | ✅ | Loading state for save operation |
| objects | ObjectsFieldType | ✅ | Object selection configuration |
| accounts | AccountsFieldType | ✅ | Account selection configuration |
| actions | ActionsFieldType | ✅ | Action selection configuration |
| isTriggerPage | boolean | ✅ | Current page state |
| navigateTriggerPage | (isTriggerPage: boolean) => void | ✅ | Page navigation handler |
| previousMapping | boolean | ✅ | Whether previous mapping exists |
| onSaveHandler | (editFieldId?: string) => void | ✅ | Save operation handler |
| previousMappingHandler | () => void | ✅ | Previous mapping navigation |
| surveyDetails | SurveyDetails | ✅ | Survey information |
| hasNestedCondition | boolean | ✅ | Whether nested conditions are supported |
| fields | TriggerField | ✅ | Trigger field configuration |
| token | string | ✅ | Authentication token |
| apiURL | string | ✅ | API endpoint URL |
| setFields | (fields: TriggerField) => void | ✅ | Fields state setter |
| shareRecipentOptions | SelectOption[] | ✅ | Share recipient options |
| shareChannelOptions | SelectOption[] | ✅ | Share channel options |
| triggerDetails | TriggerDetails | ✅ | Trigger details configuration |
| setTriggerDetails | (details: TriggerDetails) => void | ✅ | Trigger details setter |
| editField | EditField \| null | ✅ | Field being edited |
| fieldOptions | SelectOption[] | ✅ | Available field options |
| variableOptions | SelectOption[] | ✅ | Available variable options |
TriggerField
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| id | string | ✅ | Unique trigger identifier |
| filters | FilterGroup[] | ✅ | Array of filter groups |
FilterGroup
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| id | string | ✅ | Filter group identifier |
| conditions | FilterCondition[] | ✅ | Array of filter conditions |
| operator | 'AND' \| 'OR' | ✅ | Logical operator between conditions |
Example
import { Triggers } from '@sparrowengg/integrations-templates-frontend';
function TriggersExample() {
const [triggerFields, setTriggerFields] = useState({
id: "trigger_1",
filters: [
{
id: "group_1",
conditions: [
{
id: "condition_1",
field: { label: "Score", value: "score" },
operator: { label: "Greater than", value: "gt" },
value: 8
}
],
operator: "AND"
}
]
});
const [triggerDetails, setTriggerDetails] = useState({
shareChannel: { label: "Email", value: "email" },
shareRecipient: { label: "Admin", value: "[email protected]" },
shareType: { label: "Notification", value: "notification" }
});
return (
<Triggers
draftHandler={(type, id) => console.log('Save draft:', type, id)}
onSaveTriggerLoader={false}
objects={{
hasObjects: true,
options: [{ label: "Survey Response", value: "response" }],
value: { label: "Survey Response", value: "response" },
onChangeHandler: (value) => console.log('Object selected:', value)
}}
accounts={{
hasAccounts: false,
options: [],
value: null,
onChangeHandler: () => {}
}}
actions={{
hasActions: true,
options: [{ label: "Send Notification", value: "notify" }],
value: { label: "Send Notification", value: "notify" },
onChangeHandler: (value) => console.log('Action selected:', value)
}}
isTriggerPage={false}
navigateTriggerPage={(value) => console.log('Navigate to trigger page:', value)}
previousMapping={false}
onSaveHandler={(id) => console.log('Trigger saved:', id)}
previousMappingHandler={() => console.log('Go back')}
surveyDetails={{
surveyName: "Customer Satisfaction",
surveyId: "csat_survey"
}}
hasNestedCondition={true}
fields={triggerFields}
token="auth_token"
apiURL="https://api.example.com"
setFields={setTriggerFields}
shareRecipentOptions={[
{ label: "Admin", value: "[email protected]" },
{ label: "Manager", value: "[email protected]" }
]}
shareChannelOptions={[
{ label: "Email", value: "email" },
{ label: "Slack", value: "slack" }
]}
triggerDetails={triggerDetails}
setTriggerDetails={setTriggerDetails}
editField={null}
fieldOptions={[
{ label: "Score", value: "score" },
{ label: "Category", value: "category" }
]}
variableOptions={[
{ label: "Response ID", value: "response_id" },
{ label: "Respondent Email", value: "respondent_email" }
]}
/>
);
}ContactImport Component
The ContactImport component provides functionality for importing contact data with mapping, scheduling, and management capabilities.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| dashboardDescription | string | ✅ | Description text for dashboard |
| existingImports | Array<CompletedImportTypes \| ScheduledImportTypes> \| null | ✅ | Existing import records |
| hasPreviousMapping | boolean | ❌ | Whether previous mapping exists |
| previousMappingHandler | (value?: boolean) => void | ✅ | Previous mapping handler |
| onSaveHandler | () => void | ✅ | Save operation handler |
| isContactMappingPage | boolean | ✅ | Current page state |
| navigateMappingPage | (value?: boolean) => void | ✅ | Navigation handler |
| contactImportField | ContactImportFieldType | ✅ | Contact import configuration |
| setContactImportField | React.Dispatch<React.SetStateAction<ContactImportFieldType>> | ✅ | Configuration setter |
| listSegmentOptions | SelectOption[] | ✅ | List segment options |
| integrationName | string | ✅ | Integration name |
| contactProperties | ContactProperty[] | ✅ | Available contact properties |
| invitePortal | InvitePortalType | ✅ | Invite portal configuration |
ContactImportFieldType
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| configure | ConfigureObject \| null | ✅ | Configuration settings |
| description | string \| null | ✅ | Import description |
| id | string \| number \| null | ✅ | Import identifier |
| fields | ContactFieldType[] | ✅ | Field mappings |
| invitePortal | boolean | ✅ | Whether to invite to portal |
Example
import { ContactImport } from '@sparrowengg/integrations-templates-frontend';
function ContactImportExample() {
const [contactImportField, setContactImportField] = useState({
configure: null,
description: null,
id: null,
fields: [],
invitePortal: false
});
return (
<ContactImport
dashboardDescription="Manage your contact imports and sync data with your integration."
existingImports={[]}
hasPreviousMapping={false}
previousMappingHandler={() => console.log('Go back')}
onSaveHandler={() => console.log('Import saved')}
isContactMappingPage={false}
navigateMappingPage={(value) => console.log('Navigate:', value)}
contactImportField={contactImportField}
setContactImportField={setContactImportField}
listSegmentOptions={[
{ label: "All Contacts", value: "all" },
{ label: "Active Subscribers", value: "active" }
]}
integrationName="Mailchimp"
contactProperties={[
{ id: 1, label: "Email", value: "email", type: "email" },
{ id: 2, label: "First Name", value: "first_name", type: "text" }
]}
invitePortal={{
hasInvitePortal: true,
value: false,
onChangeHandler: (value) => console.log('Invite portal:', value)
}}
/>
);
}IntegrationTemplate Component
The IntegrationTemplate is the main orchestrating component that manages the flow between different integration steps including mapping, triggers, and dashboard views.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| singleMapping | SingleMappingType | ❌ | Single mapping configuration |
| draftHandler | (type: string \| null) => void | ✅ | Draft save handler |
| onMappingEditHandler | (field: unknown) => void | ✅ | Mapping edit handler |
| fieldOptions | FieldOptionsType | ✅ | Available field options |
| triggerEnabled | boolean | ✅ | Whether triggers are enabled |
| mappingEnabled | boolean | ✅ | Whether mapping is enabled |
| mappingComponent | React.ReactElement | ✅ | Mapping component instance |
| singleMappingComponent | React.ReactElement | ❌ | Single mapping component instance |
| mapping | MappingState | ✅ | Mapping state object |
| triggerComponent | React.ReactElement | ✅ | Trigger component instance |
| trigger | TriggerState | ✅ | Trigger state object |
| integrationName | string | ✅ | Integration name |
| onDeleteHandler | (id: string \| number) => void | ❌ | Delete handler |
| toggleDashboardField | (id: string \| number, status: boolean) => void | ❌ | Dashboard field toggle |
| dashboardDescription | string | ✅ | Dashboard description |
| mappingDescription | string | ✅ | Mapping description |
| triggerDescription | string | ✅ | Trigger description |
| handlePreviousNavigation | () => void | ✅ | Previous navigation handler |
| surveyType | string | ❌ | Survey type |
| syncMapping | (id: string \| number) => void | ❌ | Sync mapping handler |
Example
import { IntegrationTemplate, Mapping, Triggers } from '@sparrowengg/integrations-templates-frontend';
function IntegrationTemplateExample() {
const [mappingFields, setMappingFields] = useState({ type: "MAPPING", fields: [] });
const [triggerFields, setTriggerFields] = useState([]);
const mappingComponent = (
<Mapping
// ... mapping props
onSaveHandler={() => console.log('Mapping saved')}
/>
);
const triggerComponent = (
<Triggers
// ... trigger props
onSaveHandler={() => console.log('Trigger saved')}
/>
);
return (
<IntegrationTemplate
draftHandler={(type) => console.log('Save draft:', type)}
onMappingEditHandler={(field) => console.log('Edit mapping:', field)}
fieldOptions={[
{ label: "Email", value: "email" },
{ label: "Name", value: "name" }
]}
triggerEnabled={true}
mappingEnabled={true}
mappingComponent={mappingComponent}
mapping={{
mappedFields: mappingFields,
setMappedFields: setMappingFields
}}
triggerComponent={triggerComponent}
trigger={{
mappedFields: triggerFields,
setMappedFields: setTriggerFields
}}
integrationName="Salesforce"
dashboardDescription="Manage your Salesforce integration configurations."
mappingDescription="Map survey fields to Salesforce objects."
triggerDescription="Set up automated triggers based on survey responses."
handlePreviousNavigation={() => console.log('Navigate back')}
/>
);
}🎨 Styling
The library includes built-in CSS styles. Make sure to import the stylesheet:
import '@sparrowengg/integrations-templates-frontend/dist/es/index.css';All components use the Twigs React design system and support custom theming through the ThemeProvider.
🔧 Advanced Usage
Custom Theme Configuration
import { ThemeProvider } from '@sparrowengg/twigs-react';
const customTheme = {
fonts: {
body: "Inter, sans-serif",
heading: "Inter, sans-serif"
},
colors: {
primary500: "#4A9CA6"
}
};
function App() {
return (
<ThemeProvider theme={customTheme}>
{/* Your components */}
</ThemeProvider>
);
}Error Handling
Components provide error states and validation feedback:
// Field with validation error
{
id: "email",
type: "input",
label: "Email",
value: "invalid-email",
changeFieldValue: handleChange,
required: true,
// Error will be shown if validation fails
}Loading States
Most components support loading states for async operations:
<Mapping
onSaveMappingLoader={true} // Shows loading spinner on save button
// ... other props
/>🤝 TypeScript Support
The library is built with TypeScript and provides comprehensive type definitions for all components and props. Import types as needed:
import type {
MappingProps,
TriggerProps,
SelectOption,
FieldType
} from '@sparrowengg/integrations-templates-frontend';📖 API Reference
Common Types
SelectOption
type SelectOption = {
label: string;
value: string | number;
type?: string;
};SurveyDetails
type SurveyDetails = {
surveyName: string;
surveyId: string | number;
};FormFieldValue
type FormFieldValue = string | number | boolean | null | SelectOption | SelectOption[];