@silurus/ooxml 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -514,7 +514,20 @@ declare interface EquationRun {
514
514
  color?: string | null;
515
515
  }
516
516
 
517
- export declare type Fill = SolidFill | NoFill | GradientFill | PatternFill;
517
+ export declare type Fill = SolidFill | NoFill | GradientFill | PatternFill | ImageFill;
518
+
519
+ /**
520
+ * ECMA-376 §20.1.8.30 (CT_RelativeRect) — the destination rectangle a stretched
521
+ * blip is mapped into, as edge insets relative to the fill region. Values are
522
+ * fractions (ST_Percentage / 100000); **negative values let the image bleed
523
+ * past the box (overscan)**. Absent edges default to 0.
524
+ */
525
+ export declare interface FillRect {
526
+ l?: number;
527
+ t?: number;
528
+ r?: number;
529
+ b?: number;
530
+ }
518
531
 
519
532
  /** ECMA-376 §20.1.8.17 (CT_GlowEffect) — coloured halo with blur radius. */
520
533
  export declare interface Glow {
@@ -538,6 +551,30 @@ export declare interface GradientStop {
538
551
  color: string;
539
552
  }
540
553
 
554
+ /**
555
+ * Image fill — ECMA-376 §20.1.8.14 (CT_BlipFillProperties). The embedded blip
556
+ * is resolved to a base64 data URL at parse time. Both fill-modes are modelled
557
+ * and mutually exclusive: `stretch` (§20.1.8.56) carries {@link ImageFill.fillRect};
558
+ * `tile` (§20.1.8.58) carries {@link ImageFill.tile}.
559
+ */
560
+ export declare interface ImageFill {
561
+ fillType: 'image';
562
+ /** `data:<mime>;base64,…` of the embedded blip. */
563
+ dataUrl: string;
564
+ /**
565
+ * `<a:stretch><a:fillRect>` insets. Absent → fills the whole box (or the
566
+ * fill is tiled — see {@link ImageFill.tile}).
567
+ */
568
+ fillRect?: FillRect;
569
+ /**
570
+ * `<a:tile>` descriptor. Present only when the blipFill is tiled; mutually
571
+ * exclusive with {@link ImageFill.fillRect}.
572
+ */
573
+ tile?: TileInfo;
574
+ /** `a:blip > a:alphaModFix@amt` as a fraction (0.0–1.0). Absent = opaque. */
575
+ alpha?: number;
576
+ }
577
+
541
578
  declare interface LegendManualLayout {
542
579
  /** `"edge"` = `x`/`y` are fractions from top-left of chart space;
543
580
  * `"factor"` = fractions offset from the default position. */
@@ -551,8 +588,8 @@ declare interface LegendManualLayout {
551
588
  }
552
589
 
553
590
  /**
554
- * `<a:lightRig>` — ECMA-376 §20.1.5.9 (`CT_LightRig`). Parsed for Phase B
555
- * (lighting/bevel shading); the Phase A camera renderer ignores it.
591
+ * `<a:lightRig>` — ECMA-376 §20.1.5.9 (`CT_LightRig`). Drives the bevel-lip
592
+ * lighting (Phase B): `dir` selects the key-light octant.
556
593
  */
557
594
  export declare interface LightRig {
558
595
  /** Light-rig preset (`ST_LightRigType`), e.g. "threePt". */
@@ -914,6 +951,17 @@ export declare interface PictureElement {
914
951
  sp3d?: Sp3d;
915
952
  }
916
953
 
954
+ /** A single legacy slide comment (`<p:cm>` in `ppt/comments/commentN.xml`). */
955
+ export declare interface PptxComment {
956
+ /** Resolved author name from `ppt/commentAuthors.xml`. Absent when the
957
+ * authors file is missing or the `authorId` is out of range. */
958
+ author?: string;
959
+ /** `<p:cm @dt>` — ISO-8601 timestamp the comment was authored. */
960
+ date?: string;
961
+ /** Plain-text comment body (`<p:text>`). */
962
+ text: string;
963
+ }
964
+
917
965
  /**
918
966
  * Headless PPTX rendering engine.
919
967
  *
@@ -951,6 +999,26 @@ export declare class PptxPresentation {
951
999
  get slideWidth(): number;
952
1000
  /** Slide height in EMU. */
953
1001
  get slideHeight(): number;
1002
+ /**
1003
+ * Speaker-notes text for a slide (`ppt/notesSlides/notesSlideN.xml`,
1004
+ * ECMA-376 §13.3.5 — Notes Slide). Returns the notes-body text as a single
1005
+ * string (paragraphs joined with `\n`), or `null` when the slide has no
1006
+ * notes part. The notes are parsed at {@link load} time, so this is a
1007
+ * synchronous lookup.
1008
+ *
1009
+ * `slideIndex` is 0-based. Unlike navigation methods it is *not* clamped:
1010
+ * an out-of-range or non-integer index returns `null` rather than the notes
1011
+ * of the nearest slide (so a tool iterating by index gets an honest "no
1012
+ * notes" instead of a duplicated neighbour).
1013
+ *
1014
+ * @example
1015
+ * const pres = await PptxPresentation.load(buffer);
1016
+ * for (let i = 0; i < pres.slideCount; i++) {
1017
+ * const notes = pres.getNotes(i);
1018
+ * if (notes) console.log(`Slide ${i + 1} notes:`, notes);
1019
+ * }
1020
+ */
1021
+ getNotes(slideIndex: number): string | null;
954
1022
  /** Render a slide onto the given canvas. */
955
1023
  renderSlide(canvas: HTMLCanvasElement, slideIndex: number, opts?: RenderSlideOptions): Promise<void>;
956
1024
  /**
@@ -1035,6 +1103,13 @@ export declare class PptxViewer {
1035
1103
  prevSlide(): Promise<void>;
1036
1104
  get slideIndex(): number;
1037
1105
  get slideCount(): number;
1106
+ /**
1107
+ * Speaker-notes text for a slide (`ppt/notesSlides/notesSlideN.xml`,
1108
+ * ECMA-376 §13.3.5). Passthrough to {@link PptxPresentation.getNotes}:
1109
+ * 0-based index, returns `null` when the slide has no notes part, the index
1110
+ * is out of range, or nothing is loaded yet.
1111
+ */
1112
+ getNotes(slideIndex: number): string | null;
1038
1113
  /** The underlying <canvas> element. */
1039
1114
  get canvasElement(): HTMLCanvasElement;
1040
1115
  private renderCurrentSlide;
@@ -1255,6 +1330,20 @@ export declare interface Slide {
1255
1330
  slideNumber: number;
1256
1331
  background: Fill | null;
1257
1332
  elements: SlideElement[];
1333
+ /**
1334
+ * Speaker-notes pane text from `ppt/notesSlides/notesSlideN.xml`
1335
+ * (ECMA-376 §13.3.5 — Notes Slide). The full notes-body text as a single
1336
+ * string, paragraphs joined with `\n`. Absent (`undefined`) when the slide
1337
+ * has no notes part. The renderer ignores this — it is surfaced for tools;
1338
+ * read it via {@link PptxPresentation.getNotes}.
1339
+ */
1340
+ notes?: string;
1341
+ /**
1342
+ * Legacy slide comments (`ppt/comments/commentN.xml`, ECMA-376 §13.3.4).
1343
+ * Modern Office 365 threaded comments are not parsed. Omitted from the JSON
1344
+ * when the slide has no comments.
1345
+ */
1346
+ comments?: PptxComment[];
1258
1347
  }
1259
1348
 
1260
1349
  export declare type SlideElement = ShapeElement | PictureElement | TableElement | ChartElement | MediaElement;
@@ -1280,9 +1369,10 @@ export declare interface SolidFill {
1280
1369
  }
1281
1370
 
1282
1371
  /**
1283
- * `<a:sp3d>` — ECMA-376 §20.1.5.12 (`CT_Shape3D`). Parsed in full but **not
1284
- * rendered in Phase A** (camera-only). bevel/contour/extrusion are Phase B.
1285
- * Numeric fields are omitted from JSON when zero.
1372
+ * `<a:sp3d>` — ECMA-376 §20.1.5.12 (`CT_Shape3D`). Rendered in Phase B: bevelT/
1373
+ * bevelB are shaded as a lit lip (distance-field + lightRig), extrusionH as a
1374
+ * swept side wall, and contour as a flat outline approximation. Numeric fields
1375
+ * are omitted from JSON when zero.
1286
1376
  */
1287
1377
  export declare interface Sp3d {
1288
1378
  /** Z position of the front face in EMU (default 0). */
@@ -1528,4 +1618,27 @@ export declare interface TextRunData {
1528
1618
  outline?: TextOutline;
1529
1619
  }
1530
1620
 
1621
+ /**
1622
+ * ECMA-376 §20.1.8.58 (CT_TileInfoProperties) — tiled blip-fill placement.
1623
+ * The blip repeats at its native size (scaled by sx/sy) across the fill box.
1624
+ * Mutually exclusive with {@link ImageFill.fillRect} (the `stretch` mode).
1625
+ */
1626
+ export declare interface TileInfo {
1627
+ /** Horizontal offset of the first tile, in EMU (`tx`). Default 0. */
1628
+ tx: number;
1629
+ /** Vertical offset of the first tile, in EMU (`ty`). Default 0. */
1630
+ ty: number;
1631
+ /** Horizontal tile scale as a fraction (`sx` / 100000). Default 1.0. */
1632
+ sx: number;
1633
+ /** Vertical tile scale as a fraction (`sy` / 100000). Default 1.0. */
1634
+ sy: number;
1635
+ /** Mirror mode: `'none' | 'x' | 'y' | 'xy'` (`flip`). Default `'none'`. */
1636
+ flip: string;
1637
+ /**
1638
+ * Anchor corner the tile grid registers against:
1639
+ * `tl|t|tr|l|ctr|r|bl|b|br` (`algn`). Default `'tl'`.
1640
+ */
1641
+ algn: string;
1642
+ }
1643
+
1531
1644
  export { }
@@ -169,6 +169,8 @@ export declare type CfRule = {
169
169
  } | {
170
170
  type: 'aboveAverage';
171
171
  aboveAverage: boolean;
172
+ equalAverage?: boolean;
173
+ stdDev?: number;
172
174
  dxfId: number | null;
173
175
  priority: number;
174
176
  } | {
@@ -345,6 +347,28 @@ export declare interface DataPointOverride {
345
347
  markerLine?: string;
346
348
  }
347
349
 
350
+ /** One `<dataValidation>` rule (ECMA-376 §18.3.1.33). `type` is the constraint
351
+ * class (`list` | `whole` | `decimal` | `date` | `time` | `textLength` |
352
+ * `custom`); `operator` qualifies it (`between` | `notBetween` | `equal` | …).
353
+ * `formula1` / `formula2` are the operands (for `list`, `formula1` is the
354
+ * comma-separated literal list or a range/named reference). 1:1 with the Rust
355
+ * `DataValidation` (serde camelCase). */
356
+ export declare interface DataValidation {
357
+ /** Affected cell ranges, verbatim from `@sqref` (space-separated A1 refs). */
358
+ sqref: string;
359
+ /** Constraint class. Absent means the spec default (`none`, no constraint). */
360
+ validationType?: string;
361
+ operator?: string;
362
+ formula1?: string;
363
+ formula2?: string;
364
+ /** `@allowBlank` — empty input is permitted. */
365
+ allowBlank?: boolean;
366
+ promptTitle?: string;
367
+ prompt?: string;
368
+ errorTitle?: string;
369
+ errorMessage?: string;
370
+ }
371
+
348
372
  export declare interface DefinedName {
349
373
  name: string;
350
374
  formula: string;
@@ -710,6 +734,20 @@ export declare interface RenderViewportOptions {
710
734
  } | null;
711
735
  }
712
736
 
737
+ /**
738
+ * Resolved allowed-value set for a list validation. Either concrete display
739
+ * `values` (inline list or expanded range), or — when the operand is a defined
740
+ * name / complex formula we cannot expand — the raw `formula` text so the panel
741
+ * can disclose it instead of showing nothing.
742
+ */
743
+ export declare type ResolvedList = {
744
+ kind: 'values';
745
+ values: string[];
746
+ } | {
747
+ kind: 'formula';
748
+ formula: string;
749
+ };
750
+
713
751
  export declare interface Row {
714
752
  index: number;
715
753
  height: number | null;
@@ -1046,6 +1084,17 @@ export declare interface Worksheet {
1046
1084
  /** A1-style cell refs of commented cells (ECMA-376 §18.7.3). Rendered as a
1047
1085
  * small red triangle in each cell's top-right corner. */
1048
1086
  commentRefs?: string[];
1087
+ /** Full-fidelity comment bodies (cell ref + author + plain text) for every
1088
+ * `<comment>` in `xl/commentsN.xml` (ECMA-376 §18.7). Parallel to
1089
+ * {@link commentRefs} (one entry per ref). Consume this to read the note
1090
+ * text; the renderer uses {@link commentRefs} for the red indicator and the
1091
+ * viewer surfaces these bodies in an Excel-style hover popup. */
1092
+ comments?: XlsxComment[];
1093
+ /** Data-validation rules on this sheet (ECMA-376 §18.3.1.32–33). Exposed for
1094
+ * tooling. The viewer draws a list-dropdown arrow on the active cell when the
1095
+ * selection intersects a `list`-type rule's `sqref` (display only — opening
1096
+ * the list / picking a value is out of scope for a viewer). */
1097
+ dataValidations?: DataValidation[];
1049
1098
  /** Defined names in scope for this sheet (ECMA-376 §18.2.5). Used by
1050
1099
  * conditional-formatting `expression` rules that call named ranges
1051
1100
  * (e.g. `task_start`, `today`). */
@@ -1118,6 +1167,24 @@ export declare interface XlsxChartSeries {
1118
1167
  errBars?: ErrBars[];
1119
1168
  }
1120
1169
 
1170
+ /** One cell comment. Sourced from the classic notes file `xl/commentsN.xml`
1171
+ * (ECMA-376 §18.7) when present, otherwise from the Office-365 threaded
1172
+ * comments part `xl/threadedComments/` (MS-XLSX schema
1173
+ * `…/spreadsheetml/2018/threadedcomments`, `personId` resolved via
1174
+ * `xl/persons/`). `text` is the joined plain text — every `<r><t>` run for
1175
+ * classic notes, every reply in the thread (newline-joined) for threaded
1176
+ * comments; rich-text formatting is dropped. 1:1 with the Rust `XlsxComment`
1177
+ * (serde camelCase). */
1178
+ export declare interface XlsxComment {
1179
+ /** A1-style cell reference (`@ref` on the comment element). */
1180
+ cellRef: string;
1181
+ /** Resolved author name — the `<authors>` entry (classic) or the `<person>`
1182
+ * `displayName` (threaded). Absent when unresolved. */
1183
+ author?: string;
1184
+ /** Concatenated plain text of every run / threaded reply. */
1185
+ text: string;
1186
+ }
1187
+
1121
1188
  /** Emitted once per cell that has text, with the cell's canvas-pixel bounds. */
1122
1189
  export declare interface XlsxTextRunInfo {
1123
1190
  text: string;
@@ -1171,6 +1238,32 @@ export declare class XlsxViewer {
1171
1238
  private selectionOverlay;
1172
1239
  private keydownHandler;
1173
1240
  private pendingTap;
1241
+ /** DOM overlay element that shows the hovered cell's comment. Lives in
1242
+ * canvasArea above the scrollHost; `pointer-events:none` so it never blocks
1243
+ * cell interaction. */
1244
+ private commentPopup;
1245
+ /** `"row:col"` → comment for the current sheet, rebuilt on every showSheet. */
1246
+ private commentMap;
1247
+ /** `"row:col"` of the cell whose popup is currently shown (or pending), so a
1248
+ * pointermove within the same cell doesn't restart the show timer. */
1249
+ private commentPopupKey;
1250
+ /** Pending show timer (see {@link COMMENT_POPUP_DELAY_MS}). */
1251
+ private commentPopupTimer;
1252
+ /** DOM overlay listing a list-validated cell's allowed values. Lives in
1253
+ * canvasArea above the scrollHost; unlike the comment popup this is a click
1254
+ * target (`pointer-events:auto`). Read-only: hovering an item highlights it
1255
+ * but selecting does NOT change the cell. */
1256
+ private validationPanel;
1257
+ /** `"row:col"` of the cell whose panel is currently open, or null. Lets a
1258
+ * re-click on the same arrow toggle the panel closed. */
1259
+ private validationPanelKey;
1260
+ /** Screen rect (canvasArea CSS px) of the dropdown arrow button last drawn by
1261
+ * {@link maybeDrawValidationDropdown}, so pointerdown can hit-test it. Null
1262
+ * when no arrow is currently visible. */
1263
+ private validationArrowRect;
1264
+ /** Document-level pointerdown listener that closes the panel on an outside
1265
+ * click; installed only while the panel is open. */
1266
+ private validationOutsideHandler;
1174
1267
  constructor(container: HTMLElement, opts?: XlsxViewerOptions);
1175
1268
  /**
1176
1269
  * Load an XLSX from URL or ArrayBuffer and render the first sheet.
@@ -1245,6 +1338,14 @@ export declare class XlsxViewer {
1245
1338
  private getCellRect;
1246
1339
  /** Returns the current selection, including mode. */
1247
1340
  get selection(): CellRange | null;
1341
+ /**
1342
+ * Programmatically select a single cell by A1 reference (e.g. `"B2"`), as if
1343
+ * the user had clicked it: updates the active/anchor cell, redraws the
1344
+ * selection overlay (including any list-validation dropdown arrow), and fires
1345
+ * `onSelectionChange`. A no-op for malformed refs. Closes any open validation
1346
+ * panel, matching the click path.
1347
+ */
1348
+ select(ref: string): void;
1248
1349
  /**
1249
1350
  * Returns what the header area contains at the given client coordinates.
1250
1351
  * Returns null when the point is in the cell grid (not a header).
@@ -1253,6 +1354,49 @@ export declare class XlsxViewer {
1253
1354
  /** Copy the selected cell range as tab-separated text to the clipboard. */
1254
1355
  private copySelection;
1255
1356
  private updateSelectionOverlay;
1357
+ /** Draw the Excel list-validation dropdown button just outside the
1358
+ * bottom-right corner of the *active* cell when that cell is covered by a
1359
+ * `list` data-validation rule. Anchored to the single active cell (not the
1360
+ * whole range) to mirror Excel, which attaches the button to the active
1361
+ * cell of the selection. */
1362
+ private maybeDrawValidationDropdown;
1363
+ /** Toggle the dropdown panel for the active cell's list validation. Called
1364
+ * from pointerdown when the arrow rect is hit. Re-clicking the same arrow
1365
+ * closes it. */
1366
+ private toggleValidationPanel;
1367
+ /** Resolve the allowed values for `formula1` (relative to the current sheet)
1368
+ * and render them in the panel anchored below the active cell. Async because
1369
+ * cross-sheet range references may need a lazily-parsed worksheet. */
1370
+ private openValidationPanel;
1371
+ /** Build the panel's children. Uses textContent throughout (no HTML injection
1372
+ * from cell values). Items highlight on hover but are NOT selectable —
1373
+ * this is a read-only viewer, so clicking a value must not change the cell. */
1374
+ private renderValidationPanel;
1375
+ /** Position the (already-populated, visible-or-becoming-visible) panel below
1376
+ * the dropdown arrow / active cell using the pure geometry calculator. */
1377
+ private positionValidationPanel;
1378
+ /** Install a document-level pointerdown listener that closes the panel on a
1379
+ * click outside it (and outside the arrow, which toggles via its own path).
1380
+ * Removed by {@link hideValidationPanel}. */
1381
+ private installValidationOutsideHandler;
1382
+ /** Hide the panel and detach its outside-click listener. Called on re-click,
1383
+ * outside click, Esc, scroll, selection change, sheet switch and destroy. */
1384
+ private hideValidationPanel;
1385
+ /** Build the `"row:col"` → comment index for the given sheet. Parses each
1386
+ * `XlsxComment.cellRef` with the shared {@link parseA1}; later refs win on a
1387
+ * collision (Excel allows at most one note per cell, so this is moot in
1388
+ * practice). */
1389
+ private buildCommentMap;
1390
+ /** Show the popup for the comment on `cell` after the hover dwell, anchored to
1391
+ * the cell's current on-screen rect. No-op when the cell carries no comment.
1392
+ * Re-hovering the same cell does not restart the timer. */
1393
+ private scheduleCommentPopup;
1394
+ /** Immediately render the popup for `comment` anchored to `cell` (used by the
1395
+ * hover-dwell timer and by touch selection, which has no hover). */
1396
+ private renderCommentPopup;
1397
+ /** Hide the popup and cancel any pending show. Called on cell-out, scroll,
1398
+ * sheet switch and destroy. */
1399
+ private hideCommentPopup;
1256
1400
  private applyPointerSelection;
1257
1401
  private setupSelectionEvents;
1258
1402
  private buildTabs;
@@ -1354,6 +1498,22 @@ export declare class XlsxWorkbook {
1354
1498
  * `null` for sheets that declare no tab color. */
1355
1499
  get tabColors(): (string | null)[];
1356
1500
  getWorksheet(sheetIndex: number): Promise<Worksheet>;
1501
+ /**
1502
+ * Resolve a `list`-type data-validation `formula1` (ECMA-376 §18.3.1.32) into
1503
+ * the set of allowed values to display, evaluated relative to `sheetIndex`
1504
+ * (the sheet that owns the validation, used to resolve unqualified ranges):
1505
+ *
1506
+ * - Inline quoted list `"A,B,C"` → the literal values.
1507
+ * - Range ref `$B$2:$B$5` → each non-empty cell's *display
1508
+ * string* (the same formatted text the grid shows, via {@link formatCellValue}),
1509
+ * walked row-major. `Sheet2!$A$1:$A$9` resolves against the named sheet
1510
+ * (lazily parsed via {@link getWorksheet}, hence async).
1511
+ * - Named range / complex formula → `{ kind: 'formula' }` carrying the
1512
+ * raw text so the caller can disclose it rather than blanking it.
1513
+ *
1514
+ * Read-only: this only reads cell values for display; it never writes.
1515
+ */
1516
+ resolveValidationList(sheetIndex: number, formula1: string | undefined): Promise<ResolvedList>;
1357
1517
  renderViewport(target: HTMLCanvasElement | OffscreenCanvas, sheetIndex: number, viewport: ViewportRange, opts?: RenderViewportOptions): Promise<void>;
1358
1518
  destroy(): void;
1359
1519
  }