# SchemaRepeater

> A Repeater whose rows are generated from a field schema (text, number, select, switch, date, nested repeater) with built-in validation in English and Arabic.

Source: https://docs.nasaqui.com/components/schema-repeater

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/schema-repeater.json
```

Describe a row as a list of fields and get a full add / remove / duplicate / reorder / collapse form, with
validation. The value is plain JSON, the same shape you validate on the server (`validateRows` is exported and
has no React dependency).

## When to use

- Line items, contacts, rules, hosts: rows of standard inputs.

## When not to use

- Rows with custom layout or components: use `Repeater`.

## Import

```tsx
import { SchemaRepeater, type SchemaField } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
const fields: SchemaField[] = [
  { key: "name", type: "text", label: "Name", required: true, width: "half" },
  { key: "qty", type: "number", label: "Quantity", min: 1, integer: true, width: "half" },
  { key: "kind", type: "select", label: "Kind", options: [{ value: "a", label: "A" }] },
];

<SchemaRepeater fields={fields} label="Items" titleKey="name" min={1} max={10} onValidate={(r) => setValid(r.valid)} />
```

## Field types

| type | value | notable options |
| --- | --- | --- |
| `text` | `string` | `inputType`, `multiline`, `ltr`, `minLength`, `maxLength`, `pattern`, `patternMessage` |
| `number` | `number \| null` | `min`, `max`, `step`, `integer`, `unit` |
| `select` | `string \| null` | `options`, `placeholder` |
| `switch` | `boolean` | |
| `date` | ISO `YYYY-MM-DD \| null` | `min`, `max` |
| `repeater` | `SchemaRow[]` | `fields`, `min`, `max`, `titleKey`, `addLabel` (nested, any depth) |

All fields accept `key`, `label`, `description`, `required`, `width` ("full" or "half"), `hidden(row)` and `validate(value, row)`.

## API

| Prop | Type | Description |
| --- | --- | --- |
| `fields` | `SchemaField[]` | The row schema. |
| `value`, `defaultValue`, `onValueChange` | `SchemaRow[]` | The rows. |
| `min`, `max`, `label`, `titleKey`, `rowTitle` | | Limits and row headings. |
| `showErrors` | `boolean` | Reveal every error (after a failed submit). Otherwise a field shows its error once edited. |
| `errors` | `RowErrors[]` | Server errors by row and field key. |
| `onValidate` | `(SchemaValidation) => void` | Called when the issue count or list message changes. |
| `messages`, `labels` | | Override validation messages and repeater strings. |
| `reorderable`, `duplicable`, `collapsible`, `defaultCollapsed`, `disabled`, `addLabel`, `empty` | | Passed to `Repeater`. |

## Accessibility

Errors render in `FieldError` tied to the input; the row header shows an issue count badge; the row-count message is `role="alert"`.

## RTL

Built-in messages have Arabic text. Email, URL, tel and `ltr` text inputs stay left-to-right.

## Code

### React

```tsx
const fields: SchemaField[] = [
  { key: "name", type: "text", label: "Name", required: true, width: "half" },
  { key: "qty", type: "number", label: "Quantity", min: 1, integer: true, width: "half" },
  { key: "kind", type: "select", label: "Kind", options: [{ value: "a", label: "A" }] },
];

<SchemaRepeater fields={fields} label="Items" titleKey="name" min={1} max={10} onValidate={(r) => setValid(r.valid)} />
```

### shadcn

```tsx
const fields: SchemaField[] = [
  { key: "name", type: "text", label: "Name", required: true, width: "half" },
  { key: "qty", type: "number", label: "Quantity", min: 1, integer: true, width: "half" },
  { key: "kind", type: "select", label: "Kind", options: [{ value: "a", label: "A" }] },
];

<SchemaRepeater fields={fields} label="Items" titleKey="name" min={1} max={10} onValidate={(r) => setValid(r.valid)} />
```

### Vue

```vue
<script setup lang="ts">
import { NqSchemaRepeater, type SchemaField, type SchemaRow } from "@fadymondy/nasaq/vue";
import { ref } from "vue";

const fields: SchemaField[] = [
  { key: "name", type: "text", label: "Name", required: true, maxLength: 40 },
  { key: "kind", type: "select", label: "Kind", options: [{ value: "phone", label: "Phone" }, { value: "email", label: "Email" }], width: "half" },
  { key: "qty", type: "number", label: "Quantity", integer: true, min: 1, max: 99, unit: "pcs", width: "half" },
  { key: "active", type: "switch", label: "Active" },
];
const rows = ref<SchemaRow[]>([{ name: "Sara", kind: "phone", qty: 2, active: true }]);
</script>

<template>
  <NqSchemaRepeater v-model="rows" :fields="fields" :min="1" :max="5" title-key="name" label="Contacts" class="w-[34rem]" />
</template>
```

### Blade

```blade
@php
    $fields = [
        ['key' => 'name', 'type' => 'text', 'label' => 'Name', 'required' => true, 'maxLength' => 40],
        ['key' => 'kind', 'type' => 'select', 'label' => 'Kind', 'options' => [['value' => 'phone', 'label' => 'Phone'], ['value' => 'email', 'label' => 'Email']], 'width' => 'half'],
        ['key' => 'qty', 'type' => 'number', 'label' => 'Quantity', 'integer' => true, 'min' => 1, 'max' => 99, 'unit' => 'pcs', 'width' => 'half'],
        ['key' => 'active', 'type' => 'switch', 'label' => 'Active'],
    ];
@endphp
<x-nq::schema-repeater :fields="$fields" :rows="[['name' => 'Sara', 'kind' => 'phone', 'qty' => 2, 'active' => true]]" :min="1" :max="5" title-key="name" label="Contacts" class="w-[34rem]" />
```

### HTML + Alpine

```html
<div data-slot="schema-repeater" x-data="nqSchemaRepeater(JSON.parse('{\u0022fields\u0022:[{\u0022key\u0022:\u0022name\u0022,\u0022type\u0022:\u0022text\u0022,\u0022label\u0022:\u0022Name\u0022,\u0022required\u0022:true,\u0022maxLength\u0022:40},{\u0022key\u0022:\u0022kind\u0022,\u0022type\u0022:\u0022select\u0022,\u0022label\u0022:\u0022Kind\u0022,\u0022options\u0022:[{\u0022value\u0022:\u0022phone\u0022,\u0022label\u0022:\u0022Phone\u0022},{\u0022value\u0022:\u0022email\u0022,\u0022label\u0022:\u0022Email\u0022}],\u0022width\u0022:\u0022half\u0022},{\u0022key\u0022:\u0022qty\u0022,\u0022type\u0022:\u0022number\u0022,\u0022label\u0022:\u0022Quantity\u0022,\u0022integer\u0022:true,\u0022min\u0022:1,\u0022max\u0022:99,\u0022unit\u0022:\u0022pcs\u0022,\u0022width\u0022:\u0022half\u0022},{\u0022key\u0022:\u0022active\u0022,\u0022type\u0022:\u0022switch\u0022,\u0022label\u0022:\u0022Active\u0022}],\u0022rows\u0022:[{\u0022name\u0022:\u0022Sara\u0022,\u0022kind\u0022:\u0022phone\u0022,\u0022qty\u0022:2,\u0022active\u0022:true}],\u0022min\u0022:1,\u0022max\u0022:5,\u0022label\u0022:\u0022Contacts\u0022,\u0022titleKey\u0022:\u0022name\u0022}'))" x-modelable="rows" x-on:change="onRowsChange($event)"
    class="flex flex-col gap-2 w-[34rem]">
    <div data-slot="repeater" x-data="nqRepeater([], Object.assign(JSON.parse('{\u0022min\u0022:1,\u0022max\u0022:5}'), { createItem: () => (newRow()), rowTitle: (item, index) => (rowTitle(item)), rowSummary: (item, index) => (rowSummary(item)) }))" x-modelable="items" x-id="['nq-repeater-body']"     x-model="rows" class="flex min-w-0 flex-col gap-3">
            <div x-show="count() > 1" x-cloak style="display: none" class="flex items-center justify-between gap-2">
            <span data-slot="repeater-count" class="text-caption tabular-nums text-muted-foreground" x-text="countText()"></span>
            <button data-slot="button"
     type="button"                         x-on:click="toggleAll()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <span x-show="!allCollapsed()" aria-hidden="true" class="flex [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 20 5-5 5 5"/>
  <path d="m7 4 5 5 5-5"/>
</svg></span>
                <span x-show="allCollapsed()" x-cloak style="display: none" aria-hidden="true" class="flex [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
                <span x-text="allCollapsed() ? $nq.t('Expand all', 'توسيع الكل') : $nq.t('Collapse all', 'طيّ الكل')"></span></button>
        </div>
                <p :id="hintId()" class="sr-only">Focus the handle, then use the arrow keys to move the row. Home and End jump to the ends.</p>
    <div x-show="count() === 0" x-cloak style="display: none" data-slot="repeater-empty"
        class="rounded-card border border-dashed border-border px-4 py-6 text-center text-body-sm text-muted-foreground">
        No items yet.    </div>
    <ol x-show="count() > 0" x-cloak style="display: none" aria-label="Contacts" class="flex flex-col gap-2">
        <template x-for="(item, index) in items" :key="keyOf(index)">
            <li data-slot="repeater-row" :data-row-key="keyOf(index)" :data-collapsed="isCollapsed(index) ? 'true' : undefined" :data-dragging="isDragging(index) ? 'true' : undefined" :style="rowStyle(index)"
                class="relative rounded-card border border-border bg-card data-dragging:z-10 data-dragging:border-nq-focus data-dragging:shadow-floating">
                <div data-slot="repeater-row-header" class="flex min-h-control items-center gap-1 p-1.5">
                                            <button type="button" x-show="count() > 1" data-repeater-focus :aria-label="$nq.t('Reorder ' + name(index), 'إعادة ترتيب ' + name(index))" :title="$nq.t('Reorder ' + name(index), 'إعادة ترتيب ' + name(index))"
                            :aria-describedby="hintId()" aria-keyshortcuts="ArrowUp ArrowDown Home End" :disabled="disabled"
                            x-on:keydown="onHandleKey($event, index)" x-on:pointerdown="startDrag($event, index)"
                            class="inline-flex size-control-sm shrink-0 cursor-grab touch-none items-center justify-center rounded-control text-muted-foreground outline-none hover:bg-nq-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-nq-focus active:cursor-grabbing disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:size-4">
                            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="9" cy="12" r="1"/>
  <circle cx="9" cy="5" r="1"/>
  <circle cx="9" cy="19" r="1"/>
  <circle cx="15" cy="12" r="1"/>
  <circle cx="15" cy="5" r="1"/>
  <circle cx="15" cy="19" r="1"/>
</svg>                        </button>
                                                                <button type="button"  :aria-expanded="isCollapsed(index) ? 'false' : 'true'" :aria-controls="$id('nq-repeater-body', index)"
                            :aria-label="isCollapsed(index) ? $nq.t('Expand ' + name(index), 'توسيع ' + name(index)) : $nq.t('Collapse ' + name(index), 'طيّ ' + name(index))"
                            x-on:click="toggle(index)"
                            class="flex min-h-control-sm min-w-0 flex-1 items-center gap-2 rounded-control px-1.5 text-start outline-none hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-nq-focus">
                            <span aria-hidden="true" :class="isCollapsed(index) ? '' : 'rotate-90 rtl:-rotate-90'" class="flex size-4 shrink-0 text-muted-foreground transition-[rotate] duration-200 ease-nq rtl:-scale-x-100 [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m9 18 6-6-6-6"/>
</svg></span>
                            <span class="min-w-0 truncate text-label text-foreground" x-text="title(index)"></span>
                            <span x-show="isCollapsed(index) && summary(index)" class="min-w-0 flex-1 truncate text-body-sm text-muted-foreground" x-text="summary(index)"></span>
                        </button>
                                        <span class="sr-only" x-text="n(index + 1)"></span>
                                            <button data-slot="button"
     type="button"                         :aria-label="$nq.t(&#039;Duplicate &#039; + name(index), &#039;تكرار &#039; + name(index))" :title="$nq.t(&#039;Duplicate &#039; + name(index), &#039;تكرار &#039; + name(index))" :disabled="disabled || atMax()" x-on:click="duplicate(index)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect width="14" height="14" x="8" y="8" rx="2" ry="2"/>
  <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>
</svg></button>
                                        <button data-slot="button"
     type="button"                         :aria-label="$nq.t(&#039;Remove &#039; + name(index), &#039;حذف &#039; + name(index))" :title="$nq.t(&#039;Remove &#039; + name(index), &#039;حذف &#039; + name(index))" :disabled="disabled || atMin()" x-on:click="remove(index)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-nq-hover size-control-sm p-0 text-muted-foreground hover:text-nq-danger-text">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10 11v6"/>
  <path d="M14 11v6"/>
  <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
  <path d="M3 6h18"/>
  <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
</svg></button>
                </div>
                <div :id="$id('nq-repeater-body', index)" data-slot="repeater-body" x-show="!isCollapsed(index)" class="border-t border-border p-3 sm:p-4"><div x-show="issueCount(item, ``, index) > 0" style="display: none" class="mb-3">
    <span data-slot="schema-repeater-issues"     x-text="issuesText(issueCount(item, ``, index))" class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-nq-danger/40 bg-nq-danger-soft text-nq-danger-text"></span>
</div>
<div class="grid grid-cols-1 gap-x-4 gap-y-4 sm:grid-cols-2">
                    <div  class="min-w-0 sm:col-span-2">
                            <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Name<span aria-hidden="true" class="ms-0.5 text-nq-danger-text">*</span></label>
                                                                    <input data-slot="input" type="text"
                    x-model="item[`name`]" x-on:input="touch(item, `name`)" x-on:blur="touch(item, `name`)" x-bind:aria-invalid="msg(item, `0`, index) ? &#039;true&#039; : null" x-bind:data-invalid="msg(item, `0`, index) ? &#039;&#039; : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control">
                                                            <div data-slot="field-error" role="alert" x-show="msg(item, `0`, index)" x-text="msg(item, `0`, index)" style="display: none" class="text-caption text-nq-danger-text"></div>
</div>
                    </div>
                    <div  class="min-w-0 ">
                            <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Kind</label>
                                            <div data-slot="select" x-data="nqSelect(null, false)" x-modelable="value" x-id="['nq-select']" x-model="item[`kind`]" x-init="$watch(&#039;value&#039;, () =&gt; touch(item, `kind`))" class="contents">
    <button data-slot="select-trigger" x-ref="trigger" x-bind="trigger"
        x-bind:data-invalid="msg(item, `1`, index) ? &#039;&#039; : null" x-bind:aria-invalid="msg(item, `1`, index) ? &#039;true&#039; : null" class="flex h-control w-full min-w-0 items-center justify-between gap-2 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px]">
    <span data-slot="select-value" x-text="label() ?? 'Select\u2026'" :data-placeholder="empty() ? '' : undefined"
    class="min-w-0 flex-1 truncate text-start data-placeholder:text-muted-foreground"></span>
    <span class="flex shrink-0 text-muted-foreground [&_svg]:size-4"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg></span>
</button>
                            <template x-teleport="body">
    <div data-slot="select-content" x-ref="popup" x-bind="popup" x-nq-presence="open" x-anchor.bottom-start.offset.4="$refs.trigger"
        class="z-50 min-w-[var(--anchor-width)] max-h-[var(--available-height)] overflow-y-auto rounded-floating border border-border bg-popover p-1.5 text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0">
        <div data-slot="select-item" x-bind="item('phone', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('phone')" x-cloak class="contents"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Phone</span>
</div>
                                                                    <div data-slot="select-item" x-bind="item('email', false)"
    class="relative flex h-nav-row min-h-[var(--nq-touch-min,0px)] cursor-default select-none items-center gap-2.5 rounded-control ps-8 pe-2.5 text-body-sm text-foreground outline-none data-highlighted:bg-nq-selected data-disabled:pointer-events-none data-disabled:opacity-50">
    <span aria-hidden="true" class="absolute start-2.5 inline-flex size-4 items-center justify-center">
        <span x-show="isSelected('email')" x-cloak class="contents"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></span>
    </span>
    <span data-slot="select-item-text" class="min-w-0 flex-1 truncate">Email</span>
</div>
    </div>
</template>
    </div>
                                                            <div data-slot="field-error" role="alert" x-show="msg(item, `1`, index)" x-text="msg(item, `1`, index)" style="display: none" class="text-caption text-nq-danger-text"></div>
</div>
                    </div>
                    <div  class="min-w-0 ">
                            <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Quantity</label>
                                            <div class="relative">
                            <input data-slot="input" type="number"
     dir="ltr"                 inputmode="numeric" min="1" max="99" step="1" x-bind:value="item[`qty`] ?? &#039;&#039;" x-on:input="setNumber(item, `qty`, $event.target.value)" x-on:blur="touch(item, `qty`)" x-bind:aria-invalid="msg(item, `2`, index) ? &#039;true&#039; : null" x-bind:data-invalid="msg(item, `2`, index) ? &#039;&#039; : null" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control text-start pe-12">
                            <span class="pointer-events-none absolute inset-y-0 end-3 flex items-center text-body-sm text-muted-foreground">pcs</span>                        </div>
                                                            <div data-slot="field-error" role="alert" x-show="msg(item, `2`, index)" x-text="msg(item, `2`, index)" style="display: none" class="text-caption text-nq-danger-text"></div>
</div>
                    </div>
                    <div  class="min-w-0 sm:col-span-2">
                            <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-row items-start justify-between gap-4 rounded-control border border-border px-3 py-2.5">
    <div class="flex min-w-0 flex-col gap-0.5">
                        <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Active</label>
                                                <div data-slot="field-error" role="alert" x-show="msg(item, `3`, index)" x-text="msg(item, `3`, index)" style="display: none" class="text-caption text-nq-danger-text"></div>
                    </div>
                    <span class="contents" x-on:click="touch(item, `active`)">
                        <button type="button" role="switch" data-slot="switch" x-data="nqSwitch(false)" x-modelable="checked" x-bind="root"
    aria-checked="false"
     data-unchecked                 x-model="item[`active`]" aria-label="Active" class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent bg-nq-line-strong p-0.5 outline-none transition-colors duration-150 ease-nq data-checked:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50">
    <span data-slot="switch-thumb"  data-unchecked         x-bind:data-checked="checked ? '' : undefined" x-bind:data-unchecked="checked ? undefined : ''"
        class="block size-4 rounded-full bg-background shadow-xs data-checked:bg-primary-foreground transition-[translate] duration-150 ease-nq data-checked:translate-x-3.5 rtl:data-checked:-translate-x-3.5"></span>
    </button>
                    </span>
</div>
                    </div>
    </div></div>
            </li>
        </template>
    </ol>
    <div class="flex flex-wrap items-center gap-3">
        <button data-slot="button"
     type="button"                         data-repeater-add="data-repeater-add" :disabled="disabled || atMax()" :aria-describedby="limitText() ? limitId() : undefined" x-on:click="add()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="M12 5v14"/>
</svg>            Add item</button>
        <span x-show="limitText()" x-cloak style="display: none" :id="limitId()" class="text-caption text-muted-foreground" x-text="limitText()"></span>
    </div>
    <div aria-live="polite" role="status" class="sr-only" x-text="announcement"></div>
</div>
    <p role="alert" data-slot="schema-repeater-error" x-show="countMessage()" x-text="countMessage()" style="display: none" class="text-caption text-nq-danger-text"></p>
</div>
```
