@classic-homes/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 +11 -1
- package/dist/{chunk-YI7A4EWX.js → chunk-JFUJ47TP.js} +2 -2
- package/dist/{chunk-2IPLZ3SA.js → chunk-L7G3VH7K.js} +2 -2
- package/dist/{chunk-GXGDPBAR.js → chunk-PTTLL6PQ.js} +148 -5
- package/dist/{chunk-GXGDPBAR.js.map → chunk-PTTLL6PQ.js.map} +1 -1
- package/dist/cli.js +4 -4
- package/dist/index.d.ts +21 -4
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/{mcp-PUA45IS7.js → mcp-UX32IP2J.js} +4 -4
- package/dist/node.d.ts +2 -2
- package/dist/node.js +2 -2
- package/dist/{render-DcyKuBRD.d.ts → render-CU0sXO2y.d.ts} +25 -1
- package/package.json +1 -1
- /package/dist/{chunk-YI7A4EWX.js.map → chunk-JFUJ47TP.js.map} +0 -0
- /package/dist/{chunk-2IPLZ3SA.js.map → chunk-L7G3VH7K.js.map} +0 -0
- /package/dist/{mcp-PUA45IS7.js.map → mcp-UX32IP2J.js.map} +0 -0
package/README.md
CHANGED
|
@@ -165,7 +165,17 @@ The core entry has no Node dependencies (it runs in Workers and browsers);
|
|
|
165
165
|
(with `hint`s for chart, grid, url, video-url and point pickers),
|
|
166
166
|
`blankSlide(layout)` gives a valid starting slide, and `renderDeck(deck,
|
|
167
167
|
{ includeHidden: true, initialSlide })` plus the `postMessage` API drive a
|
|
168
|
-
live preview.
|
|
168
|
+
live preview. Fields flagged `advanced` (slide id, speaking time, accent
|
|
169
|
+
colour) belong behind an "Advanced" section.
|
|
170
|
+
|
|
171
|
+
Click-to-edit: render the preview with `editorMarkers: true` and, inside an
|
|
172
|
+
iframe, clicking a title, bullet or picture posts
|
|
173
|
+
`{ type: 'classic-slides:select', index, path }` to the parent (`index` is the
|
|
174
|
+
deck slide, `path` the field such as `['items', 2, 'text']`, or `null` for the
|
|
175
|
+
slide itself). Send `{ type: 'classic-slides:highlight', index, path }` to
|
|
176
|
+
outline the field being edited. Never turn it on for shared or exported decks.
|
|
177
|
+
`layoutGalleryDeck()` returns one deck with every layout's starting slide, for
|
|
178
|
+
rendering a layout picker's thumbnails in one pass.
|
|
169
179
|
|
|
170
180
|
Rendered HTML embeds the deck source (minus image data), so
|
|
171
181
|
`extractDeckSource(html)` recovers the editable deck.
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
LAYOUT_CATEGORIES,
|
|
5
5
|
baseSlide,
|
|
6
6
|
getLayout
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-PTTLL6PQ.js";
|
|
8
8
|
|
|
9
9
|
// src/catalog.ts
|
|
10
10
|
import { z } from "zod";
|
|
@@ -104,4 +104,4 @@ export {
|
|
|
104
104
|
deckJsonSchema,
|
|
105
105
|
AUTHORING_GUIDE
|
|
106
106
|
};
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
107
|
+
//# sourceMappingURL=chunk-JFUJ47TP.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
parseDeckSource,
|
|
3
3
|
renderDeck,
|
|
4
4
|
stringifyDeck
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PTTLL6PQ.js";
|
|
6
6
|
|
|
7
7
|
// src/node/index.ts
|
|
8
8
|
import { readFile, stat, writeFile } from "fs/promises";
|
|
@@ -103,4 +103,4 @@ export {
|
|
|
103
103
|
saveDeckFile,
|
|
104
104
|
buildDeckFile
|
|
105
105
|
};
|
|
106
|
-
//# sourceMappingURL=chunk-
|
|
106
|
+
//# sourceMappingURL=chunk-L7G3VH7K.js.map
|
|
@@ -620,6 +620,10 @@ function prose(text) {
|
|
|
620
620
|
return `<p>${inline(para)}</p>`;
|
|
621
621
|
}).join("");
|
|
622
622
|
}
|
|
623
|
+
function plain(text) {
|
|
624
|
+
if (!text) return "";
|
|
625
|
+
return text.replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1");
|
|
626
|
+
}
|
|
623
627
|
|
|
624
628
|
// src/video.ts
|
|
625
629
|
var YT = /^(?:https:\/\/)?(?:www\.|m\.)?(?:youtube\.com\/(?:watch\?(?:.*&)?v=|embed\/|shorts\/|live\/)|youtu\.be\/)([\w-]{11})/;
|
|
@@ -2193,8 +2197,11 @@ var LABELS = {
|
|
|
2193
2197
|
imageAspect: "Photo shape",
|
|
2194
2198
|
numberFrom: "First badge number",
|
|
2195
2199
|
url: "URL",
|
|
2196
|
-
id: "Slide id"
|
|
2200
|
+
id: "Slide id",
|
|
2201
|
+
time: "Speaking time",
|
|
2202
|
+
track: "Accent colour"
|
|
2197
2203
|
};
|
|
2204
|
+
var ADVANCED = /* @__PURE__ */ new Set(["id", "time", "track"]);
|
|
2198
2205
|
function labelFor(key) {
|
|
2199
2206
|
if (LABELS[key]) return LABELS[key];
|
|
2200
2207
|
const words = key.replace(/([A-Z])/g, " $1").toLowerCase();
|
|
@@ -2231,7 +2238,8 @@ function describeField(key, schema) {
|
|
|
2231
2238
|
required,
|
|
2232
2239
|
...description ? { description } : {},
|
|
2233
2240
|
...dflt !== void 0 ? { default: dflt } : {},
|
|
2234
|
-
...MULTILINE.has(key) ? { multiline: true } : {}
|
|
2241
|
+
...MULTILINE.has(key) ? { multiline: true } : {},
|
|
2242
|
+
...ADVANCED.has(key) ? { advanced: true } : {}
|
|
2235
2243
|
};
|
|
2236
2244
|
if (inner === Image) return { ...base, kind: "image" };
|
|
2237
2245
|
if (inner === ChartSpec) {
|
|
@@ -2335,6 +2343,16 @@ function layoutEditorInfo(name) {
|
|
|
2335
2343
|
function allLayoutEditorInfo() {
|
|
2336
2344
|
return LAYOUTS.map((l) => layoutEditorInfo(l.name));
|
|
2337
2345
|
}
|
|
2346
|
+
function layoutGalleryDeck() {
|
|
2347
|
+
const slides = [];
|
|
2348
|
+
const slideFor = {};
|
|
2349
|
+
for (const layout of LAYOUTS) {
|
|
2350
|
+
slideFor[layout.name] = slides.length;
|
|
2351
|
+
slides.push(blankSlide(layout.name));
|
|
2352
|
+
}
|
|
2353
|
+
const journey2 = { steps: ["Contract", "Design", "Build", "Close", "Move in", "Warranty"] };
|
|
2354
|
+
return { deck: { title: "Layouts", journey: journey2, slides }, slideFor };
|
|
2355
|
+
}
|
|
2338
2356
|
var PLACEHOLDER_IMAGE = "data:image/svg+xml;base64," + btoa(
|
|
2339
2357
|
'<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 1600 1000"><rect width="1600" height="1000" fill="#ecebe6"/><rect x="24" y="24" width="1552" height="952" fill="none" stroke="#b9bcb4" stroke-width="6" stroke-dasharray="28 20"/><text x="800" y="520" text-anchor="middle" font-family="Figtree,Arial,sans-serif" font-size="64" fill="#7a7a7a">Add a photo</text></svg>'
|
|
2340
2358
|
);
|
|
@@ -2567,8 +2585,83 @@ var RUNTIME_JS = String.raw`
|
|
|
2567
2585
|
if (!embedded || e.source !== window.parent) return;
|
|
2568
2586
|
if (d.type === 'classic-slides:go' && Number.isInteger(d.index)) go(d.index, true);
|
|
2569
2587
|
else if (d.type === 'classic-slides:notes') { if (notes && notes.classList.contains('open') !== !!d.open) toggleNotes(); }
|
|
2588
|
+
else if (d.type === 'classic-slides:highlight' && editor) highlight(d.index, d.path);
|
|
2570
2589
|
});
|
|
2571
2590
|
|
|
2591
|
+
// ---------- editor click-to-edit ----------
|
|
2592
|
+
// Matches the clicked element to a slide field by its visible text (or an
|
|
2593
|
+
// image by its src), walking up from the target, so layouts need no markup.
|
|
2594
|
+
const editor = embedded && body.hasAttribute('data-editor');
|
|
2595
|
+
const fieldsEl = editor && document.getElementById('deck-fields');
|
|
2596
|
+
const FIELDS = fieldsEl ? JSON.parse(fieldsEl.textContent || '[]') : [];
|
|
2597
|
+
const norm = (t) => (t || '').replace(/\s+/g, ' ').trim();
|
|
2598
|
+
function ownText(el) {
|
|
2599
|
+
let t = '';
|
|
2600
|
+
el.childNodes.forEach((n) => { if (n.nodeType === 3) t += n.textContent; });
|
|
2601
|
+
return norm(t);
|
|
2602
|
+
}
|
|
2603
|
+
function fieldFor(el, candidates) {
|
|
2604
|
+
if (el.tagName === 'IMG') {
|
|
2605
|
+
const src = el.getAttribute('src');
|
|
2606
|
+
return candidates.find((c) => c.img && c.img === src);
|
|
2607
|
+
}
|
|
2608
|
+
const text = norm(el.textContent);
|
|
2609
|
+
const own = ownText(el);
|
|
2610
|
+
return candidates.find((c) => c.text && (c.text === text || (own && c.text === own)));
|
|
2611
|
+
}
|
|
2612
|
+
function locate(target) {
|
|
2613
|
+
const section = target.closest && target.closest('.slide');
|
|
2614
|
+
if (!section) return null;
|
|
2615
|
+
const index = Number(section.getAttribute('data-index'));
|
|
2616
|
+
const candidates = FIELDS[index] || [];
|
|
2617
|
+
for (let el = target; el && el !== section; el = el.parentElement) {
|
|
2618
|
+
const field = fieldFor(el, candidates);
|
|
2619
|
+
if (field) return { index, path: field.path, el };
|
|
2620
|
+
}
|
|
2621
|
+
return { index, path: null, el: section };
|
|
2622
|
+
}
|
|
2623
|
+
let hovered = null;
|
|
2624
|
+
let selected = null;
|
|
2625
|
+
function highlight(index, path) {
|
|
2626
|
+
selected?.classList.remove('cs-edit-selected');
|
|
2627
|
+
selected = null;
|
|
2628
|
+
if (!Array.isArray(path)) return;
|
|
2629
|
+
const key = JSON.stringify(path);
|
|
2630
|
+
const candidates = FIELDS[index] || [];
|
|
2631
|
+
for (const section of deck.querySelectorAll('.slide[data-index="' + index + '"]')) {
|
|
2632
|
+
for (const el of section.querySelectorAll('*')) {
|
|
2633
|
+
const field = fieldFor(el, candidates);
|
|
2634
|
+
if (field && JSON.stringify(field.path) === key) {
|
|
2635
|
+
selected = el;
|
|
2636
|
+
el.classList.add('cs-edit-selected');
|
|
2637
|
+
return;
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
if (editor) {
|
|
2643
|
+
const style = document.createElement('style');
|
|
2644
|
+
style.textContent = '.cs-edit-hover{outline:2px dashed rgba(0,122,255,.7);outline-offset:4px;cursor:pointer}' +
|
|
2645
|
+
'.cs-edit-selected{outline:2px solid rgb(0,122,255);outline-offset:4px}';
|
|
2646
|
+
document.head.appendChild(style);
|
|
2647
|
+
deck.addEventListener('click', (e) => {
|
|
2648
|
+
const hit = locate(e.target);
|
|
2649
|
+
if (!hit) return;
|
|
2650
|
+
// Links on a slide would navigate the preview away
|
|
2651
|
+
if (e.target.closest('a[href]')) e.preventDefault();
|
|
2652
|
+
window.parent.postMessage({ type: 'classic-slides:select', index: hit.index, path: hit.path }, '*');
|
|
2653
|
+
}, true);
|
|
2654
|
+
deck.addEventListener('mouseover', (e) => {
|
|
2655
|
+
const hit = locate(e.target);
|
|
2656
|
+
const el = hit && hit.path ? hit.el : null;
|
|
2657
|
+
if (el === hovered) return;
|
|
2658
|
+
hovered?.classList.remove('cs-edit-hover');
|
|
2659
|
+
hovered = el;
|
|
2660
|
+
el?.classList.add('cs-edit-hover');
|
|
2661
|
+
});
|
|
2662
|
+
deck.addEventListener('mouseleave', () => { hovered?.classList.remove('cs-edit-hover'); hovered = null; });
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2572
2665
|
function onKey(e) {
|
|
2573
2666
|
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
2574
2667
|
const k = e.key;
|
|
@@ -3286,6 +3379,48 @@ body.presenter{margin:0;height:100vh;display:grid;grid-template-rows:1fr auto;ba
|
|
|
3286
3379
|
|
|
3287
3380
|
// src/render.ts
|
|
3288
3381
|
var PREVIEW_SIZE = { width: 1280, height: 720 };
|
|
3382
|
+
var NON_VISUAL_KEYS = /* @__PURE__ */ new Set([
|
|
3383
|
+
"layout",
|
|
3384
|
+
"id",
|
|
3385
|
+
"notes",
|
|
3386
|
+
"time",
|
|
3387
|
+
"hidden",
|
|
3388
|
+
"background",
|
|
3389
|
+
"backgroundImage",
|
|
3390
|
+
"overlay",
|
|
3391
|
+
"track",
|
|
3392
|
+
"step",
|
|
3393
|
+
"stepDone",
|
|
3394
|
+
"showJourney",
|
|
3395
|
+
"href",
|
|
3396
|
+
"url",
|
|
3397
|
+
"fit",
|
|
3398
|
+
"focus",
|
|
3399
|
+
"size",
|
|
3400
|
+
"alt"
|
|
3401
|
+
]);
|
|
3402
|
+
function fieldMarkers(slide, resolveImage = (src) => src) {
|
|
3403
|
+
const out = [];
|
|
3404
|
+
const walk = (value, path) => {
|
|
3405
|
+
if (typeof value === "string") {
|
|
3406
|
+
const text = plain(value).replace(/\s+/g, " ").trim();
|
|
3407
|
+
if (text) out.push({ path, text });
|
|
3408
|
+
} else if (Array.isArray(value)) {
|
|
3409
|
+
value.forEach((v, i) => walk(v, [...path, i]));
|
|
3410
|
+
} else if (value && typeof value === "object") {
|
|
3411
|
+
const obj = value;
|
|
3412
|
+
if (typeof obj.src === "string") {
|
|
3413
|
+
out.push({ path, img: resolveImage(obj.src) });
|
|
3414
|
+
return;
|
|
3415
|
+
}
|
|
3416
|
+
for (const [key, v] of Object.entries(obj)) {
|
|
3417
|
+
if (!NON_VISUAL_KEYS.has(key)) walk(v, [...path, key]);
|
|
3418
|
+
}
|
|
3419
|
+
}
|
|
3420
|
+
};
|
|
3421
|
+
walk(slide, []);
|
|
3422
|
+
return out;
|
|
3423
|
+
}
|
|
3289
3424
|
var passThrough = (src) => {
|
|
3290
3425
|
if (/^(data:|https?:)/.test(src)) return src;
|
|
3291
3426
|
throw new Error(
|
|
@@ -3476,6 +3611,12 @@ async function renderDeck(input, options = {}) {
|
|
|
3476
3611
|
});
|
|
3477
3612
|
});
|
|
3478
3613
|
const withNotes = options.speakerNotes !== false;
|
|
3614
|
+
const fields = options.editorMarkers ? `<script type="application/json" id="deck-fields">${JSON.stringify(
|
|
3615
|
+
deck.slides.map(
|
|
3616
|
+
(slide) => fieldMarkers(slide, (src) => images.get(src) ?? src)
|
|
3617
|
+
)
|
|
3618
|
+
).replace(/</g, "\\u003c")}</script>
|
|
3619
|
+
` : "";
|
|
3479
3620
|
const json = (v) => JSON.stringify(v).replace(/</g, "\\u003c");
|
|
3480
3621
|
const stripData = (key, v) => !withNotes && key === "notes" ? void 0 : typeof v === "string" && /^data:/i.test(v) ? "(embedded)" : v;
|
|
3481
3622
|
const source = options.embedSource === false ? "" : `<script type="application/json" id="deck-source">${JSON.stringify(deck, stripData).replace(/</g, "\\u003c")}</script>
|
|
@@ -3492,7 +3633,7 @@ ${deck.description ? `<meta name="description" content="${escapeAttr(deck.descri
|
|
|
3492
3633
|
<style id="brand-fonts">${fontsCss()}</style>
|
|
3493
3634
|
<style>${tokensCss(brand.stock ? void 0 : brand.palette)}${DECK_CSS}${DECK_CSS_EXTRA}</style>
|
|
3494
3635
|
</head>
|
|
3495
|
-
<body${wantFooter ? ' class="has-foot"' : ""}${options.initialSlide ? ` data-initial-slide="${Math.max(0, Math.floor(options.initialSlide))}"` : ""}${deck.settings.autoAdvance ? ` data-auto-advance="${deck.settings.autoAdvance}"` : ""}${deck.settings.loop ? " data-loop" : ""}${options.allowEmbeddedKiosk ? " data-embedded-kiosk" : ""}>
|
|
3636
|
+
<body${wantFooter ? ' class="has-foot"' : ""}${options.initialSlide ? ` data-initial-slide="${Math.max(0, Math.floor(options.initialSlide))}"` : ""}${deck.settings.autoAdvance ? ` data-auto-advance="${deck.settings.autoAdvance}"` : ""}${deck.settings.loop ? " data-loop" : ""}${options.allowEmbeddedKiosk ? " data-embedded-kiosk" : ""}${options.editorMarkers ? " data-editor" : ""}>
|
|
3496
3637
|
<div class="rail" id="rail"></div>
|
|
3497
3638
|
<main class="deck" id="deck">
|
|
3498
3639
|
${sections.join("\n")}
|
|
@@ -3503,7 +3644,7 @@ ${withNotes ? `<div class="hud"><span class="counter" id="counter" aria-live="po
|
|
|
3503
3644
|
<aside class="notes" id="notes" aria-live="polite"><div class="notes__head"><span class="tag">Speaker notes</span><span class="time" id="notesTime"></span></div><div class="notes__body" id="notesBody"></div></aside>` : `<div class="hud"><span class="counter" id="counter" aria-live="polite"></span></div>
|
|
3504
3645
|
<div class="hint"><kbd>↑</kbd><kbd>↓</kbd> or <kbd>Space</kbd> navigate · <kbd>O</kbd> overview · <kbd>F</kbd> fullscreen</div>`}
|
|
3505
3646
|
<script type="application/json" id="deck-notes">${json(withNotes ? notes : [])}</script>
|
|
3506
|
-
${source}<script>${RUNTIME_JS}</script>
|
|
3647
|
+
${source}${fields}<script>${RUNTIME_JS}</script>
|
|
3507
3648
|
</body>
|
|
3508
3649
|
</html>
|
|
3509
3650
|
`;
|
|
@@ -3727,6 +3868,7 @@ export {
|
|
|
3727
3868
|
commonSlideFields,
|
|
3728
3869
|
layoutEditorInfo,
|
|
3729
3870
|
allLayoutEditorInfo,
|
|
3871
|
+
layoutGalleryDeck,
|
|
3730
3872
|
PLACEHOLDER_IMAGE,
|
|
3731
3873
|
isPlaceholderImage,
|
|
3732
3874
|
blankSlide,
|
|
@@ -3735,10 +3877,11 @@ export {
|
|
|
3735
3877
|
formatIssues,
|
|
3736
3878
|
DeckError,
|
|
3737
3879
|
PREVIEW_SIZE,
|
|
3880
|
+
fieldMarkers,
|
|
3738
3881
|
collectImageSources,
|
|
3739
3882
|
renderDeck,
|
|
3740
3883
|
extractDeckSource,
|
|
3741
3884
|
parseDeckSource,
|
|
3742
3885
|
stringifyDeck
|
|
3743
3886
|
};
|
|
3744
|
-
//# sourceMappingURL=chunk-
|
|
3887
|
+
//# sourceMappingURL=chunk-PTTLL6PQ.js.map
|