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.
- package/CHANGELOG.md +63 -0
- package/dist/{AiChatPanel-EV22O7UO.js → AiChatPanel-7GJQ66GR.js} +19 -19
- package/dist/AiChatPanel-7GJQ66GR.js.br +0 -0
- package/dist/AiChatPanel-7GJQ66GR.js.gz +0 -0
- package/dist/{AiChatPanel-R323KNGN.mjs → AiChatPanel-AI75AT6C.mjs} +1 -1
- package/dist/AiChatPanel-AI75AT6C.mjs.br +0 -0
- package/dist/AiChatPanel-AI75AT6C.mjs.gz +0 -0
- package/dist/{chunk-V4DY4IWP.mjs → chunk-3KXEJCMG.mjs} +283 -300
- package/dist/chunk-3KXEJCMG.mjs.br +0 -0
- package/dist/chunk-3KXEJCMG.mjs.gz +0 -0
- package/dist/{chunk-Z22RD3E2.js → chunk-3TN5SUQR.js} +4 -1
- package/dist/chunk-3TN5SUQR.js.br +0 -0
- package/dist/chunk-3TN5SUQR.js.gz +0 -0
- package/dist/{chunk-YJ4DAS4V.js → chunk-6GAWXARM.js} +479 -496
- package/dist/chunk-6GAWXARM.js.br +0 -0
- package/dist/chunk-6GAWXARM.js.gz +0 -0
- package/dist/{chunk-KCUXY7DE.mjs → chunk-E6A6ZBAM.mjs} +49 -69
- package/dist/chunk-E6A6ZBAM.mjs.br +0 -0
- package/dist/chunk-E6A6ZBAM.mjs.gz +0 -0
- package/dist/{chunk-VRX5NJY2.js → chunk-I63IFSNX.js} +597 -617
- package/dist/chunk-I63IFSNX.js.br +0 -0
- package/dist/chunk-I63IFSNX.js.gz +0 -0
- package/dist/{chunk-ZCGYPCZM.mjs → chunk-ID37Y3HG.mjs} +4 -1
- package/dist/chunk-ID37Y3HG.mjs.br +0 -0
- package/dist/chunk-ID37Y3HG.mjs.gz +0 -0
- package/dist/i18n/de.cjs +1 -24
- package/dist/i18n/de.cjs.br +0 -0
- package/dist/i18n/de.cjs.gz +0 -0
- package/dist/i18n/de.mjs +1 -24
- package/dist/i18n/de.mjs.br +0 -0
- package/dist/i18n/de.mjs.gz +0 -0
- package/dist/i18n/es.cjs +1 -24
- package/dist/i18n/es.cjs.br +0 -0
- package/dist/i18n/es.cjs.gz +0 -0
- package/dist/i18n/es.mjs +1 -24
- package/dist/i18n/es.mjs.br +0 -0
- package/dist/i18n/es.mjs.gz +0 -0
- package/dist/i18n/fr.cjs +1 -24
- package/dist/i18n/fr.cjs.br +0 -0
- package/dist/i18n/fr.cjs.gz +0 -0
- package/dist/i18n/fr.mjs +1 -24
- package/dist/i18n/fr.mjs.br +0 -0
- package/dist/i18n/fr.mjs.gz +0 -0
- package/dist/i18n/zh-CN.cjs +0 -23
- package/dist/i18n/zh-CN.cjs.br +0 -0
- package/dist/i18n/zh-CN.cjs.gz +0 -0
- package/dist/i18n/zh-CN.mjs +0 -23
- package/dist/i18n/zh-CN.mjs.br +0 -0
- package/dist/i18n/zh-CN.mjs.gz +0 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.js +25 -25
- package/dist/index.js.br +0 -0
- package/dist/index.js.gz +0 -0
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.br +0 -0
- package/dist/index.mjs.gz +0 -0
- package/dist/internals.d.ts +59 -17
- package/dist/internals.js +81 -81
- package/dist/internals.js.br +0 -0
- package/dist/internals.js.gz +0 -0
- package/dist/internals.mjs +2 -2
- package/dist/internals.mjs.br +0 -0
- package/dist/internals.mjs.gz +0 -0
- package/dist/viewer/index.d.ts +13 -1
- package/dist/viewer/index.js +20 -20
- package/dist/viewer/index.js.br +0 -0
- package/dist/viewer/index.js.gz +0 -0
- package/dist/viewer/index.mjs +3 -3
- package/dist/viewer/index.mjs.br +0 -0
- package/dist/viewer/index.mjs.gz +0 -0
- package/package.json +3 -3
- package/dist/AiChatPanel-EV22O7UO.js.br +0 -0
- package/dist/AiChatPanel-EV22O7UO.js.gz +0 -0
- package/dist/AiChatPanel-R323KNGN.mjs.br +0 -0
- package/dist/AiChatPanel-R323KNGN.mjs.gz +0 -0
- package/dist/chunk-KCUXY7DE.mjs.br +0 -0
- package/dist/chunk-KCUXY7DE.mjs.gz +0 -0
- package/dist/chunk-V4DY4IWP.mjs.br +0 -0
- package/dist/chunk-V4DY4IWP.mjs.gz +0 -0
- package/dist/chunk-VRX5NJY2.js.br +0 -0
- package/dist/chunk-VRX5NJY2.js.gz +0 -0
- package/dist/chunk-YJ4DAS4V.js.br +0 -0
- package/dist/chunk-YJ4DAS4V.js.gz +0 -0
- package/dist/chunk-Z22RD3E2.js.br +0 -0
- package/dist/chunk-Z22RD3E2.js.gz +0 -0
- package/dist/chunk-ZCGYPCZM.mjs.br +0 -0
- 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-
|
|
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,
|
|
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
|
|
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
|
-
}, [
|
|
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
|
|
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
|
-
}, [
|
|
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
|
|
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]
|
|
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
|
|
7473
|
+
async function captureSlidesAsPngDataUrls(slideStageRef, slideIndices, setActiveSlide, currentSlideIndex, options = {}) {
|
|
7410
7474
|
const { scale = 2, onProgress } = options;
|
|
7411
|
-
const
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
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 ${
|
|
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
|
-
|
|
7487
|
+
captures.push({ slideIndex, dataUrl: canvas.toDataURL("image/png") });
|
|
7423
7488
|
}
|
|
7424
|
-
onProgress?.(
|
|
7489
|
+
onProgress?.(total, total);
|
|
7425
7490
|
setActiveSlide(currentSlideIndex);
|
|
7426
|
-
return
|
|
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
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
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
|
|
8170
|
+
const captures = await captureSlidesAsPngDataUrls(
|
|
8190
8171
|
canvasStageRef,
|
|
8191
|
-
|
|
8172
|
+
job.slideIndices,
|
|
8192
8173
|
setActiveSlideIndex,
|
|
8193
8174
|
activeSlideIndex,
|
|
8194
8175
|
{ scale: printRasterScale }
|
|
8195
8176
|
);
|
|
8196
|
-
if (
|
|
8177
|
+
if (captures.length === 0) {
|
|
8197
8178
|
printWindow.close();
|
|
8198
8179
|
return;
|
|
8199
8180
|
}
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
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
|
|
8248
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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({
|
|
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(
|
|
10177
|
-
|
|
10178
|
-
|
|
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
|
-
|
|
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(
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
for (const
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
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
|
-
|
|
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,
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
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
|
-
|
|
11613
|
-
|
|
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,
|