@a3s-lab/office 0.32.0 → 0.34.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 +62 -8
- package/dist/0~3539.js +2 -2
- package/dist/0~3557.js +1 -1
- package/dist/0~3635.js +1 -1
- package/dist/0~5809.js +123 -0
- package/dist/0~7048.js +1 -2
- package/dist/{0~7614.js → 0~7828.js} +376 -5
- package/dist/{0~6090.js → 0~8136.js} +71 -2
- package/dist/{0~4595.js → 0~9073.js} +3 -72
- package/dist/0~9445.js +1 -1
- package/dist/0~document-editor.js +2 -2
- package/dist/0~markdown-editor.js +2 -2
- package/dist/0~pdf-page-organization-engine.js +187 -0
- package/dist/0~pdf-viewer.js +1018 -30
- package/dist/0~presentation-editor.js +580 -68
- package/dist/0~spreadsheet-editor.js +2 -2
- 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/core.d.ts +1 -0
- package/dist/internal/features/work/editors/pdf-editor-extensions.d.ts +11 -0
- package/dist/internal/features/work/editors/pdf-page-organization-engine.d.ts +2 -0
- package/dist/internal/features/work/editors/pdf-page-organization-plan.d.ts +10 -0
- package/dist/internal/features/work/editors/pdf-page-organization-types.d.ts +68 -0
- package/dist/internal/features/work/editors/pdf-page-organization-worker-client.d.ts +2 -0
- package/dist/internal/features/work/editors/pdf-page-organization-worker-protocol.d.ts +13 -0
- package/dist/internal/features/work/editors/pdf-page-organization.d.ts +3 -0
- package/dist/internal/features/work/editors/pdf-page-organization.worker.d.ts +1 -0
- package/dist/internal/features/work/editors/pdf-page-organizer-dialog.d.ts +17 -0
- package/dist/internal/features/work/editors/pdf-thumbnail-rail.d.ts +4 -0
- package/dist/internal/features/work/editors/pdf-toolbar.d.ts +2 -1
- package/dist/internal/features/work/editors/pdf-viewer.d.ts +3 -1
- 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-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/use-pdf-page-organization.d.ts +38 -0
- package/dist/internal/features/work/editors/use-presentation-animation-commands.d.ts +15 -0
- 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/pdf-page-organization.worker.js +19667 -0
- package/dist/pdf-page-organization.worker.js.LICENSE.txt +14 -0
- package/dist/react.d.ts +1 -0
- package/dist/styles.css +438 -0
- package/dist/vue.d.ts +3 -1
- package/dist/vue.js +2 -0
- package/dist/web-component.d.ts +3 -1
- package/dist/web-component.js +9 -0
- package/docs/latest/en/browser-editor-architecture.md +29 -6
- package/package.json +8 -1
- 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";
|
|
@@ -15,13 +15,13 @@ import { createOfficeId as createWorkId } from "./4121.js";
|
|
|
15
15
|
import { OfficeTableInsertPopover, readOfficeFileAsDataUrl } from "./0~9445.js";
|
|
16
16
|
import { normalizePresentationChartLegendPosition, presentationChartDataLabelPositions, presentationChartDataLabelText, normalizePresentationBubbleSizeRepresents, parsePresentationChartCategories, presentationChartXValues, withPresentationChartLayout, presentationChartTypeLabel, presentationChartAxes, withPresentationChartSeriesAnalysis, presentationChartUsesNumericXAxis, presentationChartSupportsSeriesMarkers, presentationChartBubbleSizes, createPresentationChartElement, parsePresentationChartValueDraft, normalizePresentationChartDataLabelPosition, presentationChartSupportsAxisTitles, withPresentationChartDataLabels, withPresentationChartType, createPresentationChartSeries, presentationChartErrorBarCount, normalizePresentationScatterStyle, withPresentationChartSeriesStyle, normalizePresentationBubbleScale, presentationChartDataLabelPositionLabel, presentationChartShowsLegend, presentationChartTrendlineCount, presentationChartHasDataLabels, normalizeDoughnutHoleSize, withPresentationChartAxes } from "./0~work-presentation-charts.js";
|
|
17
17
|
import { spreadsheetChartSeriesLayout, workSpreadsheetChartSupportsGrouping, normalizeWorkSpreadsheetChartSmoothLines, workSpreadsheetChartAxisIsValueAxis, fitSpreadsheetTrendline, spreadsheetChartSeriesLegendColor, normalizeWorkSpreadsheetChartSeriesStyle, spreadsheetChartCategoryVisualIndex, errorBarSourceValues, normalizeWorkSpreadsheetErrorBars, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, normalizeWorkSpreadsheetChartGapWidth, spreadsheetChartCategoryLabelVisible, spreadsheetChartAxisLabelLayout, workSpreadsheetChartSupportsSmoothLines, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGrouping, workSpreadsheetChartSupportsBarSpacing, workSpreadsheetChartSupportsErrorBars, spreadsheetChartSeriesLineStyle, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, workSpreadsheetChartAxisIsCategoryAxis, spreadsheetErrorBarAmounts, spreadsheetChartAxisValueRatio, spreadsheetChartAxisScale, normalizeWorkSpreadsheetChartOverlap, spreadsheetChartBarGeometry, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, spreadsheetChartAxisGridlinesVisible, normalizeWorkSpreadsheetTrendline, roundChartNumber, formatSpreadsheetChartAxisNumber, spreadsheetChartSeriesFillStyle } from "./8715.js";
|
|
18
|
-
import { officePresenceColorStyle, office_text_field_OfficeTextArea, stepOfficeZoom, useOfficeEditorWheelZoom, useOfficeRemoteParticipants, button_Button, useOfficePublishPresenceLocation, CommittedOfficeTextArea, CommittedOfficeTextField, office_text_field_OfficeTextField, useDialogFocusScope, icon_button_IconButton, office_text_field_OfficeFileInput } from "./0~
|
|
18
|
+
import { officePresenceColorStyle, office_text_field_OfficeTextArea, stepOfficeZoom, useOfficeEditorWheelZoom, useOfficeRemoteParticipants, button_Button, useOfficePublishPresenceLocation, CommittedOfficeTextArea, CommittedOfficeTextField, office_text_field_OfficeTextField, useDialogFocusScope, icon_button_IconButton, office_text_field_OfficeFileInput } from "./0~8136.js";
|
|
19
19
|
import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, CommittedOfficeNumberField, useOfficeTaskPaneModal, officeFontFamilyLabel, useOfficeDialog, officeFontFamilies, CollectionState, createOfficeKernelClient, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
20
|
-
import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkOfficeRibbonGroup, WorkOfficePreviewBar, WorkOfficeRibbonButton } from "./0~
|
|
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: ()=>({
|
|
@@ -2443,17 +2475,20 @@ function presentationCommandsWithObjectFocus(commands, restoreFocus) {
|
|
|
2443
2475
|
distributeElements: afterSuccessfulCommand(commands.distributeElements),
|
|
2444
2476
|
duplicateSlide: afterSuccessfulCommand(commands.duplicateSlide),
|
|
2445
2477
|
groupElements: afterSuccessfulCommand(commands.groupElements),
|
|
2478
|
+
moveEntranceAnimation: afterSuccessfulCommand(commands.moveEntranceAnimation),
|
|
2446
2479
|
pasteSelection: afterSuccessfulCommand(commands.pasteSelection),
|
|
2447
2480
|
redo: afterSuccessfulCommand(commands.redo),
|
|
2448
2481
|
reorderElement: afterSuccessfulCommand(commands.reorderElement),
|
|
2449
2482
|
setTransition: afterSuccessfulCommand(commands.setTransition),
|
|
2483
|
+
setEntranceAnimation: afterSuccessfulCommand(commands.setEntranceAnimation),
|
|
2450
2484
|
setViewMode: afterSuccessfulCommand(commands.setViewMode),
|
|
2451
2485
|
toggleBold: afterSuccessfulCommand(commands.toggleBold),
|
|
2452
2486
|
toggleItalic: afterSuccessfulCommand(commands.toggleItalic),
|
|
2453
2487
|
toggleUnderline: afterSuccessfulCommand(commands.toggleUnderline),
|
|
2454
2488
|
undo: afterSuccessfulCommand(commands.undo),
|
|
2455
2489
|
ungroupElements: afterSuccessfulCommand(commands.ungroupElements),
|
|
2456
|
-
updateElement: afterSuccessfulCommand(commands.updateElement)
|
|
2490
|
+
updateElement: afterSuccessfulCommand(commands.updateElement),
|
|
2491
|
+
updateEntranceAnimation: afterSuccessfulCommand(commands.updateEntranceAnimation)
|
|
2457
2492
|
};
|
|
2458
2493
|
}
|
|
2459
2494
|
function presentationChartAnalysisBounds(chart, xValues) {
|
|
@@ -3572,7 +3607,7 @@ function drawRadarChart(context, chart, sourceRect) {
|
|
|
3572
3607
|
});
|
|
3573
3608
|
}
|
|
3574
3609
|
}
|
|
3575
|
-
function SlideCanvas({ content, designContent, slide, interactive, aspectRatio, showPlaceholders = false }) {
|
|
3610
|
+
function SlideCanvas({ content, designContent, slide, interactive, aspectRatio, animationCueIndex, showPlaceholders = false }) {
|
|
3576
3611
|
const view = designContent ? presentationSlideViewFromDesign(designContent, slide) : content ? presentationSlideView(content, slide) : void 0;
|
|
3577
3612
|
const elements = [
|
|
3578
3613
|
...view?.inheritedElements.map((element)=>({
|
|
@@ -3584,6 +3619,7 @@ function SlideCanvas({ content, designContent, slide, interactive, aspectRatio,
|
|
|
3584
3619
|
origin: 'slide'
|
|
3585
3620
|
}))
|
|
3586
3621
|
];
|
|
3622
|
+
const animationPlayback = void 0 === animationCueIndex ? void 0 : slideAnimationPlayback(slide.animations, animationCueIndex);
|
|
3587
3623
|
return /*#__PURE__*/ jsx("span", {
|
|
3588
3624
|
className: `work-slide-canvas ${interactive ? 'interactive' : ''}`,
|
|
3589
3625
|
style: {
|
|
@@ -3593,16 +3629,23 @@ function SlideCanvas({ content, designContent, slide, interactive, aspectRatio,
|
|
|
3593
3629
|
children: elements.map(({ element, origin })=>/*#__PURE__*/ jsx(SlideElementPreview, {
|
|
3594
3630
|
element: element,
|
|
3595
3631
|
origin: origin,
|
|
3596
|
-
showPlaceholder: showPlaceholders
|
|
3632
|
+
showPlaceholder: showPlaceholders,
|
|
3633
|
+
animationPlayback: 'slide' === origin ? animationPlayback?.get(element.id) : void 0
|
|
3597
3634
|
}, `${origin}:${element.id}`))
|
|
3598
3635
|
});
|
|
3599
3636
|
}
|
|
3600
|
-
function SlideElementPreview({ element, origin, showPlaceholder = false }) {
|
|
3637
|
+
function SlideElementPreview({ animationPlayback, element, origin, showPlaceholder = false }) {
|
|
3601
3638
|
const hasRichText = element.textRuns?.some((run)=>run.text.length > 0);
|
|
3602
3639
|
return /*#__PURE__*/ jsx("span", {
|
|
3603
3640
|
className: `work-slide-element ${element.type} ${origin} ${showPlaceholder && element.placeholder ? 'placeholder' : ''}`.trim(),
|
|
3641
|
+
"data-slide-preview-element-id": element.id,
|
|
3604
3642
|
"data-slide-element-origin": origin,
|
|
3605
|
-
|
|
3643
|
+
"data-slide-animation-effect": animationPlayback?.animation.effect,
|
|
3644
|
+
"data-slide-animation-state": animationPlayback?.state,
|
|
3645
|
+
style: {
|
|
3646
|
+
...slideElementStyle(element),
|
|
3647
|
+
...slideElementAnimationStyle(animationPlayback)
|
|
3648
|
+
},
|
|
3606
3649
|
children: 'image' === element.type && element.image ? /*#__PURE__*/ jsx("img", {
|
|
3607
3650
|
src: element.image.dataUrl,
|
|
3608
3651
|
alt: element.altText ?? element.image.name
|
|
@@ -3658,6 +3701,8 @@ function slideElementStyle(element) {
|
|
|
3658
3701
|
borderRadius: 'ellipse' === element.shapeType ? '50%' : `${element.radius ?? 0}%`,
|
|
3659
3702
|
clipPath: shapeClipPath,
|
|
3660
3703
|
opacity: element.opacity,
|
|
3704
|
+
'--work-slide-element-opacity': element.opacity ?? 1,
|
|
3705
|
+
'--work-slide-element-rotation': `${element.rotation ?? 0}deg`,
|
|
3661
3706
|
transform: element.rotation ? `rotate(${element.rotation}deg)` : void 0,
|
|
3662
3707
|
transformOrigin: 'center',
|
|
3663
3708
|
...'line' === element.type ? {
|
|
@@ -3666,6 +3711,27 @@ function slideElementStyle(element) {
|
|
|
3666
3711
|
} : {}
|
|
3667
3712
|
};
|
|
3668
3713
|
}
|
|
3714
|
+
function slideAnimationPlayback(animations, activeCueIndex) {
|
|
3715
|
+
const playback = new Map();
|
|
3716
|
+
for (const [cueIndex, cue] of workSlideAnimationCues(animations).entries())for (const item of cue.items)playback.set(item.animation.elementId, {
|
|
3717
|
+
animation: item.animation,
|
|
3718
|
+
startOffsetMs: item.startOffsetMs,
|
|
3719
|
+
state: cueIndex < activeCueIndex ? 'finished' : cueIndex === activeCueIndex ? 'playing' : 'pending'
|
|
3720
|
+
});
|
|
3721
|
+
return playback;
|
|
3722
|
+
}
|
|
3723
|
+
function slideElementAnimationStyle(playback) {
|
|
3724
|
+
if (!playback) return {};
|
|
3725
|
+
const direction = playback.animation.direction ?? 'left';
|
|
3726
|
+
const translateX = 'left' === direction ? '-18%' : 'right' === direction ? '18%' : '0';
|
|
3727
|
+
const translateY = 'up' === direction ? '-18%' : 'down' === direction ? '18%' : '0';
|
|
3728
|
+
return {
|
|
3729
|
+
'--work-slide-animation-delay': `${playback.startOffsetMs}ms`,
|
|
3730
|
+
'--work-slide-animation-duration': `${playback.animation.durationMs}ms`,
|
|
3731
|
+
'--work-slide-animation-translate-x': translateX,
|
|
3732
|
+
'--work-slide-animation-translate-y': translateY
|
|
3733
|
+
};
|
|
3734
|
+
}
|
|
3669
3735
|
function slideTextStyle(element) {
|
|
3670
3736
|
return {
|
|
3671
3737
|
color: element.color,
|
|
@@ -3741,7 +3807,7 @@ function createPresentationTimerController(now = Date.now()) {
|
|
|
3741
3807
|
runningSinceMilliseconds: now
|
|
3742
3808
|
};
|
|
3743
3809
|
}
|
|
3744
|
-
function PresentationPresenterView({ content, slide, nextSlide, index, total, aspectRatio, timer }) {
|
|
3810
|
+
function PresentationPresenterView({ animationCueIndex, content, slide, nextSlide, index, total, aspectRatio, timer }) {
|
|
3745
3811
|
const [, setTimerRevision] = useState(0);
|
|
3746
3812
|
const now = Date.now();
|
|
3747
3813
|
const running = null !== timer.runningSinceMilliseconds;
|
|
@@ -3839,6 +3905,7 @@ function PresentationPresenterView({ content, slide, nextSlide, index, total, as
|
|
|
3839
3905
|
children: slide.name
|
|
3840
3906
|
}),
|
|
3841
3907
|
/*#__PURE__*/ jsx(SlideCanvas, {
|
|
3908
|
+
animationCueIndex: animationCueIndex,
|
|
3842
3909
|
content: content,
|
|
3843
3910
|
slide: slide,
|
|
3844
3911
|
interactive: false,
|
|
@@ -3901,6 +3968,7 @@ function formatDuration(seconds) {
|
|
|
3901
3968
|
}
|
|
3902
3969
|
function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0, onExit }) {
|
|
3903
3970
|
const [playback, setPlayback] = useState({
|
|
3971
|
+
animationCueIndex: initialAnimationCueIndex(content.slides[presentationPlaybackIndex(initialIndex, content.slides.length)]),
|
|
3904
3972
|
index: presentationPlaybackIndex(initialIndex, content.slides.length),
|
|
3905
3973
|
transitionKey: 0
|
|
3906
3974
|
});
|
|
@@ -3931,12 +3999,52 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
3931
3999
|
setPlayback((current)=>{
|
|
3932
4000
|
const index = Math.min(Math.max(current.index + delta, 0), content.slides.length - 1);
|
|
3933
4001
|
return index === current.index ? current : {
|
|
4002
|
+
animationCueIndex: initialAnimationCueIndex(content.slides[index]),
|
|
4003
|
+
index,
|
|
4004
|
+
transitionKey: current.transitionKey + 1
|
|
4005
|
+
};
|
|
4006
|
+
});
|
|
4007
|
+
}, [
|
|
4008
|
+
content.slides
|
|
4009
|
+
]);
|
|
4010
|
+
const advance = useCallback(()=>{
|
|
4011
|
+
setPlayback((current)=>{
|
|
4012
|
+
const currentSlide = content.slides[current.index];
|
|
4013
|
+
const cueCount = workSlideAnimationCues(currentSlide?.animations).length;
|
|
4014
|
+
if (current.animationCueIndex < cueCount - 1) return {
|
|
4015
|
+
...current,
|
|
4016
|
+
animationCueIndex: current.animationCueIndex + 1
|
|
4017
|
+
};
|
|
4018
|
+
const index = Math.min(current.index + 1, content.slides.length - 1);
|
|
4019
|
+
if (index === current.index) return current;
|
|
4020
|
+
return {
|
|
4021
|
+
animationCueIndex: initialAnimationCueIndex(content.slides[index]),
|
|
4022
|
+
index,
|
|
4023
|
+
transitionKey: current.transitionKey + 1
|
|
4024
|
+
};
|
|
4025
|
+
});
|
|
4026
|
+
}, [
|
|
4027
|
+
content.slides
|
|
4028
|
+
]);
|
|
4029
|
+
const retreat = useCallback(()=>{
|
|
4030
|
+
setPlayback((current)=>{
|
|
4031
|
+
const currentSlide = content.slides[current.index];
|
|
4032
|
+
const initialCueIndex = initialAnimationCueIndex(currentSlide);
|
|
4033
|
+
if (current.animationCueIndex > initialCueIndex) return {
|
|
4034
|
+
...current,
|
|
4035
|
+
animationCueIndex: current.animationCueIndex - 1
|
|
4036
|
+
};
|
|
4037
|
+
const index = Math.max(current.index - 1, 0);
|
|
4038
|
+
if (index === current.index) return current;
|
|
4039
|
+
const previousCues = workSlideAnimationCues(content.slides[index]?.animations);
|
|
4040
|
+
return {
|
|
4041
|
+
animationCueIndex: previousCues.length - 1,
|
|
3934
4042
|
index,
|
|
3935
4043
|
transitionKey: current.transitionKey + 1
|
|
3936
4044
|
};
|
|
3937
4045
|
});
|
|
3938
4046
|
}, [
|
|
3939
|
-
content.slides
|
|
4047
|
+
content.slides
|
|
3940
4048
|
]);
|
|
3941
4049
|
useEffect(()=>{
|
|
3942
4050
|
const onKeyDown = (event)=>{
|
|
@@ -3950,12 +4058,12 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
3950
4058
|
if ((' ' === event.key || 'Spacebar' === event.key) && presentationTargetActivatesWithSpace(event.target)) return;
|
|
3951
4059
|
if ('ArrowRight' === event.key || 'ArrowDown' === event.key || 'PageDown' === event.key || ' ' === event.key || 'Spacebar' === event.key) {
|
|
3952
4060
|
event.preventDefault();
|
|
3953
|
-
|
|
4061
|
+
advance();
|
|
3954
4062
|
return;
|
|
3955
4063
|
}
|
|
3956
4064
|
if ('ArrowLeft' === event.key || 'ArrowUp' === event.key || 'PageUp' === event.key) {
|
|
3957
4065
|
event.preventDefault();
|
|
3958
|
-
|
|
4066
|
+
retreat();
|
|
3959
4067
|
return;
|
|
3960
4068
|
}
|
|
3961
4069
|
if ('Home' === event.key) {
|
|
@@ -3971,9 +4079,11 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
3971
4079
|
window.addEventListener('keydown', onKeyDown);
|
|
3972
4080
|
return ()=>window.removeEventListener('keydown', onKeyDown);
|
|
3973
4081
|
}, [
|
|
4082
|
+
advance,
|
|
3974
4083
|
completeExit,
|
|
3975
4084
|
content.slides.length,
|
|
3976
|
-
move
|
|
4085
|
+
move,
|
|
4086
|
+
retreat
|
|
3977
4087
|
]);
|
|
3978
4088
|
useLayoutEffect(()=>{
|
|
3979
4089
|
const player = playerRef.current;
|
|
@@ -4024,6 +4134,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4024
4134
|
if (!slide) return null;
|
|
4025
4135
|
const aspectRatio = `${content.width ?? 13.333} / ${content.height ?? 7.5}`;
|
|
4026
4136
|
const transition = slide.transition;
|
|
4137
|
+
const animationCues = workSlideAnimationCues(slide.animations);
|
|
4138
|
+
const hasPendingAnimation = playback.animationCueIndex < animationCues.length - 1;
|
|
4027
4139
|
const transitionStyle = {
|
|
4028
4140
|
'--work-slide-transition-duration': `${slideTransitionDurationMilliseconds(transition)}ms`
|
|
4029
4141
|
};
|
|
@@ -4034,6 +4146,7 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4034
4146
|
tabIndex: -1,
|
|
4035
4147
|
children: [
|
|
4036
4148
|
presenter ? /*#__PURE__*/ jsx(PresentationPresenterView, {
|
|
4149
|
+
animationCueIndex: playback.animationCueIndex,
|
|
4037
4150
|
content: content,
|
|
4038
4151
|
slide: slide,
|
|
4039
4152
|
nextSlide: content.slides[playback.index + 1],
|
|
@@ -4048,8 +4161,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4048
4161
|
type: "button",
|
|
4049
4162
|
className: "work-presentation-player-advance",
|
|
4050
4163
|
"aria-label": "单击换到下一张幻灯片",
|
|
4051
|
-
disabled: transition?.advanceOnClick === false || playback.index === content.slides.length - 1,
|
|
4052
|
-
onClick: ()=>
|
|
4164
|
+
disabled: !hasPendingAnimation && (transition?.advanceOnClick === false || playback.index === content.slides.length - 1),
|
|
4165
|
+
onClick: ()=>advance()
|
|
4053
4166
|
}),
|
|
4054
4167
|
/*#__PURE__*/ jsx("div", {
|
|
4055
4168
|
"aria-live": "polite",
|
|
@@ -4061,6 +4174,7 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4061
4174
|
"data-transition-speed": transition?.speed ?? 'medium',
|
|
4062
4175
|
style: transitionStyle,
|
|
4063
4176
|
children: /*#__PURE__*/ jsx(SlideCanvas, {
|
|
4177
|
+
animationCueIndex: playback.animationCueIndex,
|
|
4064
4178
|
content: content,
|
|
4065
4179
|
slide: slide,
|
|
4066
4180
|
interactive: false,
|
|
@@ -4075,8 +4189,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4075
4189
|
type: "button",
|
|
4076
4190
|
"aria-label": "上一张",
|
|
4077
4191
|
"aria-keyshortcuts": "ArrowLeft ArrowUp PageUp",
|
|
4078
|
-
disabled: 0 === playback.index,
|
|
4079
|
-
onClick:
|
|
4192
|
+
disabled: 0 === playback.index && playback.animationCueIndex <= initialAnimationCueIndex(slide),
|
|
4193
|
+
onClick: retreat,
|
|
4080
4194
|
children: /*#__PURE__*/ jsx(ChevronLeft, {
|
|
4081
4195
|
size: 18
|
|
4082
4196
|
})
|
|
@@ -4092,8 +4206,8 @@ function PresentationPlayer({ autoFullscreen = false, content, initialIndex = 0,
|
|
|
4092
4206
|
type: "button",
|
|
4093
4207
|
"aria-label": "下一张",
|
|
4094
4208
|
"aria-keyshortcuts": "ArrowRight ArrowDown PageDown Space",
|
|
4095
|
-
disabled: playback.index === content.slides.length - 1,
|
|
4096
|
-
onClick:
|
|
4209
|
+
disabled: !hasPendingAnimation && playback.index === content.slides.length - 1,
|
|
4210
|
+
onClick: advance,
|
|
4097
4211
|
children: /*#__PURE__*/ jsx(ChevronRight, {
|
|
4098
4212
|
size: 18
|
|
4099
4213
|
})
|
|
@@ -4146,6 +4260,9 @@ function presentationPlaybackIndex(index, slideCount) {
|
|
|
4146
4260
|
if (slideCount <= 1) return 0;
|
|
4147
4261
|
return Math.min(slideCount - 1, Math.max(0, Math.trunc(index)));
|
|
4148
4262
|
}
|
|
4263
|
+
function initialAnimationCueIndex(slide) {
|
|
4264
|
+
return initialWorkSlideAnimationCueIndex(workSlideAnimationCues(slide?.animations));
|
|
4265
|
+
}
|
|
4149
4266
|
async function requestPresentationFullscreen(element) {
|
|
4150
4267
|
if (!element.requestFullscreen) return false;
|
|
4151
4268
|
try {
|
|
@@ -4594,6 +4711,233 @@ function commonRunValue(runs, getValue, fallback) {
|
|
|
4594
4711
|
const values = runs.map((run)=>getValue(run) ?? fallback);
|
|
4595
4712
|
return values.every((value)=>value === values[0]) ? values[0] : fallback;
|
|
4596
4713
|
}
|
|
4714
|
+
function PresentationAnimationPanel({ animation, canMove, canPreview, editable, onMove, onPreview, onSetEffect, onUpdate }) {
|
|
4715
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
4716
|
+
children: [
|
|
4717
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4718
|
+
label: "入场动画",
|
|
4719
|
+
children: /*#__PURE__*/ jsxs("fieldset", {
|
|
4720
|
+
className: "work-presentation-animation-options",
|
|
4721
|
+
children: [
|
|
4722
|
+
/*#__PURE__*/ jsx("legend", {
|
|
4723
|
+
className: "sr-only",
|
|
4724
|
+
children: "对象入场动画设置"
|
|
4725
|
+
}),
|
|
4726
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4727
|
+
className: "work-office-field effect",
|
|
4728
|
+
children: [
|
|
4729
|
+
/*#__PURE__*/ jsx("span", {
|
|
4730
|
+
children: "效果"
|
|
4731
|
+
}),
|
|
4732
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4733
|
+
ariaLabel: "对象入场动画效果",
|
|
4734
|
+
disabled: !editable,
|
|
4735
|
+
value: animation?.effect ?? 'none',
|
|
4736
|
+
options: [
|
|
4737
|
+
{
|
|
4738
|
+
value: 'none',
|
|
4739
|
+
label: '无'
|
|
4740
|
+
},
|
|
4741
|
+
{
|
|
4742
|
+
value: 'appear',
|
|
4743
|
+
label: '出现'
|
|
4744
|
+
},
|
|
4745
|
+
{
|
|
4746
|
+
value: 'fade',
|
|
4747
|
+
label: '淡入'
|
|
4748
|
+
},
|
|
4749
|
+
{
|
|
4750
|
+
value: 'fly-in',
|
|
4751
|
+
label: '飞入'
|
|
4752
|
+
},
|
|
4753
|
+
{
|
|
4754
|
+
value: 'zoom',
|
|
4755
|
+
label: '缩放'
|
|
4756
|
+
}
|
|
4757
|
+
],
|
|
4758
|
+
onValueChange: (effect)=>onSetEffect('none' === effect ? void 0 : effect)
|
|
4759
|
+
})
|
|
4760
|
+
]
|
|
4761
|
+
}),
|
|
4762
|
+
/*#__PURE__*/ jsxs("div", {
|
|
4763
|
+
className: "work-office-field trigger",
|
|
4764
|
+
children: [
|
|
4765
|
+
/*#__PURE__*/ jsx("span", {
|
|
4766
|
+
children: "开始"
|
|
4767
|
+
}),
|
|
4768
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4769
|
+
ariaLabel: "对象入场动画触发方式",
|
|
4770
|
+
disabled: !animation,
|
|
4771
|
+
value: animation?.trigger ?? 'on-click',
|
|
4772
|
+
options: [
|
|
4773
|
+
{
|
|
4774
|
+
value: 'on-click',
|
|
4775
|
+
label: '单击时'
|
|
4776
|
+
},
|
|
4777
|
+
{
|
|
4778
|
+
value: 'with-previous',
|
|
4779
|
+
label: '与上一动画同时'
|
|
4780
|
+
},
|
|
4781
|
+
{
|
|
4782
|
+
value: 'after-previous',
|
|
4783
|
+
label: '上一动画之后'
|
|
4784
|
+
}
|
|
4785
|
+
],
|
|
4786
|
+
onValueChange: (trigger)=>onUpdate({
|
|
4787
|
+
trigger: trigger
|
|
4788
|
+
})
|
|
4789
|
+
})
|
|
4790
|
+
]
|
|
4791
|
+
}),
|
|
4792
|
+
animation?.effect === 'fly-in' && /*#__PURE__*/ jsxs("div", {
|
|
4793
|
+
className: "work-office-field direction",
|
|
4794
|
+
children: [
|
|
4795
|
+
/*#__PURE__*/ jsx("span", {
|
|
4796
|
+
children: "方向"
|
|
4797
|
+
}),
|
|
4798
|
+
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
4799
|
+
ariaLabel: "对象飞入方向",
|
|
4800
|
+
value: animation.direction ?? 'left',
|
|
4801
|
+
options: [
|
|
4802
|
+
{
|
|
4803
|
+
value: 'left',
|
|
4804
|
+
label: '从左侧'
|
|
4805
|
+
},
|
|
4806
|
+
{
|
|
4807
|
+
value: 'right',
|
|
4808
|
+
label: '从右侧'
|
|
4809
|
+
},
|
|
4810
|
+
{
|
|
4811
|
+
value: 'up',
|
|
4812
|
+
label: '从上方'
|
|
4813
|
+
},
|
|
4814
|
+
{
|
|
4815
|
+
value: 'down',
|
|
4816
|
+
label: '从下方'
|
|
4817
|
+
}
|
|
4818
|
+
],
|
|
4819
|
+
onValueChange: (direction)=>onUpdate({
|
|
4820
|
+
direction: direction
|
|
4821
|
+
})
|
|
4822
|
+
})
|
|
4823
|
+
]
|
|
4824
|
+
})
|
|
4825
|
+
]
|
|
4826
|
+
})
|
|
4827
|
+
}),
|
|
4828
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4829
|
+
label: "动画计时",
|
|
4830
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
4831
|
+
className: "work-presentation-animation-timing",
|
|
4832
|
+
children: [
|
|
4833
|
+
/*#__PURE__*/ jsx(AnimationTimingField, {
|
|
4834
|
+
animationId: animation?.id,
|
|
4835
|
+
ariaLabel: "对象入场动画持续秒数",
|
|
4836
|
+
disabled: !animation,
|
|
4837
|
+
label: "持续",
|
|
4838
|
+
maximumMs: 60000,
|
|
4839
|
+
minimumMs: 100,
|
|
4840
|
+
valueMs: animation?.durationMs ?? 500,
|
|
4841
|
+
onCommit: (durationMs)=>onUpdate({
|
|
4842
|
+
durationMs
|
|
4843
|
+
})
|
|
4844
|
+
}),
|
|
4845
|
+
/*#__PURE__*/ jsx(AnimationTimingField, {
|
|
4846
|
+
animationId: animation?.id,
|
|
4847
|
+
ariaLabel: "对象入场动画延迟秒数",
|
|
4848
|
+
disabled: !animation,
|
|
4849
|
+
label: "延迟",
|
|
4850
|
+
maximumMs: 60000,
|
|
4851
|
+
minimumMs: 0,
|
|
4852
|
+
valueMs: animation?.delayMs ?? 0,
|
|
4853
|
+
onCommit: (delayMs)=>onUpdate({
|
|
4854
|
+
delayMs
|
|
4855
|
+
})
|
|
4856
|
+
})
|
|
4857
|
+
]
|
|
4858
|
+
})
|
|
4859
|
+
}),
|
|
4860
|
+
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
4861
|
+
label: "动画顺序",
|
|
4862
|
+
children: [
|
|
4863
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4864
|
+
label: "提前对象动画",
|
|
4865
|
+
visibleLabel: "提前",
|
|
4866
|
+
disabled: !canMove(-1),
|
|
4867
|
+
onClick: ()=>onMove(-1),
|
|
4868
|
+
children: /*#__PURE__*/ jsx(ArrowUp, {
|
|
4869
|
+
size: 19
|
|
4870
|
+
})
|
|
4871
|
+
}),
|
|
4872
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4873
|
+
label: "推后对象动画",
|
|
4874
|
+
visibleLabel: "推后",
|
|
4875
|
+
disabled: !canMove(1),
|
|
4876
|
+
onClick: ()=>onMove(1),
|
|
4877
|
+
children: /*#__PURE__*/ jsx(ArrowDown, {
|
|
4878
|
+
size: 19
|
|
4879
|
+
})
|
|
4880
|
+
})
|
|
4881
|
+
]
|
|
4882
|
+
}),
|
|
4883
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4884
|
+
label: "动画预览",
|
|
4885
|
+
children: /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4886
|
+
label: "预览当前幻灯片动画",
|
|
4887
|
+
visibleLabel: "预览",
|
|
4888
|
+
disabled: !canPreview,
|
|
4889
|
+
onClick: onPreview,
|
|
4890
|
+
children: /*#__PURE__*/ jsx(Play, {
|
|
4891
|
+
size: 19
|
|
4892
|
+
})
|
|
4893
|
+
})
|
|
4894
|
+
})
|
|
4895
|
+
]
|
|
4896
|
+
});
|
|
4897
|
+
}
|
|
4898
|
+
function AnimationTimingField({ animationId, ariaLabel, disabled, label, maximumMs, minimumMs, onCommit, valueMs }) {
|
|
4899
|
+
const canonical = animationSecondsDraft(valueMs);
|
|
4900
|
+
const [draft, setDraft] = useState(canonical);
|
|
4901
|
+
useEffect(()=>setDraft(canonical), [
|
|
4902
|
+
animationId,
|
|
4903
|
+
canonical
|
|
4904
|
+
]);
|
|
4905
|
+
const commit = (value)=>{
|
|
4906
|
+
const next = normalizedAnimationMilliseconds(value, valueMs, minimumMs, maximumMs);
|
|
4907
|
+
setDraft(animationSecondsDraft(next));
|
|
4908
|
+
if (next !== valueMs) onCommit(next);
|
|
4909
|
+
};
|
|
4910
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
4911
|
+
className: "work-office-field seconds",
|
|
4912
|
+
children: [
|
|
4913
|
+
/*#__PURE__*/ jsx("span", {
|
|
4914
|
+
children: label
|
|
4915
|
+
}),
|
|
4916
|
+
/*#__PURE__*/ jsx(OfficeNumberField, {
|
|
4917
|
+
ariaLabel: ariaLabel,
|
|
4918
|
+
disabled: disabled,
|
|
4919
|
+
min: minimumMs / 1000,
|
|
4920
|
+
max: maximumMs / 1000,
|
|
4921
|
+
step: 0.1,
|
|
4922
|
+
value: draft,
|
|
4923
|
+
escapeConsumer: draft !== canonical,
|
|
4924
|
+
onValueChange: setDraft,
|
|
4925
|
+
onCommit: commit,
|
|
4926
|
+
onCancel: ()=>setDraft(canonical)
|
|
4927
|
+
})
|
|
4928
|
+
]
|
|
4929
|
+
});
|
|
4930
|
+
}
|
|
4931
|
+
function animationSecondsDraft(valueMs) {
|
|
4932
|
+
return String(valueMs / 1000);
|
|
4933
|
+
}
|
|
4934
|
+
function normalizedAnimationMilliseconds(value, current, minimum, maximum) {
|
|
4935
|
+
if (!value.trim()) return current;
|
|
4936
|
+
const seconds = Number(value);
|
|
4937
|
+
if (!Number.isFinite(seconds)) return current;
|
|
4938
|
+
const stepped = Math.round(10 * seconds) / 10;
|
|
4939
|
+
return Math.round(1000 * Math.min(maximum / 1000, Math.max(minimum / 1000, stepped)));
|
|
4940
|
+
}
|
|
4597
4941
|
function PresentationTransitionPanel({ slideId, transition, editable, canApplyToAll, onChange, onApplyToAll }) {
|
|
4598
4942
|
const update = (patch)=>{
|
|
4599
4943
|
if (transition) onChange({
|
|
@@ -4891,6 +5235,10 @@ const presentationRibbonTabs = [
|
|
|
4891
5235
|
id: 'transitions',
|
|
4892
5236
|
label: '切换'
|
|
4893
5237
|
},
|
|
5238
|
+
{
|
|
5239
|
+
id: 'animations',
|
|
5240
|
+
label: '动画'
|
|
5241
|
+
},
|
|
4894
5242
|
{
|
|
4895
5243
|
id: 'slideshow',
|
|
4896
5244
|
label: '幻灯片放映',
|
|
@@ -4949,6 +5297,7 @@ function PresentationToolbar({ selectedSlide, selectedElement, selectedUnitCount
|
|
|
4949
5297
|
const officeDialog = useOfficeDialog();
|
|
4950
5298
|
const [fontSizeDraft, setFontSizeDraft] = useState(()=>selectedElement ? String(selectedElement.fontSize) : '');
|
|
4951
5299
|
const fontFamilyValue = presentationFontFamilyValue(selectedElement?.fontFamily);
|
|
5300
|
+
const selectedAnimation = workSlideAnimationForElement(selectedSlide, selectedElement?.id);
|
|
4952
5301
|
useEffect(()=>{
|
|
4953
5302
|
setFontSizeDraft(selectedElement ? String(selectedElement.fontSize) : '');
|
|
4954
5303
|
}, [
|
|
@@ -5363,6 +5712,16 @@ function PresentationToolbar({ selectedSlide, selectedElement, selectedUnitCount
|
|
|
5363
5712
|
onChange: commands.setTransition,
|
|
5364
5713
|
onApplyToAll: commands.applyTransitionToAll
|
|
5365
5714
|
}),
|
|
5715
|
+
animations: /*#__PURE__*/ jsx(PresentationAnimationPanel, {
|
|
5716
|
+
animation: selectedAnimation,
|
|
5717
|
+
canMove: can.moveEntranceAnimation,
|
|
5718
|
+
canPreview: can.previewAnimations(),
|
|
5719
|
+
editable: can.setEntranceAnimation(selectedAnimation?.effect),
|
|
5720
|
+
onMove: commands.moveEntranceAnimation,
|
|
5721
|
+
onPreview: commands.previewAnimations,
|
|
5722
|
+
onSetEffect: commands.setEntranceAnimation,
|
|
5723
|
+
onUpdate: commands.updateEntranceAnimation
|
|
5724
|
+
}),
|
|
5366
5725
|
slideshow: /*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
5367
5726
|
label: "开始放映",
|
|
5368
5727
|
children: [
|
|
@@ -6502,7 +6861,7 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6502
6861
|
const selectedElement = selectedElements.at(-1) ?? null;
|
|
6503
6862
|
const copySelection = useCallback(()=>{
|
|
6504
6863
|
if (selectedElements.length) {
|
|
6505
|
-
copyPresentationElements(selectedElements);
|
|
6864
|
+
copyPresentationElements(selectedElements, 'slide' === mode ? selectedSlide?.animations : void 0);
|
|
6506
6865
|
showToast(selectedElements.length > 1 ? `已复制 ${selectedElements.length} 个对象` : '已复制演示元素', 'success');
|
|
6507
6866
|
return true;
|
|
6508
6867
|
}
|
|
@@ -6518,7 +6877,7 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6518
6877
|
const deleteSelectedElement = useCallback(()=>{
|
|
6519
6878
|
if (!selectedElements.length || !targetId) return false;
|
|
6520
6879
|
const selectedIds = new Set(selectedElements.map((element)=>element.id));
|
|
6521
|
-
const next = updateTargetElements(content, mode, targetId, (elements)=>elements.filter((element)=>!selectedIds.has(element.id)));
|
|
6880
|
+
const next = updateTargetElements(content, mode, targetId, (elements)=>elements.filter((element)=>!selectedIds.has(element.id)), selectedIds);
|
|
6522
6881
|
if (!next) return false;
|
|
6523
6882
|
onChange(next);
|
|
6524
6883
|
onSelectElements([]);
|
|
@@ -6533,7 +6892,7 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6533
6892
|
]);
|
|
6534
6893
|
const cutSelection = useCallback(()=>{
|
|
6535
6894
|
if (selectedElements.length) {
|
|
6536
|
-
copyPresentationElements(selectedElements);
|
|
6895
|
+
copyPresentationElements(selectedElements, 'slide' === mode ? selectedSlide?.animations : void 0);
|
|
6537
6896
|
if (!deleteSelectedElement()) return false;
|
|
6538
6897
|
showToast(selectedElements.length > 1 ? `已剪切 ${selectedElements.length} 个对象` : '已剪切演示元素', 'success');
|
|
6539
6898
|
return true;
|
|
@@ -6572,17 +6931,25 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6572
6931
|
}
|
|
6573
6932
|
if ('element' === clipboard.payload.kind || 'elements' === clipboard.payload.kind) {
|
|
6574
6933
|
if (!targetId) return false;
|
|
6575
|
-
const
|
|
6576
|
-
|
|
6577
|
-
] :
|
|
6934
|
+
const sourceElements = 'element' === clipboard.payload.kind ? [
|
|
6935
|
+
clipboard.payload.element
|
|
6936
|
+
] : clipboard.payload.elements;
|
|
6937
|
+
const sourceAnimations = 'element' === clipboard.payload.kind ? clipboard.payload.animation ? [
|
|
6938
|
+
clipboard.payload.animation
|
|
6939
|
+
] : [] : clipboard.payload.animations ?? [];
|
|
6940
|
+
const pasted = clonePresentationElementsAndAnimationsForPaste(sourceElements, sourceAnimations, clipboard.offset);
|
|
6941
|
+
if ('slide' === mode && !canAppendSlideAnimations(content, targetId, pasted.animations)) {
|
|
6942
|
+
showToast('对象动画数量已达到每张幻灯片 256 条的上限。', 'info');
|
|
6943
|
+
return true;
|
|
6944
|
+
}
|
|
6578
6945
|
const next = updateTargetElements(content, mode, targetId, (elements)=>[
|
|
6579
6946
|
...elements,
|
|
6580
|
-
...pasted
|
|
6581
|
-
]);
|
|
6947
|
+
...pasted.elements
|
|
6948
|
+
], void 0, pasted.animations);
|
|
6582
6949
|
if (!next) return false;
|
|
6583
6950
|
onChange(next);
|
|
6584
|
-
onSelectElements(pasted.map((element)=>element.id));
|
|
6585
|
-
showToast(pasted.length > 1 ? `已粘贴 ${pasted.length} 个对象` : '已粘贴演示元素', 'success');
|
|
6951
|
+
onSelectElements(pasted.elements.map((element)=>element.id));
|
|
6952
|
+
showToast(pasted.elements.length > 1 ? `已粘贴 ${pasted.elements.length} 个对象` : '已粘贴演示元素', 'success');
|
|
6586
6953
|
return true;
|
|
6587
6954
|
}
|
|
6588
6955
|
if ('slide' !== mode || !selectedSlide) {
|
|
@@ -6614,15 +6981,19 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6614
6981
|
]);
|
|
6615
6982
|
const duplicateSelection = useCallback(()=>{
|
|
6616
6983
|
if (selectedElements.length && targetId) {
|
|
6617
|
-
const copies =
|
|
6984
|
+
const copies = clonePresentationElementsAndAnimationsForPaste(selectedElements, 'slide' === mode ? selectedSlide?.animations ?? [] : [], 5);
|
|
6985
|
+
if ('slide' === mode && !canAppendSlideAnimations(content, targetId, copies.animations)) {
|
|
6986
|
+
showToast('对象动画数量已达到每张幻灯片 256 条的上限。', 'info');
|
|
6987
|
+
return true;
|
|
6988
|
+
}
|
|
6618
6989
|
const next = updateTargetElements(content, mode, targetId, (elements)=>[
|
|
6619
6990
|
...elements,
|
|
6620
|
-
...copies
|
|
6621
|
-
]);
|
|
6991
|
+
...copies.elements
|
|
6992
|
+
], void 0, copies.animations);
|
|
6622
6993
|
if (!next) return false;
|
|
6623
6994
|
onChange(next);
|
|
6624
|
-
onSelectElements(copies.map((element)=>element.id));
|
|
6625
|
-
showToast(copies.length > 1 ? `已复制 ${copies.length} 个对象` : '已复制演示元素', 'success');
|
|
6995
|
+
onSelectElements(copies.elements.map((element)=>element.id));
|
|
6996
|
+
showToast(copies.elements.length > 1 ? `已复制 ${copies.elements.length} 个对象` : '已复制演示元素', 'success');
|
|
6626
6997
|
return true;
|
|
6627
6998
|
}
|
|
6628
6999
|
if ('slide' !== mode || !selectedSlide) return false;
|
|
@@ -6709,15 +7080,15 @@ function usePresentationClipboard({ content, mode, targetId, selectedSlide, sele
|
|
|
6709
7080
|
toggleUnderline
|
|
6710
7081
|
};
|
|
6711
7082
|
}
|
|
6712
|
-
function updateTargetElements(content, mode, targetId, update) {
|
|
7083
|
+
function updateTargetElements(content, mode, targetId, update, removedElementIds, addedAnimations) {
|
|
6713
7084
|
if ('slide' === mode) {
|
|
6714
7085
|
if (!content.slides.some((slide)=>slide.id === targetId)) return null;
|
|
6715
7086
|
return {
|
|
6716
7087
|
...content,
|
|
6717
|
-
slides: content.slides.map((slide)=>slide.id === targetId ? {
|
|
7088
|
+
slides: content.slides.map((slide)=>slide.id === targetId ? appendWorkSlideAnimations(removeWorkSlideAnimationsForElements({
|
|
6718
7089
|
...slide,
|
|
6719
7090
|
elements: update(use_presentation_clipboard_structuredCopy(slide.elements))
|
|
6720
|
-
} : slide)
|
|
7091
|
+
}, removedElementIds ?? new Set()), addedAnimations) : slide)
|
|
6721
7092
|
};
|
|
6722
7093
|
}
|
|
6723
7094
|
const normalized = withPresentationDesign(content);
|
|
@@ -6740,10 +7111,130 @@ function updateTargetElements(content, mode, targetId, update) {
|
|
|
6740
7111
|
} : master)
|
|
6741
7112
|
};
|
|
6742
7113
|
}
|
|
7114
|
+
function canAppendSlideAnimations(content, slideId, animations) {
|
|
7115
|
+
if (!animations?.length) return true;
|
|
7116
|
+
const slide = content.slides.find((candidate)=>candidate.id === slideId);
|
|
7117
|
+
return Boolean(slide) && (slide?.animations?.length ?? 0) + animations.length <= 256;
|
|
7118
|
+
}
|
|
7119
|
+
function appendWorkSlideAnimations(slide, animations) {
|
|
7120
|
+
if (!animations?.length) return slide;
|
|
7121
|
+
return {
|
|
7122
|
+
...slide,
|
|
7123
|
+
animations: [
|
|
7124
|
+
...slide.animations ?? [],
|
|
7125
|
+
...use_presentation_clipboard_structuredCopy(animations)
|
|
7126
|
+
]
|
|
7127
|
+
};
|
|
7128
|
+
}
|
|
6743
7129
|
function use_presentation_clipboard_structuredCopy(value) {
|
|
6744
7130
|
if ('function' == typeof structuredClone) return structuredClone(value);
|
|
6745
7131
|
return JSON.parse(JSON.stringify(value));
|
|
6746
7132
|
}
|
|
7133
|
+
function usePresentationAnimationCommands({ content, onChange, selectedElementId, selectedSlide }) {
|
|
7134
|
+
const selectedElementExists = Boolean(selectedElementId && selectedSlide.elements.some((element)=>element.id === selectedElementId));
|
|
7135
|
+
const selectedAnimation = workSlideAnimationForElement(selectedSlide, selectedElementId);
|
|
7136
|
+
const setEntranceAnimation = useCallback((effect)=>{
|
|
7137
|
+
if (!selectedElementId || !selectedElementExists) return false;
|
|
7138
|
+
const current = workSlideAnimationForElement(selectedSlide, selectedElementId);
|
|
7139
|
+
if (!effect) {
|
|
7140
|
+
if (!current) return false;
|
|
7141
|
+
updateSlide(content, selectedSlide.id, (slide)=>{
|
|
7142
|
+
const animations = slide.animations?.filter((animation)=>animation.id !== current.id);
|
|
7143
|
+
return {
|
|
7144
|
+
...slide,
|
|
7145
|
+
animations: animations?.length ? animations : void 0
|
|
7146
|
+
};
|
|
7147
|
+
}, onChange);
|
|
7148
|
+
return true;
|
|
7149
|
+
}
|
|
7150
|
+
if (current?.effect === effect) return false;
|
|
7151
|
+
if (!current && (selectedSlide.animations?.length ?? 0) >= 256) return false;
|
|
7152
|
+
updateSlide(content, selectedSlide.id, (slide)=>{
|
|
7153
|
+
const next = createWorkSlideAnimation(selectedElementId, effect, current);
|
|
7154
|
+
const animations = [
|
|
7155
|
+
...slide.animations ?? []
|
|
7156
|
+
];
|
|
7157
|
+
const index = current ? animations.findIndex((animation)=>animation.id === current.id) : -1;
|
|
7158
|
+
if (index >= 0) animations[index] = next;
|
|
7159
|
+
else animations.push(next);
|
|
7160
|
+
return {
|
|
7161
|
+
...slide,
|
|
7162
|
+
animations
|
|
7163
|
+
};
|
|
7164
|
+
}, onChange);
|
|
7165
|
+
return true;
|
|
7166
|
+
}, [
|
|
7167
|
+
content,
|
|
7168
|
+
onChange,
|
|
7169
|
+
selectedElementExists,
|
|
7170
|
+
selectedElementId,
|
|
7171
|
+
selectedSlide
|
|
7172
|
+
]);
|
|
7173
|
+
const updateEntranceAnimation = useCallback((patch)=>{
|
|
7174
|
+
if (!selectedAnimation) return false;
|
|
7175
|
+
const next = normalizeWorkSlideAnimation({
|
|
7176
|
+
...selectedAnimation,
|
|
7177
|
+
...patch,
|
|
7178
|
+
id: selectedAnimation.id,
|
|
7179
|
+
elementId: selectedAnimation.elementId
|
|
7180
|
+
});
|
|
7181
|
+
if (animationsEqual(selectedAnimation, next)) return false;
|
|
7182
|
+
updateSlide(content, selectedSlide.id, (slide)=>({
|
|
7183
|
+
...slide,
|
|
7184
|
+
animations: slide.animations?.map((animation)=>animation.id === selectedAnimation.id ? next : animation)
|
|
7185
|
+
}), onChange);
|
|
7186
|
+
return true;
|
|
7187
|
+
}, [
|
|
7188
|
+
content,
|
|
7189
|
+
onChange,
|
|
7190
|
+
selectedAnimation,
|
|
7191
|
+
selectedSlide.id
|
|
7192
|
+
]);
|
|
7193
|
+
const canMoveEntranceAnimation = useCallback((direction)=>{
|
|
7194
|
+
const index = workSlideAnimationIndex(selectedSlide, selectedAnimation?.id);
|
|
7195
|
+
const target = index + direction;
|
|
7196
|
+
return index >= 0 && target >= 0 && target < (selectedSlide.animations?.length ?? 0);
|
|
7197
|
+
}, [
|
|
7198
|
+
selectedAnimation?.id,
|
|
7199
|
+
selectedSlide
|
|
7200
|
+
]);
|
|
7201
|
+
const moveEntranceAnimation = useCallback((direction)=>{
|
|
7202
|
+
if (!selectedAnimation || !canMoveEntranceAnimation(direction)) return false;
|
|
7203
|
+
updateSlide(content, selectedSlide.id, (slide)=>{
|
|
7204
|
+
const animations = [
|
|
7205
|
+
...slide.animations ?? []
|
|
7206
|
+
];
|
|
7207
|
+
const index = animations.findIndex((animation)=>animation.id === selectedAnimation.id);
|
|
7208
|
+
const target = index + direction;
|
|
7209
|
+
[animations[index], animations[target]] = [
|
|
7210
|
+
animations[target],
|
|
7211
|
+
animations[index]
|
|
7212
|
+
];
|
|
7213
|
+
return {
|
|
7214
|
+
...slide,
|
|
7215
|
+
animations
|
|
7216
|
+
};
|
|
7217
|
+
}, onChange);
|
|
7218
|
+
return true;
|
|
7219
|
+
}, [
|
|
7220
|
+
canMoveEntranceAnimation,
|
|
7221
|
+
content,
|
|
7222
|
+
onChange,
|
|
7223
|
+
selectedAnimation,
|
|
7224
|
+
selectedSlide.id
|
|
7225
|
+
]);
|
|
7226
|
+
return {
|
|
7227
|
+
canMoveEntranceAnimation,
|
|
7228
|
+
canSetEntranceAnimation: selectedElementExists,
|
|
7229
|
+
canUpdateEntranceAnimation: Boolean(selectedAnimation),
|
|
7230
|
+
moveEntranceAnimation,
|
|
7231
|
+
setEntranceAnimation,
|
|
7232
|
+
updateEntranceAnimation
|
|
7233
|
+
};
|
|
7234
|
+
}
|
|
7235
|
+
function animationsEqual(left, right) {
|
|
7236
|
+
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;
|
|
7237
|
+
}
|
|
6747
7238
|
function usePresentationDesignCommands({ activeElements, activeTargetId, designContent, designMode, designOpen, onChange, onClearSelection, onCloseComments, onEditElement, onSetDesignMode, onSetDesignOpen, selectedLayout, selectedMaster, selectedSlide }) {
|
|
6748
7239
|
const updateLayout = useCallback((layoutId, update)=>{
|
|
6749
7240
|
onChange({
|
|
@@ -8142,6 +8633,12 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
8142
8633
|
onSelectSlide: setSelectedSlideId,
|
|
8143
8634
|
selectedSlide
|
|
8144
8635
|
});
|
|
8636
|
+
const presentationAnimations = usePresentationAnimationCommands({
|
|
8637
|
+
content,
|
|
8638
|
+
onChange,
|
|
8639
|
+
selectedElementId: 'slide' === designMode && singleSelectedElement ? singleSelectedElement.id : void 0,
|
|
8640
|
+
selectedSlide
|
|
8641
|
+
});
|
|
8145
8642
|
const presentationElements = usePresentationElementCommands({
|
|
8146
8643
|
activeElements,
|
|
8147
8644
|
activeTargetId,
|
|
@@ -8274,8 +8771,30 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
8274
8771
|
selectedTextEditor,
|
|
8275
8772
|
toolbarSelectedElement
|
|
8276
8773
|
]);
|
|
8774
|
+
const startPresentationSlideshow = useCallback((source)=>{
|
|
8775
|
+
const currentIndex = content.slides.findIndex((slide)=>slide.id === selectedSlide.id);
|
|
8776
|
+
const activeElement = document.activeElement;
|
|
8777
|
+
slideshowReturnFocusRef.current = activeElement instanceof HTMLElement && activeElement !== document.body ? activeElement : document.querySelector(`[data-presentation-slideshow-source="${source}"]`);
|
|
8778
|
+
setAgentMenu(null);
|
|
8779
|
+
setSlideshowStartIndex('current' === source ? Math.max(0, currentIndex) : 0);
|
|
8780
|
+
onStartSlideshow?.();
|
|
8781
|
+
}, [
|
|
8782
|
+
content.slides,
|
|
8783
|
+
onStartSlideshow,
|
|
8784
|
+
selectedSlide.id
|
|
8785
|
+
]);
|
|
8277
8786
|
const presentationExtensions = useMemo(createPresentationEditorExtensions, []);
|
|
8278
8787
|
const presentationEditor = useOfficeEditorRuntime({
|
|
8788
|
+
animations: {
|
|
8789
|
+
canMoveEntranceAnimation: (direction)=>'slide' === designMode && presentationAnimations.canMoveEntranceAnimation(direction),
|
|
8790
|
+
canPreviewAnimations: 'slide' === designMode && Boolean(selectedSlide.animations?.length),
|
|
8791
|
+
canSetEntranceAnimation: 'slide' === designMode && presentationAnimations.canSetEntranceAnimation,
|
|
8792
|
+
canUpdateEntranceAnimation: 'slide' === designMode && presentationAnimations.canUpdateEntranceAnimation,
|
|
8793
|
+
moveEntranceAnimation: presentationAnimations.moveEntranceAnimation,
|
|
8794
|
+
previewAnimations: ()=>startPresentationSlideshow('current'),
|
|
8795
|
+
setEntranceAnimation: presentationAnimations.setEntranceAnimation,
|
|
8796
|
+
updateEntranceAnimation: presentationAnimations.updateEntranceAnimation
|
|
8797
|
+
},
|
|
8279
8798
|
clipboard: {
|
|
8280
8799
|
canCopySelection: selectedElements.length > 0 || 'slide' === designMode && Boolean(selectedSlide),
|
|
8281
8800
|
canCutSelection: selectedElements.length > 0 || 'slide' === designMode && Boolean(selectedSlide),
|
|
@@ -8392,14 +8911,7 @@ function PresentationEditingSurface({ initialSlide, autoFocus = true, collaborat
|
|
|
8392
8911
|
view: {
|
|
8393
8912
|
canStartSlideshow: 'slide' === designMode && content.slides.length > 0,
|
|
8394
8913
|
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
|
-
},
|
|
8914
|
+
startSlideshow: startPresentationSlideshow,
|
|
8403
8915
|
toggleDesign: presentationDesign.toggleDesignPanel
|
|
8404
8916
|
}
|
|
8405
8917
|
}, presentationExtensions);
|