import type { ICellAddress, AnnotationLayout, IRectangle, CellStyle } from '../../treb-base-types/src/index'; import { Rectangle } from '../../treb-base-types/src/index'; /** * moving view-specific data into a separate interface to support split. * nothing in view is serialized. */ export interface ViewData { /** flag indicating we have inflated this. not serialized */ inflated?: boolean; /** if function exists, will be called when the annotation is resized */ resize_callback?: () => void; /** if function exists, will be called when the annotation needs to update */ update_callback?: () => void; /** layout node */ node?: HTMLDivElement; /** content node */ content_node?: HTMLDivElement; /** view-specific dirty flag */ dirty?: boolean; } export interface ImageSize { width: number; height: number; } export interface ImageAnnotationData { src: string; /** * @privateRemarks * why is this a string? */ scale?: string; original_size?: ImageSize; } export type AnnotationType = 'treb-chart' | 'image' | 'textbox' | 'external'; /** * splitting persisted data from the annotation class. that class might * disappear in the future in favor of just a type. this interface should * fully match the old Partial we used before. note that we * used to define values for all members, but they may now be undefined * because the Annotation class as a Partial instance of this data. * * conceptually annotation was originally intended to support types other * than our own charts and images, but no one ever used it. so we could * lock down the `type` field if we wanted to. or perhaps have an `external` * type with opaque data. TODO. * */ export interface AnnotationDataBase { /** the new layout, persisted and takes preference over the old one */ layout?: AnnotationLayout; /** * adding cell style as a convenient store for font stack; atm we are * ignoring everything but the font_face attribute */ style?: CellStyle; /** * the old layout used rectangles, and we need to keep support for * that. this is not the layout rectangle. this rectangle is just * for serialization/deserialization. the actual rectangle is maintained * in the Annotation class. */ rect?: Partial; /** annotation can be resized. this is advisory, for UI */ resizable: boolean; /** annotation can be moved. this is advisory, for UI */ movable: boolean; /** annotation can be removed/deleted. this is advisory, for UI */ removable: boolean; /** annotation can be selected. this is advisory, for UI */ selectable: boolean; /** move when resizing/inserting rows/columns */ move_with_cells: boolean; /** resize when resizing/inserting rows/columns */ resize_with_cells: boolean; /** * optional formula. the formula will be updated on structure events * (insert/delete row/column). */ formula: string; /** * extent, useful for exporting. we could probably serialize this, * just be sure to clear it when layout changes so it will be * recalculated. * * the idea is to know the bottom/right row/column of the annotation, * so when we preserve/restore the sheet we don't trim those rows/columns. * they don't need any data, but it just looks bad. we can do this * dynamically but since it won't change all that often, we might * as well precalculate. */ extent: ICellAddress; } export interface AnnotationImageData extends AnnotationDataBase { type: 'image'; data: ImageAnnotationData; } export interface AnnotationChartData extends AnnotationDataBase { type: 'treb-chart'; } export interface AnnotationTextBoxData extends AnnotationDataBase { type: 'textbox'; /** * @internalRemarks * what's with this weird structure? did we inherit it? can we clean it up? */ data: { style?: CellStyle; paragraphs: { style?: CellStyle; content: { text: string; style?: CellStyle; }[]; }[]; }; } export interface AnnotationExternalData extends AnnotationDataBase { type: 'external'; data: Record; } export type AnnotationData = AnnotationChartData | AnnotationImageData | AnnotationExternalData | AnnotationTextBoxData; /** * why is this a class? it doesn't do anything. * FIXME: -> interface */ export declare class Annotation { data: Partial; /** * the key field is used to identify and coordinate annotations when we * have freeze panes. when an annotation crosses a freeze pane, we need * two copies of the rendered node so that we can scroll. we use the key * to match the frozen/unfrozen instances. */ get key(): number; /** coordinates, in sheet space */ rect?: Rectangle; /** display coordinates, possibly scaled. not persisted. */ scaled_rect?: Rectangle; /** also opaque data, but not serialized. */ temp: unknown; view: ViewData[]; /** * advisory, meaning we probably need an update if there's an opportunity. * only advisory and not persisted. */ dirty?: boolean; private key_; /** * constructor takes persisted data */ constructor(opts?: Partial); /** * serialization just returns persisted data, plus we update the * rectangle. * * anyone serializing annotations should just be fetching the data * object, but we're leaving this in place because we can't trace * it back using tooling. that's a real drawback of toJSON, we * should stop using it. * * although as long as we need to support `rect` here, it's not bad * that we do it this way. perhaps change the function name, and * call it directly? * */ toJSON(): Partial; }