@particle-academy/fancy-slides 0.8.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.cjs +116 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -3
- package/dist/index.d.ts +44 -3
- package/dist/index.js +112 -5
- package/dist/index.js.map +1 -1
- package/dist/registry.d.cts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/{types-9BbelJX1.d.cts → types-C3w37g3A.d.cts} +25 -1
- package/dist/{types-9BbelJX1.d.ts → types-C3w37g3A.d.ts} +25 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -940,7 +940,18 @@ function SlideElementHost({
|
|
|
940
940
|
touchAction: canMove ? "none" : void 0,
|
|
941
941
|
...buildAnimation ? buildEnterStyle(buildAnimation, buildDelay) : null
|
|
942
942
|
};
|
|
943
|
-
const
|
|
943
|
+
const rendered = renderInner({ element, theme, slideWidthPx, editing, selected, onContentChange, paraReveal }) ?? renderElement?.(element, slideWidthPx) ?? elementPlaceholder(element);
|
|
944
|
+
const inner = element.href && !editing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
945
|
+
"a",
|
|
946
|
+
{
|
|
947
|
+
href: element.href,
|
|
948
|
+
target: "_blank",
|
|
949
|
+
rel: "noreferrer",
|
|
950
|
+
style: { display: "block", width: "100%", height: "100%", color: "inherit", textDecoration: "inherit" },
|
|
951
|
+
"data-fancy-slides-href": "",
|
|
952
|
+
children: rendered
|
|
953
|
+
}
|
|
954
|
+
) : rendered;
|
|
944
955
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
945
956
|
"div",
|
|
946
957
|
{
|
|
@@ -1782,6 +1793,7 @@ function useDeckState({ value, onChange, onOp }) {
|
|
|
1782
1793
|
apply,
|
|
1783
1794
|
setTitle: (title) => apply({ kind: "deck_set_title", title }),
|
|
1784
1795
|
applyTheme: (theme) => apply({ kind: "deck_apply_theme", theme }),
|
|
1796
|
+
setDeck: (deck) => apply({ kind: "deck_set", deck }),
|
|
1785
1797
|
addSlide: (index, partial) => {
|
|
1786
1798
|
const id = partial?.id ?? slideId();
|
|
1787
1799
|
const slide = {
|
|
@@ -1836,6 +1848,8 @@ function reduce(deck, op) {
|
|
|
1836
1848
|
return { ...deck, title: op.title };
|
|
1837
1849
|
case "deck_apply_theme":
|
|
1838
1850
|
return { ...deck, theme: op.theme };
|
|
1851
|
+
case "deck_set":
|
|
1852
|
+
return op.deck;
|
|
1839
1853
|
case "slide_add": {
|
|
1840
1854
|
const slides = [...deck.slides];
|
|
1841
1855
|
slides.splice(Math.max(0, Math.min(slides.length, op.index)), 0, op.slide);
|
|
@@ -2284,7 +2298,7 @@ function ElementInspector({ element, onPatch, onDelete, onLockToggle, slide, onS
|
|
|
2284
2298
|
/* @__PURE__ */ jsxRuntime.jsxs(reactFancy.Tabs.Panels, { children: [
|
|
2285
2299
|
/* @__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 }) }) }),
|
|
2286
2300
|
/* @__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" }) }) }),
|
|
2287
|
-
/* @__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 }) }) }),
|
|
2301
|
+
/* @__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, siblings: slide?.elements ?? [] }) }) }),
|
|
2288
2302
|
/* @__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 }) }) })
|
|
2289
2303
|
] })
|
|
2290
2304
|
] }) })
|
|
@@ -2489,7 +2503,10 @@ function buildLabel(element) {
|
|
|
2489
2503
|
}
|
|
2490
2504
|
return `${element.type} #${element.id.slice(-6)}`;
|
|
2491
2505
|
}
|
|
2492
|
-
function LayoutSection({ element, onPatch }) {
|
|
2506
|
+
function LayoutSection({ element, onPatch, siblings }) {
|
|
2507
|
+
const zs = siblings.map((e) => e.z ?? 0);
|
|
2508
|
+
const bringToFront = () => onPatch({ z: (zs.length ? Math.max(...zs) : 0) + 1 });
|
|
2509
|
+
const sendToBack = () => onPatch({ z: (zs.length ? Math.min(...zs) : 0) - 1 });
|
|
2493
2510
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2494
2511
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
2495
2512
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Input, { label: "X", type: "number", value: String(roundFrac(element.x)), onChange: (e) => onPatch({ x: clamp2(parseFloat(e.target.value), 0, 1) }) }),
|
|
@@ -2499,7 +2516,26 @@ function LayoutSection({ element, onPatch }) {
|
|
|
2499
2516
|
] }),
|
|
2500
2517
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Separator, {}),
|
|
2501
2518
|
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Slider, { label: "Rotation", value: element.rotation ?? 0, onValueChange: (v) => onPatch({ rotation: Number(v) }), min: -180, max: 180 }),
|
|
2502
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2519
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-2", children: [
|
|
2520
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Input, { label: "Z-index", type: "number", value: String(element.z ?? 0), onChange: (e) => onPatch({ z: parseInt(e.target.value, 10) || 0 }), className: "flex-1" }),
|
|
2521
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Action, { size: "sm", variant: "ghost", onClick: bringToFront, "aria-label": "Bring to front", children: "Front" }),
|
|
2522
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Action, { size: "sm", variant: "ghost", onClick: sendToBack, "aria-label": "Send to back", children: "Back" })
|
|
2523
|
+
] }),
|
|
2524
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactFancy.Separator, {}),
|
|
2525
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2526
|
+
reactFancy.Input,
|
|
2527
|
+
{
|
|
2528
|
+
label: "Link (href)",
|
|
2529
|
+
value: element.href ?? "",
|
|
2530
|
+
placeholder: "https://\u2026",
|
|
2531
|
+
onChange: (e) => onPatch({ href: e.target.value || void 0 })
|
|
2532
|
+
}
|
|
2533
|
+
),
|
|
2534
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactFancy.Text, { size: "xs", className: "!text-zinc-500", children: [
|
|
2535
|
+
"Makes the whole element a click target in the viewer (opens a new tab) and exports as a pptx hyperlink. For links inside text, use markdown ",
|
|
2536
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: "[label](url)" }),
|
|
2537
|
+
"."
|
|
2538
|
+
] })
|
|
2503
2539
|
] });
|
|
2504
2540
|
}
|
|
2505
2541
|
function AdvancedSection({ element, onPatch }) {
|
|
@@ -3321,12 +3357,84 @@ function DeckEditor({
|
|
|
3321
3357
|
);
|
|
3322
3358
|
}
|
|
3323
3359
|
|
|
3360
|
+
// src/types.ts
|
|
3361
|
+
var SCHEMA_VERSION = 1;
|
|
3362
|
+
|
|
3363
|
+
// src/utils/serialize.ts
|
|
3364
|
+
var ELEMENT_TYPES = ["text", "image", "chart", "code", "table", "shape", "embed"];
|
|
3365
|
+
function validateDeck(deck) {
|
|
3366
|
+
const errors = [];
|
|
3367
|
+
const d = deck;
|
|
3368
|
+
if (!d || typeof d !== "object") {
|
|
3369
|
+
return { ok: false, errors: ["deck is not an object"] };
|
|
3370
|
+
}
|
|
3371
|
+
if (typeof d.id !== "string" || !d.id) errors.push("deck.id must be a non-empty string");
|
|
3372
|
+
if (typeof d.title !== "string") errors.push("deck.title must be a string");
|
|
3373
|
+
if (!d.theme || typeof d.theme !== "object") errors.push("deck.theme must be an object");
|
|
3374
|
+
if (!Array.isArray(d.slides)) {
|
|
3375
|
+
errors.push("deck.slides must be an array");
|
|
3376
|
+
return { ok: errors.length === 0, errors };
|
|
3377
|
+
}
|
|
3378
|
+
d.slides.forEach((slide, si) => {
|
|
3379
|
+
if (!slide || typeof slide !== "object") {
|
|
3380
|
+
errors.push(`slides[${si}] is not an object`);
|
|
3381
|
+
return;
|
|
3382
|
+
}
|
|
3383
|
+
if (typeof slide.id !== "string" || !slide.id) errors.push(`slides[${si}].id must be a non-empty string`);
|
|
3384
|
+
if (!Array.isArray(slide.elements)) {
|
|
3385
|
+
errors.push(`slides[${si}].elements must be an array`);
|
|
3386
|
+
return;
|
|
3387
|
+
}
|
|
3388
|
+
slide.elements.forEach((el, ei) => {
|
|
3389
|
+
const where = `slides[${si}].elements[${ei}]`;
|
|
3390
|
+
if (!el || typeof el !== "object") {
|
|
3391
|
+
errors.push(`${where} is not an object`);
|
|
3392
|
+
return;
|
|
3393
|
+
}
|
|
3394
|
+
if (typeof el.id !== "string" || !el.id) errors.push(`${where}.id must be a non-empty string`);
|
|
3395
|
+
if (!ELEMENT_TYPES.includes(el.type)) errors.push(`${where}.type "${el.type}" is not a known element type`);
|
|
3396
|
+
for (const k of ["x", "y", "w", "h"]) {
|
|
3397
|
+
const v = el[k];
|
|
3398
|
+
if (typeof v !== "number" || v < 0 || v > 1) errors.push(`${where}.${k} must be a number in 0..1`);
|
|
3399
|
+
}
|
|
3400
|
+
});
|
|
3401
|
+
});
|
|
3402
|
+
return { ok: errors.length === 0, errors };
|
|
3403
|
+
}
|
|
3404
|
+
function migrateDeck(deck) {
|
|
3405
|
+
let d = deck;
|
|
3406
|
+
d.version ?? 1;
|
|
3407
|
+
return d.version === SCHEMA_VERSION ? d : { ...d, version: SCHEMA_VERSION };
|
|
3408
|
+
}
|
|
3409
|
+
function serializeDeck(deck, pretty = false) {
|
|
3410
|
+
const stamped = deck.version === SCHEMA_VERSION ? deck : { ...deck, version: SCHEMA_VERSION };
|
|
3411
|
+
return JSON.stringify(stamped, null, pretty ? 2 : void 0);
|
|
3412
|
+
}
|
|
3413
|
+
function parseDeck(input) {
|
|
3414
|
+
let raw;
|
|
3415
|
+
if (typeof input === "string") {
|
|
3416
|
+
try {
|
|
3417
|
+
raw = JSON.parse(input);
|
|
3418
|
+
} catch (e) {
|
|
3419
|
+
throw new Error(`parseDeck: invalid JSON \u2014 ${e.message}`);
|
|
3420
|
+
}
|
|
3421
|
+
} else {
|
|
3422
|
+
raw = input;
|
|
3423
|
+
}
|
|
3424
|
+
const result = validateDeck(raw);
|
|
3425
|
+
if (!result.ok) {
|
|
3426
|
+
throw new Error(`parseDeck: invalid deck \u2014 ${result.errors.join("; ")}`);
|
|
3427
|
+
}
|
|
3428
|
+
return migrateDeck(raw);
|
|
3429
|
+
}
|
|
3430
|
+
|
|
3324
3431
|
exports.DeckEditor = DeckEditor;
|
|
3325
3432
|
exports.EditorToolbar = EditorToolbar;
|
|
3326
3433
|
exports.ElementInspector = ElementInspector;
|
|
3327
3434
|
exports.ImageElementRenderer = ImageElementRenderer;
|
|
3328
3435
|
exports.PRESENTATION_EDITOR_ACTIONS = PRESENTATION_EDITOR_ACTIONS;
|
|
3329
3436
|
exports.PresenterView = PresenterView;
|
|
3437
|
+
exports.SCHEMA_VERSION = SCHEMA_VERSION;
|
|
3330
3438
|
exports.ShapeElementRenderer = ShapeElementRenderer;
|
|
3331
3439
|
exports.Slide = Slide;
|
|
3332
3440
|
exports.SlideRail = SlideRail;
|
|
@@ -3345,11 +3453,14 @@ exports.defaultTheme = defaultTheme;
|
|
|
3345
3453
|
exports.defineTheme = defineTheme;
|
|
3346
3454
|
exports.elementId = elementId;
|
|
3347
3455
|
exports.isByParagraph = isByParagraph;
|
|
3456
|
+
exports.migrateDeck = migrateDeck;
|
|
3348
3457
|
exports.nextId = nextId;
|
|
3349
3458
|
exports.normalizeSlideMarkdown = normalizeSlideMarkdown;
|
|
3350
3459
|
exports.paragraphReveals = paragraphReveals;
|
|
3460
|
+
exports.parseDeck = parseDeck;
|
|
3351
3461
|
exports.reduceDeck = reduce;
|
|
3352
3462
|
exports.resolveTheme = resolveTheme;
|
|
3463
|
+
exports.serializeDeck = serializeDeck;
|
|
3353
3464
|
exports.slideId = slideId;
|
|
3354
3465
|
exports.splitParagraphs = splitParagraphs;
|
|
3355
3466
|
exports.stepDelays = stepDelays;
|
|
@@ -3359,6 +3470,7 @@ exports.useIsDarkSlide = useIsDarkSlide;
|
|
|
3359
3470
|
exports.useSlideContext = useSlideContext;
|
|
3360
3471
|
exports.useSlideKeyboard = useSlideKeyboard;
|
|
3361
3472
|
exports.useSlideTheme = useSlideTheme;
|
|
3473
|
+
exports.validateDeck = validateDeck;
|
|
3362
3474
|
exports.visibleElementIds = visibleElementIds;
|
|
3363
3475
|
exports.vividTheme = vividTheme;
|
|
3364
3476
|
//# sourceMappingURL=index.cjs.map
|