pptx-react-viewer 1.17.0 → 1.18.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.
- package/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/dist/{Model3DScene-YA4F63DT.js → Model3DScene-GVWQ6SOM.js} +3 -3
- package/dist/Model3DScene-GVWQ6SOM.js.br +0 -0
- package/dist/Model3DScene-GVWQ6SOM.js.gz +0 -0
- package/dist/{Model3DScene-QHDYQXL2.mjs → Model3DScene-JGVLIDLD.mjs} +2 -2
- package/dist/Model3DScene-JGVLIDLD.mjs.br +0 -0
- package/dist/Model3DScene-JGVLIDLD.mjs.gz +0 -0
- package/dist/{SurfaceChart3DScene-GUAS2NWQ.mjs → SurfaceChart3DScene-DBWSDSKI.mjs} +2 -2
- package/dist/SurfaceChart3DScene-DBWSDSKI.mjs.br +0 -0
- package/dist/SurfaceChart3DScene-DBWSDSKI.mjs.gz +0 -0
- package/dist/{SurfaceChart3DScene-TGNJHTJQ.js → SurfaceChart3DScene-ZOTOHOIE.js} +3 -3
- package/dist/SurfaceChart3DScene-ZOTOHOIE.js.br +0 -0
- package/dist/SurfaceChart3DScene-ZOTOHOIE.js.gz +0 -0
- package/dist/{chunk-XW5OMXW6.js → chunk-73ST7AC6.js} +2269 -1651
- package/dist/chunk-73ST7AC6.js.br +0 -0
- package/dist/chunk-73ST7AC6.js.gz +0 -0
- package/dist/{chunk-WGLJ32FW.js → chunk-AALZCSY4.js} +8 -1
- package/dist/chunk-AALZCSY4.js.br +0 -0
- package/dist/chunk-AALZCSY4.js.gz +0 -0
- package/dist/{chunk-MGLRKGCH.js → chunk-EXDUEXTO.js} +26101 -15360
- package/dist/chunk-EXDUEXTO.js.br +0 -0
- package/dist/chunk-EXDUEXTO.js.gz +0 -0
- package/dist/{chunk-JWS3RQKN.js → chunk-HBXPK572.js} +584 -144
- package/dist/chunk-HBXPK572.js.br +0 -0
- package/dist/chunk-HBXPK572.js.gz +0 -0
- package/dist/{chunk-G22EWPLH.mjs → chunk-HHTZQHKZ.mjs} +532 -119
- package/dist/chunk-HHTZQHKZ.mjs.br +0 -0
- package/dist/chunk-HHTZQHKZ.mjs.gz +0 -0
- package/dist/{chunk-3P6O7ZDM.js → chunk-JDRC3PSY.js} +655 -491
- package/dist/chunk-JDRC3PSY.js.br +0 -0
- package/dist/chunk-JDRC3PSY.js.gz +0 -0
- package/dist/{chunk-LNSHC2Z5.mjs → chunk-KMLIWCNL.mjs} +1460 -842
- package/dist/chunk-KMLIWCNL.mjs.br +0 -0
- package/dist/chunk-KMLIWCNL.mjs.gz +0 -0
- package/dist/{chunk-HJQZJ3VE.mjs → chunk-RIRK64DM.mjs} +8 -1
- package/dist/chunk-RIRK64DM.mjs.br +0 -0
- package/dist/chunk-RIRK64DM.mjs.gz +0 -0
- package/dist/{chunk-XRYREYXC.mjs → chunk-SBNTEQUA.mjs} +26062 -15360
- package/dist/chunk-SBNTEQUA.mjs.br +0 -0
- package/dist/chunk-SBNTEQUA.mjs.gz +0 -0
- package/dist/{chunk-LLHFNGAF.mjs → chunk-Z4MDCPAY.mjs} +223 -59
- package/dist/chunk-Z4MDCPAY.mjs.br +0 -0
- package/dist/chunk-Z4MDCPAY.mjs.gz +0 -0
- package/dist/{dist-2ZAH7U6U.js → dist-KRRXYUGI.js} +663 -507
- package/dist/dist-KRRXYUGI.js.br +0 -0
- package/dist/dist-KRRXYUGI.js.gz +0 -0
- package/dist/dist-N6PAPXK6.mjs +2 -0
- package/dist/dist-N6PAPXK6.mjs.br +0 -0
- package/dist/dist-N6PAPXK6.mjs.gz +0 -0
- package/dist/hooks-unstable.d.ts +484 -117
- package/dist/hooks-unstable.d.ts.map +1 -1
- package/dist/hooks-unstable.js +75 -75
- package/dist/hooks-unstable.js.br +0 -0
- package/dist/hooks-unstable.js.gz +0 -0
- package/dist/hooks-unstable.mjs +4 -4
- package/dist/hooks-unstable.mjs.br +0 -0
- package/dist/hooks-unstable.mjs.gz +0 -0
- package/dist/i18n.js +3 -3
- package/dist/i18n.js.br +0 -0
- package/dist/i18n.js.gz +0 -0
- package/dist/i18n.mjs +1 -1
- package/dist/i18n.mjs.br +0 -0
- package/dist/i18n.mjs.gz +0 -0
- package/dist/{index-XGt7MZpa.d.ts → index-DmHVR48M.d.ts} +25 -3
- package/dist/index-DmHVR48M.d.ts.map +1 -0
- package/dist/index.d.ts +412 -117
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -19
- package/dist/index.js.br +3 -1
- package/dist/index.js.gz +0 -0
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.br +3 -4
- package/dist/index.mjs.gz +0 -0
- package/dist/pptx-viewer.css +1 -1
- package/dist/pptx-viewer.css.br +0 -0
- package/dist/pptx-viewer.css.gz +0 -0
- package/dist/viewer/index.d.ts +438 -121
- package/dist/viewer/index.d.ts.map +1 -1
- package/dist/viewer/index.js +24 -20
- package/dist/viewer/index.js.br +0 -0
- package/dist/viewer/index.js.gz +0 -0
- package/dist/viewer/index.mjs +5 -5
- package/dist/viewer/index.mjs.br +0 -0
- package/dist/viewer/index.mjs.gz +0 -0
- package/package.json +1 -1
- package/dist/Model3DScene-QHDYQXL2.mjs.br +0 -0
- package/dist/Model3DScene-QHDYQXL2.mjs.gz +0 -0
- package/dist/Model3DScene-YA4F63DT.js.br +0 -0
- package/dist/Model3DScene-YA4F63DT.js.gz +0 -0
- package/dist/SurfaceChart3DScene-GUAS2NWQ.mjs.br +0 -0
- package/dist/SurfaceChart3DScene-GUAS2NWQ.mjs.gz +0 -0
- package/dist/SurfaceChart3DScene-TGNJHTJQ.js.br +0 -0
- package/dist/SurfaceChart3DScene-TGNJHTJQ.js.gz +0 -0
- package/dist/chunk-3P6O7ZDM.js.br +0 -0
- package/dist/chunk-3P6O7ZDM.js.gz +0 -0
- package/dist/chunk-G22EWPLH.mjs.br +0 -0
- package/dist/chunk-G22EWPLH.mjs.gz +0 -0
- package/dist/chunk-HJQZJ3VE.mjs.br +0 -0
- package/dist/chunk-HJQZJ3VE.mjs.gz +0 -0
- package/dist/chunk-JWS3RQKN.js.br +0 -0
- package/dist/chunk-JWS3RQKN.js.gz +0 -0
- package/dist/chunk-LLHFNGAF.mjs.br +0 -0
- package/dist/chunk-LLHFNGAF.mjs.gz +0 -0
- package/dist/chunk-LNSHC2Z5.mjs.br +0 -0
- package/dist/chunk-LNSHC2Z5.mjs.gz +0 -0
- package/dist/chunk-MGLRKGCH.js.br +0 -0
- package/dist/chunk-MGLRKGCH.js.gz +0 -0
- package/dist/chunk-WGLJ32FW.js.br +0 -0
- package/dist/chunk-WGLJ32FW.js.gz +0 -0
- package/dist/chunk-XRYREYXC.mjs.br +0 -0
- package/dist/chunk-XRYREYXC.mjs.gz +0 -0
- package/dist/chunk-XW5OMXW6.js.br +0 -0
- package/dist/chunk-XW5OMXW6.js.gz +0 -0
- package/dist/dist-2ZAH7U6U.js.br +0 -0
- package/dist/dist-2ZAH7U6U.js.gz +0 -0
- package/dist/dist-MXDC6YTS.mjs +0 -2
- package/dist/dist-MXDC6YTS.mjs.br +0 -0
- package/dist/dist-MXDC6YTS.mjs.gz +0 -0
- package/dist/index-XGt7MZpa.d.ts.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, MIN_ELEMENT_SIZE, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, SHAPE_PRESETS, ANIMATION_PRESET_OPTIONS, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useYjsDocumentSync, useFollowMode, useBroadcastFollower, resolvePalette, resolveStyle, layoutToCategory, wrapChrome, SLIDE_TRANSITION_OPTIONS, DEFAULT_FILL_COLOR, shouldRenderFallbackLabel, isImageTiled, getImageTilingStyle, renderTextSegments, getTextLayoutStyle, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, renderTableElement, renderMediaElement, buildTextBody3DSceneStyle, getTextWarpStyle, getCropShapeClipPath, SLIDE_NAV_THUMBNAIL_WIDTH, useKeyboardInsets, useModalDismissDrag, SHORTCUT_REFERENCE_ITEMS, useCollaborativeState, styleShadow, styleStroke, colour, fitFontSize, smartArtNodeGroupProps, chevronPoints, SmartArtNodeText, truncate, renderStepDownProcess, renderAlternatingFlow, renderDescendingProcess, renderPictureAccentList, renderVerticalBlockList, renderGroupedList, renderPyramidList, renderHorizontalPictureList, renderAccentProcess, renderVerticalChevronList, parseTableElementData, ensureArrayValue, getTableCellBandStyle, extractCellText, extractTableCellStyle, cellStyleToCss, renderChartElement, getDuotoneColors, renderDuotoneSvgFilter, renderArtisticEffectSvgFilter, renderImageAlphaSvgFilter, buildReactChartViewModel, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, TOOLBAR_SECTIONS, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, buildTree, treeWidth, treeDepth, nodeOpacity, gearPath, resolveSmartArtDataPalette, EMU_PER_PX, HYPERLINK_COLOR, GRID_SIZE, startPreviewAnimation, stopPreviewAnimation } from './chunk-
|
|
2
|
-
import { normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, getElementTransform, ACTION_BUTTON_PRESETS, isEditableTextElement, getAriaRole, getAriaLabel, getAriaRoleDescription, getImageEffectsOpacity, getImageEffectsFilter, getElementTransformWithoutRotation, RULER_THICKNESS, RULER_FONT_SIZE, convertLatexToOmml, convertOmmlToMathMl, buildUserFontFaceStyles, openPptxFile, buildSmartArtA11y, buildCssGradientFromShapeStyle, getElementLabel, getTextCompensationTransform,
|
|
3
|
-
import { translationsEn } from './chunk-
|
|
4
|
-
import { hasShapeProperties, hasTextProperties, SWITCHABLE_LAYOUT_TYPES, isInkElement, getLinkedTextBoxSegments, isImageLikeElement, getSubstituteFontFamily, setSmartArtNodeStyle, updateSmartArtNodeText, THEME_COLOR_SCHEME_KEYS, chartDataChangeType, chartDataUpdatePoint, chartDataAddCategory, chartDataRemoveCategory, chartDataAddSeries, chartDataRemoveSeries, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, getOleObjectTypeLabel, pptxActionToElementAction,
|
|
1
|
+
import { DEFAULT_STROKE_COLOR, getConnectorPathGeometry, buildLineShadowCss, buildLineGlowFilter, renderConnectorMarker, MIN_ELEMENT_SIZE, getShapeVisualStyle, getTextStyleForElement, DEFAULT_TEXT_COLOR, renderVectorShape, isConnectorOrLineElement, build3DExtrusionData, getImageRenderStyle, cn, SHAPE_PRESETS, ANIMATION_PRESET_OPTIONS, useReducedMotion, useViewerState, useIsMobile, useResizablePanels, useDerivedSlideState, useZoomViewport, useEditorHistory, usePresentationSetup, useTouchGestures, useViewerDialogs, useEditorOperations, useViewerIntegration, useYjsDocumentSync, useFollowMode, useBroadcastFollower, resolvePalette, resolveStyle, layoutToCategory, wrapChrome, SLIDE_TRANSITION_OPTIONS, DEFAULT_FILL_COLOR, shouldRenderFallbackLabel, isImageTiled, getImageTilingStyle, renderTextSegments, getTextLayoutStyle, hasDagDuotoneEffect, renderDagDuotoneSvgFilter, renderTableElement, renderMediaElement, buildTextBody3DSceneStyle, getTextWarpStyle, getCropShapeClipPath, SLIDE_NAV_THUMBNAIL_WIDTH, useKeyboardInsets, useModalDismissDrag, SHORTCUT_REFERENCE_ITEMS, useCollaborativeState, styleShadow, styleStroke, colour, fitFontSize, smartArtNodeGroupProps, chevronPoints, SmartArtNodeText, truncate, renderStepDownProcess, renderAlternatingFlow, renderDescendingProcess, renderPictureAccentList, renderVerticalBlockList, renderGroupedList, renderPyramidList, renderHorizontalPictureList, renderAccentProcess, renderVerticalChevronList, parseTableElementData, ensureArrayValue, getTableCellBandStyle, extractCellText, extractTableCellStyle, cellStyleToCss, renderChartElement, getDuotoneColors, renderDuotoneSvgFilter, renderArtisticEffectSvgFilter, renderImageAlphaSvgFilter, buildReactChartViewModel, DEFAULT_TEXT_FONT_SIZE, DEFAULT_FONT_FAMILY, TOOLBAR_SECTIONS, useVirtualizedSlides, useSwipeNavigation, useSheetDismissDrag, detectTargetType, parseEmailUrl, parseSlideFromUrl, ACTION_VERB_MAP, buildTree, treeWidth, treeDepth, nodeOpacity, gearPath, resolveSmartArtDataPalette, EMU_PER_PX, HYPERLINK_COLOR, GRID_SIZE, startPreviewAnimation, stopPreviewAnimation } from './chunk-Z4MDCPAY.mjs';
|
|
2
|
+
import { normalizeHexColor, colorWithOpacity, normalizeStrokeDashType, getSvgStrokeDasharray, getCompoundLineOffsets, getCompoundLineWidths, svgLineCap, getElementTransform, ACTION_BUTTON_PRESETS, isEditableTextElement, getAriaRole, getAriaLabel, getAriaRoleDescription, getImageEffectsOpacity, getImageEffectsFilter, getElementTransformWithoutRotation, RULER_THICKNESS, RULER_FONT_SIZE, convertLatexToOmml, convertOmmlToMathMl, buildUserFontFaceStyles, openPptxFile, buildSmartArtA11y, buildCssGradientFromShapeStyle, getElementLabel, getTextCompensationTransform, shouldUseSvgWarp, themeToCssVars, DEFAULT_INSERT_CHART_TYPE, hasCopyableFormat, buildJoinCollaborationConfig, buildCreateCollaborationConfig, generateBroadcastRoomId, DEFAULT_BROADCAST_SERVER_URL, buildBroadcastViewerUrl, resolveTransportForServerUrl, resolveDrawingShapeNodeId, getSlideBackgroundStyle, getPendingSelectionRestore, restoreSegmentSelection, formatAxisValue, hasPressureVariation, getInkReplayStyles, INK_REPLAY_KEYFRAMES, resolveInkColor, resolveInkWidth, resolveInkOpacity, pressuresToWidths, getContentPartReplayStyles, resolveOleType, getOleTypeColor, getOleTypeLabel, getWarpPath, filterCommands, resolveTitleBarStatusKey, TITLE_BAR_CLASSES, TITLE_BAR_DEFAULT_FILE_KEY, safeOpenUrl, isPpactionUrl, parsePpactionUrl, formatVersionTimestamp, formatRelativeTime, PRESETS, CATEGORIES, convertOmmlToLatex, clampPercent, HANDOUT_OPTIONS, activateModalFocus, buildCollaborationShareUrl, presentationInkPath, mobileElapsedSince, isFirstSlide, isLastSlide, formatMobileElapsed, mobileSlideCounter, formatElapsed, computeInlineEditorRect, findSmartArtNodeText, rebuildDrawingShapesIfCleared, shouldCommitSmartArtNodeText, 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, groupIntoParagraphs, substituteFieldText, TAB_ROW_ACTION_CLASSES, INSERT_CHART_TYPES, 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, getConnectionSites, generateTicks, getCommentMarkerPosition, buildThemeColorGrid, THEME_COLOR_LABELS, buildSmartArtPresetData, 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-HHTZQHKZ.mjs';
|
|
3
|
+
import { translationsEn } from './chunk-RIRK64DM.mjs';
|
|
4
|
+
import { hasShapeProperties, hasTextProperties, SWITCHABLE_LAYOUT_TYPES, isInkElement, getLinkedTextBoxSegments, isImageLikeElement, getSubstituteFontFamily, themeColorSchemesEqual, setSmartArtNodeStyle, updateSmartArtNodeText, 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-SBNTEQUA.mjs';
|
|
5
5
|
import React5, { 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, 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,
|
|
8
|
+
import { LuRotateCw, LuMessageSquare, LuEyeOff, LuSettings, LuX, 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, LuFolderOpen, LuPackage, LuVideo, LuImage, LuClipboardPaste, LuScissors, LuPaintbrush, LuChevronDown, LuSquare, LuDatabase, LuAArrowUp, LuAArrowDown, LuRemoveFormatting, LuHighlighter, LuList, LuListOrdered, LuIndentDecrease, LuIndentIncrease, LuReplace, LuMousePointer2, LuShapes, LuPaintBucket, LuPenLine, LuSparkles, LuChevronUp, LuPalette, LuPencil, LuCaptions, LuSpellCheck, LuGitCompare, LuGlobe, LuPipette, LuCaseSensitive, LuTimer, LuEraser, LuGripVertical, LuUpload, LuBold, LuItalic, LuUnderline, LuStrikethrough, LuLink, LuGrid2X2, LuCopyPlus, LuCirclePlay, LuCirclePause, LuRotateCcw, LuZoomIn, LuZoomOut, LuScan, LuMonitorOff, LuClipboardCopy, LuLayoutGrid, LuWand, LuTextCursorInput, LuFile, LuEllipsis, LuFolderPlus, LuAlignLeft, LuAlignCenter, LuAlignRight, LuAlignJustify, LuColumns3, LuMoveRight, LuSpline, LuAlignHorizontalSpaceAround, LuAlignVerticalSpaceAround, LuMove, LuRadio, LuLockOpen, LuArrowDown, LuArrowUp, LuArrowRight, LuArrowLeft, LuReply, LuBookmark } from 'react-icons/lu';
|
|
9
9
|
import DOMPurify from 'dompurify';
|
|
10
10
|
|
|
11
11
|
var ViewerThemeContext = createContext(void 0);
|
|
@@ -243,6 +243,7 @@ function CollaborationStatusIndicator({
|
|
|
243
243
|
return /* @__PURE__ */ jsxs(
|
|
244
244
|
"div",
|
|
245
245
|
{
|
|
246
|
+
role: "status",
|
|
246
247
|
"data-testid": "collaboration-status",
|
|
247
248
|
className: "flex items-center gap-1.5",
|
|
248
249
|
"aria-label": t("pptx.collaboration.statusAriaLabel", {
|
|
@@ -465,12 +466,21 @@ function LoadingState({ className }) {
|
|
|
465
466
|
return /* @__PURE__ */ jsx(
|
|
466
467
|
"div",
|
|
467
468
|
{
|
|
469
|
+
role: "status",
|
|
470
|
+
"aria-live": "polite",
|
|
471
|
+
"aria-atomic": "true",
|
|
468
472
|
className: cn(
|
|
469
473
|
"h-full w-full flex items-center justify-center text-muted-foreground",
|
|
470
474
|
className
|
|
471
475
|
),
|
|
472
476
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
473
|
-
/* @__PURE__ */ jsx(
|
|
477
|
+
/* @__PURE__ */ jsx(
|
|
478
|
+
"div",
|
|
479
|
+
{
|
|
480
|
+
className: "animate-spin rounded-full h-6 w-6 border-b-2 border-primary",
|
|
481
|
+
"aria-hidden": "true"
|
|
482
|
+
}
|
|
483
|
+
),
|
|
474
484
|
/* @__PURE__ */ jsx("span", { children: t("pptx.viewer.loading") })
|
|
475
485
|
] })
|
|
476
486
|
}
|
|
@@ -480,6 +490,8 @@ function ErrorState({ className, error }) {
|
|
|
480
490
|
return /* @__PURE__ */ jsx(
|
|
481
491
|
"div",
|
|
482
492
|
{
|
|
493
|
+
role: "alert",
|
|
494
|
+
"aria-live": "assertive",
|
|
483
495
|
className: cn(
|
|
484
496
|
"h-full w-full flex items-center justify-center p-6 text-center text-red-400",
|
|
485
497
|
className
|
|
@@ -883,6 +895,17 @@ function ResizeHandle({
|
|
|
883
895
|
}
|
|
884
896
|
);
|
|
885
897
|
}
|
|
898
|
+
|
|
899
|
+
// src/viewer/utils/slide-background-style.ts
|
|
900
|
+
function getReactSlideBackgroundStyle(slide) {
|
|
901
|
+
const style = getSlideBackgroundStyle(slide);
|
|
902
|
+
return {
|
|
903
|
+
backgroundColor: style["background-color"],
|
|
904
|
+
backgroundImage: style["background-image"],
|
|
905
|
+
backgroundSize: style["background-size"],
|
|
906
|
+
backgroundRepeat: style["background-repeat"]
|
|
907
|
+
};
|
|
908
|
+
}
|
|
886
909
|
function DrawingShapeRenderer({
|
|
887
910
|
elementId,
|
|
888
911
|
shapes,
|
|
@@ -2665,7 +2688,7 @@ function SlideThumbnailImpl({
|
|
|
2665
2688
|
"div",
|
|
2666
2689
|
{
|
|
2667
2690
|
className: "relative w-full overflow-hidden rounded border border-border bg-white",
|
|
2668
|
-
style: { height: previewHeight, ...
|
|
2691
|
+
style: { height: previewHeight, ...getReactSlideBackgroundStyle(slide) },
|
|
2669
2692
|
children: /* @__PURE__ */ jsxs(
|
|
2670
2693
|
"div",
|
|
2671
2694
|
{
|
|
@@ -4834,7 +4857,7 @@ function FailedToLoad() {
|
|
|
4834
4857
|
var LazyModel3DScene = React5.lazy(
|
|
4835
4858
|
async () => {
|
|
4836
4859
|
try {
|
|
4837
|
-
return await import('./Model3DScene-
|
|
4860
|
+
return await import('./Model3DScene-JGVLIDLD.mjs');
|
|
4838
4861
|
} catch {
|
|
4839
4862
|
return { default: FailedToLoad };
|
|
4840
4863
|
}
|
|
@@ -5809,7 +5832,7 @@ var ElementRenderer = React5.memo(
|
|
|
5809
5832
|
const cur = effectiveIsInlineEditing ? "cursor-text" : effectiveCanInteract ? elementLocks?.noMove ? "cursor-default" : "cursor-move" : hasAction || isZoom ? "cursor-pointer" : "";
|
|
5810
5833
|
const isPresentationPassive = !effectiveCanInteract;
|
|
5811
5834
|
const isFullscreenMedia = el.type === "media" && Boolean(el.fullScreen) && isPresentationPassive && isMediaPlaying;
|
|
5812
|
-
const ariaRole = getAriaRole(el);
|
|
5835
|
+
const ariaRole = isActionable ? "button" : getAriaRole(el);
|
|
5813
5836
|
const ariaLabel = getAriaLabel(el);
|
|
5814
5837
|
const ariaRoleDescription = getAriaRoleDescription(el);
|
|
5815
5838
|
const isFocusable = effectiveCanInteract || isActionable;
|
|
@@ -5853,6 +5876,10 @@ var ElementRenderer = React5.memo(
|
|
|
5853
5876
|
e.preventDefault();
|
|
5854
5877
|
e.stopPropagation();
|
|
5855
5878
|
onInlineEditCancel();
|
|
5879
|
+
} else if ((e.key === "Enter" || e.key === " ") && isActionable) {
|
|
5880
|
+
e.preventDefault();
|
|
5881
|
+
e.stopPropagation();
|
|
5882
|
+
e.currentTarget.click();
|
|
5856
5883
|
}
|
|
5857
5884
|
},
|
|
5858
5885
|
onClick: (e) => {
|
|
@@ -6445,11 +6472,14 @@ function SlideItemInner({
|
|
|
6445
6472
|
const scale = SLIDE_NAV_THUMBNAIL_WIDTH / safeCanvasWidth;
|
|
6446
6473
|
const previewHeight = Math.max(56, Math.round(safeCanvasHeight * scale));
|
|
6447
6474
|
return /* @__PURE__ */ jsxs(
|
|
6448
|
-
"
|
|
6475
|
+
"button",
|
|
6449
6476
|
{
|
|
6477
|
+
type: "button",
|
|
6450
6478
|
ref: slideRef,
|
|
6479
|
+
"aria-label": `Go to slide ${slideIndex + 1}`,
|
|
6480
|
+
"aria-current": isActive ? "true" : void 0,
|
|
6451
6481
|
className: cn(
|
|
6452
|
-
"group relative flex items-center gap-1 cursor-pointer py-0.5 px-1 transition-all",
|
|
6482
|
+
"group relative flex w-full items-center gap-1 cursor-pointer border-0 bg-transparent py-0.5 px-1 text-left transition-all",
|
|
6453
6483
|
isActive && "bg-accent/40 before:absolute before:left-0 before:top-1 before:bottom-1 before:w-[3px] before:bg-primary before:rounded-r",
|
|
6454
6484
|
isHidden && "opacity-50"
|
|
6455
6485
|
),
|
|
@@ -6892,7 +6922,8 @@ var HANDOUT_SLIDES_PER_PAGE_OPTIONS = [1, 2, 3, 4, 6, 9];
|
|
|
6892
6922
|
function HandoutMasterPanel({
|
|
6893
6923
|
handoutMaster,
|
|
6894
6924
|
slidesPerPage,
|
|
6895
|
-
onSlidesPerPageChange
|
|
6925
|
+
onSlidesPerPageChange,
|
|
6926
|
+
onBackgroundChange
|
|
6896
6927
|
}) {
|
|
6897
6928
|
const { t } = useTranslation();
|
|
6898
6929
|
if (!handoutMaster) {
|
|
@@ -6905,6 +6936,7 @@ function HandoutMasterPanel({
|
|
|
6905
6936
|
"button",
|
|
6906
6937
|
{
|
|
6907
6938
|
type: "button",
|
|
6939
|
+
"aria-pressed": slidesPerPage === count,
|
|
6908
6940
|
className: cn(
|
|
6909
6941
|
"px-2 py-1.5 rounded text-[11px] font-medium transition-colors",
|
|
6910
6942
|
slidesPerPage === count ? "bg-primary text-white" : "bg-accent/50 text-muted-foreground hover:bg-accent/70 hover:text-foreground"
|
|
@@ -6918,12 +6950,13 @@ function HandoutMasterPanel({
|
|
|
6918
6950
|
/* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border/60 bg-muted/40 p-2", children: [
|
|
6919
6951
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("pptx.master.handoutBackground") }),
|
|
6920
6952
|
/* @__PURE__ */ jsx(
|
|
6921
|
-
"
|
|
6953
|
+
"input",
|
|
6922
6954
|
{
|
|
6955
|
+
type: "color",
|
|
6956
|
+
"aria-label": "Master background color",
|
|
6923
6957
|
className: "w-full h-8 rounded border border-border",
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
}
|
|
6958
|
+
value: handoutMaster.backgroundColor ?? "#ffffff",
|
|
6959
|
+
onChange: (event) => onBackgroundChange(event.target.value)
|
|
6927
6960
|
}
|
|
6928
6961
|
)
|
|
6929
6962
|
] }),
|
|
@@ -6943,7 +6976,10 @@ function HandoutMasterPanel({
|
|
|
6943
6976
|
] })
|
|
6944
6977
|
] });
|
|
6945
6978
|
}
|
|
6946
|
-
function NotesMasterPanel({
|
|
6979
|
+
function NotesMasterPanel({
|
|
6980
|
+
notesMaster,
|
|
6981
|
+
onBackgroundChange
|
|
6982
|
+
}) {
|
|
6947
6983
|
const { t } = useTranslation();
|
|
6948
6984
|
const placeholderLabels = useMemo(() => {
|
|
6949
6985
|
if (!notesMaster?.placeholders) {
|
|
@@ -6961,10 +6997,13 @@ function NotesMasterPanel({ notesMaster }) {
|
|
|
6961
6997
|
/* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border/60 bg-muted/40 p-2", children: [
|
|
6962
6998
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("pptx.master.notesMasterBackground") }),
|
|
6963
6999
|
/* @__PURE__ */ jsx(
|
|
6964
|
-
"
|
|
7000
|
+
"input",
|
|
6965
7001
|
{
|
|
7002
|
+
type: "color",
|
|
7003
|
+
"aria-label": "Master background color",
|
|
6966
7004
|
className: "w-full h-8 rounded border border-border",
|
|
6967
|
-
|
|
7005
|
+
value: notesMaster.backgroundColor ?? "#ffffff",
|
|
7006
|
+
onChange: (event) => onBackgroundChange(event.target.value)
|
|
6968
7007
|
}
|
|
6969
7008
|
)
|
|
6970
7009
|
] }),
|
|
@@ -7111,7 +7150,9 @@ function MasterViewSidebar({
|
|
|
7111
7150
|
onSelectLayout,
|
|
7112
7151
|
onCollapse,
|
|
7113
7152
|
onTabChange,
|
|
7114
|
-
onHandoutSlidesPerPageChange
|
|
7153
|
+
onHandoutSlidesPerPageChange,
|
|
7154
|
+
onNotesMasterBackgroundChange,
|
|
7155
|
+
onHandoutMasterBackgroundChange
|
|
7115
7156
|
}) {
|
|
7116
7157
|
const scrollRef = useRef(null);
|
|
7117
7158
|
const { t } = useTranslation();
|
|
@@ -7127,56 +7168,80 @@ function MasterViewSidebar({
|
|
|
7127
7168
|
},
|
|
7128
7169
|
[onSelectLayout]
|
|
7129
7170
|
);
|
|
7130
|
-
return /* @__PURE__ */ jsxs(
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
className: "
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7171
|
+
return /* @__PURE__ */ jsxs(
|
|
7172
|
+
"aside",
|
|
7173
|
+
{
|
|
7174
|
+
"aria-label": t("pptx.view.masterViews"),
|
|
7175
|
+
className: "flex h-full flex-col border-r border-border/80 bg-background/70 backdrop-blur-sm w-56",
|
|
7176
|
+
children: [
|
|
7177
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-3 py-2", children: [
|
|
7178
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs uppercase tracking-wide text-muted-foreground", children: masterViewTab === "slides" ? t("pptx.master.title") : masterViewTab === "notes" ? t("pptx.master.notesMasterTitle") : t("pptx.master.handoutMasterTitle") }),
|
|
7179
|
+
/* @__PURE__ */ jsx(
|
|
7180
|
+
"button",
|
|
7181
|
+
{
|
|
7182
|
+
type: "button",
|
|
7183
|
+
className: "rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
7184
|
+
title: t("pptx.master.collapseMasterPane"),
|
|
7185
|
+
onClick: onCollapse,
|
|
7186
|
+
children: /* @__PURE__ */ jsx(LuPanelLeftClose, { className: "h-3.5 w-3.5" })
|
|
7187
|
+
}
|
|
7188
|
+
)
|
|
7189
|
+
] }),
|
|
7190
|
+
/* @__PURE__ */ jsx(
|
|
7191
|
+
"div",
|
|
7192
|
+
{
|
|
7193
|
+
role: "tablist",
|
|
7194
|
+
"aria-label": t("pptx.mode.masterView"),
|
|
7195
|
+
className: "flex border-b border-border/60 px-1",
|
|
7196
|
+
children: TABS.map((tab) => /* @__PURE__ */ jsx(
|
|
7197
|
+
"button",
|
|
7198
|
+
{
|
|
7199
|
+
type: "button",
|
|
7200
|
+
role: "tab",
|
|
7201
|
+
"aria-selected": masterViewTab === tab.key,
|
|
7202
|
+
className: cn(
|
|
7203
|
+
"flex-1 px-1 py-1.5 text-[10px] font-medium transition-colors border-b-2",
|
|
7204
|
+
masterViewTab === tab.key ? "border-amber-500 text-amber-400" : "border-transparent text-muted-foreground hover:text-foreground"
|
|
7205
|
+
),
|
|
7206
|
+
onClick: () => onTabChange(tab.key),
|
|
7207
|
+
children: t(tab.labelKey)
|
|
7208
|
+
},
|
|
7209
|
+
tab.key
|
|
7210
|
+
))
|
|
7211
|
+
}
|
|
7151
7212
|
),
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7213
|
+
/* @__PURE__ */ jsxs("div", { ref: scrollRef, className: "flex-1 space-y-2 overflow-y-auto px-1.5 pb-2 pt-1", children: [
|
|
7214
|
+
masterViewTab === "slides" && /* @__PURE__ */ jsx(
|
|
7215
|
+
SlideMastersList,
|
|
7216
|
+
{
|
|
7217
|
+
slideMasters,
|
|
7218
|
+
activeMasterIndex,
|
|
7219
|
+
activeLayoutIndex,
|
|
7220
|
+
canvasSize,
|
|
7221
|
+
onSelectMaster: handleMasterClick,
|
|
7222
|
+
onSelectLayout: handleLayoutClick
|
|
7223
|
+
}
|
|
7224
|
+
),
|
|
7225
|
+
masterViewTab === "notes" && /* @__PURE__ */ jsx(
|
|
7226
|
+
NotesMasterPanel,
|
|
7227
|
+
{
|
|
7228
|
+
notesMaster,
|
|
7229
|
+
onBackgroundChange: onNotesMasterBackgroundChange
|
|
7230
|
+
}
|
|
7231
|
+
),
|
|
7232
|
+
masterViewTab === "handout" && /* @__PURE__ */ jsx(
|
|
7233
|
+
HandoutMasterPanel,
|
|
7234
|
+
{
|
|
7235
|
+
handoutMaster,
|
|
7236
|
+
slidesPerPage: handoutSlidesPerPage,
|
|
7237
|
+
onSlidesPerPageChange: onHandoutSlidesPerPageChange,
|
|
7238
|
+
onBackgroundChange: onHandoutMasterBackgroundChange
|
|
7239
|
+
}
|
|
7240
|
+
)
|
|
7241
|
+
] })
|
|
7242
|
+
]
|
|
7243
|
+
}
|
|
7244
|
+
);
|
|
7180
7245
|
}
|
|
7181
7246
|
var DEFAULT_NOTES_WIDTH = 720;
|
|
7182
7247
|
var DEFAULT_NOTES_HEIGHT = 960;
|
|
@@ -7196,6 +7261,12 @@ var DEFAULT_POSITIONS = {
|
|
|
7196
7261
|
dt: { x: 0.6, y: 0, w: 0.4, h: 0.04 },
|
|
7197
7262
|
sldNum: { x: 0.6, y: 0.96, w: 0.4, h: 0.04 }
|
|
7198
7263
|
};
|
|
7264
|
+
function elementText(element) {
|
|
7265
|
+
if ("textSegments" in element && element.textSegments?.length) {
|
|
7266
|
+
return element.textSegments.map((segment) => segment.text).join("");
|
|
7267
|
+
}
|
|
7268
|
+
return "text" in element ? element.text ?? "" : "";
|
|
7269
|
+
}
|
|
7199
7270
|
function NotesMasterCanvas({
|
|
7200
7271
|
notesMaster,
|
|
7201
7272
|
canvasSize,
|
|
@@ -7339,7 +7410,24 @@ function NotesMasterCanvas({
|
|
|
7339
7410
|
},
|
|
7340
7411
|
`${ph.type}-${ph.idx ?? "default"}`
|
|
7341
7412
|
);
|
|
7342
|
-
})
|
|
7413
|
+
}),
|
|
7414
|
+
notesMaster.elements?.map((element) => /* @__PURE__ */ jsx(
|
|
7415
|
+
"div",
|
|
7416
|
+
{
|
|
7417
|
+
"data-pptx-element": "true",
|
|
7418
|
+
"data-element-id": element.id,
|
|
7419
|
+
className: "absolute overflow-hidden",
|
|
7420
|
+
style: {
|
|
7421
|
+
left: element.x * scale,
|
|
7422
|
+
top: element.y * scale,
|
|
7423
|
+
width: element.width * scale,
|
|
7424
|
+
height: element.height * scale,
|
|
7425
|
+
zIndex: 2
|
|
7426
|
+
},
|
|
7427
|
+
children: elementText(element)
|
|
7428
|
+
},
|
|
7429
|
+
element.id
|
|
7430
|
+
))
|
|
7343
7431
|
]
|
|
7344
7432
|
}
|
|
7345
7433
|
) });
|
|
@@ -7347,6 +7435,12 @@ function NotesMasterCanvas({
|
|
|
7347
7435
|
var PAGE_WIDTH = 720;
|
|
7348
7436
|
var PAGE_HEIGHT = 960;
|
|
7349
7437
|
var MARGIN = 0.06;
|
|
7438
|
+
function elementText2(element) {
|
|
7439
|
+
if ("textSegments" in element && element.textSegments?.length) {
|
|
7440
|
+
return element.textSegments.map((segment) => segment.text).join("");
|
|
7441
|
+
}
|
|
7442
|
+
return "text" in element ? element.text ?? "" : "";
|
|
7443
|
+
}
|
|
7350
7444
|
function computeSlotLayout(slidesPerPage, slideAspect) {
|
|
7351
7445
|
const mx = MARGIN;
|
|
7352
7446
|
const my = MARGIN;
|
|
@@ -7498,6 +7592,23 @@ function HandoutMasterCanvas({
|
|
|
7498
7592
|
i
|
|
7499
7593
|
);
|
|
7500
7594
|
}),
|
|
7595
|
+
handoutMaster.elements?.map((element) => /* @__PURE__ */ jsx(
|
|
7596
|
+
"div",
|
|
7597
|
+
{
|
|
7598
|
+
"data-pptx-element": "true",
|
|
7599
|
+
"data-element-id": element.id,
|
|
7600
|
+
className: "absolute overflow-hidden",
|
|
7601
|
+
style: {
|
|
7602
|
+
left: element.x * scale,
|
|
7603
|
+
top: element.y * scale,
|
|
7604
|
+
width: element.width * scale,
|
|
7605
|
+
height: element.height * scale,
|
|
7606
|
+
zIndex: 2
|
|
7607
|
+
},
|
|
7608
|
+
children: elementText2(element)
|
|
7609
|
+
},
|
|
7610
|
+
element.id
|
|
7611
|
+
)),
|
|
7501
7612
|
/* @__PURE__ */ jsx(
|
|
7502
7613
|
"div",
|
|
7503
7614
|
{
|
|
@@ -9938,6 +10049,18 @@ function ComparePanel({
|
|
|
9938
10049
|
)) })
|
|
9939
10050
|
] });
|
|
9940
10051
|
}
|
|
10052
|
+
function useModalFocus(open, panelRef, onClose, initialFocusRef) {
|
|
10053
|
+
useEffect(() => {
|
|
10054
|
+
const panel = panelRef.current;
|
|
10055
|
+
if (!open || !panel) {
|
|
10056
|
+
return;
|
|
10057
|
+
}
|
|
10058
|
+
return activateModalFocus(panel, {
|
|
10059
|
+
initialFocus: initialFocusRef?.current,
|
|
10060
|
+
onEscape: onClose
|
|
10061
|
+
});
|
|
10062
|
+
}, [initialFocusRef, onClose, open, panelRef]);
|
|
10063
|
+
}
|
|
9941
10064
|
function getPasswordStrength(password) {
|
|
9942
10065
|
if (!password) {
|
|
9943
10066
|
return 0;
|
|
@@ -9979,6 +10102,8 @@ function PasswordProtectionDialog({
|
|
|
9979
10102
|
const [confirmPassword, setConfirmPassword] = useState("");
|
|
9980
10103
|
const [showPassword, setShowPassword] = useState(false);
|
|
9981
10104
|
const [error, setError] = useState("");
|
|
10105
|
+
const dialogRef = useRef(null);
|
|
10106
|
+
const passwordRef = useRef(null);
|
|
9982
10107
|
const strength = useMemo(() => getPasswordStrength(password), [password]);
|
|
9983
10108
|
const strengthLabel = useMemo(() => {
|
|
9984
10109
|
const labels = [
|
|
@@ -10021,6 +10146,7 @@ function PasswordProtectionDialog({
|
|
|
10021
10146
|
setError("");
|
|
10022
10147
|
onClose();
|
|
10023
10148
|
}, [onClose]);
|
|
10149
|
+
useModalFocus(isOpen, dialogRef, handleClose, passwordRef);
|
|
10024
10150
|
if (!isOpen) {
|
|
10025
10151
|
return null;
|
|
10026
10152
|
}
|
|
@@ -10040,117 +10166,148 @@ function PasswordProtectionDialog({
|
|
|
10040
10166
|
{
|
|
10041
10167
|
style: { zIndex: 1201 },
|
|
10042
10168
|
className: "fixed inset-0 flex items-center justify-center pointer-events-none",
|
|
10043
|
-
children: /* @__PURE__ */ jsxs(
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
className: "
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
)
|
|
10059
|
-
] }),
|
|
10060
|
-
/* @__PURE__ */ jsxs("div", { className: "px-5 py-4 space-y-4", children: [
|
|
10061
|
-
isCurrentlyProtected && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg bg-green-900/30 border border-green-700/40 px-3 py-2", children: [
|
|
10062
|
-
/* @__PURE__ */ jsx(LuShieldCheck, { className: "w-4 h-4 text-green-400 shrink-0" }),
|
|
10063
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-green-300", children: t("pptx.security.currentlyProtected") })
|
|
10064
|
-
] }),
|
|
10065
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("pptx.security.description") }),
|
|
10066
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
10067
|
-
/* @__PURE__ */ jsx("label", { className: "block text-xs text-foreground mb-1", children: t("pptx.security.password") }),
|
|
10068
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
10169
|
+
children: /* @__PURE__ */ jsxs(
|
|
10170
|
+
"div",
|
|
10171
|
+
{
|
|
10172
|
+
ref: dialogRef,
|
|
10173
|
+
role: "dialog",
|
|
10174
|
+
"aria-modal": "true",
|
|
10175
|
+
"aria-labelledby": "pptx-password-title",
|
|
10176
|
+
tabIndex: -1,
|
|
10177
|
+
className: "pointer-events-auto w-[420px] overscroll-contain 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)]",
|
|
10178
|
+
children: [
|
|
10179
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/60", children: [
|
|
10180
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
10181
|
+
/* @__PURE__ */ jsx(LuLock, { className: "w-5 h-5 text-primary", "aria-hidden": "true" }),
|
|
10182
|
+
/* @__PURE__ */ jsx("h2", { id: "pptx-password-title", className: "text-sm font-semibold text-foreground", children: t("pptx.security.protectPresentation") })
|
|
10183
|
+
] }),
|
|
10069
10184
|
/* @__PURE__ */ jsx(
|
|
10070
|
-
"
|
|
10185
|
+
"button",
|
|
10071
10186
|
{
|
|
10072
|
-
type:
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10077
|
-
setPassword(e.target.value);
|
|
10078
|
-
setError("");
|
|
10079
|
-
}
|
|
10187
|
+
type: "button",
|
|
10188
|
+
onClick: handleClose,
|
|
10189
|
+
className: "p-1 rounded hover:bg-accent transition-colors",
|
|
10190
|
+
"aria-label": t("common.close"),
|
|
10191
|
+
children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4 text-muted-foreground", "aria-hidden": "true" })
|
|
10080
10192
|
}
|
|
10081
|
-
)
|
|
10082
|
-
|
|
10193
|
+
)
|
|
10194
|
+
] }),
|
|
10195
|
+
/* @__PURE__ */ jsxs("div", { className: "px-5 py-4 space-y-4", children: [
|
|
10196
|
+
isCurrentlyProtected && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg bg-green-900/30 border border-green-700/40 px-3 py-2", children: [
|
|
10197
|
+
/* @__PURE__ */ jsx(LuShieldCheck, { className: "w-4 h-4 text-green-400 shrink-0", "aria-hidden": "true" }),
|
|
10198
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-green-300", children: t("pptx.security.currentlyProtected") })
|
|
10199
|
+
] }),
|
|
10200
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("pptx.security.description") }),
|
|
10201
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10202
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pptx-password", className: "block text-xs text-foreground mb-1", children: t("pptx.security.password") }),
|
|
10203
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
10204
|
+
/* @__PURE__ */ jsx(
|
|
10205
|
+
"input",
|
|
10206
|
+
{
|
|
10207
|
+
ref: passwordRef,
|
|
10208
|
+
id: "pptx-password",
|
|
10209
|
+
name: "presentation-password",
|
|
10210
|
+
autoComplete: "new-password",
|
|
10211
|
+
"aria-invalid": Boolean(error),
|
|
10212
|
+
"aria-describedby": error ? "pptx-password-error" : "pptx-password-strength",
|
|
10213
|
+
type: showPassword ? "text" : "password",
|
|
10214
|
+
className: "w-full rounded-lg border border-border bg-muted px-3 py-2 text-sm text-foreground placeholder-muted-foreground focus:border-primary focus:ring-1 focus:ring-primary outline-none",
|
|
10215
|
+
placeholder: t("pptx.security.passwordPlaceholder"),
|
|
10216
|
+
value: password,
|
|
10217
|
+
onChange: (e) => {
|
|
10218
|
+
setPassword(e.target.value);
|
|
10219
|
+
setError("");
|
|
10220
|
+
}
|
|
10221
|
+
}
|
|
10222
|
+
),
|
|
10223
|
+
/* @__PURE__ */ jsx(
|
|
10224
|
+
"button",
|
|
10225
|
+
{
|
|
10226
|
+
type: "button",
|
|
10227
|
+
onClick: () => setShowPassword(!showPassword),
|
|
10228
|
+
className: "absolute right-2 top-1/2 -translate-y-1/2 p-1 text-muted-foreground hover:text-foreground",
|
|
10229
|
+
"aria-label": showPassword ? t("pptx.security.hidePassword") : t("pptx.security.showPassword"),
|
|
10230
|
+
children: showPassword ? /* @__PURE__ */ jsx(LuEyeOff, { className: "w-4 h-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(LuEye, { className: "w-4 h-4", "aria-hidden": "true" })
|
|
10231
|
+
}
|
|
10232
|
+
)
|
|
10233
|
+
] })
|
|
10234
|
+
] }),
|
|
10235
|
+
password && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
10236
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-1", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx(
|
|
10237
|
+
"div",
|
|
10238
|
+
{
|
|
10239
|
+
className: `h-1 flex-1 rounded-full transition-colors ${i <= strength ? STRENGTH_COLORS[strength] : "bg-accent"}`
|
|
10240
|
+
},
|
|
10241
|
+
`str-${i}`
|
|
10242
|
+
)) }),
|
|
10243
|
+
/* @__PURE__ */ jsx(
|
|
10244
|
+
"p",
|
|
10245
|
+
{
|
|
10246
|
+
id: "pptx-password-strength",
|
|
10247
|
+
className: "text-[11px] text-muted-foreground",
|
|
10248
|
+
role: "status",
|
|
10249
|
+
"aria-live": "polite",
|
|
10250
|
+
children: strengthLabel
|
|
10251
|
+
}
|
|
10252
|
+
)
|
|
10253
|
+
] }),
|
|
10254
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10255
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "pptx-password-confirm", className: "block text-xs text-foreground mb-1", children: t("pptx.security.confirmPassword") }),
|
|
10256
|
+
/* @__PURE__ */ jsx(
|
|
10257
|
+
"input",
|
|
10258
|
+
{
|
|
10259
|
+
id: "pptx-password-confirm",
|
|
10260
|
+
name: "presentation-password-confirmation",
|
|
10261
|
+
autoComplete: "new-password",
|
|
10262
|
+
"aria-invalid": Boolean(error),
|
|
10263
|
+
"aria-describedby": error ? "pptx-password-error" : void 0,
|
|
10264
|
+
type: showPassword ? "text" : "password",
|
|
10265
|
+
className: "w-full rounded-lg border border-border bg-muted px-3 py-2 text-sm text-foreground placeholder-muted-foreground focus:border-primary focus:ring-1 focus:ring-primary outline-none",
|
|
10266
|
+
placeholder: t("pptx.security.confirmPasswordPlaceholder"),
|
|
10267
|
+
value: confirmPassword,
|
|
10268
|
+
onChange: (e) => {
|
|
10269
|
+
setConfirmPassword(e.target.value);
|
|
10270
|
+
setError("");
|
|
10271
|
+
}
|
|
10272
|
+
}
|
|
10273
|
+
)
|
|
10274
|
+
] }),
|
|
10275
|
+
error && /* @__PURE__ */ jsx("p", { id: "pptx-password-error", className: "text-xs text-red-400", role: "alert", children: error })
|
|
10276
|
+
] }),
|
|
10277
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3 border-t border-border/60", children: [
|
|
10278
|
+
/* @__PURE__ */ jsx("div", { children: isCurrentlyProtected && /* @__PURE__ */ jsx(
|
|
10083
10279
|
"button",
|
|
10084
10280
|
{
|
|
10085
10281
|
type: "button",
|
|
10086
|
-
onClick:
|
|
10087
|
-
className: "
|
|
10088
|
-
|
|
10089
|
-
children: showPassword ? /* @__PURE__ */ jsx(LuEyeOff, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(LuEye, { className: "w-4 h-4" })
|
|
10282
|
+
onClick: handleRemove,
|
|
10283
|
+
className: "text-xs text-red-400 hover:text-red-300 transition-colors",
|
|
10284
|
+
children: t("pptx.security.removePassword")
|
|
10090
10285
|
}
|
|
10091
|
-
)
|
|
10286
|
+
) }),
|
|
10287
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
10288
|
+
/* @__PURE__ */ jsx(
|
|
10289
|
+
"button",
|
|
10290
|
+
{
|
|
10291
|
+
type: "button",
|
|
10292
|
+
onClick: handleClose,
|
|
10293
|
+
className: "px-3 py-1.5 text-xs rounded-lg border border-border text-foreground hover:bg-muted transition-colors",
|
|
10294
|
+
children: t("common.cancel")
|
|
10295
|
+
}
|
|
10296
|
+
),
|
|
10297
|
+
/* @__PURE__ */ jsx(
|
|
10298
|
+
"button",
|
|
10299
|
+
{
|
|
10300
|
+
type: "button",
|
|
10301
|
+
onClick: handleSubmit,
|
|
10302
|
+
className: "px-3 py-1.5 text-xs rounded-lg bg-primary text-white hover:bg-primary/80 transition-colors",
|
|
10303
|
+
children: isCurrentlyProtected ? t("pptx.security.updatePassword") : t("pptx.security.setPassword")
|
|
10304
|
+
}
|
|
10305
|
+
)
|
|
10306
|
+
] })
|
|
10092
10307
|
] })
|
|
10093
|
-
]
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
"div",
|
|
10097
|
-
{
|
|
10098
|
-
className: `h-1 flex-1 rounded-full transition-colors ${i <= strength ? STRENGTH_COLORS[strength] : "bg-accent"}`
|
|
10099
|
-
},
|
|
10100
|
-
`str-${i}`
|
|
10101
|
-
)) }),
|
|
10102
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: strengthLabel })
|
|
10103
|
-
] }),
|
|
10104
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
10105
|
-
/* @__PURE__ */ jsx("label", { className: "block text-xs text-foreground mb-1", children: t("pptx.security.confirmPassword") }),
|
|
10106
|
-
/* @__PURE__ */ jsx(
|
|
10107
|
-
"input",
|
|
10108
|
-
{
|
|
10109
|
-
type: showPassword ? "text" : "password",
|
|
10110
|
-
className: "w-full rounded-lg border border-border bg-muted px-3 py-2 text-sm text-foreground placeholder-muted-foreground focus:border-primary focus:ring-1 focus:ring-primary outline-none",
|
|
10111
|
-
placeholder: t("pptx.security.confirmPasswordPlaceholder"),
|
|
10112
|
-
value: confirmPassword,
|
|
10113
|
-
onChange: (e) => {
|
|
10114
|
-
setConfirmPassword(e.target.value);
|
|
10115
|
-
setError("");
|
|
10116
|
-
}
|
|
10117
|
-
}
|
|
10118
|
-
)
|
|
10119
|
-
] }),
|
|
10120
|
-
error && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-400", children: error })
|
|
10121
|
-
] }),
|
|
10122
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3 border-t border-border/60", children: [
|
|
10123
|
-
/* @__PURE__ */ jsx("div", { children: isCurrentlyProtected && /* @__PURE__ */ jsx(
|
|
10124
|
-
"button",
|
|
10125
|
-
{
|
|
10126
|
-
type: "button",
|
|
10127
|
-
onClick: handleRemove,
|
|
10128
|
-
className: "text-xs text-red-400 hover:text-red-300 transition-colors",
|
|
10129
|
-
children: t("pptx.security.removePassword")
|
|
10130
|
-
}
|
|
10131
|
-
) }),
|
|
10132
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
10133
|
-
/* @__PURE__ */ jsx(
|
|
10134
|
-
"button",
|
|
10135
|
-
{
|
|
10136
|
-
type: "button",
|
|
10137
|
-
onClick: handleClose,
|
|
10138
|
-
className: "px-3 py-1.5 text-xs rounded-lg border border-border text-foreground hover:bg-muted transition-colors",
|
|
10139
|
-
children: t("common.cancel")
|
|
10140
|
-
}
|
|
10141
|
-
),
|
|
10142
|
-
/* @__PURE__ */ jsx(
|
|
10143
|
-
"button",
|
|
10144
|
-
{
|
|
10145
|
-
type: "button",
|
|
10146
|
-
onClick: handleSubmit,
|
|
10147
|
-
className: "px-3 py-1.5 text-xs rounded-lg bg-primary text-white hover:bg-primary/80 transition-colors",
|
|
10148
|
-
children: isCurrentlyProtected ? t("pptx.security.updatePassword") : t("pptx.security.setPassword")
|
|
10149
|
-
}
|
|
10150
|
-
)
|
|
10151
|
-
] })
|
|
10152
|
-
] })
|
|
10153
|
-
] })
|
|
10308
|
+
]
|
|
10309
|
+
}
|
|
10310
|
+
)
|
|
10154
10311
|
}
|
|
10155
10312
|
)
|
|
10156
10313
|
] });
|
|
@@ -10982,17 +11139,224 @@ function EncryptedFileDialog({
|
|
|
10982
11139
|
)
|
|
10983
11140
|
] });
|
|
10984
11141
|
}
|
|
10985
|
-
function
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
11142
|
+
function PresentationAudienceEffects({ snapshot }) {
|
|
11143
|
+
const strokes = snapshot.inkStrokes?.filter((stroke) => stroke.slideIndex === snapshot.slideIndex) ?? [];
|
|
11144
|
+
return /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute inset-0 z-[75] overflow-hidden", children: [
|
|
11145
|
+
snapshot.blackout !== "none" && /* @__PURE__ */ jsx(
|
|
11146
|
+
"div",
|
|
11147
|
+
{
|
|
11148
|
+
className: `absolute inset-0 ${snapshot.blackout === "black" ? "bg-black" : "bg-white"}`
|
|
11149
|
+
}
|
|
11150
|
+
),
|
|
11151
|
+
/* @__PURE__ */ jsx(
|
|
11152
|
+
"svg",
|
|
11153
|
+
{
|
|
11154
|
+
className: "absolute inset-0 h-full w-full",
|
|
11155
|
+
viewBox: "0 0 100 100",
|
|
11156
|
+
preserveAspectRatio: "none",
|
|
11157
|
+
"aria-hidden": "true",
|
|
11158
|
+
children: strokes.map((stroke) => /* @__PURE__ */ jsx(
|
|
11159
|
+
"path",
|
|
11160
|
+
{
|
|
11161
|
+
d: presentationInkPath(stroke.points),
|
|
11162
|
+
fill: "none",
|
|
11163
|
+
stroke: stroke.color,
|
|
11164
|
+
strokeWidth: stroke.width / 10,
|
|
11165
|
+
strokeLinecap: "round",
|
|
11166
|
+
strokeLinejoin: "round",
|
|
11167
|
+
opacity: stroke.tool === "highlighter" ? 0.42 : 1
|
|
11168
|
+
},
|
|
11169
|
+
stroke.id
|
|
11170
|
+
))
|
|
11171
|
+
}
|
|
11172
|
+
),
|
|
11173
|
+
snapshot.pointer?.tool === "laser" && /* @__PURE__ */ jsx(
|
|
10991
11174
|
"span",
|
|
10992
|
-
{
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
11175
|
+
{
|
|
11176
|
+
className: "absolute h-5 w-5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-red-500 shadow-[0_0_20px_8px_rgba(239,68,68,.55)]",
|
|
11177
|
+
style: { left: `${snapshot.pointer.x * 100}%`, top: `${snapshot.pointer.y * 100}%` }
|
|
11178
|
+
}
|
|
11179
|
+
),
|
|
11180
|
+
snapshot.subtitlesVisible && snapshot.caption && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-[10%] bottom-8 rounded-lg bg-black/80 px-6 py-3 text-center text-xl font-medium text-white", children: snapshot.caption })
|
|
11181
|
+
] });
|
|
11182
|
+
}
|
|
11183
|
+
function PresentationSubtitleBar({
|
|
11184
|
+
visible,
|
|
11185
|
+
onCaptionChange
|
|
11186
|
+
}) {
|
|
11187
|
+
const { t } = useTranslation();
|
|
11188
|
+
const [captionText, setCaptionText] = useState("");
|
|
11189
|
+
const [supportState, setSupportState] = useState(
|
|
11190
|
+
"unknown"
|
|
11191
|
+
);
|
|
11192
|
+
const recognitionRef = useRef(null);
|
|
11193
|
+
const shouldRunRef = useRef(false);
|
|
11194
|
+
useEffect(() => {
|
|
11195
|
+
if (!visible) {
|
|
11196
|
+
shouldRunRef.current = false;
|
|
11197
|
+
recognitionRef.current?.stop();
|
|
11198
|
+
recognitionRef.current = null;
|
|
11199
|
+
setCaptionText("");
|
|
11200
|
+
return;
|
|
11201
|
+
}
|
|
11202
|
+
shouldRunRef.current = true;
|
|
11203
|
+
const speechWindow = window;
|
|
11204
|
+
const RecognitionCtor = speechWindow.SpeechRecognition ?? speechWindow.webkitSpeechRecognition;
|
|
11205
|
+
if (!RecognitionCtor) {
|
|
11206
|
+
setSupportState("unsupported");
|
|
11207
|
+
return;
|
|
11208
|
+
}
|
|
11209
|
+
setSupportState("supported");
|
|
11210
|
+
const recognition = new RecognitionCtor();
|
|
11211
|
+
recognition.continuous = true;
|
|
11212
|
+
recognition.interimResults = true;
|
|
11213
|
+
recognition.lang = navigator.language || "en-US";
|
|
11214
|
+
recognition.onresult = (event) => {
|
|
11215
|
+
let finalText = "";
|
|
11216
|
+
let interimText = "";
|
|
11217
|
+
for (let index = event.resultIndex; index < event.results.length; index += 1) {
|
|
11218
|
+
const result = event.results[index];
|
|
11219
|
+
const fragment = result?.[0]?.transcript ?? "";
|
|
11220
|
+
if (result?.isFinal) {
|
|
11221
|
+
finalText += fragment;
|
|
11222
|
+
} else {
|
|
11223
|
+
interimText += fragment;
|
|
11224
|
+
}
|
|
11225
|
+
}
|
|
11226
|
+
const merged = `${finalText} ${interimText}`.trim();
|
|
11227
|
+
if (merged.length > 0) {
|
|
11228
|
+
setCaptionText(merged);
|
|
11229
|
+
onCaptionChange?.(merged);
|
|
11230
|
+
}
|
|
11231
|
+
};
|
|
11232
|
+
recognition.onerror = () => {
|
|
11233
|
+
};
|
|
11234
|
+
recognition.onend = () => {
|
|
11235
|
+
if (!shouldRunRef.current) {
|
|
11236
|
+
return;
|
|
11237
|
+
}
|
|
11238
|
+
try {
|
|
11239
|
+
recognition.start();
|
|
11240
|
+
} catch {
|
|
11241
|
+
}
|
|
11242
|
+
};
|
|
11243
|
+
recognitionRef.current = recognition;
|
|
11244
|
+
try {
|
|
11245
|
+
recognition.start();
|
|
11246
|
+
} catch {
|
|
11247
|
+
setSupportState("unsupported");
|
|
11248
|
+
}
|
|
11249
|
+
return () => {
|
|
11250
|
+
shouldRunRef.current = false;
|
|
11251
|
+
recognition.stop();
|
|
11252
|
+
recognitionRef.current = null;
|
|
11253
|
+
};
|
|
11254
|
+
}, [visible, onCaptionChange]);
|
|
11255
|
+
if (!visible) {
|
|
11256
|
+
return null;
|
|
11257
|
+
}
|
|
11258
|
+
const renderedText = supportState === "unsupported" ? t("pptx.subtitles.notSupported") : captionText.length > 0 ? captionText : t("pptx.subtitles.listening");
|
|
11259
|
+
return /* @__PURE__ */ jsx("div", { className: "absolute bottom-14 left-1/2 -translate-x-1/2 z-[70] max-w-[80%] min-w-[300px]", children: /* @__PURE__ */ jsx("div", { className: "px-6 py-3 rounded-lg bg-black/75 backdrop-blur-sm border border-white/10", children: /* @__PURE__ */ jsx("p", { className: "text-center text-[15px] text-white/70 italic", children: renderedText }) }) });
|
|
11260
|
+
}
|
|
11261
|
+
function renderNotesSegments(segments) {
|
|
11262
|
+
return notesSegmentsToSpans(segments).map((span) => {
|
|
11263
|
+
if (span.kind === "break") {
|
|
11264
|
+
return React5.createElement("br", { key: span.key });
|
|
11265
|
+
}
|
|
11266
|
+
return React5.createElement(
|
|
11267
|
+
"span",
|
|
11268
|
+
{ key: span.key, style: span.style },
|
|
11269
|
+
span.text
|
|
11270
|
+
);
|
|
11271
|
+
});
|
|
11272
|
+
}
|
|
11273
|
+
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-sky-500 text-slate-950" : "bg-white/7 text-slate-200 hover:bg-white/14"}`;
|
|
11274
|
+
function PresenterConsoleToolbar(props) {
|
|
11275
|
+
const pointerTool = props.snapshot.pointer?.tool ?? "none";
|
|
11276
|
+
const zoom = props.snapshot.zoom?.scale ?? 1;
|
|
11277
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 border-b border-white/10 bg-slate-950 px-3 py-2", children: [
|
|
11278
|
+
/* @__PURE__ */ jsx(
|
|
11279
|
+
"button",
|
|
11280
|
+
{
|
|
11281
|
+
className: toolClass(false),
|
|
11282
|
+
onClick: props.onToggleTimer,
|
|
11283
|
+
title: "Pause or resume timer",
|
|
11284
|
+
children: props.snapshot.paused ? /* @__PURE__ */ jsx(LuCirclePlay, {}) : /* @__PURE__ */ jsx(LuCirclePause, {})
|
|
11285
|
+
}
|
|
11286
|
+
),
|
|
11287
|
+
/* @__PURE__ */ jsx("button", { className: toolClass(false), onClick: props.onResetTimer, title: "Reset timer", children: /* @__PURE__ */ jsx(LuRotateCcw, {}) }),
|
|
11288
|
+
/* @__PURE__ */ jsx("span", { className: "mx-1 h-6 w-px bg-white/15" }),
|
|
11289
|
+
/* @__PURE__ */ jsxs("button", { className: toolClass(false), onClick: props.onShowSlides, title: "See all slides", children: [
|
|
11290
|
+
/* @__PURE__ */ jsx(LuGrid2X2, {}),
|
|
11291
|
+
" Slides"
|
|
11292
|
+
] }),
|
|
11293
|
+
/* @__PURE__ */ jsx("button", { className: toolClass(zoom > 1), onClick: () => props.onStepZoom(1), title: "Zoom in", children: /* @__PURE__ */ jsx(LuZoomIn, {}) }),
|
|
11294
|
+
/* @__PURE__ */ jsx("button", { className: toolClass(false), onClick: () => props.onStepZoom(-1), title: "Zoom out", children: /* @__PURE__ */ jsx(LuZoomOut, {}) }),
|
|
11295
|
+
/* @__PURE__ */ jsx("button", { className: toolClass(false), onClick: props.onResetZoom, title: "Reset zoom", children: /* @__PURE__ */ jsx(LuScan, {}) }),
|
|
11296
|
+
/* @__PURE__ */ jsx("span", { className: "mx-1 h-6 w-px bg-white/15" }),
|
|
11297
|
+
["laser", "pen", "highlighter", "eraser"].map((tool) => /* @__PURE__ */ jsx(
|
|
11298
|
+
"button",
|
|
11299
|
+
{
|
|
11300
|
+
className: toolClass(pointerTool === tool),
|
|
11301
|
+
onClick: () => props.onPointerTool(pointerTool === tool ? "none" : tool),
|
|
11302
|
+
title: tool[0].toUpperCase() + tool.slice(1),
|
|
11303
|
+
children: tool === "laser" ? /* @__PURE__ */ jsx(LuMousePointer2, {}) : tool === "pen" ? /* @__PURE__ */ jsx(LuPenTool, {}) : tool === "highlighter" ? /* @__PURE__ */ jsx(LuHighlighter, {}) : /* @__PURE__ */ jsx(LuEraser, {})
|
|
11304
|
+
},
|
|
11305
|
+
tool
|
|
11306
|
+
)),
|
|
11307
|
+
/* @__PURE__ */ jsx("span", { className: "mx-1 h-6 w-px bg-white/15" }),
|
|
11308
|
+
/* @__PURE__ */ jsx(
|
|
11309
|
+
"button",
|
|
11310
|
+
{
|
|
11311
|
+
className: toolClass(props.snapshot.blackout === "black"),
|
|
11312
|
+
onClick: () => props.onBlackout(props.snapshot.blackout === "black" ? "none" : "black"),
|
|
11313
|
+
title: "Black screen",
|
|
11314
|
+
children: "B"
|
|
11315
|
+
}
|
|
11316
|
+
),
|
|
11317
|
+
/* @__PURE__ */ jsx(
|
|
11318
|
+
"button",
|
|
11319
|
+
{
|
|
11320
|
+
className: toolClass(props.snapshot.blackout === "white"),
|
|
11321
|
+
onClick: () => props.onBlackout(props.snapshot.blackout === "white" ? "none" : "white"),
|
|
11322
|
+
title: "White screen",
|
|
11323
|
+
children: "W"
|
|
11324
|
+
}
|
|
11325
|
+
),
|
|
11326
|
+
/* @__PURE__ */ jsx(
|
|
11327
|
+
"button",
|
|
11328
|
+
{
|
|
11329
|
+
className: toolClass(Boolean(props.snapshot.subtitlesVisible)),
|
|
11330
|
+
onClick: props.onToggleSubtitles,
|
|
11331
|
+
title: "Toggle subtitles",
|
|
11332
|
+
children: /* @__PURE__ */ jsx(LuCaptions, {})
|
|
11333
|
+
}
|
|
11334
|
+
),
|
|
11335
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
11336
|
+
/* @__PURE__ */ jsx(
|
|
11337
|
+
"button",
|
|
11338
|
+
{
|
|
11339
|
+
className: toolClass(props.audienceOpen),
|
|
11340
|
+
onClick: props.onToggleAudience,
|
|
11341
|
+
title: "Audience display",
|
|
11342
|
+
children: props.audienceOpen ? /* @__PURE__ */ jsx(LuMonitorOff, {}) : /* @__PURE__ */ jsx(LuMonitor, {})
|
|
11343
|
+
}
|
|
11344
|
+
),
|
|
11345
|
+
/* @__PURE__ */ jsx(
|
|
11346
|
+
"button",
|
|
11347
|
+
{
|
|
11348
|
+
className: toolClass(false),
|
|
11349
|
+
onClick: props.onSwapDisplays,
|
|
11350
|
+
disabled: !props.audienceOpen,
|
|
11351
|
+
title: "Swap displays",
|
|
11352
|
+
children: "Swap"
|
|
11353
|
+
}
|
|
11354
|
+
),
|
|
11355
|
+
/* @__PURE__ */ jsxs("button", { className: toolClass(false), onClick: props.onExit, title: "End slide show", children: [
|
|
11356
|
+
/* @__PURE__ */ jsx(LuX, {}),
|
|
11357
|
+
" End"
|
|
11358
|
+
] })
|
|
11359
|
+
] });
|
|
10996
11360
|
}
|
|
10997
11361
|
function ScaledSlidePreviewImpl({
|
|
10998
11362
|
slide,
|
|
@@ -11284,6 +11648,250 @@ function arePropsEqual4(prev, next) {
|
|
|
11284
11648
|
return true;
|
|
11285
11649
|
}
|
|
11286
11650
|
var ScaledSlidePreview = React5.memo(ScaledSlidePreviewImpl, arePropsEqual4);
|
|
11651
|
+
function PresenterNotesRail({
|
|
11652
|
+
slides,
|
|
11653
|
+
current,
|
|
11654
|
+
canvasSize,
|
|
11655
|
+
templateElements,
|
|
11656
|
+
now,
|
|
11657
|
+
elapsed,
|
|
11658
|
+
onMove,
|
|
11659
|
+
onUpdateNotes
|
|
11660
|
+
}) {
|
|
11661
|
+
const { t } = useTranslation();
|
|
11662
|
+
const slide = slides[current];
|
|
11663
|
+
const nextSlide = slides.slice(current + 1).find((candidate) => !candidate.hidden);
|
|
11664
|
+
const notesText = slide?.notes ?? "";
|
|
11665
|
+
const notesSegments = slide?.notesSegments;
|
|
11666
|
+
const [notesDraft, setNotesDraft] = useState(notesText);
|
|
11667
|
+
const [fontSize, setFontSize] = useState(NOTES_FONT_SIZE_DEFAULT);
|
|
11668
|
+
useEffect(() => setNotesDraft(notesText), [current, notesText]);
|
|
11669
|
+
const notes = useMemo(
|
|
11670
|
+
() => notesSegments?.length ? renderNotesSegments(notesSegments) : notesText.trim() ? notesText : /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: t("pptx.presenter.noNotes") }),
|
|
11671
|
+
[notesSegments, notesText, t]
|
|
11672
|
+
);
|
|
11673
|
+
return /* @__PURE__ */ jsxs("aside", { className: "flex flex-[3] min-w-[260px] max-w-[440px] flex-col border-l border-border bg-background", children: [
|
|
11674
|
+
/* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between border-b border-border/60 px-4 py-3", children: [
|
|
11675
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
11676
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.currentTime") }),
|
|
11677
|
+
/* @__PURE__ */ jsx("div", { className: "font-mono text-lg tabular-nums", children: formatTime(new Date(now)) })
|
|
11678
|
+
] }),
|
|
11679
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
11680
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.elapsed") }),
|
|
11681
|
+
/* @__PURE__ */ jsx("div", { className: "font-mono text-lg tabular-nums text-primary", children: formatElapsed(elapsed) })
|
|
11682
|
+
] })
|
|
11683
|
+
] }),
|
|
11684
|
+
/* @__PURE__ */ jsxs("nav", { className: "flex items-center justify-between border-b border-border/60 px-4 py-2", children: [
|
|
11685
|
+
/* @__PURE__ */ jsxs(
|
|
11686
|
+
"button",
|
|
11687
|
+
{
|
|
11688
|
+
type: "button",
|
|
11689
|
+
onClick: () => onMove(-1),
|
|
11690
|
+
disabled: current === 0,
|
|
11691
|
+
className: "inline-flex items-center gap-1 rounded bg-muted px-3 py-1.5 text-xs disabled:opacity-40",
|
|
11692
|
+
children: [
|
|
11693
|
+
/* @__PURE__ */ jsx(LuChevronLeft, {}),
|
|
11694
|
+
" ",
|
|
11695
|
+
t("pptx.presenter.prev")
|
|
11696
|
+
]
|
|
11697
|
+
}
|
|
11698
|
+
),
|
|
11699
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono text-sm tabular-nums", children: [
|
|
11700
|
+
current + 1,
|
|
11701
|
+
" / ",
|
|
11702
|
+
slides.length
|
|
11703
|
+
] }),
|
|
11704
|
+
/* @__PURE__ */ jsxs(
|
|
11705
|
+
"button",
|
|
11706
|
+
{
|
|
11707
|
+
type: "button",
|
|
11708
|
+
onClick: () => onMove(1),
|
|
11709
|
+
disabled: current >= slides.length - 1,
|
|
11710
|
+
className: "inline-flex items-center gap-1 rounded bg-muted px-3 py-1.5 text-xs disabled:opacity-40",
|
|
11711
|
+
children: [
|
|
11712
|
+
t("pptx.presenter.next"),
|
|
11713
|
+
" ",
|
|
11714
|
+
/* @__PURE__ */ jsx(LuChevronRight, {})
|
|
11715
|
+
]
|
|
11716
|
+
}
|
|
11717
|
+
)
|
|
11718
|
+
] }),
|
|
11719
|
+
/* @__PURE__ */ jsxs("section", { className: "border-b border-border/60 px-4 py-3", children: [
|
|
11720
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2 text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.nextSlidePreview") }),
|
|
11721
|
+
nextSlide ? /* @__PURE__ */ jsx(
|
|
11722
|
+
ScaledSlidePreview,
|
|
11723
|
+
{
|
|
11724
|
+
slide: nextSlide,
|
|
11725
|
+
templateElements,
|
|
11726
|
+
canvasSize
|
|
11727
|
+
}
|
|
11728
|
+
) : /* @__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") })
|
|
11729
|
+
] }),
|
|
11730
|
+
/* @__PURE__ */ jsxs("section", { className: "flex min-h-0 flex-1 flex-col px-4 py-3", children: [
|
|
11731
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
|
|
11732
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground", children: t("pptx.presenter.speakerNotes") }),
|
|
11733
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
11734
|
+
/* @__PURE__ */ jsx(
|
|
11735
|
+
"button",
|
|
11736
|
+
{
|
|
11737
|
+
type: "button",
|
|
11738
|
+
onClick: () => setFontSize(clampNotesFontSize(fontSize - NOTES_FONT_SIZE_STEP)),
|
|
11739
|
+
disabled: fontSize <= NOTES_FONT_SIZE_MIN,
|
|
11740
|
+
"aria-label": t("pptx.presenter.decreaseFontSize"),
|
|
11741
|
+
children: /* @__PURE__ */ jsx(LuMinus, {})
|
|
11742
|
+
}
|
|
11743
|
+
),
|
|
11744
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-8 text-center font-mono text-[10px]", children: [
|
|
11745
|
+
fontSize,
|
|
11746
|
+
"px"
|
|
11747
|
+
] }),
|
|
11748
|
+
/* @__PURE__ */ jsx(
|
|
11749
|
+
"button",
|
|
11750
|
+
{
|
|
11751
|
+
type: "button",
|
|
11752
|
+
onClick: () => setFontSize(clampNotesFontSize(fontSize + NOTES_FONT_SIZE_STEP)),
|
|
11753
|
+
disabled: fontSize >= NOTES_FONT_SIZE_MAX,
|
|
11754
|
+
"aria-label": t("pptx.presenter.increaseFontSize"),
|
|
11755
|
+
children: /* @__PURE__ */ jsx(LuPlus, {})
|
|
11756
|
+
}
|
|
11757
|
+
)
|
|
11758
|
+
] })
|
|
11759
|
+
] }),
|
|
11760
|
+
onUpdateNotes ? /* @__PURE__ */ jsx(
|
|
11761
|
+
"textarea",
|
|
11762
|
+
{
|
|
11763
|
+
className: "min-h-0 flex-1 resize-none rounded border border-border/30 bg-muted/40 px-3 py-2 leading-relaxed",
|
|
11764
|
+
style: { fontSize },
|
|
11765
|
+
value: notesDraft,
|
|
11766
|
+
onChange: (event) => setNotesDraft(event.target.value),
|
|
11767
|
+
onBlur: () => onUpdateNotes(notesDraft),
|
|
11768
|
+
"aria-label": t("pptx.presenter.speakerNotes")
|
|
11769
|
+
}
|
|
11770
|
+
) : /* @__PURE__ */ jsx(
|
|
11771
|
+
"div",
|
|
11772
|
+
{
|
|
11773
|
+
className: "min-h-0 flex-1 overflow-y-auto whitespace-pre-wrap rounded border border-border/30 bg-muted/40 px-3 py-2 leading-relaxed",
|
|
11774
|
+
style: { fontSize },
|
|
11775
|
+
children: notes
|
|
11776
|
+
}
|
|
11777
|
+
)
|
|
11778
|
+
] })
|
|
11779
|
+
] });
|
|
11780
|
+
}
|
|
11781
|
+
function PresenterSlideNavigator(props) {
|
|
11782
|
+
return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-[120] flex flex-col bg-slate-950/98 text-slate-100", children: [
|
|
11783
|
+
/* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between border-b border-white/10 px-6 py-4", children: [
|
|
11784
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
11785
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-[0.22em] text-sky-300", children: "Slide navigator" }),
|
|
11786
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: "See all slides" })
|
|
11787
|
+
] }),
|
|
11788
|
+
/* @__PURE__ */ jsx(
|
|
11789
|
+
"button",
|
|
11790
|
+
{
|
|
11791
|
+
className: "rounded-md bg-white/10 px-4 py-2 hover:bg-white/20",
|
|
11792
|
+
onClick: props.onClose,
|
|
11793
|
+
children: "Close"
|
|
11794
|
+
}
|
|
11795
|
+
)
|
|
11796
|
+
] }),
|
|
11797
|
+
/* @__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(
|
|
11798
|
+
"button",
|
|
11799
|
+
{
|
|
11800
|
+
className: `group text-left ${index === props.current ? "ring-2 ring-sky-400" : ""} ${slide.hidden ? "opacity-45" : ""}`,
|
|
11801
|
+
onClick: () => props.onSelect(index),
|
|
11802
|
+
children: [
|
|
11803
|
+
/* @__PURE__ */ jsx(
|
|
11804
|
+
ScaledSlidePreview,
|
|
11805
|
+
{
|
|
11806
|
+
slide,
|
|
11807
|
+
templateElements: props.templateElements,
|
|
11808
|
+
canvasSize: props.canvasSize
|
|
11809
|
+
}
|
|
11810
|
+
),
|
|
11811
|
+
/* @__PURE__ */ jsxs("span", { className: "mt-2 block text-xs tabular-nums text-slate-400", children: [
|
|
11812
|
+
index + 1,
|
|
11813
|
+
slide.hidden ? " - hidden" : ""
|
|
11814
|
+
] })
|
|
11815
|
+
]
|
|
11816
|
+
},
|
|
11817
|
+
slide.id ?? index
|
|
11818
|
+
)) })
|
|
11819
|
+
] });
|
|
11820
|
+
}
|
|
11821
|
+
function usePresenterInk(snapshot, onUpdate) {
|
|
11822
|
+
const drawingId = useRef(null);
|
|
11823
|
+
const point = (event) => {
|
|
11824
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
11825
|
+
return {
|
|
11826
|
+
x: (event.clientX - rect.left) / rect.width,
|
|
11827
|
+
y: (event.clientY - rect.top) / rect.height
|
|
11828
|
+
};
|
|
11829
|
+
};
|
|
11830
|
+
const onPointerDown = useCallback(
|
|
11831
|
+
(event) => {
|
|
11832
|
+
const pointer = snapshot.pointer;
|
|
11833
|
+
if (!pointer || pointer.tool === "none" || pointer.tool === "laser") {
|
|
11834
|
+
return;
|
|
11835
|
+
}
|
|
11836
|
+
const nextPoint = point(event);
|
|
11837
|
+
if (pointer.tool === "eraser") {
|
|
11838
|
+
onUpdate({
|
|
11839
|
+
inkStrokes: erasePresentationInkAt(
|
|
11840
|
+
snapshot.inkStrokes ?? [],
|
|
11841
|
+
snapshot.slideIndex,
|
|
11842
|
+
nextPoint
|
|
11843
|
+
)
|
|
11844
|
+
});
|
|
11845
|
+
return;
|
|
11846
|
+
}
|
|
11847
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
11848
|
+
const stroke = {
|
|
11849
|
+
id: crypto.randomUUID(),
|
|
11850
|
+
slideIndex: snapshot.slideIndex,
|
|
11851
|
+
tool: pointer.tool,
|
|
11852
|
+
color: pointer.color,
|
|
11853
|
+
width: pointer.tool === "highlighter" ? 12 : 4,
|
|
11854
|
+
points: [nextPoint]
|
|
11855
|
+
};
|
|
11856
|
+
drawingId.current = stroke.id;
|
|
11857
|
+
onUpdate({ inkStrokes: [...snapshot.inkStrokes ?? [], stroke] });
|
|
11858
|
+
},
|
|
11859
|
+
[onUpdate, snapshot]
|
|
11860
|
+
);
|
|
11861
|
+
const onPointerMove = useCallback(
|
|
11862
|
+
(event) => {
|
|
11863
|
+
const nextPoint = point(event);
|
|
11864
|
+
const pointer = snapshot.pointer;
|
|
11865
|
+
if (!pointer) {
|
|
11866
|
+
return;
|
|
11867
|
+
}
|
|
11868
|
+
if (pointer.tool === "laser") {
|
|
11869
|
+
onUpdate({ pointer: movePresenterPointer(pointer, nextPoint.x, nextPoint.y) });
|
|
11870
|
+
}
|
|
11871
|
+
if (pointer.tool === "eraser" && event.buttons === 1) {
|
|
11872
|
+
onUpdate({
|
|
11873
|
+
inkStrokes: erasePresentationInkAt(
|
|
11874
|
+
snapshot.inkStrokes ?? [],
|
|
11875
|
+
snapshot.slideIndex,
|
|
11876
|
+
nextPoint
|
|
11877
|
+
)
|
|
11878
|
+
});
|
|
11879
|
+
}
|
|
11880
|
+
if (drawingId.current && event.buttons === 1) {
|
|
11881
|
+
onUpdate({
|
|
11882
|
+
inkStrokes: (snapshot.inkStrokes ?? []).map(
|
|
11883
|
+
(stroke) => stroke.id === drawingId.current ? appendPresentationInkPoint(stroke, nextPoint) : stroke
|
|
11884
|
+
)
|
|
11885
|
+
});
|
|
11886
|
+
}
|
|
11887
|
+
},
|
|
11888
|
+
[onUpdate, snapshot]
|
|
11889
|
+
);
|
|
11890
|
+
const onPointerUp = useCallback(() => {
|
|
11891
|
+
drawingId.current = null;
|
|
11892
|
+
}, []);
|
|
11893
|
+
return { onPointerDown, onPointerMove, onPointerUp };
|
|
11894
|
+
}
|
|
11287
11895
|
function PresenterView({
|
|
11288
11896
|
slides,
|
|
11289
11897
|
currentSlideIndex,
|
|
@@ -11294,187 +11902,126 @@ function PresenterView({
|
|
|
11294
11902
|
onExit,
|
|
11295
11903
|
onOpenAudienceWindow,
|
|
11296
11904
|
onCloseAudienceWindow,
|
|
11297
|
-
isAudienceWindowOpen
|
|
11905
|
+
isAudienceWindowOpen,
|
|
11906
|
+
snapshot,
|
|
11907
|
+
onNavigateToSlide,
|
|
11908
|
+
onToggleTimer,
|
|
11909
|
+
onResetTimer,
|
|
11910
|
+
onStepZoom,
|
|
11911
|
+
onResetZoom,
|
|
11912
|
+
onSetBlackout,
|
|
11913
|
+
onUpdateSnapshot,
|
|
11914
|
+
onToggleSubtitles,
|
|
11915
|
+
onSwapDisplays,
|
|
11916
|
+
onUpdateNotes
|
|
11298
11917
|
}) {
|
|
11299
11918
|
const { t } = useTranslation();
|
|
11300
|
-
const [mounted, setMounted] = useState(false);
|
|
11301
|
-
useEffect(() => {
|
|
11302
|
-
const timer = window.setTimeout(() => setMounted(true), 300);
|
|
11303
|
-
return () => window.clearTimeout(timer);
|
|
11304
|
-
}, []);
|
|
11305
11919
|
const [now, setNow] = useState(Date.now());
|
|
11306
11920
|
useEffect(() => {
|
|
11307
11921
|
const interval = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
11308
11922
|
return () => window.clearInterval(interval);
|
|
11309
11923
|
}, []);
|
|
11310
|
-
const elapsed = presentationStartTime ? now - presentationStartTime : 0;
|
|
11311
|
-
const [
|
|
11312
|
-
const
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
}, []);
|
|
11924
|
+
const elapsed = snapshot.elapsedMs ?? (presentationStartTime ? now - presentationStartTime : 0);
|
|
11925
|
+
const [showSlides, setShowSlides] = useState(false);
|
|
11926
|
+
const ink = usePresenterInk(snapshot, onUpdateSnapshot);
|
|
11927
|
+
const handleCaptionChange = useCallback(
|
|
11928
|
+
(caption) => onUpdateSnapshot({ caption }),
|
|
11929
|
+
[onUpdateSnapshot]
|
|
11930
|
+
);
|
|
11318
11931
|
const currentSlide = slides[currentSlideIndex];
|
|
11319
|
-
const nextSlide = currentSlideIndex + 1 < slides.length ? slides[currentSlideIndex + 1] : void 0;
|
|
11320
|
-
const notesText = currentSlide?.notes ?? "";
|
|
11321
|
-
const notesSegments = currentSlide?.notesSegments;
|
|
11322
|
-
const hasRichNotes = notesSegments && notesSegments.length > 0;
|
|
11323
11932
|
if (!currentSlide) {
|
|
11324
11933
|
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") });
|
|
11325
11934
|
}
|
|
11326
11935
|
const TIMER_SEGMENT_MS = 5 * 60 * 1e3;
|
|
11327
11936
|
const timerProgress = Math.min(100, elapsed % TIMER_SEGMENT_MS / TIMER_SEGMENT_MS * 100);
|
|
11328
11937
|
const timerSegment = Math.floor(elapsed / TIMER_SEGMENT_MS);
|
|
11329
|
-
return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-50 flex flex-col bg-
|
|
11330
|
-
/* @__PURE__ */
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
),
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
onCloseAudienceWindow?.();
|
|
11364
|
-
} else {
|
|
11365
|
-
onOpenAudienceWindow();
|
|
11366
|
-
}
|
|
11367
|
-
},
|
|
11368
|
-
className: "p-1.5 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
11369
|
-
title: isAudienceWindowOpen ? t("pptx.presenter.closeAudienceWindow") : t("pptx.presenter.openAudienceWindow"),
|
|
11370
|
-
"aria-label": isAudienceWindowOpen ? t("pptx.presenter.closeAudienceWindow") : t("pptx.presenter.openAudienceWindow"),
|
|
11371
|
-
children: isAudienceWindowOpen ? /* @__PURE__ */ jsx(LuMonitorOff, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(LuMonitor, { className: "w-5 h-5" })
|
|
11372
|
-
}
|
|
11373
|
-
),
|
|
11374
|
-
/* @__PURE__ */ jsx(
|
|
11375
|
-
"button",
|
|
11376
|
-
{
|
|
11377
|
-
type: "button",
|
|
11378
|
-
onClick: onExit,
|
|
11379
|
-
className: "p-1.5 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
11380
|
-
title: t("pptx.presenter.endPresentation"),
|
|
11381
|
-
"aria-label": t("pptx.presenter.endPresentation"),
|
|
11382
|
-
children: /* @__PURE__ */ jsx(LuX, { className: "w-5 h-5" })
|
|
11383
|
-
}
|
|
11384
|
-
)
|
|
11385
|
-
] })
|
|
11386
|
-
] }),
|
|
11387
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2 border-b border-border/60", children: [
|
|
11388
|
-
/* @__PURE__ */ jsxs(
|
|
11389
|
-
"button",
|
|
11390
|
-
{
|
|
11391
|
-
type: "button",
|
|
11392
|
-
onClick: () => onMovePresentationSlide(-1),
|
|
11393
|
-
disabled: currentSlideIndex === 0,
|
|
11394
|
-
className: "inline-flex items-center gap-1.5 px-3 py-1.5 rounded bg-muted hover:bg-accent disabled:opacity-40 disabled:cursor-not-allowed text-xs transition-colors",
|
|
11395
|
-
title: t("pptx.presenter.previousSlide"),
|
|
11396
|
-
children: [
|
|
11397
|
-
/* @__PURE__ */ jsx(LuChevronLeft, { className: "w-4 h-4" }),
|
|
11398
|
-
t("pptx.presenter.prev")
|
|
11399
|
-
]
|
|
11400
|
-
}
|
|
11401
|
-
),
|
|
11402
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm font-mono tabular-nums text-foreground", children: [
|
|
11403
|
-
currentSlideIndex + 1,
|
|
11404
|
-
" / ",
|
|
11405
|
-
slides.length
|
|
11406
|
-
] }),
|
|
11407
|
-
/* @__PURE__ */ jsxs(
|
|
11408
|
-
"button",
|
|
11409
|
-
{
|
|
11410
|
-
type: "button",
|
|
11411
|
-
onClick: () => onMovePresentationSlide(1),
|
|
11412
|
-
disabled: currentSlideIndex >= slides.length - 1,
|
|
11413
|
-
className: "inline-flex items-center gap-1.5 px-3 py-1.5 rounded bg-muted hover:bg-accent disabled:opacity-40 disabled:cursor-not-allowed text-xs transition-colors",
|
|
11414
|
-
title: t("pptx.presenter.nextSlide"),
|
|
11415
|
-
children: [
|
|
11416
|
-
t("pptx.presenter.next"),
|
|
11417
|
-
/* @__PURE__ */ jsx(LuChevronRight, { className: "w-4 h-4" })
|
|
11418
|
-
]
|
|
11419
|
-
}
|
|
11420
|
-
)
|
|
11421
|
-
] }),
|
|
11422
|
-
/* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-border/60", children: [
|
|
11423
|
-
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground uppercase tracking-wider mb-2", children: t("pptx.presenter.nextSlidePreview") }),
|
|
11424
|
-
nextSlide ? /* @__PURE__ */ jsx(
|
|
11425
|
-
ScaledSlidePreview,
|
|
11426
|
-
{
|
|
11427
|
-
slide: nextSlide,
|
|
11428
|
-
templateElements,
|
|
11429
|
-
canvasSize
|
|
11430
|
-
}
|
|
11431
|
-
) : /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-16 rounded border border-border/30 bg-muted/40 text-xs text-muted-foreground italic", children: t("pptx.presenter.endOfPresentation") })
|
|
11432
|
-
] }),
|
|
11433
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-h-0 px-4 py-3", children: [
|
|
11434
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
11435
|
-
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground uppercase tracking-wider", children: t("pptx.presenter.speakerNotes") }),
|
|
11436
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
11938
|
+
return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-50 flex flex-col bg-slate-950 text-slate-100", children: [
|
|
11939
|
+
/* @__PURE__ */ jsx(
|
|
11940
|
+
PresenterConsoleToolbar,
|
|
11941
|
+
{
|
|
11942
|
+
snapshot,
|
|
11943
|
+
audienceOpen: Boolean(isAudienceWindowOpen),
|
|
11944
|
+
onToggleAudience: () => isAudienceWindowOpen ? onCloseAudienceWindow?.() : onOpenAudienceWindow?.(),
|
|
11945
|
+
onSwapDisplays,
|
|
11946
|
+
onToggleTimer,
|
|
11947
|
+
onResetTimer,
|
|
11948
|
+
onShowSlides: () => setShowSlides(true),
|
|
11949
|
+
onStepZoom,
|
|
11950
|
+
onResetZoom,
|
|
11951
|
+
onBlackout: onSetBlackout,
|
|
11952
|
+
onPointerTool: (tool) => onUpdateSnapshot({
|
|
11953
|
+
pointer: { ...snapshot.pointer ?? { x: 0.5, y: 0.5, color: "#ef4444" }, tool }
|
|
11954
|
+
}),
|
|
11955
|
+
onToggleSubtitles,
|
|
11956
|
+
onExit
|
|
11957
|
+
}
|
|
11958
|
+
),
|
|
11959
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 min-h-0", children: [
|
|
11960
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-[7] flex flex-col items-center justify-center bg-black p-6 min-w-0 overflow-hidden", children: [
|
|
11961
|
+
/* @__PURE__ */ jsxs(
|
|
11962
|
+
"div",
|
|
11963
|
+
{
|
|
11964
|
+
className: "relative transition-transform duration-200",
|
|
11965
|
+
style: {
|
|
11966
|
+
transform: `scale(${snapshot.zoom?.scale ?? 1})`,
|
|
11967
|
+
transformOrigin: `${(snapshot.zoom?.originX ?? 0.5) * 100}% ${(snapshot.zoom?.originY ?? 0.5) * 100}%`,
|
|
11968
|
+
touchAction: "none"
|
|
11969
|
+
},
|
|
11970
|
+
...ink,
|
|
11971
|
+
children: [
|
|
11437
11972
|
/* @__PURE__ */ jsx(
|
|
11438
|
-
|
|
11973
|
+
ScaledSlidePreview,
|
|
11439
11974
|
{
|
|
11440
|
-
|
|
11441
|
-
|
|
11442
|
-
|
|
11443
|
-
className: "p-0.5 rounded hover:bg-accent text-muted-foreground hover:text-foreground disabled:opacity-30 disabled:cursor-not-allowed transition-colors",
|
|
11444
|
-
title: t("pptx.presenter.decreaseFontSize"),
|
|
11445
|
-
"aria-label": t("pptx.presenter.decreaseFontSize"),
|
|
11446
|
-
children: /* @__PURE__ */ jsx(LuMinus, { className: "w-3.5 h-3.5" })
|
|
11975
|
+
slide: currentSlide,
|
|
11976
|
+
templateElements,
|
|
11977
|
+
canvasSize
|
|
11447
11978
|
}
|
|
11448
11979
|
),
|
|
11449
|
-
/* @__PURE__ */
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
children: hasRichNotes ? renderNotesSegments(notesSegments) : notesText.trim().length > 0 ? notesText : /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: t("pptx.presenter.noNotes") })
|
|
11473
|
-
}
|
|
11474
|
-
)
|
|
11475
|
-
] })
|
|
11476
|
-
] })
|
|
11980
|
+
/* @__PURE__ */ jsx(PresentationAudienceEffects, { snapshot })
|
|
11981
|
+
]
|
|
11982
|
+
}
|
|
11983
|
+
),
|
|
11984
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 text-xs font-mono tabular-nums text-white/50 select-none", children: t("pptx.presenter.slideLabel", {
|
|
11985
|
+
current: currentSlideIndex + 1,
|
|
11986
|
+
total: slides.length,
|
|
11987
|
+
defaultValue: `Slide ${currentSlideIndex + 1} of ${slides.length}`
|
|
11988
|
+
}) })
|
|
11989
|
+
] }),
|
|
11990
|
+
/* @__PURE__ */ jsx(
|
|
11991
|
+
PresenterNotesRail,
|
|
11992
|
+
{
|
|
11993
|
+
slides,
|
|
11994
|
+
current: currentSlideIndex,
|
|
11995
|
+
canvasSize,
|
|
11996
|
+
templateElements,
|
|
11997
|
+
now,
|
|
11998
|
+
elapsed,
|
|
11999
|
+
onMove: onMovePresentationSlide,
|
|
12000
|
+
onUpdateNotes
|
|
12001
|
+
}
|
|
12002
|
+
)
|
|
11477
12003
|
] }),
|
|
12004
|
+
/* @__PURE__ */ jsx(
|
|
12005
|
+
PresentationSubtitleBar,
|
|
12006
|
+
{
|
|
12007
|
+
visible: Boolean(snapshot.subtitlesVisible),
|
|
12008
|
+
onCaptionChange: handleCaptionChange
|
|
12009
|
+
}
|
|
12010
|
+
),
|
|
12011
|
+
showSlides && /* @__PURE__ */ jsx(
|
|
12012
|
+
PresenterSlideNavigator,
|
|
12013
|
+
{
|
|
12014
|
+
slides,
|
|
12015
|
+
current: currentSlideIndex,
|
|
12016
|
+
canvasSize,
|
|
12017
|
+
templateElements,
|
|
12018
|
+
onSelect: (index) => {
|
|
12019
|
+
onNavigateToSlide(index);
|
|
12020
|
+
setShowSlides(false);
|
|
12021
|
+
},
|
|
12022
|
+
onClose: () => setShowSlides(false)
|
|
12023
|
+
}
|
|
12024
|
+
),
|
|
11478
12025
|
/* @__PURE__ */ jsx(
|
|
11479
12026
|
"div",
|
|
11480
12027
|
{
|
|
@@ -14611,23 +15158,12 @@ function MobileSheet({
|
|
|
14611
15158
|
}) {
|
|
14612
15159
|
const sheetRef = useRef(null);
|
|
14613
15160
|
const { dragY, dragging, handlers } = useSheetDismissDrag(onClose);
|
|
14614
|
-
|
|
14615
|
-
if (!open) {
|
|
14616
|
-
return;
|
|
14617
|
-
}
|
|
14618
|
-
const handleKey = (e) => {
|
|
14619
|
-
if (e.key === "Escape") {
|
|
14620
|
-
onClose();
|
|
14621
|
-
}
|
|
14622
|
-
};
|
|
14623
|
-
window.addEventListener("keydown", handleKey);
|
|
14624
|
-
return () => window.removeEventListener("keydown", handleKey);
|
|
14625
|
-
}, [open, onClose]);
|
|
15161
|
+
useModalFocus(open, sheetRef, onClose);
|
|
14626
15162
|
if (!open) {
|
|
14627
15163
|
return null;
|
|
14628
15164
|
}
|
|
14629
15165
|
const heightStyle = autoHeight ? { maxHeight: "calc(85dvh - env(safe-area-inset-top))" } : fullScreen ? { height: "calc(100dvh - env(safe-area-inset-top))" } : { height: `${Math.round(heightFraction * 100)}dvh` };
|
|
14630
|
-
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex flex-col justify-end",
|
|
15166
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex flex-col justify-end", children: [
|
|
14631
15167
|
/* @__PURE__ */ jsx(
|
|
14632
15168
|
"button",
|
|
14633
15169
|
{
|
|
@@ -14641,6 +15177,10 @@ function MobileSheet({
|
|
|
14641
15177
|
"div",
|
|
14642
15178
|
{
|
|
14643
15179
|
ref: sheetRef,
|
|
15180
|
+
role: "dialog",
|
|
15181
|
+
"aria-modal": "true",
|
|
15182
|
+
"aria-label": typeof title === "string" ? title : "Mobile panel",
|
|
15183
|
+
tabIndex: -1,
|
|
14644
15184
|
className: cn(
|
|
14645
15185
|
"relative bg-background border-t border-border rounded-t-2xl shadow-2xl flex flex-col overflow-hidden",
|
|
14646
15186
|
"animate-in slide-in-from-bottom duration-200",
|
|
@@ -14664,7 +15204,18 @@ function MobileSheet({
|
|
|
14664
15204
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center pt-2 pb-1", children: /* @__PURE__ */ jsx("div", { className: "h-1 w-10 rounded-full bg-muted-foreground/40" }) }),
|
|
14665
15205
|
(title || headerRight) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-4 pb-2 border-b border-border/60", children: [
|
|
14666
15206
|
/* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-foreground truncate", children: title }),
|
|
14667
|
-
headerRight
|
|
15207
|
+
headerRight,
|
|
15208
|
+
/* @__PURE__ */ jsx(
|
|
15209
|
+
"button",
|
|
15210
|
+
{
|
|
15211
|
+
type: "button",
|
|
15212
|
+
"aria-label": "Close",
|
|
15213
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
15214
|
+
onClick: onClose,
|
|
15215
|
+
className: "inline-flex h-8 w-8 items-center justify-center rounded text-xl text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
15216
|
+
children: "\xD7"
|
|
15217
|
+
}
|
|
15218
|
+
)
|
|
14668
15219
|
] })
|
|
14669
15220
|
]
|
|
14670
15221
|
}
|
|
@@ -15874,45 +16425,54 @@ function Toolbar(p) {
|
|
|
15874
16425
|
className: "relative z-20 border-b border-border bg-secondary/50 overflow-visible",
|
|
15875
16426
|
children: [
|
|
15876
16427
|
/* @__PURE__ */ jsx(ToolbarPrimaryRow, { ...p }),
|
|
15877
|
-
showRibbon && /* @__PURE__ */ jsxs(
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
|
|
15884
|
-
"
|
|
15885
|
-
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
|
|
15889
|
-
|
|
15890
|
-
|
|
15891
|
-
|
|
15892
|
-
|
|
15893
|
-
|
|
15894
|
-
|
|
15895
|
-
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
|
|
15900
|
-
|
|
15901
|
-
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
"px-2 py-1 rounded text-[11px] transition-colors mr-1",
|
|
15907
|
-
isCompactToolbarOpen ? "bg-primary/80 text-white" : "text-muted-foreground hover:text-foreground"
|
|
15908
|
-
),
|
|
15909
|
-
title: t(
|
|
15910
|
-
isCompactToolbarOpen ? "pptx.ribbon.collapseRibbon" : "pptx.ribbon.expandRibbon"
|
|
16428
|
+
showRibbon && /* @__PURE__ */ jsxs(
|
|
16429
|
+
"div",
|
|
16430
|
+
{
|
|
16431
|
+
role: "tablist",
|
|
16432
|
+
className: "flex items-center border-b border-border/60 px-1 max-md:overflow-x-auto max-md:scrollbar-none",
|
|
16433
|
+
children: [
|
|
16434
|
+
TOOLBAR_SECTIONS.map((s) => /* @__PURE__ */ jsx(
|
|
16435
|
+
"button",
|
|
16436
|
+
{
|
|
16437
|
+
type: "button",
|
|
16438
|
+
role: "tab",
|
|
16439
|
+
"aria-selected": toolbarSection === s.id,
|
|
16440
|
+
onClick: () => onSetToolbarSection(s.id),
|
|
16441
|
+
className: cn(
|
|
16442
|
+
"relative px-3.5 py-2 text-[12px] font-medium whitespace-nowrap transition-colors max-md:min-h-[36px] max-md:px-3",
|
|
16443
|
+
toolbarSection === s.id ? s.id === "file" ? "text-white bg-primary/80 rounded-sm" : "text-foreground after:absolute after:-bottom-px after:left-0 after:right-0 after:h-[2.5px] after:bg-primary" : s.id === "file" ? "text-primary hover:bg-primary/15 rounded-sm" : "text-muted-foreground hover:text-foreground hover:bg-accent/30"
|
|
16444
|
+
),
|
|
16445
|
+
children: t(s.labelKey)
|
|
16446
|
+
},
|
|
16447
|
+
s.id
|
|
16448
|
+
)),
|
|
16449
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
16450
|
+
/* @__PURE__ */ jsx(
|
|
16451
|
+
TabRowActions,
|
|
16452
|
+
{
|
|
16453
|
+
onEnterRehearsalMode: p.canEdit ? p.onEnterRehearsalMode : void 0,
|
|
16454
|
+
onOpenShareDialog: p.onOpenShareDialog,
|
|
16455
|
+
onPackageForSharing: p.onPackageForSharing
|
|
16456
|
+
}
|
|
15911
16457
|
),
|
|
15912
|
-
|
|
15913
|
-
|
|
15914
|
-
|
|
15915
|
-
|
|
16458
|
+
isNarrowViewport && /* @__PURE__ */ jsx(
|
|
16459
|
+
"button",
|
|
16460
|
+
{
|
|
16461
|
+
type: "button",
|
|
16462
|
+
onClick: p.onToggleCompactToolbar,
|
|
16463
|
+
className: cn(
|
|
16464
|
+
"px-2 py-1 rounded text-[11px] transition-colors mr-1",
|
|
16465
|
+
isCompactToolbarOpen ? "bg-primary/80 text-white" : "text-muted-foreground hover:text-foreground"
|
|
16466
|
+
),
|
|
16467
|
+
title: t(
|
|
16468
|
+
isCompactToolbarOpen ? "pptx.ribbon.collapseRibbon" : "pptx.ribbon.expandRibbon"
|
|
16469
|
+
),
|
|
16470
|
+
children: t(isCompactToolbarOpen ? "pptx.ribbon.collapseRibbon" : "pptx.ribbon.expandRibbon")
|
|
16471
|
+
}
|
|
16472
|
+
)
|
|
16473
|
+
]
|
|
16474
|
+
}
|
|
16475
|
+
),
|
|
15916
16476
|
showRibbon && /* @__PURE__ */ jsxs(
|
|
15917
16477
|
"div",
|
|
15918
16478
|
{
|
|
@@ -20689,6 +21249,8 @@ function SmartArtLayoutSwitcher({
|
|
|
20689
21249
|
layoutType: updated.layoutType,
|
|
20690
21250
|
resolvedLayoutType: updated.resolvedLayoutType,
|
|
20691
21251
|
layout: updated.layout,
|
|
21252
|
+
layoutDirty: updated.layoutDirty,
|
|
21253
|
+
drawingDirty: updated.drawingDirty,
|
|
20692
21254
|
drawingShapes: updated.drawingShapes
|
|
20693
21255
|
});
|
|
20694
21256
|
};
|
|
@@ -20701,6 +21263,7 @@ function SmartArtLayoutSwitcher({
|
|
|
20701
21263
|
"button",
|
|
20702
21264
|
{
|
|
20703
21265
|
type: "button",
|
|
21266
|
+
"data-testid": `smartart-layout-${type}`,
|
|
20704
21267
|
disabled: !canEdit,
|
|
20705
21268
|
className: cn(
|
|
20706
21269
|
"flex flex-col items-center gap-0.5 rounded border p-1.5 transition-colors",
|
|
@@ -20841,6 +21404,7 @@ function SmartArtNodeRow({
|
|
|
20841
21404
|
{
|
|
20842
21405
|
ref: inputRef,
|
|
20843
21406
|
type: "text",
|
|
21407
|
+
"data-testid": "smartart-node-text",
|
|
20844
21408
|
disabled: !canEdit,
|
|
20845
21409
|
"aria-label": label,
|
|
20846
21410
|
className: cn(INPUT, "flex-1 text-[11px] py-0.5"),
|
|
@@ -21057,6 +21621,7 @@ function SmartArtPropertiesPanel({
|
|
|
21057
21621
|
"select",
|
|
21058
21622
|
{
|
|
21059
21623
|
disabled: !canEdit,
|
|
21624
|
+
"data-testid": "smartart-color-scheme",
|
|
21060
21625
|
"aria-label": t("pptx.smartart.colorScheme"),
|
|
21061
21626
|
className: cn(INPUT, "w-full"),
|
|
21062
21627
|
value: smartArtData.colorScheme ?? "colorful1",
|
|
@@ -22296,6 +22861,42 @@ function InspectorCommentsSection({
|
|
|
22296
22861
|
] })
|
|
22297
22862
|
] });
|
|
22298
22863
|
}
|
|
22864
|
+
function InspectorPaneHeader({
|
|
22865
|
+
activeTab,
|
|
22866
|
+
onSetActiveTab,
|
|
22867
|
+
onClose
|
|
22868
|
+
}) {
|
|
22869
|
+
const { t } = useTranslation();
|
|
22870
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b border-border", children: [
|
|
22871
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 rounded bg-muted p-0.5", children: INSPECTOR_TABS.map(({ key, label, icon: Icon }) => /* @__PURE__ */ jsxs(
|
|
22872
|
+
"button",
|
|
22873
|
+
{
|
|
22874
|
+
type: "button",
|
|
22875
|
+
title: label,
|
|
22876
|
+
className: cn(
|
|
22877
|
+
"flex items-center gap-1 px-2 py-1 rounded text-[11px] transition-colors",
|
|
22878
|
+
activeTab === key ? "bg-primary text-white" : "text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
22879
|
+
),
|
|
22880
|
+
onClick: () => onSetActiveTab(key),
|
|
22881
|
+
children: [
|
|
22882
|
+
/* @__PURE__ */ jsx(Icon, { className: "w-3.5 h-3.5" }),
|
|
22883
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: label })
|
|
22884
|
+
]
|
|
22885
|
+
},
|
|
22886
|
+
key
|
|
22887
|
+
)) }),
|
|
22888
|
+
/* @__PURE__ */ jsx(
|
|
22889
|
+
"button",
|
|
22890
|
+
{
|
|
22891
|
+
type: "button",
|
|
22892
|
+
onClick: onClose,
|
|
22893
|
+
title: t("common.close"),
|
|
22894
|
+
className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
|
|
22895
|
+
children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
|
|
22896
|
+
}
|
|
22897
|
+
)
|
|
22898
|
+
] });
|
|
22899
|
+
}
|
|
22299
22900
|
function InfoRow({ label, value }) {
|
|
22300
22901
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
22301
22902
|
/* @__PURE__ */ jsx("span", { children: label }),
|
|
@@ -22680,8 +23281,23 @@ function SlideThemeOverridePanel({
|
|
|
22680
23281
|
}) {
|
|
22681
23282
|
const { t } = useTranslation();
|
|
22682
23283
|
const override = activeSlide?.clrMapOverride;
|
|
22683
|
-
const isOverrideActive =
|
|
23284
|
+
const isOverrideActive = override !== void 0;
|
|
22684
23285
|
const targetSlotOptions = useMemo(() => [...THEME_COLOR_SCHEME_KEYS], []);
|
|
23286
|
+
const commitOverride = useCallback(
|
|
23287
|
+
(nextOverride) => {
|
|
23288
|
+
if (!activeSlide || !theme?.colorScheme) {
|
|
23289
|
+
onUpdateSlide({ clrMapOverride: nextOverride });
|
|
23290
|
+
return;
|
|
23291
|
+
}
|
|
23292
|
+
const nextSlide = applyThemeOverrideToSlide(activeSlide, theme.colorScheme, nextOverride);
|
|
23293
|
+
onUpdateSlide({
|
|
23294
|
+
clrMapOverride: nextSlide.clrMapOverride,
|
|
23295
|
+
backgroundColor: nextSlide.backgroundColor,
|
|
23296
|
+
elements: nextSlide.elements
|
|
23297
|
+
});
|
|
23298
|
+
},
|
|
23299
|
+
[activeSlide, onUpdateSlide, theme?.colorScheme]
|
|
23300
|
+
);
|
|
22685
23301
|
const handleToggle = useCallback(
|
|
22686
23302
|
(enabled) => {
|
|
22687
23303
|
if (enabled) {
|
|
@@ -22689,12 +23305,12 @@ function SlideThemeOverridePanel({
|
|
|
22689
23305
|
for (const key of COLOR_MAP_ALIAS_KEYS) {
|
|
22690
23306
|
defaultMap[key] = DEFAULT_COLOR_MAP[key];
|
|
22691
23307
|
}
|
|
22692
|
-
|
|
23308
|
+
commitOverride(defaultMap);
|
|
22693
23309
|
} else {
|
|
22694
|
-
|
|
23310
|
+
commitOverride(void 0);
|
|
22695
23311
|
}
|
|
22696
23312
|
},
|
|
22697
|
-
[
|
|
23313
|
+
[commitOverride]
|
|
22698
23314
|
);
|
|
22699
23315
|
const handleAliasChange = useCallback(
|
|
22700
23316
|
(alias, targetSlot) => {
|
|
@@ -22705,9 +23321,9 @@ function SlideThemeOverridePanel({
|
|
|
22705
23321
|
next[key] = DEFAULT_COLOR_MAP[key];
|
|
22706
23322
|
}
|
|
22707
23323
|
}
|
|
22708
|
-
|
|
23324
|
+
commitOverride(next);
|
|
22709
23325
|
},
|
|
22710
|
-
[
|
|
23326
|
+
[commitOverride, override]
|
|
22711
23327
|
);
|
|
22712
23328
|
const resolveSlotColor = useCallback(
|
|
22713
23329
|
(slot) => {
|
|
@@ -23142,6 +23758,35 @@ function TemplateBackgroundCard({
|
|
|
23142
23758
|
})()
|
|
23143
23759
|
] });
|
|
23144
23760
|
}
|
|
23761
|
+
var ANIMATION_PANEL_MIN_HEIGHT = 80;
|
|
23762
|
+
var ANIMATION_PANEL_MAX_HEIGHT = 500;
|
|
23763
|
+
var ANIMATION_PANEL_DEFAULT_HEIGHT = 220;
|
|
23764
|
+
function useInspectorPaneState(themeOptions, slideMasters, theme) {
|
|
23765
|
+
const activeThemePath = slideMasters?.[0]?.themePath;
|
|
23766
|
+
const effectiveThemeOptions = useMemo(() => {
|
|
23767
|
+
if (themeOptions.length > 0 || !activeThemePath) {
|
|
23768
|
+
return themeOptions;
|
|
23769
|
+
}
|
|
23770
|
+
return [{ path: activeThemePath, name: theme?.name }];
|
|
23771
|
+
}, [activeThemePath, theme?.name, themeOptions]);
|
|
23772
|
+
const [selectedThemePath, setSelectedThemePath] = useState("");
|
|
23773
|
+
useEffect(() => {
|
|
23774
|
+
setSelectedThemePath(activeThemePath ?? effectiveThemeOptions[0]?.path ?? "");
|
|
23775
|
+
}, [activeThemePath, effectiveThemeOptions]);
|
|
23776
|
+
const [animationPanelHeight, setAnimationPanelHeight] = useState(ANIMATION_PANEL_DEFAULT_HEIGHT);
|
|
23777
|
+
const onResizeAnimationPanel = useCallback((delta) => {
|
|
23778
|
+
setAnimationPanelHeight(
|
|
23779
|
+
(height) => Math.min(ANIMATION_PANEL_MAX_HEIGHT, Math.max(ANIMATION_PANEL_MIN_HEIGHT, height - delta))
|
|
23780
|
+
);
|
|
23781
|
+
}, []);
|
|
23782
|
+
return {
|
|
23783
|
+
animationPanelHeight,
|
|
23784
|
+
effectiveThemeOptions,
|
|
23785
|
+
onResizeAnimationPanel,
|
|
23786
|
+
selectedThemePath,
|
|
23787
|
+
setSelectedThemePath
|
|
23788
|
+
};
|
|
23789
|
+
}
|
|
23145
23790
|
function InspectorPane(props) {
|
|
23146
23791
|
const {
|
|
23147
23792
|
isOpen,
|
|
@@ -23206,23 +23851,13 @@ function InspectorPane(props) {
|
|
|
23206
23851
|
const hasSelection = selectedElement !== null;
|
|
23207
23852
|
const { t } = useTranslation();
|
|
23208
23853
|
const { dragY, handlers: dragHandlers } = useSheetDismissDrag(onClose);
|
|
23209
|
-
const
|
|
23210
|
-
|
|
23211
|
-
|
|
23212
|
-
|
|
23213
|
-
|
|
23214
|
-
|
|
23215
|
-
|
|
23216
|
-
}, []);
|
|
23217
|
-
useEffect(() => {
|
|
23218
|
-
const activeThemePath = slideMasters?.[0]?.themePath;
|
|
23219
|
-
if (activeThemePath && activeThemePath.length > 0) {
|
|
23220
|
-
setSelectedThemePath(activeThemePath);
|
|
23221
|
-
return;
|
|
23222
|
-
}
|
|
23223
|
-
const fallback = themeOptions[0]?.path ?? "";
|
|
23224
|
-
setSelectedThemePath((previous) => previous || fallback);
|
|
23225
|
-
}, [slideMasters, themeOptions]);
|
|
23854
|
+
const {
|
|
23855
|
+
animationPanelHeight,
|
|
23856
|
+
effectiveThemeOptions,
|
|
23857
|
+
onResizeAnimationPanel,
|
|
23858
|
+
selectedThemePath,
|
|
23859
|
+
setSelectedThemePath
|
|
23860
|
+
} = useInspectorPaneState(themeOptions, slideMasters, theme);
|
|
23226
23861
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23227
23862
|
isOpen && /* @__PURE__ */ jsx(
|
|
23228
23863
|
"button",
|
|
@@ -23264,35 +23899,14 @@ function InspectorPane(props) {
|
|
|
23264
23899
|
children: /* @__PURE__ */ jsx("div", { className: "h-1 w-10 rounded-full bg-muted-foreground/40" })
|
|
23265
23900
|
}
|
|
23266
23901
|
),
|
|
23267
|
-
/* @__PURE__ */
|
|
23268
|
-
|
|
23269
|
-
|
|
23270
|
-
|
|
23271
|
-
|
|
23272
|
-
|
|
23273
|
-
|
|
23274
|
-
|
|
23275
|
-
activeTab === key ? "bg-primary text-white" : "text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
23276
|
-
),
|
|
23277
|
-
onClick: () => onSetActiveTab(key),
|
|
23278
|
-
children: [
|
|
23279
|
-
/* @__PURE__ */ jsx(Icon, { className: "w-3.5 h-3.5" }),
|
|
23280
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: label })
|
|
23281
|
-
]
|
|
23282
|
-
},
|
|
23283
|
-
key
|
|
23284
|
-
)) }),
|
|
23285
|
-
/* @__PURE__ */ jsx(
|
|
23286
|
-
"button",
|
|
23287
|
-
{
|
|
23288
|
-
type: "button",
|
|
23289
|
-
onClick: onClose,
|
|
23290
|
-
title: t("common.close"),
|
|
23291
|
-
className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
|
|
23292
|
-
children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
|
|
23293
|
-
}
|
|
23294
|
-
)
|
|
23295
|
-
] }),
|
|
23902
|
+
/* @__PURE__ */ jsx(
|
|
23903
|
+
InspectorPaneHeader,
|
|
23904
|
+
{
|
|
23905
|
+
activeTab,
|
|
23906
|
+
onSetActiveTab,
|
|
23907
|
+
onClose
|
|
23908
|
+
}
|
|
23909
|
+
),
|
|
23296
23910
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
|
|
23297
23911
|
activeTab === "elements" && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
23298
23912
|
/* @__PURE__ */ jsx("div", { className: cn(HEADING, "mb-2"), children: t("pptx.inspector.layerOrder") }),
|
|
@@ -23345,7 +23959,7 @@ function InspectorPane(props) {
|
|
|
23345
23959
|
coreProperties,
|
|
23346
23960
|
appProperties,
|
|
23347
23961
|
customProperties,
|
|
23348
|
-
themeOptions,
|
|
23962
|
+
themeOptions: effectiveThemeOptions,
|
|
23349
23963
|
selectedThemePath,
|
|
23350
23964
|
setSelectedThemePath,
|
|
23351
23965
|
onApplyTheme,
|
|
@@ -23402,12 +24016,12 @@ function InspectorPane(props) {
|
|
|
23402
24016
|
)
|
|
23403
24017
|
] }),
|
|
23404
24018
|
hasSelection && selectedElement && activeSlide && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23405
|
-
/* @__PURE__ */ jsx(ResizeHandle, { direction: "vertical", onResize:
|
|
24019
|
+
/* @__PURE__ */ jsx(ResizeHandle, { direction: "vertical", onResize: onResizeAnimationPanel }),
|
|
23406
24020
|
/* @__PURE__ */ jsx(
|
|
23407
24021
|
"div",
|
|
23408
24022
|
{
|
|
23409
24023
|
className: "border-t border-border p-3 overflow-y-auto flex-shrink-0",
|
|
23410
|
-
style: { height:
|
|
24024
|
+
style: { height: animationPanelHeight },
|
|
23411
24025
|
children: /* @__PURE__ */ jsx(
|
|
23412
24026
|
AnimationPanel,
|
|
23413
24027
|
{
|
|
@@ -23968,93 +24582,17 @@ function PresentationTouchControls({
|
|
|
23968
24582
|
},
|
|
23969
24583
|
"aria-label": t("pptx.presenter.nextSlide"),
|
|
23970
24584
|
children: /* @__PURE__ */ jsx(LuChevronRight, { size: 26 })
|
|
23971
|
-
}
|
|
23972
|
-
),
|
|
23973
|
-
/* @__PURE__ */ jsx(
|
|
23974
|
-
"span",
|
|
23975
|
-
{
|
|
23976
|
-
className: "fixed z-[90] left-1/2 -translate-x-1/2 px-3 py-1 rounded-full bg-black/55 text-white text-xs font-mono tabular-nums pointer-events-none",
|
|
23977
|
-
style: { bottom: "calc(env(safe-area-inset-bottom, 0px) + 0.5rem)" },
|
|
23978
|
-
children: totalSlides === 0 ? "0 / 0" : `${currentSlideIndex + 1} / ${totalSlides}`
|
|
23979
|
-
}
|
|
23980
|
-
)
|
|
23981
|
-
] });
|
|
23982
|
-
}
|
|
23983
|
-
function PresentationSubtitleBar({
|
|
23984
|
-
visible
|
|
23985
|
-
}) {
|
|
23986
|
-
const { t } = useTranslation();
|
|
23987
|
-
const [captionText, setCaptionText] = useState("");
|
|
23988
|
-
const [supportState, setSupportState] = useState(
|
|
23989
|
-
"unknown"
|
|
23990
|
-
);
|
|
23991
|
-
const recognitionRef = useRef(null);
|
|
23992
|
-
const shouldRunRef = useRef(false);
|
|
23993
|
-
useEffect(() => {
|
|
23994
|
-
if (!visible) {
|
|
23995
|
-
shouldRunRef.current = false;
|
|
23996
|
-
recognitionRef.current?.stop();
|
|
23997
|
-
recognitionRef.current = null;
|
|
23998
|
-
setCaptionText("");
|
|
23999
|
-
return;
|
|
24000
|
-
}
|
|
24001
|
-
shouldRunRef.current = true;
|
|
24002
|
-
const speechWindow = window;
|
|
24003
|
-
const RecognitionCtor = speechWindow.SpeechRecognition ?? speechWindow.webkitSpeechRecognition;
|
|
24004
|
-
if (!RecognitionCtor) {
|
|
24005
|
-
setSupportState("unsupported");
|
|
24006
|
-
return;
|
|
24007
|
-
}
|
|
24008
|
-
setSupportState("supported");
|
|
24009
|
-
const recognition = new RecognitionCtor();
|
|
24010
|
-
recognition.continuous = true;
|
|
24011
|
-
recognition.interimResults = true;
|
|
24012
|
-
recognition.lang = navigator.language || "en-US";
|
|
24013
|
-
recognition.onresult = (event) => {
|
|
24014
|
-
let finalText = "";
|
|
24015
|
-
let interimText = "";
|
|
24016
|
-
for (let index = event.resultIndex; index < event.results.length; index += 1) {
|
|
24017
|
-
const result = event.results[index];
|
|
24018
|
-
const fragment = result?.[0]?.transcript ?? "";
|
|
24019
|
-
if (result?.isFinal) {
|
|
24020
|
-
finalText += fragment;
|
|
24021
|
-
} else {
|
|
24022
|
-
interimText += fragment;
|
|
24023
|
-
}
|
|
24024
|
-
}
|
|
24025
|
-
const merged = `${finalText} ${interimText}`.trim();
|
|
24026
|
-
if (merged.length > 0) {
|
|
24027
|
-
setCaptionText(merged);
|
|
24028
|
-
}
|
|
24029
|
-
};
|
|
24030
|
-
recognition.onerror = () => {
|
|
24031
|
-
};
|
|
24032
|
-
recognition.onend = () => {
|
|
24033
|
-
if (!shouldRunRef.current) {
|
|
24034
|
-
return;
|
|
24035
|
-
}
|
|
24036
|
-
try {
|
|
24037
|
-
recognition.start();
|
|
24038
|
-
} catch {
|
|
24039
|
-
}
|
|
24040
|
-
};
|
|
24041
|
-
recognitionRef.current = recognition;
|
|
24042
|
-
try {
|
|
24043
|
-
recognition.start();
|
|
24044
|
-
} catch {
|
|
24045
|
-
setSupportState("unsupported");
|
|
24046
|
-
}
|
|
24047
|
-
return () => {
|
|
24048
|
-
shouldRunRef.current = false;
|
|
24049
|
-
recognition.stop();
|
|
24050
|
-
recognitionRef.current = null;
|
|
24051
|
-
};
|
|
24052
|
-
}, [visible]);
|
|
24053
|
-
if (!visible) {
|
|
24054
|
-
return null;
|
|
24055
|
-
}
|
|
24056
|
-
const renderedText = supportState === "unsupported" ? t("pptx.subtitles.notSupported") : captionText.length > 0 ? captionText : t("pptx.subtitles.listening");
|
|
24057
|
-
return /* @__PURE__ */ jsx("div", { className: "absolute bottom-14 left-1/2 -translate-x-1/2 z-[70] max-w-[80%] min-w-[300px]", children: /* @__PURE__ */ jsx("div", { className: "px-6 py-3 rounded-lg bg-black/75 backdrop-blur-sm border border-white/10", children: /* @__PURE__ */ jsx("p", { className: "text-center text-[15px] text-white/70 italic", children: renderedText }) }) });
|
|
24585
|
+
}
|
|
24586
|
+
),
|
|
24587
|
+
/* @__PURE__ */ jsx(
|
|
24588
|
+
"span",
|
|
24589
|
+
{
|
|
24590
|
+
className: "fixed z-[90] left-1/2 -translate-x-1/2 px-3 py-1 rounded-full bg-black/55 text-white text-xs font-mono tabular-nums pointer-events-none",
|
|
24591
|
+
style: { bottom: "calc(env(safe-area-inset-bottom, 0px) + 0.5rem)" },
|
|
24592
|
+
children: totalSlides === 0 ? "0 / 0" : `${currentSlideIndex + 1} / ${totalSlides}`
|
|
24593
|
+
}
|
|
24594
|
+
)
|
|
24595
|
+
] });
|
|
24058
24596
|
}
|
|
24059
24597
|
function SlideLayer({ slide, templateElements, canvasSize }) {
|
|
24060
24598
|
const safeWidth = Math.max(canvasSize.width, 1);
|
|
@@ -24402,6 +24940,7 @@ function PresentationTransitionOverlay({
|
|
|
24402
24940
|
"div",
|
|
24403
24941
|
{
|
|
24404
24942
|
ref: containerRef,
|
|
24943
|
+
"data-pptx-transition-overlay": true,
|
|
24405
24944
|
className: "pptx-react-transition-overlay absolute inset-0 pointer-events-none overflow-hidden",
|
|
24406
24945
|
style: { zIndex: outgoingZIndex },
|
|
24407
24946
|
children: [
|
|
@@ -24409,6 +24948,7 @@ function PresentationTransitionOverlay({
|
|
|
24409
24948
|
/* @__PURE__ */ jsx(
|
|
24410
24949
|
"div",
|
|
24411
24950
|
{
|
|
24951
|
+
"data-pptx-transition-layer": "outgoing",
|
|
24412
24952
|
className: "pptx-react-transition-layer absolute inset-0 flex items-center justify-center",
|
|
24413
24953
|
style: {
|
|
24414
24954
|
animation: animations.outgoing !== "none" ? animations.outgoing : void 0
|
|
@@ -25480,6 +26020,7 @@ function BroadcastDialog({
|
|
|
25480
26020
|
const [copied, setCopied] = useState(false);
|
|
25481
26021
|
const dialogRef = useRef(null);
|
|
25482
26022
|
const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
|
|
26023
|
+
useModalFocus(open, dialogRef, onClose);
|
|
25483
26024
|
useEffect(() => {
|
|
25484
26025
|
if (open && !isBroadcasting) {
|
|
25485
26026
|
const broadcastRoom = defaultRoomId ? `broadcast-${defaultRoomId}` : generateBroadcastRoomId();
|
|
@@ -25488,23 +26029,6 @@ function BroadcastDialog({
|
|
|
25488
26029
|
setServerUrl(defaultServerUrl ?? DEFAULT_BROADCAST_SERVER_URL);
|
|
25489
26030
|
}
|
|
25490
26031
|
}, [open, isBroadcasting, defaultRoomId, defaultUserName, defaultServerUrl]);
|
|
25491
|
-
useEffect(() => {
|
|
25492
|
-
if (!open) {
|
|
25493
|
-
return;
|
|
25494
|
-
}
|
|
25495
|
-
function handleKeyDown(e) {
|
|
25496
|
-
if (e.key === "Escape") {
|
|
25497
|
-
onClose();
|
|
25498
|
-
}
|
|
25499
|
-
}
|
|
25500
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
25501
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
25502
|
-
}, [open, onClose]);
|
|
25503
|
-
useEffect(() => {
|
|
25504
|
-
if (open && dialogRef.current) {
|
|
25505
|
-
dialogRef.current.focus();
|
|
25506
|
-
}
|
|
25507
|
-
}, [open]);
|
|
25508
26032
|
const activeRoomId = isBroadcasting ? collab.config.roomId : roomId;
|
|
25509
26033
|
const activeServerUrl = isBroadcasting ? collab.config.serverUrl : serverUrl;
|
|
25510
26034
|
const broadcastUrl = typeof window !== "undefined" ? buildBroadcastViewerUrl(activeRoomId, activeServerUrl, window.location) : activeRoomId;
|
|
@@ -25790,24 +26314,252 @@ function ActiveBroadcastView({
|
|
|
25790
26314
|
}
|
|
25791
26315
|
function getInitials3(name) {
|
|
25792
26316
|
const parts = name.trim().split(/\s+/u);
|
|
25793
|
-
|
|
25794
|
-
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
25795
|
-
}
|
|
25796
|
-
return name.slice(0, 2).toUpperCase();
|
|
26317
|
+
return parts.length >= 2 ? (parts[0][0] + parts[parts.length - 1][0]).toUpperCase() : name.slice(0, 2).toUpperCase();
|
|
25797
26318
|
}
|
|
25798
26319
|
function isP2P(config) {
|
|
25799
26320
|
return config.transport === "webrtc" || !config.serverUrl?.trim();
|
|
25800
26321
|
}
|
|
25801
|
-
function
|
|
25802
|
-
|
|
25803
|
-
|
|
25804
|
-
|
|
25805
|
-
|
|
25806
|
-
|
|
25807
|
-
|
|
25808
|
-
|
|
25809
|
-
|
|
25810
|
-
|
|
26322
|
+
function shareUrl(config) {
|
|
26323
|
+
return buildCollaborationShareUrl(
|
|
26324
|
+
config,
|
|
26325
|
+
typeof window === "undefined" ? void 0 : { origin: window.location.origin, pathname: window.location.pathname }
|
|
26326
|
+
);
|
|
26327
|
+
}
|
|
26328
|
+
function ActiveSessionView({
|
|
26329
|
+
collab,
|
|
26330
|
+
activeCollaboration,
|
|
26331
|
+
copied,
|
|
26332
|
+
onCopyRoomId,
|
|
26333
|
+
onStopCollaboration
|
|
26334
|
+
}) {
|
|
26335
|
+
const { t } = useTranslation();
|
|
26336
|
+
const statusColor = collab.status === "connected" ? "text-green-400" : collab.status === "connecting" ? "text-yellow-400" : "text-red-400";
|
|
26337
|
+
const statusIcon = collab.status === "connected" || collab.status === "connecting" ? /* @__PURE__ */ jsx(LuWifi, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(LuWifiOff, { className: "w-4 h-4" });
|
|
26338
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
26339
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26340
|
+
/* @__PURE__ */ jsx("span", { className: statusColor, children: statusIcon }),
|
|
26341
|
+
/* @__PURE__ */ jsx("span", { className: "text-[13px] font-medium text-foreground capitalize", children: collab.status }),
|
|
26342
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[12px] text-muted-foreground ml-auto flex items-center gap-1", children: [
|
|
26343
|
+
/* @__PURE__ */ jsx(LuUsers, { className: "w-3.5 h-3.5" }),
|
|
26344
|
+
t("pptx.collaboration.userCount", { count: collab.connectedCount })
|
|
26345
|
+
] })
|
|
26346
|
+
] }),
|
|
26347
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26348
|
+
/* @__PURE__ */ jsx("label", { className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.shareLink") }),
|
|
26349
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26350
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 px-3 py-1.5 rounded border border-border bg-background text-[11px] text-foreground select-all font-mono truncate", children: shareUrl(collab.config) }),
|
|
26351
|
+
/* @__PURE__ */ jsx(
|
|
26352
|
+
"button",
|
|
26353
|
+
{
|
|
26354
|
+
type: "button",
|
|
26355
|
+
onClick: onCopyRoomId,
|
|
26356
|
+
className: "flex items-center gap-1 px-2.5 py-1.5 rounded border border-border bg-muted hover:bg-accent text-[12px] text-foreground transition-colors shrink-0",
|
|
26357
|
+
title: t("pptx.share.copyLink"),
|
|
26358
|
+
children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26359
|
+
/* @__PURE__ */ jsx(LuCheck, { className: "w-3.5 h-3.5 text-green-400" }),
|
|
26360
|
+
/* @__PURE__ */ jsx("span", { children: t("pptx.share.copied") })
|
|
26361
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26362
|
+
/* @__PURE__ */ jsx(LuCopy, { className: "w-3.5 h-3.5" }),
|
|
26363
|
+
/* @__PURE__ */ jsx("span", { children: t("pptx.share.copyUrl") })
|
|
26364
|
+
] })
|
|
26365
|
+
}
|
|
26366
|
+
)
|
|
26367
|
+
] }),
|
|
26368
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: t("pptx.share.shareHint") })
|
|
26369
|
+
] }),
|
|
26370
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[11px] text-muted-foreground", children: [
|
|
26371
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
26372
|
+
t("pptx.share.room"),
|
|
26373
|
+
" ",
|
|
26374
|
+
/* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: collab.config.roomId })
|
|
26375
|
+
] }),
|
|
26376
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
26377
|
+
t("pptx.share.server"),
|
|
26378
|
+
" ",
|
|
26379
|
+
/* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: isP2P(collab.config) ? t("pptx.share.p2pServerValue") : collab.config.serverUrl })
|
|
26380
|
+
] })
|
|
26381
|
+
] }),
|
|
26382
|
+
collab.remoteUsers.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26383
|
+
/* @__PURE__ */ jsx("label", { className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.connectedUsers") }),
|
|
26384
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded border border-border bg-background divide-y divide-border max-h-[140px] overflow-y-auto", children: [
|
|
26385
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [
|
|
26386
|
+
/* @__PURE__ */ jsx(
|
|
26387
|
+
"div",
|
|
26388
|
+
{
|
|
26389
|
+
className: "w-6 h-6 rounded-full flex items-center justify-center text-[9px] font-semibold text-white shrink-0",
|
|
26390
|
+
style: { backgroundColor: collab.config.userColor ?? "#6366f1" },
|
|
26391
|
+
children: getInitials3(activeCollaboration?.userName ?? collab.config.userName)
|
|
26392
|
+
}
|
|
26393
|
+
),
|
|
26394
|
+
/* @__PURE__ */ jsx("span", { className: "text-[12px] text-foreground truncate", children: activeCollaboration?.userName ?? collab.config.userName }),
|
|
26395
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground ml-auto", children: t("pptx.share.you") })
|
|
26396
|
+
] }),
|
|
26397
|
+
collab.remoteUsers.map((user) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [
|
|
26398
|
+
/* @__PURE__ */ jsx(
|
|
26399
|
+
"div",
|
|
26400
|
+
{
|
|
26401
|
+
className: "w-6 h-6 rounded-full flex items-center justify-center text-[9px] font-semibold text-white shrink-0",
|
|
26402
|
+
style: { backgroundColor: user.userColor },
|
|
26403
|
+
children: user.userAvatar ? /* @__PURE__ */ jsx(
|
|
26404
|
+
"img",
|
|
26405
|
+
{
|
|
26406
|
+
src: user.userAvatar,
|
|
26407
|
+
alt: "",
|
|
26408
|
+
className: "w-full h-full rounded-full object-cover"
|
|
26409
|
+
}
|
|
26410
|
+
) : getInitials3(user.userName)
|
|
26411
|
+
}
|
|
26412
|
+
),
|
|
26413
|
+
/* @__PURE__ */ jsx("span", { className: "text-[12px] text-foreground truncate", children: user.userName }),
|
|
26414
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground ml-auto", children: [
|
|
26415
|
+
"Slide ",
|
|
26416
|
+
user.activeSlideIndex + 1
|
|
26417
|
+
] })
|
|
26418
|
+
] }, user.clientId))
|
|
26419
|
+
] })
|
|
26420
|
+
] }),
|
|
26421
|
+
onStopCollaboration && /* @__PURE__ */ jsx(
|
|
26422
|
+
"button",
|
|
26423
|
+
{
|
|
26424
|
+
type: "button",
|
|
26425
|
+
onClick: onStopCollaboration,
|
|
26426
|
+
className: "w-full px-3 py-2 rounded border border-red-500/30 bg-red-500/10 hover:bg-red-500/20 text-[12px] text-red-400 font-medium transition-colors",
|
|
26427
|
+
children: t("pptx.share.stopSharing")
|
|
26428
|
+
}
|
|
26429
|
+
)
|
|
26430
|
+
] });
|
|
26431
|
+
}
|
|
26432
|
+
function StartSessionForm({
|
|
26433
|
+
mode,
|
|
26434
|
+
invitation,
|
|
26435
|
+
roomId,
|
|
26436
|
+
userName,
|
|
26437
|
+
serverUrl,
|
|
26438
|
+
onRoomIdChange,
|
|
26439
|
+
onUserNameChange,
|
|
26440
|
+
onServerUrlChange,
|
|
26441
|
+
onModeChange,
|
|
26442
|
+
onInvitationChange,
|
|
26443
|
+
preconfigured,
|
|
26444
|
+
connectionFailed,
|
|
26445
|
+
onRetry
|
|
26446
|
+
}) {
|
|
26447
|
+
const { t } = useTranslation();
|
|
26448
|
+
const inputReadOnlyClass = preconfigured ? " opacity-70 cursor-not-allowed" : "";
|
|
26449
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
26450
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1 rounded-lg bg-muted p-1", role: "tablist", children: ["create", "join"].map((candidate) => /* @__PURE__ */ jsx(
|
|
26451
|
+
"button",
|
|
26452
|
+
{
|
|
26453
|
+
type: "button",
|
|
26454
|
+
role: "tab",
|
|
26455
|
+
"aria-selected": mode === candidate,
|
|
26456
|
+
onClick: () => onModeChange(candidate),
|
|
26457
|
+
className: `rounded-md px-3 py-1.5 text-[12px] font-medium transition-colors ${mode === candidate ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
|
|
26458
|
+
children: t(candidate === "create" ? "pptx.share.createSession" : "pptx.share.joinSession")
|
|
26459
|
+
},
|
|
26460
|
+
candidate
|
|
26461
|
+
)) }),
|
|
26462
|
+
/* @__PURE__ */ jsx("p", { className: "text-[13px] text-muted-foreground leading-relaxed", children: mode === "join" ? t("pptx.share.joinDescription") : preconfigured ? t("pptx.share.preconfiguredDescription") : t("pptx.share.description") }),
|
|
26463
|
+
connectionFailed && /* @__PURE__ */ jsxs(
|
|
26464
|
+
"div",
|
|
26465
|
+
{
|
|
26466
|
+
role: "alert",
|
|
26467
|
+
className: "flex items-start gap-2 rounded border border-red-500/30 bg-red-500/10 px-3 py-2 text-[12px] text-red-400",
|
|
26468
|
+
children: [
|
|
26469
|
+
/* @__PURE__ */ jsx(LuWifiOff, { className: "w-4 h-4 mt-0.5 shrink-0" }),
|
|
26470
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1", children: [
|
|
26471
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: t("pptx.share.connectionError") }),
|
|
26472
|
+
onRetry && /* @__PURE__ */ jsx(
|
|
26473
|
+
"button",
|
|
26474
|
+
{
|
|
26475
|
+
type: "button",
|
|
26476
|
+
onClick: onRetry,
|
|
26477
|
+
className: "underline underline-offset-2 hover:no-underline",
|
|
26478
|
+
children: t("pptx.collaboration.retry")
|
|
26479
|
+
}
|
|
26480
|
+
)
|
|
26481
|
+
] })
|
|
26482
|
+
]
|
|
26483
|
+
}
|
|
26484
|
+
),
|
|
26485
|
+
mode === "join" ? /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26486
|
+
/* @__PURE__ */ jsx(
|
|
26487
|
+
"label",
|
|
26488
|
+
{
|
|
26489
|
+
htmlFor: "share-invitation",
|
|
26490
|
+
className: "block text-[12px] font-medium text-foreground",
|
|
26491
|
+
children: t("pptx.share.invitationLabel")
|
|
26492
|
+
}
|
|
26493
|
+
),
|
|
26494
|
+
/* @__PURE__ */ jsx(
|
|
26495
|
+
"input",
|
|
26496
|
+
{
|
|
26497
|
+
id: "share-invitation",
|
|
26498
|
+
type: "text",
|
|
26499
|
+
value: invitation,
|
|
26500
|
+
onChange: (event) => onInvitationChange(event.target.value),
|
|
26501
|
+
placeholder: t("pptx.share.invitationPlaceholder"),
|
|
26502
|
+
className: "w-full px-3 py-1.5 rounded border border-border bg-background text-foreground text-[13px] placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary"
|
|
26503
|
+
}
|
|
26504
|
+
),
|
|
26505
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: t("pptx.share.invitationHint") })
|
|
26506
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26507
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "share-room-id", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.sessionName") }),
|
|
26508
|
+
/* @__PURE__ */ jsx(
|
|
26509
|
+
"input",
|
|
26510
|
+
{
|
|
26511
|
+
id: "share-room-id",
|
|
26512
|
+
type: "text",
|
|
26513
|
+
"aria-label": t("pptx.share.sessionName"),
|
|
26514
|
+
value: roomId,
|
|
26515
|
+
onChange: (e) => onRoomIdChange(e.target.value),
|
|
26516
|
+
readOnly: preconfigured,
|
|
26517
|
+
placeholder: t("pptx.share.sessionPlaceholder"),
|
|
26518
|
+
className: `w-full px-3 py-1.5 rounded border border-border bg-background text-foreground text-[13px] placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary${inputReadOnlyClass}`
|
|
26519
|
+
}
|
|
26520
|
+
),
|
|
26521
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: t("pptx.share.sessionHint") })
|
|
26522
|
+
] }),
|
|
26523
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26524
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "share-user-name", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.displayName") }),
|
|
26525
|
+
/* @__PURE__ */ jsx(
|
|
26526
|
+
"input",
|
|
26527
|
+
{
|
|
26528
|
+
id: "share-user-name",
|
|
26529
|
+
type: "text",
|
|
26530
|
+
"aria-label": t("pptx.share.displayName"),
|
|
26531
|
+
value: userName,
|
|
26532
|
+
onChange: (e) => onUserNameChange(e.target.value),
|
|
26533
|
+
readOnly: preconfigured,
|
|
26534
|
+
placeholder: t("pptx.share.namePlaceholder"),
|
|
26535
|
+
className: `w-full px-3 py-1.5 rounded border border-border bg-background text-foreground text-[13px] placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary${inputReadOnlyClass}`
|
|
26536
|
+
}
|
|
26537
|
+
)
|
|
26538
|
+
] }),
|
|
26539
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26540
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "share-server-url", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.serverLabel") }),
|
|
26541
|
+
/* @__PURE__ */ jsx(
|
|
26542
|
+
"input",
|
|
26543
|
+
{
|
|
26544
|
+
id: "share-server-url",
|
|
26545
|
+
type: "text",
|
|
26546
|
+
"aria-label": t("pptx.share.serverLabel"),
|
|
26547
|
+
value: serverUrl,
|
|
26548
|
+
onChange: (e) => onServerUrlChange(e.target.value),
|
|
26549
|
+
readOnly: preconfigured,
|
|
26550
|
+
placeholder: t("pptx.share.serverPlaceholder"),
|
|
26551
|
+
className: `w-full px-3 py-1.5 rounded border border-border bg-background text-foreground text-[13px] placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary${inputReadOnlyClass}`
|
|
26552
|
+
}
|
|
26553
|
+
)
|
|
26554
|
+
] }),
|
|
26555
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: serverUrl.trim().length === 0 ? t("pptx.share.p2pHint") : t("pptx.share.serverHint") })
|
|
26556
|
+
] });
|
|
26557
|
+
}
|
|
26558
|
+
function shareUrl2(config) {
|
|
26559
|
+
return buildCollaborationShareUrl(
|
|
26560
|
+
config,
|
|
26561
|
+
typeof window === "undefined" ? void 0 : { origin: window.location.origin, pathname: window.location.pathname }
|
|
26562
|
+
);
|
|
25811
26563
|
}
|
|
25812
26564
|
function ShareDialog({
|
|
25813
26565
|
open,
|
|
@@ -25826,55 +26578,34 @@ function ShareDialog({
|
|
|
25826
26578
|
const [roomId, setRoomId] = useState(defaultRoomId ?? "");
|
|
25827
26579
|
const [userName, setUserName] = useState(defaultUserName ?? "");
|
|
25828
26580
|
const [serverUrl, setServerUrl] = useState(defaultServerUrl ?? "");
|
|
26581
|
+
const [mode, setMode] = useState("create");
|
|
26582
|
+
const [invitation, setInvitation] = useState("");
|
|
25829
26583
|
const [copied, setCopied] = useState(false);
|
|
25830
26584
|
const dialogRef = useRef(null);
|
|
25831
26585
|
const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
|
|
26586
|
+
useModalFocus(open, dialogRef, onClose);
|
|
25832
26587
|
useEffect(() => {
|
|
25833
26588
|
if (activeCollaboration) {
|
|
25834
|
-
setRoomId(activeCollaboration.roomId);
|
|
25835
|
-
setUserName(activeCollaboration.userName);
|
|
25836
|
-
setServerUrl(activeCollaboration.serverUrl);
|
|
25837
|
-
}
|
|
25838
|
-
}, [activeCollaboration]);
|
|
25839
|
-
useEffect(() => {
|
|
25840
|
-
if (!open) {
|
|
25841
|
-
return;
|
|
25842
|
-
}
|
|
25843
|
-
function handleKeyDown(e) {
|
|
25844
|
-
if (e.key === "Escape") {
|
|
25845
|
-
onClose();
|
|
25846
|
-
}
|
|
25847
|
-
}
|
|
25848
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
25849
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
25850
|
-
}, [open, onClose]);
|
|
25851
|
-
useEffect(() => {
|
|
25852
|
-
if (open && dialogRef.current) {
|
|
25853
|
-
dialogRef.current.focus();
|
|
26589
|
+
setRoomId(activeCollaboration.roomId);
|
|
26590
|
+
setUserName(activeCollaboration.userName);
|
|
26591
|
+
setServerUrl(activeCollaboration.serverUrl);
|
|
25854
26592
|
}
|
|
25855
|
-
}, [
|
|
26593
|
+
}, [activeCollaboration]);
|
|
25856
26594
|
const handleCopyRoomId = useCallback(() => {
|
|
25857
26595
|
const config = activeCollaboration ?? { roomId, serverUrl };
|
|
25858
|
-
void navigator.clipboard.writeText(
|
|
26596
|
+
void navigator.clipboard.writeText(shareUrl2(config)).then(() => {
|
|
25859
26597
|
setCopied(true);
|
|
25860
26598
|
setTimeout(() => setCopied(false), 2e3);
|
|
25861
26599
|
return void 0;
|
|
25862
26600
|
});
|
|
25863
26601
|
}, [activeCollaboration, roomId, serverUrl]);
|
|
25864
26602
|
const handleStartSharing = useCallback(() => {
|
|
25865
|
-
|
|
25866
|
-
|
|
26603
|
+
const config = mode === "join" ? buildJoinCollaborationConfig({ invitation, userName, serverUrl }) : buildCreateCollaborationConfig({ roomId, userName, serverUrl });
|
|
26604
|
+
if (config) {
|
|
26605
|
+
onStartCollaboration?.(config);
|
|
25867
26606
|
}
|
|
25868
|
-
|
|
25869
|
-
|
|
25870
|
-
roomId: roomId.trim(),
|
|
25871
|
-
serverUrl: trimmedServer,
|
|
25872
|
-
userName: userName.trim(),
|
|
25873
|
-
// A blank server selects the serverless peer-to-peer transport.
|
|
25874
|
-
transport: resolveTransportForServerUrl(trimmedServer)
|
|
25875
|
-
});
|
|
25876
|
-
}, [roomId, userName, serverUrl, onStartCollaboration]);
|
|
25877
|
-
const canStart = roomId.trim().length > 0 && userName.trim().length > 0;
|
|
26607
|
+
}, [invitation, mode, roomId, userName, serverUrl, onStartCollaboration]);
|
|
26608
|
+
const canStart = (mode === "join" ? buildJoinCollaborationConfig({ invitation, userName, serverUrl }) : buildCreateCollaborationConfig({ roomId, userName, serverUrl })) !== null;
|
|
25878
26609
|
if (!open) {
|
|
25879
26610
|
return null;
|
|
25880
26611
|
}
|
|
@@ -25937,12 +26668,16 @@ function ShareDialog({
|
|
|
25937
26668
|
) : /* @__PURE__ */ jsx(
|
|
25938
26669
|
StartSessionForm,
|
|
25939
26670
|
{
|
|
26671
|
+
mode,
|
|
26672
|
+
invitation,
|
|
25940
26673
|
roomId,
|
|
25941
26674
|
userName,
|
|
25942
26675
|
serverUrl,
|
|
25943
26676
|
onRoomIdChange: setRoomId,
|
|
25944
26677
|
onUserNameChange: setUserName,
|
|
25945
26678
|
onServerUrlChange: setServerUrl,
|
|
26679
|
+
onModeChange: setMode,
|
|
26680
|
+
onInvitationChange: setInvitation,
|
|
25946
26681
|
preconfigured,
|
|
25947
26682
|
connectionFailed: collab?.status === "error",
|
|
25948
26683
|
onRetry: collab?.retry
|
|
@@ -25965,7 +26700,7 @@ function ShareDialog({
|
|
|
25965
26700
|
disabled: !canStart,
|
|
25966
26701
|
onClick: handleStartSharing,
|
|
25967
26702
|
className: "px-3 py-1.5 rounded bg-primary hover:bg-primary/90 text-[12px] text-white transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
|
|
25968
|
-
children: t("pptx.share.startSharing")
|
|
26703
|
+
children: t(mode === "join" ? "pptx.share.joinSession" : "pptx.share.startSharing")
|
|
25969
26704
|
}
|
|
25970
26705
|
)
|
|
25971
26706
|
] })
|
|
@@ -25976,199 +26711,6 @@ function ShareDialog({
|
|
|
25976
26711
|
)
|
|
25977
26712
|
] });
|
|
25978
26713
|
}
|
|
25979
|
-
function StartSessionForm({
|
|
25980
|
-
roomId,
|
|
25981
|
-
userName,
|
|
25982
|
-
serverUrl,
|
|
25983
|
-
onRoomIdChange,
|
|
25984
|
-
onUserNameChange,
|
|
25985
|
-
onServerUrlChange,
|
|
25986
|
-
preconfigured,
|
|
25987
|
-
connectionFailed,
|
|
25988
|
-
onRetry
|
|
25989
|
-
}) {
|
|
25990
|
-
const { t } = useTranslation();
|
|
25991
|
-
const inputReadOnlyClass = preconfigured ? " opacity-70 cursor-not-allowed" : "";
|
|
25992
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
25993
|
-
/* @__PURE__ */ jsx("p", { className: "text-[13px] text-muted-foreground leading-relaxed", children: preconfigured ? t("pptx.share.preconfiguredDescription") : t("pptx.share.description") }),
|
|
25994
|
-
connectionFailed && /* @__PURE__ */ jsxs(
|
|
25995
|
-
"div",
|
|
25996
|
-
{
|
|
25997
|
-
role: "alert",
|
|
25998
|
-
className: "flex items-start gap-2 rounded border border-red-500/30 bg-red-500/10 px-3 py-2 text-[12px] text-red-400",
|
|
25999
|
-
children: [
|
|
26000
|
-
/* @__PURE__ */ jsx(LuWifiOff, { className: "w-4 h-4 mt-0.5 shrink-0" }),
|
|
26001
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1", children: [
|
|
26002
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium", children: t("pptx.share.connectionError") }),
|
|
26003
|
-
onRetry && /* @__PURE__ */ jsx(
|
|
26004
|
-
"button",
|
|
26005
|
-
{
|
|
26006
|
-
type: "button",
|
|
26007
|
-
onClick: onRetry,
|
|
26008
|
-
className: "underline underline-offset-2 hover:no-underline",
|
|
26009
|
-
children: t("pptx.collaboration.retry")
|
|
26010
|
-
}
|
|
26011
|
-
)
|
|
26012
|
-
] })
|
|
26013
|
-
]
|
|
26014
|
-
}
|
|
26015
|
-
),
|
|
26016
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26017
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "share-room-id", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.sessionName") }),
|
|
26018
|
-
/* @__PURE__ */ jsx(
|
|
26019
|
-
"input",
|
|
26020
|
-
{
|
|
26021
|
-
id: "share-room-id",
|
|
26022
|
-
type: "text",
|
|
26023
|
-
"aria-label": t("pptx.share.sessionName"),
|
|
26024
|
-
value: roomId,
|
|
26025
|
-
onChange: (e) => onRoomIdChange(e.target.value),
|
|
26026
|
-
readOnly: preconfigured,
|
|
26027
|
-
placeholder: t("pptx.share.sessionPlaceholder"),
|
|
26028
|
-
className: `w-full px-3 py-1.5 rounded border border-border bg-background text-foreground text-[13px] placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary${inputReadOnlyClass}`
|
|
26029
|
-
}
|
|
26030
|
-
),
|
|
26031
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: t("pptx.share.sessionHint") })
|
|
26032
|
-
] }),
|
|
26033
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26034
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "share-user-name", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.displayName") }),
|
|
26035
|
-
/* @__PURE__ */ jsx(
|
|
26036
|
-
"input",
|
|
26037
|
-
{
|
|
26038
|
-
id: "share-user-name",
|
|
26039
|
-
type: "text",
|
|
26040
|
-
"aria-label": t("pptx.share.displayName"),
|
|
26041
|
-
value: userName,
|
|
26042
|
-
onChange: (e) => onUserNameChange(e.target.value),
|
|
26043
|
-
readOnly: preconfigured,
|
|
26044
|
-
placeholder: t("pptx.share.namePlaceholder"),
|
|
26045
|
-
className: `w-full px-3 py-1.5 rounded border border-border bg-background text-foreground text-[13px] placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary${inputReadOnlyClass}`
|
|
26046
|
-
}
|
|
26047
|
-
)
|
|
26048
|
-
] }),
|
|
26049
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26050
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "share-server-url", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.serverLabel") }),
|
|
26051
|
-
/* @__PURE__ */ jsx(
|
|
26052
|
-
"input",
|
|
26053
|
-
{
|
|
26054
|
-
id: "share-server-url",
|
|
26055
|
-
type: "text",
|
|
26056
|
-
"aria-label": t("pptx.share.serverLabel"),
|
|
26057
|
-
value: serverUrl,
|
|
26058
|
-
onChange: (e) => onServerUrlChange(e.target.value),
|
|
26059
|
-
readOnly: preconfigured,
|
|
26060
|
-
placeholder: t("pptx.share.serverPlaceholder"),
|
|
26061
|
-
className: `w-full px-3 py-1.5 rounded border border-border bg-background text-foreground text-[13px] placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary${inputReadOnlyClass}`
|
|
26062
|
-
}
|
|
26063
|
-
)
|
|
26064
|
-
] }),
|
|
26065
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: serverUrl.trim().length === 0 ? t("pptx.share.p2pHint") : t("pptx.share.serverHint") })
|
|
26066
|
-
] });
|
|
26067
|
-
}
|
|
26068
|
-
function ActiveSessionView({
|
|
26069
|
-
collab,
|
|
26070
|
-
activeCollaboration,
|
|
26071
|
-
copied,
|
|
26072
|
-
onCopyRoomId,
|
|
26073
|
-
onStopCollaboration
|
|
26074
|
-
}) {
|
|
26075
|
-
const { t } = useTranslation();
|
|
26076
|
-
const statusColor = collab.status === "connected" ? "text-green-400" : collab.status === "connecting" ? "text-yellow-400" : "text-red-400";
|
|
26077
|
-
const statusIcon = collab.status === "connected" || collab.status === "connecting" ? /* @__PURE__ */ jsx(LuWifi, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(LuWifiOff, { className: "w-4 h-4" });
|
|
26078
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
26079
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26080
|
-
/* @__PURE__ */ jsx("span", { className: statusColor, children: statusIcon }),
|
|
26081
|
-
/* @__PURE__ */ jsx("span", { className: "text-[13px] font-medium text-foreground capitalize", children: collab.status }),
|
|
26082
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[12px] text-muted-foreground ml-auto flex items-center gap-1", children: [
|
|
26083
|
-
/* @__PURE__ */ jsx(LuUsers, { className: "w-3.5 h-3.5" }),
|
|
26084
|
-
t("pptx.collaboration.userCount", { count: collab.connectedCount })
|
|
26085
|
-
] })
|
|
26086
|
-
] }),
|
|
26087
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26088
|
-
/* @__PURE__ */ jsx("label", { className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.shareLink") }),
|
|
26089
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26090
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 px-3 py-1.5 rounded border border-border bg-background text-[11px] text-foreground select-all font-mono truncate", children: buildCollabShareUrl(collab.config) }),
|
|
26091
|
-
/* @__PURE__ */ jsx(
|
|
26092
|
-
"button",
|
|
26093
|
-
{
|
|
26094
|
-
type: "button",
|
|
26095
|
-
onClick: onCopyRoomId,
|
|
26096
|
-
className: "flex items-center gap-1 px-2.5 py-1.5 rounded border border-border bg-muted hover:bg-accent text-[12px] text-foreground transition-colors shrink-0",
|
|
26097
|
-
title: t("pptx.share.copyLink"),
|
|
26098
|
-
children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26099
|
-
/* @__PURE__ */ jsx(LuCheck, { className: "w-3.5 h-3.5 text-green-400" }),
|
|
26100
|
-
/* @__PURE__ */ jsx("span", { children: t("pptx.share.copied") })
|
|
26101
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26102
|
-
/* @__PURE__ */ jsx(LuCopy, { className: "w-3.5 h-3.5" }),
|
|
26103
|
-
/* @__PURE__ */ jsx("span", { children: t("pptx.share.copyUrl") })
|
|
26104
|
-
] })
|
|
26105
|
-
}
|
|
26106
|
-
)
|
|
26107
|
-
] }),
|
|
26108
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: t("pptx.share.shareHint") })
|
|
26109
|
-
] }),
|
|
26110
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[11px] text-muted-foreground", children: [
|
|
26111
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
26112
|
-
t("pptx.share.room"),
|
|
26113
|
-
" ",
|
|
26114
|
-
/* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: collab.config.roomId })
|
|
26115
|
-
] }),
|
|
26116
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
26117
|
-
t("pptx.share.server"),
|
|
26118
|
-
" ",
|
|
26119
|
-
/* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: isP2P(collab.config) ? t("pptx.share.p2pServerValue") : collab.config.serverUrl })
|
|
26120
|
-
] })
|
|
26121
|
-
] }),
|
|
26122
|
-
collab.remoteUsers.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26123
|
-
/* @__PURE__ */ jsx("label", { className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.connectedUsers") }),
|
|
26124
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded border border-border bg-background divide-y divide-border max-h-[140px] overflow-y-auto", children: [
|
|
26125
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [
|
|
26126
|
-
/* @__PURE__ */ jsx(
|
|
26127
|
-
"div",
|
|
26128
|
-
{
|
|
26129
|
-
className: "w-6 h-6 rounded-full flex items-center justify-center text-[9px] font-semibold text-white shrink-0",
|
|
26130
|
-
style: { backgroundColor: collab.config.userColor ?? "#6366f1" },
|
|
26131
|
-
children: getInitials3(activeCollaboration?.userName ?? collab.config.userName)
|
|
26132
|
-
}
|
|
26133
|
-
),
|
|
26134
|
-
/* @__PURE__ */ jsx("span", { className: "text-[12px] text-foreground truncate", children: activeCollaboration?.userName ?? collab.config.userName }),
|
|
26135
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground ml-auto", children: t("pptx.share.you") })
|
|
26136
|
-
] }),
|
|
26137
|
-
collab.remoteUsers.map((user) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [
|
|
26138
|
-
/* @__PURE__ */ jsx(
|
|
26139
|
-
"div",
|
|
26140
|
-
{
|
|
26141
|
-
className: "w-6 h-6 rounded-full flex items-center justify-center text-[9px] font-semibold text-white shrink-0",
|
|
26142
|
-
style: { backgroundColor: user.userColor },
|
|
26143
|
-
children: user.userAvatar ? /* @__PURE__ */ jsx(
|
|
26144
|
-
"img",
|
|
26145
|
-
{
|
|
26146
|
-
src: user.userAvatar,
|
|
26147
|
-
alt: "",
|
|
26148
|
-
className: "w-full h-full rounded-full object-cover"
|
|
26149
|
-
}
|
|
26150
|
-
) : getInitials3(user.userName)
|
|
26151
|
-
}
|
|
26152
|
-
),
|
|
26153
|
-
/* @__PURE__ */ jsx("span", { className: "text-[12px] text-foreground truncate", children: user.userName }),
|
|
26154
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground ml-auto", children: [
|
|
26155
|
-
"Slide ",
|
|
26156
|
-
user.activeSlideIndex + 1
|
|
26157
|
-
] })
|
|
26158
|
-
] }, user.clientId))
|
|
26159
|
-
] })
|
|
26160
|
-
] }),
|
|
26161
|
-
onStopCollaboration && /* @__PURE__ */ jsx(
|
|
26162
|
-
"button",
|
|
26163
|
-
{
|
|
26164
|
-
type: "button",
|
|
26165
|
-
onClick: onStopCollaboration,
|
|
26166
|
-
className: "w-full px-3 py-2 rounded border border-red-500/30 bg-red-500/10 hover:bg-red-500/20 text-[12px] text-red-400 font-medium transition-colors",
|
|
26167
|
-
children: t("pptx.share.stopSharing")
|
|
26168
|
-
}
|
|
26169
|
-
)
|
|
26170
|
-
] });
|
|
26171
|
-
}
|
|
26172
26714
|
function HyperlinkTabContent({
|
|
26173
26715
|
targetType,
|
|
26174
26716
|
url,
|
|
@@ -27790,7 +28332,7 @@ function SlideCanvas({
|
|
|
27790
28332
|
// pinch-zoom. View/present mode keeps the default so the slide can
|
|
27791
28333
|
// still be scrolled and swipe-navigated.
|
|
27792
28334
|
touchAction: isEditableCanvas ? "none" : void 0,
|
|
27793
|
-
...
|
|
28335
|
+
...getReactSlideBackgroundStyle(activeSlide)
|
|
27794
28336
|
},
|
|
27795
28337
|
onClick: handleStageClick,
|
|
27796
28338
|
onDoubleClick: handleStageDblClick,
|
|
@@ -28117,6 +28659,7 @@ function ViewerInspector({
|
|
|
28117
28659
|
return /* @__PURE__ */ jsx(
|
|
28118
28660
|
"div",
|
|
28119
28661
|
{
|
|
28662
|
+
"data-pptx-inspector": true,
|
|
28120
28663
|
role: "complementary",
|
|
28121
28664
|
"aria-label": t("pptx.inspector.properties"),
|
|
28122
28665
|
className: "h-full flex-shrink-0 max-md:absolute max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:z-30",
|
|
@@ -28969,10 +29512,11 @@ function EquationEditorDialog({
|
|
|
28969
29512
|
const [latex, setLatex] = useState(initialLatex);
|
|
28970
29513
|
const deferredLatex = useDeferredValue(latex);
|
|
28971
29514
|
const textareaRef = useRef(null);
|
|
29515
|
+
const dialogRef = useRef(null);
|
|
29516
|
+
useModalFocus(isOpen, dialogRef, onClose, textareaRef);
|
|
28972
29517
|
useEffect(() => {
|
|
28973
29518
|
if (isOpen) {
|
|
28974
29519
|
setLatex(initialLatex);
|
|
28975
|
-
setTimeout(() => textareaRef.current?.focus(), 50);
|
|
28976
29520
|
}
|
|
28977
29521
|
}, [isOpen, initialLatex]);
|
|
28978
29522
|
const { mathml, omml } = useMemo(() => {
|
|
@@ -29036,11 +29580,13 @@ function EquationEditorDialog({
|
|
|
29036
29580
|
children: /* @__PURE__ */ jsxs(
|
|
29037
29581
|
"div",
|
|
29038
29582
|
{
|
|
29583
|
+
ref: dialogRef,
|
|
29039
29584
|
style: panelStyle,
|
|
29040
29585
|
className: "bg-background border border-border rounded-xl shadow-2xl w-[640px] max-h-[85vh] flex flex-col overflow-hidden 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: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)]",
|
|
29041
29586
|
onClick: (e) => e.stopPropagation(),
|
|
29042
29587
|
role: "dialog",
|
|
29043
29588
|
"aria-modal": "true",
|
|
29589
|
+
tabIndex: -1,
|
|
29044
29590
|
"aria-label": isEditing ? t("pptx.equation.editTitle", "Edit Equation") : t("pptx.equation.insertTitle", "Insert Equation"),
|
|
29045
29591
|
children: [
|
|
29046
29592
|
/* @__PURE__ */ jsxs(
|
|
@@ -29056,6 +29602,7 @@ function EquationEditorDialog({
|
|
|
29056
29602
|
type: "button",
|
|
29057
29603
|
onClick: onClose,
|
|
29058
29604
|
className: "p-1 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
29605
|
+
"aria-label": t("pptx.settings.close"),
|
|
29059
29606
|
children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
|
|
29060
29607
|
}
|
|
29061
29608
|
)
|
|
@@ -29190,6 +29737,8 @@ function InsertSmartArtDialog({
|
|
|
29190
29737
|
const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
|
|
29191
29738
|
const [activeCategory, setActiveCategory] = useState("list");
|
|
29192
29739
|
const [selectedLayout, setSelectedLayout] = useState(null);
|
|
29740
|
+
const dialogRef = useRef(null);
|
|
29741
|
+
useModalFocus(isOpen, dialogRef, onClose);
|
|
29193
29742
|
const filteredPresets = PRESETS.filter((p) => p.category === activeCategory);
|
|
29194
29743
|
const handleInsert = useCallback(() => {
|
|
29195
29744
|
if (!selectedLayout) {
|
|
@@ -29224,11 +29773,13 @@ function InsertSmartArtDialog({
|
|
|
29224
29773
|
children: /* @__PURE__ */ jsxs(
|
|
29225
29774
|
"div",
|
|
29226
29775
|
{
|
|
29776
|
+
ref: dialogRef,
|
|
29227
29777
|
style: panelStyle,
|
|
29228
29778
|
className: "pointer-events-auto w-[600px] max-w-[90vw] max-h-[80vh] rounded-lg border border-border bg-background shadow-2xl flex flex-col max-md:fixed max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:w-full max-md:max-w-none max-md:max-h-[88dvh] max-md:rounded-t-2xl max-md:rounded-b-none max-md:border-x-0 max-md:border-b-0 max-md:pb-[max(env(safe-area-inset-bottom),0px)]",
|
|
29229
29779
|
role: "dialog",
|
|
29230
29780
|
"aria-modal": "true",
|
|
29231
29781
|
"aria-label": t("pptx.smartart.insertTitle"),
|
|
29782
|
+
tabIndex: -1,
|
|
29232
29783
|
children: [
|
|
29233
29784
|
/* @__PURE__ */ jsxs(
|
|
29234
29785
|
"div",
|
|
@@ -29251,43 +29802,60 @@ function InsertSmartArtDialog({
|
|
|
29251
29802
|
}
|
|
29252
29803
|
),
|
|
29253
29804
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
|
|
29254
|
-
/* @__PURE__ */ jsx(
|
|
29255
|
-
"
|
|
29805
|
+
/* @__PURE__ */ jsx(
|
|
29806
|
+
"nav",
|
|
29256
29807
|
{
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
|
|
29260
|
-
|
|
29261
|
-
|
|
29262
|
-
|
|
29263
|
-
|
|
29264
|
-
|
|
29265
|
-
|
|
29266
|
-
|
|
29267
|
-
|
|
29268
|
-
|
|
29269
|
-
|
|
29270
|
-
|
|
29271
|
-
|
|
29808
|
+
className: "w-40 border-r border-border py-2",
|
|
29809
|
+
"aria-label": t("pptx.insertSmartArt.categories"),
|
|
29810
|
+
children: CATEGORIES.map((cat) => /* @__PURE__ */ jsx(
|
|
29811
|
+
"button",
|
|
29812
|
+
{
|
|
29813
|
+
type: "button",
|
|
29814
|
+
onClick: () => {
|
|
29815
|
+
setActiveCategory(cat.id);
|
|
29816
|
+
setSelectedLayout(null);
|
|
29817
|
+
},
|
|
29818
|
+
className: cn(
|
|
29819
|
+
"w-full text-left px-3 py-1.5 text-xs transition-colors",
|
|
29820
|
+
activeCategory === cat.id ? "bg-primary text-white" : "text-foreground hover:bg-muted"
|
|
29821
|
+
),
|
|
29822
|
+
children: t(cat.label)
|
|
29823
|
+
},
|
|
29824
|
+
cat.id
|
|
29825
|
+
))
|
|
29826
|
+
}
|
|
29827
|
+
),
|
|
29828
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 p-3 overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
29829
|
+
"div",
|
|
29272
29830
|
{
|
|
29273
|
-
|
|
29274
|
-
|
|
29275
|
-
|
|
29276
|
-
|
|
29277
|
-
|
|
29278
|
-
|
|
29279
|
-
|
|
29280
|
-
|
|
29281
|
-
|
|
29282
|
-
|
|
29283
|
-
|
|
29284
|
-
|
|
29285
|
-
|
|
29286
|
-
|
|
29287
|
-
|
|
29288
|
-
|
|
29289
|
-
|
|
29290
|
-
|
|
29831
|
+
className: "grid grid-cols-3 gap-2",
|
|
29832
|
+
role: "listbox",
|
|
29833
|
+
"aria-label": t("pptx.insertSmartArt.layouts"),
|
|
29834
|
+
children: filteredPresets.map((preset) => /* @__PURE__ */ jsxs(
|
|
29835
|
+
"button",
|
|
29836
|
+
{
|
|
29837
|
+
type: "button",
|
|
29838
|
+
role: "option",
|
|
29839
|
+
"aria-selected": selectedLayout === preset.layout,
|
|
29840
|
+
onClick: () => setSelectedLayout(preset.layout),
|
|
29841
|
+
onDoubleClick: () => {
|
|
29842
|
+
setSelectedLayout(preset.layout);
|
|
29843
|
+
onInsert(preset.layout, preset.defaultItems);
|
|
29844
|
+
onClose();
|
|
29845
|
+
},
|
|
29846
|
+
className: cn(
|
|
29847
|
+
"flex flex-col items-center gap-1 p-2 rounded border transition-colors",
|
|
29848
|
+
selectedLayout === preset.layout ? "border-primary bg-primary/20" : "border-border hover:border-border hover:bg-muted/50"
|
|
29849
|
+
),
|
|
29850
|
+
children: [
|
|
29851
|
+
/* @__PURE__ */ jsx("div", { className: "w-16 h-12 flex items-center justify-center bg-muted rounded", children: getPreviewForLayout(preset.layout) }),
|
|
29852
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-foreground text-center leading-tight", children: t(preset.labelKey) })
|
|
29853
|
+
]
|
|
29854
|
+
},
|
|
29855
|
+
preset.layout
|
|
29856
|
+
))
|
|
29857
|
+
}
|
|
29858
|
+
) })
|
|
29291
29859
|
] }),
|
|
29292
29860
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-border", children: [
|
|
29293
29861
|
/* @__PURE__ */ jsx(
|
|
@@ -29510,9 +30078,19 @@ function ViewerDialogGroup(props) {
|
|
|
29510
30078
|
] });
|
|
29511
30079
|
}
|
|
29512
30080
|
function ViewerPresentationLayer(props) {
|
|
29513
|
-
const {
|
|
30081
|
+
const {
|
|
30082
|
+
mode,
|
|
30083
|
+
slides,
|
|
30084
|
+
canvasSize,
|
|
30085
|
+
templateElements,
|
|
30086
|
+
presentation,
|
|
30087
|
+
onExitPresentation,
|
|
30088
|
+
isMobile,
|
|
30089
|
+
onUpdateNotes
|
|
30090
|
+
} = props;
|
|
29514
30091
|
const presenterActive = mode === "present" && presentation.presenterMode;
|
|
29515
30092
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
30093
|
+
mode === "present" && !presentation.presenterMode && /* @__PURE__ */ jsx(PresentationAudienceEffects, { snapshot: presentation.presenterSnapshot }),
|
|
29516
30094
|
presenterActive && (isMobile ? /* @__PURE__ */ jsx(
|
|
29517
30095
|
MobilePresenterView,
|
|
29518
30096
|
{
|
|
@@ -29536,7 +30114,20 @@ function ViewerPresentationLayer(props) {
|
|
|
29536
30114
|
onExit: onExitPresentation,
|
|
29537
30115
|
onOpenAudienceWindow: presentation.openAudienceWindow,
|
|
29538
30116
|
onCloseAudienceWindow: presentation.closeAudienceWindow,
|
|
29539
|
-
isAudienceWindowOpen: presentation.isAudienceWindowOpen()
|
|
30117
|
+
isAudienceWindowOpen: presentation.isAudienceWindowOpen(),
|
|
30118
|
+
snapshot: presentation.presenterSnapshot,
|
|
30119
|
+
onNavigateToSlide: presentation.navigateToSlide,
|
|
30120
|
+
onToggleTimer: presentation.togglePresenterTimer,
|
|
30121
|
+
onResetTimer: presentation.resetPresenterTimer,
|
|
30122
|
+
onStepZoom: presentation.stepPresenterZoom,
|
|
30123
|
+
onResetZoom: presentation.resetPresenterZoom,
|
|
30124
|
+
onSetBlackout: presentation.setPresenterBlackout,
|
|
30125
|
+
onUpdateSnapshot: presentation.updatePresenterSnapshot,
|
|
30126
|
+
onToggleSubtitles: () => presentation.setPresenterSubtitlesVisible(
|
|
30127
|
+
!presentation.presenterSnapshot.subtitlesVisible
|
|
30128
|
+
),
|
|
30129
|
+
onSwapDisplays: () => void presentation.swapPresenterDisplays(),
|
|
30130
|
+
onUpdateNotes
|
|
29540
30131
|
}
|
|
29541
30132
|
)),
|
|
29542
30133
|
mode === "present" && presentation.rehearsing && /* @__PURE__ */ jsx(
|
|
@@ -29714,7 +30305,7 @@ function ViewerCanvasArea(props) {
|
|
|
29714
30305
|
{
|
|
29715
30306
|
handoutMaster: s.handoutMaster,
|
|
29716
30307
|
canvasSize,
|
|
29717
|
-
slidesPerPage: s.handoutSlidesPerPage
|
|
30308
|
+
slidesPerPage: s.handoutMaster?.slidesPerPage ?? s.handoutSlidesPerPage
|
|
29718
30309
|
}
|
|
29719
30310
|
) : /* @__PURE__ */ jsx(
|
|
29720
30311
|
SlideCanvas,
|
|
@@ -30761,6 +31352,11 @@ function ThemeGallery({
|
|
|
30761
31352
|
const { t } = useTranslation();
|
|
30762
31353
|
const [selectedTheme, setSelectedTheme] = useState(currentTheme ?? null);
|
|
30763
31354
|
const fileInputRef = useRef(null);
|
|
31355
|
+
useEffect(() => {
|
|
31356
|
+
if (open) {
|
|
31357
|
+
setSelectedTheme(currentTheme ?? null);
|
|
31358
|
+
}
|
|
31359
|
+
}, [currentTheme, open]);
|
|
30764
31360
|
if (!open) {
|
|
30765
31361
|
return null;
|
|
30766
31362
|
}
|
|
@@ -30888,6 +31484,9 @@ function ViewerSidePanels(props) {
|
|
|
30888
31484
|
onResizeRight
|
|
30889
31485
|
} = props;
|
|
30890
31486
|
const effectiveSlide = mode === "master" ? masterPseudoSlide : activeSlide;
|
|
31487
|
+
const currentBuiltInTheme = BUILT_IN_THEMES.find(
|
|
31488
|
+
(candidate) => themeColorSchemesEqual(s.theme?.colorScheme, candidate.colorScheme)
|
|
31489
|
+
) ?? null;
|
|
30891
31490
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
30892
31491
|
(mode === "edit" || mode === "master") && s.isInspectorPaneOpen && onResizeRight && /* @__PURE__ */ jsx(ResizeHandle, { direction: "horizontal", onResize: onResizeRight }),
|
|
30893
31492
|
/* @__PURE__ */ jsx(
|
|
@@ -30985,7 +31584,7 @@ function ViewerSidePanels(props) {
|
|
|
30985
31584
|
ThemeGallery,
|
|
30986
31585
|
{
|
|
30987
31586
|
open: s.isThemeGalleryOpen,
|
|
30988
|
-
currentTheme:
|
|
31587
|
+
currentTheme: currentBuiltInTheme,
|
|
30989
31588
|
canEdit,
|
|
30990
31589
|
onClose: () => s.setIsThemeGalleryOpen(false),
|
|
30991
31590
|
onApplyTheme: (theme) => {
|
|
@@ -31089,12 +31688,28 @@ function ViewerMainContent(props) {
|
|
|
31089
31688
|
masterViewTab: state.masterViewTab,
|
|
31090
31689
|
notesMaster: state.notesMaster,
|
|
31091
31690
|
handoutMaster: state.handoutMaster,
|
|
31092
|
-
handoutSlidesPerPage: state.handoutSlidesPerPage,
|
|
31691
|
+
handoutSlidesPerPage: state.handoutMaster?.slidesPerPage ?? state.handoutSlidesPerPage,
|
|
31093
31692
|
onSelectMaster: dialogs.handleSelectMaster,
|
|
31094
31693
|
onSelectLayout: dialogs.handleSelectLayout,
|
|
31095
|
-
onCollapse:
|
|
31694
|
+
onCollapse: dialogs.handleCloseMasterView,
|
|
31096
31695
|
onTabChange: state.setMasterViewTab,
|
|
31097
|
-
onHandoutSlidesPerPageChange:
|
|
31696
|
+
onHandoutSlidesPerPageChange: (count) => {
|
|
31697
|
+
state.setHandoutSlidesPerPage(count);
|
|
31698
|
+
state.setHandoutMaster(
|
|
31699
|
+
(master) => master ? { ...master, slidesPerPage: count } : master
|
|
31700
|
+
);
|
|
31701
|
+
state.setIsDirty(true);
|
|
31702
|
+
},
|
|
31703
|
+
onNotesMasterBackgroundChange: (backgroundColor) => {
|
|
31704
|
+
state.setNotesMaster((master) => master ? { ...master, backgroundColor } : master);
|
|
31705
|
+
state.setIsDirty(true);
|
|
31706
|
+
},
|
|
31707
|
+
onHandoutMasterBackgroundChange: (backgroundColor) => {
|
|
31708
|
+
state.setHandoutMaster(
|
|
31709
|
+
(master) => master ? { ...master, backgroundColor } : master
|
|
31710
|
+
);
|
|
31711
|
+
state.setIsDirty(true);
|
|
31712
|
+
}
|
|
31098
31713
|
}
|
|
31099
31714
|
),
|
|
31100
31715
|
/* @__PURE__ */ jsx(
|
|
@@ -31225,6 +31840,7 @@ function MobileBottomBar({
|
|
|
31225
31840
|
active ? "text-primary" : "text-muted-foreground hover:text-foreground"
|
|
31226
31841
|
),
|
|
31227
31842
|
"aria-pressed": active,
|
|
31843
|
+
"aria-label": key === "notes" ? t("pptx.statusBar.toggleNotes") : void 0,
|
|
31228
31844
|
children: [
|
|
31229
31845
|
/* @__PURE__ */ jsx(Icon, { className: "w-5 h-5" }),
|
|
31230
31846
|
/* @__PURE__ */ jsx("span", { children: t(label) }),
|
|
@@ -31825,6 +32441,7 @@ var PowerPointViewer = forwardRef(
|
|
|
31825
32441
|
{
|
|
31826
32442
|
style: themeStyle,
|
|
31827
32443
|
"data-pptx-viewer": "",
|
|
32444
|
+
"aria-busy": loading,
|
|
31828
32445
|
className: "h-full w-full bg-background text-foreground relative",
|
|
31829
32446
|
children: [
|
|
31830
32447
|
/* @__PURE__ */ jsx(
|
|
@@ -32051,6 +32668,7 @@ var PowerPointViewer = forwardRef(
|
|
|
32051
32668
|
templateElements: state.templateElements,
|
|
32052
32669
|
presentation,
|
|
32053
32670
|
onExitPresentation: () => handleSetMode("edit"),
|
|
32671
|
+
onUpdateNotes: propertyHandlers.handleUpdateNotes,
|
|
32054
32672
|
isMobile
|
|
32055
32673
|
}
|
|
32056
32674
|
)
|