@atom63/slides 0.4.1 → 0.4.2
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/editor/index.js +123 -130
- package/dist/editor/index.js.map +1 -1
- package/package.json +1 -1
- package/src/editor/styles.css +0 -23
package/dist/editor/index.js
CHANGED
|
@@ -599,7 +599,6 @@ function EditPane({
|
|
|
599
599
|
onPresent,
|
|
600
600
|
themeValue
|
|
601
601
|
}) {
|
|
602
|
-
const [theme, setTheme] = useState("light");
|
|
603
602
|
const [rightTab, setRightTab] = useState("source");
|
|
604
603
|
const [formSlideIdx, setFormSlideIdx] = useState(0);
|
|
605
604
|
const textareaRef = useRef(null);
|
|
@@ -652,149 +651,143 @@ ${snippet}`);
|
|
|
652
651
|
},
|
|
653
652
|
[source, clampedIdx, onChange]
|
|
654
653
|
);
|
|
655
|
-
return
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
654
|
+
return (
|
|
655
|
+
// data-slides-theme on the real grid box (NOT a display:contents wrapper) so
|
|
656
|
+
// the deck theme's custom properties reliably cascade to the slide preview.
|
|
657
|
+
/* @__PURE__ */ jsxs("div", { className: "a63-editor", "data-slides-theme": themeValue || void 0, children: [
|
|
658
|
+
/* @__PURE__ */ jsxs("section", { className: "a63-editor__preview", children: [
|
|
659
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "a63-editor__error", role: "alert", children: [
|
|
660
|
+
/* @__PURE__ */ jsx$1("span", { className: "a63-editor__error-tag", children: "MDX error" }),
|
|
661
|
+
/* @__PURE__ */ jsx$1("span", { className: "a63-editor__error-msg", children: error })
|
|
662
|
+
] }) : null,
|
|
663
|
+
deck ? /* @__PURE__ */ jsx$1("div", { className: "a63-editor__preview-stage", children: /* @__PURE__ */ jsx$1(SlidesPlayer, { deck, onBack: () => {
|
|
664
|
+
} }) }) : /* @__PURE__ */ jsx$1("div", { className: "a63-editor__preview-empty", children: error ? "Fix the MDX error to render a preview." : "Compiling preview\u2026" })
|
|
665
|
+
] }),
|
|
666
|
+
/* @__PURE__ */ jsxs("section", { className: "a63-editor__source", children: [
|
|
667
|
+
/* @__PURE__ */ jsxs("div", { className: "a63-editor__toolbar", children: [
|
|
668
|
+
/* @__PURE__ */ jsx$1("span", { className: "a63-editor__title", children: "Deck source \xB7 MDX" }),
|
|
669
|
+
/* @__PURE__ */ jsxs("div", { className: "a63-editor__toolbar-actions", children: [
|
|
670
|
+
/* @__PURE__ */ jsxs("div", { className: "a63-editor__subtoggle", role: "group", "aria-label": "Edit mode", children: [
|
|
671
|
+
/* @__PURE__ */ jsx$1(
|
|
672
|
+
"button",
|
|
673
|
+
{
|
|
674
|
+
type: "button",
|
|
675
|
+
className: "a63-editor__subtoggle-btn",
|
|
676
|
+
"aria-pressed": rightTab === "source",
|
|
677
|
+
onClick: () => setRightTab("source"),
|
|
678
|
+
children: "Source"
|
|
679
|
+
}
|
|
680
|
+
),
|
|
681
|
+
/* @__PURE__ */ jsx$1(
|
|
682
|
+
"button",
|
|
683
|
+
{
|
|
684
|
+
type: "button",
|
|
685
|
+
className: "a63-editor__subtoggle-btn",
|
|
686
|
+
"aria-pressed": rightTab === "form",
|
|
687
|
+
onClick: () => setRightTab("form"),
|
|
688
|
+
children: "Form"
|
|
689
|
+
}
|
|
690
|
+
)
|
|
691
|
+
] }),
|
|
692
|
+
/* @__PURE__ */ jsx$1(ThemePicker, { source, theme: themeValue, onChange }),
|
|
693
|
+
onSave ? /* @__PURE__ */ jsx$1("button", { type: "button", className: "a63-editor__save", onClick: () => onSave(source), children: "Save" }) : null,
|
|
694
|
+
/* @__PURE__ */ jsx$1("button", { type: "button", className: "a63-editor__present", onClick: onPresent, children: "Present" })
|
|
695
|
+
] })
|
|
696
|
+
] }),
|
|
697
|
+
rightTab === "source" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
698
|
+
/* @__PURE__ */ jsx$1(
|
|
699
|
+
"textarea",
|
|
700
|
+
{
|
|
701
|
+
ref: textareaRef,
|
|
702
|
+
className: "a63-editor__textarea",
|
|
703
|
+
value: source,
|
|
704
|
+
onChange: handleChange,
|
|
705
|
+
onKeyDown: handleKeyDown,
|
|
706
|
+
spellCheck: false,
|
|
707
|
+
"aria-label": "Deck MDX source"
|
|
708
|
+
}
|
|
709
|
+
),
|
|
710
|
+
/* @__PURE__ */ jsxs("div", { className: "a63-editor__palette", children: [
|
|
711
|
+
/* @__PURE__ */ jsx$1("div", { className: "a63-editor__palette-label", children: "Templates \xB7 click to append" }),
|
|
712
|
+
/* @__PURE__ */ jsx$1("div", { className: "a63-editor__palette-grid", children: templates.map((t) => /* @__PURE__ */ jsxs(
|
|
713
|
+
"button",
|
|
714
|
+
{
|
|
715
|
+
type: "button",
|
|
716
|
+
className: "a63-editor__chip",
|
|
717
|
+
onClick: () => insert(t.name),
|
|
718
|
+
title: `Insert ${t.name}`,
|
|
719
|
+
children: [
|
|
720
|
+
/* @__PURE__ */ jsx$1("span", { className: "a63-editor__chip-name", children: t.name }),
|
|
721
|
+
/* @__PURE__ */ jsx$1("span", { className: "a63-editor__chip-meta", children: t.label })
|
|
722
|
+
]
|
|
723
|
+
},
|
|
724
|
+
t.name
|
|
725
|
+
)) })
|
|
726
|
+
] })
|
|
727
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "a63-editor__form-panel", children: [
|
|
728
|
+
/* @__PURE__ */ jsxs("div", { className: "a63-editor__slide-stepper", children: [
|
|
669
729
|
/* @__PURE__ */ jsx$1(
|
|
670
730
|
"button",
|
|
671
731
|
{
|
|
672
732
|
type: "button",
|
|
673
|
-
className: "a63-
|
|
674
|
-
"aria-
|
|
675
|
-
|
|
676
|
-
|
|
733
|
+
className: "a63-editor__stepper-btn",
|
|
734
|
+
"aria-label": "Previous slide",
|
|
735
|
+
disabled: clampedIdx <= 0,
|
|
736
|
+
onClick: () => setFormSlideIdx((i) => Math.max(0, i - 1)),
|
|
737
|
+
children: "\u2039"
|
|
677
738
|
}
|
|
678
739
|
),
|
|
740
|
+
/* @__PURE__ */ jsxs("span", { className: "a63-editor__stepper-label", children: [
|
|
741
|
+
"Slide ",
|
|
742
|
+
clampedIdx + 1,
|
|
743
|
+
" / ",
|
|
744
|
+
slideCount
|
|
745
|
+
] }),
|
|
679
746
|
/* @__PURE__ */ jsx$1(
|
|
680
747
|
"button",
|
|
681
748
|
{
|
|
682
749
|
type: "button",
|
|
683
|
-
className: "a63-
|
|
684
|
-
"aria-
|
|
685
|
-
|
|
686
|
-
|
|
750
|
+
className: "a63-editor__stepper-btn",
|
|
751
|
+
"aria-label": "Next slide",
|
|
752
|
+
disabled: clampedIdx >= slideCount - 1,
|
|
753
|
+
onClick: () => setFormSlideIdx((i) => Math.min(slideCount - 1, i + 1)),
|
|
754
|
+
children: "\u203A"
|
|
687
755
|
}
|
|
688
756
|
)
|
|
689
757
|
] }),
|
|
690
|
-
/* @__PURE__ */ jsx$1(
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
),
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
/* @__PURE__ */ jsx$1("div", { className: "a63-editor__palette-label", children: "Templates \xB7 click to append" }),
|
|
720
|
-
/* @__PURE__ */ jsx$1("div", { className: "a63-editor__palette-grid", children: templates.map((t) => /* @__PURE__ */ jsxs(
|
|
721
|
-
"button",
|
|
722
|
-
{
|
|
723
|
-
type: "button",
|
|
724
|
-
className: "a63-editor__chip",
|
|
725
|
-
onClick: () => insert(t.name),
|
|
726
|
-
title: `Insert ${t.name}`,
|
|
727
|
-
children: [
|
|
728
|
-
/* @__PURE__ */ jsx$1("span", { className: "a63-editor__chip-name", children: t.name }),
|
|
729
|
-
/* @__PURE__ */ jsx$1("span", { className: "a63-editor__chip-meta", children: t.label })
|
|
730
|
-
]
|
|
731
|
-
},
|
|
732
|
-
t.name
|
|
733
|
-
)) })
|
|
734
|
-
] })
|
|
735
|
-
] }) : /* @__PURE__ */ jsxs("div", { className: "a63-editor__form-panel", children: [
|
|
736
|
-
/* @__PURE__ */ jsxs("div", { className: "a63-editor__slide-stepper", children: [
|
|
737
|
-
/* @__PURE__ */ jsx$1(
|
|
738
|
-
"button",
|
|
739
|
-
{
|
|
740
|
-
type: "button",
|
|
741
|
-
className: "a63-editor__stepper-btn",
|
|
742
|
-
"aria-label": "Previous slide",
|
|
743
|
-
disabled: clampedIdx <= 0,
|
|
744
|
-
onClick: () => setFormSlideIdx((i) => Math.max(0, i - 1)),
|
|
745
|
-
children: "\u2039"
|
|
746
|
-
}
|
|
747
|
-
),
|
|
748
|
-
/* @__PURE__ */ jsxs("span", { className: "a63-editor__stepper-label", children: [
|
|
749
|
-
"Slide ",
|
|
750
|
-
clampedIdx + 1,
|
|
751
|
-
" / ",
|
|
752
|
-
slideCount
|
|
753
|
-
] }),
|
|
754
|
-
/* @__PURE__ */ jsx$1(
|
|
755
|
-
"button",
|
|
756
|
-
{
|
|
757
|
-
type: "button",
|
|
758
|
-
className: "a63-editor__stepper-btn",
|
|
759
|
-
"aria-label": "Next slide",
|
|
760
|
-
disabled: clampedIdx >= slideCount - 1,
|
|
761
|
-
onClick: () => setFormSlideIdx((i) => Math.min(slideCount - 1, i + 1)),
|
|
762
|
-
children: "\u203A"
|
|
763
|
-
}
|
|
764
|
-
)
|
|
765
|
-
] }),
|
|
766
|
-
parsedSlide === null ? /* @__PURE__ */ jsx$1("p", { className: "a63-editor__form-empty", children: "No slides found." }) : parsedSlide.kind === "opaque" ? /* @__PURE__ */ jsxs("div", { className: "a63-editor__form-opaque", children: [
|
|
767
|
-
/* @__PURE__ */ jsx$1("p", { children: "This slide is only editable in Source." }),
|
|
768
|
-
/* @__PURE__ */ jsx$1(
|
|
769
|
-
"button",
|
|
770
|
-
{
|
|
771
|
-
type: "button",
|
|
772
|
-
className: "a63-editor__subtoggle-btn",
|
|
773
|
-
onClick: () => setRightTab("source"),
|
|
774
|
-
children: "Switch to Source"
|
|
775
|
-
}
|
|
776
|
-
)
|
|
777
|
-
] }) : /* @__PURE__ */ jsxs("div", { className: "a63-editor__form-fields", children: [
|
|
778
|
-
/* @__PURE__ */ jsx$1(
|
|
779
|
-
TemplatePicker,
|
|
780
|
-
{
|
|
781
|
-
name: parsedSlide.name,
|
|
782
|
-
props: parsedSlide.props,
|
|
783
|
-
onSwitch: handleTemplateSwitch
|
|
784
|
-
}
|
|
785
|
-
),
|
|
786
|
-
/* @__PURE__ */ jsx$1(
|
|
787
|
-
SlotForm,
|
|
788
|
-
{
|
|
789
|
-
name: parsedSlide.name,
|
|
790
|
-
props: parsedSlide.props,
|
|
791
|
-
onChange: handleSlotChange
|
|
792
|
-
}
|
|
793
|
-
)
|
|
758
|
+
parsedSlide === null ? /* @__PURE__ */ jsx$1("p", { className: "a63-editor__form-empty", children: "No slides found." }) : parsedSlide.kind === "opaque" ? /* @__PURE__ */ jsxs("div", { className: "a63-editor__form-opaque", children: [
|
|
759
|
+
/* @__PURE__ */ jsx$1("p", { children: "This slide is only editable in Source." }),
|
|
760
|
+
/* @__PURE__ */ jsx$1(
|
|
761
|
+
"button",
|
|
762
|
+
{
|
|
763
|
+
type: "button",
|
|
764
|
+
className: "a63-editor__subtoggle-btn",
|
|
765
|
+
onClick: () => setRightTab("source"),
|
|
766
|
+
children: "Switch to Source"
|
|
767
|
+
}
|
|
768
|
+
)
|
|
769
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "a63-editor__form-fields", children: [
|
|
770
|
+
/* @__PURE__ */ jsx$1(
|
|
771
|
+
TemplatePicker,
|
|
772
|
+
{
|
|
773
|
+
name: parsedSlide.name,
|
|
774
|
+
props: parsedSlide.props,
|
|
775
|
+
onSwitch: handleTemplateSwitch
|
|
776
|
+
}
|
|
777
|
+
),
|
|
778
|
+
/* @__PURE__ */ jsx$1(
|
|
779
|
+
SlotForm,
|
|
780
|
+
{
|
|
781
|
+
name: parsedSlide.name,
|
|
782
|
+
props: parsedSlide.props,
|
|
783
|
+
onChange: handleSlotChange
|
|
784
|
+
}
|
|
785
|
+
)
|
|
786
|
+
] })
|
|
794
787
|
] })
|
|
795
788
|
] })
|
|
796
789
|
] })
|
|
797
|
-
|
|
790
|
+
);
|
|
798
791
|
}
|
|
799
792
|
function DeckSurface({
|
|
800
793
|
source: sourceProp,
|
|
@@ -846,7 +839,7 @@ function DeckSurface({
|
|
|
846
839
|
return () => window.removeEventListener("keydown", onKey);
|
|
847
840
|
}, [editable, mode]);
|
|
848
841
|
if (editable && mode === "edit") {
|
|
849
|
-
return /* @__PURE__ */ jsx$1(
|
|
842
|
+
return /* @__PURE__ */ jsx$1(
|
|
850
843
|
EditPane,
|
|
851
844
|
{
|
|
852
845
|
source,
|
|
@@ -857,7 +850,7 @@ function DeckSurface({
|
|
|
857
850
|
onPresent: () => setMode("present"),
|
|
858
851
|
themeValue: theme
|
|
859
852
|
}
|
|
860
|
-
)
|
|
853
|
+
);
|
|
861
854
|
}
|
|
862
855
|
return /* @__PURE__ */ jsxs("div", { className: "a63-surface", "data-slides-theme": theme, children: [
|
|
863
856
|
editable && /* @__PURE__ */ jsx$1("button", { type: "button", className: "a63-surface__edit", onClick: () => setMode("edit"), children: "Edit" }),
|
package/dist/editor/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/editor/compile-deck.ts","../../src/editor/parse-slide.ts","../../src/editor/serialize-slot.ts","../../src/editor/slide-blocks.ts","../../src/editor/slide-edit.ts","../../src/editor/slot-form.tsx","../../src/editor/template-picker.tsx","../../src/editor/template-snippets.ts","../../src/editor/frontmatter-edit.ts","../../src/editor/theme-picker.tsx","../../src/editor/edit-pane.tsx","../../src/editor/deck-surface.tsx","../../src/editor/deck-editor.tsx"],"names":["IMPORT_RE","rendered","jsx","jsxs","useState","useMemo"],"mappings":"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","file":"index.js","sourcesContent":["import { evaluate } from '@mdx-js/mdx'\nimport yaml from 'js-yaml'\nimport type { ComponentType } from 'react'\nimport * as runtime from 'react/jsx-runtime'\nimport remarkGfm from 'remark-gfm'\nimport { slideMdxComponents } from '../content/mdx-components'\nimport type { SlideDeckMeta } from '../types'\n\n/**\n * Browser-safe YAML frontmatter split. We deliberately avoid the common\n * \"gray matter\" style parser because it depends on Node's `Buffer`, which\n * doesn't exist in the browser — a browser library must not force consumers to\n * polyfill Node globals.\n *\n * If `source` begins with a `---` fence line, the block up to the next `---`\n * fence is parsed as YAML into `meta` and the remainder is returned as `body`.\n * Otherwise `meta` is empty and the whole source is the `body`.\n */\nexport function parseFrontmatter(source: string): { meta: Record<string, unknown>; body: string } {\n // Frontmatter must start at the very top of the file (allowing a UTF-8 BOM).\n const normalized = source.replace(/^/, '')\n const lines = normalized.split('\\n')\n if (lines[0]?.trim() !== '---') {\n return { meta: {}, body: source }\n }\n\n // Find the closing fence line.\n let end = -1\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n end = i\n break\n }\n }\n if (end === -1) {\n // No closing fence — treat the whole thing as body, no frontmatter.\n return { meta: {}, body: source }\n }\n\n const yamlBlock = lines.slice(1, end).join('\\n')\n const body = lines.slice(end + 1).join('\\n')\n const loaded = yaml.load(yamlBlock)\n const meta = loaded && typeof loaded === 'object' ? (loaded as Record<string, unknown>) : {}\n return { meta, body }\n}\n\n/**\n * Result of a runtime deck compile.\n *\n * On success: the parsed frontmatter `meta` plus a `Content` component ready to\n * hand to `SlidesPlayer` as `deck.content`. On failure: a human-readable\n * `error` string (compile + frontmatter parsing both throw on bad input).\n */\nexport type CompileDeckResult =\n | { ok: true; meta: SlideDeckMeta; Content: ComponentType }\n | { ok: false; error: string }\n\n/**\n * Matches bare ES `import` statements at the start of a line. A deck's MDX body\n * carries lines like `import { CoverSlide } from \"@atom63/slides\"`. The runtime\n * `evaluate` below has no module resolver, so these must be stripped — the\n * components are injected via `useMDXComponents` instead (see compileDeck).\n *\n * Covers single- and multi-line import specifier blocks:\n * import Foo from \"x\"\n * import { A, B } from \"x\"\n * import {\n * A,\n * B,\n * } from \"x\"\n */\nconst IMPORT_RE = /^[ \\t]*import\\b[\\s\\S]*?(?:from\\s*['\"][^'\"]*['\"]|['\"][^'\"]*['\"])[ \\t]*;?[ \\t]*$/gm\n\n/** Remove bare `import ... from \"...\"` lines so runtime evaluate doesn't choke. */\nexport function stripImports(body: string): string {\n return body.replace(IMPORT_RE, '')\n}\n\nconst DEFAULT_META: SlideDeckMeta = {\n title: 'Untitled deck',\n date: new Date().toISOString().slice(0, 10),\n}\n\n/**\n * Compile a deck's raw MDX source into a renderable Content component using a\n * runtime MDX pipeline (no bundler step).\n *\n * Pipeline:\n * 1. `parseFrontmatter` splits the YAML frontmatter (the deck `meta`) from the\n * body using a browser-safe parser (no Node `Buffer`).\n * 2. `stripImports` removes bare `import ... from \"@atom63/slides\"` lines that\n * the runtime evaluator cannot resolve.\n * 3. `@mdx-js/mdx`'s `evaluate` compiles + runs the body. The slide components\n * (templates + primitives + markdown mappings) are provided through MDX\n * context via `useMDXComponents: () => slideMdxComponents`, so bare JSX such\n * as `<CoverSlide/>` resolves with no import. `---` thematic breaks are\n * preserved as the engine's slide separators.\n *\n * Async and can throw on malformed MDX/frontmatter — callers should debounce\n * and keep the last good render on failure (DeckEditor does this).\n */\nexport async function compileDeck(source: string): Promise<CompileDeckResult> {\n try {\n const { meta: data, body: content } = parseFrontmatter(source)\n const meta: SlideDeckMeta = { ...DEFAULT_META, ...(data as Partial<SlideDeckMeta>) }\n const body = stripImports(content)\n\n const { default: Content } = await evaluate(body, {\n ...runtime,\n useMDXComponents: () => slideMdxComponents,\n remarkPlugins: [remarkGfm],\n })\n\n return { ok: true, meta, Content: Content as ComponentType }\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err)\n return { ok: false, error }\n }\n}\n","import { Parser } from 'acorn'\nimport jsx from 'acorn-jsx'\nimport { templateNames } from '../content/template-registry'\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport type ParsedSlide =\n | { kind: 'template'; name: string; props: Record<string, string> }\n | { kind: 'opaque'; reason: string }\n\n// ── Internal acorn-jsx parser ──────────────────────────────────────────────\n\nconst JsxParser = Parser.extend(jsx())\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\n// biome-ignore lint/suspicious/noExplicitAny: acorn AST nodes are untyped\ntype AnyNode = any\n\n/**\n * Matches a leading ES `import` statement (with or without a trailing\n * semicolon). MDX decks routinely write `import { X } from '...'` with NO\n * semicolon, and acorn does NOT insert one before the following JSX — it\n * throws. We neutralize imports before parsing by replacing each import's\n * characters with EQUAL-LENGTH whitespace (newlines preserved), so the JSX\n * element's source offsets stay identical to the original block — which\n * `serialize-slot` relies on for span-based, byte-preserving edits.\n */\nconst IMPORT_RE =\n /^[ \\t]*import\\b[\\s\\S]*?(?:from\\s*['\"][^'\"]*['\"]|['\"][^'\"]*['\"])[ \\t]*;?[ \\t]*$/gm\n\nfunction blankImports(block: string): string {\n return block.replace(IMPORT_RE, m => m.replace(/[^\\n]/g, ' '))\n}\n\n/**\n * Given a parsed block string, return the single JSXElement acorn node if\n * the block contains exactly one JSX expression statement (with any number of\n * leading ImportDeclarations and nothing else). Returns null otherwise.\n *\n * Exported so Task 4 can reuse it (offset-based element finding).\n */\nexport function findTemplateElement(block: string): AnyNode | null {\n let ast: AnyNode\n try {\n // Blank imports first (offset-preserving) so a semicolon-less import before\n // the JSX doesn't make acorn throw. Offsets remain valid for `block`.\n ast = JsxParser.parse(blankImports(block), { ecmaVersion: 'latest', sourceType: 'module' })\n } catch {\n return null\n }\n\n const body: AnyNode[] = ast.body\n\n let jsxElement: AnyNode | null = null\n\n for (const node of body) {\n if (node.type === 'ImportDeclaration') {\n // allowed — skip\n continue\n }\n if (node.type === 'ExpressionStatement' && node.expression?.type === 'JSXElement') {\n if (jsxElement !== null) {\n // more than one JSX element → opaque\n return null\n }\n jsxElement = node.expression\n } else {\n // unexpected statement type (non-import, non-jsx-expression) → opaque\n return null\n }\n }\n\n return jsxElement\n}\n\n// ── Main export ────────────────────────────────────────────────────────────\n\n/**\n * Parse one MDX slide block and decide whether it is a known single-element\n * template with all literal-string props (→ \"template\") or anything else\n * (→ \"opaque\", edit-in-source only).\n */\nexport function parseSlide(block: string): ParsedSlide {\n const element = findTemplateElement(block)\n\n if (element === null) {\n return { kind: 'opaque', reason: 'block contains no single JSX template element' }\n }\n\n // Resolve component name (must be a plain JSXIdentifier, not a MemberExpression)\n const openingEl = element.openingElement\n const nameNode = openingEl.name\n if (nameNode.type !== 'JSXIdentifier') {\n return { kind: 'opaque', reason: 'JSX element name is not a plain identifier' }\n }\n const componentName: string = nameNode.name\n\n if (!(templateNames as readonly string[]).includes(componentName)) {\n return { kind: 'opaque', reason: `\"${componentName}\" is not a registered template` }\n }\n\n // Require attribute-only / self-closing (no non-whitespace children)\n const children: AnyNode[] = element.children ?? []\n for (const child of children) {\n if (child.type === 'JSXText') {\n // Allow whitespace-only JSXText (newlines, spaces between tags)\n if (child.value.trim() !== '') {\n return { kind: 'opaque', reason: 'element has non-whitespace children' }\n }\n } else {\n // JSXElement, JSXExpressionContainer, JSXFragment, JSXSpreadChild\n return { kind: 'opaque', reason: 'element has non-whitespace children' }\n }\n }\n\n // Extract props — all must be JSXAttribute with a string Literal value\n const props: Record<string, string> = {}\n const attributes: AnyNode[] = openingEl.attributes ?? []\n for (const attr of attributes) {\n if (attr.type === 'JSXSpreadAttribute') {\n return { kind: 'opaque', reason: 'element has spread attribute' }\n }\n if (attr.type !== 'JSXAttribute') {\n return { kind: 'opaque', reason: 'unexpected attribute node type' }\n }\n const attrName: string = attr.name.name\n const attrValue: AnyNode = attr.value\n\n // Allow bare boolean shorthand (e.g. `<Foo required />` — value is null)\n // but we only model it as a string flag \"true\" for now. Actually per spec:\n // only string Literals are permitted; anything else → opaque.\n if (attrValue === null) {\n // bare attribute (boolean shorthand) — not a string literal\n return { kind: 'opaque', reason: `attribute \"${attrName}\" has no string value (boolean shorthand)` }\n }\n if (attrValue.type !== 'Literal' || typeof attrValue.value !== 'string') {\n return {\n kind: 'opaque',\n reason: `attribute \"${attrName}\" is not a string literal`,\n }\n }\n\n props[attrName] = attrValue.value\n }\n\n return { kind: 'template', name: componentName, props }\n}\n","import { findTemplateElement } from './parse-slide'\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\n// biome-ignore lint/suspicious/noExplicitAny: acorn AST nodes are untyped\ntype AnyNode = any\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\n/**\n * Encode a plain string value as a JSX attribute string value with surrounding\n * double-quote delimiters.\n *\n * Acorn-jsx decodes JSX entity references inside quoted attribute string\n * values (`&` → `&`, `"` → `\"`), so our encoder must mirror exactly\n * what the parser decodes:\n * 1. `&` → `&` (MUST be first to avoid double-encoding)\n * 2. `\"` → `"`\n *\n * Other JSX-level entities (`<`, `>`, `'`) are not emitted by this\n * encoder, but we do NOT need to escape `<` or `>` inside a JSX attribute\n * string — those are only significant in JSX *text* content, not attribute\n * values.\n *\n * Exported so `slide-edit.ts` can reuse the same escaping for\n * `switchSlideTemplate`, ensuring the fix lands in exactly one place.\n */\nexport function renderJsxAttr(name: string, value: string): string {\n // Encode & first (before \" to avoid double-encoding), then \"\n const encoded = value.replaceAll('&', '&').replaceAll('\"', '"')\n return `${name}=\"${encoded}\"`\n}\n\n/**\n * Render a string value as a valid JSX attribute value (including surrounding\n * delimiters).\n *\n * Always produces a double-quoted value with `&` and `"` entity\n * escaping so that the round-trip `parseProp(setProp(block, k, v)) === v`\n * holds for ALL string values, including those containing `&`, `\"`, or\n * pre-existing entity references such as `"` or `&`.\n *\n * (The previous single-quote optimisation was removed because acorn-jsx also\n * decodes entities inside single-quoted attributes, making the same escaping\n * necessary regardless of delimiter choice. Using double-quotes uniformly\n * keeps the implementation simple and correct.)\n */\nfunction renderValue(value: string): string {\n const encoded = value.replaceAll('&', '&').replaceAll('\"', '"')\n return `\"${encoded}\"`\n}\n\n// ── Main export ────────────────────────────────────────────────────────────\n\n/**\n * Apply one prop change to an MDX slide block string.\n *\n * Only the bytes belonging to the changed attribute value are mutated; every\n * other character in `block` (whitespace, other props, import lines, the tag\n * name, etc.) is byte-preserved.\n *\n * @param block The raw MDX block text (may include leading import lines).\n * @param name The JSX attribute name to set.\n * @param value The new plain-string value.\n * @returns The updated block string.\n *\n * If `block` cannot be parsed as a single template element (e.g. opaque block)\n * the function returns `block` unchanged — callers should only call this on\n * blocks that `parseSlide` classifies as `{ kind: 'template' }`.\n */\nexport function setProp(block: string, name: string, value: string): string {\n const element: AnyNode | null = findTemplateElement(block)\n if (element === null) {\n return block\n }\n\n const openingEl: AnyNode = element.openingElement\n const attributes: AnyNode[] = openingEl.attributes ?? []\n\n // ── Case 1: attribute already exists ──────────────────────────────────────\n const existing: AnyNode | undefined = attributes.find(\n (attr: AnyNode) => attr.type === 'JSXAttribute' && attr.name?.name === name\n )\n\n if (existing !== undefined) {\n const attrValue: AnyNode = existing.value\n if (attrValue === null || attrValue.type !== 'Literal') {\n // Non-string attribute (expression container, boolean shorthand, etc.) —\n // not supported; return block unchanged to avoid corrupting it.\n return block\n }\n\n // No-op fast path: if the existing raw bytes already match what renderValue\n // would produce, return unchanged (byte-identical).\n const existingRaw = block.slice(attrValue.start, attrValue.end)\n const rendered = renderValue(value)\n if (existingRaw === rendered) {\n return block\n }\n\n // Value or encoding changed — replace only the value span (offsets include\n // the surrounding quotes).\n return block.slice(0, attrValue.start) + rendered + block.slice(attrValue.end)\n }\n\n // ── Case 2: attribute not present — insert before closing `/>` or `>` ─────\n //\n // Strategy: walk backwards from `openingEl.end` to find the `/>` or `>`\n // boundary and insert ` name=\"value\"` just before it (before any preceding\n // whitespace that is part of the closing token itself).\n //\n // acorn-jsx sets `openingElement.end` to the position AFTER the closing\n // `>` (or `/>`) of the opening tag. We back-track to find its start.\n\n const tagEnd: number = openingEl.end // exclusive: char at [tagEnd] is AFTER `>`\n const rendered = renderValue(value)\n\n // Find the position of `/>` or `>` by scanning backwards from tagEnd\n // (the two characters before tagEnd for a self-closing tag are `/>`).\n let insertAt: number\n if (block[tagEnd - 1] === '>' && block[tagEnd - 2] === '/') {\n // Self-closing: `/>` sits at [tagEnd-2, tagEnd)\n insertAt = tagEnd - 2\n } else if (block[tagEnd - 1] === '>') {\n // Regular closing `>`\n insertAt = tagEnd - 1\n } else {\n // Unexpected — fall back to inserting at tagEnd (safe, may look odd)\n insertAt = tagEnd\n }\n\n // Strip any whitespace that already precedes the `/>` so we control spacing\n // (don't add double spaces). We keep existing whitespace and just prepend\n // a single space before our new attribute.\n const insertion = ` ${name}=${rendered}`\n return block.slice(0, insertAt) + insertion + block.slice(insertAt)\n}\n","/**\n * Split a deck's MDX source into typed blocks so a form editor can mutate ONE\n * slide's content while leaving all other bytes byte-identical.\n *\n * Partition rules\n * ---------------\n * • `frontmatter` — the leading `---`…`---` YAML fence (including both fence\n * lines and the trailing newline after the closing `---`). Present only when\n * the source begins with a `---` line that has a matching closing fence.\n * • `separator` — a single `---\\n` (or `---` at EOF) at the top level that\n * acts as a slide boundary. In-code `---` lines (inside ``` / ~~~ fences) are\n * NOT treated as separators.\n * • `slide` — all content between separators (may be empty string if two\n * separators are adjacent). Each slide block's `text` includes any surrounding\n * blank lines that are NOT part of a separator.\n *\n * Byte-fidelity guarantee\n * -----------------------\n * `joinBlocks(splitBlocks(source)) === source` for every valid input.\n * Each block stores its exact original text; `joinBlocks` is just concatenation.\n */\n\nexport interface Block {\n /** Sequential index across all emitted blocks (0-based). */\n index: number\n kind: 'frontmatter' | 'separator' | 'slide'\n /** Exact original text for this block — concatenating all texts reproduces the source. */\n text: string\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Returns true when a line (already trimmed) opens or closes a fenced code block. */\nfunction isFenceMarker(trimmed: string): boolean {\n return trimmed.startsWith('```') || trimmed.startsWith('~~~')\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Split `source` into typed blocks.\n *\n * Algorithm:\n * 1. Strip a leading frontmatter block if present (same rule as parseFrontmatter).\n * 2. Walk the remainder line-by-line, toggling a `inFence` flag on ``` / ~~~.\n * 3. Lines that are exactly `---` at top level (not inside a fence) become\n * `separator` blocks; everything else accumulates into a `slide` chunk.\n * 4. A trailing `---` with no content after it still emits a separator but\n * does NOT emit an additional empty slide.\n */\nexport function splitBlocks(source: string): Block[] {\n const blocks: Block[] = []\n let idx = 0\n\n // ── Step 1: peel frontmatter ──────────────────────────────────────────────\n // Mirrors parseFrontmatter exactly (same fence rule, same BOM strip).\n const normalized = source.replace(/^/, '')\n const allLines = normalized.split('\\n')\n\n let remainder = source\n let frontmatterConsumed = 0 // byte count consumed by frontmatter\n\n if (allLines[0]?.trim() === '---') {\n // Look for a closing fence starting at line 1.\n let closeIdx = -1\n for (let i = 1; i < allLines.length; i++) {\n if (allLines[i].trim() === '---') {\n closeIdx = i\n break\n }\n }\n\n if (closeIdx !== -1) {\n // Frontmatter text = lines[0..closeIdx] joined with '\\n', plus the '\\n'\n // that was between closeIdx and the next line (the split() consumed it).\n const fmLines = allLines.slice(0, closeIdx + 1)\n // Each line was split on '\\n', so we re-join with '\\n' and add the\n // trailing '\\n' that existed after the closing fence (unless it was the\n // very last character of source, in which case split produces an empty\n // string at the end and we must not double-add).\n const fmText = `${fmLines.join('\\n')}\\n`\n\n // Validate that source actually contains this prefix (handles BOM).\n if (source.startsWith(fmText) || normalized.startsWith(fmText)) {\n frontmatterConsumed = fmText.length\n blocks.push({ index: idx++, kind: 'frontmatter', text: fmText })\n remainder = source.slice(frontmatterConsumed)\n }\n }\n }\n\n // ── Step 2: walk the remainder line-by-line ───────────────────────────────\n // We need line-by-line iteration but must reconstruct exact text for each\n // block. To keep byte-fidelity we track character offsets into `remainder`.\n\n const remLines = remainder.split('\\n')\n // split('\\n') on \"a\\nb\\n\" → [\"a\",\"b\",\"\"] — the trailing \"\" represents the\n // final newline. We re-attach '\\n' to every line except the very last one\n // when it is the empty string produced by a trailing newline.\n\n // Build an array of {content, raw} where `raw` is the exact substring\n // including the '\\n' terminator (or nothing for a true EOF without newline).\n const lineRaws: string[] = []\n for (let i = 0; i < remLines.length; i++) {\n const isLast = i === remLines.length - 1\n if (isLast && remLines[i] === '') {\n // This empty string is the artifact of a trailing '\\n' — the newline\n // already belongs to the previous line's raw. Don't emit a line for it.\n break\n }\n lineRaws.push(isLast ? remLines[i] : `${remLines[i]}\\n`)\n }\n\n let inFence = false\n let slideText = ''\n\n const flushSlide = () => {\n // Always emit a slide block, even if empty — this preserves byte-fidelity\n // for adjacent separators. But we skip a trailing empty slide if the\n // remainder ended at a separator (handled in the loop by checking whether\n // lineRaws is exhausted after the last separator).\n blocks.push({ index: idx++, kind: 'slide', text: slideText })\n slideText = ''\n }\n\n for (let i = 0; i < lineRaws.length; i++) {\n const raw = lineRaws[i]\n const trimmed = raw.trimEnd().replace(/\\r$/, '') // trim CR for CRLF safety\n\n if (!inFence && trimmed === '---') {\n // This is a top-level separator.\n // Flush accumulated slide content before the separator.\n flushSlide()\n // Emit the separator block (just the `---\\n` line).\n blocks.push({ index: idx++, kind: 'separator', text: raw })\n // After the separator, check if there's more content. If not, don't\n // emit a phantom empty slide — the loop will simply end.\n } else {\n // Toggle fenced-code state.\n if (isFenceMarker(trimmed)) {\n inFence = !inFence\n }\n slideText += raw\n }\n }\n\n // Flush final slide (may be empty if source ended with a separator).\n // Only emit if non-empty OR if there were no separators at all (single slide).\n if (slideText !== '' || blocks.filter(b => b.kind === 'slide').length === 0) {\n flushSlide()\n }\n\n return blocks\n}\n\n/**\n * Reconstruct the original source from a block array.\n * Concatenation is sufficient because each block stores its exact original text.\n */\nexport function joinBlocks(blocks: Block[]): string {\n return blocks.map(b => b.text).join('')\n}\n","/**\n * Pure helpers that operate on the WHOLE-deck `source` string, tying together\n * `splitBlocks` / `joinBlocks`, `setProp`, and `findTemplateElement` so that\n * the Form view can edit individual slides without touching any other bytes.\n *\n * All functions are stateless and synchronous — safe to call on every render.\n */\n\nimport { findTemplateElement, parseSlide } from './parse-slide'\nimport { renderJsxAttr, setProp } from './serialize-slot'\nimport { joinBlocks, splitBlocks } from './slide-blocks'\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Returns the indices (into `splitBlocks(source)`) of non-empty slide blocks,\n * in document order. Empty slide blocks (text that is blank / whitespace-only)\n * that appear between two adjacent separators are skipped — they are not\n * rendered as visible slides.\n */\nexport function slideBlockIndices(source: string): number[] {\n const blocks = splitBlocks(source)\n const indices: number[] = []\n for (const block of blocks) {\n if (block.kind === 'slide' && block.text.trim() !== '') {\n indices.push(block.index)\n }\n }\n return indices\n}\n\n/**\n * Return the block (by its position in `splitBlocks`) and its exact text for\n * the Nth (0-based) rendered slide. Returns `null` when `slideOrdinal` is out\n * of range.\n */\nexport function getSlideBlock(\n source: string,\n slideOrdinal: number\n): { blockIndex: number; text: string } | null {\n const indices = slideBlockIndices(source)\n if (slideOrdinal < 0 || slideOrdinal >= indices.length) return null\n const blockIndex = indices[slideOrdinal]\n const blocks = splitBlocks(source)\n const block = blocks.find(b => b.index === blockIndex)\n if (!block) return null\n return { blockIndex, text: block.text }\n}\n\n/**\n * Apply one prop change to the Nth (0-based) rendered slide inside `source`.\n *\n * Uses `setProp` for byte-stable mutation — only the changed attribute value\n * is rewritten; all other bytes in the source are preserved exactly.\n *\n * Returns the original `source` unchanged when `slideOrdinal` is out of range\n * or the target block is opaque (i.e. `parseSlide` does not return\n * `{ kind: 'template' }`). This is a hard safety gate — opaque blocks are\n * never lossily rewritten, regardless of whether `findTemplateElement` would\n * have matched.\n */\nexport function setSlideProp(\n source: string,\n slideOrdinal: number,\n key: string,\n value: string\n): string {\n const indices = slideBlockIndices(source)\n if (slideOrdinal < 0 || slideOrdinal >= indices.length) return source\n const blockIndex = indices[slideOrdinal]\n\n const blocks = splitBlocks(source)\n const updated = blocks.map(b => {\n if (b.index !== blockIndex) return b\n // Opaque-safety gate: only rewrite template blocks\n if (parseSlide(b.text).kind !== 'template') return b\n return { ...b, text: setProp(b.text, key, value) }\n })\n return joinBlocks(updated)\n}\n\n// ── switchSlideTemplate ───────────────────────────────────────────────────────\n\n/**\n * Render a set of props as JSX attribute string (name=\"value\" pairs, single\n * space separated).\n *\n * Delegates to `renderJsxAttr` (from serialize-slot) so entity escaping is\n * consolidated in one place and both code paths benefit from the same fix.\n */\nfunction renderProps(props: Record<string, string>): string {\n return Object.entries(props)\n .map(([k, v]) => renderJsxAttr(k, v))\n .join(' ')\n}\n\n/**\n * Replace the JSX template element in the Nth (0-based) rendered slide with a\n * freshly-rendered self-closing `<NextName key=\"val\" … />` built from\n * `nextProps`.\n *\n * Only the JSX element span is replaced; any leading import declarations or\n * surrounding whitespace/text in the block are preserved byte-for-byte.\n *\n * Returns the original `source` unchanged when `slideOrdinal` is out of range\n * or the target block is opaque (i.e. `parseSlide` does not return\n * `{ kind: 'template' }`). This is a hard safety gate — opaque blocks are\n * never lossily rewritten, regardless of whether `findTemplateElement` would\n * have matched.\n */\nexport function switchSlideTemplate(\n source: string,\n slideOrdinal: number,\n nextName: string,\n nextProps: Record<string, string>\n): string {\n const indices = slideBlockIndices(source)\n if (slideOrdinal < 0 || slideOrdinal >= indices.length) return source\n const blockIndex = indices[slideOrdinal]\n\n const blocks = splitBlocks(source)\n const updated = blocks.map(b => {\n if (b.index !== blockIndex) return b\n\n // Opaque-safety gate: only rewrite template blocks\n if (parseSlide(b.text).kind !== 'template') return b\n\n const element = findTemplateElement(b.text)\n if (element === null) return b\n\n // Build the replacement element string\n const propsStr = renderProps(nextProps)\n const replacement =\n propsStr.length > 0 ? `<${nextName} ${propsStr} />` : `<${nextName} />`\n\n // element.start / element.end are offsets into b.text\n const newText =\n b.text.slice(0, element.start) + replacement + b.text.slice(element.end)\n return { ...b, text: newText }\n })\n\n return joinBlocks(updated)\n}\n","import type { JSX } from 'react'\nimport type { SlotDef, SlotKind } from '../content/template-registry'\nimport { getTemplate } from '../content/template-registry'\n\nexport interface SlotFormProps {\n /** Template component name, e.g. \"CoverSlide\". */\n name: string\n /** Current prop values keyed by SlotDef.key. */\n props: Record<string, string>\n /** Called when any field value changes. */\n onChange: (key: string, value: string) => void\n}\n\nfunction fieldId(templateName: string, key: string): string {\n return `a63-slot-${templateName}-${key}`\n}\n\nfunction isMultiline(kind: SlotKind): boolean {\n return kind === 'richtext' || kind === 'list'\n}\n\nfunction SlotField({\n templateName,\n slot,\n value,\n onChange,\n}: {\n templateName: string\n slot: SlotDef\n value: string\n onChange: (key: string, value: string) => void\n}): JSX.Element {\n const id = fieldId(templateName, slot.key)\n const multiline = isMultiline(slot.kind)\n\n return (\n <div className=\"a63-form__field\">\n <div className=\"a63-form__label-row\">\n <label className=\"a63-form__label\" htmlFor={id}>\n {slot.label}\n </label>\n {slot.required && (\n <span className=\"a63-form__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </div>\n {multiline ? (\n <textarea\n id={id}\n className=\"a63-form__textarea\"\n value={value}\n required={slot.required}\n aria-required={slot.required}\n onChange={e => onChange(slot.key, e.target.value)}\n />\n ) : (\n <input\n type=\"text\"\n id={id}\n className=\"a63-form__input\"\n value={value}\n required={slot.required}\n aria-required={slot.required}\n onChange={e => onChange(slot.key, e.target.value)}\n />\n )}\n </div>\n )\n}\n\nexport function SlotForm({ name, props, onChange }: SlotFormProps): JSX.Element {\n const tpl = getTemplate(name)\n\n if (!tpl) {\n return (\n <p className=\"a63-form__unknown\">\n Unknown template: <code>{name}</code>\n </p>\n )\n }\n\n const slotGroupNames = tpl.slots.map(s => s.name)\n\n return (\n <div className=\"a63-form\">\n {tpl.props.map(slot => (\n <SlotField\n key={slot.key}\n templateName={name}\n slot={slot}\n value={props[slot.key] ?? ''}\n onChange={onChange}\n />\n ))}\n {slotGroupNames.length > 0 && (\n <p className=\"a63-form__slots-note\">\n Repeatable sections ({slotGroupNames.join(', ')}) are edited in Source.\n </p>\n )}\n </div>\n )\n}\n","import { type JSX, useState } from 'react'\nimport { getTemplate, listTemplates } from '../content/template-registry'\n\nexport interface TemplateSwitch {\n props: Record<string, string>\n dropped: string[]\n}\n\nexport interface TemplatePickerProps {\n /** Current template component name, e.g. \"CoverSlide\". */\n name: string\n /** Current prop values keyed by SlotDef.key. */\n props: Record<string, string>\n /** Called when the user picks a different template. */\n onSwitch: (next: string, mapped: TemplateSwitch) => void\n}\n\nexport function TemplatePicker({ name, props, onSwitch }: TemplatePickerProps): JSX.Element {\n const [warning, setWarning] = useState<{ from: string; to: string; dropped: string[] } | null>(\n null\n )\n\n function handleChange(next: string): void {\n if (next === name) return\n\n const nextDef = getTemplate(next)\n if (!nextDef) return\n\n const nextKeys = new Set(nextDef.props.map(s => s.key))\n\n // Carry over props whose key exists in the next template\n const carried: Record<string, string> = {}\n for (const [k, v] of Object.entries(props)) {\n if (nextKeys.has(k)) {\n carried[k] = v\n }\n }\n\n // Dropped = current keys not in next, but only those with non-empty values\n const dropped: string[] = Object.entries(props)\n .filter(([k, v]) => !nextKeys.has(k) && v !== '')\n .map(([k]) => k)\n\n // Fill required slots not already carried\n for (const slot of nextDef.props) {\n if (!(slot.key in carried)) {\n carried[slot.key] = ''\n }\n }\n\n onSwitch(next, { props: carried, dropped })\n\n if (dropped.length > 0) {\n setWarning({ from: name, to: next, dropped })\n } else {\n setWarning(null)\n }\n }\n\n const templates = listTemplates()\n\n return (\n <div className=\"a63-form__field\">\n <label className=\"a63-form__label\" htmlFor=\"a63-template-picker\">\n Template\n </label>\n <select\n id=\"a63-template-picker\"\n className=\"a63-form__input\"\n aria-label=\"Template\"\n value={name}\n onChange={e => handleChange(e.target.value)}\n >\n {templates.map(tpl => (\n <option key={tpl.name} value={tpl.name}>\n {tpl.label ?? tpl.name}\n </option>\n ))}\n </select>\n {warning && (\n <output className=\"a63-form__picker-warning\">\n <span>\n Switched {warning.from} → {warning.to}; dropped: {warning.dropped.join(', ')}.\n </span>\n <button\n type=\"button\"\n className=\"a63-form__picker-dismiss\"\n aria-label=\"Dismiss\"\n onClick={() => setWarning(null)}\n >\n ×\n </button>\n </output>\n )}\n </div>\n )\n}\n","import {\n listTemplates,\n type SlotDef,\n type SlotGroupDef,\n type TemplateDef,\n} from '../content/template-registry'\n\n/**\n * Generates a minimal, paste-ready MDX snippet per template from the engine's\n * registry (`listTemplates()`), mirroring the synthesis logic in\n * `skill/scripts/gen-templates.mjs`. The palette in\n * <DeckEditor> appends `templateSnippets[name]` when a template is clicked.\n *\n * Registry is the single source of truth; snippets cannot drift from the\n * published template props/slots.\n */\n\nconst PLACEHOLDER_IMG = '/images/placeholder-1920x1080.webp'\n\nfunction exampleValue(prop: SlotDef): string {\n switch (prop.kind) {\n case 'media':\n return PLACEHOLDER_IMG\n default:\n // text / richtext / list-as-scalar\n return `${prop.label}…`\n }\n}\n\n/** Render the direct-prop attributes for a template's opening tag. */\nfunction renderPropAttrs(props: SlotDef[], indent = ' '): string[] {\n const lines: string[] = []\n for (const prop of props) {\n if (prop.key === 'children') continue\n if (prop.array) {\n if (prop.kind === 'media') {\n lines.push(\n `${indent}${prop.key}={[\"${PLACEHOLDER_IMG}\", \"${PLACEHOLDER_IMG}\", \"${PLACEHOLDER_IMG}\"]}`\n )\n } else {\n lines.push(`${indent}${prop.key}={[{ label: \"Label\", value: \"Value\", href: \"https://…\" }]}`)\n }\n continue\n }\n lines.push(`${indent}${prop.key}=\"${exampleValue(prop)}\"`)\n }\n return lines\n}\n\n/** Render one compound-slot child element, e.g. `<HeroBento.Card title=\"…\" />`. */\nfunction renderSlotChild(templateName: string, slot: SlotGroupDef): string {\n const attrs: string[] = []\n let childrenText: string | null = null\n for (const prop of slot.props) {\n if (prop.key === 'children') {\n childrenText = `${prop.label}…`\n continue\n }\n if (prop.array) {\n attrs.push(`${prop.key}={[…]}`)\n continue\n }\n const value = prop.kind === 'media' ? PLACEHOLDER_IMG : `${prop.label}…`\n attrs.push(`${prop.key}=\"${value}\"`)\n }\n const tag = `${templateName}.${slot.name}`\n const attrStr = attrs.length ? ` ${attrs.join(' ')}` : ''\n if (childrenText !== null) {\n return ` <${tag}${attrStr}>${childrenText}</${tag}>`\n }\n return ` <${tag}${attrStr} />`\n}\n\n/**\n * Synthesize a minimal, valid MDX usage example from a template's schema.\n * - Simple templates → self-closing tag with its props.\n * - Compound templates → open tag + one instance of each slot at `min` (or 1).\n */\nexport function synthExample(t: TemplateDef): string {\n const hasSlots = t.slots.length > 0\n const propLines = renderPropAttrs(t.props)\n\n if (!hasSlots) {\n if (propLines.length === 0) return `<${t.name} />`\n return [`<${t.name}`, ...propLines, '/>'].join('\\n')\n }\n\n const open = propLines.length ? [`<${t.name}`, ...propLines, '>'] : [`<${t.name}>`]\n const childLines: string[] = []\n for (const slot of t.slots) {\n const count = Math.min(Math.max(slot.min, 1), 3)\n for (let i = 0; i < count; i++) {\n childLines.push(renderSlotChild(t.name, slot))\n }\n }\n return [...open, ...childLines, `</${t.name}>`].join('\\n')\n}\n\n/**\n * Wrap a synthesized example as an insertable slide: a leading `---` separator\n * (the engine's slide break) followed by the example, so appending to a deck\n * body always starts a fresh slide.\n */\nexport function toInsertSnippet(t: TemplateDef): string {\n return `\\n---\\n\\n${synthExample(t)}\\n`\n}\n\n/** Map of `templateName -> insertable MDX snippet`, built from the live registry. */\nexport const templateSnippets: Record<string, string> = Object.fromEntries(\n listTemplates().map(t => [t.name, toInsertSnippet(t)])\n)\n","/**\n * Pure frontmatter field editor — rewrites one YAML key in MDX/Markdown source\n * text-faithfully, without a YAML serializer, so unrelated lines are preserved\n * verbatim (including values that contain colons, quotes, etc.).\n *\n * Frontmatter detection mirrors `parseFrontmatter` in compile-deck.ts:\n * - First line must be exactly `---` (after stripping a UTF-8 BOM).\n * - The block closes at the next line that is exactly `---`.\n * - If no closing fence is found the whole source is treated as body (no FM).\n *\n * Line-ending fidelity: the function detects whether the source uses CRLF or\n * LF as its dominant line ending and uses that same sequence when rebuilding\n * the frontmatter fence and the inserted/updated field line. Body lines passed\n * through are never touched — they already carry the original endings.\n *\n * BOM fidelity: a leading UTF-8 BOM (U+FEFF) is stripped before detection and\n * re-prepended to the reconstructed output, so a BOM-prefixed source remains\n * BOM-prefixed after the edit.\n *\n * Empty-block edge case: when removing the only remaining field leaves an empty\n * inner block, we keep `---${nl}---${nl}` (two fence lines with no content\n * between them) rather than dropping the block entirely. This is the simplest\n * choice that is unambiguous and avoids shifting byte offsets of the body;\n * callers that want to collapse it can do so separately.\n */\n\nconst BOM = ''\n\n/**\n * Detect the dominant line ending in `text`.\n * Returns `'\\r\\n'` if CRLF appears at least as often as bare LF, else `'\\n'`.\n */\nfunction detectNewline(text: string): '\\r\\n' | '\\n' {\n const crlf = (text.match(/\\r\\n/g) ?? []).length\n const lf = (text.match(/(?<!\\r)\\n/g) ?? []).length\n return crlf >= lf && crlf > 0 ? '\\r\\n' : '\\n'\n}\n\n/**\n * Set (or remove) a single frontmatter field in `source`.\n *\n * - If `value` is non-empty: upsert `key: value` into the frontmatter block.\n * - If `value` is empty: remove the `key:` line from the frontmatter block.\n * - If no frontmatter block exists and `value` is non-empty: prepend one.\n * - If no frontmatter block exists and `value` is empty: return `source` unchanged.\n * - If the field already has the same value: return the same string reference\n * (byte-identical, no allocation).\n *\n * Line endings in the source (LF or CRLF) are detected and preserved. A leading\n * UTF-8 BOM is preserved in the output.\n */\nexport function setFrontmatterField(source: string, key: string, value: string): string {\n // ── BOM handling ─────────────────────────────────────────────────────────\n const hasBom = source.startsWith(BOM)\n const withoutBom = hasBom ? source.slice(1) : source\n\n // ── Line-ending detection (from the full source, before splitting) ────────\n const nl = detectNewline(withoutBom)\n\n // Split on \\n after stripping \\r so line content is clean regardless of ending.\n // We re-join with the detected `nl` when rebuilding.\n const lines = withoutBom.split('\\n').map(l => l.replace(/\\r$/, ''))\n\n // ── Detect frontmatter block ──────────────────────────────────────────────\n const hasFrontmatter = lines[0]?.trim() === '---'\n\n if (!hasFrontmatter) {\n // No frontmatter: removing a field is a no-op; adding creates a new block.\n if (!value) return source\n const prefix = `---${nl}${key}: ${value}${nl}---${nl}`\n return hasBom ? BOM + prefix + withoutBom : prefix + withoutBom\n }\n\n // Find closing fence.\n let closingIndex = -1\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n closingIndex = i\n break\n }\n }\n\n if (closingIndex === -1) {\n // Unclosed frontmatter — treat as body, same as parseFrontmatter.\n if (!value) return source\n const prefix = `---${nl}${key}: ${value}${nl}---${nl}`\n return hasBom ? BOM + prefix + withoutBom : prefix + withoutBom\n }\n\n // Inner YAML lines (between the two fences, excluding them).\n const innerLines = lines.slice(1, closingIndex)\n\n // Lines after the closing fence (the body, as a single rejoined string).\n // We preserve these exactly as-is — re-join with the detected nl so the\n // body's own endings are reconstructed faithfully.\n const bodyLines = lines.slice(closingIndex + 1)\n\n // ── Operate on innerLines ─────────────────────────────────────────────────\n // Match `key:` at the start of a line (key followed by colon, optional space).\n const keyRe = new RegExp(`^${escapeRegExp(key)}:`)\n const existingIdx = innerLines.findIndex(l => keyRe.test(l))\n\n let newInnerLines: string[]\n\n if (existingIdx !== -1) {\n const existing = innerLines[existingIdx]\n if (value) {\n const desired = `${key}: ${value}`\n // No-op check: same value already present → return source unchanged.\n if (existing === desired) return source\n // Replace in place.\n newInnerLines = [...innerLines]\n newInnerLines[existingIdx] = desired\n } else {\n // Remove the field line.\n newInnerLines = innerLines.filter((_, i) => i !== existingIdx)\n }\n } else {\n if (!value) {\n // Key doesn't exist and we're removing — no-op.\n return source\n }\n // Append new field as the last inner line.\n newInnerLines = [...innerLines, `${key}: ${value}`]\n }\n\n // ── Rebuild ───────────────────────────────────────────────────────────────\n // Reconstruct the frontmatter block + the body, using the source's own nl.\n const innerBlock = newInnerLines.join(nl)\n const bodyBlock = bodyLines.join(nl)\n const rebuilt = `---${nl}${innerBlock}${nl}---${nl}${bodyBlock}`\n\n return hasBom ? BOM + rebuilt : rebuilt\n}\n\n/** Escape special regex characters in a literal string. */\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","import { type JSX, useId } from 'react'\nimport { BUILTIN_THEMES } from '../content/themes'\nimport { setFrontmatterField } from './frontmatter-edit'\n\nexport interface ThemePickerProps {\n source: string\n theme: string | undefined\n onChange: (next: string) => void\n}\n\n/**\n * ThemePicker — writes `theme:` into the deck frontmatter.\n *\n * This controls the DECK token theme (dark/terminal/editorial/neon/bold),\n * distinct from the Light/Dark preview-canvas toggle in EditPane which only\n * affects the editor's background. Selecting \"Default\" removes the theme line.\n */\nexport function ThemePicker({ source, theme, onChange }: ThemePickerProps): JSX.Element {\n const id = useId()\n return (\n <label htmlFor={id} className=\"a63-editor__theme-picker-label\">\n <span className=\"a63-editor__theme-picker-text\">Theme</span>\n <select\n id={id}\n aria-label=\"Theme\"\n className=\"a63-editor__theme-select\"\n value={theme ?? ''}\n onChange={e => onChange(setFrontmatterField(source, 'theme', e.target.value))}\n >\n <option value=\"\">Default</option>\n {BUILTIN_THEMES.map(t => (\n <option key={t} value={t}>\n {t.charAt(0).toUpperCase() + t.slice(1)}\n </option>\n ))}\n </select>\n </label>\n )\n}\n","import { type ChangeEvent, type KeyboardEvent, useCallback, useMemo, useRef, useState } from 'react'\nimport { listTemplates } from '../content/template-registry'\nimport { SlidesPlayer } from '../player/slides-player'\nimport type { SlideDeckItem } from '../types'\nimport { parseSlide } from './parse-slide'\nimport { getSlideBlock, setSlideProp, slideBlockIndices, switchSlideTemplate } from './slide-edit'\nimport { SlotForm } from './slot-form'\nimport { TemplatePicker } from './template-picker'\nimport { templateSnippets } from './template-snippets'\nimport { ThemePicker } from './theme-picker'\n\nexport interface EditPaneProps {\n source: string\n onChange: (next: string) => void\n onSave?: (source: string) => void | Promise<void>\n deck: SlideDeckItem | null\n error: string | null\n onPresent: () => void\n /**\n * The validated deck token theme (dark/terminal/editorial/neon/bold) from\n * frontmatter. ThemePicker (deck theme) is distinct from the Light/Dark\n * preview-canvas toggle (editor background only).\n */\n themeValue?: string\n}\n\ntype RightPaneTab = 'source' | 'form'\n\nexport function EditPane({\n source,\n onChange,\n onSave,\n deck,\n error,\n onPresent,\n themeValue,\n}: EditPaneProps) {\n const [theme, setTheme] = useState<'light' | 'dark'>('light')\n const [rightTab, setRightTab] = useState<RightPaneTab>('source')\n // TODO: sync with preview nav — currently uses a form-local stepper defaulting to slide 0.\n const [formSlideIdx, setFormSlideIdx] = useState(0)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const templates = useMemo(() => listTemplates(), [])\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value),\n [onChange]\n )\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 's') {\n e.preventDefault()\n onSave?.(source)\n }\n },\n [onSave, source]\n )\n const insert = useCallback(\n (name: string) => {\n const snippet = templateSnippets[name]\n if (!snippet) return\n onChange(`${source.replace(/\\s*$/, '')}\\n${snippet}`)\n requestAnimationFrame(() => {\n const el = textareaRef.current\n if (!el) return\n el.focus()\n el.selectionStart = el.selectionEnd = el.value.length\n el.scrollTop = el.scrollHeight\n })\n },\n [source, onChange]\n )\n\n // ── Form view helpers ─────────────────────────────────────────────────────\n const slideCount = useMemo(() => slideBlockIndices(source).length, [source])\n const clampedIdx = Math.min(formSlideIdx, Math.max(0, slideCount - 1))\n\n const currentBlock = useMemo(() => getSlideBlock(source, clampedIdx), [source, clampedIdx])\n const parsedSlide = useMemo(\n () => (currentBlock ? parseSlide(currentBlock.text) : null),\n [currentBlock]\n )\n\n const handleSlotChange = useCallback(\n (key: string, value: string) => {\n onChange(setSlideProp(source, clampedIdx, key, value))\n },\n [source, clampedIdx, onChange]\n )\n\n const handleTemplateSwitch = useCallback(\n (next: string, mapped: { props: Record<string, string>; dropped: string[] }) => {\n onChange(switchSlideTemplate(source, clampedIdx, next, mapped.props))\n },\n [source, clampedIdx, onChange]\n )\n\n return (\n <div className=\"a63-editor\">\n <section className=\"a63-editor__preview\" data-theme={theme}>\n {error ? (\n <div className=\"a63-editor__error\" role=\"alert\">\n <span className=\"a63-editor__error-tag\">MDX error</span>\n <span className=\"a63-editor__error-msg\">{error}</span>\n </div>\n ) : null}\n {deck ? (\n <div className=\"a63-editor__preview-stage\" key={theme}>\n <SlidesPlayer deck={deck} onBack={() => {}} />\n </div>\n ) : (\n <div className=\"a63-editor__preview-empty\">\n {error ? 'Fix the MDX error to render a preview.' : 'Compiling preview…'}\n </div>\n )}\n </section>\n <section className=\"a63-editor__source\">\n <div className=\"a63-editor__toolbar\">\n <span className=\"a63-editor__title\">Deck source · MDX</span>\n <div className=\"a63-editor__toolbar-actions\">\n {/* Source | Form sub-toggle */}\n <div className=\"a63-editor__subtoggle\" role=\"group\" aria-label=\"Edit mode\">\n <button\n type=\"button\"\n className=\"a63-editor__subtoggle-btn\"\n aria-pressed={rightTab === 'source'}\n onClick={() => setRightTab('source')}\n >\n Source\n </button>\n <button\n type=\"button\"\n className=\"a63-editor__subtoggle-btn\"\n aria-pressed={rightTab === 'form'}\n onClick={() => setRightTab('form')}\n >\n Form\n </button>\n </div>\n {/* ThemePicker: writes deck token theme to frontmatter `theme:`.\n Distinct from the Light/Dark toggle below (preview-canvas background only). */}\n <ThemePicker source={source} theme={themeValue} onChange={onChange} />\n {onSave ? (\n <button type=\"button\" className=\"a63-editor__save\" onClick={() => onSave(source)}>\n Save\n </button>\n ) : null}\n <button\n type=\"button\"\n className=\"a63-editor__theme-toggle\"\n onClick={() => setTheme(t => (t === 'light' ? 'dark' : 'light'))}\n aria-pressed={theme === 'dark'}\n >\n {theme === 'light' ? '☀︎ Light' : '☾ Dark'}\n </button>\n <button type=\"button\" className=\"a63-editor__present\" onClick={onPresent}>\n Present\n </button>\n </div>\n </div>\n\n {rightTab === 'source' ? (\n <>\n <textarea\n ref={textareaRef}\n className=\"a63-editor__textarea\"\n value={source}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n spellCheck={false}\n aria-label=\"Deck MDX source\"\n />\n <div className=\"a63-editor__palette\">\n <div className=\"a63-editor__palette-label\">Templates · click to append</div>\n <div className=\"a63-editor__palette-grid\">\n {templates.map(t => (\n <button\n key={t.name}\n type=\"button\"\n className=\"a63-editor__chip\"\n onClick={() => insert(t.name)}\n title={`Insert ${t.name}`}\n >\n <span className=\"a63-editor__chip-name\">{t.name}</span>\n <span className=\"a63-editor__chip-meta\">{t.label}</span>\n </button>\n ))}\n </div>\n </div>\n </>\n ) : (\n <div className=\"a63-editor__form-panel\">\n {/* Slide stepper */}\n <div className=\"a63-editor__slide-stepper\">\n <button\n type=\"button\"\n className=\"a63-editor__stepper-btn\"\n aria-label=\"Previous slide\"\n disabled={clampedIdx <= 0}\n onClick={() => setFormSlideIdx(i => Math.max(0, i - 1))}\n >\n ‹\n </button>\n <span className=\"a63-editor__stepper-label\">\n Slide {clampedIdx + 1} / {slideCount}\n </span>\n <button\n type=\"button\"\n className=\"a63-editor__stepper-btn\"\n aria-label=\"Next slide\"\n disabled={clampedIdx >= slideCount - 1}\n onClick={() => setFormSlideIdx(i => Math.min(slideCount - 1, i + 1))}\n >\n ›\n </button>\n </div>\n\n {/* Form content */}\n {parsedSlide === null ? (\n <p className=\"a63-editor__form-empty\">No slides found.</p>\n ) : parsedSlide.kind === 'opaque' ? (\n <div className=\"a63-editor__form-opaque\">\n <p>This slide is only editable in Source.</p>\n <button\n type=\"button\"\n className=\"a63-editor__subtoggle-btn\"\n onClick={() => setRightTab('source')}\n >\n Switch to Source\n </button>\n </div>\n ) : (\n <div className=\"a63-editor__form-fields\">\n <TemplatePicker\n name={parsedSlide.name}\n props={parsedSlide.props}\n onSwitch={handleTemplateSwitch}\n />\n <SlotForm\n name={parsedSlide.name}\n props={parsedSlide.props}\n onChange={handleSlotChange}\n />\n </div>\n )}\n </div>\n )}\n </section>\n </div>\n )\n}\n","import { type ComponentType, useEffect, useMemo, useState } from 'react'\nimport { resolveTheme } from '../content/themes'\nimport { SlidesPlayer } from '../player/slides-player'\nimport type { SlideDeckItem } from '../types'\nimport { compileDeck } from './compile-deck'\nimport { EditPane } from './edit-pane'\n\nexport type DeckSurfaceMode = 'present' | 'edit'\n\nexport interface DeckSurfaceProps {\n /**\n * Raw deck MDX source (frontmatter + `---`-separated slide body). The single\n * canonical input for both Present and Edit modes.\n *\n * **Controlled vs. uncontrolled:**\n * - When `onChange` is provided the surface is **controlled** — the parent\n * owns source state and must feed back the updated string on each change.\n * - When `onChange` is omitted the surface is **uncontrolled** and\n * **present-only**: `source` is read once on mount and later prop changes\n * are ignored. This is the production / read-only contract.\n */\n source: string\n /**\n * Called with the next source string on every edit or template insert\n * (in-memory, per-keystroke). Presence of this prop **enables Edit mode**\n * and makes the surface controlled — the parent holds source state.\n * When omitted the surface is present-only (no edit chrome, no keyboard\n * shortcut to enter Edit).\n */\n onChange?: (next: string) => void\n /**\n * Called on an **explicit** save action (Save button or Cmd/Ctrl-S in Edit\n * mode). This is the persistence hook, distinct from the per-keystroke\n * `onChange`. Wire it to the dev write-back plugin (or any async persistence\n * layer) to flush the source to disk on demand. No-op / absent in a\n * production build.\n */\n onSave?: (source: string) => void | Promise<void>\n /**\n * The mode the surface starts in. Defaults to `'present'`. Forced to\n * `'present'` when `onChange` is absent (present-only surfaces cannot enter\n * Edit mode).\n */\n initialMode?: DeckSurfaceMode\n /**\n * Debounce window in milliseconds before recompiling the preview after a\n * source change. Defaults to `300`. Pass `0` in tests to compile\n * synchronously on the next microtask tick.\n */\n debounceMs?: number\n}\n\ntype Preview = { Content: ComponentType; meta: SlideDeckItem['meta'] } | null\n\nexport function DeckSurface({\n source: sourceProp,\n onChange,\n onSave,\n initialMode = 'present',\n debounceMs = 300,\n}: DeckSurfaceProps) {\n const editable = onChange !== undefined\n\n // Controlled when onChange provided; uncontrolled otherwise.\n const [internalSource, setInternalSource] = useState(sourceProp)\n const source = editable ? sourceProp : internalSource\n\n const setSource = (next: string) => {\n if (editable) onChange(next)\n else setInternalSource(next)\n }\n\n const [mode, setMode] = useState<DeckSurfaceMode>(editable ? initialMode : 'present')\n\n const [preview, setPreview] = useState<Preview>(null)\n const [error, setError] = useState<string | null>(null)\n\n // Debounced runtime compile. Keeps the last good preview on error.\n useEffect(() => {\n let cancelled = false\n const h = setTimeout(async () => {\n const r = await compileDeck(source)\n if (cancelled) return\n if (r.ok) {\n setPreview({ Content: r.Content, meta: r.meta })\n setError(null)\n } else {\n setError(r.error)\n }\n }, debounceMs)\n return () => {\n cancelled = true\n clearTimeout(h)\n }\n }, [source, debounceMs])\n\n const deck: SlideDeckItem | null = useMemo(\n () => (preview ? { slug: 'draft', meta: preview.meta, content: preview.Content } : null),\n [preview]\n )\n\n const theme = resolveTheme(deck?.meta as { theme?: unknown } | undefined)\n\n // Keyboard shortcuts (only when editable).\n useEffect(() => {\n if (!editable) return\n const onKey = (e: KeyboardEvent) => {\n const typing = (e.target as HTMLElement)?.tagName === 'TEXTAREA'\n if (e.key === 'e' && !typing && mode === 'present') setMode('edit')\n if (e.key === 'Escape' && mode === 'edit') setMode('present')\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [editable, mode])\n\n if (editable && mode === 'edit') {\n return (\n <div className=\"a63-surface-edit\" data-slides-theme={theme}>\n <EditPane\n source={source}\n onChange={setSource}\n onSave={onSave}\n deck={deck}\n error={error}\n onPresent={() => setMode('present')}\n themeValue={theme}\n />\n </div>\n )\n }\n\n return (\n <div className=\"a63-surface\" data-slides-theme={theme}>\n {editable && (\n <button type=\"button\" className=\"a63-surface__edit\" onClick={() => setMode('edit')}>\n Edit\n </button>\n )}\n {deck ? (\n <SlidesPlayer deck={deck} onBack={() => {}} />\n ) : (\n <div className=\"a63-editor__preview-empty\">\n {error ? 'Fix the MDX error to render a preview.' : 'Compiling preview…'}\n </div>\n )}\n </div>\n )\n}\n","import { DeckSurface } from './deck-surface'\n\nexport interface DeckEditorProps {\n source: string\n onChange?: (next: string) => void\n debounceMs?: number\n}\n\n/**\n * Backward-compatible editor: DeckSurface locked to Edit mode. The unified\n * surface ({@link DeckSurface}) is the preferred API; this remains for existing\n * consumers.\n */\nexport function DeckEditor({ source, onChange, debounceMs }: DeckEditorProps) {\n return (\n <DeckSurface\n source={source}\n onChange={onChange ?? (() => {})}\n initialMode=\"edit\"\n debounceMs={debounceMs}\n />\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/editor/compile-deck.ts","../../src/editor/parse-slide.ts","../../src/editor/serialize-slot.ts","../../src/editor/slide-blocks.ts","../../src/editor/slide-edit.ts","../../src/editor/slot-form.tsx","../../src/editor/template-picker.tsx","../../src/editor/template-snippets.ts","../../src/editor/frontmatter-edit.ts","../../src/editor/theme-picker.tsx","../../src/editor/edit-pane.tsx","../../src/editor/deck-surface.tsx","../../src/editor/deck-editor.tsx"],"names":["IMPORT_RE","rendered","jsx","jsxs","useState","useMemo"],"mappings":"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","file":"index.js","sourcesContent":["import { evaluate } from '@mdx-js/mdx'\nimport yaml from 'js-yaml'\nimport type { ComponentType } from 'react'\nimport * as runtime from 'react/jsx-runtime'\nimport remarkGfm from 'remark-gfm'\nimport { slideMdxComponents } from '../content/mdx-components'\nimport type { SlideDeckMeta } from '../types'\n\n/**\n * Browser-safe YAML frontmatter split. We deliberately avoid the common\n * \"gray matter\" style parser because it depends on Node's `Buffer`, which\n * doesn't exist in the browser — a browser library must not force consumers to\n * polyfill Node globals.\n *\n * If `source` begins with a `---` fence line, the block up to the next `---`\n * fence is parsed as YAML into `meta` and the remainder is returned as `body`.\n * Otherwise `meta` is empty and the whole source is the `body`.\n */\nexport function parseFrontmatter(source: string): { meta: Record<string, unknown>; body: string } {\n // Frontmatter must start at the very top of the file (allowing a UTF-8 BOM).\n const normalized = source.replace(/^/, '')\n const lines = normalized.split('\\n')\n if (lines[0]?.trim() !== '---') {\n return { meta: {}, body: source }\n }\n\n // Find the closing fence line.\n let end = -1\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n end = i\n break\n }\n }\n if (end === -1) {\n // No closing fence — treat the whole thing as body, no frontmatter.\n return { meta: {}, body: source }\n }\n\n const yamlBlock = lines.slice(1, end).join('\\n')\n const body = lines.slice(end + 1).join('\\n')\n const loaded = yaml.load(yamlBlock)\n const meta = loaded && typeof loaded === 'object' ? (loaded as Record<string, unknown>) : {}\n return { meta, body }\n}\n\n/**\n * Result of a runtime deck compile.\n *\n * On success: the parsed frontmatter `meta` plus a `Content` component ready to\n * hand to `SlidesPlayer` as `deck.content`. On failure: a human-readable\n * `error` string (compile + frontmatter parsing both throw on bad input).\n */\nexport type CompileDeckResult =\n | { ok: true; meta: SlideDeckMeta; Content: ComponentType }\n | { ok: false; error: string }\n\n/**\n * Matches bare ES `import` statements at the start of a line. A deck's MDX body\n * carries lines like `import { CoverSlide } from \"@atom63/slides\"`. The runtime\n * `evaluate` below has no module resolver, so these must be stripped — the\n * components are injected via `useMDXComponents` instead (see compileDeck).\n *\n * Covers single- and multi-line import specifier blocks:\n * import Foo from \"x\"\n * import { A, B } from \"x\"\n * import {\n * A,\n * B,\n * } from \"x\"\n */\nconst IMPORT_RE = /^[ \\t]*import\\b[\\s\\S]*?(?:from\\s*['\"][^'\"]*['\"]|['\"][^'\"]*['\"])[ \\t]*;?[ \\t]*$/gm\n\n/** Remove bare `import ... from \"...\"` lines so runtime evaluate doesn't choke. */\nexport function stripImports(body: string): string {\n return body.replace(IMPORT_RE, '')\n}\n\nconst DEFAULT_META: SlideDeckMeta = {\n title: 'Untitled deck',\n date: new Date().toISOString().slice(0, 10),\n}\n\n/**\n * Compile a deck's raw MDX source into a renderable Content component using a\n * runtime MDX pipeline (no bundler step).\n *\n * Pipeline:\n * 1. `parseFrontmatter` splits the YAML frontmatter (the deck `meta`) from the\n * body using a browser-safe parser (no Node `Buffer`).\n * 2. `stripImports` removes bare `import ... from \"@atom63/slides\"` lines that\n * the runtime evaluator cannot resolve.\n * 3. `@mdx-js/mdx`'s `evaluate` compiles + runs the body. The slide components\n * (templates + primitives + markdown mappings) are provided through MDX\n * context via `useMDXComponents: () => slideMdxComponents`, so bare JSX such\n * as `<CoverSlide/>` resolves with no import. `---` thematic breaks are\n * preserved as the engine's slide separators.\n *\n * Async and can throw on malformed MDX/frontmatter — callers should debounce\n * and keep the last good render on failure (DeckEditor does this).\n */\nexport async function compileDeck(source: string): Promise<CompileDeckResult> {\n try {\n const { meta: data, body: content } = parseFrontmatter(source)\n const meta: SlideDeckMeta = { ...DEFAULT_META, ...(data as Partial<SlideDeckMeta>) }\n const body = stripImports(content)\n\n const { default: Content } = await evaluate(body, {\n ...runtime,\n useMDXComponents: () => slideMdxComponents,\n remarkPlugins: [remarkGfm],\n })\n\n return { ok: true, meta, Content: Content as ComponentType }\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err)\n return { ok: false, error }\n }\n}\n","import { Parser } from 'acorn'\nimport jsx from 'acorn-jsx'\nimport { templateNames } from '../content/template-registry'\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport type ParsedSlide =\n | { kind: 'template'; name: string; props: Record<string, string> }\n | { kind: 'opaque'; reason: string }\n\n// ── Internal acorn-jsx parser ──────────────────────────────────────────────\n\nconst JsxParser = Parser.extend(jsx())\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\n// biome-ignore lint/suspicious/noExplicitAny: acorn AST nodes are untyped\ntype AnyNode = any\n\n/**\n * Matches a leading ES `import` statement (with or without a trailing\n * semicolon). MDX decks routinely write `import { X } from '...'` with NO\n * semicolon, and acorn does NOT insert one before the following JSX — it\n * throws. We neutralize imports before parsing by replacing each import's\n * characters with EQUAL-LENGTH whitespace (newlines preserved), so the JSX\n * element's source offsets stay identical to the original block — which\n * `serialize-slot` relies on for span-based, byte-preserving edits.\n */\nconst IMPORT_RE =\n /^[ \\t]*import\\b[\\s\\S]*?(?:from\\s*['\"][^'\"]*['\"]|['\"][^'\"]*['\"])[ \\t]*;?[ \\t]*$/gm\n\nfunction blankImports(block: string): string {\n return block.replace(IMPORT_RE, m => m.replace(/[^\\n]/g, ' '))\n}\n\n/**\n * Given a parsed block string, return the single JSXElement acorn node if\n * the block contains exactly one JSX expression statement (with any number of\n * leading ImportDeclarations and nothing else). Returns null otherwise.\n *\n * Exported so Task 4 can reuse it (offset-based element finding).\n */\nexport function findTemplateElement(block: string): AnyNode | null {\n let ast: AnyNode\n try {\n // Blank imports first (offset-preserving) so a semicolon-less import before\n // the JSX doesn't make acorn throw. Offsets remain valid for `block`.\n ast = JsxParser.parse(blankImports(block), { ecmaVersion: 'latest', sourceType: 'module' })\n } catch {\n return null\n }\n\n const body: AnyNode[] = ast.body\n\n let jsxElement: AnyNode | null = null\n\n for (const node of body) {\n if (node.type === 'ImportDeclaration') {\n // allowed — skip\n continue\n }\n if (node.type === 'ExpressionStatement' && node.expression?.type === 'JSXElement') {\n if (jsxElement !== null) {\n // more than one JSX element → opaque\n return null\n }\n jsxElement = node.expression\n } else {\n // unexpected statement type (non-import, non-jsx-expression) → opaque\n return null\n }\n }\n\n return jsxElement\n}\n\n// ── Main export ────────────────────────────────────────────────────────────\n\n/**\n * Parse one MDX slide block and decide whether it is a known single-element\n * template with all literal-string props (→ \"template\") or anything else\n * (→ \"opaque\", edit-in-source only).\n */\nexport function parseSlide(block: string): ParsedSlide {\n const element = findTemplateElement(block)\n\n if (element === null) {\n return { kind: 'opaque', reason: 'block contains no single JSX template element' }\n }\n\n // Resolve component name (must be a plain JSXIdentifier, not a MemberExpression)\n const openingEl = element.openingElement\n const nameNode = openingEl.name\n if (nameNode.type !== 'JSXIdentifier') {\n return { kind: 'opaque', reason: 'JSX element name is not a plain identifier' }\n }\n const componentName: string = nameNode.name\n\n if (!(templateNames as readonly string[]).includes(componentName)) {\n return { kind: 'opaque', reason: `\"${componentName}\" is not a registered template` }\n }\n\n // Require attribute-only / self-closing (no non-whitespace children)\n const children: AnyNode[] = element.children ?? []\n for (const child of children) {\n if (child.type === 'JSXText') {\n // Allow whitespace-only JSXText (newlines, spaces between tags)\n if (child.value.trim() !== '') {\n return { kind: 'opaque', reason: 'element has non-whitespace children' }\n }\n } else {\n // JSXElement, JSXExpressionContainer, JSXFragment, JSXSpreadChild\n return { kind: 'opaque', reason: 'element has non-whitespace children' }\n }\n }\n\n // Extract props — all must be JSXAttribute with a string Literal value\n const props: Record<string, string> = {}\n const attributes: AnyNode[] = openingEl.attributes ?? []\n for (const attr of attributes) {\n if (attr.type === 'JSXSpreadAttribute') {\n return { kind: 'opaque', reason: 'element has spread attribute' }\n }\n if (attr.type !== 'JSXAttribute') {\n return { kind: 'opaque', reason: 'unexpected attribute node type' }\n }\n const attrName: string = attr.name.name\n const attrValue: AnyNode = attr.value\n\n // Allow bare boolean shorthand (e.g. `<Foo required />` — value is null)\n // but we only model it as a string flag \"true\" for now. Actually per spec:\n // only string Literals are permitted; anything else → opaque.\n if (attrValue === null) {\n // bare attribute (boolean shorthand) — not a string literal\n return { kind: 'opaque', reason: `attribute \"${attrName}\" has no string value (boolean shorthand)` }\n }\n if (attrValue.type !== 'Literal' || typeof attrValue.value !== 'string') {\n return {\n kind: 'opaque',\n reason: `attribute \"${attrName}\" is not a string literal`,\n }\n }\n\n props[attrName] = attrValue.value\n }\n\n return { kind: 'template', name: componentName, props }\n}\n","import { findTemplateElement } from './parse-slide'\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\n// biome-ignore lint/suspicious/noExplicitAny: acorn AST nodes are untyped\ntype AnyNode = any\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\n/**\n * Encode a plain string value as a JSX attribute string value with surrounding\n * double-quote delimiters.\n *\n * Acorn-jsx decodes JSX entity references inside quoted attribute string\n * values (`&` → `&`, `"` → `\"`), so our encoder must mirror exactly\n * what the parser decodes:\n * 1. `&` → `&` (MUST be first to avoid double-encoding)\n * 2. `\"` → `"`\n *\n * Other JSX-level entities (`<`, `>`, `'`) are not emitted by this\n * encoder, but we do NOT need to escape `<` or `>` inside a JSX attribute\n * string — those are only significant in JSX *text* content, not attribute\n * values.\n *\n * Exported so `slide-edit.ts` can reuse the same escaping for\n * `switchSlideTemplate`, ensuring the fix lands in exactly one place.\n */\nexport function renderJsxAttr(name: string, value: string): string {\n // Encode & first (before \" to avoid double-encoding), then \"\n const encoded = value.replaceAll('&', '&').replaceAll('\"', '"')\n return `${name}=\"${encoded}\"`\n}\n\n/**\n * Render a string value as a valid JSX attribute value (including surrounding\n * delimiters).\n *\n * Always produces a double-quoted value with `&` and `"` entity\n * escaping so that the round-trip `parseProp(setProp(block, k, v)) === v`\n * holds for ALL string values, including those containing `&`, `\"`, or\n * pre-existing entity references such as `"` or `&`.\n *\n * (The previous single-quote optimisation was removed because acorn-jsx also\n * decodes entities inside single-quoted attributes, making the same escaping\n * necessary regardless of delimiter choice. Using double-quotes uniformly\n * keeps the implementation simple and correct.)\n */\nfunction renderValue(value: string): string {\n const encoded = value.replaceAll('&', '&').replaceAll('\"', '"')\n return `\"${encoded}\"`\n}\n\n// ── Main export ────────────────────────────────────────────────────────────\n\n/**\n * Apply one prop change to an MDX slide block string.\n *\n * Only the bytes belonging to the changed attribute value are mutated; every\n * other character in `block` (whitespace, other props, import lines, the tag\n * name, etc.) is byte-preserved.\n *\n * @param block The raw MDX block text (may include leading import lines).\n * @param name The JSX attribute name to set.\n * @param value The new plain-string value.\n * @returns The updated block string.\n *\n * If `block` cannot be parsed as a single template element (e.g. opaque block)\n * the function returns `block` unchanged — callers should only call this on\n * blocks that `parseSlide` classifies as `{ kind: 'template' }`.\n */\nexport function setProp(block: string, name: string, value: string): string {\n const element: AnyNode | null = findTemplateElement(block)\n if (element === null) {\n return block\n }\n\n const openingEl: AnyNode = element.openingElement\n const attributes: AnyNode[] = openingEl.attributes ?? []\n\n // ── Case 1: attribute already exists ──────────────────────────────────────\n const existing: AnyNode | undefined = attributes.find(\n (attr: AnyNode) => attr.type === 'JSXAttribute' && attr.name?.name === name\n )\n\n if (existing !== undefined) {\n const attrValue: AnyNode = existing.value\n if (attrValue === null || attrValue.type !== 'Literal') {\n // Non-string attribute (expression container, boolean shorthand, etc.) —\n // not supported; return block unchanged to avoid corrupting it.\n return block\n }\n\n // No-op fast path: if the existing raw bytes already match what renderValue\n // would produce, return unchanged (byte-identical).\n const existingRaw = block.slice(attrValue.start, attrValue.end)\n const rendered = renderValue(value)\n if (existingRaw === rendered) {\n return block\n }\n\n // Value or encoding changed — replace only the value span (offsets include\n // the surrounding quotes).\n return block.slice(0, attrValue.start) + rendered + block.slice(attrValue.end)\n }\n\n // ── Case 2: attribute not present — insert before closing `/>` or `>` ─────\n //\n // Strategy: walk backwards from `openingEl.end` to find the `/>` or `>`\n // boundary and insert ` name=\"value\"` just before it (before any preceding\n // whitespace that is part of the closing token itself).\n //\n // acorn-jsx sets `openingElement.end` to the position AFTER the closing\n // `>` (or `/>`) of the opening tag. We back-track to find its start.\n\n const tagEnd: number = openingEl.end // exclusive: char at [tagEnd] is AFTER `>`\n const rendered = renderValue(value)\n\n // Find the position of `/>` or `>` by scanning backwards from tagEnd\n // (the two characters before tagEnd for a self-closing tag are `/>`).\n let insertAt: number\n if (block[tagEnd - 1] === '>' && block[tagEnd - 2] === '/') {\n // Self-closing: `/>` sits at [tagEnd-2, tagEnd)\n insertAt = tagEnd - 2\n } else if (block[tagEnd - 1] === '>') {\n // Regular closing `>`\n insertAt = tagEnd - 1\n } else {\n // Unexpected — fall back to inserting at tagEnd (safe, may look odd)\n insertAt = tagEnd\n }\n\n // Strip any whitespace that already precedes the `/>` so we control spacing\n // (don't add double spaces). We keep existing whitespace and just prepend\n // a single space before our new attribute.\n const insertion = ` ${name}=${rendered}`\n return block.slice(0, insertAt) + insertion + block.slice(insertAt)\n}\n","/**\n * Split a deck's MDX source into typed blocks so a form editor can mutate ONE\n * slide's content while leaving all other bytes byte-identical.\n *\n * Partition rules\n * ---------------\n * • `frontmatter` — the leading `---`…`---` YAML fence (including both fence\n * lines and the trailing newline after the closing `---`). Present only when\n * the source begins with a `---` line that has a matching closing fence.\n * • `separator` — a single `---\\n` (or `---` at EOF) at the top level that\n * acts as a slide boundary. In-code `---` lines (inside ``` / ~~~ fences) are\n * NOT treated as separators.\n * • `slide` — all content between separators (may be empty string if two\n * separators are adjacent). Each slide block's `text` includes any surrounding\n * blank lines that are NOT part of a separator.\n *\n * Byte-fidelity guarantee\n * -----------------------\n * `joinBlocks(splitBlocks(source)) === source` for every valid input.\n * Each block stores its exact original text; `joinBlocks` is just concatenation.\n */\n\nexport interface Block {\n /** Sequential index across all emitted blocks (0-based). */\n index: number\n kind: 'frontmatter' | 'separator' | 'slide'\n /** Exact original text for this block — concatenating all texts reproduces the source. */\n text: string\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Returns true when a line (already trimmed) opens or closes a fenced code block. */\nfunction isFenceMarker(trimmed: string): boolean {\n return trimmed.startsWith('```') || trimmed.startsWith('~~~')\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Split `source` into typed blocks.\n *\n * Algorithm:\n * 1. Strip a leading frontmatter block if present (same rule as parseFrontmatter).\n * 2. Walk the remainder line-by-line, toggling a `inFence` flag on ``` / ~~~.\n * 3. Lines that are exactly `---` at top level (not inside a fence) become\n * `separator` blocks; everything else accumulates into a `slide` chunk.\n * 4. A trailing `---` with no content after it still emits a separator but\n * does NOT emit an additional empty slide.\n */\nexport function splitBlocks(source: string): Block[] {\n const blocks: Block[] = []\n let idx = 0\n\n // ── Step 1: peel frontmatter ──────────────────────────────────────────────\n // Mirrors parseFrontmatter exactly (same fence rule, same BOM strip).\n const normalized = source.replace(/^/, '')\n const allLines = normalized.split('\\n')\n\n let remainder = source\n let frontmatterConsumed = 0 // byte count consumed by frontmatter\n\n if (allLines[0]?.trim() === '---') {\n // Look for a closing fence starting at line 1.\n let closeIdx = -1\n for (let i = 1; i < allLines.length; i++) {\n if (allLines[i].trim() === '---') {\n closeIdx = i\n break\n }\n }\n\n if (closeIdx !== -1) {\n // Frontmatter text = lines[0..closeIdx] joined with '\\n', plus the '\\n'\n // that was between closeIdx and the next line (the split() consumed it).\n const fmLines = allLines.slice(0, closeIdx + 1)\n // Each line was split on '\\n', so we re-join with '\\n' and add the\n // trailing '\\n' that existed after the closing fence (unless it was the\n // very last character of source, in which case split produces an empty\n // string at the end and we must not double-add).\n const fmText = `${fmLines.join('\\n')}\\n`\n\n // Validate that source actually contains this prefix (handles BOM).\n if (source.startsWith(fmText) || normalized.startsWith(fmText)) {\n frontmatterConsumed = fmText.length\n blocks.push({ index: idx++, kind: 'frontmatter', text: fmText })\n remainder = source.slice(frontmatterConsumed)\n }\n }\n }\n\n // ── Step 2: walk the remainder line-by-line ───────────────────────────────\n // We need line-by-line iteration but must reconstruct exact text for each\n // block. To keep byte-fidelity we track character offsets into `remainder`.\n\n const remLines = remainder.split('\\n')\n // split('\\n') on \"a\\nb\\n\" → [\"a\",\"b\",\"\"] — the trailing \"\" represents the\n // final newline. We re-attach '\\n' to every line except the very last one\n // when it is the empty string produced by a trailing newline.\n\n // Build an array of {content, raw} where `raw` is the exact substring\n // including the '\\n' terminator (or nothing for a true EOF without newline).\n const lineRaws: string[] = []\n for (let i = 0; i < remLines.length; i++) {\n const isLast = i === remLines.length - 1\n if (isLast && remLines[i] === '') {\n // This empty string is the artifact of a trailing '\\n' — the newline\n // already belongs to the previous line's raw. Don't emit a line for it.\n break\n }\n lineRaws.push(isLast ? remLines[i] : `${remLines[i]}\\n`)\n }\n\n let inFence = false\n let slideText = ''\n\n const flushSlide = () => {\n // Always emit a slide block, even if empty — this preserves byte-fidelity\n // for adjacent separators. But we skip a trailing empty slide if the\n // remainder ended at a separator (handled in the loop by checking whether\n // lineRaws is exhausted after the last separator).\n blocks.push({ index: idx++, kind: 'slide', text: slideText })\n slideText = ''\n }\n\n for (let i = 0; i < lineRaws.length; i++) {\n const raw = lineRaws[i]\n const trimmed = raw.trimEnd().replace(/\\r$/, '') // trim CR for CRLF safety\n\n if (!inFence && trimmed === '---') {\n // This is a top-level separator.\n // Flush accumulated slide content before the separator.\n flushSlide()\n // Emit the separator block (just the `---\\n` line).\n blocks.push({ index: idx++, kind: 'separator', text: raw })\n // After the separator, check if there's more content. If not, don't\n // emit a phantom empty slide — the loop will simply end.\n } else {\n // Toggle fenced-code state.\n if (isFenceMarker(trimmed)) {\n inFence = !inFence\n }\n slideText += raw\n }\n }\n\n // Flush final slide (may be empty if source ended with a separator).\n // Only emit if non-empty OR if there were no separators at all (single slide).\n if (slideText !== '' || blocks.filter(b => b.kind === 'slide').length === 0) {\n flushSlide()\n }\n\n return blocks\n}\n\n/**\n * Reconstruct the original source from a block array.\n * Concatenation is sufficient because each block stores its exact original text.\n */\nexport function joinBlocks(blocks: Block[]): string {\n return blocks.map(b => b.text).join('')\n}\n","/**\n * Pure helpers that operate on the WHOLE-deck `source` string, tying together\n * `splitBlocks` / `joinBlocks`, `setProp`, and `findTemplateElement` so that\n * the Form view can edit individual slides without touching any other bytes.\n *\n * All functions are stateless and synchronous — safe to call on every render.\n */\n\nimport { findTemplateElement, parseSlide } from './parse-slide'\nimport { renderJsxAttr, setProp } from './serialize-slot'\nimport { joinBlocks, splitBlocks } from './slide-blocks'\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Returns the indices (into `splitBlocks(source)`) of non-empty slide blocks,\n * in document order. Empty slide blocks (text that is blank / whitespace-only)\n * that appear between two adjacent separators are skipped — they are not\n * rendered as visible slides.\n */\nexport function slideBlockIndices(source: string): number[] {\n const blocks = splitBlocks(source)\n const indices: number[] = []\n for (const block of blocks) {\n if (block.kind === 'slide' && block.text.trim() !== '') {\n indices.push(block.index)\n }\n }\n return indices\n}\n\n/**\n * Return the block (by its position in `splitBlocks`) and its exact text for\n * the Nth (0-based) rendered slide. Returns `null` when `slideOrdinal` is out\n * of range.\n */\nexport function getSlideBlock(\n source: string,\n slideOrdinal: number\n): { blockIndex: number; text: string } | null {\n const indices = slideBlockIndices(source)\n if (slideOrdinal < 0 || slideOrdinal >= indices.length) return null\n const blockIndex = indices[slideOrdinal]\n const blocks = splitBlocks(source)\n const block = blocks.find(b => b.index === blockIndex)\n if (!block) return null\n return { blockIndex, text: block.text }\n}\n\n/**\n * Apply one prop change to the Nth (0-based) rendered slide inside `source`.\n *\n * Uses `setProp` for byte-stable mutation — only the changed attribute value\n * is rewritten; all other bytes in the source are preserved exactly.\n *\n * Returns the original `source` unchanged when `slideOrdinal` is out of range\n * or the target block is opaque (i.e. `parseSlide` does not return\n * `{ kind: 'template' }`). This is a hard safety gate — opaque blocks are\n * never lossily rewritten, regardless of whether `findTemplateElement` would\n * have matched.\n */\nexport function setSlideProp(\n source: string,\n slideOrdinal: number,\n key: string,\n value: string\n): string {\n const indices = slideBlockIndices(source)\n if (slideOrdinal < 0 || slideOrdinal >= indices.length) return source\n const blockIndex = indices[slideOrdinal]\n\n const blocks = splitBlocks(source)\n const updated = blocks.map(b => {\n if (b.index !== blockIndex) return b\n // Opaque-safety gate: only rewrite template blocks\n if (parseSlide(b.text).kind !== 'template') return b\n return { ...b, text: setProp(b.text, key, value) }\n })\n return joinBlocks(updated)\n}\n\n// ── switchSlideTemplate ───────────────────────────────────────────────────────\n\n/**\n * Render a set of props as JSX attribute string (name=\"value\" pairs, single\n * space separated).\n *\n * Delegates to `renderJsxAttr` (from serialize-slot) so entity escaping is\n * consolidated in one place and both code paths benefit from the same fix.\n */\nfunction renderProps(props: Record<string, string>): string {\n return Object.entries(props)\n .map(([k, v]) => renderJsxAttr(k, v))\n .join(' ')\n}\n\n/**\n * Replace the JSX template element in the Nth (0-based) rendered slide with a\n * freshly-rendered self-closing `<NextName key=\"val\" … />` built from\n * `nextProps`.\n *\n * Only the JSX element span is replaced; any leading import declarations or\n * surrounding whitespace/text in the block are preserved byte-for-byte.\n *\n * Returns the original `source` unchanged when `slideOrdinal` is out of range\n * or the target block is opaque (i.e. `parseSlide` does not return\n * `{ kind: 'template' }`). This is a hard safety gate — opaque blocks are\n * never lossily rewritten, regardless of whether `findTemplateElement` would\n * have matched.\n */\nexport function switchSlideTemplate(\n source: string,\n slideOrdinal: number,\n nextName: string,\n nextProps: Record<string, string>\n): string {\n const indices = slideBlockIndices(source)\n if (slideOrdinal < 0 || slideOrdinal >= indices.length) return source\n const blockIndex = indices[slideOrdinal]\n\n const blocks = splitBlocks(source)\n const updated = blocks.map(b => {\n if (b.index !== blockIndex) return b\n\n // Opaque-safety gate: only rewrite template blocks\n if (parseSlide(b.text).kind !== 'template') return b\n\n const element = findTemplateElement(b.text)\n if (element === null) return b\n\n // Build the replacement element string\n const propsStr = renderProps(nextProps)\n const replacement =\n propsStr.length > 0 ? `<${nextName} ${propsStr} />` : `<${nextName} />`\n\n // element.start / element.end are offsets into b.text\n const newText =\n b.text.slice(0, element.start) + replacement + b.text.slice(element.end)\n return { ...b, text: newText }\n })\n\n return joinBlocks(updated)\n}\n","import type { JSX } from 'react'\nimport type { SlotDef, SlotKind } from '../content/template-registry'\nimport { getTemplate } from '../content/template-registry'\n\nexport interface SlotFormProps {\n /** Template component name, e.g. \"CoverSlide\". */\n name: string\n /** Current prop values keyed by SlotDef.key. */\n props: Record<string, string>\n /** Called when any field value changes. */\n onChange: (key: string, value: string) => void\n}\n\nfunction fieldId(templateName: string, key: string): string {\n return `a63-slot-${templateName}-${key}`\n}\n\nfunction isMultiline(kind: SlotKind): boolean {\n return kind === 'richtext' || kind === 'list'\n}\n\nfunction SlotField({\n templateName,\n slot,\n value,\n onChange,\n}: {\n templateName: string\n slot: SlotDef\n value: string\n onChange: (key: string, value: string) => void\n}): JSX.Element {\n const id = fieldId(templateName, slot.key)\n const multiline = isMultiline(slot.kind)\n\n return (\n <div className=\"a63-form__field\">\n <div className=\"a63-form__label-row\">\n <label className=\"a63-form__label\" htmlFor={id}>\n {slot.label}\n </label>\n {slot.required && (\n <span className=\"a63-form__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </div>\n {multiline ? (\n <textarea\n id={id}\n className=\"a63-form__textarea\"\n value={value}\n required={slot.required}\n aria-required={slot.required}\n onChange={e => onChange(slot.key, e.target.value)}\n />\n ) : (\n <input\n type=\"text\"\n id={id}\n className=\"a63-form__input\"\n value={value}\n required={slot.required}\n aria-required={slot.required}\n onChange={e => onChange(slot.key, e.target.value)}\n />\n )}\n </div>\n )\n}\n\nexport function SlotForm({ name, props, onChange }: SlotFormProps): JSX.Element {\n const tpl = getTemplate(name)\n\n if (!tpl) {\n return (\n <p className=\"a63-form__unknown\">\n Unknown template: <code>{name}</code>\n </p>\n )\n }\n\n const slotGroupNames = tpl.slots.map(s => s.name)\n\n return (\n <div className=\"a63-form\">\n {tpl.props.map(slot => (\n <SlotField\n key={slot.key}\n templateName={name}\n slot={slot}\n value={props[slot.key] ?? ''}\n onChange={onChange}\n />\n ))}\n {slotGroupNames.length > 0 && (\n <p className=\"a63-form__slots-note\">\n Repeatable sections ({slotGroupNames.join(', ')}) are edited in Source.\n </p>\n )}\n </div>\n )\n}\n","import { type JSX, useState } from 'react'\nimport { getTemplate, listTemplates } from '../content/template-registry'\n\nexport interface TemplateSwitch {\n props: Record<string, string>\n dropped: string[]\n}\n\nexport interface TemplatePickerProps {\n /** Current template component name, e.g. \"CoverSlide\". */\n name: string\n /** Current prop values keyed by SlotDef.key. */\n props: Record<string, string>\n /** Called when the user picks a different template. */\n onSwitch: (next: string, mapped: TemplateSwitch) => void\n}\n\nexport function TemplatePicker({ name, props, onSwitch }: TemplatePickerProps): JSX.Element {\n const [warning, setWarning] = useState<{ from: string; to: string; dropped: string[] } | null>(\n null\n )\n\n function handleChange(next: string): void {\n if (next === name) return\n\n const nextDef = getTemplate(next)\n if (!nextDef) return\n\n const nextKeys = new Set(nextDef.props.map(s => s.key))\n\n // Carry over props whose key exists in the next template\n const carried: Record<string, string> = {}\n for (const [k, v] of Object.entries(props)) {\n if (nextKeys.has(k)) {\n carried[k] = v\n }\n }\n\n // Dropped = current keys not in next, but only those with non-empty values\n const dropped: string[] = Object.entries(props)\n .filter(([k, v]) => !nextKeys.has(k) && v !== '')\n .map(([k]) => k)\n\n // Fill required slots not already carried\n for (const slot of nextDef.props) {\n if (!(slot.key in carried)) {\n carried[slot.key] = ''\n }\n }\n\n onSwitch(next, { props: carried, dropped })\n\n if (dropped.length > 0) {\n setWarning({ from: name, to: next, dropped })\n } else {\n setWarning(null)\n }\n }\n\n const templates = listTemplates()\n\n return (\n <div className=\"a63-form__field\">\n <label className=\"a63-form__label\" htmlFor=\"a63-template-picker\">\n Template\n </label>\n <select\n id=\"a63-template-picker\"\n className=\"a63-form__input\"\n aria-label=\"Template\"\n value={name}\n onChange={e => handleChange(e.target.value)}\n >\n {templates.map(tpl => (\n <option key={tpl.name} value={tpl.name}>\n {tpl.label ?? tpl.name}\n </option>\n ))}\n </select>\n {warning && (\n <output className=\"a63-form__picker-warning\">\n <span>\n Switched {warning.from} → {warning.to}; dropped: {warning.dropped.join(', ')}.\n </span>\n <button\n type=\"button\"\n className=\"a63-form__picker-dismiss\"\n aria-label=\"Dismiss\"\n onClick={() => setWarning(null)}\n >\n ×\n </button>\n </output>\n )}\n </div>\n )\n}\n","import {\n listTemplates,\n type SlotDef,\n type SlotGroupDef,\n type TemplateDef,\n} from '../content/template-registry'\n\n/**\n * Generates a minimal, paste-ready MDX snippet per template from the engine's\n * registry (`listTemplates()`), mirroring the synthesis logic in\n * `skill/scripts/gen-templates.mjs`. The palette in\n * <DeckEditor> appends `templateSnippets[name]` when a template is clicked.\n *\n * Registry is the single source of truth; snippets cannot drift from the\n * published template props/slots.\n */\n\nconst PLACEHOLDER_IMG = '/images/placeholder-1920x1080.webp'\n\nfunction exampleValue(prop: SlotDef): string {\n switch (prop.kind) {\n case 'media':\n return PLACEHOLDER_IMG\n default:\n // text / richtext / list-as-scalar\n return `${prop.label}…`\n }\n}\n\n/** Render the direct-prop attributes for a template's opening tag. */\nfunction renderPropAttrs(props: SlotDef[], indent = ' '): string[] {\n const lines: string[] = []\n for (const prop of props) {\n if (prop.key === 'children') continue\n if (prop.array) {\n if (prop.kind === 'media') {\n lines.push(\n `${indent}${prop.key}={[\"${PLACEHOLDER_IMG}\", \"${PLACEHOLDER_IMG}\", \"${PLACEHOLDER_IMG}\"]}`\n )\n } else {\n lines.push(`${indent}${prop.key}={[{ label: \"Label\", value: \"Value\", href: \"https://…\" }]}`)\n }\n continue\n }\n lines.push(`${indent}${prop.key}=\"${exampleValue(prop)}\"`)\n }\n return lines\n}\n\n/** Render one compound-slot child element, e.g. `<HeroBento.Card title=\"…\" />`. */\nfunction renderSlotChild(templateName: string, slot: SlotGroupDef): string {\n const attrs: string[] = []\n let childrenText: string | null = null\n for (const prop of slot.props) {\n if (prop.key === 'children') {\n childrenText = `${prop.label}…`\n continue\n }\n if (prop.array) {\n attrs.push(`${prop.key}={[…]}`)\n continue\n }\n const value = prop.kind === 'media' ? PLACEHOLDER_IMG : `${prop.label}…`\n attrs.push(`${prop.key}=\"${value}\"`)\n }\n const tag = `${templateName}.${slot.name}`\n const attrStr = attrs.length ? ` ${attrs.join(' ')}` : ''\n if (childrenText !== null) {\n return ` <${tag}${attrStr}>${childrenText}</${tag}>`\n }\n return ` <${tag}${attrStr} />`\n}\n\n/**\n * Synthesize a minimal, valid MDX usage example from a template's schema.\n * - Simple templates → self-closing tag with its props.\n * - Compound templates → open tag + one instance of each slot at `min` (or 1).\n */\nexport function synthExample(t: TemplateDef): string {\n const hasSlots = t.slots.length > 0\n const propLines = renderPropAttrs(t.props)\n\n if (!hasSlots) {\n if (propLines.length === 0) return `<${t.name} />`\n return [`<${t.name}`, ...propLines, '/>'].join('\\n')\n }\n\n const open = propLines.length ? [`<${t.name}`, ...propLines, '>'] : [`<${t.name}>`]\n const childLines: string[] = []\n for (const slot of t.slots) {\n const count = Math.min(Math.max(slot.min, 1), 3)\n for (let i = 0; i < count; i++) {\n childLines.push(renderSlotChild(t.name, slot))\n }\n }\n return [...open, ...childLines, `</${t.name}>`].join('\\n')\n}\n\n/**\n * Wrap a synthesized example as an insertable slide: a leading `---` separator\n * (the engine's slide break) followed by the example, so appending to a deck\n * body always starts a fresh slide.\n */\nexport function toInsertSnippet(t: TemplateDef): string {\n return `\\n---\\n\\n${synthExample(t)}\\n`\n}\n\n/** Map of `templateName -> insertable MDX snippet`, built from the live registry. */\nexport const templateSnippets: Record<string, string> = Object.fromEntries(\n listTemplates().map(t => [t.name, toInsertSnippet(t)])\n)\n","/**\n * Pure frontmatter field editor — rewrites one YAML key in MDX/Markdown source\n * text-faithfully, without a YAML serializer, so unrelated lines are preserved\n * verbatim (including values that contain colons, quotes, etc.).\n *\n * Frontmatter detection mirrors `parseFrontmatter` in compile-deck.ts:\n * - First line must be exactly `---` (after stripping a UTF-8 BOM).\n * - The block closes at the next line that is exactly `---`.\n * - If no closing fence is found the whole source is treated as body (no FM).\n *\n * Line-ending fidelity: the function detects whether the source uses CRLF or\n * LF as its dominant line ending and uses that same sequence when rebuilding\n * the frontmatter fence and the inserted/updated field line. Body lines passed\n * through are never touched — they already carry the original endings.\n *\n * BOM fidelity: a leading UTF-8 BOM (U+FEFF) is stripped before detection and\n * re-prepended to the reconstructed output, so a BOM-prefixed source remains\n * BOM-prefixed after the edit.\n *\n * Empty-block edge case: when removing the only remaining field leaves an empty\n * inner block, we keep `---${nl}---${nl}` (two fence lines with no content\n * between them) rather than dropping the block entirely. This is the simplest\n * choice that is unambiguous and avoids shifting byte offsets of the body;\n * callers that want to collapse it can do so separately.\n */\n\nconst BOM = ''\n\n/**\n * Detect the dominant line ending in `text`.\n * Returns `'\\r\\n'` if CRLF appears at least as often as bare LF, else `'\\n'`.\n */\nfunction detectNewline(text: string): '\\r\\n' | '\\n' {\n const crlf = (text.match(/\\r\\n/g) ?? []).length\n const lf = (text.match(/(?<!\\r)\\n/g) ?? []).length\n return crlf >= lf && crlf > 0 ? '\\r\\n' : '\\n'\n}\n\n/**\n * Set (or remove) a single frontmatter field in `source`.\n *\n * - If `value` is non-empty: upsert `key: value` into the frontmatter block.\n * - If `value` is empty: remove the `key:` line from the frontmatter block.\n * - If no frontmatter block exists and `value` is non-empty: prepend one.\n * - If no frontmatter block exists and `value` is empty: return `source` unchanged.\n * - If the field already has the same value: return the same string reference\n * (byte-identical, no allocation).\n *\n * Line endings in the source (LF or CRLF) are detected and preserved. A leading\n * UTF-8 BOM is preserved in the output.\n */\nexport function setFrontmatterField(source: string, key: string, value: string): string {\n // ── BOM handling ─────────────────────────────────────────────────────────\n const hasBom = source.startsWith(BOM)\n const withoutBom = hasBom ? source.slice(1) : source\n\n // ── Line-ending detection (from the full source, before splitting) ────────\n const nl = detectNewline(withoutBom)\n\n // Split on \\n after stripping \\r so line content is clean regardless of ending.\n // We re-join with the detected `nl` when rebuilding.\n const lines = withoutBom.split('\\n').map(l => l.replace(/\\r$/, ''))\n\n // ── Detect frontmatter block ──────────────────────────────────────────────\n const hasFrontmatter = lines[0]?.trim() === '---'\n\n if (!hasFrontmatter) {\n // No frontmatter: removing a field is a no-op; adding creates a new block.\n if (!value) return source\n const prefix = `---${nl}${key}: ${value}${nl}---${nl}`\n return hasBom ? BOM + prefix + withoutBom : prefix + withoutBom\n }\n\n // Find closing fence.\n let closingIndex = -1\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n closingIndex = i\n break\n }\n }\n\n if (closingIndex === -1) {\n // Unclosed frontmatter — treat as body, same as parseFrontmatter.\n if (!value) return source\n const prefix = `---${nl}${key}: ${value}${nl}---${nl}`\n return hasBom ? BOM + prefix + withoutBom : prefix + withoutBom\n }\n\n // Inner YAML lines (between the two fences, excluding them).\n const innerLines = lines.slice(1, closingIndex)\n\n // Lines after the closing fence (the body, as a single rejoined string).\n // We preserve these exactly as-is — re-join with the detected nl so the\n // body's own endings are reconstructed faithfully.\n const bodyLines = lines.slice(closingIndex + 1)\n\n // ── Operate on innerLines ─────────────────────────────────────────────────\n // Match `key:` at the start of a line (key followed by colon, optional space).\n const keyRe = new RegExp(`^${escapeRegExp(key)}:`)\n const existingIdx = innerLines.findIndex(l => keyRe.test(l))\n\n let newInnerLines: string[]\n\n if (existingIdx !== -1) {\n const existing = innerLines[existingIdx]\n if (value) {\n const desired = `${key}: ${value}`\n // No-op check: same value already present → return source unchanged.\n if (existing === desired) return source\n // Replace in place.\n newInnerLines = [...innerLines]\n newInnerLines[existingIdx] = desired\n } else {\n // Remove the field line.\n newInnerLines = innerLines.filter((_, i) => i !== existingIdx)\n }\n } else {\n if (!value) {\n // Key doesn't exist and we're removing — no-op.\n return source\n }\n // Append new field as the last inner line.\n newInnerLines = [...innerLines, `${key}: ${value}`]\n }\n\n // ── Rebuild ───────────────────────────────────────────────────────────────\n // Reconstruct the frontmatter block + the body, using the source's own nl.\n const innerBlock = newInnerLines.join(nl)\n const bodyBlock = bodyLines.join(nl)\n const rebuilt = `---${nl}${innerBlock}${nl}---${nl}${bodyBlock}`\n\n return hasBom ? BOM + rebuilt : rebuilt\n}\n\n/** Escape special regex characters in a literal string. */\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","import { type JSX, useId } from 'react'\nimport { BUILTIN_THEMES } from '../content/themes'\nimport { setFrontmatterField } from './frontmatter-edit'\n\nexport interface ThemePickerProps {\n source: string\n theme: string | undefined\n onChange: (next: string) => void\n}\n\n/**\n * ThemePicker — writes `theme:` into the deck frontmatter.\n *\n * This controls the DECK token theme (dark/terminal/editorial/neon/bold),\n * distinct from the Light/Dark preview-canvas toggle in EditPane which only\n * affects the editor's background. Selecting \"Default\" removes the theme line.\n */\nexport function ThemePicker({ source, theme, onChange }: ThemePickerProps): JSX.Element {\n const id = useId()\n return (\n <label htmlFor={id} className=\"a63-editor__theme-picker-label\">\n <span className=\"a63-editor__theme-picker-text\">Theme</span>\n <select\n id={id}\n aria-label=\"Theme\"\n className=\"a63-editor__theme-select\"\n value={theme ?? ''}\n onChange={e => onChange(setFrontmatterField(source, 'theme', e.target.value))}\n >\n <option value=\"\">Default</option>\n {BUILTIN_THEMES.map(t => (\n <option key={t} value={t}>\n {t.charAt(0).toUpperCase() + t.slice(1)}\n </option>\n ))}\n </select>\n </label>\n )\n}\n","import { type ChangeEvent, type KeyboardEvent, useCallback, useMemo, useRef, useState } from 'react'\nimport { listTemplates } from '../content/template-registry'\nimport { SlidesPlayer } from '../player/slides-player'\nimport type { SlideDeckItem } from '../types'\nimport { parseSlide } from './parse-slide'\nimport { getSlideBlock, setSlideProp, slideBlockIndices, switchSlideTemplate } from './slide-edit'\nimport { SlotForm } from './slot-form'\nimport { TemplatePicker } from './template-picker'\nimport { templateSnippets } from './template-snippets'\nimport { ThemePicker } from './theme-picker'\n\nexport interface EditPaneProps {\n source: string\n onChange: (next: string) => void\n onSave?: (source: string) => void | Promise<void>\n deck: SlideDeckItem | null\n error: string | null\n onPresent: () => void\n /**\n * The validated deck token theme (dark/terminal/editorial/neon/bold) from\n * frontmatter. ThemePicker (deck theme) is distinct from the Light/Dark\n * preview-canvas toggle (editor background only).\n */\n themeValue?: string\n}\n\ntype RightPaneTab = 'source' | 'form'\n\nexport function EditPane({\n source,\n onChange,\n onSave,\n deck,\n error,\n onPresent,\n themeValue,\n}: EditPaneProps) {\n const [rightTab, setRightTab] = useState<RightPaneTab>('source')\n // TODO: sync with preview nav — currently uses a form-local stepper defaulting to slide 0.\n const [formSlideIdx, setFormSlideIdx] = useState(0)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const templates = useMemo(() => listTemplates(), [])\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value),\n [onChange]\n )\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 's') {\n e.preventDefault()\n onSave?.(source)\n }\n },\n [onSave, source]\n )\n const insert = useCallback(\n (name: string) => {\n const snippet = templateSnippets[name]\n if (!snippet) return\n onChange(`${source.replace(/\\s*$/, '')}\\n${snippet}`)\n requestAnimationFrame(() => {\n const el = textareaRef.current\n if (!el) return\n el.focus()\n el.selectionStart = el.selectionEnd = el.value.length\n el.scrollTop = el.scrollHeight\n })\n },\n [source, onChange]\n )\n\n // ── Form view helpers ─────────────────────────────────────────────────────\n const slideCount = useMemo(() => slideBlockIndices(source).length, [source])\n const clampedIdx = Math.min(formSlideIdx, Math.max(0, slideCount - 1))\n\n const currentBlock = useMemo(() => getSlideBlock(source, clampedIdx), [source, clampedIdx])\n const parsedSlide = useMemo(\n () => (currentBlock ? parseSlide(currentBlock.text) : null),\n [currentBlock]\n )\n\n const handleSlotChange = useCallback(\n (key: string, value: string) => {\n onChange(setSlideProp(source, clampedIdx, key, value))\n },\n [source, clampedIdx, onChange]\n )\n\n const handleTemplateSwitch = useCallback(\n (next: string, mapped: { props: Record<string, string>; dropped: string[] }) => {\n onChange(switchSlideTemplate(source, clampedIdx, next, mapped.props))\n },\n [source, clampedIdx, onChange]\n )\n\n return (\n // data-slides-theme on the real grid box (NOT a display:contents wrapper) so\n // the deck theme's custom properties reliably cascade to the slide preview.\n <div className=\"a63-editor\" data-slides-theme={themeValue || undefined}>\n <section className=\"a63-editor__preview\">\n {error ? (\n <div className=\"a63-editor__error\" role=\"alert\">\n <span className=\"a63-editor__error-tag\">MDX error</span>\n <span className=\"a63-editor__error-msg\">{error}</span>\n </div>\n ) : null}\n {deck ? (\n <div className=\"a63-editor__preview-stage\">\n <SlidesPlayer deck={deck} onBack={() => {}} />\n </div>\n ) : (\n <div className=\"a63-editor__preview-empty\">\n {error ? 'Fix the MDX error to render a preview.' : 'Compiling preview…'}\n </div>\n )}\n </section>\n <section className=\"a63-editor__source\">\n <div className=\"a63-editor__toolbar\">\n <span className=\"a63-editor__title\">Deck source · MDX</span>\n <div className=\"a63-editor__toolbar-actions\">\n {/* Source | Form sub-toggle */}\n <div className=\"a63-editor__subtoggle\" role=\"group\" aria-label=\"Edit mode\">\n <button\n type=\"button\"\n className=\"a63-editor__subtoggle-btn\"\n aria-pressed={rightTab === 'source'}\n onClick={() => setRightTab('source')}\n >\n Source\n </button>\n <button\n type=\"button\"\n className=\"a63-editor__subtoggle-btn\"\n aria-pressed={rightTab === 'form'}\n onClick={() => setRightTab('form')}\n >\n Form\n </button>\n </div>\n {/* ThemePicker: writes the deck token theme to frontmatter `theme:`. */}\n <ThemePicker source={source} theme={themeValue} onChange={onChange} />\n {onSave ? (\n <button type=\"button\" className=\"a63-editor__save\" onClick={() => onSave(source)}>\n Save\n </button>\n ) : null}\n <button type=\"button\" className=\"a63-editor__present\" onClick={onPresent}>\n Present\n </button>\n </div>\n </div>\n\n {rightTab === 'source' ? (\n <>\n <textarea\n ref={textareaRef}\n className=\"a63-editor__textarea\"\n value={source}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n spellCheck={false}\n aria-label=\"Deck MDX source\"\n />\n <div className=\"a63-editor__palette\">\n <div className=\"a63-editor__palette-label\">Templates · click to append</div>\n <div className=\"a63-editor__palette-grid\">\n {templates.map(t => (\n <button\n key={t.name}\n type=\"button\"\n className=\"a63-editor__chip\"\n onClick={() => insert(t.name)}\n title={`Insert ${t.name}`}\n >\n <span className=\"a63-editor__chip-name\">{t.name}</span>\n <span className=\"a63-editor__chip-meta\">{t.label}</span>\n </button>\n ))}\n </div>\n </div>\n </>\n ) : (\n <div className=\"a63-editor__form-panel\">\n {/* Slide stepper */}\n <div className=\"a63-editor__slide-stepper\">\n <button\n type=\"button\"\n className=\"a63-editor__stepper-btn\"\n aria-label=\"Previous slide\"\n disabled={clampedIdx <= 0}\n onClick={() => setFormSlideIdx(i => Math.max(0, i - 1))}\n >\n ‹\n </button>\n <span className=\"a63-editor__stepper-label\">\n Slide {clampedIdx + 1} / {slideCount}\n </span>\n <button\n type=\"button\"\n className=\"a63-editor__stepper-btn\"\n aria-label=\"Next slide\"\n disabled={clampedIdx >= slideCount - 1}\n onClick={() => setFormSlideIdx(i => Math.min(slideCount - 1, i + 1))}\n >\n ›\n </button>\n </div>\n\n {/* Form content */}\n {parsedSlide === null ? (\n <p className=\"a63-editor__form-empty\">No slides found.</p>\n ) : parsedSlide.kind === 'opaque' ? (\n <div className=\"a63-editor__form-opaque\">\n <p>This slide is only editable in Source.</p>\n <button\n type=\"button\"\n className=\"a63-editor__subtoggle-btn\"\n onClick={() => setRightTab('source')}\n >\n Switch to Source\n </button>\n </div>\n ) : (\n <div className=\"a63-editor__form-fields\">\n <TemplatePicker\n name={parsedSlide.name}\n props={parsedSlide.props}\n onSwitch={handleTemplateSwitch}\n />\n <SlotForm\n name={parsedSlide.name}\n props={parsedSlide.props}\n onChange={handleSlotChange}\n />\n </div>\n )}\n </div>\n )}\n </section>\n </div>\n )\n}\n","import { type ComponentType, useEffect, useMemo, useState } from 'react'\nimport { resolveTheme } from '../content/themes'\nimport { SlidesPlayer } from '../player/slides-player'\nimport type { SlideDeckItem } from '../types'\nimport { compileDeck } from './compile-deck'\nimport { EditPane } from './edit-pane'\n\nexport type DeckSurfaceMode = 'present' | 'edit'\n\nexport interface DeckSurfaceProps {\n /**\n * Raw deck MDX source (frontmatter + `---`-separated slide body). The single\n * canonical input for both Present and Edit modes.\n *\n * **Controlled vs. uncontrolled:**\n * - When `onChange` is provided the surface is **controlled** — the parent\n * owns source state and must feed back the updated string on each change.\n * - When `onChange` is omitted the surface is **uncontrolled** and\n * **present-only**: `source` is read once on mount and later prop changes\n * are ignored. This is the production / read-only contract.\n */\n source: string\n /**\n * Called with the next source string on every edit or template insert\n * (in-memory, per-keystroke). Presence of this prop **enables Edit mode**\n * and makes the surface controlled — the parent holds source state.\n * When omitted the surface is present-only (no edit chrome, no keyboard\n * shortcut to enter Edit).\n */\n onChange?: (next: string) => void\n /**\n * Called on an **explicit** save action (Save button or Cmd/Ctrl-S in Edit\n * mode). This is the persistence hook, distinct from the per-keystroke\n * `onChange`. Wire it to the dev write-back plugin (or any async persistence\n * layer) to flush the source to disk on demand. No-op / absent in a\n * production build.\n */\n onSave?: (source: string) => void | Promise<void>\n /**\n * The mode the surface starts in. Defaults to `'present'`. Forced to\n * `'present'` when `onChange` is absent (present-only surfaces cannot enter\n * Edit mode).\n */\n initialMode?: DeckSurfaceMode\n /**\n * Debounce window in milliseconds before recompiling the preview after a\n * source change. Defaults to `300`. Pass `0` in tests to compile\n * synchronously on the next microtask tick.\n */\n debounceMs?: number\n}\n\ntype Preview = { Content: ComponentType; meta: SlideDeckItem['meta'] } | null\n\nexport function DeckSurface({\n source: sourceProp,\n onChange,\n onSave,\n initialMode = 'present',\n debounceMs = 300,\n}: DeckSurfaceProps) {\n const editable = onChange !== undefined\n\n // Controlled when onChange provided; uncontrolled otherwise.\n const [internalSource, setInternalSource] = useState(sourceProp)\n const source = editable ? sourceProp : internalSource\n\n const setSource = (next: string) => {\n if (editable) onChange(next)\n else setInternalSource(next)\n }\n\n const [mode, setMode] = useState<DeckSurfaceMode>(editable ? initialMode : 'present')\n\n const [preview, setPreview] = useState<Preview>(null)\n const [error, setError] = useState<string | null>(null)\n\n // Debounced runtime compile. Keeps the last good preview on error.\n useEffect(() => {\n let cancelled = false\n const h = setTimeout(async () => {\n const r = await compileDeck(source)\n if (cancelled) return\n if (r.ok) {\n setPreview({ Content: r.Content, meta: r.meta })\n setError(null)\n } else {\n setError(r.error)\n }\n }, debounceMs)\n return () => {\n cancelled = true\n clearTimeout(h)\n }\n }, [source, debounceMs])\n\n const deck: SlideDeckItem | null = useMemo(\n () => (preview ? { slug: 'draft', meta: preview.meta, content: preview.Content } : null),\n [preview]\n )\n\n const theme = resolveTheme(deck?.meta as { theme?: unknown } | undefined)\n\n // Keyboard shortcuts (only when editable).\n useEffect(() => {\n if (!editable) return\n const onKey = (e: KeyboardEvent) => {\n const typing = (e.target as HTMLElement)?.tagName === 'TEXTAREA'\n if (e.key === 'e' && !typing && mode === 'present') setMode('edit')\n if (e.key === 'Escape' && mode === 'edit') setMode('present')\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [editable, mode])\n\n if (editable && mode === 'edit') {\n // EditPane applies `data-slides-theme` to its real `.a63-editor` box (via\n // themeValue) so the deck theme cascades to the slide — no display:contents\n // wrapper, which was breaking custom-property inheritance to the preview.\n return (\n <EditPane\n source={source}\n onChange={setSource}\n onSave={onSave}\n deck={deck}\n error={error}\n onPresent={() => setMode('present')}\n themeValue={theme}\n />\n )\n }\n\n return (\n <div className=\"a63-surface\" data-slides-theme={theme}>\n {editable && (\n <button type=\"button\" className=\"a63-surface__edit\" onClick={() => setMode('edit')}>\n Edit\n </button>\n )}\n {deck ? (\n <SlidesPlayer deck={deck} onBack={() => {}} />\n ) : (\n <div className=\"a63-editor__preview-empty\">\n {error ? 'Fix the MDX error to render a preview.' : 'Compiling preview…'}\n </div>\n )}\n </div>\n )\n}\n","import { DeckSurface } from './deck-surface'\n\nexport interface DeckEditorProps {\n source: string\n onChange?: (next: string) => void\n debounceMs?: number\n}\n\n/**\n * Backward-compatible editor: DeckSurface locked to Edit mode. The unified\n * surface ({@link DeckSurface}) is the preferred API; this remains for existing\n * consumers.\n */\nexport function DeckEditor({ source, onChange, debounceMs }: DeckEditorProps) {\n return (\n <DeckSurface\n source={source}\n onChange={onChange ?? (() => {})}\n initialMode=\"edit\"\n debounceMs={debounceMs}\n />\n )\n}\n"]}
|
package/package.json
CHANGED
package/src/editor/styles.css
CHANGED
|
@@ -108,24 +108,6 @@
|
|
|
108
108
|
letter-spacing: 0.01em;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
.a63-editor__theme-toggle {
|
|
112
|
-
display: inline-flex;
|
|
113
|
-
align-items: center;
|
|
114
|
-
gap: 0.4rem;
|
|
115
|
-
padding: 0.25rem 0.6rem;
|
|
116
|
-
border: 1px solid rgba(127, 127, 127, 0.4);
|
|
117
|
-
border-radius: 999px;
|
|
118
|
-
background: transparent;
|
|
119
|
-
color: inherit;
|
|
120
|
-
font-size: 0.72rem;
|
|
121
|
-
font-weight: 600;
|
|
122
|
-
cursor: pointer;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.a63-editor__theme-toggle:hover {
|
|
126
|
-
background: rgba(127, 127, 127, 0.12);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
111
|
.a63-editor__textarea {
|
|
130
112
|
flex: 1;
|
|
131
113
|
min-height: 0;
|
|
@@ -212,11 +194,6 @@
|
|
|
212
194
|
height: 100%;
|
|
213
195
|
}
|
|
214
196
|
|
|
215
|
-
/* DeckSurface edit-mode wrapper — pass-through so it doesn't affect layout. */
|
|
216
|
-
.a63-surface-edit {
|
|
217
|
-
display: contents;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
197
|
/* Floating Edit button — top-right corner of present view. */
|
|
221
198
|
.a63-surface__edit {
|
|
222
199
|
position: absolute;
|