diff --git a/README.md b/README.md index 7a251d4..6b86b72 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,6 @@ Most UI libraries provide styled primitive `` components, form `` ## Contents -| Field | About | -| ------------------------------- | --------------------------------------- | -| [`textField()`](#textfield) | A fieldAtom to capture `string` values. | -| [`selectField()`](#selectfield) | A fieldAtom to capture enum values. | - | Hooks | About | | ------------------------------------------------------- | ----------------------------- | | [`useClearFileFieldEffect()`](#useclearfilefieldeffect) | A hook to control file input. | diff --git a/src/Intro.contents.md b/src/Intro.contents.md index db4a9cb..cae2f7d 100644 --- a/src/Intro.contents.md +++ b/src/Intro.contents.md @@ -7,6 +7,7 @@ | [fileField()](?path=/docs/fields-filefield--docs) | A field to hold a `FileList` value. | | [numberField()](?path=/docs/fields-numberfield--docs) | A field to hold a `number` type. | | [textField()](?path=/docs/fields-textfield--docs) | A field to hold a `string` type. | +| [selectField()](?path=/docs/fields-selectfield--docs) | A generic field to hold one of radio or select options. | ### Components diff --git a/src/fields/select-field/Docs.mdx b/src/fields/select-field/Docs.mdx new file mode 100644 index 0000000..1073099 --- /dev/null +++ b/src/fields/select-field/Docs.mdx @@ -0,0 +1,43 @@ +import { Meta, Markdown } from "@storybook/blocks"; + +import Config from "./config.md?raw"; + + + +# `selectField(): ValidatedFieldAtom` + +A generic choice field to hold a key of some options e.g. in `` or `` elements. +The `undefined` empty value means that no option is selected. + +```ts +import { selectField } from "@form-atoms/field"; + +// required string, must be filled to submit +const favoriteCategory = selectField(); + +// optional string, can be empty to submit +const companySize = selectField({ optional: true }); +``` + +## Initial Config + +{Config} + +## Examples + +### Number select + +By default the select field works with `string` values. You can specify your own type. For example to make a rating field with choices 1-5 +you will need a `numericSelectField`: + +```ts +import { selectField } from "@form-atoms/field"; +import { useFieldActions } from "form-atoms"; + +const rating = selectField({ schema: z.number() }); + +const actions = useFieldActions(rating); + +actions.setValue("4"); // ERR! +actions.setValue(4); // OK +``` diff --git a/src/fields/select-field/config.md b/src/fields/select-field/config.md new file mode 100644 index 0000000..f659895 --- /dev/null +++ b/src/fields/select-field/config.md @@ -0,0 +1,5 @@ +| Param | Value | +| ---------------- | ------------------- | +| `value` | `undefined` | +| `schema` | `z.string()` | +| `optionalSchema` | `schema.optional()` | diff --git a/src/fields/select-field/selectField.ts b/src/fields/select-field/selectField.ts index 08f6750..77663c0 100644 --- a/src/fields/select-field/selectField.ts +++ b/src/fields/select-field/selectField.ts @@ -5,18 +5,18 @@ import { ValidatedFieldAtomConfig, validatedFieldAtom, } from ".."; +import { ZodParams, defaultParams } from "../zodParams"; export type SelectFieldAtom = ValidatedFieldAtom< Value | undefined >; -// possibly validate option literals, or union of literals -// https://zod.dev/?id=unions -export const selectField = ( - config: Partial> = {} -) => +export const selectField = ({ + required_error = defaultParams.required_error, + ...config +}: Partial> & ZodParams = {}) => validatedFieldAtom({ value: undefined, - schema: z.string({ required_error: "This field is required" }), + schema: z.string({ required_error }), ...config, }); diff --git a/src/fields/text-field/useTextFieldProps.tsx b/src/fields/text-field/useTextFieldProps.tsx index 0694963..630f493 100644 --- a/src/fields/text-field/useTextFieldProps.tsx +++ b/src/fields/text-field/useTextFieldProps.tsx @@ -1,6 +1,6 @@ import { ChangeEvent } from "react"; -import { TextFieldAtom, TextValue } from "./textField"; +import { TextFieldAtom, TextFieldValue } from "./textField"; import { FieldProps, useFieldProps } from ".."; export type TextFieldProps = FieldProps; @@ -10,7 +10,7 @@ const getEventValue = ( ) => event.target.value; export const useTextFieldProps = (field: F) => - useFieldProps( + useFieldProps( field, getEventValue );