pptx-react-viewer 2.11.1 → 2.12.1

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 (117) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/{AiChatPanel-RMQIJDUJ.mjs → AiChatPanel-CGGUPVQX.mjs} +4 -4
  3. package/dist/AiChatPanel-CGGUPVQX.mjs.br +0 -0
  4. package/dist/AiChatPanel-CGGUPVQX.mjs.gz +0 -0
  5. package/dist/{AiChatPanel-E6W3EACA.js → AiChatPanel-UEFYTUJN.js} +23 -23
  6. package/dist/AiChatPanel-UEFYTUJN.js.br +0 -0
  7. package/dist/AiChatPanel-UEFYTUJN.js.gz +0 -0
  8. package/dist/{Model3DScene-U4B4NZJT.js → Model3DScene-QYXJNALP.js} +2 -2
  9. package/dist/{Model3DScene-U4B4NZJT.js.br → Model3DScene-QYXJNALP.js.br} +0 -0
  10. package/dist/Model3DScene-QYXJNALP.js.gz +0 -0
  11. package/dist/{Model3DScene-WHSHBMR5.mjs → Model3DScene-TU4NTHRM.mjs} +1 -1
  12. package/dist/Model3DScene-TU4NTHRM.mjs.br +0 -0
  13. package/dist/Model3DScene-TU4NTHRM.mjs.gz +0 -0
  14. package/dist/{SurfaceChart3DScene-5S43UBRD.js → SurfaceChart3DScene-4VCO3DRP.js} +2 -2
  15. package/dist/SurfaceChart3DScene-4VCO3DRP.js.br +0 -0
  16. package/dist/SurfaceChart3DScene-4VCO3DRP.js.gz +0 -0
  17. package/dist/{SurfaceChart3DScene-77JP5XH5.mjs → SurfaceChart3DScene-VTJBKUQY.mjs} +1 -1
  18. package/dist/{SurfaceChart3DScene-77JP5XH5.mjs.br → SurfaceChart3DScene-VTJBKUQY.mjs.br} +0 -0
  19. package/dist/SurfaceChart3DScene-VTJBKUQY.mjs.gz +0 -0
  20. package/dist/{chunk-NJ4PTG4F.mjs → chunk-4GYNTY2G.mjs} +28 -48
  21. package/dist/chunk-4GYNTY2G.mjs.br +0 -0
  22. package/dist/chunk-4GYNTY2G.mjs.gz +0 -0
  23. package/dist/{chunk-PXYZFWDA.mjs → chunk-4SGXEGVL.mjs} +339 -256
  24. package/dist/chunk-4SGXEGVL.mjs.br +0 -0
  25. package/dist/chunk-4SGXEGVL.mjs.gz +0 -0
  26. package/dist/{chunk-IOVOQ6ZJ.js → chunk-BXAK3JFM.js} +301 -1
  27. package/dist/chunk-BXAK3JFM.js.br +0 -0
  28. package/dist/chunk-BXAK3JFM.js.gz +0 -0
  29. package/dist/{chunk-FV7HEYCX.mjs → chunk-CABQXGPI.mjs} +621 -70
  30. package/dist/chunk-CABQXGPI.mjs.br +0 -0
  31. package/dist/chunk-CABQXGPI.mjs.gz +0 -0
  32. package/dist/{chunk-IXBM3HWH.js → chunk-GBKIWNW6.js} +2047 -1964
  33. package/dist/chunk-GBKIWNW6.js.br +0 -0
  34. package/dist/chunk-GBKIWNW6.js.gz +0 -0
  35. package/dist/{chunk-FAP6OPLL.js → chunk-LE6YA5WB.js} +262 -296
  36. package/dist/chunk-LE6YA5WB.js.br +0 -0
  37. package/dist/chunk-LE6YA5WB.js.gz +0 -0
  38. package/dist/{chunk-HF6L2CTF.mjs → chunk-N3NKU7SC.mjs} +1 -1
  39. package/dist/chunk-N3NKU7SC.mjs.br +0 -0
  40. package/dist/{chunk-HF6L2CTF.mjs.gz → chunk-N3NKU7SC.mjs.gz} +0 -0
  41. package/dist/{chunk-QT6BPOZM.js → chunk-NUDH7TI2.js} +355 -375
  42. package/dist/chunk-NUDH7TI2.js.br +0 -0
  43. package/dist/chunk-NUDH7TI2.js.gz +0 -0
  44. package/dist/{chunk-KDJBWJJH.js → chunk-TDUDH7S4.js} +648 -71
  45. package/dist/chunk-TDUDH7S4.js.br +0 -0
  46. package/dist/chunk-TDUDH7S4.js.gz +0 -0
  47. package/dist/{chunk-RHR7GTDX.mjs → chunk-TEXIGSA6.mjs} +301 -1
  48. package/dist/chunk-TEXIGSA6.mjs.br +0 -0
  49. package/dist/chunk-TEXIGSA6.mjs.gz +0 -0
  50. package/dist/{chunk-X3SFCKAF.js → chunk-UIWY4XJT.js} +3 -3
  51. package/dist/chunk-UIWY4XJT.js.br +0 -0
  52. package/dist/chunk-UIWY4XJT.js.gz +0 -0
  53. package/dist/{chunk-DD54KUDG.mjs → chunk-YIPR3GKG.mjs} +24 -58
  54. package/dist/chunk-YIPR3GKG.mjs.br +0 -0
  55. package/dist/chunk-YIPR3GKG.mjs.gz +0 -0
  56. package/dist/i18n.js +4 -4
  57. package/dist/i18n.js.br +0 -0
  58. package/dist/i18n.js.gz +0 -0
  59. package/dist/i18n.mjs +1 -1
  60. package/dist/i18n.mjs.br +0 -0
  61. package/dist/i18n.mjs.gz +0 -0
  62. package/dist/index.js +36 -36
  63. package/dist/index.js.br +0 -0
  64. package/dist/index.js.gz +0 -0
  65. package/dist/index.mjs +6 -6
  66. package/dist/index.mjs.br +0 -0
  67. package/dist/index.mjs.gz +0 -0
  68. package/dist/internals.d.ts.map +1 -1
  69. package/dist/internals.js +79 -79
  70. package/dist/internals.js.br +0 -0
  71. package/dist/internals.js.gz +0 -0
  72. package/dist/internals.mjs +4 -4
  73. package/dist/internals.mjs.br +0 -0
  74. package/dist/internals.mjs.gz +0 -0
  75. package/dist/pptx-viewer.css +1 -1
  76. package/dist/pptx-viewer.css.br +0 -0
  77. package/dist/pptx-viewer.css.gz +0 -0
  78. package/dist/viewer/index.js +22 -22
  79. package/dist/viewer/index.js.br +0 -0
  80. package/dist/viewer/index.js.gz +0 -0
  81. package/dist/viewer/index.mjs +6 -6
  82. package/dist/viewer/index.mjs.br +0 -0
  83. package/dist/viewer/index.mjs.gz +0 -0
  84. package/package.json +1 -1
  85. package/dist/AiChatPanel-E6W3EACA.js.br +0 -0
  86. package/dist/AiChatPanel-E6W3EACA.js.gz +0 -0
  87. package/dist/AiChatPanel-RMQIJDUJ.mjs.br +0 -0
  88. package/dist/AiChatPanel-RMQIJDUJ.mjs.gz +0 -0
  89. package/dist/Model3DScene-U4B4NZJT.js.gz +0 -0
  90. package/dist/Model3DScene-WHSHBMR5.mjs.br +0 -0
  91. package/dist/Model3DScene-WHSHBMR5.mjs.gz +0 -0
  92. package/dist/SurfaceChart3DScene-5S43UBRD.js.br +0 -0
  93. package/dist/SurfaceChart3DScene-5S43UBRD.js.gz +0 -0
  94. package/dist/SurfaceChart3DScene-77JP5XH5.mjs.gz +0 -0
  95. package/dist/chunk-DD54KUDG.mjs.br +0 -0
  96. package/dist/chunk-DD54KUDG.mjs.gz +0 -0
  97. package/dist/chunk-FAP6OPLL.js.br +0 -0
  98. package/dist/chunk-FAP6OPLL.js.gz +0 -0
  99. package/dist/chunk-FV7HEYCX.mjs.br +0 -0
  100. package/dist/chunk-FV7HEYCX.mjs.gz +0 -0
  101. package/dist/chunk-HF6L2CTF.mjs.br +0 -0
  102. package/dist/chunk-IOVOQ6ZJ.js.br +0 -0
  103. package/dist/chunk-IOVOQ6ZJ.js.gz +0 -0
  104. package/dist/chunk-IXBM3HWH.js.br +0 -0
  105. package/dist/chunk-IXBM3HWH.js.gz +0 -0
  106. package/dist/chunk-KDJBWJJH.js.br +0 -0
  107. package/dist/chunk-KDJBWJJH.js.gz +0 -0
  108. package/dist/chunk-NJ4PTG4F.mjs.br +0 -0
  109. package/dist/chunk-NJ4PTG4F.mjs.gz +0 -0
  110. package/dist/chunk-PXYZFWDA.mjs.br +0 -0
  111. package/dist/chunk-PXYZFWDA.mjs.gz +0 -0
  112. package/dist/chunk-QT6BPOZM.js.br +0 -0
  113. package/dist/chunk-QT6BPOZM.js.gz +0 -0
  114. package/dist/chunk-RHR7GTDX.mjs.br +0 -0
  115. package/dist/chunk-RHR7GTDX.mjs.gz +0 -0
  116. package/dist/chunk-X3SFCKAF.js.br +0 -0
  117. package/dist/chunk-X3SFCKAF.js.gz +0 -0
@@ -1,12 +1,12 @@
1
- import { computeFocusTargets, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, toRenderableParts } from './chunk-HF6L2CTF.mjs';
2
- import { useReducedMotion, useViewerState, useViewerOptions, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useYjsDocumentSync, useCollaborationLivePatch, useFollowMode, useBroadcastFollower, scopeLayoutOptionsToActiveSlide, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, useCollaborativeState, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, downloadBlob } from './chunk-NJ4PTG4F.mjs';
3
- import { SHAPE_PRESETS, DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, MIN_ELEMENT_SIZE, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, ANIMATION_PRESET_OPTIONS, resolvePalette, resolveStyle, layoutToCategory, wrapChrome, DEFAULT_FILL_COLOR, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, getCropShapeClipPath, SLIDE_NAV_THUMBNAIL_WIDTH, styleShadow, styleStroke, colour, fitFontSize, smartArtNodeGroupProps, chevronPoints, SmartArtNodeText, truncate, renderStepDownProcess, renderAlternatingFlow, renderDescendingProcess, renderPictureAccentList, renderVerticalBlockList, renderGroupedList, renderPyramidList, renderHorizontalPictureList, renderAccentProcess, renderVerticalChevronList, isImageTiled, getImageTilingStyle, getDuotoneColors, getTextWarpStyle, renderTextSegments, buildReactChartViewModel, renderChartElement, buildTextBody3DSceneStyle, TOOLBAR_SECTIONS, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, buildTree, treeWidth, treeDepth, nodeOpacity, gearPath, resolveSmartArtDataPalette, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, HYPERLINK_COLOR, GRID_SIZE, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, THEME_COLOR_SWATCHES, STROKE_DASH_OPTIONS } from './chunk-DD54KUDG.mjs';
4
- import { LOCALE_CATALOG, translationsEn } from './chunk-RHR7GTDX.mjs';
5
- import { hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, getElementTransform, ACTION_BUTTON_PRESETS, isEditableTextElement, isElementRendered, isElementActionable, getAriaRole, getAriaLabel, getAriaRoleDescription, getImageEffectsOpacity, getImageEffectsFilter, getElementTransformWithoutRotation, SWITCHABLE_LAYOUT_TYPES, DEFAULT_VIEWER_OPTIONS, compileEquationTemplateMathMl, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, viewerOptionsToPreferences, applyPreferenceToOptions, listAutosaveSnapshots, deleteAutosaveSnapshot, RULER_THICKNESS, RULER_FONT_SIZE, revealedSmartArtNodeCount, buildSmartArtA11y, buildCssGradientFromShapeStyle, resolveGroupChildFill, getGroupChildParentFill, getComputedEffectStyle, getSoftEdgeSvgFilter, buildStrokeOutline, svgGradientFillRef, isInkElement, getElementLabel, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, themeToCssVars, applyMotionPathPreset, DEFAULT_INSERT_CHART_TYPE, hasCopyableFormat, createBackstagePresentation, printPropertiesFrameSlides, printPropertiesSlidesPerPage, VIEWER_OPTIONS_TABS, DEFAULT_QUICK_ACCESS_COMMAND_IDS, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, resolveDrawingShapeNodeId, buildSummaryZoomView, getImageColorWashStyle, isImageLikeElement, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, applyChartBuildReveal, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleTypeColor, getOleTypeLabel, filterRenderedElements, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, getSlideBackgroundStyle, filterCommands, resolveTitleBarStatusKey, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, buildFieldSubstitutionContext, shouldConfirmExternalHyperlink, safeOpenUrl, isPpactionUrl, parsePpactionUrl, isPresentationAdvanceClick, buildContextMenuEntries, themeColorSchemesEqual, STATUS_BAR_CLASSES, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, clampPercent, HANDOUT_OPTIONS, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS, resolveViewerAddinRows, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, activateModalFocus, buildCollaborationShareUrl, canGoPrevious, formatSlideCounter, READING_VIEW_COUNTER_ATTR, canGoNext, READING_VIEW_ATTR, OUTLINE_LEVEL_ATTR, OUTLINE_SLIDE_ATTR, OUTLINE_ROW_ATTR, OUTLINE_VIEW_ATTR, mobileElapsedSince, nextPresentedSlide, isFirstSlide, isLastSlide, formatMobileElapsed, mobileSlideCounter, presenterPaneAdvancesOnClick, formatElapsed, computeInlineEditorRect, findSmartArtNodeText, setSmartArtNodeStyle, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, updateSmartArtNodeText, getImageSvgFilters, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, findChartPartTarget, dragValueForPart, withChartPointValue, dragAnchorViewY, withChartTitle, computeSmartArtLayout, buildSmartArt3DModel, extractPathPoints, generatePressureCircles, isBrowserOpenableMime, formatBytes, getOleBadgeLabel, openUrlInNewTab, getSubstituteFontFamily, getWarpPath, extraQuickAccessCommands, TAB_ROW_ACTION_CLASSES, listBackstageRecentFiles, BACKSTAGE_NAV, INSERT_CHART_TYPES, DEFAULT_MOTION_PATH_PRESET_ID, SLIDE_VIRTUALIZATION_THRESHOLD, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES, presentationInkPath, motionPathFor, setMotionPath, getShapeAdjustmentHandleDescriptor, PRESET_THEMES, isUrlSafe, sanitizeMathMl, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, QUICK_ACCESS_COMMAND_CATALOG, openReadingView, applyReadingViewCommand, createPresentationKeyBuffer, readingViewFitScale, READING_VIEW_STAGE_ATTR, buildOutline, applyOutlineEdit, mapOutlineKey, notesSegmentsToSpans, erasePresentationInkAt, movePresenterPointer, appendPresentationInkPoint, NOTES_FONT_SIZE_DEFAULT, formatTime, NOTES_FONT_SIZE_MIN, clampNotesFontSize, NOTES_FONT_SIZE_STEP, NOTES_FONT_SIZE_MAX, groupIntoParagraphs, substituteFieldText, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, ENTRANCE_PRESET_VALUES, EMPHASIS_PRESET_VALUES, EXIT_PRESET_VALUES, MOTION_PATH_FAMILIES, motionPathFamilyLabelKey, motionPathPresetsByFamily, motionPathPresetLabelKey, getConnectionSites, generateTicks, rulerDragToGuidePosition, getCommentMarkerPosition, motionPathToSvgD, motionPathEndPixel, isEditableMotionPath, setMotionPathEnd, buildThemeColorGrid, THEME_COLOR_SCHEME_KEYS, THEME_COLOR_LABELS, COMMON_FONTS, buildSmartArtPresetData, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, mergeSlideTransition, buildTableDataGrid, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, chartDataChangeType, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, getOleObjectTypeLabel, sanitizeGradientStops, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, TRANSITION_VALID_DIRECTIONS, TRANSITION_ORIENTATION_TYPES, clampTransitionNumber, flattenTagCollections, formatCommentTimestamp, clearMotionPath, DIRECTIONAL_PRESETS, motionPathPresetIdForPath, computeMergeCellRight, computeMergeCellDown, computeSplitCell, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, addSmartArtNodeAsChild, removeSmartArtNode, clampCropValue, DUOTONE_PRESETS, ARTISTIC_EFFECTS, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, toSlideIndex, elementActionToPptxAction, canCommitActionType, TRANSITION_DIR_ARROWS, buildDirectionGrid, updateTagInCollections, deleteTagFromCollections, addTagToCollections, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, switchSmartArtLayout, addSmartArtNode, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode, SHAPE_QUICK_STYLES, quickStyleSwatchCss, getPatternSvg, TEXT_WARP_PRESETS, warpPreviewPath, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS } from './chunk-FV7HEYCX.mjs';
6
- import React34, { createContext, useMemo, useState, useCallback, lazy, forwardRef, useEffect, useRef, useContext, Suspense, useLayoutEffect, Fragment as Fragment$1, useDeferredValue } from 'react';
1
+ import { computeFocusTargets, aiChangeAnimationCss, changeGhostStyle, createChatHistoryStore, toRenderableParts } from './chunk-N3NKU7SC.mjs';
2
+ import { useReducedMotion, useViewerState, useViewerOptions, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useYjsDocumentSync, useCollaborationLivePatch, useFollowMode, useBroadcastFollower, scopeLayoutOptionsToActiveSlide, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, useCollaborativeState, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, downloadBlob } from './chunk-4GYNTY2G.mjs';
3
+ import { SHAPE_PRESETS, DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, MIN_ELEMENT_SIZE, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, ANIMATION_PRESET_OPTIONS, resolvePalette, resolveStyle, layoutToCategory, wrapChrome, DEFAULT_FILL_COLOR, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, getCropShapeClipPath, SLIDE_NAV_THUMBNAIL_WIDTH, styleShadow, styleStroke, colour, fitFontSize, smartArtNodeGroupProps, chevronPoints, SmartArtNodeText, truncate, renderStepDownProcess, renderAlternatingFlow, renderDescendingProcess, renderPictureAccentList, renderVerticalBlockList, renderGroupedList, renderPyramidList, renderHorizontalPictureList, renderAccentProcess, renderVerticalChevronList, isImageTiled, getImageTilingStyle, getDuotoneColors, getTextWarpStyle, renderTextSegments, buildReactChartViewModel, renderChartElement, buildTextBody3DSceneStyle, TOOLBAR_SECTIONS, SHORTCUT_REFERENCE_ITEMS as SHORTCUT_REFERENCE_ITEMS$1, buildTree, treeWidth, treeDepth, nodeOpacity, gearPath, resolveSmartArtDataPalette, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, HYPERLINK_COLOR, GRID_SIZE, CONNECTOR_ARROW_OPTIONS, ARROW_SIZE_OPTIONS, startMotionPathPreview, startPreviewAnimation, stopPreviewAnimation, THEME_COLOR_SWATCHES, STROKE_DASH_OPTIONS } from './chunk-YIPR3GKG.mjs';
4
+ import { LOCALE_CATALOG, translationsEn } from './chunk-TEXIGSA6.mjs';
5
+ import { hasShapeProperties, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, hasTextProperties, getElementTransform, ACTION_BUTTON_PRESETS, isEditableTextElement, isElementRendered, isElementActionable, getAriaRole, getAriaLabel, getAriaRoleDescription, getImageEffectsOpacity, getImageEffectsFilter, getElementTransformWithoutRotation, LINK_TOOLTIP_HOST_CLASS, SWITCHABLE_LAYOUT_TYPES, DEFAULT_VIEWER_OPTIONS, compileEquationTemplateMathMl, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, viewerOptionsToPreferences, applyPreferenceToOptions, listAutosaveSnapshots, deleteAutosaveSnapshot, RULER_THICKNESS, RULER_FONT_SIZE, revealedSmartArtNodeCount, buildSmartArtA11y, buildCssGradientFromShapeStyle, resolveGroupChildFill, getGroupChildParentFill, ensureActionAffordanceStyles, resolveElementActionAffordance, actionAffordanceLabels, getComputedEffectStyle, getSoftEdgeSvgFilter, buildStrokeOutline, svgGradientFillRef, mediaTransportVisible, isInkElement, getElementLabel, buildPreviewElements, deriveSlideFieldContext, SLIDE_TRANSITION_OPTIONS, hiddenSlideCue, HIDDEN_SLIDE_SLASH_GRADIENT, HIDDEN_SLIDE_LABEL_KEY, themeToCssVars, applyMotionPathPreset, DEFAULT_INSERT_CHART_TYPE, hasCopyableFormat, createBackstagePresentation, printPropertiesFrameSlides, printPropertiesSlidesPerPage, VIEWER_OPTIONS_TABS, DEFAULT_QUICK_ACCESS_COMMAND_IDS, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, resolveDrawingShapeNodeId, buildSummaryZoomView, getImageColorWashStyle, isImageLikeElement, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, applyChartBuildReveal, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleTypeColor, getOleTypeLabel, filterRenderedElements, isLinkedTextBox, getOverflowSegments, shouldUseSvgWarp, ACTION_INDICATOR_CLASS, ACTION_INDICATOR_ICON_PATH, LINK_TOOLTIP_CLASS, LINK_TOOLTIP_PANEL_CLASS, LINK_TOOLTIP_LABEL_CLASS, LINK_TOOLTIP_HINT_CLASS, getSlideBackgroundStyle, filterCommands, resolveTitleBarStatusKey, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, buildFieldSubstitutionContext, shouldConfirmExternalHyperlink, safeOpenUrl, isPpactionUrl, parsePpactionUrl, isPresentationAdvanceClick, PRESENT_TOOLBAR_CLASSES, buildContextMenuEntries, themeColorSchemesEqual, STATUS_BAR_CLASSES, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, compileLatexEquation, convertLatexToOmml, EQUATION_TEMPLATES, clampPercent, HANDOUT_OPTIONS, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS, resolveViewerAddinRows, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, activateModalFocus, buildCollaborationShareUrl, 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, computeInlineEditorRect, findSmartArtNodeText, setSmartArtNodeStyle, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, updateSmartArtNodeText, getImageSvgFilters, buildDuotoneCacheKey, getDuotoneCachedResult, applyDuotone, setDuotoneCachedResult, buildCacheKey, DEFAULT_COLOR_CHANGE_TOLERANCE, getCachedResult, applyColorChange, setCachedResult, findChartPartTarget, dragValueForPart, withChartPointValue, dragAnchorViewY, withChartTitle, computeSmartArtLayout, buildSmartArt3DModel, extractPathPoints, generatePressureCircles, isBrowserOpenableMime, formatBytes, getOleBadgeLabel, openUrlInNewTab, getSubstituteFontFamily, getWarpPath, extraQuickAccessCommands, TAB_ROW_ACTION_CLASSES, listBackstageRecentFiles, BACKSTAGE_NAV, INSERT_CHART_TYPES, DEFAULT_MOTION_PATH_PRESET_ID, SLIDE_VIRTUALIZATION_THRESHOLD, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES, presentationInkPath, motionPathFor, setMotionPath, getShapeAdjustmentHandleDescriptor, PRESENTER_NAVIGATOR_LABEL_KEYS, PEN_COLORS, HIGHLIGHTER_COLORS, PRESET_THEMES, isUrlSafe, sanitizeMathMl, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, QUICK_ACCESS_COMMAND_CATALOG, openReadingView, applyReadingViewCommand, createPresentationKeyBuffer, readingViewFitScale, READING_VIEW_STAGE_ATTR, buildOutline, applyOutlineEdit, mapOutlineKey, notesSegmentsToSpans, erasePresentationInkAt, movePresenterPointer, appendPresentationInkPoint, PRESENTER_CONSOLE_CONTROLS, NOTES_FONT_SIZE_DEFAULT, formatTime, NOTES_FONT_SIZE_MIN, clampNotesFontSize, NOTES_FONT_SIZE_STEP, NOTES_FONT_SIZE_MAX, groupIntoParagraphs, substituteFieldText, BACKSTAGE_TEMPLATES, formatBackstageDate, formatBackstageSize, backstageCardsFor, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, ENTRANCE_PRESET_VALUES, EMPHASIS_PRESET_VALUES, EXIT_PRESET_VALUES, MOTION_PATH_FAMILIES, motionPathFamilyLabelKey, motionPathPresetsByFamily, motionPathPresetLabelKey, getConnectionSites, generateTicks, rulerDragToGuidePosition, getCommentMarkerPosition, motionPathToSvgD, motionPathEndPixel, isEditableMotionPath, setMotionPathEnd, buildThemeColorGrid, THEME_COLOR_SCHEME_KEYS, THEME_COLOR_LABELS, COMMON_FONTS, buildSmartArtPresetData, handleReadingViewKey, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, mergeSlideTransition, buildTableDataGrid, appendTableElementRow, removeLastTableElementRow, appendTableElementColumn, removeLastTableElementColumn, removeTableElementColumn, removeTableElementRow, setTableElementCellText, TABLE_STYLE_PRESETS, chartDataChangeType, setChartCategoryLabel, setChartCellValue, addChartCategory, removeChartCategory, addChartSeries, removeChartSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, getOleObjectTypeLabel, sanitizeGradientStops, pptxActionToElementAction, withFrameSlides, withSlidesPerPage, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, schemaLabel, THEME_COLOR_SLOT_LABEL_KEYS, TRANSITION_VALID_DIRECTIONS, TRANSITION_ORIENTATION_TYPES, clampTransitionNumber, flattenTagCollections, formatCommentTimestamp, clearMotionPath, DIRECTIONAL_PRESETS, motionPathPresetIdForPath, computeMergeCellRight, computeMergeCellDown, computeSplitCell, SMARTART_COLOR_SCHEME_LABEL_KEYS, SMARTART_STYLE_LABEL_KEYS, addSmartArtNodeAsChild, removeSmartArtNode, clampCropValue, DUOTONE_PRESETS, ARTISTIC_EFFECTS, resolveActionType, ELEMENT_ACTION_TYPE_OPTIONS, toSlideIndex, elementActionToPptxAction, canCommitActionType, TRANSITION_DIR_ARROWS, buildDirectionGrid, updateTagInCollections, deleteTagFromCollections, addTagToCollections, animationEffectLabel, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, switchSmartArtLayout, addSmartArtNode, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode, SHAPE_QUICK_STYLES, quickStyleSwatchCss, getPatternSvg, TEXT_WARP_PRESETS, warpPreviewPath, text3dPtToEmu, text3dEmuToPt, MATERIAL_PRESETS, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS, FILL_PATTERN_LABEL_KEYS, openNativeEyeDropper, toggleText3dExtrusion, BEVEL_PRESETS } from './chunk-CABQXGPI.mjs';
6
+ import React35, { createContext, useMemo, useState, useCallback, lazy, forwardRef, useEffect, useRef, useContext, Suspense, useLayoutEffect, Fragment as Fragment$1, useDeferredValue } from 'react';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
8
  import { useTranslation } from 'react-i18next';
9
- import { LuRotateCw, LuMessageSquare, LuEyeOff, LuSettings, LuX, LuCalendarDays, LuHash, LuText, LuCast, LuSave, LuUndo, LuRedo, LuSearch, LuShieldCheck, LuPlus, LuPanelLeftClose, LuStickyNote, LuMonitor, LuColumns2, LuPresentation, LuMinus, LuLayers, LuSettings2, LuClock, LuDownload, LuTrash2, LuCheck, LuLock, LuEye, LuFileText, LuType, LuLoader, LuShieldAlert, LuSignature, LuInfo, LuTriangleAlert, LuPrinter, LuPenTool, LuBug, LuChevronUp, LuChevronDown, LuWifi, LuWifiOff, LuUsers, LuCopy, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuZoomOut, LuZoomIn, LuSpellCheck, LuFileDown, LuMenu, LuSparkles, LuShare2, LuPanelLeft, LuPanelRight, LuArrowLeft, LuFolderOpen, LuClipboardPaste, LuScissors, LuPaintbrush, LuSquare, LuImage, LuVideo, LuDatabase, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuReplace, LuMousePointer2, LuShapes, LuPaintBucket, LuPenLine, LuPalette, LuPencil, LuStar, LuMoveRight, LuMousePointerClick, LuClock3, LuMonitorPlay, LuListVideo, LuCaptions, LuCamera, LuEraser, LuRotateCcw, LuCircleHelp, LuBookOpen, LuLanguages, LuGlobe, LuGitCompare, LuMessageSquarePlus, LuLockKeyhole, LuPanelTop, LuLayoutGrid, LuGrid3X3, LuPipette, LuRuler, LuMaximize2, LuCode, LuCaseSensitive, LuTimer, LuGripVertical, LuLoaderCircle, LuUpload, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuCirclePlay, LuCirclePause, LuScan, LuMonitorOff, LuClipboardCopy, LuWand, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuFilePlus2, LuHouse, LuPackage, LuBox, LuFileImage, LuUser, LuHardDrive, LuLogIn, LuFolderPlus, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuColumns3, LuSpline, LuAlignHorizontalSpaceAround, LuAlignVerticalSpaceAround, LuGroup, LuUngroup, LuMove, LuRadio, LuLockOpen, LuArrowDown, LuArrowUp, LuArrowRight, LuReply, LuBookmark } from 'react-icons/lu';
9
+ import { LuRotateCw, LuMessageSquare, LuEyeOff, LuSettings, LuX, LuCalendarDays, LuHash, LuText, LuCast, LuSave, LuUndo, LuRedo, LuSearch, LuShieldCheck, LuPlus, LuPanelLeftClose, LuStickyNote, LuMonitor, LuColumns2, LuPresentation, LuMinus, LuLayers, LuSettings2, LuClock, LuDownload, LuTrash2, LuCheck, LuLock, LuEye, LuFileText, LuType, LuLoader, LuShieldAlert, LuSignature, LuInfo, LuTriangleAlert, LuPrinter, LuPenTool, LuBug, LuChevronUp, LuChevronDown, LuWifi, LuWifiOff, LuUsers, LuCopy, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuZoomOut, LuZoomIn, LuSpellCheck, LuFileDown, LuMenu, LuSparkles, LuShare2, LuPanelLeft, LuPanelRight, LuArrowLeft, LuFolderOpen, LuClipboardPaste, LuScissors, LuPaintbrush, LuSquare, LuImage, LuVideo, LuDatabase, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuReplace, LuMousePointer2, LuShapes, LuPaintBucket, LuPenLine, LuPalette, LuPencil, LuStar, LuMoveRight, LuMousePointerClick, LuClock3, LuMonitorPlay, LuListVideo, LuCaptions, LuCamera, LuEraser, LuRotateCcw, LuCircleHelp, LuBookOpen, LuLanguages, LuGlobe, LuGitCompare, LuMessageSquarePlus, LuLockKeyhole, LuPanelTop, LuLayoutGrid, LuGrid3X3, LuPipette, LuRuler, LuMaximize2, LuCode, LuCaseSensitive, LuTimer, LuGripVertical, LuLoaderCircle, LuUpload, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuScan, LuMonitorOff, LuCirclePlay, LuCirclePause, LuArrowLeftRight, LuClipboardCopy, LuWand, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuFilePlus2, LuHouse, LuPackage, LuBox, LuFileImage, LuUser, LuHardDrive, LuLogIn, LuFolderPlus, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuColumns3, LuSpline, LuAlignHorizontalSpaceAround, LuAlignVerticalSpaceAround, LuGroup, LuUngroup, LuMove, LuRadio, LuLockOpen, LuArrowDown, LuArrowUp, LuArrowRight, LuReply, LuBookmark } from 'react-icons/lu';
10
10
 
11
11
  var ViewerThemeContext = createContext(void 0);
12
12
  function ViewerThemeProvider({ theme, children }) {
@@ -1246,11 +1246,11 @@ var TRANSITION_PRESETS = [
1246
1246
  ];
1247
1247
  function TransitionsSection(p) {
1248
1248
  const { t } = useTranslation();
1249
- const [selected, setSelected] = React34.useState("none");
1250
- const [duration, setDuration] = React34.useState("00.50");
1251
- const [advanceOnClick, setAdvanceOnClick] = React34.useState(true);
1252
- const [advanceAfter, setAdvanceAfter] = React34.useState(false);
1253
- const [advanceAfterSeconds, setAdvanceAfterSeconds] = React34.useState("00:00.00");
1249
+ const [selected, setSelected] = React35.useState("none");
1250
+ const [duration, setDuration] = React35.useState("00.50");
1251
+ const [advanceOnClick, setAdvanceOnClick] = React35.useState(true);
1252
+ const [advanceAfter, setAdvanceAfter] = React35.useState(false);
1253
+ const [advanceAfterSeconds, setAdvanceAfterSeconds] = React35.useState("00:00.00");
1254
1254
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1255
1255
  /* @__PURE__ */ jsxs("button", { type: "button", className: pill, title: t("pptx.ribbon.previewTransition"), children: [
1256
1256
  /* @__PURE__ */ jsx(LuPlay, { className: ics }),
@@ -1452,7 +1452,7 @@ function AccountPage() {
1452
1452
  return void 0;
1453
1453
  });
1454
1454
  };
1455
- const version = "2.11.0" ;
1455
+ const version = "2.12.0" ;
1456
1456
  return /* @__PURE__ */ jsxs("div", { className: "mt-8 max-w-[700px] space-y-6", children: [
1457
1457
  /* @__PURE__ */ jsxs("section", { className: cardClass, children: [
1458
1458
  /* @__PURE__ */ jsxs("h2", { className: "flex items-center gap-2 text-sm font-semibold", children: [
@@ -6175,7 +6175,7 @@ function HorizontalRulerView({ ticks, widthPx, highlight }) {
6175
6175
  }
6176
6176
  );
6177
6177
  }
6178
- var HorizontalRuler = React34.memo(HorizontalRulerView);
6178
+ var HorizontalRuler = React35.memo(HorizontalRulerView);
6179
6179
  HorizontalRuler.displayName = "HorizontalRuler";
6180
6180
  function VerticalRulerView({ ticks, heightPx, highlight }) {
6181
6181
  return /* @__PURE__ */ jsxs(
@@ -6247,7 +6247,7 @@ function VerticalRulerView({ ticks, heightPx, highlight }) {
6247
6247
  }
6248
6248
  );
6249
6249
  }
6250
- var VerticalRuler = React34.memo(VerticalRulerView);
6250
+ var VerticalRuler = React35.memo(VerticalRulerView);
6251
6251
  VerticalRuler.displayName = "VerticalRuler";
6252
6252
  function Ruler({
6253
6253
  canvasSize,
@@ -6951,6 +6951,39 @@ function useStableCallbacks(callbacks) {
6951
6951
  stableResizeTableRow
6952
6952
  };
6953
6953
  }
6954
+ function useActionAffordance(element, canInteract) {
6955
+ const { t } = useTranslation();
6956
+ ensureActionAffordanceStyles();
6957
+ return useMemo(
6958
+ () => resolveElementActionAffordance(element, {
6959
+ canInteract,
6960
+ // Wrapped rather than passed by reference: i18next's `TFunction` is
6961
+ // heavily overloaded and does not assign to a plain key -> string.
6962
+ labels: actionAffordanceLabels((key) => t(key))
6963
+ }),
6964
+ [element, canInteract, t]
6965
+ );
6966
+ }
6967
+ function ActionIndicator({ title }) {
6968
+ return /* @__PURE__ */ jsx("div", { className: ACTION_INDICATOR_CLASS, title, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: ACTION_INDICATOR_ICON_PATH }) }) });
6969
+ }
6970
+ function LinkTooltip({ label, hint }) {
6971
+ return /* @__PURE__ */ jsx("div", { className: LINK_TOOLTIP_CLASS, children: /* @__PURE__ */ jsxs("div", { className: LINK_TOOLTIP_PANEL_CLASS, children: [
6972
+ /* @__PURE__ */ jsx("div", { className: LINK_TOOLTIP_LABEL_CLASS, children: label }),
6973
+ /* @__PURE__ */ jsx("div", { className: LINK_TOOLTIP_HINT_CLASS, children: hint })
6974
+ ] }) });
6975
+ }
6976
+ function ActionAffordances({
6977
+ affordance
6978
+ }) {
6979
+ if (!affordance.showIndicator && !affordance.showLinkTooltip) {
6980
+ return null;
6981
+ }
6982
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
6983
+ affordance.showIndicator && /* @__PURE__ */ jsx(ActionIndicator, { title: affordance.indicatorTitle }),
6984
+ affordance.showLinkTooltip && /* @__PURE__ */ jsx(LinkTooltip, { label: affordance.linkTooltipLabel, hint: affordance.linkTooltipHint })
6985
+ ] });
6986
+ }
6954
6987
  function ConnectorTextOverlay({
6955
6988
  connectorText,
6956
6989
  connectorTextSegments,
@@ -7199,7 +7232,7 @@ function ResizeHandles({
7199
7232
  ) : null
7200
7233
  ] });
7201
7234
  }
7202
- var ConnectorElementRenderer = React34.memo(
7235
+ var ConnectorElementRenderer = React35.memo(
7203
7236
  ({
7204
7237
  el,
7205
7238
  isSelected,
@@ -7495,6 +7528,8 @@ function getElementInteractionProps({
7495
7528
  title: canInteract && element.actionClick ? void 0 : element.actionClick?.tooltip || element.actionHover?.tooltip || void 0
7496
7529
  };
7497
7530
  }
7531
+
7532
+ // src/viewer/components/elements/element-renderer-helpers.tsx
7498
7533
  function renderDagDuotoneFilterForElement(el) {
7499
7534
  if (!hasDagDuotoneEffect(el)) {
7500
7535
  return null;
@@ -7545,19 +7580,6 @@ function getContainerStyle({
7545
7580
  ...templateEditing ? { outline: "2px dashed rgb(217, 119, 6)", outlineOffset: "1px", opacity: opacity ?? 0.95 } : {}
7546
7581
  };
7547
7582
  }
7548
- function ActionIndicator({
7549
- clickTooltip,
7550
- hoverTooltip
7551
- }) {
7552
- return /* @__PURE__ */ jsx(
7553
- "div",
7554
- {
7555
- className: "absolute -top-1 -right-1 z-20 w-4 h-4 rounded-full bg-amber-500 flex items-center justify-center shadow",
7556
- title: clickTooltip || hoverTooltip || "Has action",
7557
- children: /* @__PURE__ */ jsx("svg", { className: "w-2.5 h-2.5 text-white", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M13 2L3 14h9l-1 8 10-12h-9l1-8z" }) })
7558
- }
7559
- );
7560
- }
7561
7583
 
7562
7584
  // src/viewer/components/elements/element-shape-params.ts
7563
7585
  function shapeParams(element) {
@@ -8705,10 +8727,10 @@ function InlineTextEditor({
8705
8727
  function FailedToLoad() {
8706
8728
  return null;
8707
8729
  }
8708
- var LazyModel3DScene = React34.lazy(
8730
+ var LazyModel3DScene = React35.lazy(
8709
8731
  async () => {
8710
8732
  try {
8711
- return await import('./Model3DScene-WHSHBMR5.mjs');
8733
+ return await import('./Model3DScene-TU4NTHRM.mjs');
8712
8734
  } catch {
8713
8735
  return { default: FailedToLoad };
8714
8736
  }
@@ -8791,7 +8813,7 @@ function PosterFallback({
8791
8813
  }
8792
8814
  );
8793
8815
  }
8794
- var Model3DErrorBoundary = class extends React34.Component {
8816
+ var Model3DErrorBoundary = class extends React35.Component {
8795
8817
  constructor(props) {
8796
8818
  super(props);
8797
8819
  this.state = { hasError: false };
@@ -8982,10 +9004,10 @@ function SmartArtInlineNodeEditor({
8982
9004
  onCancel
8983
9005
  }) {
8984
9006
  const { t } = useTranslation();
8985
- const ref = React34.useRef(null);
8986
- const [value, setValue] = React34.useState(initialText);
8987
- const settled = React34.useRef(false);
8988
- React34.useEffect(() => {
9007
+ const ref = React35.useRef(null);
9008
+ const [value, setValue] = React35.useState(initialText);
9009
+ const settled = React35.useRef(false);
9010
+ React35.useEffect(() => {
8989
9011
  const el = ref.current;
8990
9012
  if (el) {
8991
9013
  el.focus();
@@ -9077,16 +9099,16 @@ function findNodeIdFromEvent(target) {
9077
9099
  return null;
9078
9100
  }
9079
9101
  function useSmartArtHoverState(containerRef) {
9080
- const [hoveredNodeId, setHoveredNodeId] = React34.useState(null);
9081
- const [hoveredNodeRect, setHoveredNodeRect] = React34.useState(null);
9082
- const hideTimeoutRef = React34.useRef(null);
9083
- const cancelPendingHide = React34.useCallback(() => {
9102
+ const [hoveredNodeId, setHoveredNodeId] = React35.useState(null);
9103
+ const [hoveredNodeRect, setHoveredNodeRect] = React35.useState(null);
9104
+ const hideTimeoutRef = React35.useRef(null);
9105
+ const cancelPendingHide = React35.useCallback(() => {
9084
9106
  if (hideTimeoutRef.current !== null) {
9085
9107
  window.clearTimeout(hideTimeoutRef.current);
9086
9108
  hideTimeoutRef.current = null;
9087
9109
  }
9088
9110
  }, []);
9089
- const handleMouseMove = React34.useCallback(
9111
+ const handleMouseMove = React35.useCallback(
9090
9112
  (e, ignoreRef) => {
9091
9113
  const nodeEl = findNodeIdFromEvent(e.target);
9092
9114
  const container = containerRef.current;
@@ -9114,12 +9136,12 @@ function useSmartArtHoverState(containerRef) {
9114
9136
  },
9115
9137
  [containerRef, cancelPendingHide]
9116
9138
  );
9117
- const clearHover = React34.useCallback(() => {
9139
+ const clearHover = React35.useCallback(() => {
9118
9140
  cancelPendingHide();
9119
9141
  setHoveredNodeId(null);
9120
9142
  setHoveredNodeRect(null);
9121
9143
  }, [cancelPendingHide]);
9122
- React34.useEffect(() => cancelPendingHide, [cancelPendingHide]);
9144
+ React35.useEffect(() => cancelPendingHide, [cancelPendingHide]);
9123
9145
  return { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover };
9124
9146
  }
9125
9147
  var EDITOR_PADDING = 4;
@@ -9134,11 +9156,11 @@ function SmartArtEditableLayer({
9134
9156
  onChangeNodeStyle,
9135
9157
  children
9136
9158
  }) {
9137
- const containerRef = React34.useRef(null);
9138
- const styleBarRef = React34.useRef(null);
9139
- const [edit, setEdit] = React34.useState(null);
9159
+ const containerRef = React35.useRef(null);
9160
+ const styleBarRef = React35.useRef(null);
9161
+ const [edit, setEdit] = React35.useState(null);
9140
9162
  const { hoveredNodeId, hoveredNodeRect, handleMouseMove, clearHover } = useSmartArtHoverState(containerRef);
9141
- const openEditor = React34.useCallback(
9163
+ const openEditor = React35.useCallback(
9142
9164
  (target) => {
9143
9165
  const nodeEl = findNodeIdFromEvent(target);
9144
9166
  const container = containerRef.current;
@@ -10678,11 +10700,11 @@ function arePropsEqual(prev, next) {
10678
10700
  }
10679
10701
  return true;
10680
10702
  }
10681
- var SmartArtRenderer = React34.memo(SmartArtRendererImpl, arePropsEqual);
10703
+ var SmartArtRenderer = React35.memo(SmartArtRendererImpl, arePropsEqual);
10682
10704
  function FailedToLoad2() {
10683
10705
  return null;
10684
10706
  }
10685
- var LazySmartArt3DScene = React34.lazy(
10707
+ var LazySmartArt3DScene = React35.lazy(
10686
10708
  async () => {
10687
10709
  try {
10688
10710
  return await import('./SmartArt3DScene-XCFVGCXE.mjs');
@@ -10691,7 +10713,7 @@ var LazySmartArt3DScene = React34.lazy(
10691
10713
  }
10692
10714
  }
10693
10715
  );
10694
- var SceneErrorBoundary = class extends React34.Component {
10716
+ var SceneErrorBoundary = class extends React35.Component {
10695
10717
  constructor(props) {
10696
10718
  super(props);
10697
10719
  this.state = { hasError: false };
@@ -11325,6 +11347,7 @@ function renderBody(options) {
11325
11347
  onColResize,
11326
11348
  onRowResize,
11327
11349
  isPresentationPassive,
11350
+ isStaticSurface,
11328
11351
  handleMediaPlayStateChange,
11329
11352
  allSlides,
11330
11353
  onZoomClick,
@@ -11424,6 +11447,13 @@ function renderBody(options) {
11424
11447
  autoPlay: isPresentationPassive,
11425
11448
  fullScreen: isPresentationPassive && Boolean(el.fullScreen),
11426
11449
  isPresentationMode: isPresentationPassive,
11450
+ // A still of a slide never carries a transport, whatever the canvas
11451
+ // does. The rule is shared so the five bindings cannot drift on it.
11452
+ showTransport: mediaTransportVisible({
11453
+ presenting: isPresentationPassive === true,
11454
+ preview: isStaticSurface === true,
11455
+ canvasTransport: true
11456
+ }),
11427
11457
  onPlayStateChange: handleMediaPlayStateChange
11428
11458
  });
11429
11459
  }
@@ -11450,7 +11480,7 @@ function renderBody(options) {
11450
11480
  }
11451
11481
  return renderTextElementBody(options);
11452
11482
  }
11453
- var Extrusion3DOverlay = React34.memo(({ data }) => {
11483
+ var Extrusion3DOverlay = React35.memo(({ data }) => {
11454
11484
  if (!data.hasExtrusion || data.panels.length === 0) {
11455
11485
  return null;
11456
11486
  }
@@ -11483,12 +11513,6 @@ var Extrusion3DOverlay = React34.memo(({ data }) => {
11483
11513
  ] });
11484
11514
  });
11485
11515
  Extrusion3DOverlay.displayName = "Extrusion3DOverlay";
11486
- function LinkTooltip({ label, hasUrl }) {
11487
- return /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute left-1 top-full z-[9999] mt-1 max-w-64 opacity-0 transition-opacity duration-150 group-hover/link:opacity-100", children: /* @__PURE__ */ jsxs("div", { className: "rounded border border-border bg-popover px-2.5 py-1.5 shadow-lg", children: [
11488
- /* @__PURE__ */ jsx("div", { className: "truncate text-xs text-foreground", children: label }),
11489
- /* @__PURE__ */ jsx("div", { className: "mt-0.5 text-[10px] text-muted-foreground", children: hasUrl ? "Ctrl+Click to follow link" : "Active in presentation mode" })
11490
- ] }) });
11491
- }
11492
11516
 
11493
11517
  // src/viewer/components/elements/scoped-element-handlers.ts
11494
11518
  function getScopedElementHandlers(elementId, options) {
@@ -11555,6 +11579,7 @@ function StaticElementRendererImpl({
11555
11579
  {
11556
11580
  "data-static-element-type": element.type,
11557
11581
  "data-element-id": exposeElementId ? element.id : void 0,
11582
+ "data-pptx-element": exposeElementId ? "true" : void 0,
11558
11583
  "data-pptx-action": isActionable ? "click" : void 0,
11559
11584
  className: `${positioned ? "absolute" : "relative"} overflow-hidden ${isActionable ? "pointer-events-auto cursor-pointer" : "pointer-events-none"}`,
11560
11585
  role: contractRole,
@@ -11631,6 +11656,11 @@ function StaticElementRendererImpl({
11631
11656
  onCommit: noop,
11632
11657
  onCancel: noop,
11633
11658
  isPresentationPassive: false,
11659
+ // This renderer only ever paints a STILL of a slide (presenter
11660
+ // console panes, thumbnails, previews). It is not in presentation
11661
+ // mode, so without saying so a video here would carry Chrome's
11662
+ // scrubber over a slide nobody can play.
11663
+ isStaticSurface: true,
11634
11664
  slideElements: activeSlide?.elements,
11635
11665
  allSlides,
11636
11666
  sourceSlideIndex,
@@ -11643,9 +11673,9 @@ function StaticElementRendererImpl({
11643
11673
  }
11644
11674
  );
11645
11675
  }
11646
- var StaticElementRenderer = React34.memo(StaticElementRendererImpl);
11676
+ var StaticElementRenderer = React35.memo(StaticElementRendererImpl);
11647
11677
  StaticElementRenderer.displayName = "StaticElementRenderer";
11648
- var ElementRenderer = React34.memo(
11678
+ var ElementRenderer = React35.memo(
11649
11679
  // oxlint-disable-next-line prefer-arrow-callback -- named fn gives the memo component its displayName
11650
11680
  function ElementRendererInner({
11651
11681
  element: el,
@@ -11735,6 +11765,7 @@ var ElementRenderer = React34.memo(
11735
11765
  () => build3DExtrusionData(shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height),
11736
11766
  [shapeStyle3d?.shape3d, shapeStyle3d?.scene3d, fc, el.width, el.height]
11737
11767
  );
11768
+ const actionAffordance = useActionAffordance(el, canInteract);
11738
11769
  const [isMediaPlaying, setIsMediaPlaying] = useState(false);
11739
11770
  const handleMediaPlayStateChange = useCallback((playing) => {
11740
11771
  setIsMediaPlaying(playing);
@@ -11796,6 +11827,7 @@ var ElementRenderer = React34.memo(
11796
11827
  {
11797
11828
  "data-pptx-element": "true",
11798
11829
  "data-element-id": el.id,
11830
+ "data-pptx-action": isActionable ? "click" : void 0,
11799
11831
  role: ariaRole,
11800
11832
  "aria-label": ariaLabel,
11801
11833
  "aria-roledescription": ariaRoleDescription,
@@ -11808,7 +11840,10 @@ var ElementRenderer = React34.memo(
11808
11840
  effectiveCanInteract || isActionable ? "" : "pointer-events-none",
11809
11841
  isFullscreenMedia ? "pointer-events-auto" : "",
11810
11842
  selB,
11811
- effectiveCanInteract && el.actionClick && "group/link"
11843
+ // Shared class the tooltip's `:hover` rule keys off (see
11844
+ // `ACTION_AFFORDANCE_CSS`), replacing React's Tailwind `group/link`
11845
+ // so the four non-Tailwind bindings reveal it the same way.
11846
+ actionAffordance.showLinkTooltip && LINK_TOOLTIP_HOST_CLASS
11812
11847
  ),
11813
11848
  style: getContainerStyle({
11814
11849
  el,
@@ -11886,20 +11921,7 @@ var ElementRenderer = React34.memo(
11886
11921
  onUpdateChartElement: chartUpdateHandler,
11887
11922
  onFormatText
11888
11923
  }),
11889
- (el.actionClick || el.actionHover) && canInteract && /* @__PURE__ */ jsx(
11890
- ActionIndicator,
11891
- {
11892
- clickTooltip: el.actionClick?.tooltip,
11893
- hoverTooltip: el.actionHover?.tooltip
11894
- }
11895
- ),
11896
- effectiveCanInteract && el.actionClick && /* @__PURE__ */ jsx(
11897
- LinkTooltip,
11898
- {
11899
- label: el.actionClick.tooltip || el.actionClick.url || el.actionClick.action || "Link",
11900
- hasUrl: Boolean(el.actionClick.url)
11901
- }
11902
- ),
11924
+ /* @__PURE__ */ jsx(ActionAffordances, { affordance: actionAffordance }),
11903
11925
  effectiveShowResizeHandles && !effectiveIsInlineEditing && /* @__PURE__ */ jsx(
11904
11926
  ResizeHandles,
11905
11927
  {
@@ -12915,7 +12937,7 @@ function arePropsEqual2(prev, next) {
12915
12937
  }
12916
12938
  return true;
12917
12939
  }
12918
- var SlideThumbnail = React34.memo(SlideThumbnailImpl, arePropsEqual2);
12940
+ var SlideThumbnail = React35.memo(SlideThumbnailImpl, arePropsEqual2);
12919
12941
 
12920
12942
  // src/viewer/components/context-menu-dispatch.ts
12921
12943
  function tableCell(props) {
@@ -13464,7 +13486,7 @@ function LazyThumbnailInner({
13464
13486
  }
13465
13487
  ) });
13466
13488
  }
13467
- var LazyThumbnail = React34.memo(LazyThumbnailInner);
13489
+ var LazyThumbnail = React35.memo(LazyThumbnailInner);
13468
13490
 
13469
13491
  // src/viewer/components/slides-pane/utils.ts
13470
13492
  function formatTimingMs(ms) {
@@ -13520,7 +13542,9 @@ function SlideItemInner({
13520
13542
  onDrop,
13521
13543
  slideRef
13522
13544
  }) {
13545
+ const { t } = useTranslation();
13523
13546
  const isHidden = Boolean(slide.hidden);
13547
+ const cue = hiddenSlideCue(slide.hidden, "rail", slideIndex);
13524
13548
  const handleContextMenu = useCallback(
13525
13549
  (e) => {
13526
13550
  if (canEdit && onAddSection) {
@@ -13544,6 +13568,8 @@ function SlideItemInner({
13544
13568
  ref: slideRef,
13545
13569
  "aria-label": `Go to slide ${slideIndex + 1}`,
13546
13570
  "aria-current": isActive ? "true" : void 0,
13571
+ "aria-describedby": cue.labelId,
13572
+ "data-pptx-slide-hidden": cue.marker,
13547
13573
  className: cn(
13548
13574
  "group relative flex w-full items-center gap-1 cursor-pointer border-0 bg-transparent py-0.5 px-1 text-left transition-all",
13549
13575
  isActive && "bg-accent/40 before:absolute before:left-0 before:top-1 before:bottom-1 before:w-[3px] before:bg-primary before:rounded-r",
@@ -13564,6 +13590,7 @@ function SlideItemInner({
13564
13590
  "text-[10px] tabular-nums text-right select-none w-full",
13565
13591
  isActive ? "text-primary font-medium" : "text-muted-foreground"
13566
13592
  ),
13593
+ style: isHidden ? { backgroundImage: HIDDEN_SLIDE_SLASH_GRADIENT } : void 0,
13567
13594
  children: slideIndex + 1
13568
13595
  }
13569
13596
  ),
@@ -13601,7 +13628,10 @@ function SlideItemInner({
13601
13628
  /* @__PURE__ */ jsx(LuMessageSquare, { className: "w-2 h-2" }),
13602
13629
  slide.comments?.length
13603
13630
  ] }),
13604
- isHidden && /* @__PURE__ */ jsx("div", { className: "absolute bottom-0.5 right-0.5 z-10", children: /* @__PURE__ */ jsx(LuEyeOff, { className: "w-3 h-3 text-muted-foreground" }) }),
13631
+ isHidden && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-0.5 right-0.5 z-10", id: cue.labelId, children: [
13632
+ /* @__PURE__ */ jsx(LuEyeOff, { className: "w-3 h-3 text-muted-foreground" }),
13633
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: t(HIDDEN_SLIDE_LABEL_KEY) })
13634
+ ] }),
13605
13635
  rehearsalTimings && typeof rehearsalTimings[slideIndex] === "number" && /* @__PURE__ */ jsx("div", { className: "absolute bottom-0.5 left-0.5 z-10", children: /* @__PURE__ */ jsx("span", { className: "text-[8px] font-mono text-amber-400/80 tabular-nums bg-black/50 px-0.5 rounded", children: formatTimingMs(rehearsalTimings[slideIndex]) }) })
13606
13636
  ]
13607
13637
  }
@@ -13610,7 +13640,7 @@ function SlideItemInner({
13610
13640
  }
13611
13641
  );
13612
13642
  }
13613
- var SlideItem = React34.memo(SlideItemInner);
13643
+ var SlideItem = React35.memo(SlideItemInner);
13614
13644
  function useSlidePaneCallbacks(onMoveSlide, onRenameSection) {
13615
13645
  const [collapsedSections, setCollapsedSections] = useState({});
13616
13646
  const [renamingSectionId, setRenamingSectionId] = useState(null);
@@ -14801,6 +14831,8 @@ function SlideCardImpl({
14801
14831
  onDragLeave,
14802
14832
  onDrop
14803
14833
  }) {
14834
+ const { t } = useTranslation();
14835
+ const cue = hiddenSlideCue(slide.hidden, "sorter", index);
14804
14836
  return /* @__PURE__ */ jsxs(
14805
14837
  "div",
14806
14838
  {
@@ -14809,6 +14841,8 @@ function SlideCardImpl({
14809
14841
  isDragTarget ? "border-primary bg-primary/20" : isSelected ? "border-primary bg-primary/10 ring-1 ring-primary/50" : isActive ? "border-primary/50 bg-primary/5" : "border-border bg-background/50 hover:border-border",
14810
14842
  slide.hidden && "opacity-40"
14811
14843
  ),
14844
+ "data-pptx-slide-hidden": cue.marker,
14845
+ "aria-describedby": cue.labelId,
14812
14846
  onClick: (e) => onSlideClick(e, index),
14813
14847
  onDoubleClick: () => onDoubleClick(index),
14814
14848
  onContextMenu: (e) => onContextMenu(e, index),
@@ -14824,13 +14858,17 @@ function SlideCardImpl({
14824
14858
  "span",
14825
14859
  {
14826
14860
  className: cn(
14827
- "text-[11px] font-medium",
14861
+ "text-[11px] font-medium px-0.5",
14828
14862
  isSelected ? "text-primary" : isActive ? "text-primary/70" : "text-muted-foreground"
14829
14863
  ),
14864
+ style: cue.hidden ? { backgroundImage: HIDDEN_SLIDE_SLASH_GRADIENT } : void 0,
14830
14865
  children: index + 1
14831
14866
  }
14832
14867
  ),
14833
- slide.hidden && /* @__PURE__ */ jsx(LuEyeOff, { className: "h-3 w-3 text-muted-foreground" })
14868
+ cue.hidden && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", id: cue.labelId, children: [
14869
+ /* @__PURE__ */ jsx(LuEyeOff, { className: "h-3 w-3 text-muted-foreground" }),
14870
+ /* @__PURE__ */ jsx("span", { className: "text-[9px] uppercase tracking-wide text-muted-foreground", children: t(HIDDEN_SLIDE_LABEL_KEY) })
14871
+ ] })
14834
14872
  ] }),
14835
14873
  isSelected && selectedCount > 1 && /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-white text-[10px] font-bold", children: selectionOrder })
14836
14874
  ]
@@ -14879,7 +14917,7 @@ function arePropsEqual3(prev, next) {
14879
14917
  }
14880
14918
  return true;
14881
14919
  }
14882
- var SlideCard = React34.memo(SlideCardImpl, arePropsEqual3);
14920
+ var SlideCard = React35.memo(SlideCardImpl, arePropsEqual3);
14883
14921
  function SorterContextMenu({
14884
14922
  x,
14885
14923
  y,
@@ -18708,102 +18746,121 @@ function PresentationSubtitleBar({
18708
18746
  function renderNotesSegments(segments) {
18709
18747
  return notesSegmentsToSpans(segments).map((span) => {
18710
18748
  if (span.kind === "break") {
18711
- return React34.createElement("br", { key: span.key });
18749
+ return React35.createElement("br", { key: span.key });
18712
18750
  }
18713
- return React34.createElement(
18751
+ return React35.createElement(
18714
18752
  "span",
18715
18753
  { key: span.key, style: span.style },
18716
18754
  span.text
18717
18755
  );
18718
18756
  });
18719
18757
  }
18720
- var toolClass = (active) => `inline-flex h-9 min-w-9 items-center justify-center gap-2 rounded-md px-2 text-xs transition-colors ${active ? "bg-primary text-primary-foreground" : "bg-muted text-foreground hover:bg-accent"}`;
18758
+ var CONSOLE_ICONS = {
18759
+ "arrow-left-right": LuArrowLeftRight,
18760
+ captions: LuCaptions,
18761
+ "circle-pause": LuCirclePause,
18762
+ "circle-play": LuCirclePlay,
18763
+ eraser: LuEraser,
18764
+ "grid-2x2": LuGrid2X2,
18765
+ highlighter: LuHighlighter,
18766
+ monitor: LuMonitor,
18767
+ "monitor-off": LuMonitorOff,
18768
+ "mouse-pointer-2": LuMousePointer2,
18769
+ "pen-tool": LuPenTool,
18770
+ "rotate-ccw": LuRotateCcw,
18771
+ scan: LuScan,
18772
+ x: LuX,
18773
+ "zoom-in": LuZoomIn,
18774
+ "zoom-out": LuZoomOut
18775
+ };
18776
+ var POINTER_TOOLS = {
18777
+ laser: "laser",
18778
+ pen: "pen",
18779
+ highlighter: "highlighter",
18780
+ eraser: "eraser"
18781
+ };
18782
+ function slotState(control, props) {
18783
+ const snapshot = props.snapshot;
18784
+ const pointerTool = snapshot.pointer?.tool ?? "none";
18785
+ const tool = POINTER_TOOLS[control.id];
18786
+ if (tool) {
18787
+ return {
18788
+ active: pointerTool === tool,
18789
+ onClick: () => props.onPointerTool(pointerTool === tool ? "none" : tool)
18790
+ };
18791
+ }
18792
+ switch (control.id) {
18793
+ case "timer-toggle":
18794
+ return { active: Boolean(snapshot.paused), onClick: props.onToggleTimer };
18795
+ case "timer-reset":
18796
+ return { active: false, onClick: props.onResetTimer };
18797
+ case "all-slides":
18798
+ return { active: false, onClick: props.onShowSlides };
18799
+ case "zoom-in":
18800
+ return { active: (snapshot.zoom?.scale ?? 1) > 1, onClick: () => props.onStepZoom(1) };
18801
+ case "zoom-out":
18802
+ return { active: false, onClick: () => props.onStepZoom(-1) };
18803
+ case "zoom-reset":
18804
+ return { active: false, onClick: props.onResetZoom };
18805
+ case "blackout-black":
18806
+ return {
18807
+ active: snapshot.blackout === "black",
18808
+ onClick: () => props.onBlackout(snapshot.blackout === "black" ? "none" : "black")
18809
+ };
18810
+ case "blackout-white":
18811
+ return {
18812
+ active: snapshot.blackout === "white",
18813
+ onClick: () => props.onBlackout(snapshot.blackout === "white" ? "none" : "white")
18814
+ };
18815
+ case "captions":
18816
+ return { active: Boolean(snapshot.subtitlesVisible), onClick: props.onToggleSubtitles };
18817
+ case "audience":
18818
+ return { active: props.audienceOpen, onClick: props.onToggleAudience };
18819
+ case "swap-displays":
18820
+ return { active: false, onClick: props.onSwapDisplays, disabled: !props.audienceOpen };
18821
+ case "end":
18822
+ return { active: false, onClick: props.onExit };
18823
+ default:
18824
+ return { active: false, onClick: () => void 0 };
18825
+ }
18826
+ }
18721
18827
  function PresenterConsoleToolbar(props) {
18722
- const pointerTool = props.snapshot.pointer?.tool ?? "none";
18723
- const zoom = props.snapshot.zoom?.scale ?? 1;
18724
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 border-b border-border bg-card px-3 py-2", children: [
18725
- /* @__PURE__ */ jsx(
18726
- "button",
18727
- {
18728
- className: toolClass(false),
18729
- onClick: props.onToggleTimer,
18730
- title: "Pause or resume timer",
18731
- children: props.snapshot.paused ? /* @__PURE__ */ jsx(LuCirclePlay, {}) : /* @__PURE__ */ jsx(LuCirclePause, {})
18732
- }
18733
- ),
18734
- /* @__PURE__ */ jsx("button", { className: toolClass(false), onClick: props.onResetTimer, title: "Reset timer", children: /* @__PURE__ */ jsx(LuRotateCcw, {}) }),
18735
- /* @__PURE__ */ jsx("span", { className: "mx-1 h-6 w-px bg-border" }),
18736
- /* @__PURE__ */ jsxs("button", { className: toolClass(false), onClick: props.onShowSlides, title: "See all slides", children: [
18737
- /* @__PURE__ */ jsx(LuGrid2X2, {}),
18738
- " Slides"
18739
- ] }),
18740
- /* @__PURE__ */ jsx("button", { className: toolClass(zoom > 1), onClick: () => props.onStepZoom(1), title: "Zoom in", children: /* @__PURE__ */ jsx(LuZoomIn, {}) }),
18741
- /* @__PURE__ */ jsx("button", { className: toolClass(false), onClick: () => props.onStepZoom(-1), title: "Zoom out", children: /* @__PURE__ */ jsx(LuZoomOut, {}) }),
18742
- /* @__PURE__ */ jsx("button", { className: toolClass(false), onClick: props.onResetZoom, title: "Reset zoom", children: /* @__PURE__ */ jsx(LuScan, {}) }),
18743
- /* @__PURE__ */ jsx("span", { className: "mx-1 h-6 w-px bg-border" }),
18744
- ["laser", "pen", "highlighter", "eraser"].map((tool) => /* @__PURE__ */ jsx(
18828
+ const { t } = useTranslation();
18829
+ return /* @__PURE__ */ jsx("div", { className: PRESENTER_CONSOLE_CLASSES.strip, "data-pptx-presenter-toolbar": true, children: PRESENTER_CONSOLE_CONTROLS.map((control) => {
18830
+ if (control.kind === "divider" || control.kind === "spacer") {
18831
+ return /* @__PURE__ */ jsx(
18832
+ "span",
18833
+ {
18834
+ "data-pptx-presenter-control": control.id,
18835
+ className: control.kind === "divider" ? PRESENTER_CONSOLE_CLASSES.divider : PRESENTER_CONSOLE_CLASSES.spacer
18836
+ },
18837
+ control.id
18838
+ );
18839
+ }
18840
+ const state = slotState(control, props);
18841
+ const labelKey = state.active && control.activeLabelKey ? control.activeLabelKey : control.labelKey;
18842
+ const iconName = state.active && control.activeIcon ? control.activeIcon : control.icon;
18843
+ const Icon = iconName === void 0 ? void 0 : CONSOLE_ICONS[iconName];
18844
+ const label = labelKey === void 0 ? void 0 : t(labelKey);
18845
+ return /* @__PURE__ */ jsxs(
18745
18846
  "button",
18746
18847
  {
18747
- className: toolClass(pointerTool === tool),
18748
- onClick: () => props.onPointerTool(pointerTool === tool ? "none" : tool),
18749
- title: tool[0].toUpperCase() + tool.slice(1),
18750
- children: tool === "laser" ? /* @__PURE__ */ jsx(LuMousePointer2, {}) : tool === "pen" ? /* @__PURE__ */ jsx(LuPenTool, {}) : tool === "highlighter" ? /* @__PURE__ */ jsx(LuHighlighter, {}) : /* @__PURE__ */ jsx(LuEraser, {})
18848
+ type: "button",
18849
+ "data-pptx-presenter-control": control.id,
18850
+ className: state.active ? PRESENTER_CONSOLE_CLASSES.controlActive : PRESENTER_CONSOLE_CLASSES.control,
18851
+ onClick: state.onClick,
18852
+ disabled: state.disabled,
18853
+ "aria-label": label,
18854
+ title: label,
18855
+ "aria-pressed": control.kind === "toggle" ? state.active : void 0,
18856
+ children: [
18857
+ Icon ? /* @__PURE__ */ jsx(Icon, {}) : null,
18858
+ control.glyph
18859
+ ]
18751
18860
  },
18752
- tool
18753
- )),
18754
- /* @__PURE__ */ jsx("span", { className: "mx-1 h-6 w-px bg-border" }),
18755
- /* @__PURE__ */ jsx(
18756
- "button",
18757
- {
18758
- className: toolClass(props.snapshot.blackout === "black"),
18759
- onClick: () => props.onBlackout(props.snapshot.blackout === "black" ? "none" : "black"),
18760
- title: "Black screen",
18761
- children: "B"
18762
- }
18763
- ),
18764
- /* @__PURE__ */ jsx(
18765
- "button",
18766
- {
18767
- className: toolClass(props.snapshot.blackout === "white"),
18768
- onClick: () => props.onBlackout(props.snapshot.blackout === "white" ? "none" : "white"),
18769
- title: "White screen",
18770
- children: "W"
18771
- }
18772
- ),
18773
- /* @__PURE__ */ jsx(
18774
- "button",
18775
- {
18776
- className: toolClass(Boolean(props.snapshot.subtitlesVisible)),
18777
- onClick: props.onToggleSubtitles,
18778
- title: "Toggle subtitles",
18779
- children: /* @__PURE__ */ jsx(LuCaptions, {})
18780
- }
18781
- ),
18782
- /* @__PURE__ */ jsx("div", { className: "flex-1" }),
18783
- /* @__PURE__ */ jsx(
18784
- "button",
18785
- {
18786
- className: toolClass(props.audienceOpen),
18787
- onClick: props.onToggleAudience,
18788
- title: "Audience display",
18789
- children: props.audienceOpen ? /* @__PURE__ */ jsx(LuMonitorOff, {}) : /* @__PURE__ */ jsx(LuMonitor, {})
18790
- }
18791
- ),
18792
- /* @__PURE__ */ jsx(
18793
- "button",
18794
- {
18795
- className: toolClass(false),
18796
- onClick: props.onSwapDisplays,
18797
- disabled: !props.audienceOpen,
18798
- title: "Swap displays",
18799
- children: "Swap"
18800
- }
18801
- ),
18802
- /* @__PURE__ */ jsxs("button", { className: toolClass(false), onClick: props.onExit, title: "End slide show", children: [
18803
- /* @__PURE__ */ jsx(LuX, {}),
18804
- " End"
18805
- ] })
18806
- ] });
18861
+ control.id
18862
+ );
18863
+ }) });
18807
18864
  }
18808
18865
  function ScaledSlidePreviewImpl({
18809
18866
  slide,
@@ -18917,7 +18974,7 @@ function arePropsEqual4(prev, next) {
18917
18974
  }
18918
18975
  return true;
18919
18976
  }
18920
- var ScaledSlidePreview = React34.memo(ScaledSlidePreviewImpl, arePropsEqual4);
18977
+ var ScaledSlidePreview = React35.memo(ScaledSlidePreviewImpl, arePropsEqual4);
18921
18978
  function PresenterNotesRail({
18922
18979
  slides,
18923
18980
  current,
@@ -18940,14 +18997,14 @@ function PresenterNotesRail({
18940
18997
  () => notesSegments?.length ? renderNotesSegments(notesSegments) : notesText.trim() ? notesText : /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: t("pptx.presenter.noNotes") }),
18941
18998
  [notesSegments, notesText, t]
18942
18999
  );
18943
- return /* @__PURE__ */ jsxs("aside", { className: "flex flex-[3] min-w-[260px] max-w-[440px] flex-col border-l border-border bg-background", children: [
19000
+ return /* @__PURE__ */ jsxs("aside", { className: PRESENTER_CONSOLE_CLASSES.rail, children: [
18944
19001
  /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between border-b border-border/60 px-4 py-3", children: [
18945
19002
  /* @__PURE__ */ jsxs("div", { children: [
18946
- /* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.currentTime") }),
19003
+ /* @__PURE__ */ jsx("div", { className: PRESENTER_CONSOLE_CLASSES.railHeading, children: t("pptx.presenter.currentTime") }),
18947
19004
  /* @__PURE__ */ jsx("div", { className: "font-mono text-lg tabular-nums", children: formatTime(new Date(now)) })
18948
19005
  ] }),
18949
19006
  /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
18950
- /* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.elapsed") }),
19007
+ /* @__PURE__ */ jsx("div", { className: PRESENTER_CONSOLE_CLASSES.railHeading, children: t("pptx.presenter.elapsed") }),
18951
19008
  /* @__PURE__ */ jsx("div", { className: "font-mono text-lg tabular-nums text-primary", children: formatElapsed(elapsed) })
18952
19009
  ] })
18953
19010
  ] }),
@@ -18957,7 +19014,8 @@ function PresenterNotesRail({
18957
19014
  {
18958
19015
  type: "button",
18959
19016
  onClick: () => onMove(-1),
18960
- disabled: current === 0,
19017
+ disabled: presenterPrevDisabled(current),
19018
+ "data-pptx-presenter-control": "prev",
18961
19019
  className: "inline-flex items-center gap-1 rounded bg-muted px-3 py-1.5 text-xs disabled:opacity-40",
18962
19020
  children: [
18963
19021
  /* @__PURE__ */ jsx(LuChevronLeft, {}),
@@ -18976,6 +19034,8 @@ function PresenterNotesRail({
18976
19034
  {
18977
19035
  type: "button",
18978
19036
  onClick: () => onMove(1),
19037
+ disabled: presenterNextDisabled(),
19038
+ "data-pptx-presenter-control": "next",
18979
19039
  className: "inline-flex items-center gap-1 rounded bg-muted px-3 py-1.5 text-xs disabled:opacity-40",
18980
19040
  children: [
18981
19041
  t("pptx.presenter.next"),
@@ -18985,8 +19045,8 @@ function PresenterNotesRail({
18985
19045
  }
18986
19046
  )
18987
19047
  ] }),
18988
- /* @__PURE__ */ jsxs("section", { className: "border-b border-border/60 px-4 py-3", children: [
18989
- /* @__PURE__ */ jsx("div", { className: "mb-2 text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.nextSlidePreview") }),
19048
+ /* @__PURE__ */ jsxs("section", { className: "border-b border-border/60 px-4 py-3", "data-pptx-presenter-next-preview": true, children: [
19049
+ /* @__PURE__ */ jsx("div", { className: `mb-2 ${PRESENTER_CONSOLE_CLASSES.railHeading}`, children: t("pptx.presenter.nextSlidePreview") }),
18990
19050
  nextSlide ? /* @__PURE__ */ jsx(
18991
19051
  ScaledSlidePreview,
18992
19052
  {
@@ -18996,9 +19056,9 @@ function PresenterNotesRail({
18996
19056
  }
18997
19057
  ) : /* @__PURE__ */ jsx("div", { className: "flex h-16 items-center justify-center rounded bg-muted/40 text-xs italic text-muted-foreground", children: t("pptx.presenter.endOfPresentation") })
18998
19058
  ] }),
18999
- /* @__PURE__ */ jsxs("section", { className: "flex min-h-0 flex-1 flex-col px-4 py-3", children: [
19059
+ /* @__PURE__ */ jsxs("section", { className: "flex min-h-0 flex-1 flex-col px-4 py-3", "data-pptx-presenter-notes": true, children: [
19000
19060
  /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
19001
- /* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.speakerNotes") }),
19061
+ /* @__PURE__ */ jsx("div", { className: PRESENTER_CONSOLE_CLASSES.railHeading, children: t("pptx.presenter.speakerNotes") }),
19002
19062
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
19003
19063
  /* @__PURE__ */ jsx(
19004
19064
  "button",
@@ -19006,6 +19066,7 @@ function PresenterNotesRail({
19006
19066
  type: "button",
19007
19067
  onClick: () => setFontSize(clampNotesFontSize(fontSize - NOTES_FONT_SIZE_STEP)),
19008
19068
  disabled: fontSize <= NOTES_FONT_SIZE_MIN,
19069
+ "data-pptx-presenter-control": "notes-font-decrease",
19009
19070
  "aria-label": t("pptx.presenter.decreaseFontSize"),
19010
19071
  children: /* @__PURE__ */ jsx(LuMinus, {})
19011
19072
  }
@@ -19020,6 +19081,7 @@ function PresenterNotesRail({
19020
19081
  type: "button",
19021
19082
  onClick: () => setFontSize(clampNotesFontSize(fontSize + NOTES_FONT_SIZE_STEP)),
19022
19083
  disabled: fontSize >= NOTES_FONT_SIZE_MAX,
19084
+ "data-pptx-presenter-control": "notes-font-increase",
19023
19085
  "aria-label": t("pptx.presenter.increaseFontSize"),
19024
19086
  children: /* @__PURE__ */ jsx(LuPlus, {})
19025
19087
  }
@@ -19048,17 +19110,27 @@ function PresenterNotesRail({
19048
19110
  ] });
19049
19111
  }
19050
19112
  function PresenterSlideNavigator(props) {
19051
- return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-[120] flex flex-col bg-card/98 text-foreground", children: [
19052
- /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between border-b border-border px-6 py-4", children: [
19113
+ const { t } = useTranslation();
19114
+ return /* @__PURE__ */ jsxs("div", { className: `${PRESENTER_CONSOLE_CLASSES.navigator} text-foreground`, children: [
19115
+ /* @__PURE__ */ jsxs("header", { className: "mb-4 flex items-center justify-between border-b border-border pb-4", children: [
19053
19116
  /* @__PURE__ */ jsxs("div", { children: [
19054
- /* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-[0.22em] text-sky-300", children: "Slide navigator" }),
19055
- /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: "See all slides" })
19117
+ /* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-[0.22em] text-sky-300", children: t(PRESENTER_NAVIGATOR_LABEL_KEYS.title) }),
19118
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: t(PRESENTER_NAVIGATOR_LABEL_KEYS.subtitle) })
19056
19119
  ] }),
19057
- /* @__PURE__ */ jsx("button", { className: "rounded-md bg-muted px-4 py-2 hover:bg-accent", onClick: props.onClose, children: "Close" })
19120
+ /* @__PURE__ */ jsx(
19121
+ "button",
19122
+ {
19123
+ type: "button",
19124
+ className: "rounded-md bg-muted px-4 py-2 hover:bg-accent",
19125
+ onClick: props.onClose,
19126
+ children: t(PRESENTER_NAVIGATOR_LABEL_KEYS.close)
19127
+ }
19128
+ )
19058
19129
  ] }),
19059
- /* @__PURE__ */ jsx("div", { className: "grid flex-1 grid-cols-[repeat(auto-fill,minmax(220px,1fr))] gap-5 overflow-auto p-6", children: props.slides.map((slide, index) => /* @__PURE__ */ jsxs(
19130
+ /* @__PURE__ */ jsx("div", { className: PRESENTER_CONSOLE_CLASSES.navigatorGrid, children: props.slides.map((slide, index) => /* @__PURE__ */ jsxs(
19060
19131
  "button",
19061
19132
  {
19133
+ type: "button",
19062
19134
  className: `group text-left ${index === props.current ? "ring-2 ring-sky-400" : ""} ${slide.hidden ? "opacity-45" : ""}`,
19063
19135
  onClick: () => props.onSelect(index),
19064
19136
  children: [
@@ -19202,10 +19274,8 @@ function PresenterView({
19202
19274
  if (!currentSlide) {
19203
19275
  return /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-card text-muted-foreground", children: t("pptx.presenter.noSlides") });
19204
19276
  }
19205
- const TIMER_SEGMENT_MS = 5 * 60 * 1e3;
19206
- const timerProgress = Math.min(100, elapsed % TIMER_SEGMENT_MS / TIMER_SEGMENT_MS * 100);
19207
- const timerSegment = Math.floor(elapsed / TIMER_SEGMENT_MS);
19208
- return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-50 flex flex-col bg-card text-foreground", children: [
19277
+ const timerProgress = presenterTimerProgress(elapsed);
19278
+ return /* @__PURE__ */ jsxs("div", { className: PRESENTER_CONSOLE_CLASSES.root, children: [
19209
19279
  /* @__PURE__ */ jsx(
19210
19280
  PresenterConsoleToolbar,
19211
19281
  {
@@ -19226,14 +19296,14 @@ function PresenterView({
19226
19296
  onExit
19227
19297
  }
19228
19298
  ),
19229
- /* @__PURE__ */ jsxs("div", { className: "flex flex-1 min-h-0", children: [
19299
+ /* @__PURE__ */ jsxs("div", { className: PRESENTER_CONSOLE_CLASSES.body, children: [
19230
19300
  /* @__PURE__ */ jsxs(
19231
19301
  "div",
19232
19302
  {
19233
19303
  role: "presentation",
19234
19304
  "data-pptx-presenter-slide": true,
19235
19305
  onClick: handleSlidePaneClick,
19236
- className: `relative flex-[7] flex flex-col items-center justify-center bg-black p-6 min-w-0 overflow-hidden ${paneAdvancesOnClick ? "cursor-pointer" : ""}`,
19306
+ className: `${PRESENTER_CONSOLE_CLASSES.main} ${paneAdvancesOnClick ? "cursor-pointer" : ""}`,
19237
19307
  children: [
19238
19308
  endOfShowVisible && /* @__PURE__ */ jsx(PresentationEndOverlay, { onExit: () => onMovePresentationSlide(1) }),
19239
19309
  /* @__PURE__ */ jsxs(
@@ -19303,18 +19373,21 @@ function PresenterView({
19303
19373
  /* @__PURE__ */ jsx(
19304
19374
  "div",
19305
19375
  {
19306
- className: "h-1.5 w-full bg-muted/60 flex-shrink-0",
19376
+ className: PRESENTER_CONSOLE_CLASSES.progressTrack,
19307
19377
  role: "progressbar",
19308
- "aria-valuenow": Math.round(timerProgress),
19378
+ "aria-valuenow": Math.round(timerProgress.percent),
19309
19379
  "aria-valuemin": 0,
19310
19380
  "aria-valuemax": 100,
19311
19381
  "aria-label": t("pptx.presenter.timerProgress"),
19312
- title: `${formatElapsed(elapsed)} (segment ${timerSegment + 1})`,
19382
+ title: t("pptx.presenter.timerTitle", {
19383
+ elapsed: formatElapsed(elapsed),
19384
+ segment: timerProgress.segment + 1
19385
+ }),
19313
19386
  children: /* @__PURE__ */ jsx(
19314
19387
  "div",
19315
19388
  {
19316
- className: "h-full bg-primary transition-[width] duration-1000 ease-linear",
19317
- style: { width: `${timerProgress}%` }
19389
+ className: PRESENTER_CONSOLE_CLASSES.progressFill,
19390
+ style: { width: `${timerProgress.percent}%` }
19318
19391
  }
19319
19392
  )
19320
19393
  }
@@ -19345,8 +19418,8 @@ function MobilePresenterView({
19345
19418
  const notesText = currentSlide.notes ?? "";
19346
19419
  const notesSegments = currentSlide.notesSegments;
19347
19420
  const hasRichNotes = notesSegments && notesSegments.length > 0;
19348
- const atFirst = isFirstSlide(currentSlideIndex);
19349
- const atLast = isLastSlide(currentSlideIndex, slides.length);
19421
+ const prevDisabled = presenterPrevDisabled(currentSlideIndex);
19422
+ const nextDisabled = presenterNextDisabled();
19350
19423
  const insetStyle = {
19351
19424
  paddingTop: "env(safe-area-inset-top, 0px)",
19352
19425
  paddingBottom: "env(safe-area-inset-bottom, 0px)",
@@ -19400,8 +19473,9 @@ function MobilePresenterView({
19400
19473
  "button",
19401
19474
  {
19402
19475
  type: "button",
19476
+ "data-pptx-presenter-control": "prev",
19403
19477
  onClick: () => onMovePresentationSlide(-1),
19404
- disabled: atFirst,
19478
+ disabled: prevDisabled,
19405
19479
  className: "inline-flex items-center justify-center gap-1.5 flex-1 h-11 rounded bg-muted hover:bg-accent disabled:opacity-40 disabled:cursor-not-allowed text-sm transition-colors",
19406
19480
  title: t("pptx.presenter.previousSlide"),
19407
19481
  "aria-label": t("pptx.presenter.previousSlide"),
@@ -19415,8 +19489,9 @@ function MobilePresenterView({
19415
19489
  "button",
19416
19490
  {
19417
19491
  type: "button",
19492
+ "data-pptx-presenter-control": "next",
19418
19493
  onClick: () => onMovePresentationSlide(1),
19419
- disabled: atLast,
19494
+ disabled: nextDisabled,
19420
19495
  className: "inline-flex items-center justify-center gap-1.5 flex-1 h-11 rounded bg-muted hover:bg-accent disabled:opacity-40 disabled:cursor-not-allowed text-sm transition-colors",
19421
19496
  title: t("pptx.presenter.nextSlide"),
19422
19497
  "aria-label": t("pptx.presenter.nextSlide"),
@@ -19825,15 +19900,13 @@ function animationTypeColor(anim) {
19825
19900
  }
19826
19901
  return "bg-muted-foreground/40";
19827
19902
  }
19828
- function animationTypeLabel(anim) {
19829
- return anim.entrance ?? anim.emphasis ?? anim.exit ?? "custom";
19830
- }
19831
19903
  function AnimationTimelineSection({
19832
19904
  selectedElementId,
19833
19905
  canEdit,
19834
19906
  handlers
19835
19907
  }) {
19836
19908
  const { t } = useTranslation();
19909
+ const effectLabel = (anim) => animationEffectLabel(anim, (key) => t(key));
19837
19910
  const {
19838
19911
  sortedAnimations,
19839
19912
  dragIndex,
@@ -19869,7 +19942,7 @@ function AnimationTimelineSection({
19869
19942
  left: `${bar.leftPercent}%`,
19870
19943
  width: `${Math.max(bar.widthPercent, 2)}%`
19871
19944
  },
19872
- title: `${getTimelineLabel(bar.anim)} - ${animationTypeLabel(bar.anim)} (${bar.anim.durationMs ?? 500}ms)`,
19945
+ title: `${getTimelineLabel(bar.anim)} - ${effectLabel(bar.anim)} (${bar.anim.durationMs ?? 500}ms)`,
19873
19946
  onMouseEnter: () => handleAnimationHover(bar.anim),
19874
19947
  onMouseLeave: handleAnimationHoverEnd
19875
19948
  },
@@ -22411,7 +22484,7 @@ function ConnectorArrowsSection({
22411
22484
  ["Start", "End"].map((end) => {
22412
22485
  const widthKey = end === "Start" ? "connectorStartArrowWidth" : "connectorEndArrowWidth";
22413
22486
  const lengthKey = end === "Start" ? "connectorStartArrowLength" : "connectorEndArrowLength";
22414
- return /* @__PURE__ */ jsxs(React34.Fragment, { children: [
22487
+ return /* @__PURE__ */ jsxs(React35.Fragment, { children: [
22415
22488
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
22416
22489
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t(END_LABEL_KEYS[end].width) }),
22417
22490
  /* @__PURE__ */ jsx(
@@ -25240,7 +25313,7 @@ function StrokeEffectsSection({
25240
25313
  ] }),
25241
25314
  EFFECT_CONFIGS.map((cfg) => {
25242
25315
  const on = cfg.isOn(style);
25243
- return /* @__PURE__ */ jsxs(React34.Fragment, { children: [
25316
+ return /* @__PURE__ */ jsxs(React35.Fragment, { children: [
25244
25317
  /* @__PURE__ */ jsxs("label", { className: `inline-flex items-center gap-2 text-foreground ${COL2}`, children: [
25245
25318
  /* @__PURE__ */ jsx(
25246
25319
  "input",
@@ -26077,7 +26150,7 @@ function TextWarpGallery({
26077
26150
  onUpdateTextStyle
26078
26151
  }) {
26079
26152
  const { t } = useTranslation();
26080
- const [expanded, setExpanded] = React34.useState(false);
26153
+ const [expanded, setExpanded] = React35.useState(false);
26081
26154
  const currentPreset = ts?.textWarpPreset || "textNoShape";
26082
26155
  return /* @__PURE__ */ jsxs("div", { className: "mt-2 rounded border border-border bg-card p-2 space-y-2", children: [
26083
26156
  /* @__PURE__ */ jsxs(
@@ -26793,7 +26866,7 @@ function SmartArtStyleControls({
26793
26866
  onChangeStyle
26794
26867
  }) {
26795
26868
  const { t } = useTranslation();
26796
- const translate = React34.useCallback((key) => t(key), [t]);
26869
+ const translate = React35.useCallback((key) => t(key), [t]);
26797
26870
  return /* @__PURE__ */ jsxs(Fragment, { children: [
26798
26871
  /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1 text-[11px]", children: [
26799
26872
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("pptx.smartart.colorScheme") }),
@@ -26849,9 +26922,9 @@ function SmartArtPropertiesPanel({
26849
26922
  const nodes = smartArtData.nodes ?? [];
26850
26923
  const layout = smartArtData.resolvedLayoutType;
26851
26924
  const topLevelCount = nodes.filter((n) => !n.parentId).length;
26852
- const inputRefs = React34.useRef(/* @__PURE__ */ new Map());
26853
- const pendingFocusId = React34.useRef(null);
26854
- React34.useEffect(() => {
26925
+ const inputRefs = React35.useRef(/* @__PURE__ */ new Map());
26926
+ const pendingFocusId = React35.useRef(null);
26927
+ React35.useEffect(() => {
26855
26928
  const id = pendingFocusId.current;
26856
26929
  if (id) {
26857
26930
  inputRefs.current.get(id)?.focus();
@@ -29293,7 +29366,7 @@ function PresentationPropertiesPanel({
29293
29366
  onUpdateTagCollections
29294
29367
  }) {
29295
29368
  const { t } = useTranslation();
29296
- const handleTransitionChange = React34.useCallback(
29369
+ const handleTransitionChange = React35.useCallback(
29297
29370
  (updates) => {
29298
29371
  onUpdateSlide({
29299
29372
  transition: mergeSlideTransition(activeSlide?.transition, updates)
@@ -30012,26 +30085,6 @@ function PresentationAnnotationOverlay({
30012
30085
  }
30013
30086
  );
30014
30087
  }
30015
- var PEN_COLORS = [
30016
- "#ff0000",
30017
- "#0000ff",
30018
- "#00aa00",
30019
- "#ff8800",
30020
- "#ffffff",
30021
- "#000000",
30022
- "#ff00ff",
30023
- "#00cccc"
30024
- ];
30025
- var HIGHLIGHTER_COLORS = [
30026
- "#ffff00",
30027
- "#00ff00",
30028
- "#ff69b4",
30029
- "#00bfff",
30030
- "#ff8c00",
30031
- "#adff2f",
30032
- "#ff6347",
30033
- "#87ceeb"
30034
- ];
30035
30088
  function PresentationToolbar({
30036
30089
  presentationTool,
30037
30090
  penColor,
@@ -30090,19 +30143,24 @@ function PresentationToolbar({
30090
30143
  setShowHighlighterColors((prev) => !prev);
30091
30144
  setShowPenColors(false);
30092
30145
  }, []);
30093
- const toolBtnClass = (tool) => `flex items-center justify-center w-9 h-9 rounded-md transition-colors ${presentationTool === tool ? "bg-white/25 text-white" : "text-white/70 hover:text-white hover:bg-white/10"}`;
30094
- const navBtnClass = "flex items-center justify-center w-9 h-9 rounded-md transition-colors text-white/70 hover:text-white hover:bg-white/10 disabled:text-white/20 disabled:cursor-not-allowed";
30146
+ const toolBtnClass = (tool) => presentationTool === tool ? PRESENT_TOOLBAR_CLASSES.toggleActive : PRESENT_TOOLBAR_CLASSES.toggle;
30147
+ const navBtnClass = PRESENT_TOOLBAR_CLASSES.button;
30095
30148
  return /* @__PURE__ */ jsxs(
30096
30149
  "div",
30097
30150
  {
30098
30151
  ref: toolbarRef,
30099
- className: "flex items-center gap-1 px-3 py-2 rounded-xl bg-neutral-900/90 backdrop-blur-md border border-white/15 shadow-2xl",
30152
+ "data-pptx-present-toolbar": true,
30153
+ role: "toolbar",
30154
+ tabIndex: -1,
30155
+ "aria-label": t("pptx.toolbar.presentationToolbarAria"),
30156
+ className: PRESENT_TOOLBAR_CLASSES.container,
30100
30157
  onClick: (e) => e.stopPropagation(),
30101
30158
  children: [
30102
30159
  /* @__PURE__ */ jsx(
30103
30160
  "button",
30104
30161
  {
30105
30162
  type: "button",
30163
+ "data-pptx-present-control": "previous",
30106
30164
  className: navBtnClass,
30107
30165
  onClick: () => onMovePresentationSlide(-1),
30108
30166
  disabled: currentSlideIndex === 0,
@@ -30111,11 +30169,12 @@ function PresentationToolbar({
30111
30169
  children: /* @__PURE__ */ jsx(LuChevronLeft, { size: 18 })
30112
30170
  }
30113
30171
  ),
30114
- /* @__PURE__ */ jsx("span", { className: "text-xs font-mono tabular-nums text-white/80 px-1.5 select-none min-w-[48px] text-center", children: formatSlideCounter(currentSlideIndex, totalSlides) }),
30172
+ /* @__PURE__ */ jsx("span", { "data-pptx-present-control": "counter", className: PRESENT_TOOLBAR_CLASSES.counter, children: formatSlideCounter(currentSlideIndex, totalSlides) }),
30115
30173
  /* @__PURE__ */ jsx(
30116
30174
  "button",
30117
30175
  {
30118
30176
  type: "button",
30177
+ "data-pptx-present-control": "next",
30119
30178
  className: navBtnClass,
30120
30179
  onClick: () => onMovePresentationSlide(1),
30121
30180
  disabled: currentSlideIndex >= totalSlides - 1,
@@ -30124,26 +30183,36 @@ function PresentationToolbar({
30124
30183
  children: /* @__PURE__ */ jsx(LuChevronRight, { size: 18 })
30125
30184
  }
30126
30185
  ),
30127
- /* @__PURE__ */ jsx("div", { className: "w-px h-6 bg-white/20 mx-1" }),
30186
+ /* @__PURE__ */ jsx(
30187
+ "div",
30188
+ {
30189
+ "data-pptx-present-control": "divider-navigation",
30190
+ className: PRESENT_TOOLBAR_CLASSES.divider
30191
+ }
30192
+ ),
30128
30193
  /* @__PURE__ */ jsxs(
30129
30194
  "div",
30130
30195
  {
30131
- className: "flex items-center gap-1.5 text-xs font-mono tabular-nums text-white/60 px-1 select-none",
30196
+ "data-pptx-present-control": "timer",
30197
+ className: PRESENT_TOOLBAR_CLASSES.timer,
30132
30198
  title: t("pptx.presenter.elapsed"),
30199
+ "aria-label": t("pptx.presenter.elapsed"),
30133
30200
  children: [
30134
30201
  /* @__PURE__ */ jsx(LuTimer, { size: 14 }),
30135
30202
  /* @__PURE__ */ jsx("span", { children: formatElapsed(elapsed) })
30136
30203
  ]
30137
30204
  }
30138
30205
  ),
30139
- /* @__PURE__ */ jsx("div", { className: "w-px h-6 bg-white/20 mx-1" }),
30206
+ /* @__PURE__ */ jsx("div", { "data-pptx-present-control": "divider-timer", className: PRESENT_TOOLBAR_CLASSES.divider }),
30140
30207
  /* @__PURE__ */ jsx(
30141
30208
  "button",
30142
30209
  {
30143
30210
  type: "button",
30211
+ "data-pptx-present-control": "laser",
30144
30212
  className: toolBtnClass("laser"),
30145
30213
  onClick: () => handleToolClick("laser"),
30146
30214
  title: t("pptx.presentation.laserPointer"),
30215
+ "aria-label": t("pptx.presentation.laserPointer"),
30147
30216
  children: /* @__PURE__ */ jsx(LuMousePointer2, { size: 18 })
30148
30217
  }
30149
30218
  ),
@@ -30152,16 +30221,18 @@ function PresentationToolbar({
30152
30221
  "button",
30153
30222
  {
30154
30223
  type: "button",
30224
+ "data-pptx-present-control": "pen",
30155
30225
  className: toolBtnClass("pen"),
30156
30226
  onClick: () => handleToolClick("pen"),
30157
30227
  onContextMenu: handlePenRightClick,
30158
30228
  title: t("pptx.presentation.pen"),
30229
+ "aria-label": t("pptx.presentation.pen"),
30159
30230
  children: [
30160
30231
  /* @__PURE__ */ jsx(LuPenTool, { size: 18 }),
30161
30232
  /* @__PURE__ */ jsx(
30162
30233
  "div",
30163
30234
  {
30164
- className: "absolute bottom-0.5 left-1/2 -translate-x-1/2 w-3 h-0.5 rounded-full",
30235
+ className: PRESENT_TOOLBAR_CLASSES.swatchBar,
30165
30236
  style: { backgroundColor: penColor }
30166
30237
  }
30167
30238
  )
@@ -30172,21 +30243,23 @@ function PresentationToolbar({
30172
30243
  "button",
30173
30244
  {
30174
30245
  type: "button",
30175
- className: "flex items-center justify-center w-7 h-9 -ml-1 rounded-r-md transition-colors text-white/50 hover:text-white hover:bg-white/10",
30246
+ "data-pptx-present-control": "pen-color",
30247
+ className: PRESENT_TOOLBAR_CLASSES.caret,
30176
30248
  onClick: () => {
30177
30249
  setShowPenColors((prev) => !prev);
30178
30250
  setShowHighlighterColors(false);
30179
30251
  },
30180
- title: `${t("pptx.presentation.pen")} \u2014 color`,
30252
+ title: t("pptx.presentationToolbar.penColor"),
30253
+ "aria-label": t("pptx.presentationToolbar.penColor"),
30181
30254
  children: /* @__PURE__ */ jsx(LuChevronDown, { size: 12 })
30182
30255
  }
30183
30256
  ),
30184
- showPenColors && /* @__PURE__ */ jsx("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 p-3 bg-neutral-800 rounded-lg border border-white/20 shadow-xl grid grid-cols-4 gap-2", children: PEN_COLORS.map((color) => /* @__PURE__ */ jsx(
30257
+ showPenColors && /* @__PURE__ */ jsx("div", { className: PRESENT_TOOLBAR_CLASSES.palette, children: PEN_COLORS.map((color) => /* @__PURE__ */ jsx(
30185
30258
  "button",
30186
30259
  {
30187
30260
  type: "button",
30188
- "aria-label": `${t("pptx.presentation.pen")} ${color}`,
30189
- className: `w-9 h-9 rounded-full border-2 transition-transform hover:scale-110 ${penColor === color ? "border-white" : "border-white/20"}`,
30261
+ "aria-label": t("pptx.presentationToolbar.penColorValue", { color }),
30262
+ className: `${PRESENT_TOOLBAR_CLASSES.swatch} ${penColor === color ? "border-white" : "border-white/20"}`,
30190
30263
  style: { backgroundColor: color },
30191
30264
  onClick: () => {
30192
30265
  onSetPenColor(color);
@@ -30204,16 +30277,18 @@ function PresentationToolbar({
30204
30277
  "button",
30205
30278
  {
30206
30279
  type: "button",
30280
+ "data-pptx-present-control": "highlighter",
30207
30281
  className: toolBtnClass("highlighter"),
30208
30282
  onClick: () => handleToolClick("highlighter"),
30209
30283
  onContextMenu: handleHighlighterRightClick,
30210
30284
  title: t("pptx.presentation.highlighter"),
30285
+ "aria-label": t("pptx.presentation.highlighter"),
30211
30286
  children: [
30212
30287
  /* @__PURE__ */ jsx(LuHighlighter, { size: 18 }),
30213
30288
  /* @__PURE__ */ jsx(
30214
30289
  "div",
30215
30290
  {
30216
- className: "absolute bottom-0.5 left-1/2 -translate-x-1/2 w-3 h-0.5 rounded-full",
30291
+ className: PRESENT_TOOLBAR_CLASSES.swatchBar,
30217
30292
  style: { backgroundColor: highlighterColor }
30218
30293
  }
30219
30294
  )
@@ -30224,21 +30299,23 @@ function PresentationToolbar({
30224
30299
  "button",
30225
30300
  {
30226
30301
  type: "button",
30227
- className: "flex items-center justify-center w-7 h-9 -ml-1 rounded-r-md transition-colors text-white/50 hover:text-white hover:bg-white/10",
30302
+ "data-pptx-present-control": "highlighter-color",
30303
+ className: PRESENT_TOOLBAR_CLASSES.caret,
30228
30304
  onClick: () => {
30229
30305
  setShowHighlighterColors((prev) => !prev);
30230
30306
  setShowPenColors(false);
30231
30307
  },
30232
- title: `${t("pptx.presentation.highlighter")} \u2014 color`,
30308
+ title: t("pptx.presentationToolbar.highlighterColor"),
30309
+ "aria-label": t("pptx.presentationToolbar.highlighterColor"),
30233
30310
  children: /* @__PURE__ */ jsx(LuChevronDown, { size: 12 })
30234
30311
  }
30235
30312
  ),
30236
- showHighlighterColors && /* @__PURE__ */ jsx("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 p-3 bg-neutral-800 rounded-lg border border-white/20 shadow-xl grid grid-cols-4 gap-2", children: HIGHLIGHTER_COLORS.map((color) => /* @__PURE__ */ jsx(
30313
+ showHighlighterColors && /* @__PURE__ */ jsx("div", { className: PRESENT_TOOLBAR_CLASSES.palette, children: HIGHLIGHTER_COLORS.map((color) => /* @__PURE__ */ jsx(
30237
30314
  "button",
30238
30315
  {
30239
30316
  type: "button",
30240
- "aria-label": `${t("pptx.presentation.highlighter")} ${color}`,
30241
- className: `w-9 h-9 rounded-full border-2 transition-transform hover:scale-110 ${highlighterColor === color ? "border-white" : "border-white/20"}`,
30317
+ "aria-label": t("pptx.presentationToolbar.highlighterColorValue", { color }),
30318
+ className: `${PRESENT_TOOLBAR_CLASSES.swatch} ${highlighterColor === color ? "border-white" : "border-white/20"}`,
30242
30319
  style: { backgroundColor: color },
30243
30320
  onClick: () => {
30244
30321
  onSetHighlighterColor(color);
@@ -30255,9 +30332,11 @@ function PresentationToolbar({
30255
30332
  "button",
30256
30333
  {
30257
30334
  type: "button",
30335
+ "data-pptx-present-control": "eraser",
30258
30336
  className: toolBtnClass("eraser"),
30259
30337
  onClick: () => handleToolClick("eraser"),
30260
30338
  title: t("pptx.presentation.eraser"),
30339
+ "aria-label": t("pptx.presentation.eraser"),
30261
30340
  children: /* @__PURE__ */ jsx(LuEraser, { size: 18 })
30262
30341
  }
30263
30342
  ),
@@ -30265,22 +30344,25 @@ function PresentationToolbar({
30265
30344
  "button",
30266
30345
  {
30267
30346
  type: "button",
30268
- className: `flex items-center justify-center w-9 h-9 rounded-md transition-colors ${hasAnnotations ? "text-white/70 hover:text-red-400 hover:bg-white/10" : "text-white/30 cursor-not-allowed"}`,
30347
+ "data-pptx-present-control": "clear",
30348
+ className: `${PRESENT_TOOLBAR_CLASSES.button} ${hasAnnotations ? "hover:text-red-400" : ""}`,
30269
30349
  onClick: hasAnnotations ? onClearAnnotations : void 0,
30270
30350
  title: t("pptx.presentation.clearAnnotations"),
30351
+ "aria-label": t("pptx.presentation.clearAnnotations"),
30271
30352
  disabled: !hasAnnotations,
30272
30353
  children: /* @__PURE__ */ jsx(LuTrash2, { size: 18 })
30273
30354
  }
30274
30355
  ),
30275
- /* @__PURE__ */ jsx("div", { className: "w-px h-6 bg-white/20 mx-1" }),
30356
+ /* @__PURE__ */ jsx("div", { "data-pptx-present-control": "divider-tools", className: PRESENT_TOOLBAR_CLASSES.divider }),
30276
30357
  onTogglePresenterView && /* @__PURE__ */ jsx(
30277
30358
  "button",
30278
30359
  {
30279
30360
  type: "button",
30280
- className: `flex items-center justify-center w-9 h-9 rounded-md transition-colors ${presenterMode ? "bg-white/25 text-white" : "text-white/70 hover:text-white hover:bg-white/10"}`,
30361
+ "data-pptx-present-control": "presenter-view",
30362
+ className: presenterMode ? PRESENT_TOOLBAR_CLASSES.toggleActive : PRESENT_TOOLBAR_CLASSES.toggle,
30281
30363
  onClick: onTogglePresenterView,
30282
- title: t("pptx.presenter.presenterView", { defaultValue: "Presenter view" }),
30283
- "aria-label": t("pptx.presenter.presenterView", { defaultValue: "Presenter view" }),
30364
+ title: t("pptx.presenter.presenterView"),
30365
+ "aria-label": t("pptx.presenter.presenterView"),
30284
30366
  children: /* @__PURE__ */ jsx(LuPanelRight, { size: 18 })
30285
30367
  }
30286
30368
  ),
@@ -30288,7 +30370,8 @@ function PresentationToolbar({
30288
30370
  "button",
30289
30371
  {
30290
30372
  type: "button",
30291
- className: "flex items-center justify-center w-9 h-9 rounded-md transition-colors text-white/70 hover:text-red-400 hover:bg-white/10",
30373
+ "data-pptx-present-control": "end",
30374
+ className: `${PRESENT_TOOLBAR_CLASSES.button} hover:text-red-400`,
30292
30375
  onClick: onEndPresentation,
30293
30376
  title: t("pptx.presenter.endPresentation"),
30294
30377
  "aria-label": t("pptx.presenter.endPresentation"),
@@ -33216,7 +33299,7 @@ function ViewerToolbarSection(props) {
33216
33299
  },
33217
33300
  [activeSlide, propertyHandlers]
33218
33301
  );
33219
- const scopedLayoutOptions = React34.useMemo(
33302
+ const scopedLayoutOptions = React35.useMemo(
33220
33303
  () => scopeLayoutOptionsToActiveSlide(s.layoutOptions, activeSlide),
33221
33304
  [s.layoutOptions, activeSlide]
33222
33305
  );
@@ -34935,7 +35018,7 @@ ${url}`)) {
34935
35018
  mode === "present" && /* @__PURE__ */ jsx(
34936
35019
  "div",
34937
35020
  {
34938
- className: "absolute bottom-6 left-1/2 -translate-x-1/2 z-[80] transition-opacity duration-300",
35021
+ className: PRESENT_TOOLBAR_CLASSES.wrapper,
34939
35022
  style: {
34940
35023
  opacity: annotations.toolbarVisible ? 1 : 0,
34941
35024
  pointerEvents: annotations.toolbarVisible ? "auto" : "none"
@@ -34970,7 +35053,7 @@ ${url}`)) {
34970
35053
  )
34971
35054
  );
34972
35055
  }
34973
- var AiChatPanel = lazy(() => import('./AiChatPanel-RMQIJDUJ.mjs'));
35056
+ var AiChatPanel = lazy(() => import('./AiChatPanel-CGGUPVQX.mjs'));
34974
35057
  function AiChatPanelLazy(props) {
34975
35058
  return /* @__PURE__ */ jsx(
34976
35059
  Suspense,