/
FormRadio.ts
100 lines (88 loc) · 3.08 KB
/
FormRadio.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import * as React from "react";
import { createComponent } from "reakit-system/createComponent";
import { As, PropsWithAs } from "reakit-utils/types";
import { createHook } from "reakit-system/createHook";
import { useAllCallbacks } from "reakit-utils/useAllCallbacks";
import { RadioHTMLProps, useRadio } from "../Radio/Radio";
import { BoxOptions } from "../Box";
import { FormRadioGroupContext } from "./FormRadioGroup";
import { unstable_FormStateReturn, unstable_useFormState } from "./FormState";
import { unstable_getIn } from "./utils/getIn";
import { formatInputName } from "./__utils/formatInputName";
import { DeepPath, DeepPathValue } from "./__utils/types";
export type unstable_FormRadioOptions<
V,
P extends DeepPath<V, P>
> = BoxOptions &
Pick<unstable_FormStateReturn<V>, "values" | "update" | "blur"> & {
/**
* FormRadio's name as in form values.
*/
name: P;
/**
* FormRadio's value.
*/
value: DeepPathValue<V, P>;
};
export type unstable_FormRadioHTMLProps = RadioHTMLProps;
export type unstable_FormRadioProps<
V,
P extends DeepPath<V, P>
> = unstable_FormRadioOptions<V, P> & unstable_FormRadioHTMLProps;
export const unstable_useFormRadio = createHook<
unstable_FormRadioOptions<any, any>,
unstable_FormRadioHTMLProps
>({
name: "FormRadio",
compose: useRadio,
useState: unstable_useFormState,
keys: ["name", "value"],
useOptions(options, htmlProps) {
const name = options.name || htmlProps.name;
const value =
typeof options.value !== "undefined" ? options.value : htmlProps.value;
const rover = React.useContext(FormRadioGroupContext);
const currentChecked = unstable_getIn(options.values, name);
const checked = currentChecked === value;
if (!rover) {
// TODO: Better error
throw new Error("Missing FormRadioGroup");
}
return { ...options, ...rover, checked, name, value };
},
useProps(
options,
{
onChange: htmlOnChange,
onBlur: htmlOnBlur,
onFocus: htmlOnFocus,
...htmlProps
}
) {
const onChange = React.useCallback(() => {
options.update(options.name, options.value);
}, [options.update, options.name, options.value]);
const onBlur = React.useCallback(() => {
options.blur(options.name);
}, [options.blur, options.name]);
const onFocus = React.useCallback(() => {
options.update(options.name, options.value);
}, [options.update, options.name, options.value]);
return {
name: formatInputName(options.name),
onChange: useAllCallbacks(onChange, htmlOnChange),
onBlur: useAllCallbacks(onBlur, htmlOnBlur),
onFocus: useAllCallbacks(onFocus, htmlOnFocus),
...htmlProps
};
}
}) as <V, P extends DeepPath<V, P>>(
options: unstable_FormRadioOptions<V, P>,
htmlProps?: unstable_FormRadioHTMLProps
) => unstable_FormRadioHTMLProps;
export const unstable_FormRadio = (createComponent({
as: "input",
useHook: unstable_useFormRadio
}) as unknown) as <V, P extends DeepPath<V, P>, T extends As = "input">(
props: PropsWithAs<unstable_FormRadioOptions<V, P>, T>
) => JSX.Element;