formshell 1.0.0
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/LICENSE +21 -0
- package/README.md +665 -0
- package/dist/global.d.ts +26 -0
- package/dist/index.d.ts +615 -0
- package/dist/index.js +1070 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lorenzo Caputo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,665 @@
|
|
|
1
|
+
# FormShell
|
|
2
|
+
|
|
3
|
+
An elegant framework for creating interactive multi-step forms directly in the browser console.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Multi-Step Forms**: One-question-at-a-time flow
|
|
13
|
+
- **Built-in Validation**: Validation for every field type
|
|
14
|
+
- **Conditional Logic**: Show/hide steps based on previous answers
|
|
15
|
+
- **Progress Tracking**: Progress bar, step counter, and estimated time
|
|
16
|
+
- **Non-blocking Help**: Call `formShell.help()` at any time without losing your place
|
|
17
|
+
- **Zero Dependencies**: No external libraries required
|
|
18
|
+
- **Endpoint Ready**: POST JSON to custom endpoints with response handling
|
|
19
|
+
- **TypeScript**: Full type definitions included
|
|
20
|
+
- **Vite**: Modern dev server and build tool
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
### 1. Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm install formshell
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or clone and install locally:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone <repository-url>
|
|
36
|
+
cd formshell
|
|
37
|
+
pnpm install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. Development
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm dev
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then open your browser and navigate to `http://localhost:5173`.
|
|
47
|
+
|
|
48
|
+
### 3. Build
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm build
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Step-by-Step Guide
|
|
57
|
+
|
|
58
|
+
This section walks through the entire flow, from configuration to API response.
|
|
59
|
+
|
|
60
|
+
### Step 1 -- Create a FormConfig
|
|
61
|
+
|
|
62
|
+
A `FormConfig` object defines everything about your form. Here is the full interface with every available option:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { FormShell } from 'formshell';
|
|
66
|
+
import type { FormConfig, FormData } from 'formshell';
|
|
67
|
+
|
|
68
|
+
const config: FormConfig = {
|
|
69
|
+
// (required) The form title, displayed on the welcome and help screens
|
|
70
|
+
title: 'Feedback Form',
|
|
71
|
+
|
|
72
|
+
// (optional) A subtitle shown below the title
|
|
73
|
+
subtitle: 'We value your opinion',
|
|
74
|
+
|
|
75
|
+
// (optional) POST endpoint -- when set, formShell.submit() sends data here
|
|
76
|
+
endpoint: '/api/feedback',
|
|
77
|
+
|
|
78
|
+
// (required) Array of field configurations (see "Supported Field Types" below)
|
|
79
|
+
steps: [
|
|
80
|
+
{
|
|
81
|
+
id: 'name',
|
|
82
|
+
type: 'text',
|
|
83
|
+
label: 'What is your name?',
|
|
84
|
+
description: 'Enter your full name',
|
|
85
|
+
required: true,
|
|
86
|
+
minLength: 2,
|
|
87
|
+
maxLength: 100
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'email',
|
|
91
|
+
type: 'email',
|
|
92
|
+
label: 'Your email address?',
|
|
93
|
+
required: true
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'rating',
|
|
97
|
+
type: 'rating',
|
|
98
|
+
label: 'How satisfied are you?',
|
|
99
|
+
required: true,
|
|
100
|
+
min: 1,
|
|
101
|
+
max: 5
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 'subscribe',
|
|
105
|
+
type: 'yesno',
|
|
106
|
+
label: 'Subscribe to our newsletter?',
|
|
107
|
+
required: false,
|
|
108
|
+
defaultValue: false
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
|
|
112
|
+
// (optional) Called after successful submission
|
|
113
|
+
// When an endpoint is set, `data` contains the server's JSON response.
|
|
114
|
+
// When no endpoint is set, `data` contains the collected form answers.
|
|
115
|
+
onComplete: (data: FormData) => {
|
|
116
|
+
console.log('Received:', data);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Step 2 -- Instantiate FormShell
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const form = new FormShell(config);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
> **TypeScript autocomplete:** FormShell includes global type definitions for `window.formShell`.
|
|
128
|
+
>
|
|
129
|
+
> To enable them in your TypeScript project, reference the global declarations at the top of your main file:
|
|
130
|
+
>
|
|
131
|
+
> ```typescript
|
|
132
|
+
> /// <reference types="formshell/global" />
|
|
133
|
+
>
|
|
134
|
+
> // Now window.formShell has full type support!
|
|
135
|
+
> const form = new FormShell(config);
|
|
136
|
+
> ```
|
|
137
|
+
>
|
|
138
|
+
> If you want to use a **custom name** for your brand instead of `formShell`:
|
|
139
|
+
>
|
|
140
|
+
> ```typescript
|
|
141
|
+
> // global.d.ts in your project root
|
|
142
|
+
> import type { FormShell } from 'formshell';
|
|
143
|
+
>
|
|
144
|
+
> declare global {
|
|
145
|
+
> interface Window {
|
|
146
|
+
> myBrandName: FormShell; // Use your custom name
|
|
147
|
+
> }
|
|
148
|
+
> }
|
|
149
|
+
>
|
|
150
|
+
> export {};
|
|
151
|
+
> ```
|
|
152
|
+
>
|
|
153
|
+
> Then assign it manually:
|
|
154
|
+
> ```typescript
|
|
155
|
+
> const form = new FormShell(config);
|
|
156
|
+
> window.myBrandName = form;
|
|
157
|
+
> ```
|
|
158
|
+
|
|
159
|
+
### Step 3 -- Include in HTML
|
|
160
|
+
|
|
161
|
+
```html
|
|
162
|
+
<script type="module" src="./my-form.ts"></script>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
That is all. The form renders entirely inside the browser console -- no visible UI is needed.
|
|
166
|
+
|
|
167
|
+
### Step 4 -- Open the Console
|
|
168
|
+
|
|
169
|
+
- **Chrome/Edge**: `F12` or `Ctrl+Shift+J` (`Cmd+Option+J` on Mac)
|
|
170
|
+
- **Firefox**: `F12` or `Ctrl+Shift+K` (`Cmd+Option+K` on Mac)
|
|
171
|
+
- **Safari**: Enable Developer menu, then `Cmd+Option+C`
|
|
172
|
+
|
|
173
|
+
When the page loads you will see:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
Feedback Form
|
|
177
|
+
We value your opinion
|
|
178
|
+
|
|
179
|
+
Type formShell.start() to begin or formShell.help() for available commands
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Step 5 -- Interact with the Form
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
// Show all available commands (non-blocking, does not interrupt the form)
|
|
186
|
+
formShell.help()
|
|
187
|
+
|
|
188
|
+
// Start the form
|
|
189
|
+
formShell.start()
|
|
190
|
+
|
|
191
|
+
// Answer questions
|
|
192
|
+
formShell.answer("John Doe")
|
|
193
|
+
formShell.answer("john@example.com")
|
|
194
|
+
formShell.answer(4) // rating
|
|
195
|
+
formShell.y() // yes/no shortcut
|
|
196
|
+
|
|
197
|
+
// Navigate
|
|
198
|
+
formShell.back() // go to previous question
|
|
199
|
+
formShell.skip() // skip optional question
|
|
200
|
+
|
|
201
|
+
// After the last answer the summary screen appears
|
|
202
|
+
formShell.submit() // send data to the endpoint (or log it)
|
|
203
|
+
|
|
204
|
+
// At any point
|
|
205
|
+
formShell.help() // show commands -- does NOT lose your progress
|
|
206
|
+
formShell.continue() // resume where you left off after help
|
|
207
|
+
formShell.reset() // start over from scratch
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Step 6 -- What Happens on Submit
|
|
211
|
+
|
|
212
|
+
When `formShell.submit()` is called:
|
|
213
|
+
|
|
214
|
+
1. **With an endpoint** -- a `POST` request is sent:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
POST /api/feedback
|
|
218
|
+
Content-Type: application/json
|
|
219
|
+
|
|
220
|
+
{
|
|
221
|
+
"name": "John Doe",
|
|
222
|
+
"email": "john@example.com",
|
|
223
|
+
"rating": 4,
|
|
224
|
+
"subscribe": true
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The server's JSON response is passed to `onComplete(response)` and printed in the console:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
Response: { success: true, feedbackId: "fb-1707562800000", ... }
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
2. **Without an endpoint** -- the collected data is passed directly to `onComplete(data)` and printed:
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
Data: { name: "John Doe", email: "john@example.com", rating: 4, subscribe: true }
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Supported Field Types
|
|
243
|
+
|
|
244
|
+
### Text Field
|
|
245
|
+
|
|
246
|
+
Free text with length and pattern validation.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
{
|
|
250
|
+
id: 'name',
|
|
251
|
+
type: 'text',
|
|
252
|
+
label: 'What is your name?',
|
|
253
|
+
description: 'Optional help text',
|
|
254
|
+
required: true,
|
|
255
|
+
minLength: 2,
|
|
256
|
+
maxLength: 100,
|
|
257
|
+
pattern: /^[A-Za-z\s]+$/ // optional regex
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Number Field
|
|
262
|
+
|
|
263
|
+
Numbers with range and integer validation.
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
{
|
|
267
|
+
id: 'age',
|
|
268
|
+
type: 'number',
|
|
269
|
+
label: 'How old are you?',
|
|
270
|
+
required: true,
|
|
271
|
+
min: 18,
|
|
272
|
+
max: 120,
|
|
273
|
+
integer: true
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Email Field
|
|
278
|
+
|
|
279
|
+
Email with automatic pattern validation.
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
{
|
|
283
|
+
id: 'email',
|
|
284
|
+
type: 'email',
|
|
285
|
+
label: 'What is your email?',
|
|
286
|
+
required: true
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### URL Field
|
|
291
|
+
|
|
292
|
+
URL with http/https format validation.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
{
|
|
296
|
+
id: 'website',
|
|
297
|
+
type: 'url',
|
|
298
|
+
label: 'Your website address?',
|
|
299
|
+
required: false
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Date Field
|
|
304
|
+
|
|
305
|
+
Date in DD/MM/YYYY format with validation.
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
{
|
|
309
|
+
id: 'birthdate',
|
|
310
|
+
type: 'date',
|
|
311
|
+
label: 'Date of birth?',
|
|
312
|
+
required: true
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Choice Field
|
|
317
|
+
|
|
318
|
+
Single choice from a list of options.
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
{
|
|
322
|
+
id: 'service',
|
|
323
|
+
type: 'choice',
|
|
324
|
+
label: 'Which service are you interested in?',
|
|
325
|
+
required: true,
|
|
326
|
+
options: [
|
|
327
|
+
'Web Development',
|
|
328
|
+
'Mobile App',
|
|
329
|
+
'UI/UX Design',
|
|
330
|
+
'Consulting'
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
// Answer: formShell.answer(2) selects "Mobile App"
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Options can also use `{ value, label }` objects:
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
options: [
|
|
340
|
+
{ value: 'web', label: 'Web Development' },
|
|
341
|
+
{ value: 'mobile', label: 'Mobile App' }
|
|
342
|
+
]
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Multiple Choice Field
|
|
346
|
+
|
|
347
|
+
Multiple selections from a list.
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
{
|
|
351
|
+
id: 'interests',
|
|
352
|
+
type: 'multiple-choice',
|
|
353
|
+
label: 'Which technologies do you use?',
|
|
354
|
+
required: true,
|
|
355
|
+
options: ['JavaScript', 'Python', 'Java', 'Go', 'Rust'],
|
|
356
|
+
minChoices: 1,
|
|
357
|
+
maxChoices: 3
|
|
358
|
+
}
|
|
359
|
+
// Answer: formShell.answer("1,3,5") selects JavaScript, Java, Rust
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Rating Field
|
|
363
|
+
|
|
364
|
+
Numeric scale with star visualization.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
{
|
|
368
|
+
id: 'satisfaction',
|
|
369
|
+
type: 'rating',
|
|
370
|
+
label: 'How satisfied are you?',
|
|
371
|
+
required: true,
|
|
372
|
+
min: 1,
|
|
373
|
+
max: 5
|
|
374
|
+
}
|
|
375
|
+
// Answer: formShell.answer(4)
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Yes/No Field
|
|
379
|
+
|
|
380
|
+
Binary Yes/No question.
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
{
|
|
384
|
+
id: 'newsletter',
|
|
385
|
+
type: 'yesno',
|
|
386
|
+
label: 'Subscribe to newsletter?',
|
|
387
|
+
required: true,
|
|
388
|
+
defaultValue: false
|
|
389
|
+
}
|
|
390
|
+
// Answer: formShell.y() or formShell.n()
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Conditional Logic
|
|
396
|
+
|
|
397
|
+
Steps can be shown or hidden based on previous answers using the `condition` callback:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
{
|
|
401
|
+
id: 'react_rating',
|
|
402
|
+
type: 'rating',
|
|
403
|
+
label: 'Rate your React experience',
|
|
404
|
+
required: true,
|
|
405
|
+
min: 1,
|
|
406
|
+
max: 5,
|
|
407
|
+
condition: (data) => {
|
|
408
|
+
return data.position === 'Frontend Developer'
|
|
409
|
+
|| data.position === 'Full-stack Developer';
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
When a step's `condition` returns `false`, it is skipped during navigation, excluded from the progress bar, and hidden in the summary.
|
|
415
|
+
|
|
416
|
+
See `examples/job-application.ts` for a complete conditional-logic example.
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Commands Reference
|
|
421
|
+
|
|
422
|
+
| Command | Description |
|
|
423
|
+
|---------|-------------|
|
|
424
|
+
| `formShell.start()` | Start the form from the welcome screen |
|
|
425
|
+
| `formShell.help()` | Show all commands (can be called at any time) |
|
|
426
|
+
| `formShell.continue()` | Resume the form after viewing help |
|
|
427
|
+
| `formShell.answer(value)` | Answer the current question and proceed |
|
|
428
|
+
| `formShell.y()` / `formShell.n()` | Shortcut for yes/no questions |
|
|
429
|
+
| `formShell.skip()` | Skip the current question (if optional) |
|
|
430
|
+
| `formShell.back()` | Go to the previous question |
|
|
431
|
+
| `formShell.submit()` | Submit data to the endpoint (after completing all steps) |
|
|
432
|
+
| `formShell.reset()` | Start over from scratch |
|
|
433
|
+
| `formShell.destroy()` | Cleanup and destroy the instance |
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Customization
|
|
438
|
+
|
|
439
|
+
### Modify the Theme
|
|
440
|
+
|
|
441
|
+
Customize colors and styles by editing `src/formshell/theme.ts`:
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
export const Theme = {
|
|
445
|
+
colors: {
|
|
446
|
+
primary: '#6366f1',
|
|
447
|
+
secondary: '#8b5cf6',
|
|
448
|
+
success: '#10b981',
|
|
449
|
+
error: '#ef4444',
|
|
450
|
+
// ...
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## Project Structure
|
|
458
|
+
|
|
459
|
+
```
|
|
460
|
+
formshell/
|
|
461
|
+
├── src/
|
|
462
|
+
│ └── formshell/
|
|
463
|
+
│ ├── types.ts # TypeScript type definitions
|
|
464
|
+
│ ├── theme.ts # Design system (colors, icons, styles)
|
|
465
|
+
│ ├── tui-renderer.ts # Console rendering engine
|
|
466
|
+
│ ├── field-types.ts # Field types and validators
|
|
467
|
+
│ ├── form-framework.ts # Core framework (FormShell class)
|
|
468
|
+
│ └── index.ts # Main entry point and exports
|
|
469
|
+
├── examples/
|
|
470
|
+
│ ├── contact-form.ts # Contact form example
|
|
471
|
+
│ ├── survey-form.ts # Satisfaction survey example
|
|
472
|
+
│ └── job-application.ts # Job application with conditional logic
|
|
473
|
+
├── dist/ # Build output
|
|
474
|
+
│ ├── index.js # ESM bundle
|
|
475
|
+
│ └── index.d.ts # Type definitions
|
|
476
|
+
├── vite.config.ts # Vite config (includes mock API endpoints)
|
|
477
|
+
├── tsconfig.json # TypeScript configuration
|
|
478
|
+
├── package.json # Package configuration
|
|
479
|
+
├── index.html # Demo page
|
|
480
|
+
└── README.md # This documentation
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## API Reference
|
|
486
|
+
|
|
487
|
+
### FormShell
|
|
488
|
+
|
|
489
|
+
#### Constructor
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
new FormShell(config: FormConfig)
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**FormConfig:**
|
|
496
|
+
|
|
497
|
+
| Property | Type | Required | Description |
|
|
498
|
+
|----------|------|----------|-------------|
|
|
499
|
+
| `title` | `string` | yes | Form title shown on welcome/help screens |
|
|
500
|
+
| `subtitle` | `string` | no | Subtitle shown below the title |
|
|
501
|
+
| `endpoint` | `string` | no | POST endpoint for `formShell.submit()` |
|
|
502
|
+
| `steps` | `FieldConfig[]` | yes | Array of field configurations |
|
|
503
|
+
| `onComplete` | `(data: FormData) => void \| Promise<void>` | no | Callback after successful submission |
|
|
504
|
+
|
|
505
|
+
#### Public Methods
|
|
506
|
+
|
|
507
|
+
| Method | Return | Description |
|
|
508
|
+
|--------|--------|-------------|
|
|
509
|
+
| `start()` | `void` | Start the form |
|
|
510
|
+
| `help()` | `void` | Show help (non-blocking) |
|
|
511
|
+
| `continue()` | `void` | Resume after help |
|
|
512
|
+
| `answer(value)` | `void` | Answer current question |
|
|
513
|
+
| `y()` / `n()` | `void` | Yes/No shortcuts |
|
|
514
|
+
| `skip()` | `void` | Skip optional question |
|
|
515
|
+
| `back()` | `void` | Go to previous question |
|
|
516
|
+
| `submit()` | `Promise<void>` | Submit data |
|
|
517
|
+
| `reset()` | `void` | Start over |
|
|
518
|
+
| `destroy()` | `void` | Cleanup instance |
|
|
519
|
+
| `getProgress()` | `ProgressInfo` | Get current progress |
|
|
520
|
+
| `getEstimatedTime()` | `string \| null` | Estimated remaining time |
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Data Submission
|
|
525
|
+
|
|
526
|
+
### POST to Endpoint
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
const form = new FormShell({
|
|
530
|
+
title: 'My Form',
|
|
531
|
+
endpoint: 'https://api.yoursite.com/submit',
|
|
532
|
+
steps: [/* ... */],
|
|
533
|
+
onComplete: (serverResponse) => {
|
|
534
|
+
// serverResponse is the parsed JSON from the endpoint
|
|
535
|
+
console.log('Server says:', serverResponse);
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
When `formShell.submit()` is called, FormShell sends:
|
|
541
|
+
|
|
542
|
+
```
|
|
543
|
+
POST https://api.yoursite.com/submit
|
|
544
|
+
Content-Type: application/json
|
|
545
|
+
Body: { "field_id_1": "value1", "field_id_2": "value2", ... }
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Without Endpoint
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
const form = new FormShell({
|
|
552
|
+
title: 'My Form',
|
|
553
|
+
steps: [/* ... */],
|
|
554
|
+
onComplete: (collectedData) => {
|
|
555
|
+
// collectedData is a plain object with all answers
|
|
556
|
+
console.log('Collected:', collectedData);
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### JSON Data Format
|
|
562
|
+
|
|
563
|
+
```json
|
|
564
|
+
{
|
|
565
|
+
"name": "John Doe",
|
|
566
|
+
"email": "john@example.com",
|
|
567
|
+
"service": "Web Development",
|
|
568
|
+
"rating": 5,
|
|
569
|
+
"newsletter": true,
|
|
570
|
+
"technologies": ["JavaScript", "Python"]
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## Complete Examples
|
|
577
|
+
|
|
578
|
+
### Contact Form
|
|
579
|
+
|
|
580
|
+
See `examples/contact-form.ts` -- a complete contact form with:
|
|
581
|
+
- Name (text, required), Email (email, required), Phone (text, optional)
|
|
582
|
+
- Service selection (choice), Budget (choice), Urgency (choice)
|
|
583
|
+
- Satisfaction rating (rating), Message (text, optional)
|
|
584
|
+
- Newsletter (yes/no), Privacy consent (yes/no)
|
|
585
|
+
|
|
586
|
+
### Satisfaction Survey
|
|
587
|
+
|
|
588
|
+
See `examples/survey-form.ts` -- a questionnaire with:
|
|
589
|
+
- Single and multiple choice questions
|
|
590
|
+
- Multiple rating scales
|
|
591
|
+
- Text feedback fields
|
|
592
|
+
- Automatic average rating calculation
|
|
593
|
+
|
|
594
|
+
### Job Application (Conditional Logic)
|
|
595
|
+
|
|
596
|
+
See `examples/job-application.ts` -- a technical interview form with:
|
|
597
|
+
- Position selection drives which questions appear
|
|
598
|
+
- Frontend-specific questions (TypeScript, React, CSS frameworks)
|
|
599
|
+
- Backend-specific questions (Node.js, databases, API design)
|
|
600
|
+
- DevOps-specific questions (cloud, containers, CI/CD)
|
|
601
|
+
- Full-stack candidates see both frontend and backend sections
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Validation
|
|
606
|
+
|
|
607
|
+
Each field type has built-in validation:
|
|
608
|
+
|
|
609
|
+
- **Required**: Mandatory field
|
|
610
|
+
- **Min/Max Length**: For text fields
|
|
611
|
+
- **Min/Max Value**: For number and rating fields
|
|
612
|
+
- **Pattern**: Regex for email, URL, date
|
|
613
|
+
- **Options**: Valid choices for choice/multiple-choice
|
|
614
|
+
|
|
615
|
+
Error messages are clear and contextual:
|
|
616
|
+
|
|
617
|
+
```javascript
|
|
618
|
+
formShell.answer("ab") // minLength: 3 -> "Minimum 3 characters required"
|
|
619
|
+
formShell.answer("bad-email") // -> "Invalid email address"
|
|
620
|
+
formShell.answer(10) // 5 options -> "Choose a number between 1 and 5"
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
## Browser Compatibility
|
|
626
|
+
|
|
627
|
+
| Browser | Minimum Version | Notes |
|
|
628
|
+
|---------|----------------|-------|
|
|
629
|
+
| Chrome | 88+ | Full support |
|
|
630
|
+
| Firefox | 85+ | Full support |
|
|
631
|
+
| Safari | 14+ | Full support |
|
|
632
|
+
| Edge | 88+ | Full support |
|
|
633
|
+
|
|
634
|
+
**Requirements:**
|
|
635
|
+
- ES6 Modules support
|
|
636
|
+
- `console.log` CSS styling support
|
|
637
|
+
- Active JavaScript console
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## Troubleshooting
|
|
642
|
+
|
|
643
|
+
### Form does not appear
|
|
644
|
+
- Make sure you have opened the Browser Console
|
|
645
|
+
- Check for JavaScript errors in the console
|
|
646
|
+
- Verify files are served via HTTP(S), not `file://`
|
|
647
|
+
|
|
648
|
+
### Colors do not show
|
|
649
|
+
- Some browsers may not support console styling
|
|
650
|
+
- Check browser console settings
|
|
651
|
+
|
|
652
|
+
### Endpoint does not receive data
|
|
653
|
+
- Check CORS configuration on the server
|
|
654
|
+
- Verify the endpoint accepts `POST` with `Content-Type: application/json`
|
|
655
|
+
- Inspect the Network tab for request details
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
## License
|
|
660
|
+
|
|
661
|
+
MIT License -- Feel free to use this framework in your projects!
|
|
662
|
+
|
|
663
|
+
## Contributing
|
|
664
|
+
|
|
665
|
+
Contributions, issues, and feature requests are welcome!
|
package/dist/global.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global TypeScript declarations for FormShell
|
|
3
|
+
*
|
|
4
|
+
* This file provides type definitions for the global `formShell` object
|
|
5
|
+
* attached to the window for console interaction.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Access formShell in the console with full type support
|
|
9
|
+
* formShell.start()
|
|
10
|
+
* formShell.answer("response")
|
|
11
|
+
* formShell.submit()
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { FormShell } from './index';
|
|
15
|
+
|
|
16
|
+
declare global {
|
|
17
|
+
interface Window {
|
|
18
|
+
/**
|
|
19
|
+
* Global FormShell instance for console interaction
|
|
20
|
+
* Automatically assigned by the library for development and testing
|
|
21
|
+
*/
|
|
22
|
+
formShell: FormShell;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {};
|