Support the `ai_json_schema` element inside off-canvas dialogs
# Title Support the `ai_json_schema` element inside off-canvas dialogs (correct rendering + value sync) ## Description The `ai_json_schema` form element (`Drupal\ai\Element\AiJsonSchema`) is documented for use "in any Drupal form", but it does not work when rendered inside Drupal's **off-canvas dialog** — which is how the `bpmn_io` modeller shows configuration forms. Upstream the element is only used on full-page forms (e.g. AI API Explorer), where it works; off-canvas has never been exercised, so this is not a regression — it is making the element robust in a context new consumers need. Two distinct problems with the same trigger (the editor mounted inside `#drupal-off-canvas-wrapper`): 1. **Rendering.** Core's off-canvas reset applies `all: revert` to every element in the dialog (`core/misc/dialog/off-canvas/css/reset.css`), reverting CodeMirror's low-specificity, runtime-injected styles. Result: line numbers run horizontally and CodeMirror's visually-hidden announcement region becomes visible. 2. **Value sync.** The editor updates its hidden input programmatically, which fires no `input`/`change`. The off-canvas modeller syncs field values on `change` events (it does not POST the Drupal form), so the entered value is silently dropped and saves empty. On full-page forms this is invisible because submit serialization reads the input regardless. This is the prerequisite for the structured-output schema editor in the ECA Chat action ([ai_integration_eca#3585014](https://git.drupalcode.org/project/ai_integration_eca/-/work_items/3585014)), and applies to any future off-canvas consumer (e.g. moving AI Agents' structured-output field to this element). ## Tasks * [ ] Add `data-drupal-ck-style-fence` to the editor wrapper in `AiJsonSchema::processElement()` so its descendants are excluded from the off-canvas `all: revert` reset (the same mechanism CKEditor uses). * [ ] In `ui/json-schema-editor/src/ai-json-schema.js`, dispatch bubbling `input` and `change` events on the hidden input whenever CodeMirror updates it; rebuild the `dist/` bundle. (Matches the module's mdxeditor widget, which already does this in `ui/mdxeditor/src/main.jsx`.) * [ ] Add a kernel assertion that the editor wrapper carries `data-drupal-ck-style-fence`. * [ ] Add a FunctionalJavascript test that the editor mounts, hides the textarea fallback, syncs edits into the hidden input, and dispatches a `change` event. ## Acceptance criteria * Inside an off-canvas dialog, the editor renders the same as on full-page forms: vertical line-number gutter, syntax highlighting, and no visible announcement text. * A value entered in the editor inside an off-canvas dialog is captured and persists (e.g. the ECA Chat action Schema field saves and reloads correctly). * Existing full-page usages (AI API Explorer) are visually and behaviourally unchanged. ## Testing instructions *(added by implementor before review)* 1. Enable `ai`, `eca`, `bpmn_io`, `modeler_api`, and `ai_integration_eca` (with the #3585014 change). 2. If In an ECA model, add the **Chat** action and open its configuration (right-hand off-canvas panel). 3. Confirm the **Schema** editor renders correctly (vertical gutter, highlighting, no stray "Selection deleted" text). 4. Enter a JSON schema, **Save**, reopen the action — confirm the schema persists. 5. Confirm the AI API Explorer JSON Schema field (`/admin/config/ai/explorers/chat_generator`, Advanced) is unchanged. ## Related issues <!-- Cross-project: ai_integration_eca#3585014 is the first consumer and is blocked by this task. --> * /relate ai_integration_eca#3585014
task