@stacksjs/stx 0.2.155 → 0.2.157

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 (241) hide show
  1. package/dist/a11y.d.ts +87 -46
  2. package/dist/animation.d.ts +96 -42
  3. package/dist/appearance-bootstrap.d.ts +49 -15
  4. package/dist/asset-roots.d.ts +32 -0
  5. package/dist/asset-roots.js +7 -0
  6. package/dist/assets.d.ts +9 -7
  7. package/dist/async-components.d.ts +78 -56
  8. package/dist/auth.d.ts +3 -0
  9. package/dist/build-externalize.d.ts +40 -0
  10. package/dist/build-externalize.js +63 -0
  11. package/dist/build-id.d.ts +22 -22
  12. package/dist/build-message.d.ts +73 -2
  13. package/dist/build-message.js +47 -8
  14. package/dist/builtins/attrs.d.ts +14 -0
  15. package/dist/builtins/drawer.d.ts +22 -0
  16. package/dist/builtins/icon.d.ts +16 -2
  17. package/dist/builtins/index.d.ts +5 -15
  18. package/dist/builtins/modal.d.ts +24 -0
  19. package/dist/builtins/safe-image.d.ts +42 -0
  20. package/dist/builtins/stx-image.d.ts +27 -0
  21. package/dist/builtins/stx-link.d.ts +9 -0
  22. package/dist/builtins/stx-loading-indicator.d.ts +11 -0
  23. package/dist/builtins/suspense.d.ts +28 -0
  24. package/dist/builtins/toast.d.ts +17 -0
  25. package/dist/builtins/transition-group.d.ts +25 -0
  26. package/dist/caching.d.ts +12 -15
  27. package/dist/cli.js +1798 -908
  28. package/dist/client/directive.d.ts +7 -0
  29. package/dist/client/index.d.ts +0 -1
  30. package/dist/client-script-bundler.d.ts +63 -5
  31. package/dist/client-script-bundler.js +30 -2
  32. package/dist/client-script.d.ts +102 -47
  33. package/dist/client-script.js +15 -3
  34. package/dist/codemod.d.ts +56 -0
  35. package/dist/codemod.js +192 -0
  36. package/dist/color-mode-boot.d.ts +83 -65
  37. package/dist/component-client-factories.d.ts +1 -6
  38. package/dist/component-processing.d.ts +58 -49
  39. package/dist/component-processing.js +1 -1
  40. package/dist/component-registry.d.ts +94 -31
  41. package/dist/component-renderer.d.ts +18 -0
  42. package/dist/composable-loader.d.ts +24 -0
  43. package/dist/composable-loader.js +12 -9
  44. package/dist/composables/index.d.ts +7 -0
  45. package/dist/composables/index.js +1 -0
  46. package/dist/composables/use-fetch.js +30 -2
  47. package/dist/composables/use-form.d.ts +91 -0
  48. package/dist/composables/use-form.js +112 -0
  49. package/dist/composables.d.ts +64 -60
  50. package/dist/computed.d.ts +86 -92
  51. package/dist/conditionals.d.ts +24 -8
  52. package/dist/conditionals.js +16 -0
  53. package/dist/config.d.ts +34 -21
  54. package/dist/config.js +35 -14
  55. package/dist/craft.js +1476 -768
  56. package/dist/crosswind-config.d.ts +58 -0
  57. package/dist/crosswind-config.js +40 -0
  58. package/dist/csp.d.ts +107 -41
  59. package/dist/defer.d.ts +24 -0
  60. package/dist/dev-server/crosswind.d.ts +35 -26
  61. package/dist/dev-server/crosswind.js +2 -18
  62. package/dist/dev-server/serve-app.js +4 -3
  63. package/dist/dev-server/terminal-colors.d.ts +32 -32
  64. package/dist/directive-api.d.ts +86 -43
  65. package/dist/document-shell.d.ts +54 -41
  66. package/dist/dynamic-components.d.ts +9 -0
  67. package/dist/error-boundaries.d.ts +47 -41
  68. package/dist/error-handling.d.ts +1 -1
  69. package/dist/errors/codes.d.ts +51 -43
  70. package/dist/errors/formatter.d.ts +58 -38
  71. package/dist/errors/index.d.ts +5 -61
  72. package/dist/errors/logger.d.ts +114 -40
  73. package/dist/errors/sanitizer.d.ts +53 -23
  74. package/dist/errors/types.d.ts +44 -31
  75. package/dist/events.d.ts +86 -25
  76. package/dist/expressions.d.ts +50 -42
  77. package/dist/forms-validation.d.ts +138 -123
  78. package/dist/forms-validation.js +1 -90
  79. package/dist/forms.d.ts +120 -66
  80. package/dist/forms.js +31 -11
  81. package/dist/fragment-container.d.ts +57 -0
  82. package/dist/fragment-container.js +109 -0
  83. package/dist/framework-composables.d.ts +32 -0
  84. package/dist/head.d.ts +156 -114
  85. package/dist/heatmap.d.ts +152 -72
  86. package/dist/html-masking.d.ts +40 -34
  87. package/dist/hydration-runtime.d.ts +20 -24
  88. package/dist/i18n.d.ts +93 -32
  89. package/dist/image-optimization/auto-sibling.d.ts +32 -4
  90. package/dist/includes.d.ts +69 -7
  91. package/dist/index.d.ts +66 -0
  92. package/dist/index.js +23 -0
  93. package/dist/internal-markdown.d.ts +12 -8
  94. package/dist/island-chunking.d.ts +30 -13
  95. package/dist/keep-alive.d.ts +72 -52
  96. package/dist/layout-types.d.ts +45 -0
  97. package/dist/layout-types.js +56 -0
  98. package/dist/lazy-module.d.ts +10 -0
  99. package/dist/loops.d.ts +66 -0
  100. package/dist/loops.js +47 -6
  101. package/dist/markdown.d.ts +0 -1
  102. package/dist/media/image/component.d.ts +25 -9
  103. package/dist/media/image/directive.d.ts +15 -1
  104. package/dist/media/image/placeholder.d.ts +20 -9
  105. package/dist/media/image/processor/cache.d.ts +40 -18
  106. package/dist/media/image/processor/index.d.ts +1 -10
  107. package/dist/media/image/processor/optimizer.d.ts +12 -1
  108. package/dist/media/image/processor/responsive.d.ts +16 -6
  109. package/dist/media/image/srcset.d.ts +47 -50
  110. package/dist/media/shared/cache.d.ts +51 -31
  111. package/dist/media/shared/hash.d.ts +7 -0
  112. package/dist/media/types.d.ts +1235 -754
  113. package/dist/media/video/directive.d.ts +15 -1
  114. package/dist/media/video/index.d.ts +39 -17
  115. package/dist/media/video/processor/cache.d.ts +42 -19
  116. package/dist/media/video/processor/index.d.ts +1 -18
  117. package/dist/media/video/processor/streaming.d.ts +17 -10
  118. package/dist/media/video/processor/thumbnail.d.ts +21 -15
  119. package/dist/media/video/processor/transcoder.d.ts +11 -1
  120. package/dist/method-spoofing.d.ts +7 -0
  121. package/dist/middleware.d.ts +60 -0
  122. package/dist/owned-routes.d.ts +42 -0
  123. package/dist/owned-routes.js +26 -0
  124. package/dist/page-meta.d.ts +38 -0
  125. package/dist/page-meta.js +16 -0
  126. package/dist/parser/directive-parser.d.ts +57 -45
  127. package/dist/parser/expression-parser.d.ts +33 -35
  128. package/dist/parser/index.d.ts +4 -39
  129. package/dist/parser/tokenizer.d.ts +61 -49
  130. package/dist/partial-hydration.d.ts +82 -50
  131. package/dist/performance-utils.d.ts +217 -124
  132. package/dist/placeholder.d.ts +18 -9
  133. package/dist/plugin-system.d.ts +264 -115
  134. package/dist/process.d.ts +11 -6
  135. package/dist/process.js +21 -4
  136. package/dist/production-builder.js +7 -0
  137. package/dist/prop-sentinels.d.ts +11 -11
  138. package/dist/public-env.d.ts +14 -0
  139. package/dist/pwa/directives.d.ts +12 -3
  140. package/dist/pwa/inject.d.ts +10 -0
  141. package/dist/pwa/precache.d.ts +22 -16
  142. package/dist/pwa/service-worker.d.ts +12 -0
  143. package/dist/pwa.js +1318 -610
  144. package/dist/reactive-bindings.d.ts +34 -11
  145. package/dist/reactive.d.ts +58 -30
  146. package/dist/reactive.js +56 -31
  147. package/dist/render.d.ts +0 -14
  148. package/dist/render.js +17 -0
  149. package/dist/route-middleware.d.ts +2 -35
  150. package/dist/route-types.d.ts +134 -0
  151. package/dist/route-types.js +24 -0
  152. package/dist/router.d.ts +5 -7
  153. package/dist/routes.d.ts +1 -3
  154. package/dist/runtime-globals.d.ts +147 -24
  155. package/dist/runtime-globals.js +16 -1
  156. package/dist/runtime-injection.d.ts +8 -0
  157. package/dist/runtime-injection.js +33 -24
  158. package/dist/script-emit.d.ts +30 -0
  159. package/dist/script-json.d.ts +36 -0
  160. package/dist/script-json.js +6 -0
  161. package/dist/script-validation.d.ts +21 -4
  162. package/dist/seo.d.ts +118 -47
  163. package/dist/server-bindings.d.ts +21 -0
  164. package/dist/sfc-template.d.ts +8 -8
  165. package/dist/signal-processing.d.ts +35 -15
  166. package/dist/signals-api.d.ts +117 -58
  167. package/dist/signals-api.js +7 -4
  168. package/dist/signals.d.ts +24 -17
  169. package/dist/signals.js +765 -60
  170. package/dist/site-builder/build.js +8 -0
  171. package/dist/site-url.d.ts +46 -0
  172. package/dist/site-url.js +70 -0
  173. package/dist/slots.d.ts +86 -20
  174. package/dist/source-signature.d.ts +45 -0
  175. package/dist/source-signature.js +20 -0
  176. package/dist/ssg.d.ts +285 -142
  177. package/dist/ssg.js +1268 -556
  178. package/dist/state-dir.d.ts +4 -4
  179. package/dist/state-management.d.ts +0 -12
  180. package/dist/state-management.js +8 -25
  181. package/dist/store-imports.d.ts +23 -0
  182. package/dist/store-imports.js +3 -0
  183. package/dist/store-loader.d.ts +10 -0
  184. package/dist/store-loader.js +10 -9
  185. package/dist/story/analytics.d.ts +138 -60
  186. package/dist/story/bookmarks.d.ts +87 -34
  187. package/dist/story/cli.d.ts +123 -69
  188. package/dist/story/collect/scanner.d.ts +4 -0
  189. package/dist/story/collect/tree.d.ts +8 -1
  190. package/dist/story/commands/build.d.ts +11 -6
  191. package/dist/story/commands/dev.d.ts +15 -8
  192. package/dist/story/commands/preview.d.ts +13 -7
  193. package/dist/story/config-watcher.d.ts +20 -13
  194. package/dist/story/config.d.ts +11 -8
  195. package/dist/story/context.d.ts +14 -8
  196. package/dist/story/hmr.d.ts +24 -26
  197. package/dist/story/hot-swap.d.ts +34 -23
  198. package/dist/story/keyboard-shortcuts.d.ts +23 -18
  199. package/dist/story/output.d.ts +46 -44
  200. package/dist/story/performance.d.ts +107 -45
  201. package/dist/story/presets.d.ts +107 -41
  202. package/dist/story/renderer.d.ts +41 -27
  203. package/dist/story/search.d.ts +23 -12
  204. package/dist/story/server.d.ts +21 -11
  205. package/dist/story/setup.d.ts +23 -15
  206. package/dist/story/testing.d.ts +65 -40
  207. package/dist/story/types.d.ts +262 -160
  208. package/dist/streaming.d.ts +119 -57
  209. package/dist/stx-virtual-ts.d.ts +165 -0
  210. package/dist/stx-virtual-ts.js +372 -0
  211. package/dist/stx.d.ts +78 -1
  212. package/dist/style-scoping.d.ts +17 -4
  213. package/dist/suspense.d.ts +67 -52
  214. package/dist/teleport.d.ts +22 -0
  215. package/dist/template-tag-balance.d.ts +22 -6
  216. package/dist/transitions.d.ts +66 -55
  217. package/dist/typecheck.d.ts +77 -0
  218. package/dist/typecheck.js +156 -0
  219. package/dist/types/component-types.d.ts +187 -122
  220. package/dist/types/config-types.d.ts +758 -297
  221. package/dist/types/context-types.d.ts +46 -24
  222. package/dist/types/csp-types.d.ts +70 -66
  223. package/dist/types/directive-types.d.ts +211 -155
  224. package/dist/types/index.d.ts +6 -109
  225. package/dist/types/pwa-types.d.ts +273 -148
  226. package/dist/types.d.ts +0 -1
  227. package/dist/typescript-templates.d.ts +11 -0
  228. package/dist/unresolved-identifiers.d.ts +24 -22
  229. package/dist/unresolved-identifiers.js +2 -0
  230. package/dist/utils.d.ts +24 -21
  231. package/dist/validator.d.ts +28 -26
  232. package/dist/variable-extractor.d.ts +48 -13
  233. package/dist/variable-extractor.js +27 -4
  234. package/dist/view-composers.d.ts +80 -81
  235. package/dist/virtual-scrolling.d.ts +101 -81
  236. package/dist/vue-template.d.ts +23 -0
  237. package/dist/web-components/css-scoping.d.ts +21 -11
  238. package/dist/web-components.d.ts +81 -58
  239. package/dist/x-element.d.ts +0 -1
  240. package/package.json +5 -5
  241. package/stx.d.ts +78 -1
@@ -1,30 +1,151 @@
1
- export type { ValidatorFn, AsyncValidatorFn, ValidatorRule, FieldState, FormState };
2
1
  /**
3
- * Define a form with validation schema.
2
+ * STX Form Validation
3
+ *
4
+ * A simple, chainable form validation API.
4
5
  *
5
6
  * @example
6
7
  * ```typescript
7
- * const form = defineForm({
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
- * // Access form state
14
- * form.values.email
15
- * form.errors.email
16
- * form.isValid
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 function defineForm<T extends Record<string, Validator>>(schema: T, initialValues?: Partial<{ [K in keyof T]: unknown }>): FormState<T>;
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 };
@@ -345,96 +345,7 @@ class Validator {
345
345
  }
346
346
  }
347
347
  export const v = new Validator;
348
- export function defineForm(schema, initialValues) {
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>): { valid: boolean, errors: string[] };
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>): { valid: boolean, errors: 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
- }