FortuneSheetAdapter
Costruttore
class FortuneSheetAdapter implements IFortuneSheetAdapter {
constructor()
}
Adapter Strategy che è l'unico punto di contatto tra la libreria e @fortune-sheet/core. Tutti i componenti e composables comunicano con il workbook solo tramite questa interfaccia.
FortuneSheetSnapshot (blob opaco), CellValue (primitivi) e SpreadsheetChangeEvent. Nessuna dipendenza diretta su tipi/API di Fortune Sheet. Questo permette test isolati e potenziale sostituzione dell'engine.Interfaccia IFortuneSheetAdapter
interface IFortuneSheetAdapter {
// Lifecycle
initialize(container: HTMLElement): Promise<void>
destroy(): void
// Snapshot I/O
loadSnapshot(snapshot: FortuneSheetSnapshot | null): void
getSnapshot(): FortuneSheetSnapshot
// Celle
getCellValue(row: number, col: number, sheetIndex?: number): CellValue
setCellValue(row: number, col: number, value: CellValue, sheetIndex?: number): void
setCellError(row: number, col: number, errorCode: string, sheetIndex?: number): void
setRange(startRow: number, startCol: number, data: CellValue[][], sheetIndex?: number): void
// Undo/Redo
undo(): void
redo(): void
canUndo(): boolean
canRedo(): boolean
// Funzioni custom ERP
registerCustomFunctions(functions: ErpFormulaFunction[]): void
// Eventi
onChange(handler: (event: SpreadsheetChangeEvent) => void): void
offChange(): void
}
Lifecycle
initialize(container)
Istanzia un'app Vue contenente FortuneSheetWorkbook e la monta nel container DOM fornito.
const adapter = new FortuneSheetAdapter()
const containerEl = document.querySelector('#workbook-container')
await adapter.initialize(containerEl)
initialize() lancia errore. Per re-mount, chiamare destroy() prima.destroy()
Smonta l'app Vue interna e rilascia riferimenti. Da chiamare in onUnmounted o quando si vuole ri-inizializzare l'adapter.
Snapshot I/O
loadSnapshot(snapshot)
Carica un snapshot JSONB nell'editor. Se snapshot === null, crea un workbook vuoto con un solo tab.
const versione = await fogliService.caricaUltimaVersione(42)
adapter.loadSnapshot(versione?.snapshot ?? null)
Pre-buffering: se loadSnapshot è chiamato prima di initialize, il valore viene memorizzato in pendingSnapshot e applicato al mount del workbook.
getSnapshot()
Estrae lo snapshot corrente in formato Fortune Sheet:
const snapshot = adapter.getSnapshot()
// → Record<string, unknown> — blob opaco da persistere
Usato da useSpreadsheet.save() per ottenere il payload da inviare a salvaVersione.
API celle
const v: CellValue = adapter.getCellValue(0, 0) // riga 0, col 0, foglio 0
adapter.setCellValue(0, 0, 'Ciao')
adapter.setCellValue(0, 1, 42)
adapter.setCellValue(1, 0, true, 1) // foglio 1
CellValue è string | number | boolean | null.
setRange(startRow, startCol, data, sheetIndex?)
Scrive un blocco di celle a partire da (startRow, startCol):
adapter.setRange(0, 0, [
['Codice', 'Nome', 'Imponibile'],
['F001', 'Cliente A', 1234.56],
['F002', 'Cliente B', 987.65],
])
Usato da useSpreadsheetERP per scrivere risultati di una sorgente nelle celle target.
setCellError(row, col, errorCode, sheetIndex?)
Scrive un errore visivo nella cella (es. #ERP_ERR):
adapter.setCellError(0, 0, '#ERP_ERR_FATTURE')
Usato per segnalare errori di fetch ERP senza interrompere il workbook.
Undo/Redo
if (adapter.canUndo()) adapter.undo()
if (adapter.canRedo()) adapter.redo()
Sfruttano lo stack di history di Fortune Sheet. Non richiedono interazione col DB: undo/redo agiscono solo localmente fino al prossimo save().
Funzioni custom ERP
registerCustomFunctions(functions)
Registra funzioni formula ERP-native nel motore di Fortune Sheet:
interface ErpFormulaFunction {
name: string // es. 'ERP.FATTURATO'
handler: (...args: (string | number | null)[]) => Promise<number | string>
}
import { erpFunctions } from '@pzeta/vue-foglidicalcolo/erp-functions'
adapter.registerCustomFunctions(erpFunctions)
Una volta registrate, le funzioni sono disponibili come formule:
=ERP.FATTURATO("V"; "2026-01-01"; "2026-12-31"; 42)
erpFunctions sono placeholder (lanciano Not implemented). Il consumer deve fornire implementazioni concrete. Vedi erp-functions.initialize(). La registrazione multipla può causare doppi handler.Eventi
onChange(handler)
Registra una callback chiamata ad ogni modifica cella, debounced 500ms internamente:
adapter.onChange((event) => {
console.log(`Cella (${event.row}, ${event.col}) modificata: ${event.value}`)
console.log(`Foglio ${event.sheetIndex}, dirty: ${event.isDirty}`)
})
interface SpreadsheetChangeEvent {
sheetIndex: number
row: number
col: number
value: CellValue
isDirty: boolean
}
useSpreadsheet/SpreadsheetEditor usano questa callback per:
- aggiornare
isDirty.value = true - emettere l'evento
changeverso il consumer
offChange()
Rimuove il handler registrato. Chiamare in onUnmounted per evitare leak.
Esempio standalone
import { FortuneSheetAdapter, erpFunctions } from '@pzeta/vue-foglidicalcolo'
const adapter = new FortuneSheetAdapter()
const container = document.getElementById('workbook')!
// 1. Setup
await adapter.initialize(container)
adapter.registerCustomFunctions(erpFunctions)
// 2. Carica snapshot da localStorage o API
const stored = localStorage.getItem('my-snapshot')
adapter.loadSnapshot(stored ? JSON.parse(stored) : null)
// 3. Scrivi dati
adapter.setRange(0, 0, [
['Mese', 'Vendite'],
['Gen', 1000],
['Feb', 1500],
])
// 4. Ascolta modifiche
adapter.onChange((e) => {
console.log('modified', e)
})
// 5. Più tardi: salva
const snapshot = adapter.getSnapshot()
localStorage.setItem('my-snapshot', JSON.stringify(snapshot))
// 6. Cleanup
adapter.offChange()
adapter.destroy()
Tipi correlati
FortuneSheetSnapshot— blob opacoRecord<string, unknown>CellValue—string | number | boolean | nullSpreadsheetChangeEventErpFormulaFunctionFortuneSheetWorkbook— componente che l'adapter montauseSpreadsheet— consumatore principale