@jdlien/validator 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/demo.html ADDED
@@ -0,0 +1,779 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Validator Demo</title>
6
+ <link rel="stylesheet" href="demo.css" />
7
+ </head>
8
+
9
+ <body class="p-6 bg-gray-400 dark:bg-gray-800 dark:text-white">
10
+ <main class="max-w-3xl mx-auto bg-gray-200 dark:bg-gray-900 rounded-xl p-8 shadow-xl">
11
+ <h1 class="text-4xl font-semibold text-center text-gray-200">Validator Demo</h1>
12
+ <div class="text-center">
13
+ <p class="my-8">
14
+ Validator has been applied to this form to help sanitize and validate user input.<br />
15
+ This form won't submit if any fields are invalid and helpful errors will be shown or
16
+ hidden as the user changes fields.
17
+ </p>
18
+
19
+ <div>Install this Validator through npm:</div>
20
+
21
+ <div>
22
+ <code>npm install @jdlien/validator</code>
23
+ </div>
24
+
25
+ <p class="my-8">
26
+ Source code and documentation at
27
+ <a
28
+ href="https://github.com/jdlien/validator/"
29
+ class="text-blue-700 dark:text-blue-400 hover:underline"
30
+ >github.com/jdlien/validator</a
31
+ >.
32
+ </p>
33
+ </div>
34
+ <form id="demo-form" class="space-y-3 max-w-2xl mx-auto mb-12">
35
+ <p class="text-gray-500 dark:text-gray-400">
36
+ Fields can be required, have a minimum or maximum length, or a pattern.<br />
37
+ Numeric inputs won't even allow invalid values to be typed in.
38
+ </p>
39
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
40
+ <label
41
+ for="input-required"
42
+ id="input-required-label"
43
+ class="block font-medium sm:mt-px sm:pt-1"
44
+ >Required</label
45
+ >
46
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
47
+ <div class="flex relative sm:max-w-sm">
48
+ <input
49
+ class="block w-full px-1.5 transition"
50
+ type="text"
51
+ required="true"
52
+ minlength="8"
53
+ id="input-required"
54
+ name="input-required"
55
+ data-error-default=""
56
+ aria-labelledby="input-required-label"
57
+ />
58
+ </div>
59
+
60
+ <div style="min-height: 20px">
61
+ <div
62
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
63
+ id="input-required-error"
64
+ ></div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
70
+ <label
71
+ for="input-pattern"
72
+ id="input-pattern-label"
73
+ class="block font-medium sm:mt-px sm:pt-1"
74
+ >Regex Pattern</label
75
+ >
76
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
77
+ <div class="flex relative sm:max-w-sm">
78
+ <input
79
+ class="block w-full px-1.5 transition"
80
+ type="text"
81
+ pattern="^[a-zA-Z]\d+$"
82
+ data-error-default="^[a-zA-Z]\d+$ (A letter followed by one or more numbers)"
83
+ id="input-pattern"
84
+ data-pattern="^[a-zA-Z]\d+$"
85
+ name="input-pattern"
86
+ aria-labelledby="input-pattern-label"
87
+ />
88
+ </div>
89
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
90
+ A letter followed by numbers <strong>(^[a-zA-Z]\d+$)</strong>
91
+ </p>
92
+ <div style="min-height: 20px">
93
+ <div
94
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
95
+ id="input-pattern-error"
96
+ ></div>
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
102
+ <label for="input-min" id="input-min-label" class="block font-medium sm:mt-px sm:pt-1"
103
+ >Minimum 8 chars</label
104
+ >
105
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
106
+ <div class="flex relative sm:max-w-sm">
107
+ <input
108
+ class="block w-full px-1.5 transition"
109
+ type="text"
110
+ minlength="8"
111
+ id="input-min"
112
+ name="input-min"
113
+ data-error-default=""
114
+ aria-labelledby="input-min-label"
115
+ />
116
+ </div>
117
+
118
+ <div style="min-height: 20px">
119
+ <div
120
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
121
+ id="input-min-error"
122
+ ></div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+
127
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
128
+ <label for="input-max" id="input-max-label" class="block font-medium sm:mt-px sm:pt-1"
129
+ >Maximum</label
130
+ >
131
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
132
+ <div class="flex relative sm:max-w-sm">
133
+ <input
134
+ class="block w-full px-1.5 transition"
135
+ type="text"
136
+ data-max-length="3"
137
+ id="input-max"
138
+ name="input-max"
139
+ data-error-default=""
140
+ aria-labelledby="input-max-label"
141
+ />
142
+ </div>
143
+
144
+ <div style="min-height: 20px">
145
+ <div
146
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
147
+ id="input-max-error"
148
+ ></div>
149
+ </div>
150
+ </div>
151
+ </div>
152
+
153
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
154
+ <label
155
+ for="input-integer"
156
+ id="input-integer-label"
157
+ class="block font-medium sm:mt-px sm:pt-1"
158
+ >Positive Integers</label
159
+ >
160
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
161
+ <div class="flex relative sm:max-w-sm">
162
+ <input
163
+ class="block w-full px-1.5 transition"
164
+ type="text"
165
+ id="input-integer"
166
+ data-type="integer"
167
+ name="input-integer"
168
+ data-error-default=""
169
+ aria-labelledby="input-integer-label"
170
+ />
171
+ </div>
172
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
173
+ Up/down arrow keys increment &amp; decrement
174
+ </p>
175
+ <div style="min-height: 20px">
176
+ <div
177
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
178
+ id="input-integer-error"
179
+ ></div>
180
+ </div>
181
+ </div>
182
+ </div>
183
+
184
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
185
+ <label
186
+ for="input-number"
187
+ id="input-number-label"
188
+ class="block font-medium sm:mt-px sm:pt-1"
189
+ >Any Number</label
190
+ >
191
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
192
+ <div class="flex relative sm:max-w-sm">
193
+ <input
194
+ class="block w-full px-1.5 transition"
195
+ type="text"
196
+ id="input-number"
197
+ data-type="number"
198
+ name="input-number"
199
+ data-error-default=""
200
+ aria-labelledby="input-number-label"
201
+ />
202
+ </div>
203
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
204
+ Negative numbers and decimals are allowed
205
+ </p>
206
+
207
+ <div style="min-height: 20px">
208
+ <div
209
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
210
+ id="input-number-error"
211
+ ></div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+
216
+ <p class="text-gray-500 dark:text-gray-400">
217
+ Dates can be entered by users in almost any format, and will be converted
218
+ to the format specified in the data-date-format attribute.<br>
219
+ Dates can also be constrained to past or future dates.<br>
220
+ These features are compatible with datepickers like
221
+ <a href="https://flatpickr.js.org/"
222
+ class="text-blue-700 dark:text-blue-400 hover:underline"
223
+ >Flatpickr</a>.
224
+ </p>
225
+ </p>
226
+
227
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
228
+ <label for="input-date" id="input-date-label" class="block font-medium sm:mt-px sm:pt-1"
229
+ >Date</label
230
+ >
231
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
232
+ <div class="flex relative sm:max-w-sm">
233
+ <input
234
+ class="block w-full px-1.5 transition flatpickr-input"
235
+ type="text"
236
+ value="2021-Jan-01"
237
+ id="input-date"
238
+ data-date-format="YYYY-MMM-DD"
239
+ data-type="date"
240
+ placeholder="YYYY-Mmm-D"
241
+ name="input-date"
242
+ data-error-default=""
243
+ aria-labelledby="input-date-label"
244
+ />
245
+ </div>
246
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
247
+ Any date will be converted to the <em>YYYY-MMM-DD</em> format
248
+ </p>
249
+ <div style="min-height: 20px">
250
+ <div
251
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
252
+ id="input-date-error"
253
+ ></div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+
258
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
259
+ <label
260
+ for="input-past-date"
261
+ id="input-past-date-label"
262
+ class="block font-medium sm:mt-px sm:pt-1"
263
+ >Past date</label
264
+ >
265
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
266
+ <div class="flex relative sm:max-w-sm">
267
+ <input
268
+ class="block w-full px-1.5 transition flatpickr-input"
269
+ type="text"
270
+ data-date-range="past"
271
+ value="2021-01-01"
272
+ id="input-past-date"
273
+ data-date-format="YYYY-MM-DD"
274
+ data-type="date"
275
+ placeholder="YYYY-Mmm-D"
276
+ name="input-past-date"
277
+ data-error-default=""
278
+ aria-labelledby="input-past-date-label"
279
+ />
280
+ </div>
281
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
282
+ YYYY-MM-DD format is enforced
283
+ </p>
284
+
285
+ <div style="min-height: 20px">
286
+ <div
287
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
288
+ id="input-past-date-error"
289
+ ></div>
290
+ </div>
291
+ </div>
292
+ </div>
293
+
294
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
295
+ <label
296
+ for="input-future-date"
297
+ id="input-future-date-label"
298
+ class="block font-medium sm:mt-px sm:pt-1"
299
+ >Enter Future date</label
300
+ >
301
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
302
+ <div class="flex relative sm:max-w-sm">
303
+ <input
304
+ class="block w-full px-1.5 transition flatpickr-input"
305
+ type="text"
306
+ data-date-range="future"
307
+ id="input-future-date"
308
+ data-date-format="YYYY-MM-DD"
309
+ data-type="date"
310
+ placeholder="YYYY-Mmm-D"
311
+ name="input-future-date"
312
+ data-error-default=""
313
+ aria-labelledby="input-future-date-label"
314
+ />
315
+ </div>
316
+
317
+ <div style="min-height: 20px">
318
+ <div
319
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
320
+ id="input-future-date-error"
321
+ ></div>
322
+ </div>
323
+ </div>
324
+ </div>
325
+
326
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
327
+ <label for="input-url" id="input-url-label" class="block font-medium sm:mt-px sm:pt-1"
328
+ >Web Address</label
329
+ >
330
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
331
+ <div class="flex relative sm:max-w-sm">
332
+ <input
333
+ class="block w-full px-1.5 transition"
334
+ type="url"
335
+ required="true"
336
+ id="input-url"
337
+ inputmode="url"
338
+ placeholder="https://____.___"
339
+ name="input-url"
340
+ data-error-default="You have to put text here."
341
+ aria-describedby="input-url-error"
342
+ aria-labelledby="input-url-label"
343
+ />
344
+ </div>
345
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
346
+ This is a text input with a provided error
347
+ </p>
348
+ <div style="min-height: 20px">
349
+ <div
350
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
351
+ id="input-url-error"
352
+ ></div>
353
+ </div>
354
+ </div>
355
+ </div>
356
+
357
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
358
+ <label for="input-tel" id="input-tel-label" class="block font-medium sm:mt-px sm:pt-1"
359
+ >Tel</label
360
+ >
361
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
362
+ <div class="flex relative sm:max-w-sm">
363
+ <input
364
+ class="block w-full px-1.5 transition"
365
+ type="tel"
366
+ required="true"
367
+ id="input-tel"
368
+ inputmode="tel"
369
+ data-type="tel"
370
+ placeholder="___-___-____"
371
+ name="input-tel"
372
+ data-error-default=""
373
+ aria-labelledby="input-tel-label"
374
+ />
375
+ </div>
376
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
377
+ A North-American phone number will be formatted on change
378
+ </p>
379
+
380
+ <div style="min-height: 20px">
381
+ <div
382
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
383
+ id="input-tel-error"
384
+ ></div>
385
+ </div>
386
+ </div>
387
+ </div>
388
+
389
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
390
+ <label
391
+ for="input-JmMZ56f26"
392
+ id="input-JmMZ56f26-label"
393
+ class="block font-medium sm:mt-px sm:pt-1"
394
+ >Email</label
395
+ >
396
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
397
+ <div class="flex relative sm:max-w-sm">
398
+ <input
399
+ class="block w-full px-1.5 transition"
400
+ type="email"
401
+ required="true"
402
+ id="input-JmMZ56f26"
403
+ inputmode="email"
404
+ data-type="email"
405
+ placeholder="____@____.___"
406
+ name="input-JmMZ56f26"
407
+ data-error-default=""
408
+ aria-labelledby="input-JmMZ56f26-label"
409
+ />
410
+ </div>
411
+
412
+ <div style="min-height: 20px">
413
+ <div
414
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
415
+ id="input-JmMZ56f26-error"
416
+ ></div>
417
+ </div>
418
+ </div>
419
+ </div>
420
+
421
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
422
+ <label
423
+ for="input-y371jQeI5"
424
+ id="input-y371jQeI5-label"
425
+ class="block font-medium sm:mt-px sm:pt-1"
426
+ >US Zip Code</label
427
+ >
428
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
429
+ <div class="flex relative sm:max-w-sm">
430
+ <input
431
+ class="block w-full px-1.5 transition"
432
+ type="text"
433
+ id="input-y371jQeI5"
434
+ data-type="zip"
435
+ name="input-y371jQeI5"
436
+ data-error-default=""
437
+ aria-labelledby="input-y371jQeI5-label"
438
+ />
439
+ </div>
440
+
441
+ <div style="min-height: 20px">
442
+ <div
443
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
444
+ id="input-y371jQeI5-error"
445
+ ></div>
446
+ </div>
447
+ </div>
448
+ </div>
449
+
450
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
451
+ <label
452
+ for="input-1RE0Iv460"
453
+ id="input-1RE0Iv460-label"
454
+ class="block font-medium sm:mt-px sm:pt-1"
455
+ >Canadian Postal Code</label
456
+ >
457
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
458
+ <div class="flex relative sm:max-w-sm">
459
+ <input
460
+ class="block w-full px-1.5 transition"
461
+ type="text"
462
+ id="input-1RE0Iv460"
463
+ data-type="postal"
464
+ name="input-1RE0Iv460"
465
+ data-error-default=""
466
+ aria-labelledby="input-1RE0Iv460-label"
467
+ />
468
+ </div>
469
+
470
+ <div style="min-height: 20px">
471
+ <div
472
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
473
+ id="input-1RE0Iv460-error"
474
+ ></div>
475
+ </div>
476
+ </div>
477
+ </div>
478
+
479
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
480
+ <label
481
+ for="input-Iju9bFf25"
482
+ id="input-Iju9bFf25-label"
483
+ class="block font-medium sm:mt-px sm:pt-1"
484
+ >Time of Day</label
485
+ >
486
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
487
+ <div class="flex relative sm:max-w-sm">
488
+ <input
489
+ class="block w-full px-1.5 transition flatpickr-input"
490
+ type="text"
491
+ data-time-format="h:mm A"
492
+ id="input-Iju9bFf25"
493
+ data-type="time"
494
+ placeholder="H:MM AM"
495
+ name="input-Iju9bFf25"
496
+ data-error-default=""
497
+ aria-labelledby="input-Iju9bFf25-label"
498
+ />
499
+ </div>
500
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
501
+ Anything resembling a time will be converted into the specified format
502
+ </p>
503
+ <div style="min-height: 20px">
504
+ <div
505
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
506
+ id="input-Iju9bFf25-error"
507
+ ></div>
508
+ </div>
509
+ </div>
510
+ </div>
511
+
512
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
513
+ <label for="input-color" id="input-color-label" class="block font-medium sm:mt-px sm:pt-1"
514
+ >Color value with picker</label
515
+ >
516
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
517
+ <div class="flex relative sm:max-w-sm">
518
+ <input
519
+ class="block w-full px-1.5 transition rounded-r-none"
520
+ type="text"
521
+ id="input-color"
522
+ data-type="color"
523
+ name="input-color"
524
+ data-error-default=""
525
+ aria-labelledby="input-color-label"
526
+ />
527
+ <label
528
+ id="input-color-color-label"
529
+ for="input-color-color"
530
+ class="border border-l-0 border-gray-350 dark:border-gray-500 cursor-pointer w-20 rounded-r"
531
+ style="background-color: #888888"
532
+ >
533
+ <input
534
+ type="color"
535
+ id="input-color-color"
536
+ class="invisible w-full h-full"
537
+ value="#888888"
538
+ />
539
+ </label>
540
+ </div>
541
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
542
+ The label will show a swatch of any valid color
543
+ </p>
544
+ <div style="min-height: 20px">
545
+ <div
546
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
547
+ id="input-1Au5G5fdg-error"
548
+ ></div>
549
+ </div>
550
+ </div>
551
+ </div>
552
+
553
+ <!-- Accept an array of basic options for a select -->
554
+ <p class="text-gray-500 dark:text-gray-400">Selects can be required as well.</p>
555
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
556
+ <label
557
+ for="input-2A59h7jYl"
558
+ id="input-2A59h7jYl-label"
559
+ class="block font-medium sm:mt-px sm:pt-1"
560
+ >Select an option</label
561
+ >
562
+ <div class="mt-1 sm:mt-0 sm:col-span-2">
563
+ <select
564
+ class="block w-full sm:max-w-sm"
565
+ required="true"
566
+ id="input-2A59h7jYl"
567
+ name="input-2A59h7jYl"
568
+ data-error-default=""
569
+ aria-labelledby="input-2A59h7jYl-label"
570
+ >
571
+ <option value=""></option>
572
+ <option value="red">Red</option>
573
+ <option value="green">Green</option>
574
+ <option value="blue">Blue</option>
575
+ </select>
576
+
577
+ <div style="min-height: 20px">
578
+ <div
579
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
580
+ id="input-2A59h7jYl-error"
581
+ ></div>
582
+ </div>
583
+ </div>
584
+ </div>
585
+
586
+ <p class="text-gray-500 dark:text-gray-400">
587
+ You can require groups of radio buttons or checkboxes so one must be selected.
588
+ </p>
589
+
590
+ <!-- Accept an array of basic options for a radio button group -->
591
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
592
+ <label
593
+ for="checkboxGroup"
594
+ id="checkboxGroup-label"
595
+ class="block font-medium sm:mt-px sm:pt-1"
596
+ >Checkbox group</label
597
+ >
598
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
599
+ <div class="flex relative sm:max-w-sm">
600
+ <div class="mb-3 sm:col-span-2 space-y-3">
601
+ <div class="pt-2">
602
+ <div class="flex items-start h-5">
603
+ <label class="checked-border" for="checkboxGroup-1-red">
604
+ <input
605
+ id="checkboxGroup-1-red"
606
+ required=""
607
+ name="checkboxGroup"
608
+ type="checkbox"
609
+ value="red"
610
+ data-error-default="You have to check at least one box."
611
+ class="block transition"
612
+ />
613
+ <span class="checked-label">Red</span>
614
+ </label>
615
+ </div>
616
+ </div>
617
+ <div class="pt-2">
618
+ <div class="flex items-start h-5">
619
+ <label class="checked-border" for="checkboxGroup-2-green">
620
+ <input
621
+ id="checkboxGroup-2-green"
622
+ required=""
623
+ name="checkboxGroup"
624
+ type="checkbox"
625
+ value="green"
626
+ data-error-default="You have to check at least one box."
627
+ class="block transition"
628
+ />
629
+ <span class="checked-label">Green</span>
630
+ </label>
631
+ </div>
632
+ </div>
633
+ <div class="pt-2">
634
+ <div class="flex items-start h-5">
635
+ <label class="checked-border" for="checkboxGroup-3-blue">
636
+ <input
637
+ id="checkboxGroup-3-blue"
638
+ required=""
639
+ name="checkboxGroup"
640
+ type="checkbox"
641
+ value="blue"
642
+ data-error-default="You have to check at least one box."
643
+ class="block transition"
644
+ />
645
+ <span class="checked-label">Blue</span>
646
+ </label>
647
+ </div>
648
+ </div>
649
+ </div>
650
+ </div>
651
+
652
+ <div style="min-height: 20px">
653
+ <div
654
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
655
+ id="checkboxGroup-error"
656
+ ></div>
657
+ </div>
658
+ </div>
659
+ </div>
660
+
661
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
662
+ <label
663
+ for="input-radio"
664
+ id="input-radio-label"
665
+ class="block font-medium sm:mt-px sm:pt-1"
666
+ >Radio button group</label
667
+ >
668
+ <div class="my-0.5 sm:mt-0 sm:col-span-2">
669
+ <div class="flex relative sm:max-w-sm">
670
+ <div class="mb-3 sm:col-span-2 space-y-3">
671
+ <div class="pt-2">
672
+ <div class="flex items-start h-5">
673
+ <label class="checked-border rounded-full" for="input-radio-1-red">
674
+ <input
675
+ id="input-radio-1-red"
676
+ required=""
677
+ name="input-radio"
678
+ type="radio"
679
+ value="red"
680
+ class="block transition"
681
+ />
682
+ <span class="checked-label">red</span>
683
+ </label>
684
+ </div>
685
+ </div>
686
+ <div class="pt-2">
687
+ <div class="flex items-start h-5">
688
+ <label class="checked-border rounded-full" for="input-radio-2-green">
689
+ <input
690
+ id="input-radio-2-green"
691
+ required=""
692
+ name="input-radio"
693
+ type="radio"
694
+ value="green"
695
+ class="block transition"
696
+ />
697
+ <span class="checked-label">green</span>
698
+ </label>
699
+ </div>
700
+ </div>
701
+ <div class="pt-2">
702
+ <div class="flex items-start h-5">
703
+ <label class="checked-border rounded-full" for="input-radio-3-blue">
704
+ <input
705
+ id="input-radio-3-blue"
706
+ required=""
707
+ name="input-radio"
708
+ type="radio"
709
+ value="blue"
710
+ class="block transition"
711
+ />
712
+ <span class="checked-label">blue</span>
713
+ </label>
714
+ </div>
715
+ </div>
716
+ </div>
717
+ </div>
718
+
719
+ <div style="min-height: 20px">
720
+ <div
721
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
722
+ id="input-radio-error"
723
+ ></div>
724
+ </div>
725
+ </div>
726
+ </div>
727
+
728
+ <p class="text-gray-500 dark:text-gray-400">
729
+ Textarea elements can have min and max lengths as well as be required.
730
+ </p>
731
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4">
732
+ <label
733
+ for="input-textarea"
734
+ id="input-textarea-label"
735
+ class="block font-medium sm:mt-px sm:pt-1"
736
+ >Multiple Text Lines</label
737
+ >
738
+ <div class="mt-1 sm:mt-0 sm:col-span-2">
739
+ <textarea
740
+ required="true"
741
+ data-min-length="2"
742
+ data-max-length="50"
743
+ id="input-textarea"
744
+ class="w-full"
745
+ name="input-textarea"
746
+ data-error-default=""
747
+ aria-labelledby="input-textarea-label"
748
+ placeholder="Between 2 and 50 characters"
749
+ ></textarea>
750
+
751
+ <div style="min-height: 20px">
752
+ <div
753
+ class="error hidden text-sm text-red-600 transition dark:text-red-500"
754
+ id="input-textarea-error"
755
+ ></div>
756
+ </div>
757
+ </div>
758
+ </div>
759
+
760
+ <div class="text-center">
761
+ <input
762
+ class="bg-blue-600 rounded hover:bg-blue-500 py-1 active:bg-blue-700 text-white text-lg w-60"
763
+ type="submit"
764
+ />
765
+ </div>
766
+ </form>
767
+
768
+ <p class="text-center">
769
+ If the form is invalid when submitted, 'form-error-main' will be displayed above.
770
+ </p>
771
+
772
+ <script src="./dist/validator.js"></script>
773
+ <script>
774
+ const form = document.getElementById('demo-form')
775
+ const validator = new Validator(form)
776
+ </script>
777
+ </main>
778
+ </body>
779
+ </html>