pptx-react-viewer 3.1.1 → 3.1.3

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 (161) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/{AiChatPanel-EIENGCKW.mjs → AiChatPanel-5JAQBLTU.mjs} +4 -4
  3. package/dist/AiChatPanel-5JAQBLTU.mjs.br +0 -0
  4. package/dist/AiChatPanel-5JAQBLTU.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-6PERJN7M.js → AiChatPanel-C3E7UV7T.js} +24 -24
  6. package/dist/AiChatPanel-C3E7UV7T.js.br +0 -0
  7. package/dist/AiChatPanel-C3E7UV7T.js.gz +0 -0
  8. package/dist/{Area3DChartScene-W6SVC235.mjs → Area3DChartScene-KE434ERF.mjs} +1 -1
  9. package/dist/{Area3DChartScene-W6SVC235.mjs.br → Area3DChartScene-KE434ERF.mjs.br} +0 -0
  10. package/dist/Area3DChartScene-KE434ERF.mjs.gz +0 -0
  11. package/dist/{Area3DChartScene-TXCLQLBQ.js → Area3DChartScene-XY2PKRMA.js} +2 -2
  12. package/dist/Area3DChartScene-XY2PKRMA.js.br +0 -0
  13. package/dist/Area3DChartScene-XY2PKRMA.js.gz +0 -0
  14. package/dist/{Bar3DChartScene-FCVUZIJ3.mjs → Bar3DChartScene-2KQABQZM.mjs} +1 -1
  15. package/dist/{Bar3DChartScene-FCVUZIJ3.mjs.br → Bar3DChartScene-2KQABQZM.mjs.br} +0 -0
  16. package/dist/Bar3DChartScene-2KQABQZM.mjs.gz +0 -0
  17. package/dist/{Bar3DChartScene-6RHPFLZT.js → Bar3DChartScene-YMADUUZN.js} +2 -2
  18. package/dist/Bar3DChartScene-YMADUUZN.js.br +0 -0
  19. package/dist/Bar3DChartScene-YMADUUZN.js.gz +0 -0
  20. package/dist/{Line3DChartScene-2ZFE53KO.js → Line3DChartScene-AB7N6ORX.js} +2 -2
  21. package/dist/Line3DChartScene-AB7N6ORX.js.br +0 -0
  22. package/dist/Line3DChartScene-AB7N6ORX.js.gz +0 -0
  23. package/dist/{Line3DChartScene-MJXFXSPW.mjs → Line3DChartScene-K3BSK6BB.mjs} +1 -1
  24. package/dist/{Line3DChartScene-MJXFXSPW.mjs.br → Line3DChartScene-K3BSK6BB.mjs.br} +0 -0
  25. package/dist/Line3DChartScene-K3BSK6BB.mjs.gz +0 -0
  26. package/dist/{Model3DScene-A5RV3KNJ.mjs → Model3DScene-NT5RRIB5.mjs} +1 -1
  27. package/dist/{Model3DScene-A5RV3KNJ.mjs.br → Model3DScene-NT5RRIB5.mjs.br} +0 -0
  28. package/dist/Model3DScene-NT5RRIB5.mjs.gz +0 -0
  29. package/dist/{Model3DScene-7VQNRY5B.js → Model3DScene-VSLGUWC7.js} +2 -2
  30. package/dist/{Model3DScene-7VQNRY5B.js.br → Model3DScene-VSLGUWC7.js.br} +0 -0
  31. package/dist/Model3DScene-VSLGUWC7.js.gz +0 -0
  32. package/dist/{PieChart3DScene-JTHZESS3.js → PieChart3DScene-6MUFRFYJ.js} +2 -2
  33. package/dist/PieChart3DScene-6MUFRFYJ.js.br +0 -0
  34. package/dist/PieChart3DScene-6MUFRFYJ.js.gz +0 -0
  35. package/dist/{PieChart3DScene-UEVFZZVW.mjs → PieChart3DScene-NFRBKII7.mjs} +1 -1
  36. package/dist/PieChart3DScene-NFRBKII7.mjs.br +0 -0
  37. package/dist/PieChart3DScene-NFRBKII7.mjs.gz +0 -0
  38. package/dist/PowerPointViewer-Cl6jBPNw.d.ts.map +1 -1
  39. package/dist/{SurfaceChart3DScene-FXUNT5OK.js → SurfaceChart3DScene-2UQOKVFB.js} +2 -2
  40. package/dist/SurfaceChart3DScene-2UQOKVFB.js.br +0 -0
  41. package/dist/SurfaceChart3DScene-2UQOKVFB.js.gz +0 -0
  42. package/dist/{SurfaceChart3DScene-WD65PAG4.mjs → SurfaceChart3DScene-UKIOTKJC.mjs} +1 -1
  43. package/dist/{SurfaceChart3DScene-WD65PAG4.mjs.br → SurfaceChart3DScene-UKIOTKJC.mjs.br} +0 -0
  44. package/dist/SurfaceChart3DScene-UKIOTKJC.mjs.gz +0 -0
  45. package/dist/{chunk-ICAYXQVJ.mjs → chunk-5WH6UVWC.mjs} +289 -135
  46. package/dist/chunk-5WH6UVWC.mjs.br +0 -0
  47. package/dist/chunk-5WH6UVWC.mjs.gz +0 -0
  48. package/dist/{chunk-OUX4O5XK.mjs → chunk-ACVLIDUS.mjs} +2 -2
  49. package/dist/chunk-ACVLIDUS.mjs.br +0 -0
  50. package/dist/chunk-ACVLIDUS.mjs.gz +0 -0
  51. package/dist/{chunk-MKPSUHUH.mjs → chunk-ARJE3V6V.mjs} +5 -6
  52. package/dist/chunk-ARJE3V6V.mjs.br +0 -0
  53. package/dist/chunk-ARJE3V6V.mjs.gz +0 -0
  54. package/dist/{chunk-MAOUVROK.mjs → chunk-BZ6OM3H5.mjs} +360 -338
  55. package/dist/chunk-BZ6OM3H5.mjs.br +0 -0
  56. package/dist/chunk-BZ6OM3H5.mjs.gz +0 -0
  57. package/dist/{chunk-GIFQWIW5.js → chunk-GCOGKBK3.js} +1368 -1214
  58. package/dist/chunk-GCOGKBK3.js.br +0 -0
  59. package/dist/chunk-GCOGKBK3.js.gz +0 -0
  60. package/dist/{chunk-IDTNKL4S.js → chunk-HMZA25W2.js} +300 -45
  61. package/dist/chunk-HMZA25W2.js.br +0 -0
  62. package/dist/chunk-HMZA25W2.js.gz +0 -0
  63. package/dist/{chunk-OZGFMZEX.js → chunk-K4DUVYZ7.js} +3 -3
  64. package/dist/chunk-K4DUVYZ7.js.br +0 -0
  65. package/dist/chunk-K4DUVYZ7.js.gz +0 -0
  66. package/dist/{chunk-GCE2TYHF.js → chunk-OABOL32L.js} +157 -157
  67. package/dist/chunk-OABOL32L.js.br +0 -0
  68. package/dist/chunk-OABOL32L.js.gz +0 -0
  69. package/dist/{chunk-ISDTM2V3.mjs → chunk-SRAXNEJX.mjs} +286 -45
  70. package/dist/chunk-SRAXNEJX.mjs.br +0 -0
  71. package/dist/chunk-SRAXNEJX.mjs.gz +0 -0
  72. package/dist/{chunk-PIUB7R2K.js → chunk-SWRY3SI5.js} +5 -6
  73. package/dist/chunk-SWRY3SI5.js.br +0 -0
  74. package/dist/chunk-SWRY3SI5.js.gz +0 -0
  75. package/dist/{chunk-OTBQBTTQ.js → chunk-XBR7W47W.js} +726 -706
  76. package/dist/chunk-XBR7W47W.js.br +0 -0
  77. package/dist/chunk-XBR7W47W.js.gz +0 -0
  78. package/dist/{chunk-5ERW2B25.mjs → chunk-Z3DEULRJ.mjs} +1 -1
  79. package/dist/chunk-Z3DEULRJ.mjs.br +0 -0
  80. package/dist/chunk-Z3DEULRJ.mjs.gz +0 -0
  81. package/dist/i18n.js +4 -4
  82. package/dist/i18n.js.br +0 -0
  83. package/dist/i18n.js.gz +0 -0
  84. package/dist/i18n.mjs +1 -1
  85. package/dist/i18n.mjs.br +0 -0
  86. package/dist/i18n.mjs.gz +0 -0
  87. package/dist/index.d.ts +27 -1
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +47 -47
  90. package/dist/index.js.br +0 -0
  91. package/dist/index.js.gz +0 -0
  92. package/dist/index.mjs +6 -6
  93. package/dist/index.mjs.br +0 -0
  94. package/dist/index.mjs.gz +0 -0
  95. package/dist/internals.d.ts +99 -22
  96. package/dist/internals.d.ts.map +1 -1
  97. package/dist/internals.js +79 -79
  98. package/dist/internals.js.br +0 -0
  99. package/dist/internals.js.gz +0 -0
  100. package/dist/internals.mjs +4 -4
  101. package/dist/internals.mjs.br +0 -0
  102. package/dist/internals.mjs.gz +0 -0
  103. package/dist/pptx-viewer.css +1 -1
  104. package/dist/pptx-viewer.css.br +0 -0
  105. package/dist/pptx-viewer.css.gz +0 -0
  106. package/dist/{useViewerBuildingBlocks-DC1O_op4.d.ts → useViewerBuildingBlocks-X1L8BjsQ.d.ts} +19 -2
  107. package/dist/useViewerBuildingBlocks-X1L8BjsQ.d.ts.map +1 -0
  108. package/dist/viewer/index.js +27 -27
  109. package/dist/viewer/index.js.br +0 -0
  110. package/dist/viewer/index.js.gz +0 -0
  111. package/dist/viewer/index.mjs +6 -6
  112. package/dist/viewer/index.mjs.br +0 -0
  113. package/dist/viewer/index.mjs.gz +0 -0
  114. package/package.json +1 -1
  115. package/dist/AiChatPanel-6PERJN7M.js.br +0 -0
  116. package/dist/AiChatPanel-6PERJN7M.js.gz +0 -0
  117. package/dist/AiChatPanel-EIENGCKW.mjs.br +0 -0
  118. package/dist/AiChatPanel-EIENGCKW.mjs.gz +0 -0
  119. package/dist/Area3DChartScene-TXCLQLBQ.js.br +0 -0
  120. package/dist/Area3DChartScene-TXCLQLBQ.js.gz +0 -0
  121. package/dist/Area3DChartScene-W6SVC235.mjs.gz +0 -0
  122. package/dist/Bar3DChartScene-6RHPFLZT.js.br +0 -0
  123. package/dist/Bar3DChartScene-6RHPFLZT.js.gz +0 -0
  124. package/dist/Bar3DChartScene-FCVUZIJ3.mjs.gz +0 -0
  125. package/dist/Line3DChartScene-2ZFE53KO.js.br +0 -0
  126. package/dist/Line3DChartScene-2ZFE53KO.js.gz +0 -0
  127. package/dist/Line3DChartScene-MJXFXSPW.mjs.gz +0 -0
  128. package/dist/Model3DScene-7VQNRY5B.js.gz +0 -0
  129. package/dist/Model3DScene-A5RV3KNJ.mjs.gz +0 -0
  130. package/dist/PieChart3DScene-JTHZESS3.js.br +0 -0
  131. package/dist/PieChart3DScene-JTHZESS3.js.gz +0 -0
  132. package/dist/PieChart3DScene-UEVFZZVW.mjs.br +0 -0
  133. package/dist/PieChart3DScene-UEVFZZVW.mjs.gz +0 -0
  134. package/dist/SurfaceChart3DScene-FXUNT5OK.js.br +0 -0
  135. package/dist/SurfaceChart3DScene-FXUNT5OK.js.gz +0 -0
  136. package/dist/SurfaceChart3DScene-WD65PAG4.mjs.gz +0 -0
  137. package/dist/chunk-5ERW2B25.mjs.br +0 -0
  138. package/dist/chunk-5ERW2B25.mjs.gz +0 -0
  139. package/dist/chunk-GCE2TYHF.js.br +0 -0
  140. package/dist/chunk-GCE2TYHF.js.gz +0 -0
  141. package/dist/chunk-GIFQWIW5.js.br +0 -0
  142. package/dist/chunk-GIFQWIW5.js.gz +0 -0
  143. package/dist/chunk-ICAYXQVJ.mjs.br +0 -0
  144. package/dist/chunk-ICAYXQVJ.mjs.gz +0 -0
  145. package/dist/chunk-IDTNKL4S.js.br +0 -0
  146. package/dist/chunk-IDTNKL4S.js.gz +0 -0
  147. package/dist/chunk-ISDTM2V3.mjs.br +0 -0
  148. package/dist/chunk-ISDTM2V3.mjs.gz +0 -0
  149. package/dist/chunk-MAOUVROK.mjs.br +0 -0
  150. package/dist/chunk-MAOUVROK.mjs.gz +0 -0
  151. package/dist/chunk-MKPSUHUH.mjs.br +0 -0
  152. package/dist/chunk-MKPSUHUH.mjs.gz +0 -0
  153. package/dist/chunk-OTBQBTTQ.js.br +0 -0
  154. package/dist/chunk-OTBQBTTQ.js.gz +0 -0
  155. package/dist/chunk-OUX4O5XK.mjs.br +0 -0
  156. package/dist/chunk-OUX4O5XK.mjs.gz +0 -0
  157. package/dist/chunk-OZGFMZEX.js.br +0 -0
  158. package/dist/chunk-OZGFMZEX.js.gz +0 -0
  159. package/dist/chunk-PIUB7R2K.js.br +0 -0
  160. package/dist/chunk-PIUB7R2K.js.gz +0 -0
  161. package/dist/useViewerBuildingBlocks-DC1O_op4.d.ts.map +0 -1
@@ -1,8 +1,7 @@
1
- import { cloneHistorySnapshot, MIN_ELEMENT_SIZE, ZOOM_TO_SELECTION_PADDING, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, UNGROUPED_SECTION_ID, DEFAULT_SECTION_GROUP_ID, DEFAULT_TABLE_ROWS, DEFAULT_TABLE_COLUMNS, executeMediaCommand, buildPdfFromImageData, buildNotesPdf, GRID_SIZE, DEFAULT_TEXT_FONT_SIZE } from './chunk-OUX4O5XK.mjs';
2
- import { translationsEn } from './chunk-MKPSUHUH.mjs';
3
- import { TOOLBAR_TABS, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createPresenceProjector, BROADCAST_THROTTLE_MS, createSyncGate, clearLocalAwareness, validateRoomId, createDepartureChannel, resolveTransportForServerUrl, isMixedContentBlocked, CONNECTION_TIMEOUT_MS, registerCollaborationTeardown, sanitizeColor, cloneTemplateElementsBySlideId, cloneSlide, createWheelStepBuffer, createViewerZoomStore, clampZoomScale, mapEditingWheel, PresentationAnimationController, PRESENTATION_HASH, PRESENTATION_NONCE_KEY, PRESENTATION_CHANNEL_NAME, swapPresentationWindows, PRESENTATION_MESSAGE_ORIGIN, clearAudienceContent, buildPresentationAudienceUrl, resolveAudienceScreenPlacement, placeAudienceWindow, storeAudienceContent, isPresentationSessionMessage, endAudienceDisplay, createPresentationKeyBuffer, acceptsPresentationInput, resolveAutoAdvanceDelayMs, hasShowSlideAfter, nextShowSlideIndex, previousShowSlideIndex, createPresenterShowGuard, attachPresentationVisibilityPause, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, createCollaborationLivePatcher, publishLiveInlineText, PptxHandler, collectMediaElements, collectImagePaths, collectTableCellImagePaths, applyTableCellImagePatches, collectTableStyleImagePaths, applyTableStyleImagePatches, partitionTemplateElements, resolveAuthoredCustomShowId, buildInitialGuides, EncryptedFileError, resolveAutosaveIntervalMs, shouldWriteAutosaveSnapshot, saveAutosaveSnapshot, autosaveSnapshotMark, updateMasterViewElement, isTemplateElementId, hasShapeProperties, hasTextProperties, getInlineEditorSelection, applyStyleToSelectedSegments, setPendingSelectionRestore, applyCaseTransformToSegments, transformTextCase, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, normalizeColorsForCapture, preprocessCssForCapture, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, recordProgressPercent, downloadBlob, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, comparePresentation, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, mayLeaveSlideShow, stopAllPersistentAudio, remapTextToSegments, guidePxToEmu, buildSaveSlides, embeddedFontSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, shouldProbeAutosaveRecovery, probeAutosaveRecovery, acceptAutosaveRecovery, discardAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, copyFormatFromElement, applyFormatToElement, mapEditorKey, isEditorTextInputTarget, createViewerOptionsStore, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, LOCAL_SYNC_ORIGIN, observeYDocSlides, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, isKeyboardOpen, scopeLayoutOptionsToSlide, openPptxFile, readBackstageRecentFile, isActionHidden, resolveInlineEditAutoFitHeight, canInteractWithElement, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, savedPresentationFileName, generatePackageReadme, presentationBaseName, exportDeckJson, groupElements, generateElementId, makeCloneId, ungroupElements, alignElements, distributeElements, bringForward, sendBackward, bringToFront, sendToBack, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, mergeShapes, mapPresentationKey, lastShowSlideIndex, firstShowSlideIndex, mapPresentationWheel, computeColorFilter, computeSlideIndices, buildPrintDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, buildThemeColorMap, reResolveSlideColors, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, runPresentationAction, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, replyToCommentInList, canvasToJpegData, downloadDataUrl, pickSupportedMimeType, WEBM_MIME_CANDIDATES, fpsToFrameIntervalMs, segmentFrameCount, encodeGif, computeGridSpacingPx, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, hasCopyableFormat, createBackstagePresentation, buildFieldSubstitutionContext, cloneElementForPaste, computeScrollDelta, getPresetShapeClipPath, svgPathToPolygons, polygonsToSvgPath, rerouteConnectorsForMovedElements, applyReroutedConnectors, SvgExporter, buildPrintHtmlDocument, deleteTableColumn, rebuildTableStructureInRawXml, insertTableColumn, deleteTableRow, insertTableRow, updateCellTextStyleInRawXml, setCellText, updateCellTextInRawXml, splitCell, updateMergeAttrsInRawXml, mergeCells, isPpactionUrl, parsePpactionUrl, safeOpenUrl, ACTION_BUTTON_PRESETS, elementActionToPptxAction, isUrlSafe, buildSmartArtPresetData, classifyMediaType, computeSnapToShape, publishLiveGeometry, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, applyResize, snapBoxToGrid, applyMotionPathPreset } from './chunk-ISDTM2V3.mjs';
4
- import { useRef, useState, useEffect, useCallback, useMemo, useLayoutEffect, useImperativeHandle, useSyncExternalStore } from 'react';
5
- import JSZip from 'jszip';
1
+ import { cloneHistorySnapshot, MIN_ELEMENT_SIZE, ZOOM_TO_SELECTION_PADDING, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, UNGROUPED_SECTION_ID, DEFAULT_SECTION_GROUP_ID, DEFAULT_TABLE_ROWS, DEFAULT_TABLE_COLUMNS, executeMediaCommand, buildPdfFromImageData, buildNotesPdf, GRID_SIZE, DEFAULT_TEXT_FONT_SIZE } from './chunk-ACVLIDUS.mjs';
2
+ import { translationsEn } from './chunk-ARJE3V6V.mjs';
3
+ import { DEFAULT_VIEWER_OPTIONS, TOOLBAR_TABS, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createPresenceProjector, BROADCAST_THROTTLE_MS, createSyncGate, clearLocalAwareness, validateRoomId, createDepartureChannel, resolveTransportForServerUrl, isMixedContentBlocked, CONNECTION_TIMEOUT_MS, registerCollaborationTeardown, sanitizeColor, cloneTemplateElementsBySlideId, cloneSlide, createWheelStepBuffer, createViewerZoomStore, clampZoomScale, mapEditingWheel, PresentationAnimationController, PRESENTATION_HASH, PRESENTATION_NONCE_KEY, PRESENTATION_CHANNEL_NAME, swapPresentationWindows, PRESENTATION_MESSAGE_ORIGIN, clearAudienceContent, buildPresentationAudienceUrl, resolveAudienceScreenPlacement, placeAudienceWindow, storeAudienceContent, isPresentationSessionMessage, endAudienceDisplay, createPresentationKeyBuffer, acceptsPresentationInput, resolveAutoAdvanceDelayMs, hasShowSlideAfter, nextShowSlideIndex, previousShowSlideIndex, createPresenterShowGuard, attachPresentationVisibilityPause, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, createCollaborationLivePatcher, publishLiveInlineText, PptxHandler, collectMediaElements, collectImagePaths, collectTableCellImagePaths, applyTableCellImagePatches, collectTableStyleImagePaths, applyTableStyleImagePatches, partitionTemplateElements, resolveAuthoredCustomShowId, buildInitialGuides, EncryptedFileError, resolveAutosaveIntervalMs, shouldWriteAutosaveSnapshot, saveAutosaveSnapshot, autosaveSnapshotMark, updateMasterViewElement, isTemplateElementId, hasShapeProperties, hasTextProperties, getInlineEditorSelection, applyStyleToSelectedSegments, setPendingSelectionRestore, applyCaseTransformToSegments, transformTextCase, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, normalizeColorsForCapture, preprocessCssForCapture, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, recordProgressPercent, downloadBlob, resolveImageResolutionScale, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, comparePresentation, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, mayLeaveSlideShow, stopAllPersistentAudio, remapTextToSegments, guidePxToEmu, buildSaveSlides, embeddedFontSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, shouldProbeAutosaveRecovery, probeAutosaveRecovery, acceptAutosaveRecovery, discardAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, copyFormatFromElement, applyFormatToElement, mapEditorKey, isEditorTextInputTarget, createViewerOptionsStore, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, LOCAL_SYNC_ORIGIN, observeYDocSlides, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, isKeyboardOpen, scopeLayoutOptionsToSlide, openPptxFile, readBackstageRecentFile, isActionHidden, resolveInlineEditAutoFitHeight, canInteractWithElement, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, savedPresentationFileName, exportDeckJson, groupElements, generateElementId, makeCloneId, ungroupElements, alignElements, distributeElements, bringForward, sendBackward, bringToFront, sendToBack, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, mergeShapes, mapPresentationKey, lastShowSlideIndex, firstShowSlideIndex, mapPresentationWheel, openPendingPrintWindow, computeColorFilter, filterHiddenSlideIndices, computeSlideIndices, buildPrintDocument, finishPrintWindow, buildPrintHtmlDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, buildThemeColorMap, reResolveSlideColors, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, runPresentationAction, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, replyToCommentInList, canvasToJpegData, downloadDataUrl, pickSupportedMimeType, WEBM_MIME_CANDIDATES, fpsToFrameIntervalMs, segmentFrameCount, encodeGif, computeGridSpacingPx, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, resolveHistoryDepth, hasCopyableFormat, createBackstagePresentation, buildFieldSubstitutionContext, cloneElementForPaste, computeScrollDelta, getPresetShapeClipPath, svgPathToPolygons, polygonsToSvgPath, rerouteConnectorsForMovedElements, applyReroutedConnectors, SvgExporter, deleteTableColumn, rebuildTableStructureInRawXml, insertTableColumn, deleteTableRow, insertTableRow, updateCellTextStyleInRawXml, setCellText, updateCellTextInRawXml, splitCell, updateMergeAttrsInRawXml, mergeCells, isPpactionUrl, parsePpactionUrl, resolvePresentationAction, ACTION_BUTTON_PRESETS, elementActionToPptxAction, isUrlSafe, buildSmartArtPresetData, classifyMediaType, computeSnapToShape, publishLiveGeometry, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, shouldConfirmExternalHyperlink, safeOpenUrl, applyResize, snapBoxToGrid, applyMotionPathPreset } from './chunk-SRAXNEJX.mjs';
4
+ import { createContext, useRef, useState, useEffect, useCallback, useMemo, useLayoutEffect, useContext, useImperativeHandle, useSyncExternalStore } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
 
8
7
  function useVirtualizedSlides({
@@ -3792,7 +3791,8 @@ function useLoadContent({
3792
3791
  setError,
3793
3792
  setIsDirty,
3794
3793
  setIsEncrypted,
3795
- onContentApplied
3794
+ onContentApplied,
3795
+ allowExternalImages
3796
3796
  }) {
3797
3797
  const handlerRef = useRef(null);
3798
3798
  const originalBufferRef = useRef(null);
@@ -3818,7 +3818,7 @@ function useLoadContent({
3818
3818
  }
3819
3819
  const previousHandler = handlerRef.current;
3820
3820
  const handler = new PptxHandler();
3821
- const parsed = await handler.load(buffer);
3821
+ const parsed = await handler.load(buffer, { allowExternalImages });
3822
3822
  if (cancelled || token !== renderTokenRef.current) {
3823
3823
  handler.dispose();
3824
3824
  return;
@@ -4904,8 +4904,7 @@ function usePointerHandlers(input) {
4904
4904
  updateSlides,
4905
4905
  updateElementById,
4906
4906
  markDirty,
4907
- livePatcher,
4908
- input
4907
+ livePatcher
4909
4908
  ]);
4910
4909
  }
4911
4910
  function mouseDownStartsSelectionDrag(event) {
@@ -6546,13 +6545,15 @@ function createTableStructHandlers(input) {
6546
6545
  elementLookup,
6547
6546
  setTableEditorState,
6548
6547
  ops,
6549
- history
6548
+ history,
6549
+ transformCommittedText
6550
6550
  } = input;
6551
- const handleCommitCellEdit = (elementId, rowIndex, colIndex, text) => {
6551
+ const handleCommitCellEdit = (elementId, rowIndex, colIndex, rawText) => {
6552
6552
  const el = elementLookup.get(elementId);
6553
6553
  if (!el || el.type !== "table") {
6554
6554
  return;
6555
6555
  }
6556
+ const text = transformCommittedText ? transformCommittedText(rawText) : rawText;
6556
6557
  const updates = {};
6557
6558
  if (el.tableData) {
6558
6559
  updates.tableData = setCellText(el, rowIndex, colIndex, text).tableData;
@@ -6743,6 +6744,144 @@ async function renderToCanvas(element, options = {}) {
6743
6744
  });
6744
6745
  }
6745
6746
 
6747
+ // src/viewer/hooks/useExportSaveAs.ts
6748
+ function useExportSaveAs(input) {
6749
+ const {
6750
+ slides,
6751
+ templateElementsBySlideId,
6752
+ filePath,
6753
+ handlerRef,
6754
+ headerFooter,
6755
+ presentationProperties,
6756
+ customShows,
6757
+ sections,
6758
+ coreProperties,
6759
+ appProperties,
6760
+ customProperties,
6761
+ tagCollections,
6762
+ slideMasters,
6763
+ notesMaster,
6764
+ handoutMaster,
6765
+ guides,
6766
+ activeSlideIndexForGuides,
6767
+ theme,
6768
+ canvasSize,
6769
+ slideSizeEmu,
6770
+ password
6771
+ } = input;
6772
+ const handleSaveAsFormat = async (format) => {
6773
+ const handler = handlerRef.current;
6774
+ if (!handler) {
6775
+ return;
6776
+ }
6777
+ const downloadName = savedPresentationFileName(filePath, format);
6778
+ try {
6779
+ const data = await buildSaveAsData(handler, format);
6780
+ const blob = new Blob([data], {
6781
+ type: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
6782
+ });
6783
+ downloadBlob(blob, downloadName);
6784
+ } catch (err) {
6785
+ console.error(`[PowerPointViewer] Save as .${format} failed:`, err);
6786
+ }
6787
+ };
6788
+ const buildSaveAsData = async (handler, format) => {
6789
+ const slidesWithGuides = slides.map((slide, idx) => {
6790
+ if (idx !== activeSlideIndexForGuides) {
6791
+ return slide;
6792
+ }
6793
+ const pptxGuides = guides.map((g) => ({
6794
+ id: g.id,
6795
+ orientation: g.axis === "h" ? "horz" : "vert",
6796
+ positionEmu: guidePxToEmu(g.position)
6797
+ }));
6798
+ return {
6799
+ ...slide,
6800
+ guides: pptxGuides.length > 0 ? pptxGuides : void 0
6801
+ };
6802
+ });
6803
+ const slidesToSave = buildSaveSlides(slidesWithGuides, templateElementsBySlideId);
6804
+ const saveOptions = {
6805
+ // Save As shares Save's slide-size decision; leaving it out here is how
6806
+ // a preset picked in the inspector reached one save path and not the other.
6807
+ slideSize: resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size,
6808
+ headerFooter,
6809
+ presentationProperties,
6810
+ customShows: customShows.length > 0 ? customShows : void 0,
6811
+ sections: sections.length > 0 ? sections : void 0,
6812
+ coreProperties: coreProperties ?? void 0,
6813
+ appProperties: appProperties ?? void 0,
6814
+ customProperties: customProperties.length > 0 ? customProperties : void 0,
6815
+ tags: tagCollections.length > 0 ? tagCollections : void 0,
6816
+ slideMasters,
6817
+ notesMaster,
6818
+ handoutMaster,
6819
+ outputFormat: format
6820
+ };
6821
+ return saveDeckWithPassword(handler, slidesToSave, saveOptions, password);
6822
+ };
6823
+ const handleExportJson = () => {
6824
+ const sourceName = filePath ? filePath.replace(/\\/gu, "/").split("/").pop() : void 0;
6825
+ const slideSize = resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size;
6826
+ const data = {
6827
+ slides: buildSaveSlides(slides, templateElementsBySlideId),
6828
+ width: canvasSize.width,
6829
+ height: canvasSize.height,
6830
+ widthEmu: slideSize.widthEmu,
6831
+ heightEmu: slideSize.heightEmu,
6832
+ slideSizeType: slideSize.type === "" ? void 0 : slideSize.type,
6833
+ theme,
6834
+ headerFooter,
6835
+ presentationProperties,
6836
+ customShows: customShows.length > 0 ? customShows : void 0,
6837
+ sections: sections.length > 0 ? sections : void 0,
6838
+ coreProperties: coreProperties ?? void 0,
6839
+ appProperties: appProperties ?? void 0,
6840
+ customProperties: customProperties.length > 0 ? customProperties : void 0,
6841
+ tags: tagCollections.length > 0 ? tagCollections : void 0,
6842
+ notesMaster,
6843
+ handoutMaster
6844
+ };
6845
+ try {
6846
+ exportDeckJson(data, sourceName);
6847
+ } catch (err) {
6848
+ console.error("[PowerPointViewer] JSON export failed:", err);
6849
+ }
6850
+ };
6851
+ const handleSaveAsPptx = () => {
6852
+ void handleSaveAsFormat("pptx");
6853
+ };
6854
+ const handleSaveAsPpsx = () => {
6855
+ void handleSaveAsFormat("ppsx");
6856
+ };
6857
+ const handleSaveAsPptm = () => {
6858
+ void handleSaveAsFormat("pptm");
6859
+ };
6860
+ return {
6861
+ handleExportJson,
6862
+ handleSaveAsFormat,
6863
+ handleSaveAsPptx,
6864
+ handleSaveAsPpsx,
6865
+ handleSaveAsPptm
6866
+ };
6867
+ }
6868
+
6869
+ // src/viewer/utils/dom-helpers.ts
6870
+ function safePrompt(message, defaultValue) {
6871
+ try {
6872
+ return window.prompt(message, defaultValue);
6873
+ } catch {
6874
+ return null;
6875
+ }
6876
+ }
6877
+ function safeConfirm(message) {
6878
+ try {
6879
+ return window.confirm(message);
6880
+ } catch {
6881
+ return false;
6882
+ }
6883
+ }
6884
+
6746
6885
  // src/viewer/utils/export-helpers.ts
6747
6886
  async function renderElementToCanvas(element, scale = 2, backgroundColor) {
6748
6887
  const canvas = await renderToCanvas(element, {
@@ -7052,194 +7191,6 @@ function exportAllSlidesToSvg(data, options = {}) {
7052
7191
  return results;
7053
7192
  }
7054
7193
 
7055
- // src/viewer/hooks/useExportSaveAs.ts
7056
- function useExportSaveAs(input) {
7057
- const {
7058
- slides,
7059
- templateElementsBySlideId,
7060
- filePath,
7061
- handlerRef,
7062
- serializeSlides,
7063
- headerFooter,
7064
- presentationProperties,
7065
- customShows,
7066
- sections,
7067
- coreProperties,
7068
- appProperties,
7069
- customProperties,
7070
- tagCollections,
7071
- slideMasters,
7072
- notesMaster,
7073
- handoutMaster,
7074
- guides,
7075
- activeSlideIndexForGuides,
7076
- theme,
7077
- canvasSize,
7078
- slideSizeEmu,
7079
- modalControls,
7080
- password
7081
- } = input;
7082
- const {
7083
- setExportModalOpen,
7084
- setExportModalTitle,
7085
- setExportProgress,
7086
- setExportStatusMessage,
7087
- exportAbortRef
7088
- } = modalControls;
7089
- const handlePackageForSharing = async () => {
7090
- const abortCtrl = new AbortController();
7091
- exportAbortRef.current = abortCtrl;
7092
- setExportModalTitle("Package for Sharing");
7093
- setExportStatusMessage("Preparing package...");
7094
- setExportProgress(0);
7095
- setExportModalOpen(true);
7096
- try {
7097
- const zip = new JSZip();
7098
- const pkgFolder = zip.folder("presentation-package");
7099
- setExportProgress(10);
7100
- setExportStatusMessage("Adding presentation...");
7101
- const pptxData = await serializeSlides();
7102
- const pptxFilename = savedPresentationFileName(filePath);
7103
- if (pptxData) {
7104
- pkgFolder.file(pptxFilename, pptxData);
7105
- }
7106
- setExportProgress(70);
7107
- setExportStatusMessage("Writing README...");
7108
- const readme = generatePackageReadme(pptxFilename);
7109
- pkgFolder.file("README.txt", readme);
7110
- if (abortCtrl.signal.aborted) {
7111
- throw new DOMException("Export cancelled", "AbortError");
7112
- }
7113
- setExportProgress(85);
7114
- setExportStatusMessage("Generating ZIP...");
7115
- const zipBlob = await zip.generateAsync({ type: "blob" });
7116
- setExportProgress(95);
7117
- setExportStatusMessage("Downloading...");
7118
- downloadBlob(zipBlob, `${presentationBaseName(pptxFilename)}-package.zip`);
7119
- setExportProgress(100);
7120
- } catch (err) {
7121
- if (err.name !== "AbortError") {
7122
- console.error("[PowerPointViewer] Package export failed:", err);
7123
- }
7124
- } finally {
7125
- exportAbortRef.current = null;
7126
- setExportModalOpen(false);
7127
- }
7128
- };
7129
- const handleSaveAsFormat = async (format) => {
7130
- const handler = handlerRef.current;
7131
- if (!handler) {
7132
- return;
7133
- }
7134
- const downloadName = savedPresentationFileName(filePath, format);
7135
- try {
7136
- const data = await buildSaveAsData(handler, format);
7137
- const blob = new Blob([data], {
7138
- type: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
7139
- });
7140
- downloadBlob(blob, downloadName);
7141
- } catch (err) {
7142
- console.error(`[PowerPointViewer] Save as .${format} failed:`, err);
7143
- }
7144
- };
7145
- const buildSaveAsData = async (handler, format) => {
7146
- const slidesWithGuides = slides.map((slide, idx) => {
7147
- if (idx !== activeSlideIndexForGuides) {
7148
- return slide;
7149
- }
7150
- const pptxGuides = guides.map((g) => ({
7151
- id: g.id,
7152
- orientation: g.axis === "h" ? "horz" : "vert",
7153
- positionEmu: guidePxToEmu(g.position)
7154
- }));
7155
- return {
7156
- ...slide,
7157
- guides: pptxGuides.length > 0 ? pptxGuides : void 0
7158
- };
7159
- });
7160
- const slidesToSave = buildSaveSlides(slidesWithGuides, templateElementsBySlideId);
7161
- const saveOptions = {
7162
- // Save As shares Save's slide-size decision; leaving it out here is how
7163
- // a preset picked in the inspector reached one save path and not the other.
7164
- slideSize: resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size,
7165
- headerFooter,
7166
- presentationProperties,
7167
- customShows: customShows.length > 0 ? customShows : void 0,
7168
- sections: sections.length > 0 ? sections : void 0,
7169
- coreProperties: coreProperties ?? void 0,
7170
- appProperties: appProperties ?? void 0,
7171
- customProperties: customProperties.length > 0 ? customProperties : void 0,
7172
- tags: tagCollections.length > 0 ? tagCollections : void 0,
7173
- slideMasters,
7174
- notesMaster,
7175
- handoutMaster,
7176
- outputFormat: format
7177
- };
7178
- return saveDeckWithPassword(handler, slidesToSave, saveOptions, password);
7179
- };
7180
- const handleExportJson = () => {
7181
- const sourceName = filePath ? filePath.replace(/\\/gu, "/").split("/").pop() : void 0;
7182
- const slideSize = resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size;
7183
- const data = {
7184
- slides: buildSaveSlides(slides, templateElementsBySlideId),
7185
- width: canvasSize.width,
7186
- height: canvasSize.height,
7187
- widthEmu: slideSize.widthEmu,
7188
- heightEmu: slideSize.heightEmu,
7189
- slideSizeType: slideSize.type === "" ? void 0 : slideSize.type,
7190
- theme,
7191
- headerFooter,
7192
- presentationProperties,
7193
- customShows: customShows.length > 0 ? customShows : void 0,
7194
- sections: sections.length > 0 ? sections : void 0,
7195
- coreProperties: coreProperties ?? void 0,
7196
- appProperties: appProperties ?? void 0,
7197
- customProperties: customProperties.length > 0 ? customProperties : void 0,
7198
- tags: tagCollections.length > 0 ? tagCollections : void 0,
7199
- notesMaster,
7200
- handoutMaster
7201
- };
7202
- try {
7203
- exportDeckJson(data, sourceName);
7204
- } catch (err) {
7205
- console.error("[PowerPointViewer] JSON export failed:", err);
7206
- }
7207
- };
7208
- const handleSaveAsPptx = () => {
7209
- void handleSaveAsFormat("pptx");
7210
- };
7211
- const handleSaveAsPpsx = () => {
7212
- void handleSaveAsFormat("ppsx");
7213
- };
7214
- const handleSaveAsPptm = () => {
7215
- void handleSaveAsFormat("pptm");
7216
- };
7217
- return {
7218
- handleExportJson,
7219
- handlePackageForSharing,
7220
- handleSaveAsFormat,
7221
- handleSaveAsPptx,
7222
- handleSaveAsPpsx,
7223
- handleSaveAsPptm
7224
- };
7225
- }
7226
-
7227
- // src/viewer/utils/dom-helpers.ts
7228
- function safePrompt(message, defaultValue) {
7229
- try {
7230
- return window.prompt(message, defaultValue);
7231
- } catch {
7232
- return null;
7233
- }
7234
- }
7235
- function safeConfirm(message) {
7236
- try {
7237
- return window.confirm(message);
7238
- } catch {
7239
- return false;
7240
- }
7241
- }
7242
-
7243
7194
  // src/viewer/hooks/useExportHandlers.ts
7244
7195
  function useExportHandlers(input) {
7245
7196
  const {
@@ -7251,7 +7202,6 @@ function useExportHandlers(input) {
7251
7202
  canvasStageRef,
7252
7203
  setActiveSlideIndex,
7253
7204
  handlerRef,
7254
- serializeSlides,
7255
7205
  headerFooter,
7256
7206
  presentationProperties,
7257
7207
  customShows,
@@ -7268,23 +7218,16 @@ function useExportHandlers(input) {
7268
7218
  theme,
7269
7219
  canvasSize,
7270
7220
  slideSizeEmu,
7271
- password
7221
+ password,
7222
+ imageExportScale
7272
7223
  } = input;
7273
7224
  const [exportModalOpen, setExportModalOpen] = useState(false);
7274
7225
  const [exportModalTitle, setExportModalTitle] = useState("");
7275
7226
  const [exportProgress, setExportProgress] = useState(0);
7276
7227
  const [exportStatusMessage, setExportStatusMessage] = useState("");
7277
7228
  const exportAbortRef = useRef(null);
7278
- const modalControls = {
7279
- setExportModalOpen,
7280
- setExportModalTitle,
7281
- setExportProgress,
7282
- setExportStatusMessage,
7283
- exportAbortRef
7284
- };
7285
7229
  const {
7286
7230
  handleExportJson,
7287
- handlePackageForSharing,
7288
7231
  handleSaveAsFormat,
7289
7232
  handleSaveAsPptx,
7290
7233
  handleSaveAsPpsx,
@@ -7294,7 +7237,6 @@ function useExportHandlers(input) {
7294
7237
  templateElementsBySlideId,
7295
7238
  filePath,
7296
7239
  handlerRef,
7297
- serializeSlides,
7298
7240
  headerFooter,
7299
7241
  presentationProperties,
7300
7242
  customShows,
@@ -7311,7 +7253,6 @@ function useExportHandlers(input) {
7311
7253
  theme,
7312
7254
  canvasSize,
7313
7255
  slideSizeEmu,
7314
- modalControls,
7315
7256
  password
7316
7257
  });
7317
7258
  const handleExportPng = useCallback(async () => {
@@ -7321,12 +7262,13 @@ function useExportHandlers(input) {
7321
7262
  }
7322
7263
  try {
7323
7264
  await exportSlideAsPng(stageEl, activeSlideIndex, {
7324
- backgroundColor: activeSlide?.backgroundColor
7265
+ backgroundColor: activeSlide?.backgroundColor,
7266
+ scale: imageExportScale
7325
7267
  });
7326
7268
  } catch (err) {
7327
7269
  console.error("[PowerPointViewer] PNG export failed:", err);
7328
7270
  }
7329
- }, [canvasStageRef, activeSlideIndex, activeSlide?.backgroundColor]);
7271
+ }, [canvasStageRef, activeSlideIndex, activeSlide?.backgroundColor, imageExportScale]);
7330
7272
  const handleExportPdf = useCallback(async () => {
7331
7273
  if (!canvasStageRef.current) {
7332
7274
  return;
@@ -7345,7 +7287,7 @@ function useExportHandlers(input) {
7345
7287
  activeSlideIndex,
7346
7288
  "presentation.pdf",
7347
7289
  {
7348
- scale: 2,
7290
+ scale: imageExportScale,
7349
7291
  onProgress: (current, total) => {
7350
7292
  setExportProgress(slideProgressPercent(current, total));
7351
7293
  setExportStatusMessage(slideStatusLabel("Rendering", current, total));
@@ -7368,7 +7310,7 @@ function useExportHandlers(input) {
7368
7310
  exportAbortRef.current = null;
7369
7311
  setExportModalOpen(false);
7370
7312
  }
7371
- }, [canvasStageRef, slides.length, setActiveSlideIndex, activeSlideIndex]);
7313
+ }, [canvasStageRef, slides.length, setActiveSlideIndex, activeSlideIndex, imageExportScale]);
7372
7314
  const handleExportNotesPdf = useCallback(async () => {
7373
7315
  if (!canvasStageRef.current) {
7374
7316
  return;
@@ -7389,7 +7331,7 @@ function useExportHandlers(input) {
7389
7331
  slideNotes,
7390
7332
  "presentation-notes.pdf",
7391
7333
  {
7392
- scale: 2,
7334
+ scale: imageExportScale,
7393
7335
  onProgress: (current, total) => {
7394
7336
  setExportProgress(slideProgressPercent(current, total));
7395
7337
  setExportStatusMessage(slideStatusLabel("Rendering", current, total));
@@ -7412,7 +7354,7 @@ function useExportHandlers(input) {
7412
7354
  exportAbortRef.current = null;
7413
7355
  setExportModalOpen(false);
7414
7356
  }
7415
- }, [canvasStageRef, slides, setActiveSlideIndex, activeSlideIndex]);
7357
+ }, [canvasStageRef, slides, setActiveSlideIndex, activeSlideIndex, imageExportScale]);
7416
7358
  const handleCopySlideAsImage = useCallback(async () => {
7417
7359
  const stageEl = canvasStageRef.current;
7418
7360
  if (!stageEl) {
@@ -7420,12 +7362,13 @@ function useExportHandlers(input) {
7420
7362
  }
7421
7363
  try {
7422
7364
  await copySlideToClipboard(stageEl, {
7423
- backgroundColor: activeSlide?.backgroundColor
7365
+ backgroundColor: activeSlide?.backgroundColor,
7366
+ scale: imageExportScale
7424
7367
  });
7425
7368
  } catch (err) {
7426
7369
  console.error("[PowerPointViewer] Copy slide as image failed:", err);
7427
7370
  }
7428
- }, [canvasStageRef, activeSlide?.backgroundColor]);
7371
+ }, [canvasStageRef, activeSlide?.backgroundColor, imageExportScale]);
7429
7372
  const handleExportVideo = useCallback(async () => {
7430
7373
  if (!canvasStageRef.current) {
7431
7374
  return;
@@ -7522,7 +7465,6 @@ function useExportHandlers(input) {
7522
7465
  handleExportVideo,
7523
7466
  handleExportGif,
7524
7467
  handleExportJson,
7525
- handlePackageForSharing,
7526
7468
  handleSaveAsFormat,
7527
7469
  handleSaveAsPptx,
7528
7470
  handleSaveAsPpsx,
@@ -7534,95 +7476,96 @@ function useExportHandlers(input) {
7534
7476
  exportStatusMessage
7535
7477
  };
7536
7478
  }
7537
- function openPrintWindow(title, bodyHtml, orientation, colorFilter, frameSlides) {
7538
- const printWindow = window.open("", "_blank", "noopener,noreferrer");
7539
- if (!printWindow) {
7540
- return false;
7541
- }
7542
- printWindow.document.open();
7543
- printWindow.document.write(
7544
- buildPrintHtmlDocument({ title, bodyHtml, orientation, colorFilter, frameSlides })
7545
- );
7546
- printWindow.document.close();
7547
- printWindow.focus();
7548
- setTimeout(() => {
7549
- printWindow.print();
7550
- }, 300);
7551
- return true;
7552
- }
7553
- function openPrintWindowWithDocument(htmlDocument) {
7554
- const printWindow = window.open("", "_blank", "noopener,noreferrer");
7555
- if (!printWindow) {
7556
- return false;
7557
- }
7558
- printWindow.document.open();
7559
- printWindow.document.write(htmlDocument);
7560
- printWindow.document.close();
7561
- printWindow.focus();
7562
- setTimeout(() => {
7563
- printWindow.print();
7564
- }, 300);
7565
- return true;
7479
+ var ViewerOptionsContext = createContext(DEFAULT_VIEWER_OPTIONS);
7480
+ function useViewerOptionsContext() {
7481
+ return useContext(ViewerOptionsContext);
7566
7482
  }
7483
+
7484
+ // src/viewer/hooks/usePrintHandlers.ts
7567
7485
  function usePrintHandlers(input) {
7568
7486
  const { slides, activeSlideIndex, canvasStageRef, setActiveSlideIndex, pptxData } = input;
7569
7487
  const [isPrintDialogOpen, setIsPrintDialogOpen] = useState(false);
7488
+ const { t } = useTranslation();
7489
+ const viewerOptions = useViewerOptionsContext();
7490
+ const includeHiddenSlides = viewerOptions.advanced.printHiddenSlides;
7491
+ const printRasterScale = (viewerOptions.advanced.printHighQuality ? 4 : 3) * resolveImageResolutionScale(viewerOptions);
7570
7492
  const handlePrint = () => {
7571
7493
  setIsPrintDialogOpen(true);
7572
7494
  };
7573
7495
  const handlePrintSvg = async (settings) => {
7574
7496
  setIsPrintDialogOpen(false);
7497
+ const printWindow = openPendingPrintWindow(t("pptx.print.preparingToPrint"));
7498
+ if (!printWindow) {
7499
+ console.warn(
7500
+ "[PowerPointViewer] Print window was blocked by the browser. Allow popups for this site to print."
7501
+ );
7502
+ return;
7503
+ }
7575
7504
  if (!pptxData || settings.printWhat !== "slides") {
7576
- return handlePrintWithSettings(settings);
7505
+ return runRasterPrint(printWindow, settings);
7577
7506
  }
7578
7507
  const colorFilter = computeColorFilter(settings.colorMode);
7579
- const slideIndices = computeSlideIndices(
7580
- settings.slideRange,
7581
- activeSlideIndex,
7582
- slides.length,
7583
- settings.customRangeFrom,
7584
- settings.customRangeTo
7508
+ const slideIndices = filterHiddenSlideIndices(
7509
+ computeSlideIndices(
7510
+ settings.slideRange,
7511
+ activeSlideIndex,
7512
+ slides.length,
7513
+ settings.customRangeFrom,
7514
+ settings.customRangeTo
7515
+ ),
7516
+ slides,
7517
+ includeHiddenSlides
7585
7518
  );
7586
7519
  try {
7587
7520
  const svgs = exportAllSlidesToSvg(pptxData, {
7588
7521
  slideIndices
7589
7522
  });
7590
7523
  if (svgs.length === 0) {
7524
+ printWindow.close();
7591
7525
  return;
7592
7526
  }
7593
7527
  const printDoc = buildPrintDocument(svgs, pptxData.width, pptxData.height, {
7594
7528
  title: "Slides (Vector)",
7595
7529
  orientation: settings.orientation,
7596
- colorFilter
7530
+ colorFilter,
7531
+ scaleToFit: settings.scaleToFit
7597
7532
  });
7598
- openPrintWindowWithDocument(printDoc);
7533
+ finishPrintWindow(printWindow, printDoc);
7599
7534
  } catch (err) {
7600
7535
  console.warn("[PowerPointViewer] SVG print path failed, falling back to raster:", err);
7601
- return handlePrintWithSettings(settings);
7536
+ return runRasterPrint(printWindow, settings);
7602
7537
  }
7603
7538
  };
7604
- const handlePrintWithSettings = async (settings) => {
7605
- setIsPrintDialogOpen(false);
7539
+ const runRasterPrint = async (printWindow, settings) => {
7606
7540
  const colorFilter = computeColorFilter(settings.colorMode);
7607
- const slideIndices = computeSlideIndices(
7608
- settings.slideRange,
7609
- activeSlideIndex,
7610
- slides.length,
7611
- settings.customRangeFrom,
7612
- settings.customRangeTo
7541
+ const slideIndices = filterHiddenSlideIndices(
7542
+ computeSlideIndices(
7543
+ settings.slideRange,
7544
+ activeSlideIndex,
7545
+ slides.length,
7546
+ settings.customRangeFrom,
7547
+ settings.customRangeTo
7548
+ ),
7549
+ slides,
7550
+ includeHiddenSlides
7613
7551
  );
7614
7552
  if (settings.printWhat === "outline") {
7615
- openPrintWindow(
7616
- "Outline",
7617
- `<div class="outline-page">${buildOutlineHtml(slideIndices, slides)}</div>`,
7618
- settings.orientation,
7619
- colorFilter,
7620
- settings.frameSlides
7553
+ finishPrintWindow(
7554
+ printWindow,
7555
+ buildPrintHtmlDocument({
7556
+ title: "Outline",
7557
+ bodyHtml: `<div class="outline-page">${buildOutlineHtml(slideIndices, slides)}</div>`,
7558
+ orientation: settings.orientation,
7559
+ colorFilter,
7560
+ frameSlides: settings.frameSlides,
7561
+ scaleToFit: settings.scaleToFit
7562
+ })
7621
7563
  );
7622
7564
  return;
7623
7565
  }
7624
7566
  try {
7625
7567
  if (!canvasStageRef.current) {
7568
+ printWindow.close();
7626
7569
  return;
7627
7570
  }
7628
7571
  const allImages = await captureAllSlidesAsPngDataUrls(
@@ -7630,46 +7573,70 @@ function usePrintHandlers(input) {
7630
7573
  slides.length,
7631
7574
  setActiveSlideIndex,
7632
7575
  activeSlideIndex,
7633
- { scale: 3 }
7576
+ { scale: printRasterScale }
7634
7577
  );
7635
7578
  if (allImages.length === 0) {
7579
+ printWindow.close();
7636
7580
  return;
7637
7581
  }
7638
7582
  const slideImages = slideIndices.map((idx) => allImages[idx]).filter(Boolean);
7639
7583
  if (settings.printWhat === "slides") {
7640
- openPrintWindow(
7641
- "Slides",
7642
- buildSlidesHtml(slideImages, slideIndices),
7643
- settings.orientation,
7644
- colorFilter,
7645
- settings.frameSlides
7584
+ finishPrintWindow(
7585
+ printWindow,
7586
+ buildPrintHtmlDocument({
7587
+ title: "Slides",
7588
+ bodyHtml: buildSlidesHtml(slideImages, slideIndices),
7589
+ orientation: settings.orientation,
7590
+ colorFilter,
7591
+ frameSlides: settings.frameSlides,
7592
+ scaleToFit: settings.scaleToFit
7593
+ })
7646
7594
  );
7647
7595
  return;
7648
7596
  }
7649
7597
  if (settings.printWhat === "notes") {
7650
- openPrintWindow(
7651
- "Notes Pages",
7652
- buildNotesHtml(slideImages, slideIndices, slides),
7653
- "portrait",
7654
- colorFilter,
7655
- settings.frameSlides
7598
+ finishPrintWindow(
7599
+ printWindow,
7600
+ buildPrintHtmlDocument({
7601
+ title: "Notes Pages",
7602
+ bodyHtml: buildNotesHtml(slideImages, slideIndices, slides),
7603
+ orientation: "portrait",
7604
+ colorFilter,
7605
+ frameSlides: settings.frameSlides,
7606
+ scaleToFit: settings.scaleToFit
7607
+ })
7656
7608
  );
7657
7609
  return;
7658
7610
  }
7659
7611
  if (settings.printWhat === "handouts") {
7660
7612
  const spp = settings.slidesPerPage;
7661
- openPrintWindow(
7662
- `Handout ${spp} per page`,
7663
- buildHandoutsHtml(slideImages, slideIndices, spp),
7664
- "portrait",
7665
- colorFilter,
7666
- settings.frameSlides
7613
+ finishPrintWindow(
7614
+ printWindow,
7615
+ buildPrintHtmlDocument({
7616
+ title: `Handout ${spp} per page`,
7617
+ bodyHtml: buildHandoutsHtml(slideImages, slideIndices, spp),
7618
+ orientation: "portrait",
7619
+ colorFilter,
7620
+ frameSlides: settings.frameSlides,
7621
+ scaleToFit: settings.scaleToFit
7622
+ })
7667
7623
  );
7668
7624
  }
7669
7625
  } catch (err) {
7670
7626
  console.error("[PowerPointViewer] Print layout failed:", err);
7671
7627
  }
7672
7628
  };
7629
+ const handlePrintWithSettings = async (settings) => {
7630
+ setIsPrintDialogOpen(false);
7631
+ const printWindow = openPendingPrintWindow(t("pptx.print.preparingToPrint"));
7632
+ if (!printWindow) {
7633
+ console.warn(
7634
+ "[PowerPointViewer] Print window was blocked by the browser. Allow popups for this site to print."
7635
+ );
7636
+ return;
7637
+ }
7638
+ return runRasterPrint(printWindow, settings);
7639
+ };
7673
7640
  return {
7674
7641
  handlePrint,
7675
7642
  handlePrintWithSettings,
@@ -8460,11 +8427,12 @@ function useAnnotationHandlers(input) {
8460
8427
  presentation.enterPresentMode();
8461
8428
  } else if (mode === "present" && annotations.hasAnyAnnotations) {
8462
8429
  stopAllPersistentAudio();
8463
- pendingModeAfterAnnotationsRef.current = nextMode;
8464
8430
  if (promptKeepInkAnnotations) {
8431
+ pendingModeAfterAnnotationsRef.current = nextMode;
8465
8432
  setShowKeepAnnotationsDialog(true);
8466
8433
  } else {
8467
- handleKeepAnnotations();
8434
+ annotations.clearAllAnnotations();
8435
+ setMode(nextMode);
8468
8436
  }
8469
8437
  } else {
8470
8438
  if (mode === "present") {
@@ -8473,14 +8441,7 @@ function useAnnotationHandlers(input) {
8473
8441
  setMode(nextMode);
8474
8442
  }
8475
8443
  },
8476
- [
8477
- presentation,
8478
- mode,
8479
- annotations.hasAnyAnnotations,
8480
- promptKeepInkAnnotations,
8481
- handleKeepAnnotations,
8482
- setMode
8483
- ]
8444
+ [presentation, mode, annotations, promptKeepInkAnnotations, setMode]
8484
8445
  );
8485
8446
  const handleDiscardAnnotations = useCallback(() => {
8486
8447
  annotations.clearAllAnnotations();
@@ -8678,8 +8639,7 @@ function usePresentationSetup(input) {
8678
8639
  onToggleSubtitles
8679
8640
  } = input;
8680
8641
  const actionSoundHandlerRef = useRef(null);
8681
- const [, setShowKeepAnnotationsDialog] = useState(false);
8682
- const pendingModeRef = useRef("edit");
8642
+ const exitModeHandlerRef = useRef(null);
8683
8643
  const annotations = usePresentationAnnotations({
8684
8644
  isActive: mode === "present",
8685
8645
  activeSlideIndex,
@@ -8696,16 +8656,19 @@ function usePresentationSetup(input) {
8696
8656
  if (mode === "present" && nextMode !== "present" && !mayLeaveSlideShow()) {
8697
8657
  return;
8698
8658
  }
8699
- if (mode === "present" && nextMode !== "present" && annotations.hasAnyAnnotations && promptKeepInkAnnotations) {
8700
- pendingModeRef.current = nextMode;
8701
- setShowKeepAnnotationsDialog(true);
8702
- } else {
8703
- if (mode === "present" && nextMode !== "present") {
8704
- stopAllPersistentAudio();
8705
- stopAnimationSound();
8659
+ if (mode === "present" && nextMode !== "present") {
8660
+ stopAllPersistentAudio();
8661
+ stopAnimationSound();
8662
+ const exitHandler = exitModeHandlerRef.current;
8663
+ if (exitHandler) {
8664
+ exitHandler(nextMode);
8665
+ return;
8666
+ }
8667
+ if (annotations.hasAnyAnnotations && !promptKeepInkAnnotations) {
8668
+ annotations.clearAllAnnotations();
8706
8669
  }
8707
- setMode(nextMode);
8708
8670
  }
8671
+ setMode(nextMode);
8709
8672
  },
8710
8673
  onSetActiveSlideIndex: setActiveSlideIndex,
8711
8674
  onPlayActionSound: (soundPath, options) => {
@@ -8764,7 +8727,14 @@ function usePresentationSetup(input) {
8764
8727
  useTimings: presentationProperties.advanceMode !== "manual",
8765
8728
  endWithBlackSlide
8766
8729
  });
8767
- return { presentation, annotations, actionSoundHandlerRef };
8730
+ return {
8731
+ presentation,
8732
+ annotations,
8733
+ actionSoundHandlerRef,
8734
+ setExitModeHandler: (handler) => {
8735
+ exitModeHandlerRef.current = handler;
8736
+ }
8737
+ };
8768
8738
  }
8769
8739
  function useEditorOperations(input) {
8770
8740
  const {
@@ -8928,7 +8898,8 @@ function useEditorOperations(input) {
8928
8898
  tableEditorState: state.tableEditorState,
8929
8899
  setTableEditorState: state.setTableEditorState,
8930
8900
  ops,
8931
- history
8901
+ history,
8902
+ transformCommittedText
8932
8903
  });
8933
8904
  const combinedUpdateTextStyle = useCallback(
8934
8905
  (updates) => {
@@ -9030,11 +9001,11 @@ function useIOHandlers(input) {
9030
9001
  ops,
9031
9002
  zoom,
9032
9003
  handlerRef,
9033
- serializeSlides,
9034
9004
  serializeForRecovery,
9035
9005
  setContent,
9036
9006
  onContentChange,
9037
- password
9007
+ password,
9008
+ imageExportScale
9038
9009
  } = input;
9039
9010
  const exportHandlers = useExportHandlers({
9040
9011
  slides,
@@ -9045,7 +9016,6 @@ function useIOHandlers(input) {
9045
9016
  canvasStageRef: zoom.canvasStageRef,
9046
9017
  setActiveSlideIndex: state.setActiveSlideIndex,
9047
9018
  handlerRef,
9048
- serializeSlides,
9049
9019
  headerFooter: state.headerFooter,
9050
9020
  presentationProperties: state.presentationProperties,
9051
9021
  customShows: state.customShows,
@@ -9062,7 +9032,8 @@ function useIOHandlers(input) {
9062
9032
  theme: state.theme,
9063
9033
  canvasSize,
9064
9034
  slideSizeEmu: state.slideSizeEmu,
9065
- password
9035
+ password,
9036
+ imageExportScale
9066
9037
  });
9067
9038
  const printHandlers = usePrintHandlers({
9068
9039
  slides,
@@ -9276,7 +9247,8 @@ function useContentLifecycle(input) {
9276
9247
  actionSoundHandlerRef,
9277
9248
  setIsEncryptedDialogOpen,
9278
9249
  password,
9279
- onContentApplied
9250
+ onContentApplied,
9251
+ allowExternalImages
9280
9252
  } = input;
9281
9253
  const { handlerRef } = useLoadContent({
9282
9254
  content,
@@ -9315,7 +9287,8 @@ function useContentLifecycle(input) {
9315
9287
  setError: state.setError,
9316
9288
  setIsDirty: state.setIsDirty,
9317
9289
  setIsEncrypted: setIsEncryptedDialogOpen,
9318
- onContentApplied
9290
+ onContentApplied,
9291
+ allowExternalImages
9319
9292
  });
9320
9293
  useEffect(() => {
9321
9294
  actionSoundHandlerRef.current = handlerRef.current;
@@ -9554,7 +9527,10 @@ function useViewerIntegration(input) {
9554
9527
  autosaveEnabled,
9555
9528
  autosaveAllowed = true,
9556
9529
  autosaveIntervalMs,
9530
+ allowExternalImages,
9557
9531
  canEdit,
9532
+ promptKeepInkAnnotations,
9533
+ imageExportScale,
9558
9534
  mode,
9559
9535
  slides,
9560
9536
  activeSlide,
@@ -9619,7 +9595,8 @@ function useViewerIntegration(input) {
9619
9595
  actionSoundHandlerRef,
9620
9596
  setIsEncryptedDialogOpen,
9621
9597
  password: dialogs.presentationPassword ?? void 0,
9622
- onContentApplied: () => setLoadVersion((v) => v + 1)
9598
+ onContentApplied: () => setLoadVersion((v) => v + 1),
9599
+ allowExternalImages
9623
9600
  }
9624
9601
  );
9625
9602
  const { exportHandlers, printHandlers, themeHandlers, propertyHandlers } = useIOHandlers({
@@ -9632,11 +9609,11 @@ function useViewerIntegration(input) {
9632
9609
  ops: editorOps.ops,
9633
9610
  zoom,
9634
9611
  handlerRef,
9635
- serializeSlides,
9636
9612
  serializeForRecovery,
9637
9613
  setContent,
9638
9614
  onContentChange,
9639
- password: dialogs.presentationPassword ?? void 0
9615
+ password: dialogs.presentationPassword ?? void 0,
9616
+ imageExportScale
9640
9617
  });
9641
9618
  const {
9642
9619
  showKeepAnnotationsDialog,
@@ -9651,7 +9628,8 @@ function useViewerIntegration(input) {
9651
9628
  annotations,
9652
9629
  history,
9653
9630
  setMode: state.setMode,
9654
- setSlides: state.setSlides
9631
+ setSlides: state.setSlides,
9632
+ promptKeepInkAnnotations
9655
9633
  });
9656
9634
  const recovery = useRecoveryDetection({
9657
9635
  filePath,
@@ -9930,13 +9908,19 @@ function useViewerOptions() {
9930
9908
  return { optionsStore: store, options };
9931
9909
  }
9932
9910
  var KNOWN_TAB_IDS = new Set(TOOLBAR_TABS.map((tab) => tab.id));
9933
- function computeToolbarVisibility(hiddenActions) {
9911
+ function computeToolbarVisibility(hiddenActions, hiddenTabIds = []) {
9934
9912
  const isHidden = (id) => isActionHidden(id, hiddenActions);
9935
- const isTabVisible = (id) => !KNOWN_TAB_IDS.has(id) || !isHidden(id);
9913
+ const userHidden = new Set(hiddenTabIds);
9914
+ userHidden.delete("file");
9915
+ const isTabVisible = (id) => !KNOWN_TAB_IDS.has(id) || !isHidden(id) && !userHidden.has(id);
9936
9916
  return { isHidden, isTabVisible };
9937
9917
  }
9938
9918
  function useToolbarVisibility(hiddenActions) {
9939
- return useMemo(() => computeToolbarVisibility(hiddenActions), [hiddenActions]);
9919
+ const hiddenTabIds = useViewerOptionsContext().ribbon.hiddenTabIds;
9920
+ return useMemo(
9921
+ () => computeToolbarVisibility(hiddenActions, hiddenTabIds),
9922
+ [hiddenActions, hiddenTabIds]
9923
+ );
9940
9924
  }
9941
9925
  function useCollaborativeHistory({
9942
9926
  localClientId: _localClientId,
@@ -10509,7 +10493,9 @@ function buildCanvasProps(input) {
10509
10493
  tableOps,
10510
10494
  presentation,
10511
10495
  findResults,
10512
- findResultIndex
10496
+ findResultIndex,
10497
+ viewerOptions,
10498
+ buildHyperlinkConfirmMessage
10513
10499
  } = input;
10514
10500
  const effectiveSlide = mode === "master" ? masterPseudoSlide : activeSlide;
10515
10501
  const effectiveTemplateElements = mode === "master" ? s.activeLayout ? s.activeMaster?.elements ?? [] : [] : templateElements;
@@ -10519,11 +10505,22 @@ function buildCanvasProps(input) {
10519
10505
  slide: activeSlide
10520
10506
  });
10521
10507
  const tableStyleContext = s.theme || s.tableStyleMap ? { theme: s.theme, tableStyleMap: s.tableStyleMap } : void 0;
10508
+ const openExternalUrl = (url) => {
10509
+ if (shouldConfirmExternalHyperlink(viewerOptions, url) && !window.confirm(buildHyperlinkConfirmMessage(url))) {
10510
+ return;
10511
+ }
10512
+ safeOpenUrl(url);
10513
+ };
10522
10514
  const handleActionClick = (_elementId, action) => {
10523
10515
  if (mode === "present") {
10516
+ const resolved = resolvePresentationAction(action, { slideCount: slides.length });
10517
+ if (resolved.intent.kind === "openUrl") {
10518
+ openExternalUrl(resolved.intent.url);
10519
+ return;
10520
+ }
10524
10521
  presentation.handlePresentationAction(action);
10525
10522
  } else if (action.url) {
10526
- safeOpenUrl(action.url);
10523
+ openExternalUrl(action.url);
10527
10524
  }
10528
10525
  };
10529
10526
  const handleHyperlinkClick = (url) => {
@@ -10539,7 +10536,7 @@ function buildCanvasProps(input) {
10539
10536
  }
10540
10537
  return;
10541
10538
  }
10542
- safeOpenUrl(url);
10539
+ openExternalUrl(url);
10543
10540
  };
10544
10541
  return {
10545
10542
  activeSlide: effectiveSlide,
@@ -10839,7 +10836,6 @@ function buildToolbarProps(input) {
10839
10836
  onExportVideo: exportHandlers.handleExportVideo,
10840
10837
  onExportGif: exportHandlers.handleExportGif,
10841
10838
  onExportJson: exportHandlers.handleExportJson,
10842
- onPackageForSharing: exportHandlers.handlePackageForSharing,
10843
10839
  onOpenFile,
10844
10840
  onOpenRecentFile,
10845
10841
  onCreatePresentation: (templateId) => {
@@ -10977,6 +10973,7 @@ function useViewerBuildingBlocksCore(input) {
10977
10973
  ]
10978
10974
  );
10979
10975
  const zoom = useZoomViewport({ canvasSize, selectedElements: state.selectedElements });
10976
+ const { options: viewerOptions } = useViewerOptions();
10980
10977
  const history = useEditorHistory({
10981
10978
  slides,
10982
10979
  canvasSize,
@@ -10986,6 +10983,7 @@ function useViewerBuildingBlocksCore(input) {
10986
10983
  headerFooter: state.headerFooter,
10987
10984
  loading,
10988
10985
  error,
10986
+ maxHistoryEntries: resolveHistoryDepth(viewerOptions),
10989
10987
  hasActivePointerInteraction,
10990
10988
  pointerCommitNonce: state.pointerCommitNonce,
10991
10989
  setSlides: state.setSlides,
@@ -11007,12 +11005,15 @@ function useViewerBuildingBlocksCore(input) {
11007
11005
  activeMaster: state.activeMaster,
11008
11006
  documentGridSpacing: state.viewProperties?.gridSpacing
11009
11007
  });
11010
- const { options: viewerOptions } = useViewerOptions();
11011
- const { presentation, annotations, actionSoundHandlerRef } = usePresentationSetup({
11008
+ const { presentation, annotations, actionSoundHandlerRef, setExitModeHandler } = usePresentationSetup({
11012
11009
  mode,
11013
11010
  slides,
11014
11011
  visibleSlideIndexes,
11015
11012
  endWithBlackSlide: viewerOptions.advanced.slideShowEndWithBlackSlide,
11013
+ // File > Options > Advanced > "Prompt to keep ink annotations when
11014
+ // exiting" / "Show popup toolbar" while presenting.
11015
+ promptKeepInkAnnotations: viewerOptions.advanced.slideShowPromptKeepInkAnnotations,
11016
+ popupToolbarEnabled: viewerOptions.advanced.slideShowShowPopupToolbar,
11016
11017
  activeSlideIndex,
11017
11018
  containerRef,
11018
11019
  content,
@@ -11042,8 +11043,13 @@ function useViewerBuildingBlocksCore(input) {
11042
11043
  presentation,
11043
11044
  annotations,
11044
11045
  actionSoundHandlerRef,
11046
+ setExitModeHandler,
11045
11047
  masterPseudoSlide,
11046
- gridSpacingPx
11048
+ gridSpacingPx,
11049
+ // Multiplied against the pre-existing 2x baseline; see the matching
11050
+ // comment in `PowerPointViewer.tsx`.
11051
+ imageExportScale: 2 * resolveImageResolutionScale(viewerOptions),
11052
+ viewerOptions
11047
11053
  };
11048
11054
  }
11049
11055
  function useViewerBuildingBlocksState(input) {
@@ -11071,7 +11077,10 @@ function useViewerBuildingBlocksState(input) {
11071
11077
  presentation,
11072
11078
  annotations,
11073
11079
  actionSoundHandlerRef,
11074
- gridSpacingPx
11080
+ gridSpacingPx,
11081
+ imageExportScale,
11082
+ setExitModeHandler,
11083
+ viewerOptions
11075
11084
  } = core;
11076
11085
  const dialogs = useViewerDialogs({
11077
11086
  mode,
@@ -11142,7 +11151,13 @@ function useViewerBuildingBlocksState(input) {
11142
11151
  content,
11143
11152
  filePath,
11144
11153
  autosaveEnabled,
11154
+ // Trust Center > "Allow external content": same gate `PowerPointViewer`
11155
+ // applies, so the headless building-blocks API loads http(s) images
11156
+ // under the same default-off, core-side SSRF/privacy guard.
11157
+ allowExternalImages: viewerOptions.trust.allowExternalContent,
11145
11158
  canEdit,
11159
+ promptKeepInkAnnotations: viewerOptions.advanced.slideShowPromptKeepInkAnnotations,
11160
+ imageExportScale,
11146
11161
  mode,
11147
11162
  slides,
11148
11163
  activeSlide,
@@ -11160,6 +11175,7 @@ function useViewerBuildingBlocksState(input) {
11160
11175
  onSelectionChange,
11161
11176
  onSlideCountChange
11162
11177
  });
11178
+ setExitModeHandler(handleSetMode);
11163
11179
  return {
11164
11180
  dialogs,
11165
11181
  editorOps,
@@ -11195,6 +11211,7 @@ function useViewerBuildingBlocks(input) {
11195
11211
  onOpenHeaderFooter,
11196
11212
  onOpenShareDialog
11197
11213
  } = input;
11214
+ const { t } = useTranslation();
11198
11215
  const [content, setContent] = useState(incomingContent ?? null);
11199
11216
  useEffect(() => {
11200
11217
  setContent(incomingContent ?? null);
@@ -11229,7 +11246,8 @@ function useViewerBuildingBlocks(input) {
11229
11246
  history,
11230
11247
  presentation,
11231
11248
  masterPseudoSlide,
11232
- gridSpacingPx
11249
+ gridSpacingPx,
11250
+ viewerOptions
11233
11251
  } = core;
11234
11252
  const {
11235
11253
  dialogs,
@@ -11305,7 +11323,11 @@ function useViewerBuildingBlocks(input) {
11305
11323
  tableOps: editorOps.tableOps,
11306
11324
  presentation,
11307
11325
  findResults: editorOps.findReplace.findResults,
11308
- findResultIndex: editorOps.findReplace.findResultIndex
11326
+ findResultIndex: editorOps.findReplace.findResultIndex,
11327
+ viewerOptions,
11328
+ buildHyperlinkConfirmMessage: (url) => `${t("pptx.options.trust.confirmHyperlinks")}
11329
+
11330
+ ${url}`
11309
11331
  });
11310
11332
  return { toolbarProps, canvasProps, mode, loading, error, autosaveStatus };
11311
11333
  }
@@ -11379,4 +11401,4 @@ function useResizablePanels() {
11379
11401
  };
11380
11402
  }
11381
11403
 
11382
- export { ACTION_VERB_MAP, MIN_TOUCH_TARGET, computeToolbarVisibility, detectTargetType, isAudienceTab, parseAudienceNonce, parseEmailUrl, parseSlideFromUrl, renderToCanvas, scopeLayoutOptionsToActiveSlide, useAnimationPlayback, useAnnotationHandlers, useAudienceMode, useAutosave, useBroadcastFollower, useCanvasInteractions, useClipboardHandlers, useCollaborationLivePatch, useCollaborativeHistory, useCollaborativeState, useComments, useContentLifecycle, useDerivedElementState, useDerivedSlideState, useDialogCustomShows, useEditorHistory, useEditorOperations, useElementManipulation, useElementOperations, useExportHandlers, useExportSaveAs, useFindReplace, useFollowMode, useFontInjection, useGroupAlignLayerHandlers, useIOHandlers, useInsertElements, useIsMobile, useKeyboardInsets, useKeyboardShortcutWiring, useKeyboardShortcuts, useLayoutSwitching, useLoadContent, useMergeShapesHandler, useModalDismissDrag, usePointerHandlers, usePresenceTracking, usePresentationAnnotations, usePresentationKeyboard, usePresentationMode, usePresentationSetup, usePresenterWindow, usePrintHandlers, usePropertyHandlers, useRecoveryDetection, useReducedMotion, useRehearsalTimings, useResizablePanels, useSectionOperations, useSerialize, useSheetDismissDrag, useSlideManagement, useSlideNavigation, useSwipeNavigation, useTableOperations, useThemeHandlers, useThemeSwitching, useToolbarVisibility, useTouchGestures, useViewerBuildingBlocks, useViewerCoreState, useViewerDialogs, useViewerIntegration, useViewerOptions, useViewerState, useViewerUIState, useVirtualizedSlides, useYjsDocumentSync, useYjsProvider, useZoomNavigation, useZoomViewport };
11404
+ export { ACTION_VERB_MAP, MIN_TOUCH_TARGET, ViewerOptionsContext, computeToolbarVisibility, detectTargetType, isAudienceTab, parseAudienceNonce, parseEmailUrl, parseSlideFromUrl, renderToCanvas, scopeLayoutOptionsToActiveSlide, useAnimationPlayback, useAnnotationHandlers, useAudienceMode, useAutosave, useBroadcastFollower, useCanvasInteractions, useClipboardHandlers, useCollaborationLivePatch, useCollaborativeHistory, useCollaborativeState, useComments, useContentLifecycle, useDerivedElementState, useDerivedSlideState, useDialogCustomShows, useEditorHistory, useEditorOperations, useElementManipulation, useElementOperations, useExportHandlers, useExportSaveAs, useFindReplace, useFollowMode, useFontInjection, useGroupAlignLayerHandlers, useIOHandlers, useInsertElements, useIsMobile, useKeyboardInsets, useKeyboardShortcutWiring, useKeyboardShortcuts, useLayoutSwitching, useLoadContent, useMergeShapesHandler, useModalDismissDrag, usePointerHandlers, usePresenceTracking, usePresentationAnnotations, usePresentationKeyboard, usePresentationMode, usePresentationSetup, usePresenterWindow, usePrintHandlers, usePropertyHandlers, useRecoveryDetection, useReducedMotion, useRehearsalTimings, useResizablePanels, useSectionOperations, useSerialize, useSheetDismissDrag, useSlideManagement, useSlideNavigation, useSwipeNavigation, useTableOperations, useThemeHandlers, useThemeSwitching, useToolbarVisibility, useTouchGestures, useViewerBuildingBlocks, useViewerCoreState, useViewerDialogs, useViewerIntegration, useViewerOptions, useViewerOptionsContext, useViewerState, useViewerUIState, useVirtualizedSlides, useYjsDocumentSync, useYjsProvider, useZoomNavigation, useZoomViewport };