@particle-academy/fancy-slides 0.4.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/README.md +9 -0
- package/dist/index.cjs +200 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -68
- package/dist/index.d.ts +109 -68
- package/dist/index.js +199 -116
- package/dist/index.js.map +1 -1
- package/dist/registry.d.cts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/{types-P-9MmnGU.d.cts → types-9BbelJX1.d.cts} +10 -0
- package/dist/{types-P-9MmnGU.d.ts → types-9BbelJX1.d.ts} +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,9 +94,18 @@ element.animation = {
|
|
|
94
94
|
duration: 500, // ms
|
|
95
95
|
delay: 0, // ms
|
|
96
96
|
order: 0, // build order, ascending; ties broken by element index
|
|
97
|
+
byParagraph: false, // text only — reveal one line/bullet per click
|
|
97
98
|
};
|
|
98
99
|
```
|
|
99
100
|
|
|
101
|
+
For a **text** element you can set `byParagraph: true` to reveal it one
|
|
102
|
+
paragraph at a time (PowerPoint/Google Slides "By paragraph"). The element's
|
|
103
|
+
`content` is split on `"\n"` (a trailing empty line is dropped) and expands into
|
|
104
|
+
one build per line — the first line uses the element's own `trigger`, every
|
|
105
|
+
subsequent line reveals on a fresh click. Each markdown line renders through the
|
|
106
|
+
normal path, so a `- …` bullet line builds in as its own item. Toggle it from
|
|
107
|
+
the Build tab when a text element has an effect selected.
|
|
108
|
+
|
|
100
109
|
A slide's builds group into *click steps*: the first build and every
|
|
101
110
|
`on-click` build opens a new step; `with-prev` plays alongside that step's lead
|
|
102
111
|
and `after-prev` follows it. In `SlideViewer` / `PresenterView`, → / Space /
|
package/dist/index.cjs
CHANGED
|
@@ -74,6 +74,15 @@ function cn(...parts) {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
// src/utils/builds.ts
|
|
77
|
+
function splitParagraphs(content) {
|
|
78
|
+
const lines = content.split("\n");
|
|
79
|
+
if (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
|
|
80
|
+
return lines;
|
|
81
|
+
}
|
|
82
|
+
function isByParagraph(element, animation) {
|
|
83
|
+
if (!animation.byParagraph || element.type !== "text") return false;
|
|
84
|
+
return splitParagraphs(element.content).length > 1;
|
|
85
|
+
}
|
|
77
86
|
var DEFAULT_BUILD_DURATION = 500;
|
|
78
87
|
function collectBuilds(slide) {
|
|
79
88
|
if (!slide) return [];
|
|
@@ -83,12 +92,25 @@ function collectBuilds(slide) {
|
|
|
83
92
|
builds.push({ element, animation: element.animation, index });
|
|
84
93
|
}
|
|
85
94
|
});
|
|
86
|
-
|
|
95
|
+
const ordered = builds.sort((a, b) => {
|
|
87
96
|
const ao = a.animation.order ?? 0;
|
|
88
97
|
const bo = b.animation.order ?? 0;
|
|
89
98
|
if (ao !== bo) return ao - bo;
|
|
90
99
|
return a.index - b.index;
|
|
91
100
|
});
|
|
101
|
+
const expanded = [];
|
|
102
|
+
for (const build of ordered) {
|
|
103
|
+
if (isByParagraph(build.element, build.animation)) {
|
|
104
|
+
const paras = splitParagraphs(build.element.content);
|
|
105
|
+
paras.forEach((_, paraIndex) => {
|
|
106
|
+
const animation = paraIndex === 0 ? build.animation : { ...build.animation, trigger: "on-click" };
|
|
107
|
+
expanded.push({ element: build.element, animation, index: build.index, paraIndex });
|
|
108
|
+
});
|
|
109
|
+
} else {
|
|
110
|
+
expanded.push(build);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return expanded;
|
|
92
114
|
}
|
|
93
115
|
function buildSteps(slide) {
|
|
94
116
|
const builds = collectBuilds(slide);
|
|
@@ -112,7 +134,9 @@ function visibleElementIds(slide, buildStep) {
|
|
|
112
134
|
const steps = buildSteps(slide);
|
|
113
135
|
const stepOfElement = /* @__PURE__ */ new Map();
|
|
114
136
|
steps.forEach((step, i) => {
|
|
115
|
-
for (const b of step.builds)
|
|
137
|
+
for (const b of step.builds) {
|
|
138
|
+
if (!stepOfElement.has(b.element.id)) stepOfElement.set(b.element.id, i + 1);
|
|
139
|
+
}
|
|
116
140
|
});
|
|
117
141
|
for (const element of slide.elements) {
|
|
118
142
|
const revealStep = stepOfElement.get(element.id);
|
|
@@ -124,6 +148,25 @@ function visibleElementIds(slide, buildStep) {
|
|
|
124
148
|
}
|
|
125
149
|
return visible;
|
|
126
150
|
}
|
|
151
|
+
function paragraphReveals(slide, buildStep) {
|
|
152
|
+
const out = /* @__PURE__ */ new Map();
|
|
153
|
+
if (!slide) return out;
|
|
154
|
+
const steps = buildSteps(slide);
|
|
155
|
+
steps.forEach((step, i) => {
|
|
156
|
+
const stepNum = i + 1;
|
|
157
|
+
for (const b of step.builds) {
|
|
158
|
+
if (b.paraIndex === void 0) continue;
|
|
159
|
+
const fired = buildStep >= stepNum;
|
|
160
|
+
const prev = out.get(b.element.id) ?? { revealed: 0 };
|
|
161
|
+
if (fired) {
|
|
162
|
+
prev.revealed = Math.max(prev.revealed, b.paraIndex + 1);
|
|
163
|
+
if (stepNum === buildStep) prev.firingParaIndex = b.paraIndex;
|
|
164
|
+
}
|
|
165
|
+
out.set(b.element.id, prev);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
127
170
|
function buildsForStep(slide, buildStep) {
|
|
128
171
|
const steps = buildSteps(slide);
|
|
129
172
|
const step = steps[buildStep - 1];
|
|
@@ -145,13 +188,95 @@ function stepDelays(builds) {
|
|
|
145
188
|
}
|
|
146
189
|
return delays;
|
|
147
190
|
}
|
|
191
|
+
|
|
192
|
+
// src/components/Slide/builds-style.ts
|
|
193
|
+
var DEFAULT_BUILD_DURATION2 = 500;
|
|
194
|
+
var EASE = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
195
|
+
function buildEnterStyle(animation, effectiveDelay) {
|
|
196
|
+
const duration = animation.duration ?? DEFAULT_BUILD_DURATION2;
|
|
197
|
+
const dir = animation.direction ?? "left";
|
|
198
|
+
let name;
|
|
199
|
+
switch (animation.effect) {
|
|
200
|
+
case "fade":
|
|
201
|
+
name = "fs-build-fade";
|
|
202
|
+
break;
|
|
203
|
+
case "zoom":
|
|
204
|
+
name = "fs-build-zoom";
|
|
205
|
+
break;
|
|
206
|
+
case "fly-in":
|
|
207
|
+
name = `fs-build-fly-${dir}`;
|
|
208
|
+
break;
|
|
209
|
+
case "wipe":
|
|
210
|
+
name = `fs-build-wipe-${dir}`;
|
|
211
|
+
break;
|
|
212
|
+
default:
|
|
213
|
+
name = "fs-build-fade";
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
animationName: name,
|
|
217
|
+
animationDuration: `${duration}ms`,
|
|
218
|
+
animationDelay: `${effectiveDelay}ms`,
|
|
219
|
+
animationTimingFunction: EASE,
|
|
220
|
+
animationFillMode: "both"
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
var BUILD_KEYFRAMES = `
|
|
224
|
+
@media (prefers-reduced-motion: reduce) {
|
|
225
|
+
.fs-build-enter { animation: none !important; }
|
|
226
|
+
}
|
|
227
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
228
|
+
@keyframes fs-build-fade {
|
|
229
|
+
from { opacity: 0; }
|
|
230
|
+
to { opacity: 1; }
|
|
231
|
+
}
|
|
232
|
+
@keyframes fs-build-zoom {
|
|
233
|
+
from { opacity: 0; transform: scale(0.8); }
|
|
234
|
+
to { opacity: 1; transform: scale(1); }
|
|
235
|
+
}
|
|
236
|
+
@keyframes fs-build-fly-left {
|
|
237
|
+
from { opacity: 0; transform: translateX(-24%); }
|
|
238
|
+
to { opacity: 1; transform: translateX(0); }
|
|
239
|
+
}
|
|
240
|
+
@keyframes fs-build-fly-right {
|
|
241
|
+
from { opacity: 0; transform: translateX(24%); }
|
|
242
|
+
to { opacity: 1; transform: translateX(0); }
|
|
243
|
+
}
|
|
244
|
+
@keyframes fs-build-fly-up {
|
|
245
|
+
from { opacity: 0; transform: translateY(24%); }
|
|
246
|
+
to { opacity: 1; transform: translateY(0); }
|
|
247
|
+
}
|
|
248
|
+
@keyframes fs-build-fly-down {
|
|
249
|
+
from { opacity: 0; transform: translateY(-24%); }
|
|
250
|
+
to { opacity: 1; transform: translateY(0); }
|
|
251
|
+
}
|
|
252
|
+
/* wipe: clip-path inset reveals from the named edge toward the opposite one.
|
|
253
|
+
inset(top right bottom left) \u2014 start fully clipped on the far side. */
|
|
254
|
+
@keyframes fs-build-wipe-left {
|
|
255
|
+
from { clip-path: inset(0 100% 0 0); }
|
|
256
|
+
to { clip-path: inset(0 0 0 0); }
|
|
257
|
+
}
|
|
258
|
+
@keyframes fs-build-wipe-right {
|
|
259
|
+
from { clip-path: inset(0 0 0 100%); }
|
|
260
|
+
to { clip-path: inset(0 0 0 0); }
|
|
261
|
+
}
|
|
262
|
+
@keyframes fs-build-wipe-up {
|
|
263
|
+
from { clip-path: inset(100% 0 0 0); }
|
|
264
|
+
to { clip-path: inset(0 0 0 0); }
|
|
265
|
+
}
|
|
266
|
+
@keyframes fs-build-wipe-down {
|
|
267
|
+
from { clip-path: inset(0 0 100% 0); }
|
|
268
|
+
to { clip-path: inset(0 0 0 0); }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
148
272
|
function TextElementRenderer({
|
|
149
273
|
element,
|
|
150
274
|
theme,
|
|
151
275
|
slideWidthPx,
|
|
152
276
|
editing = false,
|
|
153
277
|
selected = false,
|
|
154
|
-
onContentChange
|
|
278
|
+
onContentChange,
|
|
279
|
+
paraReveal
|
|
155
280
|
}) {
|
|
156
281
|
const t = resolveTheme(theme);
|
|
157
282
|
const style = element.style ?? {};
|
|
@@ -198,30 +323,53 @@ function TextElementRenderer({
|
|
|
198
323
|
}
|
|
199
324
|
);
|
|
200
325
|
}
|
|
326
|
+
const proseScope = `[data-fs-text-scope="${scopeId}"]`;
|
|
327
|
+
const doubleScope = `${proseScope}${proseScope}`;
|
|
328
|
+
const proseStyle = /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
329
|
+
${proseScope} > div { width: 100%; height: 100%; font-size: inherit; }
|
|
330
|
+
${doubleScope} :is(p, ul, ol, li, blockquote, h1, h2, h3, h4, h5, h6, pre, code, strong, em, a) {
|
|
331
|
+
font-size: inherit;
|
|
332
|
+
}
|
|
333
|
+
${doubleScope} h1 { font-size: 1.6em; font-weight: 700; }
|
|
334
|
+
${doubleScope} h2 { font-size: 1.35em; font-weight: 700; }
|
|
335
|
+
${doubleScope} h3 { font-size: 1.15em; font-weight: 600; }
|
|
336
|
+
${proseScope} :where(p, ul, ol, h1, h2, h3, h4, h5, h6, pre, blockquote) {
|
|
337
|
+
margin: 0;
|
|
338
|
+
padding: 0;
|
|
339
|
+
}
|
|
340
|
+
${proseScope} :where(p, li) + :where(p, li, ul, ol) { margin-top: 0.4em; }
|
|
341
|
+
${proseScope} :where(ul, ol) { padding-left: 1.4em; }
|
|
342
|
+
${proseScope} :where(strong) { font-weight: ${Math.max(700, weight(style.weight) ?? 400 + 200)}; }
|
|
343
|
+
${proseScope} :where(a) { color: inherit; text-decoration: underline; }
|
|
344
|
+
${proseScope} :where(code) { font-family: ${t.fonts?.mono ?? "monospace"}; }
|
|
345
|
+
` });
|
|
346
|
+
const renderChunk = (content) => format === "plain" ? content : /* @__PURE__ */ jsxRuntime.jsx(reactFancy.ContentRenderer, { value: content, format: format === "html" ? "html" : "markdown" });
|
|
347
|
+
if (paraReveal) {
|
|
348
|
+
const paras = splitParagraphs(element.content);
|
|
349
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-fs-text-scope": scopeId, style: css, children: [
|
|
350
|
+
proseStyle,
|
|
351
|
+
paras.map((para, i) => {
|
|
352
|
+
if (i >= paraReveal.revealed) return null;
|
|
353
|
+
const firing = i === paraReveal.firingParaIndex && !!element.animation;
|
|
354
|
+
const enter = firing ? buildEnterStyle(element.animation, element.animation.delay ?? 0) : null;
|
|
355
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
356
|
+
"div",
|
|
357
|
+
{
|
|
358
|
+
className: firing ? "fs-build-enter" : void 0,
|
|
359
|
+
style: { whiteSpace: format === "plain" ? "pre-wrap" : "normal", ...enter },
|
|
360
|
+
"data-fancy-slides-paragraph": i,
|
|
361
|
+
children: renderChunk(para)
|
|
362
|
+
},
|
|
363
|
+
i
|
|
364
|
+
);
|
|
365
|
+
})
|
|
366
|
+
] });
|
|
367
|
+
}
|
|
201
368
|
if (format === "plain") {
|
|
202
369
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: css, children: element.content });
|
|
203
370
|
}
|
|
204
|
-
const proseScope = `[data-fs-text-scope="${scopeId}"]`;
|
|
205
|
-
const doubleScope = `${proseScope}${proseScope}`;
|
|
206
371
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-fs-text-scope": scopeId, style: css, children: [
|
|
207
|
-
|
|
208
|
-
${proseScope} > div { width: 100%; height: 100%; font-size: inherit; }
|
|
209
|
-
${doubleScope} :is(p, ul, ol, li, blockquote, h1, h2, h3, h4, h5, h6, pre, code, strong, em, a) {
|
|
210
|
-
font-size: inherit;
|
|
211
|
-
}
|
|
212
|
-
${doubleScope} h1 { font-size: 1.6em; font-weight: 700; }
|
|
213
|
-
${doubleScope} h2 { font-size: 1.35em; font-weight: 700; }
|
|
214
|
-
${doubleScope} h3 { font-size: 1.15em; font-weight: 600; }
|
|
215
|
-
${proseScope} :where(p, ul, ol, h1, h2, h3, h4, h5, h6, pre, blockquote) {
|
|
216
|
-
margin: 0;
|
|
217
|
-
padding: 0;
|
|
218
|
-
}
|
|
219
|
-
${proseScope} :where(p, li) + :where(p, li, ul, ol) { margin-top: 0.4em; }
|
|
220
|
-
${proseScope} :where(ul, ol) { padding-left: 1.4em; }
|
|
221
|
-
${proseScope} :where(strong) { font-weight: ${Math.max(700, weight(style.weight) ?? 400 + 200)}; }
|
|
222
|
-
${proseScope} :where(a) { color: inherit; text-decoration: underline; }
|
|
223
|
-
${proseScope} :where(code) { font-family: ${t.fonts?.mono ?? "monospace"}; }
|
|
224
|
-
` }),
|
|
372
|
+
proseStyle,
|
|
225
373
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.ContentRenderer, { value: element.content, format: format === "html" ? "html" : "markdown" })
|
|
226
374
|
] });
|
|
227
375
|
}
|
|
@@ -353,87 +501,6 @@ function relativeLuminance(r, g, b) {
|
|
|
353
501
|
};
|
|
354
502
|
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
355
503
|
}
|
|
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
|
-
`;
|
|
437
504
|
function Slide({
|
|
438
505
|
slide,
|
|
439
506
|
theme,
|
|
@@ -490,13 +557,16 @@ function Slide({
|
|
|
490
557
|
if (steps.length === 0) return null;
|
|
491
558
|
const revealStep = /* @__PURE__ */ new Map();
|
|
492
559
|
steps.forEach((step, i) => {
|
|
493
|
-
for (const b of step.builds)
|
|
560
|
+
for (const b of step.builds) {
|
|
561
|
+
if (!revealStep.has(b.element.id)) revealStep.set(b.element.id, i + 1);
|
|
562
|
+
}
|
|
494
563
|
});
|
|
495
564
|
const driven = buildStep !== void 0;
|
|
496
565
|
const currentStep = driven ? buildStep : steps.length;
|
|
497
566
|
const firing = driven ? steps[currentStep - 1] : void 0;
|
|
498
567
|
const delays = firing ? stepDelays(firing.builds) : /* @__PURE__ */ new Map();
|
|
499
|
-
|
|
568
|
+
const paraReveals = driven ? paragraphReveals(slide, currentStep) : /* @__PURE__ */ new Map();
|
|
569
|
+
return { revealStep, currentStep, delays, paraReveals, driven };
|
|
500
570
|
}, [editing, slide, buildStep]);
|
|
501
571
|
return /* @__PURE__ */ jsxRuntime.jsx(SlideContext.Provider, { value: slideContext, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
502
572
|
"div",
|
|
@@ -522,12 +592,13 @@ function Slide({
|
|
|
522
592
|
let buildHidden = false;
|
|
523
593
|
let buildAnimation;
|
|
524
594
|
let buildDelay = 0;
|
|
595
|
+
const paraReveal = buildInfo?.paraReveals.get(element.id);
|
|
525
596
|
if (buildInfo) {
|
|
526
597
|
const step = buildInfo.revealStep.get(element.id);
|
|
527
598
|
if (step !== void 0) {
|
|
528
599
|
if (buildInfo.currentStep < step) {
|
|
529
600
|
buildHidden = true;
|
|
530
|
-
} else if (buildInfo.currentStep === step && element.animation) {
|
|
601
|
+
} else if (paraReveal) ; else if (buildInfo.currentStep === step && element.animation) {
|
|
531
602
|
buildAnimation = element.animation;
|
|
532
603
|
buildDelay = buildInfo.delays.get(element.id) ?? 0;
|
|
533
604
|
}
|
|
@@ -549,7 +620,8 @@ function Slide({
|
|
|
549
620
|
onResize: onElementResize,
|
|
550
621
|
renderElement,
|
|
551
622
|
buildAnimation,
|
|
552
|
-
buildDelay
|
|
623
|
+
buildDelay,
|
|
624
|
+
paraReveal
|
|
553
625
|
},
|
|
554
626
|
element.id
|
|
555
627
|
);
|
|
@@ -573,7 +645,8 @@ function SlideElementHost({
|
|
|
573
645
|
onResize,
|
|
574
646
|
renderElement,
|
|
575
647
|
buildAnimation,
|
|
576
|
-
buildDelay = 0
|
|
648
|
+
buildDelay = 0,
|
|
649
|
+
paraReveal
|
|
577
650
|
}) {
|
|
578
651
|
const dragRef = react.useRef(null);
|
|
579
652
|
if (element.hidden) return null;
|
|
@@ -645,7 +718,7 @@ function SlideElementHost({
|
|
|
645
718
|
touchAction: canMove ? "none" : void 0,
|
|
646
719
|
...buildAnimation ? buildEnterStyle(buildAnimation, buildDelay) : null
|
|
647
720
|
};
|
|
648
|
-
const inner = renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange }) ?? renderElement?.(element, slideWidthPx);
|
|
721
|
+
const inner = renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal }) ?? renderElement?.(element, slideWidthPx);
|
|
649
722
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
650
723
|
"div",
|
|
651
724
|
{
|
|
@@ -712,7 +785,7 @@ function ResizeHandles({ onStart, onMove, onEnd }) {
|
|
|
712
785
|
anchor
|
|
713
786
|
)) });
|
|
714
787
|
}
|
|
715
|
-
function renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange }) {
|
|
788
|
+
function renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal }) {
|
|
716
789
|
switch (element.type) {
|
|
717
790
|
case "text":
|
|
718
791
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -723,7 +796,8 @@ function renderInner({ element, theme, slideWidthPx, editing, selected, onConten
|
|
|
723
796
|
slideWidthPx,
|
|
724
797
|
editing,
|
|
725
798
|
selected,
|
|
726
|
-
onContentChange: onContentChange ? (c) => onContentChange(element.id, c) : void 0
|
|
799
|
+
onContentChange: onContentChange ? (c) => onContentChange(element.id, c) : void 0,
|
|
800
|
+
paraReveal
|
|
727
801
|
}
|
|
728
802
|
);
|
|
729
803
|
case "image":
|
|
@@ -1897,7 +1971,7 @@ function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onS
|
|
|
1897
1971
|
] }),
|
|
1898
1972
|
/* @__PURE__ */ jsxRuntime.jsxs(reactFancy.Tabs.Panels, { children: [
|
|
1899
1973
|
/* @__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 }) }) }),
|
|
1974
|
+
/* @__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, isText: element.type === "text" }) }) }),
|
|
1901
1975
|
/* @__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 }) }) }),
|
|
1902
1976
|
/* @__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 }) }) })
|
|
1903
1977
|
] })
|
|
@@ -2047,7 +2121,8 @@ function AdvancedSection({ element, onPatch }) {
|
|
|
2047
2121
|
var NO_ANIMATION = "none";
|
|
2048
2122
|
function AnimateSection({
|
|
2049
2123
|
animation,
|
|
2050
|
-
onSetAnimation
|
|
2124
|
+
onSetAnimation,
|
|
2125
|
+
isText
|
|
2051
2126
|
}) {
|
|
2052
2127
|
if (!onSetAnimation) {
|
|
2053
2128
|
return /* @__PURE__ */ jsxRuntime.jsx(reactFancy.Text, { size: "sm", className: "!text-zinc-500", children: "Build animations aren't wired up in this editor." });
|
|
@@ -2134,6 +2209,14 @@ function AnimateSection({
|
|
|
2134
2209
|
onChange: (e) => set({ order: parseInt(e.target.value, 10) || 0 })
|
|
2135
2210
|
}
|
|
2136
2211
|
),
|
|
2212
|
+
isText && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2213
|
+
reactFancy.Switch,
|
|
2214
|
+
{
|
|
2215
|
+
label: "Animate by paragraph (one line per click)",
|
|
2216
|
+
checked: !!animation?.byParagraph,
|
|
2217
|
+
onCheckedChange: (v) => set({ byParagraph: v })
|
|
2218
|
+
}
|
|
2219
|
+
),
|
|
2137
2220
|
/* @__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
2221
|
] })
|
|
2139
2222
|
] });
|
|
@@ -2847,10 +2930,13 @@ exports.deckId = deckId;
|
|
|
2847
2930
|
exports.defaultTheme = defaultTheme;
|
|
2848
2931
|
exports.defineTheme = defineTheme;
|
|
2849
2932
|
exports.elementId = elementId;
|
|
2933
|
+
exports.isByParagraph = isByParagraph;
|
|
2850
2934
|
exports.nextId = nextId;
|
|
2935
|
+
exports.paragraphReveals = paragraphReveals;
|
|
2851
2936
|
exports.reduceDeck = reduce;
|
|
2852
2937
|
exports.resolveTheme = resolveTheme;
|
|
2853
2938
|
exports.slideId = slideId;
|
|
2939
|
+
exports.splitParagraphs = splitParagraphs;
|
|
2854
2940
|
exports.stepDelays = stepDelays;
|
|
2855
2941
|
exports.totalBuildSteps = totalBuildSteps;
|
|
2856
2942
|
exports.useDeckState = useDeckState;
|