pptx-react-viewer 1.0.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 (45) hide show
  1. package/README.md +982 -0
  2. package/dist/PowerPointViewer-K2URyPlJ.d.mts +522 -0
  3. package/dist/PowerPointViewer-K2URyPlJ.d.ts +522 -0
  4. package/dist/index.d.mts +71 -0
  5. package/dist/index.d.ts +71 -0
  6. package/dist/index.js +121771 -0
  7. package/dist/index.mjs +121737 -0
  8. package/dist/pptx-viewer.css +2 -0
  9. package/dist/viewer/index.d.mts +267 -0
  10. package/dist/viewer/index.d.ts +267 -0
  11. package/dist/viewer/index.js +121947 -0
  12. package/dist/viewer/index.mjs +121908 -0
  13. package/node_modules/emf-converter/README.md +629 -0
  14. package/node_modules/emf-converter/dist/index.d.mts +86 -0
  15. package/node_modules/emf-converter/dist/index.d.ts +86 -0
  16. package/node_modules/emf-converter/dist/index.js +4199 -0
  17. package/node_modules/emf-converter/dist/index.mjs +4195 -0
  18. package/node_modules/emf-converter/package.json +42 -0
  19. package/node_modules/mtx-decompressor/README.md +271 -0
  20. package/node_modules/mtx-decompressor/dist/index.d.mts +83 -0
  21. package/node_modules/mtx-decompressor/dist/index.d.ts +83 -0
  22. package/node_modules/mtx-decompressor/dist/index.js +1510 -0
  23. package/node_modules/mtx-decompressor/dist/index.mjs +1506 -0
  24. package/node_modules/mtx-decompressor/package.json +37 -0
  25. package/node_modules/pptx-viewer-core/README.md +1294 -0
  26. package/node_modules/pptx-viewer-core/dist/SvgExporter-BZJguJbp.d.ts +557 -0
  27. package/node_modules/pptx-viewer-core/dist/SvgExporter-DqcmwxFu.d.mts +557 -0
  28. package/node_modules/pptx-viewer-core/dist/cli/index.d.mts +150 -0
  29. package/node_modules/pptx-viewer-core/dist/cli/index.d.ts +150 -0
  30. package/node_modules/pptx-viewer-core/dist/cli/index.js +39790 -0
  31. package/node_modules/pptx-viewer-core/dist/cli/index.mjs +39757 -0
  32. package/node_modules/pptx-viewer-core/dist/converter/index.d.mts +48 -0
  33. package/node_modules/pptx-viewer-core/dist/converter/index.d.ts +48 -0
  34. package/node_modules/pptx-viewer-core/dist/converter/index.js +3676 -0
  35. package/node_modules/pptx-viewer-core/dist/converter/index.mjs +3664 -0
  36. package/node_modules/pptx-viewer-core/dist/index.d.mts +10796 -0
  37. package/node_modules/pptx-viewer-core/dist/index.d.ts +10796 -0
  38. package/node_modules/pptx-viewer-core/dist/index.js +49658 -0
  39. package/node_modules/pptx-viewer-core/dist/index.mjs +49270 -0
  40. package/node_modules/pptx-viewer-core/dist/presentation-Bo7cMMCe.d.mts +4558 -0
  41. package/node_modules/pptx-viewer-core/dist/presentation-Bo7cMMCe.d.ts +4558 -0
  42. package/node_modules/pptx-viewer-core/dist/text-operations-Bo-WG-Z8.d.mts +134 -0
  43. package/node_modules/pptx-viewer-core/dist/text-operations-D0f1jred.d.ts +134 -0
  44. package/node_modules/pptx-viewer-core/package.json +61 -0
  45. package/package.json +89 -0
package/README.md ADDED
@@ -0,0 +1,982 @@
1
+ # pptx-viewer
2
+
3
+ A full-featured **React** component for viewing, editing, and presenting PowerPoint (.pptx) files in the browser. Built on top of `pptx-viewer-core`, it provides a complete UI with toolbar, inspector panels, slide canvas, animation engine, presentation mode, real-time collaboration, and export capabilities.
4
+
5
+ ## Table of Contents
6
+
7
+ - [pptx-viewer](#pptx-viewer)
8
+ - [Table of Contents](#table-of-contents)
9
+ - [Overview](#overview)
10
+ - [Quick Start](#quick-start)
11
+ - [API Reference](#api-reference)
12
+ - [`PowerPointViewer` Component](#powerpointviewer-component)
13
+ - [`PowerPointViewerHandle` (imperative API)](#powerpointviewerhandle-imperative-api)
14
+ - [`renderToCanvas`](#rendertocanvas)
15
+ - [Styling & Theming](#styling--theming)
16
+ - [Mode 1: Tailwind CSS project](#mode-1-tailwind-css-project-no-extra-setup)
17
+ - [Mode 2: Bundled stylesheet](#mode-2-no-tailwind--use-the-bundled-stylesheet)
18
+ - [Mode 3: CSS custom properties](#mode-3-css-custom-properties-only)
19
+ - [`ViewerTheme` reference](#viewertheme-reference)
20
+ - [Theme utilities](#theme-utilities)
21
+ - [Light theme example](#light-theme-example)
22
+ - [Architecture](#architecture)
23
+ - [High-Level Component Tree](#high-level-component-tree)
24
+ - [Hook Composition](#hook-composition)
25
+ - [Data Flow](#data-flow)
26
+ - [Rendering Pipeline](#rendering-pipeline)
27
+ - [Deep Dive: How It Works](#deep-dive-how-it-works)
28
+ - [1. Component Hierarchy](#1-component-hierarchy)
29
+ - [2. State Management](#2-state-management)
30
+ - [3. Slide Canvas Rendering](#3-slide-canvas-rendering)
31
+ - [4. Element Rendering](#4-element-rendering)
32
+ - [5. Inspector Panels](#5-inspector-panels)
33
+ - [6. Presentation Mode](#6-presentation-mode)
34
+ - [7. Animation Engine](#7-animation-engine)
35
+ - [8. Chart Rendering](#8-chart-rendering)
36
+ - [9. Export System](#9-export-system)
37
+ - [10. Connector Routing](#10-connector-routing)
38
+ - [11. Real-Time Collaboration](#11-real-time-collaboration)
39
+ - [12. 3D Rendering](#12-3d-rendering)
40
+ - [Hooks Reference](#hooks-reference)
41
+ - [Utility Modules Reference](#utility-modules-reference)
42
+ - [File Structure Reference](#file-structure-reference)
43
+ - [Limitations](#limitations)
44
+
45
+ ---
46
+
47
+ ## Overview
48
+
49
+ This package provides a drop-in React component that turns raw `.pptx` bytes into a fully interactive PowerPoint experience. The viewer renders slides using **CSS-based layout** (not Canvas) for sharp text, accessibility, and DOM interactivity.
50
+
51
+ | Feature | Description |
52
+ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
53
+ | **View** | Render slides with 16 element types: shapes, text, images, tables, 23 chart types, SmartArt, connectors, media, ink, OLE, 3D models, zoom |
54
+ | **Edit** | Insert/move/resize/delete elements, edit text inline, modify styles, manage slides |
55
+ | **Present** | Fullscreen slideshow with 40+ animations, 42 transitions (including morph), speaker notes, presenter view with timer |
56
+ | **Export** | PNG/JPEG/SVG/PDF/GIF/video slide export, save-as PPTX |
57
+ | **Collaborate** | Real-time multi-user editing via Yjs CRDT with presence tracking, remote cursors, and user avatars |
58
+ | **Print** | Print dialog with handout layouts and notes page formatting with overflow pagination |
59
+ | **Annotate** | Pen/highlighter/laser pointer tools during presentations |
60
+ | **Compare** | Side-by-side slide diff comparison |
61
+ | **Find & Replace** | Cross-slide text search with regex support |
62
+ | **Accessibility** | Keyboard navigation, alt-text audit panel, screen reader support |
63
+ | **3D** | GLB/GLTF model rendering via Three.js, 3D surface charts, CSS 3D shape/text extrusion |
64
+
65
+ **Peer dependencies:** React 19, framer-motion, html2canvas, lucide-react, react-icons, jspdf, jszip, fast-xml-parser, i18next/react-i18next.
66
+
67
+ **Optional dependencies:** three, @react-three/fiber, @react-three/drei (3D models/charts), yjs, y-websocket (collaboration).
68
+
69
+ ---
70
+
71
+ ## Quick Start
72
+
73
+ ```tsx
74
+ import { PowerPointViewer } from 'pptx-viewer';
75
+ import type { PowerPointViewerHandle } from 'pptx-viewer';
76
+ import { useRef, useEffect, useState } from 'react';
77
+
78
+ // If your project does NOT use Tailwind CSS, import the bundled stylesheet:
79
+ import 'pptx-viewer/styles';
80
+
81
+ function App() {
82
+ const viewerRef = useRef<PowerPointViewerHandle>(null);
83
+ const [content, setContent] = useState<ArrayBuffer | null>(null);
84
+
85
+ useEffect(() => {
86
+ fetch('presentation.pptx')
87
+ .then((r) => r.arrayBuffer())
88
+ .then(setContent);
89
+ }, []);
90
+
91
+ const handleSave = async () => {
92
+ if (viewerRef.current) {
93
+ const bytes = await viewerRef.current.getContent();
94
+ // Save bytes to file...
95
+ }
96
+ };
97
+
98
+ if (!content) return <div>Loading...</div>;
99
+
100
+ return (
101
+ <div style={{ height: '100vh' }}>
102
+ <PowerPointViewer
103
+ ref={viewerRef}
104
+ content={content}
105
+ canEdit={true}
106
+ onContentChange={(dirty) => console.log('Dirty:', dirty)}
107
+ onDirtyChange={(isDirty) => console.log('Is dirty:', isDirty)}
108
+ onActiveSlideChange={(index) => console.log('Slide:', index)}
109
+ />
110
+ </div>
111
+ );
112
+ }
113
+ ```
114
+
115
+ The component fills its parent container. Make sure the parent has a defined height.
116
+
117
+ ---
118
+
119
+ ## API Reference
120
+
121
+ ### `PowerPointViewer` Component
122
+
123
+ The main React component. Uses `forwardRef` to expose an imperative handle.
124
+
125
+ **Props (`PowerPointViewerProps`):**
126
+
127
+ | Prop | Type | Default | Description |
128
+ | --------------------- | ----------------------------------- | -------- | ----------------------------------------------------------------- |
129
+ | `content` | `ArrayBuffer \| Uint8Array \| null` | required | Raw .pptx file bytes |
130
+ | `filePath` | `string` | -- | Optional file path (for display and autosave) |
131
+ | `canEdit` | `boolean` | `false` | Enable editing mode |
132
+ | `onContentChange` | `(dirty: boolean) => void` | -- | Called when content changes |
133
+ | `onDirtyChange` | `(isDirty: boolean) => void` | -- | Called when dirty state changes |
134
+ | `onActiveSlideChange` | `(index: number) => void` | -- | Called when active slide changes |
135
+ | `theme` | `ViewerTheme` | -- | Theme configuration for customising colours, radius, and CSS vars |
136
+
137
+ ### `PowerPointViewerHandle` (imperative API)
138
+
139
+ Exposed via `ref`. Extends `FileViewerHandle`.
140
+
141
+ | Method | Signature | Description |
142
+ | ------------ | ------------------------------------- | -------------------------------------- |
143
+ | `getContent` | `() => Promise<string \| Uint8Array>` | Serialise current state to .pptx bytes |
144
+
145
+ ### `renderToCanvas`
146
+
147
+ Standalone utility for rendering a DOM element to a Canvas with oklch colour space workaround.
148
+
149
+ ```typescript
150
+ import { renderToCanvas } from 'pptx-viewer';
151
+
152
+ const canvas = await renderToCanvas(element, options);
153
+ // => HTMLCanvasElement with the rendered content
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Styling & Theming
159
+
160
+ The viewer's UI is built with utility CSS classes that reference **CSS custom properties** for all visual tokens (colours, border-radius, etc.). This means it works in three modes:
161
+
162
+ ### Mode 1: Tailwind CSS project (no extra setup)
163
+
164
+ If your project already uses **Tailwind CSS v4** with semantic colour tokens (the shadcn/ui convention), the viewer classes will resolve through your existing Tailwind configuration. No additional CSS import is needed.
165
+
166
+ If you want to override specific values, pass a `theme` prop:
167
+
168
+ ```tsx
169
+ <PowerPointViewer
170
+ content={bytes}
171
+ theme={{
172
+ colors: { primary: '#6366f1', background: '#0f172a' },
173
+ }}
174
+ />
175
+ ```
176
+
177
+ ### Mode 2: No Tailwind -- use the bundled stylesheet
178
+
179
+ Import the self-contained CSS file that ships with the package. It includes all the utility classes the viewer needs plus sensible dark-theme defaults:
180
+
181
+ ```tsx
182
+ // Import once at your app's entry point
183
+ import 'pptx-viewer/styles';
184
+ // or: import "pptx-viewer/styles.css";
185
+ ```
186
+
187
+ Then optionally customise with the `theme` prop or by setting CSS custom properties in your own stylesheet.
188
+
189
+ ### Mode 3: CSS custom properties only
190
+
191
+ If you want full control, define the `--pptx-*` custom properties yourself and skip both the bundled CSS and the `theme` prop:
192
+
193
+ ```css
194
+ :root {
195
+ --pptx-background: #0f172a;
196
+ --pptx-foreground: #f8fafc;
197
+ --pptx-primary: #6366f1;
198
+ --pptx-primary-foreground: #ffffff;
199
+ --pptx-muted: #1e293b;
200
+ --pptx-muted-foreground: #94a3b8;
201
+ --pptx-accent: #1e293b;
202
+ --pptx-accent-foreground: #f8fafc;
203
+ --pptx-card: #1e293b;
204
+ --pptx-card-foreground: #f8fafc;
205
+ --pptx-popover: #1e293b;
206
+ --pptx-popover-foreground: #f8fafc;
207
+ --pptx-border: #334155;
208
+ --pptx-destructive: #ef4444;
209
+ --pptx-destructive-foreground: #ffffff;
210
+ --pptx-input: #334155;
211
+ --pptx-ring: #6366f1;
212
+ --pptx-radius: 0.5rem;
213
+ }
214
+ ```
215
+
216
+ ### `ViewerTheme` reference
217
+
218
+ ```typescript
219
+ import type { ViewerTheme } from 'pptx-viewer';
220
+
221
+ const myTheme: ViewerTheme = {
222
+ colors: {
223
+ // All properties are optional -- only override what you need.
224
+ background: '#0f172a', // Page / root background
225
+ foreground: '#f8fafc', // Default text colour
226
+ card: '#1e293b', // Card / panel surface
227
+ cardForeground: '#f8fafc', // Text on card surfaces
228
+ popover: '#1e293b', // Popover / dropdown surface
229
+ popoverForeground: '#f8fafc', // Text inside popovers
230
+ primary: '#6366f1', // Primary action colour
231
+ primaryForeground: '#ffffff', // Text on primary backgrounds
232
+ secondary: '#334155', // Secondary action colour
233
+ secondaryForeground: '#f8fafc',
234
+ muted: '#1e293b', // Muted / disabled surface
235
+ mutedForeground: '#94a3b8', // Secondary text colour
236
+ accent: '#1e293b', // Hover-highlight surface
237
+ accentForeground: '#f8fafc', // Text on accent surfaces
238
+ destructive: '#ef4444', // Danger / delete colour
239
+ destructiveForeground: '#ffffff',
240
+ border: '#334155', // Default border colour
241
+ input: '#334155', // Input field border
242
+ ring: '#6366f1', // Focus ring colour
243
+ },
244
+ radius: '0.5rem', // Base border-radius
245
+
246
+ // Escape hatch for arbitrary CSS custom properties
247
+ cssVars: {
248
+ '--my-custom-shadow': '0 4px 12px rgba(0,0,0,0.5)',
249
+ },
250
+ };
251
+ ```
252
+
253
+ ### Theme utilities
254
+
255
+ ```typescript
256
+ import {
257
+ defaultThemeColors, // Full set of default colour values
258
+ defaultRadius, // Default border-radius ("0.5rem")
259
+ themeToCssVars, // Convert a ViewerTheme -> Record<string, string> of CSS vars
260
+ defaultCssVars, // Get all default --pptx-* CSS vars
261
+ ViewerThemeProvider, // React context provider (advanced)
262
+ useViewerTheme, // Hook to read current theme from context
263
+ } from 'pptx-viewer';
264
+ ```
265
+
266
+ ### Light theme example
267
+
268
+ ```tsx
269
+ <PowerPointViewer
270
+ content={bytes}
271
+ theme={{
272
+ colors: {
273
+ background: '#ffffff',
274
+ foreground: '#0f172a',
275
+ card: '#f8fafc',
276
+ cardForeground: '#0f172a',
277
+ popover: '#ffffff',
278
+ popoverForeground: '#0f172a',
279
+ primary: '#4f46e5',
280
+ primaryForeground: '#ffffff',
281
+ muted: '#f1f5f9',
282
+ mutedForeground: '#64748b',
283
+ accent: '#f1f5f9',
284
+ accentForeground: '#0f172a',
285
+ border: '#e2e8f0',
286
+ destructive: '#dc2626',
287
+ destructiveForeground: '#ffffff',
288
+ },
289
+ }}
290
+ />
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Architecture
296
+
297
+ ### High-Level Component Tree
298
+
299
+ ```mermaid
300
+ flowchart TB
301
+ PPV["PowerPointViewer<br/>(root orchestrator)"]
302
+
303
+ PPV --> VTS["ViewerToolbarSection<br/>Toolbar + ModeSwitcher"]
304
+ PPV --> VMC["ViewerMainContent<br/>Canvas + sidebars + inspector"]
305
+ PPV --> VBP["ViewerBottomPanels<br/>Notes + status bar"]
306
+ PPV --> VDG["ViewerDialogGroup<br/>All modal dialogs"]
307
+ PPV --> VO["ViewerOverlays<br/>Shortcuts, accessibility, slide sorter"]
308
+ PPV --> VPL["ViewerPresentationLayer<br/>Fullscreen slideshow"]
309
+
310
+ VMC --> VSP["ViewerSidePanels<br/>Slides pane + master pane"]
311
+ VMC --> VCA["ViewerCanvasArea<br/>SlideCanvas + overlays"]
312
+ VMC --> VI["ViewerInspector<br/>Properties panel"]
313
+
314
+ VCA --> SC["SlideCanvas<br/>Main slide rendering"]
315
+ SC --> ER["ElementRenderer<br/>Per-element dispatch"]
316
+ ER --> SH["Shape / Text"]
317
+ ER --> IM["Image"]
318
+ ER --> TB["Table"]
319
+ ER --> CH["Chart (SVG)"]
320
+ ER --> CN["Connector"]
321
+ ER --> SA["SmartArt"]
322
+ ER --> M3["3D Model"]
323
+ ER --> MD["Media (audio/video)"]
324
+ ER --> IK["Ink"]
325
+ ```
326
+
327
+ ### Hook Composition
328
+
329
+ The viewer's logic is decomposed into 67+ custom hooks, composed in `PowerPointViewer.tsx`:
330
+
331
+ ```mermaid
332
+ flowchart TD
333
+ subgraph "Core State"
334
+ VS["useViewerState<br/>All mutable state"]
335
+ VCS["useViewerCoreState<br/>Slides, selection, canvas"]
336
+ VUI["useViewerUIState<br/>Panels, dialogs, UI flags"]
337
+ end
338
+
339
+ subgraph "Derived State"
340
+ DSS["useDerivedSlideState<br/>Visible indexes, sections"]
341
+ DES["useDerivedElementState<br/>Selected element computed props"]
342
+ end
343
+
344
+ subgraph "Core Operations"
345
+ EH["useEditorHistory<br/>Undo/redo snapshot stack"]
346
+ ZV["useZoomViewport<br/>Zoom level + viewport"]
347
+ EO["useEditorOperations<br/>Compose all editor ops"]
348
+ end
349
+
350
+ subgraph "Feature Hooks"
351
+ LC["useLoadContent<br/>Parse PPTX on mount"]
352
+ PM["usePresentationMode<br/>Slideshow navigation"]
353
+ PA["usePresentationAnnotations<br/>Pen/highlighter tools"]
354
+ IE["useInsertElements<br/>Shape/image/table insertion"]
355
+ EM["useElementManipulation<br/>Move/resize/delete"]
356
+ PH["usePointerHandlers<br/>Mouse/touch events"]
357
+ KS["useKeyboardShortcuts<br/>Hotkey bindings"]
358
+ EX["useExportHandlers<br/>PNG/SVG/PDF/video export"]
359
+ PR["usePrintHandlers<br/>Print dialog"]
360
+ SM["useSlideManagement<br/>Add/delete/reorder slides"]
361
+ TO["useTableOperations<br/>Row/column/cell ops"]
362
+ FR["useFindReplace<br/>Text search"]
363
+ CM["useComments<br/>Comment management"]
364
+ end
365
+
366
+ subgraph "Collaboration"
367
+ YJS["useYjsProvider<br/>WebSocket lifecycle"]
368
+ PT["usePresenceTracking<br/>Remote cursors"]
369
+ CS["useCollaborativeState<br/>CRDT shared state"]
370
+ CH2["useCollaborativeHistory<br/>Collab undo/redo"]
371
+ end
372
+
373
+ VS --> VCS
374
+ VS --> VUI
375
+ VCS --> DSS
376
+ VS --> EH
377
+ VS --> ZV
378
+ EH --> EO
379
+ ZV --> EO
380
+ EO --> IE
381
+ EO --> EM
382
+ EO --> PH
383
+ EO --> SM
384
+ EO --> TO
385
+ EO --> FR
386
+ EO --> CM
387
+ ```
388
+
389
+ ### Data Flow
390
+
391
+ ```mermaid
392
+ sequenceDiagram
393
+ participant P as Parent App
394
+ participant V as PowerPointViewer
395
+ participant H as PptxHandler (core)
396
+ participant S as State (hooks)
397
+ participant C as SlideCanvas
398
+
399
+ P->>V: content={arrayBuffer}
400
+ V->>S: useViewerState({ content })
401
+ S->>H: handler.load(buffer)
402
+ H-->>S: PptxData { slides, theme, ... }
403
+ S-->>V: { slides, activeSlide, canvasSize, ... }
404
+ V->>C: Render active slide
405
+ C->>C: Map elements -> React components
406
+
407
+ Note over C: User edits element
408
+ C->>S: setState(updatedSlides)
409
+ S->>S: Push undo snapshot
410
+ S-->>V: Re-render with updated state
411
+
412
+ Note over V: User saves
413
+ V->>H: handler.save(slides)
414
+ H-->>P: Uint8Array via onContentChange
415
+ ```
416
+
417
+ ### Rendering Pipeline
418
+
419
+ Slides are rendered using **CSS positioning and transforms**, not HTML Canvas. This enables:
420
+
421
+ - Crisp text rendering at any zoom level
422
+ - Native browser text selection and accessibility
423
+ - DOM-based interaction (click, drag, resize)
424
+ - Standard CSS effects (shadows, gradients, borders)
425
+
426
+ ```mermaid
427
+ flowchart LR
428
+ subgraph "Data Model"
429
+ E["PptxElement<br/>(from core)"]
430
+ end
431
+
432
+ subgraph "React Components"
433
+ ER["ElementRenderer<br/>Type dispatch"]
434
+ EB["ElementBody<br/>Visual rendering"]
435
+ RH["ResizeHandles<br/>Selection UI"]
436
+ end
437
+
438
+ subgraph "CSS Output"
439
+ POS["position: absolute<br/>left/top/width/height"]
440
+ ROT["transform: rotate()"]
441
+ FIL["background: fill style"]
442
+ BOR["border: stroke style"]
443
+ SHD["box-shadow: effects"]
444
+ TXT["text styling (font, color, align)"]
445
+ end
446
+
447
+ E --> ER
448
+ ER --> EB
449
+ ER --> RH
450
+ EB --> POS
451
+ EB --> ROT
452
+ EB --> FIL
453
+ EB --> BOR
454
+ EB --> SHD
455
+ EB --> TXT
456
+ ```
457
+
458
+ ---
459
+
460
+ ## Deep Dive: How It Works
461
+
462
+ ### 1. Component Hierarchy
463
+
464
+ The component tree is split into six main sections, each rendered conditionally based on the current `ViewerMode`:
465
+
466
+ | Component | Visible In | Purpose |
467
+ | ------------------------- | --------------------- | -------------------------------------------------------- |
468
+ | `ViewerToolbarSection` | edit, preview, master | Toolbar with formatting, insert, view controls |
469
+ | `ViewerMainContent` | all modes | Central area: slides pane + canvas + inspector |
470
+ | `ViewerBottomPanels` | edit, preview, master | Speaker notes editor + status bar |
471
+ | `ViewerDialogGroup` | any (modal) | All dialogs: properties, export, print, signatures, etc. |
472
+ | `ViewerOverlays` | any (overlay) | Keyboard shortcuts, accessibility audit, slide sorter |
473
+ | `ViewerPresentationLayer` | present | Fullscreen slideshow with transition/animation engine |
474
+
475
+ **Component counts by directory:**
476
+
477
+ | Directory | Files | Purpose |
478
+ | --------------------------- | ----- | ------------------------------------------- |
479
+ | `components/` (root) | ~80 | Core UI components |
480
+ | `components/inspector/` | 84 | Property inspector panels |
481
+ | `components/toolbar/` | 17 | Toolbar sections and controls |
482
+ | `components/canvas/` | 14 | Canvas overlays, rulers, grids |
483
+ | `components/elements/` | 12 | Element-specific renderers |
484
+ | `components/collaboration/` | 7 | Collaboration UI (cursors, avatars, status) |
485
+ | `components/slides-pane/` | 7 | Slide thumbnail sidebar |
486
+ | `components/slide-sorter/` | 7 | Drag-and-drop slide reordering |
487
+ | `components/notes/` | 6 | Notes editing toolbar and utils |
488
+ | `components/print/` | 5 | Print preview and layout |
489
+
490
+ ### 2. State Management
491
+
492
+ All state lives in React hooks -- no external state library. The state is split across two layers:
493
+
494
+ **`useViewerCoreState`** -- Document-level state:
495
+
496
+ - `slides` -- The slide array (source of truth)
497
+ - `activeSlideIndex` -- Currently selected slide
498
+ - `selectedElementId` / `selectedElementIds` -- Selection
499
+ - `canvasSize` -- Slide dimensions (width x height in px)
500
+ - `mode` -- Current viewer mode (`edit` | `preview` | `present` | `master`)
501
+ - `templateElementsBySlideId` -- Layout/master elements per slide
502
+ - Refs for drag/resize/marquee interaction state
503
+
504
+ **`useViewerUIState`** -- UI-level state:
505
+
506
+ - Panel visibility (slides pane, notes, inspector, accessibility)
507
+ - Dialog open/close flags
508
+ - Toolbar state (draw mode, format painter, eyedropper)
509
+ - Find/replace state
510
+ - Custom shows, sections, guides
511
+
512
+ **`useEditorHistory`** -- Undo/redo:
513
+
514
+ - Maintains a snapshot stack of `{ slides, canvasSize, activeSlideIndex, ... }`
515
+ - Defers snapshots during pointer interactions (drag, resize)
516
+ - Triggered by a `pointerCommitNonce` that increments when an interaction ends
517
+
518
+ ### 3. Slide Canvas Rendering
519
+
520
+ `SlideCanvas` renders the active slide as a scaled, positioned `div`:
521
+
522
+ ```
523
+ +---------------------------------------------+
524
+ | Canvas Container (scrollable viewport) |
525
+ | +-----------------------------------+ |
526
+ | | Slide Div (scaled via transform) | |
527
+ | | +-----------------------------+ | |
528
+ | | | Background (gradient/image) | | |
529
+ | | +-----------------------------+ | |
530
+ | | | Template elements (layout) | | |
531
+ | | +-----------------------------+ | |
532
+ | | | Slide elements | | |
533
+ | | | ElementRenderer xN | | |
534
+ | | +-----------------------------+ | |
535
+ | | | Canvas Overlays: | | |
536
+ | | | - Grid | | |
537
+ | | | - Rulers | | |
538
+ | | | - Drawing overlay (SVG) | | |
539
+ | | | - Connector overlay | | |
540
+ | | | - Comment markers | | |
541
+ | | | - Selection marquee | | |
542
+ | | | - Collaboration cursors | | |
543
+ | | +-----------------------------+ | |
544
+ | +-----------------------------------+ |
545
+ +---------------------------------------------+
546
+ ```
547
+
548
+ **Zoom** is applied via CSS `transform: scale(zoom)` on the slide div, keeping the DOM structure intact for interaction hit-testing.
549
+
550
+ ### 4. Element Rendering
551
+
552
+ `ElementRenderer` dispatches to specialised renderers based on element type:
553
+
554
+ | Element Type | Renderer | Technique |
555
+ | --------------------- | --------------------------- | -------------------------------------------------------------------- |
556
+ | `shape` | `ElementBody` + text layout | CSS positioning + HTML text spans |
557
+ | `text` | `ElementBody` + text layout | CSS positioning + HTML text spans |
558
+ | `image` / `picture` | `ImageRenderer` | `<img>` with CSS clip-path, artistic effects (23 filters), and fills |
559
+ | `table` | `table-render.tsx` | HTML `<table>` with cell styling |
560
+ | `chart` | `chart.tsx` -> SVG | Custom SVG rendering (23 chart types) |
561
+ | `connector` | `ConnectorElementRenderer` | SVG `<path>` with marker arrows |
562
+ | `smartArt` | `SmartArtRenderer` | Decomposed shapes with layout-specific positioning (13 layouts) |
563
+ | `model3d` | `Model3DRenderer` | Three.js GLB/GLTF rendering via @react-three/fiber |
564
+ | `group` | Recursive `ElementRenderer` | Nested div with group transform |
565
+ | `media` | `media.tsx` | `<video>` / `<audio>` with custom controls |
566
+ | `ink` / `contentPart` | `InkGroupRenderers` | SVG `<polyline>` strokes with pressure-based width |
567
+ | `ole` | `ElementBody` (fallback) | Placeholder with OLE type label and preview image |
568
+ | `zoom` | `ImageRenderer` | Live slide thumbnail with click navigation |
569
+
570
+ **Shape visual rendering** (`shape-visual.tsx`, `shape-visual-style.ts`, `shape-visual-effects.ts`):
571
+
572
+ - Gradient fills -> CSS `linear-gradient` / `radial-gradient`
573
+ - Pattern fills -> 48 pattern presets as repeating CSS background patterns
574
+ - Image fills -> `background-image` with stretch/tile modes
575
+ - Shadows -> CSS `box-shadow` or `filter: drop-shadow()`
576
+ - 3D effects -> CSS `perspective` + `transform3d` for shape and text extrusion
577
+ - Text warp -> SVG `<textPath>` for curved text effects (24+ presets)
578
+ - Artistic effects -> 23 image filters via CSS and SVG filter primitives
579
+
580
+ ### 5. Inspector Panels
581
+
582
+ The right-side inspector (`InspectorPane`) displays contextual property editors:
583
+
584
+ | Panel | Shown When | Controls |
585
+ | ------------------------- | ------------------------ | -------------------------------------------------- |
586
+ | `SlideProperties` | No element selected | Background, layout, size |
587
+ | `ElementProperties` | Element selected | Position, size, rotation |
588
+ | `FillStrokeProperties` | Shape/connector selected | Fill type, colour, gradient, stroke |
589
+ | `TextProperties` | Text element selected | Font, size, colour, alignment, spacing |
590
+ | `ImagePropertiesPanel` | Image selected | Crop, effects, 23 artistic filters |
591
+ | `TablePropertiesPanel` | Table selected | Cell formatting, borders, band styling |
592
+ | `ChartDataPanel` | Chart selected | Series data grid, chart type selector |
593
+ | `SmartArtPropertiesPanel` | SmartArt selected | Node editing, layout switching |
594
+ | `MediaPropertiesPanel` | Media selected | Playback settings, trim, bookmarks |
595
+ | `AnimationPanel` | Any element | Animation timeline, presets, drag-and-drop reorder |
596
+ | `SlideTransitionSection` | Slide level | Transition type, duration, advance mode |
597
+ | `ConnectorArrowsSection` | Connector selected | Arrow head/tail type and size |
598
+ | `ThemeEditorPanel` | Theme editing | Colour scheme, font scheme, presets |
599
+
600
+ ### 6. Presentation Mode
601
+
602
+ Activated by setting `mode` to `"present"`. The `ViewerPresentationLayer` takes over with:
603
+
604
+ ```mermaid
605
+ flowchart TD
606
+ PM["usePresentationMode"] --> SN["useSlideNavigation<br/>Next/prev/goto slide"]
607
+ PM --> AP["useAnimationPlayback<br/>Trigger animations in sequence"]
608
+ PM --> PK["usePresentationKeyboard<br/>Arrow keys, Esc, N-key toggle"]
609
+ PM --> RT["useRehearsalTimings<br/>Practice mode with timer"]
610
+
611
+ subgraph "Rendering"
612
+ ST["Slide Transition<br/>(CSS + framer-motion)"]
613
+ AN["Animation Overlays<br/>(keyframe sequences)"]
614
+ AO["Annotation Overlay<br/>(pen/highlighter SVG)"]
615
+ PV["Presenter View<br/>(dual-screen notes + preview + timer)"]
616
+ TB2["Slideshow Toolbar<br/>(auto-hide on mouse idle)"]
617
+ end
618
+
619
+ SN --> ST
620
+ AP --> AN
621
+ PM --> AO
622
+ PM --> PV
623
+ PM --> TB2
624
+ ```
625
+
626
+ **Slide transitions** (`slide-transitions.ts`, `transition-keyframes.ts`):
627
+
628
+ - 42 transition types matching PowerPoint's built-in transitions
629
+ - CSS `@keyframes` for fade, push, wipe, split, reveal, etc.
630
+ - p14 extension transitions (vortex, ripple, shred, etc.)
631
+ - Morph transitions computed from element ID matching
632
+
633
+ **Presenter view** includes speaker notes display, next slide preview, current/elapsed timer, and N-key toggle for notes visibility.
634
+
635
+ ### 7. Animation Engine
636
+
637
+ The animation system (`viewer/utils/animation*.ts`, ~14 files) processes OOXML timing trees:
638
+
639
+ ```mermaid
640
+ flowchart LR
641
+ A["PptxElementAnimation<br/>(from core)"] --> B["animation-timeline.ts<br/>Build timeline"]
642
+ B --> C["animation-sequencer.ts<br/>Resolve triggers:<br/>onClick, afterPrevious,<br/>withPrevious"]
643
+ C --> D["animation-keyframes.ts<br/>Generate CSS @keyframes"]
644
+ D --> E["animation-effects.ts<br/>Apply to DOM elements"]
645
+
646
+ subgraph "Effect Types"
647
+ F["Entrance<br/>(appear, fly in, fade, zoom)"]
648
+ G["Emphasis<br/>(pulse, spin, grow/shrink, color)"]
649
+ H["Exit<br/>(disappear, fly out, fade)"]
650
+ I["Motion Path<br/>(custom path with auto-rotation)"]
651
+ end
652
+
653
+ D --> F
654
+ D --> G
655
+ D --> H
656
+ D --> I
657
+ ```
658
+
659
+ Supports 40+ animation presets with configurable duration, delay, repeat, color animations, motion path auto-rotation, and text-build options (by word, by letter, by paragraph).
660
+
661
+ ### 8. Chart Rendering
662
+
663
+ Charts are rendered as custom SVG using React components (`viewer/utils/chart*.tsx`, ~20 files):
664
+
665
+ | Chart Type | File |
666
+ | ---------------------- | --------------------------- |
667
+ | Bar / Column | `chart-bar.tsx` |
668
+ | Stacked Bar | `chart-stacked-bar.tsx` |
669
+ | Line / Area | `chart-area-line.tsx` |
670
+ | Pie / Doughnut | `chart-pie.tsx` |
671
+ | Scatter / Bubble | `chart-scatter-bubble.tsx` |
672
+ | Radar | `chart-radar.tsx` |
673
+ | Stock (OHLC) | `chart-stock.tsx` |
674
+ | Waterfall / Combo | `chart-waterfall-combo.tsx` |
675
+ | Surface / Treemap | `chart-surface-treemap.tsx` |
676
+ | Sunburst / Funnel | `chart-sunburst-funnel.tsx` |
677
+ | Histogram / BoxWhisker | `chart-map.tsx` |
678
+ | Trendlines | `chart-trendlines.tsx` |
679
+
680
+ Chart chrome (axes, legends, titles, gridlines, data labels, data tables, display units) is rendered by `chart-chrome.tsx` and `chart-data-table.tsx`. Logarithmic axes and chart color styles are fully supported.
681
+
682
+ 3D surface charts are rendered using Three.js via `@react-three/fiber`.
683
+
684
+ ### 9. Export System
685
+
686
+ The export pipeline (`viewer/utils/export*.ts`, `viewer/hooks/useExportHandlers.ts`):
687
+
688
+ ```mermaid
689
+ flowchart TD
690
+ A["Export Request"] --> B{Format?}
691
+
692
+ B -->|PNG/JPEG| C["renderToCanvas (html2canvas)<br/>-> canvas.toDataURL()"]
693
+ B -->|SVG| D["DOM -> SVG serialisation<br/>(export-svg.ts)"]
694
+ B -->|PDF| E["jspdf + renderToCanvas<br/>-> multi-page PDF<br/>(with notes pages + overflow)"]
695
+ B -->|GIF| F["export-gif-encoder.ts<br/>-> animated GIF frames"]
696
+ B -->|Video| G["export-video.ts<br/>-> MediaRecorder API"]
697
+ B -->|PPTX| H["PptxHandler.save()<br/>-> Uint8Array download"]
698
+ B -->|Slides| I["PptxHandler.exportSlides()<br/>-> per-slide PPTX files"]
699
+
700
+ C --> J["Download / Blob URL"]
701
+ D --> J
702
+ E --> J
703
+ F --> J
704
+ G --> J
705
+ H --> J
706
+ I --> J
707
+ ```
708
+
709
+ The `renderToCanvas` wrapper (`lib/canvas-export.ts`) patches `html2canvas` to work around oklch colour space parsing issues in browsers that don't fully support it.
710
+
711
+ ### 10. Connector Routing
712
+
713
+ Connectors between shapes use a graph-based routing algorithm:
714
+
715
+ ```mermaid
716
+ flowchart LR
717
+ A["Start Shape<br/>(connection point)"] --> B["connector-router.ts<br/>A* pathfinding"]
718
+ B --> C["connector-router-graph.ts<br/>Build obstacle grid"]
719
+ C --> D["connector-router-astar.ts<br/>Find shortest path"]
720
+ D --> E["connector-path.tsx<br/>SVG path rendering"]
721
+ E --> F["Arrow markers<br/>(start/end heads)"]
722
+ ```
723
+
724
+ The router avoids overlapping shapes by building an obstacle grid and using A\* pathfinding with Manhattan distance heuristics. Supports straight, elbow (bent), and curved connector types.
725
+
726
+ ### 11. Real-Time Collaboration
727
+
728
+ The collaboration system uses **Yjs** (CRDT) with WebSocket transport for multi-user editing:
729
+
730
+ | Component / Hook | Purpose |
731
+ | ------------------------------ | --------------------------------------------------------------- |
732
+ | `useYjsProvider` | Manages WebSocket connection lifecycle to a y-websocket server |
733
+ | `usePresenceTracking` | Tracks user cursor positions, selections, and connection status |
734
+ | `useCollaborativeState` | Synchronizes document state via Yjs shared types |
735
+ | `useCollaborativeHistory` | Provides collaborative undo/redo with operation transforms |
736
+ | `CollaborationProvider` | React context provider for collaboration state |
737
+ | `CollaborationCursorOverlay` | Renders remote user cursors on the slide canvas |
738
+ | `RemoteUserCursors` | Individual cursor component with user name label |
739
+ | `UserAvatarBar` | Displays connected users with colour-coded avatars |
740
+ | `CollaborationStatusIndicator` | Shows connection status (connected/disconnected/syncing) |
741
+
742
+ The collaboration hooks include input sanitization (`sanitize.ts`) for room IDs, user names, cursor positions, and presence data.
743
+
744
+ Yjs and y-websocket are **optional dependencies** -- the viewer works fully without them in single-user mode.
745
+
746
+ ### 12. 3D Rendering
747
+
748
+ The viewer supports two types of 3D content:
749
+
750
+ **3D Models** (`Model3DRenderer.tsx`):
751
+
752
+ - Renders GLB/GLTF models embedded in PowerPoint 365+ presentations
753
+ - Uses Three.js via `@react-three/fiber` and `@react-three/drei`
754
+ - Falls back to poster/preview image when Three.js is not available
755
+ - Optional dependency -- requires `three`, `@react-three/fiber`, `@react-three/drei`
756
+
757
+ **3D Surface Charts**:
758
+
759
+ - Rendered using Three.js for perspective-correct 3D wireframe/surface visualization
760
+ - Supports rotation and lighting
761
+
762
+ **3D Shape/Text Extrusion**:
763
+
764
+ - CSS 3D transforms (`perspective`, `transform3d`) for shape and text extrusion effects
765
+ - Implemented in `shape-visual-3d.ts`
766
+
767
+ ---
768
+
769
+ ## Hooks Reference
770
+
771
+ | Hook | Purpose |
772
+ | ---------------------------- | -------------------------------------------------------------- |
773
+ | `useViewerState` | All mutable viewer state (composes core + UI state) |
774
+ | `useViewerCoreState` | Document state: slides, selection, canvas size, mode |
775
+ | `useViewerUIState` | UI state: panel visibility, toolbar flags |
776
+ | `useEditorHistory` | Undo/redo snapshot stack with deferred capture |
777
+ | `useZoomViewport` | Zoom level, fit-to-width, viewport DOM ref |
778
+ | `useDerivedSlideState` | Computed: visible indexes, section groups, master pseudo-slide |
779
+ | `useDerivedElementState` | Computed: selected element properties |
780
+ | `useLoadContent` | Parse PPTX buffer on mount via PptxHandler |
781
+ | `useContentLifecycle` | Content sync, dirty tracking, recovery detection |
782
+ | `usePresentationMode` | Slideshow navigation, animation, transitions |
783
+ | `usePresentationSetup` | Compose presentation mode + annotations |
784
+ | `usePresentationAnnotations` | Pen/highlighter/laser/eraser tools |
785
+ | `useEditorOperations` | Compose all editor operations into one result |
786
+ | `useViewerIntegration` | Compose I/O, export, print, pointers, lifecycle |
787
+ | `useViewerDialogs` | Dialog open/close state management |
788
+ | `useElementManipulation` | Move, resize, rotate, delete elements |
789
+ | `useElementOperations` | Element property updates |
790
+ | `useInsertElements` | Shape, image, text box, table, chart insertion |
791
+ | `useSlideManagement` | Add, delete, duplicate, reorder, hide slides |
792
+ | `useSectionOperations` | Section add/rename/delete/reorder |
793
+ | `useTableOperations` | Insert/delete rows & columns, merge/split cells |
794
+ | `usePointerHandlers` | Mouse/touch event processing for canvas |
795
+ | `useCanvasInteractions` | Canvas-level interactions (pan, zoom, marquee) |
796
+ | `useKeyboardShortcuts` | Hotkey definitions |
797
+ | `useKeyboardShortcutWiring` | Bind shortcuts to handler functions |
798
+ | `useClipboardHandlers` | Cut/copy/paste via Clipboard API |
799
+ | `useGroupAlignLayerHandlers` | Group/ungroup, align, distribute, z-order |
800
+ | `useFindReplace` | Text search across all slides |
801
+ | `useComments` | Comment CRUD and threading |
802
+ | `useExportHandlers` | PNG/SVG/PDF/PPTX/GIF/video export |
803
+ | `usePrintHandlers` | Print dialog and layout |
804
+ | `useThemeHandlers` | Theme application and editing |
805
+ | `usePropertyHandlers` | Document property updates |
806
+ | `useIOHandlers` | File open/save operations |
807
+ | `useSerialize` | Serialise current state to .pptx bytes |
808
+ | `useAutosave` | Periodic auto-save with dirty tracking |
809
+ | `useFontInjection` | Inject embedded fonts into DOM |
810
+ | `useRecoveryDetection` | Detect unsaved changes on reload |
811
+ | `useDialogCustomShows` | Custom slideshow management dialog |
812
+ | `useYjsProvider` | Yjs WebSocket provider lifecycle |
813
+ | `usePresenceTracking` | User presence, cursor positions, connection status |
814
+ | `useCollaborativeState` | CRDT-backed shared document state |
815
+ | `useCollaborativeHistory` | Collaborative undo/redo |
816
+
817
+ ---
818
+
819
+ ## Utility Modules Reference
820
+
821
+ | Category | Files | Key Modules |
822
+ | ------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
823
+ | **Shape rendering** | 12 | `shape.tsx`, `shape-visual.tsx`, `shape-visual-style.ts`, `shape-visual-effects.ts`, `shape-visual-3d.ts`, `shape-round-rect.ts`, `shape-adjustment.ts`, `vector-shape-renderer.tsx` |
824
+ | **Text rendering** | 10 | `text.tsx`, `text-layout.tsx`, `text-render.tsx`, `text-effects.tsx`, `text-warp.tsx`, `text-warp-css.tsx`, `warp-text-renderer.tsx`, `text-field-substitution.tsx` |
825
+ | **Table rendering** | 14 | `table.tsx`, `table-render.tsx`, `table-parse.tsx`, `table-cell-style.tsx`, `table-cell-fill.tsx`, `table-band-style.tsx`, `table-diagonal-borders.tsx`, `table-merge-core.ts` |
826
+ | **Chart rendering** | 22 | `chart.tsx`, `chart-bar.tsx`, `chart-pie.tsx`, `chart-area-line.tsx`, `chart-scatter-bubble.tsx`, `chart-radar.tsx`, `chart-stock.tsx`, `chart-chrome.tsx`, `chart-helpers.ts`, `chart-map.tsx` |
827
+ | **SmartArt** | 12 | `smartart.tsx`, `smartart-list.tsx`, `smartart-process.tsx`, `smartart-cycle.tsx`, `smartart-hierarchy.tsx`, `smartart-matrix.tsx`, `smartart-gear.tsx` |
828
+ | **Animation** | 14 | `animation.ts`, `animation-timeline.ts`, `animation-sequencer.ts`, `animation-keyframes.ts`, `animation-effects.ts`, `animation-presets.ts`, `animation-sound.ts` |
829
+ | **Transitions** | 7 | `slide-transitions.ts`, `transition-keyframes.ts`, `transition-helpers.ts`, `morph-transition.ts`, `p14-transition-animations.ts`, `p14-transition-keyframes.ts` |
830
+ | **Export** | 8 | `export.ts`, `export-slides.ts`, `export-helpers.ts`, `export-package.ts`, `export-gif.ts`, `export-gif-encoder.ts`, `export-video.ts`, `export-svg.ts` |
831
+ | **Colour** | 5 | `color.ts`, `color-core.ts`, `color-gradient.ts`, `color-patterns.ts`, `drawing-color.ts` |
832
+ | **Connector** | 5 | `connector-path.tsx`, `connector-router.ts`, `connector-router-graph.ts`, `connector-router-astar.ts`, `shape-connector.tsx` |
833
+ | **Media** | 5 | `media.tsx`, `media-render.tsx`, `media-controller.tsx`, `media-components.tsx`, `media-persistent-audio.tsx` |
834
+ | **Geometry** | 4 | `geometry.ts`, `geometry-image.ts`, `geometry-selection.ts`, `shape-types.tsx` |
835
+ | **PDF** | 2 | `pdf-builder.ts`, `notes-page-layout-utils.ts` |
836
+ | **Math (OMML)** | 5 | `omml-to-mathml.ts`, `omml-helpers.ts`, `omml-converters.ts`, `latex-to-omml.ts`, `latex-to-omml-parser.ts` |
837
+ | **Security** | 1 | `hyperlink-security.ts` |
838
+
839
+ ---
840
+
841
+ ## File Structure Reference
842
+
843
+ ```
844
+ src/
845
+ +-- index.ts # Package entry -- exports viewer + canvas export
846
+ +-- utils.ts # cn() utility (clsx + tailwind-merge)
847
+ |
848
+ +-- lib/
849
+ | +-- canvas-export.ts # html2canvas wrapper with oklch fix
850
+ |
851
+ +-- viewer/ # Main viewer module (469 files)
852
+ +-- index.ts # Viewer barrel export
853
+ +-- PowerPointViewer.tsx # Root orchestrator component
854
+ +-- types.ts # Type barrel (core + UI)
855
+ +-- types-core.ts # Data-model types (ViewerMode, shapes, etc.)
856
+ +-- types-ui.ts # UI types (context menu, shortcuts, props)
857
+ +-- constants.ts # Legacy constant re-exports
858
+ |
859
+ +-- constants/ # Constants (10 files)
860
+ | +-- scalar.ts # EMU/px conversion, default sizes
861
+ | +-- theme.ts # Default theme colours
862
+ | +-- toolbar.ts # Toolbar section definitions
863
+ | +-- shape-styles.ts # Quick style presets
864
+ | +-- shape-presets.ts # Shape insertion palette
865
+ | +-- connectors-strokes.ts # Connector and stroke presets
866
+ | +-- table-styles.ts # Built-in table style definitions
867
+ | +-- transitions-animations.ts # Transition/animation preset lists
868
+ | +-- action-buttons.ts # Action button definitions
869
+ |
870
+ +-- components/ # React components (230+ files)
871
+ | +-- index.ts # Component barrel export
872
+ | +-- SlideCanvas.tsx # Main slide rendering canvas
873
+ | +-- ElementRenderer.tsx # Element type dispatch
874
+ | +-- Toolbar.tsx # Main toolbar component
875
+ | +-- InspectorPane.tsx # Property inspector sidebar
876
+ | +-- ContextMenu.tsx # Right-click context menu
877
+ | +-- SlidesPaneSidebar.tsx # Slide thumbnail list
878
+ | +-- SlideNotesPanel.tsx # Speaker notes editor
879
+ | +-- PresenterView.tsx # Dual-screen presenter view
880
+ | +-- StatusBar.tsx # Bottom status bar
881
+ | |
882
+ | +-- elements/ # Element renderers (12 files)
883
+ | | +-- ElementBody.tsx # Shape body + visual effects
884
+ | | +-- ImageRenderer.tsx # Image with effects/crop
885
+ | | +-- ConnectorElementRenderer.tsx # SVG connector paths
886
+ | | +-- ConnectorTextOverlay.tsx # Text on connectors
887
+ | | +-- SmartArtRenderer.tsx # SmartArt layout rendering
888
+ | | +-- Model3DRenderer.tsx # 3D model rendering (Three.js)
889
+ | | +-- InkGroupRenderers.tsx # Ink annotation strokes
890
+ | | +-- InlineTextEditor.tsx # In-place text editing
891
+ | | +-- ResizeHandles.tsx # Selection + resize UI
892
+ | | +-- element-renderer-helpers.tsx # Shared renderer utilities
893
+ | |
894
+ | +-- collaboration/ # Collaboration UI (7 files)
895
+ | | +-- CollaborationProvider.tsx # Context provider
896
+ | | +-- CollaborationCursorOverlay.tsx # Remote cursor rendering
897
+ | | +-- RemoteUserCursors.tsx # Individual cursor component
898
+ | | +-- UserAvatarBar.tsx # Connected user avatars
899
+ | | +-- CollaborationStatusIndicator.tsx # Connection status
900
+ | |
901
+ | +-- canvas/ # Canvas overlays (14 files)
902
+ | +-- inspector/ # Inspector panels (84 files)
903
+ | +-- toolbar/ # Toolbar sections (17 files)
904
+ | +-- slides-pane/ # Slides sidebar (7 files)
905
+ | +-- slide-sorter/ # Slide sorter overlay (7 files)
906
+ | +-- notes/ # Notes toolbar & utils (6 files)
907
+ | +-- print/ # Print preview layouts (5 files)
908
+ |
909
+ +-- hooks/ # Custom hooks (67+ files)
910
+ | +-- index.ts # Hook barrel export
911
+ | +-- useViewerState.ts # Composite state hook
912
+ | +-- useViewerCoreState.ts # Core document state
913
+ | +-- useViewerUIState.ts # UI state
914
+ | +-- useEditorHistory.ts # Undo/redo
915
+ | +-- useZoomViewport.ts # Zoom/viewport
916
+ | +-- useLoadContent.ts # PPTX loading
917
+ | +-- usePresentationMode.ts # Slideshow mode
918
+ | +-- useEditorOperations.ts # Editor ops composition
919
+ | +-- useViewerIntegration.ts # Top-level integration
920
+ | +-- usePointerHandlers.ts # Mouse/touch events
921
+ | +-- useElementManipulation.ts # Move/resize/rotate
922
+ | +-- useInsertElements.ts # Element insertion
923
+ | +-- useSlideManagement.ts # Slide CRUD
924
+ | +-- useTableOperations.ts # Table operations
925
+ | +-- useExportHandlers.ts # Export logic
926
+ | +-- useKeyboardShortcuts.ts # Hotkey definitions
927
+ | +-- useFindReplace.ts # Search across slides
928
+ | +-- useComments.ts # Comment management
929
+ | +-- ...48 more hooks
930
+ | |
931
+ | +-- collaboration/ # Collaboration hooks (9 files)
932
+ | | +-- useYjsProvider.ts
933
+ | | +-- usePresenceTracking.ts
934
+ | | +-- useCollaborativeState.ts
935
+ | | +-- useCollaborativeHistory.ts
936
+ | | +-- sanitize.ts
937
+ | | +-- types.ts
938
+ | |
939
+ | +-- presentation-mode/ # Presentation sub-hooks (9 files)
940
+ | +-- useSlideNavigation.ts
941
+ | +-- useAnimationPlayback.ts
942
+ | +-- usePresentationKeyboard.ts
943
+ | +-- useRehearsalTimings.ts
944
+ |
945
+ +-- utils/ # Utility modules (159 files)
946
+ | +-- index.ts # Utility barrel export
947
+ | +-- shape.tsx # Shape rendering entry
948
+ | +-- text.tsx # Text rendering entry
949
+ | +-- table.tsx # Table rendering entry
950
+ | +-- chart.tsx # Chart rendering entry
951
+ | +-- smartart.tsx # SmartArt rendering entry
952
+ | +-- media.tsx # Media rendering entry
953
+ | +-- animation.ts # Animation engine entry
954
+ | +-- export.ts # Export pipeline entry
955
+ | +-- export-svg.ts # SVG vector export
956
+ | +-- hyperlink-security.ts # URL sanitization
957
+ | +-- color.ts # Colour utilities
958
+ | +-- geometry.ts # Geometry calculations
959
+ | +-- style.ts # CSS style generation
960
+ | +-- connector-router.ts # Connector pathfinding
961
+ | +-- pdf-builder.ts # PDF generation
962
+ | +-- ...145 more utility modules
963
+ |
964
+ +-- styles/
965
+ +-- print.css # Print-specific CSS
966
+ ```
967
+
968
+ ---
969
+
970
+ ## Limitations
971
+
972
+ - **CSS-based rendering** -- Slides are rendered as HTML/CSS rather than Canvas, which gives sharp text at any zoom, native accessibility, and DOM interactivity. The tradeoff is that some visual effects are approximated: `backdrop-filter` is replaced with semi-transparent backgrounds, `mix-blend-mode` is mapped to opacity fallbacks, and CSS 3D transforms (rotateX/Y) are flattened to 2D. Path gradients are approximated as elliptical radials.
973
+ - **Font availability** -- Text renders using fonts available in the browser. Missing fonts fall back to system defaults, which may affect text metrics and layout fidelity. Embedded fonts in the PPTX are deobfuscated and injected into the DOM when available.
974
+ - **Embedded media** -- Audio/video playback depends on browser codec support (e.g. browsers may not support WMV or legacy codecs). DRM-protected media will not play.
975
+ - **Animation triggers** -- 40+ animation presets are supported with `onClick`, `withPrevious`, `afterPrevious`, `afterDelay`, `onHover`, and `onShapeClick` triggers. Advanced OOXML timing tree conditions (compound triggers, multiple simultaneous conditions) are parsed but simplified for playback.
976
+ - **Morph transitions** -- Morph matches elements across slides using three strategies: explicit `!!` naming convention, element ID matching, and proximity matching (within 300px). Position, size, opacity, rotation, and colour are interpolated. Shape geometry morphing (interpolating between different shape types) and intelligent text token morphing are not implemented -- unmatched elements crossfade.
977
+ - **Chart interactivity** -- Charts are rendered as static SVG with hover tooltips. They are not directly editable via the chart surface -- use the inspector panel's chart data editor instead.
978
+ - **SmartArt editing** -- SmartArt is decomposed into individual positioned shapes using PowerPoint's pre-computed drawing data (13 layout types). The shapes are fully editable, but there is no live reflow engine -- moving or reordering shapes won't automatically recalculate the SmartArt layout.
979
+ - **Print and export fidelity** -- Raster exports (PNG/JPEG/PDF) go through `html2canvas`, which does not support `backdrop-filter`, CSS custom properties (`var()`), or CSS 3D transforms. The library preprocesses CSS to approximate these, but some fidelity is lost. An SVG export path is available as a vector alternative.
980
+ - **Maximum export resolution** -- Canvas-based exports are constrained by the browser's maximum canvas size (typically 16384x16384 or 32768x32768 pixels depending on browser and GPU).
981
+ - **Mobile support** -- Touch interactions (drag, pinch-zoom) are supported but the toolbar, inspector panels, and dialogs are designed for desktop viewport sizes.
982
+ - **3D models** -- Rendering GLB/GLTF 3D models requires optional peer dependencies (`three`, `@react-three/fiber`, `@react-three/drei`). Without them, the element falls back to its poster image.