Store
Presentation store API reference.
The store is the single source of truth for all presentation state: loading, navigation, zoom, edits, and undo history. It's compatible with React's useSyncExternalStore.
Creating a store
Uncontrolled (default)
Presentation.Root creates an internal store automatically. This is the simplest setup:
<Presentation.Root file={file}>
{/* descendants can use usePresentation(), useSlide(), useZoom() */}
</Presentation.Root>Controlled
Use useCreatePresentationStore when you need to drive the store from outside (programmatic load, toolbar buttons, save):
import { useCreatePresentationStore } from "@diceui/pptx";
const store = useCreatePresentationStore();
// then pass it to the provider
<Presentation.Provider store={store}>
<Presentation.Root>...</Presentation.Root>
</Presentation.Provider>;State
interface PresentationState {
status: "idle" | "loading" | "ready" | "error";
presentation: PresentationData | null;
activeSlideId: string | null;
zoom: number; // default: 1
progress: number; // 0–100, meaningful while status === "loading"
error: Error | null;
revision: number; // bumped on every edit/undo/redo
}revision is important: presentation is mutated in place by edits, so its object identity never changes. Subscribe to revision to react to content changes.
Methods
load(input, options?)
store.load(file, {
defaultSlideIndex?: number | ((slides) => number), // default: 0
readOnly?: boolean, // default: true
lazy?: boolean, // default: true (parse slides on demand)
embedFonts?: boolean, // default: true (decode embedded fonts before ready)
})Parses a File, Blob, ArrayBuffer, or Uint8Array. Returns a promise that resolves to PresentationData. A superseded load rejects with DOMException("AbortError") (safe to ignore).
reset()
Clears the store back to the initial idle state and aborts any in-flight load.
Navigation
store.goTo(slideId: string) // by stable slide id
store.goToIndex(index: number) // 0-based, clamped to valid range
store.next()
store.prev()
store.getActiveSlide() // SlideData | null
store.canGoNext()
store.canGoPrev()Zoom
store.setZoom(n: number) // clamped to [0.1, 4]
store.zoomIn(step?: number) // default step: 0.25
store.zoomOut(step?: number)
store.fitTo(width, height, padding?) // compute largest zoom that fitsEditing
Requires the deck to have been loaded with { readOnly: false }.
await store.edit(op: EditOperation): Promise<EditResult>
store.undo(): boolean
await store.redo(): Promise<boolean>
store.canUndo(): boolean
store.canRedo(): boolean
await store.save(options?): Promise<Uint8Array>
store.getSlideRevision(slideId: string): numberEdit operations
All operations accept slideId and nodeId (both strings).
setTextRun
Replace a single run's text content. Preserves all other run formatting.
await store.edit({
type: "setTextRun",
slideId,
nodeId,
paragraphIndex: 0,
runIndex: 0,
text: "New text",
});setTextBody
Replace all paragraphs and runs in a shape.
await store.edit({
type: "setTextBody",
slideId,
nodeId,
paragraphs: [
{
runs: [{ text: "Line one" }],
},
{
runs: [{ text: "Line two" }],
},
],
});setNodeTransform
Move or resize a shape. All values are in slide pixels.
await store.edit({
type: "setNodeTransform",
slideId,
nodeId,
x: 100,
y: 50,
width: 400,
height: 200,
rotation: 0, // degrees, optional
});setSolidFill
Change a shape's solid fill color.
await store.edit({
type: "setSolidFill",
slideId,
nodeId,
color: "#3b82f6", // hex
});deleteNode
Remove a shape from a slide.
await store.edit({ type: "deleteNode", slideId, nodeId });moveSlide
Reorder slides.
await store.edit({ type: "moveSlide", slideId, toIndex: 2 });duplicateSlide
Clone a slide. The duplicate is inserted immediately after the source.
await store.edit({ type: "duplicateSlide", slideId });deleteSlide
Remove a slide.
await store.edit({ type: "deleteSlide", slideId });batch
Group multiple operations into a single undoable step.
await store.edit({
type: "batch",
ops: [
{ type: "deleteNode", slideId, nodeId: "2" },
{ type: "deleteNode", slideId, nodeId: "3" },
],
});Hooks
import {
usePresentation, // { presentation, status, progress, error }
useSlide, // { slide, slideId, index }
useZoom, // { zoom, setZoom, zoomIn, zoomOut, fitTo }
} from "@diceui/pptx";All hooks must be used inside Presentation.Root or Presentation.Provider.