pptx-react-viewer 4.49.0 → 4.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/dist/{AiChatPanel-NKTBHT5B.mjs → AiChatPanel-VJV5OEG2.mjs} +1 -1
  3. package/dist/AiChatPanel-VJV5OEG2.mjs.br +0 -0
  4. package/dist/AiChatPanel-VJV5OEG2.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-S4WNQCY4.js → AiChatPanel-WYAL24DX.js} +9 -9
  6. package/dist/AiChatPanel-WYAL24DX.js.br +0 -0
  7. package/dist/AiChatPanel-WYAL24DX.js.gz +0 -0
  8. package/dist/{chunk-2ZXXHNNR.js → chunk-4OF7X5EE.js} +1669 -3046
  9. package/dist/chunk-4OF7X5EE.js.br +0 -0
  10. package/dist/chunk-4OF7X5EE.js.gz +0 -0
  11. package/dist/{chunk-YKLL2Z33.mjs → chunk-5JJQLK7N.mjs} +452 -1829
  12. package/dist/chunk-5JJQLK7N.mjs.br +0 -0
  13. package/dist/chunk-5JJQLK7N.mjs.gz +0 -0
  14. package/dist/{chunk-PFV626ED.mjs → chunk-77IXTLKU.mjs} +3 -4
  15. package/dist/chunk-77IXTLKU.mjs.br +0 -0
  16. package/dist/chunk-77IXTLKU.mjs.gz +0 -0
  17. package/dist/{chunk-ME5QRTVS.js → chunk-D5NXYXPP.js} +740 -1188
  18. package/dist/chunk-D5NXYXPP.js.br +0 -0
  19. package/dist/chunk-D5NXYXPP.js.gz +0 -0
  20. package/dist/chunk-DDJ634MV.js.br +0 -0
  21. package/dist/chunk-DDJ634MV.js.gz +0 -0
  22. package/dist/{chunk-JAI42EXQ.js → chunk-JWNBTFZZ.js} +0 -6
  23. package/dist/chunk-JWNBTFZZ.js.br +0 -0
  24. package/dist/chunk-JWNBTFZZ.js.gz +0 -0
  25. package/dist/{chunk-Z62JFXMZ.mjs → chunk-QHGEPW5G.mjs} +563 -1011
  26. package/dist/chunk-QHGEPW5G.mjs.br +0 -0
  27. package/dist/chunk-QHGEPW5G.mjs.gz +0 -0
  28. package/dist/chunk-QIUK53JR.mjs.br +0 -0
  29. package/dist/chunk-QIUK53JR.mjs.gz +0 -0
  30. package/dist/i18n/de.cjs +1138 -221
  31. package/dist/i18n/de.cjs.br +0 -0
  32. package/dist/i18n/de.cjs.gz +0 -0
  33. package/dist/i18n/de.mjs +1138 -221
  34. package/dist/i18n/de.mjs.br +0 -0
  35. package/dist/i18n/de.mjs.gz +0 -0
  36. package/dist/i18n/es.cjs +1138 -221
  37. package/dist/i18n/es.cjs.br +0 -0
  38. package/dist/i18n/es.cjs.gz +0 -0
  39. package/dist/i18n/es.mjs +1138 -221
  40. package/dist/i18n/es.mjs.br +0 -0
  41. package/dist/i18n/es.mjs.gz +0 -0
  42. package/dist/i18n/fr.cjs +1138 -221
  43. package/dist/i18n/fr.cjs.br +0 -0
  44. package/dist/i18n/fr.cjs.gz +0 -0
  45. package/dist/i18n/fr.mjs +1138 -221
  46. package/dist/i18n/fr.mjs.br +0 -0
  47. package/dist/i18n/fr.mjs.gz +0 -0
  48. package/dist/i18n/zh-CN.cjs +1138 -221
  49. package/dist/i18n/zh-CN.cjs.br +0 -0
  50. package/dist/i18n/zh-CN.cjs.gz +0 -0
  51. package/dist/i18n/zh-CN.mjs +1138 -221
  52. package/dist/i18n/zh-CN.mjs.br +0 -0
  53. package/dist/i18n/zh-CN.mjs.gz +0 -0
  54. package/dist/index.d.ts +5 -15
  55. package/dist/index.js +24 -24
  56. package/dist/index.js.br +0 -0
  57. package/dist/index.js.gz +0 -0
  58. package/dist/index.mjs +3 -3
  59. package/dist/index.mjs.br +0 -0
  60. package/dist/index.mjs.gz +0 -0
  61. package/dist/internals.d.ts +105 -94
  62. package/dist/internals.js +81 -81
  63. package/dist/internals.js.br +0 -0
  64. package/dist/internals.js.gz +0 -0
  65. package/dist/internals.mjs +2 -2
  66. package/dist/internals.mjs.br +0 -0
  67. package/dist/internals.mjs.gz +0 -0
  68. package/dist/pptx-viewer-canvas.css +1 -1
  69. package/dist/pptx-viewer-canvas.css.br +0 -0
  70. package/dist/pptx-viewer-canvas.css.gz +0 -0
  71. package/dist/pptx-viewer.css +1 -1
  72. package/dist/pptx-viewer.css.br +0 -0
  73. package/dist/pptx-viewer.css.gz +0 -0
  74. package/dist/viewer/index.d.ts +7 -12
  75. package/dist/viewer/index.js +19 -19
  76. package/dist/viewer/index.js.br +0 -0
  77. package/dist/viewer/index.js.gz +0 -0
  78. package/dist/viewer/index.mjs +3 -3
  79. package/dist/viewer/index.mjs.br +0 -0
  80. package/dist/viewer/index.mjs.gz +0 -0
  81. package/dist/{y-webrtc-2H7UYAQD.mjs → y-webrtc-HRGGVQZH.mjs} +1 -1
  82. package/dist/y-webrtc-HRGGVQZH.mjs.br +0 -0
  83. package/dist/y-webrtc-HRGGVQZH.mjs.gz +0 -0
  84. package/dist/{y-webrtc-DVPQNFLL.js → y-webrtc-QVVT5PCK.js} +124 -124
  85. package/dist/y-webrtc-QVVT5PCK.js.br +0 -0
  86. package/dist/y-webrtc-QVVT5PCK.js.gz +0 -0
  87. package/dist/{y-websocket-WORVRRQS.mjs → y-websocket-46M6UFI7.mjs} +1 -1
  88. package/dist/y-websocket-46M6UFI7.mjs.br +0 -0
  89. package/dist/y-websocket-46M6UFI7.mjs.gz +0 -0
  90. package/dist/{y-websocket-TN4OKPXQ.js → y-websocket-EDOMWMAD.js} +78 -78
  91. package/dist/y-websocket-EDOMWMAD.js.br +0 -0
  92. package/dist/y-websocket-EDOMWMAD.js.gz +0 -0
  93. package/package.json +3 -3
  94. package/dist/AiChatPanel-NKTBHT5B.mjs.br +0 -0
  95. package/dist/AiChatPanel-NKTBHT5B.mjs.gz +0 -0
  96. package/dist/AiChatPanel-S4WNQCY4.js.br +0 -0
  97. package/dist/AiChatPanel-S4WNQCY4.js.gz +0 -0
  98. package/dist/chunk-2ZXXHNNR.js.br +0 -0
  99. package/dist/chunk-2ZXXHNNR.js.gz +0 -0
  100. package/dist/chunk-3VVZGHHY.mjs.br +0 -0
  101. package/dist/chunk-3VVZGHHY.mjs.gz +0 -0
  102. package/dist/chunk-JAI42EXQ.js.br +0 -0
  103. package/dist/chunk-JAI42EXQ.js.gz +0 -0
  104. package/dist/chunk-ME5QRTVS.js.br +0 -0
  105. package/dist/chunk-ME5QRTVS.js.gz +0 -0
  106. package/dist/chunk-NUNDT6EL.js.br +0 -0
  107. package/dist/chunk-NUNDT6EL.js.gz +0 -0
  108. package/dist/chunk-PFV626ED.mjs.br +0 -0
  109. package/dist/chunk-PFV626ED.mjs.gz +0 -0
  110. package/dist/chunk-YKLL2Z33.mjs.br +0 -0
  111. package/dist/chunk-YKLL2Z33.mjs.gz +0 -0
  112. package/dist/chunk-Z62JFXMZ.mjs.br +0 -0
  113. package/dist/chunk-Z62JFXMZ.mjs.gz +0 -0
  114. package/dist/y-webrtc-2H7UYAQD.mjs.br +0 -0
  115. package/dist/y-webrtc-2H7UYAQD.mjs.gz +0 -0
  116. package/dist/y-webrtc-DVPQNFLL.js.br +0 -0
  117. package/dist/y-webrtc-DVPQNFLL.js.gz +0 -0
  118. package/dist/y-websocket-TN4OKPXQ.js.br +0 -0
  119. package/dist/y-websocket-TN4OKPXQ.js.gz +0 -0
  120. package/dist/y-websocket-WORVRRQS.mjs.br +0 -0
  121. package/dist/y-websocket-WORVRRQS.mjs.gz +0 -0
  122. package/dist/{chunk-NUNDT6EL.js → chunk-DDJ634MV.js} +436 -436
  123. package/dist/{chunk-3VVZGHHY.mjs → chunk-QIUK53JR.mjs} +436 -436
@@ -1,15 +1,15 @@
1
- import { StaticElementRenderer, useModalDismissDrag, useToolbarVisibility, useViewerOptionsContext, InlineCollaborationContext, SlideBackgroundImageLayer, ElementRenderer, withDisplayName, useCollaboration, ResizeHandles, imgSrc, renderStrokeView, useViewerOptions, useReadOnlyRecommendationState, useCompatibilityToastsState, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useViewPreferencesSync, useLayoutSwitching, Rendering3DFlagsContext, CollaborationProvider, ChartFormatContext, useChartFormatContext, safePrompt, scopeLayoutOptionsToActiveSlide, createReviewCommentsHost, ChartPartSelectionProvider, useKeyboardInsets, ViewerOptionsStoreContext, ViewerOptionsContext, useReportOnChange, useCollaborationDocumentSync, useFollowMode, useBroadcastFollower, useSheetDismissDrag, playAnimationSound, useVirtualizedSlides, useSwipeNavigation, PresentationTransitionOverlay, RemoteSelectionOverlay, CollaborationCursorOverlay, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, SmartArtRenderer, downloadBlob, useChartPartSelection, DUOTONE_PRESETS, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES, resolveSmartArtDataPalette } from './chunk-Z62JFXMZ.mjs';
2
- import { cn, getShapeAdjustmentHandleDescriptors, isConnectorOrLineElement, TOOLBAR_SECTIONS, GRID_SIZE, getElementTransformWithoutRotation, getElementTransform, MIN_ELEMENT_SIZE, hasCopyableFormat, DEFAULT_SECTION_GROUP_ID, safeOpenUrl, isPpactionUrl, parsePpactionUrl, SHORTCUT_REFERENCE_ITEMS, isUrlSafe, computeHandoutLayout, getPrintableArea, generateNoteLineCount, normalizeHexColor, UNGROUPED_SECTION_ID, SLIDE_NAV_THUMBNAIL_WIDTH, SLIDE_TRANSITION_OPTIONS, getElementLabel, TABLE_STYLE_PRESETS, SHAPE_PRESETS, sanitizeGradientStops, formatCommentTimestamp, ANIMATION_PRESET_OPTIONS, clampCropValue, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, DEFAULT_FILL_COLOR, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, getPatternSvg, DEFAULT_STROKE_COLOR, STROKE_DASH_OPTIONS, openNativeEyeDropper } from './chunk-PFV626ED.mjs';
3
- import { ANIMATION_DIRECTION_LABEL_KEYS, buildQuickStylesGallery, buildSlideTemplateContent, SLIDE_TEMPLATES, homeLaunchers, attachRibbonOverflow, isPanelVisible, parentSelection, slideSpaceElement, isGroupMember, motionPathFor, setMotionPath, RULER_THICKNESS, shouldShowElementHandles, deviceStrokeStageStyle, activateModalFocus, visibleContextualTabs, resolveActiveRibbonTab, visibleRibbonAddIns, isDialogAvailable, resolveScreenTip, RIBBON_ADD_IN_TAB_ATTR, contextualTabLabelKey, RIBBON_CONTEXTUAL_TAB_ATTR, buildTabRowActionsState, isFeatureEnabled, TAB_ROW_ACTION_CLASSES, tabRowActionsAttributes, buildTitleBarState, backstageNavEntries, BACKSTAGE_NAV, listBackstageRecentFiles, BACKSTAGE_BACK_CLASSES, BACKSTAGE_NAV_CLASSES, DEFAULT_INSERT_CHART_KIND, FREEFORM_TOOL_IDS, isDrawingToolVisible, textFontSizePtToPx, withHomeGalleries, drawingHomeControls, homeGalleryControls, homeGalleryApply, shapeOutlineChange, shapeFillChange, editingHomeControls, arrangeHomeControls, arrangePainterHomeControls, arrangeAlignAction, DESIGN_RIBBON_GROUPS, FIXED_TAB_GALLERIES, DESIGN_RIBBON_COMMANDS, designCommandState, CONTEXTUAL_TAB_GROUPS, attachEditorImagePaste, authorConnectorBetweenSites, findEraserHitElementId, generateTicks, rulerDragToGuidePosition, resolveElementInteractivity, buildChartQuickActionsDescriptor, applyChartElementToggle, CHART_QUICK_ACTION_BUTTON_SIZE, applyChartStylePreset, hideChartSeries, restoreFilteredSeries, buildCropOverlay, CROP_HANDLE_ARIA_KEY, getActiveXControlOverlayView, buildCommentMarkers, COMMENT_MARKER_SIZE, collectConnectorSiteCandidates, getConnectorEndpointHandles, findConnectorSiteNear, motionPathToSvgD, motionPathEndPixel, isEditableMotionPath, setMotionPathEnd, canEditElementPoints, getSlideBackgroundStyle, resolveCollaborationConfig, resolveViewerRootOptions, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, isEditingAllowed, resolveAutosaveActivation, viewerOptionsToPreferences, applyPreferenceToOptions, resolveHistoryDepth, attachViewerHyperlinks, shouldConfirmExternalHyperlink, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, saveFailureMessage, withSaveFailureToast, createSlidePackageClipboard, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, RIBBON_SCOPE_ATTR, resolve3DRenderingFlags, resolveSlideSizeSelection, EMPTY_RESOLVED_CUSTOMIZATION, getRegionRenderer, ViewerRegionHost, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, customizeBackstageCards, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, clipboardHomeControls, slidesHomeControls, resolveInsertSlideLayout, resolveDefaultFontFamily, textFontSizePxToPt, getInlineEditorSelectionResult, selectedParagraphBulletKind, elementBulletKind, selectionBulletKind, fontPickerHomeControls, fontHomeControls, nextToggleValue, RIBBON_GROUP_ATTR, paragraphHomeAlign, paragraphHomeControls, paragraphHomeAction, arrangeShapeHomeControls, strokeWidthOf, canSetStrokeWidth, canUngroupSelection, canGroupSelection, buildRibbonGallery, readRibbonTransitionDraft, SLIDE_SHOW_COMMAND_GROUPS, buildRecordRibbon, trackActiveComment, commentCounts, findCommentLocation, buildReviewRibbon, buildHelpRibbon, galleryTextLabel, pictureSizeHomeControls, chartSelectionHomeControls, dispatchChartSelectionRequest, buildFreeformShapeElement, buildLiveInkStrokeView, beginCropDrag, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, FreeformToolSession, attachOverlayKeyboard, EditPointsSession, EDIT_POINTS_STYLE, themeToCssVars, createCustomizationController, resolveEffectiveHiddenActions, pruneExpiredAutosaveSnapshots, createDeckStyleHost, galleryDeckView, tableLayoutCells, resetChartFormatTarget, masterViewCrudActions, applyMasterViewCrudAction, masterViewCrudFailureKey, EDITOR_CHROME_CSS, ribbonCustomizationCss, applyMotionPathPreset, resetSlideLayoutPath, templateSchemeFromTheme, createBackstagePresentation, playFeedbackSound, shouldDiscardAutosaveOnSuccessfulSave, deleteAutosaveSnapshot, dispatchReadOnlyBannerIntent, readOnlyBannerState, buildFieldSubstitutionContext, setMasterViewBackgroundColor, canUseClipboard, runProgramNoticeStackStyle, observeElementHeight, printPropertiesFrameSlides, printPropertiesSlidesPerPage, PASTE_SPECIAL_OPTIONS, findCanvasElementNode, isHeaderFooterDateTextVisible, isHeaderFooterHeaderTextVisible, isHeaderFooterFooterTextVisible, getDensePanelTouchTargetPx, shouldStickyActionRow, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, MIN_TOUCH_TARGET_PX, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, getSelectionTextStyleFlags, TEXT_DECORATION_FLAGS, dispatchCropRequest, applyRibbonGalleryItem, ribbonTransitionsDraftPatch, ribbonTransitionUpdates, ribbonTransitionsSoundChange, ribbonTransitionStockSoundUrl, playSlideTransitionPreview, playAnimationRibbonPreview, SLIDE_SHOW_OPTIONS, createViewerOptionsStore, subtitleSettingsFromOptions, subtitleSettingsLabels, isReviewCommentCommand, runReviewCommentCommand, hasTiltData, RULER_FONT_SIZE, toElementAxes, dragCropHandle, panCropImage, clientToSlidePoint, EDIT_POINTS_TARGET_ATTR, pushRecentColor, mruColorsPatch, shouldClearAutosaveCacheOnClose, clearAutosaveSnapshots, canCropElement, cropSessionChanged, cancelCropUpdate, startCropSession, editorThumbnailWidth, EDITOR_THUMBNAIL_WIDTH, masterViewBackgroundColor, resolvePresentationAction, isPresentationAdvanceClick, toggleBlackboard, visibleTemplateElements, PRESENT_TOOLBAR_CLASSES, resolveEditPointsAvailability, isCurrentLayout, EXPANDED_MAX_HEIGHT, statusBarState, statusBarViewMode, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, resolveDefaultPrintSettings, HANDOUT_OPTIONS, bindPptxOptionsDialog, optionsBlockSlot, optionsPaneSlot, DEFAULT_QUICK_ACCESS_COMMAND_IDS, AI_OPTIONS_CATEGORY, buildCollaborationShareUrl, buildActiveSessionUsers, slideClipboardLabels, sorterPasteInsertAt, SORTER_MIN_ZOOM, SORTER_ZOOM_STEP, SORTER_MAX_ZOOM, canGoPrevious, formatSlideCounter, READING_VIEW_COUNTER_ATTR, canGoNext, READING_VIEW_ATTR, listenForOutlineViewDismiss, OUTLINE_LEVEL_ATTR, OUTLINE_SLIDE_ATTR, OUTLINE_ROW_ATTR, OUTLINE_VIEW_ATTR, mobileElapsedSince, nextPresentedSlide, presenterPrevDisabled, presenterNextDisabled, formatMobileElapsed, mobileSlideCounter, presenterPaneAdvancesOnClick, presenterTimerProgress, PRESENTER_CONSOLE_CLASSES, formatElapsed, createCollaborationStateReporter, buildCollaborationState, writeBackReport, computeAnchoredPopupPosition, updateSubtitleSettings, overlayPointerInput, cropModeKeyAction, editorThumbnailStep, resolveSlidePaneClick, SLIDE_VIRTUALIZATION_THRESHOLD, buildSectionContextMenuEntries, buildSlidePaneContextMenuEntries, slidePaneViewItems, isEditPointsEnabled, findReplacementAvailability, PRESENTATION_HIT_TEST_CSS, PRESENTATION_STAGE_ATTRIBUTE, buildStrokePathD, cursorForTool, annotationOverlayZIndex, presentationInkPath, resolveNotesSchematicBodyFontSizePx, PRESENTER_NAVIGATOR_LABEL_KEYS, getPresentationContextMenuSections, CONTEXT_MENU_PRESENTATION_LAYER, presentationViewItems, subtitleRecognitionLanguage, getSpeechRecognitionCtor, mergeCaptionResults, customizeContextMenuEntries, buildContextMenuEntries, contextMenuViewItems, customizeCanvasContextMenuEntries, buildCanvasContextMenuEntries, buildLayoutPreviewGeometry, scaleSlidesForSizeChange, slideSizeToCanvasPx, resolveSelectionPaneRename, themeEditorLabels, resolveNotesSegments, defaultRichEnabled, segmentsToEditorHtml, DEBOUNCE_MS, createPlainNotesSegments, parseSegmentsFromRichEditor, segmentsToPlainText, getCurrentParagraphIndex, segmentsToParagraphs, paragraphsToSegments, MAX_INDENT_LEVEL, INDENT_PX as INDENT_PX$1, buildNotesPrintHtml, dispatchStatusBarIntent, toggleSheet, describeElementChange, SMARTART_PREVIEW_ELEMENT_HEIGHT, SMARTART_PREVIEW_ELEMENT_WIDTH, buildSmartArtPreviewElement, sanitizeMathMl, compileEquationTemplateMathMl, computeAllNotesPages, getNotesPrintableArea, CUSTOM_FONT_ACCEPT, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, resolveViewerAddinRows, createSlideSorterState, sorterSelectionIndexes, selectSorterSlide, applySorterAction, sorterGridColumns, sorterMenuContext, buildSlideSorterContextMenuEntries, slideSorterContextMenuLabel, openReadingView, applyReadingViewCommand, createPresentationKeyBuffer, readingViewFitScale, READING_VIEW_STAGE_ATTR, buildOutline, applyOutlineEdit, mapOutlineKey, notesSegmentsToSpans, erasePresentationInkAt, movePresenterPointer, appendPresentationInkPoint, presenterConsoleAction, presenterConsoleViewState, NOTES_FONT_SIZE_DEFAULT, formatTime, NOTES_FONT_SIZE_MIN, clampNotesFontSize, NOTES_FONT_SIZE_STEP, NOTES_FONT_SIZE_MAX, sectionAddAfterSlideIndex, masterViewPseudoSlide, PRESENTATION_ANIM_TRIGGER_ATTRIBUTE, applyTableStyleDelete, applyTableStyleMapChange, registerCustomFont, QUICK_ACCESS_COMMAND_CATALOG, handleReadingViewKey, editorThumbnailHeight, buildPreviewElements, deriveSlideFieldContext, hiddenSlideCue, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, MERGE_SHAPES_MENU_ITEMS, hasMultipleSelectedTableCells, isElementLocked, mergeSlideTransition, slideBackgroundClearState, slideBackgroundClearPatch, effectiveDirection, TRIGGER_OPTIONS, effectiveTimingCurve, getAfterAnimationState, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, elementLockTogglePatch, buildTableDataGrid, getDenseGridLayoutPlan, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, applyTableStylePreset, tableStyleAssignmentUpdate, evenColumnWidths, redistributeColumnWidth, evenRowHeights, inspectorNumber, patchChartData, collapseChartTitleRunsForEdit, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setDataLabelsRangeCache, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, imageResetPatch, imageResetState, canInteractWithElement, buildOleObjectNamePatch, shouldShowAccessibilitySection, withFrameSlides, withSlidesPerPage, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, SLIDE_SIZE_PRESETS, TRANSITION_ORIENTATION_TYPES, clampTransitionNumber, TRANSITION_SPEED_OPTIONS, TRANSITION_MORPH_OPTIONS, flattenTagCollections, resolveTemplateBackgroundRows, commentMentionQuery, matchCommentMentionAuthors, buildAnimationTimelineRows, clearMotionPath, setTrigger, setTriggerBookmark, getEffectSoundState, setEffectSound, setEffectStockSound, setAfterAnimation, setAfterAnimationColor, directionValuesFor, buildAnimationTimelineBars, motionPathPresetIdForPath, MOTION_PATH_FAMILIES, motionPathPresetsByFamily, motionPathPresetLabelKey, motionPathFamilyLabelKey, EFFECT_SOUND_CATALOGUE, listMediaBookmarkOptions, selectedBookmarkOptionValue, describeTableStyleEditor, TABLE_STYLE_EDITOR_PARTS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, resolveDisplayedChartType, CHART_TYPE_OPTIONS, chartDataLabelsTogglePatch, BAR3D_SHAPE_OPTIONS, bar3DShapePatch, RADAR_STYLE_OPTIONS, radarStylePatch, SURFACE_WIREFRAME_OPTIONS, surfaceWireframePatch, isSeriesUsingSecondaryAxis, seriesColorClearState, listChartUserShapeRows, withChartUserShapeAdded, createDefaultChartUserShape, withChartUserShapeRowRemoved, withChartUserShapeRowTextUpdated, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, addSiblingAfter, removeEmptyNode, demote, promote, reorder, cropResetState, cropResetPatch, ARTISTIC_EFFECTS, mediaTrimEndSeconds, trimmedMediaDurationMs, mediaTrimEndAbsoluteMs, mediaTrimResetState, mediaTrimEndMsFromAbsoluteMs, mediaTrimResetPatch, buildOleEditDialogDescriptor, buildOleContentUpdatePatch, buildThemeColorSwatchGrid, themeColorGridView, getNonVisualDescriptionFields, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, canCommitActionType, slideSizeFromPreset, withSlideSizeOrientation, TRANSITION_DIR_ARROWS, buildDirectionGrid, updateTagInCollections, deleteTagFromCollections, addTagToCollections, commentTextSegments, COMMENT_MENTION_CLASS, COMMENT_MENTION_ATTRIBUTE, insertCommentMention, reorderAnimationTimelineRows, applyAnimationTimelineOrder, getEffectSoundAsset, animationEffectLabel, TABLE_STYLE_BORDER_SIDES, applyTableStyleFieldEdit, withCellStyle, LBL as LBL$1, SEL as SEL$1, FILL_MODE_OPTIONS as FILL_MODE_OPTIONS$1, SECTION_HEADING, NUM as NUM$1, getChartUserShapeGroupTransform, withChartUserShapeGroupChildAdded, createDefaultChartUserShapeGroupChild, withChartUserShapeRowUpdated, getChartUserShapeRowChartBox, withChartUserShapeRowFlipUpdated, withChartUserShapeRowRotationUpdated, withChartUserShapeRowChartBoxUpdated, smartArtLayoutSwitchPatch, rebuildDrawingShapesIfCleared, mediaTrimEndMsFromSeconds, validateMediaTrimRange, OFFICE_COLOR_SWATCHES, officeColorSwatchLabel, PATTERN_PRESET_OPTIONS as PATTERN_PRESET_OPTIONS$1, COMPOUND_LINE_OPTIONS as COMPOUND_LINE_OPTIONS$1, LINE_JOIN_OPTIONS as LINE_JOIN_OPTIONS$1, LINE_CAP_OPTIONS as LINE_CAP_OPTIONS$1, themeColorGridCommit, buildTextWarpGallery, TEXT_WARP_PRESETS, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, toSlideIndex, TABLE_STYLE_BORDER_SIDE_LABEL_KEYS, TABLE_STYLE_DASH_PRESETS, GRADIENT_TYPE_OPTIONS as GRADIENT_TYPE_OPTIONS$1, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, quickStyleShapeStyle, textWarpStyle, toggleText3dExtrusion, BEVEL_PRESETS, cropFit, cropFill, cropToAspectRatio } from 'ooxml-ui/pptx';
1
+ import { StaticElementRenderer, useModalDismissDrag, useToolbarVisibility, useViewerOptionsContext, InlineCollaborationContext, SlideBackgroundImageLayer, ElementRenderer, withDisplayName, useCollaboration, ResizeHandles, imgSrc, renderStrokeView, useViewerOptions, useReadOnlyRecommendationState, useCompatibilityToastsState, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useViewPreferencesSync, useLayoutSwitching, Rendering3DFlagsContext, CollaborationProvider, ChartFormatContext, useChartFormatContext, safePrompt, useController, scopeLayoutOptionsToActiveSlide, createReviewCommentsHost, ChartPartSelectionProvider, useKeyboardInsets, ViewerOptionsStoreContext, ViewerOptionsContext, useReportOnChange, useCollaborationDocumentSync, useFollowMode, useBroadcastFollower, useSheetDismissDrag, playAnimationSound, useVirtualizedSlides, useSwipeNavigation, PresentationTransitionOverlay, RemoteSelectionOverlay, CollaborationCursorOverlay, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, downloadBlob, useChartPartSelection, resolveSmartArtDataPalette, DUOTONE_PRESETS, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES } from './chunk-QHGEPW5G.mjs';
2
+ import { cn, getShapeAdjustmentHandleDescriptors, isConnectorOrLineElement, TOOLBAR_SECTIONS, GRID_SIZE, getElementTransformWithoutRotation, getElementTransform, MIN_ELEMENT_SIZE, hasCopyableFormat, DEFAULT_SECTION_GROUP_ID, safeOpenUrl, isPpactionUrl, parsePpactionUrl, SHORTCUT_REFERENCE_ITEMS, isUrlSafe, computeHandoutLayout, getPrintableArea, generateNoteLineCount, normalizeHexColor, UNGROUPED_SECTION_ID, SLIDE_NAV_THUMBNAIL_WIDTH, SLIDE_TRANSITION_OPTIONS, getElementLabel, TABLE_STYLE_PRESETS, SHAPE_PRESETS, sanitizeGradientStops, formatCommentTimestamp, ANIMATION_PRESET_OPTIONS, clampCropValue, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, DEFAULT_FILL_COLOR, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, getPatternSvg, DEFAULT_STROKE_COLOR, openNativeEyeDropper } from './chunk-77IXTLKU.mjs';
3
+ import { ANIMATION_DIRECTION_LABEL_KEYS, buildQuickStylesGallery, buildSlideTemplateContent, SLIDE_TEMPLATES, homeLaunchers, attachRibbonOverflow, isPanelVisible, parentSelection, slideSpaceElement, isGroupMember, motionPathFor, setMotionPath, RULER_THICKNESS, shouldShowElementHandles, deviceStrokeStageStyle, activateModalFocus, visibleContextualTabs, resolveActiveRibbonTab, visibleRibbonAddIns, isDialogAvailable, resolveScreenTip, RIBBON_ADD_IN_TAB_ATTR, contextualTabLabelKey, RIBBON_CONTEXTUAL_TAB_ATTR, buildTabRowActionsState, isFeatureEnabled, TAB_ROW_ACTION_CLASSES, tabRowActionsAttributes, buildTitleBarState, backstageNavEntries, BACKSTAGE_NAV, listBackstageRecentFiles, BACKSTAGE_BACK_CLASSES, BACKSTAGE_NAV_CLASSES, DEFAULT_INSERT_CHART_KIND, FREEFORM_TOOL_IDS, isDrawingToolVisible, textFontSizePtToPx, withHomeGalleries, drawingHomeControls, homeGalleryControls, homeGalleryApply, shapeOutlineChange, shapeFillChange, editingHomeControls, arrangeHomeControls, arrangePainterHomeControls, arrangeAlignAction, DESIGN_RIBBON_GROUPS, FIXED_TAB_GALLERIES, DESIGN_RIBBON_COMMANDS, designCommandState, CONTEXTUAL_TAB_GROUPS, attachEditorImagePaste, authorConnectorBetweenSites, findEraserHitElementId, generateTicks, rulerDragToGuidePosition, resolveElementInteractivity, buildChartQuickActionsDescriptor, applyChartElementToggle, CHART_QUICK_ACTION_BUTTON_SIZE, applyChartStylePreset, hideChartSeries, restoreFilteredSeries, buildCropOverlay, CROP_HANDLE_ARIA_KEY, getActiveXControlOverlayView, buildCommentMarkers, COMMENT_MARKER_SIZE, collectConnectorSiteCandidates, getConnectorEndpointHandles, findConnectorSiteNear, motionPathToSvgD, motionPathEndPixel, isEditableMotionPath, setMotionPathEnd, canEditElementPoints, getSlideBackgroundStyle, resolveCollaborationConfig, resolveViewerRootOptions, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, isEditingAllowed, resolveAutosaveActivation, viewerOptionsToPreferences, applyPreferenceToOptions, resolveHistoryDepth, attachViewerHyperlinks, shouldConfirmExternalHyperlink, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, saveFailureMessage, withSaveFailureToast, createSlidePackageClipboard, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, RIBBON_SCOPE_ATTR, resolve3DRenderingFlags, resolveSlideSizeSelection, EMPTY_RESOLVED_CUSTOMIZATION, getRegionRenderer, ViewerRegionHost, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, customizeBackstageCards, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, clipboardHomeControls, slidesHomeControls, resolveInsertSlideLayout, resolveDefaultFontFamily, textFontSizePxToPt, getInlineEditorSelectionResult, selectedParagraphBulletKind, elementBulletKind, selectionBulletKind, fontPickerHomeControls, fontHomeControls, nextToggleValue, RIBBON_GROUP_ATTR, paragraphHomeAlign, paragraphHomeControls, paragraphHomeAction, arrangeShapeHomeControls, strokeWidthOf, canSetStrokeWidth, canUngroupSelection, canGroupSelection, buildRibbonGallery, readRibbonTransitionDraft, SLIDE_SHOW_COMMAND_GROUPS, buildRecordRibbon, trackActiveComment, commentCounts, findCommentLocation, buildReviewRibbon, buildHelpRibbon, galleryTextLabel, pictureSizeHomeControls, chartSelectionHomeControls, dispatchChartSelectionRequest, buildFreeformShapeElement, buildLiveInkStrokeView, beginCropDrag, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, FreeformToolSession, attachOverlayKeyboard, EditPointsSession, EDIT_POINTS_STYLE, themeToCssVars, createCustomizationController, resolveEffectiveHiddenActions, pruneExpiredAutosaveSnapshots, createDeckStyleHost, galleryDeckView, tableLayoutCells, resetChartFormatTarget, masterViewCrudActions, applyMasterViewCrudAction, masterViewCrudFailureKey, EDITOR_CHROME_CSS, ribbonCustomizationCss, applyMotionPathPreset, resetSlideLayoutPath, templateSchemeFromTheme, createBackstagePresentation, playFeedbackSound, shouldDiscardAutosaveOnSuccessfulSave, deleteAutosaveSnapshot, dispatchReadOnlyBannerIntent, readOnlyBannerState, buildFieldSubstitutionContext, setMasterViewBackgroundColor, canUseClipboard, runProgramNoticeStackStyle, observeElementHeight, printPropertiesFrameSlides, printPropertiesSlidesPerPage, PASTE_SPECIAL_OPTIONS, findCanvasElementNode, isHeaderFooterDateTextVisible, isHeaderFooterHeaderTextVisible, isHeaderFooterFooterTextVisible, getDensePanelTouchTargetPx, shouldStickyActionRow, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, MIN_TOUCH_TARGET_PX, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, getSelectionTextStyleFlags, TEXT_DECORATION_FLAGS, dispatchCropRequest, applyRibbonGalleryItem, ribbonTransitionsDraftPatch, ribbonTransitionUpdates, ribbonTransitionsSoundChange, ribbonTransitionStockSoundUrl, playSlideTransitionPreview, playAnimationRibbonPreview, SLIDE_SHOW_OPTIONS, createViewerOptionsStore, subtitleSettingsFromOptions, subtitleSettingsLabels, isReviewCommentCommand, runReviewCommentCommand, hasTiltData, RULER_FONT_SIZE, toElementAxes, dragCropHandle, panCropImage, clientToSlidePoint, EDIT_POINTS_TARGET_ATTR, pushRecentColor, mruColorsPatch, shouldClearAutosaveCacheOnClose, clearAutosaveSnapshots, canCropElement, cropSessionChanged, cancelCropUpdate, startCropSession, editorThumbnailWidth, EDITOR_THUMBNAIL_WIDTH, masterViewBackgroundColor, resolvePresentationAction, isPresentationAdvanceClick, toggleBlackboard, visibleTemplateElements, PRESENT_TOOLBAR_CLASSES, resolveEditPointsAvailability, isCurrentLayout, EXPANDED_MAX_HEIGHT, statusBarState, statusBarViewMode, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, resolveDefaultPrintSettings, HANDOUT_OPTIONS, bindPptxOptionsDialog, optionsBlockSlot, optionsPaneSlot, DEFAULT_QUICK_ACCESS_COMMAND_IDS, AI_OPTIONS_CATEGORY, buildCollaborationShareUrl, buildActiveSessionUsers, slideClipboardLabels, sorterPasteInsertAt, SORTER_MIN_ZOOM, SORTER_ZOOM_STEP, SORTER_MAX_ZOOM, canGoPrevious, formatSlideCounter, READING_VIEW_COUNTER_ATTR, canGoNext, READING_VIEW_ATTR, listenForOutlineViewDismiss, OUTLINE_LEVEL_ATTR, OUTLINE_SLIDE_ATTR, OUTLINE_ROW_ATTR, OUTLINE_VIEW_ATTR, mobileElapsedSince, nextPresentedSlide, presenterPrevDisabled, presenterNextDisabled, formatMobileElapsed, mobileSlideCounter, presenterPaneAdvancesOnClick, presenterTimerProgress, PRESENTER_CONSOLE_CLASSES, formatElapsed, createCollaborationStateReporter, buildCollaborationState, writeBackReport, computeAnchoredPopupPosition, updateSubtitleSettings, overlayPointerInput, cropModeKeyAction, editorThumbnailStep, resolveSlidePaneClick, SLIDE_VIRTUALIZATION_THRESHOLD, buildSectionContextMenuEntries, buildSlidePaneContextMenuEntries, slidePaneViewItems, isEditPointsEnabled, findReplacementAvailability, PRESENTATION_HIT_TEST_CSS, PRESENTATION_STAGE_ATTRIBUTE, buildStrokePathD, cursorForTool, annotationOverlayZIndex, presentationInkPath, resolveNotesSchematicBodyFontSizePx, PRESENTER_NAVIGATOR_LABEL_KEYS, getPresentationContextMenuSections, CONTEXT_MENU_PRESENTATION_LAYER, presentationViewItems, subtitleRecognitionLanguage, getSpeechRecognitionCtor, mergeCaptionResults, customizeContextMenuEntries, buildContextMenuEntries, contextMenuViewItems, customizeCanvasContextMenuEntries, buildCanvasContextMenuEntries, buildLayoutPreviewGeometry, scaleSlidesForSizeChange, slideSizeToCanvasPx, resolveSelectionPaneRename, themeEditorLabels, resolveNotesSegments, defaultRichEnabled, segmentsToEditorHtml, DEBOUNCE_MS, createPlainNotesSegments, parseSegmentsFromRichEditor, segmentsToPlainText, getCurrentParagraphIndex, segmentsToParagraphs, paragraphsToSegments, MAX_INDENT_LEVEL, INDENT_PX as INDENT_PX$1, buildNotesPrintHtml, dispatchStatusBarIntent, toggleSheet, describeElementChange, sanitizeMathMl, compileEquationTemplateMathMl, computeAllNotesPages, getNotesPrintableArea, CUSTOM_FONT_ACCEPT, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, resolveViewerAddinRows, createSlideSorterState, sorterSelectionIndexes, selectSorterSlide, applySorterAction, sorterGridColumns, sorterMenuContext, buildSlideSorterContextMenuEntries, slideSorterContextMenuLabel, openReadingView, applyReadingViewCommand, createPresentationKeyBuffer, readingViewFitScale, READING_VIEW_STAGE_ATTR, buildOutline, applyOutlineEdit, mapOutlineKey, notesSegmentsToSpans, erasePresentationInkAt, movePresenterPointer, appendPresentationInkPoint, presenterConsoleAction, presenterConsoleViewState, NOTES_FONT_SIZE_DEFAULT, formatTime, NOTES_FONT_SIZE_MIN, clampNotesFontSize, NOTES_FONT_SIZE_STEP, NOTES_FONT_SIZE_MAX, sectionAddAfterSlideIndex, masterViewPseudoSlide, PRESENTATION_ANIM_TRIGGER_ATTRIBUTE, applyTableStyleDelete, applyTableStyleMapChange, registerCustomFont, QUICK_ACCESS_COMMAND_CATALOG, handleReadingViewKey, editorThumbnailHeight, buildPreviewElements, deriveSlideFieldContext, hiddenSlideCue, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, MERGE_SHAPES_MENU_ITEMS, hasMultipleSelectedTableCells, isElementLocked, ELEMENT_GEOMETRY_SECTIONS, mergeSlideTransition, slideBackgroundClearState, slideBackgroundClearPatch, effectiveDirection, TRIGGER_OPTIONS, effectiveTimingCurve, getAfterAnimationState, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, elementLockTogglePatch, resolveInspectorSections, inspectorTogglePatch, buildTableDataGrid, getDenseGridLayoutPlan, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, applyTableStylePreset, tableStyleAssignmentUpdate, evenColumnWidths, redistributeColumnWidth, evenRowHeights, inspectorNumber, patchChartData, collapseChartTitleRunsForEdit, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setDataLabelsRangeCache, imageResetPatch, imageResetState, canInteractWithElement, buildOleObjectNamePatch, shouldShowAccessibilitySection, withFrameSlides, withSlidesPerPage, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, SLIDE_SIZE_PRESETS, TRANSITION_ORIENTATION_TYPES, clampTransitionNumber, TRANSITION_SPEED_OPTIONS, TRANSITION_MORPH_OPTIONS, flattenTagCollections, resolveTemplateBackgroundRows, commentMentionQuery, matchCommentMentionAuthors, buildAnimationTimelineRows, clearMotionPath, setTrigger, setTriggerBookmark, getEffectSoundState, setEffectSound, setEffectStockSound, setAfterAnimation, setAfterAnimationColor, directionValuesFor, buildAnimationTimelineBars, motionPathPresetIdForPath, MOTION_PATH_FAMILIES, motionPathPresetsByFamily, motionPathPresetLabelKey, motionPathFamilyLabelKey, EFFECT_SOUND_CATALOGUE, listMediaBookmarkOptions, selectedBookmarkOptionValue, describeTableStyleEditor, TABLE_STYLE_EDITOR_PARTS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, resolveDisplayedChartType, CHART_TYPE_OPTIONS, chartDataLabelsTogglePatch, BAR3D_SHAPE_OPTIONS, bar3DShapePatch, RADAR_STYLE_OPTIONS, radarStylePatch, SURFACE_WIREFRAME_OPTIONS, surfaceWireframePatch, isSeriesUsingSecondaryAxis, seriesColorClearState, listChartUserShapeRows, withChartUserShapeAdded, createDefaultChartUserShape, withChartUserShapeRowRemoved, withChartUserShapeRowTextUpdated, rebuildDrawingShapesIfCleared, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, cropResetState, cropResetPatch, ARTISTIC_EFFECTS, mediaTrimEndSeconds, trimmedMediaDurationMs, mediaTrimEndAbsoluteMs, mediaTrimResetState, mediaTrimEndMsFromAbsoluteMs, mediaTrimResetPatch, buildOleEditDialogDescriptor, buildOleContentUpdatePatch, buildThemeColorSwatchGrid, themeColorGridView, recentColorsGridView, getNonVisualDescriptionFields, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, canCommitActionType, slideSizeFromPreset, withSlideSizeOrientation, TRANSITION_DIR_ARROWS, buildDirectionGrid, updateTagInCollections, deleteTagFromCollections, addTagToCollections, commentTextSegments, COMMENT_MENTION_CLASS, COMMENT_MENTION_ATTRIBUTE, insertCommentMention, reorderAnimationTimelineRows, applyAnimationTimelineOrder, getEffectSoundAsset, animationEffectLabel, inspectorFieldPatch, TABLE_STYLE_BORDER_SIDES, applyTableStyleFieldEdit, withCellStyle, LBL as LBL$1, SEL as SEL$1, FILL_MODE_OPTIONS as FILL_MODE_OPTIONS$1, SECTION_HEADING, NUM as NUM$1, getChartUserShapeGroupTransform, withChartUserShapeGroupChildAdded, createDefaultChartUserShapeGroupChild, withChartUserShapeRowUpdated, getChartUserShapeRowChartBox, withChartUserShapeRowFlipUpdated, withChartUserShapeRowRotationUpdated, withChartUserShapeRowChartBoxUpdated, smartArtLayoutSwitchPatch, mediaTrimEndMsFromSeconds, validateMediaTrimRange, OFFICE_COLOR_SWATCHES, officeColorSwatchLabel, PATTERN_PRESET_OPTIONS as PATTERN_PRESET_OPTIONS$1, SHAPE_LINE_SECTIONS, SHAPE_EFFECT_SECTIONS, themeColorGridCommit, TEXT_BOX_SECTIONS, buildTextWarpGallery, TEXT_WARP_PRESETS, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, toSlideIndex, TABLE_STYLE_BORDER_SIDE_LABEL_KEYS, TABLE_STYLE_DASH_PRESETS, GRADIENT_TYPE_OPTIONS as GRADIENT_TYPE_OPTIONS$1, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, quickStyleShapeStyle, textWarpStyle, toggleText3dExtrusion, BEVEL_PRESETS, cropFit, cropFill, cropToAspectRatio } from 'ooxml-ui/pptx';
4
4
  export { THEME_CATALOG, defaultCssVars, defaultRadius, defaultThemeColors, resolveThemeCatalogEntry, themeToCssVars, vermilionDarkColors, vermilionDarkTheme, vermilionLightColors, vermilionLightTheme, vermilionRadius } from 'ooxml-ui/pptx';
5
- import React107, { createContext, useContext, useMemo, useState, useRef, useCallback, useEffect, useLayoutEffect, forwardRef, useSyncExternalStore, useReducer, useId, Fragment as Fragment$1, useDeferredValue, Suspense, lazy } from 'react';
5
+ import React108, { createContext, useContext, useMemo, useState, useRef, useCallback, useEffect, useLayoutEffect, forwardRef, useSyncExternalStore, useReducer, useId, Fragment as Fragment$1, useDeferredValue, Suspense, lazy } from 'react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { LuArrowDown, LuArrowUp, LuArrowRight, LuArrowLeft, LuArrowDownRight, LuArrowDownLeft, LuArrowUpRight, LuArrowUpLeft, LuX, LuPanelLeft, LuPanelRight, LuSparkles, LuSettings, LuFolderOpen, LuType, LuPalette, LuFilter, LuPaintbrush, LuPlus, LuClipboardCopy, LuShapes, LuLayoutGrid, LuWand, LuPresentation, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuUpload, LuShare2, LuPrinter, LuDownload, LuSave, LuInfo, LuFilePlus2, LuHouse, LuCopy, LuFileJson, LuBox, LuVideo, LuFileImage, LuFileText, LuDatabase, LuPlay, LuClock3, LuShieldAlert, LuLock, LuUser, LuHardDrive, LuLogIn, LuHistory, LuCalendarDays, LuClock, LuHash, LuText, LuCast, LuChevronRight, LuChevronDown, LuMonitor, LuRadio, LuCaptions, LuCheck, LuImage, LuSearch, LuShieldCheck, LuPanelLeftClose, LuTrash2, LuEyeOff, LuEye, LuLoader, LuSignature, LuTriangleAlert, LuPenTool, LuWifi, LuWifiOff, LuUsers, LuMinus, LuChevronLeft, LuPause, LuCaseSensitive, LuChevronUp, LuReplace, LuGripVertical, LuLoaderCircle, LuGrid2X2, LuStickyNote, LuList, LuBug, LuMove, LuCopyPlus, LuClipboardPaste, LuMessageSquare, LuLayers, LuSettings2, LuLockOpen, LuPencil, LuReply, LuMoveRight, LuRotateCw, LuScissors, LuBookmark, LuPipette } from 'react-icons/lu';
9
9
  import { createPortal } from 'react-dom';
10
- import { hasTextProperties, hasShapeProperties, buildThemeColorMap, themeColorSchemesEqual, isImageLikeElement, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, getOleObjectTypeLabel, pptxActionToElementAction, THEME_COLOR_SCHEME_KEYS, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, TRANSITION_VALID_DIRECTIONS, TRANSITION_PATTERN_OPTIONS, TRANSITION_THRUBLK_TYPES, normalizeTableStyleGuid, updateMergeAttrsInRawXml, addSmartArtNodeAsChild, setSmartArtNodeStyle, removeSmartArtNode, updateSmartArtNodeText, applyOleSheetCellEdit, getOleSheetGrid, applyOleDocumentParagraphEdit, getOleDocumentParagraphs, applyOleNestedDeckElementTextEdit, getOleNestedDeckDetail, replaceOleFile, elementActionToPptxAction, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, SWITCHABLE_LAYOUT_TYPES } from 'ooxml-core/pptx';
10
+ import { hasTextProperties, hasShapeProperties, buildThemeColorMap, themeColorSchemesEqual, isImageLikeElement, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, getOleObjectTypeLabel, pptxActionToElementAction, THEME_COLOR_SCHEME_KEYS, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, TRANSITION_VALID_DIRECTIONS, TRANSITION_PATTERN_OPTIONS, TRANSITION_THRUBLK_TYPES, normalizeTableStyleGuid, updateMergeAttrsInRawXml, applyOleSheetCellEdit, getOleSheetGrid, applyOleDocumentParagraphEdit, getOleDocumentParagraphs, applyOleNestedDeckElementTextEdit, getOleNestedDeckDetail, replaceOleFile, elementActionToPptxAction, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, SWITCHABLE_LAYOUT_TYPES } from 'ooxml-core/pptx';
11
11
  import { LOCALE_CATALOG } from 'ooxml-ui/pptx/i18n';
12
- import { computeFocusTargets, deckDataFieldChanged, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs as exportAiChatLogs$1, applyElementUpdate } from 'ooxml-ui/pptx/ai';
12
+ import { createPptxAiPanelController, computeFocusTargets, createPptxAiBridge, resolveAiEffectiveTargets, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs as exportAiChatLogs$1 } from 'ooxml-ui/pptx/ai';
13
13
 
14
14
  var ViewerThemeContext = /* @__PURE__ */ createContext(void 0);
15
15
  function ViewerThemeProvider({ theme, children }) {
@@ -742,6 +742,7 @@ function InsertSection(p) {
742
742
  activeFreeformTool: p.activeFreeformTool ?? null,
743
743
  freeformTools: p.onArmFreeformTool ? FREEFORM_TOOL_IDS.filter((tool) => isDrawingToolVisible(customization, tool)) : [],
744
744
  chartAvailable: Boolean(p.onAddChart),
745
+ chartDialogAvailable: Boolean(p.onAddChart && p.onOpenChartDialog),
745
746
  fieldAvailable: Boolean(p.onInsertField),
746
747
  headerFooterAvailable: Boolean(p.onOpenHeaderFooter),
747
748
  newSlideAvailable: Boolean(p.onInsertSlideFromLayout && p.layoutOptions?.length),
@@ -809,6 +810,9 @@ function InsertSection(p) {
809
810
  case "chart":
810
811
  p.onAddChart?.(intent.value);
811
812
  break;
813
+ case "chartDialog":
814
+ p.onOpenChartDialog?.();
815
+ break;
812
816
  case "freeform":
813
817
  p.onArmFreeformTool?.(intent.value);
814
818
  break;
@@ -970,6 +974,7 @@ function MobileInsertSheet(p) {
970
974
  onAddShape: p.onAddShape,
971
975
  onAddTable: p.onAddTable,
972
976
  onAddChart: p.onAddChart,
977
+ onOpenChartDialog: p.onOpenChartDialog,
973
978
  onAddSmartArt: p.onAddSmartArt,
974
979
  onAddEquation: p.onAddEquation,
975
980
  onAddActionButton: p.onAddActionButton,
@@ -1130,7 +1135,7 @@ function WebHomeControls({
1130
1135
  host.addEventListener("home-popup", listener);
1131
1136
  return () => host.removeEventListener("home-popup", listener);
1132
1137
  }, [onPopup]);
1133
- return React107.createElement(`pptx-ui-ribbon-home-${family}`, { ref });
1138
+ return React108.createElement(`pptx-ui-ribbon-home-${family}`, { ref });
1134
1139
  }
1135
1140
  function ShapeArrangeExtras(p) {
1136
1141
  const commands = useShapeFormatContext();
@@ -1673,7 +1678,7 @@ function AccountPage() {
1673
1678
  return void 0;
1674
1679
  });
1675
1680
  };
1676
- const version = "4.49.0" ;
1681
+ const version = "4.50.0" ;
1677
1682
  return /* @__PURE__ */ jsxs("div", { className: "mt-8 max-w-[700px] space-y-6", children: [
1678
1683
  /* @__PURE__ */ jsxs("section", { className: cardClass, children: [
1679
1684
  /* @__PURE__ */ jsxs("h2", { className: "flex items-center gap-2 text-sm font-semibold", children: [
@@ -3377,6 +3382,7 @@ function MobileSectionBody({
3377
3382
  onAddShape: p.onAddShape,
3378
3383
  onAddTable: p.onAddTable,
3379
3384
  onAddChart: p.onAddChart,
3385
+ onOpenChartDialog: p.onOpenChartDialog,
3380
3386
  onAddSmartArt: p.onAddSmartArt,
3381
3387
  onAddEquation: p.onAddEquation,
3382
3388
  onAddActionButton: p.onAddActionButton,
@@ -4813,6 +4819,7 @@ function Toolbar(p) {
4813
4819
  onAddShape: p.onAddShape,
4814
4820
  onAddTable: p.onAddTable,
4815
4821
  onAddChart: p.onAddChart,
4822
+ onOpenChartDialog: p.onOpenChartDialog,
4816
4823
  onAddSmartArt: p.onAddSmartArt,
4817
4824
  onAddEquation: p.onAddEquation,
4818
4825
  onAddActionButton: p.onAddActionButton,
@@ -5012,7 +5019,6 @@ var HEADING = "text-[11px] uppercase tracking-wide text-muted-foreground";
5012
5019
  var CARD = "rounded border border-border bg-card p-2 space-y-2";
5013
5020
  var INPUT = "flex-1 bg-muted border border-border rounded px-1.5 py-0.5 w-full max-md:min-h-[44px]!";
5014
5021
  var BTN = "rounded bg-muted hover:bg-accent px-2 py-1 text-[11px] transition-colors max-md:min-h-[44px]!";
5015
- var CELL_INPUT = "bg-muted border border-border rounded px-1 py-0.5 text-[11px] w-full text-center";
5016
5022
  var GROUPING_OPTIONS = [
5017
5023
  { value: "clustered", labelKey: "pptx.chart.groupingClustered" },
5018
5024
  { value: "stacked", labelKey: "pptx.chart.groupingStacked" },
@@ -5186,7 +5192,7 @@ function ChartQuickActionsOverlay({
5186
5192
  "data-export-ignore": "true",
5187
5193
  style: { position: "absolute", left: 0, top: 0, zIndex: 59 },
5188
5194
  onMouseDown: (e) => e.stopPropagation(),
5189
- children: descriptor.buttons.map((button) => /* @__PURE__ */ jsxs(React107.Fragment, { children: [
5195
+ children: descriptor.buttons.map((button) => /* @__PURE__ */ jsxs(React108.Fragment, { children: [
5190
5196
  /* @__PURE__ */ jsx(
5191
5197
  "button",
5192
5198
  {
@@ -5206,7 +5212,7 @@ function ChartQuickActionsOverlay({
5206
5212
  transformOrigin: "top left"
5207
5213
  },
5208
5214
  className: "flex items-center justify-center rounded bg-white border border-gray-300 shadow-sm hover:bg-gray-100 text-gray-700",
5209
- children: React107.createElement(ICONS3[button.id], { className: "size-3.5" })
5215
+ children: React108.createElement(ICONS3[button.id], { className: "size-3.5" })
5210
5216
  }
5211
5217
  ),
5212
5218
  open === button.id && button.id === "elements" && /* @__PURE__ */ jsxs(
@@ -6353,7 +6359,7 @@ function HorizontalRulerView({ ticks, widthPx, highlight }) {
6353
6359
  );
6354
6360
  }
6355
6361
  var HorizontalRuler = /* @__PURE__ */ withDisplayName(
6356
- /* @__PURE__ */ React107.memo(HorizontalRulerView),
6362
+ /* @__PURE__ */ React108.memo(HorizontalRulerView),
6357
6363
  "HorizontalRuler"
6358
6364
  );
6359
6365
  function VerticalRulerView({ ticks, heightPx, highlight }) {
@@ -6427,7 +6433,7 @@ function VerticalRulerView({ ticks, heightPx, highlight }) {
6427
6433
  );
6428
6434
  }
6429
6435
  var VerticalRuler = /* @__PURE__ */ withDisplayName(
6430
- /* @__PURE__ */ React107.memo(VerticalRulerView),
6436
+ /* @__PURE__ */ React108.memo(VerticalRulerView),
6431
6437
  "VerticalRuler"
6432
6438
  );
6433
6439
  function Ruler({
@@ -8266,7 +8272,7 @@ function slideThumbnailPropsEqual(prev, next) {
8266
8272
  }
8267
8273
  return true;
8268
8274
  }
8269
- var SlideThumbnail = /* @__PURE__ */ React107.memo(
8275
+ var SlideThumbnail = /* @__PURE__ */ React108.memo(
8270
8276
  SlideThumbnailImpl,
8271
8277
  slideThumbnailPropsEqual
8272
8278
  );
@@ -8966,7 +8972,7 @@ function LazyThumbnailInner({
8966
8972
  }
8967
8973
  ) });
8968
8974
  }
8969
- var LazyThumbnail = /* @__PURE__ */ React107.memo(LazyThumbnailInner);
8975
+ var LazyThumbnail = /* @__PURE__ */ React108.memo(LazyThumbnailInner);
8970
8976
  function declaredSectionFacts(groups, sectionId) {
8971
8977
  const declared = groups.filter((group) => group.id !== DEFAULT_SECTION_GROUP_ID && group.id !== UNGROUPED_SECTION_ID).map((group) => group.id);
8972
8978
  return {
@@ -9134,7 +9140,7 @@ function SlideItemInner({
9134
9140
  }
9135
9141
  );
9136
9142
  }
9137
- var SlideItem = /* @__PURE__ */ React107.memo(SlideItemInner);
9143
+ var SlideItem = /* @__PURE__ */ React108.memo(SlideItemInner);
9138
9144
  function useSlidePaneCallbacks(onMoveSlide, onRenameSection, onToggleSectionCollapse) {
9139
9145
  const [collapsedSections, setCollapsedSections] = useState({});
9140
9146
  const [renamingSectionId, setRenamingSectionId] = useState(null);
@@ -10547,7 +10553,7 @@ function arePropsEqual(prev, next) {
10547
10553
  }
10548
10554
  return true;
10549
10555
  }
10550
- var SlideCard = /* @__PURE__ */ React107.memo(SlideCardImpl, arePropsEqual);
10556
+ var SlideCard = /* @__PURE__ */ React108.memo(SlideCardImpl, arePropsEqual);
10551
10557
  var ICON_CLASS = "h-3.5 w-3.5 text-muted-foreground";
10552
10558
  function SorterContextMenu({
10553
10559
  x,
@@ -10972,7 +10978,7 @@ function SlideSorterOverlay({
10972
10978
  count: state.selectedSlideIds.length
10973
10979
  }) })
10974
10980
  ] }),
10975
- React107.createElement("pptx-ui-slide-clipboard", {
10981
+ React108.createElement("pptx-ui-slide-clipboard", {
10976
10982
  ref: (node) => {
10977
10983
  if (!node) {
10978
10984
  return;
@@ -11888,8 +11894,8 @@ function SlideNotesPanel({
11888
11894
  onHeightChange
11889
11895
  }) {
11890
11896
  const { t } = useTranslation();
11891
- const rootRef = React107.useRef(null);
11892
- React107.useEffect(() => {
11897
+ const rootRef = React108.useRef(null);
11898
+ React108.useEffect(() => {
11893
11899
  const el = rootRef.current;
11894
11900
  if (!el || !onHeightChange) {
11895
11901
  return void 0;
@@ -13732,9 +13738,9 @@ function PresentationSubtitleBar({
13732
13738
  function renderNotesSegments(segments) {
13733
13739
  return notesSegmentsToSpans(segments).map((span) => {
13734
13740
  if (span.kind === "break") {
13735
- return React107.createElement("br", { key: span.key });
13741
+ return React108.createElement("br", { key: span.key });
13736
13742
  }
13737
- return React107.createElement(
13743
+ return React108.createElement(
13738
13744
  "span",
13739
13745
  { key: span.key, style: span.style },
13740
13746
  span.text
@@ -13910,7 +13916,7 @@ function scaledSlidePreviewPropsEqual(prev, next) {
13910
13916
  }
13911
13917
  return true;
13912
13918
  }
13913
- var ScaledSlidePreview = /* @__PURE__ */ React107.memo(
13919
+ var ScaledSlidePreview = /* @__PURE__ */ React108.memo(
13914
13920
  ScaledSlidePreviewImpl,
13915
13921
  scaledSlidePreviewPropsEqual
13916
13922
  );
@@ -15156,7 +15162,7 @@ function EffectSoundRow({
15156
15162
  onPickStock
15157
15163
  }) {
15158
15164
  const { t } = useTranslation();
15159
- const fileInputRef = React107.useRef(null);
15165
+ const fileInputRef = React108.useRef(null);
15160
15166
  const selectedValue = soundState.catalogueId ?? (soundState.hasSound ? CURRENT_VALUE : NONE_VALUE);
15161
15167
  const handleSelectChange = (event) => {
15162
15168
  const value = event.target.value;
@@ -16026,12 +16032,6 @@ var HEADING2 = "pptx-editor-heading text-[11px] uppercase tracking-wide text-mut
16026
16032
  var CARD2 = "pptx-editor-card rounded border border-border bg-card p-2 space-y-2";
16027
16033
  var INPUT2 = "flex-1 bg-muted border border-border rounded px-1.5 py-0.5 w-full max-md:min-h-[44px]!";
16028
16034
  var BTN2 = "rounded bg-muted hover:bg-accent px-2 py-1 text-[11px] transition-colors max-md:min-h-[44px]! max-md:min-w-[44px]!";
16029
- var POS_FIELDS = [
16030
- ["X", "x"],
16031
- ["Y", "y"],
16032
- ["W", "width"],
16033
- ["H", "height"]
16034
- ];
16035
16035
  var URL_LABEL_KEY = {
16036
16036
  url: "pptx.action.gotoUrl",
16037
16037
  openFile: "pptx.hyperlink.actionOpenFile",
@@ -16585,149 +16585,6 @@ function ChartComboTypeOptions({
16585
16585
  ] }, `${s.name}-${i}`)) })
16586
16586
  ] });
16587
16587
  }
16588
- function ChartDataGrid({
16589
- series,
16590
- categories,
16591
- canEdit,
16592
- highlightCell,
16593
- onUpdateSeries,
16594
- onUpdateCategoryLabel,
16595
- onUpdateValue,
16596
- onAddCategory,
16597
- onRemoveCategory,
16598
- onAddSeries,
16599
- onRemoveSeries
16600
- }) {
16601
- const { t } = useTranslation();
16602
- const highlightRef = useRef(null);
16603
- const { viewportWidth } = useIsMobile();
16604
- const gridPlan = getDenseGridLayoutPlan(viewportWidth);
16605
- const touchTargetPx = getDensePanelTouchTargetPx(viewportWidth);
16606
- const rowHeaderClass = gridPlan.stickyFirstColumn ? "sticky left-0 z-10 bg-card" : "";
16607
- const iconBtnStyle = { minWidth: touchTargetPx, minHeight: touchTargetPx };
16608
- useEffect(() => {
16609
- highlightRef.current?.scrollIntoView({ block: "nearest", inline: "nearest" });
16610
- }, [highlightCell?.seriesIndex, highlightCell?.pointIndex]);
16611
- const highlightClass = " ring-1 ring-primary";
16612
- const isSeriesHighlight = (si) => highlightCell?.seriesIndex === si && highlightCell.pointIndex === void 0;
16613
- const isValueHighlight = (si, ci) => highlightCell?.seriesIndex === si && highlightCell.pointIndex === ci;
16614
- return /* @__PURE__ */ jsxs("div", { className: CARD, children: [
16615
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
16616
- /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.chart.data") }),
16617
- canEdit && /* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
16618
- /* @__PURE__ */ jsxs(
16619
- "button",
16620
- {
16621
- type: "button",
16622
- className: `${BTN} inline-flex items-center justify-center`,
16623
- style: iconBtnStyle,
16624
- title: t("pptx.chart.addCategory"),
16625
- onClick: onAddCategory,
16626
- children: [
16627
- /* @__PURE__ */ jsx(LuPlus, { className: "inline w-3 h-3 mr-0.5" }),
16628
- t("pptx.chart.cat")
16629
- ]
16630
- }
16631
- ),
16632
- /* @__PURE__ */ jsxs(
16633
- "button",
16634
- {
16635
- type: "button",
16636
- className: `${BTN} inline-flex items-center justify-center`,
16637
- style: iconBtnStyle,
16638
- title: t("pptx.chart.addSeries"),
16639
- onClick: onAddSeries,
16640
- children: [
16641
- /* @__PURE__ */ jsx(LuPlus, { className: "inline w-3 h-3 mr-0.5" }),
16642
- t("pptx.chart.seriesShort")
16643
- ]
16644
- }
16645
- )
16646
- ] })
16647
- ] }),
16648
- /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-[11px] border-collapse", children: [
16649
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
16650
- /* @__PURE__ */ jsx(
16651
- "th",
16652
- {
16653
- "aria-label": t("pptx.chart.categories"),
16654
- className: `text-muted-foreground p-0.5 text-left ${rowHeaderClass}`,
16655
- style: { minWidth: gridPlan.minCellWidthPx }
16656
- }
16657
- ),
16658
- series.map((s, si) => /* @__PURE__ */ jsx(
16659
- "th",
16660
- {
16661
- className: "p-0.5 font-normal",
16662
- style: { minWidth: gridPlan.minCellWidthPx },
16663
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
16664
- /* @__PURE__ */ jsx(
16665
- "input",
16666
- {
16667
- type: "text",
16668
- disabled: !canEdit,
16669
- ref: isSeriesHighlight(si) ? highlightRef : null,
16670
- className: `${CELL_INPUT}${isSeriesHighlight(si) ? highlightClass : ""}`,
16671
- value: s.name,
16672
- onChange: (e) => onUpdateSeries(si, { name: e.target.value })
16673
- }
16674
- ),
16675
- canEdit && series.length > 1 && /* @__PURE__ */ jsx(
16676
- "button",
16677
- {
16678
- type: "button",
16679
- className: "text-muted-foreground hover:text-red-400 shrink-0 inline-flex items-center justify-center",
16680
- style: iconBtnStyle,
16681
- title: t("pptx.chart.removeSeries"),
16682
- onClick: () => onRemoveSeries(si),
16683
- children: /* @__PURE__ */ jsx(LuTrash2, { className: "w-3 h-3" })
16684
- }
16685
- )
16686
- ] })
16687
- },
16688
- si
16689
- ))
16690
- ] }) }),
16691
- /* @__PURE__ */ jsx("tbody", { children: categories.map((cat, ci) => /* @__PURE__ */ jsxs("tr", { children: [
16692
- /* @__PURE__ */ jsx("td", { className: `p-0.5 ${rowHeaderClass}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
16693
- /* @__PURE__ */ jsx(
16694
- "input",
16695
- {
16696
- type: "text",
16697
- disabled: !canEdit,
16698
- className: CELL_INPUT,
16699
- value: cat,
16700
- onChange: (e) => onUpdateCategoryLabel(ci, e.target.value)
16701
- }
16702
- ),
16703
- canEdit && categories.length > 1 && /* @__PURE__ */ jsx(
16704
- "button",
16705
- {
16706
- type: "button",
16707
- className: "text-muted-foreground hover:text-red-400 shrink-0 inline-flex items-center justify-center",
16708
- style: iconBtnStyle,
16709
- title: t("pptx.chart.removeCategory"),
16710
- onClick: () => onRemoveCategory(ci),
16711
- children: /* @__PURE__ */ jsx(LuTrash2, { className: "w-3 h-3" })
16712
- }
16713
- )
16714
- ] }) }),
16715
- series.map((s, si) => /* @__PURE__ */ jsx("td", { className: "p-0.5", children: /* @__PURE__ */ jsx(
16716
- "input",
16717
- {
16718
- type: "number",
16719
- "aria-label": t("pptx.chart.seriesValueCell", { name: s.name, number: ci + 1 }),
16720
- disabled: !canEdit,
16721
- ref: isValueHighlight(si, ci) ? highlightRef : null,
16722
- className: `${CELL_INPUT}${isValueHighlight(si, ci) ? highlightClass : ""}`,
16723
- value: s.values[ci] ?? 0,
16724
- onChange: (e) => onUpdateValue(si, ci, e.target.value)
16725
- }
16726
- ) }, si))
16727
- ] }, ci)) })
16728
- ] }) })
16729
- ] });
16730
- }
16731
16588
  function ChartDataLabelOptions({
16732
16589
  style,
16733
16590
  canEdit,
@@ -16982,6 +16839,37 @@ function ChartDataPointOptions({
16982
16839
  }) })
16983
16840
  ] });
16984
16841
  }
16842
+ function ChartDataSheet({
16843
+ chartData,
16844
+ canEdit,
16845
+ followDataPoint,
16846
+ highlightCell,
16847
+ onChange
16848
+ }) {
16849
+ const { t } = useTranslation();
16850
+ const ref = useRef(null);
16851
+ useLayoutEffect(() => {
16852
+ if (ref.current) {
16853
+ ref.current.state = {
16854
+ chartData,
16855
+ canEdit,
16856
+ followDataPoint,
16857
+ highlight: highlightCell ?? null,
16858
+ translate: (key, params) => t(key, params)
16859
+ };
16860
+ }
16861
+ }, [chartData, canEdit, followDataPoint, highlightCell, t]);
16862
+ useEffect(() => {
16863
+ const sheet = ref.current;
16864
+ if (!sheet) {
16865
+ return;
16866
+ }
16867
+ const commit = (event) => onChange(event.detail.chartData);
16868
+ sheet.addEventListener("pptx-chart-data-change", commit);
16869
+ return () => sheet.removeEventListener("pptx-chart-data-change", commit);
16870
+ }, [onChange]);
16871
+ return /* @__PURE__ */ jsx("div", { className: CARD, children: /* @__PURE__ */ jsx("pptx-ui-chart-data-sheet", { ref }) });
16872
+ }
16985
16873
  function ChartDisplayOptions({
16986
16874
  style,
16987
16875
  canEdit,
@@ -18072,52 +17960,6 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
18072
17960
  },
18073
17961
  [updateSeries]
18074
17962
  );
18075
- const updateCategoryLabel = useCallback(
18076
- (catIndex, value) => {
18077
- const next = chartData && setChartCategoryLabel(chartData, catIndex, value);
18078
- if (next) {
18079
- replaceChartData(next);
18080
- }
18081
- },
18082
- [chartData, replaceChartData]
18083
- );
18084
- const updateValue = useCallback(
18085
- (seriesIndex, catIndex, raw) => {
18086
- const next = chartData && setChartCellValue(chartData, seriesIndex, catIndex, raw);
18087
- if (next) {
18088
- replaceChartData(next);
18089
- }
18090
- },
18091
- [chartData, replaceChartData]
18092
- );
18093
- const addCategory = useCallback(() => {
18094
- if (chartData) {
18095
- replaceChartData(addChartCategory(chartData));
18096
- }
18097
- }, [chartData, replaceChartData]);
18098
- const removeCategory = useCallback(
18099
- (catIndex) => {
18100
- const next = chartData && removeChartCategory(chartData, catIndex, followDataPoint);
18101
- if (next) {
18102
- replaceChartData(next);
18103
- }
18104
- },
18105
- [chartData, followDataPoint, replaceChartData]
18106
- );
18107
- const addSeries = useCallback(() => {
18108
- if (chartData) {
18109
- replaceChartData(addChartSeries(chartData));
18110
- }
18111
- }, [chartData, replaceChartData]);
18112
- const removeSeries = useCallback(
18113
- (seriesIndex) => {
18114
- const next = chartData && removeChartSeries(chartData, seriesIndex);
18115
- if (next) {
18116
- replaceChartData(next);
18117
- }
18118
- },
18119
- [chartData, replaceChartData]
18120
- );
18121
17963
  const hideSeries = useCallback(
18122
17964
  (seriesIndex) => {
18123
17965
  const next = chartData && hideChartSeries(chartData, seriesIndex);
@@ -18334,19 +18176,13 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
18334
18176
  }
18335
18177
  ),
18336
18178
  /* @__PURE__ */ jsx(
18337
- ChartDataGrid,
18179
+ ChartDataSheet,
18338
18180
  {
18339
- categories,
18340
- series,
18181
+ chartData,
18341
18182
  canEdit,
18183
+ followDataPoint,
18342
18184
  highlightCell: canvasPart ? { seriesIndex: canvasPart.seriesIndex, pointIndex: canvasPart.pointIndex } : null,
18343
- onUpdateSeries: updateSeries,
18344
- onUpdateCategoryLabel: updateCategoryLabel,
18345
- onUpdateValue: updateValue,
18346
- onAddCategory: addCategory,
18347
- onRemoveCategory: removeCategory,
18348
- onAddSeries: addSeries,
18349
- onRemoveSeries: removeSeries
18185
+ onChange: replaceChartData
18350
18186
  }
18351
18187
  )
18352
18188
  ] });
@@ -18714,7 +18550,7 @@ function ConnectorArrowsSection({
18714
18550
  ["Start", "End"].map((end) => {
18715
18551
  const widthKey = end === "Start" ? "connectorStartArrowWidth" : "connectorEndArrowWidth";
18716
18552
  const lengthKey = end === "Start" ? "connectorStartArrowLength" : "connectorEndArrowLength";
18717
- return /* @__PURE__ */ jsxs(React107.Fragment, { children: [
18553
+ return /* @__PURE__ */ jsxs(React108.Fragment, { children: [
18718
18554
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
18719
18555
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t(END_LABEL_KEYS[end].width) }),
18720
18556
  /* @__PURE__ */ jsx(
@@ -18867,36 +18703,21 @@ function TransformPanel({
18867
18703
  }) {
18868
18704
  return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
18869
18705
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: "Transform" }),
18870
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-1.5 text-[11px]", children: [
18871
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
18872
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Rotation (\xB0)" }),
18873
- /* @__PURE__ */ jsx(
18874
- "input",
18875
- {
18876
- type: "number",
18877
- disabled: !canEdit,
18878
- className: INPUT2,
18879
- value: Math.round(selectedElement.rotation || 0),
18880
- onChange: (e) => onUpdateElement({ rotation: Number(e.target.value) })
18881
- }
18882
- )
18883
- ] }),
18884
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
18885
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Opacity" }),
18886
- /* @__PURE__ */ jsx(
18887
- "input",
18888
- {
18889
- type: "range",
18890
- disabled: !canEdit,
18891
- min: 0,
18892
- max: 100,
18893
- value: Math.round((selectedElement.opacity ?? 1) * 100),
18894
- className: "accent-primary",
18895
- onChange: (e) => onUpdateElement({ opacity: Number(e.target.value) / 100 })
18896
- }
18897
- )
18898
- ] })
18899
- ] })
18706
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1.5 text-[11px]", children: /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
18707
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Opacity" }),
18708
+ /* @__PURE__ */ jsx(
18709
+ "input",
18710
+ {
18711
+ type: "range",
18712
+ disabled: !canEdit,
18713
+ min: 0,
18714
+ max: 100,
18715
+ value: Math.round((selectedElement.opacity ?? 1) * 100),
18716
+ className: "accent-primary",
18717
+ onChange: (e) => onUpdateElement({ opacity: Number(e.target.value) / 100 })
18718
+ }
18719
+ )
18720
+ ] }) })
18900
18721
  ] });
18901
18722
  }
18902
18723
  function LayerOrderButtons({
@@ -19534,6 +19355,130 @@ function ImagePropertiesPanel({
19534
19355
  ] })
19535
19356
  ] });
19536
19357
  }
19358
+
19359
+ // src/viewer/components/inspector/FillStrokeHelpers.tsx
19360
+ var SEL = "bg-muted border border-border rounded px-2 py-1 max-md:min-h-[44px]!";
19361
+ var NUM = SEL;
19362
+ var RNG = "accent-primary";
19363
+ var SWATCH = "h-4 w-4 rounded border border-border";
19364
+ var DIS = "disabled:opacity-40 disabled:cursor-not-allowed";
19365
+ var LBL = "text-muted-foreground";
19366
+ var COL2 = "col-span-2";
19367
+ var isLineish = (el, st) => el.type === "connector" || st === "line";
19368
+ function InspectorFields({
19369
+ sections,
19370
+ target,
19371
+ onPatch,
19372
+ disabled = false
19373
+ }) {
19374
+ const { t } = useTranslation();
19375
+ const commitRecentColor = useRecentColorCommit();
19376
+ const views = resolveInspectorSections(sections, target);
19377
+ const change = (sectionId, fieldId, raw) => {
19378
+ const patch = inspectorFieldPatch(sections, sectionId, fieldId, target, raw);
19379
+ if (patch !== void 0) {
19380
+ onPatch(patch);
19381
+ }
19382
+ };
19383
+ const renderField = (sectionId, field) => {
19384
+ const label = t(field.labelKey);
19385
+ const cls = `flex flex-col gap-1 ${field.wide ? COL2 : ""}`;
19386
+ const key = `${sectionId}.${field.id}`;
19387
+ if (field.control === "checkbox") {
19388
+ return /* @__PURE__ */ jsxs("label", { className: `flex items-center gap-2 ${field.wide ? COL2 : ""}`, children: [
19389
+ /* @__PURE__ */ jsx(
19390
+ WebCheckbox,
19391
+ {
19392
+ "data-testid": field.testId,
19393
+ checked: Boolean(field.value),
19394
+ disabled,
19395
+ onChange: (e) => change(sectionId, field.id, e.target.checked),
19396
+ className: "h-4 w-4"
19397
+ }
19398
+ ),
19399
+ /* @__PURE__ */ jsx("span", { className: LBL, children: label })
19400
+ ] }, key);
19401
+ }
19402
+ if (field.control === "select") {
19403
+ return /* @__PURE__ */ jsxs("label", { className: cls, children: [
19404
+ /* @__PURE__ */ jsx("span", { className: LBL, children: label }),
19405
+ /* @__PURE__ */ jsx(
19406
+ WebSelect,
19407
+ {
19408
+ "data-testid": field.testId,
19409
+ "aria-label": label,
19410
+ value: String(field.value),
19411
+ disabled,
19412
+ onChange: (e) => change(sectionId, field.id, e.target.value),
19413
+ className: SEL,
19414
+ children: field.options?.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: t(o.labelKey) }, o.value))
19415
+ }
19416
+ )
19417
+ ] }, key);
19418
+ }
19419
+ if (field.control === "color") {
19420
+ return /* @__PURE__ */ jsxs("label", { className: cls, children: [
19421
+ /* @__PURE__ */ jsx("span", { className: LBL, children: label }),
19422
+ /* @__PURE__ */ jsx(
19423
+ "input",
19424
+ {
19425
+ type: "color",
19426
+ "data-testid": field.testId,
19427
+ "aria-label": label,
19428
+ value: String(field.value),
19429
+ disabled,
19430
+ ref: commitRecentColor,
19431
+ onChange: (e) => change(sectionId, field.id, e.target.value),
19432
+ className: `h-8 ${SEL} px-1`
19433
+ }
19434
+ )
19435
+ ] }, key);
19436
+ }
19437
+ return /* @__PURE__ */ jsxs("label", { className: cls, children: [
19438
+ /* @__PURE__ */ jsx("span", { className: LBL, children: label }),
19439
+ /* @__PURE__ */ jsx(
19440
+ "input",
19441
+ {
19442
+ type: field.control,
19443
+ "data-testid": field.testId,
19444
+ "aria-label": label,
19445
+ min: field.min,
19446
+ max: field.max,
19447
+ step: field.step,
19448
+ value: Number(field.value),
19449
+ disabled,
19450
+ onChange: (e) => change(sectionId, field.id, e.target.value),
19451
+ className: field.control === "range" ? RNG : NUM
19452
+ }
19453
+ )
19454
+ ] }, key);
19455
+ };
19456
+ return /* @__PURE__ */ jsx(Fragment, { children: views.map((section) => /* @__PURE__ */ jsxs(React108.Fragment, { children: [
19457
+ section.toggleable ? /* @__PURE__ */ jsxs("label", { className: `inline-flex items-center gap-2 text-foreground ${COL2}`, children: [
19458
+ /* @__PURE__ */ jsx(
19459
+ WebCheckbox,
19460
+ {
19461
+ "data-testid": section.toggleTestId,
19462
+ checked: section.on,
19463
+ disabled,
19464
+ onChange: (e) => {
19465
+ const patch = inspectorTogglePatch(
19466
+ sections,
19467
+ section.id,
19468
+ target,
19469
+ e.target.checked
19470
+ );
19471
+ if (patch !== void 0) {
19472
+ onPatch(patch);
19473
+ }
19474
+ }
19475
+ }
19476
+ ),
19477
+ t(section.labelKey ?? "")
19478
+ ] }) : section.labelKey ? /* @__PURE__ */ jsx("span", { className: `${LBL} ${COL2}`, children: t(section.labelKey) }) : null,
19479
+ section.fields.map((field) => renderField(section.id, field))
19480
+ ] }, section.id)) });
19481
+ }
19537
19482
  var HEADING3 = "text-[11px] uppercase tracking-wide text-muted-foreground";
19538
19483
  var CARD3 = "rounded border border-border bg-card p-2 space-y-2";
19539
19484
  var INPUT3 = "flex-1 bg-muted border border-border rounded px-1.5 py-0.5 w-full";
@@ -20398,9 +20343,6 @@ function AccessibilityTextSection({
20398
20343
  ] })
20399
20344
  ] });
20400
20345
  }
20401
- var COMPOUND_LINE_OPTIONS = COMPOUND_LINE_OPTIONS$1;
20402
- var LINE_JOIN_OPTIONS = LINE_JOIN_OPTIONS$1;
20403
- var LINE_CAP_OPTIONS = LINE_CAP_OPTIONS$1;
20404
20346
  var PATTERN_PRESET_OPTIONS = PATTERN_PRESET_OPTIONS$1;
20405
20347
  var FILL_MODE_OPTIONS = [
20406
20348
  { value: "solid", label: "Solid", i18nKey: "pptx.fill.solid" },
@@ -20417,589 +20359,45 @@ var IMAGE_MODE_OPTIONS = [
20417
20359
  { value: "stretch", label: "Stretch", i18nKey: "pptx.image.stretch" },
20418
20360
  { value: "tile", label: "Tile", i18nKey: "pptx.image.tile" }
20419
20361
  ];
20420
- function getCompoundLinePreviewStyle(type) {
20421
- const baseColor = "#6b7280";
20422
- switch (type) {
20423
- case "sng":
20424
- return {
20425
- borderTop: `2px solid ${baseColor}`,
20426
- width: "100%"
20427
- };
20428
- case "dbl": {
20429
- const lineWidth = 2;
20430
- const gap = 2;
20431
- return {
20432
- position: "relative",
20433
- height: `${lineWidth * 2 + gap}px`,
20434
- width: "100%",
20435
- boxShadow: `inset 0 ${lineWidth + gap}px 0 ${-lineWidth}px ${baseColor}, inset 0 ${ -4}px 0 ${-lineWidth}px ${baseColor}`
20436
- };
20437
- }
20438
- case "thickThin": {
20439
- const thickWidth = 3;
20440
- const thinWidth = 1;
20441
- const gap = 1;
20442
- return {
20443
- position: "relative",
20444
- height: `${thickWidth + thinWidth + gap}px`,
20445
- width: "100%",
20446
- boxShadow: `inset 0 ${thickWidth / 2 + gap}px 0 ${-thickWidth}px ${baseColor}, inset 0 ${ -3.5}px 0 ${-thinWidth}px ${baseColor}`
20447
- };
20448
- }
20449
- case "thinThick": {
20450
- const thinWidth = 1;
20451
- const thickWidth = 3;
20452
- const gap = 1;
20453
- return {
20454
- position: "relative",
20455
- height: `${thinWidth + thickWidth + gap}px`,
20456
- width: "100%",
20457
- boxShadow: `inset 0 ${thickWidth / 2 + gap}px 0 ${-thinWidth}px ${baseColor}, inset 0 ${ -3.5}px 0 ${-thickWidth}px ${baseColor}`
20458
- };
20459
- }
20460
- case "tri": {
20461
- const lineWidth = 1;
20462
- const gap = 1;
20463
- const offset1 = lineWidth + gap;
20464
- return {
20465
- position: "relative",
20466
- height: `${lineWidth * 3 + gap * 2}px`,
20467
- width: "100%",
20468
- boxShadow: `inset 0 0 0 ${-lineWidth}px ${baseColor}, inset 0 ${offset1}px 0 ${-lineWidth}px ${baseColor}, inset 0 ${ -4}px 0 ${-lineWidth}px ${baseColor}`
20469
- };
20470
- }
20471
- default:
20472
- return {};
20473
- }
20474
- }
20475
-
20476
- // src/viewer/components/inspector/bevel-type-options.ts
20477
- var BEVEL_TYPE_OPTIONS = [
20478
- { value: "circle", label: "Circle", i18nKey: "pptx.bevelTypes.circle" },
20479
- { value: "relaxedInset", label: "Relaxed Inset", i18nKey: "pptx.bevelTypes.relaxedInset" },
20480
- { value: "cross", label: "Cross", i18nKey: "pptx.bevelTypes.cross" },
20481
- { value: "slope", label: "Slope", i18nKey: "pptx.bevelTypes.slope" },
20482
- { value: "convex", label: "Convex", i18nKey: "pptx.bevelTypes.convex" },
20483
- { value: "coolSlant", label: "Cool Slant", i18nKey: "pptx.bevelTypes.coolSlant" },
20484
- { value: "angle", label: "Angle", i18nKey: "pptx.bevelTypes.angle" },
20485
- { value: "softRound", label: "Soft Round", i18nKey: "pptx.bevelTypes.softRound" },
20486
- { value: "riblet", label: "Riblet", i18nKey: "pptx.bevelTypes.riblet" },
20487
- { value: "hardEdge", label: "Hard Edge", i18nKey: "pptx.bevelTypes.hardEdge" },
20488
- { value: "artDeco", label: "Art Deco", i18nKey: "pptx.bevelTypes.artDeco" },
20489
- { value: "divot", label: "Divot", i18nKey: "pptx.bevelTypes.divot" }
20490
- ];
20491
-
20492
- // src/viewer/components/inspector/fill-stroke-effect-configs.ts
20493
- var clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
20494
- var SHADOW_EFFECT_CONFIGS = [
20495
- /* Shadow */
20496
- {
20497
- label: "Shadow",
20498
- isOn: (s) => Boolean(s?.shadowColor) && s?.shadowColor !== "transparent",
20499
- onEnable: (s) => {
20500
- let angle = s?.shadowAngle ?? 315;
20501
- let distance = s?.shadowDistance ?? 5.66;
20502
- const offsetX = s?.shadowOffsetX ?? 4;
20503
- const offsetY = s?.shadowOffsetY ?? 4;
20504
- if (s?.shadowAngle === null && s?.shadowDistance === null && (offsetX !== 0 || offsetY !== 0)) {
20505
- distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
20506
- angle = (Math.atan2(offsetY, offsetX) * 180 / Math.PI + 360) % 360;
20507
- }
20508
- return {
20509
- shadowColor: normalizeHexColor(s?.shadowColor, "#000000"),
20510
- shadowOpacity: s?.shadowOpacity ?? 0.35,
20511
- shadowBlur: s?.shadowBlur ?? 6,
20512
- shadowAngle: angle,
20513
- shadowDistance: distance,
20514
- shadowOffsetX: offsetX,
20515
- shadowOffsetY: offsetY,
20516
- shadowRotateWithShape: s?.shadowRotateWithShape ?? true
20517
- };
20518
- },
20519
- onDisable: () => ({ shadowColor: "transparent" }),
20520
- fields: [
20521
- {
20522
- key: "sc",
20523
- label: "Shadow Color",
20524
- type: "color",
20525
- read: (s) => normalizeHexColor(s?.shadowColor, "#000000"),
20526
- write: (v) => ({ shadowColor: String(v) })
20527
- },
20528
- {
20529
- key: "so",
20530
- label: "Shadow Opacity",
20531
- type: "range",
20532
- min: 0,
20533
- max: 100,
20534
- isPercent: true,
20535
- read: (s) => Math.round((s?.shadowOpacity ?? 0.35) * 100),
20536
- write: (v) => ({ shadowOpacity: Number(v) / 100 })
20537
- },
20538
- {
20539
- key: "sb",
20540
- label: "Shadow Blur",
20541
- type: "number",
20542
- min: 0,
20543
- max: 96,
20544
- read: (s) => Math.round(s?.shadowBlur ?? 6),
20545
- write: (v) => ({ shadowBlur: clamp(Number(v), 0, 96) })
20546
- },
20547
- {
20548
- key: "sa",
20549
- label: "Shadow Angle",
20550
- type: "number",
20551
- min: 0,
20552
- max: 359,
20553
- read: (s) => {
20554
- if (typeof s?.shadowAngle === "number") {
20555
- return Math.round(s.shadowAngle) % 360;
20556
- }
20557
- const x = s?.shadowOffsetX ?? 4;
20558
- const y = s?.shadowOffsetY ?? 4;
20559
- return Math.round((Math.atan2(y, x) * 180 / Math.PI + 360) % 360);
20560
- },
20561
- write: (v) => {
20562
- const angle = Number(v) % 360;
20563
- return (s) => {
20564
- const dist = typeof s?.shadowDistance === "number" ? s.shadowDistance : 5.66;
20565
- const angleRad = angle * Math.PI / 180;
20566
- return {
20567
- shadowAngle: angle,
20568
- shadowDistance: dist,
20569
- shadowOffsetX: Math.cos(angleRad) * dist,
20570
- shadowOffsetY: Math.sin(angleRad) * dist
20571
- };
20572
- };
20573
- }
20574
- },
20575
- {
20576
- key: "sd",
20577
- label: "Shadow Distance",
20578
- type: "number",
20579
- min: 0,
20580
- max: 100,
20581
- read: (s) => {
20582
- if (typeof s?.shadowDistance === "number") {
20583
- return Math.round(s.shadowDistance * 10) / 10;
20584
- }
20585
- const x = s?.shadowOffsetX ?? 4;
20586
- const y = s?.shadowOffsetY ?? 4;
20587
- return Math.round(Math.sqrt(x * x + y * y) * 10) / 10;
20588
- },
20589
- write: (v) => {
20590
- return (s) => {
20591
- const distance = clamp(Number(v), 0, 100);
20592
- const angle = typeof s?.shadowAngle === "number" ? s.shadowAngle : 315;
20593
- const angleRad = angle * Math.PI / 180;
20594
- return {
20595
- shadowAngle: angle,
20596
- shadowDistance: distance,
20597
- shadowOffsetX: Math.cos(angleRad) * distance,
20598
- shadowOffsetY: Math.sin(angleRad) * distance
20599
- };
20600
- };
20601
- }
20602
- },
20603
- {
20604
- key: "sr",
20605
- label: "Rotate with Shape",
20606
- i18nKey: "pptx.effects.rotateWithShape",
20607
- type: "checkbox",
20608
- read: (s) => s?.shadowRotateWithShape ?? true,
20609
- write: (v) => ({ shadowRotateWithShape: Boolean(v) })
20610
- },
20611
- {
20612
- key: "sx",
20613
- label: "Shadow X",
20614
- type: "number",
20615
- min: -96,
20616
- max: 96,
20617
- read: (s) => Math.round(s?.shadowOffsetX ?? 4),
20618
- write: (v) => {
20619
- return (s) => {
20620
- const offsetX = clamp(Number(v), -96, 96);
20621
- const offsetY = s?.shadowOffsetY ?? 4;
20622
- const distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
20623
- const angle = (Math.atan2(offsetY, offsetX) * 180 / Math.PI + 360) % 360;
20624
- return {
20625
- shadowOffsetX: offsetX,
20626
- shadowAngle: angle,
20627
- shadowDistance: distance
20628
- };
20629
- };
20630
- }
20631
- },
20632
- {
20633
- key: "sy",
20634
- label: "Shadow Y",
20635
- type: "number",
20636
- min: -96,
20637
- max: 96,
20638
- span2: true,
20639
- read: (s) => Math.round(s?.shadowOffsetY ?? 4),
20640
- write: (v) => {
20641
- return (s) => {
20642
- const offsetY = clamp(Number(v), -96, 96);
20643
- const offsetX = s?.shadowOffsetX ?? 4;
20644
- const distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
20645
- const angle = (Math.atan2(offsetY, offsetX) * 180 / Math.PI + 360) % 360;
20646
- return {
20647
- shadowOffsetY: offsetY,
20648
- shadowAngle: angle,
20649
- shadowDistance: distance
20650
- };
20651
- };
20652
- }
20653
- }
20654
- ]
20655
- },
20656
- /* Inner Shadow */
20657
- {
20658
- label: "Inner Shadow",
20659
- isOn: (s) => Boolean(s?.innerShadowColor) && s?.innerShadowColor !== "transparent",
20660
- onEnable: (s) => ({
20661
- innerShadowColor: normalizeHexColor(s?.innerShadowColor, "#000000"),
20662
- innerShadowOpacity: s?.innerShadowOpacity ?? 0.5,
20663
- innerShadowBlur: s?.innerShadowBlur ?? 5,
20664
- innerShadowOffsetX: s?.innerShadowOffsetX ?? 0,
20665
- innerShadowOffsetY: s?.innerShadowOffsetY ?? 0
20666
- }),
20667
- onDisable: () => ({ innerShadowColor: "transparent" }),
20668
- fields: [
20669
- {
20670
- key: "isc",
20671
- label: "Color",
20672
- type: "color",
20673
- read: (s) => normalizeHexColor(s?.innerShadowColor, "#000000"),
20674
- write: (v) => ({ innerShadowColor: String(v) })
20675
- },
20676
- {
20677
- key: "iso",
20678
- label: "Opacity",
20679
- type: "range",
20680
- min: 0,
20681
- max: 100,
20682
- isPercent: true,
20683
- read: (s) => Math.round((s?.innerShadowOpacity ?? 0.5) * 100),
20684
- write: (v) => ({ innerShadowOpacity: Number(v) / 100 })
20685
- },
20686
- {
20687
- key: "isb",
20688
- label: "Blur",
20689
- type: "number",
20690
- min: 0,
20691
- max: 96,
20692
- read: (s) => Math.round(s?.innerShadowBlur ?? 5),
20693
- write: (v) => ({ innerShadowBlur: clamp(Number(v), 0, 96) })
20694
- },
20695
- {
20696
- key: "isx",
20697
- label: "Offset X",
20698
- type: "number",
20699
- min: -96,
20700
- max: 96,
20701
- read: (s) => Math.round(s?.innerShadowOffsetX ?? 0),
20702
- write: (v) => ({
20703
- innerShadowOffsetX: clamp(Number(v), -96, 96)
20704
- })
20705
- },
20706
- {
20707
- key: "isy",
20708
- label: "Offset Y",
20709
- type: "number",
20710
- min: -96,
20711
- max: 96,
20712
- span2: true,
20713
- read: (s) => Math.round(s?.innerShadowOffsetY ?? 0),
20714
- write: (v) => ({
20715
- innerShadowOffsetY: clamp(Number(v), -96, 96)
20716
- })
20717
- }
20718
- ]
20719
- }
20720
- ];
20721
-
20722
- // src/viewer/components/inspector/fill-stroke-visual-configs.ts
20723
- var clamp2 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
20724
- var VISUAL_EFFECT_CONFIGS = [
20725
- /* Glow */
20726
- {
20727
- label: "Glow",
20728
- isOn: (s) => Boolean(s?.glowColor) && s?.glowColor !== "transparent",
20729
- onEnable: (s) => ({
20730
- glowColor: s?.glowColor && s.glowColor !== "transparent" ? s.glowColor : "#ffff00",
20731
- glowOpacity: s?.glowOpacity ?? 0.75,
20732
- glowRadius: s?.glowRadius ?? 6
20733
- }),
20734
- onDisable: () => ({ glowColor: "transparent", glowRadius: 0 }),
20735
- fields: [
20736
- {
20737
- key: "gc",
20738
- label: "Glow Color",
20739
- type: "color",
20740
- read: (s) => s?.glowColor && s.glowColor !== "transparent" ? s.glowColor : "#ffff00",
20741
- write: (v) => ({ glowColor: String(v) })
20742
- },
20743
- {
20744
- key: "go",
20745
- label: "Glow Opacity",
20746
- type: "range",
20747
- min: 0,
20748
- max: 100,
20749
- isPercent: true,
20750
- read: (s) => Math.round((s?.glowOpacity ?? 0.75) * 100),
20751
- write: (v) => ({ glowOpacity: Number(v) / 100 })
20752
- },
20753
- {
20754
- key: "gr",
20755
- label: "Glow Radius",
20756
- type: "number",
20757
- min: 0,
20758
- max: 96,
20759
- span2: true,
20760
- read: (s) => Math.round(s?.glowRadius ?? 6),
20761
- write: (v) => ({ glowRadius: clamp2(Number(v), 0, 96) })
20762
- }
20763
- ]
20764
- },
20765
- /* Soft Edge */
20766
- {
20767
- label: "Soft Edge",
20768
- i18nKey: "pptx.inspector.softEdge",
20769
- isOn: (s) => typeof s?.softEdgeRadius === "number" && s.softEdgeRadius > 0,
20770
- onEnable: () => ({ softEdgeRadius: 6 }),
20771
- onDisable: () => ({ softEdgeRadius: 0 }),
20772
- fields: [
20773
- {
20774
- key: "se",
20775
- label: "Soft Edge Radius",
20776
- i18nKey: "pptx.inspector.softEdgeRadius",
20777
- type: "number",
20778
- min: 0,
20779
- max: 96,
20780
- span2: true,
20781
- read: (s) => Math.round(s?.softEdgeRadius ?? 6),
20782
- write: (v) => ({ softEdgeRadius: clamp2(Number(v), 0, 96) })
20783
- }
20784
- ]
20785
- },
20786
- /* Reflection */
20787
- {
20788
- label: "Reflection",
20789
- isOn: (s) => (s?.reflectionBlurRadius ?? 0) > 0 || (s?.reflectionStartOpacity ?? 0) > 0,
20790
- onEnable: () => ({
20791
- reflectionBlurRadius: 3,
20792
- reflectionStartOpacity: 50,
20793
- reflectionEndOpacity: 0,
20794
- reflectionEndPosition: 50,
20795
- reflectionDirection: 90,
20796
- reflectionDistance: 0
20797
- }),
20798
- onDisable: () => ({
20799
- reflectionBlurRadius: 0,
20800
- reflectionStartOpacity: 0,
20801
- reflectionEndOpacity: 0,
20802
- reflectionEndPosition: 0,
20803
- reflectionDirection: 0,
20804
- reflectionDistance: 0
20805
- }),
20806
- fields: [
20807
- {
20808
- key: "rb",
20809
- label: "Blur",
20810
- type: "number",
20811
- min: 0,
20812
- max: 20,
20813
- step: 0.5,
20814
- read: (s) => s?.reflectionBlurRadius ?? 3,
20815
- write: (v) => ({ reflectionBlurRadius: clamp2(Number(v), 0, 20) })
20816
- },
20817
- {
20818
- key: "rs",
20819
- label: "Start Opacity %",
20820
- type: "number",
20821
- min: 0,
20822
- max: 100,
20823
- read: (s) => s?.reflectionStartOpacity ?? 50,
20824
- write: (v) => ({ reflectionStartOpacity: clamp2(Number(v), 0, 100) })
20825
- },
20826
- {
20827
- key: "re",
20828
- label: "End Opacity %",
20829
- type: "number",
20830
- min: 0,
20831
- max: 100,
20832
- read: (s) => s?.reflectionEndOpacity ?? 0,
20833
- write: (v) => ({ reflectionEndOpacity: clamp2(Number(v), 0, 100) })
20834
- },
20835
- {
20836
- key: "rd",
20837
- label: "Distance",
20838
- type: "number",
20839
- min: 0,
20840
- max: 50,
20841
- read: (s) => s?.reflectionDistance ?? 0,
20842
- write: (v) => ({ reflectionDistance: clamp2(Number(v), 0, 50) })
20843
- },
20844
- {
20845
- key: "rdir",
20846
- label: "Direction",
20847
- type: "number",
20848
- min: 0,
20849
- max: 360,
20850
- read: (s) => s?.reflectionDirection ?? 90,
20851
- write: (v) => ({ reflectionDirection: clamp2(Number(v), 0, 360) })
20852
- },
20853
- {
20854
- key: "rrot",
20855
- label: "Rotation",
20856
- type: "number",
20857
- min: 0,
20858
- max: 360,
20859
- span2: true,
20860
- read: (s) => s?.reflectionRotation ?? 0,
20861
- write: (v) => ({ reflectionRotation: clamp2(Number(v), 0, 360) })
20862
- }
20863
- ]
20864
- },
20865
- /* Blur */
20866
- {
20867
- label: "Blur",
20868
- isOn: (s) => (s?.blurRadius ?? 0) > 0,
20869
- onEnable: () => ({ blurRadius: 4 }),
20870
- onDisable: () => ({ blurRadius: 0 }),
20871
- fields: [
20872
- {
20873
- key: "bl",
20874
- label: "Blur Radius",
20875
- type: "number",
20876
- min: 0,
20877
- max: 50,
20878
- span2: true,
20879
- read: (s) => Math.round(s?.blurRadius ?? 4),
20880
- write: (v) => ({ blurRadius: clamp2(Number(v), 0, 50) })
20881
- }
20882
- ]
20883
- },
20884
- /* Bevel / 3D */
20885
- {
20886
- label: "Bevel / 3D",
20887
- isOn: (s) => Boolean(s?.shape3d?.bevelTopType) && s?.shape3d?.bevelTopType !== "none",
20888
- onEnable: (s) => ({
20889
- shape3d: {
20890
- ...s?.shape3d,
20891
- bevelTopType: s?.shape3d?.bevelTopType || "circle",
20892
- bevelTopWidth: s?.shape3d?.bevelTopWidth ?? 76200,
20893
- bevelTopHeight: s?.shape3d?.bevelTopHeight ?? 76200
20894
- }
20895
- }),
20896
- onDisable: (s) => ({
20897
- shape3d: {
20898
- ...s?.shape3d,
20899
- bevelTopType: void 0,
20900
- bevelTopWidth: void 0,
20901
- bevelTopHeight: void 0
20902
- }
20903
- }),
20904
- fields: [
20905
- {
20906
- key: "btype",
20907
- label: "Bevel Type",
20908
- type: "select",
20909
- span2: true,
20910
- options: BEVEL_TYPE_OPTIONS,
20911
- read: (s) => s?.shape3d?.bevelTopType ?? "circle",
20912
- write: (v, s) => ({
20913
- shape3d: { ...s?.shape3d, bevelTopType: String(v) }
20914
- })
20915
- },
20916
- {
20917
- key: "bw",
20918
- label: "Bevel Width (EMU)",
20919
- type: "number",
20920
- min: 0,
20921
- max: 5e5,
20922
- step: 12700,
20923
- read: (s) => s?.shape3d?.bevelTopWidth ?? 76200,
20924
- write: (v, s) => ({
20925
- shape3d: {
20926
- ...s?.shape3d,
20927
- bevelTopWidth: clamp2(Number(v), 0, 5e5)
20928
- }
20929
- })
20930
- },
20931
- {
20932
- key: "bh",
20933
- label: "Bevel Height (EMU)",
20934
- type: "number",
20935
- min: 0,
20936
- max: 5e5,
20937
- step: 12700,
20938
- span2: true,
20939
- read: (s) => s?.shape3d?.bevelTopHeight ?? 76200,
20940
- write: (v, s) => ({
20941
- shape3d: {
20942
- ...s?.shape3d,
20943
- bevelTopHeight: clamp2(Number(v), 0, 5e5)
20944
- }
20945
- })
20946
- }
20947
- ]
20948
- }
20949
- ];
20950
-
20951
- // src/viewer/components/inspector/FillStrokeHelpers.tsx
20952
- var EFFECT_CONFIGS = [...SHADOW_EFFECT_CONFIGS, ...VISUAL_EFFECT_CONFIGS];
20953
- var SEL = "bg-muted border border-border rounded px-2 py-1 max-md:min-h-[44px]!";
20954
- var NUM = SEL;
20955
- var RNG = "accent-primary";
20956
- var SWATCH = "h-4 w-4 rounded border border-border";
20957
- var DIS = "disabled:opacity-40 disabled:cursor-not-allowed";
20958
- var LBL = "text-muted-foreground";
20959
- var COL2 = "col-span-2";
20960
- var isLineish = (el, st) => el.type === "connector" || st === "line";
20961
- var safeNum = (raw, fallback) => {
20962
- const n = Number(raw);
20963
- return Number.isFinite(n) ? n : fallback;
20964
- };
20965
20362
  function RecentColorsRow({
20966
- prefix,
20967
20363
  disabled,
20968
20364
  onCommit
20969
20365
  }) {
20970
20366
  const { t } = useTranslation();
20971
20367
  const { recentColors, pushColor } = useRecentColors();
20972
- if (recentColors.length === 0) {
20368
+ const shown = recentColors.length > 0;
20369
+ const ref = useRef(null);
20370
+ useLayoutEffect(() => {
20371
+ const grid = ref.current;
20372
+ if (!grid) {
20373
+ return;
20374
+ }
20375
+ const view = recentColorsGridView(recentColors, (key, params) => t(key, params));
20376
+ grid.palette = view.palette;
20377
+ grid.standardColors = view.standardColors;
20378
+ grid.recentColors = view.recentColors;
20379
+ grid.recentHeading = view.recentHeading;
20380
+ grid.recentLabel = view.recentLabel;
20381
+ grid.label = view.label;
20382
+ grid.disabled = Boolean(disabled);
20383
+ }, [recentColors, disabled, t]);
20384
+ useEffect(() => {
20385
+ const grid = ref.current;
20386
+ if (!shown || !grid) {
20387
+ return;
20388
+ }
20389
+ const pick = (event) => {
20390
+ const { color } = event.detail;
20391
+ onCommit(color);
20392
+ pushColor(color);
20393
+ };
20394
+ grid.addEventListener("office-color-pick", pick);
20395
+ return () => grid.removeEventListener("office-color-pick", pick);
20396
+ }, [shown, onCommit, pushColor]);
20397
+ if (!shown) {
20973
20398
  return null;
20974
20399
  }
20975
- return /* @__PURE__ */ jsxs(
20976
- "div",
20977
- {
20978
- "data-testid": "pptx-color-recent",
20979
- "aria-label": t("pptx.colorPicker.recentColors"),
20980
- className: "mt-1 flex flex-wrap items-center gap-1",
20981
- children: [
20982
- /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground", children: t("pptx.colorPicker.recentColors") }),
20983
- recentColors.map((c) => /* @__PURE__ */ jsx(
20984
- "button",
20985
- {
20986
- type: "button",
20987
- "data-pptx-compact": true,
20988
- className: "h-4 w-4 rounded border border-primary",
20989
- style: { backgroundColor: c },
20990
- title: c,
20991
- "aria-label": `Recent ${c}`,
20992
- disabled,
20993
- onClick: () => {
20994
- onCommit(c);
20995
- pushColor(c);
20996
- }
20997
- },
20998
- `${prefix}-recent-${c}`
20999
- ))
21000
- ]
21001
- }
21002
- );
20400
+ return /* @__PURE__ */ jsx("pptx-ui-color-grid", { ref, "data-testid": "pptx-color-recent", className: "mt-1" });
21003
20401
  }
21004
20402
  function ThemeColorSwatchGrid({
21005
20403
  disabled,
@@ -21047,107 +20445,6 @@ function ThemeColorSwatchGrid({
21047
20445
  }
21048
20446
  return /* @__PURE__ */ jsx("pptx-ui-color-grid", { ref, className: "mt-1" });
21049
20447
  }
21050
- function EffectField({
21051
- field,
21052
- style,
21053
- onUpdate
21054
- }) {
21055
- const { t } = useTranslation();
21056
- const commitRecentColor = useRecentColorCommit();
21057
- const fieldLabel = field.i18nKey ? t(field.i18nKey) : field.label;
21058
- const val = field.read(style);
21059
- const cls = `flex flex-col gap-1 ${field.span2 ? COL2 : ""}`;
21060
- if (field.type === "select" && field.options) {
21061
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21062
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21063
- /* @__PURE__ */ jsx(
21064
- WebSelect,
21065
- {
21066
- "aria-label": fieldLabel,
21067
- value: String(val),
21068
- onChange: (e) => {
21069
- const result = field.write(e.target.value, style);
21070
- onUpdate(typeof result === "function" ? result(style) : result);
21071
- },
21072
- className: SEL,
21073
- children: field.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
21074
- }
21075
- )
21076
- ] });
21077
- }
21078
- if (field.type === "color") {
21079
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21080
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21081
- /* @__PURE__ */ jsx(
21082
- "input",
21083
- {
21084
- type: "color",
21085
- value: String(val),
21086
- ref: commitRecentColor,
21087
- onChange: (e) => {
21088
- const result = field.write(e.target.value, style);
21089
- onUpdate(typeof result === "function" ? result(style) : result);
21090
- },
21091
- className: `h-8 ${SEL} px-1`
21092
- }
21093
- )
21094
- ] });
21095
- }
21096
- if (field.type === "checkbox") {
21097
- return /* @__PURE__ */ jsxs("label", { className: `flex items-center gap-2 ${field.span2 ? COL2 : ""}`, children: [
21098
- /* @__PURE__ */ jsx(
21099
- WebCheckbox,
21100
- {
21101
- checked: Boolean(val),
21102
- onChange: (e) => {
21103
- const result = field.write(e.target.checked, style);
21104
- onUpdate(typeof result === "function" ? result(style) : result);
21105
- },
21106
- className: "h-4 w-4"
21107
- }
21108
- ),
21109
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel })
21110
- ] });
21111
- }
21112
- if (field.type === "range") {
21113
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21114
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21115
- /* @__PURE__ */ jsx(
21116
- "input",
21117
- {
21118
- type: "range",
21119
- min: field.min ?? 0,
21120
- max: field.max ?? 100,
21121
- value: Number(val),
21122
- onChange: (e) => {
21123
- const result = field.write(Number(e.target.value), style);
21124
- onUpdate(typeof result === "function" ? result(style) : result);
21125
- },
21126
- className: RNG
21127
- }
21128
- )
21129
- ] });
21130
- }
21131
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21132
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21133
- /* @__PURE__ */ jsx(
21134
- "input",
21135
- {
21136
- type: "number",
21137
- min: field.min,
21138
- max: field.max,
21139
- step: field.step,
21140
- value: Number(val),
21141
- onChange: (e) => {
21142
- const n = safeNum(e.target.value, Number(val));
21143
- const result = field.write(n, style);
21144
- onUpdate(typeof result === "function" ? result(style) : result);
21145
- },
21146
- className: NUM
21147
- }
21148
- )
21149
- ] });
21150
- }
21151
20448
  function SelectRow({
21152
20449
  label,
21153
20450
  value,
@@ -21247,7 +20544,7 @@ function ColorPickerRow({
21247
20544
  `${prefix}-standard-${c.hex}`
21248
20545
  )) })
21249
20546
  ] }),
21250
- /* @__PURE__ */ jsx(RecentColorsRow, { prefix, disabled, onCommit: commit })
20547
+ /* @__PURE__ */ jsx(RecentColorsRow, { disabled, onCommit: commit })
21251
20548
  ] });
21252
20549
  }
21253
20550
  function GradientStopRow({
@@ -21565,22 +20862,6 @@ function StrokeEffectsSection({
21565
20862
  onChange: onSetStrokeColor
21566
20863
  }
21567
20864
  ),
21568
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
21569
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.strokeWidth") }),
21570
- /* @__PURE__ */ jsx(
21571
- "input",
21572
- {
21573
- type: "number",
21574
- min: 0,
21575
- value: Math.round(style?.strokeWidth || 0),
21576
- onChange: (e) => {
21577
- const v = safeNum(e.target.value, 0);
21578
- onUpdateShapeStyle({ strokeWidth: Math.max(0, v) });
21579
- },
21580
- className: NUM
21581
- }
21582
- )
21583
- ] }),
21584
20865
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
21585
20866
  /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.fillOpacity") }),
21586
20867
  /* @__PURE__ */ jsx(
@@ -21596,94 +20877,13 @@ function StrokeEffectsSection({
21596
20877
  }
21597
20878
  )
21598
20879
  ] }),
21599
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
21600
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.strokeOpacity") }),
21601
- /* @__PURE__ */ jsx(
21602
- "input",
21603
- {
21604
- type: "range",
21605
- min: 0,
21606
- max: 100,
21607
- value: Math.round((style?.strokeOpacity ?? 1) * 100),
21608
- onChange: (e) => onUpdateShapeStyle({
21609
- strokeOpacity: Number(e.target.value) / 100
21610
- }),
21611
- className: RNG
21612
- }
21613
- )
21614
- ] }),
21615
- /* @__PURE__ */ jsxs("label", { className: `flex flex-col gap-1 ${COL2}`, children: [
21616
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.strokeDash") }),
21617
- /* @__PURE__ */ jsx(
21618
- WebSelect,
21619
- {
21620
- "aria-label": t("pptx.strokeEffects.strokeDash"),
21621
- value: style?.strokeDash || "solid",
21622
- onChange: (e) => onUpdateShapeStyle({
21623
- strokeDash: e.target.value
21624
- }),
21625
- className: SEL,
21626
- children: STROKE_DASH_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: t(o.i18nKey) }, o.value))
21627
- }
21628
- )
21629
- ] }),
21630
- /* @__PURE__ */ jsxs("label", { className: `flex flex-col gap-1 ${COL2}`, children: [
21631
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.compoundLine") }),
21632
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1", children: COMPOUND_LINE_OPTIONS.map((opt) => /* @__PURE__ */ jsx(
21633
- "button",
21634
- {
21635
- type: "button",
21636
- title: t(opt.i18nKey),
21637
- "aria-label": t(opt.i18nKey),
21638
- className: `h-10 max-md:h-11 px-2 rounded border transition-all ${(style?.compoundLine || "sng") === opt.value ? "border-primary bg-accent" : "border-border hover:border-primary/50"}`,
21639
- onClick: () => onUpdateShapeStyle({
21640
- compoundLine: opt.value
21641
- }),
21642
- children: /* @__PURE__ */ jsx(
21643
- "div",
21644
- {
21645
- className: "w-full h-full flex items-center justify-center",
21646
- style: getCompoundLinePreviewStyle(opt.value)
21647
- }
21648
- )
21649
- },
21650
- opt.value
21651
- )) })
21652
- ] }),
21653
- EFFECT_CONFIGS.map((cfg) => {
21654
- const on = cfg.isOn(style);
21655
- return /* @__PURE__ */ jsxs(React107.Fragment, { children: [
21656
- /* @__PURE__ */ jsxs("label", { className: `inline-flex items-center gap-2 text-foreground ${COL2}`, children: [
21657
- /* @__PURE__ */ jsx(
21658
- WebCheckbox,
21659
- {
21660
- checked: on,
21661
- onChange: (e) => {
21662
- onUpdateShapeStyle(e.target.checked ? cfg.onEnable(style) : cfg.onDisable(style));
21663
- }
21664
- }
21665
- ),
21666
- cfg.i18nKey ? t(cfg.i18nKey) : cfg.label
21667
- ] }),
21668
- on && cfg.fields.map((f) => /* @__PURE__ */ jsx(EffectField, { field: f, style, onUpdate: onUpdateShapeStyle }, f.key))
21669
- ] }, cfg.label);
21670
- }),
20880
+ /* @__PURE__ */ jsx(InspectorFields, { sections: SHAPE_LINE_SECTIONS, target: style, onPatch: onUpdateShapeStyle }),
21671
20881
  /* @__PURE__ */ jsx(
21672
- SelectRow,
20882
+ InspectorFields,
21673
20883
  {
21674
- label: t("pptx.strokeEffects.lineJoin"),
21675
- value: style?.lineJoin || "round",
21676
- options: LINE_JOIN_OPTIONS,
21677
- onChange: (v) => onUpdateShapeStyle({ lineJoin: v })
21678
- }
21679
- ),
21680
- /* @__PURE__ */ jsx(
21681
- SelectRow,
21682
- {
21683
- label: t("pptx.strokeEffects.lineCap"),
21684
- value: style?.lineCap || "flat",
21685
- options: LINE_CAP_OPTIONS,
21686
- onChange: (v) => onUpdateShapeStyle({ lineCap: v })
20884
+ sections: SHAPE_EFFECT_SECTIONS,
20885
+ target: style,
20886
+ onPatch: onUpdateShapeStyle
21687
20887
  }
21688
20888
  )
21689
20889
  ] });
@@ -22167,17 +21367,15 @@ function AdvancedTextFormatting({
22167
21367
  )
22168
21368
  ] })
22169
21369
  ] }),
22170
- /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-foreground", children: [
22171
- /* @__PURE__ */ jsx(
22172
- WebCheckbox,
22173
- {
22174
- checked: Boolean(ts?.autoFit),
22175
- disabled: !canEdit,
22176
- onChange: (e) => onUpdateTextStyle({ autoFit: e.target.checked })
22177
- }
22178
- ),
22179
- t("pptx.textProperties.autoFitToShape")
22180
- ] })
21370
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: /* @__PURE__ */ jsx(
21371
+ InspectorFields,
21372
+ {
21373
+ sections: TEXT_BOX_SECTIONS,
21374
+ target: ts,
21375
+ onPatch: onUpdateTextStyle,
21376
+ disabled: !canEdit
21377
+ }
21378
+ ) })
22181
21379
  ] });
22182
21380
  }
22183
21381
  function TextReflectionSection({
@@ -22495,7 +21693,7 @@ function TextWarpGallery({
22495
21693
  onUpdateTextStyle
22496
21694
  }) {
22497
21695
  const { t } = useTranslation();
22498
- const [expanded, setExpanded] = React107.useState(false);
21696
+ const [expanded, setExpanded] = React108.useState(false);
22499
21697
  const currentPreset = ts?.textWarpPreset || "textNoShape";
22500
21698
  const descriptor = useMemo(() => buildTextWarpGallery(ts?.textWarpPreset), [ts?.textWarpPreset]);
22501
21699
  const ref = useRef(null);
@@ -22651,7 +21849,6 @@ function ShapeTextPanels({
22651
21849
  /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsx(
22652
21850
  RecentColorsRow,
22653
21851
  {
22654
- prefix: "text-color",
22655
21852
  disabled: !canEdit,
22656
21853
  onCommit: (hex) => onUpdateTextStyle({ color: hex, colorRef: void 0 })
22657
21854
  }
@@ -22930,205 +22127,6 @@ function SmartArtLayoutSwitcher({
22930
22127
  }) })
22931
22128
  ] });
22932
22129
  }
22933
- var DEFAULT_FILL = "#3b82f6";
22934
- var DEFAULT_FONT = "#ffffff";
22935
- var EMPHASIS_BTN = "px-1.5 py-0.5 text-[10px] rounded border transition-colors disabled:opacity-40 disabled:cursor-not-allowed";
22936
- function SmartArtNodeStyleControls({
22937
- nodeId,
22938
- style,
22939
- label,
22940
- canEdit,
22941
- onChangeStyle
22942
- }) {
22943
- const commitRecentColor = useRecentColorCommit();
22944
- const bold = Boolean(style?.bold);
22945
- const italic = Boolean(style?.italic);
22946
- return /* @__PURE__ */ jsxs(
22947
- "div",
22948
- {
22949
- className: "flex items-center gap-1.5 mt-1 pl-4",
22950
- role: "group",
22951
- "aria-label": `Style for ${label}`,
22952
- children: [
22953
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-0.5 text-[9px] text-muted-foreground", children: [
22954
- /* @__PURE__ */ jsx("span", { children: "Fill" }),
22955
- /* @__PURE__ */ jsx(
22956
- "input",
22957
- {
22958
- type: "color",
22959
- disabled: !canEdit,
22960
- "aria-label": `Fill colour for ${label}`,
22961
- className: "h-4 w-5 cursor-pointer rounded border border-border bg-transparent p-0 disabled:cursor-not-allowed",
22962
- value: style?.fillColor ?? DEFAULT_FILL,
22963
- ref: commitRecentColor,
22964
- onChange: (e) => onChangeStyle(nodeId, { fillColor: e.target.value })
22965
- }
22966
- )
22967
- ] }),
22968
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-0.5 text-[9px] text-muted-foreground", children: [
22969
- /* @__PURE__ */ jsx("span", { children: "Text" }),
22970
- /* @__PURE__ */ jsx(
22971
- "input",
22972
- {
22973
- type: "color",
22974
- disabled: !canEdit,
22975
- "aria-label": `Font colour for ${label}`,
22976
- className: "h-4 w-5 cursor-pointer rounded border border-border bg-transparent p-0 disabled:cursor-not-allowed",
22977
- value: style?.fontColor ?? DEFAULT_FONT,
22978
- ref: commitRecentColor,
22979
- onChange: (e) => onChangeStyle(nodeId, { fontColor: e.target.value })
22980
- }
22981
- )
22982
- ] }),
22983
- /* @__PURE__ */ jsx(
22984
- "button",
22985
- {
22986
- type: "button",
22987
- disabled: !canEdit,
22988
- "aria-label": `Bold ${label}`,
22989
- "aria-pressed": bold,
22990
- className: cn(
22991
- EMPHASIS_BTN,
22992
- "font-bold",
22993
- bold ? "border-primary bg-primary/20 text-primary" : "border-border text-muted-foreground"
22994
- ),
22995
- onClick: () => onChangeStyle(nodeId, { bold: !bold }),
22996
- children: "B"
22997
- }
22998
- ),
22999
- /* @__PURE__ */ jsx(
23000
- "button",
23001
- {
23002
- type: "button",
23003
- disabled: !canEdit,
23004
- "aria-label": `Italic ${label}`,
23005
- "aria-pressed": italic,
23006
- className: cn(
23007
- EMPHASIS_BTN,
23008
- "italic",
23009
- italic ? "border-primary bg-primary/20 text-primary" : "border-border text-muted-foreground"
23010
- ),
23011
- onClick: () => onChangeStyle(nodeId, { italic: !italic }),
23012
- children: "I"
23013
- }
23014
- )
23015
- ]
23016
- }
23017
- );
23018
- }
23019
- var MINI_BTN = "text-[9px] text-muted-foreground hover:text-primary px-1 disabled:opacity-40 disabled:cursor-not-allowed";
23020
- function SmartArtNodeRow({
23021
- nodeId,
23022
- text,
23023
- displayIndex,
23024
- isChild,
23025
- canEdit,
23026
- removeDisabled,
23027
- moveUpDisabled,
23028
- moveDownDisabled,
23029
- inputRef,
23030
- style,
23031
- onChangeText,
23032
- onKeyDown,
23033
- onAddSubItem,
23034
- onMoveUp,
23035
- onMoveDown,
23036
- onRemove,
23037
- onChangeStyle
23038
- }) {
23039
- const { t } = useTranslation();
23040
- const label = isChild ? `Sub-item: ${text || "empty"}` : `Item ${displayIndex}: ${text || "empty"}`;
23041
- return /* @__PURE__ */ jsxs(
23042
- "div",
23043
- {
23044
- role: "listitem",
23045
- className: cn(
23046
- "rounded border bg-background/60 p-1.5",
23047
- isChild ? "border-border/60 ml-4" : "border-border"
23048
- ),
23049
- children: [
23050
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
23051
- /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground w-3 shrink-0", "aria-hidden": "true", children: isChild ? "\u2022" : `${displayIndex}` }),
23052
- /* @__PURE__ */ jsx(
23053
- "input",
23054
- {
23055
- ref: inputRef,
23056
- type: "text",
23057
- "data-testid": "smartart-node-text",
23058
- disabled: !canEdit,
23059
- "aria-label": label,
23060
- className: cn(INPUT2, "flex-1 text-[11px] py-0.5"),
23061
- value: text,
23062
- onChange: (e) => onChangeText(nodeId, e.target.value),
23063
- onKeyDown: (e) => onKeyDown(e, nodeId),
23064
- placeholder: t("pptx.smartArt.nodePlaceholder")
23065
- }
23066
- ),
23067
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [
23068
- /* @__PURE__ */ jsx(
23069
- "button",
23070
- {
23071
- type: "button",
23072
- disabled: !canEdit || moveUpDisabled,
23073
- className: MINI_BTN,
23074
- onClick: () => onMoveUp(nodeId),
23075
- "aria-label": `Move ${label} up`,
23076
- title: t("pptx.smartArt.moveUp"),
23077
- children: "\u2191"
23078
- }
23079
- ),
23080
- /* @__PURE__ */ jsx(
23081
- "button",
23082
- {
23083
- type: "button",
23084
- disabled: !canEdit || moveDownDisabled,
23085
- className: MINI_BTN,
23086
- onClick: () => onMoveDown(nodeId),
23087
- "aria-label": `Move ${label} down`,
23088
- title: t("pptx.smartArt.moveDown"),
23089
- children: "\u2193"
23090
- }
23091
- ),
23092
- !isChild && /* @__PURE__ */ jsx(
23093
- "button",
23094
- {
23095
- type: "button",
23096
- disabled: !canEdit,
23097
- className: MINI_BTN,
23098
- onClick: () => onAddSubItem(nodeId),
23099
- "aria-label": `Add sub-item under ${label}`,
23100
- title: t("pptx.smartArt.addSubItem"),
23101
- children: "+Sub"
23102
- }
23103
- ),
23104
- /* @__PURE__ */ jsx(
23105
- "button",
23106
- {
23107
- type: "button",
23108
- disabled: !canEdit || removeDisabled,
23109
- className: cn(MINI_BTN, "hover:text-red-400"),
23110
- onClick: () => onRemove(nodeId),
23111
- "aria-label": `Remove ${label}`,
23112
- title: removeDisabled ? t("pptx.smartArt.layoutMinimum") : t("pptx.smartArt.remove"),
23113
- children: "x"
23114
- }
23115
- )
23116
- ] })
23117
- ] }),
23118
- /* @__PURE__ */ jsx(
23119
- SmartArtNodeStyleControls,
23120
- {
23121
- nodeId,
23122
- style,
23123
- label,
23124
- canEdit,
23125
- onChangeStyle
23126
- }
23127
- )
23128
- ]
23129
- }
23130
- );
23131
- }
23132
22130
  function SmartArtStyleControls({
23133
22131
  colorSchemes,
23134
22132
  styleOptions,
@@ -23139,7 +22137,7 @@ function SmartArtStyleControls({
23139
22137
  onChangeStyle
23140
22138
  }) {
23141
22139
  const { t } = useTranslation();
23142
- const translate = React107.useCallback((key) => t(key), [t]);
22140
+ const translate = React108.useCallback((key) => t(key), [t]);
23143
22141
  return /* @__PURE__ */ jsxs(Fragment, { children: [
23144
22142
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
23145
22143
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.smartart.colorScheme") }),
@@ -23191,22 +22189,9 @@ function SmartArtPropertiesPanel({
23191
22189
  box
23192
22190
  }) {
23193
22191
  const { t } = useTranslation();
23194
- const nodes = smartArtData.nodes ?? [];
23195
- const layout = smartArtData.resolvedLayoutType;
23196
- const topLevelCount = nodes.filter((n) => !n.parentId).length;
23197
- const inputRefs = React107.useRef(/* @__PURE__ */ new Map());
23198
- const pendingFocusId = React107.useRef(null);
23199
- React107.useEffect(() => {
23200
- const id = pendingFocusId.current;
23201
- if (id) {
23202
- inputRefs.current.get(id)?.focus();
23203
- pendingFocusId.current = null;
23204
- }
23205
- });
23206
- const applySmartArtData = (newData, focusId) => {
23207
- if (focusId) {
23208
- pendingFocusId.current = focusId;
23209
- }
22192
+ const { pushColor } = useRecentColors();
22193
+ const paneRef = React108.useRef(null);
22194
+ const applySmartArtData = (newData) => {
23210
22195
  const reflowed = box ? rebuildDrawingShapesIfCleared(
23211
22196
  newData,
23212
22197
  newData.layout,
@@ -23217,87 +22202,35 @@ function SmartArtPropertiesPanel({
23217
22202
  ) : newData;
23218
22203
  onUpdateElement({ smartArtData: reflowed });
23219
22204
  };
22205
+ const applyRef = React108.useRef(applySmartArtData);
22206
+ applyRef.current = applySmartArtData;
23220
22207
  const updateSmartArt = (patch) => {
23221
22208
  applySmartArtData({ ...smartArtData, ...patch });
23222
22209
  };
23223
- const handleUpdateNodeText = (nodeId, text) => {
23224
- applySmartArtData(updateSmartArtNodeText(smartArtData, nodeId, text));
23225
- };
23226
- const handleChangeNodeStyle = (nodeId, patch) => {
23227
- const next = setSmartArtNodeStyle(smartArtData, nodeId, patch);
23228
- if (next !== smartArtData) {
23229
- applySmartArtData(next);
23230
- }
23231
- };
23232
- const addNode = () => {
23233
- if (!canAddTopLevelNode(layout, topLevelCount)) {
23234
- return;
22210
+ React108.useLayoutEffect(() => {
22211
+ if (paneRef.current) {
22212
+ paneRef.current.state = {
22213
+ smartArtData,
22214
+ canEdit,
22215
+ translate: (key, params) => t(key, params)
22216
+ };
23235
22217
  }
23236
- applySmartArtData(addSmartArtNodeAsChild(smartArtData));
23237
- };
23238
- const addSubItem = (parentId) => {
23239
- applySmartArtData(addSmartArtNodeAsChild(smartArtData, parentId, "Sub-item"));
23240
- };
23241
- const removeNode = (nodeId) => {
23242
- const isTopLevel = !nodes.find((n) => n.id === nodeId)?.parentId;
23243
- if (isTopLevel && !canRemoveTopLevelNode(layout, topLevelCount)) {
22218
+ }, [smartArtData, canEdit, t]);
22219
+ React108.useEffect(() => {
22220
+ const pane = paneRef.current;
22221
+ if (!pane) {
23244
22222
  return;
23245
22223
  }
23246
- applySmartArtData(removeSmartArtNode(smartArtData, nodeId));
23247
- };
23248
- const moveNode = (nodeId, direction) => {
23249
- const next = reorder(smartArtData, nodeId, direction);
23250
- if (next) {
23251
- applySmartArtData(next, nodeId);
23252
- }
23253
- };
23254
- const handleKeyDown = (e, nodeId) => {
23255
- const node = nodes.find((n) => n.id === nodeId);
23256
- const isEmpty = !node?.text;
23257
- if (e.key === "Enter") {
23258
- e.preventDefault();
23259
- const result = addSiblingAfter(smartArtData, nodeId);
23260
- if (result) {
23261
- applySmartArtData(result.data, result.focusNodeId);
22224
+ const commit = (event) => {
22225
+ const { smartArtData: next, recentColor } = event.detail;
22226
+ applyRef.current(next);
22227
+ if (recentColor) {
22228
+ pushColor(recentColor);
23262
22229
  }
23263
- } else if ((e.key === "Backspace" || e.key === "Delete") && isEmpty) {
23264
- const isTop = !node?.parentId;
23265
- if (isTop && !canRemoveTopLevelNode(layout, topLevelCount)) {
23266
- return;
23267
- }
23268
- e.preventDefault();
23269
- const result = removeEmptyNode(smartArtData, nodeId);
23270
- if (result) {
23271
- applySmartArtData(result.data, result.focusNodeId);
23272
- }
23273
- } else if (e.key === "Tab" && !e.shiftKey) {
23274
- e.preventDefault();
23275
- const next = demote(smartArtData, nodeId);
23276
- if (next) {
23277
- applySmartArtData(next, nodeId);
23278
- }
23279
- } else if (e.key === "Tab" && e.shiftKey) {
23280
- e.preventDefault();
23281
- const next = promote(smartArtData, nodeId);
23282
- if (next) {
23283
- applySmartArtData(next, nodeId);
23284
- }
23285
- }
23286
- };
23287
- const setInputRef = (nodeId) => (el) => {
23288
- if (el) {
23289
- inputRefs.current.set(nodeId, el);
23290
- } else {
23291
- inputRefs.current.delete(nodeId);
23292
- }
23293
- };
23294
- const boundsHint = describeSmartArtBounds(layout);
23295
- const addDisabled = !canEdit || !canAddTopLevelNode(layout, topLevelCount);
23296
- const extraConnections = classifyExtraConnections(smartArtData);
23297
- const extraConnectionSummary = Array.from(
23298
- new Set(extraConnections.map((c) => c.type ?? "unknown"))
23299
- ).join(", ");
23300
- let topDisplayIndex = 0;
22230
+ };
22231
+ pane.addEventListener("pptx-smartart-data-change", commit);
22232
+ return () => pane.removeEventListener("pptx-smartart-data-change", commit);
22233
+ }, [pushColor]);
23301
22234
  return /* @__PURE__ */ jsxs("div", { className: CARD2, role: "group", "aria-label": t("pptx.smartart.title"), children: [
23302
22235
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.smartart.title") }),
23303
22236
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
@@ -23321,76 +22254,12 @@ function SmartArtPropertiesPanel({
23321
22254
  onChangeStyle: (style) => updateSmartArt({ style })
23322
22255
  }
23323
22256
  ),
23324
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
23325
- /* @__PURE__ */ jsxs("span", { className: "text-[11px] text-muted-foreground", children: [
23326
- t("pptx.smartart.textPane"),
23327
- " (",
23328
- nodes.length,
23329
- ")"
23330
- ] }),
23331
- /* @__PURE__ */ jsx(
23332
- "button",
23333
- {
23334
- type: "button",
23335
- disabled: addDisabled,
23336
- className: BTN2,
23337
- onClick: addNode,
23338
- title: addDisabled ? boundsHint : void 0,
23339
- children: t("pptx.smartart.addItem")
23340
- }
23341
- )
23342
- ] }),
23343
- boundsHint && /* @__PURE__ */ jsx("div", { className: "text-[9px] text-muted-foreground", role: "note", children: boundsHint }),
23344
- /* @__PURE__ */ jsx("div", { className: "max-h-52 overflow-y-auto space-y-1 pr-1", role: "list", children: nodes.map((node) => {
23345
- const isChild = Boolean(node.parentId);
23346
- if (!isChild) {
23347
- topDisplayIndex += 1;
23348
- }
23349
- const sIdx = siblingIndex(smartArtData, node.id);
23350
- const sCount = siblingCount(smartArtData, node.id);
23351
- const removeDisabled = nodes.length <= 1 || !isChild && !canRemoveTopLevelNode(layout, topLevelCount);
23352
- return /* @__PURE__ */ jsx(
23353
- SmartArtNodeRow,
23354
- {
23355
- nodeId: node.id,
23356
- text: node.text,
23357
- displayIndex: topDisplayIndex,
23358
- isChild,
23359
- canEdit,
23360
- removeDisabled,
23361
- moveUpDisabled: sIdx <= 0,
23362
- moveDownDisabled: sIdx < 0 || sIdx >= sCount - 1,
23363
- inputRef: setInputRef(node.id),
23364
- style: node.style,
23365
- onChangeText: handleUpdateNodeText,
23366
- onKeyDown: handleKeyDown,
23367
- onAddSubItem: addSubItem,
23368
- onMoveUp: (id) => moveNode(id, -1),
23369
- onMoveDown: (id) => moveNode(id, 1),
23370
- onRemove: removeNode,
23371
- onChangeStyle: handleChangeNodeStyle
23372
- },
23373
- node.id
23374
- );
23375
- }) }),
23376
- extraConnections.length > 0 && /* @__PURE__ */ jsxs(
23377
- "div",
23378
- {
23379
- className: "text-[9px] text-muted-foreground",
23380
- role: "note",
23381
- "aria-label": `${extraConnections.length} non-tree relationship connection(s): ${extraConnectionSummary}`,
23382
- children: [
23383
- t("pptx.smartart.extraConnections", { count: extraConnections.length }),
23384
- /* @__PURE__ */ jsx("span", { className: "block opacity-80", children: extraConnectionSummary })
23385
- ]
23386
- }
23387
- ),
23388
- /* @__PURE__ */ jsx("div", { className: "text-[9px] text-muted-foreground mt-1", children: t("pptx.smartart.tabHint") })
22257
+ /* @__PURE__ */ jsx("pptx-ui-smartart-text-pane", { ref: paneRef, "data-testid": "smartart-text-pane" })
23389
22258
  ] })
23390
22259
  ] });
23391
22260
  }
23392
22261
  var HEADER_CELL = "flex items-center justify-center gap-0.5 bg-muted text-muted-foreground border border-border -m-px px-1 py-0.5 whitespace-nowrap";
23393
- var CELL_INPUT2 = "w-full box-border bg-muted px-1 py-0.5 text-[11px] border-0 outline-none focus:bg-accent disabled:opacity-60";
22262
+ var CELL_INPUT = "w-full box-border bg-muted px-1 py-0.5 text-[11px] border-0 outline-none focus:bg-accent disabled:opacity-60";
23394
22263
  var REMOVE_BTN = "px-0.5 leading-none text-destructive hover:opacity-80";
23395
22264
  function TableDataGrid({
23396
22265
  tableElement,
@@ -23534,7 +22403,7 @@ function TableDataGrid({
23534
22403
  "input",
23535
22404
  {
23536
22405
  type: "text",
23537
- className: CELL_INPUT2,
22406
+ className: CELL_INPUT,
23538
22407
  disabled: !canEdit,
23539
22408
  "aria-label": t("pptx.tableDataEditor.cellAriaLabel", {
23540
22409
  row: cell.rowIndex + 1,
@@ -24537,21 +23406,15 @@ function ElementInspectorBody({
24537
23406
  }
24538
23407
  )
24539
23408
  ] }),
24540
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1.5 text-[11px]", children: POS_FIELDS.map(([label, key]) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1", children: [
24541
- /* @__PURE__ */ jsx("span", { className: "w-4 text-muted-foreground", children: label }),
24542
- /* @__PURE__ */ jsx(
24543
- "input",
24544
- {
24545
- type: "number",
24546
- className: INPUT2,
24547
- disabled: !canEdit,
24548
- value: Math.round(selectedElement[key] ?? 0),
24549
- onChange: (e) => onUpdateElement({
24550
- [key]: Number(e.target.value)
24551
- })
24552
- }
24553
- )
24554
- ] }, key)) })
23409
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1.5 text-[11px]", children: /* @__PURE__ */ jsx(
23410
+ InspectorFields,
23411
+ {
23412
+ sections: ELEMENT_GEOMETRY_SECTIONS,
23413
+ target: selectedElement,
23414
+ onPatch: (patch) => onUpdateElement(patch),
23415
+ disabled: !canEdit
23416
+ }
23417
+ ) })
24555
23418
  ] }),
24556
23419
  selectedElement.type === "table" && /* @__PURE__ */ jsxs(Fragment, { children: [
24557
23420
  /* @__PURE__ */ jsx(
@@ -24790,7 +23653,7 @@ function CommentBody({ text, mentions, className }) {
24790
23653
  index
24791
23654
  ) : (
24792
23655
  // eslint-disable-next-line react/no-array-index-key -- segments are positional
24793
- /* @__PURE__ */ jsx(React107.Fragment, { children: segment.text }, index)
23656
+ /* @__PURE__ */ jsx(React108.Fragment, { children: segment.text }, index)
24794
23657
  )
24795
23658
  ) });
24796
23659
  }
@@ -26307,7 +25170,7 @@ function PresentationPropertiesPanel({
26307
25170
  onUpdateTagCollections
26308
25171
  }) {
26309
25172
  const { t } = useTranslation();
26310
- const handleTransitionChange = React107.useCallback(
25173
+ const handleTransitionChange = React108.useCallback(
26311
25174
  (updates) => {
26312
25175
  onUpdateSlide({
26313
25176
  transition: mergeSlideTransition(activeSlide?.transition, updates)
@@ -29788,7 +28651,7 @@ function ViewerToolbarSection(props) {
29788
28651
  },
29789
28652
  [activeSlide, propertyHandlers]
29790
28653
  );
29791
- const scopedLayoutOptions = React107.useMemo(
28654
+ const scopedLayoutOptions = React108.useMemo(
29792
28655
  () => scopeLayoutOptionsToActiveSlide(s.layoutOptions, activeSlide),
29793
28656
  [s.layoutOptions, activeSlide]
29794
28657
  );
@@ -30064,6 +28927,7 @@ function ViewerToolbarSection(props) {
30064
28927
  onAddShape: insertHandlers.handleAddShape,
30065
28928
  onAddTable: insertHandlers.handleAddTable,
30066
28929
  onAddChart: insertHandlers.handleAddChart,
28930
+ onOpenChartDialog: () => dialogs.setIsChartDialogOpen(true),
30067
28931
  onAddSmartArt: () => dialogs.setIsSmartArtDialogOpen(true),
30068
28932
  onAddEquation: () => {
30069
28933
  dialogs.setEditingEquationOmml(null);
@@ -30456,183 +29320,67 @@ function EquationEditorDialog({
30456
29320
  }
30457
29321
  );
30458
29322
  }
30459
- var PREVIEW_TILE_WIDTH2 = 64;
30460
- function getPreviewForLayout(layout) {
30461
- const scale = PREVIEW_TILE_WIDTH2 / SMARTART_PREVIEW_ELEMENT_WIDTH;
30462
- return /* @__PURE__ */ jsx(
30463
- "div",
30464
- {
30465
- "aria-hidden": true,
30466
- className: "overflow-hidden pointer-events-none",
30467
- style: {
30468
- width: PREVIEW_TILE_WIDTH2,
30469
- height: Math.round(SMARTART_PREVIEW_ELEMENT_HEIGHT * scale)
30470
- },
30471
- children: /* @__PURE__ */ jsx(
30472
- "div",
30473
- {
30474
- style: {
30475
- width: SMARTART_PREVIEW_ELEMENT_WIDTH,
30476
- height: SMARTART_PREVIEW_ELEMENT_HEIGHT,
30477
- transform: `scale(${scale})`,
30478
- transformOrigin: "top left"
30479
- },
30480
- children: /* @__PURE__ */ jsx(SmartArtRenderer, { element: buildSmartArtPreviewElement(layout) })
30481
- }
30482
- )
29323
+ function useDialogEvents(ref, insertEvent, onInsert, onClose) {
29324
+ useEffect(() => {
29325
+ const host = ref.current;
29326
+ if (!host) {
29327
+ return;
30483
29328
  }
30484
- );
29329
+ host.addEventListener(insertEvent, onInsert);
29330
+ host.addEventListener("dialog-close", onClose);
29331
+ return () => {
29332
+ host.removeEventListener(insertEvent, onInsert);
29333
+ host.removeEventListener("dialog-close", onClose);
29334
+ };
29335
+ }, [ref, insertEvent, onInsert, onClose]);
30485
29336
  }
30486
29337
  function InsertSmartArtDialog({
30487
29338
  isOpen,
30488
29339
  onClose,
30489
29340
  onInsert
30490
29341
  }) {
29342
+ const ref = useRef(null);
30491
29343
  const { t } = useTranslation();
30492
- const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
30493
- const [activeCategory, setActiveCategory] = useState("list");
30494
- const [selectedLayout, setSelectedLayout] = useState(null);
30495
- const dialogRef = useRef(null);
30496
- useModalFocus(isOpen, dialogRef, onClose);
30497
- const filteredPresets = PRESETS.filter((p) => p.category === activeCategory);
30498
- const handleInsert = useCallback(() => {
30499
- if (!selectedLayout) {
30500
- return;
29344
+ useLayoutEffect(() => {
29345
+ if (ref.current) {
29346
+ ref.current.translateLabel = t;
29347
+ ref.current.open = isOpen;
30501
29348
  }
30502
- const preset = PRESETS.find((p) => p.layout === selectedLayout);
30503
- if (!preset) {
30504
- return;
29349
+ }, [isOpen, t]);
29350
+ useDialogEvents(
29351
+ ref,
29352
+ "insert-smartart",
29353
+ (event) => {
29354
+ const { layout, items } = event.detail;
29355
+ onInsert(layout, items);
29356
+ },
29357
+ onClose
29358
+ );
29359
+ return /* @__PURE__ */ jsx("pptx-ui-insert-smartart-dialog", { ref });
29360
+ }
29361
+ function InsertChartDialog({
29362
+ isOpen,
29363
+ onClose,
29364
+ onInsert
29365
+ }) {
29366
+ const ref = useRef(null);
29367
+ const { t } = useTranslation();
29368
+ useLayoutEffect(() => {
29369
+ if (ref.current) {
29370
+ ref.current.translateLabel = t;
29371
+ ref.current.open = isOpen;
30505
29372
  }
30506
- onInsert(preset.layout, preset.defaultItems);
30507
- onClose();
30508
- }, [selectedLayout, onInsert, onClose]);
30509
- if (!isOpen) {
30510
- return null;
30511
- }
30512
- return /* @__PURE__ */ jsxs(Fragment, { children: [
30513
- /* @__PURE__ */ jsx(
30514
- "button",
30515
- {
30516
- type: "button",
30517
- style: { zIndex: 1200 },
30518
- className: "fixed inset-0 bg-black/50",
30519
- onClick: onClose,
30520
- "aria-label": t("pptx.smartart.close")
30521
- }
30522
- ),
30523
- /* @__PURE__ */ jsx(
30524
- "div",
30525
- {
30526
- style: { zIndex: 1201 },
30527
- className: "fixed inset-0 flex items-center justify-center pointer-events-none",
30528
- children: /* @__PURE__ */ jsxs(
30529
- "div",
30530
- {
30531
- ref: dialogRef,
30532
- style: panelStyle,
30533
- className: "pointer-events-auto w-[600px] max-w-[90vw] max-h-[80vh] rounded-lg border border-border bg-background shadow-2xl flex flex-col max-md:fixed max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:w-full max-md:max-w-none max-md:max-h-[88dvh] max-md:rounded-t-2xl max-md:rounded-b-none max-md:border-x-0 max-md:border-b-0 max-md:pb-[max(env(safe-area-inset-bottom),0px)]",
30534
- role: "dialog",
30535
- "aria-modal": "true",
30536
- "aria-label": t("pptx.smartart.insertTitle"),
30537
- tabIndex: -1,
30538
- children: [
30539
- /* @__PURE__ */ jsxs(
30540
- "div",
30541
- {
30542
- ...dragHandlers,
30543
- className: "flex items-center justify-between px-4 py-3 border-b border-border touch-none",
30544
- children: [
30545
- /* @__PURE__ */ jsx("h2", { className: "text-sm font-medium text-foreground", children: t("pptx.smartart.insertTitle") }),
30546
- /* @__PURE__ */ jsx(
30547
- "button",
30548
- {
30549
- type: "button",
30550
- onClick: onClose,
30551
- className: "p-1 rounded hover:bg-muted transition-colors",
30552
- "aria-label": t("pptx.smartart.close"),
30553
- children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
30554
- }
30555
- )
30556
- ]
30557
- }
30558
- ),
30559
- /* @__PURE__ */ jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
30560
- /* @__PURE__ */ jsx(
30561
- "nav",
30562
- {
30563
- className: "w-40 border-r border-border py-2",
30564
- "aria-label": t("pptx.insertSmartArt.categories"),
30565
- children: CATEGORIES.map((cat) => /* @__PURE__ */ jsx(
30566
- "button",
30567
- {
30568
- type: "button",
30569
- onClick: () => {
30570
- setActiveCategory(cat.id);
30571
- setSelectedLayout(null);
30572
- },
30573
- className: cn(
30574
- "w-full text-left px-3 py-1.5 text-xs transition-colors",
30575
- activeCategory === cat.id ? "bg-primary text-white" : "text-foreground hover:bg-muted"
30576
- ),
30577
- children: t(cat.label)
30578
- },
30579
- cat.id
30580
- ))
30581
- }
30582
- ),
30583
- /* @__PURE__ */ jsx("div", { className: "flex-1 p-3 overflow-y-auto", children: /* @__PURE__ */ jsx(
30584
- "div",
30585
- {
30586
- className: "grid grid-cols-3 gap-2",
30587
- role: "listbox",
30588
- "aria-label": t("pptx.insertSmartArt.layouts"),
30589
- children: filteredPresets.map((preset) => /* @__PURE__ */ jsxs(
30590
- "button",
30591
- {
30592
- type: "button",
30593
- role: "option",
30594
- "aria-selected": selectedLayout === preset.layout,
30595
- onClick: () => setSelectedLayout(preset.layout),
30596
- onDoubleClick: () => {
30597
- setSelectedLayout(preset.layout);
30598
- onInsert(preset.layout, preset.defaultItems);
30599
- onClose();
30600
- },
30601
- className: cn(
30602
- "flex flex-col items-center gap-1 p-2 rounded border transition-colors",
30603
- selectedLayout === preset.layout ? "border-primary bg-primary/20" : "border-border hover:border-border hover:bg-muted/50"
30604
- ),
30605
- children: [
30606
- /* @__PURE__ */ jsx("div", { className: "w-16 h-12 flex items-center justify-center bg-muted rounded", children: getPreviewForLayout(preset.layout) }),
30607
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-foreground text-center leading-tight", children: t(preset.labelKey) })
30608
- ]
30609
- },
30610
- preset.layout
30611
- ))
30612
- }
30613
- ) })
30614
- ] }),
30615
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
30616
- DialogFooter,
30617
- {
30618
- actions: [
30619
- { id: "cancel", label: t("pptx.smartart.cancel") },
30620
- {
30621
- id: "insert",
30622
- label: t("pptx.smartart.insert"),
30623
- variant: "primary",
30624
- disabled: !selectedLayout
30625
- }
30626
- ],
30627
- onAction: (id) => id === "insert" ? handleInsert() : onClose()
30628
- }
30629
- ) })
30630
- ]
30631
- }
30632
- )
30633
- }
30634
- )
30635
- ] });
29373
+ }, [isOpen, t]);
29374
+ useDialogEvents(
29375
+ ref,
29376
+ "insert-chart",
29377
+ (event) => {
29378
+ const { kind, title, grouping } = event.detail;
29379
+ onInsert(kind, { title, grouping });
29380
+ },
29381
+ onClose
29382
+ );
29383
+ return /* @__PURE__ */ jsx("pptx-ui-insert-chart-dialog", { ref });
30636
29384
  }
30637
29385
  function ViewerDialogGroup(props) {
30638
29386
  const {
@@ -30758,6 +29506,14 @@ function ViewerDialogGroup(props) {
30758
29506
  onInsert: insertHandlers.handleInsertSmartArt
30759
29507
  }
30760
29508
  ),
29509
+ /* @__PURE__ */ jsx(
29510
+ InsertChartDialog,
29511
+ {
29512
+ isOpen: dialogs.isChartDialogOpen,
29513
+ onClose: () => dialogs.setIsChartDialogOpen(false),
29514
+ onInsert: insertHandlers.handleAddChart
29515
+ }
29516
+ ),
30761
29517
  /* @__PURE__ */ jsx(
30762
29518
  EquationEditorDialog,
30763
29519
  {
@@ -31742,7 +30498,7 @@ function useTableStyleMapHandlers(input) {
31742
30498
  var AiChatPanel = /* @__PURE__ */ lazy(async () => {
31743
30499
  const [{ useChat }, { default: Panel }] = await Promise.all([
31744
30500
  import('@ai-sdk/react'),
31745
- import('./AiChatPanel-NKTBHT5B.mjs')
30501
+ import('./AiChatPanel-VJV5OEG2.mjs')
31746
30502
  ]);
31747
30503
  function BoundAiChatPanel(props) {
31748
30504
  return /* @__PURE__ */ jsx(Panel, { ...props, useChat });
@@ -34009,253 +32765,120 @@ function useAiBridge(input) {
34009
32765
  const ref = useRef(input);
34010
32766
  ref.current = input;
34011
32767
  return useMemo(() => {
34012
- const applySlidesUpdate = (updater, _label) => {
34013
- const live = ref.current;
34014
- live.setSlides((prev) => updater(structuredClone(prev)));
34015
- live.bumpHistory();
34016
- live.markDirty();
34017
- };
34018
- const readDeckData = (live) => ({
34019
- slides: live.slides,
34020
- width: live.canvasSize.width,
34021
- height: live.canvasSize.height,
34022
- theme: live.theme,
34023
- sections: live.sections,
34024
- presentationProperties: live.presentationProperties,
34025
- customProperties: live.customProperties,
34026
- coreProperties: live.coreProperties,
34027
- appProperties: live.appProperties,
34028
- viewProperties: live.viewProperties,
34029
- tableStyleMap: live.tableStyleMap,
34030
- tableStylesDefaultId: live.tableStylesDefaultId,
34031
- tags: live.tagCollections
34032
- });
34033
- const differs = deckDataFieldChanged;
34034
- return {
34035
- getDeckMeta() {
34036
- const live = ref.current;
34037
- const firstTitle = live.slides[0]?.elements.find(
34038
- (el) => "text" in el && typeof el.text === "string" && el.text.trim().length > 0
34039
- );
34040
- return {
34041
- slideCount: live.slides.length,
34042
- activeSlideIndex: live.activeSlideIndex,
34043
- title: live.fileName ?? (firstTitle && "text" in firstTitle ? String(firstTitle.text) : void 0),
34044
- width: live.canvasSize.width,
34045
- height: live.canvasSize.height
34046
- };
34047
- },
34048
- getSlides: () => ref.current.slides,
34049
- getActiveSlideIndex: () => ref.current.activeSlideIndex,
34050
- getTheme: () => ref.current.theme,
34051
- getHandler: () => ref.current.handlerRef.current ?? void 0,
34052
- goToSlide(index) {
34053
- ref.current.setActiveSlideIndex(index);
34054
- },
32768
+ const live = () => ref.current;
32769
+ return createPptxAiBridge({
32770
+ getSlides: () => live().slides,
32771
+ getActiveSlideIndex: () => live().activeSlideIndex,
32772
+ getCanvasSize: () => live().canvasSize,
32773
+ getTheme: () => live().theme,
32774
+ getHandler: () => live().handlerRef.current,
32775
+ getFileName: () => live().fileName,
32776
+ getSections: () => live().sections,
32777
+ getPresentationProperties: () => live().presentationProperties,
32778
+ getCustomProperties: () => live().customProperties,
32779
+ getCoreProperties: () => live().coreProperties,
32780
+ getAppProperties: () => live().appProperties,
32781
+ getViewProperties: () => live().viewProperties,
32782
+ getTableStyleMap: () => live().tableStyleMap,
32783
+ getTableStylesDefaultId: () => live().tableStylesDefaultId,
32784
+ getTagCollections: () => live().tagCollections,
32785
+ goToSlide: (index) => live().setActiveSlideIndex(index),
34055
32786
  selectElements(slideIndex, elementIds) {
34056
- const live = ref.current;
34057
- if (slideIndex !== live.activeSlideIndex) {
34058
- live.setActiveSlideIndex(slideIndex);
32787
+ const current = live();
32788
+ if (slideIndex !== current.activeSlideIndex) {
32789
+ current.setActiveSlideIndex(slideIndex);
34059
32790
  }
34060
- live.applySelection(elementIds[0] ?? null, elementIds);
34061
- },
34062
- applySlidesUpdate,
34063
- updateElement(slideIndex, elementId2, updates) {
34064
- applySlidesUpdate((slides) => {
34065
- const el = slides[slideIndex]?.elements.find((e) => e.id === elementId2);
34066
- if (el) {
34067
- applyElementUpdate(el, updates);
34068
- }
34069
- return slides;
34070
- });
34071
- },
34072
- applyTheme(updates) {
34073
- ref.current.applyThemeUpdates(updates);
32791
+ current.applySelection(elementIds[0] ?? null, elementIds);
34074
32792
  },
34075
- getDeckData() {
34076
- return readDeckData(ref.current);
32793
+ updateSlides(update) {
32794
+ const current = live();
32795
+ current.setSlides((prev) => update(prev));
32796
+ current.bumpHistory();
32797
+ current.markDirty();
34077
32798
  },
34078
- applyDeckData(updater, _label) {
34079
- const live = ref.current;
34080
- const before = readDeckData(live);
34081
- const after = updater(structuredClone(before));
34082
- if (differs(before.slides, after.slides)) {
34083
- live.setSlides(() => after.slides);
34084
- live.bumpHistory();
34085
- }
34086
- if (before.width !== after.width || before.height !== after.height) {
34087
- live.setCanvasSize({ width: after.width, height: after.height });
34088
- }
34089
- const nextSections = after.sections ?? before.sections ?? [];
34090
- if (differs(before.sections, nextSections)) {
34091
- live.setSections(nextSections);
34092
- }
34093
- const nextPresProps = after.presentationProperties ?? live.presentationProperties;
34094
- if (differs(before.presentationProperties, nextPresProps)) {
34095
- live.setPresentationProperties(nextPresProps);
34096
- }
34097
- const nextCustomProps = after.customProperties ?? before.customProperties ?? [];
34098
- if (differs(before.customProperties, nextCustomProps)) {
34099
- live.setCustomProperties(nextCustomProps);
34100
- }
34101
- if (differs(before.coreProperties, after.coreProperties)) {
34102
- live.setCoreProperties(after.coreProperties);
34103
- }
34104
- if (differs(before.appProperties, after.appProperties)) {
34105
- live.setAppProperties(after.appProperties);
34106
- }
34107
- if (differs(before.viewProperties, after.viewProperties)) {
34108
- live.setViewProperties(after.viewProperties);
34109
- }
34110
- if (differs(before.tableStyleMap, after.tableStyleMap)) {
34111
- live.setTableStyleMap(after.tableStyleMap);
34112
- }
34113
- if (differs(before.tableStylesDefaultId, after.tableStylesDefaultId)) {
34114
- live.setTableStylesDefaultId(after.tableStylesDefaultId);
34115
- }
34116
- const nextTags = after.tags ?? before.tags ?? [];
34117
- if (differs(before.tags, nextTags)) {
34118
- live.setTagCollections(nextTags);
34119
- }
34120
- live.markDirty();
32799
+ applyTheme: (updates) => live().applyThemeUpdates(updates),
32800
+ setCanvasSize: (size) => live().setCanvasSize(size),
32801
+ setSections: (sections) => live().setSections(sections),
32802
+ setPresentationProperties: (props) => live().setPresentationProperties(props),
32803
+ setDocumentProperties(core, app, custom) {
32804
+ const current = live();
32805
+ current.setCoreProperties(core);
32806
+ current.setAppProperties(app);
32807
+ current.setCustomProperties(custom);
34121
32808
  },
32809
+ setViewProperties: (props) => live().setViewProperties(props),
32810
+ setTableStyleMap: (map) => live().setTableStyleMap(map),
32811
+ setTableStylesDefaultId: (id) => live().setTableStylesDefaultId(id),
32812
+ setTagCollections: (tags) => live().setTagCollections(tags),
32813
+ afterDeckUpdate: () => live().markDirty(),
34122
32814
  getFocusedTargets() {
34123
- const live = ref.current;
34124
- if (live.pickedFocus && live.pickedFocus.length > 0) {
34125
- return live.pickedFocus;
34126
- }
34127
- if (live.pinnedFocus && live.pinnedFocus.length > 0) {
34128
- return live.pinnedFocus;
34129
- }
34130
- return computeFocusTargets({
34131
- activeSlideIndex: live.activeSlideIndex,
34132
- selectedElementIds: live.selectedElementIds,
34133
- selectedElementId: live.selectedElementId
34134
- });
32815
+ const current = live();
32816
+ return resolveAiEffectiveTargets(
32817
+ { pickTargets: current.pickedFocus ?? [], pinnedFocus: current.pinnedFocus },
32818
+ computeFocusTargets({
32819
+ activeSlideIndex: current.activeSlideIndex,
32820
+ selectedElementIds: current.selectedElementIds,
32821
+ selectedElementId: current.selectedElementId
32822
+ })
32823
+ );
34135
32824
  },
34136
- notify(message, level) {
34137
- ref.current.notify?.(message, level);
34138
- }
34139
- };
32825
+ notify: (message, level) => live().notify?.(message, level)
32826
+ });
34140
32827
  }, []);
34141
32828
  }
34142
- var TOOL_FLASH_MS = 2600;
34143
- function fixDirective(element, slideIndex) {
34144
- return `Review and fix any issues with this ${element.type} (id=${element.id}) on slide ${slideIndex + 1}.`;
34145
- }
34146
32829
  function useAiPanelController(input) {
34147
- const { activeSlideIndex, selectedElementId, selectedElementIds, selectedElement } = input;
34148
- const [isOpen, setIsOpen] = useState(false);
34149
- const [pinnedFocus, setPinnedFocus] = useState(null);
34150
- const [prefill, setPrefill] = useState({ text: "", nonce: 0 });
34151
- const [pickMode, setPickMode] = useState(false);
34152
- const [pickTargets, setPickTargets] = useState([]);
34153
- const [toolFocus, setToolFocus] = useState(
34154
- null
32830
+ const { activeSlideIndex, selectedElementId, selectedElementIds } = input;
32831
+ const inputRef = useRef(input);
32832
+ inputRef.current = input;
32833
+ const [controller] = useState(
32834
+ () => createPptxAiPanelController({
32835
+ getSelection: () => ({
32836
+ activeSlideIndex: inputRef.current.activeSlideIndex,
32837
+ selectedElementIds: inputRef.current.selectedElementIds,
32838
+ selectedElementId: inputRef.current.selectedElementId
32839
+ }),
32840
+ getSelectedElement: () => inputRef.current.selectedElement
32841
+ })
34155
32842
  );
34156
- const [flashTick, setFlashTick] = useState(0);
34157
- const flashTimer = useRef(null);
34158
- const [changeBatch, setChangeBatch] = useState(null);
34159
- const showChangeBatch = useCallback((batch) => setChangeBatch(batch), []);
32843
+ const state = useController(controller);
32844
+ useEffect(() => () => controller.dispose(), [controller]);
34160
32845
  const liveFocusTargets = useMemo(
34161
32846
  () => computeFocusTargets({ activeSlideIndex, selectedElementIds, selectedElementId }),
34162
32847
  [activeSlideIndex, selectedElementIds, selectedElementId]
34163
32848
  );
34164
- const open = useCallback(() => setIsOpen(true), []);
34165
- const close = useCallback(() => setIsOpen(false), []);
34166
- const toggle = useCallback(() => setIsOpen((p) => !p), []);
34167
- const pinFocus = useCallback(() => setPinnedFocus(liveFocusTargets), [liveFocusTargets]);
34168
- const clearPinnedFocus = useCallback(() => setPinnedFocus(null), []);
34169
- const askAboutSelection = useCallback(() => {
34170
- setPinnedFocus(liveFocusTargets);
34171
- setPrefill((p) => ({ text: "", nonce: p.nonce + 1 }));
34172
- setIsOpen(true);
34173
- }, [liveFocusTargets]);
34174
- const fixSelection = useCallback(() => {
34175
- setPinnedFocus(liveFocusTargets);
34176
- const text = selectedElement ? fixDirective(selectedElement, activeSlideIndex) : "";
34177
- setPrefill((p) => ({ text, nonce: p.nonce + 1 }));
34178
- setIsOpen(true);
34179
- }, [liveFocusTargets, selectedElement, activeSlideIndex]);
34180
- const startPicking = useCallback(() => {
34181
- setPickMode(true);
34182
- setIsOpen(true);
34183
- }, []);
34184
- const stopPicking = useCallback(() => setPickMode(false), []);
34185
- const addPick = useCallback((slideIndex, elementId2) => {
34186
- setPickTargets((prev) => {
34187
- if (prev.some((t) => t.kind === "element" && t.elementId === elementId2)) {
34188
- return prev;
34189
- }
34190
- return [...prev, { kind: "element", slideIndex, elementId: elementId2 }];
34191
- });
34192
- }, []);
34193
- const clearPicks = useCallback(() => {
34194
- setPickTargets([]);
34195
- setPickMode(false);
34196
- }, []);
34197
- const flashToolTarget = useCallback((target) => {
34198
- if (target && target.slideIndex !== void 0 && target.elementIds.length > 0) {
34199
- setToolFocus({ slideIndex: target.slideIndex, elementIds: target.elementIds });
34200
- } else {
34201
- setToolFocus(null);
34202
- }
34203
- setFlashTick((n) => n + 1);
34204
- if (flashTimer.current) {
34205
- clearTimeout(flashTimer.current);
34206
- }
34207
- flashTimer.current = setTimeout(() => {
34208
- setToolFocus(null);
34209
- setFlashTick(0);
34210
- }, TOOL_FLASH_MS);
34211
- }, []);
34212
- useEffect(
34213
- () => () => {
34214
- if (flashTimer.current) {
34215
- clearTimeout(flashTimer.current);
34216
- }
34217
- },
34218
- []
32849
+ const actions = useMemo(
32850
+ () => ({
32851
+ open: () => controller.open(),
32852
+ close: () => controller.close(),
32853
+ toggle: () => controller.toggle(),
32854
+ pinFocus: () => controller.pinFocus(),
32855
+ clearPinnedFocus: () => controller.clearPinnedFocus(),
32856
+ askAboutSelection: () => controller.askAboutSelection(),
32857
+ fixSelection: () => controller.fixSelection(),
32858
+ startPicking: () => controller.startPicking(),
32859
+ stopPicking: () => controller.stopPicking(),
32860
+ addPick: (slideIndex, elementId2) => controller.addPick(slideIndex, elementId2),
32861
+ clearPicks: () => controller.clearPicks(),
32862
+ flashToolTarget: (target) => controller.flashToolTarget(target),
32863
+ showChangeBatch: (batch) => controller.showChangeBatch(batch)
32864
+ }),
32865
+ [controller]
32866
+ );
32867
+ return useMemo(
32868
+ () => ({
32869
+ ...actions,
32870
+ isOpen: state.isOpen,
32871
+ liveFocusTargets,
32872
+ pinnedFocus: state.pinnedFocus,
32873
+ prefill: state.prefill,
32874
+ pickMode: state.pickMode,
32875
+ pickTargets: state.pickTargets,
32876
+ canvasHighlights: state.canvasHighlights,
32877
+ canvasAnimating: state.canvasAnimating,
32878
+ changeBatch: state.changeBatch
32879
+ }),
32880
+ [actions, liveFocusTargets, state]
34219
32881
  );
34220
- const canvasHighlights = useMemo(() => {
34221
- const out = [];
34222
- for (const t of pickTargets) {
34223
- if (t.kind === "element") {
34224
- out.push({ slideIndex: t.slideIndex, elementId: t.elementId, variant: "pick" });
34225
- }
34226
- }
34227
- if (toolFocus) {
34228
- for (const elementId2 of toolFocus.elementIds) {
34229
- out.push({ slideIndex: toolFocus.slideIndex, elementId: elementId2, variant: "active" });
34230
- }
34231
- }
34232
- return out;
34233
- }, [pickTargets, toolFocus]);
34234
- const canvasAnimating = canvasHighlights.length > 0 || flashTick > 0;
34235
- return {
34236
- isOpen,
34237
- open,
34238
- close,
34239
- toggle,
34240
- liveFocusTargets,
34241
- pinnedFocus,
34242
- pinFocus,
34243
- clearPinnedFocus,
34244
- prefill,
34245
- askAboutSelection,
34246
- fixSelection,
34247
- pickMode,
34248
- startPicking,
34249
- stopPicking,
34250
- pickTargets,
34251
- addPick,
34252
- clearPicks,
34253
- canvasHighlights,
34254
- canvasAnimating,
34255
- flashToolTarget,
34256
- changeBatch,
34257
- showChangeBatch
34258
- };
34259
32882
  }
34260
32883
  function useCollaborationStateReport(collab, onChange) {
34261
32884
  const callback = useRef(onChange);