@voxket-ai/events-sdk 1.0.4 → 1.0.6

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,349 +1,382 @@
1
- # @voxket-ai/events-sdk
2
-
3
- > Enterprise embeddable event registration, ticketing, and attendee self-service portal SDK for Voxket.
4
-
5
- [![npm version](https://img.shields.io/npm/v/@voxket-ai/events-sdk.svg)](https://www.npmjs.com/package/@voxket-ai/events-sdk)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
-
8
- ---
9
-
10
- ## Features
11
-
12
- - **Multiple Display Formats**: Seamlessly embed as an inline `widget`, a floating corner `popup`, or a `fullscreen` modal.
13
- - **Interactive Corner Snapping**: In popup mode, attendees can slide/drag the collapsed widget to any screen corner (`bottom-right`, `bottom-left`, `top-right`, `top-left`).
14
- - **Shadow DOM Isolation**: Runs inside an isolated Shadow Root so host CSS styles and framework resets never bleed in or break the widget layout.
15
- - **Configurable Dark & Light Themes**: Full host-configured dark mode (`bg-black text-white`) and light mode with custom brand primary colors and typography.
16
- - **Event Callbacks (`onError`, `onRegister`)**: Native typed callbacks to easily display host toast notifications, trigger analytics, or redirect users.
17
- - **Attendee Self-Service Portal**: Attendees can log in, request OTP/verification codes, update registration fields, upload documents, and purchase add-ons.
18
- - **Draft Auto-save & Instant Recovery**: Automatically tracks in-progress form inputs and seamlessly recovers drafts via `xref_id` or email.
19
- - **Configurable Network Timeout**: Built-in 2-minute (`120,000 ms`) timeout across all API operations to handle slow mobile networks cleanly.
20
- - **Framework Agnostic & React Support**: Usable via vanilla JavaScript (`EventWidgetClient`) or directly as a declarative React component (`EventWidget`).
21
-
22
- ---
23
-
24
- ## Installation
25
-
26
- ```bash
27
- npm install @voxket-ai/events-sdk
28
- ```
29
-
30
- Or via Yarn / pnpm:
31
-
32
- ```bash
33
- yarn add @voxket-ai/events-sdk
34
- # or
35
- pnpm add @voxket-ai/events-sdk
36
- ```
37
-
38
- ---
39
-
40
- ## Quick Start
41
-
42
- ### 1. React Applications
43
-
44
- Import `EventWidget` and pass your `WidgetConfig`:
45
-
46
- ```tsx
47
- import React from 'react';
48
- import { EventWidget, type WidgetConfig } from '@voxket-ai/events-sdk';
49
-
50
- export function RegistrationSection() {
51
- const config: WidgetConfig = {
52
- eventSlug: 'fogsi-yuva_2026',
53
- baseUrl: 'https://api.voxket.com',
54
- displayMode: 'popup', // 'popup' | 'widget' | 'fullscreen'
55
- position: 'bottom-right',
56
- themeMode: 'light', // 'light' | 'dark'
57
- theme: {
58
- primaryColor: '#8b5cf6',
59
- fontFamily: 'Inter, system-ui, sans-serif'
60
- },
61
- // Fired when registration is completed
62
- onRegister: (data) => {
63
- console.log('Registered successfully:', data);
64
- alert(`Registration confirmed! Reference: ${data.payload.xref_id || 'N/A'}`);
65
- },
66
- // Fired on validation, submission, or network failure
67
- onError: (err) => {
68
- console.error('Widget error:', err);
69
- alert(`Error [${err.type}]: ${err.message}`);
70
- }
71
- };
72
-
73
- return <EventWidget config={config} />;
74
- }
75
- ```
76
-
77
- ---
78
-
79
- ### 2. Vanilla JavaScript / HTML
80
-
81
- Use `EventWidgetClient` to mount and manage the widget programmatically:
82
-
83
- ```html
84
- <!DOCTYPE html>
85
- <html lang="en">
86
- <head>
87
- <meta charset="UTF-8" />
88
- <title>Event Registration</title>
89
- </head>
90
- <body>
91
- <!-- Mount target for inline widget or popup anchor -->
92
- <div id="voxket-widget-container"></div>
93
-
94
- <script type="module">
95
- import { EventWidgetClient } from '@voxket-ai/events-sdk';
96
-
97
- const client = new EventWidgetClient({
98
- eventSlug: 'fogsi-yuva_2026',
99
- baseUrl: 'https://api.voxket.com',
100
- displayMode: 'popup',
101
- position: 'bottom-right',
102
- themeMode: 'dark', // Enable dark mode
103
- theme: {
104
- primaryColor: '#6366f1'
105
- },
106
- onRegister: (data) => {
107
- console.log('Registration complete:', data);
108
- },
109
- onError: (error) => {
110
- console.error('Error occurred:', error.message);
111
- }
112
- });
113
-
114
- // Mount to the DOM
115
- client.mount('voxket-widget-container');
116
-
117
- // Dynamically update configuration without unmounting
118
- // client.updateConfig({ position: 'bottom-left' });
119
-
120
- // Clean up when leaving the page
121
- // client.unmount();
122
- </script>
123
- </body>
124
- </html>
125
- ```
126
-
127
- ---
128
-
129
- ### 3. Abstract Submission Page
130
-
131
- Set `isAbstract: true` to render a dedicated abstract page. It uses the same form types and form UI as registration.
132
-
133
- - **No Attendee Login tab.** The page shows only the form types.
134
- - **Review fields are shown.** Fields with `is_review: true` or `false` both appear. Review fields get a card that takes either a file or text, one at a time (**Send text only** / **Send file** toggle).
135
- - **Review uploads authenticate by email.** They go to `POST /api/portal/{slug}/me/submissions/` with the email entered in the form; no bearer token is sent.
136
- - **The submit call carries a flag.** The form posts to the registration submit API with `accept_review_file: true`, and draft saves send the same flag.
137
- - **After submitting:** a "Submitted" screen with a **Submit Again** button. There is no payment step.
138
-
139
- **React**
140
-
141
- ```tsx
142
- <EventWidget
143
- config={{
144
- eventSlug: 'fogsi-yuva_2026',
145
- baseUrl: 'https://api.voxket.com',
146
- displayMode: 'widget', // full-page
147
- isAbstract: true,
148
- theme: { primaryColor: '#c026d3' },
149
- onEvent: (name, payload) => console.log(name, payload),
150
- onError: (err) => console.error(err.message),
151
- }}
152
- />
153
- ```
154
-
155
- **Vanilla JS**
156
-
157
- ```js
158
- const client = new EventWidgetClient({
159
- eventSlug: 'fogsi-yuva_2026',
160
- baseUrl: 'https://api.voxket.com',
161
- displayMode: 'fullscreen',
162
- isAbstract: true,
163
- });
164
- client.mount('voxket-widget-container');
165
-
166
- // Switch an existing widget between registration and abstract
167
- // client.updateConfig({ isAbstract: false });
168
- ```
169
-
170
- To host both pages, render one widget per page (or route) and set `isAbstract` on the abstract one only.
171
-
172
- ---
173
-
174
- ## Configuration Reference (`WidgetConfig`)
175
-
176
- All available options for the `WidgetConfig` object:
177
-
178
- | Parameter | Type | Default | Description |
179
- | :--- | :--- | :--- | :--- |
180
- | `eventSlug` | `string` | *(Required)* | The unique identifier/slug of the event in Voxket. |
181
- | `baseUrl` | `string` | *(Required)* | API base URL for Voxket backend endpoints. |
182
- | `displayMode` | `'popup' \| 'widget' \| 'fullscreen'` | `'widget'` | Layout style: floating popup badge, inline embedded container, or full viewport modal. |
183
- | `position` | `WidgetPosition` | `'bottom-right'` | Starting corner for popup mode. Options: `'bottom-right'`, `'bottom-left'`, `'top-right'`, `'top-left'`, `'right-bottom'`, `'left-bottom'`, `'right-top'`, `'left-top'`. |
184
- | `themeMode` | `'light' \| 'dark'` | `'light'` | Controls the base color scheme (clean white/gray or deep black `#000` with high-contrast text). |
185
- | `theme` | `object` | `{}` | Detailed appearance customization (see below). |
186
- | `theme.primaryColor` | `string` | `'#2563eb'` | Brand color used for primary buttons, tabs, highlights, and headers. |
187
- | `theme.fontFamily` | `string` | System font | Custom font family CSS string (e.g. `'Inter, sans-serif'`). |
188
- | `theme.mode` | `'light' \| 'dark' \| 'blue' \| 'white' \| 'custom'` | `'light'` | Preset theme mode alias. |
189
- | `isAbstract` | `boolean` | `false` | Abstract submission page: no attendee login, shows `is_review` fields, adds `accept_review_file: true` on submit. See [Abstract Submission Page](#3-abstract-submission-page). |
190
- | `headerBannerImage` | `string` | `undefined` | Image shown on the right of the top header strip. The header also gets a theme-color gradient that the image fades into. |
191
- | `listBackgroundImage` | `string` | `undefined` | Faded background image behind the form-types list. The tabs row keeps the light/dark theme color. |
192
- | `backgroundImage` | `string` | `undefined` | Optional wallpaper URL shown behind the forms. Also accepted as `theme.backgroundImage`. |
193
- | `width` | `string` | `undefined` | Custom width override (e.g. `'500px'`, `'100%'`). |
194
- | `height` | `string` | `undefined` | Custom height override (e.g. `'700px'`, `'650px'`). |
195
- | `timeoutMs` | `number` | `120000` *(2 min)* | Network request timeout in milliseconds before triggering `onError`. |
196
- | `debug` | `boolean` | `false` | Enables verbose debug logging in the browser console. |
197
- | `onRegister` | `(data: RegistrationSuccessPayload) => void` | `undefined` | Callback fired when an attendee completes registration successfully. |
198
- | `onRegistered` | `(data: RegistrationSuccessPayload) => void` | `undefined` | Alias for `onRegister`. |
199
- | `onError` | `(error: WidgetErrorPayload) => void` | `undefined` | Callback fired on validation, submission, network, or schema load errors. |
200
- | `onEvent` | `(eventName: string, payload: any) => void` | `undefined` | Optional generic event bus for internal widget lifecycle events. |
201
-
202
- **Common `onEvent` names:**
203
-
204
- | Event | When it fires |
205
- | :--- | :--- |
206
- | `form_loaded` | The form schema has loaded. |
207
- | `draft_saved` | Form progress was auto-saved. |
208
- | `submitted` | The form was submitted (registration or abstract). |
209
- | `review_submission_uploaded` | A review field was submitted from the abstract page. |
210
- | `portal_submission_uploaded` | A review field was submitted from the attendee portal. |
211
- | `portal_file_deleted` | The attendee deleted an uploaded file in the portal. |
212
- | `attendee_profile_loaded` | The attendee portal profile has loaded. |
213
-
214
- ---
215
-
216
- ## Event Callbacks & Toast Notifications
217
-
218
- The SDK exposes dedicated callback functions so host applications can handle state transitions and show native toast notifications.
219
-
220
- ### 1. `onError`
221
-
222
- Fires whenever an operation fails (form validation failure, network disconnect, timeout, attendee login error, or profile update issue):
223
-
224
- ```typescript
225
- onError: (err: WidgetErrorPayload) => void;
226
- ```
227
-
228
- **Payload Schema:**
229
- ```typescript
230
- interface WidgetErrorPayload {
231
- type: 'submit_error' | 'schema_load' | 'login_error' | 'profile_update_error' | 'file_upload_error' | 'network_error' | string;
232
- message: string;
233
- error?: any;
234
- }
235
- ```
236
-
237
- **Toast Example (React Toastify / Sonner / AntD):**
238
- ```tsx
239
- const config: WidgetConfig = {
240
- // ...
241
- onError: (err) => {
242
- // Show toast in your host application
243
- toast.error(err.message, {
244
- description: `Error code: ${err.type}`
245
- });
246
- }
247
- };
248
- ```
249
-
250
- ---
251
-
252
- ### 2. `onRegister` (or `onRegistered`)
253
-
254
- Fires when an attendee successfully submits their registration form:
255
-
256
- ```typescript
257
- onRegister: (data: RegistrationSuccessPayload) => void;
258
- ```
259
-
260
- **Payload Schema:**
261
- ```typescript
262
- interface RegistrationSuccessPayload {
263
- registrationType: string | number; // Selected ticket type
264
- payload: Record<string, any>; // Form field responses submitted
265
- response?: any; // Raw backend API response
266
- paymentUrl?: string | null; // Gateway URL if payment is required
267
- }
268
- ```
269
-
270
- **Toast & Redirect Example:**
271
- ```tsx
272
- const config: WidgetConfig = {
273
- // ...
274
- onRegister: (data) => {
275
- toast.success(`Registration received for ${data.registrationType}!`);
276
-
277
- if (data.paymentUrl) {
278
- console.log('Payment gateway URL ready:', data.paymentUrl);
279
- }
280
- }
281
- };
282
- ```
283
-
284
- ---
285
-
286
- ## Draggable Corner Positioning (Popup Mode)
287
-
288
- When `displayMode: 'popup'` is active:
289
- 1. The widget renders as a compact floating badge at the configured `position` (e.g. `bottom-right`).
290
- 2. **Move Handle**: Hovering over the badge reveals a corner drag handle (`Move` icon at the top-left of the badge).
291
- 3. **Corner Snapping**: Clicking and dragging the badge moves it across the screen; releasing snaps it to the nearest corner (`bottom-right`, `bottom-left`, `top-right`, or `top-left`).
292
- 4. Once the popup is opened into full view, positioning is locked to prevent accidental movement during form completion.
293
-
294
- ---
295
-
296
- ## Dark Mode Support
297
-
298
- Theme mode is configured by the host application via `themeMode`:
299
-
300
- ```typescript
301
- const config: WidgetConfig = {
302
- eventSlug: 'fogsi-yuva_2026',
303
- baseUrl: 'https://api.voxket.com',
304
- themeMode: 'dark', // 'dark' | 'light'
305
- theme: {
306
- primaryColor: '#8b5cf6'
307
- }
308
- };
309
- ```
310
-
311
- - When set to `'dark'`, all views—Ticket Selector, Attendee Portal, Dynamic Form Inputs, Payment Screens, and Error Modals—render in high-contrast deep black (`#000000`) and dark zinc tones with crisp borders.
312
- - Attendees cannot override the theme from within the widget headers; theme configuration is strictly controlled by your application config.
313
-
314
- ---
315
-
316
- ## Client API Methods (`EventWidgetClient`)
317
-
318
- When using the vanilla JavaScript / non-React API:
319
-
320
- | Method | Description |
321
- | :--- | :--- |
322
- | `mount(container: HTMLElement \| string)` | Mounts the widget into a DOM container element or element ID. |
323
- | `updateConfig(newConfig: Partial<WidgetConfig>)` | Merges new configuration values into the running widget without remounting. |
324
- | `setConfig(newConfig: WidgetConfig)` | Replaces the entire widget configuration. |
325
- | `unmount()` | Cleanly destroys the React root, removes DOM nodes, and releases event listeners. |
326
-
327
- ---
328
-
329
- ## TypeScript Exports
330
-
331
- All primary types are exported directly from the package:
332
-
333
- ```typescript
334
- import {
335
- EventWidget,
336
- EventWidgetClient,
337
- type WidgetConfig,
338
- type WidgetPosition,
339
- type ThemeMode,
340
- type RegistrationSuccessPayload,
341
- type WidgetErrorPayload
342
- } from '@voxket-ai/events-sdk';
343
- ```
344
-
345
- ---
346
-
347
- ## License
348
-
349
- MIT © Voxket
1
+ # @voxket-ai/events-sdk
2
+
3
+ > Enterprise embeddable event registration, ticketing, and attendee self-service portal SDK for Voxket.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@voxket-ai/events-sdk.svg)](https://www.npmjs.com/package/@voxket-ai/events-sdk)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ ---
9
+
10
+ ## Features
11
+
12
+ - **Multiple Display Formats**: Seamlessly embed as an inline `widget`, a floating corner `popup`, or a `fullscreen` modal.
13
+ - **Interactive Corner Snapping**: In popup mode, attendees can slide/drag the collapsed widget to any screen corner (`bottom-right`, `bottom-left`, `top-right`, `top-left`).
14
+ - **Shadow DOM Isolation**: Runs inside an isolated Shadow Root so host CSS styles and framework resets never bleed in or break the widget layout.
15
+ - **Configurable Dark & Light Themes**: Full host-configured dark mode (`bg-black text-white`) and light mode with custom brand primary colors and typography.
16
+ - **Event Callbacks (`onError`, `onRegister`)**: Native typed callbacks to easily display host toast notifications, trigger analytics, or redirect users.
17
+ - **Attendee Self-Service Portal**: Attendees can log in, request OTP/verification codes, update registration fields, upload documents, and purchase add-ons.
18
+ - **Draft Auto-save & Instant Recovery**: Automatically tracks in-progress form inputs and seamlessly recovers drafts via `xref_id` or email.
19
+ - **Configurable Network Timeout**: Built-in 2-minute (`120,000 ms`) timeout across all API operations to handle slow mobile networks cleanly.
20
+ - **Framework Agnostic & React Support**: Usable via vanilla JavaScript (`EventWidgetClient`) or directly as a declarative React component (`EventWidget`).
21
+
22
+ ---
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install @voxket-ai/events-sdk
28
+ ```
29
+
30
+ Or via Yarn / pnpm:
31
+
32
+ ```bash
33
+ yarn add @voxket-ai/events-sdk
34
+ # or
35
+ pnpm add @voxket-ai/events-sdk
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Quick Start
41
+
42
+ ### 1. React Applications
43
+
44
+ Import `EventWidget` and pass your `WidgetConfig`:
45
+
46
+ ```tsx
47
+ import React from 'react';
48
+ import { EventWidget, type WidgetConfig } from '@voxket-ai/events-sdk';
49
+
50
+ export function RegistrationSection() {
51
+ const config: WidgetConfig = {
52
+ eventSlug: 'fogsi-yuva_2026',
53
+ baseUrl: 'https://api.voxket.com',
54
+ displayMode: 'popup', // 'popup' | 'widget' | 'fullscreen'
55
+ position: 'bottom-right',
56
+ themeMode: 'light', // 'light' | 'dark'
57
+ theme: {
58
+ primaryColor: '#8b5cf6',
59
+ fontFamily: 'Inter, system-ui, sans-serif'
60
+ },
61
+ // Fired when registration is completed
62
+ onRegister: (data) => {
63
+ console.log('Registered successfully:', data);
64
+ alert(`Registration confirmed! Reference: ${data.payload.xref_id || 'N/A'}`);
65
+ },
66
+ // Fired on validation, submission, or network failure
67
+ onError: (err) => {
68
+ console.error('Widget error:', err);
69
+ alert(`Error [${err.type}]: ${err.message}`);
70
+ }
71
+ };
72
+
73
+ return <EventWidget config={config} />;
74
+ }
75
+ ```
76
+
77
+ ---
78
+
79
+ ### 2. Vanilla JavaScript / HTML
80
+
81
+ Use `EventWidgetClient` to mount and manage the widget programmatically:
82
+
83
+ ```html
84
+ <!DOCTYPE html>
85
+ <html lang="en">
86
+ <head>
87
+ <meta charset="UTF-8" />
88
+ <title>Event Registration</title>
89
+ </head>
90
+ <body>
91
+ <!-- Mount target for inline widget or popup anchor -->
92
+ <div id="voxket-widget-container"></div>
93
+
94
+ <script type="module">
95
+ import { EventWidgetClient } from '@voxket-ai/events-sdk';
96
+
97
+ const client = new EventWidgetClient({
98
+ eventSlug: 'fogsi-yuva_2026',
99
+ baseUrl: 'https://api.voxket.com',
100
+ displayMode: 'popup',
101
+ position: 'bottom-right',
102
+ themeMode: 'dark', // Enable dark mode
103
+ theme: {
104
+ primaryColor: '#6366f1'
105
+ },
106
+ onRegister: (data) => {
107
+ console.log('Registration complete:', data);
108
+ },
109
+ onError: (error) => {
110
+ console.error('Error occurred:', error.message);
111
+ }
112
+ });
113
+
114
+ // Mount to the DOM
115
+ client.mount('voxket-widget-container');
116
+
117
+ // Dynamically update configuration without unmounting
118
+ // client.updateConfig({ position: 'bottom-left' });
119
+
120
+ // Clean up when leaving the page
121
+ // client.unmount();
122
+ </script>
123
+ </body>
124
+ </html>
125
+ ```
126
+
127
+ ---
128
+
129
+ ### 3. Abstract Submission Page
130
+
131
+ Set `isAbstract: true` to render a dedicated abstract page. It uses the same form types and form UI as registration.
132
+
133
+ - **No Attendee Login tab.** The page shows only the form types.
134
+ - **Review fields are shown.** Fields with `is_review: true` or `false` both appear. Review fields get a card that takes either a file or text, one at a time (**Send text only** / **Send file** toggle).
135
+ - **Review uploads authenticate by email.** They go to `POST /api/portal/{slug}/me/submissions/` with the email entered in the form; no bearer token is sent.
136
+ - **The submit call carries a flag.** The form posts to the registration submit API with `accept_review_file: true`, and draft saves send the same flag.
137
+ - **After submitting:** a "Submitted" screen with a **Submit Again** button. There is no payment step.
138
+
139
+ **React**
140
+
141
+ ```tsx
142
+ <EventWidget
143
+ config={{
144
+ eventSlug: 'fogsi-yuva_2026',
145
+ baseUrl: 'https://api.voxket.com',
146
+ displayMode: 'widget', // full-page
147
+ isAbstract: true,
148
+ theme: { primaryColor: '#c026d3' },
149
+ onEvent: (name, payload) => console.log(name, payload),
150
+ onError: (err) => console.error(err.message),
151
+ }}
152
+ />
153
+ ```
154
+
155
+ **Vanilla JS**
156
+
157
+ ```js
158
+ const client = new EventWidgetClient({
159
+ eventSlug: 'fogsi-yuva_2026',
160
+ baseUrl: 'https://api.voxket.com',
161
+ displayMode: 'fullscreen',
162
+ isAbstract: true,
163
+ });
164
+ client.mount('voxket-widget-container');
165
+
166
+ // Switch an existing widget between registration and abstract
167
+ // client.updateConfig({ isAbstract: false });
168
+ ```
169
+
170
+ To host both pages, render one widget per page (or route) and set `isAbstract` on the abstract one only.
171
+
172
+ ---
173
+
174
+ ## Configuration Reference (`WidgetConfig`)
175
+
176
+ All available options for the `WidgetConfig` object:
177
+
178
+ | Parameter | Type | Default | Description |
179
+ | :--- | :--- | :--- | :--- |
180
+ | `eventSlug` | `string` | *(Required)* | The unique identifier/slug of the event in Voxket. |
181
+ | `baseUrl` | `string` | *(Required)* | API base URL for Voxket backend endpoints. |
182
+ | `displayMode` | `'popup' \| 'widget' \| 'fullscreen'` | `'widget'` | Layout style: floating popup badge, inline embedded container, or full viewport modal. |
183
+ | `position` | `WidgetPosition` | `'bottom-right'` | Starting corner for popup mode. Options: `'bottom-right'`, `'bottom-left'`, `'top-right'`, `'top-left'`, `'right-bottom'`, `'left-bottom'`, `'right-top'`, `'left-top'`. |
184
+ | `themeMode` | `'light' \| 'dark'` | `'light'` | Controls the base color scheme (clean white/gray or deep black `#000` with high-contrast text). |
185
+ | `theme` | `object` | `{}` | Detailed appearance customization (see below). |
186
+ | `theme.primaryColor` | `string` | `'#2563eb'` | Brand color used for primary buttons, tabs, highlights, and headers. |
187
+ | `theme.fontFamily` | `string` | System font | Custom font family CSS string (e.g. `'Inter, sans-serif'`). |
188
+ | `theme.mode` | `'light' \| 'dark' \| 'blue' \| 'white' \| 'custom'` | `'light'` | Preset theme mode alias. |
189
+ | `isAbstract` | `boolean` | `false` | Abstract submission page: no attendee login, shows `is_review` fields, adds `accept_review_file: true` on submit. See [Abstract Submission Page](#3-abstract-submission-page). |
190
+ | `headerBannerImage` | `string` | `undefined` | Banner image on the right of the top header, scaled to the header's height; its left edge fades into the header's theme-color gradient. See [Banner & Background Images](#banner--background-images). |
191
+ | `backgroundImage` | `string` | `undefined` | Faded background image behind the form-types list, the form page and the attendee login/portal. It stays still while content scrolls. See [Banner & Background Images](#banner--background-images). |
192
+ | `width` | `string` | `undefined` | Custom width override (e.g. `'500px'`, `'100%'`). |
193
+ | `height` | `string` | `undefined` | Custom height override (e.g. `'700px'`, `'650px'`). |
194
+ | `timeoutMs` | `number` | `120000` *(2 min)* | Network request timeout in milliseconds before triggering `onError`. |
195
+ | `debug` | `boolean` | `false` | Enables verbose debug logging in the browser console. |
196
+ | `onRegister` | `(data: RegistrationSuccessPayload) => void` | `undefined` | Callback fired when an attendee completes registration successfully. |
197
+ | `onRegistered` | `(data: RegistrationSuccessPayload) => void` | `undefined` | Alias for `onRegister`. |
198
+ | `onError` | `(error: WidgetErrorPayload) => void` | `undefined` | Callback fired on validation, submission, network, or schema load errors. |
199
+ | `onEvent` | `(eventName: string, payload: any) => void` | `undefined` | Optional generic event bus for internal widget lifecycle events. |
200
+
201
+ **Common `onEvent` names:**
202
+
203
+ | Event | When it fires |
204
+ | :--- | :--- |
205
+ | `form_loaded` | The form schema has loaded. |
206
+ | `draft_saved` | Form progress was auto-saved. |
207
+ | `submitted` | The form was submitted (registration or abstract). |
208
+ | `review_submission_uploaded` | A review field was submitted from the abstract page. |
209
+ | `portal_submission_uploaded` | A review field was submitted from the attendee portal. |
210
+ | `portal_file_deleted` | The attendee deleted an uploaded file in the portal. |
211
+ | `attendee_profile_loaded` | The attendee portal profile has loaded. |
212
+
213
+ ---
214
+
215
+ ## Event Callbacks & Toast Notifications
216
+
217
+ The SDK exposes dedicated callback functions so host applications can handle state transitions and show native toast notifications.
218
+
219
+ ### 1. `onError`
220
+
221
+ Fires whenever an operation fails (form validation failure, network disconnect, timeout, attendee login error, or profile update issue):
222
+
223
+ ```typescript
224
+ onError: (err: WidgetErrorPayload) => void;
225
+ ```
226
+
227
+ **Payload Schema:**
228
+ ```typescript
229
+ interface WidgetErrorPayload {
230
+ type: 'submit_error' | 'schema_load' | 'login_error' | 'profile_update_error' | 'file_upload_error' | 'network_error' | string;
231
+ message: string;
232
+ error?: any;
233
+ }
234
+ ```
235
+
236
+ **Toast Example (React Toastify / Sonner / AntD):**
237
+ ```tsx
238
+ const config: WidgetConfig = {
239
+ // ...
240
+ onError: (err) => {
241
+ // Show toast in your host application
242
+ toast.error(err.message, {
243
+ description: `Error code: ${err.type}`
244
+ });
245
+ }
246
+ };
247
+ ```
248
+
249
+ ---
250
+
251
+ ### 2. `onRegister` (or `onRegistered`)
252
+
253
+ Fires when an attendee successfully submits their registration form:
254
+
255
+ ```typescript
256
+ onRegister: (data: RegistrationSuccessPayload) => void;
257
+ ```
258
+
259
+ **Payload Schema:**
260
+ ```typescript
261
+ interface RegistrationSuccessPayload {
262
+ registrationType: string | number; // Selected ticket type
263
+ payload: Record<string, any>; // Form field responses submitted
264
+ response?: any; // Raw backend API response
265
+ paymentUrl?: string | null; // Gateway URL if payment is required
266
+ }
267
+ ```
268
+
269
+ **Toast & Redirect Example:**
270
+ ```tsx
271
+ const config: WidgetConfig = {
272
+ // ...
273
+ onRegister: (data) => {
274
+ toast.success(`Registration received for ${data.registrationType}!`);
275
+
276
+ if (data.paymentUrl) {
277
+ console.log('Payment gateway URL ready:', data.paymentUrl);
278
+ }
279
+ }
280
+ };
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Draggable Corner Positioning (Popup Mode)
286
+
287
+ When `displayMode: 'popup'` is active:
288
+ 1. The widget renders as a compact floating badge at the configured `position` (e.g. `bottom-right`).
289
+ 2. **Move Handle**: Hovering over the badge reveals a corner drag handle (`Move` icon at the top-left of the badge).
290
+ 3. **Corner Snapping**: Clicking and dragging the badge moves it across the screen; releasing snaps it to the nearest corner (`bottom-right`, `bottom-left`, `top-right`, or `top-left`).
291
+ 4. Once the popup is opened into full view, positioning is locked to prevent accidental movement during form completion.
292
+
293
+ ---
294
+
295
+ ## Dark Mode Support
296
+
297
+ Theme mode is configured by the host application via `themeMode`:
298
+
299
+ ```typescript
300
+ const config: WidgetConfig = {
301
+ eventSlug: 'fogsi-yuva_2026',
302
+ baseUrl: 'https://api.voxket.com',
303
+ themeMode: 'dark', // 'dark' | 'light'
304
+ theme: {
305
+ primaryColor: '#8b5cf6'
306
+ }
307
+ };
308
+ ```
309
+
310
+ - When set to `'dark'`, all views—Ticket Selector, Attendee Portal, Dynamic Form Inputs, Payment Screens, and Error Modals—render in high-contrast deep black (`#000000`) and dark zinc tones with crisp borders.
311
+ - Attendees cannot override the theme from within the widget headers; theme configuration is strictly controlled by your application config.
312
+
313
+ ---
314
+
315
+ ## Registration Number & `?rn=` Success Link
316
+
317
+ - After a successful submit, the widget shows the `registration_number` from the submit response with a **Copy** button. It appears on both the success screen and the "complete your payment" screen.
318
+ - If the page URL has `?rn=<registration number>` (for example, the URL the payment gateway redirects back to), the widget opens straight on the success screen with that number. Popup mode opens automatically. **Back** removes `rn` from the URL and returns to the form types.
319
+
320
+ ```
321
+ https://your-site.com/register?rn=FOGS-2026-00030
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Banner & Background Images
327
+
328
+ ```typescript
329
+ const config: WidgetConfig = {
330
+ eventSlug: 'fogsi-yuva_2026',
331
+ baseUrl: 'https://api.voxket.com',
332
+ theme: { primaryColor: '#c026d3' },
333
+ headerBannerImage: 'https://i.postimg.cc/Hk02BDTh/image.png',
334
+ backgroundImage: 'https://i.postimg.cc/DZmb4dtH/Screenshot-2026-09-24-200659.png',
335
+ };
336
+ ```
337
+
338
+ | Prop | Where it shows | Behaviour |
339
+ | :--- | :--- | :--- |
340
+ | `headerBannerImage` | Right side of the top header, on every view (registration, attendee login, abstract) | Scaled to the header's height and never makes the header taller. Its left edge fades into the header gradient. Uses at most 65% of the header width; on narrow screens the image is cropped from the left. |
341
+ | `backgroundImage` | Behind the form-types list, the form page and the attendee login/portal | Covered by a page-colored overlay so content stays readable; the overlay follows `themeMode` (light or dark). Stays still while content scrolls. Cards and form inputs keep their normal colors. |
342
+
343
+ - The header always uses a theme-color gradient, whether or not a banner is set.
344
+ - The tabs row is not affected by either image; it keeps the light/dark theme color.
345
+ - Both images are optional. Leave them out for a plain gradient header and a solid page background.
346
+
347
+ ---
348
+
349
+ ## Client API Methods (`EventWidgetClient`)
350
+
351
+ When using the vanilla JavaScript / non-React API:
352
+
353
+ | Method | Description |
354
+ | :--- | :--- |
355
+ | `mount(container: HTMLElement \| string)` | Mounts the widget into a DOM container element or element ID. |
356
+ | `updateConfig(newConfig: Partial<WidgetConfig>)` | Merges new configuration values into the running widget without remounting. |
357
+ | `setConfig(newConfig: WidgetConfig)` | Replaces the entire widget configuration. |
358
+ | `unmount()` | Cleanly destroys the React root, removes DOM nodes, and releases event listeners. |
359
+
360
+ ---
361
+
362
+ ## TypeScript Exports
363
+
364
+ All primary types are exported directly from the package:
365
+
366
+ ```typescript
367
+ import {
368
+ EventWidget,
369
+ EventWidgetClient,
370
+ type WidgetConfig,
371
+ type WidgetPosition,
372
+ type ThemeMode,
373
+ type RegistrationSuccessPayload,
374
+ type WidgetErrorPayload
375
+ } from '@voxket-ai/events-sdk';
376
+ ```
377
+
378
+ ---
379
+
380
+ ## License
381
+
382
+ MIT © Voxket