@particle-academy/fancy-slides 0.3.0 → 0.4.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/README.md +26 -0
- package/dist/index.cjs +460 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -9
- package/dist/index.d.ts +97 -9
- package/dist/index.js +455 -40
- package/dist/index.js.map +1 -1
- package/dist/registry.d.cts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/{types-B2ecrEAz.d.cts → types-P-9MmnGU.d.cts} +32 -1
- package/dist/{types-B2ecrEAz.d.ts → types-P-9MmnGU.d.ts} +32 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -72,6 +72,79 @@ function resolveTheme(theme) {
|
|
|
72
72
|
function cn(...parts) {
|
|
73
73
|
return parts.filter(Boolean).join(" ");
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
// src/utils/builds.ts
|
|
77
|
+
var DEFAULT_BUILD_DURATION = 500;
|
|
78
|
+
function collectBuilds(slide) {
|
|
79
|
+
if (!slide) return [];
|
|
80
|
+
const builds = [];
|
|
81
|
+
slide.elements.forEach((element, index) => {
|
|
82
|
+
if (element.animation) {
|
|
83
|
+
builds.push({ element, animation: element.animation, index });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return builds.sort((a, b) => {
|
|
87
|
+
const ao = a.animation.order ?? 0;
|
|
88
|
+
const bo = b.animation.order ?? 0;
|
|
89
|
+
if (ao !== bo) return ao - bo;
|
|
90
|
+
return a.index - b.index;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function buildSteps(slide) {
|
|
94
|
+
const builds = collectBuilds(slide);
|
|
95
|
+
const steps = [];
|
|
96
|
+
for (const build of builds) {
|
|
97
|
+
const trigger = build.animation.trigger ?? "on-click";
|
|
98
|
+
if (steps.length === 0 || trigger === "on-click") {
|
|
99
|
+
steps.push({ builds: [build] });
|
|
100
|
+
} else {
|
|
101
|
+
steps[steps.length - 1].builds.push(build);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return steps;
|
|
105
|
+
}
|
|
106
|
+
function totalBuildSteps(slide) {
|
|
107
|
+
return buildSteps(slide).length;
|
|
108
|
+
}
|
|
109
|
+
function visibleElementIds(slide, buildStep) {
|
|
110
|
+
const visible = /* @__PURE__ */ new Set();
|
|
111
|
+
if (!slide) return visible;
|
|
112
|
+
const steps = buildSteps(slide);
|
|
113
|
+
const stepOfElement = /* @__PURE__ */ new Map();
|
|
114
|
+
steps.forEach((step, i) => {
|
|
115
|
+
for (const b of step.builds) stepOfElement.set(b.element.id, i + 1);
|
|
116
|
+
});
|
|
117
|
+
for (const element of slide.elements) {
|
|
118
|
+
const revealStep = stepOfElement.get(element.id);
|
|
119
|
+
if (revealStep === void 0) {
|
|
120
|
+
visible.add(element.id);
|
|
121
|
+
} else if (buildStep >= revealStep) {
|
|
122
|
+
visible.add(element.id);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return visible;
|
|
126
|
+
}
|
|
127
|
+
function buildsForStep(slide, buildStep) {
|
|
128
|
+
const steps = buildSteps(slide);
|
|
129
|
+
const step = steps[buildStep - 1];
|
|
130
|
+
return step ? step.builds : [];
|
|
131
|
+
}
|
|
132
|
+
function stepDelays(builds) {
|
|
133
|
+
const delays = /* @__PURE__ */ new Map();
|
|
134
|
+
const lead = builds[0];
|
|
135
|
+
if (!lead) return delays;
|
|
136
|
+
const leadDelay = lead.animation.delay ?? 0;
|
|
137
|
+
const leadDuration = lead.animation.duration ?? DEFAULT_BUILD_DURATION;
|
|
138
|
+
delays.set(lead.element.id, leadDelay);
|
|
139
|
+
for (let i = 1; i < builds.length; i++) {
|
|
140
|
+
const b = builds[i];
|
|
141
|
+
const own = b.animation.delay ?? 0;
|
|
142
|
+
const trigger = b.animation.trigger ?? "on-click";
|
|
143
|
+
const base = trigger === "after-prev" ? leadDelay + leadDuration : leadDelay;
|
|
144
|
+
delays.set(b.element.id, base + own);
|
|
145
|
+
}
|
|
146
|
+
return delays;
|
|
147
|
+
}
|
|
75
148
|
function TextElementRenderer({
|
|
76
149
|
element,
|
|
77
150
|
theme,
|
|
@@ -280,12 +353,94 @@ function relativeLuminance(r, g, b) {
|
|
|
280
353
|
};
|
|
281
354
|
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
282
355
|
}
|
|
356
|
+
|
|
357
|
+
// src/components/Slide/builds-style.ts
|
|
358
|
+
var DEFAULT_BUILD_DURATION2 = 500;
|
|
359
|
+
var EASE = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
360
|
+
function buildEnterStyle(animation, effectiveDelay) {
|
|
361
|
+
const duration = animation.duration ?? DEFAULT_BUILD_DURATION2;
|
|
362
|
+
const dir = animation.direction ?? "left";
|
|
363
|
+
let name;
|
|
364
|
+
switch (animation.effect) {
|
|
365
|
+
case "fade":
|
|
366
|
+
name = "fs-build-fade";
|
|
367
|
+
break;
|
|
368
|
+
case "zoom":
|
|
369
|
+
name = "fs-build-zoom";
|
|
370
|
+
break;
|
|
371
|
+
case "fly-in":
|
|
372
|
+
name = `fs-build-fly-${dir}`;
|
|
373
|
+
break;
|
|
374
|
+
case "wipe":
|
|
375
|
+
name = `fs-build-wipe-${dir}`;
|
|
376
|
+
break;
|
|
377
|
+
default:
|
|
378
|
+
name = "fs-build-fade";
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
animationName: name,
|
|
382
|
+
animationDuration: `${duration}ms`,
|
|
383
|
+
animationDelay: `${effectiveDelay}ms`,
|
|
384
|
+
animationTimingFunction: EASE,
|
|
385
|
+
animationFillMode: "both"
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
var BUILD_KEYFRAMES = `
|
|
389
|
+
@media (prefers-reduced-motion: reduce) {
|
|
390
|
+
.fs-build-enter { animation: none !important; }
|
|
391
|
+
}
|
|
392
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
393
|
+
@keyframes fs-build-fade {
|
|
394
|
+
from { opacity: 0; }
|
|
395
|
+
to { opacity: 1; }
|
|
396
|
+
}
|
|
397
|
+
@keyframes fs-build-zoom {
|
|
398
|
+
from { opacity: 0; transform: scale(0.8); }
|
|
399
|
+
to { opacity: 1; transform: scale(1); }
|
|
400
|
+
}
|
|
401
|
+
@keyframes fs-build-fly-left {
|
|
402
|
+
from { opacity: 0; transform: translateX(-24%); }
|
|
403
|
+
to { opacity: 1; transform: translateX(0); }
|
|
404
|
+
}
|
|
405
|
+
@keyframes fs-build-fly-right {
|
|
406
|
+
from { opacity: 0; transform: translateX(24%); }
|
|
407
|
+
to { opacity: 1; transform: translateX(0); }
|
|
408
|
+
}
|
|
409
|
+
@keyframes fs-build-fly-up {
|
|
410
|
+
from { opacity: 0; transform: translateY(24%); }
|
|
411
|
+
to { opacity: 1; transform: translateY(0); }
|
|
412
|
+
}
|
|
413
|
+
@keyframes fs-build-fly-down {
|
|
414
|
+
from { opacity: 0; transform: translateY(-24%); }
|
|
415
|
+
to { opacity: 1; transform: translateY(0); }
|
|
416
|
+
}
|
|
417
|
+
/* wipe: clip-path inset reveals from the named edge toward the opposite one.
|
|
418
|
+
inset(top right bottom left) \u2014 start fully clipped on the far side. */
|
|
419
|
+
@keyframes fs-build-wipe-left {
|
|
420
|
+
from { clip-path: inset(0 100% 0 0); }
|
|
421
|
+
to { clip-path: inset(0 0 0 0); }
|
|
422
|
+
}
|
|
423
|
+
@keyframes fs-build-wipe-right {
|
|
424
|
+
from { clip-path: inset(0 0 0 100%); }
|
|
425
|
+
to { clip-path: inset(0 0 0 0); }
|
|
426
|
+
}
|
|
427
|
+
@keyframes fs-build-wipe-up {
|
|
428
|
+
from { clip-path: inset(100% 0 0 0); }
|
|
429
|
+
to { clip-path: inset(0 0 0 0); }
|
|
430
|
+
}
|
|
431
|
+
@keyframes fs-build-wipe-down {
|
|
432
|
+
from { clip-path: inset(0 0 100% 0); }
|
|
433
|
+
to { clip-path: inset(0 0 0 0); }
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
`;
|
|
283
437
|
function Slide({
|
|
284
438
|
slide,
|
|
285
439
|
theme,
|
|
286
440
|
width,
|
|
287
441
|
aspectRatio,
|
|
288
442
|
editing = false,
|
|
443
|
+
buildStep,
|
|
289
444
|
onElementContentChange,
|
|
290
445
|
onElementSelect,
|
|
291
446
|
selectedElementId,
|
|
@@ -329,7 +484,21 @@ function Slide({
|
|
|
329
484
|
}),
|
|
330
485
|
[t, effectiveBg, slideWidthPx]
|
|
331
486
|
);
|
|
332
|
-
|
|
487
|
+
const buildInfo = react.useMemo(() => {
|
|
488
|
+
if (editing) return null;
|
|
489
|
+
const steps = buildSteps(slide);
|
|
490
|
+
if (steps.length === 0) return null;
|
|
491
|
+
const revealStep = /* @__PURE__ */ new Map();
|
|
492
|
+
steps.forEach((step, i) => {
|
|
493
|
+
for (const b of step.builds) revealStep.set(b.element.id, i + 1);
|
|
494
|
+
});
|
|
495
|
+
const driven = buildStep !== void 0;
|
|
496
|
+
const currentStep = driven ? buildStep : steps.length;
|
|
497
|
+
const firing = driven ? steps[currentStep - 1] : void 0;
|
|
498
|
+
const delays = firing ? stepDelays(firing.builds) : /* @__PURE__ */ new Map();
|
|
499
|
+
return { revealStep, currentStep, delays };
|
|
500
|
+
}, [editing, slide, buildStep]);
|
|
501
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SlideContext.Provider, { value: slideContext, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
333
502
|
"div",
|
|
334
503
|
{
|
|
335
504
|
ref,
|
|
@@ -347,23 +516,45 @@ function Slide({
|
|
|
347
516
|
onClick: (e) => {
|
|
348
517
|
if (e.target === e.currentTarget && onElementSelect) onElementSelect(null);
|
|
349
518
|
},
|
|
350
|
-
children:
|
|
351
|
-
|
|
352
|
-
{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
519
|
+
children: [
|
|
520
|
+
buildInfo && /* @__PURE__ */ jsxRuntime.jsx("style", { children: BUILD_KEYFRAMES }),
|
|
521
|
+
orderedElements(slide.elements).map((element) => {
|
|
522
|
+
let buildHidden = false;
|
|
523
|
+
let buildAnimation;
|
|
524
|
+
let buildDelay = 0;
|
|
525
|
+
if (buildInfo) {
|
|
526
|
+
const step = buildInfo.revealStep.get(element.id);
|
|
527
|
+
if (step !== void 0) {
|
|
528
|
+
if (buildInfo.currentStep < step) {
|
|
529
|
+
buildHidden = true;
|
|
530
|
+
} else if (buildInfo.currentStep === step && element.animation) {
|
|
531
|
+
buildAnimation = element.animation;
|
|
532
|
+
buildDelay = buildInfo.delays.get(element.id) ?? 0;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (buildHidden) return null;
|
|
537
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
538
|
+
SlideElementHost,
|
|
539
|
+
{
|
|
540
|
+
element,
|
|
541
|
+
theme: t,
|
|
542
|
+
slideWidthPx,
|
|
543
|
+
slideHeightPx,
|
|
544
|
+
editing,
|
|
545
|
+
selected: selectedElementId === element.id,
|
|
546
|
+
onContentChange: onElementContentChange,
|
|
547
|
+
onSelect: onElementSelect,
|
|
548
|
+
onMove: onElementMove,
|
|
549
|
+
onResize: onElementResize,
|
|
550
|
+
renderElement,
|
|
551
|
+
buildAnimation,
|
|
552
|
+
buildDelay
|
|
553
|
+
},
|
|
554
|
+
element.id
|
|
555
|
+
);
|
|
556
|
+
})
|
|
557
|
+
]
|
|
367
558
|
}
|
|
368
559
|
) });
|
|
369
560
|
}
|
|
@@ -380,7 +571,9 @@ function SlideElementHost({
|
|
|
380
571
|
onSelect,
|
|
381
572
|
onMove,
|
|
382
573
|
onResize,
|
|
383
|
-
renderElement
|
|
574
|
+
renderElement,
|
|
575
|
+
buildAnimation,
|
|
576
|
+
buildDelay = 0
|
|
384
577
|
}) {
|
|
385
578
|
const dragRef = react.useRef(null);
|
|
386
579
|
if (element.hidden) return null;
|
|
@@ -449,15 +642,18 @@ function SlideElementHost({
|
|
|
449
642
|
outline: selected ? "2px solid #8b5cf6" : void 0,
|
|
450
643
|
outlineOffset: selected ? 2 : void 0,
|
|
451
644
|
cursor: canMove ? "move" : interactive ? "pointer" : "default",
|
|
452
|
-
touchAction: canMove ? "none" : void 0
|
|
645
|
+
touchAction: canMove ? "none" : void 0,
|
|
646
|
+
...buildAnimation ? buildEnterStyle(buildAnimation, buildDelay) : null
|
|
453
647
|
};
|
|
454
648
|
const inner = renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange }) ?? renderElement?.(element, slideWidthPx);
|
|
455
649
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
456
650
|
"div",
|
|
457
651
|
{
|
|
652
|
+
className: buildAnimation ? "fs-build-enter" : void 0,
|
|
458
653
|
style: box,
|
|
459
654
|
"data-fancy-slides-element": element.id,
|
|
460
655
|
"data-fancy-slides-element-type": element.type,
|
|
656
|
+
"data-fancy-slides-build": buildAnimation ? "" : void 0,
|
|
461
657
|
onPointerDown: canMove ? startDrag("move") : void 0,
|
|
462
658
|
onPointerMove: canMove ? onPointerMove : void 0,
|
|
463
659
|
onPointerUp: canMove ? endDrag : void 0,
|
|
@@ -579,6 +775,8 @@ function useSlideKeyboard({
|
|
|
579
775
|
total,
|
|
580
776
|
index,
|
|
581
777
|
goTo,
|
|
778
|
+
onAdvance,
|
|
779
|
+
onRetreat,
|
|
582
780
|
onExit,
|
|
583
781
|
onBlank,
|
|
584
782
|
onFullscreen,
|
|
@@ -595,13 +793,15 @@ function useSlideKeyboard({
|
|
|
595
793
|
case "ArrowLeft":
|
|
596
794
|
case "PageUp":
|
|
597
795
|
e.preventDefault();
|
|
598
|
-
if (
|
|
796
|
+
if (onRetreat) onRetreat();
|
|
797
|
+
else if (index > 0) goTo(index - 1);
|
|
599
798
|
return;
|
|
600
799
|
case "ArrowRight":
|
|
601
800
|
case "PageDown":
|
|
602
801
|
case " ":
|
|
603
802
|
e.preventDefault();
|
|
604
|
-
if (
|
|
803
|
+
if (onAdvance) onAdvance();
|
|
804
|
+
else if (index < total - 1) goTo(index + 1);
|
|
605
805
|
return;
|
|
606
806
|
case "Home":
|
|
607
807
|
e.preventDefault();
|
|
@@ -643,7 +843,7 @@ function useSlideKeyboard({
|
|
|
643
843
|
};
|
|
644
844
|
window.addEventListener("keydown", handler);
|
|
645
845
|
return () => window.removeEventListener("keydown", handler);
|
|
646
|
-
}, [enabled, index, total, goTo, onExit, onBlank, onFullscreen]);
|
|
846
|
+
}, [enabled, index, total, goTo, onAdvance, onRetreat, onExit, onBlank, onFullscreen]);
|
|
647
847
|
}
|
|
648
848
|
function SlideViewer({
|
|
649
849
|
deck,
|
|
@@ -671,13 +871,34 @@ function SlideViewer({
|
|
|
671
871
|
const containerRef = react.useRef(null);
|
|
672
872
|
const prevIndexRef = react.useRef(index);
|
|
673
873
|
const forward = index >= prevIndexRef.current;
|
|
874
|
+
const slide = deck.slides[index];
|
|
875
|
+
const totalSteps = totalBuildSteps(slide);
|
|
876
|
+
const [buildStep, setBuildStep] = react.useState(0);
|
|
877
|
+
const nextFreshRef = react.useRef(false);
|
|
674
878
|
react.useEffect(() => {
|
|
879
|
+
if (index === prevIndexRef.current) return;
|
|
675
880
|
prevIndexRef.current = index;
|
|
676
|
-
|
|
881
|
+
const fresh = nextFreshRef.current;
|
|
882
|
+
nextFreshRef.current = false;
|
|
883
|
+
setBuildStep(fresh ? 0 : totalBuildSteps(deck.slides[index]));
|
|
884
|
+
}, [index, deck.slides]);
|
|
885
|
+
const advance = react.useCallback(() => {
|
|
886
|
+
if (buildStep < totalSteps) {
|
|
887
|
+
setBuildStep((s) => s + 1);
|
|
888
|
+
} else if (index < deck.slides.length - 1) {
|
|
889
|
+
nextFreshRef.current = true;
|
|
890
|
+
goTo(index + 1);
|
|
891
|
+
}
|
|
892
|
+
}, [buildStep, totalSteps, index, deck.slides.length, goTo]);
|
|
893
|
+
const retreat = react.useCallback(() => {
|
|
894
|
+
if (index > 0) goTo(index - 1);
|
|
895
|
+
}, [index, goTo]);
|
|
677
896
|
useSlideKeyboard({
|
|
678
897
|
total: deck.slides.length,
|
|
679
898
|
index,
|
|
680
899
|
goTo,
|
|
900
|
+
onAdvance: advance,
|
|
901
|
+
onRetreat: retreat,
|
|
681
902
|
onExit,
|
|
682
903
|
onBlank: () => setBlanked((b) => !b),
|
|
683
904
|
onFullscreen: () => {
|
|
@@ -690,11 +911,15 @@ function SlideViewer({
|
|
|
690
911
|
react.useEffect(() => {
|
|
691
912
|
if (!autoAdvanceMs || deck.slides.length <= 1) return;
|
|
692
913
|
const t = setTimeout(() => {
|
|
693
|
-
|
|
914
|
+
if (buildStep < totalSteps) {
|
|
915
|
+
setBuildStep((s) => s + 1);
|
|
916
|
+
} else {
|
|
917
|
+
nextFreshRef.current = true;
|
|
918
|
+
goTo(index + 1 < deck.slides.length ? index + 1 : 0);
|
|
919
|
+
}
|
|
694
920
|
}, autoAdvanceMs);
|
|
695
921
|
return () => clearTimeout(t);
|
|
696
|
-
}, [autoAdvanceMs, index, deck.slides.length, goTo]);
|
|
697
|
-
const slide = deck.slides[index];
|
|
922
|
+
}, [autoAdvanceMs, index, deck.slides.length, goTo, buildStep, totalSteps]);
|
|
698
923
|
const theme = resolveTheme(deck.theme);
|
|
699
924
|
const aspectRatio = theme.aspectRatio ?? 16 / 9;
|
|
700
925
|
const transition = slide?.transition ?? theme.defaultTransition;
|
|
@@ -716,6 +941,11 @@ function SlideViewer({
|
|
|
716
941
|
},
|
|
717
942
|
tabIndex: 0,
|
|
718
943
|
"data-fancy-slides-viewer": deck.id,
|
|
944
|
+
"data-fancy-slides-build-step": buildStep,
|
|
945
|
+
onClick: () => {
|
|
946
|
+
if (blanked) return;
|
|
947
|
+
advance();
|
|
948
|
+
},
|
|
719
949
|
children: [
|
|
720
950
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: TRANSITION_KEYFRAMES }),
|
|
721
951
|
!blanked && slide && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -729,7 +959,7 @@ function SlideViewer({
|
|
|
729
959
|
["--fs-ratio"]: aspectRatio.toString(),
|
|
730
960
|
boxShadow: "0 8px 30px rgba(0,0,0,0.35)"
|
|
731
961
|
},
|
|
732
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fs-slide-enter", style: enterStyle, children: /* @__PURE__ */ jsxRuntime.jsx(Slide, { slide, theme, renderElement }) }, index)
|
|
962
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fs-slide-enter", style: enterStyle, children: /* @__PURE__ */ jsxRuntime.jsx(Slide, { slide, theme, buildStep, renderElement }) }, index)
|
|
733
963
|
}
|
|
734
964
|
),
|
|
735
965
|
!hideChrome && !blanked && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -760,7 +990,7 @@ function SlideViewer({
|
|
|
760
990
|
);
|
|
761
991
|
}
|
|
762
992
|
var DEFAULT_DURATION = 400;
|
|
763
|
-
var
|
|
993
|
+
var EASE2 = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
764
994
|
function transitionEnterStyle(transition, forward) {
|
|
765
995
|
const kind = transition?.kind ?? "none";
|
|
766
996
|
if (kind === "none") return { width: "100%", height: "100%" };
|
|
@@ -786,7 +1016,7 @@ function transitionEnterStyle(transition, forward) {
|
|
|
786
1016
|
height: "100%",
|
|
787
1017
|
animationName: name,
|
|
788
1018
|
animationDuration: `${duration}ms`,
|
|
789
|
-
animationTimingFunction:
|
|
1019
|
+
animationTimingFunction: EASE2,
|
|
790
1020
|
animationFillMode: "both"
|
|
791
1021
|
};
|
|
792
1022
|
}
|
|
@@ -842,14 +1072,38 @@ function PresenterView({
|
|
|
842
1072
|
},
|
|
843
1073
|
[deck.slides.length, isControlled, onIndexChange]
|
|
844
1074
|
);
|
|
1075
|
+
const slide = deck.slides[index];
|
|
1076
|
+
const totalSteps = totalBuildSteps(slide);
|
|
1077
|
+
const [buildStep, setBuildStep] = react.useState(0);
|
|
1078
|
+
const prevIndexRef = react.useRef(index);
|
|
1079
|
+
const nextFreshRef = react.useRef(false);
|
|
1080
|
+
react.useEffect(() => {
|
|
1081
|
+
if (index === prevIndexRef.current) return;
|
|
1082
|
+
prevIndexRef.current = index;
|
|
1083
|
+
const fresh = nextFreshRef.current;
|
|
1084
|
+
nextFreshRef.current = false;
|
|
1085
|
+
setBuildStep(fresh ? 0 : totalBuildSteps(deck.slides[index]));
|
|
1086
|
+
}, [index, deck.slides]);
|
|
1087
|
+
const advance = react.useCallback(() => {
|
|
1088
|
+
if (buildStep < totalSteps) {
|
|
1089
|
+
setBuildStep((s) => s + 1);
|
|
1090
|
+
} else if (index < deck.slides.length - 1) {
|
|
1091
|
+
nextFreshRef.current = true;
|
|
1092
|
+
goTo(index + 1);
|
|
1093
|
+
}
|
|
1094
|
+
}, [buildStep, totalSteps, index, deck.slides.length, goTo]);
|
|
1095
|
+
const retreat = react.useCallback(() => {
|
|
1096
|
+
if (index > 0) goTo(index - 1);
|
|
1097
|
+
}, [index, goTo]);
|
|
845
1098
|
useSlideKeyboard({
|
|
846
1099
|
total: deck.slides.length,
|
|
847
1100
|
index,
|
|
848
1101
|
goTo,
|
|
1102
|
+
onAdvance: advance,
|
|
1103
|
+
onRetreat: retreat,
|
|
849
1104
|
onExit
|
|
850
1105
|
});
|
|
851
1106
|
const theme = resolveTheme(deck.theme);
|
|
852
|
-
const slide = deck.slides[index];
|
|
853
1107
|
const nextSlide = deck.slides[index + 1];
|
|
854
1108
|
const [now, setNow] = react.useState(() => Date.now());
|
|
855
1109
|
react.useEffect(() => {
|
|
@@ -896,7 +1150,7 @@ function PresenterView({
|
|
|
896
1150
|
borderRadius: 8,
|
|
897
1151
|
overflow: "hidden"
|
|
898
1152
|
},
|
|
899
|
-
children: slide ? /* @__PURE__ */ jsxRuntime.jsx(Slide, { slide, theme, renderElement }) : null
|
|
1153
|
+
children: slide ? /* @__PURE__ */ jsxRuntime.jsx(Slide, { slide, theme, buildStep, renderElement }) : null
|
|
900
1154
|
}
|
|
901
1155
|
)
|
|
902
1156
|
}
|
|
@@ -1000,8 +1254,8 @@ function PresenterView({
|
|
|
1000
1254
|
/* @__PURE__ */ jsxRuntime.jsx(StatusChip, { label: "Elapsed", children: formatElapsed(now - startedAtRef) }),
|
|
1001
1255
|
/* @__PURE__ */ jsxRuntime.jsx(StatusChip, { label: "Clock", children: formatClock(now) }),
|
|
1002
1256
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginLeft: "auto", display: "flex", gap: 8 }, children: [
|
|
1003
|
-
/* @__PURE__ */ jsxRuntime.jsx(NavButton, { onClick:
|
|
1004
|
-
/* @__PURE__ */ jsxRuntime.jsx(NavButton, { onClick:
|
|
1257
|
+
/* @__PURE__ */ jsxRuntime.jsx(NavButton, { onClick: retreat, disabled: index === 0, children: "\u2190 Prev" }),
|
|
1258
|
+
/* @__PURE__ */ jsxRuntime.jsx(NavButton, { onClick: advance, disabled: index >= deck.slides.length - 1 && buildStep >= totalSteps, children: "Next \u2192" })
|
|
1005
1259
|
] })
|
|
1006
1260
|
]
|
|
1007
1261
|
}
|
|
@@ -1184,6 +1438,7 @@ function useDeckState({ value, onChange, onOp }) {
|
|
|
1184
1438
|
updateElement: (slideIdArg, elementIdArg, patch) => apply({ kind: "element_update", slideId: slideIdArg, elementId: elementIdArg, patch }),
|
|
1185
1439
|
moveElement: (slideIdArg, elementIdArg, x, y) => apply({ kind: "element_move", slideId: slideIdArg, elementId: elementIdArg, x, y }),
|
|
1186
1440
|
resizeElement: (slideIdArg, elementIdArg, w, h) => apply({ kind: "element_resize", slideId: slideIdArg, elementId: elementIdArg, w, h }),
|
|
1441
|
+
setAnimation: (slideIdArg, elementIdArg, animation) => apply({ kind: "element_set_animation", slideId: slideIdArg, elementId: elementIdArg, animation }),
|
|
1187
1442
|
getSlide: (id) => value.slides.find((s) => s.id === id),
|
|
1188
1443
|
getElement: (slideIdArg, elementIdArg) => value.slides.find((s) => s.id === slideIdArg)?.elements.find((e) => e.id === elementIdArg)
|
|
1189
1444
|
};
|
|
@@ -1251,6 +1506,23 @@ function reduce(deck, op) {
|
|
|
1251
1506
|
(s) => s.id === op.slideId ? { ...s, elements: s.elements.map((e) => e.id === op.elementId ? { ...e, w: op.w, h: op.h } : e) } : s
|
|
1252
1507
|
)
|
|
1253
1508
|
};
|
|
1509
|
+
case "element_set_animation":
|
|
1510
|
+
return {
|
|
1511
|
+
...deck,
|
|
1512
|
+
slides: deck.slides.map(
|
|
1513
|
+
(s) => s.id === op.slideId ? {
|
|
1514
|
+
...s,
|
|
1515
|
+
elements: s.elements.map((e) => {
|
|
1516
|
+
if (e.id !== op.elementId) return e;
|
|
1517
|
+
if (op.animation === void 0) {
|
|
1518
|
+
const { animation: _drop, ...rest } = e;
|
|
1519
|
+
return rest;
|
|
1520
|
+
}
|
|
1521
|
+
return { ...e, animation: op.animation };
|
|
1522
|
+
})
|
|
1523
|
+
} : s
|
|
1524
|
+
)
|
|
1525
|
+
};
|
|
1254
1526
|
}
|
|
1255
1527
|
}
|
|
1256
1528
|
|
|
@@ -1592,10 +1864,10 @@ function EditorToolbar({
|
|
|
1592
1864
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tooltip, { content: "Present (F)", children: /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Action, { color: "violet", size: "sm", icon: "play", onClick: onPresent, children: "Present" }) }) })
|
|
1593
1865
|
] });
|
|
1594
1866
|
}
|
|
1595
|
-
function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground }) {
|
|
1867
|
+
function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onSetTransition, onSetBackground, onSetAnimation, onSetElementAnimation }) {
|
|
1596
1868
|
if (!element) {
|
|
1597
1869
|
if (slide) {
|
|
1598
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SlideSettings, { slide, onSetTransition, onSetBackground });
|
|
1870
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SlideSettings, { slide, onSetTransition, onSetBackground, onSetElementAnimation });
|
|
1599
1871
|
}
|
|
1600
1872
|
return /* @__PURE__ */ jsxRuntime.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: [
|
|
1601
1873
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Heading, { as: "h3", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Inspector" }),
|
|
@@ -1620,10 +1892,12 @@ function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onS
|
|
|
1620
1892
|
/* @__PURE__ */ jsxRuntime.jsxs(reactFancy.Tabs.List, { children: [
|
|
1621
1893
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Tab, { value: "style", children: "Style" }),
|
|
1622
1894
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Tab, { value: "layout", children: "Layout" }),
|
|
1895
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Tab, { value: "build", children: "Build" }),
|
|
1623
1896
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Tab, { value: "advanced", children: "Advanced" })
|
|
1624
1897
|
] }),
|
|
1625
1898
|
/* @__PURE__ */ jsxRuntime.jsxs(reactFancy.Tabs.Panels, { children: [
|
|
1626
1899
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Panel, { value: "style", children: /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxRuntime.jsx(StyleSection, { element, onPatch }) }) }),
|
|
1900
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Panel, { value: "build", children: /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxRuntime.jsx(AnimateSection, { animation: element.animation, onSetAnimation }) }) }),
|
|
1627
1901
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Panel, { value: "layout", children: /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxRuntime.jsx(LayoutSection, { element, onPatch }) }) }),
|
|
1628
1902
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Tabs.Panel, { value: "advanced", children: /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Card, { padding: "md", className: "!bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxRuntime.jsx(AdvancedSection, { element, onPatch }) }) })
|
|
1629
1903
|
] })
|
|
@@ -1633,7 +1907,8 @@ function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onS
|
|
|
1633
1907
|
function SlideSettings({
|
|
1634
1908
|
slide,
|
|
1635
1909
|
onSetTransition,
|
|
1636
|
-
onSetBackground
|
|
1910
|
+
onSetBackground,
|
|
1911
|
+
onSetElementAnimation
|
|
1637
1912
|
}) {
|
|
1638
1913
|
const transition = slide.transition;
|
|
1639
1914
|
const kind = transition?.kind ?? "none";
|
|
@@ -1700,10 +1975,54 @@ function SlideSettings({
|
|
|
1700
1975
|
onChange: (c) => onSetBackground({ ...slide.background, color: c })
|
|
1701
1976
|
}
|
|
1702
1977
|
) })
|
|
1703
|
-
] }) })
|
|
1978
|
+
] }) }),
|
|
1979
|
+
onSetElementAnimation && /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Card, { padding: "md", className: "mt-3 !bg-white dark:!bg-zinc-950", children: /* @__PURE__ */ jsxRuntime.jsx(BuildOrderList, { slide, onSetElementAnimation }) })
|
|
1704
1980
|
] })
|
|
1705
1981
|
] });
|
|
1706
1982
|
}
|
|
1983
|
+
function BuildOrderList({
|
|
1984
|
+
slide,
|
|
1985
|
+
onSetElementAnimation
|
|
1986
|
+
}) {
|
|
1987
|
+
const builds = collectBuilds(slide);
|
|
1988
|
+
const move = (from, to) => {
|
|
1989
|
+
if (to < 0 || to >= builds.length) return;
|
|
1990
|
+
const reordered = [...builds];
|
|
1991
|
+
const [item] = reordered.splice(from, 1);
|
|
1992
|
+
reordered.splice(to, 0, item);
|
|
1993
|
+
reordered.forEach((b, i) => {
|
|
1994
|
+
if ((b.animation.order ?? 0) !== i) {
|
|
1995
|
+
onSetElementAnimation(b.element.id, { ...b.animation, order: i });
|
|
1996
|
+
}
|
|
1997
|
+
});
|
|
1998
|
+
};
|
|
1999
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
2000
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Heading, { as: "h4", size: "xs", className: "!uppercase !tracking-wider !text-zinc-500", children: "Build order" }),
|
|
2001
|
+
builds.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Text, { size: "xs", className: "!text-zinc-500", children: "No animated elements yet. Select an element and add a build under its Build tab." }) : builds.map((b, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2002
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactFancy.Text, { size: "xs", className: "!font-mono !text-zinc-400 w-5", children: [
|
|
2003
|
+
i + 1,
|
|
2004
|
+
"."
|
|
2005
|
+
] }),
|
|
2006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2007
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Text, { size: "sm", className: "truncate", children: buildLabel(b.element) }),
|
|
2008
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactFancy.Text, { size: "xs", className: "!font-mono !text-zinc-400", children: [
|
|
2009
|
+
b.animation.effect,
|
|
2010
|
+
" \xB7 ",
|
|
2011
|
+
b.animation.trigger ?? "on-click"
|
|
2012
|
+
] })
|
|
2013
|
+
] }),
|
|
2014
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Action, { size: "xs", variant: "ghost", icon: "chevron-up", onClick: () => move(i, i - 1), disabled: i === 0, "aria-label": "Move earlier" }),
|
|
2015
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Action, { size: "xs", variant: "ghost", icon: "chevron-down", onClick: () => move(i, i + 1), disabled: i === builds.length - 1, "aria-label": "Move later" })
|
|
2016
|
+
] }, b.element.id))
|
|
2017
|
+
] });
|
|
2018
|
+
}
|
|
2019
|
+
function buildLabel(element) {
|
|
2020
|
+
if (element.type === "text") {
|
|
2021
|
+
const text = element.content.replace(/\s+/g, " ").trim();
|
|
2022
|
+
return text ? text.length > 28 ? `${text.slice(0, 28)}\u2026` : text : "Text";
|
|
2023
|
+
}
|
|
2024
|
+
return `${element.type} #${element.id.slice(-6)}`;
|
|
2025
|
+
}
|
|
1707
2026
|
function LayoutSection({ element, onPatch }) {
|
|
1708
2027
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
1709
2028
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
@@ -1725,6 +2044,100 @@ function AdvancedSection({ element, onPatch }) {
|
|
|
1725
2044
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Action, { size: "sm", variant: element.hidden ? "default" : "ghost", onClick: () => onPatch({ hidden: !element.hidden }), children: element.hidden ? "Hidden \u2014 show" : "Hide on slide" }) })
|
|
1726
2045
|
] });
|
|
1727
2046
|
}
|
|
2047
|
+
var NO_ANIMATION = "none";
|
|
2048
|
+
function AnimateSection({
|
|
2049
|
+
animation,
|
|
2050
|
+
onSetAnimation
|
|
2051
|
+
}) {
|
|
2052
|
+
if (!onSetAnimation) {
|
|
2053
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Text, { size: "sm", className: "!text-zinc-500", children: "Build animations aren't wired up in this editor." });
|
|
2054
|
+
}
|
|
2055
|
+
const effect = animation?.effect;
|
|
2056
|
+
const set = (next) => {
|
|
2057
|
+
const base = animation ?? { effect: "fade" };
|
|
2058
|
+
onSetAnimation({ ...base, ...next });
|
|
2059
|
+
};
|
|
2060
|
+
const showDirection = effect === "fly-in" || effect === "wipe";
|
|
2061
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2062
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2063
|
+
reactFancy.Select,
|
|
2064
|
+
{
|
|
2065
|
+
label: "Effect",
|
|
2066
|
+
list: [
|
|
2067
|
+
{ value: NO_ANIMATION, label: "None" },
|
|
2068
|
+
{ value: "fade", label: "Fade" },
|
|
2069
|
+
{ value: "fly-in", label: "Fly in" },
|
|
2070
|
+
{ value: "zoom", label: "Zoom" },
|
|
2071
|
+
{ value: "wipe", label: "Wipe" }
|
|
2072
|
+
],
|
|
2073
|
+
value: effect ?? NO_ANIMATION,
|
|
2074
|
+
onValueChange: (v) => {
|
|
2075
|
+
if (v === NO_ANIMATION) onSetAnimation(void 0);
|
|
2076
|
+
else set({ effect: v });
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
),
|
|
2080
|
+
effect && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2081
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2082
|
+
reactFancy.Select,
|
|
2083
|
+
{
|
|
2084
|
+
label: "Trigger",
|
|
2085
|
+
list: [
|
|
2086
|
+
{ value: "on-click", label: "On click" },
|
|
2087
|
+
{ value: "with-prev", label: "With previous" },
|
|
2088
|
+
{ value: "after-prev", label: "After previous" }
|
|
2089
|
+
],
|
|
2090
|
+
value: animation?.trigger ?? "on-click",
|
|
2091
|
+
onValueChange: (v) => set({ trigger: v })
|
|
2092
|
+
}
|
|
2093
|
+
),
|
|
2094
|
+
showDirection && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2095
|
+
reactFancy.Select,
|
|
2096
|
+
{
|
|
2097
|
+
label: "Direction",
|
|
2098
|
+
list: [
|
|
2099
|
+
{ value: "left", label: "From left" },
|
|
2100
|
+
{ value: "right", label: "From right" },
|
|
2101
|
+
{ value: "up", label: "From bottom" },
|
|
2102
|
+
{ value: "down", label: "From top" }
|
|
2103
|
+
],
|
|
2104
|
+
value: animation?.direction ?? "left",
|
|
2105
|
+
onValueChange: (v) => set({ direction: v })
|
|
2106
|
+
}
|
|
2107
|
+
),
|
|
2108
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
2109
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2110
|
+
reactFancy.Input,
|
|
2111
|
+
{
|
|
2112
|
+
label: "Duration (ms)",
|
|
2113
|
+
type: "number",
|
|
2114
|
+
value: String(animation?.duration ?? 500),
|
|
2115
|
+
onChange: (e) => set({ duration: parseInt(e.target.value, 10) || 500 })
|
|
2116
|
+
}
|
|
2117
|
+
),
|
|
2118
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2119
|
+
reactFancy.Input,
|
|
2120
|
+
{
|
|
2121
|
+
label: "Delay (ms)",
|
|
2122
|
+
type: "number",
|
|
2123
|
+
value: String(animation?.delay ?? 0),
|
|
2124
|
+
onChange: (e) => set({ delay: parseInt(e.target.value, 10) || 0 })
|
|
2125
|
+
}
|
|
2126
|
+
)
|
|
2127
|
+
] }),
|
|
2128
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2129
|
+
reactFancy.Input,
|
|
2130
|
+
{
|
|
2131
|
+
label: "Order",
|
|
2132
|
+
type: "number",
|
|
2133
|
+
value: String(animation?.order ?? 0),
|
|
2134
|
+
onChange: (e) => set({ order: parseInt(e.target.value, 10) || 0 })
|
|
2135
|
+
}
|
|
2136
|
+
),
|
|
2137
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Text, { size: "xs", className: "!text-zinc-500", children: `Builds reveal in ascending order. "On click" starts a new step; "with previous" plays alongside the step's lead; "after previous" follows it. Honors prefers-reduced-motion.` })
|
|
2138
|
+
] })
|
|
2139
|
+
] });
|
|
2140
|
+
}
|
|
1728
2141
|
function StyleSection({ element, onPatch }) {
|
|
1729
2142
|
switch (element.type) {
|
|
1730
2143
|
case "text":
|
|
@@ -2400,7 +2813,9 @@ function DeckEditor({
|
|
|
2400
2813
|
},
|
|
2401
2814
|
onLockToggle: (locked) => slide && elementIdSelected && ops.updateElement(slide.id, elementIdSelected, { locked }),
|
|
2402
2815
|
onSetTransition: (transition) => slide && ops.setTransition(slide.id, transition),
|
|
2403
|
-
onSetBackground: (background) => slide && ops.setBackground(slide.id, background)
|
|
2816
|
+
onSetBackground: (background) => slide && ops.setBackground(slide.id, background),
|
|
2817
|
+
onSetAnimation: (animation) => slide && elementIdSelected && ops.setAnimation(slide.id, elementIdSelected, animation),
|
|
2818
|
+
onSetElementAnimation: (eid, animation) => slide && ops.setAnimation(slide.id, eid, animation)
|
|
2404
2819
|
}
|
|
2405
2820
|
) })
|
|
2406
2821
|
] }),
|
|
@@ -2422,8 +2837,11 @@ exports.SlideThumbnail = SlideThumbnail;
|
|
|
2422
2837
|
exports.SlideViewer = SlideViewer;
|
|
2423
2838
|
exports.SpeakerNotes = SpeakerNotes;
|
|
2424
2839
|
exports.TextElementRenderer = TextElementRenderer;
|
|
2840
|
+
exports.buildSteps = buildSteps;
|
|
2841
|
+
exports.buildsForStep = buildsForStep;
|
|
2425
2842
|
exports.builtinThemes = builtinThemes;
|
|
2426
2843
|
exports.chartStarterOption = chartStarterOption;
|
|
2844
|
+
exports.collectBuilds = collectBuilds;
|
|
2427
2845
|
exports.darkTheme = darkTheme;
|
|
2428
2846
|
exports.deckId = deckId;
|
|
2429
2847
|
exports.defaultTheme = defaultTheme;
|
|
@@ -2433,11 +2851,14 @@ exports.nextId = nextId;
|
|
|
2433
2851
|
exports.reduceDeck = reduce;
|
|
2434
2852
|
exports.resolveTheme = resolveTheme;
|
|
2435
2853
|
exports.slideId = slideId;
|
|
2854
|
+
exports.stepDelays = stepDelays;
|
|
2855
|
+
exports.totalBuildSteps = totalBuildSteps;
|
|
2436
2856
|
exports.useDeckState = useDeckState;
|
|
2437
2857
|
exports.useIsDarkSlide = useIsDarkSlide;
|
|
2438
2858
|
exports.useSlideContext = useSlideContext;
|
|
2439
2859
|
exports.useSlideKeyboard = useSlideKeyboard;
|
|
2440
2860
|
exports.useSlideTheme = useSlideTheme;
|
|
2861
|
+
exports.visibleElementIds = visibleElementIds;
|
|
2441
2862
|
exports.vividTheme = vividTheme;
|
|
2442
2863
|
//# sourceMappingURL=index.cjs.map
|
|
2443
2864
|
//# sourceMappingURL=index.cjs.map
|