@particle-academy/fancy-slides 0.9.0 → 0.10.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 { i as Slide$1, p as Theme, k as SlideElement, D as Deck, d as DeckOp, h as ShapeKind, m as SlideTransition, j as SlideBackground, l as SlideLayout, E as ElementAnimation, n as TextElement, I as ImageElement, g as ShapeElement } from './types-2yYMJPhi.cjs';
4
- export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, S as SCHEMA_VERSION, T as TableElement, o as TextStyle, q as ThemeColors, r as ThemeFonts, s as TransitionKind } from './types-2yYMJPhi.cjs';
3
+ import { i as Slide$1, p as Theme, k as SlideElement, D as Deck, d as DeckOp, h as ShapeKind, m as SlideTransition, j as SlideBackground, l as SlideLayout, E as ElementAnimation, n as TextElement, I as ImageElement, g as ShapeElement } from './types-C3w37g3A.cjs';
4
+ export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, S as SCHEMA_VERSION, T as TableElement, o as TextStyle, q as ThemeColors, r as ThemeFonts, s as TransitionKind } from './types-C3w37g3A.cjs';
5
5
  import { EditorAction } from '@particle-academy/react-fancy';
6
6
 
7
7
  interface SlideProps {
@@ -594,6 +594,8 @@ interface DeckStateApi {
594
594
  /** Deck-level helpers. */
595
595
  setTitle: (title: string) => void;
596
596
  applyTheme: (theme: Theme) => void;
597
+ /** Replace the entire deck — stream a full presentation in atomically. */
598
+ setDeck: (deck: Deck) => void;
597
599
  /** Slide-level helpers. */
598
600
  addSlide: (index?: number, partial?: Partial<Slide$1>) => string;
599
601
  duplicateSlide: (id: string) => string;
@@ -673,4 +675,43 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
673
675
  type Option = Record<string, unknown>;
674
676
  declare function chartStarterOption(kind: ChartKind): Option;
675
677
 
676
- 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, PRESENTATION_EDITOR_ACTIONS, 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, normalizeSlideMarkdown, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };
678
+ /**
679
+ * Stream a full presentation in and out. The `Deck` is already plain JSON
680
+ * (no functions, no React children), so "serialize" is mostly `JSON.stringify`
681
+ * — these helpers add the schema-version stamp, a forgiving structural
682
+ * validation, and a forward-migration shim so a host can persist a deck, hand
683
+ * it to an agent, and load it back safely.
684
+ *
685
+ * Streaming OUT: read `value` / `onChange` from the controlled editor, or call
686
+ * `serializeDeck(deck)`.
687
+ * Streaming IN: `parseDeck(json)` → feed to `DeckEditor`'s `value`, or apply a
688
+ * `{ kind: "deck_set", deck }` op (also exposed as the bridge's `deck_set` tool).
689
+ */
690
+
691
+ interface DeckValidation {
692
+ ok: boolean;
693
+ errors: string[];
694
+ }
695
+ /**
696
+ * Structurally validate a deck. Forgiving by design — it checks the shape an
697
+ * editor / writer relies on (ids, slides array, element types + 0..1 geometry),
698
+ * not every optional field. Returns all problems found rather than throwing.
699
+ */
700
+ declare function validateDeck(deck: unknown): DeckValidation;
701
+ /**
702
+ * Migrate a deck authored against an older schema version forward to the
703
+ * current one. Today it only stamps the version (no breaking changes yet); the
704
+ * `switch` is where future migrations slot in, each bumping `version` by one.
705
+ */
706
+ declare function migrateDeck(deck: Deck): Deck;
707
+ /** Serialize a deck to a JSON string, stamping the current schema version. */
708
+ declare function serializeDeck(deck: Deck, pretty?: boolean): string;
709
+ /**
710
+ * Parse a deck from a JSON string (or an already-parsed object), migrating it
711
+ * forward and validating its structure. Throws a descriptive error when the
712
+ * JSON is malformed or the structure is invalid — callers streaming untrusted
713
+ * input should try/catch.
714
+ */
715
+ declare function parseDeck(input: string | unknown): Deck;
716
+
717
+ export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, type DeckValidation, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, PRESENTATION_EDITOR_ACTIONS, 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, migrateDeck, nextId, normalizeSlideMarkdown, paragraphReveals, parseDeck, reduce as reduceDeck, resolveTheme, serializeDeck, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, validateDeck, 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 { i as Slide$1, p as Theme, k as SlideElement, D as Deck, d as DeckOp, h as ShapeKind, m as SlideTransition, j as SlideBackground, l as SlideLayout, E as ElementAnimation, n as TextElement, I as ImageElement, g as ShapeElement } from './types-2yYMJPhi.js';
4
- export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, S as SCHEMA_VERSION, T as TableElement, o as TextStyle, q as ThemeColors, r as ThemeFonts, s as TransitionKind } from './types-2yYMJPhi.js';
3
+ import { i as Slide$1, p as Theme, k as SlideElement, D as Deck, d as DeckOp, h as ShapeKind, m as SlideTransition, j as SlideBackground, l as SlideLayout, E as ElementAnimation, n as TextElement, I as ImageElement, g as ShapeElement } from './types-C3w37g3A.js';
4
+ export { A as AnimationEffect, a as AnimationTrigger, C as ChartElement, b as CodeElement, c as DeckActivity, e as ElementBase, f as EmbedElement, S as SCHEMA_VERSION, T as TableElement, o as TextStyle, q as ThemeColors, r as ThemeFonts, s as TransitionKind } from './types-C3w37g3A.js';
5
5
  import { EditorAction } from '@particle-academy/react-fancy';
6
6
 
7
7
  interface SlideProps {
@@ -594,6 +594,8 @@ interface DeckStateApi {
594
594
  /** Deck-level helpers. */
595
595
  setTitle: (title: string) => void;
596
596
  applyTheme: (theme: Theme) => void;
597
+ /** Replace the entire deck — stream a full presentation in atomically. */
598
+ setDeck: (deck: Deck) => void;
597
599
  /** Slide-level helpers. */
598
600
  addSlide: (index?: number, partial?: Partial<Slide$1>) => string;
599
601
  duplicateSlide: (id: string) => string;
@@ -673,4 +675,43 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
673
675
  type Option = Record<string, unknown>;
674
676
  declare function chartStarterOption(kind: ChartKind): Option;
675
677
 
676
- 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, PRESENTATION_EDITOR_ACTIONS, 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, normalizeSlideMarkdown, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, visibleElementIds, vividTheme };
678
+ /**
679
+ * Stream a full presentation in and out. The `Deck` is already plain JSON
680
+ * (no functions, no React children), so "serialize" is mostly `JSON.stringify`
681
+ * — these helpers add the schema-version stamp, a forgiving structural
682
+ * validation, and a forward-migration shim so a host can persist a deck, hand
683
+ * it to an agent, and load it back safely.
684
+ *
685
+ * Streaming OUT: read `value` / `onChange` from the controlled editor, or call
686
+ * `serializeDeck(deck)`.
687
+ * Streaming IN: `parseDeck(json)` → feed to `DeckEditor`'s `value`, or apply a
688
+ * `{ kind: "deck_set", deck }` op (also exposed as the bridge's `deck_set` tool).
689
+ */
690
+
691
+ interface DeckValidation {
692
+ ok: boolean;
693
+ errors: string[];
694
+ }
695
+ /**
696
+ * Structurally validate a deck. Forgiving by design — it checks the shape an
697
+ * editor / writer relies on (ids, slides array, element types + 0..1 geometry),
698
+ * not every optional field. Returns all problems found rather than throwing.
699
+ */
700
+ declare function validateDeck(deck: unknown): DeckValidation;
701
+ /**
702
+ * Migrate a deck authored against an older schema version forward to the
703
+ * current one. Today it only stamps the version (no breaking changes yet); the
704
+ * `switch` is where future migrations slot in, each bumping `version` by one.
705
+ */
706
+ declare function migrateDeck(deck: Deck): Deck;
707
+ /** Serialize a deck to a JSON string, stamping the current schema version. */
708
+ declare function serializeDeck(deck: Deck, pretty?: boolean): string;
709
+ /**
710
+ * Parse a deck from a JSON string (or an already-parsed object), migrating it
711
+ * forward and validating its structure. Throws a descriptive error when the
712
+ * JSON is malformed or the structure is invalid — callers streaming untrusted
713
+ * input should try/catch.
714
+ */
715
+ declare function parseDeck(input: string | unknown): Deck;
716
+
717
+ export { type Build, type BuildStep, type ChartKind$1 as ChartKind, Deck, DeckEditor, type DeckEditorProps, DeckOp, type DeckStateApi, type DeckValidation, EditorToolbar, type EditorToolbarProps, ElementAnimation, ElementInspector, type ElementInspectorProps, ImageElement, ImageElementRenderer, type ImageElementRendererProps, PRESENTATION_EDITOR_ACTIONS, 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, migrateDeck, nextId, normalizeSlideMarkdown, paragraphReveals, parseDeck, reduce as reduceDeck, resolveTheme, serializeDeck, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useIsDarkSlide, useSlideContext, useSlideKeyboard, useSlideTheme, validateDeck, visibleElementIds, vividTheme };
package/dist/index.js CHANGED
@@ -1542,6 +1542,7 @@ function useDeckState({ value, onChange, onOp }) {
1542
1542
  apply,
1543
1543
  setTitle: (title) => apply({ kind: "deck_set_title", title }),
1544
1544
  applyTheme: (theme) => apply({ kind: "deck_apply_theme", theme }),
1545
+ setDeck: (deck) => apply({ kind: "deck_set", deck }),
1545
1546
  addSlide: (index, partial) => {
1546
1547
  const id = partial?.id ?? slideId();
1547
1548
  const slide = {
@@ -1596,6 +1597,8 @@ function reduce(deck, op) {
1596
1597
  return { ...deck, title: op.title };
1597
1598
  case "deck_apply_theme":
1598
1599
  return { ...deck, theme: op.theme };
1600
+ case "deck_set":
1601
+ return op.deck;
1599
1602
  case "slide_add": {
1600
1603
  const slides = [...deck.slides];
1601
1604
  slides.splice(Math.max(0, Math.min(slides.length, op.index)), 0, op.slide);
@@ -3106,6 +3109,74 @@ function DeckEditor({
3106
3109
  // src/types.ts
3107
3110
  var SCHEMA_VERSION = 1;
3108
3111
 
3109
- export { DeckEditor, EditorToolbar, ElementInspector, ImageElementRenderer, PRESENTATION_EDITOR_ACTIONS, PresenterView, SCHEMA_VERSION, ShapeElementRenderer, Slide, SlideRail, SlideThumbnail, SlideViewer, SpeakerNotes, TextElementRenderer, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, nextId, normalizeSlideMarkdown, paragraphReveals, reduce as reduceDeck, resolveTheme, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useSlideKeyboard, visibleElementIds, vividTheme };
3112
+ // src/utils/serialize.ts
3113
+ var ELEMENT_TYPES = ["text", "image", "chart", "code", "table", "shape", "embed"];
3114
+ function validateDeck(deck) {
3115
+ const errors = [];
3116
+ const d = deck;
3117
+ if (!d || typeof d !== "object") {
3118
+ return { ok: false, errors: ["deck is not an object"] };
3119
+ }
3120
+ if (typeof d.id !== "string" || !d.id) errors.push("deck.id must be a non-empty string");
3121
+ if (typeof d.title !== "string") errors.push("deck.title must be a string");
3122
+ if (!d.theme || typeof d.theme !== "object") errors.push("deck.theme must be an object");
3123
+ if (!Array.isArray(d.slides)) {
3124
+ errors.push("deck.slides must be an array");
3125
+ return { ok: errors.length === 0, errors };
3126
+ }
3127
+ d.slides.forEach((slide, si) => {
3128
+ if (!slide || typeof slide !== "object") {
3129
+ errors.push(`slides[${si}] is not an object`);
3130
+ return;
3131
+ }
3132
+ if (typeof slide.id !== "string" || !slide.id) errors.push(`slides[${si}].id must be a non-empty string`);
3133
+ if (!Array.isArray(slide.elements)) {
3134
+ errors.push(`slides[${si}].elements must be an array`);
3135
+ return;
3136
+ }
3137
+ slide.elements.forEach((el, ei) => {
3138
+ const where = `slides[${si}].elements[${ei}]`;
3139
+ if (!el || typeof el !== "object") {
3140
+ errors.push(`${where} is not an object`);
3141
+ return;
3142
+ }
3143
+ if (typeof el.id !== "string" || !el.id) errors.push(`${where}.id must be a non-empty string`);
3144
+ if (!ELEMENT_TYPES.includes(el.type)) errors.push(`${where}.type "${el.type}" is not a known element type`);
3145
+ for (const k of ["x", "y", "w", "h"]) {
3146
+ const v = el[k];
3147
+ if (typeof v !== "number" || v < 0 || v > 1) errors.push(`${where}.${k} must be a number in 0..1`);
3148
+ }
3149
+ });
3150
+ });
3151
+ return { ok: errors.length === 0, errors };
3152
+ }
3153
+ function migrateDeck(deck) {
3154
+ let d = deck;
3155
+ d.version ?? 1;
3156
+ return d.version === SCHEMA_VERSION ? d : { ...d, version: SCHEMA_VERSION };
3157
+ }
3158
+ function serializeDeck(deck, pretty = false) {
3159
+ const stamped = deck.version === SCHEMA_VERSION ? deck : { ...deck, version: SCHEMA_VERSION };
3160
+ return JSON.stringify(stamped, null, pretty ? 2 : void 0);
3161
+ }
3162
+ function parseDeck(input) {
3163
+ let raw;
3164
+ if (typeof input === "string") {
3165
+ try {
3166
+ raw = JSON.parse(input);
3167
+ } catch (e) {
3168
+ throw new Error(`parseDeck: invalid JSON \u2014 ${e.message}`);
3169
+ }
3170
+ } else {
3171
+ raw = input;
3172
+ }
3173
+ const result = validateDeck(raw);
3174
+ if (!result.ok) {
3175
+ throw new Error(`parseDeck: invalid deck \u2014 ${result.errors.join("; ")}`);
3176
+ }
3177
+ return migrateDeck(raw);
3178
+ }
3179
+
3180
+ export { DeckEditor, EditorToolbar, ElementInspector, ImageElementRenderer, PRESENTATION_EDITOR_ACTIONS, PresenterView, SCHEMA_VERSION, ShapeElementRenderer, Slide, SlideRail, SlideThumbnail, SlideViewer, SpeakerNotes, TextElementRenderer, buildSteps, buildsForStep, builtinThemes, chartStarterOption, collectBuilds, darkTheme, deckId, defaultTheme, defineTheme, elementId, isByParagraph, migrateDeck, nextId, normalizeSlideMarkdown, paragraphReveals, parseDeck, reduce as reduceDeck, resolveTheme, serializeDeck, slideId, splitParagraphs, stepDelays, totalBuildSteps, useDeckState, useSlideKeyboard, validateDeck, visibleElementIds, vividTheme };
3110
3181
  //# sourceMappingURL=index.js.map
3111
3182
  //# sourceMappingURL=index.js.map