@xapp/form-widget 1.78.0 → 1.79.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,435 @@
1
1
  ## Form Widget
2
2
 
3
- An scheduling widget that supports multi-step form (displays)
3
+ A scheduling widget that supports multi-step forms and displays.
4
+
5
+ ## Features
6
+
7
+ - Multi-step form flows with dynamic display logic
8
+ - Integration with Stentor conversational AI platform
9
+ - Automatic tracking parameter pass-through for analytics
10
+ - Material-UI components with theming support
11
+ - Audio/voice input capabilities
12
+ - Address autocomplete and service area validation
13
+ - Session management and response caching
14
+
15
+ ## Tracking & Analytics
16
+
17
+ The form widget automatically captures and passes marketing attribution parameters to all API requests for analytics filtering.
18
+
19
+ ### Supported Tracking Parameters
20
+
21
+ #### Standard UTM Parameters
22
+ - `utm_source` - Traffic source (e.g., "google", "facebook", "newsletter")
23
+ - `utm_medium` - Marketing medium (e.g., "cpc", "email", "social")
24
+ - `utm_campaign` - Campaign name (e.g., "spring_sale", "product_launch")
25
+ - `utm_term` - Paid keywords (for paid search campaigns)
26
+ - `utm_content` - Ad content identifier (for A/B testing)
27
+
28
+ #### Platform Click IDs
29
+ - `gclid` - Google Click ID (Google Ads auto-tagging)
30
+ - `fbclid` - Facebook Click ID
31
+ - `msclkid` - Microsoft Click ID (Bing Ads)
32
+
33
+ #### Custom Parameters
34
+ - `track_*` - Any parameter with "track_" prefix
35
+
36
+ ### Implementation
37
+
38
+ Tracking parameters are automatically:
39
+ 1. **Extracted** from the page URL when the widget loads
40
+ 2. **Stored** in localStorage with 30-day expiration
41
+ 3. **Included** in all Stentor API requests via the `attributes` field
42
+ 4. **Available** for filtering in OpenSearch analytics
43
+
44
+ ### API Integration
45
+
46
+ All tracking parameters are included in the request attributes sent to the Stentor API:
47
+
48
+ ```javascript
49
+ // Example API request with tracking data
50
+ {
51
+ "sessionId": "stentor-form-session-123",
52
+ "userId": "user-456",
53
+ "attributes": {
54
+ "utm_source": "google",
55
+ "utm_medium": "cpc",
56
+ "utm_campaign": "spring_sale",
57
+ "gclid": "abc123def456",
58
+ "track_landing_page": "homepage"
59
+ },
60
+ // ... other request data
61
+ }
62
+ ```
63
+
64
+ ### Configuration
65
+
66
+ Tracking is enabled by default. The system handles:
67
+ - Parameter extraction and validation
68
+ - Automatic cleanup of expired data
69
+ - Cross-session persistence
70
+ - Error handling for malformed data
71
+
72
+ No additional configuration is required - the widget will automatically capture and pass through any UTM parameters, click IDs, or custom tracking parameters present in the page URL.
73
+
74
+ ### Implementation Notes
75
+
76
+ **When used standalone:** The widget extracts tracking parameters from the page URL on mount and stores them in localStorage with the prefix `xa_tracking_`.
77
+
78
+ **When embedded in contact-app:** Both the contact-app and form-widget will extract and store tracking parameters. This is safe and intentional:
79
+ - Both extract from the same URL (`window.location.href`)
80
+ - Both write to the same localStorage keys (`xa_tracking_utm_source`, etc.)
81
+ - The function is idempotent - the second extraction just refreshes stored values with identical data
82
+ - No data corruption occurs; it's just a minor inefficiency
83
+
84
+ **Storage format:** Parameters are stored as JSON objects with expiration:
85
+ ```javascript
86
+ localStorage.getItem('xa_tracking_utm_source')
87
+ // Returns: {"value":"google","expires":1234567890,"stored":1234567890}
88
+ ```
89
+
90
+ ## Form Field Types
91
+
92
+ The form widget supports multiple field types for building dynamic forms. Below are JSON examples for each supported field type.
93
+
94
+ ### Text Input
95
+
96
+ Basic text input field with optional formatting (phone, email, address).
97
+
98
+ ```json
99
+ {
100
+ "name": "full_name",
101
+ "type": "TEXT",
102
+ "title": "Full Name",
103
+ "placeholder": "Enter your name",
104
+ "mandatory": true,
105
+ "mandatoryError": "Name is required"
106
+ }
107
+ ```
108
+
109
+ #### Phone Number Input
110
+
111
+ ```json
112
+ {
113
+ "name": "phone",
114
+ "type": "TEXT",
115
+ "title": "Phone Number",
116
+ "format": "PHONE",
117
+ "placeholder": "(555) 555-5555",
118
+ "mandatory": true
119
+ }
120
+ ```
121
+
122
+ #### Email Input
123
+
124
+ ```json
125
+ {
126
+ "name": "email",
127
+ "type": "TEXT",
128
+ "title": "Email Address",
129
+ "format": "EMAIL",
130
+ "placeholder": "you@example.com"
131
+ }
132
+ ```
133
+
134
+ #### Multiline Text
135
+
136
+ ```json
137
+ {
138
+ "name": "description",
139
+ "type": "TEXT",
140
+ "title": "Description",
141
+ "multiline": true,
142
+ "rows": 4,
143
+ "rowsMax": 8,
144
+ "placeholder": "Tell us more..."
145
+ }
146
+ ```
147
+
148
+ #### Address Input with Autocomplete
149
+
150
+ ```json
151
+ {
152
+ "name": "address",
153
+ "type": "TEXT",
154
+ "title": "Service Address",
155
+ "format": "ADDRESS",
156
+ "mapsBaseUrl": "https://maps.googleapis.com/maps/api/place/autocomplete",
157
+ "googleMapsApiKey": "YOUR_API_KEY",
158
+ "mapsUrlQueryParams": {
159
+ "components": "country:us",
160
+ "language": "en"
161
+ }
162
+ }
163
+ ```
164
+
165
+ ### Dropdown
166
+
167
+ Single-select dropdown menu.
168
+
169
+ ```json
170
+ {
171
+ "name": "service_type",
172
+ "type": "DROPDOWN",
173
+ "title": "Select a service",
174
+ "mandatory": true,
175
+ "items": [
176
+ {
177
+ "id": "plumbing",
178
+ "label": "Plumbing"
179
+ },
180
+ {
181
+ "id": "electrical",
182
+ "label": "Electrical"
183
+ },
184
+ {
185
+ "id": "hvac",
186
+ "label": "HVAC"
187
+ }
188
+ ]
189
+ }
190
+ ```
191
+
192
+ #### Dropdown with Freeform Input
193
+
194
+ Allows users to enter custom text when they select specific options.
195
+
196
+ ```json
197
+ {
198
+ "name": "issue",
199
+ "type": "DROPDOWN",
200
+ "title": "What issue are you experiencing?",
201
+ "items": [
202
+ {
203
+ "id": "installation",
204
+ "label": "Installation"
205
+ },
206
+ {
207
+ "id": "repair",
208
+ "label": "Repair"
209
+ },
210
+ {
211
+ "id": "maintenance",
212
+ "label": "Maintenance"
213
+ },
214
+ {
215
+ "id": "other",
216
+ "label": "Other",
217
+ "freeFormInput": true
218
+ }
219
+ ]
220
+ }
221
+ ```
222
+
223
+ When `freeFormInput: true`, selecting that option displays a text input field. The user's typed text becomes the field value instead of the item's ID.
224
+
225
+ ### Chips
226
+
227
+ Visual chip-based selection, supports both single and multi-select.
228
+
229
+ #### Multi-select Chips
230
+
231
+ ```json
232
+ {
233
+ "name": "services",
234
+ "type": "CHIPS",
235
+ "title": "Select services you need",
236
+ "minRequired": 1,
237
+ "maxAllowed": 3,
238
+ "items": [
239
+ {
240
+ "id": "service1",
241
+ "label": "Service 1"
242
+ },
243
+ {
244
+ "id": "service2",
245
+ "label": "Service 2",
246
+ "selected": true
247
+ },
248
+ {
249
+ "id": "service3",
250
+ "label": "Service 3"
251
+ }
252
+ ]
253
+ }
254
+ ```
255
+
256
+ #### Single-select Chips (Radio)
257
+
258
+ ```json
259
+ {
260
+ "name": "membership",
261
+ "type": "CHIPS",
262
+ "title": "Are you a member?",
263
+ "radio": true,
264
+ "items": [
265
+ {
266
+ "id": "yes",
267
+ "label": "Yes"
268
+ },
269
+ {
270
+ "id": "no",
271
+ "label": "No",
272
+ "selected": true
273
+ }
274
+ ]
275
+ }
276
+ ```
277
+
278
+ #### Chips with Actionable Items
279
+
280
+ ```json
281
+ {
282
+ "name": "options",
283
+ "type": "CHIPS",
284
+ "title": "Choose an option",
285
+ "items": [
286
+ {
287
+ "id": "option1",
288
+ "label": "Option 1"
289
+ },
290
+ {
291
+ "id": "learn_more",
292
+ "label": "Learn More",
293
+ "url": "https://example.com/info"
294
+ }
295
+ ]
296
+ }
297
+ ```
298
+
299
+ ### Checkboxes / Radio Buttons
300
+
301
+ Traditional checkbox or radio button selection.
302
+
303
+ #### Checkboxes (Multi-select)
304
+
305
+ ```json
306
+ {
307
+ "name": "preferences",
308
+ "type": "CHECK",
309
+ "title": "Select your preferences",
310
+ "items": [
311
+ {
312
+ "id": "email_updates",
313
+ "label": "Email Updates"
314
+ },
315
+ {
316
+ "id": "sms_notifications",
317
+ "label": "SMS Notifications"
318
+ },
319
+ {
320
+ "id": "phone_calls",
321
+ "label": "Phone Calls"
322
+ }
323
+ ]
324
+ }
325
+ ```
326
+
327
+ #### Radio Buttons (Single-select)
328
+
329
+ ```json
330
+ {
331
+ "name": "contact_method",
332
+ "type": "CHECK",
333
+ "title": "Preferred contact method",
334
+ "radio": true,
335
+ "items": [
336
+ {
337
+ "id": "email",
338
+ "label": "Email"
339
+ },
340
+ {
341
+ "id": "phone",
342
+ "label": "Phone"
343
+ },
344
+ {
345
+ "id": "sms",
346
+ "label": "SMS"
347
+ }
348
+ ]
349
+ }
350
+ ```
351
+
352
+ ### Date Picker
353
+
354
+ Single date selection with optional busy day configuration.
355
+
356
+ ```json
357
+ {
358
+ "name": "appointment_date",
359
+ "type": "DATE",
360
+ "title": "Select appointment date",
361
+ "mandatory": true,
362
+ "defaultBusyDays": {
363
+ "blockWeekends": true,
364
+ "blockCurrentDay": true,
365
+ "blockNextBusinessDays": 1
366
+ }
367
+ }
368
+ ```
369
+
370
+ #### Date with Available Days
371
+
372
+ ```json
373
+ {
374
+ "name": "service_date",
375
+ "type": "DATE",
376
+ "title": "Preferred service date",
377
+ "defaultBusyDays": {
378
+ "availableDays": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"]
379
+ }
380
+ }
381
+ ```
382
+
383
+ ### Date Range Picker
384
+
385
+ Select a start and end date.
386
+
387
+ ```json
388
+ {
389
+ "name": "vacation_dates",
390
+ "type": "DATERANGE",
391
+ "title": "Select date range",
392
+ "preselecteDates": {
393
+ "from": "2024-01-01",
394
+ "to": "2024-01-07"
395
+ }
396
+ }
397
+ ```
398
+
399
+ ### Card
400
+
401
+ Display-only card with optional image, header, and text content.
402
+
403
+ ```json
404
+ {
405
+ "name": "info_card",
406
+ "type": "CARD",
407
+ "header": {
408
+ "title": "Service Information",
409
+ "subheader": "What to expect"
410
+ },
411
+ "media": {
412
+ "imageUrl": "https://example.com/image.jpg",
413
+ "alt": "Service image",
414
+ "height": 200,
415
+ "width": 400
416
+ },
417
+ "text": "Our technicians will arrive within the scheduled time window.",
418
+ "variant": "outlined",
419
+ "color": "primary"
420
+ }
421
+ ```
422
+
423
+ ## Common Field Properties
424
+
425
+ All field types support these common properties:
426
+
427
+ - `name` (string, required) - Field identifier used in form data
428
+ - `type` (string, required) - Field type (TEXT, DROPDOWN, CHIPS, CHECK, DATE, DATERANGE, CARD)
429
+ - `title` (string, optional) - Display label for the field
430
+ - `mandatory` (boolean, optional) - Whether the field is required
431
+ - `mandatoryError` (string, optional) - Custom error message when required field is empty
432
+ - `condition` (string, optional) - JavaScript expression to conditionally show field (e.g., `"service === 'repair'"`)
433
+ - `style` (object, optional) - React CSSProperties object for custom styling
434
+ - `shape` (string, optional) - Visual shape: "ROUND" or "SQUARE"
435
+ - `mandatoryGroup` (string, optional) - Group name for "one of" validation
@@ -8,6 +8,8 @@ export declare const DefaultBlank: VFC;
8
8
  export declare const Styled: VFC;
9
9
  export declare const AutoOpened: VFC;
10
10
  export declare const WithIframe: FC;
11
+ export declare const WithCustomFont: FC;
12
+ export declare const WithCustomFontAndOverride: FC;
11
13
  export declare function buildDefaultTheme(_opts: {
12
14
  fontFamily?: string;
13
15
  }): FormWidgetTheme;
@@ -2,5 +2,6 @@ import { Meta } from "@storybook/react";
2
2
  declare const _default: Meta;
3
3
  export default _default;
4
4
  export declare const Default: any;
5
+ export declare const DefaultWithConsent: any;
5
6
  export declare const WithFormServiceOptions: any;
6
7
  export declare const WithFormServiceOptionsZipCodeServiceArea: any;
@@ -0,0 +1,8 @@
1
+ import { Meta } from "@storybook/react";
2
+ declare const _default: Meta;
3
+ export default _default;
4
+ export declare const Default: any;
5
+ export declare const WithManyOptions: any;
6
+ export declare const NoTitle: any;
7
+ export declare const WithFreeFormInput: any;
8
+ export declare const MultipleFreeFormOptions: any;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Form, FormContainer, FormProps, FormWidget, FormWidgetProps, FormDisplay, WidgetStylesheet, } from "./components";
2
2
  export { FormWidgetConfig, StentorApiConfig } from "./config";
3
- export { FormWidgetCardTheme, FormWidgetCheckboxTheme, FormWidgetChipsTheme, FormWidgetDateTheme, FormWidgetDropdownTheme, FormWidgetTextTheme, } from "@xapp/stentor-form-widget-channel";
3
+ export { FormWidgetCardTheme, FormWidgetCheckboxTheme, FormWidgetChipsTheme, FormWidgetDateTheme, FormWidgetDropdownTheme, FormWidgetFontTheme, FormWidgetTextTheme, } from "@xapp/stentor-form-widget-channel";
4
4
  export { SearchIcon, SpinnerIcon, LeftAngleIcon, RightAngleIcon } from "./components/icons";
5
5
  export { parseWidgetEnv } from "./utils/parseWidgetEnv";
6
6
  export * from "./components/FormDisplay/model";