---
title: Editor-API
description: Vollständige Referenz für die init()-Funktion, TemplaticalEditorConfig und die TemplaticalEditor-Instanz.
---

# Editor-API

Der Haupteinstiegspunkt ist die `init()`-Funktion aus `@templatical/editor`.

## `init(config)`

Erstellt und hängt den Editor in ein Container-Element ein. Gibt ein Promise zurück, das aufgelöst wird, sobald der Editor bereit ist.

Ein Container enthält einen Editor. Ein späteres `init()` auf demselben Container ersetzt den Editor dort und behält den Container auch dann, wenn das Promise eines früheren Aufrufs noch aussteht: Dieser frühere Aufruf liefert dann einen Editor, der nie gemountet wird. Ein Aufruf mit ungültigem `layout` oder `content` lehnt ab, bevor er den Container berührt: Der Editor dort und ein noch ausstehender früherer Aufruf bleiben unverändert.

```ts
import { init } from "@templatical/editor";
import "@templatical/editor/style.css";

const editor = await init({
  container: "#editor",
  content: savedTemplate,
  onChange(content) {
    // Auto-save or update state
  },
});
```

**Rückgabewert:** [`TemplaticalEditor`](#templaticaleditor)

## `unmount()`

Zerstört den zuletzt gemounteten Editor und räumt Event-Listener auf. Um einen bestimmten Editor abzubauen, rufen Sie `unmount()` an der von `init()` zurückgegebenen Instanz auf.

```ts
import { unmount } from "@templatical/editor";

unmount();
```

## TemplaticalEditorConfig

| Property             | Type                                                              | Required | Beschreibung                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| -------------------- | ----------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `container`          | `string \| HTMLElement`                                           | Ja       | CSS-Selektor oder DOM-Element, in das der Editor eingehängt wird. Im Standardmodus (Shadow DOM) muss es ein Element sein, das einen Shadow Root aufnehmen kann — `<div>` wird empfohlen. Siehe [Anforderungen an das Container-Element](#anforderungen-an-das-container-element) unten                                                                                                                                                                                                                                                                                                     |
| `shadowDom`          | `boolean`                                                         | Nein     | Mountet innerhalb eines Shadow DOM zur CSS-Isolation von der Host-Seite. Standardwert `true`. Auf `false` setzen, um stattdessen im Light DOM zu mounten (z. B. für `document.querySelector`-Zugriff auf Editor-Interna oder Firefox-<101 / Safari-<16.4-Unterstützung). Siehe [Shadow DOM](/de/guide/shadow-dom) für Kompromisse                                                                                                                                                                                                                                                          |
| `content`            | `TemplateContent`                                                 | Nein     | Anfänglicher Template-Inhalt. Standardmäßig ein leeres Template. Der Editor arbeitet auf einer Kopie, Änderungen erreichen das übergebene Objekt also nie                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `layout`             | `TemplateContent`                                                 | Nein     | Hülle des Hosts, angewendet in Vorschau und `toMjml()` / `toHtml()`. Nie in `getContent()`, Speichern, Verlauf oder die Bearbeitungsleinwand geschrieben. Ein `TemplateContent` mit genau einem `slot`. Darf eigene `settings.locales`, Block-`l10n` und `settings.l10n` enthalten, auch in Wrapper-Kindern; wird mit `missing: "default"` für die angefragte Sprache projiziert, mit Fallback auf die Standardsprache des Layouts. Wirft, wenn der Slot in einem Wrapper sitzt und die Vorlage `mj-wrapper` erzeugt. Siehe [Layout](/de/guide/layout)                                                                                                                                                                                                   |
| `sectionWrapper`     | `boolean`                                                         | Nein     | Ob die Sektions-Symbolleiste Wrapper hinzufügen anbietet. Weggelassen / `true` ist an. `false` blendet das Steuerelement aus, auch dort, wo ein Wrapper zulässig ist. Bereits eingeschaltete Wrapper bleiben erreichbar. Nur Darstellung: Ausblenden entfernt `section.wrapper` nie. Unabhängig von `layout`. Siehe [Layout](/de/guide/layout)                                                                                                                                                                               |
| `onChange`           | `(content: TemplateContent) => void`                              | Nein     | Wird aufgerufen, wenn sich der Template-Inhalt ändert (entprellt)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `onError`            | `(error: Error) => void`                                          | Nein     | Wird aufgerufen, wenn ein Fehler auftritt                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `onDirtyChange`      | `(isDirty: boolean) => void`                                      | Nein     | Wird aufgerufen, wenn der Zustand „ungespeicherte Änderungen" umschlägt. Funktioniert mit und ohne `templates`-Provider — damit sichern Sie einen clientseitigen Router ab, den `beforeunload` nicht abdecken kann. Siehe [Speichern & Laden](/de/backend/templates#ungespeicherte-anderungen)                                                                                                                                                                                                                                                                                             |
| `templates`          | `TemplatesProvider`                                               | Nein     | Speicher-Backend für die Vorlage selbst — der Speicher-/Ladezyklus. Dasselbe Objekt trägt auch die Konfiguration `autoSave`, `unsavedChangesGuard` und `nameField` sowie die Events `onSaved` / `onCreated` / `onLoaded` — nichts davon bedeutet etwas ohne ein Ziel zum Speichern. Der Editor liefert Namensfeld, Speichern-Schaltfläche, Statusanzeige und Cmd+S; Sie liefern die Persistenz. Lassen Sie `templates` weg, ist die Funktion vollständig deaktiviert: kein Namensfeld, keine Speichern-Schaltfläche, keine Statusanzeige. Siehe [Speichern & Laden](/de/backend/templates) |
| `render`             | `RenderProvider`                                                  | Nein     | Rendering-Backend für `toMjml()` / `toHtml()`. Jede Methode (`toMjml`, `toHtml`, `compileMjml`) ist unabhängig optional und wird separat aufgelöst. Weglassen: `toMjml()` rendert lokal, `toHtml()` lehnt ab — das SDK bündelt keinen MJML-Compiler. Siehe [Rendering & Export](/de/backend/render)                                                                                                                                                                                                                                                                                        |
| `ai` | `AiProvider` | Nein | KI über Ihr eigenes Backend: KI-Assistent mit Rückgängig und Anhängen, **Aus Screenshot oder PDF importieren**, Umformulieren und statische, lokalisierte Einstiegsanfragen. `chat`, `fixFinding`, `rewrite` und `altText` sind Funktionen oder `false`. `chatAttachments` ist ein boolesches Flag, das nur wirkt, wenn `chat` eine Funktion ist; die Einstiegspunkte erscheinen erst nach `create()` oder `load()`. Weglassen deaktiviert die Funktion einschließlich ihrer UI-Chunks. Siehe [KI](/de/backend/ai). |
| `versionHistory`     | `VersionHistoryProvider`                                          | Nein     | Speicher-Backend für den Versionsverlauf der Vorlage — die früheren Stände, die Nutzende durchsehen, in der Vorschau ansehen und wiederherstellen können. Der Editor liefert das Header-Steuerelement, das Vorschaubanner und den Wiederherstellungsablauf; Sie liefern den Speicher. Dasselbe Objekt trägt auch die Events `onCreated` und `onRestored`. Er zeichnet nie selbst eine Version auf: Das entscheidet Ihr `templates.save`. Weglassen, um die Funktion vollständig zu deaktivieren. Siehe [Versionsverlauf](/de/backend/version-history)                                      |
| `comments`           | `CommentsProvider`                                                | Nein     | Speicher-Backend für Review-Kommentare — Threads, die an einem Block oder der Vorlage hängen. Dasselbe Objekt trägt auch die Events `onCreated`, `onUpdated`, `onDeleted`, `onResolved` und `onUnresolved`. Der Editor liefert die Seitenleiste, den Editor, Auflösen/Antworten und die Block-Marker; Sie liefern die Persistenz. **Erfordert `user`**: ohne Identität meldet sich die Funktion als nicht verfügbar, statt anonyme Kommentare zu schreiben. Ein optionales `subscribe` schiebt entfernte Änderungen herein. Siehe [Kommentare](/de/backend/comments)                       |
| `collaboration`      | `CollaborationProvider`                                           | Nein     | Echtzeit-Zusammenarbeit über Ihr Backend: Jede Änderung geht als Batch von [Operationen](/de/api/operations) über `submit` hinaus, Batches anderer Sitzungen werden in Revisionsreihenfolge angewendet, die Auswahl eines Blocks nimmt seine Sperre, die Kopfzeile zeigt, wer sonst da ist, und Rückgängig schickt umgekehrte Operationen, die Ihr Backend ablehnen kann. **Benötigt `templates`**, dessen `load` die `revision` des Templates liefert; `templates.save` erhält dann nur noch Umbenennungen. Die drei Sperr-Methoden sind nur gemeinsam optional. Siehe [Zusammenarbeit](/de/backend/collaboration) |
| `onRemoteChange`     | `(change: CollaborationRemoteChange) => void`                     | Nein     | Wird mit `{ actor, ops }` aufgerufen, nachdem der Batch einer anderen Sitzung auf dem Canvas angewendet wurde. Nicht für die eigenen Änderungen dieses Editors und nicht für einen Resync, der das Template neu lädt |
| `user`               | `EditorUser`                                                      | Nein     | Wer den Editor benutzt — `{ id, name }`. Wird von jeder Funktion benötigt, die Arbeit einer Person zuordnet: `comments` und `collaboration`, deren Leiste in der Kopfzeile die eigenen Sitzungen dieses Nutzers auslässt. Keine Sicherheitsgrenze: Die Angabe identifiziert die Person gegenüber der Oberfläche, im Browser dieser Person. Ordnen Sie Schreibvorgänge serverseitig der Sitzung zu, der Ihr Backend ohnehin vertraut                                                                                                                                                                                                                                           |
| `changeDebounce`     | `number`                                                          | Nein     | Wie lange der Editor nach der letzten Änderung wartet, bevor `onChange` auslöst und, sofern `templates.autoSave` aktiv ist, bevor gespeichert wird. Ein Timer treibt beides, sodass er `onChange` auch ohne konfigurierten `templates`-Provider taktet. Standardwert `2000`. Siehe [Speichern & Laden](/de/backend/templates#autosave)                                                                                                                                                                                                                                                     |
| `onRequestMedia`     | `(context?: MediaRequestContext) => Promise<MediaResult \| null>` | Nein     | UI-Überschreibung für die Medienauswahl (Bynder, Cloudinary-Widget, ein Host-Modal). Hat Vorrang vor `media`, wenn beide gesetzt sind. Gibt `{ url, alt?, width?, height? }` oder `null` zurück. Siehe [Bilder](/de/guide/images) und [Medien](/de/backend/media)                                                                                                                                                                                                                                                                                                                                           |
| `resolveImageUrl`    | `(src: string) => string \| null \| Promise<string \| null>`      | Nein     | Reiner Anzeige-Resolver für Bild-`src`-Werte sowie für die Hintergrundbild-URLs von Sektionen, Sektions-Wrappern und Layout-Wrapper-Bändern (nie für eine Merge-Tag-URL): bildet einen kanonischen src auf eine Vorschau-URL für die Leinwand ab. Inhalt und `toMjml()`-Ausgabe behalten den kanonischen Wert. `null` zurückgeben, um den src unverändert zu verwenden. Wird einmal pro bestätigtem src aufgerufen (entprellt), pro src zwischengespeichert. Siehe [Bilder](/de/guide/images#reine-anzeige-aufloesung-von-bild-urls)                                                                                                                          |
| `mergeTags`          | `MergeTagsConfig`                                                 | Nein     | Merge-Tag-Konfiguration. Jedes Tag kann ein optionales `sample` tragen — einen Beispielwert, den Vorschauen an seiner Stelle anzeigen. `showRawValue: false` hält den rohen Token aus der Autoren-Oberfläche heraus. Siehe [Merge-Tags](/de/guide/merge-tags)                                                                                                                                                                                                                                                                                                                              |
| `resolvePreview`     | `ResolvePreview`                                                  | Nein     | Löst die Vorlage für Vorschauflächen auf — typischerweise durch Auswerten von Logik-Tags mit echten Daten in Ihrem Backend. Nur zur Anzeige: nie in `getContent()`, im Versand oder im Export. Siehe [Vorschau-Rendering](/de/guide/preview-rendering)                                                                                                                                                                                                                                                                                                                                     |
| `displayConditions`  | `DisplayConditionsConfig`                                         | Nein     | Konfiguration für Anzeigebedingungen. Siehe [Anzeigebedingungen](/de/guide/display-conditions)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `logicTags`          | `LogicTagsConfig`                                                 | Nein     | Konfiguration für Logik-Tags — Kontrollfluss Ihrer Template-Sprache (Bedingungen, Schleifen), inline im Rich Text und in Textfeldern eingefügt. Siehe [Logik-Tags](/de/guide/logic-tags)                                                                                                                                                                                                                                                                                                                                                                                                   |
| `customBlocks`       | `CustomBlockDefinition[]`                                         | Nein     | Definitionen für benutzerdefinierte Blocktypen. Siehe [Benutzerdefinierte Blöcke](/de/guide/custom-blocks)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `savedBlocks`        | `SavedBlocksProvider`                                             | Nein     | Speicher-Backend für gespeicherte Blöcke — wiederverwendbare Blockgruppen, die Nutzer speichern und erneut einfügen. Der Editor stellt die Oberfläche, Sie die Persistenz. Dasselbe Objekt trägt auch die Events `onCreated`, `onUpdated` und `onDeleted`. Weglassen deaktiviert die Funktion vollständig. `createLocalStorageSavedBlocksProvider()` bietet eine Variante ohne Backend. Siehe [Gespeicherte Blöcke](/de/backend/saved-blocks)                                                                                                                                              |
| `media`              | `MediaProvider`                                                   | Nein     | Speicher-Backend für die Medienbibliothek — die Auswahl hinter Durchsuchen an Bildfeldern, Video-Thumbnails und Bildfeldern benutzerdefinierter Blöcke. Der Editor stellt Modal, Raster, Zuschnitt und Einfügen; Sie stellen die Persistenz. `list` ist erforderlich; jede andere Methode ist `false \| fn`. Dasselbe Objekt trägt auch `onCreated` / `onUpdated` / `onDeleted`. Weglassen lässt Bildfelder URL-only, sofern `onRequestMedia` nicht gesetzt ist. `createLocalStorageMediaProvider()` bietet eine Variante ohne Backend. Siehe [Medien](/de/backend/media)                  |
| `testEmail`          | `TestEmailProvider`                                               | Nein     | Versand-Backend für Test-E-Mails — Nutzer senden sich die Vorlage zu, die sie bearbeiten. Der Editor stellt Auslöser, Dialog, Prüfung und Zustände; Sie stellen den Versand. Dasselbe Objekt trägt auch das Event `onSent`. Weglassen deaktiviert die Funktion vollständig. `allowedRecipients` schränkt nur die Auswahl ein und ist **keine** Sicherheitsgrenze — serverseitig prüfen. Siehe [Test-E-Mails](/de/backend/test-email)                                                                                                                                                       |
| `paletteBlocks`      | `string[]`                                                        | Nein     | Allowlist + Reihenfolge für die Block-Palette. Nur die aufgeführten Typen erscheinen, in dieser Reihenfolge; nicht aufgeführte integrierte Blöcke werden ausgeblendet. Integrierte Blöcke über ihren reinen Typ (`'image'`), benutzerdefinierte über den `custom:`-präfixierten Typ (`'custom:qrcode'`). Siehe [Block-Palette anpassen](#block-palette-anpassen)                                                                                                                                                                                                                           |
| `htmlBlockPreview`   | `boolean \| { enabled: boolean }`                                 | Nein     | Rendert den Inhalt jedes HTML-Blocks als Live-Vorschau in der Leinwand — in einem sandboxed `<iframe>` ohne Skriptausführung — statt des statischen Platzhalters. Standardmäßig `false`. Nur Vorschau; der MJML-/HTML-Export rendert HTML-Blöcke unabhängig davon. Siehe [HTML-Blöcke in der Vorschau](#html-bloecke-in-der-vorschau)                                                                                                                                                                                                                                                      |
| `blockDefaults`      | `BlockDefaults`                                                   | Nein     | Standard-Property-Überschreibungen für neue Blöcke. Siehe [Standardwerte](/de/guide/defaults)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `templateDefaults`   | `TemplateDefaults`                                                | Nein     | Standardeinstellungen für leere Templates. Siehe [Standardwerte](/de/guide/defaults)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `fonts`              | `FontsConfig`                                                     | Nein     | Schriftart-Konfiguration. Siehe [Benutzerdefinierte Schriftarten](/de/guide/fonts)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `socialIconsBaseUrl` | `string`                                                          | Nein     | Basis-URL für die Social-Icon-PNGs im exportierten MJML, weitergereicht an [`socialIconsBaseUrl`](/de/api/renderer-typescript#social-icons) des Renderers. Setzen Sie sie, um die Icons selbst zu hosten, und spiegeln Sie dabei alle Ordner, auch die `{style}-{tone}`-Ordner für einen `iconTone` von `dark` oder `light`; ohne Angabe gilt der versionsgebundene jsDelivr-Standard. Betrifft nur den lokalen `toMjml()` / `toHtml()`-Pfad (über `compileMjml`) — eine `render.toMjml`-Implementierung übergibt die URL an ihr eigenes `renderToMjml`                                                                                                                                                       |
| `colors`             | `ColorsConfig`                                                    | Nein     | Farbwähler-Palette. `presets` werden als anklickbares Raster in jedem Farbwähler gerendert; `allowCustom: false` beschränkt Autoren darauf. Siehe [Vordefinierte Farben](#vordefinierte-farben)                                                                                                                                                                                                                                                                                                                                                                                            |
| `templateSettings`   | `TemplateSettingsConfig`                                          | Nein     | Welche Template-Einstellungen das Einstellungs-Panel anbietet. `fields` ist eine Positivliste über `Exclude<keyof TemplateSettings, "locales" \| "l10n">` oder `false` für keine (dann entfällt der Tab). Ohne Angabe sind alle Einstellungen bearbeitbar. Siehe [Einstellungs-Panel einschränken](#einstellungs-panel-einschraenken)                                                                                                                                                                                                                                                                       |
| `theme`              | `ThemeOverrides`                                                  | Nein     | Überschreibungen für Farb-Tokens. Unterstützt einen `dark`-Schlüssel für Dark-Mode-Überschreibungen. Siehe [Theming](/de/guide/theming)                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `uiTheme`            | `'light' \| 'dark' \| 'auto'`                                     | Nein     | UI-Farbschema. `'auto'` folgt den Systemeinstellungen. Standardwert ist `'auto'`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `localization` | `{ locales: string[]; doNotTranslate?: string[] }` | Nein | Aktiviert Template-Sprachversionen. Ohne Angabe keine Sprachen-UI; vorhandene Ebenen bleiben erhalten. Renderer, Validator und Kollaborationsbackend zuerst aktualisieren. Siehe [Lokalisierte Templates](/de/guide/localized-templates). `doNotTranslate` akzeptiert höchstens 500 Begriffe mit jeweils 1–100 Zeichen nach dem Trimmen; passende Begriffe bleiben beim Übersetzen Byte für Byte erhalten. Ungültige Listen werden mit `SdkError` abgelehnt: `localization.doNotTranslate must be an array of at most 500 terms, each 1–100 characters.` Siehe [Maskierung](/de/backend/translation#provider-vertrag). |
| `translation` | `TranslationProvider` | Nein | Übersetzt geeignete Felder in einer aktivierten Nicht-Standardsprachansicht; benötigt `localization`. Ohne Provider fehlt Übersetzen. Unabhängig von `ai`. Ist der Wert kein Objekt mit einer `translate`-Funktion, lehnt `init()` mit `SdkError` ab: `translation must be an object with a translate function.` Siehe [Übersetzung](/de/backend/translation). |
| `onLocaleChange` | `(locale: string) => void` | Nein | Meldet die Sprache, die der Canvas zeigt (`getLocale()`), bei jedem Wechsel: Auswahl einer Version, Rückkehr zum Standard und ein neuer Standard, während der Standard angezeigt wird (Als Standard festlegen, dessen Rückgängig oder Wiederholen, `setDefaultLocale` einer anderen Sitzung oder ein geladenes oder wiederhergestelltes Template mit anderer Standardsprache). Wird die angezeigte Version zum Standard, meldet es nichts. Die aktive Sprache ist ungespeicherter Ansichtsstatus. |
| `locale`             | `string`                                                          | Nein     | Locale-Code (z. B. `'en'`, `'de'`, `'pt-BR'`, `'es'`, `'ca'`, `'fr'`, `'nl'`, `'ja'`). Standardwert ist `'en'`                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `branding`           | `boolean`                                                         | Nein     | Zeigt den "Powered by Templatical"-Footer. Standardwert `true`. Auf `false` setzen, um ihn auszublenden                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `smallScreenNotice`  | `boolean`                                                         | Nein     | Zeigt auf Viewports schmaler als ~768px einen Hinweis „Bitte größeren Bildschirm verwenden" anstelle des Editors. Standardwert `true`. Der Drag-and-Drop-Editor ist ein Desktop-Werkzeug und lässt sich auf einem Smartphone nicht sinnvoll darstellen. Auf `false` setzen, um den Editor bei jeder Breite zu rendern, wenn Sie kleine Bildschirme selbst behandeln                                                                                                                                                                                                                        |
| `lint`               | `LintOptions`                                                     | Nein     | Konfiguration des Template-Linters. `@templatical/quality` ist eine optionale Abhängigkeit des Editors und wird standardmäßig mitinstalliert. Sie können es weglassen: Der Editor funktioniert ohne das Paket und blendet den Tab „Probleme“ aus. Ohne Angabe startet Linting beim Mounten des Editors. `disabled: true` überspringt den Import vollständig und blendet den Sidebar-Tab sowie die Inline-Marker aus. Siehe [Quality-Optionen](/de/quality/options)                                                                                                                                                                                                                                                 |

### Anforderungen an das Container-Element

Das Standard-Mount (Shadow DOM) ruft `attachShadow()` auf Ihrem Container auf, und die HTML-Spezifikation erlaubt Shadow Roots nur für eine feste Menge von Elementen. Verwenden Sie eines davon:

`<article>`, `<aside>`, `<blockquote>`, `<body>`, `<div>` (empfohlen), `<footer>`, `<h1>`–`<h6>`, `<header>`, `<main>`, `<nav>`, `<p>`, `<section>`, `<span>` sowie jedes von Ihnen definierte Custom Element.

**Nicht erlaubt:** `<table>`, `<tr>`, `<td>`, `<form>`, `<input>`, `<button>`, `<select>`, Listenelemente (`<ul>`, `<ol>`, `<li>`), `<iframe>`, ersetzte Elemente (`<img>`, `<video>` usw.). Die Übergabe eines dieser Elemente wirft eine `DOMException` aus `attachShadow()`.

Wenn Ihre Integration ein nicht unterstütztes Element verwenden muss (z. B. Mount in eine `<form>`-Zelle eines CMS-Layouts), übergeben Sie `shadowDom: false` — das Light-DOM-Mount akzeptiert jedes Element. Der Kompromiss ist die Host-CSS-Isolation, auf die Sie verzichten.

### Block-Palette anpassen

Standardmäßig listet die Seitenleisten-Palette jeden integrierten Blocktyp auf. Übergeben Sie `paletteBlocks`, um die Palette auf eine bestimmte Menge zu beschränken und ihre Reihenfolge zu steuern — nützlich, um nicht verwendete Blocktypen (`video`, `table`, …) auszublenden oder einen häufig genutzten [benutzerdefinierten Block](/de/guide/custom-blocks) über die integrierten Blöcke zu stellen.

```ts
const editor = await init({
  container: "#editor",
  customBlocks: [qrCodeDefinition],
  paletteBlocks: [
    "section",
    "title",
    "paragraph",
    "image",
    "custom:qrcode", // a custom block, interleaved among built-ins
    "button",
  ],
});
```

- **Strikte Allowlist + Reihenfolge.** Es werden nur die aufgeführten Typen angezeigt, in genau dieser Reihenfolge. Jeder nicht aufgeführte integrierte Block (hier `hero`, `divider`, `video`, `social`, `menu`, `table`, `spacer`, `html`) wird aus der Palette ausgeblendet.
- **Integrierte Blöcke über ihren reinen Typ** (`"section"`, `"image"`, …) und **benutzerdefinierte Blöcke über ihren `custom:`-präfixierten Typ** (`"custom:qrcode"`) referenzieren, sodass beide frei vermischt werden können.
- **`"hero"` ist eine Verknüpfung, kein Blocktyp.** Sie fügt eine einspaltige Sektion im Hero-Modus mit Titel, Absatz und Button ein (siehe [Hero](/de/guide/sections-and-columns#hero)). Führen Sie sie wie einen integrierten Block auf.
- **Unbekannte Einträge werden übersprungen.** Ein Tippfehler, ein nicht registrierter benutzerdefinierter Block oder `countdown` außerhalb eines Cloud-Plans wird mit einer Warnung in der Konsole protokolliert und nicht in die Palette aufgenommen.
- **Das Filtern der Palette wirkt sich nie auf das Rendering aus.** Das Ausblenden eines Blocktyps entfernt ihn nur aus der Palette — vorhandener Inhalt, der diesen Typ bereits verwendet, wird weiterhin korrekt gerendert. `paletteBlocks` steuert, was Benutzer _einfügen_ können, nicht, was der Editor _anzeigen_ kann.

Lassen Sie `paletteBlocks` weg (oder übergeben Sie ein leeres Array), um die vollständige Standard-Palette anzuzeigen.

### HTML-Blöcke in der Vorschau {#html-bloecke-in-der-vorschau}

Standardmäßig zeigt ein HTML-Block in der Leinwand eine Platzhalterkarte an, anstatt sein Markup zu rendern — der Inhalt wird erst beim Export realisiert. Setzen Sie `htmlBlockPreview`, um den Inhalt jedes HTML-Blocks stattdessen live in der Leinwand zu rendern:

```ts
const editor = await init({
  container: "#editor",
  htmlBlockPreview: true, // shorthand for { enabled: true }
});
```

- **Standardmäßig aus.** Lassen Sie die Option weg (oder übergeben Sie `false` / `{ enabled: false }`), um den statischen Platzhalter beizubehalten.
- **In einem sandboxed `<iframe>` gerendert.** Der Inhalt wird unverändert in einem `<iframe sandbox="allow-same-origin">` **ohne** `allow-scripts` angezeigt — Skripte und Inline-Event-Handler werden nie ausgeführt, und die Styles des Fragments können nicht in den Rest des Editors gelangen. So wird verhindert, dass beliebiges oder von Mitarbeitenden erstelltes HTML im Origin Ihrer App ausgeführt wird.
- **Nur Vorschau.** Diese Einstellung steuert die Editor-Leinwand, nicht die Ausgabe — `renderToMjml()` / `editor.toMjml()` rendern HTML-Blöcke unabhängig davon.

### Vordefinierte Farben {#vordefinierte-farben}

Jeder Farbwähler im Editor — Block-Symbolleisten, Template-Einstellungen, Rich-Text-Farbe, Farbfelder benutzerdefinierter Blöcke — öffnet ein Popover mit einem Farbrad und einem Hex-Eingabefeld. Übergeben Sie `colors`, um diesem Popover eine Reihe vordefinierter Farben hinzuzufügen und optional die freien Eingabefelder zu entfernen. Die Konfiguration ist die Grundlage für jeden Farbwähler; das Farbfeld eines benutzerdefinierten Blocks kann sie für sich selbst weiter einschränken (siehe den letzten Punkt):

```ts
const editor = await init({
  container: "#editor",
  colors: {
    presets: ["#0b5cff", "#111827", "#6b7280", "#ffffff"],
    allowCustom: false,
  },
});
```

- **`presets`** — Hex-Zeichenketten, die als anklickbares Raster gerendert werden. Ein Klick übernimmt die Farbe; die vordefinierte Farbe, die dem aktuellen Wert entspricht, wird als ausgewählt markiert. Ergänzt das Farbrad und das Hex-Eingabefeld. Jeder Eintrag muss eine `#rgb`- oder `#rrggbb`-Hex-Zeichenkette sein — 4-/8-stellige Alpha-Hex-Werte und andere Formate werden übersprungen und mit einer Konsolenwarnung protokolliert, die die betreffenden Einträge auflistet.
- **`allowCustom`** — standardmäßig `true`. Auf `false` gesetzt (zusammen mit `presets`) werden das Farbrad und das Hex-Eingabefeld ausgeblendet, sodass Autoren nur aus der Palette wählen können — nützlich beim Einbetten des Editors als White-Label- / Brand-Kit-Werkzeug. In diesem gesperrten Modus beginnt die Palette mit einem „Keine Farbe“-Feld, das den nicht gesetzten (geerbten) Zustand wiederherstellt, da die Schaltfläche zum Löschen des Hex-Eingabefelds ausgeblendet ist. Ebenfalls im gesperrten Modus protokolliert der Editor eine Entwicklungswarnung, wenn eine Farbe aus `blockDefaults` / `templateDefaults` außerhalb von `presets` liegt — neue Blöcke würden sonst mit einer Farbe beginnen, die kein Farbwähler erneut auswählen kann; setzen Sie diese Standardwerte daher aus derselben Palette. Wird mit einer Warnung ignoriert, wenn keine `presets` konfiguriert sind, da der Farbwähler sonst keine Möglichkeit hätte, eine Farbe festzulegen.
- **Einschränkung auf Feldebene.** Das `color`-Feld eines benutzerdefinierten Blocks kann eigene `presets` / `allowCustom` mitbringen — siehe [vordefinierte Farben pro Feld](/de/guide/custom-blocks#color). Ein Feld darf eine eigene Palette vorgeben oder einzeln gesperrt werden, während der übrige Editor freie Eingaben zulässt; seine `presets` ersetzen dieses Raster für dieses Feld, statt eine Schnittmenge damit zu bilden, sodass ein gesperrtes Feld Farben anbieten kann, die in diesen `presets` überhaupt nicht vorkommen. Was ein Feld nie kann, ist den Editor entsperren — `allowCustom: false` sperrt hier weiterhin jeden Farbwähler.

### Einstellungs-Panel einschränken {#einstellungs-panel-einschraenken}

Der Tab „Einstellungen“ in der rechten Seitenleiste bietet `Exclude<keyof TemplateSettings, "locales" | "l10n">` an. Übergeben Sie `templateSettings.fields`, um daraus eine Positivliste zu machen — für Einstellungen, die Ihre Anwendung besitzt und nicht der Autor:

```ts
const editor = await init({
  container: "#editor",
  templateSettings: {
    fields: [
      "width",
      "backgroundColor",
      "textColor",
      "linkColor",
      "linkUnderline",
      "fontFamily",
    ],
  },
});
```

| Wert                              | Ergebnis                                             |
| --------------------------------- | ---------------------------------------------------- |
| ohne Angabe oder `fields: true`   | alle Einstellungen sind bearbeitbar                  |
| `fields: [...]`                   | nur die aufgeführten Einstellungen                   |
| `fields: false` oder `fields: []` | keine — der Tab „Einstellungen“ wird nicht gerendert |

Die Felder sind `width`, `backgroundColor`, `textColor`, `linkColor`, `linkUnderline`, `fontFamily`, `locale`, `direction` und `preheaderText`.

- **Karten folgen ihren Feldern.** Eine Karte wird gerendert, solange mindestens eine ihrer Einstellungen übrig bleibt. Ohne `locale` und `direction` entfällt die Sprach-Karte, ohne `preheaderText` die Preheader-Karte. `width` bildet die Layout-Karte, die fünf Farb- und Schrift-Einstellungen die Darstellungs-Karte.
- **Die Liste schränkt ein, sie sortiert nicht um.** Einstellungen sitzen in festen Karten — anders als bei [`paletteBlocks`](#block-palette-anpassen) gibt es keine Reihenfolge auszudrücken.
- **Ein unbekannter Eintrag wird mit einer Konsolenwarnung übersprungen.** TypeScript lehnt ihn bereits beim Kompilieren ab; bei einem JavaScript-Aufruf schränkt ein Tippfehler das Panel weiter ein, statt stillschweigend alle Einstellungen wiederherzustellen.
- **Eine Einstellung auszublenden ändert ihren Wert nicht.** Was der geladene Inhalt mitbringt, wird weiterhin gerendert und bleibt über `getContent()` und den Export erhalten. Setzen Sie die ausgeblendeten Werte über den Inhalt, den Sie dem Editor übergeben — `init({ content })` oder das `load` Ihres eigenen `templates`-Providers, die Nahtstelle für „die Sprache dieses Templates kommt aus meiner Anwendung“. Für ein Template, das Sie **laden**, genügt [`templateDefaults`](/de/guide/defaults) dafür nicht: es greift nur, wenn kein Inhalt übergeben wird. Bei einem _leeren_ Template greift es, und für `locale` gibt es dort eine Abkürzung — `init({ locale })` setzt die Inhaltssprache, solange Sie kein `templateDefaults.locale` angeben, sodass auch bei ausgeblendetem Feld das richtige `<html lang>` entsteht.
- **Keine Sicherheitsgrenze.** Die Positivliste liegt im Browser des Nutzers, wie jede andere clientseitige Einschränkung. Prüfen Sie serverseitig, was Sie speichern.
- **Ohne `locale` ist auch die Sprache neuer Blöcke festgelegt.** Die `locale` eines Templates bestimmt die empfängerseitigen Standardwerte, mit denen ein neu eingefügter Block startet — das `alt` eines Videos, die Beschriftungen und die Ablaufmeldung eines Countdowns. Ohne das Feld folgen diese der Sprache, die der geladene Inhalt mitbringt, und der Autor kann sie nicht mehr ändern. Das ist meist genau die Absicht, bedeutet aber: der Wert, den Sie setzen, wirkt über `<html lang>` hinaus.
- **Ohne `preheaderText` bleibt eine Linter-Regel ohne Handlungsoption.** `a11y.missing-preheader` (Schweregrad `info`) meldet ein Template ohne Preheader, und ohne das Feld kann der Autor darauf nicht reagieren. Setzen Sie entweder einen Preheader im geladenen Inhalt oder schalten Sie die Regel ab: `lint: { accessibility: { rules: { 'a11y.missing-preheader': 'off' } } }`. Keine andere Regel liest eine Template-Einstellung.

::: tip Verwandte Einschränkungen
Andere Teile der Editor-Oberfläche haben eigene Schlüssel: [`paletteBlocks`](#block-palette-anpassen) für die Block-Palette, [`fonts.builtIns`](/de/guide/fonts) für die Schriftauswahl, [`colors.allowCustom`](#vordefinierte-farben) für freie Farbeingaben und `templates.nameField` für das Namensfeld in der Kopfzeile.
:::

## TemplaticalEditor

Das von `init()` zurückgegebene Objekt.

### `getContent()`

Gibt den aktuellen Template-Inhalt als `TemplateContent`-Objekt zurück.

```ts
const content = editor.getContent();
// { blocks: [...], settings: { width: 600, ... } }
```

### `setContent(content)`

Ersetzt den Editor-Inhalt durch eine Kopie von `content`; spätere Änderungen an Ihrem Objekt erreichen den Editor nicht.

```ts
import { createDefaultTemplateContent } from "@templatical/types";

editor.setContent(createDefaultTemplateContent());
```

### `insertBlock(block)`

Fügt einen Block dort ein, wo ein Klick auf ein Element der Block-Palette ihn platzieren würde: unter dem ausgewählten Block, in derselben Spalte, wenn die Auswahl in einer Section liegt (eine Section landet stattdessen nach dieser Section), oder am Ende, wenn nichts ausgewählt ist. Der neue Block wird ausgewählt und in den sichtbaren Bereich gescrollt, sodass der nächste Aufruf darunter einfügt. Verwenden Sie die Methode, um aus Ihrer eigenen Oberfläche einzufügen, etwa aus einer Bibliothek fertiger Sections.

```ts
import type { Block } from "@templatical/types";

// A section from your own library, saved earlier as editor JSON
// (for example, a block taken from `editor.getContent().blocks`).
const footer: Block = librarySections.footer;

footerButton.addEventListener("click", () => {
  editor.insertBlock(footer);
});
```

**Parameter:** `block: Block`

**Rückgabewert:** `string | null`, die ID des eingefügten Blocks, oder `null`, wenn die Instanz mit `unmount()` abgebaut oder durch einen späteren `init()`-Aufruf auf demselben Container ersetzt wurde, im Vorschaumodus (mit einer Warnung in der Konsole) oder wenn der Block nicht platziert werden kann.

Der Block wird so eingefügt, wie er übergeben wird. Ein Block aus der Block-Palette wird mit den Standardwerten des Editors erstellt: Ihren `blockDefaults`, lokalisierten Platzhaltertexten und rechtsbündigen Titeln und Tabellen in RTL-Templates. Diese werden hier nicht angewendet. Für fertige Inhalte ist das richtig, ein frisch mit `createTitleBlock()` erstellter Block kann aber anders aussehen als einer aus der Block-Palette.

Der Editor fügt eine Kopie mit neuen IDs ein, auch für die Kinder einer Section, sodass derselbe Block beliebig oft eingefügt werden kann. Suchen Sie den Block über die zurückgegebene ID, nicht über `block.id`. Merge-Tags, die als reine Tokens im Text stehen, werden genauso umgewandelt wie bei `setContent`. Ein Slot- oder Wrapper-Block löst einen Fehler aus, wie bei `setContent`.

### `setTheme(theme)`

Wechselt das UI-Farbschema zur Laufzeit, ohne den Editor neu zu initialisieren.

```ts
editor.setTheme("dark");
editor.setTheme("light");
editor.setTheme("auto"); // follow system preference
```

**Parameter:** `theme: 'light' | 'dark' | 'auto'`

### `setMergeTags(tags)`

Ersetzt die konfigurierten Merge-Tags zur Laufzeit. Canvas, Felder der Seitenleiste und der integrierte Picker lesen dieselbe Liste und werden gemeinsam neu gezeichnet.

```ts
editor.setMergeTags([
  { label: 'First Name', value: '{{first_name}}' },
  { label: 'Plan', value: '{{plan_name}}' },
]);
```

**Parameter:** `tags: MergeTag[]`

Verwenden Sie die Methode, wenn Tags erzeugt oder umbenannt werden, während der Editor geöffnet ist. Das an `init()` übergebene Array zu mutieren ist kein unterstützter Ersatz — es zeichnet nichts neu, was bereits sichtbar ist. Siehe [Merge-Tags](/de/guide/merge-tags) für die eine Einschränkung bei der Autovervollständigung.

### `unmount()`

Zerstört diese Editor-Instanz und keine andere. Hat ein späteres `init()` auf demselben Container sie bereits ersetzt oder ihr Mounten verhindert, bewirkt das `unmount()` der alten Instanz nichts.

### `create(input?)` / `load(id)` / `save()`

Der Speicher-/Ladezyklus der Vorlage, über den `templates`-Provider.

```ts
const template = await editor.create({ name: "Welcome email" });
await editor.load(template.id);
await editor.save();
```

- **`create(input?)`** speichert den aktuellen Inhalt als neue Vorlage und übernimmt das Ergebnis. Übergeben Sie `content`, um zuvor den Inhalt des Editors zu ersetzen.
- **`load(id)`** holt eine Vorlage und macht sie zum Inhalt des Editors; lokale Änderungen werden verworfen.
- **`save()`** speichert Name und Inhalt der geladenen Vorlage als einen Patch.

Alle drei geben ein `Promise<Template>` zurück und sind stets im Typ vorhanden. Sie werden mit einer erklärenden Fehlermeldung abgelehnt, wenn kein `templates`-Provider konfiguriert ist, wenn der Provider die jeweilige Methode zurückhält (`create: false` / `save: false`) oder — bei `save()` — wenn noch nichts erstellt oder geladen wurde. Siehe [Speichern & Laden](/de/backend/templates).

### `isDirty()`

Ob es Änderungen gibt, von denen der Editor weiß, dass sie nicht gespeichert sind. Wird durch ein erfolgreiches `save()`, `create()` oder `load()` zurückgesetzt.

```ts
router.beforeEach((to, from, next) => {
  if (editor.isDirty() && !confirm("Discard unsaved changes?"))
    return next(false);
  next();
});
```

`onDirtyChange` ist das gegenläufige Push-Pendant.

### `getLocale()` / `setLocale(locale)`

`getLocale(): string` liefert die aktive Template-Sprache, anfangs den Standard. `setLocale(locale: string): void` wählt bei aktivierter Lokalisierung den Standard oder eine vorhandene Version; eine unbekannte Version wirft `SdkError` mit Code `unknown_locale`. Eine gespeicherte Version außerhalb von `localization.locales` bleibt auswählbar, aber schreibgeschützt (**Nicht aktiviert**); Wert- und Strukturänderungen werden abgelehnt. Siehe [Eine Sprache hinzufügen](/de/guide/localized-templates#eine-sprache-hinzufugen).

`toMjml(options?: { locale?: string }): Promise<string>` und `toHtml(options?: { locale?: string }): Promise<string>` rendern die ausgewählte Version, etwa `editor.toMjml({ locale: "de" })`. Ohne `locale` gilt der Standard, unabhängig von der aktiven Ansicht. Unbekannte Versionen lehnen mit `unknown_locale` ab. Render-Provider erhalten den projizierten Inhalt ohne Lokalisierungsfelder.

### `toMjml(options?)`

Rendert den aktuellen Inhalt in MJML-Markup. Gibt ein `Promise<string>` zurück, da das Auflösen benutzerdefinierter Blöcke asynchrone Arbeit erfordern kann (der Liquid-Renderer des Editors wird bei Bedarf geladen).

```ts
const mjml = await editor.toMjml();
```

Löst zuerst `render.toMjml` auf, wenn ein [`render`-Provider](/de/backend/render) es bereitstellt, danach den lokalen `@templatical/renderer`. Lehnt mit einem klaren Fehler ab, wenn keines von beiden verfügbar ist — der Renderer ist eine optionale Peer-Abhängigkeit, installieren Sie ihn also für lokalen MJML-Export. Siehe [Installation](/de/getting-started/installation).

### `toHtml(options?)`

Rendert den aktuellen Inhalt in versandfertiges HTML.

```ts
const html = await editor.toHtml();
```

Löst zuerst `render.toHtml` auf, danach die Ausgabe von `toMjml()` über `render.compileMjml`. **Eines von beiden ist erforderlich**: Das SDK bündelt keinen MJML-Compiler, ohne `render`-Provider lehnt dieser Aufruf also immer ab, und der Fehler nennt die zu ergänzende Methode. Siehe [Rendering & Export](/de/backend/render).

::: tip Cloud-Editor
Der Cloud-Editor stellt **beide** Methoden bereit, aufgelöst über Clouds serverseitigen Renderer (oder Ihren eigenen `render`-Provider). Beachten Sie: Cloud rendert das _gespeicherte_ Template, jeder Aufruf speichert also zuerst.
:::

### `renderCustomBlock(block)`

Rendert einen einzelnen benutzerdefinierten Block in seine HTML-Darstellung. Nützlich für Headless-Aufrufer, die `@templatical/renderer`s `renderCustomBlock`-Option von außerhalb der Editor-Instanz steuern möchten – etwa beim direkten Aufruf des Renderers mit eigener Konfiguration.

```ts
const html = await editor.renderCustomBlock(customBlock);
```

### `getCustomBlockStylesheet(customType)`

Gibt das auf Definitionsebene registrierte CSS eines Custom-Block-Typs zurück — oder `undefined`, wenn der Typ unbekannt ist oder kein Stylesheet hat. Das Gegenstück zu `renderCustomBlock()` für Headless-Aufrufe, die die Option `getCustomBlockStylesheet` von `@templatical/renderer` selbst bedienen.

```ts
const css = editor.getCustomBlockStylesheet("qrcode");
```

## KI-Regellisten

`@templatical/editor` exportiert `AI_FIXABLE_RULES` und `AI_ALT_TEXT_RULES` als schreibgeschützte Tupel von Lint-Regel-IDs. `AI_FIXABLE_RULES` benennt die Regeln für [Mit KI beheben](/de/backend/ai#mit-ki-beheben); `AI_ALT_TEXT_RULES` benennt die Bildregeln für Alt-Text. Die Konstante allein aktiviert keine Alt-Text-Oberfläche. Die [Qualitätsdokumentation](/de/quality/) beschreibt die Befunde.

## Core-Composables

Für fortgeschrittene Anwendungsfälle können Sie die Composables aus `@templatical/core` direkt verwenden.

### `useEditor(options)`

Das Kern-Composable, das den gesamten Editor-Zustand verwaltet: den Block-Baum, Template-Einstellungen, Block-Auswahl, Viewport-Modus sowie alle Mutationsmethoden. Dies ist das, was `init()` intern verwendet. Verwenden Sie es direkt, wenn Sie eine vollständig benutzerdefinierte Editor-Oberfläche auf der Templatical-State-Engine aufbauen.

```ts
import { useEditor } from "@templatical/core";

const editor = useEditor({ content: templateContent });

editor.selectBlock(blockId);
editor.updateBlock(blockId, { content: "New text" });
editor.setViewport("mobile");
```

### `useHistory(options)`

Verfolgt Inhalts-Snapshots und stellt Undo/Redo bereit. Wird mit der Content-Ref des Editors verbunden und erfasst den Zustand nach jeder Mutation. Eine konfigurierbare maximale Verlaufsgröße verhindert unbegrenztes Speicherwachstum.

```ts
import { useHistory } from "@templatical/core";

const history = useHistory({
  content: editor.content,
  setContent: editor.setContent,
  maxSize: 50,
});

history.undo();
history.redo();
```

### `useCollaboration(options)`

Führt eine Collaboration-Sitzung über einen [`CollaborationProvider`](/de/backend/collaboration): Sie schickt die Änderungen des Editors als Operations-Batches, wendet die Batches anderer Sitzungen in Revisionsreihenfolge an, nimmt die Sperre des ausgewählten Blocks, verfolgt, wer da ist, und führt Rückgängig und Wiederholen als umgekehrte Batches. `init({ collaboration })` erstellt sie für Sie; rufen Sie sie nur selbst auf, wenn Sie einen eigenen Editor auf `useEditor` bauen.

```ts
import { useCollaboration, useEditor } from "@templatical/core";

const collaboration = useCollaboration({
  provider: myCollaborationProvider,
  loadTemplate: (id) => myTemplatesProvider.load(id),
  onNotice: (notice) => showNotice(notice),
});
const editor = useEditor({
  content,
  templates: myTemplatesProvider,
  lockedBlocks: collaboration.locks,
});
collaboration.attach(editor);
await editor.load("tpl_123");

collaboration.undo();
await collaboration.settle(); // resolves once every batch is confirmed
```

### `useBlockActions(options)`

Komfortmethoden auf höherer Ebene für gängige Block-Operationen: einen Block erstellen und in einem Schritt einfügen, einen bestehenden Block duplizieren (Deep Clone mit neuer ID) und Löschen mit automatischer Auswahl-Bereinigung.

```ts
import { useBlockActions } from "@templatical/core";

const actions = useBlockActions({
  addBlock: editor.addBlock,
  removeBlock: editor.removeBlock,
  updateBlock: editor.updateBlock,
  selectBlock: editor.selectBlock,
});

const newBlock = actions.createAndAddBlock("paragraph");
actions.duplicateBlock(existingBlock);
actions.deleteBlock(blockId);
actions.updateBlockProperty(blockId, "content", "<p>Updated</p>");
```

### `useAutoSave(options)`

Überwacht den Editor-Inhalt und ruft Ihren Speicher-Callback mit konfigurierbarer Entprellung (Debounce) auf. Enthält Pause/Resume zum vorübergehenden Deaktivieren von Speichervorgängen (z. B. während Massenoperationen) sowie eine `flush()`-Methode für sofortiges Speichern.

```ts
import { useAutoSave } from "@templatical/core";

const autoSave = useAutoSave({
  content: editor.content,
  isDirty: () => editor.state.isDirty,
  onChange: (content) => saveToServer(content),
  debounce: 2000, // the default
  enabled: true, // boolean or () => boolean
});

autoSave.flush(); // Save immediately
autoSave.cancel(); // Cancel pending debounced save
autoSave.pause(); // Pause auto-save
autoSave.resume(); // Resume
autoSave.destroy(); // Stop watching and clean up
```

### `useConditionPreview()`

Verwaltet den Vorschauzustand für Anzeigebedingungen im Editor. Ermöglicht das Ein-/Ausschalten einzelner Blöcke, um zu simulieren, wie bedingter Inhalt aussieht, wenn unterschiedliche Bedingungen erfüllt sind.

```ts
import { useConditionPreview } from "@templatical/core";

const preview = useConditionPreview(editor);

preview.isHidden(blockId); // Check if a block is hidden in preview
preview.toggleBlock(blockId); // Toggle a block's visibility
preview.reset(); // Reset all blocks to visible
preview.hasHiddenBlocks; // ComputedRef<boolean>
```

### `useDataSourceFetch(options)`

Übernimmt das Abrufen externer Daten für benutzerdefinierte Blöcke mit Datenquellen. Verwaltet den Ladezustand und die Fehlerbehandlung für den `onFetch`-Callback.

```ts
import { useDataSourceFetch } from "@templatical/core";

const dataFetch = useDataSourceFetch({
  definition: computed(() => customBlockDefinition),
  block: computed(() => customBlock),
  onUpdate: (fieldValues, fetched) => {
    updateBlock(block.id, { fieldValues, dataSourceFetched: fetched });
  },
});

dataFetch.isFetching; // Ref<boolean>
dataFetch.fetchError; // Ref<boolean>
dataFetch.hasDataSource; // ComputedRef<boolean>
dataFetch.needsFetch; // ComputedRef<boolean>
await dataFetch.fetch(); // Trigger the fetch
```
