@codebards/ik-embeddable-form 1.0.13 → 1.0.15

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
@@ -2,6 +2,8 @@
2
2
 
3
3
  A production-ready, config-driven embeddable form platform built with **Preact**, **TypeScript**, **Vite**, **Tailwind CSS**, and **Shadow DOM** isolation.
4
4
 
5
+ > **Integrating the form on your site?** See **[INTEGRATION.md](INTEGRATION.md)** for step-by-step guides (HTML, WordPress, React), variant usage, custom JSON variants, and fallback behavior.
6
+
5
7
  ---
6
8
 
7
9
  ## Table of Contents
@@ -36,8 +38,9 @@ src/
36
38
  │ └── Shared/ # Button · Input · Select · Textarea · Radio · Checkbox
37
39
 
38
40
  ├── configs/
39
- │ ├── sample-webinar.config.ts # Multi-step webinar registration
40
- └── sample-contact.config.ts # Conditional contact form
41
+ │ ├── gql-webinar.base.ts # Full webinar form superset
42
+ ├── gql-webinar.config.ts # Base + bundled variants registry
43
+ │ └── variants/ # Structural overrides (default, india, event)
41
44
 
42
45
  ├── hooks/
43
46
  │ ├── useFormEngine.ts # Subscribes to FormEngine state
@@ -70,7 +73,7 @@ The form is mounted inside a **Shadow DOM** attached to a `<div id="ik-form-host
70
73
  ### Via CDN (Recommended)
71
74
 
72
75
  ```html
73
- <script src="https://cdn.example.com/forms/v1/embed.js"></script>
76
+ <script src="https://cdn.example.com/forms/v1.0.11/embed.js" async></script>
74
77
  ```
75
78
 
76
79
  ### Self-hosted
@@ -85,15 +88,22 @@ npm run build:production
85
88
  ### npm (for framework integration)
86
89
 
87
90
  ```bash
88
- npm install ik-embeddable-form
91
+ npm install @codebards/ik-embeddable-form
89
92
  ```
90
93
 
91
94
  ```ts
92
- import { IKForm } from 'ik-embeddable-form';
95
+ import { IKForm } from '@codebards/ik-embeddable-form';
93
96
 
94
- IKForm.open({ eventName: 'my-webinar', webinarType: 'live', ... });
97
+ IKForm.open({
98
+ eventName: 'How to Nail your next Technical Interview',
99
+ webinarType: 'REGULAR',
100
+ site: 'organic',
101
+ variant: 'default',
102
+ });
95
103
  ```
96
104
 
105
+ Full integration examples (HTML, WordPress, React, variants, custom JSON): **[INTEGRATION.md](INTEGRATION.md)**
106
+
97
107
  ---
98
108
 
99
109
  ## Script Usage
@@ -101,64 +111,59 @@ IKForm.open({ eventName: 'my-webinar', webinarType: 'live', ... });
101
111
  ### Basic
102
112
 
103
113
  ```html
104
- <script src="https://cdn.example.com/forms/embed.js"></script>
114
+ <script src="https://cdn.example.com/forms/v1.0.11/embed.js" async></script>
105
115
  <script>
106
116
  window.IKForm.open({
107
- eventName: 'ai-summit-2026',
108
- webinarType: 'live',
109
- site: 'main',
110
- variant: 'default',
117
+ eventName: 'How to Nail your next Technical Interview',
118
+ webinarType: 'REGULAR',
119
+ site: 'organic', // or 'learn'
120
+ variant: 'default', // 'default' | 'india' | 'event' | content variant name
111
121
  });
112
122
  </script>
113
123
  ```
114
124
 
115
- ### With All Options
125
+ ### Common options
116
126
 
117
127
  ```ts
118
128
  window.IKForm.open({
119
129
  // Required
120
- eventName: 'ai-summit-2026', // Matches FormConfig.eventName
121
- webinarType: 'live', // Matches FormConfig.webinarType
122
- site: 'main', // Multi-site identifier (forwarded to API)
123
- variant: 'compact', // Must match a FormVariant.id (or 'default')
130
+ eventName: 'How to Nail your next Technical Interview',
131
+ webinarType: 'REGULAR',
132
+ site: 'learn',
133
+ variant: 'india',
124
134
 
125
135
  // Optional
126
- preferredSlot: 'slot-morning', // Pre-selects a slot field
127
-
128
- prefilledValues: { // Pre-fills form fields by name
129
- email: 'user@example.com',
130
- firstName: 'Jane',
136
+ prefilledValues: {
137
+ email: 'user@example.com',
138
+ fullName: 'Jane Doe',
131
139
  },
132
140
 
133
- configOverrides: { // Runtime overrides merged on top of config
134
- theme: { modalMaxWidth: '600px' },
141
+ configOverrides: {
142
+ layout: {
143
+ leftPanel: { data: { headline: 'Campaign headline' } },
144
+ },
135
145
  },
136
146
 
137
- // Callbacks
138
- onSuccess: (result) => {
139
- console.log('Form submitted:', result.data);
140
- console.log('Ticket/Reg ID:', result.data.registrationId);
141
- },
142
- onClose: () => {
143
- console.log('Modal closed');
144
- },
145
- onError: (err) => {
146
- console.error('Form error:', err.code, err.message);
147
- },
147
+ dataClickId: 'hero_cta',
148
+
149
+ // WordPress — theme already loads GTM
150
+ loadGtm: false,
151
+ loadClarity: false,
152
+
153
+ onSuccess: (result) => console.log('Submitted:', result.data),
154
+ onClose: () => console.log('Closed'),
155
+ onError: (err) => console.error(err.code, err.message),
148
156
  });
149
157
  ```
150
158
 
159
+ See **[INTEGRATION.md](INTEGRATION.md)** for WordPress, React/SPA, variant JSON, and fallback details.
160
+
151
161
  ### Programmatic Control
152
162
 
153
163
  ```ts
154
- // Close the modal
155
164
  window.IKForm.close();
156
-
157
- // Full cleanup (SPA route change)
158
- window.IKForm.destroy();
159
-
160
- // Get loaded version
161
- console.log(window.IKForm.getVersion()); // "1.0.0"
165
+ window.IKForm.destroy(); // SPA route change
166
+ console.log(window.IKForm.getVersion()); // "1.0.11"
162
167
  ```
163
168
 
164
169
  ---
@@ -352,46 +357,71 @@ The `__VERSION__` constant is automatically injected from `package.json` at buil
352
357
 
353
358
  ## Adding New Form Variants
354
359
 
355
- ### Option A New Variant on Existing Config
360
+ The form uses a **base config + variant overrides** merge pattern. See **[INTEGRATION.md](INTEGRATION.md)** for host-page usage, JSON schema, resolution order, and fallback behavior.
361
+
362
+ | Tier | Examples | Where | Deploy needed? |
363
+ |------|----------|-------|----------------|
364
+ | **Structural** | `default`, `india`, `event` | `src/configs/variants/*.variant.ts` | Yes (code review) |
365
+ | **Content** | `masterclass`, campaign names | CDN JSON at `{VITE_FORM_VARIANTS_BASE_URL}/{variant}.json` | No (upload JSON only) |
366
+
367
+ **Resolution order:** bundled variant → remote JSON → fallback to `default` (console warning).
368
+
369
+ Set `VITE_FORM_VARIANTS_BASE_URL` at build time. Local dev defaults to `/form-variants` (`public/form-variants/masterclass.json`).
356
370
 
357
- Add a `FormVariant` to the `variants` array of an existing `FormConfig`:
371
+ ### Bundled variant files
372
+
373
+ | File | Purpose |
374
+ |------|---------|
375
+ | `default.variant.ts` | Standard flow |
376
+ | `india.variant.ts` | Hide `primaryGoal` on profile step |
377
+ | `event.variant.ts` | Hide slot picker; event copy; auto-book slot |
378
+
379
+ Base config (`gql-webinar.base.ts`) holds the full superset. Each variant file declares only what differs.
380
+
381
+ ### Adding a structural variant (engineering)
382
+
383
+ 1. Create `src/configs/variants/my-variant.variant.ts` with only the diff:
358
384
 
359
385
  ```ts
360
- // src/configs/sample-webinar.config.ts
361
- variants: [
362
- {
363
- id: 'enterprise',
364
- overrides: {
365
- steps: [ /* override any step */ ],
366
- theme: { modalMaxWidth: '680px' },
386
+ import type { FormVariant } from '@/types';
387
+
388
+ export const myVariant: FormVariant = {
389
+ id: 'my-variant',
390
+ overrides: {
391
+ steps: {
392
+ 'profile-details': {
393
+ fields: { primaryGoal: { show: false } },
394
+ },
367
395
  },
368
396
  },
369
- ],
397
+ };
370
398
  ```
371
399
 
372
- Then call:
373
- ```ts
374
- IKForm.open({ eventName: 'ai-summit-2026', webinarType: 'live', variant: 'enterprise' });
375
- ```
400
+ 2. Register in `src/configs/variants/index.ts`
401
+ 3. Deploy embed
402
+
403
+ ---
404
+
405
+ ### Adding a content variant (no code deploy)
406
+
407
+ 1. Create `{variant}.json` — see [INTEGRATION.md → Create your own variant JSON](INTEGRATION.md#create-your-own-variant-json)
408
+ 2. Upload to `{VITE_FORM_VARIANTS_BASE_URL}/{variant}.json`
409
+ 3. Landing page: `IKForm.open({ ..., variant: 'masterclass' })`
410
+
411
+ ---
376
412
 
377
413
  ### Option B — New FormConfig File
378
414
 
379
- 1. Create `src/configs/my-new-form.config.ts`
380
- 2. Export a `FormConfig` object with a unique `eventName` + `webinarType`
381
- 3. Register it in `src/configs/index.ts`:
415
+ For a fundamentally different product flow (not a variant of GQL webinar):
382
416
 
383
- ```ts
384
- import { myNewFormConfig } from './my-new-form.config';
417
+ 1. Create `src/configs/my-new-form.base.ts`
418
+ 2. Export a `FormConfig` with a unique `webinarType`
419
+ 3. Register in `src/configs/index.ts`
385
420
 
386
- export const ALL_CONFIGS: FormConfig[] = [
387
- webinarConfig,
388
- contactConfig,
389
- myNewFormConfig, // ← add here
390
- ];
421
+ ```ts
422
+ IKForm.open({ webinarType: 'MASTERCLASS', variant: 'default', ... });
391
423
  ```
392
424
 
393
- No other files need to change. The platform supports **25+ variants** this way.
394
-
395
425
  ---
396
426
 
397
427
  ## Analytics Integration
@@ -408,10 +438,15 @@ The embed can **load its own GTM container** (per architecture doc) so form conv
408
438
 
409
439
  ```ts
410
440
  // Self-contained LP (embed loads GTM)
411
- IKForm.open({ eventName: '...', webinarType: 'REGULAR', site: 'organic', variant: 'default' });
441
+ IKForm.open({
442
+ eventName: 'How to Nail your next Technical Interview',
443
+ webinarType: 'REGULAR',
444
+ site: 'learn',
445
+ variant: 'default',
446
+ });
412
447
 
413
448
  // WordPress page that already has GTM-P335R9N in the theme
414
- IKForm.open({ ..., loadGtm: false });
449
+ IKForm.open({ ..., loadGtm: false, loadClarity: false });
415
450
  ```
416
451
 
417
452
  **dataLayer events** (WordPress parity + embed lifecycle):
@@ -461,9 +496,9 @@ All API calls are defined in `ApiContract` objects inside your form config — *
461
496
  ### Dynamic URL Interpolation
462
497
 
463
498
  ```ts
464
- endpoint: 'slots/{slot}/reserve'
465
- // If form data has { slot: "slot-morning" }
466
- // → POST https://api.example.com/api/slots/slot-morning/reserve
499
+ endpoint: 'webinar/{site}/add-info'
500
+ // If form data has { site: "organic" }
501
+ // → POST https://api.example.com/api/webinar/organic/add-info
467
502
  ```
468
503
 
469
504
  ### Body Mapping
@@ -491,7 +526,7 @@ responseMapping: {
491
526
  ### Auth Token
492
527
 
493
528
  ```ts
494
- import { apiClient } from 'ik-embeddable-form';
529
+ import { apiClient } from '@codebards/ik-embeddable-form';
495
530
 
496
531
  apiClient.setAuthToken('Bearer your-token-here');
497
532
  ```
@@ -511,7 +546,7 @@ import type {
511
546
  OpenConfig,
512
547
  ConditionalRule,
513
548
  IKFormSDK,
514
- } from 'ik-embeddable-form';
549
+ } from '@codebards/ik-embeddable-form';
515
550
  ```
516
551
 
517
552
  ---