-
Notifications
You must be signed in to change notification settings - Fork 0
/
preact.ts
79 lines (65 loc) · 1.86 KB
/
preact.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
import { RefObject } from 'preact'
import {
Mode,
getEventNameForMode,
getFormValues,
getOnSubmit,
setHiddenValue,
} from './mod.ts'
export type UseFormOptions<T> = {
onSubmit?: (state: T, form: HTMLFormElement) => void
}
export type Form = RefObject<HTMLFormElement>
export function useForm<T>(opts?: UseFormOptions<T>): Form {
const form = useRef<HTMLFormElement>(null)
useEffect(() => {
const el = form.current
if (!el) return
const onSubmit = getOnSubmit<T>(el, opts?.onSubmit)
el.addEventListener('submit', onSubmit)
return () => {
el?.removeEventListener('submit', onSubmit)
}
}, [form, opts])
return form
}
export function useInput() {
const ref = useRef<HTMLInputElement>(null)
const setValue = useCallback((value: string) => {
if (ref.current) setHiddenValue(ref.current, value)
}, [])
return [ref, setValue] as const
}
export type UseFormValuesOptions<T> = {
mode?: Mode
initialValue?: T
}
export function useFormValues<T>(form: Form, opts?: UseFormValuesOptions<T>) {
const mode = opts?.mode || 'change'
const initialValue = opts?.initialValue || ({} as T)
const [state, setState] = useState<T>(initialValue)
// Initial load
useEffect(() => {
if (!form.current) return
setState(getFormValues(form.current))
}, [form])
// Subcribe to changes
useEffect(() => {
const el = form.current
if (!el) return
const onChange = () => {
setState(getFormValues(el))
}
const fields = Array.from<Element>(el.elements)
fields.forEach((field) => {
field.addEventListener(getEventNameForMode(field, mode), onChange)
})
return () => {
fields.forEach((field) => {
field.removeEventListener(getEventNameForMode(field, mode), onChange)
})
}
}, [mode, form])
return state
}