UNPKG

@sheetxl/models

Version:

Models - A Headless javascript spreadsheet library.

196 lines 8.74 kB
import { RemoveListener } from "@sheetxl/common"; /** * Used for transactional state. * This represents a single record change. * This is used by transactional operations, undo/redo, version control, and distributed state. * This also includes eventing but this is only for eventing for the final writes to the transaction * store any local eventing needs to be handled by the record itself. */ export interface ChangeSet<STATE, INPUTS> { state: STATE; /** * Inputs are values that are not part of the state but were used to calculate the state. * This is done because we want to allow different for inputs. For example * selection is considered an input because in a multi view environment we may * not want to selection to change if another view updates the data/state. */ inputs?: INPUTS; prevState: STATE | null; /**Unique Identifier for the change */ uuid: string; } export interface TransactionalUpdateStateOptions<STATE = any, INPUTS = undefined> { uuid?: string; description?: string; isUndo?: boolean; record: any; /** * The previous state will be: * The state of a previous transaction + any child transactions. */ state: ((prev: STATE) => STATE) | STATE; /** * The previous input will be: * The inputs from child transactions. (but not from previous transactions) */ inputs?: ((prev: INPUTS) => INPUTS) | INPUTS; } export interface TransactionStoreListener<STATE = any, INPUTS = undefined> { /** * Called when a change set is committed to the global changeset. * This is a map of unique ids to change sets. * * @param changes * @param description */ onChange(changes: Map<any, ChangeSet<STATE, INPUTS>>, description: string): void; /** * Called when all transactions are cleared. Handlers should clear their state. * For example undo should clear the undo stack. */ onClear?(uuid: string): void; } export interface ChangeSetListener<STATE = any, INPUTS = undefined> { /** * Called during a transaction this is when changes should be applied */ onRecordChange?(change: ChangeSet<STATE, INPUTS>, description: string, record: any, isUndo?: boolean): void; /** * Called at the end of a transaction. */ onAfterRecordChange?(change: ChangeSet<STATE, INPUTS>, description: string, record: any): void; /** * Called synchronously at the beginning of a transaction before a record is changed. * * If this throws an exception then all records within the transaction will not * be applied. */ onBeforeRecordChange?(uuid: string, description: string, record: any, newInputs: INPUTS): void; /** * Called when all transactions are cleared. Handlers should clear their state. * For example undo should clear the undo stack. */ onClear?(uuid: string): void; } /** * Objects that support interfacing with a transactional store implement this interface. */ export interface ITransactionStack { /** * Begins a transaction but puts it onto a global stack. * This will batch all 'transactional' changes until they have all be committed or rolled back. * * @remarks * Any changes that are made to this object will be reflected in the local sheet but * not committed to the transactional store until the batch is popped. * * @param description */ pushTransaction(description?: string): ITransaction; } export declare const setTransactionStoreSync: (isSync: boolean) => void; export interface ITransaction { /** * Begin a transaction with self contained, non-eventing updates * @remarks * * Context is useful for debugging and logging. * This is treated as a stack so it's fifo. This means * that when finally committed to global changeset * that only the final context will be maintained. * @param description The description of the transaction * @param onClose A callback for when the transaction is closed (due to either a commit or rollback) * @param isUndo A hint to indicate if the transaction should be support undo. */ beginTransaction(description?: string, onClose?: (transaction: ITransaction) => void, isUndo?: boolean): ITransaction; /** * Commit the transaction and all children transactions to the parent changeset. */ commit(): ITransaction; /** * Discard all changes and children transaction changes. */ rollback(): ITransaction; /** * If root transaction will return self */ parent(): ITransaction; /** * unique id for this transaction. This will be the same id for all sub transactions. */ readonly uuid: string; readonly depth: number; readonly description: string; readonly isUndo: boolean; updateState<STATE = any, INPUTS = undefined>(options: TransactionalUpdateStateOptions<STATE, INPUTS>): ChangeSet<STATE, INPUTS>; getChangeSet<STATE = any, INPUTS = undefined>(record: any): ChangeSet<STATE, INPUTS>; getState<STATE = any>(record: any): STATE; } declare abstract class AbstractTransaction implements ITransaction { protected _mapRecordToChanges: Map<any, ChangeSet<any, any>>; protected _children: Set<AbstractTransaction>; protected _updatingStates: any[]; protected _depth: number; protected _lookupCache: any; protected _description: string; protected _isUndo: boolean; constructor(description?: string, isUndo?: boolean); get depth(): number; /** * Creates a child transaction */ beginTransaction(description?: string, onClose?: (transaction: ITransaction) => void, isUndo?: boolean): ITransaction; protected _removeChild(child: AbstractTransaction): void; updateStates<STATE = any, INPUTS = undefined>(uuid: string, recordsToChanges: Map<any, ChangeSet<any, any>>, options: Omit<TransactionalUpdateStateOptions<STATE, INPUTS>, 'record' | 'state'>): Map<any, ChangeSet<any, any>>; updateState<STATE = any, INPUTS = undefined>(options: TransactionalUpdateStateOptions<STATE, INPUTS>): ChangeSet<STATE, INPUTS>; getState<STATE = any>(record: any): STATE; abstract getChangeSet<STATE = any, INPUTS = undefined>(record: any): ChangeSet<STATE, INPUTS>; abstract commit(): ITransaction; abstract rollback(): ITransaction; /** * If root transaction will return self */ abstract parent(): ITransaction; abstract get uuid(): string; get description(): string; get isUndo(): boolean; } /** * Events are never fired on sub transactions. Only when making changes to the root * either directly or through a final commit. Any models that want to fire non transactional * events should do this directly. */ export default class TransactionStore extends AbstractTransaction implements ITransaction { private _listeners; private _listenersChangeSet; private _transactionStack; private _isSync; constructor(isSync?: boolean); peekTransaction(): ITransaction; get uuid(): string; /** * calls beginTransaction but adds to a shared stack */ pushTransaction(description: string, onClose?: (transaction: ITransaction) => void, isUndo?: boolean): ITransaction; clear(record: any): void; commit(): ITransaction; rollback(): ITransaction; parent(): ITransaction; getChangeSet<STATE = any, INPUTS = undefined>(record: any): ChangeSet<STATE, INPUTS>; updateState<STATE = any, INPUTS = undefined>(options: TransactionalUpdateStateOptions<STATE, INPUTS>): ChangeSet<STATE, INPUTS>; updateStates<STATE = any, INPUTS = undefined>(uuid: string, recordsToChanges: Map<any, ChangeSet<any, any>>, options: TransactionalUpdateStateOptions<STATE, INPUTS>): Map<any, ChangeSet<any, any>>; addListener(listener: TransactionStoreListener): RemoveListener; /** * Fired when information at a specific record is changed. * This will be fired both during a commit and during a change to the global store */ addChangeSetListener<STATE = any, INPUTS = undefined>(record: any, listener: ChangeSetListener<STATE, INPUTS>): RemoveListener; private dispatchEvents; notifyRecordChange(changes: ChangeSet<any, any>, description: string, record: any, isUndo: boolean): void; notifyBeforeChange(uuid: string, description: string, record: any, newInputs: any): void; notifyAfterChange(changes: ChangeSet<any, any>, description: string, record: any): void; notifyChange(changes: Map<any, ChangeSet<any, any>>, description: string): void; notifyClear(uuid: string, record: any): void; } export { TransactionStore }; //# sourceMappingURL=Transaction.d.ts.map