pptx-react-viewer 4.2.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +138 -0
  2. package/dist/{AiChatPanel-SEIRQ3XP.mjs → AiChatPanel-QJHUDIWT.mjs} +4 -4
  3. package/dist/AiChatPanel-QJHUDIWT.mjs.br +0 -0
  4. package/dist/AiChatPanel-QJHUDIWT.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-VVTLQXQ5.js → AiChatPanel-UFMSTNCB.js} +28 -28
  6. package/dist/AiChatPanel-UFMSTNCB.js.br +0 -0
  7. package/dist/AiChatPanel-UFMSTNCB.js.gz +0 -0
  8. package/dist/{Model3DScene-DCTVSK2F.mjs → Model3DScene-3GOC5HUS.mjs} +1 -1
  9. package/dist/Model3DScene-3GOC5HUS.mjs.br +0 -0
  10. package/dist/Model3DScene-3GOC5HUS.mjs.gz +0 -0
  11. package/dist/{Model3DScene-SCWQXMEA.js → Model3DScene-KXNJBAQD.js} +2 -2
  12. package/dist/Model3DScene-KXNJBAQD.js.br +0 -0
  13. package/dist/Model3DScene-KXNJBAQD.js.gz +0 -0
  14. package/dist/{chunk-S65QSO6T.js → chunk-7WWINBGF.js} +17172 -8075
  15. package/dist/chunk-7WWINBGF.js.br +0 -0
  16. package/dist/chunk-7WWINBGF.js.gz +0 -0
  17. package/dist/{chunk-KTSDPBQZ.js → chunk-AI6K5EAE.js} +1270 -1079
  18. package/dist/chunk-AI6K5EAE.js.br +0 -0
  19. package/dist/chunk-AI6K5EAE.js.gz +0 -0
  20. package/dist/{chunk-3WYNGYB6.js → chunk-CSY422LU.js} +5 -5
  21. package/dist/chunk-CSY422LU.js.br +0 -0
  22. package/dist/chunk-CSY422LU.js.gz +0 -0
  23. package/dist/{chunk-VPJOJJ36.mjs → chunk-D3TZOCQP.mjs} +17139 -8067
  24. package/dist/chunk-D3TZOCQP.mjs.br +0 -0
  25. package/dist/chunk-D3TZOCQP.mjs.gz +0 -0
  26. package/dist/{chunk-NXGUR2DO.js → chunk-I4D6JQOI.js} +27 -2
  27. package/dist/chunk-I4D6JQOI.js.br +0 -0
  28. package/dist/chunk-I4D6JQOI.js.gz +0 -0
  29. package/dist/{chunk-PC7H3C5W.mjs → chunk-JQXN6PO7.mjs} +27 -2
  30. package/dist/chunk-JQXN6PO7.mjs.br +0 -0
  31. package/dist/chunk-JQXN6PO7.mjs.gz +0 -0
  32. package/dist/{chunk-ZYIJODUR.mjs → chunk-LUHUYBGW.mjs} +211 -20
  33. package/dist/chunk-LUHUYBGW.mjs.br +0 -0
  34. package/dist/chunk-LUHUYBGW.mjs.gz +0 -0
  35. package/dist/{chunk-5MRNT4V6.js → chunk-OWTHF5N4.js} +209 -187
  36. package/dist/chunk-OWTHF5N4.js.br +0 -0
  37. package/dist/chunk-OWTHF5N4.js.gz +0 -0
  38. package/dist/{chunk-4GTDG2FH.mjs → chunk-WCHKDZP6.mjs} +660 -197
  39. package/dist/chunk-WCHKDZP6.mjs.br +0 -0
  40. package/dist/chunk-WCHKDZP6.mjs.gz +0 -0
  41. package/dist/{chunk-B5YZABYX.mjs → chunk-WNFHFFYE.mjs} +32 -10
  42. package/dist/chunk-WNFHFFYE.mjs.br +0 -0
  43. package/dist/chunk-WNFHFFYE.mjs.gz +0 -0
  44. package/dist/{chunk-L4XBWL7J.mjs → chunk-XMKLY2SE.mjs} +1 -1
  45. package/dist/chunk-XMKLY2SE.mjs.br +0 -0
  46. package/dist/chunk-XMKLY2SE.mjs.gz +0 -0
  47. package/dist/{chunk-P2SBIMYF.js → chunk-YJKR7Z3X.js} +2161 -1698
  48. package/dist/chunk-YJKR7Z3X.js.br +0 -0
  49. package/dist/chunk-YJKR7Z3X.js.gz +0 -0
  50. package/dist/i18n/de.cjs +25 -2
  51. package/dist/i18n/de.cjs.br +0 -0
  52. package/dist/i18n/de.cjs.gz +0 -0
  53. package/dist/i18n/de.mjs +25 -2
  54. package/dist/i18n/de.mjs.br +0 -0
  55. package/dist/i18n/de.mjs.gz +0 -0
  56. package/dist/i18n/es.cjs +25 -2
  57. package/dist/i18n/es.cjs.br +0 -0
  58. package/dist/i18n/es.cjs.gz +0 -0
  59. package/dist/i18n/es.mjs +25 -2
  60. package/dist/i18n/es.mjs.br +0 -0
  61. package/dist/i18n/es.mjs.gz +0 -0
  62. package/dist/i18n/fr.cjs +25 -2
  63. package/dist/i18n/fr.cjs.br +0 -0
  64. package/dist/i18n/fr.cjs.gz +0 -0
  65. package/dist/i18n/fr.mjs +25 -2
  66. package/dist/i18n/fr.mjs.br +0 -0
  67. package/dist/i18n/fr.mjs.gz +0 -0
  68. package/dist/i18n/zh-CN.cjs +25 -2
  69. package/dist/i18n/zh-CN.cjs.br +0 -0
  70. package/dist/i18n/zh-CN.cjs.gz +0 -0
  71. package/dist/i18n/zh-CN.mjs +25 -2
  72. package/dist/i18n/zh-CN.mjs.br +0 -0
  73. package/dist/i18n/zh-CN.mjs.gz +0 -0
  74. package/dist/i18n.js +4 -4
  75. package/dist/i18n.js.br +0 -0
  76. package/dist/i18n.js.gz +0 -0
  77. package/dist/i18n.mjs +1 -1
  78. package/dist/i18n.mjs.br +0 -0
  79. package/dist/i18n.mjs.gz +0 -0
  80. package/dist/index.d.ts +311 -6
  81. package/dist/index.js +49 -49
  82. package/dist/index.js.br +0 -0
  83. package/dist/index.js.gz +0 -0
  84. package/dist/index.mjs +6 -6
  85. package/dist/index.mjs.br +0 -0
  86. package/dist/index.mjs.gz +0 -0
  87. package/dist/internals.d.ts +461 -42
  88. package/dist/internals.js +105 -105
  89. package/dist/internals.js.br +0 -0
  90. package/dist/internals.js.gz +0 -0
  91. package/dist/internals.mjs +4 -4
  92. package/dist/internals.mjs.br +0 -0
  93. package/dist/internals.mjs.gz +0 -0
  94. package/dist/pptx-viewer.css +1 -1
  95. package/dist/pptx-viewer.css.br +0 -0
  96. package/dist/pptx-viewer.css.gz +0 -0
  97. package/dist/viewer/index.d.ts +274 -4
  98. package/dist/viewer/index.js +27 -27
  99. package/dist/viewer/index.js.br +0 -0
  100. package/dist/viewer/index.js.gz +0 -0
  101. package/dist/viewer/index.mjs +6 -6
  102. package/dist/viewer/index.mjs.br +0 -0
  103. package/dist/viewer/index.mjs.gz +0 -0
  104. package/package.json +1 -1
  105. package/dist/AiChatPanel-SEIRQ3XP.mjs.br +0 -0
  106. package/dist/AiChatPanel-SEIRQ3XP.mjs.gz +0 -0
  107. package/dist/AiChatPanel-VVTLQXQ5.js.br +0 -0
  108. package/dist/AiChatPanel-VVTLQXQ5.js.gz +0 -0
  109. package/dist/Model3DScene-DCTVSK2F.mjs.br +0 -0
  110. package/dist/Model3DScene-DCTVSK2F.mjs.gz +0 -0
  111. package/dist/Model3DScene-SCWQXMEA.js.br +0 -0
  112. package/dist/Model3DScene-SCWQXMEA.js.gz +0 -0
  113. package/dist/chunk-3WYNGYB6.js.br +0 -0
  114. package/dist/chunk-3WYNGYB6.js.gz +0 -0
  115. package/dist/chunk-4GTDG2FH.mjs.br +0 -0
  116. package/dist/chunk-4GTDG2FH.mjs.gz +0 -0
  117. package/dist/chunk-5MRNT4V6.js.br +0 -0
  118. package/dist/chunk-5MRNT4V6.js.gz +0 -0
  119. package/dist/chunk-B5YZABYX.mjs.br +0 -0
  120. package/dist/chunk-B5YZABYX.mjs.gz +0 -0
  121. package/dist/chunk-KTSDPBQZ.js.br +0 -0
  122. package/dist/chunk-KTSDPBQZ.js.gz +0 -0
  123. package/dist/chunk-L4XBWL7J.mjs.br +0 -0
  124. package/dist/chunk-L4XBWL7J.mjs.gz +0 -0
  125. package/dist/chunk-NXGUR2DO.js.br +0 -0
  126. package/dist/chunk-NXGUR2DO.js.gz +0 -0
  127. package/dist/chunk-P2SBIMYF.js.br +0 -0
  128. package/dist/chunk-P2SBIMYF.js.gz +0 -0
  129. package/dist/chunk-PC7H3C5W.mjs.br +0 -0
  130. package/dist/chunk-PC7H3C5W.mjs.gz +0 -0
  131. package/dist/chunk-S65QSO6T.js.br +0 -0
  132. package/dist/chunk-S65QSO6T.js.gz +0 -0
  133. package/dist/chunk-VPJOJJ36.mjs.br +0 -0
  134. package/dist/chunk-VPJOJJ36.mjs.gz +0 -0
  135. package/dist/chunk-ZYIJODUR.mjs.br +0 -0
  136. package/dist/chunk-ZYIJODUR.mjs.gz +0 -0
@@ -1,7 +1,7 @@
1
- import { DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, getImageSurfaceStyle, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, DEFAULT_FILL_COLOR, getCropShapeClipPath, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getImageSurfaceMaskStyle, getImageTilingStyle, getDuotoneColors, getTextWarpStyle, renderTextSegments, buildReactChartViewModel, renderChartElement, MIN_ELEMENT_SIZE, buildTextBody3DSceneStyle, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, HYPERLINK_COLOR, cloneHistorySnapshot, ZOOM_TO_SELECTION_PADDING, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, UNGROUPED_SECTION_ID, DEFAULT_SECTION_GROUP_ID, DEFAULT_TABLE_ROWS, DEFAULT_TABLE_COLUMNS, buildPdfFromTiledImageData, GRID_SIZE, buildNotesPdf } from './chunk-B5YZABYX.mjs';
2
- import { GlyphOutlineFontCache, createGlyphOutlineLookup, DEFAULT_VIEWER_OPTIONS, TOOLBAR_TABS, defineThreeViewElement, getSelectionControlArtworkStyle, hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, getSelectionOutlineColor, connectorWrapperTransform, getAriaRoleDescription, getAriaLabel, getAriaRole, resolveElementInteractivity, isEditableTextElement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, shouldRenderHitTarget, elementHitTargetStyle, getImageEffectsOpacity, getImageEffectsFilter, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, ACTION_BUTTON_PRESETS, mediaTransportVisible, isInkElement, getGroupChildParentFill, getElementLabel, getResizeHandleHitAreaStyle, paintedStrokeWidth, buildCssGradientFromShapeStyle, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, paintedElementSize, getElementTransform, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, getEffectStyleSource, getBevelLightingSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, isImageLikeElement, strokeOutlineViewBox, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, canDrillDown, computeSmartArtElementLayout, flattenNodes, buildSummaryZoomView, isImageTiled, getImageColorWashStyle, readEditableText, placeCaretAtEnd, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, subscribeBarFacePicturePixelSamples, getBarFacePicturePixelSampleVersion, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, buildInkGroupStrokes, getInkReplayStyles, INK_REPLAY_KEYFRAMES, buildContentPartStrokes, getContentPartReplayStyles, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, attachRotateHandlePlacement, elementIdSelector, createRotationDrag, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, DEFAULT_PALETTE2, resolvePalette, computeDrawingViewBox, projectDrawingShapes, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, measureSvgViewportRect, modelDataToBlobUrl, getImageSvgFilters, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, inlineListBodyText, createInlineListSeed, readListActivationSelection, createInlineListModelObserver, attachCollaborationInlineEditor, bindInlineListParagraph, bindInlineListRun, attachInlineListController, restoreInlineListBodySelection, getInlineEditorSelectionResult, isBulletMarkerSegment, resolveChartThreeViewSpec, applyChart3DDrag, applyChart3DSelect, findChartPartTarget, withChartTitle, resolveSmartArtThreeViewSpec, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, openUrlInNewTab, getSubstituteFontFamily, hasGlyphEnvelope, buildGlyphEnvelope, getWarpPath, isWedgeCalloutPresetShape, isElementActionable, centeredSvgTextLines, findSmartArtNodeText, setSmartArtNodeStyle, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, updateSmartArtNodeText, advanceChartMarkDrag, advanceChartValueDrag, resolveChartKind, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, groupIntoParagraphs, substituteFieldText, computeInlineEditorRect, MIN_TOUCH_TARGET_PX, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createSyncGate, clearLocalAwareness, validateRoomId, createDepartureChannel, resolveTransportForServerUrl, isMixedContentBlocked, CONNECTION_TIMEOUT_MS, registerCollaborationTeardown, createPresenceProjector, BROADCAST_THROTTLE_MS, sanitizeColor, cloneTemplateElementsBySlideId, cloneSlide, createWheelStepBuffer, createViewerZoomStore, clampZoomScale, mapEditingWheel, createActiveAnimationGroup, cancelBuildReveal, clearPlaybackTimers, PresentationAnimationController, resolveMediaTimeNodeElementIds, advanceMainSequence, playGroup, PRESENTATION_HASH, PRESENTATION_NONCE_KEY, PRESENTATION_CHANNEL_NAME, swapPresentationWindows, PRESENTATION_MESSAGE_ORIGIN, clearAudienceContent, buildPresentationAudienceUrl, resolveAudienceScreenPlacement, placeAudienceWindow, storeAudienceContent, isPresentationSessionMessage, endAudienceDisplay, createPresentationKeyBuffer, acceptsPresentationInput, resolveAutoAdvanceDelayMs, hasShowSlideAfter, nextShowSlideIndex, previousShowSlideIndex, createPresenterShowGuard, firstShowSlideIndex, attachPresentationVisibilityPause, presentationEntrySlideIndex, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, visibleTemplateElements, createCollaborationLivePatcher, publishLiveInlineText, PptxHandler, createPresentationLoadResources, collectMediaElements, resolveMediaElementSource, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, partitionTemplateElements, seedRecentColors, resolveAuthoredCustomShowId, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, EncryptedFileError, resolveAutosaveIntervalMs, shouldWriteAutosaveSnapshot, saveAutosaveSnapshot, autosaveSnapshotMark, updateMasterViewElement, isTemplateElementId, updateElement, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, canInteractWithElement, prepareExportClone, normalizeColorsForCapture, preprocessCssForCapture, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, resolveImageResolutionScale, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, comparePresentation, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, resolveAuthoredSlideRange, mayLeaveSlideShow, stopAllPersistentAudio, guidePxToEmu, buildSaveSlides, buildDeckSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, shouldProbeAutosaveRecovery, probeAutosaveRecovery, acceptAutosaveRecovery, acknowledgeAutosaveRecovery, discardAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, copyFormatFromElement, applyFormatToElement, collectReferencedFontFamilies, resolveGoogleWebfontHref, syncGoogleWebfontStylesheet, selectGoogleWebfontFamilies, fetchGoogleWebfontOutlineBytes, mapSlideShowStartKey, mapEditorKey, isEditorTextInputTarget, prepareElementForInsertion, createViewerOptionsStore, observeYDocSlides, LOCAL_SYNC_ORIGIN, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, isKeyboardOpen, scopeLayoutOptionsToSlide, checkModifyPassword, viewerPreferencesFromViewProperties, DEFAULT_VIEWER_PREFERENCES, viewPropertiesPatchFromPreferences, openPptxFile, readBackstageRecentFile, resolveCollaborationShellEditability, resolveCollaborationShellState, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, getSlideTransitionAnimations, getFragmentedTransitionDescriptor, SLIDE_TRANSITION_KEYFRAMES, isActionHidden, buildInlineTextCommitPatch, resolveInlineEditAutoFitHeight, resolveInlineEditNormAutofitShrink, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, savedPresentationFileName, downloadBlob, exportDeckJson, groupElements, generateElementId, makeCloneId, ungroupElements, alignElements, distributeElements, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, mergeShapes, mapPresentationKey, lastShowSlideIndex, mapPresentationWheel, openPendingPrintWindow, computeColorFilter, filterHiddenSlideIndices, computeSlideIndices, buildPrintDocument, finishPrintWindow, buildPrintHtmlDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, buildThemeColorMap, reResolveSlideColors, reResolveElementColors, resolveViewportFitOptions, calculateViewportFit, scheduleAutoAdvanceChain, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, resolveTransitionSoundAction, runPresentationAction, safeOpenUrl, buildRunProgramNotice, toggleStageElementMedia, resolveOleVerbTarget, downloadDataUrl, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, remapTextToSegments, buildInlineListStylePatch, applyActiveInlineListFormatting, applyListStyleUpdate, setPendingSelectionRestore, applyTextStyleUpdate, toggleSelectionBullets, transformInlineListCase, applyCaseTransformToSegments, transformTextCase, resolveExportCaptureDecision, recordProgressPercent, computeGridSpacingPx, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, overlayMasterViewInlineSnapshot, overlayInlineTextSnapshot, cloneElementUpdates, assertElementUpdateTarget, prepareElementUpdateBatch, createWriteBackScheduler, observeExternalCollaborationReadiness, resolveHistoryDepth, hasCopyableFormat, createBackstagePresentation, buildFieldSubstitutionContext, cloneElementForPaste, computeScrollDelta, getPresetShapeClipPath, svgPathToPolygons, polygonsToSvgPath, rerouteConnectorsForMovedElements, applyReroutedConnectors, SvgExporter, replyToCommentInList, removeTableElementColumn, insertTableElementColumn, removeTableElementRow, insertTableElementRow, updateCellTextStyleInRawXml, setCellText, updateCellTextInRawXml, splitCell, updateMergeAttrsInRawXml, mergeCells, pickSupportedMimeType, WEBM_MIME_CANDIDATES, fpsToFrameIntervalMs, segmentFrameCount, stopCaptureStream, GIF_POST_CAPTURE_MAX_SIDE, encodeGif, rasterResultToPngBlob, rasterizeElementTiles, placeTileOnPage, PDF_SLIDES_PAGE_WIDTH_PT, PDF_SLIDES_PAGE_HEIGHT_PT, canvasToJpegData, createSnapshotTextPositions, isPpactionUrl, parsePpactionUrl, resolvePresentationAction, elementActionToPptxAction, isUrlSafe, buildSmartArtPresetData, classifyMediaType, computeSnapToShape, publishLiveGeometry, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, rasterizeElementTiledToCanvas, borrowExternalCollaborationAwareness, observeExternalCollaborationSession, clampGifDimensions, rasterizeElement, shouldConfirmExternalHyperlink, applyResize, lockResizeAspect, snapBoxToGrid, applyMotionPathPreset, bringForward, sendBackward, bringToFront, sendToBack } from './chunk-VPJOJJ36.mjs';
3
- import { translationsEn } from './chunk-PC7H3C5W.mjs';
4
- import React16, { createContext, useMemo, useState, useCallback, useEffect, Suspense, useRef, useLayoutEffect, useContext, useSyncExternalStore, useImperativeHandle } from 'react';
1
+ import { DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, getImageSurfaceStyle, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, DEFAULT_FILL_COLOR, getCropShapeClipPath, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getImageSurfaceMaskStyle, getDuotoneColors, getTextWarpStyle, renderTextSegments, buildReactChartViewModel, renderChartElement, MIN_ELEMENT_SIZE, buildTextBody3DSceneStyle, getImageTilingStyle, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, HYPERLINK_COLOR, cloneHistorySnapshot, ZOOM_TO_SELECTION_PADDING, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, UNGROUPED_SECTION_ID, DEFAULT_SECTION_GROUP_ID, DEFAULT_TABLE_ROWS, DEFAULT_TABLE_COLUMNS, buildPdfFromTiledImageData, GRID_SIZE, buildNotesPdf } from './chunk-WNFHFFYE.mjs';
2
+ import { GlyphOutlineFontCache, createGlyphOutlineLookup, DEFAULT_VIEWER_OPTIONS, TOOLBAR_TABS, defineThreeViewElement, getSelectionControlArtworkStyle, hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, getSelectionOutlineColor, connectorWrapperTransform, getAriaRoleDescription, getAriaLabel, getAriaRole, resolveElementInteractivity, isEditableTextElement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, isMediaFullscreenActive, shouldRenderHitTarget, elementHitTargetStyle, getImageEffectsOpacity, getImageEffectsFilter, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, ACTION_BUTTON_PRESETS, mediaTransportVisible, isInkElement, oleActionsVisible, getGroupChildParentFill, getElementLabel, getResizeHandleHitAreaStyle, paintedStrokeWidth, buildCssGradientFromShapeStyle, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, paintedElementSize, MEDIA_FULLSCREEN_OVERLAY_STYLE, elementContainerHeightStyle, getElementTransform, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, getEffectStyleSource, getBevelLightingSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, isImageLikeElement, strokeOutlineViewBox, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, canDrillDown, computeSmartArtElementLayout, flattenNodes, buildSummaryZoomView, isImageTiled, getImageColorWashStyle, readEditableText, placeCaretAtEnd, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, mapInlineTextFormatKey, subscribeBarFacePicturePixelSamples, getBarFacePicturePixelSampleVersion, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, buildInkGroupStrokes, getInkReplayStyles, INK_REPLAY_KEYFRAMES, buildContentPartStrokes, getContentPartReplayStyles, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, attachRotateHandlePlacement, elementIdSelector, createRotationDrag, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, DEFAULT_PALETTE2, resolvePalette, computeDrawingViewBox, projectDrawingShapes, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, measureSvgViewportRect, modelDataToBlobUrl, resolveZoomNavigationTarget, getImageSvgFilters, getCachedNativeImageSize, probeNativeImageSize, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, inlineListBodyText, createInlineListSeed, readListActivationSelection, createInlineListModelObserver, attachCollaborationInlineEditor, bindInlineListParagraph, bindInlineListRun, attachInlineListController, restoreInlineListBodySelection, getInlineEditorSelectionResult, isBulletMarkerSegment, resolveChartThreeViewSpec, applyChart3DDrag, applyChart3DSelect, findChartPartTarget, withChartTitle, resolveSmartArtThreeViewSpec, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, openUrlInNewTab, getSubstituteFontFamily, hasGlyphEnvelope, buildGlyphEnvelopeBlock, getWarpPath, isWedgeCalloutPresetShape, isElementActionable, centeredSvgTextLines, findSmartArtNodeText, setSmartArtNodeStyle, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, updateSmartArtNodeText, advanceChartMarkDrag, advanceChartValueDrag, resolveChartKind, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, groupIntoParagraphs, substituteFieldText, computeInlineEditorRect, MIN_TOUCH_TARGET_PX, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createSyncGate, clearLocalAwareness, validateRoomId, createDepartureChannel, resolveTransportForServerUrl, isMixedContentBlocked, CONNECTION_TIMEOUT_MS, registerCollaborationTeardown, createPresenceProjector, BROADCAST_THROTTLE_MS, sanitizeColor, cloneTemplateElementsBySlideId, cloneSlide, 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, resolveForwardSlideWithZoomReturn, buildZoomTransitionOverride, hasShowSlideAfter, nextShowSlideIndex, previousShowSlideIndex, beginZoomExcursion, createPresenterShowGuard, firstShowSlideIndex, attachPresentationVisibilityPause, presentationEntrySlideIndex, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, visibleTemplateElements, createCollaborationLivePatcher, publishLiveInlineText, PptxHandler, createPresentationLoadResources, collectMediaElements, resolveMediaElementSource, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, partitionTemplateElements, seedRecentColors, resolveAuthoredCustomShowId, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, EncryptedFileError, resolveAutosaveIntervalMs, shouldWriteAutosaveSnapshot, saveAutosaveSnapshot, autosaveSnapshotMark, updateMasterViewElement, isTemplateElementId, updateElement, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, canInteractWithElement, prepareExportClone, normalizeColorsForCapture, preprocessCssForCapture, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, resolveImageResolutionScale, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, comparePresentation, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, resolveAuthoredSlideRange, mayLeaveSlideShow, stopAllPersistentAudio, guidePxToEmu, buildSaveSlides, buildDeckSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, shouldProbeAutosaveRecovery, probeAutosaveRecovery, acceptAutosaveRecovery, acknowledgeAutosaveRecovery, discardAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, rasterResultToPngBlob, downloadBlob, elementPictureFilename, collectReferencedFontFamilies, resolveGoogleWebfontHref, syncGoogleWebfontStylesheet, selectGoogleWebfontFamilies, fetchGoogleWebfontOutlineBytes, mapSlideShowStartKey, mapEditorKey, isEditorTextInputTarget, textFontSizePtToPx, stepFontSizePt, textFontSizePxToPt, cycleSelectableElement, prepareElementForInsertion, createViewerOptionsStore, observeYDocSlides, LOCAL_SYNC_ORIGIN, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, isKeyboardOpen, scopeLayoutOptionsToSlide, checkModifyPassword, viewerPreferencesFromViewProperties, DEFAULT_VIEWER_PREFERENCES, viewPropertiesPatchFromPreferences, openPptxFile, readBackstageRecentFile, resolveCollaborationShellEditability, resolveCollaborationShellState, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, getSlideTransitionAnimations, getFragmentedTransitionDescriptor, SLIDE_TRANSITION_KEYFRAMES, isActionHidden, buildInlineTextCommitPatch, resolveInlineEditAutoFitHeight, resolveInlineEditNormAutofitShrink, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, contextMenuInspectorAnchor, savedPresentationFileName, exportDeckJson, groupElements, generateElementId, makeCloneId, ungroupElements, alignElements, distributeElements, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, mergeShapes, mapPresentationKey, lastShowSlideIndex, mapPresentationWheel, openPendingPrintWindow, computeColorFilter, filterHiddenSlideIndices, computeSlideIndices, buildPrintDocument, finishPrintWindow, buildPrintHtmlDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, buildThemeColorMap, reResolveSlideColors, reResolveElementColors, resolveViewportFitOptions, calculateViewportFit, scheduleAutoAdvanceChain, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, resolveTransitionSoundAction, runPresentationAction, safeOpenUrl, buildRunProgramNotice, toggleStageElementMedia, resolveOleVerbTarget, downloadDataUrl, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, remapTextToSegments, buildInlineListStylePatch, applyActiveInlineListFormatting, applyListStyleUpdate, setPendingSelectionRestore, applyTextStyleUpdate, toggleSelectionBullets, transformInlineListCase, applyCaseTransformToSegments, transformTextCase, resolveExportCaptureDecision, recordProgressPercent, computeGridSpacingPx, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, overlayMasterViewInlineSnapshot, overlayInlineTextSnapshot, rasterizeElement, cloneElementForPaste, applyPasteSpecialFormat, buildRasterPictureElement, copyFormatFromElement, cloneElementUpdates, assertElementUpdateTarget, prepareElementUpdateBatch, createWriteBackScheduler, observeExternalCollaborationReadiness, resolveHistoryDepth, hasCopyableFormat, createBackstagePresentation, buildFieldSubstitutionContext, scrollInspectorSectionIntoView, computeScrollDelta, getPresetShapeClipPath, svgPathToPolygons, polygonsToSvgPath, rerouteConnectorsForMovedElements, applyReroutedConnectors, SvgExporter, replyToCommentInList, removeTableElementColumn, insertTableElementColumn, removeTableElementRow, insertTableElementRow, updateCellTextStyleInRawXml, setCellText, updateCellTextInRawXml, splitCell, updateMergeAttrsInRawXml, mergeCells, 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, canvasToJpegData, applyFormatToElement, createSnapshotTextPositions, isPpactionUrl, parsePpactionUrl, resolvePresentationAction, elementActionToPptxAction, isUrlSafe, buildSmartArtPresetData, classifyMediaType, computeSnapToShape, publishLiveGeometry, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, rasterizeElementTiledToCanvas, borrowExternalCollaborationAwareness, observeExternalCollaborationSession, clampGifDimensions, rasterResultToPngDataUrl, shouldConfirmExternalHyperlink, applyResize, lockResizeAspect, snapBoxToGrid, applyMotionPathPreset, bringForward, sendBackward, bringToFront, sendToBack } from './chunk-D3TZOCQP.mjs';
3
+ import { translationsEn } from './chunk-JQXN6PO7.mjs';
4
+ import React17, { createContext, useMemo, useState, useCallback, useEffect, Suspense, useRef, useLayoutEffect, useContext, useSyncExternalStore, useImperativeHandle } from 'react';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { flushSync } from 'react-dom';
@@ -1334,6 +1334,9 @@ function useAnimationPlayback(input) {
1334
1334
  const activeAnimationGroupRef = useRef(createActiveAnimationGroup());
1335
1335
  const seededCompletedRef = useRef(false);
1336
1336
  const mediaTimeNodeElementIdsRef = useRef(/* @__PURE__ */ new Map());
1337
+ const mediaBookmarkTimesMsRef = useRef(
1338
+ /* @__PURE__ */ new Map()
1339
+ );
1337
1340
  const lastSeedCompletedRef = useRef(false);
1338
1341
  const buildPlaybackContext = useCallback(() => {
1339
1342
  return {
@@ -1343,7 +1346,8 @@ function useAnimationPlayback(input) {
1343
1346
  onPlayActionSound,
1344
1347
  playSound: playAnimationSound,
1345
1348
  stopSound: stopAnimationSound,
1346
- mediaTimeNodeElementIds: mediaTimeNodeElementIdsRef.current
1349
+ mediaTimeNodeElementIds: mediaTimeNodeElementIdsRef.current,
1350
+ mediaBookmarkTimesMs: mediaBookmarkTimesMsRef.current
1347
1351
  };
1348
1352
  }, [onPlayActionSound]);
1349
1353
  useEffect(() => {
@@ -1361,6 +1365,7 @@ function useAnimationPlayback(input) {
1361
1365
  if (!slide) {
1362
1366
  controllerRef.current = null;
1363
1367
  mediaTimeNodeElementIdsRef.current = /* @__PURE__ */ new Map();
1368
+ mediaBookmarkTimesMsRef.current = /* @__PURE__ */ new Map();
1364
1369
  setPresentationElementStates(/* @__PURE__ */ new Map());
1365
1370
  setPresentationKeyframesCss("");
1366
1371
  setInteractiveTriggerShapeIds(/* @__PURE__ */ new Set());
@@ -1377,6 +1382,7 @@ function useAnimationPlayback(input) {
1377
1382
  mediaTimeNodeElementIdsRef.current = resolveMediaTimeNodeElementIds(
1378
1383
  slide.nativeAnimations ?? []
1379
1384
  );
1385
+ mediaBookmarkTimesMsRef.current = resolveMediaBookmarkTimesMs(slide.elements);
1380
1386
  setPresentationKeyframesCss(controller.keyframesCss);
1381
1387
  setInteractiveTriggerShapeIds(controller.interactiveTriggerShapeIds);
1382
1388
  setHoverTriggerShapeIds(controller.hoverTriggerShapeIds);
@@ -2071,7 +2077,7 @@ function handlePresentationActionImpl(action, deps) {
2071
2077
  // src/viewer/hooks/presentation-mode/slide-transition.ts
2072
2078
  function executeSlideTransition(nextSlideIndex, deps) {
2073
2079
  const incomingSlide = deps.slides[nextSlideIndex];
2074
- const transition = deps.reverse ? deps.slides[deps.currentSlideIndex]?.transition : incomingSlide?.transition;
2080
+ const transition = deps.transitionOverride ?? (deps.reverse ? deps.slides[deps.currentSlideIndex]?.transition : incomingSlide?.transition);
2075
2081
  const durationMs = deps.playTransition ? resolveTransitionDurationMs(transition) : 0;
2076
2082
  deps.clearPresentationTimers();
2077
2083
  deps.setPresentationSlideIndex(nextSlideIndex);
@@ -2136,7 +2142,8 @@ function useSlideNavigation(input) {
2136
2142
  onOpenPresentation,
2137
2143
  onPlayMedia,
2138
2144
  onOleVerb,
2139
- onRunProgram
2145
+ onRunProgram,
2146
+ zoomExcursionRef
2140
2147
  } = input;
2141
2148
  const movePresentationSlideRef = useRef(() => {
2142
2149
  });
@@ -2161,6 +2168,37 @@ function useSlideNavigation(input) {
2161
2168
  if (isClickAdvanceBlocked(slides[presentationSlideIndex], direction, trigger)) {
2162
2169
  return;
2163
2170
  }
2171
+ if (direction === 1) {
2172
+ const consumedExcursion = zoomExcursionRef.current;
2173
+ const step = resolveForwardSlideWithZoomReturn(
2174
+ presentationSlideIndex,
2175
+ void 0,
2176
+ consumedExcursion
2177
+ );
2178
+ if (step.returnedToZoom && step.nextSlideIndex !== void 0) {
2179
+ zoomExcursionRef.current = step.excursion;
2180
+ executeSlideTransition(step.nextSlideIndex, {
2181
+ slides,
2182
+ currentSlideIndex: presentationSlideIndex,
2183
+ onPlayActionSound,
2184
+ onStopActionSound,
2185
+ setPresentationSlideVisible,
2186
+ clearPresentationTimers,
2187
+ setPresentationSlideIndex,
2188
+ onSetActiveSlideIndex,
2189
+ seedSlideAnimations,
2190
+ startSlideAnimations,
2191
+ scheduleAutoAdvanceForSlide,
2192
+ presentationTimersRef,
2193
+ setTransitionOverlay,
2194
+ playTransition: true,
2195
+ transitionOverride: buildZoomTransitionOverride(
2196
+ consumedExcursion?.transitionDurationMs
2197
+ )
2198
+ });
2199
+ return;
2200
+ }
2201
+ }
2164
2202
  const availableSlideIndexes = visibleSlideIndexes.length > 0 ? visibleSlideIndexes : slides.map((_slide, slideIndex) => slideIndex);
2165
2203
  if (availableSlideIndexes.length === 0) {
2166
2204
  return;
@@ -2236,12 +2274,13 @@ function useSlideNavigation(input) {
2236
2274
  visibleSlideIndexes,
2237
2275
  setPresentationSlideVisible,
2238
2276
  setPresentationSlideIndex,
2239
- setTransitionOverlay
2277
+ setTransitionOverlay,
2278
+ zoomExcursionRef
2240
2279
  ]
2241
2280
  );
2242
2281
  movePresentationSlideRef.current = movePresentationSlide;
2243
2282
  const navigateToSlide = useCallback(
2244
- (targetIndex) => {
2283
+ (targetIndex, transitionOverride) => {
2245
2284
  if (targetIndex < 0 || targetIndex >= slides.length) {
2246
2285
  return;
2247
2286
  }
@@ -2269,7 +2308,11 @@ function useSlideNavigation(input) {
2269
2308
  // on-slide links (this is how the issue #131 reporter drives their
2270
2309
  // wheel menu) appeared to have no morph at all, while the same
2271
2310
  // transition played fine on PageDown.
2272
- playTransition: true
2311
+ playTransition: true,
2312
+ // A Slide Zoom / Section Zoom / Summary Zoom click carries its own
2313
+ // `zmPr/@transitionDur`, independent of the destination's own
2314
+ // authored transition (see `useZoomNavigation`).
2315
+ transitionOverride
2273
2316
  });
2274
2317
  },
2275
2318
  [
@@ -2329,31 +2372,22 @@ function useSlideNavigation(input) {
2329
2372
  };
2330
2373
  }
2331
2374
  function useZoomNavigation(input) {
2332
- const { navigateToSlide } = input;
2333
- const zoomReturnSlideIndex = useRef(null);
2375
+ const { slides, navigateToSlide, zoomExcursionRef } = input;
2334
2376
  const handleZoomClick = useCallback(
2335
- (targetSlideIndex, returnSlideIndex) => {
2336
- zoomReturnSlideIndex.current = returnSlideIndex;
2337
- navigateToSlide(targetSlideIndex);
2377
+ (target, returnSlideIndex) => {
2378
+ zoomExcursionRef.current = beginZoomExcursion(target, returnSlideIndex, slides);
2379
+ navigateToSlide(
2380
+ target.targetSlideIndex,
2381
+ buildZoomTransitionOverride(target.transitionDurationMs)
2382
+ );
2338
2383
  },
2339
- [navigateToSlide]
2384
+ [navigateToSlide, slides, zoomExcursionRef]
2340
2385
  );
2341
- const returnToZoomSlide = useCallback(() => {
2342
- const returnIndex = zoomReturnSlideIndex.current;
2343
- if (returnIndex === null) {
2344
- return false;
2345
- }
2346
- zoomReturnSlideIndex.current = null;
2347
- navigateToSlide(returnIndex);
2348
- return true;
2349
- }, [navigateToSlide]);
2350
2386
  const clearZoomReturn = useCallback(() => {
2351
- zoomReturnSlideIndex.current = null;
2352
- }, []);
2387
+ zoomExcursionRef.current = void 0;
2388
+ }, [zoomExcursionRef]);
2353
2389
  return {
2354
2390
  handleZoomClick,
2355
- zoomReturnSlideIndex,
2356
- returnToZoomSlide,
2357
2391
  clearZoomReturn
2358
2392
  };
2359
2393
  }
@@ -2655,6 +2689,7 @@ function usePresentationMode(input) {
2655
2689
  setEndOfShowVisible,
2656
2690
  onAddRunProgramNotice
2657
2691
  });
2692
+ const zoomExcursionRef = useRef(void 0);
2658
2693
  const {
2659
2694
  movePresentationSlide: moveNavigationSlide,
2660
2695
  navigateToSlide,
@@ -2662,6 +2697,7 @@ function usePresentationMode(input) {
2662
2697
  scheduleAutoAdvanceForSlide
2663
2698
  } = useSlideNavigation({
2664
2699
  slides,
2700
+ zoomExcursionRef,
2665
2701
  visibleSlideIndexes,
2666
2702
  presentationSlideIndex,
2667
2703
  setPresentationSlideIndex,
@@ -2718,7 +2754,16 @@ function usePresentationMode(input) {
2718
2754
  runPresentationEntranceAnimations
2719
2755
  ]
2720
2756
  );
2721
- const { handleZoomClick, zoomReturnSlideIndex, returnToZoomSlide, clearZoomReturn } = useZoomNavigation({ navigateToSlide });
2757
+ const { handleZoomClick, clearZoomReturn } = useZoomNavigation({
2758
+ slides,
2759
+ navigateToSlide,
2760
+ zoomExcursionRef
2761
+ });
2762
+ useEffect(() => {
2763
+ if (mode !== "present") {
2764
+ clearZoomReturn();
2765
+ }
2766
+ }, [mode, clearZoomReturn]);
2722
2767
  const openAllSlides = useCallback(() => setAllSlidesOpen(true), []);
2723
2768
  const closeAllSlides = useCallback(() => setAllSlidesOpen(false), []);
2724
2769
  const presenterConsole = usePresenterConsole(presentationSlideIndex, mode === "present");
@@ -3003,8 +3048,6 @@ ${imageRules}`;
3003
3048
  rehearsalPaused,
3004
3049
  toggleRehearsalPause,
3005
3050
  handleZoomClick,
3006
- zoomReturnSlideIndex,
3007
- returnToZoomSlide,
3008
3051
  clearZoomReturn,
3009
3052
  openAudienceWindow,
3010
3053
  closeAudienceWindow,
@@ -3331,7 +3374,7 @@ function useFindReplace({
3331
3374
  canEdit: mode === "edit",
3332
3375
  isTextInputTarget: isEditorTextInputTarget(event.target)
3333
3376
  });
3334
- if (action !== "find") {
3377
+ if (action !== "find" && action !== "findReplace") {
3335
3378
  return;
3336
3379
  }
3337
3380
  event.preventDefault();
@@ -6471,12 +6514,13 @@ function useClipboardHandlers(input) {
6471
6514
  ops.updateActiveElements((els) => [...els, clone]);
6472
6515
  ops.applySelection(clone.id);
6473
6516
  history.markDirty();
6517
+ return clone;
6474
6518
  };
6475
6519
  const handlePaste = () => {
6476
6520
  if (!clipboardPayload || !activeSlide) {
6477
6521
  return;
6478
6522
  }
6479
- insertClone(clipboardPayload.element);
6523
+ input.onPasted?.(insertClone(clipboardPayload.element));
6480
6524
  };
6481
6525
  const handleDuplicate = () => {
6482
6526
  if (!selectedElement || !activeSlide) {
@@ -6938,8 +6982,25 @@ function useGroupAlignLayerHandlers(input) {
6938
6982
  }
6939
6983
 
6940
6984
  // src/viewer/hooks/useElementManipulation.ts
6985
+ function focusInspectorSection(setIsInspectorPaneOpen, setSidebarPanelMode, anchor) {
6986
+ setIsInspectorPaneOpen(true);
6987
+ setSidebarPanelMode("properties");
6988
+ if (!anchor) {
6989
+ return;
6990
+ }
6991
+ requestAnimationFrame(() => {
6992
+ requestAnimationFrame(() => scrollInspectorSectionIntoView(document, anchor));
6993
+ });
6994
+ }
6941
6995
  function useElementManipulation(input) {
6942
- const { setIsInspectorPaneOpen, setSidebarPanelMode, onOpenHyperlinkDialog } = input;
6996
+ const {
6997
+ selectedElement,
6998
+ setIsInspectorPaneOpen,
6999
+ setSidebarPanelMode,
7000
+ onOpenHyperlinkDialog,
7001
+ onEditText,
7002
+ onSaveElementAsPicture
7003
+ } = input;
6943
7004
  const { handleCopy, handleCut, handlePaste, handleDuplicate, handleDelete } = useClipboardHandlers(input);
6944
7005
  const {
6945
7006
  handleGroupElements,
@@ -7001,6 +7062,37 @@ function useElementManipulation(input) {
7001
7062
  case "editHyperlink":
7002
7063
  onOpenHyperlinkDialog();
7003
7064
  break;
7065
+ case "edit-text":
7066
+ if (selectedElement) {
7067
+ onEditText?.(selectedElement.id);
7068
+ }
7069
+ break;
7070
+ case "save-as-picture":
7071
+ if (selectedElement) {
7072
+ onSaveElementAsPicture?.(selectedElement.id);
7073
+ }
7074
+ break;
7075
+ case "edit-alt-text":
7076
+ focusInspectorSection(
7077
+ setIsInspectorPaneOpen,
7078
+ setSidebarPanelMode,
7079
+ contextMenuInspectorAnchor("edit-alt-text")
7080
+ );
7081
+ break;
7082
+ case "size-and-position":
7083
+ focusInspectorSection(
7084
+ setIsInspectorPaneOpen,
7085
+ setSidebarPanelMode,
7086
+ contextMenuInspectorAnchor("size-and-position")
7087
+ );
7088
+ break;
7089
+ case "format-shape":
7090
+ focusInspectorSection(
7091
+ setIsInspectorPaneOpen,
7092
+ setSidebarPanelMode,
7093
+ contextMenuInspectorAnchor("format-shape")
7094
+ );
7095
+ break;
7004
7096
  }
7005
7097
  };
7006
7098
  return {
@@ -7627,6 +7719,9 @@ async function renderElementToRaster(element, scale = 2, backgroundColor, mode =
7627
7719
  buildRasterOptions(element, scale, backgroundColor, mode)
7628
7720
  );
7629
7721
  }
7722
+ async function renderElementToRasterDataUrl(element, scale = 2) {
7723
+ return rasterResultToPngDataUrl(await renderElementToRaster(element, scale));
7724
+ }
7630
7725
  async function renderElementToTiles(element, scale = 2, backgroundColor, mode = "auto") {
7631
7726
  const { width, height } = measureNaturalSize(element);
7632
7727
  return rasterizeElementTiles(
@@ -9803,6 +9898,195 @@ function useCanvasImagePaste(input) {
9803
9898
  [loading, error, eligible, slideId, width, height]
9804
9899
  );
9805
9900
  }
9901
+ function formatPatchFor(element, format) {
9902
+ const updated = applyFormatToElement(element, format);
9903
+ const updates = {};
9904
+ if (hasShapeProperties(updated)) {
9905
+ updates.shapeStyle = updated.shapeStyle;
9906
+ }
9907
+ if (hasTextProperties(updated)) {
9908
+ updates.textStyle = updated.textStyle;
9909
+ }
9910
+ return updates;
9911
+ }
9912
+ function useFormatPainterEditing(input) {
9913
+ const {
9914
+ selectedElement,
9915
+ elementLookup,
9916
+ formatPainterActive,
9917
+ setFormatPainterActive,
9918
+ canvasHandlers,
9919
+ ops
9920
+ } = input;
9921
+ const copiedFormatRef = useRef(null);
9922
+ const prevFormatPainterRef = useRef(false);
9923
+ useEffect(() => {
9924
+ if (formatPainterActive && !prevFormatPainterRef.current && selectedElement) {
9925
+ copiedFormatRef.current = copyFormatFromElement(selectedElement);
9926
+ } else if (!formatPainterActive) {
9927
+ copiedFormatRef.current = null;
9928
+ }
9929
+ prevFormatPainterRef.current = formatPainterActive;
9930
+ }, [formatPainterActive, selectedElement]);
9931
+ const copyFormatFromSelection = useCallback(() => {
9932
+ if (selectedElement) {
9933
+ setFormatPainterActive(true);
9934
+ }
9935
+ }, [selectedElement, setFormatPainterActive]);
9936
+ const pasteFormatToSelection = useCallback(
9937
+ (targetIds) => {
9938
+ const format = copiedFormatRef.current;
9939
+ if (!format) {
9940
+ return;
9941
+ }
9942
+ for (const id of targetIds) {
9943
+ const element = elementLookup.get(id);
9944
+ if (element) {
9945
+ ops.updateElementById(id, formatPatchFor(element, format));
9946
+ }
9947
+ }
9948
+ copiedFormatRef.current = null;
9949
+ setFormatPainterActive(false);
9950
+ },
9951
+ [elementLookup, ops, setFormatPainterActive]
9952
+ );
9953
+ useEffect(() => {
9954
+ if (!formatPainterActive) {
9955
+ return;
9956
+ }
9957
+ const onKey = (e) => {
9958
+ if (e.key === "Escape") {
9959
+ setFormatPainterActive(false);
9960
+ }
9961
+ };
9962
+ window.addEventListener("keydown", onKey);
9963
+ return () => window.removeEventListener("keydown", onKey);
9964
+ }, [formatPainterActive, setFormatPainterActive]);
9965
+ const wrappedCanvasHandlers = useMemo(
9966
+ () => ({
9967
+ ...canvasHandlers,
9968
+ handleElementClick: (elementId, e) => {
9969
+ if (formatPainterActive && copiedFormatRef.current) {
9970
+ e.stopPropagation();
9971
+ const element = elementLookup.get(elementId);
9972
+ if (element) {
9973
+ ops.updateElementById(elementId, formatPatchFor(element, copiedFormatRef.current));
9974
+ }
9975
+ copiedFormatRef.current = null;
9976
+ setFormatPainterActive(false);
9977
+ ops.applySelection(elementId);
9978
+ return;
9979
+ }
9980
+ canvasHandlers.handleElementClick(elementId, e);
9981
+ },
9982
+ handleCanvasMouseDown: (e) => {
9983
+ if (formatPainterActive) {
9984
+ setFormatPainterActive(false);
9985
+ return;
9986
+ }
9987
+ canvasHandlers.handleCanvasMouseDown(e);
9988
+ }
9989
+ }),
9990
+ [canvasHandlers, ops, formatPainterActive, setFormatPainterActive, elementLookup]
9991
+ );
9992
+ return {
9993
+ canvasHandlers: wrappedCanvasHandlers,
9994
+ copyFormatFromSelection,
9995
+ pasteFormatToSelection
9996
+ };
9997
+ }
9998
+ function findMountedElementNode(elementId) {
9999
+ return document.querySelector(
10000
+ `[data-element-id="${elementId}"][data-pptx-element="true"]`
10001
+ );
10002
+ }
10003
+ async function rasterizePastedNode(elementId) {
10004
+ const node = findMountedElementNode(elementId);
10005
+ if (!node) {
10006
+ return null;
10007
+ }
10008
+ return renderElementToRasterDataUrl(node, 2);
10009
+ }
10010
+ function usePasteSpecial(input) {
10011
+ const { clipboardPayload, editTemplateMode, ops, markDirty } = input;
10012
+ const [isPasteSpecialDialogOpen, setIsPasteSpecialDialogOpen] = useState(false);
10013
+ const [pasteOptionsToolbar, setPasteOptionsToolbar] = useState(
10014
+ null
10015
+ );
10016
+ const openPasteSpecialDialog = useCallback(() => {
10017
+ if (clipboardPayload) {
10018
+ setIsPasteSpecialDialogOpen(true);
10019
+ }
10020
+ }, [clipboardPayload]);
10021
+ const closePasteSpecialDialog = useCallback(() => setIsPasteSpecialDialogOpen(false), []);
10022
+ const dismissPasteOptionsToolbar = useCallback(() => setPasteOptionsToolbar(null), []);
10023
+ const notePastedElement = useCallback((element) => {
10024
+ setPasteOptionsToolbar({ elementId: element.id, sourceClone: element });
10025
+ }, []);
10026
+ const replacePastedElement = useCallback(
10027
+ (elementId, next) => {
10028
+ ops.updateActiveElements((els) => els.map((el) => el.id === elementId ? next : el));
10029
+ markDirty();
10030
+ },
10031
+ [ops, markDirty]
10032
+ );
10033
+ const pasteWithFormat = useCallback(
10034
+ async (format) => {
10035
+ if (!clipboardPayload) {
10036
+ return;
10037
+ }
10038
+ setIsPasteSpecialDialogOpen(false);
10039
+ const sourceClone = cloneElementForPaste(clipboardPayload.element, {
10040
+ intoTemplate: editTemplateMode
10041
+ });
10042
+ const initial = format === "picture" ? sourceClone : applyPasteSpecialFormat(sourceClone, format);
10043
+ ops.updateActiveElements((els) => [...els, initial]);
10044
+ ops.applySelection(initial.id);
10045
+ markDirty();
10046
+ setPasteOptionsToolbar({ elementId: initial.id, sourceClone });
10047
+ if (format === "picture") {
10048
+ await new Promise((resolve) => {
10049
+ requestAnimationFrame(() => resolve());
10050
+ });
10051
+ const dataUrl = await rasterizePastedNode(initial.id);
10052
+ if (dataUrl) {
10053
+ replacePastedElement(initial.id, buildRasterPictureElement(sourceClone, dataUrl));
10054
+ }
10055
+ }
10056
+ },
10057
+ [clipboardPayload, editTemplateMode, ops, markDirty, replacePastedElement]
10058
+ );
10059
+ const reformatPastedElement = useCallback(
10060
+ async (format) => {
10061
+ const toolbar = pasteOptionsToolbar;
10062
+ if (!toolbar) {
10063
+ return;
10064
+ }
10065
+ if (format === "picture") {
10066
+ const dataUrl = await rasterizePastedNode(toolbar.elementId);
10067
+ if (dataUrl) {
10068
+ replacePastedElement(
10069
+ toolbar.elementId,
10070
+ buildRasterPictureElement(toolbar.sourceClone, dataUrl)
10071
+ );
10072
+ }
10073
+ return;
10074
+ }
10075
+ replacePastedElement(toolbar.elementId, applyPasteSpecialFormat(toolbar.sourceClone, format));
10076
+ },
10077
+ [pasteOptionsToolbar, replacePastedElement]
10078
+ );
10079
+ return {
10080
+ isPasteSpecialDialogOpen,
10081
+ openPasteSpecialDialog,
10082
+ closePasteSpecialDialog,
10083
+ pasteWithFormat,
10084
+ pasteOptionsToolbar,
10085
+ notePastedElement,
10086
+ reformatPastedElement,
10087
+ dismissPasteOptionsToolbar
10088
+ };
10089
+ }
9806
10090
 
9807
10091
  // src/viewer/hooks/useEditorOperations.ts
9808
10092
  function useEditorOperations(input) {
@@ -9946,6 +10230,35 @@ function useEditorOperations(input) {
9946
10230
  handlerRef,
9947
10231
  insertElement: insertHandlers.addElement
9948
10232
  });
10233
+ const handleEditTextFromContextMenu = useCallback(
10234
+ (elementId) => {
10235
+ canvasHandlers.handleElementDoubleClick(elementId, {});
10236
+ },
10237
+ [canvasHandlers]
10238
+ );
10239
+ const handleSaveElementAsPicture = useCallback(
10240
+ (elementId) => {
10241
+ const node = document.querySelector(
10242
+ `[data-element-id="${elementId}"][data-pptx-element="true"]`
10243
+ );
10244
+ if (!node) {
10245
+ return;
10246
+ }
10247
+ void (async () => {
10248
+ const result = await renderElementToRaster(node, 2);
10249
+ const blob = await rasterResultToPngBlob(result);
10250
+ const el = state.elementLookup.get(elementId);
10251
+ downloadBlob(blob, elementPictureFilename(el?.name, "Picture"));
10252
+ })();
10253
+ },
10254
+ [state.elementLookup]
10255
+ );
10256
+ const pasteSpecial = usePasteSpecial({
10257
+ clipboardPayload: state.clipboardPayload,
10258
+ editTemplateMode: state.editTemplateMode,
10259
+ ops,
10260
+ markDirty: history.markDirty
10261
+ });
9949
10262
  const manipulation = useElementManipulation({
9950
10263
  activeSlide,
9951
10264
  activeSlideIndex,
@@ -9963,7 +10276,10 @@ function useEditorOperations(input) {
9963
10276
  setSidebarPanelMode: state.setSidebarPanelMode,
9964
10277
  ops,
9965
10278
  history,
9966
- onOpenHyperlinkDialog: () => dialogs.setIsHyperlinkDialogOpen(true)
10279
+ onOpenHyperlinkDialog: () => dialogs.setIsHyperlinkDialogOpen(true),
10280
+ onEditText: handleEditTextFromContextMenu,
10281
+ onSaveElementAsPicture: handleSaveElementAsPicture,
10282
+ onPasted: pasteSpecial.notePastedElement
9967
10283
  });
9968
10284
  const slideOps = useSlideManagement({
9969
10285
  slides,
@@ -10002,64 +10318,19 @@ function useEditorOperations(input) {
10002
10318
  }),
10003
10319
  [ops, combinedUpdateTextStyle]
10004
10320
  );
10005
- const copiedFormatRef = useRef(null);
10006
- const prevFormatPainterRef = useRef(false);
10007
10321
  const { formatPainterActive, setFormatPainterActive, elementLookup } = state;
10008
- useEffect(() => {
10009
- if (formatPainterActive && !prevFormatPainterRef.current && selectedElement) {
10010
- copiedFormatRef.current = copyFormatFromElement(selectedElement);
10011
- } else if (!formatPainterActive) {
10012
- copiedFormatRef.current = null;
10013
- }
10014
- prevFormatPainterRef.current = formatPainterActive;
10015
- }, [formatPainterActive, selectedElement]);
10016
- useEffect(() => {
10017
- if (!formatPainterActive) {
10018
- return;
10019
- }
10020
- const onKey = (e) => {
10021
- if (e.key === "Escape") {
10022
- setFormatPainterActive(false);
10023
- }
10024
- };
10025
- window.addEventListener("keydown", onKey);
10026
- return () => window.removeEventListener("keydown", onKey);
10027
- }, [formatPainterActive, setFormatPainterActive]);
10028
- const formatPainterCanvasHandlers = useMemo(
10029
- () => ({
10030
- ...canvasHandlers,
10031
- handleElementClick: (elementId, e) => {
10032
- if (formatPainterActive && copiedFormatRef.current) {
10033
- e.stopPropagation();
10034
- const element = elementLookup.get(elementId);
10035
- if (element) {
10036
- const updated = applyFormatToElement(element, copiedFormatRef.current);
10037
- const updates = {};
10038
- if (hasShapeProperties(updated)) {
10039
- updates.shapeStyle = updated.shapeStyle;
10040
- }
10041
- if (hasTextProperties(updated)) {
10042
- updates.textStyle = updated.textStyle;
10043
- }
10044
- ops.updateElementById(elementId, updates);
10045
- }
10046
- copiedFormatRef.current = null;
10047
- setFormatPainterActive(false);
10048
- ops.applySelection(elementId);
10049
- return;
10050
- }
10051
- canvasHandlers.handleElementClick(elementId, e);
10052
- },
10053
- handleCanvasMouseDown: (e) => {
10054
- if (formatPainterActive) {
10055
- setFormatPainterActive(false);
10056
- return;
10057
- }
10058
- canvasHandlers.handleCanvasMouseDown(e);
10059
- }
10060
- }),
10061
- [canvasHandlers, ops, formatPainterActive, setFormatPainterActive, elementLookup]
10062
- );
10322
+ const {
10323
+ canvasHandlers: formatPainterCanvasHandlers,
10324
+ copyFormatFromSelection,
10325
+ pasteFormatToSelection
10326
+ } = useFormatPainterEditing({
10327
+ selectedElement,
10328
+ elementLookup,
10329
+ formatPainterActive,
10330
+ setFormatPainterActive,
10331
+ canvasHandlers,
10332
+ ops
10333
+ });
10063
10334
  return {
10064
10335
  ops: combinedOps,
10065
10336
  sectionOps,
@@ -10068,8 +10339,11 @@ function useEditorOperations(input) {
10068
10339
  canvasHandlers: formatPainterCanvasHandlers,
10069
10340
  insertHandlers: { ...insertHandlers, imagePaste },
10070
10341
  manipulation,
10342
+ pasteSpecial,
10071
10343
  slideOps,
10072
- tableOps
10344
+ tableOps,
10345
+ copyFormatFromSelection,
10346
+ pasteFormatToSelection
10073
10347
  };
10074
10348
  }
10075
10349
 
@@ -10542,6 +10816,51 @@ function useKeyboardShortcuts(input) {
10542
10816
  case "nextSlide":
10543
10817
  current.onNextSlide?.();
10544
10818
  break;
10819
+ case "alignLeft":
10820
+ current.onAlignLeft?.();
10821
+ break;
10822
+ case "alignCenter":
10823
+ current.onAlignCenter?.();
10824
+ break;
10825
+ case "alignRight":
10826
+ current.onAlignRight?.();
10827
+ break;
10828
+ case "alignJustify":
10829
+ current.onAlignJustify?.();
10830
+ break;
10831
+ case "increaseFontSize":
10832
+ current.onIncreaseFontSize?.();
10833
+ break;
10834
+ case "decreaseFontSize":
10835
+ current.onDecreaseFontSize?.();
10836
+ break;
10837
+ case "copyFormat":
10838
+ current.onCopyFormat?.();
10839
+ break;
10840
+ case "pasteFormat":
10841
+ current.onPasteFormat?.();
10842
+ break;
10843
+ case "newSlide":
10844
+ current.onNewSlide?.();
10845
+ break;
10846
+ case "hyperlink":
10847
+ current.onHyperlink?.();
10848
+ break;
10849
+ case "findReplace":
10850
+ current.onFindReplace?.();
10851
+ break;
10852
+ case "clearFormatting":
10853
+ current.onClearFormatting?.();
10854
+ break;
10855
+ case "cycleSelectionNext":
10856
+ current.onCycleSelectionNext?.();
10857
+ break;
10858
+ case "cycleSelectionPrev":
10859
+ current.onCycleSelectionPrev?.();
10860
+ break;
10861
+ case "pasteSpecial":
10862
+ current.onPasteSpecial?.();
10863
+ break;
10545
10864
  }
10546
10865
  }, []);
10547
10866
  useEffect(() => {
@@ -10553,6 +10872,13 @@ function useKeyboardShortcuts(input) {
10553
10872
  }
10554
10873
 
10555
10874
  // src/viewer/hooks/useKeyboardShortcutWiring.ts
10875
+ var CLEAR_FORMATTING_PATCH = {
10876
+ bold: false,
10877
+ italic: false,
10878
+ underline: false,
10879
+ strikethrough: false,
10880
+ highlightColor: void 0
10881
+ };
10556
10882
  function useKeyboardShortcutWiring(input) {
10557
10883
  const {
10558
10884
  state,
@@ -10564,7 +10890,12 @@ function useKeyboardShortcutWiring(input) {
10564
10890
  manipulation,
10565
10891
  history,
10566
10892
  onEnterPresentModeFromBeginning,
10567
- onSetMode
10893
+ onSetMode,
10894
+ handleAddSlide,
10895
+ onOpenHyperlinkDialog,
10896
+ copyFormatFromSelection,
10897
+ pasteFormatToSelection,
10898
+ onPasteSpecial
10568
10899
  } = input;
10569
10900
  useKeyboardShortcuts({
10570
10901
  containerRef: state.containerRef,
@@ -10638,9 +10969,39 @@ function useKeyboardShortcutWiring(input) {
10638
10969
  state.setActiveSlideIndex((prev) => Math.min(slides.length - 1, prev + 1));
10639
10970
  },
10640
10971
  onStartShowFromBeginning: onEnterPresentModeFromBeginning,
10641
- onStartShowFromCurrent: () => onSetMode("present")
10972
+ onStartShowFromCurrent: () => onSetMode("present"),
10973
+ onAlignLeft: () => ops.updateSelectedTextStyle({ align: "left" }),
10974
+ onAlignCenter: () => ops.updateSelectedTextStyle({ align: "center" }),
10975
+ onAlignRight: () => ops.updateSelectedTextStyle({ align: "right" }),
10976
+ onAlignJustify: () => ops.updateSelectedTextStyle({ align: "justify" }),
10977
+ onIncreaseFontSize: () => stepSelectedFontSize(state, ops, "increase"),
10978
+ onDecreaseFontSize: () => stepSelectedFontSize(state, ops, "decrease"),
10979
+ onCopyFormat: copyFormatFromSelection,
10980
+ onPasteFormat: () => pasteFormatToSelection(state.effectiveSelectedIds),
10981
+ onNewSlide: handleAddSlide,
10982
+ onHyperlink: onOpenHyperlinkDialog,
10983
+ onClearFormatting: () => ops.updateSelectedTextStyle({ ...CLEAR_FORMATTING_PATCH }),
10984
+ onCycleSelectionNext: () => cycleSelection(state, activeSlide, ops, "next"),
10985
+ onCycleSelectionPrev: () => cycleSelection(state, activeSlide, ops, "prev"),
10986
+ onPasteSpecial
10642
10987
  });
10643
10988
  }
10989
+ function stepSelectedFontSize(state, ops, direction) {
10990
+ const selected = state.selectedElement;
10991
+ const currentPx = (selected && hasTextProperties(selected) ? selected.textStyle?.fontSize : void 0) ?? textFontSizePtToPx(18);
10992
+ const nextPt = stepFontSizePt(textFontSizePxToPt(currentPx), direction);
10993
+ ops.updateSelectedTextStyle({ fontSize: textFontSizePtToPx(nextPt) });
10994
+ }
10995
+ function cycleSelection(state, activeSlide, ops, direction) {
10996
+ if (!activeSlide) {
10997
+ return;
10998
+ }
10999
+ const ids = activeSlide.elements.map((el) => el.id);
11000
+ const nextId = cycleSelectableElement(ids, state.selectedElementId, direction);
11001
+ if (nextId) {
11002
+ ops.applySelection(nextId, [nextId]);
11003
+ }
11004
+ }
10644
11005
  function useElementUpdateBatch(input) {
10645
11006
  const live = useRef(input);
10646
11007
  live.current = input;
@@ -11037,7 +11398,12 @@ function useViewerIntegration(input) {
11037
11398
  manipulation: editorOps.manipulation,
11038
11399
  history,
11039
11400
  onEnterPresentModeFromBeginning: presentation.enterPresentModeFromBeginning,
11040
- onSetMode: handleSetMode
11401
+ onSetMode: handleSetMode,
11402
+ handleAddSlide: editorOps.slideOps.handleAddSlide,
11403
+ onOpenHyperlinkDialog: () => dialogs.setIsHyperlinkDialogOpen(true),
11404
+ copyFormatFromSelection: editorOps.copyFormatFromSelection,
11405
+ pasteFormatToSelection: editorOps.pasteFormatToSelection,
11406
+ onPasteSpecial: editorOps.pasteSpecial.openPasteSpecialDialog
11041
11407
  });
11042
11408
  return {
11043
11409
  exportHandlers,
@@ -12199,6 +12565,12 @@ function buildToolbarProps(input) {
12199
12565
  onOpenSettings,
12200
12566
  onRunAccessibilityCheck: dialogs.handleRunAccessibilityCheck,
12201
12567
  onToggleSlideSorter: () => s.setShowSlideSorter((p) => !p),
12568
+ onGoToNormalView: () => {
12569
+ s.setShowSlideSorter(false);
12570
+ s.setShowReadingView(false);
12571
+ s.setShowOutlineView(false);
12572
+ dialogs.handleCloseMasterView();
12573
+ },
12202
12574
  onOpenReadingView: () => s.setShowReadingView(true),
12203
12575
  onOpenOutlineView: () => s.setShowOutlineView(true),
12204
12576
  onUpdateTextStyle: ops.updateSelectedTextStyle,
@@ -13238,6 +13610,33 @@ function DuotoneImage({
13238
13610
  }
13239
13611
  );
13240
13612
  }
13613
+ function TiledImageLayer({
13614
+ element,
13615
+ src,
13616
+ className,
13617
+ style
13618
+ }) {
13619
+ const [nativeSize, setNativeSize] = useState(() => getCachedNativeImageSize(src));
13620
+ useEffect(() => {
13621
+ const cached = getCachedNativeImageSize(src);
13622
+ if (cached) {
13623
+ setNativeSize(cached);
13624
+ return;
13625
+ }
13626
+ let cancelled = false;
13627
+ probeNativeImageSize(src).then((size) => {
13628
+ if (!cancelled && size) {
13629
+ setNativeSize(size);
13630
+ }
13631
+ return void 0;
13632
+ }).catch(() => {
13633
+ });
13634
+ return () => {
13635
+ cancelled = true;
13636
+ };
13637
+ }, [src]);
13638
+ return /* @__PURE__ */ jsx("div", { className, style: { ...getImageTilingStyle(element, nativeSize), ...style } });
13639
+ }
13241
13640
  function renderImageEffectDefinitions(element, excludeDuotone = false) {
13242
13641
  return getImageSvgFilters(element).filter((definition) => !excludeDuotone || definition.id !== `duotone-${element.id}`).map((definition) => /* @__PURE__ */ jsx(
13243
13642
  "svg",
@@ -13313,10 +13712,12 @@ function renderImg(el, style, filter, alt, opacity) {
13313
13712
  return /* @__PURE__ */ jsxs(Fragment, { children: [
13314
13713
  renderImageEffectDefinitions(el),
13315
13714
  /* @__PURE__ */ jsx(
13316
- "div",
13715
+ TiledImageLayer,
13317
13716
  {
13717
+ element: el,
13718
+ src: tileSrc,
13318
13719
  className: "pointer-events-none select-none w-full h-full",
13319
- style: { ...getImageTilingStyle(el), ...effectStyles }
13720
+ style: effectStyles
13320
13721
  }
13321
13722
  )
13322
13723
  ] });
@@ -14196,7 +14597,7 @@ function ResizeHandles({
14196
14597
  ))
14197
14598
  ] });
14198
14599
  }
14199
- var ConnectorElementRenderer = React16.memo(
14600
+ var ConnectorElementRenderer = React17.memo(
14200
14601
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
14201
14602
  function ConnectorElementRendererInner({
14202
14603
  el,
@@ -14534,21 +14935,23 @@ function getContainerStyle({
14534
14935
  );
14535
14936
  const overflowValue = has3DExtrusion || blurGrowVisible || isPicture ? "visible" : isImg || el.type === "media" ? "hidden" : void 0;
14536
14937
  const painted = paintedElementSize(el);
14938
+ const fs = MEDIA_FULLSCREEN_OVERLAY_STYLE;
14939
+ const heightStyle = isFullscreenMedia ? { height: fs.height } : el.type === "table" ? elementContainerHeightStyle(el, painted.height) : { height: painted.height };
14537
14940
  return {
14538
- left: isFullscreenMedia ? 0 : el.x,
14539
- top: isFullscreenMedia ? 0 : el.y,
14540
- width: isFullscreenMedia ? "100%" : painted.width,
14541
- height: isFullscreenMedia ? "100%" : painted.height,
14542
- transform: isFullscreenMedia ? "none" : getElementTransform(el),
14941
+ left: isFullscreenMedia ? fs.left : el.x,
14942
+ top: isFullscreenMedia ? fs.top : el.y,
14943
+ width: isFullscreenMedia ? fs.width : painted.width,
14944
+ ...heightStyle,
14945
+ transform: isFullscreenMedia ? fs.transform : getElementTransform(el),
14543
14946
  transformOrigin: "center",
14544
14947
  overflow: overflowValue,
14545
14948
  clipPath: isPicture ? void 0 : isImg && !has3DExtrusion ? getCropShapeClipPath(el) : void 0,
14546
- zIndex: isFullscreenMedia ? 20 : zIndex,
14949
+ zIndex: isFullscreenMedia ? fs.zIndex : zIndex,
14547
14950
  visibility: animationState?.visible === false ? "hidden" : "visible",
14548
14951
  animation: animationState?.cssAnimation,
14549
- background: isFullscreenMedia ? "#000" : void 0,
14550
- transition: isFullscreenMedia ? "left 0.3s ease, top 0.3s ease, width 0.3s ease, height 0.3s ease" : void 0,
14551
- borderColor: isFullscreenMedia ? "transparent" : void 0,
14952
+ background: isFullscreenMedia ? fs.background : void 0,
14953
+ transition: isFullscreenMedia ? fs.transition : void 0,
14954
+ borderColor: isFullscreenMedia ? fs.borderColor : void 0,
14552
14955
  ...shapeVisualStyle,
14553
14956
  ...isPicture ? {
14554
14957
  backgroundColor: "transparent",
@@ -14583,7 +14986,7 @@ function shapeParams(element) {
14583
14986
  const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
14584
14987
  return { hf: hasFill, fc: fillColor, sw: strokeWidth, sc: strokeColor };
14585
14988
  }
14586
- var Extrusion3DOverlay = React16.memo(
14989
+ var Extrusion3DOverlay = React17.memo(
14587
14990
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
14588
14991
  function Extrusion3DOverlayInner({ data }) {
14589
14992
  if (!data.hasExtrusion || data.panels.length === 0) {
@@ -14817,7 +15220,7 @@ function ShapeEffectOverlay({
14817
15220
  ) : null
14818
15221
  ] });
14819
15222
  }
14820
- var ElementRenderer = React16.memo(
15223
+ var ElementRenderer = React17.memo(
14821
15224
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
14822
15225
  function ElementRendererInner({
14823
15226
  element: el,
@@ -14953,7 +15356,11 @@ var ElementRenderer = React16.memo(
14953
15356
  const selB = isSelected ? `outline-1 -outline-offset-1 outline-${selClr} ring-2 ring-${selClr}/50` : showHoverBorder ? "outline-1 -outline-offset-1 outline-transparent hover:outline-primary/40" : "";
14954
15357
  const cur = effectiveIsInlineEditing ? "cursor-text" : effectiveCanInteract ? !allow.movable ? "cursor-default" : "cursor-move" : hasAction || isZoom ? "cursor-pointer" : "";
14955
15358
  const isPresentationPassive = presenting === true;
14956
- const isFullscreenMedia = el.type === "media" && Boolean(el.fullScreen) && isPresentationPassive && isMediaPlaying;
15359
+ const isFullscreenMedia = el.type === "media" && isMediaFullscreenActive({
15360
+ fullScreen: el.fullScreen,
15361
+ presenting: isPresentationPassive,
15362
+ playing: isMediaPlaying
15363
+ });
14957
15364
  const hitTargetStyle = shouldRenderHitTarget(effectiveCanInteract, isPresentationPassive) ? elementHitTargetStyle(el) : void 0;
14958
15365
  const isFocusable = effectiveCanInteract || isActionable;
14959
15366
  const containerStyle = getContainerStyle({
@@ -15140,30 +15547,48 @@ var ElementRenderer = React16.memo(
15140
15547
  );
15141
15548
  }
15142
15549
  );
15143
- function renderPressureStroke(circles, color, opacity, keyPrefix) {
15144
- return /* @__PURE__ */ jsx("g", { opacity, children: circles.map((c, j) => /* @__PURE__ */ jsx("circle", { cx: c.cx, cy: c.cy, r: c.r, fill: color }, `${keyPrefix}-pc-${j}`)) });
15550
+ function renderPressureStroke(circles, color, opacity, blendMode, keyPrefix) {
15551
+ return /* @__PURE__ */ jsx(
15552
+ "g",
15553
+ {
15554
+ opacity,
15555
+ style: blendMode === "multiply" ? { mixBlendMode: "multiply" } : void 0,
15556
+ children: circles.map((c, j) => /* @__PURE__ */ jsx("circle", { cx: c.cx, cy: c.cy, r: c.r, fill: color }, `${keyPrefix}-pc-${j}`))
15557
+ }
15558
+ );
15145
15559
  }
15146
- function renderNibMarkStroke(marks, color, opacity, keyPrefix) {
15147
- return /* @__PURE__ */ jsx("g", { opacity, children: marks.map((m, j) => /* @__PURE__ */ jsx(
15148
- "ellipse",
15560
+ function renderNibMarkStroke(marks, color, opacity, blendMode, keyPrefix) {
15561
+ return /* @__PURE__ */ jsx(
15562
+ "g",
15149
15563
  {
15150
- cx: m.cx,
15151
- cy: m.cy,
15152
- rx: m.rPerp,
15153
- ry: m.rTilt,
15154
- transform: `rotate(${m.rotationDeg} ${m.cx} ${m.cy})`,
15155
- fill: color
15156
- },
15157
- `${keyPrefix}-nib-${j}`
15158
- )) });
15564
+ opacity,
15565
+ style: blendMode === "multiply" ? { mixBlendMode: "multiply" } : void 0,
15566
+ children: marks.map((m, j) => /* @__PURE__ */ jsx(
15567
+ "ellipse",
15568
+ {
15569
+ cx: m.cx,
15570
+ cy: m.cy,
15571
+ rx: m.rPerp,
15572
+ ry: m.rTilt,
15573
+ transform: `rotate(${m.rotationDeg} ${m.cx} ${m.cy})`,
15574
+ fill: color
15575
+ },
15576
+ `${keyPrefix}-nib-${j}`
15577
+ ))
15578
+ }
15579
+ );
15159
15580
  }
15160
15581
  function renderStrokeView(view, pressureSensitive, replayStyle, key) {
15161
15582
  if (view.nibMarks) {
15162
- return /* @__PURE__ */ jsx("g", { children: renderNibMarkStroke(view.nibMarks, view.color, view.opacity, key) }, key);
15583
+ return /* @__PURE__ */ jsx("g", { children: renderNibMarkStroke(view.nibMarks, view.color, view.opacity, view.blendMode, key) }, key);
15163
15584
  }
15164
15585
  if (pressureSensitive && view.circles) {
15165
- return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(view.circles, view.color, view.opacity, key) }, key);
15586
+ return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(view.circles, view.color, view.opacity, view.blendMode, key) }, key);
15166
15587
  }
15588
+ const style = {
15589
+ ...replayStyle ? { animation: replayStyle.animation, "--ink-path-length": replayStyle.pathLength } : {},
15590
+ ...view.blendMode === "multiply" ? { mixBlendMode: "multiply" } : {}
15591
+ };
15167
15592
  return /* @__PURE__ */ jsx(
15168
15593
  "path",
15169
15594
  {
@@ -15177,12 +15602,9 @@ function renderStrokeView(view, pressureSensitive, replayStyle, key) {
15177
15602
  vectorEffect: "non-scaling-stroke",
15178
15603
  ...replayStyle ? {
15179
15604
  strokeDasharray: replayStyle.strokeDasharray,
15180
- strokeDashoffset: replayStyle.strokeDashoffset,
15181
- style: {
15182
- animation: replayStyle.animation,
15183
- "--ink-path-length": replayStyle.pathLength
15184
- }
15185
- } : {}
15605
+ strokeDashoffset: replayStyle.strokeDashoffset
15606
+ } : {},
15607
+ ...Object.keys(style).length > 0 ? { style } : {}
15186
15608
  },
15187
15609
  key
15188
15610
  );
@@ -15262,10 +15684,11 @@ function renderGroup(children, parentGroupFill) {
15262
15684
  renderGroup(c.children, getGroupChildParentFill(c, parentGroupFill))
15263
15685
  ) : isI && ("svgData" in c && c.svgData || "imageData" in c && c.imageData) ? /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 pointer-events-none", style: getImageSurfaceStyle(c), children: [
15264
15686
  isImageTiled(c) ? /* @__PURE__ */ jsx(
15265
- "div",
15687
+ TiledImageLayer,
15266
15688
  {
15267
- className: "pointer-events-none select-none w-full h-full",
15268
- style: getImageTilingStyle(c)
15689
+ element: c,
15690
+ src: "svgData" in c && c.svgData ? c.svgData : c.imageData,
15691
+ className: "pointer-events-none select-none w-full h-full"
15269
15692
  }
15270
15693
  ) : /* @__PURE__ */ jsx(
15271
15694
  "img",
@@ -15827,18 +16250,15 @@ function InlineTextEditor({
15827
16250
  onCommit();
15828
16251
  },
15829
16252
  onKeyDown: (e) => {
15830
- if ((e.ctrlKey || e.metaKey) && !e.shiftKey && onFormatText) {
15831
- const key = e.key.toLowerCase();
15832
- if (key === "b" || key === "i" || key === "u") {
15833
- e.preventDefault();
15834
- e.stopPropagation();
15835
- const property = key === "b" ? "bold" : key === "i" ? "italic" : "underline";
15836
- const value = nextInlineStyleValue(property);
15837
- if (value !== void 0) {
15838
- onFormatText({ [property]: value });
15839
- }
15840
- return;
16253
+ const property = onFormatText ? mapInlineTextFormatKey(e) : null;
16254
+ if (property) {
16255
+ e.preventDefault();
16256
+ e.stopPropagation();
16257
+ const value = nextInlineStyleValue(property);
16258
+ if (value !== void 0) {
16259
+ onFormatText?.({ [property]: value });
15841
16260
  }
16261
+ return;
15842
16262
  }
15843
16263
  if (e.key === "Escape") {
15844
16264
  e.preventDefault();
@@ -15872,10 +16292,10 @@ function InlineTextEditor({
15872
16292
  function FailedToLoad() {
15873
16293
  return null;
15874
16294
  }
15875
- var LazyModel3DScene = React16.lazy(
16295
+ var LazyModel3DScene = React17.lazy(
15876
16296
  async () => {
15877
16297
  try {
15878
- return await import('./Model3DScene-DCTVSK2F.mjs');
16298
+ return await import('./Model3DScene-3GOC5HUS.mjs');
15879
16299
  } catch {
15880
16300
  return { default: FailedToLoad };
15881
16301
  }
@@ -15937,7 +16357,7 @@ function PosterFallback({
15937
16357
  }
15938
16358
  );
15939
16359
  }
15940
- var Model3DErrorBoundary = class extends React16.Component {
16360
+ var Model3DErrorBoundary = class extends React17.Component {
15941
16361
  constructor(props) {
15942
16362
  super(props);
15943
16363
  this.state = { hasError: false };
@@ -16023,9 +16443,13 @@ function buildTooltip(info) {
16023
16443
  function stopPointer(e) {
16024
16444
  e.stopPropagation();
16025
16445
  }
16026
- function OleActionFooter({ el, info }) {
16446
+ function OleActionFooter({
16447
+ el,
16448
+ info,
16449
+ showActions
16450
+ }) {
16027
16451
  const { t } = useTranslation();
16028
- if (!info.canDownload || !el.oleEmbeddedData) {
16452
+ if (!showActions || !info.canDownload || !el.oleEmbeddedData) {
16029
16453
  return null;
16030
16454
  }
16031
16455
  const downloadName = info.fileName ?? "embedded-object";
@@ -16068,7 +16492,10 @@ function OleActionFooter({ el, info }) {
16068
16492
  }
16069
16493
  );
16070
16494
  }
16071
- function OleRenderer({ element: el }) {
16495
+ function OleRenderer({
16496
+ element: el,
16497
+ showActions = true
16498
+ }) {
16072
16499
  const oleType = resolveOleType(el);
16073
16500
  const ariaLabel = getOleAriaLabel(el);
16074
16501
  const info = buildEmbedInfo(el);
@@ -16092,7 +16519,7 @@ function OleRenderer({ element: el }) {
16092
16519
  }
16093
16520
  ),
16094
16521
  renderOleBadge(oleType),
16095
- /* @__PURE__ */ jsx(OleActionFooter, { el, info })
16522
+ /* @__PURE__ */ jsx(OleActionFooter, { el, info, showActions })
16096
16523
  ]
16097
16524
  }
16098
16525
  );
@@ -16116,7 +16543,7 @@ function OleRenderer({ element: el }) {
16116
16543
  getOleIcon(oleType, color, 36),
16117
16544
  /* @__PURE__ */ jsx("span", { className: "mt-2 text-[12px] font-medium max-w-[90%] truncate", style: { color }, children: displayName }),
16118
16545
  /* @__PURE__ */ jsx("span", { className: "mt-0.5 text-[10px] text-white/50 max-w-[90%] truncate", children: info.readableSize ? `${label} \xB7 ${info.readableSize}` : label }),
16119
- /* @__PURE__ */ jsx(OleActionFooter, { el, info })
16546
+ /* @__PURE__ */ jsx(OleActionFooter, { el, info, showActions })
16120
16547
  ]
16121
16548
  }
16122
16549
  );
@@ -16131,10 +16558,10 @@ function SmartArtInlineNodeEditor({
16131
16558
  onCancel
16132
16559
  }) {
16133
16560
  const { t } = useTranslation();
16134
- const ref = React16.useRef(null);
16135
- const [value, setValue] = React16.useState(initialText);
16136
- const settled = React16.useRef(false);
16137
- React16.useEffect(() => {
16561
+ const ref = React17.useRef(null);
16562
+ const [value, setValue] = React17.useState(initialText);
16563
+ const settled = React17.useRef(false);
16564
+ React17.useEffect(() => {
16138
16565
  const el = ref.current;
16139
16566
  if (el) {
16140
16567
  el.focus();
@@ -16227,16 +16654,16 @@ function findNodeIdFromEvent(target) {
16227
16654
  return null;
16228
16655
  }
16229
16656
  function useSmartArtHoverState(containerRef, measureNodeRect = measureScreenNodeRect) {
16230
- const [hoveredNodeId, setHoveredNodeId] = React16.useState(null);
16231
- const [hoveredNodeRect, setHoveredNodeRect] = React16.useState(null);
16232
- const hideTimeoutRef = React16.useRef(null);
16233
- const cancelPendingHide = React16.useCallback(() => {
16657
+ const [hoveredNodeId, setHoveredNodeId] = React17.useState(null);
16658
+ const [hoveredNodeRect, setHoveredNodeRect] = React17.useState(null);
16659
+ const hideTimeoutRef = React17.useRef(null);
16660
+ const cancelPendingHide = React17.useCallback(() => {
16234
16661
  if (hideTimeoutRef.current !== null) {
16235
16662
  window.clearTimeout(hideTimeoutRef.current);
16236
16663
  hideTimeoutRef.current = null;
16237
16664
  }
16238
16665
  }, []);
16239
- const handleMouseMove = React16.useCallback(
16666
+ const handleMouseMove = React17.useCallback(
16240
16667
  (e, ignoreRef) => {
16241
16668
  const nodeEl = findNodeIdFromEvent(e.target);
16242
16669
  const container = containerRef.current;
@@ -16259,12 +16686,12 @@ function useSmartArtHoverState(containerRef, measureNodeRect = measureScreenNode
16259
16686
  },
16260
16687
  [containerRef, cancelPendingHide, measureNodeRect]
16261
16688
  );
16262
- const clearHover = React16.useCallback(() => {
16689
+ const clearHover = React17.useCallback(() => {
16263
16690
  cancelPendingHide();
16264
16691
  setHoveredNodeId(null);
16265
16692
  setHoveredNodeRect(null);
16266
16693
  }, [cancelPendingHide]);
16267
- React16.useEffect(() => cancelPendingHide, [cancelPendingHide]);
16694
+ React17.useEffect(() => cancelPendingHide, [cancelPendingHide]);
16268
16695
  return { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover };
16269
16696
  }
16270
16697
  var EDITOR_PADDING = 4;
@@ -16280,14 +16707,14 @@ function SmartArtEditableLayer({
16280
16707
  measureNodeRect = measureScreenNodeRect,
16281
16708
  children
16282
16709
  }) {
16283
- const containerRef = React16.useRef(null);
16284
- const styleBarRef = React16.useRef(null);
16285
- const [edit, setEdit] = React16.useState(null);
16710
+ const containerRef = React17.useRef(null);
16711
+ const styleBarRef = React17.useRef(null);
16712
+ const [edit, setEdit] = React17.useState(null);
16286
16713
  const { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover } = useSmartArtHoverState(
16287
16714
  containerRef,
16288
16715
  measureNodeRect
16289
16716
  );
16290
- const openEditor = React16.useCallback(
16717
+ const openEditor = React17.useCallback(
16291
16718
  (target) => {
16292
16719
  const nodeEl = findNodeIdFromEvent(target);
16293
16720
  const container = containerRef.current;
@@ -16916,7 +17343,7 @@ function sameDiagramReveal(prev, next) {
16916
17343
  }
16917
17344
  return true;
16918
17345
  }
16919
- var SmartArtRenderer = React16.memo(SmartArtRendererImpl, arePropsEqual);
17346
+ var SmartArtRenderer = React17.memo(SmartArtRendererImpl, arePropsEqual);
16920
17347
  function SmartArt3DView({
16921
17348
  element,
16922
17349
  className,
@@ -16993,7 +17420,12 @@ function groupIntoParagraphs2(element, fieldContext) {
16993
17420
  element,
16994
17421
  fieldContext ? (seg) => {
16995
17422
  if (seg.fieldType) {
16996
- const substituted = substituteFieldText(seg.text, seg.fieldType, fieldContext);
17423
+ const substituted = substituteFieldText(
17424
+ seg.text,
17425
+ seg.fieldType,
17426
+ fieldContext,
17427
+ seg.style?.language
17428
+ );
16997
17429
  if (substituted !== seg.text) {
16998
17430
  return { ...seg, text: substituted };
16999
17431
  }
@@ -17056,7 +17488,7 @@ function EnvelopeGlyph({
17056
17488
  }
17057
17489
  return /* @__PURE__ */ jsx("g", { "data-glyph-slices": glyph.slices.length, children: glyph.slices.map((slice, si) => {
17058
17490
  const clipId = `${glyphKey}-s${si}`;
17059
- return /* @__PURE__ */ jsxs(React16.Fragment, { children: [
17491
+ return /* @__PURE__ */ jsxs(React17.Fragment, { children: [
17060
17492
  /* @__PURE__ */ jsx("clipPath", { id: clipId, clipPathUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx(
17061
17493
  "rect",
17062
17494
  {
@@ -17126,6 +17558,22 @@ function WarpedText({
17126
17558
  const baseFontFamily = textEl.textStyle?.fontFamily ? getSubstituteFontFamily(textEl.textStyle.fontFamily) : DEFAULT_FONT_FAMILY;
17127
17559
  const baseFill = normalizeHexColor(textEl.textStyle?.color, fallbackColor);
17128
17560
  if (hasGlyphEnvelope(preset)) {
17561
+ const perLine = buildGlyphEnvelopeBlock(
17562
+ preset,
17563
+ paragraphs.map(
17564
+ (para) => para.segments.map((seg, i) => ({
17565
+ text: seg.text,
17566
+ font: resolveSegmentFont(seg, textEl),
17567
+ segmentIndex: i
17568
+ }))
17569
+ ),
17570
+ width,
17571
+ height,
17572
+ align,
17573
+ warpAdj,
17574
+ warpAdj2,
17575
+ getGlyphOutline
17576
+ );
17129
17577
  return /* @__PURE__ */ jsx(
17130
17578
  "svg",
17131
17579
  {
@@ -17136,23 +17584,7 @@ function WarpedText({
17136
17584
  style: { overflow: "visible", position: "absolute", inset: 0, pointerEvents: "none" },
17137
17585
  "aria-hidden": "true",
17138
17586
  children: paragraphs.map((para, paraIdx) => {
17139
- const segsInput = para.segments.map((seg, i) => ({
17140
- text: seg.text,
17141
- font: resolveSegmentFont(seg, textEl),
17142
- segmentIndex: i
17143
- }));
17144
- const glyphs = buildGlyphEnvelope(
17145
- preset,
17146
- segsInput,
17147
- width,
17148
- height,
17149
- align,
17150
- warpAdj,
17151
- warpAdj2,
17152
- paraIdx,
17153
- lineCount,
17154
- getGlyphOutline
17155
- );
17587
+ const glyphs = perLine[paraIdx] ?? [];
17156
17588
  return /* @__PURE__ */ jsx(
17157
17589
  EnvelopeLine,
17158
17590
  {
@@ -17426,14 +17858,30 @@ function ZoomElementRenderer({
17426
17858
  onClick: (event) => {
17427
17859
  if (isPresentationMode && onZoomClick) {
17428
17860
  event.stopPropagation();
17429
- onZoomClick(tile.targetSlideIndex, sourceSlideIndex ?? 0);
17861
+ onZoomClick(
17862
+ {
17863
+ targetSlideIndex: tile.targetSlideIndex,
17864
+ targetSectionId: tile.sectionId,
17865
+ returnToParent: tile.returnToParent,
17866
+ transitionDurationMs: tile.transitionDurationMs
17867
+ },
17868
+ sourceSlideIndex ?? 0
17869
+ );
17430
17870
  }
17431
17871
  },
17432
17872
  onKeyDown: (event) => {
17433
17873
  if (isPresentationMode && onZoomClick && (event.key === "Enter" || event.key === " ")) {
17434
17874
  event.preventDefault();
17435
17875
  event.stopPropagation();
17436
- onZoomClick(tile.targetSlideIndex, sourceSlideIndex ?? 0);
17876
+ onZoomClick(
17877
+ {
17878
+ targetSlideIndex: tile.targetSlideIndex,
17879
+ targetSectionId: tile.sectionId,
17880
+ returnToParent: tile.returnToParent,
17881
+ transitionDurationMs: tile.transitionDurationMs
17882
+ },
17883
+ sourceSlideIndex ?? 0
17884
+ );
17437
17885
  }
17438
17886
  },
17439
17887
  children: tile.imageSrc ? /* @__PURE__ */ jsx(
@@ -17461,7 +17909,10 @@ function ZoomElementRenderer({
17461
17909
  return;
17462
17910
  }
17463
17911
  e.stopPropagation();
17464
- onZoomClick(element.targetSlideIndex, sourceSlideIndex ?? 0);
17912
+ const target = resolveZoomNavigationTarget(element);
17913
+ if (target) {
17914
+ onZoomClick(target, sourceSlideIndex ?? 0);
17915
+ }
17465
17916
  };
17466
17917
  const handleKeyDown = (e) => {
17467
17918
  if (!isPresentationMode || !onZoomClick) {
@@ -17470,7 +17921,10 @@ function ZoomElementRenderer({
17470
17921
  if (e.key === "Enter" || e.key === " ") {
17471
17922
  e.preventDefault();
17472
17923
  e.stopPropagation();
17473
- onZoomClick(element.targetSlideIndex, sourceSlideIndex ?? 0);
17924
+ const target = resolveZoomNavigationTarget(element);
17925
+ if (target) {
17926
+ onZoomClick(target, sourceSlideIndex ?? 0);
17927
+ }
17474
17928
  }
17475
17929
  };
17476
17930
  const hasPreviewImage = Boolean(element.imageData);
@@ -17752,7 +18206,16 @@ function renderBody(options) {
17752
18206
  });
17753
18207
  }
17754
18208
  if (el.type === "ole") {
17755
- return /* @__PURE__ */ jsx(OleRenderer, { element: el });
18209
+ return /* @__PURE__ */ jsx(
18210
+ OleRenderer,
18211
+ {
18212
+ element: el,
18213
+ showActions: oleActionsVisible({
18214
+ presenting: isPresentationPassive === true,
18215
+ preview: isStaticSurface === true
18216
+ })
18217
+ }
18218
+ );
17756
18219
  }
17757
18220
  if (doGrp && el.type === "group" && el.children) {
17758
18221
  if (renderGroupChild) {
@@ -17984,7 +18447,7 @@ function StaticElementRendererImpl({
17984
18447
  }
17985
18448
  );
17986
18449
  }
17987
- var StaticElementRenderer = React16.memo(StaticElementRendererImpl);
18450
+ var StaticElementRenderer = React17.memo(StaticElementRendererImpl);
17988
18451
  StaticElementRenderer.displayName = "StaticElementRenderer";
17989
18452
  function SlideLayer({
17990
18453
  slide,