@stacksjs/stx 0.2.155 → 0.2.156
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/dist/a11y.d.ts +87 -46
- package/dist/animation.d.ts +96 -42
- package/dist/appearance-bootstrap.d.ts +49 -15
- package/dist/asset-roots.d.ts +32 -0
- package/dist/asset-roots.js +7 -0
- package/dist/assets.d.ts +9 -7
- package/dist/async-components.d.ts +78 -56
- package/dist/auth.d.ts +3 -0
- package/dist/build-externalize.d.ts +40 -0
- package/dist/build-externalize.js +63 -0
- package/dist/build-id.d.ts +22 -22
- package/dist/build-message.d.ts +73 -2
- package/dist/build-message.js +47 -8
- package/dist/builtins/attrs.d.ts +14 -0
- package/dist/builtins/drawer.d.ts +22 -0
- package/dist/builtins/icon.d.ts +16 -2
- package/dist/builtins/index.d.ts +5 -15
- package/dist/builtins/modal.d.ts +24 -0
- package/dist/builtins/safe-image.d.ts +42 -0
- package/dist/builtins/stx-image.d.ts +27 -0
- package/dist/builtins/stx-link.d.ts +9 -0
- package/dist/builtins/stx-loading-indicator.d.ts +11 -0
- package/dist/builtins/suspense.d.ts +28 -0
- package/dist/builtins/toast.d.ts +17 -0
- package/dist/builtins/transition-group.d.ts +25 -0
- package/dist/caching.d.ts +12 -15
- package/dist/cli.js +1798 -908
- package/dist/client/directive.d.ts +7 -0
- package/dist/client/index.d.ts +0 -1
- package/dist/client-script-bundler.d.ts +63 -5
- package/dist/client-script-bundler.js +30 -2
- package/dist/client-script.d.ts +102 -47
- package/dist/client-script.js +15 -3
- package/dist/codemod.d.ts +56 -0
- package/dist/codemod.js +192 -0
- package/dist/color-mode-boot.d.ts +83 -65
- package/dist/component-client-factories.d.ts +1 -6
- package/dist/component-processing.d.ts +58 -49
- package/dist/component-processing.js +1 -1
- package/dist/component-registry.d.ts +94 -31
- package/dist/component-renderer.d.ts +18 -0
- package/dist/composable-loader.d.ts +24 -0
- package/dist/composable-loader.js +12 -9
- package/dist/composables/index.d.ts +7 -0
- package/dist/composables/index.js +1 -0
- package/dist/composables/use-fetch.js +30 -2
- package/dist/composables/use-form.d.ts +91 -0
- package/dist/composables/use-form.js +112 -0
- package/dist/composables.d.ts +64 -60
- package/dist/computed.d.ts +86 -92
- package/dist/conditionals.d.ts +24 -8
- package/dist/conditionals.js +16 -0
- package/dist/config.d.ts +34 -21
- package/dist/config.js +35 -14
- package/dist/craft.js +1476 -768
- package/dist/crosswind-config.d.ts +58 -0
- package/dist/crosswind-config.js +40 -0
- package/dist/csp.d.ts +107 -41
- package/dist/defer.d.ts +24 -0
- package/dist/dev-server/crosswind.d.ts +35 -26
- package/dist/dev-server/crosswind.js +2 -18
- package/dist/dev-server/serve-app.js +4 -3
- package/dist/dev-server/terminal-colors.d.ts +32 -32
- package/dist/directive-api.d.ts +86 -43
- package/dist/document-shell.d.ts +54 -41
- package/dist/dynamic-components.d.ts +9 -0
- package/dist/error-boundaries.d.ts +47 -41
- package/dist/error-handling.d.ts +1 -1
- package/dist/errors/codes.d.ts +51 -43
- package/dist/errors/formatter.d.ts +58 -38
- package/dist/errors/index.d.ts +5 -61
- package/dist/errors/logger.d.ts +114 -40
- package/dist/errors/sanitizer.d.ts +53 -23
- package/dist/errors/types.d.ts +44 -31
- package/dist/events.d.ts +86 -25
- package/dist/expressions.d.ts +50 -42
- package/dist/forms-validation.d.ts +138 -123
- package/dist/forms-validation.js +1 -90
- package/dist/forms.d.ts +120 -66
- package/dist/forms.js +31 -11
- package/dist/fragment-container.d.ts +57 -0
- package/dist/fragment-container.js +109 -0
- package/dist/framework-composables.d.ts +32 -0
- package/dist/head.d.ts +156 -114
- package/dist/heatmap.d.ts +152 -72
- package/dist/html-masking.d.ts +40 -34
- package/dist/hydration-runtime.d.ts +20 -24
- package/dist/i18n.d.ts +93 -32
- package/dist/image-optimization/auto-sibling.d.ts +32 -4
- package/dist/includes.d.ts +69 -7
- package/dist/index.d.ts +66 -0
- package/dist/index.js +23 -0
- package/dist/internal-markdown.d.ts +12 -8
- package/dist/island-chunking.d.ts +30 -13
- package/dist/keep-alive.d.ts +72 -52
- package/dist/layout-types.d.ts +45 -0
- package/dist/layout-types.js +56 -0
- package/dist/lazy-module.d.ts +10 -0
- package/dist/loops.d.ts +66 -0
- package/dist/loops.js +47 -6
- package/dist/markdown.d.ts +0 -1
- package/dist/media/image/component.d.ts +25 -9
- package/dist/media/image/directive.d.ts +15 -1
- package/dist/media/image/placeholder.d.ts +20 -9
- package/dist/media/image/processor/cache.d.ts +40 -18
- package/dist/media/image/processor/index.d.ts +1 -10
- package/dist/media/image/processor/optimizer.d.ts +12 -1
- package/dist/media/image/processor/responsive.d.ts +16 -6
- package/dist/media/image/srcset.d.ts +47 -50
- package/dist/media/shared/cache.d.ts +51 -31
- package/dist/media/shared/hash.d.ts +7 -0
- package/dist/media/types.d.ts +1235 -754
- package/dist/media/video/directive.d.ts +15 -1
- package/dist/media/video/index.d.ts +39 -17
- package/dist/media/video/processor/cache.d.ts +42 -19
- package/dist/media/video/processor/index.d.ts +1 -18
- package/dist/media/video/processor/streaming.d.ts +17 -10
- package/dist/media/video/processor/thumbnail.d.ts +21 -15
- package/dist/media/video/processor/transcoder.d.ts +11 -1
- package/dist/method-spoofing.d.ts +7 -0
- package/dist/middleware.d.ts +60 -0
- package/dist/owned-routes.d.ts +42 -0
- package/dist/owned-routes.js +26 -0
- package/dist/page-meta.d.ts +38 -0
- package/dist/page-meta.js +16 -0
- package/dist/parser/directive-parser.d.ts +57 -45
- package/dist/parser/expression-parser.d.ts +33 -35
- package/dist/parser/index.d.ts +4 -39
- package/dist/parser/tokenizer.d.ts +61 -49
- package/dist/partial-hydration.d.ts +82 -50
- package/dist/performance-utils.d.ts +217 -124
- package/dist/placeholder.d.ts +18 -9
- package/dist/plugin-system.d.ts +264 -115
- package/dist/process.d.ts +11 -6
- package/dist/process.js +21 -4
- package/dist/production-builder.js +7 -0
- package/dist/prop-sentinels.d.ts +11 -11
- package/dist/public-env.d.ts +14 -0
- package/dist/pwa/directives.d.ts +12 -3
- package/dist/pwa/inject.d.ts +10 -0
- package/dist/pwa/precache.d.ts +22 -16
- package/dist/pwa/service-worker.d.ts +12 -0
- package/dist/pwa.js +1318 -610
- package/dist/reactive-bindings.d.ts +34 -11
- package/dist/reactive.d.ts +58 -30
- package/dist/reactive.js +56 -31
- package/dist/render.js +1 -0
- package/dist/route-middleware.d.ts +2 -35
- package/dist/route-types.d.ts +134 -0
- package/dist/route-types.js +24 -0
- package/dist/router.d.ts +5 -7
- package/dist/routes.d.ts +1 -3
- package/dist/runtime-globals.d.ts +147 -24
- package/dist/runtime-globals.js +16 -1
- package/dist/runtime-injection.d.ts +8 -0
- package/dist/runtime-injection.js +33 -24
- package/dist/script-emit.d.ts +30 -0
- package/dist/script-json.d.ts +36 -0
- package/dist/script-json.js +6 -0
- package/dist/script-validation.d.ts +21 -4
- package/dist/seo.d.ts +118 -47
- package/dist/server-bindings.d.ts +21 -0
- package/dist/sfc-template.d.ts +8 -8
- package/dist/signal-processing.d.ts +35 -15
- package/dist/signals-api.d.ts +117 -58
- package/dist/signals-api.js +7 -4
- package/dist/signals.d.ts +24 -17
- package/dist/signals.js +765 -60
- package/dist/site-builder/build.js +8 -0
- package/dist/site-url.d.ts +46 -0
- package/dist/site-url.js +70 -0
- package/dist/slots.d.ts +86 -20
- package/dist/source-signature.d.ts +45 -0
- package/dist/source-signature.js +20 -0
- package/dist/ssg.d.ts +285 -142
- package/dist/ssg.js +1268 -556
- package/dist/state-dir.d.ts +4 -4
- package/dist/state-management.d.ts +0 -12
- package/dist/state-management.js +8 -25
- package/dist/store-imports.d.ts +23 -0
- package/dist/store-imports.js +3 -0
- package/dist/store-loader.d.ts +10 -0
- package/dist/store-loader.js +10 -9
- package/dist/story/analytics.d.ts +138 -60
- package/dist/story/bookmarks.d.ts +87 -34
- package/dist/story/cli.d.ts +123 -69
- package/dist/story/collect/scanner.d.ts +4 -0
- package/dist/story/collect/tree.d.ts +8 -1
- package/dist/story/commands/build.d.ts +11 -6
- package/dist/story/commands/dev.d.ts +15 -8
- package/dist/story/commands/preview.d.ts +13 -7
- package/dist/story/config-watcher.d.ts +20 -13
- package/dist/story/config.d.ts +11 -8
- package/dist/story/context.d.ts +14 -8
- package/dist/story/hmr.d.ts +24 -26
- package/dist/story/hot-swap.d.ts +34 -23
- package/dist/story/keyboard-shortcuts.d.ts +23 -18
- package/dist/story/output.d.ts +46 -44
- package/dist/story/performance.d.ts +107 -45
- package/dist/story/presets.d.ts +107 -41
- package/dist/story/renderer.d.ts +41 -27
- package/dist/story/search.d.ts +23 -12
- package/dist/story/server.d.ts +21 -11
- package/dist/story/setup.d.ts +23 -15
- package/dist/story/testing.d.ts +65 -40
- package/dist/story/types.d.ts +262 -160
- package/dist/streaming.d.ts +119 -57
- package/dist/stx-virtual-ts.d.ts +165 -0
- package/dist/stx-virtual-ts.js +372 -0
- package/dist/stx.d.ts +78 -1
- package/dist/style-scoping.d.ts +17 -4
- package/dist/suspense.d.ts +67 -52
- package/dist/teleport.d.ts +22 -0
- package/dist/template-tag-balance.d.ts +22 -6
- package/dist/transitions.d.ts +66 -55
- package/dist/typecheck.d.ts +77 -0
- package/dist/typecheck.js +156 -0
- package/dist/types/component-types.d.ts +187 -122
- package/dist/types/config-types.d.ts +758 -297
- package/dist/types/context-types.d.ts +46 -24
- package/dist/types/csp-types.d.ts +70 -66
- package/dist/types/directive-types.d.ts +211 -155
- package/dist/types/index.d.ts +6 -109
- package/dist/types/pwa-types.d.ts +273 -148
- package/dist/types.d.ts +0 -1
- package/dist/typescript-templates.d.ts +11 -0
- package/dist/unresolved-identifiers.d.ts +24 -22
- package/dist/unresolved-identifiers.js +2 -0
- package/dist/utils.d.ts +24 -21
- package/dist/validator.d.ts +28 -26
- package/dist/variable-extractor.d.ts +48 -13
- package/dist/variable-extractor.js +27 -4
- package/dist/view-composers.d.ts +80 -81
- package/dist/virtual-scrolling.d.ts +101 -81
- package/dist/vue-template.d.ts +23 -0
- package/dist/web-components/css-scoping.d.ts +21 -11
- package/dist/web-components.d.ts +81 -58
- package/dist/x-element.d.ts +0 -1
- package/package.json +5 -5
- package/stx.d.ts +78 -1
|
@@ -1,30 +1,151 @@
|
|
|
1
|
-
export type { ValidatorFn, AsyncValidatorFn, ValidatorRule, FieldState, FormState };
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* STX Form Validation
|
|
3
|
+
*
|
|
4
|
+
* A simple, chainable form validation API.
|
|
4
5
|
*
|
|
5
6
|
* @example
|
|
6
7
|
* ```typescript
|
|
7
|
-
*
|
|
8
|
+
* import { useForm, v } from 'stx'
|
|
9
|
+
*
|
|
10
|
+
* const form = useForm({
|
|
8
11
|
* email: v.required().email(),
|
|
9
12
|
* password: v.required().min(8),
|
|
10
13
|
* age: v.number().between(18, 100)
|
|
11
14
|
* })
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
type ValidatorFn = (value: unknown, formValues?: Record<string, unknown>) => true | string;
|
|
18
|
+
type AsyncValidatorFn = (value: unknown, formValues?: Record<string, unknown>) => Promise<true | string>;
|
|
19
|
+
interface ValidatorRule {
|
|
20
|
+
name: string;
|
|
21
|
+
validate: ValidatorFn | AsyncValidatorFn;
|
|
22
|
+
message: string;
|
|
23
|
+
async?: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface FieldState {
|
|
26
|
+
value: unknown;
|
|
27
|
+
errors: string[];
|
|
28
|
+
touched: boolean;
|
|
29
|
+
dirty: boolean;
|
|
30
|
+
valid: boolean;
|
|
31
|
+
validating: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface FormState<T extends Record<string, Validator>> {
|
|
34
|
+
values: {
|
|
35
|
+
[K in keyof T]: unknown;
|
|
36
|
+
};
|
|
37
|
+
errors: {
|
|
38
|
+
[K in keyof T]: string[];
|
|
39
|
+
};
|
|
40
|
+
touched: {
|
|
41
|
+
[K in keyof T]: boolean;
|
|
42
|
+
};
|
|
43
|
+
dirty: {
|
|
44
|
+
[K in keyof T]: boolean;
|
|
45
|
+
};
|
|
46
|
+
isValid: boolean;
|
|
47
|
+
isValidating: boolean;
|
|
48
|
+
isDirty: boolean;
|
|
49
|
+
validate: () => Promise<boolean>;
|
|
50
|
+
validateField: (field: keyof T) => Promise<boolean>;
|
|
51
|
+
reset: () => void;
|
|
52
|
+
setValues: (values: Partial<{
|
|
53
|
+
[K in keyof T]: unknown;
|
|
54
|
+
}>) => void;
|
|
55
|
+
setFieldValue: (field: keyof T, value: unknown) => void;
|
|
56
|
+
setFieldTouched: (field: keyof T, touched?: boolean) => void;
|
|
57
|
+
getFieldState: (field: keyof T) => FieldState;
|
|
58
|
+
handleSubmit: (onSubmit: (values: {
|
|
59
|
+
[K in keyof T]: unknown;
|
|
60
|
+
}) => void | Promise<void>) => (e?: Event) => Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
declare class Validator {
|
|
63
|
+
private rules;
|
|
64
|
+
private defaultValue;
|
|
65
|
+
private addRule;
|
|
66
|
+
/** Field is required */
|
|
67
|
+
required(message?: string): Validator;
|
|
68
|
+
/** Must be a valid email */
|
|
69
|
+
email(message?: string): Validator;
|
|
70
|
+
/** Must be a valid URL */
|
|
71
|
+
url(message?: string): Validator;
|
|
72
|
+
/** Minimum length */
|
|
73
|
+
min(length: number, message?: string): Validator;
|
|
74
|
+
/** Maximum length */
|
|
75
|
+
max(length: number, message?: string): Validator;
|
|
76
|
+
/** Length between min and max */
|
|
77
|
+
length(min: number, max: number, message?: string): Validator;
|
|
78
|
+
/** Must match a regex pattern */
|
|
79
|
+
pattern(regex: RegExp, message?: string): Validator;
|
|
80
|
+
/** Must contain uppercase letter */
|
|
81
|
+
hasUppercase(message?: string): Validator;
|
|
82
|
+
/** Must contain lowercase letter */
|
|
83
|
+
hasLowercase(message?: string): Validator;
|
|
84
|
+
/** Must contain a number */
|
|
85
|
+
hasNumber(message?: string): Validator;
|
|
86
|
+
/** Must contain a special character */
|
|
87
|
+
hasSpecial(message?: string): Validator;
|
|
88
|
+
/** Only alphanumeric characters */
|
|
89
|
+
alphanumeric(message?: string): Validator;
|
|
90
|
+
/** Must start with a letter */
|
|
91
|
+
startsWithLetter(message?: string): Validator;
|
|
92
|
+
/** No spaces allowed */
|
|
93
|
+
noSpaces(message?: string): Validator;
|
|
94
|
+
/** Must be a number */
|
|
95
|
+
number(message?: string): Validator;
|
|
96
|
+
/** Must be an integer */
|
|
97
|
+
integer(message?: string): Validator;
|
|
98
|
+
/** Must be positive */
|
|
99
|
+
positive(message?: string): Validator;
|
|
100
|
+
/** Must be negative */
|
|
101
|
+
negative(message?: string): Validator;
|
|
102
|
+
/** Minimum value */
|
|
103
|
+
minValue(min: number, message?: string): Validator;
|
|
104
|
+
/** Maximum value */
|
|
105
|
+
maxValue(max: number, message?: string): Validator;
|
|
106
|
+
/** Value between min and max */
|
|
107
|
+
between(min: number, max: number, message?: string): Validator;
|
|
108
|
+
/** Must match another field's value */
|
|
109
|
+
matches(fieldName: string, message?: string): Validator;
|
|
110
|
+
/** Must be one of the given values */
|
|
111
|
+
oneOf(values: unknown[], message?: string): Validator;
|
|
112
|
+
/** Must not be one of the given values */
|
|
113
|
+
notOneOf(values: unknown[], message?: string): Validator;
|
|
114
|
+
/** Must be a valid date */
|
|
115
|
+
date(message?: string): Validator;
|
|
116
|
+
/** Must be before a date */
|
|
117
|
+
before(date: Date | string, message?: string): Validator;
|
|
118
|
+
/** Must be after a date */
|
|
119
|
+
after(date: Date | string, message?: string): Validator;
|
|
120
|
+
/** Custom validation function */
|
|
121
|
+
custom(fn: ValidatorFn, message?: string): Validator;
|
|
122
|
+
/** Async custom validation (e.g., API check) */
|
|
123
|
+
async(fn: AsyncValidatorFn, message?: string): Validator;
|
|
124
|
+
/** Conditional validation */
|
|
125
|
+
when(condition: (value: unknown, formValues: Record<string, unknown>) => boolean, thenValidator: Validator): Validator;
|
|
126
|
+
/** Get all rules */
|
|
127
|
+
getRules(): ValidatorRule[];
|
|
128
|
+
/** Get default value for this validator */
|
|
129
|
+
getDefaultValue(): unknown;
|
|
130
|
+
/** Set default value */
|
|
131
|
+
default(value: unknown): Validator;
|
|
132
|
+
/** Validate a value */
|
|
133
|
+
validate(value: unknown, formValues?: Record<string, unknown>): Promise<string[]>;
|
|
134
|
+
/** Validate synchronously (ignores async rules) */
|
|
135
|
+
validateSync(value: unknown, formValues?: Record<string, unknown>): string[];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Starting point for building validation rules.
|
|
12
139
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* // Validate
|
|
19
|
-
* await form.validate()
|
|
20
|
-
*
|
|
21
|
-
* // Handle submit
|
|
22
|
-
* form.handleSubmit((values) => {
|
|
23
|
-
* console.log(values)
|
|
24
|
-
* })
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* v.required().email()
|
|
143
|
+
* v.required().min(8).hasUppercase()
|
|
144
|
+
* v.number().between(1, 100)
|
|
25
145
|
* ```
|
|
26
146
|
*/
|
|
27
|
-
export declare
|
|
147
|
+
export declare const v: Validator;
|
|
148
|
+
export { defineForm, useForm } from './composables/use-form';
|
|
28
149
|
/**
|
|
29
150
|
* Process @error directive in templates
|
|
30
151
|
*
|
|
@@ -64,111 +185,5 @@ export declare function processHasErrorsDirective(content: string, context: Reco
|
|
|
64
185
|
* Process all form validation directives
|
|
65
186
|
*/
|
|
66
187
|
export declare function processFormValidationDirectives(content: string, context: Record<string, unknown>, filePath?: string): string;
|
|
67
|
-
/**
|
|
68
|
-
* Starting point for building validation rules.
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* ```typescript
|
|
72
|
-
* v.required().email()
|
|
73
|
-
* v.required().min(8).hasUppercase()
|
|
74
|
-
* v.number().between(1, 100)
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export declare const v: Validator;
|
|
78
|
-
declare interface ValidatorRule {
|
|
79
|
-
name: string
|
|
80
|
-
validate: ValidatorFn | AsyncValidatorFn
|
|
81
|
-
message: string
|
|
82
|
-
async?: boolean
|
|
83
|
-
}
|
|
84
|
-
declare interface FieldState {
|
|
85
|
-
value: unknown
|
|
86
|
-
errors: string[]
|
|
87
|
-
touched: boolean
|
|
88
|
-
dirty: boolean
|
|
89
|
-
valid: boolean
|
|
90
|
-
validating: boolean
|
|
91
|
-
}
|
|
92
|
-
declare interface FormState<T extends Record<string, Validator>> {
|
|
93
|
-
values: { [K in keyof T]: unknown }
|
|
94
|
-
errors: { [K in keyof T]: string[] }
|
|
95
|
-
touched: { [K in keyof T]: boolean }
|
|
96
|
-
dirty: { [K in keyof T]: boolean }
|
|
97
|
-
isValid: boolean
|
|
98
|
-
isValidating: boolean
|
|
99
|
-
isDirty: boolean
|
|
100
|
-
validate: () => Promise<boolean>
|
|
101
|
-
validateField: (field: keyof T) => Promise<boolean>
|
|
102
|
-
reset: () => void
|
|
103
|
-
setValues: (values: Partial<{ [K in keyof T]: unknown }>) => void
|
|
104
|
-
setFieldValue: (field: keyof T, value: unknown) => void
|
|
105
|
-
setFieldTouched: (field: keyof T, touched?: boolean) => void
|
|
106
|
-
getFieldState: (field: keyof T) => FieldState
|
|
107
|
-
handleSubmit: (onSubmit: (values: { [K in keyof T]: unknown }) => void | Promise<void>) => (e?: Event) => Promise<void>
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* STX Form Validation
|
|
111
|
-
*
|
|
112
|
-
* A simple, chainable form validation API.
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* ```typescript
|
|
116
|
-
* import { defineForm, v } from 'stx'
|
|
117
|
-
*
|
|
118
|
-
* const form = defineForm({
|
|
119
|
-
* email: v.required().email(),
|
|
120
|
-
* password: v.required().min(8),
|
|
121
|
-
* age: v.number().between(18, 100)
|
|
122
|
-
* })
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
// =============================================================================
|
|
126
|
-
// Types
|
|
127
|
-
// =============================================================================
|
|
128
|
-
// eslint-disable-next-line pickier/no-unused-vars
|
|
129
|
-
declare type ValidatorFn = (value: unknown, formValues?: Record<string, unknown>) => true | string;
|
|
130
|
-
// eslint-disable-next-line pickier/no-unused-vars
|
|
131
|
-
declare type AsyncValidatorFn = (value: unknown, formValues?: Record<string, unknown>) => Promise<true | string>;
|
|
132
|
-
// =============================================================================
|
|
133
|
-
// Validator Class
|
|
134
|
-
// =============================================================================
|
|
135
|
-
declare class Validator {
|
|
136
|
-
required(message?: string): Validator;
|
|
137
|
-
email(message?: string): Validator;
|
|
138
|
-
url(message?: string): Validator;
|
|
139
|
-
min(length: number, message?: string): Validator;
|
|
140
|
-
max(length: number, message?: string): Validator;
|
|
141
|
-
length(min: number, max: number, message?: string): Validator;
|
|
142
|
-
pattern(regex: RegExp, message?: string): Validator;
|
|
143
|
-
hasUppercase(message?: string): Validator;
|
|
144
|
-
hasLowercase(message?: string): Validator;
|
|
145
|
-
hasNumber(message?: string): Validator;
|
|
146
|
-
hasSpecial(message?: string): Validator;
|
|
147
|
-
alphanumeric(message?: string): Validator;
|
|
148
|
-
startsWithLetter(message?: string): Validator;
|
|
149
|
-
noSpaces(message?: string): Validator;
|
|
150
|
-
number(message?: string): Validator;
|
|
151
|
-
integer(message?: string): Validator;
|
|
152
|
-
positive(message?: string): Validator;
|
|
153
|
-
negative(message?: string): Validator;
|
|
154
|
-
minValue(min: number, message?: string): Validator;
|
|
155
|
-
maxValue(max: number, message?: string): Validator;
|
|
156
|
-
between(min: number, max: number, message?: string): Validator;
|
|
157
|
-
matches(fieldName: string, message?: string): Validator;
|
|
158
|
-
oneOf(values: unknown[], message?: string): Validator;
|
|
159
|
-
notOneOf(values: unknown[], message?: string): Validator;
|
|
160
|
-
date(message?: string): Validator;
|
|
161
|
-
before(date: Date | string, message?: string): Validator;
|
|
162
|
-
after(date: Date | string, message?: string): Validator;
|
|
163
|
-
custom(fn: ValidatorFn, message?: string): Validator;
|
|
164
|
-
when(condition: (value: unknown, formValues: Record<string, unknown>) => boolean, thenValidator: Validator): Validator;
|
|
165
|
-
getRules(): ValidatorRule[];
|
|
166
|
-
getDefaultValue(): unknown;
|
|
167
|
-
default(value: unknown): Validator;
|
|
168
|
-
validate(value: unknown, formValues?: Record<string, unknown>): Promise<string[]>;
|
|
169
|
-
validateSync(value: unknown, formValues?: Record<string, unknown>): string[];
|
|
170
|
-
}
|
|
171
|
-
// =============================================================================
|
|
172
|
-
// Re-exports
|
|
173
|
-
// =============================================================================
|
|
174
188
|
export { Validator };
|
|
189
|
+
export type { ValidatorFn, AsyncValidatorFn, ValidatorRule, FieldState, FormState };
|
package/dist/forms-validation.js
CHANGED
|
@@ -345,96 +345,7 @@ class Validator {
|
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
347
|
export const v = new Validator;
|
|
348
|
-
export
|
|
349
|
-
const fields = Object.keys(schema), values = {}, errors = {}, touched = {}, dirty = {}, validating = {};
|
|
350
|
-
for (const field of fields) {
|
|
351
|
-
values[field] = initialValues?.[field] ?? schema[field].getDefaultValue();
|
|
352
|
-
errors[field] = [];
|
|
353
|
-
touched[field] = !1;
|
|
354
|
-
dirty[field] = !1;
|
|
355
|
-
validating[field] = !1;
|
|
356
|
-
}
|
|
357
|
-
let isValidating = !1;
|
|
358
|
-
async function validateField(field) {
|
|
359
|
-
validating[field] = !0;
|
|
360
|
-
const fieldErrors = await schema[field].validate(values[field], values);
|
|
361
|
-
errors[field] = fieldErrors;
|
|
362
|
-
validating[field] = !1;
|
|
363
|
-
return fieldErrors.length === 0;
|
|
364
|
-
}
|
|
365
|
-
async function validate() {
|
|
366
|
-
isValidating = !0;
|
|
367
|
-
const results = await Promise.all(fields.map(validateField));
|
|
368
|
-
isValidating = !1;
|
|
369
|
-
return results.every(Boolean);
|
|
370
|
-
}
|
|
371
|
-
function reset() {
|
|
372
|
-
for (const field of fields) {
|
|
373
|
-
values[field] = initialValues?.[field] ?? schema[field].getDefaultValue();
|
|
374
|
-
errors[field] = [];
|
|
375
|
-
touched[field] = !1;
|
|
376
|
-
dirty[field] = !1;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
function setValues(newValues) {
|
|
380
|
-
for (const field of fields)
|
|
381
|
-
if (field in newValues) {
|
|
382
|
-
values[field] = newValues[field];
|
|
383
|
-
dirty[field] = !0;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
function setFieldValue(field, value) {
|
|
387
|
-
values[field] = value;
|
|
388
|
-
dirty[field] = !0;
|
|
389
|
-
}
|
|
390
|
-
function setFieldTouched(field, isTouched = !0) {
|
|
391
|
-
touched[field] = isTouched;
|
|
392
|
-
if (isTouched)
|
|
393
|
-
validateField(field);
|
|
394
|
-
}
|
|
395
|
-
function getFieldState(field) {
|
|
396
|
-
return {
|
|
397
|
-
value: values[field],
|
|
398
|
-
errors: errors[field],
|
|
399
|
-
touched: touched[field],
|
|
400
|
-
dirty: dirty[field],
|
|
401
|
-
valid: errors[field].length === 0,
|
|
402
|
-
validating: validating[field]
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
function handleSubmit(onSubmit) {
|
|
406
|
-
return async (e) => {
|
|
407
|
-
e?.preventDefault?.();
|
|
408
|
-
for (const field of fields)
|
|
409
|
-
touched[field] = !0;
|
|
410
|
-
if (await validate())
|
|
411
|
-
await onSubmit(values);
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
return {
|
|
415
|
-
values,
|
|
416
|
-
errors,
|
|
417
|
-
touched,
|
|
418
|
-
dirty,
|
|
419
|
-
get isValid() {
|
|
420
|
-
return fields.every((f) => errors[f].length === 0);
|
|
421
|
-
},
|
|
422
|
-
get isValidating() {
|
|
423
|
-
return isValidating || fields.some((f) => validating[f]);
|
|
424
|
-
},
|
|
425
|
-
get isDirty() {
|
|
426
|
-
return fields.some((f) => dirty[f]);
|
|
427
|
-
},
|
|
428
|
-
validate,
|
|
429
|
-
validateField,
|
|
430
|
-
reset,
|
|
431
|
-
setValues,
|
|
432
|
-
setFieldValue,
|
|
433
|
-
setFieldTouched,
|
|
434
|
-
getFieldState,
|
|
435
|
-
handleSubmit
|
|
436
|
-
};
|
|
437
|
-
}
|
|
348
|
+
export { defineForm, useForm } from "./composables/use-form.js";
|
|
438
349
|
export function processErrorDirective(content, context, _filePath) {
|
|
439
350
|
const errorRegex = /@error\s*\(\s*([^)]+)\s*\)([\s\S]*?)@enderror/g;
|
|
440
351
|
return content.replace(errorRegex, (_, fieldPath, body) => {
|
package/dist/forms.d.ts
CHANGED
|
@@ -1,4 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module for processing form-related directives.
|
|
3
|
+
*
|
|
4
|
+
* Provides directives for building accessible, validated forms:
|
|
5
|
+
* - `@csrf` - CSRF token hidden input
|
|
6
|
+
* - `@method('PUT')` - HTTP method spoofing
|
|
7
|
+
* - `@form` / `@endform` - Form wrapper with auto CSRF
|
|
8
|
+
* - `@input`, `@textarea`, `@select` - Form controls with validation
|
|
9
|
+
* - `@checkbox`, `@radio` - Check inputs with state binding
|
|
10
|
+
* - `@file` - File upload input with accept and multiple support
|
|
11
|
+
* - `@label` - Associated labels
|
|
12
|
+
* - `@error` / `@enderror` - Validation error display
|
|
13
|
+
* - `@validate` - Add validation rules with HTML5 attributes
|
|
14
|
+
*
|
|
15
|
+
* ## File Upload Example
|
|
16
|
+
*
|
|
17
|
+
* ```html
|
|
18
|
+
* @file('avatar', { accept: 'image/*' })
|
|
19
|
+
* @file('documents', { accept: '.pdf,.doc,.docx', multiple: true })
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ## Validation Rules
|
|
23
|
+
*
|
|
24
|
+
* Built-in validation rules:
|
|
25
|
+
* - `required` - Field must have a value
|
|
26
|
+
* - `email` - Must be valid email format
|
|
27
|
+
* - `url` - Must be valid URL
|
|
28
|
+
* - `numeric` - Must be a number
|
|
29
|
+
* - `integer` - Must be an integer
|
|
30
|
+
* - `alpha` - Letters only
|
|
31
|
+
* - `alphanumeric` - Letters and numbers only
|
|
32
|
+
* - `min:n` - Minimum length/value
|
|
33
|
+
* - `max:n` - Maximum length/value
|
|
34
|
+
* - `confirmed` - Must match `{field}_confirmation`
|
|
35
|
+
* - `in:a,b,c` - Must be one of the values
|
|
36
|
+
* - `notIn:a,b,c` - Must not be one of the values
|
|
37
|
+
* - `regex:pattern` - Must match regex
|
|
38
|
+
* - `date` - Must be valid date
|
|
39
|
+
* - `before:date` - Must be before date
|
|
40
|
+
* - `after:date` - Must be after date
|
|
41
|
+
*
|
|
42
|
+
* ## Configuration
|
|
43
|
+
*
|
|
44
|
+
* CSS class names can be customized via `stx.config.ts`:
|
|
45
|
+
* ```typescript
|
|
46
|
+
* export default {
|
|
47
|
+
* forms: {
|
|
48
|
+
* classes: {
|
|
49
|
+
* input: 'my-input',
|
|
50
|
+
* inputError: 'my-input--error',
|
|
51
|
+
* // ...
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
1
57
|
import type { StxOptions } from './types';
|
|
58
|
+
/**
|
|
59
|
+
* Default CSS class names for form elements.
|
|
60
|
+
* Based on Bootstrap conventions but fully customizable.
|
|
61
|
+
*/
|
|
62
|
+
export interface FormClassConfig {
|
|
63
|
+
/** Class for text inputs, textareas, and selects (default: 'form-control') */
|
|
64
|
+
input: string;
|
|
65
|
+
/** Class added to inputs with validation errors (default: 'is-invalid') */
|
|
66
|
+
inputError: string;
|
|
67
|
+
/** Class for checkboxes and radios (default: 'form-check-input') */
|
|
68
|
+
checkInput: string;
|
|
69
|
+
/** Class for labels (default: 'form-label') */
|
|
70
|
+
label: string;
|
|
71
|
+
/** Class for error message containers (default: 'invalid-feedback') */
|
|
72
|
+
errorFeedback: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Default form class configuration (Bootstrap-compatible)
|
|
76
|
+
*/
|
|
77
|
+
export declare const defaultFormClasses: FormClassConfig;
|
|
2
78
|
/**
|
|
3
79
|
* Process all form-related directives.
|
|
4
80
|
*
|
|
@@ -30,6 +106,25 @@ export declare function processFormInputDirectives(template: string, context: Re
|
|
|
30
106
|
* ```
|
|
31
107
|
*/
|
|
32
108
|
export declare function processErrorDirective(template: string, context: Record<string, any>, _classes?: FormClassConfig): string;
|
|
109
|
+
/**
|
|
110
|
+
* Validation rule definition
|
|
111
|
+
*/
|
|
112
|
+
export interface ValidationRule {
|
|
113
|
+
/** Rule name (e.g., 'required', 'email', 'min') */
|
|
114
|
+
name: string;
|
|
115
|
+
/** Rule parameters (e.g., min:5 → params = ['5']) */
|
|
116
|
+
params?: string[];
|
|
117
|
+
/** Custom error message */
|
|
118
|
+
message?: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Validation result for a single field
|
|
122
|
+
*/
|
|
123
|
+
export interface FieldValidationResult {
|
|
124
|
+
field: string;
|
|
125
|
+
valid: boolean;
|
|
126
|
+
errors: string[];
|
|
127
|
+
}
|
|
33
128
|
/**
|
|
34
129
|
* Register a custom validation rule.
|
|
35
130
|
*
|
|
@@ -88,6 +183,23 @@ export declare function validateFields(data: Record<string, any>, rules: Record<
|
|
|
88
183
|
* ```
|
|
89
184
|
*/
|
|
90
185
|
export declare function processValidateDirective(template: string, _context: Record<string, any>): string;
|
|
186
|
+
/**
|
|
187
|
+
* Enhanced validation rule definition with HTML5 support
|
|
188
|
+
*/
|
|
189
|
+
export interface EnhancedValidationRule {
|
|
190
|
+
/** Rule name */
|
|
191
|
+
name: string;
|
|
192
|
+
/** Validation function - returns true if valid, error message if invalid */
|
|
193
|
+
validate: (value: unknown, params: string[], allValues: Record<string, unknown>) => true | string;
|
|
194
|
+
/** HTML5 attribute generator */
|
|
195
|
+
toHtml5?: (params: string[]) => string[];
|
|
196
|
+
/** Default error message with {{param}} placeholders */
|
|
197
|
+
message: string;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Enhanced validation rules registry with full validation support
|
|
201
|
+
*/
|
|
202
|
+
export declare const enhancedValidationRules: Record<string, EnhancedValidationRule>;
|
|
91
203
|
/**
|
|
92
204
|
* Register a custom enhanced validation rule
|
|
93
205
|
*/
|
|
@@ -95,76 +207,18 @@ export declare function registerEnhancedValidationRule(rule: EnhancedValidationR
|
|
|
95
207
|
/**
|
|
96
208
|
* Validate a single value against enhanced rules
|
|
97
209
|
*/
|
|
98
|
-
export declare function validateValueEnhanced(value: unknown, rules: string, allValues?: Record<string, unknown>): {
|
|
210
|
+
export declare function validateValueEnhanced(value: unknown, rules: string, allValues?: Record<string, unknown>): {
|
|
211
|
+
valid: boolean;
|
|
212
|
+
errors: string[];
|
|
213
|
+
};
|
|
99
214
|
/**
|
|
100
215
|
* Validate multiple values with enhanced validation
|
|
101
216
|
*/
|
|
102
|
-
export declare function validateFormEnhanced(values: Record<string, unknown>, rules: Record<string, string>): {
|
|
217
|
+
export declare function validateFormEnhanced(values: Record<string, unknown>, rules: Record<string, string>): {
|
|
218
|
+
valid: boolean;
|
|
219
|
+
errors: Record<string, string[]>;
|
|
220
|
+
};
|
|
103
221
|
/**
|
|
104
222
|
* Generate client-side validation script for a form
|
|
105
223
|
*/
|
|
106
224
|
export declare function generateValidationScript(formId: string, rules: Record<string, string>): string;
|
|
107
|
-
/**
|
|
108
|
-
* Default form class configuration (Bootstrap-compatible)
|
|
109
|
-
*/
|
|
110
|
-
export declare const defaultFormClasses: FormClassConfig;
|
|
111
|
-
/**
|
|
112
|
-
* Enhanced validation rules registry with full validation support
|
|
113
|
-
*/
|
|
114
|
-
export declare const enhancedValidationRules: {
|
|
115
|
-
required: { name: 'required'; validate: (value) => unknown; toHtml5: () => readonly ['required']; message: 'This field is required' };
|
|
116
|
-
email: { name: 'email'; validate: (value) => unknown; toHtml5: () => readonly ['type="email"']; message: 'Please enter a valid email address' };
|
|
117
|
-
url: { name: 'url'; validate: (value) => unknown; toHtml5: () => readonly ['type="url"']; message: 'Please enter a valid URL' };
|
|
118
|
-
numeric: { name: 'numeric'; validate: (value) => unknown; toHtml5: () => readonly ['type="number"']; message: 'Please enter a number' };
|
|
119
|
-
integer: { name: 'integer'; validate: (value) => unknown; toHtml5: () => readonly ['type="number"', 'step="1"']; message: 'Please enter a whole number' };
|
|
120
|
-
alpha: { name: 'alpha'; validate: (value) => unknown; toHtml5: () => readonly ['pattern="[a-zA-Z]+"']; message: 'Please enter only letters' };
|
|
121
|
-
alphanumeric: { name: 'alphanumeric'; validate: (value) => unknown; toHtml5: () => readonly ['pattern="[a-zA-Z0-9]+"']; message: 'Please enter only letters and numbers' };
|
|
122
|
-
min: { name: 'min'; validate: (value, params) => unknown; toHtml5: (params) => readonly [`minlength="${params[0]}"`, `min="${params[0]}"`]; message: 'Must be at least {{param}} characters' };
|
|
123
|
-
max: { name: 'max'; validate: (value, params) => unknown; toHtml5: (params) => readonly [`maxlength="${params[0]}"`, `max="${params[0]}"`]; message: 'Must be no more than {{param}} characters' };
|
|
124
|
-
between: { name: 'between'; validate: (value, params) => unknown; toHtml5: (params) => readonly [`minlength="${params[0]}"`, `maxlength="${params[1]}"`]; message: 'Must be between {{min}} and {{max}}' };
|
|
125
|
-
confirmed: { name: 'confirmed'; validate: (value, _params, allValues) => unknown; message: 'Confirmation does not match' };
|
|
126
|
-
in: { name: 'in'; validate: (value, params) => unknown; message: 'Must be one of: {{values}}' };
|
|
127
|
-
notIn: { name: 'notIn'; validate: (value, params) => unknown; message: 'Must not be: {{values}}' };
|
|
128
|
-
regex: { name: 'regex'; validate: (value, params) => unknown; toHtml5: (params) => readonly [`pattern="${params[0]}"`]; message: 'Invalid format' };
|
|
129
|
-
date: { name: 'date'; validate: (value) => unknown; toHtml5: () => readonly ['type="date"']; message: 'Please enter a valid date' };
|
|
130
|
-
before: { name: 'before'; validate: (value, params) => unknown; toHtml5: (params) => readonly [`max="${params[0]}"`]; message: 'Must be before {{date}}' };
|
|
131
|
-
after: { name: 'after'; validate: (value, params) => unknown; toHtml5: (params) => readonly [`min="${params[0]}"`]; message: 'Must be after {{date}}' };
|
|
132
|
-
size: { name: 'size'; validate: (value, params) => unknown; message: 'Must be exactly {{size}}' };
|
|
133
|
-
phone: { name: 'phone'; validate: (value) => unknown; toHtml5: () => readonly ['type="tel"', 'pattern="\\+?\\(?\\d{1,4}\\)?[-\\s./\\d]*"']; message: 'Please enter a valid phone number' }
|
|
134
|
-
};
|
|
135
|
-
/**
|
|
136
|
-
* Default CSS class names for form elements.
|
|
137
|
-
* Based on Bootstrap conventions but fully customizable.
|
|
138
|
-
*/
|
|
139
|
-
export declare interface FormClassConfig {
|
|
140
|
-
input: string
|
|
141
|
-
inputError: string
|
|
142
|
-
checkInput: string
|
|
143
|
-
label: string
|
|
144
|
-
errorFeedback: string
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Validation rule definition
|
|
148
|
-
*/
|
|
149
|
-
export declare interface ValidationRule {
|
|
150
|
-
name: string
|
|
151
|
-
params?: string[]
|
|
152
|
-
message?: string
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Validation result for a single field
|
|
156
|
-
*/
|
|
157
|
-
export declare interface FieldValidationResult {
|
|
158
|
-
field: string
|
|
159
|
-
valid: boolean
|
|
160
|
-
errors: string[]
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Enhanced validation rule definition with HTML5 support
|
|
164
|
-
*/
|
|
165
|
-
export declare interface EnhancedValidationRule {
|
|
166
|
-
name: string
|
|
167
|
-
validate: (value: unknown, params: string[], allValues: Record<string, unknown>) => true | string
|
|
168
|
-
toHtml5?: (params: string[]) => string[]
|
|
169
|
-
message: string
|
|
170
|
-
}
|