pptx-react-viewer 3.3.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/{AiChatPanel-BNFDBP4S.mjs → AiChatPanel-AIM55U76.mjs} +4 -4
  3. package/dist/AiChatPanel-AIM55U76.mjs.br +0 -0
  4. package/dist/AiChatPanel-AIM55U76.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-WNQCTQB5.js → AiChatPanel-Q2ZVO4RR.js} +25 -25
  6. package/dist/AiChatPanel-Q2ZVO4RR.js.br +0 -0
  7. package/dist/AiChatPanel-Q2ZVO4RR.js.gz +0 -0
  8. package/dist/{Area3DChartScene-SAQVRYOH.mjs → Area3DChartScene-DNLGOR5F.mjs} +1 -1
  9. package/dist/{Area3DChartScene-SAQVRYOH.mjs.br → Area3DChartScene-DNLGOR5F.mjs.br} +0 -0
  10. package/dist/Area3DChartScene-DNLGOR5F.mjs.gz +0 -0
  11. package/dist/{Area3DChartScene-FXBSLIGX.js → Area3DChartScene-W5HVINQ6.js} +2 -2
  12. package/dist/Area3DChartScene-W5HVINQ6.js.br +0 -0
  13. package/dist/Area3DChartScene-W5HVINQ6.js.gz +0 -0
  14. package/dist/{Bar3DChartScene-7HVUTP2E.js → Bar3DChartScene-SOO62TCP.js} +2 -2
  15. package/dist/Bar3DChartScene-SOO62TCP.js.br +0 -0
  16. package/dist/Bar3DChartScene-SOO62TCP.js.gz +0 -0
  17. package/dist/{Bar3DChartScene-LUA6E2K6.mjs → Bar3DChartScene-VYKQAY6X.mjs} +1 -1
  18. package/dist/Bar3DChartScene-VYKQAY6X.mjs.br +0 -0
  19. package/dist/Bar3DChartScene-VYKQAY6X.mjs.gz +0 -0
  20. package/dist/{Line3DChartScene-OVPULUTF.js → Line3DChartScene-BAP3YA3R.js} +2 -2
  21. package/dist/Line3DChartScene-BAP3YA3R.js.br +0 -0
  22. package/dist/Line3DChartScene-BAP3YA3R.js.gz +0 -0
  23. package/dist/{Line3DChartScene-IW4JGH57.mjs → Line3DChartScene-ZVELPNOD.mjs} +1 -1
  24. package/dist/{Line3DChartScene-IW4JGH57.mjs.br → Line3DChartScene-ZVELPNOD.mjs.br} +0 -0
  25. package/dist/Line3DChartScene-ZVELPNOD.mjs.gz +0 -0
  26. package/dist/{Model3DScene-5KP6BVCV.js → Model3DScene-BWNVCCAZ.js} +2 -2
  27. package/dist/Model3DScene-BWNVCCAZ.js.br +0 -0
  28. package/dist/Model3DScene-BWNVCCAZ.js.gz +0 -0
  29. package/dist/{Model3DScene-BERTZYCJ.mjs → Model3DScene-ZJWU5IUY.mjs} +1 -1
  30. package/dist/Model3DScene-ZJWU5IUY.mjs.br +0 -0
  31. package/dist/Model3DScene-ZJWU5IUY.mjs.gz +0 -0
  32. package/dist/{PieChart3DScene-3R2ETTGA.js → PieChart3DScene-2DJE4BM3.js} +2 -2
  33. package/dist/PieChart3DScene-2DJE4BM3.js.br +0 -0
  34. package/dist/PieChart3DScene-2DJE4BM3.js.gz +0 -0
  35. package/dist/{PieChart3DScene-O6FFK5L7.mjs → PieChart3DScene-NNLKJ6LN.mjs} +1 -1
  36. package/dist/PieChart3DScene-NNLKJ6LN.mjs.br +0 -0
  37. package/dist/PieChart3DScene-NNLKJ6LN.mjs.gz +0 -0
  38. package/dist/PowerPointViewer-Cl6jBPNw.d.ts.map +1 -1
  39. package/dist/{SurfaceChart3DScene-OCR26R5D.mjs → SurfaceChart3DScene-NWB4QAOI.mjs} +1 -1
  40. package/dist/SurfaceChart3DScene-NWB4QAOI.mjs.br +0 -0
  41. package/dist/SurfaceChart3DScene-NWB4QAOI.mjs.gz +0 -0
  42. package/dist/{SurfaceChart3DScene-TGFAOLHL.js → SurfaceChart3DScene-WRSCQKJV.js} +2 -2
  43. package/dist/SurfaceChart3DScene-WRSCQKJV.js.br +0 -0
  44. package/dist/SurfaceChart3DScene-WRSCQKJV.js.gz +0 -0
  45. package/dist/{chunk-ITN5NYYM.mjs → chunk-4YGGPPJZ.mjs} +6 -19
  46. package/dist/chunk-4YGGPPJZ.mjs.br +0 -0
  47. package/dist/chunk-4YGGPPJZ.mjs.gz +0 -0
  48. package/dist/{chunk-3B5FRKYU.mjs → chunk-EM3D67TB.mjs} +1430 -511
  49. package/dist/chunk-EM3D67TB.mjs.br +0 -0
  50. package/dist/chunk-EM3D67TB.mjs.gz +0 -0
  51. package/dist/{chunk-44CQ67GQ.js → chunk-GKRE7272.js} +172 -185
  52. package/dist/chunk-GKRE7272.js.br +0 -0
  53. package/dist/chunk-GKRE7272.js.gz +0 -0
  54. package/dist/{chunk-2FTJAMFA.mjs → chunk-IJLTDBXT.mjs} +13 -5
  55. package/dist/chunk-IJLTDBXT.mjs.br +0 -0
  56. package/dist/chunk-IJLTDBXT.mjs.gz +0 -0
  57. package/dist/{chunk-DM2IZCSD.mjs → chunk-PADP3NUM.mjs} +3056 -857
  58. package/dist/chunk-PADP3NUM.mjs.br +0 -0
  59. package/dist/chunk-PADP3NUM.mjs.gz +0 -0
  60. package/dist/{chunk-FSQCEAMG.js → chunk-PDVJNNWP.js} +17 -9
  61. package/dist/chunk-PDVJNNWP.js.br +0 -0
  62. package/dist/chunk-PDVJNNWP.js.gz +0 -0
  63. package/dist/{chunk-QEEU4S4Z.mjs → chunk-QEAU2XTI.mjs} +671 -114
  64. package/dist/chunk-QEAU2XTI.mjs.br +0 -0
  65. package/dist/chunk-QEAU2XTI.mjs.gz +0 -0
  66. package/dist/{chunk-K6R2JNCK.js → chunk-SEJEVNXW.js} +3088 -856
  67. package/dist/chunk-SEJEVNXW.js.br +0 -0
  68. package/dist/chunk-SEJEVNXW.js.gz +0 -0
  69. package/dist/{chunk-3P7FYHJH.js → chunk-UNIJUD5C.js} +44 -1
  70. package/dist/chunk-UNIJUD5C.js.br +0 -0
  71. package/dist/{chunk-3P7FYHJH.js.gz → chunk-UNIJUD5C.js.gz} +0 -0
  72. package/dist/{chunk-QKSYKQEL.js → chunk-WXQQ43IA.js} +2546 -1627
  73. package/dist/chunk-WXQQ43IA.js.br +0 -0
  74. package/dist/chunk-WXQQ43IA.js.gz +0 -0
  75. package/dist/{chunk-AMRT3AE4.mjs → chunk-XWUMM2TX.mjs} +44 -1
  76. package/dist/chunk-XWUMM2TX.mjs.br +0 -0
  77. package/dist/{chunk-AMRT3AE4.mjs.gz → chunk-XWUMM2TX.mjs.gz} +0 -0
  78. package/dist/{chunk-GR6SJJIT.js → chunk-Y2B5EZEV.js} +1080 -518
  79. package/dist/chunk-Y2B5EZEV.js.br +0 -0
  80. package/dist/chunk-Y2B5EZEV.js.gz +0 -0
  81. package/dist/i18n.js +4 -4
  82. package/dist/i18n.js.br +0 -0
  83. package/dist/i18n.js.gz +0 -0
  84. package/dist/i18n.mjs +1 -1
  85. package/dist/i18n.mjs.br +0 -0
  86. package/dist/i18n.mjs.gz +0 -0
  87. package/dist/index.d.ts +7 -0
  88. package/dist/index.js +47 -47
  89. package/dist/index.js.br +0 -0
  90. package/dist/index.js.gz +0 -0
  91. package/dist/index.mjs +6 -6
  92. package/dist/index.mjs.br +0 -0
  93. package/dist/index.mjs.gz +0 -0
  94. package/dist/internals.d.ts +176 -5
  95. package/dist/internals.d.ts.map +1 -1
  96. package/dist/internals.js +79 -79
  97. package/dist/internals.js.br +0 -0
  98. package/dist/internals.js.gz +0 -0
  99. package/dist/internals.mjs +4 -4
  100. package/dist/internals.mjs.br +0 -0
  101. package/dist/internals.mjs.gz +0 -0
  102. package/dist/pptx-viewer.css +1 -1
  103. package/dist/pptx-viewer.css.br +0 -0
  104. package/dist/pptx-viewer.css.gz +0 -0
  105. package/dist/{useViewerBuildingBlocks-X1L8BjsQ.d.ts → useViewerBuildingBlocks-f6oNGKMX.d.ts} +8 -1
  106. package/dist/useViewerBuildingBlocks-f6oNGKMX.d.ts.map +1 -0
  107. package/dist/viewer/index.js +27 -27
  108. package/dist/viewer/index.js.br +0 -0
  109. package/dist/viewer/index.js.gz +0 -0
  110. package/dist/viewer/index.mjs +6 -6
  111. package/dist/viewer/index.mjs.br +0 -0
  112. package/dist/viewer/index.mjs.gz +0 -0
  113. package/package.json +1 -1
  114. package/dist/AiChatPanel-BNFDBP4S.mjs.br +0 -0
  115. package/dist/AiChatPanel-BNFDBP4S.mjs.gz +0 -0
  116. package/dist/AiChatPanel-WNQCTQB5.js.br +0 -0
  117. package/dist/AiChatPanel-WNQCTQB5.js.gz +0 -0
  118. package/dist/Area3DChartScene-FXBSLIGX.js.br +0 -0
  119. package/dist/Area3DChartScene-FXBSLIGX.js.gz +0 -0
  120. package/dist/Area3DChartScene-SAQVRYOH.mjs.gz +0 -0
  121. package/dist/Bar3DChartScene-7HVUTP2E.js.br +0 -0
  122. package/dist/Bar3DChartScene-7HVUTP2E.js.gz +0 -0
  123. package/dist/Bar3DChartScene-LUA6E2K6.mjs.br +0 -3
  124. package/dist/Bar3DChartScene-LUA6E2K6.mjs.gz +0 -0
  125. package/dist/Line3DChartScene-IW4JGH57.mjs.gz +0 -0
  126. package/dist/Line3DChartScene-OVPULUTF.js.br +0 -0
  127. package/dist/Line3DChartScene-OVPULUTF.js.gz +0 -0
  128. package/dist/Model3DScene-5KP6BVCV.js.br +0 -0
  129. package/dist/Model3DScene-5KP6BVCV.js.gz +0 -0
  130. package/dist/Model3DScene-BERTZYCJ.mjs.br +0 -0
  131. package/dist/Model3DScene-BERTZYCJ.mjs.gz +0 -0
  132. package/dist/PieChart3DScene-3R2ETTGA.js.br +0 -0
  133. package/dist/PieChart3DScene-3R2ETTGA.js.gz +0 -0
  134. package/dist/PieChart3DScene-O6FFK5L7.mjs.br +0 -0
  135. package/dist/PieChart3DScene-O6FFK5L7.mjs.gz +0 -0
  136. package/dist/SurfaceChart3DScene-OCR26R5D.mjs.br +0 -0
  137. package/dist/SurfaceChart3DScene-OCR26R5D.mjs.gz +0 -0
  138. package/dist/SurfaceChart3DScene-TGFAOLHL.js.br +0 -0
  139. package/dist/SurfaceChart3DScene-TGFAOLHL.js.gz +0 -0
  140. package/dist/chunk-2FTJAMFA.mjs.br +0 -0
  141. package/dist/chunk-2FTJAMFA.mjs.gz +0 -0
  142. package/dist/chunk-3B5FRKYU.mjs.br +0 -0
  143. package/dist/chunk-3B5FRKYU.mjs.gz +0 -0
  144. package/dist/chunk-3P7FYHJH.js.br +0 -0
  145. package/dist/chunk-44CQ67GQ.js.br +0 -0
  146. package/dist/chunk-44CQ67GQ.js.gz +0 -0
  147. package/dist/chunk-AMRT3AE4.mjs.br +0 -0
  148. package/dist/chunk-DM2IZCSD.mjs.br +0 -0
  149. package/dist/chunk-DM2IZCSD.mjs.gz +0 -0
  150. package/dist/chunk-FSQCEAMG.js.br +0 -0
  151. package/dist/chunk-FSQCEAMG.js.gz +0 -0
  152. package/dist/chunk-GR6SJJIT.js.br +0 -0
  153. package/dist/chunk-GR6SJJIT.js.gz +0 -0
  154. package/dist/chunk-ITN5NYYM.mjs.br +0 -0
  155. package/dist/chunk-ITN5NYYM.mjs.gz +0 -0
  156. package/dist/chunk-K6R2JNCK.js.br +0 -0
  157. package/dist/chunk-K6R2JNCK.js.gz +0 -0
  158. package/dist/chunk-QEEU4S4Z.mjs.br +0 -0
  159. package/dist/chunk-QEEU4S4Z.mjs.gz +0 -0
  160. package/dist/chunk-QKSYKQEL.js.br +0 -0
  161. package/dist/chunk-QKSYKQEL.js.gz +0 -0
  162. package/dist/useViewerBuildingBlocks-X1L8BjsQ.d.ts.map +0 -1
@@ -1,12 +1,12 @@
1
- import { computeFocusTargets, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs, applyElementUpdate } from './chunk-2FTJAMFA.mjs';
2
- import { useViewerOptions, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useLayoutSwitching, ViewerOptionsContext, useYjsDocumentSync, useCollaborationLivePatch, useFollowMode, useBroadcastFollower, scopeLayoutOptionsToActiveSlide, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, useCollaborativeState, useViewerOptionsContext, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP } from './chunk-QEEU4S4Z.mjs';
3
- import { MIN_ELEMENT_SIZE, DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, getImageSurfaceStyle, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, SHAPE_PRESETS, ANIMATION_PRESET_OPTIONS, DEFAULT_FILL_COLOR, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getImageSurfaceMaskStyle, getCropShapeClipPath, getImageTilingStyle, getDuotoneColors, getTextWarpStyle, renderTextSegments, buildReactChartViewModel, renderChartElement, buildTextBody3DSceneStyle, SLIDE_NAV_THUMBNAIL_WIDTH, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, TOOLBAR_SECTIONS, DEFAULT_SECTION_GROUP_ID, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, HYPERLINK_COLOR, GRID_SIZE, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, THEME_COLOR_SWATCHES, STROKE_DASH_OPTIONS } from './chunk-ITN5NYYM.mjs';
4
- import { hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, getElementTransform, getAriaRoleDescription, getAriaLabel, getAriaRole, resolveElementInteractivity, isEditableTextElement, isElementRendered, isElementActionable, getImageEffectsOpacity, getImageEffectsFilter, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, ACTION_BUTTON_PRESETS, mediaTransportVisible, isInkElement, getGroupChildParentFill, getElementLabel, SWITCHABLE_LAYOUT_TYPES, compileEquationTemplateMathMl, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, resolveAutosaveActivation, viewerOptionsToPreferences, applyPreferenceToOptions, listAutosaveSnapshots, deleteAutosaveSnapshot, resolveExpiredAutosaveSnapshots, resolveHistoryDepth, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, resolve3DRenderingFlags, paintedStrokeWidth, buildCssGradientFromShapeStyle, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, getComputedEffectStyle, getSoftEdgeSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, isImageLikeElement, getComputedFillStyle, strokeOutlineViewBox, revealedSmartArtNodeCount, buildSmartArtA11y, computeSmartArtElementLayout, flattenNodes, buildSummaryZoomView, isImageTiled, getImageColorWashStyle, placeCaretAtEnd, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, resolveChartKind, ensureChartInteractionStyles, applyChartPartHighlight, applyChartBuildReveal, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, isWedgeCalloutPresetShape, RULER_THICKNESS, RULER_FONT_SIZE, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, hiddenSlideCue, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, themeToCssVars, shouldClearAutosaveCacheOnClose, applyMotionPathPreset, resetSlideLayoutPath, DEFAULT_INSERT_CHART_KIND, hasCopyableFormat, templateSchemeFromTheme, createBackstagePresentation, playFeedbackSound, shouldDiscardAutosaveOnSuccessfulSave, setMasterViewBackgroundColor, printPropertiesFrameSlides, printPropertiesSlidesPerPage, VIEWER_OPTIONS_TABS, DEFAULT_QUICK_ACCESS_COMMAND_IDS, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, DEFAULT_PALETTE2, resolvePalette, computeDrawingViewBox, projectDrawingShapes, styleShadowFilter, resolveDrawingShapeNodeId, buildChromeStyle, modelDataToBlobUrl, getImageSvgFilters, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, findChartPartTarget, advanceChartValueDrag, beginChartValueDrag, buildSurfaceChart3DDataForElement, buildBarChart3DDataForElement, buildLineChart3DDataForElement, buildAreaChart3DDataForElement, buildPieChart3DDataForElement, withChartTitle, buildSmartArt3DModel, extractPathPoints, generatePressureCircles, generateNibMarks, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, openUrlInNewTab, getSubstituteFontFamily, getWarpPath, getSlideBackgroundStyle, filterCommands, resolveTitleBarStatusKey, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, resolveScreenTip, masterViewBackgroundColor, buildFieldSubstitutionContext, shouldConfirmExternalHyperlink, safeOpenUrl, resolvePresentationAction, isPpactionUrl, parsePpactionUrl, isPresentationAdvanceClick, toggleBlackboard, PRESENT_TOOLBAR_CLASSES, buildContextMenuEntries, themeColorSchemesEqual, EXPANDED_MAX_HEIGHT, STATUS_BAR_CLASSES, buildBarActions, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, clampPercent2, resolveDefaultPrintSettings, HANDOUT_OPTIONS, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS, resolveViewerAddinRows, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, CUSTOM_FONT_ACCEPT, activateModalFocus, buildCollaborationShareUrl, buildActiveSessionUsers, SORTER_MIN_ZOOM, SORTER_ZOOM_STEP, SORTER_MAX_ZOOM, canGoPrevious, formatSlideCounter, READING_VIEW_COUNTER_ATTR, canGoNext, READING_VIEW_ATTR, OUTLINE_LEVEL_ATTR, OUTLINE_SLIDE_ATTR, OUTLINE_ROW_ATTR, OUTLINE_VIEW_ATTR, mobileElapsedSince, nextPresentedSlide, presenterPrevDisabled, presenterNextDisabled, formatMobileElapsed, mobileSlideCounter, presenterPaneAdvancesOnClick, presenterTimerProgress, PRESENTER_CONSOLE_CLASSES, formatElapsed, centeredSvgTextLines, computeInlineEditorRect, findSmartArtNodeText, setSmartArtNodeStyle, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, updateSmartArtNodeText, groupIntoParagraphs, substituteFieldText, extraQuickAccessCommands, TAB_ROW_ACTION_CLASSES, listBackstageRecentFiles, BACKSTAGE_NAV, COMMON_FONT_SIZES, INSERT_CHART_TYPES, CHARACTER_SPACING_OPTIONS, RIBBON_SHAPE_SWATCHES, shapeFillChange, shapeOutlineChange, readRibbonTransitionDraft, ribbonTransitionUpdates, readSoundFileAsDataUrl, applyTransitionSoundFile, playSlideTransitionPreview, RIBBON_TRANSITION_PRESETS, transitionSoundOptions, transitionSoundSelectedValue, DEFAULT_MOTION_PATH_PRESET_ID, SLIDE_SHOW_OPTIONS, slideShowOptionChange, readSlideShowOption, SLIDE_VIRTUALIZATION_THRESHOLD, PRESENTATION_HIT_TEST_CSS, PRESENTATION_STAGE_ATTRIBUTE, getSlideTransitionAnimations, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, SLIDE_TRANSITION_KEYFRAMES, buildStrokePathD, cursorForTool, annotationOverlayZIndex, presentationInkPath, resolveNotesSchematicBodyFontSizePx, motionPathFor, setMotionPath, getShapeAdjustmentHandleDescriptors, PRESENTER_NAVIGATOR_LABEL_KEYS, PEN_COLORS, HIGHLIGHTER_COLORS, isBlackboardActive, slideSizeToCanvasPx, resolveSelectionPaneRename, PRESET_THEMES, resolveNotesSegments, segmentsToEditorHtml, DEBOUNCE_MS, createPlainNotesSegments, parseSegmentsFromRichEditor, segmentsToPlainText, getCurrentParagraphIndex, segmentsToParagraphs, paragraphsToSegments, MAX_INDENT_LEVEL, INDENT_PX, isUrlSafe, buildNotesPrintHtml, toggleSheet, SMARTART_PREVIEW_ELEMENT_HEIGHT, SMARTART_PREVIEW_ELEMENT_WIDTH, buildSmartArtPreviewElement, sanitizeMathMl, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, downloadBlob, clampOptionNumber, QUICK_ACCESS_COMMAND_CATALOG, registerCustomFont, openReadingView, applyReadingViewCommand, createPresentationKeyBuffer, readingViewFitScale, READING_VIEW_STAGE_ATTR, buildOutline, applyOutlineEdit, mapOutlineKey, notesSegmentsToSpans, erasePresentationInkAt, movePresenterPointer, appendPresentationInkPoint, PRESENTER_CONSOLE_CONTROLS, NOTES_FONT_SIZE_DEFAULT, formatTime, NOTES_FONT_SIZE_MIN, clampNotesFontSize, NOTES_FONT_SIZE_STEP, NOTES_FONT_SIZE_MAX, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, resolveDefaultFontFamily, buildFontCatalog, canGroupSelection, canUngroupSelection, canSetStrokeWidth, strokeWidthOf, TRANSITION_SOUND_OTHER_VALUE, TRANSITION_SOUND_NONE_VALUE, clearTransitionSound, ENTRANCE_PRESET_VALUES, EMPHASIS_PRESET_VALUES, EXIT_PRESET_VALUES, MOTION_PATH_FAMILIES, motionPathFamilyLabelKey, motionPathPresetsByFamily, motionPathPresetLabelKey, masterViewPseudoSlide, authorConnectorBetweenSites, findEraserHitElementId, generateTicks, rulerDragToGuidePosition, getElementTransformWithoutRotation, buildCommentMarkers, COMMENT_MARKER_SIZE, collectConnectorSiteCandidates, getConnectorEndpointHandles, findConnectorSiteNear, motionPathToSvgD, motionPathEndPixel, isEditableMotionPath, setMotionPathEnd, themeColorLabel, buildThemeColorGrid, THEME_COLOR_SCHEME_KEYS, COMMON_FONTS, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, isCurrentLayout, SLIDE_TEMPLATES, computeAnchoredPopupPosition, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, isElementLocked, mergeSlideTransition, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, buildLayoutPreviewGeometry, buildSlideTemplateContent, elementLockTogglePatch, buildTableDataGrid, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, applyTableStylePreset, evenColumnWidths, redistributeColumnWidth, evenRowHeights, patchChartData, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, buildOleObjectNamePatch, getOleObjectTypeLabel, sanitizeGradientStops, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, resolveSlideSizeSelection, SLIDE_SIZE_PRESETS, TRANSITION_VALID_DIRECTIONS, TRANSITION_ORIENTATION_TYPES, clampTransitionNumber, TRANSITION_SPEED_OPTIONS, TRANSITION_MORPH_OPTIONS, flattenTagCollections, resolveTemplateBackgroundRows, formatCommentTimestamp, buildAnimationTimelineRows, clearMotionPath, getEffectSoundState, setEffectSound, setAfterAnimation, setAfterAnimationColor, DIRECTIONAL_PRESETS, buildAnimationTimelineBars, motionPathPresetIdForPath, computeMergeCellRight, computeMergeCellDown, computeSplitCell, CHART_TYPE_OPTIONS, isSeriesUsingSecondaryAxis, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, addSmartArtNodeAsChild, removeSmartArtNode, addSiblingAfter, removeEmptyNode, demote, promote, reorder, clampCropValue, DUOTONE_PRESETS, ARTISTIC_EFFECTS, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, toSlideIndex, elementActionToPptxAction, canCommitActionType, slideSizeFromPreset, withSlideSizeOrientation, TRANSITION_DIR_ARROWS, buildDirectionGrid, updateTagInCollections, deleteTagFromCollections, addTagToCollections, commentTextSegments, COMMENT_MENTION_CLASS, COMMENT_MENTION_ATTRIBUTE, reorderAnimationTimelineRows, applyAnimationTimelineOrder, animationEffectLabel, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, switchSmartArtLayout, SHAPE_QUICK_STYLES, quickStyleSwatchCss, PATTERN_PRESET_OPTIONS, getPatternSvg, COMPOUND_LINE_OPTIONS, LINE_JOIN_OPTIONS, LINE_CAP_OPTIONS, TEXT_WARP_PRESETS, warpPreviewPath, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS } from './chunk-DM2IZCSD.mjs';
5
- import { LOCALE_CATALOG, translationsEn } from './chunk-AMRT3AE4.mjs';
1
+ import { computeFocusTargets, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs, applyElementUpdate } from './chunk-IJLTDBXT.mjs';
2
+ import { useViewerOptions, useReadOnlyRecommendationState, useCompatibilityToastsState, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useViewPreferencesSync, useLayoutSwitching, ViewerOptionsContext, useYjsDocumentSync, useCollaborationLivePatch, useFollowMode, useBroadcastFollower, safePrompt, scopeLayoutOptionsToActiveSlide, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, useCollaborativeState, useViewerOptionsContext, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, syncSelectionHandleOverlay } from './chunk-QEAU2XTI.mjs';
3
+ import { MIN_ELEMENT_SIZE, DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, getImageSurfaceStyle, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, SHAPE_PRESETS, ANIMATION_PRESET_OPTIONS, DEFAULT_FILL_COLOR, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getImageSurfaceMaskStyle, getCropShapeClipPath, getImageTilingStyle, getDuotoneColors, getTextWarpStyle, renderTextSegments, buildReactChartViewModel, renderChartElement, buildTextBody3DSceneStyle, SLIDE_NAV_THUMBNAIL_WIDTH, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, TOOLBAR_SECTIONS, DEFAULT_SECTION_GROUP_ID, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, HYPERLINK_COLOR, GRID_SIZE, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, THEME_COLOR_SWATCHES, STROKE_DASH_OPTIONS } from './chunk-4YGGPPJZ.mjs';
4
+ import { hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, getElementTransform, getAriaRoleDescription, getAriaLabel, getAriaRole, resolveElementInteractivity, isEditableTextElement, isElementRendered, isElementActionable, getImageEffectsOpacity, getImageEffectsFilter, inlineElementPointerEvents, isHollowShapeElement, LINK_TOOLTIP_HOST_CLASS, ACTION_BUTTON_PRESETS, mediaTransportVisible, isInkElement, getGroupChildParentFill, getElementLabel, SWITCHABLE_LAYOUT_TYPES, compileEquationTemplateMathMl, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, resolveAutosaveActivation, viewerOptionsToPreferences, applyPreferenceToOptions, listAutosaveSnapshots, deleteAutosaveSnapshot, resolveExpiredAutosaveSnapshots, resolveHistoryDepth, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, resolve3DRenderingFlags, paintedStrokeWidth, buildCssGradientFromShapeStyle, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, getComputedEffectStyle, getSoftEdgeSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, isImageLikeElement, getComputedFillStyle, strokeOutlineViewBox, revealedSmartArtNodeCount, buildSmartArtA11y, computeSmartArtElementLayout, flattenNodes, buildSummaryZoomView, isImageTiled, getImageColorWashStyle, placeCaretAtEnd, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, resolveChartKind, ensureChartInteractionStyles, applyChartPartHighlight, applyChartBuildReveal, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, isWedgeCalloutPresetShape, RULER_THICKNESS, RULER_FONT_SIZE, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, hiddenSlideCue, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, themeToCssVars, shouldClearAutosaveCacheOnClose, masterViewCrudActions, applyMasterViewCrudAction, masterViewCrudFailureKey, applyMotionPathPreset, resetSlideLayoutPath, DEFAULT_INSERT_CHART_KIND, hasCopyableFormat, templateSchemeFromTheme, createBackstagePresentation, playFeedbackSound, shouldDiscardAutosaveOnSuccessfulSave, setMasterViewBackgroundColor, compatToastStackStyle, printPropertiesFrameSlides, printPropertiesSlidesPerPage, VIEWER_OPTIONS_TABS, DEFAULT_QUICK_ACCESS_COMMAND_IDS, isHeaderFooterDateTextVisible, isHeaderFooterHeaderTextVisible, isHeaderFooterFooterTextVisible, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, elementIdSelector, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, DEFAULT_PALETTE2, resolvePalette, computeDrawingViewBox, projectDrawingShapes, styleShadowFilter, resolveDrawingShapeNodeId, buildChromeStyle, modelDataToBlobUrl, getImageSvgFilters, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, findChartPartTarget, advanceChartValueDrag, beginChartValueDrag, buildSurfaceChart3DDataForElement, buildBarChart3DDataForElement, buildLineChart3DDataForElement, buildAreaChart3DDataForElement, buildPieChart3DDataForElement, withChartTitle, buildSmartArt3DModel, extractPathPoints, generatePressureCircles, generateNibMarks, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, openUrlInNewTab, getSubstituteFontFamily, getWarpPath, getSlideBackgroundStyle, pushRecentColor, mruColorsPatch, filterCommands, resolveTitleBarStatusKey, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, resolveScreenTip, masterViewBackgroundColor, buildFieldSubstitutionContext, shouldConfirmExternalHyperlink, safeOpenUrl, resolvePresentationAction, isPpactionUrl, parsePpactionUrl, isPresentationAdvanceClick, toggleBlackboard, PRESENT_TOOLBAR_CLASSES, buildContextMenuEntries, themeColorSchemesEqual, EXPANDED_MAX_HEIGHT, STATUS_BAR_CLASSES, buildBarActions, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, clampPercent2, resolveDefaultPrintSettings, HANDOUT_OPTIONS, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS, resolveViewerAddinRows, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, CUSTOM_FONT_ACCEPT, activateModalFocus, buildCollaborationShareUrl, buildActiveSessionUsers, SORTER_MIN_ZOOM, SORTER_ZOOM_STEP, SORTER_MAX_ZOOM, canGoPrevious, formatSlideCounter, READING_VIEW_COUNTER_ATTR, canGoNext, READING_VIEW_ATTR, OUTLINE_LEVEL_ATTR, OUTLINE_SLIDE_ATTR, OUTLINE_ROW_ATTR, OUTLINE_VIEW_ATTR, mobileElapsedSince, nextPresentedSlide, presenterPrevDisabled, presenterNextDisabled, formatMobileElapsed, mobileSlideCounter, presenterPaneAdvancesOnClick, presenterTimerProgress, PRESENTER_CONSOLE_CLASSES, formatElapsed, centeredSvgTextLines, computeInlineEditorRect, findSmartArtNodeText, setSmartArtNodeStyle, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, updateSmartArtNodeText, groupIntoParagraphs, substituteFieldText, extraQuickAccessCommands, TAB_ROW_ACTION_CLASSES, listBackstageRecentFiles, BACKSTAGE_NAV, COMMON_FONT_SIZES, INSERT_CHART_TYPES, CHARACTER_SPACING_OPTIONS, shapeFillChange, shapeOutlineChange, readRibbonTransitionDraft, ribbonTransitionUpdates, readSoundFileAsDataUrl, applyTransitionSoundFile, playSlideTransitionPreview, RIBBON_TRANSITION_PRESETS, transitionSoundOptions, transitionSoundSelectedValue, DEFAULT_MOTION_PATH_PRESET_ID, SLIDE_SHOW_OPTIONS, slideShowOptionChange, readSlideShowOption, SLIDE_VIRTUALIZATION_THRESHOLD, PRESENTATION_HIT_TEST_CSS, PRESENTATION_STAGE_ATTRIBUTE, getSlideTransitionAnimations, MORPH_CROSSFADE_GROUP_STYLE, MORPH_CROSSFADE_HALF_STYLE, SLIDE_TRANSITION_KEYFRAMES, buildStrokePathD, cursorForTool, annotationOverlayZIndex, presentationInkPath, resolveNotesSchematicBodyFontSizePx, motionPathFor, setMotionPath, getShapeAdjustmentHandleDescriptors, PRESENTER_NAVIGATOR_LABEL_KEYS, PEN_COLORS, HIGHLIGHTER_COLORS, isBlackboardActive, scaleSlidesForSizeChange, slideSizeToCanvasPx, resolveSelectionPaneRename, PRESET_THEMES, resolveNotesSegments, segmentsToEditorHtml, DEBOUNCE_MS, createPlainNotesSegments, parseSegmentsFromRichEditor, segmentsToPlainText, getCurrentParagraphIndex, segmentsToParagraphs, paragraphsToSegments, MAX_INDENT_LEVEL, INDENT_PX, isUrlSafe, buildNotesPrintHtml, toggleSheet, SMARTART_PREVIEW_ELEMENT_HEIGHT, SMARTART_PREVIEW_ELEMENT_WIDTH, buildSmartArtPreviewElement, sanitizeMathMl, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, downloadBlob, clampOptionNumber, QUICK_ACCESS_COMMAND_CATALOG, registerCustomFont, openReadingView, applyReadingViewCommand, createPresentationKeyBuffer, readingViewFitScale, READING_VIEW_STAGE_ATTR, buildOutline, applyOutlineEdit, mapOutlineKey, notesSegmentsToSpans, erasePresentationInkAt, movePresenterPointer, appendPresentationInkPoint, PRESENTER_CONSOLE_CONTROLS, NOTES_FONT_SIZE_DEFAULT, formatTime, NOTES_FONT_SIZE_MIN, clampNotesFontSize, NOTES_FONT_SIZE_STEP, NOTES_FONT_SIZE_MAX, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, resolveDefaultFontFamily, buildFontCatalog, RIBBON_SHAPE_SWATCHES, canGroupSelection, canUngroupSelection, canSetStrokeWidth, strokeWidthOf, TRANSITION_SOUND_OTHER_VALUE, TRANSITION_SOUND_NONE_VALUE, clearTransitionSound, ENTRANCE_PRESET_VALUES, EMPHASIS_PRESET_VALUES, EXIT_PRESET_VALUES, MOTION_PATH_FAMILIES, motionPathFamilyLabelKey, motionPathPresetsByFamily, motionPathPresetLabelKey, masterViewPseudoSlide, authorConnectorBetweenSites, findEraserHitElementId, generateTicks, rulerDragToGuidePosition, getElementTransformWithoutRotation, getActiveXControlOverlayView, buildCommentMarkers, COMMENT_MARKER_SIZE, collectConnectorSiteCandidates, getConnectorEndpointHandles, findConnectorSiteNear, motionPathToSvgD, motionPathEndPixel, isEditableMotionPath, setMotionPathEnd, themeColorLabel, buildThemeColorGrid, THEME_COLOR_SCHEME_KEYS, COMMON_FONTS, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, isCurrentLayout, SLIDE_TEMPLATES, computeAnchoredPopupPosition, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, isElementLocked, mergeSlideTransition, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, buildLayoutPreviewGeometry, buildSlideTemplateContent, elementLockTogglePatch, buildTableDataGrid, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, applyTableStylePreset, evenColumnWidths, redistributeColumnWidth, evenRowHeights, patchChartData, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, buildOleObjectNamePatch, getOleObjectTypeLabel, sanitizeGradientStops, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, resolveSlideSizeSelection, SLIDE_SIZE_PRESETS, TRANSITION_VALID_DIRECTIONS, TRANSITION_ORIENTATION_TYPES, clampTransitionNumber, TRANSITION_SPEED_OPTIONS, TRANSITION_MORPH_OPTIONS, flattenTagCollections, resolveTemplateBackgroundRows, formatCommentTimestamp, commentMentionQuery, matchCommentMentionAuthors, buildAnimationTimelineRows, clearMotionPath, getEffectSoundState, setEffectSound, setAfterAnimation, setAfterAnimationColor, DIRECTIONAL_PRESETS, buildAnimationTimelineBars, motionPathPresetIdForPath, computeMergeCellRight, computeMergeCellDown, computeSplitCell, CHART_TYPE_OPTIONS, BAR3D_SHAPE_OPTIONS, bar3DShapePatch, RADAR_STYLE_OPTIONS, radarStylePatch, SURFACE_WIREFRAME_OPTIONS, surfaceWireframePatch, isSeriesUsingSecondaryAxis, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, addSmartArtNodeAsChild, removeSmartArtNode, addSiblingAfter, removeEmptyNode, demote, promote, reorder, clampCropValue, DUOTONE_PRESETS, ARTISTIC_EFFECTS, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, elementActionToPptxAction, canCommitActionType, slideSizeFromPreset, withSlideSizeOrientation, TRANSITION_DIR_ARROWS, buildDirectionGrid, updateTagInCollections, deleteTagFromCollections, addTagToCollections, commentTextSegments, COMMENT_MENTION_CLASS, COMMENT_MENTION_ATTRIBUTE, insertCommentMention, reorderAnimationTimelineRows, applyAnimationTimelineOrder, animationEffectLabel, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, switchSmartArtLayout, SHAPE_QUICK_STYLES, quickStyleSwatchCss, PATTERN_PRESET_OPTIONS, getPatternSvg, COMPOUND_LINE_OPTIONS, LINE_JOIN_OPTIONS, LINE_CAP_OPTIONS, TEXT_WARP_PRESETS, warpPreviewPath, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, toSlideIndex, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS } from './chunk-PADP3NUM.mjs';
5
+ import { LOCALE_CATALOG, translationsEn } from './chunk-XWUMM2TX.mjs';
6
6
  import React19, { createContext, useMemo, useState, useCallback, lazy, forwardRef, useEffect, useRef, Suspense, useLayoutEffect, useContext, Fragment as Fragment$1, useDeferredValue } from 'react';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
8
  import { useTranslation } from 'react-i18next';
9
- import { LuRotateCw, LuMessageSquare, LuEyeOff, LuHistory, LuTrash2, LuSettings, LuX, LuCalendarDays, LuHash, LuText, LuCast, LuSave, LuUndo, LuRedo, LuSearch, LuShieldCheck, LuPlus, LuPanelLeftClose, LuStickyNote, LuMonitor, LuColumns2, LuPresentation, LuMinus, LuSettings2, LuLayers, LuClock, LuDownload, LuCheck, LuLock, LuEye, LuFileText, LuType, LuLoader, LuShieldAlert, LuSignature, LuInfo, LuTriangleAlert, LuPrinter, LuPenTool, LuBug, LuChevronUp, LuChevronDown, LuUpload, LuWifi, LuWifiOff, LuUsers, LuCopy, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuZoomOut, LuZoomIn, LuSpellCheck, LuFileDown, LuMenu, LuSparkles, LuShare2, LuPanelLeft, LuPanelRight, LuArrowLeft, LuFolderOpen, LuClipboardPaste, LuScissors, LuPaintbrush, LuSquare, LuImage, LuVideo, LuDatabase, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuReplace, LuMousePointer2, LuShapes, LuPaintBucket, LuPenLine, LuPalette, LuPencil, LuStar, LuMoveRight, LuMousePointerClick, LuClock3, LuMonitorPlay, LuListVideo, LuCaptions, LuCamera, LuEraser, LuRotateCcw, LuCircleHelp, LuBookOpen, LuLanguages, LuGlobe, LuGitCompare, LuMessageSquarePlus, LuLockKeyhole, LuPanelTop, LuLayoutGrid, LuGrid3X3, LuPipette, LuRuler, LuMaximize2, LuCode, LuCaseSensitive, LuTimer, LuGripVertical, LuLoaderCircle, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuScan, LuMonitorOff, LuCirclePlay, LuCirclePause, LuArrowLeftRight, LuClipboardCopy, LuWand, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuFilePlus2, LuHouse, LuFileJson, LuBox, LuFileImage, LuUser, LuHardDrive, LuLogIn, LuLayoutTemplate, LuFolderPlus, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuColumns3, LuSpline, LuAlignHorizontalSpaceAround, LuAlignVerticalSpaceAround, LuGroup, LuUngroup, LuMove, LuRadio, LuLockOpen, LuArrowDown, LuArrowUp, LuArrowRight, LuReply, LuBookmark } from 'react-icons/lu';
9
+ import { LuRotateCw, LuMessageSquare, LuEyeOff, LuHistory, LuTrash2, LuSettings, LuX, LuCalendarDays, LuClock, LuHash, LuFileText, LuText, LuCast, LuSave, LuUndo, LuRedo, LuSearch, LuShieldCheck, LuPlus, LuPanelLeftClose, LuStickyNote, LuMonitor, LuColumns2, LuPresentation, LuMinus, LuSettings2, LuLayers, LuDownload, LuCheck, LuLock, LuEye, LuType, LuLoader, LuShieldAlert, LuSignature, LuInfo, LuTriangleAlert, LuPrinter, LuPenTool, LuBug, LuChevronUp, LuChevronDown, LuUpload, LuWifi, LuWifiOff, LuUsers, LuCopy, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuZoomOut, LuZoomIn, LuSpellCheck, LuFileDown, LuMenu, LuSparkles, LuShare2, LuPanelLeft, LuPanelRight, LuArrowLeft, LuFolderOpen, LuClipboardPaste, LuScissors, LuPaintbrush, LuSquare, LuImage, LuVideo, LuDatabase, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuReplace, LuMousePointer2, LuShapes, LuPaintBucket, LuPenLine, LuPalette, LuPencil, LuStar, LuMoveRight, LuMousePointerClick, LuClock3, LuMonitorPlay, LuListVideo, LuCaptions, LuCamera, LuEraser, LuRotateCcw, LuCircleHelp, LuBookOpen, LuLanguages, LuGlobe, LuGitCompare, LuMessageSquarePlus, LuLockKeyhole, LuPanelTop, LuLayoutGrid, LuGrid3X3, LuPipette, LuRuler, LuMaximize2, LuCode, LuCaseSensitive, LuTimer, LuGripVertical, LuLoaderCircle, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuScan, LuMonitorOff, LuCirclePlay, LuCirclePause, LuArrowLeftRight, LuClipboardCopy, LuWand, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuFilePlus2, LuHouse, LuFileJson, LuBox, LuFileImage, LuUser, LuHardDrive, LuLogIn, LuLayoutTemplate, LuFolderPlus, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuColumns3, LuSpline, LuAlignHorizontalSpaceAround, LuAlignVerticalSpaceAround, LuGroup, LuUngroup, LuMove, LuRadio, LuLockOpen, LuArrowDown, LuArrowUp, LuArrowRight, LuReply, LuBookmark } from 'react-icons/lu';
10
10
 
11
11
  var ViewerThemeContext = createContext(void 0);
12
12
  function ViewerThemeProvider({ theme, children }) {
@@ -514,7 +514,7 @@ function FailedToLoad() {
514
514
  var LazyArea3DChartScene = React19.lazy(
515
515
  async () => {
516
516
  try {
517
- return await import('./Area3DChartScene-SAQVRYOH.mjs');
517
+ return await import('./Area3DChartScene-DNLGOR5F.mjs');
518
518
  } catch {
519
519
  return { default: FailedToLoad };
520
520
  }
@@ -570,7 +570,7 @@ function FailedToLoad2() {
570
570
  var LazyBar3DChartScene = React19.lazy(
571
571
  async () => {
572
572
  try {
573
- return await import('./Bar3DChartScene-LUA6E2K6.mjs');
573
+ return await import('./Bar3DChartScene-VYKQAY6X.mjs');
574
574
  } catch {
575
575
  return { default: FailedToLoad2 };
576
576
  }
@@ -626,7 +626,7 @@ function FailedToLoad3() {
626
626
  var LazyLine3DChartScene = React19.lazy(
627
627
  async () => {
628
628
  try {
629
- return await import('./Line3DChartScene-IW4JGH57.mjs');
629
+ return await import('./Line3DChartScene-ZVELPNOD.mjs');
630
630
  } catch {
631
631
  return { default: FailedToLoad3 };
632
632
  }
@@ -682,7 +682,7 @@ function FailedToLoad4() {
682
682
  var LazyPieChart3DScene = React19.lazy(
683
683
  async () => {
684
684
  try {
685
- return await import('./PieChart3DScene-O6FFK5L7.mjs');
685
+ return await import('./PieChart3DScene-NNLKJ6LN.mjs');
686
686
  } catch {
687
687
  return { default: FailedToLoad4 };
688
688
  }
@@ -738,7 +738,7 @@ function FailedToLoad5() {
738
738
  var LazySurfaceChart3DScene = React19.lazy(
739
739
  async () => {
740
740
  try {
741
- return await import('./SurfaceChart3DScene-OCR26R5D.mjs');
741
+ return await import('./SurfaceChart3DScene-NWB4QAOI.mjs');
742
742
  } catch {
743
743
  return { default: FailedToLoad5 };
744
744
  }
@@ -1355,9 +1355,8 @@ function ResizeHandles({
1355
1355
  onResizePointerDown(elementId, e, handle);
1356
1356
  };
1357
1357
  const startRotate = (btn, pointerId) => {
1358
- const wrapper = document.querySelector(
1359
- `[data-element-id="${elementId}"]`
1360
- );
1358
+ const scope = btn.closest("[data-pptx-viewport]") ?? document;
1359
+ const wrapper = scope.querySelector(elementIdSelector(elementId));
1361
1360
  if (!wrapper) {
1362
1361
  return;
1363
1362
  }
@@ -1377,7 +1376,9 @@ function ResizeHandles({
1377
1376
  }
1378
1377
  deg = Math.round((deg % 360 + 360) % 360);
1379
1378
  last = deg;
1380
- wrapper.style.transform = `rotate(${deg}deg)${base}`;
1379
+ const transform = `rotate(${deg}deg)${base}`;
1380
+ wrapper.style.transform = transform;
1381
+ syncSelectionHandleOverlay(wrapper, elementId, { transform });
1381
1382
  };
1382
1383
  const onPointerMove = (ev) => apply(ev.clientX, ev.clientY, ev.shiftKey);
1383
1384
  const end = () => {
@@ -3021,7 +3022,7 @@ function FailedToLoad6() {
3021
3022
  var LazyModel3DScene = React19.lazy(
3022
3023
  async () => {
3023
3024
  try {
3024
- return await import('./Model3DScene-BERTZYCJ.mjs');
3025
+ return await import('./Model3DScene-ZJWU5IUY.mjs');
3025
3026
  } catch {
3026
3027
  return { default: FailedToLoad6 };
3027
3028
  }
@@ -6187,8 +6188,29 @@ function DesignSection(p) {
6187
6188
  )
6188
6189
  ] });
6189
6190
  }
6191
+ var DEFAULT_VALUE = {
6192
+ recentColors: [],
6193
+ pushColor: () => {
6194
+ }
6195
+ };
6196
+ var RecentColorsContext = createContext(DEFAULT_VALUE);
6197
+ var RecentColorsProvider = RecentColorsContext.Provider;
6198
+ function useRecentColors() {
6199
+ return useContext(RecentColorsContext);
6200
+ }
6190
6201
  function DrawSection(p) {
6191
6202
  const { t } = useTranslation();
6203
+ const { pushColor } = useRecentColors();
6204
+ const colorRef = useRef(null);
6205
+ useEffect(() => {
6206
+ const el = colorRef.current;
6207
+ if (!el) {
6208
+ return;
6209
+ }
6210
+ const handler = () => pushColor(el.value);
6211
+ el.addEventListener("change", handler);
6212
+ return () => el.removeEventListener("change", handler);
6213
+ }, [pushColor]);
6192
6214
  return /* @__PURE__ */ jsxs(Fragment, { children: [
6193
6215
  /* @__PURE__ */ jsx("div", { className: grp, children: DRAW_TOOLS.map((tool, i, a) => /* @__PURE__ */ jsx(
6194
6216
  "button",
@@ -6215,6 +6237,7 @@ function DrawSection(p) {
6215
6237
  /* @__PURE__ */ jsx(
6216
6238
  "input",
6217
6239
  {
6240
+ ref: colorRef,
6218
6241
  type: "color",
6219
6242
  value: p.drawingColor,
6220
6243
  onChange: (e) => p.onSetDrawingColor(e.target.value),
@@ -6279,7 +6302,7 @@ function AccountPage() {
6279
6302
  return void 0;
6280
6303
  });
6281
6304
  };
6282
- const version = "3.2.0" ;
6305
+ const version = "3.4.0" ;
6283
6306
  return /* @__PURE__ */ jsxs("div", { className: "mt-8 max-w-[700px] space-y-6", children: [
6284
6307
  /* @__PURE__ */ jsxs("section", { className: cardClass, children: [
6285
6308
  /* @__PURE__ */ jsxs("h2", { className: "flex items-center gap-2 text-sm font-semibold", children: [
@@ -7979,7 +8002,7 @@ function SlideShowSection(p) {
7979
8002
  {
7980
8003
  label: t("pptx.slideShow.fromBeginning"),
7981
8004
  icon: /* @__PURE__ */ jsx(LuPlay, {}),
7982
- onClick: () => p.onSetMode("present"),
8005
+ onClick: p.onPresentFromBeginning ?? (() => p.onSetMode("present")),
7983
8006
  title: t("pptx.slideShow.fromBeginningTooltip")
7984
8007
  }
7985
8008
  ),
@@ -8119,6 +8142,45 @@ function SlideShowSection(p) {
8119
8142
  ] })
8120
8143
  ] });
8121
8144
  }
8145
+ function RecentColorsRow({
8146
+ prefix,
8147
+ disabled,
8148
+ onCommit
8149
+ }) {
8150
+ const { t } = useTranslation();
8151
+ const { recentColors, pushColor } = useRecentColors();
8152
+ if (recentColors.length === 0) {
8153
+ return null;
8154
+ }
8155
+ return /* @__PURE__ */ jsxs(
8156
+ "div",
8157
+ {
8158
+ "data-testid": "pptx-color-recent",
8159
+ "aria-label": t("pptx.colorPicker.recentColors"),
8160
+ className: "mt-1 flex flex-wrap items-center gap-1",
8161
+ children: [
8162
+ /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground", children: t("pptx.colorPicker.recentColors") }),
8163
+ recentColors.map((c) => /* @__PURE__ */ jsx(
8164
+ "button",
8165
+ {
8166
+ type: "button",
8167
+ "data-pptx-compact": true,
8168
+ className: "h-4 w-4 rounded border border-primary",
8169
+ style: { backgroundColor: c },
8170
+ title: c,
8171
+ "aria-label": `Recent ${c}`,
8172
+ disabled,
8173
+ onClick: () => {
8174
+ onCommit(c);
8175
+ pushColor(c);
8176
+ }
8177
+ },
8178
+ `${prefix}-recent-${c}`
8179
+ ))
8180
+ ]
8181
+ }
8182
+ );
8183
+ }
8122
8184
  var LINE_SPACING_OPTIONS = [
8123
8185
  { label: "1.0", value: 1 },
8124
8186
  { label: "1.15", value: 1.15 },
@@ -8331,14 +8393,16 @@ function TextSection(p) {
8331
8393
  const changeCaseRef = useRef(null);
8332
8394
  const fontColorRef = useRef(null);
8333
8395
  const highlightMenuRef = useRef(null);
8396
+ const { pushColor } = useRecentColors();
8334
8397
  const handleColorChange = useCallback(
8335
8398
  (color) => {
8336
8399
  if (!canFormat) {
8337
8400
  return;
8338
8401
  }
8339
8402
  p.onUpdateTextStyle({ color });
8403
+ pushColor(color);
8340
8404
  },
8341
- [canFormat, p]
8405
+ [canFormat, p, pushColor]
8342
8406
  );
8343
8407
  const handleHighlightChange = useCallback(
8344
8408
  (highlightColor) => {
@@ -8346,8 +8410,9 @@ function TextSection(p) {
8346
8410
  return;
8347
8411
  }
8348
8412
  p.onUpdateTextStyle({ highlightColor });
8413
+ pushColor(highlightColor);
8349
8414
  },
8350
- [canFormat, p]
8415
+ [canFormat, p, pushColor]
8351
8416
  );
8352
8417
  return /* @__PURE__ */ jsxs(Fragment, { children: [
8353
8418
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
@@ -8695,6 +8760,14 @@ function TextSection(p) {
8695
8760
  value: currentColor,
8696
8761
  onChange: (e) => handleColorChange(e.target.value)
8697
8762
  }
8763
+ ),
8764
+ /* @__PURE__ */ jsx(
8765
+ RecentColorsRow,
8766
+ {
8767
+ prefix: "font-color",
8768
+ disabled: !canMut,
8769
+ onCommit: handleColorChange
8770
+ }
8698
8771
  )
8699
8772
  ] }) })
8700
8773
  ] }),
@@ -9343,6 +9416,7 @@ function MobileSectionBody({
9343
9416
  SlideShowSection,
9344
9417
  {
9345
9418
  onPresent: () => p.onSetMode("present"),
9419
+ onPresentFromBeginning: p.onPresentFromBeginning,
9346
9420
  onEnterPresenterView: p.onEnterPresenterView ?? (() => {
9347
9421
  }),
9348
9422
  onEnterRehearsalMode: p.onEnterRehearsalMode ?? (() => {
@@ -9541,9 +9615,55 @@ function MobileToolbar(props) {
9541
9615
  }
9542
9616
  );
9543
9617
  }
9618
+ function ShapeColorPopover({
9619
+ icon,
9620
+ title,
9621
+ prefix,
9622
+ anchorRef,
9623
+ open,
9624
+ onToggle,
9625
+ disabled,
9626
+ swatchAriaLabel,
9627
+ onApply,
9628
+ onClose
9629
+ }) {
9630
+ return /* @__PURE__ */ jsxs("div", { className: "relative", ref: anchorRef, children: [
9631
+ /* @__PURE__ */ jsx("button", { type: "button", disabled, className: pill, title, onClick: onToggle, children: icon }),
9632
+ open && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef, className: "pt-1", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl p-2", children: [
9633
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-6 gap-1", children: RIBBON_SHAPE_SWATCHES.map((c) => /* @__PURE__ */ jsx(
9634
+ "button",
9635
+ {
9636
+ type: "button",
9637
+ "aria-label": `${swatchAriaLabel} ${c}`,
9638
+ "data-pptx-compact": true,
9639
+ className: "w-5 h-5 rounded border border-border/60 hover:scale-110 transition-transform",
9640
+ style: { backgroundColor: c },
9641
+ title: c,
9642
+ onClick: () => {
9643
+ onApply(c);
9644
+ onClose();
9645
+ }
9646
+ },
9647
+ c
9648
+ )) }),
9649
+ /* @__PURE__ */ jsx(
9650
+ RecentColorsRow,
9651
+ {
9652
+ prefix,
9653
+ disabled,
9654
+ onCommit: (c) => {
9655
+ onApply(c);
9656
+ onClose();
9657
+ }
9658
+ }
9659
+ )
9660
+ ] }) })
9661
+ ] });
9662
+ }
9544
9663
  var TOP_SHAPES = SHAPE_PRESETS.slice(0, 12);
9545
9664
  function DrawingGroup(p) {
9546
9665
  const { t } = useTranslation();
9666
+ const { pushColor } = useRecentColors();
9547
9667
  const [shapesOpen, setShapesOpen] = useState(false);
9548
9668
  const [arrangeOpen, setArrangeOpen] = useState(false);
9549
9669
  const [fillOpen, setFillOpen] = useState(false);
@@ -9705,64 +9825,42 @@ function DrawingGroup(p) {
9705
9825
  )
9706
9826
  ] }) })
9707
9827
  ] }),
9708
- /* @__PURE__ */ jsxs("div", { className: "relative", ref: fillRef, children: [
9709
- /* @__PURE__ */ jsx(
9710
- "button",
9711
- {
9712
- type: "button",
9713
- disabled: !p.canEdit || !p.selectedElement,
9714
- className: pill,
9715
- title: t("pptx.drawing.shapeFill"),
9716
- onClick: () => setFillOpen((v) => !v),
9717
- children: /* @__PURE__ */ jsx(LuPaintBucket, { className: ic })
9718
- }
9719
- ),
9720
- fillOpen && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: fillRef, className: "pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl p-2 grid grid-cols-6 gap-1", children: RIBBON_SHAPE_SWATCHES.map((c) => /* @__PURE__ */ jsx(
9721
- "button",
9722
- {
9723
- type: "button",
9724
- "aria-label": `Fill colour ${c}`,
9725
- "data-pptx-compact": true,
9726
- className: "w-5 h-5 rounded border border-border/60 hover:scale-110 transition-transform",
9727
- style: { backgroundColor: c },
9728
- title: c,
9729
- onClick: () => {
9730
- p.onUpdateElementStyle?.(shapeFillChange(c));
9731
- setFillOpen(false);
9732
- }
9828
+ /* @__PURE__ */ jsx(
9829
+ ShapeColorPopover,
9830
+ {
9831
+ icon: /* @__PURE__ */ jsx(LuPaintBucket, { className: ic }),
9832
+ title: t("pptx.drawing.shapeFill"),
9833
+ prefix: "shape-fill",
9834
+ anchorRef: fillRef,
9835
+ open: fillOpen,
9836
+ onToggle: () => setFillOpen((v) => !v),
9837
+ disabled: !p.canEdit || !p.selectedElement,
9838
+ swatchAriaLabel: "Fill colour",
9839
+ onApply: (c) => {
9840
+ p.onUpdateElementStyle?.(shapeFillChange(c));
9841
+ pushColor(c);
9733
9842
  },
9734
- c
9735
- )) }) })
9736
- ] }),
9737
- /* @__PURE__ */ jsxs("div", { className: "relative", ref: outlineRef, children: [
9738
- /* @__PURE__ */ jsx(
9739
- "button",
9740
- {
9741
- type: "button",
9742
- disabled: !p.canEdit || !p.selectedElement,
9743
- className: pill,
9744
- title: t("pptx.drawing.shapeOutline"),
9745
- onClick: () => setOutlineOpen((v) => !v),
9746
- children: /* @__PURE__ */ jsx(LuPenLine, { className: ic })
9747
- }
9748
- ),
9749
- outlineOpen && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: outlineRef, className: "pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl p-2 grid grid-cols-6 gap-1", children: RIBBON_SHAPE_SWATCHES.map((c) => /* @__PURE__ */ jsx(
9750
- "button",
9751
- {
9752
- type: "button",
9753
- "aria-label": `Outline colour ${c}`,
9754
- "data-pptx-compact": true,
9755
- className: "w-5 h-5 rounded border border-border/60 hover:scale-110 transition-transform",
9756
- style: { backgroundColor: c },
9757
- title: c,
9758
- onClick: () => {
9759
- p.onUpdateElementStyle?.(shapeOutlineChange(c));
9760
- setOutlineOpen(false);
9761
- }
9843
+ onClose: () => setFillOpen(false)
9844
+ }
9845
+ ),
9846
+ /* @__PURE__ */ jsx(
9847
+ ShapeColorPopover,
9848
+ {
9849
+ icon: /* @__PURE__ */ jsx(LuPenLine, { className: ic }),
9850
+ title: t("pptx.drawing.shapeOutline"),
9851
+ prefix: "shape-outline",
9852
+ anchorRef: outlineRef,
9853
+ open: outlineOpen,
9854
+ onToggle: () => setOutlineOpen((v) => !v),
9855
+ disabled: !p.canEdit || !p.selectedElement,
9856
+ swatchAriaLabel: "Outline colour",
9857
+ onApply: (c) => {
9858
+ p.onUpdateElementStyle?.(shapeOutlineChange(c));
9859
+ pushColor(c);
9762
9860
  },
9763
- c
9764
- )) }) })
9765
- ] }),
9861
+ onClose: () => setOutlineOpen(false)
9862
+ }
9863
+ ),
9766
9864
  /* @__PURE__ */ jsx(
9767
9865
  "button",
9768
9866
  {
@@ -10666,6 +10764,7 @@ function Toolbar(p) {
10666
10764
  SlideShowSection,
10667
10765
  {
10668
10766
  onPresent: () => p.onSetMode("present"),
10767
+ onPresentFromBeginning: p.onPresentFromBeginning,
10669
10768
  onEnterPresenterView: p.onEnterPresenterView ?? (() => {
10670
10769
  }),
10671
10770
  onEnterRehearsalMode: p.onEnterRehearsalMode ?? (() => {
@@ -12153,8 +12252,6 @@ function useStableCallbacks(callbacks) {
12153
12252
  stableResizeTableRow
12154
12253
  };
12155
12254
  }
12156
- var PLACEHOLDER_WIDTH = 120;
12157
- var PLACEHOLDER_HEIGHT = 40;
12158
12255
  function ActiveXControlOverlay({
12159
12256
  controls,
12160
12257
  canvasSize,
@@ -12163,24 +12260,17 @@ function ActiveXControlOverlay({
12163
12260
  if (controls.length === 0) {
12164
12261
  return null;
12165
12262
  }
12166
- return /* @__PURE__ */ jsx("div", { className: "absolute inset-0 pointer-events-none z-[40]", children: controls.map((control, idx) => {
12167
- const width = control.width ?? PLACEHOLDER_WIDTH;
12168
- const height = control.height ?? PLACEHOLDER_HEIGHT;
12169
- const left = control.x ?? 8;
12170
- const top = control.y ?? 8 + idx * (PLACEHOLDER_HEIGHT + 6);
12171
- const clampedWidth = Math.min(width, canvasSize.width);
12172
- const clampedHeight = Math.min(height, canvasSize.height);
12173
- const imageUrl = control.fallbackImageRelId ? resolveFallbackImage?.(control.fallbackImageRelId) : void 0;
12174
- const label = control.name || "ActiveX control";
12175
- if (imageUrl) {
12263
+ return /* @__PURE__ */ jsx("div", { className: "absolute inset-0 pointer-events-none z-[40]", "data-testid": "pptx-activex-overlay", children: controls.map((control, idx) => {
12264
+ const view = getActiveXControlOverlayView(control, canvasSize, idx, resolveFallbackImage);
12265
+ if (view.className === "image" && view.imageUrl) {
12176
12266
  return /* @__PURE__ */ jsx(
12177
12267
  "img",
12178
12268
  {
12179
- src: imageUrl,
12180
- alt: label,
12181
- title: `ActiveX control: ${label}`,
12269
+ src: view.imageUrl,
12270
+ alt: view.label,
12271
+ title: `ActiveX control: ${view.label}`,
12182
12272
  className: "absolute",
12183
- style: { left, top, width: clampedWidth, height: clampedHeight }
12273
+ style: { left: view.left, top: view.top, width: view.width, height: view.height }
12184
12274
  },
12185
12275
  `${control.relId}-${idx}`
12186
12276
  );
@@ -12189,12 +12279,12 @@ function ActiveXControlOverlay({
12189
12279
  "div",
12190
12280
  {
12191
12281
  className: "absolute",
12192
- title: `ActiveX control: ${label} (interactive controls are not supported in the viewer)`,
12282
+ title: `ActiveX control: ${view.label} (interactive controls are not supported in the viewer)`,
12193
12283
  style: {
12194
- left,
12195
- top,
12196
- width: clampedWidth,
12197
- height: clampedHeight,
12284
+ left: view.left,
12285
+ top: view.top,
12286
+ width: view.width,
12287
+ height: view.height,
12198
12288
  display: "flex",
12199
12289
  alignItems: "center",
12200
12290
  justifyContent: "center",
@@ -12214,7 +12304,7 @@ function ActiveXControlOverlay({
12214
12304
  },
12215
12305
  children: [
12216
12306
  /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2699" }),
12217
- /* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: label })
12307
+ /* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: view.label })
12218
12308
  ]
12219
12309
  },
12220
12310
  `${control.relId}-${idx}`
@@ -14528,6 +14618,8 @@ function MasterViewSidebar({
14528
14618
  onSelectLayout,
14529
14619
  onCollapse,
14530
14620
  onTabChange,
14621
+ crudActions,
14622
+ onCrudAction,
14531
14623
  onHandoutSlidesPerPageChange,
14532
14624
  onNotesMasterBackgroundChange,
14533
14625
  onHandoutMasterBackgroundChange,
@@ -14607,6 +14699,19 @@ function MasterViewSidebar({
14607
14699
  }
14608
14700
  )
14609
14701
  ] }),
14702
+ masterViewTab === "slides" && canEdit && crudActions.length > 0 && /* @__PURE__ */ jsx("section", { className: "grid grid-cols-2 gap-1 rounded-md border border-border/60 p-2", children: crudActions.map((action) => /* @__PURE__ */ jsx(
14703
+ "button",
14704
+ {
14705
+ type: "button",
14706
+ "data-testid": `pptx-master-crud-${action.id}`,
14707
+ disabled: !action.enabled,
14708
+ title: action.disabledReasonKey ? t(action.disabledReasonKey) : void 0,
14709
+ onClick: () => onCrudAction(action.id),
14710
+ className: "rounded border border-border/60 px-1.5 py-1 text-[10px] hover:bg-accent/60 disabled:cursor-not-allowed disabled:opacity-40",
14711
+ children: t(action.labelKey)
14712
+ },
14713
+ action.id
14714
+ )) }),
14610
14715
  masterViewTab === "slides" && /* @__PURE__ */ jsx(
14611
14716
  SlideMastersList,
14612
14717
  {
@@ -18883,12 +18988,13 @@ function PresenterNotesRail({
18883
18988
  now,
18884
18989
  elapsed,
18885
18990
  activeCustomShow,
18991
+ authoredRange,
18886
18992
  onMove,
18887
18993
  onUpdateNotes
18888
18994
  }) {
18889
18995
  const { t } = useTranslation();
18890
18996
  const slide = slides[current];
18891
- const nextSlide = nextPresentedSlide(slides, current, activeCustomShow);
18997
+ const nextSlide = nextPresentedSlide(slides, current, activeCustomShow, authoredRange);
18892
18998
  const notesText = slide?.notes ?? "";
18893
18999
  const notesSegments = slide?.notesSegments;
18894
19000
  const [notesDraft, setNotesDraft] = useState(notesText);
@@ -19134,6 +19240,7 @@ function PresenterView({
19134
19240
  templateElements,
19135
19241
  presentationStartTime,
19136
19242
  activeCustomShow,
19243
+ authoredRange,
19137
19244
  onMovePresentationSlide,
19138
19245
  onExit,
19139
19246
  onOpenAudienceWindow,
@@ -19245,6 +19352,7 @@ function PresenterView({
19245
19352
  canvasSize,
19246
19353
  templateElements,
19247
19354
  activeCustomShow,
19355
+ authoredRange,
19248
19356
  now,
19249
19357
  elapsed,
19250
19358
  onMove: onMovePresentationSlide,
@@ -19302,6 +19410,8 @@ function MobilePresenterView({
19302
19410
  currentSlideIndex,
19303
19411
  canvasSize,
19304
19412
  templateElements,
19413
+ activeCustomShow,
19414
+ authoredRange,
19305
19415
  presentationStartTime,
19306
19416
  onMovePresentationSlide,
19307
19417
  onExit
@@ -19314,7 +19424,7 @@ function MobilePresenterView({
19314
19424
  }, []);
19315
19425
  const elapsed = mobileElapsedSince(presentationStartTime, now);
19316
19426
  const currentSlide = slides[currentSlideIndex];
19317
- const nextSlide = nextPresentedSlide(slides, currentSlideIndex);
19427
+ const nextSlide = nextPresentedSlide(slides, currentSlideIndex, activeCustomShow, authoredRange);
19318
19428
  if (!currentSlide) {
19319
19429
  return /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-card text-muted-foreground", children: t("pptx.presenter.noSlides") });
19320
19430
  }
@@ -19847,6 +19957,7 @@ function AfterAnimationRow({
19847
19957
  onColorChange
19848
19958
  }) {
19849
19959
  const { t } = useTranslation();
19960
+ const { pushColor } = useRecentColors();
19850
19961
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
19851
19962
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
19852
19963
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-[11px]", children: t("pptx.animation.afterAnimation") }),
@@ -19870,7 +19981,10 @@ function AfterAnimationRow({
19870
19981
  type: "color",
19871
19982
  "aria-label": t("pptx.animation.afterAnimation.color"),
19872
19983
  value: color ?? "#808080",
19873
- onChange: (event) => onColorChange(event.target.value),
19984
+ onChange: (event) => {
19985
+ onColorChange(event.target.value);
19986
+ pushColor(event.target.value);
19987
+ },
19874
19988
  disabled: !canEdit,
19875
19989
  className: "h-6 w-10 rounded border border-border bg-transparent p-0"
19876
19990
  }
@@ -20852,17 +20966,105 @@ var POS_FIELDS = [
20852
20966
  ["W", "width"],
20853
20967
  ["H", "height"]
20854
20968
  ];
20969
+ var URL_LABEL_KEY = {
20970
+ url: "pptx.action.gotoUrl",
20971
+ openFile: "pptx.hyperlink.actionOpenFile",
20972
+ openPresentation: "pptx.hyperlink.actionOpenPresentation"
20973
+ };
20974
+ function ActionTargetFields({
20975
+ type,
20976
+ canEdit,
20977
+ slideCount,
20978
+ customShows,
20979
+ url,
20980
+ slideIndex,
20981
+ customShowId,
20982
+ returnAfter,
20983
+ onChange
20984
+ }) {
20985
+ const { t } = useTranslation();
20986
+ const urlLabelKey = URL_LABEL_KEY[type];
20987
+ if (urlLabelKey) {
20988
+ return /* @__PURE__ */ jsx(
20989
+ "input",
20990
+ {
20991
+ type: "text",
20992
+ disabled: !canEdit,
20993
+ "aria-label": t(urlLabelKey),
20994
+ className: cn(INPUT, "w-full"),
20995
+ placeholder: "https://...",
20996
+ value: url ?? "",
20997
+ onChange: (e) => onChange({ url: e.target.value })
20998
+ }
20999
+ );
21000
+ }
21001
+ if (type === "slide") {
21002
+ return /* @__PURE__ */ jsx(
21003
+ "input",
21004
+ {
21005
+ type: "number",
21006
+ disabled: !canEdit,
21007
+ "aria-label": t("pptx.action.gotoSlide"),
21008
+ className: cn(INPUT, "w-full"),
21009
+ placeholder: t("pptx.action.slideNumberPlaceholder"),
21010
+ min: 1,
21011
+ max: slideCount,
21012
+ value: (slideIndex ?? 0) + 1,
21013
+ onChange: (e) => {
21014
+ const idx = toSlideIndex(Number(e.target.value), slideCount);
21015
+ if (idx !== void 0) {
21016
+ onChange({ slideIndex: idx });
21017
+ }
21018
+ }
21019
+ }
21020
+ );
21021
+ }
21022
+ if (type === "customShow") {
21023
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
21024
+ /* @__PURE__ */ jsxs(
21025
+ "select",
21026
+ {
21027
+ "data-testid": "pptx-action-custom-show",
21028
+ disabled: !canEdit,
21029
+ "aria-label": t("pptx.hyperlink.customShowLabel"),
21030
+ className: cn(INPUT, "w-full"),
21031
+ value: customShowId ?? "",
21032
+ onChange: (e) => onChange({ customShowId: e.target.value, returnAfter }),
21033
+ children: [
21034
+ /* @__PURE__ */ jsx("option", { value: "", children: t("pptx.hyperlink.customShowLabel") }),
21035
+ customShows.map((show) => /* @__PURE__ */ jsx("option", { value: show.id, children: show.name }, show.id))
21036
+ ]
21037
+ }
21038
+ ),
21039
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
21040
+ /* @__PURE__ */ jsx(
21041
+ "input",
21042
+ {
21043
+ type: "checkbox",
21044
+ "data-testid": "pptx-action-custom-show-return",
21045
+ disabled: !canEdit,
21046
+ checked: returnAfter ?? false,
21047
+ onChange: (e) => onChange({ customShowId, returnAfter: e.target.checked })
21048
+ }
21049
+ ),
21050
+ t("pptx.hyperlink.customShowReturn")
21051
+ ] })
21052
+ ] });
21053
+ }
21054
+ return null;
21055
+ }
20855
21056
  function ActionSettingsPanel({
20856
21057
  selectedElement,
20857
21058
  slides,
20858
21059
  canEdit,
21060
+ customShows,
20859
21061
  onUpdateElement
20860
21062
  }) {
20861
21063
  const { t } = useTranslation();
20862
21064
  const clickAction = selectedElement.actionClick ? pptxActionToElementAction(selectedElement.actionClick, "click") : void 0;
20863
21065
  const hoverAction = selectedElement.actionHover ? pptxActionToElementAction(selectedElement.actionHover, "hover") : void 0;
20864
- const updateAction = (trigger, type, url, slideIndex) => {
20865
- const ea = { trigger, type, url, slideIndex };
21066
+ const updateAction = (trigger, type, patch) => {
21067
+ const ea = { trigger, type, ...patch };
20866
21068
  const pa = elementActionToPptxAction(ea);
20867
21069
  if (trigger === "click") {
20868
21070
  onUpdateElement({ actionClick: pa });
@@ -20872,9 +21074,13 @@ function ActionSettingsPanel({
20872
21074
  };
20873
21075
  const changeType = (trigger, type) => {
20874
21076
  const current = trigger === "click" ? clickAction : hoverAction;
20875
- const target = { url: current?.url, slideIndex: current?.slideIndex };
21077
+ const target = {
21078
+ url: current?.url,
21079
+ slideIndex: current?.slideIndex,
21080
+ customShowId: current?.customShowId
21081
+ };
20876
21082
  if (canCommitActionType(type, target)) {
20877
- updateAction(trigger, type, target.url, target.slideIndex);
21083
+ updateAction(trigger, type, target);
20878
21084
  }
20879
21085
  };
20880
21086
  return /* @__PURE__ */ jsxs("div", { className: CARD, "data-pptx-action-settings": true, children: [
@@ -20891,9 +21097,9 @@ function ActionSettingsPanel({
20891
21097
  fallbackSlideIndex: selectedElement.actionClick?.targetSlideIndex,
20892
21098
  canEdit,
20893
21099
  slideCount: slides.length,
21100
+ customShows,
20894
21101
  onChangeType: (type) => changeType("click", type),
20895
- onChangeUrl: (url) => updateAction("click", "url", url),
20896
- onChangeSlide: (idx) => updateAction("click", "slide", void 0, idx)
21102
+ onChangeTarget: (type, patch) => updateAction("click", type, patch)
20897
21103
  },
20898
21104
  `click-${selectedElement.id}`
20899
21105
  ),
@@ -20908,9 +21114,9 @@ function ActionSettingsPanel({
20908
21114
  fallbackSlideIndex: selectedElement.actionHover?.targetSlideIndex,
20909
21115
  canEdit,
20910
21116
  slideCount: slides.length,
21117
+ customShows,
20911
21118
  onChangeType: (type) => changeType("hover", type),
20912
- onChangeUrl: (url) => updateAction("hover", "url", url),
20913
- onChangeSlide: (idx) => updateAction("hover", "slide", void 0, idx)
21119
+ onChangeTarget: (type, patch) => updateAction("hover", type, patch)
20914
21120
  },
20915
21121
  `hover-${selectedElement.id}`
20916
21122
  )
@@ -20926,9 +21132,9 @@ function ActionTriggerSection({
20926
21132
  fallbackSlideIndex,
20927
21133
  canEdit,
20928
21134
  slideCount,
21135
+ customShows,
20929
21136
  onChangeType,
20930
- onChangeUrl,
20931
- onChangeSlide
21137
+ onChangeTarget
20932
21138
  }) {
20933
21139
  const { t } = useTranslation();
20934
21140
  const [pendingType, setPendingType] = useState(void 0);
@@ -20950,35 +21156,18 @@ function ActionTriggerSection({
20950
21156
  children: ELEMENT_ACTION_TYPE_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: t(o.labelKey) }, o.value))
20951
21157
  }
20952
21158
  ),
20953
- effectiveType === "url" && /* @__PURE__ */ jsx(
20954
- "input",
20955
- {
20956
- type: "text",
20957
- disabled: !canEdit,
20958
- "aria-label": t("pptx.action.gotoUrl"),
20959
- className: cn(INPUT, "w-full"),
20960
- placeholder: "https://...",
20961
- value: action?.url ?? fallbackUrl ?? "",
20962
- onChange: (e) => onChangeUrl(e.target.value)
20963
- }
20964
- ),
20965
- effectiveType === "slide" && /* @__PURE__ */ jsx(
20966
- "input",
21159
+ /* @__PURE__ */ jsx(
21160
+ ActionTargetFields,
20967
21161
  {
20968
- type: "number",
20969
- disabled: !canEdit,
20970
- "aria-label": t("pptx.action.gotoSlide"),
20971
- className: cn(INPUT, "w-full"),
20972
- placeholder: t("pptx.action.slideNumberPlaceholder"),
20973
- min: 1,
20974
- max: slideCount,
20975
- value: (action?.slideIndex ?? fallbackSlideIndex ?? 0) + 1,
20976
- onChange: (e) => {
20977
- const idx = toSlideIndex(Number(e.target.value), slideCount);
20978
- if (idx !== void 0) {
20979
- onChangeSlide(idx);
20980
- }
20981
- }
21162
+ type: effectiveType,
21163
+ canEdit,
21164
+ slideCount,
21165
+ customShows,
21166
+ url: action?.url ?? fallbackUrl,
21167
+ slideIndex: action?.slideIndex ?? fallbackSlideIndex,
21168
+ customShowId: action?.customShowId,
21169
+ returnAfter: action?.returnAfter,
21170
+ onChange: (patch) => onChangeTarget(effectiveType, patch)
20982
21171
  }
20983
21172
  )
20984
21173
  ] });
@@ -21266,6 +21455,7 @@ function ChartAxisStyleOptions({
21266
21455
  onSetGridlineStyle
21267
21456
  }) {
21268
21457
  const { t } = useTranslation();
21458
+ const { pushColor } = useRecentColors();
21269
21459
  const rows = SCALE_AXES.map((row) => ({
21270
21460
  ...row,
21271
21461
  axis: axes?.find((a) => a.axisType === row.type)
@@ -21367,7 +21557,10 @@ function ChartAxisStyleOptions({
21367
21557
  disabled: !canEdit,
21368
21558
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
21369
21559
  value: axis.fontColor ?? "#000000",
21370
- onChange: (e) => onSetTitleStyle(type, { fontColor: e.target.value })
21560
+ onChange: (e) => {
21561
+ onSetTitleStyle(type, { fontColor: e.target.value });
21562
+ pushColor(e.target.value);
21563
+ }
21371
21564
  }
21372
21565
  )
21373
21566
  ] })
@@ -21390,7 +21583,10 @@ function ChartAxisStyleOptions({
21390
21583
  title: t("pptx.chart.gridlineColor"),
21391
21584
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
21392
21585
  value: spPr?.strokeColor ?? "#d9d9d9",
21393
- onChange: (e) => onSetGridlineStyle(type, which, { color: e.target.value })
21586
+ onChange: (e) => {
21587
+ onSetGridlineStyle(type, which, { color: e.target.value });
21588
+ pushColor(e.target.value);
21589
+ }
21394
21590
  }
21395
21591
  ),
21396
21592
  /* @__PURE__ */ jsx(
@@ -21640,6 +21836,7 @@ function ChartDataPointMarkerOptions({
21640
21836
  onSetPointMarker
21641
21837
  }) {
21642
21838
  const { t } = useTranslation();
21839
+ const { pushColor } = useRecentColors();
21643
21840
  const [seriesIndex, setSeriesIndex] = useState(0);
21644
21841
  if (!MARKER_SUPPORTED_TYPES.has(chartType) || series.length === 0 || categories.length === 0) {
21645
21842
  return null;
@@ -21727,7 +21924,10 @@ function ChartDataPointMarkerOptions({
21727
21924
  title: t("pptx.chart.markerFill"),
21728
21925
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
21729
21926
  value: point2.marker.spPr?.fillColor ?? "#4472c4",
21730
- onChange: (e) => onSetPointMarker(seriesIndex, idx, { fillColor: e.target.value })
21927
+ onChange: (e) => {
21928
+ onSetPointMarker(seriesIndex, idx, { fillColor: e.target.value });
21929
+ pushColor(e.target.value);
21930
+ }
21731
21931
  }
21732
21932
  )
21733
21933
  ] })
@@ -21745,6 +21945,7 @@ function ChartDataPointOptions({
21745
21945
  onSetPointLabel
21746
21946
  }) {
21747
21947
  const { t } = useTranslation();
21948
+ const { pushColor } = useRecentColors();
21748
21949
  const [seriesIndex, setSeriesIndex] = useState(0);
21749
21950
  if (series.length === 0 || categories.length === 0) {
21750
21951
  return null;
@@ -21795,7 +21996,10 @@ function ChartDataPointOptions({
21795
21996
  title: t("pptx.chart.pointFill"),
21796
21997
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
21797
21998
  value: point2?.spPr?.fillColor ?? activeSeries.color ?? "#4472c4",
21798
- onChange: (e) => onSetPointFill(seriesIndex, idx, e.target.value)
21999
+ onChange: (e) => {
22000
+ onSetPointFill(seriesIndex, idx, e.target.value);
22001
+ pushColor(e.target.value);
22002
+ }
21799
22003
  }
21800
22004
  ),
21801
22005
  point2?.spPr?.fillColor && /* @__PURE__ */ jsx(
@@ -22007,6 +22211,7 @@ function ChartMarkerOptions({
22007
22211
  onSetMarker
22008
22212
  }) {
22009
22213
  const { t } = useTranslation();
22214
+ const { pushColor } = useRecentColors();
22010
22215
  if (!MARKER_SUPPORTED_TYPES.has(chartType) || series.length === 0) {
22011
22216
  return null;
22012
22217
  }
@@ -22065,7 +22270,10 @@ function ChartMarkerOptions({
22065
22270
  disabled: !canEdit,
22066
22271
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
22067
22272
  value: marker.spPr?.fillColor ?? "#4472c4",
22068
- onChange: (e) => onSetMarker(i, { fillColor: e.target.value })
22273
+ onChange: (e) => {
22274
+ onSetMarker(i, { fillColor: e.target.value });
22275
+ pushColor(e.target.value);
22276
+ }
22069
22277
  }
22070
22278
  )
22071
22279
  ] })
@@ -22084,14 +22292,19 @@ function DebouncedColorInput({
22084
22292
  const [local, setLocal] = useState(value);
22085
22293
  const commitRef = useRef(onCommit);
22086
22294
  commitRef.current = onCommit;
22295
+ const { pushColor } = useRecentColors();
22087
22296
  useEffect(() => {
22088
22297
  setLocal(value);
22089
22298
  }, [value]);
22090
- const handleChange = useCallback((e) => {
22091
- const next = e.target.value;
22092
- setLocal(next);
22093
- commitRef.current(next);
22094
- }, []);
22299
+ const handleChange = useCallback(
22300
+ (e) => {
22301
+ const next = e.target.value;
22302
+ setLocal(next);
22303
+ commitRef.current(next);
22304
+ pushColor(next);
22305
+ },
22306
+ [pushColor]
22307
+ );
22095
22308
  return /* @__PURE__ */ jsx(
22096
22309
  "input",
22097
22310
  {
@@ -22156,6 +22369,71 @@ function ChartSeriesColorOptions({
22156
22369
  ] }, `${s.name}-${i}`)) })
22157
22370
  ] });
22158
22371
  }
22372
+ function ChartSubtypeOptions({
22373
+ chartData,
22374
+ canEdit,
22375
+ onUpdateChartData
22376
+ }) {
22377
+ const { t } = useTranslation();
22378
+ if (chartData.chartType !== "bar3D" && chartData.chartType !== "radar" && chartData.chartType !== "surface") {
22379
+ return null;
22380
+ }
22381
+ return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
22382
+ /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.chart.display") }),
22383
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
22384
+ chartData.chartType === "bar3D" && /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-[11px]", children: [
22385
+ /* @__PURE__ */ jsx("span", { className: "w-16 text-muted-foreground shrink-0", children: t("pptx.chart.bar3DShapeLabel") }),
22386
+ /* @__PURE__ */ jsx(
22387
+ "select",
22388
+ {
22389
+ "data-testid": "pptx-chart-bar3d-shape",
22390
+ "aria-label": t("pptx.chart.bar3DShapeLabel"),
22391
+ disabled: !canEdit,
22392
+ className: INPUT2,
22393
+ value: chartData.barShape ?? "box",
22394
+ onChange: (e) => onUpdateChartData(bar3DShapePatch(chartData, e.target.value)),
22395
+ children: BAR3D_SHAPE_OPTIONS.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: t(opt.labelKey) }, opt.value))
22396
+ }
22397
+ )
22398
+ ] }),
22399
+ chartData.chartType === "radar" && /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-[11px]", children: [
22400
+ /* @__PURE__ */ jsx("span", { className: "w-16 text-muted-foreground shrink-0", children: t("pptx.chart.radarStyleLabel") }),
22401
+ /* @__PURE__ */ jsx(
22402
+ "select",
22403
+ {
22404
+ "data-testid": "pptx-chart-radar-style",
22405
+ "aria-label": t("pptx.chart.radarStyleLabel"),
22406
+ disabled: !canEdit,
22407
+ className: INPUT2,
22408
+ value: chartData.radarStyle ?? "standard",
22409
+ onChange: (e) => onUpdateChartData(
22410
+ radarStylePatch(
22411
+ chartData,
22412
+ e.target.value
22413
+ )
22414
+ ),
22415
+ children: RADAR_STYLE_OPTIONS.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: t(opt.labelKey) }, opt.value))
22416
+ }
22417
+ )
22418
+ ] }),
22419
+ chartData.chartType === "surface" && /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-[11px]", children: [
22420
+ /* @__PURE__ */ jsx("span", { className: "w-16 text-muted-foreground shrink-0", children: t("pptx.chart.surfaceWireframeLabel") }),
22421
+ /* @__PURE__ */ jsx(
22422
+ "select",
22423
+ {
22424
+ "data-testid": "pptx-chart-surface-wireframe",
22425
+ "aria-label": t("pptx.chart.surfaceWireframeLabel"),
22426
+ disabled: !canEdit,
22427
+ className: INPUT2,
22428
+ value: chartData.wireframe ? "true" : "false",
22429
+ onChange: (e) => onUpdateChartData(surfaceWireframePatch(chartData, e.target.value === "true")),
22430
+ children: SURFACE_WIREFRAME_OPTIONS.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: t(opt.labelKey) }, opt.value))
22431
+ }
22432
+ )
22433
+ ] })
22434
+ ] })
22435
+ ] });
22436
+ }
22159
22437
  function ChartTrendlineOptions({
22160
22438
  chartType,
22161
22439
  series,
@@ -22536,6 +22814,14 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
22536
22814
  onToggleGridlines: toggleGridlines
22537
22815
  }
22538
22816
  ),
22817
+ /* @__PURE__ */ jsx(
22818
+ ChartSubtypeOptions,
22819
+ {
22820
+ chartData,
22821
+ canEdit,
22822
+ onUpdateChartData: updateChartData
22823
+ }
22824
+ ),
22539
22825
  /* @__PURE__ */ jsx(ChartDataLabelOptions, { style, canEdit, onUpdateStyle: updateStyle }),
22540
22826
  /* @__PURE__ */ jsx(ChartAxisOptions, { axes: chartData.axes, canEdit, onUpdateAxis: updateAxis }),
22541
22827
  /* @__PURE__ */ jsx(
@@ -23074,6 +23360,7 @@ function DebouncedColorInput2({
23074
23360
  const [local, setLocal] = useState(value);
23075
23361
  const commitRef = useRef(onCommit);
23076
23362
  commitRef.current = onCommit;
23363
+ const { pushColor } = useRecentColors();
23077
23364
  useEffect(() => {
23078
23365
  setLocal(value);
23079
23366
  }, [value]);
@@ -23082,7 +23369,8 @@ function DebouncedColorInput2({
23082
23369
  }, []);
23083
23370
  const handleBlur = useCallback(() => {
23084
23371
  commitRef.current(local);
23085
- }, [local]);
23372
+ pushColor(local);
23373
+ }, [local, pushColor]);
23086
23374
  const inputRef = useRef(null);
23087
23375
  useEffect(() => {
23088
23376
  const el = inputRef.current;
@@ -23091,10 +23379,11 @@ function DebouncedColorInput2({
23091
23379
  }
23092
23380
  const handler = () => {
23093
23381
  commitRef.current(el.value);
23382
+ pushColor(el.value);
23094
23383
  };
23095
23384
  el.addEventListener("change", handler);
23096
23385
  return () => el.removeEventListener("change", handler);
23097
- }, []);
23386
+ }, [pushColor]);
23098
23387
  return /* @__PURE__ */ jsx(
23099
23388
  "input",
23100
23389
  {
@@ -24911,6 +25200,108 @@ var safeNum = (raw, fallback) => {
24911
25200
  const n = Number(raw);
24912
25201
  return Number.isFinite(n) ? n : fallback;
24913
25202
  };
25203
+ function EffectField({
25204
+ field,
25205
+ style,
25206
+ onUpdate
25207
+ }) {
25208
+ const { t } = useTranslation();
25209
+ const { pushColor } = useRecentColors();
25210
+ const fieldLabel = field.i18nKey ? t(field.i18nKey) : field.label;
25211
+ const val = field.read(style);
25212
+ const cls = `flex flex-col gap-1 ${field.span2 ? COL2 : ""}`;
25213
+ if (field.type === "select" && field.options) {
25214
+ return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25215
+ /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25216
+ /* @__PURE__ */ jsx(
25217
+ "select",
25218
+ {
25219
+ "aria-label": fieldLabel,
25220
+ value: String(val),
25221
+ onChange: (e) => {
25222
+ const result = field.write(e.target.value, style);
25223
+ onUpdate(typeof result === "function" ? result(style) : result);
25224
+ },
25225
+ className: SEL2,
25226
+ children: field.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
25227
+ }
25228
+ )
25229
+ ] });
25230
+ }
25231
+ if (field.type === "color") {
25232
+ return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25233
+ /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25234
+ /* @__PURE__ */ jsx(
25235
+ "input",
25236
+ {
25237
+ type: "color",
25238
+ value: String(val),
25239
+ onChange: (e) => {
25240
+ const result = field.write(e.target.value, style);
25241
+ onUpdate(typeof result === "function" ? result(style) : result);
25242
+ pushColor(e.target.value);
25243
+ },
25244
+ className: `h-8 ${SEL2} px-1`
25245
+ }
25246
+ )
25247
+ ] });
25248
+ }
25249
+ if (field.type === "checkbox") {
25250
+ return /* @__PURE__ */ jsxs("label", { className: `flex items-center gap-2 ${field.span2 ? COL2 : ""}`, children: [
25251
+ /* @__PURE__ */ jsx(
25252
+ "input",
25253
+ {
25254
+ type: "checkbox",
25255
+ checked: Boolean(val),
25256
+ onChange: (e) => {
25257
+ const result = field.write(e.target.checked, style);
25258
+ onUpdate(typeof result === "function" ? result(style) : result);
25259
+ },
25260
+ className: "h-4 w-4"
25261
+ }
25262
+ ),
25263
+ /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel })
25264
+ ] });
25265
+ }
25266
+ if (field.type === "range") {
25267
+ return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25268
+ /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25269
+ /* @__PURE__ */ jsx(
25270
+ "input",
25271
+ {
25272
+ type: "range",
25273
+ min: field.min ?? 0,
25274
+ max: field.max ?? 100,
25275
+ value: Number(val),
25276
+ onChange: (e) => {
25277
+ const result = field.write(Number(e.target.value), style);
25278
+ onUpdate(typeof result === "function" ? result(style) : result);
25279
+ },
25280
+ className: RNG
25281
+ }
25282
+ )
25283
+ ] });
25284
+ }
25285
+ return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25286
+ /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25287
+ /* @__PURE__ */ jsx(
25288
+ "input",
25289
+ {
25290
+ type: "number",
25291
+ min: field.min,
25292
+ max: field.max,
25293
+ step: field.step,
25294
+ value: Number(val),
25295
+ onChange: (e) => {
25296
+ const n = safeNum(e.target.value, Number(val));
25297
+ const result = field.write(n, style);
25298
+ onUpdate(typeof result === "function" ? result(style) : result);
25299
+ },
25300
+ className: NUM2
25301
+ }
25302
+ )
25303
+ ] });
25304
+ }
24914
25305
  function SelectRow({
24915
25306
  label,
24916
25307
  value,
@@ -24938,14 +25329,18 @@ function ColorPickerRow({
24938
25329
  value,
24939
25330
  disabled,
24940
25331
  prefix,
24941
- recentColors,
24942
25332
  onChange
24943
25333
  }) {
24944
25334
  const { t } = useTranslation();
25335
+ const { pushColor } = useRecentColors();
25336
+ const commit = (color) => {
25337
+ onChange(color);
25338
+ pushColor(color);
25339
+ };
24945
25340
  const handleEyedropper = async () => {
24946
25341
  const color = await openNativeEyeDropper();
24947
25342
  if (color) {
24948
- onChange(color);
25343
+ commit(color);
24949
25344
  }
24950
25345
  };
24951
25346
  return /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
@@ -24957,7 +25352,7 @@ function ColorPickerRow({
24957
25352
  type: "color",
24958
25353
  value,
24959
25354
  disabled,
24960
- onChange: (e) => onChange(e.target.value),
25355
+ onChange: (e) => commit(e.target.value),
24961
25356
  className: `h-8 flex-1 ${SEL2} px-1 ${DIS}`
24962
25357
  }
24963
25358
  ),
@@ -24976,35 +25371,21 @@ function ColorPickerRow({
24976
25371
  }
24977
25372
  )
24978
25373
  ] }),
24979
- /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap gap-1", children: [
24980
- THEME_COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx(
24981
- "button",
24982
- {
24983
- type: "button",
24984
- className: `${SWATCH} ${DIS}`,
24985
- style: { backgroundColor: c },
24986
- title: `${label} ${c}`,
24987
- "aria-label": `${label} ${c}`,
24988
- "data-pptx-compact": true,
24989
- disabled,
24990
- onClick: () => onChange(c)
24991
- },
24992
- `${prefix}-theme-${c}`
24993
- )),
24994
- recentColors?.map((c) => /* @__PURE__ */ jsx(
24995
- "button",
24996
- {
24997
- type: "button",
24998
- "data-pptx-compact": true,
24999
- className: "h-4 w-4 rounded border border-primary",
25000
- style: { backgroundColor: c },
25001
- title: `Recent ${c}`,
25002
- "aria-label": `Recent ${c}`,
25003
- onClick: () => onChange(c)
25004
- },
25005
- `${prefix}-recent-${c}`
25006
- ))
25007
- ] })
25374
+ /* @__PURE__ */ jsx("div", { className: "mt-1 flex flex-wrap gap-1", children: THEME_COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx(
25375
+ "button",
25376
+ {
25377
+ type: "button",
25378
+ className: `${SWATCH} ${DIS}`,
25379
+ style: { backgroundColor: c },
25380
+ title: `${label} ${c}`,
25381
+ "aria-label": `${label} ${c}`,
25382
+ "data-pptx-compact": true,
25383
+ disabled,
25384
+ onClick: () => commit(c)
25385
+ },
25386
+ `${prefix}-theme-${c}`
25387
+ )) }),
25388
+ /* @__PURE__ */ jsx(RecentColorsRow, { prefix, disabled, onCommit: commit })
25008
25389
  ] });
25009
25390
  }
25010
25391
  function GradientStopRow({
@@ -25015,6 +25396,7 @@ function GradientStopRow({
25015
25396
  allStops
25016
25397
  }) {
25017
25398
  const { t } = useTranslation();
25399
+ const { pushColor } = useRecentColors();
25018
25400
  const patchStop = (patch) => {
25019
25401
  const next = allStops.map((s, i) => i === index ? { ...s, ...patch } : s);
25020
25402
  onUpdate(next);
@@ -25026,7 +25408,11 @@ function GradientStopRow({
25026
25408
  {
25027
25409
  type: "color",
25028
25410
  value: normalizeHexColor(stop.color, "#3b82f6"),
25029
- onChange: (e) => patchStop({ color: normalizeHexColor(e.target.value, "#3b82f6") }),
25411
+ onChange: (e) => {
25412
+ const hex = normalizeHexColor(e.target.value, "#3b82f6");
25413
+ patchStop({ color: hex });
25414
+ pushColor(hex);
25415
+ },
25030
25416
  className: "h-7 w-10 rounded border border-border bg-muted"
25031
25417
  }
25032
25418
  ),
@@ -25072,106 +25458,6 @@ function GradientStopRow({
25072
25458
  ] })
25073
25459
  ] });
25074
25460
  }
25075
- function EffectField({
25076
- field,
25077
- style,
25078
- onUpdate
25079
- }) {
25080
- const { t } = useTranslation();
25081
- const fieldLabel = field.i18nKey ? t(field.i18nKey) : field.label;
25082
- const val = field.read(style);
25083
- const cls = `flex flex-col gap-1 ${field.span2 ? COL2 : ""}`;
25084
- if (field.type === "select" && field.options) {
25085
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25086
- /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25087
- /* @__PURE__ */ jsx(
25088
- "select",
25089
- {
25090
- "aria-label": fieldLabel,
25091
- value: String(val),
25092
- onChange: (e) => {
25093
- const result = field.write(e.target.value, style);
25094
- onUpdate(typeof result === "function" ? result(style) : result);
25095
- },
25096
- className: SEL2,
25097
- children: field.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
25098
- }
25099
- )
25100
- ] });
25101
- }
25102
- if (field.type === "color") {
25103
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25104
- /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25105
- /* @__PURE__ */ jsx(
25106
- "input",
25107
- {
25108
- type: "color",
25109
- value: String(val),
25110
- onChange: (e) => {
25111
- const result = field.write(e.target.value, style);
25112
- onUpdate(typeof result === "function" ? result(style) : result);
25113
- },
25114
- className: `h-8 ${SEL2} px-1`
25115
- }
25116
- )
25117
- ] });
25118
- }
25119
- if (field.type === "checkbox") {
25120
- return /* @__PURE__ */ jsxs("label", { className: `flex items-center gap-2 ${field.span2 ? COL2 : ""}`, children: [
25121
- /* @__PURE__ */ jsx(
25122
- "input",
25123
- {
25124
- type: "checkbox",
25125
- checked: Boolean(val),
25126
- onChange: (e) => {
25127
- const result = field.write(e.target.checked, style);
25128
- onUpdate(typeof result === "function" ? result(style) : result);
25129
- },
25130
- className: "h-4 w-4"
25131
- }
25132
- ),
25133
- /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel })
25134
- ] });
25135
- }
25136
- if (field.type === "range") {
25137
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25138
- /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25139
- /* @__PURE__ */ jsx(
25140
- "input",
25141
- {
25142
- type: "range",
25143
- min: field.min ?? 0,
25144
- max: field.max ?? 100,
25145
- value: Number(val),
25146
- onChange: (e) => {
25147
- const result = field.write(Number(e.target.value), style);
25148
- onUpdate(typeof result === "function" ? result(style) : result);
25149
- },
25150
- className: RNG
25151
- }
25152
- )
25153
- ] });
25154
- }
25155
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
25156
- /* @__PURE__ */ jsx("span", { className: LBL2, children: fieldLabel }),
25157
- /* @__PURE__ */ jsx(
25158
- "input",
25159
- {
25160
- type: "number",
25161
- min: field.min,
25162
- max: field.max,
25163
- step: field.step,
25164
- value: Number(val),
25165
- onChange: (e) => {
25166
- const n = safeNum(e.target.value, Number(val));
25167
- const result = field.write(n, style);
25168
- onUpdate(typeof result === "function" ? result(style) : result);
25169
- },
25170
- className: NUM2
25171
- }
25172
- )
25173
- ] });
25174
- }
25175
25461
  function FillAdvancedControls({
25176
25462
  style,
25177
25463
  gradientStops,
@@ -25381,7 +25667,6 @@ function QuickStylesGallery({
25381
25667
  function StrokeEffectsSection({
25382
25668
  style,
25383
25669
  isLine,
25384
- recentColors,
25385
25670
  onUpdateShapeStyle,
25386
25671
  onSetStrokeColor
25387
25672
  }) {
@@ -25393,7 +25678,6 @@ function StrokeEffectsSection({
25393
25678
  label: t("pptx.inspector.stroke"),
25394
25679
  prefix: "stroke",
25395
25680
  value: normalizeHexColor(style?.strokeColor, DEFAULT_STROKE_COLOR),
25396
- recentColors,
25397
25681
  onChange: onSetStrokeColor
25398
25682
  }
25399
25683
  ),
@@ -25526,7 +25810,6 @@ function FillStrokeProperties({
25526
25810
  selectedShapeStyle,
25527
25811
  selectedShapeType,
25528
25812
  selectedGradientStops,
25529
- recentColors,
25530
25813
  onUpdateShapeStyle,
25531
25814
  onSetFillColor,
25532
25815
  onSetStrokeColor
@@ -25625,7 +25908,6 @@ function FillStrokeProperties({
25625
25908
  {
25626
25909
  style,
25627
25910
  isLine: line,
25628
- recentColors,
25629
25911
  onUpdateShapeStyle,
25630
25912
  onSetStrokeColor
25631
25913
  }
@@ -25640,6 +25922,7 @@ function Text3DProperties({
25640
25922
  onUpdateTextStyle
25641
25923
  }) {
25642
25924
  const { t } = useTranslation();
25925
+ const { pushColor } = useRecentColors();
25643
25926
  const t3d = ts?.text3d;
25644
25927
  const hasExtrusion = Boolean(t3d?.extrusionHeight && t3d.extrusionHeight > 0);
25645
25928
  const update3d = (partial) => {
@@ -25693,7 +25976,10 @@ function Text3DProperties({
25693
25976
  {
25694
25977
  type: "color",
25695
25978
  value: normalizeHexColor(t3d?.extrusionColor, "#888888"),
25696
- onChange: (e) => update3d({ extrusionColor: e.target.value }),
25979
+ onChange: (e) => {
25980
+ update3d({ extrusionColor: e.target.value });
25981
+ pushColor(e.target.value);
25982
+ },
25697
25983
  className: COLOR_CLS
25698
25984
  }
25699
25985
  )
@@ -25859,6 +26145,7 @@ function AdvancedTextFormatting({
25859
26145
  numChange
25860
26146
  }) {
25861
26147
  const { t } = useTranslation();
26148
+ const { pushColor } = useRecentColors();
25862
26149
  return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded border border-border bg-card p-2 space-y-2", children: [
25863
26150
  /* @__PURE__ */ jsx("div", { className: "text-[11px] uppercase tracking-wide text-muted-foreground", children: t("pptx.textProperties.advancedTextHeading") }),
25864
26151
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: BASELINE_TOGGLES.map(([label, baseline]) => /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-foreground", children: [
@@ -25881,7 +26168,10 @@ function AdvancedTextFormatting({
25881
26168
  {
25882
26169
  type: "color",
25883
26170
  value: normalizeHexColor(ts?.highlightColor, "#ffff00"),
25884
- onChange: (e) => onUpdateTextStyle({ highlightColor: e.target.value }),
26171
+ onChange: (e) => {
26172
+ onUpdateTextStyle({ highlightColor: e.target.value });
26173
+ pushColor(e.target.value);
26174
+ },
25885
26175
  disabled: !canEdit,
25886
26176
  className: COLOR_CLS2
25887
26177
  }
@@ -25912,7 +26202,10 @@ function AdvancedTextFormatting({
25912
26202
  {
25913
26203
  type: "color",
25914
26204
  value: ts?.underlineColor || ts?.color || "#000000",
25915
- onChange: (e) => onUpdateTextStyle({ underlineColor: e.target.value }),
26205
+ onChange: (e) => {
26206
+ onUpdateTextStyle({ underlineColor: e.target.value });
26207
+ pushColor(e.target.value);
26208
+ },
25916
26209
  className: COLOR_CLS2
25917
26210
  }
25918
26211
  )
@@ -25943,7 +26236,10 @@ function AdvancedTextFormatting({
25943
26236
  {
25944
26237
  type: "color",
25945
26238
  value: ts?.textOutlineColor || "#000000",
25946
- onChange: (e) => onUpdateTextStyle({ textOutlineColor: e.target.value }),
26239
+ onChange: (e) => {
26240
+ onUpdateTextStyle({ textOutlineColor: e.target.value });
26241
+ pushColor(e.target.value);
26242
+ },
25947
26243
  className: COLOR_CLS2
25948
26244
  }
25949
26245
  )
@@ -26017,19 +26313,128 @@ function AdvancedTextFormatting({
26017
26313
  ] })
26018
26314
  ] });
26019
26315
  }
26316
+ function TextReflectionSection({
26317
+ ts,
26318
+ onUpdateTextStyle,
26319
+ numChange
26320
+ }) {
26321
+ const { t } = useTranslation();
26322
+ const hasReflection = Boolean(ts?.textReflection);
26323
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
26324
+ /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-foreground", children: [
26325
+ /* @__PURE__ */ jsx(
26326
+ "input",
26327
+ {
26328
+ type: "checkbox",
26329
+ checked: hasReflection,
26330
+ onChange: (e) => {
26331
+ if (e.target.checked) {
26332
+ onUpdateTextStyle({
26333
+ textReflection: true,
26334
+ textReflectionBlur: 1,
26335
+ textReflectionStartOpacity: 0.5,
26336
+ textReflectionEndOpacity: 0,
26337
+ textReflectionOffset: 3
26338
+ });
26339
+ } else {
26340
+ onUpdateTextStyle({
26341
+ textReflection: void 0,
26342
+ textReflectionBlur: void 0,
26343
+ textReflectionStartOpacity: void 0,
26344
+ textReflectionEndOpacity: void 0,
26345
+ textReflectionOffset: void 0
26346
+ });
26347
+ }
26348
+ }
26349
+ }
26350
+ ),
26351
+ t("pptx.textEffects.reflection")
26352
+ ] }),
26353
+ hasReflection && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 pl-4", children: [
26354
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26355
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Blur" }),
26356
+ /* @__PURE__ */ jsx(
26357
+ "input",
26358
+ {
26359
+ type: "number",
26360
+ min: 0,
26361
+ max: 20,
26362
+ step: 0.5,
26363
+ value: Number(ts?.textReflectionBlur ?? 1).toFixed(1),
26364
+ onChange: numChange((v) => ({
26365
+ textReflectionBlur: Math.max(0, Math.min(20, v))
26366
+ })),
26367
+ className: INPUT_CLS3
26368
+ }
26369
+ )
26370
+ ] }),
26371
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26372
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Offset" }),
26373
+ /* @__PURE__ */ jsx(
26374
+ "input",
26375
+ {
26376
+ type: "number",
26377
+ min: 0,
26378
+ max: 20,
26379
+ step: 1,
26380
+ value: Math.round(ts?.textReflectionOffset ?? 3),
26381
+ onChange: numChange((v) => ({
26382
+ textReflectionOffset: Math.max(0, Math.min(20, v))
26383
+ })),
26384
+ className: INPUT_CLS3
26385
+ }
26386
+ )
26387
+ ] }),
26388
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26389
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.textEffects.startOpacity") }),
26390
+ /* @__PURE__ */ jsx(
26391
+ "input",
26392
+ {
26393
+ type: "number",
26394
+ min: 0,
26395
+ max: 1,
26396
+ step: 0.05,
26397
+ value: Number(ts?.textReflectionStartOpacity ?? 0.5).toFixed(2),
26398
+ onChange: numChange((v) => ({
26399
+ textReflectionStartOpacity: Math.max(0, Math.min(1, v))
26400
+ })),
26401
+ className: INPUT_CLS3
26402
+ }
26403
+ )
26404
+ ] }),
26405
+ /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26406
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.textEffects.endOpacity") }),
26407
+ /* @__PURE__ */ jsx(
26408
+ "input",
26409
+ {
26410
+ type: "number",
26411
+ min: 0,
26412
+ max: 1,
26413
+ step: 0.05,
26414
+ value: Number(ts?.textReflectionEndOpacity ?? 0).toFixed(2),
26415
+ onChange: numChange((v) => ({
26416
+ textReflectionEndOpacity: Math.max(0, Math.min(1, v))
26417
+ })),
26418
+ className: INPUT_CLS3
26419
+ }
26420
+ )
26421
+ ] })
26422
+ ] })
26423
+ ] });
26424
+ }
26020
26425
  function TextEffectsPanel({
26021
26426
  ts,
26022
26427
  onUpdateTextStyle,
26023
26428
  numChange
26024
26429
  }) {
26025
26430
  const { t } = useTranslation();
26431
+ const { pushColor } = useRecentColors();
26026
26432
  const hasShadow = Boolean(
26027
26433
  ts?.textShadowColor || typeof ts?.textShadowBlur === "number" && ts.textShadowBlur > 0
26028
26434
  );
26029
26435
  const hasGlow = Boolean(
26030
26436
  ts?.textGlowColor || typeof ts?.textGlowRadius === "number" && ts.textGlowRadius > 0
26031
26437
  );
26032
- const hasReflection = Boolean(ts?.textReflection);
26033
26438
  return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded border border-border bg-card p-2 space-y-2", children: [
26034
26439
  /* @__PURE__ */ jsx("div", { className: "text-[11px] uppercase tracking-wide text-muted-foreground", children: t("pptx.textEffects.title") }),
26035
26440
  /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
@@ -26070,7 +26475,10 @@ function TextEffectsPanel({
26070
26475
  {
26071
26476
  type: "color",
26072
26477
  value: normalizeHexColor(ts?.textShadowColor, "#000000"),
26073
- onChange: (e) => onUpdateTextStyle({ textShadowColor: e.target.value }),
26478
+ onChange: (e) => {
26479
+ onUpdateTextStyle({ textShadowColor: e.target.value });
26480
+ pushColor(e.target.value);
26481
+ },
26074
26482
  className: COLOR_CLS2
26075
26483
  }
26076
26484
  )
@@ -26175,7 +26583,10 @@ function TextEffectsPanel({
26175
26583
  {
26176
26584
  type: "color",
26177
26585
  value: normalizeHexColor(ts?.textGlowColor, "#ffff00"),
26178
- onChange: (e) => onUpdateTextStyle({ textGlowColor: e.target.value }),
26586
+ onChange: (e) => {
26587
+ onUpdateTextStyle({ textGlowColor: e.target.value });
26588
+ pushColor(e.target.value);
26589
+ },
26179
26590
  className: COLOR_CLS2
26180
26591
  }
26181
26592
  )
@@ -26216,107 +26627,7 @@ function TextEffectsPanel({
26216
26627
  ] })
26217
26628
  ] })
26218
26629
  ] }),
26219
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
26220
- /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-foreground", children: [
26221
- /* @__PURE__ */ jsx(
26222
- "input",
26223
- {
26224
- type: "checkbox",
26225
- checked: hasReflection,
26226
- onChange: (e) => {
26227
- if (e.target.checked) {
26228
- onUpdateTextStyle({
26229
- textReflection: true,
26230
- textReflectionBlur: 1,
26231
- textReflectionStartOpacity: 0.5,
26232
- textReflectionEndOpacity: 0,
26233
- textReflectionOffset: 3
26234
- });
26235
- } else {
26236
- onUpdateTextStyle({
26237
- textReflection: void 0,
26238
- textReflectionBlur: void 0,
26239
- textReflectionStartOpacity: void 0,
26240
- textReflectionEndOpacity: void 0,
26241
- textReflectionOffset: void 0
26242
- });
26243
- }
26244
- }
26245
- }
26246
- ),
26247
- t("pptx.textEffects.reflection")
26248
- ] }),
26249
- hasReflection && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 pl-4", children: [
26250
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26251
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Blur" }),
26252
- /* @__PURE__ */ jsx(
26253
- "input",
26254
- {
26255
- type: "number",
26256
- min: 0,
26257
- max: 20,
26258
- step: 0.5,
26259
- value: Number(ts?.textReflectionBlur ?? 1).toFixed(1),
26260
- onChange: numChange((v) => ({
26261
- textReflectionBlur: Math.max(0, Math.min(20, v))
26262
- })),
26263
- className: INPUT_CLS3
26264
- }
26265
- )
26266
- ] }),
26267
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26268
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Offset" }),
26269
- /* @__PURE__ */ jsx(
26270
- "input",
26271
- {
26272
- type: "number",
26273
- min: 0,
26274
- max: 20,
26275
- step: 1,
26276
- value: Math.round(ts?.textReflectionOffset ?? 3),
26277
- onChange: numChange((v) => ({
26278
- textReflectionOffset: Math.max(0, Math.min(20, v))
26279
- })),
26280
- className: INPUT_CLS3
26281
- }
26282
- )
26283
- ] }),
26284
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26285
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.textEffects.startOpacity") }),
26286
- /* @__PURE__ */ jsx(
26287
- "input",
26288
- {
26289
- type: "number",
26290
- min: 0,
26291
- max: 1,
26292
- step: 0.05,
26293
- value: Number(ts?.textReflectionStartOpacity ?? 0.5).toFixed(2),
26294
- onChange: numChange((v) => ({
26295
- textReflectionStartOpacity: Math.max(0, Math.min(1, v))
26296
- })),
26297
- className: INPUT_CLS3
26298
- }
26299
- )
26300
- ] }),
26301
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
26302
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.textEffects.endOpacity") }),
26303
- /* @__PURE__ */ jsx(
26304
- "input",
26305
- {
26306
- type: "number",
26307
- min: 0,
26308
- max: 1,
26309
- step: 0.05,
26310
- value: Number(ts?.textReflectionEndOpacity ?? 0).toFixed(2),
26311
- onChange: numChange((v) => ({
26312
- textReflectionEndOpacity: Math.max(0, Math.min(1, v))
26313
- })),
26314
- className: INPUT_CLS3
26315
- }
26316
- )
26317
- ] })
26318
- ] })
26319
- ] })
26630
+ /* @__PURE__ */ jsx(TextReflectionSection, { ts, onUpdateTextStyle, numChange })
26320
26631
  ] });
26321
26632
  }
26322
26633
  function TextWarpGallery({
@@ -26390,7 +26701,6 @@ function TextAdvancedSections({
26390
26701
  /* @__PURE__ */ jsx(Text3DProperties, { ts, onUpdateTextStyle })
26391
26702
  ] });
26392
26703
  }
26393
- var EMPTY_RECENT_COLORS = [];
26394
26704
  function ShapeTextPanels({
26395
26705
  selectedElement,
26396
26706
  canEdit,
@@ -26426,7 +26736,6 @@ function ShapeTextPanels({
26426
26736
  selectedGradientStops: sanitizeGradientStops(
26427
26737
  selectedElement.shapeStyle?.fillGradientStops
26428
26738
  ),
26429
- recentColors: EMPTY_RECENT_COLORS,
26430
26739
  canEdit,
26431
26740
  onUpdateShapeStyle: onUpdateElementStyle,
26432
26741
  onSetFillColor: (hex) => onUpdateElementStyle({ fillColor: hex, fillMode: "solid" }),
@@ -26434,7 +26743,7 @@ function ShapeTextPanels({
26434
26743
  }
26435
26744
  )
26436
26745
  ] }),
26437
- hasTextProperties(selectedElement) && /* @__PURE__ */ jsxs("div", { className: CARD, children: [
26746
+ hasTextProperties(selectedElement) && /* @__PURE__ */ jsxs("div", { className: CARD, "data-pptx-text-card": true, children: [
26438
26747
  /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.text.title", "Text") }),
26439
26748
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-1.5 text-[11px]", children: [
26440
26749
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
@@ -26458,12 +26767,21 @@ function ShapeTextPanels({
26458
26767
  DebouncedColorInput,
26459
26768
  {
26460
26769
  disabled: !canEdit,
26770
+ ariaLabel: "Text Color",
26461
26771
  value: normalizeHexColor(selectedElement.textStyle?.color, "#000000"),
26462
26772
  className: "w-full h-7 rounded border border-border bg-transparent cursor-pointer",
26463
26773
  onCommit: (hex) => onUpdateTextStyle({ color: hex })
26464
26774
  }
26465
26775
  )
26466
26776
  ] }),
26777
+ /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsx(
26778
+ RecentColorsRow,
26779
+ {
26780
+ prefix: "text-color",
26781
+ disabled: !canEdit,
26782
+ onCommit: (hex) => onUpdateTextStyle({ color: hex })
26783
+ }
26784
+ ) }),
26467
26785
  /* @__PURE__ */ jsxs("div", { className: "flex gap-1 col-span-2", children: [
26468
26786
  /* @__PURE__ */ jsx(
26469
26787
  TextFormatToggle,
@@ -26746,6 +27064,7 @@ function SmartArtNodeStyleControls({
26746
27064
  canEdit,
26747
27065
  onChangeStyle
26748
27066
  }) {
27067
+ const { pushColor } = useRecentColors();
26749
27068
  const bold = Boolean(style?.bold);
26750
27069
  const italic = Boolean(style?.italic);
26751
27070
  return /* @__PURE__ */ jsxs(
@@ -26765,7 +27084,10 @@ function SmartArtNodeStyleControls({
26765
27084
  "aria-label": `Fill colour for ${label}`,
26766
27085
  className: "h-4 w-5 cursor-pointer rounded border border-border bg-transparent p-0 disabled:cursor-not-allowed",
26767
27086
  value: style?.fillColor ?? DEFAULT_FILL,
26768
- onChange: (e) => onChangeStyle(nodeId, { fillColor: e.target.value })
27087
+ onChange: (e) => {
27088
+ onChangeStyle(nodeId, { fillColor: e.target.value });
27089
+ pushColor(e.target.value);
27090
+ }
26769
27091
  }
26770
27092
  )
26771
27093
  ] }),
@@ -26779,7 +27101,10 @@ function SmartArtNodeStyleControls({
26779
27101
  "aria-label": `Font colour for ${label}`,
26780
27102
  className: "h-4 w-5 cursor-pointer rounded border border-border bg-transparent p-0 disabled:cursor-not-allowed",
26781
27103
  value: style?.fontColor ?? DEFAULT_FONT,
26782
- onChange: (e) => onChangeStyle(nodeId, { fontColor: e.target.value })
27104
+ onChange: (e) => {
27105
+ onChangeStyle(nodeId, { fontColor: e.target.value });
27106
+ pushColor(e.target.value);
27107
+ }
26783
27108
  }
26784
27109
  )
26785
27110
  ] }),
@@ -27343,6 +27668,7 @@ function TableCellPatternFill({
27343
27668
  onUpdateCellStyle
27344
27669
  }) {
27345
27670
  const { t } = useTranslation();
27671
+ const { pushColor } = useRecentColors();
27346
27672
  const translate = (key) => t(key);
27347
27673
  return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
27348
27674
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-0.5", children: [
@@ -27369,7 +27695,10 @@ function TableCellPatternFill({
27369
27695
  disabled: !canEdit,
27370
27696
  className: "w-full h-7 rounded border border-border bg-transparent cursor-pointer",
27371
27697
  value: cellStyle.patternFillForeground ?? "#000000",
27372
- onChange: (e) => onUpdateCellStyle({ patternFillForeground: e.target.value })
27698
+ onChange: (e) => {
27699
+ onUpdateCellStyle({ patternFillForeground: e.target.value });
27700
+ pushColor(e.target.value);
27701
+ }
27373
27702
  }
27374
27703
  )
27375
27704
  ] }),
@@ -27382,7 +27711,10 @@ function TableCellPatternFill({
27382
27711
  disabled: !canEdit,
27383
27712
  className: "w-full h-7 rounded border border-border bg-transparent cursor-pointer",
27384
27713
  value: cellStyle.patternFillBackground ?? "#FFFFFF",
27385
- onChange: (e) => onUpdateCellStyle({ patternFillBackground: e.target.value })
27714
+ onChange: (e) => {
27715
+ onUpdateCellStyle({ patternFillBackground: e.target.value });
27716
+ pushColor(e.target.value);
27717
+ }
27386
27718
  }
27387
27719
  )
27388
27720
  ] })
@@ -27483,6 +27815,7 @@ function GradientControls({
27483
27815
  onUpdateCellStyle
27484
27816
  }) {
27485
27817
  const { t } = useTranslation();
27818
+ const { pushColor } = useRecentColors();
27486
27819
  const stops = cellStyle.gradientFillStops ?? [];
27487
27820
  const gradType = cellStyle.gradientFillType ?? "linear";
27488
27821
  const updateStop = (index, patch) => {
@@ -27539,7 +27872,10 @@ function GradientControls({
27539
27872
  disabled: !canEdit,
27540
27873
  className: "h-6 w-6 rounded border border-border cursor-pointer",
27541
27874
  value: stop.color,
27542
- onChange: (e) => updateStop(idx, { color: e.target.value })
27875
+ onChange: (e) => {
27876
+ updateStop(idx, { color: e.target.value });
27877
+ pushColor(e.target.value);
27878
+ }
27543
27879
  }
27544
27880
  ),
27545
27881
  /* @__PURE__ */ jsx(
@@ -27984,6 +28320,7 @@ function ElementInspectorBody({
27984
28320
  selectedElement,
27985
28321
  canEdit,
27986
28322
  slides,
28323
+ customShows,
27987
28324
  tableEditorState,
27988
28325
  mediaDataUrls,
27989
28326
  onUpdateElement,
@@ -28118,6 +28455,7 @@ function ElementInspectorBody({
28118
28455
  selectedElement,
28119
28456
  slides,
28120
28457
  canEdit,
28458
+ customShows,
28121
28459
  onUpdateElement
28122
28460
  }
28123
28461
  ),
@@ -28132,6 +28470,122 @@ function ElementInspectorBody({
28132
28470
  /* @__PURE__ */ jsx(LayerOrderButtons, { canEdit, onMoveLayer })
28133
28471
  ] });
28134
28472
  }
28473
+ function CommentMentionTextarea({
28474
+ value,
28475
+ mentions,
28476
+ authors,
28477
+ onChange,
28478
+ onSubmitShortcut,
28479
+ placeholder,
28480
+ rows = 2,
28481
+ className,
28482
+ ariaLabel
28483
+ }) {
28484
+ const { t } = useTranslation();
28485
+ const textareaRef = useRef(null);
28486
+ const [caret, setCaret] = useState(value.length);
28487
+ const [highlighted, setHighlighted] = useState(0);
28488
+ const [dismissedAt, setDismissedAt] = useState(null);
28489
+ const query = useMemo(() => commentMentionQuery(value, caret), [value, caret]);
28490
+ const activeQuery = query && query.start !== dismissedAt ? query : null;
28491
+ const matches = useMemo(
28492
+ () => activeQuery ? matchCommentMentionAuthors(authors, activeQuery.query) : [],
28493
+ [activeQuery, authors]
28494
+ );
28495
+ const safeHighlighted = matches.length > 0 ? highlighted % matches.length : 0;
28496
+ const syncCaret = (target) => {
28497
+ setCaret(target.selectionStart ?? target.value.length);
28498
+ setHighlighted(0);
28499
+ };
28500
+ const acceptAuthor = (author) => {
28501
+ const result = insertCommentMention(value, mentions, caret, author);
28502
+ onChange(result.text, result.mentions);
28503
+ setCaret(result.caret);
28504
+ setDismissedAt(null);
28505
+ requestAnimationFrame(() => {
28506
+ textareaRef.current?.setSelectionRange(result.caret, result.caret);
28507
+ textareaRef.current?.focus();
28508
+ });
28509
+ };
28510
+ const handleChange = (event) => {
28511
+ onChange(event.target.value, mentions);
28512
+ syncCaret(event.target);
28513
+ };
28514
+ const handleKeyDown = (event) => {
28515
+ if (matches.length > 0) {
28516
+ if (event.key === "ArrowDown") {
28517
+ event.preventDefault();
28518
+ setHighlighted((index) => (index + 1) % matches.length);
28519
+ return;
28520
+ }
28521
+ if (event.key === "ArrowUp") {
28522
+ event.preventDefault();
28523
+ setHighlighted((index) => (index - 1 + matches.length) % matches.length);
28524
+ return;
28525
+ }
28526
+ if (event.key === "Enter" || event.key === "Tab") {
28527
+ event.preventDefault();
28528
+ acceptAuthor(matches[safeHighlighted]);
28529
+ return;
28530
+ }
28531
+ if (event.key === "Escape") {
28532
+ event.preventDefault();
28533
+ setDismissedAt(activeQuery?.start ?? null);
28534
+ return;
28535
+ }
28536
+ }
28537
+ if (onSubmitShortcut && event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
28538
+ event.preventDefault();
28539
+ onSubmitShortcut();
28540
+ }
28541
+ };
28542
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
28543
+ /* @__PURE__ */ jsx(
28544
+ "textarea",
28545
+ {
28546
+ ref: textareaRef,
28547
+ "aria-label": ariaLabel,
28548
+ rows,
28549
+ placeholder: placeholder ?? t("pptx.comments.mentionPlaceholder"),
28550
+ value,
28551
+ className,
28552
+ onChange: handleChange,
28553
+ onSelect: (event) => syncCaret(event.currentTarget),
28554
+ onClick: (event) => syncCaret(event.currentTarget),
28555
+ onKeyDown: handleKeyDown,
28556
+ onKeyUp: (event) => syncCaret(event.currentTarget)
28557
+ }
28558
+ ),
28559
+ activeQuery && matches.length > 0 && /* @__PURE__ */ jsx(
28560
+ "div",
28561
+ {
28562
+ "data-testid": "pptx-comment-mention-suggestions",
28563
+ role: "listbox",
28564
+ "aria-label": t("pptx.comments.mentionSuggestions"),
28565
+ className: "absolute z-10 mt-0.5 max-h-40 w-full overflow-y-auto rounded border border-border bg-popover shadow-lg",
28566
+ children: matches.map((author, index) => /* @__PURE__ */ jsx(
28567
+ "button",
28568
+ {
28569
+ type: "button",
28570
+ "data-testid": "pptx-comment-mention-option",
28571
+ role: "option",
28572
+ "aria-selected": index === safeHighlighted,
28573
+ className: cn(
28574
+ "block w-full px-2 py-1 text-left text-[11px] hover:bg-accent",
28575
+ index === safeHighlighted && "bg-accent"
28576
+ ),
28577
+ onMouseDown: (event) => {
28578
+ event.preventDefault();
28579
+ acceptAuthor(author);
28580
+ },
28581
+ children: author.name
28582
+ },
28583
+ author.id
28584
+ ))
28585
+ }
28586
+ )
28587
+ ] });
28588
+ }
28135
28589
  function CommentBody({ text, mentions, className }) {
28136
28590
  const segments = commentTextSegments(text, mentions);
28137
28591
  if (!segments.some((segment) => segment.kind === "mention")) {
@@ -28153,6 +28607,59 @@ function CommentBody({ text, mentions, className }) {
28153
28607
  )
28154
28608
  ) });
28155
28609
  }
28610
+ function InspectorCommentReplyForm({
28611
+ commentId,
28612
+ authorName,
28613
+ draft,
28614
+ mentions,
28615
+ authors,
28616
+ onDraftChange,
28617
+ onSubmit,
28618
+ onCancel
28619
+ }) {
28620
+ const { t } = useTranslation();
28621
+ return /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-1.5 pl-3 border-l-2 border-l-primary/40", children: [
28622
+ /* @__PURE__ */ jsx(
28623
+ CommentMentionTextarea,
28624
+ {
28625
+ value: draft,
28626
+ mentions,
28627
+ authors,
28628
+ rows: 2,
28629
+ placeholder: t("pptx.comments.replyPlaceholder", { author: authorName || "Author" }),
28630
+ className: "w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground outline-none focus:border-primary resize-y",
28631
+ onChange: (text, next) => onDraftChange(commentId, text, next),
28632
+ onSubmitShortcut: () => onSubmit(commentId)
28633
+ }
28634
+ ),
28635
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
28636
+ /* @__PURE__ */ jsxs(
28637
+ "button",
28638
+ {
28639
+ type: "button",
28640
+ className: "inline-flex items-center gap-1 rounded bg-primary px-2 py-1 text-[11px] text-white hover:bg-primary/80 disabled:opacity-40 disabled:cursor-not-allowed",
28641
+ onClick: () => onSubmit(commentId),
28642
+ disabled: draft.trim().length === 0,
28643
+ children: [
28644
+ /* @__PURE__ */ jsx(LuReply, { className: "h-3 w-3" }),
28645
+ t("pptx.comments.addReply")
28646
+ ]
28647
+ }
28648
+ ),
28649
+ /* @__PURE__ */ jsx(
28650
+ "button",
28651
+ {
28652
+ type: "button",
28653
+ className: "inline-flex items-center gap-1 rounded bg-muted px-2 py-1 text-[11px] text-foreground hover:bg-accent",
28654
+ onClick: onCancel,
28655
+ children: t("pptx.comments.cancel")
28656
+ }
28657
+ )
28658
+ ] })
28659
+ ] });
28660
+ }
28661
+ var EMPTY_REPLY_MENTIONS = {};
28662
+ var EMPTY_AUTHORS = [];
28156
28663
  function InspectorCommentRow({
28157
28664
  comment,
28158
28665
  canEdit,
@@ -28161,6 +28668,8 @@ function InspectorCommentRow({
28161
28668
  commentEditDraft,
28162
28669
  replyingToCommentId,
28163
28670
  replyDraftByCommentId,
28671
+ replyDraftMentionsByCommentId = EMPTY_REPLY_MENTIONS,
28672
+ commentAuthors = EMPTY_AUTHORS,
28164
28673
  onStartEditComment,
28165
28674
  onSaveEditComment,
28166
28675
  onCancelEditComment,
@@ -28323,6 +28832,8 @@ function InspectorCommentRow({
28323
28832
  commentEditDraft,
28324
28833
  replyingToCommentId,
28325
28834
  replyDraftByCommentId,
28835
+ replyDraftMentionsByCommentId,
28836
+ commentAuthors,
28326
28837
  onStartEditComment,
28327
28838
  onSaveEditComment,
28328
28839
  onCancelEditComment,
@@ -28339,50 +28850,19 @@ function InspectorCommentRow({
28339
28850
  `${reply.id}-${ri}`
28340
28851
  )) })
28341
28852
  ] }),
28342
- isReplying && onCancelReply && onReplyDraftChange && onSubmitReply && /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-1.5 pl-3 border-l-2 border-l-primary/40", children: [
28343
- /* @__PURE__ */ jsx(
28344
- "textarea",
28345
- {
28346
- value: replyDraft,
28347
- onChange: (e) => onReplyDraftChange(comment.id, e.target.value),
28348
- rows: 2,
28349
- placeholder: t("pptx.comments.replyPlaceholder", {
28350
- author: comment.author || "Author"
28351
- }),
28352
- className: "w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground outline-none focus:border-primary resize-y",
28353
- onKeyDown: (e) => {
28354
- if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
28355
- e.preventDefault();
28356
- onSubmitReply(comment.id);
28357
- }
28358
- }
28359
- }
28360
- ),
28361
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
28362
- /* @__PURE__ */ jsxs(
28363
- "button",
28364
- {
28365
- type: "button",
28366
- className: "inline-flex items-center gap-1 rounded bg-primary px-2 py-1 text-[11px] text-white hover:bg-primary/80 disabled:opacity-40 disabled:cursor-not-allowed",
28367
- onClick: () => onSubmitReply(comment.id),
28368
- disabled: replyDraft.trim().length === 0,
28369
- children: [
28370
- /* @__PURE__ */ jsx(LuReply, { className: "h-3 w-3" }),
28371
- t("pptx.comments.addReply")
28372
- ]
28373
- }
28374
- ),
28375
- /* @__PURE__ */ jsx(
28376
- "button",
28377
- {
28378
- type: "button",
28379
- className: "inline-flex items-center gap-1 rounded bg-muted px-2 py-1 text-[11px] text-foreground hover:bg-accent",
28380
- onClick: onCancelReply,
28381
- children: t("pptx.comments.cancel")
28382
- }
28383
- )
28384
- ] })
28385
- ] })
28853
+ isReplying && onCancelReply && onReplyDraftChange && onSubmitReply && /* @__PURE__ */ jsx(
28854
+ InspectorCommentReplyForm,
28855
+ {
28856
+ commentId: comment.id,
28857
+ authorName: comment.author ?? "",
28858
+ draft: replyDraft,
28859
+ mentions: replyDraftMentionsByCommentId[comment.id] ?? [],
28860
+ authors: commentAuthors,
28861
+ onDraftChange: onReplyDraftChange,
28862
+ onSubmit: onSubmitReply,
28863
+ onCancel: onCancelReply
28864
+ }
28865
+ )
28386
28866
  ]
28387
28867
  }
28388
28868
  );
@@ -28395,8 +28875,11 @@ function InspectorCommentsSection({
28395
28875
  editingCommentId,
28396
28876
  commentEditDraft,
28397
28877
  commentDraft,
28878
+ commentDraftMentions,
28879
+ commentAuthors,
28398
28880
  replyingToCommentId,
28399
28881
  replyDraftByCommentId,
28882
+ replyDraftMentionsByCommentId,
28400
28883
  onSetCommentDraft,
28401
28884
  onAddComment,
28402
28885
  onDeleteComment,
@@ -28428,6 +28911,8 @@ function InspectorCommentsSection({
28428
28911
  commentEditDraft,
28429
28912
  replyingToCommentId,
28430
28913
  replyDraftByCommentId,
28914
+ replyDraftMentionsByCommentId,
28915
+ commentAuthors,
28431
28916
  onStartEditComment,
28432
28917
  onSaveEditComment,
28433
28918
  onCancelEditComment,
@@ -28450,21 +28935,18 @@ function InspectorCommentsSection({
28450
28935
  })
28451
28936
  ] }),
28452
28937
  /* @__PURE__ */ jsx(
28453
- "textarea",
28938
+ CommentMentionTextarea,
28454
28939
  {
28940
+ value: commentDraft,
28941
+ mentions: commentDraftMentions,
28942
+ authors: commentAuthors,
28455
28943
  rows: 2,
28456
28944
  placeholder: selectedElement ? t("pptx.comments.addOnElement", {
28457
28945
  element: getElementLabel(selectedElement)
28458
28946
  }) : t("pptx.comments.addPlaceholder"),
28459
- value: commentDraft,
28460
28947
  className: "w-full bg-muted border border-border rounded px-2 py-1 text-xs resize-y outline-none focus:border-primary",
28461
- onChange: (e) => onSetCommentDraft(e.target.value),
28462
- onKeyDown: (e) => {
28463
- if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
28464
- e.preventDefault();
28465
- onAddComment();
28466
- }
28467
- }
28948
+ onChange: onSetCommentDraft,
28949
+ onSubmitShortcut: onAddComment
28468
28950
  }
28469
28951
  ),
28470
28952
  /* @__PURE__ */ jsxs(
@@ -28781,26 +29263,78 @@ function DocumentPropertiesCard({
28781
29263
  ] })
28782
29264
  ] });
28783
29265
  }
29266
+ function SlideSizeRescalePrompt({
29267
+ onChoose
29268
+ }) {
29269
+ const { t } = useTranslation();
29270
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 rounded border border-border bg-muted/40 p-2 text-[11px]", children: [
29271
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: t("pptx.slideSize.rescaleTitle") }),
29272
+ /* @__PURE__ */ jsx("div", { className: "text-muted-foreground", children: t("pptx.slideSize.rescaleDescription") }),
29273
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-1.5 pt-1", children: [
29274
+ /* @__PURE__ */ jsx(
29275
+ "button",
29276
+ {
29277
+ type: "button",
29278
+ "data-testid": "pptx-slide-size-rescale-maximize",
29279
+ title: t("pptx.slideSize.rescaleMaximizeHint"),
29280
+ className: "rounded bg-primary px-2 py-1 text-primary-foreground transition-colors hover:opacity-90",
29281
+ onClick: () => onChoose("maximize"),
29282
+ children: t("pptx.slideSize.rescaleMaximize")
29283
+ }
29284
+ ),
29285
+ /* @__PURE__ */ jsx(
29286
+ "button",
29287
+ {
29288
+ type: "button",
29289
+ "data-testid": "pptx-slide-size-rescale-ensure-fit",
29290
+ title: t("pptx.slideSize.rescaleEnsureFitHint"),
29291
+ className: "rounded bg-muted px-2 py-1 transition-colors hover:bg-accent",
29292
+ onClick: () => onChoose("ensureFit"),
29293
+ children: t("pptx.slideSize.rescaleEnsureFit")
29294
+ }
29295
+ )
29296
+ ] })
29297
+ ] });
29298
+ }
28784
29299
  var CUSTOM_PRESET_VALUE = "";
29300
+ function sizesDiffer(a, b) {
29301
+ return a.widthEmu !== b.widthEmu || a.heightEmu !== b.heightEmu;
29302
+ }
28785
29303
  function SlideSizeCard({
28786
29304
  canvasSize,
28787
29305
  slideSizeEmu,
28788
29306
  canEdit,
28789
29307
  onUpdate,
28790
- onUpdateSlideSize
29308
+ onUpdateSlideSize,
29309
+ hasContent
28791
29310
  }) {
28792
29311
  const { t } = useTranslation();
28793
29312
  const selection = resolveSlideSizeSelection({ current: slideSizeEmu, canvas: canvasSize });
28794
29313
  const presetDisabled = !canEdit || !onUpdateSlideSize;
29314
+ const [pendingSize, setPendingSize] = useState(null);
29315
+ const applyOrPromptSize = (nextSize) => {
29316
+ if (hasContent && sizesDiffer(selection.size, nextSize)) {
29317
+ setPendingSize(nextSize);
29318
+ return;
29319
+ }
29320
+ onUpdateSlideSize?.(nextSize);
29321
+ };
28795
29322
  const handlePreset = (labelKey) => {
28796
29323
  const preset = SLIDE_SIZE_PRESETS.find((candidate) => candidate.labelKey === labelKey);
28797
29324
  if (!preset) {
28798
29325
  return;
28799
29326
  }
28800
- onUpdateSlideSize?.(slideSizeFromPreset(preset, selection.orientation));
29327
+ applyOrPromptSize(slideSizeFromPreset(preset, selection.orientation));
28801
29328
  };
28802
29329
  const handleOrientation = (orientation) => {
28803
- onUpdateSlideSize?.(withSlideSizeOrientation(selection.size, orientation));
29330
+ applyOrPromptSize(withSlideSizeOrientation(selection.size, orientation));
29331
+ };
29332
+ const handleRescale = (mode) => {
29333
+ if (!pendingSize) {
29334
+ return;
29335
+ }
29336
+ onUpdateSlideSize?.(pendingSize, mode);
29337
+ setPendingSize(null);
28804
29338
  };
28805
29339
  return /* @__PURE__ */ jsxs("div", { className: CARD, children: [
28806
29340
  /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.slideSize.title") }),
@@ -28856,7 +29390,8 @@ function SlideSizeCard({
28856
29390
  onChange: (e) => onUpdate({ ...canvasSize, [key]: Number(e.target.value) })
28857
29391
  }
28858
29392
  )
28859
- ] }, key)) })
29393
+ ] }, key)) }),
29394
+ pendingSize && /* @__PURE__ */ jsx(SlideSizeRescalePrompt, { onChoose: handleRescale })
28860
29395
  ] })
28861
29396
  ] });
28862
29397
  }
@@ -29515,6 +30050,7 @@ function PresentationPropertiesPanel({
29515
30050
  onUpdateCanvasSize,
29516
30051
  slideSizeEmu,
29517
30052
  onUpdateSlideSize,
30053
+ hasContent,
29518
30054
  notesCanvasSize,
29519
30055
  notesMaster,
29520
30056
  handoutMaster,
@@ -29574,7 +30110,8 @@ function PresentationPropertiesPanel({
29574
30110
  slideSizeEmu,
29575
30111
  canEdit,
29576
30112
  onUpdate: onUpdateCanvasSize,
29577
- onUpdateSlideSize
30113
+ onUpdateSlideSize,
30114
+ hasContent
29578
30115
  }
29579
30116
  ),
29580
30117
  /* @__PURE__ */ jsx(
@@ -29815,6 +30352,7 @@ function InspectorPane(props) {
29815
30352
  canEdit,
29816
30353
  activeSlide,
29817
30354
  slides,
30355
+ customShows,
29818
30356
  canvasSize,
29819
30357
  selectedElement,
29820
30358
  selectedElementIds,
@@ -29842,6 +30380,8 @@ function InspectorPane(props) {
29842
30380
  onApplyTheme,
29843
30381
  comments,
29844
30382
  commentDraft,
30383
+ commentDraftMentions,
30384
+ commentAuthors,
29845
30385
  editingCommentId,
29846
30386
  commentEditDraft,
29847
30387
  onSetCommentDraft,
@@ -29858,6 +30398,7 @@ function InspectorPane(props) {
29858
30398
  onSubmitReply,
29859
30399
  replyingToCommentId,
29860
30400
  replyDraftByCommentId,
30401
+ replyDraftMentionsByCommentId,
29861
30402
  onUpdateCanvasSize,
29862
30403
  slideSizeEmu,
29863
30404
  onUpdateSlideSize,
@@ -29949,6 +30490,7 @@ function InspectorPane(props) {
29949
30490
  selectedElement,
29950
30491
  canEdit,
29951
30492
  slides,
30493
+ customShows,
29952
30494
  tableEditorState,
29953
30495
  mediaDataUrls,
29954
30496
  onUpdateElement,
@@ -29982,6 +30524,7 @@ function InspectorPane(props) {
29982
30524
  onUpdateCanvasSize,
29983
30525
  slideSizeEmu,
29984
30526
  onUpdateSlideSize,
30527
+ hasContent: slides.some((slide) => slide.elements.length > 0),
29985
30528
  activeSlide,
29986
30529
  theme,
29987
30530
  onUpdateSlide
@@ -30010,8 +30553,11 @@ function InspectorPane(props) {
30010
30553
  editingCommentId,
30011
30554
  commentEditDraft,
30012
30555
  commentDraft,
30556
+ commentDraftMentions: commentDraftMentions ?? [],
30557
+ commentAuthors: commentAuthors ?? [],
30013
30558
  replyingToCommentId: replyingToCommentId ?? null,
30014
30559
  replyDraftByCommentId: replyDraftByCommentId ?? {},
30560
+ replyDraftMentionsByCommentId: replyDraftMentionsByCommentId ?? {},
30015
30561
  onSetCommentDraft,
30016
30562
  onAddComment,
30017
30563
  onDeleteComment,
@@ -30828,13 +31374,45 @@ function PresentationTransitionOverlay({
30828
31374
  style: { zIndex: outgoingZIndex },
30829
31375
  children: [
30830
31376
  /* @__PURE__ */ jsx("style", { children: SLIDE_TRANSITION_KEYFRAMES }),
31377
+ !morphPlan && animations.incoming !== "none" && incomingSlide ? /* @__PURE__ */ jsx(
31378
+ "div",
31379
+ {
31380
+ "data-pptx-transition-layer": "incoming",
31381
+ className: "pptx-react-transition-layer absolute inset-0 flex items-center justify-center",
31382
+ style: {
31383
+ animation: animations.incoming,
31384
+ zIndex: animations.outgoingOnTop ? 0 : 10
31385
+ },
31386
+ children: /* @__PURE__ */ jsx(
31387
+ "div",
31388
+ {
31389
+ style: {
31390
+ width: canvasSize.width,
31391
+ height: canvasSize.height,
31392
+ flexShrink: 0,
31393
+ transform: `scale(${scale})`,
31394
+ transformOrigin: "center"
31395
+ },
31396
+ children: /* @__PURE__ */ jsx(
31397
+ SlideLayer,
31398
+ {
31399
+ slide: incomingSlide,
31400
+ templateElements,
31401
+ canvasSize
31402
+ }
31403
+ )
31404
+ }
31405
+ )
31406
+ }
31407
+ ) : null,
30831
31408
  /* @__PURE__ */ jsx(
30832
31409
  "div",
30833
31410
  {
30834
31411
  "data-pptx-transition-layer": "outgoing",
30835
31412
  className: "pptx-react-transition-layer absolute inset-0 flex items-center justify-center",
30836
31413
  style: {
30837
- animation: animations.outgoing !== "none" ? animations.outgoing : void 0
31414
+ animation: animations.outgoing !== "none" ? animations.outgoing : void 0,
31415
+ zIndex: animations.outgoingOnTop ? 10 : 0
30838
31416
  },
30839
31417
  children: /* @__PURE__ */ jsx(
30840
31418
  "div",
@@ -33063,6 +33641,7 @@ function ViewerInspector({
33063
33641
  mode,
33064
33642
  activeSlide,
33065
33643
  slides,
33644
+ customShows,
33066
33645
  canvasSize,
33067
33646
  selectedElement,
33068
33647
  effectiveSelectedIds,
@@ -33070,6 +33649,7 @@ function ViewerInspector({
33070
33649
  sidebarPanelMode,
33071
33650
  activeSlideIndex,
33072
33651
  comments,
33652
+ commentAuthors,
33073
33653
  onSetSidebarPanelMode,
33074
33654
  onClose,
33075
33655
  onUpdateElementStyle,
@@ -33129,6 +33709,7 @@ function ViewerInspector({
33129
33709
  mode,
33130
33710
  activeSlide,
33131
33711
  slides,
33712
+ customShows,
33132
33713
  canvasSize,
33133
33714
  selectedElement,
33134
33715
  selectedElementIds: effectiveSelectedIds,
@@ -33161,9 +33742,11 @@ function ViewerInspector({
33161
33742
  onUpdateTagCollections,
33162
33743
  onApplyTheme,
33163
33744
  commentDraft,
33745
+ commentDraftMentions: comments.commentDraftMentionsBySlideId?.[slideId] ?? [],
33746
+ commentAuthors: commentAuthors ?? [],
33164
33747
  editingCommentId,
33165
33748
  commentEditDraft: editingCommentId ? comments.commentEditDraftByCommentId[editingCommentId] ?? "" : "",
33166
- onSetCommentDraft: (draft) => comments.handleCommentDraftChange(slideId, draft),
33749
+ onSetCommentDraft: (draft, mentions) => comments.handleCommentDraftChange(slideId, draft, mentions),
33167
33750
  onAddComment: () => comments.handleAddSlideComment(activeSlideIndex),
33168
33751
  onDeleteComment: (id) => comments.handleDeleteSlideComment(activeSlideIndex, id),
33169
33752
  onStartEditComment: (id) => comments.handleStartCommentEdit(slideId, id),
@@ -33176,10 +33759,11 @@ function ViewerInspector({
33176
33759
  onToggleCommentResolved: (id) => comments.handleToggleCommentResolved(activeSlideIndex, id),
33177
33760
  onStartReply: (id) => comments.handleStartReply(activeSlideIndex, id),
33178
33761
  onCancelReply: comments.handleCancelReply,
33179
- onReplyDraftChange: (commentId, draft) => comments.handleReplyDraftChange(commentId, draft),
33762
+ onReplyDraftChange: (commentId, draft, mentions) => comments.handleReplyDraftChange(commentId, draft, mentions),
33180
33763
  onSubmitReply: (commentId) => comments.handleSubmitReply(activeSlideIndex, commentId),
33181
33764
  replyingToCommentId: comments.replyingToCommentId,
33182
33765
  replyDraftByCommentId: comments.replyDraftByCommentId,
33766
+ replyDraftMentionsByCommentId: comments.replyDraftMentionsByCommentId,
33183
33767
  onUpdateCanvasSize: onSetCanvasSize,
33184
33768
  slideSizeEmu,
33185
33769
  onUpdateSlideSize: onSetSlideSize,
@@ -33423,6 +34007,7 @@ function ViewerToolbarSection(props) {
33423
34007
  customFontFamilies,
33424
34008
  ops,
33425
34009
  onSetMode,
34010
+ onPresentFromBeginning,
33426
34011
  onEnterPresenterView,
33427
34012
  onEnterRehearsalMode,
33428
34013
  onOpenSettings,
@@ -33441,7 +34026,10 @@ function ViewerToolbarSection(props) {
33441
34026
  isAiPanelOpen,
33442
34027
  onToggleAiPanel,
33443
34028
  isProtectedView,
33444
- onEnableEditing
34029
+ onEnableEditing,
34030
+ onSetSnapToGrid,
34031
+ onSetSnapToShape,
34032
+ onSetShowGuides
33445
34033
  } = props;
33446
34034
  const { t } = useTranslation();
33447
34035
  const handleAddAnimation = useCallback(
@@ -33618,7 +34206,7 @@ function ViewerToolbarSection(props) {
33618
34206
  case "slideShow":
33619
34207
  switch (action) {
33620
34208
  case "fromBeginning":
33621
- onSetMode("present");
34209
+ (onPresentFromBeginning ?? (() => onSetMode("present")))();
33622
34210
  break;
33623
34211
  case "presenterView":
33624
34212
  onEnterPresenterView();
@@ -33667,6 +34255,7 @@ function ViewerToolbarSection(props) {
33667
34255
  dialogs,
33668
34256
  zoom,
33669
34257
  onSetMode,
34258
+ onPresentFromBeginning,
33670
34259
  onEnterPresenterView,
33671
34260
  manipulation,
33672
34261
  handleOpenSlideSize
@@ -33675,7 +34264,7 @@ function ViewerToolbarSection(props) {
33675
34264
  const handleQuickAccessCommand = useCallback(
33676
34265
  (id) => {
33677
34266
  const handlers = {
33678
- presentFromStart: () => onSetMode("present"),
34267
+ presentFromStart: onPresentFromBeginning ?? (() => onSetMode("present")),
33679
34268
  print: printHandlers.handlePrint,
33680
34269
  exportPdf: exportHandlers.handleExportPdf,
33681
34270
  newSlide: slideOps.handleAddSlide,
@@ -33685,7 +34274,7 @@ function ViewerToolbarSection(props) {
33685
34274
  };
33686
34275
  handlers[id]?.();
33687
34276
  },
33688
- [onSetMode, printHandlers, exportHandlers, slideOps, s, zoom]
34277
+ [onSetMode, onPresentFromBeginning, printHandlers, exportHandlers, slideOps, s, zoom]
33689
34278
  );
33690
34279
  return /* @__PURE__ */ jsxs(Fragment, { children: [
33691
34280
  !dialogs.isNarrowViewport && /* @__PURE__ */ jsx(
@@ -33744,6 +34333,7 @@ function ViewerToolbarSection(props) {
33744
34333
  drawingWidth: s.drawingWidth,
33745
34334
  clipboardPayload: s.clipboardPayload,
33746
34335
  onSetMode,
34336
+ onPresentFromBeginning,
33747
34337
  onToggleSidebar: () => s.setIsSlidesPaneOpen((p) => !p),
33748
34338
  onToggleInspector: () => s.setIsInspectorPaneOpen((p) => !p),
33749
34339
  onOpenAnimationPanel: () => {
@@ -33788,9 +34378,9 @@ function ViewerToolbarSection(props) {
33788
34378
  onSetSpellCheckEnabled: s.setSpellCheckEnabled,
33789
34379
  onSetShowGrid: s.setShowGrid,
33790
34380
  onSetShowRulers: s.setShowRulers,
33791
- onSetShowGuides: s.setShowGuides,
33792
- onSetSnapToGrid: s.setSnapToGrid,
33793
- onSetSnapToShape: s.setSnapToShape,
34381
+ onSetShowGuides: onSetShowGuides ?? s.setShowGuides,
34382
+ onSetSnapToGrid: onSetSnapToGrid ?? s.setSnapToGrid,
34383
+ onSetSnapToShape: onSetSnapToShape ?? s.setSnapToShape,
33794
34384
  onAddGuide: dialogs.handleAddGuide,
33795
34385
  onAlignElements: manipulation.handleAlignElements,
33796
34386
  onDistributeElements: manipulation.handleDistributeElements,
@@ -34531,6 +35121,7 @@ function ViewerPresentationLayer(props) {
34531
35121
  templateElements,
34532
35122
  presentation,
34533
35123
  activeCustomShow,
35124
+ authoredRange,
34534
35125
  onExitPresentation,
34535
35126
  isMobile,
34536
35127
  onUpdateNotes
@@ -34544,6 +35135,8 @@ function ViewerPresentationLayer(props) {
34544
35135
  currentSlideIndex: presentation.presentationSlideIndex,
34545
35136
  canvasSize,
34546
35137
  templateElements,
35138
+ activeCustomShow,
35139
+ authoredRange,
34547
35140
  presentationStartTime: presentation.presentationStartTime,
34548
35141
  onMovePresentationSlide: presentation.movePresentationSlide,
34549
35142
  onExit: onExitPresentation
@@ -34556,6 +35149,7 @@ function ViewerPresentationLayer(props) {
34556
35149
  canvasSize,
34557
35150
  templateElements,
34558
35151
  activeCustomShow,
35152
+ authoredRange,
34559
35153
  presentationStartTime: presentation.presentationStartTime,
34560
35154
  onMovePresentationSlide: presentation.movePresentationSlide,
34561
35155
  onExit: onExitPresentation,
@@ -34912,14 +35506,14 @@ ${url}`)) {
34912
35506
  [viewerOptions, t]
34913
35507
  );
34914
35508
  const handleActionClick = useCallback(
34915
- (_elementId, action) => {
35509
+ (elementId, action) => {
34916
35510
  if (mode === "present") {
34917
35511
  const resolved = resolvePresentationAction(action, { slideCount: slides.length });
34918
35512
  if (resolved.intent.kind === "openUrl") {
34919
35513
  openExternalUrl(resolved.intent.url);
34920
35514
  return;
34921
35515
  }
34922
- presentation.handlePresentationAction(action);
35516
+ presentation.handlePresentationAction(action, elementId);
34923
35517
  } else if (action.url) {
34924
35518
  openExternalUrl(action.url);
34925
35519
  }
@@ -35323,7 +35917,7 @@ ${url}`)) {
35323
35917
  var AiChatPanel = lazy(async () => {
35324
35918
  const [{ useChat }, { default: Panel }] = await Promise.all([
35325
35919
  import('@ai-sdk/react'),
35326
- import('./AiChatPanel-BNFDBP4S.mjs')
35920
+ import('./AiChatPanel-AIM55U76.mjs')
35327
35921
  ]);
35328
35922
  function BoundAiChatPanel(props) {
35329
35923
  return /* @__PURE__ */ jsx(Panel, { ...props, useChat });
@@ -36230,7 +36824,10 @@ function ViewerSidePanels(props) {
36230
36824
  aiBridge,
36231
36825
  aiPanel
36232
36826
  } = props;
36233
- const handleSetSlideSize = (size) => {
36827
+ const handleSetSlideSize = (size, rescaleMode) => {
36828
+ if (rescaleMode && s.slideSizeEmu) {
36829
+ s.setSlides(scaleSlidesForSizeChange(slides, s.slideSizeEmu, size, rescaleMode));
36830
+ }
36234
36831
  s.setSlideSizeEmu(size);
36235
36832
  s.setCanvasSize(slideSizeToCanvasPx(size));
36236
36833
  history.markDirty();
@@ -36249,6 +36846,7 @@ function ViewerSidePanels(props) {
36249
36846
  mode,
36250
36847
  activeSlide: effectiveSlide,
36251
36848
  slides,
36849
+ customShows: s.customShows,
36252
36850
  canvasSize,
36253
36851
  selectedElement,
36254
36852
  effectiveSelectedIds: s.effectiveSelectedIds,
@@ -36256,6 +36854,7 @@ function ViewerSidePanels(props) {
36256
36854
  sidebarPanelMode: s.sidebarPanelMode,
36257
36855
  activeSlideIndex,
36258
36856
  comments,
36857
+ commentAuthors: s.modernCommentAuthors,
36259
36858
  onSetSidebarPanelMode: s.setSidebarPanelMode,
36260
36859
  onClose: () => s.setIsInspectorPaneOpen(false),
36261
36860
  onUpdateElementStyle: ops.updateSelectedShapeStyle,
@@ -36396,6 +36995,7 @@ function ViewerMainContent(props) {
36396
36995
  themeHandlers,
36397
36996
  history,
36398
36997
  comments,
36998
+ masterViewCrud,
36399
36999
  zoom,
36400
37000
  isMobile: _isMobile = false,
36401
37001
  isTouchDevice: _isTouchDevice = false,
@@ -36480,6 +37080,8 @@ function ViewerMainContent(props) {
36480
37080
  onSelectLayout: dialogs.handleSelectLayout,
36481
37081
  onCollapse: dialogs.handleCloseMasterView,
36482
37082
  onTabChange: state.setMasterViewTab,
37083
+ crudActions: masterViewCrud.crudActions,
37084
+ onCrudAction: masterViewCrud.handleCrudAction,
36483
37085
  onHandoutSlidesPerPageChange: (count) => {
36484
37086
  state.setHandoutSlidesPerPage(count);
36485
37087
  state.setHandoutMaster(
@@ -36673,7 +37275,61 @@ function AutosaveRecoveryDialog({
36673
37275
  }
36674
37276
  );
36675
37277
  }
36676
- function ToggleRow({ checked, onChange, icon, label }) {
37278
+ function CompatibilityToasts({ toasts, onDismiss, onDismissAll }) {
37279
+ const { t } = useTranslation();
37280
+ if (toasts.length === 0) {
37281
+ return null;
37282
+ }
37283
+ return /* @__PURE__ */ jsxs(
37284
+ "div",
37285
+ {
37286
+ "data-testid": "pptx-compat-toasts",
37287
+ className: "max-h-[60%] overflow-y-auto",
37288
+ style: compatToastStackStyle(),
37289
+ children: [
37290
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-1", style: { pointerEvents: "auto" }, children: [
37291
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: t("pptx.compatibility.toastTitle") }),
37292
+ /* @__PURE__ */ jsx(
37293
+ "button",
37294
+ {
37295
+ type: "button",
37296
+ "data-testid": "pptx-compat-toasts-dismiss-all",
37297
+ onClick: onDismissAll,
37298
+ className: "text-[11px] text-muted-foreground underline-offset-2 hover:underline",
37299
+ children: t("pptx.compatibility.dismissAll")
37300
+ }
37301
+ )
37302
+ ] }),
37303
+ toasts.map((toast) => /* @__PURE__ */ jsxs(
37304
+ "div",
37305
+ {
37306
+ "data-testid": "pptx-compat-toast",
37307
+ "data-code": toast.code,
37308
+ "data-severity": toast.severity,
37309
+ className: "flex items-start gap-2 rounded border border-border bg-card p-2 text-[11px] shadow-md",
37310
+ style: { pointerEvents: "auto" },
37311
+ children: [
37312
+ /* @__PURE__ */ jsx("span", { className: "flex-1 min-w-0", children: t(toast.messageKey, toast.params) }),
37313
+ /* @__PURE__ */ jsx(
37314
+ "button",
37315
+ {
37316
+ type: "button",
37317
+ "data-testid": "pptx-compat-toast-dismiss",
37318
+ onClick: () => onDismiss(toast.id),
37319
+ "aria-label": t("pptx.compatibility.dismiss"),
37320
+ className: "shrink-0 text-muted-foreground hover:text-foreground",
37321
+ children: "\xD7"
37322
+ }
37323
+ )
37324
+ ]
37325
+ },
37326
+ toast.id
37327
+ ))
37328
+ ]
37329
+ }
37330
+ );
37331
+ }
37332
+ function ToggleRow({ checked, onChange, icon, label, testId }) {
36677
37333
  return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2.5 cursor-pointer group select-none", children: [
36678
37334
  /* @__PURE__ */ jsxs("span", { className: "relative flex items-center justify-center w-4 h-4", children: [
36679
37335
  /* @__PURE__ */ jsx(
@@ -36682,6 +37338,7 @@ function ToggleRow({ checked, onChange, icon, label }) {
36682
37338
  type: "checkbox",
36683
37339
  checked,
36684
37340
  onChange: (e) => onChange(e.target.checked),
37341
+ "data-testid": testId,
36685
37342
  className: "peer sr-only"
36686
37343
  }
36687
37344
  ),
@@ -36695,25 +37352,33 @@ function ToggleRow({ checked, onChange, icon, label }) {
36695
37352
  ] });
36696
37353
  }
36697
37354
  function HeaderFooterPanel({
36698
- showDateTime,
36699
- showSlideNumber,
36700
- showFooter,
36701
- footerText,
36702
- onSetShowDateTime,
36703
- onSetShowSlideNumber,
36704
- onSetShowFooter,
36705
- onSetFooterText,
37355
+ headerFooter,
37356
+ onUpdate,
36706
37357
  onApplyToAll,
36707
37358
  onApplyToCurrent,
36708
37359
  onClose
36709
37360
  }) {
37361
+ const { t } = useTranslation();
37362
+ const showDateTime = headerFooter.hasDateTime ?? false;
37363
+ const dateTimeAuto = headerFooter.dateTimeAuto ?? false;
37364
+ const showDateText = isHeaderFooterDateTextVisible(headerFooter);
37365
+ const showSlideNumber = headerFooter.hasSlideNumber ?? false;
37366
+ const showHeader = headerFooter.hasHeader ?? false;
37367
+ const showHeaderText = isHeaderFooterHeaderTextVisible(headerFooter);
37368
+ const showFooter = headerFooter.hasFooter ?? false;
37369
+ const showFooterText = isHeaderFooterFooterTextVisible(headerFooter);
37370
+ const handleDateTextChange = useCallback(
37371
+ (e) => onUpdate({ dateTimeText: e.target.value }),
37372
+ [onUpdate]
37373
+ );
37374
+ const handleHeaderTextChange = useCallback(
37375
+ (e) => onUpdate({ headerText: e.target.value }),
37376
+ [onUpdate]
37377
+ );
36710
37378
  const handleFooterTextChange = useCallback(
36711
- (e) => {
36712
- onSetFooterText(e.target.value);
36713
- },
36714
- [onSetFooterText]
37379
+ (e) => onUpdate({ footerText: e.target.value }),
37380
+ [onUpdate]
36715
37381
  );
36716
- const { t } = useTranslation();
36717
37382
  return /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm rounded-lg border border-border bg-background shadow-2xl", children: [
36718
37383
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
36719
37384
  /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-foreground", children: t("pptx.headerFooter.title") }),
@@ -36724,6 +37389,7 @@ function HeaderFooterPanel({
36724
37389
  onClick: onClose,
36725
37390
  className: "rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors",
36726
37391
  "aria-label": t("pptx.headerFooter.close"),
37392
+ "data-testid": "header-footer-close",
36727
37393
  children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
36728
37394
  }
36729
37395
  )
@@ -36733,36 +37399,84 @@ function HeaderFooterPanel({
36733
37399
  ToggleRow,
36734
37400
  {
36735
37401
  checked: showDateTime,
36736
- onChange: onSetShowDateTime,
37402
+ onChange: (hasDateTime) => onUpdate({ hasDateTime }),
36737
37403
  icon: /* @__PURE__ */ jsx(LuCalendarDays, { className: "w-3.5 h-3.5" }),
36738
- label: t("pptx.headerFooter.dateAndTime")
37404
+ label: t("pptx.headerFooter.dateAndTime"),
37405
+ testId: "hf-date-time"
36739
37406
  }
36740
37407
  ),
37408
+ showDateTime && /* @__PURE__ */ jsxs("div", { className: "pl-6 space-y-2", children: [
37409
+ /* @__PURE__ */ jsx(
37410
+ ToggleRow,
37411
+ {
37412
+ checked: dateTimeAuto,
37413
+ onChange: (auto) => onUpdate({ dateTimeAuto: auto }),
37414
+ icon: /* @__PURE__ */ jsx(LuClock, { className: "w-3.5 h-3.5" }),
37415
+ label: t("pptx.headerFooter.updateAutomatically"),
37416
+ testId: "hf-date-auto"
37417
+ }
37418
+ ),
37419
+ showDateText && /* @__PURE__ */ jsx(
37420
+ "input",
37421
+ {
37422
+ type: "text",
37423
+ value: headerFooter.dateTimeText ?? "",
37424
+ onChange: handleDateTextChange,
37425
+ placeholder: t("pptx.headerFooter.fixedDate"),
37426
+ "data-testid": "hf-date-text",
37427
+ className: "w-full rounded border border-border bg-muted px-2.5 py-1.5 text-xs text-foreground placeholder-muted-foreground outline-none transition-colors focus:border-primary focus:ring-1 focus:ring-primary/30"
37428
+ }
37429
+ )
37430
+ ] }),
36741
37431
  /* @__PURE__ */ jsx(
36742
37432
  ToggleRow,
36743
37433
  {
36744
37434
  checked: showSlideNumber,
36745
- onChange: onSetShowSlideNumber,
37435
+ onChange: (hasSlideNumber) => onUpdate({ hasSlideNumber }),
36746
37436
  icon: /* @__PURE__ */ jsx(LuHash, { className: "w-3.5 h-3.5" }),
36747
- label: t("pptx.headerFooter.slideNumber")
37437
+ label: t("pptx.headerFooter.slideNumber"),
37438
+ testId: "hf-slide-number"
36748
37439
  }
36749
37440
  ),
37441
+ /* @__PURE__ */ jsx(
37442
+ ToggleRow,
37443
+ {
37444
+ checked: showHeader,
37445
+ onChange: (hasHeader) => onUpdate({ hasHeader }),
37446
+ icon: /* @__PURE__ */ jsx(LuFileText, { className: "w-3.5 h-3.5" }),
37447
+ label: t("pptx.field.header"),
37448
+ testId: "hf-header"
37449
+ }
37450
+ ),
37451
+ showHeaderText && /* @__PURE__ */ jsx("div", { className: "pl-6", children: /* @__PURE__ */ jsx(
37452
+ "input",
37453
+ {
37454
+ type: "text",
37455
+ value: headerFooter.headerText ?? "",
37456
+ onChange: handleHeaderTextChange,
37457
+ placeholder: t("pptx.headerFooter.headerText"),
37458
+ "data-testid": "hf-header-text",
37459
+ className: "w-full rounded border border-border bg-muted px-2.5 py-1.5 text-xs text-foreground placeholder-muted-foreground outline-none transition-colors focus:border-primary focus:ring-1 focus:ring-primary/30"
37460
+ }
37461
+ ) }),
36750
37462
  /* @__PURE__ */ jsx(
36751
37463
  ToggleRow,
36752
37464
  {
36753
37465
  checked: showFooter,
36754
- onChange: onSetShowFooter,
37466
+ onChange: (hasFooter) => onUpdate({ hasFooter }),
36755
37467
  icon: /* @__PURE__ */ jsx(LuText, { className: "w-3.5 h-3.5" }),
36756
- label: t("pptx.headerFooter.footer")
37468
+ label: t("pptx.headerFooter.footer"),
37469
+ testId: "hf-footer"
36757
37470
  }
36758
37471
  ),
36759
- showFooter && /* @__PURE__ */ jsx("div", { className: "pl-6", children: /* @__PURE__ */ jsx(
37472
+ showFooterText && /* @__PURE__ */ jsx("div", { className: "pl-6", children: /* @__PURE__ */ jsx(
36760
37473
  "input",
36761
37474
  {
36762
37475
  type: "text",
36763
- value: footerText,
37476
+ value: headerFooter.footerText ?? "",
36764
37477
  onChange: handleFooterTextChange,
36765
37478
  placeholder: t("pptx.headerFooter.footerPlaceholder"),
37479
+ "data-testid": "hf-footer-text",
36766
37480
  className: "w-full rounded border border-border bg-muted px-2.5 py-1.5 text-xs text-foreground placeholder-muted-foreground outline-none transition-colors focus:border-primary focus:ring-1 focus:ring-primary/30"
36767
37481
  }
36768
37482
  ) })
@@ -36773,6 +37487,7 @@ function HeaderFooterPanel({
36773
37487
  {
36774
37488
  type: "button",
36775
37489
  onClick: onApplyToAll,
37490
+ "data-testid": "hf-apply-all",
36776
37491
  className: "rounded bg-accent px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent/80 transition-colors",
36777
37492
  children: t("pptx.headerFooter.applyToAll")
36778
37493
  }
@@ -36782,6 +37497,7 @@ function HeaderFooterPanel({
36782
37497
  {
36783
37498
  type: "button",
36784
37499
  onClick: onApplyToCurrent,
37500
+ "data-testid": "hf-apply-current",
36785
37501
  className: "rounded bg-primary px-3 py-1.5 text-xs font-medium text-white hover:bg-primary/80 transition-colors",
36786
37502
  children: t("pptx.headerFooter.applyToCurrent")
36787
37503
  }
@@ -36986,6 +37702,41 @@ function MobileChromeOverlay(props) {
36986
37702
  )
36987
37703
  ] });
36988
37704
  }
37705
+ function ReadOnlyBanner({ recommendation, onEditAnyway, onDismiss }) {
37706
+ const { t } = useTranslation();
37707
+ return /* @__PURE__ */ jsxs(
37708
+ "div",
37709
+ {
37710
+ "data-testid": "pptx-readonly-banner",
37711
+ "data-kind": recommendation.kind ?? void 0,
37712
+ className: "flex items-center gap-3 px-3 py-1.5 bg-amber-600/10 border-b border-amber-600/30 text-[12px] text-amber-900 dark:text-amber-200",
37713
+ children: [
37714
+ /* @__PURE__ */ jsx("span", { className: "flex-1 min-w-0", children: t(recommendation.messageKey) }),
37715
+ /* @__PURE__ */ jsx(
37716
+ "button",
37717
+ {
37718
+ type: "button",
37719
+ "data-testid": "pptx-readonly-edit-anyway",
37720
+ onClick: onEditAnyway,
37721
+ className: "shrink-0 rounded-sm bg-amber-600/90 px-2 py-0.5 text-[11px] text-amber-50 transition-colors hover:bg-amber-600",
37722
+ children: t("pptx.readOnly.editAnyway")
37723
+ }
37724
+ ),
37725
+ /* @__PURE__ */ jsx(
37726
+ "button",
37727
+ {
37728
+ type: "button",
37729
+ "data-testid": "pptx-readonly-dismiss",
37730
+ onClick: onDismiss,
37731
+ "aria-label": t("pptx.readOnly.dismiss"),
37732
+ className: "shrink-0 rounded-sm px-1.5 py-0.5 text-[11px] text-amber-900/80 transition-colors hover:bg-amber-600/20 dark:text-amber-200/80",
37733
+ children: t("pptx.readOnly.dismiss")
37734
+ }
37735
+ )
37736
+ ]
37737
+ }
37738
+ );
37739
+ }
36989
37740
  function AddinTable({
36990
37741
  title,
36991
37742
  rows,
@@ -38131,6 +38882,109 @@ function useAiPanelController(input) {
38131
38882
  showChangeBatch
38132
38883
  };
38133
38884
  }
38885
+ function useMasterViewCrud(input) {
38886
+ const {
38887
+ handlerRef,
38888
+ slides,
38889
+ slideMasters,
38890
+ target,
38891
+ setSlides,
38892
+ setSlideMasters,
38893
+ setActiveMasterIndex,
38894
+ setActiveLayoutIndex,
38895
+ markDirty,
38896
+ pushToast
38897
+ } = input;
38898
+ const { t } = useTranslation();
38899
+ const data = useMemo(
38900
+ () => ({ slides, slideMasters }),
38901
+ [slides, slideMasters]
38902
+ );
38903
+ const crudActions = useMemo(() => masterViewCrudActions(data, target), [data, target]);
38904
+ const handleCrudAction = useCallback(
38905
+ async (id) => {
38906
+ const handler = handlerRef.current;
38907
+ if (!handler || !target) {
38908
+ return;
38909
+ }
38910
+ const action = crudActions.find((candidate) => candidate.id === id);
38911
+ if (!action?.enabled) {
38912
+ return;
38913
+ }
38914
+ let name;
38915
+ if (id === "renameLayout" || id === "renameMaster") {
38916
+ const master = slideMasters[target.masterIndex];
38917
+ const current = id === "renameLayout" ? master?.layouts?.[target.layoutIndex ?? -1]?.name ?? "" : master?.name ?? "";
38918
+ const next = safePrompt(t("pptx.masterView.renamePrompt"), current)?.trim();
38919
+ if (!next) {
38920
+ return;
38921
+ }
38922
+ name = next;
38923
+ }
38924
+ const result = await applyMasterViewCrudAction(
38925
+ handler,
38926
+ data,
38927
+ id,
38928
+ target,
38929
+ name !== void 0 ? { name } : void 0
38930
+ );
38931
+ if (!result.ok) {
38932
+ pushToast({
38933
+ id: `master-crud-${Date.now()}`,
38934
+ code: `masterViewCrud:${result.reason}`,
38935
+ severity: "warning",
38936
+ messageKey: masterViewCrudFailureKey(id, result.reason)
38937
+ });
38938
+ return;
38939
+ }
38940
+ handlerRef.current = result.handler;
38941
+ setSlides(result.data.slides);
38942
+ setSlideMasters(result.data.slideMasters ?? []);
38943
+ setActiveMasterIndex(result.target.masterIndex);
38944
+ setActiveLayoutIndex(result.target.layoutIndex);
38945
+ markDirty();
38946
+ },
38947
+ [
38948
+ handlerRef,
38949
+ target,
38950
+ crudActions,
38951
+ slideMasters,
38952
+ t,
38953
+ data,
38954
+ pushToast,
38955
+ setSlides,
38956
+ setSlideMasters,
38957
+ setActiveMasterIndex,
38958
+ setActiveLayoutIndex,
38959
+ markDirty
38960
+ ]
38961
+ );
38962
+ return { crudActions, handleCrudAction };
38963
+ }
38964
+ function applyRecentColorPick(recent, hex) {
38965
+ const next = pushRecentColor(recent, hex);
38966
+ if (next === recent) {
38967
+ return null;
38968
+ }
38969
+ return { recentColors: next, patch: mruColorsPatch(next) };
38970
+ }
38971
+ function useRecentColorsSync(input) {
38972
+ const { setRecentColors, setPresentationProperties } = input;
38973
+ const pushColor = useCallback(
38974
+ (hex) => {
38975
+ setRecentColors((prev) => {
38976
+ const applied = applyRecentColorPick(prev, hex);
38977
+ if (!applied) {
38978
+ return prev;
38979
+ }
38980
+ setPresentationProperties((properties) => ({ ...properties, ...applied.patch }));
38981
+ return applied.recentColors;
38982
+ });
38983
+ },
38984
+ [setRecentColors, setPresentationProperties]
38985
+ );
38986
+ return { pushColor };
38987
+ }
38134
38988
  var PowerPointViewer = forwardRef(
38135
38989
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the forwardRef component its displayName
38136
38990
  function PowerPointViewer2(props, ref) {
@@ -38277,7 +39131,9 @@ var PowerPointViewer = forwardRef(
38277
39131
  const handleEnableEditing = useCallback(() => {
38278
39132
  setProtectedViewOverridden(true);
38279
39133
  }, []);
38280
- const canEdit = hostCanEdit && !isProtectedView;
39134
+ const readOnlyRec = useReadOnlyRecommendationState(content);
39135
+ const compatToastsState = useCompatibilityToastsState();
39136
+ const canEdit = hostCanEdit && !isProtectedView && !readOnlyRec.locked;
38281
39137
  const [isSettingsOpen, setIsSettingsOpen] = useState(false);
38282
39138
  const [isHeaderFooterOpen, setIsHeaderFooterOpen] = useState(false);
38283
39139
  const [autosaveEnabled, setAutosaveEnabled] = useState(true);
@@ -38304,6 +39160,14 @@ var PowerPointViewer = forwardRef(
38304
39160
  activeSlide,
38305
39161
  selectedElement
38306
39162
  } = state;
39163
+ const { pushColor } = useRecentColorsSync({
39164
+ setRecentColors: state.setRecentColors,
39165
+ setPresentationProperties: state.setPresentationProperties
39166
+ });
39167
+ const recentColorsValue = useMemo(
39168
+ () => ({ recentColors: state.recentColors, pushColor }),
39169
+ [state.recentColors, pushColor]
39170
+ );
38307
39171
  const settings = useMemo(
38308
39172
  () => ({
38309
39173
  autoSave: autosaveEnabled,
@@ -38418,11 +39282,18 @@ var PowerPointViewer = forwardRef(
38418
39282
  const mobile = useIsMobile();
38419
39283
  const { isMobile, isTouchDevice, isVirtualKeyboardOpen } = mobile;
38420
39284
  const resizablePanels = useResizablePanels();
38421
- const { gridSpacingPx, visibleSlideIndexes, slideSectionGroups, masterPseudoSlide } = useDerivedSlideState({
39285
+ const {
39286
+ gridSpacingPx,
39287
+ visibleSlideIndexes,
39288
+ slideSectionGroups,
39289
+ masterPseudoSlide,
39290
+ authoredRange
39291
+ } = useDerivedSlideState({
38422
39292
  slides,
38423
39293
  sections: state.sections,
38424
39294
  customShows: state.customShows,
38425
39295
  activeCustomShowId: state.activeCustomShowId,
39296
+ presentationProperties: state.presentationProperties,
38426
39297
  mode,
38427
39298
  activeLayout: state.activeLayout,
38428
39299
  activeMaster: state.activeMaster,
@@ -38501,7 +39372,10 @@ var PowerPointViewer = forwardRef(
38501
39372
  onToggleSubtitles: () => state.setPresentationProperties((prev) => ({
38502
39373
  ...prev,
38503
39374
  showSubtitles: !prev.showSubtitles
38504
- }))
39375
+ })),
39376
+ customShows: state.customShows,
39377
+ activeCustomShowId: state.activeCustomShowId,
39378
+ onSetActiveCustomShowId: state.setActiveCustomShowId
38505
39379
  });
38506
39380
  useTouchGestures({
38507
39381
  targetRef: zoom.canvasViewportRef,
@@ -38631,6 +39505,8 @@ var PowerPointViewer = forwardRef(
38631
39505
  // (SSRF/privacy-safe), so only an explicit `true` here lets remote
38632
39506
  // http(s) image sources actually load.
38633
39507
  allowExternalImages: viewerOptions.trust.allowExternalContent,
39508
+ setReadOnlyRecommendation: readOnlyRec.setRecommendation,
39509
+ setCompatToasts: compatToastsState.setToasts,
38634
39510
  canEdit,
38635
39511
  promptKeepInkAnnotations: viewerOptions.advanced.slideShowPromptKeepInkAnnotations,
38636
39512
  // File > Options > Advanced > "Image Size and Quality" (do-not-compress /
@@ -38658,6 +39534,17 @@ var PowerPointViewer = forwardRef(
38658
39534
  onSelectionChange,
38659
39535
  onSlideCountChange
38660
39536
  });
39537
+ const viewPreferencesSync = useViewPreferencesSync({
39538
+ loadVersion,
39539
+ viewProperties: state.viewProperties,
39540
+ setViewProperties: state.setViewProperties,
39541
+ snapToGrid: state.snapToGrid,
39542
+ setSnapToGrid: state.setSnapToGrid,
39543
+ snapToShape: state.snapToShape,
39544
+ setSnapToShape: state.setSnapToShape,
39545
+ showGuides: state.showGuides,
39546
+ setShowGuides: state.setShowGuides
39547
+ });
38661
39548
  const exportHandlers = useMemo(() => {
38662
39549
  const afterSuccessfulSave = (format) => {
38663
39550
  playFeedbackSound(viewerOptions);
@@ -38692,6 +39579,22 @@ var PowerPointViewer = forwardRef(
38692
39579
  history,
38693
39580
  onTemplateElementsChanged: handleTemplateElementsChanged
38694
39581
  });
39582
+ const masterViewCrud = useMasterViewCrud({
39583
+ handlerRef,
39584
+ slides,
39585
+ slideMasters: state.slideMasters,
39586
+ target: {
39587
+ tab: state.masterViewTab,
39588
+ masterIndex: state.activeMasterIndex,
39589
+ layoutIndex: state.activeLayoutIndex
39590
+ },
39591
+ setSlides: state.setSlides,
39592
+ setSlideMasters: state.setSlideMasters,
39593
+ setActiveMasterIndex: state.setActiveMasterIndex,
39594
+ setActiveLayoutIndex: state.setActiveLayoutIndex,
39595
+ markDirty: history.markDirty,
39596
+ pushToast: (toast) => compatToastsState.setToasts((prev) => [...prev, toast])
39597
+ });
38695
39598
  const applyAiTheme = useCallback(
38696
39599
  (updates) => {
38697
39600
  if (updates.colorScheme) {
@@ -38765,7 +39668,7 @@ var PowerPointViewer = forwardRef(
38765
39668
  ref: containerRef,
38766
39669
  tabIndex: 0,
38767
39670
  className: "h-full w-full flex flex-col overflow-hidden outline-none",
38768
- children: loading ? /* @__PURE__ */ jsx(LoadingState, {}) : error ? /* @__PURE__ */ jsx(ErrorState, { error }) : /* @__PURE__ */ jsxs(Fragment, { children: [
39671
+ children: loading ? /* @__PURE__ */ jsx(LoadingState, {}) : error ? /* @__PURE__ */ jsx(ErrorState, { error }) : /* @__PURE__ */ jsxs(RecentColorsProvider, { value: recentColorsValue, children: [
38769
39672
  mode !== "present" && /* @__PURE__ */ jsx(
38770
39673
  ViewerToolbarSection,
38771
39674
  {
@@ -38791,6 +39694,7 @@ var PowerPointViewer = forwardRef(
38791
39694
  customFontFamilies,
38792
39695
  ops: editorOps.ops,
38793
39696
  onSetMode: handleSetMode,
39697
+ onPresentFromBeginning: presentation.enterPresentModeFromBeginning,
38794
39698
  onEnterPresenterView: handleEnterPresenterView,
38795
39699
  onEnterRehearsalMode: handleEnterRehearsalMode,
38796
39700
  onOpenSettings: () => setIsSettingsOpen(true),
@@ -38812,7 +39716,18 @@ var PowerPointViewer = forwardRef(
38812
39716
  isAiPanelOpen: aiPanel.isOpen,
38813
39717
  onToggleAiPanel: aiPanel.toggle,
38814
39718
  isProtectedView,
38815
- onEnableEditing: hostCanEdit ? handleEnableEditing : void 0
39719
+ onEnableEditing: hostCanEdit ? handleEnableEditing : void 0,
39720
+ onSetSnapToGrid: viewPreferencesSync.handleSetSnapToGrid,
39721
+ onSetSnapToShape: viewPreferencesSync.handleSetSnapToShape,
39722
+ onSetShowGuides: viewPreferencesSync.handleSetShowGuides
39723
+ }
39724
+ ),
39725
+ mode !== "present" && readOnlyRec.bannerVisible && /* @__PURE__ */ jsx(
39726
+ ReadOnlyBanner,
39727
+ {
39728
+ recommendation: readOnlyRec.recommendation,
39729
+ onEditAnyway: readOnlyRec.editAnyway,
39730
+ onDismiss: readOnlyRec.dismiss
38816
39731
  }
38817
39732
  ),
38818
39733
  /* @__PURE__ */ jsx(
@@ -38839,6 +39754,7 @@ var PowerPointViewer = forwardRef(
38839
39754
  themeHandlers,
38840
39755
  history,
38841
39756
  comments: editorOps.comments,
39757
+ masterViewCrud,
38842
39758
  zoom,
38843
39759
  isMobile,
38844
39760
  isTouchDevice,
@@ -38898,6 +39814,14 @@ var PowerPointViewer = forwardRef(
38898
39814
  ] })
38899
39815
  }
38900
39816
  ),
39817
+ mode !== "present" && /* @__PURE__ */ jsx(
39818
+ CompatibilityToasts,
39819
+ {
39820
+ toasts: compatToastsState.toasts,
39821
+ onDismiss: compatToastsState.dismiss,
39822
+ onDismissAll: compatToastsState.dismissAll
39823
+ }
39824
+ ),
38901
39825
  /* @__PURE__ */ jsx(
38902
39826
  ViewerDialogGroup,
38903
39827
  {
@@ -38965,14 +39889,8 @@ var PowerPointViewer = forwardRef(
38965
39889
  isHeaderFooterOpen && /* @__PURE__ */ jsx(
38966
39890
  HeaderFooterPanel,
38967
39891
  {
38968
- showDateTime: state.headerFooter.hasDateTime ?? false,
38969
- showSlideNumber: state.headerFooter.hasSlideNumber ?? false,
38970
- showFooter: state.headerFooter.hasFooter ?? false,
38971
- footerText: state.headerFooter.footerText ?? "",
38972
- onSetShowDateTime: (hasDateTime) => state.setHeaderFooter((current) => ({ ...current, hasDateTime })),
38973
- onSetShowSlideNumber: (hasSlideNumber) => state.setHeaderFooter((current) => ({ ...current, hasSlideNumber })),
38974
- onSetShowFooter: (hasFooter) => state.setHeaderFooter((current) => ({ ...current, hasFooter })),
38975
- onSetFooterText: (footerText) => state.setHeaderFooter((current) => ({ ...current, footerText })),
39892
+ headerFooter: state.headerFooter,
39893
+ onUpdate: (patch) => state.setHeaderFooter((current) => ({ ...current, ...patch })),
38976
39894
  onApplyToAll: () => {
38977
39895
  history.markDirty();
38978
39896
  setIsHeaderFooterOpen(false);
@@ -39058,6 +39976,7 @@ var PowerPointViewer = forwardRef(
39058
39976
  templateElements: state.templateElements,
39059
39977
  presentation,
39060
39978
  activeCustomShow,
39979
+ authoredRange,
39061
39980
  onExitPresentation: () => handleSetMode("edit"),
39062
39981
  onUpdateNotes: propertyHandlers.handleUpdateNotes,
39063
39982
  isMobile