pptx-react-viewer 1.24.0 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +46 -21
  3. package/dist/{Model3DScene-RD4XEC3F.js → Model3DScene-G434BPF4.js} +2 -2
  4. package/dist/Model3DScene-G434BPF4.js.br +0 -0
  5. package/dist/Model3DScene-G434BPF4.js.gz +0 -0
  6. package/dist/{Model3DScene-QTNGCODM.mjs → Model3DScene-GGNUAOGD.mjs} +1 -1
  7. package/dist/Model3DScene-GGNUAOGD.mjs.br +0 -0
  8. package/dist/Model3DScene-GGNUAOGD.mjs.gz +0 -0
  9. package/dist/PowerPointViewer-CnADroqZ.d.ts.map +1 -1
  10. package/dist/{SurfaceChart3DScene-VKS3ELTU.mjs → SurfaceChart3DScene-JU737NN5.mjs} +1 -1
  11. package/dist/SurfaceChart3DScene-JU737NN5.mjs.br +0 -0
  12. package/dist/SurfaceChart3DScene-JU737NN5.mjs.gz +0 -0
  13. package/dist/{SurfaceChart3DScene-YR3GX4X6.js → SurfaceChart3DScene-UFFJ3P6T.js} +2 -2
  14. package/dist/{SurfaceChart3DScene-YR3GX4X6.js.br → SurfaceChart3DScene-UFFJ3P6T.js.br} +0 -0
  15. package/dist/SurfaceChart3DScene-UFFJ3P6T.js.gz +0 -0
  16. package/dist/{chunk-ZISXRMDJ.js → chunk-2EFVXYNA.js} +187 -1
  17. package/dist/chunk-2EFVXYNA.js.br +0 -0
  18. package/dist/{chunk-ZISXRMDJ.js.gz → chunk-2EFVXYNA.js.gz} +0 -0
  19. package/dist/{chunk-3YMK5VLS.js → chunk-EM77GISR.js} +1675 -1033
  20. package/dist/chunk-EM77GISR.js.br +0 -0
  21. package/dist/chunk-EM77GISR.js.gz +0 -0
  22. package/dist/{chunk-GKST4OS7.js → chunk-IHHK6WEQ.js} +555 -446
  23. package/dist/chunk-IHHK6WEQ.js.br +0 -0
  24. package/dist/chunk-IHHK6WEQ.js.gz +0 -0
  25. package/dist/{chunk-E3KJKCSV.mjs → chunk-M3SIFXWD.mjs} +187 -1
  26. package/dist/chunk-M3SIFXWD.mjs.br +0 -0
  27. package/dist/{chunk-E3KJKCSV.mjs.gz → chunk-M3SIFXWD.mjs.gz} +0 -0
  28. package/dist/{chunk-PUQ6GIOM.mjs → chunk-NKSIDFYP.mjs} +972 -330
  29. package/dist/chunk-NKSIDFYP.mjs.br +0 -0
  30. package/dist/chunk-NKSIDFYP.mjs.gz +0 -0
  31. package/dist/{chunk-KPT54MHG.mjs → chunk-QOBKJKLT.mjs} +861 -10
  32. package/dist/chunk-QOBKJKLT.mjs.br +0 -0
  33. package/dist/{chunk-KPT54MHG.mjs.gz → chunk-QOBKJKLT.mjs.gz} +0 -0
  34. package/dist/{chunk-YJVMOX2Y.mjs → chunk-VDALVGDT.mjs} +151 -43
  35. package/dist/chunk-VDALVGDT.mjs.br +0 -0
  36. package/dist/chunk-VDALVGDT.mjs.gz +0 -0
  37. package/dist/{chunk-I5SO5OV4.js → chunk-VKOVFVDJ.js} +876 -10
  38. package/dist/chunk-VKOVFVDJ.js.br +0 -0
  39. package/dist/{chunk-I5SO5OV4.js.gz → chunk-VKOVFVDJ.js.gz} +0 -0
  40. package/dist/hooks-unstable.d.ts +231 -4
  41. package/dist/hooks-unstable.d.ts.map +1 -1
  42. package/dist/hooks-unstable.js +81 -77
  43. package/dist/hooks-unstable.js.br +0 -0
  44. package/dist/hooks-unstable.js.gz +0 -0
  45. package/dist/hooks-unstable.mjs +3 -3
  46. package/dist/hooks-unstable.mjs.br +0 -0
  47. package/dist/hooks-unstable.mjs.gz +0 -0
  48. package/dist/i18n.js +4 -4
  49. package/dist/i18n.js.br +0 -0
  50. package/dist/i18n.js.gz +0 -0
  51. package/dist/i18n.mjs +1 -1
  52. package/dist/i18n.mjs.br +0 -0
  53. package/dist/i18n.mjs.gz +0 -0
  54. package/dist/{index-hm2FF-FU.d.ts → index-DWvM1PBB.d.ts} +25 -2
  55. package/dist/index-DWvM1PBB.d.ts.map +1 -0
  56. package/dist/index.d.ts +146 -26
  57. package/dist/index.js +34 -34
  58. package/dist/index.js.br +0 -0
  59. package/dist/index.js.gz +0 -0
  60. package/dist/index.mjs +4 -4
  61. package/dist/index.mjs.br +0 -0
  62. package/dist/index.mjs.gz +0 -0
  63. package/dist/pptx-viewer.css +1 -1
  64. package/dist/pptx-viewer.css.br +0 -0
  65. package/dist/pptx-viewer.css.gz +0 -0
  66. package/dist/viewer/index.js +20 -20
  67. package/dist/viewer/index.js.br +0 -0
  68. package/dist/viewer/index.js.gz +0 -0
  69. package/dist/viewer/index.mjs +4 -4
  70. package/dist/viewer/index.mjs.br +0 -0
  71. package/dist/viewer/index.mjs.gz +0 -0
  72. package/package.json +1 -1
  73. package/dist/Model3DScene-QTNGCODM.mjs.br +0 -0
  74. package/dist/Model3DScene-QTNGCODM.mjs.gz +0 -0
  75. package/dist/Model3DScene-RD4XEC3F.js.br +0 -0
  76. package/dist/Model3DScene-RD4XEC3F.js.gz +0 -0
  77. package/dist/SurfaceChart3DScene-VKS3ELTU.mjs.br +0 -0
  78. package/dist/SurfaceChart3DScene-VKS3ELTU.mjs.gz +0 -0
  79. package/dist/SurfaceChart3DScene-YR3GX4X6.js.gz +0 -0
  80. package/dist/chunk-3YMK5VLS.js.br +0 -0
  81. package/dist/chunk-3YMK5VLS.js.gz +0 -0
  82. package/dist/chunk-E3KJKCSV.mjs.br +0 -0
  83. package/dist/chunk-GKST4OS7.js.br +0 -0
  84. package/dist/chunk-GKST4OS7.js.gz +0 -0
  85. package/dist/chunk-I5SO5OV4.js.br +0 -0
  86. package/dist/chunk-KPT54MHG.mjs.br +0 -0
  87. package/dist/chunk-PUQ6GIOM.mjs.br +0 -0
  88. package/dist/chunk-PUQ6GIOM.mjs.gz +0 -0
  89. package/dist/chunk-YJVMOX2Y.mjs.br +0 -0
  90. package/dist/chunk-YJVMOX2Y.mjs.gz +0 -0
  91. package/dist/chunk-ZISXRMDJ.js.br +0 -0
  92. package/dist/index-hm2FF-FU.d.ts.map +0 -1
@@ -1,11 +1,11 @@
1
- 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, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useYjsDocumentSync, useFollowMode, useBroadcastFollower, resolvePalette, resolveStyle, layoutToCategory, wrapChrome, DEFAULT_FILL_COLOR, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, getCropShapeClipPath, SLIDE_TRANSITION_OPTIONS, SLIDE_NAV_THUMBNAIL_WIDTH, scopeLayoutOptionsToActiveSlide, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, SHORTCUT_REFERENCE_ITEMS, useCollaborativeState, 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, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, buildTree, treeWidth, treeDepth, nodeOpacity, gearPath, resolveSmartArtDataPalette, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, HYPERLINK_COLOR, GRID_SIZE, startPreviewAnimation, stopPreviewAnimation } from './chunk-YJVMOX2Y.mjs';
2
- import { RULER_THICKNESS, RULER_FONT_SIZE, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, getElementTransform, ACTION_BUTTON_PRESETS, isEditableTextElement, getAriaRole, getAriaLabel, getAriaRoleDescription, getImageEffectsOpacity, getImageEffectsFilter, getElementTransformWithoutRotation, EQUATION_TEMPLATES, convertLatexToOmml, convertOmmlToMathMl, sanitizeMathMl, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, buildSmartArtA11y, buildCssGradientFromShapeStyle, getElementLabel, themeToCssVars, DEFAULT_INSERT_CHART_TYPE, hasCopyableFormat, createBackstagePresentation, SETTING_TOGGLES, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, resolveDrawingShapeNodeId, buildSummaryZoomView, getImageColorWashStyle, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleTypeColor, getOleTypeLabel, shouldUseSvgWarp, getSlideBackgroundStyle, filterCommands, resolveTitleBarStatusKey, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, safeOpenUrl, isPpactionUrl, parsePpactionUrl, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, clampPercent, HANDOUT_OPTIONS, activateModalFocus, buildCollaborationShareUrl, presentationInkPath, mobileElapsedSince, isFirstSlide, isLastSlide, formatMobileElapsed, mobileSlideCounter, formatElapsed, computeInlineEditorRect, findSmartArtNodeText, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, 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, getWarpPath, TAB_ROW_ACTION_CLASSES, listBackstageRecentFiles, BACKSTAGE_NAV, INSERT_CHART_TYPES, SLIDE_VIRTUALIZATION_THRESHOLD, getShapeAdjustmentHandleDescriptor, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES, formatSlideCounter, isUrlSafe, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, 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, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, getConnectionSites, generateTicks, getCommentMarkerPosition, buildThemeColorGrid, THEME_COLOR_LABELS, buildSmartArtPresetData, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, TABLE_STYLE_PRESETS, formatCommentTimestamp, DIRECTIONAL_PRESETS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, DUOTONE_PRESETS, ARTISTIC_EFFECTS, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS } from './chunk-KPT54MHG.mjs';
3
- import { LOCALE_CATALOG, translationsEn } from './chunk-E3KJKCSV.mjs';
1
+ 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, useReducedMotion, useViewerState, useViewerOptions, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useYjsDocumentSync, useFollowMode, useBroadcastFollower, resolvePalette, resolveStyle, layoutToCategory, wrapChrome, DEFAULT_FILL_COLOR, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, getTextLayoutStyle, renderTableElement, renderMediaElement, shouldRenderFallbackLabel, getCropShapeClipPath, SLIDE_TRANSITION_OPTIONS, SLIDE_NAV_THUMBNAIL_WIDTH, scopeLayoutOptionsToActiveSlide, useToolbarVisibility, useKeyboardInsets, useModalDismissDrag, useCollaborativeState, 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, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, 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, startPreviewAnimation, stopPreviewAnimation } from './chunk-VDALVGDT.mjs';
2
+ import { RULER_THICKNESS, RULER_FONT_SIZE, normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, getElementTransform, ACTION_BUTTON_PRESETS, isEditableTextElement, getAriaRole, getAriaLabel, getAriaRoleDescription, getImageEffectsOpacity, getImageEffectsFilter, getElementTransformWithoutRotation, EQUATION_TEMPLATES, convertLatexToOmml, convertOmmlToMathMl, sanitizeMathMl, DEFAULT_VIEWER_OPTIONS, buildUserFontFaceStyles, readStoredViewerPrefs, resolveThemeCatalogEntry, THEME_CATALOG, writeStoredViewerPrefs, openPptxFile, readBackstageRecentFile, viewerOptionsToPreferences, applyPreferenceToOptions, listAutosaveSnapshots, deleteAutosaveSnapshot, buildSmartArtA11y, buildCssGradientFromShapeStyle, getElementLabel, themeToCssVars, DEFAULT_INSERT_CHART_TYPE, hasCopyableFormat, createBackstagePresentation, VIEWER_OPTIONS_TABS, DEFAULT_QUICK_ACCESS_COMMAND_IDS, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, resolveDrawingShapeNodeId, buildSummaryZoomView, getImageColorWashStyle, getPendingSelectionRestore, restoreSegmentSelection, getTextCompensationTransform, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleTypeColor, getOleTypeLabel, shouldUseSvgWarp, getSlideBackgroundStyle, filterCommands, resolveTitleBarStatusKey, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, shouldConfirmExternalHyperlink, safeOpenUrl, isPpactionUrl, parsePpactionUrl, formatVersionTimestamp, formatRelativeTime, scanAvailableFontFamilies, PRESETS, CATEGORIES, convertOmmlToLatex, clampPercent, HANDOUT_OPTIONS, TOOLBAR_TABS, SHORTCUT_REFERENCE_ITEMS, resolveViewerAddinRows, availableQuickAccessCommands, addQuickAccessCommand, removeQuickAccessCommand, moveQuickAccessCommand, activateModalFocus, buildCollaborationShareUrl, presentationInkPath, mobileElapsedSince, isFirstSlide, isLastSlide, formatMobileElapsed, mobileSlideCounter, formatElapsed, computeInlineEditorRect, findSmartArtNodeText, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, 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, getWarpPath, TAB_ROW_ACTION_CLASSES, listBackstageRecentFiles, BACKSTAGE_NAV, INSERT_CHART_TYPES, SLIDE_VIRTUALIZATION_THRESHOLD, getShapeAdjustmentHandleDescriptor, getSlideTransitionAnimations, SLIDE_TRANSITION_KEYFRAMES, formatSlideCounter, isUrlSafe, computeHandoutLayout, getPrintableArea, generateNoteLineCount, computeAllNotesPages, getNotesPrintableArea, QUICK_ACCESS_COMMAND_CATALOG, 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, DEFAULT_VIEWER_PROFILE, resolveProfileInitial, AVATAR_COLOR_SWATCHES, getConnectionSites, generateTicks, getCommentMarkerPosition, buildThemeColorGrid, THEME_COLOR_LABELS, buildSmartArtPresetData, getLocalStorageUsageSummary, saveViewerProfile, clearAllLocalViewerData, TABLE_STYLE_PRESETS, formatCommentTimestamp, DIRECTIONAL_PRESETS, computeMergeCellRight, computeMergeCellDown, computeSplitCell, DUOTONE_PRESETS, ARTISTIC_EFFECTS, LBL, SEL, FILL_MODE_OPTIONS, SECTION_HEADING, NUM, GRADIENT_TYPE_OPTIONS, PATTERN_OPTIONS } from './chunk-QOBKJKLT.mjs';
3
+ import { LOCALE_CATALOG, translationsEn } from './chunk-M3SIFXWD.mjs';
4
4
  import { hasShapeProperties, hasTextProperties, SWITCHABLE_LAYOUT_TYPES, isInkElement, isImageLikeElement, getLinkedTextBoxSegments, themeColorSchemesEqual, setSmartArtNodeStyle, updateSmartArtNodeText, getSubstituteFontFamily, THEME_COLOR_SCHEME_KEYS, chartDataChangeType, chartDataUpdatePoint, chartDataAddCategory, chartDataRemoveCategory, chartDataAddSeries, chartDataRemoveSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, getOleObjectTypeLabel, pptxActionToElementAction, applyThemeOverrideToSlide, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, addSmartArtNodeAsChild, removeSmartArtNode, elementActionToPptxAction, switchSmartArtLayout, addSmartArtNode, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode } from './chunk-LDZQNYWL.mjs';
5
5
  import React32, { createContext, useMemo, useState, useCallback, forwardRef, useEffect, useRef, useContext, Suspense, useLayoutEffect, useDeferredValue } from 'react';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
  import { useTranslation } from 'react-i18next';
8
- 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, LuWifi, LuWifiOff, LuUsers, LuCopy, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuMenu, LuShare2, LuPanelLeft, LuPanelRight, LuArrowLeft, LuFolderOpen, LuPackage, LuFileImage, LuVideo, LuBox, LuClipboardPaste, LuScissors, LuPaintbrush, LuChevronDown, LuSquare, LuImage, LuDatabase, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuReplace, LuMousePointer2, LuShapes, LuPaintBucket, LuPenLine, LuSparkles, LuChevronUp, LuPalette, LuPencil, LuStar, LuMoveRight, LuMousePointerClick, LuClock3, LuMonitorPlay, LuListVideo, LuCaptions, LuCamera, LuEraser, LuRotateCcw, LuCircleHelp, LuSpellCheck, LuBookOpen, LuLanguages, LuGlobe, LuGitCompare, LuMessageSquarePlus, LuLockKeyhole, LuPanelTop, LuLayoutGrid, LuGrid3X3, LuPipette, LuRuler, LuZoomIn, LuMaximize2, LuCode, LuCaseSensitive, LuTimer, LuGripVertical, LuUpload, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuCirclePlay, LuCirclePause, LuZoomOut, LuScan, LuMonitorOff, LuClipboardCopy, LuWand, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuFilePlus2, LuHouse, LuUser, LuHardDrive, LuLogIn, LuFolderPlus, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuColumns3, LuSpline, LuAlignHorizontalSpaceAround, LuAlignVerticalSpaceAround, LuMove, LuRadio, LuLockOpen, LuArrowDown, LuArrowUp, LuArrowRight, LuReply, LuBookmark } from 'react-icons/lu';
8
+ 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, LuChevronUp, LuChevronDown, LuWifi, LuWifiOff, LuUsers, LuCopy, LuChevronLeft, LuChevronRight, LuPlay, LuPause, LuMenu, LuShare2, LuPanelLeft, LuPanelRight, LuArrowLeft, LuFolderOpen, LuPackage, LuFileImage, LuVideo, LuBox, LuClipboardPaste, LuScissors, LuPaintbrush, LuSquare, LuImage, LuDatabase, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuReplace, LuMousePointer2, LuShapes, LuPaintBucket, LuPenLine, LuSparkles, LuPalette, LuPencil, LuStar, LuMoveRight, LuMousePointerClick, LuClock3, LuMonitorPlay, LuListVideo, LuCaptions, LuCamera, LuEraser, LuRotateCcw, LuCircleHelp, LuSpellCheck, LuBookOpen, LuLanguages, LuGlobe, LuGitCompare, LuMessageSquarePlus, LuLockKeyhole, LuPanelTop, LuLayoutGrid, LuGrid3X3, LuPipette, LuRuler, LuZoomIn, LuMaximize2, LuCode, LuCaseSensitive, LuTimer, LuGripVertical, LuUpload, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuCirclePlay, LuCirclePause, LuZoomOut, LuScan, LuMonitorOff, LuClipboardCopy, LuWand, LuTextCursorInput, LuFile, LuEllipsis, LuUserRound, LuFilePlus2, LuHouse, LuUser, LuHardDrive, LuLogIn, LuFolderPlus, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuColumns3, LuSpline, LuAlignHorizontalSpaceAround, LuAlignVerticalSpaceAround, LuMove, LuRadio, LuLockOpen, LuArrowDown, LuArrowUp, LuArrowRight, LuReply, LuBookmark } from 'react-icons/lu';
9
9
 
10
10
  var ViewerThemeContext = createContext(void 0);
11
11
  function ViewerThemeProvider({ theme, children }) {
@@ -1334,7 +1334,7 @@ function AccountPage() {
1334
1334
  return void 0;
1335
1335
  });
1336
1336
  };
1337
- const version = "1.23.0" ;
1337
+ const version = "1.24.1" ;
1338
1338
  return /* @__PURE__ */ jsxs("div", { className: "mt-8 max-w-[700px] space-y-6", children: [
1339
1339
  /* @__PURE__ */ jsxs("section", { className: cardClass, children: [
1340
1340
  /* @__PURE__ */ jsxs("h2", { className: "flex items-center gap-2 text-sm font-semibold", children: [
@@ -8264,7 +8264,7 @@ function FailedToLoad() {
8264
8264
  var LazyModel3DScene = React32.lazy(
8265
8265
  async () => {
8266
8266
  try {
8267
- return await import('./Model3DScene-QTNGCODM.mjs');
8267
+ return await import('./Model3DScene-GGNUAOGD.mjs');
8268
8268
  } catch {
8269
8269
  return { default: FailedToLoad };
8270
8270
  }
@@ -11737,7 +11737,7 @@ function ShortcutPanel({ isOpen, onClose }) {
11737
11737
  }
11738
11738
  )
11739
11739
  ] }),
11740
- /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto p-2 space-y-1", children: SHORTCUT_REFERENCE_ITEMS.map((shortcut) => /* @__PURE__ */ jsxs(
11740
+ /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto p-2 space-y-1", children: SHORTCUT_REFERENCE_ITEMS$1.map((shortcut) => /* @__PURE__ */ jsxs(
11741
11741
  "div",
11742
11742
  {
11743
11743
  className: "flex items-center justify-between gap-3 rounded bg-muted/80 px-2 py-1.5",
@@ -30433,6 +30433,79 @@ function ViewerPresentationLayer(props) {
30433
30433
  )
30434
30434
  ] });
30435
30435
  }
30436
+ var itemClass = "block w-full whitespace-nowrap px-3 py-1.5 text-left text-xs text-foreground transition-colors hover:bg-accent";
30437
+ function PresentationContextMenu(p) {
30438
+ const { t } = useTranslation();
30439
+ const run = (action) => {
30440
+ action();
30441
+ p.onClose();
30442
+ };
30443
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
30444
+ /* @__PURE__ */ jsx(
30445
+ "div",
30446
+ {
30447
+ className: "fixed inset-0 z-[1299]",
30448
+ onClick: p.onClose,
30449
+ onContextMenu: (e) => {
30450
+ e.preventDefault();
30451
+ p.onClose();
30452
+ }
30453
+ }
30454
+ ),
30455
+ /* @__PURE__ */ jsxs(
30456
+ "div",
30457
+ {
30458
+ "data-pptx-presentation-menu": "",
30459
+ role: "menu",
30460
+ tabIndex: -1,
30461
+ className: "fixed z-[1300] min-w-[160px] rounded-md border border-border bg-popover py-1 shadow-xl",
30462
+ style: { left: p.state.x, top: p.state.y },
30463
+ onContextMenu: (e) => e.preventDefault(),
30464
+ children: [
30465
+ /* @__PURE__ */ jsx("button", { type: "button", role: "menuitem", className: itemClass, onClick: () => run(p.onNext), children: t("pptx.presenter.nextSlide") }),
30466
+ /* @__PURE__ */ jsx(
30467
+ "button",
30468
+ {
30469
+ type: "button",
30470
+ role: "menuitem",
30471
+ className: itemClass,
30472
+ onClick: () => run(p.onPrevious),
30473
+ children: t("pptx.presenter.previousSlide")
30474
+ }
30475
+ ),
30476
+ /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-border/60" }),
30477
+ /* @__PURE__ */ jsx(
30478
+ "button",
30479
+ {
30480
+ type: "button",
30481
+ role: "menuitem",
30482
+ className: itemClass,
30483
+ onClick: () => run(p.onEndShow),
30484
+ children: t("pptx.presenter.endPresentation")
30485
+ }
30486
+ )
30487
+ ]
30488
+ }
30489
+ )
30490
+ ] });
30491
+ }
30492
+ function PresentationEndOverlay({ onExit }) {
30493
+ const { t } = useTranslation();
30494
+ return /* @__PURE__ */ jsx(
30495
+ "button",
30496
+ {
30497
+ type: "button",
30498
+ "data-pptx-end-of-show": "",
30499
+ onClick: onExit,
30500
+ className: "absolute inset-0 z-[90] flex cursor-default items-start bg-black text-left",
30501
+ children: /* @__PURE__ */ jsx("span", { className: "px-4 py-3 text-[12px] text-white/70", children: t("pptx.presentation.endOfSlideShow", "End of slide show, click to exit.") })
30502
+ }
30503
+ );
30504
+ }
30505
+ var ViewerOptionsContext = createContext(DEFAULT_VIEWER_OPTIONS);
30506
+ function useViewerOptionsContext() {
30507
+ return useContext(ViewerOptionsContext);
30508
+ }
30436
30509
  function ViewerCanvasArea(props) {
30437
30510
  const {
30438
30511
  mode,
@@ -30458,6 +30531,7 @@ function ViewerCanvasArea(props) {
30458
30531
  } = props;
30459
30532
  const { t } = useTranslation();
30460
30533
  const { isHidden } = useToolbarVisibility(hiddenActions);
30534
+ const viewerOptions = useViewerOptionsContext();
30461
30535
  const effectiveSlide = mode === "master" ? masterPseudoSlide : activeSlide;
30462
30536
  const effectiveTemplateElements = mode === "master" ? s.activeLayout ? s.activeMaster?.elements ?? [] : [] : templateElements;
30463
30537
  const fieldContext = useMemo(() => {
@@ -30494,15 +30568,26 @@ function ViewerCanvasArea(props) {
30494
30568
  }
30495
30569
  return { theme: s.theme, tableStyleMap: s.tableStyleMap };
30496
30570
  }, [s.theme, s.tableStyleMap]);
30571
+ const openExternalUrl = useCallback(
30572
+ (url) => {
30573
+ if (shouldConfirmExternalHyperlink(viewerOptions, url) && !window.confirm(`${t("pptx.options.trust.confirmHyperlinks")}
30574
+
30575
+ ${url}`)) {
30576
+ return;
30577
+ }
30578
+ safeOpenUrl(url);
30579
+ },
30580
+ [viewerOptions, t]
30581
+ );
30497
30582
  const handleActionClick = useCallback(
30498
30583
  (_elementId, action) => {
30499
30584
  if (mode === "present") {
30500
30585
  presentation.handlePresentationAction(action);
30501
30586
  } else if (action.url) {
30502
- safeOpenUrl(action.url);
30587
+ openExternalUrl(action.url);
30503
30588
  }
30504
30589
  },
30505
- [mode, presentation]
30590
+ [mode, presentation, openExternalUrl]
30506
30591
  );
30507
30592
  const handleHyperlinkClick = useCallback(
30508
30593
  (url) => {
@@ -30519,9 +30604,25 @@ function ViewerCanvasArea(props) {
30519
30604
  }
30520
30605
  return;
30521
30606
  }
30522
- safeOpenUrl(url);
30607
+ openExternalUrl(url);
30523
30608
  },
30524
- [mode, presentation]
30609
+ [mode, presentation, openExternalUrl]
30610
+ );
30611
+ const [presentationMenu, setPresentationMenu] = useState(
30612
+ null
30613
+ );
30614
+ const handlePresentationContextMenu = useCallback(
30615
+ (e) => {
30616
+ if (mode !== "present") {
30617
+ return;
30618
+ }
30619
+ e.preventDefault();
30620
+ if (!viewerOptions.advanced.slideShowShowMenuOnRightClick) {
30621
+ return;
30622
+ }
30623
+ setPresentationMenu({ x: e.clientX, y: e.clientY });
30624
+ },
30625
+ [mode, viewerOptions.advanced.slideShowShowMenuOnRightClick]
30525
30626
  );
30526
30627
  const toolbarHoveringRef = useRef(false);
30527
30628
  const handleToolbarMouseEnter = useCallback(() => {
@@ -30551,227 +30652,243 @@ function ViewerCanvasArea(props) {
30551
30652
  onNext: handleSwipeNext,
30552
30653
  onPrev: handleSwipePrev
30553
30654
  });
30554
- return /* @__PURE__ */ jsxs(
30555
- "main",
30556
- {
30557
- "aria-label": t("pptx.viewer.slideEditorAria"),
30558
- className: "flex-1 min-w-0 relative flex flex-col bg-background",
30559
- onTouchStart: swipe.onTouchStart,
30560
- onTouchEnd: swipe.onTouchEnd,
30561
- children: [
30562
- findReplace.findReplaceOpen && /* @__PURE__ */ jsx(
30563
- FindReplacePanel,
30564
- {
30565
- findQuery: findReplace.findQuery,
30566
- replaceQuery: findReplace.replaceQuery,
30567
- findMatchCase: findReplace.findMatchCase,
30568
- findResults: findReplace.findResults,
30569
- findResultIndex: findReplace.findResultIndex,
30570
- onSetFindQuery: findReplace.setFindQuery,
30571
- onSetReplaceQuery: findReplace.setReplaceQuery,
30572
- onSetFindMatchCase: findReplace.setFindMatchCase,
30573
- onPerformFind: findReplace.performFind,
30574
- onNavigateResult: findReplace.navigateFindResult,
30575
- onReplace: findReplace.handleReplace,
30576
- onReplaceAll: findReplace.handleReplaceAll,
30577
- onClose: () => findReplace.setFindReplaceOpen(false)
30578
- }
30579
- ),
30580
- mode === "master" && s.masterViewTab === "notes" ? /* @__PURE__ */ jsx(
30581
- NotesMasterCanvas,
30582
- {
30583
- notesMaster: s.notesMaster,
30584
- canvasSize,
30585
- notesCanvasSize: s.notesCanvasSize
30586
- }
30587
- ) : mode === "master" && s.masterViewTab === "handout" ? /* @__PURE__ */ jsx(
30588
- HandoutMasterCanvas,
30589
- {
30590
- handoutMaster: s.handoutMaster,
30591
- canvasSize,
30592
- slidesPerPage: s.handoutMaster?.slidesPerPage ?? s.handoutSlidesPerPage
30593
- }
30594
- ) : /* @__PURE__ */ jsx(
30595
- SlideCanvas,
30596
- {
30597
- activeSlide: effectiveSlide,
30598
- templateElements: effectiveTemplateElements,
30599
- canvasSize,
30600
- zoom,
30601
- mode,
30602
- canEdit,
30603
- editTemplateMode: mode === "master" || s.editTemplateMode,
30604
- selectedElementIdSet: s.selectedElementIdSet,
30605
- selectedElement,
30606
- inlineEditingElementId: s.inlineEditingElementId,
30607
- inlineEditingText: s.inlineEditingText,
30608
- spellCheckEnabled: s.spellCheckEnabled,
30609
- mediaDataUrls: s.mediaDataUrls,
30610
- tableEditorState: s.tableEditorState,
30611
- marqueeSelectionState: s.marqueeSelectionState,
30612
- snapLines: s.snapLines,
30613
- showGrid: s.showGrid,
30614
- gridSpacingPx,
30615
- showRulers: s.showRulers,
30616
- guides: s.guides,
30617
- presentationElementStates: mode === "present" ? presentation.presentationElementStates : void 0,
30618
- presentationKeyframesCss: mode === "present" ? presentation.presentationKeyframesCss : void 0,
30619
- onClick: canvasHandlers.handleElementClick,
30620
- onDoubleClick: canvasHandlers.handleElementDoubleClick,
30621
- onMouseDown: canvasHandlers.handleElementMouseDown,
30622
- onContextMenu: canvasHandlers.handleElementContextMenu,
30623
- onCanvasMouseDown: canvasHandlers.handleCanvasMouseDown,
30624
- onResizePointerDown: canvasHandlers.handleResizePointerDown,
30625
- onAdjustmentPointerDown: canvasHandlers.handleAdjustmentPointerDown,
30626
- onRotate: canvasHandlers.handleRotate,
30627
- onInlineEditChange: s.setInlineEditingText,
30628
- onInlineEditCommit: canvasHandlers.handleInlineEditCommit,
30629
- onInlineEditCancel: () => s.setInlineEditingElementId(null),
30630
- onTableCellSelect: (cell, elementId) => s.setTableEditorState(cell ? { ...cell, elementId } : null),
30631
- onCommitCellEdit: tableOps.handleCommitCellEdit,
30632
- onUpdateSmartArtElement: canvasHandlers.handleUpdateSmartArtElement,
30633
- onFormatText: canvasHandlers.handleFormatText,
30634
- onResizeTableColumns: tableOps.handleResizeTableColumns,
30635
- onResizeTableRow: tableOps.handleResizeTableRow,
30636
- findResults: findReplace.findResults,
30637
- findResultIndex: findReplace.findResultIndex,
30638
- activeSlideIndex,
30639
- activeTool: s.activeTool,
30640
- drawingColor: s.drawingColor,
30641
- drawingWidth: s.drawingWidth,
30642
- isDrawingRef: s.isDrawingRef,
30643
- onAddInkElement: insertHandlers.handleAddInkElement,
30644
- onAddFreeformShape: insertHandlers.handleAddFreeformShape,
30645
- onEraseInkElement: insertHandlers.handleEraseInkElement,
30646
- onActionClick: handleActionClick,
30647
- onHyperlinkClick: handleHyperlinkClick,
30648
- allSlides: mode === "present" ? slides : void 0,
30649
- onZoomClick: mode === "present" ? presentation.handleZoomClick : void 0,
30650
- sourceSlideIndex: mode === "present" ? activeSlideIndex : void 0,
30651
- fieldContext,
30652
- tableStyleContext,
30653
- collaborationOverlay: /* @__PURE__ */ jsxs(Fragment, { children: [
30654
- /* @__PURE__ */ jsx(
30655
- RemoteSelectionOverlay,
30656
- {
30657
- elements: effectiveSlide?.elements ?? [],
30658
- activeSlideIndex
30659
- }
30660
- ),
30661
- /* @__PURE__ */ jsx(
30662
- CollaborationCursorOverlay,
30663
- {
30664
- activeSlideIndex,
30665
- canvasWidth: canvasSize.width,
30666
- canvasHeight: canvasSize.height,
30667
- selectedElementId: s.selectedElementId
30668
- }
30669
- )
30670
- ] }),
30671
- comments: activeSlide?.comments,
30672
- showCommentMarkers: s.sidebarPanelMode === "comments",
30673
- onCommentMarkerClick: () => s.setSidebarPanelMode("comments"),
30674
- onMoveGuide: (guideId, position) => {
30675
- s.setGuides(
30676
- (prev) => prev.map(
30677
- (guide) => guide.id === guideId ? {
30678
- ...guide,
30679
- position: guide.axis === "h" ? Math.max(0, Math.min(canvasSize.height, position)) : Math.max(0, Math.min(canvasSize.width, position))
30680
- } : guide
30655
+ return (
30656
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- the canvas area hosts swipe navigation and the presentation-mode right-click menu; it has no interactive semantics of its own
30657
+ /* @__PURE__ */ jsxs(
30658
+ "main",
30659
+ {
30660
+ "aria-label": t("pptx.viewer.slideEditorAria"),
30661
+ className: "flex-1 min-w-0 relative flex flex-col bg-background",
30662
+ onTouchStart: swipe.onTouchStart,
30663
+ onTouchEnd: swipe.onTouchEnd,
30664
+ onContextMenu: mode === "present" ? handlePresentationContextMenu : void 0,
30665
+ children: [
30666
+ findReplace.findReplaceOpen && /* @__PURE__ */ jsx(
30667
+ FindReplacePanel,
30668
+ {
30669
+ findQuery: findReplace.findQuery,
30670
+ replaceQuery: findReplace.replaceQuery,
30671
+ findMatchCase: findReplace.findMatchCase,
30672
+ findResults: findReplace.findResults,
30673
+ findResultIndex: findReplace.findResultIndex,
30674
+ onSetFindQuery: findReplace.setFindQuery,
30675
+ onSetReplaceQuery: findReplace.setReplaceQuery,
30676
+ onSetFindMatchCase: findReplace.setFindMatchCase,
30677
+ onPerformFind: findReplace.performFind,
30678
+ onNavigateResult: findReplace.navigateFindResult,
30679
+ onReplace: findReplace.handleReplace,
30680
+ onReplaceAll: findReplace.handleReplaceAll,
30681
+ onClose: () => findReplace.setFindReplaceOpen(false)
30682
+ }
30683
+ ),
30684
+ mode === "master" && s.masterViewTab === "notes" ? /* @__PURE__ */ jsx(
30685
+ NotesMasterCanvas,
30686
+ {
30687
+ notesMaster: s.notesMaster,
30688
+ canvasSize,
30689
+ notesCanvasSize: s.notesCanvasSize
30690
+ }
30691
+ ) : mode === "master" && s.masterViewTab === "handout" ? /* @__PURE__ */ jsx(
30692
+ HandoutMasterCanvas,
30693
+ {
30694
+ handoutMaster: s.handoutMaster,
30695
+ canvasSize,
30696
+ slidesPerPage: s.handoutMaster?.slidesPerPage ?? s.handoutSlidesPerPage
30697
+ }
30698
+ ) : /* @__PURE__ */ jsx(
30699
+ SlideCanvas,
30700
+ {
30701
+ activeSlide: effectiveSlide,
30702
+ templateElements: effectiveTemplateElements,
30703
+ canvasSize,
30704
+ zoom,
30705
+ mode,
30706
+ canEdit,
30707
+ editTemplateMode: mode === "master" || s.editTemplateMode,
30708
+ selectedElementIdSet: s.selectedElementIdSet,
30709
+ selectedElement,
30710
+ inlineEditingElementId: s.inlineEditingElementId,
30711
+ inlineEditingText: s.inlineEditingText,
30712
+ spellCheckEnabled: s.spellCheckEnabled,
30713
+ mediaDataUrls: s.mediaDataUrls,
30714
+ tableEditorState: s.tableEditorState,
30715
+ marqueeSelectionState: s.marqueeSelectionState,
30716
+ snapLines: s.snapLines,
30717
+ showGrid: s.showGrid,
30718
+ gridSpacingPx,
30719
+ showRulers: s.showRulers,
30720
+ guides: s.guides,
30721
+ presentationElementStates: mode === "present" ? presentation.presentationElementStates : void 0,
30722
+ presentationKeyframesCss: mode === "present" ? presentation.presentationKeyframesCss : void 0,
30723
+ onClick: canvasHandlers.handleElementClick,
30724
+ onDoubleClick: canvasHandlers.handleElementDoubleClick,
30725
+ onMouseDown: canvasHandlers.handleElementMouseDown,
30726
+ onContextMenu: canvasHandlers.handleElementContextMenu,
30727
+ onCanvasMouseDown: canvasHandlers.handleCanvasMouseDown,
30728
+ onResizePointerDown: canvasHandlers.handleResizePointerDown,
30729
+ onAdjustmentPointerDown: canvasHandlers.handleAdjustmentPointerDown,
30730
+ onRotate: canvasHandlers.handleRotate,
30731
+ onInlineEditChange: s.setInlineEditingText,
30732
+ onInlineEditCommit: canvasHandlers.handleInlineEditCommit,
30733
+ onInlineEditCancel: () => s.setInlineEditingElementId(null),
30734
+ onTableCellSelect: (cell, elementId) => s.setTableEditorState(cell ? { ...cell, elementId } : null),
30735
+ onCommitCellEdit: tableOps.handleCommitCellEdit,
30736
+ onUpdateSmartArtElement: canvasHandlers.handleUpdateSmartArtElement,
30737
+ onFormatText: canvasHandlers.handleFormatText,
30738
+ onResizeTableColumns: tableOps.handleResizeTableColumns,
30739
+ onResizeTableRow: tableOps.handleResizeTableRow,
30740
+ findResults: findReplace.findResults,
30741
+ findResultIndex: findReplace.findResultIndex,
30742
+ activeSlideIndex,
30743
+ activeTool: s.activeTool,
30744
+ drawingColor: s.drawingColor,
30745
+ drawingWidth: s.drawingWidth,
30746
+ isDrawingRef: s.isDrawingRef,
30747
+ onAddInkElement: insertHandlers.handleAddInkElement,
30748
+ onAddFreeformShape: insertHandlers.handleAddFreeformShape,
30749
+ onEraseInkElement: insertHandlers.handleEraseInkElement,
30750
+ onActionClick: handleActionClick,
30751
+ onHyperlinkClick: handleHyperlinkClick,
30752
+ allSlides: mode === "present" ? slides : void 0,
30753
+ onZoomClick: mode === "present" ? presentation.handleZoomClick : void 0,
30754
+ sourceSlideIndex: mode === "present" ? activeSlideIndex : void 0,
30755
+ fieldContext,
30756
+ tableStyleContext,
30757
+ collaborationOverlay: /* @__PURE__ */ jsxs(Fragment, { children: [
30758
+ /* @__PURE__ */ jsx(
30759
+ RemoteSelectionOverlay,
30760
+ {
30761
+ elements: effectiveSlide?.elements ?? [],
30762
+ activeSlideIndex
30763
+ }
30764
+ ),
30765
+ /* @__PURE__ */ jsx(
30766
+ CollaborationCursorOverlay,
30767
+ {
30768
+ activeSlideIndex,
30769
+ canvasWidth: canvasSize.width,
30770
+ canvasHeight: canvasSize.height,
30771
+ selectedElementId: s.selectedElementId
30772
+ }
30681
30773
  )
30682
- );
30683
- },
30684
- onDeleteGuide: (guideId) => {
30685
- s.setGuides((prev) => prev.filter((guide) => guide.id !== guideId));
30774
+ ] }),
30775
+ comments: activeSlide?.comments,
30776
+ showCommentMarkers: s.sidebarPanelMode === "comments",
30777
+ onCommentMarkerClick: () => s.setSidebarPanelMode("comments"),
30778
+ onMoveGuide: (guideId, position) => {
30779
+ s.setGuides(
30780
+ (prev) => prev.map(
30781
+ (guide) => guide.id === guideId ? {
30782
+ ...guide,
30783
+ position: guide.axis === "h" ? Math.max(0, Math.min(canvasSize.height, position)) : Math.max(0, Math.min(canvasSize.width, position))
30784
+ } : guide
30785
+ )
30786
+ );
30787
+ },
30788
+ onDeleteGuide: (guideId) => {
30789
+ s.setGuides((prev) => prev.filter((guide) => guide.id !== guideId));
30790
+ },
30791
+ onCreateGuideFromRuler: (axis, positionPx) => {
30792
+ s.setGuides((prev) => [
30793
+ ...prev,
30794
+ {
30795
+ id: `guide-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
30796
+ axis,
30797
+ position: positionPx
30798
+ }
30799
+ ]);
30800
+ }
30801
+ }
30802
+ ),
30803
+ mode === "present" && presentation.transitionOverlay && slides[presentation.transitionOverlay.outgoingSlideIndex] && /* @__PURE__ */ jsx(
30804
+ PresentationTransitionOverlay,
30805
+ {
30806
+ outgoingSlide: slides[presentation.transitionOverlay.outgoingSlideIndex],
30807
+ templateElements,
30808
+ canvasSize,
30809
+ transition: presentation.transitionOverlay.transition,
30810
+ durationMs: presentation.transitionOverlay.durationMs,
30811
+ onComplete: presentation.handleTransitionOverlayComplete
30686
30812
  },
30687
- onCreateGuideFromRuler: (axis, positionPx) => {
30688
- s.setGuides((prev) => [
30689
- ...prev,
30813
+ `${presentation.transitionOverlay.outgoingSlideIndex}-${presentation.transitionOverlay.incomingSlideIndex}`
30814
+ ),
30815
+ mode === "present" && presentation.endOfShowVisible && /* @__PURE__ */ jsx(PresentationEndOverlay, { onExit: () => presentation.movePresentationSlide(1) }),
30816
+ mode === "present" && presentationMenu && /* @__PURE__ */ jsx(
30817
+ PresentationContextMenu,
30818
+ {
30819
+ state: presentationMenu,
30820
+ onNext: () => presentation.movePresentationSlide(1),
30821
+ onPrevious: () => presentation.movePresentationSlide(-1),
30822
+ onEndShow: onEndPresentation ?? (() => {
30823
+ }),
30824
+ onClose: () => setPresentationMenu(null)
30825
+ }
30826
+ ),
30827
+ mode === "present" && annotations.presentationTool !== "none" && /* @__PURE__ */ jsx(
30828
+ PresentationAnnotationOverlay,
30829
+ {
30830
+ canvasSize,
30831
+ editorScale: zoom.editorScale,
30832
+ presentationTool: annotations.presentationTool,
30833
+ annotationStrokes: annotations.annotationStrokes,
30834
+ currentStroke: annotations.currentStroke,
30835
+ laserPosition: annotations.laserPosition,
30836
+ onPointerDown: annotations.handlePointerDown,
30837
+ onPointerMove: annotations.handlePointerMove,
30838
+ onPointerUp: annotations.handlePointerUp,
30839
+ onLaserMove: annotations.handleLaserMove,
30840
+ onLaserLeave: annotations.handleLaserLeave,
30841
+ onEraseAtPoint: annotations.eraseAtPoint
30842
+ }
30843
+ ),
30844
+ mode === "present" && /* @__PURE__ */ jsx(PresentationSubtitleBar, { visible: Boolean(s.presentationProperties.showSubtitles) }),
30845
+ mode === "present" && /* @__PURE__ */ jsx(
30846
+ PresentationTouchControls,
30847
+ {
30848
+ currentSlideIndex: presentation.presentationSlideIndex,
30849
+ totalSlides: slides.length,
30850
+ onMovePresentationSlide: presentation.movePresentationSlide,
30851
+ onEndPresentation: onEndPresentation ?? (() => {
30852
+ }),
30853
+ hideNavigation: isHidden("navigation")
30854
+ }
30855
+ ),
30856
+ mode === "present" && /* @__PURE__ */ jsx(
30857
+ "div",
30858
+ {
30859
+ className: "absolute bottom-6 left-1/2 -translate-x-1/2 z-[80] transition-opacity duration-300",
30860
+ style: {
30861
+ opacity: annotations.toolbarVisible ? 1 : 0,
30862
+ pointerEvents: annotations.toolbarVisible ? "auto" : "none"
30863
+ },
30864
+ onMouseEnter: handleToolbarMouseEnter,
30865
+ onMouseLeave: handleToolbarMouseLeave,
30866
+ children: /* @__PURE__ */ jsx(
30867
+ PresentationToolbar,
30690
30868
  {
30691
- id: `guide-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
30692
- axis,
30693
- position: positionPx
30869
+ presentationTool: annotations.presentationTool,
30870
+ penColor: annotations.penColor,
30871
+ highlighterColor: annotations.highlighterColor,
30872
+ hasAnnotations: annotations.annotationStrokes.length > 0,
30873
+ onSetTool: annotations.setPresentationTool,
30874
+ onSetPenColor: annotations.setPenColor,
30875
+ onSetHighlighterColor: annotations.setHighlighterColor,
30876
+ onClearAnnotations: annotations.clearAnnotations,
30877
+ currentSlideIndex: presentation.presentationSlideIndex,
30878
+ totalSlides: slides.length,
30879
+ onMovePresentationSlide: presentation.movePresentationSlide,
30880
+ presentationStartTime: presentation.presentationStartTime,
30881
+ onEndPresentation: onEndPresentation ?? (() => {
30882
+ }),
30883
+ onTogglePresenterView: presentation.togglePresenterView,
30884
+ presenterMode: presentation.presenterMode
30694
30885
  }
30695
- ]);
30886
+ )
30696
30887
  }
30697
- }
30698
- ),
30699
- mode === "present" && presentation.transitionOverlay && slides[presentation.transitionOverlay.outgoingSlideIndex] && /* @__PURE__ */ jsx(
30700
- PresentationTransitionOverlay,
30701
- {
30702
- outgoingSlide: slides[presentation.transitionOverlay.outgoingSlideIndex],
30703
- templateElements,
30704
- canvasSize,
30705
- transition: presentation.transitionOverlay.transition,
30706
- durationMs: presentation.transitionOverlay.durationMs,
30707
- onComplete: presentation.handleTransitionOverlayComplete
30708
- },
30709
- `${presentation.transitionOverlay.outgoingSlideIndex}-${presentation.transitionOverlay.incomingSlideIndex}`
30710
- ),
30711
- mode === "present" && annotations.presentationTool !== "none" && /* @__PURE__ */ jsx(
30712
- PresentationAnnotationOverlay,
30713
- {
30714
- canvasSize,
30715
- editorScale: zoom.editorScale,
30716
- presentationTool: annotations.presentationTool,
30717
- annotationStrokes: annotations.annotationStrokes,
30718
- currentStroke: annotations.currentStroke,
30719
- laserPosition: annotations.laserPosition,
30720
- onPointerDown: annotations.handlePointerDown,
30721
- onPointerMove: annotations.handlePointerMove,
30722
- onPointerUp: annotations.handlePointerUp,
30723
- onLaserMove: annotations.handleLaserMove,
30724
- onLaserLeave: annotations.handleLaserLeave,
30725
- onEraseAtPoint: annotations.eraseAtPoint
30726
- }
30727
- ),
30728
- mode === "present" && /* @__PURE__ */ jsx(PresentationSubtitleBar, { visible: Boolean(s.presentationProperties.showSubtitles) }),
30729
- mode === "present" && /* @__PURE__ */ jsx(
30730
- PresentationTouchControls,
30731
- {
30732
- currentSlideIndex: presentation.presentationSlideIndex,
30733
- totalSlides: slides.length,
30734
- onMovePresentationSlide: presentation.movePresentationSlide,
30735
- onEndPresentation: onEndPresentation ?? (() => {
30736
- }),
30737
- hideNavigation: isHidden("navigation")
30738
- }
30739
- ),
30740
- mode === "present" && /* @__PURE__ */ jsx(
30741
- "div",
30742
- {
30743
- className: "absolute bottom-6 left-1/2 -translate-x-1/2 z-[80] transition-opacity duration-300",
30744
- style: {
30745
- opacity: annotations.toolbarVisible ? 1 : 0,
30746
- pointerEvents: annotations.toolbarVisible ? "auto" : "none"
30747
- },
30748
- onMouseEnter: handleToolbarMouseEnter,
30749
- onMouseLeave: handleToolbarMouseLeave,
30750
- children: /* @__PURE__ */ jsx(
30751
- PresentationToolbar,
30752
- {
30753
- presentationTool: annotations.presentationTool,
30754
- penColor: annotations.penColor,
30755
- highlighterColor: annotations.highlighterColor,
30756
- hasAnnotations: annotations.annotationStrokes.length > 0,
30757
- onSetTool: annotations.setPresentationTool,
30758
- onSetPenColor: annotations.setPenColor,
30759
- onSetHighlighterColor: annotations.setHighlighterColor,
30760
- onClearAnnotations: annotations.clearAnnotations,
30761
- currentSlideIndex: presentation.presentationSlideIndex,
30762
- totalSlides: slides.length,
30763
- onMovePresentationSlide: presentation.movePresentationSlide,
30764
- presentationStartTime: presentation.presentationStartTime,
30765
- onEndPresentation: onEndPresentation ?? (() => {
30766
- }),
30767
- onTogglePresenterView: presentation.togglePresenterView,
30768
- presenterMode: presentation.presenterMode
30769
- }
30770
- )
30771
- }
30772
- )
30773
- ]
30774
- }
30888
+ )
30889
+ ]
30890
+ }
30891
+ )
30775
30892
  );
30776
30893
  }
30777
30894
 
@@ -32369,6 +32486,423 @@ function MobileChromeOverlay(props) {
32369
32486
  )
32370
32487
  ] });
32371
32488
  }
32489
+ function AddinTable({
32490
+ title,
32491
+ rows,
32492
+ selectedId,
32493
+ onSelect
32494
+ }) {
32495
+ const { t } = useTranslation();
32496
+ return /* @__PURE__ */ jsxs("section", { children: [
32497
+ /* @__PURE__ */ jsx("h4", { className: "mb-1 text-xs font-semibold text-foreground", children: title }),
32498
+ rows.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-1 text-xs italic text-muted-foreground", children: t("pptx.options.addIns.description") }) : /* @__PURE__ */ jsx("table", { className: "w-full border-collapse text-left", children: /* @__PURE__ */ jsx("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxs(
32499
+ "tr",
32500
+ {
32501
+ onClick: () => onSelect(row.id),
32502
+ className: cn(
32503
+ "cursor-pointer border-b border-border/40 transition-colors",
32504
+ selectedId === row.id ? "bg-primary/10" : "hover:bg-accent"
32505
+ ),
32506
+ children: [
32507
+ /* @__PURE__ */ jsx("td", { className: "px-2 py-1.5 text-xs text-foreground", children: t(row.nameKey) }),
32508
+ /* @__PURE__ */ jsx("td", { className: "px-2 py-1.5 font-mono text-[11px] text-muted-foreground", children: row.location }),
32509
+ /* @__PURE__ */ jsx("td", { className: "px-2 py-1.5 text-xs text-muted-foreground", children: t(`pptx.options.addInType.${row.type}`) })
32510
+ ]
32511
+ },
32512
+ row.id
32513
+ )) }) })
32514
+ ] });
32515
+ }
32516
+ function OptionsAddInsPane({ addinStatus }) {
32517
+ const { t } = useTranslation();
32518
+ const [selectedId, setSelectedId] = useState(null);
32519
+ const rows = resolveViewerAddinRows(addinStatus);
32520
+ const active = rows.filter((row) => row.active);
32521
+ const inactive = rows.filter((row) => !row.active);
32522
+ const selected = rows.find((row) => row.id === selectedId);
32523
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
32524
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_auto_auto] gap-x-2 border-b border-border pb-1 pl-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: [
32525
+ /* @__PURE__ */ jsx("span", { children: t("pptx.options.addIns.name") }),
32526
+ /* @__PURE__ */ jsx("span", { children: t("pptx.options.addIns.location") }),
32527
+ /* @__PURE__ */ jsx("span", { children: t("pptx.options.addIns.type") })
32528
+ ] }),
32529
+ /* @__PURE__ */ jsx(
32530
+ AddinTable,
32531
+ {
32532
+ title: t("pptx.options.addIns.active"),
32533
+ rows: active,
32534
+ selectedId,
32535
+ onSelect: setSelectedId
32536
+ }
32537
+ ),
32538
+ /* @__PURE__ */ jsx(
32539
+ AddinTable,
32540
+ {
32541
+ title: t("pptx.options.addIns.inactive"),
32542
+ rows: inactive,
32543
+ selectedId,
32544
+ onSelect: setSelectedId
32545
+ }
32546
+ ),
32547
+ selected && /* @__PURE__ */ jsxs("div", { className: "rounded border border-border/60 bg-muted/40 p-3", children: [
32548
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-foreground", children: t(selected.nameKey) }),
32549
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: t(selected.descriptionKey) }),
32550
+ /* @__PURE__ */ jsx("p", { className: "mt-1 font-mono text-[11px] text-muted-foreground", children: selected.location })
32551
+ ] })
32552
+ ] });
32553
+ }
32554
+ function readValue(options, control) {
32555
+ const group = options[control.group];
32556
+ const value = group[control.key];
32557
+ return typeof value === "boolean" || typeof value === "number" || typeof value === "string" ? value : void 0;
32558
+ }
32559
+ function InfoTip({ text }) {
32560
+ return /* @__PURE__ */ jsx("span", { title: text, className: "inline-flex cursor-help align-middle", children: /* @__PURE__ */ jsx(LuInfo, { className: "ml-1 h-3.5 w-3.5 text-primary/70", "aria-label": text }) });
32561
+ }
32562
+ function ControlRow({
32563
+ control,
32564
+ options,
32565
+ onOptionChange
32566
+ }) {
32567
+ const { t } = useTranslation();
32568
+ const value = readValue(options, control);
32569
+ const label = t(control.labelKey);
32570
+ const info = control.infoKey ? /* @__PURE__ */ jsx(InfoTip, { text: t(control.infoKey) }) : null;
32571
+ const rowClass = cn("flex items-center justify-between gap-3 py-1.5", control.indent && "pl-6");
32572
+ if (control.kind === "toggle") {
32573
+ return /* @__PURE__ */ jsxs("label", { className: cn(rowClass, "cursor-pointer select-none"), children: [
32574
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-foreground", children: [
32575
+ label,
32576
+ info
32577
+ ] }),
32578
+ /* @__PURE__ */ jsx(
32579
+ "input",
32580
+ {
32581
+ type: "checkbox",
32582
+ className: "h-4 w-4 shrink-0 accent-[var(--pptx-primary,#6366f1)]",
32583
+ checked: value === true,
32584
+ onChange: (event) => onOptionChange(control.group, control.key, event.target.checked)
32585
+ }
32586
+ )
32587
+ ] });
32588
+ }
32589
+ if (control.kind === "select") {
32590
+ return /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
32591
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-foreground", children: [
32592
+ label,
32593
+ info
32594
+ ] }),
32595
+ /* @__PURE__ */ jsx(
32596
+ "select",
32597
+ {
32598
+ "aria-label": label,
32599
+ className: "max-w-[55%] rounded border border-border bg-background px-2 py-1 text-xs text-foreground",
32600
+ value: typeof value === "string" ? value : "",
32601
+ onChange: (event) => onOptionChange(control.group, control.key, event.target.value),
32602
+ children: control.choices.map((choice) => /* @__PURE__ */ jsx("option", { value: choice.value, children: t(choice.labelKey) }, choice.value))
32603
+ }
32604
+ )
32605
+ ] });
32606
+ }
32607
+ if (control.kind === "number") {
32608
+ return /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
32609
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-foreground", children: [
32610
+ label,
32611
+ info
32612
+ ] }),
32613
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
32614
+ /* @__PURE__ */ jsx(
32615
+ "input",
32616
+ {
32617
+ type: "number",
32618
+ "aria-label": label,
32619
+ className: "w-20 rounded border border-border bg-background px-2 py-1 text-right text-xs text-foreground",
32620
+ min: control.min,
32621
+ max: control.max,
32622
+ step: control.step ?? 1,
32623
+ value: typeof value === "number" ? value : control.min,
32624
+ onChange: (event) => {
32625
+ const parsed = Number(event.target.value);
32626
+ if (Number.isFinite(parsed)) {
32627
+ onOptionChange(
32628
+ control.group,
32629
+ control.key,
32630
+ Math.min(control.max, Math.max(control.min, parsed))
32631
+ );
32632
+ }
32633
+ }
32634
+ }
32635
+ ),
32636
+ control.unitKey && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t(control.unitKey) })
32637
+ ] })
32638
+ ] });
32639
+ }
32640
+ return /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
32641
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-foreground", children: [
32642
+ label,
32643
+ info
32644
+ ] }),
32645
+ /* @__PURE__ */ jsx(
32646
+ "input",
32647
+ {
32648
+ type: "text",
32649
+ "aria-label": label,
32650
+ className: "w-48 max-w-[55%] rounded border border-border bg-background px-2 py-1 text-xs text-foreground",
32651
+ maxLength: control.maxLength,
32652
+ value: typeof value === "string" ? value : "",
32653
+ onChange: (event) => onOptionChange(control.group, control.key, event.target.value)
32654
+ }
32655
+ )
32656
+ ] });
32657
+ }
32658
+ function OptionsPane({
32659
+ tab,
32660
+ options,
32661
+ onOptionChange,
32662
+ renderSpecial,
32663
+ children
32664
+ }) {
32665
+ const { t } = useTranslation();
32666
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
32667
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: t(tab.descriptionKey) }),
32668
+ tab.sections.map((section) => /* @__PURE__ */ jsxs("section", { children: [
32669
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 border-b border-border/60 pb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: t(section.titleKey) }),
32670
+ section.descriptionKey && /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-muted-foreground", children: t(section.descriptionKey) }),
32671
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: section.controls.map((control) => /* @__PURE__ */ jsx(
32672
+ ControlRow,
32673
+ {
32674
+ control,
32675
+ options,
32676
+ onOptionChange
32677
+ },
32678
+ `${control.group}.${control.key}.${section.id}`
32679
+ )) }),
32680
+ section.special && renderSpecial?.(section)
32681
+ ] }, section.id)),
32682
+ children
32683
+ ] });
32684
+ }
32685
+ function CommandList({
32686
+ title,
32687
+ commandIds,
32688
+ selectedId,
32689
+ onSelect
32690
+ }) {
32691
+ const { t } = useTranslation();
32692
+ return /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
32693
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: title }),
32694
+ /* @__PURE__ */ jsx(
32695
+ "div",
32696
+ {
32697
+ role: "listbox",
32698
+ "aria-label": title,
32699
+ className: "h-48 space-y-0.5 overflow-y-auto rounded border border-border/60 p-1",
32700
+ children: commandIds.map((id) => {
32701
+ const command = QUICK_ACCESS_COMMAND_CATALOG.find((entry) => entry.id === id);
32702
+ if (!command) {
32703
+ return null;
32704
+ }
32705
+ return /* @__PURE__ */ jsx(
32706
+ "button",
32707
+ {
32708
+ type: "button",
32709
+ role: "option",
32710
+ "aria-selected": selectedId === id,
32711
+ onClick: () => onSelect(id),
32712
+ className: cn(
32713
+ "flex w-full items-center rounded px-2 py-1.5 text-left text-sm transition-colors",
32714
+ selectedId === id ? "bg-primary/15 text-primary" : "text-foreground hover:bg-accent"
32715
+ ),
32716
+ children: t(command.labelKey)
32717
+ },
32718
+ id
32719
+ );
32720
+ })
32721
+ }
32722
+ )
32723
+ ] });
32724
+ }
32725
+ function OptionsQuickAccessPane({
32726
+ options,
32727
+ onQuickAccessCommandsChange,
32728
+ onResetQuickAccess
32729
+ }) {
32730
+ const { t } = useTranslation();
32731
+ const [selectedAvailable, setSelectedAvailable] = useState(null);
32732
+ const [selectedCurrent, setSelectedCurrent] = useState(null);
32733
+ const current = options.quickAccess.commandIds;
32734
+ const available = availableQuickAccessCommands(current).map((entry) => entry.id);
32735
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
32736
+ /* @__PURE__ */ jsxs("div", { className: "flex items-stretch gap-3", children: [
32737
+ /* @__PURE__ */ jsx(
32738
+ CommandList,
32739
+ {
32740
+ title: t("pptx.options.quickAccess.chooseCommands"),
32741
+ commandIds: available,
32742
+ selectedId: selectedAvailable,
32743
+ onSelect: setSelectedAvailable
32744
+ }
32745
+ ),
32746
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col justify-center gap-2", children: [
32747
+ /* @__PURE__ */ jsxs(
32748
+ "button",
32749
+ {
32750
+ type: "button",
32751
+ disabled: !selectedAvailable,
32752
+ onClick: () => {
32753
+ if (selectedAvailable) {
32754
+ onQuickAccessCommandsChange(addQuickAccessCommand(current, selectedAvailable));
32755
+ setSelectedAvailable(null);
32756
+ }
32757
+ },
32758
+ className: "rounded border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50",
32759
+ children: [
32760
+ t("pptx.options.quickAccess.add"),
32761
+ " >>"
32762
+ ]
32763
+ }
32764
+ ),
32765
+ /* @__PURE__ */ jsxs(
32766
+ "button",
32767
+ {
32768
+ type: "button",
32769
+ disabled: !selectedCurrent,
32770
+ onClick: () => {
32771
+ if (selectedCurrent) {
32772
+ onQuickAccessCommandsChange(removeQuickAccessCommand(current, selectedCurrent));
32773
+ setSelectedCurrent(null);
32774
+ }
32775
+ },
32776
+ className: "rounded border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50",
32777
+ children: [
32778
+ "<< ",
32779
+ t("pptx.options.quickAccess.remove")
32780
+ ]
32781
+ }
32782
+ )
32783
+ ] }),
32784
+ /* @__PURE__ */ jsx(
32785
+ CommandList,
32786
+ {
32787
+ title: t("pptx.options.quickAccess.currentCommands"),
32788
+ commandIds: current,
32789
+ selectedId: selectedCurrent,
32790
+ onSelect: setSelectedCurrent
32791
+ }
32792
+ ),
32793
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col justify-center gap-2", children: [
32794
+ /* @__PURE__ */ jsx(
32795
+ "button",
32796
+ {
32797
+ type: "button",
32798
+ "aria-label": t("pptx.options.quickAccess.moveUp"),
32799
+ disabled: !selectedCurrent,
32800
+ onClick: () => {
32801
+ if (selectedCurrent) {
32802
+ onQuickAccessCommandsChange(moveQuickAccessCommand(current, selectedCurrent, "up"));
32803
+ }
32804
+ },
32805
+ className: "rounded border border-border p-1.5 text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50",
32806
+ children: /* @__PURE__ */ jsx(LuChevronUp, { className: "h-4 w-4" })
32807
+ }
32808
+ ),
32809
+ /* @__PURE__ */ jsx(
32810
+ "button",
32811
+ {
32812
+ type: "button",
32813
+ "aria-label": t("pptx.options.quickAccess.moveDown"),
32814
+ disabled: !selectedCurrent,
32815
+ onClick: () => {
32816
+ if (selectedCurrent) {
32817
+ onQuickAccessCommandsChange(
32818
+ moveQuickAccessCommand(current, selectedCurrent, "down")
32819
+ );
32820
+ }
32821
+ },
32822
+ className: "rounded border border-border p-1.5 text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50",
32823
+ children: /* @__PURE__ */ jsx(LuChevronDown, { className: "h-4 w-4" })
32824
+ }
32825
+ )
32826
+ ] })
32827
+ ] }),
32828
+ /* @__PURE__ */ jsx(
32829
+ "button",
32830
+ {
32831
+ type: "button",
32832
+ onClick: onResetQuickAccess,
32833
+ className: "rounded border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-accent",
32834
+ children: t("pptx.options.quickAccess.reset")
32835
+ }
32836
+ )
32837
+ ] });
32838
+ }
32839
+ function OptionsRibbonPane({
32840
+ options,
32841
+ onRibbonTabHiddenChange,
32842
+ onResetRibbon
32843
+ }) {
32844
+ const { t } = useTranslation();
32845
+ const hidden = new Set(options.ribbon.hiddenTabIds);
32846
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
32847
+ /* @__PURE__ */ jsxs("section", { children: [
32848
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 border-b border-border/60 pb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: t("pptx.options.ribbon.tabsTitle") }),
32849
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-muted-foreground", children: t("pptx.options.ribbon.tabsDescription") }),
32850
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5 rounded border border-border/60 p-2", children: TOOLBAR_TABS.map((tab) => {
32851
+ const isFile = tab.id === "file";
32852
+ const isVisible = isFile || !hidden.has(tab.id);
32853
+ return /* @__PURE__ */ jsxs(
32854
+ "label",
32855
+ {
32856
+ className: cn(
32857
+ "flex items-center gap-2 rounded px-2 py-1.5",
32858
+ isFile ? "cursor-not-allowed opacity-60" : "cursor-pointer hover:bg-accent"
32859
+ ),
32860
+ children: [
32861
+ /* @__PURE__ */ jsx(
32862
+ "input",
32863
+ {
32864
+ type: "checkbox",
32865
+ className: "h-4 w-4 accent-[var(--pptx-primary,#6366f1)]",
32866
+ checked: isVisible,
32867
+ disabled: isFile,
32868
+ onChange: (event) => onRibbonTabHiddenChange(tab.id, !event.target.checked)
32869
+ }
32870
+ ),
32871
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: t(tab.labelKey) })
32872
+ ]
32873
+ },
32874
+ tab.id
32875
+ );
32876
+ }) }),
32877
+ /* @__PURE__ */ jsx(
32878
+ "button",
32879
+ {
32880
+ type: "button",
32881
+ onClick: onResetRibbon,
32882
+ className: "mt-2 rounded border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-accent",
32883
+ children: t("pptx.options.ribbon.reset")
32884
+ }
32885
+ )
32886
+ ] }),
32887
+ /* @__PURE__ */ jsxs("section", { children: [
32888
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 border-b border-border/60 pb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: t("pptx.settings.keyboardShortcuts") }),
32889
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: SHORTCUT_REFERENCE_ITEMS.map((shortcut, i) => /* @__PURE__ */ jsxs(
32890
+ "div",
32891
+ {
32892
+ className: cn(
32893
+ "flex items-center justify-between gap-3 rounded px-3 py-2",
32894
+ i % 2 === 0 ? "bg-muted/60" : ""
32895
+ ),
32896
+ children: [
32897
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-foreground", children: t(shortcut.actionKey) }),
32898
+ /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap font-mono text-[11px] text-muted-foreground", children: shortcut.shortcut })
32899
+ ]
32900
+ },
32901
+ shortcut.actionKey
32902
+ )) })
32903
+ ] })
32904
+ ] });
32905
+ }
32372
32906
  function SettingsAppearanceTab({
32373
32907
  activeThemeKey,
32374
32908
  themes,
@@ -32438,43 +32972,17 @@ function SettingsLanguageTab({
32438
32972
  );
32439
32973
  }) });
32440
32974
  }
32441
- function ToggleSwitch({
32442
- label,
32443
- enabled,
32444
- onToggle
32445
- }) {
32446
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-2.5 px-3", children: [
32447
- /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: label }),
32448
- /* @__PURE__ */ jsx(
32449
- "button",
32450
- {
32451
- type: "button",
32452
- onClick: onToggle,
32453
- className: cn(
32454
- "relative inline-flex h-5 w-9 items-center rounded-full transition-colors",
32455
- enabled ? "bg-primary" : "bg-muted-foreground/30"
32456
- ),
32457
- role: "switch",
32458
- "aria-checked": enabled,
32459
- "aria-label": label,
32460
- children: /* @__PURE__ */ jsx(
32461
- "span",
32462
- {
32463
- className: cn(
32464
- "inline-block h-3.5 w-3.5 rounded-full bg-white transition-transform",
32465
- enabled ? "translate-x-[18px]" : "translate-x-[3px]"
32466
- )
32467
- }
32468
- )
32469
- }
32470
- )
32471
- ] });
32472
- }
32473
32975
  function SettingsDialog({
32474
32976
  isOpen,
32475
32977
  onClose,
32476
- settings,
32477
- onSettingsChange,
32978
+ options,
32979
+ onOptionChange,
32980
+ onRestoreOptions,
32981
+ onRibbonTabHiddenChange,
32982
+ onQuickAccessCommandsChange,
32983
+ onResetOptions,
32984
+ onClearCache,
32985
+ addinStatus,
32478
32986
  themeKey,
32479
32987
  availableThemes,
32480
32988
  onSelectTheme,
@@ -32482,9 +32990,23 @@ function SettingsDialog({
32482
32990
  availableLocales,
32483
32991
  onSelectLocale
32484
32992
  }) {
32485
- const [activeTab, setActiveTab] = useState("general");
32993
+ const [activeTabId, setActiveTabId] = useState("general");
32486
32994
  const { t } = useTranslation();
32487
32995
  const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
32996
+ const snapshotRef = useRef(null);
32997
+ const wasOpenRef = useRef(false);
32998
+ useEffect(() => {
32999
+ if (isOpen && !wasOpenRef.current) {
33000
+ snapshotRef.current = options;
33001
+ }
33002
+ wasOpenRef.current = isOpen;
33003
+ }, [isOpen, options]);
33004
+ const handleCancel = useCallback(() => {
33005
+ if (snapshotRef.current) {
33006
+ onRestoreOptions(snapshotRef.current);
33007
+ }
33008
+ onClose();
33009
+ }, [onClose, onRestoreOptions]);
32488
33010
  const handleKeyDown = useCallback(
32489
33011
  (e) => {
32490
33012
  if (e.key === "Escape") {
@@ -32502,12 +33024,10 @@ function SettingsDialog({
32502
33024
  if (!isOpen) {
32503
33025
  return null;
32504
33026
  }
32505
- const tabs = [
32506
- { id: "general", label: t("pptx.settings.general") },
32507
- { id: "appearance", label: t("pptx.settings.appearance") },
32508
- { id: "language", label: t("pptx.settings.language") },
32509
- { id: "shortcuts", label: t("pptx.settings.keyboardShortcuts") }
32510
- ];
33027
+ const activeTab = VIEWER_OPTIONS_TABS.find((tab) => tab.id === activeTabId) ?? VIEWER_OPTIONS_TABS[0];
33028
+ if (!activeTab) {
33029
+ return null;
33030
+ }
32511
33031
  return /* @__PURE__ */ jsxs(Fragment, { children: [
32512
33032
  /* @__PURE__ */ jsx(
32513
33033
  "button",
@@ -32528,87 +33048,157 @@ function SettingsDialog({
32528
33048
  "div",
32529
33049
  {
32530
33050
  style: panelStyle,
32531
- className: "pointer-events-auto w-[min(32rem,calc(100%-2rem))] rounded-xl border border-border bg-popover backdrop-blur-xl shadow-2xl max-md:fixed max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:w-full max-md:max-h-[88dvh] max-md:overflow-y-auto max-md:rounded-t-2xl max-md:rounded-b-none max-md:border-x-0 max-md:border-b-0 max-md:pb-[max(env(safe-area-inset-bottom),0px)]",
33051
+ role: "dialog",
33052
+ "aria-modal": "true",
33053
+ "aria-label": t("pptx.options.title"),
33054
+ className: "pointer-events-auto flex max-h-[85vh] w-[min(56rem,calc(100%-2rem))] flex-col rounded-xl border border-border bg-popover shadow-2xl backdrop-blur-xl max-md:fixed max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:max-h-[88dvh] max-md:w-full max-md:rounded-t-2xl max-md:rounded-b-none max-md:border-x-0 max-md:border-b-0 max-md:pb-[max(env(safe-area-inset-bottom),0px)]",
32532
33055
  children: [
32533
33056
  /* @__PURE__ */ jsxs(
32534
33057
  "div",
32535
33058
  {
32536
33059
  ...dragHandlers,
32537
- className: "flex items-center justify-between px-5 py-4 border-b border-border/60 touch-none",
33060
+ className: "flex items-center justify-between border-b border-border/60 px-5 py-4 touch-none",
32538
33061
  children: [
32539
33062
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
32540
- /* @__PURE__ */ jsx(LuSettings, { className: "w-5 h-5 text-primary" }),
32541
- /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-foreground", children: t("pptx.settings.title") })
33063
+ /* @__PURE__ */ jsx(LuSettings, { className: "h-5 w-5 text-primary" }),
33064
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-foreground", children: t("pptx.options.title") })
32542
33065
  ] }),
32543
33066
  /* @__PURE__ */ jsx(
32544
33067
  "button",
32545
33068
  {
32546
33069
  type: "button",
32547
33070
  onClick: onClose,
32548
- className: "p-1 rounded hover:bg-accent transition-colors",
33071
+ className: "rounded p-1 transition-colors hover:bg-accent",
32549
33072
  "aria-label": t("pptx.settings.close"),
32550
- children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4 text-muted-foreground" })
33073
+ children: /* @__PURE__ */ jsx(LuX, { className: "h-4 w-4 text-muted-foreground" })
32551
33074
  }
32552
33075
  )
32553
33076
  ]
32554
33077
  }
32555
33078
  ),
32556
- /* @__PURE__ */ jsx("div", { className: "flex border-b border-border/60 px-5", children: tabs.map((tab) => /* @__PURE__ */ jsxs(
32557
- "button",
32558
- {
32559
- type: "button",
32560
- onClick: () => setActiveTab(tab.id),
32561
- className: cn(
32562
- "px-3 py-2 text-xs font-medium transition-colors relative",
32563
- activeTab === tab.id ? "text-primary" : "text-muted-foreground hover:text-foreground"
32564
- ),
32565
- children: [
32566
- tab.label,
32567
- activeTab === tab.id && /* @__PURE__ */ jsx("span", { className: "absolute bottom-0 left-0 right-0 h-0.5 bg-primary rounded-full" })
32568
- ]
32569
- },
32570
- tab.id
32571
- )) }),
32572
- /* @__PURE__ */ jsxs("div", { className: "px-5 py-4 max-h-[60vh] overflow-y-auto", children: [
32573
- activeTab === "general" && /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: SETTING_TOGGLES.map((toggle) => /* @__PURE__ */ jsx(
32574
- ToggleSwitch,
32575
- {
32576
- label: t(toggle.labelKey),
32577
- enabled: settings[toggle.key],
32578
- onToggle: () => onSettingsChange(toggle.key, !settings[toggle.key])
32579
- },
32580
- toggle.key
32581
- )) }),
32582
- activeTab === "appearance" && /* @__PURE__ */ jsx(
32583
- SettingsAppearanceTab,
33079
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 max-md:flex-col", children: [
33080
+ /* @__PURE__ */ jsx(
33081
+ "nav",
32584
33082
  {
32585
- activeThemeKey: themeKey,
32586
- themes: availableThemes,
32587
- onSelectTheme
33083
+ "aria-label": t("pptx.options.title"),
33084
+ className: "w-44 shrink-0 space-y-0.5 overflow-y-auto border-r border-border/60 p-2 max-md:flex max-md:w-full max-md:space-y-0 max-md:gap-1 max-md:overflow-x-auto max-md:border-b max-md:border-r-0",
33085
+ children: VIEWER_OPTIONS_TABS.map((tab) => /* @__PURE__ */ jsx(
33086
+ "button",
33087
+ {
33088
+ type: "button",
33089
+ onClick: () => setActiveTabId(tab.id),
33090
+ "aria-current": activeTabId === tab.id,
33091
+ className: cn(
33092
+ "block w-full whitespace-nowrap rounded px-3 py-2 text-left text-sm transition-colors max-md:w-auto",
33093
+ activeTabId === tab.id ? "bg-primary/10 font-medium text-primary" : "text-foreground hover:bg-accent"
33094
+ ),
33095
+ children: t(tab.labelKey)
33096
+ },
33097
+ tab.id
33098
+ ))
32588
33099
  }
32589
33100
  ),
32590
- activeTab === "language" && /* @__PURE__ */ jsx(
32591
- SettingsLanguageTab,
33101
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-5 py-4", children: activeTab.custom === "language" ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
33102
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: t(activeTab.descriptionKey) }),
33103
+ /* @__PURE__ */ jsxs("section", { children: [
33104
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 border-b border-border/60 pb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: t("pptx.options.language.displayLanguage") }),
33105
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-muted-foreground", children: t("pptx.options.language.displayLanguageDescription") }),
33106
+ /* @__PURE__ */ jsx(
33107
+ SettingsLanguageTab,
33108
+ {
33109
+ activeLocale: localeCode,
33110
+ locales: availableLocales,
33111
+ onSelectLocale
33112
+ }
33113
+ )
33114
+ ] })
33115
+ ] }) : activeTab.custom === "ribbon" ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
33116
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: t(activeTab.descriptionKey) }),
33117
+ /* @__PURE__ */ jsx(
33118
+ OptionsRibbonPane,
33119
+ {
33120
+ options,
33121
+ onRibbonTabHiddenChange,
33122
+ onResetRibbon: () => onResetOptions("ribbon")
33123
+ }
33124
+ )
33125
+ ] }) : activeTab.custom === "addIns" ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
33126
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: t(activeTab.descriptionKey) }),
33127
+ /* @__PURE__ */ jsx(OptionsAddInsPane, { addinStatus })
33128
+ ] }) : /* @__PURE__ */ jsx(
33129
+ OptionsPane,
32592
33130
  {
32593
- activeLocale: localeCode,
32594
- locales: availableLocales,
32595
- onSelectLocale
33131
+ tab: activeTab,
33132
+ options,
33133
+ onOptionChange,
33134
+ renderSpecial: (section) => {
33135
+ if (section.special === "themePicker") {
33136
+ return /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(
33137
+ SettingsAppearanceTab,
33138
+ {
33139
+ activeThemeKey: themeKey,
33140
+ themes: availableThemes,
33141
+ onSelectTheme
33142
+ }
33143
+ ) });
33144
+ }
33145
+ if (section.special === "clearCache") {
33146
+ return /* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
33147
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-muted-foreground", children: t("pptx.options.save.clearCacheDescription") }),
33148
+ /* @__PURE__ */ jsx(
33149
+ "button",
33150
+ {
33151
+ type: "button",
33152
+ onClick: onClearCache,
33153
+ className: "rounded border border-border px-3 py-1.5 text-xs text-foreground transition-colors hover:bg-accent",
33154
+ children: t("pptx.options.save.clearCacheNow")
33155
+ }
33156
+ )
33157
+ ] });
33158
+ }
33159
+ return null;
33160
+ },
33161
+ children: activeTab.custom === "quickAccess" && /* @__PURE__ */ jsx(
33162
+ OptionsQuickAccessPane,
33163
+ {
33164
+ options,
33165
+ onQuickAccessCommandsChange,
33166
+ onResetQuickAccess: () => onQuickAccessCommandsChange([...DEFAULT_QUICK_ACCESS_COMMAND_IDS])
33167
+ }
33168
+ )
32596
33169
  }
32597
- ),
32598
- activeTab === "shortcuts" && /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: SHORTCUT_REFERENCE_ITEMS.map((shortcut, i) => /* @__PURE__ */ jsxs(
32599
- "div",
33170
+ ) })
33171
+ ] }),
33172
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 border-t border-border/60 px-5 py-3", children: [
33173
+ /* @__PURE__ */ jsx(
33174
+ "button",
32600
33175
  {
32601
- className: cn(
32602
- "flex items-center justify-between gap-3 rounded px-3 py-2",
32603
- i % 2 === 0 ? "bg-muted/60" : ""
32604
- ),
32605
- children: [
32606
- /* @__PURE__ */ jsx("span", { className: "text-xs text-foreground", children: t(shortcut.actionKey) }),
32607
- /* @__PURE__ */ jsx("span", { className: "font-mono text-[11px] text-muted-foreground whitespace-nowrap", children: shortcut.shortcut })
32608
- ]
32609
- },
32610
- shortcut.actionKey
32611
- )) })
33176
+ type: "button",
33177
+ onClick: () => onResetOptions(),
33178
+ className: "rounded border border-border px-3 py-1.5 text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
33179
+ children: t("pptx.options.resetAll")
33180
+ }
33181
+ ),
33182
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
33183
+ /* @__PURE__ */ jsx(
33184
+ "button",
33185
+ {
33186
+ type: "button",
33187
+ onClick: handleCancel,
33188
+ className: "rounded border border-border px-4 py-1.5 text-xs text-foreground transition-colors hover:bg-accent",
33189
+ children: t("pptx.common.cancel")
33190
+ }
33191
+ ),
33192
+ /* @__PURE__ */ jsx(
33193
+ "button",
33194
+ {
33195
+ type: "button",
33196
+ onClick: onClose,
33197
+ className: "rounded bg-primary px-4 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90",
33198
+ children: t("pptx.common.ok")
33199
+ }
33200
+ )
33201
+ ] })
32612
33202
  ] })
32613
33203
  ]
32614
33204
  }
@@ -32801,6 +33391,49 @@ var PowerPointViewer = forwardRef(
32801
33391
  },
32802
33392
  [state, reducedMotion, toggleReducedMotion]
32803
33393
  );
33394
+ const { optionsStore, options: viewerOptions } = useViewerOptions();
33395
+ const settingsRef = useRef(settings);
33396
+ settingsRef.current = settings;
33397
+ const syncingFromOptionsRef = useRef(false);
33398
+ useEffect(() => {
33399
+ const mapped = viewerOptionsToPreferences(viewerOptions);
33400
+ let changed = false;
33401
+ for (const key of Object.keys(mapped)) {
33402
+ if (mapped[key] !== settingsRef.current[key]) {
33403
+ changed = true;
33404
+ handleSettingsChange(key, mapped[key]);
33405
+ }
33406
+ }
33407
+ if (changed) {
33408
+ syncingFromOptionsRef.current = true;
33409
+ }
33410
+ }, [viewerOptions, handleSettingsChange]);
33411
+ useEffect(() => {
33412
+ const current = optionsStore.getOptions();
33413
+ const mapped = viewerOptionsToPreferences(current);
33414
+ const keys = Object.keys(mapped);
33415
+ if (syncingFromOptionsRef.current) {
33416
+ if (keys.every((key) => mapped[key] === settings[key])) {
33417
+ syncingFromOptionsRef.current = false;
33418
+ }
33419
+ return;
33420
+ }
33421
+ let next = current;
33422
+ for (const key of keys) {
33423
+ if (mapped[key] !== settings[key]) {
33424
+ next = applyPreferenceToOptions(next, key, settings[key]);
33425
+ }
33426
+ }
33427
+ if (next !== current) {
33428
+ optionsStore.setOptions(next);
33429
+ }
33430
+ }, [settings, optionsStore]);
33431
+ const handleClearOptionsCache = useCallback(() => {
33432
+ void (async () => {
33433
+ const snapshots = await listAutosaveSnapshots();
33434
+ await Promise.all(snapshots.map((entry) => deleteAutosaveSnapshot(entry.key)));
33435
+ })();
33436
+ }, []);
32804
33437
  const mobile = useIsMobile({ containerRef });
32805
33438
  const { isMobile, isTouchDevice, isVirtualKeyboardOpen } = mobile;
32806
33439
  const resizablePanels = useResizablePanels();
@@ -32960,7 +33593,8 @@ var PowerPointViewer = forwardRef(
32960
33593
  handleEnterRehearsalMode,
32961
33594
  autosaveStatus,
32962
33595
  isEncryptedDialogOpen,
32963
- setIsEncryptedDialogOpen
33596
+ setIsEncryptedDialogOpen,
33597
+ loadVersion
32964
33598
  } = useViewerIntegration({
32965
33599
  state,
32966
33600
  zoom,
@@ -33156,8 +33790,13 @@ var PowerPointViewer = forwardRef(
33156
33790
  {
33157
33791
  isOpen: isSettingsOpen,
33158
33792
  onClose: () => setIsSettingsOpen(false),
33159
- settings,
33160
- onSettingsChange: handleSettingsChange,
33793
+ options: viewerOptions,
33794
+ onOptionChange: (group, key, value) => optionsStore.setValue(group, key, value),
33795
+ onRestoreOptions: (snapshot) => optionsStore.setOptions(snapshot),
33796
+ onRibbonTabHiddenChange: (tabId, hidden) => optionsStore.setRibbonTabHidden(tabId, hidden),
33797
+ onQuickAccessCommandsChange: (commandIds) => optionsStore.setQuickAccessCommands(commandIds),
33798
+ onResetOptions: (group) => optionsStore.reset(group),
33799
+ onClearCache: handleClearOptionsCache,
33161
33800
  themeKey,
33162
33801
  availableThemes: themeCatalog,
33163
33802
  onSelectTheme: handleThemeChange,
@@ -33272,7 +33911,8 @@ var PowerPointViewer = forwardRef(
33272
33911
  templateElementsBySlideId,
33273
33912
  setSlides: state.setSlides,
33274
33913
  config: collaboration,
33275
- content
33914
+ content,
33915
+ loadVersion
33276
33916
  }
33277
33917
  ),
33278
33918
  /* @__PURE__ */ jsx(
@@ -33309,7 +33949,8 @@ function CollaborationDocumentSync({
33309
33949
  templateElementsBySlideId,
33310
33950
  setSlides,
33311
33951
  config,
33312
- content
33952
+ content,
33953
+ loadVersion
33313
33954
  }) {
33314
33955
  const collab = useCollaboration();
33315
33956
  const contentRef = useRef(content);
@@ -33329,7 +33970,8 @@ function CollaborationDocumentSync({
33329
33970
  isConnected: collab?.status === "connected",
33330
33971
  isSynced: collab?.synced ?? true,
33331
33972
  config,
33332
- getSourceBytes
33973
+ getSourceBytes,
33974
+ loadVersion
33333
33975
  });
33334
33976
  return null;
33335
33977
  }