# UnifiedWriter Public API Contract

## AMD entry

```js
require(['UnifiedWriter/main'], function(UnifiedWriter){
  const control = UnifiedWriter.createControl(options);
const editor = UnifiedWriter.createEditorControl({ container:'#frame', mode:'edit' });
const viewer = UnifiedWriter.createEditorControl({ container:'#frame', mode:'view', readOnly:true });
const workbench = UnifiedWriter.createWorkbenchControl({ container:'#frame', mode:'edit' });
});
```

## Control API

- `mount()`
- `destroy()`
- `exec(commandId, payload)`
- `on(eventName, handler)`
- `off(eventName, handler)`
- `getState()`
- `setOptions(options)`
- `getContext()`

- `getCommandRegistry(options)`
- `getHostCommandRegistry()`
- `getMenuContributions(options)`
- `getToolbarContributions(options)`
- `getContextMenuContributions(options)`
- `getImportCapabilities()`
- `getExportCapabilities()`
- `getFileCapabilities()`
- `getControlVariantContract()`

## Commands

- `newFile`
- `open`
- `save`
- `saveAs`
- `importFile`
- `exportAs`
- `showFileProperties`
- `toggleToolbar`
- `toggleLeftPane`
- `toggleRightPane`
- `toggleStatusbar`

Compatibility aliases such as `file:open`, `file:save`, `view:preview` are also registered.

## Events

- `beforeCommand`
- `afterCommand`
- `commandError`
- `fileOpened`
- `fileSaved`
- `fileImported`
- `fileExported`

## File callbacks

See `docs/FILE_IO_POLICY.md`.

## View/readOnly mode command guard

When a Control is created with `mode: "view"` or `readOnly: true`, mutation commands are filtered from contributions and guarded at `exec()`. Examples such as `writer.format.bold`, `writer.insert.image`, and legacy `bold` are rejected with `commandError`. View-safe commands such as `writer.file.openPackage`, `writer.file.export`, `writer.file.printContent`, `writer.file.properties`, and `writer.edit.findReplace` remain available.

## File capability registry

`getFileCapabilities()` returns readable, writable, export, and template format metadata so OneEditor / OneViewer or another Host surface can build New/Open/Save/Export UI without hard-coding UnifiedWriter formats.

## v5.66.1 Control Framework contract

UnifiedWriter public Controls are UnifiedControl Framework subclasses.

| Class | File | Base | Purpose |
|---|---|---|---|
| `EditorControl` | `scripts/controls/editor_control.js` | `UnifiedControl.Control` | Body Control for edit and view/readOnly mode. |
| `WorkbenchControl` | `scripts/controls/workbench_control.js` | `UnifiedControl.Control` through `EditorControl` | Composite surface that adds package MenuBar / Toolbar / panes / status bar. |

Required peer dependency:

```json
{
  "requiredPackages": {
    "UnifiedControl": {
      "apiVersion": ">=0.7 <1.0",
      "publicEntry": "scripts/main.js",
      "required": true
    }
  }
}
```

The required Host-facing methods are available from the Control classes: `mount`, `destroy`, `exec`, `on`, `off`, `getState`, `setState`, `dialog`, `getCommandRegistry`, `getCommandContributions`, `getMenuContributions`, `getToolbarContributions`, `getContextMenuContributions`, and `getFileCapabilities`.

The current document engine remains behind `scripts/controls/legacy_runtime.js`; Host integrations must treat it as internal migration code and must not call it directly.


## v5.66.3 UnifiedControl direct base Control import
UnifiedWriter still treats UnifiedControl as a peer package referenced by package root URL and does not copy it into the Writer ZIP. To avoid loading optional UnifiedControl Content/Designer modules during app boot, EditorControl imports the required base class from `UnifiedControl/controls/control` rather than `UnifiedControl/main`. Host/Demo RequireJS aliases remain the same: `UnifiedControl` points to `<UnifiedControl package root>/scripts` and `UnifiedWriter` points to `<UnifiedWriter package root>/scripts`.


## v5.67.0 EditorControl Programable File API

`EditorControl` exposes `openFile(payload, context)`, `saveFile(payload, context)`, `saveAsFile(payload, context)`, `exportFile(payload, context)`, and `getFileContext()`. `openFile` accepts `HostFilePayload/v1`. Save/export APIs return `HostSavePayload/v1` with generated data in `payload.data`.


## v5.67.1 Demo File Save Policy Alignment

Demo SaveFile callbacks now follow the single-file policy v1.3 direction split: Workbench/Command obtains or generates a HostSavePayload/v1 with payload.data, then the Demo Host SaveFile callback writes that data by using a local-device download adapter. Demo code does not mark App Storage as the user-facing save destination and does not save without payload.data. Save As dialogs use the package overlay class `uwriter-floating-ui` so file-save UI remains scoped under the v1.10 CSS/Theme contract.
