pptx-react-viewer 4.48.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 +126 -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-5FAX7F3O.js → chunk-4OF7X5EE.js} +1754 -3189
  9. package/dist/chunk-4OF7X5EE.js.br +0 -0
  10. package/dist/chunk-4OF7X5EE.js.gz +0 -0
  11. package/dist/{chunk-H7JRMKYC.mjs → chunk-5JJQLK7N.mjs} +542 -1977
  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-JKZNL6HP.js → chunk-D5NXYXPP.js} +773 -1245
  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-JHQHAO43.mjs → chunk-QHGEPW5G.mjs} +596 -1068
  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-3VVZGHHY.mjs.br +0 -0
  99. package/dist/chunk-3VVZGHHY.mjs.gz +0 -0
  100. package/dist/chunk-5FAX7F3O.js.br +0 -0
  101. package/dist/chunk-5FAX7F3O.js.gz +0 -0
  102. package/dist/chunk-H7JRMKYC.mjs.br +0 -0
  103. package/dist/chunk-H7JRMKYC.mjs.gz +0 -0
  104. package/dist/chunk-JAI42EXQ.js.br +0 -0
  105. package/dist/chunk-JAI42EXQ.js.gz +0 -0
  106. package/dist/chunk-JHQHAO43.mjs.br +0 -0
  107. package/dist/chunk-JHQHAO43.mjs.gz +0 -0
  108. package/dist/chunk-JKZNL6HP.js.br +0 -0
  109. package/dist/chunk-JKZNL6HP.js.gz +0 -0
  110. package/dist/chunk-NUNDT6EL.js.br +0 -0
  111. package/dist/chunk-NUNDT6EL.js.gz +0 -0
  112. package/dist/chunk-PFV626ED.mjs.br +0 -0
  113. package/dist/chunk-PFV626ED.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-JHQHAO43.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, 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, clampPercent, 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.48.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({
@@ -8044,41 +8050,11 @@ function ExportProgressModal({
8044
8050
  onCancel
8045
8051
  }) {
8046
8052
  const { t } = useTranslation();
8047
- if (!isOpen) {
8048
- return null;
8049
- }
8050
- const clampedProgress = clampPercent(progress);
8051
- return /* @__PURE__ */ jsx(
8052
- "div",
8053
- {
8054
- style: { zIndex: 1200 },
8055
- className: "fixed inset-0 flex items-center justify-center bg-black/60 backdrop-blur-sm",
8056
- children: /* @__PURE__ */ jsxs("div", { className: "w-96 max-w-[calc(100%-2rem)] rounded-xl border border-border bg-background p-6 shadow-2xl", children: [
8057
- /* @__PURE__ */ jsx("h3", { className: "mb-4 text-sm font-semibold text-foreground", children: title }),
8058
- /* @__PURE__ */ jsx("div", { className: "mb-3 h-2.5 w-full overflow-hidden rounded-full bg-accent", children: /* @__PURE__ */ jsx(
8059
- "div",
8060
- {
8061
- className: "h-full rounded-full bg-primary transition-all duration-300 ease-out",
8062
- style: { width: `${clampedProgress}%` }
8063
- }
8064
- ) }),
8065
- /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center justify-between text-xs text-muted-foreground", children: [
8066
- /* @__PURE__ */ jsx("span", { children: statusMessage ?? t("pptx.export.processing") }),
8067
- /* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
8068
- clampedProgress,
8069
- "%"
8070
- ] })
8071
- ] }),
8072
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
8073
- DialogFooter,
8074
- {
8075
- actions: [{ id: "cancel", label: t("pptx.export.cancel") }],
8076
- onAction: onCancel
8077
- }
8078
- ) })
8079
- ] })
8080
- }
8053
+ const ref = useWebControl(
8054
+ { open: isOpen, title, progress, status: statusMessage, translate: t },
8055
+ { "export-cancel": () => onCancel() }
8081
8056
  );
8057
+ return /* @__PURE__ */ jsx("pptx-ui-export-progress", { ref });
8082
8058
  }
8083
8059
  function StatusBar(p) {
8084
8060
  const { t } = useTranslation();
@@ -8296,7 +8272,7 @@ function slideThumbnailPropsEqual(prev, next) {
8296
8272
  }
8297
8273
  return true;
8298
8274
  }
8299
- var SlideThumbnail = /* @__PURE__ */ React107.memo(
8275
+ var SlideThumbnail = /* @__PURE__ */ React108.memo(
8300
8276
  SlideThumbnailImpl,
8301
8277
  slideThumbnailPropsEqual
8302
8278
  );
@@ -8996,7 +8972,7 @@ function LazyThumbnailInner({
8996
8972
  }
8997
8973
  ) });
8998
8974
  }
8999
- var LazyThumbnail = /* @__PURE__ */ React107.memo(LazyThumbnailInner);
8975
+ var LazyThumbnail = /* @__PURE__ */ React108.memo(LazyThumbnailInner);
9000
8976
  function declaredSectionFacts(groups, sectionId) {
9001
8977
  const declared = groups.filter((group) => group.id !== DEFAULT_SECTION_GROUP_ID && group.id !== UNGROUPED_SECTION_ID).map((group) => group.id);
9002
8978
  return {
@@ -9164,7 +9140,7 @@ function SlideItemInner({
9164
9140
  }
9165
9141
  );
9166
9142
  }
9167
- var SlideItem = /* @__PURE__ */ React107.memo(SlideItemInner);
9143
+ var SlideItem = /* @__PURE__ */ React108.memo(SlideItemInner);
9168
9144
  function useSlidePaneCallbacks(onMoveSlide, onRenameSection, onToggleSectionCollapse) {
9169
9145
  const [collapsedSections, setCollapsedSections] = useState({});
9170
9146
  const [renamingSectionId, setRenamingSectionId] = useState(null);
@@ -10577,7 +10553,7 @@ function arePropsEqual(prev, next) {
10577
10553
  }
10578
10554
  return true;
10579
10555
  }
10580
- var SlideCard = /* @__PURE__ */ React107.memo(SlideCardImpl, arePropsEqual);
10556
+ var SlideCard = /* @__PURE__ */ React108.memo(SlideCardImpl, arePropsEqual);
10581
10557
  var ICON_CLASS = "h-3.5 w-3.5 text-muted-foreground";
10582
10558
  function SorterContextMenu({
10583
10559
  x,
@@ -11002,7 +10978,7 @@ function SlideSorterOverlay({
11002
10978
  count: state.selectedSlideIds.length
11003
10979
  }) })
11004
10980
  ] }),
11005
- React107.createElement("pptx-ui-slide-clipboard", {
10981
+ React108.createElement("pptx-ui-slide-clipboard", {
11006
10982
  ref: (node) => {
11007
10983
  if (!node) {
11008
10984
  return;
@@ -11918,8 +11894,8 @@ function SlideNotesPanel({
11918
11894
  onHeightChange
11919
11895
  }) {
11920
11896
  const { t } = useTranslation();
11921
- const rootRef = React107.useRef(null);
11922
- React107.useEffect(() => {
11897
+ const rootRef = React108.useRef(null);
11898
+ React108.useEffect(() => {
11923
11899
  const el = rootRef.current;
11924
11900
  if (!el || !onHeightChange) {
11925
11901
  return void 0;
@@ -13762,9 +13738,9 @@ function PresentationSubtitleBar({
13762
13738
  function renderNotesSegments(segments) {
13763
13739
  return notesSegmentsToSpans(segments).map((span) => {
13764
13740
  if (span.kind === "break") {
13765
- return React107.createElement("br", { key: span.key });
13741
+ return React108.createElement("br", { key: span.key });
13766
13742
  }
13767
- return React107.createElement(
13743
+ return React108.createElement(
13768
13744
  "span",
13769
13745
  { key: span.key, style: span.style },
13770
13746
  span.text
@@ -13940,7 +13916,7 @@ function scaledSlidePreviewPropsEqual(prev, next) {
13940
13916
  }
13941
13917
  return true;
13942
13918
  }
13943
- var ScaledSlidePreview = /* @__PURE__ */ React107.memo(
13919
+ var ScaledSlidePreview = /* @__PURE__ */ React108.memo(
13944
13920
  ScaledSlidePreviewImpl,
13945
13921
  scaledSlidePreviewPropsEqual
13946
13922
  );
@@ -14915,6 +14891,24 @@ var AFTER_ANIMATION_OPTIONS = [
14915
14891
  { value: "hideAfterAnimation", labelKey: "pptx.animation.afterAnimation.hideAfterAnimation" },
14916
14892
  { value: "hideOnNextClick", labelKey: "pptx.animation.afterAnimation.hideOnNextClick" }
14917
14893
  ];
14894
+ var pushers = /* @__PURE__ */ new WeakMap();
14895
+ function pushCommittedColor(event) {
14896
+ const input = event.currentTarget;
14897
+ pushers.get(input)?.current(input.value);
14898
+ }
14899
+ function useRecentColorCommit() {
14900
+ const { pushColor } = useRecentColors();
14901
+ const pushRef = useRef(pushColor);
14902
+ useEffect(() => {
14903
+ pushRef.current = pushColor;
14904
+ }, [pushColor]);
14905
+ return useCallback((input) => {
14906
+ if (input) {
14907
+ pushers.set(input, pushRef);
14908
+ input.addEventListener("change", pushCommittedColor);
14909
+ }
14910
+ }, []);
14911
+ }
14918
14912
  function AfterAnimationRow({
14919
14913
  action,
14920
14914
  color,
@@ -14924,7 +14918,7 @@ function AfterAnimationRow({
14924
14918
  onColorChange
14925
14919
  }) {
14926
14920
  const { t } = useTranslation();
14927
- const { pushColor } = useRecentColors();
14921
+ const commitRecentColor = useRecentColorCommit();
14928
14922
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
14929
14923
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
14930
14924
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-[11px]", children: t("pptx.animation.afterAnimation") }),
@@ -14948,10 +14942,8 @@ function AfterAnimationRow({
14948
14942
  type: "color",
14949
14943
  "aria-label": t("pptx.animation.afterAnimation.color"),
14950
14944
  value: color ?? "#808080",
14951
- onChange: (event) => {
14952
- onColorChange(event.target.value);
14953
- pushColor(event.target.value);
14954
- },
14945
+ ref: commitRecentColor,
14946
+ onChange: (event) => onColorChange(event.target.value),
14955
14947
  disabled: !canEdit,
14956
14948
  className: "h-6 w-10 rounded border border-border bg-transparent p-0"
14957
14949
  }
@@ -15170,7 +15162,7 @@ function EffectSoundRow({
15170
15162
  onPickStock
15171
15163
  }) {
15172
15164
  const { t } = useTranslation();
15173
- const fileInputRef = React107.useRef(null);
15165
+ const fileInputRef = React108.useRef(null);
15174
15166
  const selectedValue = soundState.catalogueId ?? (soundState.hasSound ? CURRENT_VALUE : NONE_VALUE);
15175
15167
  const handleSelectChange = (event) => {
15176
15168
  const value = event.target.value;
@@ -16040,12 +16032,6 @@ var HEADING2 = "pptx-editor-heading text-[11px] uppercase tracking-wide text-mut
16040
16032
  var CARD2 = "pptx-editor-card rounded border border-border bg-card p-2 space-y-2";
16041
16033
  var INPUT2 = "flex-1 bg-muted border border-border rounded px-1.5 py-0.5 w-full max-md:min-h-[44px]!";
16042
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]!";
16043
- var POS_FIELDS = [
16044
- ["X", "x"],
16045
- ["Y", "y"],
16046
- ["W", "width"],
16047
- ["H", "height"]
16048
- ];
16049
16035
  var URL_LABEL_KEY = {
16050
16036
  url: "pptx.action.gotoUrl",
16051
16037
  openFile: "pptx.hyperlink.actionOpenFile",
@@ -16404,7 +16390,7 @@ function ChartAxisStyleOptions({
16404
16390
  onSetGridlineStyle
16405
16391
  }) {
16406
16392
  const { t } = useTranslation();
16407
- const { pushColor } = useRecentColors();
16393
+ const commitRecentColor = useRecentColorCommit();
16408
16394
  const rows = SCALE_AXES.map((row) => ({
16409
16395
  ...row,
16410
16396
  axis: axes?.find((a) => a.axisType === row.type)
@@ -16504,10 +16490,8 @@ function ChartAxisStyleOptions({
16504
16490
  disabled: !canEdit,
16505
16491
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
16506
16492
  value: axis.fontColor ?? "#000000",
16507
- onChange: (e) => {
16508
- onSetTitleStyle(type, { fontColor: e.target.value });
16509
- pushColor(e.target.value);
16510
- }
16493
+ ref: commitRecentColor,
16494
+ onChange: (e) => onSetTitleStyle(type, { fontColor: e.target.value })
16511
16495
  }
16512
16496
  )
16513
16497
  ] })
@@ -16530,10 +16514,8 @@ function ChartAxisStyleOptions({
16530
16514
  title: t("pptx.chart.gridlineColor"),
16531
16515
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
16532
16516
  value: spPr?.strokeColor ?? "#d9d9d9",
16533
- onChange: (e) => {
16534
- onSetGridlineStyle(type, which, { color: e.target.value });
16535
- pushColor(e.target.value);
16536
- }
16517
+ ref: commitRecentColor,
16518
+ onChange: (e) => onSetGridlineStyle(type, which, { color: e.target.value })
16537
16519
  }
16538
16520
  ),
16539
16521
  /* @__PURE__ */ jsx(
@@ -16603,149 +16585,6 @@ function ChartComboTypeOptions({
16603
16585
  ] }, `${s.name}-${i}`)) })
16604
16586
  ] });
16605
16587
  }
16606
- function ChartDataGrid({
16607
- series,
16608
- categories,
16609
- canEdit,
16610
- highlightCell,
16611
- onUpdateSeries,
16612
- onUpdateCategoryLabel,
16613
- onUpdateValue,
16614
- onAddCategory,
16615
- onRemoveCategory,
16616
- onAddSeries,
16617
- onRemoveSeries
16618
- }) {
16619
- const { t } = useTranslation();
16620
- const highlightRef = useRef(null);
16621
- const { viewportWidth } = useIsMobile();
16622
- const gridPlan = getDenseGridLayoutPlan(viewportWidth);
16623
- const touchTargetPx = getDensePanelTouchTargetPx(viewportWidth);
16624
- const rowHeaderClass = gridPlan.stickyFirstColumn ? "sticky left-0 z-10 bg-card" : "";
16625
- const iconBtnStyle = { minWidth: touchTargetPx, minHeight: touchTargetPx };
16626
- useEffect(() => {
16627
- highlightRef.current?.scrollIntoView({ block: "nearest", inline: "nearest" });
16628
- }, [highlightCell?.seriesIndex, highlightCell?.pointIndex]);
16629
- const highlightClass = " ring-1 ring-primary";
16630
- const isSeriesHighlight = (si) => highlightCell?.seriesIndex === si && highlightCell.pointIndex === void 0;
16631
- const isValueHighlight = (si, ci) => highlightCell?.seriesIndex === si && highlightCell.pointIndex === ci;
16632
- return /* @__PURE__ */ jsxs("div", { className: CARD, children: [
16633
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
16634
- /* @__PURE__ */ jsx("div", { className: HEADING, children: t("pptx.chart.data") }),
16635
- canEdit && /* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
16636
- /* @__PURE__ */ jsxs(
16637
- "button",
16638
- {
16639
- type: "button",
16640
- className: `${BTN} inline-flex items-center justify-center`,
16641
- style: iconBtnStyle,
16642
- title: t("pptx.chart.addCategory"),
16643
- onClick: onAddCategory,
16644
- children: [
16645
- /* @__PURE__ */ jsx(LuPlus, { className: "inline w-3 h-3 mr-0.5" }),
16646
- t("pptx.chart.cat")
16647
- ]
16648
- }
16649
- ),
16650
- /* @__PURE__ */ jsxs(
16651
- "button",
16652
- {
16653
- type: "button",
16654
- className: `${BTN} inline-flex items-center justify-center`,
16655
- style: iconBtnStyle,
16656
- title: t("pptx.chart.addSeries"),
16657
- onClick: onAddSeries,
16658
- children: [
16659
- /* @__PURE__ */ jsx(LuPlus, { className: "inline w-3 h-3 mr-0.5" }),
16660
- t("pptx.chart.seriesShort")
16661
- ]
16662
- }
16663
- )
16664
- ] })
16665
- ] }),
16666
- /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-[11px] border-collapse", children: [
16667
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
16668
- /* @__PURE__ */ jsx(
16669
- "th",
16670
- {
16671
- "aria-label": t("pptx.chart.categories"),
16672
- className: `text-muted-foreground p-0.5 text-left ${rowHeaderClass}`,
16673
- style: { minWidth: gridPlan.minCellWidthPx }
16674
- }
16675
- ),
16676
- series.map((s, si) => /* @__PURE__ */ jsx(
16677
- "th",
16678
- {
16679
- className: "p-0.5 font-normal",
16680
- style: { minWidth: gridPlan.minCellWidthPx },
16681
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
16682
- /* @__PURE__ */ jsx(
16683
- "input",
16684
- {
16685
- type: "text",
16686
- disabled: !canEdit,
16687
- ref: isSeriesHighlight(si) ? highlightRef : null,
16688
- className: `${CELL_INPUT}${isSeriesHighlight(si) ? highlightClass : ""}`,
16689
- value: s.name,
16690
- onChange: (e) => onUpdateSeries(si, { name: e.target.value })
16691
- }
16692
- ),
16693
- canEdit && series.length > 1 && /* @__PURE__ */ jsx(
16694
- "button",
16695
- {
16696
- type: "button",
16697
- className: "text-muted-foreground hover:text-red-400 shrink-0 inline-flex items-center justify-center",
16698
- style: iconBtnStyle,
16699
- title: t("pptx.chart.removeSeries"),
16700
- onClick: () => onRemoveSeries(si),
16701
- children: /* @__PURE__ */ jsx(LuTrash2, { className: "w-3 h-3" })
16702
- }
16703
- )
16704
- ] })
16705
- },
16706
- si
16707
- ))
16708
- ] }) }),
16709
- /* @__PURE__ */ jsx("tbody", { children: categories.map((cat, ci) => /* @__PURE__ */ jsxs("tr", { children: [
16710
- /* @__PURE__ */ jsx("td", { className: `p-0.5 ${rowHeaderClass}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
16711
- /* @__PURE__ */ jsx(
16712
- "input",
16713
- {
16714
- type: "text",
16715
- disabled: !canEdit,
16716
- className: CELL_INPUT,
16717
- value: cat,
16718
- onChange: (e) => onUpdateCategoryLabel(ci, e.target.value)
16719
- }
16720
- ),
16721
- canEdit && categories.length > 1 && /* @__PURE__ */ jsx(
16722
- "button",
16723
- {
16724
- type: "button",
16725
- className: "text-muted-foreground hover:text-red-400 shrink-0 inline-flex items-center justify-center",
16726
- style: iconBtnStyle,
16727
- title: t("pptx.chart.removeCategory"),
16728
- onClick: () => onRemoveCategory(ci),
16729
- children: /* @__PURE__ */ jsx(LuTrash2, { className: "w-3 h-3" })
16730
- }
16731
- )
16732
- ] }) }),
16733
- series.map((s, si) => /* @__PURE__ */ jsx("td", { className: "p-0.5", children: /* @__PURE__ */ jsx(
16734
- "input",
16735
- {
16736
- type: "number",
16737
- "aria-label": t("pptx.chart.seriesValueCell", { name: s.name, number: ci + 1 }),
16738
- disabled: !canEdit,
16739
- ref: isValueHighlight(si, ci) ? highlightRef : null,
16740
- className: `${CELL_INPUT}${isValueHighlight(si, ci) ? highlightClass : ""}`,
16741
- value: s.values[ci] ?? 0,
16742
- onChange: (e) => onUpdateValue(si, ci, e.target.value)
16743
- }
16744
- ) }, si))
16745
- ] }, ci)) })
16746
- ] }) })
16747
- ] });
16748
- }
16749
16588
  function ChartDataLabelOptions({
16750
16589
  style,
16751
16590
  canEdit,
@@ -16800,7 +16639,7 @@ function ChartDataPointMarkerOptions({
16800
16639
  onSetPointMarker
16801
16640
  }) {
16802
16641
  const { t } = useTranslation();
16803
- const { pushColor } = useRecentColors();
16642
+ const commitRecentColor = useRecentColorCommit();
16804
16643
  const [seriesIndex, setSeriesIndex] = useState(0);
16805
16644
  if (!MARKER_SUPPORTED_TYPES.has(chartType) || series.length === 0 || categories.length === 0) {
16806
16645
  return null;
@@ -16887,10 +16726,8 @@ function ChartDataPointMarkerOptions({
16887
16726
  title: t("pptx.chart.markerFill"),
16888
16727
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
16889
16728
  value: point2.marker.spPr?.fillColor ?? "#4472c4",
16890
- onChange: (e) => {
16891
- onSetPointMarker(seriesIndex, idx, { fillColor: e.target.value });
16892
- pushColor(e.target.value);
16893
- }
16729
+ ref: commitRecentColor,
16730
+ onChange: (e) => onSetPointMarker(seriesIndex, idx, { fillColor: e.target.value })
16894
16731
  }
16895
16732
  )
16896
16733
  ] })
@@ -16908,7 +16745,7 @@ function ChartDataPointOptions({
16908
16745
  onSetPointLabel
16909
16746
  }) {
16910
16747
  const { t } = useTranslation();
16911
- const { pushColor } = useRecentColors();
16748
+ const commitRecentColor = useRecentColorCommit();
16912
16749
  const [seriesIndex, setSeriesIndex] = useState(0);
16913
16750
  if (series.length === 0 || categories.length === 0) {
16914
16751
  return null;
@@ -16959,10 +16796,8 @@ function ChartDataPointOptions({
16959
16796
  title: t("pptx.chart.pointFill"),
16960
16797
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
16961
16798
  value: point2?.spPr?.fillColor ?? activeSeries.color ?? "#4472c4",
16962
- onChange: (e) => {
16963
- onSetPointFill(seriesIndex, idx, e.target.value);
16964
- pushColor(e.target.value);
16965
- }
16799
+ ref: commitRecentColor,
16800
+ onChange: (e) => onSetPointFill(seriesIndex, idx, e.target.value)
16966
16801
  }
16967
16802
  ),
16968
16803
  point2?.spPr?.fillColor && /* @__PURE__ */ jsx(
@@ -17004,6 +16839,37 @@ function ChartDataPointOptions({
17004
16839
  }) })
17005
16840
  ] });
17006
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
+ }
17007
16873
  function ChartDisplayOptions({
17008
16874
  style,
17009
16875
  canEdit,
@@ -17249,7 +17115,7 @@ function ChartMarkerOptions({
17249
17115
  onSetMarker
17250
17116
  }) {
17251
17117
  const { t } = useTranslation();
17252
- const { pushColor } = useRecentColors();
17118
+ const commitRecentColor = useRecentColorCommit();
17253
17119
  if (!MARKER_SUPPORTED_TYPES.has(chartType) || series.length === 0) {
17254
17120
  return null;
17255
17121
  }
@@ -17308,10 +17174,8 @@ function ChartMarkerOptions({
17308
17174
  disabled: !canEdit,
17309
17175
  className: "h-6 w-8 cursor-pointer rounded border border-border bg-transparent",
17310
17176
  value: marker.spPr?.fillColor ?? "#4472c4",
17311
- onChange: (e) => {
17312
- onSetMarker(i, { fillColor: e.target.value });
17313
- pushColor(e.target.value);
17314
- }
17177
+ ref: commitRecentColor,
17178
+ onChange: (e) => onSetMarker(i, { fillColor: e.target.value })
17315
17179
  }
17316
17180
  )
17317
17181
  ] })
@@ -17330,19 +17194,15 @@ function DebouncedColorInput({
17330
17194
  const [local, setLocal] = useState(value);
17331
17195
  const commitRef = useRef(onCommit);
17332
17196
  commitRef.current = onCommit;
17333
- const { pushColor } = useRecentColors();
17197
+ const commitRecentColor = useRecentColorCommit();
17334
17198
  useEffect(() => {
17335
17199
  setLocal(value);
17336
17200
  }, [value]);
17337
- const handleChange = useCallback(
17338
- (e) => {
17339
- const next = e.target.value;
17340
- setLocal(next);
17341
- commitRef.current(next);
17342
- pushColor(next);
17343
- },
17344
- [pushColor]
17345
- );
17201
+ const handleChange = useCallback((e) => {
17202
+ const next = e.target.value;
17203
+ setLocal(next);
17204
+ commitRef.current(next);
17205
+ }, []);
17346
17206
  return /* @__PURE__ */ jsx(
17347
17207
  "input",
17348
17208
  {
@@ -17351,6 +17211,7 @@ function DebouncedColorInput({
17351
17211
  disabled,
17352
17212
  value: local,
17353
17213
  className,
17214
+ ref: commitRecentColor,
17354
17215
  onChange: handleChange
17355
17216
  }
17356
17217
  );
@@ -18099,52 +17960,6 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
18099
17960
  },
18100
17961
  [updateSeries]
18101
17962
  );
18102
- const updateCategoryLabel = useCallback(
18103
- (catIndex, value) => {
18104
- const next = chartData && setChartCategoryLabel(chartData, catIndex, value);
18105
- if (next) {
18106
- replaceChartData(next);
18107
- }
18108
- },
18109
- [chartData, replaceChartData]
18110
- );
18111
- const updateValue = useCallback(
18112
- (seriesIndex, catIndex, raw) => {
18113
- const next = chartData && setChartCellValue(chartData, seriesIndex, catIndex, raw);
18114
- if (next) {
18115
- replaceChartData(next);
18116
- }
18117
- },
18118
- [chartData, replaceChartData]
18119
- );
18120
- const addCategory = useCallback(() => {
18121
- if (chartData) {
18122
- replaceChartData(addChartCategory(chartData));
18123
- }
18124
- }, [chartData, replaceChartData]);
18125
- const removeCategory = useCallback(
18126
- (catIndex) => {
18127
- const next = chartData && removeChartCategory(chartData, catIndex, followDataPoint);
18128
- if (next) {
18129
- replaceChartData(next);
18130
- }
18131
- },
18132
- [chartData, followDataPoint, replaceChartData]
18133
- );
18134
- const addSeries = useCallback(() => {
18135
- if (chartData) {
18136
- replaceChartData(addChartSeries(chartData));
18137
- }
18138
- }, [chartData, replaceChartData]);
18139
- const removeSeries = useCallback(
18140
- (seriesIndex) => {
18141
- const next = chartData && removeChartSeries(chartData, seriesIndex);
18142
- if (next) {
18143
- replaceChartData(next);
18144
- }
18145
- },
18146
- [chartData, replaceChartData]
18147
- );
18148
17963
  const hideSeries = useCallback(
18149
17964
  (seriesIndex) => {
18150
17965
  const next = chartData && hideChartSeries(chartData, seriesIndex);
@@ -18361,19 +18176,13 @@ function ChartDataPanel({ selectedElement, canEdit, onUpdateElement }) {
18361
18176
  }
18362
18177
  ),
18363
18178
  /* @__PURE__ */ jsx(
18364
- ChartDataGrid,
18179
+ ChartDataSheet,
18365
18180
  {
18366
- categories,
18367
- series,
18181
+ chartData,
18368
18182
  canEdit,
18183
+ followDataPoint,
18369
18184
  highlightCell: canvasPart ? { seriesIndex: canvasPart.seriesIndex, pointIndex: canvasPart.pointIndex } : null,
18370
- onUpdateSeries: updateSeries,
18371
- onUpdateCategoryLabel: updateCategoryLabel,
18372
- onUpdateValue: updateValue,
18373
- onAddCategory: addCategory,
18374
- onRemoveCategory: removeCategory,
18375
- onAddSeries: addSeries,
18376
- onRemoveSeries: removeSeries
18185
+ onChange: replaceChartData
18377
18186
  }
18378
18187
  )
18379
18188
  ] });
@@ -18741,7 +18550,7 @@ function ConnectorArrowsSection({
18741
18550
  ["Start", "End"].map((end) => {
18742
18551
  const widthKey = end === "Start" ? "connectorStartArrowWidth" : "connectorEndArrowWidth";
18743
18552
  const lengthKey = end === "Start" ? "connectorStartArrowLength" : "connectorEndArrowLength";
18744
- return /* @__PURE__ */ jsxs(React107.Fragment, { children: [
18553
+ return /* @__PURE__ */ jsxs(React108.Fragment, { children: [
18745
18554
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
18746
18555
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t(END_LABEL_KEYS[end].width) }),
18747
18556
  /* @__PURE__ */ jsx(
@@ -18894,36 +18703,21 @@ function TransformPanel({
18894
18703
  }) {
18895
18704
  return /* @__PURE__ */ jsxs("div", { className: CARD2, children: [
18896
18705
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: "Transform" }),
18897
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-1.5 text-[11px]", children: [
18898
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
18899
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Rotation (\xB0)" }),
18900
- /* @__PURE__ */ jsx(
18901
- "input",
18902
- {
18903
- type: "number",
18904
- disabled: !canEdit,
18905
- className: INPUT2,
18906
- value: Math.round(selectedElement.rotation || 0),
18907
- onChange: (e) => onUpdateElement({ rotation: Number(e.target.value) })
18908
- }
18909
- )
18910
- ] }),
18911
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
18912
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Opacity" }),
18913
- /* @__PURE__ */ jsx(
18914
- "input",
18915
- {
18916
- type: "range",
18917
- disabled: !canEdit,
18918
- min: 0,
18919
- max: 100,
18920
- value: Math.round((selectedElement.opacity ?? 1) * 100),
18921
- className: "accent-primary",
18922
- onChange: (e) => onUpdateElement({ opacity: Number(e.target.value) / 100 })
18923
- }
18924
- )
18925
- ] })
18926
- ] })
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
+ ] }) })
18927
18721
  ] });
18928
18722
  }
18929
18723
  function LayerOrderButtons({
@@ -19561,6 +19355,130 @@ function ImagePropertiesPanel({
19561
19355
  ] })
19562
19356
  ] });
19563
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
+ }
19564
19482
  var HEADING3 = "text-[11px] uppercase tracking-wide text-muted-foreground";
19565
19483
  var CARD3 = "rounded border border-border bg-card p-2 space-y-2";
19566
19484
  var INPUT3 = "flex-1 bg-muted border border-border rounded px-1.5 py-0.5 w-full";
@@ -20425,9 +20343,6 @@ function AccessibilityTextSection({
20425
20343
  ] })
20426
20344
  ] });
20427
20345
  }
20428
- var COMPOUND_LINE_OPTIONS = COMPOUND_LINE_OPTIONS$1;
20429
- var LINE_JOIN_OPTIONS = LINE_JOIN_OPTIONS$1;
20430
- var LINE_CAP_OPTIONS = LINE_CAP_OPTIONS$1;
20431
20346
  var PATTERN_PRESET_OPTIONS = PATTERN_PRESET_OPTIONS$1;
20432
20347
  var FILL_MODE_OPTIONS = [
20433
20348
  { value: "solid", label: "Solid", i18nKey: "pptx.fill.solid" },
@@ -20444,589 +20359,45 @@ var IMAGE_MODE_OPTIONS = [
20444
20359
  { value: "stretch", label: "Stretch", i18nKey: "pptx.image.stretch" },
20445
20360
  { value: "tile", label: "Tile", i18nKey: "pptx.image.tile" }
20446
20361
  ];
20447
- function getCompoundLinePreviewStyle(type) {
20448
- const baseColor = "#6b7280";
20449
- switch (type) {
20450
- case "sng":
20451
- return {
20452
- borderTop: `2px solid ${baseColor}`,
20453
- width: "100%"
20454
- };
20455
- case "dbl": {
20456
- const lineWidth = 2;
20457
- const gap = 2;
20458
- return {
20459
- position: "relative",
20460
- height: `${lineWidth * 2 + gap}px`,
20461
- width: "100%",
20462
- boxShadow: `inset 0 ${lineWidth + gap}px 0 ${-lineWidth}px ${baseColor}, inset 0 ${ -4}px 0 ${-lineWidth}px ${baseColor}`
20463
- };
20464
- }
20465
- case "thickThin": {
20466
- const thickWidth = 3;
20467
- const thinWidth = 1;
20468
- const gap = 1;
20469
- return {
20470
- position: "relative",
20471
- height: `${thickWidth + thinWidth + gap}px`,
20472
- width: "100%",
20473
- boxShadow: `inset 0 ${thickWidth / 2 + gap}px 0 ${-thickWidth}px ${baseColor}, inset 0 ${ -3.5}px 0 ${-thinWidth}px ${baseColor}`
20474
- };
20475
- }
20476
- case "thinThick": {
20477
- const thinWidth = 1;
20478
- const thickWidth = 3;
20479
- const gap = 1;
20480
- return {
20481
- position: "relative",
20482
- height: `${thinWidth + thickWidth + gap}px`,
20483
- width: "100%",
20484
- boxShadow: `inset 0 ${thickWidth / 2 + gap}px 0 ${-thinWidth}px ${baseColor}, inset 0 ${ -3.5}px 0 ${-thickWidth}px ${baseColor}`
20485
- };
20486
- }
20487
- case "tri": {
20488
- const lineWidth = 1;
20489
- const gap = 1;
20490
- const offset1 = lineWidth + gap;
20491
- return {
20492
- position: "relative",
20493
- height: `${lineWidth * 3 + gap * 2}px`,
20494
- width: "100%",
20495
- boxShadow: `inset 0 0 0 ${-lineWidth}px ${baseColor}, inset 0 ${offset1}px 0 ${-lineWidth}px ${baseColor}, inset 0 ${ -4}px 0 ${-lineWidth}px ${baseColor}`
20496
- };
20497
- }
20498
- default:
20499
- return {};
20500
- }
20501
- }
20502
-
20503
- // src/viewer/components/inspector/bevel-type-options.ts
20504
- var BEVEL_TYPE_OPTIONS = [
20505
- { value: "circle", label: "Circle", i18nKey: "pptx.bevelTypes.circle" },
20506
- { value: "relaxedInset", label: "Relaxed Inset", i18nKey: "pptx.bevelTypes.relaxedInset" },
20507
- { value: "cross", label: "Cross", i18nKey: "pptx.bevelTypes.cross" },
20508
- { value: "slope", label: "Slope", i18nKey: "pptx.bevelTypes.slope" },
20509
- { value: "convex", label: "Convex", i18nKey: "pptx.bevelTypes.convex" },
20510
- { value: "coolSlant", label: "Cool Slant", i18nKey: "pptx.bevelTypes.coolSlant" },
20511
- { value: "angle", label: "Angle", i18nKey: "pptx.bevelTypes.angle" },
20512
- { value: "softRound", label: "Soft Round", i18nKey: "pptx.bevelTypes.softRound" },
20513
- { value: "riblet", label: "Riblet", i18nKey: "pptx.bevelTypes.riblet" },
20514
- { value: "hardEdge", label: "Hard Edge", i18nKey: "pptx.bevelTypes.hardEdge" },
20515
- { value: "artDeco", label: "Art Deco", i18nKey: "pptx.bevelTypes.artDeco" },
20516
- { value: "divot", label: "Divot", i18nKey: "pptx.bevelTypes.divot" }
20517
- ];
20518
-
20519
- // src/viewer/components/inspector/fill-stroke-effect-configs.ts
20520
- var clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
20521
- var SHADOW_EFFECT_CONFIGS = [
20522
- /* Shadow */
20523
- {
20524
- label: "Shadow",
20525
- isOn: (s) => Boolean(s?.shadowColor) && s?.shadowColor !== "transparent",
20526
- onEnable: (s) => {
20527
- let angle = s?.shadowAngle ?? 315;
20528
- let distance = s?.shadowDistance ?? 5.66;
20529
- const offsetX = s?.shadowOffsetX ?? 4;
20530
- const offsetY = s?.shadowOffsetY ?? 4;
20531
- if (s?.shadowAngle === null && s?.shadowDistance === null && (offsetX !== 0 || offsetY !== 0)) {
20532
- distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
20533
- angle = (Math.atan2(offsetY, offsetX) * 180 / Math.PI + 360) % 360;
20534
- }
20535
- return {
20536
- shadowColor: normalizeHexColor(s?.shadowColor, "#000000"),
20537
- shadowOpacity: s?.shadowOpacity ?? 0.35,
20538
- shadowBlur: s?.shadowBlur ?? 6,
20539
- shadowAngle: angle,
20540
- shadowDistance: distance,
20541
- shadowOffsetX: offsetX,
20542
- shadowOffsetY: offsetY,
20543
- shadowRotateWithShape: s?.shadowRotateWithShape ?? true
20544
- };
20545
- },
20546
- onDisable: () => ({ shadowColor: "transparent" }),
20547
- fields: [
20548
- {
20549
- key: "sc",
20550
- label: "Shadow Color",
20551
- type: "color",
20552
- read: (s) => normalizeHexColor(s?.shadowColor, "#000000"),
20553
- write: (v) => ({ shadowColor: String(v) })
20554
- },
20555
- {
20556
- key: "so",
20557
- label: "Shadow Opacity",
20558
- type: "range",
20559
- min: 0,
20560
- max: 100,
20561
- isPercent: true,
20562
- read: (s) => Math.round((s?.shadowOpacity ?? 0.35) * 100),
20563
- write: (v) => ({ shadowOpacity: Number(v) / 100 })
20564
- },
20565
- {
20566
- key: "sb",
20567
- label: "Shadow Blur",
20568
- type: "number",
20569
- min: 0,
20570
- max: 96,
20571
- read: (s) => Math.round(s?.shadowBlur ?? 6),
20572
- write: (v) => ({ shadowBlur: clamp(Number(v), 0, 96) })
20573
- },
20574
- {
20575
- key: "sa",
20576
- label: "Shadow Angle",
20577
- type: "number",
20578
- min: 0,
20579
- max: 359,
20580
- read: (s) => {
20581
- if (typeof s?.shadowAngle === "number") {
20582
- return Math.round(s.shadowAngle) % 360;
20583
- }
20584
- const x = s?.shadowOffsetX ?? 4;
20585
- const y = s?.shadowOffsetY ?? 4;
20586
- return Math.round((Math.atan2(y, x) * 180 / Math.PI + 360) % 360);
20587
- },
20588
- write: (v) => {
20589
- const angle = Number(v) % 360;
20590
- return (s) => {
20591
- const dist = typeof s?.shadowDistance === "number" ? s.shadowDistance : 5.66;
20592
- const angleRad = angle * Math.PI / 180;
20593
- return {
20594
- shadowAngle: angle,
20595
- shadowDistance: dist,
20596
- shadowOffsetX: Math.cos(angleRad) * dist,
20597
- shadowOffsetY: Math.sin(angleRad) * dist
20598
- };
20599
- };
20600
- }
20601
- },
20602
- {
20603
- key: "sd",
20604
- label: "Shadow Distance",
20605
- type: "number",
20606
- min: 0,
20607
- max: 100,
20608
- read: (s) => {
20609
- if (typeof s?.shadowDistance === "number") {
20610
- return Math.round(s.shadowDistance * 10) / 10;
20611
- }
20612
- const x = s?.shadowOffsetX ?? 4;
20613
- const y = s?.shadowOffsetY ?? 4;
20614
- return Math.round(Math.sqrt(x * x + y * y) * 10) / 10;
20615
- },
20616
- write: (v) => {
20617
- return (s) => {
20618
- const distance = clamp(Number(v), 0, 100);
20619
- const angle = typeof s?.shadowAngle === "number" ? s.shadowAngle : 315;
20620
- const angleRad = angle * Math.PI / 180;
20621
- return {
20622
- shadowAngle: angle,
20623
- shadowDistance: distance,
20624
- shadowOffsetX: Math.cos(angleRad) * distance,
20625
- shadowOffsetY: Math.sin(angleRad) * distance
20626
- };
20627
- };
20628
- }
20629
- },
20630
- {
20631
- key: "sr",
20632
- label: "Rotate with Shape",
20633
- i18nKey: "pptx.effects.rotateWithShape",
20634
- type: "checkbox",
20635
- read: (s) => s?.shadowRotateWithShape ?? true,
20636
- write: (v) => ({ shadowRotateWithShape: Boolean(v) })
20637
- },
20638
- {
20639
- key: "sx",
20640
- label: "Shadow X",
20641
- type: "number",
20642
- min: -96,
20643
- max: 96,
20644
- read: (s) => Math.round(s?.shadowOffsetX ?? 4),
20645
- write: (v) => {
20646
- return (s) => {
20647
- const offsetX = clamp(Number(v), -96, 96);
20648
- const offsetY = s?.shadowOffsetY ?? 4;
20649
- const distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
20650
- const angle = (Math.atan2(offsetY, offsetX) * 180 / Math.PI + 360) % 360;
20651
- return {
20652
- shadowOffsetX: offsetX,
20653
- shadowAngle: angle,
20654
- shadowDistance: distance
20655
- };
20656
- };
20657
- }
20658
- },
20659
- {
20660
- key: "sy",
20661
- label: "Shadow Y",
20662
- type: "number",
20663
- min: -96,
20664
- max: 96,
20665
- span2: true,
20666
- read: (s) => Math.round(s?.shadowOffsetY ?? 4),
20667
- write: (v) => {
20668
- return (s) => {
20669
- const offsetY = clamp(Number(v), -96, 96);
20670
- const offsetX = s?.shadowOffsetX ?? 4;
20671
- const distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
20672
- const angle = (Math.atan2(offsetY, offsetX) * 180 / Math.PI + 360) % 360;
20673
- return {
20674
- shadowOffsetY: offsetY,
20675
- shadowAngle: angle,
20676
- shadowDistance: distance
20677
- };
20678
- };
20679
- }
20680
- }
20681
- ]
20682
- },
20683
- /* Inner Shadow */
20684
- {
20685
- label: "Inner Shadow",
20686
- isOn: (s) => Boolean(s?.innerShadowColor) && s?.innerShadowColor !== "transparent",
20687
- onEnable: (s) => ({
20688
- innerShadowColor: normalizeHexColor(s?.innerShadowColor, "#000000"),
20689
- innerShadowOpacity: s?.innerShadowOpacity ?? 0.5,
20690
- innerShadowBlur: s?.innerShadowBlur ?? 5,
20691
- innerShadowOffsetX: s?.innerShadowOffsetX ?? 0,
20692
- innerShadowOffsetY: s?.innerShadowOffsetY ?? 0
20693
- }),
20694
- onDisable: () => ({ innerShadowColor: "transparent" }),
20695
- fields: [
20696
- {
20697
- key: "isc",
20698
- label: "Color",
20699
- type: "color",
20700
- read: (s) => normalizeHexColor(s?.innerShadowColor, "#000000"),
20701
- write: (v) => ({ innerShadowColor: String(v) })
20702
- },
20703
- {
20704
- key: "iso",
20705
- label: "Opacity",
20706
- type: "range",
20707
- min: 0,
20708
- max: 100,
20709
- isPercent: true,
20710
- read: (s) => Math.round((s?.innerShadowOpacity ?? 0.5) * 100),
20711
- write: (v) => ({ innerShadowOpacity: Number(v) / 100 })
20712
- },
20713
- {
20714
- key: "isb",
20715
- label: "Blur",
20716
- type: "number",
20717
- min: 0,
20718
- max: 96,
20719
- read: (s) => Math.round(s?.innerShadowBlur ?? 5),
20720
- write: (v) => ({ innerShadowBlur: clamp(Number(v), 0, 96) })
20721
- },
20722
- {
20723
- key: "isx",
20724
- label: "Offset X",
20725
- type: "number",
20726
- min: -96,
20727
- max: 96,
20728
- read: (s) => Math.round(s?.innerShadowOffsetX ?? 0),
20729
- write: (v) => ({
20730
- innerShadowOffsetX: clamp(Number(v), -96, 96)
20731
- })
20732
- },
20733
- {
20734
- key: "isy",
20735
- label: "Offset Y",
20736
- type: "number",
20737
- min: -96,
20738
- max: 96,
20739
- span2: true,
20740
- read: (s) => Math.round(s?.innerShadowOffsetY ?? 0),
20741
- write: (v) => ({
20742
- innerShadowOffsetY: clamp(Number(v), -96, 96)
20743
- })
20744
- }
20745
- ]
20746
- }
20747
- ];
20748
-
20749
- // src/viewer/components/inspector/fill-stroke-visual-configs.ts
20750
- var clamp2 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
20751
- var VISUAL_EFFECT_CONFIGS = [
20752
- /* Glow */
20753
- {
20754
- label: "Glow",
20755
- isOn: (s) => Boolean(s?.glowColor) && s?.glowColor !== "transparent",
20756
- onEnable: (s) => ({
20757
- glowColor: s?.glowColor && s.glowColor !== "transparent" ? s.glowColor : "#ffff00",
20758
- glowOpacity: s?.glowOpacity ?? 0.75,
20759
- glowRadius: s?.glowRadius ?? 6
20760
- }),
20761
- onDisable: () => ({ glowColor: "transparent", glowRadius: 0 }),
20762
- fields: [
20763
- {
20764
- key: "gc",
20765
- label: "Glow Color",
20766
- type: "color",
20767
- read: (s) => s?.glowColor && s.glowColor !== "transparent" ? s.glowColor : "#ffff00",
20768
- write: (v) => ({ glowColor: String(v) })
20769
- },
20770
- {
20771
- key: "go",
20772
- label: "Glow Opacity",
20773
- type: "range",
20774
- min: 0,
20775
- max: 100,
20776
- isPercent: true,
20777
- read: (s) => Math.round((s?.glowOpacity ?? 0.75) * 100),
20778
- write: (v) => ({ glowOpacity: Number(v) / 100 })
20779
- },
20780
- {
20781
- key: "gr",
20782
- label: "Glow Radius",
20783
- type: "number",
20784
- min: 0,
20785
- max: 96,
20786
- span2: true,
20787
- read: (s) => Math.round(s?.glowRadius ?? 6),
20788
- write: (v) => ({ glowRadius: clamp2(Number(v), 0, 96) })
20789
- }
20790
- ]
20791
- },
20792
- /* Soft Edge */
20793
- {
20794
- label: "Soft Edge",
20795
- i18nKey: "pptx.inspector.softEdge",
20796
- isOn: (s) => typeof s?.softEdgeRadius === "number" && s.softEdgeRadius > 0,
20797
- onEnable: () => ({ softEdgeRadius: 6 }),
20798
- onDisable: () => ({ softEdgeRadius: 0 }),
20799
- fields: [
20800
- {
20801
- key: "se",
20802
- label: "Soft Edge Radius",
20803
- i18nKey: "pptx.inspector.softEdgeRadius",
20804
- type: "number",
20805
- min: 0,
20806
- max: 96,
20807
- span2: true,
20808
- read: (s) => Math.round(s?.softEdgeRadius ?? 6),
20809
- write: (v) => ({ softEdgeRadius: clamp2(Number(v), 0, 96) })
20810
- }
20811
- ]
20812
- },
20813
- /* Reflection */
20814
- {
20815
- label: "Reflection",
20816
- isOn: (s) => (s?.reflectionBlurRadius ?? 0) > 0 || (s?.reflectionStartOpacity ?? 0) > 0,
20817
- onEnable: () => ({
20818
- reflectionBlurRadius: 3,
20819
- reflectionStartOpacity: 50,
20820
- reflectionEndOpacity: 0,
20821
- reflectionEndPosition: 50,
20822
- reflectionDirection: 90,
20823
- reflectionDistance: 0
20824
- }),
20825
- onDisable: () => ({
20826
- reflectionBlurRadius: 0,
20827
- reflectionStartOpacity: 0,
20828
- reflectionEndOpacity: 0,
20829
- reflectionEndPosition: 0,
20830
- reflectionDirection: 0,
20831
- reflectionDistance: 0
20832
- }),
20833
- fields: [
20834
- {
20835
- key: "rb",
20836
- label: "Blur",
20837
- type: "number",
20838
- min: 0,
20839
- max: 20,
20840
- step: 0.5,
20841
- read: (s) => s?.reflectionBlurRadius ?? 3,
20842
- write: (v) => ({ reflectionBlurRadius: clamp2(Number(v), 0, 20) })
20843
- },
20844
- {
20845
- key: "rs",
20846
- label: "Start Opacity %",
20847
- type: "number",
20848
- min: 0,
20849
- max: 100,
20850
- read: (s) => s?.reflectionStartOpacity ?? 50,
20851
- write: (v) => ({ reflectionStartOpacity: clamp2(Number(v), 0, 100) })
20852
- },
20853
- {
20854
- key: "re",
20855
- label: "End Opacity %",
20856
- type: "number",
20857
- min: 0,
20858
- max: 100,
20859
- read: (s) => s?.reflectionEndOpacity ?? 0,
20860
- write: (v) => ({ reflectionEndOpacity: clamp2(Number(v), 0, 100) })
20861
- },
20862
- {
20863
- key: "rd",
20864
- label: "Distance",
20865
- type: "number",
20866
- min: 0,
20867
- max: 50,
20868
- read: (s) => s?.reflectionDistance ?? 0,
20869
- write: (v) => ({ reflectionDistance: clamp2(Number(v), 0, 50) })
20870
- },
20871
- {
20872
- key: "rdir",
20873
- label: "Direction",
20874
- type: "number",
20875
- min: 0,
20876
- max: 360,
20877
- read: (s) => s?.reflectionDirection ?? 90,
20878
- write: (v) => ({ reflectionDirection: clamp2(Number(v), 0, 360) })
20879
- },
20880
- {
20881
- key: "rrot",
20882
- label: "Rotation",
20883
- type: "number",
20884
- min: 0,
20885
- max: 360,
20886
- span2: true,
20887
- read: (s) => s?.reflectionRotation ?? 0,
20888
- write: (v) => ({ reflectionRotation: clamp2(Number(v), 0, 360) })
20889
- }
20890
- ]
20891
- },
20892
- /* Blur */
20893
- {
20894
- label: "Blur",
20895
- isOn: (s) => (s?.blurRadius ?? 0) > 0,
20896
- onEnable: () => ({ blurRadius: 4 }),
20897
- onDisable: () => ({ blurRadius: 0 }),
20898
- fields: [
20899
- {
20900
- key: "bl",
20901
- label: "Blur Radius",
20902
- type: "number",
20903
- min: 0,
20904
- max: 50,
20905
- span2: true,
20906
- read: (s) => Math.round(s?.blurRadius ?? 4),
20907
- write: (v) => ({ blurRadius: clamp2(Number(v), 0, 50) })
20908
- }
20909
- ]
20910
- },
20911
- /* Bevel / 3D */
20912
- {
20913
- label: "Bevel / 3D",
20914
- isOn: (s) => Boolean(s?.shape3d?.bevelTopType) && s?.shape3d?.bevelTopType !== "none",
20915
- onEnable: (s) => ({
20916
- shape3d: {
20917
- ...s?.shape3d,
20918
- bevelTopType: s?.shape3d?.bevelTopType || "circle",
20919
- bevelTopWidth: s?.shape3d?.bevelTopWidth ?? 76200,
20920
- bevelTopHeight: s?.shape3d?.bevelTopHeight ?? 76200
20921
- }
20922
- }),
20923
- onDisable: (s) => ({
20924
- shape3d: {
20925
- ...s?.shape3d,
20926
- bevelTopType: void 0,
20927
- bevelTopWidth: void 0,
20928
- bevelTopHeight: void 0
20929
- }
20930
- }),
20931
- fields: [
20932
- {
20933
- key: "btype",
20934
- label: "Bevel Type",
20935
- type: "select",
20936
- span2: true,
20937
- options: BEVEL_TYPE_OPTIONS,
20938
- read: (s) => s?.shape3d?.bevelTopType ?? "circle",
20939
- write: (v, s) => ({
20940
- shape3d: { ...s?.shape3d, bevelTopType: String(v) }
20941
- })
20942
- },
20943
- {
20944
- key: "bw",
20945
- label: "Bevel Width (EMU)",
20946
- type: "number",
20947
- min: 0,
20948
- max: 5e5,
20949
- step: 12700,
20950
- read: (s) => s?.shape3d?.bevelTopWidth ?? 76200,
20951
- write: (v, s) => ({
20952
- shape3d: {
20953
- ...s?.shape3d,
20954
- bevelTopWidth: clamp2(Number(v), 0, 5e5)
20955
- }
20956
- })
20957
- },
20958
- {
20959
- key: "bh",
20960
- label: "Bevel Height (EMU)",
20961
- type: "number",
20962
- min: 0,
20963
- max: 5e5,
20964
- step: 12700,
20965
- span2: true,
20966
- read: (s) => s?.shape3d?.bevelTopHeight ?? 76200,
20967
- write: (v, s) => ({
20968
- shape3d: {
20969
- ...s?.shape3d,
20970
- bevelTopHeight: clamp2(Number(v), 0, 5e5)
20971
- }
20972
- })
20973
- }
20974
- ]
20975
- }
20976
- ];
20977
-
20978
- // src/viewer/components/inspector/FillStrokeHelpers.tsx
20979
- var EFFECT_CONFIGS = [...SHADOW_EFFECT_CONFIGS, ...VISUAL_EFFECT_CONFIGS];
20980
- var SEL = "bg-muted border border-border rounded px-2 py-1 max-md:min-h-[44px]!";
20981
- var NUM = SEL;
20982
- var RNG = "accent-primary";
20983
- var SWATCH = "h-4 w-4 rounded border border-border";
20984
- var DIS = "disabled:opacity-40 disabled:cursor-not-allowed";
20985
- var LBL = "text-muted-foreground";
20986
- var COL2 = "col-span-2";
20987
- var isLineish = (el, st) => el.type === "connector" || st === "line";
20988
- var safeNum = (raw, fallback) => {
20989
- const n = Number(raw);
20990
- return Number.isFinite(n) ? n : fallback;
20991
- };
20992
20362
  function RecentColorsRow({
20993
- prefix,
20994
20363
  disabled,
20995
20364
  onCommit
20996
20365
  }) {
20997
20366
  const { t } = useTranslation();
20998
20367
  const { recentColors, pushColor } = useRecentColors();
20999
- 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) {
21000
20398
  return null;
21001
20399
  }
21002
- return /* @__PURE__ */ jsxs(
21003
- "div",
21004
- {
21005
- "data-testid": "pptx-color-recent",
21006
- "aria-label": t("pptx.colorPicker.recentColors"),
21007
- className: "mt-1 flex flex-wrap items-center gap-1",
21008
- children: [
21009
- /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground", children: t("pptx.colorPicker.recentColors") }),
21010
- recentColors.map((c) => /* @__PURE__ */ jsx(
21011
- "button",
21012
- {
21013
- type: "button",
21014
- "data-pptx-compact": true,
21015
- className: "h-4 w-4 rounded border border-primary",
21016
- style: { backgroundColor: c },
21017
- title: c,
21018
- "aria-label": `Recent ${c}`,
21019
- disabled,
21020
- onClick: () => {
21021
- onCommit(c);
21022
- pushColor(c);
21023
- }
21024
- },
21025
- `${prefix}-recent-${c}`
21026
- ))
21027
- ]
21028
- }
21029
- );
20400
+ return /* @__PURE__ */ jsx("pptx-ui-color-grid", { ref, "data-testid": "pptx-color-recent", className: "mt-1" });
21030
20401
  }
21031
20402
  function ThemeColorSwatchGrid({
21032
20403
  disabled,
@@ -21074,107 +20445,6 @@ function ThemeColorSwatchGrid({
21074
20445
  }
21075
20446
  return /* @__PURE__ */ jsx("pptx-ui-color-grid", { ref, className: "mt-1" });
21076
20447
  }
21077
- function EffectField({
21078
- field,
21079
- style,
21080
- onUpdate
21081
- }) {
21082
- const { t } = useTranslation();
21083
- const { pushColor } = useRecentColors();
21084
- const fieldLabel = field.i18nKey ? t(field.i18nKey) : field.label;
21085
- const val = field.read(style);
21086
- const cls = `flex flex-col gap-1 ${field.span2 ? COL2 : ""}`;
21087
- if (field.type === "select" && field.options) {
21088
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21089
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21090
- /* @__PURE__ */ jsx(
21091
- WebSelect,
21092
- {
21093
- "aria-label": fieldLabel,
21094
- value: String(val),
21095
- onChange: (e) => {
21096
- const result = field.write(e.target.value, style);
21097
- onUpdate(typeof result === "function" ? result(style) : result);
21098
- },
21099
- className: SEL,
21100
- children: field.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
21101
- }
21102
- )
21103
- ] });
21104
- }
21105
- if (field.type === "color") {
21106
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21107
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21108
- /* @__PURE__ */ jsx(
21109
- "input",
21110
- {
21111
- type: "color",
21112
- value: String(val),
21113
- onChange: (e) => {
21114
- const result = field.write(e.target.value, style);
21115
- onUpdate(typeof result === "function" ? result(style) : result);
21116
- pushColor(e.target.value);
21117
- },
21118
- className: `h-8 ${SEL} px-1`
21119
- }
21120
- )
21121
- ] });
21122
- }
21123
- if (field.type === "checkbox") {
21124
- return /* @__PURE__ */ jsxs("label", { className: `flex items-center gap-2 ${field.span2 ? COL2 : ""}`, children: [
21125
- /* @__PURE__ */ jsx(
21126
- WebCheckbox,
21127
- {
21128
- checked: Boolean(val),
21129
- onChange: (e) => {
21130
- const result = field.write(e.target.checked, style);
21131
- onUpdate(typeof result === "function" ? result(style) : result);
21132
- },
21133
- className: "h-4 w-4"
21134
- }
21135
- ),
21136
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel })
21137
- ] });
21138
- }
21139
- if (field.type === "range") {
21140
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21141
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21142
- /* @__PURE__ */ jsx(
21143
- "input",
21144
- {
21145
- type: "range",
21146
- min: field.min ?? 0,
21147
- max: field.max ?? 100,
21148
- value: Number(val),
21149
- onChange: (e) => {
21150
- const result = field.write(Number(e.target.value), style);
21151
- onUpdate(typeof result === "function" ? result(style) : result);
21152
- },
21153
- className: RNG
21154
- }
21155
- )
21156
- ] });
21157
- }
21158
- return /* @__PURE__ */ jsxs("label", { className: cls, children: [
21159
- /* @__PURE__ */ jsx("span", { className: LBL, children: fieldLabel }),
21160
- /* @__PURE__ */ jsx(
21161
- "input",
21162
- {
21163
- type: "number",
21164
- min: field.min,
21165
- max: field.max,
21166
- step: field.step,
21167
- value: Number(val),
21168
- onChange: (e) => {
21169
- const n = safeNum(e.target.value, Number(val));
21170
- const result = field.write(n, style);
21171
- onUpdate(typeof result === "function" ? result(style) : result);
21172
- },
21173
- className: NUM
21174
- }
21175
- )
21176
- ] });
21177
- }
21178
20448
  function SelectRow({
21179
20449
  label,
21180
20450
  value,
@@ -21207,6 +20477,7 @@ function ColorPickerRow({
21207
20477
  }) {
21208
20478
  const { t } = useTranslation();
21209
20479
  const { pushColor } = useRecentColors();
20480
+ const commitRecentColor = useRecentColorCommit();
21210
20481
  const commit = (color, ref) => {
21211
20482
  onChange(color, ref);
21212
20483
  pushColor(color);
@@ -21226,7 +20497,8 @@ function ColorPickerRow({
21226
20497
  type: "color",
21227
20498
  value,
21228
20499
  disabled,
21229
- onChange: (e) => commit(e.target.value),
20500
+ ref: commitRecentColor,
20501
+ onChange: (e) => onChange(e.target.value),
21230
20502
  className: `h-8 flex-1 ${SEL} px-1 ${DIS}`
21231
20503
  }
21232
20504
  ),
@@ -21272,7 +20544,7 @@ function ColorPickerRow({
21272
20544
  `${prefix}-standard-${c.hex}`
21273
20545
  )) })
21274
20546
  ] }),
21275
- /* @__PURE__ */ jsx(RecentColorsRow, { prefix, disabled, onCommit: commit })
20547
+ /* @__PURE__ */ jsx(RecentColorsRow, { disabled, onCommit: commit })
21276
20548
  ] });
21277
20549
  }
21278
20550
  function GradientStopRow({
@@ -21284,6 +20556,7 @@ function GradientStopRow({
21284
20556
  }) {
21285
20557
  const { t } = useTranslation();
21286
20558
  const { pushColor } = useRecentColors();
20559
+ const commitRecentColor = useRecentColorCommit();
21287
20560
  const patchStop = (patch) => {
21288
20561
  const next = allStops.map((s, i) => i === index ? { ...s, ...patch } : s);
21289
20562
  onUpdate(next);
@@ -21295,11 +20568,8 @@ function GradientStopRow({
21295
20568
  {
21296
20569
  type: "color",
21297
20570
  value: normalizeHexColor(stop2.color, "#3b82f6"),
21298
- onChange: (e) => {
21299
- const hex = normalizeHexColor(e.target.value, "#3b82f6");
21300
- patchStop({ color: hex, colorRef: void 0 });
21301
- pushColor(hex);
21302
- },
20571
+ ref: commitRecentColor,
20572
+ onChange: (e) => patchStop({ color: normalizeHexColor(e.target.value, "#3b82f6"), colorRef: void 0 }),
21303
20573
  className: "h-7 w-10 rounded border border-border bg-muted"
21304
20574
  }
21305
20575
  ),
@@ -21592,22 +20862,6 @@ function StrokeEffectsSection({
21592
20862
  onChange: onSetStrokeColor
21593
20863
  }
21594
20864
  ),
21595
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
21596
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.strokeWidth") }),
21597
- /* @__PURE__ */ jsx(
21598
- "input",
21599
- {
21600
- type: "number",
21601
- min: 0,
21602
- value: Math.round(style?.strokeWidth || 0),
21603
- onChange: (e) => {
21604
- const v = safeNum(e.target.value, 0);
21605
- onUpdateShapeStyle({ strokeWidth: Math.max(0, v) });
21606
- },
21607
- className: NUM
21608
- }
21609
- )
21610
- ] }),
21611
20865
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
21612
20866
  /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.fillOpacity") }),
21613
20867
  /* @__PURE__ */ jsx(
@@ -21623,94 +20877,13 @@ function StrokeEffectsSection({
21623
20877
  }
21624
20878
  )
21625
20879
  ] }),
21626
- /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
21627
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.strokeOpacity") }),
21628
- /* @__PURE__ */ jsx(
21629
- "input",
21630
- {
21631
- type: "range",
21632
- min: 0,
21633
- max: 100,
21634
- value: Math.round((style?.strokeOpacity ?? 1) * 100),
21635
- onChange: (e) => onUpdateShapeStyle({
21636
- strokeOpacity: Number(e.target.value) / 100
21637
- }),
21638
- className: RNG
21639
- }
21640
- )
21641
- ] }),
21642
- /* @__PURE__ */ jsxs("label", { className: `flex flex-col gap-1 ${COL2}`, children: [
21643
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.strokeDash") }),
21644
- /* @__PURE__ */ jsx(
21645
- WebSelect,
21646
- {
21647
- "aria-label": t("pptx.strokeEffects.strokeDash"),
21648
- value: style?.strokeDash || "solid",
21649
- onChange: (e) => onUpdateShapeStyle({
21650
- strokeDash: e.target.value
21651
- }),
21652
- className: SEL,
21653
- children: STROKE_DASH_OPTIONS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: t(o.i18nKey) }, o.value))
21654
- }
21655
- )
21656
- ] }),
21657
- /* @__PURE__ */ jsxs("label", { className: `flex flex-col gap-1 ${COL2}`, children: [
21658
- /* @__PURE__ */ jsx("span", { className: LBL, children: t("pptx.strokeEffects.compoundLine") }),
21659
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1", children: COMPOUND_LINE_OPTIONS.map((opt) => /* @__PURE__ */ jsx(
21660
- "button",
21661
- {
21662
- type: "button",
21663
- title: t(opt.i18nKey),
21664
- "aria-label": t(opt.i18nKey),
21665
- 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"}`,
21666
- onClick: () => onUpdateShapeStyle({
21667
- compoundLine: opt.value
21668
- }),
21669
- children: /* @__PURE__ */ jsx(
21670
- "div",
21671
- {
21672
- className: "w-full h-full flex items-center justify-center",
21673
- style: getCompoundLinePreviewStyle(opt.value)
21674
- }
21675
- )
21676
- },
21677
- opt.value
21678
- )) })
21679
- ] }),
21680
- EFFECT_CONFIGS.map((cfg) => {
21681
- const on = cfg.isOn(style);
21682
- return /* @__PURE__ */ jsxs(React107.Fragment, { children: [
21683
- /* @__PURE__ */ jsxs("label", { className: `inline-flex items-center gap-2 text-foreground ${COL2}`, children: [
21684
- /* @__PURE__ */ jsx(
21685
- WebCheckbox,
21686
- {
21687
- checked: on,
21688
- onChange: (e) => {
21689
- onUpdateShapeStyle(e.target.checked ? cfg.onEnable(style) : cfg.onDisable(style));
21690
- }
21691
- }
21692
- ),
21693
- cfg.i18nKey ? t(cfg.i18nKey) : cfg.label
21694
- ] }),
21695
- on && cfg.fields.map((f) => /* @__PURE__ */ jsx(EffectField, { field: f, style, onUpdate: onUpdateShapeStyle }, f.key))
21696
- ] }, cfg.label);
21697
- }),
21698
- /* @__PURE__ */ jsx(
21699
- SelectRow,
21700
- {
21701
- label: t("pptx.strokeEffects.lineJoin"),
21702
- value: style?.lineJoin || "round",
21703
- options: LINE_JOIN_OPTIONS,
21704
- onChange: (v) => onUpdateShapeStyle({ lineJoin: v })
21705
- }
21706
- ),
20880
+ /* @__PURE__ */ jsx(InspectorFields, { sections: SHAPE_LINE_SECTIONS, target: style, onPatch: onUpdateShapeStyle }),
21707
20881
  /* @__PURE__ */ jsx(
21708
- SelectRow,
20882
+ InspectorFields,
21709
20883
  {
21710
- label: t("pptx.strokeEffects.lineCap"),
21711
- value: style?.lineCap || "flat",
21712
- options: LINE_CAP_OPTIONS,
21713
- onChange: (v) => onUpdateShapeStyle({ lineCap: v })
20884
+ sections: SHAPE_EFFECT_SECTIONS,
20885
+ target: style,
20886
+ onPatch: onUpdateShapeStyle
21714
20887
  }
21715
20888
  )
21716
20889
  ] });
@@ -21833,7 +21006,7 @@ function Text3DProperties({
21833
21006
  onUpdateTextStyle
21834
21007
  }) {
21835
21008
  const { t } = useTranslation();
21836
- const { pushColor } = useRecentColors();
21009
+ const commitRecentColor = useRecentColorCommit();
21837
21010
  const t3d = ts?.text3d;
21838
21011
  const hasExtrusion = Boolean(t3d?.extrusionHeight && t3d.extrusionHeight > 0);
21839
21012
  const update3d = (partial) => {
@@ -21880,10 +21053,8 @@ function Text3DProperties({
21880
21053
  {
21881
21054
  type: "color",
21882
21055
  value: normalizeHexColor(t3d?.extrusionColor, "#888888"),
21883
- onChange: (e) => {
21884
- update3d({ extrusionColor: e.target.value });
21885
- pushColor(e.target.value);
21886
- },
21056
+ ref: commitRecentColor,
21057
+ onChange: (e) => update3d({ extrusionColor: e.target.value }),
21887
21058
  className: COLOR_CLS
21888
21059
  }
21889
21060
  )
@@ -22049,7 +21220,7 @@ function AdvancedTextFormatting({
22049
21220
  numChange
22050
21221
  }) {
22051
21222
  const { t } = useTranslation();
22052
- const { pushColor } = useRecentColors();
21223
+ const commitRecentColor = useRecentColorCommit();
22053
21224
  return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded border border-border bg-card p-2 space-y-2", children: [
22054
21225
  /* @__PURE__ */ jsx("div", { className: "text-[11px] uppercase tracking-wide text-muted-foreground", children: t("pptx.textProperties.advancedTextHeading") }),
22055
21226
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: BASELINE_TOGGLES.map(([label, baseline]) => /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-foreground", children: [
@@ -22071,10 +21242,8 @@ function AdvancedTextFormatting({
22071
21242
  {
22072
21243
  type: "color",
22073
21244
  value: normalizeHexColor(ts?.highlightColor, "#ffff00"),
22074
- onChange: (e) => {
22075
- onUpdateTextStyle({ highlightColor: e.target.value });
22076
- pushColor(e.target.value);
22077
- },
21245
+ ref: commitRecentColor,
21246
+ onChange: (e) => onUpdateTextStyle({ highlightColor: e.target.value }),
22078
21247
  disabled: !canEdit,
22079
21248
  className: COLOR_CLS2
22080
21249
  }
@@ -22105,10 +21274,8 @@ function AdvancedTextFormatting({
22105
21274
  {
22106
21275
  type: "color",
22107
21276
  value: ts?.underlineColor || ts?.color || "#000000",
22108
- onChange: (e) => {
22109
- onUpdateTextStyle({ underlineColor: e.target.value });
22110
- pushColor(e.target.value);
22111
- },
21277
+ ref: commitRecentColor,
21278
+ onChange: (e) => onUpdateTextStyle({ underlineColor: e.target.value }),
22112
21279
  className: COLOR_CLS2
22113
21280
  }
22114
21281
  )
@@ -22139,10 +21306,8 @@ function AdvancedTextFormatting({
22139
21306
  {
22140
21307
  type: "color",
22141
21308
  value: ts?.textOutlineColor || "#000000",
22142
- onChange: (e) => {
22143
- onUpdateTextStyle({ textOutlineColor: e.target.value });
22144
- pushColor(e.target.value);
22145
- },
21309
+ ref: commitRecentColor,
21310
+ onChange: (e) => onUpdateTextStyle({ textOutlineColor: e.target.value }),
22146
21311
  className: COLOR_CLS2
22147
21312
  }
22148
21313
  )
@@ -22202,17 +21367,15 @@ function AdvancedTextFormatting({
22202
21367
  )
22203
21368
  ] })
22204
21369
  ] }),
22205
- /* @__PURE__ */ jsxs("label", { className: "inline-flex items-center gap-2 text-foreground", children: [
22206
- /* @__PURE__ */ jsx(
22207
- WebCheckbox,
22208
- {
22209
- checked: Boolean(ts?.autoFit),
22210
- disabled: !canEdit,
22211
- onChange: (e) => onUpdateTextStyle({ autoFit: e.target.checked })
22212
- }
22213
- ),
22214
- t("pptx.textProperties.autoFitToShape")
22215
- ] })
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
+ ) })
22216
21379
  ] });
22217
21380
  }
22218
21381
  function TextReflectionSection({
@@ -22329,7 +21492,7 @@ function TextEffectsPanel({
22329
21492
  numChange
22330
21493
  }) {
22331
21494
  const { t } = useTranslation();
22332
- const { pushColor } = useRecentColors();
21495
+ const commitRecentColor = useRecentColorCommit();
22333
21496
  const hasShadow = Boolean(
22334
21497
  ts?.textShadowColor || typeof ts?.textShadowBlur === "number" && ts.textShadowBlur > 0
22335
21498
  );
@@ -22375,10 +21538,8 @@ function TextEffectsPanel({
22375
21538
  {
22376
21539
  type: "color",
22377
21540
  value: normalizeHexColor(ts?.textShadowColor, "#000000"),
22378
- onChange: (e) => {
22379
- onUpdateTextStyle({ textShadowColor: e.target.value });
22380
- pushColor(e.target.value);
22381
- },
21541
+ ref: commitRecentColor,
21542
+ onChange: (e) => onUpdateTextStyle({ textShadowColor: e.target.value }),
22382
21543
  className: COLOR_CLS2
22383
21544
  }
22384
21545
  )
@@ -22482,10 +21643,8 @@ function TextEffectsPanel({
22482
21643
  {
22483
21644
  type: "color",
22484
21645
  value: normalizeHexColor(ts?.textGlowColor, "#ffff00"),
22485
- onChange: (e) => {
22486
- onUpdateTextStyle({ textGlowColor: e.target.value });
22487
- pushColor(e.target.value);
22488
- },
21646
+ ref: commitRecentColor,
21647
+ onChange: (e) => onUpdateTextStyle({ textGlowColor: e.target.value }),
22489
21648
  className: COLOR_CLS2
22490
21649
  }
22491
21650
  )
@@ -22534,7 +21693,7 @@ function TextWarpGallery({
22534
21693
  onUpdateTextStyle
22535
21694
  }) {
22536
21695
  const { t } = useTranslation();
22537
- const [expanded, setExpanded] = React107.useState(false);
21696
+ const [expanded, setExpanded] = React108.useState(false);
22538
21697
  const currentPreset = ts?.textWarpPreset || "textNoShape";
22539
21698
  const descriptor = useMemo(() => buildTextWarpGallery(ts?.textWarpPreset), [ts?.textWarpPreset]);
22540
21699
  const ref = useRef(null);
@@ -22690,7 +21849,6 @@ function ShapeTextPanels({
22690
21849
  /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsx(
22691
21850
  RecentColorsRow,
22692
21851
  {
22693
- prefix: "text-color",
22694
21852
  disabled: !canEdit,
22695
21853
  onCommit: (hex) => onUpdateTextStyle({ color: hex, colorRef: void 0 })
22696
21854
  }
@@ -22969,209 +22127,6 @@ function SmartArtLayoutSwitcher({
22969
22127
  }) })
22970
22128
  ] });
22971
22129
  }
22972
- var DEFAULT_FILL = "#3b82f6";
22973
- var DEFAULT_FONT = "#ffffff";
22974
- var EMPHASIS_BTN = "px-1.5 py-0.5 text-[10px] rounded border transition-colors disabled:opacity-40 disabled:cursor-not-allowed";
22975
- function SmartArtNodeStyleControls({
22976
- nodeId,
22977
- style,
22978
- label,
22979
- canEdit,
22980
- onChangeStyle
22981
- }) {
22982
- const { pushColor } = useRecentColors();
22983
- const bold = Boolean(style?.bold);
22984
- const italic = Boolean(style?.italic);
22985
- return /* @__PURE__ */ jsxs(
22986
- "div",
22987
- {
22988
- className: "flex items-center gap-1.5 mt-1 pl-4",
22989
- role: "group",
22990
- "aria-label": `Style for ${label}`,
22991
- children: [
22992
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-0.5 text-[9px] text-muted-foreground", children: [
22993
- /* @__PURE__ */ jsx("span", { children: "Fill" }),
22994
- /* @__PURE__ */ jsx(
22995
- "input",
22996
- {
22997
- type: "color",
22998
- disabled: !canEdit,
22999
- "aria-label": `Fill colour for ${label}`,
23000
- className: "h-4 w-5 cursor-pointer rounded border border-border bg-transparent p-0 disabled:cursor-not-allowed",
23001
- value: style?.fillColor ?? DEFAULT_FILL,
23002
- onChange: (e) => {
23003
- onChangeStyle(nodeId, { fillColor: e.target.value });
23004
- pushColor(e.target.value);
23005
- }
23006
- }
23007
- )
23008
- ] }),
23009
- /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-0.5 text-[9px] text-muted-foreground", children: [
23010
- /* @__PURE__ */ jsx("span", { children: "Text" }),
23011
- /* @__PURE__ */ jsx(
23012
- "input",
23013
- {
23014
- type: "color",
23015
- disabled: !canEdit,
23016
- "aria-label": `Font colour for ${label}`,
23017
- className: "h-4 w-5 cursor-pointer rounded border border-border bg-transparent p-0 disabled:cursor-not-allowed",
23018
- value: style?.fontColor ?? DEFAULT_FONT,
23019
- onChange: (e) => {
23020
- onChangeStyle(nodeId, { fontColor: e.target.value });
23021
- pushColor(e.target.value);
23022
- }
23023
- }
23024
- )
23025
- ] }),
23026
- /* @__PURE__ */ jsx(
23027
- "button",
23028
- {
23029
- type: "button",
23030
- disabled: !canEdit,
23031
- "aria-label": `Bold ${label}`,
23032
- "aria-pressed": bold,
23033
- className: cn(
23034
- EMPHASIS_BTN,
23035
- "font-bold",
23036
- bold ? "border-primary bg-primary/20 text-primary" : "border-border text-muted-foreground"
23037
- ),
23038
- onClick: () => onChangeStyle(nodeId, { bold: !bold }),
23039
- children: "B"
23040
- }
23041
- ),
23042
- /* @__PURE__ */ jsx(
23043
- "button",
23044
- {
23045
- type: "button",
23046
- disabled: !canEdit,
23047
- "aria-label": `Italic ${label}`,
23048
- "aria-pressed": italic,
23049
- className: cn(
23050
- EMPHASIS_BTN,
23051
- "italic",
23052
- italic ? "border-primary bg-primary/20 text-primary" : "border-border text-muted-foreground"
23053
- ),
23054
- onClick: () => onChangeStyle(nodeId, { italic: !italic }),
23055
- children: "I"
23056
- }
23057
- )
23058
- ]
23059
- }
23060
- );
23061
- }
23062
- var MINI_BTN = "text-[9px] text-muted-foreground hover:text-primary px-1 disabled:opacity-40 disabled:cursor-not-allowed";
23063
- function SmartArtNodeRow({
23064
- nodeId,
23065
- text,
23066
- displayIndex,
23067
- isChild,
23068
- canEdit,
23069
- removeDisabled,
23070
- moveUpDisabled,
23071
- moveDownDisabled,
23072
- inputRef,
23073
- style,
23074
- onChangeText,
23075
- onKeyDown,
23076
- onAddSubItem,
23077
- onMoveUp,
23078
- onMoveDown,
23079
- onRemove,
23080
- onChangeStyle
23081
- }) {
23082
- const { t } = useTranslation();
23083
- const label = isChild ? `Sub-item: ${text || "empty"}` : `Item ${displayIndex}: ${text || "empty"}`;
23084
- return /* @__PURE__ */ jsxs(
23085
- "div",
23086
- {
23087
- role: "listitem",
23088
- className: cn(
23089
- "rounded border bg-background/60 p-1.5",
23090
- isChild ? "border-border/60 ml-4" : "border-border"
23091
- ),
23092
- children: [
23093
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
23094
- /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground w-3 shrink-0", "aria-hidden": "true", children: isChild ? "\u2022" : `${displayIndex}` }),
23095
- /* @__PURE__ */ jsx(
23096
- "input",
23097
- {
23098
- ref: inputRef,
23099
- type: "text",
23100
- "data-testid": "smartart-node-text",
23101
- disabled: !canEdit,
23102
- "aria-label": label,
23103
- className: cn(INPUT2, "flex-1 text-[11px] py-0.5"),
23104
- value: text,
23105
- onChange: (e) => onChangeText(nodeId, e.target.value),
23106
- onKeyDown: (e) => onKeyDown(e, nodeId),
23107
- placeholder: t("pptx.smartArt.nodePlaceholder")
23108
- }
23109
- ),
23110
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [
23111
- /* @__PURE__ */ jsx(
23112
- "button",
23113
- {
23114
- type: "button",
23115
- disabled: !canEdit || moveUpDisabled,
23116
- className: MINI_BTN,
23117
- onClick: () => onMoveUp(nodeId),
23118
- "aria-label": `Move ${label} up`,
23119
- title: t("pptx.smartArt.moveUp"),
23120
- children: "\u2191"
23121
- }
23122
- ),
23123
- /* @__PURE__ */ jsx(
23124
- "button",
23125
- {
23126
- type: "button",
23127
- disabled: !canEdit || moveDownDisabled,
23128
- className: MINI_BTN,
23129
- onClick: () => onMoveDown(nodeId),
23130
- "aria-label": `Move ${label} down`,
23131
- title: t("pptx.smartArt.moveDown"),
23132
- children: "\u2193"
23133
- }
23134
- ),
23135
- !isChild && /* @__PURE__ */ jsx(
23136
- "button",
23137
- {
23138
- type: "button",
23139
- disabled: !canEdit,
23140
- className: MINI_BTN,
23141
- onClick: () => onAddSubItem(nodeId),
23142
- "aria-label": `Add sub-item under ${label}`,
23143
- title: t("pptx.smartArt.addSubItem"),
23144
- children: "+Sub"
23145
- }
23146
- ),
23147
- /* @__PURE__ */ jsx(
23148
- "button",
23149
- {
23150
- type: "button",
23151
- disabled: !canEdit || removeDisabled,
23152
- className: cn(MINI_BTN, "hover:text-red-400"),
23153
- onClick: () => onRemove(nodeId),
23154
- "aria-label": `Remove ${label}`,
23155
- title: removeDisabled ? t("pptx.smartArt.layoutMinimum") : t("pptx.smartArt.remove"),
23156
- children: "x"
23157
- }
23158
- )
23159
- ] })
23160
- ] }),
23161
- /* @__PURE__ */ jsx(
23162
- SmartArtNodeStyleControls,
23163
- {
23164
- nodeId,
23165
- style,
23166
- label,
23167
- canEdit,
23168
- onChangeStyle
23169
- }
23170
- )
23171
- ]
23172
- }
23173
- );
23174
- }
23175
22130
  function SmartArtStyleControls({
23176
22131
  colorSchemes,
23177
22132
  styleOptions,
@@ -23182,7 +22137,7 @@ function SmartArtStyleControls({
23182
22137
  onChangeStyle
23183
22138
  }) {
23184
22139
  const { t } = useTranslation();
23185
- const translate = React107.useCallback((key) => t(key), [t]);
22140
+ const translate = React108.useCallback((key) => t(key), [t]);
23186
22141
  return /* @__PURE__ */ jsxs(Fragment, { children: [
23187
22142
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
23188
22143
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.smartart.colorScheme") }),
@@ -23234,22 +22189,9 @@ function SmartArtPropertiesPanel({
23234
22189
  box
23235
22190
  }) {
23236
22191
  const { t } = useTranslation();
23237
- const nodes = smartArtData.nodes ?? [];
23238
- const layout = smartArtData.resolvedLayoutType;
23239
- const topLevelCount = nodes.filter((n) => !n.parentId).length;
23240
- const inputRefs = React107.useRef(/* @__PURE__ */ new Map());
23241
- const pendingFocusId = React107.useRef(null);
23242
- React107.useEffect(() => {
23243
- const id = pendingFocusId.current;
23244
- if (id) {
23245
- inputRefs.current.get(id)?.focus();
23246
- pendingFocusId.current = null;
23247
- }
23248
- });
23249
- const applySmartArtData = (newData, focusId) => {
23250
- if (focusId) {
23251
- pendingFocusId.current = focusId;
23252
- }
22192
+ const { pushColor } = useRecentColors();
22193
+ const paneRef = React108.useRef(null);
22194
+ const applySmartArtData = (newData) => {
23253
22195
  const reflowed = box ? rebuildDrawingShapesIfCleared(
23254
22196
  newData,
23255
22197
  newData.layout,
@@ -23260,87 +22202,35 @@ function SmartArtPropertiesPanel({
23260
22202
  ) : newData;
23261
22203
  onUpdateElement({ smartArtData: reflowed });
23262
22204
  };
22205
+ const applyRef = React108.useRef(applySmartArtData);
22206
+ applyRef.current = applySmartArtData;
23263
22207
  const updateSmartArt = (patch) => {
23264
22208
  applySmartArtData({ ...smartArtData, ...patch });
23265
22209
  };
23266
- const handleUpdateNodeText = (nodeId, text) => {
23267
- applySmartArtData(updateSmartArtNodeText(smartArtData, nodeId, text));
23268
- };
23269
- const handleChangeNodeStyle = (nodeId, patch) => {
23270
- const next = setSmartArtNodeStyle(smartArtData, nodeId, patch);
23271
- if (next !== smartArtData) {
23272
- applySmartArtData(next);
23273
- }
23274
- };
23275
- const addNode = () => {
23276
- if (!canAddTopLevelNode(layout, topLevelCount)) {
23277
- return;
22210
+ React108.useLayoutEffect(() => {
22211
+ if (paneRef.current) {
22212
+ paneRef.current.state = {
22213
+ smartArtData,
22214
+ canEdit,
22215
+ translate: (key, params) => t(key, params)
22216
+ };
23278
22217
  }
23279
- applySmartArtData(addSmartArtNodeAsChild(smartArtData));
23280
- };
23281
- const addSubItem = (parentId) => {
23282
- applySmartArtData(addSmartArtNodeAsChild(smartArtData, parentId, "Sub-item"));
23283
- };
23284
- const removeNode = (nodeId) => {
23285
- const isTopLevel = !nodes.find((n) => n.id === nodeId)?.parentId;
23286
- if (isTopLevel && !canRemoveTopLevelNode(layout, topLevelCount)) {
22218
+ }, [smartArtData, canEdit, t]);
22219
+ React108.useEffect(() => {
22220
+ const pane = paneRef.current;
22221
+ if (!pane) {
23287
22222
  return;
23288
22223
  }
23289
- applySmartArtData(removeSmartArtNode(smartArtData, nodeId));
23290
- };
23291
- const moveNode = (nodeId, direction) => {
23292
- const next = reorder(smartArtData, nodeId, direction);
23293
- if (next) {
23294
- applySmartArtData(next, nodeId);
23295
- }
23296
- };
23297
- const handleKeyDown = (e, nodeId) => {
23298
- const node = nodes.find((n) => n.id === nodeId);
23299
- const isEmpty = !node?.text;
23300
- if (e.key === "Enter") {
23301
- e.preventDefault();
23302
- const result = addSiblingAfter(smartArtData, nodeId);
23303
- if (result) {
23304
- applySmartArtData(result.data, result.focusNodeId);
23305
- }
23306
- } else if ((e.key === "Backspace" || e.key === "Delete") && isEmpty) {
23307
- const isTop = !node?.parentId;
23308
- if (isTop && !canRemoveTopLevelNode(layout, topLevelCount)) {
23309
- return;
22224
+ const commit = (event) => {
22225
+ const { smartArtData: next, recentColor } = event.detail;
22226
+ applyRef.current(next);
22227
+ if (recentColor) {
22228
+ pushColor(recentColor);
23310
22229
  }
23311
- e.preventDefault();
23312
- const result = removeEmptyNode(smartArtData, nodeId);
23313
- if (result) {
23314
- applySmartArtData(result.data, result.focusNodeId);
23315
- }
23316
- } else if (e.key === "Tab" && !e.shiftKey) {
23317
- e.preventDefault();
23318
- const next = demote(smartArtData, nodeId);
23319
- if (next) {
23320
- applySmartArtData(next, nodeId);
23321
- }
23322
- } else if (e.key === "Tab" && e.shiftKey) {
23323
- e.preventDefault();
23324
- const next = promote(smartArtData, nodeId);
23325
- if (next) {
23326
- applySmartArtData(next, nodeId);
23327
- }
23328
- }
23329
- };
23330
- const setInputRef = (nodeId) => (el) => {
23331
- if (el) {
23332
- inputRefs.current.set(nodeId, el);
23333
- } else {
23334
- inputRefs.current.delete(nodeId);
23335
- }
23336
- };
23337
- const boundsHint = describeSmartArtBounds(layout);
23338
- const addDisabled = !canEdit || !canAddTopLevelNode(layout, topLevelCount);
23339
- const extraConnections = classifyExtraConnections(smartArtData);
23340
- const extraConnectionSummary = Array.from(
23341
- new Set(extraConnections.map((c) => c.type ?? "unknown"))
23342
- ).join(", ");
23343
- let topDisplayIndex = 0;
22230
+ };
22231
+ pane.addEventListener("pptx-smartart-data-change", commit);
22232
+ return () => pane.removeEventListener("pptx-smartart-data-change", commit);
22233
+ }, [pushColor]);
23344
22234
  return /* @__PURE__ */ jsxs("div", { className: CARD2, role: "group", "aria-label": t("pptx.smartart.title"), children: [
23345
22235
  /* @__PURE__ */ jsx("div", { className: HEADING2, children: t("pptx.smartart.title") }),
23346
22236
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
@@ -23364,76 +22254,12 @@ function SmartArtPropertiesPanel({
23364
22254
  onChangeStyle: (style) => updateSmartArt({ style })
23365
22255
  }
23366
22256
  ),
23367
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
23368
- /* @__PURE__ */ jsxs("span", { className: "text-[11px] text-muted-foreground", children: [
23369
- t("pptx.smartart.textPane"),
23370
- " (",
23371
- nodes.length,
23372
- ")"
23373
- ] }),
23374
- /* @__PURE__ */ jsx(
23375
- "button",
23376
- {
23377
- type: "button",
23378
- disabled: addDisabled,
23379
- className: BTN2,
23380
- onClick: addNode,
23381
- title: addDisabled ? boundsHint : void 0,
23382
- children: t("pptx.smartart.addItem")
23383
- }
23384
- )
23385
- ] }),
23386
- boundsHint && /* @__PURE__ */ jsx("div", { className: "text-[9px] text-muted-foreground", role: "note", children: boundsHint }),
23387
- /* @__PURE__ */ jsx("div", { className: "max-h-52 overflow-y-auto space-y-1 pr-1", role: "list", children: nodes.map((node) => {
23388
- const isChild = Boolean(node.parentId);
23389
- if (!isChild) {
23390
- topDisplayIndex += 1;
23391
- }
23392
- const sIdx = siblingIndex(smartArtData, node.id);
23393
- const sCount = siblingCount(smartArtData, node.id);
23394
- const removeDisabled = nodes.length <= 1 || !isChild && !canRemoveTopLevelNode(layout, topLevelCount);
23395
- return /* @__PURE__ */ jsx(
23396
- SmartArtNodeRow,
23397
- {
23398
- nodeId: node.id,
23399
- text: node.text,
23400
- displayIndex: topDisplayIndex,
23401
- isChild,
23402
- canEdit,
23403
- removeDisabled,
23404
- moveUpDisabled: sIdx <= 0,
23405
- moveDownDisabled: sIdx < 0 || sIdx >= sCount - 1,
23406
- inputRef: setInputRef(node.id),
23407
- style: node.style,
23408
- onChangeText: handleUpdateNodeText,
23409
- onKeyDown: handleKeyDown,
23410
- onAddSubItem: addSubItem,
23411
- onMoveUp: (id) => moveNode(id, -1),
23412
- onMoveDown: (id) => moveNode(id, 1),
23413
- onRemove: removeNode,
23414
- onChangeStyle: handleChangeNodeStyle
23415
- },
23416
- node.id
23417
- );
23418
- }) }),
23419
- extraConnections.length > 0 && /* @__PURE__ */ jsxs(
23420
- "div",
23421
- {
23422
- className: "text-[9px] text-muted-foreground",
23423
- role: "note",
23424
- "aria-label": `${extraConnections.length} non-tree relationship connection(s): ${extraConnectionSummary}`,
23425
- children: [
23426
- t("pptx.smartart.extraConnections", { count: extraConnections.length }),
23427
- /* @__PURE__ */ jsx("span", { className: "block opacity-80", children: extraConnectionSummary })
23428
- ]
23429
- }
23430
- ),
23431
- /* @__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" })
23432
22258
  ] })
23433
22259
  ] });
23434
22260
  }
23435
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";
23436
- 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";
23437
22263
  var REMOVE_BTN = "px-0.5 leading-none text-destructive hover:opacity-80";
23438
22264
  function TableDataGrid({
23439
22265
  tableElement,
@@ -23577,7 +22403,7 @@ function TableDataGrid({
23577
22403
  "input",
23578
22404
  {
23579
22405
  type: "text",
23580
- className: CELL_INPUT2,
22406
+ className: CELL_INPUT,
23581
22407
  disabled: !canEdit,
23582
22408
  "aria-label": t("pptx.tableDataEditor.cellAriaLabel", {
23583
22409
  row: cell.rowIndex + 1,
@@ -23607,7 +22433,7 @@ function TableCellPatternFill({
23607
22433
  onUpdateCellStyle
23608
22434
  }) {
23609
22435
  const { t } = useTranslation();
23610
- const { pushColor } = useRecentColors();
22436
+ const commitRecentColor = useRecentColorCommit();
23611
22437
  const translate = (key) => t(key);
23612
22438
  return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
23613
22439
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-0.5", children: [
@@ -23634,10 +22460,8 @@ function TableCellPatternFill({
23634
22460
  disabled: !canEdit,
23635
22461
  className: "w-full h-7 rounded border border-border bg-transparent cursor-pointer",
23636
22462
  value: cellStyle.patternFillForeground ?? "#000000",
23637
- onChange: (e) => {
23638
- onUpdateCellStyle({ patternFillForeground: e.target.value });
23639
- pushColor(e.target.value);
23640
- }
22463
+ ref: commitRecentColor,
22464
+ onChange: (e) => onUpdateCellStyle({ patternFillForeground: e.target.value })
23641
22465
  }
23642
22466
  )
23643
22467
  ] }),
@@ -23650,10 +22474,8 @@ function TableCellPatternFill({
23650
22474
  disabled: !canEdit,
23651
22475
  className: "w-full h-7 rounded border border-border bg-transparent cursor-pointer",
23652
22476
  value: cellStyle.patternFillBackground ?? "#FFFFFF",
23653
- onChange: (e) => {
23654
- onUpdateCellStyle({ patternFillBackground: e.target.value });
23655
- pushColor(e.target.value);
23656
- }
22477
+ ref: commitRecentColor,
22478
+ onChange: (e) => onUpdateCellStyle({ patternFillBackground: e.target.value })
23657
22479
  }
23658
22480
  )
23659
22481
  ] })
@@ -23754,7 +22576,7 @@ function GradientControls({
23754
22576
  onUpdateCellStyle
23755
22577
  }) {
23756
22578
  const { t } = useTranslation();
23757
- const { pushColor } = useRecentColors();
22579
+ const commitRecentColor = useRecentColorCommit();
23758
22580
  const stops = cellStyle.gradientFillStops ?? [];
23759
22581
  const gradType = cellStyle.gradientFillType ?? "linear";
23760
22582
  const updateStop = (index, patch) => {
@@ -23811,10 +22633,8 @@ function GradientControls({
23811
22633
  disabled: !canEdit,
23812
22634
  className: "h-6 w-6 rounded border border-border cursor-pointer",
23813
22635
  value: stop2.color,
23814
- onChange: (e) => {
23815
- updateStop(idx, { color: e.target.value });
23816
- pushColor(e.target.value);
23817
- }
22636
+ ref: commitRecentColor,
22637
+ onChange: (e) => updateStop(idx, { color: e.target.value })
23818
22638
  }
23819
22639
  ),
23820
22640
  /* @__PURE__ */ jsx(
@@ -24586,21 +23406,15 @@ function ElementInspectorBody({
24586
23406
  }
24587
23407
  )
24588
23408
  ] }),
24589
- /* @__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: [
24590
- /* @__PURE__ */ jsx("span", { className: "w-4 text-muted-foreground", children: label }),
24591
- /* @__PURE__ */ jsx(
24592
- "input",
24593
- {
24594
- type: "number",
24595
- className: INPUT2,
24596
- disabled: !canEdit,
24597
- value: Math.round(selectedElement[key] ?? 0),
24598
- onChange: (e) => onUpdateElement({
24599
- [key]: Number(e.target.value)
24600
- })
24601
- }
24602
- )
24603
- ] }, 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
+ ) })
24604
23418
  ] }),
24605
23419
  selectedElement.type === "table" && /* @__PURE__ */ jsxs(Fragment, { children: [
24606
23420
  /* @__PURE__ */ jsx(
@@ -24839,7 +23653,7 @@ function CommentBody({ text, mentions, className }) {
24839
23653
  index
24840
23654
  ) : (
24841
23655
  // eslint-disable-next-line react/no-array-index-key -- segments are positional
24842
- /* @__PURE__ */ jsx(React107.Fragment, { children: segment.text }, index)
23656
+ /* @__PURE__ */ jsx(React108.Fragment, { children: segment.text }, index)
24843
23657
  )
24844
23658
  ) });
24845
23659
  }
@@ -26356,7 +25170,7 @@ function PresentationPropertiesPanel({
26356
25170
  onUpdateTagCollections
26357
25171
  }) {
26358
25172
  const { t } = useTranslation();
26359
- const handleTransitionChange = React107.useCallback(
25173
+ const handleTransitionChange = React108.useCallback(
26360
25174
  (updates) => {
26361
25175
  onUpdateSlide({
26362
25176
  transition: mergeSlideTransition(activeSlide?.transition, updates)
@@ -29837,7 +28651,7 @@ function ViewerToolbarSection(props) {
29837
28651
  },
29838
28652
  [activeSlide, propertyHandlers]
29839
28653
  );
29840
- const scopedLayoutOptions = React107.useMemo(
28654
+ const scopedLayoutOptions = React108.useMemo(
29841
28655
  () => scopeLayoutOptionsToActiveSlide(s.layoutOptions, activeSlide),
29842
28656
  [s.layoutOptions, activeSlide]
29843
28657
  );
@@ -30113,6 +28927,7 @@ function ViewerToolbarSection(props) {
30113
28927
  onAddShape: insertHandlers.handleAddShape,
30114
28928
  onAddTable: insertHandlers.handleAddTable,
30115
28929
  onAddChart: insertHandlers.handleAddChart,
28930
+ onOpenChartDialog: () => dialogs.setIsChartDialogOpen(true),
30116
28931
  onAddSmartArt: () => dialogs.setIsSmartArtDialogOpen(true),
30117
28932
  onAddEquation: () => {
30118
28933
  dialogs.setEditingEquationOmml(null);
@@ -30505,183 +29320,67 @@ function EquationEditorDialog({
30505
29320
  }
30506
29321
  );
30507
29322
  }
30508
- var PREVIEW_TILE_WIDTH2 = 64;
30509
- function getPreviewForLayout(layout) {
30510
- const scale = PREVIEW_TILE_WIDTH2 / SMARTART_PREVIEW_ELEMENT_WIDTH;
30511
- return /* @__PURE__ */ jsx(
30512
- "div",
30513
- {
30514
- "aria-hidden": true,
30515
- className: "overflow-hidden pointer-events-none",
30516
- style: {
30517
- width: PREVIEW_TILE_WIDTH2,
30518
- height: Math.round(SMARTART_PREVIEW_ELEMENT_HEIGHT * scale)
30519
- },
30520
- children: /* @__PURE__ */ jsx(
30521
- "div",
30522
- {
30523
- style: {
30524
- width: SMARTART_PREVIEW_ELEMENT_WIDTH,
30525
- height: SMARTART_PREVIEW_ELEMENT_HEIGHT,
30526
- transform: `scale(${scale})`,
30527
- transformOrigin: "top left"
30528
- },
30529
- children: /* @__PURE__ */ jsx(SmartArtRenderer, { element: buildSmartArtPreviewElement(layout) })
30530
- }
30531
- )
29323
+ function useDialogEvents(ref, insertEvent, onInsert, onClose) {
29324
+ useEffect(() => {
29325
+ const host = ref.current;
29326
+ if (!host) {
29327
+ return;
30532
29328
  }
30533
- );
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]);
30534
29336
  }
30535
29337
  function InsertSmartArtDialog({
30536
29338
  isOpen,
30537
29339
  onClose,
30538
29340
  onInsert
30539
29341
  }) {
29342
+ const ref = useRef(null);
30540
29343
  const { t } = useTranslation();
30541
- const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
30542
- const [activeCategory, setActiveCategory] = useState("list");
30543
- const [selectedLayout, setSelectedLayout] = useState(null);
30544
- const dialogRef = useRef(null);
30545
- useModalFocus(isOpen, dialogRef, onClose);
30546
- const filteredPresets = PRESETS.filter((p) => p.category === activeCategory);
30547
- const handleInsert = useCallback(() => {
30548
- if (!selectedLayout) {
30549
- return;
29344
+ useLayoutEffect(() => {
29345
+ if (ref.current) {
29346
+ ref.current.translateLabel = t;
29347
+ ref.current.open = isOpen;
30550
29348
  }
30551
- const preset = PRESETS.find((p) => p.layout === selectedLayout);
30552
- if (!preset) {
30553
- 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;
30554
29372
  }
30555
- onInsert(preset.layout, preset.defaultItems);
30556
- onClose();
30557
- }, [selectedLayout, onInsert, onClose]);
30558
- if (!isOpen) {
30559
- return null;
30560
- }
30561
- return /* @__PURE__ */ jsxs(Fragment, { children: [
30562
- /* @__PURE__ */ jsx(
30563
- "button",
30564
- {
30565
- type: "button",
30566
- style: { zIndex: 1200 },
30567
- className: "fixed inset-0 bg-black/50",
30568
- onClick: onClose,
30569
- "aria-label": t("pptx.smartart.close")
30570
- }
30571
- ),
30572
- /* @__PURE__ */ jsx(
30573
- "div",
30574
- {
30575
- style: { zIndex: 1201 },
30576
- className: "fixed inset-0 flex items-center justify-center pointer-events-none",
30577
- children: /* @__PURE__ */ jsxs(
30578
- "div",
30579
- {
30580
- ref: dialogRef,
30581
- style: panelStyle,
30582
- 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)]",
30583
- role: "dialog",
30584
- "aria-modal": "true",
30585
- "aria-label": t("pptx.smartart.insertTitle"),
30586
- tabIndex: -1,
30587
- children: [
30588
- /* @__PURE__ */ jsxs(
30589
- "div",
30590
- {
30591
- ...dragHandlers,
30592
- className: "flex items-center justify-between px-4 py-3 border-b border-border touch-none",
30593
- children: [
30594
- /* @__PURE__ */ jsx("h2", { className: "text-sm font-medium text-foreground", children: t("pptx.smartart.insertTitle") }),
30595
- /* @__PURE__ */ jsx(
30596
- "button",
30597
- {
30598
- type: "button",
30599
- onClick: onClose,
30600
- className: "p-1 rounded hover:bg-muted transition-colors",
30601
- "aria-label": t("pptx.smartart.close"),
30602
- children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
30603
- }
30604
- )
30605
- ]
30606
- }
30607
- ),
30608
- /* @__PURE__ */ jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
30609
- /* @__PURE__ */ jsx(
30610
- "nav",
30611
- {
30612
- className: "w-40 border-r border-border py-2",
30613
- "aria-label": t("pptx.insertSmartArt.categories"),
30614
- children: CATEGORIES.map((cat) => /* @__PURE__ */ jsx(
30615
- "button",
30616
- {
30617
- type: "button",
30618
- onClick: () => {
30619
- setActiveCategory(cat.id);
30620
- setSelectedLayout(null);
30621
- },
30622
- className: cn(
30623
- "w-full text-left px-3 py-1.5 text-xs transition-colors",
30624
- activeCategory === cat.id ? "bg-primary text-white" : "text-foreground hover:bg-muted"
30625
- ),
30626
- children: t(cat.label)
30627
- },
30628
- cat.id
30629
- ))
30630
- }
30631
- ),
30632
- /* @__PURE__ */ jsx("div", { className: "flex-1 p-3 overflow-y-auto", children: /* @__PURE__ */ jsx(
30633
- "div",
30634
- {
30635
- className: "grid grid-cols-3 gap-2",
30636
- role: "listbox",
30637
- "aria-label": t("pptx.insertSmartArt.layouts"),
30638
- children: filteredPresets.map((preset) => /* @__PURE__ */ jsxs(
30639
- "button",
30640
- {
30641
- type: "button",
30642
- role: "option",
30643
- "aria-selected": selectedLayout === preset.layout,
30644
- onClick: () => setSelectedLayout(preset.layout),
30645
- onDoubleClick: () => {
30646
- setSelectedLayout(preset.layout);
30647
- onInsert(preset.layout, preset.defaultItems);
30648
- onClose();
30649
- },
30650
- className: cn(
30651
- "flex flex-col items-center gap-1 p-2 rounded border transition-colors",
30652
- selectedLayout === preset.layout ? "border-primary bg-primary/20" : "border-border hover:border-border hover:bg-muted/50"
30653
- ),
30654
- children: [
30655
- /* @__PURE__ */ jsx("div", { className: "w-16 h-12 flex items-center justify-center bg-muted rounded", children: getPreviewForLayout(preset.layout) }),
30656
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-foreground text-center leading-tight", children: t(preset.labelKey) })
30657
- ]
30658
- },
30659
- preset.layout
30660
- ))
30661
- }
30662
- ) })
30663
- ] }),
30664
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
30665
- DialogFooter,
30666
- {
30667
- actions: [
30668
- { id: "cancel", label: t("pptx.smartart.cancel") },
30669
- {
30670
- id: "insert",
30671
- label: t("pptx.smartart.insert"),
30672
- variant: "primary",
30673
- disabled: !selectedLayout
30674
- }
30675
- ],
30676
- onAction: (id) => id === "insert" ? handleInsert() : onClose()
30677
- }
30678
- ) })
30679
- ]
30680
- }
30681
- )
30682
- }
30683
- )
30684
- ] });
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 });
30685
29384
  }
30686
29385
  function ViewerDialogGroup(props) {
30687
29386
  const {
@@ -30807,6 +29506,14 @@ function ViewerDialogGroup(props) {
30807
29506
  onInsert: insertHandlers.handleInsertSmartArt
30808
29507
  }
30809
29508
  ),
29509
+ /* @__PURE__ */ jsx(
29510
+ InsertChartDialog,
29511
+ {
29512
+ isOpen: dialogs.isChartDialogOpen,
29513
+ onClose: () => dialogs.setIsChartDialogOpen(false),
29514
+ onInsert: insertHandlers.handleAddChart
29515
+ }
29516
+ ),
30810
29517
  /* @__PURE__ */ jsx(
30811
29518
  EquationEditorDialog,
30812
29519
  {
@@ -31791,7 +30498,7 @@ function useTableStyleMapHandlers(input) {
31791
30498
  var AiChatPanel = /* @__PURE__ */ lazy(async () => {
31792
30499
  const [{ useChat }, { default: Panel }] = await Promise.all([
31793
30500
  import('@ai-sdk/react'),
31794
- import('./AiChatPanel-NKTBHT5B.mjs')
30501
+ import('./AiChatPanel-VJV5OEG2.mjs')
31795
30502
  ]);
31796
30503
  function BoundAiChatPanel(props) {
31797
30504
  return /* @__PURE__ */ jsx(Panel, { ...props, useChat });
@@ -33335,31 +32042,22 @@ function MobileChromeOverlay(props) {
33335
32042
  function ReadOnlyBanner(p) {
33336
32043
  const { t } = useTranslation();
33337
32044
  const ref = useWebControl(
32045
+ readOnlyBannerState(
32046
+ p.recommendation,
32047
+ {
32048
+ passwordPromptOpen: p.passwordPromptOpen ?? false,
32049
+ passwordError: p.passwordError ?? null,
32050
+ checkingPassword: p.checkingPassword ?? false
32051
+ },
32052
+ t
32053
+ ),
33338
32054
  {
33339
- kind: p.recommendation.kind ?? null,
33340
- messageKey: p.recommendation.messageKey,
33341
- passwordPromptOpen: p.passwordPromptOpen ?? false,
33342
- passwordError: p.passwordError ?? null,
33343
- checkingPassword: p.checkingPassword ?? false,
33344
- translate: t
33345
- },
33346
- {
33347
- "read-only-request": (event) => {
33348
- const intent = event.detail;
33349
- switch (intent.id) {
33350
- case "editAnyway":
33351
- p.onEditAnyway();
33352
- break;
33353
- case "dismiss":
33354
- p.onDismiss();
33355
- break;
33356
- case "cancelPassword":
33357
- p.onCancelPassword?.();
33358
- break;
33359
- case "submitPassword":
33360
- p.onSubmitPassword?.(intent.password);
33361
- }
33362
- }
32055
+ "read-only-request": (event) => dispatchReadOnlyBannerIntent(event, {
32056
+ editAnyway: p.onEditAnyway,
32057
+ dismiss: p.onDismiss,
32058
+ cancelPassword: p.onCancelPassword,
32059
+ submitPassword: p.onSubmitPassword
32060
+ })
33363
32061
  }
33364
32062
  );
33365
32063
  return /* @__PURE__ */ jsx("pptx-ui-read-only-banner", { ref });
@@ -34067,253 +32765,120 @@ function useAiBridge(input) {
34067
32765
  const ref = useRef(input);
34068
32766
  ref.current = input;
34069
32767
  return useMemo(() => {
34070
- const applySlidesUpdate = (updater, _label) => {
34071
- const live = ref.current;
34072
- live.setSlides((prev) => updater(structuredClone(prev)));
34073
- live.bumpHistory();
34074
- live.markDirty();
34075
- };
34076
- const readDeckData = (live) => ({
34077
- slides: live.slides,
34078
- width: live.canvasSize.width,
34079
- height: live.canvasSize.height,
34080
- theme: live.theme,
34081
- sections: live.sections,
34082
- presentationProperties: live.presentationProperties,
34083
- customProperties: live.customProperties,
34084
- coreProperties: live.coreProperties,
34085
- appProperties: live.appProperties,
34086
- viewProperties: live.viewProperties,
34087
- tableStyleMap: live.tableStyleMap,
34088
- tableStylesDefaultId: live.tableStylesDefaultId,
34089
- tags: live.tagCollections
34090
- });
34091
- const differs = deckDataFieldChanged;
34092
- return {
34093
- getDeckMeta() {
34094
- const live = ref.current;
34095
- const firstTitle = live.slides[0]?.elements.find(
34096
- (el) => "text" in el && typeof el.text === "string" && el.text.trim().length > 0
34097
- );
34098
- return {
34099
- slideCount: live.slides.length,
34100
- activeSlideIndex: live.activeSlideIndex,
34101
- title: live.fileName ?? (firstTitle && "text" in firstTitle ? String(firstTitle.text) : void 0),
34102
- width: live.canvasSize.width,
34103
- height: live.canvasSize.height
34104
- };
34105
- },
34106
- getSlides: () => ref.current.slides,
34107
- getActiveSlideIndex: () => ref.current.activeSlideIndex,
34108
- getTheme: () => ref.current.theme,
34109
- getHandler: () => ref.current.handlerRef.current ?? void 0,
34110
- goToSlide(index) {
34111
- ref.current.setActiveSlideIndex(index);
34112
- },
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),
34113
32786
  selectElements(slideIndex, elementIds) {
34114
- const live = ref.current;
34115
- if (slideIndex !== live.activeSlideIndex) {
34116
- live.setActiveSlideIndex(slideIndex);
32787
+ const current = live();
32788
+ if (slideIndex !== current.activeSlideIndex) {
32789
+ current.setActiveSlideIndex(slideIndex);
34117
32790
  }
34118
- live.applySelection(elementIds[0] ?? null, elementIds);
34119
- },
34120
- applySlidesUpdate,
34121
- updateElement(slideIndex, elementId2, updates) {
34122
- applySlidesUpdate((slides) => {
34123
- const el = slides[slideIndex]?.elements.find((e) => e.id === elementId2);
34124
- if (el) {
34125
- applyElementUpdate(el, updates);
34126
- }
34127
- return slides;
34128
- });
32791
+ current.applySelection(elementIds[0] ?? null, elementIds);
34129
32792
  },
34130
- applyTheme(updates) {
34131
- ref.current.applyThemeUpdates(updates);
32793
+ updateSlides(update) {
32794
+ const current = live();
32795
+ current.setSlides((prev) => update(prev));
32796
+ current.bumpHistory();
32797
+ current.markDirty();
34132
32798
  },
34133
- getDeckData() {
34134
- return readDeckData(ref.current);
34135
- },
34136
- applyDeckData(updater, _label) {
34137
- const live = ref.current;
34138
- const before = readDeckData(live);
34139
- const after = updater(structuredClone(before));
34140
- if (differs(before.slides, after.slides)) {
34141
- live.setSlides(() => after.slides);
34142
- live.bumpHistory();
34143
- }
34144
- if (before.width !== after.width || before.height !== after.height) {
34145
- live.setCanvasSize({ width: after.width, height: after.height });
34146
- }
34147
- const nextSections = after.sections ?? before.sections ?? [];
34148
- if (differs(before.sections, nextSections)) {
34149
- live.setSections(nextSections);
34150
- }
34151
- const nextPresProps = after.presentationProperties ?? live.presentationProperties;
34152
- if (differs(before.presentationProperties, nextPresProps)) {
34153
- live.setPresentationProperties(nextPresProps);
34154
- }
34155
- const nextCustomProps = after.customProperties ?? before.customProperties ?? [];
34156
- if (differs(before.customProperties, nextCustomProps)) {
34157
- live.setCustomProperties(nextCustomProps);
34158
- }
34159
- if (differs(before.coreProperties, after.coreProperties)) {
34160
- live.setCoreProperties(after.coreProperties);
34161
- }
34162
- if (differs(before.appProperties, after.appProperties)) {
34163
- live.setAppProperties(after.appProperties);
34164
- }
34165
- if (differs(before.viewProperties, after.viewProperties)) {
34166
- live.setViewProperties(after.viewProperties);
34167
- }
34168
- if (differs(before.tableStyleMap, after.tableStyleMap)) {
34169
- live.setTableStyleMap(after.tableStyleMap);
34170
- }
34171
- if (differs(before.tableStylesDefaultId, after.tableStylesDefaultId)) {
34172
- live.setTableStylesDefaultId(after.tableStylesDefaultId);
34173
- }
34174
- const nextTags = after.tags ?? before.tags ?? [];
34175
- if (differs(before.tags, nextTags)) {
34176
- live.setTagCollections(nextTags);
34177
- }
34178
- 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);
34179
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(),
34180
32814
  getFocusedTargets() {
34181
- const live = ref.current;
34182
- if (live.pickedFocus && live.pickedFocus.length > 0) {
34183
- return live.pickedFocus;
34184
- }
34185
- if (live.pinnedFocus && live.pinnedFocus.length > 0) {
34186
- return live.pinnedFocus;
34187
- }
34188
- return computeFocusTargets({
34189
- activeSlideIndex: live.activeSlideIndex,
34190
- selectedElementIds: live.selectedElementIds,
34191
- selectedElementId: live.selectedElementId
34192
- });
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
+ );
34193
32824
  },
34194
- notify(message, level) {
34195
- ref.current.notify?.(message, level);
34196
- }
34197
- };
32825
+ notify: (message, level) => live().notify?.(message, level)
32826
+ });
34198
32827
  }, []);
34199
32828
  }
34200
- var TOOL_FLASH_MS = 2600;
34201
- function fixDirective(element, slideIndex) {
34202
- return `Review and fix any issues with this ${element.type} (id=${element.id}) on slide ${slideIndex + 1}.`;
34203
- }
34204
32829
  function useAiPanelController(input) {
34205
- const { activeSlideIndex, selectedElementId, selectedElementIds, selectedElement } = input;
34206
- const [isOpen, setIsOpen] = useState(false);
34207
- const [pinnedFocus, setPinnedFocus] = useState(null);
34208
- const [prefill, setPrefill] = useState({ text: "", nonce: 0 });
34209
- const [pickMode, setPickMode] = useState(false);
34210
- const [pickTargets, setPickTargets] = useState([]);
34211
- const [toolFocus, setToolFocus] = useState(
34212
- 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
+ })
34213
32842
  );
34214
- const [flashTick, setFlashTick] = useState(0);
34215
- const flashTimer = useRef(null);
34216
- const [changeBatch, setChangeBatch] = useState(null);
34217
- const showChangeBatch = useCallback((batch) => setChangeBatch(batch), []);
32843
+ const state = useController(controller);
32844
+ useEffect(() => () => controller.dispose(), [controller]);
34218
32845
  const liveFocusTargets = useMemo(
34219
32846
  () => computeFocusTargets({ activeSlideIndex, selectedElementIds, selectedElementId }),
34220
32847
  [activeSlideIndex, selectedElementIds, selectedElementId]
34221
32848
  );
34222
- const open = useCallback(() => setIsOpen(true), []);
34223
- const close = useCallback(() => setIsOpen(false), []);
34224
- const toggle = useCallback(() => setIsOpen((p) => !p), []);
34225
- const pinFocus = useCallback(() => setPinnedFocus(liveFocusTargets), [liveFocusTargets]);
34226
- const clearPinnedFocus = useCallback(() => setPinnedFocus(null), []);
34227
- const askAboutSelection = useCallback(() => {
34228
- setPinnedFocus(liveFocusTargets);
34229
- setPrefill((p) => ({ text: "", nonce: p.nonce + 1 }));
34230
- setIsOpen(true);
34231
- }, [liveFocusTargets]);
34232
- const fixSelection = useCallback(() => {
34233
- setPinnedFocus(liveFocusTargets);
34234
- const text = selectedElement ? fixDirective(selectedElement, activeSlideIndex) : "";
34235
- setPrefill((p) => ({ text, nonce: p.nonce + 1 }));
34236
- setIsOpen(true);
34237
- }, [liveFocusTargets, selectedElement, activeSlideIndex]);
34238
- const startPicking = useCallback(() => {
34239
- setPickMode(true);
34240
- setIsOpen(true);
34241
- }, []);
34242
- const stopPicking = useCallback(() => setPickMode(false), []);
34243
- const addPick = useCallback((slideIndex, elementId2) => {
34244
- setPickTargets((prev) => {
34245
- if (prev.some((t) => t.kind === "element" && t.elementId === elementId2)) {
34246
- return prev;
34247
- }
34248
- return [...prev, { kind: "element", slideIndex, elementId: elementId2 }];
34249
- });
34250
- }, []);
34251
- const clearPicks = useCallback(() => {
34252
- setPickTargets([]);
34253
- setPickMode(false);
34254
- }, []);
34255
- const flashToolTarget = useCallback((target) => {
34256
- if (target && target.slideIndex !== void 0 && target.elementIds.length > 0) {
34257
- setToolFocus({ slideIndex: target.slideIndex, elementIds: target.elementIds });
34258
- } else {
34259
- setToolFocus(null);
34260
- }
34261
- setFlashTick((n) => n + 1);
34262
- if (flashTimer.current) {
34263
- clearTimeout(flashTimer.current);
34264
- }
34265
- flashTimer.current = setTimeout(() => {
34266
- setToolFocus(null);
34267
- setFlashTick(0);
34268
- }, TOOL_FLASH_MS);
34269
- }, []);
34270
- useEffect(
34271
- () => () => {
34272
- if (flashTimer.current) {
34273
- clearTimeout(flashTimer.current);
34274
- }
34275
- },
34276
- []
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]
34277
32881
  );
34278
- const canvasHighlights = useMemo(() => {
34279
- const out = [];
34280
- for (const t of pickTargets) {
34281
- if (t.kind === "element") {
34282
- out.push({ slideIndex: t.slideIndex, elementId: t.elementId, variant: "pick" });
34283
- }
34284
- }
34285
- if (toolFocus) {
34286
- for (const elementId2 of toolFocus.elementIds) {
34287
- out.push({ slideIndex: toolFocus.slideIndex, elementId: elementId2, variant: "active" });
34288
- }
34289
- }
34290
- return out;
34291
- }, [pickTargets, toolFocus]);
34292
- const canvasAnimating = canvasHighlights.length > 0 || flashTick > 0;
34293
- return {
34294
- isOpen,
34295
- open,
34296
- close,
34297
- toggle,
34298
- liveFocusTargets,
34299
- pinnedFocus,
34300
- pinFocus,
34301
- clearPinnedFocus,
34302
- prefill,
34303
- askAboutSelection,
34304
- fixSelection,
34305
- pickMode,
34306
- startPicking,
34307
- stopPicking,
34308
- pickTargets,
34309
- addPick,
34310
- clearPicks,
34311
- canvasHighlights,
34312
- canvasAnimating,
34313
- flashToolTarget,
34314
- changeBatch,
34315
- showChangeBatch
34316
- };
34317
32882
  }
34318
32883
  function useCollaborationStateReport(collab, onChange) {
34319
32884
  const callback = useRef(onChange);