pptx-react-viewer 4.48.0 → 4.50.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 +126 -0
- package/dist/{AiChatPanel-NKTBHT5B.mjs → AiChatPanel-VJV5OEG2.mjs} +1 -1
- package/dist/AiChatPanel-VJV5OEG2.mjs.br +0 -0
- package/dist/AiChatPanel-VJV5OEG2.mjs.gz +0 -0
- package/dist/{AiChatPanel-S4WNQCY4.js → AiChatPanel-WYAL24DX.js} +9 -9
- package/dist/AiChatPanel-WYAL24DX.js.br +0 -0
- package/dist/AiChatPanel-WYAL24DX.js.gz +0 -0
- package/dist/{chunk-5FAX7F3O.js → chunk-4OF7X5EE.js} +1754 -3189
- package/dist/chunk-4OF7X5EE.js.br +0 -0
- package/dist/chunk-4OF7X5EE.js.gz +0 -0
- package/dist/{chunk-H7JRMKYC.mjs → chunk-5JJQLK7N.mjs} +542 -1977
- package/dist/chunk-5JJQLK7N.mjs.br +0 -0
- package/dist/chunk-5JJQLK7N.mjs.gz +0 -0
- package/dist/{chunk-PFV626ED.mjs → chunk-77IXTLKU.mjs} +3 -4
- package/dist/chunk-77IXTLKU.mjs.br +0 -0
- package/dist/chunk-77IXTLKU.mjs.gz +0 -0
- package/dist/{chunk-JKZNL6HP.js → chunk-D5NXYXPP.js} +773 -1245
- package/dist/chunk-D5NXYXPP.js.br +0 -0
- package/dist/chunk-D5NXYXPP.js.gz +0 -0
- package/dist/chunk-DDJ634MV.js.br +0 -0
- package/dist/chunk-DDJ634MV.js.gz +0 -0
- package/dist/{chunk-JAI42EXQ.js → chunk-JWNBTFZZ.js} +0 -6
- package/dist/chunk-JWNBTFZZ.js.br +0 -0
- package/dist/chunk-JWNBTFZZ.js.gz +0 -0
- package/dist/{chunk-JHQHAO43.mjs → chunk-QHGEPW5G.mjs} +596 -1068
- package/dist/chunk-QHGEPW5G.mjs.br +0 -0
- package/dist/chunk-QHGEPW5G.mjs.gz +0 -0
- package/dist/chunk-QIUK53JR.mjs.br +0 -0
- package/dist/chunk-QIUK53JR.mjs.gz +0 -0
- package/dist/i18n/de.cjs +1138 -221
- package/dist/i18n/de.cjs.br +0 -0
- package/dist/i18n/de.cjs.gz +0 -0
- package/dist/i18n/de.mjs +1138 -221
- package/dist/i18n/de.mjs.br +0 -0
- package/dist/i18n/de.mjs.gz +0 -0
- package/dist/i18n/es.cjs +1138 -221
- package/dist/i18n/es.cjs.br +0 -0
- package/dist/i18n/es.cjs.gz +0 -0
- package/dist/i18n/es.mjs +1138 -221
- package/dist/i18n/es.mjs.br +0 -0
- package/dist/i18n/es.mjs.gz +0 -0
- package/dist/i18n/fr.cjs +1138 -221
- package/dist/i18n/fr.cjs.br +0 -0
- package/dist/i18n/fr.cjs.gz +0 -0
- package/dist/i18n/fr.mjs +1138 -221
- package/dist/i18n/fr.mjs.br +0 -0
- package/dist/i18n/fr.mjs.gz +0 -0
- package/dist/i18n/zh-CN.cjs +1138 -221
- package/dist/i18n/zh-CN.cjs.br +0 -0
- package/dist/i18n/zh-CN.cjs.gz +0 -0
- package/dist/i18n/zh-CN.mjs +1138 -221
- package/dist/i18n/zh-CN.mjs.br +0 -0
- package/dist/i18n/zh-CN.mjs.gz +0 -0
- package/dist/index.d.ts +5 -15
- package/dist/index.js +24 -24
- 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 +105 -94
- 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/pptx-viewer-canvas.css +1 -1
- package/dist/pptx-viewer-canvas.css.br +0 -0
- package/dist/pptx-viewer-canvas.css.gz +0 -0
- package/dist/pptx-viewer.css +1 -1
- package/dist/pptx-viewer.css.br +0 -0
- package/dist/pptx-viewer.css.gz +0 -0
- package/dist/viewer/index.d.ts +7 -12
- package/dist/viewer/index.js +19 -19
- 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/dist/{y-webrtc-2H7UYAQD.mjs → y-webrtc-HRGGVQZH.mjs} +1 -1
- package/dist/y-webrtc-HRGGVQZH.mjs.br +0 -0
- package/dist/y-webrtc-HRGGVQZH.mjs.gz +0 -0
- package/dist/{y-webrtc-DVPQNFLL.js → y-webrtc-QVVT5PCK.js} +124 -124
- package/dist/y-webrtc-QVVT5PCK.js.br +0 -0
- package/dist/y-webrtc-QVVT5PCK.js.gz +0 -0
- package/dist/{y-websocket-WORVRRQS.mjs → y-websocket-46M6UFI7.mjs} +1 -1
- package/dist/y-websocket-46M6UFI7.mjs.br +0 -0
- package/dist/y-websocket-46M6UFI7.mjs.gz +0 -0
- package/dist/{y-websocket-TN4OKPXQ.js → y-websocket-EDOMWMAD.js} +78 -78
- package/dist/y-websocket-EDOMWMAD.js.br +0 -0
- package/dist/y-websocket-EDOMWMAD.js.gz +0 -0
- package/package.json +3 -3
- package/dist/AiChatPanel-NKTBHT5B.mjs.br +0 -0
- package/dist/AiChatPanel-NKTBHT5B.mjs.gz +0 -0
- package/dist/AiChatPanel-S4WNQCY4.js.br +0 -0
- package/dist/AiChatPanel-S4WNQCY4.js.gz +0 -0
- package/dist/chunk-3VVZGHHY.mjs.br +0 -0
- package/dist/chunk-3VVZGHHY.mjs.gz +0 -0
- package/dist/chunk-5FAX7F3O.js.br +0 -0
- package/dist/chunk-5FAX7F3O.js.gz +0 -0
- package/dist/chunk-H7JRMKYC.mjs.br +0 -0
- package/dist/chunk-H7JRMKYC.mjs.gz +0 -0
- package/dist/chunk-JAI42EXQ.js.br +0 -0
- package/dist/chunk-JAI42EXQ.js.gz +0 -0
- package/dist/chunk-JHQHAO43.mjs.br +0 -0
- package/dist/chunk-JHQHAO43.mjs.gz +0 -0
- package/dist/chunk-JKZNL6HP.js.br +0 -0
- package/dist/chunk-JKZNL6HP.js.gz +0 -0
- package/dist/chunk-NUNDT6EL.js.br +0 -0
- package/dist/chunk-NUNDT6EL.js.gz +0 -0
- package/dist/chunk-PFV626ED.mjs.br +0 -0
- package/dist/chunk-PFV626ED.mjs.gz +0 -0
- package/dist/y-webrtc-2H7UYAQD.mjs.br +0 -0
- package/dist/y-webrtc-2H7UYAQD.mjs.gz +0 -0
- package/dist/y-webrtc-DVPQNFLL.js.br +0 -0
- package/dist/y-webrtc-DVPQNFLL.js.gz +0 -0
- package/dist/y-websocket-TN4OKPXQ.js.br +0 -0
- package/dist/y-websocket-TN4OKPXQ.js.gz +0 -0
- package/dist/y-websocket-WORVRRQS.mjs.br +0 -0
- package/dist/y-websocket-WORVRRQS.mjs.gz +0 -0
- package/dist/{chunk-NUNDT6EL.js → chunk-DDJ634MV.js} +436 -436
- package/dist/{chunk-3VVZGHHY.mjs → chunk-QIUK53JR.mjs} +436 -436
|
@@ -1,7 +1,7 @@
|
|
|
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, 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,
|
|
2
|
-
import { defineThreeViewElement, MIN_TOUCH_TARGET_PX, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createSyncGate, clearLocalAwareness, validateRoomId, createDepartureChannel, resolveTransportForServerUrl, isMixedContentBlocked, CONNECTION_TIMEOUT_MS, registerCollaborationTeardown, createPresenceProjector, BROADCAST_THROTTLE_MS, sanitizeColor, 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, initialInspectorOpen, createPresentationLoadResources, collectMediaElements, resolveMediaElementSource, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, resolveTextFillBlipUrls, seedRecentColors, resolveAuthoredCustomShowId, GlyphOutlineFontCache, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, resolveInitialSlideIndex, resolveAutosaveIntervalMs, shouldWriteAutosaveSnapshot, saveAutosaveSnapshot, autosaveSnapshotMark, updateMasterViewElement, updateElement, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, canMergeShapes, canInteractWithElement, prepareHtml2CanvasClone, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, DEFAULT_VIEWER_OPTIONS, resolveImageResolutionScale, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, resolveAuthoredSlideRange, mayLeaveSlideShow, buildDeckSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, shouldProbeAutosaveRecovery, probeAutosaveRecovery, acceptAutosaveRecovery, acknowledgeAutosaveRecovery, discardAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, rasterResultToPngBlob, downloadBlob, elementPictureFilename, canEditElementPoints, selectTrustedEmbeddedFonts, resolveFontWeight, resolveFontItalic, collectReferencedFontFamilies, resolveGoogleWebfontHref, syncGoogleWebfontStylesheet, selectGoogleWebfontFamilies, fetchGoogleWebfontOutlineBytes, isFeatureEnabled, mapSlideShowStartKey, mapCustomizedEditorKey, isEditorControlTarget, isEditorTextInputTarget, parentSelection, textFontSizePtToPx, stepFontSizePt, textFontSizePxToPt, cycleSelectableElement, createCustomizationController, prepareElementForInsertion, slideSpaceElement, autosaveStatusKind, createViewerOptionsStore, observeYDocSlides, LOCAL_SYNC_ORIGIN, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, isKeyboardOpen, scopeLayoutOptionsToSlide, checkModifyPassword, 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, elementIdSelector, createRotationDrag, isActionHidden, buildInlineTextCommitPatch, resolveInlineEditAutoFitHeight, resolveInlineEditNormAutofitShrink, setPendingCaretPoint, drillSelectionForDoubleClick, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, contextMenuInspectorAnchor, savedPresentationFileName, deliverSavedPresentation, exportDeckJson, 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, resolveExportCaptureDecision, recordProgressPercent, computeGridSpacingPx as computeGridSpacingPx$1, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, overlayMasterViewInlineSnapshot, overlayInlineTextSnapshot, rasterizeElement, cloneElementForPaste, applyPasteSpecialFormat, buildRasterPictureElement, cloneElementUpdates, assertElementUpdateTarget, prepareElementUpdateBatch, createWriteBackScheduler, writeBackReport, 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, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, canDrillDown, computeSmartArtElementLayout, flattenNodes, 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, TOOLBAR_TABS, isEnterableGroup, memberChainAtPoint, findElementPath, drillSelectionForClick, 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, SMARTART_DEFAULT_PALETTE, computeDrawingViewBox, projectDrawingShapes, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, measureSvgViewportRect, modelDataToBlobUrl, resolveZoomNavigationTarget, inlineListBodyText, createInlineListSeed, readListActivationSelection, createInlineListModelObserver, attachCollaborationInlineEditor, bindInlineListParagraph, bindInlineListRun, attachInlineListController, restoreInlineListBodySelection, isBulletMarkerSegment, resolveChartThreeViewSpec, applyChart3DDrag, applyChart3DSelect, findChartPartTarget, withChartTitle, resolveSmartArtThreeViewSpec, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, hasGlyphEnvelope, buildGlyphEnvelopeBlock, getWarpPath, isWedgeCalloutPresetShape, getAriaRole as getAriaRole$1, isElementActionable, buildSmartArtPresetData, classifyMediaType, publishLiveGeometry, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, rasterizeElementTiledToCanvas, borrowExternalCollaborationAwareness, observeExternalCollaborationSession, clampGifDimensions, rasterResultToPngDataUrl, shouldConfirmExternalHyperlink, centeredSvgTextLines, findSmartArtNodeText, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, advanceChartMarkDrag, advanceChartValueDrag, resolveChartKind, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, commitSmartArtNodeFill, commitSmartArtNodeText, groupIntoParagraphs as groupIntoParagraphs$1, createGlyphOutlineLookup, applyResize, lockResizeAspect, snapBoxToGrid, applyMotionPathPreset, computeInlineEditorRect, smartArtNodeAtPoint, 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, 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-77IXTLKU.mjs';
|
|
2
|
+
import { defineThreeViewElement, MIN_TOUCH_TARGET_PX, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createCollaborationSessionController, registerCollaborationTeardown, createPresenceProjector, BROADCAST_THROTTLE_MS, sanitizeColor, createEditorHistoryController, createWheelStepBuffer, createViewerZoomStore, clampZoomScale, mapEditingWheel, createActiveAnimationGroup, cancelBuildReveal, clearPlaybackTimers, PresentationAnimationController, resolveMediaTimeNodeElementIds, resolveMediaBookmarkTimesMs, advanceMainSequence, playGroup, PRESENTATION_HASH, PRESENTATION_NONCE_KEY, PRESENTATION_CHANNEL_NAME, swapPresentationWindows, PRESENTATION_MESSAGE_ORIGIN, clearAudienceContent, buildPresentationAudienceUrl, resolveAudienceScreenPlacement, placeAudienceWindow, storeAudienceContent, isPresentationSessionMessage, endAudienceDisplay, createPresentationKeyBuffer, acceptsPresentationInput, resolveAutoAdvanceDelayMs, resolveShowBackward, resolveShowForward, beginZoomExcursion, buildZoomTransitionOverride, createPresenterShowGuard, firstShowSlideIndex, attachPresentationVisibilityPause, presentationEntrySlideIndex, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, visibleTemplateElements, createCollaborationLivePatcher, reportInlineTextDraft, initialInspectorOpen, createPresentationLoadResources, collectMediaElements, resolveMediaElementSource, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, resolveTextFillBlipUrls, seedRecentColors, resolveAuthoredCustomShowId, GlyphOutlineFontCache, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, resolveInitialSlideIndex, resolveAutosaveIntervalMs, createAutosaveController, saveAutosaveSnapshot, updateMasterViewElement, updateElement, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, canMergeShapes, canInteractWithElement, prepareHtml2CanvasClone, html2canvasCaptureScope, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, DEFAULT_VIEWER_OPTIONS, resolveImageResolutionScale, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, resolveAuthoredSlideRange, mayLeaveSlideShow, buildDeckSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, createAutosaveRecoveryController, discardAutosaveRecovery, probeAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, rasterResultToPngBlob, downloadBlob, elementPictureFilename, canEditElementPoints, selectTrustedEmbeddedFonts, resolveFontWeight, resolveFontItalic, collectReferencedFontFamilies, resolveGoogleWebfontHref, syncGoogleWebfontStylesheet, selectGoogleWebfontFamilies, fetchGoogleWebfontOutlineBytes, dispatchEditorKey, isFeatureEnabled, parentSelection, textFontSizePtToPx, stepFontSizePt, textFontSizePxToPt, cycleSelectableElement, createCustomizationController, prepareElementForInsertion, slideSpaceElement, autosaveStatusKind, createViewerOptionsStore, observeYDocSlides, LOCAL_SYNC_ORIGIN, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, isKeyboardOpen, scopeLayoutOptionsToSlide, INITIAL_READ_ONLY_SESSION, readOnlySessionActions, applyReadOnlySessionEvent, readOnlyBannerVisible, readOnlyLocked, viewerPreferencesFromViewProperties, DEFAULT_VIEWER_PREFERENCES, viewPropertiesPatchFromPreferences, resolveCollaborationConfig, openPptxFile, readBackstageRecentFile, resolveCollaborationShellEditability, resolveCollaborationShellState, getResizeHandleHitAreaStyle, resolveElementInteractivity, getBackgroundAnimationState, getShapeEffectLayerPlacement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, isMediaFullscreenActive, shouldRenderHitTarget, elementHitTargetStyle, getShapeEffectAnimationLayerStyle, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, resolvePalette as resolvePalette$1, mediaTransportVisible, oleActionsVisible, getGroupChildParentFill, deviceStrokeStageStyle, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, getSlideTransitionAnimations, getFragmentedTransitionDescriptor, SLIDE_TRANSITION_KEYFRAMES, isActionHidden, buildInlineTextCommitPatch, resolveInlineEditAutoFitHeight, resolveInlineEditNormAutofitShrink, setPendingCaretPoint, resolveGroupDoubleClickTarget, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, contextMenuInspectorAnchor, savedPresentationFileName, deliverSavedPresentation, exportDeckJson, mapCustomizedEditorKey, isEditorTextInputTarget, groupElements, generateElementId, ungroupElements, alignElements, distributeElements, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, planMergeShapes, applyMergeShapesPlan, mapPresentationKey, lastShowSlideIndex, mapPresentationWheel, openPendingPrintWindow, computeColorFilter, filterHiddenSlideIndices, computeSlideIndices, buildPrintDocument, finishPrintWindow, buildPrintHtmlDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, insertSlidePaste, applySlidePasteTemplates, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, needsOwnedSession, openOwnedCollaboration, resolveViewportFitOptions, editorViewportFitFor, calculateViewportFit, observeViewportClientSize, scheduleAutoAdvanceChain, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, resolveTransitionSoundAction, runPresentationAction, safeOpenUrl, buildRunProgramNotice, toggleStageElementMedia, resolveOleVerbTarget, downloadDataUrl, openUrlInNewTab, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, slideSpaceMembers, remapTextToSegments, getInlineEditorSelectionResult, buildInlineListStylePatch, applyActiveInlineListFormatting, applyListStyleUpdate, setPendingSelectionRestore, applyTextStyleUpdate, toggleSelectionBullets, transformInlineListCase, applyCaseTransformToSegments, transformTextCase, createGestureController, resolveExportCaptureDecision, recordProgressPercent, computeGridSpacingPx as computeGridSpacingPx$1, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, overlayMasterViewInlineSnapshot, overlayInlineTextSnapshot, rasterizeElement, cloneElementForPaste, applyPasteSpecialFormat, buildRasterPictureElement, cloneElementUpdates, assertElementUpdateTarget, prepareElementUpdateBatch, createWriteBackScheduler, writeBackReport, createSyncGate, observeExternalCollaborationReadiness, resolveHistoryDepth, createBackstagePresentation, buildFieldSubstitutionContext, getImageColorWashStyle, attachRotateHandlePlacement, getSelectionControlArtworkStyle, getSelectionOutlineColor, paintedStrokeWidth, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, paintedElementSize, MEDIA_FULLSCREEN_OVERLAY_STYLE, elementContainerHeightStyle, getAnimationOpacity, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, getEffectStyleSource, getBevelLightingSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, strokeOutlineViewBox, buildSummaryZoomView, readEditableText, placeCaretAt, takePendingCaretPoint, getPendingSelectionRestore, restoreSegmentSelection, mapInlineTextFormatKey, mapInlineEditorChord, subscribeBarFacePicturePixelSamples, getBarFacePicturePixelSampleVersion, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, chartFormatTargetFromEvent, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, getAriaRoleDescription, getAriaLabel, elementIdSelector, TOOLBAR_TABS, resolveGroupPressTarget, scrollInspectorSectionIntoView, computeScrollDelta, replyToCommentInList, removeTableElementColumn, insertTableElementColumn, removeTableElementRow, insertTableElementRow, withCellStyle, setCellText, pickSupportedMimeType, WEBM_MIME_CANDIDATES, fpsToFrameIntervalMs, segmentFrameCount, stopCaptureStream, GIF_POST_CAPTURE_MAX_SIDE, encodeGif, rasterizeElementTiles, placeTileOnPage, PDF_SLIDES_PAGE_WIDTH_PT, PDF_SLIDES_PAGE_HEIGHT_PT, createSnapshotTextPositions, resolvePresentationAction, getImageSvgFilters, getCachedNativeImageSize, probeNativeImageSize, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, svgLineCap, screenStrokeWidth, connectorWrapperTransform, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, modelDataToBlobUrl, resolveZoomNavigationTarget, inlineListBodyText, createInlineListSeed, readListActivationSelection, createInlineListModelObserver, attachCollaborationInlineEditor, bindInlineListParagraph, bindInlineListRun, attachInlineListController, restoreInlineListBodySelection, isBulletMarkerSegment, resolveChartThreeViewSpec, applyChart3DDrag, applyChart3DSelect, canDrillDown, findChartPartTarget, withChartTitle, resolveSmartArtThreeViewSpec, measureSvgViewportRect, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, hasGlyphEnvelope, buildGlyphEnvelopeBlock, getWarpPath, isWedgeCalloutPresetShape, getAriaRole as getAriaRole$1, isElementActionable, buildSmartArtPresetData, classifyMediaType, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, rasterizeElementTiledToCanvas, borrowExternalCollaborationAwareness, observeExternalCollaborationSession, publishLiveGeometry, clampGifDimensions, rasterResultToPngDataUrl, shouldConfirmExternalHyperlink, advanceChartMarkDrag, advanceChartValueDrag, resolveChartKind, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, findSmartArtNodeText, commitSmartArtNodeFill, commitSmartArtNodeText, groupIntoParagraphs as groupIntoParagraphs$1, createGlyphOutlineLookup, applyMotionPathPreset, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, computeSmartArtElementLayout, flattenNodes, computeInlineEditorRect, smartArtNodeAtPoint, SMARTART_DEFAULT_PALETTE, computeDrawingViewBox, projectDrawingShapes, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, centeredSvgTextLines, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, bringForward, sendBackward, bringToFront, sendToBack } from 'ooxml-ui/pptx';
|
|
3
3
|
export { DUOTONE_PRESETS, MOBILE_BREAKPOINT, SLIDE_TRANSITION_KEYFRAMES, TABLET_BREAKPOINT, clearAudienceContent, computeVirtualRange, downloadBlob, getSlideTransitionAnimations, loadAudienceContent, storeAudienceContent } from 'ooxml-ui/pptx';
|
|
4
|
-
import React17, { useRef, useState, useCallback, useEffect, useMemo, useContext, useLayoutEffect, createContext, useImperativeHandle,
|
|
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
6
|
import { PptxHandler, EncryptedFileError, hasShapeProperties, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, guidePxToEmu, hasTextProperties, isInkElement, duplicateSlide, buildThemeColorMap, reResolveSlideColors, reResolveElementColors, isImageLikeElement, SvgExporter, reResolveElementFonts, getSubstituteFontFamily, elementActionToPptxAction, setSmartArtNodeStyle, updateSmartArtNodeText } from 'ooxml-core/pptx';
|
|
7
7
|
import { translationsEn } from 'ooxml-ui/pptx/i18n';
|
|
@@ -75,240 +75,59 @@ function useVirtualizedSlides({
|
|
|
75
75
|
scrollToIndex
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
+
function useController(controller) {
|
|
79
|
+
return useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/viewer/hooks/collaboration/collaboration-modules.ts
|
|
83
|
+
var collabModules = {
|
|
84
|
+
loadYjs: () => import('yjs'),
|
|
85
|
+
loadWebsocket: () => import('./y-websocket-46M6UFI7.mjs'),
|
|
86
|
+
loadWebrtc: () => import('./y-webrtc-HRGGVQZH.mjs')
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// src/viewer/hooks/collaboration/useYjsProvider.ts
|
|
78
90
|
function useYjsProvider({ config: inputConfig }) {
|
|
79
91
|
const config = inputConfig?.externalSession ? void 0 : inputConfig;
|
|
80
|
-
const [
|
|
81
|
-
|
|
82
|
-
const [doc, setDoc] = useState(null);
|
|
83
|
-
const [clientId, setClientId] = useState(null);
|
|
84
|
-
const [synced, setSynced] = useState(false);
|
|
85
|
-
const cleanupRef = useRef(null);
|
|
86
|
-
const generationRef = useRef(0);
|
|
87
|
-
const timeoutRef = useRef(null);
|
|
88
|
-
const departureRef = useRef(null);
|
|
89
|
-
const gateRef = useRef(null);
|
|
90
|
-
if (!gateRef.current) {
|
|
91
|
-
gateRef.current = createSyncGate(() => setSynced(true));
|
|
92
|
-
}
|
|
93
|
-
const teardown = useCallback(() => {
|
|
94
|
-
generationRef.current += 1;
|
|
95
|
-
if (timeoutRef.current) {
|
|
96
|
-
clearTimeout(timeoutRef.current);
|
|
97
|
-
timeoutRef.current = null;
|
|
98
|
-
}
|
|
99
|
-
gateRef.current?.reset();
|
|
100
|
-
setSynced(false);
|
|
101
|
-
cleanupRef.current?.();
|
|
102
|
-
cleanupRef.current = null;
|
|
103
|
-
}, []);
|
|
104
|
-
const announceDeparture = useCallback(() => {
|
|
105
|
-
departureRef.current?.announce();
|
|
106
|
-
departureRef.current?.dispose();
|
|
107
|
-
departureRef.current = null;
|
|
108
|
-
}, []);
|
|
109
|
-
const buildCleanup = useCallback(
|
|
110
|
-
(provider, yDoc) => () => {
|
|
111
|
-
announceDeparture();
|
|
112
|
-
clearLocalAwareness(provider.awareness);
|
|
113
|
-
provider.destroy();
|
|
114
|
-
yDoc.destroy();
|
|
115
|
-
setDoc(null);
|
|
116
|
-
setAwareness(null);
|
|
117
|
-
setClientId(null);
|
|
118
|
-
setStatus("disconnected");
|
|
119
|
-
},
|
|
120
|
-
[announceDeparture]
|
|
92
|
+
const [controller] = useState(
|
|
93
|
+
() => createCollaborationSessionController({ modules: collabModules, registerTeardown: false })
|
|
121
94
|
);
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
setStatus("connecting");
|
|
128
|
-
try {
|
|
129
|
-
const [Y, { WebrtcProvider }] = await Promise.all([import('yjs'), import('./y-webrtc-2H7UYAQD.mjs')]);
|
|
130
|
-
if (generation !== generationRef.current) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const yDoc = new Y.Doc();
|
|
134
|
-
const opts = {};
|
|
135
|
-
if (config.signaling && config.signaling.length > 0) {
|
|
136
|
-
opts.signaling = config.signaling;
|
|
137
|
-
}
|
|
138
|
-
if (config.authToken) {
|
|
139
|
-
opts.password = config.authToken;
|
|
140
|
-
}
|
|
141
|
-
const roomId = validateRoomId(config.roomId);
|
|
142
|
-
const provider = new WebrtcProvider(roomId, yDoc, opts);
|
|
143
|
-
departureRef.current = createDepartureChannel(roomId, provider.awareness);
|
|
144
|
-
setDoc(yDoc);
|
|
145
|
-
setAwareness(provider.awareness);
|
|
146
|
-
setClientId(provider.awareness.clientID);
|
|
147
|
-
setStatus("connected");
|
|
148
|
-
const handleSynced = (event) => {
|
|
149
|
-
if (event?.synced !== false) {
|
|
150
|
-
gateRef.current?.open();
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
provider.on("synced", handleSynced);
|
|
154
|
-
gateRef.current?.arm();
|
|
155
|
-
const handleStatus = (event) => {
|
|
156
|
-
if (event.connected === false) {
|
|
157
|
-
setStatus("disconnected");
|
|
158
|
-
gateRef.current?.reset();
|
|
159
|
-
setSynced(false);
|
|
160
|
-
gateRef.current?.arm();
|
|
161
|
-
} else if (event.connected) {
|
|
162
|
-
setStatus("connected");
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
provider.on("status", handleStatus);
|
|
166
|
-
const baseCleanup = buildCleanup(provider, yDoc);
|
|
167
|
-
cleanupRef.current = () => {
|
|
168
|
-
provider.off("synced", handleSynced);
|
|
169
|
-
provider.off("status", handleStatus);
|
|
170
|
-
baseCleanup();
|
|
171
|
-
};
|
|
172
|
-
} catch (err) {
|
|
173
|
-
if (generation !== generationRef.current) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
console.warn(
|
|
177
|
-
"[pptx-viewer] WebRTC collaboration packages not available:",
|
|
178
|
-
err instanceof Error ? err.message : err
|
|
179
|
-
);
|
|
180
|
-
setStatus("error");
|
|
181
|
-
}
|
|
182
|
-
}, [config?.roomId, config?.authToken, config?.signaling, buildCleanup]);
|
|
183
|
-
const init = useCallback(async () => {
|
|
184
|
-
teardown();
|
|
185
|
-
const generation = generationRef.current;
|
|
95
|
+
const state = useController(controller);
|
|
96
|
+
const signalingKey = config?.signaling?.join("\n");
|
|
97
|
+
useEffect(() => {
|
|
186
98
|
if (!config) {
|
|
99
|
+
controller.stop();
|
|
187
100
|
return;
|
|
188
101
|
}
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
);
|
|
199
|
-
setStatus("error");
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
setStatus("connecting");
|
|
203
|
-
try {
|
|
204
|
-
const [Y, { WebsocketProvider }] = await Promise.all([import('yjs'), import('./y-websocket-WORVRRQS.mjs')]);
|
|
205
|
-
if (generation !== generationRef.current) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
const yDoc = new Y.Doc();
|
|
209
|
-
const provider = new WebsocketProvider(config.serverUrl, roomId, yDoc, {
|
|
210
|
-
params: config.authToken ? { token: config.authToken } : void 0
|
|
211
|
-
});
|
|
212
|
-
departureRef.current = createDepartureChannel(roomId, provider.awareness);
|
|
213
|
-
let connected = false;
|
|
214
|
-
const handleStatus = (event) => {
|
|
215
|
-
if (event.status === "connected") {
|
|
216
|
-
connected = true;
|
|
217
|
-
if (timeoutRef.current) {
|
|
218
|
-
clearTimeout(timeoutRef.current);
|
|
219
|
-
timeoutRef.current = null;
|
|
220
|
-
}
|
|
221
|
-
setStatus("connected");
|
|
222
|
-
gateRef.current?.arm();
|
|
223
|
-
} else if (event.status === "disconnected") {
|
|
224
|
-
setStatus("disconnected");
|
|
225
|
-
gateRef.current?.reset();
|
|
226
|
-
setSynced(false);
|
|
227
|
-
gateRef.current?.arm();
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
const handleSynced = (isSynced) => {
|
|
231
|
-
if (isSynced) {
|
|
232
|
-
gateRef.current?.open();
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
provider.on("status", handleStatus);
|
|
236
|
-
provider.on("sync", handleSynced);
|
|
237
|
-
if (provider.wsconnected) {
|
|
238
|
-
connected = true;
|
|
239
|
-
setStatus("connected");
|
|
240
|
-
gateRef.current?.arm();
|
|
241
|
-
}
|
|
242
|
-
if (provider.synced) {
|
|
243
|
-
gateRef.current?.open();
|
|
244
|
-
}
|
|
245
|
-
if (!connected) {
|
|
246
|
-
timeoutRef.current = setTimeout(() => {
|
|
247
|
-
timeoutRef.current = null;
|
|
248
|
-
if (!connected) {
|
|
249
|
-
provider.off("status", handleStatus);
|
|
250
|
-
provider.off("sync", handleSynced);
|
|
251
|
-
announceDeparture();
|
|
252
|
-
clearLocalAwareness(provider.awareness);
|
|
253
|
-
provider.destroy();
|
|
254
|
-
yDoc.destroy();
|
|
255
|
-
setDoc(null);
|
|
256
|
-
setAwareness(null);
|
|
257
|
-
setClientId(null);
|
|
258
|
-
cleanupRef.current = null;
|
|
259
|
-
setStatus("error");
|
|
260
|
-
}
|
|
261
|
-
}, CONNECTION_TIMEOUT_MS);
|
|
262
|
-
}
|
|
263
|
-
setDoc(yDoc);
|
|
264
|
-
setAwareness(provider.awareness);
|
|
265
|
-
setClientId(provider.awareness.clientID);
|
|
266
|
-
cleanupRef.current = () => {
|
|
267
|
-
provider.off("status", handleStatus);
|
|
268
|
-
provider.off("sync", handleSynced);
|
|
269
|
-
announceDeparture();
|
|
270
|
-
clearLocalAwareness(provider.awareness);
|
|
271
|
-
provider.destroy();
|
|
272
|
-
yDoc.destroy();
|
|
273
|
-
setDoc(null);
|
|
274
|
-
setAwareness(null);
|
|
275
|
-
setClientId(null);
|
|
276
|
-
setStatus("disconnected");
|
|
277
|
-
};
|
|
278
|
-
} catch (err) {
|
|
279
|
-
if (generation !== generationRef.current) {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
console.warn(
|
|
283
|
-
"[pptx-viewer] Collaboration packages not available:",
|
|
284
|
-
err instanceof Error ? err.message : err
|
|
285
|
-
);
|
|
286
|
-
setStatus("error");
|
|
287
|
-
}
|
|
102
|
+
void controller.start(config);
|
|
103
|
+
const disposeTeardown = registerCollaborationTeardown({
|
|
104
|
+
leave: () => controller.stop(),
|
|
105
|
+
rejoin: () => void controller.retry()
|
|
106
|
+
});
|
|
107
|
+
return () => {
|
|
108
|
+
disposeTeardown();
|
|
109
|
+
controller.stop();
|
|
110
|
+
};
|
|
288
111
|
}, [
|
|
112
|
+
controller,
|
|
289
113
|
config?.roomId,
|
|
290
114
|
config?.serverUrl,
|
|
291
115
|
config?.authToken,
|
|
292
116
|
config?.transport,
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
teardown
|
|
117
|
+
signalingKey,
|
|
118
|
+
Boolean(config)
|
|
296
119
|
]);
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
const retry = useCallback(() => {
|
|
309
|
-
init();
|
|
310
|
-
}, [init]);
|
|
311
|
-
return { status, awareness, doc, clientId, synced, retry };
|
|
120
|
+
const session = state.active ? controller.getSession() : null;
|
|
121
|
+
return {
|
|
122
|
+
status: state.status,
|
|
123
|
+
awareness: session?.awareness ?? null,
|
|
124
|
+
doc: session?.doc ?? null,
|
|
125
|
+
clientId: state.clientId,
|
|
126
|
+
synced: state.synced,
|
|
127
|
+
retry: () => {
|
|
128
|
+
void controller.retry();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
312
131
|
}
|
|
313
132
|
function usePresenceTracking({
|
|
314
133
|
awareness,
|
|
@@ -757,15 +576,11 @@ function serializeHistoryDocument(snapshot) {
|
|
|
757
576
|
)
|
|
758
577
|
});
|
|
759
578
|
}
|
|
760
|
-
function recordExplicitSlideUpdate(
|
|
579
|
+
function recordExplicitSlideUpdate(history, previous, before, label) {
|
|
761
580
|
if (previous && serializeHistoryDocument(previous) !== serializeHistoryDocument(before)) {
|
|
762
|
-
|
|
763
|
-
}
|
|
764
|
-
past.push({ ...cloneHistorySnapshot(before), actionLabel: label });
|
|
765
|
-
while (past.length > Math.max(1, maxDepth)) {
|
|
766
|
-
past.shift();
|
|
581
|
+
history.record(cloneHistorySnapshot(previous), previous.actionLabel);
|
|
767
582
|
}
|
|
768
|
-
|
|
583
|
+
history.record({ ...cloneHistorySnapshot(before), actionLabel: label }, label);
|
|
769
584
|
}
|
|
770
585
|
var POLL_INTERVAL_MS = 16;
|
|
771
586
|
function usePointerReleaseWakeup(hasActivePointerInteraction) {
|
|
@@ -801,7 +616,6 @@ function usePointerReleaseWakeup(hasActivePointerInteraction) {
|
|
|
801
616
|
}
|
|
802
617
|
|
|
803
618
|
// src/viewer/hooks/useEditorHistory.ts
|
|
804
|
-
var DEFAULT_MAX_HISTORY_ENTRIES = 120;
|
|
805
619
|
function useEditorHistory(input) {
|
|
806
620
|
const {
|
|
807
621
|
slides,
|
|
@@ -810,7 +624,7 @@ function useEditorHistory(input) {
|
|
|
810
624
|
templateElementsBySlideId,
|
|
811
625
|
loading,
|
|
812
626
|
error,
|
|
813
|
-
maxHistoryEntries
|
|
627
|
+
maxHistoryEntries,
|
|
814
628
|
hasActivePointerInteraction,
|
|
815
629
|
pointerCommitNonce,
|
|
816
630
|
onDirty,
|
|
@@ -821,30 +635,23 @@ function useEditorHistory(input) {
|
|
|
821
635
|
setSelectedElementId,
|
|
822
636
|
setSelectedElementIds
|
|
823
637
|
} = input;
|
|
824
|
-
const
|
|
825
|
-
const
|
|
638
|
+
const [history] = useState(() => createEditorHistoryController());
|
|
639
|
+
const historyState = useController(history);
|
|
826
640
|
const lastHistorySnapshotRef = useRef(null);
|
|
827
641
|
const lastHistorySerializedRef = useRef("");
|
|
828
642
|
const lastCheapHashRef = useRef("");
|
|
829
643
|
const isApplyingHistoryRef = useRef(false);
|
|
830
644
|
const trackingHeldRef = useRef(false);
|
|
831
645
|
const unlockHistoryTimerRef = useRef(null);
|
|
832
|
-
const [canUndo, setCanUndo] = useState(false);
|
|
833
|
-
const [canRedo, setCanRedo] = useState(false);
|
|
834
|
-
const [undoLabel, setUndoLabel] = useState(void 0);
|
|
835
|
-
const [redoLabel, setRedoLabel] = useState(void 0);
|
|
836
646
|
const [editCommitNonce, setEditCommitNonce] = useState(0);
|
|
837
647
|
const { pointerReleaseNonce, deferUntilPointerReleased } = usePointerReleaseWakeup(
|
|
838
648
|
hasActivePointerInteraction
|
|
839
649
|
);
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
const futureTop = historyFutureRef.current[historyFutureRef.current.length - 1];
|
|
846
|
-
setRedoLabel(futureTop?.actionLabel);
|
|
847
|
-
}, []);
|
|
650
|
+
useEffect(() => {
|
|
651
|
+
if (maxHistoryEntries !== void 0) {
|
|
652
|
+
history.setMaxDepth(maxHistoryEntries);
|
|
653
|
+
}
|
|
654
|
+
}, [history, maxHistoryEntries]);
|
|
848
655
|
const buildHistorySnapshot = useCallback(
|
|
849
656
|
(actionLabel) => {
|
|
850
657
|
return {
|
|
@@ -899,53 +706,40 @@ function useEditorHistory(input) {
|
|
|
899
706
|
onDirtyRef.current?.();
|
|
900
707
|
}, []);
|
|
901
708
|
const handleUndo = useCallback(() => {
|
|
902
|
-
|
|
903
|
-
|
|
709
|
+
if (!history.getSnapshot().canUndo) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const result = history.undo(buildHistorySnapshot());
|
|
713
|
+
if (!result) {
|
|
904
714
|
return;
|
|
905
715
|
}
|
|
906
|
-
const currentSnapshot = buildHistorySnapshot(previousSnapshot.actionLabel);
|
|
907
|
-
historyFutureRef.current.push(currentSnapshot);
|
|
908
716
|
isApplyingHistoryRef.current = true;
|
|
909
|
-
const nextSnapshot = cloneHistorySnapshot(
|
|
717
|
+
const nextSnapshot = cloneHistorySnapshot(result.snapshot);
|
|
910
718
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(nextSnapshot);
|
|
911
719
|
lastHistorySerializedRef.current = serializeHistoryDocument(nextSnapshot);
|
|
912
720
|
applyHistorySnapshot(nextSnapshot);
|
|
913
|
-
updateHistoryAvailability();
|
|
914
721
|
unlockHistoryTracking();
|
|
915
722
|
markDirty();
|
|
916
|
-
}, [
|
|
917
|
-
applyHistorySnapshot,
|
|
918
|
-
buildHistorySnapshot,
|
|
919
|
-
markDirty,
|
|
920
|
-
unlockHistoryTracking,
|
|
921
|
-
updateHistoryAvailability
|
|
922
|
-
]);
|
|
723
|
+
}, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
|
|
923
724
|
const handleRedo = useCallback(() => {
|
|
924
|
-
|
|
925
|
-
|
|
725
|
+
if (!history.getSnapshot().canRedo) {
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
const result = history.redo(buildHistorySnapshot());
|
|
729
|
+
if (!result) {
|
|
926
730
|
return;
|
|
927
731
|
}
|
|
928
|
-
const currentSnapshot = buildHistorySnapshot(nextSnapshot.actionLabel);
|
|
929
|
-
historyPastRef.current.push(currentSnapshot);
|
|
930
732
|
isApplyingHistoryRef.current = true;
|
|
931
|
-
const targetSnapshot = cloneHistorySnapshot(
|
|
733
|
+
const targetSnapshot = cloneHistorySnapshot(result.snapshot);
|
|
932
734
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(targetSnapshot);
|
|
933
735
|
lastHistorySerializedRef.current = serializeHistoryDocument(targetSnapshot);
|
|
934
736
|
applyHistorySnapshot(targetSnapshot);
|
|
935
|
-
updateHistoryAvailability();
|
|
936
737
|
unlockHistoryTracking();
|
|
937
738
|
markDirty();
|
|
938
|
-
}, [
|
|
939
|
-
applyHistorySnapshot,
|
|
940
|
-
buildHistorySnapshot,
|
|
941
|
-
markDirty,
|
|
942
|
-
unlockHistoryTracking,
|
|
943
|
-
updateHistoryAvailability
|
|
944
|
-
]);
|
|
739
|
+
}, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
|
|
945
740
|
const resetHistory = useCallback(
|
|
946
741
|
(initialSnapshot) => {
|
|
947
|
-
|
|
948
|
-
historyFutureRef.current = [];
|
|
742
|
+
history.clear();
|
|
949
743
|
if (initialSnapshot) {
|
|
950
744
|
const clonedInitial = cloneHistorySnapshot(initialSnapshot);
|
|
951
745
|
lastHistorySnapshotRef.current = clonedInitial;
|
|
@@ -954,9 +748,8 @@ function useEditorHistory(input) {
|
|
|
954
748
|
lastHistorySnapshotRef.current = null;
|
|
955
749
|
lastHistorySerializedRef.current = "";
|
|
956
750
|
}
|
|
957
|
-
updateHistoryAvailability();
|
|
958
751
|
},
|
|
959
|
-
[
|
|
752
|
+
[history]
|
|
960
753
|
);
|
|
961
754
|
useEffect(() => {
|
|
962
755
|
return () => {
|
|
@@ -999,19 +792,13 @@ function useEditorHistory(input) {
|
|
|
999
792
|
lastHistorySnapshotRef.current = snapshot;
|
|
1000
793
|
lastHistorySerializedRef.current = serialized;
|
|
1001
794
|
lastCheapHashRef.current = cheapHash;
|
|
1002
|
-
updateHistoryAvailability();
|
|
1003
795
|
return;
|
|
1004
796
|
}
|
|
1005
797
|
onDirtyRef.current?.();
|
|
1006
|
-
|
|
1007
|
-
while (historyPastRef.current.length > Math.max(1, maxHistoryEntries)) {
|
|
1008
|
-
historyPastRef.current.shift();
|
|
1009
|
-
}
|
|
1010
|
-
historyFutureRef.current = [];
|
|
798
|
+
history.record(previousSnapshot, previousSnapshot.actionLabel);
|
|
1011
799
|
lastHistorySnapshotRef.current = snapshot;
|
|
1012
800
|
lastHistorySerializedRef.current = serialized;
|
|
1013
801
|
lastCheapHashRef.current = cheapHash;
|
|
1014
|
-
updateHistoryAvailability();
|
|
1015
802
|
}, [
|
|
1016
803
|
activeSlideIndex,
|
|
1017
804
|
buildHistorySnapshot,
|
|
@@ -1021,30 +808,21 @@ function useEditorHistory(input) {
|
|
|
1021
808
|
editCommitNonce,
|
|
1022
809
|
error,
|
|
1023
810
|
hasActivePointerInteraction,
|
|
811
|
+
history,
|
|
1024
812
|
loading,
|
|
1025
|
-
maxHistoryEntries,
|
|
1026
813
|
pointerCommitNonce,
|
|
1027
814
|
pointerReleaseNonce,
|
|
1028
|
-
slides
|
|
1029
|
-
updateHistoryAvailability
|
|
815
|
+
slides
|
|
1030
816
|
]);
|
|
1031
817
|
const commitSlides = (nextSlides, label, beforeSlides = slides) => {
|
|
1032
818
|
const before = { ...buildHistorySnapshot(), slides: beforeSlides.map(cloneSlide) };
|
|
1033
819
|
const after = { ...before, slides: nextSlides.map(cloneSlide) };
|
|
1034
|
-
recordExplicitSlideUpdate(
|
|
1035
|
-
historyPastRef.current,
|
|
1036
|
-
historyFutureRef.current,
|
|
1037
|
-
lastHistorySnapshotRef.current,
|
|
1038
|
-
before,
|
|
1039
|
-
label,
|
|
1040
|
-
maxHistoryEntries
|
|
1041
|
-
);
|
|
820
|
+
recordExplicitSlideUpdate(history, lastHistorySnapshotRef.current, before, label);
|
|
1042
821
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(after);
|
|
1043
822
|
lastHistorySerializedRef.current = serializeHistoryDocument(after);
|
|
1044
823
|
isApplyingHistoryRef.current = false;
|
|
1045
824
|
setSlides(nextSlides);
|
|
1046
825
|
onDirtyRef.current?.();
|
|
1047
|
-
updateHistoryAvailability();
|
|
1048
826
|
};
|
|
1049
827
|
const holdTracking = useCallback((held) => {
|
|
1050
828
|
trackingHeldRef.current = held;
|
|
@@ -1052,10 +830,10 @@ function useEditorHistory(input) {
|
|
|
1052
830
|
return {
|
|
1053
831
|
commitSlides,
|
|
1054
832
|
holdTracking,
|
|
1055
|
-
canUndo,
|
|
1056
|
-
canRedo,
|
|
1057
|
-
undoLabel,
|
|
1058
|
-
redoLabel,
|
|
833
|
+
canUndo: historyState.canUndo,
|
|
834
|
+
canRedo: historyState.canRedo,
|
|
835
|
+
undoLabel: historyState.undoLabel,
|
|
836
|
+
redoLabel: historyState.redoLabel,
|
|
1059
837
|
handleUndo,
|
|
1060
838
|
handleRedo,
|
|
1061
839
|
resetHistory,
|
|
@@ -2198,9 +1976,6 @@ function executeSlideTransition(nextSlideIndex, deps) {
|
|
|
2198
1976
|
}
|
|
2199
1977
|
|
|
2200
1978
|
// src/viewer/hooks/presentation-mode/useSlideNavigation.ts
|
|
2201
|
-
function isClickAdvanceBlocked(slide, direction, trigger) {
|
|
2202
|
-
return trigger === "click" && direction === 1 && slide?.transition?.advanceOnClick === false;
|
|
2203
|
-
}
|
|
2204
1979
|
function useSlideNavigation(input) {
|
|
2205
1980
|
const {
|
|
2206
1981
|
slides,
|
|
@@ -2250,50 +2025,71 @@ function useSlideNavigation(input) {
|
|
|
2250
2025
|
);
|
|
2251
2026
|
const movePresentationSlide = useCallback(
|
|
2252
2027
|
(direction, trigger = "explicit") => {
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
}
|
|
2256
|
-
|
|
2028
|
+
const showOrder = visibleSlideIndexes.length > 0 ? visibleSlideIndexes : slides.map((_slide, slideIndex) => slideIndex);
|
|
2029
|
+
const current = presentationSlideIndex;
|
|
2030
|
+
const transitionTo = (index, options = {}) => executeSlideTransition(index, {
|
|
2031
|
+
slides,
|
|
2032
|
+
currentSlideIndex: current,
|
|
2033
|
+
onPlayActionSound,
|
|
2034
|
+
onStopActionSound,
|
|
2035
|
+
setPresentationSlideVisible,
|
|
2036
|
+
clearPresentationTimers,
|
|
2037
|
+
setPresentationSlideIndex,
|
|
2038
|
+
onSetActiveSlideIndex,
|
|
2039
|
+
seedSlideAnimations,
|
|
2040
|
+
startSlideAnimations,
|
|
2041
|
+
scheduleAutoAdvanceForSlide: rehearsing ? void 0 : scheduleAutoAdvanceForSlide,
|
|
2042
|
+
presentationTimersRef,
|
|
2043
|
+
setTransitionOverlay,
|
|
2044
|
+
// PowerPoint plays a slide's transition only when advancing into it,
|
|
2045
|
+
// and replays the LEAVING slide's transition in reverse when stepping
|
|
2046
|
+
// back (a morph glides its shapes back to where they came from).
|
|
2047
|
+
playTransition: true,
|
|
2048
|
+
...options
|
|
2049
|
+
});
|
|
2050
|
+
if (direction === -1) {
|
|
2051
|
+
const step2 = resolveShowBackward({
|
|
2052
|
+
currentIndex: current,
|
|
2053
|
+
showOrder,
|
|
2054
|
+
endOfShow: false,
|
|
2055
|
+
seededCompleted: false
|
|
2056
|
+
});
|
|
2057
|
+
if (step2.kind === "go") {
|
|
2058
|
+
transitionTo(step2.index, { reverse: true, seedCompleted: true });
|
|
2059
|
+
}
|
|
2257
2060
|
return;
|
|
2258
2061
|
}
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
)
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
clearPresentationTimers,
|
|
2275
|
-
setPresentationSlideIndex,
|
|
2276
|
-
onSetActiveSlideIndex,
|
|
2277
|
-
seedSlideAnimations,
|
|
2278
|
-
startSlideAnimations,
|
|
2062
|
+
const step = resolveShowForward({
|
|
2063
|
+
currentIndex: current,
|
|
2064
|
+
currentSlide: slides[current],
|
|
2065
|
+
showOrder,
|
|
2066
|
+
endOfShow: false,
|
|
2067
|
+
fromClick: trigger === "click",
|
|
2068
|
+
loop: Boolean(loopContinuously) && !rehearsing,
|
|
2069
|
+
endWithBlackSlide: true,
|
|
2070
|
+
zoomExcursion: zoomExcursionRef.current,
|
|
2071
|
+
advanceBuild: playNextAnimationGroup
|
|
2072
|
+
});
|
|
2073
|
+
if (step.kind === "go") {
|
|
2074
|
+
if (step.zoomReturn) {
|
|
2075
|
+
zoomExcursionRef.current = step.zoomReturn.excursion;
|
|
2076
|
+
transitionTo(step.index, {
|
|
2279
2077
|
scheduleAutoAdvanceForSlide,
|
|
2280
|
-
|
|
2281
|
-
setTransitionOverlay,
|
|
2282
|
-
playTransition: true,
|
|
2283
|
-
transitionOverride: buildZoomTransitionOverride(
|
|
2284
|
-
consumedExcursion?.transitionDurationMs
|
|
2285
|
-
)
|
|
2078
|
+
transitionOverride: step.zoomReturn.transitionOverride
|
|
2286
2079
|
});
|
|
2287
2080
|
return;
|
|
2288
2081
|
}
|
|
2082
|
+
if (rehearsing) {
|
|
2083
|
+
recordCurrentSlideTime(current);
|
|
2084
|
+
}
|
|
2085
|
+
transitionTo(step.index);
|
|
2086
|
+
return;
|
|
2289
2087
|
}
|
|
2290
|
-
|
|
2291
|
-
if (availableSlideIndexes.length === 0) {
|
|
2088
|
+
if (step.kind !== "end-screen" && step.kind !== "exit") {
|
|
2292
2089
|
return;
|
|
2293
2090
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
recordCurrentSlideTime(presentationSlideIndex);
|
|
2091
|
+
if (rehearsing) {
|
|
2092
|
+
recordCurrentSlideTime(current);
|
|
2297
2093
|
try {
|
|
2298
2094
|
if (document.fullscreenElement) {
|
|
2299
2095
|
void document.exitFullscreen().catch(() => {
|
|
@@ -2305,41 +2101,7 @@ function useSlideNavigation(input) {
|
|
|
2305
2101
|
setShowRehearsalSummary(true);
|
|
2306
2102
|
return;
|
|
2307
2103
|
}
|
|
2308
|
-
|
|
2309
|
-
onAdvancePastLastSlide();
|
|
2310
|
-
return;
|
|
2311
|
-
}
|
|
2312
|
-
const nextSlideIndex = direction === 1 ? nextShowSlideIndex(presentationSlideIndex, availableSlideIndexes, {
|
|
2313
|
-
loop: Boolean(loopContinuously) && !rehearsing
|
|
2314
|
-
}) : previousShowSlideIndex(presentationSlideIndex, availableSlideIndexes);
|
|
2315
|
-
if (nextSlideIndex === void 0 || nextSlideIndex === presentationSlideIndex) {
|
|
2316
|
-
return;
|
|
2317
|
-
}
|
|
2318
|
-
if (rehearsing && direction === 1) {
|
|
2319
|
-
recordCurrentSlideTime(presentationSlideIndex);
|
|
2320
|
-
}
|
|
2321
|
-
executeSlideTransition(nextSlideIndex, {
|
|
2322
|
-
slides,
|
|
2323
|
-
currentSlideIndex: presentationSlideIndex,
|
|
2324
|
-
onPlayActionSound,
|
|
2325
|
-
onStopActionSound,
|
|
2326
|
-
setPresentationSlideVisible,
|
|
2327
|
-
clearPresentationTimers,
|
|
2328
|
-
setPresentationSlideIndex,
|
|
2329
|
-
onSetActiveSlideIndex,
|
|
2330
|
-
seedSlideAnimations,
|
|
2331
|
-
startSlideAnimations,
|
|
2332
|
-
scheduleAutoAdvanceForSlide: rehearsing ? void 0 : scheduleAutoAdvanceForSlide,
|
|
2333
|
-
presentationTimersRef,
|
|
2334
|
-
setTransitionOverlay,
|
|
2335
|
-
// PowerPoint plays a slide's transition only when advancing into it,
|
|
2336
|
-
// and replays the LEAVING slide's transition in reverse when stepping
|
|
2337
|
-
// back (a morph glides its shapes back to where they came from).
|
|
2338
|
-
playTransition: true,
|
|
2339
|
-
reverse: direction === -1,
|
|
2340
|
-
// Stepping back onto a slide shows it with its builds already played.
|
|
2341
|
-
seedCompleted: direction === -1
|
|
2342
|
-
});
|
|
2104
|
+
onAdvancePastLastSlide?.();
|
|
2343
2105
|
},
|
|
2344
2106
|
[
|
|
2345
2107
|
clearPresentationTimers,
|
|
@@ -4199,6 +3961,7 @@ function useViewerCoreState(_input) {
|
|
|
4199
3961
|
const marqueeStateRef = useRef(null);
|
|
4200
3962
|
const isDrawingRef = useRef(false);
|
|
4201
3963
|
const justInteractedRef = useRef(false);
|
|
3964
|
+
const gestureControllerRef = useRef(null);
|
|
4202
3965
|
const livePatcher = useMemo(() => createCollaborationLivePatcher(), []);
|
|
4203
3966
|
useEffect(() => () => livePatcher.dispose(), [livePatcher]);
|
|
4204
3967
|
const [mode, setMode] = useState("edit");
|
|
@@ -4215,10 +3978,11 @@ function useViewerCoreState(_input) {
|
|
|
4215
3978
|
const [selectedElementId, setSelectedElementId] = useState(null);
|
|
4216
3979
|
const [selectedElementIds, setSelectedElementIds] = useState([]);
|
|
4217
3980
|
const [isDirty, setIsDirty] = useState(false);
|
|
3981
|
+
const autosaveDraftSinkRef = useRef(null);
|
|
4218
3982
|
const publishInlineText = useCallback(
|
|
4219
3983
|
(elementId, text) => {
|
|
4220
|
-
|
|
4221
|
-
livePatcher,
|
|
3984
|
+
reportInlineTextDraft(
|
|
3985
|
+
{ livePatcher, autosave: autosaveDraftSinkRef.current },
|
|
4222
3986
|
slidesRef.current[activeSlideIndexRef.current],
|
|
4223
3987
|
elementId,
|
|
4224
3988
|
text
|
|
@@ -4284,6 +4048,7 @@ function useViewerCoreState(_input) {
|
|
|
4284
4048
|
imageInputRef,
|
|
4285
4049
|
mediaInputRef,
|
|
4286
4050
|
activeSlideIndexRef,
|
|
4051
|
+
autosaveDraftSinkRef,
|
|
4287
4052
|
...inlineEditing,
|
|
4288
4053
|
...editPointsMode,
|
|
4289
4054
|
dragStateRef,
|
|
@@ -4292,6 +4057,7 @@ function useViewerCoreState(_input) {
|
|
|
4292
4057
|
marqueeStateRef,
|
|
4293
4058
|
isDrawingRef,
|
|
4294
4059
|
justInteractedRef,
|
|
4060
|
+
gestureControllerRef,
|
|
4295
4061
|
livePatcher,
|
|
4296
4062
|
mode,
|
|
4297
4063
|
setMode,
|
|
@@ -4778,96 +4544,43 @@ function useLoadContent({
|
|
|
4778
4544
|
return { handlerRef };
|
|
4779
4545
|
}
|
|
4780
4546
|
function useAutosave(input) {
|
|
4781
|
-
const { isDirty, filePath,
|
|
4547
|
+
const { isDirty, filePath, enabled = true } = input;
|
|
4782
4548
|
const intervalMs = resolveAutosaveIntervalMs({
|
|
4783
4549
|
hostIntervalMs: input.intervalMs,
|
|
4784
4550
|
optionsIntervalSeconds: input.intervalSeconds
|
|
4785
4551
|
});
|
|
4786
|
-
const
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
}
|
|
4807
|
-
|
|
4808
|
-
serializeRef.current = serializeSlides;
|
|
4809
|
-
}, [serializeSlides]);
|
|
4552
|
+
const live = useRef(input);
|
|
4553
|
+
live.current = input;
|
|
4554
|
+
const [controller] = useState(
|
|
4555
|
+
() => createAutosaveController({
|
|
4556
|
+
getActivation: () => ({ active: live.current.enabled ?? true }),
|
|
4557
|
+
getFilePath: () => live.current.filePath,
|
|
4558
|
+
getIntervalMs: () => resolveAutosaveIntervalMs({
|
|
4559
|
+
hostIntervalMs: live.current.intervalMs,
|
|
4560
|
+
optionsIntervalSeconds: live.current.intervalSeconds
|
|
4561
|
+
}),
|
|
4562
|
+
serialize: () => live.current.serializeSlides(),
|
|
4563
|
+
getStorage: () => live.current.storage,
|
|
4564
|
+
onSaved: (data) => live.current.onSaved?.(data),
|
|
4565
|
+
writeSnapshot: saveAutosaveSnapshot,
|
|
4566
|
+
// serializeSlides already overlays the live inline draft from its refs.
|
|
4567
|
+
getInlineEditingId: () => live.current.getInlineEditingId?.()
|
|
4568
|
+
})
|
|
4569
|
+
);
|
|
4570
|
+
if (input.inlineDraftSinkRef) {
|
|
4571
|
+
input.inlineDraftSinkRef.current = controller;
|
|
4572
|
+
}
|
|
4573
|
+
const { status } = useController(controller);
|
|
4810
4574
|
useEffect(() => {
|
|
4811
|
-
|
|
4812
|
-
}, [
|
|
4813
|
-
const doAutosave = useCallback(async (options) => {
|
|
4814
|
-
const path = filePathRef.current;
|
|
4815
|
-
if (!path) {
|
|
4816
|
-
return;
|
|
4817
|
-
}
|
|
4818
|
-
const sources = changeSourcesRef.current?.() ?? [];
|
|
4819
|
-
if (!shouldWriteAutosaveSnapshot({
|
|
4820
|
-
filePath: path,
|
|
4821
|
-
isDirty: isDirtyRef.current,
|
|
4822
|
-
saving: isSavingRef.current,
|
|
4823
|
-
sources: options?.polled === true ? sources : [],
|
|
4824
|
-
lastSnapshot: lastSnapshotRef.current
|
|
4825
|
-
})) {
|
|
4826
|
-
return;
|
|
4827
|
-
}
|
|
4828
|
-
isSavingRef.current = true;
|
|
4829
|
-
setAutosaveStatus({ state: "saving" });
|
|
4830
|
-
try {
|
|
4831
|
-
const data = await serializeRef.current();
|
|
4832
|
-
if (!data) {
|
|
4833
|
-
setAutosaveStatus({ state: "idle" });
|
|
4834
|
-
isSavingRef.current = false;
|
|
4835
|
-
return;
|
|
4836
|
-
}
|
|
4837
|
-
await saveAutosaveSnapshot(path, data, storageRef.current);
|
|
4838
|
-
lastSnapshotRef.current = autosaveSnapshotMark(path, sources);
|
|
4839
|
-
setAutosaveStatus({ state: "saved", timestamp: Date.now() });
|
|
4840
|
-
onSavedRef.current?.(data);
|
|
4841
|
-
} catch (err) {
|
|
4842
|
-
setAutosaveStatus({
|
|
4843
|
-
state: "error",
|
|
4844
|
-
message: err instanceof Error ? err.message : "Autosave failed"
|
|
4845
|
-
});
|
|
4846
|
-
} finally {
|
|
4847
|
-
isSavingRef.current = false;
|
|
4848
|
-
}
|
|
4849
|
-
}, []);
|
|
4575
|
+
controller.refresh();
|
|
4576
|
+
}, [controller, enabled, filePath, intervalMs]);
|
|
4850
4577
|
useEffect(() => {
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
}
|
|
4855
|
-
if (!filePath) {
|
|
4856
|
-
setAutosaveStatus({
|
|
4857
|
-
state: "disabled",
|
|
4858
|
-
reason: "no_file_path"
|
|
4859
|
-
});
|
|
4860
|
-
return;
|
|
4861
|
-
}
|
|
4862
|
-
setAutosaveStatus((prev) => prev.state === "disabled" ? { state: "idle" } : prev);
|
|
4863
|
-
const id = setInterval(() => {
|
|
4864
|
-
void doAutosave({ polled: true });
|
|
4865
|
-
}, intervalMs);
|
|
4866
|
-
return () => clearInterval(id);
|
|
4867
|
-
}, [enabled, filePath, intervalMs, doAutosave]);
|
|
4578
|
+
controller.observe(isDirty, live.current.getChangeSources?.() ?? []);
|
|
4579
|
+
});
|
|
4580
|
+
useEffect(() => () => controller.markClean(), [controller]);
|
|
4868
4581
|
return {
|
|
4869
|
-
autosaveStatus,
|
|
4870
|
-
triggerAutosave: () =>
|
|
4582
|
+
autosaveStatus: status,
|
|
4583
|
+
triggerAutosave: () => controller.saveNow()
|
|
4871
4584
|
};
|
|
4872
4585
|
}
|
|
4873
4586
|
|
|
@@ -5382,45 +5095,238 @@ function syncSelectionHandleOverlay(elementNode, elementId, geometry) {
|
|
|
5382
5095
|
}
|
|
5383
5096
|
}
|
|
5384
5097
|
|
|
5385
|
-
// src/viewer/hooks/
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5098
|
+
// src/viewer/hooks/canvas-gestures.ts
|
|
5099
|
+
var animationFrames = {
|
|
5100
|
+
request: (callback) => requestAnimationFrame(callback),
|
|
5101
|
+
cancel: (handle) => cancelAnimationFrame(handle)
|
|
5102
|
+
};
|
|
5103
|
+
function createCanvasGestures(getInput, frames = animationFrames) {
|
|
5104
|
+
let armed = null;
|
|
5105
|
+
let pending = null;
|
|
5106
|
+
let frameHandle = 0;
|
|
5107
|
+
let lastSnapLinesKey = "";
|
|
5108
|
+
const liveTarget = () => {
|
|
5109
|
+
const { livePatcher, editTemplateMode, activeSlide } = getInput();
|
|
5110
|
+
return livePatcher && !editTemplateMode && livePatcher.isActive() ? { patcher: livePatcher, slideId: activeSlide?.id } : void 0;
|
|
5111
|
+
};
|
|
5112
|
+
function showSnapLines(lines) {
|
|
5113
|
+
const next = lines.map((line) => ({
|
|
5114
|
+
axis: line.axis === "v" ? "x" : "y",
|
|
5115
|
+
position: line.position
|
|
5116
|
+
}));
|
|
5117
|
+
const key = JSON.stringify(next);
|
|
5118
|
+
if (key !== lastSnapLinesKey) {
|
|
5119
|
+
lastSnapLinesKey = key;
|
|
5120
|
+
getInput().setSnapLines(next);
|
|
5121
|
+
}
|
|
5391
5122
|
}
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5123
|
+
function paintMove(drag, transform) {
|
|
5124
|
+
const start = drag.startPositionsById[transform.id];
|
|
5125
|
+
if (!start) {
|
|
5126
|
+
return;
|
|
5127
|
+
}
|
|
5128
|
+
drag.lastDx = transform.x - start.x;
|
|
5129
|
+
drag.lastDy = transform.y - start.y;
|
|
5130
|
+
const live = liveTarget();
|
|
5131
|
+
for (const [id, from] of Object.entries(drag.startPositionsById)) {
|
|
5132
|
+
const x = from.x + drag.lastDx;
|
|
5133
|
+
const y = from.y + drag.lastDy;
|
|
5134
|
+
const domEl = drag.domEls.get(id);
|
|
5135
|
+
if (domEl) {
|
|
5136
|
+
domEl.style.left = `${x}px`;
|
|
5137
|
+
domEl.style.top = `${y}px`;
|
|
5138
|
+
syncSelectionHandleOverlay(domEl, id, { x, y });
|
|
5139
|
+
}
|
|
5140
|
+
if (live) {
|
|
5141
|
+
publishLiveGeometry(live.patcher, live.slideId, id, { x, y });
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
5145
|
+
function paintResize(resize, transform) {
|
|
5146
|
+
const { x, y } = transform;
|
|
5147
|
+
const width = Math.max(transform.width, MIN_ELEMENT_SIZE);
|
|
5148
|
+
const height = Math.max(transform.height, MIN_ELEMENT_SIZE);
|
|
5149
|
+
resize.lastX = x;
|
|
5150
|
+
resize.lastY = y;
|
|
5151
|
+
resize.lastWidth = transform.width;
|
|
5152
|
+
resize.lastHeight = transform.height;
|
|
5153
|
+
if (resize.domEl) {
|
|
5154
|
+
Object.assign(resize.domEl.style, {
|
|
5155
|
+
left: `${x}px`,
|
|
5156
|
+
top: `${y}px`,
|
|
5157
|
+
width: `${width}px`,
|
|
5158
|
+
height: `${height}px`
|
|
5159
|
+
});
|
|
5160
|
+
syncSelectionHandleOverlay(resize.domEl, resize.elementId, { x, y, width, height });
|
|
5161
|
+
}
|
|
5162
|
+
const live = liveTarget();
|
|
5163
|
+
if (live) {
|
|
5164
|
+
publishLiveGeometry(live.patcher, live.slideId, resize.elementId, { x, y, width, height });
|
|
5165
|
+
}
|
|
5166
|
+
}
|
|
5167
|
+
function paintPending() {
|
|
5168
|
+
const frame = pending;
|
|
5169
|
+
pending = null;
|
|
5170
|
+
frameHandle = 0;
|
|
5171
|
+
if (!frame || !armed) {
|
|
5172
|
+
return;
|
|
5173
|
+
}
|
|
5174
|
+
if (armed.kind === "move") {
|
|
5175
|
+
armed.drag.moved = true;
|
|
5176
|
+
showSnapLines(frame.lines);
|
|
5177
|
+
paintMove(armed.drag, frame.transform);
|
|
5178
|
+
} else {
|
|
5179
|
+
armed.resize.moved = true;
|
|
5180
|
+
paintResize(armed.resize, frame.transform);
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
function flushFrame() {
|
|
5184
|
+
if (frameHandle !== 0) {
|
|
5185
|
+
frames.cancel(frameHandle);
|
|
5186
|
+
}
|
|
5187
|
+
paintPending();
|
|
5395
5188
|
}
|
|
5396
|
-
|
|
5189
|
+
const controller = createGestureController({
|
|
5190
|
+
getScale: () => getInput().editorScale,
|
|
5191
|
+
// Axis-aligned, as the canvas has always moved and resized (no rotation).
|
|
5192
|
+
getElementBox: (id) => {
|
|
5193
|
+
const el = getInput().elementLookup.get(id);
|
|
5194
|
+
return el ? { x: el.x, y: el.y, width: el.width, height: el.height } : void 0;
|
|
5195
|
+
},
|
|
5196
|
+
getSiblings: () => {
|
|
5197
|
+
const { editTemplateMode, templateElements, activeSlide } = getInput();
|
|
5198
|
+
const source = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
|
|
5199
|
+
return source.map(({ id, x, y, width, height }) => ({ id, x, y, width, height }));
|
|
5200
|
+
},
|
|
5201
|
+
getSnapToGrid: () => getInput().snapToGrid,
|
|
5202
|
+
getGridSize: () => getInput().gridSpacingPx,
|
|
5203
|
+
getSnapToShape: () => getInput().snapToShape,
|
|
5204
|
+
getGuides: () => getInput().guides.map(({ axis, position }) => ({ axis, position })),
|
|
5205
|
+
getMinSize: () => MIN_ELEMENT_SIZE,
|
|
5206
|
+
getSnapExcludeIds: () => armed?.kind === "move" ? Object.keys(armed.drag.startPositionsById) : [],
|
|
5207
|
+
getStageOrigin: () => {
|
|
5208
|
+
const rect = getInput().canvasStageRef.current?.getBoundingClientRect();
|
|
5209
|
+
return { left: rect?.left ?? 0, top: rect?.top ?? 0 };
|
|
5210
|
+
},
|
|
5211
|
+
onStart: () => void 0,
|
|
5212
|
+
onPreview: (transform, lines) => {
|
|
5213
|
+
pending = { transform, lines };
|
|
5214
|
+
if (frameHandle === 0) {
|
|
5215
|
+
frameHandle = frames.request(paintPending);
|
|
5216
|
+
}
|
|
5217
|
+
},
|
|
5218
|
+
onEnd: (transform, moved) => {
|
|
5219
|
+
flushFrame();
|
|
5220
|
+
const ended = armed;
|
|
5221
|
+
armed = null;
|
|
5222
|
+
if (ended) {
|
|
5223
|
+
finishGesture(ended, moved ? transform : null);
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
});
|
|
5227
|
+
function finishGesture(ended, transform) {
|
|
5228
|
+
const input = getInput();
|
|
5229
|
+
if (transform) {
|
|
5230
|
+
if (ended.kind === "move") {
|
|
5231
|
+
commitMove(input, ended.drag);
|
|
5232
|
+
} else {
|
|
5233
|
+
commitResize(input, ended.resize);
|
|
5234
|
+
}
|
|
5235
|
+
input.justInteractedRef.current = true;
|
|
5236
|
+
input.livePatcher?.flush();
|
|
5237
|
+
}
|
|
5238
|
+
input.dragStateRef.current = null;
|
|
5239
|
+
input.resizeStateRef.current = null;
|
|
5240
|
+
lastSnapLinesKey = "";
|
|
5241
|
+
input.setSnapLines([]);
|
|
5242
|
+
if (transform) {
|
|
5243
|
+
input.markDirty();
|
|
5244
|
+
}
|
|
5245
|
+
input.setPointerCommitNonce((n) => n + 1);
|
|
5246
|
+
}
|
|
5247
|
+
return {
|
|
5248
|
+
begin(kind, id, pointer) {
|
|
5249
|
+
if (controller.isActive()) {
|
|
5250
|
+
return;
|
|
5251
|
+
}
|
|
5252
|
+
const input = getInput();
|
|
5253
|
+
const drag = input.dragStateRef.current;
|
|
5254
|
+
const resize = input.resizeStateRef.current;
|
|
5255
|
+
armed = kind === "move" && drag ? { kind, drag } : kind === "resize" && resize ? { kind, resize } : null;
|
|
5256
|
+
if (!armed) {
|
|
5257
|
+
return;
|
|
5258
|
+
}
|
|
5259
|
+
lastSnapLinesKey = "";
|
|
5260
|
+
const handle = armed.kind === "resize" ? armed.resize.handle : void 0;
|
|
5261
|
+
controller.begin(kind, id, pointer, handle);
|
|
5262
|
+
if (!controller.isActive()) {
|
|
5263
|
+
armed = null;
|
|
5264
|
+
}
|
|
5265
|
+
},
|
|
5266
|
+
isActive: () => controller.isActive(),
|
|
5267
|
+
dispose: () => {
|
|
5268
|
+
if (frameHandle !== 0) {
|
|
5269
|
+
frames.cancel(frameHandle);
|
|
5270
|
+
frameHandle = 0;
|
|
5271
|
+
}
|
|
5272
|
+
pending = null;
|
|
5273
|
+
armed = null;
|
|
5274
|
+
controller.dispose();
|
|
5275
|
+
}
|
|
5276
|
+
};
|
|
5397
5277
|
}
|
|
5398
|
-
function
|
|
5399
|
-
const {
|
|
5400
|
-
|
|
5401
|
-
|
|
5278
|
+
function commitMove(input, drag) {
|
|
5279
|
+
const { lastDx: dx, lastDy: dy } = drag;
|
|
5280
|
+
const movedIds = new Set(Object.keys(drag.startPositionsById));
|
|
5281
|
+
const moveElements = (elements) => {
|
|
5282
|
+
const moved = elements.map((el) => {
|
|
5283
|
+
const start = drag.startPositionsById[el.id];
|
|
5284
|
+
return start ? { ...el, x: start.x + dx, y: start.y + dy } : el;
|
|
5285
|
+
});
|
|
5286
|
+
return applyReroutedConnectors(moved, rerouteConnectorsForMovedElements(moved, movedIds));
|
|
5287
|
+
};
|
|
5288
|
+
if (input.editTemplateMode) {
|
|
5289
|
+
const slideId = input.activeSlide?.id;
|
|
5290
|
+
if (slideId) {
|
|
5291
|
+
input.setTemplateElementsBySlideId((prev) => ({
|
|
5292
|
+
...prev,
|
|
5293
|
+
[slideId]: moveElements(prev[slideId] ?? [])
|
|
5294
|
+
}));
|
|
5295
|
+
}
|
|
5296
|
+
return;
|
|
5402
5297
|
}
|
|
5403
|
-
|
|
5298
|
+
input.updateSlides(
|
|
5299
|
+
(prev) => prev.map(
|
|
5300
|
+
(s, i) => i !== input.activeSlideIndex ? s : { ...s, elements: moveElements(s.elements) }
|
|
5301
|
+
)
|
|
5302
|
+
);
|
|
5303
|
+
}
|
|
5304
|
+
function commitResize(input, resize) {
|
|
5305
|
+
input.updateElementById(resize.elementId, {
|
|
5306
|
+
x: resize.lastX,
|
|
5307
|
+
y: resize.lastY,
|
|
5308
|
+
width: resize.lastWidth,
|
|
5309
|
+
height: resize.lastHeight
|
|
5310
|
+
});
|
|
5311
|
+
const movedIds = /* @__PURE__ */ new Set([resize.elementId]);
|
|
5312
|
+
input.updateSlides(
|
|
5313
|
+
(prev) => prev.map((s, i) => {
|
|
5314
|
+
if (i !== input.activeSlideIndex) {
|
|
5315
|
+
return s;
|
|
5316
|
+
}
|
|
5317
|
+
const rerouted = rerouteConnectorsForMovedElements(s.elements, movedIds);
|
|
5318
|
+
return rerouted.length === 0 ? s : { ...s, elements: applyReroutedConnectors(s.elements, rerouted) };
|
|
5319
|
+
})
|
|
5320
|
+
);
|
|
5404
5321
|
}
|
|
5405
|
-
function processPointerMove(e, input
|
|
5322
|
+
function processPointerMove(e, input) {
|
|
5406
5323
|
const {
|
|
5407
5324
|
editorScale,
|
|
5408
5325
|
canvasStageRef,
|
|
5409
5326
|
canvasSize,
|
|
5410
|
-
snapToGrid,
|
|
5411
|
-
snapToShape,
|
|
5412
|
-
gridSpacingPx,
|
|
5413
|
-
editTemplateMode,
|
|
5414
|
-
templateElements,
|
|
5415
|
-
activeSlide,
|
|
5416
|
-
guides,
|
|
5417
|
-
elementLookup,
|
|
5418
5327
|
marqueeStateRef,
|
|
5419
|
-
dragStateRef,
|
|
5420
|
-
resizeStateRef,
|
|
5421
5328
|
shapeAdjustmentDragStateRef,
|
|
5422
5329
|
setMarqueeSelectionState,
|
|
5423
|
-
setSnapLines,
|
|
5424
5330
|
updateElementById
|
|
5425
5331
|
} = input;
|
|
5426
5332
|
const marquee = marqueeStateRef.current;
|
|
@@ -5435,31 +5341,6 @@ function processPointerMove(e, input, tracker) {
|
|
|
5435
5341
|
);
|
|
5436
5342
|
return;
|
|
5437
5343
|
}
|
|
5438
|
-
const drag = dragStateRef.current;
|
|
5439
|
-
if (drag) {
|
|
5440
|
-
processDragMove(
|
|
5441
|
-
e,
|
|
5442
|
-
drag,
|
|
5443
|
-
editorScale,
|
|
5444
|
-
snapToGrid,
|
|
5445
|
-
snapToShape,
|
|
5446
|
-
gridSpacingPx,
|
|
5447
|
-
editTemplateMode,
|
|
5448
|
-
templateElements,
|
|
5449
|
-
activeSlide,
|
|
5450
|
-
guides,
|
|
5451
|
-
elementLookup,
|
|
5452
|
-
tracker,
|
|
5453
|
-
setSnapLines,
|
|
5454
|
-
resolveLiveTarget(input)
|
|
5455
|
-
);
|
|
5456
|
-
return;
|
|
5457
|
-
}
|
|
5458
|
-
const rs = resizeStateRef.current;
|
|
5459
|
-
if (rs) {
|
|
5460
|
-
processResizeMove(e, rs, editorScale, snapToGrid, gridSpacingPx, resolveLiveTarget(input));
|
|
5461
|
-
return;
|
|
5462
|
-
}
|
|
5463
5344
|
const adj = shapeAdjustmentDragStateRef.current;
|
|
5464
5345
|
if (adj) {
|
|
5465
5346
|
processAdjustmentMove(e, adj, editorScale, updateElementById);
|
|
@@ -5475,129 +5356,6 @@ function processMarqueeMove(e, marquee, canvasStageRef, canvasSize, editorScale,
|
|
|
5475
5356
|
marquee.currentY = Math.max(0, Math.min(canvasSize.height, (e.clientY - rect.top) / editorScale));
|
|
5476
5357
|
setMarqueeSelectionState({ ...marquee });
|
|
5477
5358
|
}
|
|
5478
|
-
function processDragMove(e, drag, editorScale, snapToGrid, snapToShape, gridSpacingPx, editTemplateMode, templateElements, activeSlide, guides, elementLookup, tracker, setSnapLines, live) {
|
|
5479
|
-
const dx = (e.clientX - drag.startClientX) / editorScale;
|
|
5480
|
-
const dy = (e.clientY - drag.startClientY) / editorScale;
|
|
5481
|
-
if (!drag.moved && (Math.abs(dx) > 2 || Math.abs(dy) > 2)) {
|
|
5482
|
-
drag.moved = true;
|
|
5483
|
-
}
|
|
5484
|
-
if (!drag.moved) {
|
|
5485
|
-
return;
|
|
5486
|
-
}
|
|
5487
|
-
let appliedDx = dx;
|
|
5488
|
-
let appliedDy = dy;
|
|
5489
|
-
const draggedIds = Object.keys(drag.startPositionsById);
|
|
5490
|
-
const primaryId = draggedIds[0];
|
|
5491
|
-
const primaryStart = primaryId ? drag.startPositionsById[primaryId] : void 0;
|
|
5492
|
-
const primaryEl = primaryId ? elementLookup.get(primaryId) : void 0;
|
|
5493
|
-
if (primaryStart && primaryEl) {
|
|
5494
|
-
let targetX = primaryStart.x + appliedDx;
|
|
5495
|
-
let targetY = primaryStart.y + appliedDy;
|
|
5496
|
-
if (snapToGrid) {
|
|
5497
|
-
targetX = Math.round(targetX / gridSpacingPx) * gridSpacingPx;
|
|
5498
|
-
targetY = Math.round(targetY / gridSpacingPx) * gridSpacingPx;
|
|
5499
|
-
}
|
|
5500
|
-
if (snapToShape) {
|
|
5501
|
-
const siblingSource = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
|
|
5502
|
-
const siblings = siblingSource.map((el) => ({
|
|
5503
|
-
id: el.id,
|
|
5504
|
-
x: el.x,
|
|
5505
|
-
y: el.y,
|
|
5506
|
-
width: el.width,
|
|
5507
|
-
height: el.height
|
|
5508
|
-
}));
|
|
5509
|
-
const snapResult = computeSnapToShape(
|
|
5510
|
-
targetX,
|
|
5511
|
-
targetY,
|
|
5512
|
-
primaryEl.width,
|
|
5513
|
-
primaryEl.height,
|
|
5514
|
-
siblings,
|
|
5515
|
-
new Set(draggedIds),
|
|
5516
|
-
guides.map((g) => ({ axis: g.axis, position: g.position }))
|
|
5517
|
-
);
|
|
5518
|
-
targetX = snapResult.x;
|
|
5519
|
-
targetY = snapResult.y;
|
|
5520
|
-
const newSnapLines = snapResult.lines.map((line) => ({
|
|
5521
|
-
axis: line.axis === "v" ? "x" : "y",
|
|
5522
|
-
position: line.position
|
|
5523
|
-
}));
|
|
5524
|
-
const newKey = JSON.stringify(newSnapLines);
|
|
5525
|
-
if (newKey !== tracker.lastSnapLinesKey) {
|
|
5526
|
-
tracker.lastSnapLinesKey = newKey;
|
|
5527
|
-
setSnapLines(newSnapLines);
|
|
5528
|
-
}
|
|
5529
|
-
} else if (tracker.lastSnapLinesKey !== "[]") {
|
|
5530
|
-
tracker.lastSnapLinesKey = "[]";
|
|
5531
|
-
setSnapLines([]);
|
|
5532
|
-
}
|
|
5533
|
-
appliedDx = targetX - primaryStart.x;
|
|
5534
|
-
appliedDy = targetY - primaryStart.y;
|
|
5535
|
-
}
|
|
5536
|
-
drag.lastDx = appliedDx;
|
|
5537
|
-
drag.lastDy = appliedDy;
|
|
5538
|
-
for (const [id, domEl] of drag.domEls) {
|
|
5539
|
-
const start = drag.startPositionsById[id];
|
|
5540
|
-
if (start) {
|
|
5541
|
-
const x = start.x + appliedDx;
|
|
5542
|
-
const y = start.y + appliedDy;
|
|
5543
|
-
domEl.style.left = `${x}px`;
|
|
5544
|
-
domEl.style.top = `${y}px`;
|
|
5545
|
-
syncSelectionHandleOverlay(domEl, id, { x, y });
|
|
5546
|
-
}
|
|
5547
|
-
}
|
|
5548
|
-
if (live) {
|
|
5549
|
-
for (const id of Object.keys(drag.startPositionsById)) {
|
|
5550
|
-
const start = drag.startPositionsById[id];
|
|
5551
|
-
publishLiveGeometry(live.patcher, live.slideId, id, {
|
|
5552
|
-
x: start.x + appliedDx,
|
|
5553
|
-
y: start.y + appliedDy
|
|
5554
|
-
});
|
|
5555
|
-
}
|
|
5556
|
-
}
|
|
5557
|
-
}
|
|
5558
|
-
function processResizeMove(e, rs, editorScale, snapToGrid, gridSpacingPx, live) {
|
|
5559
|
-
const dx = (e.clientX - rs.startClientX) / editorScale;
|
|
5560
|
-
const dy = (e.clientY - rs.startClientY) / editorScale;
|
|
5561
|
-
if (!rs.moved && (Math.abs(dx) > 2 || Math.abs(dy) > 2)) {
|
|
5562
|
-
rs.moved = true;
|
|
5563
|
-
}
|
|
5564
|
-
if (!rs.moved) {
|
|
5565
|
-
return;
|
|
5566
|
-
}
|
|
5567
|
-
const geo = computeResizeGeometry(
|
|
5568
|
-
rs.handle,
|
|
5569
|
-
rs.startX,
|
|
5570
|
-
rs.startY,
|
|
5571
|
-
rs.startWidth,
|
|
5572
|
-
rs.startHeight,
|
|
5573
|
-
dx,
|
|
5574
|
-
dy,
|
|
5575
|
-
snapToGrid,
|
|
5576
|
-
gridSpacingPx,
|
|
5577
|
-
e.shiftKey
|
|
5578
|
-
);
|
|
5579
|
-
rs.lastX = geo.x;
|
|
5580
|
-
rs.lastY = geo.y;
|
|
5581
|
-
rs.lastWidth = geo.width;
|
|
5582
|
-
rs.lastHeight = geo.height;
|
|
5583
|
-
const width = Math.max(geo.width, MIN_ELEMENT_SIZE);
|
|
5584
|
-
const height = Math.max(geo.height, MIN_ELEMENT_SIZE);
|
|
5585
|
-
if (rs.domEl) {
|
|
5586
|
-
rs.domEl.style.left = `${geo.x}px`;
|
|
5587
|
-
rs.domEl.style.top = `${geo.y}px`;
|
|
5588
|
-
rs.domEl.style.width = `${width}px`;
|
|
5589
|
-
rs.domEl.style.height = `${height}px`;
|
|
5590
|
-
syncSelectionHandleOverlay(rs.domEl, rs.elementId, { x: geo.x, y: geo.y, width, height });
|
|
5591
|
-
}
|
|
5592
|
-
if (live) {
|
|
5593
|
-
publishLiveGeometry(live.patcher, live.slideId, rs.elementId, {
|
|
5594
|
-
x: geo.x,
|
|
5595
|
-
y: geo.y,
|
|
5596
|
-
width,
|
|
5597
|
-
height
|
|
5598
|
-
});
|
|
5599
|
-
}
|
|
5600
|
-
}
|
|
5601
5359
|
function processAdjustmentMove(e, adj, editorScale, updateElementById) {
|
|
5602
5360
|
const dx = (e.clientX - adj.startClientX) / editorScale;
|
|
5603
5361
|
const dy = (e.clientY - adj.startClientY) / editorScale;
|
|
@@ -5616,26 +5374,20 @@ function processPointerUp(input) {
|
|
|
5616
5374
|
editTemplateMode,
|
|
5617
5375
|
templateElements,
|
|
5618
5376
|
activeSlide,
|
|
5619
|
-
activeSlideIndex,
|
|
5620
5377
|
marqueeStateRef,
|
|
5621
5378
|
dragStateRef,
|
|
5622
5379
|
resizeStateRef,
|
|
5623
5380
|
shapeAdjustmentDragStateRef,
|
|
5624
5381
|
justInteractedRef,
|
|
5382
|
+
gestureRef,
|
|
5625
5383
|
setMarqueeSelectionState,
|
|
5626
|
-
setSnapLines,
|
|
5627
|
-
setTemplateElementsBySlideId,
|
|
5628
5384
|
setPointerCommitNonce,
|
|
5629
5385
|
applySelection,
|
|
5630
5386
|
clearSelection,
|
|
5631
|
-
updateSlides,
|
|
5632
|
-
updateElementById,
|
|
5633
5387
|
markDirty,
|
|
5634
5388
|
livePatcher
|
|
5635
5389
|
} = input;
|
|
5636
5390
|
const marquee = marqueeStateRef.current;
|
|
5637
|
-
const drag = dragStateRef.current;
|
|
5638
|
-
const rs = resizeStateRef.current;
|
|
5639
5391
|
const adj = shapeAdjustmentDragStateRef.current;
|
|
5640
5392
|
if (marquee) {
|
|
5641
5393
|
commitMarquee(
|
|
@@ -5646,62 +5398,22 @@ function processPointerUp(input) {
|
|
|
5646
5398
|
applySelection,
|
|
5647
5399
|
clearSelection
|
|
5648
5400
|
);
|
|
5649
|
-
marqueeStateRef.current = null;
|
|
5650
|
-
setMarqueeSelectionState(null);
|
|
5651
5401
|
}
|
|
5652
|
-
if (
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
editTemplateMode,
|
|
5656
|
-
activeSlide,
|
|
5657
|
-
activeSlideIndex,
|
|
5658
|
-
setTemplateElementsBySlideId,
|
|
5659
|
-
updateSlides
|
|
5660
|
-
);
|
|
5402
|
+
if (!gestureRef?.current?.isActive()) {
|
|
5403
|
+
dragStateRef.current = null;
|
|
5404
|
+
resizeStateRef.current = null;
|
|
5661
5405
|
}
|
|
5662
|
-
if (
|
|
5663
|
-
const resizedId = rs.elementId;
|
|
5664
|
-
const resizeUpdates = {
|
|
5665
|
-
x: rs.lastX,
|
|
5666
|
-
y: rs.lastY,
|
|
5667
|
-
width: rs.lastWidth,
|
|
5668
|
-
height: rs.lastHeight
|
|
5669
|
-
};
|
|
5670
|
-
updateElementById(resizedId, resizeUpdates);
|
|
5671
|
-
const movedIds = /* @__PURE__ */ new Set([resizedId]);
|
|
5672
|
-
updateSlides(
|
|
5673
|
-
(prev) => prev.map((s, i) => {
|
|
5674
|
-
if (i !== activeSlideIndex) {
|
|
5675
|
-
return s;
|
|
5676
|
-
}
|
|
5677
|
-
const rerouted = rerouteConnectorsForMovedElements(s.elements, movedIds);
|
|
5678
|
-
if (rerouted.length === 0) {
|
|
5679
|
-
return s;
|
|
5680
|
-
}
|
|
5681
|
-
return {
|
|
5682
|
-
...s,
|
|
5683
|
-
elements: applyReroutedConnectors(s.elements, rerouted)
|
|
5684
|
-
};
|
|
5685
|
-
})
|
|
5686
|
-
);
|
|
5687
|
-
}
|
|
5688
|
-
const wasMoved = drag?.moved || rs?.moved || adj?.moved;
|
|
5689
|
-
if (wasMoved) {
|
|
5406
|
+
if (adj?.moved) {
|
|
5690
5407
|
justInteractedRef.current = true;
|
|
5691
|
-
}
|
|
5692
|
-
if (wasMoved) {
|
|
5693
5408
|
livePatcher?.flush();
|
|
5694
5409
|
}
|
|
5695
5410
|
marqueeStateRef.current = null;
|
|
5696
|
-
dragStateRef.current = null;
|
|
5697
|
-
resizeStateRef.current = null;
|
|
5698
5411
|
shapeAdjustmentDragStateRef.current = null;
|
|
5699
5412
|
setMarqueeSelectionState(null);
|
|
5700
|
-
|
|
5701
|
-
if (wasMoved) {
|
|
5413
|
+
if (adj?.moved) {
|
|
5702
5414
|
markDirty();
|
|
5703
5415
|
}
|
|
5704
|
-
if (
|
|
5416
|
+
if (adj || marquee) {
|
|
5705
5417
|
setPointerCommitNonce((n) => n + 1);
|
|
5706
5418
|
}
|
|
5707
5419
|
}
|
|
@@ -5721,35 +5433,6 @@ function commitMarquee(marquee, editTemplateMode, templateElements, activeSlide,
|
|
|
5721
5433
|
clearSelection();
|
|
5722
5434
|
}
|
|
5723
5435
|
}
|
|
5724
|
-
function commitDrag(drag, editTemplateMode, activeSlide, activeSlideIndex, setTemplateElementsBySlideId, updateSlides) {
|
|
5725
|
-
const dx = drag.lastDx, dy = drag.lastDy;
|
|
5726
|
-
const movedIds = new Set(Object.keys(drag.startPositionsById));
|
|
5727
|
-
const moveElements = (elements) => {
|
|
5728
|
-
const movedElements = elements.map((el) => {
|
|
5729
|
-
const start = drag.startPositionsById[el.id];
|
|
5730
|
-
if (!start) {
|
|
5731
|
-
return el;
|
|
5732
|
-
}
|
|
5733
|
-
return { ...el, x: start.x + dx, y: start.y + dy };
|
|
5734
|
-
});
|
|
5735
|
-
const rerouted = rerouteConnectorsForMovedElements(movedElements, movedIds);
|
|
5736
|
-
return applyReroutedConnectors(movedElements, rerouted);
|
|
5737
|
-
};
|
|
5738
|
-
if (editTemplateMode) {
|
|
5739
|
-
const slideId = activeSlide?.id;
|
|
5740
|
-
if (!slideId) {
|
|
5741
|
-
return;
|
|
5742
|
-
}
|
|
5743
|
-
setTemplateElementsBySlideId((prev) => ({
|
|
5744
|
-
...prev,
|
|
5745
|
-
[slideId]: moveElements(prev[slideId] ?? [])
|
|
5746
|
-
}));
|
|
5747
|
-
return;
|
|
5748
|
-
}
|
|
5749
|
-
updateSlides(
|
|
5750
|
-
(prev) => prev.map((s, i) => i !== activeSlideIndex ? s : { ...s, elements: moveElements(s.elements) })
|
|
5751
|
-
);
|
|
5752
|
-
}
|
|
5753
5436
|
|
|
5754
5437
|
// src/viewer/hooks/usePointerHandlers.ts
|
|
5755
5438
|
function usePointerHandlers(input) {
|
|
@@ -5759,41 +5442,42 @@ function usePointerHandlers(input) {
|
|
|
5759
5442
|
canvasSize,
|
|
5760
5443
|
activeSlide,
|
|
5761
5444
|
activeSlideIndex,
|
|
5762
|
-
gridSpacingPx,
|
|
5763
|
-
dragStateRef,
|
|
5764
|
-
resizeStateRef,
|
|
5765
5445
|
shapeAdjustmentDragStateRef,
|
|
5766
5446
|
marqueeStateRef,
|
|
5767
5447
|
editTemplateMode,
|
|
5768
|
-
snapToGrid,
|
|
5769
|
-
snapToShape,
|
|
5770
|
-
guides,
|
|
5771
5448
|
templateElements,
|
|
5772
|
-
elementLookup,
|
|
5773
5449
|
setMarqueeSelectionState,
|
|
5774
|
-
setSnapLines,
|
|
5775
|
-
setTemplateElementsBySlideId,
|
|
5776
5450
|
setPointerCommitNonce,
|
|
5777
5451
|
applySelection,
|
|
5778
5452
|
clearSelection,
|
|
5779
|
-
updateSlides,
|
|
5780
5453
|
updateElementById,
|
|
5781
5454
|
markDirty,
|
|
5782
|
-
livePatcher
|
|
5455
|
+
livePatcher,
|
|
5456
|
+
gestureRef
|
|
5783
5457
|
} = input;
|
|
5458
|
+
const inputRef = useRef(input);
|
|
5459
|
+
inputRef.current = input;
|
|
5460
|
+
const gestures = useMemo(() => createCanvasGestures(() => inputRef.current), []);
|
|
5784
5461
|
useEffect(() => {
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5462
|
+
if (gestureRef) {
|
|
5463
|
+
gestureRef.current = gestures;
|
|
5464
|
+
}
|
|
5465
|
+
return () => {
|
|
5466
|
+
gestures.dispose();
|
|
5467
|
+
if (gestureRef?.current === gestures) {
|
|
5468
|
+
gestureRef.current = null;
|
|
5469
|
+
}
|
|
5789
5470
|
};
|
|
5471
|
+
}, [gestures, gestureRef]);
|
|
5472
|
+
useEffect(() => {
|
|
5473
|
+
const tracker = { rafId: 0, pendingMoveEvent: null };
|
|
5790
5474
|
const handlePointerMove = (e) => {
|
|
5791
5475
|
tracker.pendingMoveEvent = e;
|
|
5792
5476
|
if (tracker.rafId === 0) {
|
|
5793
5477
|
tracker.rafId = requestAnimationFrame(() => {
|
|
5794
5478
|
tracker.rafId = 0;
|
|
5795
5479
|
if (tracker.pendingMoveEvent) {
|
|
5796
|
-
processPointerMove(tracker.pendingMoveEvent, input
|
|
5480
|
+
processPointerMove(tracker.pendingMoveEvent, input);
|
|
5797
5481
|
tracker.pendingMoveEvent = null;
|
|
5798
5482
|
}
|
|
5799
5483
|
});
|
|
@@ -5821,31 +5505,22 @@ function usePointerHandlers(input) {
|
|
|
5821
5505
|
}, [
|
|
5822
5506
|
editorScale,
|
|
5823
5507
|
canvasStageRef,
|
|
5824
|
-
dragStateRef,
|
|
5825
|
-
resizeStateRef,
|
|
5826
5508
|
shapeAdjustmentDragStateRef,
|
|
5827
5509
|
marqueeStateRef,
|
|
5828
5510
|
editTemplateMode,
|
|
5829
|
-
snapToGrid,
|
|
5830
|
-
snapToShape,
|
|
5831
|
-
guides,
|
|
5832
5511
|
templateElements,
|
|
5833
5512
|
setMarqueeSelectionState,
|
|
5834
|
-
setSnapLines,
|
|
5835
|
-
elementLookup,
|
|
5836
|
-
setTemplateElementsBySlideId,
|
|
5837
5513
|
setPointerCommitNonce,
|
|
5838
5514
|
activeSlide,
|
|
5839
5515
|
activeSlideIndex,
|
|
5840
5516
|
canvasSize.width,
|
|
5841
5517
|
canvasSize.height,
|
|
5842
|
-
gridSpacingPx,
|
|
5843
5518
|
applySelection,
|
|
5844
5519
|
clearSelection,
|
|
5845
|
-
updateSlides,
|
|
5846
5520
|
updateElementById,
|
|
5847
5521
|
markDirty,
|
|
5848
|
-
livePatcher
|
|
5522
|
+
livePatcher,
|
|
5523
|
+
gestureRef
|
|
5849
5524
|
]);
|
|
5850
5525
|
}
|
|
5851
5526
|
function mouseDownStartsSelectionDrag(event) {
|
|
@@ -5871,6 +5546,7 @@ function useCanvasInteractions(input) {
|
|
|
5871
5546
|
shapeAdjustmentDragStateRef,
|
|
5872
5547
|
marqueeStateRef,
|
|
5873
5548
|
justInteractedRef,
|
|
5549
|
+
gestureRef,
|
|
5874
5550
|
setInlineEditingElementId,
|
|
5875
5551
|
setInlineEditingText,
|
|
5876
5552
|
setContextMenuState,
|
|
@@ -5896,25 +5572,7 @@ function useCanvasInteractions(input) {
|
|
|
5896
5572
|
const scale = editorScale || 1;
|
|
5897
5573
|
return rect ? { x: (e.clientX - rect.left) / scale, y: (e.clientY - rect.top) / scale } : null;
|
|
5898
5574
|
};
|
|
5899
|
-
const
|
|
5900
|
-
if (!slideElements) {
|
|
5901
|
-
return null;
|
|
5902
|
-
}
|
|
5903
|
-
const top = slideElements.find((el) => el.id === elementId);
|
|
5904
|
-
const point = slidePoint(e);
|
|
5905
|
-
if (!top || !point || !isEnterableGroup(top)) {
|
|
5906
|
-
return null;
|
|
5907
|
-
}
|
|
5908
|
-
return memberChainAtPoint(slideElements, elementId, point);
|
|
5909
|
-
};
|
|
5910
|
-
const resolvePressTarget = (elementId, e) => {
|
|
5911
|
-
const chain = drillChain(elementId, e);
|
|
5912
|
-
if (!chain || !slideElements) {
|
|
5913
|
-
return elementId;
|
|
5914
|
-
}
|
|
5915
|
-
const selectedPath = selectedElementId ? findElementPath(slideElements, selectedElementId) : null;
|
|
5916
|
-
return drillSelectionForClick(chain, selectedPath) ?? elementId;
|
|
5917
|
-
};
|
|
5575
|
+
const resolvePressTarget = (elementId, e) => slideElements ? resolveGroupPressTarget(slideElements, elementId, slidePoint(e), effectiveSelectedIds) : elementId;
|
|
5918
5576
|
const handleInlineEditCommit = () => {
|
|
5919
5577
|
const editId = inlineEditingElementId;
|
|
5920
5578
|
if (!editId) {
|
|
@@ -6014,9 +5672,7 @@ function useCanvasInteractions(input) {
|
|
|
6014
5672
|
}
|
|
6015
5673
|
};
|
|
6016
5674
|
const handleElementDoubleClick = (pressedId, e) => {
|
|
6017
|
-
const
|
|
6018
|
-
const innermost = chain ? drillSelectionForDoubleClick(chain) : null;
|
|
6019
|
-
const elementId = innermost && canInteractWithElement(elementLookup.get(innermost), "select") ? innermost : pressedId;
|
|
5675
|
+
const elementId = mode === "present" || !slideElements ? pressedId : resolveGroupDoubleClickTarget(slideElements, pressedId, slidePoint(e));
|
|
6020
5676
|
if (elementId !== pressedId) {
|
|
6021
5677
|
ops.applySelection(elementId);
|
|
6022
5678
|
}
|
|
@@ -6079,6 +5735,7 @@ function useCanvasInteractions(input) {
|
|
|
6079
5735
|
lastDy: 0
|
|
6080
5736
|
};
|
|
6081
5737
|
setSnapLines([]);
|
|
5738
|
+
gestureRef?.current?.begin("move", movableIds[0], e);
|
|
6082
5739
|
};
|
|
6083
5740
|
const handleElementContextMenu = (elementId, e) => {
|
|
6084
5741
|
if (mode === "present") {
|
|
@@ -6151,6 +5808,7 @@ function useCanvasInteractions(input) {
|
|
|
6151
5808
|
lastWidth: el.width,
|
|
6152
5809
|
lastHeight: el.height
|
|
6153
5810
|
};
|
|
5811
|
+
gestureRef?.current?.begin("resize", elementId, e);
|
|
6154
5812
|
};
|
|
6155
5813
|
const handleRotate = (elementId, rotationDeg) => {
|
|
6156
5814
|
const el = elementLookup.get(elementId);
|
|
@@ -6656,11 +6314,11 @@ function useInsertElements(input) {
|
|
|
6656
6314
|
id: generateElementId()
|
|
6657
6315
|
});
|
|
6658
6316
|
};
|
|
6659
|
-
const handleAddChart = (chartKind) => {
|
|
6317
|
+
const handleAddChart = (chartKind, options) => {
|
|
6660
6318
|
if (!activeSlide) {
|
|
6661
6319
|
return;
|
|
6662
6320
|
}
|
|
6663
|
-
addElement(createDefaultChartElement(chartKind));
|
|
6321
|
+
addElement(createDefaultChartElement(chartKind, void 0, options));
|
|
6664
6322
|
};
|
|
6665
6323
|
const structured = createStructuredElementHandlers({
|
|
6666
6324
|
activeSlide,
|
|
@@ -7551,6 +7209,8 @@ async function renderToCanvas(element, options = {}) {
|
|
|
7551
7209
|
const { default: html2canvasPro } = await import('html2canvas-pro');
|
|
7552
7210
|
return html2canvasPro(element, {
|
|
7553
7211
|
...options,
|
|
7212
|
+
// Clone only the captured element's branch: html2canvas would copy the whole page.
|
|
7213
|
+
ignoreElements: html2canvasCaptureScope(element, options.ignoreElements),
|
|
7554
7214
|
onclone: async (doc, clonedEl) => {
|
|
7555
7215
|
await prepareHtml2CanvasClone(element, doc, clonedEl);
|
|
7556
7216
|
if (typeof userOnClone === "function") {
|
|
@@ -9103,6 +8763,7 @@ function useViewerDialogs(input) {
|
|
|
9103
8763
|
embeddedFontFamilies
|
|
9104
8764
|
} = input;
|
|
9105
8765
|
const [isSmartArtDialogOpen, setIsSmartArtDialogOpen] = useState(false);
|
|
8766
|
+
const [isChartDialogOpen, setIsChartDialogOpen] = useState(false);
|
|
9106
8767
|
const [isEquationDialogOpen, setIsEquationDialogOpen] = useState(false);
|
|
9107
8768
|
const [isHyperlinkDialogOpen, setIsHyperlinkDialogOpen] = useState(false);
|
|
9108
8769
|
const [isPasswordDialogOpen, setIsPasswordDialogOpen] = useState(false);
|
|
@@ -9247,6 +8908,8 @@ function useViewerDialogs(input) {
|
|
|
9247
8908
|
return {
|
|
9248
8909
|
isSmartArtDialogOpen,
|
|
9249
8910
|
setIsSmartArtDialogOpen,
|
|
8911
|
+
isChartDialogOpen,
|
|
8912
|
+
setIsChartDialogOpen,
|
|
9250
8913
|
isEquationDialogOpen,
|
|
9251
8914
|
setIsEquationDialogOpen,
|
|
9252
8915
|
isHyperlinkDialogOpen,
|
|
@@ -9692,84 +9355,35 @@ function useSerialize(input) {
|
|
|
9692
9355
|
}
|
|
9693
9356
|
function useRecoveryDetection(input) {
|
|
9694
9357
|
const { filePath, fileName, loading, error, slideCount, autosaveAllowed = true } = input;
|
|
9695
|
-
const
|
|
9696
|
-
|
|
9697
|
-
const
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9358
|
+
const live = useRef(input);
|
|
9359
|
+
live.current = input;
|
|
9360
|
+
const [controller] = useState(
|
|
9361
|
+
() => createAutosaveRecoveryController({
|
|
9362
|
+
getStorage: () => live.current.storage,
|
|
9363
|
+
load: (bytes) => live.current.onRestore?.(bytes),
|
|
9364
|
+
onOffered: (record) => {
|
|
9365
|
+
live.current.onOffered?.(record);
|
|
9366
|
+
live.current.openVersionHistory?.();
|
|
9367
|
+
},
|
|
9368
|
+
probe: probeAutosaveRecovery,
|
|
9369
|
+
discardRecord: discardAutosaveRecovery
|
|
9370
|
+
})
|
|
9371
|
+
);
|
|
9372
|
+
const { prompt, discarding } = useController(controller);
|
|
9708
9373
|
useEffect(() => {
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
void (async () => {
|
|
9721
|
-
const offer = await probeAutosaveRecovery(
|
|
9722
|
-
filePath,
|
|
9723
|
-
Date.now(),
|
|
9724
|
-
fileName,
|
|
9725
|
-
storageRef.current
|
|
9726
|
-
);
|
|
9727
|
-
if (!offer) {
|
|
9728
|
-
return;
|
|
9729
|
-
}
|
|
9730
|
-
recordRef.current = offer.record;
|
|
9731
|
-
setPrompt(offer.prompt);
|
|
9732
|
-
onOfferedRef.current?.(offer.record);
|
|
9733
|
-
openVersionHistory?.();
|
|
9734
|
-
})();
|
|
9735
|
-
}, [filePath, fileName, loading, error, slideCount, autosaveAllowed, openVersionHistory]);
|
|
9736
|
-
const restore = useCallback(() => {
|
|
9737
|
-
if (actionPendingRef.current) {
|
|
9738
|
-
return;
|
|
9739
|
-
}
|
|
9740
|
-
actionPendingRef.current = true;
|
|
9741
|
-
const record = recordRef.current;
|
|
9742
|
-
setPrompt(null);
|
|
9743
|
-
if (record && onRestore) {
|
|
9744
|
-
onRestore(acceptAutosaveRecovery(record));
|
|
9745
|
-
acknowledgeAutosaveRecovery(record);
|
|
9746
|
-
}
|
|
9747
|
-
recordRef.current = null;
|
|
9748
|
-
}, [onRestore]);
|
|
9749
|
-
const discard = useCallback(() => {
|
|
9750
|
-
if (actionPendingRef.current) {
|
|
9751
|
-
return;
|
|
9752
|
-
}
|
|
9753
|
-
const record = recordRef.current;
|
|
9754
|
-
if (!record) {
|
|
9755
|
-
setPrompt(null);
|
|
9756
|
-
return;
|
|
9374
|
+
controller.check({ filePath, fileName, loading, error, slideCount, autosaveAllowed });
|
|
9375
|
+
}, [controller, filePath, fileName, loading, error, slideCount, autosaveAllowed]);
|
|
9376
|
+
return {
|
|
9377
|
+
prompt,
|
|
9378
|
+
discarding,
|
|
9379
|
+
restore: () => {
|
|
9380
|
+
void controller.restore().catch(() => {
|
|
9381
|
+
});
|
|
9382
|
+
},
|
|
9383
|
+
discard: () => {
|
|
9384
|
+
void controller.discard();
|
|
9757
9385
|
}
|
|
9758
|
-
|
|
9759
|
-
setDiscarding(true);
|
|
9760
|
-
void (async () => {
|
|
9761
|
-
try {
|
|
9762
|
-
await discardAutosaveRecovery(record, storageRef.current);
|
|
9763
|
-
recordRef.current = null;
|
|
9764
|
-
setPrompt(null);
|
|
9765
|
-
} catch {
|
|
9766
|
-
} finally {
|
|
9767
|
-
actionPendingRef.current = false;
|
|
9768
|
-
setDiscarding(false);
|
|
9769
|
-
}
|
|
9770
|
-
})();
|
|
9771
|
-
}, []);
|
|
9772
|
-
return { prompt, restore, discard, discarding };
|
|
9386
|
+
};
|
|
9773
9387
|
}
|
|
9774
9388
|
function usePresentationSetup(input) {
|
|
9775
9389
|
const {
|
|
@@ -10243,6 +9857,7 @@ function useEditorOperations(input) {
|
|
|
10243
9857
|
shapeAdjustmentDragStateRef: state.shapeAdjustmentDragStateRef,
|
|
10244
9858
|
marqueeStateRef: state.marqueeStateRef,
|
|
10245
9859
|
justInteractedRef: state.justInteractedRef,
|
|
9860
|
+
gestureRef: state.gestureControllerRef,
|
|
10246
9861
|
setInlineEditingElementId: state.setInlineEditingElementId,
|
|
10247
9862
|
setInlineEditingText: state.setInlineEditingText,
|
|
10248
9863
|
setContextMenuState: state.setContextMenuState,
|
|
@@ -10775,6 +10390,8 @@ function useContentLifecycle(input) {
|
|
|
10775
10390
|
// deck it has already snapshotted. The two refs are read by `.current`
|
|
10776
10391
|
// because an inline edit in progress lives there and nowhere else yet.
|
|
10777
10392
|
onSaved: input.onAutosave,
|
|
10393
|
+
inlineDraftSinkRef: state.autosaveDraftSinkRef,
|
|
10394
|
+
getInlineEditingId: () => state.inlineEditingElementIdRef.current,
|
|
10778
10395
|
getChangeSources: () => [
|
|
10779
10396
|
slides,
|
|
10780
10397
|
state.templateElementsBySlideId,
|
|
@@ -10804,138 +10421,27 @@ function useKeyboardShortcuts(input) {
|
|
|
10804
10421
|
inputRef.current = input;
|
|
10805
10422
|
const handleKeyDown = useCallback((e) => {
|
|
10806
10423
|
const current = inputRef.current;
|
|
10807
|
-
|
|
10808
|
-
if (startAction !== null) {
|
|
10809
|
-
e.preventDefault();
|
|
10810
|
-
if (startAction === "fromBeginning") {
|
|
10811
|
-
current.onStartShowFromBeginning();
|
|
10812
|
-
} else {
|
|
10813
|
-
current.onStartShowFromCurrent();
|
|
10814
|
-
}
|
|
10815
|
-
return;
|
|
10816
|
-
}
|
|
10817
|
-
const { action, dx, dy } = mapCustomizedEditorKey(
|
|
10424
|
+
dispatchEditorKey(
|
|
10818
10425
|
e,
|
|
10819
10426
|
{
|
|
10820
10427
|
canEdit: current.canEdit,
|
|
10821
|
-
canPaste: current.canPaste,
|
|
10822
|
-
// The Slide Master view is an editing surface, not a viewing one
|
|
10823
|
-
//
|
|
10824
|
-
// NO_ACTION there, so Delete, the arrow-key nudges and the clipboard
|
|
10825
|
-
// keys were all inert over a master shape even though the write path
|
|
10826
|
-
// behind them routes to the owning part correctly. Svelte and
|
|
10827
|
-
// vanilla, which render the master into their ordinary editable
|
|
10828
|
-
// stage, never had the gap.
|
|
10428
|
+
...current.canPaste === void 0 ? {} : { canPaste: current.canPaste },
|
|
10429
|
+
// The Slide Master view is an editing surface, not a viewing one, so
|
|
10430
|
+
// only the other modes count as "not editing" for the editor keymap.
|
|
10829
10431
|
isPresenting: current.mode !== "edit" && current.mode !== "master",
|
|
10432
|
+
// F5 is only inert while the show itself runs: a read-only viewer can
|
|
10433
|
+
// still start a show (it has a "From Beginning" button too).
|
|
10434
|
+
isShowRunning: current.mode === "present",
|
|
10435
|
+
canStartShow: !current.customization || isFeatureEnabled(current.customization, "presentMode"),
|
|
10830
10436
|
hasSelection: current.hasSelection,
|
|
10831
10437
|
isEditingText: Boolean(
|
|
10832
10438
|
current.inlineEditingElementId || current.tableEditorState?.isEditing
|
|
10833
10439
|
),
|
|
10834
10440
|
isDrawing: current.activeTool !== "select",
|
|
10835
|
-
|
|
10836
|
-
isControlTarget: isEditorControlTarget(e.target)
|
|
10441
|
+
keyboard: current.customization?.keyboard
|
|
10837
10442
|
},
|
|
10838
|
-
current
|
|
10443
|
+
toEditorKeyHandlers(current)
|
|
10839
10444
|
);
|
|
10840
|
-
if (action === null) {
|
|
10841
|
-
return;
|
|
10842
|
-
}
|
|
10843
|
-
e.preventDefault();
|
|
10844
|
-
switch (action) {
|
|
10845
|
-
case "escape":
|
|
10846
|
-
current.onEscape();
|
|
10847
|
-
break;
|
|
10848
|
-
case "delete":
|
|
10849
|
-
current.onDelete();
|
|
10850
|
-
break;
|
|
10851
|
-
case "undo":
|
|
10852
|
-
current.onUndo();
|
|
10853
|
-
break;
|
|
10854
|
-
case "redo":
|
|
10855
|
-
current.onRedo();
|
|
10856
|
-
break;
|
|
10857
|
-
case "copy":
|
|
10858
|
-
current.onCopy();
|
|
10859
|
-
break;
|
|
10860
|
-
case "cut":
|
|
10861
|
-
current.onCut();
|
|
10862
|
-
break;
|
|
10863
|
-
case "paste":
|
|
10864
|
-
current.onPaste();
|
|
10865
|
-
break;
|
|
10866
|
-
case "duplicate":
|
|
10867
|
-
current.onDuplicate();
|
|
10868
|
-
break;
|
|
10869
|
-
case "selectAll":
|
|
10870
|
-
current.onSelectAll();
|
|
10871
|
-
break;
|
|
10872
|
-
case "group":
|
|
10873
|
-
current.onGroup?.();
|
|
10874
|
-
break;
|
|
10875
|
-
case "ungroup":
|
|
10876
|
-
current.onUngroup?.();
|
|
10877
|
-
break;
|
|
10878
|
-
case "toggleShortcuts":
|
|
10879
|
-
current.onToggleShortcuts?.();
|
|
10880
|
-
break;
|
|
10881
|
-
case "find":
|
|
10882
|
-
current.onFind?.();
|
|
10883
|
-
break;
|
|
10884
|
-
case "nudge":
|
|
10885
|
-
current.onNudge(dx ?? 0, dy ?? 0);
|
|
10886
|
-
break;
|
|
10887
|
-
case "prevSlide":
|
|
10888
|
-
current.onPrevSlide?.();
|
|
10889
|
-
break;
|
|
10890
|
-
case "nextSlide":
|
|
10891
|
-
current.onNextSlide?.();
|
|
10892
|
-
break;
|
|
10893
|
-
case "alignLeft":
|
|
10894
|
-
current.onAlignLeft?.();
|
|
10895
|
-
break;
|
|
10896
|
-
case "alignCenter":
|
|
10897
|
-
current.onAlignCenter?.();
|
|
10898
|
-
break;
|
|
10899
|
-
case "alignRight":
|
|
10900
|
-
current.onAlignRight?.();
|
|
10901
|
-
break;
|
|
10902
|
-
case "alignJustify":
|
|
10903
|
-
current.onAlignJustify?.();
|
|
10904
|
-
break;
|
|
10905
|
-
case "increaseFontSize":
|
|
10906
|
-
current.onIncreaseFontSize?.();
|
|
10907
|
-
break;
|
|
10908
|
-
case "decreaseFontSize":
|
|
10909
|
-
current.onDecreaseFontSize?.();
|
|
10910
|
-
break;
|
|
10911
|
-
case "copyFormat":
|
|
10912
|
-
current.onCopyFormat?.();
|
|
10913
|
-
break;
|
|
10914
|
-
case "pasteFormat":
|
|
10915
|
-
current.onPasteFormat?.();
|
|
10916
|
-
break;
|
|
10917
|
-
case "newSlide":
|
|
10918
|
-
current.onNewSlide?.();
|
|
10919
|
-
break;
|
|
10920
|
-
case "hyperlink":
|
|
10921
|
-
current.onHyperlink?.();
|
|
10922
|
-
break;
|
|
10923
|
-
case "findReplace":
|
|
10924
|
-
current.onFindReplace?.();
|
|
10925
|
-
break;
|
|
10926
|
-
case "clearFormatting":
|
|
10927
|
-
current.onClearFormatting?.();
|
|
10928
|
-
break;
|
|
10929
|
-
case "cycleSelectionNext":
|
|
10930
|
-
current.onCycleSelectionNext?.();
|
|
10931
|
-
break;
|
|
10932
|
-
case "cycleSelectionPrev":
|
|
10933
|
-
current.onCycleSelectionPrev?.();
|
|
10934
|
-
break;
|
|
10935
|
-
case "pasteSpecial":
|
|
10936
|
-
current.onPasteSpecial?.();
|
|
10937
|
-
break;
|
|
10938
|
-
}
|
|
10939
10445
|
}, []);
|
|
10940
10446
|
useEffect(() => {
|
|
10941
10447
|
window.addEventListener("keydown", handleKeyDown);
|
|
@@ -10944,6 +10450,43 @@ function useKeyboardShortcuts(input) {
|
|
|
10944
10450
|
};
|
|
10945
10451
|
}, [handleKeyDown]);
|
|
10946
10452
|
}
|
|
10453
|
+
function toEditorKeyHandlers(current) {
|
|
10454
|
+
return {
|
|
10455
|
+
startShowFromBeginning: current.onStartShowFromBeginning,
|
|
10456
|
+
startShowFromCurrent: current.onStartShowFromCurrent,
|
|
10457
|
+
escape: current.onEscape,
|
|
10458
|
+
delete: current.onDelete,
|
|
10459
|
+
undo: current.onUndo,
|
|
10460
|
+
redo: current.onRedo,
|
|
10461
|
+
copy: current.onCopy,
|
|
10462
|
+
cut: current.onCut,
|
|
10463
|
+
paste: current.onPaste,
|
|
10464
|
+
duplicate: current.onDuplicate,
|
|
10465
|
+
selectAll: current.onSelectAll,
|
|
10466
|
+
group: current.onGroup,
|
|
10467
|
+
ungroup: current.onUngroup,
|
|
10468
|
+
toggleShortcuts: current.onToggleShortcuts,
|
|
10469
|
+
find: current.onFind,
|
|
10470
|
+
nudge: current.onNudge,
|
|
10471
|
+
prevSlide: current.onPrevSlide,
|
|
10472
|
+
nextSlide: current.onNextSlide,
|
|
10473
|
+
alignLeft: current.onAlignLeft,
|
|
10474
|
+
alignCenter: current.onAlignCenter,
|
|
10475
|
+
alignRight: current.onAlignRight,
|
|
10476
|
+
alignJustify: current.onAlignJustify,
|
|
10477
|
+
increaseFontSize: current.onIncreaseFontSize,
|
|
10478
|
+
decreaseFontSize: current.onDecreaseFontSize,
|
|
10479
|
+
copyFormat: current.onCopyFormat,
|
|
10480
|
+
pasteFormat: current.onPasteFormat,
|
|
10481
|
+
newSlide: current.onNewSlide,
|
|
10482
|
+
hyperlink: current.onHyperlink,
|
|
10483
|
+
findReplace: current.onFindReplace,
|
|
10484
|
+
clearFormatting: current.onClearFormatting,
|
|
10485
|
+
cycleSelectionNext: current.onCycleSelectionNext,
|
|
10486
|
+
cycleSelectionPrev: current.onCycleSelectionPrev,
|
|
10487
|
+
pasteSpecial: current.onPasteSpecial
|
|
10488
|
+
};
|
|
10489
|
+
}
|
|
10947
10490
|
var CLEAR_FORMATTING_PATCH = {
|
|
10948
10491
|
bold: false,
|
|
10949
10492
|
italic: false,
|
|
@@ -11209,7 +10752,8 @@ function useViewerIntegration(input) {
|
|
|
11209
10752
|
updateSlides: editorOps.ops.updateSlides,
|
|
11210
10753
|
updateElementById: editorOps.ops.updateElementById,
|
|
11211
10754
|
markDirty: history.markDirty,
|
|
11212
|
-
livePatcher: state.livePatcher
|
|
10755
|
+
livePatcher: state.livePatcher,
|
|
10756
|
+
gestureRef: state.gestureControllerRef
|
|
11213
10757
|
});
|
|
11214
10758
|
const [isEncryptedDialogOpen, setIsEncryptedDialogOpen] = useState(false);
|
|
11215
10759
|
const [loadVersion, setLoadVersion] = useState(0);
|
|
@@ -12646,6 +12190,7 @@ function buildToolbarProps(input) {
|
|
|
12646
12190
|
onAddShape: insertHandlers.handleAddShape,
|
|
12647
12191
|
onAddTable: insertHandlers.handleAddTable,
|
|
12648
12192
|
onAddChart: insertHandlers.handleAddChart,
|
|
12193
|
+
onOpenChartDialog: () => dialogs.setIsChartDialogOpen(true),
|
|
12649
12194
|
onAddSmartArt: () => dialogs.setIsSmartArtDialogOpen(true),
|
|
12650
12195
|
onAddEquation: () => {
|
|
12651
12196
|
dialogs.setEditingEquationOmml(null);
|
|
@@ -13178,73 +12723,47 @@ function useReadOnlyRecommendationState(content) {
|
|
|
13178
12723
|
() => readOnlyRecommendation(void 0)
|
|
13179
12724
|
);
|
|
13180
12725
|
const [modifyVerifier, setModifyVerifier] = useState(void 0);
|
|
13181
|
-
const [
|
|
13182
|
-
const
|
|
13183
|
-
const
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
setPasswordPromptOpen(false);
|
|
13190
|
-
setPasswordError(null);
|
|
13191
|
-
setCheckingPassword(false);
|
|
13192
|
-
}, [content]);
|
|
13193
|
-
const unlock = useCallback(() => {
|
|
13194
|
-
setEditAnywayActive(true);
|
|
13195
|
-
setBannerHidden(true);
|
|
13196
|
-
setPasswordPromptOpen(false);
|
|
13197
|
-
setPasswordError(null);
|
|
13198
|
-
}, []);
|
|
13199
|
-
const editAnyway = useCallback(() => {
|
|
13200
|
-
if (recommendation.requiresPassword) {
|
|
13201
|
-
setPasswordPromptOpen(true);
|
|
13202
|
-
setPasswordError(null);
|
|
13203
|
-
return;
|
|
13204
|
-
}
|
|
13205
|
-
unlock();
|
|
13206
|
-
}, [recommendation.requiresPassword, unlock]);
|
|
13207
|
-
const dismiss = useCallback(() => {
|
|
13208
|
-
setBannerHidden(true);
|
|
13209
|
-
}, []);
|
|
13210
|
-
const cancelPasswordPrompt = useCallback(() => {
|
|
13211
|
-
setPasswordPromptOpen(false);
|
|
13212
|
-
setPasswordError(null);
|
|
13213
|
-
}, []);
|
|
13214
|
-
const submitPassword = useCallback(
|
|
13215
|
-
async (password) => {
|
|
13216
|
-
setCheckingPassword(true);
|
|
13217
|
-
try {
|
|
13218
|
-
const result = await checkModifyPassword(modifyVerifier, password);
|
|
13219
|
-
if (result.ok) {
|
|
13220
|
-
unlock();
|
|
13221
|
-
} else {
|
|
13222
|
-
setPasswordError(result.reason);
|
|
13223
|
-
}
|
|
13224
|
-
} finally {
|
|
13225
|
-
setCheckingPassword(false);
|
|
12726
|
+
const [session, setSession] = useState(INITIAL_READ_ONLY_SESSION);
|
|
12727
|
+
const latestSession = useRef(session);
|
|
12728
|
+
const store = useMemo(
|
|
12729
|
+
() => ({
|
|
12730
|
+
get: () => latestSession.current,
|
|
12731
|
+
set: (next) => {
|
|
12732
|
+
latestSession.current = next;
|
|
12733
|
+
setSession(next);
|
|
13226
12734
|
}
|
|
13227
|
-
},
|
|
13228
|
-
|
|
13229
|
-
[modifyVerifier, unlock]
|
|
12735
|
+
}),
|
|
12736
|
+
[]
|
|
13230
12737
|
);
|
|
12738
|
+
const actions = useMemo(
|
|
12739
|
+
() => readOnlySessionActions(store, {
|
|
12740
|
+
recommendation: () => recommendation,
|
|
12741
|
+
modifyVerifier: () => modifyVerifier
|
|
12742
|
+
}),
|
|
12743
|
+
[store, recommendation, modifyVerifier]
|
|
12744
|
+
);
|
|
12745
|
+
useEffect(() => {
|
|
12746
|
+
applyReadOnlySessionEvent(store, { type: "reset" });
|
|
12747
|
+
}, [content, store]);
|
|
13231
12748
|
return {
|
|
13232
12749
|
recommendation,
|
|
13233
12750
|
setRecommendation,
|
|
13234
12751
|
setModifyVerifier,
|
|
13235
12752
|
/** Whether the viewer's `canEdit` should be forced off. */
|
|
13236
|
-
locked: recommendation
|
|
13237
|
-
bannerVisible: recommendation
|
|
13238
|
-
|
|
13239
|
-
|
|
12753
|
+
locked: readOnlyLocked(recommendation, session),
|
|
12754
|
+
bannerVisible: readOnlyBannerVisible(recommendation, session),
|
|
12755
|
+
/** The banner's "Edit anyway": opens the password prompt when one is required, else unlocks. */
|
|
12756
|
+
editAnyway: actions.editAnyway,
|
|
12757
|
+
dismiss: actions.dismiss,
|
|
13240
12758
|
/** Whether the inline password prompt should render in place of the banner's buttons. */
|
|
13241
|
-
passwordPromptOpen,
|
|
12759
|
+
passwordPromptOpen: session.passwordPromptOpen,
|
|
13242
12760
|
/** Reason the last password attempt failed, or null before any attempt / after success. */
|
|
13243
|
-
passwordError,
|
|
12761
|
+
passwordError: session.passwordError,
|
|
13244
12762
|
/** True while `submitPassword`'s check is in flight (disables the form). */
|
|
13245
|
-
checkingPassword,
|
|
13246
|
-
|
|
13247
|
-
|
|
12763
|
+
checkingPassword: session.checkingPassword,
|
|
12764
|
+
/** Check `password` against the deck's `modifyVerifier`; unlocks on a match. */
|
|
12765
|
+
submitPassword: actions.submitPassword,
|
|
12766
|
+
cancelPasswordPrompt: actions.cancelPassword
|
|
13248
12767
|
};
|
|
13249
12768
|
}
|
|
13250
12769
|
function useViewPreferencesSync(input) {
|
|
@@ -14531,6 +14050,50 @@ var EDGE_HANDLES = [
|
|
|
14531
14050
|
sizeClass: "w-2 h-5 max-md:w-3 max-md:h-8 rounded-sm"
|
|
14532
14051
|
}
|
|
14533
14052
|
];
|
|
14053
|
+
var wholeDegrees = (deg) => Math.round((deg % 360 + 360) % 360) % 360;
|
|
14054
|
+
function startRotateKnobGesture(options) {
|
|
14055
|
+
const { button, elementId, rotation, onRotate } = options;
|
|
14056
|
+
const scope = button.closest("[data-pptx-viewport]") ?? document;
|
|
14057
|
+
const wrapper = scope.querySelector(elementIdSelector(elementId));
|
|
14058
|
+
if (!wrapper) {
|
|
14059
|
+
return;
|
|
14060
|
+
}
|
|
14061
|
+
const rect = wrapper.getBoundingClientRect();
|
|
14062
|
+
const base = options.nonRotationTransform ? ` ${options.nonRotationTransform}` : "";
|
|
14063
|
+
const paint = (deg) => {
|
|
14064
|
+
const transform = `rotate(${deg}deg)${base}`;
|
|
14065
|
+
wrapper.style.transform = transform;
|
|
14066
|
+
syncSelectionHandleOverlay(wrapper, elementId, { transform });
|
|
14067
|
+
};
|
|
14068
|
+
if (options.pointerId !== void 0) {
|
|
14069
|
+
button.setPointerCapture?.(options.pointerId);
|
|
14070
|
+
}
|
|
14071
|
+
const gesture = createGestureController({
|
|
14072
|
+
getScale: () => 1,
|
|
14073
|
+
getElementBox: () => ({
|
|
14074
|
+
x: rect.left,
|
|
14075
|
+
y: rect.top,
|
|
14076
|
+
width: rect.width,
|
|
14077
|
+
height: rect.height,
|
|
14078
|
+
rotation
|
|
14079
|
+
}),
|
|
14080
|
+
getSiblings: () => [],
|
|
14081
|
+
getStageOrigin: () => ({ left: 0, top: 0 }),
|
|
14082
|
+
onStart: () => void 0,
|
|
14083
|
+
onPreview: (transform) => paint(wholeDegrees(transform.rotation)),
|
|
14084
|
+
onEnd: (transform) => {
|
|
14085
|
+
const deg = transform ? wholeDegrees(transform.rotation) : rotation;
|
|
14086
|
+
if (deg !== rotation) {
|
|
14087
|
+
onRotate?.(elementId, deg);
|
|
14088
|
+
}
|
|
14089
|
+
}
|
|
14090
|
+
});
|
|
14091
|
+
gesture.begin("rotate", elementId, {
|
|
14092
|
+
clientX: options.pointer.clientX,
|
|
14093
|
+
clientY: options.pointer.clientY,
|
|
14094
|
+
shiftKey: false
|
|
14095
|
+
});
|
|
14096
|
+
}
|
|
14534
14097
|
var appearance = { fill: "var(--color-primary)", borderColor: "#ffffff" };
|
|
14535
14098
|
var cornerSize = "var(--pptx-react-corner-default, 12px)";
|
|
14536
14099
|
var edgeLength = "var(--pptx-react-edge-length-default, 20px)";
|
|
@@ -14644,50 +14207,15 @@ function ResizeHandles({
|
|
|
14644
14207
|
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
14645
14208
|
onResizePointerDown(elementId, e, handle);
|
|
14646
14209
|
};
|
|
14647
|
-
const startRotate = (
|
|
14648
|
-
|
|
14649
|
-
|
|
14650
|
-
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
const base = nonRotationTransform ? ` ${nonRotationTransform}` : "";
|
|
14657
|
-
const startDeg = rotation ?? 0;
|
|
14658
|
-
const dragRotation = createRotationDrag(
|
|
14659
|
-
{ x: cx, y: cy },
|
|
14660
|
-
{ x: pointer.clientX, y: pointer.clientY },
|
|
14661
|
-
startDeg
|
|
14662
|
-
);
|
|
14663
|
-
let last = startDeg;
|
|
14664
|
-
if (pointerId !== void 0) {
|
|
14665
|
-
btn.setPointerCapture?.(pointerId);
|
|
14666
|
-
}
|
|
14667
|
-
const apply = (clientX, clientY, shift) => {
|
|
14668
|
-
let deg = dragRotation({ x: clientX, y: clientY });
|
|
14669
|
-
if (shift) {
|
|
14670
|
-
deg = Math.round(deg / 15) * 15;
|
|
14671
|
-
}
|
|
14672
|
-
deg = Math.round((deg % 360 + 360) % 360);
|
|
14673
|
-
last = deg;
|
|
14674
|
-
const transform = `rotate(${deg}deg)${base}`;
|
|
14675
|
-
wrapper.style.transform = transform;
|
|
14676
|
-
syncSelectionHandleOverlay(wrapper, elementId, { transform });
|
|
14677
|
-
};
|
|
14678
|
-
const onPointerMove = (ev) => apply(ev.clientX, ev.clientY, ev.shiftKey);
|
|
14679
|
-
const end = () => {
|
|
14680
|
-
window.removeEventListener("pointermove", onPointerMove);
|
|
14681
|
-
window.removeEventListener("pointerup", end);
|
|
14682
|
-
window.removeEventListener("pointercancel", end);
|
|
14683
|
-
if (last !== startDeg) {
|
|
14684
|
-
onRotate?.(elementId, last);
|
|
14685
|
-
}
|
|
14686
|
-
};
|
|
14687
|
-
window.addEventListener("pointermove", onPointerMove);
|
|
14688
|
-
window.addEventListener("pointerup", end);
|
|
14689
|
-
window.addEventListener("pointercancel", end);
|
|
14690
|
-
};
|
|
14210
|
+
const startRotate = (button, pointer) => startRotateKnobGesture({
|
|
14211
|
+
button,
|
|
14212
|
+
elementId,
|
|
14213
|
+
pointer,
|
|
14214
|
+
pointerId: pointer.pointerId,
|
|
14215
|
+
rotation: rotation ?? 0,
|
|
14216
|
+
...nonRotationTransform ? { nonRotationTransform } : {},
|
|
14217
|
+
...onRotate ? { onRotate } : {}
|
|
14218
|
+
});
|
|
14691
14219
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14692
14220
|
[...CORNER_HANDLES, ...EDGE_HANDLES].map(({ handle, posClass, cursor }) => {
|
|
14693
14221
|
const corner = handle.length === 2;
|
|
@@ -14758,7 +14286,7 @@ function ResizeHandles({
|
|
|
14758
14286
|
},
|
|
14759
14287
|
onPointerDown: (e) => {
|
|
14760
14288
|
e.stopPropagation();
|
|
14761
|
-
startRotate(e.currentTarget, e
|
|
14289
|
+
startRotate(e.currentTarget, e);
|
|
14762
14290
|
},
|
|
14763
14291
|
onMouseDown: (e) => {
|
|
14764
14292
|
e.stopPropagation();
|
|
@@ -19168,4 +18696,4 @@ function useResizablePanels() {
|
|
|
19168
18696
|
};
|
|
19169
18697
|
}
|
|
19170
18698
|
|
|
19171
|
-
export { ACTION_VERB_MAP, ChartFormatContext, ChartPartSelectionProvider, CollaborationCursorOverlay, CollaborationProvider, ElementRenderer, FragmentedTransitionLayer, InlineCollaborationContext, MIN_TOUCH_TARGET, MorphTransitionOverlay, PresentationTransitionOverlay, RemoteSelectionOverlay, RemoteUserCursors, Rendering3DFlagsContext, ResizeHandles, SlideBackgroundImageLayer, SlideLayer,
|
|
18699
|
+
export { ACTION_VERB_MAP, ChartFormatContext, ChartPartSelectionProvider, CollaborationCursorOverlay, CollaborationProvider, ElementRenderer, FragmentedTransitionLayer, InlineCollaborationContext, MIN_TOUCH_TARGET, MorphTransitionOverlay, PresentationTransitionOverlay, RemoteSelectionOverlay, RemoteUserCursors, Rendering3DFlagsContext, ResizeHandles, SlideBackgroundImageLayer, SlideLayer, StaticElementRenderer, ViewerOptionsContext, ViewerOptionsStoreContext, computeToolbarVisibility, createReviewCommentsHost, detectTargetType, imgSrc, isAudienceTab, parseAudienceNonce, parseEmailUrl, parseSlideFromUrl, playAnimationSound, renderStrokeView, renderToCanvas, resolveSmartArtDataPalette, safePrompt, scopeLayoutOptionsToActiveSlide, useAnimationPlayback, useAnnotationHandlers, useAudienceMode, useAutosave, useBroadcastFollower, useCanvasInteractions, useChartFormatContext, useChartPartSelection, useClipboardHandlers, useCollaboration, useCollaborationDocumentSync, useCollaborativeHistory, useCollaborativeState, useComments, useCompatibilityToastsState, useContentLifecycle, useController, useDerivedElementState, useDerivedSlideState, useDialogCustomShows, useEditorHistory, useEditorOperations, useElementManipulation, useElementOperations, useExportHandlers, useExportSaveAs, useFindReplace, useFollowMode, useFontInjection, useGroupAlignLayerHandlers, useIOHandlers, useInsertElements, useIsMobile, useKeyboardInsets, useKeyboardShortcutWiring, useKeyboardShortcuts, useLayoutSwitching, useLoadContent, useMergeShapesHandler, useModalDismissDrag, usePointerHandlers, usePresenceTracking, usePresentationAnnotations, usePresentationKeyboard, usePresentationMode, usePresentationSetup, usePresenterWindow, usePrintHandlers, usePropertyHandlers, useReadOnlyRecommendationState, useRecoveryDetection, useReducedMotion, useRehearsalTimings, useReportOnChange, useResizablePanels, useSectionOperations, useSerialize, useSheetDismissDrag, useSlideManagement, useSlideNavigation, useSwipeNavigation, useTableOperations, useThemeHandlers, useThemeSwitching, useToolbarVisibility, useTouchGestures, useViewPreferencesSync, useViewerBuildingBlocks, useViewerCoreState, useViewerDialogs, useViewerIntegration, useViewerOptions, useViewerOptionsContext, useViewerState, useViewerUIState, useVirtualizedSlides, useYjsDocumentSync, useYjsProvider, useZoomNavigation, useZoomViewport, withDisplayName };
|