pptx-react-viewer 4.51.1 → 4.52.1

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 (87) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/dist/{AiChatPanel-EV22O7UO.js → AiChatPanel-7GJQ66GR.js} +19 -19
  3. package/dist/AiChatPanel-7GJQ66GR.js.br +0 -0
  4. package/dist/AiChatPanel-7GJQ66GR.js.gz +0 -0
  5. package/dist/{AiChatPanel-R323KNGN.mjs → AiChatPanel-AI75AT6C.mjs} +1 -1
  6. package/dist/AiChatPanel-AI75AT6C.mjs.br +0 -0
  7. package/dist/AiChatPanel-AI75AT6C.mjs.gz +0 -0
  8. package/dist/{chunk-YJ4DAS4V.js → chunk-2AM5YYWI.js} +586 -615
  9. package/dist/chunk-2AM5YYWI.js.br +0 -0
  10. package/dist/chunk-2AM5YYWI.js.gz +0 -0
  11. package/dist/{chunk-Z22RD3E2.js → chunk-3TN5SUQR.js} +4 -1
  12. package/dist/chunk-3TN5SUQR.js.br +0 -0
  13. package/dist/chunk-3TN5SUQR.js.gz +0 -0
  14. package/dist/{chunk-V4DY4IWP.mjs → chunk-6436YER5.mjs} +390 -420
  15. package/dist/chunk-6436YER5.mjs.br +0 -0
  16. package/dist/chunk-6436YER5.mjs.gz +0 -0
  17. package/dist/{chunk-ZCGYPCZM.mjs → chunk-ID37Y3HG.mjs} +4 -1
  18. package/dist/chunk-ID37Y3HG.mjs.br +0 -0
  19. package/dist/chunk-ID37Y3HG.mjs.gz +0 -0
  20. package/dist/{chunk-VRX5NJY2.js → chunk-JUH4YPMU.js} +1702 -1616
  21. package/dist/chunk-JUH4YPMU.js.br +0 -0
  22. package/dist/chunk-JUH4YPMU.js.gz +0 -0
  23. package/dist/{chunk-KCUXY7DE.mjs → chunk-L77POU5D.mjs} +216 -130
  24. package/dist/chunk-L77POU5D.mjs.br +0 -0
  25. package/dist/chunk-L77POU5D.mjs.gz +0 -0
  26. package/dist/i18n/de.cjs +1 -24
  27. package/dist/i18n/de.cjs.br +0 -0
  28. package/dist/i18n/de.cjs.gz +0 -0
  29. package/dist/i18n/de.mjs +1 -24
  30. package/dist/i18n/de.mjs.br +0 -0
  31. package/dist/i18n/de.mjs.gz +0 -0
  32. package/dist/i18n/es.cjs +1 -24
  33. package/dist/i18n/es.cjs.br +0 -0
  34. package/dist/i18n/es.cjs.gz +0 -0
  35. package/dist/i18n/es.mjs +1 -24
  36. package/dist/i18n/es.mjs.br +0 -0
  37. package/dist/i18n/es.mjs.gz +0 -0
  38. package/dist/i18n/fr.cjs +1 -24
  39. package/dist/i18n/fr.cjs.br +0 -0
  40. package/dist/i18n/fr.cjs.gz +0 -0
  41. package/dist/i18n/fr.mjs +1 -24
  42. package/dist/i18n/fr.mjs.br +0 -0
  43. package/dist/i18n/fr.mjs.gz +0 -0
  44. package/dist/i18n/zh-CN.cjs +0 -23
  45. package/dist/i18n/zh-CN.cjs.br +0 -0
  46. package/dist/i18n/zh-CN.cjs.gz +0 -0
  47. package/dist/i18n/zh-CN.mjs +0 -23
  48. package/dist/i18n/zh-CN.mjs.br +0 -0
  49. package/dist/i18n/zh-CN.mjs.gz +0 -0
  50. package/dist/index.d.ts +14 -2
  51. package/dist/index.js +25 -25
  52. package/dist/index.js.br +0 -0
  53. package/dist/index.js.gz +0 -0
  54. package/dist/index.mjs +3 -3
  55. package/dist/index.mjs.br +0 -0
  56. package/dist/index.mjs.gz +0 -0
  57. package/dist/internals.d.ts +85 -23
  58. package/dist/internals.js +81 -81
  59. package/dist/internals.js.br +0 -0
  60. package/dist/internals.js.gz +0 -0
  61. package/dist/internals.mjs +2 -2
  62. package/dist/internals.mjs.br +0 -0
  63. package/dist/internals.mjs.gz +0 -0
  64. package/dist/viewer/index.d.ts +13 -1
  65. package/dist/viewer/index.js +20 -20
  66. package/dist/viewer/index.js.br +0 -0
  67. package/dist/viewer/index.js.gz +0 -0
  68. package/dist/viewer/index.mjs +3 -3
  69. package/dist/viewer/index.mjs.br +0 -0
  70. package/dist/viewer/index.mjs.gz +0 -0
  71. package/package.json +3 -3
  72. package/dist/AiChatPanel-EV22O7UO.js.br +0 -0
  73. package/dist/AiChatPanel-EV22O7UO.js.gz +0 -0
  74. package/dist/AiChatPanel-R323KNGN.mjs.br +0 -0
  75. package/dist/AiChatPanel-R323KNGN.mjs.gz +0 -0
  76. package/dist/chunk-KCUXY7DE.mjs.br +0 -0
  77. package/dist/chunk-KCUXY7DE.mjs.gz +0 -0
  78. package/dist/chunk-V4DY4IWP.mjs.br +0 -0
  79. package/dist/chunk-V4DY4IWP.mjs.gz +0 -0
  80. package/dist/chunk-VRX5NJY2.js.br +0 -0
  81. package/dist/chunk-VRX5NJY2.js.gz +0 -0
  82. package/dist/chunk-YJ4DAS4V.js.br +0 -0
  83. package/dist/chunk-YJ4DAS4V.js.gz +0 -0
  84. package/dist/chunk-Z22RD3E2.js.br +0 -0
  85. package/dist/chunk-Z22RD3E2.js.gz +0 -0
  86. package/dist/chunk-ZCGYPCZM.mjs.br +0 -0
  87. package/dist/chunk-ZCGYPCZM.mjs.gz +0 -0
@@ -1,9 +1,9 @@
1
- import { cloneTemplateElementsBySlideId, cloneSlide, cloneHistorySnapshot, MIN_ELEMENT_SIZE, ZOOM_TO_SELECTION_PADDING, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, partitionTemplateElements, isTemplateElementId, DEFAULT_TABLE_ROWS, DEFAULT_TABLE_COLUMNS, useTranslation, comparePresentation, UNGROUPED_SECTION_ID, DEFAULT_SECTION_GROUP_ID, stopAllPersistentAudio, buildSaveSlides, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, getImageEffectsOpacity, getImageEffectsFilter, getImageRenderStyle, cn, isEditableTextElement, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageSurfaceStyle, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, getElementLabel, normalizeHexColor, makeCloneId, DEFAULT_TEXT_FONT_SIZE, buildPdfFromTiledImageData, GRID_SIZE, copyFormatFromElement, hasCopyableFormat, isImageTiled, getDuotoneColors, DEFAULT_STROKE_COLOR, DEFAULT_FILL_COLOR, buildCssGradientFromShapeStyle, getCropShapeClipPath, getElementTransform, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getImageSurfaceMaskStyle, getTextWarpStyle, getTextCompensationTransform, renderTextSegments, buildReactChartViewModel, renderChartElement, buildInkGroupStrokes, getInkReplayStyles, INK_REPLAY_KEYFRAMES, buildContentPartStrokes, getContentPartReplayStyles, buildTextBody3DSceneStyle, rerouteConnectorsForMovedElements, applyReroutedConnectors, updateCellTextStyleInRawXml, updateCellTextInRawXml, splitCell, updateMergeAttrsInRawXml, mergeCells, buildNotesPdf, canvasToJpegData, applyFormatToElement, isPpactionUrl, parsePpactionUrl, getImageTilingStyle, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, getAriaRoleDescription as getAriaRoleDescription$1, getAriaLabel as getAriaLabel$1, getAriaRole, DEFAULT_FONT_FAMILY, ACTION_BUTTON_PRESETS, isUrlSafe, safeOpenUrl as safeOpenUrl$1, substituteFieldText, HYPERLINK_COLOR } from './chunk-ZCGYPCZM.mjs';
2
- import { defineThreeViewElement, MIN_TOUCH_TARGET_PX, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createCollaborationSessionController, registerCollaborationTeardown, createPresenceProjector, BROADCAST_THROTTLE_MS, sanitizeColor, createEditorHistoryController, createWheelStepBuffer, createViewerZoomStore, clampZoomScale, mapEditingWheel, createActiveAnimationGroup, cancelBuildReveal, clearPlaybackTimers, PresentationAnimationController, resolveMediaTimeNodeElementIds, resolveMediaBookmarkTimesMs, advanceMainSequence, playGroup, PRESENTATION_HASH, PRESENTATION_NONCE_KEY, PRESENTATION_CHANNEL_NAME, swapPresentationWindows, PRESENTATION_MESSAGE_ORIGIN, clearAudienceContent, buildPresentationAudienceUrl, resolveAudienceScreenPlacement, placeAudienceWindow, storeAudienceContent, isPresentationSessionMessage, endAudienceDisplay, createPresentationKeyBuffer, acceptsPresentationInput, resolveAutoAdvanceDelayMs, resolveShowBackward, resolveShowForward, beginZoomExcursion, buildZoomTransitionOverride, createPresenterShowGuard, firstShowSlideIndex, attachPresentationVisibilityPause, presentationEntrySlideIndex, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, visibleTemplateElements, createCollaborationLivePatcher, reportInlineTextDraft, initialInspectorOpen, createPresentationLoadResources, collectMediaElements, resolveMediaElementSource, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, resolveTextFillBlipUrls, seedRecentColors, resolveAuthoredCustomShowId, GlyphOutlineFontCache, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, resolveInitialSlideIndex, resolveAutosaveIntervalMs, createAutosaveController, saveAutosaveSnapshot, updateMasterViewElement, updateElement, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, canMergeShapes, canInteractWithElement, prepareHtml2CanvasClone, html2canvasCaptureScope, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, DEFAULT_VIEWER_OPTIONS, resolveImageResolutionScale, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, resolveAuthoredSlideRange, mayLeaveSlideShow, buildDeckSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, createAutosaveRecoveryController, discardAutosaveRecovery, probeAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, rasterResultToPngBlob, downloadBlob, elementPictureFilename, canEditElementPoints, selectTrustedEmbeddedFonts, resolveFontWeight, resolveFontItalic, collectReferencedFontFamilies, resolveGoogleWebfontHref, syncGoogleWebfontStylesheet, selectGoogleWebfontFamilies, fetchGoogleWebfontOutlineBytes, dispatchEditorKey, isFeatureEnabled, parentSelection, textFontSizePtToPx, stepFontSizePt, textFontSizePxToPt, cycleSelectableElement, createCustomizationController, prepareElementForInsertion, slideSpaceElement, autosaveStatusKind, createViewerOptionsStore, observeYDocSlides, LOCAL_SYNC_ORIGIN, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, isKeyboardOpen, scopeLayoutOptionsToSlide, INITIAL_READ_ONLY_SESSION, readOnlySessionActions, applyReadOnlySessionEvent, readOnlyBannerVisible, readOnlyLocked, viewerPreferencesFromViewProperties, DEFAULT_VIEWER_PREFERENCES, viewPropertiesPatchFromPreferences, resolveCollaborationConfig, openPptxFile, readBackstageRecentFile, resolveCollaborationShellEditability, resolveCollaborationShellState, getResizeHandleHitAreaStyle, resolveElementInteractivity, getBackgroundAnimationState, getShapeEffectLayerPlacement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, isMediaFullscreenActive, shouldRenderHitTarget, elementHitTargetStyle, getShapeEffectAnimationLayerStyle, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, resolvePalette as resolvePalette$1, mediaTransportVisible, oleActionsVisible, getGroupChildParentFill, deviceStrokeStageStyle, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, getSlideTransitionAnimations, getFragmentedTransitionDescriptor, SLIDE_TRANSITION_KEYFRAMES, isActionHidden, buildInlineTextCommitPatch, resolveInlineEditAutoFitHeight, resolveInlineEditNormAutofitShrink, setPendingCaretPoint, resolveGroupDoubleClickTarget, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, contextMenuInspectorAnchor, savedPresentationFileName, deliverSavedPresentation, exportDeckJson, mapCustomizedEditorKey, isEditorTextInputTarget, groupElements, generateElementId, ungroupElements, alignElements, distributeElements, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, planMergeShapes, applyMergeShapesPlan, mapPresentationKey, lastShowSlideIndex, mapPresentationWheel, openPendingPrintWindow, computeColorFilter, filterHiddenSlideIndices, computeSlideIndices, buildPrintDocument, finishPrintWindow, buildPrintHtmlDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, insertSlidePaste, applySlidePasteTemplates, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, needsOwnedSession, openOwnedCollaboration, resolveViewportFitOptions, editorViewportFitFor, calculateViewportFit, observeViewportClientSize, scheduleAutoAdvanceChain, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, resolveTransitionSoundAction, runPresentationAction, safeOpenUrl, buildRunProgramNotice, toggleStageElementMedia, resolveOleVerbTarget, downloadDataUrl, openUrlInNewTab, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, slideSpaceMembers, remapTextToSegments, getInlineEditorSelectionResult, buildInlineListStylePatch, applyActiveInlineListFormatting, applyListStyleUpdate, setPendingSelectionRestore, applyTextStyleUpdate, toggleSelectionBullets, transformInlineListCase, applyCaseTransformToSegments, transformTextCase, createGestureController, resolveExportCaptureDecision, recordProgressPercent, computeGridSpacingPx as computeGridSpacingPx$1, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, overlayMasterViewInlineSnapshot, overlayInlineTextSnapshot, rasterizeElement, cloneElementForPaste, applyPasteSpecialFormat, buildRasterPictureElement, cloneElementUpdates, assertElementUpdateTarget, prepareElementUpdateBatch, createWriteBackScheduler, writeBackReport, createSyncGate, observeExternalCollaborationReadiness, resolveHistoryDepth, createBackstagePresentation, buildFieldSubstitutionContext, getImageColorWashStyle, attachRotateHandlePlacement, getSelectionControlArtworkStyle, getSelectionOutlineColor, paintedStrokeWidth, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, paintedElementSize, MEDIA_FULLSCREEN_OVERLAY_STYLE, elementContainerHeightStyle, getAnimationOpacity, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, getEffectStyleSource, getBevelLightingSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, strokeOutlineViewBox, buildSummaryZoomView, readEditableText, placeCaretAt, takePendingCaretPoint, getPendingSelectionRestore, restoreSegmentSelection, mapInlineTextFormatKey, mapInlineEditorChord, subscribeBarFacePicturePixelSamples, getBarFacePicturePixelSampleVersion, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, chartFormatTargetFromEvent, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, getAriaRoleDescription, getAriaLabel, elementIdSelector, TOOLBAR_TABS, resolveGroupPressTarget, scrollInspectorSectionIntoView, computeScrollDelta, replyToCommentInList, removeTableElementColumn, insertTableElementColumn, removeTableElementRow, insertTableElementRow, withCellStyle, setCellText, pickSupportedMimeType, WEBM_MIME_CANDIDATES, fpsToFrameIntervalMs, segmentFrameCount, stopCaptureStream, GIF_POST_CAPTURE_MAX_SIDE, encodeGif, rasterizeElementTiles, placeTileOnPage, PDF_SLIDES_PAGE_WIDTH_PT, PDF_SLIDES_PAGE_HEIGHT_PT, createSnapshotTextPositions, resolvePresentationAction, getImageSvgFilters, getCachedNativeImageSize, probeNativeImageSize, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, svgLineCap, screenStrokeWidth, connectorWrapperTransform, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, modelDataToBlobUrl, resolveZoomNavigationTarget, inlineListBodyText, createInlineListSeed, readListActivationSelection, createInlineListModelObserver, attachCollaborationInlineEditor, bindInlineListParagraph, bindInlineListRun, attachInlineListController, restoreInlineListBodySelection, isBulletMarkerSegment, resolveChartThreeViewSpec, applyChart3DDrag, applyChart3DSelect, canDrillDown, findChartPartTarget, withChartTitle, resolveSmartArtThreeViewSpec, measureSvgViewportRect, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, hasGlyphEnvelope, buildGlyphEnvelopeBlock, getWarpPath, isWedgeCalloutPresetShape, getAriaRole as getAriaRole$1, isElementActionable, buildSmartArtPresetData, classifyMediaType, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, rasterizeElementTiledToCanvas, borrowExternalCollaborationAwareness, observeExternalCollaborationSession, publishLiveGeometry, clampGifDimensions, rasterResultToPngDataUrl, shouldConfirmExternalHyperlink, advanceChartMarkDrag, advanceChartValueDrag, resolveChartKind, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, findSmartArtNodeText, commitSmartArtNodeFill, commitSmartArtNodeText, groupIntoParagraphs as groupIntoParagraphs$1, createGlyphOutlineLookup, applyMotionPathPreset, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, computeSmartArtElementLayout, flattenNodes, computeInlineEditorRect, smartArtNodeAtPoint, SMARTART_DEFAULT_PALETTE, computeDrawingViewBox, projectDrawingShapes, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, centeredSvgTextLines, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, bringForward, sendBackward, bringToFront, sendToBack } from 'ooxml-ui/pptx';
1
+ import { cloneTemplateElementsBySlideId, cloneSlide, cloneHistorySnapshot, MIN_ELEMENT_SIZE, ZOOM_TO_SELECTION_PADDING, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, partitionTemplateElements, isTemplateElementId, DEFAULT_TABLE_ROWS, DEFAULT_TABLE_COLUMNS, useTranslation, comparePresentation, UNGROUPED_SECTION_ID, DEFAULT_SECTION_GROUP_ID, stopAllPersistentAudio, buildSaveSlides, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, getImageEffectsOpacity, getImageEffectsFilter, getImageRenderStyle, cn, isEditableTextElement, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageSurfaceStyle, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, getElementLabel, normalizeHexColor, makeCloneId, DEFAULT_TEXT_FONT_SIZE, buildPdfFromTiledImageData, GRID_SIZE, copyFormatFromElement, hasCopyableFormat, isImageTiled, getDuotoneColors, DEFAULT_STROKE_COLOR, DEFAULT_FILL_COLOR, buildCssGradientFromShapeStyle, getCropShapeClipPath, getElementTransform, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getImageSurfaceMaskStyle, getTextWarpStyle, getTextCompensationTransform, renderTextSegments, buildReactChartViewModel, renderChartElement, buildInkGroupStrokes, getInkReplayStyles, INK_REPLAY_KEYFRAMES, buildContentPartStrokes, getContentPartReplayStyles, buildTextBody3DSceneStyle, rerouteConnectorsForMovedElements, applyReroutedConnectors, updateCellTextStyleInRawXml, updateCellTextInRawXml, splitCell, updateMergeAttrsInRawXml, mergeCells, buildNotesPdf, canvasToJpegData, applyFormatToElement, isPpactionUrl, parsePpactionUrl, getImageTilingStyle, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, getAriaRoleDescription as getAriaRoleDescription$1, getAriaLabel as getAriaLabel$1, getAriaRole, DEFAULT_FONT_FAMILY, ACTION_BUTTON_PRESETS, isUrlSafe, safeOpenUrl as safeOpenUrl$1, substituteFieldText, HYPERLINK_COLOR } from './chunk-ID37Y3HG.mjs';
2
+ import { defineThreeViewElement, MIN_TOUCH_TARGET_PX, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createCollaborationSessionController, registerCollaborationTeardown, createPresenceProjector, BROADCAST_THROTTLE_MS, sanitizeColor, createEditorHistoryController, historyTheme, crossedHistoryTheme, createWheelStepBuffer, createViewerZoomStore, clampZoomScale, mapEditingWheel, createActiveAnimationGroup, cancelBuildReveal, clearPlaybackTimers, PresentationAnimationController, resolveMediaTimeNodeElementIds, resolveMediaBookmarkTimesMs, advanceMainSequence, playGroup, PRESENTATION_HASH, PRESENTATION_NONCE_KEY, PRESENTATION_CHANNEL_NAME, swapPresentationWindows, PRESENTATION_MESSAGE_ORIGIN, clearAudienceContent, buildPresentationAudienceUrl, resolveAudienceScreenPlacement, placeAudienceWindow, storeAudienceContent, isPresentationSessionMessage, endAudienceDisplay, createPresentationKeyBuffer, acceptsPresentationInput, resolveAutoAdvanceDelayMs, resolveShowBackward, resolveShowForward, beginZoomExcursion, buildZoomTransitionOverride, createPresenterShowGuard, firstShowSlideIndex, attachPresentationVisibilityPause, presentationEntrySlideIndex, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, INITIAL_FIND_REPLACE_SESSION, findReplaceSessionActions, visibleTemplateElements, createCollaborationLivePatcher, reportInlineTextDraft, initialInspectorOpen, createPresentationLoadResources, collectMediaElements, resolveMediaElementSource, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, resolveTextFillBlipUrls, seedRecentColors, resolveAuthoredCustomShowId, GlyphOutlineFontCache, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, resolveInitialSlideIndex, resolveAutosaveIntervalMs, createAutosaveController, saveAutosaveSnapshot, updateMasterViewElement, updateElement, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, canMergeShapes, canInteractWithElement, prepareHtml2CanvasClone, html2canvasCaptureScope, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, DEFAULT_VIEWER_OPTIONS, resolveImageResolutionScale, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, resolveAuthoredSlideRange, mayLeaveSlideShow, buildDeckSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, createAutosaveRecoveryController, discardAutosaveRecovery, probeAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, rasterResultToPngBlob, downloadBlob, elementPictureFilename, canEditElementPoints, resolveGoogleFontsCss2Base, selectTrustedEmbeddedFonts, resolveFontWeight, resolveFontItalic, collectReferencedFontFamilies, resolveGoogleWebfontHref, syncGoogleWebfontStylesheet, selectGoogleWebfontFamilies, fetchGoogleWebfontOutlineBytes, dispatchEditorKey, isFeatureEnabled, parentSelection, textFontSizePtToPx, stepFontSizePt, textFontSizePxToPt, cycleSelectableElement, createCustomizationController, prepareElementForInsertion, slideSpaceElement, autosaveStatusKind, createViewerOptionsStore, observeYDocSlides, LOCAL_SYNC_ORIGIN, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, isKeyboardOpen, scopeLayoutOptionsToSlide, INITIAL_READ_ONLY_SESSION, readOnlySessionActions, applyReadOnlySessionEvent, readOnlyBannerVisible, readOnlyLocked, viewerPreferencesFromViewProperties, DEFAULT_VIEWER_PREFERENCES, viewPropertiesPatchFromPreferences, resolveCollaborationConfig, openPptxFile, readBackstageRecentFile, resolveCollaborationShellEditability, resolveCollaborationShellState, getResizeHandleHitAreaStyle, resolveElementInteractivity, getBackgroundAnimationState, getShapeEffectLayerPlacement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, isMediaFullscreenActive, shouldRenderHitTarget, elementHitTargetStyle, getShapeEffectAnimationLayerStyle, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, resolvePalette as resolvePalette$1, mediaTransportVisible, oleActionsVisible, getGroupChildParentFill, deviceStrokeStageStyle, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, getSlideTransitionAnimations, getFragmentedTransitionDescriptor, SLIDE_TRANSITION_KEYFRAMES, isActionHidden, buildInlineTextCommitPatch, resolveInlineEditAutoFitHeight, resolveInlineEditNormAutofitShrink, setPendingCaretPoint, resolveGroupDoubleClickTarget, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, contextMenuInspectorAnchor, savedPresentationFileName, deliverSavedPresentation, exportDeckJson, mapCustomizedEditorKey, isEditorTextInputTarget, groupElements, generateElementId, ungroupElements, alignElements, distributeElements, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, planMergeShapes, applyMergeShapesPlan, mapPresentationKey, lastShowSlideIndex, mapPresentationWheel, createBlankSlide, insertSlidePaste, applySlidePasteTemplates, makeSlideId, insertedLayoutCompletion, buildSlideTemplateSlide, templateSchemeFromTheme, queueThemeWrite, needsOwnedSession, openOwnedCollaboration, resolveViewportFitOptions, editorViewportFitFor, calculateViewportFit, observeViewportClientSize, scheduleAutoAdvanceChain, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, resolveTransitionSoundAction, runPresentationAction, safeOpenUrl, buildRunProgramNotice, toggleStageElementMedia, resolveOleVerbTarget, downloadDataUrl, openUrlInNewTab, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, slideSpaceMembers, remapTextToSegments, getInlineEditorSelectionResult, buildInlineListStylePatch, applyActiveInlineListFormatting, applyListStyleUpdate, setPendingSelectionRestore, applyTextStyleUpdate, toggleSelectionBullets, transformInlineListCase, applyCaseTransformToSegments, transformTextCase, createGestureController, resolveExportCaptureDecision, recordProgressPercent, computeGridSpacingPx as computeGridSpacingPx$1, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, overlayMasterViewInlineSnapshot, overlayInlineTextSnapshot, rasterizeElement, cloneElementForPaste, applyPasteSpecialFormat, buildRasterPictureElement, cloneElementUpdates, assertElementUpdateTarget, prepareElementUpdateBatch, createWriteBackScheduler, writeBackReport, createSyncGate, observeExternalCollaborationReadiness, resolveHistoryDepth, createBackstagePresentation, buildFieldSubstitutionContext, getImageColorWashStyle, attachRotateHandlePlacement, getSelectionControlArtworkStyle, getSelectionOutlineColor, paintedStrokeWidth, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, paintedElementSize, MEDIA_FULLSCREEN_OVERLAY_STYLE, elementContainerHeightStyle, getAnimationOpacity, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, getEffectStyleSource, getBevelLightingSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, strokeOutlineViewBox, buildSummaryZoomView, readEditableText, placeCaretAt, takePendingCaretPoint, getPendingSelectionRestore, restoreSegmentSelection, mapInlineTextFormatKey, mapInlineEditorChord, subscribeBarFacePicturePixelSamples, getBarFacePicturePixelSampleVersion, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, chartFormatTargetFromEvent, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, getAriaRoleDescription, getAriaLabel, elementIdSelector, TOOLBAR_TABS, resolveGroupPressTarget, scrollInspectorSectionIntoView, computeScrollDelta, buildOutlinePrintJobDocument, printJobRasterFallback, applyThemeByPath, withHistoryTheme, withHistoryMasterThemes, writeThemeParts, loadedThemeName, replyToCommentInList, removeTableElementColumn, insertTableElementColumn, removeTableElementRow, insertTableElementRow, withCellStyle, setCellText, pickSupportedMimeType, WEBM_MIME_CANDIDATES, fpsToFrameIntervalMs, segmentFrameCount, stopCaptureStream, GIF_POST_CAPTURE_MAX_SIDE, encodeGif, rasterizeElementTiles, placeTileOnPage, PDF_SLIDES_PAGE_WIDTH_PT, PDF_SLIDES_PAGE_HEIGHT_PT, createSnapshotTextPositions, resolvePresentationAction, getImageSvgFilters, getCachedNativeImageSize, probeNativeImageSize, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, svgLineCap, screenStrokeWidth, connectorWrapperTransform, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, modelDataToBlobUrl, resolveZoomNavigationTarget, inlineListBodyText, createInlineListSeed, readListActivationSelection, createInlineListModelObserver, attachCollaborationInlineEditor, bindInlineListParagraph, bindInlineListRun, attachInlineListController, restoreInlineListBodySelection, isBulletMarkerSegment, resolveChartThreeViewSpec, applyChart3DDrag, applyChart3DSelect, canDrillDown, findChartPartTarget, withChartTitle, resolveSmartArtThreeViewSpec, measureSvgViewportRect, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, hasGlyphEnvelope, buildGlyphEnvelopeBlock, getWarpPath, isWedgeCalloutPresetShape, getAriaRole as getAriaRole$1, isElementActionable, buildSmartArtPresetData, classifyMediaType, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, planPrintJob, openPrintWindow, buildVectorPrintJobDocument, openPendingPrintWindow, borrowExternalCollaborationAwareness, observeExternalCollaborationSession, publishLiveGeometry, rasterizeElementTiledToCanvas, clampGifDimensions, rasterResultToPngDataUrl, shouldConfirmExternalHyperlink, advanceChartMarkDrag, advanceChartValueDrag, resolveChartKind, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, findSmartArtNodeText, commitSmartArtNodeFill, commitSmartArtNodeText, groupIntoParagraphs as groupIntoParagraphs$1, createGlyphOutlineLookup, finishPrintWindow, buildRasterPrintJobDocument, applyMotionPathPreset, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, computeSmartArtElementLayout, flattenNodes, computeInlineEditorRect, smartArtNodeAtPoint, SMARTART_DEFAULT_PALETTE, computeDrawingViewBox, projectDrawingShapes, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, centeredSvgTextLines, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, bringForward, sendBackward, bringToFront, sendToBack } from 'ooxml-ui/pptx';
3
3
  export { DUOTONE_PRESETS, MOBILE_BREAKPOINT, SLIDE_TRANSITION_KEYFRAMES, TABLET_BREAKPOINT, clearAudienceContent, computeVirtualRange, downloadBlob, getSlideTransitionAnimations, loadAudienceContent, storeAudienceContent } from 'ooxml-ui/pptx';
4
4
  import React17, { useRef, useState, useCallback, useEffect, useSyncExternalStore, useMemo, useContext, useLayoutEffect, createContext, useImperativeHandle, Suspense } from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
- import { PptxHandler, EncryptedFileError, hasShapeProperties, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, guidePxToEmu, hasTextProperties, isInkElement, duplicateSlide, buildThemeColorMap, reResolveSlideColors, reResolveElementColors, reResolveSlideFonts, reResolveElementFonts, isImageLikeElement, SvgExporter, getSubstituteFontFamily, elementActionToPptxAction, setSmartArtNodeStyle, updateSmartArtNodeText } from 'ooxml-core/pptx';
6
+ import { PptxHandler, EncryptedFileError, hasShapeProperties, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, guidePxToEmu, hasTextProperties, isInkElement, duplicateSlide, buildThemeColorMap, reResolveSlideColors, reResolveElementColors, reResolveSlideFonts, reResolveElementFonts, isImageLikeElement, getSubstituteFontFamily, elementActionToPptxAction, SvgExporter, setSmartArtNodeStyle, updateSmartArtNodeText } from 'ooxml-core/pptx';
7
7
  import { translationsEn } from 'ooxml-ui/pptx/i18n';
8
8
  import { flushSync } from 'react-dom';
9
9
  import { LuRotateCw } from 'react-icons/lu';
@@ -572,9 +572,30 @@ function serializeHistoryDocument(snapshot) {
572
572
  slideId,
573
573
  elements.map(historyElementContent)
574
574
  ])
575
- )
575
+ ),
576
+ // A theme pick that changes nothing on the slides is still an edit, and an undo step.
577
+ theme: snapshot.theme
576
578
  });
577
579
  }
580
+ function withMasterPathsIn(snapshot, paths) {
581
+ const { theme, ...rest } = snapshot;
582
+ if (!theme?.masterThemePaths) {
583
+ return snapshot;
584
+ }
585
+ const { masterThemePaths, ...parts } = theme;
586
+ const kept = Object.entries(masterThemePaths).filter(([path]) => paths.has(path));
587
+ const next = kept.length > 0 ? { ...parts, masterThemePaths: Object.fromEntries(kept) } : parts;
588
+ return Object.keys(next).length > 0 ? { ...rest, theme: next } : rest;
589
+ }
590
+ function differsOnlyInMasterSet(previous, next) {
591
+ const before = Object.keys(previous.theme?.masterThemePaths ?? {});
592
+ const after = new Set(Object.keys(next.theme?.masterThemePaths ?? {}));
593
+ if (before.length === after.size && before.every((path) => after.has(path))) {
594
+ return false;
595
+ }
596
+ const shared = new Set(before.filter((path) => after.has(path)));
597
+ return serializeHistoryDocument(withMasterPathsIn(previous, shared)) === serializeHistoryDocument(withMasterPathsIn(next, shared));
598
+ }
578
599
  function recordExplicitSlideUpdate(history, previous, before, label) {
579
600
  if (previous && serializeHistoryDocument(previous) !== serializeHistoryDocument(before)) {
580
601
  history.record(cloneHistorySnapshot(previous), previous.actionLabel);
@@ -627,6 +648,9 @@ function useEditorHistory(input) {
627
648
  hasActivePointerInteraction,
628
649
  pointerCommitNonce,
629
650
  onDirty,
651
+ theme,
652
+ slideMasters,
653
+ onRestoreTheme,
630
654
  setSlides,
631
655
  setCanvasSize,
632
656
  setActiveSlideIndex,
@@ -653,16 +677,18 @@ function useEditorHistory(input) {
653
677
  }, [history, maxHistoryEntries]);
654
678
  const buildHistorySnapshot = useCallback(
655
679
  (actionLabel) => {
680
+ const recordedTheme = historyTheme(theme, slideMasters);
656
681
  return {
657
682
  width: canvasSize.width,
658
683
  height: canvasSize.height,
659
684
  activeSlideIndex,
660
685
  slides: slides.map(cloneSlide),
661
686
  templateElementsBySlideId: cloneTemplateElementsBySlideId(templateElementsBySlideId),
687
+ ...recordedTheme ? { theme: recordedTheme } : {},
662
688
  ...actionLabel ? { actionLabel } : {}
663
689
  };
664
690
  },
665
- [activeSlideIndex, canvasSize, slides, templateElementsBySlideId]
691
+ [activeSlideIndex, canvasSize, slideMasters, slides, templateElementsBySlideId, theme]
666
692
  );
667
693
  const applyHistorySnapshot = useCallback(
668
694
  (snapshot) => {
@@ -700,15 +726,41 @@ function useEditorHistory(input) {
700
726
  useEffect(() => {
701
727
  onDirtyRef.current = onDirty;
702
728
  }, [onDirty]);
729
+ const untrackedDepthRef = useRef(0);
703
730
  const markDirty = useCallback(() => {
731
+ if (untrackedDepthRef.current > 0) {
732
+ return;
733
+ }
704
734
  setEditCommitNonce((previous) => previous + 1);
705
735
  onDirtyRef.current?.();
706
736
  }, []);
737
+ const onRestoreThemeRef = useRef(onRestoreTheme);
738
+ useEffect(() => {
739
+ onRestoreThemeRef.current = onRestoreTheme;
740
+ }, [onRestoreTheme]);
741
+ const restoreTheme = useCallback(
742
+ (current, target) => {
743
+ const crossed = crossedHistoryTheme(current.theme, target.theme);
744
+ if (crossed) {
745
+ onRestoreThemeRef.current?.(crossed);
746
+ }
747
+ },
748
+ []
749
+ );
750
+ const withoutUndoStep = useCallback((apply) => {
751
+ untrackedDepthRef.current += 1;
752
+ try {
753
+ apply();
754
+ } finally {
755
+ untrackedDepthRef.current -= 1;
756
+ }
757
+ }, []);
707
758
  const handleUndo = useCallback(() => {
708
759
  if (!history.getSnapshot().canUndo) {
709
760
  return;
710
761
  }
711
- const result = history.undo(buildHistorySnapshot());
762
+ const currentSnapshot = buildHistorySnapshot();
763
+ const result = history.undo(currentSnapshot);
712
764
  if (!result) {
713
765
  return;
714
766
  }
@@ -717,14 +769,23 @@ function useEditorHistory(input) {
717
769
  lastHistorySnapshotRef.current = cloneHistorySnapshot(nextSnapshot);
718
770
  lastHistorySerializedRef.current = serializeHistoryDocument(nextSnapshot);
719
771
  applyHistorySnapshot(nextSnapshot);
772
+ restoreTheme(currentSnapshot, nextSnapshot);
720
773
  unlockHistoryTracking();
721
774
  markDirty();
722
- }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
775
+ }, [
776
+ applyHistorySnapshot,
777
+ buildHistorySnapshot,
778
+ history,
779
+ markDirty,
780
+ restoreTheme,
781
+ unlockHistoryTracking
782
+ ]);
723
783
  const handleRedo = useCallback(() => {
724
784
  if (!history.getSnapshot().canRedo) {
725
785
  return;
726
786
  }
727
- const result = history.redo(buildHistorySnapshot());
787
+ const currentSnapshot = buildHistorySnapshot();
788
+ const result = history.redo(currentSnapshot);
728
789
  if (!result) {
729
790
  return;
730
791
  }
@@ -733,9 +794,17 @@ function useEditorHistory(input) {
733
794
  lastHistorySnapshotRef.current = cloneHistorySnapshot(targetSnapshot);
734
795
  lastHistorySerializedRef.current = serializeHistoryDocument(targetSnapshot);
735
796
  applyHistorySnapshot(targetSnapshot);
797
+ restoreTheme(currentSnapshot, targetSnapshot);
736
798
  unlockHistoryTracking();
737
799
  markDirty();
738
- }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
800
+ }, [
801
+ applyHistorySnapshot,
802
+ buildHistorySnapshot,
803
+ history,
804
+ markDirty,
805
+ restoreTheme,
806
+ unlockHistoryTracking
807
+ ]);
739
808
  const resetHistory = useCallback(
740
809
  (initialSnapshot) => {
741
810
  history.clear();
@@ -787,7 +856,7 @@ function useEditorHistory(input) {
787
856
  return;
788
857
  }
789
858
  const previousSnapshot = lastHistorySnapshotRef.current;
790
- if (!previousSnapshot) {
859
+ if (!previousSnapshot || differsOnlyInMasterSet(previousSnapshot, snapshot)) {
791
860
  lastHistorySnapshotRef.current = snapshot;
792
861
  lastHistorySerializedRef.current = serialized;
793
862
  lastCheapHashRef.current = cheapHash;
@@ -813,9 +882,15 @@ function useEditorHistory(input) {
813
882
  pointerReleaseNonce,
814
883
  slides
815
884
  ]);
816
- const commitSlides = (nextSlides, label, beforeSlides = slides) => {
885
+ const commitSlides = (nextSlides, label, beforeSlides = slides, nextSlideMasters) => {
817
886
  const before = { ...buildHistorySnapshot(), slides: beforeSlides.map(cloneSlide) };
818
- const after = { ...before, slides: nextSlides.map(cloneSlide) };
887
+ const { theme: beforeTheme, ...unthemed } = before;
888
+ const afterTheme = nextSlideMasters ? historyTheme(theme, nextSlideMasters) : beforeTheme;
889
+ const after = {
890
+ ...unthemed,
891
+ slides: nextSlides.map(cloneSlide),
892
+ ...afterTheme ? { theme: afterTheme } : {}
893
+ };
819
894
  recordExplicitSlideUpdate(history, lastHistorySnapshotRef.current, before, label);
820
895
  lastHistorySnapshotRef.current = cloneHistorySnapshot(after);
821
896
  lastHistorySerializedRef.current = serializeHistoryDocument(after);
@@ -836,7 +911,9 @@ function useEditorHistory(input) {
836
911
  handleUndo,
837
912
  handleRedo,
838
913
  resetHistory,
914
+ forgetHistory: history.forget,
839
915
  markDirty,
916
+ withoutUndoStep,
840
917
  buildHistorySnapshot
841
918
  };
842
919
  }
@@ -3135,109 +3212,62 @@ function usePresentationAnnotations(input) {
3135
3212
  function useFindReplace({
3136
3213
  slides,
3137
3214
  mode,
3138
- onSetActiveSlideIndex,
3139
- onSetSelectedElementId,
3215
+ onShowMatch,
3140
3216
  onUpdateSlides,
3141
3217
  onMarkDirty,
3142
3218
  keyboard
3143
3219
  }) {
3144
3220
  const [findReplaceOpen, setFindReplaceOpen] = useState(false);
3145
- const [findQuery, setFindQuery] = useState("");
3146
- const [replaceQuery, setReplaceQuery] = useState("");
3147
- const [findMatchCase, setFindMatchCase] = useState(false);
3148
- const [findIncludeNotes, setFindIncludeNotes] = useState(false);
3149
- const [findIncludeChartTitles, setFindIncludeChartTitles] = useState(true);
3150
- const [findIncludeChartData, setFindIncludeChartData] = useState(false);
3151
- const [findResults, setFindResults] = useState([]);
3152
- const [findResultIndex, setFindResultIndex] = useState(-1);
3153
- const pendingRefindRef = useRef(false);
3154
- useEffect(() => {
3155
- if (findReplaceOpen) {
3156
- return;
3157
- }
3158
- setFindResults([]);
3159
- setFindResultIndex(-1);
3160
- pendingRefindRef.current = false;
3161
- }, [findReplaceOpen]);
3162
- const performFind = useCallback(() => {
3163
- const results = findInSlides(slides, findQuery, {
3164
- matchCase: findMatchCase,
3165
- includeNotes: findIncludeNotes,
3166
- includeChartTitles: findIncludeChartTitles,
3167
- includeChartData: findIncludeChartData
3168
- });
3169
- if (!findQuery) {
3170
- setFindResults([]);
3171
- setFindResultIndex(-1);
3172
- return;
3173
- }
3174
- setFindResults(results);
3175
- setFindResultIndex(results.length > 0 ? 0 : -1);
3176
- if (results.length > 0) {
3177
- onSetActiveSlideIndex(results[0].slideIndex);
3178
- onSetSelectedElementId(results[0].elementId);
3179
- }
3180
- }, [
3181
- slides,
3182
- findQuery,
3183
- findMatchCase,
3184
- findIncludeNotes,
3185
- findIncludeChartTitles,
3186
- findIncludeChartData,
3187
- onSetActiveSlideIndex,
3188
- onSetSelectedElementId
3189
- ]);
3190
- const navigateFindResult = useCallback(
3191
- (direction) => {
3192
- if (findResults.length === 0) {
3193
- return;
3194
- }
3195
- const nextIdx = (findResultIndex + direction + findResults.length) % findResults.length;
3196
- setFindResultIndex(nextIdx);
3197
- const match = findResults[nextIdx];
3198
- if (match) {
3199
- onSetActiveSlideIndex(match.slideIndex);
3200
- onSetSelectedElementId(match.elementId);
3201
- }
3202
- },
3203
- [findResults, findResultIndex, onSetActiveSlideIndex, onSetSelectedElementId]
3204
- );
3205
- const applyReplacements = useCallback(
3206
- (toReplace) => {
3207
- if (toReplace.length === 0) {
3208
- return;
3209
- }
3210
- if (toReplace.some((match) => match.readOnly)) {
3211
- return;
3221
+ const [session, setSession] = useState(INITIAL_FIND_REPLACE_SESSION);
3222
+ const latest = useRef({ slides, onShowMatch, onUpdateSlides, onMarkDirty });
3223
+ latest.current = { slides, onShowMatch, onUpdateSlides, onMarkDirty };
3224
+ const latestSession = useRef(session);
3225
+ const [actions] = useState(
3226
+ () => findReplaceSessionActions(
3227
+ {
3228
+ get: () => latestSession.current,
3229
+ set: (next) => {
3230
+ latestSession.current = next;
3231
+ setSession(next);
3232
+ }
3233
+ },
3234
+ {
3235
+ slides: () => latest.current.slides,
3236
+ commit: (next) => {
3237
+ latest.current.onUpdateSlides(() => next);
3238
+ latest.current.onMarkDirty();
3239
+ },
3240
+ navigate: ({ slideIndex, elementId }) => latest.current.onShowMatch(slideIndex, elementId)
3212
3241
  }
3213
- onUpdateSlides(
3214
- (prevSlides) => applyFindReplacements(prevSlides, toReplace, replaceQuery).slides
3215
- );
3216
- onMarkDirty();
3217
- },
3218
- [replaceQuery, onUpdateSlides, onMarkDirty]
3242
+ )
3219
3243
  );
3220
- const handleReplace = useCallback(() => {
3221
- if (findResults.length === 0 || findResultIndex < 0) {
3222
- return;
3223
- }
3224
- applyReplacements([findResults[findResultIndex]]);
3225
- pendingRefindRef.current = true;
3226
- }, [findResults, findResultIndex, applyReplacements]);
3227
- const handleReplaceAll = useCallback(() => {
3228
- if (findResults.length === 0) {
3229
- return;
3230
- }
3231
- applyReplacements(findResults);
3232
- pendingRefindRef.current = true;
3233
- }, [findResults, applyReplacements]);
3234
3244
  useEffect(() => {
3235
- if (!pendingRefindRef.current) {
3236
- return;
3245
+ if (!findReplaceOpen) {
3246
+ actions.close();
3237
3247
  }
3238
- pendingRefindRef.current = false;
3239
- performFind();
3240
- }, [performFind]);
3248
+ }, [findReplaceOpen, actions]);
3249
+ useEffect(() => {
3250
+ actions.slidesChanged();
3251
+ }, [slides, actions]);
3252
+ const handlers = useMemo(
3253
+ () => ({
3254
+ setFindQuery: (query) => actions.search({ query }),
3255
+ setReplaceQuery: actions.setReplacement,
3256
+ setFindMatchCase: (matchCase) => actions.search({ options: { matchCase } }),
3257
+ setFindIncludeNotes: (includeNotes) => actions.search({ options: { includeNotes } }),
3258
+ setFindIncludeChartTitles: (includeChartTitles) => actions.search({ options: { includeChartTitles } }),
3259
+ setFindIncludeChartData: (includeChartData) => actions.search({ options: { includeChartData } }),
3260
+ performFind: () => actions.search(),
3261
+ navigateFindResult: (direction) => direction > 0 ? actions.next() : actions.previous(),
3262
+ handleReplace: () => {
3263
+ actions.replaceCurrent();
3264
+ },
3265
+ handleReplaceAll: () => {
3266
+ actions.replaceAll();
3267
+ }
3268
+ }),
3269
+ [actions]
3270
+ );
3241
3271
  useEffect(() => {
3242
3272
  const handler = (event) => {
3243
3273
  const { action } = mapCustomizedEditorKey(
@@ -3260,24 +3290,15 @@ function useFindReplace({
3260
3290
  return {
3261
3291
  findReplaceOpen,
3262
3292
  setFindReplaceOpen,
3263
- findQuery,
3264
- setFindQuery,
3265
- replaceQuery,
3266
- setReplaceQuery,
3267
- findMatchCase,
3268
- setFindMatchCase,
3269
- findIncludeNotes,
3270
- setFindIncludeNotes,
3271
- findIncludeChartTitles,
3272
- findIncludeChartData,
3273
- setFindIncludeChartTitles,
3274
- setFindIncludeChartData,
3275
- findResults,
3276
- findResultIndex,
3277
- performFind,
3278
- navigateFindResult,
3279
- handleReplace,
3280
- handleReplaceAll
3293
+ findQuery: session.query,
3294
+ replaceQuery: session.replacement,
3295
+ findMatchCase: session.options.matchCase,
3296
+ findIncludeNotes: session.options.includeNotes,
3297
+ findIncludeChartTitles: session.options.includeChartTitles,
3298
+ findIncludeChartData: session.options.includeChartData,
3299
+ findResults: session.matches,
3300
+ findResultIndex: session.current,
3301
+ ...handlers
3281
3302
  };
3282
3303
  }
3283
3304
  function useModalDismissDrag(onClose, threshold = 120) {
@@ -3937,6 +3958,35 @@ function useInlineEditingState(onTextChange) {
3937
3958
  registerInlineEditReader
3938
3959
  };
3939
3960
  }
3961
+ function useSlideChangeSelection({
3962
+ setActiveSlideIndex,
3963
+ setSelectedElementId,
3964
+ setSelectedElementIds
3965
+ }) {
3966
+ const slideSelectionRef = useRef(null);
3967
+ const showSlideSelection = useCallback(
3968
+ (slideIndex, elementId) => {
3969
+ slideSelectionRef.current = slideIndex;
3970
+ setActiveSlideIndex(slideIndex);
3971
+ setSelectedElementId(elementId);
3972
+ setSelectedElementIds([]);
3973
+ },
3974
+ [setActiveSlideIndex, setSelectedElementId, setSelectedElementIds]
3975
+ );
3976
+ return { slideSelectionRef, showSlideSelection };
3977
+ }
3978
+ function useClearSelectionOnSlideChange(state, activeSlideIndex) {
3979
+ useEffect(() => {
3980
+ const kept = state.slideSelectionRef.current === activeSlideIndex;
3981
+ state.slideSelectionRef.current = null;
3982
+ state.setInlineEditingElementId(null);
3983
+ if (kept) {
3984
+ return;
3985
+ }
3986
+ state.setSelectedElementId(null);
3987
+ state.setSelectedElementIds([]);
3988
+ }, [activeSlideIndex]);
3989
+ }
3940
3990
  function useSlideState() {
3941
3991
  const [renderedSlides, setRenderedSlides] = useState([]);
3942
3992
  const slidesRef = useRef(renderedSlides);
@@ -3976,6 +4026,11 @@ function useViewerCoreState(_input) {
3976
4026
  const [activeSlideIndex, setActiveSlideIndex] = useState(0);
3977
4027
  const [selectedElementId, setSelectedElementId] = useState(null);
3978
4028
  const [selectedElementIds, setSelectedElementIds] = useState([]);
4029
+ const slideChangeSelection = useSlideChangeSelection({
4030
+ setActiveSlideIndex,
4031
+ setSelectedElementId,
4032
+ setSelectedElementIds
4033
+ });
3979
4034
  const [isDirty, setIsDirty] = useState(false);
3980
4035
  const autosaveDraftSinkRef = useRef(null);
3981
4036
  const publishInlineText = useCallback(
@@ -4079,6 +4134,7 @@ function useViewerCoreState(_input) {
4079
4134
  setSelectedElementId,
4080
4135
  selectedElementIds,
4081
4136
  setSelectedElementIds,
4137
+ ...slideChangeSelection,
4082
4138
  isDirty,
4083
4139
  setIsDirty,
4084
4140
  editTemplateMode,
@@ -6886,7 +6942,7 @@ function useSlideManagement(input) {
6886
6942
  async (updated) => {
6887
6943
  const templateElements = await handler.getTemplateElementsForSlide(updated.id).catch(() => []);
6888
6944
  ops.updateSlides((prev) => {
6889
- if (prev[insertAt]?.id !== draft.id) {
6945
+ if (insertedLayoutCompletion(prev[insertAt], draft) !== "replace") {
6890
6946
  return prev;
6891
6947
  }
6892
6948
  const next = [...prev];
@@ -7406,24 +7462,25 @@ async function copySlideToClipboard(slideElement, options = {}) {
7406
7462
  const blob = await exportSlideToPngBlob(slideElement, options);
7407
7463
  await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
7408
7464
  }
7409
- async function captureAllSlidesAsPngDataUrls(slideStageRef, totalSlides, setActiveSlide, currentSlideIndex, options = {}) {
7465
+ async function captureSlidesAsPngDataUrls(slideStageRef, slideIndices, setActiveSlide, currentSlideIndex, options = {}) {
7410
7466
  const { scale = 2, onProgress } = options;
7411
- const dataUrls = [];
7412
- for (let i = 0; i < totalSlides; i++) {
7413
- onProgress?.(i, totalSlides);
7414
- setActiveSlide(i);
7467
+ const total = slideIndices.length;
7468
+ const captures = [];
7469
+ for (const [position, slideIndex] of slideIndices.entries()) {
7470
+ onProgress?.(position, total);
7471
+ setActiveSlide(slideIndex);
7415
7472
  await waitForRender(150);
7416
7473
  const stageEl = slideStageRef.current;
7417
7474
  if (!stageEl) {
7418
- console.warn(`[export] Could not find slide stage element for slide ${i}`);
7475
+ console.warn(`[export] Could not find slide stage element for slide ${slideIndex}`);
7419
7476
  continue;
7420
7477
  }
7421
7478
  const { canvas } = await renderElementToTiledCanvas(stageEl, scale);
7422
- dataUrls.push(canvas.toDataURL("image/png"));
7479
+ captures.push({ slideIndex, dataUrl: canvas.toDataURL("image/png") });
7423
7480
  }
7424
- onProgress?.(totalSlides, totalSlides);
7481
+ onProgress?.(total, total);
7425
7482
  setActiveSlide(currentSlideIndex);
7426
- return dataUrls;
7483
+ return captures;
7427
7484
  }
7428
7485
  function tilesToPdfPage(tilesResult) {
7429
7486
  return tilesResult.tiles.map((tile) => ({
@@ -7663,35 +7720,12 @@ function injectFontFaces(svg, fontFaces) {
7663
7720
  }
7664
7721
  return `${svg.slice(0, closingBracket + 1)}<defs>${styleBlock}</defs>${svg.slice(closingBracket + 1)}`;
7665
7722
  }
7666
- function exportAllSlidesToSvg(data, options = {}) {
7667
- const { onProgress, embedFonts, fontFaces } = options;
7668
- const svgOptions = {
7669
- includeHidden: options.includeHidden,
7670
- slideIndices: options.slideIndices,
7671
- defaultFontFamily: options.defaultFontFamily,
7672
- defaultFontSize: options.defaultFontSize
7673
- };
7674
- const results = [];
7675
- const includeHidden = svgOptions.includeHidden ?? false;
7676
- let processedCount = 0;
7677
- for (let i = 0; i < data.slides.length; i++) {
7678
- if (svgOptions.slideIndices && !svgOptions.slideIndices.includes(i)) {
7679
- continue;
7680
- }
7681
- const slide = data.slides[i];
7682
- if (slide.hidden && !includeHidden) {
7683
- continue;
7684
- }
7685
- onProgress?.(processedCount, data.slides.length);
7686
- let svg = SvgExporter.exportSlide(slide, data.width, data.height, svgOptions);
7687
- if (embedFonts && fontFaces?.length) {
7688
- svg = injectFontFaces(svg, fontFaces);
7689
- }
7690
- results.push(svg);
7691
- processedCount++;
7723
+ function exportSlideToSvg(slide, width, height, options = {}) {
7724
+ let svg = SvgExporter.exportSlide(slide, width, height, options);
7725
+ if (options.embedFonts && options.fontFaces?.length) {
7726
+ svg = injectFontFaces(svg, options.fontFaces);
7692
7727
  }
7693
- onProgress?.(processedCount, data.slides.length);
7694
- return results;
7728
+ return svg;
7695
7729
  }
7696
7730
  function safePrompt(message, defaultValue) {
7697
7731
  try {
@@ -8100,161 +8134,95 @@ function useViewerOptionsContext() {
8100
8134
  }
8101
8135
 
8102
8136
  // src/viewer/hooks/usePrintHandlers.ts
8137
+ var BLOCKED_WARNING = "[PowerPointViewer] Print window was blocked by the browser. Allow popups for this site to print.";
8103
8138
  function usePrintHandlers(input) {
8104
- const { slides, activeSlideIndex, canvasStageRef, setActiveSlideIndex, pptxData } = input;
8139
+ const { slides, activeSlideIndex, canvasStageRef, setActiveSlideIndex, canvasSize } = input;
8140
+ const handoutMaster = input.handoutMaster ?? input.pptxData?.handoutMaster;
8105
8141
  const [isPrintDialogOpen, setIsPrintDialogOpen] = useState(false);
8106
8142
  const { t } = useTranslation();
8107
8143
  const viewerOptions = useViewerOptionsContext();
8108
- const includeHiddenSlides = viewerOptions.advanced.printHiddenSlides;
8109
8144
  const printRasterScale = (viewerOptions.advanced.printHighQuality ? 4 : 3) * resolveImageResolutionScale(viewerOptions);
8110
8145
  const handlePrint = () => {
8111
8146
  setIsPrintDialogOpen(true);
8112
8147
  };
8113
- const handlePrintSvg = async (settings) => {
8114
- setIsPrintDialogOpen(false);
8115
- const printWindow = openPendingPrintWindow(t("pptx.print.preparingToPrint"));
8116
- if (!printWindow) {
8117
- console.warn(
8118
- "[PowerPointViewer] Print window was blocked by the browser. Allow popups for this site to print."
8119
- );
8120
- return;
8121
- }
8122
- if (!pptxData || settings.printWhat !== "slides") {
8123
- return runRasterPrint(printWindow, settings);
8124
- }
8125
- const colorFilter = computeColorFilter(settings.colorMode);
8126
- const slideIndices = filterHiddenSlideIndices(
8127
- computeSlideIndices(
8128
- settings.slideRange,
8129
- activeSlideIndex,
8130
- slides.length,
8131
- settings.customRangeFrom,
8132
- settings.customRangeTo
8133
- ),
8134
- slides,
8135
- includeHiddenSlides
8136
- );
8137
- try {
8138
- const svgs = exportAllSlidesToSvg(pptxData, {
8139
- slideIndices
8140
- });
8141
- if (svgs.length === 0) {
8142
- printWindow.close();
8143
- return;
8144
- }
8145
- const printDoc = buildPrintDocument(svgs, pptxData.width, pptxData.height, {
8146
- title: "Slides (Vector)",
8147
- orientation: settings.orientation,
8148
- colorFilter,
8149
- scaleToFit: settings.scaleToFit
8150
- });
8151
- finishPrintWindow(printWindow, printDoc);
8152
- } catch (err) {
8153
- console.warn("[PowerPointViewer] SVG print path failed, falling back to raster:", err);
8154
- return runRasterPrint(printWindow, settings);
8155
- }
8156
- };
8157
- const runRasterPrint = async (printWindow, settings) => {
8158
- const colorFilter = computeColorFilter(settings.colorMode);
8159
- const slideIndices = filterHiddenSlideIndices(
8160
- computeSlideIndices(
8161
- settings.slideRange,
8162
- activeSlideIndex,
8163
- slides.length,
8164
- settings.customRangeFrom,
8165
- settings.customRangeTo
8166
- ),
8167
- slides,
8168
- includeHiddenSlides
8169
- );
8170
- if (settings.printWhat === "outline") {
8171
- finishPrintWindow(
8172
- printWindow,
8173
- buildPrintHtmlDocument({
8174
- title: "Outline",
8175
- bodyHtml: `<div class="outline-page">${buildOutlineHtml(slideIndices, slides)}</div>`,
8176
- orientation: settings.orientation,
8177
- colorFilter,
8178
- frameSlides: settings.frameSlides,
8179
- scaleToFit: settings.scaleToFit
8180
- })
8181
- );
8182
- return;
8183
- }
8148
+ const deckSlides = () => input.templateElementsBySlideId ? buildSaveSlides(slides, input.templateElementsBySlideId) : slides;
8149
+ const plan = (settings, deck) => planPrintJob(settings, {
8150
+ slides: deck,
8151
+ activeSlideIndex,
8152
+ // Options > Advanced > "Print hidden slides".
8153
+ includeHiddenSlides: viewerOptions.advanced.printHiddenSlides
8154
+ });
8155
+ const title = (job) => t(job.title.key, job.title.params);
8156
+ const runRasterPrint = async (printWindow, job, deck) => {
8184
8157
  try {
8185
8158
  if (!canvasStageRef.current) {
8186
8159
  printWindow.close();
8187
8160
  return;
8188
8161
  }
8189
- const allImages = await captureAllSlidesAsPngDataUrls(
8162
+ const captures = await captureSlidesAsPngDataUrls(
8190
8163
  canvasStageRef,
8191
- slides.length,
8164
+ job.slideIndices,
8192
8165
  setActiveSlideIndex,
8193
8166
  activeSlideIndex,
8194
8167
  { scale: printRasterScale }
8195
8168
  );
8196
- if (allImages.length === 0) {
8169
+ if (captures.length === 0) {
8197
8170
  printWindow.close();
8198
8171
  return;
8199
8172
  }
8200
- const slideImages = slideIndices.map((idx) => allImages[idx]).filter(Boolean);
8201
- if (settings.printWhat === "slides") {
8202
- finishPrintWindow(
8203
- printWindow,
8204
- buildPrintHtmlDocument({
8205
- title: "Slides",
8206
- bodyHtml: buildSlidesHtml(slideImages, slideIndices),
8207
- orientation: settings.orientation,
8208
- colorFilter,
8209
- frameSlides: settings.frameSlides,
8210
- scaleToFit: settings.scaleToFit
8211
- })
8212
- );
8213
- return;
8214
- }
8215
- if (settings.printWhat === "notes") {
8216
- finishPrintWindow(
8217
- printWindow,
8218
- buildPrintHtmlDocument({
8219
- title: "Notes Pages",
8220
- bodyHtml: buildNotesHtml(slideImages, slideIndices, slides),
8221
- orientation: "portrait",
8222
- colorFilter,
8223
- frameSlides: settings.frameSlides,
8224
- scaleToFit: settings.scaleToFit
8225
- })
8226
- );
8227
- return;
8228
- }
8229
- if (settings.printWhat === "handouts") {
8230
- const spp = settings.slidesPerPage;
8231
- finishPrintWindow(
8232
- printWindow,
8233
- buildPrintHtmlDocument({
8234
- title: `Handout ${spp} per page`,
8235
- bodyHtml: buildHandoutsHtml(slideImages, slideIndices, spp, pptxData?.handoutMaster),
8236
- orientation: "portrait",
8237
- colorFilter,
8238
- frameSlides: settings.frameSlides,
8239
- scaleToFit: settings.scaleToFit
8240
- })
8241
- );
8242
- }
8173
+ finishPrintWindow(
8174
+ printWindow,
8175
+ buildRasterPrintJobDocument(job, title(job), captures, deck, handoutMaster)
8176
+ );
8243
8177
  } catch (err) {
8244
8178
  console.error("[PowerPointViewer] Print layout failed:", err);
8179
+ printWindow.close();
8245
8180
  }
8246
8181
  };
8247
- const handlePrintWithSettings = async (settings) => {
8248
- setIsPrintDialogOpen(false);
8182
+ const openNow = (html) => {
8183
+ if (!openPrintWindow(html)) {
8184
+ console.warn(BLOCKED_WARNING);
8185
+ }
8186
+ };
8187
+ const startRasterPrint = async (job, deck) => {
8249
8188
  const printWindow = openPendingPrintWindow(t("pptx.print.preparingToPrint"));
8250
8189
  if (!printWindow) {
8251
- console.warn(
8252
- "[PowerPointViewer] Print window was blocked by the browser. Allow popups for this site to print."
8190
+ console.warn(BLOCKED_WARNING);
8191
+ return;
8192
+ }
8193
+ await runRasterPrint(printWindow, job, deck);
8194
+ };
8195
+ const vectorDocument = (job, deck) => {
8196
+ try {
8197
+ const svgs = job.slideIndices.map(
8198
+ (index) => exportSlideToSvg(deck[index], canvasSize.width, canvasSize.height)
8253
8199
  );
8200
+ return buildVectorPrintJobDocument(job, title(job), svgs, canvasSize);
8201
+ } catch (err) {
8202
+ console.warn("[PowerPointViewer] SVG print path failed, falling back to raster:", err);
8203
+ return void 0;
8204
+ }
8205
+ };
8206
+ const runPrintJob = async (settings, vector) => {
8207
+ setIsPrintDialogOpen(false);
8208
+ const deck = deckSlides();
8209
+ const job = plan(settings, deck);
8210
+ if (!job.ok) {
8211
+ return;
8212
+ }
8213
+ if (job.output === "outline") {
8214
+ openNow(buildOutlinePrintJobDocument(job, title(job), deck));
8215
+ return;
8216
+ }
8217
+ const html = vector && job.output === "vector" ? vectorDocument(job, deck) : void 0;
8218
+ if (html !== void 0) {
8219
+ openNow(html);
8254
8220
  return;
8255
8221
  }
8256
- return runRasterPrint(printWindow, settings);
8222
+ await startRasterPrint(printJobRasterFallback(job), deck);
8257
8223
  };
8224
+ const handlePrintSvg = (settings) => runPrintJob(settings, true);
8225
+ const handlePrintWithSettings = (settings) => runPrintJob(settings, false);
8258
8226
  return {
8259
8227
  handlePrint,
8260
8228
  handlePrintWithSettings,
@@ -8263,6 +8231,27 @@ function usePrintHandlers(input) {
8263
8231
  setIsPrintDialogOpen
8264
8232
  };
8265
8233
  }
8234
+ async function applyThemePartInPlace(input, themePath, applyToAllMasters) {
8235
+ const change = await applyThemeByPath(input.handlerRef.current, {
8236
+ themePath,
8237
+ applyToAllMasters,
8238
+ slides: input.slides,
8239
+ slideMasters: input.slideMasters,
8240
+ theme: input.theme,
8241
+ templateElementsBySlideId: input.templateElementsBySlideId
8242
+ });
8243
+ if (!change) {
8244
+ return;
8245
+ }
8246
+ input.bumpHistory();
8247
+ input.setSlides(change.slides);
8248
+ input.setTemplateElementsBySlideId(change.templateElementsBySlideId);
8249
+ input.setSlideMasters(change.slideMasters);
8250
+ if (change.deckTheme) {
8251
+ input.setTheme(change.deckTheme.theme);
8252
+ }
8253
+ input.history.markDirty();
8254
+ }
8266
8255
  async function applyThemeEditorEdit(input, { colorScheme, fontScheme, name }) {
8267
8256
  const {
8268
8257
  handlerRef,
@@ -8277,7 +8266,7 @@ async function applyThemeEditorEdit(input, { colorScheme, fontScheme, name }) {
8277
8266
  if (!handler) {
8278
8267
  return;
8279
8268
  }
8280
- await handler.applyTheme(colorScheme, fontScheme, name);
8269
+ await queueThemeWrite(handler, () => handler.applyTheme(colorScheme, fontScheme, name));
8281
8270
  const previousMap = theme?.colorScheme ? buildThemeColorMap(theme.colorScheme) : {};
8282
8271
  bumpHistory();
8283
8272
  setSlides(
@@ -8303,14 +8292,27 @@ async function applyThemeEditorEdit(input, { colorScheme, fontScheme, name }) {
8303
8292
  setTheme((prev) => ({ ...prev, colorScheme, fontScheme, name }));
8304
8293
  history.markDirty();
8305
8294
  }
8295
+ function restoreHistoryTheme(input, target) {
8296
+ const masters = input.slideMasters;
8297
+ const current = historyTheme(input.theme, masters);
8298
+ input.setTheme((prev) => withHistoryTheme(prev, target));
8299
+ if (target.masterThemePaths) {
8300
+ input.setSlideMasters(
8301
+ (prev) => withHistoryMasterThemes(prev, target)
8302
+ );
8303
+ }
8304
+ return writeThemeParts(
8305
+ input.handlerRef.current,
8306
+ current,
8307
+ target,
8308
+ loadedThemeName(input.themeOptions, input.slideMasters)
8309
+ );
8310
+ }
8306
8311
 
8307
8312
  // src/viewer/hooks/useThemeHandlers.ts
8308
8313
  function useThemeHandlers(input) {
8309
8314
  const {
8310
8315
  handlerRef,
8311
- serializeSlides,
8312
- setContent,
8313
- onContentChange,
8314
8316
  setTheme,
8315
8317
  setSlideMasters,
8316
8318
  slideMasters,
@@ -8321,36 +8323,13 @@ function useThemeHandlers(input) {
8321
8323
  theme,
8322
8324
  bumpHistory
8323
8325
  } = input;
8324
- const refreshContentAfterThemeChange = async () => {
8325
- const updated = await serializeSlides();
8326
- if (!updated) {
8327
- return;
8328
- }
8329
- setContent(updated);
8330
- if (onContentChange) {
8331
- onContentChange(updated);
8332
- }
8333
- history.markDirty();
8334
- };
8335
- const handleApplyTheme = async (themePath, applyToAllMasters) => {
8336
- const handler = handlerRef.current;
8337
- if (!handler) {
8338
- return;
8339
- }
8340
- await handler.setPresentationTheme(themePath, applyToAllMasters);
8341
- setSlideMasters(
8342
- (prev) => prev.map(
8343
- (master, index) => applyToAllMasters || index === 0 ? { ...master, themePath } : master
8344
- )
8345
- );
8346
- await refreshContentAfterThemeChange();
8347
- };
8326
+ const handleApplyTheme = (themePath, applyToAllMasters) => applyThemePartInPlace(input, themePath, applyToAllMasters);
8348
8327
  const handleUpdateThemeColorScheme = async (colorScheme) => {
8349
8328
  const handler = handlerRef.current;
8350
8329
  if (!handler) {
8351
8330
  return;
8352
8331
  }
8353
- await handler.updateThemeColorScheme(colorScheme);
8332
+ await queueThemeWrite(handler, () => handler.updateThemeColorScheme(colorScheme));
8354
8333
  const previousMap = theme?.colorScheme ? buildThemeColorMap(theme.colorScheme) : {};
8355
8334
  setSlides((prev) => reResolveSlideColors(prev, previousMap, colorScheme));
8356
8335
  if (Object.keys(templateElementsBySlideId).length > 0) {
@@ -8371,7 +8350,7 @@ function useThemeHandlers(input) {
8371
8350
  if (!handler) {
8372
8351
  return;
8373
8352
  }
8374
- await handler.updateThemeFontScheme(fontScheme);
8353
+ await queueThemeWrite(handler, () => handler.updateThemeFontScheme(fontScheme));
8375
8354
  const previousFonts = theme?.fontScheme;
8376
8355
  bumpHistory();
8377
8356
  setSlides((prev) => reResolveSlideFonts(prev, previousFonts, fontScheme));
@@ -8391,20 +8370,15 @@ function useThemeHandlers(input) {
8391
8370
  if (!handler) {
8392
8371
  return;
8393
8372
  }
8394
- await handler.updateThemeName(name);
8373
+ await queueThemeWrite(handler, () => handler.updateThemeName(name));
8395
8374
  setTheme((prev) => prev ? { ...prev, name } : { name });
8396
8375
  history.markDirty();
8397
8376
  };
8398
8377
  const handleApplyThemeToPresentation = async () => {
8399
- const handler = handlerRef.current;
8400
- if (!handler) {
8401
- return;
8402
- }
8403
8378
  const primaryThemePath = slideMasters[0]?.themePath;
8404
8379
  if (primaryThemePath) {
8405
- await handler.setPresentationTheme(primaryThemePath, true);
8380
+ await applyThemePartInPlace(input, primaryThemePath, true);
8406
8381
  }
8407
- await refreshContentAfterThemeChange();
8408
8382
  };
8409
8383
  const handleApplyThemeData = (colorScheme, fontScheme, themeName) => applyThemeEditorEdit(input, { colorScheme, fontScheme, name: themeName ?? theme?.name ?? "" });
8410
8384
  const handleSetTemplateBackground = (path, backgroundColor) => {
@@ -8432,16 +8406,9 @@ function useThemeHandlers(input) {
8432
8406
  }
8433
8407
  return handler.getAvailableThemes();
8434
8408
  };
8435
- const handleSwitchTheme = async (themePath) => {
8436
- const handler = handlerRef.current;
8437
- if (!handler) {
8438
- return;
8439
- }
8440
- await handler.setPresentationTheme(themePath, true);
8441
- setSlideMasters((prev) => prev.map((master) => ({ ...master, themePath })));
8442
- await refreshContentAfterThemeChange();
8443
- };
8409
+ const handleSwitchTheme = (themePath) => applyThemePartInPlace(input, themePath, true);
8444
8410
  const handleApplyThemeEdit = (edit) => applyThemeEditorEdit(input, edit);
8411
+ const handleRestoreHistoryTheme = (target) => restoreHistoryTheme(input, target);
8445
8412
  return {
8446
8413
  handleApplyThemeEdit,
8447
8414
  handleApplyTheme,
@@ -8450,6 +8417,7 @@ function useThemeHandlers(input) {
8450
8417
  handleUpdateThemeName,
8451
8418
  handleApplyThemeToPresentation,
8452
8419
  handleApplyThemeData,
8420
+ handleRestoreHistoryTheme,
8453
8421
  handleSetTemplateBackground,
8454
8422
  handleGetTemplateBackgroundColor,
8455
8423
  handleGetAvailableThemes,
@@ -9820,8 +9788,7 @@ function useEditorOperations(input) {
9820
9788
  const findReplace = useFindReplace({
9821
9789
  slides,
9822
9790
  mode,
9823
- onSetActiveSlideIndex: state.setActiveSlideIndex,
9824
- onSetSelectedElementId: state.setSelectedElementId,
9791
+ onShowMatch: state.showSlideSelection,
9825
9792
  onUpdateSlides: ops.updateSlides,
9826
9793
  onMarkDirty: history.markDirty,
9827
9794
  keyboard
@@ -10026,9 +9993,7 @@ function useIOHandlers(input) {
10026
9993
  zoom,
10027
9994
  handlerRef,
10028
9995
  serializeSlides,
10029
- serializeForRecovery,
10030
9996
  setContent,
10031
- onContentChange,
10032
9997
  onPropertiesChange,
10033
9998
  onNotesUpdate,
10034
9999
  imageExportScale,
@@ -10065,19 +10030,19 @@ function useIOHandlers(input) {
10065
10030
  slides,
10066
10031
  activeSlideIndex,
10067
10032
  canvasStageRef: zoom.canvasStageRef,
10068
- setActiveSlideIndex: state.setActiveSlideIndex
10033
+ setActiveSlideIndex: state.setActiveSlideIndex,
10034
+ canvasSize,
10035
+ templateElementsBySlideId: state.templateElementsBySlideId,
10036
+ handoutMaster: state.handoutMaster
10069
10037
  });
10070
10038
  const themeHandlers = useThemeHandlers({
10071
10039
  handlerRef,
10072
- // Theme apply re-serialises and re-parses through `setContent`, so these
10073
- // bytes go back into our own loader: plaintext, never the protected save.
10074
- serializeSlides: serializeForRecovery,
10075
- setContent,
10076
- onContentChange,
10077
10040
  setTheme: state.setTheme,
10078
10041
  setSlideMasters: state.setSlideMasters,
10079
10042
  slideMasters: state.slideMasters,
10043
+ themeOptions: state.themeOptions,
10080
10044
  history,
10045
+ slides,
10081
10046
  setSlides: state.setSlides,
10082
10047
  templateElementsBySlideId: state.templateElementsBySlideId,
10083
10048
  setTemplateElementsBySlideId: state.setTemplateElementsBySlideId,
@@ -10131,7 +10096,12 @@ function isFontDataUrlSafe(url) {
10131
10096
  }
10132
10097
  return FONT_DATA_URL_PATTERN.test(url);
10133
10098
  }
10134
- function useFontInjection({ embeddedFonts, slides }) {
10099
+ function useFontInjection({
10100
+ embeddedFonts,
10101
+ slides,
10102
+ googleFonts
10103
+ }) {
10104
+ const googleFontsBase = resolveGoogleFontsCss2Base(googleFonts);
10135
10105
  useEffect(() => {
10136
10106
  if (!embeddedFonts.length) {
10137
10107
  return;
@@ -10173,17 +10143,19 @@ function useFontInjection({ embeddedFonts, slides }) {
10173
10143
  const referencedFamilies = useMemo(() => collectReferencedFontFamilies(slides), [slides]);
10174
10144
  useEffect(() => {
10175
10145
  let cancelled = false;
10176
- void resolveGoogleWebfontHref(slides, embeddedFonts).then((href) => {
10177
- if (cancelled) {
10178
- return null;
10146
+ void resolveGoogleWebfontHref(slides, embeddedFonts, void 0, googleFontsBase).then(
10147
+ (href) => {
10148
+ if (cancelled) {
10149
+ return null;
10150
+ }
10151
+ syncGoogleWebfontStylesheet(document, GOOGLE_FONTS_LINK_ID, href);
10152
+ return href;
10179
10153
  }
10180
- syncGoogleWebfontStylesheet(document, GOOGLE_FONTS_LINK_ID, href);
10181
- return href;
10182
- });
10154
+ );
10183
10155
  return () => {
10184
10156
  cancelled = true;
10185
10157
  };
10186
- }, [embeddedFonts, slides]);
10158
+ }, [embeddedFonts, slides, googleFontsBase]);
10187
10159
  useEffect(() => () => document.getElementById(GOOGLE_FONTS_LINK_ID)?.remove(), []);
10188
10160
  const [, setOutlineFontsTick] = useState(0);
10189
10161
  useEffect(() => {
@@ -10196,41 +10168,43 @@ function useFontInjection({ embeddedFonts, slides }) {
10196
10168
  if (candidates.length === 0) {
10197
10169
  return;
10198
10170
  }
10199
- void resolveGoogleWebfontHref(slides, embeddedFonts).then(async (href) => {
10200
- if (cancelled || !href) {
10201
- return;
10202
- }
10203
- const boldItalicVariants = [
10204
- { bold: false, italic: false },
10205
- { bold: true, italic: false }
10206
- ];
10207
- let registeredAny = false;
10208
- for (const family of candidates) {
10209
- for (const variant of boldItalicVariants) {
10210
- if (cancelled) {
10211
- return;
10212
- }
10213
- const bytes = await fetchGoogleWebfontOutlineBytes(
10214
- href,
10215
- family,
10216
- variant.bold,
10217
- variant.italic,
10218
- fetch
10219
- );
10220
- if (bytes && glyphOutlineFontCache.registerFontBytes(family, variant.bold, variant.italic, bytes)) {
10221
- registeredAny = true;
10171
+ void resolveGoogleWebfontHref(slides, embeddedFonts, void 0, googleFontsBase).then(
10172
+ async (href) => {
10173
+ if (cancelled || !href) {
10174
+ return;
10175
+ }
10176
+ const boldItalicVariants = [
10177
+ { bold: false, italic: false },
10178
+ { bold: true, italic: false }
10179
+ ];
10180
+ let registeredAny = false;
10181
+ for (const family of candidates) {
10182
+ for (const variant of boldItalicVariants) {
10183
+ if (cancelled) {
10184
+ return;
10185
+ }
10186
+ const bytes = await fetchGoogleWebfontOutlineBytes(
10187
+ href,
10188
+ family,
10189
+ variant.bold,
10190
+ variant.italic,
10191
+ fetch
10192
+ );
10193
+ if (bytes && glyphOutlineFontCache.registerFontBytes(family, variant.bold, variant.italic, bytes)) {
10194
+ registeredAny = true;
10195
+ }
10222
10196
  }
10223
10197
  }
10198
+ if (registeredAny && !cancelled) {
10199
+ setOutlineFontsTick((tick) => tick + 1);
10200
+ }
10201
+ return void 0;
10224
10202
  }
10225
- if (registeredAny && !cancelled) {
10226
- setOutlineFontsTick((tick) => tick + 1);
10227
- }
10228
- return void 0;
10229
- });
10203
+ );
10230
10204
  return () => {
10231
10205
  cancelled = true;
10232
10206
  };
10233
- }, [embeddedFonts, slides]);
10207
+ }, [embeddedFonts, slides, googleFontsBase]);
10234
10208
  useEffect(() => {
10235
10209
  const neededSymbolFonts = SYMBOL_FONT_FAMILIES.filter((f) => referencedFamilies.has(f));
10236
10210
  if (neededSymbolFonts.length === 0) {
@@ -10278,6 +10252,7 @@ function useContentLifecycle(input) {
10278
10252
  onContentApplied,
10279
10253
  allowExternalImages,
10280
10254
  initialSlide,
10255
+ googleFonts,
10281
10256
  setReadOnlyRecommendation,
10282
10257
  setModifyVerifier,
10283
10258
  setCompatToasts
@@ -10334,7 +10309,7 @@ function useContentLifecycle(input) {
10334
10309
  useEffect(() => {
10335
10310
  actionSoundHandlerRef.current = handlerRef.current;
10336
10311
  }, [handlerRef, actionSoundHandlerRef, state.loading]);
10337
- useFontInjection({ embeddedFonts: state.embeddedFonts, slides });
10312
+ useFontInjection({ embeddedFonts: state.embeddedFonts, slides, googleFonts });
10338
10313
  const serializeInput = {
10339
10314
  slides,
10340
10315
  templateElementsBySlideId: state.templateElementsBySlideId,
@@ -10690,6 +10665,7 @@ function useViewerIntegration(input) {
10690
10665
  autosaveIntervalMs,
10691
10666
  allowExternalImages,
10692
10667
  initialSlide,
10668
+ googleFonts,
10693
10669
  setReadOnlyRecommendation,
10694
10670
  setModifyVerifier,
10695
10671
  setCompatToasts,
@@ -10754,32 +10730,31 @@ function useViewerIntegration(input) {
10754
10730
  });
10755
10731
  const [isEncryptedDialogOpen, setIsEncryptedDialogOpen] = useState(false);
10756
10732
  const [loadVersion, setLoadVersion] = useState(0);
10757
- const { handlerRef, serializeSlides, serializeForRecovery, autosaveStatus } = useContentLifecycle(
10758
- {
10759
- content,
10760
- filePath,
10761
- storage,
10762
- autosaveEnabled,
10763
- autosaveIntervalMs,
10764
- onAutosave,
10765
- // The File > Fonts toggle, finally reaching a save call.
10766
- embedFonts: dialogs.embedFontsEnabled,
10767
- slides,
10768
- state,
10769
- history,
10770
- ops: editorOps.ops,
10771
- transformCommittedText: input.transformCommittedText,
10772
- actionSoundHandlerRef,
10773
- setIsEncryptedDialogOpen,
10774
- password: dialogs.presentationPassword ?? void 0,
10775
- onContentApplied: () => setLoadVersion((v) => v + 1),
10776
- allowExternalImages,
10777
- initialSlide,
10778
- setReadOnlyRecommendation,
10779
- setModifyVerifier,
10780
- setCompatToasts
10781
- }
10782
- );
10733
+ const { handlerRef, serializeSlides, autosaveStatus } = useContentLifecycle({
10734
+ content,
10735
+ filePath,
10736
+ storage,
10737
+ autosaveEnabled,
10738
+ autosaveIntervalMs,
10739
+ onAutosave,
10740
+ // The File > Fonts toggle, finally reaching a save call.
10741
+ embedFonts: dialogs.embedFontsEnabled,
10742
+ slides,
10743
+ state,
10744
+ history,
10745
+ ops: editorOps.ops,
10746
+ transformCommittedText: input.transformCommittedText,
10747
+ actionSoundHandlerRef,
10748
+ setIsEncryptedDialogOpen,
10749
+ password: dialogs.presentationPassword ?? void 0,
10750
+ onContentApplied: () => setLoadVersion((v) => v + 1),
10751
+ allowExternalImages,
10752
+ initialSlide,
10753
+ googleFonts,
10754
+ setReadOnlyRecommendation,
10755
+ setModifyVerifier,
10756
+ setCompatToasts
10757
+ });
10783
10758
  const { exportHandlers, printHandlers, themeHandlers, propertyHandlers } = useIOHandlers({
10784
10759
  state,
10785
10760
  slides,
@@ -10793,9 +10768,7 @@ function useViewerIntegration(input) {
10793
10768
  zoom,
10794
10769
  handlerRef,
10795
10770
  serializeSlides,
10796
- serializeForRecovery,
10797
10771
  setContent,
10798
- onContentChange,
10799
10772
  onPropertiesChange,
10800
10773
  onNotesUpdate,
10801
10774
  imageExportScale,
@@ -11608,11 +11581,9 @@ function useLayoutSwitching(input) {
11608
11581
  }
11609
11582
  setIsLoading(true);
11610
11583
  try {
11611
- const updated = await handler.applyLayoutToSlide(
11612
- activeSlideIndex,
11613
- layoutPath,
11614
- slidesRef.current
11615
- );
11584
+ const updated = await handler.applyLayoutToSlide(activeSlideIndex, layoutPath, [
11585
+ ...slidesRef.current
11586
+ ]);
11616
11587
  ops.updateSlides((prev) => {
11617
11588
  const next = [...prev];
11618
11589
  next[activeSlideIndex] = updated;
@@ -12833,7 +12804,7 @@ function useViewPreferencesSync(input) {
12833
12804
  // src/viewer/hooks/useViewerBuildingBlocksState.ts
12834
12805
  function useViewerBuildingBlocksState(input) {
12835
12806
  const { core, content, canEdit, filePath, autosaveEnabled, userName, handle, setContent } = input;
12836
- const { initialSlide } = input;
12807
+ const { initialSlide, googleFonts } = input;
12837
12808
  const {
12838
12809
  onContentChange,
12839
12810
  onDirtyChange,
@@ -12891,11 +12862,7 @@ function useViewerBuildingBlocksState(input) {
12891
12862
  });
12892
12863
  const readOnlyRec = useReadOnlyRecommendationState(content);
12893
12864
  const compatToastsState = useCompatibilityToastsState();
12894
- useEffect(() => {
12895
- state.setSelectedElementId(null);
12896
- state.setSelectedElementIds([]);
12897
- state.setInlineEditingElementId(null);
12898
- }, [activeSlideIndex]);
12865
+ useClearSelectionOnSlideChange(state, activeSlideIndex);
12899
12866
  const editorOps = useEditorOperations({
12900
12867
  state,
12901
12868
  history,
@@ -12937,6 +12904,7 @@ function useViewerBuildingBlocksState(input) {
12937
12904
  filePath,
12938
12905
  autosaveEnabled,
12939
12906
  initialSlide,
12907
+ googleFonts,
12940
12908
  // Trust Center > "Allow external content": same gate `PowerPointViewer`
12941
12909
  // applies, so the headless building-blocks API loads http(s) images
12942
12910
  // under the same default-off, core-side SSRF/privacy guard.
@@ -13001,6 +12969,7 @@ function useViewerBuildingBlocks(input) {
13001
12969
  filePath,
13002
12970
  fileName,
13003
12971
  initialSlide,
12972
+ googleFonts,
13004
12973
  autosaveEnabled = true,
13005
12974
  userName,
13006
12975
  hiddenActions,
@@ -13089,6 +13058,7 @@ function useViewerBuildingBlocks(input) {
13089
13058
  canEdit,
13090
13059
  filePath,
13091
13060
  initialSlide,
13061
+ googleFonts,
13092
13062
  autosaveEnabled,
13093
13063
  userName,
13094
13064
  handle,
@@ -18693,4 +18663,4 @@ function useResizablePanels() {
18693
18663
  };
18694
18664
  }
18695
18665
 
18696
- export { ACTION_VERB_MAP, ChartFormatContext, ChartPartSelectionProvider, CollaborationCursorOverlay, CollaborationProvider, ElementRenderer, FragmentedTransitionLayer, InlineCollaborationContext, MIN_TOUCH_TARGET, MorphTransitionOverlay, PresentationTransitionOverlay, RemoteSelectionOverlay, RemoteUserCursors, Rendering3DFlagsContext, ResizeHandles, SlideBackgroundImageLayer, SlideLayer, StaticElementRenderer, ViewerOptionsContext, ViewerOptionsStoreContext, computeToolbarVisibility, createReviewCommentsHost, detectTargetType, imgSrc, isAudienceTab, parseAudienceNonce, parseEmailUrl, parseSlideFromUrl, playAnimationSound, renderStrokeView, renderToCanvas, resolveSmartArtDataPalette, safePrompt, scopeLayoutOptionsToActiveSlide, useAnimationPlayback, useAnnotationHandlers, useAudienceMode, useAutosave, useBroadcastFollower, useCanvasInteractions, useChartFormatContext, useChartPartSelection, useClipboardHandlers, useCollaboration, useCollaborationDocumentSync, useCollaborativeHistory, useCollaborativeState, useComments, useCompatibilityToastsState, useContentLifecycle, useController, 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, useReportOnChange, 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, withDisplayName };
18666
+ export { ACTION_VERB_MAP, ChartFormatContext, ChartPartSelectionProvider, CollaborationCursorOverlay, CollaborationProvider, ElementRenderer, FragmentedTransitionLayer, InlineCollaborationContext, MIN_TOUCH_TARGET, MorphTransitionOverlay, PresentationTransitionOverlay, RemoteSelectionOverlay, RemoteUserCursors, Rendering3DFlagsContext, ResizeHandles, SlideBackgroundImageLayer, SlideLayer, StaticElementRenderer, ViewerOptionsContext, ViewerOptionsStoreContext, computeToolbarVisibility, createReviewCommentsHost, detectTargetType, imgSrc, isAudienceTab, parseAudienceNonce, parseEmailUrl, parseSlideFromUrl, playAnimationSound, renderStrokeView, renderToCanvas, resolveSmartArtDataPalette, safePrompt, scopeLayoutOptionsToActiveSlide, useAnimationPlayback, useAnnotationHandlers, useAudienceMode, useAutosave, useBroadcastFollower, useCanvasInteractions, useChartFormatContext, useChartPartSelection, useClearSelectionOnSlideChange, useClipboardHandlers, useCollaboration, useCollaborationDocumentSync, useCollaborativeHistory, useCollaborativeState, useComments, useCompatibilityToastsState, useContentLifecycle, useController, 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, useReportOnChange, 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, withDisplayName };