pptx-react-viewer 3.3.0 → 3.4.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 (164) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/{AiChatPanel-WNQCTQB5.js → AiChatPanel-3Q4STA5E.js} +25 -25
  3. package/dist/AiChatPanel-3Q4STA5E.js.br +0 -0
  4. package/dist/AiChatPanel-3Q4STA5E.js.gz +0 -0
  5. package/dist/{AiChatPanel-BNFDBP4S.mjs → AiChatPanel-NQZBZIRM.mjs} +4 -4
  6. package/dist/AiChatPanel-NQZBZIRM.mjs.br +0 -0
  7. package/dist/AiChatPanel-NQZBZIRM.mjs.gz +0 -0
  8. package/dist/{Area3DChartScene-SAQVRYOH.mjs → Area3DChartScene-7PARQDOZ.mjs} +1 -1
  9. package/dist/Area3DChartScene-7PARQDOZ.mjs.br +3 -0
  10. package/dist/Area3DChartScene-7PARQDOZ.mjs.gz +0 -0
  11. package/dist/{Area3DChartScene-FXBSLIGX.js → Area3DChartScene-THLG74CM.js} +2 -2
  12. package/dist/Area3DChartScene-THLG74CM.js.br +0 -0
  13. package/dist/Area3DChartScene-THLG74CM.js.gz +0 -0
  14. package/dist/{Bar3DChartScene-7HVUTP2E.js → Bar3DChartScene-OLZ2V56I.js} +2 -2
  15. package/dist/Bar3DChartScene-OLZ2V56I.js.br +2 -0
  16. package/dist/Bar3DChartScene-OLZ2V56I.js.gz +0 -0
  17. package/dist/{Bar3DChartScene-LUA6E2K6.mjs → Bar3DChartScene-QUU6RUXM.mjs} +1 -1
  18. package/dist/Bar3DChartScene-QUU6RUXM.mjs.br +0 -0
  19. package/dist/Bar3DChartScene-QUU6RUXM.mjs.gz +0 -0
  20. package/dist/{Line3DChartScene-OVPULUTF.js → Line3DChartScene-2VZS52IB.js} +2 -2
  21. package/dist/Line3DChartScene-2VZS52IB.js.br +0 -0
  22. package/dist/Line3DChartScene-2VZS52IB.js.gz +0 -0
  23. package/dist/{Line3DChartScene-IW4JGH57.mjs → Line3DChartScene-D77ORA4K.mjs} +1 -1
  24. package/dist/Line3DChartScene-D77ORA4K.mjs.br +3 -0
  25. package/dist/Line3DChartScene-D77ORA4K.mjs.gz +0 -0
  26. package/dist/{Model3DScene-5KP6BVCV.js → Model3DScene-3WCALTXO.js} +2 -2
  27. package/dist/Model3DScene-3WCALTXO.js.br +0 -0
  28. package/dist/Model3DScene-3WCALTXO.js.gz +0 -0
  29. package/dist/{Model3DScene-BERTZYCJ.mjs → Model3DScene-ZEGWNILH.mjs} +1 -1
  30. package/dist/Model3DScene-ZEGWNILH.mjs.br +0 -0
  31. package/dist/Model3DScene-ZEGWNILH.mjs.gz +0 -0
  32. package/dist/{PieChart3DScene-3R2ETTGA.js → PieChart3DScene-7C3ACGKN.js} +2 -2
  33. package/dist/PieChart3DScene-7C3ACGKN.js.br +0 -0
  34. package/dist/PieChart3DScene-7C3ACGKN.js.gz +0 -0
  35. package/dist/{PieChart3DScene-O6FFK5L7.mjs → PieChart3DScene-DGD4PZVV.mjs} +1 -1
  36. package/dist/PieChart3DScene-DGD4PZVV.mjs.br +0 -0
  37. package/dist/PieChart3DScene-DGD4PZVV.mjs.gz +0 -0
  38. package/dist/PowerPointViewer-Cl6jBPNw.d.ts.map +1 -1
  39. package/dist/{SurfaceChart3DScene-OCR26R5D.mjs → SurfaceChart3DScene-QGH3OLJV.mjs} +1 -1
  40. package/dist/SurfaceChart3DScene-QGH3OLJV.mjs.br +0 -0
  41. package/dist/SurfaceChart3DScene-QGH3OLJV.mjs.gz +0 -0
  42. package/dist/{SurfaceChart3DScene-TGFAOLHL.js → SurfaceChart3DScene-SJPQGGGE.js} +2 -2
  43. package/dist/SurfaceChart3DScene-SJPQGGGE.js.br +0 -0
  44. package/dist/SurfaceChart3DScene-SJPQGGGE.js.gz +0 -0
  45. package/dist/{chunk-QKSYKQEL.js → chunk-7E6SM42A.js} +2513 -1626
  46. package/dist/chunk-7E6SM42A.js.br +0 -0
  47. package/dist/chunk-7E6SM42A.js.gz +0 -0
  48. package/dist/{chunk-DM2IZCSD.mjs → chunk-B7WAGQW4.mjs} +2955 -835
  49. package/dist/chunk-B7WAGQW4.mjs.br +0 -0
  50. package/dist/chunk-B7WAGQW4.mjs.gz +0 -0
  51. package/dist/{chunk-2FTJAMFA.mjs → chunk-C4WTQIC6.mjs} +13 -5
  52. package/dist/chunk-C4WTQIC6.mjs.br +0 -0
  53. package/dist/chunk-C4WTQIC6.mjs.gz +0 -0
  54. package/dist/{chunk-FSQCEAMG.js → chunk-KY6JQJXK.js} +17 -9
  55. package/dist/chunk-KY6JQJXK.js.br +0 -0
  56. package/dist/chunk-KY6JQJXK.js.gz +0 -0
  57. package/dist/{chunk-3B5FRKYU.mjs → chunk-L5MRKDRM.mjs} +1397 -510
  58. package/dist/chunk-L5MRKDRM.mjs.br +0 -0
  59. package/dist/chunk-L5MRKDRM.mjs.gz +0 -0
  60. package/dist/{chunk-QEEU4S4Z.mjs → chunk-MSUUPLQ7.mjs} +671 -114
  61. package/dist/chunk-MSUUPLQ7.mjs.br +0 -0
  62. package/dist/chunk-MSUUPLQ7.mjs.gz +0 -0
  63. package/dist/{chunk-K6R2JNCK.js → chunk-PCW2KT7Z.js} +2987 -834
  64. package/dist/chunk-PCW2KT7Z.js.br +0 -0
  65. package/dist/chunk-PCW2KT7Z.js.gz +0 -0
  66. package/dist/{chunk-ITN5NYYM.mjs → chunk-SFMATKNJ.mjs} +6 -19
  67. package/dist/chunk-SFMATKNJ.mjs.br +0 -0
  68. package/dist/chunk-SFMATKNJ.mjs.gz +0 -0
  69. package/dist/{chunk-GR6SJJIT.js → chunk-TJNG5VEK.js} +1080 -518
  70. package/dist/chunk-TJNG5VEK.js.br +0 -0
  71. package/dist/chunk-TJNG5VEK.js.gz +0 -0
  72. package/dist/{chunk-3P7FYHJH.js → chunk-UNIJUD5C.js} +44 -1
  73. package/dist/chunk-UNIJUD5C.js.br +0 -0
  74. package/dist/{chunk-3P7FYHJH.js.gz → chunk-UNIJUD5C.js.gz} +0 -0
  75. package/dist/{chunk-44CQ67GQ.js → chunk-XBTHWXNO.js} +172 -185
  76. package/dist/chunk-XBTHWXNO.js.br +0 -0
  77. package/dist/chunk-XBTHWXNO.js.gz +0 -0
  78. package/dist/{chunk-AMRT3AE4.mjs → chunk-XWUMM2TX.mjs} +44 -1
  79. package/dist/chunk-XWUMM2TX.mjs.br +0 -0
  80. package/dist/{chunk-AMRT3AE4.mjs.gz → chunk-XWUMM2TX.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 +7 -0
  88. package/dist/index.js +47 -47
  89. package/dist/index.js.br +0 -0
  90. package/dist/index.js.gz +0 -0
  91. package/dist/index.mjs +6 -6
  92. package/dist/index.mjs.br +0 -0
  93. package/dist/index.mjs.gz +0 -0
  94. package/dist/internals.d.ts +176 -5
  95. package/dist/internals.d.ts.map +1 -1
  96. package/dist/internals.js +79 -79
  97. package/dist/internals.js.br +0 -0
  98. package/dist/internals.js.gz +0 -0
  99. package/dist/internals.mjs +4 -4
  100. package/dist/internals.mjs.br +0 -0
  101. package/dist/internals.mjs.gz +0 -0
  102. package/dist/pptx-viewer.css +1 -1
  103. package/dist/pptx-viewer.css.br +0 -0
  104. package/dist/pptx-viewer.css.gz +0 -0
  105. package/dist/{useViewerBuildingBlocks-X1L8BjsQ.d.ts → useViewerBuildingBlocks-f6oNGKMX.d.ts} +8 -1
  106. package/dist/useViewerBuildingBlocks-f6oNGKMX.d.ts.map +1 -0
  107. package/dist/viewer/index.js +27 -27
  108. package/dist/viewer/index.js.br +0 -0
  109. package/dist/viewer/index.js.gz +0 -0
  110. package/dist/viewer/index.mjs +6 -6
  111. package/dist/viewer/index.mjs.br +0 -0
  112. package/dist/viewer/index.mjs.gz +0 -0
  113. package/package.json +1 -1
  114. package/dist/AiChatPanel-BNFDBP4S.mjs.br +0 -0
  115. package/dist/AiChatPanel-BNFDBP4S.mjs.gz +0 -0
  116. package/dist/AiChatPanel-WNQCTQB5.js.br +0 -0
  117. package/dist/AiChatPanel-WNQCTQB5.js.gz +0 -0
  118. package/dist/Area3DChartScene-FXBSLIGX.js.br +0 -0
  119. package/dist/Area3DChartScene-FXBSLIGX.js.gz +0 -0
  120. package/dist/Area3DChartScene-SAQVRYOH.mjs.br +0 -0
  121. package/dist/Area3DChartScene-SAQVRYOH.mjs.gz +0 -0
  122. package/dist/Bar3DChartScene-7HVUTP2E.js.br +0 -0
  123. package/dist/Bar3DChartScene-7HVUTP2E.js.gz +0 -0
  124. package/dist/Bar3DChartScene-LUA6E2K6.mjs.br +0 -3
  125. package/dist/Bar3DChartScene-LUA6E2K6.mjs.gz +0 -0
  126. package/dist/Line3DChartScene-IW4JGH57.mjs.br +0 -0
  127. package/dist/Line3DChartScene-IW4JGH57.mjs.gz +0 -0
  128. package/dist/Line3DChartScene-OVPULUTF.js.br +0 -0
  129. package/dist/Line3DChartScene-OVPULUTF.js.gz +0 -0
  130. package/dist/Model3DScene-5KP6BVCV.js.br +0 -0
  131. package/dist/Model3DScene-5KP6BVCV.js.gz +0 -0
  132. package/dist/Model3DScene-BERTZYCJ.mjs.br +0 -0
  133. package/dist/Model3DScene-BERTZYCJ.mjs.gz +0 -0
  134. package/dist/PieChart3DScene-3R2ETTGA.js.br +0 -0
  135. package/dist/PieChart3DScene-3R2ETTGA.js.gz +0 -0
  136. package/dist/PieChart3DScene-O6FFK5L7.mjs.br +0 -0
  137. package/dist/PieChart3DScene-O6FFK5L7.mjs.gz +0 -0
  138. package/dist/SurfaceChart3DScene-OCR26R5D.mjs.br +0 -0
  139. package/dist/SurfaceChart3DScene-OCR26R5D.mjs.gz +0 -0
  140. package/dist/SurfaceChart3DScene-TGFAOLHL.js.br +0 -0
  141. package/dist/SurfaceChart3DScene-TGFAOLHL.js.gz +0 -0
  142. package/dist/chunk-2FTJAMFA.mjs.br +0 -0
  143. package/dist/chunk-2FTJAMFA.mjs.gz +0 -0
  144. package/dist/chunk-3B5FRKYU.mjs.br +0 -0
  145. package/dist/chunk-3B5FRKYU.mjs.gz +0 -0
  146. package/dist/chunk-3P7FYHJH.js.br +0 -0
  147. package/dist/chunk-44CQ67GQ.js.br +0 -0
  148. package/dist/chunk-44CQ67GQ.js.gz +0 -0
  149. package/dist/chunk-AMRT3AE4.mjs.br +0 -0
  150. package/dist/chunk-DM2IZCSD.mjs.br +0 -0
  151. package/dist/chunk-DM2IZCSD.mjs.gz +0 -0
  152. package/dist/chunk-FSQCEAMG.js.br +0 -0
  153. package/dist/chunk-FSQCEAMG.js.gz +0 -0
  154. package/dist/chunk-GR6SJJIT.js.br +0 -0
  155. package/dist/chunk-GR6SJJIT.js.gz +0 -0
  156. package/dist/chunk-ITN5NYYM.mjs.br +0 -0
  157. package/dist/chunk-ITN5NYYM.mjs.gz +0 -0
  158. package/dist/chunk-K6R2JNCK.js.br +0 -0
  159. package/dist/chunk-K6R2JNCK.js.gz +0 -0
  160. package/dist/chunk-QEEU4S4Z.mjs.br +0 -0
  161. package/dist/chunk-QEEU4S4Z.mjs.gz +0 -0
  162. package/dist/chunk-QKSYKQEL.js.br +0 -0
  163. package/dist/chunk-QKSYKQEL.js.gz +0 -0
  164. package/dist/useViewerBuildingBlocks-X1L8BjsQ.d.ts.map +0 -1
@@ -1,6 +1,6 @@
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, buildPdfFromImageData, buildNotesPdf, GRID_SIZE, DEFAULT_TEXT_FONT_SIZE } from './chunk-ITN5NYYM.mjs';
2
- 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, cancelBuildReveal, PresentationAnimationController, scheduleAutoAdvanceChain, playGroup, 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, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, partitionTemplateElements, resolveAuthoredCustomShowId, buildInitialGuides, EncryptedFileError, resolveAutosaveIntervalMs, shouldWriteAutosaveSnapshot, saveAutosaveSnapshot, autosaveSnapshotMark, updateMasterViewElement, isTemplateElementId, updateElement, 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, collectReferencedFontFamilies, resolveGoogleWebfontHref, 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, lockResizeAspect, snapBoxToGrid, applyMotionPathPreset } from './chunk-DM2IZCSD.mjs';
3
- import { translationsEn } from './chunk-AMRT3AE4.mjs';
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, buildPdfFromImageData, buildNotesPdf, GRID_SIZE, DEFAULT_TEXT_FONT_SIZE } from './chunk-SFMATKNJ.mjs';
2
+ 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, cancelBuildReveal, PresentationAnimationController, scheduleAutoAdvanceChain, playGroup, 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, firstShowSlideIndex, attachPresentationVisibilityPause, presentationEntrySlideIndex, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, createCollaborationLivePatcher, publishLiveInlineText, PptxHandler, collectMediaElements, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, partitionTemplateElements, seedRecentColors, resolveAuthoredCustomShowId, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, EncryptedFileError, resolveAutosaveIntervalMs, shouldWriteAutosaveSnapshot, saveAutosaveSnapshot, autosaveSnapshotMark, updateMasterViewElement, isTemplateElementId, updateElement, 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, resolveAuthoredSlideRange, mayLeaveSlideShow, stopAllPersistentAudio, remapTextToSegments, guidePxToEmu, buildSaveSlides, embeddedFontSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, shouldProbeAutosaveRecovery, probeAutosaveRecovery, acceptAutosaveRecovery, discardAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, copyFormatFromElement, applyFormatToElement, collectReferencedFontFamilies, resolveGoogleWebfontHref, mapSlideShowStartKey, mapEditorKey, isEditorTextInputTarget, createViewerOptionsStore, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, LOCAL_SYNC_ORIGIN, observeYDocSlides, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, isKeyboardOpen, scopeLayoutOptionsToSlide, viewerPreferencesFromViewProperties, DEFAULT_VIEWER_PREFERENCES, viewPropertiesPatchFromPreferences, 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, mapPresentationWheel, openPendingPrintWindow, computeColorFilter, filterHiddenSlideIndices, computeSlideIndices, buildPrintDocument, finishPrintWindow, buildPrintHtmlDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, buildThemeColorMap, reResolveSlideColors, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, runPresentationAction, safeOpenUrl, toggleStageElementMedia, resolveOleVerbTarget, openUrlInNewTab, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, 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, replyToCommentInList, 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, applyResize, lockResizeAspect, snapBoxToGrid, applyMotionPathPreset } from './chunk-B7WAGQW4.mjs';
3
+ import { translationsEn } from './chunk-XWUMM2TX.mjs';
4
4
  import { createContext, useRef, useState, useEffect, useCallback, useMemo, useLayoutEffect, useContext, useImperativeHandle, useSyncExternalStore } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
@@ -1833,7 +1833,7 @@ function useRehearsalTimings(input) {
1833
1833
  function handlePresentationActionImpl(action, deps) {
1834
1834
  runPresentationAction(
1835
1835
  action,
1836
- { slideCount: deps.slidesLength },
1836
+ { slideCount: deps.slidesLength, ...deps.elementId ? { elementId: deps.elementId } : {} },
1837
1837
  {
1838
1838
  goToSlide: (slideIndex) => {
1839
1839
  deps.navigateToSlide(slideIndex);
@@ -1844,7 +1844,13 @@ function handlePresentationActionImpl(action, deps) {
1844
1844
  endShow: () => {
1845
1845
  deps.onSetMode("edit");
1846
1846
  },
1847
- playSound: deps.onPlayActionSound ? (soundPath) => deps.onPlayActionSound?.(soundPath) : void 0
1847
+ playSound: deps.onPlayActionSound ? (soundPath) => deps.onPlayActionSound?.(soundPath) : void 0,
1848
+ lastViewed: deps.onLastViewed,
1849
+ customShow: deps.onCustomShow,
1850
+ openFile: deps.onOpenFile,
1851
+ openPresentation: deps.onOpenPresentation,
1852
+ playMedia: deps.onPlayMedia,
1853
+ oleVerb: deps.onOleVerb
1848
1854
  }
1849
1855
  );
1850
1856
  }
@@ -1852,7 +1858,7 @@ function handlePresentationActionImpl(action, deps) {
1852
1858
  // src/viewer/hooks/presentation-mode/slide-transition.ts
1853
1859
  function executeSlideTransition(nextSlideIndex, deps) {
1854
1860
  const incomingSlide = deps.slides[nextSlideIndex];
1855
- const transition = incomingSlide?.transition;
1861
+ const transition = deps.reverse ? deps.slides[deps.currentSlideIndex]?.transition : incomingSlide?.transition;
1856
1862
  const durationMs = deps.playTransition ? resolveTransitionDurationMs(transition) : 0;
1857
1863
  deps.clearPresentationTimers();
1858
1864
  deps.setPresentationSlideIndex(nextSlideIndex);
@@ -1906,7 +1912,13 @@ function useSlideNavigation(input) {
1906
1912
  presentationTimersRef,
1907
1913
  rehearsing,
1908
1914
  recordCurrentSlideTime,
1909
- setShowRehearsalSummary
1915
+ setShowRehearsalSummary,
1916
+ onLastViewed,
1917
+ onCustomShow,
1918
+ onOpenFile,
1919
+ onOpenPresentation,
1920
+ onPlayMedia,
1921
+ onOleVerb
1910
1922
  } = input;
1911
1923
  const movePresentationSlideRef = useRef(() => {
1912
1924
  });
@@ -1975,8 +1987,11 @@ function useSlideNavigation(input) {
1975
1987
  scheduleAutoAdvanceForSlide: rehearsing ? void 0 : scheduleAutoAdvanceForSlide,
1976
1988
  presentationTimersRef,
1977
1989
  setTransitionOverlay,
1978
- // PowerPoint plays a slide's transition only when advancing into it.
1979
- playTransition: direction === 1,
1990
+ // PowerPoint plays a slide's transition only when advancing into it,
1991
+ // and replays the LEAVING slide's transition in reverse when stepping
1992
+ // back (a morph glides its shapes back to where they came from).
1993
+ playTransition: true,
1994
+ reverse: direction === -1,
1980
1995
  // Stepping back onto a slide shows it with its builds already played.
1981
1996
  seedCompleted: direction === -1
1982
1997
  });
@@ -2052,16 +2067,35 @@ function useSlideNavigation(input) {
2052
2067
  ]
2053
2068
  );
2054
2069
  const handlePresentationAction = useCallback(
2055
- (action) => {
2070
+ (action, elementId) => {
2056
2071
  handlePresentationActionImpl(action, {
2072
+ elementId,
2057
2073
  movePresentationSlide,
2058
2074
  navigateToSlide,
2059
2075
  onPlayActionSound,
2060
2076
  onSetMode,
2061
- slidesLength: slides.length
2077
+ slidesLength: slides.length,
2078
+ onLastViewed,
2079
+ onCustomShow,
2080
+ onOpenFile,
2081
+ onOpenPresentation,
2082
+ onPlayMedia,
2083
+ onOleVerb
2062
2084
  });
2063
2085
  },
2064
- [movePresentationSlide, navigateToSlide, onPlayActionSound, onSetMode, slides.length]
2086
+ [
2087
+ movePresentationSlide,
2088
+ navigateToSlide,
2089
+ onPlayActionSound,
2090
+ onSetMode,
2091
+ slides.length,
2092
+ onLastViewed,
2093
+ onCustomShow,
2094
+ onOpenFile,
2095
+ onOpenPresentation,
2096
+ onPlayMedia,
2097
+ onOleVerb
2098
+ ]
2065
2099
  );
2066
2100
  return {
2067
2101
  movePresentationSlide,
@@ -2099,6 +2133,136 @@ function useZoomNavigation(input) {
2099
2133
  clearZoomReturn
2100
2134
  };
2101
2135
  }
2136
+ function createCustomShowRunner(deps) {
2137
+ let origin = null;
2138
+ return {
2139
+ runCustomShow(customShowId, returnAfter) {
2140
+ const target = deps.getCustomShows().find((show) => show.id === customShowId);
2141
+ if (!target) {
2142
+ return;
2143
+ }
2144
+ origin = returnAfter ? { showId: deps.getActiveCustomShowId(), slideIndex: deps.getPresentationSlideIndex() } : null;
2145
+ const first = firstShowSlideIndex(resolveShowSlideIndexes(deps.getSlides(), target));
2146
+ deps.setActiveCustomShowId(customShowId);
2147
+ if (first !== void 0) {
2148
+ deps.navigateToSlide(first);
2149
+ }
2150
+ },
2151
+ tryReturnFromCustomShow() {
2152
+ if (!origin) {
2153
+ return false;
2154
+ }
2155
+ const { showId, slideIndex } = origin;
2156
+ origin = null;
2157
+ deps.setActiveCustomShowId(showId);
2158
+ deps.navigateToSlide(slideIndex);
2159
+ return true;
2160
+ }
2161
+ };
2162
+ }
2163
+ function useCustomShowRunner(deps) {
2164
+ const depsRef = useRef(deps);
2165
+ depsRef.current = deps;
2166
+ const runnerRef = useRef(null);
2167
+ runnerRef.current ??= createCustomShowRunner({
2168
+ getSlides: () => depsRef.current.getSlides(),
2169
+ getCustomShows: () => depsRef.current.getCustomShows(),
2170
+ getActiveCustomShowId: () => depsRef.current.getActiveCustomShowId(),
2171
+ setActiveCustomShowId: (id) => depsRef.current.setActiveCustomShowId(id),
2172
+ navigateToSlide: (index) => depsRef.current.navigateToSlide(index),
2173
+ getPresentationSlideIndex: () => depsRef.current.getPresentationSlideIndex()
2174
+ });
2175
+ return runnerRef.current;
2176
+ }
2177
+
2178
+ // src/viewer/hooks/presentation-mode/usePresentationActionExtensions.ts
2179
+ function usePresentationActionExtensions(input) {
2180
+ const {
2181
+ slides,
2182
+ customShows,
2183
+ activeCustomShowId,
2184
+ onSetActiveCustomShowId,
2185
+ presentationSlideIndex,
2186
+ containerRef,
2187
+ endWithBlackSlide,
2188
+ onSetMode,
2189
+ setEndOfShowVisible
2190
+ } = input;
2191
+ const navigateToSlideRef = useRef(null);
2192
+ const navigateToSlideViaRef = useCallback((index) => {
2193
+ navigateToSlideRef.current?.(index);
2194
+ }, []);
2195
+ const customShowRunner = useCustomShowRunner({
2196
+ getSlides: () => slides,
2197
+ getCustomShows: () => customShows,
2198
+ getActiveCustomShowId: () => activeCustomShowId,
2199
+ setActiveCustomShowId: (id) => onSetActiveCustomShowId?.(id),
2200
+ navigateToSlide: navigateToSlideViaRef,
2201
+ getPresentationSlideIndex: () => presentationSlideIndex
2202
+ });
2203
+ const previousSlideRef = useRef(presentationSlideIndex);
2204
+ const lastViewedSlideRef = useRef(null);
2205
+ useEffect(() => {
2206
+ lastViewedSlideRef.current = previousSlideRef.current;
2207
+ previousSlideRef.current = presentationSlideIndex;
2208
+ }, [presentationSlideIndex]);
2209
+ const onCustomShow = useCallback(
2210
+ (customShowId, returnAfter) => {
2211
+ customShowRunner.runCustomShow(customShowId, returnAfter);
2212
+ },
2213
+ [customShowRunner]
2214
+ );
2215
+ const onLastViewed = useCallback(() => {
2216
+ const previous = lastViewedSlideRef.current;
2217
+ if (previous !== null) {
2218
+ navigateToSlideViaRef(previous);
2219
+ }
2220
+ }, [navigateToSlideViaRef]);
2221
+ const onOpenFile = useCallback((target) => {
2222
+ safeOpenUrl(target);
2223
+ }, []);
2224
+ const onOpenPresentation = useCallback((target) => {
2225
+ safeOpenUrl(target);
2226
+ }, []);
2227
+ const onPlayMedia = useCallback(
2228
+ (elementId) => {
2229
+ toggleStageElementMedia(containerRef.current, elementId);
2230
+ },
2231
+ [containerRef]
2232
+ );
2233
+ const onOleVerb = useCallback(
2234
+ (verb, elementId) => {
2235
+ const target = resolveOleVerbTarget(slides[presentationSlideIndex], elementId, verb);
2236
+ if (target) {
2237
+ openUrlInNewTab(target.url);
2238
+ }
2239
+ },
2240
+ [slides, presentationSlideIndex]
2241
+ );
2242
+ const handleAdvancePastLastSlide = useCallback(() => {
2243
+ if (customShowRunner.tryReturnFromCustomShow()) {
2244
+ return;
2245
+ }
2246
+ if (endWithBlackSlide) {
2247
+ setEndOfShowVisible(true);
2248
+ } else {
2249
+ onSetMode("edit");
2250
+ }
2251
+ }, [customShowRunner, endWithBlackSlide, onSetMode, setEndOfShowVisible]);
2252
+ const bindNavigateToSlide = useCallback((navigateToSlide) => {
2253
+ navigateToSlideRef.current = navigateToSlide;
2254
+ }, []);
2255
+ return {
2256
+ onLastViewed,
2257
+ onCustomShow,
2258
+ onOpenFile,
2259
+ onOpenPresentation,
2260
+ onPlayMedia,
2261
+ onOleVerb,
2262
+ handleAdvancePastLastSlide,
2263
+ bindNavigateToSlide
2264
+ };
2265
+ }
2102
2266
  function usePresenterConsole(slideIndex, active) {
2103
2267
  const timerRef = useRef(createPresenterTimer());
2104
2268
  const [snapshot, setSnapshot] = useState(() => createInitialPresentationSnapshot(slideIndex));
@@ -2155,6 +2319,7 @@ function usePresentationMode(input) {
2155
2319
  const {
2156
2320
  mode,
2157
2321
  slides,
2322
+ templateElementsBySlideId,
2158
2323
  visibleSlideIndexes,
2159
2324
  activeSlideIndex,
2160
2325
  containerRef,
@@ -2171,7 +2336,10 @@ function usePresentationMode(input) {
2171
2336
  loopContinuously,
2172
2337
  showWithAnimation,
2173
2338
  useTimings,
2174
- endWithBlackSlide = true
2339
+ endWithBlackSlide = true,
2340
+ customShows = [],
2341
+ activeCustomShowId = null,
2342
+ onSetActiveCustomShowId
2175
2343
  } = input;
2176
2344
  const [presentationSlideIndex, setPresentationSlideIndex] = useState(0);
2177
2345
  const [presentationSlideVisible, setPresentationSlideVisible] = useState(true);
@@ -2226,13 +2394,17 @@ function usePresentationMode(input) {
2226
2394
  setPresenterMode(false);
2227
2395
  }
2228
2396
  }, [mode]);
2229
- const handleAdvancePastLastSlide = useCallback(() => {
2230
- if (endWithBlackSlide) {
2231
- setEndOfShowVisible(true);
2232
- } else {
2233
- onSetMode("edit");
2234
- }
2235
- }, [endWithBlackSlide, onSetMode]);
2397
+ const actionExtensions = usePresentationActionExtensions({
2398
+ slides,
2399
+ customShows,
2400
+ activeCustomShowId,
2401
+ onSetActiveCustomShowId,
2402
+ presentationSlideIndex,
2403
+ containerRef,
2404
+ endWithBlackSlide,
2405
+ onSetMode,
2406
+ setEndOfShowVisible
2407
+ });
2236
2408
  const {
2237
2409
  movePresentationSlide: moveNavigationSlide,
2238
2410
  navigateToSlide,
@@ -2250,7 +2422,7 @@ function usePresentationMode(input) {
2250
2422
  onPlayActionSound,
2251
2423
  loopContinuously,
2252
2424
  useTimings,
2253
- onAdvancePastLastSlide: handleAdvancePastLastSlide,
2425
+ onAdvancePastLastSlide: actionExtensions.handleAdvancePastLastSlide,
2254
2426
  playNextAnimationGroup,
2255
2427
  clearPresentationTimers,
2256
2428
  seedSlideAnimations,
@@ -2258,8 +2430,15 @@ function usePresentationMode(input) {
2258
2430
  presentationTimersRef,
2259
2431
  rehearsing,
2260
2432
  recordCurrentSlideTime,
2261
- setShowRehearsalSummary
2433
+ setShowRehearsalSummary,
2434
+ onLastViewed: actionExtensions.onLastViewed,
2435
+ onCustomShow: actionExtensions.onCustomShow,
2436
+ onOpenFile: actionExtensions.onOpenFile,
2437
+ onOpenPresentation: actionExtensions.onOpenPresentation,
2438
+ onPlayMedia: actionExtensions.onPlayMedia,
2439
+ onOleVerb: actionExtensions.onOleVerb
2262
2440
  });
2441
+ actionExtensions.bindNavigateToSlide(navigateToSlide);
2263
2442
  const movePresentationSlide = useCallback(
2264
2443
  (direction, trigger = "explicit") => {
2265
2444
  if (!acceptsPresentationInput()) {
@@ -2330,6 +2509,13 @@ function usePresentationMode(input) {
2330
2509
  }
2331
2510
  onSetMode("present");
2332
2511
  }, [containerRef, onSetMode, setRehearsing]);
2512
+ const enterPresentModeFromBeginning = useCallback(() => {
2513
+ const first = firstShowSlideIndex(visibleSlideIndexes);
2514
+ if (first !== void 0) {
2515
+ onSetActiveSlideIndex(first);
2516
+ }
2517
+ enterPresentMode();
2518
+ }, [visibleSlideIndexes, onSetActiveSlideIndex, enterPresentMode]);
2333
2519
  const enterPresenterView = useCallback(() => {
2334
2520
  setPresenterMode(true);
2335
2521
  setRehearsing(false);
@@ -2392,6 +2578,10 @@ function usePresentationMode(input) {
2392
2578
  scheduleAutoAdvanceRef.current = scheduleAutoAdvanceForSlide;
2393
2579
  const activeSlideIndexRef = useRef(activeSlideIndex);
2394
2580
  activeSlideIndexRef.current = activeSlideIndex;
2581
+ const visibleSlideIndexesRef = useRef(visibleSlideIndexes);
2582
+ visibleSlideIndexesRef.current = visibleSlideIndexes;
2583
+ const onSetActiveSlideIndexRef = useRef(onSetActiveSlideIndex);
2584
+ onSetActiveSlideIndexRef.current = onSetActiveSlideIndex;
2395
2585
  const presentationSlideIndexRef = useRef(presentationSlideIndex);
2396
2586
  presentationSlideIndexRef.current = presentationSlideIndex;
2397
2587
  const clearPresentationTimersRef = useRef(clearPresentationTimers);
@@ -2408,8 +2598,14 @@ function usePresentationMode(input) {
2408
2598
  }, [mode, containerRef]);
2409
2599
  useLayoutEffect(() => {
2410
2600
  if (mode === "present") {
2411
- const idx = activeSlideIndexRef.current;
2601
+ const idx = presentationEntrySlideIndex(
2602
+ activeSlideIndexRef.current,
2603
+ visibleSlideIndexesRef.current
2604
+ );
2412
2605
  setPresentationSlideIndex(idx);
2606
+ if (idx !== activeSlideIndexRef.current) {
2607
+ onSetActiveSlideIndexRef.current(idx);
2608
+ }
2413
2609
  runEntranceAnimationsRef.current(idx);
2414
2610
  scheduleAutoAdvanceRef.current(idx);
2415
2611
  } else {
@@ -2480,13 +2676,18 @@ function usePresentationMode(input) {
2480
2676
  if (!transitionOverlay || transitionOverlay.transition.type !== "morph") {
2481
2677
  return void 0;
2482
2678
  }
2679
+ const incoming = slides[transitionOverlay.incomingSlideIndex];
2483
2680
  return buildMorphTransitionPlan(
2484
2681
  slides[transitionOverlay.outgoingSlideIndex],
2485
- slides[transitionOverlay.incomingSlideIndex],
2682
+ incoming,
2486
2683
  transitionOverlay.durationMs,
2487
- morphOptionToMode(transitionOverlay.transition.morphOption)
2684
+ morphOptionToMode(transitionOverlay.transition.morphOption),
2685
+ // `PresentationStage` stacks the incoming slide's elements above its
2686
+ // template shapes (`zIndex = templateElements.length + index`), so a
2687
+ // z-index journey has to start counting where the stage does.
2688
+ { zIndexBase: incoming ? templateElementsBySlideId?.[incoming.id]?.length ?? 0 : 0 }
2488
2689
  );
2489
- }, [transitionOverlay, slides]);
2690
+ }, [transitionOverlay, slides, templateElementsBySlideId]);
2490
2691
  const morphedElementStates = useMemo(() => {
2491
2692
  if (!morphPlan || morphPlan.incomingAnimations.size === 0) {
2492
2693
  return presentationElementStates;
@@ -2535,6 +2736,7 @@ ${imageRules}`;
2535
2736
  handleHoverStart,
2536
2737
  handleHoverEnd,
2537
2738
  enterPresentMode,
2739
+ enterPresentModeFromBeginning,
2538
2740
  presenterMode,
2539
2741
  enterPresenterView,
2540
2742
  togglePresenterView,
@@ -2926,6 +3128,38 @@ function useModalDismissDrag(onClose, threshold = 120) {
2926
3128
  handlers: { onPointerDown, onPointerMove, onPointerUp, onPointerCancel: onPointerUp }
2927
3129
  };
2928
3130
  }
3131
+ function withoutKey(map, key) {
3132
+ if (!(key in map)) {
3133
+ return map;
3134
+ }
3135
+ const next = { ...map };
3136
+ delete next[key];
3137
+ return next;
3138
+ }
3139
+ function useCommentMentionDrafts() {
3140
+ const [commentDraftMentionsBySlideId, setCommentDraftMentionsBySlideId] = useState({});
3141
+ const [replyDraftMentionsByCommentId, setReplyDraftMentionsByCommentId] = useState({});
3142
+ const setCommentDraftMentions = useCallback((slideId, mentions) => {
3143
+ setCommentDraftMentionsBySlideId((prev) => ({ ...prev, [slideId]: mentions }));
3144
+ }, []);
3145
+ const setReplyDraftMentions = useCallback((commentId, mentions) => {
3146
+ setReplyDraftMentionsByCommentId((prev) => ({ ...prev, [commentId]: mentions }));
3147
+ }, []);
3148
+ const clearCommentDraftMentions = useCallback((slideId) => {
3149
+ setCommentDraftMentionsBySlideId((prev) => withoutKey(prev, slideId));
3150
+ }, []);
3151
+ const clearReplyDraftMentions = useCallback((commentId) => {
3152
+ setReplyDraftMentionsByCommentId((prev) => withoutKey(prev, commentId));
3153
+ }, []);
3154
+ return {
3155
+ commentDraftMentionsBySlideId,
3156
+ replyDraftMentionsByCommentId,
3157
+ setCommentDraftMentions,
3158
+ setReplyDraftMentions,
3159
+ clearCommentDraftMentions,
3160
+ clearReplyDraftMentions
3161
+ };
3162
+ }
2929
3163
 
2930
3164
  // src/viewer/hooks/useComments-helpers.ts
2931
3165
  function replaceCommentsOnSlide(slides, slideIndex, next) {
@@ -2933,7 +3167,7 @@ function replaceCommentsOnSlide(slides, slideIndex, next) {
2933
3167
  (entry, index) => index === slideIndex ? { ...entry, comments: next } : entry
2934
3168
  );
2935
3169
  }
2936
- function addCommentToSlide(slides, slideIndex, text, authorName, elementId) {
3170
+ function addCommentToSlide(slides, slideIndex, text, authorName, elementId, mentions) {
2937
3171
  const slide = slides[slideIndex];
2938
3172
  if (!slide) {
2939
3173
  return { slides, didAdd: false };
@@ -2949,7 +3183,10 @@ function addCommentToSlide(slides, slideIndex, text, authorName, elementId) {
2949
3183
  if (!next) {
2950
3184
  return { slides, didAdd: false };
2951
3185
  }
2952
- return { slides: replaceCommentsOnSlide(slides, slideIndex, next), didAdd: true };
3186
+ const withMentions = mentions && mentions.length > 0 ? next.map(
3187
+ (comment, index) => index === next.length - 1 ? { ...comment, mentions } : comment
3188
+ ) : next;
3189
+ return { slides: replaceCommentsOnSlide(slides, slideIndex, withMentions), didAdd: true };
2953
3190
  }
2954
3191
  function removeCommentFromSlide(slides, slideIndex, commentId) {
2955
3192
  const slide = slides[slideIndex];
@@ -2984,7 +3221,7 @@ function toggleResolvedInSlide(slides, slideIndex, commentId) {
2984
3221
  }
2985
3222
  return { slides: replaceCommentsOnSlide(slides, slideIndex, next), didUpdate: true };
2986
3223
  }
2987
- function addReplyToSlide(slides, slideIndex, parentId, text, authorName) {
3224
+ function addReplyToSlide(slides, slideIndex, parentId, text, authorName, mentions) {
2988
3225
  const slide = slides[slideIndex];
2989
3226
  if (!slide) {
2990
3227
  return { slides, didAdd: false };
@@ -2993,7 +3230,15 @@ function addReplyToSlide(slides, slideIndex, parentId, text, authorName) {
2993
3230
  if (!next) {
2994
3231
  return { slides, didAdd: false };
2995
3232
  }
2996
- return { slides: replaceCommentsOnSlide(slides, slideIndex, next), didAdd: true };
3233
+ const withMentions = mentions && mentions.length > 0 ? next.map(
3234
+ (comment) => comment.id === parentId && comment.replies && comment.replies.length > 0 ? {
3235
+ ...comment,
3236
+ replies: comment.replies.map(
3237
+ (reply, index) => index === comment.replies.length - 1 ? { ...reply, mentions } : reply
3238
+ )
3239
+ } : comment
3240
+ ) : next;
3241
+ return { slides: replaceCommentsOnSlide(slides, slideIndex, withMentions), didAdd: true };
2997
3242
  }
2998
3243
  function pruneSlideDrafts(drafts, slideIds) {
2999
3244
  const next = {};
@@ -3008,6 +3253,95 @@ function pruneSlideDrafts(drafts, slideIds) {
3008
3253
  return changed ? next : null;
3009
3254
  }
3010
3255
 
3256
+ // src/viewer/hooks/useCommentReplyHandlers.ts
3257
+ function useCommentReplyHandlers(input) {
3258
+ const {
3259
+ slides,
3260
+ canEdit,
3261
+ userName,
3262
+ onUpdateSlides,
3263
+ onMarkDirty,
3264
+ replyDraftMentionsByCommentId,
3265
+ setReplyDraftMentions,
3266
+ clearReplyDraftMentions
3267
+ } = input;
3268
+ const [replyDraftByCommentId, setReplyDraftByCommentId] = useState({});
3269
+ const [replyingToCommentId, setReplyingToCommentId] = useState(null);
3270
+ const handleStartReply = useCallback((_slideIndex, commentId) => {
3271
+ setReplyingToCommentId(commentId);
3272
+ setReplyDraftByCommentId((prev) => ({ ...prev, [commentId]: "" }));
3273
+ }, []);
3274
+ const handleCancelReply = useCallback(() => {
3275
+ setReplyingToCommentId(null);
3276
+ }, []);
3277
+ const handleReplyDraftChange = useCallback(
3278
+ (commentId, draft, mentions) => {
3279
+ setReplyDraftByCommentId((prev) => ({ ...prev, [commentId]: draft }));
3280
+ if (mentions) {
3281
+ setReplyDraftMentions(commentId, mentions);
3282
+ }
3283
+ },
3284
+ [setReplyDraftMentions]
3285
+ );
3286
+ const handleSubmitReply = useCallback(
3287
+ (slideIndex, commentId) => {
3288
+ if (!canEdit) {
3289
+ return;
3290
+ }
3291
+ const slide = slides[slideIndex];
3292
+ if (!slide) {
3293
+ return;
3294
+ }
3295
+ const replyText = String(replyDraftByCommentId[commentId] || "").trim();
3296
+ if (replyText.length === 0) {
3297
+ return;
3298
+ }
3299
+ let didAdd = false;
3300
+ onUpdateSlides((prev) => {
3301
+ const result = addReplyToSlide(
3302
+ prev,
3303
+ slideIndex,
3304
+ commentId,
3305
+ replyText,
3306
+ userName,
3307
+ replyDraftMentionsByCommentId[commentId]
3308
+ );
3309
+ didAdd = result.didAdd;
3310
+ return result.slides;
3311
+ });
3312
+ if (!didAdd) {
3313
+ return;
3314
+ }
3315
+ setReplyingToCommentId(null);
3316
+ setReplyDraftByCommentId((prev) => {
3317
+ const next = { ...prev };
3318
+ delete next[commentId];
3319
+ return next;
3320
+ });
3321
+ clearReplyDraftMentions(commentId);
3322
+ onMarkDirty();
3323
+ },
3324
+ [
3325
+ canEdit,
3326
+ onMarkDirty,
3327
+ onUpdateSlides,
3328
+ replyDraftByCommentId,
3329
+ replyDraftMentionsByCommentId,
3330
+ clearReplyDraftMentions,
3331
+ slides,
3332
+ userName
3333
+ ]
3334
+ );
3335
+ return {
3336
+ replyingToCommentId,
3337
+ replyDraftByCommentId,
3338
+ handleStartReply,
3339
+ handleCancelReply,
3340
+ handleReplyDraftChange,
3341
+ handleSubmitReply
3342
+ };
3343
+ }
3344
+
3011
3345
  // src/viewer/hooks/useComments.ts
3012
3346
  function useComments({
3013
3347
  slides,
@@ -3020,11 +3354,33 @@ function useComments({
3020
3354
  const [commentDraftBySlideId, setCommentDraftBySlideId] = useState({});
3021
3355
  const [editingCommentIdBySlideId, setEditingCommentIdBySlideId] = useState({});
3022
3356
  const [commentEditDraftByCommentId, setCommentEditDraftByCommentId] = useState({});
3023
- const [replyDraftByCommentId, setReplyDraftByCommentId] = useState({});
3024
- const [replyingToCommentId, setReplyingToCommentId] = useState(null);
3025
- const handleCommentDraftChange = useCallback((slideId, draft) => {
3026
- setCommentDraftBySlideId((prev) => ({ ...prev, [slideId]: draft }));
3027
- }, []);
3357
+ const {
3358
+ commentDraftMentionsBySlideId,
3359
+ replyDraftMentionsByCommentId,
3360
+ setCommentDraftMentions,
3361
+ setReplyDraftMentions,
3362
+ clearCommentDraftMentions,
3363
+ clearReplyDraftMentions
3364
+ } = useCommentMentionDrafts();
3365
+ const reply = useCommentReplyHandlers({
3366
+ slides,
3367
+ canEdit,
3368
+ userName,
3369
+ onUpdateSlides,
3370
+ onMarkDirty,
3371
+ replyDraftMentionsByCommentId,
3372
+ setReplyDraftMentions,
3373
+ clearReplyDraftMentions
3374
+ });
3375
+ const handleCommentDraftChange = useCallback(
3376
+ (slideId, draft, mentions) => {
3377
+ setCommentDraftBySlideId((prev) => ({ ...prev, [slideId]: draft }));
3378
+ if (mentions) {
3379
+ setCommentDraftMentions(slideId, mentions);
3380
+ }
3381
+ },
3382
+ [setCommentDraftMentions]
3383
+ );
3028
3384
  const handleSetCommentEditDraft = useCallback((commentId, draft) => {
3029
3385
  setCommentEditDraftByCommentId((prev) => ({
3030
3386
  ...prev,
@@ -3051,7 +3407,8 @@ function useComments({
3051
3407
  slideIndex,
3052
3408
  draft,
3053
3409
  userName,
3054
- selectedElementId ?? void 0
3410
+ selectedElementId ?? void 0,
3411
+ commentDraftMentionsBySlideId[slide.id]
3055
3412
  );
3056
3413
  didAdd = result.didAdd;
3057
3414
  return result.slides;
@@ -3063,11 +3420,14 @@ function useComments({
3063
3420
  ...prev,
3064
3421
  [slide.id]: ""
3065
3422
  }));
3423
+ clearCommentDraftMentions(slide.id);
3066
3424
  onMarkDirty();
3067
3425
  },
3068
3426
  [
3069
3427
  canEdit,
3070
3428
  commentDraftBySlideId,
3429
+ commentDraftMentionsBySlideId,
3430
+ clearCommentDraftMentions,
3071
3431
  onMarkDirty,
3072
3432
  onUpdateSlides,
3073
3433
  selectedElementId,
@@ -3179,48 +3539,6 @@ function useComments({
3179
3539
  },
3180
3540
  [canEdit, onMarkDirty, onUpdateSlides, slides]
3181
3541
  );
3182
- const handleStartReply = useCallback((_slideIndex, commentId) => {
3183
- setReplyingToCommentId(commentId);
3184
- setReplyDraftByCommentId((prev) => ({ ...prev, [commentId]: "" }));
3185
- }, []);
3186
- const handleCancelReply = useCallback(() => {
3187
- setReplyingToCommentId(null);
3188
- }, []);
3189
- const handleReplyDraftChange = useCallback((commentId, draft) => {
3190
- setReplyDraftByCommentId((prev) => ({ ...prev, [commentId]: draft }));
3191
- }, []);
3192
- const handleSubmitReply = useCallback(
3193
- (slideIndex, commentId) => {
3194
- if (!canEdit) {
3195
- return;
3196
- }
3197
- const slide = slides[slideIndex];
3198
- if (!slide) {
3199
- return;
3200
- }
3201
- const replyText = String(replyDraftByCommentId[commentId] || "").trim();
3202
- if (replyText.length === 0) {
3203
- return;
3204
- }
3205
- let didAdd = false;
3206
- onUpdateSlides((prev) => {
3207
- const result = addReplyToSlide(prev, slideIndex, commentId, replyText, userName);
3208
- didAdd = result.didAdd;
3209
- return result.slides;
3210
- });
3211
- if (!didAdd) {
3212
- return;
3213
- }
3214
- setReplyingToCommentId(null);
3215
- setReplyDraftByCommentId((prev) => {
3216
- const next = { ...prev };
3217
- delete next[commentId];
3218
- return next;
3219
- });
3220
- onMarkDirty();
3221
- },
3222
- [canEdit, onMarkDirty, onUpdateSlides, replyDraftByCommentId, slides, userName]
3223
- );
3224
3542
  useEffect(() => {
3225
3543
  const slideIds = new Set(slides.map((slide) => slide.id));
3226
3544
  setCommentDraftBySlideId((prev) => {
@@ -3232,8 +3550,8 @@ function useComments({
3232
3550
  commentDraftBySlideId,
3233
3551
  editingCommentIdBySlideId,
3234
3552
  commentEditDraftByCommentId,
3235
- replyingToCommentId,
3236
- replyDraftByCommentId,
3553
+ commentDraftMentionsBySlideId,
3554
+ replyDraftMentionsByCommentId,
3237
3555
  handleCommentDraftChange,
3238
3556
  handleAddSlideComment,
3239
3557
  handleDeleteSlideComment,
@@ -3242,10 +3560,7 @@ function useComments({
3242
3560
  handleSaveCommentEdit,
3243
3561
  handleSetCommentEditDraft,
3244
3562
  handleToggleCommentResolved,
3245
- handleStartReply,
3246
- handleCancelReply,
3247
- handleReplyDraftChange,
3248
- handleSubmitReply
3563
+ ...reply
3249
3564
  };
3250
3565
  }
3251
3566
  function buildElementLookup(templateElements, slideElements) {
@@ -3410,6 +3725,8 @@ function useViewerCoreState(_input) {
3410
3725
  const [headerFooter, setHeaderFooter] = useState({});
3411
3726
  const [layoutOptions, setLayoutOptions] = useState([]);
3412
3727
  const [slideMasters, setSlideMasters] = useState([]);
3728
+ const [modernCommentAuthors, setModernCommentAuthors] = useState([]);
3729
+ const [recentColors, setRecentColors] = useState([]);
3413
3730
  const [theme, setTheme] = useState();
3414
3731
  const [tableStyleMap, setTableStyleMap] = useState();
3415
3732
  const [themeOptions, setThemeOptions] = useState([]);
@@ -3503,6 +3820,10 @@ function useViewerCoreState(_input) {
3503
3820
  setLayoutOptions,
3504
3821
  slideMasters,
3505
3822
  setSlideMasters,
3823
+ modernCommentAuthors,
3824
+ setModernCommentAuthors,
3825
+ recentColors,
3826
+ setRecentColors,
3506
3827
  theme,
3507
3828
  setTheme,
3508
3829
  tableStyleMap,
@@ -3687,6 +4008,8 @@ function useLoadContent({
3687
4008
  setHeaderFooter,
3688
4009
  setLayoutOptions,
3689
4010
  setSlideMasters,
4011
+ setModernCommentAuthors,
4012
+ setRecentColors,
3690
4013
  setTheme,
3691
4014
  setTableStyleMap,
3692
4015
  setThemeOptions,
@@ -3708,6 +4031,8 @@ function useLoadContent({
3708
4031
  setHasDigitalSignatures,
3709
4032
  setDigitalSignatureCount,
3710
4033
  setGuides,
4034
+ setReadOnlyRecommendation,
4035
+ setCompatToasts,
3711
4036
  setLoading,
3712
4037
  setError,
3713
4038
  setIsDirty,
@@ -3837,6 +4162,8 @@ function useLoadContent({
3837
4162
  setHeaderFooter(parsed.headerFooter ?? {});
3838
4163
  setLayoutOptions(parsed.layoutOptions ?? []);
3839
4164
  setSlideMasters(parsed.slideMasters ?? []);
4165
+ setModernCommentAuthors(parsed.modernCommentAuthors ?? []);
4166
+ setRecentColors(seedRecentColors({ mruColors: parsed.mruColors }));
3840
4167
  setTheme(parsed.theme);
3841
4168
  setTableStyleMap(nextTableStyleMap);
3842
4169
  setThemeOptions(parsed.themeOptions ?? []);
@@ -3866,6 +4193,13 @@ function useLoadContent({
3866
4193
  setHasDigitalSignatures(parsed.hasDigitalSignatures === true);
3867
4194
  setDigitalSignatureCount(parsed.digitalSignatureCount ?? 0);
3868
4195
  setGuides(buildInitialGuides(parsed.presentationGuides, parsed.slides[0]?.guides));
4196
+ setReadOnlyRecommendation(readOnlyRecommendation(parsed));
4197
+ setCompatToasts(
4198
+ compatibilityWarningToasts([
4199
+ ...parsed.warnings ?? [],
4200
+ ...parsed.slides.flatMap((slide) => slide.warnings ?? [])
4201
+ ])
4202
+ );
3869
4203
  setActiveSlideIndex(0);
3870
4204
  clearSelection();
3871
4205
  setIsDirty(false);
@@ -4282,6 +4616,42 @@ function useSectionOperations(input) {
4282
4616
  };
4283
4617
  }
4284
4618
 
4619
+ // src/viewer/utils/selection-handle-overlay.ts
4620
+ var VIEWPORT_SELECTOR = "[data-pptx-viewport]";
4621
+ function findSelectionHandleHost(elementNode, elementId) {
4622
+ const scope = elementNode.closest(VIEWPORT_SELECTOR) ?? elementNode.parentElement;
4623
+ if (!scope) {
4624
+ return null;
4625
+ }
4626
+ for (const candidate of scope.querySelectorAll("[data-pptx-handle-for]")) {
4627
+ if (candidate.getAttribute("data-pptx-handle-for") === elementId) {
4628
+ return candidate;
4629
+ }
4630
+ }
4631
+ return null;
4632
+ }
4633
+ function syncSelectionHandleOverlay(elementNode, elementId, geometry) {
4634
+ const host = findSelectionHandleHost(elementNode, elementId);
4635
+ if (!host) {
4636
+ return;
4637
+ }
4638
+ if (geometry.x !== void 0) {
4639
+ host.style.left = `${geometry.x}px`;
4640
+ }
4641
+ if (geometry.y !== void 0) {
4642
+ host.style.top = `${geometry.y}px`;
4643
+ }
4644
+ if (geometry.width !== void 0) {
4645
+ host.style.width = `${geometry.width}px`;
4646
+ }
4647
+ if (geometry.height !== void 0) {
4648
+ host.style.height = `${geometry.height}px`;
4649
+ }
4650
+ if (geometry.transform !== void 0) {
4651
+ host.style.transform = geometry.transform;
4652
+ }
4653
+ }
4654
+
4285
4655
  // src/viewer/hooks/pointer-move-handlers.ts
4286
4656
  function computeResizeGeometry(handle, startX, startY, startWidth, startHeight, dx, dy, snapToGrid, gridSpacingPx, lockAspect = false) {
4287
4657
  const startBox = { x: startX, y: startY, width: startWidth, height: startHeight };
@@ -4438,8 +4808,11 @@ function processDragMove(e, drag, editorScale, snapToGrid, snapToShape, gridSpac
4438
4808
  for (const [id, domEl] of drag.domEls) {
4439
4809
  const start = drag.startPositionsById[id];
4440
4810
  if (start) {
4441
- domEl.style.left = `${start.x + appliedDx}px`;
4442
- domEl.style.top = `${start.y + appliedDy}px`;
4811
+ const x = start.x + appliedDx;
4812
+ const y = start.y + appliedDy;
4813
+ domEl.style.left = `${x}px`;
4814
+ domEl.style.top = `${y}px`;
4815
+ syncSelectionHandleOverlay(domEl, id, { x, y });
4443
4816
  }
4444
4817
  }
4445
4818
  if (live) {
@@ -4477,18 +4850,21 @@ function processResizeMove(e, rs, editorScale, snapToGrid, gridSpacingPx, live)
4477
4850
  rs.lastY = geo.y;
4478
4851
  rs.lastWidth = geo.width;
4479
4852
  rs.lastHeight = geo.height;
4853
+ const width = Math.max(geo.width, MIN_ELEMENT_SIZE);
4854
+ const height = Math.max(geo.height, MIN_ELEMENT_SIZE);
4480
4855
  if (rs.domEl) {
4481
4856
  rs.domEl.style.left = `${geo.x}px`;
4482
4857
  rs.domEl.style.top = `${geo.y}px`;
4483
- rs.domEl.style.width = `${Math.max(geo.width, MIN_ELEMENT_SIZE)}px`;
4484
- rs.domEl.style.height = `${Math.max(geo.height, MIN_ELEMENT_SIZE)}px`;
4858
+ rs.domEl.style.width = `${width}px`;
4859
+ rs.domEl.style.height = `${height}px`;
4860
+ syncSelectionHandleOverlay(rs.domEl, rs.elementId, { x: geo.x, y: geo.y, width, height });
4485
4861
  }
4486
4862
  if (live) {
4487
4863
  publishLiveGeometry(live.patcher, live.slideId, rs.elementId, {
4488
4864
  x: geo.x,
4489
4865
  y: geo.y,
4490
- width: Math.max(geo.width, MIN_ELEMENT_SIZE),
4491
- height: Math.max(geo.height, MIN_ELEMENT_SIZE)
4866
+ width,
4867
+ height
4492
4868
  });
4493
4869
  }
4494
4870
  }
@@ -7447,7 +7823,7 @@ function usePrintHandlers(input) {
7447
7823
  printWindow,
7448
7824
  buildPrintHtmlDocument({
7449
7825
  title: `Handout ${spp} per page`,
7450
- bodyHtml: buildHandoutsHtml(slideImages, slideIndices, spp),
7826
+ bodyHtml: buildHandoutsHtml(slideImages, slideIndices, spp, pptxData?.handoutMaster),
7451
7827
  orientation: "portrait",
7452
7828
  colorFilter,
7453
7829
  frameSlides: settings.frameSlides,
@@ -8104,9 +8480,10 @@ function useViewerDialogs(input) {
8104
8480
  function computeGridSpacingPx2(documentGridSpacing) {
8105
8481
  return computeGridSpacingPx(documentGridSpacing, GRID_SIZE);
8106
8482
  }
8107
- function computeVisibleSlideIndexes(slides, activeCustomShowId, customShows) {
8483
+ function computeVisibleSlideIndexes(slides, activeCustomShowId, customShows, presentationProperties) {
8108
8484
  const activeShow = activeCustomShowId ? customShows.find((show) => show.id === activeCustomShowId) : void 0;
8109
- return resolveShowSlideIndexes(slides, activeShow);
8485
+ const authoredRange = resolveAuthoredSlideRange(presentationProperties, slides.length);
8486
+ return resolveShowSlideIndexes(slides, activeShow, authoredRange);
8110
8487
  }
8111
8488
  function computeSlideSectionGroups(slides, sections) {
8112
8489
  return groupSlidesBySection(sections, slides).map((group) => ({
@@ -8135,6 +8512,7 @@ function useDerivedSlideState(input) {
8135
8512
  sections,
8136
8513
  customShows,
8137
8514
  activeCustomShowId,
8515
+ presentationProperties,
8138
8516
  mode,
8139
8517
  activeLayout,
8140
8518
  activeMaster,
@@ -8145,8 +8523,12 @@ function useDerivedSlideState(input) {
8145
8523
  [documentGridSpacing]
8146
8524
  );
8147
8525
  const visibleSlideIndexes = useMemo(
8148
- () => computeVisibleSlideIndexes(slides, activeCustomShowId, customShows),
8149
- [slides, activeCustomShowId, customShows]
8526
+ () => computeVisibleSlideIndexes(slides, activeCustomShowId, customShows, presentationProperties),
8527
+ [slides, activeCustomShowId, customShows, presentationProperties]
8528
+ );
8529
+ const authoredRange = useMemo(
8530
+ () => resolveAuthoredSlideRange(presentationProperties, slides.length),
8531
+ [presentationProperties, slides.length]
8150
8532
  );
8151
8533
  const slideSectionGroups = useMemo(
8152
8534
  () => computeSlideSectionGroups(slides, sections).map((group) => {
@@ -8168,7 +8550,8 @@ function useDerivedSlideState(input) {
8168
8550
  gridSpacingPx,
8169
8551
  visibleSlideIndexes,
8170
8552
  slideSectionGroups,
8171
- masterPseudoSlide
8553
+ masterPseudoSlide,
8554
+ authoredRange
8172
8555
  };
8173
8556
  }
8174
8557
  function useAnnotationHandlers(input) {
@@ -8306,6 +8689,7 @@ function useSerialize(input) {
8306
8689
  guides,
8307
8690
  headerFooter,
8308
8691
  presentationProperties,
8692
+ viewProperties,
8309
8693
  customShows,
8310
8694
  sections,
8311
8695
  coreProperties,
@@ -8367,6 +8751,7 @@ function useSerialize(input) {
8367
8751
  slideSize: resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize }).size,
8368
8752
  headerFooter,
8369
8753
  presentationProperties,
8754
+ viewProperties,
8370
8755
  customShows: customShows.length > 0 ? customShows : void 0,
8371
8756
  sections: sections.length > 0 ? sections : void 0,
8372
8757
  coreProperties,
@@ -8386,6 +8771,7 @@ function useSerialize(input) {
8386
8771
  slideSizeEmu,
8387
8772
  headerFooter,
8388
8773
  presentationProperties,
8774
+ viewProperties,
8389
8775
  customShows,
8390
8776
  sections,
8391
8777
  coreProperties,
@@ -8456,6 +8842,7 @@ function usePresentationSetup(input) {
8456
8842
  const {
8457
8843
  mode,
8458
8844
  slides,
8845
+ templateElementsBySlideId,
8459
8846
  visibleSlideIndexes,
8460
8847
  activeSlideIndex,
8461
8848
  containerRef,
@@ -8469,7 +8856,10 @@ function usePresentationSetup(input) {
8469
8856
  endWithBlackSlide = true,
8470
8857
  promptKeepInkAnnotations = true,
8471
8858
  popupToolbarEnabled = true,
8472
- onToggleSubtitles
8859
+ onToggleSubtitles,
8860
+ customShows = [],
8861
+ activeCustomShowId = null,
8862
+ onSetActiveCustomShowId
8473
8863
  } = input;
8474
8864
  const actionSoundHandlerRef = useRef(null);
8475
8865
  const exitModeHandlerRef = useRef(null);
@@ -8481,6 +8871,7 @@ function usePresentationSetup(input) {
8481
8871
  const presentation = usePresentationMode({
8482
8872
  mode,
8483
8873
  slides,
8874
+ templateElementsBySlideId,
8484
8875
  visibleSlideIndexes,
8485
8876
  activeSlideIndex,
8486
8877
  containerRef,
@@ -8558,7 +8949,10 @@ function usePresentationSetup(input) {
8558
8949
  loopContinuously: shouldLoopContinuously(presentationProperties),
8559
8950
  showWithAnimation: presentationProperties.showWithAnimation,
8560
8951
  useTimings: presentationProperties.advanceMode !== "manual",
8561
- endWithBlackSlide
8952
+ endWithBlackSlide,
8953
+ customShows,
8954
+ activeCustomShowId,
8955
+ onSetActiveCustomShowId
8562
8956
  });
8563
8957
  return {
8564
8958
  presentation,
@@ -9042,7 +9436,9 @@ function useContentLifecycle(input) {
9042
9436
  setIsEncryptedDialogOpen,
9043
9437
  password,
9044
9438
  onContentApplied,
9045
- allowExternalImages
9439
+ allowExternalImages,
9440
+ setReadOnlyRecommendation,
9441
+ setCompatToasts
9046
9442
  } = input;
9047
9443
  const { handlerRef } = useLoadContent({
9048
9444
  content,
@@ -9056,6 +9452,8 @@ function useContentLifecycle(input) {
9056
9452
  setHeaderFooter: state.setHeaderFooter,
9057
9453
  setLayoutOptions: state.setLayoutOptions,
9058
9454
  setSlideMasters: state.setSlideMasters,
9455
+ setModernCommentAuthors: state.setModernCommentAuthors,
9456
+ setRecentColors: state.setRecentColors,
9059
9457
  setTheme: state.setTheme,
9060
9458
  setTableStyleMap: state.setTableStyleMap,
9061
9459
  setThemeOptions: state.setThemeOptions,
@@ -9077,6 +9475,8 @@ function useContentLifecycle(input) {
9077
9475
  setHasDigitalSignatures: state.setHasDigitalSignatures,
9078
9476
  setDigitalSignatureCount: state.setDigitalSignatureCount,
9079
9477
  setGuides: state.setGuides,
9478
+ setReadOnlyRecommendation,
9479
+ setCompatToasts,
9080
9480
  setLoading: state.setLoading,
9081
9481
  setError: state.setError,
9082
9482
  setIsDirty: state.setIsDirty,
@@ -9097,6 +9497,7 @@ function useContentLifecycle(input) {
9097
9497
  guides: state.guides,
9098
9498
  headerFooter: state.headerFooter,
9099
9499
  presentationProperties: state.presentationProperties,
9500
+ viewProperties: state.viewProperties,
9100
9501
  customShows: state.customShows,
9101
9502
  sections: state.sections,
9102
9503
  coreProperties: state.coreProperties,
@@ -9152,6 +9553,16 @@ function useKeyboardShortcuts(input) {
9152
9553
  inputRef.current = input;
9153
9554
  const handleKeyDown = useCallback((e) => {
9154
9555
  const current = inputRef.current;
9556
+ const startAction = mapSlideShowStartKey(e, { isPresenting: current.mode === "present" });
9557
+ if (startAction !== null) {
9558
+ e.preventDefault();
9559
+ if (startAction === "fromBeginning") {
9560
+ current.onStartShowFromBeginning();
9561
+ } else {
9562
+ current.onStartShowFromCurrent();
9563
+ }
9564
+ return;
9565
+ }
9155
9566
  const { action, dx, dy } = mapEditorKey(e, {
9156
9567
  canEdit: current.canEdit,
9157
9568
  // The Slide Master view is an editing surface, not a viewing one.
@@ -9232,7 +9643,18 @@ function useKeyboardShortcuts(input) {
9232
9643
 
9233
9644
  // src/viewer/hooks/useKeyboardShortcutWiring.ts
9234
9645
  function useKeyboardShortcutWiring(input) {
9235
- const { state, mode, canEdit, slides, activeSlide, ops, manipulation, history } = input;
9646
+ const {
9647
+ state,
9648
+ mode,
9649
+ canEdit,
9650
+ slides,
9651
+ activeSlide,
9652
+ ops,
9653
+ manipulation,
9654
+ history,
9655
+ onEnterPresentModeFromBeginning,
9656
+ onSetMode
9657
+ } = input;
9236
9658
  useKeyboardShortcuts({
9237
9659
  containerRef: state.containerRef,
9238
9660
  mode,
@@ -9302,7 +9724,9 @@ function useKeyboardShortcutWiring(input) {
9302
9724
  return;
9303
9725
  }
9304
9726
  state.setActiveSlideIndex((prev) => Math.min(slides.length - 1, prev + 1));
9305
- }
9727
+ },
9728
+ onStartShowFromBeginning: onEnterPresentModeFromBeginning,
9729
+ onStartShowFromCurrent: () => onSetMode("present")
9306
9730
  });
9307
9731
  }
9308
9732
  function useViewerIntegration(input) {
@@ -9322,6 +9746,8 @@ function useViewerIntegration(input) {
9322
9746
  autosaveAllowed = true,
9323
9747
  autosaveIntervalMs,
9324
9748
  allowExternalImages,
9749
+ setReadOnlyRecommendation,
9750
+ setCompatToasts,
9325
9751
  canEdit,
9326
9752
  promptKeepInkAnnotations,
9327
9753
  imageExportScale,
@@ -9390,7 +9816,9 @@ function useViewerIntegration(input) {
9390
9816
  setIsEncryptedDialogOpen,
9391
9817
  password: dialogs.presentationPassword ?? void 0,
9392
9818
  onContentApplied: () => setLoadVersion((v) => v + 1),
9393
- allowExternalImages
9819
+ allowExternalImages,
9820
+ setReadOnlyRecommendation,
9821
+ setCompatToasts
9394
9822
  }
9395
9823
  );
9396
9824
  const { exportHandlers, printHandlers, themeHandlers, propertyHandlers } = useIOHandlers({
@@ -9625,7 +10053,9 @@ function useViewerIntegration(input) {
9625
10053
  activeSlide,
9626
10054
  ops: editorOps.ops,
9627
10055
  manipulation: editorOps.manipulation,
9628
- history
10056
+ history,
10057
+ onEnterPresentModeFromBeginning: presentation.enterPresentModeFromBeginning,
10058
+ onSetMode: handleSetMode
9629
10059
  });
9630
10060
  return {
9631
10061
  exportHandlers,
@@ -10305,14 +10735,14 @@ function buildCanvasProps(input) {
10305
10735
  }
10306
10736
  safeOpenUrl(url);
10307
10737
  };
10308
- const handleActionClick = (_elementId, action) => {
10738
+ const handleActionClick = (elementId, action) => {
10309
10739
  if (mode === "present") {
10310
10740
  const resolved = resolvePresentationAction(action, { slideCount: slides.length });
10311
10741
  if (resolved.intent.kind === "openUrl") {
10312
10742
  openExternalUrl(resolved.intent.url);
10313
10743
  return;
10314
10744
  }
10315
- presentation.handlePresentationAction(action);
10745
+ presentation.handlePresentationAction(action, elementId);
10316
10746
  } else if (action.url) {
10317
10747
  openExternalUrl(action.url);
10318
10748
  }
@@ -10521,7 +10951,8 @@ function buildToolbarProps(input) {
10521
10951
  onOpenFile,
10522
10952
  onOpenRecentFile,
10523
10953
  fileName,
10524
- hiddenActions
10954
+ hiddenActions,
10955
+ viewPreferencesSync
10525
10956
  } = input;
10526
10957
  const {
10527
10958
  handleAddAnimation,
@@ -10605,9 +11036,9 @@ function buildToolbarProps(input) {
10605
11036
  onSetSpellCheckEnabled: s.setSpellCheckEnabled,
10606
11037
  onSetShowGrid: s.setShowGrid,
10607
11038
  onSetShowRulers: s.setShowRulers,
10608
- onSetShowGuides: s.setShowGuides,
10609
- onSetSnapToGrid: s.setSnapToGrid,
10610
- onSetSnapToShape: s.setSnapToShape,
11039
+ onSetShowGuides: viewPreferencesSync?.handleSetShowGuides ?? s.setShowGuides,
11040
+ onSetSnapToGrid: viewPreferencesSync?.handleSetSnapToGrid ?? s.setSnapToGrid,
11041
+ onSetSnapToShape: viewPreferencesSync?.handleSetSnapToShape ?? s.setSnapToShape,
10611
11042
  onAddGuide: dialogs.handleAddGuide,
10612
11043
  onAlignElements: manipulation.handleAlignElements,
10613
11044
  onDistributeElements: manipulation.handleDistributeElements,
@@ -10794,6 +11225,7 @@ function useViewerBuildingBlocksCore(input) {
10794
11225
  sections: state.sections,
10795
11226
  customShows: state.customShows,
10796
11227
  activeCustomShowId: state.activeCustomShowId,
11228
+ presentationProperties: state.presentationProperties,
10797
11229
  mode,
10798
11230
  activeLayout: state.activeLayout,
10799
11231
  activeMaster: state.activeMaster,
@@ -10802,6 +11234,7 @@ function useViewerBuildingBlocksCore(input) {
10802
11234
  const { presentation, annotations, actionSoundHandlerRef, setExitModeHandler } = usePresentationSetup({
10803
11235
  mode,
10804
11236
  slides,
11237
+ templateElementsBySlideId,
10805
11238
  visibleSlideIndexes,
10806
11239
  endWithBlackSlide: viewerOptions.advanced.slideShowEndWithBlackSlide,
10807
11240
  // File > Options > Advanced > "Prompt to keep ink annotations when
@@ -10846,6 +11279,111 @@ function useViewerBuildingBlocksCore(input) {
10846
11279
  viewerOptions
10847
11280
  };
10848
11281
  }
11282
+ function useCompatibilityToastsState() {
11283
+ const [toasts, setToasts] = useState([]);
11284
+ const dismiss = useCallback((id) => {
11285
+ setToasts((prev) => prev.filter((toast) => toast.id !== id));
11286
+ }, []);
11287
+ const dismissAll = useCallback(() => {
11288
+ setToasts([]);
11289
+ }, []);
11290
+ return { toasts, setToasts, dismiss, dismissAll };
11291
+ }
11292
+ function useReadOnlyRecommendationState(content) {
11293
+ const [recommendation, setRecommendation] = useState(
11294
+ () => readOnlyRecommendation(void 0)
11295
+ );
11296
+ const [bannerHidden, setBannerHidden] = useState(false);
11297
+ const [editAnywayActive, setEditAnywayActive] = useState(false);
11298
+ useEffect(() => {
11299
+ setBannerHidden(false);
11300
+ setEditAnywayActive(false);
11301
+ }, [content]);
11302
+ const editAnyway = useCallback(() => {
11303
+ setEditAnywayActive(true);
11304
+ setBannerHidden(true);
11305
+ }, []);
11306
+ const dismiss = useCallback(() => {
11307
+ setBannerHidden(true);
11308
+ }, []);
11309
+ return {
11310
+ recommendation,
11311
+ setRecommendation,
11312
+ /** Whether the viewer's `canEdit` should be forced off. */
11313
+ locked: recommendation.defaultReadOnly && !editAnywayActive,
11314
+ bannerVisible: recommendation.kind !== null && !bannerHidden,
11315
+ editAnyway,
11316
+ dismiss
11317
+ };
11318
+ }
11319
+ function useViewPreferencesSync(input) {
11320
+ const {
11321
+ loadVersion,
11322
+ viewProperties,
11323
+ setViewProperties,
11324
+ snapToGrid,
11325
+ setSnapToGrid,
11326
+ snapToShape,
11327
+ setSnapToShape,
11328
+ showGuides,
11329
+ setShowGuides
11330
+ } = input;
11331
+ useEffect(() => {
11332
+ const seeded = viewerPreferencesFromViewProperties(
11333
+ { viewProperties },
11334
+ { ...DEFAULT_VIEWER_PREFERENCES, snapToGrid, snapToObjects: snapToShape, showGuides }
11335
+ );
11336
+ setSnapToGrid(seeded.snapToGrid);
11337
+ setSnapToShape(seeded.snapToObjects ?? snapToShape);
11338
+ setShowGuides(seeded.showGuides ?? showGuides);
11339
+ }, [loadVersion]);
11340
+ const patchViewProperties = useCallback(
11341
+ (prefsOverride) => {
11342
+ setViewProperties((prev) => {
11343
+ const merged = {
11344
+ ...DEFAULT_VIEWER_PREFERENCES,
11345
+ snapToGrid,
11346
+ snapToObjects: snapToShape,
11347
+ showGuides,
11348
+ gridSpacingCx: prev?.gridSpacing?.cx,
11349
+ gridSpacingCy: prev?.gridSpacing?.cy,
11350
+ ...prefsOverride
11351
+ };
11352
+ const patch = viewPropertiesPatchFromPreferences(merged);
11353
+ return {
11354
+ ...prev,
11355
+ slideViewPr: { ...prev?.slideViewPr, ...patch.slideViewPr },
11356
+ ...patch.gridSpacing ? { gridSpacing: patch.gridSpacing } : {}
11357
+ };
11358
+ });
11359
+ },
11360
+ [setViewProperties, snapToGrid, snapToShape, showGuides]
11361
+ );
11362
+ const handleSetSnapToGrid = useCallback(
11363
+ (value) => {
11364
+ setSnapToGrid(value);
11365
+ patchViewProperties({ snapToGrid: value });
11366
+ },
11367
+ [setSnapToGrid, patchViewProperties]
11368
+ );
11369
+ const handleSetSnapToShape = useCallback(
11370
+ (value) => {
11371
+ setSnapToShape(value);
11372
+ patchViewProperties({ snapToObjects: value });
11373
+ },
11374
+ [setSnapToShape, patchViewProperties]
11375
+ );
11376
+ const handleSetShowGuides = useCallback(
11377
+ (value) => {
11378
+ setShowGuides(value);
11379
+ patchViewProperties({ showGuides: value });
11380
+ },
11381
+ [setShowGuides, patchViewProperties]
11382
+ );
11383
+ return { handleSetSnapToGrid, handleSetSnapToShape, handleSetShowGuides };
11384
+ }
11385
+
11386
+ // src/viewer/hooks/useViewerBuildingBlocksState.ts
10849
11387
  function useViewerBuildingBlocksState(input) {
10850
11388
  const { core, content, canEdit, filePath, autosaveEnabled, userName, handle, setContent } = input;
10851
11389
  const {
@@ -10901,6 +11439,8 @@ function useViewerBuildingBlocksState(input) {
10901
11439
  isDirty: state.isDirty,
10902
11440
  history
10903
11441
  });
11442
+ const readOnlyRec = useReadOnlyRecommendationState(content);
11443
+ const compatToastsState = useCompatibilityToastsState();
10904
11444
  useEffect(() => {
10905
11445
  state.setSelectedElementId(null);
10906
11446
  state.setSelectedElementIds([]);
@@ -10931,7 +11471,8 @@ function useViewerBuildingBlocksState(input) {
10931
11471
  handleSetMode,
10932
11472
  handleEnterPresenterView,
10933
11473
  handleEnterRehearsalMode,
10934
- autosaveStatus
11474
+ autosaveStatus,
11475
+ loadVersion
10935
11476
  } = useViewerIntegration({
10936
11477
  state,
10937
11478
  zoom,
@@ -10949,6 +11490,8 @@ function useViewerBuildingBlocksState(input) {
10949
11490
  // applies, so the headless building-blocks API loads http(s) images
10950
11491
  // under the same default-off, core-side SSRF/privacy guard.
10951
11492
  allowExternalImages: viewerOptions.trust.allowExternalContent,
11493
+ setReadOnlyRecommendation: readOnlyRec.setRecommendation,
11494
+ setCompatToasts: compatToastsState.setToasts,
10952
11495
  canEdit,
10953
11496
  promptKeepInkAnnotations: viewerOptions.advanced.slideShowPromptKeepInkAnnotations,
10954
11497
  imageExportScale,
@@ -10970,6 +11513,17 @@ function useViewerBuildingBlocksState(input) {
10970
11513
  onSlideCountChange
10971
11514
  });
10972
11515
  setExitModeHandler(handleSetMode);
11516
+ const viewPreferencesSync = useViewPreferencesSync({
11517
+ loadVersion,
11518
+ viewProperties: state.viewProperties,
11519
+ setViewProperties: state.setViewProperties,
11520
+ snapToGrid: state.snapToGrid,
11521
+ setSnapToGrid: state.setSnapToGrid,
11522
+ snapToShape: state.snapToShape,
11523
+ setSnapToShape: state.setSnapToShape,
11524
+ showGuides: state.showGuides,
11525
+ setShowGuides: state.setShowGuides
11526
+ });
10973
11527
  return {
10974
11528
  dialogs,
10975
11529
  editorOps,
@@ -10979,7 +11533,8 @@ function useViewerBuildingBlocksState(input) {
10979
11533
  handleSetMode,
10980
11534
  handleEnterPresenterView,
10981
11535
  handleEnterRehearsalMode,
10982
- autosaveStatus
11536
+ autosaveStatus,
11537
+ viewPreferencesSync
10983
11538
  };
10984
11539
  }
10985
11540
 
@@ -11052,7 +11607,8 @@ function useViewerBuildingBlocks(input) {
11052
11607
  handleSetMode,
11053
11608
  handleEnterPresenterView,
11054
11609
  handleEnterRehearsalMode,
11055
- autosaveStatus
11610
+ autosaveStatus,
11611
+ viewPreferencesSync
11056
11612
  } = useViewerBuildingBlocksState({
11057
11613
  core,
11058
11614
  content,
@@ -11097,7 +11653,8 @@ function useViewerBuildingBlocks(input) {
11097
11653
  onOpenFile,
11098
11654
  onOpenRecentFile,
11099
11655
  fileName,
11100
- hiddenActions
11656
+ hiddenActions,
11657
+ viewPreferencesSync
11101
11658
  });
11102
11659
  const canvasProps = buildCanvasProps({
11103
11660
  mode,
@@ -11195,4 +11752,4 @@ function useResizablePanels() {
11195
11752
  };
11196
11753
  }
11197
11754
 
11198
- 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 };
11755
+ export { ACTION_VERB_MAP, MIN_TOUCH_TARGET, ViewerOptionsContext, computeToolbarVisibility, detectTargetType, isAudienceTab, parseAudienceNonce, parseEmailUrl, parseSlideFromUrl, renderToCanvas, safePrompt, scopeLayoutOptionsToActiveSlide, syncSelectionHandleOverlay, useAnimationPlayback, useAnnotationHandlers, useAudienceMode, useAutosave, useBroadcastFollower, useCanvasInteractions, useClipboardHandlers, useCollaborationLivePatch, useCollaborativeHistory, useCollaborativeState, useComments, useCompatibilityToastsState, 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, useReadOnlyRecommendationState, useRecoveryDetection, useReducedMotion, useRehearsalTimings, useResizablePanels, useSectionOperations, useSerialize, useSheetDismissDrag, useSlideManagement, useSlideNavigation, useSwipeNavigation, useTableOperations, useThemeHandlers, useThemeSwitching, useToolbarVisibility, useTouchGestures, useViewPreferencesSync, useViewerBuildingBlocks, useViewerCoreState, useViewerDialogs, useViewerIntegration, useViewerOptions, useViewerOptionsContext, useViewerState, useViewerUIState, useVirtualizedSlides, useYjsDocumentSync, useYjsProvider, useZoomNavigation, useZoomViewport };