Skip to content

Services

PowerPointViewerComponent is a thin, OnPush, signal-driven orchestrator. Almost all of its logic lives in roughly four dozen @Injectable orchestration services, provided on the component (providers: [...]) and wired together with inject(), plus 200+ standalone child components and plain helper functions. This is Angular's counterpart to React's 80+ custom hooks and Vue's composables: the same decomposition, expressed through Angular's own idiom (injectable services with signal-based state instead of hook closures).

Public vs internal

Most of these building blocks are internal architecture: they assume a specific composition order and shared inputs. A curated subset (listed below) is the intended public surface, exported from the pptx-angular-viewer package root. The complete set is importable from the pptx-angular-viewer/internals subpath: internal building blocks that are not covered by semver, so prefer the stable root exports. (ng-packagr builds this package as a single compilation unit, so internals is an alias over the same bundle rather than an isolated one; the symbols therefore stay importable from the root too.) See Complete Services Reference.

DI setup

All viewer services are declared as plain @Injectable() (not providedIn: 'root'). PowerPointViewerComponent lists every one of them in its own providers array, so each viewer instance gets its own isolated service tree; two viewers on one page never share state. Nothing is registered globally and there is no provide* bootstrap function to call.

To use a service standalone (outside the viewer component), provide it yourself at whatever scope fits and inject it:

ts
import { Component, inject } from '@angular/core';
import { LoadContentService, EditorStateService } from 'pptx-angular-viewer';

@Component({
	selector: 'app-headless-deck',
	standalone: true,
	providers: [LoadContentService, EditorStateService],
	template: `<p>{{ loader.slideCount() }} slides</p>`,
})
export class HeadlessDeckComponent {
	readonly loader = inject(LoadContentService);
	readonly editor = inject(EditorStateService);
}

Two flavors exist, and only one is meant for standalone use:

  • Self-contained state services (LoadContentService, EditorStateService, ExportService, CollaborationService, ViewerZoomService, IsMobileService, ...) own their state as signals and work anywhere they are provided.
  • Viewer* orchestration services (ViewerFileIOService, ViewerExportService, ViewerCanvasEditingService, ...) expect the host component to call bind(host) with a set of accessors in its constructor and throw ("...bind() was not called") when used without it. They are exported for completeness, not for standalone use.

Orchestration services (internal architecture)

These services describe how the viewer is wired. Treat this table as conceptual reference, not an API contract.

ServiceConcern
EditorStateServiceDocument state: slides, selection, undo/redo history, template elements.
LoadContentServiceParses the .pptx buffer on load; owns canvas size, media data URLs, embedded fonts.
ViewerFileIOServiceFile > Open / Save As orchestration, content override, getContent().
AutosaveServicePeriodic autosave scheduling and status, writing recovery snapshots to IndexedDB.
ViewerZoomServiceZoom level state (zoom, zoomPercent, zoomIn, zoomOut, zoomReset).
ZoomNavigationServicePowerPoint "Zoom" (summary/section zoom) navigation targets.
ZoomTargetServiceResolves a Zoom tile's fallback thumbnail info (background/number/section) from the live deck.
ViewerCanvasEditingServiceCanvas editing orchestration: element select, background click, transform, text/ink/table-cell edits.
ViewerInspectorPanelServiceRight-rail inspector panel switching (element/slide/comments/signatures/accessibility/selection).
ViewerFormatPainterServiceFormat painter + eyedropper tool state.
ViewerFindReplaceServiceFind and Find & Replace bar state and search/replace operations.
ViewerKeyboardServiceKeyboard shortcut dispatch for the component's document-level keydown listener.
ViewerTouchGesturesServicePinch-zoom, swipe-navigation, and long-press gesture wiring on the canvas host.
ViewerMobileSheetServiceMobile bottom-sheet state (slides/menu/notes) and quick-insert action.
ViewerPresentationModeServicePresentation-mode orchestration: enter/exit, presenter view, audience window.
ViewerCustomShowsServiceCustom-show (subset-of-slides presentation) state and presentation slide selection.
ViewerDocumentPropertiesServiceDocument Info dialog and hyperlink dialog state.
ViewerThemeGalleryServiceTheme gallery dialog state and applying a theme preset.
ViewerExportServicePNG / PDF / GIF / video export and print orchestration, with progress reporting and cancellation.
CollaborationServiceYjs CRDT connection, sync, and presence for a session.
ViewerCollaborationSessionServiceShare/Broadcast dialog state and session connect/disconnect orchestration.
ViewerCollabCursorServiceLocal pointer tracking for broadcasting the user's cursor position.
TableSelectionServiceTable cell selection state for the table editor.
EmbeddedFontsServiceInjects a presentation's embedded fonts as managed @font-face rules.
AccessibilityService, PrintService, IsMobileService, SmartArt3DService, FieldContextServiceAccessibility issue scanning, print jobs, device/viewport classification, the opt-in 3D SmartArt gate, and field/placeholder context, respectively.

There are more still (ink drawing, ruler guides, canvas-fit sizing). See the Complete Services Reference for the full list, grouped by concern.

Public services & components

The following are exported from the package root and safe to import for building custom UI around the viewer or driving it programmatically.

LoadContentService

Loads a .pptx and exposes everything parsed from it as signals: slides, canvasSize, theme, slideMasters, mediaDataUrls, embeddedFonts, coreProperties, appProperties, sections, loading, error, isEncrypted, hasMacros, and more, plus a computed slideCount.

MemberPurpose
load(raw)(raw: Uint8Array | ArrayBuffer | null | undefined) => Promise<void>: parse a buffer into the signals.
getContent()() => Promise<Uint8Array>: serialize the loaded presentation back to bytes.
saveSlides(slides, format?, sections?)Serialize an edited deck (for example EditorStateService's slides) using the loaded presentation's handler.
ts
@Component({ providers: [LoadContentService] /* ... */ })
export class DeckStatsComponent {
	private readonly loader = inject(LoadContentService);

	async open(file: File): Promise<void> {
		await this.loader.load(await file.arrayBuffer());
		if (this.loader.error()) return;
		console.log(this.loader.slideCount(), this.loader.canvasSize());
	}
}

EditorStateService

Signal-based editing state: slides, sections, selectedIds, dirty, editTemplateMode, templateElementsBySlideId, canUndo / canRedo / undoLabel / redoLabel, and a large set of imperative operations, all history-aware: setSlides, updateElement(slideIndex, id, patch), addElement, deleteSelected, duplicateSelected, moveSelectedBy, alignSelected, groupSelected, copySelected / paste, addSlide, deleteSlide, duplicateSlide, moveSlide, undo, redo, and more.

ts
const editor = inject(EditorStateService);

editor.setSlides(loadedSlides); // clones, partitions template elements, resets history
editor.updateElement(0, 'el_12', { x: 120, y: 80 });
editor.select(['el_12']);
editor.duplicateSelected(0);
editor.undo();

const bytes = await this.loader.saveSlides(editor.snapshot());

Collaboration

For building custom collaboration UIs or driving sync yourself. See Collaboration.

ExportPurpose
CollaborationServiceconnect(config, options?) / disconnect() / retry() for a Yjs session; signals for status, presence, cursors, connectedCount; broadcastSlides, setCursor, setSelection, setActiveSlide, followUser. Disconnects itself on destroy.
CollaborationCursorsComponentRenders remote cursors on the slide canvas.
RemoteSelectionOverlayComponent (internals)Renders remote users' element-selection highlights.
collaboration-helpers exportsvalidateRoomId, sanitizeUserName, derivePresenceList, assignUserColor, and more.
ts
const collab = inject(CollaborationService);

await collab.connect(
	{ roomId: 'deck-42', serverUrl: 'wss://collab.example.com', userName: 'Ada' },
	{ onRemoteSlides: (slides) => this.editor.applyRemoteSlides(slides) },
);

Rendering & renderers

SlideCanvasComponent, ElementRendererComponent, ConnectorRendererComponent, TableRendererComponent, ChartRendererComponent, SmartArtRendererComponent, InkRendererComponent, OleRendererComponent, Model3DRendererComponent, ZoomRendererComponent, EquationRendererComponent: the per-element-type renderers SlideCanvasComponent composes.

Export

ExportPurpose
ExportServiceSlide SVG export (exportSlideToSvg, exportAllSlidesToSvg), element rasterization (exportElementToPng, copyElementAsPng, renderElement), file download helpers (savePptx, savePresentation), and PDF/GIF/WebM assembly from rendered canvases.
renderToCanvasStandalone html2canvas-pro wrapper with an oklch-colour workaround. See Export.

Using an internal service directly

If the curated public services above don't cover what you need, every internal service, component, and helper is also importable in full from pptx-angular-viewer itself (there is no separate subpath):

ts
import { ViewerZoomService, buildSaveSlides } from 'pptx-angular-viewer';

Internal building blocks

Everything documented on the Complete Services Reference page is re-exported unmodified from the same building blocks PowerPointViewerComponent composes internally, behind the pptx-angular-viewer/internals subpath. They are not covered by semver: signatures and behavior can change, and services/components can be renamed or removed, without a major bump. Prefer the inputs/outputs/public API or the curated services above first; reach for internals only for advanced integrations, and pin an exact version if you depend on it.

See the Complete Services Reference for the full list and Overview for the broader architectural picture.

Released under the Apache-2.0 License.