@particle-academy/fancy-slides 0.1.7 → 0.2.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.cjs +156 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -5
- package/dist/index.d.ts +12 -5
- package/dist/index.js +157 -4
- package/dist/index.js.map +1 -1
- package/dist/registry.d.cts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/{types-Bc-psiRF.d.cts → types-B2ecrEAz.d.cts} +4 -0
- package/dist/{types-Bc-psiRF.d.ts → types-B2ecrEAz.d.ts} +4 -0
- package/package.json +1 -1
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, k as TextElement, I as ImageElement, S as ShapeElement, i as SlideLayout
|
|
4
|
-
export { C as ChartElement, a as CodeElement, b as DeckActivity, E as ElementBase, d as EmbedElement,
|
|
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';
|
|
5
5
|
|
|
6
6
|
interface SlideProps {
|
|
7
7
|
/** The slide to render. */
|
|
@@ -279,7 +279,7 @@ interface EditorToolbarProps {
|
|
|
279
279
|
declare function EditorToolbar({ title, onTitleChange, themeName, onApplyTheme, onInsertText, onInsertImage, onInsertShape, onInsertChart, onInsertCode, onInsertTable, onPresent, disabled, }: EditorToolbarProps): react_jsx_runtime.JSX.Element;
|
|
280
280
|
|
|
281
281
|
interface ElementInspectorProps {
|
|
282
|
-
/** Element being inspected. `null`
|
|
282
|
+
/** Element being inspected. `null` falls back to slide settings (or the empty state). */
|
|
283
283
|
element: SlideElement | null;
|
|
284
284
|
/** Patch a property on the element. */
|
|
285
285
|
onPatch: (patch: Partial<SlideElement>) => void;
|
|
@@ -287,6 +287,12 @@ interface ElementInspectorProps {
|
|
|
287
287
|
onDelete?: () => void;
|
|
288
288
|
/** Lock toggle. */
|
|
289
289
|
onLockToggle?: (locked: boolean) => void;
|
|
290
|
+
/** Selected slide — shown when no element is selected so the user can edit slide-level settings. */
|
|
291
|
+
slide?: Slide$1 | null;
|
|
292
|
+
/** Set the slide's entrance transition. */
|
|
293
|
+
onSetTransition?: (transition?: SlideTransition) => void;
|
|
294
|
+
/** Set the slide's background. */
|
|
295
|
+
onSetBackground?: (background?: SlideBackground) => void;
|
|
290
296
|
}
|
|
291
297
|
/**
|
|
292
298
|
* Right-hand inspector. Tabs split position + style + advanced properties.
|
|
@@ -294,7 +300,7 @@ interface ElementInspectorProps {
|
|
|
294
300
|
* react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
|
|
295
301
|
* `Action`.
|
|
296
302
|
*/
|
|
297
|
-
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
303
|
+
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
298
304
|
|
|
299
305
|
interface SpeakerNotesProps {
|
|
300
306
|
notes?: string;
|
|
@@ -413,6 +419,7 @@ interface DeckStateApi {
|
|
|
413
419
|
setLayout: (id: string, layout: SlideLayout) => void;
|
|
414
420
|
setNotes: (id: string, notes: string) => void;
|
|
415
421
|
setBackground: (id: string, bg?: SlideBackground) => void;
|
|
422
|
+
setTransition: (id: string, transition?: SlideTransition) => void;
|
|
416
423
|
/** Element-level helpers. */
|
|
417
424
|
addElement: (slideId: string, element: Omit<SlideElement, "id"> & {
|
|
418
425
|
id?: string;
|
|
@@ -481,4 +488,4 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
|
|
|
481
488
|
type Option = Record<string, unknown>;
|
|
482
489
|
declare function chartStarterOption(kind: ChartKind): Option;
|
|
483
490
|
|
|
484
|
-
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, 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 };
|
|
491
|
+
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 };
|
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, k as TextElement, I as ImageElement, S as ShapeElement, i as SlideLayout
|
|
4
|
-
export { C as ChartElement, a as CodeElement, b as DeckActivity, E as ElementBase, d as EmbedElement,
|
|
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';
|
|
5
5
|
|
|
6
6
|
interface SlideProps {
|
|
7
7
|
/** The slide to render. */
|
|
@@ -279,7 +279,7 @@ interface EditorToolbarProps {
|
|
|
279
279
|
declare function EditorToolbar({ title, onTitleChange, themeName, onApplyTheme, onInsertText, onInsertImage, onInsertShape, onInsertChart, onInsertCode, onInsertTable, onPresent, disabled, }: EditorToolbarProps): react_jsx_runtime.JSX.Element;
|
|
280
280
|
|
|
281
281
|
interface ElementInspectorProps {
|
|
282
|
-
/** Element being inspected. `null`
|
|
282
|
+
/** Element being inspected. `null` falls back to slide settings (or the empty state). */
|
|
283
283
|
element: SlideElement | null;
|
|
284
284
|
/** Patch a property on the element. */
|
|
285
285
|
onPatch: (patch: Partial<SlideElement>) => void;
|
|
@@ -287,6 +287,12 @@ interface ElementInspectorProps {
|
|
|
287
287
|
onDelete?: () => void;
|
|
288
288
|
/** Lock toggle. */
|
|
289
289
|
onLockToggle?: (locked: boolean) => void;
|
|
290
|
+
/** Selected slide — shown when no element is selected so the user can edit slide-level settings. */
|
|
291
|
+
slide?: Slide$1 | null;
|
|
292
|
+
/** Set the slide's entrance transition. */
|
|
293
|
+
onSetTransition?: (transition?: SlideTransition) => void;
|
|
294
|
+
/** Set the slide's background. */
|
|
295
|
+
onSetBackground?: (background?: SlideBackground) => void;
|
|
290
296
|
}
|
|
291
297
|
/**
|
|
292
298
|
* Right-hand inspector. Tabs split position + style + advanced properties.
|
|
@@ -294,7 +300,7 @@ interface ElementInspectorProps {
|
|
|
294
300
|
* react-fancy `Card`, `Tabs`, `Input`, `Select`, `Slider`, `ColorPicker`,
|
|
295
301
|
* `Action`.
|
|
296
302
|
*/
|
|
297
|
-
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
303
|
+
declare function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground }: ElementInspectorProps): react_jsx_runtime.JSX.Element;
|
|
298
304
|
|
|
299
305
|
interface SpeakerNotesProps {
|
|
300
306
|
notes?: string;
|
|
@@ -413,6 +419,7 @@ interface DeckStateApi {
|
|
|
413
419
|
setLayout: (id: string, layout: SlideLayout) => void;
|
|
414
420
|
setNotes: (id: string, notes: string) => void;
|
|
415
421
|
setBackground: (id: string, bg?: SlideBackground) => void;
|
|
422
|
+
setTransition: (id: string, transition?: SlideTransition) => void;
|
|
416
423
|
/** Element-level helpers. */
|
|
417
424
|
addElement: (slideId: string, element: Omit<SlideElement, "id"> & {
|
|
418
425
|
id?: string;
|
|
@@ -481,4 +488,4 @@ type ChartKind = "bar" | "line" | "pie" | "area" | "scatter";
|
|
|
481
488
|
type Option = Record<string, unknown>;
|
|
482
489
|
declare function chartStarterOption(kind: ChartKind): Option;
|
|
483
490
|
|
|
484
|
-
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, 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 };
|
|
491
|
+
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isDarkColor, SlideContext } from './chunk-WIUXPQAK.js';
|
|
2
2
|
export { useIsDarkSlide, useSlideContext, useSlideTheme } from './chunk-WIUXPQAK.js';
|
|
3
3
|
import { useId, useRef, useState, useEffect, useMemo, useCallback } from 'react';
|
|
4
|
-
import { ContentRenderer, Text, Action, ContextMenu, Separator, Tooltip, Dropdown, Badge, Heading, Tabs, Card,
|
|
4
|
+
import { ContentRenderer, Text, Action, ContextMenu, Separator, Tooltip, Dropdown, Badge, Heading, Tabs, Card, Select, Input, ColorPicker, Slider, Textarea } from '@particle-academy/react-fancy';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
// src/theme/default-theme.ts
|
|
@@ -611,6 +611,11 @@ function SlideViewer({
|
|
|
611
611
|
);
|
|
612
612
|
const [blanked, setBlanked] = useState(false);
|
|
613
613
|
const containerRef = useRef(null);
|
|
614
|
+
const prevIndexRef = useRef(index);
|
|
615
|
+
const forward = index >= prevIndexRef.current;
|
|
616
|
+
useEffect(() => {
|
|
617
|
+
prevIndexRef.current = index;
|
|
618
|
+
}, [index]);
|
|
614
619
|
useSlideKeyboard({
|
|
615
620
|
total: deck.slides.length,
|
|
616
621
|
index,
|
|
@@ -634,6 +639,8 @@ function SlideViewer({
|
|
|
634
639
|
const slide = deck.slides[index];
|
|
635
640
|
const theme = resolveTheme(deck.theme);
|
|
636
641
|
const aspectRatio = theme.aspectRatio ?? 16 / 9;
|
|
642
|
+
const transition = slide?.transition ?? theme.defaultTransition;
|
|
643
|
+
const enterStyle = transitionEnterStyle(transition, forward);
|
|
637
644
|
return /* @__PURE__ */ jsxs(
|
|
638
645
|
"div",
|
|
639
646
|
{
|
|
@@ -652,6 +659,7 @@ function SlideViewer({
|
|
|
652
659
|
tabIndex: 0,
|
|
653
660
|
"data-fancy-slides-viewer": deck.id,
|
|
654
661
|
children: [
|
|
662
|
+
/* @__PURE__ */ jsx("style", { children: TRANSITION_KEYFRAMES }),
|
|
655
663
|
!blanked && slide && /* @__PURE__ */ jsx(
|
|
656
664
|
"div",
|
|
657
665
|
{
|
|
@@ -663,7 +671,7 @@ function SlideViewer({
|
|
|
663
671
|
["--fs-ratio"]: aspectRatio.toString(),
|
|
664
672
|
boxShadow: "0 8px 30px rgba(0,0,0,0.35)"
|
|
665
673
|
},
|
|
666
|
-
children: /* @__PURE__ */ jsx(Slide, { slide, theme, renderElement })
|
|
674
|
+
children: /* @__PURE__ */ jsx("div", { className: "fs-slide-enter", style: enterStyle, children: /* @__PURE__ */ jsx(Slide, { slide, theme, renderElement }) }, index)
|
|
667
675
|
}
|
|
668
676
|
),
|
|
669
677
|
!hideChrome && !blanked && /* @__PURE__ */ jsxs(
|
|
@@ -693,6 +701,68 @@ function SlideViewer({
|
|
|
693
701
|
}
|
|
694
702
|
);
|
|
695
703
|
}
|
|
704
|
+
var DEFAULT_DURATION = 400;
|
|
705
|
+
var EASE = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
706
|
+
function transitionEnterStyle(transition, forward) {
|
|
707
|
+
const kind = transition?.kind ?? "none";
|
|
708
|
+
if (kind === "none") return { width: "100%", height: "100%" };
|
|
709
|
+
const duration = transition?.duration ?? DEFAULT_DURATION;
|
|
710
|
+
let name;
|
|
711
|
+
switch (kind) {
|
|
712
|
+
case "fade":
|
|
713
|
+
name = "fs-fade-in";
|
|
714
|
+
break;
|
|
715
|
+
case "zoom":
|
|
716
|
+
name = "fs-zoom-in";
|
|
717
|
+
break;
|
|
718
|
+
case "slide": {
|
|
719
|
+
const dir = transition?.direction ?? (forward ? "right" : "left");
|
|
720
|
+
name = `fs-slide-in-${dir}`;
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
default:
|
|
724
|
+
return { width: "100%", height: "100%" };
|
|
725
|
+
}
|
|
726
|
+
return {
|
|
727
|
+
width: "100%",
|
|
728
|
+
height: "100%",
|
|
729
|
+
animationName: name,
|
|
730
|
+
animationDuration: `${duration}ms`,
|
|
731
|
+
animationTimingFunction: EASE,
|
|
732
|
+
animationFillMode: "both"
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
var TRANSITION_KEYFRAMES = `
|
|
736
|
+
@media (prefers-reduced-motion: reduce) {
|
|
737
|
+
.fs-slide-enter { animation: none !important; }
|
|
738
|
+
}
|
|
739
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
740
|
+
@keyframes fs-fade-in {
|
|
741
|
+
from { opacity: 0; }
|
|
742
|
+
to { opacity: 1; }
|
|
743
|
+
}
|
|
744
|
+
@keyframes fs-zoom-in {
|
|
745
|
+
from { opacity: 0; transform: scale(0.92); }
|
|
746
|
+
to { opacity: 1; transform: scale(1); }
|
|
747
|
+
}
|
|
748
|
+
@keyframes fs-slide-in-right {
|
|
749
|
+
from { opacity: 0; transform: translateX(8%); }
|
|
750
|
+
to { opacity: 1; transform: translateX(0); }
|
|
751
|
+
}
|
|
752
|
+
@keyframes fs-slide-in-left {
|
|
753
|
+
from { opacity: 0; transform: translateX(-8%); }
|
|
754
|
+
to { opacity: 1; transform: translateX(0); }
|
|
755
|
+
}
|
|
756
|
+
@keyframes fs-slide-in-up {
|
|
757
|
+
from { opacity: 0; transform: translateY(8%); }
|
|
758
|
+
to { opacity: 1; transform: translateY(0); }
|
|
759
|
+
}
|
|
760
|
+
@keyframes fs-slide-in-down {
|
|
761
|
+
from { opacity: 0; transform: translateY(-8%); }
|
|
762
|
+
to { opacity: 1; transform: translateY(0); }
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
`;
|
|
696
766
|
function PresenterView({
|
|
697
767
|
deck,
|
|
698
768
|
index: controlledIndex,
|
|
@@ -1046,6 +1116,7 @@ function useDeckState({ value, onChange, onOp }) {
|
|
|
1046
1116
|
setLayout: (id, layout) => apply({ kind: "slide_set_layout", id, layout }),
|
|
1047
1117
|
setNotes: (id, notes) => apply({ kind: "slide_set_notes", id, notes }),
|
|
1048
1118
|
setBackground: (id, background) => apply({ kind: "slide_set_background", id, background }),
|
|
1119
|
+
setTransition: (id, transition) => apply({ kind: "slide_set_transition", id, transition }),
|
|
1049
1120
|
addElement: (slideId2, element) => {
|
|
1050
1121
|
const id = element.id ?? elementId();
|
|
1051
1122
|
apply({ kind: "element_add", slideId: slideId2, element: { ...element, id } });
|
|
@@ -1087,6 +1158,8 @@ function reduce(deck, op) {
|
|
|
1087
1158
|
return { ...deck, slides: deck.slides.map((s) => s.id === op.id ? { ...s, notes: op.notes } : s) };
|
|
1088
1159
|
case "slide_set_background":
|
|
1089
1160
|
return { ...deck, slides: deck.slides.map((s) => s.id === op.id ? { ...s, background: op.background } : s) };
|
|
1161
|
+
case "slide_set_transition":
|
|
1162
|
+
return { ...deck, slides: deck.slides.map((s) => s.id === op.id ? { ...s, transition: op.transition } : s) };
|
|
1090
1163
|
case "element_add":
|
|
1091
1164
|
return {
|
|
1092
1165
|
...deck,
|
|
@@ -1354,8 +1427,11 @@ function EditorToolbar({
|
|
|
1354
1427
|
/* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-2", children: /* @__PURE__ */ jsx(Tooltip, { content: "Present (F)", children: /* @__PURE__ */ jsx(Action, { color: "violet", size: "sm", icon: "play", onClick: onPresent, children: "Present" }) }) })
|
|
1355
1428
|
] });
|
|
1356
1429
|
}
|
|
1357
|
-
function ElementInspector({ element, onPatch, onDelete, onLockToggle }) {
|
|
1430
|
+
function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground }) {
|
|
1358
1431
|
if (!element) {
|
|
1432
|
+
if (slide) {
|
|
1433
|
+
return /* @__PURE__ */ jsx(SlideSettings, { slide, onSetTransition, onSetBackground });
|
|
1434
|
+
}
|
|
1359
1435
|
return /* @__PURE__ */ jsxs("div", { className: "fs-inspector flex h-full flex-col border-l border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
1360
1436
|
/* @__PURE__ */ jsx(Heading, { as: "h3", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Inspector" }),
|
|
1361
1437
|
/* @__PURE__ */ jsx(Text, { size: "sm", className: "mt-2 !text-zinc-500", children: "Select an element to edit its properties." })
|
|
@@ -1389,6 +1465,80 @@ function ElementInspector({ element, onPatch, onDelete, onLockToggle }) {
|
|
|
1389
1465
|
] }) })
|
|
1390
1466
|
] });
|
|
1391
1467
|
}
|
|
1468
|
+
function SlideSettings({
|
|
1469
|
+
slide,
|
|
1470
|
+
onSetTransition,
|
|
1471
|
+
onSetBackground
|
|
1472
|
+
}) {
|
|
1473
|
+
const transition = slide.transition;
|
|
1474
|
+
const kind = transition?.kind ?? "none";
|
|
1475
|
+
const setTransition = (next) => {
|
|
1476
|
+
const merged = { kind, duration: transition?.duration, direction: transition?.direction, ...next };
|
|
1477
|
+
onSetTransition?.(merged.kind === "none" ? { kind: "none" } : merged);
|
|
1478
|
+
};
|
|
1479
|
+
return /* @__PURE__ */ jsxs("div", { className: "fs-inspector flex h-full w-full flex-col border-l border-zinc-200 bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
1480
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between border-b border-zinc-200 px-3 py-2 dark:border-zinc-800", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1481
|
+
/* @__PURE__ */ jsx(Heading, { as: "h3", size: "xs", className: "!font-mono !uppercase !tracking-wider !text-zinc-500", children: "slide" }),
|
|
1482
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", className: "!font-mono !text-zinc-400", children: [
|
|
1483
|
+
"#",
|
|
1484
|
+
slide.id.slice(-6)
|
|
1485
|
+
] })
|
|
1486
|
+
] }) }),
|
|
1487
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-3", children: [
|
|
1488
|
+
/* @__PURE__ */ jsx(Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1489
|
+
/* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Transition" }),
|
|
1490
|
+
/* @__PURE__ */ jsx(
|
|
1491
|
+
Select,
|
|
1492
|
+
{
|
|
1493
|
+
label: "Kind",
|
|
1494
|
+
list: [
|
|
1495
|
+
{ value: "none", label: "None" },
|
|
1496
|
+
{ value: "fade", label: "Fade" },
|
|
1497
|
+
{ value: "slide", label: "Slide" },
|
|
1498
|
+
{ value: "zoom", label: "Zoom" }
|
|
1499
|
+
],
|
|
1500
|
+
value: kind,
|
|
1501
|
+
onValueChange: (v) => setTransition({ kind: v })
|
|
1502
|
+
}
|
|
1503
|
+
),
|
|
1504
|
+
kind === "slide" && /* @__PURE__ */ jsx(
|
|
1505
|
+
Select,
|
|
1506
|
+
{
|
|
1507
|
+
label: "Direction",
|
|
1508
|
+
list: [
|
|
1509
|
+
{ value: "left", label: "From left" },
|
|
1510
|
+
{ value: "right", label: "From right" },
|
|
1511
|
+
{ value: "up", label: "From bottom" },
|
|
1512
|
+
{ value: "down", label: "From top" }
|
|
1513
|
+
],
|
|
1514
|
+
value: transition?.direction ?? "right",
|
|
1515
|
+
onValueChange: (v) => setTransition({ direction: v })
|
|
1516
|
+
}
|
|
1517
|
+
),
|
|
1518
|
+
kind !== "none" && /* @__PURE__ */ jsx(
|
|
1519
|
+
Input,
|
|
1520
|
+
{
|
|
1521
|
+
label: "Duration (ms)",
|
|
1522
|
+
type: "number",
|
|
1523
|
+
value: String(transition?.duration ?? 400),
|
|
1524
|
+
onChange: (e) => setTransition({ duration: parseInt(e.target.value, 10) || 400 })
|
|
1525
|
+
}
|
|
1526
|
+
),
|
|
1527
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", className: "!text-zinc-500", children: "Entrance animation played when this slide appears in the viewer. Falls back to the theme default. Honors prefers-reduced-motion." })
|
|
1528
|
+
] }) }),
|
|
1529
|
+
onSetBackground && /* @__PURE__ */ jsx(Card, { padding: "md", className: "mt-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1530
|
+
/* @__PURE__ */ jsx(Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Background" }),
|
|
1531
|
+
/* @__PURE__ */ jsx(FieldLabel, { label: "Color", children: /* @__PURE__ */ jsx(
|
|
1532
|
+
ColorPicker,
|
|
1533
|
+
{
|
|
1534
|
+
value: slide.background?.color ?? "#ffffff",
|
|
1535
|
+
onChange: (c) => onSetBackground({ ...slide.background, color: c })
|
|
1536
|
+
}
|
|
1537
|
+
) })
|
|
1538
|
+
] }) })
|
|
1539
|
+
] })
|
|
1540
|
+
] });
|
|
1541
|
+
}
|
|
1392
1542
|
function LayoutSection({ element, onPatch }) {
|
|
1393
1543
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1394
1544
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
@@ -1838,13 +1988,16 @@ function DeckEditor({
|
|
|
1838
1988
|
ElementInspector,
|
|
1839
1989
|
{
|
|
1840
1990
|
element: selectedElement,
|
|
1991
|
+
slide: slide ?? null,
|
|
1841
1992
|
onPatch: (patch) => slide && elementIdSelected && ops.updateElement(slide.id, elementIdSelected, patch),
|
|
1842
1993
|
onDelete: () => {
|
|
1843
1994
|
if (!slide || !elementIdSelected) return;
|
|
1844
1995
|
ops.removeElement(slide.id, elementIdSelected);
|
|
1845
1996
|
setElementIdSelected(null);
|
|
1846
1997
|
},
|
|
1847
|
-
onLockToggle: (locked) => slide && elementIdSelected && ops.updateElement(slide.id, elementIdSelected, { locked })
|
|
1998
|
+
onLockToggle: (locked) => slide && elementIdSelected && ops.updateElement(slide.id, elementIdSelected, { locked }),
|
|
1999
|
+
onSetTransition: (transition) => slide && ops.setTransition(slide.id, transition),
|
|
2000
|
+
onSetBackground: (background) => slide && ops.setBackground(slide.id, background)
|
|
1848
2001
|
}
|
|
1849
2002
|
) })
|
|
1850
2003
|
] }),
|