@odoo/o-spreadsheet
Version:
A spreadsheet component
1,338 lines (1,298 loc) • 520 kB
TypeScript
import * as chart_js from 'chart.js';
import { ChartConfiguration, ChartDataset, CoreChartOptions, Scriptable, Color as Color$1, ScriptableContext, FontSpec, Point, ChartType as ChartType$1, ChartMeta } from 'chart.js';
import * as ChartGeo from 'chartjs-chart-geo';
import * as chart_js_dist_types_utils from 'chart.js/dist/types/utils';
import * as chart_js_dist_types_geometric from 'chart.js/dist/types/geometric';
import * as _odoo_owl from '@odoo/owl';
import { Component, ComponentConstructor } from '@odoo/owl';
import * as chart_js_dist_types_basic from 'chart.js/dist/types/basic';
import * as chart_js_auto from 'chart.js/auto';
import { Chart, ChartConfiguration as ChartConfiguration$1 } from 'chart.js/auto';
type LocaleCode = string & Alias;
interface Locale {
name: string;
code: LocaleCode;
thousandsSeparator?: string;
decimalSeparator: string;
weekStart: number;
dateFormat: string;
timeFormat: string;
formulaArgSeparator: string;
}
declare const DEFAULT_LOCALES: Locale[];
declare const DEFAULT_LOCALE: Locale;
type Format = string & Alias;
type FormattedValue = string & Alias;
interface LocaleFormat {
locale: Locale;
format?: Format;
}
interface CellAttributes {
readonly id: UID;
/**
* Raw cell content
*/
readonly content: string;
readonly format?: Format;
}
interface LiteralCell extends CellAttributes {
readonly isFormula: false;
readonly parsedValue: CellValue;
}
interface FormulaCell extends CellAttributes {
readonly isFormula: true;
readonly compiledFormula: RangeCompiledFormula;
}
type Cell = LiteralCell | FormulaCell;
interface EvaluatedCellProperties extends FunctionResultObject {
readonly format?: Format;
/**
* Cell value formatted based on the format
*/
readonly formattedValue: FormattedValue;
readonly defaultAlign: "right" | "center" | "left";
/**
* Can the cell appear in an automatic sum zone.
*/
readonly isAutoSummable: boolean;
readonly link?: Link;
}
type CellValue = string | number | boolean | null;
type EvaluatedCell = NumberCell | TextCell | BooleanCell | EmptyCell | ErrorCell;
interface NumberCell extends EvaluatedCellProperties {
readonly type: CellValueType.number;
readonly value: number;
}
interface TextCell extends EvaluatedCellProperties {
readonly type: CellValueType.text;
readonly value: string;
}
interface BooleanCell extends EvaluatedCellProperties {
readonly type: CellValueType.boolean;
readonly value: boolean;
}
interface EmptyCell extends EvaluatedCellProperties {
readonly type: CellValueType.empty;
readonly value: null;
}
interface ErrorCell extends EvaluatedCellProperties {
readonly type: CellValueType.error;
readonly value: string;
readonly message?: string;
}
declare enum CellValueType {
boolean = "boolean",
number = "number",
text = "text",
empty = "empty",
error = "error"
}
type TokenType = "OPERATOR" | "NUMBER" | "STRING" | "SYMBOL" | "SPACE" | "DEBUGGER" | "ARG_SEPARATOR" | "ARRAY_ROW_SEPARATOR" | "LEFT_PAREN" | "RIGHT_PAREN" | "LEFT_BRACE" | "RIGHT_BRACE" | "REFERENCE" | "INVALID_REFERENCE" | "UNKNOWN";
interface Token {
readonly type: TokenType;
readonly value: string;
}
declare function tokenize(str: string, locale?: Locale): Token[];
interface GenericCriterion {
type: GenericCriterionType;
values: string[];
}
type GenericDateCriterion = GenericCriterion & {
dateValue: DateCriterionValue;
};
type GenericCriterionType = "containsText" | "notContainsText" | "isEqualText" | "isEmail" | "isLink" | "dateIs" | "dateIsBefore" | "dateIsOnOrBefore" | "dateIsAfter" | "dateIsOnOrAfter" | "dateIsBetween" | "dateIsNotBetween" | "dateIsValid" | "isEqual" | "isNotEqual" | "isGreaterThan" | "isGreaterOrEqualTo" | "isLessThan" | "isLessOrEqualTo" | "isBetween" | "isNotBetween" | "isBoolean" | "isValueInList" | "isValueInRange" | "customFormula" | "beginsWithText" | "endsWithText" | "isNotEmpty" | "isEmpty";
type DateCriterionValue = "today" | "tomorrow" | "yesterday" | "lastWeek" | "lastMonth" | "lastYear" | "exactDate";
type EvaluatedCriterion<T extends GenericCriterion = GenericCriterion> = Omit<T, "values"> & {
values: CellValue[];
};
type EvaluatedDateCriterion = EvaluatedCriterion<GenericDateCriterion>;
interface RangePart {
readonly colFixed: boolean;
readonly rowFixed: boolean;
}
interface Range {
readonly zone: Readonly<Zone>;
readonly unboundedZone: Readonly<UnboundedZone>;
readonly parts: readonly RangePart[];
readonly invalidXc?: string;
/** true if the user provided the range with the sheet name */
readonly prefixSheet: boolean;
/** the name of any sheet that is invalid */
readonly invalidSheetName?: string;
/** the sheet on which the range is defined */
readonly sheetId: UID;
}
interface BoundedRange {
sheetId: UID;
zone: Zone;
}
interface RangeStringOptions {
useBoundedReference?: boolean;
useFixedReference?: boolean;
}
interface RangeData {
_zone: Zone | UnboundedZone;
_sheetId: UID;
}
/**
* https://docs.microsoft.com/en-us/openspecs/office_standards/ms-xlsx/025ea6e4-ad42-43ea-a016-16f4e4688ac8
*/
interface ConditionalFormat {
id: UID;
rule: ConditionalFormatRule;
stopIfTrue?: boolean;
ranges: string[];
}
interface ConditionalFormatInternal extends Omit<ConditionalFormat, "ranges" | "rule"> {
ranges: Range[];
rule: ConditionalFormatRuleInternal;
}
type ConditionalFormatRule = SingleColorRules | ColorScaleRule | IconSetRule | DataBarRule;
type ConditionalFormatRuleInternal = SingleColorRules | ColorScaleRule | IconSetRule | DataBarRuleInternal;
type SingleColorRules = CellIsRule;
interface SingleColorRule {
style: Style;
}
interface TextRule extends SingleColorRule {
text: string;
}
interface CellIsRule extends SingleColorRule {
type: "CellIsRule";
operator: ConditionalFormattingOperatorValues;
values: string[];
dateValue?: DateCriterionValue;
}
interface ExpressionRule extends SingleColorRule {
type: "ExpressionRule";
}
type ThresholdType = "value" | "number" | "percentage" | "percentile" | "formula";
type ColorScaleThreshold = {
color: number;
type: ThresholdType;
value?: string;
};
type ColorScaleMidPointThreshold = {
color: number;
type: Exclude<ThresholdType, "value">;
value: string;
};
type IconThreshold = {
type: Exclude<ThresholdType, "value">;
operator: "gt" | "ge";
value: string;
};
interface ColorScaleRule {
type: "ColorScaleRule";
minimum: ColorScaleThreshold;
maximum: ColorScaleThreshold;
midpoint?: ColorScaleMidPointThreshold;
}
interface DataBarRule {
type: "DataBarRule";
color: number;
rangeValues?: string;
}
interface DataBarRuleInternal extends Omit<DataBarRule, "rangeValues"> {
rangeValues?: Range;
}
interface IconSet {
upper: string;
middle: string;
lower: string;
}
interface IconSetRule {
type: "IconSetRule";
icons: IconSet;
upperInflectionPoint: IconThreshold;
lowerInflectionPoint: IconThreshold;
}
interface ContainsTextRule extends TextRule {
type: "ContainsTextRule";
}
interface NotContainsTextRule extends TextRule {
type: "NotContainsTextRule";
}
interface BeginsWithRule extends TextRule {
type: "BeginsWithRule";
}
interface EndsWithRule extends TextRule {
type: "EndsWithRule";
}
interface containsBlanksRule extends TextRule {
type: "containsBlanksRule";
}
interface notContainsBlanksRule extends TextRule {
type: "notContainsBlanksRule";
}
interface containsErrorsRule extends SingleColorRule {
type: "containsErrorsRule";
}
interface notContainsErrorsRule extends SingleColorRule {
type: "notContainsErrorsRule";
}
interface TimePeriodRule extends SingleColorRule {
type: "TimePeriodRule";
timePeriod: string;
}
interface AboveAverageRule extends SingleColorRule {
type: "AboveAverageRule";
aboveAverage: boolean;
equalAverage: boolean;
}
interface Top10Rule extends SingleColorRule {
type: "Top10Rule";
percent: boolean;
bottom: boolean;
rank: number;
}
declare const cfOperators: readonly ["containsText", "notContainsText", "isGreaterThan", "isGreaterOrEqualTo", "isLessThan", "isLessOrEqualTo", "isBetween", "isNotBetween", "beginsWithText", "endsWithText", "isNotEmpty", "isEmpty", "isNotEqual", "isEqual", "customFormula", "dateIs", "dateIsBefore", "dateIsAfter", "dateIsOnOrBefore", "dateIsOnOrAfter"];
type ConditionalFormattingOperatorValues = (typeof cfOperators)[number];
declare const availableConditionalFormatOperators: Set<ConditionalFormattingOperatorValues>;
declare const functionCache: {
[key: string]: FormulaToExecute;
};
declare function compile(formula: string): CompiledFormula;
declare function compileTokens(tokens: Token[]): CompiledFormula;
interface ASTBase {
debug?: boolean;
tokenStartIndex: number;
tokenEndIndex: number;
}
interface ASTNumber extends ASTBase {
type: "NUMBER";
value: number;
}
interface ASTReference extends ASTBase {
type: "REFERENCE";
value: string;
}
interface ASTString extends ASTBase {
type: "STRING";
value: string;
}
interface ASTBoolean extends ASTBase {
type: "BOOLEAN";
value: boolean;
}
interface ASTUnaryOperation extends ASTBase {
type: "UNARY_OPERATION";
value: any;
operand: AST;
postfix?: boolean;
}
interface ASTOperation extends ASTBase {
type: "BIN_OPERATION";
value: any;
left: AST;
right: AST;
}
interface ASTFuncall extends ASTBase {
type: "FUNCALL";
value: string;
args: AST[];
}
interface ASTSymbol extends ASTBase {
type: "SYMBOL";
value: string;
}
interface ASTArray extends ASTBase {
type: "ARRAY";
value: AST[][];
}
interface ASTEmpty extends ASTBase {
type: "EMPTY";
value: "";
}
type AST = ASTOperation | ASTUnaryOperation | ASTFuncall | ASTSymbol | ASTArray | ASTNumber | ASTBoolean | ASTString | ASTReference | ASTEmpty;
/**
* Parse an expression (as a string) into an AST.
*/
declare function parse(str: string): AST;
declare function parseTokens(tokens: Token[]): AST;
/**
* Allows to visit all nodes of an AST and apply a mapping function
* to nodes of a specific type.
* Useful if you want to convert some part of a formula.
*
* @example
* convertAstNodes(ast, "FUNCALL", convertFormulaToExcel)
*
* function convertFormulaToExcel(ast: ASTFuncall) {
* // ...
* return modifiedAst
* }
*/
declare function convertAstNodes<T extends AST["type"]>(ast: AST, type: T, fn: (ast: Extract<AST, {
type: T;
}>) => AST): AST;
declare function iterateAstNodes(ast: AST): AST[];
declare class Registry$1<T> {
content: Record<string, T>;
add(key: string, value: T): this;
replace(key: string, value: T): this;
get(key: string): T;
contains(key: string): boolean;
getAll(): T[];
getKeys(): string[];
remove(key: string): void;
}
type ArgType = "ANY" | "BOOLEAN" | "NUMBER" | "STRING" | "DATE" | "RANGE" | "RANGE<BOOLEAN>" | "RANGE<NUMBER>" | "RANGE<DATE>" | "RANGE<STRING>" | "RANGE<ANY>" | "META" | "RANGE<META>";
interface ArgDefinition {
acceptMatrix?: boolean;
acceptMatrixOnly?: boolean;
acceptErrors?: boolean;
repeating?: boolean;
optional?: boolean;
description: string;
name: string;
type: ArgType[];
default?: boolean;
defaultValue?: any;
proposalValues?: ArgProposal[];
}
type ArgProposal = {
value: CellValue;
label?: string;
};
type ComputeFunction<R> = (this: EvalContext, ...args: Arg[]) => R;
interface AddFunctionDescription {
compute: ComputeFunction<FunctionResultObject | Matrix<FunctionResultObject> | CellValue | Matrix<CellValue>>;
description: string;
category?: string;
args: ArgDefinition[];
isExported?: boolean;
hidden?: boolean;
}
type FunctionDescription = AddFunctionDescription & {
name: string;
minArgRequired: number;
maxArgPossible: number;
nbrArgRepeating: number;
nbrOptionalNonRepeatingArgs: number;
};
type EvalContext = {
__originSheetId: UID;
__originCellPosition?: CellPosition;
locale: Locale;
getters: Getters;
[key: string]: any;
updateDependencies?: (position: CellPosition) => void;
addDependencies?: (position: CellPosition, ranges: Range[]) => void;
debug?: boolean;
lookupCaches?: LookupCaches;
};
/**
* used to cache lookup values for linear search
**/
type LookupCaches = {
forwardSearch: Map<unknown, Map<CellValue, number>>;
reverseSearch: Map<unknown, Map<CellValue, number>>;
};
declare class FunctionRegistry extends Registry$1<FunctionDescription> {
mapping: {
[key: string]: ComputeFunction<Matrix<FunctionResultObject> | FunctionResultObject>;
};
add(name: string, addDescr: AddFunctionDescription): this;
replace(name: string, addDescr: AddFunctionDescription): this;
}
type Functions = {
[functionName: string]: AddFunctionDescription;
};
type Category = {
name: string;
functions: Functions;
};
declare const categories: Category[];
interface SearchOptions {
matchCase: boolean;
exactMatch: boolean;
searchFormulas: boolean;
searchScope: "allSheets" | "activeSheet" | "specificRange";
specificRange?: Range;
}
/**
* Deep copy arrays, plain objects and primitive values.
* Throws an error for other types such as class instances.
* Sparse arrays remain sparse.
*/
declare function deepCopy<T>(obj: T): T;
/**
* Remove quotes from a quoted string.
*/
declare function unquote(string: string, quoteChar?: "'" | '"'): string;
/** Replace the excel-excluded characters of a sheetName */
declare function sanitizeSheetName(sheetName: string, replacementChar?: string): string;
declare function isMarkdownLink(str: string): boolean;
/**
* Build a markdown link from a label and an url
*/
declare function markdownLink(label: string, url: string): string;
declare function parseMarkdownLink(str: string): {
url: string;
label: string;
};
/**
* This helper function can be used as a type guard when filtering arrays.
* const foo: number[] = [1, 2, undefined, 4].filter(isDefined)
*/
declare function isDefined<T>(argument: T | undefined): argument is T;
/**
* Lazy value computed by the provided function.
*/
declare function lazy<T>(fn: (() => T) | T): Lazy<T>;
/**
* Compares n objects.
*/
declare function deepEquals(...o: any[]): boolean;
declare function getUniqueText(text: string, texts: string[], options?: {
compute?: (text: string, increment: number) => string;
start?: number;
computeFirstOne?: boolean;
}): string;
declare function isFormula(content: string): boolean;
/**
* Return true if the argument is a "number string".
*
* Note that "" (empty string) does not count as a number string
*/
declare function isNumber(value: string | undefined, locale: Locale): boolean;
declare function splitReference(ref: string): {
sheetName?: string;
xc: string;
};
declare class UuidGenerator {
private getCrypto;
/**
* Generates a custom UUID using a simple 36^12 method (8-character alphanumeric string with lowercase letters)
* This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
* it also has a smaller size, which is preferable to alleviate the overall data size.
*
* This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
* as they will appear several times in the revisions and local history.
*
*/
smallUuid(): string;
/**
* Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
* This method should be used when you need to avoid collisions at all costs, like the id of a revision.
*/
uuidv4(): string;
}
/**
* This is a generic event bus based on the Owl event bus.
* This bus however ensures type safety across events and subscription callbacks.
*/
declare class EventBus<Event extends {
type: string;
}> {
subscriptions: {
[eventType: string]: Subscription[];
};
/**
* Add a listener for the 'eventType' events.
*
* Note that the 'owner' of this event can be anything, but will more likely
* be a component or a class. The idea is that the callback will be called with
* the proper owner bound.
*
* Also, the owner should be kind of unique. This will be used to remove the
* listener.
*/
on<T extends Event["type"], E extends Extract<Event, {
type: T;
}>>(type: T, owner: any, callback: (r: Omit<E, "type">) => void): void;
/**
* Emit an event of type 'eventType'. Any extra arguments will be passed to
* the listeners callback.
*/
trigger<T extends Event["type"], E extends Extract<Event, {
type: T;
}>>(type: T, payload?: Omit<E, "type">): void;
/**
* Remove a listener
*/
off<T extends Event["type"]>(eventType: T, owner: any): void;
/**
* Remove all subscriptions.
*/
clear(): void;
}
type Callback = (...args: any[]) => void;
interface Subscription {
owner: any;
callback: Callback;
}
declare class PositionMap<T> {
private map;
constructor(entries?: Iterable<readonly [CellPosition, T]>);
set({ sheetId, col, row }: CellPosition, value: T): void;
setMany(values: Iterable<[CellPosition, T]>): void;
get({ sheetId, col, row }: CellPosition): T | undefined;
getSheet(sheetId: UID): Record<number, Record<number, T>> | undefined;
clearSheet(sheetId: UID): void;
has({ sheetId, col, row }: CellPosition): boolean;
delete({ sheetId, col, row }: CellPosition): void;
keys(): CellPosition[];
keysForSheet(sheetId: UID): CellPosition[];
entries(): IterableIterator<[CellPosition, T]>;
}
/**
* An Operation can be executed to change a data structure from state A
* to state B.
* It should hold the necessary data used to perform this transition.
* It should be possible to revert the changes made by this operation.
*
* In the context of o-spreadsheet, the data from an operation would
* be a revision (the commands are used to execute it, the `changes` are used
* to revert it).
*/
declare class Operation<T> {
readonly id: UID;
readonly data: T;
constructor(id: UID, data: T);
transformed(transformation: Transformation<T>): Operation<T>;
}
/**
* A branch holds a sequence of operations.
* It can be represented as "A - B - C - D" if A, B, C and D are executed one
* after the other.
*
* @param buildTransformation Factory to build transformations
* @param operations initial operations
*/
declare class Branch<T> {
private readonly buildTransformation;
private operations;
constructor(buildTransformation: TransformationFactory<T>, operations?: Operation<T>[]);
getOperations(): readonly Operation<T>[];
getOperation(operationId: UID): Operation<T>;
getLastOperationId(): UID | undefined;
/**
* Get the id of the operation appears first in the list of operations
*/
getFirstOperationAmong(op1: UID, op2: UID): UID;
contains(operationId: UID): boolean;
/**
* Add the given operation as the first operation
*/
prepend(operation: Operation<T>): void;
/**
* add the given operation after the given predecessorOpId
*/
insert(newOperation: Operation<T>, predecessorOpId: UID): void;
/**
* Add the given operation as the last operation
*/
append(operation: Operation<T>): void;
/**
* Append operations in the given branch to this branch.
*/
appendBranch(branch: Branch<T>): void;
/**
* Create and return a copy of this branch, starting after the given operationId
*/
fork(operationId: UID): Branch<T>;
/**
* Transform all the operations in this branch with the given transformation
*/
transform(transformation: Transformation<T>): void;
/**
* Cut the branch before the operation, meaning the operation
* and all following operations are dropped.
*/
cutBefore(operationId: UID): void;
/**
* Cut the branch after the operation, meaning all following operations are dropped.
*/
cutAfter(operationId: UID): void;
/**
* Find an operation in this branch based on its id.
* This returns the operation itself, operations which comes before it
* and operation which comes after it.
*/
private locateOperation;
}
interface CreateRevisionOptions {
revisionId?: UID;
clientId?: UID;
pending?: boolean;
}
interface HistoryChange {
key: string;
target: any;
before: any;
}
interface WorkbookHistory<Plugin> {
update<T extends keyof Plugin>(key: T, val: Plugin[T]): void;
update<T extends keyof Plugin, U extends keyof NonNullable<Plugin[T]>>(key1: T, key2: U, val: NonNullable<Plugin[T]>[U]): void;
update<T extends keyof Plugin, U extends keyof NonNullable<Plugin[T]>, K extends keyof NonNullable<NonNullable<Plugin[T]>[U]>>(key1: T, key2: U, key3: K, val: NonNullable<NonNullable<Plugin[T]>[U]>[K]): void;
update<T extends keyof Plugin, U extends keyof NonNullable<Plugin[T]>, K extends keyof NonNullable<NonNullable<Plugin[T]>[U]>, V extends keyof NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>>(key1: T, key2: U, key3: K, key4: V, val: NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>[V]): void;
update<T extends keyof Plugin, U extends keyof NonNullable<Plugin[T]>, K extends keyof NonNullable<NonNullable<Plugin[T]>[U]>, V extends keyof NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>, W extends keyof NonNullable<NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>[V]>>(key1: T, key2: U, key3: K, key4: V, key5: W, val: NonNullable<NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>[V]>[W]): void;
update<T extends keyof Plugin, U extends keyof NonNullable<Plugin[T]>, K extends keyof NonNullable<NonNullable<Plugin[T]>[U]>, V extends keyof NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>, W extends keyof NonNullable<NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>[V]>, Y extends keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>[V]>[W]>>(key1: T, key2: U, key3: K, key4: V, key5: W, key6: Y, val: NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<Plugin[T]>[U]>[K]>[V]>[W]>[Y]): void;
}
type Transformation<T = unknown> = (dataToTransform: T) => T;
interface TransformationFactory<T = unknown> {
/**
* Build a transformation function to transform any operation as if the execution of
* a previous `operation` was omitted.
*/
without: (operation: T) => Transformation<T>;
/**
* Build a transformation function to transform any operation as if a new `operation` was
* executed before.
*/
with: (operation: T) => Transformation<T>;
}
interface OperationSequenceNode<T> {
operation: Operation<T>;
branch: Branch<T>;
isCancelled: boolean;
next?: {
operation: Operation<T>;
branch: Branch<T>;
};
}
type HistoryPath = [any, ...(number | string)[]];
declare class StateObserver {
private changes;
private commands;
/**
* Record the changes which could happen in the given callback, save them in a
* new revision with the given id and userId.
*/
recordChanges(callback: () => void): {
changes: HistoryChange[];
commands: CoreCommand[];
};
addCommand(command: CoreCommand): void;
addChange(...args: [...HistoryPath, any]): void;
}
interface CarouselState {
readonly carousels: Record<UID, Record<UID, Carousel | undefined> | undefined>;
}
declare class CarouselPlugin extends CorePlugin<CarouselState> implements CarouselState {
static getters: readonly ["getCarousel", "doesCarouselExist"];
readonly carousels: Record<UID, Record<UID, Carousel | undefined> | undefined>;
allowDispatch(cmd: CoreCommand): CommandResult.Success | CommandResult.InvalidFigureId | CommandResult.DuplicatedFigureId;
handle(cmd: CoreCommand): void;
doesCarouselExist(figureId: UID): boolean;
getCarousel(figureId: UID): Carousel;
private removeDeletedCharts;
import(data: WorkbookData): void;
export(data: WorkbookData): void;
}
interface CoreState$1 {
cells: Record<UID, Record<UID, Cell | undefined> | undefined>;
nextId: number;
}
/**
* Core Plugin
*
* This is the most fundamental of all plugins. It defines how to interact with
* cell and sheet content.
*/
declare class CellPlugin extends CorePlugin<CoreState$1> implements CoreState$1 {
static getters: readonly ["zoneToXC", "getCells", "getTranslatedCellFormula", "getCellById", "getFormulaString", "getFormulaMovedInSheet"];
readonly nextId = 1;
readonly cells: {
[sheetId: string]: {
[id: string]: Cell;
};
};
adaptRanges({ applyChange }: RangeAdapterFunctions, sheetId: UID, sheetName: AdaptSheetName): void;
allowDispatch(cmd: CoreCommand): CommandResult | CommandResult[];
handle(cmd: CoreCommand): void;
private clearZones;
/**
* Set a format to all the cells in a zone
*/
private setFormatter;
/**
* Clear the styles and format of zones
*/
private clearFormatting;
/**
* Clear the styles, the format and the content of zones
*/
private clearCells;
/**
* Copy the format of the reference column/row to the new columns/rows.
*/
private handleAddColumnsRows;
import(data: WorkbookData): void;
export(data: WorkbookData): void;
importCell(sheetId: UID, content?: string, format?: Format): Cell;
exportForExcel(data: ExcelWorkbookData): void;
getCells(sheetId: UID): Record<UID, Cell>;
/**
* get a cell by ID. Used in evaluation when evaluating an async cell, we need to be able to find it back after
* starting an async evaluation even if it has been moved or re-allocated
*/
getCellById(cellId: UID): Cell | undefined;
getFormulaString(sheetId: UID, tokens: Token[], dependencies: Range[], useBoundedReference?: boolean): string;
getTranslatedCellFormula(sheetId: UID, offsetX: number, offsetY: number, tokens: Token[]): string;
getFormulaMovedInSheet(originSheetId: UID, targetSheetId: UID, tokens: Token[]): string;
/**
* Converts a zone to a XC coordinate system
*
* The conversion also treats merges as one single cell
*
* Examples:
* {top:0,left:0,right:0,bottom:0} ==> A1
* {top:0,left:0,right:1,bottom:1} ==> A1:B2
*
* if A1:B2 is a merge:
* {top:0,left:0,right:1,bottom:1} ==> A1
* {top:1,left:0,right:1,bottom:2} ==> A1:B3
*
* if A1:B2 and A4:B5 are merges:
* {top:1,left:0,right:1,bottom:3} ==> A1:A5
*/
zoneToXC(sheetId: UID, zone: Zone, fixedParts?: RangePart[]): string;
/**
* Copy the format of one column to other columns.
*/
private copyColumnFormat;
/**
* Copy the format of one row to other rows.
*/
private copyRowFormat;
/**
* gets the currently used style and format of a cell based on it's coordinates
*/
private getFormat;
private getNextUid;
private updateCell;
private createCell;
private createLiteralCell;
private createFormulaCell;
/**
* Create a new formula cell with the content
* being a computed property to rebuild the dependencies XC.
*/
private createFormulaCellWithDependencies;
private checkCellOutOfSheet;
private checkUselessClearCell;
private checkUselessUpdateCell;
}
interface Validator {
/**
* Combine multiple validation functions into a single function
* returning the list of result of every validation.
*/
batchValidations<T>(...validations: Validation<T>[]): Validation<T>;
/**
* Combine multiple validation functions. Every validation is executed one after
* the other. As soon as one validation fails, it stops and the cancelled reason
* is returned.
*/
chainValidations<T>(...validations: Validation<T>[]): Validation<T>;
checkValidations<T>(command: T, ...validations: Validation<T>[]): CommandResult | CommandResult[];
}
/**
* AbstractChart is the class from which every Chart should inherit.
* The role of this class is to maintain the state of each chart.
*/
declare abstract class AbstractChart {
readonly sheetId: UID;
readonly title: TitleDesign;
abstract readonly type: ChartType;
protected readonly getters: CoreGetters;
readonly humanize: boolean;
constructor(definition: ChartDefinition, sheetId: UID, getters: CoreGetters);
/**
* Validate the chart definition given as arguments. This function will be
* called from allowDispatch function
*/
static validateChartDefinition(validator: Validator, definition: ChartDefinition): CommandResult | CommandResult[];
/**
* Get a new chart definition transformed with the executed command. This
* functions will be called during operational transform process
*/
static transformDefinition(chartSheetId: UID, definition: ChartDefinition, applyChange: RangeAdapter): ChartDefinition;
/**
* Get an empty definition based on the given context
*/
static getDefinitionFromContextCreation(context: ChartCreationContext): ChartDefinition;
/**
* Get the definition of the chart
*/
abstract getDefinition(): ChartDefinition;
/**
* Get the definition of the chart that will be used for excel export.
* If the chart is not supported by Excel, this function returns undefined.
*/
abstract getDefinitionForExcel(getters: CoreGetters): ExcelChartDefinition | undefined;
/**
* This function should be used to update all the ranges of the chart after
* a grid change (add/remove col/row, rename sheet, ...)
*/
abstract updateRanges(rangeAdapters: RangeAdapterFunctions): AbstractChart;
/**
* Duplicate the chart when a sheet is duplicated.
* The ranges that are in the same sheet as the chart are adapted to the new sheetId.
*/
abstract duplicateInDuplicatedSheet(newSheetId: UID): AbstractChart;
/**
* Get a copy a the chart in the given sheetId.
* The ranges of the chart will stay the same as the copied chart.
*/
abstract copyInSheetId(sheetId: UID): AbstractChart;
/**
* Extract the ChartCreationContext of the chart
*/
abstract getContextCreation(): ChartCreationContext;
protected getCommonDataSetAttributesForExcel(labelRange: Range | undefined, dataSets: DataSet[], shouldRemoveFirstLabel: boolean): {
dataSets: ExcelChartDataset[];
labelRange: string | undefined;
};
}
interface FigureChart {
figureId: UID;
chart: AbstractChart;
}
interface ChartState {
readonly charts: Record<UID, FigureChart | undefined>;
}
declare class ChartPlugin extends CorePlugin<ChartState> implements ChartState {
static getters: readonly ["isChartDefined", "getChartDefinition", "getChartType", "getChartIds", "getChart", "getFigureIdFromChartId", "getContextCreationChart"];
readonly charts: Record<UID, FigureChart | undefined>;
private createChart;
private validateChartDefinition;
adaptRanges(rangeAdapters: RangeAdapterFunctions): void;
allowDispatch(cmd: Command): CommandResult | CommandResult[];
handle(cmd: CoreCommand): void;
getContextCreationChart(chartId: UID): ChartCreationContext | undefined;
getChart(chartId: UID): AbstractChart | undefined;
getFigureIdFromChartId(chartId: UID): UID;
getChartType(chartId: UID): ChartType;
isChartDefined(chartId: UID): boolean;
getChartIds(sheetId: UID): string[];
getChartDefinition(chartId: UID): ChartDefinition;
import(data: WorkbookData): void;
export(data: WorkbookData): void;
/**
* Add a figure with tag chart with the given id at the given position
*/
private addFigure;
/**
* Add a chart in the local state. If a chart already exists, this chart is
* replaced
*/
private addChart;
private checkChartDuplicate;
private checkChartExists;
private checkChartChanged;
/** If the command is meant to create a new figure, the position & offset argument need to be defined in the command */
private checkFigureArguments;
}
interface ConditionalFormatState {
readonly cfRules: {
[sheet: string]: ConditionalFormatInternal[];
};
}
declare class ConditionalFormatPlugin extends CorePlugin<ConditionalFormatState> implements ConditionalFormatState {
static getters: readonly ["getConditionalFormats", "getRulesSelection", "getRulesByCell", "getAdaptedCfRanges"];
readonly cfRules: {
[sheet: string]: ConditionalFormatInternal[];
};
adaptCFFormulas({ applyChange, adaptFormulaString }: RangeAdapterFunctions): void;
adaptCFRanges(sheetId: UID, { applyChange }: RangeAdapterFunctions): void;
adaptRanges(rangeAdapters: RangeAdapterFunctions, sheetId: UID): void;
allowDispatch(cmd: Command): CommandResult | CommandResult[];
handle(cmd: CoreCommand): void;
import(data: WorkbookData): void;
export(data: Partial<WorkbookData>): void;
exportForExcel(data: ExcelWorkbookData): void;
/**
* Returns all the conditional format rules defined for the current sheet to display the user
*/
getConditionalFormats(sheetId: UID): ConditionalFormat[];
getRulesSelection(sheetId: UID, selection: Zone[]): UID[];
getRulesByZone(sheetId: UID, zone: Zone): Set<UID>;
getRulesByCell(sheetId: UID, cellCol: number, cellRow: number): Set<ConditionalFormat>;
/**
* Add or remove cells to a given conditional formatting rule and return the adapted CF's XCs.
*/
getAdaptedCfRanges(sheetId: UID, cf: ConditionalFormat, toAdd: Zone[], toRemove: Zone[]): RangeData[] | undefined;
private mapToConditionalFormat;
private mapToConditionalFormatInternal;
/**
* Add or replace a conditional format rule
*/
private addConditionalFormatting;
private checkValidPriorityChange;
private checkEmptyRange;
private checkCFRule;
private checkCFHasChanged;
private checkOperatorArgsNumber;
private checkNaN;
private checkFormulaCompilation;
private checkThresholds;
private checkInflectionPoints;
private checkLowerBiggerThanUpper;
private checkMinBiggerThanMax;
private checkMidBiggerThanMax;
private checkMinBiggerThanMid;
private checkCFValues;
private removeConditionalFormatting;
private changeCFPriority;
}
interface DataValidationRule {
id: UID;
criterion: DataValidationCriterion;
ranges: Range[];
isBlocking?: boolean;
}
type TextContainsCriterion = {
type: "containsText";
values: string[];
};
type TextNotContainsCriterion = {
type: "notContainsText";
values: string[];
};
type TextIsCriterion = {
type: "isEqualText";
values: string[];
};
type TextIsEmailCriterion = {
type: "isEmail";
values: string[];
};
type TextIsLinkCriterion = {
type: "isLink";
values: string[];
};
type DateIsCriterion = {
type: "dateIs";
dateValue: DateCriterionValue;
values: string[];
};
type DateIsBeforeCriterion = {
type: "dateIsBefore";
dateValue: DateCriterionValue;
values: string[];
};
type DateIsOnOrBeforeCriterion = {
type: "dateIsOnOrBefore";
dateValue: DateCriterionValue;
values: string[];
};
type DateIsAfterCriterion = {
type: "dateIsAfter";
dateValue: DateCriterionValue;
values: string[];
};
type DateIsOnOrAfterCriterion = {
type: "dateIsOnOrAfter";
dateValue: DateCriterionValue;
values: string[];
};
type DateIsBetweenCriterion = {
type: "dateIsBetween";
values: string[];
};
type DateIsNotBetweenCriterion = {
type: "dateIsNotBetween";
values: string[];
};
type DateIsValidCriterion = {
type: "dateIsValid";
values: string[];
};
type IsEqualCriterion = {
type: "isEqual";
values: string[];
};
type IsNotEqualCriterion = {
type: "isNotEqual";
values: string[];
};
type IsGreaterThanCriterion = {
type: "isGreaterThan";
values: string[];
};
type IsGreaterOrEqualToCriterion = {
type: "isGreaterOrEqualTo";
values: string[];
};
type IsLessThanCriterion = {
type: "isLessThan";
values: string[];
};
type IsLessOrEqualToCriterion = {
type: "isLessOrEqualTo";
values: string[];
};
type IsBetweenCriterion = {
type: "isBetween";
values: string[];
};
type IsNotBetweenCriterion = {
type: "isNotBetween";
values: string[];
};
type IsCheckboxCriterion = {
type: "isBoolean";
values: string[];
};
type IsValueInListCriterion = {
type: "isValueInList";
values: string[];
colors?: Record<string, Color | undefined>;
displayStyle: "arrow" | "plainText" | "chip";
};
type IsValueInRangeCriterion = {
type: "isValueInRange";
values: string[];
colors?: Record<string, Color | undefined>;
displayStyle: "arrow" | "plainText" | "chip";
};
type CustomFormulaCriterion = {
type: "customFormula";
values: string[];
};
type DataValidationCriterion = TextContainsCriterion | TextNotContainsCriterion | TextIsCriterion | TextIsEmailCriterion | TextIsLinkCriterion | IsBetweenCriterion | DateIsCriterion | DateIsBeforeCriterion | DateIsOnOrBeforeCriterion | DateIsAfterCriterion | DateIsOnOrAfterCriterion | DateIsBetweenCriterion | DateIsNotBetweenCriterion | DateIsValidCriterion | IsEqualCriterion | IsNotEqualCriterion | IsGreaterThanCriterion | IsGreaterOrEqualToCriterion | IsLessThanCriterion | IsLessOrEqualToCriterion | IsNotBetweenCriterion | IsCheckboxCriterion | IsValueInListCriterion | IsValueInRangeCriterion | CustomFormulaCriterion;
type DataValidationCriterionType = DataValidationCriterion["type"];
type DataValidationDateCriterion = Extract<DataValidationCriterion, {
dateValue: DateCriterionValue;
}>;
declare const availableDataValidationOperators: Set<DataValidationCriterionType>;
interface DataValidationState {
readonly rules: {
[sheet: string]: DataValidationRule[];
};
}
declare class DataValidationPlugin extends CorePlugin<DataValidationState> implements DataValidationState {
static getters: readonly ["cellHasListDataValidationIcon", "getDataValidationRule", "getDataValidationRules", "getValidationRuleForCell"];
readonly rules: {
[sheet: string]: DataValidationRule[];
};
adaptRanges(rangeAdapters: RangeAdapterFunctions, sheetId: UID): void;
private adaptDVFormulas;
private adaptDVRanges;
allowDispatch(cmd: Command): CommandResult | CommandResult[];
handle(cmd: CoreCommand): void;
getDataValidationRules(sheetId: UID): DataValidationRule[];
getDataValidationRule(sheetId: UID, id: UID): DataValidationRule | undefined;
getValidationRuleForCell({ sheetId, col, row }: CellPosition): DataValidationRule | undefined;
cellHasListDataValidationIcon(cellPosition: CellPosition): boolean;
private addDataValidationRule;
private removeRangesFromRules;
private removeDataValidationRule;
private setCenterStyleToBooleanCells;
private checkEmptyRange;
import(data: WorkbookData): void;
export(data: Partial<WorkbookData>): void;
exportForExcel(data: ExcelWorkbookData): void;
private checkCriterionTypeIsValid;
private checkCriterionHasValidNumberOfValues;
private checkCriterionValuesAreValid;
private checkValidRange;
}
interface FigureState {
readonly figures: {
[sheet: string]: Record<UID, Figure | undefined> | undefined;
};
readonly insertionOrders: UID[];
}
declare class FigurePlugin extends CorePlugin<FigureState> implements FigureState {
static getters: readonly ["getFigures", "getFigure", "getFigureSheetId"];
readonly figures: {
[sheet: string]: Record<UID, Figure | undefined> | undefined;
};
readonly insertionOrders: UID[];
adaptRanges({ applyChange }: RangeAdapterFunctions, sheetId: UID): void;
allowDispatch(cmd: CoreCommand): CommandResult | CommandResult[];
beforeHandle(cmd: CoreCommand): void;
handle(cmd: CoreCommand): void;
private onColRemove;
private onRowRemove;
private getPositionInSheet;
private updateFigure;
private addFigure;
private deleteSheet;
private removeFigure;
private checkFigureExists;
private checkFigureDuplicate;
private checkFigureAnchorOffset;
getFigures(sheetId: UID): Figure[];
getFigure(sheetId: UID, figureId: string): Figure | undefined;
getFigureSheetId(figureId: string): UID | undefined;
import(data: WorkbookData): void;
export(data: WorkbookData): void;
exportForExcel(data: ExcelWorkbookData): void;
}
interface State$6 {
groups: Record<UID, Record<Dimension, HeaderGroup[]>>;
}
declare class HeaderGroupingPlugin extends CorePlugin<State$6> {
static getters: readonly ["getHeaderGroups", "getGroupsLayers", "getVisibleGroupLayers", "getHeaderGroup", "getHeaderGroupsInZone", "isGroupFolded", "isRowFolded", "isColFolded"];
private readonly groups;
allowDispatch(cmd: CoreCommand): CommandResult;
handle(cmd: CoreCommand): void;
getHeaderGroups(sheetId: UID, dim: Dimension): HeaderGroup[];
getHeaderGroup(sheetId: UID, dim: Dimension, start: number, end: number): HeaderGroup | undefined;
getHeaderGroupsInZone(sheetId: UID, dim: Dimension, zone: Zone): HeaderGroup[];
/**
* Get all the groups of a sheet in a dimension, and return an array of layers of those groups.
*
* The layering rules are:
* 1) A group containing another group should be on a layer above the group it contains
* 2) The widest/highest groups should be on the left/top layer compared to the groups it contains
* 3) The group should be on the left/top-most layer possible, barring intersections with other groups (see rules 1 and 2)
*/
getGroupsLayers(sheetId: UID, dimension: Dimension): HeaderGroup[][];
/**
* Get all the groups of a sheet in a dimension, and return an array of layers of those groups,
* excluding the groups that are totally hidden.
*/
getVisibleGroupLayers(sheetId: UID, dimension: Dimension): HeaderGroup[][];
isGroupFolded(sheetId: UID, dimension: Dimension, start: number, end: number): boolean;
isRowFolded(sheetId: UID, row: HeaderIndex): boolean;
isColFolded(sheetId: UID, col: HeaderIndex): boolean;
private getGroupId;
/**
* To get layers of groups, and to add/remove headers from groups, we can see each header of a group as a brick. Each
* brick falls down in the pile corresponding to its header, until it hits another brick, or the ground.
*
* With this abstraction, we can very simply group/ungroup headers from groups, and get the layers of groups.
* - grouping headers is done by adding a brick to each header pile
* - un-grouping headers is done by removing a brick from each header pile
* - getting the layers of groups is done by simply letting the brick fall and checking the result
*
* Example:
* We have 2 groups ([A=>E] and [C=>D]), and we want to group headers [C=>F]
*
* Headers : A B C D E F G A B C D E F G A B C D E F G
* Headers to group: [C=>D]: _ _ [C=>F]: _ _ _ _
* | | ==> | | | | ==> ==> Result: 3 groups
* | | ˅ ˅ | | _ _ - [C=>D]
* Groups: ˅ ˅ _ _ ˅ | _ _ _ - [C=>E]
* Groups: _ _ _ _ _ _ _ _ _ _ ˅ _ _ _ _ _ _ - [A=>F]
* @param groups
* @param start start of the range where to add/remove headers
* @param end end of the range where to add/remove headers
* @param delta -1: remove headers, 1: add headers, 0: get layers (don't add/remove anything)
*/
private bricksFallingAlgorithm;
private groupHeaders;
/**
* Ungroup the given headers. The headers will be taken out of the group they are in. This might split a group into two
* if the headers were in the middle of a group. If multiple groups contains a header, it will only be taken out of the
* lowest group in the layering of the groups.
*/
private unGroupHeaders;
private moveGroupsOnHeaderInsertion;
private moveGroupsOnHeaderDeletion;
private doGroupOverlap;
private removeDuplicateGroups;
private findGroupWithStartEnd;
/**
* Fold the given group, and all the groups starting at the same index that are contained inside the given group.
*/
private foldHeaderGroup;
/**
* Unfold the given group, and all the groups starting at the same index that contain the given group.
*/
private unfoldHeaderGroup;
private getGroupIndex;
import(data: WorkbookData): void;
export(data: WorkbookData): void;
exportForExcel(data: ExcelWorkbookData): void;
}
interface HeaderSizeState$1 {
sizes: Record<UID, Record<Dimension, Array<Pixel | undefined>>>;
}
declare class HeaderSizePlugin extends CorePlugin<HeaderSizeState$1> implements HeaderSizeState$1 {
static getters: readonly ["getUserRowSize", "getColSize"];
readonly sizes: Record<UID, Record<Dimension, Array<Pixel | undefined>>>;
handle(cmd: Command): void;
getColSize(sheetId: UID, index: HeaderIndex): Pixel;
getUserRowSize(sheetId: UID, index: HeaderIndex): Pixel | undefined;
import(data: WorkbookData): void;
exportForExcel(data: ExcelWorkbookData): void;
export(data: WorkbookData): void;
/**
* Export the header sizes
*
* @param exportDefaults : if true, export column/row sizes even if they have the default size
*/
exportData(data: WorkbookData, exportDefaults?: boolean): void;
}
declare class HeaderVisibilityPlugin extends CorePlugin {
static getters: readonly ["checkElementsIncludeAllVisibleHeaders", "getHiddenColsGroups", "getHiddenRowsGroups", "isHeaderHiddenByUser", "isRowHiddenByUser", "isColHiddenByUser"];
private readonly hiddenHeaders;
allowDispatch(cmd: Command): CommandResult.Success | CommandResult.NotEnoughElements | CommandResult.InvalidSheetId | CommandResult.TooManyHiddenElements | CommandResult.InvalidHeaderIndex;
handle(cmd: Command): void;
checkElementsIncludeAllVisibleHeaders(sheetId: UID, dimension: Dimension, elements: HeaderIndex[]): boolean;
isHeaderHiddenByUser(sheetId: UID, dimension: Dimension, index: HeaderIndex): boolean;
isRowHiddenByUser(sheetId: UID, index: HeaderIndex): boolean;
isColHiddenByUser(sheetId: UID, index: HeaderIndex): boolean;
getHiddenColsGroups(sheetId: UID): ConsecutiveIndexes[];
getHiddenRowsGroups(sheetId: UID): ConsecutiveIndexes[];
private getAllVisibleHeaders;
import(data: WorkbookData): void;
exportForExcel(data: ExcelWorkbookData): void;
export(data: WorkbookData): void;
exportData(data: WorkbookData, exportDefaults?: boolean): void;
}
type FilePath = string;
/**
* FileStore manage the transfer of file with the server.
*/
interface FileStore {
/**
* Upload a file to a server and returns its path.
*/
upload(file: File): Promise<FilePath>;
/**
* get File from the server
*/
getFile(filePath: FilePath): Promise<File | Blob>;
}
/**
* ImageProvider can request the user to input an image file before sending it to a server.
*/
interface ImageProviderInterface {
/**
* RequestImage ask the user to input an image file. Then send it to a server trough an FileStore. Finally it return the path and the size of the image in the server.
*/
requestImage(): Promise<Image>;
uploadFile(file: File | Blob): Promise<Image>;
getImageOriginalSize(path: string): Promise<FigureSize>;
}
interface ImageState {
readonly images: Record<UID, Record<UID, Image | undefined> | undefined>;
}
declare class ImagePlugin extends CorePlugin<ImageState> implements ImageState {
static getters: readonly ["getImage", "getImagePath", "getImageSize"];
readonly fileStore?: FileStore;
readonly images: Record<UID, Record<UID, Image | undefined> | undefined>;
/**
* paths of images synced with the file store server.
*/
readonly syncedImages: Set<Image["path"]>;
constructor(config: CorePluginConfig);
allowDispatch(cmd: CoreCommand): CommandResult.Success | CommandResult.InvalidFigureId;
handle(cmd: CoreCommand): void;
getImage(figureId: UID): Image;
getImagePath(figureId: UID): string;
getImageSize(figureId: UID): FigureSize;
private addFigure;
import(data: WorkbookData): void;
export(data: WorkbookData): void;
exportForExcel(data: ExcelWorkbookData): void;
}
type SheetMergeCellMap = Record<number, Record<number, number | undefined> | undefined>;
interface MergeState {
readonly merges: Record<UID, Record<number, Range | undefined> | undefined>;
readonly mergeCellMap: Record<UID, SheetMergeCellMap | undefined>;
}
declare class MergePlugin extends CorePlugin<MergeState> implements MergeState {
static getters: readonly ["isInMerge", "isInSameMerge", "isMergeHidden", "getMainCellPosition", "expandZone", "doesIntersectMerge", "doesColumnsHaveCommonMerges", "doesRowsHaveCommonMerges", "getMerges", "getMerge", "getMergesInZone", "isSingleCellOrMerge", "getSelectionRangeString", "isMainCellPosition"];
private nextId;
readonly merges: Record<UID, Record<number, Range | undefined> | undefined>;
readonly mergeCellMap: Record<UID, SheetMergeCellMap | undefined>;
allowDispatch(cmd: CoreCommand): CommandResult | CommandResult[];