pptx-react-viewer 4.18.0 → 4.19.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 (135) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/{AiChatPanel-4RAGQKFE.js → AiChatPanel-6ABOTMI4.js} +28 -28
  3. package/dist/AiChatPanel-6ABOTMI4.js.br +0 -0
  4. package/dist/AiChatPanel-6ABOTMI4.js.gz +0 -0
  5. package/dist/{AiChatPanel-BIS3OYZ2.mjs → AiChatPanel-QEOFQGNY.mjs} +4 -4
  6. package/dist/AiChatPanel-QEOFQGNY.mjs.br +0 -0
  7. package/dist/AiChatPanel-QEOFQGNY.mjs.gz +0 -0
  8. package/dist/{Model3DScene-ZVXXKGMO.mjs → Model3DScene-CKBO4RI2.mjs} +1 -1
  9. package/dist/{Model3DScene-ZVXXKGMO.mjs.br → Model3DScene-CKBO4RI2.mjs.br} +0 -0
  10. package/dist/Model3DScene-CKBO4RI2.mjs.gz +0 -0
  11. package/dist/{Model3DScene-KJBH5LFE.js → Model3DScene-ESGCOB2O.js} +2 -2
  12. package/dist/Model3DScene-ESGCOB2O.js.br +0 -0
  13. package/dist/Model3DScene-ESGCOB2O.js.gz +0 -0
  14. package/dist/{chunk-XZQNOZA6.js → chunk-E3TLDJPS.js} +4666 -2413
  15. package/dist/chunk-E3TLDJPS.js.br +0 -0
  16. package/dist/chunk-E3TLDJPS.js.gz +0 -0
  17. package/dist/{chunk-SJJ4AOLI.js → chunk-FNO4C3LU.js} +831 -831
  18. package/dist/chunk-FNO4C3LU.js.br +0 -0
  19. package/dist/chunk-FNO4C3LU.js.gz +0 -0
  20. package/dist/{chunk-UWRUG37I.js → chunk-H7FXW2Q3.js} +5 -5
  21. package/dist/chunk-H7FXW2Q3.js.br +0 -0
  22. package/dist/chunk-H7FXW2Q3.js.gz +0 -0
  23. package/dist/{chunk-X5O53JPT.mjs → chunk-LE3JUNIR.mjs} +2 -2
  24. package/dist/chunk-LE3JUNIR.mjs.br +0 -0
  25. package/dist/chunk-LE3JUNIR.mjs.gz +0 -0
  26. package/dist/{chunk-2GRLCBMP.js → chunk-LKL6DQ55.js} +24 -4
  27. package/dist/chunk-LKL6DQ55.js.br +0 -0
  28. package/dist/chunk-LKL6DQ55.js.gz +0 -0
  29. package/dist/{chunk-SJJY4B4V.mjs → chunk-OCUCBRXU.mjs} +4 -4
  30. package/dist/chunk-OCUCBRXU.mjs.br +0 -0
  31. package/dist/chunk-OCUCBRXU.mjs.gz +0 -0
  32. package/dist/{chunk-IDZ7S2O3.mjs → chunk-Q4HRYUEP.mjs} +24 -4
  33. package/dist/chunk-Q4HRYUEP.mjs.br +0 -0
  34. package/dist/chunk-Q4HRYUEP.mjs.gz +0 -0
  35. package/dist/{chunk-CJ3GYPF6.js → chunk-QSBL4SL6.js} +2829 -3781
  36. package/dist/chunk-QSBL4SL6.js.br +0 -0
  37. package/dist/chunk-QSBL4SL6.js.gz +0 -0
  38. package/dist/{chunk-5OYCO5WW.mjs → chunk-VX52VUBD.mjs} +1 -1
  39. package/dist/chunk-VX52VUBD.mjs.br +0 -0
  40. package/dist/chunk-VX52VUBD.mjs.gz +0 -0
  41. package/dist/{chunk-7T64DQTQ.js → chunk-WAUDRNBY.js} +197 -197
  42. package/dist/chunk-WAUDRNBY.js.br +0 -0
  43. package/dist/chunk-WAUDRNBY.js.gz +0 -0
  44. package/dist/{chunk-NWWE7I6R.mjs → chunk-YL7IPY2B.mjs} +985 -1937
  45. package/dist/chunk-YL7IPY2B.mjs.br +0 -0
  46. package/dist/chunk-YL7IPY2B.mjs.gz +0 -0
  47. package/dist/{chunk-EDQ436NK.mjs → chunk-YYVPC6KI.mjs} +4660 -2401
  48. package/dist/chunk-YYVPC6KI.mjs.br +0 -0
  49. package/dist/chunk-YYVPC6KI.mjs.gz +0 -0
  50. package/dist/i18n/de.cjs +20 -0
  51. package/dist/i18n/de.cjs.br +0 -0
  52. package/dist/i18n/de.cjs.gz +0 -0
  53. package/dist/i18n/de.mjs +20 -0
  54. package/dist/i18n/de.mjs.br +0 -0
  55. package/dist/i18n/de.mjs.gz +0 -0
  56. package/dist/i18n/es.cjs +20 -0
  57. package/dist/i18n/es.cjs.br +0 -0
  58. package/dist/i18n/es.cjs.gz +0 -0
  59. package/dist/i18n/es.mjs +20 -0
  60. package/dist/i18n/es.mjs.br +0 -0
  61. package/dist/i18n/es.mjs.gz +0 -0
  62. package/dist/i18n/fr.cjs +20 -0
  63. package/dist/i18n/fr.cjs.br +0 -0
  64. package/dist/i18n/fr.cjs.gz +0 -0
  65. package/dist/i18n/fr.mjs +20 -0
  66. package/dist/i18n/fr.mjs.br +0 -0
  67. package/dist/i18n/fr.mjs.gz +0 -0
  68. package/dist/i18n/zh-CN.cjs +20 -0
  69. package/dist/i18n/zh-CN.cjs.br +0 -0
  70. package/dist/i18n/zh-CN.cjs.gz +0 -0
  71. package/dist/i18n/zh-CN.mjs +20 -0
  72. package/dist/i18n/zh-CN.mjs.br +0 -0
  73. package/dist/i18n/zh-CN.mjs.gz +0 -0
  74. package/dist/i18n.js +4 -4
  75. package/dist/i18n.js.br +0 -0
  76. package/dist/i18n.js.gz +0 -0
  77. package/dist/i18n.mjs +1 -1
  78. package/dist/i18n.mjs.br +0 -0
  79. package/dist/i18n.mjs.gz +0 -0
  80. package/dist/index.d.ts +153 -5
  81. package/dist/index.js +63 -63
  82. package/dist/index.js.br +0 -0
  83. package/dist/index.js.gz +0 -0
  84. package/dist/index.mjs +6 -6
  85. package/dist/index.mjs.br +0 -0
  86. package/dist/index.mjs.gz +0 -0
  87. package/dist/internals.d.ts +153 -5
  88. package/dist/internals.js +105 -105
  89. package/dist/internals.js.br +0 -0
  90. package/dist/internals.js.gz +0 -0
  91. package/dist/internals.mjs +4 -4
  92. package/dist/internals.mjs.br +0 -0
  93. package/dist/internals.mjs.gz +0 -0
  94. package/dist/pptx-viewer.css +1 -1
  95. package/dist/pptx-viewer.css.br +0 -0
  96. package/dist/pptx-viewer.css.gz +0 -0
  97. package/dist/viewer/index.d.ts +153 -5
  98. package/dist/viewer/index.js +27 -27
  99. package/dist/viewer/index.js.br +0 -0
  100. package/dist/viewer/index.js.gz +0 -0
  101. package/dist/viewer/index.mjs +6 -6
  102. package/dist/viewer/index.mjs.br +1 -1
  103. package/dist/viewer/index.mjs.gz +0 -0
  104. package/package.json +1 -1
  105. package/dist/AiChatPanel-4RAGQKFE.js.br +0 -0
  106. package/dist/AiChatPanel-4RAGQKFE.js.gz +0 -0
  107. package/dist/AiChatPanel-BIS3OYZ2.mjs.br +0 -0
  108. package/dist/AiChatPanel-BIS3OYZ2.mjs.gz +0 -0
  109. package/dist/Model3DScene-KJBH5LFE.js.br +0 -0
  110. package/dist/Model3DScene-KJBH5LFE.js.gz +0 -0
  111. package/dist/Model3DScene-ZVXXKGMO.mjs.gz +0 -0
  112. package/dist/chunk-2GRLCBMP.js.br +0 -0
  113. package/dist/chunk-2GRLCBMP.js.gz +0 -0
  114. package/dist/chunk-5OYCO5WW.mjs.br +0 -0
  115. package/dist/chunk-5OYCO5WW.mjs.gz +0 -0
  116. package/dist/chunk-7T64DQTQ.js.br +0 -0
  117. package/dist/chunk-7T64DQTQ.js.gz +0 -0
  118. package/dist/chunk-CJ3GYPF6.js.br +0 -0
  119. package/dist/chunk-CJ3GYPF6.js.gz +0 -0
  120. package/dist/chunk-EDQ436NK.mjs.br +0 -0
  121. package/dist/chunk-EDQ436NK.mjs.gz +0 -0
  122. package/dist/chunk-IDZ7S2O3.mjs.br +0 -0
  123. package/dist/chunk-IDZ7S2O3.mjs.gz +0 -0
  124. package/dist/chunk-NWWE7I6R.mjs.br +0 -0
  125. package/dist/chunk-NWWE7I6R.mjs.gz +0 -0
  126. package/dist/chunk-SJJ4AOLI.js.br +0 -0
  127. package/dist/chunk-SJJ4AOLI.js.gz +0 -0
  128. package/dist/chunk-SJJY4B4V.mjs.br +0 -0
  129. package/dist/chunk-SJJY4B4V.mjs.gz +0 -0
  130. package/dist/chunk-UWRUG37I.js.br +0 -0
  131. package/dist/chunk-UWRUG37I.js.gz +0 -0
  132. package/dist/chunk-X5O53JPT.mjs.br +0 -0
  133. package/dist/chunk-X5O53JPT.mjs.gz +0 -0
  134. package/dist/chunk-XZQNOZA6.js.br +0 -0
  135. package/dist/chunk-XZQNOZA6.js.gz +0 -0
@@ -1,12 +1,12 @@
1
- import { computeFocusTargets, deckDataFieldChanged, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs, applyElementUpdate } from './chunk-5OYCO5WW.mjs';
2
- import { useViewerOptions, useReadOnlyRecommendationState, useCompatibilityToastsState, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useViewPreferencesSync, useLayoutSwitching, Rendering3DFlagsContext, CollaborationProvider, useCollaboration, useCollaborationDocumentSync, useFollowMode, useBroadcastFollower, SlideBackgroundImageLayer, StaticElementRenderer, safePrompt, scopeLayoutOptionsToActiveSlide, ChartPartSelectionProvider, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, ViewerOptionsStoreContext, ViewerOptionsContext, useViewerOptionsContext, useVirtualizedSlides, useSwipeNavigation, PresentationTransitionOverlay, RemoteSelectionOverlay, CollaborationCursorOverlay, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, ElementRenderer, InlineCollaborationContext, SmartArtRenderer, playAnimationSound, ResizeHandles, imgSrc, renderStrokeView, useChartPartSelection, resolveSmartArtDataPalette } from './chunk-SJJY4B4V.mjs';
3
- import { SHAPE_PRESETS, ANIMATION_PRESET_OPTIONS, cn, SLIDE_NAV_THUMBNAIL_WIDTH, DEFAULT_SECTION_GROUP_ID, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, TOOLBAR_SECTIONS, UNGROUPED_SECTION_ID, isConnectorOrLineElement, GRID_SIZE, MIN_ELEMENT_SIZE, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, DEFAULT_FILL_COLOR, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, DEFAULT_STROKE_COLOR, STROKE_DASH_OPTIONS } from './chunk-X5O53JPT.mjs';
4
- import { EMPTY_RESOLVED_CUSTOMIZATION, FIXED_TAB_GALLERIES, editingHomeControls, ANIMATION_DIRECTION_LABEL_KEYS, SWITCHABLE_LAYOUT_TYPES, compileEquationTemplateMathMl, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, isFeatureEnabled, isDialogAvailable, resolveAutosaveActivation, buildThemeColorMap, viewerOptionsToPreferences, applyPreferenceToOptions, resolveHistoryDepth, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, isPanelVisible, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, RIBBON_SCOPE_ATTR, resolve3DRenderingFlags, resolveSlideSizeSelection, RULER_THICKNESS, RULER_FONT_SIZE, editorThumbnailHeight, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, hiddenSlideCue, EDITOR_THUMBNAIL_WIDTH, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, visibleTemplateElements, normalizeHexColor, themeToCssVars, createCustomizationController, resolveEffectiveHiddenActions, listAutosaveSnapshots, resolveExpiredAutosaveSnapshots, deleteAutosaveSnapshot, masterViewCrudActions, applyMasterViewCrudAction, masterViewCrudFailureKey, EDITOR_CHROME_CSS, ribbonCustomizationCss, applyMotionPathPreset, resetSlideLayoutPath, DEFAULT_INSERT_CHART_KIND, hasCopyableFormat, templateSchemeFromTheme, createBackstagePresentation, playFeedbackSound, shouldDiscardAutosaveOnSuccessfulSave, setMasterViewBackgroundColor, canUseClipboard, runProgramNoticeStackStyle, printPropertiesFrameSlides, printPropertiesSlidesPerPage, PASTE_SPECIAL_OPTIONS, findCanvasElementNode, getDensePanelTouchTargetPx, shouldStickyActionRow, customizeOptionsTabs, VIEWER_OPTIONS_TABS, isOptionsPageVisible, DEFAULT_QUICK_ACCESS_COMMAND_IDS, isHeaderFooterDateTextVisible, isHeaderFooterHeaderTextVisible, isHeaderFooterFooterTextVisible, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, getSlideBackgroundStyle, pushRecentColor, mruColorsPatch, shouldClearAutosaveCacheOnClose, canCropElement, cropSessionChanged, cancelCropUpdate, startCropSession, editorThumbnailWidth, masterViewBackgroundColor, buildFieldSubstitutionContext, shouldConfirmExternalHyperlink, safeOpenUrl, resolvePresentationAction, isPpactionUrl, parsePpactionUrl, isPresentationAdvanceClick, toggleBlackboard, PRESENT_TOOLBAR_CLASSES, resolveEditPointsAvailability, isCurrentLayout, themeColorSchemesEqual, observeElementHeight, EXPANDED_MAX_HEIGHT, resolveStatusBarSave, statusBarViewMode, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, clampPercent2, resolveDefaultPrintSettings, HANDOUT_OPTIONS, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS, resolveViewerAddinRows, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, CUSTOM_FONT_ACCEPT, activateModalFocus, buildCollaborationShareUrl, buildActiveSessionUsers, SORTER_MIN_ZOOM, SORTER_ZOOM_STEP, SORTER_MAX_ZOOM, canGoPrevious, formatSlideCounter, READING_VIEW_COUNTER_ATTR, canGoNext, READING_VIEW_ATTR, OUTLINE_LEVEL_ATTR, OUTLINE_SLIDE_ATTR, OUTLINE_ROW_ATTR, OUTLINE_VIEW_ATTR, mobileElapsedSince, nextPresentedSlide, presenterPrevDisabled, presenterNextDisabled, formatMobileElapsed, mobileSlideCounter, presenterPaneAdvancesOnClick, presenterTimerProgress, PRESENTER_CONSOLE_CLASSES, formatElapsed, cropModeKeyAction, buildTitleBarState, resolveScreenTip, visibleContextualTabs, resolveActiveRibbonTab, contextualTabLabelKey, RIBBON_CONTEXTUAL_TAB_ATTR, TAB_ROW_ACTION_CLASSES, customizeBackstageNav, BACKSTAGE_NAV, listBackstageRecentFiles, BACKSTAGE_BACK_CLASSES, BACKSTAGE_NAV_CLASSES, hasTextProperties, textFontSizePtToPx, FREEFORM_TOOL_IDS, isDrawingToolVisible, hasShapeProperties, drawingHomeControls, shapeFillChange, shapeOutlineChange, arrangeHomeControls, arrangeAlignAction, DESIGN_RIBBON_GROUPS, DESIGN_RIBBON_COMMANDS, designCommandState, CONTEXTUAL_TAB_GROUPS, editorThumbnailStep, resolveSlidePaneClick, SLIDE_VIRTUALIZATION_THRESHOLD, buildSectionContextMenuEntries, buildSlidePaneContextMenuEntries, slidePaneViewItems, isEditPointsEnabled, PRESENTATION_HIT_TEST_CSS, PRESENTATION_STAGE_ATTRIBUTE, buildStrokePathD, cursorForTool, annotationOverlayZIndex, presentationInkPath, resolveNotesSchematicBodyFontSizePx, PRESENTER_NAVIGATOR_LABEL_KEYS, getPresentationContextMenuSections, CONTEXT_MENU_PRESENTATION_LAYER, presentationViewItems, subtitleRecognitionLanguage, subtitleSettingsFromOptions, 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, isUrlSafe, buildNotesPrintHtml, MIN_TOUCH_TARGET_PX, toggleSheet, SMARTART_PREVIEW_ELEMENT_HEIGHT, SMARTART_PREVIEW_ELEMENT_WIDTH, buildSmartArtPreviewElement, sanitizeMathMl, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, downloadBlob, clampOptionNumber, QUICK_ACCESS_COMMAND_CATALOG, registerCustomFont, 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, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, customizeBackstageCards, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, resolveDefaultFontFamily, textFontSizePxToPt, clipboardHomeControls, slidesHomeControls, buildFontCatalog, COMMON_FONT_SIZES, getInlineEditorSelectionResult, selectedParagraphBulletKind, elementBulletKind, selectionBulletKind, fontHomeControls, nextToggleValue, CHARACTER_SPACING_OPTIONS, OFFICE_COLOR_SWATCHES, RIBBON_GROUP_ATTR, paragraphHomeAlign, paragraphHomeControls, paragraphHomeAction, RIBBON_CONTROL_ATTR, RIBBON_SHAPE_SWATCHES, buildRibbonGallery, canGroupSelection, canUngroupSelection, canSetStrokeWidth, strokeWidthOf, readRibbonTransitionDraft, SLIDE_SHOW_COMMAND_GROUPS, RECORD_COMMAND_GROUPS, buildReviewRibbon, HELP_RIBBON_COMMANDS, galleryTextLabel, sectionAddAfterSlideIndex, masterViewPseudoSlide, PRESENTATION_ANIM_TRIGGER_ATTRIBUTE, parentSelection, slideSpaceElement, isGroupMember, motionPathFor, setMotionPath, getShapeAdjustmentHandleDescriptors, shouldShowElementHandles, computeAnchoredPopupPosition, applyTableStyleDelete, applyTableStyleMapChange, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, SLIDE_TEMPLATES, getSelectionTextStyleFlags, TEXT_DECORATION_FLAGS, buildThemeColorSwatchGrid, themeColorSwatchRows, findSelectedThemeSwatch, themeSwatchCommit, applyRibbonGalleryItem, MERGE_SHAPES_LABEL_KEY, MERGE_SHAPES_HINT_KEY, MERGE_SHAPES_MENU_ITEMS, CROP_LABEL_KEY, CROP_ASPECT_LABEL_KEY, CROP_ASPECT_GROUP_LABEL_KEYS, CROP_ASPECT_PRESETS, CROP_FILL_LABEL_KEY, CROP_FIT_LABEL_KEY, ribbonTransitionsDraftPatch, ribbonTransitionUpdates, ribbonTransitionsSoundChange, ribbonTransitionStockSoundUrl, playSlideTransitionPreview, playAnimationRibbonPreview, SLIDE_SHOW_OPTIONS, createViewerOptionsStore, subtitleSettingsLabels, attachEditorImagePaste, authorConnectorBetweenSites, findEraserHitElementId, generateTicks, rulerDragToGuidePosition, resolveElementInteractivity, getElementTransformWithoutRotation, getElementTransform, 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, hasMultipleSelectedTableCells, isElementLocked, isImageLikeElement, mergeSlideTransition, slideBackgroundClearState, slideBackgroundClearPatch, getElementLabel, effectiveDirection, TRIGGER_OPTIONS, effectiveTimingCurve, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, buildSlideTemplateContent, updateSubtitleSettings, buildFreeformShapeElement, buildLiveInkStrokeView, beginCropDrag, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, FreeformToolSession, attachOverlayKeyboard, EditPointsSession, EDIT_POINTS_STYLE, elementLockTogglePatch, buildTableDataGrid, getDenseGridLayoutPlan, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, applyTableStylePreset, tableStyleAssignmentUpdate, evenColumnWidths, redistributeColumnWidth, evenRowHeights, patchChartData, collapseChartTitleRunsForEdit, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setDataLabelsRangeCache, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, imageResetPatch, imageResetState, canInteractWithElement, buildOleObjectNamePatch, getOleObjectTypeLabel, sanitizeGradientStops, shouldShowAccessibilitySection, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, THEME_COLOR_SCHEME_KEYS, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, SLIDE_SIZE_PRESETS, TRANSITION_VALID_DIRECTIONS, TRANSITION_ORIENTATION_TYPES, TRANSITION_PATTERN_OPTIONS, TRANSITION_THRUBLK_TYPES, clampTransitionNumber, TRANSITION_SPEED_OPTIONS, TRANSITION_MORPH_OPTIONS, flattenTagCollections, resolveTemplateBackgroundRows, formatCommentTimestamp, 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, hasTiltData, toElementAxes, dragCropHandle, panCropImage, clientToSlidePoint, EDIT_POINTS_TARGET_ATTR, normalizeTableStyleGuid, describeTableStyleEditor, TABLE_STYLE_EDITOR_PARTS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, updateMergeAttrsInRawXml, 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, addSmartArtNodeAsChild, setSmartArtNodeStyle, removeSmartArtNode, addSiblingAfter, removeEmptyNode, demote, promote, updateSmartArtNodeText, reorder, cropResetState, clampCropValue, cropResetPatch, DUOTONE_PRESETS, ARTISTIC_EFFECTS, mediaTrimEndSeconds, trimmedMediaDurationMs, mediaTrimEndAbsoluteMs, mediaTrimResetState, mediaTrimEndMsFromAbsoluteMs, mediaTrimResetPatch, buildOleEditDialogDescriptor, buildOleContentUpdatePatch, applyOleSheetCellEdit, getOleSheetGrid, applyOleDocumentParagraphEdit, getOleDocumentParagraphs, applyOleNestedDeckElementTextEdit, getOleNestedDeckDetail, replaceOleFile, getNonVisualDescriptionFields, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, elementActionToPptxAction, canCommitActionType, slideSizeFromPreset, withSlideSizeOrientation, TRANSITION_DIR_ARROWS, buildDirectionGrid, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES, updateTagInCollections, deleteTagFromCollections, addTagToCollections, commentTextSegments, COMMENT_MENTION_CLASS, COMMENT_MENTION_ATTRIBUTE, insertCommentMention, reorderAnimationTimelineRows, applyAnimationTimelineOrder, getEffectSoundAsset, animationEffectLabel, overlayPointerInput, TABLE_STYLE_BORDER_SIDES, applyTableStyleFieldEdit, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, getChartUserShapeGroupTransform, withChartUserShapeGroupChildAdded, createDefaultChartUserShapeGroupChild, withChartUserShapeRowUpdated, getChartUserShapeRowChartBox, withChartUserShapeRowFlipUpdated, withChartUserShapeRowRotationUpdated, withChartUserShapeRowChartBoxUpdated, switchSmartArtLayout, rebuildDrawingShapesIfCleared, mediaTrimEndMsFromSeconds, validateMediaTrimRange, SHAPE_QUICK_STYLES, quickStyleSwatchCss, PATTERN_PRESET_OPTIONS, getPatternSvg, COMPOUND_LINE_OPTIONS, LINE_JOIN_OPTIONS, LINE_CAP_OPTIONS, TEXT_WARP_PRESETS, warpPreviewPath, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, toSlideIndex, TABLE_STYLE_BORDER_SIDE_LABEL_KEYS, TABLE_STYLE_DASH_PRESETS, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS, cropFit, cropFill, cropToAspectRatio } from './chunk-EDQ436NK.mjs';
5
- import { LOCALE_CATALOG } from './chunk-IDZ7S2O3.mjs';
6
- import React99, { createContext, lazy, forwardRef, useEffect, useState, useCallback, useMemo, useRef, useLayoutEffect, useSyncExternalStore, useId, useContext, useDeferredValue, Suspense, useReducer, Fragment as Fragment$1 } from 'react';
1
+ import { computeFocusTargets, deckDataFieldChanged, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, collectStoredChats, exportAiChatLogs, applyElementUpdate } from './chunk-VX52VUBD.mjs';
2
+ import { useViewerOptions, useReadOnlyRecommendationState, useCompatibilityToastsState, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useViewPreferencesSync, useLayoutSwitching, Rendering3DFlagsContext, CollaborationProvider, useCollaboration, useCollaborationDocumentSync, useFollowMode, useBroadcastFollower, SlideBackgroundImageLayer, StaticElementRenderer, safePrompt, scopeLayoutOptionsToActiveSlide, ChartPartSelectionProvider, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, ViewerOptionsStoreContext, ViewerOptionsContext, useViewerOptionsContext, useVirtualizedSlides, useSwipeNavigation, PresentationTransitionOverlay, RemoteSelectionOverlay, CollaborationCursorOverlay, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, ElementRenderer, InlineCollaborationContext, SmartArtRenderer, playAnimationSound, ResizeHandles, imgSrc, renderStrokeView, useChartPartSelection, resolveSmartArtDataPalette } from './chunk-OCUCBRXU.mjs';
3
+ import { ANIMATION_PRESET_OPTIONS, cn, SLIDE_NAV_THUMBNAIL_WIDTH, DEFAULT_SECTION_GROUP_ID, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, TOOLBAR_SECTIONS, UNGROUPED_SECTION_ID, isConnectorOrLineElement, GRID_SIZE, MIN_ELEMENT_SIZE, SHAPE_PRESETS, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, DEFAULT_FILL_COLOR, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, DEFAULT_STROKE_COLOR, STROKE_DASH_OPTIONS } from './chunk-LE3JUNIR.mjs';
4
+ import { EMPTY_RESOLVED_CUSTOMIZATION, ANIMATION_DIRECTION_LABEL_KEYS, SWITCHABLE_LAYOUT_TYPES, compileEquationTemplateMathMl, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, isFeatureEnabled, isDialogAvailable, resolveAutosaveActivation, buildThemeColorMap, viewerOptionsToPreferences, applyPreferenceToOptions, resolveHistoryDepth, applyAutoCorrect, resolveImageResolutionScale, resolveAutosaveIntervalMs, resolveAutosaveIntervalSeconds, isPanelVisible, shouldShowAutosaveRecoveryPrompt, resolveOptionRootClasses, RIBBON_SCOPE_ATTR, resolve3DRenderingFlags, resolveSlideSizeSelection, RULER_THICKNESS, RULER_FONT_SIZE, editorThumbnailHeight, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, hiddenSlideCue, EDITOR_THUMBNAIL_WIDTH, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, visibleTemplateElements, normalizeHexColor, themeToCssVars, createCustomizationController, resolveEffectiveHiddenActions, listAutosaveSnapshots, resolveExpiredAutosaveSnapshots, deleteAutosaveSnapshot, masterViewCrudActions, applyMasterViewCrudAction, masterViewCrudFailureKey, EDITOR_CHROME_CSS, ribbonCustomizationCss, applyMotionPathPreset, resetSlideLayoutPath, DEFAULT_INSERT_CHART_KIND, hasCopyableFormat, templateSchemeFromTheme, createBackstagePresentation, playFeedbackSound, shouldDiscardAutosaveOnSuccessfulSave, setMasterViewBackgroundColor, canUseClipboard, runProgramNoticeStackStyle, printPropertiesFrameSlides, printPropertiesSlidesPerPage, PASTE_SPECIAL_OPTIONS, findCanvasElementNode, getDensePanelTouchTargetPx, shouldStickyActionRow, customizeOptionsTabs, VIEWER_OPTIONS_TABS, isOptionsPageVisible, DEFAULT_QUICK_ACCESS_COMMAND_IDS, isHeaderFooterDateTextVisible, isHeaderFooterHeaderTextVisible, isHeaderFooterFooterTextVisible, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, getSlideBackgroundStyle, pushRecentColor, mruColorsPatch, shouldClearAutosaveCacheOnClose, canCropElement, cropSessionChanged, cancelCropUpdate, startCropSession, editorThumbnailWidth, masterViewBackgroundColor, buildFieldSubstitutionContext, shouldConfirmExternalHyperlink, safeOpenUrl, resolvePresentationAction, isPpactionUrl, parsePpactionUrl, isPresentationAdvanceClick, toggleBlackboard, PRESENT_TOOLBAR_CLASSES, resolveEditPointsAvailability, isCurrentLayout, themeColorSchemesEqual, observeElementHeight, EXPANDED_MAX_HEIGHT, resolveStatusBarSave, statusBarViewMode, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, clampPercent2, resolveDefaultPrintSettings, HANDOUT_OPTIONS, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS, resolveViewerAddinRows, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, CUSTOM_FONT_ACCEPT, activateModalFocus, buildCollaborationShareUrl, buildActiveSessionUsers, SORTER_MIN_ZOOM, SORTER_ZOOM_STEP, SORTER_MAX_ZOOM, canGoPrevious, formatSlideCounter, READING_VIEW_COUNTER_ATTR, canGoNext, READING_VIEW_ATTR, OUTLINE_LEVEL_ATTR, OUTLINE_SLIDE_ATTR, OUTLINE_ROW_ATTR, OUTLINE_VIEW_ATTR, mobileElapsedSince, nextPresentedSlide, presenterPrevDisabled, presenterNextDisabled, formatMobileElapsed, mobileSlideCounter, presenterPaneAdvancesOnClick, presenterTimerProgress, PRESENTER_CONSOLE_CLASSES, formatElapsed, cropModeKeyAction, buildTitleBarState, resolveScreenTip, visibleContextualTabs, resolveActiveRibbonTab, contextualTabLabelKey, RIBBON_CONTEXTUAL_TAB_ATTR, TAB_ROW_ACTION_CLASSES, customizeBackstageNav, BACKSTAGE_NAV, listBackstageRecentFiles, BACKSTAGE_BACK_CLASSES, BACKSTAGE_NAV_CLASSES, hasTextProperties, textFontSizePtToPx, FREEFORM_TOOL_IDS, isDrawingToolVisible, editingHomeControls, hasShapeProperties, withHomeGalleries, drawingHomeControls, homeGalleryControls, homeGalleryApply, shapeOutlineChange, shapeFillChange, arrangeHomeControls, arrangePainterHomeControls, arrangeAlignAction, DESIGN_RIBBON_GROUPS, DESIGN_RIBBON_COMMANDS, designCommandState, FIXED_TAB_GALLERIES, CONTEXTUAL_TAB_GROUPS, editorThumbnailStep, resolveSlidePaneClick, SLIDE_VIRTUALIZATION_THRESHOLD, buildSectionContextMenuEntries, buildSlidePaneContextMenuEntries, slidePaneViewItems, isEditPointsEnabled, PRESENTATION_HIT_TEST_CSS, PRESENTATION_STAGE_ATTRIBUTE, buildStrokePathD, cursorForTool, annotationOverlayZIndex, presentationInkPath, resolveNotesSchematicBodyFontSizePx, PRESENTER_NAVIGATOR_LABEL_KEYS, getPresentationContextMenuSections, CONTEXT_MENU_PRESENTATION_LAYER, presentationViewItems, subtitleRecognitionLanguage, subtitleSettingsFromOptions, 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, isUrlSafe, buildNotesPrintHtml, MIN_TOUCH_TARGET_PX, toggleSheet, SMARTART_PREVIEW_ELEMENT_HEIGHT, SMARTART_PREVIEW_ELEMENT_WIDTH, buildSmartArtPreviewElement, sanitizeMathMl, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, downloadBlob, clampOptionNumber, QUICK_ACCESS_COMMAND_CATALOG, registerCustomFont, 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, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, customizeBackstageCards, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, resolveDefaultFontFamily, textFontSizePxToPt, clipboardHomeControls, slidesHomeControls, fontPickerHomeControls, getInlineEditorSelectionResult, selectedParagraphBulletKind, elementBulletKind, selectionBulletKind, fontHomeControls, nextToggleValue, RIBBON_GROUP_ATTR, paragraphHomeAlign, paragraphHomeControls, paragraphHomeAction, arrangeShapeHomeControls, strokeWidthOf, canSetStrokeWidth, canUngroupSelection, canGroupSelection, parseCropValue, buildRibbonGallery, readRibbonTransitionDraft, SLIDE_SHOW_COMMAND_GROUPS, RECORD_COMMAND_GROUPS, buildReviewRibbon, HELP_RIBBON_COMMANDS, galleryTextLabel, sectionAddAfterSlideIndex, masterViewPseudoSlide, PRESENTATION_ANIM_TRIGGER_ATTRIBUTE, parentSelection, slideSpaceElement, isGroupMember, motionPathFor, setMotionPath, getShapeAdjustmentHandleDescriptors, shouldShowElementHandles, computeAnchoredPopupPosition, applyTableStyleDelete, applyTableStyleMapChange, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, SLIDE_TEMPLATES, getSelectionTextStyleFlags, TEXT_DECORATION_FLAGS, applyRibbonGalleryItem, ribbonTransitionsDraftPatch, ribbonTransitionUpdates, ribbonTransitionsSoundChange, ribbonTransitionStockSoundUrl, playSlideTransitionPreview, playAnimationRibbonPreview, SLIDE_SHOW_OPTIONS, createViewerOptionsStore, subtitleSettingsLabels, attachEditorImagePaste, authorConnectorBetweenSites, findEraserHitElementId, generateTicks, rulerDragToGuidePosition, resolveElementInteractivity, getElementTransformWithoutRotation, getElementTransform, 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, MERGE_SHAPES_MENU_ITEMS, hasMultipleSelectedTableCells, isElementLocked, isImageLikeElement, mergeSlideTransition, slideBackgroundClearState, slideBackgroundClearPatch, getElementLabel, effectiveDirection, TRIGGER_OPTIONS, effectiveTimingCurve, mapSlideSorterKey, isEditorTextInputTarget, clampSorterZoom, buildSlideTemplateContent, updateSubtitleSettings, buildFreeformShapeElement, buildLiveInkStrokeView, beginCropDrag, CONNECTOR_SITE_SNAP_PX, resolveConnectorEndpointUpdate, withConnectorEndpointUpdate, getShapeConnectionSites, FreeformToolSession, attachOverlayKeyboard, EditPointsSession, EDIT_POINTS_STYLE, elementLockTogglePatch, buildTableDataGrid, getDenseGridLayoutPlan, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, applyTableStylePreset, tableStyleAssignmentUpdate, evenColumnWidths, redistributeColumnWidth, evenRowHeights, patchChartData, collapseChartTitleRunsForEdit, chartGridlinesState, chartGridlinesPatch, seriesSecondaryAxisPatch, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setDataLabelsRangeCache, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, describeSmartArtBounds, canAddTopLevelNode, classifyExtraConnections, siblingIndex, siblingCount, canRemoveTopLevelNode, imageResetPatch, imageResetState, canInteractWithElement, buildOleObjectNamePatch, getOleObjectTypeLabel, sanitizeGradientStops, shouldShowAccessibilitySection, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, THEME_COLOR_SCHEME_KEYS, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, SLIDE_SIZE_PRESETS, TRANSITION_VALID_DIRECTIONS, TRANSITION_ORIENTATION_TYPES, TRANSITION_PATTERN_OPTIONS, TRANSITION_THRUBLK_TYPES, clampTransitionNumber, TRANSITION_SPEED_OPTIONS, TRANSITION_MORPH_OPTIONS, flattenTagCollections, resolveTemplateBackgroundRows, formatCommentTimestamp, 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, hasTiltData, toElementAxes, dragCropHandle, panCropImage, clientToSlidePoint, EDIT_POINTS_TARGET_ATTR, normalizeTableStyleGuid, describeTableStyleEditor, TABLE_STYLE_EDITOR_PARTS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, updateMergeAttrsInRawXml, 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, addSmartArtNodeAsChild, setSmartArtNodeStyle, removeSmartArtNode, addSiblingAfter, removeEmptyNode, demote, promote, updateSmartArtNodeText, reorder, cropResetState, clampCropValue, cropResetPatch, DUOTONE_PRESETS, ARTISTIC_EFFECTS, mediaTrimEndSeconds, trimmedMediaDurationMs, mediaTrimEndAbsoluteMs, mediaTrimResetState, mediaTrimEndMsFromAbsoluteMs, mediaTrimResetPatch, buildOleEditDialogDescriptor, buildOleContentUpdatePatch, applyOleSheetCellEdit, getOleSheetGrid, applyOleDocumentParagraphEdit, getOleDocumentParagraphs, applyOleNestedDeckElementTextEdit, getOleNestedDeckDetail, replaceOleFile, buildThemeColorSwatchGrid, themeColorSwatchRows, findSelectedThemeSwatch, themeSwatchCommit, getNonVisualDescriptionFields, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, elementActionToPptxAction, canCommitActionType, slideSizeFromPreset, withSlideSizeOrientation, TRANSITION_DIR_ARROWS, buildDirectionGrid, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES, updateTagInCollections, deleteTagFromCollections, addTagToCollections, commentTextSegments, COMMENT_MENTION_CLASS, COMMENT_MENTION_ATTRIBUTE, insertCommentMention, reorderAnimationTimelineRows, applyAnimationTimelineOrder, getEffectSoundAsset, animationEffectLabel, overlayPointerInput, TABLE_STYLE_BORDER_SIDES, applyTableStyleFieldEdit, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, getChartUserShapeGroupTransform, withChartUserShapeGroupChildAdded, createDefaultChartUserShapeGroupChild, withChartUserShapeRowUpdated, getChartUserShapeRowChartBox, withChartUserShapeRowFlipUpdated, withChartUserShapeRowRotationUpdated, withChartUserShapeRowChartBoxUpdated, switchSmartArtLayout, rebuildDrawingShapesIfCleared, mediaTrimEndMsFromSeconds, validateMediaTrimRange, SHAPE_QUICK_STYLES, quickStyleSwatchCss, OFFICE_COLOR_SWATCHES, PATTERN_PRESET_OPTIONS, getPatternSvg, COMPOUND_LINE_OPTIONS, LINE_JOIN_OPTIONS, LINE_CAP_OPTIONS, TEXT_WARP_PRESETS, warpPreviewPath, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, toSlideIndex, TABLE_STYLE_BORDER_SIDE_LABEL_KEYS, TABLE_STYLE_DASH_PRESETS, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS, cropFit, cropFill, cropToAspectRatio } from './chunk-YYVPC6KI.mjs';
5
+ import { LOCALE_CATALOG } from './chunk-Q4HRYUEP.mjs';
6
+ import React97, { createContext, lazy, forwardRef, useEffect, useState, useCallback, useMemo, useRef, useLayoutEffect, useSyncExternalStore, useId, useContext, useDeferredValue, Suspense, useReducer, Fragment as Fragment$1 } from 'react';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
8
  import { useTranslation } from 'react-i18next';
9
- import { LuArrowDown, LuArrowUp, LuArrowRight, LuArrowLeft, LuArrowDownRight, LuArrowDownLeft, LuArrowUpRight, LuArrowUpLeft, LuMessageSquare, LuEyeOff, LuHistory, LuSettings, LuX, LuCalendarDays, LuClock, LuHash, LuFileText, LuText, LuCast, LuShieldCheck, LuPlus, LuPanelLeftClose, LuDownload, LuTrash2, LuCheck, LuLock, LuEye, LuType, LuLoader, LuShieldAlert, LuSignature, LuInfo, LuTriangleAlert, LuPrinter, LuPenTool, LuBug, LuChevronUp, LuChevronDown, LuUpload, LuWifi, LuWifiOff, LuUsers, LuCopy, LuMinus, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuPanelLeft, LuPanelRight, LuSparkles, LuShare2, LuFolderOpen, LuMousePointer2, LuPalette, LuPaintbrush, LuSearch, LuCaseSensitive, LuReplace, LuGripVertical, LuLoaderCircle, LuGrid2X2, LuStickyNote, LuList, LuClipboardCopy, LuShapes, LuLayoutGrid, LuWand, LuPresentation, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuSave, LuFilePlus2, LuHouse, LuFileJson, LuBox, LuVideo, LuFileImage, LuDatabase, LuClock3, LuUser, LuHardDrive, LuLogIn, LuHighlighter, LuGroup, LuUngroup, LuMove, LuCopyPlus, LuClipboardPaste, LuMonitor, LuRadio, LuCaptions, LuImage, LuColumns3, LuCombine, LuCrop, LuFilter, LuLayers, LuSettings2, LuLockOpen, LuPencil, LuReply, LuMoveRight, LuRotateCw, LuScissors, LuBookmark, LuPipette, LuListOrdered } from 'react-icons/lu';
9
+ import { LuArrowDown, LuArrowUp, LuArrowRight, LuArrowLeft, LuArrowDownRight, LuArrowDownLeft, LuArrowUpRight, LuArrowUpLeft, LuMessageSquare, LuEyeOff, LuHistory, LuSettings, LuX, LuCalendarDays, LuClock, LuHash, LuFileText, LuText, LuCast, LuShieldCheck, LuPlus, LuPanelLeftClose, LuDownload, LuTrash2, LuCheck, LuLock, LuEye, LuType, LuLoader, LuShieldAlert, LuSignature, LuInfo, LuTriangleAlert, LuPrinter, LuPenTool, LuBug, LuChevronUp, LuChevronDown, LuUpload, LuWifi, LuWifiOff, LuUsers, LuCopy, LuMinus, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuPanelLeft, LuPanelRight, LuSparkles, LuShare2, LuFolderOpen, LuPalette, LuSearch, LuCaseSensitive, LuReplace, LuGripVertical, LuLoaderCircle, LuGrid2X2, LuStickyNote, LuList, LuClipboardCopy, LuPaintbrush, LuShapes, LuLayoutGrid, LuWand, LuPresentation, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuSave, LuFilePlus2, LuHouse, LuFileJson, LuBox, LuVideo, LuFileImage, LuDatabase, LuClock3, LuUser, LuHardDrive, LuLogIn, LuMove, LuCopyPlus, LuClipboardPaste, LuMonitor, LuRadio, LuCaptions, LuImage, LuFilter, LuLayers, LuSettings2, LuLockOpen, LuPencil, LuReply, LuMoveRight, LuRotateCw, LuScissors, LuBookmark, LuPipette } from 'react-icons/lu';
10
10
  import { createPortal } from 'react-dom';
11
11
 
12
12
  var ViewerThemeContext = createContext(void 0);
@@ -331,6 +331,38 @@ function useModalFocus(open, panelRef, onClose, initialFocusRef) {
331
331
  });
332
332
  }, [initialFocusRef, open, panelRef]);
333
333
  }
334
+ function useWebControl(state, handlers) {
335
+ const ref = useRef(null);
336
+ const latest = useRef(handlers);
337
+ latest.current = handlers;
338
+ useEffect(() => {
339
+ const host = ref.current;
340
+ if (!host) {
341
+ return;
342
+ }
343
+ host.state = state;
344
+ const attached = Object.keys(latest.current).map((name) => {
345
+ const listener = (event) => latest.current[name]?.(event);
346
+ host.addEventListener(name, listener);
347
+ return [name, listener];
348
+ });
349
+ return () => {
350
+ for (const [name, listener] of attached) {
351
+ host.removeEventListener(name, listener);
352
+ }
353
+ };
354
+ });
355
+ return ref;
356
+ }
357
+ function DialogFooter({ actions, onAction }) {
358
+ const ref = useWebControl(
359
+ { actions },
360
+ {
361
+ "dialog-footer-request": (event) => onAction(event.detail.id)
362
+ }
363
+ );
364
+ return /* @__PURE__ */ jsx("pptx-ui-dialog-footer", { ref });
365
+ }
334
366
  function SlideTemplateGalleryDialog({
335
367
  isOpen,
336
368
  onClose,
@@ -434,30 +466,21 @@ function SlideTemplateGalleryDialog({
434
466
  ))
435
467
  }
436
468
  ) }),
437
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-border", children: [
438
- /* @__PURE__ */ jsx(
439
- "button",
440
- {
441
- type: "button",
442
- onClick: onClose,
443
- className: "px-3 py-1.5 text-xs rounded bg-muted hover:bg-accent text-foreground transition-colors",
444
- children: t("pptx.slideTemplates.cancel")
445
- }
446
- ),
447
- /* @__PURE__ */ jsx(
448
- "button",
449
- {
450
- type: "button",
451
- onClick: handleInsert,
452
- disabled: !selected,
453
- className: cn(
454
- "px-3 py-1.5 text-xs rounded transition-colors",
455
- selected ? "bg-primary hover:bg-primary/80 text-white" : "bg-muted text-muted-foreground cursor-not-allowed"
456
- ),
457
- children: t("pptx.slideTemplates.insert")
458
- }
459
- )
460
- ] })
469
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
470
+ DialogFooter,
471
+ {
472
+ actions: [
473
+ { id: "cancel", label: t("pptx.slideTemplates.cancel") },
474
+ {
475
+ id: "insert",
476
+ label: t("pptx.slideTemplates.insert"),
477
+ variant: "primary",
478
+ disabled: !selected
479
+ }
480
+ ],
481
+ onAction: (id) => id === "insert" ? handleInsert() : onClose()
482
+ }
483
+ ) })
461
484
  ]
462
485
  }
463
486
  )
@@ -465,29 +488,6 @@ function SlideTemplateGalleryDialog({
465
488
  )
466
489
  ] });
467
490
  }
468
- function useWebControl(state, handlers) {
469
- const ref = useRef(null);
470
- const latest = useRef(handlers);
471
- latest.current = handlers;
472
- useEffect(() => {
473
- const host = ref.current;
474
- if (!host) {
475
- return;
476
- }
477
- host.state = state;
478
- const attached = Object.keys(latest.current).map((name) => {
479
- const listener = (event) => latest.current[name]?.(event);
480
- host.addEventListener(name, listener);
481
- return [name, listener];
482
- });
483
- return () => {
484
- for (const [name, listener] of attached) {
485
- host.removeEventListener(name, listener);
486
- }
487
- };
488
- });
489
- return ref;
490
- }
491
491
  function AnimationsSection(p) {
492
492
  const { t } = useTranslation();
493
493
  const ref = useRef(null);
@@ -624,8 +624,37 @@ function WebCheckbox({
624
624
  }
625
625
  );
626
626
  }
627
- function controlAttr(id) {
628
- return id ? { [RIBBON_CONTROL_ATTR]: id } : {};
627
+ function WebRadio({
628
+ checked,
629
+ disabled = false,
630
+ onChange,
631
+ value,
632
+ name,
633
+ ...rest
634
+ }) {
635
+ const ref = useRef(null);
636
+ useLayoutEffect(() => {
637
+ if (ref.current) {
638
+ ref.current.checked = checked;
639
+ ref.current.disabled = disabled;
640
+ }
641
+ }, [checked, disabled]);
642
+ useHostEvent(
643
+ ref,
644
+ "change",
645
+ onChange ? (event) => onChange(event) : void 0
646
+ );
647
+ return /* @__PURE__ */ jsx(
648
+ "pptx-ui-radio",
649
+ {
650
+ ref,
651
+ checked: checked || void 0,
652
+ disabled: disabled || void 0,
653
+ name,
654
+ value: value === void 0 ? void 0 : String(value),
655
+ ...rest
656
+ }
657
+ );
629
658
  }
630
659
  function groupAttr(id) {
631
660
  return id ? { [RIBBON_GROUP_ATTR]: id } : {};
@@ -640,440 +669,113 @@ var ShapeFormatContext = createContext(null);
640
669
  function useShapeFormatContext() {
641
670
  return useContext(ShapeFormatContext);
642
671
  }
643
- function RibbonMenu({
644
- anchorRef,
645
- className,
646
- children
672
+ function WebHomeControls({
673
+ family,
674
+ controls,
675
+ onRequest,
676
+ onPopup,
677
+ layoutArtwork
647
678
  }) {
648
- const [pos, setPos] = useState(null);
679
+ const { t } = useTranslation();
680
+ const ref = useRef(null);
649
681
  useEffect(() => {
650
- const anchor = anchorRef.current;
651
- if (!anchor) {
682
+ if (ref.current) {
683
+ ref.current.state = { controls, translate: t };
684
+ }
685
+ }, [controls, t]);
686
+ useEffect(() => {
687
+ if (ref.current) {
688
+ ref.current.layoutArtwork = layoutArtwork;
689
+ }
690
+ }, [layoutArtwork]);
691
+ useEffect(() => {
692
+ const host = ref.current;
693
+ if (!host) {
652
694
  return;
653
695
  }
654
- const update = () => {
655
- const { left, top } = computeAnchoredPopupPosition(anchor.getBoundingClientRect());
656
- setPos(
657
- (prev) => prev && prev.left === left && prev.top === top ? prev : { left: left ?? 0, top }
658
- );
659
- };
660
- update();
661
- anchor.addEventListener("mouseenter", update);
662
- window.addEventListener("resize", update);
663
- document.addEventListener("scroll", update, true);
664
- return () => {
665
- anchor.removeEventListener("mouseenter", update);
666
- window.removeEventListener("resize", update);
667
- document.removeEventListener("scroll", update, true);
696
+ const listener = (event) => {
697
+ const intent = event.detail;
698
+ onRequest(intent.id, intent.part, intent);
668
699
  };
669
- }, [anchorRef]);
670
- return /* @__PURE__ */ jsx(
671
- "div",
672
- {
673
- className: cn("fixed z-50", className),
674
- style: pos ? { left: pos.left, top: pos.top } : { visibility: "hidden" },
675
- children
676
- }
677
- );
678
- }
679
- var _b = "inline-flex items-center justify-center px-2.5 py-1.5 max-md:min-h-[44px] max-md:min-w-[44px] active:scale-95 active:opacity-80";
680
- var gB = `${_b} border-r border-border hover:bg-accent disabled:opacity-40 disabled:cursor-not-allowed`;
681
- var gL = `${_b} hover:bg-accent disabled:opacity-40 disabled:cursor-not-allowed`;
682
- var grp = "inline-flex items-center rounded bg-muted text-xs overflow-hidden";
683
- var pill = "inline-flex items-center gap-1.5 px-2.5 py-1.5 max-md:min-h-[44px] rounded bg-muted hover:bg-accent text-xs transition-colors active:scale-95 active:opacity-80 disabled:opacity-40 disabled:cursor-not-allowed";
684
- var sep = /* @__PURE__ */ jsx("div", { className: "w-px self-stretch bg-border/40 mx-1 max-md:hidden" });
685
- var ic = "w-4 h-4";
686
- var ics = "w-3.5 h-3.5";
687
- var OV = [
688
- {
689
- k: "png",
690
- labelKey: "pptx.ribbon.exportPng",
691
- i: /* @__PURE__ */ jsx(LuDownload, { className: `${ics} text-muted-foreground` })
692
- },
693
- {
694
- k: "pdf",
695
- labelKey: "pptx.ribbon.exportPdf",
696
- i: /* @__PURE__ */ jsx(LuFileText, { className: `${ics} text-muted-foreground` })
697
- },
698
- {
699
- k: "video",
700
- labelKey: "pptx.ribbon.exportVideo",
701
- i: /* @__PURE__ */ jsx(LuVideo, { className: `${ics} text-muted-foreground` })
702
- },
703
- {
704
- k: "gif",
705
- labelKey: "pptx.ribbon.exportGif",
706
- i: /* @__PURE__ */ jsx(LuImage, { className: `${ics} text-muted-foreground` })
707
- },
708
- {
709
- k: "pptx",
710
- labelKey: "pptx.file.saveAsPptxTooltip",
711
- i: /* @__PURE__ */ jsx(LuDownload, { className: `${ics} text-muted-foreground` })
712
- },
713
- {
714
- k: "ppsx",
715
- labelKey: "pptx.file.saveAsPpsxTooltip",
716
- i: /* @__PURE__ */ jsx(LuPlay, { className: `${ics} text-muted-foreground` })
717
- },
718
- {
719
- k: "pptm",
720
- labelKey: "pptx.file.saveAsPptmTooltip",
721
- i: /* @__PURE__ */ jsx(LuDatabase, { className: `${ics} text-muted-foreground` })
722
- },
723
- {
724
- k: "ppt",
725
- labelKey: "pptx.file.saveAsPptTooltip",
726
- i: /* @__PURE__ */ jsx(LuFileText, { className: `${ics} text-muted-foreground` })
727
- },
728
- { k: "---0", labelKey: "", i: null },
729
- {
730
- k: "print",
731
- labelKey: "pptx.print.printButton",
732
- i: /* @__PURE__ */ jsx(LuPrinter, { className: `${ics} text-muted-foreground` })
733
- },
734
- {
735
- k: "copyImg",
736
- labelKey: "pptx.file.copyImageTooltip",
737
- i: /* @__PURE__ */ jsx(LuCopy, { className: `${ics} text-muted-foreground` })
738
- },
739
- { k: "---", labelKey: "", i: null },
740
- {
741
- k: "a11y",
742
- labelKey: "pptx.ribbon.accessibilityCheck",
743
- i: /* @__PURE__ */ jsx(LuCheck, { className: `${ics} text-muted-foreground` })
744
- },
745
- {
746
- k: "shortcuts",
747
- labelKey: "pptx.settings.keyboardShortcuts",
748
- i: /* @__PURE__ */ jsx(LuSearch, { className: `${ics} text-muted-foreground` })
749
- },
750
- { k: "---2", labelKey: "", i: null },
751
- {
752
- k: "versionHistory",
753
- labelKey: "pptx.ribbon.versionHistory",
754
- i: /* @__PURE__ */ jsx(LuClock, { className: `${ics} text-muted-foreground` })
755
- },
756
- { k: "---3", labelKey: "", i: null },
757
- {
758
- k: "documentProperties",
759
- labelKey: "pptx.ribbon.documentProperties",
760
- i: /* @__PURE__ */ jsx(LuInfo, { className: `${ics} text-muted-foreground` })
761
- },
762
- {
763
- k: "passwordProtection",
764
- labelKey: "pptx.security.protectPresentation",
765
- i: /* @__PURE__ */ jsx(LuLock, { className: `${ics} text-muted-foreground` })
766
- },
767
- {
768
- k: "fontEmbedding",
769
- labelKey: "pptx.ribbon.embedFonts",
770
- i: /* @__PURE__ */ jsx(LuType, { className: `${ics} text-muted-foreground` })
771
- },
772
- {
773
- k: "digitalSignatures",
774
- labelKey: "pptx.viewer.digitalSignatures",
775
- i: /* @__PURE__ */ jsx(LuShieldAlert, { className: `${ics} text-muted-foreground` })
776
- }
777
- ];
778
- function useRibbonDropdown() {
779
- const [open, setOpen] = useState(false);
780
- const ref = useRef(null);
700
+ host.addEventListener("home-request", listener);
701
+ return () => host.removeEventListener("home-request", listener);
702
+ }, [onRequest]);
781
703
  useEffect(() => {
782
- if (!open) {
704
+ const host = ref.current;
705
+ if (!host || !onPopup) {
783
706
  return;
784
707
  }
785
- const onMouseDown = (event) => {
786
- if (ref.current && !ref.current.contains(event.target)) {
787
- setOpen(false);
788
- }
708
+ const listener = (event) => {
709
+ const { id, open } = event.detail;
710
+ onPopup(id, open);
789
711
  };
790
- const onKeyDown = (event) => {
791
- if (event.key === "Escape") {
792
- setOpen(false);
793
- }
794
- };
795
- document.addEventListener("mousedown", onMouseDown);
796
- document.addEventListener("keydown", onKeyDown);
797
- return () => {
798
- document.removeEventListener("mousedown", onMouseDown);
799
- document.removeEventListener("keydown", onKeyDown);
800
- };
801
- }, [open]);
802
- return { open, setOpen, ref };
803
- }
804
- var RIBBON_MENU_ITEM_CLASS = "flex items-center w-full px-3 py-1.5 text-xs text-left hover:bg-muted transition-colors";
805
- var RIBBON_MENU_SURFACE_CLASS = "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 min-w-36";
806
- var GROUPS = ["square", "portrait", "landscape"];
807
- function CropRibbonControls({ canEdit }) {
808
- const { t } = useTranslation();
809
- const crop = useShapeFormatContext()?.crop;
810
- const { open, setOpen, ref } = useRibbonDropdown();
811
- const enabled = canEdit && Boolean(crop?.canCrop);
812
- const active = Boolean(crop?.element);
813
- const label = t(CROP_LABEL_KEY);
814
- const hint = t("pptx.image.cropHint");
815
- const run = (action) => {
816
- setOpen(false);
817
- action();
818
- };
819
- return /* @__PURE__ */ jsxs("div", { className: "relative", ref, ...controlAttr("home.arrange.crop"), children: [
820
- /* @__PURE__ */ jsxs("div", { className: grp, children: [
821
- /* @__PURE__ */ jsx(
822
- "button",
823
- {
824
- type: "button",
825
- "data-pptx-chrome": "crop-main",
826
- "data-pptx-ribbon-control": "crop",
827
- "aria-label": label,
828
- "aria-pressed": active,
829
- title: enabled ? label : hint,
830
- disabled: !enabled,
831
- className: cn(gB, active && "bg-accent text-accent-foreground"),
832
- onMouseDown: (e) => e.preventDefault(),
833
- onClick: () => crop?.toggle(),
834
- children: /* @__PURE__ */ jsx(LuCrop, { className: ic })
835
- }
836
- ),
837
- /* @__PURE__ */ jsx(
838
- "button",
839
- {
840
- type: "button",
841
- "data-pptx-chrome": "crop-caret",
842
- "data-pptx-ribbon-control": "crop-menu",
843
- "aria-label": t(CROP_ASPECT_LABEL_KEY),
844
- "aria-haspopup": "menu",
845
- "aria-expanded": open && enabled,
846
- title: enabled ? t(CROP_ASPECT_LABEL_KEY) : hint,
847
- disabled: !enabled,
848
- className: gL,
849
- onMouseDown: (e) => e.preventDefault(),
850
- onClick: () => setOpen((v) => !v),
851
- children: /* @__PURE__ */ jsx(LuChevronDown, { className: "w-3 h-3" })
852
- }
853
- )
854
- ] }),
855
- open && enabled && crop && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: ref, className: "pt-1", children: /* @__PURE__ */ jsxs("div", { role: "menu", "aria-label": label, className: RIBBON_MENU_SURFACE_CLASS, children: [
856
- GROUPS.map((group) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": t(CROP_ASPECT_GROUP_LABEL_KEYS[group]), children: [
857
- /* @__PURE__ */ jsx(
858
- "div",
859
- {
860
- "aria-hidden": "true",
861
- className: "px-3 pt-1.5 pb-0.5 text-[10px] font-semibold text-muted-foreground",
862
- children: t(CROP_ASPECT_GROUP_LABEL_KEYS[group])
863
- }
864
- ),
865
- CROP_ASPECT_PRESETS.filter((preset) => preset.group === group).map((preset) => /* @__PURE__ */ jsx(
866
- "button",
867
- {
868
- type: "button",
869
- role: "menuitem",
870
- "data-pptx-crop-aspect": preset.id,
871
- className: RIBBON_MENU_ITEM_CLASS,
872
- onMouseDown: (e) => e.preventDefault(),
873
- onClick: () => run(() => crop.cropToAspect(preset.ratioWidth, preset.ratioHeight)),
874
- children: preset.id
875
- },
876
- preset.id
877
- ))
878
- ] }, group)),
879
- /* @__PURE__ */ jsx("hr", { className: "my-1 border-0 h-px bg-border" }),
880
- /* @__PURE__ */ jsx(
881
- "button",
882
- {
883
- type: "button",
884
- role: "menuitem",
885
- "data-pptx-crop-action": "fill",
886
- className: RIBBON_MENU_ITEM_CLASS,
887
- onMouseDown: (e) => e.preventDefault(),
888
- onClick: () => run(crop.fill),
889
- children: t(CROP_FILL_LABEL_KEY)
890
- }
891
- ),
892
- /* @__PURE__ */ jsx(
893
- "button",
894
- {
895
- type: "button",
896
- role: "menuitem",
897
- "data-pptx-crop-action": "fit",
898
- className: RIBBON_MENU_ITEM_CLASS,
899
- onMouseDown: (e) => e.preventDefault(),
900
- onClick: () => run(crop.fit),
901
- children: t(CROP_FIT_LABEL_KEY)
902
- }
903
- )
904
- ] }) })
905
- ] });
906
- }
907
- function MergeShapesMenu({ canEdit }) {
908
- const { t } = useTranslation();
909
- const commands = useShapeFormatContext();
910
- const { open, setOpen, ref } = useRibbonDropdown();
911
- const enabled = canEdit && Boolean(commands?.canMergeShapes);
912
- const label = t(MERGE_SHAPES_LABEL_KEY);
913
- return /* @__PURE__ */ jsxs("div", { className: "relative", ref, ...controlAttr("home.arrange.mergeShapes"), children: [
914
- /* @__PURE__ */ jsxs(
915
- "button",
916
- {
917
- type: "button",
918
- "data-pptx-ribbon-control": "merge-shapes",
919
- "aria-label": label,
920
- "aria-haspopup": "menu",
921
- "aria-expanded": open && enabled,
922
- title: enabled ? label : t(MERGE_SHAPES_HINT_KEY),
923
- disabled: !enabled,
924
- className: pill,
925
- onMouseDown: (e) => e.preventDefault(),
926
- onClick: () => setOpen((v) => !v),
927
- children: [
928
- /* @__PURE__ */ jsx(LuCombine, { className: ic }),
929
- /* @__PURE__ */ jsx(LuChevronDown, { className: "w-3 h-3" })
930
- ]
931
- }
932
- ),
933
- open && enabled && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: ref, className: "pt-1", children: /* @__PURE__ */ jsx("div", { role: "menu", "aria-label": label, className: RIBBON_MENU_SURFACE_CLASS, children: MERGE_SHAPES_MENU_ITEMS.map((item) => /* @__PURE__ */ jsx(
934
- "button",
935
- {
936
- type: "button",
937
- role: "menuitem",
938
- "data-pptx-merge-op": item.operation,
939
- className: RIBBON_MENU_ITEM_CLASS,
940
- onMouseDown: (e) => e.preventDefault(),
941
- onClick: () => {
942
- setOpen(false);
943
- commands?.mergeShapes(item.operation);
944
- },
945
- children: t(item.labelKey)
946
- },
947
- item.operation
948
- )) }) })
949
- ] });
712
+ host.addEventListener("home-popup", listener);
713
+ return () => host.removeEventListener("home-popup", listener);
714
+ }, [onPopup]);
715
+ return React97.createElement(`pptx-ui-ribbon-home-${family}`, { ref });
950
716
  }
951
717
  function ShapeArrangeExtras(p) {
952
- const { t } = useTranslation();
953
- const canGroup = canGroupSelection(p.canEdit, p.selectedCount, p.selectionGroupable);
954
- const canUngroup = canUngroupSelection(p.canEdit, p.selectedElement);
955
- const canStrokeWidth = canSetStrokeWidth(p.canEdit, p.selectedElement);
956
- const strokeWidth = strokeWidthOf(p.selectedElement);
718
+ const commands = useShapeFormatContext();
719
+ const crop = commands?.crop;
957
720
  const { isHidden } = useToolbarVisibility(p.hiddenActions);
958
- return /* @__PURE__ */ jsxs(Fragment, { children: [
959
- /* @__PURE__ */ jsxs("div", { className: grp, children: [
960
- /* @__PURE__ */ jsx(
961
- "button",
962
- {
963
- type: "button",
964
- onClick: p.onGroupElements,
965
- disabled: !canGroup,
966
- className: gB,
967
- title: t("pptx.contextMenu.group"),
968
- ...controlAttr("home.arrange.group"),
969
- "aria-label": t("pptx.contextMenu.group"),
970
- children: /* @__PURE__ */ jsx(LuGroup, { className: ic })
971
- }
972
- ),
973
- /* @__PURE__ */ jsx(
974
- "button",
975
- {
976
- type: "button",
977
- onClick: p.onUngroupElement,
978
- disabled: !canUngroup,
979
- className: gL,
980
- title: t("pptx.contextMenu.ungroup"),
981
- ...controlAttr("home.arrange.ungroup"),
982
- "aria-label": t("pptx.contextMenu.ungroup"),
983
- children: /* @__PURE__ */ jsx(LuUngroup, { className: ic })
984
- }
985
- )
986
- ] }),
987
- !isHidden("mergeShapes") && /* @__PURE__ */ jsx(MergeShapesMenu, { canEdit: p.canEdit }),
988
- !isHidden("crop") && /* @__PURE__ */ jsx(CropRibbonControls, { canEdit: p.canEdit }),
989
- /* @__PURE__ */ jsx(
990
- "input",
991
- {
992
- type: "number",
993
- min: "0",
994
- max: "120",
995
- step: "0.5",
996
- disabled: !canStrokeWidth,
997
- "aria-label": t("pptx.ribbon.strokeWidth"),
998
- title: t("pptx.ribbon.strokeWidth"),
999
- ...controlAttr("home.arrange.outlineWidth"),
1000
- value: strokeWidth,
1001
- onChange: (event) => {
1002
- const next = Number(event.target.value);
1003
- if (Number.isFinite(next)) {
1004
- p.onUpdateElementStyle({ strokeWidth: Math.max(0, next) });
721
+ const { onGroupElements, onUngroupElement, onUpdateElementStyle } = p;
722
+ const controls = useMemo(
723
+ () => arrangeShapeHomeControls({
724
+ editable: p.canEdit,
725
+ canGroup: canGroupSelection(p.canEdit, p.selectedCount, p.selectionGroupable),
726
+ canUngroup: canUngroupSelection(p.canEdit, p.selectedElement),
727
+ canMerge: Boolean(commands?.canMergeShapes),
728
+ canCrop: Boolean(crop?.canCrop),
729
+ cropActive: Boolean(crop?.element),
730
+ canStrokeWidth: canSetStrokeWidth(p.canEdit, p.selectedElement),
731
+ strokeWidth: strokeWidthOf(p.selectedElement),
732
+ hideMerge: isHidden("mergeShapes"),
733
+ hideCrop: isHidden("crop")
734
+ }),
735
+ [
736
+ p.canEdit,
737
+ p.selectedCount,
738
+ p.selectionGroupable,
739
+ p.selectedElement,
740
+ commands?.canMergeShapes,
741
+ crop?.canCrop,
742
+ crop?.element,
743
+ isHidden
744
+ ]
745
+ );
746
+ const request = useCallback(
747
+ (id, _part, intent) => {
748
+ const value = intent?.value;
749
+ switch (id) {
750
+ case "home.arrange.group":
751
+ onGroupElements();
752
+ break;
753
+ case "home.arrange.ungroup":
754
+ onUngroupElement();
755
+ break;
756
+ case "home.arrange.mergeShapes":
757
+ commands?.mergeShapes(value);
758
+ break;
759
+ case "home.arrange.outlineWidth":
760
+ onUpdateElementStyle({ strokeWidth: Math.max(0, Number(value)) });
761
+ break;
762
+ case "home.arrange.crop": {
763
+ const action = parseCropValue(value);
764
+ if (!action) {
765
+ crop?.toggle();
766
+ } else if (action.kind === "aspect") {
767
+ crop?.cropToAspect(action.width, action.height);
768
+ } else if (action.kind === "fill") {
769
+ crop?.fill();
770
+ } else {
771
+ crop?.fit();
1005
772
  }
1006
- },
1007
- className: "h-[26px] w-[52px] rounded border border-border bg-muted px-1 text-center text-[11px] text-foreground disabled:opacity-40"
1008
- }
1009
- )
1010
- ] });
1011
- }
1012
- function WebHomeControls({
1013
- family,
1014
- controls,
1015
- onRequest,
1016
- elementRef
1017
- }) {
1018
- const { t } = useTranslation();
1019
- const ref = useRef(null);
1020
- useEffect(() => {
1021
- if (ref.current) {
1022
- ref.current.state = { controls, translate: t };
1023
- }
1024
- }, [controls, t]);
1025
- useEffect(() => {
1026
- const host = ref.current;
1027
- if (!host) {
1028
- return;
1029
- }
1030
- const listener = (event) => {
1031
- const { id, part } = event.detail;
1032
- onRequest(id, part);
1033
- };
1034
- host.addEventListener("home-request", listener);
1035
- return () => host.removeEventListener("home-request", listener);
1036
- }, [onRequest]);
1037
- return React99.createElement(`pptx-ui-ribbon-home-${family}`, {
1038
- ref: (node) => {
1039
- ref.current = node;
1040
- if (elementRef) {
1041
- elementRef.current = node;
1042
- }
1043
- }
1044
- });
1045
- }
1046
- function useHomeAnchor(elementRef, id) {
1047
- const [anchor, setAnchor] = useState(null);
1048
- useEffect(() => {
1049
- setAnchor(elementRef.current?.anchor(id) ?? null);
1050
- }, [elementRef, id]);
1051
- return anchor;
1052
- }
1053
- function useHomePopover(anchor) {
1054
- const [open, setOpen] = useState(false);
1055
- useEffect(() => {
1056
- if (!open) {
1057
- return;
1058
- }
1059
- const onMouseDown = (event) => {
1060
- if (anchor && !anchor.contains(event.target)) {
1061
- setOpen(false);
1062
- }
1063
- };
1064
- const onKeyDown = (event) => {
1065
- if (event.key === "Escape") {
1066
- setOpen(false);
773
+ }
1067
774
  }
1068
- };
1069
- document.addEventListener("mousedown", onMouseDown);
1070
- document.addEventListener("keydown", onKeyDown);
1071
- return () => {
1072
- document.removeEventListener("mousedown", onMouseDown);
1073
- document.removeEventListener("keydown", onKeyDown);
1074
- };
1075
- }, [open, anchor]);
1076
- return { open, setOpen, anchorRef: { current: anchor } };
775
+ },
776
+ [onGroupElements, onUngroupElement, onUpdateElementStyle, commands, crop]
777
+ );
778
+ return /* @__PURE__ */ jsx(WebHomeControls, { family: "arrange-shape", controls, onRequest: request });
1077
779
  }
1078
780
  function ArrangeSection(p) {
1079
781
  const { t } = useTranslation();
@@ -1094,6 +796,17 @@ function ArrangeSection(p) {
1094
796
  }),
1095
797
  [p.canEdit, p.selectedElement, p.canDistribute]
1096
798
  );
799
+ const painterControls = useMemo(
800
+ () => arrangePainterHomeControls({
801
+ editable: p.canEdit,
802
+ active: Boolean(p.formatPainterActive),
803
+ canFormatPaint: p.canActivateFormatPainter !== false,
804
+ show: true
805
+ }),
806
+ [p.canEdit, p.formatPainterActive, p.canActivateFormatPainter]
807
+ );
808
+ const { onToggleFormatPainter } = p;
809
+ const requestPainter = useCallback(() => onToggleFormatPainter?.(), [onToggleFormatPainter]);
1097
810
  const requestAlign = useCallback(
1098
811
  (_id, part) => {
1099
812
  const action = arrangeAlignAction(part);
@@ -1134,24 +847,12 @@ function ArrangeSection(p) {
1134
847
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", ...groupAttr("home.arrange"), children: [
1135
848
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", "data-pptx-chrome": "arrange-controls", children: [
1136
849
  /* @__PURE__ */ jsx(WebHomeControls, { family: "arrange-align", controls, onRequest: requestAlign }),
1137
- p.onToggleFormatPainter && /* @__PURE__ */ jsxs(
1138
- "button",
850
+ p.onToggleFormatPainter && /* @__PURE__ */ jsx(
851
+ WebHomeControls,
1139
852
  {
1140
- type: "button",
1141
- onClick: p.onToggleFormatPainter,
1142
- disabled: !p.canEdit || p.canActivateFormatPainter === false && !p.formatPainterActive,
1143
- "data-testid": "format-painter-toggle",
1144
- "data-active": p.formatPainterActive ? "true" : "false",
1145
- className: cn(
1146
- pill,
1147
- p.formatPainterActive ? "bg-amber-600 hover:bg-amber-500 text-amber-50" : ""
1148
- ),
1149
- title: t("pptx.arrange.formatPainter"),
1150
- ...controlAttr("home.clipboard.formatPainter"),
1151
- children: [
1152
- /* @__PURE__ */ jsx(LuPaintbrush, { className: ic }),
1153
- t("pptx.arrange.format")
1154
- ]
853
+ family: "arrange-painter",
854
+ controls: painterControls,
855
+ onRequest: requestPainter
1155
856
  }
1156
857
  ),
1157
858
  /* @__PURE__ */ jsx(WebHomeControls, { family: "arrange-flip", controls, onRequest: requestFlip }),
@@ -1509,7 +1210,7 @@ function AccountPage() {
1509
1210
  return void 0;
1510
1211
  });
1511
1212
  };
1512
- const version = "4.17.1" ;
1213
+ const version = "4.18.0" ;
1513
1214
  return /* @__PURE__ */ jsxs("div", { className: "mt-8 max-w-[700px] space-y-6", children: [
1514
1215
  /* @__PURE__ */ jsxs("section", { className: cardClass, children: [
1515
1216
  /* @__PURE__ */ jsxs("h2", { className: "flex items-center gap-2 text-sm font-semibold", children: [
@@ -1952,50 +1653,28 @@ function ClipboardGroup(p) {
1952
1653
  );
1953
1654
  return /* @__PURE__ */ jsx(WebHomeControls, { family: "clipboard", controls, onRequest: request });
1954
1655
  }
1955
- function FontPickers(p) {
1656
+ function FontPickerGroup(p) {
1956
1657
  const { t } = useTranslation();
1957
- const groups = buildFontCatalog(p);
1958
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", "data-ribbon-group": "home.font", children: [
1959
- /* @__PURE__ */ jsxs("div", { "data-pptx-chrome": "font-picker-controls", children: [
1960
- /* @__PURE__ */ jsx(
1961
- WebSelect,
1962
- {
1963
- variant: "ribbon-font",
1964
- "data-font-picker": "family",
1965
- "data-ribbon-control": "home.font.fontFamily",
1966
- "aria-label": t("pptx.ribbon.fontFamily"),
1967
- value: p.fontFamily,
1968
- disabled: !p.enabled,
1969
- onChange: (e) => p.onFamily(e.target.value),
1970
- children: groups.map((group) => /* @__PURE__ */ jsx("optgroup", { label: t(group.labelKey), children: group.entries.map((entry) => /* @__PURE__ */ jsx(
1971
- "option",
1972
- {
1973
- value: entry.family,
1974
- style: { fontFamily: entry.family },
1975
- "data-display-label": entry.family,
1976
- "data-description": entry.themeRole ? t(`pptx.font.role.${entry.themeRole}`) : void 0,
1977
- children: entry.family
1978
- },
1979
- entry.family
1980
- )) }, group.id))
1981
- }
1982
- ),
1983
- /* @__PURE__ */ jsx(
1984
- WebSelect,
1985
- {
1986
- variant: "ribbon-font",
1987
- "data-font-picker": "size",
1988
- "data-ribbon-control": "home.font.fontSize",
1989
- "aria-label": t("pptx.ribbon.fontSize"),
1990
- value: p.fontSize,
1991
- disabled: !p.enabled,
1992
- onChange: (e) => p.onSize(Number(e.target.value)),
1993
- children: COMMON_FONT_SIZES.map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
1994
- }
1995
- )
1996
- ] }),
1997
- /* @__PURE__ */ jsx("span", { "data-pptx-chrome": "ribbon-group-label", children: t("pptx.ribbon.font") })
1998
- ] });
1658
+ const { enabled, fontFamily, fontSize, themeFonts, embeddedFonts, customFonts } = p;
1659
+ const { onFamily, onSize } = p;
1660
+ const controls = useMemo(
1661
+ () => fontPickerHomeControls(
1662
+ { enabled, fontFamily, fontSize, themeFonts, embeddedFonts, customFonts },
1663
+ t
1664
+ ),
1665
+ [enabled, fontFamily, fontSize, themeFonts, embeddedFonts, customFonts, t]
1666
+ );
1667
+ const request = useCallback(
1668
+ (id, _part, intent) => {
1669
+ if (id === "home.font.fontFamily") {
1670
+ onFamily(String(intent?.value));
1671
+ } else {
1672
+ onSize(Number(intent?.value));
1673
+ }
1674
+ },
1675
+ [onFamily, onSize]
1676
+ );
1677
+ return /* @__PURE__ */ jsx(WebHomeControls, { family: "font-picker", controls, onRequest: request });
1999
1678
  }
2000
1679
  function useLayoutPreviews(loadPreviews, enabled) {
2001
1680
  const [previews, setPreviews] = useState(/* @__PURE__ */ new Map());
@@ -2017,6 +1696,42 @@ function useLayoutPreviews(loadPreviews, enabled) {
2017
1696
  }, [enabled, loadPreviews]);
2018
1697
  return previews;
2019
1698
  }
1699
+ function RibbonMenu({
1700
+ anchorRef,
1701
+ className,
1702
+ children
1703
+ }) {
1704
+ const [pos, setPos] = useState(null);
1705
+ useEffect(() => {
1706
+ const anchor = anchorRef.current;
1707
+ if (!anchor) {
1708
+ return;
1709
+ }
1710
+ const update = () => {
1711
+ const { left, top } = computeAnchoredPopupPosition(anchor.getBoundingClientRect());
1712
+ setPos(
1713
+ (prev) => prev && prev.left === left && prev.top === top ? prev : { left: left ?? 0, top }
1714
+ );
1715
+ };
1716
+ update();
1717
+ anchor.addEventListener("mouseenter", update);
1718
+ window.addEventListener("resize", update);
1719
+ document.addEventListener("scroll", update, true);
1720
+ return () => {
1721
+ anchor.removeEventListener("mouseenter", update);
1722
+ window.removeEventListener("resize", update);
1723
+ document.removeEventListener("scroll", update, true);
1724
+ };
1725
+ }, [anchorRef]);
1726
+ return /* @__PURE__ */ jsx(
1727
+ "div",
1728
+ {
1729
+ className: cn("fixed z-50", className),
1730
+ style: pos ? { left: pos.left, top: pos.top } : { visibility: "hidden" },
1731
+ children
1732
+ }
1733
+ );
1734
+ }
2020
1735
  var THUMB_WIDTH = 128;
2021
1736
  var THUMB_HEIGHT = 72;
2022
1737
  var MAX_PREVIEW_ELEMENTS = 100;
@@ -2056,13 +1771,6 @@ function LayoutGalleryMenu(p) {
2056
1771
  }
2057
1772
  function LayoutThumbnail({ preview, name }) {
2058
1773
  const geometry = buildLayoutPreviewGeometry(preview, THUMB_WIDTH, THUMB_HEIGHT);
2059
- const slide = {
2060
- id: `layout-preview-${preview?.path ?? name}`,
2061
- rId: "",
2062
- slideNumber: 0,
2063
- elements: preview?.elements ?? [],
2064
- backgroundColor: geometry.backgroundColor
2065
- };
2066
1774
  return /* @__PURE__ */ jsx(
2067
1775
  "div",
2068
1776
  {
@@ -2083,16 +1791,7 @@ function LayoutThumbnail({ preview, name }) {
2083
1791
  backgroundColor: geometry.backgroundColor
2084
1792
  },
2085
1793
  children: [
2086
- (preview?.elements ?? []).slice(0, MAX_PREVIEW_ELEMENTS).map((element, index) => /* @__PURE__ */ jsx(
2087
- StaticElementRenderer,
2088
- {
2089
- element,
2090
- activeSlide: slide,
2091
- allSlides: [slide],
2092
- zIndex: index
2093
- },
2094
- element.id
2095
- )),
1794
+ /* @__PURE__ */ jsx(LayoutArtwork, { preview, name, backgroundColor: geometry.backgroundColor }),
2096
1795
  geometry.frames.map((frame) => /* @__PURE__ */ jsx(
2097
1796
  "div",
2098
1797
  {
@@ -2114,43 +1813,164 @@ function LayoutThumbnail({ preview, name }) {
2114
1813
  }
2115
1814
  );
2116
1815
  }
2117
- function SlidesGroup(p) {
2118
- const elementRef = useRef(null);
2119
- const newSlide = useHomePopover(useHomeAnchor(elementRef, "home.slides.newSlide"));
2120
- const layout = useHomePopover(useHomeAnchor(elementRef, "home.slides.layout"));
2121
- const [templateGalleryOpen, setTemplateGalleryOpen] = useState(false);
2122
- const previews = useLayoutPreviews(p.loadLayoutPreviews, newSlide.open || layout.open);
2123
- const { layoutOptions, onInsertSlideFromLayout, onResetSlide, onAddSection } = p;
2124
- const { setOpen: setNewSlideOpen } = newSlide;
2125
- const { setOpen: setLayoutOpen } = layout;
2126
- const controls = useMemo(
2127
- () => slidesHomeControls({
2128
- editable: p.canEdit,
2129
- hasLayouts: layoutOptions.length > 0,
2130
- hasSlides: true,
2131
- showTemplates: Boolean(p.onInsertSlideFromTemplate),
2132
- newSlideNeedsLayout: true,
2133
- resetNeedsSlide: false,
2134
- newSlideOpen: newSlide.open,
2135
- layoutOpen: layout.open
2136
- }),
2137
- [p.canEdit, layoutOptions.length, p.onInsertSlideFromTemplate, newSlide.open, layout.open]
2138
- );
2139
- const request = useCallback(
2140
- (id, part) => {
2141
- switch (id) {
2142
- case "home.slides.newSlide":
2143
- if (part === "caret") {
2144
- setNewSlideOpen((v) => !v);
2145
- } else if (layoutOptions.length > 0) {
2146
- onInsertSlideFromLayout(layoutOptions[0].path, layoutOptions[0].name);
2147
- }
2148
- break;
2149
- case "home.slides.slideTemplates":
1816
+ function LayoutArtwork({
1817
+ preview,
1818
+ name,
1819
+ backgroundColor
1820
+ }) {
1821
+ const slide = {
1822
+ id: `layout-preview-${preview?.path ?? name}`,
1823
+ rId: "",
1824
+ slideNumber: 0,
1825
+ elements: preview?.elements ?? [],
1826
+ backgroundColor
1827
+ };
1828
+ return /* @__PURE__ */ jsx(Fragment, { children: (preview?.elements ?? []).slice(0, MAX_PREVIEW_ELEMENTS).map((element, index) => /* @__PURE__ */ jsx(
1829
+ StaticElementRenderer,
1830
+ {
1831
+ element,
1832
+ activeSlide: slide,
1833
+ allSlides: [slide],
1834
+ zIndex: index
1835
+ },
1836
+ element.id
1837
+ )) });
1838
+ }
1839
+ var sep = /* @__PURE__ */ jsx("div", { className: "w-px self-stretch bg-border/40 mx-1 max-md:hidden" });
1840
+ var ic = "w-4 h-4";
1841
+ var ics = "w-3.5 h-3.5";
1842
+ var OV = [
1843
+ {
1844
+ k: "png",
1845
+ labelKey: "pptx.ribbon.exportPng",
1846
+ i: /* @__PURE__ */ jsx(LuDownload, { className: `${ics} text-muted-foreground` })
1847
+ },
1848
+ {
1849
+ k: "pdf",
1850
+ labelKey: "pptx.ribbon.exportPdf",
1851
+ i: /* @__PURE__ */ jsx(LuFileText, { className: `${ics} text-muted-foreground` })
1852
+ },
1853
+ {
1854
+ k: "video",
1855
+ labelKey: "pptx.ribbon.exportVideo",
1856
+ i: /* @__PURE__ */ jsx(LuVideo, { className: `${ics} text-muted-foreground` })
1857
+ },
1858
+ {
1859
+ k: "gif",
1860
+ labelKey: "pptx.ribbon.exportGif",
1861
+ i: /* @__PURE__ */ jsx(LuImage, { className: `${ics} text-muted-foreground` })
1862
+ },
1863
+ {
1864
+ k: "pptx",
1865
+ labelKey: "pptx.file.saveAsPptxTooltip",
1866
+ i: /* @__PURE__ */ jsx(LuDownload, { className: `${ics} text-muted-foreground` })
1867
+ },
1868
+ {
1869
+ k: "ppsx",
1870
+ labelKey: "pptx.file.saveAsPpsxTooltip",
1871
+ i: /* @__PURE__ */ jsx(LuPlay, { className: `${ics} text-muted-foreground` })
1872
+ },
1873
+ {
1874
+ k: "pptm",
1875
+ labelKey: "pptx.file.saveAsPptmTooltip",
1876
+ i: /* @__PURE__ */ jsx(LuDatabase, { className: `${ics} text-muted-foreground` })
1877
+ },
1878
+ {
1879
+ k: "ppt",
1880
+ labelKey: "pptx.file.saveAsPptTooltip",
1881
+ i: /* @__PURE__ */ jsx(LuFileText, { className: `${ics} text-muted-foreground` })
1882
+ },
1883
+ { k: "---0", labelKey: "", i: null },
1884
+ {
1885
+ k: "print",
1886
+ labelKey: "pptx.print.printButton",
1887
+ i: /* @__PURE__ */ jsx(LuPrinter, { className: `${ics} text-muted-foreground` })
1888
+ },
1889
+ {
1890
+ k: "copyImg",
1891
+ labelKey: "pptx.file.copyImageTooltip",
1892
+ i: /* @__PURE__ */ jsx(LuCopy, { className: `${ics} text-muted-foreground` })
1893
+ },
1894
+ { k: "---", labelKey: "", i: null },
1895
+ {
1896
+ k: "a11y",
1897
+ labelKey: "pptx.ribbon.accessibilityCheck",
1898
+ i: /* @__PURE__ */ jsx(LuCheck, { className: `${ics} text-muted-foreground` })
1899
+ },
1900
+ {
1901
+ k: "shortcuts",
1902
+ labelKey: "pptx.settings.keyboardShortcuts",
1903
+ i: /* @__PURE__ */ jsx(LuSearch, { className: `${ics} text-muted-foreground` })
1904
+ },
1905
+ { k: "---2", labelKey: "", i: null },
1906
+ {
1907
+ k: "versionHistory",
1908
+ labelKey: "pptx.ribbon.versionHistory",
1909
+ i: /* @__PURE__ */ jsx(LuClock, { className: `${ics} text-muted-foreground` })
1910
+ },
1911
+ { k: "---3", labelKey: "", i: null },
1912
+ {
1913
+ k: "documentProperties",
1914
+ labelKey: "pptx.ribbon.documentProperties",
1915
+ i: /* @__PURE__ */ jsx(LuInfo, { className: `${ics} text-muted-foreground` })
1916
+ },
1917
+ {
1918
+ k: "passwordProtection",
1919
+ labelKey: "pptx.security.protectPresentation",
1920
+ i: /* @__PURE__ */ jsx(LuLock, { className: `${ics} text-muted-foreground` })
1921
+ },
1922
+ {
1923
+ k: "fontEmbedding",
1924
+ labelKey: "pptx.ribbon.embedFonts",
1925
+ i: /* @__PURE__ */ jsx(LuType, { className: `${ics} text-muted-foreground` })
1926
+ },
1927
+ {
1928
+ k: "digitalSignatures",
1929
+ labelKey: "pptx.viewer.digitalSignatures",
1930
+ i: /* @__PURE__ */ jsx(LuShieldAlert, { className: `${ics} text-muted-foreground` })
1931
+ }
1932
+ ];
1933
+ var nextTile = 0;
1934
+ function SlidesGroup(p) {
1935
+ const [templateGalleryOpen, setTemplateGalleryOpen] = useState(false);
1936
+ const [galleryOpen, setGalleryOpen] = useState(false);
1937
+ const [tiles, setTiles] = useState([]);
1938
+ const previews = useLayoutPreviews(p.loadLayoutPreviews, galleryOpen);
1939
+ const { layoutOptions, onInsertSlideFromLayout, onApplyLayout, onResetSlide, onAddSection } = p;
1940
+ const controls = useMemo(
1941
+ () => slidesHomeControls({
1942
+ editable: p.canEdit,
1943
+ hasLayouts: layoutOptions.length > 0,
1944
+ hasSlides: true,
1945
+ showTemplates: Boolean(p.onInsertSlideFromTemplate),
1946
+ newSlideNeedsLayout: true,
1947
+ resetNeedsSlide: false,
1948
+ layouts: {
1949
+ layouts: layoutOptions.map(({ path, name }) => ({ path, name })),
1950
+ current: p.currentLayoutPath,
1951
+ previews
1952
+ }
1953
+ }),
1954
+ [p.canEdit, layoutOptions, p.onInsertSlideFromTemplate, p.currentLayoutPath, previews]
1955
+ );
1956
+ const request = useCallback(
1957
+ (id, _part, intent) => {
1958
+ const value = intent?.value;
1959
+ switch (id) {
1960
+ case "home.slides.newSlide": {
1961
+ const layout = value === void 0 ? layoutOptions[0] : layoutOptions.find((l) => l.path === value);
1962
+ if (layout) {
1963
+ onInsertSlideFromLayout(layout.path, layout.name);
1964
+ }
1965
+ break;
1966
+ }
1967
+ case "home.slides.slideTemplates":
2150
1968
  setTemplateGalleryOpen(true);
2151
1969
  break;
2152
1970
  case "home.slides.layout":
2153
- setLayoutOpen((v) => !v);
1971
+ if (value !== void 0) {
1972
+ onApplyLayout?.(String(value));
1973
+ }
2154
1974
  break;
2155
1975
  case "home.slides.reset":
2156
1976
  onResetSlide?.();
@@ -2159,15 +1979,20 @@ function SlidesGroup(p) {
2159
1979
  onAddSection?.();
2160
1980
  }
2161
1981
  },
2162
- [
2163
- layoutOptions,
2164
- onInsertSlideFromLayout,
2165
- onResetSlide,
2166
- onAddSection,
2167
- setNewSlideOpen,
2168
- setLayoutOpen
2169
- ]
2170
- );
1982
+ [layoutOptions, onInsertSlideFromLayout, onApplyLayout, onResetSlide, onAddSection]
1983
+ );
1984
+ const popup = useCallback((_id, open) => setGalleryOpen(open), []);
1985
+ const artwork = useCallback((preview, geometry, container) => {
1986
+ const tile = {
1987
+ key: nextTile++,
1988
+ preview,
1989
+ name: preview.path,
1990
+ backgroundColor: geometry.backgroundColor,
1991
+ container
1992
+ };
1993
+ setTiles((all) => [...all, tile]);
1994
+ return () => setTiles((all) => all.filter((entry) => entry.key !== tile.key));
1995
+ }, []);
2171
1996
  return /* @__PURE__ */ jsxs(Fragment, { children: [
2172
1997
  /* @__PURE__ */ jsx(
2173
1998
  WebHomeControls,
@@ -2175,39 +2000,23 @@ function SlidesGroup(p) {
2175
2000
  family: "slides",
2176
2001
  controls,
2177
2002
  onRequest: request,
2178
- elementRef
2003
+ onPopup: popup,
2004
+ layoutArtwork: artwork
2179
2005
  }
2180
2006
  ),
2181
- newSlide.open && newSlide.anchorRef.current && createPortal(
2182
- /* @__PURE__ */ jsx(
2183
- LayoutGalleryMenu,
2184
- {
2185
- anchorRef: newSlide.anchorRef,
2186
- layoutOptions,
2187
- previews,
2188
- onSelect: (l) => {
2189
- onInsertSlideFromLayout(l.path, l.name);
2190
- setNewSlideOpen(false);
2191
- }
2192
- }
2193
- ),
2194
- newSlide.anchorRef.current
2195
- ),
2196
- layout.open && layout.anchorRef.current && createPortal(
2197
- /* @__PURE__ */ jsx(
2198
- LayoutGalleryMenu,
2199
- {
2200
- anchorRef: layout.anchorRef,
2201
- layoutOptions,
2202
- previews,
2203
- currentLayoutPath: p.currentLayoutPath,
2204
- onSelect: (l) => {
2205
- p.onApplyLayout?.(l.path);
2206
- setLayoutOpen(false);
2007
+ tiles.map(
2008
+ (tile) => createPortal(
2009
+ /* @__PURE__ */ jsx(
2010
+ LayoutArtwork,
2011
+ {
2012
+ preview: tile.preview,
2013
+ name: tile.name,
2014
+ backgroundColor: tile.backgroundColor
2207
2015
  }
2208
- }
2209
- ),
2210
- layout.anchorRef.current
2016
+ ),
2017
+ tile.container,
2018
+ String(tile.key)
2019
+ )
2211
2020
  ),
2212
2021
  sep,
2213
2022
  p.onInsertSlideFromTemplate && /* @__PURE__ */ jsx(
@@ -2277,7 +2086,7 @@ function HomeSection(p) {
2277
2086
  }
2278
2087
  ),
2279
2088
  /* @__PURE__ */ jsx(
2280
- FontPickers,
2089
+ FontPickerGroup,
2281
2090
  {
2282
2091
  enabled: canFormat,
2283
2092
  fontFamily,
@@ -2385,26 +2194,16 @@ function DateTimeFieldDialog(p) {
2385
2194
  }
2386
2195
  )
2387
2196
  ] }),
2388
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 pt-1", children: [
2389
- /* @__PURE__ */ jsx(
2390
- "button",
2391
- {
2392
- type: "button",
2393
- className: "px-3 py-1.5 text-xs rounded border border-border text-foreground hover:bg-muted transition-colors",
2394
- onClick: () => p.onClose(),
2395
- children: t("pptx.common.cancel", "Cancel")
2396
- }
2397
- ),
2398
- /* @__PURE__ */ jsx(
2399
- "button",
2400
- {
2401
- type: "button",
2402
- className: "px-3 py-1.5 text-xs rounded bg-primary text-white hover:bg-primary/90 transition-colors",
2403
- onClick: confirmDatePicker,
2404
- children: t("pptx.common.insert", "Insert")
2405
- }
2406
- )
2407
- ] })
2197
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end gap-2 pt-1", children: /* @__PURE__ */ jsx(
2198
+ DialogFooter,
2199
+ {
2200
+ actions: [
2201
+ { id: "cancel", label: t("pptx.common.cancel", "Cancel") },
2202
+ { id: "insert", label: t("pptx.common.insert", "Insert"), variant: "primary" }
2203
+ ],
2204
+ onAction: (id) => id === "insert" ? confirmDatePicker() : p.onClose()
2205
+ }
2206
+ ) })
2408
2207
  ] })
2409
2208
  }
2410
2209
  );
@@ -2785,6 +2584,11 @@ function SlideShowSection(p) {
2785
2584
  ) })
2786
2585
  ] });
2787
2586
  }
2587
+ var ThemeColorMapContext = createContext(void 0);
2588
+ var ThemeColorMapProvider = ThemeColorMapContext.Provider;
2589
+ function useThemeColorMap() {
2590
+ return useContext(ThemeColorMapContext);
2591
+ }
2788
2592
 
2789
2593
  // src/viewer/components/toolbar/text-section-state.ts
2790
2594
  function getEffectiveTextStyle(element, tableEditorState) {
@@ -2841,7 +2645,9 @@ var TEXT_SHADOW_OFF = {
2841
2645
  };
2842
2646
  function FontFormatGroup(p) {
2843
2647
  const { canMut, canFormat, isTextEl, selectedElement, tableEditorState, effectiveTs } = p;
2844
- const { onUpdateTextStyle } = p;
2648
+ const { onUpdateTextStyle, onTransformTextCase, isTable, currentColor, currentHighlight } = p;
2649
+ const themeColors = useThemeColorMap();
2650
+ const { recentColors, pushColor } = useRecentColors();
2845
2651
  const flags = textSectionFlags(selectedElement, tableEditorState, false);
2846
2652
  const shadow = Boolean(effectiveTs?.textShadowColor);
2847
2653
  const controls = useMemo(
@@ -2851,15 +2657,58 @@ function FontFormatGroup(p) {
2851
2657
  italic: flags.italic === "on",
2852
2658
  underline: flags.underline === "on",
2853
2659
  strikethrough: flags.strikethrough === "on",
2854
- shadow
2660
+ shadow,
2661
+ characterSpacing: effectiveTs?.characterSpacing,
2662
+ fontColor: {
2663
+ value: currentColor,
2664
+ ref: p.currentColorRef,
2665
+ themeColors,
2666
+ recent: recentColors
2667
+ },
2668
+ highlight: { value: currentHighlight, recent: recentColors }
2855
2669
  }),
2856
- [canMut, canFormat, flags.bold, flags.italic, flags.underline, flags.strikethrough, shadow]
2670
+ [
2671
+ canMut,
2672
+ canFormat,
2673
+ flags.bold,
2674
+ flags.italic,
2675
+ flags.underline,
2676
+ flags.strikethrough,
2677
+ shadow,
2678
+ effectiveTs?.characterSpacing,
2679
+ currentColor,
2680
+ p.currentColorRef,
2681
+ currentHighlight,
2682
+ themeColors,
2683
+ recentColors
2684
+ ]
2857
2685
  );
2858
2686
  const request = useCallback(
2859
- (id) => {
2687
+ (id, _part, intent) => {
2860
2688
  if (!canFormat || !selectedElement) {
2861
2689
  return;
2862
2690
  }
2691
+ const value = intent?.value;
2692
+ switch (id) {
2693
+ case "home.font.characterSpacing":
2694
+ onUpdateTextStyle({ characterSpacing: Number(value) });
2695
+ return;
2696
+ case "home.font.changeCase":
2697
+ if (isTable) {
2698
+ onUpdateTextStyle({ textCaps: value === "upper" ? "all" : "none" });
2699
+ } else {
2700
+ onTransformTextCase(value);
2701
+ }
2702
+ return;
2703
+ case "home.font.fontColor":
2704
+ onUpdateTextStyle({ color: String(value), colorRef: intent?.ref });
2705
+ pushColor(String(value));
2706
+ return;
2707
+ case "home.font.highlightColor":
2708
+ onUpdateTextStyle({ highlightColor: String(value) });
2709
+ pushColor(String(value));
2710
+ return;
2711
+ }
2863
2712
  const flag = id.replace("home.font.", "");
2864
2713
  if (isTextDecorationFlag(flag)) {
2865
2714
  const current2 = textSectionFlags(selectedElement, tableEditorState, true);
@@ -2898,633 +2747,85 @@ function FontFormatGroup(p) {
2898
2747
  isTextEl,
2899
2748
  effectiveTs,
2900
2749
  shadow,
2901
- onUpdateTextStyle
2750
+ onUpdateTextStyle,
2751
+ onTransformTextCase,
2752
+ isTable,
2753
+ pushColor
2902
2754
  ]
2903
2755
  );
2904
2756
  return /* @__PURE__ */ jsx(WebHomeControls, { family: "font", controls, onRequest: request });
2905
2757
  }
2906
- var LINE_SPACING_OPTIONS = [
2907
- { label: "1.0", value: 1 },
2908
- { label: "1.15", value: 1.15 },
2909
- { label: "1.5", value: 1.5 },
2910
- { label: "2.0", value: 2 },
2911
- { label: "2.5", value: 2.5 },
2912
- { label: "3.0", value: 3 }
2913
- ];
2914
- var TEXT_DIRECTION_OPTIONS = [
2915
- { label: "Horizontal", value: "horizontal" },
2916
- { label: "Rotate 90\xB0", value: "vertical" },
2917
- { label: "Rotate 270\xB0", value: "vertical270" },
2918
- { label: "Stacked", value: "wordArtVert" }
2919
- ];
2920
- var COLUMN_OPTIONS = [
2921
- { label: "1 Column", value: 1 },
2922
- { label: "2 Columns", value: 2 },
2923
- { label: "3 Columns", value: 3 }
2924
- ];
2925
- function useCloseOnClickOutside(ref, open, setOpen) {
2926
- useEffect(() => {
2927
- if (!open) {
2928
- return;
2929
- }
2930
- const handler = (e) => {
2931
- if (ref.current && !ref.current.contains(e.target)) {
2932
- setOpen(false);
2933
- }
2934
- };
2935
- document.addEventListener("mousedown", handler);
2936
- return () => document.removeEventListener("mousedown", handler);
2937
- }, [open, ref, setOpen]);
2938
- }
2939
- function LineSpacingDropdown(p) {
2758
+ function ParagraphGroup(p) {
2940
2759
  const { t } = useTranslation();
2941
- const [open, setOpen] = useState(false);
2942
- const ref = useRef(null);
2943
- useCloseOnClickOutside(ref, open, setOpen);
2944
- return /* @__PURE__ */ jsxs("div", { className: "relative", ref, ...controlAttr("home.paragraph.lineSpacing"), children: [
2945
- /* @__PURE__ */ jsx(
2946
- "button",
2947
- {
2948
- type: "button",
2949
- disabled: !p.canMut,
2950
- onMouseDown: (e) => e.preventDefault(),
2951
- onClick: () => setOpen((v) => !v),
2952
- className: pill,
2953
- title: t("pptx.paragraph.lineSpacing"),
2954
- "aria-label": t("pptx.paragraph.lineSpacing"),
2955
- children: /* @__PURE__ */ jsxs("svg", { className: ic, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
2956
- /* @__PURE__ */ jsx("line", { x1: "5", y1: "5", x2: "19", y2: "5" }),
2957
- /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
2958
- /* @__PURE__ */ jsx("line", { x1: "5", y1: "19", x2: "19", y2: "19" }),
2959
- /* @__PURE__ */ jsx("path", { d: "M2 8 L2 3 M2 3 L3.5 4.5 M2 3 L0.5 4.5" }),
2960
- /* @__PURE__ */ jsx("path", { d: "M2 16 L2 21 M2 21 L3.5 19.5 M2 21 L0.5 19.5" })
2961
- ] })
2962
- }
2760
+ const { canMut, canFormat, effectiveTs, onUpdateTextStyle, onToggleBullets } = p;
2761
+ const commands = useRibbonGalleryCommands();
2762
+ const align = paragraphHomeAlign(effectiveTs?.align);
2763
+ const enabled = canMut && canFormat;
2764
+ const controls = useMemo(
2765
+ () => withHomeGalleries(
2766
+ paragraphHomeControls({
2767
+ enabled,
2768
+ align,
2769
+ list: p.bulletKind === "mixed" ? "none" : p.bulletKind,
2770
+ lineSpacing: effectiveTs?.lineSpacing,
2771
+ columns: effectiveTs?.columnCount,
2772
+ textDirection: effectiveTs?.textDirection
2773
+ }),
2774
+ homeGalleryControls("paragraph", commands?.context ?? { element: null }, enabled),
2775
+ Boolean(commands?.editable) && enabled
2963
2776
  ),
2964
- open && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: ref, className: "pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 w-28", children: LINE_SPACING_OPTIONS.map((opt) => /* @__PURE__ */ jsxs(
2965
- "button",
2966
- {
2967
- type: "button",
2968
- className: "flex items-center w-full px-3 py-1.5 text-xs hover:bg-muted transition-colors",
2969
- onMouseDown: (e) => e.preventDefault(),
2970
- onClick: () => {
2971
- if (!p.canFormat) {
2972
- return;
2777
+ [
2778
+ enabled,
2779
+ align,
2780
+ p.bulletKind,
2781
+ effectiveTs?.lineSpacing,
2782
+ effectiveTs?.columnCount,
2783
+ effectiveTs?.textDirection,
2784
+ commands?.context,
2785
+ commands?.editable
2786
+ ]
2787
+ );
2788
+ const request = useCallback(
2789
+ (id, _part, intent) => {
2790
+ if (!canFormat) {
2791
+ return;
2792
+ }
2793
+ const value = intent?.value;
2794
+ switch (id) {
2795
+ case "home.paragraph.bullets":
2796
+ case "home.paragraph.numbering":
2797
+ if (value === void 0) {
2798
+ onToggleBullets(id === "home.paragraph.bullets" ? "bullet" : "numbered");
2799
+ } else if (commands?.editable) {
2800
+ const result = homeGalleryApply("paragraph", id, String(value), commands.context);
2801
+ if (result) {
2802
+ commands.dispatch(result);
2803
+ }
2973
2804
  }
2974
- p.onUpdateTextStyle({ lineSpacing: opt.value });
2975
- setOpen(false);
2976
- },
2977
- children: [
2978
- opt.label,
2979
- p.effectiveTs?.lineSpacing === opt.value && /* @__PURE__ */ jsx("span", { className: "ml-auto text-primary", children: "\u2022" })
2980
- ]
2981
- },
2982
- opt.value
2983
- )) }) })
2984
- ] });
2985
- }
2986
- function TextDirectionDropdown(p) {
2987
- const { t } = useTranslation();
2988
- const [open, setOpen] = useState(false);
2989
- const ref = useRef(null);
2990
- useCloseOnClickOutside(ref, open, setOpen);
2991
- return /* @__PURE__ */ jsxs("div", { className: "relative", ref, ...controlAttr("home.paragraph.textDirection"), children: [
2992
- /* @__PURE__ */ jsx(
2993
- "button",
2994
- {
2995
- type: "button",
2996
- disabled: !p.canMut,
2997
- onMouseDown: (e) => e.preventDefault(),
2998
- onClick: () => setOpen((v) => !v),
2999
- className: pill,
3000
- title: t("pptx.paragraph.textDirection"),
3001
- "aria-label": t("pptx.paragraph.textDirection"),
3002
- children: /* @__PURE__ */ jsxs("svg", { className: ic, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3003
- /* @__PURE__ */ jsx("text", { x: "3", y: "16", fontSize: "12", fill: "currentColor", stroke: "none", children: "A" }),
3004
- /* @__PURE__ */ jsx("path", { d: "M18 6 C21 6 21 10 18 10" }),
3005
- /* @__PURE__ */ jsx("path", { d: "M18 10 L19.5 8.5 M18 10 L16.5 8.5" })
3006
- ] })
3007
- }
3008
- ),
3009
- open && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: ref, className: "pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 w-36", children: TEXT_DIRECTION_OPTIONS.map((opt) => /* @__PURE__ */ jsx(
3010
- "button",
3011
- {
3012
- type: "button",
3013
- className: "flex items-center w-full px-3 py-1.5 text-xs hover:bg-muted transition-colors",
3014
- onMouseDown: (e) => e.preventDefault(),
3015
- onClick: () => {
3016
- if (!p.canFormat) {
3017
- return;
3018
- }
3019
- p.onUpdateTextStyle({ textDirection: opt.value });
3020
- setOpen(false);
3021
- },
3022
- children: opt.label
3023
- },
3024
- opt.value
3025
- )) }) })
3026
- ] });
3027
- }
3028
- function ColumnsDropdown(p) {
3029
- const { t } = useTranslation();
3030
- const [open, setOpen] = useState(false);
3031
- const ref = useRef(null);
3032
- useCloseOnClickOutside(ref, open, setOpen);
3033
- return /* @__PURE__ */ jsxs("div", { className: "relative", ref, ...controlAttr("home.paragraph.columns"), children: [
3034
- /* @__PURE__ */ jsx(
3035
- "button",
3036
- {
3037
- type: "button",
3038
- disabled: !p.canMut,
3039
- onMouseDown: (e) => e.preventDefault(),
3040
- onClick: () => setOpen((v) => !v),
3041
- className: pill,
3042
- title: t("pptx.paragraph.columns"),
3043
- children: /* @__PURE__ */ jsx(LuColumns3, { className: ic })
3044
- }
3045
- ),
3046
- open && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: ref, className: "pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 w-28", children: COLUMN_OPTIONS.map((opt) => /* @__PURE__ */ jsx(
3047
- "button",
3048
- {
3049
- type: "button",
3050
- className: "flex items-center w-full px-3 py-1.5 text-xs hover:bg-muted transition-colors",
3051
- onMouseDown: (e) => e.preventDefault(),
3052
- onClick: () => {
3053
- if (!p.canFormat) {
3054
- return;
3055
- }
3056
- p.onUpdateTextStyle({ columnCount: opt.value });
3057
- setOpen(false);
3058
- },
3059
- children: opt.label
3060
- },
3061
- opt.value
3062
- )) }) })
3063
- ] });
3064
- }
3065
- var ON = "bg-primary/20 ring-1 ring-primary";
3066
- function fixedGallery(control) {
3067
- return FIXED_TAB_GALLERIES.find((placement) => placement.control === control);
3068
- }
3069
- var BULLETS_GALLERY = fixedGallery("home.paragraph.bullets");
3070
- var NUMBERING_GALLERY = fixedGallery("home.paragraph.numbering");
3071
- function ParagraphGroup(p) {
3072
- const { t } = useTranslation();
3073
- const { canMut, canFormat, effectiveTs, onUpdateTextStyle } = p;
3074
- const align = paragraphHomeAlign(effectiveTs?.align);
3075
- const paragraphControls = useMemo(
3076
- () => paragraphHomeControls({ enabled: canMut && canFormat, align }),
3077
- [canMut, canFormat, align]
3078
- );
3079
- const requestParagraph = useCallback(
3080
- (id) => {
3081
- const action = paragraphHomeAction(id);
3082
- if (!canFormat || !action) {
3083
- return;
3084
- }
3085
- if (action.kind === "indent") {
3086
- const current = effectiveTs?.paragraphMarginLeft ?? 0;
3087
- onUpdateTextStyle({ paragraphMarginLeft: Math.max(0, current + action.delta) });
3088
- } else {
3089
- onUpdateTextStyle({ align: action.align });
3090
- }
3091
- },
3092
- [canFormat, effectiveTs, onUpdateTextStyle]
3093
- );
3094
- const listToggle = (kind, placement, title, icon) => /* @__PURE__ */ jsxs("div", { className: grp, ...controlAttr(placement?.control), children: [
3095
- /* @__PURE__ */ jsx(
3096
- "button",
3097
- {
3098
- type: "button",
3099
- disabled: !canMut,
3100
- "aria-pressed": p.bulletKind === kind,
3101
- onMouseDown: (e) => e.preventDefault(),
3102
- onClick: () => p.onToggleBullets(kind),
3103
- className: `${placement ? gB : gL}${p.bulletKind === kind ? ` ${ON}` : ""}`,
3104
- title,
3105
- children: icon
3106
- }
3107
- ),
3108
- placement && /* @__PURE__ */ jsx(RibbonGallery, { placement, chevronOnly: true, tagControl: false })
3109
- ] });
3110
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", ...groupAttr("home.paragraph"), children: [
3111
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
3112
- listToggle(
3113
- "bullet",
3114
- BULLETS_GALLERY,
3115
- t("pptx.text.bulletList"),
3116
- /* @__PURE__ */ jsx(LuList, { className: ic })
3117
- ),
3118
- listToggle(
3119
- "numbered",
3120
- NUMBERING_GALLERY,
3121
- t("pptx.text.numberedList"),
3122
- /* @__PURE__ */ jsx(LuListOrdered, { className: ic })
3123
- ),
3124
- /* @__PURE__ */ jsx(
3125
- WebHomeControls,
3126
- {
3127
- family: "paragraph",
3128
- controls: paragraphControls,
3129
- onRequest: requestParagraph
3130
- }
3131
- ),
3132
- /* @__PURE__ */ jsx(
3133
- LineSpacingDropdown,
3134
- {
3135
- canMut,
3136
- canFormat,
3137
- effectiveTs: p.effectiveTs,
3138
- onUpdateTextStyle: p.onUpdateTextStyle
3139
- }
3140
- ),
3141
- /* @__PURE__ */ jsx(
3142
- TextDirectionDropdown,
3143
- {
3144
- canMut,
3145
- canFormat,
3146
- onUpdateTextStyle: p.onUpdateTextStyle
3147
- }
3148
- ),
3149
- /* @__PURE__ */ jsx(
3150
- ColumnsDropdown,
3151
- {
3152
- canMut,
3153
- canFormat,
3154
- onUpdateTextStyle: p.onUpdateTextStyle
3155
- }
3156
- )
3157
- ] }),
3158
- /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: t("pptx.ribbon.paragraph") })
3159
- ] });
3160
- }
3161
- function RecentColorsRow({
3162
- prefix,
3163
- disabled,
3164
- onCommit
3165
- }) {
3166
- const { t } = useTranslation();
3167
- const { recentColors, pushColor } = useRecentColors();
3168
- if (recentColors.length === 0) {
3169
- return null;
3170
- }
3171
- return /* @__PURE__ */ jsxs(
3172
- "div",
3173
- {
3174
- "data-testid": "pptx-color-recent",
3175
- "aria-label": t("pptx.colorPicker.recentColors"),
3176
- className: "mt-1 flex flex-wrap items-center gap-1",
3177
- children: [
3178
- /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground", children: t("pptx.colorPicker.recentColors") }),
3179
- recentColors.map((c) => /* @__PURE__ */ jsx(
3180
- "button",
3181
- {
3182
- type: "button",
3183
- "data-pptx-compact": true,
3184
- className: "h-4 w-4 rounded border border-primary",
3185
- style: { backgroundColor: c },
3186
- title: c,
3187
- "aria-label": `Recent ${c}`,
3188
- disabled,
3189
- onClick: () => {
3190
- onCommit(c);
3191
- pushColor(c);
3192
- }
3193
- },
3194
- `${prefix}-recent-${c}`
3195
- ))
3196
- ]
3197
- }
3198
- );
3199
- }
3200
- var ThemeColorMapContext = createContext(void 0);
3201
- var ThemeColorMapProvider = ThemeColorMapContext.Provider;
3202
- function useThemeColorMap() {
3203
- return useContext(ThemeColorMapContext);
3204
- }
3205
- function ThemeColorSwatchGrid({
3206
- prefix,
3207
- disabled,
3208
- selectedRef,
3209
- selectedHex,
3210
- onPick
3211
- }) {
3212
- const { t } = useTranslation();
3213
- const themeColorMap = useThemeColorMap();
3214
- const columns = useMemo(() => buildThemeColorSwatchGrid(themeColorMap), [themeColorMap]);
3215
- const rows = useMemo(() => themeColorSwatchRows(columns), [columns]);
3216
- const selected = useMemo(
3217
- () => findSelectedThemeSwatch(columns, selectedRef, selectedHex),
3218
- [columns, selectedRef, selectedHex]
3219
- );
3220
- if (columns.length === 0) {
3221
- return null;
3222
- }
3223
- return /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
3224
- /* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("pptx.colorPicker.themeColors") }),
3225
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: rows.map((row, rowIndex) => (
3226
- // eslint-disable-next-line react/no-array-index-key
3227
- /* @__PURE__ */ jsx("div", { className: "flex gap-0.5", children: row.map(
3228
- (swatch, colIndex) => swatch ? /* @__PURE__ */ jsx(
3229
- "button",
3230
- {
3231
- type: "button",
3232
- disabled,
3233
- "data-pptx-compact": true,
3234
- title: swatch.label,
3235
- "aria-label": swatch.label,
3236
- className: `h-4 w-4 rounded-sm border transition-transform hover:scale-110 disabled:opacity-40 disabled:cursor-not-allowed ${selected === swatch ? "border-primary ring-1 ring-primary" : "border-border"}`,
3237
- style: { backgroundColor: swatch.hex },
3238
- onClick: () => onPick(themeSwatchCommit(swatch))
3239
- },
3240
- `${prefix}-theme-${swatch.ref.scheme}-${rowIndex}`
3241
- ) : /* @__PURE__ */ jsx("div", { className: "h-4 w-4" }, `${prefix}-theme-empty-${rowIndex}-${colIndex}`)
3242
- ) }, `${prefix}-theme-row-${rowIndex}`)
3243
- )) })
3244
- ] });
3245
- }
3246
- var HIGHLIGHT_COLOR_PRESETS = [
3247
- "#ffff00",
3248
- "#00ff00",
3249
- "#00ffff",
3250
- "#ff00ff",
3251
- "#0000ff",
3252
- "#ff0000",
3253
- "#000080",
3254
- "#008080",
3255
- "#008000",
3256
- "#800080"
3257
- ];
3258
- function TextColorMenus(p) {
3259
- const { t } = useTranslation();
3260
- const {
3261
- canMut,
3262
- currentColor,
3263
- currentColorThemeRef,
3264
- currentHighlight,
3265
- handleColorChange,
3266
- handleHighlightChange
3267
- } = p;
3268
- const colorInputRef = useRef(null);
3269
- const highlightInputRef = useRef(null);
3270
- const fontColorRef = useRef(null);
3271
- const highlightMenuRef = useRef(null);
3272
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3273
- /* @__PURE__ */ jsxs("div", { className: "relative group", ref: fontColorRef, ...controlAttr("home.font.fontColor"), children: [
3274
- /* @__PURE__ */ jsxs(
3275
- "button",
3276
- {
3277
- type: "button",
3278
- disabled: !canMut,
3279
- onMouseDown: (e) => e.preventDefault(),
3280
- className: pill,
3281
- title: t("pptx.text.fontColor"),
3282
- "aria-label": t("pptx.text.fontColor"),
3283
- children: [
3284
- /* @__PURE__ */ jsx(
3285
- "svg",
3286
- {
3287
- className: ic,
3288
- viewBox: "0 0 24 24",
3289
- fill: "none",
3290
- stroke: "currentColor",
3291
- strokeWidth: "2",
3292
- strokeLinecap: "round",
3293
- strokeLinejoin: "round",
3294
- children: /* @__PURE__ */ jsx("path", { d: "M6 20h12M9.5 4h5L18 16H6L9.5 4z" })
3295
- }
3296
- ),
3297
- /* @__PURE__ */ jsx("div", { className: "w-4 h-1 rounded-sm -mt-0.5", style: { backgroundColor: currentColor } })
3298
- ]
3299
- }
3300
- ),
3301
- /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: fontColorRef, className: "hidden group-hover:block pt-1", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl p-2 w-48", children: [
3302
- /* @__PURE__ */ jsx(
3303
- ThemeColorSwatchGrid,
3304
- {
3305
- prefix: "font-color",
3306
- disabled: !canMut,
3307
- selectedRef: currentColorThemeRef,
3308
- selectedHex: currentColor,
3309
- onPick: (c) => handleColorChange(c.hex, c.ref)
3310
- }
3311
- ),
3312
- /* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground mt-1 mb-1", children: t("pptx.colorPicker.standardColors") }),
3313
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1.5 mb-2", children: OFFICE_COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx(
3314
- "button",
3315
- {
3316
- type: "button",
3317
- "aria-label": c.label,
3318
- title: c.label,
3319
- "data-pptx-compact": true,
3320
- className: `w-5 h-5 rounded-full border transition-transform hover:scale-125 ${currentColor?.toLowerCase() === c.hex ? "border-primary ring-1 ring-primary" : "border-border"}`,
3321
- style: { backgroundColor: c.hex },
3322
- onMouseDown: (e) => e.preventDefault(),
3323
- onClick: () => handleColorChange(c.hex)
3324
- },
3325
- c.hex
3326
- )) }),
3327
- /* @__PURE__ */ jsx(
3328
- "button",
3329
- {
3330
- type: "button",
3331
- className: "w-full text-[10px] text-muted-foreground hover:text-foreground py-1 transition-colors",
3332
- onMouseDown: (e) => e.preventDefault(),
3333
- onClick: () => colorInputRef.current?.click(),
3334
- children: t("pptx.ribbon.customColour")
3335
- }
3336
- ),
3337
- /* @__PURE__ */ jsx(
3338
- "input",
3339
- {
3340
- ref: colorInputRef,
3341
- type: "color",
3342
- className: "sr-only",
3343
- value: currentColor,
3344
- onChange: (e) => handleColorChange(e.target.value)
3345
- }
3346
- ),
3347
- /* @__PURE__ */ jsx(RecentColorsRow, { prefix: "font-color", disabled: !canMut, onCommit: handleColorChange })
3348
- ] }) })
3349
- ] }),
3350
- /* @__PURE__ */ jsxs(
3351
- "div",
3352
- {
3353
- className: "relative group",
3354
- ref: highlightMenuRef,
3355
- ...controlAttr("home.font.highlightColor"),
3356
- children: [
3357
- /* @__PURE__ */ jsxs(
3358
- "button",
3359
- {
3360
- type: "button",
3361
- disabled: !canMut,
3362
- onMouseDown: (e) => e.preventDefault(),
3363
- className: pill,
3364
- title: t("pptx.text.highlightColor"),
3365
- "aria-label": t("pptx.text.highlightColor"),
3366
- children: [
3367
- /* @__PURE__ */ jsx(LuHighlighter, { className: ic }),
3368
- /* @__PURE__ */ jsx(
3369
- "div",
3370
- {
3371
- className: "w-4 h-1 rounded-sm -mt-0.5",
3372
- style: { backgroundColor: currentHighlight }
3373
- }
3374
- )
3375
- ]
3376
- }
3377
- ),
3378
- /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: highlightMenuRef, className: "hidden group-hover:block pt-1", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl p-2 w-36", children: [
3379
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1.5 mb-2", children: HIGHLIGHT_COLOR_PRESETS.map((c) => /* @__PURE__ */ jsx(
3380
- "button",
3381
- {
3382
- type: "button",
3383
- "aria-label": c,
3384
- "data-pptx-compact": true,
3385
- className: `w-5 h-5 rounded-full border transition-transform hover:scale-125 ${currentHighlight?.toLowerCase() === c ? "border-primary ring-1 ring-primary" : "border-border"}`,
3386
- style: { backgroundColor: c },
3387
- onMouseDown: (e) => e.preventDefault(),
3388
- onClick: () => handleHighlightChange(c)
3389
- },
3390
- c
3391
- )) }),
3392
- /* @__PURE__ */ jsx(
3393
- "button",
3394
- {
3395
- type: "button",
3396
- className: "w-full text-[10px] text-muted-foreground hover:text-foreground py-1 transition-colors",
3397
- onMouseDown: (e) => e.preventDefault(),
3398
- onClick: () => highlightInputRef.current?.click(),
3399
- children: t("pptx.ribbon.customColour")
3400
- }
3401
- ),
3402
- /* @__PURE__ */ jsx(
3403
- "input",
3404
- {
3405
- ref: highlightInputRef,
3406
- type: "color",
3407
- className: "sr-only",
3408
- value: currentHighlight,
3409
- onChange: (e) => handleHighlightChange(e.target.value)
3410
- }
3411
- )
3412
- ] }) })
3413
- ]
3414
- }
3415
- )
3416
- ] });
3417
- }
3418
- function TextSpacingCaseMenus(p) {
3419
- const { t } = useTranslation();
3420
- const { canMut, canFormat, isTable } = p;
3421
- const charSpacingRef = useRef(null);
3422
- const changeCaseRef = useRef(null);
3423
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3424
- /* @__PURE__ */ jsxs(
3425
- "div",
3426
- {
3427
- className: "relative group",
3428
- ref: charSpacingRef,
3429
- ...controlAttr("home.font.characterSpacing"),
3430
- children: [
3431
- /* @__PURE__ */ jsx(
3432
- "button",
3433
- {
3434
- type: "button",
3435
- disabled: !canMut,
3436
- onMouseDown: (e) => e.preventDefault(),
3437
- className: pill,
3438
- title: t("pptx.text.characterSpacing"),
3439
- "aria-label": t("pptx.text.characterSpacing"),
3440
- children: /* @__PURE__ */ jsxs(
3441
- "svg",
3442
- {
3443
- className: ic,
3444
- viewBox: "0 0 24 24",
3445
- fill: "none",
3446
- stroke: "currentColor",
3447
- strokeWidth: "1.5",
3448
- children: [
3449
- /* @__PURE__ */ jsx("text", { x: "4", y: "16", fontSize: "11", fontWeight: "bold", fill: "currentColor", stroke: "none", children: "AV" }),
3450
- /* @__PURE__ */ jsx("path", { d: "M3 20 L1 20 M3 20 L5 20", strokeWidth: "1.5" }),
3451
- /* @__PURE__ */ jsx("path", { d: "M21 20 L19 20 M21 20 L23 20", strokeWidth: "1.5" })
3452
- ]
3453
- }
3454
- )
3455
- }
3456
- ),
3457
- /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: charSpacingRef, className: "hidden group-hover:block pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 w-32", children: CHARACTER_SPACING_OPTIONS.map((opt) => /* @__PURE__ */ jsx(
3458
- "button",
3459
- {
3460
- type: "button",
3461
- className: "flex items-center w-full px-3 py-1.5 text-xs hover:bg-muted transition-colors",
3462
- onMouseDown: (e) => e.preventDefault(),
3463
- onClick: () => {
3464
- if (!canFormat) {
3465
- return;
3466
- }
3467
- p.onUpdateTextStyle({ characterSpacing: opt.value });
3468
- },
3469
- children: t(opt.i18nKey)
3470
- },
3471
- opt.i18nKey
3472
- )) }) })
3473
- ]
3474
- }
3475
- ),
3476
- /* @__PURE__ */ jsxs("div", { className: "relative group", ref: changeCaseRef, ...controlAttr("home.font.changeCase"), children: [
3477
- /* @__PURE__ */ jsx(
3478
- "button",
3479
- {
3480
- type: "button",
3481
- disabled: !canMut,
3482
- onMouseDown: (e) => e.preventDefault(),
3483
- className: pill,
3484
- title: t("pptx.text.changeCase"),
3485
- "aria-label": t("pptx.text.changeCase"),
3486
- children: /* @__PURE__ */ jsx(
3487
- "svg",
3488
- {
3489
- className: ic,
3490
- viewBox: "0 0 24 24",
3491
- fill: "none",
3492
- stroke: "currentColor",
3493
- strokeWidth: "1.5",
3494
- children: /* @__PURE__ */ jsx("text", { x: "2", y: "16", fontSize: "13", fontWeight: "bold", fill: "currentColor", stroke: "none", children: "Aa" })
3495
- }
3496
- )
3497
- }
3498
- ),
3499
- /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: changeCaseRef, className: "hidden group-hover:block pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 w-44", children: [
3500
- { label: t("pptx.text.changeCaseSentence"), value: "sentence" },
3501
- { label: t("pptx.text.changeCaseLower"), value: "lower" },
3502
- { label: t("pptx.text.changeCaseUpper"), value: "upper" },
3503
- { label: t("pptx.text.changeCaseCapitalize"), value: "capitalize" },
3504
- { label: t("pptx.text.changeCaseToggle"), value: "toggle" }
3505
- ].map((opt) => /* @__PURE__ */ jsx(
3506
- "button",
3507
- {
3508
- type: "button",
3509
- className: "flex items-center w-full px-3 py-1.5 text-xs hover:bg-muted transition-colors",
3510
- onMouseDown: (e) => e.preventDefault(),
3511
- onClick: () => {
3512
- if (!canFormat) {
3513
- return;
3514
- }
3515
- if (isTable) {
3516
- p.onUpdateTextStyle({
3517
- textCaps: opt.value === "upper" ? "all" : "none"
3518
- });
3519
- return;
3520
- }
3521
- p.onTransformTextCase(opt.value);
3522
- },
3523
- children: opt.label
3524
- },
3525
- opt.value
3526
- )) }) })
3527
- ] })
2805
+ return;
2806
+ case "home.paragraph.lineSpacing":
2807
+ onUpdateTextStyle({ lineSpacing: Number(value) });
2808
+ return;
2809
+ case "home.paragraph.textDirection":
2810
+ onUpdateTextStyle({ textDirection: value });
2811
+ return;
2812
+ case "home.paragraph.columns":
2813
+ onUpdateTextStyle({ columnCount: Number(value) });
2814
+ return;
2815
+ }
2816
+ const action = paragraphHomeAction(id);
2817
+ if (action?.kind === "indent") {
2818
+ const current = effectiveTs?.paragraphMarginLeft ?? 0;
2819
+ onUpdateTextStyle({ paragraphMarginLeft: Math.max(0, current + action.delta) });
2820
+ } else if (action) {
2821
+ onUpdateTextStyle({ align: action.align });
2822
+ }
2823
+ },
2824
+ [canFormat, effectiveTs, onUpdateTextStyle, onToggleBullets, commands]
2825
+ );
2826
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", ...groupAttr("home.paragraph"), children: [
2827
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx(WebHomeControls, { family: "paragraph", controls, onRequest: request }) }),
2828
+ /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: t("pptx.ribbon.paragraph") })
3528
2829
  ] });
3529
2830
  }
3530
2831
  function subscribe(onChange) {
@@ -3578,64 +2879,25 @@ function TextSection(p) {
3578
2879
  const currentColor = isTextEl && p.selectedElement && hasTextProperties(p.selectedElement) ? p.selectedElement.textSegments?.[0]?.style?.color ?? p.selectedElement.textStyle?.color ?? "#000000" : effectiveTs?.color ?? "#000000";
3579
2880
  const currentColorThemeRef = isTextEl && p.selectedElement && hasTextProperties(p.selectedElement) ? p.selectedElement.textSegments?.[0]?.style?.colorRef ?? p.selectedElement.textStyle?.colorRef : void 0;
3580
2881
  const currentHighlight = isTextEl && p.selectedElement && hasTextProperties(p.selectedElement) ? p.selectedElement.textSegments?.[0]?.style?.highlightColor ?? p.selectedElement.textStyle?.highlightColor ?? "#ffff00" : "#ffff00";
3581
- const { pushColor } = useRecentColors();
3582
- const handleColorChange = useCallback(
3583
- (color, ref) => {
3584
- if (!canFormat) {
3585
- return;
3586
- }
3587
- p.onUpdateTextStyle({ color, colorRef: ref });
3588
- pushColor(color);
3589
- },
3590
- [canFormat, p, pushColor]
3591
- );
3592
- const handleHighlightChange = useCallback(
3593
- (highlightColor) => {
3594
- if (!canFormat) {
3595
- return;
3596
- }
3597
- p.onUpdateTextStyle({ highlightColor });
3598
- pushColor(highlightColor);
3599
- },
3600
- [canFormat, p, pushColor]
3601
- );
3602
2882
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3603
2883
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", ...groupAttr("home.font"), children: [
3604
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", "data-pptx-chrome": "font-controls", children: [
3605
- /* @__PURE__ */ jsx(
3606
- FontFormatGroup,
3607
- {
3608
- canMut,
3609
- canFormat,
3610
- isTextEl,
3611
- selectedElement: p.selectedElement,
3612
- tableEditorState: p.tableEditorState,
3613
- effectiveTs,
3614
- onUpdateTextStyle: p.onUpdateTextStyle
3615
- }
3616
- ),
3617
- /* @__PURE__ */ jsx(
3618
- TextSpacingCaseMenus,
3619
- {
3620
- canMut,
3621
- canFormat,
3622
- isTable,
3623
- onUpdateTextStyle: p.onUpdateTextStyle,
3624
- onTransformTextCase: p.onTransformTextCase
3625
- }
3626
- ),
3627
- /* @__PURE__ */ jsx(
3628
- TextColorMenus,
3629
- {
3630
- canMut,
3631
- currentColor,
3632
- currentColorThemeRef,
3633
- currentHighlight,
3634
- handleColorChange,
3635
- handleHighlightChange
3636
- }
3637
- )
3638
- ] }),
2884
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", "data-pptx-chrome": "font-controls", children: /* @__PURE__ */ jsx(
2885
+ FontFormatGroup,
2886
+ {
2887
+ canMut,
2888
+ canFormat,
2889
+ isTextEl,
2890
+ selectedElement: p.selectedElement,
2891
+ tableEditorState: p.tableEditorState,
2892
+ effectiveTs,
2893
+ isTable,
2894
+ currentColor,
2895
+ currentColorRef: currentColorThemeRef,
2896
+ currentHighlight,
2897
+ onUpdateTextStyle: p.onUpdateTextStyle,
2898
+ onTransformTextCase: p.onTransformTextCase
2899
+ }
2900
+ ) }),
3639
2901
  /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: t("pptx.ribbon.font") })
3640
2902
  ] }),
3641
2903
  sep,
@@ -4152,276 +3414,106 @@ function ContextualTabSection({ tab }) {
4152
3414
  group.group
4153
3415
  )) });
4154
3416
  }
4155
- function ShapeColorPopover({
4156
- prefix,
4157
- anchorRef,
4158
- disabled,
4159
- swatchAriaLabel,
4160
- selectedRef,
4161
- selectedHex,
4162
- onApply,
4163
- onClose
4164
- }) {
4165
- const { t } = useTranslation();
4166
- return /* @__PURE__ */ jsx(RibbonMenu, { anchorRef, className: "pt-1", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl p-2", children: [
4167
- /* @__PURE__ */ jsx(
4168
- ThemeColorSwatchGrid,
4169
- {
4170
- prefix,
4171
- disabled,
4172
- selectedRef,
4173
- selectedHex,
4174
- onPick: (c) => {
4175
- onApply(c.hex, c.ref);
4176
- onClose();
4177
- }
4178
- }
4179
- ),
4180
- /* @__PURE__ */ jsx("div", { className: "mt-1 text-[10px] text-muted-foreground mb-1", children: t("pptx.colorPicker.standardColors") }),
4181
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-6 gap-1", children: RIBBON_SHAPE_SWATCHES.map((c) => /* @__PURE__ */ jsx(
4182
- "button",
4183
- {
4184
- type: "button",
4185
- "aria-label": `${swatchAriaLabel} ${c}`,
4186
- "data-pptx-compact": true,
4187
- className: "w-5 h-5 rounded border border-border/60 hover:scale-110 transition-transform",
4188
- style: { backgroundColor: c },
4189
- title: c,
4190
- onClick: () => {
4191
- onApply(c);
4192
- onClose();
4193
- }
4194
- },
4195
- c
4196
- )) }),
4197
- /* @__PURE__ */ jsx(
4198
- RecentColorsRow,
4199
- {
4200
- prefix,
4201
- disabled,
4202
- onCommit: (c) => {
4203
- onApply(c);
4204
- onClose();
4205
- }
4206
- }
4207
- )
4208
- ] }) });
4209
- }
4210
- var TOP_SHAPES = SHAPE_PRESETS.slice(0, 12);
4211
- var HOME_DRAWING_GALLERIES = FIXED_TAB_GALLERIES.filter(
4212
- (placement) => placement.control.startsWith("home.drawing.")
4213
- );
4214
3417
  function DrawingGroup(p) {
4215
3418
  const { t } = useTranslation();
4216
- const { pushColor } = useRecentColors();
4217
- const selectedShapeStyle = p.selectedElement && hasShapeProperties(p.selectedElement) ? p.selectedElement.shapeStyle : void 0;
4218
- const elementRef = useRef(null);
4219
- const shapes = useHomePopover(useHomeAnchor(elementRef, "home.drawing.shapes"));
4220
- const arrange = useHomePopover(useHomeAnchor(elementRef, "home.drawing.arrange"));
4221
- const fill = useHomePopover(useHomeAnchor(elementRef, "home.drawing.shapeFill"));
4222
- const outline = useHomePopover(useHomeAnchor(elementRef, "home.drawing.shapeOutline"));
4223
- const setShapesOpen = shapes.setOpen;
4224
- const setArrangeOpen = arrange.setOpen;
4225
- const setFillOpen = fill.setOpen;
4226
- const setOutlineOpen = outline.setOpen;
4227
- const { onMoveLayer, onMoveLayerToEdge } = p;
3419
+ const { recentColors, pushColor } = useRecentColors();
3420
+ const themeColors = useThemeColorMap();
3421
+ const commands = useRibbonGalleryCommands();
3422
+ const style = p.selectedElement && hasShapeProperties(p.selectedElement) ? p.selectedElement.shapeStyle : void 0;
3423
+ const { onMoveLayer, onMoveLayerToEdge, onSetNewShapeType, onAddShape, onUpdateElementStyle } = p;
3424
+ const hasSelection = Boolean(p.selectedElement);
4228
3425
  const controls = useMemo(
4229
- () => drawingHomeControls({
4230
- editable: p.canEdit,
4231
- hasSelection: Boolean(p.selectedElement),
4232
- open: {
4233
- shapes: shapes.open,
4234
- arrange: arrange.open,
4235
- fill: fill.open,
4236
- outline: outline.open
4237
- }
4238
- }),
4239
- [p.canEdit, p.selectedElement, shapes.open, arrange.open, fill.open, outline.open]
3426
+ () => withHomeGalleries(
3427
+ drawingHomeControls({
3428
+ editable: p.canEdit,
3429
+ hasSelection,
3430
+ shapeType: p.newShapeType,
3431
+ fill: {
3432
+ value: style?.fillColor ?? "#ffffff",
3433
+ ref: style?.fillColorRef,
3434
+ themeColors,
3435
+ recent: recentColors
3436
+ },
3437
+ outline: {
3438
+ value: style?.strokeColor ?? "#000000",
3439
+ ref: style?.strokeColorRef,
3440
+ themeColors,
3441
+ recent: recentColors
3442
+ }
3443
+ }),
3444
+ homeGalleryControls("drawing", commands?.context ?? { element: null }, p.canEdit),
3445
+ p.canEdit
3446
+ ),
3447
+ [p.canEdit, hasSelection, p.newShapeType, style, themeColors, recentColors, commands?.context]
4240
3448
  );
4241
3449
  const request = useCallback(
4242
- (id) => {
3450
+ (id, _part, intent) => {
3451
+ const value = intent?.value;
3452
+ if (value === void 0) {
3453
+ return;
3454
+ }
4243
3455
  switch (id) {
4244
3456
  case "home.drawing.shapes":
4245
- setShapesOpen((v) => !v);
3457
+ onSetNewShapeType(value);
3458
+ onAddShape();
4246
3459
  break;
4247
3460
  case "home.drawing.arrange":
4248
- setArrangeOpen((v) => !v);
3461
+ if (value === "forward" || value === "backward") {
3462
+ onMoveLayer(value);
3463
+ } else {
3464
+ onMoveLayerToEdge(String(value));
3465
+ }
4249
3466
  break;
4250
3467
  case "home.drawing.shapeFill":
4251
- setFillOpen((v) => !v);
3468
+ onUpdateElementStyle?.(shapeFillChange(String(value), intent?.ref));
3469
+ pushColor(String(value));
4252
3470
  break;
4253
3471
  case "home.drawing.shapeOutline":
4254
- setOutlineOpen((v) => !v);
3472
+ onUpdateElementStyle?.(shapeOutlineChange(String(value), intent?.ref));
3473
+ pushColor(String(value));
3474
+ break;
3475
+ default:
3476
+ if (commands?.editable) {
3477
+ const result = homeGalleryApply("drawing", id, String(value), commands.context);
3478
+ if (result) {
3479
+ commands.dispatch(result);
3480
+ }
3481
+ }
4255
3482
  }
4256
3483
  },
4257
- [setShapesOpen, setArrangeOpen, setFillOpen, setOutlineOpen]
3484
+ [
3485
+ onMoveLayer,
3486
+ onMoveLayerToEdge,
3487
+ onSetNewShapeType,
3488
+ onAddShape,
3489
+ onUpdateElementStyle,
3490
+ pushColor,
3491
+ commands
3492
+ ]
4258
3493
  );
4259
- const arrangeItems = [
4260
- ["pptx.contextMenu.bringForward", () => onMoveLayer("forward")],
4261
- ["pptx.contextMenu.sendBackward", () => onMoveLayer("backward")],
4262
- ["pptx.contextMenu.bringToFront", () => onMoveLayerToEdge("front")],
4263
- ["pptx.contextMenu.sendToBack", () => onMoveLayerToEdge("back")]
4264
- ];
4265
- const noTarget = !p.canEdit || !p.selectedElement;
4266
3494
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4267
3495
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", ...groupAttr("home.drawing"), children: [
4268
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", "data-pptx-chrome": "drawing-controls", children: [
4269
- /* @__PURE__ */ jsx(
4270
- WebHomeControls,
4271
- {
4272
- family: "drawing",
4273
- controls,
4274
- onRequest: request,
4275
- elementRef
4276
- }
4277
- ),
4278
- shapes.open && shapes.anchorRef.current && createPortal(
4279
- /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: shapes.anchorRef, className: "flex flex-col w-52 pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 max-h-60 overflow-y-auto", children: TOP_SHAPES.map((s) => /* @__PURE__ */ jsxs(
4280
- "button",
4281
- {
4282
- type: "button",
4283
- className: cn(
4284
- "flex items-center gap-2 w-full px-3 py-1.5 text-xs text-foreground hover:bg-muted transition-colors",
4285
- p.newShapeType === s.type && "bg-accent"
4286
- ),
4287
- onClick: () => {
4288
- p.onSetNewShapeType(s.type);
4289
- p.onAddShape();
4290
- setShapesOpen(false);
4291
- },
4292
- children: [
4293
- s.icon,
4294
- t(s.i18nKey)
4295
- ]
4296
- },
4297
- s.type
4298
- )) }) }),
4299
- shapes.anchorRef.current
4300
- ),
4301
- arrange.open && arrange.anchorRef.current && createPortal(
4302
- /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: arrange.anchorRef, className: "flex flex-col w-44 pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1", children: arrangeItems.map(([key, run]) => /* @__PURE__ */ jsx(
4303
- "button",
4304
- {
4305
- type: "button",
4306
- className: "flex items-center w-full px-3 py-1.5 text-xs text-foreground hover:bg-muted transition-colors",
4307
- onClick: () => {
4308
- run();
4309
- setArrangeOpen(false);
4310
- },
4311
- children: t(key)
4312
- },
4313
- key
4314
- )) }) }),
4315
- arrange.anchorRef.current
4316
- ),
4317
- fill.open && fill.anchorRef.current && createPortal(
4318
- /* @__PURE__ */ jsx(
4319
- ShapeColorPopover,
4320
- {
4321
- prefix: "shape-fill",
4322
- anchorRef: fill.anchorRef,
4323
- disabled: noTarget,
4324
- swatchAriaLabel: "Fill colour",
4325
- selectedRef: selectedShapeStyle?.fillColorRef,
4326
- selectedHex: selectedShapeStyle?.fillColor,
4327
- onApply: (c, ref) => {
4328
- p.onUpdateElementStyle?.(shapeFillChange(c, ref));
4329
- pushColor(c);
4330
- },
4331
- onClose: () => setFillOpen(false)
4332
- }
4333
- ),
4334
- fill.anchorRef.current
4335
- ),
4336
- outline.open && outline.anchorRef.current && createPortal(
4337
- /* @__PURE__ */ jsx(
4338
- ShapeColorPopover,
4339
- {
4340
- prefix: "shape-outline",
4341
- anchorRef: outline.anchorRef,
4342
- disabled: noTarget,
4343
- swatchAriaLabel: "Outline colour",
4344
- selectedRef: selectedShapeStyle?.strokeColorRef,
4345
- selectedHex: selectedShapeStyle?.strokeColor,
4346
- onApply: (c, ref) => {
4347
- p.onUpdateElementStyle?.(shapeOutlineChange(c, ref));
4348
- pushColor(c);
4349
- },
4350
- onClose: () => setOutlineOpen(false)
4351
- }
4352
- ),
4353
- outline.anchorRef.current
4354
- ),
4355
- HOME_DRAWING_GALLERIES.map((placement) => /* @__PURE__ */ jsx(
4356
- RibbonGallery,
4357
- {
4358
- placement,
4359
- icon: placement.gallery === "shapeEffects" ? /* @__PURE__ */ jsx(LuSparkles, { className: ic }) : /* @__PURE__ */ jsx(LuPalette, { className: ic })
4360
- },
4361
- placement.control
4362
- ))
4363
- ] }),
3496
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", "data-pptx-chrome": "drawing-controls", children: /* @__PURE__ */ jsx(WebHomeControls, { family: "drawing", controls, onRequest: request }) }),
4364
3497
  /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: t("pptx.ribbon.groupDrawing") })
4365
3498
  ] }),
4366
3499
  sep
4367
3500
  ] });
4368
3501
  }
4369
- var editingControls = editingHomeControls();
4370
3502
  function EditingSection(p) {
4371
3503
  const { t } = useTranslation();
4372
- const [selectMenuOpen, setSelectMenuOpen] = useState(false);
4373
- const menuRef = useRef(null);
4374
- useEffect(() => {
4375
- if (!selectMenuOpen) {
4376
- return;
4377
- }
4378
- const handler = (e) => {
4379
- if (menuRef.current && !menuRef.current.contains(e.target)) {
4380
- setSelectMenuOpen(false);
4381
- }
4382
- };
4383
- document.addEventListener("mousedown", handler);
4384
- return () => document.removeEventListener("mousedown", handler);
4385
- }, [selectMenuOpen]);
3504
+ const { onToggleFindReplace, onSelectAll } = p;
3505
+ const controls = useMemo(
3506
+ () => editingHomeControls({ selectAll: Boolean(onSelectAll) }),
3507
+ [onSelectAll]
3508
+ );
3509
+ const request = useCallback(
3510
+ (id) => id === "home.editing.select" ? onSelectAll?.() : onToggleFindReplace(),
3511
+ [onSelectAll, onToggleFindReplace]
3512
+ );
4386
3513
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4387
3514
  sep,
4388
3515
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5", ...groupAttr("home.editing"), children: [
4389
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
4390
- /* @__PURE__ */ jsx(
4391
- WebHomeControls,
4392
- {
4393
- family: "editing",
4394
- controls: editingControls,
4395
- onRequest: p.onToggleFindReplace
4396
- }
4397
- ),
4398
- /* @__PURE__ */ jsxs("div", { className: "relative", ref: menuRef, ...controlAttr("home.editing.select"), children: [
4399
- /* @__PURE__ */ jsx(
4400
- "button",
4401
- {
4402
- type: "button",
4403
- onMouseDown: (e) => e.preventDefault(),
4404
- onClick: () => setSelectMenuOpen((v) => !v),
4405
- className: pill,
4406
- title: t("pptx.ribbon.tool.select"),
4407
- children: /* @__PURE__ */ jsx(LuMousePointer2, { className: ic })
4408
- }
4409
- ),
4410
- selectMenuOpen && /* @__PURE__ */ jsx(RibbonMenu, { anchorRef: menuRef, className: "pt-1", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border bg-popover backdrop-blur-lg shadow-2xl py-1 w-32", children: /* @__PURE__ */ jsx(
4411
- "button",
4412
- {
4413
- type: "button",
4414
- className: "flex items-center w-full px-3 py-1.5 text-xs hover:bg-muted transition-colors",
4415
- onMouseDown: (e) => e.preventDefault(),
4416
- onClick: () => {
4417
- p.onSelectAll?.();
4418
- setSelectMenuOpen(false);
4419
- },
4420
- children: t("pptx.editing.selectAll")
4421
- }
4422
- ) }) })
4423
- ] })
4424
- ] }),
3516
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx(WebHomeControls, { family: "editing", controls, onRequest: request }) }),
4425
3517
  /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: t("pptx.ribbon.editing") })
4426
3518
  ] })
4427
3519
  ] });
@@ -5052,7 +4144,6 @@ function RecordSection(props) {
5052
4144
  label: t(command.labelKey),
5053
4145
  icon: command.icon,
5054
4146
  disabled: command.unsupported,
5055
- compact: true,
5056
4147
  onCommand: actions[command.id]
5057
4148
  },
5058
4149
  command.id
@@ -5707,7 +4798,7 @@ function ChartQuickActionsOverlay({
5707
4798
  "data-export-ignore": "true",
5708
4799
  style: { position: "absolute", left: 0, top: 0, zIndex: 59 },
5709
4800
  onMouseDown: (e) => e.stopPropagation(),
5710
- children: descriptor.buttons.map((button) => /* @__PURE__ */ jsxs(React99.Fragment, { children: [
4801
+ children: descriptor.buttons.map((button) => /* @__PURE__ */ jsxs(React97.Fragment, { children: [
5711
4802
  /* @__PURE__ */ jsx(
5712
4803
  "button",
5713
4804
  {
@@ -5727,7 +4818,7 @@ function ChartQuickActionsOverlay({
5727
4818
  transformOrigin: "top left"
5728
4819
  },
5729
4820
  className: "flex items-center justify-center rounded bg-white border border-gray-300 shadow-sm hover:bg-gray-100 text-gray-700",
5730
- children: React99.createElement(ICONS3[button.id], { className: "size-3.5" })
4821
+ children: React97.createElement(ICONS3[button.id], { className: "size-3.5" })
5731
4822
  }
5732
4823
  ),
5733
4824
  open === button.id && button.id === "elements" && /* @__PURE__ */ jsxs(
@@ -6873,7 +5964,7 @@ function HorizontalRulerView({ ticks, widthPx, highlight }) {
6873
5964
  }
6874
5965
  );
6875
5966
  }
6876
- var HorizontalRuler = React99.memo(HorizontalRulerView);
5967
+ var HorizontalRuler = React97.memo(HorizontalRulerView);
6877
5968
  HorizontalRuler.displayName = "HorizontalRuler";
6878
5969
  function VerticalRulerView({ ticks, heightPx, highlight }) {
6879
5970
  return /* @__PURE__ */ jsxs(
@@ -6945,7 +6036,7 @@ function VerticalRulerView({ ticks, heightPx, highlight }) {
6945
6036
  }
6946
6037
  );
6947
6038
  }
6948
- var VerticalRuler = React99.memo(VerticalRulerView);
6039
+ var VerticalRuler = React97.memo(VerticalRulerView);
6949
6040
  VerticalRuler.displayName = "VerticalRuler";
6950
6041
  function Ruler({
6951
6042
  canvasSize,
@@ -8583,12 +7674,10 @@ function ExportProgressModal({
8583
7674
  ] })
8584
7675
  ] }),
8585
7676
  /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
8586
- "button",
7677
+ DialogFooter,
8587
7678
  {
8588
- type: "button",
8589
- onClick: onCancel,
8590
- className: "rounded-md border border-border bg-muted px-4 py-1.5 text-xs text-foreground transition-colors hover:bg-accent",
8591
- children: t("pptx.export.cancel")
7679
+ actions: [{ id: "cancel", label: t("pptx.export.cancel") }],
7680
+ onAction: onCancel
8592
7681
  }
8593
7682
  ) })
8594
7683
  ] })
@@ -8824,7 +7913,7 @@ function slideThumbnailPropsEqual(prev, next) {
8824
7913
  }
8825
7914
  return true;
8826
7915
  }
8827
- var SlideThumbnail = React99.memo(SlideThumbnailImpl, slideThumbnailPropsEqual);
7916
+ var SlideThumbnail = React97.memo(SlideThumbnailImpl, slideThumbnailPropsEqual);
8828
7917
 
8829
7918
  // src/viewer/components/context-menu-dispatch.ts
8830
7919
  function tableCell(props) {
@@ -9469,7 +8558,7 @@ function LazyThumbnailInner({
9469
8558
  }
9470
8559
  ) });
9471
8560
  }
9472
- var LazyThumbnail = React99.memo(LazyThumbnailInner);
8561
+ var LazyThumbnail = React97.memo(LazyThumbnailInner);
9473
8562
 
9474
8563
  // src/viewer/components/slides-pane/utils.ts
9475
8564
  function declaredSectionFacts(groups, sectionId) {
@@ -9639,7 +8728,7 @@ function SlideItemInner({
9639
8728
  }
9640
8729
  );
9641
8730
  }
9642
- var SlideItem = React99.memo(SlideItemInner);
8731
+ var SlideItem = React97.memo(SlideItemInner);
9643
8732
  function useSlidePaneCallbacks(onMoveSlide, onRenameSection, onToggleSectionCollapse) {
9644
8733
  const [collapsedSections, setCollapsedSections] = useState({});
9645
8734
  const [renamingSectionId, setRenamingSectionId] = useState(null);
@@ -11051,7 +10140,7 @@ function arePropsEqual(prev, next) {
11051
10140
  }
11052
10141
  return true;
11053
10142
  }
11054
- var SlideCard = React99.memo(SlideCardImpl, arePropsEqual);
10143
+ var SlideCard = React97.memo(SlideCardImpl, arePropsEqual);
11055
10144
  var ICON_CLASS = "h-3.5 w-3.5 text-muted-foreground";
11056
10145
  function SorterContextMenu({
11057
10146
  x,
@@ -12073,12 +11162,12 @@ function NotesPrintDialog({
12073
11162
  ] }, slide.id);
12074
11163
  }) }),
12075
11164
  /* @__PURE__ */ jsx("div", { className: "flex justify-end px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
12076
- "button",
11165
+ DialogFooter,
12077
11166
  {
12078
- type: "button",
12079
- onClick: handlePrint,
12080
- className: "px-3 py-1.5 text-xs bg-primary hover:bg-primary/80 text-white rounded",
12081
- children: t("pptx.notes.print")
11167
+ actions: [
11168
+ { id: "print", label: t("pptx.notes.print"), variant: "primary", icon: "print" }
11169
+ ],
11170
+ onAction: handlePrint
12082
11171
  }
12083
11172
  ) }),
12084
11173
  /* @__PURE__ */ jsx(
@@ -12398,8 +11487,8 @@ function SlideNotesPanel({
12398
11487
  onHeightChange
12399
11488
  }) {
12400
11489
  const { t } = useTranslation();
12401
- const rootRef = React99.useRef(null);
12402
- React99.useEffect(() => {
11490
+ const rootRef = React97.useRef(null);
11491
+ React97.useEffect(() => {
12403
11492
  const el = rootRef.current;
12404
11493
  if (!el || !onHeightChange) {
12405
11494
  return void 0;
@@ -13246,37 +12335,28 @@ function PasswordProtectionDialog({
13246
12335
  ] }),
13247
12336
  error && /* @__PURE__ */ jsx("p", { id: "pptx-password-error", className: "text-xs text-red-400", role: "alert", children: error })
13248
12337
  ] }),
13249
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3 border-t border-border/60", children: [
13250
- /* @__PURE__ */ jsx("div", { children: isCurrentlyProtected && /* @__PURE__ */ jsx(
13251
- "button",
13252
- {
13253
- type: "button",
13254
- onClick: handleRemove,
13255
- className: "text-xs text-red-400 hover:text-red-300 transition-colors",
13256
- children: t("pptx.security.removePassword")
13257
- }
13258
- ) }),
13259
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
13260
- /* @__PURE__ */ jsx(
13261
- "button",
13262
- {
13263
- type: "button",
13264
- onClick: handleClose,
13265
- className: "px-3 py-1.5 text-xs rounded-lg border border-border text-foreground hover:bg-muted transition-colors",
13266
- children: t("pptx.common.cancel")
13267
- }
13268
- ),
13269
- /* @__PURE__ */ jsx(
13270
- "button",
12338
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ jsx(
12339
+ DialogFooter,
12340
+ {
12341
+ actions: [
12342
+ ...isCurrentlyProtected ? [
12343
+ {
12344
+ id: "remove",
12345
+ label: t("pptx.security.removePassword"),
12346
+ variant: "danger",
12347
+ align: "start"
12348
+ }
12349
+ ] : [],
12350
+ { id: "cancel", label: t("pptx.common.cancel") },
13271
12351
  {
13272
- type: "button",
13273
- onClick: handleSubmit,
13274
- className: "px-3 py-1.5 text-xs rounded-lg bg-primary text-white hover:bg-primary/80 transition-colors",
13275
- children: isCurrentlyProtected ? t("pptx.security.updatePassword") : t("pptx.security.setPassword")
12352
+ id: "submit",
12353
+ label: isCurrentlyProtected ? t("pptx.security.updatePassword") : t("pptx.security.setPassword"),
12354
+ variant: "primary"
13276
12355
  }
13277
- )
13278
- ] })
13279
- ] })
12356
+ ],
12357
+ onAction: (id) => id === "remove" ? handleRemove() : id === "submit" ? handleSubmit() : handleClose()
12358
+ }
12359
+ ) })
13280
12360
  ]
13281
12361
  }
13282
12362
  )
@@ -13692,27 +12772,21 @@ function DocumentPropertiesDialog({
13692
12772
  }
13693
12773
  )
13694
12774
  ] }),
13695
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 px-5 py-3 border-t border-border/60", children: [
13696
- /* @__PURE__ */ jsx(
13697
- "button",
13698
- {
13699
- type: "button",
13700
- onClick: handleClose,
13701
- className: "px-3 py-1.5 text-xs rounded-lg border border-border text-foreground hover:bg-muted transition-colors",
13702
- children: t("pptx.common.cancel")
13703
- }
13704
- ),
13705
- /* @__PURE__ */ jsx(
13706
- "button",
13707
- {
13708
- type: "button",
13709
- onClick: handleSave,
13710
- disabled: !isDirty,
13711
- className: "px-3 py-1.5 text-xs rounded-lg bg-primary text-white hover:bg-primary/80 transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
13712
- children: t("pptx.common.save")
13713
- }
13714
- )
13715
- ] })
12775
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ jsx(
12776
+ DialogFooter,
12777
+ {
12778
+ actions: [
12779
+ { id: "cancel", label: t("pptx.common.cancel") },
12780
+ {
12781
+ id: "save",
12782
+ label: t("pptx.common.save"),
12783
+ variant: "primary",
12784
+ disabled: !isDirty
12785
+ }
12786
+ ],
12787
+ onAction: (id) => id === "save" ? handleSave() : handleClose()
12788
+ }
12789
+ ) })
13716
12790
  ]
13717
12791
  }
13718
12792
  )
@@ -13841,12 +12915,10 @@ function FontEmbeddingPanel({
13841
12915
  }) })
13842
12916
  ] }),
13843
12917
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end px-5 py-3 border-t border-border/60 shrink-0", children: /* @__PURE__ */ jsx(
13844
- "button",
12918
+ DialogFooter,
13845
12919
  {
13846
- type: "button",
13847
- onClick: onClose,
13848
- className: "px-3 py-1.5 text-xs rounded-lg bg-primary text-white hover:bg-primary/80 transition-colors",
13849
- children: t("pptx.common.done")
12920
+ actions: [{ id: "done", label: t("pptx.common.done"), variant: "primary" }],
12921
+ onAction: onClose
13850
12922
  }
13851
12923
  ) })
13852
12924
  ] })
@@ -13916,12 +12988,10 @@ function DigitalSignaturesDialog({
13916
12988
  /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("pptx.digitalSignatures.noSignatures") })
13917
12989
  ] }) }) }),
13918
12990
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ jsx(
13919
- "button",
12991
+ DialogFooter,
13920
12992
  {
13921
- type: "button",
13922
- onClick: onClose,
13923
- className: "px-3 py-1.5 text-xs rounded-lg bg-accent text-foreground hover:bg-accent/80 transition-colors",
13924
- children: t("pptx.common.close")
12993
+ actions: [{ id: "close", label: t("pptx.common.close") }],
12994
+ onAction: onClose
13925
12995
  }
13926
12996
  ) })
13927
12997
  ] })
@@ -13954,15 +13024,6 @@ function SignatureStatusBadge({
13954
13024
  }
13955
13025
  );
13956
13026
  }
13957
- function DialogFooter({ actions, onAction }) {
13958
- const ref = useWebControl(
13959
- { actions },
13960
- {
13961
- "dialog-footer-request": (event) => onAction(event.detail.id)
13962
- }
13963
- );
13964
- return /* @__PURE__ */ jsx("pptx-ui-dialog-footer", { ref });
13965
- }
13966
13027
  function SignatureStrippedDialog({
13967
13028
  isOpen,
13968
13029
  signatureCount,
@@ -14083,12 +13144,10 @@ function EncryptedFileDialog({
14083
13144
  ] })
14084
13145
  ] }) }),
14085
13146
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ jsx(
14086
- "button",
13147
+ DialogFooter,
14087
13148
  {
14088
- type: "button",
14089
- onClick: onClose,
14090
- className: "px-3 py-1.5 text-xs rounded-lg bg-accent text-foreground hover:bg-accent/80 transition-colors",
14091
- children: t("pptx.common.close")
13149
+ actions: [{ id: "close", label: t("pptx.common.close") }],
13150
+ onAction: onClose
14092
13151
  }
14093
13152
  ) })
14094
13153
  ] })
@@ -14272,9 +13331,9 @@ function PresentationSubtitleBar({
14272
13331
  function renderNotesSegments(segments) {
14273
13332
  return notesSegmentsToSpans(segments).map((span) => {
14274
13333
  if (span.kind === "break") {
14275
- return React99.createElement("br", { key: span.key });
13334
+ return React97.createElement("br", { key: span.key });
14276
13335
  }
14277
- return React99.createElement(
13336
+ return React97.createElement(
14278
13337
  "span",
14279
13338
  { key: span.key, style: span.style },
14280
13339
  span.text
@@ -14449,7 +13508,7 @@ function scaledSlidePreviewPropsEqual(prev, next) {
14449
13508
  }
14450
13509
  return true;
14451
13510
  }
14452
- var ScaledSlidePreview = React99.memo(ScaledSlidePreviewImpl, scaledSlidePreviewPropsEqual);
13511
+ var ScaledSlidePreview = React97.memo(ScaledSlidePreviewImpl, scaledSlidePreviewPropsEqual);
14453
13512
  function PresenterNotesRail({
14454
13513
  slides,
14455
13514
  current,
@@ -15082,26 +14141,16 @@ function RehearseTimingsSummary({
15082
14141
  ] }, slideIndex);
15083
14142
  }) })
15084
14143
  ] }) }),
15085
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-border px-5 py-3", children: [
15086
- /* @__PURE__ */ jsx(
15087
- "button",
15088
- {
15089
- type: "button",
15090
- onClick: onDiscard,
15091
- className: "rounded-lg px-4 py-2 text-sm text-foreground hover:bg-muted transition-colors",
15092
- children: t("pptx.rehearse.discard")
15093
- }
15094
- ),
15095
- /* @__PURE__ */ jsx(
15096
- "button",
15097
- {
15098
- type: "button",
15099
- onClick: onSave,
15100
- className: "rounded-lg bg-primary px-4 py-2 text-sm text-white hover:bg-primary/80 transition-colors",
15101
- children: t("pptx.rehearse.saveTimings")
15102
- }
15103
- )
15104
- ] })
14144
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 border-t border-border px-5 py-3", children: /* @__PURE__ */ jsx(
14145
+ DialogFooter,
14146
+ {
14147
+ actions: [
14148
+ { id: "discard", label: t("pptx.rehearse.discard") },
14149
+ { id: "save", label: t("pptx.rehearse.saveTimings"), variant: "primary" }
14150
+ ],
14151
+ onAction: (id) => id === "save" ? onSave() : onDiscard()
14152
+ }
14153
+ ) })
15105
14154
  ] }) });
15106
14155
  }
15107
14156
 
@@ -15687,7 +14736,7 @@ function EffectSoundRow({
15687
14736
  onPickStock
15688
14737
  }) {
15689
14738
  const { t } = useTranslation();
15690
- const fileInputRef = React99.useRef(null);
14739
+ const fileInputRef = React97.useRef(null);
15691
14740
  const selectedValue = soundState.catalogueId ?? (soundState.hasSound ? CURRENT_VALUE : NONE_VALUE);
15692
14741
  const handleSelectChange = (event) => {
15693
14742
  const value = event.target.value;
@@ -19185,12 +18234,13 @@ function OleEditorDialog({
19185
18234
  }
19186
18235
  ),
19187
18236
  /* @__PURE__ */ jsx(
19188
- "button",
18237
+ DialogFooter,
19189
18238
  {
19190
- type: "button",
19191
- onClick: () => fileInputRef.current?.click(),
19192
- className: "px-3 py-1.5 rounded-lg text-xs text-foreground border border-border hover:bg-accent transition-colors",
19193
- children: t("pptx.ole.editDialog.replaceFile")
18239
+ actions: [
18240
+ { id: "replace", label: t("pptx.ole.editDialog.replaceFile"), align: "start" },
18241
+ { id: "save", label: t("pptx.ole.editDialog.save"), variant: "primary" }
18242
+ ],
18243
+ onAction: (id) => id === "replace" ? fileInputRef.current?.click() : onClose()
19194
18244
  }
19195
18245
  ),
19196
18246
  /* @__PURE__ */ jsx(
@@ -19258,7 +18308,7 @@ function ConnectorArrowsSection({
19258
18308
  ["Start", "End"].map((end) => {
19259
18309
  const widthKey = end === "Start" ? "connectorStartArrowWidth" : "connectorEndArrowWidth";
19260
18310
  const lengthKey = end === "Start" ? "connectorStartArrowLength" : "connectorEndArrowLength";
19261
- return /* @__PURE__ */ jsxs(React99.Fragment, { children: [
18311
+ return /* @__PURE__ */ jsxs(React97.Fragment, { children: [
19262
18312
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
19263
18313
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t(END_LABEL_KEYS[end].width) }),
19264
18314
  /* @__PURE__ */ jsx(
@@ -21492,22 +20542,102 @@ var VISUAL_EFFECT_CONFIGS = [
21492
20542
  }
21493
20543
  ]
21494
20544
  }
21495
- ];
21496
-
21497
- // src/viewer/components/inspector/FillStrokeHelpers.tsx
21498
- var EFFECT_CONFIGS = [...SHADOW_EFFECT_CONFIGS, ...VISUAL_EFFECT_CONFIGS];
21499
- var SEL2 = "bg-muted border border-border rounded px-2 py-1 max-md:min-h-[44px]!";
21500
- var NUM2 = SEL2;
21501
- var RNG = "accent-primary";
21502
- var SWATCH = "h-4 w-4 rounded border border-border";
21503
- var DIS = "disabled:opacity-40 disabled:cursor-not-allowed";
21504
- var LBL2 = "text-muted-foreground";
21505
- var COL2 = "col-span-2";
21506
- var isLineish = (el, st) => el.type === "connector" || st === "line";
21507
- var safeNum = (raw, fallback) => {
21508
- const n = Number(raw);
21509
- return Number.isFinite(n) ? n : fallback;
21510
- };
20545
+ ];
20546
+
20547
+ // src/viewer/components/inspector/FillStrokeHelpers.tsx
20548
+ var EFFECT_CONFIGS = [...SHADOW_EFFECT_CONFIGS, ...VISUAL_EFFECT_CONFIGS];
20549
+ var SEL2 = "bg-muted border border-border rounded px-2 py-1 max-md:min-h-[44px]!";
20550
+ var NUM2 = SEL2;
20551
+ var RNG = "accent-primary";
20552
+ var SWATCH = "h-4 w-4 rounded border border-border";
20553
+ var DIS = "disabled:opacity-40 disabled:cursor-not-allowed";
20554
+ var LBL2 = "text-muted-foreground";
20555
+ var COL2 = "col-span-2";
20556
+ var isLineish = (el, st) => el.type === "connector" || st === "line";
20557
+ var safeNum = (raw, fallback) => {
20558
+ const n = Number(raw);
20559
+ return Number.isFinite(n) ? n : fallback;
20560
+ };
20561
+ function RecentColorsRow({
20562
+ prefix,
20563
+ disabled,
20564
+ onCommit
20565
+ }) {
20566
+ const { t } = useTranslation();
20567
+ const { recentColors, pushColor } = useRecentColors();
20568
+ if (recentColors.length === 0) {
20569
+ return null;
20570
+ }
20571
+ return /* @__PURE__ */ jsxs(
20572
+ "div",
20573
+ {
20574
+ "data-testid": "pptx-color-recent",
20575
+ "aria-label": t("pptx.colorPicker.recentColors"),
20576
+ className: "mt-1 flex flex-wrap items-center gap-1",
20577
+ children: [
20578
+ /* @__PURE__ */ jsx("span", { className: "text-[9px] text-muted-foreground", children: t("pptx.colorPicker.recentColors") }),
20579
+ recentColors.map((c) => /* @__PURE__ */ jsx(
20580
+ "button",
20581
+ {
20582
+ type: "button",
20583
+ "data-pptx-compact": true,
20584
+ className: "h-4 w-4 rounded border border-primary",
20585
+ style: { backgroundColor: c },
20586
+ title: c,
20587
+ "aria-label": `Recent ${c}`,
20588
+ disabled,
20589
+ onClick: () => {
20590
+ onCommit(c);
20591
+ pushColor(c);
20592
+ }
20593
+ },
20594
+ `${prefix}-recent-${c}`
20595
+ ))
20596
+ ]
20597
+ }
20598
+ );
20599
+ }
20600
+ function ThemeColorSwatchGrid({
20601
+ prefix,
20602
+ disabled,
20603
+ selectedRef,
20604
+ selectedHex,
20605
+ onPick
20606
+ }) {
20607
+ const { t } = useTranslation();
20608
+ const themeColorMap = useThemeColorMap();
20609
+ const columns = useMemo(() => buildThemeColorSwatchGrid(themeColorMap), [themeColorMap]);
20610
+ const rows = useMemo(() => themeColorSwatchRows(columns), [columns]);
20611
+ const selected = useMemo(
20612
+ () => findSelectedThemeSwatch(columns, selectedRef, selectedHex),
20613
+ [columns, selectedRef, selectedHex]
20614
+ );
20615
+ if (columns.length === 0) {
20616
+ return null;
20617
+ }
20618
+ return /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
20619
+ /* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("pptx.colorPicker.themeColors") }),
20620
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: rows.map((row, rowIndex) => (
20621
+ // eslint-disable-next-line react/no-array-index-key
20622
+ /* @__PURE__ */ jsx("div", { className: "flex gap-0.5", children: row.map(
20623
+ (swatch, colIndex) => swatch ? /* @__PURE__ */ jsx(
20624
+ "button",
20625
+ {
20626
+ type: "button",
20627
+ disabled,
20628
+ "data-pptx-compact": true,
20629
+ title: swatch.label,
20630
+ "aria-label": swatch.label,
20631
+ className: `h-4 w-4 rounded-sm border transition-transform hover:scale-110 disabled:opacity-40 disabled:cursor-not-allowed ${selected === swatch ? "border-primary ring-1 ring-primary" : "border-border"}`,
20632
+ style: { backgroundColor: swatch.hex },
20633
+ onClick: () => onPick(themeSwatchCommit(swatch))
20634
+ },
20635
+ `${prefix}-theme-${swatch.ref.scheme}-${rowIndex}`
20636
+ ) : /* @__PURE__ */ jsx("div", { className: "h-4 w-4" }, `${prefix}-theme-empty-${rowIndex}-${colIndex}`)
20637
+ ) }, `${prefix}-theme-row-${rowIndex}`)
20638
+ )) })
20639
+ ] });
20640
+ }
21511
20641
  function EffectField({
21512
20642
  field,
21513
20643
  style,
@@ -22105,7 +21235,7 @@ function StrokeEffectsSection({
22105
21235
  ] }),
22106
21236
  EFFECT_CONFIGS.map((cfg) => {
22107
21237
  const on = cfg.isOn(style);
22108
- return /* @__PURE__ */ jsxs(React99.Fragment, { children: [
21238
+ return /* @__PURE__ */ jsxs(React97.Fragment, { children: [
22109
21239
  /* @__PURE__ */ jsxs("label", { className: `inline-flex items-center gap-2 text-foreground ${COL2}`, children: [
22110
21240
  /* @__PURE__ */ jsx(
22111
21241
  WebCheckbox,
@@ -22960,7 +22090,7 @@ function TextWarpGallery({
22960
22090
  onUpdateTextStyle
22961
22091
  }) {
22962
22092
  const { t } = useTranslation();
22963
- const [expanded, setExpanded] = React99.useState(false);
22093
+ const [expanded, setExpanded] = React97.useState(false);
22964
22094
  const currentPreset = ts?.textWarpPreset || "textNoShape";
22965
22095
  return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded border border-border bg-card p-2 space-y-2", children: [
22966
22096
  /* @__PURE__ */ jsxs(
@@ -23611,7 +22741,7 @@ function SmartArtStyleControls({
23611
22741
  onChangeStyle
23612
22742
  }) {
23613
22743
  const { t } = useTranslation();
23614
- const translate = React99.useCallback((key) => t(key), [t]);
22744
+ const translate = React97.useCallback((key) => t(key), [t]);
23615
22745
  return /* @__PURE__ */ jsxs(Fragment, { children: [
23616
22746
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
23617
22747
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.smartart.colorScheme") }),
@@ -23666,9 +22796,9 @@ function SmartArtPropertiesPanel({
23666
22796
  const nodes = smartArtData.nodes ?? [];
23667
22797
  const layout = smartArtData.resolvedLayoutType;
23668
22798
  const topLevelCount = nodes.filter((n) => !n.parentId).length;
23669
- const inputRefs = React99.useRef(/* @__PURE__ */ new Map());
23670
- const pendingFocusId = React99.useRef(null);
23671
- React99.useEffect(() => {
22799
+ const inputRefs = React97.useRef(/* @__PURE__ */ new Map());
22800
+ const pendingFocusId = React97.useRef(null);
22801
+ React97.useEffect(() => {
23672
22802
  const id = pendingFocusId.current;
23673
22803
  if (id) {
23674
22804
  inputRefs.current.get(id)?.focus();
@@ -25279,7 +24409,7 @@ function CommentBody({ text, mentions, className }) {
25279
24409
  index
25280
24410
  ) : (
25281
24411
  // eslint-disable-next-line react/no-array-index-key -- segments are positional
25282
- /* @__PURE__ */ jsx(React99.Fragment, { children: segment.text }, index)
24412
+ /* @__PURE__ */ jsx(React97.Fragment, { children: segment.text }, index)
25283
24413
  )
25284
24414
  ) });
25285
24415
  }
@@ -26795,7 +25925,7 @@ function PresentationPropertiesPanel({
26795
25925
  onUpdateTagCollections
26796
25926
  }) {
26797
25927
  const { t } = useTranslation();
26798
- const handleTransitionChange = React99.useCallback(
25928
+ const handleTransitionChange = React97.useCallback(
26799
25929
  (updates) => {
26800
25930
  onUpdateSlide({
26801
25931
  transition: mergeSlideTransition(activeSlide?.transition, updates)
@@ -27726,9 +26856,8 @@ function PasteSpecialDialog({
27726
26856
  /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-foreground mb-3", children: t("pptx.pasteSpecial.dialogTitle") }),
27727
26857
  /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1 mb-5", children: PASTE_SPECIAL_OPTIONS.map((option) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer hover:bg-accent text-sm text-foreground", children: [
27728
26858
  /* @__PURE__ */ jsx(
27729
- "input",
26859
+ WebRadio,
27730
26860
  {
27731
- type: "radio",
27732
26861
  name: "paste-special-format",
27733
26862
  value: option.id,
27734
26863
  checked: selected === option.id,
@@ -27988,9 +27117,8 @@ function PrintSettingsPanel({
27988
27117
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
27989
27118
  /* @__PURE__ */ jsxs("label", { className: radioClass(printWhat === "slides"), children: [
27990
27119
  /* @__PURE__ */ jsx(
27991
- "input",
27120
+ WebRadio,
27992
27121
  {
27993
- type: "radio",
27994
27122
  name: "printWhat",
27995
27123
  className: "sr-only",
27996
27124
  checked: printWhat === "slides",
@@ -28002,9 +27130,8 @@ function PrintSettingsPanel({
28002
27130
  ] }),
28003
27131
  /* @__PURE__ */ jsxs("label", { className: radioClass(printWhat === "handouts"), children: [
28004
27132
  /* @__PURE__ */ jsx(
28005
- "input",
27133
+ WebRadio,
28006
27134
  {
28007
- type: "radio",
28008
27135
  name: "printWhat",
28009
27136
  className: "sr-only",
28010
27137
  checked: printWhat === "handouts",
@@ -28016,9 +27143,8 @@ function PrintSettingsPanel({
28016
27143
  ] }),
28017
27144
  /* @__PURE__ */ jsxs("label", { className: radioClass(printWhat === "notes"), children: [
28018
27145
  /* @__PURE__ */ jsx(
28019
- "input",
27146
+ WebRadio,
28020
27147
  {
28021
- type: "radio",
28022
27148
  name: "printWhat",
28023
27149
  className: "sr-only",
28024
27150
  checked: printWhat === "notes",
@@ -28030,9 +27156,8 @@ function PrintSettingsPanel({
28030
27156
  ] }),
28031
27157
  /* @__PURE__ */ jsxs("label", { className: radioClass(printWhat === "outline"), children: [
28032
27158
  /* @__PURE__ */ jsx(
28033
- "input",
27159
+ WebRadio,
28034
27160
  {
28035
- type: "radio",
28036
27161
  name: "printWhat",
28037
27162
  className: "sr-only",
28038
27163
  checked: printWhat === "outline",
@@ -28062,9 +27187,8 @@ function PrintSettingsPanel({
28062
27187
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
28063
27188
  /* @__PURE__ */ jsxs("label", { className: radioClass(slideRange === "all"), children: [
28064
27189
  /* @__PURE__ */ jsx(
28065
- "input",
27190
+ WebRadio,
28066
27191
  {
28067
- type: "radio",
28068
27192
  name: "slideRange",
28069
27193
  className: "sr-only",
28070
27194
  checked: slideRange === "all",
@@ -28078,9 +27202,8 @@ function PrintSettingsPanel({
28078
27202
  ] }),
28079
27203
  /* @__PURE__ */ jsxs("label", { className: radioClass(slideRange === "current"), children: [
28080
27204
  /* @__PURE__ */ jsx(
28081
- "input",
27205
+ WebRadio,
28082
27206
  {
28083
- type: "radio",
28084
27207
  name: "slideRange",
28085
27208
  className: "sr-only",
28086
27209
  checked: slideRange === "current",
@@ -28094,9 +27217,8 @@ function PrintSettingsPanel({
28094
27217
  ] }),
28095
27218
  /* @__PURE__ */ jsxs("label", { className: radioClass(slideRange === "custom"), children: [
28096
27219
  /* @__PURE__ */ jsx(
28097
- "input",
27220
+ WebRadio,
28098
27221
  {
28099
- type: "radio",
28100
27222
  name: "slideRange",
28101
27223
  className: "sr-only",
28102
27224
  checked: slideRange === "custom",
@@ -28138,9 +27260,8 @@ function PrintSettingsPanel({
28138
27260
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
28139
27261
  /* @__PURE__ */ jsxs("label", { className: radioClass(orientation === "landscape"), children: [
28140
27262
  /* @__PURE__ */ jsx(
28141
- "input",
27263
+ WebRadio,
28142
27264
  {
28143
- type: "radio",
28144
27265
  name: "orientation",
28145
27266
  className: "sr-only",
28146
27267
  checked: orientation === "landscape",
@@ -28151,9 +27272,8 @@ function PrintSettingsPanel({
28151
27272
  ] }),
28152
27273
  /* @__PURE__ */ jsxs("label", { className: radioClass(orientation === "portrait"), children: [
28153
27274
  /* @__PURE__ */ jsx(
28154
- "input",
27275
+ WebRadio,
28155
27276
  {
28156
- type: "radio",
28157
27277
  name: "orientation",
28158
27278
  className: "sr-only",
28159
27279
  checked: orientation === "portrait",
@@ -28169,9 +27289,8 @@ function PrintSettingsPanel({
28169
27289
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2 flex-wrap", children: [
28170
27290
  /* @__PURE__ */ jsxs("label", { className: radioClass(colorMode === "color"), children: [
28171
27291
  /* @__PURE__ */ jsx(
28172
- "input",
27292
+ WebRadio,
28173
27293
  {
28174
- type: "radio",
28175
27294
  name: "colorMode",
28176
27295
  className: "sr-only",
28177
27296
  checked: colorMode === "color",
@@ -28182,9 +27301,8 @@ function PrintSettingsPanel({
28182
27301
  ] }),
28183
27302
  /* @__PURE__ */ jsxs("label", { className: radioClass(colorMode === "grayscale"), children: [
28184
27303
  /* @__PURE__ */ jsx(
28185
- "input",
27304
+ WebRadio,
28186
27305
  {
28187
- type: "radio",
28188
27306
  name: "colorMode",
28189
27307
  className: "sr-only",
28190
27308
  checked: colorMode === "grayscale",
@@ -28195,9 +27313,8 @@ function PrintSettingsPanel({
28195
27313
  ] }),
28196
27314
  /* @__PURE__ */ jsxs("label", { className: radioClass(colorMode === "blackAndWhite"), children: [
28197
27315
  /* @__PURE__ */ jsx(
28198
- "input",
27316
+ WebRadio,
28199
27317
  {
28200
- type: "radio",
28201
27318
  name: "colorMode",
28202
27319
  className: "sr-only",
28203
27320
  checked: colorMode === "blackAndWhite",
@@ -28234,7 +27351,6 @@ function PrintDialog({
28234
27351
  const { viewportWidth } = useIsMobile();
28235
27352
  const touchTargetPx = getDensePanelTouchTargetPx(viewportWidth);
28236
27353
  const closeBtnStyle = { minWidth: touchTargetPx, minHeight: touchTargetPx };
28237
- const footerBtnStyle = { minHeight: touchTargetPx };
28238
27354
  const printOptionDefaults = resolveDefaultPrintSettings(useViewerOptionsContext());
28239
27355
  const [printWhat, setPrintWhat] = useState(printOptionDefaults?.printWhat ?? "slides");
28240
27356
  const [orientation, setOrientation] = useState("landscape");
@@ -28407,31 +27523,21 @@ function PrintDialog({
28407
27523
  pages: pageCount,
28408
27524
  slides: slideCount
28409
27525
  }) }),
28410
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
28411
- /* @__PURE__ */ jsx(
28412
- "button",
28413
- {
28414
- type: "button",
28415
- onClick: onClose,
28416
- style: footerBtnStyle,
28417
- className: "px-4 py-2 text-sm rounded-lg border border-border text-muted-foreground hover:text-foreground hover:bg-accent transition-colors",
28418
- children: t("pptx.common.cancel")
28419
- }
28420
- ),
28421
- /* @__PURE__ */ jsxs(
28422
- "button",
28423
- {
28424
- type: "button",
28425
- onClick: handlePrint,
28426
- style: footerBtnStyle,
28427
- className: "px-4 py-2 text-sm rounded-lg bg-primary text-white hover:bg-primary/90 transition-colors flex items-center gap-1.5",
28428
- children: [
28429
- /* @__PURE__ */ jsx(LuPrinter, { className: "w-3.5 h-3.5" }),
28430
- t("pptx.print.printButton")
28431
- ]
28432
- }
28433
- )
28434
- ] })
27526
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsx(
27527
+ DialogFooter,
27528
+ {
27529
+ actions: [
27530
+ { id: "cancel", label: t("pptx.common.cancel") },
27531
+ {
27532
+ id: "print",
27533
+ label: t("pptx.print.printButton"),
27534
+ variant: "primary",
27535
+ icon: "print"
27536
+ }
27537
+ ],
27538
+ onAction: (id) => id === "print" ? handlePrint() : onClose()
27539
+ }
27540
+ ) })
28435
27541
  ] })
28436
27542
  ]
28437
27543
  }
@@ -28506,9 +27612,8 @@ function ShowSlidesFieldset({
28506
27612
  /* @__PURE__ */ jsx("legend", { className: "text-[11px] font-medium text-muted-foreground uppercase tracking-wide mb-1", children: t("pptx.slideShow.showSlides") }),
28507
27613
  /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
28508
27614
  /* @__PURE__ */ jsx(
28509
- "input",
27615
+ WebRadio,
28510
27616
  {
28511
- type: "radio",
28512
27617
  name: "showSlides",
28513
27618
  value: "all",
28514
27619
  checked: showSlidesMode === "all",
@@ -28520,9 +27625,8 @@ function ShowSlidesFieldset({
28520
27625
  ] }),
28521
27626
  /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
28522
27627
  /* @__PURE__ */ jsx(
28523
- "input",
27628
+ WebRadio,
28524
27629
  {
28525
- type: "radio",
28526
27630
  name: "showSlides",
28527
27631
  value: "range",
28528
27632
  checked: showSlidesMode === "range",
@@ -28576,9 +27680,8 @@ function ShowSlidesFieldset({
28576
27680
  customShows.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
28577
27681
  /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
28578
27682
  /* @__PURE__ */ jsx(
28579
- "input",
27683
+ WebRadio,
28580
27684
  {
28581
- type: "radio",
28582
27685
  name: "showSlides",
28583
27686
  value: "customShow",
28584
27687
  checked: showSlidesMode === "customShow",
@@ -28669,9 +27772,8 @@ function SetUpSlideShowDialog({
28669
27772
  ["kiosk", t("pptx.slideShow.browsedAtKiosk")]
28670
27773
  ].map(([value, label]) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
28671
27774
  /* @__PURE__ */ jsx(
28672
- "input",
27775
+ WebRadio,
28673
27776
  {
28674
- type: "radio",
28675
27777
  name: "showType",
28676
27778
  value,
28677
27779
  checked: showType === value,
@@ -28699,9 +27801,8 @@ function SetUpSlideShowDialog({
28699
27801
  /* @__PURE__ */ jsx("legend", { className: "text-[11px] font-medium text-muted-foreground uppercase tracking-wide mb-1", children: t("pptx.slideShow.advanceSlides") }),
28700
27802
  /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
28701
27803
  /* @__PURE__ */ jsx(
28702
- "input",
27804
+ WebRadio,
28703
27805
  {
28704
- type: "radio",
28705
27806
  name: "advanceMode",
28706
27807
  value: "manual",
28707
27808
  checked: draft.advanceMode === "manual",
@@ -28713,9 +27814,8 @@ function SetUpSlideShowDialog({
28713
27814
  ] }),
28714
27815
  /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
28715
27816
  /* @__PURE__ */ jsx(
28716
- "input",
27817
+ WebRadio,
28717
27818
  {
28718
- type: "radio",
28719
27819
  name: "advanceMode",
28720
27820
  value: "useTimings",
28721
27821
  checked: (draft.advanceMode ?? "useTimings") === "useTimings",
@@ -28728,26 +27828,16 @@ function SetUpSlideShowDialog({
28728
27828
  ] }),
28729
27829
  /* @__PURE__ */ jsx(ShowOptionsFieldset, { draft, update })
28730
27830
  ] }),
28731
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 px-5 py-3 border-t border-border shrink-0", children: [
28732
- /* @__PURE__ */ jsx(
28733
- "button",
28734
- {
28735
- type: "button",
28736
- onClick: onClose,
28737
- className: "px-3 py-1.5 rounded bg-muted hover:bg-accent text-[12px] text-foreground transition-colors",
28738
- children: t("pptx.common.cancel")
28739
- }
28740
- ),
28741
- /* @__PURE__ */ jsx(
28742
- "button",
28743
- {
28744
- type: "button",
28745
- onClick: handleSave,
28746
- className: "px-3 py-1.5 rounded bg-primary hover:bg-primary/80 text-[12px] text-white transition-colors",
28747
- children: t("pptx.common.ok")
28748
- }
28749
- )
28750
- ] })
27831
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end gap-2 px-5 py-3 border-t border-border shrink-0", children: /* @__PURE__ */ jsx(
27832
+ DialogFooter,
27833
+ {
27834
+ actions: [
27835
+ { id: "cancel", label: t("pptx.common.cancel") },
27836
+ { id: "ok", label: t("pptx.common.ok"), variant: "primary" }
27837
+ ],
27838
+ onAction: (id) => id === "ok" ? handleSave() : onClose()
27839
+ }
27840
+ ) })
28751
27841
  ] })
28752
27842
  }
28753
27843
  )
@@ -28887,27 +27977,21 @@ function BroadcastDialog({
28887
27977
  onServerUrlChange: setServerUrl
28888
27978
  }
28889
27979
  ) }),
28890
- !isBroadcasting && /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 px-5 py-3 border-t border-border", children: [
28891
- /* @__PURE__ */ jsx(
28892
- "button",
28893
- {
28894
- type: "button",
28895
- onClick: onClose,
28896
- className: "px-3 py-1.5 rounded bg-muted hover:bg-accent text-[12px] text-foreground transition-colors",
28897
- children: t("pptx.common.close")
28898
- }
28899
- ),
28900
- /* @__PURE__ */ jsx(
28901
- "button",
28902
- {
28903
- type: "button",
28904
- disabled: !canStart,
28905
- onClick: handleStartBroadcast,
28906
- className: "px-3 py-1.5 rounded bg-primary hover:bg-primary/90 text-[12px] text-white transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
28907
- children: t("pptx.broadcast.startBroadcast")
28908
- }
28909
- )
28910
- ] })
27980
+ !isBroadcasting && /* @__PURE__ */ jsx("div", { className: "flex justify-end gap-2 px-5 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
27981
+ DialogFooter,
27982
+ {
27983
+ actions: [
27984
+ { id: "close", label: t("pptx.common.close") },
27985
+ {
27986
+ id: "start",
27987
+ label: t("pptx.broadcast.startBroadcast"),
27988
+ variant: "primary",
27989
+ disabled: !canStart
27990
+ }
27991
+ ],
27992
+ onAction: (id) => id === "start" ? handleStartBroadcast() : onClose()
27993
+ }
27994
+ ) })
28911
27995
  ]
28912
27996
  }
28913
27997
  )
@@ -29429,33 +28513,29 @@ function ShareDialog({
29429
28513
  onRetry: collab?.retry
29430
28514
  }
29431
28515
  ) }),
29432
- /* @__PURE__ */ jsxs(
28516
+ /* @__PURE__ */ jsx(
29433
28517
  "div",
29434
28518
  {
29435
28519
  className: `flex justify-end gap-2 px-5 py-3 border-t border-border ${stickyFooterClass}`,
29436
- children: [
29437
- /* @__PURE__ */ jsx(
29438
- "button",
29439
- {
29440
- type: "button",
29441
- onClick: onClose,
29442
- style: touchBtnStyle,
29443
- className: "px-3 py-1.5 rounded bg-muted hover:bg-accent text-[12px] text-foreground transition-colors inline-flex items-center justify-center",
29444
- children: isActive ? t("pptx.share.close") : t("pptx.share.cancel")
29445
- }
29446
- ),
29447
- !isActive && /* @__PURE__ */ jsx(
29448
- "button",
29449
- {
29450
- type: "button",
29451
- disabled: !canStart,
29452
- onClick: handleStartSharing,
29453
- style: touchBtnStyle,
29454
- className: "px-3 py-1.5 rounded bg-primary hover:bg-primary/90 text-[12px] text-white transition-colors disabled:opacity-40 disabled:cursor-not-allowed inline-flex items-center justify-center",
29455
- children: t(mode === "join" ? "pptx.share.joinSession" : "pptx.share.startSharing")
29456
- }
29457
- )
29458
- ]
28520
+ children: /* @__PURE__ */ jsx(
28521
+ DialogFooter,
28522
+ {
28523
+ actions: [
28524
+ { id: "cancel", label: isActive ? t("pptx.share.close") : t("pptx.share.cancel") },
28525
+ ...isActive ? [] : [
28526
+ {
28527
+ id: "start",
28528
+ label: t(
28529
+ mode === "join" ? "pptx.share.joinSession" : "pptx.share.startSharing"
28530
+ ),
28531
+ variant: "primary",
28532
+ disabled: !canStart
28533
+ }
28534
+ ]
28535
+ ],
28536
+ onAction: (id) => id === "start" ? handleStartSharing() : onClose()
28537
+ }
28538
+ )
29459
28539
  }
29460
28540
  )
29461
28541
  ]
@@ -29757,26 +28837,16 @@ function HyperlinkEditDialog({
29757
28837
  onEnterConfirm: handleConfirm
29758
28838
  }
29759
28839
  ),
29760
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 px-4 py-3 border-t border-border", children: [
29761
- /* @__PURE__ */ jsx(
29762
- "button",
29763
- {
29764
- type: "button",
29765
- className: "px-3 py-1.5 text-xs rounded border border-border text-foreground hover:bg-muted",
29766
- onClick: onCancel,
29767
- children: t("pptx.common.cancel")
29768
- }
29769
- ),
29770
- /* @__PURE__ */ jsx(
29771
- "button",
29772
- {
29773
- type: "button",
29774
- className: "px-3 py-1.5 text-xs rounded bg-primary text-white hover:bg-primary/90",
29775
- onClick: handleConfirm,
29776
- children: t("pptx.common.apply")
29777
- }
29778
- )
29779
- ] })
28840
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end gap-2 px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
28841
+ DialogFooter,
28842
+ {
28843
+ actions: [
28844
+ { id: "cancel", label: t("pptx.common.cancel") },
28845
+ { id: "apply", label: t("pptx.common.apply"), variant: "primary" }
28846
+ ],
28847
+ onAction: (id) => id === "apply" ? handleConfirm() : onCancel()
28848
+ }
28849
+ ) })
29780
28850
  ]
29781
28851
  }
29782
28852
  )
@@ -30240,7 +29310,7 @@ function ViewerToolbarSection(props) {
30240
29310
  },
30241
29311
  [activeSlide, propertyHandlers]
30242
29312
  );
30243
- const scopedLayoutOptions = React99.useMemo(
29313
+ const scopedLayoutOptions = React97.useMemo(
30244
29314
  () => scopeLayoutOptionsToActiveSlide(s.layoutOptions, activeSlide),
30245
29315
  [s.layoutOptions, activeSlide]
30246
29316
  );
@@ -30878,27 +29948,21 @@ function EquationEditorDialog({
30878
29948
  }) })
30879
29949
  ] })
30880
29950
  ] }),
30881
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 px-5 py-3 border-t border-border", children: [
30882
- /* @__PURE__ */ jsx(
30883
- "button",
30884
- {
30885
- type: "button",
30886
- onClick: onClose,
30887
- className: "px-4 py-1.5 rounded-lg text-xs text-foreground hover:bg-accent transition-colors",
30888
- children: t("pptx.equation.cancel", "Cancel")
30889
- }
30890
- ),
30891
- /* @__PURE__ */ jsx(
30892
- "button",
30893
- {
30894
- type: "button",
30895
- onClick: handleInsert,
30896
- disabled: !hasContent,
30897
- className: "px-4 py-1.5 rounded-lg text-xs font-medium bg-primary hover:bg-primary/80 text-white disabled:opacity-40 disabled:cursor-not-allowed transition-colors",
30898
- children: isEditing ? t("pptx.equation.update", "Update") : t("pptx.equation.insert", "Insert")
30899
- }
30900
- )
30901
- ] })
29951
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 px-5 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
29952
+ DialogFooter,
29953
+ {
29954
+ actions: [
29955
+ { id: "cancel", label: t("pptx.equation.cancel", "Cancel") },
29956
+ {
29957
+ id: "insert",
29958
+ label: isEditing ? t("pptx.equation.update", "Update") : t("pptx.equation.insert", "Insert"),
29959
+ variant: "primary",
29960
+ disabled: !hasContent
29961
+ }
29962
+ ],
29963
+ onAction: (id) => id === "insert" ? handleInsert() : onClose()
29964
+ }
29965
+ ) })
30902
29966
  ]
30903
29967
  }
30904
29968
  )
@@ -31061,30 +30125,21 @@ function InsertSmartArtDialog({
31061
30125
  }
31062
30126
  ) })
31063
30127
  ] }),
31064
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-border", children: [
31065
- /* @__PURE__ */ jsx(
31066
- "button",
31067
- {
31068
- type: "button",
31069
- onClick: onClose,
31070
- className: "px-3 py-1.5 text-xs rounded bg-muted hover:bg-accent text-foreground transition-colors",
31071
- children: t("pptx.smartart.cancel")
31072
- }
31073
- ),
31074
- /* @__PURE__ */ jsx(
31075
- "button",
31076
- {
31077
- type: "button",
31078
- onClick: handleInsert,
31079
- disabled: !selectedLayout,
31080
- className: cn(
31081
- "px-3 py-1.5 text-xs rounded transition-colors",
31082
- selectedLayout ? "bg-primary hover:bg-primary/80 text-white" : "bg-muted text-muted-foreground cursor-not-allowed"
31083
- ),
31084
- children: t("pptx.smartart.insert")
31085
- }
31086
- )
31087
- ] })
30128
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-border", children: /* @__PURE__ */ jsx(
30129
+ DialogFooter,
30130
+ {
30131
+ actions: [
30132
+ { id: "cancel", label: t("pptx.smartart.cancel") },
30133
+ {
30134
+ id: "insert",
30135
+ label: t("pptx.smartart.insert"),
30136
+ variant: "primary",
30137
+ disabled: !selectedLayout
30138
+ }
30139
+ ],
30140
+ onAction: (id) => id === "insert" ? handleInsert() : onClose()
30141
+ }
30142
+ ) })
31088
30143
  ]
31089
30144
  }
31090
30145
  )
@@ -32185,7 +31240,7 @@ function useTableStyleMapHandlers(input) {
32185
31240
  var AiChatPanel = lazy(async () => {
32186
31241
  const [{ useChat }, { default: Panel }] = await Promise.all([
32187
31242
  import('@ai-sdk/react'),
32188
- import('./AiChatPanel-BIS3OYZ2.mjs')
31243
+ import('./AiChatPanel-QEOFQGNY.mjs')
32189
31244
  ]);
32190
31245
  function BoundAiChatPanel(props) {
32191
31246
  return /* @__PURE__ */ jsx(Panel, { ...props, useChat });
@@ -33506,28 +32561,21 @@ function HeaderFooterPanel({
33506
32561
  }
33507
32562
  ) })
33508
32563
  ] }),
33509
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-border px-4 py-3", children: [
33510
- /* @__PURE__ */ jsx(
33511
- "button",
33512
- {
33513
- type: "button",
33514
- onClick: onApplyToAll,
33515
- "data-testid": "hf-apply-all",
33516
- className: "rounded bg-accent px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent/80 transition-colors",
33517
- children: t("pptx.headerFooter.applyToAll")
33518
- }
33519
- ),
33520
- /* @__PURE__ */ jsx(
33521
- "button",
33522
- {
33523
- type: "button",
33524
- onClick: onApplyToCurrent,
33525
- "data-testid": "hf-apply-current",
33526
- className: "rounded bg-primary px-3 py-1.5 text-xs font-medium text-white hover:bg-primary/80 transition-colors",
33527
- children: t("pptx.headerFooter.applyToCurrent")
33528
- }
33529
- )
33530
- ] })
32564
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 border-t border-border px-4 py-3", children: /* @__PURE__ */ jsx(
32565
+ DialogFooter,
32566
+ {
32567
+ actions: [
32568
+ { id: "applyAll", label: t("pptx.headerFooter.applyToAll"), testId: "hf-apply-all" },
32569
+ {
32570
+ id: "applyCurrent",
32571
+ label: t("pptx.headerFooter.applyToCurrent"),
32572
+ variant: "primary",
32573
+ testId: "hf-apply-current"
32574
+ }
32575
+ ],
32576
+ onAction: (id) => id === "applyAll" ? onApplyToAll() : onApplyToCurrent()
32577
+ }
32578
+ ) })
33531
32579
  ] }) });
33532
32580
  }
33533
32581
  function MobileBottomBar(p) {