pptx-react-viewer 4.49.0 → 4.51.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 +125 -0
- package/README.md +38 -4
- package/dist/{AiChatPanel-S4WNQCY4.js → AiChatPanel-EV22O7UO.js} +19 -20
- package/dist/AiChatPanel-EV22O7UO.js.br +0 -0
- package/dist/AiChatPanel-EV22O7UO.js.gz +0 -0
- package/dist/{AiChatPanel-NKTBHT5B.mjs → AiChatPanel-R323KNGN.mjs} +1 -2
- package/dist/AiChatPanel-R323KNGN.mjs.br +0 -0
- package/dist/AiChatPanel-R323KNGN.mjs.gz +0 -0
- package/dist/{chunk-Z62JFXMZ.mjs → chunk-ACFR4LFQ.mjs} +577 -1028
- package/dist/chunk-ACFR4LFQ.mjs.br +0 -0
- package/dist/chunk-ACFR4LFQ.mjs.gz +0 -0
- package/dist/chunk-DDJ634MV.js.br +0 -0
- package/dist/chunk-DDJ634MV.js.gz +0 -0
- package/dist/{chunk-YKLL2Z33.mjs → chunk-ETJ752B5.mjs} +597 -1871
- package/dist/chunk-ETJ752B5.mjs.br +0 -0
- package/dist/chunk-ETJ752B5.mjs.gz +0 -0
- package/dist/chunk-QIUK53JR.mjs.br +0 -0
- package/dist/chunk-QIUK53JR.mjs.gz +0 -0
- package/dist/{chunk-ME5QRTVS.js → chunk-V3XADJ2O.js} +763 -1214
- package/dist/chunk-V3XADJ2O.js.br +0 -0
- package/dist/chunk-V3XADJ2O.js.gz +0 -0
- package/dist/{chunk-2ZXXHNNR.js → chunk-VI5DQRQZ.js} +2052 -3325
- package/dist/chunk-VI5DQRQZ.js.br +0 -0
- package/dist/chunk-VI5DQRQZ.js.gz +0 -0
- package/dist/{chunk-JAI42EXQ.js → chunk-Z22RD3E2.js} +41 -12
- package/dist/chunk-Z22RD3E2.js.br +0 -0
- package/dist/chunk-Z22RD3E2.js.gz +0 -0
- package/dist/{chunk-PFV626ED.mjs → chunk-ZCGYPCZM.mjs} +37 -8
- package/dist/chunk-ZCGYPCZM.mjs.br +0 -0
- package/dist/chunk-ZCGYPCZM.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 +56 -27
- package/dist/index.js +28 -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 +58 -24
- package/dist/viewer/index.js +23 -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-2ZXXHNNR.js.br +0 -0
- package/dist/chunk-2ZXXHNNR.js.gz +0 -0
- package/dist/chunk-3VVZGHHY.mjs.br +0 -0
- package/dist/chunk-3VVZGHHY.mjs.gz +0 -0
- package/dist/chunk-JAI42EXQ.js.br +0 -0
- package/dist/chunk-JAI42EXQ.js.gz +0 -0
- package/dist/chunk-ME5QRTVS.js.br +0 -0
- package/dist/chunk-ME5QRTVS.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/chunk-YKLL2Z33.mjs.br +0 -0
- package/dist/chunk-YKLL2Z33.mjs.gz +0 -0
- package/dist/chunk-Z62JFXMZ.mjs.br +0 -0
- package/dist/chunk-Z62JFXMZ.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,11 +1,10 @@
|
|
|
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, html2canvasCaptureScope, 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, 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, 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, useTranslation, comparePresentation, UNGROUPED_SECTION_ID, DEFAULT_SECTION_GROUP_ID, stopAllPersistentAudio, buildSaveSlides, MAX_ZOOM_SCALE, MIN_ZOOM_SCALE, getImageEffectsOpacity, getImageEffectsFilter, getImageRenderStyle, cn, isEditableTextElement, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageSurfaceStyle, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, getElementLabel, normalizeHexColor, makeCloneId, DEFAULT_TEXT_FONT_SIZE, buildPdfFromTiledImageData, GRID_SIZE, copyFormatFromElement, hasCopyableFormat, isImageTiled, getDuotoneColors, DEFAULT_STROKE_COLOR, DEFAULT_FILL_COLOR, buildCssGradientFromShapeStyle, getCropShapeClipPath, getElementTransform, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getImageSurfaceMaskStyle, getTextWarpStyle, getTextCompensationTransform, renderTextSegments, buildReactChartViewModel, renderChartElement, buildInkGroupStrokes, getInkReplayStyles, INK_REPLAY_KEYFRAMES, buildContentPartStrokes, getContentPartReplayStyles, buildTextBody3DSceneStyle, rerouteConnectorsForMovedElements, applyReroutedConnectors, updateCellTextStyleInRawXml, updateCellTextInRawXml, splitCell, updateMergeAttrsInRawXml, mergeCells, buildNotesPdf, canvasToJpegData, applyFormatToElement, isPpactionUrl, parsePpactionUrl, getImageTilingStyle, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, getAriaRoleDescription as getAriaRoleDescription$1, getAriaLabel as getAriaLabel$1, getAriaRole, DEFAULT_FONT_FAMILY, ACTION_BUTTON_PRESETS, isUrlSafe, safeOpenUrl as safeOpenUrl$1, substituteFieldText, HYPERLINK_COLOR } from './chunk-ZCGYPCZM.mjs';
|
|
2
|
+
import { defineThreeViewElement, MIN_TOUCH_TARGET_PX, computeVirtualRange, DEFAULT_VIRTUAL_OVERSCAN, createCollaborationSessionController, registerCollaborationTeardown, createPresenceProjector, BROADCAST_THROTTLE_MS, sanitizeColor, createEditorHistoryController, createWheelStepBuffer, createViewerZoomStore, clampZoomScale, mapEditingWheel, createActiveAnimationGroup, cancelBuildReveal, clearPlaybackTimers, PresentationAnimationController, resolveMediaTimeNodeElementIds, resolveMediaBookmarkTimesMs, advanceMainSequence, playGroup, PRESENTATION_HASH, PRESENTATION_NONCE_KEY, PRESENTATION_CHANNEL_NAME, swapPresentationWindows, PRESENTATION_MESSAGE_ORIGIN, clearAudienceContent, buildPresentationAudienceUrl, resolveAudienceScreenPlacement, placeAudienceWindow, storeAudienceContent, isPresentationSessionMessage, endAudienceDisplay, createPresentationKeyBuffer, acceptsPresentationInput, resolveAutoAdvanceDelayMs, resolveShowBackward, resolveShowForward, beginZoomExcursion, buildZoomTransitionOverride, createPresenterShowGuard, firstShowSlideIndex, attachPresentationVisibilityPause, presentationEntrySlideIndex, buildMorphTransitionPlan, morphOptionToMode, buildMorphAnimationRules, findInSlides, applyFindReplacements, visibleTemplateElements, createCollaborationLivePatcher, reportInlineTextDraft, initialInspectorOpen, createPresentationLoadResources, collectMediaElements, resolveMediaElementSource, collectImagePaths, applyImagePathPatches, resolveTableCellImageUrls, resolveTableStyleImageUrls, resolveTextFillBlipUrls, seedRecentColors, resolveAuthoredCustomShowId, GlyphOutlineFontCache, buildInitialGuides, readOnlyRecommendation, compatibilityWarningToasts, resolveInitialSlideIndex, resolveAutosaveIntervalMs, createAutosaveController, saveAutosaveSnapshot, updateMasterViewElement, updateElement, masterViewElements, replaceMasterViewElements, addSection, renameSection, deleteSection, moveSectionUp, moveSectionDown, moveSlidesToSection, canMergeShapes, canInteractWithElement, prepareHtml2CanvasClone, html2canvasCaptureScope, slideProgressPercent, slideStatusLabel, EXPORT_ASSEMBLING_PERCENT, EXPORT_DONE_PERCENT, isExportAbortError, DEFAULT_VIEWER_OPTIONS, resolveImageResolutionScale, applyAcceptSlide, applyAcceptAllSlides, collectUsedFonts, describeFontEmbedding, isMobileViewport, resolveAuthoredSlideRange, mayLeaveSlideShow, buildDeckSaveOptions, resolveSlideSizeSelection, saveDeckWithPassword, createAutosaveRecoveryController, discardAutosaveRecovery, probeAutosaveRecovery, shouldLoopContinuously, applyRehearsalTimings, rasterResultToPngBlob, downloadBlob, elementPictureFilename, canEditElementPoints, selectTrustedEmbeddedFonts, resolveFontWeight, resolveFontItalic, collectReferencedFontFamilies, resolveGoogleWebfontHref, syncGoogleWebfontStylesheet, selectGoogleWebfontFamilies, fetchGoogleWebfontOutlineBytes, dispatchEditorKey, isFeatureEnabled, parentSelection, textFontSizePtToPx, stepFontSizePt, textFontSizePxToPt, cycleSelectableElement, createCustomizationController, prepareElementForInsertion, slideSpaceElement, autosaveStatusKind, createViewerOptionsStore, observeYDocSlides, LOCAL_SYNC_ORIGIN, readSlidesFromYDoc, shouldRoomSlidesReplaceLoad, reconcileSlidesInYDoc, shouldAutoFollowBroadcaster, detectTouchDevice, detectOrientation, deriveViewportBreakpoints, createTouchGestureRecognizer, isKeyboardOpen, scopeLayoutOptionsToSlide, INITIAL_READ_ONLY_SESSION, readOnlySessionActions, applyReadOnlySessionEvent, readOnlyBannerVisible, readOnlyLocked, viewerPreferencesFromViewProperties, DEFAULT_VIEWER_PREFERENCES, viewPropertiesPatchFromPreferences, resolveCollaborationConfig, openPptxFile, readBackstageRecentFile, resolveCollaborationShellEditability, resolveCollaborationShellState, getResizeHandleHitAreaStyle, resolveElementInteractivity, getBackgroundAnimationState, getShapeEffectLayerPlacement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, isMediaFullscreenActive, shouldRenderHitTarget, elementHitTargetStyle, getShapeEffectAnimationLayerStyle, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, resolvePalette as resolvePalette$1, mediaTransportVisible, oleActionsVisible, getGroupChildParentFill, deviceStrokeStageStyle, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, getSlideTransitionAnimations, getFragmentedTransitionDescriptor, SLIDE_TRANSITION_KEYFRAMES, isActionHidden, buildInlineTextCommitPatch, resolveInlineEditAutoFitHeight, resolveInlineEditNormAutofitShrink, setPendingCaretPoint, resolveGroupDoubleClickTarget, filterInteractableIds, beginShapeAdjustment, buildElementClipboardPayload, contextMenuInspectorAnchor, savedPresentationFileName, deliverSavedPresentation, exportDeckJson, mapCustomizedEditorKey, isEditorTextInputTarget, groupElements, generateElementId, ungroupElements, alignElements, distributeElements, newTableElement, createDefaultChartElement, readViewportMetrics, computeKeyboardInset, planMergeShapes, applyMergeShapesPlan, mapPresentationKey, lastShowSlideIndex, mapPresentationWheel, openPendingPrintWindow, computeColorFilter, filterHiddenSlideIndices, computeSlideIndices, buildPrintDocument, finishPrintWindow, buildPrintHtmlDocument, buildOutlineHtml, buildSlidesHtml, buildNotesHtml, buildHandoutsHtml, createBlankSlide, insertSlidePaste, applySlidePasteTemplates, makeSlideId, buildSlideTemplateSlide, templateSchemeFromTheme, needsOwnedSession, openOwnedCollaboration, resolveViewportFitOptions, editorViewportFitFor, calculateViewportFit, observeViewportClientSize, scheduleAutoAdvanceChain, computeEntranceAnimationDelay, createPresentationSessionId, resolveTransitionDurationMs, resolveTransitionSoundAction, runPresentationAction, safeOpenUrl, buildRunProgramNotice, toggleStageElementMedia, resolveOleVerbTarget, downloadDataUrl, openUrlInNewTab, createPresenterTimer, createInitialPresentationSnapshot, mergePresentationSnapshot, resetPresenterTimer, presenterElapsed, stepPresenterZoom, togglePresenterTimer, addCommentToList, removeCommentFromList, editCommentInList, toggleCommentResolvedInList, slideSpaceMembers, remapTextToSegments, getInlineEditorSelectionResult, buildInlineListStylePatch, applyActiveInlineListFormatting, applyListStyleUpdate, setPendingSelectionRestore, applyTextStyleUpdate, toggleSelectionBullets, transformInlineListCase, applyCaseTransformToSegments, transformTextCase, createGestureController, resolveExportCaptureDecision, recordProgressPercent, computeGridSpacingPx as computeGridSpacingPx$1, resolveShowSlideIndexes, groupSlidesBySection, masterViewPseudoSlide, overlayMasterViewInlineSnapshot, overlayInlineTextSnapshot, rasterizeElement, cloneElementForPaste, applyPasteSpecialFormat, buildRasterPictureElement, cloneElementUpdates, assertElementUpdateTarget, prepareElementUpdateBatch, createWriteBackScheduler, writeBackReport, createSyncGate, observeExternalCollaborationReadiness, resolveHistoryDepth, createBackstagePresentation, buildFieldSubstitutionContext, getImageColorWashStyle, attachRotateHandlePlacement, getSelectionControlArtworkStyle, getSelectionOutlineColor, paintedStrokeWidth, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, paintedElementSize, MEDIA_FULLSCREEN_OVERLAY_STYLE, elementContainerHeightStyle, getAnimationOpacity, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, getEffectStyleSource, getBevelLightingSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, strokeOutlineViewBox, buildSummaryZoomView, readEditableText, placeCaretAt, takePendingCaretPoint, getPendingSelectionRestore, restoreSegmentSelection, mapInlineTextFormatKey, mapInlineEditorChord, subscribeBarFacePicturePixelSamples, getBarFacePicturePixelSampleVersion, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, chartFormatTargetFromEvent, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, getAriaRoleDescription, getAriaLabel, elementIdSelector, TOOLBAR_TABS, resolveGroupPressTarget, scrollInspectorSectionIntoView, computeScrollDelta, replyToCommentInList, removeTableElementColumn, insertTableElementColumn, removeTableElementRow, insertTableElementRow, withCellStyle, setCellText, pickSupportedMimeType, WEBM_MIME_CANDIDATES, fpsToFrameIntervalMs, segmentFrameCount, stopCaptureStream, GIF_POST_CAPTURE_MAX_SIDE, encodeGif, rasterizeElementTiles, placeTileOnPage, PDF_SLIDES_PAGE_WIDTH_PT, PDF_SLIDES_PAGE_HEIGHT_PT, createSnapshotTextPositions, resolvePresentationAction, getImageSvgFilters, getCachedNativeImageSize, probeNativeImageSize, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, svgLineCap, screenStrokeWidth, connectorWrapperTransform, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, modelDataToBlobUrl, resolveZoomNavigationTarget, inlineListBodyText, createInlineListSeed, readListActivationSelection, createInlineListModelObserver, attachCollaborationInlineEditor, bindInlineListParagraph, bindInlineListRun, attachInlineListController, restoreInlineListBodySelection, isBulletMarkerSegment, resolveChartThreeViewSpec, applyChart3DDrag, applyChart3DSelect, canDrillDown, findChartPartTarget, withChartTitle, resolveSmartArtThreeViewSpec, measureSvgViewportRect, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, hasGlyphEnvelope, buildGlyphEnvelopeBlock, getWarpPath, isWedgeCalloutPresetShape, getAriaRole as getAriaRole$1, isElementActionable, buildSmartArtPresetData, classifyMediaType, getDraggedShapeAdjustments, computeMarqueeHitIds, mergeAdditiveSelection, rasterizeElementTiledToCanvas, borrowExternalCollaborationAwareness, observeExternalCollaborationSession, publishLiveGeometry, clampGifDimensions, rasterResultToPngDataUrl, shouldConfirmExternalHyperlink, advanceChartMarkDrag, advanceChartValueDrag, resolveChartKind, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, findSmartArtNodeText, commitSmartArtNodeFill, commitSmartArtNodeText, groupIntoParagraphs as groupIntoParagraphs$1, createGlyphOutlineLookup, applyMotionPathPreset, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, computeSmartArtElementLayout, flattenNodes, computeInlineEditorRect, smartArtNodeAtPoint, SMARTART_DEFAULT_PALETTE, computeDrawingViewBox, projectDrawingShapes, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, centeredSvgTextLines, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, bringForward, sendBackward, bringToFront, sendToBack } from 'ooxml-ui/pptx';
|
|
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
|
-
import { PptxHandler, EncryptedFileError, hasShapeProperties, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, guidePxToEmu, hasTextProperties, isInkElement, duplicateSlide, buildThemeColorMap, reResolveSlideColors, reResolveElementColors, isImageLikeElement, SvgExporter,
|
|
6
|
+
import { PptxHandler, EncryptedFileError, hasShapeProperties, applyThemeToData, THEME_PRESETS, themeColorSchemesEqual, guidePxToEmu, hasTextProperties, isInkElement, duplicateSlide, buildThemeColorMap, reResolveSlideColors, reResolveElementColors, reResolveSlideFonts, reResolveElementFonts, isImageLikeElement, SvgExporter, getSubstituteFontFamily, elementActionToPptxAction, setSmartArtNodeStyle, updateSmartArtNodeText } from 'ooxml-core/pptx';
|
|
7
7
|
import { translationsEn } from 'ooxml-ui/pptx/i18n';
|
|
8
|
-
import { useTranslation } from 'react-i18next';
|
|
9
8
|
import { flushSync } from 'react-dom';
|
|
10
9
|
import { LuRotateCw } from 'react-icons/lu';
|
|
11
10
|
|
|
@@ -75,240 +74,59 @@ function useVirtualizedSlides({
|
|
|
75
74
|
scrollToIndex
|
|
76
75
|
};
|
|
77
76
|
}
|
|
77
|
+
function useController(controller) {
|
|
78
|
+
return useSyncExternalStore(controller.subscribe, controller.getSnapshot, controller.getSnapshot);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/viewer/hooks/collaboration/collaboration-modules.ts
|
|
82
|
+
var collabModules = {
|
|
83
|
+
loadYjs: () => import('yjs'),
|
|
84
|
+
loadWebsocket: () => import('./y-websocket-46M6UFI7.mjs'),
|
|
85
|
+
loadWebrtc: () => import('./y-webrtc-HRGGVQZH.mjs')
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// src/viewer/hooks/collaboration/useYjsProvider.ts
|
|
78
89
|
function useYjsProvider({ config: inputConfig }) {
|
|
79
90
|
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]
|
|
91
|
+
const [controller] = useState(
|
|
92
|
+
() => createCollaborationSessionController({ modules: collabModules, registerTeardown: false })
|
|
121
93
|
);
|
|
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;
|
|
94
|
+
const state = useController(controller);
|
|
95
|
+
const signalingKey = config?.signaling?.join("\n");
|
|
96
|
+
useEffect(() => {
|
|
186
97
|
if (!config) {
|
|
98
|
+
controller.stop();
|
|
187
99
|
return;
|
|
188
100
|
}
|
|
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
|
-
}
|
|
101
|
+
void controller.start(config);
|
|
102
|
+
const disposeTeardown = registerCollaborationTeardown({
|
|
103
|
+
leave: () => controller.stop(),
|
|
104
|
+
rejoin: () => void controller.retry()
|
|
105
|
+
});
|
|
106
|
+
return () => {
|
|
107
|
+
disposeTeardown();
|
|
108
|
+
controller.stop();
|
|
109
|
+
};
|
|
288
110
|
}, [
|
|
111
|
+
controller,
|
|
289
112
|
config?.roomId,
|
|
290
113
|
config?.serverUrl,
|
|
291
114
|
config?.authToken,
|
|
292
115
|
config?.transport,
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
teardown
|
|
116
|
+
signalingKey,
|
|
117
|
+
Boolean(config)
|
|
296
118
|
]);
|
|
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 };
|
|
119
|
+
const session = state.active ? controller.getSession() : null;
|
|
120
|
+
return {
|
|
121
|
+
status: state.status,
|
|
122
|
+
awareness: session?.awareness ?? null,
|
|
123
|
+
doc: session?.doc ?? null,
|
|
124
|
+
clientId: state.clientId,
|
|
125
|
+
synced: state.synced,
|
|
126
|
+
retry: () => {
|
|
127
|
+
void controller.retry();
|
|
128
|
+
}
|
|
129
|
+
};
|
|
312
130
|
}
|
|
313
131
|
function usePresenceTracking({
|
|
314
132
|
awareness,
|
|
@@ -757,15 +575,11 @@ function serializeHistoryDocument(snapshot) {
|
|
|
757
575
|
)
|
|
758
576
|
});
|
|
759
577
|
}
|
|
760
|
-
function recordExplicitSlideUpdate(
|
|
578
|
+
function recordExplicitSlideUpdate(history, previous, before, label) {
|
|
761
579
|
if (previous && serializeHistoryDocument(previous) !== serializeHistoryDocument(before)) {
|
|
762
|
-
|
|
580
|
+
history.record(cloneHistorySnapshot(previous), previous.actionLabel);
|
|
763
581
|
}
|
|
764
|
-
|
|
765
|
-
while (past.length > Math.max(1, maxDepth)) {
|
|
766
|
-
past.shift();
|
|
767
|
-
}
|
|
768
|
-
future.length = 0;
|
|
582
|
+
history.record({ ...cloneHistorySnapshot(before), actionLabel: label }, label);
|
|
769
583
|
}
|
|
770
584
|
var POLL_INTERVAL_MS = 16;
|
|
771
585
|
function usePointerReleaseWakeup(hasActivePointerInteraction) {
|
|
@@ -801,7 +615,6 @@ function usePointerReleaseWakeup(hasActivePointerInteraction) {
|
|
|
801
615
|
}
|
|
802
616
|
|
|
803
617
|
// src/viewer/hooks/useEditorHistory.ts
|
|
804
|
-
var DEFAULT_MAX_HISTORY_ENTRIES = 120;
|
|
805
618
|
function useEditorHistory(input) {
|
|
806
619
|
const {
|
|
807
620
|
slides,
|
|
@@ -810,7 +623,7 @@ function useEditorHistory(input) {
|
|
|
810
623
|
templateElementsBySlideId,
|
|
811
624
|
loading,
|
|
812
625
|
error,
|
|
813
|
-
maxHistoryEntries
|
|
626
|
+
maxHistoryEntries,
|
|
814
627
|
hasActivePointerInteraction,
|
|
815
628
|
pointerCommitNonce,
|
|
816
629
|
onDirty,
|
|
@@ -821,30 +634,23 @@ function useEditorHistory(input) {
|
|
|
821
634
|
setSelectedElementId,
|
|
822
635
|
setSelectedElementIds
|
|
823
636
|
} = input;
|
|
824
|
-
const
|
|
825
|
-
const
|
|
637
|
+
const [history] = useState(() => createEditorHistoryController());
|
|
638
|
+
const historyState = useController(history);
|
|
826
639
|
const lastHistorySnapshotRef = useRef(null);
|
|
827
640
|
const lastHistorySerializedRef = useRef("");
|
|
828
641
|
const lastCheapHashRef = useRef("");
|
|
829
642
|
const isApplyingHistoryRef = useRef(false);
|
|
830
643
|
const trackingHeldRef = useRef(false);
|
|
831
644
|
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
645
|
const [editCommitNonce, setEditCommitNonce] = useState(0);
|
|
837
646
|
const { pointerReleaseNonce, deferUntilPointerReleased } = usePointerReleaseWakeup(
|
|
838
647
|
hasActivePointerInteraction
|
|
839
648
|
);
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
const futureTop = historyFutureRef.current[historyFutureRef.current.length - 1];
|
|
846
|
-
setRedoLabel(futureTop?.actionLabel);
|
|
847
|
-
}, []);
|
|
649
|
+
useEffect(() => {
|
|
650
|
+
if (maxHistoryEntries !== void 0) {
|
|
651
|
+
history.setMaxDepth(maxHistoryEntries);
|
|
652
|
+
}
|
|
653
|
+
}, [history, maxHistoryEntries]);
|
|
848
654
|
const buildHistorySnapshot = useCallback(
|
|
849
655
|
(actionLabel) => {
|
|
850
656
|
return {
|
|
@@ -899,53 +705,40 @@ function useEditorHistory(input) {
|
|
|
899
705
|
onDirtyRef.current?.();
|
|
900
706
|
}, []);
|
|
901
707
|
const handleUndo = useCallback(() => {
|
|
902
|
-
|
|
903
|
-
|
|
708
|
+
if (!history.getSnapshot().canUndo) {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
const result = history.undo(buildHistorySnapshot());
|
|
712
|
+
if (!result) {
|
|
904
713
|
return;
|
|
905
714
|
}
|
|
906
|
-
const currentSnapshot = buildHistorySnapshot(previousSnapshot.actionLabel);
|
|
907
|
-
historyFutureRef.current.push(currentSnapshot);
|
|
908
715
|
isApplyingHistoryRef.current = true;
|
|
909
|
-
const nextSnapshot = cloneHistorySnapshot(
|
|
716
|
+
const nextSnapshot = cloneHistorySnapshot(result.snapshot);
|
|
910
717
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(nextSnapshot);
|
|
911
718
|
lastHistorySerializedRef.current = serializeHistoryDocument(nextSnapshot);
|
|
912
719
|
applyHistorySnapshot(nextSnapshot);
|
|
913
|
-
updateHistoryAvailability();
|
|
914
720
|
unlockHistoryTracking();
|
|
915
721
|
markDirty();
|
|
916
|
-
}, [
|
|
917
|
-
applyHistorySnapshot,
|
|
918
|
-
buildHistorySnapshot,
|
|
919
|
-
markDirty,
|
|
920
|
-
unlockHistoryTracking,
|
|
921
|
-
updateHistoryAvailability
|
|
922
|
-
]);
|
|
722
|
+
}, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
|
|
923
723
|
const handleRedo = useCallback(() => {
|
|
924
|
-
|
|
925
|
-
|
|
724
|
+
if (!history.getSnapshot().canRedo) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
const result = history.redo(buildHistorySnapshot());
|
|
728
|
+
if (!result) {
|
|
926
729
|
return;
|
|
927
730
|
}
|
|
928
|
-
const currentSnapshot = buildHistorySnapshot(nextSnapshot.actionLabel);
|
|
929
|
-
historyPastRef.current.push(currentSnapshot);
|
|
930
731
|
isApplyingHistoryRef.current = true;
|
|
931
|
-
const targetSnapshot = cloneHistorySnapshot(
|
|
732
|
+
const targetSnapshot = cloneHistorySnapshot(result.snapshot);
|
|
932
733
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(targetSnapshot);
|
|
933
734
|
lastHistorySerializedRef.current = serializeHistoryDocument(targetSnapshot);
|
|
934
735
|
applyHistorySnapshot(targetSnapshot);
|
|
935
|
-
updateHistoryAvailability();
|
|
936
736
|
unlockHistoryTracking();
|
|
937
737
|
markDirty();
|
|
938
|
-
}, [
|
|
939
|
-
applyHistorySnapshot,
|
|
940
|
-
buildHistorySnapshot,
|
|
941
|
-
markDirty,
|
|
942
|
-
unlockHistoryTracking,
|
|
943
|
-
updateHistoryAvailability
|
|
944
|
-
]);
|
|
738
|
+
}, [applyHistorySnapshot, buildHistorySnapshot, history, markDirty, unlockHistoryTracking]);
|
|
945
739
|
const resetHistory = useCallback(
|
|
946
740
|
(initialSnapshot) => {
|
|
947
|
-
|
|
948
|
-
historyFutureRef.current = [];
|
|
741
|
+
history.clear();
|
|
949
742
|
if (initialSnapshot) {
|
|
950
743
|
const clonedInitial = cloneHistorySnapshot(initialSnapshot);
|
|
951
744
|
lastHistorySnapshotRef.current = clonedInitial;
|
|
@@ -954,9 +747,8 @@ function useEditorHistory(input) {
|
|
|
954
747
|
lastHistorySnapshotRef.current = null;
|
|
955
748
|
lastHistorySerializedRef.current = "";
|
|
956
749
|
}
|
|
957
|
-
updateHistoryAvailability();
|
|
958
750
|
},
|
|
959
|
-
[
|
|
751
|
+
[history]
|
|
960
752
|
);
|
|
961
753
|
useEffect(() => {
|
|
962
754
|
return () => {
|
|
@@ -999,19 +791,13 @@ function useEditorHistory(input) {
|
|
|
999
791
|
lastHistorySnapshotRef.current = snapshot;
|
|
1000
792
|
lastHistorySerializedRef.current = serialized;
|
|
1001
793
|
lastCheapHashRef.current = cheapHash;
|
|
1002
|
-
updateHistoryAvailability();
|
|
1003
794
|
return;
|
|
1004
795
|
}
|
|
1005
796
|
onDirtyRef.current?.();
|
|
1006
|
-
|
|
1007
|
-
while (historyPastRef.current.length > Math.max(1, maxHistoryEntries)) {
|
|
1008
|
-
historyPastRef.current.shift();
|
|
1009
|
-
}
|
|
1010
|
-
historyFutureRef.current = [];
|
|
797
|
+
history.record(previousSnapshot, previousSnapshot.actionLabel);
|
|
1011
798
|
lastHistorySnapshotRef.current = snapshot;
|
|
1012
799
|
lastHistorySerializedRef.current = serialized;
|
|
1013
800
|
lastCheapHashRef.current = cheapHash;
|
|
1014
|
-
updateHistoryAvailability();
|
|
1015
801
|
}, [
|
|
1016
802
|
activeSlideIndex,
|
|
1017
803
|
buildHistorySnapshot,
|
|
@@ -1021,30 +807,21 @@ function useEditorHistory(input) {
|
|
|
1021
807
|
editCommitNonce,
|
|
1022
808
|
error,
|
|
1023
809
|
hasActivePointerInteraction,
|
|
810
|
+
history,
|
|
1024
811
|
loading,
|
|
1025
|
-
maxHistoryEntries,
|
|
1026
812
|
pointerCommitNonce,
|
|
1027
813
|
pointerReleaseNonce,
|
|
1028
|
-
slides
|
|
1029
|
-
updateHistoryAvailability
|
|
814
|
+
slides
|
|
1030
815
|
]);
|
|
1031
816
|
const commitSlides = (nextSlides, label, beforeSlides = slides) => {
|
|
1032
817
|
const before = { ...buildHistorySnapshot(), slides: beforeSlides.map(cloneSlide) };
|
|
1033
818
|
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
|
-
);
|
|
819
|
+
recordExplicitSlideUpdate(history, lastHistorySnapshotRef.current, before, label);
|
|
1042
820
|
lastHistorySnapshotRef.current = cloneHistorySnapshot(after);
|
|
1043
821
|
lastHistorySerializedRef.current = serializeHistoryDocument(after);
|
|
1044
822
|
isApplyingHistoryRef.current = false;
|
|
1045
823
|
setSlides(nextSlides);
|
|
1046
824
|
onDirtyRef.current?.();
|
|
1047
|
-
updateHistoryAvailability();
|
|
1048
825
|
};
|
|
1049
826
|
const holdTracking = useCallback((held) => {
|
|
1050
827
|
trackingHeldRef.current = held;
|
|
@@ -1052,10 +829,10 @@ function useEditorHistory(input) {
|
|
|
1052
829
|
return {
|
|
1053
830
|
commitSlides,
|
|
1054
831
|
holdTracking,
|
|
1055
|
-
canUndo,
|
|
1056
|
-
canRedo,
|
|
1057
|
-
undoLabel,
|
|
1058
|
-
redoLabel,
|
|
832
|
+
canUndo: historyState.canUndo,
|
|
833
|
+
canRedo: historyState.canRedo,
|
|
834
|
+
undoLabel: historyState.undoLabel,
|
|
835
|
+
redoLabel: historyState.redoLabel,
|
|
1059
836
|
handleUndo,
|
|
1060
837
|
handleRedo,
|
|
1061
838
|
resetHistory,
|
|
@@ -2198,9 +1975,6 @@ function executeSlideTransition(nextSlideIndex, deps) {
|
|
|
2198
1975
|
}
|
|
2199
1976
|
|
|
2200
1977
|
// 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
1978
|
function useSlideNavigation(input) {
|
|
2205
1979
|
const {
|
|
2206
1980
|
slides,
|
|
@@ -2250,50 +2024,71 @@ function useSlideNavigation(input) {
|
|
|
2250
2024
|
);
|
|
2251
2025
|
const movePresentationSlide = useCallback(
|
|
2252
2026
|
(direction, trigger = "explicit") => {
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
}
|
|
2256
|
-
|
|
2027
|
+
const showOrder = visibleSlideIndexes.length > 0 ? visibleSlideIndexes : slides.map((_slide, slideIndex) => slideIndex);
|
|
2028
|
+
const current = presentationSlideIndex;
|
|
2029
|
+
const transitionTo = (index, options = {}) => executeSlideTransition(index, {
|
|
2030
|
+
slides,
|
|
2031
|
+
currentSlideIndex: current,
|
|
2032
|
+
onPlayActionSound,
|
|
2033
|
+
onStopActionSound,
|
|
2034
|
+
setPresentationSlideVisible,
|
|
2035
|
+
clearPresentationTimers,
|
|
2036
|
+
setPresentationSlideIndex,
|
|
2037
|
+
onSetActiveSlideIndex,
|
|
2038
|
+
seedSlideAnimations,
|
|
2039
|
+
startSlideAnimations,
|
|
2040
|
+
scheduleAutoAdvanceForSlide: rehearsing ? void 0 : scheduleAutoAdvanceForSlide,
|
|
2041
|
+
presentationTimersRef,
|
|
2042
|
+
setTransitionOverlay,
|
|
2043
|
+
// PowerPoint plays a slide's transition only when advancing into it,
|
|
2044
|
+
// and replays the LEAVING slide's transition in reverse when stepping
|
|
2045
|
+
// back (a morph glides its shapes back to where they came from).
|
|
2046
|
+
playTransition: true,
|
|
2047
|
+
...options
|
|
2048
|
+
});
|
|
2049
|
+
if (direction === -1) {
|
|
2050
|
+
const step2 = resolveShowBackward({
|
|
2051
|
+
currentIndex: current,
|
|
2052
|
+
showOrder,
|
|
2053
|
+
endOfShow: false,
|
|
2054
|
+
seededCompleted: false
|
|
2055
|
+
});
|
|
2056
|
+
if (step2.kind === "go") {
|
|
2057
|
+
transitionTo(step2.index, { reverse: true, seedCompleted: true });
|
|
2058
|
+
}
|
|
2257
2059
|
return;
|
|
2258
2060
|
}
|
|
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,
|
|
2061
|
+
const step = resolveShowForward({
|
|
2062
|
+
currentIndex: current,
|
|
2063
|
+
currentSlide: slides[current],
|
|
2064
|
+
showOrder,
|
|
2065
|
+
endOfShow: false,
|
|
2066
|
+
fromClick: trigger === "click",
|
|
2067
|
+
loop: Boolean(loopContinuously) && !rehearsing,
|
|
2068
|
+
endWithBlackSlide: true,
|
|
2069
|
+
zoomExcursion: zoomExcursionRef.current,
|
|
2070
|
+
advanceBuild: playNextAnimationGroup
|
|
2071
|
+
});
|
|
2072
|
+
if (step.kind === "go") {
|
|
2073
|
+
if (step.zoomReturn) {
|
|
2074
|
+
zoomExcursionRef.current = step.zoomReturn.excursion;
|
|
2075
|
+
transitionTo(step.index, {
|
|
2279
2076
|
scheduleAutoAdvanceForSlide,
|
|
2280
|
-
|
|
2281
|
-
setTransitionOverlay,
|
|
2282
|
-
playTransition: true,
|
|
2283
|
-
transitionOverride: buildZoomTransitionOverride(
|
|
2284
|
-
consumedExcursion?.transitionDurationMs
|
|
2285
|
-
)
|
|
2077
|
+
transitionOverride: step.zoomReturn.transitionOverride
|
|
2286
2078
|
});
|
|
2287
2079
|
return;
|
|
2288
2080
|
}
|
|
2081
|
+
if (rehearsing) {
|
|
2082
|
+
recordCurrentSlideTime(current);
|
|
2083
|
+
}
|
|
2084
|
+
transitionTo(step.index);
|
|
2085
|
+
return;
|
|
2289
2086
|
}
|
|
2290
|
-
|
|
2291
|
-
if (availableSlideIndexes.length === 0) {
|
|
2087
|
+
if (step.kind !== "end-screen" && step.kind !== "exit") {
|
|
2292
2088
|
return;
|
|
2293
2089
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
recordCurrentSlideTime(presentationSlideIndex);
|
|
2090
|
+
if (rehearsing) {
|
|
2091
|
+
recordCurrentSlideTime(current);
|
|
2297
2092
|
try {
|
|
2298
2093
|
if (document.fullscreenElement) {
|
|
2299
2094
|
void document.exitFullscreen().catch(() => {
|
|
@@ -2305,41 +2100,7 @@ function useSlideNavigation(input) {
|
|
|
2305
2100
|
setShowRehearsalSummary(true);
|
|
2306
2101
|
return;
|
|
2307
2102
|
}
|
|
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
|
-
});
|
|
2103
|
+
onAdvancePastLastSlide?.();
|
|
2343
2104
|
},
|
|
2344
2105
|
[
|
|
2345
2106
|
clearPresentationTimers,
|
|
@@ -4199,6 +3960,7 @@ function useViewerCoreState(_input) {
|
|
|
4199
3960
|
const marqueeStateRef = useRef(null);
|
|
4200
3961
|
const isDrawingRef = useRef(false);
|
|
4201
3962
|
const justInteractedRef = useRef(false);
|
|
3963
|
+
const gestureControllerRef = useRef(null);
|
|
4202
3964
|
const livePatcher = useMemo(() => createCollaborationLivePatcher(), []);
|
|
4203
3965
|
useEffect(() => () => livePatcher.dispose(), [livePatcher]);
|
|
4204
3966
|
const [mode, setMode] = useState("edit");
|
|
@@ -4215,10 +3977,11 @@ function useViewerCoreState(_input) {
|
|
|
4215
3977
|
const [selectedElementId, setSelectedElementId] = useState(null);
|
|
4216
3978
|
const [selectedElementIds, setSelectedElementIds] = useState([]);
|
|
4217
3979
|
const [isDirty, setIsDirty] = useState(false);
|
|
3980
|
+
const autosaveDraftSinkRef = useRef(null);
|
|
4218
3981
|
const publishInlineText = useCallback(
|
|
4219
3982
|
(elementId, text) => {
|
|
4220
|
-
|
|
4221
|
-
livePatcher,
|
|
3983
|
+
reportInlineTextDraft(
|
|
3984
|
+
{ livePatcher, autosave: autosaveDraftSinkRef.current },
|
|
4222
3985
|
slidesRef.current[activeSlideIndexRef.current],
|
|
4223
3986
|
elementId,
|
|
4224
3987
|
text
|
|
@@ -4284,6 +4047,7 @@ function useViewerCoreState(_input) {
|
|
|
4284
4047
|
imageInputRef,
|
|
4285
4048
|
mediaInputRef,
|
|
4286
4049
|
activeSlideIndexRef,
|
|
4050
|
+
autosaveDraftSinkRef,
|
|
4287
4051
|
...inlineEditing,
|
|
4288
4052
|
...editPointsMode,
|
|
4289
4053
|
dragStateRef,
|
|
@@ -4292,6 +4056,7 @@ function useViewerCoreState(_input) {
|
|
|
4292
4056
|
marqueeStateRef,
|
|
4293
4057
|
isDrawingRef,
|
|
4294
4058
|
justInteractedRef,
|
|
4059
|
+
gestureControllerRef,
|
|
4295
4060
|
livePatcher,
|
|
4296
4061
|
mode,
|
|
4297
4062
|
setMode,
|
|
@@ -4778,96 +4543,43 @@ function useLoadContent({
|
|
|
4778
4543
|
return { handlerRef };
|
|
4779
4544
|
}
|
|
4780
4545
|
function useAutosave(input) {
|
|
4781
|
-
const { isDirty, filePath,
|
|
4546
|
+
const { isDirty, filePath, enabled = true } = input;
|
|
4782
4547
|
const intervalMs = resolveAutosaveIntervalMs({
|
|
4783
4548
|
hostIntervalMs: input.intervalMs,
|
|
4784
4549
|
optionsIntervalSeconds: input.intervalSeconds
|
|
4785
4550
|
});
|
|
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]);
|
|
4551
|
+
const live = useRef(input);
|
|
4552
|
+
live.current = input;
|
|
4553
|
+
const [controller] = useState(
|
|
4554
|
+
() => createAutosaveController({
|
|
4555
|
+
getActivation: () => ({ active: live.current.enabled ?? true }),
|
|
4556
|
+
getFilePath: () => live.current.filePath,
|
|
4557
|
+
getIntervalMs: () => resolveAutosaveIntervalMs({
|
|
4558
|
+
hostIntervalMs: live.current.intervalMs,
|
|
4559
|
+
optionsIntervalSeconds: live.current.intervalSeconds
|
|
4560
|
+
}),
|
|
4561
|
+
serialize: () => live.current.serializeSlides(),
|
|
4562
|
+
getStorage: () => live.current.storage,
|
|
4563
|
+
onSaved: (data) => live.current.onSaved?.(data),
|
|
4564
|
+
writeSnapshot: saveAutosaveSnapshot,
|
|
4565
|
+
// serializeSlides already overlays the live inline draft from its refs.
|
|
4566
|
+
getInlineEditingId: () => live.current.getInlineEditingId?.()
|
|
4567
|
+
})
|
|
4568
|
+
);
|
|
4569
|
+
if (input.inlineDraftSinkRef) {
|
|
4570
|
+
input.inlineDraftSinkRef.current = controller;
|
|
4571
|
+
}
|
|
4572
|
+
const { status } = useController(controller);
|
|
4810
4573
|
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
|
-
}, []);
|
|
4574
|
+
controller.refresh();
|
|
4575
|
+
}, [controller, enabled, filePath, intervalMs]);
|
|
4850
4576
|
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]);
|
|
4577
|
+
controller.observe(isDirty, live.current.getChangeSources?.() ?? []);
|
|
4578
|
+
});
|
|
4579
|
+
useEffect(() => () => controller.markClean(), [controller]);
|
|
4868
4580
|
return {
|
|
4869
|
-
autosaveStatus,
|
|
4870
|
-
triggerAutosave: () =>
|
|
4581
|
+
autosaveStatus: status,
|
|
4582
|
+
triggerAutosave: () => controller.saveNow()
|
|
4871
4583
|
};
|
|
4872
4584
|
}
|
|
4873
4585
|
|
|
@@ -5382,45 +5094,238 @@ function syncSelectionHandleOverlay(elementNode, elementId, geometry) {
|
|
|
5382
5094
|
}
|
|
5383
5095
|
}
|
|
5384
5096
|
|
|
5385
|
-
// src/viewer/hooks/
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5097
|
+
// src/viewer/hooks/canvas-gestures.ts
|
|
5098
|
+
var animationFrames = {
|
|
5099
|
+
request: (callback) => requestAnimationFrame(callback),
|
|
5100
|
+
cancel: (handle) => cancelAnimationFrame(handle)
|
|
5101
|
+
};
|
|
5102
|
+
function createCanvasGestures(getInput, frames = animationFrames) {
|
|
5103
|
+
let armed = null;
|
|
5104
|
+
let pending = null;
|
|
5105
|
+
let frameHandle = 0;
|
|
5106
|
+
let lastSnapLinesKey = "";
|
|
5107
|
+
const liveTarget = () => {
|
|
5108
|
+
const { livePatcher, editTemplateMode, activeSlide } = getInput();
|
|
5109
|
+
return livePatcher && !editTemplateMode && livePatcher.isActive() ? { patcher: livePatcher, slideId: activeSlide?.id } : void 0;
|
|
5110
|
+
};
|
|
5111
|
+
function showSnapLines(lines) {
|
|
5112
|
+
const next = lines.map((line) => ({
|
|
5113
|
+
axis: line.axis === "v" ? "x" : "y",
|
|
5114
|
+
position: line.position
|
|
5115
|
+
}));
|
|
5116
|
+
const key = JSON.stringify(next);
|
|
5117
|
+
if (key !== lastSnapLinesKey) {
|
|
5118
|
+
lastSnapLinesKey = key;
|
|
5119
|
+
getInput().setSnapLines(next);
|
|
5120
|
+
}
|
|
5391
5121
|
}
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5122
|
+
function paintMove(drag, transform) {
|
|
5123
|
+
const start = drag.startPositionsById[transform.id];
|
|
5124
|
+
if (!start) {
|
|
5125
|
+
return;
|
|
5126
|
+
}
|
|
5127
|
+
drag.lastDx = transform.x - start.x;
|
|
5128
|
+
drag.lastDy = transform.y - start.y;
|
|
5129
|
+
const live = liveTarget();
|
|
5130
|
+
for (const [id, from] of Object.entries(drag.startPositionsById)) {
|
|
5131
|
+
const x = from.x + drag.lastDx;
|
|
5132
|
+
const y = from.y + drag.lastDy;
|
|
5133
|
+
const domEl = drag.domEls.get(id);
|
|
5134
|
+
if (domEl) {
|
|
5135
|
+
domEl.style.left = `${x}px`;
|
|
5136
|
+
domEl.style.top = `${y}px`;
|
|
5137
|
+
syncSelectionHandleOverlay(domEl, id, { x, y });
|
|
5138
|
+
}
|
|
5139
|
+
if (live) {
|
|
5140
|
+
publishLiveGeometry(live.patcher, live.slideId, id, { x, y });
|
|
5141
|
+
}
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
function paintResize(resize, transform) {
|
|
5145
|
+
const { x, y } = transform;
|
|
5146
|
+
const width = Math.max(transform.width, MIN_ELEMENT_SIZE);
|
|
5147
|
+
const height = Math.max(transform.height, MIN_ELEMENT_SIZE);
|
|
5148
|
+
resize.lastX = x;
|
|
5149
|
+
resize.lastY = y;
|
|
5150
|
+
resize.lastWidth = transform.width;
|
|
5151
|
+
resize.lastHeight = transform.height;
|
|
5152
|
+
if (resize.domEl) {
|
|
5153
|
+
Object.assign(resize.domEl.style, {
|
|
5154
|
+
left: `${x}px`,
|
|
5155
|
+
top: `${y}px`,
|
|
5156
|
+
width: `${width}px`,
|
|
5157
|
+
height: `${height}px`
|
|
5158
|
+
});
|
|
5159
|
+
syncSelectionHandleOverlay(resize.domEl, resize.elementId, { x, y, width, height });
|
|
5160
|
+
}
|
|
5161
|
+
const live = liveTarget();
|
|
5162
|
+
if (live) {
|
|
5163
|
+
publishLiveGeometry(live.patcher, live.slideId, resize.elementId, { x, y, width, height });
|
|
5164
|
+
}
|
|
5165
|
+
}
|
|
5166
|
+
function paintPending() {
|
|
5167
|
+
const frame = pending;
|
|
5168
|
+
pending = null;
|
|
5169
|
+
frameHandle = 0;
|
|
5170
|
+
if (!frame || !armed) {
|
|
5171
|
+
return;
|
|
5172
|
+
}
|
|
5173
|
+
if (armed.kind === "move") {
|
|
5174
|
+
armed.drag.moved = true;
|
|
5175
|
+
showSnapLines(frame.lines);
|
|
5176
|
+
paintMove(armed.drag, frame.transform);
|
|
5177
|
+
} else {
|
|
5178
|
+
armed.resize.moved = true;
|
|
5179
|
+
paintResize(armed.resize, frame.transform);
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
function flushFrame() {
|
|
5183
|
+
if (frameHandle !== 0) {
|
|
5184
|
+
frames.cancel(frameHandle);
|
|
5185
|
+
}
|
|
5186
|
+
paintPending();
|
|
5187
|
+
}
|
|
5188
|
+
const controller = createGestureController({
|
|
5189
|
+
getScale: () => getInput().editorScale,
|
|
5190
|
+
// Axis-aligned, as the canvas has always moved and resized (no rotation).
|
|
5191
|
+
getElementBox: (id) => {
|
|
5192
|
+
const el = getInput().elementLookup.get(id);
|
|
5193
|
+
return el ? { x: el.x, y: el.y, width: el.width, height: el.height } : void 0;
|
|
5194
|
+
},
|
|
5195
|
+
getSiblings: () => {
|
|
5196
|
+
const { editTemplateMode, templateElements, activeSlide } = getInput();
|
|
5197
|
+
const source = editTemplateMode ? templateElements : activeSlide?.elements ?? [];
|
|
5198
|
+
return source.map(({ id, x, y, width, height }) => ({ id, x, y, width, height }));
|
|
5199
|
+
},
|
|
5200
|
+
getSnapToGrid: () => getInput().snapToGrid,
|
|
5201
|
+
getGridSize: () => getInput().gridSpacingPx,
|
|
5202
|
+
getSnapToShape: () => getInput().snapToShape,
|
|
5203
|
+
getGuides: () => getInput().guides.map(({ axis, position }) => ({ axis, position })),
|
|
5204
|
+
getMinSize: () => MIN_ELEMENT_SIZE,
|
|
5205
|
+
getSnapExcludeIds: () => armed?.kind === "move" ? Object.keys(armed.drag.startPositionsById) : [],
|
|
5206
|
+
getStageOrigin: () => {
|
|
5207
|
+
const rect = getInput().canvasStageRef.current?.getBoundingClientRect();
|
|
5208
|
+
return { left: rect?.left ?? 0, top: rect?.top ?? 0 };
|
|
5209
|
+
},
|
|
5210
|
+
onStart: () => void 0,
|
|
5211
|
+
onPreview: (transform, lines) => {
|
|
5212
|
+
pending = { transform, lines };
|
|
5213
|
+
if (frameHandle === 0) {
|
|
5214
|
+
frameHandle = frames.request(paintPending);
|
|
5215
|
+
}
|
|
5216
|
+
},
|
|
5217
|
+
onEnd: (transform, moved) => {
|
|
5218
|
+
flushFrame();
|
|
5219
|
+
const ended = armed;
|
|
5220
|
+
armed = null;
|
|
5221
|
+
if (ended) {
|
|
5222
|
+
finishGesture(ended, moved ? transform : null);
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
});
|
|
5226
|
+
function finishGesture(ended, transform) {
|
|
5227
|
+
const input = getInput();
|
|
5228
|
+
if (transform) {
|
|
5229
|
+
if (ended.kind === "move") {
|
|
5230
|
+
commitMove(input, ended.drag);
|
|
5231
|
+
} else {
|
|
5232
|
+
commitResize(input, ended.resize);
|
|
5233
|
+
}
|
|
5234
|
+
input.justInteractedRef.current = true;
|
|
5235
|
+
input.livePatcher?.flush();
|
|
5236
|
+
}
|
|
5237
|
+
input.dragStateRef.current = null;
|
|
5238
|
+
input.resizeStateRef.current = null;
|
|
5239
|
+
lastSnapLinesKey = "";
|
|
5240
|
+
input.setSnapLines([]);
|
|
5241
|
+
if (transform) {
|
|
5242
|
+
input.markDirty();
|
|
5243
|
+
}
|
|
5244
|
+
input.setPointerCommitNonce((n) => n + 1);
|
|
5395
5245
|
}
|
|
5396
|
-
return
|
|
5246
|
+
return {
|
|
5247
|
+
begin(kind, id, pointer) {
|
|
5248
|
+
if (controller.isActive()) {
|
|
5249
|
+
return;
|
|
5250
|
+
}
|
|
5251
|
+
const input = getInput();
|
|
5252
|
+
const drag = input.dragStateRef.current;
|
|
5253
|
+
const resize = input.resizeStateRef.current;
|
|
5254
|
+
armed = kind === "move" && drag ? { kind, drag } : kind === "resize" && resize ? { kind, resize } : null;
|
|
5255
|
+
if (!armed) {
|
|
5256
|
+
return;
|
|
5257
|
+
}
|
|
5258
|
+
lastSnapLinesKey = "";
|
|
5259
|
+
const handle = armed.kind === "resize" ? armed.resize.handle : void 0;
|
|
5260
|
+
controller.begin(kind, id, pointer, handle);
|
|
5261
|
+
if (!controller.isActive()) {
|
|
5262
|
+
armed = null;
|
|
5263
|
+
}
|
|
5264
|
+
},
|
|
5265
|
+
isActive: () => controller.isActive(),
|
|
5266
|
+
dispose: () => {
|
|
5267
|
+
if (frameHandle !== 0) {
|
|
5268
|
+
frames.cancel(frameHandle);
|
|
5269
|
+
frameHandle = 0;
|
|
5270
|
+
}
|
|
5271
|
+
pending = null;
|
|
5272
|
+
armed = null;
|
|
5273
|
+
controller.dispose();
|
|
5274
|
+
}
|
|
5275
|
+
};
|
|
5397
5276
|
}
|
|
5398
|
-
function
|
|
5399
|
-
const {
|
|
5400
|
-
|
|
5401
|
-
|
|
5277
|
+
function commitMove(input, drag) {
|
|
5278
|
+
const { lastDx: dx, lastDy: dy } = drag;
|
|
5279
|
+
const movedIds = new Set(Object.keys(drag.startPositionsById));
|
|
5280
|
+
const moveElements = (elements) => {
|
|
5281
|
+
const moved = elements.map((el) => {
|
|
5282
|
+
const start = drag.startPositionsById[el.id];
|
|
5283
|
+
return start ? { ...el, x: start.x + dx, y: start.y + dy } : el;
|
|
5284
|
+
});
|
|
5285
|
+
return applyReroutedConnectors(moved, rerouteConnectorsForMovedElements(moved, movedIds));
|
|
5286
|
+
};
|
|
5287
|
+
if (input.editTemplateMode) {
|
|
5288
|
+
const slideId = input.activeSlide?.id;
|
|
5289
|
+
if (slideId) {
|
|
5290
|
+
input.setTemplateElementsBySlideId((prev) => ({
|
|
5291
|
+
...prev,
|
|
5292
|
+
[slideId]: moveElements(prev[slideId] ?? [])
|
|
5293
|
+
}));
|
|
5294
|
+
}
|
|
5295
|
+
return;
|
|
5402
5296
|
}
|
|
5403
|
-
|
|
5297
|
+
input.updateSlides(
|
|
5298
|
+
(prev) => prev.map(
|
|
5299
|
+
(s, i) => i !== input.activeSlideIndex ? s : { ...s, elements: moveElements(s.elements) }
|
|
5300
|
+
)
|
|
5301
|
+
);
|
|
5404
5302
|
}
|
|
5405
|
-
function
|
|
5303
|
+
function commitResize(input, resize) {
|
|
5304
|
+
input.updateElementById(resize.elementId, {
|
|
5305
|
+
x: resize.lastX,
|
|
5306
|
+
y: resize.lastY,
|
|
5307
|
+
width: resize.lastWidth,
|
|
5308
|
+
height: resize.lastHeight
|
|
5309
|
+
});
|
|
5310
|
+
const movedIds = /* @__PURE__ */ new Set([resize.elementId]);
|
|
5311
|
+
input.updateSlides(
|
|
5312
|
+
(prev) => prev.map((s, i) => {
|
|
5313
|
+
if (i !== input.activeSlideIndex) {
|
|
5314
|
+
return s;
|
|
5315
|
+
}
|
|
5316
|
+
const rerouted = rerouteConnectorsForMovedElements(s.elements, movedIds);
|
|
5317
|
+
return rerouted.length === 0 ? s : { ...s, elements: applyReroutedConnectors(s.elements, rerouted) };
|
|
5318
|
+
})
|
|
5319
|
+
);
|
|
5320
|
+
}
|
|
5321
|
+
function processPointerMove(e, input) {
|
|
5406
5322
|
const {
|
|
5407
5323
|
editorScale,
|
|
5408
5324
|
canvasStageRef,
|
|
5409
5325
|
canvasSize,
|
|
5410
|
-
snapToGrid,
|
|
5411
|
-
snapToShape,
|
|
5412
|
-
gridSpacingPx,
|
|
5413
|
-
editTemplateMode,
|
|
5414
|
-
templateElements,
|
|
5415
|
-
activeSlide,
|
|
5416
|
-
guides,
|
|
5417
|
-
elementLookup,
|
|
5418
5326
|
marqueeStateRef,
|
|
5419
|
-
dragStateRef,
|
|
5420
|
-
resizeStateRef,
|
|
5421
5327
|
shapeAdjustmentDragStateRef,
|
|
5422
5328
|
setMarqueeSelectionState,
|
|
5423
|
-
setSnapLines,
|
|
5424
5329
|
updateElementById
|
|
5425
5330
|
} = input;
|
|
5426
5331
|
const marquee = marqueeStateRef.current;
|
|
@@ -5435,31 +5340,6 @@ function processPointerMove(e, input, tracker) {
|
|
|
5435
5340
|
);
|
|
5436
5341
|
return;
|
|
5437
5342
|
}
|
|
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
5343
|
const adj = shapeAdjustmentDragStateRef.current;
|
|
5464
5344
|
if (adj) {
|
|
5465
5345
|
processAdjustmentMove(e, adj, editorScale, updateElementById);
|
|
@@ -5475,129 +5355,6 @@ function processMarqueeMove(e, marquee, canvasStageRef, canvasSize, editorScale,
|
|
|
5475
5355
|
marquee.currentY = Math.max(0, Math.min(canvasSize.height, (e.clientY - rect.top) / editorScale));
|
|
5476
5356
|
setMarqueeSelectionState({ ...marquee });
|
|
5477
5357
|
}
|
|
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
5358
|
function processAdjustmentMove(e, adj, editorScale, updateElementById) {
|
|
5602
5359
|
const dx = (e.clientX - adj.startClientX) / editorScale;
|
|
5603
5360
|
const dy = (e.clientY - adj.startClientY) / editorScale;
|
|
@@ -5616,26 +5373,20 @@ function processPointerUp(input) {
|
|
|
5616
5373
|
editTemplateMode,
|
|
5617
5374
|
templateElements,
|
|
5618
5375
|
activeSlide,
|
|
5619
|
-
activeSlideIndex,
|
|
5620
5376
|
marqueeStateRef,
|
|
5621
5377
|
dragStateRef,
|
|
5622
5378
|
resizeStateRef,
|
|
5623
5379
|
shapeAdjustmentDragStateRef,
|
|
5624
5380
|
justInteractedRef,
|
|
5381
|
+
gestureRef,
|
|
5625
5382
|
setMarqueeSelectionState,
|
|
5626
|
-
setSnapLines,
|
|
5627
|
-
setTemplateElementsBySlideId,
|
|
5628
5383
|
setPointerCommitNonce,
|
|
5629
5384
|
applySelection,
|
|
5630
5385
|
clearSelection,
|
|
5631
|
-
updateSlides,
|
|
5632
|
-
updateElementById,
|
|
5633
5386
|
markDirty,
|
|
5634
5387
|
livePatcher
|
|
5635
5388
|
} = input;
|
|
5636
5389
|
const marquee = marqueeStateRef.current;
|
|
5637
|
-
const drag = dragStateRef.current;
|
|
5638
|
-
const rs = resizeStateRef.current;
|
|
5639
5390
|
const adj = shapeAdjustmentDragStateRef.current;
|
|
5640
5391
|
if (marquee) {
|
|
5641
5392
|
commitMarquee(
|
|
@@ -5646,62 +5397,22 @@ function processPointerUp(input) {
|
|
|
5646
5397
|
applySelection,
|
|
5647
5398
|
clearSelection
|
|
5648
5399
|
);
|
|
5649
|
-
marqueeStateRef.current = null;
|
|
5650
|
-
setMarqueeSelectionState(null);
|
|
5651
|
-
}
|
|
5652
|
-
if (drag?.moved) {
|
|
5653
|
-
commitDrag(
|
|
5654
|
-
drag,
|
|
5655
|
-
editTemplateMode,
|
|
5656
|
-
activeSlide,
|
|
5657
|
-
activeSlideIndex,
|
|
5658
|
-
setTemplateElementsBySlideId,
|
|
5659
|
-
updateSlides
|
|
5660
|
-
);
|
|
5661
5400
|
}
|
|
5662
|
-
if (
|
|
5663
|
-
|
|
5664
|
-
|
|
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
|
-
);
|
|
5401
|
+
if (!gestureRef?.current?.isActive()) {
|
|
5402
|
+
dragStateRef.current = null;
|
|
5403
|
+
resizeStateRef.current = null;
|
|
5687
5404
|
}
|
|
5688
|
-
|
|
5689
|
-
if (wasMoved) {
|
|
5405
|
+
if (adj?.moved) {
|
|
5690
5406
|
justInteractedRef.current = true;
|
|
5691
|
-
}
|
|
5692
|
-
if (wasMoved) {
|
|
5693
5407
|
livePatcher?.flush();
|
|
5694
5408
|
}
|
|
5695
5409
|
marqueeStateRef.current = null;
|
|
5696
|
-
dragStateRef.current = null;
|
|
5697
|
-
resizeStateRef.current = null;
|
|
5698
5410
|
shapeAdjustmentDragStateRef.current = null;
|
|
5699
5411
|
setMarqueeSelectionState(null);
|
|
5700
|
-
|
|
5701
|
-
if (wasMoved) {
|
|
5412
|
+
if (adj?.moved) {
|
|
5702
5413
|
markDirty();
|
|
5703
5414
|
}
|
|
5704
|
-
if (
|
|
5415
|
+
if (adj || marquee) {
|
|
5705
5416
|
setPointerCommitNonce((n) => n + 1);
|
|
5706
5417
|
}
|
|
5707
5418
|
}
|
|
@@ -5721,35 +5432,6 @@ function commitMarquee(marquee, editTemplateMode, templateElements, activeSlide,
|
|
|
5721
5432
|
clearSelection();
|
|
5722
5433
|
}
|
|
5723
5434
|
}
|
|
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
5435
|
|
|
5754
5436
|
// src/viewer/hooks/usePointerHandlers.ts
|
|
5755
5437
|
function usePointerHandlers(input) {
|
|
@@ -5759,41 +5441,42 @@ function usePointerHandlers(input) {
|
|
|
5759
5441
|
canvasSize,
|
|
5760
5442
|
activeSlide,
|
|
5761
5443
|
activeSlideIndex,
|
|
5762
|
-
gridSpacingPx,
|
|
5763
|
-
dragStateRef,
|
|
5764
|
-
resizeStateRef,
|
|
5765
5444
|
shapeAdjustmentDragStateRef,
|
|
5766
5445
|
marqueeStateRef,
|
|
5767
5446
|
editTemplateMode,
|
|
5768
|
-
snapToGrid,
|
|
5769
|
-
snapToShape,
|
|
5770
|
-
guides,
|
|
5771
5447
|
templateElements,
|
|
5772
|
-
elementLookup,
|
|
5773
5448
|
setMarqueeSelectionState,
|
|
5774
|
-
setSnapLines,
|
|
5775
|
-
setTemplateElementsBySlideId,
|
|
5776
5449
|
setPointerCommitNonce,
|
|
5777
5450
|
applySelection,
|
|
5778
5451
|
clearSelection,
|
|
5779
|
-
updateSlides,
|
|
5780
5452
|
updateElementById,
|
|
5781
5453
|
markDirty,
|
|
5782
|
-
livePatcher
|
|
5454
|
+
livePatcher,
|
|
5455
|
+
gestureRef
|
|
5783
5456
|
} = input;
|
|
5457
|
+
const inputRef = useRef(input);
|
|
5458
|
+
inputRef.current = input;
|
|
5459
|
+
const gestures = useMemo(() => createCanvasGestures(() => inputRef.current), []);
|
|
5784
5460
|
useEffect(() => {
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5461
|
+
if (gestureRef) {
|
|
5462
|
+
gestureRef.current = gestures;
|
|
5463
|
+
}
|
|
5464
|
+
return () => {
|
|
5465
|
+
gestures.dispose();
|
|
5466
|
+
if (gestureRef?.current === gestures) {
|
|
5467
|
+
gestureRef.current = null;
|
|
5468
|
+
}
|
|
5789
5469
|
};
|
|
5470
|
+
}, [gestures, gestureRef]);
|
|
5471
|
+
useEffect(() => {
|
|
5472
|
+
const tracker = { rafId: 0, pendingMoveEvent: null };
|
|
5790
5473
|
const handlePointerMove = (e) => {
|
|
5791
5474
|
tracker.pendingMoveEvent = e;
|
|
5792
5475
|
if (tracker.rafId === 0) {
|
|
5793
5476
|
tracker.rafId = requestAnimationFrame(() => {
|
|
5794
5477
|
tracker.rafId = 0;
|
|
5795
5478
|
if (tracker.pendingMoveEvent) {
|
|
5796
|
-
processPointerMove(tracker.pendingMoveEvent, input
|
|
5479
|
+
processPointerMove(tracker.pendingMoveEvent, input);
|
|
5797
5480
|
tracker.pendingMoveEvent = null;
|
|
5798
5481
|
}
|
|
5799
5482
|
});
|
|
@@ -5821,31 +5504,22 @@ function usePointerHandlers(input) {
|
|
|
5821
5504
|
}, [
|
|
5822
5505
|
editorScale,
|
|
5823
5506
|
canvasStageRef,
|
|
5824
|
-
dragStateRef,
|
|
5825
|
-
resizeStateRef,
|
|
5826
5507
|
shapeAdjustmentDragStateRef,
|
|
5827
5508
|
marqueeStateRef,
|
|
5828
5509
|
editTemplateMode,
|
|
5829
|
-
snapToGrid,
|
|
5830
|
-
snapToShape,
|
|
5831
|
-
guides,
|
|
5832
5510
|
templateElements,
|
|
5833
5511
|
setMarqueeSelectionState,
|
|
5834
|
-
setSnapLines,
|
|
5835
|
-
elementLookup,
|
|
5836
|
-
setTemplateElementsBySlideId,
|
|
5837
5512
|
setPointerCommitNonce,
|
|
5838
5513
|
activeSlide,
|
|
5839
5514
|
activeSlideIndex,
|
|
5840
5515
|
canvasSize.width,
|
|
5841
5516
|
canvasSize.height,
|
|
5842
|
-
gridSpacingPx,
|
|
5843
5517
|
applySelection,
|
|
5844
5518
|
clearSelection,
|
|
5845
|
-
updateSlides,
|
|
5846
5519
|
updateElementById,
|
|
5847
5520
|
markDirty,
|
|
5848
|
-
livePatcher
|
|
5521
|
+
livePatcher,
|
|
5522
|
+
gestureRef
|
|
5849
5523
|
]);
|
|
5850
5524
|
}
|
|
5851
5525
|
function mouseDownStartsSelectionDrag(event) {
|
|
@@ -5871,6 +5545,7 @@ function useCanvasInteractions(input) {
|
|
|
5871
5545
|
shapeAdjustmentDragStateRef,
|
|
5872
5546
|
marqueeStateRef,
|
|
5873
5547
|
justInteractedRef,
|
|
5548
|
+
gestureRef,
|
|
5874
5549
|
setInlineEditingElementId,
|
|
5875
5550
|
setInlineEditingText,
|
|
5876
5551
|
setContextMenuState,
|
|
@@ -5896,25 +5571,7 @@ function useCanvasInteractions(input) {
|
|
|
5896
5571
|
const scale = editorScale || 1;
|
|
5897
5572
|
return rect ? { x: (e.clientX - rect.left) / scale, y: (e.clientY - rect.top) / scale } : null;
|
|
5898
5573
|
};
|
|
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
|
-
};
|
|
5574
|
+
const resolvePressTarget = (elementId, e) => slideElements ? resolveGroupPressTarget(slideElements, elementId, slidePoint(e), effectiveSelectedIds) : elementId;
|
|
5918
5575
|
const handleInlineEditCommit = () => {
|
|
5919
5576
|
const editId = inlineEditingElementId;
|
|
5920
5577
|
if (!editId) {
|
|
@@ -6014,9 +5671,7 @@ function useCanvasInteractions(input) {
|
|
|
6014
5671
|
}
|
|
6015
5672
|
};
|
|
6016
5673
|
const handleElementDoubleClick = (pressedId, e) => {
|
|
6017
|
-
const
|
|
6018
|
-
const innermost = chain ? drillSelectionForDoubleClick(chain) : null;
|
|
6019
|
-
const elementId = innermost && canInteractWithElement(elementLookup.get(innermost), "select") ? innermost : pressedId;
|
|
5674
|
+
const elementId = mode === "present" || !slideElements ? pressedId : resolveGroupDoubleClickTarget(slideElements, pressedId, slidePoint(e));
|
|
6020
5675
|
if (elementId !== pressedId) {
|
|
6021
5676
|
ops.applySelection(elementId);
|
|
6022
5677
|
}
|
|
@@ -6079,6 +5734,7 @@ function useCanvasInteractions(input) {
|
|
|
6079
5734
|
lastDy: 0
|
|
6080
5735
|
};
|
|
6081
5736
|
setSnapLines([]);
|
|
5737
|
+
gestureRef?.current?.begin("move", movableIds[0], e);
|
|
6082
5738
|
};
|
|
6083
5739
|
const handleElementContextMenu = (elementId, e) => {
|
|
6084
5740
|
if (mode === "present") {
|
|
@@ -6151,6 +5807,7 @@ function useCanvasInteractions(input) {
|
|
|
6151
5807
|
lastWidth: el.width,
|
|
6152
5808
|
lastHeight: el.height
|
|
6153
5809
|
};
|
|
5810
|
+
gestureRef?.current?.begin("resize", elementId, e);
|
|
6154
5811
|
};
|
|
6155
5812
|
const handleRotate = (elementId, rotationDeg) => {
|
|
6156
5813
|
const el = elementLookup.get(elementId);
|
|
@@ -6656,11 +6313,11 @@ function useInsertElements(input) {
|
|
|
6656
6313
|
id: generateElementId()
|
|
6657
6314
|
});
|
|
6658
6315
|
};
|
|
6659
|
-
const handleAddChart = (chartKind) => {
|
|
6316
|
+
const handleAddChart = (chartKind, options) => {
|
|
6660
6317
|
if (!activeSlide) {
|
|
6661
6318
|
return;
|
|
6662
6319
|
}
|
|
6663
|
-
addElement(createDefaultChartElement(chartKind));
|
|
6320
|
+
addElement(createDefaultChartElement(chartKind, void 0, options));
|
|
6664
6321
|
};
|
|
6665
6322
|
const structured = createStructuredElementHandlers({
|
|
6666
6323
|
activeSlide,
|
|
@@ -8715,8 +8372,19 @@ function useThemeHandlers(input) {
|
|
|
8715
8372
|
return;
|
|
8716
8373
|
}
|
|
8717
8374
|
await handler.updateThemeFontScheme(fontScheme);
|
|
8375
|
+
const previousFonts = theme?.fontScheme;
|
|
8376
|
+
bumpHistory();
|
|
8377
|
+
setSlides((prev) => reResolveSlideFonts(prev, previousFonts, fontScheme));
|
|
8378
|
+
setTemplateElementsBySlideId(
|
|
8379
|
+
(prev) => Object.fromEntries(
|
|
8380
|
+
Object.entries(prev).map(([slideId, elements]) => [
|
|
8381
|
+
slideId,
|
|
8382
|
+
reResolveElementFonts(elements, previousFonts, fontScheme)
|
|
8383
|
+
])
|
|
8384
|
+
)
|
|
8385
|
+
);
|
|
8718
8386
|
setTheme((prev) => prev ? { ...prev, fontScheme } : { fontScheme });
|
|
8719
|
-
|
|
8387
|
+
history.markDirty();
|
|
8720
8388
|
};
|
|
8721
8389
|
const handleUpdateThemeName = async (name) => {
|
|
8722
8390
|
const handler = handlerRef.current;
|
|
@@ -8738,20 +8406,7 @@ function useThemeHandlers(input) {
|
|
|
8738
8406
|
}
|
|
8739
8407
|
await refreshContentAfterThemeChange();
|
|
8740
8408
|
};
|
|
8741
|
-
const handleApplyThemeData =
|
|
8742
|
-
const handler = handlerRef.current;
|
|
8743
|
-
if (!handler) {
|
|
8744
|
-
return;
|
|
8745
|
-
}
|
|
8746
|
-
await handler.applyTheme(colorScheme, fontScheme, themeName);
|
|
8747
|
-
setTheme((prev) => ({
|
|
8748
|
-
...prev,
|
|
8749
|
-
colorScheme,
|
|
8750
|
-
fontScheme,
|
|
8751
|
-
...themeName && { name: themeName }
|
|
8752
|
-
}));
|
|
8753
|
-
await refreshContentAfterThemeChange();
|
|
8754
|
-
};
|
|
8409
|
+
const handleApplyThemeData = (colorScheme, fontScheme, themeName) => applyThemeEditorEdit(input, { colorScheme, fontScheme, name: themeName ?? theme?.name ?? "" });
|
|
8755
8410
|
const handleSetTemplateBackground = (path, backgroundColor) => {
|
|
8756
8411
|
const handler = handlerRef.current;
|
|
8757
8412
|
if (!handler) {
|
|
@@ -9105,6 +8760,7 @@ function useViewerDialogs(input) {
|
|
|
9105
8760
|
embeddedFontFamilies
|
|
9106
8761
|
} = input;
|
|
9107
8762
|
const [isSmartArtDialogOpen, setIsSmartArtDialogOpen] = useState(false);
|
|
8763
|
+
const [isChartDialogOpen, setIsChartDialogOpen] = useState(false);
|
|
9108
8764
|
const [isEquationDialogOpen, setIsEquationDialogOpen] = useState(false);
|
|
9109
8765
|
const [isHyperlinkDialogOpen, setIsHyperlinkDialogOpen] = useState(false);
|
|
9110
8766
|
const [isPasswordDialogOpen, setIsPasswordDialogOpen] = useState(false);
|
|
@@ -9249,6 +8905,8 @@ function useViewerDialogs(input) {
|
|
|
9249
8905
|
return {
|
|
9250
8906
|
isSmartArtDialogOpen,
|
|
9251
8907
|
setIsSmartArtDialogOpen,
|
|
8908
|
+
isChartDialogOpen,
|
|
8909
|
+
setIsChartDialogOpen,
|
|
9252
8910
|
isEquationDialogOpen,
|
|
9253
8911
|
setIsEquationDialogOpen,
|
|
9254
8912
|
isHyperlinkDialogOpen,
|
|
@@ -9694,84 +9352,35 @@ function useSerialize(input) {
|
|
|
9694
9352
|
}
|
|
9695
9353
|
function useRecoveryDetection(input) {
|
|
9696
9354
|
const { filePath, fileName, loading, error, slideCount, autosaveAllowed = true } = input;
|
|
9697
|
-
const
|
|
9698
|
-
|
|
9699
|
-
const
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9355
|
+
const live = useRef(input);
|
|
9356
|
+
live.current = input;
|
|
9357
|
+
const [controller] = useState(
|
|
9358
|
+
() => createAutosaveRecoveryController({
|
|
9359
|
+
getStorage: () => live.current.storage,
|
|
9360
|
+
load: (bytes) => live.current.onRestore?.(bytes),
|
|
9361
|
+
onOffered: (record) => {
|
|
9362
|
+
live.current.onOffered?.(record);
|
|
9363
|
+
live.current.openVersionHistory?.();
|
|
9364
|
+
},
|
|
9365
|
+
probe: probeAutosaveRecovery,
|
|
9366
|
+
discardRecord: discardAutosaveRecovery
|
|
9367
|
+
})
|
|
9368
|
+
);
|
|
9369
|
+
const { prompt, discarding } = useController(controller);
|
|
9710
9370
|
useEffect(() => {
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
void (async () => {
|
|
9723
|
-
const offer = await probeAutosaveRecovery(
|
|
9724
|
-
filePath,
|
|
9725
|
-
Date.now(),
|
|
9726
|
-
fileName,
|
|
9727
|
-
storageRef.current
|
|
9728
|
-
);
|
|
9729
|
-
if (!offer) {
|
|
9730
|
-
return;
|
|
9731
|
-
}
|
|
9732
|
-
recordRef.current = offer.record;
|
|
9733
|
-
setPrompt(offer.prompt);
|
|
9734
|
-
onOfferedRef.current?.(offer.record);
|
|
9735
|
-
openVersionHistory?.();
|
|
9736
|
-
})();
|
|
9737
|
-
}, [filePath, fileName, loading, error, slideCount, autosaveAllowed, openVersionHistory]);
|
|
9738
|
-
const restore = useCallback(() => {
|
|
9739
|
-
if (actionPendingRef.current) {
|
|
9740
|
-
return;
|
|
9741
|
-
}
|
|
9742
|
-
actionPendingRef.current = true;
|
|
9743
|
-
const record = recordRef.current;
|
|
9744
|
-
setPrompt(null);
|
|
9745
|
-
if (record && onRestore) {
|
|
9746
|
-
onRestore(acceptAutosaveRecovery(record));
|
|
9747
|
-
acknowledgeAutosaveRecovery(record);
|
|
9748
|
-
}
|
|
9749
|
-
recordRef.current = null;
|
|
9750
|
-
}, [onRestore]);
|
|
9751
|
-
const discard = useCallback(() => {
|
|
9752
|
-
if (actionPendingRef.current) {
|
|
9753
|
-
return;
|
|
9754
|
-
}
|
|
9755
|
-
const record = recordRef.current;
|
|
9756
|
-
if (!record) {
|
|
9757
|
-
setPrompt(null);
|
|
9758
|
-
return;
|
|
9371
|
+
controller.check({ filePath, fileName, loading, error, slideCount, autosaveAllowed });
|
|
9372
|
+
}, [controller, filePath, fileName, loading, error, slideCount, autosaveAllowed]);
|
|
9373
|
+
return {
|
|
9374
|
+
prompt,
|
|
9375
|
+
discarding,
|
|
9376
|
+
restore: () => {
|
|
9377
|
+
void controller.restore().catch(() => {
|
|
9378
|
+
});
|
|
9379
|
+
},
|
|
9380
|
+
discard: () => {
|
|
9381
|
+
void controller.discard();
|
|
9759
9382
|
}
|
|
9760
|
-
|
|
9761
|
-
setDiscarding(true);
|
|
9762
|
-
void (async () => {
|
|
9763
|
-
try {
|
|
9764
|
-
await discardAutosaveRecovery(record, storageRef.current);
|
|
9765
|
-
recordRef.current = null;
|
|
9766
|
-
setPrompt(null);
|
|
9767
|
-
} catch {
|
|
9768
|
-
} finally {
|
|
9769
|
-
actionPendingRef.current = false;
|
|
9770
|
-
setDiscarding(false);
|
|
9771
|
-
}
|
|
9772
|
-
})();
|
|
9773
|
-
}, []);
|
|
9774
|
-
return { prompt, restore, discard, discarding };
|
|
9383
|
+
};
|
|
9775
9384
|
}
|
|
9776
9385
|
function usePresentationSetup(input) {
|
|
9777
9386
|
const {
|
|
@@ -10245,6 +9854,7 @@ function useEditorOperations(input) {
|
|
|
10245
9854
|
shapeAdjustmentDragStateRef: state.shapeAdjustmentDragStateRef,
|
|
10246
9855
|
marqueeStateRef: state.marqueeStateRef,
|
|
10247
9856
|
justInteractedRef: state.justInteractedRef,
|
|
9857
|
+
gestureRef: state.gestureControllerRef,
|
|
10248
9858
|
setInlineEditingElementId: state.setInlineEditingElementId,
|
|
10249
9859
|
setInlineEditingText: state.setInlineEditingText,
|
|
10250
9860
|
setContextMenuState: state.setContextMenuState,
|
|
@@ -10777,6 +10387,8 @@ function useContentLifecycle(input) {
|
|
|
10777
10387
|
// deck it has already snapshotted. The two refs are read by `.current`
|
|
10778
10388
|
// because an inline edit in progress lives there and nowhere else yet.
|
|
10779
10389
|
onSaved: input.onAutosave,
|
|
10390
|
+
inlineDraftSinkRef: state.autosaveDraftSinkRef,
|
|
10391
|
+
getInlineEditingId: () => state.inlineEditingElementIdRef.current,
|
|
10780
10392
|
getChangeSources: () => [
|
|
10781
10393
|
slides,
|
|
10782
10394
|
state.templateElementsBySlideId,
|
|
@@ -10806,138 +10418,27 @@ function useKeyboardShortcuts(input) {
|
|
|
10806
10418
|
inputRef.current = input;
|
|
10807
10419
|
const handleKeyDown = useCallback((e) => {
|
|
10808
10420
|
const current = inputRef.current;
|
|
10809
|
-
|
|
10810
|
-
if (startAction !== null) {
|
|
10811
|
-
e.preventDefault();
|
|
10812
|
-
if (startAction === "fromBeginning") {
|
|
10813
|
-
current.onStartShowFromBeginning();
|
|
10814
|
-
} else {
|
|
10815
|
-
current.onStartShowFromCurrent();
|
|
10816
|
-
}
|
|
10817
|
-
return;
|
|
10818
|
-
}
|
|
10819
|
-
const { action, dx, dy } = mapCustomizedEditorKey(
|
|
10421
|
+
dispatchEditorKey(
|
|
10820
10422
|
e,
|
|
10821
10423
|
{
|
|
10822
10424
|
canEdit: current.canEdit,
|
|
10823
|
-
canPaste: current.canPaste,
|
|
10824
|
-
// The Slide Master view is an editing surface, not a viewing one
|
|
10825
|
-
//
|
|
10826
|
-
// NO_ACTION there, so Delete, the arrow-key nudges and the clipboard
|
|
10827
|
-
// keys were all inert over a master shape even though the write path
|
|
10828
|
-
// behind them routes to the owning part correctly. Svelte and
|
|
10829
|
-
// vanilla, which render the master into their ordinary editable
|
|
10830
|
-
// stage, never had the gap.
|
|
10425
|
+
...current.canPaste === void 0 ? {} : { canPaste: current.canPaste },
|
|
10426
|
+
// The Slide Master view is an editing surface, not a viewing one, so
|
|
10427
|
+
// only the other modes count as "not editing" for the editor keymap.
|
|
10831
10428
|
isPresenting: current.mode !== "edit" && current.mode !== "master",
|
|
10429
|
+
// F5 is only inert while the show itself runs: a read-only viewer can
|
|
10430
|
+
// still start a show (it has a "From Beginning" button too).
|
|
10431
|
+
isShowRunning: current.mode === "present",
|
|
10432
|
+
canStartShow: !current.customization || isFeatureEnabled(current.customization, "presentMode"),
|
|
10832
10433
|
hasSelection: current.hasSelection,
|
|
10833
10434
|
isEditingText: Boolean(
|
|
10834
10435
|
current.inlineEditingElementId || current.tableEditorState?.isEditing
|
|
10835
10436
|
),
|
|
10836
10437
|
isDrawing: current.activeTool !== "select",
|
|
10837
|
-
|
|
10838
|
-
isControlTarget: isEditorControlTarget(e.target)
|
|
10438
|
+
keyboard: current.customization?.keyboard
|
|
10839
10439
|
},
|
|
10840
|
-
current
|
|
10440
|
+
toEditorKeyHandlers(current)
|
|
10841
10441
|
);
|
|
10842
|
-
if (action === null) {
|
|
10843
|
-
return;
|
|
10844
|
-
}
|
|
10845
|
-
e.preventDefault();
|
|
10846
|
-
switch (action) {
|
|
10847
|
-
case "escape":
|
|
10848
|
-
current.onEscape();
|
|
10849
|
-
break;
|
|
10850
|
-
case "delete":
|
|
10851
|
-
current.onDelete();
|
|
10852
|
-
break;
|
|
10853
|
-
case "undo":
|
|
10854
|
-
current.onUndo();
|
|
10855
|
-
break;
|
|
10856
|
-
case "redo":
|
|
10857
|
-
current.onRedo();
|
|
10858
|
-
break;
|
|
10859
|
-
case "copy":
|
|
10860
|
-
current.onCopy();
|
|
10861
|
-
break;
|
|
10862
|
-
case "cut":
|
|
10863
|
-
current.onCut();
|
|
10864
|
-
break;
|
|
10865
|
-
case "paste":
|
|
10866
|
-
current.onPaste();
|
|
10867
|
-
break;
|
|
10868
|
-
case "duplicate":
|
|
10869
|
-
current.onDuplicate();
|
|
10870
|
-
break;
|
|
10871
|
-
case "selectAll":
|
|
10872
|
-
current.onSelectAll();
|
|
10873
|
-
break;
|
|
10874
|
-
case "group":
|
|
10875
|
-
current.onGroup?.();
|
|
10876
|
-
break;
|
|
10877
|
-
case "ungroup":
|
|
10878
|
-
current.onUngroup?.();
|
|
10879
|
-
break;
|
|
10880
|
-
case "toggleShortcuts":
|
|
10881
|
-
current.onToggleShortcuts?.();
|
|
10882
|
-
break;
|
|
10883
|
-
case "find":
|
|
10884
|
-
current.onFind?.();
|
|
10885
|
-
break;
|
|
10886
|
-
case "nudge":
|
|
10887
|
-
current.onNudge(dx ?? 0, dy ?? 0);
|
|
10888
|
-
break;
|
|
10889
|
-
case "prevSlide":
|
|
10890
|
-
current.onPrevSlide?.();
|
|
10891
|
-
break;
|
|
10892
|
-
case "nextSlide":
|
|
10893
|
-
current.onNextSlide?.();
|
|
10894
|
-
break;
|
|
10895
|
-
case "alignLeft":
|
|
10896
|
-
current.onAlignLeft?.();
|
|
10897
|
-
break;
|
|
10898
|
-
case "alignCenter":
|
|
10899
|
-
current.onAlignCenter?.();
|
|
10900
|
-
break;
|
|
10901
|
-
case "alignRight":
|
|
10902
|
-
current.onAlignRight?.();
|
|
10903
|
-
break;
|
|
10904
|
-
case "alignJustify":
|
|
10905
|
-
current.onAlignJustify?.();
|
|
10906
|
-
break;
|
|
10907
|
-
case "increaseFontSize":
|
|
10908
|
-
current.onIncreaseFontSize?.();
|
|
10909
|
-
break;
|
|
10910
|
-
case "decreaseFontSize":
|
|
10911
|
-
current.onDecreaseFontSize?.();
|
|
10912
|
-
break;
|
|
10913
|
-
case "copyFormat":
|
|
10914
|
-
current.onCopyFormat?.();
|
|
10915
|
-
break;
|
|
10916
|
-
case "pasteFormat":
|
|
10917
|
-
current.onPasteFormat?.();
|
|
10918
|
-
break;
|
|
10919
|
-
case "newSlide":
|
|
10920
|
-
current.onNewSlide?.();
|
|
10921
|
-
break;
|
|
10922
|
-
case "hyperlink":
|
|
10923
|
-
current.onHyperlink?.();
|
|
10924
|
-
break;
|
|
10925
|
-
case "findReplace":
|
|
10926
|
-
current.onFindReplace?.();
|
|
10927
|
-
break;
|
|
10928
|
-
case "clearFormatting":
|
|
10929
|
-
current.onClearFormatting?.();
|
|
10930
|
-
break;
|
|
10931
|
-
case "cycleSelectionNext":
|
|
10932
|
-
current.onCycleSelectionNext?.();
|
|
10933
|
-
break;
|
|
10934
|
-
case "cycleSelectionPrev":
|
|
10935
|
-
current.onCycleSelectionPrev?.();
|
|
10936
|
-
break;
|
|
10937
|
-
case "pasteSpecial":
|
|
10938
|
-
current.onPasteSpecial?.();
|
|
10939
|
-
break;
|
|
10940
|
-
}
|
|
10941
10442
|
}, []);
|
|
10942
10443
|
useEffect(() => {
|
|
10943
10444
|
window.addEventListener("keydown", handleKeyDown);
|
|
@@ -10946,6 +10447,43 @@ function useKeyboardShortcuts(input) {
|
|
|
10946
10447
|
};
|
|
10947
10448
|
}, [handleKeyDown]);
|
|
10948
10449
|
}
|
|
10450
|
+
function toEditorKeyHandlers(current) {
|
|
10451
|
+
return {
|
|
10452
|
+
startShowFromBeginning: current.onStartShowFromBeginning,
|
|
10453
|
+
startShowFromCurrent: current.onStartShowFromCurrent,
|
|
10454
|
+
escape: current.onEscape,
|
|
10455
|
+
delete: current.onDelete,
|
|
10456
|
+
undo: current.onUndo,
|
|
10457
|
+
redo: current.onRedo,
|
|
10458
|
+
copy: current.onCopy,
|
|
10459
|
+
cut: current.onCut,
|
|
10460
|
+
paste: current.onPaste,
|
|
10461
|
+
duplicate: current.onDuplicate,
|
|
10462
|
+
selectAll: current.onSelectAll,
|
|
10463
|
+
group: current.onGroup,
|
|
10464
|
+
ungroup: current.onUngroup,
|
|
10465
|
+
toggleShortcuts: current.onToggleShortcuts,
|
|
10466
|
+
find: current.onFind,
|
|
10467
|
+
nudge: current.onNudge,
|
|
10468
|
+
prevSlide: current.onPrevSlide,
|
|
10469
|
+
nextSlide: current.onNextSlide,
|
|
10470
|
+
alignLeft: current.onAlignLeft,
|
|
10471
|
+
alignCenter: current.onAlignCenter,
|
|
10472
|
+
alignRight: current.onAlignRight,
|
|
10473
|
+
alignJustify: current.onAlignJustify,
|
|
10474
|
+
increaseFontSize: current.onIncreaseFontSize,
|
|
10475
|
+
decreaseFontSize: current.onDecreaseFontSize,
|
|
10476
|
+
copyFormat: current.onCopyFormat,
|
|
10477
|
+
pasteFormat: current.onPasteFormat,
|
|
10478
|
+
newSlide: current.onNewSlide,
|
|
10479
|
+
hyperlink: current.onHyperlink,
|
|
10480
|
+
findReplace: current.onFindReplace,
|
|
10481
|
+
clearFormatting: current.onClearFormatting,
|
|
10482
|
+
cycleSelectionNext: current.onCycleSelectionNext,
|
|
10483
|
+
cycleSelectionPrev: current.onCycleSelectionPrev,
|
|
10484
|
+
pasteSpecial: current.onPasteSpecial
|
|
10485
|
+
};
|
|
10486
|
+
}
|
|
10949
10487
|
var CLEAR_FORMATTING_PATCH = {
|
|
10950
10488
|
bold: false,
|
|
10951
10489
|
italic: false,
|
|
@@ -11211,7 +10749,8 @@ function useViewerIntegration(input) {
|
|
|
11211
10749
|
updateSlides: editorOps.ops.updateSlides,
|
|
11212
10750
|
updateElementById: editorOps.ops.updateElementById,
|
|
11213
10751
|
markDirty: history.markDirty,
|
|
11214
|
-
livePatcher: state.livePatcher
|
|
10752
|
+
livePatcher: state.livePatcher,
|
|
10753
|
+
gestureRef: state.gestureControllerRef
|
|
11215
10754
|
});
|
|
11216
10755
|
const [isEncryptedDialogOpen, setIsEncryptedDialogOpen] = useState(false);
|
|
11217
10756
|
const [loadVersion, setLoadVersion] = useState(0);
|
|
@@ -12648,6 +12187,7 @@ function buildToolbarProps(input) {
|
|
|
12648
12187
|
onAddShape: insertHandlers.handleAddShape,
|
|
12649
12188
|
onAddTable: insertHandlers.handleAddTable,
|
|
12650
12189
|
onAddChart: insertHandlers.handleAddChart,
|
|
12190
|
+
onOpenChartDialog: () => dialogs.setIsChartDialogOpen(true),
|
|
12651
12191
|
onAddSmartArt: () => dialogs.setIsSmartArtDialogOpen(true),
|
|
12652
12192
|
onAddEquation: () => {
|
|
12653
12193
|
dialogs.setEditingEquationOmml(null);
|
|
@@ -14507,6 +14047,50 @@ var EDGE_HANDLES = [
|
|
|
14507
14047
|
sizeClass: "w-2 h-5 max-md:w-3 max-md:h-8 rounded-sm"
|
|
14508
14048
|
}
|
|
14509
14049
|
];
|
|
14050
|
+
var wholeDegrees = (deg) => Math.round((deg % 360 + 360) % 360) % 360;
|
|
14051
|
+
function startRotateKnobGesture(options) {
|
|
14052
|
+
const { button, elementId, rotation, onRotate } = options;
|
|
14053
|
+
const scope = button.closest("[data-pptx-viewport]") ?? document;
|
|
14054
|
+
const wrapper = scope.querySelector(elementIdSelector(elementId));
|
|
14055
|
+
if (!wrapper) {
|
|
14056
|
+
return;
|
|
14057
|
+
}
|
|
14058
|
+
const rect = wrapper.getBoundingClientRect();
|
|
14059
|
+
const base = options.nonRotationTransform ? ` ${options.nonRotationTransform}` : "";
|
|
14060
|
+
const paint = (deg) => {
|
|
14061
|
+
const transform = `rotate(${deg}deg)${base}`;
|
|
14062
|
+
wrapper.style.transform = transform;
|
|
14063
|
+
syncSelectionHandleOverlay(wrapper, elementId, { transform });
|
|
14064
|
+
};
|
|
14065
|
+
if (options.pointerId !== void 0) {
|
|
14066
|
+
button.setPointerCapture?.(options.pointerId);
|
|
14067
|
+
}
|
|
14068
|
+
const gesture = createGestureController({
|
|
14069
|
+
getScale: () => 1,
|
|
14070
|
+
getElementBox: () => ({
|
|
14071
|
+
x: rect.left,
|
|
14072
|
+
y: rect.top,
|
|
14073
|
+
width: rect.width,
|
|
14074
|
+
height: rect.height,
|
|
14075
|
+
rotation
|
|
14076
|
+
}),
|
|
14077
|
+
getSiblings: () => [],
|
|
14078
|
+
getStageOrigin: () => ({ left: 0, top: 0 }),
|
|
14079
|
+
onStart: () => void 0,
|
|
14080
|
+
onPreview: (transform) => paint(wholeDegrees(transform.rotation)),
|
|
14081
|
+
onEnd: (transform) => {
|
|
14082
|
+
const deg = transform ? wholeDegrees(transform.rotation) : rotation;
|
|
14083
|
+
if (deg !== rotation) {
|
|
14084
|
+
onRotate?.(elementId, deg);
|
|
14085
|
+
}
|
|
14086
|
+
}
|
|
14087
|
+
});
|
|
14088
|
+
gesture.begin("rotate", elementId, {
|
|
14089
|
+
clientX: options.pointer.clientX,
|
|
14090
|
+
clientY: options.pointer.clientY,
|
|
14091
|
+
shiftKey: false
|
|
14092
|
+
});
|
|
14093
|
+
}
|
|
14510
14094
|
var appearance = { fill: "var(--color-primary)", borderColor: "#ffffff" };
|
|
14511
14095
|
var cornerSize = "var(--pptx-react-corner-default, 12px)";
|
|
14512
14096
|
var edgeLength = "var(--pptx-react-edge-length-default, 20px)";
|
|
@@ -14620,50 +14204,15 @@ function ResizeHandles({
|
|
|
14620
14204
|
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
14621
14205
|
onResizePointerDown(elementId, e, handle);
|
|
14622
14206
|
};
|
|
14623
|
-
const startRotate = (
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
|
|
14631
|
-
|
|
14632
|
-
const base = nonRotationTransform ? ` ${nonRotationTransform}` : "";
|
|
14633
|
-
const startDeg = rotation ?? 0;
|
|
14634
|
-
const dragRotation = createRotationDrag(
|
|
14635
|
-
{ x: cx, y: cy },
|
|
14636
|
-
{ x: pointer.clientX, y: pointer.clientY },
|
|
14637
|
-
startDeg
|
|
14638
|
-
);
|
|
14639
|
-
let last = startDeg;
|
|
14640
|
-
if (pointerId !== void 0) {
|
|
14641
|
-
btn.setPointerCapture?.(pointerId);
|
|
14642
|
-
}
|
|
14643
|
-
const apply = (clientX, clientY, shift) => {
|
|
14644
|
-
let deg = dragRotation({ x: clientX, y: clientY });
|
|
14645
|
-
if (shift) {
|
|
14646
|
-
deg = Math.round(deg / 15) * 15;
|
|
14647
|
-
}
|
|
14648
|
-
deg = Math.round((deg % 360 + 360) % 360);
|
|
14649
|
-
last = deg;
|
|
14650
|
-
const transform = `rotate(${deg}deg)${base}`;
|
|
14651
|
-
wrapper.style.transform = transform;
|
|
14652
|
-
syncSelectionHandleOverlay(wrapper, elementId, { transform });
|
|
14653
|
-
};
|
|
14654
|
-
const onPointerMove = (ev) => apply(ev.clientX, ev.clientY, ev.shiftKey);
|
|
14655
|
-
const end = () => {
|
|
14656
|
-
window.removeEventListener("pointermove", onPointerMove);
|
|
14657
|
-
window.removeEventListener("pointerup", end);
|
|
14658
|
-
window.removeEventListener("pointercancel", end);
|
|
14659
|
-
if (last !== startDeg) {
|
|
14660
|
-
onRotate?.(elementId, last);
|
|
14661
|
-
}
|
|
14662
|
-
};
|
|
14663
|
-
window.addEventListener("pointermove", onPointerMove);
|
|
14664
|
-
window.addEventListener("pointerup", end);
|
|
14665
|
-
window.addEventListener("pointercancel", end);
|
|
14666
|
-
};
|
|
14207
|
+
const startRotate = (button, pointer) => startRotateKnobGesture({
|
|
14208
|
+
button,
|
|
14209
|
+
elementId,
|
|
14210
|
+
pointer,
|
|
14211
|
+
pointerId: pointer.pointerId,
|
|
14212
|
+
rotation: rotation ?? 0,
|
|
14213
|
+
...nonRotationTransform ? { nonRotationTransform } : {},
|
|
14214
|
+
...onRotate ? { onRotate } : {}
|
|
14215
|
+
});
|
|
14667
14216
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14668
14217
|
[...CORNER_HANDLES, ...EDGE_HANDLES].map(({ handle, posClass, cursor }) => {
|
|
14669
14218
|
const corner = handle.length === 2;
|
|
@@ -14734,7 +14283,7 @@ function ResizeHandles({
|
|
|
14734
14283
|
},
|
|
14735
14284
|
onPointerDown: (e) => {
|
|
14736
14285
|
e.stopPropagation();
|
|
14737
|
-
startRotate(e.currentTarget, e
|
|
14286
|
+
startRotate(e.currentTarget, e);
|
|
14738
14287
|
},
|
|
14739
14288
|
onMouseDown: (e) => {
|
|
14740
14289
|
e.stopPropagation();
|
|
@@ -19144,4 +18693,4 @@ function useResizablePanels() {
|
|
|
19144
18693
|
};
|
|
19145
18694
|
}
|
|
19146
18695
|
|
|
19147
|
-
export { ACTION_VERB_MAP, ChartFormatContext, ChartPartSelectionProvider, CollaborationCursorOverlay, CollaborationProvider, ElementRenderer, FragmentedTransitionLayer, InlineCollaborationContext, MIN_TOUCH_TARGET, MorphTransitionOverlay, PresentationTransitionOverlay, RemoteSelectionOverlay, RemoteUserCursors, Rendering3DFlagsContext, ResizeHandles, SlideBackgroundImageLayer, SlideLayer,
|
|
18696
|
+
export { ACTION_VERB_MAP, ChartFormatContext, ChartPartSelectionProvider, CollaborationCursorOverlay, CollaborationProvider, ElementRenderer, FragmentedTransitionLayer, InlineCollaborationContext, MIN_TOUCH_TARGET, MorphTransitionOverlay, PresentationTransitionOverlay, RemoteSelectionOverlay, RemoteUserCursors, Rendering3DFlagsContext, ResizeHandles, SlideBackgroundImageLayer, SlideLayer, StaticElementRenderer, ViewerOptionsContext, ViewerOptionsStoreContext, computeToolbarVisibility, createReviewCommentsHost, detectTargetType, imgSrc, isAudienceTab, parseAudienceNonce, parseEmailUrl, parseSlideFromUrl, playAnimationSound, renderStrokeView, renderToCanvas, resolveSmartArtDataPalette, safePrompt, scopeLayoutOptionsToActiveSlide, useAnimationPlayback, useAnnotationHandlers, useAudienceMode, useAutosave, useBroadcastFollower, useCanvasInteractions, useChartFormatContext, useChartPartSelection, useClipboardHandlers, useCollaboration, useCollaborationDocumentSync, useCollaborativeHistory, useCollaborativeState, useComments, useCompatibilityToastsState, useContentLifecycle, useController, useDerivedElementState, useDerivedSlideState, useDialogCustomShows, useEditorHistory, useEditorOperations, useElementManipulation, useElementOperations, useExportHandlers, useExportSaveAs, useFindReplace, useFollowMode, useFontInjection, useGroupAlignLayerHandlers, useIOHandlers, useInsertElements, useIsMobile, useKeyboardInsets, useKeyboardShortcutWiring, useKeyboardShortcuts, useLayoutSwitching, useLoadContent, useMergeShapesHandler, useModalDismissDrag, usePointerHandlers, usePresenceTracking, usePresentationAnnotations, usePresentationKeyboard, usePresentationMode, usePresentationSetup, usePresenterWindow, usePrintHandlers, usePropertyHandlers, useReadOnlyRecommendationState, useRecoveryDetection, useReducedMotion, useRehearsalTimings, useReportOnChange, useResizablePanels, useSectionOperations, useSerialize, useSheetDismissDrag, useSlideManagement, useSlideNavigation, useSwipeNavigation, useTableOperations, useThemeHandlers, useThemeSwitching, useToolbarVisibility, useTouchGestures, useViewPreferencesSync, useViewerBuildingBlocks, useViewerCoreState, useViewerDialogs, useViewerIntegration, useViewerOptions, useViewerOptionsContext, useViewerState, useViewerUIState, useVirtualizedSlides, useYjsDocumentSync, useYjsProvider, useZoomNavigation, useZoomViewport, withDisplayName };
|