pptx-react-viewer 3.7.0 → 3.9.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 (183) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/{AiChatPanel-M3AHKYPS.js → AiChatPanel-3A42W7RW.js} +25 -25
  3. package/dist/AiChatPanel-3A42W7RW.js.br +0 -0
  4. package/dist/AiChatPanel-3A42W7RW.js.gz +0 -0
  5. package/dist/{AiChatPanel-L5QGWVZK.mjs → AiChatPanel-II6VOOAL.mjs} +4 -4
  6. package/dist/AiChatPanel-II6VOOAL.mjs.br +0 -0
  7. package/dist/AiChatPanel-II6VOOAL.mjs.gz +0 -0
  8. package/dist/{Area3DChartScene-AE2XYKDW.mjs → Area3DChartScene-JM3CQ3WQ.mjs} +21 -4
  9. package/dist/Area3DChartScene-JM3CQ3WQ.mjs.br +0 -0
  10. package/dist/Area3DChartScene-JM3CQ3WQ.mjs.gz +0 -0
  11. package/dist/{Area3DChartScene-ZQLQK6L4.js → Area3DChartScene-XJK4ZA4R.js} +21 -4
  12. package/dist/Area3DChartScene-XJK4ZA4R.js.br +0 -0
  13. package/dist/Area3DChartScene-XJK4ZA4R.js.gz +0 -0
  14. package/dist/{Bar3DChartScene-TZ6ADFBS.js → Bar3DChartScene-RGRZY5P6.js} +21 -4
  15. package/dist/Bar3DChartScene-RGRZY5P6.js.br +0 -0
  16. package/dist/Bar3DChartScene-RGRZY5P6.js.gz +0 -0
  17. package/dist/{Bar3DChartScene-FQV62XOI.mjs → Bar3DChartScene-VNFWI2QG.mjs} +21 -4
  18. package/dist/Bar3DChartScene-VNFWI2QG.mjs.br +0 -0
  19. package/dist/Bar3DChartScene-VNFWI2QG.mjs.gz +0 -0
  20. package/dist/{Line3DChartScene-FEUY3PCE.mjs → Line3DChartScene-GXOWGIFJ.mjs} +21 -4
  21. package/dist/Line3DChartScene-GXOWGIFJ.mjs.br +0 -0
  22. package/dist/Line3DChartScene-GXOWGIFJ.mjs.gz +0 -0
  23. package/dist/{Line3DChartScene-5CKPAX63.js → Line3DChartScene-MEY42DBF.js} +21 -4
  24. package/dist/Line3DChartScene-MEY42DBF.js.br +0 -0
  25. package/dist/Line3DChartScene-MEY42DBF.js.gz +0 -0
  26. package/dist/{Model3DScene-BLXEALM6.js → Model3DScene-MWXTGHDM.js} +2 -2
  27. package/dist/Model3DScene-MWXTGHDM.js.br +0 -0
  28. package/dist/Model3DScene-MWXTGHDM.js.gz +0 -0
  29. package/dist/{Model3DScene-V3DHIISV.mjs → Model3DScene-WJ3MMIZH.mjs} +1 -1
  30. package/dist/Model3DScene-WJ3MMIZH.mjs.br +0 -0
  31. package/dist/Model3DScene-WJ3MMIZH.mjs.gz +0 -0
  32. package/dist/{PieChart3DScene-GHHT3PDV.js → PieChart3DScene-FJJGOQIS.js} +15 -4
  33. package/dist/PieChart3DScene-FJJGOQIS.js.br +0 -0
  34. package/dist/PieChart3DScene-FJJGOQIS.js.gz +0 -0
  35. package/dist/{PieChart3DScene-VZI2VARG.mjs → PieChart3DScene-WXJEDYMK.mjs} +15 -4
  36. package/dist/PieChart3DScene-WXJEDYMK.mjs.br +0 -0
  37. package/dist/PieChart3DScene-WXJEDYMK.mjs.gz +0 -0
  38. package/dist/PowerPointViewer-Cl6jBPNw.d.ts.map +1 -1
  39. package/dist/{SmartArt3DScene-ZO3KFDI2.js → SmartArt3DScene-BK7QN3WT.js} +85 -23
  40. package/dist/SmartArt3DScene-BK7QN3WT.js.br +0 -0
  41. package/dist/SmartArt3DScene-BK7QN3WT.js.gz +0 -0
  42. package/dist/{SmartArt3DScene-XCFVGCXE.mjs → SmartArt3DScene-ODKCGJBO.mjs} +85 -23
  43. package/dist/SmartArt3DScene-ODKCGJBO.mjs.br +0 -0
  44. package/dist/SmartArt3DScene-ODKCGJBO.mjs.gz +0 -0
  45. package/dist/{SurfaceChart3DScene-T36E2HBA.mjs → SurfaceChart3DScene-IKPE2SVE.mjs} +19 -4
  46. package/dist/SurfaceChart3DScene-IKPE2SVE.mjs.br +0 -0
  47. package/dist/SurfaceChart3DScene-IKPE2SVE.mjs.gz +0 -0
  48. package/dist/{SurfaceChart3DScene-WWIMQ65D.js → SurfaceChart3DScene-VDK3F224.js} +19 -4
  49. package/dist/SurfaceChart3DScene-VDK3F224.js.br +0 -0
  50. package/dist/SurfaceChart3DScene-VDK3F224.js.gz +0 -0
  51. package/dist/{audience-content-store-bR7Gs_1S.d.ts → audience-content-store-CB2WVM1K.d.ts} +12 -3
  52. package/dist/{audience-content-store-bR7Gs_1S.d.ts.map → audience-content-store-CB2WVM1K.d.ts.map} +1 -1
  53. package/dist/{chunk-TUSALM3A.js → chunk-3NIJ5HIZ.js} +3650 -2503
  54. package/dist/chunk-3NIJ5HIZ.js.br +0 -0
  55. package/dist/chunk-3NIJ5HIZ.js.gz +0 -0
  56. package/dist/{chunk-WKODF5ZU.mjs → chunk-3Y63XPIN.mjs} +5 -2
  57. package/dist/chunk-3Y63XPIN.mjs.br +0 -0
  58. package/dist/chunk-3Y63XPIN.mjs.gz +0 -0
  59. package/dist/{chunk-OBE4TB76.js → chunk-5CPGDXD6.js} +632 -579
  60. package/dist/chunk-5CPGDXD6.js.br +0 -0
  61. package/dist/chunk-5CPGDXD6.js.gz +0 -0
  62. package/dist/{chunk-TXY2E7VQ.mjs → chunk-76Z3X6JX.mjs} +1684 -537
  63. package/dist/chunk-76Z3X6JX.mjs.br +0 -0
  64. package/dist/chunk-76Z3X6JX.mjs.gz +0 -0
  65. package/dist/chunk-DNR6CH6I.js +30 -0
  66. package/dist/chunk-DNR6CH6I.js.br +0 -0
  67. package/dist/chunk-DNR6CH6I.js.gz +0 -0
  68. package/dist/{chunk-DCNHUEWQ.js → chunk-G3JPCRKN.js} +18490 -10327
  69. package/dist/chunk-G3JPCRKN.js.br +0 -0
  70. package/dist/chunk-G3JPCRKN.js.gz +0 -0
  71. package/dist/{chunk-FGTMS7LR.mjs → chunk-JBSAKP4Z.mjs} +70 -4
  72. package/dist/chunk-JBSAKP4Z.mjs.br +0 -0
  73. package/dist/chunk-JBSAKP4Z.mjs.gz +0 -0
  74. package/dist/{chunk-3EJFZ7TE.js → chunk-K6Q6KLA6.js} +9 -5
  75. package/dist/chunk-K6Q6KLA6.js.br +0 -0
  76. package/dist/chunk-K6Q6KLA6.js.gz +0 -0
  77. package/dist/{chunk-VIFDZIVX.js → chunk-LBJAVP3H.js} +206 -179
  78. package/dist/chunk-LBJAVP3H.js.br +0 -0
  79. package/dist/chunk-LBJAVP3H.js.gz +0 -0
  80. package/dist/{chunk-JANUSAEK.mjs → chunk-NTWFXLZX.mjs} +35 -8
  81. package/dist/chunk-NTWFXLZX.mjs.br +0 -0
  82. package/dist/chunk-NTWFXLZX.mjs.gz +0 -0
  83. package/dist/{chunk-PC62KGU3.mjs → chunk-PCCM7NVY.mjs} +206 -153
  84. package/dist/chunk-PCCM7NVY.mjs.br +0 -0
  85. package/dist/chunk-PCCM7NVY.mjs.gz +0 -0
  86. package/dist/chunk-T6GFCLSM.mjs +27 -0
  87. package/dist/chunk-T6GFCLSM.mjs.br +4 -0
  88. package/dist/chunk-T6GFCLSM.mjs.gz +0 -0
  89. package/dist/{chunk-W24OJ7H5.js → chunk-TEVGDXVW.js} +70 -4
  90. package/dist/chunk-TEVGDXVW.js.br +0 -0
  91. package/dist/chunk-TEVGDXVW.js.gz +0 -0
  92. package/dist/{chunk-NV55GU5V.mjs → chunk-VQX7G75Z.mjs} +18447 -10316
  93. package/dist/chunk-VQX7G75Z.mjs.br +0 -0
  94. package/dist/chunk-VQX7G75Z.mjs.gz +0 -0
  95. package/dist/i18n.js +4 -4
  96. package/dist/i18n.js.br +0 -0
  97. package/dist/i18n.js.gz +0 -0
  98. package/dist/i18n.mjs +1 -1
  99. package/dist/i18n.mjs.br +0 -0
  100. package/dist/i18n.mjs.gz +0 -0
  101. package/dist/index.d.ts +545 -81
  102. package/dist/index.js +47 -47
  103. package/dist/index.js.br +0 -0
  104. package/dist/index.js.gz +0 -0
  105. package/dist/index.mjs +6 -6
  106. package/dist/index.mjs.br +0 -0
  107. package/dist/index.mjs.gz +0 -0
  108. package/dist/internals.d.ts +774 -229
  109. package/dist/internals.d.ts.map +1 -1
  110. package/dist/internals.js +79 -79
  111. package/dist/internals.js.br +0 -0
  112. package/dist/internals.js.gz +0 -0
  113. package/dist/internals.mjs +4 -4
  114. package/dist/internals.mjs.br +0 -0
  115. package/dist/internals.mjs.gz +0 -0
  116. package/dist/pptx-viewer.css +1 -1
  117. package/dist/pptx-viewer.css.br +0 -0
  118. package/dist/pptx-viewer.css.gz +0 -0
  119. package/dist/types-Bzdkiakq.d.ts.map +1 -1
  120. package/dist/viewer/index.d.ts +488 -66
  121. package/dist/viewer/index.js +27 -27
  122. package/dist/viewer/index.js.br +0 -0
  123. package/dist/viewer/index.js.gz +0 -0
  124. package/dist/viewer/index.mjs +6 -6
  125. package/dist/viewer/index.mjs.br +0 -0
  126. package/dist/viewer/index.mjs.gz +0 -0
  127. package/package.json +2 -2
  128. package/dist/AiChatPanel-L5QGWVZK.mjs.br +0 -0
  129. package/dist/AiChatPanel-L5QGWVZK.mjs.gz +0 -0
  130. package/dist/AiChatPanel-M3AHKYPS.js.br +0 -0
  131. package/dist/AiChatPanel-M3AHKYPS.js.gz +0 -0
  132. package/dist/Area3DChartScene-AE2XYKDW.mjs.br +0 -1
  133. package/dist/Area3DChartScene-AE2XYKDW.mjs.gz +0 -0
  134. package/dist/Area3DChartScene-ZQLQK6L4.js.br +0 -0
  135. package/dist/Area3DChartScene-ZQLQK6L4.js.gz +0 -0
  136. package/dist/Bar3DChartScene-FQV62XOI.mjs.br +0 -2
  137. package/dist/Bar3DChartScene-FQV62XOI.mjs.gz +0 -0
  138. package/dist/Bar3DChartScene-TZ6ADFBS.js.br +0 -0
  139. package/dist/Bar3DChartScene-TZ6ADFBS.js.gz +0 -0
  140. package/dist/Line3DChartScene-5CKPAX63.js.br +0 -0
  141. package/dist/Line3DChartScene-5CKPAX63.js.gz +0 -0
  142. package/dist/Line3DChartScene-FEUY3PCE.mjs.br +0 -1
  143. package/dist/Line3DChartScene-FEUY3PCE.mjs.gz +0 -0
  144. package/dist/Model3DScene-BLXEALM6.js.br +0 -0
  145. package/dist/Model3DScene-BLXEALM6.js.gz +0 -0
  146. package/dist/Model3DScene-V3DHIISV.mjs.br +0 -0
  147. package/dist/Model3DScene-V3DHIISV.mjs.gz +0 -0
  148. package/dist/PieChart3DScene-GHHT3PDV.js.br +0 -0
  149. package/dist/PieChart3DScene-GHHT3PDV.js.gz +0 -0
  150. package/dist/PieChart3DScene-VZI2VARG.mjs.br +0 -0
  151. package/dist/PieChart3DScene-VZI2VARG.mjs.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-T36E2HBA.mjs.br +0 -0
  157. package/dist/SurfaceChart3DScene-T36E2HBA.mjs.gz +0 -0
  158. package/dist/SurfaceChart3DScene-WWIMQ65D.js.br +0 -0
  159. package/dist/SurfaceChart3DScene-WWIMQ65D.js.gz +0 -0
  160. package/dist/chunk-3EJFZ7TE.js.br +0 -0
  161. package/dist/chunk-3EJFZ7TE.js.gz +0 -0
  162. package/dist/chunk-DCNHUEWQ.js.br +0 -0
  163. package/dist/chunk-DCNHUEWQ.js.gz +0 -0
  164. package/dist/chunk-FGTMS7LR.mjs.br +0 -0
  165. package/dist/chunk-FGTMS7LR.mjs.gz +0 -0
  166. package/dist/chunk-JANUSAEK.mjs.br +0 -0
  167. package/dist/chunk-JANUSAEK.mjs.gz +0 -0
  168. package/dist/chunk-NV55GU5V.mjs.br +0 -0
  169. package/dist/chunk-NV55GU5V.mjs.gz +0 -0
  170. package/dist/chunk-OBE4TB76.js.br +0 -0
  171. package/dist/chunk-OBE4TB76.js.gz +0 -0
  172. package/dist/chunk-PC62KGU3.mjs.br +0 -0
  173. package/dist/chunk-PC62KGU3.mjs.gz +0 -0
  174. package/dist/chunk-TUSALM3A.js.br +0 -0
  175. package/dist/chunk-TUSALM3A.js.gz +0 -0
  176. package/dist/chunk-TXY2E7VQ.mjs.br +0 -0
  177. package/dist/chunk-TXY2E7VQ.mjs.gz +0 -0
  178. package/dist/chunk-VIFDZIVX.js.br +0 -0
  179. package/dist/chunk-VIFDZIVX.js.gz +0 -0
  180. package/dist/chunk-W24OJ7H5.js.br +0 -0
  181. package/dist/chunk-W24OJ7H5.js.gz +0 -0
  182. package/dist/chunk-WKODF5ZU.mjs.br +0 -0
  183. package/dist/chunk-WKODF5ZU.mjs.gz +0 -0
@@ -1,9 +1,9 @@
1
- import { computeFocusTargets, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs, applyElementUpdate } from './chunk-WKODF5ZU.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-PC62KGU3.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-JANUSAEK.mjs';
4
- import { hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, connectorWrapperTransform, getAriaRoleDescription, getAriaLabel, getAriaRole, resolveElementInteractivity, isEditableTextElement, 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, 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, advanceChartValueDrag, 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, themeColorLabel, buildThemeColorGrid, THEME_COLOR_SCHEME_KEYS, COMMON_FONTS, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, isCurrentLayout, SLIDE_TEMPLATES, computeAnchoredPopupPosition, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, isElementLocked, mergeSlideTransition, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, buildLayoutPreviewGeometry, buildSlideTemplateContent, elementLockTogglePatch, buildTableDataGrid, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, applyTableStylePreset, evenColumnWidths, redistributeColumnWidth, evenRowHeights, patchChartData, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, canInteractWithElement, buildOleObjectNamePatch, getOleObjectTypeLabel, sanitizeGradientStops, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, resolveSlideSizeSelection, SLIDE_SIZE_PRESETS, TRANSITION_VALID_DIRECTIONS, TRANSITION_ORIENTATION_TYPES, clampTransitionNumber, TRANSITION_SPEED_OPTIONS, TRANSITION_MORPH_OPTIONS, flattenTagCollections, resolveTemplateBackgroundRows, formatCommentTimestamp, commentMentionQuery, matchCommentMentionAuthors, buildAnimationTimelineRows, clearMotionPath, getEffectSoundState, setEffectSound, setAfterAnimation, setAfterAnimationColor, DIRECTIONAL_PRESETS, buildAnimationTimelineBars, motionPathPresetIdForPath, computeMergeCellRight, computeMergeCellDown, computeSplitCell, CHART_TYPE_OPTIONS, BAR3D_SHAPE_OPTIONS, bar3DShapePatch, RADAR_STYLE_OPTIONS, radarStylePatch, SURFACE_WIREFRAME_OPTIONS, surfaceWireframePatch, isSeriesUsingSecondaryAxis, 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, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, elementActionToPptxAction, canCommitActionType, slideSizeFromPreset, withSlideSizeOrientation, TRANSITION_DIR_ARROWS, buildDirectionGrid, updateTagInCollections, deleteTagFromCollections, addTagToCollections, commentTextSegments, COMMENT_MENTION_CLASS, COMMENT_MENTION_ATTRIBUTE, insertCommentMention, reorderAnimationTimelineRows, applyAnimationTimelineOrder, animationEffectLabel, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, switchSmartArtLayout, 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, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS } from './chunk-NV55GU5V.mjs';
5
- import { LOCALE_CATALOG, translationsEn } from './chunk-FGTMS7LR.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-3Y63XPIN.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-PCCM7NVY.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-NTWFXLZX.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, 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, 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, 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, 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, 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, setAfterAnimation, setAfterAnimationColor, DIRECTIONAL_PRESETS, buildAnimationTimelineBars, motionPathPresetIdForPath, 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, 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-VQX7G75Z.mjs';
5
+ import { LOCALE_CATALOG, translationsEn } from './chunk-JBSAKP4Z.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-AE2XYKDW.mjs');
517
+ return await import('./Area3DChartScene-JM3CQ3WQ.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-FQV62XOI.mjs');
586
+ return await import('./Bar3DChartScene-VNFWI2QG.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-FEUY3PCE.mjs');
689
+ return await import('./Line3DChartScene-GXOWGIFJ.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-VZI2VARG.mjs');
758
+ return await import('./PieChart3DScene-WXJEDYMK.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-T36E2HBA.mjs');
825
+ return await import('./SurfaceChart3DScene-IKPE2SVE.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,55 +874,42 @@ 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
- const { selection, setSelection } = useChartPartSelection();
896
+ const markDragRef = useRef(null);
801
897
  const [previewData, setPreviewData] = useState(null);
802
898
  const [dragValue, setDragValue] = useState(null);
803
- const [titleDraft, setTitleDraft] = useState(null);
804
- const selectedPart = selection?.elementId === element.id ? selection.part : null;
805
- const canEdit = editable && Boolean(onUpdateElement);
806
- const use3D = useContext(SurfaceChart3DContext);
807
- const isSurfaceKind = resolveChartKind(element.chartData?.chartType ?? "bar") === "surface";
808
- const use3DBar = useContext(BarChart3DContext);
809
- const isBar3DKind = element.chartData?.chartType === "bar3D";
810
- const use3DLine = useContext(LineChart3DContext);
811
- const isLine3DKind = element.chartData?.chartType === "line3D";
812
- const use3DArea = useContext(AreaChart3DContext);
813
- const isArea3DKind = element.chartData?.chartType === "area3D";
814
- const use3DPie = useContext(PieChart3DContext);
815
- const isPie3DKind = element.chartData?.chartType === "pie3D";
816
- const viewModel = useMemo(
817
- () => canEdit ? buildReactChartViewModel(element) : null,
818
- [canEdit, element]
819
- );
820
- useEffect(ensureChartInteractionStyles, []);
821
- useEffect(() => {
822
- if (!onUpdateElement) {
823
- return;
824
- }
825
- if (!canEdit && selection?.elementId === element.id) {
826
- setSelection(null);
827
- }
828
- }, [canEdit, selection, element.id, setSelection, onUpdateElement]);
829
- useEffect(() => {
830
- applyChartPartHighlight(wrapperRef.current, selectedPart);
831
- });
832
899
  const endDrag = (commit) => {
833
900
  const active = dragRef.current;
901
+ const markActive = markDragRef.current;
834
902
  dragRef.current = null;
903
+ markDragRef.current = null;
835
904
  setPreviewData(null);
836
905
  setDragValue(null);
837
- if (commit && active?.moved && active.lastData && onUpdateElement) {
906
+ if (!commit || !onUpdateElement) {
907
+ return;
908
+ }
909
+ if (active?.moved && active.lastData) {
838
910
  onUpdateElement({ chartData: active.lastData });
911
+ } else if (markActive?.moved && markActive.lastData) {
912
+ onUpdateElement({ chartData: markActive.lastData });
839
913
  }
840
914
  };
841
915
  useEffect(() => {
@@ -863,13 +937,44 @@ function ChartElementView({
863
937
  if (!viewModel || !element.chartData) {
864
938
  return;
865
939
  }
866
- const started = beginChartValueDrag({
867
- part,
868
- viewModel,
869
- chartData: element.chartData,
870
- clientY: e.clientY
871
- });
872
- if (!started) {
940
+ let captured = false;
941
+ const chartKind = resolveChartKind(element.chartData.chartType ?? "bar");
942
+ if (part.pointIndex !== void 0 && chartKind !== "unsupported") {
943
+ const markGeometry = buildChartMarkDragGeometry({
944
+ kind: chartKind,
945
+ element,
946
+ chartData: element.chartData,
947
+ categoryLabels: element.chartData.categories,
948
+ seriesIndex: part.seriesIndex,
949
+ pointIndex: part.pointIndex
950
+ });
951
+ const startedMark = beginChartMarkDrag({
952
+ part,
953
+ geometry: markGeometry,
954
+ chartData: element.chartData,
955
+ svgWidth: viewModel.svgWidth,
956
+ svgHeight: viewModel.svgHeight,
957
+ clientX: e.clientX,
958
+ clientY: e.clientY
959
+ });
960
+ if (startedMark) {
961
+ markDragRef.current = startedMark;
962
+ captured = true;
963
+ }
964
+ }
965
+ if (!captured) {
966
+ const started = beginChartValueDrag({
967
+ part,
968
+ viewModel,
969
+ chartData: element.chartData,
970
+ clientY: e.clientY
971
+ });
972
+ if (started) {
973
+ dragRef.current = started;
974
+ captured = true;
975
+ }
976
+ }
977
+ if (!captured) {
873
978
  return;
874
979
  }
875
980
  e.preventDefault();
@@ -877,9 +982,22 @@ function ChartElementView({
877
982
  e.currentTarget.setPointerCapture?.(e.pointerId);
878
983
  } catch {
879
984
  }
880
- dragRef.current = started;
881
985
  };
882
986
  const handlePointerMove = (e) => {
987
+ const markActive = markDragRef.current;
988
+ if (markActive) {
989
+ const rect = wrapperRef.current?.querySelector("svg")?.getBoundingClientRect();
990
+ if (!rect) {
991
+ return;
992
+ }
993
+ const step2 = advanceChartMarkDrag(markActive, e.clientX, e.clientY, rect);
994
+ if (!step2) {
995
+ return;
996
+ }
997
+ setPreviewData(step2.chartData);
998
+ setDragValue(step2.value);
999
+ return;
1000
+ }
883
1001
  const active = dragRef.current;
884
1002
  if (!active) {
885
1003
  return;
@@ -893,10 +1011,83 @@ function ChartElementView({
893
1011
  setDragValue(step.value);
894
1012
  };
895
1013
  const handlePointerUp = () => {
896
- if (dragRef.current) {
1014
+ if (dragRef.current || markDragRef.current) {
897
1015
  endDrag(true);
898
1016
  }
899
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
+ });
900
1091
  const handleDoubleClick = (e) => {
901
1092
  if (!canEdit || !canDrillDown(element)) {
902
1093
  return;
@@ -935,7 +1126,46 @@ function ChartElementView({
935
1126
  onPointerUp: handlePointerUp,
936
1127
  onDoubleClick: handleDoubleClick,
937
1128
  children: [
938
- 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),
939
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) }),
940
1170
  titleDraft !== null && /* @__PURE__ */ jsx(
941
1171
  "input",
@@ -1488,7 +1718,7 @@ function ResizeHandles({
1488
1718
  ))
1489
1719
  ] });
1490
1720
  }
1491
- var ConnectorElementRenderer = React19.memo(
1721
+ var ConnectorElementRenderer = React20.memo(
1492
1722
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
1493
1723
  function ConnectorElementRendererInner({
1494
1724
  el,
@@ -1502,7 +1732,8 @@ var ConnectorElementRenderer = React19.memo(
1502
1732
  adjustmentHandles: adjH,
1503
1733
  onResizePointerDown,
1504
1734
  onAdjustmentPointerDown,
1505
- animationState
1735
+ animationState,
1736
+ textStyleOverrideCss
1506
1737
  }) {
1507
1738
  const shapeEl = hasShapeProperties(el) ? el : void 0;
1508
1739
  const boxWidth = Math.max(el.width, MIN_ELEMENT_SIZE);
@@ -1570,6 +1801,7 @@ var ConnectorElementRenderer = React19.memo(
1570
1801
  ...lineGlow ? { filter: lineGlow } : {}
1571
1802
  },
1572
1803
  children: [
1804
+ textStyleOverrideCss && /* @__PURE__ */ jsx("style", { children: textStyleOverrideCss }),
1573
1805
  /* @__PURE__ */ jsxs(
1574
1806
  "svg",
1575
1807
  {
@@ -1867,7 +2099,7 @@ function shapeParams(element) {
1867
2099
  const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
1868
2100
  return { hf: hasFill, fc: fillColor, sw: strokeWidth, sc: strokeColor };
1869
2101
  }
1870
- var Extrusion3DOverlay = React19.memo(
2102
+ var Extrusion3DOverlay = React20.memo(
1871
2103
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
1872
2104
  function Extrusion3DOverlayInner({ data }) {
1873
2105
  if (!data.hasExtrusion || data.panels.length === 0) {
@@ -1952,23 +2184,19 @@ function renderOutlinePaint(paint) {
1952
2184
  function ShapeEffectOverlay({
1953
2185
  element,
1954
2186
  animatesFill = false,
1955
- animatesStroke = false
2187
+ animatesStroke = false,
2188
+ suppressReflection = false
1956
2189
  }) {
1957
- if (!hasShapeProperties(element)) {
1958
- return null;
1959
- }
1960
2190
  const fx = getComputedEffectStyle(element);
1961
2191
  const overlay = fx.fillOverlay;
1962
- const reflection = fx.reflection;
1963
- const softEdge = getSoftEdgeSvgFilter(element.shapeStyle, element.id);
2192
+ const reflection = suppressReflection ? void 0 : fx.reflection;
2193
+ const softEdge = getSoftEdgeSvgFilter(getEffectStyleSource(element), element.id);
1964
2194
  const strokeOutline = buildStrokeOutline(element);
1965
2195
  const hollowHit = buildHollowHitOutline(element);
1966
2196
  const subpathFill = buildSubpathFillOverlay(element);
1967
2197
  if (!overlay && !softEdge && !strokeOutline && !hollowHit && !subpathFill && !reflection) {
1968
2198
  return null;
1969
2199
  }
1970
- const reflectionFill = reflection && !isImageLikeElement(element) ? getComputedFillStyle(element) : void 0;
1971
- const reflectionImgSrc = reflection && isImageLikeElement(element) ? imgSrc(element) : void 0;
1972
2200
  const fillOverlayStyle = overlay ? {
1973
2201
  position: "absolute",
1974
2202
  inset: 0,
@@ -2084,44 +2312,12 @@ function ShapeEffectOverlay({
2084
2312
  className: "pptx-react-reflection",
2085
2313
  "aria-hidden": "true",
2086
2314
  style: reflection,
2087
- children: reflectionImgSrc ? /* @__PURE__ */ jsx(
2088
- "div",
2089
- {
2090
- className: "pptx-react-reflection-picture-surface",
2091
- style: getImageSurfaceStyle(element),
2092
- children: /* @__PURE__ */ jsx(
2093
- "img",
2094
- {
2095
- src: reflectionImgSrc,
2096
- alt: "",
2097
- draggable: false,
2098
- style: {
2099
- width: "100%",
2100
- height: "100%",
2101
- ...getImageRenderStyle(element)
2102
- }
2103
- }
2104
- )
2105
- }
2106
- ) : reflectionFill ? /* @__PURE__ */ jsx(
2107
- "div",
2108
- {
2109
- style: {
2110
- width: "100%",
2111
- height: "100%",
2112
- backgroundColor: reflectionFill.backgroundColor,
2113
- backgroundImage: reflectionFill.backgroundImage,
2114
- backgroundSize: reflectionFill.backgroundSize,
2115
- backgroundPosition: reflectionFill.backgroundPosition,
2116
- backgroundRepeat: reflectionFill.backgroundRepeat
2117
- }
2118
- }
2119
- ) : null
2315
+ children: /* @__PURE__ */ jsx(StaticElementRenderer, { element, positioned: false, suppressReflection: true })
2120
2316
  }
2121
2317
  ) : null
2122
2318
  ] });
2123
2319
  }
2124
- var ElementRenderer = React19.memo(
2320
+ var ElementRenderer = React20.memo(
2125
2321
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
2126
2322
  function ElementRendererInner({
2127
2323
  element: el,
@@ -2186,6 +2382,7 @@ var ElementRenderer = React19.memo(
2186
2382
  const visualAnimationState = backgroundAnimationState ?? animationState;
2187
2383
  const isTxt = isEditableTextElement(el) && allow.textEditable;
2188
2384
  const txtSE = hasTextProperties(el) ? el.textStyle : void 0;
2385
+ const textStyleOverrideCss = buildTextStyleOverrideCss(el.id, visualAnimationState?.textStyle);
2189
2386
  const ss = getShapeVisualStyle(
2190
2387
  el,
2191
2388
  hf,
@@ -2236,7 +2433,8 @@ var ElementRenderer = React19.memo(
2236
2433
  adjustmentHandles: adjH,
2237
2434
  onResizePointerDown,
2238
2435
  onAdjustmentPointerDown,
2239
- animationState
2436
+ animationState,
2437
+ textStyleOverrideCss
2240
2438
  }
2241
2439
  );
2242
2440
  }
@@ -2319,6 +2517,7 @@ var ElementRenderer = React19.memo(
2319
2517
  ...interactionProps,
2320
2518
  children: [
2321
2519
  renderDagDuotoneFilterForElement(el),
2520
+ textStyleOverrideCss && /* @__PURE__ */ jsx("style", { children: textStyleOverrideCss }),
2322
2521
  backgroundAnimationState ? /* @__PURE__ */ jsxs(
2323
2522
  "div",
2324
2523
  {
@@ -2425,22 +2624,10 @@ var ElementRenderer = React19.memo(
2425
2624
  );
2426
2625
  }
2427
2626
  );
2428
- function renderPressureStroke(pathD, widths, baseWidth, color, opacity, keyPrefix) {
2429
- const points = extractPathPoints(pathD);
2430
- const circles = generatePressureCircles(points, widths, {
2431
- baseWidth,
2432
- minRadius: 0.5,
2433
- maxRadius: baseWidth * 1.5
2434
- });
2627
+ function renderPressureStroke(circles, color, opacity, keyPrefix) {
2435
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}`)) });
2436
2629
  }
2437
- function renderNibMarkStroke(pathD, widths, tiltAngles, tiltMagnitudes, baseWidth, color, opacity, keyPrefix) {
2438
- const points = extractPathPoints(pathD);
2439
- const marks = generateNibMarks(points, widths, tiltAngles, tiltMagnitudes, {
2440
- baseWidth,
2441
- minRadius: 0.5,
2442
- maxRadius: baseWidth * 1.5
2443
- });
2630
+ function renderNibMarkStroke(marks, color, opacity, keyPrefix) {
2444
2631
  return /* @__PURE__ */ jsx("g", { opacity, children: marks.map((m, j) => /* @__PURE__ */ jsx(
2445
2632
  "ellipse",
2446
2633
  {
@@ -2454,10 +2641,41 @@ function renderNibMarkStroke(pathD, widths, tiltAngles, tiltMagnitudes, baseWidt
2454
2641
  `${keyPrefix}-nib-${j}`
2455
2642
  )) });
2456
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
+ }
2457
2674
  function renderInk(el, options) {
2458
2675
  const replay = options?.replay ?? false;
2459
- Boolean(el.inkPointPressures) && el.inkPointPressures.length > 0;
2460
- 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;
2461
2679
  const replayStyles = replay ? getInkReplayStyles(el, options?.replayConfig) : null;
2462
2680
  return /* @__PURE__ */ jsxs(
2463
2681
  "svg",
@@ -2467,44 +2685,9 @@ function renderInk(el, options) {
2467
2685
  preserveAspectRatio: "none",
2468
2686
  children: [
2469
2687
  replay && /* @__PURE__ */ jsx("style", { children: INK_REPLAY_KEYFRAMES }),
2470
- el.inkPaths.map((d, i) => {
2471
- const color = resolveInkColor(el.inkColors, i);
2472
- const width = resolveInkWidth(el.inkWidths, i);
2473
- const opacity = resolveInkOpacity(el.inkOpacities, i);
2474
- {
2475
- const pointPressures = el.inkPointPressures?.[i];
2476
- if (pointPressures && pointPressures.length > 1 && hasPressureVariation(pointPressures)) {
2477
- const pointWidths = pressuresToWidths(pointPressures, width);
2478
- return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(d, pointWidths, width, color, opacity, `${el.id}-ink-${i}`) }, `${el.id}-ink-${i}`);
2479
- }
2480
- if (el.inkWidths && el.inkWidths.length > 1 && hasPressureVariation(el.inkWidths)) {
2481
- return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(d, el.inkWidths, width, color, opacity, `${el.id}-ink-${i}`) }, `${el.id}-ink-${i}`);
2482
- }
2483
- }
2484
- const replayStyle = replayStyles?.[i];
2485
- return /* @__PURE__ */ jsx(
2486
- "path",
2487
- {
2488
- d,
2489
- fill: "none",
2490
- stroke: color,
2491
- strokeWidth: width,
2492
- strokeOpacity: opacity,
2493
- strokeLinecap: "round",
2494
- strokeLinejoin: "round",
2495
- vectorEffect: "non-scaling-stroke",
2496
- ...replayStyle ? {
2497
- strokeDasharray: replayStyle.strokeDasharray,
2498
- strokeDashoffset: replayStyle.strokeDashoffset,
2499
- style: {
2500
- animation: replayStyle.animation,
2501
- "--ink-path-length": replayStyle.pathLength
2502
- }
2503
- } : {}
2504
- },
2505
- `${el.id}-ink-${i}`
2506
- );
2507
- })
2688
+ strokes.map(
2689
+ (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-ink-${i}`)
2690
+ )
2508
2691
  ]
2509
2692
  }
2510
2693
  );
@@ -2600,6 +2783,7 @@ function renderContentPart(el, options) {
2600
2783
  if (el.inkStrokes && el.inkStrokes.length > 0) {
2601
2784
  const replay = options?.replay ?? false;
2602
2785
  const pressureSensitive = options?.pressureSensitive ?? true;
2786
+ const strokes = buildContentPartStrokes(el);
2603
2787
  const replayStyles = replay ? getContentPartReplayStyles(el.inkStrokes, options?.replayConfig) : null;
2604
2788
  return /* @__PURE__ */ jsxs(
2605
2789
  "svg",
@@ -2609,56 +2793,9 @@ function renderContentPart(el, options) {
2609
2793
  preserveAspectRatio: "none",
2610
2794
  children: [
2611
2795
  replay && /* @__PURE__ */ jsx("style", { children: INK_REPLAY_KEYFRAMES }),
2612
- el.inkStrokes.map((stroke, i) => {
2613
- if (stroke.tiltAngles && stroke.tiltAngles.length > 0) {
2614
- const magnitudes = stroke.tiltMagnitudes ?? stroke.tiltAngles.map(() => 0.5);
2615
- const widths = stroke.pressures && stroke.pressures.length > 1 && hasPressureVariation(stroke.pressures) ? pressuresToWidths(stroke.pressures, stroke.width) : [stroke.width];
2616
- return /* @__PURE__ */ jsx("g", { children: renderNibMarkStroke(
2617
- stroke.path,
2618
- widths,
2619
- stroke.tiltAngles,
2620
- magnitudes,
2621
- stroke.width,
2622
- stroke.color,
2623
- stroke.opacity,
2624
- `${el.id}-cp-ink-${i}`
2625
- ) }, `${el.id}-cp-ink-${i}`);
2626
- }
2627
- if (pressureSensitive && stroke.pressures && stroke.pressures.length > 1 && hasPressureVariation(stroke.pressures)) {
2628
- const pointWidths = pressuresToWidths(stroke.pressures, stroke.width);
2629
- return /* @__PURE__ */ jsx("g", { children: renderPressureStroke(
2630
- stroke.path,
2631
- pointWidths,
2632
- stroke.width,
2633
- stroke.color,
2634
- stroke.opacity,
2635
- `${el.id}-cp-ink-${i}`
2636
- ) }, `${el.id}-cp-ink-${i}`);
2637
- }
2638
- const replayStyle = replayStyles?.[i];
2639
- return /* @__PURE__ */ jsx(
2640
- "path",
2641
- {
2642
- d: stroke.path,
2643
- fill: "none",
2644
- stroke: stroke.color,
2645
- strokeWidth: stroke.width,
2646
- strokeOpacity: stroke.opacity,
2647
- strokeLinecap: "round",
2648
- strokeLinejoin: "round",
2649
- vectorEffect: "non-scaling-stroke",
2650
- ...replayStyle ? {
2651
- strokeDasharray: replayStyle.strokeDasharray,
2652
- strokeDashoffset: replayStyle.strokeDashoffset,
2653
- style: {
2654
- animation: replayStyle.animation,
2655
- "--ink-path-length": replayStyle.pathLength
2656
- }
2657
- } : {}
2658
- },
2659
- `${el.id}-cp-ink-${i}`
2660
- );
2661
- })
2796
+ strokes.map(
2797
+ (s, i) => renderStrokeView(s, pressureSensitive, replayStyles?.[i], `${el.id}-cp-ink-${i}`)
2798
+ )
2662
2799
  ]
2663
2800
  }
2664
2801
  );
@@ -3025,10 +3162,10 @@ function InlineTextEditor({
3025
3162
  function FailedToLoad6() {
3026
3163
  return null;
3027
3164
  }
3028
- var LazyModel3DScene = React19.lazy(
3165
+ var LazyModel3DScene = React20.lazy(
3029
3166
  async () => {
3030
3167
  try {
3031
- return await import('./Model3DScene-V3DHIISV.mjs');
3168
+ return await import('./Model3DScene-WJ3MMIZH.mjs');
3032
3169
  } catch {
3033
3170
  return { default: FailedToLoad6 };
3034
3171
  }
@@ -3090,7 +3227,7 @@ function PosterFallback({
3090
3227
  }
3091
3228
  );
3092
3229
  }
3093
- var Model3DErrorBoundary = class extends React19.Component {
3230
+ var Model3DErrorBoundary = class extends React20.Component {
3094
3231
  constructor(props) {
3095
3232
  super(props);
3096
3233
  this.state = { hasError: false };
@@ -3299,10 +3436,10 @@ function SmartArtInlineNodeEditor({
3299
3436
  onCancel
3300
3437
  }) {
3301
3438
  const { t } = useTranslation();
3302
- const ref = React19.useRef(null);
3303
- const [value, setValue] = React19.useState(initialText);
3304
- const settled = React19.useRef(false);
3305
- React19.useEffect(() => {
3439
+ const ref = React20.useRef(null);
3440
+ const [value, setValue] = React20.useState(initialText);
3441
+ const settled = React20.useRef(false);
3442
+ React20.useEffect(() => {
3306
3443
  const el = ref.current;
3307
3444
  if (el) {
3308
3445
  el.focus();
@@ -3394,16 +3531,16 @@ function findNodeIdFromEvent(target) {
3394
3531
  return null;
3395
3532
  }
3396
3533
  function useSmartArtHoverState(containerRef) {
3397
- const [hoveredNodeId, setHoveredNodeId] = React19.useState(null);
3398
- const [hoveredNodeRect, setHoveredNodeRect] = React19.useState(null);
3399
- const hideTimeoutRef = React19.useRef(null);
3400
- 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(() => {
3401
3538
  if (hideTimeoutRef.current !== null) {
3402
3539
  window.clearTimeout(hideTimeoutRef.current);
3403
3540
  hideTimeoutRef.current = null;
3404
3541
  }
3405
3542
  }, []);
3406
- const handleMouseMove = React19.useCallback(
3543
+ const handleMouseMove = React20.useCallback(
3407
3544
  (e, ignoreRef) => {
3408
3545
  const nodeEl = findNodeIdFromEvent(e.target);
3409
3546
  const container = containerRef.current;
@@ -3431,12 +3568,12 @@ function useSmartArtHoverState(containerRef) {
3431
3568
  },
3432
3569
  [containerRef, cancelPendingHide]
3433
3570
  );
3434
- const clearHover = React19.useCallback(() => {
3571
+ const clearHover = React20.useCallback(() => {
3435
3572
  cancelPendingHide();
3436
3573
  setHoveredNodeId(null);
3437
3574
  setHoveredNodeRect(null);
3438
3575
  }, [cancelPendingHide]);
3439
- React19.useEffect(() => cancelPendingHide, [cancelPendingHide]);
3576
+ React20.useEffect(() => cancelPendingHide, [cancelPendingHide]);
3440
3577
  return { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover };
3441
3578
  }
3442
3579
  var EDITOR_PADDING = 4;
@@ -3451,11 +3588,11 @@ function SmartArtEditableLayer({
3451
3588
  onChangeNodeStyle,
3452
3589
  children
3453
3590
  }) {
3454
- const containerRef = React19.useRef(null);
3455
- const styleBarRef = React19.useRef(null);
3456
- 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);
3457
3594
  const { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover } = useSmartArtHoverState(containerRef);
3458
- const openEditor = React19.useCallback(
3595
+ const openEditor = React20.useCallback(
3459
3596
  (target) => {
3460
3597
  const nodeEl = findNodeIdFromEvent(target);
3461
3598
  const container = containerRef.current;
@@ -4067,20 +4204,20 @@ function sameDiagramReveal(prev, next) {
4067
4204
  }
4068
4205
  return true;
4069
4206
  }
4070
- var SmartArtRenderer = React19.memo(SmartArtRendererImpl, arePropsEqual);
4207
+ var SmartArtRenderer = React20.memo(SmartArtRendererImpl, arePropsEqual);
4071
4208
  function FailedToLoad7() {
4072
4209
  return null;
4073
4210
  }
4074
- var LazySmartArt3DScene = React19.lazy(
4211
+ var LazySmartArt3DScene = React20.lazy(
4075
4212
  async () => {
4076
4213
  try {
4077
- return await import('./SmartArt3DScene-XCFVGCXE.mjs');
4214
+ return await import('./SmartArt3DScene-ODKCGJBO.mjs');
4078
4215
  } catch {
4079
4216
  return { default: FailedToLoad7 };
4080
4217
  }
4081
4218
  }
4082
4219
  );
4083
- var SceneErrorBoundary6 = class extends React19.Component {
4220
+ var SceneErrorBoundary6 = class extends React20.Component {
4084
4221
  constructor(props) {
4085
4222
  super(props);
4086
4223
  this.state = { hasError: false };
@@ -4097,7 +4234,8 @@ function SmartArt3DRenderer({
4097
4234
  className,
4098
4235
  interactive = false,
4099
4236
  canEdit,
4100
- onUpdateElement
4237
+ onUpdateElement,
4238
+ animationState
4101
4239
  }) {
4102
4240
  const [threeAvailable, setThreeAvailable] = useState(null);
4103
4241
  useEffect(() => {
@@ -4153,7 +4291,8 @@ function SmartArt3DRenderer({
4153
4291
  model,
4154
4292
  width: element.width,
4155
4293
  height: element.height,
4156
- interactive
4294
+ interactive,
4295
+ textStyle: animationState?.textStyle
4157
4296
  }
4158
4297
  ) }) });
4159
4298
  const editEnabled = canEdit && Boolean(onUpdateElement);
@@ -4197,7 +4336,8 @@ function SmartArtElement({
4197
4336
  element,
4198
4337
  className,
4199
4338
  canEdit,
4200
- onUpdateElement
4339
+ onUpdateElement,
4340
+ animationState
4201
4341
  }
4202
4342
  );
4203
4343
  }
@@ -4257,6 +4397,67 @@ function getSegmentTspanProps(segment, element, fallbackColor) {
4257
4397
  textDecoration: decos.length > 0 ? decos.join(" ") : void 0
4258
4398
  };
4259
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
+ }
4260
4461
  function WarpedText({
4261
4462
  element,
4262
4463
  width,
@@ -4285,6 +4486,48 @@ function WarpedText({
4285
4486
  const baseFontSize = textEl.textStyle?.fontSize ?? DEFAULT_TEXT_FONT_SIZE;
4286
4487
  const baseFontFamily = textEl.textStyle?.fontFamily ? getSubstituteFontFamily(textEl.textStyle.fontFamily) : DEFAULT_FONT_FAMILY;
4287
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
+ }
4288
4531
  return /* @__PURE__ */ jsxs(
4289
4532
  "svg",
4290
4533
  {
@@ -4413,13 +4656,26 @@ function renderTextElementBody(options) {
4413
4656
  const useSvgWarp = shouldUseSvgWarp(
4414
4657
  hasTextProperties(el) ? el.textStyle?.textWarpPreset : void 0
4415
4658
  );
4416
- 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;
4417
4660
  const rotationTransform = getTextBodyRotationTransform(el);
4418
4661
  const composedTransform = [rotationTransform, getTextCompensationTransform(el), scene3dStyle?.transform].filter(Boolean).join(" ") || void 0;
4419
4662
  const transformStyle = {
4420
4663
  transform: composedTransform,
4421
- 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",
4422
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 } : {},
4423
4679
  ...scene3dStyle?.transformStyle ? { transformStyle: scene3dStyle.transformStyle } : {},
4424
4680
  ...isLinkedTextBox2 ? { overflow: "hidden" } : {}
4425
4681
  };
@@ -4846,7 +5102,9 @@ function renderBody(options) {
4846
5102
  }
4847
5103
  if (doInk && isInkElement(el)) {
4848
5104
  return renderInk(el, {
4849
- replay: isPresentationPassive});
5105
+ replay: isPresentationPassive,
5106
+ pressureSensitive: true
5107
+ });
4850
5108
  }
4851
5109
  if (el.type === "contentPart") {
4852
5110
  return renderContentPart(el, {
@@ -4867,9 +5125,8 @@ function renderBody(options) {
4867
5125
  }
4868
5126
  return renderTextElementBody(options);
4869
5127
  }
4870
- var noop = () => {
4871
- };
4872
- var EMPTY_MEDIA_DATA_URLS = /* @__PURE__ */ new Map();
5128
+
5129
+ // src/viewer/components/static-element-renderer-utils.ts
4873
5130
  function defaultTextColorForFill(fillColor) {
4874
5131
  const hex = String(fillColor ?? "").replace(/^#/u, "");
4875
5132
  if (!/^[0-9a-f]{6}$/iu.test(hex)) {
@@ -4879,26 +5136,7 @@ function defaultTextColorForFill(fillColor) {
4879
5136
  const luminance = channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
4880
5137
  return luminance > 0.179 ? DEFAULT_TEXT_COLOR : "#ffffff";
4881
5138
  }
4882
- function StaticElementRendererImpl({
4883
- element,
4884
- activeSlide,
4885
- allSlides,
4886
- mediaDataUrls = EMPTY_MEDIA_DATA_URLS,
4887
- sourceSlideIndex,
4888
- zIndex,
4889
- positioned = true,
4890
- fieldContext,
4891
- tableStyleContext,
4892
- parentGroupFill,
4893
- onActionClick,
4894
- actionRequiresModifier = false,
4895
- animation,
4896
- imageAnimation,
4897
- exposeElementId = false
4898
- }) {
4899
- if (!isElementRendered(element)) {
4900
- return null;
4901
- }
5139
+ function getStaticElementVisualState(element, parentGroupFill) {
4902
5140
  const style = hasShapeProperties(element) ? element.shapeStyle : void 0;
4903
5141
  const hasFill = style?.fillColor !== void 0 && style.fillColor !== "transparent" || Boolean(buildCssGradientFromShapeStyle(style) || style?.fillGradient) || style?.fillMode === "pattern" && Boolean(style.fillPatternPreset);
4904
5142
  const fill = normalizeHexColor(style?.fillColor, DEFAULT_FILL_COLOR);
@@ -4922,9 +5160,69 @@ function StaticElementRendererImpl({
4922
5160
  const letsTextOverflow = hasTextProperties(element) && element.textStyle?.autoFitMode === "shrink" && (element.type === "text" || element.locks?.txBox === true);
4923
5161
  const shapeType = hasShapeProperties(element) ? element.shapeType : void 0;
4924
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) {
4925
5176
  const action = element.actionClick;
4926
- const isActionable = Boolean(action && onActionClick);
5177
+ const isActionable = Boolean(action && hasActionHandler);
4927
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
+ );
4928
5226
  return /* @__PURE__ */ jsxs(
4929
5227
  "div",
4930
5228
  {
@@ -4932,7 +5230,12 @@ function StaticElementRendererImpl({
4932
5230
  "data-element-id": exposeElementId ? element.id : void 0,
4933
5231
  "data-pptx-element": exposeElementId ? "true" : void 0,
4934
5232
  "data-pptx-action": isActionable ? "click" : void 0,
4935
- 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
+ ),
4936
5239
  role: contractRole,
4937
5240
  "aria-label": exposeElementId ? getAriaLabel(element) : void 0,
4938
5241
  "aria-roledescription": exposeElementId ? getAriaRoleDescription(element) : void 0,
@@ -4976,7 +5279,7 @@ function StaticElementRendererImpl({
4976
5279
  animation
4977
5280
  },
4978
5281
  children: [
4979
- /* @__PURE__ */ jsx(ShapeEffectOverlay, { element }),
5282
+ /* @__PURE__ */ jsx(ShapeEffectOverlay, { element, suppressReflection }),
4980
5283
  element.type === "group" ? /* @__PURE__ */ jsx("div", { className: "relative w-full h-full", children: (element.children ?? []).map((child, index) => /* @__PURE__ */ jsx(
4981
5284
  StaticElementRenderer,
4982
5285
  {
@@ -5041,7 +5344,7 @@ function StaticElementRendererImpl({
5041
5344
  }
5042
5345
  );
5043
5346
  }
5044
- var StaticElementRenderer = React19.memo(StaticElementRendererImpl);
5347
+ var StaticElementRenderer = React20.memo(StaticElementRendererImpl);
5045
5348
  StaticElementRenderer.displayName = "StaticElementRenderer";
5046
5349
  var PREVIEW_CANVAS_WIDTH = 1280;
5047
5350
  var PREVIEW_CANVAS_HEIGHT = 720;
@@ -5958,17 +6261,17 @@ function ArrangeSection(p) {
5958
6261
  function TransitionsSection(p) {
5959
6262
  const { t } = useTranslation();
5960
6263
  const canEdit = p.canEdit !== false;
5961
- const draft = React19.useMemo(() => readRibbonTransitionDraft(p.activeSlide), [p.activeSlide]);
5962
- const [durationBuffer, setDurationBuffer] = React19.useState(null);
5963
- const [advanceBuffer, setAdvanceBuffer] = React19.useState(null);
5964
- const commit = React19.useCallback(
6264
+ const draft = React20.useMemo(() => readRibbonTransitionDraft(p.activeSlide), [p.activeSlide]);
6265
+ const [durationBuffer, setDurationBuffer] = React20.useState(null);
6266
+ const [advanceBuffer, setAdvanceBuffer] = React20.useState(null);
6267
+ const commit = React20.useCallback(
5965
6268
  (changes) => {
5966
6269
  p.onTransitionChange(ribbonTransitionUpdates({ ...draft, ...changes }));
5967
6270
  },
5968
6271
  [draft, p]
5969
6272
  );
5970
- const soundFileInputRef = React19.useRef(null);
5971
- const handleSoundFilePicked = React19.useCallback(
6273
+ const soundFileInputRef = React20.useRef(null);
6274
+ const handleSoundFilePicked = React20.useCallback(
5972
6275
  (file) => {
5973
6276
  void readSoundFileAsDataUrl(file).then((dataUrl) => {
5974
6277
  if (dataUrl) {
@@ -6333,7 +6636,7 @@ function AccountPage() {
6333
6636
  return void 0;
6334
6637
  });
6335
6638
  };
6336
- const version = "3.6.0" ;
6639
+ const version = "3.8.0" ;
6337
6640
  return /* @__PURE__ */ jsxs("div", { className: "mt-8 max-w-[700px] space-y-6", children: [
6338
6641
  /* @__PURE__ */ jsxs("section", { className: cardClass, children: [
6339
6642
  /* @__PURE__ */ jsxs("h2", { className: "flex items-center gap-2 text-sm font-semibold", children: [
@@ -6769,7 +7072,7 @@ function FontFamilyMenu(p) {
6769
7072
  embeddedFonts: p.embeddedFonts,
6770
7073
  customFonts: p.customFonts
6771
7074
  });
6772
- 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: [
7075
+ 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: [
6773
7076
  /* @__PURE__ */ jsx(
6774
7077
  "div",
6775
7078
  {
@@ -10963,8 +11266,8 @@ function Toolbar(p) {
10963
11266
  }
10964
11267
 
10965
11268
  // src/viewer/utils/slide-background-style.ts
10966
- function getReactSlideBackgroundStyle(slide) {
10967
- const style = getSlideBackgroundStyle(slide);
11269
+ function getReactSlideBackgroundStyle(slide, slideSize) {
11270
+ const style = getSlideBackgroundStyle(slide, slideSize);
10968
11271
  return {
10969
11272
  backgroundColor: style["background-color"],
10970
11273
  backgroundImage: slide?.backgroundImage ? void 0 : style["background-image"],
@@ -11306,6 +11609,7 @@ function DrawingOverlaySvg({
11306
11609
  drawingWidth,
11307
11610
  isStrokeActive,
11308
11611
  liveStrokeD,
11612
+ liveStrokeView,
11309
11613
  onPointerDown,
11310
11614
  onPointerMove,
11311
11615
  onPointerUp
@@ -11324,7 +11628,7 @@ function DrawingOverlaySvg({
11324
11628
  onPointerDown,
11325
11629
  onPointerMove,
11326
11630
  onPointerUp,
11327
- children: isStrokeActive && liveStrokeD && /* @__PURE__ */ jsx(
11631
+ children: isStrokeActive && liveStrokeView ? renderStrokeView(liveStrokeView, true, void 0, "ink-live-preview") : isStrokeActive && liveStrokeD && /* @__PURE__ */ jsx(
11328
11632
  "path",
11329
11633
  {
11330
11634
  d: liveStrokeD,
@@ -11543,7 +11847,7 @@ function HorizontalRulerView({ ticks, widthPx, highlight }) {
11543
11847
  }
11544
11848
  );
11545
11849
  }
11546
- var HorizontalRuler = React19.memo(HorizontalRulerView);
11850
+ var HorizontalRuler = React20.memo(HorizontalRulerView);
11547
11851
  HorizontalRuler.displayName = "HorizontalRuler";
11548
11852
  function VerticalRulerView({ ticks, heightPx, highlight }) {
11549
11853
  return /* @__PURE__ */ jsxs(
@@ -11615,7 +11919,7 @@ function VerticalRulerView({ ticks, heightPx, highlight }) {
11615
11919
  }
11616
11920
  );
11617
11921
  }
11618
- var VerticalRuler = React19.memo(VerticalRulerView);
11922
+ var VerticalRuler = React20.memo(VerticalRulerView);
11619
11923
  VerticalRuler.displayName = "VerticalRuler";
11620
11924
  function Ruler({
11621
11925
  canvasSize,
@@ -12088,6 +12392,140 @@ function useConnectorCreation({
12088
12392
  handleConnectorDragEnd
12089
12393
  };
12090
12394
  }
12395
+
12396
+ // src/viewer/components/canvas/canvas-path.ts
12397
+ function buildCanvasPathD(points) {
12398
+ if (points.length === 0) {
12399
+ return "";
12400
+ }
12401
+ const parts = [`M ${points[0].x} ${points[0].y}`];
12402
+ for (let i = 1; i < points.length; i++) {
12403
+ parts.push(`L ${points[i].x} ${points[i].y}`);
12404
+ }
12405
+ return parts.join(" ");
12406
+ }
12407
+
12408
+ // src/viewer/components/canvas/finishDrawStroke.ts
12409
+ function finishDrawStroke(input) {
12410
+ const { tool, points, pressures, tiltX, tiltY, color, width } = input;
12411
+ if (points.length < 2) {
12412
+ return null;
12413
+ }
12414
+ let minX = Infinity;
12415
+ let minY = Infinity;
12416
+ let maxX = -Infinity;
12417
+ let maxY = -Infinity;
12418
+ for (const pt of points) {
12419
+ if (pt.x < minX) {
12420
+ minX = pt.x;
12421
+ }
12422
+ if (pt.y < minY) {
12423
+ minY = pt.y;
12424
+ }
12425
+ if (pt.x > maxX) {
12426
+ maxX = pt.x;
12427
+ }
12428
+ if (pt.y > maxY) {
12429
+ maxY = pt.y;
12430
+ }
12431
+ }
12432
+ const pad = width;
12433
+ minX -= pad;
12434
+ minY -= pad;
12435
+ maxX += pad;
12436
+ maxY += pad;
12437
+ const w = Math.max(maxX - minX, 1);
12438
+ const h = Math.max(maxY - minY, 1);
12439
+ const relPoints = points.map((pt) => ({ x: pt.x - minX, y: pt.y - minY }));
12440
+ if (tool === "freeform") {
12441
+ return {
12442
+ kind: "freeform",
12443
+ element: buildFreeformShape(relPoints, { x: minX, y: minY, w, h }, color, width)
12444
+ };
12445
+ }
12446
+ return {
12447
+ kind: "ink",
12448
+ element: buildInkElement(
12449
+ relPoints,
12450
+ { x: minX, y: minY, w, h },
12451
+ tool,
12452
+ { pressures, tiltX, tiltY },
12453
+ color,
12454
+ width
12455
+ )
12456
+ };
12457
+ }
12458
+ function buildFreeformShape(relPoints, box, color, width) {
12459
+ const COORD_SCALE = 100;
12460
+ const segments = [];
12461
+ for (let i = 0; i < relPoints.length; i++) {
12462
+ const scaledPt = {
12463
+ x: Math.round(relPoints[i].x * COORD_SCALE),
12464
+ y: Math.round(relPoints[i].y * COORD_SCALE)
12465
+ };
12466
+ segments.push(i === 0 ? { type: "moveTo", pt: scaledPt } : { type: "lineTo", pt: scaledPt });
12467
+ }
12468
+ if (segments.length > 2) {
12469
+ segments.push({ type: "close" });
12470
+ }
12471
+ return {
12472
+ id: `shape-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12473
+ type: "shape",
12474
+ x: box.x,
12475
+ y: box.y,
12476
+ width: box.w,
12477
+ height: box.h,
12478
+ shapeType: "custom",
12479
+ shapeStyle: { fillColor: "transparent", strokeColor: color, strokeWidth: width },
12480
+ customGeometryPaths: [
12481
+ { width: Math.round(box.w * COORD_SCALE), height: Math.round(box.h * COORD_SCALE), segments }
12482
+ ]
12483
+ };
12484
+ }
12485
+ function buildInkElement(relPoints, box, tool, channels, color, width) {
12486
+ const pathD = buildCanvasPathD(relPoints);
12487
+ const isHighlighter = tool === "highlighter";
12488
+ const { pressures, tiltX, tiltY } = channels;
12489
+ const hasPressure = pressures.length >= 2 && pressures.some((p) => Math.abs(p - pressures[0]) > 0.01);
12490
+ const hasTilt = hasTiltData(tiltX, tiltY);
12491
+ return {
12492
+ id: `ink-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12493
+ type: "ink",
12494
+ x: box.x,
12495
+ y: box.y,
12496
+ width: box.w,
12497
+ height: box.h,
12498
+ inkPaths: [pathD],
12499
+ inkColors: [color],
12500
+ inkWidths: [width],
12501
+ inkOpacities: [isHighlighter ? 0.4 : 1],
12502
+ inkTool: isHighlighter ? "highlighter" : "pen",
12503
+ ...hasPressure ? { inkPointPressures: [pressures] } : {},
12504
+ ...hasTilt ? { inkPointTiltX: [tiltX], inkPointTiltY: [tiltY] } : {}
12505
+ };
12506
+ }
12507
+ function useLiveInkPreview(isStrokeActive, activeTool, points, pressures, tiltX, tiltY, color, width) {
12508
+ const liveStrokeD = useMemo(
12509
+ () => isStrokeActive ? buildCanvasPathD(points) : "",
12510
+ [isStrokeActive, points]
12511
+ );
12512
+ const liveStrokeView = useMemo(() => {
12513
+ if (!isStrokeActive || activeTool === "select" || activeTool === "eraser") {
12514
+ return null;
12515
+ }
12516
+ const inkPoints = points.map((pt, i) => ({
12517
+ x: pt.x,
12518
+ y: pt.y,
12519
+ pressure: pressures[i],
12520
+ tiltX: tiltX[i],
12521
+ tiltY: tiltY[i]
12522
+ }));
12523
+ return buildLiveInkStrokeView({ points: inkPoints, color, width, tool: activeTool });
12524
+ }, [isStrokeActive, activeTool, points, pressures, tiltX, tiltY, color, width]);
12525
+ return { liveStrokeD, liveStrokeView };
12526
+ }
12527
+
12528
+ // src/viewer/components/canvas/useDrawingOverlay.ts
12091
12529
  function useDrawingOverlay({
12092
12530
  activeTool,
12093
12531
  activeSlide,
@@ -12104,6 +12542,8 @@ function useDrawingOverlay({
12104
12542
  []
12105
12543
  );
12106
12544
  const [currentStrokePressures, setCurrentStrokePressures] = useState([]);
12545
+ const [currentStrokeTiltX, setCurrentStrokeTiltX] = useState([]);
12546
+ const [currentStrokeTiltY, setCurrentStrokeTiltY] = useState([]);
12107
12547
  const [isStrokeActive, setIsStrokeActive] = useState(false);
12108
12548
  const pointerToCanvasCoords = useCallback(
12109
12549
  (e) => {
@@ -12120,16 +12560,6 @@ function useDrawingOverlay({
12120
12560
  },
12121
12561
  [zoom.canvasStageRef, zoom.editorScale]
12122
12562
  );
12123
- const buildPathD = useCallback((pts) => {
12124
- if (pts.length === 0) {
12125
- return "";
12126
- }
12127
- const parts = [`M ${pts[0].x} ${pts[0].y}`];
12128
- for (let i = 1; i < pts.length; i++) {
12129
- parts.push(`L ${pts[i].x} ${pts[i].y}`);
12130
- }
12131
- return parts.join(" ");
12132
- }, []);
12133
12563
  const handleDrawPointerDown = useCallback(
12134
12564
  (e) => {
12135
12565
  if (activeTool === "select") {
@@ -12154,6 +12584,8 @@ function useDrawingOverlay({
12154
12584
  e.target.setPointerCapture(e.pointerId);
12155
12585
  setCurrentStrokePoints([pt]);
12156
12586
  setCurrentStrokePressures([e.pressure]);
12587
+ setCurrentStrokeTiltX([e.tiltX ?? 0]);
12588
+ setCurrentStrokeTiltY([e.tiltY ?? 0]);
12157
12589
  setIsStrokeActive(true);
12158
12590
  if (isDrawingRef) {
12159
12591
  isDrawingRef.current = true;
@@ -12172,6 +12604,8 @@ function useDrawingOverlay({
12172
12604
  }
12173
12605
  setCurrentStrokePoints((prev) => [...prev, pt]);
12174
12606
  setCurrentStrokePressures((prev) => [...prev, e.pressure]);
12607
+ setCurrentStrokeTiltX((prev) => [...prev, e.tiltX ?? 0]);
12608
+ setCurrentStrokeTiltY((prev) => [...prev, e.tiltY ?? 0]);
12175
12609
  },
12176
12610
  [isStrokeActive, activeTool, pointerToCanvasCoords]
12177
12611
  );
@@ -12185,113 +12619,54 @@ function useDrawingOverlay({
12185
12619
  if (isDrawingRef) {
12186
12620
  isDrawingRef.current = false;
12187
12621
  }
12188
- if (currentStrokePoints.length < 2) {
12189
- setCurrentStrokePoints([]);
12190
- return;
12191
- }
12192
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
12193
- for (const pt of currentStrokePoints) {
12194
- if (pt.x < minX) {
12195
- minX = pt.x;
12196
- }
12197
- if (pt.y < minY) {
12198
- minY = pt.y;
12199
- }
12200
- if (pt.x > maxX) {
12201
- maxX = pt.x;
12202
- }
12203
- if (pt.y > maxY) {
12204
- maxY = pt.y;
12205
- }
12206
- }
12207
- const PAD = drawingWidth;
12208
- minX -= PAD;
12209
- minY -= PAD;
12210
- maxX += PAD;
12211
- maxY += PAD;
12212
- const w = Math.max(maxX - minX, 1);
12213
- const h = Math.max(maxY - minY, 1);
12214
- const relPoints = currentStrokePoints.map((pt) => ({
12215
- x: pt.x - minX,
12216
- y: pt.y - minY
12217
- }));
12218
- if (activeTool === "freeform") {
12219
- const COORD_SCALE = 100;
12220
- const pathW = Math.round(w * COORD_SCALE);
12221
- const pathH = Math.round(h * COORD_SCALE);
12222
- const segments = [];
12223
- for (let i = 0; i < relPoints.length; i++) {
12224
- const scaledPt = {
12225
- x: Math.round(relPoints[i].x * COORD_SCALE),
12226
- y: Math.round(relPoints[i].y * COORD_SCALE)
12227
- };
12228
- segments.push(
12229
- i === 0 ? { type: "moveTo", pt: scaledPt } : { type: "lineTo", pt: scaledPt }
12230
- );
12231
- }
12232
- if (segments.length > 2) {
12233
- segments.push({ type: "close" });
12234
- }
12235
- const freeformShape = {
12236
- id: `shape-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12237
- type: "shape",
12238
- x: minX,
12239
- y: minY,
12240
- width: w,
12241
- height: h,
12242
- shapeType: "custom",
12243
- shapeStyle: {
12244
- fillColor: "transparent",
12245
- strokeColor: drawingColor,
12246
- strokeWidth: drawingWidth
12247
- },
12248
- customGeometryPaths: [{ width: pathW, height: pathH, segments }]
12249
- };
12250
- onAddFreeformShape?.(freeformShape);
12251
- } else {
12252
- const pathD = buildPathD(relPoints);
12253
- const isHighlighter = activeTool === "highlighter";
12254
- const hasPressure = currentStrokePressures.length >= 2 && currentStrokePressures.some((p) => Math.abs(p - currentStrokePressures[0]) > 0.01);
12255
- const ink = {
12256
- id: `ink-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
12257
- type: "ink",
12258
- x: minX,
12259
- y: minY,
12260
- width: w,
12261
- height: h,
12262
- inkPaths: [pathD],
12263
- inkColors: [drawingColor],
12264
- inkWidths: [drawingWidth],
12265
- inkOpacities: [isHighlighter ? 0.4 : 1],
12266
- inkTool: isHighlighter ? "highlighter" : "pen",
12267
- ...hasPressure ? { inkPointPressures: [currentStrokePressures] } : {}
12268
- };
12269
- onAddInkElement?.(ink);
12622
+ const finished = finishDrawStroke({
12623
+ tool: activeTool,
12624
+ points: currentStrokePoints,
12625
+ pressures: currentStrokePressures,
12626
+ tiltX: currentStrokeTiltX,
12627
+ tiltY: currentStrokeTiltY,
12628
+ color: drawingColor,
12629
+ width: drawingWidth
12630
+ });
12631
+ if (finished?.kind === "freeform") {
12632
+ onAddFreeformShape?.(finished.element);
12633
+ } else if (finished?.kind === "ink") {
12634
+ onAddInkElement?.(finished.element);
12270
12635
  }
12271
12636
  setCurrentStrokePoints([]);
12272
12637
  setCurrentStrokePressures([]);
12638
+ setCurrentStrokeTiltX([]);
12639
+ setCurrentStrokeTiltY([]);
12273
12640
  },
12274
12641
  [
12275
12642
  isStrokeActive,
12276
12643
  activeTool,
12277
12644
  currentStrokePoints,
12645
+ currentStrokeTiltX,
12646
+ currentStrokeTiltY,
12278
12647
  drawingColor,
12279
12648
  drawingWidth,
12280
12649
  isDrawingRef,
12281
12650
  onAddInkElement,
12282
12651
  onAddFreeformShape,
12283
- buildPathD,
12284
12652
  currentStrokePressures
12285
12653
  ]
12286
12654
  );
12287
- const liveStrokeD = useMemo(
12288
- () => isStrokeActive ? buildPathD(currentStrokePoints) : "",
12289
- [isStrokeActive, currentStrokePoints, buildPathD]
12655
+ const { liveStrokeD, liveStrokeView } = useLiveInkPreview(
12656
+ isStrokeActive,
12657
+ activeTool,
12658
+ currentStrokePoints,
12659
+ currentStrokePressures,
12660
+ currentStrokeTiltX,
12661
+ currentStrokeTiltY,
12662
+ drawingColor,
12663
+ drawingWidth
12290
12664
  );
12291
12665
  return {
12292
12666
  isDrawing,
12293
12667
  isStrokeActive,
12294
12668
  liveStrokeD,
12669
+ liveStrokeView,
12295
12670
  currentStrokePoints,
12296
12671
  handleDrawPointerDown,
12297
12672
  handleDrawPointerMove,
@@ -12609,6 +12984,7 @@ function SlideCanvas({
12609
12984
  isDrawing,
12610
12985
  isStrokeActive,
12611
12986
  liveStrokeD,
12987
+ liveStrokeView,
12612
12988
  handleDrawPointerDown,
12613
12989
  handleDrawPointerMove,
12614
12990
  handleDrawPointerUp
@@ -12678,7 +13054,10 @@ function SlideCanvas({
12678
13054
  // pinch-zoom. View/present mode keeps the default so the slide can
12679
13055
  // still be scrolled and swipe-navigated.
12680
13056
  touchAction: isEditableCanvas ? "none" : void 0,
12681
- ...getReactSlideBackgroundStyle(activeSlide)
13057
+ ...getReactSlideBackgroundStyle(activeSlide, {
13058
+ widthPx: canvasSize.width,
13059
+ heightPx: canvasSize.height
13060
+ })
12682
13061
  },
12683
13062
  onClick: handleStageClick,
12684
13063
  onDoubleClick: handleStageDblClick,
@@ -12859,6 +13238,7 @@ function SlideCanvas({
12859
13238
  drawingWidth,
12860
13239
  isStrokeActive,
12861
13240
  liveStrokeD,
13241
+ liveStrokeView,
12862
13242
  onPointerDown: handleDrawPointerDown,
12863
13243
  onPointerMove: handleDrawPointerMove,
12864
13244
  onPointerUp: handleDrawPointerUp
@@ -13320,7 +13700,13 @@ function SlideThumbnailImpl({
13320
13700
  "div",
13321
13701
  {
13322
13702
  className: "relative w-full overflow-hidden rounded border border-border bg-white",
13323
- style: { height: previewHeight, ...getReactSlideBackgroundStyle(slide) },
13703
+ style: {
13704
+ height: previewHeight,
13705
+ ...getReactSlideBackgroundStyle(slide, {
13706
+ widthPx: safeCanvasWidth,
13707
+ heightPx: safeCanvasHeight
13708
+ })
13709
+ },
13324
13710
  children: /* @__PURE__ */ jsxs(
13325
13711
  "div",
13326
13712
  {
@@ -13398,7 +13784,7 @@ function arePropsEqual2(prev, next) {
13398
13784
  }
13399
13785
  return true;
13400
13786
  }
13401
- var SlideThumbnail = React19.memo(SlideThumbnailImpl, arePropsEqual2);
13787
+ var SlideThumbnail = React20.memo(SlideThumbnailImpl, arePropsEqual2);
13402
13788
 
13403
13789
  // src/viewer/components/context-menu-dispatch.ts
13404
13790
  function tableCell(props) {
@@ -13948,7 +14334,7 @@ function LazyThumbnailInner({
13948
14334
  }
13949
14335
  ) });
13950
14336
  }
13951
- var LazyThumbnail = React19.memo(LazyThumbnailInner);
14337
+ var LazyThumbnail = React20.memo(LazyThumbnailInner);
13952
14338
 
13953
14339
  // src/viewer/components/slides-pane/utils.ts
13954
14340
  function formatTimingMs(ms) {
@@ -14102,7 +14488,7 @@ function SlideItemInner({
14102
14488
  }
14103
14489
  );
14104
14490
  }
14105
- var SlideItem = React19.memo(SlideItemInner);
14491
+ var SlideItem = React20.memo(SlideItemInner);
14106
14492
  function useSlidePaneCallbacks(onMoveSlide, onRenameSection, onToggleSectionCollapse) {
14107
14493
  const [collapsedSections, setCollapsedSections] = useState({});
14108
14494
  const [renamingSectionId, setRenamingSectionId] = useState(null);
@@ -15423,7 +15809,7 @@ function arePropsEqual3(prev, next) {
15423
15809
  }
15424
15810
  return true;
15425
15811
  }
15426
- var SlideCard = React19.memo(SlideCardImpl, arePropsEqual3);
15812
+ var SlideCard = React20.memo(SlideCardImpl, arePropsEqual3);
15427
15813
  function SorterContextMenu({
15428
15814
  x,
15429
15815
  y,
@@ -18867,9 +19253,9 @@ function PresentationSubtitleBar({
18867
19253
  function renderNotesSegments(segments) {
18868
19254
  return notesSegmentsToSpans(segments).map((span) => {
18869
19255
  if (span.kind === "break") {
18870
- return React19.createElement("br", { key: span.key });
19256
+ return React20.createElement("br", { key: span.key });
18871
19257
  }
18872
- return React19.createElement(
19258
+ return React20.createElement(
18873
19259
  "span",
18874
19260
  { key: span.key, style: span.style },
18875
19261
  span.text
@@ -19098,7 +19484,7 @@ function arePropsEqual4(prev, next) {
19098
19484
  }
19099
19485
  return true;
19100
19486
  }
19101
- var ScaledSlidePreview = React19.memo(ScaledSlidePreviewImpl, arePropsEqual4);
19487
+ var ScaledSlidePreview = React20.memo(ScaledSlidePreviewImpl, arePropsEqual4);
19102
19488
  function PresenterNotesRail({
19103
19489
  slides,
19104
19490
  current,
@@ -20287,7 +20673,7 @@ function EffectSoundRow({
20287
20673
  onPick
20288
20674
  }) {
20289
20675
  const { t } = useTranslation();
20290
- const fileInputRef = React19.useRef(null);
20676
+ const fileInputRef = React20.useRef(null);
20291
20677
  const handleSelectChange = (event) => {
20292
20678
  if (event.target.value === "custom") {
20293
20679
  fileInputRef.current?.click();
@@ -22626,14 +23012,17 @@ function ChartTrendlineOptions({
22626
23012
  function ChartTypeSelector({
22627
23013
  title,
22628
23014
  chartType,
23015
+ chartData,
22629
23016
  grouping,
22630
23017
  seriesCount,
22631
23018
  categoryCount,
22632
23019
  canEdit,
22633
- onUpdateChartData
23020
+ onUpdateChartData,
23021
+ onTitleChange
22634
23022
  }) {
22635
23023
  const { t } = useTranslation();
22636
23024
  const supportsGrouping = GROUPING_SUPPORTED_TYPES.has(chartType);
23025
+ const displayedType = resolveDisplayedChartType(chartData);
22637
23026
  return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
22638
23027
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.chart.heading") }),
22639
23028
  /* @__PURE__ */ jsxs("div", { className: "text-[11px] text-muted-foreground mb-1", children: [
@@ -22654,7 +23043,7 @@ function ChartTypeSelector({
22654
23043
  disabled: !canEdit,
22655
23044
  className: INPUT2,
22656
23045
  value: title ?? "",
22657
- onChange: (e) => onUpdateChartData({ title: e.target.value })
23046
+ onChange: (e) => onTitleChange(e.target.value)
22658
23047
  }
22659
23048
  )
22660
23049
  ] }),
@@ -22666,7 +23055,7 @@ function ChartTypeSelector({
22666
23055
  "aria-label": t("pptx.chart.type"),
22667
23056
  disabled: !canEdit,
22668
23057
  className: INPUT2,
22669
- value: chartType,
23058
+ value: displayedType,
22670
23059
  onChange: (e) => onUpdateChartData({
22671
23060
  chartType: e.target.value
22672
23061
  }),
@@ -22692,6 +23081,208 @@ function ChartTypeSelector({
22692
23081
  ] })
22693
23082
  ] });
22694
23083
  }
23084
+ function NumberField({ value, canEdit, fraction, nonNegative, onChange }) {
23085
+ return /* @__PURE__ */ jsx(
23086
+ "input",
23087
+ {
23088
+ type: "number",
23089
+ step: fraction ? "0.01" : void 0,
23090
+ min: fraction || nonNegative ? 0 : void 0,
23091
+ max: fraction ? 1 : void 0,
23092
+ disabled: !canEdit,
23093
+ className: INPUT2,
23094
+ value,
23095
+ onChange: (e) => onChange(Number(e.target.value))
23096
+ }
23097
+ );
23098
+ }
23099
+ function RotationField({
23100
+ row,
23101
+ canEdit,
23102
+ onRotationPatch
23103
+ }) {
23104
+ const { t } = useTranslation();
23105
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
23106
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeRotation") }),
23107
+ /* @__PURE__ */ jsx(
23108
+ "input",
23109
+ {
23110
+ type: "number",
23111
+ step: "1",
23112
+ "aria-label": t("pptx.chart.userShapeRotation"),
23113
+ disabled: !canEdit,
23114
+ className: INPUT2,
23115
+ value: row.rotation ?? 0,
23116
+ onChange: (e) => onRotationPatch(row.path, Number(e.target.value) || void 0)
23117
+ }
23118
+ )
23119
+ ] });
23120
+ }
23121
+ function FlipFields({
23122
+ row,
23123
+ canEdit,
23124
+ onFlipPatch
23125
+ }) {
23126
+ const { t } = useTranslation();
23127
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
23128
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1 cursor-pointer", children: [
23129
+ /* @__PURE__ */ jsx(
23130
+ "input",
23131
+ {
23132
+ type: "checkbox",
23133
+ "aria-label": t("pptx.arrange.flipHorizontally"),
23134
+ disabled: !canEdit,
23135
+ className: "accent-primary",
23136
+ checked: row.flipH ?? false,
23137
+ onChange: (e) => onFlipPatch(row.path, { flipH: e.target.checked })
23138
+ }
23139
+ ),
23140
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.arrange.flipHorizontally") })
23141
+ ] }),
23142
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1 cursor-pointer", children: [
23143
+ /* @__PURE__ */ jsx(
23144
+ "input",
23145
+ {
23146
+ type: "checkbox",
23147
+ "aria-label": t("pptx.arrange.flipVertically"),
23148
+ disabled: !canEdit,
23149
+ className: "accent-primary",
23150
+ checked: row.flipV ?? false,
23151
+ onChange: (e) => onFlipPatch(row.path, { flipV: e.target.checked })
23152
+ }
23153
+ ),
23154
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.arrange.flipVertically") })
23155
+ ] })
23156
+ ] });
23157
+ }
23158
+ function ChartUserShapePositionFields({
23159
+ row,
23160
+ userShapes,
23161
+ canEdit,
23162
+ onPatch,
23163
+ onBoxPatch,
23164
+ onRotationPatch,
23165
+ onFlipPatch
23166
+ }) {
23167
+ const { t } = useTranslation();
23168
+ const update = (patch) => onPatch(row.path, patch);
23169
+ if (row.depth === 0) {
23170
+ const from = row.from;
23171
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 text-[11px]", children: [
23172
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFrom") }),
23173
+ /* @__PURE__ */ jsx(
23174
+ NumberField,
23175
+ {
23176
+ fraction: true,
23177
+ canEdit,
23178
+ value: from.x,
23179
+ onChange: (x) => update({ from: { ...from, x } })
23180
+ }
23181
+ ),
23182
+ /* @__PURE__ */ jsx(
23183
+ NumberField,
23184
+ {
23185
+ fraction: true,
23186
+ canEdit,
23187
+ value: from.y,
23188
+ onChange: (y) => update({ from: { ...from, y } })
23189
+ }
23190
+ ),
23191
+ row.anchor === "rel" && row.to ? /* @__PURE__ */ jsxs(Fragment, { children: [
23192
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeTo") }),
23193
+ /* @__PURE__ */ jsx(
23194
+ NumberField,
23195
+ {
23196
+ fraction: true,
23197
+ canEdit,
23198
+ value: row.to.x,
23199
+ onChange: (x) => update({ to: { ...row.to, x } })
23200
+ }
23201
+ ),
23202
+ /* @__PURE__ */ jsx(
23203
+ NumberField,
23204
+ {
23205
+ fraction: true,
23206
+ canEdit,
23207
+ value: row.to.y,
23208
+ onChange: (y) => update({ to: { ...row.to, y } })
23209
+ }
23210
+ )
23211
+ ] }) : null,
23212
+ row.anchor === "abs" && row.ext ? /* @__PURE__ */ jsxs(Fragment, { children: [
23213
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeSize") }),
23214
+ /* @__PURE__ */ jsx(
23215
+ NumberField,
23216
+ {
23217
+ nonNegative: true,
23218
+ canEdit,
23219
+ value: row.ext.cx,
23220
+ onChange: (cx) => update({ ext: { ...row.ext, cx } })
23221
+ }
23222
+ ),
23223
+ /* @__PURE__ */ jsx(
23224
+ NumberField,
23225
+ {
23226
+ nonNegative: true,
23227
+ canEdit,
23228
+ value: row.ext.cy,
23229
+ onChange: (cy) => update({ ext: { ...row.ext, cy } })
23230
+ }
23231
+ )
23232
+ ] }) : null,
23233
+ /* @__PURE__ */ jsx(RotationField, { row, canEdit, onRotationPatch }),
23234
+ /* @__PURE__ */ jsx(FlipFields, { row, canEdit, onFlipPatch })
23235
+ ] });
23236
+ }
23237
+ const box = getChartUserShapeRowChartBox(userShapes, row.path);
23238
+ if (!box) {
23239
+ return null;
23240
+ }
23241
+ const patchBox = (next) => onBoxPatch(row.path, { from: box.from, to: box.to, ...next });
23242
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 text-[11px]", children: [
23243
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFrom") }),
23244
+ /* @__PURE__ */ jsx(
23245
+ NumberField,
23246
+ {
23247
+ fraction: true,
23248
+ canEdit,
23249
+ value: box.from.x,
23250
+ onChange: (x) => patchBox({ from: { ...box.from, x } })
23251
+ }
23252
+ ),
23253
+ /* @__PURE__ */ jsx(
23254
+ NumberField,
23255
+ {
23256
+ fraction: true,
23257
+ canEdit,
23258
+ value: box.from.y,
23259
+ onChange: (y) => patchBox({ from: { ...box.from, y } })
23260
+ }
23261
+ ),
23262
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeTo") }),
23263
+ /* @__PURE__ */ jsx(
23264
+ NumberField,
23265
+ {
23266
+ fraction: true,
23267
+ canEdit,
23268
+ value: box.to.x,
23269
+ onChange: (x) => patchBox({ to: { ...box.to, x } })
23270
+ }
23271
+ ),
23272
+ /* @__PURE__ */ jsx(
23273
+ NumberField,
23274
+ {
23275
+ fraction: true,
23276
+ canEdit,
23277
+ value: box.to.y,
23278
+ onChange: (y) => patchBox({ to: { ...box.to, y } })
23279
+ }
23280
+ ),
23281
+ /* @__PURE__ */ jsx(RotationField, { row, canEdit, onRotationPatch }),
23282
+ /* @__PURE__ */ jsx(FlipFields, { row, canEdit, onFlipPatch })
23283
+ ] });
23284
+ }
23285
+ var PATH_KEY = (path) => path.join(",");
22695
23286
  function ChartUserShapeOptions({
22696
23287
  chartData,
22697
23288
  canEdit,
@@ -22699,11 +23290,28 @@ function ChartUserShapeOptions({
22699
23290
  }) {
22700
23291
  const { t } = useTranslation();
22701
23292
  const shapes = chartData.userShapes;
22702
- const descriptors = listChartUserShapeDescriptors(shapes);
23293
+ const rows = listChartUserShapeRows(shapes);
22703
23294
  const kindLabel = (kind) => {
22704
23295
  const key = `pptx.chart.userShapeKind${kind.charAt(0).toUpperCase()}${kind.slice(1)}`;
22705
23296
  return t(key);
22706
23297
  };
23298
+ const update = (path, patch) => onUpdateChartData({ userShapes: withChartUserShapeRowUpdated(shapes, path, patch) });
23299
+ const updateBox = (path, box) => onUpdateChartData({ userShapes: withChartUserShapeRowChartBoxUpdated(shapes, path, box) });
23300
+ const updateRotation = (path, rotation) => onUpdateChartData({ userShapes: withChartUserShapeRowRotationUpdated(shapes, path, rotation) });
23301
+ const updateFlip = (path, flip) => onUpdateChartData({ userShapes: withChartUserShapeRowFlipUpdated(shapes, path, flip) });
23302
+ const addIntoGroup = (path) => {
23303
+ const transform = getChartUserShapeGroupTransform(shapes, path);
23304
+ if (!transform) {
23305
+ return;
23306
+ }
23307
+ onUpdateChartData({
23308
+ userShapes: withChartUserShapeGroupChildAdded(
23309
+ shapes,
23310
+ path,
23311
+ createDefaultChartUserShapeGroupChild(transform)
23312
+ )
23313
+ });
23314
+ };
22707
23315
  return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
22708
23316
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
22709
23317
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.chart.userShapes") }),
@@ -22720,99 +23328,120 @@ function ChartUserShapeOptions({
22720
23328
  }
22721
23329
  )
22722
23330
  ] }),
22723
- 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: [
22724
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px]", children: [
22725
- /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate", children: [
22726
- kindLabel(d.kind),
22727
- d.text ? ` - ${d.text}` : ""
22728
- ] }),
22729
- /* @__PURE__ */ jsx(
22730
- "button",
22731
- {
22732
- type: "button",
22733
- disabled: !canEdit,
22734
- "aria-label": t("pptx.chart.userShapeDelete"),
22735
- className: BTN2,
22736
- onClick: () => onUpdateChartData({ userShapes: withChartUserShapeRemoved(shapes, d.index) }),
22737
- children: "\u2715"
22738
- }
22739
- )
22740
- ] }),
22741
- d.editable ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[11px]", children: [
22742
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFrom") }),
22743
- /* @__PURE__ */ jsx(
22744
- "input",
22745
- {
22746
- type: "number",
22747
- step: "0.01",
22748
- min: 0,
22749
- max: 1,
22750
- disabled: !canEdit,
22751
- className: INPUT2,
22752
- value: d.from.x,
22753
- onChange: (e) => onUpdateChartData({
22754
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22755
- from: { ...d.from, x: Number(e.target.value) }
22756
- })
22757
- })
22758
- }
22759
- ),
22760
- /* @__PURE__ */ jsx(
22761
- "input",
22762
- {
22763
- type: "number",
22764
- step: "0.01",
22765
- min: 0,
22766
- max: 1,
22767
- disabled: !canEdit,
22768
- className: INPUT2,
22769
- value: d.from.y,
22770
- onChange: (e) => onUpdateChartData({
22771
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22772
- from: { ...d.from, y: Number(e.target.value) }
22773
- })
22774
- })
22775
- }
22776
- ),
22777
- d.anchor === "rel" && d.to ? /* @__PURE__ */ jsxs(Fragment, { children: [
22778
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeTo") }),
22779
- /* @__PURE__ */ jsx(
22780
- "input",
22781
- {
22782
- type: "number",
22783
- step: "0.01",
22784
- min: 0,
22785
- max: 1,
22786
- disabled: !canEdit,
22787
- className: INPUT2,
22788
- value: d.to.x,
22789
- onChange: (e) => onUpdateChartData({
22790
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22791
- to: { ...d.to, x: Number(e.target.value) }
23331
+ 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(
23332
+ "div",
23333
+ {
23334
+ "data-chart-user-shape-path": PATH_KEY(row.path),
23335
+ style: { marginLeft: row.depth * 12 },
23336
+ className: "space-y-1 rounded border border-border p-1.5",
23337
+ children: [
23338
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px]", children: [
23339
+ /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate", children: [
23340
+ kindLabel(row.kind),
23341
+ row.text ? ` - ${row.text}` : ""
23342
+ ] }),
23343
+ row.isGroup ? /* @__PURE__ */ jsx(
23344
+ "button",
23345
+ {
23346
+ type: "button",
23347
+ disabled: !canEdit,
23348
+ className: BTN2,
23349
+ onClick: () => addIntoGroup(row.path),
23350
+ children: t("pptx.chart.userShapeAddIntoGroup")
23351
+ }
23352
+ ) : null,
23353
+ /* @__PURE__ */ jsx(
23354
+ "button",
23355
+ {
23356
+ type: "button",
23357
+ disabled: !canEdit,
23358
+ "aria-label": t("pptx.chart.userShapeDelete"),
23359
+ className: BTN2,
23360
+ onClick: () => onUpdateChartData({
23361
+ userShapes: withChartUserShapeRowRemoved(shapes, row.path)
23362
+ }),
23363
+ children: "\u2715"
23364
+ }
23365
+ )
23366
+ ] }),
23367
+ row.editableVisuals ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[11px]", children: [
23368
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeText") }),
23369
+ /* @__PURE__ */ jsx(
23370
+ "input",
23371
+ {
23372
+ type: "text",
23373
+ "aria-label": t("pptx.chart.userShapeText"),
23374
+ disabled: !canEdit,
23375
+ className: INPUT2,
23376
+ value: row.text ?? "",
23377
+ onChange: (e) => onUpdateChartData({
23378
+ userShapes: withChartUserShapeRowTextUpdated(
23379
+ shapes,
23380
+ row.path,
23381
+ e.target.value
23382
+ )
22792
23383
  })
22793
- })
22794
- }
22795
- ),
23384
+ }
23385
+ )
23386
+ ] }) : null,
23387
+ row.editableVisuals ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[11px]", children: [
23388
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
23389
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeFill") }),
23390
+ /* @__PURE__ */ jsx(
23391
+ "input",
23392
+ {
23393
+ type: "color",
23394
+ "aria-label": t("pptx.chart.userShapeFill"),
23395
+ disabled: !canEdit,
23396
+ value: row.fill ?? "#ffffff",
23397
+ onChange: (e) => update(row.path, { fill: e.target.value })
23398
+ }
23399
+ )
23400
+ ] }),
23401
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
23402
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeStroke") }),
23403
+ /* @__PURE__ */ jsx(
23404
+ "input",
23405
+ {
23406
+ type: "color",
23407
+ "aria-label": t("pptx.chart.userShapeStroke"),
23408
+ disabled: !canEdit,
23409
+ value: row.stroke ?? "#000000",
23410
+ onChange: (e) => update(row.path, { stroke: e.target.value })
23411
+ }
23412
+ )
23413
+ ] })
23414
+ ] }) : null,
23415
+ row.editableAltText ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[11px]", children: [
23416
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.chart.userShapeAltText") }),
23417
+ /* @__PURE__ */ jsx(
23418
+ "input",
23419
+ {
23420
+ type: "text",
23421
+ "aria-label": t("pptx.chart.userShapeAltText"),
23422
+ disabled: !canEdit,
23423
+ className: INPUT2,
23424
+ value: row.altText ?? "",
23425
+ onChange: (e) => update(row.path, { altText: e.target.value })
23426
+ }
23427
+ )
23428
+ ] }) : null,
22796
23429
  /* @__PURE__ */ jsx(
22797
- "input",
23430
+ ChartUserShapePositionFields,
22798
23431
  {
22799
- type: "number",
22800
- step: "0.01",
22801
- min: 0,
22802
- max: 1,
22803
- disabled: !canEdit,
22804
- className: INPUT2,
22805
- value: d.to.y,
22806
- onChange: (e) => onUpdateChartData({
22807
- userShapes: withChartUserShapeUpdated(shapes, d.index, {
22808
- to: { ...d.to, y: Number(e.target.value) }
22809
- })
22810
- })
23432
+ row,
23433
+ userShapes: shapes,
23434
+ canEdit,
23435
+ onPatch: update,
23436
+ onBoxPatch: updateBox,
23437
+ onRotationPatch: updateRotation,
23438
+ onFlipPatch: updateFlip
22811
23439
  }
22812
23440
  )
22813
- ] }) : null
22814
- ] }) : /* @__PURE__ */ jsx("div", { className: "text-[10px] italic text-muted-foreground", children: t("pptx.chart.userShapeNotEditable") })
22815
- ] }, d.index)) })
23441
+ ]
23442
+ },
23443
+ PATH_KEY(row.path)
23444
+ )) })
22816
23445
  ] });
22817
23446
  }
22818
23447
  function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
@@ -22843,6 +23472,15 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
22843
23472
  },
22844
23473
  [chartData, replaceChartData]
22845
23474
  );
23475
+ const updateTitle = useCallback(
23476
+ (text) => {
23477
+ if (!chartData) {
23478
+ return;
23479
+ }
23480
+ updateChartData(collapseChartTitleRunsForEdit(chartData, text));
23481
+ },
23482
+ [chartData, updateChartData]
23483
+ );
22846
23484
  const updateStyle = useCallback(
22847
23485
  (patch) => {
22848
23486
  if (!chartData) {
@@ -23039,11 +23677,13 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
23039
23677
  {
23040
23678
  title,
23041
23679
  chartType,
23680
+ chartData,
23042
23681
  grouping,
23043
23682
  seriesCount: series.length,
23044
23683
  categoryCount: categories.length,
23045
23684
  canEdit,
23046
- onUpdateChartData: updateChartData
23685
+ onUpdateChartData: updateChartData,
23686
+ onTitleChange: updateTitle
23047
23687
  }
23048
23688
  ),
23049
23689
  /* @__PURE__ */ jsx(
@@ -23218,7 +23858,7 @@ function ConnectorArrowsSection({
23218
23858
  ["Start", "End"].map((end) => {
23219
23859
  const widthKey = end === "Start" ? "connectorStartArrowWidth" : "connectorEndArrowWidth";
23220
23860
  const lengthKey = end === "Start" ? "connectorStartArrowLength" : "connectorEndArrowLength";
23221
- return /* @__PURE__ */ jsxs(React19.Fragment, { children: [
23861
+ return /* @__PURE__ */ jsxs(React20.Fragment, { children: [
23222
23862
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
23223
23863
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t(END_LABEL_KEYS[end].width) }),
23224
23864
  /* @__PURE__ */ jsx(
@@ -24873,6 +25513,48 @@ function MediaPropertiesPanel({
24873
25513
  )
24874
25514
  ] });
24875
25515
  }
25516
+ function AccessibilityTextSection({
25517
+ selectedElement,
25518
+ canEdit,
25519
+ onUpdateElement
25520
+ }) {
25521
+ const { t } = useTranslation();
25522
+ const fields = getNonVisualDescriptionFields(selectedElement);
25523
+ if (!fields.showAltText && !fields.showTitle) {
25524
+ return null;
25525
+ }
25526
+ return /* @__PURE__ */ jsxs("div", { className: CARD, "data-pptx-accessibility-text": true, children: [
25527
+ /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.accessibility.heading", "Accessibility") }),
25528
+ fields.showAltText && /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
25529
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.elementAccessibility.altText") }),
25530
+ /* @__PURE__ */ jsx(
25531
+ "textarea",
25532
+ {
25533
+ rows: 2,
25534
+ disabled: !canEdit,
25535
+ placeholder: t("pptx.elementAccessibility.altTextPlaceholder"),
25536
+ className: cn(INPUT, "resize-none text-[11px]"),
25537
+ value: fields.altText,
25538
+ onChange: (e) => onUpdateElement({ altText: e.target.value })
25539
+ }
25540
+ )
25541
+ ] }),
25542
+ fields.showTitle && /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
25543
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.elementAccessibility.title") }),
25544
+ /* @__PURE__ */ jsx(
25545
+ "input",
25546
+ {
25547
+ type: "text",
25548
+ disabled: !canEdit,
25549
+ placeholder: t("pptx.elementAccessibility.titlePlaceholder"),
25550
+ className: cn(INPUT, "text-[11px]"),
25551
+ value: fields.title,
25552
+ onChange: (e) => onUpdateElement({ title: e.target.value })
25553
+ }
25554
+ )
25555
+ ] })
25556
+ ] });
25557
+ }
24876
25558
 
24877
25559
  // src/viewer/components/inspector/fill-stroke-options.ts
24878
25560
  var COMPOUND_LINE_OPTIONS2 = COMPOUND_LINE_OPTIONS;
@@ -26034,7 +26716,7 @@ function StrokeEffectsSection({
26034
26716
  ] }),
26035
26717
  EFFECT_CONFIGS.map((cfg) => {
26036
26718
  const on = cfg.isOn(style);
26037
- return /* @__PURE__ */ jsxs(React19.Fragment, { children: [
26719
+ return /* @__PURE__ */ jsxs(React20.Fragment, { children: [
26038
26720
  /* @__PURE__ */ jsxs("label", { className: `inline-flex items-center gap-2 text-foreground ${COL2}`, children: [
26039
26721
  /* @__PURE__ */ jsx(
26040
26722
  "input",
@@ -26902,7 +27584,7 @@ function TextWarpGallery({
26902
27584
  onUpdateTextStyle
26903
27585
  }) {
26904
27586
  const { t } = useTranslation();
26905
- const [expanded, setExpanded] = React19.useState(false);
27587
+ const [expanded, setExpanded] = React20.useState(false);
26906
27588
  const currentPreset = ts?.textWarpPreset || "textNoShape";
26907
27589
  return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded border border-border bg-card p-2 space-y-2", children: [
26908
27590
  /* @__PURE__ */ jsxs(
@@ -27104,6 +27786,14 @@ function ShapeTextPanels({
27104
27786
  canEdit,
27105
27787
  onUpdateTextStyle
27106
27788
  }
27789
+ ),
27790
+ shouldShowAccessibilitySection(selectedElement) && /* @__PURE__ */ jsx(
27791
+ AccessibilityTextSection,
27792
+ {
27793
+ selectedElement,
27794
+ canEdit,
27795
+ onUpdateElement
27796
+ }
27107
27797
  )
27108
27798
  ] });
27109
27799
  }
@@ -27545,7 +28235,7 @@ function SmartArtStyleControls({
27545
28235
  onChangeStyle
27546
28236
  }) {
27547
28237
  const { t } = useTranslation();
27548
- const translate = React19.useCallback((key) => t(key), [t]);
28238
+ const translate = React20.useCallback((key) => t(key), [t]);
27549
28239
  return /* @__PURE__ */ jsxs(Fragment, { children: [
27550
28240
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
27551
28241
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.smartart.colorScheme") }),
@@ -27600,9 +28290,9 @@ function SmartArtPropertiesPanel({
27600
28290
  const nodes = smartArtData.nodes ?? [];
27601
28291
  const layout = smartArtData.resolvedLayoutType;
27602
28292
  const topLevelCount = nodes.filter((n) => !n.parentId).length;
27603
- const inputRefs = React19.useRef(/* @__PURE__ */ new Map());
27604
- const pendingFocusId = React19.useRef(null);
27605
- React19.useEffect(() => {
28293
+ const inputRefs = React20.useRef(/* @__PURE__ */ new Map());
28294
+ const pendingFocusId = React20.useRef(null);
28295
+ React20.useEffect(() => {
27606
28296
  const id = pendingFocusId.current;
27607
28297
  if (id) {
27608
28298
  inputRefs.current.get(id)?.focus();
@@ -28438,13 +29128,252 @@ function TableCellFormattingPanel({
28438
29128
  ] })
28439
29129
  ] });
28440
29130
  }
29131
+ function TableStyleEditorFields({
29132
+ descriptor,
29133
+ canEdit,
29134
+ onEdit
29135
+ }) {
29136
+ const { t } = useTranslation();
29137
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
29138
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
29139
+ /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.tableStyleEditor.fillSection") }),
29140
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px]", children: [
29141
+ /* @__PURE__ */ jsx(
29142
+ "input",
29143
+ {
29144
+ type: "color",
29145
+ disabled: !canEdit,
29146
+ value: descriptor.fill.color.hex,
29147
+ onChange: (e) => onEdit({ kind: "fillColor", hex: e.target.value, ref: void 0 }),
29148
+ className: "h-6 w-8 rounded border border-border bg-transparent cursor-pointer"
29149
+ }
29150
+ ),
29151
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
29152
+ /* @__PURE__ */ jsx(
29153
+ "input",
29154
+ {
29155
+ type: "checkbox",
29156
+ disabled: !canEdit,
29157
+ checked: descriptor.fill.noFill,
29158
+ onChange: (e) => onEdit({ kind: "fillNone", noFill: e.target.checked })
29159
+ }
29160
+ ),
29161
+ t("pptx.tableStyleEditor.noFill")
29162
+ ] })
29163
+ ] }),
29164
+ /* @__PURE__ */ jsx(
29165
+ ThemeColorSwatchGrid,
29166
+ {
29167
+ prefix: "table-style-fill",
29168
+ disabled: !canEdit,
29169
+ selectedRef: descriptor.fill.color.ref,
29170
+ selectedHex: descriptor.fill.color.hex,
29171
+ onPick: (c) => onEdit({ kind: "fillColor", hex: c.hex, ref: c.ref })
29172
+ }
29173
+ )
29174
+ ] }),
29175
+ descriptor.hasTextAndBorders && /* @__PURE__ */ jsxs(Fragment, { children: [
29176
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
29177
+ /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.tableStyleEditor.textSection") }),
29178
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: ["bold", "italic", "underline"].map((flag) => /* @__PURE__ */ jsx(
29179
+ "button",
29180
+ {
29181
+ type: "button",
29182
+ disabled: !canEdit,
29183
+ className: `${BTN} ${descriptor.text[flag] ? "bg-accent" : ""}`,
29184
+ onClick: () => onEdit(textFlagEdit(flag, !descriptor.text[flag])),
29185
+ children: t(`pptx.format.${flag}`)
29186
+ },
29187
+ flag
29188
+ )) }),
29189
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-[11px]", children: [
29190
+ /* @__PURE__ */ jsx("span", { children: t("pptx.tableStyleEditor.textColor") }),
29191
+ /* @__PURE__ */ jsx(
29192
+ "input",
29193
+ {
29194
+ type: "color",
29195
+ disabled: !canEdit,
29196
+ value: descriptor.text.color.hex,
29197
+ onChange: (e) => onEdit({ kind: "textColor", hex: e.target.value, ref: void 0 }),
29198
+ className: "h-6 w-8 rounded border border-border bg-transparent cursor-pointer"
29199
+ }
29200
+ )
29201
+ ] }),
29202
+ /* @__PURE__ */ jsx(
29203
+ ThemeColorSwatchGrid,
29204
+ {
29205
+ prefix: "table-style-text",
29206
+ disabled: !canEdit,
29207
+ selectedRef: descriptor.text.color.ref,
29208
+ selectedHex: descriptor.text.color.hex,
29209
+ onPick: (c) => onEdit({ kind: "textColor", hex: c.hex, ref: c.ref })
29210
+ }
29211
+ )
29212
+ ] }),
29213
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
29214
+ /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.tableStyleEditor.bordersSection") }),
29215
+ TABLE_STYLE_BORDER_SIDES.map((side) => /* @__PURE__ */ jsx(
29216
+ BorderSideRow,
29217
+ {
29218
+ side,
29219
+ state: descriptor.borders[side],
29220
+ canEdit,
29221
+ onEdit
29222
+ },
29223
+ side
29224
+ ))
29225
+ ] })
29226
+ ] })
29227
+ ] });
29228
+ }
29229
+ function textFlagEdit(flag, value) {
29230
+ if (flag === "bold") {
29231
+ return { kind: "textBold", value };
29232
+ }
29233
+ if (flag === "italic") {
29234
+ return { kind: "textItalic", value };
29235
+ }
29236
+ return { kind: "textUnderline", value };
29237
+ }
29238
+ function BorderSideRow({
29239
+ side,
29240
+ state,
29241
+ canEdit,
29242
+ onEdit
29243
+ }) {
29244
+ const { t } = useTranslation();
29245
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-[11px]", children: [
29246
+ /* @__PURE__ */ jsx("span", { className: "w-28 shrink-0 text-muted-foreground", children: t(TABLE_STYLE_BORDER_SIDE_LABEL_KEYS[side]) }),
29247
+ /* @__PURE__ */ jsx(
29248
+ "input",
29249
+ {
29250
+ type: "color",
29251
+ disabled: !canEdit,
29252
+ value: state.color.hex,
29253
+ onChange: (e) => onEdit({ kind: "borderColor", side, hex: e.target.value, ref: void 0 }),
29254
+ className: "h-6 w-7 rounded border border-border bg-transparent cursor-pointer"
29255
+ }
29256
+ ),
29257
+ /* @__PURE__ */ jsx(
29258
+ "input",
29259
+ {
29260
+ type: "number",
29261
+ min: 0,
29262
+ max: 20,
29263
+ disabled: !canEdit,
29264
+ value: state.width,
29265
+ onChange: (e) => onEdit({ kind: "borderWidth", side, width: Number(e.target.value) }),
29266
+ className: `${INPUT} w-12`
29267
+ }
29268
+ ),
29269
+ /* @__PURE__ */ jsx(
29270
+ "select",
29271
+ {
29272
+ disabled: !canEdit,
29273
+ value: state.dash,
29274
+ onChange: (e) => onEdit({ kind: "borderDash", side, dash: e.target.value }),
29275
+ className: INPUT,
29276
+ children: TABLE_STYLE_DASH_PRESETS.map((dash) => /* @__PURE__ */ jsx("option", { value: dash, children: dash }, dash))
29277
+ }
29278
+ ),
29279
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1 shrink-0", children: [
29280
+ /* @__PURE__ */ jsx(
29281
+ "input",
29282
+ {
29283
+ type: "checkbox",
29284
+ disabled: !canEdit,
29285
+ checked: state.noFill,
29286
+ onChange: (e) => onEdit({ kind: "borderNone", side, noFill: e.target.checked })
29287
+ }
29288
+ ),
29289
+ t("pptx.tableStyleEditor.noBorder")
29290
+ ] })
29291
+ ] });
29292
+ }
29293
+ function TableStyleEditor({
29294
+ styleMap,
29295
+ styleId,
29296
+ canEdit,
29297
+ onStyleMapChange,
29298
+ onDeleteStyle,
29299
+ onAssignStyle,
29300
+ onClose
29301
+ }) {
29302
+ const { t } = useTranslation();
29303
+ const themeColorMap = useThemeColorMap();
29304
+ const [activeStyleId, setActiveStyleId] = useState(
29305
+ styleId ? normalizeTableStyleGuid(styleId) : ""
29306
+ );
29307
+ const [selectedPart, setSelectedPart] = useState("wholeTbl");
29308
+ const entry = activeStyleId ? styleMap?.[activeStyleId] : void 0;
29309
+ const descriptor = describeTableStyleEditor(entry, selectedPart, themeColorMap);
29310
+ function edit(fieldEdit) {
29311
+ if (!entry || !styleMap) {
29312
+ return;
29313
+ }
29314
+ const { entry: nextEntry } = applyTableStyleFieldEdit(entry, selectedPart, fieldEdit);
29315
+ onStyleMapChange({ ...styleMap, [nextEntry.styleId]: nextEntry });
29316
+ }
29317
+ function createFromCurrent() {
29318
+ const name = window.prompt(
29319
+ t("pptx.tableStyleEditor.newStyleNamePrompt"),
29320
+ entry ? `${entry.styleName ?? ""} Copy`.trim() : ""
29321
+ );
29322
+ if (!name) {
29323
+ return;
29324
+ }
29325
+ const nextMap = { ...styleMap ?? {} };
29326
+ const created = createTableStyleEntry(nextMap, { styleName: name, basedOn: entry });
29327
+ addTableStyleToMap(nextMap, created);
29328
+ onStyleMapChange(nextMap);
29329
+ setActiveStyleId(created.styleId);
29330
+ onAssignStyle?.(created.styleId);
29331
+ }
29332
+ function handleDelete() {
29333
+ if (!entry || !styleMap || !window.confirm(t("pptx.tableStyleEditor.deleteConfirm"))) {
29334
+ return;
29335
+ }
29336
+ const nextMap = { ...styleMap };
29337
+ deleteTableStyleFromMap(nextMap, entry.styleId);
29338
+ onStyleMapChange(nextMap);
29339
+ onDeleteStyle(entry.styleId);
29340
+ onClose();
29341
+ }
29342
+ return /* @__PURE__ */ jsxs("div", { className: CARD, "data-testid": "table-style-editor", children: [
29343
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
29344
+ /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.tableStyleEditor.title") }),
29345
+ /* @__PURE__ */ jsx("button", { type: "button", className: BTN, onClick: onClose, children: t("pptx.tableStyleEditor.close") })
29346
+ ] }),
29347
+ !entry && /* @__PURE__ */ jsx("div", { className: "text-[11px] text-muted-foreground", children: t("pptx.tableStyleEditor.noStyleSelected") }),
29348
+ entry && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: TABLE_STYLE_EDITOR_PARTS.map((part) => /* @__PURE__ */ jsx(
29349
+ "button",
29350
+ {
29351
+ type: "button",
29352
+ disabled: !canEdit,
29353
+ className: `${BTN} ${selectedPart === part.id ? "bg-accent" : ""}`,
29354
+ onClick: () => setSelectedPart(part.id),
29355
+ children: t(part.labelKey)
29356
+ },
29357
+ part.id
29358
+ )) }),
29359
+ descriptor && /* @__PURE__ */ jsx(TableStyleEditorFields, { descriptor, canEdit, onEdit: edit }),
29360
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 pt-1 border-t border-border", children: [
29361
+ /* @__PURE__ */ jsx("button", { type: "button", className: BTN, disabled: !canEdit, onClick: createFromCurrent, children: entry ? t("pptx.tableStyleEditor.newFromCurrent") : t("pptx.tableStyleEditor.newStyle") }),
29362
+ entry && /* @__PURE__ */ jsx("button", { type: "button", className: BTN, disabled: !canEdit, onClick: handleDelete, children: t("pptx.tableStyleEditor.deleteStyle") })
29363
+ ] })
29364
+ ] });
29365
+ }
28441
29366
  function TablePropertiesPanel({
28442
29367
  tableElement,
28443
29368
  canEdit,
28444
29369
  onUpdateElement,
28445
- tableEditorState
29370
+ tableEditorState,
29371
+ tableStyleMap,
29372
+ onTableStyleMapChange,
29373
+ onDeleteTableStyle
28446
29374
  }) {
28447
29375
  const { t } = useTranslation();
29376
+ const [showStyleEditor, setShowStyleEditor] = useState(false);
28448
29377
  const td = tableElement.tableData;
28449
29378
  if (!td) {
28450
29379
  return null;
@@ -28535,8 +29464,30 @@ function TablePropertiesPanel({
28535
29464
  ] })
28536
29465
  },
28537
29466
  preset.id
28538
- )) })
29467
+ )) }),
29468
+ onTableStyleMapChange && /* @__PURE__ */ jsx(
29469
+ "button",
29470
+ {
29471
+ type: "button",
29472
+ className: `${BTN} mt-1.5`,
29473
+ disabled: !canEdit,
29474
+ onClick: () => setShowStyleEditor((v) => !v),
29475
+ children: t("pptx.tableStyleEditor.editButton")
29476
+ }
29477
+ )
28539
29478
  ] }),
29479
+ showStyleEditor && onTableStyleMapChange && /* @__PURE__ */ jsx(
29480
+ TableStyleEditor,
29481
+ {
29482
+ styleMap: tableStyleMap,
29483
+ styleId: td.tableStyleId,
29484
+ canEdit,
29485
+ onStyleMapChange: onTableStyleMapChange,
29486
+ onDeleteStyle: (styleId) => onDeleteTableStyle?.(styleId),
29487
+ onAssignStyle: (styleId) => updateTableData(tableStyleAssignmentUpdate(styleId)),
29488
+ onClose: () => setShowStyleEditor(false)
29489
+ }
29490
+ ),
28540
29491
  /* @__PURE__ */ jsxs("div", { className: CARD, children: [
28541
29492
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
28542
29493
  /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.table.columnWidths") }),
@@ -28634,6 +29585,9 @@ function ElementInspectorBody({
28634
29585
  customShows,
28635
29586
  tableEditorState,
28636
29587
  mediaDataUrls,
29588
+ tableStyleMap,
29589
+ onTableStyleMapChange,
29590
+ onDeleteTableStyle,
28637
29591
  onUpdateElement,
28638
29592
  onUpdateElementStyle,
28639
29593
  onUpdateTextStyle,
@@ -28695,7 +29649,10 @@ function ElementInspectorBody({
28695
29649
  tableElement: selectedElement,
28696
29650
  canEdit,
28697
29651
  onUpdateElement,
28698
- tableEditorState
29652
+ tableEditorState,
29653
+ tableStyleMap,
29654
+ onTableStyleMapChange,
29655
+ onDeleteTableStyle
28699
29656
  }
28700
29657
  )
28701
29658
  ] }),
@@ -28914,7 +29871,7 @@ function CommentBody({ text, mentions, className }) {
28914
29871
  index
28915
29872
  ) : (
28916
29873
  // eslint-disable-next-line react/no-array-index-key -- segments are positional
28917
- /* @__PURE__ */ jsx(React19.Fragment, { children: segment.text }, index)
29874
+ /* @__PURE__ */ jsx(React20.Fragment, { children: segment.text }, index)
28918
29875
  )
28919
29876
  ) });
28920
29877
  }
@@ -30043,9 +31000,17 @@ function TransitionPreview({
30043
31000
  durationMs,
30044
31001
  transition.direction,
30045
31002
  transition.orient,
30046
- transition.spokes
31003
+ transition.spokes,
31004
+ transition.pattern
30047
31005
  ),
30048
- [transition.type, transition.direction, transition.orient, transition.spokes, durationMs]
31006
+ [
31007
+ transition.type,
31008
+ transition.direction,
31009
+ transition.orient,
31010
+ transition.spokes,
31011
+ transition.pattern,
31012
+ durationMs
31013
+ ]
30049
31014
  );
30050
31015
  const handlePlay = useCallback(() => {
30051
31016
  setPlaying(true);
@@ -30375,7 +31340,7 @@ function PresentationPropertiesPanel({
30375
31340
  onUpdateTagCollections
30376
31341
  }) {
30377
31342
  const { t } = useTranslation();
30378
- const handleTransitionChange = React19.useCallback(
31343
+ const handleTransitionChange = React20.useCallback(
30379
31344
  (updates) => {
30380
31345
  onUpdateSlide({
30381
31346
  transition: mergeSlideTransition(activeSlide?.transition, updates)
@@ -30734,6 +31699,9 @@ function InspectorPane(props) {
30734
31699
  onGetTemplateBackgroundColor,
30735
31700
  mediaDataUrls,
30736
31701
  theme,
31702
+ tableStyleMap,
31703
+ onTableStyleMapChange,
31704
+ onDeleteTableStyle,
30737
31705
  panelWidth
30738
31706
  } = props;
30739
31707
  const hasSelection = selectedElement !== null;
@@ -30816,6 +31784,9 @@ function InspectorPane(props) {
30816
31784
  customShows,
30817
31785
  tableEditorState,
30818
31786
  mediaDataUrls,
31787
+ tableStyleMap,
31788
+ onTableStyleMapChange,
31789
+ onDeleteTableStyle,
30819
31790
  onUpdateElement,
30820
31791
  onUpdateElementStyle,
30821
31792
  onUpdateTextStyle,
@@ -31549,9 +32520,17 @@ function PresentationTransitionOverlay({
31549
32520
  durationMs,
31550
32521
  transition.direction,
31551
32522
  transition.orient,
31552
- transition.spokes
32523
+ transition.spokes,
32524
+ transition.pattern
31553
32525
  ),
31554
- [transition.type, transition.direction, transition.orient, transition.spokes, durationMs]
32526
+ [
32527
+ transition.type,
32528
+ transition.direction,
32529
+ transition.orient,
32530
+ transition.spokes,
32531
+ transition.pattern,
32532
+ durationMs
32533
+ ]
31555
32534
  );
31556
32535
  const scale = useMemo(() => {
31557
32536
  if (resolvedStageScale !== null) {
@@ -34007,6 +34986,9 @@ function ViewerInspector({
34007
34986
  onGetTemplateBackgroundColor,
34008
34987
  mediaDataUrls,
34009
34988
  theme,
34989
+ tableStyleMap,
34990
+ onTableStyleMapChange,
34991
+ onDeleteTableStyle,
34010
34992
  panelWidth
34011
34993
  }) {
34012
34994
  const { t } = useTranslation();
@@ -34096,6 +35078,9 @@ function ViewerInspector({
34096
35078
  onGetTemplateBackgroundColor,
34097
35079
  mediaDataUrls,
34098
35080
  theme,
35081
+ tableStyleMap,
35082
+ onTableStyleMapChange,
35083
+ onDeleteTableStyle,
34099
35084
  panelWidth
34100
35085
  }
34101
35086
  )
@@ -34405,7 +35390,7 @@ function ViewerToolbarSection(props) {
34405
35390
  },
34406
35391
  [activeSlide, propertyHandlers]
34407
35392
  );
34408
- const scopedLayoutOptions = React19.useMemo(
35393
+ const scopedLayoutOptions = React20.useMemo(
34409
35394
  () => scopeLayoutOptionsToActiveSlide(s.layoutOptions, activeSlide),
34410
35395
  [s.layoutOptions, activeSlide]
34411
35396
  );
@@ -35608,7 +36593,10 @@ function PresentationStage({
35608
36593
  // the stage publishes its own size for those calc() offsets.
35609
36594
  "--pptx-slide-w": `${safeWidth}px`,
35610
36595
  "--pptx-slide-h": `${safeHeight}px`,
35611
- ...getReactSlideBackgroundStyle(activeSlide)
36596
+ ...getReactSlideBackgroundStyle(activeSlide, {
36597
+ widthPx: canvasSize.width,
36598
+ heightPx: canvasSize.height
36599
+ })
35612
36600
  },
35613
36601
  children: [
35614
36602
  /* @__PURE__ */ jsx(SlideBackgroundImageLayer, { slide: activeSlide }),
@@ -36238,10 +37226,26 @@ ${url}`)) {
36238
37226
  )
36239
37227
  );
36240
37228
  }
37229
+
37230
+ // src/viewer/hooks/useTableStyleMapHandlers.ts
37231
+ function useTableStyleMapHandlers(input) {
37232
+ const { tableStyleMap, setTableStyleMap, tableStylesToDelete, setTableStylesToDelete } = input;
37233
+ const handleTableStyleMapChange = (nextMap) => {
37234
+ const result = applyTableStyleMapChange({ tableStyleMap, tableStylesToDelete }, nextMap);
37235
+ setTableStyleMap(result.tableStyleMap);
37236
+ setTableStylesToDelete(result.tableStylesToDelete);
37237
+ };
37238
+ const handleDeleteTableStyle = (styleId) => {
37239
+ const result = applyTableStyleDelete({ tableStyleMap, tableStylesToDelete }, styleId);
37240
+ setTableStyleMap(result.tableStyleMap);
37241
+ setTableStylesToDelete(result.tableStylesToDelete);
37242
+ };
37243
+ return { handleTableStyleMapChange, handleDeleteTableStyle };
37244
+ }
36241
37245
  var AiChatPanel = lazy(async () => {
36242
37246
  const [{ useChat }, { default: Panel }] = await Promise.all([
36243
37247
  import('@ai-sdk/react'),
36244
- import('./AiChatPanel-L5QGWVZK.mjs')
37248
+ import('./AiChatPanel-II6VOOAL.mjs')
36245
37249
  ]);
36246
37250
  function BoundAiChatPanel(props) {
36247
37251
  return /* @__PURE__ */ jsx(Panel, { ...props, useChat });
@@ -37156,6 +38160,12 @@ function ViewerSidePanels(props) {
37156
38160
  s.setCanvasSize(slideSizeToCanvasPx(size));
37157
38161
  history.markDirty();
37158
38162
  };
38163
+ const { handleTableStyleMapChange, handleDeleteTableStyle } = useTableStyleMapHandlers({
38164
+ tableStyleMap: s.tableStyleMap,
38165
+ setTableStyleMap: s.setTableStyleMap,
38166
+ tableStylesToDelete: s.tableStylesToDelete,
38167
+ setTableStylesToDelete: s.setTableStylesToDelete
38168
+ });
37159
38169
  const effectiveSlide = mode === "master" ? masterPseudoSlide : activeSlide;
37160
38170
  const currentBuiltInTheme = BUILT_IN_THEMES.find(
37161
38171
  (candidate) => themeColorSchemesEqual(s.theme?.colorScheme, candidate.colorScheme)
@@ -37213,6 +38223,9 @@ function ViewerSidePanels(props) {
37213
38223
  onGetTemplateBackgroundColor: themeHandlers.handleGetTemplateBackgroundColor,
37214
38224
  mediaDataUrls: s.mediaDataUrls,
37215
38225
  theme: s.theme,
38226
+ tableStyleMap: s.tableStyleMap,
38227
+ onTableStyleMapChange: handleTableStyleMapChange,
38228
+ onDeleteTableStyle: handleDeleteTableStyle,
37216
38229
  panelWidth
37217
38230
  }
37218
38231
  ),
@@ -38027,8 +39040,24 @@ function MobileChromeOverlay(props) {
38027
39040
  )
38028
39041
  ] });
38029
39042
  }
38030
- function ReadOnlyBanner({ recommendation, onEditAnyway, onDismiss }) {
39043
+ function ReadOnlyBanner({
39044
+ recommendation,
39045
+ onEditAnyway,
39046
+ onDismiss,
39047
+ passwordPromptOpen = false,
39048
+ passwordError = null,
39049
+ checkingPassword = false,
39050
+ onSubmitPassword,
39051
+ onCancelPassword
39052
+ }) {
38031
39053
  const { t } = useTranslation();
39054
+ const [password, setPassword] = useState("");
39055
+ const inputId = useId();
39056
+ const errorId = useId();
39057
+ const handleSubmit = (event) => {
39058
+ event.preventDefault();
39059
+ onSubmitPassword?.(password);
39060
+ };
38032
39061
  return /* @__PURE__ */ jsxs(
38033
39062
  "div",
38034
39063
  {
@@ -38037,27 +39066,87 @@ function ReadOnlyBanner({ recommendation, onEditAnyway, onDismiss }) {
38037
39066
  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",
38038
39067
  children: [
38039
39068
  /* @__PURE__ */ jsx("span", { className: "flex-1 min-w-0", children: t(recommendation.messageKey) }),
38040
- /* @__PURE__ */ jsx(
38041
- "button",
39069
+ passwordPromptOpen ? /* @__PURE__ */ jsxs(
39070
+ "form",
38042
39071
  {
38043
- type: "button",
38044
- "data-testid": "pptx-readonly-edit-anyway",
38045
- onClick: onEditAnyway,
38046
- 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",
38047
- children: t("pptx.readOnly.editAnyway")
38048
- }
38049
- ),
38050
- /* @__PURE__ */ jsx(
38051
- "button",
38052
- {
38053
- type: "button",
38054
- "data-testid": "pptx-readonly-dismiss",
38055
- onClick: onDismiss,
38056
- "aria-label": t("pptx.readOnly.dismiss"),
38057
- 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",
38058
- children: t("pptx.readOnly.dismiss")
39072
+ "data-testid": "pptx-readonly-password-form",
39073
+ onSubmit: handleSubmit,
39074
+ className: "flex shrink-0 items-center gap-2",
39075
+ children: [
39076
+ /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "sr-only", children: t("pptx.readOnly.passwordLabel") }),
39077
+ /* @__PURE__ */ jsx(
39078
+ "input",
39079
+ {
39080
+ id: inputId,
39081
+ "data-testid": "pptx-readonly-password-input",
39082
+ type: "password",
39083
+ autoFocus: true,
39084
+ value: password,
39085
+ disabled: checkingPassword,
39086
+ onChange: (event) => setPassword(event.target.value),
39087
+ placeholder: t("pptx.readOnly.passwordPlaceholder"),
39088
+ "aria-invalid": passwordError !== null,
39089
+ "aria-describedby": passwordError !== null ? errorId : void 0,
39090
+ 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"
39091
+ }
39092
+ ),
39093
+ /* @__PURE__ */ jsx(
39094
+ "button",
39095
+ {
39096
+ type: "submit",
39097
+ "data-testid": "pptx-readonly-unlock",
39098
+ disabled: checkingPassword,
39099
+ 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",
39100
+ children: t("pptx.readOnly.unlock")
39101
+ }
39102
+ ),
39103
+ /* @__PURE__ */ jsx(
39104
+ "button",
39105
+ {
39106
+ type: "button",
39107
+ "data-testid": "pptx-readonly-password-cancel",
39108
+ onClick: onCancelPassword,
39109
+ 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",
39110
+ children: t("pptx.common.cancel")
39111
+ }
39112
+ ),
39113
+ passwordError !== null && /* @__PURE__ */ jsx(
39114
+ "span",
39115
+ {
39116
+ id: errorId,
39117
+ role: "alert",
39118
+ "data-testid": "pptx-readonly-password-error",
39119
+ className: "shrink-0 text-[11px] text-red-700 dark:text-red-300",
39120
+ children: t(
39121
+ passwordError === "wrong-password" ? "pptx.readOnly.wrongPassword" : "pptx.readOnly.unsupportedAlgorithm"
39122
+ )
39123
+ }
39124
+ )
39125
+ ]
38059
39126
  }
38060
- )
39127
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
39128
+ /* @__PURE__ */ jsx(
39129
+ "button",
39130
+ {
39131
+ type: "button",
39132
+ "data-testid": "pptx-readonly-edit-anyway",
39133
+ onClick: onEditAnyway,
39134
+ 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",
39135
+ children: t("pptx.readOnly.editAnyway")
39136
+ }
39137
+ ),
39138
+ /* @__PURE__ */ jsx(
39139
+ "button",
39140
+ {
39141
+ type: "button",
39142
+ "data-testid": "pptx-readonly-dismiss",
39143
+ onClick: onDismiss,
39144
+ "aria-label": t("pptx.readOnly.dismiss"),
39145
+ 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",
39146
+ children: t("pptx.readOnly.dismiss")
39147
+ }
39148
+ )
39149
+ ] })
38061
39150
  ]
38062
39151
  }
38063
39152
  );
@@ -38991,9 +40080,13 @@ function useAiBridge(input) {
38991
40080
  presentationProperties: live.presentationProperties,
38992
40081
  customProperties: live.customProperties,
38993
40082
  coreProperties: live.coreProperties,
38994
- appProperties: live.appProperties
40083
+ appProperties: live.appProperties,
40084
+ viewProperties: live.viewProperties,
40085
+ tableStyleMap: live.tableStyleMap,
40086
+ tableStylesDefaultId: live.tableStylesDefaultId,
40087
+ tags: live.tagCollections
38995
40088
  });
38996
- const differs = (a, b) => JSON.stringify(a) !== JSON.stringify(b);
40089
+ const differs = deckDataFieldChanged;
38997
40090
  return {
38998
40091
  getDeckMeta() {
38999
40092
  const live = ref.current;
@@ -39067,6 +40160,19 @@ function useAiBridge(input) {
39067
40160
  if (differs(before.appProperties, after.appProperties)) {
39068
40161
  live.setAppProperties(after.appProperties);
39069
40162
  }
40163
+ if (differs(before.viewProperties, after.viewProperties)) {
40164
+ live.setViewProperties(after.viewProperties);
40165
+ }
40166
+ if (differs(before.tableStyleMap, after.tableStyleMap)) {
40167
+ live.setTableStyleMap(after.tableStyleMap);
40168
+ }
40169
+ if (differs(before.tableStylesDefaultId, after.tableStylesDefaultId)) {
40170
+ live.setTableStylesDefaultId(after.tableStylesDefaultId);
40171
+ }
40172
+ const nextTags = after.tags ?? before.tags ?? [];
40173
+ if (differs(before.tags, nextTags)) {
40174
+ live.setTagCollections(nextTags);
40175
+ }
39070
40176
  live.markDirty();
39071
40177
  },
39072
40178
  getFocusedTargets() {
@@ -39835,6 +40941,7 @@ var PowerPointViewer = forwardRef(
39835
40941
  // http(s) image sources actually load.
39836
40942
  allowExternalImages: viewerOptions.trust.allowExternalContent,
39837
40943
  setReadOnlyRecommendation: readOnlyRec.setRecommendation,
40944
+ setModifyVerifier: readOnlyRec.setModifyVerifier,
39838
40945
  setCompatToasts: compatToastsState.setToasts,
39839
40946
  canEdit,
39840
40947
  promptKeepInkAnnotations: viewerOptions.advanced.slideShowPromptKeepInkAnnotations,
@@ -39960,12 +41067,20 @@ var PowerPointViewer = forwardRef(
39960
41067
  customProperties: state.customProperties,
39961
41068
  coreProperties: state.coreProperties,
39962
41069
  appProperties: state.appProperties,
41070
+ viewProperties: state.viewProperties,
41071
+ tableStyleMap: state.tableStyleMap,
41072
+ tableStylesDefaultId: state.tableStylesDefaultId,
41073
+ tagCollections: state.tagCollections,
39963
41074
  setCanvasSize: state.setCanvasSize,
39964
41075
  setSections: state.setSections,
39965
41076
  setPresentationProperties: state.setPresentationProperties,
39966
41077
  setCustomProperties: state.setCustomProperties,
39967
41078
  setCoreProperties: state.setCoreProperties,
39968
41079
  setAppProperties: state.setAppProperties,
41080
+ setViewProperties: state.setViewProperties,
41081
+ setTableStyleMap: state.setTableStyleMap,
41082
+ setTableStylesDefaultId: state.setTableStylesDefaultId,
41083
+ setTagCollections: state.setTagCollections,
39969
41084
  setSlides: state.setSlides,
39970
41085
  setActiveSlideIndex: state.setActiveSlideIndex,
39971
41086
  applySelection: editorOps.ops.applySelection,
@@ -40056,7 +41171,12 @@ var PowerPointViewer = forwardRef(
40056
41171
  {
40057
41172
  recommendation: readOnlyRec.recommendation,
40058
41173
  onEditAnyway: readOnlyRec.editAnyway,
40059
- onDismiss: readOnlyRec.dismiss
41174
+ onDismiss: readOnlyRec.dismiss,
41175
+ passwordPromptOpen: readOnlyRec.passwordPromptOpen,
41176
+ passwordError: readOnlyRec.passwordError,
41177
+ checkingPassword: readOnlyRec.checkingPassword,
41178
+ onSubmitPassword: readOnlyRec.submitPassword,
41179
+ onCancelPassword: readOnlyRec.cancelPasswordPrompt
40060
41180
  }
40061
41181
  ),
40062
41182
  /* @__PURE__ */ jsx(
@@ -40343,7 +41463,29 @@ var PowerPointViewer = forwardRef(
40343
41463
  content,
40344
41464
  loadVersion,
40345
41465
  loadOrigin,
40346
- livePatcher: state.livePatcher
41466
+ livePatcher: state.livePatcher,
41467
+ deckSaveState: {
41468
+ headerFooter: state.headerFooter,
41469
+ presentationProperties: state.presentationProperties,
41470
+ viewProperties: state.viewProperties,
41471
+ customShows: state.customShows,
41472
+ sections: state.sections,
41473
+ coreProperties: state.coreProperties,
41474
+ appProperties: state.appProperties,
41475
+ customProperties: state.customProperties,
41476
+ tagCollections: state.tagCollections,
41477
+ slideMasters: state.slideMasters,
41478
+ notesMaster: state.notesMaster,
41479
+ handoutMaster: state.handoutMaster,
41480
+ slideSize: resolveSlideSizeSelection({
41481
+ current: state.slideSizeEmu,
41482
+ canvas: canvasSize
41483
+ }).size,
41484
+ tableStyleMap: state.tableStyleMap,
41485
+ tableStylesDefaultId: state.tableStylesDefaultId,
41486
+ tableStylesToDelete: state.tableStylesToDelete,
41487
+ embedFonts: dialogs.embedFontsEnabled
41488
+ }
40347
41489
  }
40348
41490
  ),
40349
41491
  /* @__PURE__ */ jsx(
@@ -40384,7 +41526,8 @@ function CollaborationDocumentSync({
40384
41526
  content,
40385
41527
  loadVersion,
40386
41528
  loadOrigin,
40387
- livePatcher
41529
+ livePatcher,
41530
+ deckSaveState
40388
41531
  }) {
40389
41532
  const collab = useCollaboration();
40390
41533
  const contentRef = useRef(content);
@@ -40396,6 +41539,9 @@ function CollaborationDocumentSync({
40396
41539
  }
40397
41540
  return bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
40398
41541
  }, []);
41542
+ const deckSaveStateRef = useRef(deckSaveState);
41543
+ deckSaveStateRef.current = deckSaveState;
41544
+ const getSaveOptions = useCallback(() => buildDeckSaveOptions(deckSaveStateRef.current), []);
40399
41545
  useYjsDocumentSync({
40400
41546
  doc: collab?.doc ?? null,
40401
41547
  slides,
@@ -40405,6 +41551,7 @@ function CollaborationDocumentSync({
40405
41551
  isSynced: collab?.synced ?? true,
40406
41552
  config,
40407
41553
  getSourceBytes,
41554
+ getSaveOptions,
40408
41555
  loadVersion,
40409
41556
  loadOrigin
40410
41557
  });