UNPKG

@odoo/o-spreadsheet

Version:
1,460 lines (1,415 loc) 527 kB
import * as chart_js from 'chart.js'; import { ChartConfiguration, CoreChartOptions, Scriptable, Color as Color$1, ScriptableContext, FontSpec, ChartDataset, Point, ChartType as ChartType$1, ChartMeta } from 'chart.js'; import * as ChartGeo from 'chartjs-chart-geo'; import * as GeoJSON$1 from 'geojson'; import * as _odoo_owl from '@odoo/owl'; import { ComponentConstructor, Component } from '@odoo/owl'; 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 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'; interface FigureInfo { id: UID; width: Pixel; height: Pixel; tag: string; } interface Figure extends FigureInfo, AnchorOffset { } interface FigureUI extends DOMCoordinates, Figure { } interface AnchorOffset { col: HeaderIndex; row: HeaderIndex; offset: PixelPosition; } interface FigureSize { width: Pixel; height: Pixel; } interface ExcelFigureSize { cx: number; cy: number; } type ResizeDirection = -1 | 0 | 1; interface Carousel { readonly items: CarouselItem[]; readonly title?: TitleDesign; } type CarouselItem = { type: "chart"; chartId: UID; title?: string; } | { type: "carouselDataView"; title?: string; }; type ImageSVG = { name: string; width: number; height: number; paths: { path: string; fillColor: Color; }[]; }; interface Image$1 { path: string; size: FigureSize; mimetype?: string; } declare const AllowedImageMimeTypes: readonly ["image/avif", "image/bmp", "image/gif", "image/vnd.microsoft.icon", "image/jpeg", "image/png", "image/tiff", "image/webp"]; type XLSXExportFile = XLSXExportImageFile | XLSXExportXMLFile; interface XLSXExportXMLFile { path: string; content: string; contentType?: string; } interface XLSXExportImageFile { path: string; imageSrc: string; } interface XLSXExport { name: string; files: XLSXExportFile[]; } /** * Standardized XLSX hexadecimal color (with or without alpha channel). * Note that the alpha channel goes first! AARRGGBB * e.g. "1E5010" or "331E5010" */ type XlsxHexColor = string & Alias; type VerticalAxisPosition = "left" | "right"; type LegendPosition = "top" | "bottom" | "left" | "right" | "none"; interface CommonChartDefinition { readonly dataSets: CustomizedDataSet[]; readonly dataSetsHaveTitle: boolean; readonly labelRange?: string; readonly title: TitleDesign; readonly background?: Color; readonly legendPosition: LegendPosition; readonly aggregated?: boolean; readonly axesDesign?: AxesDesign; readonly showValues?: boolean; readonly humanize?: boolean; } interface TreeMapChartDefinition { readonly type: "treemap"; readonly dataSets: CustomizedDataSet[]; readonly dataSetsHaveTitle: boolean; readonly labelRange?: string; readonly title: TitleDesign; readonly background?: Color; readonly legendPosition: LegendPosition; readonly showHeaders?: boolean; readonly headerDesign?: TitleDesign; readonly showValues?: boolean; readonly showLabels?: boolean; readonly valuesDesign?: TitleDesign; readonly coloringOptions?: TreeMapColoringOptions; readonly humanize?: boolean; } type TreeMapCategoryColorOptions = { type: "categoryColor"; colors: (Color | undefined | null)[]; useValueBasedGradient: boolean; }; type TreeMapColorScaleOptions = { type: "colorScale"; minColor: Color; midColor?: Color; maxColor: Color; }; interface TreeMapGroupColor { label: string; color: Color; } type TreeMapColoringOptions = TreeMapCategoryColorOptions | TreeMapColorScaleOptions; type TreeMapChartRuntime = { chartJsConfig: ChartConfiguration; background: Color; }; /*! * chartjs-chart-treemap v3.1.0 * https://chartjs-chart-treemap.pages.dev/ * (c) 2024 Jukka Kurkela * Released under the MIT license */ type AnyObject = Record<string, unknown>; type TreemapScriptableContext = ScriptableContext<"treemap"> & { raw: TreemapDataPoint; }; type TreemapControllerDatasetCaptionsOptions = { align?: Scriptable<LabelAlign, TreemapScriptableContext>; color?: Scriptable<Color$1, TreemapScriptableContext>; display?: boolean; formatter?: Scriptable<string, TreemapScriptableContext>; font?: FontSpec; hoverColor?: Scriptable<Color$1, TreemapScriptableContext>; hoverFont?: FontSpec; padding?: number; }; type TreemapControllerDatasetLabelsOptions = { align?: Scriptable<LabelAlign, TreemapScriptableContext>; color?: Scriptable<Color$1 | Color$1[], TreemapScriptableContext>; display?: boolean; formatter?: Scriptable<string | Array<string>, TreemapScriptableContext>; font?: Scriptable<FontSpec | FontSpec[], TreemapScriptableContext>; hoverColor?: Scriptable<Color$1 | Color$1[], TreemapScriptableContext>; hoverFont?: Scriptable<FontSpec | FontSpec[], TreemapScriptableContext>; overflow?: Scriptable<LabelOverflow, TreemapScriptableContext>; padding?: number; position?: Scriptable<LabelPosition, TreemapScriptableContext>; }; type LabelPosition = "top" | "middle" | "bottom"; type LabelAlign = "left" | "center" | "right"; type LabelOverflow = "cut" | "hidden" | "fit"; type TreemapControllerDatasetDividersOptions = { display?: boolean; lineCapStyle?: string; lineColor?: string; lineDash?: number[]; lineDashOffset?: number; lineWidth?: number; }; interface TreemapControllerDatasetOptions<DType> { spacing?: number; rtl?: boolean; backgroundColor?: Scriptable<Color$1, TreemapScriptableContext>; borderColor?: Scriptable<Color$1, TreemapScriptableContext>; borderWidth?: number; hoverBackgroundColor?: Scriptable<Color$1, TreemapScriptableContext>; hoverBorderColor?: Scriptable<Color$1, TreemapScriptableContext>; hoverBorderWidth?: number; captions?: TreemapControllerDatasetCaptionsOptions; dividers?: TreemapControllerDatasetDividersOptions; labels?: TreemapControllerDatasetLabelsOptions; label?: string; data: TreemapDataPoint[]; groups?: Array<keyof DType>; sumKeys?: Array<keyof DType>; tree: number[] | DType[] | AnyObject; treeLeafKey?: keyof DType; key?: keyof DType; hidden?: boolean; displayMode?: "containerBoxes" | "headerBoxes"; groupColors?: TreeMapGroupColor[]; } interface TreemapDataPoint { x: number; y: number; w: number; h: number; /** * Value */ v: number; /** * Sum */ s: number; /** * Depth, only available if grouping */ l?: number; /** * Group name, only available if grouping */ g?: string; /** * Group Sum, only available if grouping */ gs?: number; /** * additonal keys sums, only available if grouping */ vs?: AnyObject; isLeaf?: boolean; } declare module "chart.js" { interface ChartTypeRegistry { treemap: { chartOptions: CoreChartOptions<"treemap">; datasetOptions: TreemapControllerDatasetOptions<Record<string, unknown>>; defaultDataPoint: TreemapDataPoint; metaExtensions: AnyObject; parsedDataType: unknown; scales: never; }; } } interface FunnelChartDefinition { readonly type: "funnel"; readonly dataSets: CustomizedDataSet[]; readonly dataSetsHaveTitle: boolean; readonly labelRange?: string; readonly title: TitleDesign; readonly background?: Color; readonly legendPosition: LegendPosition; readonly horizontal?: boolean; readonly axesDesign?: AxesDesign; readonly aggregated?: boolean; readonly showValues?: boolean; readonly funnelColors?: FunnelChartColors; readonly cumulative?: boolean; readonly humanize?: boolean; } type FunnelChartRuntime = { chartJsConfig: ChartConfiguration; background: Color; }; type FunnelChartColors = (Color | undefined)[]; interface GaugeChartDefinition { readonly type: "gauge"; readonly title: TitleDesign; readonly dataRange?: string; readonly sectionRule: SectionRule; readonly background?: Color; readonly humanize?: boolean; } interface SectionRule { readonly colors: ColorSet; readonly rangeMin: string; readonly rangeMax: string; readonly lowerInflectionPoint: SectionThreshold; readonly upperInflectionPoint: SectionThreshold; } interface ColorSet { readonly lowerColor: Color; readonly middleColor: Color; readonly upperColor: Color; } interface SectionThreshold { readonly type: "number" | "percentage"; readonly value: string; readonly operator: "<" | "<="; } interface GaugeValue { value: number; label: string; } interface GaugeInflectionValue extends GaugeValue { operator: "<" | "<="; } interface GaugeChartRuntime { background: Color; title: TitleDesign; minValue: GaugeValue; maxValue: GaugeValue; gaugeValue?: GaugeValue; inflectionValues: GaugeInflectionValue[]; colors: Color[]; } interface LineChartDefinition extends CommonChartDefinition { readonly type: "line"; readonly labelsAsText: boolean; readonly stacked: boolean; readonly aggregated?: boolean; readonly cumulative: boolean; readonly fillArea?: boolean; readonly hideDataMarkers?: boolean; readonly zoomable?: boolean; } type LineChartRuntime = { chartJsConfig: ChartConfiguration; masterChartConfig?: ChartConfiguration; background: Color; }; interface PieChartDefinition extends CommonChartDefinition { readonly type: "pie"; readonly aggregated?: boolean; readonly isDoughnut?: boolean; readonly showValues?: boolean; readonly pieHolePercentage?: number; } type PieChartRuntime = { chartJsConfig: ChartConfiguration<"pie" | "doughnut">; background: Color; }; interface PyramidChartDefinition extends Omit<BarChartDefinition, "type"> { readonly type: "pyramid"; } type PyramidChartRuntime = { chartJsConfig: ChartConfiguration; background: Color; }; interface ScatterChartDefinition extends Omit<LineChartDefinition, "type" | "stacked" | "cumulative"> { readonly type: "scatter"; } type ScatterChartRuntime = LineChartRuntime; interface ScorecardChartDefinition { readonly type: "scorecard"; readonly title: TitleDesign; readonly keyValue?: string; readonly keyDescr?: TitleDesign; readonly baseline?: string; readonly baselineMode: BaselineMode; readonly baselineDescr?: TitleDesign; readonly background?: Color; readonly baselineColorUp: Color; readonly baselineColorDown: Color; readonly humanize?: boolean; } type BaselineMode = "text" | "difference" | "percentage" | "progress"; type BaselineArrowDirection = "neutral" | "up" | "down"; interface ProgressBar { readonly value: number; readonly color: Color; } interface ScorecardChartRuntime { readonly title: TitleDesign; readonly keyValue: string; readonly keyDescr: string; readonly baselineDisplay: string; readonly baselineColor?: string; readonly baselineArrow: BaselineArrowDirection; readonly baselineDescr?: string; readonly background: Color; readonly fontColor: Color; readonly keyValueStyle?: Style; readonly keyValueDescrStyle?: Style; readonly baselineStyle?: Style; readonly baselineDescrStyle?: Style; readonly progressBar?: ProgressBar; } interface SunburstChartDefinition { readonly type: "sunburst"; readonly dataSets: CustomizedDataSet[]; readonly dataSetsHaveTitle: boolean; readonly labelRange?: string; readonly title: TitleDesign; readonly background?: Color; readonly legendPosition: LegendPosition; readonly showValues?: boolean; readonly showLabels?: boolean; readonly valuesDesign?: ChartStyle; readonly groupColors?: (Color | undefined | null)[]; readonly pieHolePercentage?: number; readonly humanize?: boolean; } type SunburstChartRuntime = { chartJsConfig: ChartConfiguration<"doughnut">; background: Color; }; interface SunburstChartJSDataset extends ChartDataset<"doughnut"> { groupColors: { label: string; color: Color; }[]; } interface WaterfallChartDefinition extends CommonChartDefinition { readonly type: "waterfall"; readonly verticalAxisPosition: VerticalAxisPosition; readonly aggregated?: boolean; readonly showSubTotals: boolean; readonly showConnectorLines: boolean; readonly firstValueAsSubtotal?: boolean; readonly positiveValuesColor?: Color; readonly negativeValuesColor?: Color; readonly subTotalValuesColor?: Color; readonly zoomable?: boolean; } type WaterfallChartRuntime = { chartJsConfig: ChartConfiguration; background: Color; }; interface BarChartDefinition extends CommonChartDefinition { readonly type: "bar"; readonly stacked: boolean; readonly horizontal?: boolean; readonly zoomable?: boolean; } type BarChartRuntime = { chartJsConfig: ChartConfiguration; masterChartConfig?: ChartConfiguration; background: Color; }; interface ComboChartDefinition extends CommonChartDefinition { readonly dataSets: ComboChartDataSet[]; readonly type: "combo"; readonly hideDataMarkers?: boolean; readonly zoomable?: boolean; } type ComboChartDataSet = CustomizedDataSet & { type?: "bar" | "line"; }; type ComboChartRuntime = { chartJsConfig: ChartConfiguration; masterChartConfig?: ChartConfiguration; background: Color; }; interface GeoChartDefinition { readonly type: "geo"; readonly dataSets: CustomizedDataSet[]; readonly dataSetsHaveTitle: boolean; readonly labelRange?: string; readonly title: TitleDesign; readonly background?: Color; readonly legendPosition: LegendPosition; readonly colorScale?: GeoChartColorScale; readonly missingValueColor?: Color; readonly region?: string; readonly humanize?: boolean; } type GeoChartRuntime = { chartJsConfig: ChartConfiguration; background: Color; }; interface GeoChartCustomColorScale { minColor: Color; midColor?: Color; maxColor: Color; } type GeoChartColorScale = GeoChartCustomColorScale | "blues" | "cividis" | "greens" | "greys" | "oranges" | "purples" | "rainbow" | "reds" | "viridis"; type GeoChartProjection = "azimuthalEqualArea" | "azimuthalEquidistant" | "gnomonic" | "orthographic" | "stereographic" | "equalEarth" | "albers" | "albersUsa" | "conicConformal" | "conicEqualArea" | "conicEquidistant" | "equirectangular" | "mercator" | "transverseMercator" | "naturalEarth1"; interface GeoChartRegion { id: string; label: string; defaultProjection: GeoChartProjection; } interface GeoChartRuntimeGenerationArgs extends ChartRuntimeGenerationArgs { availableRegions: GeoChartRegion[]; getGeoJsonFeatures: (region: string) => GeoJSON.Feature[] | undefined; geoFeatureNameToId: (region: string, featureName: string) => string | undefined; } interface RadarChartDefinition extends CommonChartDefinition { readonly type: "radar"; readonly aggregated?: boolean; readonly stacked: boolean; readonly fillArea?: boolean; readonly hideDataMarkers?: boolean; readonly humanize?: boolean; } type RadarChartRuntime = { chartJsConfig: ChartConfiguration; background: Color; }; declare const CHART_TYPES: readonly ["line", "bar", "pie", "scorecard", "gauge", "scatter", "combo", "waterfall", "pyramid", "radar", "geo", "funnel", "sunburst", "treemap"]; type ChartType = (typeof CHART_TYPES)[number]; type ChartDefinition = LineChartDefinition | PieChartDefinition | BarChartDefinition | ScorecardChartDefinition | GaugeChartDefinition | ScatterChartDefinition | ComboChartDefinition | WaterfallChartDefinition | PyramidChartDefinition | RadarChartDefinition | GeoChartDefinition | FunnelChartDefinition | SunburstChartDefinition | TreeMapChartDefinition; type ChartWithDataSetDefinition = Extract<ChartDefinition, { dataSets: CustomizedDataSet[]; labelRange?: string; humanize?: boolean; }>; type ChartWithAxisDefinition = Extract<ChartWithDataSetDefinition, { axesDesign?: AxesDesign; }>; type ZoomableChartDefinition = Extract<ChartWithAxisDefinition, { zoomable?: boolean; }>; type ChartJSRuntime = LineChartRuntime | PieChartRuntime | BarChartRuntime | ComboChartRuntime | ScatterChartRuntime | WaterfallChartRuntime | PyramidChartRuntime | RadarChartRuntime | GeoChartRuntime | FunnelChartRuntime | SunburstChartRuntime | TreeMapChartRuntime; type ChartRuntime = ChartJSRuntime | ScorecardChartRuntime | GaugeChartRuntime; interface LabelValues { readonly values: string[]; readonly formattedValues: string[]; } interface DatasetValues { readonly label?: string; readonly data: any[]; readonly hidden?: boolean; } interface DatasetDesign { readonly backgroundColor?: string; readonly yAxisId?: string; readonly label?: string; } interface AxisDesign { readonly title?: TitleDesign; } interface AxesDesign { readonly x?: AxisDesign; readonly y?: AxisDesign; readonly y1?: AxisDesign; } interface ChartStyle { readonly bold?: boolean; readonly italic?: boolean; readonly align?: Align; readonly verticalAlign?: VerticalAlign; readonly color?: Color; readonly fontSize?: number; readonly fillColor?: Color; } interface TitleDesign extends ChartStyle { readonly text?: string; } type TrendType = "polynomial" | "exponential" | "logarithmic" | "trailingMovingAverage"; interface TrendConfiguration { type?: TrendType; order?: number; color?: Color; display?: boolean; window?: number; } type CustomizedDataSet = { readonly dataRange: string; readonly trend?: TrendConfiguration; } & DatasetDesign; type AxisType = "category" | "linear" | "time"; type ChartDatasetOrientation = "rows" | "columns"; interface DataSet { readonly labelCell?: Range; readonly dataRange: Range; readonly rightYAxis?: boolean; readonly backgroundColor?: Color; readonly customLabel?: string; readonly trend?: TrendConfiguration; } interface ExcelChartDataset { readonly label?: { text?: string; } | { reference?: string; }; readonly range: string; readonly backgroundColor?: Color; readonly rightYAxis?: boolean; readonly trend?: ExcelChartTrendConfiguration; } interface ExcelChartTrendConfiguration { readonly type?: ExcelTrendlineType; readonly order?: number; readonly color?: Color; readonly window?: number; } type ExcelTrendlineType = "poly" | "exp" | "log" | "movingAvg" | "linear"; type ExcelChartType = "line" | "bar" | "pie" | "combo" | "scatter" | "radar" | "pyramid"; interface ExcelChartDefinition { readonly title?: TitleDesign; readonly type: ExcelChartType; readonly dataSets: ExcelChartDataset[]; readonly labelRange?: string; readonly backgroundColor: XlsxHexColor; readonly fontColor: XlsxHexColor; readonly legendPosition: LegendPosition; readonly stacked?: boolean; readonly cumulative?: boolean; readonly verticalAxis?: { useLeftAxis?: boolean; useRightAxis?: boolean; }; readonly axesDesign?: AxesDesign; readonly horizontal?: boolean; readonly isDoughnut?: boolean; readonly pieHolePercentage?: number; readonly maxValue?: number; } interface ChartCreationContext { readonly range?: CustomizedDataSet[]; readonly hierarchicalRanges?: CustomizedDataSet[]; readonly title?: TitleDesign; readonly background?: Color; readonly auxiliaryRange?: string; readonly aggregated?: boolean; readonly stacked?: boolean; readonly cumulative?: boolean; readonly dataSetsHaveTitle?: boolean; readonly labelsAsText?: boolean; readonly showSubTotals?: boolean; readonly showConnectorLines?: boolean; readonly firstValueAsSubtotal?: boolean; readonly legendPosition?: LegendPosition; readonly axesDesign?: AxesDesign; readonly fillArea?: boolean; readonly showValues?: boolean; readonly funnelColors?: FunnelChartColors; readonly showLabels?: boolean; readonly hideDataMarkers?: boolean; readonly valuesDesign?: ChartStyle; readonly groupColors?: (Color | undefined | null)[]; readonly horizontal?: boolean; readonly isDoughnut?: boolean; readonly pieHolePercentage?: number; readonly showHeaders?: boolean; readonly headerDesign?: TitleDesign; readonly treemapColoringOptions?: TreeMapColoringOptions; readonly zoomable?: boolean; readonly humanize?: boolean; } type ChartAxisFormats = { [axisId: string]: Format | undefined; } | undefined; interface ChartRuntimeGenerationArgs { dataSetsValues: DatasetValues[]; axisFormats: ChartAxisFormats; labels: string[]; locale: Locale; trendDataSetsValues?: (Point[] | undefined)[]; axisType?: AxisType; topPadding?: number; } /** Generic definition of chart to create a runtime: omit the chart type and the dataRange of the dataSets*/ type GenericDefinition<T extends ChartWithDataSetDefinition> = Partial<Omit<T, "dataSets" | "type">> & { dataSets?: Omit<T["dataSets"][number], "dataRange">[]; }; /** * 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 SelectiveHistory<T = unknown> { private HEAD_BRANCH; private HEAD_OPERATION; private tree; private readonly applyOperation; private readonly revertOperation; private readonly buildEmpty; private readonly buildTransformation; /** * The selective history is a data structure used to register changes/updates of a state. * Each change/update is called an "operation". * The data structure allows to easily cancel (and redo) any operation individually. * An operation can be represented by any data structure. It can be a "command", a "diff", etc. * However it must have the following properties: * - it can be applied to modify the state * - it can be reverted on the state such that it was never executed. * - it can be transformed given other operation (Operational Transformation) * * Since this data structure doesn't know anything about the state nor the structure of * operations, the actual work must be performed by external functions given as parameters. * @param initialOperationId * @param applyOperation a function which can apply an operation to the state * @param revertOperation a function which can revert an operation from the state * @param buildEmpty a function returning an "empty" operation. * i.e an operation that leaves the state unmodified once applied or reverted * (used for internal implementation) * @param buildTransformation Factory used to build transformations */ constructor(args: { initialOperationId: UID; applyOperation: (data: T) => void; revertOperation: (data: T) => void; buildEmpty: (id: UID) => T; buildTransformation: TransformationFactory<T>; }); /** * Return the operation identified by its id. */ get(operationId: UID): T; /** * Append a new operation as the last one */ append(operationId: UID, data: T): void; /** * Insert a new operation after a specific operation (may not be the last operation). * Following operations will be transformed according * to the new operation. */ insert(operationId: UID, data: T, insertAfter: UID): void; /** * @param operationId operation to undo * @param undoId the id of the "undo operation" * @param insertAfter the id of the operation after which to insert the undo */ undo(operationId: UID, undoId: UID, insertAfter: UID): void; /** * @param operationId operation to redo * @param redoId the if of the "redo operation" * @param insertAfter the id of the operation after which to insert the redo */ redo(operationId: UID, redoId: UID, insertAfter: UID): void; rebase(operationId: UID): void; /** * Revert the state as it was *before* the given operation was executed. */ private revertBefore; /** * Revert the state as it was *after* the given operation was executed. */ private revertTo; /** * Revert an execution */ private revert; /** * Replay the operations between the current HEAD_BRANCH and the end of the tree */ private fastForward; } type ClientId = string; interface Client { id: ClientId; name: string; position?: ClientPosition; color?: Color; } interface ClientWithPosition extends Client { position: ClientPosition; } interface ClientWithColor extends Client { color: Color; } interface ClientPosition { sheetId: UID; col: HeaderIndex; row: HeaderIndex; } interface RemoteRevisionReceivedEvent { type: "remote-revision-received"; commands: readonly CoreCommand[]; } interface RevisionAcknowledgedEvent { type: "revision-acknowledged"; revisionId: UID; } interface RevisionUndone { type: "revision-undone"; revisionId: UID; commands: readonly CoreCommand[]; } interface RevisionRedone { type: "revision-redone"; revisionId: UID; commands: readonly CoreCommand[]; } interface CollaborativeEventReceived { type: "collaborative-event-received"; } interface UnexpectedRevisionIdEvent { type: "unexpected-revision-id"; } interface NewLocalStateUpdateEvent { type: "new-local-state-update"; id: UID; } interface SnapshotEvent { type: "snapshot"; } type CollaborativeEvent = NewLocalStateUpdateEvent | UnexpectedRevisionIdEvent | RemoteRevisionReceivedEvent | RevisionAcknowledgedEvent | RevisionUndone | RevisionRedone | SnapshotEvent | CollaborativeEventReceived; type CollaborativeEventTypes = CollaborativeEvent["type"]; 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]>; } /** * RGBA to HEX representation (#RRGGBBAA). * * https://css-tricks.com/converting-color-spaces-in-javascript/ */ declare function rgbaToHex(rgba: RGBA): Color; /** * Color string to RGBA representation */ declare function colorToRGBA(color: Color): RGBA; declare class ColorGenerator { private preferredColors; private currentColorIndex; protected palette: Color[]; constructor(paletteSize: number, preferredColors?: (Color | undefined | null)[]); next(): string; } 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 RangeStringOptions { useBoundedReference?: boolean; useFixedReference?: boolean; } interface RangeData { _zone: Zone | UnboundedZone; _sheetId: UID; } 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; 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; /** * Convert a (col) number to the corresponding letter. * * Examples: * 0 => 'A' * 25 => 'Z' * 26 => 'AA' * 27 => 'AB' */ declare function numberToLetters(n: number): string; declare function lettersToNumber(letters: string): number; /** * Convert a "XC" coordinate to cartesian coordinates. * * Examples: * A1 => [0,0] * B3 => [1,2] * * Note: it also accepts lowercase coordinates, but not fixed references */ declare function toCartesian(xc: string): Position$1; /** * Convert from cartesian coordinate to the "XC" coordinate system. * * Examples: * - 0,0 => A1 * - 1,2 => B3 * - 0,0, {colFixed: false, rowFixed: true} => A$1 * - 1,2, {colFixed: true, rowFixed: false} => $B3 */ declare function toXC(col: HeaderIndex, row: HeaderIndex, rangePart?: RangePart): string; /** * A DateTime object that can be used to manipulate spreadsheet dates. * Conceptually, a spreadsheet date is simply a number with a date format, * and it is timezone-agnostic. * This DateTime object consistently uses UTC time to represent a naive date and time. */ declare class DateTime { private jsDate; constructor(year: number, month: number, day: number, hours?: number, minutes?: number, seconds?: number); static fromTimestamp(timestamp: number): DateTime; static now(): DateTime; toString(): string; toLocaleDateString(): string; getTime(): number; getFullYear(): number; getMonth(): number; getQuarter(): number; getDate(): number; getDay(): number; getHours(): number; getMinutes(): number; getSeconds(): number; getIsoWeek(): number; setFullYear(year: number): number; setMonth(month: number): number; setDate(date: number): number; setHours(hours: number): number; setMinutes(minutes: number): number; setSeconds(seconds: number): number; } declare function isDateTime(str: string, locale: Locale): boolean; interface FormatWidth { availableWidth: number; measureText: (text: string) => number; } /** * Formats a cell value with its format. */ declare function formatValue(value: CellValue, { format, locale, formatWidth }: LocaleFormat & { formatWidth?: FormatWidth; }): FormattedValue; declare function createCurrencyFormat(currency: Partial<Currency>): Format; /** * 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; /** * Registry * * The Registry class is basically just a mapping from a string key to an object. * It is really not much more than an object. It is however useful for the * following reasons: * * 1. it let us react and execute code when someone add something to the registry * (for example, the FunctionRegistry subclass this for this purpose) * 2. it throws an error when the get operation fails * 3. it provides a chained API to add items to the registry. */ declare class Registry<T> { content: { [key: string]: T; }; /** * Add an item to the registry, you can only add if there is no item * already present in the registery with the given key * * Note that this also returns the registry, so another add method call can * be chained */ add(key: string, value: T): this; /** * Replace (or add) an item to the registry * * Note that this also returns the registry, so another add method call can * be chained */ replace(key: string, value: T): this; /** * Get an item from the registry */ get(key: string): T; /** * Check if the key is already in the registry */ contains(key: string): boolean; /** * Get a list of all elements in the registry */ getAll(): T[]; /** * Get a list of all keys in the registry */ getKeys(): string[]; /** * Remove an item from the registry */ remove(key: string): void; } declare function splitReference(ref: string): { sheetName?: string; xc: string; }; declare function computeTextWidth(context: CanvasRenderingContext2D, text: string, style: Style, fontUnit?: "px" | "pt"): number; declare class UuidGenerator { /** * 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; } /** * Convert from a cartesian reference to a (possibly unbounded) Zone * * Examples: * "A1" ==> Top 0, Bottom 0, Left: 0, Right: 0 * "B1:B3" ==> Top 0, Bottom 3, Left: 1, Right: 1 * "B:B" ==> Top 0, Bottom undefined, Left: 1, Right: 1 * "B2:B" ==> Top 1, Bottom undefined, Left: 1, Right: 1, hasHeader: 1 * "Sheet1!A1" ==> Top 0, Bottom 0, Left: 0, Right: 0 * "Sheet1!B1:B3" ==> Top 0, Bottom 3, Left: 1, Right: 1 * * @param xc the string reference to convert * */ declare function toUnboundedZone(xc: string): UnboundedZone; /** * Convert from a cartesian reference to a Zone. * Will return throw an error if given a unbounded zone (eg : A:A). * * Examples: * "A1" ==> Top 0, Bottom 0, Left: 0, Right: 0 * "B1:B3" ==> Top 0, Bottom 2, Left: 1, Right: 1 * "Sheet1!A1" ==> Top 0, Bottom 0, Left: 0, Right: 0 * "Sheet1!B1:B3" ==> Top 0, Bottom 2, Left: 1, Right: 1 * * @param xc the string reference to convert * */ declare function toZone(xc: string): Zone; /** * Expand a zone after inserting columns or rows. * * Don't resize the zone if a col/row was added right before/after the row but only move the zone. */ declare function expandZoneOnInsertion<Z extends UnboundedZone | Zone>(zone: Z, start: "left" | "top", base: number, position: "after" | "before", quantity: number): Z; /** * Reduce a zone after deletion of elements */ declare function reduceZoneOnDeletion<Z extends UnboundedZone | Zone>(zone: Z, start: "left" | "top", elements: number[]): Z | undefined; /** * Compute the union of multiple zones. */ declare function union(...zones: Zone[]): Zone; /** * Return true if two zones overlap, false otherwise. */ declare function overlap(z1: UnboundedZone, z2: UnboundedZone): boolean; declare function isInside(col: number, row: number, zone: Zone): boolean; /** * This function will compare the modifications of selection to determine * a cell that is part of the new zone and not the previous one. */ declare function findCellInNewZone(oldZone: Zone, currentZone: Zone): Position$1; declare function positionToZone(position: Position$1): Zone; /** * Merge contiguous and overlapping zones that are in the array into bigger zones */ declare function mergeContiguousZones(zones: Zone[]): Zone[]; type SelectionEventOptions = { scrollIntoView?: boolean; unbounded?: boolean; }; interface SelectionEvent { anchor: AnchorZone; previousAnchor: AnchorZone; mode: "newAnchor" | "overrideSelection" | "updateAnchor"; options: SelectionEventOptions; } interface StreamCallbacks<Event> { handleEvent: (event: Event) => void; /** this callback will only be called when another consumer captures the stream, * not when the current consumer decides to release itself */ release?: () => void; } type StatefulStream<Event, State> = { capture(owner: unknown, state: State, callbacks: StreamCallbacks<Event>): void; registerAsDefault: (owner: unknown, state: State, callbacks: StreamCallbacks<Event>) => void; resetDefaultAnchor: (owner: unknown, state: State) => void; resetAnchor: (owner: unknown, state: State) => void; observe: (owner: unknown, callbacks: StreamCallbacks<Event>) => void; release: (owner: unknown) => void; getBackToDefault(): void; }; /** * Allows to select cells in the grid and update the selection */ interface SelectionProcessor { selectZone(anchor: AnchorZone, options?: SelectionEventOptions): DispatchResult; selectCell(col: number, row: number): DispatchResult; moveAnchorCell(direction: Direction$1, step: SelectionStep): DispatchResult; setAnchorCorner(col: number, row: number): DispatchResult; addCellToSelection(col: number, row: number): DispatchResult; resizeAnchorZone(direction: Direction$1, step: SelectionStep): DispatchResult; selectColumn(index: number, mode: SelectionEvent["mode"]): DispatchResult; selectRow(index: number, mode: SelectionEvent["mode"]): DispatchResult; selectAll(): DispatchResult; loopSelection(): DispatchResult; selectTableAroundSelection(): DispatchResult; isListening(owner: unknown): boolean; } type SelectionStreamProcessor = SelectionProcessor & StatefulStream<SelectionEvent, AnchorZone>; 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>; /** * Delete a file from the server */ delete(filePath: FilePath): Promise<void>; /** * 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$1>; uploadFile(file: File | Blob): Promise<Image$1>; getImageOriginalSize(path: string): Promise<FigureSize>; } /** * Model * * The Model class is the owner of the state of the Spreadsheet. However, it * has more a coordination role: it defers the actual state manipulation work to * plugins. * * At creation, the Model instantiates all necessary plugins. They each have * a private state (for example, the Selection plugin has the current selection). * * State changes are then performed through commands. Commands are dispatched * to the model, which will then relay them to each plugins (and the history * handler). Then, the model will trigger an 'update' event to notify whoever * is concerned that the command was applied (if it was not cancelled). * * Also, the model has an unconventional responsibility: it actually renders the * visible viewport on a canvas. This is because each plugins actually manage a * specific concern about the content of the spreadsheet, and it is more natural * if they are able to read data from their internal state to represent it on the * screen. * * Note that the Model can be used in a standalone way to manipulate * programmatically a spreadsheet. */ type Mode = "normal" | "readonly" | "dashboard"; interface ModelConfig { readonly mode: Mode; /** * Any external custom dependencies your custom plugins or functions might need. * They are available in plugins config and functions * evaluation context. */ readonly custom: Readonly<{ [key: string]: any; }>; readonly defaultCurrency?: Partial<Currency>; /** * External dependencies required to enable some features * such as uploading images. */ readonly external: Readonly<ModelExternalConfig>; readonly moveClient: (position: ClientPosition) => void; readonly transportService: TransportService; readonly client: Client; readonly snapshotRequested: boolean; readonly notifyUI: (payload: InformationNotification) => void; readonly raiseBlockingErrorUI: (text: string) => void; readonly customColors: Color[]; } interface ModelExternalConfig { readonly fileStore?: FileStore; readonly loadCurrencies?: () => Promise<Currency[]>; readonly loadLocales?: () => Promise<Locale[]>; readonly geoJsonService?: { getAvailableRegions: () => GeoChartRegion[]; getTopoJson: (region: string) => Promise<any>; /** Convert the name of a geographical feature (eg. France) to the id of the corresponding feature in the TopoJSON */ geoFeatureNameToId: (region: string, territory: string) => string | undefined; }; } declare class Model extends EventBus<any> implements CommandDispatcher { private corePlugins; private statefulUIPlugins; private range; private session; /** * In a collaborative context, some commands can be replayed, we have to ensure * that these commands are not replayed on the UI plugins. */ private isReplayingCommand; /** * A plugin can draw some contents on the canvas. But even better: it can do * so multiple times. The order of the render calls will determine a list of * "layers" (i.e., earlier calls will be obviously drawn below later calls). * This list simply keeps the renderers+layer information so the drawing code * can just iterate on it */ private renderers; /** * Internal status of the model. Important for command handling coordination */ private status; /** * The config object contains some configuration flag and callbacks */ readonly config: ModelConfig; private corePluginConfig; private coreViewPluginConfig; private uiPluginConfig; private state; readonly selection: SelectionStreamProcessor; /** * Getters are the main way the rest of the UI read data from the model. Also, * it is shared between all plugins, so they can also communicate with each * other. */ getters: Getters; /** * Getters that are accessible from the core plugins. It's a subset of `getters`, * without the UI getters */ private coreGetters; uuidGenerator: UuidGenerator; private readonly handlers; private readonly uiHandlers; private readonly coreHandlers; constructor(data?: any, config?: Partial<ModelConfig>, stateUpdateMessages?: StateUpdateMessage[], uuidGenerator?: UuidGenerator, verboseImport?: boolean); joinSession(): void; leaveSession(): Promise<void>; private setupUiPlugin; private setupCoreViewPlugin; /** * Initialize and properly configure a plugin. * * This method is private for now, but if the need arise, there is no deep * reason why the model could not add dynamically a plugin while it is running. */ private setupCorePlugin; private onRemoteRevisionReceived; private setupSession; private setupSessionEvents; private setupConfig; private setupExternalConfig; private setupCorePluginConfig; private setupCoreViewPluginConfig; private setupUiPluginConfig; /** * Check if the given command is allowed by all the plugins and the history. */ private checkDispatchAllowed; private checkDispatchAllowedCoreCommand; private checkDispatchAllowedLocalCommand; private finalize; /** * Check if a command can be dispatched, and returns a DispatchResult object with the possible * reasons the dispatch failed. */ canDispatch: CommandDispatcher["dispatch"]; /** * The dispatch method is the only entry point to manipulate data in the model. * This is through this method that commands are dispatched most of the time * recursively until no plugin want to react anymore. * * CoreCommands dispatched from this function are saved in the history. * * Small technical detail: it is defined as an arrow function. There are two * reasons for this: * 1. this means that the dispatch method can be "detached" from the model, * which is done when it is put in the environment (see the Spreadsheet * component) * 2. This allows us to define its type by using the interface CommandDispatcher */ dispatch: CommandDispatcher["dispatch"]; /** * Dispatch a command from a Core Plugin (or the History). * A command dispatched from this function is not added to the history. */ private dispatchFromCorePlugin; /** * Dispatch the given command to the given handlers. * It will call `beforeHandle` and `handle` */ private dispatchToHandlers; /** * When the Grid component is ready (= mounted), it has a reference to its * canvas and need to draw the grid on it. This is then done by calling this * method, which will dispatch the call to all registered plugins. * * Note that nothing prevent multiple grid components from calling this method * each, or one grid component calling it multiple times with a different * context. This is probably the way we should do if we want to be able to * freeze a part of the grid (so, we would need to render different zones) */ drawLayer(context: GridRenderingContext, layer: LayerName): void; /** * As the name of this method strongly implies, it is useful when we need to * export date out of the model. */ exportData(): WorkbookData; updateMode(mode: Mode): void; /** * Exports the current model data into a list of serialized XML files * to be zipped together as an *.xlsx file. * * We need to trigger a cell revaluation on every sheet and ensure that even * async functions are evaluated. * This prove to be necessary if the client did not trigger that evaluation in the first place * (e.g. open a document with several sheet and click on download before visiting each sheet) */ exportXLSX(): XLSXExport; garbageCollectExternalResources(): void; } 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;