--- name: openforms-mui description: >- Author, render, preview and debug OpenForms FormSchemaJSON form definitions as idiomatic, themed, accessible MUI (React). Use when the user wants to design an OpenForms form, render an OpenForms schema with Material UI, convert an OpenForms JSON schema into a React MUI form, preview a form schema, or debug conditional-logic / calculated fields / cross-field validation in an OpenForms schema. This is the OpenForms *form-builder* schema (github.com/henriquefps/open-forms) — NOT the "open-form.dev" documents-as-code framework, which this skill does not cover. --- # openforms-mui Runtime interpreter that renders an OpenForms `FormSchemaJSON` as MUI. Walk the schema on every render — **no code generation, no emitted per-form files**. The component mirrors the upstream `OpenFormRenderer` API so migration is a mechanical substitution. ## What this skill is (and is not) - **Is:** a React + MUI runtime for the visual **form-builder** schema from `github.com/henriquefps/open-forms` (Apache 2.0). It implements all 14 field types, both conditional-logic systems, calculated fields, and validation. - **Is not:** the `open-form.dev` "documents as code" framework. If a request is about `open-form.dev`, this skill does not apply. ## Where it lives ``` ~/.pi/agent/skills/openforms-mui/ SKILL.md references/ # load only the one you need schema.md # FormSchemaJSON structure field-widget-map.md # 14 types → MUI widget → value shape logic.md # CNF andGroups, operators, formula grammar theme-bridge.md # tokens → createTheme(); host theme provider a11y.md # matrix / repeater / signature pitfalls hu-locale.md # Hungarian conventions (opt-in via locale) tools/ # the TypeScript library + preview harness src/ # component, schema, logic, validation, theme, i18n preview/ # Vite three-panel harness + CLI tests/ # vitest suite mockups/ # approved token layer (tokens.css, ui-contract.tokens.json) ``` The skill is **user-global** — usable from any working directory, with no assumption about any particular project or document archive. ## Using the component in a project ```tsx import { OpenFormsMui } from "openforms-mui"; // resolves to tools/src/index.ts { // answers: upstream-shaped, keyed by field key (applicable fields only) // meta.submissionContext: your supplementary data, segregated from answers // meta.diagnostics: non-blocking findings (e.g. disabled/calculated violations) }} onFieldChange={(all) => {/* COMPLETE state incl. retained hidden values — not the payload */}} /> ``` ### Single-instance resolution (required) This is the **first** user-global skill to ship a `package.json` with installed dependencies. A consuming project that imports the component out of this directory must resolve React, `react-dom`, `@mui/material`, `@mui/x-date-pickers`, `@emotion/react` and `@emotion/styled` to **one** instance — a second React instance makes hooks throw an *invalid hook call*, and Emotion/MUI theme context break because they rely on module-level singletons. These packages are declared as **`peerDependencies`** (the consumer supplies them) and additionally as **`devDependencies`** (so the preview harness runs standalone). They are **never** plain `dependencies`. Resolve to one instance at the bundler level: - **Vite:** `resolve.dedupe: ["react", "react-dom", "@mui/material", "@emotion/react", "@emotion/styled"]` - **Webpack:** `resolve.alias` each of the above to the consumer's copy, or use `resolve.dedupe`/a single `node_modules`. - **A monorepo:** hoist these packages so one copy is shared. The preview harness and the vitest config already dedupe; a regression test (`tests/singleton.test.tsx`) pins single-instance resolution. ## Preview & diagnose (CLI) From `tools/`: ```bash npm run diagnose -- path/to/schema.json # print findings; exit 1 on any error npm run preview -- path/to/schema.json # three-panel Vite harness npm run preview -- path/to/schema.json --reference # side-by-side upstream 1.0.7 ``` The harness shows: the rendered MUI form (with a **Rendered form ↔ Schema source** view switch), the live `answers` JSON with validation errors, and a CNF rule-debug panel showing each condition's operand values and outcome. It reloads on schema-file save (answers preserved) and inspects mobile/tablet/ desktop widths. `--reference` loads the pinned upstream vanilla renderer in an isolated frame for fidelity checking — this is the only place upstream code is loaded and it is **never** part of the shipped library. ## Rendering a form on the pi-dashboard canvas The `npm run preview` harness is a **Vite dev server** — great for local inspection, but it does **not** render on the pi-dashboard canvas. The dashboard loads a loopback `canvas(kind:"url")` target inside a `sandbox="allow-scripts"` iframe with **no `allow-same-origin`** (opaque origin), proxied under `/live//`. Two things break there: 1. **Vite dev → blank.** Vite emits absolute asset paths (`/main.tsx`, `/@vite/client`) and the harness fetches `/__schema.json`; under the `/live//` prefix these resolve to the dashboard root → 404 → blank. 2. **Static build without CORS → blank.** In the opaque-origin iframe a `