Embedding guide
The core API separates the spreadsheet surface from the surrounding application. The host, or embedding application, chooses the visible UI, the cells that may be edited, the placement of floating UI, and the lifecycle of the workbook. Choose ui.platform independently from ui.profile; Platform and Mac UI describes the Mac ribbon and its supported dialogs.
Before mounting, import the package stylesheet and give the host a height. See Install for the CSS import, sizing example, and disposal contract.
const instance = await Spreadsheet.mount(host, {
workbook,
ui: { profile: 'standard', theme: 'paper' },
policy,
viewport,
contextMenu,
overlays
})The address types used in these options are zero-based. A cell is { sheet, row, col }; a range is { sheet, r0, c0, r1, c1 }, with both ends included.
Use case: report viewer
For a report page, keep the grid compact and make every mutation unavailable:
import {
Spreadsheet,
viewerPolicy,
WorkbookHandle
} from '@libraz/formulon-cell'
import '@libraz/formulon-cell/styles.css'
const workbook = await WorkbookHandle.loadBytes(reportBytes)
const instance = await Spreadsheet.mount(host, {
workbook,
ui: {
profile: 'embedded',
theme: 'paper',
features: { clipboard: true, shortcuts: true }
},
toolbar: false,
policy: viewerPolicy(),
viewport: {
range: { sheet: 0, r0: 0, c0: 0, r1: 40, c1: 8 },
tabBoundary: 'stop'
},
contextMenu: { mode: 'disabled' }
})viewerPolicy() keeps selection and copying available while blocking editing. The host can still provide its own export or navigation buttons around the grid.
Read-only report viewer
A bounded report embed that allows selection and copying while blocking edits.
Powered by the real Formulon engine (WASM) — it runs entirely in your browser, nothing is uploaded.
Use case: fixed-input form
For a form, declare the input cells and guide Tab through them:
import {
fixedFormPolicy,
Spreadsheet,
WorkbookHandle
} from '@libraz/formulon-cell'
const workbook = await WorkbookHandle.createDefault()
const instance = await Spreadsheet.mount(host, {
workbook,
ui: {
profile: 'embedded',
features: { clipboard: true, shortcuts: true }
},
policy: fixedFormPolicy([
{ sheet: 0, r0: 2, c0: 1, r1: 20, c1: 3 }
]),
viewport: {
range: { sheet: 0, r0: 0, c0: 0, r1: 24, c1: 5 },
tabNavigation: 'editable',
tabBoundary: 'stop'
}
})
// Host-owned prefill or refresh. This is not a user editing command.
instance.applyChanges([
{ addr: { sheet: 0, row: 2, col: 1 }, input: 'Ada Lovelace' }
])fixedFormPolicy() accepts a range list, an EditableCells predicate, or an object containing ranges or predicate. The helper allows value entry, clearing, paste, and fill in the declared cells. Use an explicit InteractionPolicy when the form needs a different set of operations; Options lists the fields and explains how a policy also limits the built-in UI.
Fixed-input form
Only B2:C4 accepts edits. The totals in column D are real formulas and recalculate live.
Powered by the real Formulon engine (WASM) — it runs entirely in your browser, nothing is uploaded.
Host-owned updates and user commands
instance.applyChanges() is a trusted host update. It is useful for prefilled values, server refreshes, and imports that the host has authorized. It addresses the workbook, including cells outside the current viewport, and the default history mode resets user history after a successful update.
Use instance.commands.execute() for user cell edits that must follow the active interaction policy. Check each low-level helper's contract: direct store or workbook mutations require host authorization, while helpers routed through the interaction controller enforce its policy. The Mac ribbon actions for Goal Seek, Consolidate, and Subtotal authorize changes through the instance before applying them. If a host update should be recorded as an undoable operation, pass history: 'record' and handle a rejected ChangeBatchResult:
const result = instance.applyChanges(
[{ addr: { sheet: 0, row: 4, col: 2 }, input: 'Approved' }],
{ history: 'record', origin: 'server-refresh' }
)
if (result.status === 'rejected') showUpdateError(result.rejected)Use case: host-owned toolbar and menu
Start with a small UI profile and let the application own the surrounding controls:
import {
presets,
Spreadsheet
} from '@libraz/formulon-cell'
const instance = await Spreadsheet.mount(host, {
workbook,
features: presets.minimal(),
toolbar: false,
contextMenu: {
mode: 'host',
onOpen: ({ cell, selection, permission }) => {
openCellMenu({
cell,
selection,
canEdit: permission({
operation: 'valueEdit',
origin: 'contextMenu',
effects: [{ kind: 'cells', cells: [cell] }]
}).allowed
})
}
}
})The host context-menu mode suppresses the browser and built-in menu and hands the current cell, selection, and permission query to the application. A host menu can call a public command helper or open a host modal.
For a built-in menu with one host action, use mode: 'builtIn' and a transform callback to change the current item snapshot:
import type { ContextMenuOptions } from '@libraz/formulon-cell'
const contextMenu: ContextMenuOptions = {
mode: 'builtIn',
transform: ({ defaultItems }) => [
...defaultItems,
{
id: 'host:details',
label: 'Open details',
action: ({ cell }) => openDetails(cell)
}
]
}Use { mode: 'disabled' } when the host supplies another interaction surface or when a compact viewer should have no right-click menu.
Runtime changes and lifecycle
Every option above can change after mount without replacing the workbook, for example instance.setPolicy(viewerPolicy()) when a user's role changes. The setters are listed in Options.
Keep the instance and the workbook under the same view owner and dispose both when the view is removed:
const instance = await Spreadsheet.mount(host, { workbook })
function closeView() {
instance.dispose()
workbook.dispose()
}For asynchronous mounts, keep the unmount path safe when initialization rejects. Install explains which workbook the instance disposes for you; React and Vue adapters dispose the instance with the component.