@a3s-lab/office 0.33.0 → 0.35.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/README.md +23 -19
- package/dist/0~5809.js +123 -0
- package/dist/{0~7614.js → 0~7828.js} +376 -5
- package/dist/0~pdf-viewer.js +5 -1
- package/dist/0~presentation-editor.js +597 -71
- package/dist/0~spreadsheet-editor.js +166 -18
- package/dist/0~work-pptx-export.js +50 -14
- package/dist/0~work-pptx-import.js +21 -9
- package/dist/4121.js +122 -1
- package/dist/4560.js +33 -0
- package/dist/internal/features/work/editors/presentation-animation-panel.d.ts +11 -0
- package/dist/internal/features/work/editors/presentation-command-types.d.ts +16 -1
- package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +2 -0
- package/dist/internal/features/work/editors/presentation-presenter-view.d.ts +2 -1
- package/dist/internal/features/work/editors/presentation-slide-canvas.d.ts +11 -3
- package/dist/internal/features/work/editors/presentation-text-editor.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-command-selection.d.ts +22 -1
- package/dist/internal/features/work/editors/use-presentation-animation-commands.d.ts +15 -0
- package/dist/internal/features/work/editors/use-presentation-selection.d.ts +1 -1
- package/dist/internal/features/work/work-pptx-animation.d.ts +13 -0
- package/dist/internal/features/work/work-pptx-groups.d.ts +4 -0
- package/dist/internal/features/work/work-presentation-animation-constraints.d.ts +4 -0
- package/dist/internal/features/work/work-presentation-animation.d.ts +20 -0
- package/dist/internal/features/work/work-presentation-clipboard.d.ts +10 -3
- package/dist/internal/features/work/work-types.d.ts +17 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +123 -0
- package/package.json +19 -13
- package/dist/0~work-presentation-transition.js +0 -38
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __webpack_require__ } from "./0~rslib-runtime.js";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
|
-
import { AlignCenter, AlignHorizontalSpaceBetween, AlignLeft, AlignRight, AlignVerticalSpaceBetween, ArrowDownToLine, ArrowUpToLine, BarChart3, Bold, ChevronLeft, ChevronRight, ClipboardPaste, Cloud, Copy, CopyCheck, CopyPlus, GalleryVerticalEnd, Grid2X2, Group, Image, Italic, LayoutTemplate, Link2, MapPin, Maximize2, MessageSquarePlus, MessagesSquare, PanelsTopLeft, Pause, Play, Plus, Presentation, Redo2, RotateCcw, Scissors, Square, SquarePlay, Trash2, Type, Underline, Undo2, Ungroup, X } from "lucide-react";
|
|
4
|
+
import { AlignCenter, AlignHorizontalSpaceBetween, AlignLeft, AlignRight, AlignVerticalSpaceBetween, ArrowDown, ArrowDownToLine, ArrowUp, ArrowUpToLine, BarChart3, Bold, ChevronLeft, ChevronRight, ClipboardPaste, Cloud, Copy, CopyCheck, CopyPlus, GalleryVerticalEnd, Grid2X2, Group, Image, Italic, LayoutTemplate, Link2, MapPin, Maximize2, MessageSquarePlus, MessagesSquare, PanelsTopLeft, Pause, Play, Plus, Presentation, Redo2, RotateCcw, Scissors, Square, SquarePlay, Trash2, Type, Underline, Undo2, Ungroup, X } from "lucide-react";
|
|
5
5
|
import extension_color from "@tiptap/extension-color";
|
|
6
6
|
import extension_placeholder from "@tiptap/extension-placeholder";
|
|
7
7
|
import { TextStyle } from "@tiptap/extension-text-style";
|
|
@@ -19,9 +19,9 @@ import { officePresenceColorStyle, office_text_field_OfficeTextArea, stepOfficeZ
|
|
|
19
19
|
import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, CommittedOfficeNumberField, useOfficeTaskPaneModal, officeFontFamilyLabel, useOfficeDialog, officeFontFamilies, CollectionState, createOfficeKernelClient, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
20
20
|
import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkOfficeRibbonGroup, WorkOfficePreviewBar, WorkOfficeRibbonButton } from "./0~9073.js";
|
|
21
21
|
import { presentationAgentProposalTargets, SpreadsheetChartSeriesStyleEditor, applyPresentationAgentProposalChanges, normalizeOptionalOfficeNumber, SpreadsheetErrorBarEditor, useOfficeHistory, presentationNotesProposalTarget, presentationAgentSelection, SpreadsheetTrendlineEditor, presentationAgentMenuItems } from "./0~3539.js";
|
|
22
|
+
import { slideTransitionDurationMilliseconds, workSlideAnimationIndex, workSlideAnimationForElement, remapWorkSlideAnimations, createWorkSlideTransition, workSlideTransitionsEqual, workSlideAnimationCues, initialWorkSlideAnimationCueIndex, normalizeWorkSlideAnimation, createWorkSlideAnimation, removeWorkSlideAnimationsForElements } from "./0~5809.js";
|
|
22
23
|
import { createOfficeEditorExtension, useOfficeEditorRuntime, useOfficeEditorKeyboardShortcuts } from "./0~3557.js";
|
|
23
24
|
import { isOfficeShortcutBlocked, OfficeColorPicker } from "./0~3635.js";
|
|
24
|
-
import { slideTransitionDurationMilliseconds, createWorkSlideTransition, workSlideTransitionsEqual } from "./0~work-presentation-transition.js";
|
|
25
25
|
import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
|
|
26
26
|
import { showToast } from "./6489.js";
|
|
27
27
|
import { scaledPresentationVisuals } from "./0~work-presentation-visual-scale.js";
|
|
@@ -1397,14 +1397,19 @@ function normalizePresentationChartPercent(value, minimum, maximum) {
|
|
|
1397
1397
|
const PRESENTATION_OBJECT_OFFSET_STEP = 5;
|
|
1398
1398
|
const PRESENTATION_CLIPBOARD_MAX_OFFSET = 20;
|
|
1399
1399
|
let work_presentation_clipboard_clipboard = null;
|
|
1400
|
-
function copyPresentationElements(elements) {
|
|
1400
|
+
function copyPresentationElements(elements, animations = []) {
|
|
1401
1401
|
if (!elements.length) return;
|
|
1402
|
+
const elementIds = new Set(elements.map((element)=>element.id));
|
|
1403
|
+
const selectedAnimations = animations.filter((animation)=>elementIds.has(animation.elementId));
|
|
1402
1404
|
work_presentation_clipboard_clipboard = {
|
|
1403
1405
|
payload: {
|
|
1404
1406
|
kind: 'elements',
|
|
1405
1407
|
elements: work_presentation_clipboard_structuredCopy([
|
|
1406
1408
|
...elements
|
|
1407
|
-
])
|
|
1409
|
+
]),
|
|
1410
|
+
...selectedAnimations.length ? {
|
|
1411
|
+
animations: work_presentation_clipboard_structuredCopy(selectedAnimations)
|
|
1412
|
+
} : {}
|
|
1408
1413
|
},
|
|
1409
1414
|
pasteCount: 0
|
|
1410
1415
|
};
|
|
@@ -1431,42 +1436,48 @@ function takePresentationClipboard() {
|
|
|
1431
1436
|
function hasPresentationClipboard() {
|
|
1432
1437
|
return null !== work_presentation_clipboard_clipboard;
|
|
1433
1438
|
}
|
|
1434
|
-
function
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
])[0];
|
|
1438
|
-
return {
|
|
1439
|
-
...copy,
|
|
1440
|
-
id: createWorkId('element'),
|
|
1441
|
-
x: work_presentation_clipboard_clamp(copy.x + offset, 0, Math.max(0, 100 - copy.width)),
|
|
1442
|
-
y: work_presentation_clipboard_clamp(copy.y + offset, 0, Math.max(0, 100 - copy.height)),
|
|
1443
|
-
placeholder: void 0
|
|
1439
|
+
function clonePresentationElementsAndAnimationsForPaste(elements, animations, offset) {
|
|
1440
|
+
if (!elements.length) return {
|
|
1441
|
+
elements: []
|
|
1444
1442
|
};
|
|
1445
|
-
}
|
|
1446
|
-
function clonePresentationElementsForPaste(elements, offset) {
|
|
1447
|
-
if (!elements.length) return [];
|
|
1448
1443
|
const right = Math.max(...elements.map((element)=>element.x + element.width));
|
|
1449
1444
|
const bottom = Math.max(...elements.map((element)=>element.y + element.height));
|
|
1450
1445
|
const offsetX = work_presentation_clipboard_clamp(offset, 0, Math.max(0, 100 - right));
|
|
1451
1446
|
const offsetY = work_presentation_clipboard_clamp(offset, 0, Math.max(0, 100 - bottom));
|
|
1452
|
-
|
|
1447
|
+
const elementIds = new Map();
|
|
1448
|
+
const copies = remapPresentationGroupPaths(work_presentation_clipboard_structuredCopy(elements)).map((element)=>{
|
|
1449
|
+
const id = createWorkId('element');
|
|
1450
|
+
elementIds.set(element.id, id);
|
|
1451
|
+
return {
|
|
1453
1452
|
...element,
|
|
1454
|
-
id
|
|
1453
|
+
id,
|
|
1455
1454
|
x: element.x + offsetX,
|
|
1456
1455
|
y: element.y + offsetY,
|
|
1457
1456
|
placeholder: void 0
|
|
1458
|
-
}
|
|
1457
|
+
};
|
|
1458
|
+
});
|
|
1459
|
+
return {
|
|
1460
|
+
elements: copies,
|
|
1461
|
+
animations: remapWorkSlideAnimations(animations, elementIds)
|
|
1462
|
+
};
|
|
1459
1463
|
}
|
|
1460
1464
|
function clonePresentationSlideForPaste(slide, existingSlideNames = []) {
|
|
1461
1465
|
const copy = work_presentation_clipboard_structuredCopy(slide);
|
|
1466
|
+
const elementIds = new Map();
|
|
1467
|
+
const elements = remapPresentationGroupPaths(copy.elements).map((element)=>{
|
|
1468
|
+
const id = createWorkId('element');
|
|
1469
|
+
elementIds.set(element.id, id);
|
|
1470
|
+
return {
|
|
1471
|
+
...element,
|
|
1472
|
+
id
|
|
1473
|
+
};
|
|
1474
|
+
});
|
|
1462
1475
|
return {
|
|
1463
1476
|
...copy,
|
|
1464
1477
|
id: createWorkId('slide'),
|
|
1465
1478
|
name: nextPresentationSlideCopyName(slide.name, existingSlideNames),
|
|
1466
|
-
elements
|
|
1467
|
-
|
|
1468
|
-
id: createWorkId('element')
|
|
1469
|
-
})),
|
|
1479
|
+
elements,
|
|
1480
|
+
animations: remapWorkSlideAnimations(copy.animations, elementIds),
|
|
1470
1481
|
comments: copy.comments?.map((comment)=>({
|
|
1471
1482
|
...comment,
|
|
1472
1483
|
id: createWorkId('slide-comment')
|
|
@@ -1720,6 +1731,27 @@ function createPresentationEditorExtensions() {
|
|
|
1720
1731
|
}
|
|
1721
1732
|
})
|
|
1722
1733
|
}),
|
|
1734
|
+
createOfficeEditorExtension({
|
|
1735
|
+
name: 'presentationAnimations',
|
|
1736
|
+
addCommands: ()=>({
|
|
1737
|
+
moveEntranceAnimation: {
|
|
1738
|
+
canExecute: ({ animations }, direction)=>animations.canMoveEntranceAnimation(direction),
|
|
1739
|
+
execute: ({ animations }, direction)=>animations.moveEntranceAnimation(direction)
|
|
1740
|
+
},
|
|
1741
|
+
previewAnimations: {
|
|
1742
|
+
canExecute: ({ animations })=>animations.canPreviewAnimations,
|
|
1743
|
+
execute: ({ animations })=>animations.previewAnimations()
|
|
1744
|
+
},
|
|
1745
|
+
setEntranceAnimation: {
|
|
1746
|
+
canExecute: ({ animations })=>animations.canSetEntranceAnimation,
|
|
1747
|
+
execute: ({ animations }, effect)=>animations.setEntranceAnimation(effect)
|
|
1748
|
+
},
|
|
1749
|
+
updateEntranceAnimation: {
|
|
1750
|
+
canExecute: ({ animations })=>animations.canUpdateEntranceAnimation,
|
|
1751
|
+
execute: ({ animations }, patch)=>animations.updateEntranceAnimation(patch)
|
|
1752
|
+
}
|
|
1753
|
+
})
|
|
1754
|
+
}),
|
|
1723
1755
|
createOfficeEditorExtension({
|
|
1724
1756
|
name: 'presentationElements',
|
|
1725
1757
|
addCommands: ()=>({
|
|
@@ -2393,6 +2425,9 @@ function PlaceholderButtons({ onAdd }) {
|
|
|
2393
2425
|
});
|
|
2394
2426
|
}
|
|
2395
2427
|
const PRESENTATION_WORKSPACE_FOCUS_RETRY_FRAMES = 6;
|
|
2428
|
+
function presentationInitialEditingElementId(elements) {
|
|
2429
|
+
return elements.find((element)=>element.placeholder?.type === 'title' && presentationElementCanEditContent(element) && !element.text.trim() && !element.textRuns?.some((run)=>run.text.trim()))?.id ?? null;
|
|
2430
|
+
}
|
|
2396
2431
|
function restorePresentationWorkspaceFocus(root, getState, focusOrigin = document.activeElement) {
|
|
2397
2432
|
if (!root) return;
|
|
2398
2433
|
const commandTrigger = focusOrigin;
|
|
@@ -2443,17 +2478,20 @@ function presentationCommandsWithObjectFocus(commands, restoreFocus) {
|
|
|
2443
2478
|
distributeElements: afterSuccessfulCommand(commands.distributeElements),
|
|
2444
2479
|
duplicateSlide: afterSuccessfulCommand(commands.duplicateSlide),
|
|
2445
2480
|
groupElements: afterSuccessfulCommand(commands.groupElements),
|
|
2481
|
+
moveEntranceAnimation: afterSuccessfulCommand(commands.moveEntranceAnimation),
|
|
2446
2482
|
pasteSelection: afterSuccessfulCommand(commands.pasteSelection),
|
|
2447
2483
|
redo: afterSuccessfulCommand(commands.redo),
|
|
2448
2484
|
reorderElement: afterSuccessfulCommand(commands.reorderElement),
|
|
2449
2485
|
setTransition: afterSuccessfulCommand(commands.setTransition),
|
|
2486
|
+
setEntranceAnimation: afterSuccessfulCommand(commands.setEntranceAnimation),
|
|
2450
2487
|
setViewMode: afterSuccessfulCommand(commands.setViewMode),
|
|
2451
2488
|
toggleBold: afterSuccessfulCommand(commands.toggleBold),
|
|
2452
2489
|
toggleItalic: afterSuccessfulCommand(commands.toggleItalic),
|
|
2453
2490
|
toggleUnderline: afterSuccessfulCommand(commands.toggleUnderline),
|
|
2454
2491
|
undo: afterSuccessfulCommand(commands.undo),
|
|
2455
2492
|
ungroupElements: afterSuccessfulCommand(commands.ungroupElements),
|
|
2456
|
-
updateElement: afterSuccessfulCommand(commands.updateElement)
|
|
2493
|
+
updateElement: afterSuccessfulCommand(commands.updateElement),
|
|
2494
|
+
updateEntranceAnimation: afterSuccessfulCommand(commands.updateEntranceAnimation)
|
|
2457
2495
|
};
|
|
2458
2496
|
}
|
|
2459
2497
|
function presentationChartAnalysisBounds(chart, xValues) {
|
|
@@ -3572,7 +3610,7 @@ function drawRadarChart(context, chart, sourceRect) {
|
|
|
3572
3610
|
});
|
|
3573
3611
|
}
|
|
3574
3612
|
}
|
|
3575
|
-
function SlideCanvas({ content, designContent, slide, interactive, aspectRatio, showPlaceholders = false }) {
|
|
3613
|
+
function SlideCanvas({ content, designContent, slide, interactive, aspectRatio, animationCueIndex, showPlaceholders = false }) {
|
|
3576
3614
|
const view = designContent ? presentationSlideViewFromDesign(designContent, slide) : content ? presentationSlideView(content, slide) : void 0;
|
|
3577
3615
|
const elements = [
|
|
3578
3616
|
...view?.inheritedElements.map((element)=>({
|
|
@@ -3584,6 +3622,7 @@ function SlideCanvas({ content, designContent, slide, interactive, aspectRatio,
|
|
|
3584
3622
|
origin: 'slide'
|
|
3585
3623
|
}))
|
|
3586
3624
|
];
|
|
3625
|
+
const animationPlayback = void 0 === animationCueIndex ? void 0 : slideAnimationPlayback(slide.animations, animationCueIndex);
|
|
3587
3626
|
return /*#__PURE__*/ jsx("span", {
|
|
3588
3627
|
className: `work-slide-canvas ${interactive ? 'interactive' : ''}`,
|
|
3589
3628
|
style: {
|
|
@@ -3593,16 +3632,23 @@ function SlideCanvas({ content, designContent, slide, interactive, aspectRatio,
|
|
|
3593
3632
|
children: elements.map(({ element, origin })=>/*#__PURE__*/ jsx(SlideElementPreview, {
|
|
3594
3633
|
element: element,
|
|
3595
3634
|
origin: origin,
|
|
3596
|
-
showPlaceholder: showPlaceholders
|
|
3635
|
+
showPlaceholder: showPlaceholders,
|
|
3636
|
+
animationPlayback: 'slide' === origin ? animationPlayback?.get(element.id) : void 0
|
|
3597
3637
|
}, `${origin}:${element.id}`))
|
|
3598
3638
|
});
|
|
3599
3639
|
}
|
|
3600
|
-
function SlideElementPreview({ element, origin, showPlaceholder = false }) {
|
|
3640
|
+
function SlideElementPreview({ animationPlayback, element, origin, showPlaceholder = false }) {
|
|
3601
3641
|
const hasRichText = element.textRuns?.some((run)=>run.text.length > 0);
|
|
3602
3642
|
return /*#__PURE__*/ jsx("span", {
|
|
3603
3643
|
className: `work-slide-element ${element.type} ${origin} ${showPlaceholder && element.placeholder ? 'placeholder' : ''}`.trim(),
|
|
3644
|
+
"data-slide-preview-element-id": element.id,
|
|
3604
3645
|
"data-slide-element-origin": origin,
|
|
3605
|
-
|
|
3646
|
+
"data-slide-animation-effect": animationPlayback?.animation.effect,
|
|
3647
|
+
"data-slide-animation-state": animationPlayback?.state,
|
|
3648
|
+
style: {
|
|
3649
|
+
...slideElementStyle(element),
|
|
3650
|
+
...slideElementAnimationStyle(animationPlayback)
|
|
3651
|
+
},
|
|
3606
3652
|
children: 'image' === element.type && element.image ? /*#__PURE__*/ jsx("img", {
|
|
3607
3653
|
src: element.image.dataUrl,
|
|
3608
3654
|
alt: element.altText ?? element.image.name
|
|
@@ -3658,6 +3704,8 @@ function slideElementStyle(element) {
|
|
|
3658
3704
|
borderRadius: 'ellipse' === element.shapeType ? '50%' : `${element.radius ?? 0}%`,
|
|
3659
3705
|
clipPath: shapeClipPath,
|
|
3660
3706
|
opacity: element.opacity,
|
|
3707
|
+
'--work-slide-element-opacity': element.opacity ?? 1,
|
|
3708
|
+
'--work-slide-element-rotation': `${element.rotation ?? 0}deg`,
|
|
3661
3709
|
transform: element.rotation ? `rotate(${element.rotation}deg)` : void 0,
|
|
3662
3710
|
transformOrigin: 'center',
|
|
3663
3711
|
...'line' === element.type ? {
|
|
@@ -3666,6 +3714,27 @@ function slideElementStyle(element) {
|
|
|
3666
3714
|
} : {}
|
|
3667
3715
|
};
|
|
3668
3716
|
}
|
|
3717
|
+
function slideAnimationPlayback(animations, activeCueIndex) {
|
|
3718
|
+
const playback = new Map();
|
|
3719
|
+
for (const [cueIndex, cue] of workSlideAnimationCues(animations).entries())for (const item of cue.items)playback.set(item.animation.elementId, {
|
|
3720
|
+
animation: item.animation,
|
|
3721
|
+
startOffsetMs: item.startOffsetMs,
|
|
3722
|
+
state: cueIndex < activeCueIndex ? 'finished' : cueIndex === activeCueIndex ? 'playing' : 'pending'
|
|
3723
|
+
});
|
|
3724
|
+
return playback;
|
|
3725
|
+
}
|
|
3726
|
+
function slideElementAnimationStyle(playback) {
|
|
3727
|
+
if (!playback) return {};
|
|
3728
|
+
const direction = playback.animation.direction ?? 'left';
|
|
3729
|
+
const translateX = 'left' === direction ? '-18%' : 'right' === direction ? '18%' : '0';
|
|
3730
|
+
const translateY = 'up' === direction ? '-18%' : 'down' === direction ? '18%' : '0';
|
|
3731
|
+
return {
|
|
3732
|
+
'--work-slide-animation-delay': `${playback.startOffsetMs}ms`,
|
|
3733
|
+
'--work-slide-animation-duration': `${playback.animation.durationMs}ms`,
|
|
3734
|
+
'--work-slide-animation-translate-x': translateX,
|
|
3735
|
+
'--work-slide-animation-translate-y': translateY
|
|
3736
|
+
};
|
|
3737
|
+
}
|
|
3669
3738
|
function slideTextStyle(element) {
|
|
3670
3739
|
return {
|
|
3671
3740
|
color: element.color,
|
|
@@ -3741,7 +3810,7 @@ function createPresentationTimerController(now = Date.now()) {
|
|
|
3741
3810
|
runningSinceMilliseconds: now
|
|
3742
3811
|
};
|
|
3743
3812
|
}
|
|
3744
|
-
function PresentationPresenterView({ content, slide, nextSlide, index, total, aspectRatio, timer }) {
|
|
3813
|
+
function PresentationPresenterView({ animationCueIndex, content, slide, nextSlide, index, total, aspectRatio, timer }) {
|
|
3745
3814
|
const [, setTimerRevision] = useState(0);
|
|
3746
3815
|
const now = Date.now();
|
|
3747
3816
|
const running = null !== timer.runningSinceMilliseconds;
|
|
@@ -3839,6 +3908,7 @@ function PresentationPresenterView({ content, slide, nextSlide, index, total, as
|
|
|
3839
3908
|
children: slide.name
|
|
3840
3909
|
}),
|
|
3841
3910
|
/*#__PURE__*/ jsx(SlideCanvas, {
|
|
3911
|
+
animationCueIndex: animationCueIndex,
|
|
3842
3912
|
content: content,
|
|
3843
3913
|
slide: slide,
|
|
3844
3914
|
interactive: false,
|
|
@@ -3901,6 +3971,7 @@ function formatDuration(seconds) {
|
|
|
3901
3971
|
}
|
|
3902
3972
|
function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0, onExit }) {
|
|
3903
3973
|
const [playback, setPlayback] = useState({
|
|
3974
|
+
animationCueIndex: initialAnimationCueIndex(content.slides[presentationPlaybackIndex(initialIndex, content.slides.length)]),
|
|
3904
3975
|
index: presentationPlaybackIndex(initialIndex, content.slides.length),
|
|
3905
3976
|
transitionKey: 0
|
|
3906
3977
|
});
|
|
@@ -3931,12 +4002,52 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
3931
4002
|
setPlayback((current)=>{
|
|
3932
4003
|
const index = Math.min(Math.max(current.index + delta, 0), content.slides.length - 1);
|
|
3933
4004
|
return index === current.index ? current : {
|
|
4005
|
+
animationCueIndex: initialAnimationCueIndex(content.slides[index]),
|
|
4006
|
+
index,
|
|
4007
|
+
transitionKey: current.transitionKey + 1
|
|
4008
|
+
};
|
|
4009
|
+
});
|
|
4010
|
+
}, [
|
|
4011
|
+
content.slides
|
|
4012
|
+
]);
|
|
4013
|
+
const advance = useCallback(()=>{
|
|
4014
|
+
setPlayback((current)=>{
|
|
4015
|
+
const currentSlide = content.slides[current.index];
|
|
4016
|
+
const cueCount = workSlideAnimationCues(currentSlide?.animations).length;
|
|
4017
|
+
if (current.animationCueIndex < cueCount - 1) return {
|
|
4018
|
+
...current,
|
|
4019
|
+
animationCueIndex: current.animationCueIndex + 1
|
|
4020
|
+
};
|
|
4021
|
+
const index = Math.min(current.index + 1, content.slides.length - 1);
|
|
4022
|
+
if (index === current.index) return current;
|
|
4023
|
+
return {
|
|
4024
|
+
animationCueIndex: initialAnimationCueIndex(content.slides[index]),
|
|
4025
|
+
index,
|
|
4026
|
+
transitionKey: current.transitionKey + 1
|
|
4027
|
+
};
|
|
4028
|
+
});
|
|
4029
|
+
}, [
|
|
4030
|
+
content.slides
|
|
4031
|
+
]);
|
|
4032
|
+
const retreat = useCallback(()=>{
|
|
4033
|
+
setPlayback((current)=>{
|
|
4034
|
+
const currentSlide = content.slides[current.index];
|
|
4035
|
+
const initialCueIndex = initialAnimationCueIndex(currentSlide);
|
|
4036
|
+
if (current.animationCueIndex > initialCueIndex) return {
|
|
4037
|
+
...current,
|
|
4038
|
+
animationCueIndex: current.animationCueIndex - 1
|
|
4039
|
+
};
|
|
4040
|
+
const index = Math.max(current.index - 1, 0);
|
|
4041
|
+
if (index === current.index) return current;
|
|
4042
|
+
const previousCues = workSlideAnimationCues(content.slides[index]?.animations);
|
|
4043
|
+
return {
|
|
4044
|
+
animationCueIndex: previousCues.length - 1,
|
|
3934
4045
|
index,
|
|
3935
4046
|
transitionKey: current.transitionKey + 1
|
|
3936
4047
|
};
|
|
3937
4048
|
});
|
|
3938
4049
|
}, [
|
|
3939
|
-
content.slides
|
|
4050
|
+
content.slides
|
|
3940
4051
|
]);
|
|
3941
4052
|
useEffect(()=>{
|
|
3942
4053
|
const onKeyDown = (event)=>{
|
|
@@ -3950,12 +4061,12 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
3950
4061
|
if ((' ' === event.key || 'Spacebar' === event.key) && presentationTargetActivatesWithSpace(event.target)) return;
|
|
3951
4062
|
if ('ArrowRight' === event.key || 'ArrowDown' === event.key || 'PageDown' === event.key || ' ' === event.key || 'Spacebar' === event.key) {
|
|
3952
4063
|
event.preventDefault();
|
|
3953
|
-
|
|
4064
|
+
advance();
|
|
3954
4065
|
return;
|
|
3955
4066
|
}
|
|
3956
4067
|
if ('ArrowLeft' === event.key || 'ArrowUp' === event.key || 'PageUp' === event.key) {
|
|
3957
4068
|
event.preventDefault();
|
|
3958
|
-
|
|
4069
|
+
retreat();
|
|
3959
4070
|
return;
|
|
3960
4071
|
}
|
|
3961
4072
|
if ('Home' === event.key) {
|
|
@@ -3971,9 +4082,11 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
3971
4082
|
window.addEventListener('keydown', onKeyDown);
|
|
3972
4083
|
return ()=>window.removeEventListener('keydown', onKeyDown);
|
|
3973
4084
|
}, [
|
|
4085
|
+
advance,
|
|
3974
4086
|
completeExit,
|
|
3975
4087
|
content.slides.length,
|
|
3976
|
-
move
|
|
4088
|
+
move,
|
|
4089
|
+
retreat
|
|
3977
4090
|
]);
|
|
3978
4091
|
useLayoutEffect(()=>{
|
|
3979
4092
|
const player = playerRef.current;
|
|
@@ -4024,6 +4137,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4024
4137
|
if (!slide) return null;
|
|
4025
4138
|
const aspectRatio = `${content.width ?? 13.333} / ${content.height ?? 7.5}`;
|
|
4026
4139
|
const transition = slide.transition;
|
|
4140
|
+
const animationCues = workSlideAnimationCues(slide.animations);
|
|
4141
|
+
const hasPendingAnimation = playback.animationCueIndex < animationCues.length - 1;
|
|
4027
4142
|
const transitionStyle = {
|
|
4028
4143
|
'--work-slide-transition-duration': `${slideTransitionDurationMilliseconds(transition)}ms`
|
|
4029
4144
|
};
|
|
@@ -4034,6 +4149,7 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4034
4149
|
tabIndex: -1,
|
|
4035
4150
|
children: [
|
|
4036
4151
|
presenter ? /*#__PURE__*/ jsx(PresentationPresenterView, {
|
|
4152
|
+
animationCueIndex: playback.animationCueIndex,
|
|
4037
4153
|
content: content,
|
|
4038
4154
|
slide: slide,
|
|
4039
4155
|
nextSlide: content.slides[playback.index + 1],
|
|
@@ -4048,8 +4164,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4048
4164
|
type: "button",
|
|
4049
4165
|
className: "work-presentation-player-advance",
|
|
4050
4166
|
"aria-label": "单击换到下一张幻灯片",
|
|
4051
|
-
disabled: transition?.advanceOnClick === false || playback.index === content.slides.length - 1,
|
|
4052
|
-
onClick: ()=>
|
|
4167
|
+
disabled: !hasPendingAnimation && (transition?.advanceOnClick === false || playback.index === content.slides.length - 1),
|
|
4168
|
+
onClick: ()=>advance()
|
|
4053
4169
|
}),
|
|
4054
4170
|
/*#__PURE__*/ jsx("div", {
|
|
4055
4171
|
"aria-live": "polite",
|
|
@@ -4061,6 +4177,7 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4061
4177
|
"data-transition-speed": transition?.speed ?? 'medium',
|
|
4062
4178
|
style: transitionStyle,
|
|
4063
4179
|
children: /*#__PURE__*/ jsx(SlideCanvas, {
|
|
4180
|
+
animationCueIndex: playback.animationCueIndex,
|
|
4064
4181
|
content: content,
|
|
4065
4182
|
slide: slide,
|
|
4066
4183
|
interactive: false,
|
|
@@ -4075,8 +4192,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4075
4192
|
type: "button",
|
|
4076
4193
|
"aria-label": "上一张",
|
|
4077
4194
|
"aria-keyshortcuts": "ArrowLeft ArrowUp PageUp",
|
|
4078
|
-
disabled: 0 === playback.index,
|
|
4079
|
-
onClick:
|
|
4195
|
+
disabled: 0 === playback.index && playback.animationCueIndex <= initialAnimationCueIndex(slide),
|
|
4196
|
+
onClick: retreat,
|
|
4080
4197
|
children: /*#__PURE__*/ jsx(ChevronLeft, {
|
|
4081
4198
|
size: 18
|
|
4082
4199
|
})
|
|
@@ -4092,8 +4209,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4092
4209
|
type: "button",
|
|
4093
4210
|
"aria-label": "下一张",
|
|
4094
4211
|
"aria-keyshortcuts": "ArrowRight ArrowDown PageDown Space",
|
|
4095
|
-
disabled: playback.index === content.slides.length - 1,
|
|
4096
|
-
onClick:
|
|
4212
|
+
disabled: !hasPendingAnimation && playback.index === content.slides.length - 1,
|
|
4213
|
+
onClick: advance,
|
|
4097
4214
|
children: /*#__PURE__*/ jsx(ChevronRight, {
|
|
4098
4215
|
size: 18
|
|
4099
4216
|
})
|
|
@@ -4146,6 +4263,9 @@ function presentationPlaybackIndex(index, slideCount) {
|
|
|
4146
4263
|
if (slideCount <= 1) return 0;
|
|
4147
4264
|
return Math.min(slideCount - 1, Math.max(0, Math.trunc(index)));
|
|
4148
4265
|
}
|
|
4266
|
+
function initialAnimationCueIndex(slide) {
|
|
4267
|
+
return initialWorkSlideAnimationCueIndex(workSlideAnimationCues(slide?.animations));
|
|
4268
|
+
}
|
|
4149
4269
|
async function requestPresentationFullscreen(element) {
|
|
4150
4270
|
if (!element.requestFullscreen) return false;
|
|
4151
4271
|
try {
|
|
@@ -4239,6 +4359,7 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
|
|
|
4239
4359
|
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
4240
4360
|
const appliedSignatureRef = useRef(presentationTextElementSignature(element));
|
|
4241
4361
|
const initialContentRef = useRef(presentationTextElementHtml(element));
|
|
4362
|
+
const initialFocusTargetRef = useRef("u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null);
|
|
4242
4363
|
elementRef.current = element;
|
|
4243
4364
|
onChangeRef.current = onChange;
|
|
4244
4365
|
onEditorChangeRef.current = onEditorChange;
|
|
@@ -4293,7 +4414,8 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
|
|
|
4293
4414
|
useEffect(()=>{
|
|
4294
4415
|
if (!autoFocus || !editor || editor.isDestroyed) return;
|
|
4295
4416
|
const frame = window.requestAnimationFrame(()=>{
|
|
4296
|
-
if (
|
|
4417
|
+
if (editor.isDestroyed || !presentationFocusOwnerIsUnchanged(initialFocusTargetRef.current)) return;
|
|
4418
|
+
editor.commands.focus('end');
|
|
4297
4419
|
});
|
|
4298
4420
|
return ()=>window.cancelAnimationFrame(frame);
|
|
4299
4421
|
}, [
|
|
@@ -4321,6 +4443,12 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
|
|
|
4321
4443
|
style: presentationTextBaseStyle(element)
|
|
4322
4444
|
});
|
|
4323
4445
|
}
|
|
4446
|
+
function presentationFocusOwnerIsUnchanged(initialFocusTarget) {
|
|
4447
|
+
if ("u" < typeof document) return true;
|
|
4448
|
+
const currentFocusTarget = document.activeElement;
|
|
4449
|
+
if (!currentFocusTarget || currentFocusTarget === document.body) return true;
|
|
4450
|
+
return !initialFocusTarget || currentFocusTarget === initialFocusTarget;
|
|
4451
|
+
}
|
|
4324
4452
|
function createPresentationTextEditorExtensions(placeholder = '输入文字') {
|
|
4325
4453
|
return [
|
|
4326
4454
|
starter_kit.configure({
|
|
@@ -4594,6 +4722,233 @@ function commonRunValue(runs, getValue, fallback) {
|
|
|
4594
4722
|
const values = runs.map((run)=>getValue(run) ?? fallback);
|
|
4595
4723
|
return values.every((value)=>value === values[0]) ? values[0] : fallback;
|
|
4596
4724
|
}
|
|
4725
|
+
function PresentationAnimationPanel({ animation, canMove, canPreview, editable, onMove, onPreview, onSetEffect, onUpdate }) {
|
|
4726
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
4727
|
+
children: [
|
|
4728
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4729
|
+
label: "入场动画",
|
|
4730
|
+
children: /*#__PURE__*/ jsxs("fieldset", {
|
|
4731
|
+
className: "work-presentation-animation-options",
|
|
4732
|
+
children: [
|
|
4733
|
+
/*#__PURE__*/ jsx("legend", {
|
|
4734
|
+
className: "sr-only",
|
|
4735
|
+
children: "对象入场动画设置"
|
|
4736
|
+
}),
|
|
4737
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4738
|
+
className: "work-office-field effect",
|
|
4739
|
+
children: [
|
|
4740
|
+
/*#__PURE__*/ jsx("span", {
|
|
4741
|
+
children: "效果"
|
|
4742
|
+
}),
|
|
4743
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4744
|
+
ariaLabel: "对象入场动画效果",
|
|
4745
|
+
disabled: !editable,
|
|
4746
|
+
value: animation?.effect ?? 'none',
|
|
4747
|
+
options: [
|
|
4748
|
+
{
|
|
4749
|
+
value: 'none',
|
|
4750
|
+
label: '无'
|
|
4751
|
+
},
|
|
4752
|
+
{
|
|
4753
|
+
value: 'appear',
|
|
4754
|
+
label: '出现'
|
|
4755
|
+
},
|
|
4756
|
+
{
|
|
4757
|
+
value: 'fade',
|
|
4758
|
+
label: '淡入'
|
|
4759
|
+
},
|
|
4760
|
+
{
|
|
4761
|
+
value: 'fly-in',
|
|
4762
|
+
label: '飞入'
|
|
4763
|
+
},
|
|
4764
|
+
{
|
|
4765
|
+
value: 'zoom',
|
|
4766
|
+
label: '缩放'
|
|
4767
|
+
}
|
|
4768
|
+
],
|
|
4769
|
+
onValueChange: (effect)=>onSetEffect('none' === effect ? void 0 : effect)
|
|
4770
|
+
})
|
|
4771
|
+
]
|
|
4772
|
+
}),
|
|
4773
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4774
|
+
className: "work-office-field trigger",
|
|
4775
|
+
children: [
|
|
4776
|
+
/*#__PURE__*/ jsx("span", {
|
|
4777
|
+
children: "开始"
|
|
4778
|
+
}),
|
|
4779
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4780
|
+
ariaLabel: "对象入场动画触发方式",
|
|
4781
|
+
disabled: !animation,
|
|
4782
|
+
value: animation?.trigger ?? 'on-click',
|
|
4783
|
+
options: [
|
|
4784
|
+
{
|
|
4785
|
+
value: 'on-click',
|
|
4786
|
+
label: '单击时'
|
|
4787
|
+
},
|
|
4788
|
+
{
|
|
4789
|
+
value: 'with-previous',
|
|
4790
|
+
label: '与上一动画同时'
|
|
4791
|
+
},
|
|
4792
|
+
{
|
|
4793
|
+
value: 'after-previous',
|
|
4794
|
+
label: '上一动画之后'
|
|
4795
|
+
}
|
|
4796
|
+
],
|
|
4797
|
+
onValueChange: (trigger)=>onUpdate({
|
|
4798
|
+
trigger: trigger
|
|
4799
|
+
})
|
|
4800
|
+
})
|
|
4801
|
+
]
|
|
4802
|
+
}),
|
|
4803
|
+
animation?.effect === 'fly-in' && /*#__PURE__*/ jsxs("div", {
|
|
4804
|
+
className: "work-office-field direction",
|
|
4805
|
+
children: [
|
|
4806
|
+
/*#__PURE__*/ jsx("span", {
|
|
4807
|
+
children: "方向"
|
|
4808
|
+
}),
|
|
4809
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4810
|
+
ariaLabel: "对象飞入方向",
|
|
4811
|
+
value: animation.direction ?? 'left',
|
|
4812
|
+
options: [
|
|
4813
|
+
{
|
|
4814
|
+
value: 'left',
|
|
4815
|
+
label: '从左侧'
|
|
4816
|
+
},
|
|
4817
|
+
{
|
|
4818
|
+
value: 'right',
|
|
4819
|
+
label: '从右侧'
|
|
4820
|
+
},
|
|
4821
|
+
{
|
|
4822
|
+
value: 'up',
|
|
4823
|
+
label: '从上方'
|
|
4824
|
+
},
|
|
4825
|
+
{
|
|
4826
|
+
value: 'down',
|
|
4827
|
+
label: '从下方'
|
|
4828
|
+
}
|
|
4829
|
+
],
|
|
4830
|
+
onValueChange: (direction)=>onUpdate({
|
|
4831
|
+
direction: direction
|
|
4832
|
+
})
|
|
4833
|
+
})
|
|
4834
|
+
]
|
|
4835
|
+
})
|
|
4836
|
+
]
|
|
4837
|
+
})
|
|
4838
|
+
}),
|
|
4839
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4840
|
+
label: "动画计时",
|
|
4841
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
4842
|
+
className: "work-presentation-animation-timing",
|
|
4843
|
+
children: [
|
|
4844
|
+
/*#__PURE__*/ jsx(AnimationTimingField, {
|
|
4845
|
+
animationId: animation?.id,
|
|
4846
|
+
ariaLabel: "对象入场动画持续秒数",
|
|
4847
|
+
disabled: !animation,
|
|
4848
|
+
label: "持续",
|
|
4849
|
+
maximumMs: 60000,
|
|
4850
|
+
minimumMs: 100,
|
|
4851
|
+
valueMs: animation?.durationMs ?? 500,
|
|
4852
|
+
onCommit: (durationMs)=>onUpdate({
|
|
4853
|
+
durationMs
|
|
4854
|
+
})
|
|
4855
|
+
}),
|
|
4856
|
+
/*#__PURE__*/ jsx(AnimationTimingField, {
|
|
4857
|
+
animationId: animation?.id,
|
|
4858
|
+
ariaLabel: "对象入场动画延迟秒数",
|
|
4859
|
+
disabled: !animation,
|
|
4860
|
+
label: "延迟",
|
|
4861
|
+
maximumMs: 60000,
|
|
4862
|
+
minimumMs: 0,
|
|
4863
|
+
valueMs: animation?.delayMs ?? 0,
|
|
4864
|
+
onCommit: (delayMs)=>onUpdate({
|
|
4865
|
+
delayMs
|
|
4866
|
+
})
|
|
4867
|
+
})
|
|
4868
|
+
]
|
|
4869
|
+
})
|
|
4870
|
+
}),
|
|
4871
|
+
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
4872
|
+
label: "动画顺序",
|
|
4873
|
+
children: [
|
|
4874
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4875
|
+
label: "提前对象动画",
|
|
4876
|
+
visibleLabel: "提前",
|
|
4877
|
+
disabled: !canMove(-1),
|
|
4878
|
+
onClick: ()=>onMove(-1),
|
|
4879
|
+
children: /*#__PURE__*/ jsx(ArrowUp, {
|
|
4880
|
+
size: 19
|
|
4881
|
+
})
|
|
4882
|
+
}),
|
|
4883
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4884
|
+
label: "推后对象动画",
|
|
4885
|
+
visibleLabel: "推后",
|
|
4886
|
+
disabled: !canMove(1),
|
|
4887
|
+
onClick: ()=>onMove(1),
|
|
4888
|
+
children: /*#__PURE__*/ jsx(ArrowDown, {
|
|
4889
|
+
size: 19
|
|
4890
|
+
})
|
|
4891
|
+
})
|
|
4892
|
+
]
|
|
4893
|
+
}),
|
|
4894
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4895
|
+
label: "动画预览",
|
|
4896
|
+
children: /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4897
|
+
label: "预览当前幻灯片动画",
|
|
4898
|
+
visibleLabel: "预览",
|
|
4899
|
+
disabled: !canPreview,
|
|
4900
|
+
onClick: onPreview,
|
|
4901
|
+
children: /*#__PURE__*/ jsx(Play, {
|
|
4902
|
+
size: 19
|
|
4903
|
+
})
|
|
4904
|
+
})
|
|
4905
|
+
})
|
|
4906
|
+
]
|
|
4907
|
+
});
|
|
4908
|
+
}
|
|
4909
|
+
function AnimationTimingField({ animationId, ariaLabel, disabled, label, maximumMs, minimumMs, onCommit, valueMs }) {
|
|
4910
|
+
const canonical = animationSecondsDraft(valueMs);
|
|
4911
|
+
const [draft, setDraft] = useState(canonical);
|
|
4912
|
+
useEffect(()=>setDraft(canonical), [
|
|
4913
|
+
animationId,
|
|
4914
|
+
canonical
|
|
4915
|
+
]);
|
|
4916
|
+
const commit = (value)=>{
|
|
4917
|
+
const next = normalizedAnimationMilliseconds(value, valueMs, minimumMs, maximumMs);
|
|
4918
|
+
setDraft(animationSecondsDraft(next));
|
|
4919
|
+
if (next !== valueMs) onCommit(next);
|
|
4920
|
+
};
|
|
4921
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
4922
|
+
className: "work-office-field seconds",
|
|
4923
|
+
children: [
|
|
4924
|
+
/*#__PURE__*/ jsx("span", {
|
|
4925
|
+
children: label
|
|
4926
|
+
}),
|
|
4927
|
+
/*#__PURE__*/ jsx(OfficeNumberField, {
|
|
4928
|
+
ariaLabel: ariaLabel,
|
|
4929
|
+
disabled: disabled,
|
|
4930
|
+
min: minimumMs / 1000,
|
|
4931
|
+
max: maximumMs / 1000,
|
|
4932
|
+
step: 0.1,
|
|
4933
|
+
value: draft,
|
|
4934
|
+
escapeConsumer: draft !== canonical,
|
|
4935
|
+
onValueChange: setDraft,
|
|
4936
|
+
onCommit: commit,
|
|
4937
|
+
onCancel: ()=>setDraft(canonical)
|
|
4938
|
+
})
|
|
4939
|
+
]
|
|
4940
|
+
});
|
|
4941
|
+
}
|
|
4942
|
+
function animationSecondsDraft(valueMs) {
|
|
4943
|
+
return String(valueMs / 1000);
|
|
4944
|
+
}
|
|
4945
|
+
function normalizedAnimationMilliseconds(value, current, minimum, maximum) {
|
|
4946
|
+
if (!value.trim()) return current;
|
|
4947
|
+
const seconds = Number(value);
|
|
4948
|
+
if (!Number.isFinite(seconds)) return current;
|
|
4949
|
+
const stepped = Math.round(10 * seconds) / 10;
|
|
4950
|
+
return Math.round(1000 * Math.min(maximum / 1000, Math.max(minimum / 1000, stepped)));
|
|
4951
|
+
}
|
|
4597
4952
|
function PresentationTransitionPanel({ slideId, transition, editable, canApplyToAll, onChange, onApplyToAll }) {
|
|
4598
4953
|
const update = (patch)=>{
|
|
4599
4954
|
if (transition) onChange({
|
|
@@ -4891,6 +5246,10 @@ const presentationRibbonTabs = [
|
|
|
4891
5246
|
id: 'transitions',
|
|
4892
5247
|
label: '切换'
|
|
4893
5248
|
},
|
|
5249
|
+
{
|
|
5250
|
+
id: 'animations',
|
|
5251
|
+
label: '动画'
|
|
5252
|
+
},
|
|
4894
5253
|
{
|
|
4895
5254
|
id: 'slideshow',
|
|
4896
5255
|
label: '幻灯片放映',
|
|
@@ -4949,6 +5308,7 @@ function PresentationToolbar({ selectedSlide, selectedElement, selectedUnitCount
|
|
|
4949
5308
|
const officeDialog = useOfficeDialog();
|
|
4950
5309
|
const [fontSizeDraft, setFontSizeDraft] = useState(()=>selectedElement ? String(selectedElement.fontSize) : '');
|
|
4951
5310
|
const fontFamilyValue = presentationFontFamilyValue(selectedElement?.fontFamily);
|
|
5311
|
+
const selectedAnimation = workSlideAnimationForElement(selectedSlide, selectedElement?.id);
|
|
4952
5312
|
useEffect(()=>{
|
|
4953
5313
|
setFontSizeDraft(selectedElement ? String(selectedElement.fontSize) : '');
|
|
4954
5314
|
}, [
|
|
@@ -5363,6 +5723,16 @@ function PresentationToolbar({ selectedSlide, selectedElement, selectedUnitCount
|
|
|
5363
5723
|
onChange: commands.setTransition,
|
|
5364
5724
|
onApplyToAll: commands.applyTransitionToAll
|
|
5365
5725
|
}),
|
|
5726
|
+
animations: /*#__PURE__*/ jsx(PresentationAnimationPanel, {
|
|
5727
|
+
animation: selectedAnimation,
|
|
5728
|
+
canMove: can.moveEntranceAnimation,
|
|
5729
|
+
canPreview: can.previewAnimations(),
|
|
5730
|
+
editable: can.setEntranceAnimation(selectedAnimation?.effect),
|
|
5731
|
+
onMove: commands.moveEntranceAnimation,
|
|
5732
|
+
onPreview: commands.previewAnimations,
|
|
5733
|
+
onSetEffect: commands.setEntranceAnimation,
|
|
5734
|
+
onUpdate: commands.updateEntranceAnimation
|
|
5735
|
+
}),
|
|
5366
5736
|
slideshow: /*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
5367
5737
|
label: "开始放映",
|
|
5368
5738
|
children: [
|
|
@@ -6502,7 +6872,7 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6502
6872
|
const selectedElement = selectedElements.at(-1) ?? null;
|
|
6503
6873
|
const copySelection = useCallback(()=>{
|
|
6504
6874
|
if (selectedElements.length) {
|
|
6505
|
-
copyPresentationElements(selectedElements);
|
|
6875
|
+
copyPresentationElements(selectedElements, 'slide' === mode ? selectedSlide?.animations : void 0);
|
|
6506
6876
|
showToast(selectedElements.length > 1 ? `已复制 ${selectedElements.length} 个对象` : '已复制演示元素', 'success');
|
|
6507
6877
|
return true;
|
|
6508
6878
|
}
|
|
@@ -6518,7 +6888,7 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6518
6888
|
const deleteSelectedElement = useCallback(()=>{
|
|
6519
6889
|
if (!selectedElements.length || !targetId) return false;
|
|
6520
6890
|
const selectedIds = new Set(selectedElements.map((element)=>element.id));
|
|
6521
|
-
const next = updateTargetElements(content, mode, targetId, (elements)=>elements.filter((element)=>!selectedIds.has(element.id)));
|
|
6891
|
+
const next = updateTargetElements(content, mode, targetId, (elements)=>elements.filter((element)=>!selectedIds.has(element.id)), selectedIds);
|
|
6522
6892
|
if (!next) return false;
|
|
6523
6893
|
onChange(next);
|
|
6524
6894
|
onSelectElements([]);
|
|
@@ -6533,7 +6903,7 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6533
6903
|
]);
|
|
6534
6904
|
const cutSelection = useCallback(()=>{
|
|
6535
6905
|
if (selectedElements.length) {
|
|
6536
|
-
copyPresentationElements(selectedElements);
|
|
6906
|
+
copyPresentationElements(selectedElements, 'slide' === mode ? selectedSlide?.animations : void 0);
|
|
6537
6907
|
if (!deleteSelectedElement()) return false;
|
|
6538
6908
|
showToast(selectedElements.length > 1 ? `已剪切 ${selectedElements.length} 个对象` : '已剪切演示元素', 'success');
|
|
6539
6909
|
return true;
|
|
@@ -6572,17 +6942,25 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6572
6942
|
}
|
|
6573
6943
|
if ('element' === clipboard.payload.kind || 'elements' === clipboard.payload.kind) {
|
|
6574
6944
|
if (!targetId) return false;
|
|
6575
|
-
const
|
|
6576
|
-
|
|
6577
|
-
] :
|
|
6945
|
+
const sourceElements = 'element' === clipboard.payload.kind ? [
|
|
6946
|
+
clipboard.payload.element
|
|
6947
|
+
] : clipboard.payload.elements;
|
|
6948
|
+
const sourceAnimations = 'element' === clipboard.payload.kind ? clipboard.payload.animation ? [
|
|
6949
|
+
clipboard.payload.animation
|
|
6950
|
+
] : [] : clipboard.payload.animations ?? [];
|
|
6951
|
+
const pasted = clonePresentationElementsAndAnimationsForPaste(sourceElements, sourceAnimations, clipboard.offset);
|
|
6952
|
+
if ('slide' === mode && !canAppendSlideAnimations(content, targetId, pasted.animations)) {
|
|
6953
|
+
showToast('对象动画数量已达到每张幻灯片 256 条的上限。', 'info');
|
|
6954
|
+
return true;
|
|
6955
|
+
}
|
|
6578
6956
|
const next = updateTargetElements(content, mode, targetId, (elements)=>[
|
|
6579
6957
|
...elements,
|
|
6580
|
-
...pasted
|
|
6581
|
-
]);
|
|
6958
|
+
...pasted.elements
|
|
6959
|
+
], void 0, pasted.animations);
|
|
6582
6960
|
if (!next) return false;
|
|
6583
6961
|
onChange(next);
|
|
6584
|
-
onSelectElements(pasted.map((element)=>element.id));
|
|
6585
|
-
showToast(pasted.length > 1 ? `已粘贴 ${pasted.length} 个对象` : '已粘贴演示元素', 'success');
|
|
6962
|
+
onSelectElements(pasted.elements.map((element)=>element.id));
|
|
6963
|
+
showToast(pasted.elements.length > 1 ? `已粘贴 ${pasted.elements.length} 个对象` : '已粘贴演示元素', 'success');
|
|
6586
6964
|
return true;
|
|
6587
6965
|
}
|
|
6588
6966
|
if ('slide' !== mode || !selectedSlide) {
|
|
@@ -6614,15 +6992,19 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6614
6992
|
]);
|
|
6615
6993
|
const duplicateSelection = useCallback(()=>{
|
|
6616
6994
|
if (selectedElements.length && targetId) {
|
|
6617
|
-
const copies =
|
|
6995
|
+
const copies = clonePresentationElementsAndAnimationsForPaste(selectedElements, 'slide' === mode ? selectedSlide?.animations ?? [] : [], 5);
|
|
6996
|
+
if ('slide' === mode && !canAppendSlideAnimations(content, targetId, copies.animations)) {
|
|
6997
|
+
showToast('对象动画数量已达到每张幻灯片 256 条的上限。', 'info');
|
|
6998
|
+
return true;
|
|
6999
|
+
}
|
|
6618
7000
|
const next = updateTargetElements(content, mode, targetId, (elements)=>[
|
|
6619
7001
|
...elements,
|
|
6620
|
-
...copies
|
|
6621
|
-
]);
|
|
7002
|
+
...copies.elements
|
|
7003
|
+
], void 0, copies.animations);
|
|
6622
7004
|
if (!next) return false;
|
|
6623
7005
|
onChange(next);
|
|
6624
|
-
onSelectElements(copies.map((element)=>element.id));
|
|
6625
|
-
showToast(copies.length > 1 ? `已复制 ${copies.length} 个对象` : '已复制演示元素', 'success');
|
|
7006
|
+
onSelectElements(copies.elements.map((element)=>element.id));
|
|
7007
|
+
showToast(copies.elements.length > 1 ? `已复制 ${copies.elements.length} 个对象` : '已复制演示元素', 'success');
|
|
6626
7008
|
return true;
|
|
6627
7009
|
}
|
|
6628
7010
|
if ('slide' !== mode || !selectedSlide) return false;
|
|
@@ -6709,15 +7091,15 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6709
7091
|
toggleUnderline
|
|
6710
7092
|
};
|
|
6711
7093
|
}
|
|
6712
|
-
function updateTargetElements(content, mode, targetId, update) {
|
|
7094
|
+
function updateTargetElements(content, mode, targetId, update, removedElementIds, addedAnimations) {
|
|
6713
7095
|
if ('slide' === mode) {
|
|
6714
7096
|
if (!content.slides.some((slide)=>slide.id === targetId)) return null;
|
|
6715
7097
|
return {
|
|
6716
7098
|
...content,
|
|
6717
|
-
slides: content.slides.map((slide)=>slide.id === targetId ? {
|
|
7099
|
+
slides: content.slides.map((slide)=>slide.id === targetId ? appendWorkSlideAnimations(removeWorkSlideAnimationsForElements({
|
|
6718
7100
|
...slide,
|
|
6719
7101
|
elements: update(use_presentation_clipboard_structuredCopy(slide.elements))
|
|
6720
|
-
} : slide)
|
|
7102
|
+
}, removedElementIds ?? new Set()), addedAnimations) : slide)
|
|
6721
7103
|
};
|
|
6722
7104
|
}
|
|
6723
7105
|
const normalized = withPresentationDesign(content);
|
|
@@ -6740,10 +7122,130 @@ function updateTargetElements(content, mode, targetId, update) {
|
|
|
6740
7122
|
} : master)
|
|
6741
7123
|
};
|
|
6742
7124
|
}
|
|
7125
|
+
function canAppendSlideAnimations(content, slideId, animations) {
|
|
7126
|
+
if (!animations?.length) return true;
|
|
7127
|
+
const slide = content.slides.find((candidate)=>candidate.id === slideId);
|
|
7128
|
+
return Boolean(slide) && (slide?.animations?.length ?? 0) + animations.length <= 256;
|
|
7129
|
+
}
|
|
7130
|
+
function appendWorkSlideAnimations(slide, animations) {
|
|
7131
|
+
if (!animations?.length) return slide;
|
|
7132
|
+
return {
|
|
7133
|
+
...slide,
|
|
7134
|
+
animations: [
|
|
7135
|
+
...slide.animations ?? [],
|
|
7136
|
+
...use_presentation_clipboard_structuredCopy(animations)
|
|
7137
|
+
]
|
|
7138
|
+
};
|
|
7139
|
+
}
|
|
6743
7140
|
function use_presentation_clipboard_structuredCopy(value) {
|
|
6744
7141
|
if ('function' == typeof structuredClone) return structuredClone(value);
|
|
6745
7142
|
return JSON.parse(JSON.stringify(value));
|
|
6746
7143
|
}
|
|
7144
|
+
function usePresentationAnimationCommands({ content, onChange, selectedElementId, selectedSlide }) {
|
|
7145
|
+
const selectedElementExists = Boolean(selectedElementId && selectedSlide.elements.some((element)=>element.id === selectedElementId));
|
|
7146
|
+
const selectedAnimation = workSlideAnimationForElement(selectedSlide, selectedElementId);
|
|
7147
|
+
const setEntranceAnimation = useCallback((effect)=>{
|
|
7148
|
+
if (!selectedElementId || !selectedElementExists) return false;
|
|
7149
|
+
const current = workSlideAnimationForElement(selectedSlide, selectedElementId);
|
|
7150
|
+
if (!effect) {
|
|
7151
|
+
if (!current) return false;
|
|
7152
|
+
updateSlide(content, selectedSlide.id, (slide)=>{
|
|
7153
|
+
const animations = slide.animations?.filter((animation)=>animation.id !== current.id);
|
|
7154
|
+
return {
|
|
7155
|
+
...slide,
|
|
7156
|
+
animations: animations?.length ? animations : void 0
|
|
7157
|
+
};
|
|
7158
|
+
}, onChange);
|
|
7159
|
+
return true;
|
|
7160
|
+
}
|
|
7161
|
+
if (current?.effect === effect) return false;
|
|
7162
|
+
if (!current && (selectedSlide.animations?.length ?? 0) >= 256) return false;
|
|
7163
|
+
updateSlide(content, selectedSlide.id, (slide)=>{
|
|
7164
|
+
const next = createWorkSlideAnimation(selectedElementId, effect, current);
|
|
7165
|
+
const animations = [
|
|
7166
|
+
...slide.animations ?? []
|
|
7167
|
+
];
|
|
7168
|
+
const index = current ? animations.findIndex((animation)=>animation.id === current.id) : -1;
|
|
7169
|
+
if (index >= 0) animations[index] = next;
|
|
7170
|
+
else animations.push(next);
|
|
7171
|
+
return {
|
|
7172
|
+
...slide,
|
|
7173
|
+
animations
|
|
7174
|
+
};
|
|
7175
|
+
}, onChange);
|
|
7176
|
+
return true;
|
|
7177
|
+
}, [
|
|
7178
|
+
content,
|
|
7179
|
+
onChange,
|
|
7180
|
+
selectedElementExists,
|
|
7181
|
+
selectedElementId,
|
|
7182
|
+
selectedSlide
|
|
7183
|
+
]);
|
|
7184
|
+
const updateEntranceAnimation = useCallback((patch)=>{
|
|
7185
|
+
if (!selectedAnimation) return false;
|
|
7186
|
+
const next = normalizeWorkSlideAnimation({
|
|
7187
|
+
...selectedAnimation,
|
|
7188
|
+
...patch,
|
|
7189
|
+
id: selectedAnimation.id,
|
|
7190
|
+
elementId: selectedAnimation.elementId
|
|
7191
|
+
});
|
|
7192
|
+
if (animationsEqual(selectedAnimation, next)) return false;
|
|
7193
|
+
updateSlide(content, selectedSlide.id, (slide)=>({
|
|
7194
|
+
...slide,
|
|
7195
|
+
animations: slide.animations?.map((animation)=>animation.id === selectedAnimation.id ? next : animation)
|
|
7196
|
+
}), onChange);
|
|
7197
|
+
return true;
|
|
7198
|
+
}, [
|
|
7199
|
+
content,
|
|
7200
|
+
onChange,
|
|
7201
|
+
selectedAnimation,
|
|
7202
|
+
selectedSlide.id
|
|
7203
|
+
]);
|
|
7204
|
+
const canMoveEntranceAnimation = useCallback((direction)=>{
|
|
7205
|
+
const index = workSlideAnimationIndex(selectedSlide, selectedAnimation?.id);
|
|
7206
|
+
const target = index + direction;
|
|
7207
|
+
return index >= 0 && target >= 0 && target < (selectedSlide.animations?.length ?? 0);
|
|
7208
|
+
}, [
|
|
7209
|
+
selectedAnimation?.id,
|
|
7210
|
+
selectedSlide
|
|
7211
|
+
]);
|
|
7212
|
+
const moveEntranceAnimation = useCallback((direction)=>{
|
|
7213
|
+
if (!selectedAnimation || !canMoveEntranceAnimation(direction)) return false;
|
|
7214
|
+
updateSlide(content, selectedSlide.id, (slide)=>{
|
|
7215
|
+
const animations = [
|
|
7216
|
+
...slide.animations ?? []
|
|
7217
|
+
];
|
|
7218
|
+
const index = animations.findIndex((animation)=>animation.id === selectedAnimation.id);
|
|
7219
|
+
const target = index + direction;
|
|
7220
|
+
[animations[index], animations[target]] = [
|
|
7221
|
+
animations[target],
|
|
7222
|
+
animations[index]
|
|
7223
|
+
];
|
|
7224
|
+
return {
|
|
7225
|
+
...slide,
|
|
7226
|
+
animations
|
|
7227
|
+
};
|
|
7228
|
+
}, onChange);
|
|
7229
|
+
return true;
|
|
7230
|
+
}, [
|
|
7231
|
+
canMoveEntranceAnimation,
|
|
7232
|
+
content,
|
|
7233
|
+
onChange,
|
|
7234
|
+
selectedAnimation,
|
|
7235
|
+
selectedSlide.id
|
|
7236
|
+
]);
|
|
7237
|
+
return {
|
|
7238
|
+
canMoveEntranceAnimation,
|
|
7239
|
+
canSetEntranceAnimation: selectedElementExists,
|
|
7240
|
+
canUpdateEntranceAnimation: Boolean(selectedAnimation),
|
|
7241
|
+
moveEntranceAnimation,
|
|
7242
|
+
setEntranceAnimation,
|
|
7243
|
+
updateEntranceAnimation
|
|
7244
|
+
};
|
|
7245
|
+
}
|
|
7246
|
+
function animationsEqual(left, right) {
|
|
7247
|
+
return left.id === right.id && left.elementId === right.elementId && left.effect === right.effect && left.trigger === right.trigger && left.durationMs === right.durationMs && left.delayMs === right.delayMs && left.direction === right.direction;
|
|
7248
|
+
}
|
|
6747
7249
|
function usePresentationDesignCommands({ activeElements, activeTargetId, designContent, designMode, designOpen, onChange, onClearSelection, onCloseComments, onEditElement, onSetDesignMode, onSetDesignOpen, selectedLayout, selectedMaster, selectedSlide }) {
|
|
6748
7250
|
const updateLayout = useCallback((layoutId, update)=>{
|
|
6749
7251
|
onChange({
|
|
@@ -7390,9 +7892,12 @@ function usePresentationReviewCommands({ content, onChange, onClearSelection, on
|
|
|
7390
7892
|
function activePresentationReviewInvoker() {
|
|
7391
7893
|
return "u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
7392
7894
|
}
|
|
7393
|
-
function usePresentationSelection(elements) {
|
|
7394
|
-
const
|
|
7395
|
-
const [
|
|
7895
|
+
function usePresentationSelection(elements, initialEditingElementId = null) {
|
|
7896
|
+
const initialEditingElementExists = Boolean(initialEditingElementId && elements.some((element)=>element.id === initialEditingElementId));
|
|
7897
|
+
const [selectedElementIds, setSelectedElementIds] = useState(()=>initialEditingElementExists && initialEditingElementId ? selectionWithPendingIds(elements, [
|
|
7898
|
+
initialEditingElementId
|
|
7899
|
+
]) : []);
|
|
7900
|
+
const [editingElementId, setEditingElementId] = useState(()=>initialEditingElementExists ? initialEditingElementId : null);
|
|
7396
7901
|
const clear = useCallback(()=>{
|
|
7397
7902
|
setSelectedElementIds([]);
|
|
7398
7903
|
setEditingElementId(null);
|
|
@@ -7991,7 +8496,7 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
7991
8496
|
const selectedLayout = designContent.layouts?.find((layout)=>layout.id === selectedSlide?.layoutId) ?? designContent.layouts?.[0];
|
|
7992
8497
|
const selectedMaster = designContent.masters?.find((master)=>master.id === selectedLayout?.masterId) ?? designContent.masters?.[0];
|
|
7993
8498
|
const activeElements = 'layout' === designMode ? selectedLayout?.elements ?? [] : 'master' === designMode ? selectedMaster?.elements ?? [] : selectedSlide?.elements ?? [];
|
|
7994
|
-
const selection = usePresentationSelection(activeElements);
|
|
8499
|
+
const selection = usePresentationSelection(activeElements, autoFocus ? presentationInitialEditingElementId(activeElements) : null);
|
|
7995
8500
|
const presentationPresenceLocation = useMemo(()=>({
|
|
7996
8501
|
kind: 'presentation',
|
|
7997
8502
|
slideId: selectedSlide.id,
|
|
@@ -8142,6 +8647,12 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
8142
8647
|
onSelectSlide: setSelectedSlideId,
|
|
8143
8648
|
selectedSlide
|
|
8144
8649
|
});
|
|
8650
|
+
const presentationAnimations = usePresentationAnimationCommands({
|
|
8651
|
+
content,
|
|
8652
|
+
onChange,
|
|
8653
|
+
selectedElementId: 'slide' === designMode && singleSelectedElement ? singleSelectedElement.id : void 0,
|
|
8654
|
+
selectedSlide
|
|
8655
|
+
});
|
|
8145
8656
|
const presentationElements = usePresentationElementCommands({
|
|
8146
8657
|
activeElements,
|
|
8147
8658
|
activeTargetId,
|
|
@@ -8274,8 +8785,30 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
8274
8785
|
selectedTextEditor,
|
|
8275
8786
|
toolbarSelectedElement
|
|
8276
8787
|
]);
|
|
8788
|
+
const startPresentationSlideshow = useCallback((source)=>{
|
|
8789
|
+
const currentIndex = content.slides.findIndex((slide)=>slide.id === selectedSlide.id);
|
|
8790
|
+
const activeElement = document.activeElement;
|
|
8791
|
+
slideshowReturnFocusRef.current = activeElement instanceof HTMLElement && activeElement !== document.body ? activeElement : document.querySelector(`[data-presentation-slideshow-source="${source}"]`);
|
|
8792
|
+
setAgentMenu(null);
|
|
8793
|
+
setSlideshowStartIndex('current' === source ? Math.max(0, currentIndex) : 0);
|
|
8794
|
+
onStartSlideshow?.();
|
|
8795
|
+
}, [
|
|
8796
|
+
content.slides,
|
|
8797
|
+
onStartSlideshow,
|
|
8798
|
+
selectedSlide.id
|
|
8799
|
+
]);
|
|
8277
8800
|
const presentationExtensions = useMemo(createPresentationEditorExtensions, []);
|
|
8278
8801
|
const presentationEditor = useOfficeEditorRuntime({
|
|
8802
|
+
animations: {
|
|
8803
|
+
canMoveEntranceAnimation: (direction)=>'slide' === designMode && presentationAnimations.canMoveEntranceAnimation(direction),
|
|
8804
|
+
canPreviewAnimations: 'slide' === designMode && Boolean(selectedSlide.animations?.length),
|
|
8805
|
+
canSetEntranceAnimation: 'slide' === designMode && presentationAnimations.canSetEntranceAnimation,
|
|
8806
|
+
canUpdateEntranceAnimation: 'slide' === designMode && presentationAnimations.canUpdateEntranceAnimation,
|
|
8807
|
+
moveEntranceAnimation: presentationAnimations.moveEntranceAnimation,
|
|
8808
|
+
previewAnimations: ()=>startPresentationSlideshow('current'),
|
|
8809
|
+
setEntranceAnimation: presentationAnimations.setEntranceAnimation,
|
|
8810
|
+
updateEntranceAnimation: presentationAnimations.updateEntranceAnimation
|
|
8811
|
+
},
|
|
8279
8812
|
clipboard: {
|
|
8280
8813
|
canCopySelection: selectedElements.length > 0 || 'slide' === designMode && Boolean(selectedSlide),
|
|
8281
8814
|
canCutSelection: selectedElements.length > 0 || 'slide' === designMode && Boolean(selectedSlide),
|
|
@@ -8392,14 +8925,7 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
8392
8925
|
view: {
|
|
8393
8926
|
canStartSlideshow: 'slide' === designMode && content.slides.length > 0,
|
|
8394
8927
|
setViewMode,
|
|
8395
|
-
startSlideshow:
|
|
8396
|
-
const currentIndex = content.slides.findIndex((slide)=>slide.id === selectedSlide.id);
|
|
8397
|
-
const activeElement = document.activeElement;
|
|
8398
|
-
slideshowReturnFocusRef.current = activeElement instanceof HTMLElement && activeElement !== document.body ? activeElement : document.querySelector(`[data-presentation-slideshow-source="${source}"]`);
|
|
8399
|
-
setAgentMenu(null);
|
|
8400
|
-
setSlideshowStartIndex('current' === source ? Math.max(0, currentIndex) : 0);
|
|
8401
|
-
onStartSlideshow?.();
|
|
8402
|
-
},
|
|
8928
|
+
startSlideshow: startPresentationSlideshow,
|
|
8403
8929
|
toggleDesign: presentationDesign.toggleDesignPanel
|
|
8404
8930
|
}
|
|
8405
8931
|
}, presentationExtensions);
|