/** * Classic cell notes (sticky comments) — text balloons anchored to worksheet cells. * * Use {@link Worksheet.comments} or the cell helpers {@link Cell.comment} / * {@link Cell.addComment} to add, read, and remove notes. Each note has author, * text, visibility, and optional width/height. Package parts are written on save. * * For modern Excel discussion threads with replies, see threaded comments instead. * * Citations: * - ECMA-376-1 §18.7 `comments` / `authors` / `author` / `comment` * (`CT_Comments`, `CT_Comment` `@ref` + `@authorId`, child `CT_Rst`) * - ECMA-376-1 content-type table * `application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml` * - ECMA-376-4 relationships table * `http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments` * (Strict twin `http://purl.oclc.org/ooxml/officeDocument/relationships/comments`) * - ECMA-376-4 §19.4.2.12 ClientData Note example (`t202`, `#ffffe1`, * `Row`/`Column` 0-based, `Visible`) and ECMA-376-1 Annex L.5.5.2 * - docs/specs/comments.md; docs/requirements/comments.md; * docs/api/COMMENTS-PROPOSAL.md (accepted v1) * * @private implementation; public types exported via index. */ import { OpcPackage } from '../core/package/opc-package'; import { OpcRelationship } from '../core/package/relationships'; import { Length } from '../core/length'; import { FormControlsImpl } from './form-controls'; /** * Options when adding a classic cell note with {@link Comments.add} or {@link Cell.addComment}. * * Provide either {@link ref} (A1 address) or {@link row} and {@link column} (1-based). * On a cell helper, the target cell is already known so those fields are omitted. * * @private Not re-exported from the package root. Call sites use object literals; * structural typing covers the shape. */ export interface AddCommentOptions { /** Cell address in A1 form (for example `"B2"`). */ readonly ref?: string; /** 1-based row number of the anchor cell. */ readonly row?: number; /** 1-based column number of the anchor cell. */ readonly column?: number; /** Note body text. Default empty. */ readonly text?: string; /** Display name of the author. Default empty. */ readonly author?: string; /** Whether the note box is shown without hovering. Default follows Excel defaults. */ readonly isVisible?: boolean; /** Width of the note box (use length helpers such as `Pt` / `Px`). */ readonly width?: Length; /** Height of the note box (use length helpers such as `Pt` / `Px`). */ readonly height?: Length; } /** * One classic sticky note on a cell. * * Change text, author, visibility, or size; call {@link delete} to remove the note. */ export interface Comment { /** A1 address of the anchor cell. */ readonly address: string; /** 1-based row of the anchor cell. */ readonly row: number; /** 1-based column of the anchor cell. */ readonly column: number; /** Note body text. */ text: string; /** Author display name. */ author: string; /** Whether the note is shown without hovering. */ isVisible: boolean; /** Width of the note box. */ width: Length; /** Height of the note box. */ height: Length; /** * `true` when this entry is Excel's legacy placeholder for a threaded * comment, not a classic sticky note. * * Excel stores one comments-part comment per top-level thread with author * `tc={guid}` ([MS-XLSX] §2.3.7.3). Those rows appear in * {@link Worksheet.comments} beside real notes. The discussion itself is * {@link Worksheet.threadedComments}. */ readonly isThreadedComments: boolean; /** Remove this note from the worksheet. */ delete(): void; } /** * All classic cell notes on a worksheet ({@link Worksheet.comments}). */ export interface Comments { /** Number of notes on the sheet. */ readonly length: number; /** Iterate every note. */ [Symbol.iterator](): IterableIterator; /** Note at a zero-based index. */ item(index: number): Comment; /** Add a note; the target cell is required via `ref` or `row`/`column`. */ add(options: AddCommentOptions): Comment; /** Remove a note by handle, A1 address, or zero-based index. */ remove(target: Comment | string | number): void; /** Note at an A1 address, or `undefined` if none. */ get(ref: string): Comment | undefined; /** Note at a 1-based row and column, or `undefined` if none. */ get(row: number, column: number): Comment | undefined; /** Whether the cell at an A1 address has a note. */ has(ref: string): boolean; /** Whether the cell at a 1-based row and column has a note. */ has(row: number, column: number): boolean; } /** Internal entry for one note. @private */ export interface CommentEntry { /** 0-based row. */ row0: number; /** 0-based col. */ col0: number; text: string; author: string; isVisible: boolean; widthEmu: number; heightEmu: number; } /** Host notifications + package access for the comments model. @private */ export interface CommentsHost { markDirty(): void; readonly package: OpcPackage; readonly sheetPartName: string | undefined; } /** Comments materialize result for worksheet flush bookkeeping. @private */ export interface CommentsMaterializeResult { /** Relationships to pass on (comments rel re-added when present). */ readonly sheetRels: ReadonlyArray; } /** * Mutable classic-notes collection for one worksheet. * @private */ export declare class CommentsImpl implements Comments { private readonly entries; private readonly handles; /** Shared sheet-scoped author list (append-only). */ private authors; private host; private formControls; private commentsPartName; private commentsRelId; private loadedFromPackage; private overlayActive; /** @private */ bindHost(host: CommentsHost): void; /** Wire the shared VML host (single VML writer). @private */ bindFormControls(formControls: FormControlsImpl): void; readonly length: number; [Symbol.iterator](): IterableIterator; item(index: number): Comment; add(options: AddCommentOptions): Comment; remove(target: Comment | string | number): void; get(a: string | number, b?: number): Comment | undefined; has(a: string | number, b?: number): boolean; /** Cell-path add (cell receiver is the target). @private */ addForCell(row: number, col: number, options: AddCommentOptions): Comment; /** Cell-path handle (no copy semantics; live). @private */ getForCell(row: number, col: number): Comment | undefined; /** Cell-path remove. @private */ removeForCell(row: number, col: number): void; /** Replace contents from parse (does not mark dirty). @private */ replaceFromParse(model: { readonly entries: ReadonlyArray; readonly authors: ReadonlyArray; }): void; /** Serialize the comments part XML (root + authors + commentList). @private */ toCommentsXml(): string | undefined; /** * Load comments model from the package (sheet rels). Call during * `ensureSheetDataLoaded` **after** form controls have loaded their VML * part so note-chrome correlation can run. * @private */ loadFromPackage(pkg: OpcPackage, sheetPartName: string | undefined): void; /** Overlay note chrome from the loaded VML (isVisible / size). */ private correlateNoteChrome; /** * Materialize the comments part + relationship and inject the note overlay. * Call during worksheet flush **before** formControls.materializeOnFlush. * @private */ materializeOnFlush(existingSheetRels: ReadonlyArray, formControls: FormControlsImpl): CommentsMaterializeResult; /** Ensure the shared author list contains `author` (append-only). */ private ensureAuthor; private entryAt; private indexOfCell; private snapshotEntries; private handleFor; /** Raise dirty after entry mutation. */ private onChange; /** Remove a known entry (handle.delete path). */ private removeEntry; private createEntryFromOptions; } /** Parse authors + commentList from a comments part XML string. @private */ export declare function parseCommentsXml(xml: string): { readonly authors: string[]; readonly entries: CommentEntry[]; };