## dev-21.0.0 Formatting commands

New / expanded commands:

- `spread.format.font` with `{ value: 'Arial' }`
- `spread.format.fontSize` with `{ value: '12' }`
- `spread.format.border`, `spread.format.border.all`, `spread.format.border.outer`, `spread.format.border.inner`, `spread.format.border.top`, `spread.format.border.right`, `spread.format.border.bottom`, `spread.format.border.left`, `spread.format.border.clear`
- `spread.format.valignTop`, `spread.format.valignMiddle`, `spread.format.valignBottom`
- `spread.format.indent.increase`, `spread.format.indent.decrease`, `spread.format.shrink`
- `spread.format.style.normal`, `spread.format.style.header`, `spread.format.style.input`, `spread.format.style.good`, `spread.format.style.warning`, `spread.format.style.bad`
- `spread.format.conditional.greaterThan`, `spread.format.conditional.lessThan`, `spread.format.conditional.clear`

Style metadata is persisted in the workbook as `sheet.styles`; conditional rules are persisted in `sheet.config.conditionalFormats`.

## dev-20.7.0 command additions

- `spread.edit.fillDown` - copy the top row of the selected range downward.
- `spread.edit.fillRight` - copy the left-most column of the selected range to the right.
- `spread.edit.fillHandle` - internal command emitted by the renderer with `{ sourceRange, targetRange }`. Host integrations may call it when they provide equivalent UI.

# API

Entry: `scripts/main.js`

```js
require(['UnifiedSpread/main'], function (UnifiedSpread) {
  const control = UnifiedSpread.createWorkbenchControl({ container: '#target' });
  control.mount();
  control.exec('spread.file.open');
});
```

## Commands added/implemented by dev-20.5.1

- `spread.view.freeze.row`
- `spread.view.freeze.col`
- `spread.view.freeze.current`
- `spread.view.freeze.clear`
- `spread.data.filter.apply`
- `spread.data.filter.clear`
- `spread.data.sort.asc`
- `spread.data.sort.desc`
- `spread.insert.sheet`
- `spread.format.merge`
- `spread.file.export.csv`

Formula bar synchronization is wired to `#nameBox` and `#formulaInput` in the demo shell. The NameBox is editable in the demo and accepts A1/range notation.


## Interaction behavior added by dev-20.5.2

- Cell mouse drag selects a range and emits `selectionChanged`.
- Row and column header resize handles now commit workbook size changes only on mouseup.
- Host code continues to consume semantic state through Control / Command APIs; raw pointer events are not part of the public API.

## dev-20.6.0 command additions

- `spread.format.number` with payload `{ value: 'General' | '0' | '0.00' | 'yyyy-mm-dd' | '#,##0' | '0%' }`
- `spread.format.fontSize` with payload `{ value: '9' | '10' | '11' | '12' | '14' | '18' }`
- `spread.format.border`
- `spread.sheet.duplicate`
- `spread.sheet.delete`
- `spread.sheet.moveLeft`
- `spread.sheet.moveRight`

Toolbar state is emitted through `unifiedspread.format.selectionChanged` with a style snapshot derived from the active selection.


## Formula Engine API additions in dev-21.0.0

Commands exposed through CommandRegistry / Host `exec()` path:

- `spread.formula.recalculate`: recalculates formula display results on demand.
- `spread.formula.dependencyGraph`: builds and returns the current dependency graph.
- `spread.data.namedRange.define`: defines a workbook-level named range from the current selection.

Formula expressions support basic arithmetic, A1 ranges, cross-sheet references, named ranges and the function groups documented in `FORMULA_ENGINE_FOUNDATION.md`.

## Formula reference editing note
While the Formula Bar or in-cell editor contains a formula beginning with `=`, grid clicks are interpreted as reference picks. The committed formula is written back to the originally edited cell.


## Data Tools commands added in dev-21.5.0

All commands are routed through the shared CommandRegistry / CommandRouter path and can be called from Host `control.exec()` where supported by the host wrapper.

- `spread.data.sort.multi` - sort the selected range by selected columns from left to right.
- `spread.data.filter.nonBlank` - filter selected column to non-empty values.
- `spread.data.filter.blank` - filter selected column to empty values.
- `spread.data.filter.textContains` - apply text contains criteria; payload may pass `value`.
- `spread.data.filter.numberGreaterThan` - apply numeric greater-than criteria; payload may pass `value`.
- `spread.data.filter.numberBetween` - apply numeric between criteria; payload may pass `min` and `max`.
- `spread.data.removeDuplicates` - remove duplicate rows within the selected range, preserving the first row as header.
- `spread.data.splitText.comma` / `spread.data.splitText.tab` - split the left-most selected column into adjacent columns.
- `spread.data.validation.list` - add Yes / No / Pending list validation to the selected range.
- `spread.data.validation.numberBetween` - add 0-100 numeric validation to the selected range.
- `spread.data.validation.clear` - remove validation rules that intersect the selected range.

## dev-22.0.0 Object Layer Commands

The following commands are available through Menu / Toolbar / ContextMenu / Host `control.exec()`:

- `spread.insert.chart` - Insert a column chart preview from the current selected range.
- `spread.insert.chart.line` - Insert a line chart preview foundation command.
- `spread.insert.image` - Insert an image placeholder object.
- `spread.insert.textBox` - Insert a floating text box object.
- `spread.insert.shape` - Insert a simple shape placeholder.
- `spread.object.duplicate` - Duplicate the selected floating object.
- `spread.object.delete` - Delete the selected floating object.

Floating objects are persisted under `sheet.objects[]` in the workbook model and native `.uspdx` package.


## dev-22.0.1 note
No public Control API change. The fix is limited to Demo layout CSS/JS and shell-safe sizing behavior.

## dev-24.0.0 Object UX Commands

Additional object commands exposed through CommandRegistry / CommandRouter / Host command path:

- `spread.insert.image` - request an image asset from Host `OpenFile` and insert it as a floating image object.
- `spread.insert.image.placeholder` - insert an image placeholder without file selection.
- `spread.object.chart.refresh` - rebuild the selected chart snapshot from its stored source range.
- `spread.object.chart.column` - switch the selected chart to column preview.
- `spread.object.chart.line` - switch the selected chart to line preview.
- `spread.object.bringForward` / `spread.object.sendBackward` - move object one z step.
- `spread.object.bringToFront` / `spread.object.sendToBack` - move object to top/bottom z order.
- `spread.object.lock.toggle` - lock or unlock object geometry editing.
- `spread.object.nudge` - internal keyboard command with `{ dx, dy }`.

Double-clicking a TextBox starts inline text editing. Image insertion follows the single-file app policy and requires Host-provided `OpenFile` callback behavior.


## dev-24.9.1 Product Quality Commands

- `spread.file.properties` returns a summary of the current workbook/file context.
- `spread.tools.compat` returns a compatibility report covering XLSX round-trip bridge, native package security, CSV guard, objects, comments and protected ranges.

## Runtime Regression Smoke Service

`UnifiedSpread/services/regression_test_service` exposes `run(control)` and `formatText(results)` for Demo/Host smoke tests through the public Control API.

## Scripting API (dev-31.0.0)

UnifiedSpread includes a browser-safe script engine. Scripts are JavaScript-syntax
modules saved in `workbook.config.scripting.modules`. Runtime access is limited
to injected `api`, `workbook`, `console` and `ui` objects.

### Commands

- `spread.script.report` - returns scripting summary.
- `spread.script.module.sample` - creates a sample UnifiedSpread Script module.
- `spread.script.run.first` - runs the first workbook script module, creating a sample if needed.
- `spread.script.run.sample` - creates and runs the sample script.
- `spread.vba.transpile.sample` - converts a sample VBA module into UnifiedSpread Script.
- `spread.vba.compat.report` - returns the current scripting/VBA compatibility summary.

### Script API example

```javascript
const sheet = api.activeSheet();
sheet.range("A1:B3").values([["Item", "Amount"], ["Apple", 120], ["Orange", 80]]);
sheet.cell(4, 1).value("Total");
sheet.cell(4, 2).formula("SUM(B2:B3)");
```

Unsupported browser-hostile VBA constructs such as COM, Shell, Win32 API and
direct file-system access are intentionally excluded.


## dev-31.0.6 Policy v1.8 / Single-file v1.2 integration APIs

UnifiedSpread exposes two creation entries from `scripts/main.js`:

```javascript
UnifiedSpread.createWorkbenchControl(options); // composite menu/toolbar/formula/status UI
UnifiedSpread.createEditorControl(options);    // Host-composed editor surface
```

The public command prefix is `spread`. Unprefixed historical IDs are intentionally rejected in this development build.

```javascript
control.exec('spread.file.open');
```

New Host-facing descriptor APIs:

```javascript
control.getCommandRegistry();
control.getCommandDescriptors();
control.getMenuContributions({ surface: 'oneEditor' });
control.getToolbarContributions({ surface: 'oneEditor' });
control.getContextMenuContributions();
control.getFileCapabilities();
```

`getMenuContributions({ surface: 'oneEditor' })` omits the File menu by default because a OneEditor-style Host owns the File menu UI. Workbench use includes the File menu.


## EditorControl Programable File API (Single File Policy v1.3)

UnifiedSpread EditorControl exposes the following standard methods for Host / WorkbenchControl / OneEditor integration.

```javascript
control.openFile(hostFilePayload, context);
control.saveFile(hostSavePayload, context);
control.saveAsFile(hostSavePayload, context);
control.exportFile(hostSavePayload, context);
control.getFileContext();
control.getFileCapabilities();
```

`openFile(payload, context)` consumes `HostFilePayload/v1` and replaces the current workbook. The payload may contain `file`, `blob`, `arrayBuffer`, or `text` plus `fileName`, `mimeType`, `size`, `lastModified`, and optional `handle`.

`saveFile`, `saveAsFile`, and `exportFile` return a Promise resolving to `HostSavePayload/v1`. The generated data is stored in `payload.data`; for browser compatibility the same Blob is also exposed as `payload.blob`.

WorkbenchControl commands keep the callback direction separate: `OpenFile` / `SaveFile` callbacks are Workbench/Package -> Host, while the methods above are Host/Workbench -> EditorControl.
