@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.
Files changed (30) hide show
  1. package/README.md +23 -19
  2. package/dist/0~5809.js +123 -0
  3. package/dist/{0~7614.js → 0~7828.js} +376 -5
  4. package/dist/0~pdf-viewer.js +5 -1
  5. package/dist/0~presentation-editor.js +597 -71
  6. package/dist/0~spreadsheet-editor.js +166 -18
  7. package/dist/0~work-pptx-export.js +50 -14
  8. package/dist/0~work-pptx-import.js +21 -9
  9. package/dist/4121.js +122 -1
  10. package/dist/4560.js +33 -0
  11. package/dist/internal/features/work/editors/presentation-animation-panel.d.ts +11 -0
  12. package/dist/internal/features/work/editors/presentation-command-types.d.ts +16 -1
  13. package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +2 -0
  14. package/dist/internal/features/work/editors/presentation-presenter-view.d.ts +2 -1
  15. package/dist/internal/features/work/editors/presentation-slide-canvas.d.ts +11 -3
  16. package/dist/internal/features/work/editors/presentation-text-editor.d.ts +7 -0
  17. package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -0
  18. package/dist/internal/features/work/editors/spreadsheet-command-selection.d.ts +22 -1
  19. package/dist/internal/features/work/editors/use-presentation-animation-commands.d.ts +15 -0
  20. package/dist/internal/features/work/editors/use-presentation-selection.d.ts +1 -1
  21. package/dist/internal/features/work/work-pptx-animation.d.ts +13 -0
  22. package/dist/internal/features/work/work-pptx-groups.d.ts +4 -0
  23. package/dist/internal/features/work/work-presentation-animation-constraints.d.ts +4 -0
  24. package/dist/internal/features/work/work-presentation-animation.d.ts +20 -0
  25. package/dist/internal/features/work/work-presentation-clipboard.d.ts +10 -3
  26. package/dist/internal/features/work/work-types.d.ts +17 -0
  27. package/dist/office-kernel.wasm +0 -0
  28. package/dist/styles.css +123 -0
  29. package/package.json +19 -13
  30. package/dist/0~work-presentation-transition.js +0 -38
package/dist/4121.js CHANGED
@@ -2918,6 +2918,13 @@ const WORK_TEMPLATES = [
2918
2918
  name: '策略汇报',
2919
2919
  description: '结论先行的三页汇报',
2920
2920
  accent: '#c85637'
2921
+ },
2922
+ {
2923
+ id: 'animated-deck',
2924
+ kind: 'presentation',
2925
+ name: '入场动画',
2926
+ description: '出现、淡入、飞入、缩放与三种触发方式',
2927
+ accent: '#7657c8'
2921
2928
  }
2922
2929
  ];
2923
2930
  function createWorkArtifact(templateId) {
@@ -2951,7 +2958,8 @@ function initialTitle(templateId, kind) {
2951
2958
  'proofing-languages': '校对语言示例',
2952
2959
  'quarterly-plan': '季度执行计划',
2953
2960
  'data-validation': '数据验证示例',
2954
- 'strategy-deck': '业务策略汇报'
2961
+ 'strategy-deck': '业务策略汇报',
2962
+ 'animated-deck': '入场动画示例'
2955
2963
  };
2956
2964
  if (titles[templateId]) return titles[templateId];
2957
2965
  if ('document' === kind) return '无标题文字';
@@ -3250,6 +3258,7 @@ function contentForTemplate(templateId) {
3250
3258
  sheets: dataValidationTemplateSheets()
3251
3259
  };
3252
3260
  if ('strategy-deck' === templateId) return strategyPresentation();
3261
+ if ('animated-deck' === templateId) return animatedPresentation();
3253
3262
  if ('blank-spreadsheet' === templateId) return {
3254
3263
  type: 'spreadsheet',
3255
3264
  sheets: [
@@ -3836,6 +3845,118 @@ function strategyPresentation() {
3836
3845
  slides
3837
3846
  };
3838
3847
  }
3848
+ function animatedPresentation() {
3849
+ const titleId = createWorkId('element');
3850
+ const subtitleId = createWorkId('element');
3851
+ const sequenceId = createWorkId('element');
3852
+ const conclusionId = createWorkId('element');
3853
+ return {
3854
+ type: 'presentation',
3855
+ slides: [
3856
+ {
3857
+ id: createWorkId('slide'),
3858
+ name: '入场动画',
3859
+ background: '#17162b',
3860
+ notes: '从“动画”选项卡编辑效果、触发方式、持续时间、延迟和顺序,再从头放映验证逐步播放。',
3861
+ elements: [
3862
+ {
3863
+ id: titleId,
3864
+ type: 'text',
3865
+ x: 8,
3866
+ y: 10,
3867
+ width: 76,
3868
+ height: 16,
3869
+ text: '让信息按叙事顺序出现',
3870
+ fontSize: 34,
3871
+ color: '#ffffff',
3872
+ fill: 'transparent',
3873
+ bold: true,
3874
+ align: 'left'
3875
+ },
3876
+ {
3877
+ id: subtitleId,
3878
+ type: 'text',
3879
+ x: 8,
3880
+ y: 28,
3881
+ width: 68,
3882
+ height: 9,
3883
+ text: '单击开始,下一对象与标题同时淡入',
3884
+ fontSize: 16,
3885
+ color: '#b9b7dc',
3886
+ fill: 'transparent',
3887
+ bold: false,
3888
+ align: 'left'
3889
+ },
3890
+ {
3891
+ id: sequenceId,
3892
+ type: 'shape',
3893
+ x: 8,
3894
+ y: 46,
3895
+ width: 52,
3896
+ height: 20,
3897
+ text: '上一动画完成后,从左侧飞入',
3898
+ fontSize: 19,
3899
+ color: '#211f35',
3900
+ fill: '#d9d3ff',
3901
+ bold: true,
3902
+ align: 'center',
3903
+ radius: 4
3904
+ },
3905
+ {
3906
+ id: conclusionId,
3907
+ type: 'shape',
3908
+ x: 66,
3909
+ y: 46,
3910
+ width: 26,
3911
+ height: 20,
3912
+ text: '再次单击\n缩放结论',
3913
+ fontSize: 17,
3914
+ color: '#ffffff',
3915
+ fill: '#7657c8',
3916
+ bold: true,
3917
+ align: 'center',
3918
+ radius: 5
3919
+ }
3920
+ ],
3921
+ animations: [
3922
+ {
3923
+ id: createWorkId('slide-animation'),
3924
+ elementId: titleId,
3925
+ effect: 'appear',
3926
+ trigger: 'on-click',
3927
+ durationMs: 300,
3928
+ delayMs: 0
3929
+ },
3930
+ {
3931
+ id: createWorkId('slide-animation'),
3932
+ elementId: subtitleId,
3933
+ effect: 'fade',
3934
+ trigger: 'with-previous',
3935
+ durationMs: 600,
3936
+ delayMs: 100
3937
+ },
3938
+ {
3939
+ id: createWorkId('slide-animation'),
3940
+ elementId: sequenceId,
3941
+ effect: 'fly-in',
3942
+ trigger: 'after-previous',
3943
+ durationMs: 700,
3944
+ delayMs: 150,
3945
+ direction: 'left'
3946
+ },
3947
+ {
3948
+ id: createWorkId('slide-animation'),
3949
+ elementId: conclusionId,
3950
+ effect: 'zoom',
3951
+ trigger: 'on-click',
3952
+ durationMs: 650,
3953
+ delayMs: 0
3954
+ }
3955
+ ]
3956
+ }
3957
+ ]
3958
+ };
3959
+ }
3839
3960
  const OFFICE_KERNEL_SPREADSHEET_MAX_ROWS = 1048576;
3840
3961
  const spreadsheetErrors = new Set([
3841
3962
  '#BLOCKED!',
package/dist/4560.js CHANGED
@@ -44,8 +44,37 @@ function validateSlide(value) {
44
44
  slide.elements = validateRecords(record.elements, `element in slide '${slide.id}'`, validateElement);
45
45
  if (void 0 !== record.layoutId) slide.layoutId = requiredIdentifier(record.layoutId, 'slide layout');
46
46
  if (void 0 !== record.comments) slide.comments = validateRecords(record.comments, `comment in slide '${slide.id}'`, validateComment);
47
+ if (void 0 !== record.animations) slide.animations = validateSlideAnimations(record.animations, slide);
47
48
  return slide;
48
49
  }
50
+ function validateSlideAnimations(value, slide) {
51
+ if (!Array.isArray(value) || value.length > 256) invalidWorkOfficePresentationInput("an array of at most 256 slide animations");
52
+ const animationIds = new Set();
53
+ const targetIds = new Set();
54
+ const elementIds = new Set(slide.elements.map((element)=>element.id));
55
+ return value.map((item)=>{
56
+ const record = requiredInputRecord(item, 'slide animation');
57
+ const animation = validateJsonRecord(record, 'slide animation');
58
+ animation.id = requiredIdentifier(record.id, 'slide animation');
59
+ animation.elementId = requiredIdentifier(record.elementId, 'slide animation element');
60
+ if (animationIds.has(animation.id)) invalidWorkOfficePresentationInput(`a unique slide animation ID; '${animation.id}' is repeated`);
61
+ if (!elementIds.has(animation.elementId)) invalidWorkOfficePresentationInput(`slide animation '${animation.id}' to reference an existing element`);
62
+ if (targetIds.has(animation.elementId)) invalidWorkOfficePresentationInput(`at most one entrance animation for element '${animation.elementId}'`);
63
+ if ('appear' !== record.effect && 'fade' !== record.effect && 'fly-in' !== record.effect && 'zoom' !== record.effect) invalidWorkOfficePresentationInput('a supported slide entrance animation effect');
64
+ animation.effect = record.effect;
65
+ if ('on-click' !== record.trigger && 'with-previous' !== record.trigger && 'after-previous' !== record.trigger) invalidWorkOfficePresentationInput('a supported slide animation trigger');
66
+ animation.trigger = record.trigger;
67
+ animation.durationMs = requiredIntegerInRange(record.durationMs, 100, 60000, 'slide animation duration');
68
+ animation.delayMs = requiredIntegerInRange(record.delayMs, 0, 60000, 'slide animation delay');
69
+ if ('fly-in' === animation.effect) {
70
+ if ('left' !== record.direction && 'right' !== record.direction && 'up' !== record.direction && 'down' !== record.direction) invalidWorkOfficePresentationInput('a direction for each fly-in animation');
71
+ animation.direction = record.direction;
72
+ } else if (void 0 !== record.direction) invalidWorkOfficePresentationInput('slide animation directions only on fly-in effects');
73
+ animationIds.add(animation.id);
74
+ targetIds.add(animation.elementId);
75
+ return animation;
76
+ });
77
+ }
49
78
  function validateMaster(value) {
50
79
  const record = requiredInputRecord(value, 'presentation master');
51
80
  const master = validateJsonRecord(record, 'presentation master');
@@ -129,6 +158,10 @@ function requiredFiniteNumber(value, label) {
129
158
  if ('number' != typeof value || !Number.isFinite(value)) invalidWorkOfficePresentationInput(`a finite number for ${label}`);
130
159
  return value;
131
160
  }
161
+ function requiredIntegerInRange(value, minimum, maximum, label) {
162
+ if ('number' != typeof value || !Number.isSafeInteger(value) || value < minimum || value > maximum) invalidWorkOfficePresentationInput(`an integer ${label} from ${minimum} through ${maximum}`);
163
+ return value;
164
+ }
132
165
  function invalidWorkOfficePresentationInput(expected) {
133
166
  throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `Presentation collaboration requires ${expected}.`);
134
167
  }
@@ -0,0 +1,11 @@
1
+ import type { WorkSlideAnimation, WorkSlideAnimationEffect } from '../work-types';
2
+ export declare function PresentationAnimationPanel({ animation, canMove, canPreview, editable, onMove, onPreview, onSetEffect, onUpdate, }: {
3
+ animation: WorkSlideAnimation | undefined;
4
+ canMove: (direction: -1 | 1) => boolean;
5
+ canPreview: boolean;
6
+ editable: boolean;
7
+ onMove: (direction: -1 | 1) => void;
8
+ onPreview: () => void;
9
+ onSetEffect: (effect: WorkSlideAnimationEffect | undefined) => void;
10
+ onUpdate: (patch: Partial<WorkSlideAnimation>) => void;
11
+ }): import("react").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import type { OfficeKernelPresentationAlignment } from '../../../kernel/office-kernel-protocol';
2
- import type { WorkPresentationContent, WorkSlideElement, WorkSlideTransition, WorkSlideTextRun } from '../work-types';
2
+ import type { WorkPresentationContent, WorkSlideAnimation, WorkSlideAnimationEffect, WorkSlideElement, WorkSlideTransition, WorkSlideTextRun } from '../work-types';
3
3
  import type { OfficeEditorCanCommands } from './office-editor-extension';
4
4
  import type { PresentationDesignMode } from './presentation-editor-types';
5
5
  import type { PresentationDistribution } from './presentation-selection';
@@ -37,9 +37,11 @@ export interface PresentationEditorCommands {
37
37
  groupElements: () => boolean;
38
38
  instantiatePlaceholder: (definition: WorkSlideElement) => PresentationCommandResult;
39
39
  locatePresentationComment: (slideId: string, commentId: string) => PresentationCommandResult;
40
+ moveEntranceAnimation: (direction: -1 | 1) => PresentationCommandResult;
40
41
  nudgeSelection: (key: string, distance: number) => boolean;
41
42
  openComment: (commentId: string) => PresentationCommandResult;
42
43
  pasteSelection: () => boolean;
44
+ previewAnimations: () => PresentationCommandResult;
43
45
  redo: () => boolean;
44
46
  renamePresentationLayout: (name: string) => PresentationCommandResult;
45
47
  renamePresentationMaster: (name: string) => PresentationCommandResult;
@@ -50,6 +52,7 @@ export interface PresentationEditorCommands {
50
52
  selectSlide: (slideId: string, returnToSlideMode?: boolean) => PresentationCommandResult;
51
53
  setPresentationContent: (content: WorkPresentationContent) => PresentationCommandResult;
52
54
  setBackground: (color: string) => PresentationCommandResult;
55
+ setEntranceAnimation: (effect: WorkSlideAnimationEffect | undefined) => PresentationCommandResult;
53
56
  setPresentationLayoutBackground: (color: string | undefined) => PresentationCommandResult;
54
57
  setPresentationMasterBackground: (color: string) => PresentationCommandResult;
55
58
  setTransition: (transition: WorkSlideTransition | undefined) => PresentationCommandResult;
@@ -66,6 +69,7 @@ export interface PresentationEditorCommands {
66
69
  updateElement: (patch: Partial<WorkSlideElement>, options?: {
67
70
  restoreTextFocus?: boolean;
68
71
  }) => PresentationCommandResult;
72
+ updateEntranceAnimation: (patch: Partial<WorkSlideAnimation>) => PresentationCommandResult;
69
73
  updateNotes: (notes: string) => PresentationCommandResult;
70
74
  updatePresentationComment: (slideId: string, commentId: string, text: string) => PresentationCommandResult;
71
75
  updateTextElement: (elementId: string, value: {
@@ -107,6 +111,16 @@ export interface PresentationSlideCommandPort {
107
111
  setTransition: (transition: WorkSlideTransition | undefined) => PresentationCommandResult;
108
112
  updateNotes: (notes: string) => PresentationCommandResult;
109
113
  }
114
+ export interface PresentationAnimationCommandPort {
115
+ canMoveEntranceAnimation: (direction: -1 | 1) => boolean;
116
+ canPreviewAnimations: boolean;
117
+ canSetEntranceAnimation: boolean;
118
+ canUpdateEntranceAnimation: boolean;
119
+ moveEntranceAnimation: (direction: -1 | 1) => PresentationCommandResult;
120
+ previewAnimations: () => PresentationCommandResult;
121
+ setEntranceAnimation: (effect: WorkSlideAnimationEffect | undefined) => PresentationCommandResult;
122
+ updateEntranceAnimation: (patch: Partial<WorkSlideAnimation>) => PresentationCommandResult;
123
+ }
110
124
  export interface PresentationInsertCommandPort {
111
125
  enabled: boolean;
112
126
  addChart: () => PresentationCommandResult;
@@ -192,6 +206,7 @@ export interface PresentationKeyboardCommandPort {
192
206
  selectedElementCount: number;
193
207
  }
194
208
  export interface PresentationCommandContext {
209
+ animations: PresentationAnimationCommandPort;
195
210
  clipboard: PresentationClipboardCommandPort;
196
211
  design: PresentationDesignCommandPort;
197
212
  document: PresentationDocumentCommandPort;
@@ -1,4 +1,5 @@
1
1
  import type { PresentationEditorCommands } from './presentation-command-types';
2
+ import type { WorkSlideElement } from '../work-types';
2
3
  export interface PresentationObjectFocusState {
3
4
  editingElementId: string | null;
4
5
  selectedElementIds: readonly string[];
@@ -7,6 +8,7 @@ export interface PresentationWorkspaceFocusState extends PresentationObjectFocus
7
8
  selectedSlideId: string;
8
9
  viewMode: 'normal' | 'sorter';
9
10
  }
11
+ export declare function presentationInitialEditingElementId(elements: readonly WorkSlideElement[]): string | null;
10
12
  export declare function restorePresentationObjectFocus(container: HTMLElement | null, getState: () => PresentationObjectFocusState, focusOrigin?: Element | null): void;
11
13
  export declare function restorePresentationWorkspaceFocus(root: HTMLElement | null, getState: () => PresentationWorkspaceFocusState, focusOrigin?: Element | null): void;
12
14
  export declare function presentationWorkspaceFocusTarget(root: HTMLElement, state: PresentationWorkspaceFocusState): HTMLElement | undefined;
@@ -4,7 +4,8 @@ export interface PresentationTimerController {
4
4
  runningSinceMilliseconds: number | null;
5
5
  }
6
6
  export declare function createPresentationTimerController(now?: number): PresentationTimerController;
7
- export declare function PresentationPresenterView({ content, slide, nextSlide, index, total, aspectRatio, timer, }: {
7
+ export declare function PresentationPresenterView({ animationCueIndex, content, slide, nextSlide, index, total, aspectRatio, timer, }: {
8
+ animationCueIndex?: number;
8
9
  content: WorkPresentationContent;
9
10
  slide: WorkSlide;
10
11
  nextSlide?: WorkSlide;
@@ -1,14 +1,16 @@
1
1
  import { type WorkPresentationDesignContent } from '../work-presentation-layouts';
2
- import type { WorkPresentationContent, WorkSlide, WorkSlideElement } from '../work-types';
3
- export declare function SlideCanvas({ content, designContent, slide, interactive, aspectRatio, showPlaceholders, }: {
2
+ import type { WorkPresentationContent, WorkSlide, WorkSlideAnimation, WorkSlideElement } from '../work-types';
3
+ export declare function SlideCanvas({ content, designContent, slide, interactive, aspectRatio, animationCueIndex, showPlaceholders, }: {
4
4
  content?: WorkPresentationContent;
5
5
  designContent?: WorkPresentationDesignContent;
6
6
  slide: WorkSlide;
7
7
  interactive: boolean;
8
8
  aspectRatio: string;
9
+ animationCueIndex?: number;
9
10
  showPlaceholders?: boolean;
10
11
  }): import("react").JSX.Element;
11
- export declare function SlideElementPreview({ element, origin, showPlaceholder, }: {
12
+ export declare function SlideElementPreview({ animationPlayback, element, origin, showPlaceholder, }: {
13
+ animationPlayback?: SlideElementAnimationPlayback;
12
14
  element: WorkSlideElement;
13
15
  origin: 'inherited' | 'slide';
14
16
  showPlaceholder?: boolean;
@@ -18,6 +20,11 @@ export declare function EditableSlideTable({ element, onChange, }: {
18
20
  onChange: (rows: string[][]) => void;
19
21
  }): import("react").JSX.Element | null;
20
22
  export declare function slideElementStyle(element: WorkSlideElement): React.CSSProperties;
23
+ interface SlideElementAnimationPlayback {
24
+ animation: WorkSlideAnimation;
25
+ startOffsetMs: number;
26
+ state: 'finished' | 'pending' | 'playing';
27
+ }
21
28
  export declare function slideTextStyle(element: WorkSlideElement): React.CSSProperties;
22
29
  export declare function SlideElementTextPreview({ element, showPlaceholder, }: {
23
30
  element: WorkSlideElement;
@@ -26,3 +33,4 @@ export declare function SlideElementTextPreview({ element, showPlaceholder, }: {
26
33
  export declare function SlideTablePreview({ element }: {
27
34
  element: WorkSlideElement;
28
35
  }): import("react").JSX.Element | null;
36
+ export {};
@@ -13,6 +13,13 @@ export interface PresentationTextEditorProps {
13
13
  onSelectionChange?: () => void;
14
14
  }
15
15
  export declare function PresentationTextEditor({ autoFocus, element, onChange, onEditorChange, onExitEditing, onSelectionChange, }: PresentationTextEditorProps): import("react").JSX.Element | null;
16
+ /**
17
+ * Keep delayed first-open focus from overriding a deliberate focus move that
18
+ * happened while the rich-text editor was being created. The document body is
19
+ * treated as an unfocused baseline so opening from a non-focusable surface can
20
+ * still enter the editor normally.
21
+ */
22
+ export declare function presentationFocusOwnerIsUnchanged(initialFocusTarget: HTMLElement | null): boolean;
16
23
  export declare function createPresentationTextEditorExtensions(placeholder?: string): Extensions;
17
24
  export declare function presentationTextElementHtml(element: WorkSlideElement): string;
18
25
  export declare function presentationTextValue(editor: Editor, element: WorkSlideElement): PresentationTextValue;
@@ -67,6 +67,15 @@ export interface SpreadsheetCommandSelection {
67
67
  sheetId: string;
68
68
  selection: Selection;
69
69
  }
70
+ /**
71
+ * Synchronous selection state shared by commands and the Fortune Sheet bridge.
72
+ * Fortune applies API calls through React state, so reading its imperative API
73
+ * twice in the same task can otherwise return the previous selection.
74
+ */
75
+ export interface SpreadsheetSelectionRef {
76
+ current: SpreadsheetCommandSelection | null;
77
+ requested: SpreadsheetCommandSelection | null;
78
+ }
70
79
  export type SpreadsheetStructureAxis = 'row' | 'column';
71
80
  export type SpreadsheetStructureInsertPosition = 'before' | 'after';
72
81
  export type SpreadsheetSortDirection = 'ascending' | 'descending';
@@ -238,6 +247,7 @@ export interface SpreadsheetCommandContext {
238
247
  onChange: (content: WorkSpreadsheetContent) => void;
239
248
  richTextFormat?: SpreadsheetRichTextFormatCommandPort | null;
240
249
  selection: SpreadsheetCommandSelection | null;
250
+ selectionRef?: SpreadsheetSelectionRef;
241
251
  table: SpreadsheetTableCommandPort;
242
252
  targetSheetGridSize?: SpreadsheetGridSize | null;
243
253
  targetSheetId: string;
@@ -1,3 +1,24 @@
1
- import type { SpreadsheetCommandContext, SpreadsheetCommandRange } from './spreadsheet-command-controller';
1
+ import type { SpreadsheetCommandContext, SpreadsheetCommandSelection, SpreadsheetCommandRange, SpreadsheetSelectionRef } from './spreadsheet-command-controller';
2
2
  export declare function canEditSpreadsheetSelection(context: SpreadsheetCommandContext): boolean;
3
3
  export declare function spreadsheetLiveCommandRange(context: SpreadsheetCommandContext): SpreadsheetCommandRange;
4
+ /**
5
+ * Returns the most recent selection known to the Office bridge. The ref is
6
+ * intentionally checked before Fortune's imperative API because that API is
7
+ * backed by React state and can lag behind a just-issued keyboard command.
8
+ */
9
+ export declare function spreadsheetLiveCommandSelection(context: SpreadsheetCommandContext): SpreadsheetCommandRange | undefined;
10
+ /**
11
+ * Returns all current selections while preserving the workbook's multi-range
12
+ * semantics. A synchronous command selection is represented as one range.
13
+ */
14
+ export declare function spreadsheetLiveCommandSelections(context: SpreadsheetCommandContext): SpreadsheetCommandRange[] | undefined;
15
+ /**
16
+ * Accept a Fortune selection callback unless it is older than a pending
17
+ * programmatic selection request. The returned value is the normalized state
18
+ * that should be published to React and collaboration consumers.
19
+ */
20
+ export declare function acceptSpreadsheetSelectionChange(selectionRef: SpreadsheetSelectionRef, sheetId: string, selection: SpreadsheetCommandRange): SpreadsheetCommandSelection | null;
21
+ export declare function rememberSpreadsheetCommandSelection(context: SpreadsheetCommandContext, selection: SpreadsheetCommandRange): void;
22
+ /** Clear a pending programmatic request when a fresh user intent arrives. */
23
+ export declare function releaseSpreadsheetSelectionRequest(selectionRef: SpreadsheetSelectionRef): void;
24
+ export declare function sameSpreadsheetSelectionValue(left: SpreadsheetCommandRange, right: SpreadsheetCommandRange): boolean;
@@ -0,0 +1,15 @@
1
+ import type { WorkPresentationContent, WorkSlide, WorkSlideAnimation, WorkSlideAnimationEffect } from '../work-types';
2
+ export interface PresentationAnimationCommands {
3
+ canMoveEntranceAnimation: (direction: -1 | 1) => boolean;
4
+ canSetEntranceAnimation: boolean;
5
+ canUpdateEntranceAnimation: boolean;
6
+ moveEntranceAnimation: (direction: -1 | 1) => boolean;
7
+ setEntranceAnimation: (effect: WorkSlideAnimationEffect | undefined) => boolean;
8
+ updateEntranceAnimation: (patch: Partial<WorkSlideAnimation>) => boolean;
9
+ }
10
+ export declare function usePresentationAnimationCommands({ content, onChange, selectedElementId, selectedSlide, }: {
11
+ content: WorkPresentationContent;
12
+ onChange: (content: WorkPresentationContent) => void;
13
+ selectedElementId: string | undefined;
14
+ selectedSlide: WorkSlide;
15
+ }): PresentationAnimationCommands;
@@ -8,4 +8,4 @@ export interface PresentationSelectionController {
8
8
  select: (elementId: string | null, additive?: boolean) => void;
9
9
  selectedElementIds: string[];
10
10
  }
11
- export declare function usePresentationSelection(elements: readonly WorkSlideElement[]): PresentationSelectionController;
11
+ export declare function usePresentationSelection(elements: readonly WorkSlideElement[], initialEditingElementId?: string | null): PresentationSelectionController;
@@ -0,0 +1,13 @@
1
+ import type { PptxGroupExportRegistry } from './work-pptx-groups';
2
+ import type { WorkSlide, WorkSlideAnimation } from './work-types';
3
+ interface PptxAnimationDiagnostic {
4
+ code: string;
5
+ message: string;
6
+ }
7
+ interface PptxAnimationReadResult {
8
+ animations: WorkSlideAnimation[];
9
+ diagnostics: PptxAnimationDiagnostic[];
10
+ }
11
+ export declare function readPptxAnimations(document: Document, elementIdByPptxShapeId: ReadonlyMap<string, string>): PptxAnimationReadResult;
12
+ export declare function patchPptxAnimations(buffer: ArrayBuffer, slides: readonly WorkSlide[], registry: PptxGroupExportRegistry): Promise<ArrayBuffer>;
13
+ export {};
@@ -7,11 +7,15 @@ interface PptxExportBinding {
7
7
  marker: string;
8
8
  }
9
9
  export declare class PptxGroupExportRegistry {
10
+ private readonly animatedElementKeys;
10
11
  private readonly bindings;
12
+ private readonly bindingsByElement;
11
13
  private readonly roleCounts;
12
14
  private markerSequence;
13
15
  get size(): number;
16
+ registerAnimatedElements(scope: string, elementIds: Iterable<string>): void;
14
17
  objectName(scope: string, element: WorkSlideElement, role: PptxExportObjectRole): string | undefined;
18
+ markerForElement(scope: string, elementId: string): string | undefined;
15
19
  binding(marker: string): PptxExportBinding | undefined;
16
20
  values(): IterableIterator<PptxExportBinding>;
17
21
  }
@@ -0,0 +1,4 @@
1
+ export declare const WORK_SLIDE_ANIMATION_LIMIT = 256;
2
+ export declare const WORK_SLIDE_ANIMATION_MIN_DURATION_MS = 100;
3
+ export declare const WORK_SLIDE_ANIMATION_MAX_DURATION_MS = 60000;
4
+ export declare const WORK_SLIDE_ANIMATION_MAX_DELAY_MS = 60000;
@@ -0,0 +1,20 @@
1
+ import type { WorkSlide, WorkSlideAnimation, WorkSlideAnimationEffect } from './work-types';
2
+ export { WORK_SLIDE_ANIMATION_LIMIT, WORK_SLIDE_ANIMATION_MAX_DELAY_MS, WORK_SLIDE_ANIMATION_MAX_DURATION_MS, WORK_SLIDE_ANIMATION_MIN_DURATION_MS, } from './work-presentation-animation-constraints';
3
+ export interface WorkSlideAnimationCueItem {
4
+ animation: WorkSlideAnimation;
5
+ endOffsetMs: number;
6
+ startOffsetMs: number;
7
+ }
8
+ export interface WorkSlideAnimationCue {
9
+ automatic: boolean;
10
+ items: WorkSlideAnimationCueItem[];
11
+ totalDurationMs: number;
12
+ }
13
+ export declare function createWorkSlideAnimation(elementId: string, effect: WorkSlideAnimationEffect, previous?: WorkSlideAnimation): WorkSlideAnimation;
14
+ export declare function normalizeWorkSlideAnimation(animation: WorkSlideAnimation): WorkSlideAnimation;
15
+ export declare function workSlideAnimationForElement(slide: WorkSlide, elementId: string | undefined): WorkSlideAnimation | undefined;
16
+ export declare function workSlideAnimationIndex(slide: WorkSlide, animationId: string | undefined): number;
17
+ export declare function workSlideAnimationCues(animations: readonly WorkSlideAnimation[] | undefined): WorkSlideAnimationCue[];
18
+ export declare function initialWorkSlideAnimationCueIndex(cues: readonly WorkSlideAnimationCue[]): number;
19
+ export declare function removeWorkSlideAnimationsForElements(slide: WorkSlide, elementIds: ReadonlySet<string>): WorkSlide;
20
+ export declare function remapWorkSlideAnimations(animations: readonly WorkSlideAnimation[] | undefined, elementIds: ReadonlyMap<string, string>): WorkSlideAnimation[] | undefined;
@@ -1,11 +1,13 @@
1
- import type { WorkSlide, WorkSlideElement } from './work-types';
1
+ import type { WorkSlide, WorkSlideAnimation, WorkSlideElement } from './work-types';
2
2
  export declare const PRESENTATION_OBJECT_OFFSET_STEP = 5;
3
3
  export type WorkPresentationClipboardPayload = {
4
4
  kind: 'element';
5
5
  element: WorkSlideElement;
6
+ animation?: WorkSlideAnimation;
6
7
  } | {
7
8
  kind: 'elements';
8
9
  elements: WorkSlideElement[];
10
+ animations?: WorkSlideAnimation[];
9
11
  } | {
10
12
  kind: 'slide';
11
13
  slide: WorkSlide;
@@ -14,13 +16,18 @@ export interface WorkPresentationClipboardRead {
14
16
  payload: WorkPresentationClipboardPayload;
15
17
  offset: number;
16
18
  }
17
- export declare function copyPresentationElement(element: WorkSlideElement): void;
18
- export declare function copyPresentationElements(elements: readonly WorkSlideElement[]): void;
19
+ export interface WorkPresentationElementPaste {
20
+ animations?: WorkSlideAnimation[];
21
+ elements: WorkSlideElement[];
22
+ }
23
+ export declare function copyPresentationElement(element: WorkSlideElement, animation?: WorkSlideAnimation): void;
24
+ export declare function copyPresentationElements(elements: readonly WorkSlideElement[], animations?: readonly WorkSlideAnimation[]): void;
19
25
  export declare function copyPresentationSlide(slide: WorkSlide): void;
20
26
  export declare function takePresentationClipboard(): WorkPresentationClipboardRead | null;
21
27
  export declare function hasPresentationClipboard(): boolean;
22
28
  export declare function clearPresentationClipboard(): void;
23
29
  export declare function clonePresentationElementForPaste(element: WorkSlideElement, offset: number): WorkSlideElement;
24
30
  export declare function clonePresentationElementsForPaste(elements: readonly WorkSlideElement[], offset: number): WorkSlideElement[];
31
+ export declare function clonePresentationElementsAndAnimationsForPaste(elements: readonly WorkSlideElement[], animations: readonly WorkSlideAnimation[], offset: number): WorkPresentationElementPaste;
25
32
  export declare function clonePresentationSlideForPaste(slide: WorkSlide, existingSlideNames?: readonly string[]): WorkSlide;
26
33
  export declare function nextPresentationSlideCopyName(sourceName: string, existingSlideNames: readonly string[]): string;
@@ -543,6 +543,22 @@ export interface WorkSlideTransition {
543
543
  advanceOnClick: boolean;
544
544
  advanceAfterMs?: number;
545
545
  }
546
+ export type WorkSlideAnimationEffect = 'appear' | 'fade' | 'fly-in' | 'zoom';
547
+ export type WorkSlideAnimationTrigger = 'on-click' | 'with-previous' | 'after-previous';
548
+ export type WorkSlideAnimationDirection = 'left' | 'right' | 'up' | 'down';
549
+ /**
550
+ * One bounded entrance animation applied to one slide-owned element.
551
+ * Array order on `WorkSlide.animations` is the canonical playback order.
552
+ */
553
+ export interface WorkSlideAnimation {
554
+ id: string;
555
+ elementId: string;
556
+ effect: WorkSlideAnimationEffect;
557
+ trigger: WorkSlideAnimationTrigger;
558
+ durationMs: number;
559
+ delayMs: number;
560
+ direction?: WorkSlideAnimationDirection;
561
+ }
546
562
  export interface WorkSlideElement {
547
563
  id: string;
548
564
  type: WorkSlideElementType;
@@ -587,6 +603,7 @@ export interface WorkSlide {
587
603
  notes?: string;
588
604
  comments?: WorkSlideComment[];
589
605
  transition?: WorkSlideTransition;
606
+ animations?: WorkSlideAnimation[];
590
607
  }
591
608
  export interface WorkSlideComment {
592
609
  id: string;
Binary file