@letar/forms

Группы и массивы

Вложенные объекты и динамические массивы полей

Form.Group

Группировка полей во вложенные объекты:

const Schema = z.object({
  address: z.object({
    street: z.string().meta({ ui: { title: 'Улица' } }),
    city: z.string().meta({ ui: { title: 'Город' } }),
    zip: z.string().meta({ ui: { title: 'Индекс' } }),
  }),
})

<Form schema={Schema} initialValue={data} onSubmit={save}>
  <Form.Group name="address">
    <Form.Field.String name="street" />   {/* → address.street */}
    <Form.Field.String name="city" />     {/* → address.city */}
    <Form.Field.String name="zip" />      {/* → address.zip */}
  </Form.Group>
</Form>

List

API: Form.Group.List

Динамические массивы с добавлением/удалением/сортировкой:

const Schema = z.object({
  phones: z.array(z.object({
    number: z.string().meta({ ui: { title: 'Номер телефона' } }),
    type: z.enum(['mobile', 'home', 'work']).meta({ ui: { title: 'Тип' } }),
  })),
})

<Form schema={Schema} initialValue={{ phones: [{ number: '', type: 'mobile' }] }} onSubmit={save}>
  <Form.Group.List name="phones">
    <Form.Field.Phone name="number" />
    <Form.Field.Select name="type" />

    <Form.Group.List.Button.Remove />
    <Form.Group.List.Button.Add>Добавить телефон</Form.Group.List.Button.Add>
  </Form.Group.List>
</Form>

Сортируемые списки

Включите drag & drop перетаскивание с пропом sortable:

<Form.Group.List name="items" sortable>
  <Form.Field.String name="title" />
  <Form.Group.List.Button.Remove />
</Form.Group.List>

Требуются peer-зависимости: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities.

Вложенные группы

Группы можно вкладывать друг в друга:

<Form.Group name="company">
  <Form.Field.String name="name" />

  <Form.Group name="address">
    <Form.Field.String name="street" />
    <Form.Field.String name="city" />
  </Form.Group>
</Form.Group>
// Создаёт: company.name, company.address.street, company.address.city

On this page