pptx-svelte-viewer 2.17.8 → 2.18.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/{AiChatPanel-CqrEXLmH.js → AiChatPanel-D6dfMwnT.js} +1 -1
  3. package/dist/{export-DxMXX_It.js → export-DbSAFc8m.js} +63641 -58874
  4. package/dist/i18n.js +1 -1
  5. package/dist/index.d.ts +166 -17
  6. package/dist/index.js +2 -2
  7. package/dist/pptx-svelte-viewer.css +1 -1
  8. package/dist/{translator-CZy5sxU0.js → translator-CZ12ZvlE.js} +20 -0
  9. package/dist/viewer/components/props-editing.d.ts +14 -0
  10. package/dist/viewer/components/props-editing.d.ts.map +1 -1
  11. package/dist/viewer/components/ribbon/transitions/transition-presets.d.ts +13 -6
  12. package/dist/viewer/components/ribbon/transitions/transition-presets.d.ts.map +1 -1
  13. package/dist/viewer/components/viewer-body-commits.d.ts +6 -0
  14. package/dist/viewer/components/viewer-body-commits.d.ts.map +1 -1
  15. package/dist/viewer/editor/context-menu-dispatch.d.ts.map +1 -1
  16. package/dist/viewer/editor/editor-adjust-gesture.d.ts +21 -0
  17. package/dist/viewer/editor/editor-adjust-gesture.d.ts.map +1 -0
  18. package/dist/viewer/editor/editor-arrange-ops.d.ts.map +1 -1
  19. package/dist/viewer/editor/editor-controller-wiring.d.ts +21 -0
  20. package/dist/viewer/editor/editor-controller-wiring.d.ts.map +1 -1
  21. package/dist/viewer/editor/editor-controller.svelte.d.ts +8 -0
  22. package/dist/viewer/editor/editor-controller.svelte.d.ts.map +1 -1
  23. package/dist/viewer/editor/editor-document-lifecycle.d.ts.map +1 -1
  24. package/dist/viewer/editor/editor-document-state.d.ts +16 -2
  25. package/dist/viewer/editor/editor-document-state.d.ts.map +1 -1
  26. package/dist/viewer/editor/editor-handle-handlers.d.ts +42 -0
  27. package/dist/viewer/editor/editor-handle-handlers.d.ts.map +1 -0
  28. package/dist/viewer/editor/editor-master-controller.d.ts +2 -0
  29. package/dist/viewer/editor/editor-master-controller.d.ts.map +1 -1
  30. package/dist/viewer/editor/editor-selection-gestures.d.ts +8 -1
  31. package/dist/viewer/editor/editor-selection-gestures.d.ts.map +1 -1
  32. package/dist/viewer/editor/editor-selection-interactivity.d.ts +43 -0
  33. package/dist/viewer/editor/editor-selection-interactivity.d.ts.map +1 -0
  34. package/dist/viewer/editor/editor-slides-controller.d.ts +8 -1
  35. package/dist/viewer/editor/editor-slides-controller.d.ts.map +1 -1
  36. package/dist/viewer/editor/editor-state.svelte.d.ts +66 -2
  37. package/dist/viewer/editor/editor-state.svelte.d.ts.map +1 -1
  38. package/dist/viewer/editor/editor-transition-controller.d.ts +12 -0
  39. package/dist/viewer/editor/editor-transition-controller.d.ts.map +1 -1
  40. package/dist/viewer/editor/index.d.ts +9 -0
  41. package/dist/viewer/editor/index.d.ts.map +1 -1
  42. package/dist/viewer/editor/inline-text.d.ts.map +1 -1
  43. package/dist/viewer/editor/table-cell-pointer.d.ts +24 -0
  44. package/dist/viewer/editor/table-cell-pointer.d.ts.map +1 -0
  45. package/dist/viewer/editor/table-cell-selection.svelte.d.ts +51 -0
  46. package/dist/viewer/editor/table-cell-selection.svelte.d.ts.map +1 -0
  47. package/dist/viewer/index.d.ts +463 -17
  48. package/dist/viewer/index.js +1 -1
  49. package/dist/viewer/master/master-view.d.ts +8 -1
  50. package/dist/viewer/master/master-view.d.ts.map +1 -1
  51. package/dist/viewer/render/index.d.ts +2 -2
  52. package/dist/viewer/render/index.d.ts.map +1 -1
  53. package/dist/viewer/render/smartart-view.d.ts +6 -5
  54. package/dist/viewer/render/smartart-view.d.ts.map +1 -1
  55. package/dist/viewer/render/table-view.d.ts +6 -0
  56. package/dist/viewer/render/table-view.d.ts.map +1 -1
  57. package/dist/viewer/state/autosave.svelte.d.ts +9 -0
  58. package/dist/viewer/state/autosave.svelte.d.ts.map +1 -1
  59. package/dist/viewer/state/create-viewer-state-collab.svelte.d.ts.map +1 -1
  60. package/dist/viewer/state/create-viewer-state-presentation.svelte.d.ts.map +1 -1
  61. package/dist/viewer/state/create-viewer-state.svelte.d.ts.map +1 -1
  62. package/dist/viewer/state/index.d.ts +2 -0
  63. package/dist/viewer/state/index.d.ts.map +1 -1
  64. package/dist/viewer/state/table-cell-selection-context.d.ts +20 -0
  65. package/dist/viewer/state/table-cell-selection-context.d.ts.map +1 -0
  66. package/dist/viewer/state/viewer-effects.svelte.d.ts.map +1 -1
  67. package/dist/viewer/style/element-style.d.ts.map +1 -1
  68. package/package.json +1 -1
@@ -1640,7 +1640,28 @@ interface BulletInfo {
1640
1640
  autoNumType?: string;
1641
1641
  /** Auto-numbering start value. */
1642
1642
  autoNumStartAt?: number;
1643
- /** Zero-based paragraph index within the text body (for auto-numbering). */
1643
+ /**
1644
+ * Auto-numbering ORDINAL OFFSET: the zero-based distance of this paragraph
1645
+ * within its own numbered list, such that
1646
+ * `autoNumStartAt + paragraphIndex` is the ordinal to render. Despite the
1647
+ * name it is NOT the paragraph's position in the text body; the two agree
1648
+ * only for a list that starts at the first paragraph and is never
1649
+ * interrupted.
1650
+ *
1651
+ * It has to be the offset rather than the raw position because every
1652
+ * consumer that re-derives a marker from `BulletInfo` alone (the renderer's
1653
+ * `resolveParagraphBullet`, the Markdown converter's `resolveListMarker`)
1654
+ * computes `autoNumStartAt + paragraphIndex`. The load path resolves the
1655
+ * real sequence itself, restarting the count after any paragraph that
1656
+ * interrupts the list, and publishes the offset here so those consumers
1657
+ * land on the same number. With the raw position they did not, and BOTH
1658
+ * markers were painted ("3.1. Item"), because the paragraph builder drops
1659
+ * the parsed marker segment only when the two strings agree.
1660
+ *
1661
+ * Runtime-only: derived at parse time and never serialized. OOXML has no
1662
+ * counterpart (`a:buAutoNum` carries only `@type` and `@startAt`), so the
1663
+ * writer neither reads nor emits it.
1664
+ */
1644
1665
  paragraphIndex?: number;
1645
1666
  /** Bullet font family from `a:buFont`. */
1646
1667
  fontFamily?: string;
@@ -3935,6 +3956,11 @@ interface PptxTableCellStyle {
3935
3956
  italic?: boolean;
3936
3957
  underline?: boolean;
3937
3958
  color?: string;
3959
+ /**
3960
+ * Font family from the first run's `a:rPr/a:latin@typeface` (falling back to
3961
+ * `a:ea` / `a:cs`). Per-run families live on {@link PptxTableCellTextRun}.
3962
+ */
3963
+ fontFamily?: string;
3938
3964
  /**
3939
3965
  * Raw XML colour-choice node preserved from `a:tc/a:txBody/.../a:rPr/a:solidFill`
3940
3966
  * for round-trip serialisation. Currently unused by the cell-level writer
@@ -4090,6 +4116,45 @@ interface PptxTableCell3D {
4090
4116
  /** Light rig direction (`a:lightRig@dir`, e.g. `tl`, `t`, `tr`). */
4091
4117
  lightRigDirection?: string;
4092
4118
  }
4119
+ /**
4120
+ * One styled text run inside a table cell's `a:txBody`.
4121
+ *
4122
+ * `PptxTableCell.text` is a flat string and `PptxTableCell.style` describes
4123
+ * only the FIRST run, so a cell mixing formats ("Revenue **grew 42%** last
4124
+ * year") cannot be represented by those two alone. {@link PptxTableCell.runs}
4125
+ * carries the full sequence, with paragraph and line breaks as marker entries
4126
+ * so a renderer can walk it linearly.
4127
+ *
4128
+ * Structurally identical to `pptx-viewer-shared`'s `CellTextRun`, which every
4129
+ * binding's table renderer already consumes.
4130
+ *
4131
+ * @example
4132
+ * ```ts
4133
+ * const runs: PptxTableCellTextRun[] = [
4134
+ * { text: "Revenue " },
4135
+ * { text: "grew 42%", bold: true, color: "#C00000" },
4136
+ * ];
4137
+ * // => satisfies PptxTableCellTextRun[]
4138
+ * ```
4139
+ */
4140
+ interface PptxTableCellTextRun {
4141
+ /** Run text. Empty for the break markers below. */
4142
+ text: string;
4143
+ /** This entry starts a new paragraph (`a:p` boundary) rather than carrying text. */
4144
+ isParagraphBreak?: boolean;
4145
+ /** This entry is a soft line break (`a:br`) rather than carrying text. */
4146
+ isLineBreak?: boolean;
4147
+ bold?: boolean;
4148
+ italic?: boolean;
4149
+ underline?: boolean;
4150
+ strikethrough?: boolean;
4151
+ /** Resolved run colour as a CSS colour string. */
4152
+ color?: string;
4153
+ /** Run font size in points (`a:rPr@sz` / 100). */
4154
+ fontSize?: number;
4155
+ /** Run font family from `a:rPr/a:latin@typeface` (or `a:ea` / `a:cs`). */
4156
+ fontFamily?: string;
4157
+ }
4093
4158
  /**
4094
4159
  * A single table cell with text content, optional style, and merge info.
4095
4160
  *
@@ -4106,6 +4171,15 @@ interface PptxTableCell3D {
4106
4171
  interface PptxTableCell {
4107
4172
  text: string;
4108
4173
  style?: PptxTableCellStyle;
4174
+ /**
4175
+ * Per-run formatting for the cell's text, when it has any beyond what
4176
+ * {@link style} can express. Present only for cells whose `a:txBody`
4177
+ * actually carries runs; renderers fall back to {@link text} when absent.
4178
+ *
4179
+ * Editing a cell's text invalidates these (the editor produces a plain
4180
+ * string), so an edit path must clear them alongside setting `text`.
4181
+ */
4182
+ textRuns?: PptxTableCellTextRun[];
4109
4183
  /** Column span (defaults to 1). */
4110
4184
  gridSpan?: number;
4111
4185
  /** Row span (defaults to 1). */
@@ -4885,6 +4959,35 @@ interface UnknownPptxElement extends PptxElementBase {
4885
4959
  type PptxElement = TextPptxElement | ShapePptxElement | ConnectorPptxElement | ImagePptxElement | PicturePptxElement | TablePptxElement | ChartPptxElement | SmartArtPptxElement | OlePptxElement | MediaPptxElement | GroupPptxElement | InkPptxElement | ContentPartPptxElement | ZoomPptxElement | Model3DPptxElement | UnknownPptxElement;
4886
4960
  //#endregion
4887
4961
  //#region src/core/types/masters.d.ts
4962
+ /**
4963
+ * A placeholder slot declared on a master or layout.
4964
+ *
4965
+ * The geometry fields are in CSS pixels (EMU / {@link EMU_PER_PX}) and are only
4966
+ * present when the shape carried an explicit `a:xfrm`. Placeholders that
4967
+ * inherit their frame from the master leave them undefined, so consumers that
4968
+ * draw placeholder outlines (the layout gallery) must skip those entries
4969
+ * rather than assume a zero-sized box at the origin.
4970
+ *
4971
+ * @example
4972
+ * ```ts
4973
+ * const frame: PptxPlaceholderFrame = { type: "body", idx: "1", x: 63, y: 130 };
4974
+ * // => satisfies PptxPlaceholderFrame
4975
+ * ```
4976
+ */
4977
+ interface PptxPlaceholderFrame {
4978
+ /** `p:ph/@type`, lower-cased by the parser; defaults to `body` when omitted. */
4979
+ type: string;
4980
+ /** `p:ph/@idx`, when present. */
4981
+ idx?: string;
4982
+ /** Left offset in CSS pixels, when the shape declares `a:off`. */
4983
+ x?: number;
4984
+ /** Top offset in CSS pixels, when the shape declares `a:off`. */
4985
+ y?: number;
4986
+ /** Width in CSS pixels, when the shape declares `a:ext`. */
4987
+ width?: number;
4988
+ /** Height in CSS pixels, when the shape declares `a:ext`. */
4989
+ height?: number;
4990
+ }
4888
4991
  /**
4889
4992
  * Parsed notes master from `ppt/notesMasters/notesMaster1.xml`.
4890
4993
  *
@@ -4906,10 +5009,7 @@ interface PptxNotesMaster {
4906
5009
  /** Background image data URL. */
4907
5010
  backgroundImage?: string;
4908
5011
  /** Placeholder shapes found on the notes master. */
4909
- placeholders?: Array<{
4910
- type: string;
4911
- idx?: string;
4912
- }>;
5012
+ placeholders?: PptxPlaceholderFrame[];
4913
5013
  /** Editable elements on the notes master (header, footer, date, page number, slide image, notes body). */
4914
5014
  elements?: PptxElement[];
4915
5015
  /** Header/footer flags from `<p:hf>` on the notes master (P-H3). */
@@ -4937,10 +5037,7 @@ interface PptxHandoutMaster {
4937
5037
  /** Background image data URL. */
4938
5038
  backgroundImage?: string;
4939
5039
  /** Placeholder shapes found on the handout master. */
4940
- placeholders?: Array<{
4941
- type: string;
4942
- idx?: string;
4943
- }>;
5040
+ placeholders?: PptxPlaceholderFrame[];
4944
5041
  /** Editable elements on the handout master (header, footer, date, page number, slide placeholders). */
4945
5042
  elements?: PptxElement[];
4946
5043
  /** Number of slides per page for handout print layout (1, 2, 3, 4, 6, or 9). */
@@ -4988,10 +5085,7 @@ interface PptxSlideMaster {
4988
5085
  /** Layout paths associated with this master. */
4989
5086
  layoutPaths?: string[];
4990
5087
  /** Placeholder shapes on the master. */
4991
- placeholders?: Array<{
4992
- type: string;
4993
- idx?: string;
4994
- }>;
5088
+ placeholders?: PptxPlaceholderFrame[];
4995
5089
  /** Parsed element shapes on the master slide (for master view rendering). */
4996
5090
  elements?: PptxElement[];
4997
5091
  /** Parsed slide layout objects associated with this master. */
@@ -5063,10 +5157,7 @@ interface PptxSlideLayout {
5063
5157
  /** Parsed element shapes on the layout. */
5064
5158
  elements?: PptxElement[];
5065
5159
  /** Placeholder shapes on the layout. */
5066
- placeholders?: Array<{
5067
- type: string;
5068
- idx?: string;
5069
- }>;
5160
+ placeholders?: PptxPlaceholderFrame[];
5070
5161
  /** Matching name attribute for layout identification (`@matchingName`). */
5071
5162
  matchingName?: string;
5072
5163
  /** Whether the layout is marked as preserved (prevent deletion, `@preserve`). */
@@ -5080,6 +5171,42 @@ interface PptxSlideLayout {
5080
5171
  /** Header/footer flags from `<p:hf>` on this layout (P-H3). */
5081
5172
  headerFooter?: PptxHeaderFooterFlags;
5082
5173
  }
5174
+ /**
5175
+ * Rendered content of a single layout, used to draw gallery thumbnails.
5176
+ *
5177
+ * Produced on demand rather than during load: materialising every layout's
5178
+ * artwork (and decoding its images) up front costs a noticeable amount of time
5179
+ * on decks with many masters, and most sessions never open the layout gallery
5180
+ * at all.
5181
+ *
5182
+ * @example
5183
+ * ```ts
5184
+ * const preview: PptxLayoutPreview = {
5185
+ * path: "ppt/slideLayouts/slideLayout2.xml",
5186
+ * width: 960,
5187
+ * height: 540,
5188
+ * elements: [],
5189
+ * placeholders: [{ type: "title" }],
5190
+ * };
5191
+ * // => satisfies PptxLayoutPreview
5192
+ * ```
5193
+ */
5194
+ interface PptxLayoutPreview {
5195
+ /** ZIP path of the layout this preview belongs to. */
5196
+ path: string;
5197
+ /** Slide width in CSS pixels, so a thumbnail can compute its own scale. */
5198
+ width: number;
5199
+ /** Slide height in CSS pixels. */
5200
+ height: number;
5201
+ /** Background resolved from the layout, falling back to its master's. */
5202
+ backgroundColor?: string;
5203
+ /** Background image data URL, when the layout or master declares one. */
5204
+ backgroundImage?: string;
5205
+ /** The layout's own artwork (pictures, shapes and static text). */
5206
+ elements: PptxElement[];
5207
+ /** Placeholder slots, drawn as outlined frames in the gallery. */
5208
+ placeholders: PptxPlaceholderFrame[];
5209
+ }
5083
5210
  /**
5084
5211
  * A theme part available in the presentation package.
5085
5212
  *
@@ -7699,6 +7826,8 @@ interface IPptxHandlerRuntime {
7699
7826
  revokeBlobUrls(): void;
7700
7827
  getCompatibilityWarnings(): PptxCompatibilityWarning[];
7701
7828
  getLayoutOptions(): PptxLayoutOption[];
7829
+ getLayoutPreview(layoutPath: string): Promise<PptxLayoutPreview | null>;
7830
+ getLayoutPreviews(layoutPaths?: readonly string[]): Promise<PptxLayoutPreview[]>;
7702
7831
  createXmlBuilder(data: PptxData): PptxXmlBuilder;
7703
7832
  Builder(data: PptxData): PptxXmlBuilder;
7704
7833
  setTemplateBackground(path: string, backgroundColor: string | undefined): void;
@@ -7887,6 +8016,26 @@ declare class PptxHandlerCore {
7887
8016
  * @returns Array of {@link PptxLayoutOption} entries.
7888
8017
  */
7889
8018
  getLayoutOptions(): PptxLayoutOption[];
8019
+ /**
8020
+ * Build the artwork thumbnails backing the New Slide / Layout galleries.
8021
+ *
8022
+ * Parsing happens on first request and is memoised afterwards, so opening
8023
+ * the gallery costs one pass over the layout parts and reopening it costs
8024
+ * nothing. Callers that only need one entry should prefer
8025
+ * {@link getLayoutPreview}.
8026
+ *
8027
+ * @param layoutPaths - Restrict the result to these layouts; defaults to
8028
+ * every layout in the presentation.
8029
+ * @returns One {@link PptxLayoutPreview} per resolvable layout.
8030
+ */
8031
+ getLayoutPreviews(layoutPaths?: readonly string[]): Promise<PptxLayoutPreview[]>;
8032
+ /**
8033
+ * Build the artwork thumbnail for a single layout.
8034
+ *
8035
+ * @param layoutPath - Archive path of the `p:sldLayout` part.
8036
+ * @returns The preview, or `null` when the presentation has no such layout.
8037
+ */
8038
+ getLayoutPreview(layoutPath: string): Promise<PptxLayoutPreview | null>;
7890
8039
  /**
7891
8040
  * Create a fluent XML builder scoped to the given presentation data.
7892
8041
  *
@@ -8670,6 +8819,20 @@ interface ElementAnimationState {
8670
8819
  animatesStroke?: boolean;
8671
8820
  }
8672
8821
  //#endregion
8822
+ //#region src/render/table-merge.d.ts
8823
+ /** A cell coordinate within a table (0-based). */
8824
+ interface CellCoord {
8825
+ row: number;
8826
+ col: number;
8827
+ }
8828
+ /** The bounding rectangle of a cell selection (inclusive end coordinates). */
8829
+ interface CellRect {
8830
+ startRow: number;
8831
+ startCol: number;
8832
+ endRow: number;
8833
+ endCol: number;
8834
+ }
8835
+ //#endregion
8673
8836
  //#region src/render/element-align.d.ts
8674
8837
  /**
8675
8838
  * Pure geometry helpers for the align / distribute editor operations.
@@ -8776,6 +8939,17 @@ interface FieldSubstitutionContext {
8776
8939
  /** Title text extracted from the first title placeholder on the slide. */
8777
8940
  slideTitle?: string;
8778
8941
  }
8942
+ /** Descriptor for the draggable adjustment handle (the amber diamond). */
8943
+ interface ShapeAdjustmentHandleDescriptor {
8944
+ key: string;
8945
+ /** Handle x offset in element-local px (origin = element top-left). */
8946
+ left: number;
8947
+ /** Handle y offset in element-local px. */
8948
+ top: number;
8949
+ /** Current adjustment value (0–50000). */
8950
+ value: number;
8951
+ cursor: string;
8952
+ }
8779
8953
  //#endregion
8780
8954
  //#region src/render/collaboration-presence.d.ts
8781
8955
  /** Connection lifecycle states for the Yjs WebSocket provider. */
@@ -8944,6 +9118,19 @@ interface CompareResult {
8944
9118
  changedCount: number;
8945
9119
  unchangedCount: number;
8946
9120
  }
9121
+ /** Everything the Transitions tab's controls currently say. */
9122
+ interface RibbonTransitionDraft {
9123
+ /** The highlighted gallery entry. */
9124
+ type: PptxTransitionType;
9125
+ /** Duration field, in seconds. */
9126
+ durationSec: number;
9127
+ /** Advance Slide > On Mouse Click. */
9128
+ advanceOnClick: boolean;
9129
+ /** Advance Slide > After (whether the timed advance is armed at all). */
9130
+ advanceAfter: boolean;
9131
+ /** Advance Slide > After, as the `mm:ss.hh` text the field holds. */
9132
+ advanceAfterText: string;
9133
+ }
8947
9134
  /**
8948
9135
  * A font supplied by the host application. The package never ships fonts:
8949
9136
  * applications provide a licensed URL, data URL, or blob URL for their users.
@@ -9049,10 +9236,89 @@ interface ElementClipboardPayload {
9049
9236
  //#endregion
9050
9237
  //#region src/render/template-editing.d.ts
9051
9238
  type TemplateElementMap = Record<string, PptxElement[]>;
9239
+ /** What the "Embed fonts in the file" toggle should look like and do. */
9240
+ interface FontEmbeddingDescriptor {
9241
+ /** Distinct typeface names the loaded deck currently embeds. */
9242
+ embeddedFamilies: string[];
9243
+ /**
9244
+ * Whether the toggle accepts input. False when the deck embeds nothing,
9245
+ * because turning it on could not produce an embedded font.
9246
+ */
9247
+ interactive: boolean;
9248
+ /**
9249
+ * The position the toggle must START in so that it describes the file that
9250
+ * would be written right now. A deck that arrived with embedded fonts keeps
9251
+ * them on save, so the switch has to read "on" from the outset; the previous
9252
+ * hardcoded `false` said the opposite of what save actually did.
9253
+ */
9254
+ initialEnabled: boolean;
9255
+ /** Present only when `interactive` is false. */
9256
+ disabledReasonKey?: string;
9257
+ }
9052
9258
  /** The percentage one zoom-in press moves to, clamped. */
9053
9259
  declare function zoomInPercent(percent: number): number;
9054
9260
  /** The percentage one zoom-out press moves to, clamped. */
9055
9261
  declare function zoomOutPercent(percent: number): number;
9262
+ /**
9263
+ * Why the deck is being serialised, which is a separate question from whether
9264
+ * the user protected it.
9265
+ *
9266
+ * - `user-file` (the default): the bytes leave the viewer as a file. Save,
9267
+ * Save As, Export, the host-facing `getContent()`. Protection applies.
9268
+ * - `recovery-snapshot`: the bytes exist only so the viewer can read them back.
9269
+ * The autosave crash-recovery snapshot in IndexedDB, and the internal
9270
+ * re-serialise-then-reload cycle behind "apply theme". Protection does NOT
9271
+ * apply: these are always written in the clear.
9272
+ *
9273
+ * ## Why a recovery snapshot must stay plaintext
9274
+ *
9275
+ * Nothing that reads a snapshot back has a password to give it.
9276
+ * `readBackstageRecentFile`, `restoreSessionDeck` and the Version History
9277
+ * panel's Restore all hand `record.data` straight to `PptxHandler.load()` with
9278
+ * no `password` option, and an encrypted package refuses to open without one
9279
+ * (`EncryptedFileError`). So an encrypted snapshot is not an inconvenience, it
9280
+ * is unreadable: the moment the user turns on protection their crash-recovery
9281
+ * data is silently destroyed, which is the exact opposite of what autosave is
9282
+ * for.
9283
+ *
9284
+ * Encrypting it "properly" is not available either. Decrypting on recovery
9285
+ * means the key has to outlive the crash the snapshot exists for, so it would
9286
+ * have to sit in the same IndexedDB / localStorage as the snapshot itself,
9287
+ * next to the ciphertext it unlocks. That is not a security boundary, it is
9288
+ * theatre. Prompting the user instead only works if they remember the password
9289
+ * of a deck they lost, which is precisely the moment they will not.
9290
+ *
9291
+ * ## The tradeoff this accepts (deliberately, not by omission)
9292
+ *
9293
+ * A password-protected deck DOES leave its content in cleartext at rest in the
9294
+ * origin's IndexedDB. Anyone with the browser profile, or any script running on
9295
+ * the origin, can read it. What limits the exposure: snapshots are scoped to
9296
+ * the origin and profile, aged out by the store, and clearable from
9297
+ * File > Account > Storage & Privacy (`clearLocalStorageData`). A user who
9298
+ * cannot accept plaintext at rest should switch AutoSave off, which stops the
9299
+ * snapshot being written at all.
9300
+ *
9301
+ * The rejected alternative was "skip autosave entirely while a password is
9302
+ * set". It removes the plaintext, but it also removes crash recovery without
9303
+ * telling anyone, so a crash loses the whole editing session. Losing data
9304
+ * quietly is the failure mode we are fixing, not a fix for it.
9305
+ */
9306
+ type DeckSavePurpose = 'user-file' | 'recovery-snapshot';
9307
+ /**
9308
+ * What the Protect-Presentation UI knows at save time. `password` is the secret
9309
+ * the dialog captured; `passwordProtected` is the separate "is protected" flag
9310
+ * some bindings track for the badge. When the flag is explicitly `false` the
9311
+ * deck saves in the clear even if a stale secret is still around, so removing
9312
+ * a password can never leave the next save encrypted.
9313
+ *
9314
+ * `purpose` defaults to `'user-file'`; see {@link DeckSavePurpose} for why
9315
+ * `'recovery-snapshot'` overrides the password.
9316
+ */
9317
+ interface DeckSaveIntent {
9318
+ password?: string | null;
9319
+ passwordProtected?: boolean;
9320
+ purpose?: DeckSavePurpose;
9321
+ }
9056
9322
  //#endregion
9057
9323
  //#region src/render/viewer-preferences.d.ts
9058
9324
  /** Framework-neutral viewer preferences surfaced by Settings dialogs. */
@@ -9134,6 +9400,15 @@ interface ViewerGeneralOptions {
9134
9400
  userName: string;
9135
9401
  userInitials: string;
9136
9402
  showStartScreen: boolean;
9403
+ /**
9404
+ * Lets the user hand a local font file to the viewer so decks authored
9405
+ * with a font the browser lacks render with the real face.
9406
+ *
9407
+ * Off by default. The registration reads a file the user picks and adds it
9408
+ * to the page's font set for the session, which is a capability a host
9409
+ * embedding the viewer should opt into rather than inherit.
9410
+ */
9411
+ enableCustomFontUpload: boolean;
9137
9412
  }
9138
9413
  interface ViewerProofingOptions {
9139
9414
  autoCorrectTwoInitialCapitals: boolean;
@@ -10168,6 +10443,14 @@ interface AutosaveDeps {
10168
10443
  getSections?: () => PptxSection[];
10169
10444
  /** The live core handler used to serialize slides to `.pptx` bytes. */
10170
10445
  getHandler: () => PptxHandler | null;
10446
+ /**
10447
+ * The Protect-Presentation state, forwarded to the shared save decision.
10448
+ * Optional, and deliberately inert: a recovery snapshot is written in the
10449
+ * clear whatever it says (see `deck-save-encryption` in
10450
+ * `pptx-viewer-shared`). It is threaded through so the snapshot path uses
10451
+ * the same one decision function as every real save.
10452
+ */
10453
+ getSaveIntent?: () => DeckSaveIntent;
10171
10454
  /**
10172
10455
  * Monotonic load counter: a change means a fresh presentation was seeded (not
10173
10456
  * a user edit), so the watcher clears dirty instead of arming a save.
@@ -10564,6 +10847,8 @@ declare class EditorMasterController {
10564
10847
  enter(masterIndex?: number, layoutIndex?: number | null): void;
10565
10848
  enterTab(tab: MasterViewTab): void;
10566
10849
  exit(): void;
10850
+ /** The document shape the shared master-view rules operate on. */
10851
+ private document;
10567
10852
  activeElements(): PptxElement[] | null;
10568
10853
  replace(elements: PptxElement[]): boolean;
10569
10854
  cloneMasters(): PptxSlideMaster[];
@@ -10661,6 +10946,13 @@ declare class EditorSlidesController {
10661
10946
  * deck is loaded. Backs the Home tab's Layout dropdown (React parity).
10662
10947
  */
10663
10948
  availableLayouts(): Promise<PptxLayoutOption[]>;
10949
+ /**
10950
+ * Artwork thumbnails for the New Slide / Layout galleries, keyed by path.
10951
+ *
10952
+ * A method rather than state: parsing every layout part is only worth doing
10953
+ * once a gallery is opened, and core memoises the result.
10954
+ */
10955
+ layoutPreviews(): Promise<ReadonlyMap<string, PptxLayoutPreview>>;
10664
10956
  /** Re-map the current slide onto `layoutPath`. Returns its index, or null when not editable. */
10665
10957
  applyLayout(layoutPath: string): Promise<number | null>;
10666
10958
  /**
@@ -10701,6 +10993,66 @@ declare class EditorTransitionController {
10701
10993
  #private;
10702
10994
  constructor(editor: EditorState);
10703
10995
  applyTransition(type: PptxTransitionType, durationMs: number, applyToAll: boolean): void;
10996
+ /**
10997
+ * Commit the Transitions tab's whole draft (preset + duration + the Advance
10998
+ * Slide modifiers) in one undoable step.
10999
+ *
11000
+ * The draft, and what it means for a slide's `p:transition`, is decided in
11001
+ * `pptx-viewer-shared` (`ribbon-transitions`) so every binding writes the
11002
+ * same fields; this only routes the result through `commitSlides`. Unlike
11003
+ * `applyTransition`'s apply-to-all, the draft is MERGED onto each target so a
11004
+ * slide keeps its authored direction / spokes / sound.
11005
+ */
11006
+ applyRibbonDraft(draft: RibbonTransitionDraft, applyToAll: boolean): void;
11007
+ }
11008
+
11009
+ /**
11010
+ * The block of table cells the user has marquee'd on the canvas.
11011
+ *
11012
+ * Svelte shipped without this model at all: `context-menu-dispatch` hard-coded
11013
+ * `hasMultiCellSelection: false`, so PowerPoint's "Merge Cells" could never be
11014
+ * offered and a user could only ever merge one cell rightwards or downwards.
11015
+ *
11016
+ * None of the rectangle math lives here. `computeSelectionRect` in
11017
+ * `pptx-viewer-shared` owns it, and it is merge-AWARE: dragging across a cell
11018
+ * that already spans expands the rectangle to cover the whole span, so the
11019
+ * highlighted block is always a real rectangle in model coordinates. (The
11020
+ * vanilla binding carries a private `rectangle()` helper that ignores spans;
11021
+ * that is a bug, not a second model, and is deliberately not copied.)
11022
+ *
11023
+ * @module editor/table-cell-selection
11024
+ */
11025
+ /** A click on a `<td>`, in model (unmerged) coordinates. */
11026
+ interface TableCellPoint {
11027
+ rowIndex: number;
11028
+ columnIndex: number;
11029
+ }
11030
+ declare class TableCellSelection {
11031
+ /** The table element the range belongs to, or null when there is none. */
11032
+ elementId: string | null;
11033
+ /** Where the range started (the un-shifted click). */
11034
+ anchor: CellCoord | null;
11035
+ /** The current rectangle, already expanded over any merged cells it meets. */
11036
+ rect: CellRect | null;
11037
+ /** Every cell in the current range, row-major. Empty when there is none. */
11038
+ get cells(): CellCoord[];
11039
+ /** True once the range covers a block, i.e. once merging becomes possible. */
11040
+ get hasBlock(): boolean;
11041
+ /** The range on `elementId`, or an empty array when it belongs elsewhere. */
11042
+ cellsFor(elementId: string | null | undefined): CellCoord[];
11043
+ /** Is this cell of this element inside the highlighted block? */
11044
+ contains(elementId: string, row: number, col: number): boolean;
11045
+ /** A plain click: the range collapses to the clicked cell, which anchors it. */
11046
+ begin(elementId: string, cell: TableCellPoint, tableData: PptxTableData): void;
11047
+ /**
11048
+ * A Shift-click: stretch anchor -> cell into a rectangle. Falls back to
11049
+ * anchoring when there is no anchor yet (or it belongs to another table), so
11050
+ * a Shift-click is never a no-op.
11051
+ */
11052
+ extend(elementId: string, cell: TableCellPoint, tableData: PptxTableData): void;
11053
+ clear(): void;
11054
+ /** Drop the range when the element selection has moved off its table. */
11055
+ syncElement(selectedElementId: string | null): void;
10704
11056
  }
10705
11057
 
10706
11058
  interface EditorStateDeps {
@@ -10726,13 +11078,52 @@ declare class EditorState {
10726
11078
  * carried through the undo snapshot and re-emitted on save.
10727
11079
  */
10728
11080
  tagCollections: PptxTagCollection[];
11081
+ /**
11082
+ * The deck's active theme, kept here so the Home tab's font dropdown can
11083
+ * lead with the theme fonts. Set by the viewer once a deck is loaded;
11084
+ * deliberately outside {@link EditorSnapshot} because it is not content the
11085
+ * undo stack owns.
11086
+ */
11087
+ theme: PptxTheme | undefined;
11088
+ /**
11089
+ * Families the deck embeds, offered as their own font-dropdown group. Write
11090
+ * through {@link adoptEmbeddedFontFamilies} so {@link embedFonts} is reseeded
11091
+ * with them.
11092
+ */
11093
+ embeddedFontFamilies: readonly string[];
11094
+ /**
11095
+ * File > Fonts > "Embed fonts in the file". Session state like
11096
+ * {@link savePassword}, not document content, so undo never restores it.
11097
+ * Seeded from the loaded deck (see {@link adoptEmbeddedFontFamilies}): a deck
11098
+ * that arrived with embedded fonts keeps them on save, so the switch has to
11099
+ * start "on" or turning it off would be the only way to describe what save
11100
+ * already does. Read by `saveEditorDocument`.
11101
+ */
11102
+ embedFonts: boolean;
11103
+ /**
11104
+ * Families the user registered from a local font file this session
11105
+ * (File > Options > Fonts, off by default). Session state, never persisted:
11106
+ * the font binary is the user's, not ours to store.
11107
+ */
11108
+ customFontFamilies: readonly string[];
10729
11109
  masterViewTarget: MasterViewTarget | null;
10730
11110
  readonly selection: EditorSelection;
11111
+ /** The block of table cells marquee'd inside the selected table, if any. */
11112
+ readonly tableCells: TableCellSelection;
10731
11113
  editable: boolean;
10732
11114
  dirty: boolean;
10733
11115
  editTemplateMode: boolean;
10734
11116
  interactionActive: boolean;
10735
11117
  clipboard: ElementClipboardPayload | null;
11118
+ /**
11119
+ * File ▸ Info ▸ Protect Presentation state. Deliberately NOT part of
11120
+ * {@link EditorSnapshot}: the secret is session state, not document content,
11121
+ * so undo must never restore or clear it. {@link saveIntent} feeds it to the
11122
+ * shared `planDeckSave`, which routes a protected save through
11123
+ * `saveEncrypted` (an OLE2 container) instead of `save` (a plain ZIP).
11124
+ */
11125
+ passwordProtected: boolean;
11126
+ savePassword: string | null;
10736
11127
  /** Undo/redo stack; the `canUndo` / `canRedo` getters below mirror it. */
10737
11128
  readonly history: EditorHistoryState;
10738
11129
  readonly clipboardOps: EditorClipboardController;
@@ -10770,6 +11161,15 @@ declare class EditorState {
10770
11161
  applyRemoteSlides(slides: PptxSlide[]): void;
10771
11162
  reset(): void;
10772
11163
  select(id: string | null): void;
11164
+ /** The element with `id` on the surface the pointer acts on, or undefined. */
11165
+ elementById(id: string): PptxElement | undefined;
11166
+ /**
11167
+ * May the pointer act on `id` at all? Two gates, both of which must pass:
11168
+ * the template rule (an inherited master/layout node is inert unless
11169
+ * edit-template mode is on) and the element's own authored `a:spLocks`. The
11170
+ * lock half was missing entirely, which is why a `noSelect` shape from a
11171
+ * real deck was as selectable and draggable as any other.
11172
+ */
10773
11173
  isElementInteractive(id: string): boolean;
10774
11174
  setTemplateEditing(enabled: boolean): void;
10775
11175
  /** Apply the File > Options "maximum number of undos" value. */
@@ -10790,6 +11190,21 @@ declare class EditorState {
10790
11190
  commitSlides(next: PptxSlide[]): void;
10791
11191
  /** A deep clone of the whole editable document (one undo entry, or save input). */
10792
11192
  snapshot(): EditorSnapshot;
11193
+ /**
11194
+ * Adopt the families a freshly loaded deck embeds, and reseed
11195
+ * {@link embedFonts} to the position that describes the file save would write
11196
+ * right now. Deliberately not an undo step: the parsed font list is not a
11197
+ * user edit.
11198
+ */
11199
+ adoptEmbeddedFontFamilies(families: readonly string[]): void;
11200
+ /** How File > Fonts should render its toggle for the loaded deck. */
11201
+ get fontEmbedding(): FontEmbeddingDescriptor;
11202
+ /** The Protect-Presentation state every save path hands to `planDeckSave`. */
11203
+ saveIntent(): DeckSaveIntent;
11204
+ /** File ▸ Info ▸ Protect Presentation: arm password encryption for saves. */
11205
+ setSavePassword(password: string): void;
11206
+ /** File ▸ Info ▸ Protect Presentation: back to saving in the clear. */
11207
+ clearSavePassword(): void;
10793
11208
  deleteSelected: () => void;
10794
11209
  duplicateSelected: () => string | null;
10795
11210
  applyElementPatch: (id: string, patch: Partial<PptxElement>) => void;
@@ -10901,6 +11316,30 @@ interface EditorMarqueeRect extends MarqueeRect {
10901
11316
  additive: boolean;
10902
11317
  }
10903
11318
 
11319
+ /**
11320
+ * What the selection overlay is allowed to offer, given the authored
11321
+ * `a:spLocks` on the selected element(s).
11322
+ *
11323
+ * The lock composition itself is NOT decided here: `canInteractWithElement` in
11324
+ * `pptx-viewer-shared` is the one decision function all five bindings consult,
11325
+ * and this module only folds its per-element verdict into the collective one an
11326
+ * overlay drawn around N elements needs. Keeping it in a plain `.ts` module
11327
+ * (rather than inside `EditorController` or the overlay SFC) keeps both of
11328
+ * those within the repo's file-size budget and makes the rule unit-testable
11329
+ * without a component mount.
11330
+ *
11331
+ * @module editor/editor-selection-interactivity
11332
+ */
11333
+ /** The chrome the overlay may draw for the current selection. */
11334
+ interface SelectionInteractivity {
11335
+ /** Draw (and honour) the eight resize handles. */
11336
+ resizable: boolean;
11337
+ /** Draw (and honour) the rotate stem + knob. */
11338
+ rotatable: boolean;
11339
+ /** The amber adjustment diamond, or null when there is none to draw. */
11340
+ adjust: ShapeAdjustmentHandleDescriptor | null;
11341
+ }
11342
+
10904
11343
  declare class EditorController {
10905
11344
  #private;
10906
11345
  snapLines: readonly SnapLine[];
@@ -10908,6 +11347,12 @@ declare class EditorController {
10908
11347
  marquee: EditorMarqueeRect | null;
10909
11348
  constructor(editor: EditorState, deps: EditorControllerDeps);
10910
11349
  get overlayBox(): OverlayBox | null;
11350
+ /**
11351
+ * Which selection chrome the authored `a:spLocks` still permit, plus the
11352
+ * shape-adjustment descriptor. The overlay only ever sees an `OverlayBox`,
11353
+ * so the element-level verdict is computed here and passed down as a prop.
11354
+ */
11355
+ get interactivity(): SelectionInteractivity;
10911
11356
  get editing(): boolean;
10912
11357
  get selectionCount(): number;
10913
11358
  get editingElement(): PptxElement | undefined;
@@ -10920,6 +11365,7 @@ declare class EditorController {
10920
11365
  onStageContextMenu: (event: MouseEvent) => void;
10921
11366
  onHandlePointerDown: (handle: ResizeHandleId, event: PointerEvent) => void;
10922
11367
  onRotatePointerDown: (event: PointerEvent) => void;
11368
+ onAdjustPointerDown: (event: PointerEvent) => void;
10923
11369
  onKeyDown: (event: KeyboardEvent) => void;
10924
11370
  /** Open the inline text editor over `id` when the element carries text. */
10925
11371
  enterInlineEdit(id: string): void;
@@ -1,4 +1,4 @@
1
- import { A as e, O as a, a as s, c as t, ct as i, d as l, f as S, g as n, i as v, k as o, l as d, n as b, o as c, r as g, s as p, st as x, t as w, u as T } from "../export-DxMXX_It.js";
1
+ import { A as e, O as a, a as s, c as t, ct as i, d as l, f as S, g as n, i as v, k as o, l as d, n as b, o as c, r as g, s as p, st as x, t as w, u as T } from "../export-DbSAFc8m.js";
2
2
  var m = e, A = o, P = a;
3
3
  export {
4
4
  w as PowerPointViewer,