@samuel-charpentier/sform 0.0.1

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.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +405 -0
  3. package/dist/Sform/Sfield.svelte +164 -0
  4. package/dist/Sform/Sfield.svelte.d.ts +4 -0
  5. package/dist/Sform/Sform.svelte +101 -0
  6. package/dist/Sform/Sform.svelte.d.ts +51 -0
  7. package/dist/Sform/context.svelte.d.ts +3 -0
  8. package/dist/Sform/context.svelte.js +65 -0
  9. package/dist/Sform/index.d.ts +5 -0
  10. package/dist/Sform/index.js +7 -0
  11. package/dist/Sform/inputs/ButtonInput.svelte +75 -0
  12. package/dist/Sform/inputs/ButtonInput.svelte.d.ts +32 -0
  13. package/dist/Sform/inputs/CheckboxGroupInput.svelte +81 -0
  14. package/dist/Sform/inputs/CheckboxGroupInput.svelte.d.ts +4 -0
  15. package/dist/Sform/inputs/CheckboxInput.svelte +47 -0
  16. package/dist/Sform/inputs/CheckboxInput.svelte.d.ts +4 -0
  17. package/dist/Sform/inputs/MaskedInput.svelte +220 -0
  18. package/dist/Sform/inputs/MaskedInput.svelte.d.ts +4 -0
  19. package/dist/Sform/inputs/NumberInput.svelte +116 -0
  20. package/dist/Sform/inputs/NumberInput.svelte.d.ts +4 -0
  21. package/dist/Sform/inputs/PasswordInput.svelte +142 -0
  22. package/dist/Sform/inputs/PasswordInput.svelte.d.ts +4 -0
  23. package/dist/Sform/inputs/RadioInput.svelte +81 -0
  24. package/dist/Sform/inputs/RadioInput.svelte.d.ts +4 -0
  25. package/dist/Sform/inputs/RangeInput.svelte +67 -0
  26. package/dist/Sform/inputs/RangeInput.svelte.d.ts +4 -0
  27. package/dist/Sform/inputs/SelectInput.svelte +36 -0
  28. package/dist/Sform/inputs/SelectInput.svelte.d.ts +4 -0
  29. package/dist/Sform/inputs/TextInput.svelte +61 -0
  30. package/dist/Sform/inputs/TextInput.svelte.d.ts +4 -0
  31. package/dist/Sform/inputs/TextareaInput.svelte +56 -0
  32. package/dist/Sform/inputs/TextareaInput.svelte.d.ts +4 -0
  33. package/dist/Sform/inputs/ToggleInput.svelte +101 -0
  34. package/dist/Sform/inputs/ToggleInput.svelte.d.ts +4 -0
  35. package/dist/Sform/inputs/ToggleOptionsInput.svelte +118 -0
  36. package/dist/Sform/inputs/ToggleOptionsInput.svelte.d.ts +4 -0
  37. package/dist/Sform/sform.css +628 -0
  38. package/dist/Sform/types.d.ts +610 -0
  39. package/dist/Sform/types.js +5 -0
  40. package/dist/Sform/utils/mask.d.ts +68 -0
  41. package/dist/Sform/utils/mask.js +155 -0
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.js +1 -0
  44. package/package.json +78 -0
@@ -0,0 +1,628 @@
1
+ /**
2
+ * Sform Library Styles
3
+ * Default styling for Sform components
4
+ */
5
+
6
+ /* ===========================================
7
+ CSS Custom Properties (Design Tokens)
8
+ =========================================== */
9
+ :root {
10
+ /* Colors */
11
+ --sform-primary: #4f46e5;
12
+ --sform-primary-hover: #4338ca;
13
+ --sform-primary-light: #e0e7ff;
14
+ --sform-success: #10b981;
15
+ --sform-success-bg: #d1fae5;
16
+ --sform-error: #ef4444;
17
+ --sform-error-bg: #fee2e2;
18
+ --sform-warning: #f59e0b;
19
+ --sform-warning-bg: #fef3c7;
20
+
21
+ /* Neutrals */
22
+ --sform-bg: #ffffff;
23
+ --sform-bg-muted: #f9fafb;
24
+ --sform-border: #d1d5db;
25
+ --sform-border-focus: var(--sform-primary);
26
+ --sform-text: #1f2937;
27
+ --sform-text-muted: #6b7280;
28
+ --sform-text-placeholder: #9ca3af;
29
+
30
+ /* Spacing */
31
+ --sform-gap: 1rem;
32
+ --sform-gap-sm: 0.5rem;
33
+ --sform-padding: 0.625rem 0.875rem;
34
+ --sform-padding-sm: 0.5rem 0.75rem;
35
+
36
+ /* Typography */
37
+ --sform-font-size: 0.9375rem;
38
+ --sform-font-size-sm: 0.8125rem;
39
+ --sform-line-height: 1.5;
40
+
41
+ /* Borders */
42
+ --sform-radius: 0.375rem;
43
+ --sform-radius-lg: 0.5rem;
44
+ --sform-border-width: 1px;
45
+
46
+ /* Transitions */
47
+ --sform-transition: 150ms ease;
48
+
49
+ /* Shadows */
50
+ --sform-shadow-focus: 0 0 0 3px rgba(79, 70, 229, 0.15);
51
+ --sform-shadow-error: 0 0 0 3px rgba(239, 68, 68, 0.15);
52
+ }
53
+
54
+ /* ===========================================
55
+ Form Layout
56
+ =========================================== */
57
+ .sform-form {
58
+ display: flex;
59
+ flex-direction: column;
60
+ gap: var(--sform-gap);
61
+ }
62
+
63
+ /* ===========================================
64
+ Field Wrapper
65
+ =========================================== */
66
+ .sform-field {
67
+ display: flex;
68
+ flex-direction: column;
69
+ gap: var(--sform-gap-sm);
70
+ }
71
+
72
+ .sform-field-inline {
73
+ flex-direction: row;
74
+ align-items: center;
75
+ }
76
+
77
+ /* ===========================================
78
+ Labels
79
+ =========================================== */
80
+ .sform-label {
81
+ font-size: var(--sform-font-size-sm);
82
+ font-weight: 500;
83
+ color: var(--sform-text);
84
+ line-height: var(--sform-line-height);
85
+ }
86
+
87
+ .sform-label-required::after {
88
+ content: ' *';
89
+ color: var(--sform-error);
90
+ }
91
+
92
+ /* ===========================================
93
+ Base Input Styles
94
+ =========================================== */
95
+ .sform-input {
96
+ padding: var(--sform-padding);
97
+ font-size: var(--sform-font-size);
98
+ line-height: var(--sform-line-height);
99
+ color: var(--sform-text);
100
+ background: var(--sform-bg);
101
+ border: var(--sform-border-width) solid var(--sform-border);
102
+ border-radius: var(--sform-radius);
103
+ transition:
104
+ border-color var(--sform-transition),
105
+ box-shadow var(--sform-transition);
106
+ }
107
+
108
+ .sform-input::placeholder {
109
+ color: var(--sform-text-placeholder);
110
+ }
111
+
112
+ .sform-input:focus {
113
+ outline: none;
114
+ border-color: var(--sform-border-focus);
115
+ box-shadow: var(--sform-shadow-focus);
116
+ }
117
+
118
+ .sform-input:disabled {
119
+ background: var(--sform-bg-muted);
120
+ color: var(--sform-text-muted);
121
+ cursor: not-allowed;
122
+ }
123
+
124
+ .sform-input:read-only {
125
+ background: var(--sform-bg-muted);
126
+ }
127
+
128
+ /* Error state */
129
+ .sform-input.sform-field-error,
130
+ .sform-input[aria-invalid='true'] {
131
+ border-color: var(--sform-error);
132
+ }
133
+
134
+ .sform-input.sform-field-error:focus,
135
+ .sform-input[aria-invalid='true']:focus {
136
+ box-shadow: var(--sform-shadow-error);
137
+ }
138
+
139
+ /* ===========================================
140
+ Input Wrapper (Prefix/Suffix)
141
+ =========================================== */
142
+ .sform-input-wrapper {
143
+ display: flex;
144
+ align-items: center;
145
+ gap: 0;
146
+ border: var(--sform-border-width) solid var(--sform-border);
147
+ border-radius: var(--sform-radius);
148
+ background-color: var(--sform-bg);
149
+ transition:
150
+ border-color var(--sform-transition),
151
+ box-shadow var(--sform-transition);
152
+ }
153
+
154
+ .sform-input-wrapper:focus-within {
155
+ border-color: var(--sform-border-focus);
156
+ box-shadow: var(--sform-shadow-focus);
157
+ outline: none;
158
+ }
159
+
160
+ .sform-input-wrapper:has(.sform-input[aria-invalid='true']) {
161
+ border-color: var(--sform-error);
162
+ }
163
+
164
+ .sform-input-wrapper:has(.sform-input[aria-invalid='true']):focus-within {
165
+ box-shadow: var(--sform-shadow-error);
166
+ }
167
+
168
+ .sform-input-wrapper .sform-input {
169
+ flex: 1;
170
+ min-width: 0;
171
+ border: none;
172
+ background: transparent;
173
+ box-shadow: none;
174
+ }
175
+
176
+ .sform-input-wrapper .sform-input:focus {
177
+ outline: none;
178
+ box-shadow: none;
179
+ }
180
+
181
+ .sform-prefix-icon,
182
+ .sform-suffix-icon,
183
+ .sform-prefix,
184
+ .sform-suffix {
185
+ display: flex;
186
+ align-items: center;
187
+ justify-content: center;
188
+ color: var(--sform-text-muted);
189
+ cursor: pointer;
190
+ user-select: none;
191
+ }
192
+
193
+ .sform-prefix-icon,
194
+ .sform-suffix-icon {
195
+ padding: 0 0.5rem;
196
+ }
197
+
198
+ .sform-prefix,
199
+ .sform-suffix {
200
+ padding: 0 0.75rem;
201
+ font-size: var(--sform-font-size-sm);
202
+ white-space: nowrap;
203
+ }
204
+
205
+ .sform-prefix-icon,
206
+ .sform-prefix {
207
+ border-right: var(--sform-border-width) solid var(--sform-border);
208
+ }
209
+
210
+ .sform-suffix-icon,
211
+ .sform-suffix {
212
+ border-left: var(--sform-border-width) solid var(--sform-border);
213
+ }
214
+
215
+ /* ===========================================
216
+ Textarea
217
+ =========================================== */
218
+ textarea.sform-input {
219
+ min-height: 100px;
220
+ resize: vertical;
221
+ }
222
+
223
+ .sform-textarea-wrapper {
224
+ align-items: stretch;
225
+ }
226
+
227
+ .sform-textarea-wrapper .sform-prefix-icon,
228
+ .sform-textarea-wrapper .sform-suffix-icon,
229
+ .sform-textarea-wrapper .sform-prefix,
230
+ .sform-textarea-wrapper .sform-suffix {
231
+ align-self: flex-start;
232
+ padding-top: 0.625rem;
233
+ }
234
+
235
+ /* ===========================================
236
+ Select
237
+ =========================================== */
238
+ select.sform-input {
239
+ appearance: none;
240
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
241
+ background-repeat: no-repeat;
242
+ background-position: right 0.75rem center;
243
+ padding-right: 2.5rem;
244
+ }
245
+
246
+ /* ===========================================
247
+ Checkbox & Radio Base
248
+ =========================================== */
249
+ .sform-checkbox,
250
+ .sform-radio {
251
+ accent-color: var(--sform-primary);
252
+ cursor: pointer;
253
+ }
254
+
255
+ .sform-checkbox:disabled,
256
+ .sform-radio:disabled {
257
+ cursor: not-allowed;
258
+ opacity: 0.5;
259
+ }
260
+
261
+ /* Radio Group */
262
+ .sform-radio-group {
263
+ display: flex;
264
+ flex-direction: column;
265
+ gap: var(--sform-gap-sm);
266
+ }
267
+
268
+ .sform-radio-option {
269
+ display: flex;
270
+ align-items: center;
271
+ gap: var(--sform-gap-sm);
272
+ cursor: pointer;
273
+ font-size: var(--sform-font-size);
274
+ color: var(--sform-text);
275
+ }
276
+
277
+ .sform-radio-option:has(input:disabled) {
278
+ cursor: not-allowed;
279
+ opacity: 0.5;
280
+ }
281
+
282
+ /* Checkbox Group */
283
+ .sform-checkbox-group {
284
+ display: flex;
285
+ flex-direction: column;
286
+ gap: var(--sform-gap-sm);
287
+ }
288
+
289
+ .sform-checkbox-option {
290
+ display: flex;
291
+ align-items: center;
292
+ gap: var(--sform-gap-sm);
293
+ cursor: pointer;
294
+ font-size: var(--sform-font-size);
295
+ color: var(--sform-text);
296
+ }
297
+
298
+ /* ===========================================
299
+ Range Slider
300
+ =========================================== */
301
+ .sform-range-wrapper {
302
+ display: flex;
303
+ align-items: center;
304
+ gap: var(--sform-gap);
305
+ }
306
+
307
+ .sform-range {
308
+ flex: 1;
309
+ height: 0.5rem;
310
+ appearance: none;
311
+ background: var(--sform-border);
312
+ border-radius: 9999px;
313
+ cursor: pointer;
314
+ }
315
+
316
+ .sform-range::-webkit-slider-thumb {
317
+ appearance: none;
318
+ width: 1.25rem;
319
+ height: 1.25rem;
320
+ background: var(--sform-primary);
321
+ border-radius: 50%;
322
+ cursor: grab;
323
+ transition: transform var(--sform-transition);
324
+ }
325
+
326
+ .sform-range::-webkit-slider-thumb:hover {
327
+ transform: scale(1.1);
328
+ }
329
+
330
+ .sform-range::-webkit-slider-thumb:active {
331
+ cursor: grabbing;
332
+ }
333
+
334
+ .sform-range::-moz-range-thumb {
335
+ width: 1.25rem;
336
+ height: 1.25rem;
337
+ background: var(--sform-primary);
338
+ border: none;
339
+ border-radius: 50%;
340
+ cursor: grab;
341
+ }
342
+
343
+ .sform-range:disabled {
344
+ opacity: 0.5;
345
+ cursor: not-allowed;
346
+ }
347
+
348
+ .sform-range-value {
349
+ min-width: 3ch;
350
+ padding: var(--sform-padding-sm);
351
+ font-size: var(--sform-font-size-sm);
352
+ font-weight: 500;
353
+ text-align: center;
354
+ color: var(--sform-text);
355
+ background: var(--sform-bg-muted);
356
+ border-radius: var(--sform-radius);
357
+ }
358
+
359
+ /* ===========================================
360
+ Toggle Switch
361
+ =========================================== */
362
+ .sform-toggle {
363
+ display: inline-flex;
364
+ align-items: center;
365
+ gap: var(--sform-gap-sm);
366
+ cursor: pointer;
367
+ }
368
+
369
+ .sform-toggle.disabled {
370
+ opacity: 0.5;
371
+ cursor: not-allowed;
372
+ }
373
+
374
+ .sform-toggle input {
375
+ position: absolute;
376
+ opacity: 0;
377
+ width: 0;
378
+ height: 0;
379
+ }
380
+
381
+ .sform-toggle-track {
382
+ position: relative;
383
+ width: 2.75rem;
384
+ height: 1.5rem;
385
+ background: var(--sform-border);
386
+ border-radius: 9999px;
387
+ transition: background-color var(--sform-transition);
388
+ }
389
+
390
+ .sform-toggle input:checked + .sform-toggle-track {
391
+ background: var(--sform-primary);
392
+ }
393
+
394
+ .sform-toggle input:focus-visible + .sform-toggle-track {
395
+ box-shadow: var(--sform-shadow-focus);
396
+ }
397
+
398
+ .sform-toggle-thumb {
399
+ position: absolute;
400
+ top: 0.125rem;
401
+ left: 0.125rem;
402
+ width: 1.25rem;
403
+ height: 1.25rem;
404
+ background: white;
405
+ border-radius: 50%;
406
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
407
+ transition: transform var(--sform-transition);
408
+ }
409
+
410
+ .sform-toggle input:checked + .sform-toggle-track .sform-toggle-thumb {
411
+ transform: translateX(1.25rem);
412
+ }
413
+
414
+ .sform-toggle-label {
415
+ font-size: var(--sform-font-size);
416
+ color: var(--sform-text);
417
+ user-select: none;
418
+ }
419
+
420
+ /* ===========================================
421
+ Toggle Options (Segmented Control)
422
+ =========================================== */
423
+ .sform-toggle-options {
424
+ display: inline-flex;
425
+ background: var(--sform-bg-muted);
426
+ border-radius: var(--sform-radius-lg);
427
+ padding: 0.25rem;
428
+ gap: 0.25rem;
429
+ }
430
+
431
+ .sform-toggle-option {
432
+ padding: var(--sform-padding-sm);
433
+ font-size: var(--sform-font-size-sm);
434
+ font-weight: 500;
435
+ color: var(--sform-text-muted);
436
+ background: transparent;
437
+ border: none;
438
+ border-radius: var(--sform-radius);
439
+ cursor: pointer;
440
+ transition:
441
+ background-color var(--sform-transition),
442
+ color var(--sform-transition);
443
+ }
444
+
445
+ .sform-toggle-option:hover:not(:disabled):not(.selected) {
446
+ color: var(--sform-text);
447
+ background: rgba(0, 0, 0, 0.05);
448
+ }
449
+
450
+ .sform-toggle-option.selected {
451
+ color: var(--sform-primary);
452
+ background: var(--sform-bg);
453
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
454
+ }
455
+
456
+ .sform-toggle-option:disabled {
457
+ opacity: 0.5;
458
+ cursor: not-allowed;
459
+ }
460
+
461
+ /* ===========================================
462
+ Password Input with Toggle
463
+ =========================================== */
464
+ .sform-password-wrapper {
465
+ position: relative;
466
+ display: flex;
467
+ align-items: center;
468
+ }
469
+
470
+ .sform-password-wrapper .sform-input {
471
+ padding-right: 3rem;
472
+ }
473
+
474
+ .sform-password-toggle {
475
+ position: absolute;
476
+ right: 0.5rem;
477
+ display: flex;
478
+ align-items: center;
479
+ justify-content: center;
480
+ width: 2rem;
481
+ height: 2rem;
482
+ padding: 0;
483
+ color: var(--sform-text-muted);
484
+ background: transparent;
485
+ border: none;
486
+ border-radius: var(--sform-radius);
487
+ cursor: pointer;
488
+ transition: color var(--sform-transition);
489
+ }
490
+
491
+ .sform-password-toggle:hover {
492
+ color: var(--sform-text);
493
+ }
494
+
495
+ .sform-password-toggle:focus-visible {
496
+ outline: 2px solid var(--sform-primary);
497
+ outline-offset: 2px;
498
+ }
499
+
500
+ /* ===========================================
501
+ Masked Input
502
+ =========================================== */
503
+ .sform-masked {
504
+ font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
505
+ letter-spacing: 0.05em;
506
+ }
507
+
508
+ /* ===========================================
509
+ Hint Text
510
+ =========================================== */
511
+ .sform-hint {
512
+ font-size: var(--sform-font-size-sm);
513
+ color: var(--sform-text-muted);
514
+ line-height: var(--sform-line-height);
515
+ }
516
+
517
+ /* ===========================================
518
+ Validation Messages
519
+ =========================================== */
520
+ .sform-messages {
521
+ display: flex;
522
+ flex-direction: column;
523
+ gap: 0.25rem;
524
+ }
525
+
526
+ .sform-messages p {
527
+ margin: 0;
528
+ font-size: var(--sform-font-size-sm);
529
+ color: var(--sform-error);
530
+ line-height: var(--sform-line-height);
531
+ }
532
+
533
+ /* ===========================================
534
+ Button
535
+ =========================================== */
536
+ .sform-button {
537
+ display: inline-flex;
538
+ align-items: center;
539
+ justify-content: center;
540
+ gap: var(--sform-gap-sm);
541
+ padding: var(--sform-padding);
542
+ font-size: var(--sform-font-size);
543
+ font-weight: 500;
544
+ color: white;
545
+ background: var(--sform-primary);
546
+ border: none;
547
+ border-radius: var(--sform-radius);
548
+ cursor: pointer;
549
+ transition:
550
+ background-color var(--sform-transition),
551
+ transform var(--sform-transition);
552
+ }
553
+
554
+ .sform-button:hover:not(:disabled) {
555
+ background: var(--sform-primary-hover);
556
+ }
557
+
558
+ .sform-button:active:not(:disabled) {
559
+ transform: scale(0.98);
560
+ }
561
+
562
+ .sform-button:focus-visible {
563
+ outline: 2px solid var(--sform-primary);
564
+ outline-offset: 2px;
565
+ }
566
+
567
+ .sform-button:disabled {
568
+ opacity: 0.6;
569
+ cursor: not-allowed;
570
+ }
571
+
572
+ /* Button variants */
573
+ .sform-button-secondary {
574
+ color: var(--sform-text);
575
+ background: var(--sform-bg-muted);
576
+ border: var(--sform-border-width) solid var(--sform-border);
577
+ }
578
+
579
+ .sform-button-secondary:hover:not(:disabled) {
580
+ background: var(--sform-border);
581
+ }
582
+
583
+ .sform-button-success {
584
+ background: var(--sform-success);
585
+ }
586
+
587
+ .sform-button-success:hover:not(:disabled) {
588
+ background: #059669;
589
+ }
590
+
591
+ /* ===========================================
592
+ Result Messages
593
+ =========================================== */
594
+ .sform-result {
595
+ padding: 0.75rem 1rem;
596
+ font-size: var(--sform-font-size-sm);
597
+ border-radius: var(--sform-radius);
598
+ }
599
+
600
+ .sform-result-success {
601
+ color: #065f46;
602
+ background: var(--sform-success-bg);
603
+ }
604
+
605
+ .sform-result-error {
606
+ color: #991b1b;
607
+ background: var(--sform-error-bg);
608
+ }
609
+
610
+ .sform-result-warning {
611
+ color: #92400e;
612
+ background: var(--sform-warning-bg);
613
+ }
614
+
615
+ /* ===========================================
616
+ Utilities
617
+ =========================================== */
618
+ .sform-sr-only {
619
+ position: absolute;
620
+ width: 1px;
621
+ height: 1px;
622
+ padding: 0;
623
+ margin: -1px;
624
+ overflow: hidden;
625
+ clip: rect(0, 0, 0, 0);
626
+ white-space: nowrap;
627
+ border: 0;
628
+ }