1- import { axios , type RouterRequestConfig , type VortexConfig } from "./router"
1+ import { axios , RouterResponse , type RouterRequestConfig , type VortexConfig } from "./router"
2+ import { useForm , VortexForm } from "./form"
3+ import { formDataToObject , isEqual } from "./helpers"
4+ import { Signal , signal } from "./signals"
25
3- export type Action < E extends HTMLElement , T > = (
6+ export type Action < E extends HTMLElement , T , R = { } > = (
47 node : E ,
58 parameters ?: T
69) => {
710 update ?: ( parameters : T ) => void
811 destroy ?: ( ) => void
9- }
12+ } & R
1013
1114type PrefetchMethod = 'click' | 'mount' | 'hover'
1215type PrefetchLinkConfig = {
@@ -153,3 +156,50 @@ export const visible: Action<HTMLElement, (VisibleConfig & RouterRequestConfig)
153156 }
154157 }
155158}
159+
160+ interface FormOptions extends RouterRequestConfig {
161+ before ?: ( form : VortexForm < any > ) => VortexForm < any >
162+ after ?: ( result : Promise < RouterResponse < any > > ) => any
163+ }
164+
165+ export const form : Action < HTMLFormElement , FormOptions , { errors : Signal < Record < string , string > > } > = ( node , rawOptions = { } ) => {
166+ let options : FormOptions = {
167+ before : ( form ) => form ,
168+ after : ( result ) => result ,
169+ ...rawOptions
170+ }
171+ const form = useForm ( formDataToObject ( new FormData ( node ) ) )
172+ const errors = signal ( form . get ( ) . errors , isEqual )
173+
174+ const unsubscribe = form . subscribe ( ( form ) => errors . set ( form . errors ) )
175+
176+ function submit ( event : SubmitEvent ) {
177+ event . preventDefault ( )
178+
179+ const { before, after } = options
180+
181+ // @ts -expect-error
182+ return after ( before ( form . get ( ) ) . request ( {
183+ method : node . method || 'post' ,
184+ url : node . action || ( window . location . origin + window . location . pathname ) ,
185+ ...options
186+ } ) )
187+ }
188+
189+ node . addEventListener ( 'submit' , submit )
190+
191+ return {
192+ errors,
193+ update ( newOptions ) {
194+ options = {
195+ before : ( form ) => form ,
196+ after : ( result ) => result ,
197+ ...newOptions
198+ }
199+ } ,
200+ destroy ( ) {
201+ node . removeEventListener ( 'submit' , submit )
202+ unsubscribe ( )
203+ }
204+ }
205+ }
0 commit comments