--- url: https://tacxou.github.io/jsonforms_builder/en/guide/ai.md --- # AI agents How coding assistants (Cursor, Claude, and similar) can consume `@tacxou/jsonforms_builder` documentation. ## `llms.txt` files On docs build, VitePress emits machine-readable indexes (**English** docs only): | File | Role | |---|---| | [llms.txt](https://tacxou.github.io/jsonforms_builder/llms.txt) | Short index: sections + links to Markdown pages | | [llms-full.txt](https://tacxou.github.io/jsonforms_builder/llms-full.txt) | Full Markdown bundle | Each guide page also has a `.md` variant (e.g. `/en/guide/installation.md`) for targeted fetches. ## MCP server The [`@tacxou/jsonforms_builder-mcp`](https://www.npmjs.com/package/@tacxou/jsonforms_builder-mcp) package exposes the docs over the [Model Context Protocol](https://modelcontextprotocol.io/) (**stdio** transport). ### Tools | Tool | Role | |---|---| | `list_doc_sources` | Reads the `llms.txt` index | | `search_docs` | Finds relevant pages in the index / full bundle | | `fetch_docs` | Fetches a docs URL (whitelisted host) | ### Cursor In `~/.cursor/mcp.json` (or project MCP config): ```json { "mcpServers": { "jsonforms-builder": { "command": "npx", "args": ["-y", "@tacxou/jsonforms_builder-mcp"] } } } ``` ### Claude Desktop In `claude_desktop_config.json`: ```json { "mcpServers": { "jsonforms-builder": { "command": "npx", "args": ["-y", "@tacxou/jsonforms_builder-mcp"] } } } ``` ### Claude Code ```bash claude mcp add-json jsonforms-builder '{"type":"stdio","command":"npx","args":["-y","@tacxou/jsonforms_builder-mcp"]}' -s local ``` ### Environment variable | Variable | Default | Role | |---|---|---| | `DOCS_BASE_URL` | `https://tacxou.github.io/jsonforms_builder` | Docs origin (no trailing slash). Point at a local `docs:preview` when needed. | Local example: ```json { "mcpServers": { "jsonforms-builder": { "command": "npx", "args": ["-y", "@tacxou/jsonforms_builder-mcp"], "env": { "DOCS_BASE_URL": "http://127.0.0.1:4173" } } } } ``` > Locally, the host must stay on the MCP whitelist (`tacxou.github.io`, `127.0.0.1`, `localhost`). ## Suggested agent rule Add to User Rules / project rules: ```text For any question about @tacxou/jsonforms_builder (Nuxt UI renderers, uischema options, FormBuilder, Tailwind/Vite integration): 1. call list_doc_sources 2. call search_docs with the question 3. call fetch_docs on relevant URLs 4. answer from that context (do not invent options) ``` --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/array.md --- # Arrays & objects *** ## Tags — `UInputTags` **Trigger:** schema `type: "array"` of `string` items + `options.format: "tags"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"tags"` | — | **Required**. | | `delimiter` | `String` | `","` | Separator on input (pasting a list). | | `placeholder` | `String` | — | Placeholder. | | `inputTags` | `Object` | — | Pass-through → `UInputTags`. | The `uniqueItems`, `maxItems` and `items.maxLength` constraints come from the **schema**. ### Example ```json { "type": "array", "title": "Emails", "uniqueItems": true, "maxItems": 10, "items": { "type": "string", "format": "email" } } ``` ```json { "type": "Control", "scope": "#/properties/emails", "options": { "format": "tags", "delimiter": ";", "placeholder": "name@example.com ;" } } ``` *** ## Array — repeatable cards **Trigger:** schema `type: "array"` of objects (other than tags / multi-enum / file). ### API | Name | Type | Default | Description | |---|---|---|---| | `showSortButtons` | `Boolean` | — | Shows the move up / move down buttons. | | `elementLabelProp` | `String` | — | Path (possibly deep) to the property used as each item’s title. | | `detail` | `UISchemaElement` | — | UISchema template rendered for each element. | ### Examples ```json { "type": "Control", "scope": "#/properties/employees", "options": { "showSortButtons": true, "elementLabelProp": "name" } } ``` With a detailed UISchema: ```json { "type": "Control", "scope": "#/properties/addresses", "options": { "showSortButtons": true, "elementLabelProp": "city", "detail": { "type": "HorizontalLayout", "elements": [ { "type": "Control", "scope": "#/properties/street" }, { "type": "Control", "scope": "#/properties/city" } ] } } } ``` *** ## List with detail Same set of options as Array (`showSortButtons`, `elementLabelProp`, `detail`) when the UISchema uses the JSON Forms list-with-detail layout. *** ## Object / allOf ### API | Name | Type | Default | Description | |---|---|---|---| | `detail` | `UISchemaElement` | — | Custom child UISchema instead of the automatic generation. | ### Example ```json { "type": "Control", "scope": "#/properties/address", "options": { "detail": { "type": "VerticalLayout", "elements": [ { "type": "Control", "scope": "#/properties/line1" }, { "type": "Control", "scope": "#/properties/zip" } ] } } } ``` *** ## oneOf / anyOf Variant selector + sub-form. No dedicated domain options beyond the [common options](./common) and the `select` / `selectMenu` pass-through on the selector. ### Minimal example ```json { "oneOf": [ { "type": "object", "properties": { "kind": { "const": "person", "title": "Person" }, "name": { "type": "string" } } }, { "type": "object", "properties": { "kind": { "const": "company", "title": "Company" }, "siret": { "type": "string" } } } ] } ``` ## Playground * [Tags](/en/playground#/?section=docs\&example=nuxt-tags) * [Array](/en/playground#/?section=docs\&example=nuxt-array) --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/boolean.md --- # Boolean **Trigger:** schema `type: "boolean"`.\ Default component: `UCheckbox`. With `toggle`: `USwitch`. ## API | Name | Type | Default | Description | |---|---|---|---| | `toggle` | `Boolean` | — | When `true`, renders a `USwitch` instead of the `UCheckbox`. | | `checkbox` | `Object` | — | Pass-through → `UCheckbox` (ignored when `toggle` is set). | | `switch` | `Object` | — | Pass-through → `USwitch` (when `toggle` is set). | ## Examples ### Checkbox ```json { "type": "boolean", "title": "I accept the terms" } ``` ```json { "type": "Control", "scope": "#/properties/terms", "options": { "checkbox": { "color": "primary" } } } ``` ### Switch ```json { "type": "Control", "scope": "#/properties/notifications", "options": { "toggle": true, "switch": { "size": "lg", "color": "success" } } } ``` ## Playground → [Boolean](/en/playground#/?section=docs\&example=nuxt-boolean) --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/common.md --- # Common options Applied to most controls (label, description, read-only, errors). ## API | Name | Type | Default | Description | |---|---|---|---| | `placeholder` | `String` | — | Field placeholder (where the Nuxt UI component supports it). | | `focus` | `Boolean` | — | Autofocus on mount. | | `readonly` | `Boolean` | — | Read-only field. Also enabled when the schema has `readOnly: true` or `config.readonly` is truthy. | | `hideRequiredAsterisk` | `Boolean` | — | Hides the asterisk on required fields. | | `showUnfocusedDescription` | `Boolean` | — | Shows the schema description even when the field is not focused. | | `hideDescription` | `Boolean` | — | Removes the description entirely. | | `clearOnHide` | `Boolean` | `true` | When a `HIDE` rule applies, resets the value to `default` / `undefined`. Set to `false` to keep the value. | | `enableFilterErrorsBeforeTouch` | `Boolean` | — | Hides validation errors until the field has been touched. | | `clearable` | `Boolean` | — | “Clear” behaviour (notably rating: click again to empty). | | `leadingIcon` | `String` | — | Nuxt Icon shown before the control (e.g. `i-lucide-mail`). | | `trailingIcon` | `String` | — | Nuxt Icon shown after the control (e.g. `i-lucide-check`). | | `iconPlacement` | `'outside' \| 'inside'` | `'outside'` | `outside`: next to the widget. `inside`: within the Nuxt UI chrome (`UInput`, `USelect`, …). | | `styles` | `Partial` | — | Local override of the theme’s Tailwind classes (see [Customization](/en/guide/customization)). | | `formField` | `Object` | — | Pass-through props to `UFormField` (see [Pass-through](./pass-through)). | In `inside` mode, pass-through still wins (`options.input.leadingIcon`, …). Controls without icon chrome (checkbox, slider, number, …) ignore `inside` — use `outside` for those. ## Examples ### Always-visible description, no asterisk ```json { "type": "Control", "scope": "#/properties/bio", "options": { "showUnfocusedDescription": true, "hideRequiredAsterisk": true, "placeholder": "A few words…" } } ``` ### Read-only ```json { "type": "Control", "scope": "#/properties/id", "options": { "readonly": true } } ``` ### Keep the value when the control is hidden ```json { "type": "Control", "scope": "#/properties/secret", "rule": { "effect": "HIDE", "condition": { "scope": "#/properties/reveal", "schema": { "const": false } } }, "options": { "clearOnHide": false } } ``` ### Autofocus ```json { "type": "Control", "scope": "#/properties/email", "options": { "focus": true, "placeholder": "you@example.com" } } ``` ### Leading / trailing icons Next to the widget (`outside`, default): ```json { "type": "Control", "scope": "#/properties/email", "options": { "leadingIcon": "i-lucide-mail", "trailingIcon": "i-lucide-check", "placeholder": "you@example.com" } } ``` Inside the Nuxt UI field (`inside`): ```json { "type": "Control", "scope": "#/properties/email", "options": { "leadingIcon": "i-lucide-mail", "trailingIcon": "i-lucide-check", "iconPlacement": "inside", "placeholder": "you@example.com" } } ``` See also the **Leading / Trailing Icons** example (`prepend-append-slots`) in the [playground](/en/playground). --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/customization.md --- # Customization Two levels, from the broadest to the most specific: ```ts // 1. Global theme, injected once for the whole tree. provide('styles', { control: { input: 'font-mono' } }) ``` ```json // 2. Per element, through the uischema options — the key targets the Nuxt UI component. { "type": "Control", "scope": "#/properties/name", "options": { "input": { "size": "lg", "ui": { "base": "tracking-wide" } } } } ``` ## Options reference Every option is documented in tables (Name / Type / Default / Description) with JSON examples: * [Common options](/en/guide/options/common) * [Text & media](/en/guide/options/string) * [Numbers](/en/guide/options/number) * [Boolean](/en/guide/options/boolean) * [Enums](/en/guide/options/enum) * [Dates](/en/guide/options/date) * [Arrays & objects](/en/guide/options/array) * [Layouts](/en/guide/options/layouts) * [Nuxt UI pass-through](/en/guide/options/pass-through) The **Control Options** playground showcase (Documentation tab) shows some of these options side by side. --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/date.md --- # Dates & calendar Segmented controls (`UInputDate` / `UInputTime`) or an inline calendar (`UCalendar`). *** ## Date / Date-time / Time — segmented fields **Trigger:** * schema `format: "date"` | `"date-time"` | `"time"`, **or** * `options.format: "date"` | `"time"` | `"date-time"` ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"date"` | `"time"` | `"date-time"` | (schema) | Control type when the schema has no `format`. | | `pattern` | `String` | per format | dayjs storage / display format (`YYYY-MM-DD`, `HH:mm`, `YYYY.MM`, `YYYY`, …). | | `locale` | `String` | `"fr-FR"` | Locale of the popover calendar. | | `months` | `Number` | — | Number of months shown in the popover. | | `weekNumbers` | `Boolean` | — | Shows week numbers. | | `minDate` | `String` | — | Inclusive lower bound (`YYYY-MM-DD`, `YYYY-MM` or `YYYY`). | | `maxDate` | `String` | — | Inclusive upper bound. | | `disabledDates` | `String[]` | — | Excluded days (`YYYY-MM-DD`). | | `disabledWeekdays` | `Number[]` | — | Excluded weekdays (`0` = Sunday … `6` = Saturday). | | `disabledMonths` | `Number[]` | — | Excluded months (`1`–`12`). | | `disabledYears` | `Number[]` | — | Excluded years. | | `inputDate` | `Object` | — | Pass-through → `UInputDate`. | | `inputTime` | `Object` | — | Pass-through → `UInputTime`. | | `calendar` | `Object` | — | Pass-through → the popover calendar. | | `calendarCard` | `Object` | — | Pass-through to the calendar card. | | `timeCard` / `timeHour` / `timeMinute` / `timeSecond` | `Object` | — | Pass-through to the time parts. | ### Examples ```json { "type": "string", "format": "date", "title": "Start date" } ``` ```json { "type": "Control", "scope": "#/properties/startDate", "options": { "pattern": "YYYY-MM-DD", "locale": "en-US", "minDate": "2026-01-01", "maxDate": "2026-12-31", "disabledWeekdays": [0, 6] } } ``` Month / year precision: ```json { "type": "Control", "scope": "#/properties/period", "options": { "format": "date", "pattern": "YYYY-MM" } } ``` Time only: ```json { "type": "Control", "scope": "#/properties/opening", "options": { "format": "time", "pattern": "HH:mm" } } ``` *** ## Calendar — inline `UCalendar` **Trigger:** `options.format: "calendar"`. ### API All the date constraints above (`minDate`, `disabledDates`, …) **plus**: | Name | Type | Default | Description | |---|---|---|---| | `format` | `"calendar"` | — | **Required**. | | `range` | `Boolean` | — | `{ start, end }` range selection (an object schema is recommended). | | `months` | `Number` | `2` when `range` | Number of months side by side. | | `calendar` | `Object` | — | Pass-through → `UCalendar`. | ### Examples Simple calendar: ```json { "type": "Control", "scope": "#/properties/day", "options": { "format": "calendar", "weekNumbers": true } } ``` Range with constraints: ```json { "type": "object", "properties": { "start": { "type": "string", "format": "date" }, "end": { "type": "string", "format": "date" } } } ``` ```json { "type": "Control", "scope": "#/properties/stay", "options": { "format": "calendar", "range": true, "months": 2, "minDate": "2026-08-01", "maxDate": "2026-09-30", "disabledWeekdays": [0, 6], "disabledDates": ["2026-08-15"] } } ``` ## Playground * [Date & Time](/en/playground#/?section=docs\&example=nuxt-dates) * [Calendar](/en/playground#/?section=docs\&example=nuxt-calendar) * [Date ranges & constraints](/en/playground#/?section=docs\&example=nuxt-date-ranges) --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/enum.md --- # Enums *** ## Select menu (default) — `USelectMenu` **Trigger:** schema `enum` or `oneOf` const/title, with no special `format`. ### API | Name | Type | Default | Description | |---|---|---|---| | `suggestion` | `Array` | — | Free-form suggestions (also usable outside a strict enum). | | `placeholder` | `String` | — | Placeholder. | | `selectMenu` | `Object` | — | Pass-through → `USelectMenu` (search, size, …). | ### Example ```json { "type": "string", "title": "Country", "enum": ["FR", "BE", "CH"] } ``` ```json { "type": "Control", "scope": "#/properties/country", "options": { "placeholder": "Choose…", "selectMenu": { "size": "md" } } } ``` *** ## Select (no search) — `USelect` **Trigger:** `options.format: "select"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"select"` | — | **Required**. | | `select` | `Object` | — | Pass-through → `USelect`. | ### Example ```json { "type": "Control", "scope": "#/properties/tier", "options": { "format": "select", "placeholder": "Plan", "select": { "size": "sm" } } } ``` *** ## Radio — `URadioGroup` **Trigger:** `options.format: "radio"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"radio"` | — | **Required**. | | `vertical` | `Boolean` | `true` (effective) | `false` → horizontal orientation. | | `orientation` | `"horizontal"` | `"vertical"` | — | Takes precedence over `vertical` when set. | | `radioGroup` | `Object` | — | Pass-through → `URadioGroup` (`variant`, `size`, `color`, `orientation`, …). | **Orientation precedence:** `radioGroup.orientation` > `orientation` > `vertical: false` > vertical. ### Examples ```json { "type": "Control", "scope": "#/properties/size", "options": { "format": "radio", "vertical": false } } ``` ```json { "type": "Control", "scope": "#/properties/plan", "options": { "format": "radio", "orientation": "horizontal", "radioGroup": { "variant": "list", "size": "md", "color": "primary" } } } ``` *** ## Multi-enum — `UCheckboxGroup` **Trigger:** schema `type: "array"` with `items.enum` or `items.oneOf`. ### API | Name | Type | Default | Description | |---|---|---|---| | `vertical` | `Boolean` | — | `false` → horizontal layout. | | `checkboxGroup` | `Object` | — | Pass-through → `UCheckboxGroup`. | ### Example ```json { "type": "array", "title": "Skills", "uniqueItems": true, "items": { "type": "string", "enum": ["vue", "typescript", "css"] } } ``` ```json { "type": "Control", "scope": "#/properties/skills", "options": { "vertical": false, "checkboxGroup": { "size": "sm" } } } ``` ## Playground * [Select](/en/playground#/?section=docs\&example=nuxt-select) * [Radio & Multi-enum](/en/playground#/?section=docs\&example=nuxt-radio) --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/installation.md --- # Installation ```bash yarn add @tacxou/jsonforms_builder @jsonforms/core @jsonforms/vue @nuxt/ui ``` `@nuxt/ui`, `@jsonforms/core`, `@jsonforms/vue` and `vue` are **peerDependencies**: the library bundles no Nuxt UI component of its own; it imports them from the host application’s installation. ## Requirements * Node.js ≥ 22 * Vue 3.5+ * Tailwind CSS 4 (through `@nuxt/ui`) ## Versions | Package | Stack | |---|---| | `@tacxou/jsonforms_builder@2.x` | Nuxt UI 4 + Tailwind 4 | | `@tacxou/jsonforms_builder@1.x` | Quasar (`v1-quasar` branch) | > **v2 — stack change.** v1 was built on Quasar. v2 renders with the Nuxt UI `U*` components and therefore inherits the host app’s theme automatically. --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/integration.md --- # Integration ## Declare the library to Tailwind (required) Tailwind 4 generates utilities by scanning the project sources and **ignores anything outside its root** — including `node_modules`. Without the line below, the classes used by the renderers show up in the DOM but match no CSS rule. ```css @import "tailwindcss"; @import "@nuxt/ui"; @source "../node_modules/@tacxou/jsonforms_builder/dist"; ``` > If your brand theme is declared in a `@theme` block, use **`@theme static`**. > Tailwind prunes variables that no source references directly, and a color > consumed only by Nuxt UI’s generated CSS > (`--ui-primary: var(--color-my-color-500)`) disappears silently. ## Nuxt ```ts export default defineNuxtConfig({ modules: ['@nuxt/ui'], vite: { optimizeDeps: { // The library imports `@nuxt/ui` SFCs: the esbuild pre-bundler // cannot compile them, so it has to be excluded. exclude: ['@tacxou/jsonforms_builder'], // `ajv` is CommonJS. Without pre-bundling its default export is not exposed // and `@jsonforms/core` fails on import. include: ['ajv', 'ajv-formats', '@jsonforms/core', '@jsonforms/vue'], }, }, }) ``` > **When upgrading the library** — if the browser throws > `does not provide an export named '…'` on `@jsonforms/vue` or `@jsonforms/core`, > the Vite pre-bundle is stale. Restarting with a cleared cache is enough: > > ```bash > rm -rf node_modules/.vite && vite --force > ``` ## Vue + Vite (without Nuxt) ```ts import ui from '@nuxt/ui/vite' export default defineConfig({ plugins: [vue(), ui({ colorMode: true })], }) ``` The WYSIWYG renderer also requires **deduplicating ProseMirror** — its plugins are identified by object identity, and two copies in the dependency tree throw `Adding different instances of a keyed plugin`: ```ts resolve: { dedupe: [ '@tiptap/core', '@tiptap/pm', '@tiptap/vue-3', 'prosemirror-state', 'prosemirror-view', 'prosemirror-model', ], } ``` See `playground/vite.config.ts` for a full commented configuration (including the `#imports` stubs `@nuxt/icon` needs outside Nuxt). ## Known upstream issue — `subTree` `@vueuse/core` 14.4.0 has an unguarded access to `vm.$` inside `onClickOutside`. After an unmount, a click reaching a surviving listener can throw `Cannot read properties of null (reading 'subTree')`. The workaround applied in the affected renderers: defer the unmounting mutation by one `nextTick`, so the menu can close first. Reproduce it in the host app if you unmount subtrees from an `@update:model-value` handler. --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/layouts.md --- # Layouts *** ## Group — `UCard` **Trigger:** UISchema element `type: "Group"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `card` | `Object` | — | Pass-through → `UCard` (`variant`, `ui`, …). | The Group’s `label` becomes the card title. ### Example ```json { "type": "Group", "label": "Contact details", "elements": [ { "type": "Control", "scope": "#/properties/email" }, { "type": "Control", "scope": "#/properties/phone" } ], "options": { "card": { "variant": "subtle" } } } ``` *** ## Categorization — `UTabs` / `UStepper` **Trigger:** `type: "Categorization"` with `Category` children. ### API (on Categorization) | Name | Type | Default | Description | |---|---|---|---| | `variant` | `"stepper"` | tabs | `"stepper"` → `UStepper` wizard; otherwise `UTabs`. | | `queryKey` | `String` | `"tab"` | Hash / query key used to remember the active tab. | | `defaultTab` | `String` | `"0"` | Initial tab identifier. | | `tabs` | `Object` | — | Pass-through → `UTabs`. | | `stepper` | `Object` | — | Pass-through → `UStepper`. | ### API (on Category) | Name | Type | Default | Description | |---|---|---|---| | `queryId` | `String` | index | Stable identifier for the URL hash. | ### Examples Tabs: ```json { "type": "Categorization", "options": { "queryKey": "section", "defaultTab": "basic" }, "elements": [ { "type": "Category", "label": "Basics", "options": { "queryId": "basic" }, "elements": [ { "type": "Control", "scope": "#/properties/name" } ] }, { "type": "Category", "label": "Advanced", "options": { "queryId": "advanced" }, "elements": [ { "type": "Control", "scope": "#/properties/notes" } ] } ] } ``` Stepper: ```json { "type": "Categorization", "options": { "variant": "stepper", "stepper": { "size": "md" } }, "elements": [ { "type": "Category", "label": "Step 1", "elements": [{ "type": "Control", "scope": "#/properties/a" }] }, { "type": "Category", "label": "Step 2", "elements": [{ "type": "Control", "scope": "#/properties/b" }] } ] } ``` *** ## VerticalLayout / HorizontalLayout No dedicated domain options. The Tailwind theme is overridden through `options.styles` or `provide('styles', …)` (`verticalLayout` / `horizontalLayout`). ### Example ```json { "type": "HorizontalLayout", "elements": [ { "type": "Control", "scope": "#/properties/firstName" }, { "type": "Control", "scope": "#/properties/lastName" } ] } ``` *** ## Label **Trigger:** `type: "Label"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `level` | `1`–`6` | `3` | HTML heading level (`h1`…`h6`). | | `separator` | `Boolean` | `true` | Shows a `USeparator` under the heading. `false` hides it. | | `style` | `Object` | — | Inline CSS styles on the heading. | ### Examples ```json { "type": "Label", "text": "Personal information", "options": { "level": 2 } } ``` ```json { "type": "Label", "text": "No separator", "options": { "level": 4, "separator": false, "style": { "letterSpacing": "0.05em" } } } ``` ## Playground → [Layouts](/en/playground#/?section=docs\&example=nuxt-layouts) --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/number.md --- # Numbers *** ## Number / Integer — `UInputNumber` **Trigger:** schema `type: "number"` or `"integer"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `step` | `Number` | `1` (integer) / `0.1` (number) | Step of the +/- buttons. | | `placeholder` | `String` | — | Placeholder. | | `inputNumber` | `Object` | — | Pass-through → `UInputNumber`. | The `minimum` / `maximum` bounds come from the **schema**. ### Examples ```json { "type": "integer", "title": "Age", "minimum": 0, "maximum": 120 } ``` ```json { "type": "Control", "scope": "#/properties/age", "options": { "step": 1, "inputNumber": { "size": "md" } } } ``` ```json { "type": "Control", "scope": "#/properties/price", "options": { "step": 0.01, "placeholder": "0.00" } } ``` *** ## Slider — `USlider` **Trigger:** `options.slider: true` **or** an object of Nuxt UI props (`options.slider: { size, color, … }`).\ The schema must declare `minimum` and `maximum` (no `default` needed — unlike the stock JSON Forms `isRangeControl` tester). ### API | Name | Type | Default | Description | |---|---|---|---| | `slider` | `Boolean` | `Object` | — | `true` enables the renderer. An object enables it too and is spread onto `USlider`. | | `step` | `Number` | `schema.multipleOf` | `1` | Slider step (takes precedence over `multipleOf`). | | `hideValue` | `Boolean` | — | Hides the numeric badge on the right (tooltip kept). | The schema’s `minimum` / `maximum` / `multipleOf` drive min / max / step. ### Examples ```json { "type": "number", "title": "Volume", "minimum": 0, "maximum": 100, "multipleOf": 5 } ``` ```json { "type": "Control", "scope": "#/properties/volume", "options": { "slider": true } } ``` With Nuxt UI props + a decimal step: ```json { "type": "Control", "scope": "#/properties/temperature", "options": { "slider": { "size": "lg", "color": "primary" }, "step": 0.5 } } ``` ## Playground * [Number](/en/playground#/?section=docs\&example=nuxt-number) * [Slider](/en/playground#/?section=docs\&example=nuxt-slider) * [Rating](/en/playground#/?section=docs\&example=nuxt-rating) *** ## Rating — `UInputRating` **Trigger:** `options.format: "rating"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"rating"` | — | **Required**. | | `length` | `Number` | `schema.maximum` | Number of icons. | | `icon` | `String` | (Nuxt UI) | Filled icon (e.g. `i-lucide-star`). | | `emptyIcon` | `String` | — | Empty icon. | | `hideValue` | `Boolean` | — | Hides the numeric label next to it. | | `clearable` | `Boolean` | `true` when not required | Click again to clear. | | `inputRating` | `Object` | — | Pass-through → `UInputRating`. | ### Examples ```json { "type": "integer", "title": "Satisfaction", "minimum": 1, "maximum": 5 } ``` ```json { "type": "Control", "scope": "#/properties/satisfaction", "options": { "format": "rating" } } ``` ```json { "type": "Control", "scope": "#/properties/heat", "options": { "format": "rating", "length": 5, "icon": "i-lucide-flame", "emptyIcon": "i-lucide-flame", "hideValue": true, "clearable": true } } ``` --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/pass-through.md --- # Nuxt UI pass-through Any object placed under the named key in `options` is **spread** onto the target Nuxt UI component (`size`, `color`, `variant`, `ui`, … props). This mirrors the native attributes Quasar / Vuetify forward outside their documented API. ## API — keys | Name | Target component | Used by | |---|---|---| | `formField` | `UFormField` | All wrapped controls | | `input` | `UInput` | string, password, color (text field) | | `textarea` | `UTextarea` | `multi: true` | | `inputNumber` | `UInputNumber` | number / integer | | `slider` | `USlider` | `slider: true` (also when the object *is* the value of `slider`) | | `inputRating` | `UInputRating` | `format: "rating"` | | `checkbox` | `UCheckbox` | boolean | | `switch` | `USwitch` | boolean + `toggle` | | `checkboxGroup` | `UCheckboxGroup` | multi-enum | | `radioGroup` | `URadioGroup` | `format: "radio"` | | `select` | `USelect` | `format: "select"`, oneOf | | `selectMenu` | `USelectMenu` | enum by default | | `inputMenu` | `UInputMenu` | `api` | | `pinInput` | `UPinInput` | `format: "pin"` | | `inputTags` | `UInputTags` | `format: "tags"` | | `colorPicker` | `UColorPicker` | color | | `fileUpload` | `UFileUpload` | file / data-url | | `inputDate` | `UInputDate` | date / date-time | | `inputTime` | `UInputTime` | time | | `calendar` | `UCalendar` | calendar / date popover | | `calendarCard` | calendar card | dates | | `timeCard` / `timeHour` / `timeMinute` / `timeSecond` | time parts | time | | `editor` | `UEditor` | `wysiwyg` | | `card` | `UCard` | Group | | `tabs` | `UTabs` | Categorization | | `stepper` | `UStepper` | Categorization + `variant: "stepper"` | See the [Nuxt UI docs](https://ui.nuxt.com) for each component’s prop list. ## Examples ### Large text field + `ui` classes ```json { "type": "Control", "scope": "#/properties/name", "options": { "input": { "size": "lg", "color": "primary", "ui": { "base": "tracking-wide font-medium" } } } } ``` ### Compact FormField ```json { "type": "Control", "scope": "#/properties/code", "options": { "formField": { "size": "sm", "ui": { "label": "text-muted" } } } } ``` ### Radio in list variant ```json { "type": "Control", "scope": "#/properties/plan", "options": { "format": "radio", "radioGroup": { "variant": "list", "orientation": "horizontal", "size": "md" } } } ``` ### Group as an outline card ```json { "type": "Group", "label": "Profile", "elements": [], "options": { "card": { "variant": "outline", "ui": { "header": "font-semibold" } } } } ``` ## Playground The showcases often pass pass-through objects (`input`, `radioGroup`, `card`, …). See the [catalogue](/en/guide/playground-examples). --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/playground-examples.md --- # Nuxt UI playground examples The playground splits into two galleries: | Tab | Content | |---|---| | **Documentation** | Nuxt UI showcases + API tables (Name / Type / Default / Description) | | **Examples** | JSONForms demos, compositions and edge cases | Any example whose `name` starts with `nuxt-` automatically lands in **Documentation**. Open the [playground](/en/playground). ## Documentation catalogue ### Overview | Example | File | Takeaway | |---|---|---| | Nuxt UI — Control showcase | `nuxt-ui-showcase.ts` | Several controls side by side to judge height / alignment | | Control Options | `control-options.ts` | Common options, restrict, toggle, autocomplete, WYSIWYG | | Simple form | `simple-form.ts` | Minimal string + boolean form | ### Text & media controls | Example | Components | Key options | |---|---|---| | [String & Textarea](/en/playground#/?section=docs\&example=nuxt-string) | `UInput`, `UTextarea`, password | `restrict`, `multi`, `input`, `format: password` | | [Pin Input](/en/playground#/?section=docs\&example=nuxt-pin-input) | `UPinInput` | `format: pin`, `otp`, `mask`, `length` | | [Color Picker](/en/playground#/?section=docs\&example=nuxt-color) | `UColorPicker` | `colorFormat`, `showInput` | | [File Upload](/en/playground#/?section=docs\&example=nuxt-file-upload) | `UFileUpload` | `accept`, `layout`, multi through `array` | | [Autocomplete API](/en/playground#/?section=docs\&example=nuxt-autocomplete) | `UInputMenu` | `api.*`, `minLength`, `suggestion` | | [WYSIWYG](/en/playground#/?section=docs\&example=nuxt-wysiwyg) | `UEditor` | `wysiwyg`, `contentType` (`json` | `html`) | ### Numbers & booleans | Example | Components | Key options | |---|---|---| | [Number](/en/playground#/?section=docs\&example=nuxt-number) | `UInputNumber` | `step`, `inputNumber` | | [Slider](/en/playground#/?section=docs\&example=nuxt-slider) | `USlider` | `slider`, `step`, `hideValue` | | [Rating](/en/playground#/?section=docs\&example=nuxt-rating) | `UInputRating` | `format: rating`, `icon`, `hideValue` | | [Boolean](/en/playground#/?section=docs\&example=nuxt-boolean) | `UCheckbox`, `USwitch` | `toggle`, `checkbox`, `switch` | ### Enums | Example | Components | Key options | |---|---|---| | [Select](/en/playground#/?section=docs\&example=nuxt-select) | `USelect`, `USelectMenu` | `format: select` vs default (search) | | [Radio & Multi-enum](/en/playground#/?section=docs\&example=nuxt-radio) | `URadioGroup`, `UCheckboxGroup` | `format: radio`, `vertical`, `radioGroup` | ### Dates | Example | Components | Key options | |---|---|---| | [Date & Time](/en/playground#/?section=docs\&example=nuxt-dates) | `UInputDate`, `UInputTime` | `pattern`, month / year precision | | [Calendar](/en/playground#/?section=docs\&example=nuxt-calendar) | `UCalendar` | `format: calendar` | | [Date ranges](/en/playground#/?section=docs\&example=nuxt-date-ranges) | Calendar / InputDate | `range`, `minDate`, `disabled*` | ### Structure | Example | Components | Key options | |---|---|---| | [Tags](/en/playground#/?section=docs\&example=nuxt-tags) | `UInputTags` | `format: tags`, `delimiter` | | [Array](/en/playground#/?section=docs\&example=nuxt-array) | Repeatable cards | `showSortButtons`, `elementLabelProp`, `detail` | | [Layouts](/en/playground#/?section=docs\&example=nuxt-layouts) | `UCard`, `UTabs`, Label | `card`, `queryKey`, `level`, `separator` | ## Adding a showcase 1. Create `playground/examples/items/nuxt-.ts` calling `registerExamples([{ name: 'nuxt-…', … }])`. 2. Prefix `name` with `nuxt-` (or pass `section: 'docs'`) to land in the Documentation tab. 3. Declare the API groups in `playground/docs-api/props.ts` (`API_BY_EXAMPLE`). 4. Document the options under `docs/guide/options/` and link them from this page. Files are eagerly loaded through `import.meta.glob` in `playground/examples/index.ts` — no extra manual registry. ## Relation to the Options API guide Every options page ends with ready-to-paste JSON. The showcases above are their interactive counterpart: * [Common](/en/guide/options/common) * [Text & media](/en/guide/options/string) * [Numbers](/en/guide/options/number) * [Boolean](/en/guide/options/boolean) * [Enums](/en/guide/options/enum) * [Dates](/en/guide/options/date) * [Arrays & objects](/en/guide/options/array) * [Layouts](/en/guide/options/layouts) * [Pass-through](/en/guide/options/pass-through) --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options.md --- # Options API All options go into `uischema.options` (merged with `config` through `defu`). The table layout follows the Quasar / Vuetify model: | Column | Meaning | |---|---| | **Name** | Key in `options` (or nested path) | | **Type** | Expected type | | **Default** | Default value (`—` = none) | | **Description** | Behaviour | Each section ends with one or more ready-to-paste JSON **examples**. ## Navigation | Control | Page | |---|---| | Common options (all fields) | [Common](./common) | | String, textarea, password, pin, color, file, API, WYSIWYG | [Text & media](./string) | | Number, slider, rating | [Numbers](./number) | | Boolean | [Boolean](./boolean) | | Enum, select, radio, multi-enum | [Enums](./enum) | | Date, time, calendar | [Dates](./date) | | Array, tags, object, oneOf | [Arrays & objects](./array) | | Group, Categorization, Label | [Layouts](./layouts) | | Nuxt UI pass-through (`input`, `formField`, …) | [Pass-through](./pass-through) | ## Placement ```json { "type": "Control", "scope": "#/properties/name", "options": { "placeholder": "Your name…", "input": { "size": "lg" } } } ``` Options can also be supplied globally through the `config` prop of `JsonForms` — control-local options win. ## Playground The interactive Nuxt UI showcases (Documentation tab) are listed in [Nuxt UI playground examples](/en/guide/playground-examples). Each options page below also points to its live showcase. --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/renderers.md --- # Renderers Schema / option → Nuxt UI component mapping. | Schema / option | Nuxt UI component | Detailed options | |---|---|---| | `string` | `UInput` | [Text](./options/string#string-—-uinput) | | `string` + `options.multi` | `UTextarea` | [Textarea](./options/string#textarea-—-utextarea) | | `string` + `format: password` | `UInput` + toggle | [Password](./options/string#password) | | `object` + `options.wysiwyg` | `UEditor` | [WYSIWYG](./options/string#wysiwyg-—-ueditor) | | `string` + `options.format: pin` | `UPinInput` | [Pin](./options/string#pin-—-upininput) | | `string` + `format: color` | `UColorPicker` | [Color](./options/string#color-—-ucolorpicker) | | `string` + `format: data-url` | `UFileUpload` | [File](./options/string#file-upload-—-ufileupload) | | `number` / `integer` | `UInputNumber` | [Numbers](./options/number) | | `number` + `options.slider` | `USlider` | [Slider](./options/number#slider-—-uslider) | | `number` + `options.format: rating` | `UInputRating` | [Rating](./options/number#rating-—-uinputrating) | | `boolean` | `UCheckbox` / `USwitch` | [Boolean](./options/boolean) | | `enum` | `USelectMenu` | [Enum](./options/enum) | | `enum` + `options.format: select` | `USelect` | [Select](./options/enum#select-no-search-—-uselect) | | `enum` + `options.format: radio` | `URadioGroup` | [Radio](./options/enum#radio-—-uradiogroup) | | `string` + `options.api` | `UInputMenu` | [Autocomplete](./options/string#autocomplete-api-—-uinputmenu) | | `format: date` / `date-time` / `time` | `UInputDate` / `UInputTime` | [Dates](./options/date) | | `options.format: calendar` | `UCalendar` | [Calendar](./options/date#calendar-—-inline-ucalendar) | | `array` + `options.format: tags` | `UInputTags` | [Tags](./options/array#tags-—-uinputtags) | | `array` | repeatable cards | [Array](./options/array#array-—-repeatable-cards) | | `oneOf` | selector + sub-form | [oneOf](./options/array#oneof-anyof) | | `Group` | `UCard` | [Group](./options/layouts#group-—-ucard) | | `Categorization` | `UTabs` / `UStepper` | [Categorization](./options/layouts#categorization-—-utabs-ustepper) | | `Label` | heading + `USeparator` | [Label](./options/layouts#label) | → [Full options API index](./options/) (Name / Type / Default / Description tables + examples, Quasar / Vuetify style). → [Playground showcase catalogue](./playground-examples) (live forms + API tab). --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/options/string.md --- # Text & media Controls based on `string` (and `object` for the WYSIWYG editor). *** ## String — `UInput` **Trigger:** `type: "string"` (no `multi`, no special format). ### API | Name | Type | Default | Description | |---|---|---|---| | `restrict` | `Boolean` | — | Enforces `schema.maxLength` and shows a character counter. | | `input` | `Object` | — | Pass-through → [`UInput`](https://ui.nuxt.com/docs/components/input) (`size`, `color`, `ui`, …). | The [common](./common) options (`placeholder`, `focus`, …) apply as well. ### Examples ```json { "type": "Control", "scope": "#/properties/name", "options": { "placeholder": "Camille Dupont", "input": { "size": "lg" } } } ``` ```json { "type": "Control", "scope": "#/properties/slug", "options": { "restrict": true } } ``` Matching schema for `restrict`: ```json { "type": "string", "maxLength": 32, "title": "Slug" } ``` *** ## Textarea — `UTextarea` **Trigger:** `options.multi: true`. ### API | Name | Type | Default | Description | |---|---|---|---| | `multi` | `Boolean` | — | **Required** to enable the textarea renderer. | | `rows` | `Number` | `30` | Maximum height (autoresize). | | `minRows` | `Number` | — | Initial / minimum number of rows. | | `textarea` | `Object` | — | Pass-through → `UTextarea`. | ### Examples ```json { "type": "Control", "scope": "#/properties/description", "options": { "multi": true, "minRows": 3, "rows": 12, "placeholder": "Long description…" } } ``` *** ## Password **Trigger:** schema `format: "password"`. Same options as String (`placeholder`, `input`, …). The show / hide button is built in. ### Example ```json { "type": "string", "format": "password", "title": "Password" } ``` ```json { "type": "Control", "scope": "#/properties/password", "options": { "placeholder": "••••••••" } } ``` *** ## Pin — `UPinInput` **Trigger:** `options.format: "pin"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"pin"` | — | **Required** to select this renderer. | | `length` | `Number` | inferred (`maxLength` / pattern) | Number of cells. | | `type` | `"text"` | `"number"` | inferred | Keyboard / input type. | | `mask` | `Boolean` | — | Masks the typed characters. | | `otp` | `Boolean` | — | Enables SMS OTP autocomplete. | | `pinInput` | `Object` | — | Pass-through → `UPinInput`. | ### Examples ```json { "type": "Control", "scope": "#/properties/code", "options": { "format": "pin", "otp": true } } ``` ```json { "type": "Control", "scope": "#/properties/secretCode", "options": { "format": "pin", "mask": true, "length": 6 } } ``` ```json { "type": "Control", "scope": "#/properties/token", "options": { "format": "pin", "length": 8, "type": "text" } } ``` *** ## Color — `UColorPicker` **Trigger:** schema `format: "color"` **or** `options.format: "color"`. ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"color"` | — | Forces the color picker when the schema has no `format: "color"`. | | `colorFormat` | `"hex"` | `"rgb"` | `"hsl"` | `"cmyk"` | `"lab"` | `"hex"` | Notation emitted in the data. | | `showInput` | `Boolean` | `true` | Shows the text field next to the picker. `false` = picker only. | | `colorPicker` | `Object` | — | Pass-through → `UColorPicker`. | | `input` | `Object` | — | Pass-through → the hex/text `UInput`. | ### Examples ```json { "type": "Control", "scope": "#/properties/brandColor", "options": { "format": "color", "colorFormat": "rgb" } } ``` ```json { "type": "Control", "scope": "#/properties/accent", "options": { "format": "color", "showInput": false } } ``` *** ## File upload — `UFileUpload` **Trigger:** schema `format: "data-url"` **or** `options.format: "file"`.\ Multi-file: schema `type: "array"` of `string` items. ### API | Name | Type | Default | Description | |---|---|---|---| | `format` | `"file"` | — | Forces the upload control (useful for an array without `format: data-url`). | | `accept` | `String` | schema `contentMediaType` | MIME filter (`image/*`, `application/pdf`, …). | | `dropLabel` | `String` | — | Title of the drop zone. | | `dropDescription` | `String` | — | Sub-text of the drop zone. | | `layout` | `String` | `"list"` | Nuxt UI layout (`"list"`, `"grid"`, …). | | `fileUpload` | `Object` | — | Pass-through → `UFileUpload`. | ### Examples ```json { "type": "Control", "scope": "#/properties/cv", "options": { "accept": "application/pdf", "dropLabel": "Drop your résumé" } } ``` ```json { "type": "Control", "scope": "#/properties/photos", "options": { "format": "file", "dropLabel": "Drop images here", "layout": "grid" } } ``` *** ## Autocomplete API — `UInputMenu` **Trigger:** presence of `options.api`. ### API | Name | Type | Default | Description | |---|---|---|---| | `api` | `Object` | — | **Required.** Remote fetch configuration (see below). | | `minLength` | `Number` | (internal) | Minimum number of characters before the request. | | `suggestion` | `String[]` | — | Local fallback suggestions. | | `placeholder` | `String` | — | Field placeholder. | | `inputMenu` | `Object` | — | Pass-through → `UInputMenu`. | #### `api` object | Name | Type | Default | Description | |---|---|---|---| | `url` | `String` | — | **Required.** Endpoint path or URL. | | `base` | `String` | — | Origin prefix (e.g. `https://api.example.com`). | | `queryKey` | `String` | `"q"` | Name of the search parameter. | | `params` | `Object` | — | Fixed query parameters. | | `headers` | `Object` | — | HTTP headers. | | `itemsPath` | `String` | — | Dot path to the array in the JSON response. | | `labelKey` | `String` | `"label"` | Path to an item’s label. | | `valueKey` | `String` | `"value"` | Path to the stored value. | ### Example ```json { "type": "Control", "scope": "#/properties/addressId", "options": { "placeholder": "Search for an address…", "minLength": 3, "api": { "base": "https://data.geopf.fr", "url": "/geocodage/search", "queryKey": "q", "itemsPath": "features", "labelKey": "properties.label", "valueKey": "properties.id" } } } ``` *** ## WYSIWYG — `UEditor` **Trigger:** `options.wysiwyg: true` on an `object` control (or string, depending on `contentType`).\ Requires `allRenderers` (not just `nuxtUiRenderers`). ### API | Name | Type | Default | Description | |---|---|---|---| | `wysiwyg` | `Boolean` | — | **Required** (`true`) to enable the editor. | | `contentType` | `"json"` | `"html"` | inferred | Stored format: ProseMirror object (`json`) or HTML string (`html`). | | `toolbar` | `Array` | Nuxt UI toolbar | Replaces the toolbar (`EditorToolbarItem[]`). | | `placeholder` | `String` | — | Editor placeholder. | | `editor` | `Object` | — | Pass-through → `UEditor`. | ### Examples ```json { "type": "Control", "scope": "#/properties/body", "options": { "wysiwyg": true, "contentType": "json" } } ``` ```json { "type": "Control", "scope": "#/properties/notesHtml", "options": { "wysiwyg": true, "contentType": "html", "placeholder": "HTML input…" } } ``` ## Playground * [String & Textarea](/en/playground#/?section=docs\&example=nuxt-string) * [Pin Input](/en/playground#/?section=docs\&example=nuxt-pin-input) * [Color](/en/playground#/?section=docs\&example=nuxt-color) * [File Upload](/en/playground#/?section=docs\&example=nuxt-file-upload) * [Autocomplete API](/en/playground#/?section=docs\&example=nuxt-autocomplete) * [WYSIWYG](/en/playground#/?section=docs\&example=nuxt-wysiwyg) --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/usage.md --- # Usage ## Renderers ```vue ``` * `nuxtUiRenderers` — controls, layouts and additional elements. * `allRenderers` — the same, plus the rich text editor (`UEditor`). ## Typical data ```ts const schema = { type: 'object', properties: { name: { type: 'string', title: 'Name' }, active: { type: 'boolean', title: 'Active' }, }, } const uischema = { type: 'VerticalLayout', elements: [ { type: 'Control', scope: '#/properties/name' }, { type: 'Control', scope: '#/properties/active', options: { toggle: true } }, ], } const data = ref({ name: '', active: false }) ``` Explore ready-made forms in the [playground](/en/playground): the **Documentation** tab for control showcases, the **Examples** tab for JSONForms demos. Full option reference: [Options API](/en/guide/options/) (tables + examples). --- --- url: https://tacxou.github.io/jsonforms_builder/en/guide/builder.md --- # Visual builder ```vue ``` The builder provides: * a **palette** of controls (input, choice, dates, structure); * a reorderable **tree** (drag-and-drop); * an **inspector** for properties and **per-component options** (common + specific: textarea, pin, date, enum, array, categorization, …); * a **live preview**; * a **JSON export** of `{ data, schema, uischema }`; * an **import** (paste JSON or load a `.json` file) to edit an existing form; * an **automatic draft save** (`schema`, `uischema`, `data`) in `localStorage` — disable it with `:storage-key="false"`. Accepted import formats: * `{ "schema": …, "uischema": …, "data"?: … }` (`data` feeds the preview); * a standalone **JSON Schema** — the UI Schema is generated automatically. You can also open it from the playground through **Open builder** (route `#/builder`, with `?return=` to get back to the gallery).