@particle-academy/fancy-slides 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, CSSProperties } from 'react';
3
- import { f as Slide$1, m as Theme, h as SlideElement, D as Deck, c as DeckOp, e as ShapeKind, j as SlideTransition, g as SlideBackground, k as TextElement, I as ImageElement, S as ShapeElement, i as SlideLayout } from './types-B2ecrEAz.cjs';
4
- export { C as ChartElement, a as CodeElement, b as DeckActivity, E as ElementBase, d as EmbedElement, T as TableElement, l as TextStyle, n as ThemeColors, o as ThemeFonts, p as TransitionKind } from './types-B2ecrEAz.cjs';
3
+ import { h as Slide$1, o as Theme, j as SlideElement, D as Deck, d as DeckOp, g as ShapeKind, l as SlideTransition, i as SlideBackground, E as ElementAnimation, m as TextElement, I as ImageElement, S as ShapeElement, k as SlideLayout } from './types-9BbelJX1.cjs';
4
+ export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, T as TableElement, n as TextStyle, p as ThemeColors, q as ThemeFonts, r as TransitionKind } from './types-9BbelJX1.cjs';
5
5
 
6
6
  interface SlideProps {
7
7
  /** The slide to render. */
@@ -14,6 +14,13 @@ interface SlideProps {
14
14
  aspectRatio?: number;
15
15
  /** Edit mode flag — passed to element renderers + enables drag/resize affordances. */
16
16
  editing?: boolean;
17
+ /**
18
+ * Current build step (0..totalSteps). `0` = nothing built (only non-animated
19
+ * elements visible); each step reveals more animated elements. Omit (or pass
20
+ * a number ≥ total) to show the fully-built slide. Ignored when `editing` —
21
+ * the editor always shows every element so authors can position them.
22
+ */
23
+ buildStep?: number;
17
24
  /** Called when a text element's content is edited (only in editing mode). */
18
25
  onElementContentChange?: (elementId: string, content: string) => void;
19
26
  /** Called when an element is clicked — host-driven selection. */
@@ -47,7 +54,7 @@ interface SlideProps {
47
54
  * Both fire through `onElementMove` / `onElementResize` so the host owns
48
55
  * the state — Slide stays a pure renderer.
49
56
  */
50
- declare function Slide({ slide, theme, width, aspectRatio, editing, onElementContentChange, onElementSelect, selectedElementId, onElementMove, onElementResize, renderElement, className, style, }: SlideProps): react_jsx_runtime.JSX.Element;
57
+ declare function Slide({ slide, theme, width, aspectRatio, editing, buildStep, onElementContentChange, onElementSelect, selectedElementId, onElementMove, onElementResize, renderElement, className, style, }: SlideProps): react_jsx_runtime.JSX.Element;
51
58
 
52
59
  /**
53
60
  * What the surrounding <Slide> knows about itself. Exposed to children
@@ -293,6 +300,10 @@ interface ElementInspectorProps {
293
300
  onSetTransition?: (transition?: SlideTransition) => void;
294
301
  /** Set the slide's background. */
295
302
  onSetBackground?: (background?: SlideBackground) => void;
303
+ /** Set or clear the selected element's entrance build animation. */
304
+ onSetAnimation?: (animation?: ElementAnimation) => void;
305
+ /** Set a specific element's build animation by id — used by the slide-level build-order list. */
306
+ onSetElementAnimation?: (elementId: string, animation?: ElementAnimation) => void;
296
307
  }
297
308
  /**
298
309
  * Right-hand inspector. Tabs split position + style + advanced properties.
@@ -300,7 +311,7 @@ interface ElementInspectorProps {
300
311
  * react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
301
312
  * `Action`.
302
313
  */
303
- declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
314
+ declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetAnimation, onSetElementAnimation }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
304
315
 
305
316
  interface SpeakerNotesProps {
306
317
  notes?: string;
@@ -314,6 +325,103 @@ interface SpeakerNotesProps {
314
325
  */
315
326
  declare function SpeakerNotes({ notes, onChange, placeholder }: SpeakerNotesProps): react_jsx_runtime.JSX.Element;
316
327
 
328
+ /**
329
+ * Build (entrance-animation) sequencing — the shared model used by both
330
+ * `SlideViewer` and `PresenterView` so step-through behaves identically.
331
+ *
332
+ * A slide's *builds* are the elements that carry an `animation`. They are
333
+ * stable-sorted by `(order ?? 0)` then original element array index, then
334
+ * grouped into *click steps*:
335
+ *
336
+ * - The first build, and every build whose trigger is `"on-click"`, starts
337
+ * a NEW step.
338
+ * - `"with-prev"` plays simultaneously with the current step's lead.
339
+ * - `"after-prev"` plays after a delay equal to the current step's lead
340
+ * duration (chained onto its `delay`).
341
+ *
342
+ * `buildStep` semantics (used by the viewer/presenter):
343
+ * - `0` → nothing built yet; only non-animated elements are visible.
344
+ * - `n` → the first `n` steps have fired; their elements are visible.
345
+ * - `totalSteps` → every build is shown (the fully-built slide).
346
+ */
347
+
348
+ /** One element participating in a build, paired with its (defaulted) animation. */
349
+ interface Build {
350
+ element: SlideElement;
351
+ animation: ElementAnimation;
352
+ /** Original index of the element in the slide's `elements` array (tie-breaker). */
353
+ index: number;
354
+ /**
355
+ * For a "by paragraph" text build, which paragraph index (0-based) this
356
+ * build reveals. Undefined for whole-element builds. The renderer uses this
357
+ * to show "the first K paragraphs of this element".
358
+ */
359
+ paraIndex?: number;
360
+ }
361
+ /**
362
+ * Split a text element's `content` into paragraphs for a "by paragraph" build.
363
+ * Splits on `"\n"` and drops a single trailing empty line (so content ending in
364
+ * a newline doesn't manifest a phantom blank build). Empty interior lines are
365
+ * preserved — they still consume a click, matching PowerPoint's behaviour.
366
+ */
367
+ declare function splitParagraphs(content: string): string[];
368
+ /**
369
+ * Whether an element expands into per-paragraph builds: a text element whose
370
+ * animation has `byParagraph` and that splits into 2+ paragraphs. With 0/1
371
+ * paragraphs it behaves like a normal single build.
372
+ */
373
+ declare function isByParagraph(element: SlideElement, animation: ElementAnimation): boolean;
374
+ /** A click step — the set of builds revealed by a single forward advance. */
375
+ interface BuildStep {
376
+ /** Builds that reveal on this step (lead first, then with-prev / after-prev). */
377
+ builds: Build[];
378
+ }
379
+ /**
380
+ * Collect a slide's builds in resolved order: every element with an
381
+ * `animation`, stable-sorted by `(order ?? 0)` then array index.
382
+ */
383
+ declare function collectBuilds(slide: Slide$1 | undefined): Build[];
384
+ /**
385
+ * Group a slide's builds into click steps. The first build always opens a
386
+ * step; thereafter an `"on-click"` trigger opens a new step while
387
+ * `"with-prev"` / `"after-prev"` attach to the current one.
388
+ */
389
+ declare function buildSteps(slide: Slide$1 | undefined): BuildStep[];
390
+ /** Total number of click steps for a slide (0 when the slide has no builds). */
391
+ declare function totalBuildSteps(slide: Slide$1 | undefined): number;
392
+ /**
393
+ * Given a slide and a `buildStep` (0..totalSteps), return the set of element
394
+ * ids that should be VISIBLE. Elements with no animation are always visible;
395
+ * animated elements become visible once their owning step has fired.
396
+ */
397
+ declare function visibleElementIds(slide: Slide$1 | undefined, buildStep: number): Set<string>;
398
+ /**
399
+ * Per-element paragraph reveal state for a "by paragraph" text build at a given
400
+ * `buildStep`. Keyed by element id:
401
+ * - `revealed` — how many paragraphs (0..count) should be shown so far.
402
+ * - `firingParaIndex` — the paragraph index revealing on the step that just
403
+ * fired (so the renderer plays its entrance effect), or `undefined` when no
404
+ * paragraph of this element fires on `buildStep`.
405
+ * Only elements that actually expand by-paragraph appear in the map.
406
+ */
407
+ interface ParaReveal {
408
+ revealed: number;
409
+ firingParaIndex?: number;
410
+ }
411
+ declare function paragraphReveals(slide: Slide$1 | undefined, buildStep: number): Map<string, ParaReveal>;
412
+ /**
413
+ * The builds that fire when advancing INTO `buildStep` (1-based). Returns the
414
+ * lead build first; the viewer uses `with-prev` / `after-prev` to compute each
415
+ * element's effective `delay`. Empty when `buildStep` is out of range.
416
+ */
417
+ declare function buildsForStep(slide: Slide$1 | undefined, buildStep: number): Build[];
418
+ /**
419
+ * Compute the effective entrance delay (ms) for each build within a step,
420
+ * honouring `with-prev` (0 extra) and `after-prev` (lead duration). The lead
421
+ * build keeps its own `delay`; followers add to it. Keyed by element id.
422
+ */
423
+ declare function stepDelays(builds: Build[]): Map<string, number>;
424
+
317
425
  interface TextElementRendererProps {
318
426
  element: TextElement;
319
427
  theme?: Theme;
@@ -331,6 +439,14 @@ interface TextElementRendererProps {
331
439
  selected?: boolean;
332
440
  /** Called when the user edits the content (only fires when the textarea is focusable). */
333
441
  onContentChange?: (content: string) => void;
442
+ /**
443
+ * By-paragraph reveal state, set by `<Slide>` in viewer mode when this text
444
+ * element has a `byParagraph` animation. When present, the renderer splits
445
+ * `content` on `"\n"` and shows only the first `revealed` paragraphs,
446
+ * animating the one at `firingParaIndex`. Ignored in editing mode (the full
447
+ * text always renders so authors can position/edit it).
448
+ */
449
+ paraReveal?: ParaReveal;
334
450
  }
335
451
  /**
336
452
  * Renderer for `text` elements. Three formats:
@@ -344,7 +460,7 @@ interface TextElementRendererProps {
344
460
  * In editing mode + when the element is selected, the renderer swaps to a
345
461
  * textarea showing the raw source. Edits flow back via `onContentChange`.
346
462
  */
347
- declare function TextElementRenderer({ element, theme, slideWidthPx, editing, selected, onContentChange, }: TextElementRendererProps): react_jsx_runtime.JSX.Element;
463
+ declare function TextElementRenderer({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal, }: TextElementRendererProps): react_jsx_runtime.JSX.Element;
348
464
 
349
465
  interface ImageElementRendererProps {
350
466
  element: ImageElement;
@@ -375,8 +491,19 @@ interface SlideKeyboardOptions {
375
491
  total: number;
376
492
  /** Current slide index. */
377
493
  index: number;
378
- /** Move to a specific slide. */
494
+ /** Move to a specific slide. Used by Home/End/1-9 (and by arrows when no `onAdvance`/`onRetreat`). */
379
495
  goTo: (index: number) => void;
496
+ /**
497
+ * Forward step (→ / Space / PageDown). When provided it OWNS forward nav —
498
+ * e.g. step through builds, then advance the slide. Falls back to
499
+ * `goTo(index + 1)` when omitted.
500
+ */
501
+ onAdvance?: () => void;
502
+ /**
503
+ * Backward step (← / PageUp). When provided it OWNS backward nav. Falls back
504
+ * to `goTo(index - 1)` when omitted.
505
+ */
506
+ onRetreat?: () => void;
380
507
  /** Called on Esc — typically exits fullscreen. */
381
508
  onExit?: () => void;
382
509
  /** Called on `B` — typically blacks/whites out the screen. */
@@ -389,8 +516,8 @@ interface SlideKeyboardOptions {
389
516
  /**
390
517
  * Standard slideshow keyboard plumbing:
391
518
  *
392
- * ← / PageUp — previous slide
393
- * → / PageDown / Space — next slide
519
+ * ← / PageUp — retreat (onRetreat, else previous slide)
520
+ * → / PageDown / Space — advance (onAdvance, else next slide)
394
521
  * Home — first slide
395
522
  * End — last slide
396
523
  * Esc — onExit
@@ -398,7 +525,7 @@ interface SlideKeyboardOptions {
398
525
  * F — onFullscreen
399
526
  * 1..9 — jump to slide N
400
527
  */
401
- declare function useSlideKeyboard({ total, index, goTo, onExit, onBlank, onFullscreen, enabled, }: SlideKeyboardOptions): void;
528
+ declare function useSlideKeyboard({ total, index, goTo, onAdvance, onRetreat, onExit, onBlank, onFullscreen, enabled, }: SlideKeyboardOptions): void;
402
529
 
403
530
  /**
404
531
  * Hook that wraps a controlled deck with a typed mutation API. Every helper
@@ -436,6 +563,8 @@ interface DeckStateApi {
436
563
  updateElement: (slideId: string, elementId: string, patch: Partial<SlideElement>) => void;
437
564
  moveElement: (slideId: string, elementId: string, x: number, y: number) => void;
438
565
  resizeElement: (slideId: string, elementId: string, w: number, h: number) => void;
566
+ /** Set or clear an element's entrance build animation. Pass `undefined` to clear. */
567
+ setAnimation: (slideId: string, elementId: string, animation?: ElementAnimation) => void;
439
568
  /** Convenience lookups. */
440
569
  getSlide: (id: string) => Slide$1 | undefined;
441
570
  getElement: (slideId: string, elementId: string) => SlideElement | undefined;
@@ -496,4 +625,4 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
496
625
  type Option = Record<string, unknown>;
497
626
  declare function chartStarterOption(kind: ChartKind): Option;
498
627
 
499
- export { type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, builtinThemes, chartStarterOption, darkTheme, deckId, defaultTheme, defineTheme, elementId, nextId, reduce as reduceDeck, resolveTheme, slideId, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, vividTheme };
628
+ export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, type ParaReveal, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, CSSProperties } from 'react';
3
- import { f as Slide$1, m as Theme, h as SlideElement, D as Deck, c as DeckOp, e as ShapeKind, j as SlideTransition, g as SlideBackground, k as TextElement, I as ImageElement, S as ShapeElement, i as SlideLayout } from './types-B2ecrEAz.js';
4
- export { C as ChartElement, a as CodeElement, b as DeckActivity, E as ElementBase, d as EmbedElement, T as TableElement, l as TextStyle, n as ThemeColors, o as ThemeFonts, p as TransitionKind } from './types-B2ecrEAz.js';
3
+ import { h as Slide$1, o as Theme, j as SlideElement, D as Deck, d as DeckOp, g as ShapeKind, l as SlideTransition, i as SlideBackground, E as ElementAnimation, m as TextElement, I as ImageElement, S as ShapeElement, k as SlideLayout } from './types-9BbelJX1.js';
4
+ export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, T as TableElement, n as TextStyle, p as ThemeColors, q as ThemeFonts, r as TransitionKind } from './types-9BbelJX1.js';
5
5
 
6
6
  interface SlideProps {
7
7
  /** The slide to render. */
@@ -14,6 +14,13 @@ interface SlideProps {
14
14
  aspectRatio?: number;
15
15
  /** Edit mode flag — passed to element renderers + enables drag/resize affordances. */
16
16
  editing?: boolean;
17
+ /**
18
+ * Current build step (0..totalSteps). `0` = nothing built (only non-animated
19
+ * elements visible); each step reveals more animated elements. Omit (or pass
20
+ * a number ≥ total) to show the fully-built slide. Ignored when `editing` —
21
+ * the editor always shows every element so authors can position them.
22
+ */
23
+ buildStep?: number;
17
24
  /** Called when a text element's content is edited (only in editing mode). */
18
25
  onElementContentChange?: (elementId: string, content: string) => void;
19
26
  /** Called when an element is clicked — host-driven selection. */
@@ -47,7 +54,7 @@ interface SlideProps {
47
54
  * Both fire through `onElementMove` / `onElementResize` so the host owns
48
55
  * the state — Slide stays a pure renderer.
49
56
  */
50
- declare function Slide({ slide, theme, width, aspectRatio, editing, onElementContentChange, onElementSelect, selectedElementId, onElementMove, onElementResize, renderElement, className, style, }: SlideProps): react_jsx_runtime.JSX.Element;
57
+ declare function Slide({ slide, theme, width, aspectRatio, editing, buildStep, onElementContentChange, onElementSelect, selectedElementId, onElementMove, onElementResize, renderElement, className, style, }: SlideProps): react_jsx_runtime.JSX.Element;
51
58
 
52
59
  /**
53
60
  * What the surrounding <Slide> knows about itself. Exposed to children
@@ -293,6 +300,10 @@ interface ElementInspectorProps {
293
300
  onSetTransition?: (transition?: SlideTransition) => void;
294
301
  /** Set the slide's background. */
295
302
  onSetBackground?: (background?: SlideBackground) => void;
303
+ /** Set or clear the selected element's entrance build animation. */
304
+ onSetAnimation?: (animation?: ElementAnimation) => void;
305
+ /** Set a specific element's build animation by id — used by the slide-level build-order list. */
306
+ onSetElementAnimation?: (elementId: string, animation?: ElementAnimation) => void;
296
307
  }
297
308
  /**
298
309
  * Right-hand inspector. Tabs split position + style + advanced properties.
@@ -300,7 +311,7 @@ interface ElementInspectorProps {
300
311
  * react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
301
312
  * `Action`.
302
313
  */
303
- declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
314
+ declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetAnimation, onSetElementAnimation }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
304
315
 
305
316
  interface SpeakerNotesProps {
306
317
  notes?: string;
@@ -314,6 +325,103 @@ interface SpeakerNotesProps {
314
325
  */
315
326
  declare function SpeakerNotes({ notes, onChange, placeholder }: SpeakerNotesProps): react_jsx_runtime.JSX.Element;
316
327
 
328
+ /**
329
+ * Build (entrance-animation) sequencing — the shared model used by both
330
+ * `SlideViewer` and `PresenterView` so step-through behaves identically.
331
+ *
332
+ * A slide's *builds* are the elements that carry an `animation`. They are
333
+ * stable-sorted by `(order ?? 0)` then original element array index, then
334
+ * grouped into *click steps*:
335
+ *
336
+ * - The first build, and every build whose trigger is `"on-click"`, starts
337
+ * a NEW step.
338
+ * - `"with-prev"` plays simultaneously with the current step's lead.
339
+ * - `"after-prev"` plays after a delay equal to the current step's lead
340
+ * duration (chained onto its `delay`).
341
+ *
342
+ * `buildStep` semantics (used by the viewer/presenter):
343
+ * - `0` → nothing built yet; only non-animated elements are visible.
344
+ * - `n` → the first `n` steps have fired; their elements are visible.
345
+ * - `totalSteps` → every build is shown (the fully-built slide).
346
+ */
347
+
348
+ /** One element participating in a build, paired with its (defaulted) animation. */
349
+ interface Build {
350
+ element: SlideElement;
351
+ animation: ElementAnimation;
352
+ /** Original index of the element in the slide's `elements` array (tie-breaker). */
353
+ index: number;
354
+ /**
355
+ * For a "by paragraph" text build, which paragraph index (0-based) this
356
+ * build reveals. Undefined for whole-element builds. The renderer uses this
357
+ * to show "the first K paragraphs of this element".
358
+ */
359
+ paraIndex?: number;
360
+ }
361
+ /**
362
+ * Split a text element's `content` into paragraphs for a "by paragraph" build.
363
+ * Splits on `"\n"` and drops a single trailing empty line (so content ending in
364
+ * a newline doesn't manifest a phantom blank build). Empty interior lines are
365
+ * preserved — they still consume a click, matching PowerPoint's behaviour.
366
+ */
367
+ declare function splitParagraphs(content: string): string[];
368
+ /**
369
+ * Whether an element expands into per-paragraph builds: a text element whose
370
+ * animation has `byParagraph` and that splits into 2+ paragraphs. With 0/1
371
+ * paragraphs it behaves like a normal single build.
372
+ */
373
+ declare function isByParagraph(element: SlideElement, animation: ElementAnimation): boolean;
374
+ /** A click step — the set of builds revealed by a single forward advance. */
375
+ interface BuildStep {
376
+ /** Builds that reveal on this step (lead first, then with-prev / after-prev). */
377
+ builds: Build[];
378
+ }
379
+ /**
380
+ * Collect a slide's builds in resolved order: every element with an
381
+ * `animation`, stable-sorted by `(order ?? 0)` then array index.
382
+ */
383
+ declare function collectBuilds(slide: Slide$1 | undefined): Build[];
384
+ /**
385
+ * Group a slide's builds into click steps. The first build always opens a
386
+ * step; thereafter an `"on-click"` trigger opens a new step while
387
+ * `"with-prev"` / `"after-prev"` attach to the current one.
388
+ */
389
+ declare function buildSteps(slide: Slide$1 | undefined): BuildStep[];
390
+ /** Total number of click steps for a slide (0 when the slide has no builds). */
391
+ declare function totalBuildSteps(slide: Slide$1 | undefined): number;
392
+ /**
393
+ * Given a slide and a `buildStep` (0..totalSteps), return the set of element
394
+ * ids that should be VISIBLE. Elements with no animation are always visible;
395
+ * animated elements become visible once their owning step has fired.
396
+ */
397
+ declare function visibleElementIds(slide: Slide$1 | undefined, buildStep: number): Set<string>;
398
+ /**
399
+ * Per-element paragraph reveal state for a "by paragraph" text build at a given
400
+ * `buildStep`. Keyed by element id:
401
+ * - `revealed` — how many paragraphs (0..count) should be shown so far.
402
+ * - `firingParaIndex` — the paragraph index revealing on the step that just
403
+ * fired (so the renderer plays its entrance effect), or `undefined` when no
404
+ * paragraph of this element fires on `buildStep`.
405
+ * Only elements that actually expand by-paragraph appear in the map.
406
+ */
407
+ interface ParaReveal {
408
+ revealed: number;
409
+ firingParaIndex?: number;
410
+ }
411
+ declare function paragraphReveals(slide: Slide$1 | undefined, buildStep: number): Map<string, ParaReveal>;
412
+ /**
413
+ * The builds that fire when advancing INTO `buildStep` (1-based). Returns the
414
+ * lead build first; the viewer uses `with-prev` / `after-prev` to compute each
415
+ * element's effective `delay`. Empty when `buildStep` is out of range.
416
+ */
417
+ declare function buildsForStep(slide: Slide$1 | undefined, buildStep: number): Build[];
418
+ /**
419
+ * Compute the effective entrance delay (ms) for each build within a step,
420
+ * honouring `with-prev` (0 extra) and `after-prev` (lead duration). The lead
421
+ * build keeps its own `delay`; followers add to it. Keyed by element id.
422
+ */
423
+ declare function stepDelays(builds: Build[]): Map<string, number>;
424
+
317
425
  interface TextElementRendererProps {
318
426
  element: TextElement;
319
427
  theme?: Theme;
@@ -331,6 +439,14 @@ interface TextElementRendererProps {
331
439
  selected?: boolean;
332
440
  /** Called when the user edits the content (only fires when the textarea is focusable). */
333
441
  onContentChange?: (content: string) => void;
442
+ /**
443
+ * By-paragraph reveal state, set by `<Slide>` in viewer mode when this text
444
+ * element has a `byParagraph` animation. When present, the renderer splits
445
+ * `content` on `"\n"` and shows only the first `revealed` paragraphs,
446
+ * animating the one at `firingParaIndex`. Ignored in editing mode (the full
447
+ * text always renders so authors can position/edit it).
448
+ */
449
+ paraReveal?: ParaReveal;
334
450
  }
335
451
  /**
336
452
  * Renderer for `text` elements. Three formats:
@@ -344,7 +460,7 @@ interface TextElementRendererProps {
344
460
  * In editing mode + when the element is selected, the renderer swaps to a
345
461
  * textarea showing the raw source. Edits flow back via `onContentChange`.
346
462
  */
347
- declare function TextElementRenderer({ element, theme, slideWidthPx, editing, selected, onContentChange, }: TextElementRendererProps): react_jsx_runtime.JSX.Element;
463
+ declare function TextElementRenderer({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal, }: TextElementRendererProps): react_jsx_runtime.JSX.Element;
348
464
 
349
465
  interface ImageElementRendererProps {
350
466
  element: ImageElement;
@@ -375,8 +491,19 @@ interface SlideKeyboardOptions {
375
491
  total: number;
376
492
  /** Current slide index. */
377
493
  index: number;
378
- /** Move to a specific slide. */
494
+ /** Move to a specific slide. Used by Home/End/1-9 (and by arrows when no `onAdvance`/`onRetreat`). */
379
495
  goTo: (index: number) => void;
496
+ /**
497
+ * Forward step (→ / Space / PageDown). When provided it OWNS forward nav —
498
+ * e.g. step through builds, then advance the slide. Falls back to
499
+ * `goTo(index + 1)` when omitted.
500
+ */
501
+ onAdvance?: () => void;
502
+ /**
503
+ * Backward step (← / PageUp). When provided it OWNS backward nav. Falls back
504
+ * to `goTo(index - 1)` when omitted.
505
+ */
506
+ onRetreat?: () => void;
380
507
  /** Called on Esc — typically exits fullscreen. */
381
508
  onExit?: () => void;
382
509
  /** Called on `B` — typically blacks/whites out the screen. */
@@ -389,8 +516,8 @@ interface SlideKeyboardOptions {
389
516
  /**
390
517
  * Standard slideshow keyboard plumbing:
391
518
  *
392
- * ← / PageUp — previous slide
393
- * → / PageDown / Space — next slide
519
+ * ← / PageUp — retreat (onRetreat, else previous slide)
520
+ * → / PageDown / Space — advance (onAdvance, else next slide)
394
521
  * Home — first slide
395
522
  * End — last slide
396
523
  * Esc — onExit
@@ -398,7 +525,7 @@ interface SlideKeyboardOptions {
398
525
  * F — onFullscreen
399
526
  * 1..9 — jump to slide N
400
527
  */
401
- declare function useSlideKeyboard({ total, index, goTo, onExit, onBlank, onFullscreen, enabled, }: SlideKeyboardOptions): void;
528
+ declare function useSlideKeyboard({ total, index, goTo, onAdvance, onRetreat, onExit, onBlank, onFullscreen, enabled, }: SlideKeyboardOptions): void;
402
529
 
403
530
  /**
404
531
  * Hook that wraps a controlled deck with a typed mutation API. Every helper
@@ -436,6 +563,8 @@ interface DeckStateApi {
436
563
  updateElement: (slideId: string, elementId: string, patch: Partial<SlideElement>) => void;
437
564
  moveElement: (slideId: string, elementId: string, x: number, y: number) => void;
438
565
  resizeElement: (slideId: string, elementId: string, w: number, h: number) => void;
566
+ /** Set or clear an element's entrance build animation. Pass `undefined` to clear. */
567
+ setAnimation: (slideId: string, elementId: string, animation?: ElementAnimation) => void;
439
568
  /** Convenience lookups. */
440
569
  getSlide: (id: string) => Slide$1 | undefined;
441
570
  getElement: (slideId: string, elementId: string) => SlideElement | undefined;
@@ -496,4 +625,4 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
496
625
  type Option = Record<string, unknown>;
497
626
  declare function chartStarterOption(kind: ChartKind): Option;
498
627
 
499
- export { type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, builtinThemes, chartStarterOption, darkTheme, deckId, defaultTheme, defineTheme, elementId, nextId, reduce as reduceDeck, resolveTheme, slideId, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, vividTheme };
628
+ export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, type ParaReveal, PresenterView, type PresenterViewProps, ShapeElement, ShapeElementRenderer, type ShapeElementRendererProps, ShapeKind, Slide, SlideBackground, type SlideContextValue, Slide$1 as SlideData, SlideElement, type SlideKeyboardOptions, SlideLayout, type SlideProps, SlideRail, type SlideRailProps, SlideThumbnail, type SlideThumbnailProps, SlideTransition, SlideViewer, type SlideViewerProps, SpeakerNotes, type SpeakerNotesProps, TextElement, TextElementRenderer, type TextElementRendererProps, Theme, type UseDeckStateOptions, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };