UNPKG

@payfit/unity-components

Version:

93 lines (92 loc) 4.07 kB
import { StandardSchemaV1 } from '@standard-schema/spec'; import { ForwardedRef, ReactNode } from 'react'; import { FieldPath, FieldValues } from 'react-hook-form'; import { Schema } from '../../hooks/use-form.types.js'; import { LabelProps } from '../label/Label.js'; import { MultiSelectProps } from '../multi-select/MultiselectTypes.js'; interface FieldProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> extends Pick<LabelProps, 'isRequired' | 'requiredVariant'> { /** The name of the field, which should match the form schema. */ name: TName; /** The label for the multi-select field. */ label: string; /** Helper text to display below the multi-select field. */ helperText?: ReactNode; /** Feedback text to display below the multi-select field. */ feedbackText?: ReactNode; /** A contextual link to display below the multi-select field. */ contextualLink?: ReactNode; } type BaseMultiSelectProps<TItems = undefined> = Omit<MultiSelectProps<TItems>, 'value' | 'defaultValue' | 'onChange' | 'aria-labelledby' | 'aria-label'>; export type MultiSelectFieldProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TItems = undefined> = FieldProps<TFieldValues, TName> & BaseMultiSelectProps<TItems>; /** * The `MultiSelectField` component renders a full field that allows selecting multiple items from a dropdown list, and integrates with the `Form` component automatically. * * The component uses a single generic parameter `TItems` that infers the item type from the `items` prop * for the dynamic API, or defaults to `undefined` for the static API (using `children` directly). * @example Static API * ```tsx * const schema = z.object({ * fruits: z.set(z.string()), * }) * * function MyForm() { * const { Form } = useUnityForm(schema) * * return ( * <Form action={handleSubmit}> * <MultiSelectField<typeof schema> * name="fruits" * label="Select fruits" * > * <MultiSelectOption value="apple">Apple</MultiSelectOption> * <MultiSelectOption value="banana">Banana</MultiSelectOption> * <MultiSelectOption value="orange">Orange</MultiSelectOption> * </MultiSelectField> * </Form> * ) * } * ``` * @example Dynamic API * ```tsx * interface Fruit { id: string; name: string } * const fruits = new Set<Fruit>([...]) * * const schema = z.object({ * fruits: z.set(z.string()), * }) * * function MyForm() { * const { Form } = useUnityForm(schema) * * return ( * <Form action={handleSubmit}> * <MultiSelectField<typeof schema, Set<Fruit>> * name="fruits" * label="Select fruits" * items={fruits} * getItemValue={fruit => fruit.id} * > * {fruit => ( * <MultiSelectOption value={fruit.id}>{fruit.name}</MultiSelectOption> * )} * </MultiSelectField> * </Form> * ) * } * ``` * @note The schema type parameter is needed to ensure type safety with the form's schema. If you omit it, the `name` prop will not be type-safe. * @remarks * [API & Docs](https://unity-components.payfit.io/?path=/docs/forms-multiselectfield--docs) • [Design Guidelines](https://www.payfit.design/24f360409/p/928776-multiselect) * @deprecated React Hook Form components are deprecated. Use the TanStack Form version instead. * @see Storybook docs: https://unity-components.payfit.io/?path=/docs/forms-introduction-to-unity-forms--docs */ /** * Component type for MultiSelectField with proper generic support */ type MultiSelectFieldComponent = <TSchema extends Schema = Schema, TItems = undefined>(props: MultiSelectFieldProps<StandardSchemaV1.InferOutput<TSchema>, FieldPath<StandardSchemaV1.InferOutput<TSchema>>, TItems> & { ref?: ForwardedRef<HTMLButtonElement>; }) => React.JSX.Element; export declare const MultiSelectField: MultiSelectFieldComponent & { displayName: string; }; export {};