vanilla-jui 1.5.12 → 1.5.13
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 +24 -20
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/form.ts +6 -1
- package/src/css/content.css +9 -3
- package/src/css/form.css +17 -17
- package/src/css/tokens.css +5 -5
- package/src/validation/validator.ts +33 -9
package/package.json
CHANGED
package/src/components/form.ts
CHANGED
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
resolveProps,
|
|
24
24
|
validateParam,
|
|
25
25
|
} from '../utilities/types.ts';
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
createValidator,
|
|
28
|
+
type ValidatorClassNameConfig,
|
|
29
|
+
} from '../validation/validator.ts';
|
|
27
30
|
import { createLoading } from '../primitives/loading.ts';
|
|
28
31
|
import { t } from 'vanilla-signal-i18n';
|
|
29
32
|
import locales from '../locales/index.ts';
|
|
@@ -137,6 +140,7 @@ export interface FormValidatorConfig {
|
|
|
137
140
|
rules?: Record<string, Record<string, unknown>>;
|
|
138
141
|
messages?: Record<string, Record<string, string>>;
|
|
139
142
|
vanilla?: boolean;
|
|
143
|
+
className?: ValidatorClassNameConfig;
|
|
140
144
|
onSubmit?: (() => void) | null;
|
|
141
145
|
[key: string]: unknown;
|
|
142
146
|
}
|
|
@@ -640,6 +644,7 @@ export function createForm(input: FormProps = {}): Form {
|
|
|
640
644
|
if (!element) return;
|
|
641
645
|
for (const control of Array.from(element.elements)) {
|
|
642
646
|
control.classList.remove('is-valid', 'is-invalid');
|
|
647
|
+
control.removeAttribute('data-valid');
|
|
643
648
|
}
|
|
644
649
|
for (const help of all<HTMLElement>(
|
|
645
650
|
'[data-field-help], [data-validator-help]',
|
package/src/css/content.css
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
margin: var(--content-heading-space) 0
|
|
32
32
|
calc(var(--content-heading-space) * 0.75);
|
|
33
33
|
font-weight: 600;
|
|
34
|
-
line-height: 1.3;
|
|
34
|
+
/* line-height: 1.3; */
|
|
35
35
|
color: var(--content-heading-fg);
|
|
36
36
|
letter-spacing: -0.02em;
|
|
37
37
|
}
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
.j-content h2 {
|
|
47
47
|
font-size: 1.625em;
|
|
48
48
|
font-weight: 650;
|
|
49
|
-
padding-bottom: 0.
|
|
49
|
+
padding-bottom: 0.25em;
|
|
50
50
|
border-bottom: 1px solid var(--content-border-subtle);
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -458,9 +458,15 @@
|
|
|
458
458
|
.hljs-comment,
|
|
459
459
|
.hljs-code,
|
|
460
460
|
.hljs-formula {
|
|
461
|
-
color: var(--ui-
|
|
461
|
+
color: var(--ui-fg-soft);
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
+
/* .dark .hljs-comment,
|
|
465
|
+
.dark .hljs-code,
|
|
466
|
+
.dark .hljs-formula {
|
|
467
|
+
color: var(--ui-gray-shade);
|
|
468
|
+
} */
|
|
469
|
+
|
|
464
470
|
/* prettylights-syntax-entity-tag */
|
|
465
471
|
.hljs-name,
|
|
466
472
|
.hljs-quote,
|
package/src/css/form.css
CHANGED
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
margin: 0;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
.j-form .form-field .field-control .help-block
|
|
73
|
+
.j-form .form-field .field-control .help-block[data-valid='false'] {
|
|
74
74
|
color: var(--state-danger);
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -188,12 +188,12 @@
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/* input validate */
|
|
191
|
-
/* .j-input
|
|
192
|
-
.j-select
|
|
193
|
-
.j-textarea
|
|
194
|
-
.j-input
|
|
195
|
-
.j-select
|
|
196
|
-
.j-textarea
|
|
191
|
+
/* .j-input[data-valid='true'],
|
|
192
|
+
.j-select[data-valid='true'],
|
|
193
|
+
.j-textarea[data-valid='true'],
|
|
194
|
+
.j-input[data-valid='false'],
|
|
195
|
+
.j-select[data-valid='false'],
|
|
196
|
+
.j-textarea[data-valid='false'] {
|
|
197
197
|
padding-right: calc(1.4285714286em + 0.875rem);
|
|
198
198
|
background-repeat: no-repeat;
|
|
199
199
|
background-position: right calc(0.3571428572em + 0.21875rem) center;
|
|
@@ -201,16 +201,16 @@
|
|
|
201
201
|
calc(0.7142857143em + 0.4375rem);
|
|
202
202
|
} */
|
|
203
203
|
|
|
204
|
-
/* .j-input
|
|
205
|
-
.j-select
|
|
206
|
-
.j-textarea
|
|
204
|
+
/* .j-input[data-valid='true'],
|
|
205
|
+
.j-select[data-valid='true'],
|
|
206
|
+
.j-textarea[data-valid='true'] {
|
|
207
207
|
border-color: var(--form-valid-border-color, var(--state-success));
|
|
208
208
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");
|
|
209
209
|
} */
|
|
210
210
|
|
|
211
|
-
.j-input
|
|
212
|
-
.j-select
|
|
213
|
-
.j-textarea
|
|
211
|
+
.j-input[data-valid='false'],
|
|
212
|
+
.j-select[data-valid='false'],
|
|
213
|
+
.j-textarea[data-valid='false'] {
|
|
214
214
|
border-color: var(--form-invalid-border-color, var(--state-danger));
|
|
215
215
|
/* background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e"); */
|
|
216
216
|
}
|
|
@@ -861,14 +861,14 @@
|
|
|
861
861
|
box-shadow: var(--input-focus-shadow, none);
|
|
862
862
|
}
|
|
863
863
|
|
|
864
|
-
/* .j-input
|
|
865
|
-
.j-select
|
|
864
|
+
/* .j-input[data-valid='true']:focus-within,
|
|
865
|
+
.j-select[data-valid='true']:focus-within {
|
|
866
866
|
border-color: transparent;
|
|
867
867
|
outline-color: var(--form-valid-border-color, var(--state-success));
|
|
868
868
|
} */
|
|
869
869
|
|
|
870
|
-
.j-input
|
|
871
|
-
.j-select
|
|
870
|
+
.j-input[data-valid='false']:focus-within,
|
|
871
|
+
.j-select[data-valid='false']:focus-within {
|
|
872
872
|
border-color: transparent;
|
|
873
873
|
outline-color: var(--form-invalid-border-color, var(--state-danger));
|
|
874
874
|
}
|
package/src/css/tokens.css
CHANGED
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
--z-badge: 2;
|
|
16
16
|
--z-toolbar: 2;
|
|
17
17
|
--z-submenu: 5;
|
|
18
|
+
--z-overlay: 9500;
|
|
19
|
+
--z-offcanvas: 9600;
|
|
20
|
+
--z-popup: 9700;
|
|
21
|
+
--z-toast: 9800;
|
|
18
22
|
--z-drop: 9900;
|
|
19
|
-
--z-overlay: 9950;
|
|
20
|
-
--z-offcanvas: 9960;
|
|
21
|
-
--z-popup: 9970;
|
|
22
|
-
--z-toast: 9980;
|
|
23
23
|
|
|
24
24
|
/* --- Spacing --- */
|
|
25
25
|
--space: 0.25rem;
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
--ui-disabled-fg: #64748b;
|
|
318
318
|
--ui-overlay: rgba(2, 6, 23, 0.7);
|
|
319
319
|
--ui-overlay-muted: rgba(2, 6, 23, 0.45);
|
|
320
|
-
--ui-popup-bg: rgba(17, 24, 39, 0.
|
|
320
|
+
--ui-popup-bg: rgba(17, 24, 39, 0.45);
|
|
321
321
|
--ui-input-color: #f9fafb;
|
|
322
322
|
--ui-input-border: rgba(148, 163, 184, 0.2);
|
|
323
323
|
--ui-input-focus-border: #a78bfa;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsx } from 'vanilla-signal';
|
|
2
2
|
|
|
3
|
+
import { joinClasses } from '../utilities/class-name.ts';
|
|
3
4
|
import { type DOMReference, all, resolveElement } from '../utilities/dom.ts';
|
|
4
5
|
import { createEventManager } from '../utilities/events.ts';
|
|
6
|
+
import { isPlainObject } from '../utilities/object.ts';
|
|
5
7
|
import {
|
|
6
8
|
type ResolveSchema,
|
|
7
9
|
resolveProps,
|
|
@@ -45,13 +47,21 @@ interface ValidatorProps extends Record<string, unknown> {
|
|
|
45
47
|
rules?: Record<string, ValidatorRule>;
|
|
46
48
|
messages?: ValidatorMessageMap;
|
|
47
49
|
vanilla?: boolean;
|
|
50
|
+
className?: ValidatorClassNameConfig;
|
|
48
51
|
onSubmit?: ((validator: ValidatorInstance) => void) | null;
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
export interface ValidatorClassNames {
|
|
55
|
+
help: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type ValidatorClassNameConfig = Partial<ValidatorClassNames>;
|
|
59
|
+
|
|
51
60
|
interface ResolvedValidatorProps extends Record<string, unknown> {
|
|
52
61
|
rules: Record<string, ValidatorRule>;
|
|
53
62
|
messages: ValidatorMessageMap;
|
|
54
63
|
vanilla: boolean;
|
|
64
|
+
className: ValidatorClassNames;
|
|
55
65
|
onSubmit: ((validator: ValidatorInstance) => void) | null;
|
|
56
66
|
}
|
|
57
67
|
|
|
@@ -75,19 +85,36 @@ export interface ValidatorInstance {
|
|
|
75
85
|
destroy(): void;
|
|
76
86
|
}
|
|
77
87
|
|
|
88
|
+
const DEFAULT_CLASS_NAMES: ValidatorClassNames = {
|
|
89
|
+
help: 'help-block',
|
|
90
|
+
};
|
|
91
|
+
|
|
78
92
|
const VALIDATOR_PROPS_SCHEMA = {
|
|
79
93
|
rules: { default: {}, type: 'object' },
|
|
80
94
|
messages: { default: {}, type: 'object' },
|
|
81
95
|
vanilla: { default: false, type: 'boolean' },
|
|
96
|
+
className: {
|
|
97
|
+
default: DEFAULT_CLASS_NAMES,
|
|
98
|
+
type: 'object',
|
|
99
|
+
normalize: (value: unknown) => resolveClassNames(value),
|
|
100
|
+
},
|
|
82
101
|
onSubmit: { default: null, types: ['function', 'null'] },
|
|
83
102
|
} satisfies ResolveSchema<ValidatorProps>;
|
|
84
103
|
|
|
104
|
+
function resolveClassNames(value: unknown): ValidatorClassNames {
|
|
105
|
+
return {
|
|
106
|
+
...DEFAULT_CLASS_NAMES,
|
|
107
|
+
...(isPlainObject(value) ? (value as ValidatorClassNameConfig) : {}),
|
|
108
|
+
} as ValidatorClassNames;
|
|
109
|
+
}
|
|
110
|
+
|
|
85
111
|
function normalizeProps(input: ValidatorProps): ResolvedValidatorProps {
|
|
86
112
|
const props = resolveProps(input, VALIDATOR_PROPS_SCHEMA, 'Validator.props');
|
|
87
113
|
return {
|
|
88
114
|
rules: props.rules as Record<string, ValidatorRule>,
|
|
89
115
|
messages: props.messages as ValidatorMessageMap,
|
|
90
116
|
vanilla: props.vanilla as boolean,
|
|
117
|
+
className: props.className as ValidatorClassNames,
|
|
91
118
|
onSubmit: props.onSubmit as ResolvedValidatorProps['onSubmit'],
|
|
92
119
|
};
|
|
93
120
|
}
|
|
@@ -353,10 +380,7 @@ function showError(
|
|
|
353
380
|
rule: string,
|
|
354
381
|
customMessage = ''
|
|
355
382
|
): void {
|
|
356
|
-
|
|
357
|
-
element.classList.remove('is-valid');
|
|
358
|
-
element.classList.add('is-invalid');
|
|
359
|
-
}
|
|
383
|
+
element.dataset.valid = 'false';
|
|
360
384
|
|
|
361
385
|
const error = customMessage || props?.messages[name]?.[rule] || '';
|
|
362
386
|
if (!error) return;
|
|
@@ -372,11 +396,13 @@ function showError(
|
|
|
372
396
|
) || null;
|
|
373
397
|
if (!help) {
|
|
374
398
|
help = jsx('div', {
|
|
375
|
-
|
|
399
|
+
'data-valid': 'false',
|
|
376
400
|
'data-validator-help': name,
|
|
377
401
|
}) as HTMLElement;
|
|
378
402
|
formControl.appendChild(help);
|
|
379
403
|
}
|
|
404
|
+
help.className = joinClasses(props?.className.help);
|
|
405
|
+
help.dataset.valid = 'false';
|
|
380
406
|
help.textContent = error;
|
|
381
407
|
}
|
|
382
408
|
|
|
@@ -388,9 +414,7 @@ function showSuccess(element: ValidatorElement): void {
|
|
|
388
414
|
}
|
|
389
415
|
}
|
|
390
416
|
|
|
391
|
-
|
|
392
|
-
element.classList.remove('is-invalid');
|
|
393
|
-
}
|
|
417
|
+
element.removeAttribute('data-valid');
|
|
394
418
|
}
|
|
395
419
|
|
|
396
420
|
export function createValidator(
|
|
@@ -543,7 +567,7 @@ export function createValidator(
|
|
|
543
567
|
if (native) root.reset();
|
|
544
568
|
for (const control of Array.from(root.elements)) {
|
|
545
569
|
if (isValidatorElement(control)) {
|
|
546
|
-
control.
|
|
570
|
+
control.removeAttribute('data-valid');
|
|
547
571
|
}
|
|
548
572
|
}
|
|
549
573
|
for (const help of all<HTMLElement>('[data-validator-help]', root)) {
|