pptx-react-viewer 4.51.1 → 4.52.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 (87) hide show
  1. package/CHANGELOG.md +63 -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-V4DY4IWP.mjs → chunk-3KXEJCMG.mjs} +283 -300
  9. package/dist/chunk-3KXEJCMG.mjs.br +0 -0
  10. package/dist/chunk-3KXEJCMG.mjs.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-YJ4DAS4V.js → chunk-6GAWXARM.js} +479 -496
  15. package/dist/chunk-6GAWXARM.js.br +0 -0
  16. package/dist/chunk-6GAWXARM.js.gz +0 -0
  17. package/dist/{chunk-KCUXY7DE.mjs → chunk-E6A6ZBAM.mjs} +49 -69
  18. package/dist/chunk-E6A6ZBAM.mjs.br +0 -0
  19. package/dist/chunk-E6A6ZBAM.mjs.gz +0 -0
  20. package/dist/{chunk-VRX5NJY2.js → chunk-I63IFSNX.js} +597 -617
  21. package/dist/chunk-I63IFSNX.js.br +0 -0
  22. package/dist/chunk-I63IFSNX.js.gz +0 -0
  23. package/dist/{chunk-ZCGYPCZM.mjs → chunk-ID37Y3HG.mjs} +4 -1
  24. package/dist/chunk-ID37Y3HG.mjs.br +0 -0
  25. package/dist/chunk-ID37Y3HG.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 +13 -1
  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 +59 -17
  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, 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, 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) => {
@@ -704,11 +730,25 @@ function useEditorHistory(input) {
704
730
  setEditCommitNonce((previous) => previous + 1);
705
731
  onDirtyRef.current?.();
706
732
  }, []);
733
+ const onRestoreThemeRef = useRef(onRestoreTheme);
734
+ useEffect(() => {
735
+ onRestoreThemeRef.current = onRestoreTheme;
736
+ }, [onRestoreTheme]);
737
+ const restoreTheme = useCallback(
738
+ (current, target) => {
739
+ const crossed = crossedHistoryTheme(current.theme, target.theme);
740
+ if (crossed) {
741
+ onRestoreThemeRef.current?.(crossed);
742
+ }
743
+ },
744
+ []
745
+ );
707
746
  const handleUndo = useCallback(() => {
708
747
  if (!history.getSnapshot().canUndo) {
709
748
  return;
710
749
  }
711
- const result = history.undo(buildHistorySnapshot());
750
+ const currentSnapshot = buildHistorySnapshot();
751
+ const result = history.undo(currentSnapshot);
712
752
  if (!result) {
713
753
  return;
714
754
  }
@@ -717,14 +757,23 @@ function useEditorHistory(input) {
717
757
  lastHistorySnapshotRef.current = cloneHistorySnapshot(nextSnapshot);
718
758
  lastHistorySerializedRef.current = serializeHistoryDocument(nextSnapshot);
719
759
  applyHistorySnapshot(nextSnapshot);
760
+ restoreTheme(currentSnapshot, nextSnapshot);
720
761
  unlockHistoryTracking();
721
762
  markDirty();
722
- }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
763
+ }, [
764
+ applyHistorySnapshot,
765
+ buildHistorySnapshot,
766
+ history,
767
+ markDirty,
768
+ restoreTheme,
769
+ unlockHistoryTracking
770
+ ]);
723
771
  const handleRedo = useCallback(() => {
724
772
  if (!history.getSnapshot().canRedo) {
725
773
  return;
726
774
  }
727
- const result = history.redo(buildHistorySnapshot());
775
+ const currentSnapshot = buildHistorySnapshot();
776
+ const result = history.redo(currentSnapshot);
728
777
  if (!result) {
729
778
  return;
730
779
  }
@@ -733,9 +782,17 @@ function useEditorHistory(input) {
733
782
  lastHistorySnapshotRef.current = cloneHistorySnapshot(targetSnapshot);
734
783
  lastHistorySerializedRef.current = serializeHistoryDocument(targetSnapshot);
735
784
  applyHistorySnapshot(targetSnapshot);
785
+ restoreTheme(currentSnapshot, targetSnapshot);
736
786
  unlockHistoryTracking();
737
787
  markDirty();
738
- }, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
788
+ }, [
789
+ applyHistorySnapshot,
790
+ buildHistorySnapshot,
791
+ history,
792
+ markDirty,
793
+ restoreTheme,
794
+ unlockHistoryTracking
795
+ ]);
739
796
  const resetHistory = useCallback(
740
797
  (initialSnapshot) => {
741
798
  history.clear();
@@ -787,7 +844,7 @@ function useEditorHistory(input) {
787
844
  return;
788
845
  }
789
846
  const previousSnapshot = lastHistorySnapshotRef.current;
790
- if (!previousSnapshot) {
847
+ if (!previousSnapshot || differsOnlyInMasterSet(previousSnapshot, snapshot)) {
791
848
  lastHistorySnapshotRef.current = snapshot;
792
849
  lastHistorySerializedRef.current = serialized;
793
850
  lastCheapHashRef.current = cheapHash;
@@ -813,9 +870,15 @@ function useEditorHistory(input) {
813
870
  pointerReleaseNonce,
814
871
  slides
815
872
  ]);
816
- const commitSlides = (nextSlides, label, beforeSlides = slides) => {
873
+ const commitSlides = (nextSlides, label, beforeSlides = slides, nextSlideMasters) => {
817
874
  const before = { ...buildHistorySnapshot(), slides: beforeSlides.map(cloneSlide) };
818
- const after = { ...before, slides: nextSlides.map(cloneSlide) };
875
+ const { theme: beforeTheme, ...unthemed } = before;
876
+ const afterTheme = nextSlideMasters ? historyTheme(theme, nextSlideMasters) : beforeTheme;
877
+ const after = {
878
+ ...unthemed,
879
+ slides: nextSlides.map(cloneSlide),
880
+ ...afterTheme ? { theme: afterTheme } : {}
881
+ };
819
882
  recordExplicitSlideUpdate(history, lastHistorySnapshotRef.current, before, label);
820
883
  lastHistorySnapshotRef.current = cloneHistorySnapshot(after);
821
884
  lastHistorySerializedRef.current = serializeHistoryDocument(after);
@@ -836,6 +899,7 @@ function useEditorHistory(input) {
836
899
  handleUndo,
837
900
  handleRedo,
838
901
  resetHistory,
902
+ forgetHistory: history.forget,
839
903
  markDirty,
840
904
  buildHistorySnapshot
841
905
  };
@@ -6886,7 +6950,7 @@ function useSlideManagement(input) {
6886
6950
  async (updated) => {
6887
6951
  const templateElements = await handler.getTemplateElementsForSlide(updated.id).catch(() => []);
6888
6952
  ops.updateSlides((prev) => {
6889
- if (prev[insertAt]?.id !== draft.id) {
6953
+ if (insertedLayoutCompletion(prev[insertAt], draft) !== "replace") {
6890
6954
  return prev;
6891
6955
  }
6892
6956
  const next = [...prev];
@@ -7406,24 +7470,25 @@ async function copySlideToClipboard(slideElement, options = {}) {
7406
7470
  const blob = await exportSlideToPngBlob(slideElement, options);
7407
7471
  await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
7408
7472
  }
7409
- async function captureAllSlidesAsPngDataUrls(slideStageRef, totalSlides, setActiveSlide, currentSlideIndex, options = {}) {
7473
+ async function captureSlidesAsPngDataUrls(slideStageRef, slideIndices, setActiveSlide, currentSlideIndex, options = {}) {
7410
7474
  const { scale = 2, onProgress } = options;
7411
- const dataUrls = [];
7412
- for (let i = 0; i < totalSlides; i++) {
7413
- onProgress?.(i, totalSlides);
7414
- setActiveSlide(i);
7475
+ const total = slideIndices.length;
7476
+ const captures = [];
7477
+ for (const [position, slideIndex] of slideIndices.entries()) {
7478
+ onProgress?.(position, total);
7479
+ setActiveSlide(slideIndex);
7415
7480
  await waitForRender(150);
7416
7481
  const stageEl = slideStageRef.current;
7417
7482
  if (!stageEl) {
7418
- console.warn(`[export] Could not find slide stage element for slide ${i}`);
7483
+ console.warn(`[export] Could not find slide stage element for slide ${slideIndex}`);
7419
7484
  continue;
7420
7485
  }
7421
7486
  const { canvas } = await renderElementToTiledCanvas(stageEl, scale);
7422
- dataUrls.push(canvas.toDataURL("image/png"));
7487
+ captures.push({ slideIndex, dataUrl: canvas.toDataURL("image/png") });
7423
7488
  }
7424
- onProgress?.(totalSlides, totalSlides);
7489
+ onProgress?.(total, total);
7425
7490
  setActiveSlide(currentSlideIndex);
7426
- return dataUrls;
7491
+ return captures;
7427
7492
  }
7428
7493
  function tilesToPdfPage(tilesResult) {
7429
7494
  return tilesResult.tiles.map((tile) => ({
@@ -7663,35 +7728,12 @@ function injectFontFaces(svg, fontFaces) {
7663
7728
  }
7664
7729
  return `${svg.slice(0, closingBracket + 1)}<defs>${styleBlock}</defs>${svg.slice(closingBracket + 1)}`;
7665
7730
  }
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++;
7731
+ function exportSlideToSvg(slide, width, height, options = {}) {
7732
+ let svg = SvgExporter.exportSlide(slide, width, height, options);
7733
+ if (options.embedFonts && options.fontFaces?.length) {
7734
+ svg = injectFontFaces(svg, options.fontFaces);
7692
7735
  }
7693
- onProgress?.(processedCount, data.slides.length);
7694
- return results;
7736
+ return svg;
7695
7737
  }
7696
7738
  function safePrompt(message, defaultValue) {
7697
7739
  try {
@@ -8100,161 +8142,95 @@ function useViewerOptionsContext() {
8100
8142
  }
8101
8143
 
8102
8144
  // src/viewer/hooks/usePrintHandlers.ts
8145
+ var BLOCKED_WARNING = "[PowerPointViewer] Print window was blocked by the browser. Allow popups for this site to print.";
8103
8146
  function usePrintHandlers(input) {
8104
- const { slides, activeSlideIndex, canvasStageRef, setActiveSlideIndex, pptxData } = input;
8147
+ const { slides, activeSlideIndex, canvasStageRef, setActiveSlideIndex, canvasSize } = input;
8148
+ const handoutMaster = input.handoutMaster ?? input.pptxData?.handoutMaster;
8105
8149
  const [isPrintDialogOpen, setIsPrintDialogOpen] = useState(false);
8106
8150
  const { t } = useTranslation();
8107
8151
  const viewerOptions = useViewerOptionsContext();
8108
- const includeHiddenSlides = viewerOptions.advanced.printHiddenSlides;
8109
8152
  const printRasterScale = (viewerOptions.advanced.printHighQuality ? 4 : 3) * resolveImageResolutionScale(viewerOptions);
8110
8153
  const handlePrint = () => {
8111
8154
  setIsPrintDialogOpen(true);
8112
8155
  };
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
- }
8156
+ const deckSlides = () => input.templateElementsBySlideId ? buildSaveSlides(slides, input.templateElementsBySlideId) : slides;
8157
+ const plan = (settings, deck) => planPrintJob(settings, {
8158
+ slides: deck,
8159
+ activeSlideIndex,
8160
+ // Options > Advanced > "Print hidden slides".
8161
+ includeHiddenSlides: viewerOptions.advanced.printHiddenSlides
8162
+ });
8163
+ const title = (job) => t(job.title.key, job.title.params);
8164
+ const runRasterPrint = async (printWindow, job, deck) => {
8184
8165
  try {
8185
8166
  if (!canvasStageRef.current) {
8186
8167
  printWindow.close();
8187
8168
  return;
8188
8169
  }
8189
- const allImages = await captureAllSlidesAsPngDataUrls(
8170
+ const captures = await captureSlidesAsPngDataUrls(
8190
8171
  canvasStageRef,
8191
- slides.length,
8172
+ job.slideIndices,
8192
8173
  setActiveSlideIndex,
8193
8174
  activeSlideIndex,
8194
8175
  { scale: printRasterScale }
8195
8176
  );
8196
- if (allImages.length === 0) {
8177
+ if (captures.length === 0) {
8197
8178
  printWindow.close();
8198
8179
  return;
8199
8180
  }
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
- }
8181
+ finishPrintWindow(
8182
+ printWindow,
8183
+ buildRasterPrintJobDocument(job, title(job), captures, deck, handoutMaster)
8184
+ );
8243
8185
  } catch (err) {
8244
8186
  console.error("[PowerPointViewer] Print layout failed:", err);
8187
+ printWindow.close();
8245
8188
  }
8246
8189
  };
8247
- const handlePrintWithSettings = async (settings) => {
8248
- setIsPrintDialogOpen(false);
8190
+ const openNow = (html) => {
8191
+ if (!openPrintWindow(html)) {
8192
+ console.warn(BLOCKED_WARNING);
8193
+ }
8194
+ };
8195
+ const startRasterPrint = async (job, deck) => {
8249
8196
  const printWindow = openPendingPrintWindow(t("pptx.print.preparingToPrint"));
8250
8197
  if (!printWindow) {
8251
- console.warn(
8252
- "[PowerPointViewer] Print window was blocked by the browser. Allow popups for this site to print."
8198
+ console.warn(BLOCKED_WARNING);
8199
+ return;
8200
+ }
8201
+ await runRasterPrint(printWindow, job, deck);
8202
+ };
8203
+ const vectorDocument = (job, deck) => {
8204
+ try {
8205
+ const svgs = job.slideIndices.map(
8206
+ (index) => exportSlideToSvg(deck[index], canvasSize.width, canvasSize.height)
8253
8207
  );
8208
+ return buildVectorPrintJobDocument(job, title(job), svgs, canvasSize);
8209
+ } catch (err) {
8210
+ console.warn("[PowerPointViewer] SVG print path failed, falling back to raster:", err);
8211
+ return void 0;
8212
+ }
8213
+ };
8214
+ const runPrintJob = async (settings, vector) => {
8215
+ setIsPrintDialogOpen(false);
8216
+ const deck = deckSlides();
8217
+ const job = plan(settings, deck);
8218
+ if (!job.ok) {
8254
8219
  return;
8255
8220
  }
8256
- return runRasterPrint(printWindow, settings);
8221
+ if (job.output === "outline") {
8222
+ openNow(buildOutlinePrintJobDocument(job, title(job), deck));
8223
+ return;
8224
+ }
8225
+ const html = vector && job.output === "vector" ? vectorDocument(job, deck) : void 0;
8226
+ if (html !== void 0) {
8227
+ openNow(html);
8228
+ return;
8229
+ }
8230
+ await startRasterPrint(printJobRasterFallback(job), deck);
8257
8231
  };
8232
+ const handlePrintSvg = (settings) => runPrintJob(settings, true);
8233
+ const handlePrintWithSettings = (settings) => runPrintJob(settings, false);
8258
8234
  return {
8259
8235
  handlePrint,
8260
8236
  handlePrintWithSettings,
@@ -8263,6 +8239,27 @@ function usePrintHandlers(input) {
8263
8239
  setIsPrintDialogOpen
8264
8240
  };
8265
8241
  }
8242
+ async function applyThemePartInPlace(input, themePath, applyToAllMasters) {
8243
+ const change = await applyThemeByPath(input.handlerRef.current, {
8244
+ themePath,
8245
+ applyToAllMasters,
8246
+ slides: input.slides,
8247
+ slideMasters: input.slideMasters,
8248
+ theme: input.theme,
8249
+ templateElementsBySlideId: input.templateElementsBySlideId
8250
+ });
8251
+ if (!change) {
8252
+ return;
8253
+ }
8254
+ input.bumpHistory();
8255
+ input.setSlides(change.slides);
8256
+ input.setTemplateElementsBySlideId(change.templateElementsBySlideId);
8257
+ input.setSlideMasters(change.slideMasters);
8258
+ if (change.deckTheme) {
8259
+ input.setTheme(change.deckTheme.theme);
8260
+ }
8261
+ input.history.markDirty();
8262
+ }
8266
8263
  async function applyThemeEditorEdit(input, { colorScheme, fontScheme, name }) {
8267
8264
  const {
8268
8265
  handlerRef,
@@ -8277,7 +8274,7 @@ async function applyThemeEditorEdit(input, { colorScheme, fontScheme, name }) {
8277
8274
  if (!handler) {
8278
8275
  return;
8279
8276
  }
8280
- await handler.applyTheme(colorScheme, fontScheme, name);
8277
+ await queueThemeWrite(handler, () => handler.applyTheme(colorScheme, fontScheme, name));
8281
8278
  const previousMap = theme?.colorScheme ? buildThemeColorMap(theme.colorScheme) : {};
8282
8279
  bumpHistory();
8283
8280
  setSlides(
@@ -8303,14 +8300,27 @@ async function applyThemeEditorEdit(input, { colorScheme, fontScheme, name }) {
8303
8300
  setTheme((prev) => ({ ...prev, colorScheme, fontScheme, name }));
8304
8301
  history.markDirty();
8305
8302
  }
8303
+ function restoreHistoryTheme(input, target) {
8304
+ const masters = input.slideMasters;
8305
+ const current = historyTheme(input.theme, masters);
8306
+ input.setTheme((prev) => withHistoryTheme(prev, target));
8307
+ if (target.masterThemePaths) {
8308
+ input.setSlideMasters(
8309
+ (prev) => withHistoryMasterThemes(prev, target)
8310
+ );
8311
+ }
8312
+ return writeThemeParts(
8313
+ input.handlerRef.current,
8314
+ current,
8315
+ target,
8316
+ loadedThemeName(input.themeOptions, input.slideMasters)
8317
+ );
8318
+ }
8306
8319
 
8307
8320
  // src/viewer/hooks/useThemeHandlers.ts
8308
8321
  function useThemeHandlers(input) {
8309
8322
  const {
8310
8323
  handlerRef,
8311
- serializeSlides,
8312
- setContent,
8313
- onContentChange,
8314
8324
  setTheme,
8315
8325
  setSlideMasters,
8316
8326
  slideMasters,
@@ -8321,36 +8331,13 @@ function useThemeHandlers(input) {
8321
8331
  theme,
8322
8332
  bumpHistory
8323
8333
  } = 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
- };
8334
+ const handleApplyTheme = (themePath, applyToAllMasters) => applyThemePartInPlace(input, themePath, applyToAllMasters);
8348
8335
  const handleUpdateThemeColorScheme = async (colorScheme) => {
8349
8336
  const handler = handlerRef.current;
8350
8337
  if (!handler) {
8351
8338
  return;
8352
8339
  }
8353
- await handler.updateThemeColorScheme(colorScheme);
8340
+ await queueThemeWrite(handler, () => handler.updateThemeColorScheme(colorScheme));
8354
8341
  const previousMap = theme?.colorScheme ? buildThemeColorMap(theme.colorScheme) : {};
8355
8342
  setSlides((prev) => reResolveSlideColors(prev, previousMap, colorScheme));
8356
8343
  if (Object.keys(templateElementsBySlideId).length > 0) {
@@ -8371,7 +8358,7 @@ function useThemeHandlers(input) {
8371
8358
  if (!handler) {
8372
8359
  return;
8373
8360
  }
8374
- await handler.updateThemeFontScheme(fontScheme);
8361
+ await queueThemeWrite(handler, () => handler.updateThemeFontScheme(fontScheme));
8375
8362
  const previousFonts = theme?.fontScheme;
8376
8363
  bumpHistory();
8377
8364
  setSlides((prev) => reResolveSlideFonts(prev, previousFonts, fontScheme));
@@ -8391,20 +8378,15 @@ function useThemeHandlers(input) {
8391
8378
  if (!handler) {
8392
8379
  return;
8393
8380
  }
8394
- await handler.updateThemeName(name);
8381
+ await queueThemeWrite(handler, () => handler.updateThemeName(name));
8395
8382
  setTheme((prev) => prev ? { ...prev, name } : { name });
8396
8383
  history.markDirty();
8397
8384
  };
8398
8385
  const handleApplyThemeToPresentation = async () => {
8399
- const handler = handlerRef.current;
8400
- if (!handler) {
8401
- return;
8402
- }
8403
8386
  const primaryThemePath = slideMasters[0]?.themePath;
8404
8387
  if (primaryThemePath) {
8405
- await handler.setPresentationTheme(primaryThemePath, true);
8388
+ await applyThemePartInPlace(input, primaryThemePath, true);
8406
8389
  }
8407
- await refreshContentAfterThemeChange();
8408
8390
  };
8409
8391
  const handleApplyThemeData = (colorScheme, fontScheme, themeName) => applyThemeEditorEdit(input, { colorScheme, fontScheme, name: themeName ?? theme?.name ?? "" });
8410
8392
  const handleSetTemplateBackground = (path, backgroundColor) => {
@@ -8432,16 +8414,9 @@ function useThemeHandlers(input) {
8432
8414
  }
8433
8415
  return handler.getAvailableThemes();
8434
8416
  };
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
- };
8417
+ const handleSwitchTheme = (themePath) => applyThemePartInPlace(input, themePath, true);
8444
8418
  const handleApplyThemeEdit = (edit) => applyThemeEditorEdit(input, edit);
8419
+ const handleRestoreHistoryTheme = (target) => restoreHistoryTheme(input, target);
8445
8420
  return {
8446
8421
  handleApplyThemeEdit,
8447
8422
  handleApplyTheme,
@@ -8450,6 +8425,7 @@ function useThemeHandlers(input) {
8450
8425
  handleUpdateThemeName,
8451
8426
  handleApplyThemeToPresentation,
8452
8427
  handleApplyThemeData,
8428
+ handleRestoreHistoryTheme,
8453
8429
  handleSetTemplateBackground,
8454
8430
  handleGetTemplateBackgroundColor,
8455
8431
  handleGetAvailableThemes,
@@ -10026,9 +10002,7 @@ function useIOHandlers(input) {
10026
10002
  zoom,
10027
10003
  handlerRef,
10028
10004
  serializeSlides,
10029
- serializeForRecovery,
10030
10005
  setContent,
10031
- onContentChange,
10032
10006
  onPropertiesChange,
10033
10007
  onNotesUpdate,
10034
10008
  imageExportScale,
@@ -10065,19 +10039,19 @@ function useIOHandlers(input) {
10065
10039
  slides,
10066
10040
  activeSlideIndex,
10067
10041
  canvasStageRef: zoom.canvasStageRef,
10068
- setActiveSlideIndex: state.setActiveSlideIndex
10042
+ setActiveSlideIndex: state.setActiveSlideIndex,
10043
+ canvasSize,
10044
+ templateElementsBySlideId: state.templateElementsBySlideId,
10045
+ handoutMaster: state.handoutMaster
10069
10046
  });
10070
10047
  const themeHandlers = useThemeHandlers({
10071
10048
  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
10049
  setTheme: state.setTheme,
10078
10050
  setSlideMasters: state.setSlideMasters,
10079
10051
  slideMasters: state.slideMasters,
10052
+ themeOptions: state.themeOptions,
10080
10053
  history,
10054
+ slides,
10081
10055
  setSlides: state.setSlides,
10082
10056
  templateElementsBySlideId: state.templateElementsBySlideId,
10083
10057
  setTemplateElementsBySlideId: state.setTemplateElementsBySlideId,
@@ -10131,7 +10105,12 @@ function isFontDataUrlSafe(url) {
10131
10105
  }
10132
10106
  return FONT_DATA_URL_PATTERN.test(url);
10133
10107
  }
10134
- function useFontInjection({ embeddedFonts, slides }) {
10108
+ function useFontInjection({
10109
+ embeddedFonts,
10110
+ slides,
10111
+ googleFonts
10112
+ }) {
10113
+ const googleFontsBase = resolveGoogleFontsCss2Base(googleFonts);
10135
10114
  useEffect(() => {
10136
10115
  if (!embeddedFonts.length) {
10137
10116
  return;
@@ -10173,17 +10152,19 @@ function useFontInjection({ embeddedFonts, slides }) {
10173
10152
  const referencedFamilies = useMemo(() => collectReferencedFontFamilies(slides), [slides]);
10174
10153
  useEffect(() => {
10175
10154
  let cancelled = false;
10176
- void resolveGoogleWebfontHref(slides, embeddedFonts).then((href) => {
10177
- if (cancelled) {
10178
- return null;
10155
+ void resolveGoogleWebfontHref(slides, embeddedFonts, void 0, googleFontsBase).then(
10156
+ (href) => {
10157
+ if (cancelled) {
10158
+ return null;
10159
+ }
10160
+ syncGoogleWebfontStylesheet(document, GOOGLE_FONTS_LINK_ID, href);
10161
+ return href;
10179
10162
  }
10180
- syncGoogleWebfontStylesheet(document, GOOGLE_FONTS_LINK_ID, href);
10181
- return href;
10182
- });
10163
+ );
10183
10164
  return () => {
10184
10165
  cancelled = true;
10185
10166
  };
10186
- }, [embeddedFonts, slides]);
10167
+ }, [embeddedFonts, slides, googleFontsBase]);
10187
10168
  useEffect(() => () => document.getElementById(GOOGLE_FONTS_LINK_ID)?.remove(), []);
10188
10169
  const [, setOutlineFontsTick] = useState(0);
10189
10170
  useEffect(() => {
@@ -10196,41 +10177,43 @@ function useFontInjection({ embeddedFonts, slides }) {
10196
10177
  if (candidates.length === 0) {
10197
10178
  return;
10198
10179
  }
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;
10180
+ void resolveGoogleWebfontHref(slides, embeddedFonts, void 0, googleFontsBase).then(
10181
+ async (href) => {
10182
+ if (cancelled || !href) {
10183
+ return;
10184
+ }
10185
+ const boldItalicVariants = [
10186
+ { bold: false, italic: false },
10187
+ { bold: true, italic: false }
10188
+ ];
10189
+ let registeredAny = false;
10190
+ for (const family of candidates) {
10191
+ for (const variant of boldItalicVariants) {
10192
+ if (cancelled) {
10193
+ return;
10194
+ }
10195
+ const bytes = await fetchGoogleWebfontOutlineBytes(
10196
+ href,
10197
+ family,
10198
+ variant.bold,
10199
+ variant.italic,
10200
+ fetch
10201
+ );
10202
+ if (bytes && glyphOutlineFontCache.registerFontBytes(family, variant.bold, variant.italic, bytes)) {
10203
+ registeredAny = true;
10204
+ }
10222
10205
  }
10223
10206
  }
10207
+ if (registeredAny && !cancelled) {
10208
+ setOutlineFontsTick((tick) => tick + 1);
10209
+ }
10210
+ return void 0;
10224
10211
  }
10225
- if (registeredAny && !cancelled) {
10226
- setOutlineFontsTick((tick) => tick + 1);
10227
- }
10228
- return void 0;
10229
- });
10212
+ );
10230
10213
  return () => {
10231
10214
  cancelled = true;
10232
10215
  };
10233
- }, [embeddedFonts, slides]);
10216
+ }, [embeddedFonts, slides, googleFontsBase]);
10234
10217
  useEffect(() => {
10235
10218
  const neededSymbolFonts = SYMBOL_FONT_FAMILIES.filter((f) => referencedFamilies.has(f));
10236
10219
  if (neededSymbolFonts.length === 0) {
@@ -10278,6 +10261,7 @@ function useContentLifecycle(input) {
10278
10261
  onContentApplied,
10279
10262
  allowExternalImages,
10280
10263
  initialSlide,
10264
+ googleFonts,
10281
10265
  setReadOnlyRecommendation,
10282
10266
  setModifyVerifier,
10283
10267
  setCompatToasts
@@ -10334,7 +10318,7 @@ function useContentLifecycle(input) {
10334
10318
  useEffect(() => {
10335
10319
  actionSoundHandlerRef.current = handlerRef.current;
10336
10320
  }, [handlerRef, actionSoundHandlerRef, state.loading]);
10337
- useFontInjection({ embeddedFonts: state.embeddedFonts, slides });
10321
+ useFontInjection({ embeddedFonts: state.embeddedFonts, slides, googleFonts });
10338
10322
  const serializeInput = {
10339
10323
  slides,
10340
10324
  templateElementsBySlideId: state.templateElementsBySlideId,
@@ -10690,6 +10674,7 @@ function useViewerIntegration(input) {
10690
10674
  autosaveIntervalMs,
10691
10675
  allowExternalImages,
10692
10676
  initialSlide,
10677
+ googleFonts,
10693
10678
  setReadOnlyRecommendation,
10694
10679
  setModifyVerifier,
10695
10680
  setCompatToasts,
@@ -10754,32 +10739,31 @@ function useViewerIntegration(input) {
10754
10739
  });
10755
10740
  const [isEncryptedDialogOpen, setIsEncryptedDialogOpen] = useState(false);
10756
10741
  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
- );
10742
+ const { handlerRef, serializeSlides, autosaveStatus } = useContentLifecycle({
10743
+ content,
10744
+ filePath,
10745
+ storage,
10746
+ autosaveEnabled,
10747
+ autosaveIntervalMs,
10748
+ onAutosave,
10749
+ // The File > Fonts toggle, finally reaching a save call.
10750
+ embedFonts: dialogs.embedFontsEnabled,
10751
+ slides,
10752
+ state,
10753
+ history,
10754
+ ops: editorOps.ops,
10755
+ transformCommittedText: input.transformCommittedText,
10756
+ actionSoundHandlerRef,
10757
+ setIsEncryptedDialogOpen,
10758
+ password: dialogs.presentationPassword ?? void 0,
10759
+ onContentApplied: () => setLoadVersion((v) => v + 1),
10760
+ allowExternalImages,
10761
+ initialSlide,
10762
+ googleFonts,
10763
+ setReadOnlyRecommendation,
10764
+ setModifyVerifier,
10765
+ setCompatToasts
10766
+ });
10783
10767
  const { exportHandlers, printHandlers, themeHandlers, propertyHandlers } = useIOHandlers({
10784
10768
  state,
10785
10769
  slides,
@@ -10793,9 +10777,7 @@ function useViewerIntegration(input) {
10793
10777
  zoom,
10794
10778
  handlerRef,
10795
10779
  serializeSlides,
10796
- serializeForRecovery,
10797
10780
  setContent,
10798
- onContentChange,
10799
10781
  onPropertiesChange,
10800
10782
  onNotesUpdate,
10801
10783
  imageExportScale,
@@ -11608,11 +11590,9 @@ function useLayoutSwitching(input) {
11608
11590
  }
11609
11591
  setIsLoading(true);
11610
11592
  try {
11611
- const updated = await handler.applyLayoutToSlide(
11612
- activeSlideIndex,
11613
- layoutPath,
11614
- slidesRef.current
11615
- );
11593
+ const updated = await handler.applyLayoutToSlide(activeSlideIndex, layoutPath, [
11594
+ ...slidesRef.current
11595
+ ]);
11616
11596
  ops.updateSlides((prev) => {
11617
11597
  const next = [...prev];
11618
11598
  next[activeSlideIndex] = updated;
@@ -12833,7 +12813,7 @@ function useViewPreferencesSync(input) {
12833
12813
  // src/viewer/hooks/useViewerBuildingBlocksState.ts
12834
12814
  function useViewerBuildingBlocksState(input) {
12835
12815
  const { core, content, canEdit, filePath, autosaveEnabled, userName, handle, setContent } = input;
12836
- const { initialSlide } = input;
12816
+ const { initialSlide, googleFonts } = input;
12837
12817
  const {
12838
12818
  onContentChange,
12839
12819
  onDirtyChange,
@@ -12937,6 +12917,7 @@ function useViewerBuildingBlocksState(input) {
12937
12917
  filePath,
12938
12918
  autosaveEnabled,
12939
12919
  initialSlide,
12920
+ googleFonts,
12940
12921
  // Trust Center > "Allow external content": same gate `PowerPointViewer`
12941
12922
  // applies, so the headless building-blocks API loads http(s) images
12942
12923
  // under the same default-off, core-side SSRF/privacy guard.
@@ -13001,6 +12982,7 @@ function useViewerBuildingBlocks(input) {
13001
12982
  filePath,
13002
12983
  fileName,
13003
12984
  initialSlide,
12985
+ googleFonts,
13004
12986
  autosaveEnabled = true,
13005
12987
  userName,
13006
12988
  hiddenActions,
@@ -13089,6 +13071,7 @@ function useViewerBuildingBlocks(input) {
13089
13071
  canEdit,
13090
13072
  filePath,
13091
13073
  initialSlide,
13074
+ googleFonts,
13092
13075
  autosaveEnabled,
13093
13076
  userName,
13094
13077
  handle,