drill-widgets 2.7.2

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 ADDED
@@ -0,0 +1,1119 @@
1
+ # ✨ Begin Widgets ✨
2
+
3
+ Easily embed powerful workflow building and running capabilities into your web applications!
4
+
5
+ Begin Widgets provides Lit-based web components that let you:
6
+
7
+ - Visually **build workflow templates** with custom forms and steps.
8
+ - **Run instances** of those workflows, guiding users through steps.
9
+ - Integrate seamlessly into your existing application with a simple JavaScript API.
10
+
11
+ Perfect for onboarding flows, request processes, checklists, approvals, and any task requiring structured, sequential steps.
12
+
13
+ ## Installation
14
+
15
+ ### From npm (Recommended)
16
+
17
+ ```bash
18
+ npm install begin-widgets
19
+ ```
20
+
21
+ ### From CDN
22
+
23
+ ```html
24
+ <script src="https://unpkg.com/begin-widgets/dist/begin-widgets.umd.js"></script>
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Key Features & Benefits
30
+
31
+ - **🚀 Rapid Integration:** Embed complex workflow UIs with just a few lines of JavaScript using `createBuilder` and `createRunner`.
32
+ - **🧩 Focused Builder (`builder-widget`):**
33
+ - Clean, intuitive interface to create workflow templates with steps and form elements
34
+ - Drag-and-drop step reordering for easy workflow organization
35
+ - Step-by-step template creation with title, description, and elements
36
+ - Modern UI design with proper form validation and user feedback
37
+ - Support for multiple question types and content elements
38
+ - **🏃‍♂️ Smooth Runner (`runner-widget`):**
39
+ - Self-contained: Runs entirely from a single `Instance` object snapshot
40
+ - Multiple execution modes: Default, Preview, Admin, View-Only, and Print modes for different use cases
41
+ - Guides users step-by-step with clear progress indication
42
+ - Includes comprehensive validation for required fields
43
+ - Provides clear event hooks (`onInstanceUpdated`, `onSignatureCaptured`, `onFileUploaded`) for saving progress and final results
44
+ - Responsive design that adapts to different screen sizes
45
+ - **🏗️ Modern Web Components:** Built with [Lit](https://lit.dev/) for encapsulated, reusable, and framework-agnostic components.
46
+ - **🔒 Consistent Runs:** Instances are snapshots of the workflow at creation time, ensuring that changes to the main workflow template don't break in-progress tasks.
47
+ - **🔌 Event-Driven:** Easily hook into the workflow lifecycle using callbacks to save data to your backend, trigger notifications, or update your UI.
48
+
49
+ ## Core Concepts
50
+
51
+ - **Workflow:** The reusable blueprint or template for a process, containing steps and elements (form questions and content blocks).
52
+ - **Instance:** A specific, runnable execution of a Workflow, captured as a snapshot. It includes the exact steps/elements from the Workflow at the time of creation, plus current progress and any instance-specific details.
53
+ - **Builder:** The component (`<builder-widget>`) used to create `Workflow` templates with a focused, clean interface.
54
+ - **Runner:** The component (`<runner-widget>`) used to execute an `Instance`, presenting the steps and elements to the user.
55
+
56
+ ## Runner Modes
57
+
58
+ The Runner widget supports different distinct modes for different use cases:
59
+
60
+ ### Default Mode
61
+
62
+ **Purpose:** Standard workflow execution with full functionality.
63
+
64
+ **Configuration:**
65
+
66
+ ```javascript
67
+ createRunner("runner-container", {
68
+ instance: instanceData, // Required: Instance object
69
+ mode: "default", // Optional: Default if not specified
70
+ // ... other options
71
+ });
72
+ ```
73
+
74
+ **Features:**
75
+
76
+ - ✅ **Data Persistence:** Form data is automatically saved to localStorage
77
+ - ✅ **Validation:** Required field validation runs on each step
78
+ - ✅ **Step Completion Tracking:** Progress is tracked and steps are marked as completed
79
+ - ✅ **Callbacks:** All callbacks fire (signature capture, file upload, etc.)
80
+ - ✅ **Smart Navigation:** Next button progresses through assigned steps only
81
+ - ✅ **Transparent Unassigned Steps:** Clickable sidebar access to view unassigned steps in read-only mode
82
+ - ✅ **Assignment-Based Interaction:** Full editing for assigned steps, read-only viewing for unassigned steps
83
+ - ✅ **Next/Submit Buttons:** Visible only when viewing assigned steps
84
+
85
+ **Use Cases:**
86
+
87
+ - Production workflow execution
88
+ - User onboarding processes
89
+ - Approval workflows
90
+ - Collaborative workflows where users need transparency into other steps
91
+ - Any scenario requiring data persistence, validation, and step-based assignments
92
+
93
+ #### Default Mode: Transparent Unassigned Step Viewing
94
+
95
+ In default mode, users can now click on **any step** in the sidebar for full workflow transparency:
96
+
97
+ **Assigned Steps (Full Mode):**
98
+
99
+ - ✅ **Full interaction:** Edit, validate, save, and progress through workflow
100
+ - ✅ **Navigation buttons:** Next/Save/Submit buttons are visible
101
+ - ✅ **Data persistence:** Changes are saved and callbacks fire
102
+ - 🎯 **Badge shows:** "Assigned"
103
+
104
+ **Unassigned Steps (Read-Only Mode):**
105
+
106
+ - 👁️ **View-only access:** Can see existing responses and form structure
107
+ - ❌ **No interaction:** All inputs are disabled and read-only
108
+ - ❌ **No buttons:** Next/Save/Submit buttons are hidden
109
+ - ❌ **No data changes:** Cannot modify or save any data
110
+ - 🏷️ **Badge shows:** "Not Assigned"
111
+
112
+ **Next Button Behavior:**
113
+
114
+ - The Next button still progresses through assigned steps only
115
+ - Clicking unassigned steps is for viewing/transparency only
116
+ - Users can freely navigate back to their assigned workflow
117
+
118
+ This provides complete workflow transparency while maintaining assignment boundaries and data integrity.
119
+
120
+ ### Preview Mode
121
+
122
+ **Purpose:** Interactive preview of workflow templates without data persistence.
123
+
124
+ **Configuration:**
125
+
126
+ ```javascript
127
+ createRunner("runner-container", {
128
+ workflow: workflowData, // Required: Workflow object (not Instance)
129
+ mode: "preview", // Required: Must be explicitly set
130
+ // ... other options
131
+ });
132
+ ```
133
+
134
+ **Features:**
135
+
136
+ - ✅ **Interactive Inputs:** Users can interact with all form elements
137
+ - ✅ **No Data Saving:** Form data is not persisted (no localStorage usage)
138
+ - ✅ **No Validation:** Required field validation is disabled
139
+ - ✅ **Free Navigation:** Users can click any step in the sidebar to navigate freely
140
+ - ✅ **No Callbacks:** Signature and file upload callbacks are disabled
141
+ - ✅ **No Navigation Buttons:** Next/Submit buttons are hidden
142
+ - ✅ **Same Visual Layout:** Identical appearance to default mode
143
+
144
+ **Use Cases:**
145
+
146
+ - Workflow template preview
147
+ - User experience testing
148
+ - Stakeholder demonstrations
149
+ - Template review and approval processes
150
+
151
+ ### Admin Mode
152
+
153
+ **Purpose:** Administrative access for workflow management with unrestricted navigation and step-by-step saving.
154
+
155
+ **Configuration:**
156
+
157
+ ```javascript
158
+ createRunner("runner-container", {
159
+ instance: instanceData, // Required: Instance object
160
+ mode: "admin", // Required: Must be explicitly set
161
+ currentUser: userData, // Required: User with admin access
162
+ // ... other options
163
+ });
164
+ ```
165
+
166
+ **Features:**
167
+
168
+ - ✅ **Unrestricted Navigation:** Access any step regardless of assignment or completion status
169
+ - ✅ **Step-by-Step Saving:** "Save" button (instead of "Next") allows saving progress without advancing
170
+ - ✅ **All Callbacks Active:** Signature capture, file upload, and instance update callbacks fire normally
171
+ - ✅ **Assignment Bypass:** Can view and edit steps not assigned to current user
172
+ - ✅ **Data Persistence:** Form data is saved to localStorage
173
+ - ✅ **Post-Submission Access:** Can still navigate and edit after workflow submission
174
+ - ✅ **Validation Active:** Required field validation still applies
175
+
176
+ **Use Cases:**
177
+
178
+ - Workflow administration and troubleshooting
179
+ - Helping users complete stuck workflows
180
+ - Data correction and updates
181
+ - Workflow testing and QA
182
+ - Support team assistance
183
+
184
+ ### View-Only Mode
185
+
186
+ **Purpose:** Read-only viewing of completed workflow data with pre-filled responses displayed as non-editable content.
187
+
188
+ **Configuration:**
189
+
190
+ ```javascript
191
+ createRunner("runner-container", {
192
+ instance: completedInstanceData, // Required: Instance with responses
193
+ mode: "view-only", // Required: Must be explicitly set
194
+ currentUser: userData, // Optional: For display purposes
195
+ // ... other options
196
+ });
197
+ ```
198
+
199
+ **Features:**
200
+
201
+ - ✅ **Free Navigation:** Navigate to any step freely (like admin mode)
202
+ - ✅ **Pre-filled Display:** All form inputs show existing response data
203
+ - ✅ **All Inputs Disabled:** No editing possible - purely read-only
204
+ - ✅ **File/Signature Links:** File uploads and signatures display as clickable links
205
+ - ✅ **No Action Buttons:** No Next/Save/Submit buttons visible
206
+ - ✅ **No Data Persistence:** No localStorage usage or data saving
207
+ - ✅ **No Callbacks:** Callbacks are disabled (read-only mode)
208
+ - ✅ **Post-Submission View:** Perfect for viewing submitted/completed workflows
209
+
210
+ **Use Cases:**
211
+
212
+ - Viewing completed workflow submissions
213
+ - Audit trails and compliance documentation
214
+ - Historical workflow data review
215
+ - Sharing completed forms with stakeholders
216
+ - Read-only workflow previews for approval
217
+
218
+ ### Print Mode
219
+
220
+ **Purpose:** Print-optimized display of completed workflow data with all steps shown on one continuous page.
221
+
222
+ **Configuration:**
223
+
224
+ ```javascript
225
+ createRunner("runner-container", {
226
+ instance: completedInstanceData, // Required: Instance with responses
227
+ mode: "print", // Required: Must be explicitly set
228
+ currentUser: userData, // Optional: For display purposes
229
+ // ... other options
230
+ });
231
+ ```
232
+
233
+ **Features:**
234
+
235
+ - ✅ **Single Page Layout:** All workflow steps displayed continuously on one page
236
+ - ✅ **No Sidebar:** Clean layout without step navigation for optimal printing
237
+ - ✅ **Pre-filled Display:** All form inputs show existing response data
238
+ - ✅ **All Inputs Disabled:** No editing possible - purely read-only
239
+ - ✅ **Detailed File Information:** File uploads show filename, size, type, and modification date
240
+ - ✅ **Print-Optimized Styling:** Special CSS for clean printing with proper page breaks
241
+ - ✅ **No Action Buttons:** No interactive elements that don't work in print
242
+ - ✅ **No Data Persistence:** No localStorage usage or data saving
243
+ - ✅ **No Callbacks:** Callbacks are disabled (read-only mode)
244
+
245
+ **File Display Enhancement:**
246
+
247
+ - **File Info Objects:** Shows detailed metadata (filename, size, type, date)
248
+ - **URL References:** Extracts filename and type from URLs automatically
249
+ - **Print-Friendly:** No non-functional buttons or links
250
+
251
+ **Use Cases:**
252
+
253
+ - Generating PDF documents of completed workflows
254
+ - Physical document printing for records
255
+ - Compliance documentation requiring paper copies
256
+ - Executive summaries and reports
257
+ - Archival purposes
258
+
259
+ ### Mode Comparison
260
+
261
+ | Feature | Default Mode | Preview Mode | Admin Mode | View-Only Mode | Print Mode |
262
+ | -------------------------- | -------------------------------------------------------- | --------------------- | ---------------------- | -------------------------------- | -------------------------------- |
263
+ | **Data Source** | Instance object | Workflow object | Instance object | Instance object (with responses) | Instance object (with responses) |
264
+ | **Data Persistence** | ✅ localStorage | ❌ None | ✅ localStorage | ❌ None | ❌ None |
265
+ | **Validation** | ✅ Required fields | ❌ Disabled | ✅ Required fields | ❌ N/A (read-only) | ❌ N/A (read-only) |
266
+ | **Step Navigation** | 🔄 Smart (assigned: restricted, unassigned: view-only) | ✅ Free (any step) | ✅ Free (any step) | ✅ Free (any step) | ❌ Single page view |
267
+ | **Input Editing** | 🔄 Conditional (assigned: enabled, unassigned: disabled) | ✅ Enabled | ✅ Enabled | ❌ Disabled (read-only) | ❌ Disabled (read-only) |
268
+ | **Callbacks** | ✅ All callbacks fire (assigned steps only) | ❌ Callbacks disabled | ✅ All callbacks fire | ❌ Callbacks disabled | ❌ Callbacks disabled |
269
+ | **Navigation Buttons** | 🔄 Conditional (visible for assigned steps only) | ❌ Hidden | ✅ Save button visible | ❌ Hidden | ❌ Hidden |
270
+ | **Assignment Checks** | ✅ Enforced | ❌ Bypassed | ❌ Bypassed | ❌ Bypassed | ❌ Bypassed |
271
+ | **Post-Submission Access** | ❌ Blocked | ✅ Always available | ✅ Always available | ✅ Always available | ✅ Always available |
272
+ | **File/Signature Display** | Form inputs | Form inputs | Form inputs | 🔗 Clickable links | 📄 Detailed info display |
273
+ | **Layout** | Sidebar + single step | Sidebar + single step | Sidebar + single step | Sidebar + single step | 📄 All steps on one page |
274
+ | **Primary Use Case** | Production execution | Template preview | Admin management | Completed data viewing | Document printing |
275
+
276
+ ## Supported Elements
277
+
278
+ ### Question Elements (Form Inputs)
279
+
280
+ | Type | Description | Features |
281
+ | ------------- | ---------------------- | ------------------------------------------------------ |
282
+ | `text_input` | Single-line text input | Placeholder text, validation |
283
+ | `textarea` | Multi-line text area | Resizable, placeholder text |
284
+ | `select` | Dropdown selection | Multiple options, placeholder |
285
+ | `number` | Numeric input | Number validation |
286
+ | `radio` | Radio button group | Multiple options, single selection |
287
+ | `checkbox` | Checkbox input | Single checkbox or checkbox group |
288
+ | `date` | Date picker | Date validation |
289
+ | `file_upload` | File upload | File selection, 5MB limit, client callback |
290
+ | `signature` | Digital signature pad | SVG output, responsive canvas, callback on next/submit |
291
+
292
+ ### Content Elements (Display Only)
293
+
294
+ | Type | Description | Features |
295
+ | ---------- | ------------------ | -------------------------- |
296
+ | `text` | Plain text content | Simple text display |
297
+ | `markdown` | Markdown content | Headers, lists, formatting |
298
+ | `html` | HTML content | Custom HTML rendering |
299
+ | `divider` | Visual separator | Optional caption |
300
+ | `image` | Image display | URL, alt text, caption |
301
+ | `video` | Video display | URL, caption |
302
+ | `file` | File display | URL, caption |
303
+
304
+ ### Features
305
+
306
+ - **Validation:** Required field validation for all question types
307
+ - **Responsive Design:** All elements adapt to different screen sizes
308
+ - **Accessibility:** Proper ARIA labels and keyboard navigation
309
+ - **Type Safety:** Full TypeScript support for all element types
310
+ - **Digital Signatures:** Responsive signature pad with SVG output and data URL generation. Signature callbacks are triggered when users click "Next" or "Submit" to capture the final signature data.
311
+ - **Multiple Signatures:** Support for multiple signature elements on the same form
312
+ - **File Uploads:** File selection with 5MB limit. File upload callbacks are triggered immediately when a file is selected.
313
+ - **Progress Tracking:** Real-time progress updates and completion tracking
314
+
315
+ ## Getting Started
316
+
317
+ ### Prerequisites
318
+
319
+ - Node.js (v18+ recommended)
320
+ - npm
321
+
322
+ ### Installation & Setup
323
+
324
+ 1. **Clone:** `git clone <your-repo-url> && cd begin-widgets`
325
+ 2. **Install:** `npm install`
326
+
327
+ ## Development Workflow
328
+
329
+ This project supports two distinct modes for different use cases:
330
+
331
+ ### 🔧 Development Mode
332
+
333
+ For active development with hot reload and fast iteration:
334
+
335
+ ```bash
336
+ npm run dev
337
+ ```
338
+
339
+ - **URL:** http://localhost:5173/
340
+ - **Features:** Hot module replacement, TypeScript compilation, ES modules
341
+ - **Use case:** Active development, debugging, adding features
342
+ - **How it works:** Vite serves source files directly using ES modules
343
+
344
+ ### 🚀 Production Preview Mode
345
+
346
+ For testing the built library as it would be distributed:
347
+
348
+ ```bash
349
+ npm run build
350
+ npm run preview
351
+ ```
352
+
353
+ - **URL:** http://localhost:4173/
354
+ - **Features:** Optimized UMD bundle, production-ready assets
355
+ - **Use case:** Testing final builds, integration testing, demo purposes
356
+ - **How it works:** Creates a UMD bundle and serves the optimized HTML
357
+
358
+ ### Key Differences
359
+
360
+ | Aspect | Development (`npm run dev`) | Production (`npm run preview`) |
361
+ | ------------- | --------------------------- | ------------------------------ |
362
+ | **Loading** | ES modules from `/src/` | UMD bundle from `/dist/` |
363
+ | **Speed** | Fast startup, HMR | Slower startup, no HMR |
364
+ | **Files** | Source TypeScript files | Compiled JavaScript bundle |
365
+ | **Debugging** | Source maps, readable code | Minified bundle |
366
+ | **Use Cases** | Development, debugging | Final testing, demos |
367
+
368
+ ### Demo Features
369
+
370
+ Both modes include a demo with:
371
+
372
+ - **Builder Tab:** Create workflow templates with steps and form elements (questions, content, etc.) using an intuitive interface
373
+ - **Runner Tab:** Execute workflow instances with step-by-step progression
374
+ - **Sample Data:** Pre-loaded workflows and instances for testing
375
+
376
+ ### Build Process Details
377
+
378
+ The build process includes a custom script that:
379
+
380
+ 1. **TypeScript Compilation:** `tsc` compiles source files
381
+ 2. **Bundle Creation:** `vite build` creates the UMD bundle
382
+ 3. **HTML Processing:** `scripts/build-html.js` converts the HTML to use the UMD bundle
383
+
384
+ ## Quick Usage Example
385
+
386
+ ### From npm (Recommended)
387
+
388
+ ```bash
389
+ npm install begin-widgets
390
+ ```
391
+
392
+ ```typescript
393
+ import { createBuilder, createRunner } from "begin-widgets";
394
+
395
+ // Initialize Builder
396
+ createBuilder("workflow-builder", {
397
+ onSave: (workflowData) => {
398
+ console.log("New workflow template created:", workflowData);
399
+ // Save the workflow template to your backend
400
+ saveWorkflowTemplate(workflowData);
401
+ },
402
+ onCancel: () => {
403
+ console.log("Template creation cancelled");
404
+ // Handle cancellation (e.g., redirect to workflows list)
405
+ },
406
+ });
407
+
408
+ // Initialize Runner (Default Mode)
409
+ const instanceData = await fetchInstanceFromBackend("instance-id-123");
410
+
411
+ if (instanceData && instanceData.steps) {
412
+ createRunner("workflow-runner", {
413
+ instance: instanceData,
414
+ mode: "default", // Optional: Default if not specified
415
+ onInstanceUpdated: (detail) => {
416
+ console.log("Progress Update:", detail);
417
+ // Save progress data (for both step updates and final submission)
418
+ saveInstanceProgress(detail.instanceId, detail);
419
+
420
+ // Check if this is the final submission (no current step)
421
+ if (!detail.currentStep) {
422
+ console.log("Workflow Complete!");
423
+ }
424
+ },
425
+ onSignatureCaptured: (detail) => {
426
+ console.log("Signature captured:", detail.questionId);
427
+ console.log("Instance ID:", detail.instanceId);
428
+ console.log("Step ID:", detail.stepId);
429
+ console.log("SVG Data:", detail.svgData);
430
+ console.log("Data URL:", detail.dataURL);
431
+ // Save signature data to your backend
432
+ // Note: This callback is triggered when user clicks "Next" or "Submit"
433
+ saveSignatureData(
434
+ detail.instanceId,
435
+ detail.questionId,
436
+ detail.svgData,
437
+ detail.dataURL
438
+ );
439
+ },
440
+ onFileUploaded: (detail) => {
441
+ console.log("File uploaded:", detail.questionId);
442
+ console.log("Instance ID:", detail.instanceId);
443
+ console.log("Step ID:", detail.stepId);
444
+ console.log("File name:", detail.fileName);
445
+ console.log("File size:", detail.fileSize);
446
+ console.log("File type:", detail.fileType);
447
+ console.log("File object:", detail.file);
448
+ // Handle file upload to your backend/storage
449
+ // Note: This callback is triggered immediately when a file is selected
450
+ handleFileUpload(detail.instanceId, detail.questionId, detail.file);
451
+ },
452
+ });
453
+ }
454
+
455
+ // Initialize Runner (Preview Mode)
456
+ const workflowData = await fetchWorkflowFromBackend("workflow-id-456");
457
+
458
+ if (workflowData && workflowData.steps) {
459
+ createRunner("workflow-preview", {
460
+ workflow: workflowData, // Note: workflow, not instance
461
+ mode: "preview", // Required for preview mode
462
+ onSignatureCaptured: (detail) => {
463
+ console.log("Preview: Signature captured:", detail.questionId);
464
+ console.log("Preview: Instance ID:", detail.instanceId);
465
+ console.log("Preview: Step ID:", detail.stepId);
466
+ // Callbacks are disabled in preview mode, but still available for logging
467
+ },
468
+ onFileUploaded: (detail) => {
469
+ console.log("Preview: File uploaded:", detail.questionId);
470
+ console.log("Preview: Instance ID:", detail.instanceId);
471
+ console.log("Preview: Step ID:", detail.stepId);
472
+ console.log("Preview: File name:", detail.fileName);
473
+ // Callbacks are disabled in preview mode, but still available for logging
474
+ },
475
+ });
476
+ }
477
+ ```
478
+
479
+ ### From CDN (UMD Bundle)
480
+
481
+ 1. **Include Script:**
482
+ ```html
483
+ <script src="https://unpkg.com/begin-widgets/dist/begin-widgets.umd.js"></script>
484
+ ```
485
+ 2. **Add Mount Points:**
486
+ ```html
487
+ <div id="workflow-builder"></div>
488
+ <div id="workflow-runner"></div>
489
+ ```
490
+ 3. **Initialize with JavaScript:**
491
+
492
+ ```javascript
493
+ document.addEventListener('DOMContentLoaded', () => {
494
+ // --- Initialize Builder ---
495
+ if (Begin.createBuilder) {
496
+ Begin.createBuilder('workflow-builder', {
497
+ // Callback when a workflow template is saved
498
+ onSave: (workflowData) => {
499
+ console.log('New workflow template created:', workflowData);
500
+ // Save the workflow template to your backend
501
+ saveWorkflowTemplate(workflowData);
502
+ },
503
+ onCancel: () => {
504
+ console.log('Template creation cancelled');
505
+ // Handle cancellation (e.g., redirect to workflows list)
506
+ }
507
+ });
508
+ }
509
+
510
+ // --- Initialize Runner (Default Mode) ---
511
+ if (Begin.createRunner) {
512
+ // Fetch a specific instance object from your backend.
513
+ // This instance object MUST contain the 'steps' array.
514
+ const instanceData = await fetchInstanceFromBackend('instance-id-123');
515
+
516
+ if (instanceData && instanceData.steps) {
517
+ Begin.createRunner('workflow-runner', {
518
+ instance: instanceData,
519
+ mode: 'default', // Optional: Default if not specified
520
+ onInstanceUpdated: (detail) => {
521
+ console.log('Progress Update:', detail);
522
+ // Save progress data (for both step updates and final submission)
523
+ saveInstanceProgress(detail.instanceId, detail);
524
+
525
+ // Check if this is the final submission (no current step)
526
+ if (!detail.currentStep) {
527
+ console.log('Workflow Complete!');
528
+ }
529
+ },
530
+ onSignatureCaptured: (detail) => {
531
+ console.log('Signature captured:', detail.questionId);
532
+ console.log('Instance ID:', detail.instanceId);
533
+ console.log('Step ID:', detail.stepId);
534
+ console.log('SVG Data:', detail.svgData);
535
+ console.log('Data URL:', detail.dataURL);
536
+ // Save signature data to your backend
537
+ // Note: This callback is triggered when user clicks "Next" or "Submit"
538
+ saveSignatureData(detail.instanceId, detail.questionId, detail.svgData, detail.dataURL);
539
+ },
540
+ onFileUploaded: (detail) => {
541
+ console.log('File uploaded:', detail.questionId);
542
+ console.log('Instance ID:', detail.instanceId);
543
+ console.log('Step ID:', detail.stepId);
544
+ console.log('File name:', detail.fileName);
545
+ console.log('File size:', detail.fileSize);
546
+ console.log('File type:', detail.fileType);
547
+ // Handle file upload to your backend/storage
548
+ // Note: This callback is triggered immediately when a file is selected
549
+ handleFileUpload(detail.instanceId, detail.questionId, detail.file);
550
+ }
551
+ });
552
+ } else {
553
+ console.error("Failed to load instance or instance missing steps.");
554
+ }
555
+ }
556
+
557
+ // --- Initialize Runner (Preview Mode) ---
558
+ if (Begin.createRunner) {
559
+ // Fetch a workflow template from your backend for preview.
560
+ // This workflow object MUST contain the 'steps' array.
561
+ const workflowData = await fetchWorkflowFromBackend('workflow-id-456');
562
+
563
+ if (workflowData && workflowData.steps) {
564
+ Begin.createRunner('workflow-preview', {
565
+ workflow: workflowData, // Note: workflow, not instance
566
+ mode: 'preview', // Required for preview mode
567
+ onSignatureCaptured: (detail) => {
568
+ console.log('Preview: Signature captured:', detail.questionId);
569
+ console.log('Preview: Instance ID:', detail.instanceId);
570
+ console.log('Preview: Step ID:', detail.stepId);
571
+ // Callbacks are disabled in preview mode, but still available for logging
572
+ },
573
+ onFileUploaded: (detail) => {
574
+ console.log('Preview: File uploaded:', detail.questionId);
575
+ console.log('Preview: Instance ID:', detail.instanceId);
576
+ console.log('Preview: Step ID:', detail.stepId);
577
+ console.log('Preview: File name:', detail.fileName);
578
+ // Callbacks are disabled in preview mode, but still available for logging
579
+ }
580
+ });
581
+ } else {
582
+ console.error("Failed to load workflow or workflow missing steps.");
583
+ }
584
+ }
585
+
586
+
587
+ });
588
+ ```
589
+
590
+ ### For ES Module Projects
591
+
592
+ If you're integrating into a modern build system that supports ES modules:
593
+
594
+ ```javascript
595
+ import { createBuilder, createRunner } from "./src/lib.ts";
596
+
597
+ // Use createBuilder and createRunner directly
598
+ createBuilder("builder-container", {
599
+ onSave: (workflowData) => console.log("Template saved:", workflowData),
600
+ onCancel: () => console.log("Template creation cancelled"),
601
+ });
602
+
603
+ // Default mode (production execution)
604
+ createRunner("runner-container", {
605
+ instance: instanceData,
606
+ mode: "default", // Optional: Default if not specified
607
+ onInstanceUpdated: (detail) => {
608
+ console.log("Progress:", detail);
609
+ if (!detail.currentStep) console.log("Complete!");
610
+ },
611
+ onSignatureCaptured: (detail) =>
612
+ console.log(
613
+ "Signature:",
614
+ detail.questionId,
615
+ "Step:",
616
+ detail.stepId,
617
+ "Instance:",
618
+ detail.instanceId
619
+ ),
620
+ onFileUploaded: (detail) =>
621
+ console.log(
622
+ "File:",
623
+ detail.fileName,
624
+ "Step:",
625
+ detail.stepId,
626
+ "Instance:",
627
+ detail.instanceId
628
+ ),
629
+ });
630
+
631
+ // Preview mode (template preview)
632
+ createRunner("preview-container", {
633
+ workflow: workflowData, // Note: workflow, not instance
634
+ mode: "preview", // Required for preview mode
635
+ onSignatureCaptured: (detail) =>
636
+ console.log(
637
+ "Preview Signature:",
638
+ detail.questionId,
639
+ "Step:",
640
+ detail.stepId
641
+ ),
642
+ onFileUploaded: (detail) =>
643
+ console.log("Preview File:", detail.fileName, "Step:", detail.stepId),
644
+ });
645
+
646
+ // Admin mode (administrative access)
647
+ createRunner("admin-container", {
648
+ instance: instanceData, // Instance object with current state
649
+ mode: "admin", // Required for admin mode
650
+ currentUser: adminUserData, // Admin user credentials
651
+ onInstanceUpdated: (detail) => {
652
+ console.log("Admin: Progress updated:", detail);
653
+ // Save admin changes to backend
654
+ saveAdminChanges(detail.instanceId, detail);
655
+ },
656
+ onSignatureCaptured: (detail) =>
657
+ console.log("Admin Signature:", detail.questionId, "Step:", detail.stepId),
658
+ onFileUploaded: (detail) =>
659
+ console.log("Admin File:", detail.fileName, "Step:", detail.stepId),
660
+ });
661
+
662
+ // View-only mode (read-only viewing of completed data)
663
+ createRunner("view-only-container", {
664
+ instance: completedInstanceData, // Instance with filled responses
665
+ mode: "view-only", // Required for view-only mode
666
+ currentUser: viewerUserData, // Optional: For display purposes
667
+ // Note: Callbacks are disabled in view-only mode
668
+ // Files and signatures display as clickable links instead of form inputs
669
+ });
670
+
671
+ // Print mode (print-optimized display of all steps on one page)
672
+ createRunner("print-container", {
673
+ instance: completedInstanceData, // Instance with filled responses
674
+ mode: "print", // Required for print mode
675
+ currentUser: viewerUserData, // Optional: For display purposes
676
+ // Note: Callbacks are disabled in print mode
677
+ // All steps displayed on one continuous page without sidebar
678
+ // Files show detailed info (filename, size, type) instead of links
679
+ });
680
+
681
+ // Loading state (can be used with any mode)
682
+ createRunner("loading-container", {
683
+ instance: instanceData,
684
+ mode: "default",
685
+ isLoading: true, // Shows loading spinner and disables step navigation
686
+ currentUser: userData,
687
+ onInstanceUpdated: (detail) => {
688
+ console.log("Progress:", detail);
689
+ // Update isLoading to false when ready
690
+ // runnerWidget.isLoading = false;
691
+ },
692
+ });
693
+ ```
694
+
695
+ ### Loading State
696
+
697
+ The Runner widget supports a loading state that can be used with any mode to show a loading indicator and disable user interaction while data is being processed or fetched.
698
+
699
+ **Configuration:**
700
+
701
+ ```javascript
702
+ const runnerWidget = createRunner("runner-container", {
703
+ instance: instanceData,
704
+ mode: "default",
705
+ isLoading: true, // Shows loading spinner and disables step navigation
706
+ currentUser: userData,
707
+ onInstanceUpdated: (detail) => {
708
+ console.log("Progress:", detail);
709
+ },
710
+ });
711
+
712
+ // Update loading state dynamically
713
+ runnerWidget.isLoading = false; // Hide loading spinner and re-enable navigation
714
+ ```
715
+
716
+ **Features:**
717
+
718
+ - ✅ **Loading Spinner:** Displays an animated spinner with "Loading..." text
719
+ - ✅ **Disabled Navigation:** All step navigation (sidebar and mobile) is disabled
720
+ - ✅ **Visual Overlay:** Semi-transparent overlay covers the entire widget
721
+ - ✅ **Dynamic Control:** Can be toggled on/off programmatically at any time
722
+ - ✅ **Mode Compatible:** Works with all runner modes (default, preview, admin, view-only, print)
723
+
724
+ **Use Cases:**
725
+
726
+ - Loading workflow data from backend
727
+ - Processing form submissions
728
+ - Saving progress to external systems
729
+ - Waiting for validation responses
730
+ - Any asynchronous operation that requires user to wait
731
+
732
+ ### View-Only Mode: File and Signature Links
733
+
734
+ In view-only mode, file uploads and signatures are displayed as clickable links instead of form inputs. This allows users to view and download the actual files and signatures that were submitted:
735
+
736
+ ### Print Mode: Enhanced File and Signature Display
737
+
738
+ In print mode, file uploads and signatures are displayed with detailed information instead of interactive elements, making them perfect for printed documents:
739
+
740
+ **File Upload Display:**
741
+
742
+ - **File Info Objects:** Shows complete metadata including filename, size (human-readable), file type, and modification date
743
+ - **URL References:** Automatically extracts filename and file type from URLs when only URL is available
744
+ - **Print-Friendly Format:** Clean, structured display without any interactive elements
745
+
746
+ **Signature Display:**
747
+
748
+ - **Embedded Images:** Signatures are displayed as images directly in the document
749
+ - **Fallback Handling:** Graceful handling of missing or corrupted signature data
750
+ - **No Interactive Elements:** Pure display mode suitable for printing
751
+
752
+ **Example Print Mode File Display:**
753
+
754
+ ```
755
+ 📎 File: contract_agreement.pdf
756
+ 📏 Size: 2.3 MB
757
+ 📄 Type: PDF Document
758
+ 📅 Modified: 12/15/2024, 2:30:15 PM
759
+ ```
760
+
761
+ ```javascript
762
+ // Example: Instance with file upload and signature responses
763
+ const completedInstanceData = {
764
+ id: "inst-123",
765
+ workflowId: "wf-onboarding",
766
+ name: "John Doe Onboarding",
767
+ status: "completed",
768
+ steps: [
769
+ {
770
+ id: "step-1",
771
+ title: "Document Upload",
772
+ responses: [
773
+ {
774
+ elementId: "resume-upload",
775
+ value: "https://storage.example.com/files/john-doe-resume.pdf", // File URL
776
+ answeredAt: new Date("2024-01-15T10:30:00Z"),
777
+ },
778
+ {
779
+ elementId: "signature-pad",
780
+ value: "https://storage.example.com/signatures/john-doe-sig.svg", // Signature URL directly in value
781
+ answeredAt: new Date("2024-01-15T10:35:00Z"),
782
+ },
783
+ ],
784
+ elements: [
785
+ {
786
+ id: "resume-upload",
787
+ type: "file_upload",
788
+ label: "Upload Resume",
789
+ required: true,
790
+ },
791
+ {
792
+ id: "signature-pad",
793
+ type: "signature",
794
+ label: "Digital Signature",
795
+ required: true,
796
+ },
797
+ ],
798
+ },
799
+ ],
800
+ completedSteps: ["step-1"],
801
+ };
802
+
803
+ // When rendered in view-only mode:
804
+ // - File upload shows: "📎 filename.pdf" (clickable link that opens file in new tab)
805
+ // - Signature shows: embedded signature image (same as print mode)
806
+ ```
807
+
808
+ ## HTML Export Utility
809
+
810
+ Begin Widgets includes a powerful HTML export utility that generates print-ready HTML from workflow instances. This is perfect for server-side PDF generation, email reports, and documentation.
811
+
812
+ ### Overview
813
+
814
+ The `generateInstanceHTML()` function takes a workflow `Instance` object and produces complete HTML that matches the appearance of the runner widget's print mode exactly. By default, it renders only the workflow steps and elements (just like print mode). Optionally, you can add metadata headers with instance information.
815
+
816
+ ### Basic Usage
817
+
818
+ ```typescript
819
+ import { generateInstanceHTML } from "begin-widgets";
820
+
821
+ const result = generateInstanceHTML(myInstance);
822
+ console.log(result.html); // Complete HTML string ready for PDF generation
823
+ ```
824
+
825
+ ### With Options
826
+
827
+ ```typescript
828
+ const result = generateInstanceHTML(myInstance, {
829
+ title: "Employee Onboarding Report",
830
+ showTimestamps: true, // Add metadata header (not in print mode)
831
+ customCSS: `
832
+ .print-layout {
833
+ font-family: 'Times New Roman', serif;
834
+ }
835
+ `,
836
+ });
837
+ ```
838
+
839
+ ### PDF Generation Example
840
+
841
+ ```typescript
842
+ const puppeteer = require("puppeteer");
843
+
844
+ async function generatePDF(instance) {
845
+ const result = generateInstanceHTML(instance, {
846
+ title: "Workflow Report",
847
+ showTimestamps: true,
848
+ });
849
+
850
+ const browser = await puppeteer.launch();
851
+ const page = await browser.newPage();
852
+
853
+ await page.setContent(result.html, { waitUntil: "networkidle0" });
854
+ await page.pdf({
855
+ path: "./report.pdf",
856
+ format: "A4",
857
+ printBackground: true,
858
+ margin: { top: "20mm", right: "20mm", bottom: "20mm", left: "20mm" },
859
+ });
860
+
861
+ await browser.close();
862
+ }
863
+ ```
864
+
865
+ ### Server-Side Usage
866
+
867
+ ```javascript
868
+ const express = require("express");
869
+ const { generateInstanceHTML } = require("begin-widgets");
870
+
871
+ app.get("/report/:instanceId", async (req, res) => {
872
+ const instance = await getInstanceFromDatabase(req.params.instanceId);
873
+
874
+ const result = generateInstanceHTML(instance, {
875
+ title: `Report: ${instance.name}`,
876
+ showTimestamps: true,
877
+ });
878
+
879
+ res.setHeader("Content-Type", "text/html");
880
+ res.send(result.html);
881
+ });
882
+ ```
883
+
884
+ ### Features
885
+
886
+ - ✅ **Exact Print Mode Replica** - Matches runner widget print mode exactly
887
+ - ✅ **All Question Types** - Text, select, radio, checkbox, file uploads, signatures
888
+ - ✅ **File Metadata** - Shows filename, size, type, modification dates
889
+ - ✅ **Signature Images** - Embedded signatures from provided URLs
890
+ - ✅ **PDF-Ready** - Print media queries, page breaks, embedded CSS
891
+ - ✅ **Server-Side Compatible** - No browser dependencies, works in Node.js
892
+ - ✅ **Zero Dependencies** - Pure HTML/CSS output
893
+
894
+ ### API Reference
895
+
896
+ ```typescript
897
+ interface HTMLExportOptions {
898
+ title?: string; // Custom document title (default: instance.name)
899
+ includeStyles?: boolean; // Include embedded CSS (default: true)
900
+ customCSS?: string; // Additional CSS to inject
901
+ showTimestamps?: boolean; // Show instance metadata header (default: false)
902
+ }
903
+
904
+ interface HTMLExportResult {
905
+ html: string; // Complete HTML document
906
+ title: string; // Document title used
907
+ generatedAt: Date; // Generation timestamp
908
+ }
909
+ ```
910
+
911
+ ## TypeScript Support
912
+
913
+ Begin Widgets includes comprehensive TypeScript definitions for full type safety and developer experience.
914
+
915
+ ### Installing Types
916
+
917
+ When you install `begin-widgets` from npm, the TypeScript declaration files are automatically included:
918
+
919
+ ```bash
920
+ npm install begin-widgets
921
+ ```
922
+
923
+ ### Importing Types
924
+
925
+ #### Option 1: Import Types with Functions (Recommended)
926
+
927
+ ```typescript
928
+ import {
929
+ createBuilder,
930
+ createRunner,
931
+ type Workflow,
932
+ type Instance,
933
+ type Step,
934
+ type StepElement,
935
+ type QuestionElement,
936
+ type ContentElement,
937
+ } from "begin-widgets";
938
+
939
+ // Use the types for type safety
940
+ const myWorkflow: Workflow = {
941
+ id: "my-workflow",
942
+ name: "My Workflow",
943
+ steps: [],
944
+ };
945
+
946
+ const myInstance: Instance = {
947
+ id: "my-instance",
948
+ workflowId: "my-workflow",
949
+ name: "My Instance",
950
+ status: "active",
951
+ createdAt: new Date(),
952
+ updatedAt: new Date(),
953
+ steps: [],
954
+ completedSteps: [],
955
+ };
956
+ ```
957
+
958
+ #### Option 2: Import Types Only
959
+
960
+ ```typescript
961
+ import type {
962
+ Workflow,
963
+ Instance,
964
+ Step,
965
+ StepElement,
966
+ QuestionElement,
967
+ ContentElement,
968
+ QuestionResponse,
969
+ StepAssignment,
970
+ BuilderConfig,
971
+ RunnerConfig,
972
+ } from "begin-widgets";
973
+ ```
974
+
975
+ #### Option 3: Dedicated Types Entry Point
976
+
977
+ ```typescript
978
+ import type {
979
+ Workflow,
980
+ Instance,
981
+ StepElement,
982
+ QuestionElement,
983
+ ContentElement,
984
+ BuilderConfig,
985
+ RunnerConfig,
986
+ } from "begin-widgets/types";
987
+ ```
988
+
989
+ ### Available Types
990
+
991
+ | Type | Description |
992
+ | ------------------ | ---------------------------------------- |
993
+ | `Workflow` | Complete workflow template definition |
994
+ | `Instance` | Workflow instance with data and progress |
995
+ | `Step` | Individual workflow step |
996
+ | `StepElement` | Union of all possible step elements |
997
+ | `QuestionElement` | Form question element |
998
+ | `ContentElement` | Content/display element |
999
+ | `QuestionResponse` | User's answer to a question |
1000
+ | `StepAssignment` | Who a step is assigned to |
1001
+ | `StepStatus` | Current status of a step |
1002
+ | `BuilderConfig` | Configuration for the builder widget |
1003
+ | `RunnerConfig` | Configuration for the runner widget |
1004
+ | `Visibility` | Element visibility rules |
1005
+ | `VisibilityRule` | Individual visibility condition |
1006
+
1007
+ > **Note:** The `Question` type is deprecated and only included for legacy support. Use `QuestionElement` for all new development.
1008
+
1009
+ ### JavaScript Projects with JSDoc
1010
+
1011
+ For JavaScript projects, you can still get type hints using JSDoc:
1012
+
1013
+ ```javascript
1014
+ /**
1015
+ * @typedef {import('begin-widgets').Workflow} Workflow
1016
+ * @typedef {import('begin-widgets').Instance} Instance
1017
+ */
1018
+
1019
+ /**
1020
+ * @param {Workflow} workflow
1021
+ * @param {Instance} instance
1022
+ */
1023
+ function processWorkflow(workflow, instance) {
1024
+ // Full intellisense and type checking here
1025
+ console.log(workflow.name);
1026
+ console.log(instance.status);
1027
+ }
1028
+ ```
1029
+
1030
+ ### UMD Bundle with Types
1031
+
1032
+ When using the UMD bundle directly in the browser, you can still import types separately for TypeScript projects:
1033
+
1034
+ ```html
1035
+ <!-- Runtime: UMD bundle -->
1036
+ <script src="https://unpkg.com/begin-widgets/dist/begin-widgets.umd.js"></script>
1037
+
1038
+ <script>
1039
+ // Runtime usage
1040
+ const { createBuilder, createRunner } = Begin;
1041
+ </script>
1042
+ ```
1043
+
1044
+ ```typescript
1045
+ // Types: Import separately in TypeScript files
1046
+ import type { Workflow, Instance } from "begin-widgets";
1047
+ ```
1048
+
1049
+ ### Type Safety Benefits
1050
+
1051
+ - **Intellisense**: Full autocomplete in VS Code, WebStorm, and other IDEs
1052
+ - **Compile-time Checking**: Catch errors before runtime
1053
+ - **Documentation**: Types serve as inline documentation
1054
+ - **Refactoring**: Safe refactoring with type checking
1055
+ - **Zero Runtime Cost**: Types are compile-time only, no bundle size impact
1056
+
1057
+ ## Project Structure
1058
+
1059
+ ```
1060
+ begin-widgets/
1061
+ ├── src/
1062
+ │ ├── models.ts # TypeScript interfaces
1063
+ │ ├── lib.ts # Main library API
1064
+ │ ├── builder-widget.ts # Workflow template builder component
1065
+ │ ├── runner-widget.ts # Workflow runner component
1066
+ │ ├── styles/ # Organized CSS styles for components
1067
+ │ │ ├── base-styles.ts
1068
+ │ │ ├── form-styles.ts
1069
+ │ │ ├── section-styles.ts
1070
+ │ │ ├── step-styles.ts
1071
+ │ │ ├── modal-styles.ts
1072
+ │ │ └── index.ts
1073
+ │ └── main.ts # Entry point for development
1074
+ ├── scripts/
1075
+ │ └── build-html.js # Build script for production HTML
1076
+ ├── dist/ # Generated files (after build)
1077
+ │ ├── begin-widgets.umd.js
1078
+ │ └── index.html
1079
+ ├── index.html # Development HTML (ES modules)
1080
+ ├── vite.config.js # Vite configuration
1081
+ └── package.json
1082
+ ```
1083
+
1084
+ ## Development Commands
1085
+
1086
+ ```bash
1087
+ # Start development server with hot reload
1088
+ npm run dev
1089
+
1090
+ # Build the production bundle
1091
+ npm run build
1092
+
1093
+ # Preview the production build
1094
+ npm run preview
1095
+
1096
+ # Run tests (placeholder)
1097
+ npm test
1098
+ ```
1099
+
1100
+ ## Troubleshooting
1101
+
1102
+ ### "Begin library not found" Error
1103
+
1104
+ - **In Development:** Make sure you're using `npm run dev`, not `npm run preview`
1105
+ - **In Production:** Make sure you ran `npm run build` before `npm run preview`
1106
+
1107
+ ### Module Loading Issues
1108
+
1109
+ - **Development mode** uses ES modules and requires a modern browser
1110
+ - **Production mode** uses UMD bundle and works in older browsers
1111
+
1112
+ ### Build Errors
1113
+
1114
+ - Ensure TypeScript compiles without errors: `npx tsc --noEmit`
1115
+ - Check that all imports are correctly typed and available
1116
+
1117
+ ---
1118
+
1119
+ Let Begin Widgets streamline your application's workflows!