1 | import * as React from "react";
|
2 | import { As, PropsWithAs, ArrayValue } from "reakit-utils/types";
|
3 | import { createComponent } from "reakit-system/createComponent";
|
4 | import { createHook } from "reakit-system/createHook";
|
5 | import { useLiveRef } from "reakit-utils/useLiveRef";
|
6 | import {
|
7 | CheckboxOptions,
|
8 | CheckboxHTMLProps,
|
9 | useCheckbox,
|
10 | } from "../Checkbox/Checkbox";
|
11 | import { DeepPath, DeepPathValue } from "./__utils/types";
|
12 | import { getInputId } from "./__utils/getInputId";
|
13 | import { getLabelId } from "./__utils/getLabelId";
|
14 | import { unstable_FormStateReturn } from "./FormState";
|
15 | import { unstable_getIn } from "./utils/getIn";
|
16 | import { formatInputName } from "./__utils/formatInputName";
|
17 | import { getMessageId } from "./__utils/getMessageId";
|
18 | import { shouldShowError } from "./__utils/shouldShowError";
|
19 | import { FORM_CHECKBOX_KEYS } from "./__keys";
|
20 |
|
21 | export type unstable_FormCheckboxOptions<V, P extends DeepPath<V, P>> = Omit<
|
22 | CheckboxOptions,
|
23 | "value" | "state" | "setState"
|
24 | > &
|
25 | Pick<
|
26 | unstable_FormStateReturn<V>,
|
27 | "baseId" | "values" | "update" | "blur" | "touched" | "errors"
|
28 | > & {
|
29 | |
30 |
|
31 |
|
32 | name: P;
|
33 | |
34 |
|
35 |
|
36 |
|
37 |
|
38 | value?: ArrayValue<DeepPathValue<V, P>>;
|
39 | };
|
40 |
|
41 | export type unstable_FormCheckboxHTMLProps = CheckboxHTMLProps &
|
42 | React.InputHTMLAttributes<any>;
|
43 |
|
44 | export type unstable_FormCheckboxProps<
|
45 | V,
|
46 | P extends DeepPath<V, P>
|
47 | > = unstable_FormCheckboxOptions<V, P> & unstable_FormCheckboxHTMLProps;
|
48 |
|
49 | export const unstable_useFormCheckbox = createHook<
|
50 | unstable_FormCheckboxOptions<any, any>,
|
51 | unstable_FormCheckboxHTMLProps
|
52 | >({
|
53 | name: "FormCheckbox",
|
54 | compose: useCheckbox,
|
55 | keys: FORM_CHECKBOX_KEYS,
|
56 |
|
57 | useOptions(options, htmlProps) {
|
58 | const name = options.name || htmlProps.name;
|
59 | const value =
|
60 | typeof options.value !== "undefined" ? options.value : htmlProps.value;
|
61 | const state = unstable_getIn(options.values, name);
|
62 | const setState = (val: any) => options.update(name, val);
|
63 | return { ...options, state, setState, name, value };
|
64 | },
|
65 |
|
66 | useProps(options, { onBlur: htmlOnBlur, ...htmlProps }) {
|
67 | const onBlurRef = useLiveRef(htmlOnBlur);
|
68 | const isBoolean = typeof options.value === "undefined";
|
69 |
|
70 | const onBlur = React.useCallback(
|
71 | (event: React.FocusEvent) => {
|
72 | onBlurRef.current?.(event);
|
73 | if (event.defaultPrevented) return;
|
74 | options.blur?.(options.name);
|
75 | },
|
76 | [options.blur, options.name]
|
77 | );
|
78 |
|
79 | return {
|
80 | "aria-invalid": shouldShowError(options, options.name),
|
81 | name: formatInputName(options.name),
|
82 | onBlur,
|
83 | ...(isBoolean
|
84 | ? {
|
85 | id: getInputId(options.name, options.baseId),
|
86 | "aria-describedby": getMessageId(options.name, options.baseId),
|
87 | "aria-labelledby": getLabelId(options.name, options.baseId),
|
88 | }
|
89 | : {}),
|
90 | ...htmlProps,
|
91 | };
|
92 | },
|
93 | }) as <V, P extends DeepPath<V, P>>(
|
94 | options: unstable_FormCheckboxOptions<V, P>,
|
95 | htmlProps?: unstable_FormCheckboxHTMLProps
|
96 | ) => unstable_FormCheckboxHTMLProps;
|
97 |
|
98 | export const unstable_FormCheckbox = (createComponent({
|
99 | as: "input",
|
100 | memo: true,
|
101 | useHook: unstable_useFormCheckbox,
|
102 | }) as unknown) as <V, P extends DeepPath<V, P>, T extends As = "input">(
|
103 | props: PropsWithAs<unstable_FormCheckboxOptions<V, P>, T>
|
104 | ) => JSX.Element;
|