@sparrowengg/integrations-templates-frontend 6.0.7 → 7.0.0-bulkify.3

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 (35) hide show
  1. package/README.md +663 -0
  2. package/dist/cjs/cascader-dropdown/cascader-dropdown-provider.js +17 -1
  3. package/dist/cjs/cascader-dropdown/cascader-dropdown-provider.js.map +1 -1
  4. package/dist/cjs/cascader-dropdown/cascader-dropdown.js +5 -1
  5. package/dist/cjs/cascader-dropdown/cascader-dropdown.js.map +1 -1
  6. package/dist/cjs/dynamic-mapping/components/mapping.js +4 -2
  7. package/dist/cjs/dynamic-mapping/components/mapping.js.map +1 -1
  8. package/dist/cjs/dynamic-mapping/constants/condition-operators.js +1 -0
  9. package/dist/cjs/dynamic-mapping/constants/condition-operators.js.map +1 -1
  10. package/dist/cjs/dynamic-mapping/helpers/mapping.helpers.js +10 -0
  11. package/dist/cjs/dynamic-mapping/helpers/mapping.helpers.js.map +1 -1
  12. package/dist/cjs/dynamic-mapping/hooks/use-mapping-data.js +44 -29
  13. package/dist/cjs/dynamic-mapping/hooks/use-mapping-data.js.map +1 -1
  14. package/dist/cjs/dynamic-mapping/index.js +4 -2
  15. package/dist/cjs/dynamic-mapping/index.js.map +1 -1
  16. package/dist/cjs/filter/filter-pill.js +19 -9
  17. package/dist/cjs/filter/filter-pill.js.map +1 -1
  18. package/dist/es/cascader-dropdown/cascader-dropdown-provider.js +18 -2
  19. package/dist/es/cascader-dropdown/cascader-dropdown-provider.js.map +1 -1
  20. package/dist/es/cascader-dropdown/cascader-dropdown.js +5 -1
  21. package/dist/es/cascader-dropdown/cascader-dropdown.js.map +1 -1
  22. package/dist/es/dynamic-mapping/components/mapping.js +4 -2
  23. package/dist/es/dynamic-mapping/components/mapping.js.map +1 -1
  24. package/dist/es/dynamic-mapping/constants/condition-operators.js +1 -0
  25. package/dist/es/dynamic-mapping/constants/condition-operators.js.map +1 -1
  26. package/dist/es/dynamic-mapping/helpers/mapping.helpers.js +10 -1
  27. package/dist/es/dynamic-mapping/helpers/mapping.helpers.js.map +1 -1
  28. package/dist/es/dynamic-mapping/hooks/use-mapping-data.js +36 -21
  29. package/dist/es/dynamic-mapping/hooks/use-mapping-data.js.map +1 -1
  30. package/dist/es/dynamic-mapping/index.js +4 -2
  31. package/dist/es/dynamic-mapping/index.js.map +1 -1
  32. package/dist/es/filter/filter-pill.js +20 -10
  33. package/dist/es/filter/filter-pill.js.map +1 -1
  34. package/dist/index.d.ts +6 -2
  35. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,663 @@
1
+ # AppNest Templates - Integration Frontend Components
2
+
3
+ A comprehensive React component library for building integration templates with field mapping, triggers, and data import functionality. Built with TypeScript and Twigs React components.
4
+
5
+ ## 📦 Installation
6
+
7
+ ```bash
8
+ npm install @sparrowengg/integrations-templates-frontend
9
+ # or
10
+ yarn add @sparrowengg/integrations-templates-frontend
11
+ ```
12
+
13
+ ## 🚀 Quick Start
14
+
15
+ ```tsx
16
+ import { Mapping, IntegrationTemplate } from '@sparrowengg/integrations-templates-frontend';
17
+ import '@sparrowengg/integrations-templates-frontend/dist/es/index.css';
18
+
19
+ // Basic mapping example
20
+ function MyMappingComponent() {
21
+ return (
22
+ <Mapping
23
+ integrationName="Salesforce"
24
+ // ... mapping props
25
+ />
26
+ );
27
+ }
28
+ ```
29
+
30
+ ## 🏗️ Architecture
31
+
32
+ The library is organized into several main modules:
33
+
34
+ - **Mapping** - Complex field mapping between survey data and integration fields
35
+ - **Single Mapping** - Simplified single-step mapping with configuration
36
+ - **Triggers** - Conditional trigger setup with filter conditions
37
+ - **Contact Import** - Contact data import with scheduling and mapping
38
+ - **Dynamic Mapping** - Dynamic field mapping capabilities
39
+ - **Filter** - Filter components for data filtering
40
+ - **Cascader Dropdown** - Hierarchical dropdown navigation
41
+ - **Integration Template** - Main wrapper component that orchestrates all modules
42
+
43
+ ## 📚 Components Documentation
44
+
45
+ ### Mapping Component
46
+
47
+ The Mapping component provides a comprehensive interface for mapping survey fields to integration fields with support for complex configurations, event setup, and field validation.
48
+
49
+ #### Props
50
+
51
+ | Prop | Type | Required | Description |
52
+ |------|------|----------|-------------|
53
+ | `havingTypeDropdown` | `boolean` | ✅ | Whether to show integration field type dropdown |
54
+ | `onSaveMappingLoader` | `boolean` | ✅ | Loading state for save operation |
55
+ | `surveyDetails` | `SurveyDetails` | ✅ | Survey information object |
56
+ | `integrationName` | `string` | ✅ | Name of the target integration |
57
+ | `fields` | `FieldType[]` | ✅ | Array of mapping field configurations |
58
+ | `setFields` | `React.Dispatch<React.SetStateAction<FieldType[]>>` | ✅ | State setter for fields |
59
+ | `integrationFields` | `IntegrationFieldType[]` | ✅ | Available integration fields |
60
+ | `setIntegrationFields` | `React.Dispatch<React.SetStateAction<IntegrationFieldType[]>>` | ✅ | State setter for integration fields |
61
+ | `apiURL` | `string` | ❌ | API endpoint URL (defaults to SurveySparrow URL) |
62
+ | `token` | `string` | ✅ | Authentication token |
63
+ | `accounts` | `AccountsFieldType` | ✅ | Account selection configuration |
64
+ | `events` | `EventFieldType` | ✅ | Event selection configuration |
65
+ | `actions` | `ActionsFieldType` | ✅ | Action selection configuration |
66
+ | `isMappingPage` | `boolean` | ✅ | Current page state (event setup vs mapping) |
67
+ | `surveyType` | `string` | ✅ | Type of survey |
68
+ | `navigateMappingPage` | `(value?: boolean) => void` | ✅ | Navigation handler |
69
+ | `customList` | `CustomListFieldType` | ✅ | Custom list configuration |
70
+ | `oldResponse` | `OldResponseFieldType` | ✅ | Old response handling configuration |
71
+ | `hasPreviousMapping` | `boolean` | ✅ | Whether previous mapping exists |
72
+ | `onSaveHandler` | `() => void` | ✅ | Save operation handler |
73
+ | `editField` | `EditField \| null` | ✅ | Field being edited |
74
+ | `previousMappingHandler` | `(value?: boolean) => void` | ✅ | Previous mapping navigation handler |
75
+ | `onDeleteHandler` | `(id: string \| number) => void` | ❌ | Delete field handler |
76
+ | `draftHandler` | `(type: string \| null, editFieldId?: string \| number) => void` | ✅ | Draft save handler |
77
+ | `configuration` | `ConfigurationObject` | ✅ | Configuration setup object |
78
+
79
+ #### FieldType
80
+
81
+ | Property | Type | Required | Description |
82
+ |----------|------|----------|-------------|
83
+ | `id` | `string` | ✅ | Unique field identifier |
84
+ | `surveySparrowField` | `SelectOption \| null` | ✅ | Selected survey field |
85
+ | `integrationField` | `SelectOption \| null` | ✅ | Selected integration field |
86
+ | `integrationFieldType` | `SelectOption \| null` | ✅ | Integration field type |
87
+ | `isEssentialField` | `boolean` | ✅ | Whether field is required for integration |
88
+ | `essentialFieldLabel` | `string` | ❌ | Label for essential field |
89
+ | `mappedType` | `SelectOption` | ✅ | Field mapping type |
90
+ | `defaultValue` | `FormFieldValue` | ❌ | Default field value |
91
+ | `dependency` | `Record<string, unknown> \| null` | ✅ | Field dependencies |
92
+
93
+ #### Example
94
+
95
+ ```tsx
96
+ import { Mapping } from '@sparrowengg/integrations-templates-frontend';
97
+
98
+ function MappingExample() {
99
+ const [fields, setFields] = useState([
100
+ {
101
+ id: "email_field",
102
+ surveySparrowField: null,
103
+ integrationField: null,
104
+ integrationFieldType: null,
105
+ isEssentialField: true,
106
+ essentialFieldLabel: "Email",
107
+ mappedType: { label: "Email", value: "email" },
108
+ defaultValue: null,
109
+ dependency: null
110
+ }
111
+ ]);
112
+
113
+ const [integrationFields, setIntegrationFields] = useState([
114
+ {
115
+ id: "email",
116
+ label: "Email Address",
117
+ value: "email",
118
+ type: "string"
119
+ }
120
+ ]);
121
+
122
+ return (
123
+ <Mapping
124
+ havingTypeDropdown={true}
125
+ onSaveMappingLoader={false}
126
+ surveyDetails={{
127
+ surveyName: "Customer Feedback Survey",
128
+ surveyId: "survey_123"
129
+ }}
130
+ integrationName="Salesforce"
131
+ fields={fields}
132
+ setFields={setFields}
133
+ integrationFields={integrationFields}
134
+ setIntegrationFields={setIntegrationFields}
135
+ token="your_auth_token"
136
+ accounts={{
137
+ hasAccounts: true,
138
+ options: [{ label: "Main Account", value: "acc_1" }],
139
+ value: null,
140
+ onChangeHandler: (value) => console.log('Account selected:', value)
141
+ }}
142
+ events={{
143
+ hasEvents: true,
144
+ options: [{ label: "Contact Update", value: "contact_update" }],
145
+ value: null,
146
+ onChangeHandler: (value) => console.log('Event selected:', value)
147
+ }}
148
+ actions={{
149
+ hasActions: true,
150
+ options: [{ label: "Create Contact", value: "create_contact" }],
151
+ value: null,
152
+ onChangeHandler: (value) => console.log('Action selected:', value)
153
+ }}
154
+ isMappingPage={false}
155
+ surveyType="standard"
156
+ navigateMappingPage={(value) => console.log('Navigate to mapping:', value)}
157
+ customList={{ hasCustomList: false, value: null, onChangeHandler: () => {} }}
158
+ oldResponse={{ hasOldResponse: false, value: null, onChangeHandler: () => {} }}
159
+ hasPreviousMapping={false}
160
+ onSaveHandler={() => console.log('Mapping saved')}
161
+ editField={null}
162
+ previousMappingHandler={() => console.log('Go back')}
163
+ draftHandler={(type, id) => console.log('Save draft:', type, id)}
164
+ configuration={{
165
+ hasConfiguration: false,
166
+ configurationFields: [],
167
+ configuredFields: {},
168
+ title: "Event Configuration"
169
+ }}
170
+ />
171
+ );
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ### SingleMapping Component
178
+
179
+ The SingleMapping component provides a simplified mapping interface with configuration steps, ideal for straightforward integration scenarios.
180
+
181
+ #### Props
182
+
183
+ | Prop | Type | Required | Description |
184
+ |------|------|----------|-------------|
185
+ | `hasPreviousMapping` | `boolean` | ❌ | Whether previous mapping exists |
186
+ | `integrationFields` | `IntegrationField[]` | ✅ | Available integration fields |
187
+ | `configuration` | `SingleMappingConfiguration` | ✅ | Configuration object |
188
+ | `token` | `string` | ❌ | Authentication token |
189
+ | `isMappingPage` | `boolean` | ✅ | Current page state |
190
+ | `navigateMappingPage` | `(value?: boolean) => void` | ✅ | Navigation handler |
191
+ | `apiURL` | `string` | ❌ | API endpoint URL |
192
+ | `surveyDetails` | `SurveyDetails` | ✅ | Survey information |
193
+ | `onSaveHandler` | `(fields: any) => void` | ✅ | Save handler |
194
+ | `setIntegrationFields` | `React.Dispatch<React.SetStateAction<any>>` | ✅ | Integration fields setter |
195
+ | `hasExistingMapping` | `boolean` | ✅ | Whether existing mapping is present |
196
+ | `importResponse` | `ImportResponse` | ✅ | Import response configuration |
197
+ | `editField` | `any` | ❌ | Field being edited |
198
+ | `previousMappingHandler` | `(value?: boolean) => void` | ❌ | Previous mapping handler |
199
+
200
+ #### Example
201
+
202
+ ```tsx
203
+ import { SingleMapping } from '@sparrowengg/integrations-templates-frontend';
204
+
205
+ function SingleMappingExample() {
206
+ const [integrationFields, setIntegrationFields] = useState([
207
+ { id: 1, label: "Name", value: "name", type: "string" },
208
+ { id: 2, label: "Email", value: "email", type: "email" }
209
+ ]);
210
+
211
+ return (
212
+ <SingleMapping
213
+ integrationFields={integrationFields}
214
+ setIntegrationFields={setIntegrationFields}
215
+ configuration={{
216
+ importOptions: {
217
+ showImportOptions: true,
218
+ excludeResponse: {
219
+ id: "exclude",
220
+ label: "Exclude existing responses",
221
+ ifChecked: () => "Existing responses will be excluded",
222
+ ifUnchecked: () => "All responses will be included",
223
+ fieldType: "checkbox",
224
+ value: false,
225
+ onChangeHandler: (value) => console.log('Exclude changed:', value)
226
+ },
227
+ options: [
228
+ {
229
+ id: 1,
230
+ label: "Import All Data",
231
+ value: "all",
232
+ description: "Import all available data",
233
+ type: null
234
+ }
235
+ ],
236
+ onChangeHandler: (value) => console.log('Import option changed:', value)
237
+ },
238
+ hasConfiguration: true,
239
+ configuredFields: {},
240
+ configurationFields: [],
241
+ onSaveHandler: () => console.log('Configuration saved')
242
+ }}
243
+ isMappingPage={false}
244
+ navigateMappingPage={(value) => console.log('Navigate:', value)}
245
+ surveyDetails={{
246
+ surveyName: "Product Feedback",
247
+ surveyId: "prod_survey_1"
248
+ }}
249
+ onSaveHandler={(fields) => console.log('Single mapping saved:', fields)}
250
+ hasExistingMapping={false}
251
+ importResponse={{
252
+ hasImportResponse: true,
253
+ value: { importMethod: "SEND_ALL_DATA" },
254
+ onChangeHandler: (value) => console.log('Import response changed:', value)
255
+ }}
256
+ />
257
+ );
258
+ }
259
+ ```
260
+
261
+ ---
262
+
263
+ ### Triggers Component
264
+
265
+ The Triggers component provides a comprehensive interface for setting up conditional triggers with filter conditions and notification settings.
266
+
267
+ #### Props
268
+
269
+ | Prop | Type | Required | Description |
270
+ |------|------|----------|-------------|
271
+ | `draftHandler` | `(type: string \| null, editFieldId?: string) => void` | ✅ | Draft save handler |
272
+ | `onSaveTriggerLoader` | `boolean` | ✅ | Loading state for save operation |
273
+ | `objects` | `ObjectsFieldType` | ✅ | Object selection configuration |
274
+ | `accounts` | `AccountsFieldType` | ✅ | Account selection configuration |
275
+ | `actions` | `ActionsFieldType` | ✅ | Action selection configuration |
276
+ | `isTriggerPage` | `boolean` | ✅ | Current page state |
277
+ | `navigateTriggerPage` | `(isTriggerPage: boolean) => void` | ✅ | Page navigation handler |
278
+ | `previousMapping` | `boolean` | ✅ | Whether previous mapping exists |
279
+ | `onSaveHandler` | `(editFieldId?: string) => void` | ✅ | Save operation handler |
280
+ | `previousMappingHandler` | `() => void` | ✅ | Previous mapping navigation |
281
+ | `surveyDetails` | `SurveyDetails` | ✅ | Survey information |
282
+ | `hasNestedCondition` | `boolean` | ✅ | Whether nested conditions are supported |
283
+ | `fields` | `TriggerField` | ✅ | Trigger field configuration |
284
+ | `token` | `string` | ✅ | Authentication token |
285
+ | `apiURL` | `string` | ✅ | API endpoint URL |
286
+ | `setFields` | `(fields: TriggerField) => void` | ✅ | Fields state setter |
287
+ | `shareRecipentOptions` | `SelectOption[]` | ✅ | Share recipient options |
288
+ | `shareChannelOptions` | `SelectOption[]` | ✅ | Share channel options |
289
+ | `triggerDetails` | `TriggerDetails` | ✅ | Trigger details configuration |
290
+ | `setTriggerDetails` | `(details: TriggerDetails) => void` | ✅ | Trigger details setter |
291
+ | `editField` | `EditField \| null` | ✅ | Field being edited |
292
+ | `fieldOptions` | `SelectOption[]` | ✅ | Available field options |
293
+ | `variableOptions` | `SelectOption[]` | ✅ | Available variable options |
294
+
295
+ #### TriggerField
296
+
297
+ | Property | Type | Required | Description |
298
+ |----------|------|----------|-------------|
299
+ | `id` | `string` | ✅ | Unique trigger identifier |
300
+ | `filters` | `FilterGroup[]` | ✅ | Array of filter groups |
301
+
302
+ #### FilterGroup
303
+
304
+ | Property | Type | Required | Description |
305
+ |----------|------|----------|-------------|
306
+ | `id` | `string` | ✅ | Filter group identifier |
307
+ | `conditions` | `FilterCondition[]` | ✅ | Array of filter conditions |
308
+ | `operator` | `'AND' \| 'OR'` | ✅ | Logical operator between conditions |
309
+
310
+ #### Example
311
+
312
+ ```tsx
313
+ import { Triggers } from '@sparrowengg/integrations-templates-frontend';
314
+
315
+ function TriggersExample() {
316
+ const [triggerFields, setTriggerFields] = useState({
317
+ id: "trigger_1",
318
+ filters: [
319
+ {
320
+ id: "group_1",
321
+ conditions: [
322
+ {
323
+ id: "condition_1",
324
+ field: { label: "Score", value: "score" },
325
+ operator: { label: "Greater than", value: "gt" },
326
+ value: 8
327
+ }
328
+ ],
329
+ operator: "AND"
330
+ }
331
+ ]
332
+ });
333
+
334
+ const [triggerDetails, setTriggerDetails] = useState({
335
+ shareChannel: { label: "Email", value: "email" },
336
+ shareRecipient: { label: "Admin", value: "admin@company.com" },
337
+ shareType: { label: "Notification", value: "notification" }
338
+ });
339
+
340
+ return (
341
+ <Triggers
342
+ draftHandler={(type, id) => console.log('Save draft:', type, id)}
343
+ onSaveTriggerLoader={false}
344
+ objects={{
345
+ hasObjects: true,
346
+ options: [{ label: "Survey Response", value: "response" }],
347
+ value: { label: "Survey Response", value: "response" },
348
+ onChangeHandler: (value) => console.log('Object selected:', value)
349
+ }}
350
+ accounts={{
351
+ hasAccounts: false,
352
+ options: [],
353
+ value: null,
354
+ onChangeHandler: () => {}
355
+ }}
356
+ actions={{
357
+ hasActions: true,
358
+ options: [{ label: "Send Notification", value: "notify" }],
359
+ value: { label: "Send Notification", value: "notify" },
360
+ onChangeHandler: (value) => console.log('Action selected:', value)
361
+ }}
362
+ isTriggerPage={false}
363
+ navigateTriggerPage={(value) => console.log('Navigate to trigger page:', value)}
364
+ previousMapping={false}
365
+ onSaveHandler={(id) => console.log('Trigger saved:', id)}
366
+ previousMappingHandler={() => console.log('Go back')}
367
+ surveyDetails={{
368
+ surveyName: "Customer Satisfaction",
369
+ surveyId: "csat_survey"
370
+ }}
371
+ hasNestedCondition={true}
372
+ fields={triggerFields}
373
+ token="auth_token"
374
+ apiURL="https://api.example.com"
375
+ setFields={setTriggerFields}
376
+ shareRecipentOptions={[
377
+ { label: "Admin", value: "admin@company.com" },
378
+ { label: "Manager", value: "manager@company.com" }
379
+ ]}
380
+ shareChannelOptions={[
381
+ { label: "Email", value: "email" },
382
+ { label: "Slack", value: "slack" }
383
+ ]}
384
+ triggerDetails={triggerDetails}
385
+ setTriggerDetails={setTriggerDetails}
386
+ editField={null}
387
+ fieldOptions={[
388
+ { label: "Score", value: "score" },
389
+ { label: "Category", value: "category" }
390
+ ]}
391
+ variableOptions={[
392
+ { label: "Response ID", value: "response_id" },
393
+ { label: "Respondent Email", value: "respondent_email" }
394
+ ]}
395
+ />
396
+ );
397
+ }
398
+ ```
399
+
400
+ ---
401
+
402
+ ### ContactImport Component
403
+
404
+ The ContactImport component provides functionality for importing contact data with mapping, scheduling, and management capabilities.
405
+
406
+ #### Props
407
+
408
+ | Prop | Type | Required | Description |
409
+ |------|------|----------|-------------|
410
+ | `dashboardDescription` | `string` | ✅ | Description text for dashboard |
411
+ | `existingImports` | `Array<CompletedImportTypes \| ScheduledImportTypes> \| null` | ✅ | Existing import records |
412
+ | `hasPreviousMapping` | `boolean` | ❌ | Whether previous mapping exists |
413
+ | `previousMappingHandler` | `(value?: boolean) => void` | ✅ | Previous mapping handler |
414
+ | `onSaveHandler` | `() => void` | ✅ | Save operation handler |
415
+ | `isContactMappingPage` | `boolean` | ✅ | Current page state |
416
+ | `navigateMappingPage` | `(value?: boolean) => void` | ✅ | Navigation handler |
417
+ | `contactImportField` | `ContactImportFieldType` | ✅ | Contact import configuration |
418
+ | `setContactImportField` | `React.Dispatch<React.SetStateAction<ContactImportFieldType>>` | ✅ | Configuration setter |
419
+ | `listSegmentOptions` | `SelectOption[]` | ✅ | List segment options |
420
+ | `integrationName` | `string` | ✅ | Integration name |
421
+ | `contactProperties` | `ContactProperty[]` | ✅ | Available contact properties |
422
+ | `invitePortal` | `InvitePortalType` | ✅ | Invite portal configuration |
423
+
424
+ #### ContactImportFieldType
425
+
426
+ | Property | Type | Required | Description |
427
+ |----------|------|----------|-------------|
428
+ | `configure` | `ConfigureObject \| null` | ✅ | Configuration settings |
429
+ | `description` | `string \| null` | ✅ | Import description |
430
+ | `id` | `string \| number \| null` | ✅ | Import identifier |
431
+ | `fields` | `ContactFieldType[]` | ✅ | Field mappings |
432
+ | `invitePortal` | `boolean` | ✅ | Whether to invite to portal |
433
+
434
+ #### Example
435
+
436
+ ```tsx
437
+ import { ContactImport } from '@sparrowengg/integrations-templates-frontend';
438
+
439
+ function ContactImportExample() {
440
+ const [contactImportField, setContactImportField] = useState({
441
+ configure: null,
442
+ description: null,
443
+ id: null,
444
+ fields: [],
445
+ invitePortal: false
446
+ });
447
+
448
+ return (
449
+ <ContactImport
450
+ dashboardDescription="Manage your contact imports and sync data with your integration."
451
+ existingImports={[]}
452
+ hasPreviousMapping={false}
453
+ previousMappingHandler={() => console.log('Go back')}
454
+ onSaveHandler={() => console.log('Import saved')}
455
+ isContactMappingPage={false}
456
+ navigateMappingPage={(value) => console.log('Navigate:', value)}
457
+ contactImportField={contactImportField}
458
+ setContactImportField={setContactImportField}
459
+ listSegmentOptions={[
460
+ { label: "All Contacts", value: "all" },
461
+ { label: "Active Subscribers", value: "active" }
462
+ ]}
463
+ integrationName="Mailchimp"
464
+ contactProperties={[
465
+ { id: 1, label: "Email", value: "email", type: "email" },
466
+ { id: 2, label: "First Name", value: "first_name", type: "text" }
467
+ ]}
468
+ invitePortal={{
469
+ hasInvitePortal: true,
470
+ value: false,
471
+ onChangeHandler: (value) => console.log('Invite portal:', value)
472
+ }}
473
+ />
474
+ );
475
+ }
476
+ ```
477
+
478
+ ---
479
+
480
+ ### IntegrationTemplate Component
481
+
482
+ The IntegrationTemplate is the main orchestrating component that manages the flow between different integration steps including mapping, triggers, and dashboard views.
483
+
484
+ #### Props
485
+
486
+ | Prop | Type | Required | Description |
487
+ |------|------|----------|-------------|
488
+ | `singleMapping` | `SingleMappingType` | ❌ | Single mapping configuration |
489
+ | `draftHandler` | `(type: string \| null) => void` | ✅ | Draft save handler |
490
+ | `onMappingEditHandler` | `(field: unknown) => void` | ✅ | Mapping edit handler |
491
+ | `fieldOptions` | `FieldOptionsType` | ✅ | Available field options |
492
+ | `triggerEnabled` | `boolean` | ✅ | Whether triggers are enabled |
493
+ | `mappingEnabled` | `boolean` | ✅ | Whether mapping is enabled |
494
+ | `mappingComponent` | `React.ReactElement` | ✅ | Mapping component instance |
495
+ | `singleMappingComponent` | `React.ReactElement` | ❌ | Single mapping component instance |
496
+ | `mapping` | `MappingState` | ✅ | Mapping state object |
497
+ | `triggerComponent` | `React.ReactElement` | ✅ | Trigger component instance |
498
+ | `trigger` | `TriggerState` | ✅ | Trigger state object |
499
+ | `integrationName` | `string` | ✅ | Integration name |
500
+ | `onDeleteHandler` | `(id: string \| number) => void` | ❌ | Delete handler |
501
+ | `toggleDashboardField` | `(id: string \| number, status: boolean) => void` | ❌ | Dashboard field toggle |
502
+ | `dashboardDescription` | `string` | ✅ | Dashboard description |
503
+ | `mappingDescription` | `string` | ✅ | Mapping description |
504
+ | `triggerDescription` | `string` | ✅ | Trigger description |
505
+ | `handlePreviousNavigation` | `() => void` | ✅ | Previous navigation handler |
506
+ | `surveyType` | `string` | ❌ | Survey type |
507
+ | `syncMapping` | `(id: string \| number) => void` | ❌ | Sync mapping handler |
508
+
509
+ #### Example
510
+
511
+ ```tsx
512
+ import { IntegrationTemplate, Mapping, Triggers } from '@sparrowengg/integrations-templates-frontend';
513
+
514
+ function IntegrationTemplateExample() {
515
+ const [mappingFields, setMappingFields] = useState({ type: "MAPPING", fields: [] });
516
+ const [triggerFields, setTriggerFields] = useState([]);
517
+
518
+ const mappingComponent = (
519
+ <Mapping
520
+ // ... mapping props
521
+ onSaveHandler={() => console.log('Mapping saved')}
522
+ />
523
+ );
524
+
525
+ const triggerComponent = (
526
+ <Triggers
527
+ // ... trigger props
528
+ onSaveHandler={() => console.log('Trigger saved')}
529
+ />
530
+ );
531
+
532
+ return (
533
+ <IntegrationTemplate
534
+ draftHandler={(type) => console.log('Save draft:', type)}
535
+ onMappingEditHandler={(field) => console.log('Edit mapping:', field)}
536
+ fieldOptions={[
537
+ { label: "Email", value: "email" },
538
+ { label: "Name", value: "name" }
539
+ ]}
540
+ triggerEnabled={true}
541
+ mappingEnabled={true}
542
+ mappingComponent={mappingComponent}
543
+ mapping={{
544
+ mappedFields: mappingFields,
545
+ setMappedFields: setMappingFields
546
+ }}
547
+ triggerComponent={triggerComponent}
548
+ trigger={{
549
+ mappedFields: triggerFields,
550
+ setMappedFields: setTriggerFields
551
+ }}
552
+ integrationName="Salesforce"
553
+ dashboardDescription="Manage your Salesforce integration configurations."
554
+ mappingDescription="Map survey fields to Salesforce objects."
555
+ triggerDescription="Set up automated triggers based on survey responses."
556
+ handlePreviousNavigation={() => console.log('Navigate back')}
557
+ />
558
+ );
559
+ }
560
+ ```
561
+
562
+ ## 🎨 Styling
563
+
564
+ The library includes built-in CSS styles. Make sure to import the stylesheet:
565
+
566
+ ```tsx
567
+ import '@sparrowengg/integrations-templates-frontend/dist/es/index.css';
568
+ ```
569
+
570
+ All components use the Twigs React design system and support custom theming through the ThemeProvider.
571
+
572
+ ## 🔧 Advanced Usage
573
+
574
+ ### Custom Theme Configuration
575
+
576
+ ```tsx
577
+ import { ThemeProvider } from '@sparrowengg/twigs-react';
578
+
579
+ const customTheme = {
580
+ fonts: {
581
+ body: "Inter, sans-serif",
582
+ heading: "Inter, sans-serif"
583
+ },
584
+ colors: {
585
+ primary500: "#4A9CA6"
586
+ }
587
+ };
588
+
589
+ function App() {
590
+ return (
591
+ <ThemeProvider theme={customTheme}>
592
+ {/* Your components */}
593
+ </ThemeProvider>
594
+ );
595
+ }
596
+ ```
597
+
598
+ ### Error Handling
599
+
600
+ Components provide error states and validation feedback:
601
+
602
+ ```tsx
603
+ // Field with validation error
604
+ {
605
+ id: "email",
606
+ type: "input",
607
+ label: "Email",
608
+ value: "invalid-email",
609
+ changeFieldValue: handleChange,
610
+ required: true,
611
+ // Error will be shown if validation fails
612
+ }
613
+ ```
614
+
615
+ ### Loading States
616
+
617
+ Most components support loading states for async operations:
618
+
619
+ ```tsx
620
+ <Mapping
621
+ onSaveMappingLoader={true} // Shows loading spinner on save button
622
+ // ... other props
623
+ />
624
+ ```
625
+
626
+ ## 🤝 TypeScript Support
627
+
628
+ The library is built with TypeScript and provides comprehensive type definitions for all components and props. Import types as needed:
629
+
630
+ ```tsx
631
+ import type {
632
+ MappingProps,
633
+ TriggerProps,
634
+ SelectOption,
635
+ FieldType
636
+ } from '@sparrowengg/integrations-templates-frontend';
637
+ ```
638
+
639
+ ## 📖 API Reference
640
+
641
+ ### Common Types
642
+
643
+ #### SelectOption
644
+ ```tsx
645
+ type SelectOption = {
646
+ label: string;
647
+ value: string | number;
648
+ type?: string;
649
+ };
650
+ ```
651
+
652
+ #### SurveyDetails
653
+ ```tsx
654
+ type SurveyDetails = {
655
+ surveyName: string;
656
+ surveyId: string | number;
657
+ };
658
+ ```
659
+
660
+ #### FormFieldValue
661
+ ```tsx
662
+ type FormFieldValue = string | number | boolean | null | SelectOption | SelectOption[];
663
+ ```
@@ -10,11 +10,27 @@ const CascaderDropdownProvider = ({
10
10
  data,
11
11
  value,
12
12
  onChange,
13
- selectorValue
13
+ selectorValue,
14
+ defaultOpen = false,
15
+ onOpenChange
14
16
  }) => {
15
17
  const id = React.useId();
16
18
  const inputRef = React.useRef(null);
17
19
  const [popoverOpen, setPopoverOpen] = React.useState(false);
20
+ const prevPopoverOpen = React.useRef(false);
21
+ React.useEffect(() => {
22
+ if (defaultOpen) {
23
+ const timer = setTimeout(() => setPopoverOpen(true), 0);
24
+ return () => clearTimeout(timer);
25
+ }
26
+ return void 0;
27
+ }, [defaultOpen]);
28
+ React.useEffect(() => {
29
+ if (prevPopoverOpen.current !== popoverOpen) {
30
+ prevPopoverOpen.current = popoverOpen;
31
+ onOpenChange == null ? void 0 : onOpenChange(popoverOpen);
32
+ }
33
+ }, [popoverOpen, onOpenChange]);
18
34
  const [selectedNode, setSelectedNode] = React.useState(null);
19
35
  const [focusedNode, setFocusedNode] = React.useState(null);
20
36
  const { selectionPath, foldersSelectionPath } = React.useMemo(() => {