pptx-react-viewer 3.8.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/{AiChatPanel-A5DCEHTO.mjs → AiChatPanel-BQSUE2OO.mjs} +4 -4
  3. package/dist/AiChatPanel-BQSUE2OO.mjs.br +0 -0
  4. package/dist/AiChatPanel-BQSUE2OO.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-XLQM4BQJ.js → AiChatPanel-NSVSBJC7.js} +25 -25
  6. package/dist/AiChatPanel-NSVSBJC7.js.br +0 -0
  7. package/dist/AiChatPanel-NSVSBJC7.js.gz +0 -0
  8. package/dist/{Area3DChartScene-5CMEMIBI.mjs → Area3DChartScene-2FQHPGNE.mjs} +21 -4
  9. package/dist/Area3DChartScene-2FQHPGNE.mjs.br +0 -0
  10. package/dist/Area3DChartScene-2FQHPGNE.mjs.gz +0 -0
  11. package/dist/{Area3DChartScene-RZ3V3WOR.js → Area3DChartScene-V3W2V7N5.js} +21 -4
  12. package/dist/Area3DChartScene-V3W2V7N5.js.br +0 -0
  13. package/dist/Area3DChartScene-V3W2V7N5.js.gz +0 -0
  14. package/dist/{Bar3DChartScene-KHCQ6TEC.js → Bar3DChartScene-55XMAUC7.js} +21 -4
  15. package/dist/Bar3DChartScene-55XMAUC7.js.br +0 -0
  16. package/dist/Bar3DChartScene-55XMAUC7.js.gz +0 -0
  17. package/dist/{Bar3DChartScene-H3MYUJKV.mjs → Bar3DChartScene-PSJEVANA.mjs} +21 -4
  18. package/dist/Bar3DChartScene-PSJEVANA.mjs.br +0 -0
  19. package/dist/Bar3DChartScene-PSJEVANA.mjs.gz +0 -0
  20. package/dist/{Line3DChartScene-QEACF3U3.js → Line3DChartScene-5KACYRSQ.js} +21 -4
  21. package/dist/Line3DChartScene-5KACYRSQ.js.br +0 -0
  22. package/dist/Line3DChartScene-5KACYRSQ.js.gz +0 -0
  23. package/dist/{Line3DChartScene-YFRPJHDX.mjs → Line3DChartScene-BUVNUFNO.mjs} +21 -4
  24. package/dist/Line3DChartScene-BUVNUFNO.mjs.br +0 -0
  25. package/dist/Line3DChartScene-BUVNUFNO.mjs.gz +0 -0
  26. package/dist/{Model3DScene-QQWKGJ3T.js → Model3DScene-6U6TN36M.js} +2 -2
  27. package/dist/Model3DScene-6U6TN36M.js.br +0 -0
  28. package/dist/Model3DScene-6U6TN36M.js.gz +0 -0
  29. package/dist/{Model3DScene-O24KP723.mjs → Model3DScene-REKMR2L6.mjs} +1 -1
  30. package/dist/{Model3DScene-O24KP723.mjs.br → Model3DScene-REKMR2L6.mjs.br} +0 -0
  31. package/dist/Model3DScene-REKMR2L6.mjs.gz +0 -0
  32. package/dist/{PieChart3DScene-CI6CW22C.mjs → PieChart3DScene-4L2VVIUJ.mjs} +15 -4
  33. package/dist/PieChart3DScene-4L2VVIUJ.mjs.br +0 -0
  34. package/dist/PieChart3DScene-4L2VVIUJ.mjs.gz +0 -0
  35. package/dist/{PieChart3DScene-L3MHKQHW.js → PieChart3DScene-MV3JF7EM.js} +15 -4
  36. package/dist/PieChart3DScene-MV3JF7EM.js.br +0 -0
  37. package/dist/PieChart3DScene-MV3JF7EM.js.gz +0 -0
  38. package/dist/{SmartArt3DScene-ZO3KFDI2.js → SmartArt3DScene-BK7QN3WT.js} +85 -23
  39. package/dist/SmartArt3DScene-BK7QN3WT.js.br +0 -0
  40. package/dist/SmartArt3DScene-BK7QN3WT.js.gz +0 -0
  41. package/dist/{SmartArt3DScene-XCFVGCXE.mjs → SmartArt3DScene-ODKCGJBO.mjs} +85 -23
  42. package/dist/SmartArt3DScene-ODKCGJBO.mjs.br +0 -0
  43. package/dist/SmartArt3DScene-ODKCGJBO.mjs.gz +0 -0
  44. package/dist/{SurfaceChart3DScene-JUXRC3K2.mjs → SurfaceChart3DScene-ARE7OBFI.mjs} +19 -4
  45. package/dist/SurfaceChart3DScene-ARE7OBFI.mjs.br +0 -0
  46. package/dist/SurfaceChart3DScene-ARE7OBFI.mjs.gz +0 -0
  47. package/dist/{SurfaceChart3DScene-5IER6VFW.js → SurfaceChart3DScene-SFIOK3G3.js} +19 -4
  48. package/dist/SurfaceChart3DScene-SFIOK3G3.js.br +0 -0
  49. package/dist/SurfaceChart3DScene-SFIOK3G3.js.gz +0 -0
  50. package/dist/{chunk-SN5EUDIT.js → chunk-2Q2NFPXA.js} +81834 -57577
  51. package/dist/chunk-2Q2NFPXA.js.br +0 -0
  52. package/dist/chunk-2Q2NFPXA.js.gz +0 -0
  53. package/dist/chunk-DNR6CH6I.js +30 -0
  54. package/dist/chunk-DNR6CH6I.js.br +0 -0
  55. package/dist/chunk-DNR6CH6I.js.gz +0 -0
  56. package/dist/{chunk-4222CHFH.js → chunk-DZ3HWACD.js} +3763 -2551
  57. package/dist/chunk-DZ3HWACD.js.br +0 -0
  58. package/dist/chunk-DZ3HWACD.js.gz +0 -0
  59. package/dist/{chunk-DE3S3UHX.js → chunk-FHOUTYMB.js} +536 -448
  60. package/dist/chunk-FHOUTYMB.js.br +0 -0
  61. package/dist/chunk-FHOUTYMB.js.gz +0 -0
  62. package/dist/{chunk-UPJW34YG.mjs → chunk-HJZA3O3S.mjs} +103 -16
  63. package/dist/chunk-HJZA3O3S.mjs.br +0 -0
  64. package/dist/chunk-HJZA3O3S.mjs.gz +0 -0
  65. package/dist/{chunk-F5NPGNMA.js → chunk-HYUPPQJW.js} +6168 -1929
  66. package/dist/chunk-HYUPPQJW.js.br +0 -0
  67. package/dist/chunk-HYUPPQJW.js.gz +0 -0
  68. package/dist/{chunk-PFPKBNNZ.mjs → chunk-KWHURCVT.mjs} +1771 -559
  69. package/dist/chunk-KWHURCVT.mjs.br +0 -0
  70. package/dist/chunk-KWHURCVT.mjs.gz +0 -0
  71. package/dist/{chunk-RHWQKZLB.mjs → chunk-M6GIPAY4.mjs} +23 -7
  72. package/dist/chunk-M6GIPAY4.mjs.br +0 -0
  73. package/dist/chunk-M6GIPAY4.mjs.gz +0 -0
  74. package/dist/{chunk-RNP5HP4L.mjs → chunk-T4ZRSRQZ.mjs} +6164 -1925
  75. package/dist/chunk-T4ZRSRQZ.mjs.br +0 -0
  76. package/dist/chunk-T4ZRSRQZ.mjs.gz +0 -0
  77. package/dist/chunk-T6GFCLSM.mjs +27 -0
  78. package/dist/chunk-T6GFCLSM.mjs.br +4 -0
  79. package/dist/chunk-T6GFCLSM.mjs.gz +0 -0
  80. package/dist/{chunk-FRZIBZTE.mjs → chunk-TAGG5YNA.mjs} +76 -1
  81. package/dist/chunk-TAGG5YNA.mjs.br +0 -0
  82. package/dist/chunk-TAGG5YNA.mjs.gz +0 -0
  83. package/dist/{chunk-6IMB5DNJ.mjs → chunk-UKPGYJ7G.mjs} +90204 -65968
  84. package/dist/chunk-UKPGYJ7G.mjs.br +0 -0
  85. package/dist/chunk-UKPGYJ7G.mjs.gz +0 -0
  86. package/dist/{chunk-QWA5YEIZ.js → chunk-XW46A7DN.js} +194 -178
  87. package/dist/chunk-XW46A7DN.js.br +0 -0
  88. package/dist/chunk-XW46A7DN.js.gz +0 -0
  89. package/dist/{chunk-L3ZIBQEB.js → chunk-Y6GG2OOW.js} +76 -1
  90. package/dist/chunk-Y6GG2OOW.js.br +0 -0
  91. package/dist/chunk-Y6GG2OOW.js.gz +0 -0
  92. package/dist/i18n.js +4 -4
  93. package/dist/i18n.js.br +0 -0
  94. package/dist/i18n.js.gz +0 -0
  95. package/dist/i18n.mjs +1 -1
  96. package/dist/i18n.mjs.br +0 -0
  97. package/dist/i18n.mjs.gz +0 -0
  98. package/dist/index-CGKutKk1.d.ts.map +1 -1
  99. package/dist/index.d.ts +616 -99
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +47 -47
  102. package/dist/index.js.br +0 -0
  103. package/dist/index.js.gz +0 -0
  104. package/dist/index.mjs +6 -6
  105. package/dist/index.mjs.br +0 -0
  106. package/dist/index.mjs.gz +0 -0
  107. package/dist/internals.d.ts +657 -86
  108. package/dist/internals.d.ts.map +1 -1
  109. package/dist/internals.js +79 -79
  110. package/dist/internals.js.br +0 -0
  111. package/dist/internals.js.gz +0 -0
  112. package/dist/internals.mjs +4 -4
  113. package/dist/internals.mjs.br +0 -0
  114. package/dist/internals.mjs.gz +0 -0
  115. package/dist/pptx-viewer.css +1 -1
  116. package/dist/pptx-viewer.css.br +0 -0
  117. package/dist/pptx-viewer.css.gz +0 -0
  118. package/dist/{useViewerBuildingBlocks-C8F_4Pzb.d.ts → useViewerBuildingBlocks-FbK-4ORi.d.ts} +2 -1
  119. package/dist/useViewerBuildingBlocks-FbK-4ORi.d.ts.map +1 -0
  120. package/dist/viewer/index.d.ts +545 -48
  121. package/dist/viewer/index.d.ts.map +1 -1
  122. package/dist/viewer/index.js +27 -27
  123. package/dist/viewer/index.js.br +0 -0
  124. package/dist/viewer/index.js.gz +0 -0
  125. package/dist/viewer/index.mjs +6 -6
  126. package/dist/viewer/index.mjs.br +0 -0
  127. package/dist/viewer/index.mjs.gz +0 -0
  128. package/package.json +9 -9
  129. package/dist/AiChatPanel-A5DCEHTO.mjs.br +0 -0
  130. package/dist/AiChatPanel-A5DCEHTO.mjs.gz +0 -0
  131. package/dist/AiChatPanel-XLQM4BQJ.js.br +0 -0
  132. package/dist/AiChatPanel-XLQM4BQJ.js.gz +0 -0
  133. package/dist/Area3DChartScene-5CMEMIBI.mjs.br +0 -0
  134. package/dist/Area3DChartScene-5CMEMIBI.mjs.gz +0 -0
  135. package/dist/Area3DChartScene-RZ3V3WOR.js.br +0 -0
  136. package/dist/Area3DChartScene-RZ3V3WOR.js.gz +0 -0
  137. package/dist/Bar3DChartScene-H3MYUJKV.mjs.br +0 -0
  138. package/dist/Bar3DChartScene-H3MYUJKV.mjs.gz +0 -0
  139. package/dist/Bar3DChartScene-KHCQ6TEC.js.br +0 -0
  140. package/dist/Bar3DChartScene-KHCQ6TEC.js.gz +0 -0
  141. package/dist/Line3DChartScene-QEACF3U3.js.br +0 -0
  142. package/dist/Line3DChartScene-QEACF3U3.js.gz +0 -0
  143. package/dist/Line3DChartScene-YFRPJHDX.mjs.br +0 -0
  144. package/dist/Line3DChartScene-YFRPJHDX.mjs.gz +0 -0
  145. package/dist/Model3DScene-O24KP723.mjs.gz +0 -0
  146. package/dist/Model3DScene-QQWKGJ3T.js.br +0 -0
  147. package/dist/Model3DScene-QQWKGJ3T.js.gz +0 -0
  148. package/dist/PieChart3DScene-CI6CW22C.mjs.br +0 -0
  149. package/dist/PieChart3DScene-CI6CW22C.mjs.gz +0 -0
  150. package/dist/PieChart3DScene-L3MHKQHW.js.br +0 -0
  151. package/dist/PieChart3DScene-L3MHKQHW.js.gz +0 -0
  152. package/dist/SmartArt3DScene-XCFVGCXE.mjs.br +0 -0
  153. package/dist/SmartArt3DScene-XCFVGCXE.mjs.gz +0 -0
  154. package/dist/SmartArt3DScene-ZO3KFDI2.js.br +0 -0
  155. package/dist/SmartArt3DScene-ZO3KFDI2.js.gz +0 -0
  156. package/dist/SurfaceChart3DScene-5IER6VFW.js.br +0 -0
  157. package/dist/SurfaceChart3DScene-5IER6VFW.js.gz +0 -0
  158. package/dist/SurfaceChart3DScene-JUXRC3K2.mjs.br +0 -0
  159. package/dist/SurfaceChart3DScene-JUXRC3K2.mjs.gz +0 -0
  160. package/dist/chunk-4222CHFH.js.br +0 -0
  161. package/dist/chunk-4222CHFH.js.gz +0 -0
  162. package/dist/chunk-6IMB5DNJ.mjs.br +0 -0
  163. package/dist/chunk-6IMB5DNJ.mjs.gz +0 -0
  164. package/dist/chunk-DE3S3UHX.js.br +0 -0
  165. package/dist/chunk-DE3S3UHX.js.gz +0 -0
  166. package/dist/chunk-F5NPGNMA.js.br +0 -0
  167. package/dist/chunk-F5NPGNMA.js.gz +0 -0
  168. package/dist/chunk-FRZIBZTE.mjs.br +0 -0
  169. package/dist/chunk-FRZIBZTE.mjs.gz +0 -0
  170. package/dist/chunk-L3ZIBQEB.js.br +0 -0
  171. package/dist/chunk-L3ZIBQEB.js.gz +0 -0
  172. package/dist/chunk-PFPKBNNZ.mjs.br +0 -0
  173. package/dist/chunk-PFPKBNNZ.mjs.gz +0 -0
  174. package/dist/chunk-QWA5YEIZ.js.br +0 -0
  175. package/dist/chunk-QWA5YEIZ.js.gz +0 -0
  176. package/dist/chunk-RHWQKZLB.mjs.br +0 -0
  177. package/dist/chunk-RHWQKZLB.mjs.gz +0 -0
  178. package/dist/chunk-RNP5HP4L.mjs.br +0 -0
  179. package/dist/chunk-RNP5HP4L.mjs.gz +0 -0
  180. package/dist/chunk-SN5EUDIT.js.br +0 -0
  181. package/dist/chunk-SN5EUDIT.js.gz +0 -0
  182. package/dist/chunk-UPJW34YG.mjs.br +0 -0
  183. package/dist/chunk-UPJW34YG.mjs.gz +0 -0
  184. package/dist/useViewerBuildingBlocks-C8F_4Pzb.d.ts.map +0 -1
@@ -1,9 +1,9 @@
1
- import { computeFocusTargets, deckDataFieldChanged, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs, applyElementUpdate } from './chunk-RNP5HP4L.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-UPJW34YG.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, STROKE_DASH_OPTIONS } from './chunk-RHWQKZLB.mjs';
4
- import { hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, connectorWrapperTransform, getAriaRoleDescription, getAriaLabel, getAriaRole, resolveElementInteractivity, isEditableTextElement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, 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, buildThemeColorMap, viewerOptionsToPreferences, applyPreferenceToOptions, listAutosaveSnapshots, deleteAutosaveSnapshot, resolveExpiredAutosaveSnapshots, resolveHistoryDepth, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, resolve3DRenderingFlags, resolveSlideSizeSelection, buildDeckSaveOptions, paintedStrokeWidth, buildCssGradientFromShapeStyle, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, isImageLikeElement, getComputedFillStyle, strokeOutlineViewBox, getElementTransform, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, canDrillDown, computeSmartArtElementLayout, flattenNodes, buildSummaryZoomView, isImageTiled, getImageColorWashStyle, readEditableText, placeCaretAtEnd, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, resolveChartKind, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, isWedgeCalloutPresetShape, isElementActionable, RULER_THICKNESS, RULER_FONT_SIZE, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, hiddenSlideCue, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, visibleTemplateElements, 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, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, modelDataToBlobUrl, getImageSvgFilters, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, getInlineEditorSelection, findChartPartTarget, advanceChartMarkDrag, advanceChartValueDrag, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, buildSurfaceChart3DDataForElement, buildBarChart3DDataForElement, buildLineChart3DDataForElement, buildAreaChart3DDataForElement, buildPieChart3DDataForElement, withChartTitle, buildSmartArt3DModel, collectCoherent3DOffNodeIds, 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, textFontSizePtToPx, INSERT_CHART_TYPES, CHARACTER_SPACING_OPTIONS, OFFICE_COLOR_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, shouldShowElementHandles, 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, textFontSizePxToPt, buildFontCatalog, buildThemeColorSwatchGrid, themeColorSwatchRows, findSelectedThemeSwatch, themeSwatchCommit, 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, applyTableStyleDelete, applyTableStyleMapChange, 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, tableStyleAssignmentUpdate, evenColumnWidths, redistributeColumnWidth, evenRowHeights, patchChartData, collapseChartTitleRunsForEdit, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, canInteractWithElement, buildOleObjectNamePatch, getOleObjectTypeLabel, sanitizeGradientStops, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, 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, normalizeTableStyleGuid, describeTableStyleEditor, TABLE_STYLE_EDITOR_PARTS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, CHART_TYPE_OPTIONS, BAR3D_SHAPE_OPTIONS, bar3DShapePatch, RADAR_STYLE_OPTIONS, radarStylePatch, SURFACE_WIREFRAME_OPTIONS, surfaceWireframePatch, isSeriesUsingSecondaryAxis, listChartUserShapeDescriptors, withChartUserShapeAdded, createDefaultChartUserShape, withChartUserShapeRemoved, withChartUserShapeUpdated, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, addSmartArtNodeAsChild, removeSmartArtNode, addSiblingAfter, removeEmptyNode, demote, promote, reorder, clampCropValue, DUOTONE_PRESETS, ARTISTIC_EFFECTS, mediaTrimEndSeconds, trimmedMediaDurationMs, mediaTrimEndAbsoluteMs, mediaTrimEndMsFromAbsoluteMs, getNonVisualDescriptionFields, 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, TABLE_STYLE_BORDER_SIDES, applyTableStyleFieldEdit, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, switchSmartArtLayout, mediaTrimEndMsFromSeconds, validateMediaTrimRange, 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, TABLE_STYLE_BORDER_SIDE_LABEL_KEYS, TABLE_STYLE_DASH_PRESETS, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS } from './chunk-6IMB5DNJ.mjs';
5
- import { LOCALE_CATALOG, translationsEn } from './chunk-FRZIBZTE.mjs';
6
- import React19, { createContext, useMemo, useState, useCallback, lazy, forwardRef, useEffect, useRef, Suspense, useLayoutEffect, useContext, Fragment as Fragment$1, useDeferredValue } from 'react';
1
+ import { computeFocusTargets, deckDataFieldChanged, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs, applyElementUpdate } from './chunk-T4ZRSRQZ.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, playAnimationSound } from './chunk-HJZA3O3S.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, STROKE_DASH_OPTIONS } from './chunk-M6GIPAY4.mjs';
4
+ import { hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, connectorWrapperTransform, getAriaRoleDescription, getAriaLabel, getAriaRole, resolveElementInteractivity, isEditableTextElement, buildTextStyleOverrideCss, isElementRendered, resolveElementAriaAttributes, 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, buildThemeColorMap, viewerOptionsToPreferences, applyPreferenceToOptions, listAutosaveSnapshots, deleteAutosaveSnapshot, resolveExpiredAutosaveSnapshots, resolveHistoryDepth, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, resolve3DRenderingFlags, resolveSlideSizeSelection, buildDeckSaveOptions, paintedStrokeWidth, buildCssGradientFromShapeStyle, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, resolveElementHighlightClick, applyHighlightClickStyle, getComputedEffectStyle, getSoftEdgeSvgFilter, getEffectStyleSource, buildStrokeOutline, buildHollowHitOutline, buildSubpathFillOverlay, isImageLikeElement, strokeOutlineViewBox, getElementTransform, resolveRevealedSmartArtNodes, resolveRevealedDrawingShapes, buildSmartArtA11y, canDrillDown, computeSmartArtElementLayout, flattenNodes, buildSummaryZoomView, isImageTiled, getImageColorWashStyle, readEditableText, placeCaretAtEnd, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, resolveChartKind, subscribeBarFacePicturePixelSamples, getBarFacePicturePixelSampleVersion, ensureChartInteractionStyles, applyChartPartHighlight, resolveRevealedChartData, formatAxisValue, buildInkGroupStrokes, getInkReplayStyles, INK_REPLAY_KEYFRAMES, buildContentPartStrokes, getContentPartReplayStyles, resolveOleType, getOleAriaLabel, getOleTypeColor, getOleTypeLabel, filterRenderedElements, resolveGroupChildFill, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getTextBodyRotationTransform, placeholderPromptDescriptor, RULER_THICKNESS, RULER_FONT_SIZE, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, hiddenSlideCue, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, visibleTemplateElements, 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, resolveRevealedDrawingShapeNodeIds, styleShadowFilter, buildChromeStyle, modelDataToBlobUrl, getImageSvgFilters, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, getInlineEditorSelection, findChartPartTarget, buildSurfaceChart3DDataForElement, buildBarChart3DDataForElement, buildLineChart3DDataForElement, buildAreaChart3DDataForElement, buildPieChart3DDataForElement, withChartTitle, buildSmartArt3DModel, collectCoherent3DOffNodeIds, isBrowserOpenableMime, formatBytes, getOleDisplayName, getOleBadgeLabel, openUrlInNewTab, getSubstituteFontFamily, hasGlyphEnvelope, buildGlyphEnvelope, getWarpPath, isWedgeCalloutPresetShape, isElementActionable, 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, advanceChartMarkDrag, advanceChartValueDrag, buildChartMarkDragGeometry, beginChartMarkDrag, beginChartValueDrag, groupIntoParagraphs, substituteFieldText, extraQuickAccessCommands, TAB_ROW_ACTION_CLASSES, listBackstageRecentFiles, BACKSTAGE_NAV, COMMON_FONT_SIZES, textFontSizePtToPx, INSERT_CHART_TYPES, CHARACTER_SPACING_OPTIONS, OFFICE_COLOR_SWATCHES, shapeFillChange, shapeOutlineChange, readRibbonTransitionDraft, ribbonTransitionUpdates, 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, shouldShowElementHandles, 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, withChartPointValue, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, resolveDefaultFontFamily, textFontSizePxToPt, buildFontCatalog, buildThemeColorSwatchGrid, themeColorSwatchRows, findSelectedThemeSwatch, themeSwatchCommit, RIBBON_SHAPE_SWATCHES, canGroupSelection, canUngroupSelection, canSetStrokeWidth, strokeWidthOf, readSoundFileAsDataUrl, applyTransitionSoundFile, TRANSITION_SOUND_OTHER_VALUE, TRANSITION_SOUND_NONE_VALUE, clearTransitionSound, applyTransitionStockSound, transitionStockSoundId, getEffectSoundAsset, 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, applyTableStyleDelete, applyTableStyleMapChange, themeColorLabel, buildThemeColorGrid, THEME_COLOR_SCHEME_KEYS, COMMON_FONTS, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, isCurrentLayout, SLIDE_TEMPLATES, computeAnchoredPopupPosition, buildLiveInkStrokeView, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, isElementLocked, mergeSlideTransition, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, buildLayoutPreviewGeometry, buildSlideTemplateContent, hasTiltData, elementLockTogglePatch, buildTableDataGrid, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, applyTableStylePreset, tableStyleAssignmentUpdate, evenColumnWidths, redistributeColumnWidth, evenRowHeights, patchChartData, collapseChartTitleRunsForEdit, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, hideChartSeries, restoreFilteredSeries, setDataLabelsRangeCache, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, canInteractWithElement, buildOleObjectNamePatch, getOleObjectTypeLabel, sanitizeGradientStops, shouldShowAccessibilitySection, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, 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, setEffectStockSound, setAfterAnimation, setAfterAnimationColor, DIRECTIONAL_PRESETS, buildAnimationTimelineBars, motionPathPresetIdForPath, EFFECT_SOUND_CATALOGUE, normalizeTableStyleGuid, describeTableStyleEditor, TABLE_STYLE_EDITOR_PARTS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, resolveDisplayedChartType, CHART_TYPE_OPTIONS, BAR3D_SHAPE_OPTIONS, bar3DShapePatch, RADAR_STYLE_OPTIONS, radarStylePatch, SURFACE_WIREFRAME_OPTIONS, surfaceWireframePatch, isSeriesUsingSecondaryAxis, listChartUserShapeRows, withChartUserShapeAdded, createDefaultChartUserShape, withChartUserShapeRowRemoved, withChartUserShapeRowTextUpdated, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, addSmartArtNodeAsChild, removeSmartArtNode, addSiblingAfter, removeEmptyNode, demote, promote, reorder, clampCropValue, DUOTONE_PRESETS, ARTISTIC_EFFECTS, mediaTrimEndSeconds, trimmedMediaDurationMs, mediaTrimEndAbsoluteMs, mediaTrimEndMsFromAbsoluteMs, buildOleEditDialogDescriptor, buildOleContentUpdatePatch, applyOleSheetCellEdit, getOleSheetGrid, applyOleDocumentParagraphEdit, getOleDocumentParagraphs, applyOleNestedDeckElementTextEdit, getOleNestedDeckDetail, replaceOleFile, getNonVisualDescriptionFields, 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, TABLE_STYLE_BORDER_SIDES, applyTableStyleFieldEdit, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, getChartUserShapeGroupTransform, withChartUserShapeGroupChildAdded, createDefaultChartUserShapeGroupChild, withChartUserShapeRowUpdated, getChartUserShapeRowChartBox, withChartUserShapeRowFlipUpdated, withChartUserShapeRowRotationUpdated, withChartUserShapeRowChartBoxUpdated, switchSmartArtLayout, mediaTrimEndMsFromSeconds, validateMediaTrimRange, 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, TABLE_STYLE_BORDER_SIDE_LABEL_KEYS, TABLE_STYLE_DASH_PRESETS, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS } from './chunk-UKPGYJ7G.mjs';
5
+ import { LOCALE_CATALOG, translationsEn } from './chunk-TAGG5YNA.mjs';
6
+ import React20, { createContext, useMemo, useState, useCallback, lazy, forwardRef, useEffect, useRef, Suspense, useLayoutEffect, useContext, useSyncExternalStore, useId, 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
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';
@@ -511,16 +511,16 @@ function LoadingState({ className }) {
511
511
  function FailedToLoad() {
512
512
  return null;
513
513
  }
514
- var LazyArea3DChartScene = React19.lazy(
514
+ var LazyArea3DChartScene = React20.lazy(
515
515
  async () => {
516
516
  try {
517
- return await import('./Area3DChartScene-5CMEMIBI.mjs');
517
+ return await import('./Area3DChartScene-2FQHPGNE.mjs');
518
518
  } catch {
519
519
  return { default: FailedToLoad };
520
520
  }
521
521
  }
522
522
  );
523
- var SceneErrorBoundary = class extends React19.Component {
523
+ var SceneErrorBoundary = class extends React20.Component {
524
524
  constructor(props) {
525
525
  super(props);
526
526
  this.state = { hasError: false };
@@ -532,7 +532,12 @@ var SceneErrorBoundary = class extends React19.Component {
532
532
  return this.state.hasError ? this.props.fallback : this.props.children;
533
533
  }
534
534
  };
535
- function Area3DChartRenderer({ element }) {
535
+ function Area3DChartRenderer({
536
+ element,
537
+ interaction,
538
+ selectedPart,
539
+ textStyle
540
+ }) {
536
541
  const [threeAvailable, setThreeAvailable] = useState(null);
537
542
  useEffect(() => {
538
543
  let cancelled = false;
@@ -561,22 +566,30 @@ function Area3DChartRenderer({ element }) {
561
566
  if (threeAvailable === null) {
562
567
  return /* @__PURE__ */ jsx(LoadingState, {});
563
568
  }
564
- return /* @__PURE__ */ jsx(SceneErrorBoundary, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(LazyArea3DChartScene, { options }) }) });
569
+ return /* @__PURE__ */ jsx(SceneErrorBoundary, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(
570
+ LazyArea3DChartScene,
571
+ {
572
+ options,
573
+ interaction,
574
+ selectedPart,
575
+ textStyle
576
+ }
577
+ ) }) });
565
578
  }
566
579
  var BarChart3DContext = createContext(false);
567
580
  function FailedToLoad2() {
568
581
  return null;
569
582
  }
570
- var LazyBar3DChartScene = React19.lazy(
583
+ var LazyBar3DChartScene = React20.lazy(
571
584
  async () => {
572
585
  try {
573
- return await import('./Bar3DChartScene-H3MYUJKV.mjs');
586
+ return await import('./Bar3DChartScene-PSJEVANA.mjs');
574
587
  } catch {
575
588
  return { default: FailedToLoad2 };
576
589
  }
577
590
  }
578
591
  );
579
- var SceneErrorBoundary2 = class extends React19.Component {
592
+ var SceneErrorBoundary2 = class extends React20.Component {
580
593
  constructor(props) {
581
594
  super(props);
582
595
  this.state = { hasError: false };
@@ -588,7 +601,12 @@ var SceneErrorBoundary2 = class extends React19.Component {
588
601
  return this.state.hasError ? this.props.fallback : this.props.children;
589
602
  }
590
603
  };
591
- function Bar3DChartRenderer({ element }) {
604
+ function Bar3DChartRenderer({
605
+ element,
606
+ interaction,
607
+ selectedPart,
608
+ textStyle
609
+ }) {
592
610
  const [threeAvailable, setThreeAvailable] = useState(null);
593
611
  useEffect(() => {
594
612
  let cancelled = false;
@@ -617,22 +635,64 @@ function Bar3DChartRenderer({ element }) {
617
635
  if (threeAvailable === null) {
618
636
  return /* @__PURE__ */ jsx(LoadingState, {});
619
637
  }
620
- return /* @__PURE__ */ jsx(SceneErrorBoundary2, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(LazyBar3DChartScene, { options }) }) });
638
+ return /* @__PURE__ */ jsx(SceneErrorBoundary2, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(
639
+ LazyBar3DChartScene,
640
+ {
641
+ options,
642
+ interaction,
643
+ selectedPart,
644
+ textStyle
645
+ }
646
+ ) }) });
647
+ }
648
+
649
+ // src/viewer/components/elements/build-chart3d-part-interaction.ts
650
+ function buildChart3DPartInteraction({
651
+ element,
652
+ canEdit,
653
+ onUpdateElement,
654
+ selection,
655
+ setSelection,
656
+ setDragValue
657
+ }) {
658
+ if (!canEdit) {
659
+ return void 0;
660
+ }
661
+ const onSelect = (part) => {
662
+ if (part) {
663
+ setSelection({ elementId: element.id, part });
664
+ } else if (selection?.elementId === element.id) {
665
+ setSelection(null);
666
+ }
667
+ };
668
+ const onValueDragPreview = (_part, value) => {
669
+ setDragValue(value);
670
+ };
671
+ const onValueDragCommit = (part, value) => {
672
+ setDragValue(null);
673
+ if (!onUpdateElement || !element.chartData || part.pointIndex === void 0) {
674
+ return;
675
+ }
676
+ onUpdateElement({
677
+ chartData: withChartPointValue(element.chartData, part.seriesIndex, part.pointIndex, value)
678
+ });
679
+ };
680
+ return { onSelect, onValueDragPreview, onValueDragCommit };
621
681
  }
622
682
  var LineChart3DContext = createContext(false);
623
683
  function FailedToLoad3() {
624
684
  return null;
625
685
  }
626
- var LazyLine3DChartScene = React19.lazy(
686
+ var LazyLine3DChartScene = React20.lazy(
627
687
  async () => {
628
688
  try {
629
- return await import('./Line3DChartScene-YFRPJHDX.mjs');
689
+ return await import('./Line3DChartScene-BUVNUFNO.mjs');
630
690
  } catch {
631
691
  return { default: FailedToLoad3 };
632
692
  }
633
693
  }
634
694
  );
635
- var SceneErrorBoundary3 = class extends React19.Component {
695
+ var SceneErrorBoundary3 = class extends React20.Component {
636
696
  constructor(props) {
637
697
  super(props);
638
698
  this.state = { hasError: false };
@@ -644,7 +704,12 @@ var SceneErrorBoundary3 = class extends React19.Component {
644
704
  return this.state.hasError ? this.props.fallback : this.props.children;
645
705
  }
646
706
  };
647
- function Line3DChartRenderer({ element }) {
707
+ function Line3DChartRenderer({
708
+ element,
709
+ interaction,
710
+ selectedPart,
711
+ textStyle
712
+ }) {
648
713
  const [threeAvailable, setThreeAvailable] = useState(null);
649
714
  useEffect(() => {
650
715
  let cancelled = false;
@@ -673,22 +738,30 @@ function Line3DChartRenderer({ element }) {
673
738
  if (threeAvailable === null) {
674
739
  return /* @__PURE__ */ jsx(LoadingState, {});
675
740
  }
676
- return /* @__PURE__ */ jsx(SceneErrorBoundary3, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(LazyLine3DChartScene, { options }) }) });
741
+ return /* @__PURE__ */ jsx(SceneErrorBoundary3, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(
742
+ LazyLine3DChartScene,
743
+ {
744
+ options,
745
+ interaction,
746
+ selectedPart,
747
+ textStyle
748
+ }
749
+ ) }) });
677
750
  }
678
751
  var PieChart3DContext = createContext(false);
679
752
  function FailedToLoad4() {
680
753
  return null;
681
754
  }
682
- var LazyPieChart3DScene = React19.lazy(
755
+ var LazyPieChart3DScene = React20.lazy(
683
756
  async () => {
684
757
  try {
685
- return await import('./PieChart3DScene-CI6CW22C.mjs');
758
+ return await import('./PieChart3DScene-4L2VVIUJ.mjs');
686
759
  } catch {
687
760
  return { default: FailedToLoad4 };
688
761
  }
689
762
  }
690
763
  );
691
- var SceneErrorBoundary4 = class extends React19.Component {
764
+ var SceneErrorBoundary4 = class extends React20.Component {
692
765
  constructor(props) {
693
766
  super(props);
694
767
  this.state = { hasError: false };
@@ -700,7 +773,11 @@ var SceneErrorBoundary4 = class extends React19.Component {
700
773
  return this.state.hasError ? this.props.fallback : this.props.children;
701
774
  }
702
775
  };
703
- function PieChart3DRenderer({ element }) {
776
+ function PieChart3DRenderer({
777
+ element,
778
+ interaction,
779
+ selectedPart
780
+ }) {
704
781
  const [threeAvailable, setThreeAvailable] = useState(null);
705
782
  useEffect(() => {
706
783
  let cancelled = false;
@@ -729,22 +806,29 @@ function PieChart3DRenderer({ element }) {
729
806
  if (threeAvailable === null) {
730
807
  return /* @__PURE__ */ jsx(LoadingState, {});
731
808
  }
732
- return /* @__PURE__ */ jsx(SceneErrorBoundary4, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(LazyPieChart3DScene, { options }) }) });
809
+ return /* @__PURE__ */ jsx(SceneErrorBoundary4, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(
810
+ LazyPieChart3DScene,
811
+ {
812
+ options,
813
+ interaction,
814
+ selectedPart
815
+ }
816
+ ) }) });
733
817
  }
734
818
  var SurfaceChart3DContext = createContext(false);
735
819
  function FailedToLoad5() {
736
820
  return null;
737
821
  }
738
- var LazySurfaceChart3DScene = React19.lazy(
822
+ var LazySurfaceChart3DScene = React20.lazy(
739
823
  async () => {
740
824
  try {
741
- return await import('./SurfaceChart3DScene-JUXRC3K2.mjs');
825
+ return await import('./SurfaceChart3DScene-ARE7OBFI.mjs');
742
826
  } catch {
743
827
  return { default: FailedToLoad5 };
744
828
  }
745
829
  }
746
830
  );
747
- var SceneErrorBoundary5 = class extends React19.Component {
831
+ var SceneErrorBoundary5 = class extends React20.Component {
748
832
  constructor(props) {
749
833
  super(props);
750
834
  this.state = { hasError: false };
@@ -757,7 +841,10 @@ var SceneErrorBoundary5 = class extends React19.Component {
757
841
  }
758
842
  };
759
843
  function SurfaceChart3DRenderer({
760
- element
844
+ element,
845
+ interaction,
846
+ selectedPart,
847
+ textStyle
761
848
  }) {
762
849
  const [threeAvailable, setThreeAvailable] = useState(null);
763
850
  useEffect(() => {
@@ -787,49 +874,28 @@ function SurfaceChart3DRenderer({
787
874
  if (threeAvailable === null) {
788
875
  return /* @__PURE__ */ jsx(LoadingState, {});
789
876
  }
790
- return /* @__PURE__ */ jsx(SceneErrorBoundary5, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(LazySurfaceChart3DScene, { options }) }) });
877
+ return /* @__PURE__ */ jsx(SceneErrorBoundary5, { fallback: svgFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingState, {}), children: /* @__PURE__ */ jsx(
878
+ LazySurfaceChart3DScene,
879
+ {
880
+ options,
881
+ interaction,
882
+ selectedPart,
883
+ textStyle
884
+ }
885
+ ) }) });
791
886
  }
792
- function ChartElementView({
887
+ function useChartMarkInteraction({
793
888
  element,
794
- editable,
889
+ canEdit,
795
890
  onUpdateElement,
796
- animationState
891
+ viewModel,
892
+ wrapperRef,
893
+ setSelection
797
894
  }) {
798
- const wrapperRef = useRef(null);
799
895
  const dragRef = useRef(null);
800
896
  const markDragRef = useRef(null);
801
- const { selection, setSelection } = useChartPartSelection();
802
897
  const [previewData, setPreviewData] = useState(null);
803
898
  const [dragValue, setDragValue] = useState(null);
804
- const [titleDraft, setTitleDraft] = useState(null);
805
- const selectedPart = selection?.elementId === element.id ? selection.part : null;
806
- const canEdit = editable && Boolean(onUpdateElement);
807
- const use3D = useContext(SurfaceChart3DContext);
808
- const isSurfaceKind = resolveChartKind(element.chartData?.chartType ?? "bar") === "surface";
809
- const use3DBar = useContext(BarChart3DContext);
810
- const isBar3DKind = element.chartData?.chartType === "bar3D";
811
- const use3DLine = useContext(LineChart3DContext);
812
- const isLine3DKind = element.chartData?.chartType === "line3D";
813
- const use3DArea = useContext(AreaChart3DContext);
814
- const isArea3DKind = element.chartData?.chartType === "area3D";
815
- const use3DPie = useContext(PieChart3DContext);
816
- const isPie3DKind = element.chartData?.chartType === "pie3D";
817
- const viewModel = useMemo(
818
- () => canEdit ? buildReactChartViewModel(element) : null,
819
- [canEdit, element]
820
- );
821
- useEffect(ensureChartInteractionStyles, []);
822
- useEffect(() => {
823
- if (!onUpdateElement) {
824
- return;
825
- }
826
- if (!canEdit && selection?.elementId === element.id) {
827
- setSelection(null);
828
- }
829
- }, [canEdit, selection, element.id, setSelection, onUpdateElement]);
830
- useEffect(() => {
831
- applyChartPartHighlight(wrapperRef.current, selectedPart);
832
- });
833
899
  const endDrag = (commit) => {
834
900
  const active = dragRef.current;
835
901
  const markActive = markDragRef.current;
@@ -949,6 +1015,79 @@ function ChartElementView({
949
1015
  endDrag(true);
950
1016
  }
951
1017
  };
1018
+ return {
1019
+ previewData,
1020
+ dragValue,
1021
+ setDragValue,
1022
+ handlePointerDown,
1023
+ handlePointerMove,
1024
+ handlePointerUp
1025
+ };
1026
+ }
1027
+ function ChartElementView({
1028
+ element,
1029
+ editable,
1030
+ onUpdateElement,
1031
+ animationState
1032
+ }) {
1033
+ const wrapperRef = useRef(null);
1034
+ const { selection, setSelection } = useChartPartSelection();
1035
+ const [titleDraft, setTitleDraft] = useState(null);
1036
+ const selectedPart = selection?.elementId === element.id ? selection.part : null;
1037
+ const canEdit = editable && Boolean(onUpdateElement);
1038
+ const use3D = useContext(SurfaceChart3DContext);
1039
+ const isSurfaceKind = resolveChartKind(element.chartData?.chartType ?? "bar") === "surface";
1040
+ const use3DBar = useContext(BarChart3DContext);
1041
+ const isBar3DKind = element.chartData?.chartType === "bar3D";
1042
+ const use3DLine = useContext(LineChart3DContext);
1043
+ const isLine3DKind = element.chartData?.chartType === "line3D";
1044
+ const use3DArea = useContext(AreaChart3DContext);
1045
+ const isArea3DKind = element.chartData?.chartType === "area3D";
1046
+ const use3DPie = useContext(PieChart3DContext);
1047
+ const isPie3DKind = element.chartData?.chartType === "pie3D";
1048
+ const barFacePictureSampleVersion = useSyncExternalStore(
1049
+ subscribeBarFacePicturePixelSamples,
1050
+ getBarFacePicturePixelSampleVersion,
1051
+ getBarFacePicturePixelSampleVersion
1052
+ );
1053
+ const viewModel = useMemo(() => {
1054
+ return canEdit ? buildReactChartViewModel(element) : null;
1055
+ }, [canEdit, element, barFacePictureSampleVersion]);
1056
+ useEffect(ensureChartInteractionStyles, []);
1057
+ useEffect(() => {
1058
+ if (!onUpdateElement) {
1059
+ return;
1060
+ }
1061
+ if (!canEdit && selection?.elementId === element.id) {
1062
+ setSelection(null);
1063
+ }
1064
+ }, [canEdit, selection, element.id, setSelection, onUpdateElement]);
1065
+ useEffect(() => {
1066
+ applyChartPartHighlight(wrapperRef.current, selectedPart);
1067
+ });
1068
+ const {
1069
+ previewData,
1070
+ dragValue,
1071
+ setDragValue,
1072
+ handlePointerDown,
1073
+ handlePointerMove,
1074
+ handlePointerUp
1075
+ } = useChartMarkInteraction({
1076
+ element,
1077
+ canEdit,
1078
+ onUpdateElement,
1079
+ viewModel,
1080
+ wrapperRef,
1081
+ setSelection
1082
+ });
1083
+ const chart3DInteraction = buildChart3DPartInteraction({
1084
+ element,
1085
+ canEdit,
1086
+ onUpdateElement,
1087
+ selection,
1088
+ setSelection,
1089
+ setDragValue
1090
+ });
952
1091
  const handleDoubleClick = (e) => {
953
1092
  if (!canEdit || !canDrillDown(element)) {
954
1093
  return;
@@ -987,7 +1126,46 @@ function ChartElementView({
987
1126
  onPointerUp: handlePointerUp,
988
1127
  onDoubleClick: handleDoubleClick,
989
1128
  children: [
990
- use3D && isSurfaceKind ? /* @__PURE__ */ jsx(SurfaceChart3DRenderer, { element: renderedElement }) : use3DBar && isBar3DKind ? /* @__PURE__ */ jsx(Bar3DChartRenderer, { element: renderedElement }) : use3DLine && isLine3DKind ? /* @__PURE__ */ jsx(Line3DChartRenderer, { element: renderedElement }) : use3DArea && isArea3DKind ? /* @__PURE__ */ jsx(Area3DChartRenderer, { element: renderedElement }) : use3DPie && isPie3DKind ? /* @__PURE__ */ jsx(PieChart3DRenderer, { element: renderedElement }) : renderChartElement(renderedElement),
1129
+ use3D && isSurfaceKind ? /* @__PURE__ */ jsx(
1130
+ SurfaceChart3DRenderer,
1131
+ {
1132
+ element: renderedElement,
1133
+ interaction: chart3DInteraction,
1134
+ selectedPart,
1135
+ textStyle: animationState?.textStyle
1136
+ }
1137
+ ) : use3DBar && isBar3DKind ? /* @__PURE__ */ jsx(
1138
+ Bar3DChartRenderer,
1139
+ {
1140
+ element: renderedElement,
1141
+ interaction: chart3DInteraction,
1142
+ selectedPart,
1143
+ textStyle: animationState?.textStyle
1144
+ }
1145
+ ) : use3DLine && isLine3DKind ? /* @__PURE__ */ jsx(
1146
+ Line3DChartRenderer,
1147
+ {
1148
+ element: renderedElement,
1149
+ interaction: chart3DInteraction,
1150
+ selectedPart,
1151
+ textStyle: animationState?.textStyle
1152
+ }
1153
+ ) : use3DArea && isArea3DKind ? /* @__PURE__ */ jsx(
1154
+ Area3DChartRenderer,
1155
+ {
1156
+ element: renderedElement,
1157
+ interaction: chart3DInteraction,
1158
+ selectedPart,
1159
+ textStyle: animationState?.textStyle
1160
+ }
1161
+ ) : use3DPie && isPie3DKind ? /* @__PURE__ */ jsx(
1162
+ PieChart3DRenderer,
1163
+ {
1164
+ element: renderedElement,
1165
+ interaction: chart3DInteraction,
1166
+ selectedPart
1167
+ }
1168
+ ) : renderChartElement(renderedElement),
991
1169
  dragValue !== null && /* @__PURE__ */ jsx("div", { className: "absolute top-1 right-1 z-10 rounded bg-primary/90 px-1.5 py-0.5 text-[10px] font-medium text-white pointer-events-none", children: formatAxisValue(dragValue) }),
992
1170
  titleDraft !== null && /* @__PURE__ */ jsx(
993
1171
  "input",
@@ -1540,7 +1718,7 @@ function ResizeHandles({
1540
1718
  ))
1541
1719
  ] });
1542
1720
  }
1543
- var ConnectorElementRenderer = React19.memo(
1721
+ var ConnectorElementRenderer = React20.memo(
1544
1722
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
1545
1723
  function ConnectorElementRendererInner({
1546
1724
  el,
@@ -1921,7 +2099,7 @@ function shapeParams(element) {
1921
2099
  const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
1922
2100
  return { hf: hasFill, fc: fillColor, sw: strokeWidth, sc: strokeColor };
1923
2101
  }
1924
- var Extrusion3DOverlay = React19.memo(
2102
+ var Extrusion3DOverlay = React20.memo(
1925
2103
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
1926
2104
  function Extrusion3DOverlayInner({ data }) {
1927
2105
  if (!data.hasExtrusion || data.panels.length === 0) {
@@ -2006,23 +2184,19 @@ function renderOutlinePaint(paint) {
2006
2184
  function ShapeEffectOverlay({
2007
2185
  element,
2008
2186
  animatesFill = false,
2009
- animatesStroke = false
2187
+ animatesStroke = false,
2188
+ suppressReflection = false
2010
2189
  }) {
2011
- if (!hasShapeProperties(element)) {
2012
- return null;
2013
- }
2014
2190
  const fx = getComputedEffectStyle(element);
2015
2191
  const overlay = fx.fillOverlay;
2016
- const reflection = fx.reflection;
2017
- const softEdge = getSoftEdgeSvgFilter(element.shapeStyle, element.id);
2192
+ const reflection = suppressReflection ? void 0 : fx.reflection;
2193
+ const softEdge = getSoftEdgeSvgFilter(getEffectStyleSource(element), element.id);
2018
2194
  const strokeOutline = buildStrokeOutline(element);
2019
2195
  const hollowHit = buildHollowHitOutline(element);
2020
2196
  const subpathFill = buildSubpathFillOverlay(element);
2021
2197
  if (!overlay && !softEdge && !strokeOutline && !hollowHit && !subpathFill && !reflection) {
2022
2198
  return null;
2023
2199
  }
2024
- const reflectionFill = reflection && !isImageLikeElement(element) ? getComputedFillStyle(element) : void 0;
2025
- const reflectionImgSrc = reflection && isImageLikeElement(element) ? imgSrc(element) : void 0;
2026
2200
  const fillOverlayStyle = overlay ? {
2027
2201
  position: "absolute",
2028
2202
  inset: 0,
@@ -2138,44 +2312,12 @@ function ShapeEffectOverlay({
2138
2312
  className: "pptx-react-reflection",
2139
2313
  "aria-hidden": "true",
2140
2314
  style: reflection,
2141
- children: reflectionImgSrc ? /* @__PURE__ */ jsx(
2142
- "div",
2143
- {
2144
- className: "pptx-react-reflection-picture-surface",
2145
- style: getImageSurfaceStyle(element),
2146
- children: /* @__PURE__ */ jsx(
2147
- "img",
2148
- {
2149
- src: reflectionImgSrc,
2150
- alt: "",
2151
- draggable: false,
2152
- style: {
2153
- width: "100%",
2154
- height: "100%",
2155
- ...getImageRenderStyle(element)
2156
- }
2157
- }
2158
- )
2159
- }
2160
- ) : reflectionFill ? /* @__PURE__ */ jsx(
2161
- "div",
2162
- {
2163
- style: {
2164
- width: "100%",
2165
- height: "100%",
2166
- backgroundColor: reflectionFill.backgroundColor,
2167
- backgroundImage: reflectionFill.backgroundImage,
2168
- backgroundSize: reflectionFill.backgroundSize,
2169
- backgroundPosition: reflectionFill.backgroundPosition,
2170
- backgroundRepeat: reflectionFill.backgroundRepeat
2171
- }
2172
- }
2173
- ) : null
2315
+ children: /* @__PURE__ */ jsx(StaticElementRenderer, { element, positioned: false, suppressReflection: true })
2174
2316
  }
2175
2317
  ) : null
2176
2318
  ] });
2177
2319
  }
2178
- var ElementRenderer = React19.memo(
2320
+ var ElementRenderer = React20.memo(
2179
2321
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
2180
2322
  function ElementRendererInner({
2181
2323
  element: el,
@@ -2482,22 +2624,10 @@ var ElementRenderer = React19.memo(
2482
2624
  );
2483
2625
  }
2484
2626
  );
2485
- function renderPressureStroke(pathD, widths, baseWidth, color, opacity, keyPrefix) {
2486
- const points = extractPathPoints(pathD);
2487
- const circles = generatePressureCircles(points, widths, {
2488
- baseWidth,
2489
- minRadius: 0.5,
2490
- maxRadius: baseWidth * 1.5
2491
- });
2627
+ function renderPressureStroke(circles, color, opacity, keyPrefix) {
2492
2628
  return /* @__PURE__ */ jsx("g", { opacity, children: circles.map((c, j) => /* @__PURE__ */ jsx("circle", { cx: c.cx, cy: c.cy, r: c.r, fill: color }, `${keyPrefix}-pc-${j}`)) });
2493
2629
  }
2494
- function renderNibMarkStroke(pathD, widths, tiltAngles, tiltMagnitudes, baseWidth, color, opacity, keyPrefix) {
2495
- const points = extractPathPoints(pathD);
2496
- const marks = generateNibMarks(points, widths, tiltAngles, tiltMagnitudes, {
2497
- baseWidth,
2498
- minRadius: 0.5,
2499
- maxRadius: baseWidth * 1.5
2500
- });
2630
+ function renderNibMarkStroke(marks, color, opacity, keyPrefix) {
2501
2631
  return /* @__PURE__ */ jsx("g", { opacity, children: marks.map((m, j) => /* @__PURE__ */ jsx(
2502
2632
  "ellipse",
2503
2633
  {
@@ -2511,10 +2641,41 @@ function renderNibMarkStroke(pathD, widths, tiltAngles, tiltMagnitudes, baseWidt
2511
2641
  `${keyPrefix}-nib-${j}`
2512
2642
  )) });
2513
2643
  }
2644
+ function renderStrokeView(view, pressureSensitive, replayStyle, key) {
2645
+ if (view.nibMarks) {
2646
+ return /* @__PURE__ */ jsx("g", { children: renderNibMarkStroke(view.nibMarks, view.color, view.opacity, key) }, key);
2647
+ }
2648
+ if (pressureSensitive && view.circles) {
2649
+ return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(view.circles, view.color, view.opacity, key) }, key);
2650
+ }
2651
+ return /* @__PURE__ */ jsx(
2652
+ "path",
2653
+ {
2654
+ d: view.d,
2655
+ fill: "none",
2656
+ stroke: view.color,
2657
+ strokeWidth: view.width,
2658
+ strokeOpacity: view.opacity,
2659
+ strokeLinecap: "round",
2660
+ strokeLinejoin: "round",
2661
+ vectorEffect: "non-scaling-stroke",
2662
+ ...replayStyle ? {
2663
+ strokeDasharray: replayStyle.strokeDasharray,
2664
+ strokeDashoffset: replayStyle.strokeDashoffset,
2665
+ style: {
2666
+ animation: replayStyle.animation,
2667
+ "--ink-path-length": replayStyle.pathLength
2668
+ }
2669
+ } : {}
2670
+ },
2671
+ key
2672
+ );
2673
+ }
2514
2674
  function renderInk(el, options) {
2515
2675
  const replay = options?.replay ?? false;
2516
- Boolean(el.inkPointPressures) && el.inkPointPressures.length > 0;
2517
- Boolean(el.inkWidths) && el.inkWidths.length > 1 && hasPressureVariation(el.inkWidths);
2676
+ const strokes = buildInkGroupStrokes(el, { color: "#000", width: 3 });
2677
+ strokes.some((s) => s.circles || s.nibMarks);
2678
+ const pressureSensitive = options?.pressureSensitive;
2518
2679
  const replayStyles = replay ? getInkReplayStyles(el, options?.replayConfig) : null;
2519
2680
  return /* @__PURE__ */ jsxs(
2520
2681
  "svg",
@@ -2524,44 +2685,9 @@ function renderInk(el, options) {
2524
2685
  preserveAspectRatio: "none",
2525
2686
  children: [
2526
2687
  replay && /* @__PURE__ */ jsx("style", { children: INK_REPLAY_KEYFRAMES }),
2527
- el.inkPaths.map((d, i) => {
2528
- const color = resolveInkColor(el.inkColors, i);
2529
- const width = resolveInkWidth(el.inkWidths, i);
2530
- const opacity = resolveInkOpacity(el.inkOpacities, i);
2531
- {
2532
- const pointPressures = el.inkPointPressures?.[i];
2533
- if (pointPressures && pointPressures.length > 1 && hasPressureVariation(pointPressures)) {
2534
- const pointWidths = pressuresToWidths(pointPressures, width);
2535
- return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(d, pointWidths, width, color, opacity, `${el.id}-ink-${i}`) }, `${el.id}-ink-${i}`);
2536
- }
2537
- if (el.inkWidths && el.inkWidths.length > 1 && hasPressureVariation(el.inkWidths)) {
2538
- return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(d, el.inkWidths, width, color, opacity, `${el.id}-ink-${i}`) }, `${el.id}-ink-${i}`);
2539
- }
2540
- }
2541
- const replayStyle = replayStyles?.[i];
2542
- return /* @__PURE__ */ jsx(
2543
- "path",
2544
- {
2545
- d,
2546
- fill: "none",
2547
- stroke: color,
2548
- strokeWidth: width,
2549
- strokeOpacity: opacity,
2550
- strokeLinecap: "round",
2551
- strokeLinejoin: "round",
2552
- vectorEffect: "non-scaling-stroke",
2553
- ...replayStyle ? {
2554
- strokeDasharray: replayStyle.strokeDasharray,
2555
- strokeDashoffset: replayStyle.strokeDashoffset,
2556
- style: {
2557
- animation: replayStyle.animation,
2558
- "--ink-path-length": replayStyle.pathLength
2559
- }
2560
- } : {}
2561
- },
2562
- `${el.id}-ink-${i}`
2563
- );
2564
- })
2688
+ strokes.map(
2689
+ (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-ink-${i}`)
2690
+ )
2565
2691
  ]
2566
2692
  }
2567
2693
  );
@@ -2657,6 +2783,7 @@ function renderContentPart(el, options) {
2657
2783
  if (el.inkStrokes && el.inkStrokes.length > 0) {
2658
2784
  const replay = options?.replay ?? false;
2659
2785
  const pressureSensitive = options?.pressureSensitive ?? true;
2786
+ const strokes = buildContentPartStrokes(el);
2660
2787
  const replayStyles = replay ? getContentPartReplayStyles(el.inkStrokes, options?.replayConfig) : null;
2661
2788
  return /* @__PURE__ */ jsxs(
2662
2789
  "svg",
@@ -2666,56 +2793,9 @@ function renderContentPart(el, options) {
2666
2793
  preserveAspectRatio: "none",
2667
2794
  children: [
2668
2795
  replay && /* @__PURE__ */ jsx("style", { children: INK_REPLAY_KEYFRAMES }),
2669
- el.inkStrokes.map((stroke, i) => {
2670
- if (stroke.tiltAngles && stroke.tiltAngles.length > 0) {
2671
- const magnitudes = stroke.tiltMagnitudes ?? stroke.tiltAngles.map(() => 0.5);
2672
- const widths = stroke.pressures && stroke.pressures.length > 1 && hasPressureVariation(stroke.pressures) ? pressuresToWidths(stroke.pressures, stroke.width) : [stroke.width];
2673
- return /* @__PURE__ */ jsx("g", { children: renderNibMarkStroke(
2674
- stroke.path,
2675
- widths,
2676
- stroke.tiltAngles,
2677
- magnitudes,
2678
- stroke.width,
2679
- stroke.color,
2680
- stroke.opacity,
2681
- `${el.id}-cp-ink-${i}`
2682
- ) }, `${el.id}-cp-ink-${i}`);
2683
- }
2684
- if (pressureSensitive && stroke.pressures && stroke.pressures.length > 1 && hasPressureVariation(stroke.pressures)) {
2685
- const pointWidths = pressuresToWidths(stroke.pressures, stroke.width);
2686
- return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(
2687
- stroke.path,
2688
- pointWidths,
2689
- stroke.width,
2690
- stroke.color,
2691
- stroke.opacity,
2692
- `${el.id}-cp-ink-${i}`
2693
- ) }, `${el.id}-cp-ink-${i}`);
2694
- }
2695
- const replayStyle = replayStyles?.[i];
2696
- return /* @__PURE__ */ jsx(
2697
- "path",
2698
- {
2699
- d: stroke.path,
2700
- fill: "none",
2701
- stroke: stroke.color,
2702
- strokeWidth: stroke.width,
2703
- strokeOpacity: stroke.opacity,
2704
- strokeLinecap: "round",
2705
- strokeLinejoin: "round",
2706
- vectorEffect: "non-scaling-stroke",
2707
- ...replayStyle ? {
2708
- strokeDasharray: replayStyle.strokeDasharray,
2709
- strokeDashoffset: replayStyle.strokeDashoffset,
2710
- style: {
2711
- animation: replayStyle.animation,
2712
- "--ink-path-length": replayStyle.pathLength
2713
- }
2714
- } : {}
2715
- },
2716
- `${el.id}-cp-ink-${i}`
2717
- );
2718
- })
2796
+ strokes.map(
2797
+ (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-cp-ink-${i}`)
2798
+ )
2719
2799
  ]
2720
2800
  }
2721
2801
  );
@@ -3082,10 +3162,10 @@ function InlineTextEditor({
3082
3162
  function FailedToLoad6() {
3083
3163
  return null;
3084
3164
  }
3085
- var LazyModel3DScene = React19.lazy(
3165
+ var LazyModel3DScene = React20.lazy(
3086
3166
  async () => {
3087
3167
  try {
3088
- return await import('./Model3DScene-O24KP723.mjs');
3168
+ return await import('./Model3DScene-REKMR2L6.mjs');
3089
3169
  } catch {
3090
3170
  return { default: FailedToLoad6 };
3091
3171
  }
@@ -3147,7 +3227,7 @@ function PosterFallback({
3147
3227
  }
3148
3228
  );
3149
3229
  }
3150
- var Model3DErrorBoundary = class extends React19.Component {
3230
+ var Model3DErrorBoundary = class extends React20.Component {
3151
3231
  constructor(props) {
3152
3232
  super(props);
3153
3233
  this.state = { hasError: false };
@@ -3356,10 +3436,10 @@ function SmartArtInlineNodeEditor({
3356
3436
  onCancel
3357
3437
  }) {
3358
3438
  const { t } = useTranslation();
3359
- const ref = React19.useRef(null);
3360
- const [value, setValue] = React19.useState(initialText);
3361
- const settled = React19.useRef(false);
3362
- React19.useEffect(() => {
3439
+ const ref = React20.useRef(null);
3440
+ const [value, setValue] = React20.useState(initialText);
3441
+ const settled = React20.useRef(false);
3442
+ React20.useEffect(() => {
3363
3443
  const el = ref.current;
3364
3444
  if (el) {
3365
3445
  el.focus();
@@ -3451,16 +3531,16 @@ function findNodeIdFromEvent(target) {
3451
3531
  return null;
3452
3532
  }
3453
3533
  function useSmartArtHoverState(containerRef) {
3454
- const [hoveredNodeId, setHoveredNodeId] = React19.useState(null);
3455
- const [hoveredNodeRect, setHoveredNodeRect] = React19.useState(null);
3456
- const hideTimeoutRef = React19.useRef(null);
3457
- const cancelPendingHide = React19.useCallback(() => {
3534
+ const [hoveredNodeId, setHoveredNodeId] = React20.useState(null);
3535
+ const [hoveredNodeRect, setHoveredNodeRect] = React20.useState(null);
3536
+ const hideTimeoutRef = React20.useRef(null);
3537
+ const cancelPendingHide = React20.useCallback(() => {
3458
3538
  if (hideTimeoutRef.current !== null) {
3459
3539
  window.clearTimeout(hideTimeoutRef.current);
3460
3540
  hideTimeoutRef.current = null;
3461
3541
  }
3462
3542
  }, []);
3463
- const handleMouseMove = React19.useCallback(
3543
+ const handleMouseMove = React20.useCallback(
3464
3544
  (e, ignoreRef) => {
3465
3545
  const nodeEl = findNodeIdFromEvent(e.target);
3466
3546
  const container = containerRef.current;
@@ -3488,12 +3568,12 @@ function useSmartArtHoverState(containerRef) {
3488
3568
  },
3489
3569
  [containerRef, cancelPendingHide]
3490
3570
  );
3491
- const clearHover = React19.useCallback(() => {
3571
+ const clearHover = React20.useCallback(() => {
3492
3572
  cancelPendingHide();
3493
3573
  setHoveredNodeId(null);
3494
3574
  setHoveredNodeRect(null);
3495
3575
  }, [cancelPendingHide]);
3496
- React19.useEffect(() => cancelPendingHide, [cancelPendingHide]);
3576
+ React20.useEffect(() => cancelPendingHide, [cancelPendingHide]);
3497
3577
  return { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover };
3498
3578
  }
3499
3579
  var EDITOR_PADDING = 4;
@@ -3508,11 +3588,11 @@ function SmartArtEditableLayer({
3508
3588
  onChangeNodeStyle,
3509
3589
  children
3510
3590
  }) {
3511
- const containerRef = React19.useRef(null);
3512
- const styleBarRef = React19.useRef(null);
3513
- const [edit, setEdit] = React19.useState(null);
3591
+ const containerRef = React20.useRef(null);
3592
+ const styleBarRef = React20.useRef(null);
3593
+ const [edit, setEdit] = React20.useState(null);
3514
3594
  const { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover } = useSmartArtHoverState(containerRef);
3515
- const openEditor = React19.useCallback(
3595
+ const openEditor = React20.useCallback(
3516
3596
  (target) => {
3517
3597
  const nodeEl = findNodeIdFromEvent(target);
3518
3598
  const container = containerRef.current;
@@ -4124,20 +4204,20 @@ function sameDiagramReveal(prev, next) {
4124
4204
  }
4125
4205
  return true;
4126
4206
  }
4127
- var SmartArtRenderer = React19.memo(SmartArtRendererImpl, arePropsEqual);
4207
+ var SmartArtRenderer = React20.memo(SmartArtRendererImpl, arePropsEqual);
4128
4208
  function FailedToLoad7() {
4129
4209
  return null;
4130
4210
  }
4131
- var LazySmartArt3DScene = React19.lazy(
4211
+ var LazySmartArt3DScene = React20.lazy(
4132
4212
  async () => {
4133
4213
  try {
4134
- return await import('./SmartArt3DScene-XCFVGCXE.mjs');
4214
+ return await import('./SmartArt3DScene-ODKCGJBO.mjs');
4135
4215
  } catch {
4136
4216
  return { default: FailedToLoad7 };
4137
4217
  }
4138
4218
  }
4139
4219
  );
4140
- var SceneErrorBoundary6 = class extends React19.Component {
4220
+ var SceneErrorBoundary6 = class extends React20.Component {
4141
4221
  constructor(props) {
4142
4222
  super(props);
4143
4223
  this.state = { hasError: false };
@@ -4154,7 +4234,8 @@ function SmartArt3DRenderer({
4154
4234
  className,
4155
4235
  interactive = false,
4156
4236
  canEdit,
4157
- onUpdateElement
4237
+ onUpdateElement,
4238
+ animationState
4158
4239
  }) {
4159
4240
  const [threeAvailable, setThreeAvailable] = useState(null);
4160
4241
  useEffect(() => {
@@ -4210,7 +4291,8 @@ function SmartArt3DRenderer({
4210
4291
  model,
4211
4292
  width: element.width,
4212
4293
  height: element.height,
4213
- interactive
4294
+ interactive,
4295
+ textStyle: animationState?.textStyle
4214
4296
  }
4215
4297
  ) }) });
4216
4298
  const editEnabled = canEdit && Boolean(onUpdateElement);
@@ -4254,7 +4336,8 @@ function SmartArtElement({
4254
4336
  element,
4255
4337
  className,
4256
4338
  canEdit,
4257
- onUpdateElement
4339
+ onUpdateElement,
4340
+ animationState
4258
4341
  }
4259
4342
  );
4260
4343
  }
@@ -4314,6 +4397,67 @@ function getSegmentTspanProps(segment, element, fallbackColor) {
4314
4397
  textDecoration: decos.length > 0 ? decos.join(" ") : void 0
4315
4398
  };
4316
4399
  }
4400
+ function resolveSegmentFont(segment, element) {
4401
+ const s = segment.style || {};
4402
+ const family = s.fontFamily || element.textStyle?.fontFamily;
4403
+ return {
4404
+ fontFamily: family ? getSubstituteFontFamily(family) : DEFAULT_FONT_FAMILY,
4405
+ fontSizePx: s.fontSize ?? element.textStyle?.fontSize ?? DEFAULT_TEXT_FONT_SIZE,
4406
+ bold: s.bold ?? element.textStyle?.bold,
4407
+ italic: s.italic ?? element.textStyle?.italic
4408
+ };
4409
+ }
4410
+ function EnvelopeGlyph({
4411
+ glyphKey,
4412
+ glyph,
4413
+ tspanProps
4414
+ }) {
4415
+ if (!glyph.slices || glyph.slices.length <= 1) {
4416
+ return /* @__PURE__ */ jsx("text", { x: glyph.x, y: glyph.y, transform: glyph.transform, ...tspanProps, children: glyph.char });
4417
+ }
4418
+ return /* @__PURE__ */ jsx("g", { "data-glyph-slices": glyph.slices.length, children: glyph.slices.map((slice, si) => {
4419
+ const clipId = `${glyphKey}-s${si}`;
4420
+ return /* @__PURE__ */ jsxs(React20.Fragment, { children: [
4421
+ /* @__PURE__ */ jsx("clipPath", { id: clipId, clipPathUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx(
4422
+ "rect",
4423
+ {
4424
+ x: slice.clipX0,
4425
+ y: -1e5,
4426
+ width: Math.max(0, slice.clipX1 - slice.clipX0),
4427
+ height: 2e5
4428
+ }
4429
+ ) }),
4430
+ /* @__PURE__ */ jsx(
4431
+ "text",
4432
+ {
4433
+ x: glyph.x,
4434
+ y: glyph.y,
4435
+ transform: slice.transform,
4436
+ clipPath: `url(#${clipId})`,
4437
+ ...tspanProps,
4438
+ children: glyph.char
4439
+ }
4440
+ )
4441
+ ] }, clipId);
4442
+ }) });
4443
+ }
4444
+ function EnvelopeLine({
4445
+ paraSegments,
4446
+ glyphs,
4447
+ element,
4448
+ fallbackColor,
4449
+ lineIdPrefix
4450
+ }) {
4451
+ return /* @__PURE__ */ jsx(Fragment, { children: glyphs.map((g, i) => /* @__PURE__ */ jsx(
4452
+ EnvelopeGlyph,
4453
+ {
4454
+ glyphKey: `${lineIdPrefix}-g${i}`,
4455
+ glyph: g,
4456
+ tspanProps: getSegmentTspanProps(paraSegments[g.segmentIndex], element, fallbackColor)
4457
+ },
4458
+ i
4459
+ )) });
4460
+ }
4317
4461
  function WarpedText({
4318
4462
  element,
4319
4463
  width,
@@ -4342,6 +4486,48 @@ function WarpedText({
4342
4486
  const baseFontSize = textEl.textStyle?.fontSize ?? DEFAULT_TEXT_FONT_SIZE;
4343
4487
  const baseFontFamily = textEl.textStyle?.fontFamily ? getSubstituteFontFamily(textEl.textStyle.fontFamily) : DEFAULT_FONT_FAMILY;
4344
4488
  const baseFill = normalizeHexColor(textEl.textStyle?.color, fallbackColor);
4489
+ if (hasGlyphEnvelope(preset)) {
4490
+ return /* @__PURE__ */ jsx(
4491
+ "svg",
4492
+ {
4493
+ width,
4494
+ height,
4495
+ viewBox: `0 0 ${width} ${height}`,
4496
+ xmlns: "http://www.w3.org/2000/svg",
4497
+ style: { overflow: "visible", position: "absolute", inset: 0, pointerEvents: "none" },
4498
+ "aria-hidden": "true",
4499
+ children: paragraphs.map((para, paraIdx) => {
4500
+ const segsInput = para.segments.map((seg, i) => ({
4501
+ text: seg.text,
4502
+ font: resolveSegmentFont(seg, textEl),
4503
+ segmentIndex: i
4504
+ }));
4505
+ const glyphs = buildGlyphEnvelope(
4506
+ preset,
4507
+ segsInput,
4508
+ width,
4509
+ height,
4510
+ align,
4511
+ warpAdj,
4512
+ warpAdj2,
4513
+ paraIdx,
4514
+ lineCount
4515
+ );
4516
+ return /* @__PURE__ */ jsx(
4517
+ EnvelopeLine,
4518
+ {
4519
+ paraSegments: para.segments,
4520
+ glyphs,
4521
+ element: textEl,
4522
+ fallbackColor,
4523
+ lineIdPrefix: `warp-${element.id}-l${paraIdx}`
4524
+ },
4525
+ `envelope-line-${paraIdx}`
4526
+ );
4527
+ })
4528
+ }
4529
+ );
4530
+ }
4345
4531
  return /* @__PURE__ */ jsxs(
4346
4532
  "svg",
4347
4533
  {
@@ -4470,13 +4656,26 @@ function renderTextElementBody(options) {
4470
4656
  const useSvgWarp = shouldUseSvgWarp(
4471
4657
  hasTextProperties(el) ? el.textStyle?.textWarpPreset : void 0
4472
4658
  );
4473
- const scene3dStyle = hasTextProperties(el) ? buildTextBody3DSceneStyle(el.textStyle) : void 0;
4659
+ const scene3dStyle = hasTextProperties(el) ? buildTextBody3DSceneStyle(el.textStyle, { width: el.width, height: el.height }) : void 0;
4474
4660
  const rotationTransform = getTextBodyRotationTransform(el);
4475
4661
  const composedTransform = [rotationTransform, getTextCompensationTransform(el), scene3dStyle?.transform].filter(Boolean).join(" ") || void 0;
4476
4662
  const transformStyle = {
4477
4663
  transform: composedTransform,
4478
- transformOrigin: "center",
4664
+ // A COM-measured homography (`scene3dStyle.transformOrigin === '0 0'`)
4665
+ // MUST win over the default centred origin, or the matrix3d's baked-in
4666
+ // translation (relative to the element's own top-left) is applied from
4667
+ // the wrong pivot and the projection is wrong (see
4668
+ // `visual-3d-camera-homography`'s module doc comment). This used to be
4669
+ // hardcoded to `'center'` unconditionally, silently clobbering
4670
+ // `scene3dStyle.transformOrigin` the same way Svelte's `ElementRenderer`
4671
+ // once re-clobbered `pointerEvents` from its own interactive flag.
4672
+ transformOrigin: scene3dStyle?.transformOrigin ?? "center",
4479
4673
  ...scene3dStyle?.perspective ? { perspective: scene3dStyle.perspective } : {},
4674
+ // COM-calibrated off-axis correction for a handful of camera presets
4675
+ // (see `visual-3d-camera`'s module doc comment); only reachable when an
4676
+ // explicit `a:camera/a:rot`/`@fov`/`@zoom` override sits alongside one of
4677
+ // those presets, since the homography path above never sets it.
4678
+ ...scene3dStyle?.perspectiveOrigin ? { perspectiveOrigin: scene3dStyle.perspectiveOrigin } : {},
4480
4679
  ...scene3dStyle?.transformStyle ? { transformStyle: scene3dStyle.transformStyle } : {},
4481
4680
  ...isLinkedTextBox2 ? { overflow: "hidden" } : {}
4482
4681
  };
@@ -4903,7 +5102,9 @@ function renderBody(options) {
4903
5102
  }
4904
5103
  if (doInk && isInkElement(el)) {
4905
5104
  return renderInk(el, {
4906
- replay: isPresentationPassive});
5105
+ replay: isPresentationPassive,
5106
+ pressureSensitive: true
5107
+ });
4907
5108
  }
4908
5109
  if (el.type === "contentPart") {
4909
5110
  return renderContentPart(el, {
@@ -4924,9 +5125,8 @@ function renderBody(options) {
4924
5125
  }
4925
5126
  return renderTextElementBody(options);
4926
5127
  }
4927
- var noop = () => {
4928
- };
4929
- var EMPTY_MEDIA_DATA_URLS = /* @__PURE__ */ new Map();
5128
+
5129
+ // src/viewer/components/static-element-renderer-utils.ts
4930
5130
  function defaultTextColorForFill(fillColor) {
4931
5131
  const hex = String(fillColor ?? "").replace(/^#/u, "");
4932
5132
  if (!/^[0-9a-f]{6}$/iu.test(hex)) {
@@ -4936,26 +5136,7 @@ function defaultTextColorForFill(fillColor) {
4936
5136
  const luminance = channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
4937
5137
  return luminance > 0.179 ? DEFAULT_TEXT_COLOR : "#ffffff";
4938
5138
  }
4939
- function StaticElementRendererImpl({
4940
- element,
4941
- activeSlide,
4942
- allSlides,
4943
- mediaDataUrls = EMPTY_MEDIA_DATA_URLS,
4944
- sourceSlideIndex,
4945
- zIndex,
4946
- positioned = true,
4947
- fieldContext,
4948
- tableStyleContext,
4949
- parentGroupFill,
4950
- onActionClick,
4951
- actionRequiresModifier = false,
4952
- animation,
4953
- imageAnimation,
4954
- exposeElementId = false
4955
- }) {
4956
- if (!isElementRendered(element)) {
4957
- return null;
4958
- }
5139
+ function getStaticElementVisualState(element, parentGroupFill) {
4959
5140
  const style = hasShapeProperties(element) ? element.shapeStyle : void 0;
4960
5141
  const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
4961
5142
  const fill = normalizeHexColor(style?.fillColor, DEFAULT_FILL_COLOR);
@@ -4979,9 +5160,69 @@ function StaticElementRendererImpl({
4979
5160
  const letsTextOverflow = hasTextProperties(element) && element.textStyle?.autoFitMode === "shrink" && (element.type === "text" || element.locks?.txBox === true);
4980
5161
  const shapeType = hasShapeProperties(element) ? element.shapeType : void 0;
4981
5162
  const isCallout = isWedgeCalloutPresetShape(shapeType) || String(shapeType ?? "").toLowerCase().includes("callout");
5163
+ return {
5164
+ hasFill,
5165
+ fill,
5166
+ strokeWidth,
5167
+ stroke,
5168
+ visualStyle,
5169
+ textStyle,
5170
+ isImage,
5171
+ letsTextOverflow,
5172
+ isCallout
5173
+ };
5174
+ }
5175
+ function getStaticElementInteractionState(element, hasActionHandler, exposeElementId) {
4982
5176
  const action = element.actionClick;
4983
- const isActionable = Boolean(action && onActionClick);
5177
+ const isActionable = Boolean(action && hasActionHandler);
4984
5178
  const contractRole = exposeElementId ? getAriaRole(element, { actionable: isElementActionable(element) }) : isActionable ? "button" : void 0;
5179
+ return { action, isActionable, contractRole };
5180
+ }
5181
+ function getStaticElementWrapperClassName(element, visual, positioned, isActionable) {
5182
+ const overflowClass = visual.isImage || element.type === "group" || isConnectorOrLineElement(element) || visual.isCallout || visual.letsTextOverflow ? "" : "overflow-hidden";
5183
+ const pointerClass = isActionable ? "pointer-events-auto cursor-pointer" : "pointer-events-none";
5184
+ return `${positioned ? "absolute" : "relative"} ${overflowClass} ${pointerClass}`;
5185
+ }
5186
+ var noop = () => {
5187
+ };
5188
+ var EMPTY_MEDIA_DATA_URLS = /* @__PURE__ */ new Map();
5189
+ function StaticElementRendererImpl({
5190
+ element,
5191
+ activeSlide,
5192
+ allSlides,
5193
+ mediaDataUrls = EMPTY_MEDIA_DATA_URLS,
5194
+ sourceSlideIndex,
5195
+ zIndex,
5196
+ positioned = true,
5197
+ fieldContext,
5198
+ tableStyleContext,
5199
+ parentGroupFill,
5200
+ onActionClick,
5201
+ actionRequiresModifier = false,
5202
+ animation,
5203
+ imageAnimation,
5204
+ exposeElementId = false,
5205
+ suppressReflection = false
5206
+ }) {
5207
+ if (!isElementRendered(element)) {
5208
+ return null;
5209
+ }
5210
+ const {
5211
+ hasFill,
5212
+ fill,
5213
+ strokeWidth,
5214
+ stroke,
5215
+ visualStyle,
5216
+ textStyle,
5217
+ isImage,
5218
+ letsTextOverflow,
5219
+ isCallout
5220
+ } = getStaticElementVisualState(element, parentGroupFill);
5221
+ const { action, isActionable, contractRole } = getStaticElementInteractionState(
5222
+ element,
5223
+ Boolean(onActionClick),
5224
+ exposeElementId
5225
+ );
4985
5226
  return /* @__PURE__ */ jsxs(
4986
5227
  "div",
4987
5228
  {
@@ -4989,7 +5230,12 @@ function StaticElementRendererImpl({
4989
5230
  "data-element-id": exposeElementId ? element.id : void 0,
4990
5231
  "data-pptx-element": exposeElementId ? "true" : void 0,
4991
5232
  "data-pptx-action": isActionable ? "click" : void 0,
4992
- className: `${positioned ? "absolute" : "relative"} ${isImage || element.type === "group" || isConnectorOrLineElement(element) || isCallout || letsTextOverflow ? "" : "overflow-hidden"} ${isActionable ? "pointer-events-auto cursor-pointer" : "pointer-events-none"}`,
5233
+ className: getStaticElementWrapperClassName(
5234
+ element,
5235
+ { isImage, letsTextOverflow, isCallout },
5236
+ positioned,
5237
+ isActionable
5238
+ ),
4993
5239
  role: contractRole,
4994
5240
  "aria-label": exposeElementId ? getAriaLabel(element) : void 0,
4995
5241
  "aria-roledescription": exposeElementId ? getAriaRoleDescription(element) : void 0,
@@ -5033,7 +5279,7 @@ function StaticElementRendererImpl({
5033
5279
  animation
5034
5280
  },
5035
5281
  children: [
5036
- /* @__PURE__ */ jsx(ShapeEffectOverlay, { element }),
5282
+ /* @__PURE__ */ jsx(ShapeEffectOverlay, { element, suppressReflection }),
5037
5283
  element.type === "group" ? /* @__PURE__ */ jsx("div", { className: "relative w-full h-full", children: (element.children ?? []).map((child, index) => /* @__PURE__ */ jsx(
5038
5284
  StaticElementRenderer,
5039
5285
  {
@@ -5098,7 +5344,7 @@ function StaticElementRendererImpl({
5098
5344
  }
5099
5345
  );
5100
5346
  }
5101
- var StaticElementRenderer = React19.memo(StaticElementRendererImpl);
5347
+ var StaticElementRenderer = React20.memo(StaticElementRendererImpl);
5102
5348
  StaticElementRenderer.displayName = "StaticElementRenderer";
5103
5349
  var PREVIEW_CANVAS_WIDTH = 1280;
5104
5350
  var PREVIEW_CANVAS_HEIGHT = 720;
@@ -5734,6 +5980,11 @@ var OV = [
5734
5980
  labelKey: "pptx.file.saveAsPptmTooltip",
5735
5981
  i: /* @__PURE__ */ jsx(LuDatabase, { className: `${ics} text-muted-foreground` })
5736
5982
  },
5983
+ {
5984
+ k: "ppt",
5985
+ labelKey: "pptx.file.saveAsPptTooltip",
5986
+ i: /* @__PURE__ */ jsx(LuFileText, { className: `${ics} text-muted-foreground` })
5987
+ },
5737
5988
  { k: "---0", labelKey: "", i: null },
5738
5989
  {
5739
5990
  k: "print",
@@ -6012,41 +6263,85 @@ function ArrangeSection(p) {
6012
6263
  /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: t("pptx.arrange.groupLabel") })
6013
6264
  ] });
6014
6265
  }
6015
- function TransitionsSection(p) {
6016
- const { t } = useTranslation();
6017
- const canEdit = p.canEdit !== false;
6018
- const draft = React19.useMemo(() => readRibbonTransitionDraft(p.activeSlide), [p.activeSlide]);
6019
- const [durationBuffer, setDurationBuffer] = React19.useState(null);
6020
- const [advanceBuffer, setAdvanceBuffer] = React19.useState(null);
6021
- const commit = React19.useCallback(
6022
- (changes) => {
6023
- p.onTransitionChange(ribbonTransitionUpdates({ ...draft, ...changes }));
6024
- },
6025
- [draft, p]
6026
- );
6027
- const soundFileInputRef = React19.useRef(null);
6028
- const handleSoundFilePicked = React19.useCallback(
6266
+ function useTransitionSoundPicker(activeSlide, onTransitionChange) {
6267
+ const soundFileInputRef = React20.useRef(null);
6268
+ const handleSoundFilePicked = React20.useCallback(
6029
6269
  (file) => {
6030
6270
  void readSoundFileAsDataUrl(file).then((dataUrl) => {
6031
6271
  if (dataUrl) {
6032
- p.onTransitionChange(applyTransitionSoundFile({ name: file.name, dataUrl }));
6272
+ onTransitionChange(applyTransitionSoundFile({ name: file.name, dataUrl }));
6033
6273
  }
6034
6274
  return void 0;
6035
6275
  });
6036
6276
  },
6037
- [p]
6277
+ [onTransitionChange]
6038
6278
  );
6039
- const handleSoundSelectChange = (event) => {
6040
- const value = event.target.value;
6041
- if (value === TRANSITION_SOUND_OTHER_VALUE) {
6042
- soundFileInputRef.current?.click();
6043
- event.target.value = transitionSoundSelectedValue(p.activeSlide?.transition);
6279
+ const handleSoundSelectChange = React20.useCallback(
6280
+ (event) => {
6281
+ const value = event.target.value;
6282
+ if (value === TRANSITION_SOUND_OTHER_VALUE) {
6283
+ soundFileInputRef.current?.click();
6284
+ event.target.value = transitionSoundSelectedValue(activeSlide?.transition);
6285
+ return;
6286
+ }
6287
+ if (value === TRANSITION_SOUND_NONE_VALUE) {
6288
+ onTransitionChange(clearTransitionSound());
6289
+ return;
6290
+ }
6291
+ const patch = applyTransitionStockSound(value);
6292
+ if (patch) {
6293
+ onTransitionChange(patch);
6294
+ }
6295
+ },
6296
+ [activeSlide, onTransitionChange]
6297
+ );
6298
+ const handleSoundFileChange = React20.useCallback(
6299
+ (event) => {
6300
+ const file = event.target.files?.[0];
6301
+ if (file) {
6302
+ handleSoundFilePicked(file);
6303
+ }
6304
+ event.target.value = "";
6305
+ },
6306
+ [handleSoundFilePicked]
6307
+ );
6308
+ const stockSoundId = transitionStockSoundId(activeSlide?.transition);
6309
+ const handleSoundPreview = React20.useCallback(() => {
6310
+ if (!stockSoundId) {
6044
6311
  return;
6045
6312
  }
6046
- if (value === TRANSITION_SOUND_NONE_VALUE) {
6047
- p.onTransitionChange(clearTransitionSound());
6313
+ const asset = getEffectSoundAsset(stockSoundId);
6314
+ if (asset) {
6315
+ playAnimationSound(asset.dataUrl);
6048
6316
  }
6317
+ }, [stockSoundId]);
6318
+ return {
6319
+ soundFileInputRef,
6320
+ stockSoundId,
6321
+ handleSoundSelectChange,
6322
+ handleSoundFileChange,
6323
+ handleSoundPreview
6049
6324
  };
6325
+ }
6326
+ function TransitionsSection(p) {
6327
+ const { t } = useTranslation();
6328
+ const canEdit = p.canEdit !== false;
6329
+ const draft = React20.useMemo(() => readRibbonTransitionDraft(p.activeSlide), [p.activeSlide]);
6330
+ const [durationBuffer, setDurationBuffer] = React20.useState(null);
6331
+ const [advanceBuffer, setAdvanceBuffer] = React20.useState(null);
6332
+ const commit = React20.useCallback(
6333
+ (changes) => {
6334
+ p.onTransitionChange(ribbonTransitionUpdates({ ...draft, ...changes }));
6335
+ },
6336
+ [draft, p]
6337
+ );
6338
+ const {
6339
+ soundFileInputRef,
6340
+ stockSoundId,
6341
+ handleSoundSelectChange,
6342
+ handleSoundFileChange,
6343
+ handleSoundPreview
6344
+ } = useTransitionSoundPicker(p.activeSlide, p.onTransitionChange);
6050
6345
  return /* @__PURE__ */ jsxs(Fragment, { children: [
6051
6346
  /* @__PURE__ */ jsxs(
6052
6347
  "button",
@@ -6116,6 +6411,17 @@ function TransitionsSection(p) {
6116
6411
  children: transitionSoundOptions(p.activeSlide?.transition).map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.i18nKey ? t(option.i18nKey) : option.label }, option.value))
6117
6412
  }
6118
6413
  ),
6414
+ /* @__PURE__ */ jsx(
6415
+ "button",
6416
+ {
6417
+ type: "button",
6418
+ "aria-label": t("pptx.animation.sound.preview"),
6419
+ onClick: handleSoundPreview,
6420
+ disabled: !stockSoundId,
6421
+ className: "shrink-0 rounded border border-border bg-muted p-1 disabled:opacity-40",
6422
+ children: /* @__PURE__ */ jsx(LuPlay, { className: "h-3 w-3" })
6423
+ }
6424
+ ),
6119
6425
  /* @__PURE__ */ jsx(
6120
6426
  "input",
6121
6427
  {
@@ -6123,13 +6429,7 @@ function TransitionsSection(p) {
6123
6429
  type: "file",
6124
6430
  accept: "audio/*",
6125
6431
  className: "hidden",
6126
- onChange: (e) => {
6127
- const file = e.target.files?.[0];
6128
- if (file) {
6129
- handleSoundFilePicked(file);
6130
- }
6131
- e.target.value = "";
6132
- }
6432
+ onChange: handleSoundFileChange
6133
6433
  }
6134
6434
  )
6135
6435
  ] }),
@@ -6390,7 +6690,7 @@ function AccountPage() {
6390
6690
  return void 0;
6391
6691
  });
6392
6692
  };
6393
- const version = "3.7.0" ;
6693
+ const version = "3.9.0" ;
6394
6694
  return /* @__PURE__ */ jsxs("div", { className: "mt-8 max-w-[700px] space-y-6", children: [
6395
6695
  /* @__PURE__ */ jsxs("section", { className: cardClass, children: [
6396
6696
  /* @__PURE__ */ jsxs("h2", { className: "flex items-center gap-2 text-sm font-semibold", children: [
@@ -6569,6 +6869,7 @@ var ICONS = {
6569
6869
  saveAsPptx: LuDownload,
6570
6870
  saveAsPpsx: LuPlay,
6571
6871
  saveAsPptm: LuFileText,
6872
+ saveAsPpt: LuDatabase,
6572
6873
  pdf: LuFileText,
6573
6874
  png: LuFileImage,
6574
6875
  video: LuVideo,
@@ -6593,6 +6894,7 @@ function BackstageCards({
6593
6894
  saveAsPptx: props.onSaveAsPptx,
6594
6895
  saveAsPpsx: props.onSaveAsPpsx,
6595
6896
  saveAsPptm: props.onSaveAsPptm,
6897
+ saveAsPpt: props.onSaveAsPpt,
6596
6898
  pdf: props.onExportPdf,
6597
6899
  png: props.onExportPng,
6598
6900
  video: props.onExportVideo,
@@ -6826,7 +7128,7 @@ function FontFamilyMenu(p) {
6826
7128
  embeddedFonts: p.embeddedFonts,
6827
7129
  customFonts: p.customFonts
6828
7130
  });
6829
- return /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: p.anchorRef, className: "flex flex-col w-64 pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 max-h-80 overflow-y-auto", children: groups.map((group, groupIndex) => /* @__PURE__ */ jsxs(React19.Fragment, { children: [
7131
+ return /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: p.anchorRef, className: "flex flex-col w-64 pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 max-h-80 overflow-y-auto", children: groups.map((group, groupIndex) => /* @__PURE__ */ jsxs(React20.Fragment, { children: [
6830
7132
  /* @__PURE__ */ jsx(
6831
7133
  "div",
6832
7134
  {
@@ -9636,6 +9938,7 @@ function MobileSectionBody({
9636
9938
  onSaveAsPptx: p.onSaveAsPptx,
9637
9939
  onSaveAsPpsx: p.onSaveAsPpsx,
9638
9940
  onSaveAsPptm: p.onSaveAsPptm,
9941
+ onSaveAsPpt: p.onSaveAsPpt,
9639
9942
  hasMacros: p.hasMacros,
9640
9943
  onCopySlideAsImage: p.onCopySlideAsImage,
9641
9944
  onPrint: p.onPrint,
@@ -10446,6 +10749,7 @@ function OverflowMenu(p) {
10446
10749
  pptx: p.onSaveAsPptx,
10447
10750
  ppsx: p.onSaveAsPpsx,
10448
10751
  pptm: p.onSaveAsPptm,
10752
+ ppt: p.onSaveAsPpt,
10449
10753
  print: p.onPrint,
10450
10754
  copyImg: p.onCopySlideAsImage,
10451
10755
  a11y: p.onRunAccessibilityCheck,
@@ -10761,6 +11065,7 @@ function Toolbar(p) {
10761
11065
  onSaveAsPptx: p.onSaveAsPptx,
10762
11066
  onSaveAsPpsx: p.onSaveAsPpsx,
10763
11067
  onSaveAsPptm: p.onSaveAsPptm,
11068
+ onSaveAsPpt: p.onSaveAsPpt,
10764
11069
  hasMacros: p.hasMacros,
10765
11070
  onCopySlideAsImage: p.onCopySlideAsImage,
10766
11071
  onPrint: p.onPrint,
@@ -11020,8 +11325,8 @@ function Toolbar(p) {
11020
11325
  }
11021
11326
 
11022
11327
  // src/viewer/utils/slide-background-style.ts
11023
- function getReactSlideBackgroundStyle(slide) {
11024
- const style = getSlideBackgroundStyle(slide);
11328
+ function getReactSlideBackgroundStyle(slide, slideSize) {
11329
+ const style = getSlideBackgroundStyle(slide, slideSize);
11025
11330
  return {
11026
11331
  backgroundColor: style["background-color"],
11027
11332
  backgroundImage: slide?.backgroundImage ? void 0 : style["background-image"],
@@ -11363,6 +11668,7 @@ function DrawingOverlaySvg({
11363
11668
  drawingWidth,
11364
11669
  isStrokeActive,
11365
11670
  liveStrokeD,
11671
+ liveStrokeView,
11366
11672
  onPointerDown,
11367
11673
  onPointerMove,
11368
11674
  onPointerUp
@@ -11381,7 +11687,7 @@ function DrawingOverlaySvg({
11381
11687
  onPointerDown,
11382
11688
  onPointerMove,
11383
11689
  onPointerUp,
11384
- children: isStrokeActive && liveStrokeD && /* @__PURE__ */ jsx(
11690
+ children: isStrokeActive && liveStrokeView ? renderStrokeView(liveStrokeView, true, void 0, "ink-live-preview") : isStrokeActive && liveStrokeD && /* @__PURE__ */ jsx(
11385
11691
  "path",
11386
11692
  {
11387
11693
  d: liveStrokeD,
@@ -11600,7 +11906,7 @@ function HorizontalRulerView({ ticks, widthPx, highlight }) {
11600
11906
  }
11601
11907
  );
11602
11908
  }
11603
- var HorizontalRuler = React19.memo(HorizontalRulerView);
11909
+ var HorizontalRuler = React20.memo(HorizontalRulerView);
11604
11910
  HorizontalRuler.displayName = "HorizontalRuler";
11605
11911
  function VerticalRulerView({ ticks, heightPx, highlight }) {
11606
11912
  return /* @__PURE__ */ jsxs(
@@ -11672,7 +11978,7 @@ function VerticalRulerView({ ticks, heightPx, highlight }) {
11672
11978
  }
11673
11979
  );
11674
11980
  }
11675
- var VerticalRuler = React19.memo(VerticalRulerView);
11981
+ var VerticalRuler = React20.memo(VerticalRulerView);
11676
11982
  VerticalRuler.displayName = "VerticalRuler";
11677
11983
  function Ruler({
11678
11984
  canvasSize,
@@ -12145,6 +12451,140 @@ function useConnectorCreation({
12145
12451
  handleConnectorDragEnd
12146
12452
  };
12147
12453
  }
12454
+
12455
+ // src/viewer/components/canvas/canvas-path.ts
12456
+ function buildCanvasPathD(points) {
12457
+ if (points.length === 0) {
12458
+ return "";
12459
+ }
12460
+ const parts = [`M ${points[0].x} ${points[0].y}`];
12461
+ for (let i = 1; i < points.length; i++) {
12462
+ parts.push(`L ${points[i].x} ${points[i].y}`);
12463
+ }
12464
+ return parts.join(" ");
12465
+ }
12466
+
12467
+ // src/viewer/components/canvas/finishDrawStroke.ts
12468
+ function finishDrawStroke(input) {
12469
+ const { tool, points, pressures, tiltX, tiltY, color, width } = input;
12470
+ if (points.length < 2) {
12471
+ return null;
12472
+ }
12473
+ let minX = Infinity;
12474
+ let minY = Infinity;
12475
+ let maxX = -Infinity;
12476
+ let maxY = -Infinity;
12477
+ for (const pt of points) {
12478
+ if (pt.x < minX) {
12479
+ minX = pt.x;
12480
+ }
12481
+ if (pt.y < minY) {
12482
+ minY = pt.y;
12483
+ }
12484
+ if (pt.x > maxX) {
12485
+ maxX = pt.x;
12486
+ }
12487
+ if (pt.y > maxY) {
12488
+ maxY = pt.y;
12489
+ }
12490
+ }
12491
+ const pad = width;
12492
+ minX -= pad;
12493
+ minY -= pad;
12494
+ maxX += pad;
12495
+ maxY += pad;
12496
+ const w = Math.max(maxX - minX, 1);
12497
+ const h = Math.max(maxY - minY, 1);
12498
+ const relPoints = points.map((pt) => ({ x: pt.x - minX, y: pt.y - minY }));
12499
+ if (tool === "freeform") {
12500
+ return {
12501
+ kind: "freeform",
12502
+ element: buildFreeformShape(relPoints, { x: minX, y: minY, w, h }, color, width)
12503
+ };
12504
+ }
12505
+ return {
12506
+ kind: "ink",
12507
+ element: buildInkElement(
12508
+ relPoints,
12509
+ { x: minX, y: minY, w, h },
12510
+ tool,
12511
+ { pressures, tiltX, tiltY },
12512
+ color,
12513
+ width
12514
+ )
12515
+ };
12516
+ }
12517
+ function buildFreeformShape(relPoints, box, color, width) {
12518
+ const COORD_SCALE = 100;
12519
+ const segments = [];
12520
+ for (let i = 0; i < relPoints.length; i++) {
12521
+ const scaledPt = {
12522
+ x: Math.round(relPoints[i].x * COORD_SCALE),
12523
+ y: Math.round(relPoints[i].y * COORD_SCALE)
12524
+ };
12525
+ segments.push(i === 0 ? { type: "moveTo", pt: scaledPt } : { type: "lineTo", pt: scaledPt });
12526
+ }
12527
+ if (segments.length > 2) {
12528
+ segments.push({ type: "close" });
12529
+ }
12530
+ return {
12531
+ id: `shape-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12532
+ type: "shape",
12533
+ x: box.x,
12534
+ y: box.y,
12535
+ width: box.w,
12536
+ height: box.h,
12537
+ shapeType: "custom",
12538
+ shapeStyle: { fillColor: "transparent", strokeColor: color, strokeWidth: width },
12539
+ customGeometryPaths: [
12540
+ { width: Math.round(box.w * COORD_SCALE), height: Math.round(box.h * COORD_SCALE), segments }
12541
+ ]
12542
+ };
12543
+ }
12544
+ function buildInkElement(relPoints, box, tool, channels, color, width) {
12545
+ const pathD = buildCanvasPathD(relPoints);
12546
+ const isHighlighter = tool === "highlighter";
12547
+ const { pressures, tiltX, tiltY } = channels;
12548
+ const hasPressure = pressures.length >= 2 && pressures.some((p) => Math.abs(p - pressures[0]) > 0.01);
12549
+ const hasTilt = hasTiltData(tiltX, tiltY);
12550
+ return {
12551
+ id: `ink-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12552
+ type: "ink",
12553
+ x: box.x,
12554
+ y: box.y,
12555
+ width: box.w,
12556
+ height: box.h,
12557
+ inkPaths: [pathD],
12558
+ inkColors: [color],
12559
+ inkWidths: [width],
12560
+ inkOpacities: [isHighlighter ? 0.4 : 1],
12561
+ inkTool: isHighlighter ? "highlighter" : "pen",
12562
+ ...hasPressure ? { inkPointPressures: [pressures] } : {},
12563
+ ...hasTilt ? { inkPointTiltX: [tiltX], inkPointTiltY: [tiltY] } : {}
12564
+ };
12565
+ }
12566
+ function useLiveInkPreview(isStrokeActive, activeTool, points, pressures, tiltX, tiltY, color, width) {
12567
+ const liveStrokeD = useMemo(
12568
+ () => isStrokeActive ? buildCanvasPathD(points) : "",
12569
+ [isStrokeActive, points]
12570
+ );
12571
+ const liveStrokeView = useMemo(() => {
12572
+ if (!isStrokeActive || activeTool === "select" || activeTool === "eraser") {
12573
+ return null;
12574
+ }
12575
+ const inkPoints = points.map((pt, i) => ({
12576
+ x: pt.x,
12577
+ y: pt.y,
12578
+ pressure: pressures[i],
12579
+ tiltX: tiltX[i],
12580
+ tiltY: tiltY[i]
12581
+ }));
12582
+ return buildLiveInkStrokeView({ points: inkPoints, color, width, tool: activeTool });
12583
+ }, [isStrokeActive, activeTool, points, pressures, tiltX, tiltY, color, width]);
12584
+ return { liveStrokeD, liveStrokeView };
12585
+ }
12586
+
12587
+ // src/viewer/components/canvas/useDrawingOverlay.ts
12148
12588
  function useDrawingOverlay({
12149
12589
  activeTool,
12150
12590
  activeSlide,
@@ -12161,6 +12601,8 @@ function useDrawingOverlay({
12161
12601
  []
12162
12602
  );
12163
12603
  const [currentStrokePressures, setCurrentStrokePressures] = useState([]);
12604
+ const [currentStrokeTiltX, setCurrentStrokeTiltX] = useState([]);
12605
+ const [currentStrokeTiltY, setCurrentStrokeTiltY] = useState([]);
12164
12606
  const [isStrokeActive, setIsStrokeActive] = useState(false);
12165
12607
  const pointerToCanvasCoords = useCallback(
12166
12608
  (e) => {
@@ -12177,16 +12619,6 @@ function useDrawingOverlay({
12177
12619
  },
12178
12620
  [zoom.canvasStageRef, zoom.editorScale]
12179
12621
  );
12180
- const buildPathD = useCallback((pts) => {
12181
- if (pts.length === 0) {
12182
- return "";
12183
- }
12184
- const parts = [`M ${pts[0].x} ${pts[0].y}`];
12185
- for (let i = 1; i < pts.length; i++) {
12186
- parts.push(`L ${pts[i].x} ${pts[i].y}`);
12187
- }
12188
- return parts.join(" ");
12189
- }, []);
12190
12622
  const handleDrawPointerDown = useCallback(
12191
12623
  (e) => {
12192
12624
  if (activeTool === "select") {
@@ -12211,6 +12643,8 @@ function useDrawingOverlay({
12211
12643
  e.target.setPointerCapture(e.pointerId);
12212
12644
  setCurrentStrokePoints([pt]);
12213
12645
  setCurrentStrokePressures([e.pressure]);
12646
+ setCurrentStrokeTiltX([e.tiltX ?? 0]);
12647
+ setCurrentStrokeTiltY([e.tiltY ?? 0]);
12214
12648
  setIsStrokeActive(true);
12215
12649
  if (isDrawingRef) {
12216
12650
  isDrawingRef.current = true;
@@ -12229,6 +12663,8 @@ function useDrawingOverlay({
12229
12663
  }
12230
12664
  setCurrentStrokePoints((prev) => [...prev, pt]);
12231
12665
  setCurrentStrokePressures((prev) => [...prev, e.pressure]);
12666
+ setCurrentStrokeTiltX((prev) => [...prev, e.tiltX ?? 0]);
12667
+ setCurrentStrokeTiltY((prev) => [...prev, e.tiltY ?? 0]);
12232
12668
  },
12233
12669
  [isStrokeActive, activeTool, pointerToCanvasCoords]
12234
12670
  );
@@ -12242,113 +12678,54 @@ function useDrawingOverlay({
12242
12678
  if (isDrawingRef) {
12243
12679
  isDrawingRef.current = false;
12244
12680
  }
12245
- if (currentStrokePoints.length < 2) {
12246
- setCurrentStrokePoints([]);
12247
- return;
12248
- }
12249
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
12250
- for (const pt of currentStrokePoints) {
12251
- if (pt.x < minX) {
12252
- minX = pt.x;
12253
- }
12254
- if (pt.y < minY) {
12255
- minY = pt.y;
12256
- }
12257
- if (pt.x > maxX) {
12258
- maxX = pt.x;
12259
- }
12260
- if (pt.y > maxY) {
12261
- maxY = pt.y;
12262
- }
12263
- }
12264
- const PAD = drawingWidth;
12265
- minX -= PAD;
12266
- minY -= PAD;
12267
- maxX += PAD;
12268
- maxY += PAD;
12269
- const w = Math.max(maxX - minX, 1);
12270
- const h = Math.max(maxY - minY, 1);
12271
- const relPoints = currentStrokePoints.map((pt) => ({
12272
- x: pt.x - minX,
12273
- y: pt.y - minY
12274
- }));
12275
- if (activeTool === "freeform") {
12276
- const COORD_SCALE = 100;
12277
- const pathW = Math.round(w * COORD_SCALE);
12278
- const pathH = Math.round(h * COORD_SCALE);
12279
- const segments = [];
12280
- for (let i = 0; i < relPoints.length; i++) {
12281
- const scaledPt = {
12282
- x: Math.round(relPoints[i].x * COORD_SCALE),
12283
- y: Math.round(relPoints[i].y * COORD_SCALE)
12284
- };
12285
- segments.push(
12286
- i === 0 ? { type: "moveTo", pt: scaledPt } : { type: "lineTo", pt: scaledPt }
12287
- );
12288
- }
12289
- if (segments.length > 2) {
12290
- segments.push({ type: "close" });
12291
- }
12292
- const freeformShape = {
12293
- id: `shape-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12294
- type: "shape",
12295
- x: minX,
12296
- y: minY,
12297
- width: w,
12298
- height: h,
12299
- shapeType: "custom",
12300
- shapeStyle: {
12301
- fillColor: "transparent",
12302
- strokeColor: drawingColor,
12303
- strokeWidth: drawingWidth
12304
- },
12305
- customGeometryPaths: [{ width: pathW, height: pathH, segments }]
12306
- };
12307
- onAddFreeformShape?.(freeformShape);
12308
- } else {
12309
- const pathD = buildPathD(relPoints);
12310
- const isHighlighter = activeTool === "highlighter";
12311
- const hasPressure = currentStrokePressures.length >= 2 && currentStrokePressures.some((p) => Math.abs(p - currentStrokePressures[0]) > 0.01);
12312
- const ink = {
12313
- id: `ink-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12314
- type: "ink",
12315
- x: minX,
12316
- y: minY,
12317
- width: w,
12318
- height: h,
12319
- inkPaths: [pathD],
12320
- inkColors: [drawingColor],
12321
- inkWidths: [drawingWidth],
12322
- inkOpacities: [isHighlighter ? 0.4 : 1],
12323
- inkTool: isHighlighter ? "highlighter" : "pen",
12324
- ...hasPressure ? { inkPointPressures: [currentStrokePressures] } : {}
12325
- };
12326
- onAddInkElement?.(ink);
12681
+ const finished = finishDrawStroke({
12682
+ tool: activeTool,
12683
+ points: currentStrokePoints,
12684
+ pressures: currentStrokePressures,
12685
+ tiltX: currentStrokeTiltX,
12686
+ tiltY: currentStrokeTiltY,
12687
+ color: drawingColor,
12688
+ width: drawingWidth
12689
+ });
12690
+ if (finished?.kind === "freeform") {
12691
+ onAddFreeformShape?.(finished.element);
12692
+ } else if (finished?.kind === "ink") {
12693
+ onAddInkElement?.(finished.element);
12327
12694
  }
12328
12695
  setCurrentStrokePoints([]);
12329
12696
  setCurrentStrokePressures([]);
12697
+ setCurrentStrokeTiltX([]);
12698
+ setCurrentStrokeTiltY([]);
12330
12699
  },
12331
12700
  [
12332
12701
  isStrokeActive,
12333
12702
  activeTool,
12334
12703
  currentStrokePoints,
12704
+ currentStrokeTiltX,
12705
+ currentStrokeTiltY,
12335
12706
  drawingColor,
12336
12707
  drawingWidth,
12337
12708
  isDrawingRef,
12338
12709
  onAddInkElement,
12339
12710
  onAddFreeformShape,
12340
- buildPathD,
12341
12711
  currentStrokePressures
12342
12712
  ]
12343
12713
  );
12344
- const liveStrokeD = useMemo(
12345
- () => isStrokeActive ? buildPathD(currentStrokePoints) : "",
12346
- [isStrokeActive, currentStrokePoints, buildPathD]
12714
+ const { liveStrokeD, liveStrokeView } = useLiveInkPreview(
12715
+ isStrokeActive,
12716
+ activeTool,
12717
+ currentStrokePoints,
12718
+ currentStrokePressures,
12719
+ currentStrokeTiltX,
12720
+ currentStrokeTiltY,
12721
+ drawingColor,
12722
+ drawingWidth
12347
12723
  );
12348
12724
  return {
12349
12725
  isDrawing,
12350
12726
  isStrokeActive,
12351
12727
  liveStrokeD,
12728
+ liveStrokeView,
12352
12729
  currentStrokePoints,
12353
12730
  handleDrawPointerDown,
12354
12731
  handleDrawPointerMove,
@@ -12666,6 +13043,7 @@ function SlideCanvas({
12666
13043
  isDrawing,
12667
13044
  isStrokeActive,
12668
13045
  liveStrokeD,
13046
+ liveStrokeView,
12669
13047
  handleDrawPointerDown,
12670
13048
  handleDrawPointerMove,
12671
13049
  handleDrawPointerUp
@@ -12735,7 +13113,10 @@ function SlideCanvas({
12735
13113
  // pinch-zoom. View/present mode keeps the default so the slide can
12736
13114
  // still be scrolled and swipe-navigated.
12737
13115
  touchAction: isEditableCanvas ? "none" : void 0,
12738
- ...getReactSlideBackgroundStyle(activeSlide)
13116
+ ...getReactSlideBackgroundStyle(activeSlide, {
13117
+ widthPx: canvasSize.width,
13118
+ heightPx: canvasSize.height
13119
+ })
12739
13120
  },
12740
13121
  onClick: handleStageClick,
12741
13122
  onDoubleClick: handleStageDblClick,
@@ -12916,6 +13297,7 @@ function SlideCanvas({
12916
13297
  drawingWidth,
12917
13298
  isStrokeActive,
12918
13299
  liveStrokeD,
13300
+ liveStrokeView,
12919
13301
  onPointerDown: handleDrawPointerDown,
12920
13302
  onPointerMove: handleDrawPointerMove,
12921
13303
  onPointerUp: handleDrawPointerUp
@@ -13377,7 +13759,13 @@ function SlideThumbnailImpl({
13377
13759
  "div",
13378
13760
  {
13379
13761
  className: "relative w-full overflow-hidden rounded border border-border bg-white",
13380
- style: { height: previewHeight, ...getReactSlideBackgroundStyle(slide) },
13762
+ style: {
13763
+ height: previewHeight,
13764
+ ...getReactSlideBackgroundStyle(slide, {
13765
+ widthPx: safeCanvasWidth,
13766
+ heightPx: safeCanvasHeight
13767
+ })
13768
+ },
13381
13769
  children: /* @__PURE__ */ jsxs(
13382
13770
  "div",
13383
13771
  {
@@ -13455,7 +13843,7 @@ function arePropsEqual2(prev, next) {
13455
13843
  }
13456
13844
  return true;
13457
13845
  }
13458
- var SlideThumbnail = React19.memo(SlideThumbnailImpl, arePropsEqual2);
13846
+ var SlideThumbnail = React20.memo(SlideThumbnailImpl, arePropsEqual2);
13459
13847
 
13460
13848
  // src/viewer/components/context-menu-dispatch.ts
13461
13849
  function tableCell(props) {
@@ -14005,7 +14393,7 @@ function LazyThumbnailInner({
14005
14393
  }
14006
14394
  ) });
14007
14395
  }
14008
- var LazyThumbnail = React19.memo(LazyThumbnailInner);
14396
+ var LazyThumbnail = React20.memo(LazyThumbnailInner);
14009
14397
 
14010
14398
  // src/viewer/components/slides-pane/utils.ts
14011
14399
  function formatTimingMs(ms) {
@@ -14159,7 +14547,7 @@ function SlideItemInner({
14159
14547
  }
14160
14548
  );
14161
14549
  }
14162
- var SlideItem = React19.memo(SlideItemInner);
14550
+ var SlideItem = React20.memo(SlideItemInner);
14163
14551
  function useSlidePaneCallbacks(onMoveSlide, onRenameSection, onToggleSectionCollapse) {
14164
14552
  const [collapsedSections, setCollapsedSections] = useState({});
14165
14553
  const [renamingSectionId, setRenamingSectionId] = useState(null);
@@ -15480,7 +15868,7 @@ function arePropsEqual3(prev, next) {
15480
15868
  }
15481
15869
  return true;
15482
15870
  }
15483
- var SlideCard = React19.memo(SlideCardImpl, arePropsEqual3);
15871
+ var SlideCard = React20.memo(SlideCardImpl, arePropsEqual3);
15484
15872
  function SorterContextMenu({
15485
15873
  x,
15486
15874
  y,
@@ -18924,9 +19312,9 @@ function PresentationSubtitleBar({
18924
19312
  function renderNotesSegments(segments) {
18925
19313
  return notesSegmentsToSpans(segments).map((span) => {
18926
19314
  if (span.kind === "break") {
18927
- return React19.createElement("br", { key: span.key });
19315
+ return React20.createElement("br", { key: span.key });
18928
19316
  }
18929
- return React19.createElement(
19317
+ return React20.createElement(
18930
19318
  "span",
18931
19319
  { key: span.key, style: span.style },
18932
19320
  span.text
@@ -19155,7 +19543,7 @@ function arePropsEqual4(prev, next) {
19155
19543
  }
19156
19544
  return true;
19157
19545
  }
19158
- var ScaledSlidePreview = React19.memo(ScaledSlidePreviewImpl, arePropsEqual4);
19546
+ var ScaledSlidePreview = React20.memo(ScaledSlidePreviewImpl, arePropsEqual4);
19159
19547
  function PresenterNotesRail({
19160
19548
  slides,
19161
19549
  current,
@@ -20338,19 +20726,32 @@ function AnimationTimelineSection({
20338
20726
  ] })
20339
20727
  ] });
20340
20728
  }
20729
+ var NONE_VALUE = "none";
20730
+ var CURRENT_VALUE = "current";
20731
+ var OTHER_VALUE = "other";
20341
20732
  function EffectSoundRow({
20342
20733
  soundState,
20343
20734
  canEdit,
20344
- onPick
20735
+ onPick,
20736
+ onPickStock
20345
20737
  }) {
20346
20738
  const { t } = useTranslation();
20347
- const fileInputRef = React19.useRef(null);
20739
+ const fileInputRef = React20.useRef(null);
20740
+ const selectedValue = soundState.catalogueId ?? (soundState.hasSound ? CURRENT_VALUE : NONE_VALUE);
20348
20741
  const handleSelectChange = (event) => {
20349
- if (event.target.value === "custom") {
20742
+ const value = event.target.value;
20743
+ if (value === OTHER_VALUE) {
20350
20744
  fileInputRef.current?.click();
20351
20745
  return;
20352
20746
  }
20353
- onPick(void 0);
20747
+ if (value === NONE_VALUE) {
20748
+ onPick(void 0);
20749
+ return;
20750
+ }
20751
+ if (value === CURRENT_VALUE) {
20752
+ return;
20753
+ }
20754
+ onPickStock(value);
20354
20755
  };
20355
20756
  const handleFileChange = (event) => {
20356
20757
  const file = event.target.files?.[0];
@@ -20366,22 +20767,46 @@ function EffectSoundRow({
20366
20767
  };
20367
20768
  reader.readAsDataURL(file);
20368
20769
  };
20770
+ const handlePreview = () => {
20771
+ if (!soundState.catalogueId) {
20772
+ return;
20773
+ }
20774
+ const asset = getEffectSoundAsset(soundState.catalogueId);
20775
+ if (asset) {
20776
+ playAnimationSound(asset.dataUrl);
20777
+ }
20778
+ };
20369
20779
  return /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
20370
20780
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-[11px]", children: t("pptx.animation.sound") }),
20371
- /* @__PURE__ */ jsxs(
20372
- "select",
20373
- {
20374
- "aria-label": t("pptx.animation.sound"),
20375
- value: soundState.hasSound ? "custom" : "none",
20376
- onChange: handleSelectChange,
20377
- disabled: !canEdit,
20378
- className: SELECT_CLS,
20379
- children: [
20380
- /* @__PURE__ */ jsx("option", { value: "none", children: t("pptx.animation.sound.none") }),
20381
- /* @__PURE__ */ jsx("option", { value: "custom", children: soundState.hasSound && soundState.fileName ? soundState.fileName : t("pptx.animation.sound.custom") })
20382
- ]
20383
- }
20384
- ),
20781
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
20782
+ /* @__PURE__ */ jsxs(
20783
+ "select",
20784
+ {
20785
+ "aria-label": t("pptx.animation.sound"),
20786
+ value: selectedValue,
20787
+ onChange: handleSelectChange,
20788
+ disabled: !canEdit,
20789
+ className: SELECT_CLS,
20790
+ children: [
20791
+ /* @__PURE__ */ jsx("option", { value: NONE_VALUE, children: t("pptx.animation.sound.none") }),
20792
+ soundState.hasSound && !soundState.catalogueId && /* @__PURE__ */ jsx("option", { value: CURRENT_VALUE, children: soundState.fileName ?? t("pptx.animation.sound.custom") }),
20793
+ EFFECT_SOUND_CATALOGUE.map((entry) => /* @__PURE__ */ jsx("option", { value: entry.id, children: t(entry.i18nKey) }, entry.id)),
20794
+ /* @__PURE__ */ jsx("option", { value: OTHER_VALUE, children: t("pptx.animation.sound.other") })
20795
+ ]
20796
+ }
20797
+ ),
20798
+ /* @__PURE__ */ jsx(
20799
+ "button",
20800
+ {
20801
+ type: "button",
20802
+ "aria-label": t("pptx.animation.sound.preview"),
20803
+ onClick: handlePreview,
20804
+ disabled: !soundState.catalogueId,
20805
+ className: "shrink-0 rounded border border-border bg-muted p-1 disabled:opacity-40",
20806
+ children: /* @__PURE__ */ jsx(LuPlay, { className: "h-3 w-3" })
20807
+ }
20808
+ )
20809
+ ] }),
20385
20810
  /* @__PURE__ */ jsx(
20386
20811
  "input",
20387
20812
  {
@@ -20752,6 +21177,15 @@ function useAnimationHandlers({
20752
21177
  },
20753
21178
  [canEdit, updateAnimations, selectedElement.id]
20754
21179
  );
21180
+ const handleEffectStockSoundPick = useCallback(
21181
+ (catalogueId) => {
21182
+ if (!canEdit) {
21183
+ return;
21184
+ }
21185
+ updateAnimations((anims) => setEffectStockSound(anims, selectedElement.id, catalogueId));
21186
+ },
21187
+ [canEdit, updateAnimations, selectedElement.id]
21188
+ );
20755
21189
  const handleAfterAnimationChange = useCallback(
20756
21190
  (action) => {
20757
21191
  if (!canEdit) {
@@ -20831,6 +21265,7 @@ function useAnimationHandlers({
20831
21265
  handleMotionPathChange,
20832
21266
  effectSoundState,
20833
21267
  handleEffectSoundPick,
21268
+ handleEffectStockSoundPick,
20834
21269
  handleAfterAnimationChange,
20835
21270
  handleAfterAnimationColorChange,
20836
21271
  getTimelineLabel,
@@ -20871,6 +21306,7 @@ function AnimationPanel({
20871
21306
  handleMotionPathChange,
20872
21307
  effectSoundState,
20873
21308
  handleEffectSoundPick,
21309
+ handleEffectStockSoundPick,
20874
21310
  handleAfterAnimationChange,
20875
21311
  handleAfterAnimationColorChange,
20876
21312
  handlePreviewClick
@@ -20994,7 +21430,8 @@ function AnimationPanel({
20994
21430
  {
20995
21431
  soundState: effectSoundState,
20996
21432
  canEdit,
20997
- onPick: handleEffectSoundPick
21433
+ onPick: handleEffectSoundPick,
21434
+ onPickStock: handleEffectStockSoundPick
20998
21435
  }
20999
21436
  ),
21000
21437
  /* @__PURE__ */ jsx(
@@ -22380,6 +22817,87 @@ function ChartErrorBarOptions({
22380
22817
  }) })
22381
22818
  ] });
22382
22819
  }
22820
+ function ChartFilteredSeriesOptions({
22821
+ chartData,
22822
+ canEdit,
22823
+ onHideSeries,
22824
+ onRestoreSeries,
22825
+ onSetDataLabelsRangeCache
22826
+ }) {
22827
+ const { t } = useTranslation();
22828
+ const filteredSeries = chartData.filteredSeries ?? [];
22829
+ const seriesWithRange = chartData.series.map((series, index) => ({ series, index })).filter(({ series }) => series.dataLabelOptions?.dataLabelsRange);
22830
+ if (filteredSeries.length === 0 && seriesWithRange.length === 0 && chartData.series.length <= 1) {
22831
+ return null;
22832
+ }
22833
+ return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
22834
+ /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.chart.chartFilters") }),
22835
+ chartData.series.length > 1 && /* @__PURE__ */ jsx("div", { className: "space-y-1", children: chartData.series.map((series, index) => /* @__PURE__ */ jsxs(
22836
+ "div",
22837
+ {
22838
+ className: "flex items-center gap-2 text-[11px]",
22839
+ children: [
22840
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", title: series.name, children: series.name }),
22841
+ /* @__PURE__ */ jsx(
22842
+ "button",
22843
+ {
22844
+ type: "button",
22845
+ className: BTN2,
22846
+ disabled: !canEdit,
22847
+ "aria-label": t("pptx.chart.hideSeries", { name: series.name }),
22848
+ "data-testid": `chart-series-hide-${index}`,
22849
+ onClick: () => onHideSeries(index),
22850
+ children: /* @__PURE__ */ jsx(LuEyeOff, { className: "size-3", "aria-hidden": "true" })
22851
+ }
22852
+ )
22853
+ ]
22854
+ },
22855
+ `visible-${series.name}-${index}`
22856
+ )) }),
22857
+ filteredSeries.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-1", children: filteredSeries.map((filtered, index) => {
22858
+ const name = filtered.name ?? chartData.filteredSeriesTitle ?? t("pptx.chart.seriesShort");
22859
+ return /* @__PURE__ */ jsxs(
22860
+ "div",
22861
+ {
22862
+ className: "flex items-center gap-2 text-[11px] opacity-60",
22863
+ children: [
22864
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", title: name, children: name }),
22865
+ /* @__PURE__ */ jsx(
22866
+ "button",
22867
+ {
22868
+ type: "button",
22869
+ className: BTN2,
22870
+ disabled: !canEdit,
22871
+ "aria-label": t("pptx.chart.showSeries", { name }),
22872
+ "data-testid": `chart-series-show-${index}`,
22873
+ onClick: () => onRestoreSeries(index),
22874
+ children: /* @__PURE__ */ jsx(LuEye, { className: "size-3", "aria-hidden": "true" })
22875
+ }
22876
+ )
22877
+ ]
22878
+ },
22879
+ `filtered-${name}-${index}`
22880
+ );
22881
+ }) }),
22882
+ seriesWithRange.map(({ series, index: seriesIndex }) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
22883
+ /* @__PURE__ */ jsx("div", { className: "text-[11px] text-muted-foreground truncate", title: series.name, children: t("pptx.chart.valueFromCells", { name: series.name }) }),
22884
+ series.dataLabelOptions.dataLabelsRange.cache.map((text, pointIndex) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-[11px]", children: [
22885
+ /* @__PURE__ */ jsx("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: chartData.categories[pointIndex] ?? pointIndex }),
22886
+ /* @__PURE__ */ jsx(
22887
+ "input",
22888
+ {
22889
+ type: "text",
22890
+ disabled: !canEdit,
22891
+ className: "flex-1 bg-muted border border-border rounded px-1.5 py-0.5",
22892
+ value: text,
22893
+ "data-testid": `chart-dlbl-range-${seriesIndex}-${pointIndex}`,
22894
+ onChange: (e) => onSetDataLabelsRangeCache(seriesIndex, pointIndex, e.target.value)
22895
+ }
22896
+ )
22897
+ ] }, pointIndex))
22898
+ ] }, `range-${series.name}-${seriesIndex}`))
22899
+ ] });
22900
+ }
22383
22901
  function ChartMarkerOptions({
22384
22902
  chartType,
22385
22903
  series,
@@ -22683,6 +23201,7 @@ function ChartTrendlineOptions({
22683
23201
  function ChartTypeSelector({
22684
23202
  title,
22685
23203
  chartType,
23204
+ chartData,
22686
23205
  grouping,
22687
23206
  seriesCount,
22688
23207
  categoryCount,
@@ -22692,6 +23211,7 @@ function ChartTypeSelector({
22692
23211
  }) {
22693
23212
  const { t } = useTranslation();
22694
23213
  const supportsGrouping = GROUPING_SUPPORTED_TYPES.has(chartType);
23214
+ const displayedType = resolveDisplayedChartType(chartData);
22695
23215
  return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
22696
23216
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.chart.heading") }),
22697
23217
  /* @__PURE__ */ jsxs("div", { className: "text-[11px] text-muted-foreground mb-1", children: [
@@ -22724,7 +23244,7 @@ function ChartTypeSelector({
22724
23244
  "aria-label": t("pptx.chart.type"),
22725
23245
  disabled: !canEdit,
22726
23246
  className: INPUT2,
22727
- value: chartType,
23247
+ value: displayedType,
22728
23248
  onChange: (e) => onUpdateChartData({
22729
23249
  chartType: e.target.value
22730
23250
  }),
@@ -22750,6 +23270,208 @@ function ChartTypeSelector({
22750
23270
  ] })
22751
23271
  ] });
22752
23272
  }
23273
+ function NumberField({ value, canEdit, fraction, nonNegative, onChange }) {
23274
+ return /* @__PURE__ */ jsx(
23275
+ "input",
23276
+ {
23277
+ type: "number",
23278
+ step: fraction ? "0.01" : void 0,
23279
+ min: fraction || nonNegative ? 0 : void 0,
23280
+ max: fraction ? 1 : void 0,
23281
+ disabled: !canEdit,
23282
+ className: INPUT2,
23283
+ value,
23284
+ onChange: (e) => onChange(Number(e.target.value))
23285
+ }
23286
+ );
23287
+ }
23288
+ function RotationField({
23289
+ row,
23290
+ canEdit,
23291
+ onRotationPatch
23292
+ }) {
23293
+ const { t } = useTranslation();
23294
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
23295
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeRotation") }),
23296
+ /* @__PURE__ */ jsx(
23297
+ "input",
23298
+ {
23299
+ type: "number",
23300
+ step: "1",
23301
+ "aria-label": t("pptx.chart.userShapeRotation"),
23302
+ disabled: !canEdit,
23303
+ className: INPUT2,
23304
+ value: row.rotation ?? 0,
23305
+ onChange: (e) => onRotationPatch(row.path, Number(e.target.value) || void 0)
23306
+ }
23307
+ )
23308
+ ] });
23309
+ }
23310
+ function FlipFields({
23311
+ row,
23312
+ canEdit,
23313
+ onFlipPatch
23314
+ }) {
23315
+ const { t } = useTranslation();
23316
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
23317
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1 cursor-pointer", children: [
23318
+ /* @__PURE__ */ jsx(
23319
+ "input",
23320
+ {
23321
+ type: "checkbox",
23322
+ "aria-label": t("pptx.arrange.flipHorizontally"),
23323
+ disabled: !canEdit,
23324
+ className: "accent-primary",
23325
+ checked: row.flipH ?? false,
23326
+ onChange: (e) => onFlipPatch(row.path, { flipH: e.target.checked })
23327
+ }
23328
+ ),
23329
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.arrange.flipHorizontally") })
23330
+ ] }),
23331
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1 cursor-pointer", children: [
23332
+ /* @__PURE__ */ jsx(
23333
+ "input",
23334
+ {
23335
+ type: "checkbox",
23336
+ "aria-label": t("pptx.arrange.flipVertically"),
23337
+ disabled: !canEdit,
23338
+ className: "accent-primary",
23339
+ checked: row.flipV ?? false,
23340
+ onChange: (e) => onFlipPatch(row.path, { flipV: e.target.checked })
23341
+ }
23342
+ ),
23343
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.arrange.flipVertically") })
23344
+ ] })
23345
+ ] });
23346
+ }
23347
+ function ChartUserShapePositionFields({
23348
+ row,
23349
+ userShapes,
23350
+ canEdit,
23351
+ onPatch,
23352
+ onBoxPatch,
23353
+ onRotationPatch,
23354
+ onFlipPatch
23355
+ }) {
23356
+ const { t } = useTranslation();
23357
+ const update = (patch) => onPatch(row.path, patch);
23358
+ if (row.depth === 0) {
23359
+ const from = row.from;
23360
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 text-[11px]", children: [
23361
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFrom") }),
23362
+ /* @__PURE__ */ jsx(
23363
+ NumberField,
23364
+ {
23365
+ fraction: true,
23366
+ canEdit,
23367
+ value: from.x,
23368
+ onChange: (x) => update({ from: { ...from, x } })
23369
+ }
23370
+ ),
23371
+ /* @__PURE__ */ jsx(
23372
+ NumberField,
23373
+ {
23374
+ fraction: true,
23375
+ canEdit,
23376
+ value: from.y,
23377
+ onChange: (y) => update({ from: { ...from, y } })
23378
+ }
23379
+ ),
23380
+ row.anchor === "rel" && row.to ? /* @__PURE__ */ jsxs(Fragment, { children: [
23381
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeTo") }),
23382
+ /* @__PURE__ */ jsx(
23383
+ NumberField,
23384
+ {
23385
+ fraction: true,
23386
+ canEdit,
23387
+ value: row.to.x,
23388
+ onChange: (x) => update({ to: { ...row.to, x } })
23389
+ }
23390
+ ),
23391
+ /* @__PURE__ */ jsx(
23392
+ NumberField,
23393
+ {
23394
+ fraction: true,
23395
+ canEdit,
23396
+ value: row.to.y,
23397
+ onChange: (y) => update({ to: { ...row.to, y } })
23398
+ }
23399
+ )
23400
+ ] }) : null,
23401
+ row.anchor === "abs" && row.ext ? /* @__PURE__ */ jsxs(Fragment, { children: [
23402
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeSize") }),
23403
+ /* @__PURE__ */ jsx(
23404
+ NumberField,
23405
+ {
23406
+ nonNegative: true,
23407
+ canEdit,
23408
+ value: row.ext.cx,
23409
+ onChange: (cx) => update({ ext: { ...row.ext, cx } })
23410
+ }
23411
+ ),
23412
+ /* @__PURE__ */ jsx(
23413
+ NumberField,
23414
+ {
23415
+ nonNegative: true,
23416
+ canEdit,
23417
+ value: row.ext.cy,
23418
+ onChange: (cy) => update({ ext: { ...row.ext, cy } })
23419
+ }
23420
+ )
23421
+ ] }) : null,
23422
+ /* @__PURE__ */ jsx(RotationField, { row, canEdit, onRotationPatch }),
23423
+ /* @__PURE__ */ jsx(FlipFields, { row, canEdit, onFlipPatch })
23424
+ ] });
23425
+ }
23426
+ const box = getChartUserShapeRowChartBox(userShapes, row.path);
23427
+ if (!box) {
23428
+ return null;
23429
+ }
23430
+ const patchBox = (next) => onBoxPatch(row.path, { from: box.from, to: box.to, ...next });
23431
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 text-[11px]", children: [
23432
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFrom") }),
23433
+ /* @__PURE__ */ jsx(
23434
+ NumberField,
23435
+ {
23436
+ fraction: true,
23437
+ canEdit,
23438
+ value: box.from.x,
23439
+ onChange: (x) => patchBox({ from: { ...box.from, x } })
23440
+ }
23441
+ ),
23442
+ /* @__PURE__ */ jsx(
23443
+ NumberField,
23444
+ {
23445
+ fraction: true,
23446
+ canEdit,
23447
+ value: box.from.y,
23448
+ onChange: (y) => patchBox({ from: { ...box.from, y } })
23449
+ }
23450
+ ),
23451
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeTo") }),
23452
+ /* @__PURE__ */ jsx(
23453
+ NumberField,
23454
+ {
23455
+ fraction: true,
23456
+ canEdit,
23457
+ value: box.to.x,
23458
+ onChange: (x) => patchBox({ to: { ...box.to, x } })
23459
+ }
23460
+ ),
23461
+ /* @__PURE__ */ jsx(
23462
+ NumberField,
23463
+ {
23464
+ fraction: true,
23465
+ canEdit,
23466
+ value: box.to.y,
23467
+ onChange: (y) => patchBox({ to: { ...box.to, y } })
23468
+ }
23469
+ ),
23470
+ /* @__PURE__ */ jsx(RotationField, { row, canEdit, onRotationPatch }),
23471
+ /* @__PURE__ */ jsx(FlipFields, { row, canEdit, onFlipPatch })
23472
+ ] });
23473
+ }
23474
+ var PATH_KEY = (path) => path.join(",");
22753
23475
  function ChartUserShapeOptions({
22754
23476
  chartData,
22755
23477
  canEdit,
@@ -22757,11 +23479,28 @@ function ChartUserShapeOptions({
22757
23479
  }) {
22758
23480
  const { t } = useTranslation();
22759
23481
  const shapes = chartData.userShapes;
22760
- const descriptors = listChartUserShapeDescriptors(shapes);
23482
+ const rows = listChartUserShapeRows(shapes);
22761
23483
  const kindLabel = (kind) => {
22762
23484
  const key = `pptx.chart.userShapeKind${kind.charAt(0).toUpperCase()}${kind.slice(1)}`;
22763
23485
  return t(key);
22764
23486
  };
23487
+ const update = (path, patch) => onUpdateChartData({ userShapes: withChartUserShapeRowUpdated(shapes, path, patch) });
23488
+ const updateBox = (path, box) => onUpdateChartData({ userShapes: withChartUserShapeRowChartBoxUpdated(shapes, path, box) });
23489
+ const updateRotation = (path, rotation) => onUpdateChartData({ userShapes: withChartUserShapeRowRotationUpdated(shapes, path, rotation) });
23490
+ const updateFlip = (path, flip) => onUpdateChartData({ userShapes: withChartUserShapeRowFlipUpdated(shapes, path, flip) });
23491
+ const addIntoGroup = (path) => {
23492
+ const transform = getChartUserShapeGroupTransform(shapes, path);
23493
+ if (!transform) {
23494
+ return;
23495
+ }
23496
+ onUpdateChartData({
23497
+ userShapes: withChartUserShapeGroupChildAdded(
23498
+ shapes,
23499
+ path,
23500
+ createDefaultChartUserShapeGroupChild(transform)
23501
+ )
23502
+ });
23503
+ };
22765
23504
  return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
22766
23505
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
22767
23506
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.chart.userShapes") }),
@@ -22778,99 +23517,120 @@ function ChartUserShapeOptions({
22778
23517
  }
22779
23518
  )
22780
23519
  ] }),
22781
- descriptors.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-[11px] text-muted-foreground", children: t("pptx.chart.userShapesEmpty") }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: descriptors.map((d) => /* @__PURE__ */ jsxs("div", { className: "space-y-1 rounded border border-border p-1.5", children: [
22782
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px]", children: [
22783
- /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate", children: [
22784
- kindLabel(d.kind),
22785
- d.text ? ` - ${d.text}` : ""
22786
- ] }),
22787
- /* @__PURE__ */ jsx(
22788
- "button",
22789
- {
22790
- type: "button",
22791
- disabled: !canEdit,
22792
- "aria-label": t("pptx.chart.userShapeDelete"),
22793
- className: BTN2,
22794
- onClick: () => onUpdateChartData({ userShapes: withChartUserShapeRemoved(shapes, d.index) }),
22795
- children: "\u2715"
22796
- }
22797
- )
22798
- ] }),
22799
- d.editable ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[11px]", children: [
22800
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFrom") }),
22801
- /* @__PURE__ */ jsx(
22802
- "input",
22803
- {
22804
- type: "number",
22805
- step: "0.01",
22806
- min: 0,
22807
- max: 1,
22808
- disabled: !canEdit,
22809
- className: INPUT2,
22810
- value: d.from.x,
22811
- onChange: (e) => onUpdateChartData({
22812
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22813
- from: { ...d.from, x: Number(e.target.value) }
22814
- })
22815
- })
22816
- }
22817
- ),
22818
- /* @__PURE__ */ jsx(
22819
- "input",
22820
- {
22821
- type: "number",
22822
- step: "0.01",
22823
- min: 0,
22824
- max: 1,
22825
- disabled: !canEdit,
22826
- className: INPUT2,
22827
- value: d.from.y,
22828
- onChange: (e) => onUpdateChartData({
22829
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22830
- from: { ...d.from, y: Number(e.target.value) }
22831
- })
22832
- })
22833
- }
22834
- ),
22835
- d.anchor === "rel" && d.to ? /* @__PURE__ */ jsxs(Fragment, { children: [
22836
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeTo") }),
22837
- /* @__PURE__ */ jsx(
22838
- "input",
22839
- {
22840
- type: "number",
22841
- step: "0.01",
22842
- min: 0,
22843
- max: 1,
22844
- disabled: !canEdit,
22845
- className: INPUT2,
22846
- value: d.to.x,
22847
- onChange: (e) => onUpdateChartData({
22848
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22849
- to: { ...d.to, x: Number(e.target.value) }
23520
+ rows.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-[11px] text-muted-foreground", children: t("pptx.chart.userShapesEmpty") }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: rows.map((row) => /* @__PURE__ */ jsxs(
23521
+ "div",
23522
+ {
23523
+ "data-chart-user-shape-path": PATH_KEY(row.path),
23524
+ style: { marginLeft: row.depth * 12 },
23525
+ className: "space-y-1 rounded border border-border p-1.5",
23526
+ children: [
23527
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px]", children: [
23528
+ /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate", children: [
23529
+ kindLabel(row.kind),
23530
+ row.text ? ` - ${row.text}` : ""
23531
+ ] }),
23532
+ row.isGroup ? /* @__PURE__ */ jsx(
23533
+ "button",
23534
+ {
23535
+ type: "button",
23536
+ disabled: !canEdit,
23537
+ className: BTN2,
23538
+ onClick: () => addIntoGroup(row.path),
23539
+ children: t("pptx.chart.userShapeAddIntoGroup")
23540
+ }
23541
+ ) : null,
23542
+ /* @__PURE__ */ jsx(
23543
+ "button",
23544
+ {
23545
+ type: "button",
23546
+ disabled: !canEdit,
23547
+ "aria-label": t("pptx.chart.userShapeDelete"),
23548
+ className: BTN2,
23549
+ onClick: () => onUpdateChartData({
23550
+ userShapes: withChartUserShapeRowRemoved(shapes, row.path)
23551
+ }),
23552
+ children: "\u2715"
23553
+ }
23554
+ )
23555
+ ] }),
23556
+ row.editableVisuals ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[11px]", children: [
23557
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeText") }),
23558
+ /* @__PURE__ */ jsx(
23559
+ "input",
23560
+ {
23561
+ type: "text",
23562
+ "aria-label": t("pptx.chart.userShapeText"),
23563
+ disabled: !canEdit,
23564
+ className: INPUT2,
23565
+ value: row.text ?? "",
23566
+ onChange: (e) => onUpdateChartData({
23567
+ userShapes: withChartUserShapeRowTextUpdated(
23568
+ shapes,
23569
+ row.path,
23570
+ e.target.value
23571
+ )
22850
23572
  })
22851
- })
22852
- }
22853
- ),
23573
+ }
23574
+ )
23575
+ ] }) : null,
23576
+ row.editableVisuals ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[11px]", children: [
23577
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
23578
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFill") }),
23579
+ /* @__PURE__ */ jsx(
23580
+ "input",
23581
+ {
23582
+ type: "color",
23583
+ "aria-label": t("pptx.chart.userShapeFill"),
23584
+ disabled: !canEdit,
23585
+ value: row.fill ?? "#ffffff",
23586
+ onChange: (e) => update(row.path, { fill: e.target.value })
23587
+ }
23588
+ )
23589
+ ] }),
23590
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
23591
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeStroke") }),
23592
+ /* @__PURE__ */ jsx(
23593
+ "input",
23594
+ {
23595
+ type: "color",
23596
+ "aria-label": t("pptx.chart.userShapeStroke"),
23597
+ disabled: !canEdit,
23598
+ value: row.stroke ?? "#000000",
23599
+ onChange: (e) => update(row.path, { stroke: e.target.value })
23600
+ }
23601
+ )
23602
+ ] })
23603
+ ] }) : null,
23604
+ row.editableAltText ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[11px]", children: [
23605
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeAltText") }),
23606
+ /* @__PURE__ */ jsx(
23607
+ "input",
23608
+ {
23609
+ type: "text",
23610
+ "aria-label": t("pptx.chart.userShapeAltText"),
23611
+ disabled: !canEdit,
23612
+ className: INPUT2,
23613
+ value: row.altText ?? "",
23614
+ onChange: (e) => update(row.path, { altText: e.target.value })
23615
+ }
23616
+ )
23617
+ ] }) : null,
22854
23618
  /* @__PURE__ */ jsx(
22855
- "input",
23619
+ ChartUserShapePositionFields,
22856
23620
  {
22857
- type: "number",
22858
- step: "0.01",
22859
- min: 0,
22860
- max: 1,
22861
- disabled: !canEdit,
22862
- className: INPUT2,
22863
- value: d.to.y,
22864
- onChange: (e) => onUpdateChartData({
22865
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22866
- to: { ...d.to, y: Number(e.target.value) }
22867
- })
22868
- })
23621
+ row,
23622
+ userShapes: shapes,
23623
+ canEdit,
23624
+ onPatch: update,
23625
+ onBoxPatch: updateBox,
23626
+ onRotationPatch: updateRotation,
23627
+ onFlipPatch: updateFlip
22869
23628
  }
22870
23629
  )
22871
- ] }) : null
22872
- ] }) : /* @__PURE__ */ jsx("div", { className: "text-[10px] italic text-muted-foreground", children: t("pptx.chart.userShapeNotEditable") })
22873
- ] }, d.index)) })
23630
+ ]
23631
+ },
23632
+ PATH_KEY(row.path)
23633
+ )) })
22874
23634
  ] });
22875
23635
  }
22876
23636
  function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
@@ -23045,6 +23805,36 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
23045
23805
  },
23046
23806
  [chartData, replaceChartData]
23047
23807
  );
23808
+ const hideSeries = useCallback(
23809
+ (seriesIndex) => {
23810
+ const next = chartData && hideChartSeries(chartData, seriesIndex);
23811
+ if (next) {
23812
+ replaceChartData(next);
23813
+ }
23814
+ },
23815
+ [chartData, replaceChartData]
23816
+ );
23817
+ const restoreSeries = useCallback(
23818
+ (filteredIndex) => {
23819
+ const next = chartData && restoreFilteredSeries(chartData, filteredIndex);
23820
+ if (next) {
23821
+ replaceChartData(next);
23822
+ }
23823
+ },
23824
+ [chartData, replaceChartData]
23825
+ );
23826
+ const setLabelsRangeCache = useCallback(
23827
+ (seriesIndex, pointIndex, text) => {
23828
+ if (!series) {
23829
+ return;
23830
+ }
23831
+ const updated = series.map(
23832
+ (s, i) => i === seriesIndex ? setDataLabelsRangeCache(s, pointIndex, text) : s
23833
+ );
23834
+ updateChartData({ series: updated });
23835
+ },
23836
+ [series, updateChartData]
23837
+ );
23048
23838
  const applyChartOp = useCallback(
23049
23839
  (mutate) => {
23050
23840
  if (!chartData) {
@@ -23106,6 +23896,7 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
23106
23896
  {
23107
23897
  title,
23108
23898
  chartType,
23899
+ chartData,
23109
23900
  grouping,
23110
23901
  seriesCount: series.length,
23111
23902
  categoryCount: categories.length,
@@ -23211,6 +24002,16 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
23211
24002
  onToggleSecondaryAxis: toggleSecondaryAxis
23212
24003
  }
23213
24004
  ),
24005
+ /* @__PURE__ */ jsx(
24006
+ ChartFilteredSeriesOptions,
24007
+ {
24008
+ chartData,
24009
+ canEdit,
24010
+ onHideSeries: hideSeries,
24011
+ onRestoreSeries: restoreSeries,
24012
+ onSetDataLabelsRangeCache: setLabelsRangeCache
24013
+ }
24014
+ ),
23214
24015
  /* @__PURE__ */ jsx(
23215
24016
  ChartUserShapeOptions,
23216
24017
  {
@@ -23237,6 +24038,296 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
23237
24038
  )
23238
24039
  ] });
23239
24040
  }
24041
+ function OleSheetGridEditor({
24042
+ grid,
24043
+ onCellEdit,
24044
+ t
24045
+ }) {
24046
+ if (!grid || grid.rows.length === 0) {
24047
+ return /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: t("pptx.ole.editDialog.emptySheet") });
24048
+ }
24049
+ return /* @__PURE__ */ jsx("div", { className: "overflow-auto max-h-[50vh] border border-border rounded", children: /* @__PURE__ */ jsx("table", { className: "w-full text-xs border-collapse", children: /* @__PURE__ */ jsx("tbody", { children: grid.rows.map((row, rowIndex) => (
24050
+ // oxlint-disable-next-line no-array-index-key -- grid rows have no stable id
24051
+ /* @__PURE__ */ jsx("tr", { children: row.cells.map((cell, colIndex) => /* @__PURE__ */ jsx(
24052
+ "td",
24053
+ {
24054
+ className: "border border-border p-0",
24055
+ children: /* @__PURE__ */ jsx(
24056
+ "input",
24057
+ {
24058
+ type: "text",
24059
+ defaultValue: cell.value,
24060
+ "aria-label": t("pptx.ole.editDialog.cellEditLabel"),
24061
+ className: "w-full px-1.5 py-1 bg-transparent focus:bg-accent/40 focus:outline-none",
24062
+ onBlur: (e) => {
24063
+ if (e.target.value !== cell.value) {
24064
+ onCellEdit(rowIndex, colIndex, e.target.value);
24065
+ }
24066
+ }
24067
+ }
24068
+ )
24069
+ },
24070
+ colIndex
24071
+ )) }, rowIndex)
24072
+ )) }) }) });
24073
+ }
24074
+ function OleDocumentEditor({
24075
+ paragraphs,
24076
+ onEdit,
24077
+ t
24078
+ }) {
24079
+ if (!paragraphs || paragraphs.length === 0) {
24080
+ return /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: t("pptx.ole.editDialog.emptyDocument") });
24081
+ }
24082
+ return /* @__PURE__ */ jsx("div", { className: "space-y-2", children: paragraphs.map((paragraph, index) => /* @__PURE__ */ jsx(
24083
+ "textarea",
24084
+ {
24085
+ defaultValue: paragraph,
24086
+ rows: 2,
24087
+ className: "w-full px-2 py-1.5 rounded border border-border bg-muted text-foreground text-xs resize-y focus:outline-none focus:ring-2 focus:ring-primary/50",
24088
+ onBlur: (e) => {
24089
+ if (e.target.value !== paragraph) {
24090
+ onEdit(index, e.target.value);
24091
+ }
24092
+ }
24093
+ },
24094
+ index
24095
+ )) });
24096
+ }
24097
+ function OleDeckEditor({
24098
+ slides,
24099
+ onEdit,
24100
+ t
24101
+ }) {
24102
+ if (!slides || slides.length === 0) {
24103
+ return /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: t("pptx.ole.editDialog.deckEmpty") });
24104
+ }
24105
+ return /* @__PURE__ */ jsx("div", { className: "space-y-3", children: slides.map((slide) => /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
24106
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs font-medium", children: t("pptx.ole.editDialog.deckSlideLabel").replace("{{number}}", String(slide.index + 1)) }),
24107
+ slide.elements.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs italic", children: t("pptx.ole.editDialog.deckEmpty") }) : slide.elements.map((element) => /* @__PURE__ */ jsx(
24108
+ "input",
24109
+ {
24110
+ type: "text",
24111
+ defaultValue: element.text,
24112
+ className: "w-full px-2 py-1.5 rounded border border-border bg-muted text-foreground text-xs focus:outline-none focus:ring-2 focus:ring-primary/50",
24113
+ onBlur: (e) => {
24114
+ if (e.target.value !== element.text) {
24115
+ onEdit(slide.index, element.elementId, e.target.value);
24116
+ }
24117
+ }
24118
+ },
24119
+ element.elementId
24120
+ ))
24121
+ ] }, slide.index)) });
24122
+ }
24123
+ function OleEditorDialog({
24124
+ isOpen,
24125
+ onClose,
24126
+ element,
24127
+ onUpdateElement
24128
+ }) {
24129
+ const { t } = useTranslation();
24130
+ const dialogRef = useRef(null);
24131
+ const fileInputRef = useRef(null);
24132
+ const descriptor = buildOleEditDialogDescriptor(element);
24133
+ const [grid, setGrid] = useState(void 0);
24134
+ const [paragraphs, setParagraphs] = useState(void 0);
24135
+ const [deckSlides, setDeckSlides] = useState(void 0);
24136
+ const [loading, setLoading] = useState(false);
24137
+ const [saveError, setSaveError] = useState(false);
24138
+ useEffect(() => {
24139
+ if (!isOpen || !descriptor.contentTab) {
24140
+ return;
24141
+ }
24142
+ let cancelled = false;
24143
+ setLoading(true);
24144
+ const kind = descriptor.contentTab.kind;
24145
+ const load = async () => {
24146
+ if (kind === "sheet") {
24147
+ const value = await getOleSheetGrid(element);
24148
+ if (!cancelled) {
24149
+ setGrid(value);
24150
+ }
24151
+ } else if (kind === "document") {
24152
+ const value = await getOleDocumentParagraphs(element);
24153
+ if (!cancelled) {
24154
+ setParagraphs(value);
24155
+ }
24156
+ } else if (kind === "deck") {
24157
+ const value = await getOleNestedDeckDetail(element);
24158
+ if (!cancelled) {
24159
+ setDeckSlides(value);
24160
+ }
24161
+ }
24162
+ if (!cancelled) {
24163
+ setLoading(false);
24164
+ }
24165
+ };
24166
+ void load();
24167
+ return () => {
24168
+ cancelled = true;
24169
+ };
24170
+ }, [isOpen, element]);
24171
+ const commit = useCallback(
24172
+ (updated) => {
24173
+ if (!updated.oleContentDirty) {
24174
+ return;
24175
+ }
24176
+ onUpdateElement(buildOleContentUpdatePatch(updated));
24177
+ },
24178
+ [onUpdateElement]
24179
+ );
24180
+ const handleCellEdit = useCallback(
24181
+ async (row, col, value) => {
24182
+ try {
24183
+ const updated = await applyOleSheetCellEdit(element, { row, col, value });
24184
+ commit(updated);
24185
+ const refreshed = await getOleSheetGrid(updated);
24186
+ setGrid(refreshed);
24187
+ } catch {
24188
+ setSaveError(true);
24189
+ }
24190
+ },
24191
+ [element, commit]
24192
+ );
24193
+ const handleParagraphEdit = useCallback(
24194
+ async (index, text) => {
24195
+ try {
24196
+ const updated = await applyOleDocumentParagraphEdit(element, index, text);
24197
+ commit(updated);
24198
+ const refreshed = await getOleDocumentParagraphs(updated);
24199
+ setParagraphs(refreshed);
24200
+ } catch {
24201
+ setSaveError(true);
24202
+ }
24203
+ },
24204
+ [element, commit]
24205
+ );
24206
+ const handleDeckElementEdit = useCallback(
24207
+ async (slideIndex, deckElementId, text) => {
24208
+ try {
24209
+ const updated = await applyOleNestedDeckElementTextEdit(
24210
+ element,
24211
+ slideIndex,
24212
+ deckElementId,
24213
+ text
24214
+ );
24215
+ commit(updated);
24216
+ const refreshed = await getOleNestedDeckDetail(updated);
24217
+ setDeckSlides(refreshed);
24218
+ } catch {
24219
+ setSaveError(true);
24220
+ }
24221
+ },
24222
+ [element, commit]
24223
+ );
24224
+ const handleReplaceFile = useCallback(
24225
+ async (file) => {
24226
+ try {
24227
+ const bytes = new Uint8Array(await file.arrayBuffer());
24228
+ const updated = await replaceOleFile(element, bytes, file.name);
24229
+ commit(updated);
24230
+ onClose();
24231
+ } catch {
24232
+ setSaveError(true);
24233
+ }
24234
+ },
24235
+ [element, commit, onClose]
24236
+ );
24237
+ const handleKeyDown = useCallback(
24238
+ (e) => {
24239
+ if (e.key === "Escape") {
24240
+ e.preventDefault();
24241
+ onClose();
24242
+ }
24243
+ },
24244
+ [onClose]
24245
+ );
24246
+ if (!isOpen) {
24247
+ return null;
24248
+ }
24249
+ return /* @__PURE__ */ jsx(
24250
+ "div",
24251
+ {
24252
+ className: "fixed inset-0 z-[9999] flex items-center justify-center bg-black/60 backdrop-blur-sm",
24253
+ onClick: (e) => {
24254
+ if (e.target === e.currentTarget) {
24255
+ onClose();
24256
+ }
24257
+ },
24258
+ onKeyDown: handleKeyDown,
24259
+ children: /* @__PURE__ */ jsxs(
24260
+ "div",
24261
+ {
24262
+ ref: dialogRef,
24263
+ className: "bg-background border border-border rounded-xl shadow-2xl w-[560px] max-h-[80vh] flex flex-col overflow-hidden",
24264
+ onClick: (e) => e.stopPropagation(),
24265
+ role: "dialog",
24266
+ "aria-modal": "true",
24267
+ tabIndex: -1,
24268
+ "aria-label": t(descriptor.titleKey),
24269
+ children: [
24270
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3 border-b border-border", children: [
24271
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-foreground", children: t(descriptor.titleKey) }),
24272
+ /* @__PURE__ */ jsx(
24273
+ "button",
24274
+ {
24275
+ type: "button",
24276
+ onClick: onClose,
24277
+ className: "p-1 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
24278
+ "aria-label": t("pptx.settings.close"),
24279
+ children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
24280
+ }
24281
+ )
24282
+ ] }),
24283
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-5 py-4 space-y-3 text-sm", children: [
24284
+ loading && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: t("pptx.ole.editDialog.loading") }),
24285
+ saveError && /* @__PURE__ */ jsx("p", { className: "text-destructive text-xs", children: t("pptx.ole.editDialog.saveError") }),
24286
+ !loading && descriptor.contentTab?.kind === "sheet" && /* @__PURE__ */ jsx(OleSheetGridEditor, { grid, onCellEdit: handleCellEdit, t }),
24287
+ !loading && descriptor.contentTab?.kind === "document" && /* @__PURE__ */ jsx(OleDocumentEditor, { paragraphs, onEdit: handleParagraphEdit, t }),
24288
+ !loading && descriptor.contentTab?.kind === "deck" && /* @__PURE__ */ jsx(OleDeckEditor, { slides: deckSlides, onEdit: handleDeckElementEdit, t }),
24289
+ !descriptor.contentTab && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: t("pptx.ole.editDialog.unsupported") })
24290
+ ] }),
24291
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-5 py-3 border-t border-border", children: [
24292
+ /* @__PURE__ */ jsx(
24293
+ "input",
24294
+ {
24295
+ ref: fileInputRef,
24296
+ type: "file",
24297
+ className: "hidden",
24298
+ onChange: (e) => {
24299
+ const file = e.target.files?.[0];
24300
+ if (file) {
24301
+ void handleReplaceFile(file);
24302
+ }
24303
+ }
24304
+ }
24305
+ ),
24306
+ /* @__PURE__ */ jsx(
24307
+ "button",
24308
+ {
24309
+ type: "button",
24310
+ onClick: () => fileInputRef.current?.click(),
24311
+ className: "px-3 py-1.5 rounded-lg text-xs text-foreground border border-border hover:bg-accent transition-colors",
24312
+ children: t("pptx.ole.editDialog.replaceFile")
24313
+ }
24314
+ ),
24315
+ /* @__PURE__ */ jsx(
24316
+ "button",
24317
+ {
24318
+ type: "button",
24319
+ onClick: onClose,
24320
+ className: "px-4 py-1.5 rounded-lg text-xs font-medium bg-primary hover:bg-primary/80 text-white transition-colors",
24321
+ children: t("pptx.ole.editDialog.save")
24322
+ }
24323
+ )
24324
+ ] })
24325
+ ]
24326
+ }
24327
+ )
24328
+ }
24329
+ );
24330
+ }
23240
24331
 
23241
24332
  // src/viewer/components/inspector/element-properties-constants.ts
23242
24333
  var SELECT_CLS2 = "bg-muted border border-border rounded px-2 py-1";
@@ -23286,7 +24377,7 @@ function ConnectorArrowsSection({
23286
24377
  ["Start", "End"].map((end) => {
23287
24378
  const widthKey = end === "Start" ? "connectorStartArrowWidth" : "connectorEndArrowWidth";
23288
24379
  const lengthKey = end === "Start" ? "connectorStartArrowLength" : "connectorEndArrowLength";
23289
- return /* @__PURE__ */ jsxs(React19.Fragment, { children: [
24380
+ return /* @__PURE__ */ jsxs(React20.Fragment, { children: [
23290
24381
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
23291
24382
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t(END_LABEL_KEYS[end].width) }),
23292
24383
  /* @__PURE__ */ jsx(
@@ -23368,6 +24459,7 @@ function OlePropertiesPanel({
23368
24459
  onUpdateElement
23369
24460
  }) {
23370
24461
  const { t } = useTranslation();
24462
+ const [isEditorOpen, setIsEditorOpen] = useState(false);
23371
24463
  if (selectedElement.type !== "ole") {
23372
24464
  return null;
23373
24465
  }
@@ -23375,6 +24467,15 @@ function OlePropertiesPanel({
23375
24467
  return /* @__PURE__ */ jsxs("div", { className: CARD, children: [
23376
24468
  /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.ole.title") }),
23377
24469
  /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 text-[11px]", children: [
24470
+ canEdit && !ole.isLinked && /* @__PURE__ */ jsx(
24471
+ "button",
24472
+ {
24473
+ type: "button",
24474
+ onClick: () => setIsEditorOpen(true),
24475
+ className: "w-full px-2 py-1.5 rounded border border-border text-foreground hover:bg-accent transition-colors text-[11px]",
24476
+ children: t("pptx.ole.editContent")
24477
+ }
24478
+ ),
23378
24479
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
23379
24480
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.ole.objectName") }),
23380
24481
  /* @__PURE__ */ jsx(
@@ -23410,7 +24511,16 @@ function OlePropertiesPanel({
23410
24511
  }
23411
24512
  )
23412
24513
  ] })
23413
- ] })
24514
+ ] }),
24515
+ /* @__PURE__ */ jsx(
24516
+ OleEditorDialog,
24517
+ {
24518
+ isOpen: isEditorOpen,
24519
+ onClose: () => setIsEditorOpen(false),
24520
+ element: ole,
24521
+ onUpdateElement
24522
+ }
24523
+ )
23414
24524
  ] });
23415
24525
  }
23416
24526
  function TransformPanel({
@@ -26144,7 +27254,7 @@ function StrokeEffectsSection({
26144
27254
  ] }),
26145
27255
  EFFECT_CONFIGS.map((cfg) => {
26146
27256
  const on = cfg.isOn(style);
26147
- return /* @__PURE__ */ jsxs(React19.Fragment, { children: [
27257
+ return /* @__PURE__ */ jsxs(React20.Fragment, { children: [
26148
27258
  /* @__PURE__ */ jsxs("label", { className: `inline-flex items-center gap-2 text-foreground ${COL2}`, children: [
26149
27259
  /* @__PURE__ */ jsx(
26150
27260
  "input",
@@ -27012,7 +28122,7 @@ function TextWarpGallery({
27012
28122
  onUpdateTextStyle
27013
28123
  }) {
27014
28124
  const { t } = useTranslation();
27015
- const [expanded, setExpanded] = React19.useState(false);
28125
+ const [expanded, setExpanded] = React20.useState(false);
27016
28126
  const currentPreset = ts?.textWarpPreset || "textNoShape";
27017
28127
  return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded border border-border bg-card p-2 space-y-2", children: [
27018
28128
  /* @__PURE__ */ jsxs(
@@ -27215,7 +28325,7 @@ function ShapeTextPanels({
27215
28325
  onUpdateTextStyle
27216
28326
  }
27217
28327
  ),
27218
- (selectedElement.type === "text" || selectedElement.type === "shape" || selectedElement.type === "connector") && /* @__PURE__ */ jsx(
28328
+ shouldShowAccessibilitySection(selectedElement) && /* @__PURE__ */ jsx(
27219
28329
  AccessibilityTextSection,
27220
28330
  {
27221
28331
  selectedElement,
@@ -27663,7 +28773,7 @@ function SmartArtStyleControls({
27663
28773
  onChangeStyle
27664
28774
  }) {
27665
28775
  const { t } = useTranslation();
27666
- const translate = React19.useCallback((key) => t(key), [t]);
28776
+ const translate = React20.useCallback((key) => t(key), [t]);
27667
28777
  return /* @__PURE__ */ jsxs(Fragment, { children: [
27668
28778
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
27669
28779
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.smartart.colorScheme") }),
@@ -27718,9 +28828,9 @@ function SmartArtPropertiesPanel({
27718
28828
  const nodes = smartArtData.nodes ?? [];
27719
28829
  const layout = smartArtData.resolvedLayoutType;
27720
28830
  const topLevelCount = nodes.filter((n) => !n.parentId).length;
27721
- const inputRefs = React19.useRef(/* @__PURE__ */ new Map());
27722
- const pendingFocusId = React19.useRef(null);
27723
- React19.useEffect(() => {
28831
+ const inputRefs = React20.useRef(/* @__PURE__ */ new Map());
28832
+ const pendingFocusId = React20.useRef(null);
28833
+ React20.useEffect(() => {
27724
28834
  const id = pendingFocusId.current;
27725
28835
  if (id) {
27726
28836
  inputRefs.current.get(id)?.focus();
@@ -29299,7 +30409,7 @@ function CommentBody({ text, mentions, className }) {
29299
30409
  index
29300
30410
  ) : (
29301
30411
  // eslint-disable-next-line react/no-array-index-key -- segments are positional
29302
- /* @__PURE__ */ jsx(React19.Fragment, { children: segment.text }, index)
30412
+ /* @__PURE__ */ jsx(React20.Fragment, { children: segment.text }, index)
29303
30413
  )
29304
30414
  ) });
29305
30415
  }
@@ -30428,9 +31538,17 @@ function TransitionPreview({
30428
31538
  durationMs,
30429
31539
  transition.direction,
30430
31540
  transition.orient,
30431
- transition.spokes
31541
+ transition.spokes,
31542
+ transition.pattern
30432
31543
  ),
30433
- [transition.type, transition.direction, transition.orient, transition.spokes, durationMs]
31544
+ [
31545
+ transition.type,
31546
+ transition.direction,
31547
+ transition.orient,
31548
+ transition.spokes,
31549
+ transition.pattern,
31550
+ durationMs
31551
+ ]
30434
31552
  );
30435
31553
  const handlePlay = useCallback(() => {
30436
31554
  setPlaying(true);
@@ -30760,7 +31878,7 @@ function PresentationPropertiesPanel({
30760
31878
  onUpdateTagCollections
30761
31879
  }) {
30762
31880
  const { t } = useTranslation();
30763
- const handleTransitionChange = React19.useCallback(
31881
+ const handleTransitionChange = React20.useCallback(
30764
31882
  (updates) => {
30765
31883
  onUpdateSlide({
30766
31884
  transition: mergeSlideTransition(activeSlide?.transition, updates)
@@ -31940,9 +33058,17 @@ function PresentationTransitionOverlay({
31940
33058
  durationMs,
31941
33059
  transition.direction,
31942
33060
  transition.orient,
31943
- transition.spokes
33061
+ transition.spokes,
33062
+ transition.pattern
31944
33063
  ),
31945
- [transition.type, transition.direction, transition.orient, transition.spokes, durationMs]
33064
+ [
33065
+ transition.type,
33066
+ transition.direction,
33067
+ transition.orient,
33068
+ transition.spokes,
33069
+ transition.pattern,
33070
+ durationMs
33071
+ ]
31946
33072
  );
31947
33073
  const scale = useMemo(() => {
31948
33074
  if (resolvedStageScale !== null) {
@@ -34802,7 +35928,7 @@ function ViewerToolbarSection(props) {
34802
35928
  },
34803
35929
  [activeSlide, propertyHandlers]
34804
35930
  );
34805
- const scopedLayoutOptions = React19.useMemo(
35931
+ const scopedLayoutOptions = React20.useMemo(
34806
35932
  () => scopeLayoutOptionsToActiveSlide(s.layoutOptions, activeSlide),
34807
35933
  [s.layoutOptions, activeSlide]
34808
35934
  );
@@ -35138,6 +36264,7 @@ function ViewerToolbarSection(props) {
35138
36264
  onSaveAsPptx: exportHandlers.handleSaveAsPptx,
35139
36265
  onSaveAsPpsx: exportHandlers.handleSaveAsPpsx,
35140
36266
  onSaveAsPptm: exportHandlers.handleSaveAsPptm,
36267
+ onSaveAsPpt: exportHandlers.handleSaveAsPpt,
35141
36268
  hasMacros: s.hasMacros,
35142
36269
  onCopySlideAsImage: exportHandlers.handleCopySlideAsImage,
35143
36270
  onPrint: printHandlers.handlePrint,
@@ -36005,7 +37132,10 @@ function PresentationStage({
36005
37132
  // the stage publishes its own size for those calc() offsets.
36006
37133
  "--pptx-slide-w": `${safeWidth}px`,
36007
37134
  "--pptx-slide-h": `${safeHeight}px`,
36008
- ...getReactSlideBackgroundStyle(activeSlide)
37135
+ ...getReactSlideBackgroundStyle(activeSlide, {
37136
+ widthPx: canvasSize.width,
37137
+ heightPx: canvasSize.height
37138
+ })
36009
37139
  },
36010
37140
  children: [
36011
37141
  /* @__PURE__ */ jsx(SlideBackgroundImageLayer, { slide: activeSlide }),
@@ -36654,7 +37784,7 @@ function useTableStyleMapHandlers(input) {
36654
37784
  var AiChatPanel = lazy(async () => {
36655
37785
  const [{ useChat }, { default: Panel }] = await Promise.all([
36656
37786
  import('@ai-sdk/react'),
36657
- import('./AiChatPanel-A5DCEHTO.mjs')
37787
+ import('./AiChatPanel-BQSUE2OO.mjs')
36658
37788
  ]);
36659
37789
  function BoundAiChatPanel(props) {
36660
37790
  return /* @__PURE__ */ jsx(Panel, { ...props, useChat });
@@ -38449,8 +39579,24 @@ function MobileChromeOverlay(props) {
38449
39579
  )
38450
39580
  ] });
38451
39581
  }
38452
- function ReadOnlyBanner({ recommendation, onEditAnyway, onDismiss }) {
39582
+ function ReadOnlyBanner({
39583
+ recommendation,
39584
+ onEditAnyway,
39585
+ onDismiss,
39586
+ passwordPromptOpen = false,
39587
+ passwordError = null,
39588
+ checkingPassword = false,
39589
+ onSubmitPassword,
39590
+ onCancelPassword
39591
+ }) {
38453
39592
  const { t } = useTranslation();
39593
+ const [password, setPassword] = useState("");
39594
+ const inputId = useId();
39595
+ const errorId = useId();
39596
+ const handleSubmit = (event) => {
39597
+ event.preventDefault();
39598
+ onSubmitPassword?.(password);
39599
+ };
38454
39600
  return /* @__PURE__ */ jsxs(
38455
39601
  "div",
38456
39602
  {
@@ -38459,27 +39605,87 @@ function ReadOnlyBanner({ recommendation, onEditAnyway, onDismiss }) {
38459
39605
  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",
38460
39606
  children: [
38461
39607
  /* @__PURE__ */ jsx("span", { className: "flex-1 min-w-0", children: t(recommendation.messageKey) }),
38462
- /* @__PURE__ */ jsx(
38463
- "button",
38464
- {
38465
- type: "button",
38466
- "data-testid": "pptx-readonly-edit-anyway",
38467
- onClick: onEditAnyway,
38468
- 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",
38469
- children: t("pptx.readOnly.editAnyway")
38470
- }
38471
- ),
38472
- /* @__PURE__ */ jsx(
38473
- "button",
39608
+ passwordPromptOpen ? /* @__PURE__ */ jsxs(
39609
+ "form",
38474
39610
  {
38475
- type: "button",
38476
- "data-testid": "pptx-readonly-dismiss",
38477
- onClick: onDismiss,
38478
- "aria-label": t("pptx.readOnly.dismiss"),
38479
- 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",
38480
- children: t("pptx.readOnly.dismiss")
39611
+ "data-testid": "pptx-readonly-password-form",
39612
+ onSubmit: handleSubmit,
39613
+ className: "flex shrink-0 items-center gap-2",
39614
+ children: [
39615
+ /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "sr-only", children: t("pptx.readOnly.passwordLabel") }),
39616
+ /* @__PURE__ */ jsx(
39617
+ "input",
39618
+ {
39619
+ id: inputId,
39620
+ "data-testid": "pptx-readonly-password-input",
39621
+ type: "password",
39622
+ autoFocus: true,
39623
+ value: password,
39624
+ disabled: checkingPassword,
39625
+ onChange: (event) => setPassword(event.target.value),
39626
+ placeholder: t("pptx.readOnly.passwordPlaceholder"),
39627
+ "aria-invalid": passwordError !== null,
39628
+ "aria-describedby": passwordError !== null ? errorId : void 0,
39629
+ className: "rounded-sm border border-amber-600/40 bg-white/80 px-1.5 py-0.5 text-[11px] text-amber-950 dark:bg-black/20 dark:text-amber-100"
39630
+ }
39631
+ ),
39632
+ /* @__PURE__ */ jsx(
39633
+ "button",
39634
+ {
39635
+ type: "submit",
39636
+ "data-testid": "pptx-readonly-unlock",
39637
+ disabled: checkingPassword,
39638
+ 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 disabled:opacity-60",
39639
+ children: t("pptx.readOnly.unlock")
39640
+ }
39641
+ ),
39642
+ /* @__PURE__ */ jsx(
39643
+ "button",
39644
+ {
39645
+ type: "button",
39646
+ "data-testid": "pptx-readonly-password-cancel",
39647
+ onClick: onCancelPassword,
39648
+ 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",
39649
+ children: t("pptx.common.cancel")
39650
+ }
39651
+ ),
39652
+ passwordError !== null && /* @__PURE__ */ jsx(
39653
+ "span",
39654
+ {
39655
+ id: errorId,
39656
+ role: "alert",
39657
+ "data-testid": "pptx-readonly-password-error",
39658
+ className: "shrink-0 text-[11px] text-red-700 dark:text-red-300",
39659
+ children: t(
39660
+ passwordError === "wrong-password" ? "pptx.readOnly.wrongPassword" : "pptx.readOnly.unsupportedAlgorithm"
39661
+ )
39662
+ }
39663
+ )
39664
+ ]
38481
39665
  }
38482
- )
39666
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
39667
+ /* @__PURE__ */ jsx(
39668
+ "button",
39669
+ {
39670
+ type: "button",
39671
+ "data-testid": "pptx-readonly-edit-anyway",
39672
+ onClick: onEditAnyway,
39673
+ 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",
39674
+ children: t("pptx.readOnly.editAnyway")
39675
+ }
39676
+ ),
39677
+ /* @__PURE__ */ jsx(
39678
+ "button",
39679
+ {
39680
+ type: "button",
39681
+ "data-testid": "pptx-readonly-dismiss",
39682
+ onClick: onDismiss,
39683
+ "aria-label": t("pptx.readOnly.dismiss"),
39684
+ 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",
39685
+ children: t("pptx.readOnly.dismiss")
39686
+ }
39687
+ )
39688
+ ] })
38483
39689
  ]
38484
39690
  }
38485
39691
  );
@@ -40274,6 +41480,7 @@ var PowerPointViewer = forwardRef(
40274
41480
  // http(s) image sources actually load.
40275
41481
  allowExternalImages: viewerOptions.trust.allowExternalContent,
40276
41482
  setReadOnlyRecommendation: readOnlyRec.setRecommendation,
41483
+ setModifyVerifier: readOnlyRec.setModifyVerifier,
40277
41484
  setCompatToasts: compatToastsState.setToasts,
40278
41485
  canEdit,
40279
41486
  promptKeepInkAnnotations: viewerOptions.advanced.slideShowPromptKeepInkAnnotations,
@@ -40503,7 +41710,12 @@ var PowerPointViewer = forwardRef(
40503
41710
  {
40504
41711
  recommendation: readOnlyRec.recommendation,
40505
41712
  onEditAnyway: readOnlyRec.editAnyway,
40506
- onDismiss: readOnlyRec.dismiss
41713
+ onDismiss: readOnlyRec.dismiss,
41714
+ passwordPromptOpen: readOnlyRec.passwordPromptOpen,
41715
+ passwordError: readOnlyRec.passwordError,
41716
+ checkingPassword: readOnlyRec.checkingPassword,
41717
+ onSubmitPassword: readOnlyRec.submitPassword,
41718
+ onCancelPassword: readOnlyRec.cancelPasswordPrompt
40507
41719
  }
40508
41720
  ),
40509
41721
  /* @__PURE__ */ jsx(