pptx-react-viewer 1.17.1 → 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 +2 -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-WH7YXV3I.js → chunk-73ST7AC6.js} +2153 -1572
- package/dist/chunk-73ST7AC6.js.br +0 -0
- package/dist/chunk-73ST7AC6.js.gz +0 -0
- package/dist/{chunk-IZXN663G.js → chunk-AALZCSY4.js} +7 -0
- 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-SXCO5HHN.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-PCQH2UBR.mjs → chunk-KMLIWCNL.mjs} +1345 -764
- package/dist/chunk-KMLIWCNL.mjs.br +0 -0
- package/dist/chunk-KMLIWCNL.mjs.gz +0 -0
- package/dist/{chunk-5CD34U2V.mjs → chunk-RIRK64DM.mjs} +7 -0
- 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-HN7CPQUG.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 +0 -0
- package/dist/index.js.gz +0 -0
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.br +0 -0
- 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-5CD34U2V.mjs.br +0 -0
- package/dist/chunk-5CD34U2V.mjs.gz +0 -0
- package/dist/chunk-G22EWPLH.mjs.br +0 -0
- package/dist/chunk-G22EWPLH.mjs.gz +0 -0
- package/dist/chunk-HN7CPQUG.mjs.br +0 -0
- package/dist/chunk-HN7CPQUG.mjs.gz +0 -0
- package/dist/chunk-IZXN663G.js.br +0 -0
- package/dist/chunk-IZXN663G.js.gz +0 -0
- package/dist/chunk-JWS3RQKN.js.br +0 -0
- package/dist/chunk-JWS3RQKN.js.gz +0 -0
- package/dist/chunk-MGLRKGCH.js.br +0 -0
- package/dist/chunk-MGLRKGCH.js.gz +0 -0
- package/dist/chunk-PCQH2UBR.mjs.br +0 -0
- package/dist/chunk-PCQH2UBR.mjs.gz +0 -0
- package/dist/chunk-SXCO5HHN.js.br +0 -0
- package/dist/chunk-SXCO5HHN.js.gz +0 -0
- package/dist/chunk-WH7YXV3I.js.br +0 -0
- package/dist/chunk-WH7YXV3I.js.gz +0 -0
- package/dist/chunk-XRYREYXC.mjs.br +0 -0
- package/dist/chunk-XRYREYXC.mjs.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);
|
|
@@ -466,12 +466,21 @@ function LoadingState({ className }) {
|
|
|
466
466
|
return /* @__PURE__ */ jsx(
|
|
467
467
|
"div",
|
|
468
468
|
{
|
|
469
|
+
role: "status",
|
|
470
|
+
"aria-live": "polite",
|
|
471
|
+
"aria-atomic": "true",
|
|
469
472
|
className: cn(
|
|
470
473
|
"h-full w-full flex items-center justify-center text-muted-foreground",
|
|
471
474
|
className
|
|
472
475
|
),
|
|
473
476
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
474
|
-
/* @__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
|
+
),
|
|
475
484
|
/* @__PURE__ */ jsx("span", { children: t("pptx.viewer.loading") })
|
|
476
485
|
] })
|
|
477
486
|
}
|
|
@@ -481,6 +490,8 @@ function ErrorState({ className, error }) {
|
|
|
481
490
|
return /* @__PURE__ */ jsx(
|
|
482
491
|
"div",
|
|
483
492
|
{
|
|
493
|
+
role: "alert",
|
|
494
|
+
"aria-live": "assertive",
|
|
484
495
|
className: cn(
|
|
485
496
|
"h-full w-full flex items-center justify-center p-6 text-center text-red-400",
|
|
486
497
|
className
|
|
@@ -884,6 +895,17 @@ function ResizeHandle({
|
|
|
884
895
|
}
|
|
885
896
|
);
|
|
886
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
|
+
}
|
|
887
909
|
function DrawingShapeRenderer({
|
|
888
910
|
elementId,
|
|
889
911
|
shapes,
|
|
@@ -2666,7 +2688,7 @@ function SlideThumbnailImpl({
|
|
|
2666
2688
|
"div",
|
|
2667
2689
|
{
|
|
2668
2690
|
className: "relative w-full overflow-hidden rounded border border-border bg-white",
|
|
2669
|
-
style: { height: previewHeight, ...
|
|
2691
|
+
style: { height: previewHeight, ...getReactSlideBackgroundStyle(slide) },
|
|
2670
2692
|
children: /* @__PURE__ */ jsxs(
|
|
2671
2693
|
"div",
|
|
2672
2694
|
{
|
|
@@ -4835,7 +4857,7 @@ function FailedToLoad() {
|
|
|
4835
4857
|
var LazyModel3DScene = React5.lazy(
|
|
4836
4858
|
async () => {
|
|
4837
4859
|
try {
|
|
4838
|
-
return await import('./Model3DScene-
|
|
4860
|
+
return await import('./Model3DScene-JGVLIDLD.mjs');
|
|
4839
4861
|
} catch {
|
|
4840
4862
|
return { default: FailedToLoad };
|
|
4841
4863
|
}
|
|
@@ -5810,7 +5832,7 @@ var ElementRenderer = React5.memo(
|
|
|
5810
5832
|
const cur = effectiveIsInlineEditing ? "cursor-text" : effectiveCanInteract ? elementLocks?.noMove ? "cursor-default" : "cursor-move" : hasAction || isZoom ? "cursor-pointer" : "";
|
|
5811
5833
|
const isPresentationPassive = !effectiveCanInteract;
|
|
5812
5834
|
const isFullscreenMedia = el.type === "media" && Boolean(el.fullScreen) && isPresentationPassive && isMediaPlaying;
|
|
5813
|
-
const ariaRole = getAriaRole(el);
|
|
5835
|
+
const ariaRole = isActionable ? "button" : getAriaRole(el);
|
|
5814
5836
|
const ariaLabel = getAriaLabel(el);
|
|
5815
5837
|
const ariaRoleDescription = getAriaRoleDescription(el);
|
|
5816
5838
|
const isFocusable = effectiveCanInteract || isActionable;
|
|
@@ -5854,6 +5876,10 @@ var ElementRenderer = React5.memo(
|
|
|
5854
5876
|
e.preventDefault();
|
|
5855
5877
|
e.stopPropagation();
|
|
5856
5878
|
onInlineEditCancel();
|
|
5879
|
+
} else if ((e.key === "Enter" || e.key === " ") && isActionable) {
|
|
5880
|
+
e.preventDefault();
|
|
5881
|
+
e.stopPropagation();
|
|
5882
|
+
e.currentTarget.click();
|
|
5857
5883
|
}
|
|
5858
5884
|
},
|
|
5859
5885
|
onClick: (e) => {
|
|
@@ -6896,7 +6922,8 @@ var HANDOUT_SLIDES_PER_PAGE_OPTIONS = [1, 2, 3, 4, 6, 9];
|
|
|
6896
6922
|
function HandoutMasterPanel({
|
|
6897
6923
|
handoutMaster,
|
|
6898
6924
|
slidesPerPage,
|
|
6899
|
-
onSlidesPerPageChange
|
|
6925
|
+
onSlidesPerPageChange,
|
|
6926
|
+
onBackgroundChange
|
|
6900
6927
|
}) {
|
|
6901
6928
|
const { t } = useTranslation();
|
|
6902
6929
|
if (!handoutMaster) {
|
|
@@ -6909,6 +6936,7 @@ function HandoutMasterPanel({
|
|
|
6909
6936
|
"button",
|
|
6910
6937
|
{
|
|
6911
6938
|
type: "button",
|
|
6939
|
+
"aria-pressed": slidesPerPage === count,
|
|
6912
6940
|
className: cn(
|
|
6913
6941
|
"px-2 py-1.5 rounded text-[11px] font-medium transition-colors",
|
|
6914
6942
|
slidesPerPage === count ? "bg-primary text-white" : "bg-accent/50 text-muted-foreground hover:bg-accent/70 hover:text-foreground"
|
|
@@ -6922,12 +6950,13 @@ function HandoutMasterPanel({
|
|
|
6922
6950
|
/* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border/60 bg-muted/40 p-2", children: [
|
|
6923
6951
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("pptx.master.handoutBackground") }),
|
|
6924
6952
|
/* @__PURE__ */ jsx(
|
|
6925
|
-
"
|
|
6953
|
+
"input",
|
|
6926
6954
|
{
|
|
6955
|
+
type: "color",
|
|
6956
|
+
"aria-label": "Master background color",
|
|
6927
6957
|
className: "w-full h-8 rounded border border-border",
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
}
|
|
6958
|
+
value: handoutMaster.backgroundColor ?? "#ffffff",
|
|
6959
|
+
onChange: (event) => onBackgroundChange(event.target.value)
|
|
6931
6960
|
}
|
|
6932
6961
|
)
|
|
6933
6962
|
] }),
|
|
@@ -6947,7 +6976,10 @@ function HandoutMasterPanel({
|
|
|
6947
6976
|
] })
|
|
6948
6977
|
] });
|
|
6949
6978
|
}
|
|
6950
|
-
function NotesMasterPanel({
|
|
6979
|
+
function NotesMasterPanel({
|
|
6980
|
+
notesMaster,
|
|
6981
|
+
onBackgroundChange
|
|
6982
|
+
}) {
|
|
6951
6983
|
const { t } = useTranslation();
|
|
6952
6984
|
const placeholderLabels = useMemo(() => {
|
|
6953
6985
|
if (!notesMaster?.placeholders) {
|
|
@@ -6965,10 +6997,13 @@ function NotesMasterPanel({ notesMaster }) {
|
|
|
6965
6997
|
/* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border/60 bg-muted/40 p-2", children: [
|
|
6966
6998
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("pptx.master.notesMasterBackground") }),
|
|
6967
6999
|
/* @__PURE__ */ jsx(
|
|
6968
|
-
"
|
|
7000
|
+
"input",
|
|
6969
7001
|
{
|
|
7002
|
+
type: "color",
|
|
7003
|
+
"aria-label": "Master background color",
|
|
6970
7004
|
className: "w-full h-8 rounded border border-border",
|
|
6971
|
-
|
|
7005
|
+
value: notesMaster.backgroundColor ?? "#ffffff",
|
|
7006
|
+
onChange: (event) => onBackgroundChange(event.target.value)
|
|
6972
7007
|
}
|
|
6973
7008
|
)
|
|
6974
7009
|
] }),
|
|
@@ -7115,7 +7150,9 @@ function MasterViewSidebar({
|
|
|
7115
7150
|
onSelectLayout,
|
|
7116
7151
|
onCollapse,
|
|
7117
7152
|
onTabChange,
|
|
7118
|
-
onHandoutSlidesPerPageChange
|
|
7153
|
+
onHandoutSlidesPerPageChange,
|
|
7154
|
+
onNotesMasterBackgroundChange,
|
|
7155
|
+
onHandoutMasterBackgroundChange
|
|
7119
7156
|
}) {
|
|
7120
7157
|
const scrollRef = useRef(null);
|
|
7121
7158
|
const { t } = useTranslation();
|
|
@@ -7131,56 +7168,80 @@ function MasterViewSidebar({
|
|
|
7131
7168
|
},
|
|
7132
7169
|
[onSelectLayout]
|
|
7133
7170
|
);
|
|
7134
|
-
return /* @__PURE__ */ jsxs(
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
className: "
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
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
|
+
}
|
|
7155
7212
|
),
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
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
|
+
);
|
|
7184
7245
|
}
|
|
7185
7246
|
var DEFAULT_NOTES_WIDTH = 720;
|
|
7186
7247
|
var DEFAULT_NOTES_HEIGHT = 960;
|
|
@@ -7200,6 +7261,12 @@ var DEFAULT_POSITIONS = {
|
|
|
7200
7261
|
dt: { x: 0.6, y: 0, w: 0.4, h: 0.04 },
|
|
7201
7262
|
sldNum: { x: 0.6, y: 0.96, w: 0.4, h: 0.04 }
|
|
7202
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
|
+
}
|
|
7203
7270
|
function NotesMasterCanvas({
|
|
7204
7271
|
notesMaster,
|
|
7205
7272
|
canvasSize,
|
|
@@ -7343,7 +7410,24 @@ function NotesMasterCanvas({
|
|
|
7343
7410
|
},
|
|
7344
7411
|
`${ph.type}-${ph.idx ?? "default"}`
|
|
7345
7412
|
);
|
|
7346
|
-
})
|
|
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
|
+
))
|
|
7347
7431
|
]
|
|
7348
7432
|
}
|
|
7349
7433
|
) });
|
|
@@ -7351,6 +7435,12 @@ function NotesMasterCanvas({
|
|
|
7351
7435
|
var PAGE_WIDTH = 720;
|
|
7352
7436
|
var PAGE_HEIGHT = 960;
|
|
7353
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
|
+
}
|
|
7354
7444
|
function computeSlotLayout(slidesPerPage, slideAspect) {
|
|
7355
7445
|
const mx = MARGIN;
|
|
7356
7446
|
const my = MARGIN;
|
|
@@ -7502,6 +7592,23 @@ function HandoutMasterCanvas({
|
|
|
7502
7592
|
i
|
|
7503
7593
|
);
|
|
7504
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
|
+
)),
|
|
7505
7612
|
/* @__PURE__ */ jsx(
|
|
7506
7613
|
"div",
|
|
7507
7614
|
{
|
|
@@ -9942,6 +10049,18 @@ function ComparePanel({
|
|
|
9942
10049
|
)) })
|
|
9943
10050
|
] });
|
|
9944
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
|
+
}
|
|
9945
10064
|
function getPasswordStrength(password) {
|
|
9946
10065
|
if (!password) {
|
|
9947
10066
|
return 0;
|
|
@@ -9983,6 +10102,8 @@ function PasswordProtectionDialog({
|
|
|
9983
10102
|
const [confirmPassword, setConfirmPassword] = useState("");
|
|
9984
10103
|
const [showPassword, setShowPassword] = useState(false);
|
|
9985
10104
|
const [error, setError] = useState("");
|
|
10105
|
+
const dialogRef = useRef(null);
|
|
10106
|
+
const passwordRef = useRef(null);
|
|
9986
10107
|
const strength = useMemo(() => getPasswordStrength(password), [password]);
|
|
9987
10108
|
const strengthLabel = useMemo(() => {
|
|
9988
10109
|
const labels = [
|
|
@@ -10025,6 +10146,7 @@ function PasswordProtectionDialog({
|
|
|
10025
10146
|
setError("");
|
|
10026
10147
|
onClose();
|
|
10027
10148
|
}, [onClose]);
|
|
10149
|
+
useModalFocus(isOpen, dialogRef, handleClose, passwordRef);
|
|
10028
10150
|
if (!isOpen) {
|
|
10029
10151
|
return null;
|
|
10030
10152
|
}
|
|
@@ -10044,117 +10166,148 @@ function PasswordProtectionDialog({
|
|
|
10044
10166
|
{
|
|
10045
10167
|
style: { zIndex: 1201 },
|
|
10046
10168
|
className: "fixed inset-0 flex items-center justify-center pointer-events-none",
|
|
10047
|
-
children: /* @__PURE__ */ jsxs(
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
className: "
|
|
10059
|
-
|
|
10060
|
-
|
|
10061
|
-
|
|
10062
|
-
)
|
|
10063
|
-
] }),
|
|
10064
|
-
/* @__PURE__ */ jsxs("div", { className: "px-5 py-4 space-y-4", children: [
|
|
10065
|
-
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: [
|
|
10066
|
-
/* @__PURE__ */ jsx(LuShieldCheck, { className: "w-4 h-4 text-green-400 shrink-0" }),
|
|
10067
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-green-300", children: t("pptx.security.currentlyProtected") })
|
|
10068
|
-
] }),
|
|
10069
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("pptx.security.description") }),
|
|
10070
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
10071
|
-
/* @__PURE__ */ jsx("label", { className: "block text-xs text-foreground mb-1", children: t("pptx.security.password") }),
|
|
10072
|
-
/* @__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
|
+
] }),
|
|
10073
10184
|
/* @__PURE__ */ jsx(
|
|
10074
|
-
"
|
|
10185
|
+
"button",
|
|
10075
10186
|
{
|
|
10076
|
-
type:
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
|
|
10080
|
-
|
|
10081
|
-
setPassword(e.target.value);
|
|
10082
|
-
setError("");
|
|
10083
|
-
}
|
|
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" })
|
|
10084
10192
|
}
|
|
10085
|
-
)
|
|
10086
|
-
|
|
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(
|
|
10087
10279
|
"button",
|
|
10088
10280
|
{
|
|
10089
10281
|
type: "button",
|
|
10090
|
-
onClick:
|
|
10091
|
-
className: "
|
|
10092
|
-
|
|
10093
|
-
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")
|
|
10094
10285
|
}
|
|
10095
|
-
)
|
|
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
|
+
] })
|
|
10096
10307
|
] })
|
|
10097
|
-
]
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
"div",
|
|
10101
|
-
{
|
|
10102
|
-
className: `h-1 flex-1 rounded-full transition-colors ${i <= strength ? STRENGTH_COLORS[strength] : "bg-accent"}`
|
|
10103
|
-
},
|
|
10104
|
-
`str-${i}`
|
|
10105
|
-
)) }),
|
|
10106
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: strengthLabel })
|
|
10107
|
-
] }),
|
|
10108
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
10109
|
-
/* @__PURE__ */ jsx("label", { className: "block text-xs text-foreground mb-1", children: t("pptx.security.confirmPassword") }),
|
|
10110
|
-
/* @__PURE__ */ jsx(
|
|
10111
|
-
"input",
|
|
10112
|
-
{
|
|
10113
|
-
type: showPassword ? "text" : "password",
|
|
10114
|
-
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",
|
|
10115
|
-
placeholder: t("pptx.security.confirmPasswordPlaceholder"),
|
|
10116
|
-
value: confirmPassword,
|
|
10117
|
-
onChange: (e) => {
|
|
10118
|
-
setConfirmPassword(e.target.value);
|
|
10119
|
-
setError("");
|
|
10120
|
-
}
|
|
10121
|
-
}
|
|
10122
|
-
)
|
|
10123
|
-
] }),
|
|
10124
|
-
error && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-400", children: error })
|
|
10125
|
-
] }),
|
|
10126
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-3 border-t border-border/60", children: [
|
|
10127
|
-
/* @__PURE__ */ jsx("div", { children: isCurrentlyProtected && /* @__PURE__ */ jsx(
|
|
10128
|
-
"button",
|
|
10129
|
-
{
|
|
10130
|
-
type: "button",
|
|
10131
|
-
onClick: handleRemove,
|
|
10132
|
-
className: "text-xs text-red-400 hover:text-red-300 transition-colors",
|
|
10133
|
-
children: t("pptx.security.removePassword")
|
|
10134
|
-
}
|
|
10135
|
-
) }),
|
|
10136
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
10137
|
-
/* @__PURE__ */ jsx(
|
|
10138
|
-
"button",
|
|
10139
|
-
{
|
|
10140
|
-
type: "button",
|
|
10141
|
-
onClick: handleClose,
|
|
10142
|
-
className: "px-3 py-1.5 text-xs rounded-lg border border-border text-foreground hover:bg-muted transition-colors",
|
|
10143
|
-
children: t("common.cancel")
|
|
10144
|
-
}
|
|
10145
|
-
),
|
|
10146
|
-
/* @__PURE__ */ jsx(
|
|
10147
|
-
"button",
|
|
10148
|
-
{
|
|
10149
|
-
type: "button",
|
|
10150
|
-
onClick: handleSubmit,
|
|
10151
|
-
className: "px-3 py-1.5 text-xs rounded-lg bg-primary text-white hover:bg-primary/80 transition-colors",
|
|
10152
|
-
children: isCurrentlyProtected ? t("pptx.security.updatePassword") : t("pptx.security.setPassword")
|
|
10153
|
-
}
|
|
10154
|
-
)
|
|
10155
|
-
] })
|
|
10156
|
-
] })
|
|
10157
|
-
] })
|
|
10308
|
+
]
|
|
10309
|
+
}
|
|
10310
|
+
)
|
|
10158
10311
|
}
|
|
10159
10312
|
)
|
|
10160
10313
|
] });
|
|
@@ -10986,18 +11139,225 @@ function EncryptedFileDialog({
|
|
|
10986
11139
|
)
|
|
10987
11140
|
] });
|
|
10988
11141
|
}
|
|
10989
|
-
function
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
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(
|
|
10995
11174
|
"span",
|
|
10996
|
-
{
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
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
|
+
] });
|
|
11360
|
+
}
|
|
11001
11361
|
function ScaledSlidePreviewImpl({
|
|
11002
11362
|
slide,
|
|
11003
11363
|
templateElements,
|
|
@@ -11288,6 +11648,250 @@ function arePropsEqual4(prev, next) {
|
|
|
11288
11648
|
return true;
|
|
11289
11649
|
}
|
|
11290
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
|
+
}
|
|
11291
11895
|
function PresenterView({
|
|
11292
11896
|
slides,
|
|
11293
11897
|
currentSlideIndex,
|
|
@@ -11298,47 +11902,83 @@ function PresenterView({
|
|
|
11298
11902
|
onExit,
|
|
11299
11903
|
onOpenAudienceWindow,
|
|
11300
11904
|
onCloseAudienceWindow,
|
|
11301
|
-
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
|
|
11302
11917
|
}) {
|
|
11303
11918
|
const { t } = useTranslation();
|
|
11304
|
-
const [mounted, setMounted] = useState(false);
|
|
11305
|
-
useEffect(() => {
|
|
11306
|
-
const timer = window.setTimeout(() => setMounted(true), 300);
|
|
11307
|
-
return () => window.clearTimeout(timer);
|
|
11308
|
-
}, []);
|
|
11309
11919
|
const [now, setNow] = useState(Date.now());
|
|
11310
11920
|
useEffect(() => {
|
|
11311
11921
|
const interval = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
11312
11922
|
return () => window.clearInterval(interval);
|
|
11313
11923
|
}, []);
|
|
11314
|
-
const elapsed = presentationStartTime ? now - presentationStartTime : 0;
|
|
11315
|
-
const [
|
|
11316
|
-
const
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
}, []);
|
|
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
|
+
);
|
|
11322
11931
|
const currentSlide = slides[currentSlideIndex];
|
|
11323
|
-
const nextSlide = currentSlideIndex + 1 < slides.length ? slides[currentSlideIndex + 1] : void 0;
|
|
11324
|
-
const notesText = currentSlide?.notes ?? "";
|
|
11325
|
-
const notesSegments = currentSlide?.notesSegments;
|
|
11326
|
-
const hasRichNotes = notesSegments && notesSegments.length > 0;
|
|
11327
11932
|
if (!currentSlide) {
|
|
11328
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") });
|
|
11329
11934
|
}
|
|
11330
11935
|
const TIMER_SEGMENT_MS = 5 * 60 * 1e3;
|
|
11331
11936
|
const timerProgress = Math.min(100, elapsed % TIMER_SEGMENT_MS / TIMER_SEGMENT_MS * 100);
|
|
11332
11937
|
const timerSegment = Math.floor(elapsed / TIMER_SEGMENT_MS);
|
|
11333
|
-
return /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-50 flex flex-col bg-
|
|
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
|
+
),
|
|
11334
11959
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 min-h-0", children: [
|
|
11335
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-[7] flex flex-col items-center justify-center bg-black p-6 min-w-0", children: [
|
|
11336
|
-
/* @__PURE__ */
|
|
11337
|
-
|
|
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",
|
|
11338
11963
|
{
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
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: [
|
|
11972
|
+
/* @__PURE__ */ jsx(
|
|
11973
|
+
ScaledSlidePreview,
|
|
11974
|
+
{
|
|
11975
|
+
slide: currentSlide,
|
|
11976
|
+
templateElements,
|
|
11977
|
+
canvasSize
|
|
11978
|
+
}
|
|
11979
|
+
),
|
|
11980
|
+
/* @__PURE__ */ jsx(PresentationAudienceEffects, { snapshot })
|
|
11981
|
+
]
|
|
11342
11982
|
}
|
|
11343
11983
|
),
|
|
11344
11984
|
/* @__PURE__ */ jsx("div", { className: "mt-3 text-xs font-mono tabular-nums text-white/50 select-none", children: t("pptx.presenter.slideLabel", {
|
|
@@ -11347,138 +11987,41 @@ function PresenterView({
|
|
|
11347
11987
|
defaultValue: `Slide ${currentSlideIndex + 1} of ${slides.length}`
|
|
11348
11988
|
}) })
|
|
11349
11989
|
] }),
|
|
11350
|
-
/* @__PURE__ */
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
{
|
|
11364
|
-
type: "button",
|
|
11365
|
-
onClick: () => {
|
|
11366
|
-
if (isAudienceWindowOpen) {
|
|
11367
|
-
onCloseAudienceWindow?.();
|
|
11368
|
-
} else {
|
|
11369
|
-
onOpenAudienceWindow();
|
|
11370
|
-
}
|
|
11371
|
-
},
|
|
11372
|
-
className: "p-1.5 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
11373
|
-
title: isAudienceWindowOpen ? t("pptx.presenter.closeAudienceWindow") : t("pptx.presenter.openAudienceWindow"),
|
|
11374
|
-
"aria-label": isAudienceWindowOpen ? t("pptx.presenter.closeAudienceWindow") : t("pptx.presenter.openAudienceWindow"),
|
|
11375
|
-
children: isAudienceWindowOpen ? /* @__PURE__ */ jsx(LuMonitorOff, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(LuMonitor, { className: "w-5 h-5" })
|
|
11376
|
-
}
|
|
11377
|
-
),
|
|
11378
|
-
/* @__PURE__ */ jsx(
|
|
11379
|
-
"button",
|
|
11380
|
-
{
|
|
11381
|
-
type: "button",
|
|
11382
|
-
onClick: onExit,
|
|
11383
|
-
className: "p-1.5 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
11384
|
-
title: t("pptx.presenter.endPresentation"),
|
|
11385
|
-
"aria-label": t("pptx.presenter.endPresentation"),
|
|
11386
|
-
children: /* @__PURE__ */ jsx(LuX, { className: "w-5 h-5" })
|
|
11387
|
-
}
|
|
11388
|
-
)
|
|
11389
|
-
] })
|
|
11390
|
-
] }),
|
|
11391
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2 border-b border-border/60", children: [
|
|
11392
|
-
/* @__PURE__ */ jsxs(
|
|
11393
|
-
"button",
|
|
11394
|
-
{
|
|
11395
|
-
type: "button",
|
|
11396
|
-
onClick: () => onMovePresentationSlide(-1),
|
|
11397
|
-
disabled: currentSlideIndex === 0,
|
|
11398
|
-
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",
|
|
11399
|
-
title: t("pptx.presenter.previousSlide"),
|
|
11400
|
-
children: [
|
|
11401
|
-
/* @__PURE__ */ jsx(LuChevronLeft, { className: "w-4 h-4" }),
|
|
11402
|
-
t("pptx.presenter.prev")
|
|
11403
|
-
]
|
|
11404
|
-
}
|
|
11405
|
-
),
|
|
11406
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm font-mono tabular-nums text-foreground", children: [
|
|
11407
|
-
currentSlideIndex + 1,
|
|
11408
|
-
" / ",
|
|
11409
|
-
slides.length
|
|
11410
|
-
] }),
|
|
11411
|
-
/* @__PURE__ */ jsxs(
|
|
11412
|
-
"button",
|
|
11413
|
-
{
|
|
11414
|
-
type: "button",
|
|
11415
|
-
onClick: () => onMovePresentationSlide(1),
|
|
11416
|
-
disabled: currentSlideIndex >= slides.length - 1,
|
|
11417
|
-
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",
|
|
11418
|
-
title: t("pptx.presenter.nextSlide"),
|
|
11419
|
-
children: [
|
|
11420
|
-
t("pptx.presenter.next"),
|
|
11421
|
-
/* @__PURE__ */ jsx(LuChevronRight, { className: "w-4 h-4" })
|
|
11422
|
-
]
|
|
11423
|
-
}
|
|
11424
|
-
)
|
|
11425
|
-
] }),
|
|
11426
|
-
/* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-border/60", children: [
|
|
11427
|
-
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground uppercase tracking-wider mb-2", children: t("pptx.presenter.nextSlidePreview") }),
|
|
11428
|
-
nextSlide ? /* @__PURE__ */ jsx(
|
|
11429
|
-
ScaledSlidePreview,
|
|
11430
|
-
{
|
|
11431
|
-
slide: nextSlide,
|
|
11432
|
-
templateElements,
|
|
11433
|
-
canvasSize
|
|
11434
|
-
}
|
|
11435
|
-
) : /* @__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") })
|
|
11436
|
-
] }),
|
|
11437
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-h-0 px-4 py-3", children: [
|
|
11438
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
11439
|
-
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground uppercase tracking-wider", children: t("pptx.presenter.speakerNotes") }),
|
|
11440
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
11441
|
-
/* @__PURE__ */ jsx(
|
|
11442
|
-
"button",
|
|
11443
|
-
{
|
|
11444
|
-
type: "button",
|
|
11445
|
-
onClick: decreaseNotesFontSize,
|
|
11446
|
-
disabled: notesFontSize <= NOTES_FONT_SIZE_MIN,
|
|
11447
|
-
className: "p-0.5 rounded hover:bg-accent text-muted-foreground hover:text-foreground disabled:opacity-30 disabled:cursor-not-allowed transition-colors",
|
|
11448
|
-
title: t("pptx.presenter.decreaseFontSize"),
|
|
11449
|
-
"aria-label": t("pptx.presenter.decreaseFontSize"),
|
|
11450
|
-
children: /* @__PURE__ */ jsx(LuMinus, { className: "w-3.5 h-3.5" })
|
|
11451
|
-
}
|
|
11452
|
-
),
|
|
11453
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[10px] font-mono tabular-nums text-muted-foreground min-w-[28px] text-center select-none", children: [
|
|
11454
|
-
notesFontSize,
|
|
11455
|
-
"px"
|
|
11456
|
-
] }),
|
|
11457
|
-
/* @__PURE__ */ jsx(
|
|
11458
|
-
"button",
|
|
11459
|
-
{
|
|
11460
|
-
type: "button",
|
|
11461
|
-
onClick: increaseNotesFontSize,
|
|
11462
|
-
disabled: notesFontSize >= NOTES_FONT_SIZE_MAX,
|
|
11463
|
-
className: "p-0.5 rounded hover:bg-accent text-muted-foreground hover:text-foreground disabled:opacity-30 disabled:cursor-not-allowed transition-colors",
|
|
11464
|
-
title: t("pptx.presenter.increaseFontSize"),
|
|
11465
|
-
"aria-label": t("pptx.presenter.increaseFontSize"),
|
|
11466
|
-
children: /* @__PURE__ */ jsx(LuPlus, { className: "w-3.5 h-3.5" })
|
|
11467
|
-
}
|
|
11468
|
-
)
|
|
11469
|
-
] })
|
|
11470
|
-
] }),
|
|
11471
|
-
/* @__PURE__ */ jsx(
|
|
11472
|
-
"div",
|
|
11473
|
-
{
|
|
11474
|
-
className: "flex-1 overflow-y-auto rounded border border-border/30 bg-muted/40 px-3 py-2 text-foreground whitespace-pre-wrap leading-relaxed",
|
|
11475
|
-
style: { fontSize: `${notesFontSize}px` },
|
|
11476
|
-
children: hasRichNotes ? renderNotesSegments(notesSegments) : notesText.trim().length > 0 ? notesText : /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: t("pptx.presenter.noNotes") })
|
|
11477
|
-
}
|
|
11478
|
-
)
|
|
11479
|
-
] })
|
|
11480
|
-
] })
|
|
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
|
+
)
|
|
11481
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
|
+
),
|
|
11482
12025
|
/* @__PURE__ */ jsx(
|
|
11483
12026
|
"div",
|
|
11484
12027
|
{
|
|
@@ -14615,23 +15158,12 @@ function MobileSheet({
|
|
|
14615
15158
|
}) {
|
|
14616
15159
|
const sheetRef = useRef(null);
|
|
14617
15160
|
const { dragY, dragging, handlers } = useSheetDismissDrag(onClose);
|
|
14618
|
-
|
|
14619
|
-
if (!open) {
|
|
14620
|
-
return;
|
|
14621
|
-
}
|
|
14622
|
-
const handleKey = (e) => {
|
|
14623
|
-
if (e.key === "Escape") {
|
|
14624
|
-
onClose();
|
|
14625
|
-
}
|
|
14626
|
-
};
|
|
14627
|
-
window.addEventListener("keydown", handleKey);
|
|
14628
|
-
return () => window.removeEventListener("keydown", handleKey);
|
|
14629
|
-
}, [open, onClose]);
|
|
15161
|
+
useModalFocus(open, sheetRef, onClose);
|
|
14630
15162
|
if (!open) {
|
|
14631
15163
|
return null;
|
|
14632
15164
|
}
|
|
14633
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` };
|
|
14634
|
-
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: [
|
|
14635
15167
|
/* @__PURE__ */ jsx(
|
|
14636
15168
|
"button",
|
|
14637
15169
|
{
|
|
@@ -14645,6 +15177,10 @@ function MobileSheet({
|
|
|
14645
15177
|
"div",
|
|
14646
15178
|
{
|
|
14647
15179
|
ref: sheetRef,
|
|
15180
|
+
role: "dialog",
|
|
15181
|
+
"aria-modal": "true",
|
|
15182
|
+
"aria-label": typeof title === "string" ? title : "Mobile panel",
|
|
15183
|
+
tabIndex: -1,
|
|
14648
15184
|
className: cn(
|
|
14649
15185
|
"relative bg-background border-t border-border rounded-t-2xl shadow-2xl flex flex-col overflow-hidden",
|
|
14650
15186
|
"animate-in slide-in-from-bottom duration-200",
|
|
@@ -14668,7 +15204,18 @@ function MobileSheet({
|
|
|
14668
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" }) }),
|
|
14669
15205
|
(title || headerRight) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-4 pb-2 border-b border-border/60", children: [
|
|
14670
15206
|
/* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-foreground truncate", children: title }),
|
|
14671
|
-
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
|
+
)
|
|
14672
15219
|
] })
|
|
14673
15220
|
]
|
|
14674
15221
|
}
|
|
@@ -20702,6 +21249,8 @@ function SmartArtLayoutSwitcher({
|
|
|
20702
21249
|
layoutType: updated.layoutType,
|
|
20703
21250
|
resolvedLayoutType: updated.resolvedLayoutType,
|
|
20704
21251
|
layout: updated.layout,
|
|
21252
|
+
layoutDirty: updated.layoutDirty,
|
|
21253
|
+
drawingDirty: updated.drawingDirty,
|
|
20705
21254
|
drawingShapes: updated.drawingShapes
|
|
20706
21255
|
});
|
|
20707
21256
|
};
|
|
@@ -22312,6 +22861,42 @@ function InspectorCommentsSection({
|
|
|
22312
22861
|
] })
|
|
22313
22862
|
] });
|
|
22314
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
|
+
}
|
|
22315
22900
|
function InfoRow({ label, value }) {
|
|
22316
22901
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
22317
22902
|
/* @__PURE__ */ jsx("span", { children: label }),
|
|
@@ -22696,8 +23281,23 @@ function SlideThemeOverridePanel({
|
|
|
22696
23281
|
}) {
|
|
22697
23282
|
const { t } = useTranslation();
|
|
22698
23283
|
const override = activeSlide?.clrMapOverride;
|
|
22699
|
-
const isOverrideActive =
|
|
23284
|
+
const isOverrideActive = override !== void 0;
|
|
22700
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
|
+
);
|
|
22701
23301
|
const handleToggle = useCallback(
|
|
22702
23302
|
(enabled) => {
|
|
22703
23303
|
if (enabled) {
|
|
@@ -22705,12 +23305,12 @@ function SlideThemeOverridePanel({
|
|
|
22705
23305
|
for (const key of COLOR_MAP_ALIAS_KEYS) {
|
|
22706
23306
|
defaultMap[key] = DEFAULT_COLOR_MAP[key];
|
|
22707
23307
|
}
|
|
22708
|
-
|
|
23308
|
+
commitOverride(defaultMap);
|
|
22709
23309
|
} else {
|
|
22710
|
-
|
|
23310
|
+
commitOverride(void 0);
|
|
22711
23311
|
}
|
|
22712
23312
|
},
|
|
22713
|
-
[
|
|
23313
|
+
[commitOverride]
|
|
22714
23314
|
);
|
|
22715
23315
|
const handleAliasChange = useCallback(
|
|
22716
23316
|
(alias, targetSlot) => {
|
|
@@ -22721,9 +23321,9 @@ function SlideThemeOverridePanel({
|
|
|
22721
23321
|
next[key] = DEFAULT_COLOR_MAP[key];
|
|
22722
23322
|
}
|
|
22723
23323
|
}
|
|
22724
|
-
|
|
23324
|
+
commitOverride(next);
|
|
22725
23325
|
},
|
|
22726
|
-
[
|
|
23326
|
+
[commitOverride, override]
|
|
22727
23327
|
);
|
|
22728
23328
|
const resolveSlotColor = useCallback(
|
|
22729
23329
|
(slot) => {
|
|
@@ -23158,6 +23758,35 @@ function TemplateBackgroundCard({
|
|
|
23158
23758
|
})()
|
|
23159
23759
|
] });
|
|
23160
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
|
+
}
|
|
23161
23790
|
function InspectorPane(props) {
|
|
23162
23791
|
const {
|
|
23163
23792
|
isOpen,
|
|
@@ -23222,23 +23851,13 @@ function InspectorPane(props) {
|
|
|
23222
23851
|
const hasSelection = selectedElement !== null;
|
|
23223
23852
|
const { t } = useTranslation();
|
|
23224
23853
|
const { dragY, handlers: dragHandlers } = useSheetDismissDrag(onClose);
|
|
23225
|
-
const
|
|
23226
|
-
|
|
23227
|
-
|
|
23228
|
-
|
|
23229
|
-
|
|
23230
|
-
|
|
23231
|
-
|
|
23232
|
-
}, []);
|
|
23233
|
-
useEffect(() => {
|
|
23234
|
-
const activeThemePath = slideMasters?.[0]?.themePath;
|
|
23235
|
-
if (activeThemePath && activeThemePath.length > 0) {
|
|
23236
|
-
setSelectedThemePath(activeThemePath);
|
|
23237
|
-
return;
|
|
23238
|
-
}
|
|
23239
|
-
const fallback = themeOptions[0]?.path ?? "";
|
|
23240
|
-
setSelectedThemePath((previous) => previous || fallback);
|
|
23241
|
-
}, [slideMasters, themeOptions]);
|
|
23854
|
+
const {
|
|
23855
|
+
animationPanelHeight,
|
|
23856
|
+
effectiveThemeOptions,
|
|
23857
|
+
onResizeAnimationPanel,
|
|
23858
|
+
selectedThemePath,
|
|
23859
|
+
setSelectedThemePath
|
|
23860
|
+
} = useInspectorPaneState(themeOptions, slideMasters, theme);
|
|
23242
23861
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23243
23862
|
isOpen && /* @__PURE__ */ jsx(
|
|
23244
23863
|
"button",
|
|
@@ -23280,35 +23899,14 @@ function InspectorPane(props) {
|
|
|
23280
23899
|
children: /* @__PURE__ */ jsx("div", { className: "h-1 w-10 rounded-full bg-muted-foreground/40" })
|
|
23281
23900
|
}
|
|
23282
23901
|
),
|
|
23283
|
-
/* @__PURE__ */
|
|
23284
|
-
|
|
23285
|
-
|
|
23286
|
-
|
|
23287
|
-
|
|
23288
|
-
|
|
23289
|
-
|
|
23290
|
-
|
|
23291
|
-
activeTab === key ? "bg-primary text-white" : "text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
23292
|
-
),
|
|
23293
|
-
onClick: () => onSetActiveTab(key),
|
|
23294
|
-
children: [
|
|
23295
|
-
/* @__PURE__ */ jsx(Icon, { className: "w-3.5 h-3.5" }),
|
|
23296
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: label })
|
|
23297
|
-
]
|
|
23298
|
-
},
|
|
23299
|
-
key
|
|
23300
|
-
)) }),
|
|
23301
|
-
/* @__PURE__ */ jsx(
|
|
23302
|
-
"button",
|
|
23303
|
-
{
|
|
23304
|
-
type: "button",
|
|
23305
|
-
onClick: onClose,
|
|
23306
|
-
title: t("common.close"),
|
|
23307
|
-
className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
|
|
23308
|
-
children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
|
|
23309
|
-
}
|
|
23310
|
-
)
|
|
23311
|
-
] }),
|
|
23902
|
+
/* @__PURE__ */ jsx(
|
|
23903
|
+
InspectorPaneHeader,
|
|
23904
|
+
{
|
|
23905
|
+
activeTab,
|
|
23906
|
+
onSetActiveTab,
|
|
23907
|
+
onClose
|
|
23908
|
+
}
|
|
23909
|
+
),
|
|
23312
23910
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
|
|
23313
23911
|
activeTab === "elements" && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
23314
23912
|
/* @__PURE__ */ jsx("div", { className: cn(HEADING, "mb-2"), children: t("pptx.inspector.layerOrder") }),
|
|
@@ -23361,7 +23959,7 @@ function InspectorPane(props) {
|
|
|
23361
23959
|
coreProperties,
|
|
23362
23960
|
appProperties,
|
|
23363
23961
|
customProperties,
|
|
23364
|
-
themeOptions,
|
|
23962
|
+
themeOptions: effectiveThemeOptions,
|
|
23365
23963
|
selectedThemePath,
|
|
23366
23964
|
setSelectedThemePath,
|
|
23367
23965
|
onApplyTheme,
|
|
@@ -23418,12 +24016,12 @@ function InspectorPane(props) {
|
|
|
23418
24016
|
)
|
|
23419
24017
|
] }),
|
|
23420
24018
|
hasSelection && selectedElement && activeSlide && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23421
|
-
/* @__PURE__ */ jsx(ResizeHandle, { direction: "vertical", onResize:
|
|
24019
|
+
/* @__PURE__ */ jsx(ResizeHandle, { direction: "vertical", onResize: onResizeAnimationPanel }),
|
|
23422
24020
|
/* @__PURE__ */ jsx(
|
|
23423
24021
|
"div",
|
|
23424
24022
|
{
|
|
23425
24023
|
className: "border-t border-border p-3 overflow-y-auto flex-shrink-0",
|
|
23426
|
-
style: { height:
|
|
24024
|
+
style: { height: animationPanelHeight },
|
|
23427
24025
|
children: /* @__PURE__ */ jsx(
|
|
23428
24026
|
AnimationPanel,
|
|
23429
24027
|
{
|
|
@@ -23993,84 +24591,8 @@ function PresentationTouchControls({
|
|
|
23993
24591
|
style: { bottom: "calc(env(safe-area-inset-bottom, 0px) + 0.5rem)" },
|
|
23994
24592
|
children: totalSlides === 0 ? "0 / 0" : `${currentSlideIndex + 1} / ${totalSlides}`
|
|
23995
24593
|
}
|
|
23996
|
-
)
|
|
23997
|
-
] });
|
|
23998
|
-
}
|
|
23999
|
-
function PresentationSubtitleBar({
|
|
24000
|
-
visible
|
|
24001
|
-
}) {
|
|
24002
|
-
const { t } = useTranslation();
|
|
24003
|
-
const [captionText, setCaptionText] = useState("");
|
|
24004
|
-
const [supportState, setSupportState] = useState(
|
|
24005
|
-
"unknown"
|
|
24006
|
-
);
|
|
24007
|
-
const recognitionRef = useRef(null);
|
|
24008
|
-
const shouldRunRef = useRef(false);
|
|
24009
|
-
useEffect(() => {
|
|
24010
|
-
if (!visible) {
|
|
24011
|
-
shouldRunRef.current = false;
|
|
24012
|
-
recognitionRef.current?.stop();
|
|
24013
|
-
recognitionRef.current = null;
|
|
24014
|
-
setCaptionText("");
|
|
24015
|
-
return;
|
|
24016
|
-
}
|
|
24017
|
-
shouldRunRef.current = true;
|
|
24018
|
-
const speechWindow = window;
|
|
24019
|
-
const RecognitionCtor = speechWindow.SpeechRecognition ?? speechWindow.webkitSpeechRecognition;
|
|
24020
|
-
if (!RecognitionCtor) {
|
|
24021
|
-
setSupportState("unsupported");
|
|
24022
|
-
return;
|
|
24023
|
-
}
|
|
24024
|
-
setSupportState("supported");
|
|
24025
|
-
const recognition = new RecognitionCtor();
|
|
24026
|
-
recognition.continuous = true;
|
|
24027
|
-
recognition.interimResults = true;
|
|
24028
|
-
recognition.lang = navigator.language || "en-US";
|
|
24029
|
-
recognition.onresult = (event) => {
|
|
24030
|
-
let finalText = "";
|
|
24031
|
-
let interimText = "";
|
|
24032
|
-
for (let index = event.resultIndex; index < event.results.length; index += 1) {
|
|
24033
|
-
const result = event.results[index];
|
|
24034
|
-
const fragment = result?.[0]?.transcript ?? "";
|
|
24035
|
-
if (result?.isFinal) {
|
|
24036
|
-
finalText += fragment;
|
|
24037
|
-
} else {
|
|
24038
|
-
interimText += fragment;
|
|
24039
|
-
}
|
|
24040
|
-
}
|
|
24041
|
-
const merged = `${finalText} ${interimText}`.trim();
|
|
24042
|
-
if (merged.length > 0) {
|
|
24043
|
-
setCaptionText(merged);
|
|
24044
|
-
}
|
|
24045
|
-
};
|
|
24046
|
-
recognition.onerror = () => {
|
|
24047
|
-
};
|
|
24048
|
-
recognition.onend = () => {
|
|
24049
|
-
if (!shouldRunRef.current) {
|
|
24050
|
-
return;
|
|
24051
|
-
}
|
|
24052
|
-
try {
|
|
24053
|
-
recognition.start();
|
|
24054
|
-
} catch {
|
|
24055
|
-
}
|
|
24056
|
-
};
|
|
24057
|
-
recognitionRef.current = recognition;
|
|
24058
|
-
try {
|
|
24059
|
-
recognition.start();
|
|
24060
|
-
} catch {
|
|
24061
|
-
setSupportState("unsupported");
|
|
24062
|
-
}
|
|
24063
|
-
return () => {
|
|
24064
|
-
shouldRunRef.current = false;
|
|
24065
|
-
recognition.stop();
|
|
24066
|
-
recognitionRef.current = null;
|
|
24067
|
-
};
|
|
24068
|
-
}, [visible]);
|
|
24069
|
-
if (!visible) {
|
|
24070
|
-
return null;
|
|
24071
|
-
}
|
|
24072
|
-
const renderedText = supportState === "unsupported" ? t("pptx.subtitles.notSupported") : captionText.length > 0 ? captionText : t("pptx.subtitles.listening");
|
|
24073
|
-
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 }) }) });
|
|
24594
|
+
)
|
|
24595
|
+
] });
|
|
24074
24596
|
}
|
|
24075
24597
|
function SlideLayer({ slide, templateElements, canvasSize }) {
|
|
24076
24598
|
const safeWidth = Math.max(canvasSize.width, 1);
|
|
@@ -25498,6 +26020,7 @@ function BroadcastDialog({
|
|
|
25498
26020
|
const [copied, setCopied] = useState(false);
|
|
25499
26021
|
const dialogRef = useRef(null);
|
|
25500
26022
|
const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
|
|
26023
|
+
useModalFocus(open, dialogRef, onClose);
|
|
25501
26024
|
useEffect(() => {
|
|
25502
26025
|
if (open && !isBroadcasting) {
|
|
25503
26026
|
const broadcastRoom = defaultRoomId ? `broadcast-${defaultRoomId}` : generateBroadcastRoomId();
|
|
@@ -25506,23 +26029,6 @@ function BroadcastDialog({
|
|
|
25506
26029
|
setServerUrl(defaultServerUrl ?? DEFAULT_BROADCAST_SERVER_URL);
|
|
25507
26030
|
}
|
|
25508
26031
|
}, [open, isBroadcasting, defaultRoomId, defaultUserName, defaultServerUrl]);
|
|
25509
|
-
useEffect(() => {
|
|
25510
|
-
if (!open) {
|
|
25511
|
-
return;
|
|
25512
|
-
}
|
|
25513
|
-
function handleKeyDown(e) {
|
|
25514
|
-
if (e.key === "Escape") {
|
|
25515
|
-
onClose();
|
|
25516
|
-
}
|
|
25517
|
-
}
|
|
25518
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
25519
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
25520
|
-
}, [open, onClose]);
|
|
25521
|
-
useEffect(() => {
|
|
25522
|
-
if (open && dialogRef.current) {
|
|
25523
|
-
dialogRef.current.focus();
|
|
25524
|
-
}
|
|
25525
|
-
}, [open]);
|
|
25526
26032
|
const activeRoomId = isBroadcasting ? collab.config.roomId : roomId;
|
|
25527
26033
|
const activeServerUrl = isBroadcasting ? collab.config.serverUrl : serverUrl;
|
|
25528
26034
|
const broadcastUrl = typeof window !== "undefined" ? buildBroadcastViewerUrl(activeRoomId, activeServerUrl, window.location) : activeRoomId;
|
|
@@ -25795,37 +26301,265 @@ function ActiveBroadcastView({
|
|
|
25795
26301
|
] })
|
|
25796
26302
|
] }, user.clientId)) })
|
|
25797
26303
|
] }),
|
|
25798
|
-
/* @__PURE__ */ jsx(
|
|
25799
|
-
"button",
|
|
25800
|
-
{
|
|
25801
|
-
type: "button",
|
|
25802
|
-
onClick: onStopBroadcast,
|
|
25803
|
-
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",
|
|
25804
|
-
children: t("pptx.broadcast.stopBroadcast")
|
|
25805
|
-
}
|
|
25806
|
-
)
|
|
26304
|
+
/* @__PURE__ */ jsx(
|
|
26305
|
+
"button",
|
|
26306
|
+
{
|
|
26307
|
+
type: "button",
|
|
26308
|
+
onClick: onStopBroadcast,
|
|
26309
|
+
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",
|
|
26310
|
+
children: t("pptx.broadcast.stopBroadcast")
|
|
26311
|
+
}
|
|
26312
|
+
)
|
|
26313
|
+
] });
|
|
26314
|
+
}
|
|
26315
|
+
function getInitials3(name) {
|
|
26316
|
+
const parts = name.trim().split(/\s+/u);
|
|
26317
|
+
return parts.length >= 2 ? (parts[0][0] + parts[parts.length - 1][0]).toUpperCase() : name.slice(0, 2).toUpperCase();
|
|
26318
|
+
}
|
|
26319
|
+
function isP2P(config) {
|
|
26320
|
+
return config.transport === "webrtc" || !config.serverUrl?.trim();
|
|
26321
|
+
}
|
|
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") })
|
|
25807
26556
|
] });
|
|
25808
26557
|
}
|
|
25809
|
-
function
|
|
25810
|
-
|
|
25811
|
-
|
|
25812
|
-
|
|
25813
|
-
|
|
25814
|
-
return name.slice(0, 2).toUpperCase();
|
|
25815
|
-
}
|
|
25816
|
-
function isP2P(config) {
|
|
25817
|
-
return config.transport === "webrtc" || !config.serverUrl?.trim();
|
|
25818
|
-
}
|
|
25819
|
-
function buildCollabShareUrl(config) {
|
|
25820
|
-
if (typeof window === "undefined") {
|
|
25821
|
-
return config.roomId;
|
|
25822
|
-
}
|
|
25823
|
-
const base = `${window.location.origin}${window.location.pathname}`;
|
|
25824
|
-
const room = encodeURIComponent(config.roomId);
|
|
25825
|
-
if (isP2P(config)) {
|
|
25826
|
-
return `${base}?room=${room}&transport=webrtc`;
|
|
25827
|
-
}
|
|
25828
|
-
return `${base}?room=${room}&server=${encodeURIComponent(config.serverUrl ?? "")}`;
|
|
26558
|
+
function shareUrl2(config) {
|
|
26559
|
+
return buildCollaborationShareUrl(
|
|
26560
|
+
config,
|
|
26561
|
+
typeof window === "undefined" ? void 0 : { origin: window.location.origin, pathname: window.location.pathname }
|
|
26562
|
+
);
|
|
25829
26563
|
}
|
|
25830
26564
|
function ShareDialog({
|
|
25831
26565
|
open,
|
|
@@ -25844,9 +26578,12 @@ function ShareDialog({
|
|
|
25844
26578
|
const [roomId, setRoomId] = useState(defaultRoomId ?? "");
|
|
25845
26579
|
const [userName, setUserName] = useState(defaultUserName ?? "");
|
|
25846
26580
|
const [serverUrl, setServerUrl] = useState(defaultServerUrl ?? "");
|
|
26581
|
+
const [mode, setMode] = useState("create");
|
|
26582
|
+
const [invitation, setInvitation] = useState("");
|
|
25847
26583
|
const [copied, setCopied] = useState(false);
|
|
25848
26584
|
const dialogRef = useRef(null);
|
|
25849
26585
|
const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
|
|
26586
|
+
useModalFocus(open, dialogRef, onClose);
|
|
25850
26587
|
useEffect(() => {
|
|
25851
26588
|
if (activeCollaboration) {
|
|
25852
26589
|
setRoomId(activeCollaboration.roomId);
|
|
@@ -25854,45 +26591,21 @@ function ShareDialog({
|
|
|
25854
26591
|
setServerUrl(activeCollaboration.serverUrl);
|
|
25855
26592
|
}
|
|
25856
26593
|
}, [activeCollaboration]);
|
|
25857
|
-
useEffect(() => {
|
|
25858
|
-
if (!open) {
|
|
25859
|
-
return;
|
|
25860
|
-
}
|
|
25861
|
-
function handleKeyDown(e) {
|
|
25862
|
-
if (e.key === "Escape") {
|
|
25863
|
-
onClose();
|
|
25864
|
-
}
|
|
25865
|
-
}
|
|
25866
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
25867
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
25868
|
-
}, [open, onClose]);
|
|
25869
|
-
useEffect(() => {
|
|
25870
|
-
if (open && dialogRef.current) {
|
|
25871
|
-
dialogRef.current.focus();
|
|
25872
|
-
}
|
|
25873
|
-
}, [open]);
|
|
25874
26594
|
const handleCopyRoomId = useCallback(() => {
|
|
25875
26595
|
const config = activeCollaboration ?? { roomId, serverUrl };
|
|
25876
|
-
void navigator.clipboard.writeText(
|
|
26596
|
+
void navigator.clipboard.writeText(shareUrl2(config)).then(() => {
|
|
25877
26597
|
setCopied(true);
|
|
25878
26598
|
setTimeout(() => setCopied(false), 2e3);
|
|
25879
26599
|
return void 0;
|
|
25880
26600
|
});
|
|
25881
26601
|
}, [activeCollaboration, roomId, serverUrl]);
|
|
25882
26602
|
const handleStartSharing = useCallback(() => {
|
|
25883
|
-
|
|
25884
|
-
|
|
26603
|
+
const config = mode === "join" ? buildJoinCollaborationConfig({ invitation, userName, serverUrl }) : buildCreateCollaborationConfig({ roomId, userName, serverUrl });
|
|
26604
|
+
if (config) {
|
|
26605
|
+
onStartCollaboration?.(config);
|
|
25885
26606
|
}
|
|
25886
|
-
|
|
25887
|
-
|
|
25888
|
-
roomId: roomId.trim(),
|
|
25889
|
-
serverUrl: trimmedServer,
|
|
25890
|
-
userName: userName.trim(),
|
|
25891
|
-
// A blank server selects the serverless peer-to-peer transport.
|
|
25892
|
-
transport: resolveTransportForServerUrl(trimmedServer)
|
|
25893
|
-
});
|
|
25894
|
-
}, [roomId, userName, serverUrl, onStartCollaboration]);
|
|
25895
|
-
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;
|
|
25896
26609
|
if (!open) {
|
|
25897
26610
|
return null;
|
|
25898
26611
|
}
|
|
@@ -25955,12 +26668,16 @@ function ShareDialog({
|
|
|
25955
26668
|
) : /* @__PURE__ */ jsx(
|
|
25956
26669
|
StartSessionForm,
|
|
25957
26670
|
{
|
|
26671
|
+
mode,
|
|
26672
|
+
invitation,
|
|
25958
26673
|
roomId,
|
|
25959
26674
|
userName,
|
|
25960
26675
|
serverUrl,
|
|
25961
26676
|
onRoomIdChange: setRoomId,
|
|
25962
26677
|
onUserNameChange: setUserName,
|
|
25963
26678
|
onServerUrlChange: setServerUrl,
|
|
26679
|
+
onModeChange: setMode,
|
|
26680
|
+
onInvitationChange: setInvitation,
|
|
25964
26681
|
preconfigured,
|
|
25965
26682
|
connectionFailed: collab?.status === "error",
|
|
25966
26683
|
onRetry: collab?.retry
|
|
@@ -25983,7 +26700,7 @@ function ShareDialog({
|
|
|
25983
26700
|
disabled: !canStart,
|
|
25984
26701
|
onClick: handleStartSharing,
|
|
25985
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",
|
|
25986
|
-
children: t("pptx.share.startSharing")
|
|
26703
|
+
children: t(mode === "join" ? "pptx.share.joinSession" : "pptx.share.startSharing")
|
|
25987
26704
|
}
|
|
25988
26705
|
)
|
|
25989
26706
|
] })
|
|
@@ -25994,199 +26711,6 @@ function ShareDialog({
|
|
|
25994
26711
|
)
|
|
25995
26712
|
] });
|
|
25996
26713
|
}
|
|
25997
|
-
function StartSessionForm({
|
|
25998
|
-
roomId,
|
|
25999
|
-
userName,
|
|
26000
|
-
serverUrl,
|
|
26001
|
-
onRoomIdChange,
|
|
26002
|
-
onUserNameChange,
|
|
26003
|
-
onServerUrlChange,
|
|
26004
|
-
preconfigured,
|
|
26005
|
-
connectionFailed,
|
|
26006
|
-
onRetry
|
|
26007
|
-
}) {
|
|
26008
|
-
const { t } = useTranslation();
|
|
26009
|
-
const inputReadOnlyClass = preconfigured ? " opacity-70 cursor-not-allowed" : "";
|
|
26010
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
26011
|
-
/* @__PURE__ */ jsx("p", { className: "text-[13px] text-muted-foreground leading-relaxed", children: preconfigured ? t("pptx.share.preconfiguredDescription") : t("pptx.share.description") }),
|
|
26012
|
-
connectionFailed && /* @__PURE__ */ jsxs(
|
|
26013
|
-
"div",
|
|
26014
|
-
{
|
|
26015
|
-
role: "alert",
|
|
26016
|
-
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",
|
|
26017
|
-
children: [
|
|
26018
|
-
/* @__PURE__ */ jsx(LuWifiOff, { className: "w-4 h-4 mt-0.5 shrink-0" }),
|
|
26019
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1", children: [
|
|
26020
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium", children: t("pptx.share.connectionError") }),
|
|
26021
|
-
onRetry && /* @__PURE__ */ jsx(
|
|
26022
|
-
"button",
|
|
26023
|
-
{
|
|
26024
|
-
type: "button",
|
|
26025
|
-
onClick: onRetry,
|
|
26026
|
-
className: "underline underline-offset-2 hover:no-underline",
|
|
26027
|
-
children: t("pptx.collaboration.retry")
|
|
26028
|
-
}
|
|
26029
|
-
)
|
|
26030
|
-
] })
|
|
26031
|
-
]
|
|
26032
|
-
}
|
|
26033
|
-
),
|
|
26034
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26035
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "share-room-id", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.sessionName") }),
|
|
26036
|
-
/* @__PURE__ */ jsx(
|
|
26037
|
-
"input",
|
|
26038
|
-
{
|
|
26039
|
-
id: "share-room-id",
|
|
26040
|
-
type: "text",
|
|
26041
|
-
"aria-label": t("pptx.share.sessionName"),
|
|
26042
|
-
value: roomId,
|
|
26043
|
-
onChange: (e) => onRoomIdChange(e.target.value),
|
|
26044
|
-
readOnly: preconfigured,
|
|
26045
|
-
placeholder: t("pptx.share.sessionPlaceholder"),
|
|
26046
|
-
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}`
|
|
26047
|
-
}
|
|
26048
|
-
),
|
|
26049
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: t("pptx.share.sessionHint") })
|
|
26050
|
-
] }),
|
|
26051
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26052
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "share-user-name", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.displayName") }),
|
|
26053
|
-
/* @__PURE__ */ jsx(
|
|
26054
|
-
"input",
|
|
26055
|
-
{
|
|
26056
|
-
id: "share-user-name",
|
|
26057
|
-
type: "text",
|
|
26058
|
-
"aria-label": t("pptx.share.displayName"),
|
|
26059
|
-
value: userName,
|
|
26060
|
-
onChange: (e) => onUserNameChange(e.target.value),
|
|
26061
|
-
readOnly: preconfigured,
|
|
26062
|
-
placeholder: t("pptx.share.namePlaceholder"),
|
|
26063
|
-
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}`
|
|
26064
|
-
}
|
|
26065
|
-
)
|
|
26066
|
-
] }),
|
|
26067
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26068
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "share-server-url", className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.serverLabel") }),
|
|
26069
|
-
/* @__PURE__ */ jsx(
|
|
26070
|
-
"input",
|
|
26071
|
-
{
|
|
26072
|
-
id: "share-server-url",
|
|
26073
|
-
type: "text",
|
|
26074
|
-
"aria-label": t("pptx.share.serverLabel"),
|
|
26075
|
-
value: serverUrl,
|
|
26076
|
-
onChange: (e) => onServerUrlChange(e.target.value),
|
|
26077
|
-
readOnly: preconfigured,
|
|
26078
|
-
placeholder: t("pptx.share.serverPlaceholder"),
|
|
26079
|
-
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}`
|
|
26080
|
-
}
|
|
26081
|
-
)
|
|
26082
|
-
] }),
|
|
26083
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: serverUrl.trim().length === 0 ? t("pptx.share.p2pHint") : t("pptx.share.serverHint") })
|
|
26084
|
-
] });
|
|
26085
|
-
}
|
|
26086
|
-
function ActiveSessionView({
|
|
26087
|
-
collab,
|
|
26088
|
-
activeCollaboration,
|
|
26089
|
-
copied,
|
|
26090
|
-
onCopyRoomId,
|
|
26091
|
-
onStopCollaboration
|
|
26092
|
-
}) {
|
|
26093
|
-
const { t } = useTranslation();
|
|
26094
|
-
const statusColor = collab.status === "connected" ? "text-green-400" : collab.status === "connecting" ? "text-yellow-400" : "text-red-400";
|
|
26095
|
-
const statusIcon = collab.status === "connected" || collab.status === "connecting" ? /* @__PURE__ */ jsx(LuWifi, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(LuWifiOff, { className: "w-4 h-4" });
|
|
26096
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
26097
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26098
|
-
/* @__PURE__ */ jsx("span", { className: statusColor, children: statusIcon }),
|
|
26099
|
-
/* @__PURE__ */ jsx("span", { className: "text-[13px] font-medium text-foreground capitalize", children: collab.status }),
|
|
26100
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[12px] text-muted-foreground ml-auto flex items-center gap-1", children: [
|
|
26101
|
-
/* @__PURE__ */ jsx(LuUsers, { className: "w-3.5 h-3.5" }),
|
|
26102
|
-
t("pptx.collaboration.userCount", { count: collab.connectedCount })
|
|
26103
|
-
] })
|
|
26104
|
-
] }),
|
|
26105
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26106
|
-
/* @__PURE__ */ jsx("label", { className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.shareLink") }),
|
|
26107
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26108
|
-
/* @__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) }),
|
|
26109
|
-
/* @__PURE__ */ jsx(
|
|
26110
|
-
"button",
|
|
26111
|
-
{
|
|
26112
|
-
type: "button",
|
|
26113
|
-
onClick: onCopyRoomId,
|
|
26114
|
-
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",
|
|
26115
|
-
title: t("pptx.share.copyLink"),
|
|
26116
|
-
children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26117
|
-
/* @__PURE__ */ jsx(LuCheck, { className: "w-3.5 h-3.5 text-green-400" }),
|
|
26118
|
-
/* @__PURE__ */ jsx("span", { children: t("pptx.share.copied") })
|
|
26119
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26120
|
-
/* @__PURE__ */ jsx(LuCopy, { className: "w-3.5 h-3.5" }),
|
|
26121
|
-
/* @__PURE__ */ jsx("span", { children: t("pptx.share.copyUrl") })
|
|
26122
|
-
] })
|
|
26123
|
-
}
|
|
26124
|
-
)
|
|
26125
|
-
] }),
|
|
26126
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: t("pptx.share.shareHint") })
|
|
26127
|
-
] }),
|
|
26128
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[11px] text-muted-foreground", children: [
|
|
26129
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
26130
|
-
t("pptx.share.room"),
|
|
26131
|
-
" ",
|
|
26132
|
-
/* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: collab.config.roomId })
|
|
26133
|
-
] }),
|
|
26134
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
26135
|
-
t("pptx.share.server"),
|
|
26136
|
-
" ",
|
|
26137
|
-
/* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: isP2P(collab.config) ? t("pptx.share.p2pServerValue") : collab.config.serverUrl })
|
|
26138
|
-
] })
|
|
26139
|
-
] }),
|
|
26140
|
-
collab.remoteUsers.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
26141
|
-
/* @__PURE__ */ jsx("label", { className: "block text-[12px] font-medium text-foreground", children: t("pptx.share.connectedUsers") }),
|
|
26142
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded border border-border bg-background divide-y divide-border max-h-[140px] overflow-y-auto", children: [
|
|
26143
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [
|
|
26144
|
-
/* @__PURE__ */ jsx(
|
|
26145
|
-
"div",
|
|
26146
|
-
{
|
|
26147
|
-
className: "w-6 h-6 rounded-full flex items-center justify-center text-[9px] font-semibold text-white shrink-0",
|
|
26148
|
-
style: { backgroundColor: collab.config.userColor ?? "#6366f1" },
|
|
26149
|
-
children: getInitials3(activeCollaboration?.userName ?? collab.config.userName)
|
|
26150
|
-
}
|
|
26151
|
-
),
|
|
26152
|
-
/* @__PURE__ */ jsx("span", { className: "text-[12px] text-foreground truncate", children: activeCollaboration?.userName ?? collab.config.userName }),
|
|
26153
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground ml-auto", children: t("pptx.share.you") })
|
|
26154
|
-
] }),
|
|
26155
|
-
collab.remoteUsers.map((user) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [
|
|
26156
|
-
/* @__PURE__ */ jsx(
|
|
26157
|
-
"div",
|
|
26158
|
-
{
|
|
26159
|
-
className: "w-6 h-6 rounded-full flex items-center justify-center text-[9px] font-semibold text-white shrink-0",
|
|
26160
|
-
style: { backgroundColor: user.userColor },
|
|
26161
|
-
children: user.userAvatar ? /* @__PURE__ */ jsx(
|
|
26162
|
-
"img",
|
|
26163
|
-
{
|
|
26164
|
-
src: user.userAvatar,
|
|
26165
|
-
alt: "",
|
|
26166
|
-
className: "w-full h-full rounded-full object-cover"
|
|
26167
|
-
}
|
|
26168
|
-
) : getInitials3(user.userName)
|
|
26169
|
-
}
|
|
26170
|
-
),
|
|
26171
|
-
/* @__PURE__ */ jsx("span", { className: "text-[12px] text-foreground truncate", children: user.userName }),
|
|
26172
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground ml-auto", children: [
|
|
26173
|
-
"Slide ",
|
|
26174
|
-
user.activeSlideIndex + 1
|
|
26175
|
-
] })
|
|
26176
|
-
] }, user.clientId))
|
|
26177
|
-
] })
|
|
26178
|
-
] }),
|
|
26179
|
-
onStopCollaboration && /* @__PURE__ */ jsx(
|
|
26180
|
-
"button",
|
|
26181
|
-
{
|
|
26182
|
-
type: "button",
|
|
26183
|
-
onClick: onStopCollaboration,
|
|
26184
|
-
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",
|
|
26185
|
-
children: t("pptx.share.stopSharing")
|
|
26186
|
-
}
|
|
26187
|
-
)
|
|
26188
|
-
] });
|
|
26189
|
-
}
|
|
26190
26714
|
function HyperlinkTabContent({
|
|
26191
26715
|
targetType,
|
|
26192
26716
|
url,
|
|
@@ -27808,7 +28332,7 @@ function SlideCanvas({
|
|
|
27808
28332
|
// pinch-zoom. View/present mode keeps the default so the slide can
|
|
27809
28333
|
// still be scrolled and swipe-navigated.
|
|
27810
28334
|
touchAction: isEditableCanvas ? "none" : void 0,
|
|
27811
|
-
...
|
|
28335
|
+
...getReactSlideBackgroundStyle(activeSlide)
|
|
27812
28336
|
},
|
|
27813
28337
|
onClick: handleStageClick,
|
|
27814
28338
|
onDoubleClick: handleStageDblClick,
|
|
@@ -28988,10 +29512,11 @@ function EquationEditorDialog({
|
|
|
28988
29512
|
const [latex, setLatex] = useState(initialLatex);
|
|
28989
29513
|
const deferredLatex = useDeferredValue(latex);
|
|
28990
29514
|
const textareaRef = useRef(null);
|
|
29515
|
+
const dialogRef = useRef(null);
|
|
29516
|
+
useModalFocus(isOpen, dialogRef, onClose, textareaRef);
|
|
28991
29517
|
useEffect(() => {
|
|
28992
29518
|
if (isOpen) {
|
|
28993
29519
|
setLatex(initialLatex);
|
|
28994
|
-
setTimeout(() => textareaRef.current?.focus(), 50);
|
|
28995
29520
|
}
|
|
28996
29521
|
}, [isOpen, initialLatex]);
|
|
28997
29522
|
const { mathml, omml } = useMemo(() => {
|
|
@@ -29055,11 +29580,13 @@ function EquationEditorDialog({
|
|
|
29055
29580
|
children: /* @__PURE__ */ jsxs(
|
|
29056
29581
|
"div",
|
|
29057
29582
|
{
|
|
29583
|
+
ref: dialogRef,
|
|
29058
29584
|
style: panelStyle,
|
|
29059
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)]",
|
|
29060
29586
|
onClick: (e) => e.stopPropagation(),
|
|
29061
29587
|
role: "dialog",
|
|
29062
29588
|
"aria-modal": "true",
|
|
29589
|
+
tabIndex: -1,
|
|
29063
29590
|
"aria-label": isEditing ? t("pptx.equation.editTitle", "Edit Equation") : t("pptx.equation.insertTitle", "Insert Equation"),
|
|
29064
29591
|
children: [
|
|
29065
29592
|
/* @__PURE__ */ jsxs(
|
|
@@ -29075,6 +29602,7 @@ function EquationEditorDialog({
|
|
|
29075
29602
|
type: "button",
|
|
29076
29603
|
onClick: onClose,
|
|
29077
29604
|
className: "p-1 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
29605
|
+
"aria-label": t("pptx.settings.close"),
|
|
29078
29606
|
children: /* @__PURE__ */ jsx(LuX, { className: "w-4 h-4" })
|
|
29079
29607
|
}
|
|
29080
29608
|
)
|
|
@@ -29209,6 +29737,8 @@ function InsertSmartArtDialog({
|
|
|
29209
29737
|
const { panelStyle, handlers: dragHandlers } = useModalDismissDrag(onClose);
|
|
29210
29738
|
const [activeCategory, setActiveCategory] = useState("list");
|
|
29211
29739
|
const [selectedLayout, setSelectedLayout] = useState(null);
|
|
29740
|
+
const dialogRef = useRef(null);
|
|
29741
|
+
useModalFocus(isOpen, dialogRef, onClose);
|
|
29212
29742
|
const filteredPresets = PRESETS.filter((p) => p.category === activeCategory);
|
|
29213
29743
|
const handleInsert = useCallback(() => {
|
|
29214
29744
|
if (!selectedLayout) {
|
|
@@ -29243,11 +29773,13 @@ function InsertSmartArtDialog({
|
|
|
29243
29773
|
children: /* @__PURE__ */ jsxs(
|
|
29244
29774
|
"div",
|
|
29245
29775
|
{
|
|
29776
|
+
ref: dialogRef,
|
|
29246
29777
|
style: panelStyle,
|
|
29247
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)]",
|
|
29248
29779
|
role: "dialog",
|
|
29249
29780
|
"aria-modal": "true",
|
|
29250
29781
|
"aria-label": t("pptx.smartart.insertTitle"),
|
|
29782
|
+
tabIndex: -1,
|
|
29251
29783
|
children: [
|
|
29252
29784
|
/* @__PURE__ */ jsxs(
|
|
29253
29785
|
"div",
|
|
@@ -29546,9 +30078,19 @@ function ViewerDialogGroup(props) {
|
|
|
29546
30078
|
] });
|
|
29547
30079
|
}
|
|
29548
30080
|
function ViewerPresentationLayer(props) {
|
|
29549
|
-
const {
|
|
30081
|
+
const {
|
|
30082
|
+
mode,
|
|
30083
|
+
slides,
|
|
30084
|
+
canvasSize,
|
|
30085
|
+
templateElements,
|
|
30086
|
+
presentation,
|
|
30087
|
+
onExitPresentation,
|
|
30088
|
+
isMobile,
|
|
30089
|
+
onUpdateNotes
|
|
30090
|
+
} = props;
|
|
29550
30091
|
const presenterActive = mode === "present" && presentation.presenterMode;
|
|
29551
30092
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
30093
|
+
mode === "present" && !presentation.presenterMode && /* @__PURE__ */ jsx(PresentationAudienceEffects, { snapshot: presentation.presenterSnapshot }),
|
|
29552
30094
|
presenterActive && (isMobile ? /* @__PURE__ */ jsx(
|
|
29553
30095
|
MobilePresenterView,
|
|
29554
30096
|
{
|
|
@@ -29572,7 +30114,20 @@ function ViewerPresentationLayer(props) {
|
|
|
29572
30114
|
onExit: onExitPresentation,
|
|
29573
30115
|
onOpenAudienceWindow: presentation.openAudienceWindow,
|
|
29574
30116
|
onCloseAudienceWindow: presentation.closeAudienceWindow,
|
|
29575
|
-
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
|
|
29576
30131
|
}
|
|
29577
30132
|
)),
|
|
29578
30133
|
mode === "present" && presentation.rehearsing && /* @__PURE__ */ jsx(
|
|
@@ -29750,7 +30305,7 @@ function ViewerCanvasArea(props) {
|
|
|
29750
30305
|
{
|
|
29751
30306
|
handoutMaster: s.handoutMaster,
|
|
29752
30307
|
canvasSize,
|
|
29753
|
-
slidesPerPage: s.handoutSlidesPerPage
|
|
30308
|
+
slidesPerPage: s.handoutMaster?.slidesPerPage ?? s.handoutSlidesPerPage
|
|
29754
30309
|
}
|
|
29755
30310
|
) : /* @__PURE__ */ jsx(
|
|
29756
30311
|
SlideCanvas,
|
|
@@ -30797,6 +31352,11 @@ function ThemeGallery({
|
|
|
30797
31352
|
const { t } = useTranslation();
|
|
30798
31353
|
const [selectedTheme, setSelectedTheme] = useState(currentTheme ?? null);
|
|
30799
31354
|
const fileInputRef = useRef(null);
|
|
31355
|
+
useEffect(() => {
|
|
31356
|
+
if (open) {
|
|
31357
|
+
setSelectedTheme(currentTheme ?? null);
|
|
31358
|
+
}
|
|
31359
|
+
}, [currentTheme, open]);
|
|
30800
31360
|
if (!open) {
|
|
30801
31361
|
return null;
|
|
30802
31362
|
}
|
|
@@ -30924,6 +31484,9 @@ function ViewerSidePanels(props) {
|
|
|
30924
31484
|
onResizeRight
|
|
30925
31485
|
} = props;
|
|
30926
31486
|
const effectiveSlide = mode === "master" ? masterPseudoSlide : activeSlide;
|
|
31487
|
+
const currentBuiltInTheme = BUILT_IN_THEMES.find(
|
|
31488
|
+
(candidate) => themeColorSchemesEqual(s.theme?.colorScheme, candidate.colorScheme)
|
|
31489
|
+
) ?? null;
|
|
30927
31490
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
30928
31491
|
(mode === "edit" || mode === "master") && s.isInspectorPaneOpen && onResizeRight && /* @__PURE__ */ jsx(ResizeHandle, { direction: "horizontal", onResize: onResizeRight }),
|
|
30929
31492
|
/* @__PURE__ */ jsx(
|
|
@@ -31021,7 +31584,7 @@ function ViewerSidePanels(props) {
|
|
|
31021
31584
|
ThemeGallery,
|
|
31022
31585
|
{
|
|
31023
31586
|
open: s.isThemeGalleryOpen,
|
|
31024
|
-
currentTheme:
|
|
31587
|
+
currentTheme: currentBuiltInTheme,
|
|
31025
31588
|
canEdit,
|
|
31026
31589
|
onClose: () => s.setIsThemeGalleryOpen(false),
|
|
31027
31590
|
onApplyTheme: (theme) => {
|
|
@@ -31125,12 +31688,28 @@ function ViewerMainContent(props) {
|
|
|
31125
31688
|
masterViewTab: state.masterViewTab,
|
|
31126
31689
|
notesMaster: state.notesMaster,
|
|
31127
31690
|
handoutMaster: state.handoutMaster,
|
|
31128
|
-
handoutSlidesPerPage: state.handoutSlidesPerPage,
|
|
31691
|
+
handoutSlidesPerPage: state.handoutMaster?.slidesPerPage ?? state.handoutSlidesPerPage,
|
|
31129
31692
|
onSelectMaster: dialogs.handleSelectMaster,
|
|
31130
31693
|
onSelectLayout: dialogs.handleSelectLayout,
|
|
31131
|
-
onCollapse:
|
|
31694
|
+
onCollapse: dialogs.handleCloseMasterView,
|
|
31132
31695
|
onTabChange: state.setMasterViewTab,
|
|
31133
|
-
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
|
+
}
|
|
31134
31713
|
}
|
|
31135
31714
|
),
|
|
31136
31715
|
/* @__PURE__ */ jsx(
|
|
@@ -31862,6 +32441,7 @@ var PowerPointViewer = forwardRef(
|
|
|
31862
32441
|
{
|
|
31863
32442
|
style: themeStyle,
|
|
31864
32443
|
"data-pptx-viewer": "",
|
|
32444
|
+
"aria-busy": loading,
|
|
31865
32445
|
className: "h-full w-full bg-background text-foreground relative",
|
|
31866
32446
|
children: [
|
|
31867
32447
|
/* @__PURE__ */ jsx(
|
|
@@ -32088,6 +32668,7 @@ var PowerPointViewer = forwardRef(
|
|
|
32088
32668
|
templateElements: state.templateElements,
|
|
32089
32669
|
presentation,
|
|
32090
32670
|
onExitPresentation: () => handleSetMode("edit"),
|
|
32671
|
+
onUpdateNotes: propertyHandlers.handleUpdateNotes,
|
|
32091
32672
|
isMobile
|
|
32092
32673
|
}
|
|
32093
32674
|
)
|