/** * xlsx STYLING — effective cell styles, ergonomic style writes, column * widths and row heights. * * OWNERSHIP (DESIGN-P3.md): this file belongs to the STYLING agent. It * imports only from `./internal.js`, `../xml/index.js` and * `../schema/index.js` — never from `./index.js`, `./structure.js`, * `./formula/` or `./streaming.js`. The Integrate agent later wires these * functions as `Worksheet` methods: * * ```ts * const style = sheet.getCellStyle('B2'); // → getCellStyle(sheet._internal(), 'B2') * sheet.setCellStyle('B2', { bold: true }); // → setCellStyle(...) * sheet.setColumnWidth('B', 14.5); // → setColumnWidth(...) * sheet.setRowHeight(3, 24); // → setRowHeight(...) * ``` * * Design rules (normative — CONTRACTS.md §8.10–§8.13): * - READ resolves the xf indirection completely: c/@s → cellXfs/xf → * fonts/fills/borders/numFmts (+ built-in numFmt codes), honoring the * apply* flags the way Excel does (attribute present on the cell xf * wins; xfId inheritance is NOT chased this phase — Excel writes fully * materialized cell xfs). * - WRITE merges the update into the cell's current EFFECTIVE style, * builds font/fill/border/numFmt elements, and find-or-appends each * into its collection using `styleElementEquals` — repeated styling * never bloats styles.xml. The count attributes are kept in sync. * - Every touched part is marked dirty; untouched parts stay L3. * * Implementation strategy: writes CLONE the cell's current xf (and the * font/fill/border elements it references) and patch only the properties * the update names. Unmodeled attributes and children (theme colors, font * family/scheme, protection, …) therefore ride along unchanged, and an * update that changes nothing dedups back to the cell's original xf — * leaving both the worksheet and styles.xml untouched (L3). */ import { XmlElement } from '../xml/index.js'; import { type CellAddress, type SheetInternal } from './internal.js'; /** Border line styles (ECMA-376 ST_BorderStyle, minus 'none'). */ export type BorderLineStyle = 'thin' | 'medium' | 'thick' | 'dashed' | 'dotted' | 'double' | 'hair' | 'mediumDashed' | 'dashDot' | 'mediumDashDot' | 'dashDotDot' | 'mediumDashDotDot' | 'slantDashDot'; /** One resolved border edge. */ export interface BorderEdge { readonly style: BorderLineStyle; /** 'RRGGBB' when the edge has an explicit rgb color; undefined for * automatic/theme/indexed colors (preserved in the DOM, not modeled). */ readonly color?: string; } /** Resolved borders of a cell; null = no line on that edge. */ export interface CellBorders { readonly top: BorderEdge | null; readonly bottom: BorderEdge | null; readonly left: BorderEdge | null; readonly right: BorderEdge | null; readonly diagonal: BorderEdge | null; } /** Resolved font of a cell. */ export interface CellFont { readonly name: string; /** Point size. */ readonly size: number; readonly bold: boolean; readonly italic: boolean; readonly underline: 'none' | 'single' | 'double'; readonly strike: boolean; /** 'RRGGBB' when the font has an explicit rgb color. */ readonly color?: string; } /** * Resolved fill. Only pattern fills are modeled; a solid fill reads as * pattern 'solid' with `color` = the fg rgb. Gradient and theme/indexed * colors are preserved in the DOM but read with `color` undefined. */ export interface CellFill { readonly pattern: string; /** Foreground 'RRGGBB' (the visible color of a solid fill). */ readonly color?: string; /** Background 'RRGGBB' of two-color patterns. */ readonly backgroundColor?: string; } /** Resolved alignment of a cell. */ export interface CellAlignmentInfo { readonly horizontal: 'general' | 'left' | 'center' | 'right' | 'fill' | 'justify' | 'centerContinuous' | 'distributed'; readonly vertical: 'top' | 'center' | 'bottom' | 'justify' | 'distributed'; readonly wrapText: boolean; readonly shrinkToFit: boolean; readonly indent: number; /** Degrees 0–180, or 255 for vertical text. */ readonly textRotation: number; } /** Resolved number format of a cell. */ export interface CellNumberFormat { readonly id: number; /** The format code ('General', '#,##0.00', …). For locale-implied * built-in ids without a defined code (5–8, 23–36, 41–44) this is * undefined. */ readonly code?: string; } /** * The EFFECTIVE style of a cell — every layer of the xf indirection * resolved to plain values. What you would see in Excel's Format Cells * dialog (for the modeled subset). */ export interface CellStyle { readonly font: CellFont; /** null = no fill (patternType 'none' or absent). */ readonly fill: CellFill | null; readonly border: CellBorders; readonly alignment: CellAlignmentInfo; readonly numberFormat: CellNumberFormat; } /** * A hex color: '#FFE699', 'FFE699', or 8-digit ARGB 'FFFFE699' — * normalized to ARGB internally. Invalid strings throw with the accepted * shapes named in the message. */ export type ColorInput = string; /** Per-edge border update; a bare style string means "that style, black". */ export interface BorderEdgeUpdate { readonly style: BorderLineStyle; readonly color?: ColorInput; } /** * Border update: set an edge to a style (or `{style, color}`), clear it * with null, or leave it alone by omitting it. `all` applies to * top/bottom/left/right before the specific edges are applied on top. */ export interface BordersUpdate { readonly all?: BorderLineStyle | BorderEdgeUpdate | null; readonly top?: BorderLineStyle | BorderEdgeUpdate | null; readonly bottom?: BorderLineStyle | BorderEdgeUpdate | null; readonly left?: BorderLineStyle | BorderEdgeUpdate | null; readonly right?: BorderLineStyle | BorderEdgeUpdate | null; } /** * A partial, ergonomic style write. Only the properties given change; the * rest of the cell's effective style survives. Explicit `null` clears a * property back to its default. * * ```ts * sheet.setCellStyle('B2', { * bold: true, * fill: '#FFE699', * numberFormat: '#,##0.00', * border: { bottom: 'thin' }, * }); * ``` */ export interface CellStyleUpdate { readonly bold?: boolean; readonly italic?: boolean; /** true = 'single'. */ readonly underline?: boolean | 'single' | 'double' | 'none'; readonly strike?: boolean; readonly fontName?: string; /** Point size. */ readonly fontSize?: number; /** Font color; null = automatic. */ readonly color?: ColorInput | null; /** A color = solid fill of that color; null = remove the fill. */ readonly fill?: ColorInput | null; /** * A format code ('#,##0.00', 'yyyy-mm-dd', …). Built-in codes map to * their built-in id; anything else allocates/reuses a custom numFmt * (ids from 164). null = back to General. */ readonly numberFormat?: string | null; /** * A bare style ('thin') = that style on all four outer edges; an object * for per-edge control; null = remove all borders. */ readonly border?: BorderLineStyle | BordersUpdate | null; readonly align?: 'left' | 'center' | 'right' | 'justify' | 'fill' | 'general'; readonly valign?: 'top' | 'center' | 'bottom' | 'justify'; readonly wrapText?: boolean; readonly indent?: number; /** Degrees 0–180, or 255 for vertical text. */ readonly textRotation?: number; } /** * @internal Resolve a cell's xf element (cellXfs child at index c/@s, or * index 0). Returns undefined when the workbook has no styles.xml or the * index is out of range. Exposed for the implementation's tests. */ export declare function resolveCellXf(sheet: SheetInternal, cell: XmlElement | undefined): XmlElement | undefined; /** * The effective style of the cell at `ref` ('B2' or {row, col}), fully * resolved through c/@s → cellXfs → fonts/fills/borders/numFmts. A cell * with no style attribute (or a missing cell) resolves through cellXf 0; * a workbook with no styles.xml yields the documented defaults (Calibri * 11, no fill, no borders, General). * * ```ts * const s = sheet.getCellStyle('B2'); * s.font.bold // → true * s.numberFormat.code // → '#,##0.00' * ``` */ export declare function getCellStyle(sheet: SheetInternal, ref: string | CellAddress): CellStyle; /** * @internal Normalize a {@link ColorInput} to 8-digit ARGB ('FFFFE699'). * Exposed for the implementation's tests; not public API. */ export declare function normalizeColor(input: ColorInput): string; /** * Merge `update` into the effective style of every cell in `ref` (a * single cell 'B2', a range 'A1:C3', or {row, col}). Creates cell * elements (carrying only r + s) for empty cells in the range so the * styling is visible in Excel. Fonts, fills, borders, numFmts and xfs are * deduplicated by structural equality — styling 10 000 cells the same way * adds at most one element to each styles.xml collection. Marks the * worksheet and styles parts dirty. * * ```ts * sheet.setCellStyle('A1:D1', { bold: true, fill: '#FFE699' }); * ``` */ export declare function setCellStyle(sheet: SheetInternal, ref: string | CellAddress, update: CellStyleUpdate): void; /** * The explicit width of a column ('B' or 1-based number), in Excel width * units (characters of the default font, the number the Excel UI shows). * null when the column has no explicit width (sheet default applies). */ export declare function getColumnWidth(sheet: SheetInternal, col: string | number): number | null; /** * Set a column's width in Excel width units ('B' or 1-based number); * null removes the explicit width (back to the sheet default). Maintains * the `cols/col` min/max run-length encoding: setting one column inside * an existing multi-column run splits the run, and never disturbs other * col properties (hidden, style, …) on the split remainder. The `cols` * element is created in schema order when missing and removed when it * becomes empty. Marks the worksheet dirty. * * ```ts * sheet.setColumnWidth('B', 14.5); * ``` */ export declare function setColumnWidth(sheet: SheetInternal, col: string | number, width: number | null): void; /** * The explicit height of a 1-based row, in points. null when the row has * no explicit height (sheet default applies). */ export declare function getRowHeight(sheet: SheetInternal, row: number): number | null; /** * Set a row's height in points; null removes the explicit height. Writes * row/@ht + @customHeight="1" (removes both on null), creating the row * element if needed and leaving all its other attributes and cells * untouched. Marks the worksheet dirty. * * ```ts * sheet.setRowHeight(3, 24); * ``` */ export declare function setRowHeight(sheet: SheetInternal, row: number, height: number | null): void; //# sourceMappingURL=styles.d.ts.map