@damiro/stylo 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +5 -0
  2. package/dist/{InPlaceView-Bu91_3Ig.js → InPlaceView-Dyf7I4XQ.js} +566 -562
  3. package/dist/InPlaceView-Dyf7I4XQ.js.map +1 -0
  4. package/dist/{Preview-AaGGwLQP.js → Preview-DIsFdBFA.js} +3 -3
  5. package/dist/{Preview-AaGGwLQP.js.map → Preview-DIsFdBFA.js.map} +1 -1
  6. package/dist/SplitView.d.ts +6 -1
  7. package/dist/SplitView.d.ts.map +1 -1
  8. package/dist/Stylo.d.ts.map +1 -1
  9. package/dist/editor/SourceView.d.ts +6 -1
  10. package/dist/editor/SourceView.d.ts.map +1 -1
  11. package/dist/editor/canvas-header-panel.d.ts +27 -0
  12. package/dist/editor/canvas-header-panel.d.ts.map +1 -0
  13. package/dist/editor/extensions.d.ts.map +1 -1
  14. package/dist/editor/search-panel-dom.d.ts +27 -0
  15. package/dist/editor/search-panel-dom.d.ts.map +1 -0
  16. package/dist/editor/search-panel.d.ts +13 -0
  17. package/dist/editor/search-panel.d.ts.map +1 -0
  18. package/dist/editor/theme.d.ts.map +1 -1
  19. package/dist/{embed-B2Dfkpd_.js → embed-Dsu6b-MV.js} +16 -9
  20. package/dist/embed-Dsu6b-MV.js.map +1 -0
  21. package/dist/frontmatter-DTCC0gaa.js +40 -0
  22. package/dist/frontmatter-DTCC0gaa.js.map +1 -0
  23. package/dist/inplace/InPlaceView.d.ts +6 -1
  24. package/dist/inplace/InPlaceView.d.ts.map +1 -1
  25. package/dist/inplace/table-widget.d.ts +10 -5
  26. package/dist/inplace/table-widget.d.ts.map +1 -1
  27. package/dist/inplace/theme-canvas.d.ts +7 -1
  28. package/dist/inplace/theme-canvas.d.ts.map +1 -1
  29. package/dist/render/Embed.d.ts.map +1 -1
  30. package/dist/styles.css +1 -1
  31. package/dist/stylo.js +190 -163
  32. package/dist/stylo.js.map +1 -1
  33. package/dist/toolbar/Toolbar.d.ts.map +1 -1
  34. package/dist/toolbar/commands.d.ts.map +1 -1
  35. package/dist/types.d.ts +12 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/{useCodeMirror-DtwupFgc.js → useCodeMirror-CjG9CwpB.js} +386 -228
  38. package/dist/useCodeMirror-CjG9CwpB.js.map +1 -0
  39. package/package.json +1 -1
  40. package/dist/InPlaceView-Bu91_3Ig.js.map +0 -1
  41. package/dist/embed-B2Dfkpd_.js.map +0 -1
  42. package/dist/frontmatter-DGUkb9z-.js +0 -39
  43. package/dist/frontmatter-DGUkb9z-.js.map +0 -1
  44. package/dist/useCodeMirror-DtwupFgc.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./markdown-BYXs9Tj8.js";
2
- import { i as s, n as c, r as l } from "./frontmatter-DGUkb9z-.js";
3
- import { a as u, i as d, n as f, o as p, t as m } from "./embed-B2Dfkpd_.js";
2
+ import { i as s, n as c, r as l } from "./frontmatter-DTCC0gaa.js";
3
+ import { a as u, i as d, n as f, o as p, t as m } from "./embed-Dsu6b-MV.js";
4
4
  import { useMemo as h } from "react";
5
5
  import { jsx as g, jsxs as _ } from "react/jsx-runtime";
6
6
  //#region src/render/remark-callout.ts
@@ -167,4 +167,4 @@ function S({ value: t, onWikiLinkClick: r, embedSource: a, onResolveError: l, fr
167
167
  //#endregion
168
168
  export { S as Preview };
169
169
 
170
- //# sourceMappingURL=Preview-AaGGwLQP.js.map
170
+ //# sourceMappingURL=Preview-DIsFdBFA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Preview-AaGGwLQP.js","names":[],"sources":["../src/render/remark-callout.ts","../src/render/remark-embed.ts","../src/render/remark-wikilink.ts","../src/render/Preview.tsx"],"sourcesContent":["import type { Blockquote, Root } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { CALLOUT_TOKEN, calloutBucket } from \"../callout\"\n\n/**\n * Turns an Obsidian callout blockquote (`> [!note] Title`) into a\n * `<blockquote class=\"stylo-callout stylo-callout-<bucket>\" data-callout=\"note\">`.\n * The `[!type]` token is stripped from the first line; a `::before` label keyed\n * off `data-callout` stands in for it (matching the in-place canvas). The\n * `-` / `+` fold marker is accepted and ignored — the box always renders open.\n */\nexport function remarkCallout() {\n return (tree: Root) => {\n visit(tree, \"blockquote\", (node: Blockquote) => {\n const para = node.children[0]\n if (para?.type !== \"paragraph\") return\n const first = para.children[0]\n if (first?.type !== \"text\") return\n\n const m = CALLOUT_TOKEN.exec(first.value)\n if (!m) return\n\n first.value = first.value.slice(m[0].length)\n const type = m[1]!.toLowerCase()\n node.data ??= {}\n const props = (node.data.hProperties ??= {}) as Record<string, unknown>\n props.className = [\"stylo-callout\", `stylo-callout-${calloutBucket(type)}`]\n props[\"data-callout\"] = type\n })\n }\n}\n","import type { Paragraph, PhrasingContent, Root, Text } from \"mdast\"\nimport { SKIP, visit } from \"unist-util-visit\"\nimport { EMBED_PATTERN, isLoneEmbed } from \"../embed\"\n\n/**\n * Turns `![[ref]]` transclusion syntax into empty carrier elements the `Embed`\n * component (wired in `Preview`) fills from the host's `embedSource`.\n *\n * - A **lone** `![[ref]]` — the whole paragraph, trimmed — becomes a block\n * `<div class=\"stylo-embed\" data-stylo-embed=\"ref\">`.\n * - A `![[ref]]` **inside other text** becomes an inline\n * `<span class=\"stylo-embed\" data-stylo-embed-inline=\"ref\">`, and the\n * surrounding text is preserved around it. The host node should be phrasing\n * content in this case.\n *\n * `![[…]]` inside inline or fenced code is left literal (it is not a `text`\n * node). Must run before `remarkWikilink`, or the inner `[[ref]]` is rewritten\n * to a link first. Off unless the consumer passes `embedSource` — `Preview` only\n * adds this plugin then.\n */\nexport function remarkEmbed() {\n return (tree: Root) => {\n visit(tree, \"paragraph\", (node: Paragraph) => {\n const only = node.children.length === 1 ? node.children[0] : undefined\n if (only?.type !== \"text\" || !isLoneEmbed(only.value)) return\n\n EMBED_PATTERN.lastIndex = 0\n const ref = (EMBED_PATTERN.exec(only.value.trim())?.[1] ?? \"\").trim()\n if (!ref) return\n\n node.children = []\n node.data ??= {}\n node.data.hName = \"div\"\n node.data.hProperties = { className: [\"stylo-embed\"], \"data-stylo-embed\": ref }\n })\n\n visit(tree, \"text\", (node: Text, index, parent) => {\n if (index == null || parent == null || !node.value.includes(\"![[\")) return\n\n const parts: PhrasingContent[] = []\n let cursor = 0\n // `matchAll` seeds its internal copy from the shared regex's `lastIndex`;\n // reset it so the scan starts at 0 (the lone-paragraph pass above left it\n // mid-string).\n EMBED_PATTERN.lastIndex = 0\n for (const match of node.value.matchAll(EMBED_PATTERN)) {\n const ref = (match[1] ?? \"\").trim()\n if (!ref) continue\n const start = match.index ?? 0\n if (start > cursor) parts.push({ type: \"text\", value: node.value.slice(cursor, start) })\n parts.push({\n type: \"text\",\n value: \"\",\n data: {\n hName: \"span\",\n hProperties: { className: [\"stylo-embed\"], \"data-stylo-embed-inline\": ref },\n hChildren: [],\n },\n })\n cursor = start + match[0].length\n }\n\n if (!parts.length) return\n if (cursor < node.value.length) parts.push({ type: \"text\", value: node.value.slice(cursor) })\n parent.children.splice(index, 1, ...parts)\n return [SKIP, index + parts.length]\n })\n }\n}\n","import type { Link, Root, Text } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { WIKILINK_PATTERN } from \"../wikilink\"\n\n/**\n * Rewrites `[[target]]` and `[[target|label]]` inside text into link nodes that\n * carry a `data-wikilink` attribute holding the target. The rendered href is\n * inert (`#`); navigation is the host's job via `onWikiLinkClick`.\n */\nexport function remarkWikilink() {\n return (tree: Root) => {\n visit(tree, \"text\", (node: Text, index, parent) => {\n if (parent == null || index == null || !node.value.includes(\"[[\")) return\n\n const out: Array<Text | Link> = []\n let cursor = 0\n\n for (const match of node.value.matchAll(WIKILINK_PATTERN)) {\n const [raw = \"\", rawTarget = \"\", rawLabel] = match\n const start = match.index ?? 0\n if (start > cursor) {\n out.push({ type: \"text\", value: node.value.slice(cursor, start) })\n }\n out.push({\n type: \"link\",\n url: \"#\",\n data: { hProperties: { \"data-wikilink\": rawTarget.trim() } },\n children: [{ type: \"text\", value: (rawLabel ?? rawTarget).trim() }],\n })\n cursor = start + raw.length\n }\n\n if (cursor === 0) return\n if (cursor < node.value.length) {\n out.push({ type: \"text\", value: node.value.slice(cursor) })\n }\n\n parent.children.splice(index, 1, ...out)\n return index + out.length\n })\n }\n}\n","import { useMemo } from \"react\"\nimport Markdown, { type Components } from \"react-markdown\"\nimport rehypeKatex from \"rehype-katex\"\nimport remarkFrontmatter from \"remark-frontmatter\"\nimport remarkGfm from \"remark-gfm\"\nimport remarkMath from \"remark-math\"\nimport { splitFrontmatter } from \"../frontmatter\"\nimport styles from \"../styles/stylo.module.css\"\nimport type { EmbedSource, FrontmatterDisplay, ResolveErrorInfo } from \"../types\"\nimport { Embed } from \"./Embed\"\nimport { remarkCallout } from \"./remark-callout\"\nimport { remarkEmbed } from \"./remark-embed\"\nimport { remarkWikilink } from \"./remark-wikilink\"\n\nconst REHYPE_PLUGINS = [rehypeKatex]\n\nexport interface PreviewProps {\n value: string\n onWikiLinkClick?: (target: string) => void\n /** Resolves `![[ref]]` embeds. Omit and `![[…]]` stays literal. */\n embedSource?: EmbedSource\n /** Notified when `embedSource` rejects; the literal fallback still renders. */\n onResolveError?: (error: unknown, info: ResolveErrorInfo) => void\n /** `\"code\"` renders the `---` block as a styled `<pre>`; `\"hidden\"` (default) drops it. */\n frontmatter?: FrontmatterDisplay\n}\n\n/** Rendered Markdown + KaTeX view. A pure function of the string. */\nexport function Preview({\n value,\n onWikiLinkClick,\n embedSource,\n onResolveError,\n frontmatter = \"hidden\",\n}: PreviewProps) {\n const fm = frontmatter === \"code\" ? splitFrontmatter(value) : null\n\n // `remarkEmbed` must precede `remarkWikilink` (it consumes the `![[…]]` before\n // the inner `[[…]]` is rewritten) and is only in the pipeline when the host\n // opts in, so a bare `![[x]]` renders unchanged otherwise.\n const remarkPlugins = useMemo(\n () => [\n remarkFrontmatter,\n remarkGfm,\n remarkMath,\n ...(embedSource ? [remarkEmbed] : []),\n remarkWikilink,\n remarkCallout,\n ],\n [embedSource],\n )\n\n const components: Components = {\n a({ node: _node, children, ...rest }) {\n const target = (rest as Record<string, unknown>)[\"data-wikilink\"]\n if (typeof target === \"string\") {\n return (\n <a\n {...rest}\n href=\"#\"\n onClick={(event) => {\n event.preventDefault()\n onWikiLinkClick?.(target)\n }}\n >\n {children}\n </a>\n )\n }\n return (\n <a {...rest} rel=\"noreferrer\">\n {children}\n </a>\n )\n },\n div({ node: _node, children, ...rest }) {\n const reference = (rest as Record<string, unknown>)[\"data-stylo-embed\"]\n if (typeof reference === \"string\" && embedSource) {\n return (\n <div {...rest}>\n <Embed reference={reference} source={embedSource} onError={onResolveError} />\n </div>\n )\n }\n return <div {...rest}>{children}</div>\n },\n span({ node: _node, children, ...rest }) {\n const reference = (rest as Record<string, unknown>)[\"data-stylo-embed-inline\"]\n if (typeof reference === \"string\" && embedSource) {\n return (\n <span {...rest}>\n <Embed reference={reference} source={embedSource} onError={onResolveError} inline />\n </span>\n )\n }\n return <span {...rest}>{children}</span>\n },\n }\n\n return (\n <div className={styles.preview}>\n {fm && <div className=\"stylo-frontmatter\">{fm.frontmatter}</div>}\n <Markdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={REHYPE_PLUGINS}\n components={components}\n >\n {value}\n </Markdown>\n </div>\n )\n}\n"],"mappings":";;;;;;AAWA,SAAgB,IAAgB;CAC9B,QAAQ,MAAe;EACrB,EAAM,GAAM,eAAe,MAAqB;GAC9C,IAAM,IAAO,EAAK,SAAS;GAC3B,IAAI,GAAM,SAAS,aAAa;GAChC,IAAM,IAAQ,EAAK,SAAS;GAC5B,IAAI,GAAO,SAAS,QAAQ;GAE5B,IAAM,IAAI,EAAc,KAAK,EAAM,KAAK;GACxC,IAAI,CAAC,GAAG;GAER,EAAM,QAAQ,EAAM,MAAM,MAAM,EAAE,EAAE,CAAC,MAAM;GAC3C,IAAM,IAAO,EAAE,EAAE,CAAE,YAAY;GAC/B,EAAK,SAAS,CAAC;GACf,IAAM,IAAS,EAAK,KAAK,gBAAgB,CAAC;GAE1C,AADA,EAAM,YAAY,CAAC,iBAAiB,iBAAiB,EAAc,CAAI,GAAG,GAC1E,EAAM,kBAAkB;EAC1B,CAAC;CACH;AACF;;;ACVA,SAAgB,IAAc;CAC5B,QAAQ,MAAe;EAerB,AAdA,EAAM,GAAM,cAAc,MAAoB;GAC5C,IAAM,IAAO,EAAK,SAAS,WAAW,IAAI,EAAK,SAAS,KAAK,KAAA;GAC7D,IAAI,GAAM,SAAS,UAAU,CAAC,EAAY,EAAK,KAAK,GAAG;GAEvD,EAAc,YAAY;GAC1B,IAAM,KAAO,EAAc,KAAK,EAAK,MAAM,KAAK,CAAC,CAAC,GAAG,MAAM,GAAA,CAAI,KAAK;GAC/D,MAEL,EAAK,WAAW,CAAC,GACjB,EAAK,SAAS,CAAC,GACf,EAAK,KAAK,QAAQ,OAClB,EAAK,KAAK,cAAc;IAAE,WAAW,CAAC,aAAa;IAAG,oBAAoB;GAAI;EAChF,CAAC,GAED,EAAM,GAAM,SAAS,GAAY,GAAO,MAAW;GACjD,IAAI,KAAS,QAAQ,KAAU,QAAQ,CAAC,EAAK,MAAM,SAAS,KAAK,GAAG;GAEpE,IAAM,IAA2B,CAAC,GAC9B,IAAS;GAIb,EAAc,YAAY;GAC1B,KAAK,IAAM,KAAS,EAAK,MAAM,SAAS,CAAa,GAAG;IACtD,IAAM,KAAO,EAAM,MAAM,GAAA,CAAI,KAAK;IAClC,IAAI,CAAC,GAAK;IACV,IAAM,IAAQ,EAAM,SAAS;IAW7B,AAVI,IAAQ,KAAQ,EAAM,KAAK;KAAE,MAAM;KAAQ,OAAO,EAAK,MAAM,MAAM,GAAQ,CAAK;IAAE,CAAC,GACvF,EAAM,KAAK;KACT,MAAM;KACN,OAAO;KACP,MAAM;MACJ,OAAO;MACP,aAAa;OAAE,WAAW,CAAC,aAAa;OAAG,2BAA2B;MAAI;MAC1E,WAAW,CAAC;KACd;IACF,CAAC,GACD,IAAS,IAAQ,EAAM,EAAE,CAAC;GAC5B;GAEK,MAAM,QAGX,OAFI,IAAS,EAAK,MAAM,UAAQ,EAAM,KAAK;IAAE,MAAM;IAAQ,OAAO,EAAK,MAAM,MAAM,CAAM;GAAE,CAAC,GAC5F,EAAO,SAAS,OAAO,GAAO,GAAG,GAAG,CAAK,GAClC,CAAC,GAAM,IAAQ,EAAM,MAAM;EACpC,CAAC;CACH;AACF;;;AC3DA,SAAgB,IAAiB;CAC/B,QAAQ,MAAe;EACrB,EAAM,GAAM,SAAS,GAAY,GAAO,MAAW;GACjD,IAAI,KAAU,QAAQ,KAAS,QAAQ,CAAC,EAAK,MAAM,SAAS,IAAI,GAAG;GAEnE,IAAM,IAA0B,CAAC,GAC7B,IAAS;GAEb,KAAK,IAAM,KAAS,EAAK,MAAM,SAAS,CAAgB,GAAG;IACzD,IAAM,CAAC,IAAM,IAAI,IAAY,IAAI,KAAY,GACvC,IAAQ,EAAM,SAAS;IAU7B,AATI,IAAQ,KACV,EAAI,KAAK;KAAE,MAAM;KAAQ,OAAO,EAAK,MAAM,MAAM,GAAQ,CAAK;IAAE,CAAC,GAEnE,EAAI,KAAK;KACP,MAAM;KACN,KAAK;KACL,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAU,KAAK,EAAE,EAAE;KAC3D,UAAU,CAAC;MAAE,MAAM;MAAQ,QAAQ,KAAY,EAAA,CAAW,KAAK;KAAE,CAAC;IACpE,CAAC,GACD,IAAS,IAAQ,EAAI;GACvB;GAEI,UAAW,GAMf,OALI,IAAS,EAAK,MAAM,UACtB,EAAI,KAAK;IAAE,MAAM;IAAQ,OAAO,EAAK,MAAM,MAAM,CAAM;GAAE,CAAC,GAG5D,EAAO,SAAS,OAAO,GAAO,GAAG,GAAG,CAAG,GAChC,IAAQ,EAAI;EACrB,CAAC;CACH;AACF;;;AC3BA,IAAM,IAAiB,CAAC,CAAW;AAcnC,SAAgB,EAAQ,EACtB,UACA,oBACA,gBACA,mBACA,iBAAc,YACC;CACf,IAAM,IAAK,MAAgB,SAAS,EAAiB,CAAK,IAAI,MAKxD,IAAgB,QACd;EACJ;EACA;EACA;EACA,GAAI,IAAc,CAAC,CAAW,IAAI,CAAC;EACnC;EACA;CACF,GACA,CAAC,CAAW,CACd;CAiDA,OACE,kBAAC,OAAD;EAAK,WAAW,EAAO;EAAvB,UAAA,CACG,KAAM,kBAAC,OAAD;GAAK,WAAU;GAAqB,UAAA,EAAG;EAAiB,CAAA,GAC/D,kBAAC,GAAD;GACiB;GACf,eAAe;GACH,YAAA;IApDhB,EAAE,EAAE,MAAM,GAAO,aAAU,GAAG,KAAQ;KACpC,IAAM,IAAU,EAAiC;KAejD,OAdI,OAAO,KAAW,WAElB,kBAAC,KAAD;MACE,GAAI;MACJ,MAAK;MACL,UAAU,MAAU;OAElB,AADA,EAAM,eAAe,GACrB,IAAkB,CAAM;MAC1B;MAEC;KACA,CAAA,IAIL,kBAAC,KAAD;MAAG,GAAI;MAAM,KAAI;MACd;KACA,CAAA;IAEP;IACA,IAAI,EAAE,MAAM,GAAO,aAAU,GAAG,KAAQ;KACtC,IAAM,IAAa,EAAiC;KAQpD,OAPI,OAAO,KAAc,YAAY,IAEjC,kBAAC,OAAD;MAAK,GAAI;MACP,UAAA,kBAAC,GAAD;OAAkB;OAAW,QAAQ;OAAa,SAAS;MAAiB,CAAA;KACzE,CAAA,IAGF,kBAAC,OAAD;MAAK,GAAI;MAAO;KAAc,CAAA;IACvC;IACA,KAAK,EAAE,MAAM,GAAO,aAAU,GAAG,KAAQ;KACvC,IAAM,IAAa,EAAiC;KAQpD,OAPI,OAAO,KAAc,YAAY,IAEjC,kBAAC,QAAD;MAAM,GAAI;MACR,UAAA,kBAAC,GAAD;OAAkB;OAAW,QAAQ;OAAa,SAAS;OAAgB,QAAA;MAAQ,CAAA;KAC/E,CAAA,IAGH,kBAAC,QAAD;MAAM,GAAI;MAAO;KAAe,CAAA;IACzC;GASgB;GAEX,UAAA;EACO,CAAA,CACP;;AAET"}
1
+ {"version":3,"file":"Preview-DIsFdBFA.js","names":[],"sources":["../src/render/remark-callout.ts","../src/render/remark-embed.ts","../src/render/remark-wikilink.ts","../src/render/Preview.tsx"],"sourcesContent":["import type { Blockquote, Root } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { CALLOUT_TOKEN, calloutBucket } from \"../callout\"\n\n/**\n * Turns an Obsidian callout blockquote (`> [!note] Title`) into a\n * `<blockquote class=\"stylo-callout stylo-callout-<bucket>\" data-callout=\"note\">`.\n * The `[!type]` token is stripped from the first line; a `::before` label keyed\n * off `data-callout` stands in for it (matching the in-place canvas). The\n * `-` / `+` fold marker is accepted and ignored — the box always renders open.\n */\nexport function remarkCallout() {\n return (tree: Root) => {\n visit(tree, \"blockquote\", (node: Blockquote) => {\n const para = node.children[0]\n if (para?.type !== \"paragraph\") return\n const first = para.children[0]\n if (first?.type !== \"text\") return\n\n const m = CALLOUT_TOKEN.exec(first.value)\n if (!m) return\n\n first.value = first.value.slice(m[0].length)\n const type = m[1]!.toLowerCase()\n node.data ??= {}\n const props = (node.data.hProperties ??= {}) as Record<string, unknown>\n props.className = [\"stylo-callout\", `stylo-callout-${calloutBucket(type)}`]\n props[\"data-callout\"] = type\n })\n }\n}\n","import type { Paragraph, PhrasingContent, Root, Text } from \"mdast\"\nimport { SKIP, visit } from \"unist-util-visit\"\nimport { EMBED_PATTERN, isLoneEmbed } from \"../embed\"\n\n/**\n * Turns `![[ref]]` transclusion syntax into empty carrier elements the `Embed`\n * component (wired in `Preview`) fills from the host's `embedSource`.\n *\n * - A **lone** `![[ref]]` — the whole paragraph, trimmed — becomes a block\n * `<div class=\"stylo-embed\" data-stylo-embed=\"ref\">`.\n * - A `![[ref]]` **inside other text** becomes an inline\n * `<span class=\"stylo-embed\" data-stylo-embed-inline=\"ref\">`, and the\n * surrounding text is preserved around it. The host node should be phrasing\n * content in this case.\n *\n * `![[…]]` inside inline or fenced code is left literal (it is not a `text`\n * node). Must run before `remarkWikilink`, or the inner `[[ref]]` is rewritten\n * to a link first. Off unless the consumer passes `embedSource` — `Preview` only\n * adds this plugin then.\n */\nexport function remarkEmbed() {\n return (tree: Root) => {\n visit(tree, \"paragraph\", (node: Paragraph) => {\n const only = node.children.length === 1 ? node.children[0] : undefined\n if (only?.type !== \"text\" || !isLoneEmbed(only.value)) return\n\n EMBED_PATTERN.lastIndex = 0\n const ref = (EMBED_PATTERN.exec(only.value.trim())?.[1] ?? \"\").trim()\n if (!ref) return\n\n node.children = []\n node.data ??= {}\n node.data.hName = \"div\"\n node.data.hProperties = { className: [\"stylo-embed\"], \"data-stylo-embed\": ref }\n })\n\n visit(tree, \"text\", (node: Text, index, parent) => {\n if (index == null || parent == null || !node.value.includes(\"![[\")) return\n\n const parts: PhrasingContent[] = []\n let cursor = 0\n // `matchAll` seeds its internal copy from the shared regex's `lastIndex`;\n // reset it so the scan starts at 0 (the lone-paragraph pass above left it\n // mid-string).\n EMBED_PATTERN.lastIndex = 0\n for (const match of node.value.matchAll(EMBED_PATTERN)) {\n const ref = (match[1] ?? \"\").trim()\n if (!ref) continue\n const start = match.index ?? 0\n if (start > cursor) parts.push({ type: \"text\", value: node.value.slice(cursor, start) })\n parts.push({\n type: \"text\",\n value: \"\",\n data: {\n hName: \"span\",\n hProperties: { className: [\"stylo-embed\"], \"data-stylo-embed-inline\": ref },\n hChildren: [],\n },\n })\n cursor = start + match[0].length\n }\n\n if (!parts.length) return\n if (cursor < node.value.length) parts.push({ type: \"text\", value: node.value.slice(cursor) })\n parent.children.splice(index, 1, ...parts)\n return [SKIP, index + parts.length]\n })\n }\n}\n","import type { Link, Root, Text } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { WIKILINK_PATTERN } from \"../wikilink\"\n\n/**\n * Rewrites `[[target]]` and `[[target|label]]` inside text into link nodes that\n * carry a `data-wikilink` attribute holding the target. The rendered href is\n * inert (`#`); navigation is the host's job via `onWikiLinkClick`.\n */\nexport function remarkWikilink() {\n return (tree: Root) => {\n visit(tree, \"text\", (node: Text, index, parent) => {\n if (parent == null || index == null || !node.value.includes(\"[[\")) return\n\n const out: Array<Text | Link> = []\n let cursor = 0\n\n for (const match of node.value.matchAll(WIKILINK_PATTERN)) {\n const [raw = \"\", rawTarget = \"\", rawLabel] = match\n const start = match.index ?? 0\n if (start > cursor) {\n out.push({ type: \"text\", value: node.value.slice(cursor, start) })\n }\n out.push({\n type: \"link\",\n url: \"#\",\n data: { hProperties: { \"data-wikilink\": rawTarget.trim() } },\n children: [{ type: \"text\", value: (rawLabel ?? rawTarget).trim() }],\n })\n cursor = start + raw.length\n }\n\n if (cursor === 0) return\n if (cursor < node.value.length) {\n out.push({ type: \"text\", value: node.value.slice(cursor) })\n }\n\n parent.children.splice(index, 1, ...out)\n return index + out.length\n })\n }\n}\n","import { useMemo } from \"react\"\nimport Markdown, { type Components } from \"react-markdown\"\nimport rehypeKatex from \"rehype-katex\"\nimport remarkFrontmatter from \"remark-frontmatter\"\nimport remarkGfm from \"remark-gfm\"\nimport remarkMath from \"remark-math\"\nimport { splitFrontmatter } from \"../frontmatter\"\nimport styles from \"../styles/stylo.module.css\"\nimport type { EmbedSource, FrontmatterDisplay, ResolveErrorInfo } from \"../types\"\nimport { Embed } from \"./Embed\"\nimport { remarkCallout } from \"./remark-callout\"\nimport { remarkEmbed } from \"./remark-embed\"\nimport { remarkWikilink } from \"./remark-wikilink\"\n\nconst REHYPE_PLUGINS = [rehypeKatex]\n\nexport interface PreviewProps {\n value: string\n onWikiLinkClick?: (target: string) => void\n /** Resolves `![[ref]]` embeds. Omit and `![[…]]` stays literal. */\n embedSource?: EmbedSource\n /** Notified when `embedSource` rejects; the literal fallback still renders. */\n onResolveError?: (error: unknown, info: ResolveErrorInfo) => void\n /** `\"code\"` renders the `---` block as a styled `<pre>`; `\"hidden\"` (default) drops it. */\n frontmatter?: FrontmatterDisplay\n}\n\n/** Rendered Markdown + KaTeX view. A pure function of the string. */\nexport function Preview({\n value,\n onWikiLinkClick,\n embedSource,\n onResolveError,\n frontmatter = \"hidden\",\n}: PreviewProps) {\n const fm = frontmatter === \"code\" ? splitFrontmatter(value) : null\n\n // `remarkEmbed` must precede `remarkWikilink` (it consumes the `![[…]]` before\n // the inner `[[…]]` is rewritten) and is only in the pipeline when the host\n // opts in, so a bare `![[x]]` renders unchanged otherwise.\n const remarkPlugins = useMemo(\n () => [\n remarkFrontmatter,\n remarkGfm,\n remarkMath,\n ...(embedSource ? [remarkEmbed] : []),\n remarkWikilink,\n remarkCallout,\n ],\n [embedSource],\n )\n\n const components: Components = {\n a({ node: _node, children, ...rest }) {\n const target = (rest as Record<string, unknown>)[\"data-wikilink\"]\n if (typeof target === \"string\") {\n return (\n <a\n {...rest}\n href=\"#\"\n onClick={(event) => {\n event.preventDefault()\n onWikiLinkClick?.(target)\n }}\n >\n {children}\n </a>\n )\n }\n return (\n <a {...rest} rel=\"noreferrer\">\n {children}\n </a>\n )\n },\n div({ node: _node, children, ...rest }) {\n const reference = (rest as Record<string, unknown>)[\"data-stylo-embed\"]\n if (typeof reference === \"string\" && embedSource) {\n return (\n <div {...rest}>\n <Embed reference={reference} source={embedSource} onError={onResolveError} />\n </div>\n )\n }\n return <div {...rest}>{children}</div>\n },\n span({ node: _node, children, ...rest }) {\n const reference = (rest as Record<string, unknown>)[\"data-stylo-embed-inline\"]\n if (typeof reference === \"string\" && embedSource) {\n return (\n <span {...rest}>\n <Embed reference={reference} source={embedSource} onError={onResolveError} inline />\n </span>\n )\n }\n return <span {...rest}>{children}</span>\n },\n }\n\n return (\n <div className={styles.preview}>\n {fm && <div className=\"stylo-frontmatter\">{fm.frontmatter}</div>}\n <Markdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={REHYPE_PLUGINS}\n components={components}\n >\n {value}\n </Markdown>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { ReactNode } from "react";
1
2
  import type { EditorView } from "@codemirror/view";
2
3
  import type { CodeLanguages, EmbedSource, FrontmatterDisplay, ResolveErrorInfo, WikiLinkSource } from "./types";
3
4
  export interface SplitViewProps {
@@ -15,6 +16,10 @@ export interface SplitViewProps {
15
16
  onSave?: (value: string) => void;
16
17
  /** Forwarded the source pane's `EditorView` for the shared toolbar. */
17
18
  onViewChange?: (view: EditorView | null) => void;
19
+ /** Host content docked in the source pane, after its search panel. Read once. */
20
+ canvasHeader?: (ctx: {
21
+ view: EditorView | null;
22
+ }) => ReactNode;
18
23
  }
19
24
  /**
20
25
  * Source and preview side by side. Both panes are a pure function of the same
@@ -22,5 +27,5 @@ export interface SplitViewProps {
22
27
  * Stylo root to have a bounded height — otherwise both panes grow and the page
23
28
  * scrolls instead.
24
29
  */
25
- export declare function SplitView({ value, onChange, onWikiLinkClick, readOnly, placeholder, codeLanguages, wikiLinkSource, embedSource, onResolveError, frontmatter, onSave, onViewChange, }: SplitViewProps): import("react").JSX.Element;
30
+ export declare function SplitView({ value, onChange, onWikiLinkClick, readOnly, placeholder, codeLanguages, wikiLinkSource, embedSource, onResolveError, frontmatter, onSave, onViewChange, canvasHeader, }: SplitViewProps): import("react").JSX.Element;
26
31
  //# sourceMappingURL=SplitView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SplitView.d.ts","sourceRoot":"","sources":["../src/SplitView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIlD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACf,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;CACjD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,MAAM,EACN,YAAY,GACb,EAAE,cAAc,+BAgEhB"}
1
+ {"version":3,"file":"SplitView.d.ts","sourceRoot":"","sources":["../src/SplitView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIlD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACf,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;CAC/D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,MAAM,EACN,YAAY,EACZ,YAAY,GACb,EAAE,cAAc,+BAiEhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stylo.d.ts","sourceRoot":"","sources":["../src/Stylo.tsx"],"names":[],"mappings":"AAUA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAoB,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAExE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,oGAiLhB,CAAA"}
1
+ {"version":3,"file":"Stylo.d.ts","sourceRoot":"","sources":["../src/Stylo.tsx"],"names":[],"mappings":"AAUA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAoB,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAExE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,oGAqLhB,CAAA"}
@@ -1,3 +1,4 @@
1
+ import type { ReactNode } from "react";
1
2
  import type { EditorView } from "@codemirror/view";
2
3
  import type { CodeLanguages, ResolveErrorInfo, WikiLinkSource } from "../types";
3
4
  export interface SourceViewProps {
@@ -15,7 +16,11 @@ export interface SourceViewProps {
15
16
  onSave?: (value: string) => void;
16
17
  /** Called with the `EditorView` once created, and with `null` on teardown. */
17
18
  onViewChange?: (view: EditorView | null) => void;
19
+ /** Host content docked after the search panel, before the document. Read once. */
20
+ canvasHeader?: (ctx: {
21
+ view: EditorView | null;
22
+ }) => ReactNode;
18
23
  }
19
24
  /** Raw CodeMirror 6 Markdown surface bound to the canonical string. */
20
- export declare function SourceView({ value, onChange, readOnly, placeholder, codeLanguages, wikiLinkSource, onResolveError, onSave, onViewChange, }: SourceViewProps): import("react").JSX.Element;
25
+ export declare function SourceView({ value, onChange, readOnly, placeholder, codeLanguages, wikiLinkSource, onResolveError, onSave, onViewChange, canvasHeader, }: SourceViewProps): import("react").JSX.Element;
21
26
  //# sourceMappingURL=SourceView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SourceView.d.ts","sourceRoot":"","sources":["../../src/editor/SourceView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAG/E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,8CAA8C;IAC9C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;CACjD;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,cAAc,EACd,MAAM,EACN,YAAY,GACb,EAAE,eAAe,+BAajB"}
1
+ {"version":3,"file":"SourceView.d.ts","sourceRoot":"","sources":["../../src/editor/SourceView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAO/E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,8CAA8C;IAC9C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,kFAAkF;IAClF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;CAC/D;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,cAAc,EACd,MAAM,EACN,YAAY,EACZ,YAAY,GACb,EAAE,eAAe,+BAwCjB"}
@@ -0,0 +1,27 @@
1
+ import type { Panel } from "@codemirror/view";
2
+ /** Class the panel root carries; CM6 adds its own `cm-panel` alongside it. */
3
+ export declare const PANEL_CLASS = "stylo-canvas-header";
4
+ /**
5
+ * Bridges `StyloProps.canvasHeader` (imperative CodeMirror DOM) to host React.
6
+ * `panel` is handed to `showPanel.of(...)` as the panel constructor CM6 calls
7
+ * once per view; the view's surface component subscribes and portals the
8
+ * host's render output into the resulting node. One instance per surface,
9
+ * created where the extension is built — never module-global, so two editors
10
+ * on a page do not share a slot.
11
+ *
12
+ * Docked as a second top panel, ordered after the search panel wherever it's
13
+ * installed (see `SourceView.tsx` / `InPlaceView.tsx`) so it sits between
14
+ * find/replace and the document body — never a sibling of anything a host
15
+ * renders via `toolbar.render`, which sits *before* the whole canvas.
16
+ */
17
+ export declare class CanvasHeaderHost {
18
+ private dom;
19
+ private listeners;
20
+ panel: () => Panel;
21
+ /** `useSyncExternalStore` subscribe. */
22
+ subscribe: (listener: () => void) => (() => void);
23
+ /** `useSyncExternalStore` snapshot — stable between `panel()` / `destroy()` calls. */
24
+ getSnapshot: () => HTMLElement | null;
25
+ private notify;
26
+ }
27
+ //# sourceMappingURL=canvas-header-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-header-panel.d.ts","sourceRoot":"","sources":["../../src/editor/canvas-header-panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAE7C,8EAA8E;AAC9E,eAAO,MAAM,WAAW,wBAAwB,CAAA;AAEhD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,SAAS,CAAwB;IAEzC,KAAK,QAAO,KAAK,CAahB;IAED,wCAAwC;IACxC,SAAS,aAAc,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAG/C;IAED,sFAAsF;IACtF,WAAW,QAAO,WAAW,GAAG,IAAI,CAAY;IAEhD,OAAO,CAAC,MAAM;CAGf"}
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/editor/extensions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,SAAS,EAAQ,MAAM,mBAAmB,CAAA;AAIrE,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAM/E;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,aAAa,CAAC,EAAE,aAAa,EAC7B,cAAc,CAAC,EAAE,cAAc,EAC/B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAChE,SAAS,CAqBX;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B,GAAG,SAAS,CAOZ"}
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/editor/extensions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,SAAS,EAAQ,MAAM,mBAAmB,CAAA;AAIrE,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAO/E;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,aAAa,CAAC,EAAE,aAAa,EAC7B,cAAc,CAAC,EAAE,cAAc,EAC/B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAChE,SAAS,CAuBX;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B,GAAG,SAAS,CAOZ"}
@@ -0,0 +1,27 @@
1
+ import type { EditorView } from "@codemirror/view";
2
+ /** Class stylo tags its panel root with; CM6 adds its own `cm-panel` alongside it. */
3
+ export declare const PANEL_CLASS = "stylo-search-panel";
4
+ /** The panel's elements, in the order they're appended — which is also Tab order. */
5
+ export interface SearchDom {
6
+ root: HTMLDivElement;
7
+ find: HTMLInputElement;
8
+ next: HTMLButtonElement;
9
+ prev: HTMLButtonElement;
10
+ all: HTMLButtonElement;
11
+ replace: HTMLInputElement;
12
+ replaceBtn: HTMLButtonElement;
13
+ replaceAllBtn: HTMLButtonElement;
14
+ caseSensitive: HTMLInputElement;
15
+ regexp: HTMLInputElement;
16
+ wholeWord: HTMLInputElement;
17
+ close: HTMLButtonElement;
18
+ }
19
+ /**
20
+ * Builds the find/replace row in reading order — find, next/prev/all, replace,
21
+ * replace/replace-all, the three checkboxes, close — so Tab order matches the visual
22
+ * layout. `@codemirror/search`'s own panel is fixed markup restyled from outside, which
23
+ * only ever let stylo reorder the *paint*, not the DOM; owning construction removes that
24
+ * ceiling entirely.
25
+ */
26
+ export declare function buildSearchDom(view: EditorView): SearchDom;
27
+ //# sourceMappingURL=search-panel-dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-panel-dom.d.ts","sourceRoot":"","sources":["../../src/editor/search-panel-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,sFAAsF;AACtF,eAAO,MAAM,WAAW,uBAAuB,CAAA;AAE/C,qFAAqF;AACrF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,EAAE,gBAAgB,CAAA;IACtB,IAAI,EAAE,iBAAiB,CAAA;IACvB,IAAI,EAAE,iBAAiB,CAAA;IACvB,GAAG,EAAE,iBAAiB,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,iBAAiB,CAAA;IAC7B,aAAa,EAAE,iBAAiB,CAAA;IAChC,aAAa,EAAE,gBAAgB,CAAA;IAC/B,MAAM,EAAE,gBAAgB,CAAA;IACxB,SAAS,EAAE,gBAAgB,CAAA;IAC3B,KAAK,EAAE,iBAAiB,CAAA;CACzB;AA0CD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAgD1D"}
@@ -0,0 +1,13 @@
1
+ import { type EditorView, type Panel } from "@codemirror/view";
2
+ /** Toolbar "search" command: opens the panel, or animates it closed if it's already open. */
3
+ export declare function toggleSearchPanel(view: EditorView): boolean;
4
+ /**
5
+ * Stylo's replacement for `@codemirror/search`'s default panel, built through the
6
+ * `search()` extension's `createPanel` hook instead of restyling the library's fixed
7
+ * markup with CSS `order` (the previous approach — see the 0.10.0 journal entry). Owning
8
+ * the DOM means the row is already built in reading order, so Tab now follows the same
9
+ * left-to-right layout that's on screen, and the close animation is a plain listener on
10
+ * our own button instead of a capture-phase interception of the library's.
11
+ */
12
+ export declare function createStyloSearchPanel(view: EditorView): Panel;
13
+ //# sourceMappingURL=search-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-panel.d.ts","sourceRoot":"","sources":["../../src/editor/search-panel.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,KAAK,EAAoB,MAAM,kBAAkB,CAAA;AAOhF,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAE3D;AAeD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,KAAK,CAuE9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/editor/theme.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,eAAO,MAAM,UAAU,uCAuFrB,CAAA"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/editor/theme.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,eAAO,MAAM,UAAU,uCAoIrB,CAAA"}
@@ -64,16 +64,23 @@ function c({ reference: r, source: i, onError: a, inline: c }) {
64
64
  a
65
65
  ]);
66
66
  let d = `![[${r}]]`;
67
- return l.status === "loading" ? /* @__PURE__ */ n("span", {
67
+ if (l.status === "loading") return /* @__PURE__ */ n("span", {
68
68
  "aria-busy": "true",
69
69
  children: d
70
- }) : l.status === "ready" && l.node != null ? c ? /* @__PURE__ */ n("span", {
71
- className: "stylo-embed-content stylo-embed-inline",
72
- children: l.node
73
- }) : /* @__PURE__ */ n("div", {
74
- className: "stylo-embed-content",
75
- children: l.node
76
- }) : /* @__PURE__ */ n("span", { children: d });
70
+ });
71
+ if (l.status === "ready" && l.node != null) {
72
+ let e = (e) => e.stopPropagation();
73
+ return c ? /* @__PURE__ */ n("span", {
74
+ className: "stylo-embed-content stylo-embed-inline",
75
+ onMouseDown: e,
76
+ children: l.node
77
+ }) : /* @__PURE__ */ n("div", {
78
+ className: "stylo-embed-content",
79
+ onMouseDown: e,
80
+ children: l.node
81
+ });
82
+ }
83
+ return /* @__PURE__ */ n("span", { children: d });
77
84
  }
78
85
  //#endregion
79
86
  //#region src/callout.ts
@@ -121,4 +128,4 @@ function m(e) {
121
128
  //#endregion
122
129
  export { f as a, l as i, m as n, c as o, u as r, p as t };
123
130
 
124
- //# sourceMappingURL=embed-B2Dfkpd_.js.map
131
+ //# sourceMappingURL=embed-Dsu6b-MV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed-Dsu6b-MV.js","names":[],"sources":["../src/render/embed-cache.ts","../src/render/Embed.tsx","../src/callout.ts","../src/embed.ts"],"sourcesContent":["import type { ReactNode } from \"react\"\nimport type { EmbedSource } from \"../types\"\n\n/**\n * A process-wide resolution cache for `![[ref]]` embeds, shared by `preview` and\n * the in-place canvas (both render through `Embed`). Without it, an embed\n * scrolled out of the canvas viewport and back — or a `preview` re-render that\n * remounts the subtree — re-invokes `embedSource`, which for a network-backed\n * source is a refetch each time.\n *\n * Keyed first by the `embedSource` identity (a `WeakMap`, so two editors with\n * different resolvers never collide and a changed `embedSource` drops its cache\n * for free — the type doc already asks consumers to keep the reference stable),\n * then by the raw `ref` string.\n *\n * In-flight promises are shared, so two embeds of the same `ref` mounting\n * together call `embedSource` once. A rejection is **not** cached — the next\n * mount retries. `null` (the host chose to keep the reference literal) is a\n * valid cached value; `settled` tells it apart from an absent entry.\n */\n\ninterface Entry {\n promise: Promise<ReactNode>\n node?: ReactNode\n settled: boolean\n}\n\n/** Distinct `ref`s kept per resolver. Eviction only costs a re-resolve. */\nconst MAX_ENTRIES = 64\n\nconst caches = new WeakMap<EmbedSource, Map<string, Entry>>()\n\nfunction bucket(source: EmbedSource): Map<string, Entry> {\n let m = caches.get(source)\n if (!m) {\n m = new Map()\n caches.set(source, m)\n }\n return m\n}\n\n/** A settled result for `ref`, or `undefined` while it is unresolved or absent. */\nexport function peekEmbed(source: EmbedSource, ref: string): { node: ReactNode } | undefined {\n const entry = bucket(source).get(ref)\n return entry?.settled ? { node: entry.node } : undefined\n}\n\n/** Resolve `ref` through the cache — reusing an in-flight or settled entry, or\n * calling `source` on a miss. */\nexport function resolveEmbed(source: EmbedSource, ref: string): Promise<ReactNode> {\n const m = bucket(source)\n const existing = m.get(ref)\n if (existing) return existing.promise\n\n const promise = Promise.resolve(source(ref)).then(\n (node) => {\n const entry = m.get(ref)\n if (entry) {\n entry.node = node\n entry.settled = true\n }\n return node\n },\n (err) => {\n m.delete(ref) // never cache a failure\n throw err\n },\n )\n m.set(ref, { promise, settled: false })\n\n // Insertion-order cap: drop the oldest distinct ref once over the limit.\n if (m.size > MAX_ENTRIES) {\n const oldest = m.keys().next().value\n if (oldest !== undefined && oldest !== ref) m.delete(oldest)\n }\n return promise\n}\n","import { type ReactNode, useEffect, useState } from \"react\"\nimport type { EmbedSource, ResolveErrorInfo } from \"../types\"\nimport { peekEmbed, resolveEmbed } from \"./embed-cache\"\n\ninterface EmbedProps {\n /** The raw `![[ref]]` reference, trimmed. */\n reference: string\n source: EmbedSource\n /** Notified if `source` rejects; the literal fallback still renders. */\n onError?: (error: unknown, info: ResolveErrorInfo) => void\n /**\n * Render as phrasing content in a `<span>` (a `![[…]]` mid-sentence) rather\n * than the default block `<div>`. The host node should be inline in this mode.\n */\n inline?: boolean\n}\n\ntype State = { status: \"loading\" | \"error\" } | { status: \"ready\"; node: ReactNode }\n\n/**\n * Renders one `![[ref]]` embed. Resolves the reference through `embedSource` —\n * via a shared cache (`embed-cache.ts`), so an embed re-mounted by a scroll or a\n * `preview` re-render is not re-fetched — and drops the result into\n * `<div class=\"stylo-embed-content\">`, or a `<span>` when `inline`. While it\n * resolves — and if it rejects, or resolves to `null` — the literal `![[ref]]`\n * text stands in, so a reference is never silently lost.\n */\nexport function Embed({ reference, source, onError, inline }: EmbedProps) {\n const [state, setState] = useState<State>(() => {\n const hit = peekEmbed(source, reference)\n return hit ? { status: \"ready\", node: hit.node } : { status: \"loading\" }\n })\n\n useEffect(() => {\n let live = true\n const hit = peekEmbed(source, reference)\n if (hit) {\n setState({ status: \"ready\", node: hit.node })\n return\n }\n setState({ status: \"loading\" })\n resolveEmbed(source, reference).then(\n (node) => live && setState({ status: \"ready\", node }),\n (error) => {\n onError?.(error, { source: \"embedSource\", input: reference })\n if (live) setState({ status: \"error\" })\n },\n )\n return () => {\n live = false\n }\n }, [reference, source, onError])\n\n const literal = `![[${reference}]]`\n if (state.status === \"loading\") return <span aria-busy=\"true\">{literal}</span>\n if (state.status === \"ready\" && state.node != null) {\n // Keep the mousedown away from the in-place canvas's own delegated\n // handler — same reason and technique as the editable table widget\n // (`table-widget.ts`): CodeMirror's built-in click-to-place-caret runs\n // for *any* mousedown that reaches `contentDOM`'s listener regardless of\n // what a custom `domEventHandlers` hook decided, so returning `false`\n // from one is not enough to keep an atomic widget's interactive content\n // clickable — the event has to be stopped before it gets there. Not\n // `preventDefault` — the button (or whatever the host renders) still\n // gets the click natively. Inert outside the canvas (`preview` / `split`\n // have no such listener to stop).\n const stop = (e: { stopPropagation: () => void }) => e.stopPropagation()\n return inline ? (\n <span className=\"stylo-embed-content stylo-embed-inline\" onMouseDown={stop}>\n {state.node}\n </span>\n ) : (\n <div className=\"stylo-embed-content\" onMouseDown={stop}>\n {state.node}\n </div>\n )\n }\n return <span>{literal}</span>\n}\n","/**\n * Obsidian-style callouts: a blockquote whose first line is `> [!type]`,\n * optionally `> [!type] Title` or `> [!type]- Title` (the `-` / `+` fold marker\n * is parsed but Stylo always renders expanded).\n *\n * Single source of truth for the in-place decoration scanner (`nodes.ts`) and\n * the preview remark plugin (`remark-callout.ts`), so the two never drift. The\n * many Obsidian type names collapse to five colour buckets; the raw type is kept\n * on a `data-callout` attribute for a `::before` label and consumer styling.\n */\n\n/** `[!type]` with an optional fold marker, anchored after any `>` prefix. */\nexport const CALLOUT_TOKEN = /^\\[!(\\w+)\\][+-]?[ \\t]*/\n\n/** A blockquote head line in the in-place canvas: `> ` prefix, then the token. */\nexport const CALLOUT_HEAD_LINE = /^([\\s>]*)(\\[!(\\w+)\\][+-]?[ \\t]*)/\n\nexport type CalloutBucket = \"note\" | \"tip\" | \"warn\" | \"danger\" | \"example\"\n\nconst BUCKET: Record<string, CalloutBucket> = {\n note: \"note\",\n info: \"note\",\n abstract: \"note\",\n summary: \"note\",\n tldr: \"note\",\n tip: \"tip\",\n hint: \"tip\",\n important: \"tip\",\n success: \"tip\",\n check: \"tip\",\n done: \"tip\",\n question: \"warn\",\n help: \"warn\",\n faq: \"warn\",\n warning: \"warn\",\n caution: \"warn\",\n attention: \"warn\",\n todo: \"warn\",\n failure: \"danger\",\n fail: \"danger\",\n missing: \"danger\",\n danger: \"danger\",\n error: \"danger\",\n bug: \"danger\",\n example: \"example\",\n quote: \"example\",\n cite: \"example\",\n}\n\n/** The colour bucket for a callout type; unknown types read as `note`. */\nexport function calloutBucket(type: string): CalloutBucket {\n return BUCKET[type.toLowerCase()] ?? \"note\"\n}\n","/**\n * `![[ref]]` transclusion. Capture group 1 is the raw reference — everything\n * between `![[` and `]]`, passed to the host verbatim (any `#heading`,\n * `#^blockid`, or `|size` suffix included). The `g` flag is set for\n * `matchAll` / `exec` loops.\n *\n * Deliberately not built on `WIKILINK_PATTERN`: in an embed the `|` is a size\n * hint (`![[image.png|300]]`), not a display label, so Stylo does not split on\n * it — the whole reference goes to `embedSource`.\n */\nexport const EMBED_PATTERN = /!\\[\\[([^\\]\\n]+?)\\]\\]/g\n\n/** True when `text` (trimmed) is exactly one `![[ref]]` and nothing else. */\nexport function isLoneEmbed(text: string): boolean {\n const trimmed = text.trim()\n EMBED_PATTERN.lastIndex = 0\n const m = EMBED_PATTERN.exec(trimmed)\n return m != null && m[0].length === trimmed.length\n}\n"],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ var e = {
2
+ root: "_root_1lohh_1",
3
+ source: "_source_1lohh_42",
4
+ inplace: "_inplace_1lohh_57",
5
+ toolbar: "_toolbar_1lohh_63",
6
+ toolbarGroup: "_toolbarGroup_1lohh_75",
7
+ toolbarButton: "_toolbarButton_1lohh_81",
8
+ toolbarSep: "_toolbarSep_1lohh_140",
9
+ toolbarSticky: "_toolbarSticky_1lohh_150",
10
+ toolbarStickyBottom: "_toolbarStickyBottom_1lohh_150",
11
+ toolbarStickyTop: "_toolbarStickyTop_1lohh_150",
12
+ toolbarStickyHidden: "_toolbarStickyHidden_1lohh_219",
13
+ stickyToolbarRootBottom: "_stickyToolbarRootBottom_1lohh_230",
14
+ stickyToolbarRootTop: "_stickyToolbarRootTop_1lohh_235",
15
+ split: "_split_1lohh_249",
16
+ splitPane: "_splitPane_1lohh_256",
17
+ preview: "_preview_1lohh_276"
18
+ }, t = /\[\[([^\]|\n]+?)(?:\|([^\]\n]+?))?\]\]/g;
19
+ //#endregion
20
+ //#region src/frontmatter.ts
21
+ function n(e) {
22
+ if (e.lines < 2 || e.line(1).text.trim() !== "---") return null;
23
+ for (let t = 2; t <= e.lines; t++) if (e.line(t).text.trim() === "---") return {
24
+ from: 0,
25
+ to: e.line(t).to
26
+ };
27
+ return null;
28
+ }
29
+ var r = /^---\r?\n(?:([\s\S]*?)\r?\n)?---[ \t]*(?:\r?\n|$)/;
30
+ function i(e) {
31
+ let t = r.exec(e);
32
+ return t ? {
33
+ frontmatter: t[1] ?? "",
34
+ body: e.slice(t[0].length)
35
+ } : null;
36
+ }
37
+ //#endregion
38
+ export { e as i, i as n, t as r, n as t };
39
+
40
+ //# sourceMappingURL=frontmatter-DTCC0gaa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-DTCC0gaa.js","names":[],"sources":["../src/styles/stylo.module.css","../src/wikilink.ts","../src/frontmatter.ts"],"sourcesContent":[".root {\n display: flex;\n flex-direction: column;\n min-height: 0;\n color: var(--stylo-text);\n background: var(--stylo-bg);\n border: 1px solid var(--stylo-border);\n border-radius: var(--stylo-radius);\n overflow: hidden;\n}\n\n/* The editing surface's own scroll container (source, in-place, and the source\n pane of split all resolve to `.cm-scroller`). Thin, token-tinted bars so the\n editor doesn't fall back to a heavier native scrollbar than the app chrome\n around it. A host's own `.cm-scroller` rules load after and win. */\n.root :global(.cm-scroller) {\n scrollbar-width: thin;\n scrollbar-color: color-mix(in srgb, var(--stylo-border) 90%, transparent) transparent;\n}\n\n.root :global(.cm-scroller)::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n\n.root :global(.cm-scroller)::-webkit-scrollbar-thumb {\n border: 3px solid transparent;\n border-radius: 6px;\n background: color-mix(in srgb, var(--stylo-border) 90%, transparent);\n background-clip: padding-box;\n}\n\n.root :global(.cm-scroller)::-webkit-scrollbar-thumb:hover {\n background: color-mix(in srgb, var(--stylo-text-muted) 55%, transparent);\n background-clip: padding-box;\n}\n\n.root :global(.cm-scroller)::-webkit-scrollbar-corner {\n background: transparent;\n}\n\n.source {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n\n.source :global(.cm-editor) {\n height: 100%;\n}\n\n.source :global(.cm-editor.cm-focused) {\n outline: 2px solid var(--stylo-ring);\n outline-offset: -2px;\n}\n\n.inplace {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n\n.toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 2px;\n padding: 4px 6px;\n background: var(--stylo-bg);\n border-bottom: 1px solid var(--stylo-border);\n}\n\n/* One flex child per `\"|\"`-delimited run of items, so `.toolbar`'s wrap\n breaks between groups instead of inside one. */\n.toolbarGroup {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.toolbarButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n min-width: 28px;\n height: 28px;\n padding: 0 5px;\n border: 0;\n border-radius: calc(var(--stylo-radius) - 3px);\n background: none;\n color: var(--stylo-text-muted);\n font: inherit;\n font-size: 0.75rem;\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n}\n\n.toolbarButton:hover:not(:disabled) {\n background: color-mix(in srgb, var(--stylo-border) 45%, transparent);\n color: var(--stylo-text);\n}\n\n.toolbarButton[data-active] {\n background: color-mix(in srgb, var(--stylo-accent) 12%, transparent);\n color: var(--stylo-text);\n}\n\n.toolbarButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.toolbarButton:focus-visible {\n outline: 2px solid var(--stylo-ring);\n outline-offset: -2px;\n}\n\n.toolbarButton svg {\n display: block;\n width: 16px;\n height: 16px;\n}\n\n/* Text glyphs that stand in for an icon (e.g. `fm`) — monospace to read as syntax. */\n.toolbarButton code {\n font-family: var(\n --stylo-font-family-mono,\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Consolas,\n monospace\n );\n font-size: 0.8125rem;\n font-weight: 500;\n}\n\n.toolbarSep {\n align-self: stretch;\n width: 1px;\n margin: 4px 3px;\n background: var(--stylo-border);\n}\n\n/* `toolbar={{ sticky: \"top\" | \"bottom\" | true }}` — pins the bar to an edge\n instead of wherever `<Stylo>` sits on the page. One row, no wrapping: it\n scrolls horizontally instead, and its buttons grow to a comfortable touch\n size. Shared by both edges; `.toolbarStickyTop` / `.toolbarStickyBottom`\n below pick the positioning mechanism and the edge itself. */\n.toolbarSticky {\n z-index: 50;\n flex-wrap: nowrap;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n transition: opacity 0.15s ease;\n /* The base `.toolbar` deliberately leaves font-family to inherit from\n wherever the host mounts `<Stylo>`. Both sticky edges are\n `position: fixed` against the window, so neither can safely lean on\n that — the prose-font token (or its default stack) instead of the\n browser's serif default. */\n font-family: var(\n --stylo-font-family,\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n Helvetica,\n Arial,\n sans-serif\n );\n}\n\n.toolbarSticky::-webkit-scrollbar {\n display: none;\n}\n\n.toolbarSticky .toolbarButton {\n min-width: 40px;\n height: 40px;\n flex: 0 0 auto;\n}\n\n/* `\"bottom\"` (or `true`) — has to be `position: fixed`: nothing about a\n mobile keyboard opening is a \"scroll\", so `position: sticky` has nothing to\n react to. Toolbar.tsx nudges it up from `bottom: 0` with\n `transform: translateY()`, tracking `useKeyboardInset`. */\n.toolbarStickyBottom {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n border-bottom: none;\n border-top: 1px solid var(--stylo-border);\n box-shadow: 0 -2px 8px color-mix(in srgb, var(--stylo-text) 10%, transparent);\n}\n\n/* `\"top\"` — `position: fixed`, always pinned rather than waiting for a scroll\n threshold like `\"bottom\"`. Nothing ever eats into the top of the screen, so\n there's no keyboard to react to and no accessory bar to collide with — the\n two problems `\"bottom\"` has. `Toolbar.tsx`'s `useFloatingWatchdog` (a\n `requestAnimationFrame` loop, not CSS) is what actually keeps it visible on\n iOS Safari: earlier rounds tried a static `translateZ(0)`, then real\n `position: sticky`, and the disappear-on-scroll bug outlived both — a value\n that's set once and never re-touched gives the browser's compositor nothing\n to recompute if it drifts, so the watchdog re-asserts a `transform` every\n frame instead of trusting a one-time fix to hold. */\n.toolbarStickyTop {\n position: fixed;\n left: 0;\n right: 0;\n top: 0;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--stylo-text) 10%, transparent);\n}\n\n/* `stickyVisibility: \"dynamic\"` — faded out while nothing is focused. */\n.toolbarStickyHidden {\n opacity: 0;\n pointer-events: none;\n}\n\n/* `\"bottom\"` is `position: fixed`, out of flow entirely — reserve its resting\n height so it doesn't sit over the document's last line. Static, not\n keyboard-aware: while the keyboard is open the bar rides up to meet it (see\n `useKeyboardInset`), but the browser's own scroll-into-view around the\n caret is what keeps typing visible above both — this padding only covers\n the keyboard-closed resting state. */\n.stickyToolbarRootBottom .source,\n.stickyToolbarRootBottom .inplace {\n padding-bottom: 52px;\n}\n\n.stickyToolbarRootTop .source,\n.stickyToolbarRootTop .inplace {\n padding-top: 52px;\n}\n\n.inplace :global(.cm-editor) {\n height: 100%;\n}\n\n.inplace :global(.cm-editor.cm-focused) {\n outline: 2px solid var(--stylo-ring);\n outline-offset: -2px;\n}\n\n.split {\n display: grid;\n grid-template-columns: 1fr 1fr;\n flex: 1;\n min-height: 0;\n}\n\n.splitPane {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n box-sizing: border-box;\n}\n\n.splitPane + .splitPane {\n border-left: 1px solid var(--stylo-border);\n}\n\n.splitPane > .source {\n flex: 1;\n min-height: 0;\n}\n\n/* Vertical rhythm follows Tailwind's `prose` (@tailwindcss/typography) as a\n visual reference — the em-based scale only, no plugin bundled. Consumer CSS\n wins: `.stylo p`, `.stylo h2`, … load after and match our specificity. */\n.preview {\n padding: 0.75rem 1rem;\n font-size: 0.9375rem;\n line-height: 1.75;\n overflow-wrap: break-word;\n}\n\n.preview > :first-child {\n margin-top: 0;\n}\n\n.preview > :last-child {\n margin-bottom: 0;\n}\n\n.preview :is(h1, h2, h3, h4, h5, h6) {\n font-weight: 600;\n}\n\n.preview h1 {\n margin: 0 0 0.8888889em;\n font-size: 2.25em;\n line-height: 1.1111111;\n}\n\n.preview h2 {\n margin: 2em 0 1em;\n font-size: 1.5em;\n line-height: 1.3333333;\n}\n\n.preview h3 {\n margin: 1.6em 0 0.6em;\n font-size: 1.25em;\n line-height: 1.6;\n}\n\n.preview :is(h4, h5, h6) {\n margin: 1.5em 0 0.5em;\n line-height: 1.5;\n}\n\n.preview p {\n margin: 1.25em 0;\n}\n\n.preview :is(ul, ol) {\n margin: 1.25em 0;\n padding-left: 1.625em;\n}\n\n.preview li {\n margin: 0.5em 0;\n}\n\n.preview li > :is(ul, ol) {\n margin: 0.75em 0;\n}\n\n.preview a {\n color: var(--stylo-link);\n text-decoration: none;\n}\n\n.preview code {\n font-family: var(\n --stylo-font-family-mono,\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Consolas,\n monospace\n );\n font-size: 0.9em;\n padding: 0.1em 0.35em;\n border-radius: calc(var(--stylo-radius) - 3px);\n background: color-mix(in srgb, var(--stylo-border) 45%, transparent);\n}\n\n.preview pre {\n margin: 1.7142857em 0;\n padding: 0.75rem 0.9rem;\n border-radius: var(--stylo-radius);\n background: color-mix(in srgb, var(--stylo-border) 35%, transparent);\n overflow-x: auto;\n}\n\n.preview pre code {\n padding: 0;\n font-size: 0.85em;\n background: none;\n}\n\n/* frontmatter=\"code\": the raw `---` block, recessed. `.stylo-frontmatter` is a\n plain (unscoped) class so a consumer's own CSS overrides it at equal\n specificity — restyle the block, or rename / remove the label:\n .stylo-frontmatter::before { content: \"Meta\" }\n .stylo-frontmatter::before { content: none } */\n:global(.stylo-frontmatter) {\n margin: 0 0 1.2em;\n padding: 0.7rem 0.9rem;\n border-left: 3px solid var(--stylo-border);\n border-radius: calc(var(--stylo-radius) - 3px);\n background: color-mix(in srgb, var(--stylo-border) 22%, transparent);\n color: var(--stylo-text-muted);\n font-family: var(\n --stylo-font-family-mono,\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Consolas,\n monospace\n );\n font-size: 0.8125rem;\n line-height: 1.5;\n white-space: pre-wrap;\n overflow-x: auto;\n}\n\n:global(.stylo-frontmatter)::before {\n content: \"Frontmatter\";\n display: block;\n margin-bottom: 0.5em;\n font-family: var(\n --stylo-font-family,\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n Helvetica,\n Arial,\n sans-serif\n );\n font-size: 0.7rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.preview blockquote {\n margin: 1.6em 0;\n padding-left: 1em;\n border-left: 0.25rem solid var(--stylo-border);\n color: var(--stylo-text-muted);\n}\n\n/* Obsidian callouts (`> [!note]`) — mirrors the in-place canvas. `remark-callout`\n adds `stylo-callout stylo-callout-<bucket>` + `data-callout`. Override\n `--stylo-callout-<bucket>` (or `--stylo-callout-accent` per type) to reskin. */\n.preview :global(.stylo-callout) {\n margin: 1.6em 0;\n padding: 0.6em 1em;\n border-left: 0.25rem solid var(--stylo-callout-accent, var(--stylo-border));\n border-radius: var(--stylo-radius);\n background: color-mix(in srgb, var(--stylo-callout-accent, var(--stylo-border)) 10%, transparent);\n color: var(--stylo-text);\n}\n.preview :global(.stylo-callout)::before {\n content: attr(data-callout);\n display: block;\n margin-bottom: 0.2em;\n font-size: 0.8em;\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--stylo-callout-accent, var(--stylo-text-muted));\n}\n.preview :global(.stylo-callout-note) {\n --stylo-callout-accent: var(--stylo-callout-note, #3b82f6);\n}\n.preview :global(.stylo-callout-tip) {\n --stylo-callout-accent: var(--stylo-callout-tip, #22c55e);\n}\n.preview :global(.stylo-callout-warn) {\n --stylo-callout-accent: var(--stylo-callout-warn, #f59e0b);\n}\n.preview :global(.stylo-callout-danger) {\n --stylo-callout-accent: var(--stylo-callout-danger, #ef4444);\n}\n.preview :global(.stylo-callout-example) {\n --stylo-callout-accent: var(--stylo-callout-example, #a855f7);\n}\n\n/* `![[embed]]` transclusion. `remark-embed` swaps a lone-`![[ref]]` paragraph\n for `<div class=\"stylo-embed\">`, and `Embed` nests the host-rendered content\n in `.stylo-embed-content`. Both classes are stable override points; set\n `--stylo-embed-accent` to reskin the rail, or zero the padding / border to\n opt out of the frame entirely. */\n.preview :global(.stylo-embed) {\n margin: 1.6em 0;\n padding-left: 1em;\n border-left: 0.25rem solid var(--stylo-embed-accent, var(--stylo-border));\n}\n.preview :global(.stylo-embed-content) > :first-child {\n margin-top: 0;\n}\n.preview :global(.stylo-embed-content) > :last-child {\n margin-bottom: 0;\n}\n\n.preview table {\n display: block;\n margin: 2em 0;\n border-collapse: collapse;\n overflow-x: auto;\n}\n\n.preview :is(th, td) {\n padding: 0.35em 0.6em;\n border: 1px solid var(--stylo-table-border);\n text-align: left;\n}\n\n.preview thead th {\n background: var(--stylo-table-header-bg);\n font-weight: 600;\n}\n\n/* Opt-in zebra striping — no-op until the host sets `--stylo-table-stripe-bg`. */\n.preview tbody tr:nth-child(even) td {\n background: var(--stylo-table-stripe-bg);\n}\n\n/* prose sets `hr { margin: 3em 0 }`, which reads as a page break, not a rule.\n GitHub / VS Code render it tight; `1em` each side matches that. */\n.preview hr {\n margin: 1em 0;\n border: none;\n border-top: 1px solid var(--stylo-border);\n}\n\n.preview :global(.katex-display) {\n padding: 0.25em 0;\n overflow-x: auto;\n overflow-y: hidden;\n}\n","/**\n * `[[target]]` or `[[target|label]]`. Capture group 1 is the target, group 2 the\n * optional display label. The `g` flag is set for `matchAll` / `exec` loops;\n * callers that keep the regex across calls must reset `lastIndex` (or use\n * `matchAll`, which is stateless).\n *\n * Single source of truth for both the render-side plugin (`remark-wikilink`) and\n * the in-place decoration scanner, so the two never drift.\n */\nexport const WIKILINK_PATTERN = /\\[\\[([^\\]|\\n]+?)(?:\\|([^\\]\\n]+?))?\\]\\]/g\n","import type { Text } from \"@codemirror/state\"\n\n/**\n * The leading `---` … `---` YAML block, if present. The CodeMirror Markdown\n * grammar has no frontmatter node — it parses the fences as two thematic breaks\n * — so the region is located by hand. Shared by the in-place decoration layer\n * and the toolbar's frontmatter command.\n */\nexport function frontmatterRange(doc: Text): { from: number; to: number } | null {\n if (doc.lines < 2 || doc.line(1).text.trim() !== \"---\") return null\n for (let n = 2; n <= doc.lines; n++) {\n if (doc.line(n).text.trim() === \"---\") return { from: 0, to: doc.line(n).to }\n }\n return null\n}\n\nconst FRONTMATTER_BLOCK = /^---\\r?\\n(?:([\\s\\S]*?)\\r?\\n)?---[ \\t]*(?:\\r?\\n|$)/\n\n/**\n * Split a leading `---` … `---` block off a Markdown string. `frontmatter` is\n * the inner text (`\"\"` for an empty block); `body` is everything after the\n * closing fence. Used by `preview` to render the block instead of dropping it.\n */\nexport function splitFrontmatter(md: string): { frontmatter: string; body: string } | null {\n const m = FRONTMATTER_BLOCK.exec(md)\n return m ? { frontmatter: m[1] ?? \"\", body: md.slice(m[0].length) } : null\n}\n"],"mappings":";;;;;;;;;;;;;;;;;GCSa,IAAmB;;;ACDhC,SAAgB,EAAiB,GAAgD;CAC/E,IAAI,EAAI,QAAQ,KAAK,EAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,OAAO,OAAO;CAC/D,KAAK,IAAI,IAAI,GAAG,KAAK,EAAI,OAAO,KAC9B,IAAI,EAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,OAAO,OAAO;EAAE,MAAM;EAAG,IAAI,EAAI,KAAK,CAAC,CAAC,CAAC;CAAG;CAE9E,OAAO;AACT;AAEA,IAAM,IAAoB;AAO1B,SAAgB,EAAiB,GAA0D;CACzF,IAAM,IAAI,EAAkB,KAAK,CAAE;CACnC,OAAO,IAAI;EAAE,aAAa,EAAE,MAAM;EAAI,MAAM,EAAG,MAAM,EAAE,EAAE,CAAC,MAAM;CAAE,IAAI;AACxE"}
@@ -1,3 +1,4 @@
1
+ import type { ReactNode } from "react";
1
2
  import type { EditorView } from "@codemirror/view";
2
3
  import type { CodeLanguages, EmbedSource, InPlaceConfig, ResolveErrorInfo, WikiLinkSource } from "../types";
3
4
  export interface InPlaceViewProps {
@@ -22,6 +23,10 @@ export interface InPlaceViewProps {
22
23
  onSave?: (value: string) => void;
23
24
  /** Called with the `EditorView` once created, and with `null` on teardown. */
24
25
  onViewChange?: (view: EditorView | null) => void;
26
+ /** Host content docked after the search panel, before the document. Read once. */
27
+ canvasHeader?: (ctx: {
28
+ view: EditorView | null;
29
+ }) => ReactNode;
25
30
  }
26
31
  /**
27
32
  * The in-place canvas: a CodeMirror surface that renders Markdown structure live
@@ -37,5 +42,5 @@ export interface InPlaceViewProps {
37
42
  * `EmbedRegistry` and portals a host `<Embed>` into every live slot, so one
38
43
  * React tree — reusing `Embed` verbatim — serves the canvas and `preview` alike.
39
44
  */
40
- export declare function InPlaceView({ value, onChange, readOnly, placeholder, onWikiLinkClick, onLinkClick, inPlace, codeLanguages, wikiLinkSource, embedSource, onResolveError, onSave, onViewChange, }: InPlaceViewProps): import("react").JSX.Element;
45
+ export declare function InPlaceView({ value, onChange, readOnly, placeholder, onWikiLinkClick, onLinkClick, inPlace, codeLanguages, wikiLinkSource, embedSource, onResolveError, onSave, onViewChange, canvasHeader, }: InPlaceViewProps): import("react").JSX.Element;
41
46
  //# sourceMappingURL=InPlaceView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InPlaceView.d.ts","sourceRoot":"","sources":["../../src/inplace/InPlaceView.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIlD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACf,MAAM,UAAU,CAAA;AAIjB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,qDAAqD;IACrD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,uDAAuD;IACvD,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,qEAAqE;IACrE,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;CACjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,eAAe,EACf,WAAW,EACX,OAAO,EACP,aAAa,EACb,cAAc,EACd,WAAW,EACX,cAAc,EACd,MAAM,EACN,YAAY,GACb,EAAE,gBAAgB,+BAgDlB"}
1
+ {"version":3,"file":"InPlaceView.d.ts","sourceRoot":"","sources":["../../src/inplace/InPlaceView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAKlD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACf,MAAM,UAAU,CAAA;AAOjB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,qDAAqD;IACrD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,uDAAuD;IACvD,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,qEAAqE;IACrE,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,kFAAkF;IAClF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;CAC/D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,eAAe,EACf,WAAW,EACX,OAAO,EACP,aAAa,EACb,cAAc,EACd,WAAW,EACX,cAAc,EACd,MAAM,EACN,YAAY,EACZ,YAAY,GACb,EAAE,gBAAgB,+BAoElB"}
@@ -17,8 +17,8 @@ export interface ParsedTable {
17
17
  * so `tableField` remaps rather than rebuilds and DOM focus survives.
18
18
  *
19
19
  * The widget never stores its document range — a serialize dispatch shifts it —
20
- * so `bounds()` re-derives it from `posAtDOM` plus a scan of contiguous pipe
21
- * lines every time it is needed.
20
+ * so `bounds()` re-derives it every time from `tableField`, the same
21
+ * syntax-tree-backed decoration `table-enter.ts` reads for keyboard entry.
22
22
  */
23
23
  export declare class EditableTableWidget extends WidgetType {
24
24
  readonly data: ParsedTable;
@@ -44,9 +44,14 @@ export declare class EditableTableWidget extends WidgetType {
44
44
  ignoreEvent(): boolean;
45
45
  private cols;
46
46
  /**
47
- * The table's current `[from, to]` in the document, derived from the DOM.
48
- * `posAtDOM` may land on any line of the widget, so the scan grows the span in
49
- * both directions across contiguous non-blank pipe lines.
47
+ * The table's current `[from, to]` in the document, derived from the DOM via
48
+ * `tableField` — the same Lezer-tree-backed decoration CodeMirror treats as
49
+ * atomic. A prior version re-derived this with its own "contiguous pipe
50
+ * lines" scan, which disagreed with the real GFM parse whenever a table was
51
+ * followed with no blank line by a plain-prose line containing no `|`: GFM
52
+ * still swallows that line into the table, but the pipe scan stopped short
53
+ * of it, so `exitBelow()` (below) landed the caret one line short of past
54
+ * the table — still inside the atomic range it was meant to escape.
50
55
  */
51
56
  private bounds;
52
57
  private cellAt;
@@ -1 +1 @@
1
- {"version":3,"file":"table-widget.d.ts","sourceRoot":"","sources":["../../src/inplace/table-widget.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,EAAE,KAAK,KAAK,EAAiB,MAAM,uBAAuB,CAAA;AAuBjE,6EAA6E;AAC7E,eAAO,MAAM,eAAe,qDAA+B,CAAA;AAE3D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;IAChB,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IAgB/C,QAAQ,CAAC,IAAI,EAAE,WAAW;IAC1B,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,MAAM;IAjBzB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,IAAI,CAAY;IACxB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,OAAO,CAAQ;IACvB,iFAAiF;IACjF,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,SAAS,CAA+B;IAChD;;+CAE2C;IAC3C,OAAO,CAAC,WAAW,CAAI;IAEvB,YACW,IAAI,EAAE,WAAW;IAC1B,6EAA6E;IAC5D,MAAM,UAAQ,EAKhC;IAEQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,WAQrC;IAEQ,WAAW,YAEnB;IAED,OAAO,CAAC,IAAI;IAIZ;;;;OAIG;IACH,OAAO,CAAC,MAAM;IAad,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,MAAM;IAId,+EAA+E;IAC/E,OAAO,CAAC,KAAK;IAIb,iEAAiE;IACjE,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,KAAK;IAIb,iFAAiF;IACjF,OAAO,CAAC,KAAK;IAsBb,wFAAwF;IACxF,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,UAAU;IAQlB,uFAAuF;IACvF,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAKlB,0CAA0C;IAC1C,OAAO,CAAC,IAAI;IA0BZ,OAAO,CAAC,KAAK;IAuFb;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CASzC;IAED;2BACuB;IACvB,OAAO,CAAC,cAAc;IAetB,KAAK,CAAC,IAAI,EAAE,UAAU,kBA2ErB;IAEQ,OAAO,SAOf;CACF"}
1
+ {"version":3,"file":"table-widget.d.ts","sourceRoot":"","sources":["../../src/inplace/table-widget.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,EAAE,KAAK,KAAK,EAAiB,MAAM,uBAAuB,CAAA;AAwBjE,6EAA6E;AAC7E,eAAO,MAAM,eAAe,qDAA+B,CAAA;AAE3D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;IAChB,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IAgB/C,QAAQ,CAAC,IAAI,EAAE,WAAW;IAC1B,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,MAAM;IAjBzB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,IAAI,CAAY;IACxB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,OAAO,CAAQ;IACvB,iFAAiF;IACjF,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,SAAS,CAA+B;IAChD;;+CAE2C;IAC3C,OAAO,CAAC,WAAW,CAAI;IAEvB,YACW,IAAI,EAAE,WAAW;IAC1B,6EAA6E;IAC5D,MAAM,UAAQ,EAKhC;IAEQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,WAQrC;IAEQ,WAAW,YAEnB;IAED,OAAO,CAAC,IAAI;IAIZ;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,MAAM;IAId,+EAA+E;IAC/E,OAAO,CAAC,KAAK;IAIb,iEAAiE;IACjE,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,KAAK;IAIb,iFAAiF;IACjF,OAAO,CAAC,KAAK;IAsBb,wFAAwF;IACxF,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,UAAU;IAQlB,uFAAuF;IACvF,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAKlB,0CAA0C;IAC1C,OAAO,CAAC,IAAI;IA0BZ,OAAO,CAAC,KAAK;IAuFb;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CASzC;IAED;2BACuB;IACvB,OAAO,CAAC,cAAc;IAetB,KAAK,CAAC,IAAI,EAAE,UAAU,kBA2ErB;IAEQ,OAAO,SAOf;CACF"}
@@ -104,12 +104,18 @@ export declare const canvasTheme: {
104
104
  };
105
105
  ".cm-inplace-embed": {
106
106
  display: string;
107
- margin: string;
107
+ padding: string;
108
108
  };
109
109
  ".cm-inplace-embed .stylo-embed-content": {
110
110
  borderLeft: string;
111
111
  paddingLeft: string;
112
112
  };
113
+ ".cm-inplace-embed .stylo-embed-content > :first-child": {
114
+ marginTop: string;
115
+ };
116
+ ".cm-inplace-embed .stylo-embed-content > :last-child": {
117
+ marginBottom: string;
118
+ };
113
119
  ".cm-inplace-embed-inline": {
114
120
  display: string;
115
121
  };
@@ -1 +1 @@
1
- {"version":3,"file":"theme-canvas.d.ts","sourceRoot":"","sources":["../../src/inplace/theme-canvas.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,WAAW;;;;;;;;QAkBN,WAAW;QAAO,YAAY;;;QAErB,UAAU;;;QACf,QAAQ;QAAY,UAAU;QAAe,UAAU;;;QACvD,QAAQ;QAAW,UAAU;QAAe,UAAU;;;QACtD,QAAQ;QAAY,UAAU;QAAS,UAAU;;;QACjD,QAAQ;QAAS,UAAU;QAAS,UAAU;;;QAC9C,QAAQ;;;QACR,QAAQ;QAAW,KAAK;;;QAEpB,UAAU;;;QACd,SAAS;;;QACL,cAAc;;;;;;;;;;;;;;;;QA0BpC,UAAU;QACV,mBAAmB;QACnB,oBAAoB;;;QAGpB,aAAa;QACb,sBAAsB;QACtB,uBAAuB;;;QAEF,KAAK;;;QAEF,QAAQ;QAAO,UAAU;;;QAIjD,KAAK;QACL,cAAc;QACd,MAAM;;;QAEkB,KAAK;;;QAG7B,OAAO;QACP,OAAO;QACP,SAAS;;;QAEgC,MAAM;;;QAM/C,OAAO;QACP,MAAM;;;QAGN,UAAU;QACV,WAAW;;;QAIiB,OAAO;;;QAKZ,QAAQ;QAAO,UAAU;;;QAGrB,QAAQ;QAAO,UAAU;;;QAEpD,OAAO;QAKP,MAAM;QACN,MAAM;QACN,MAAM;QAEN,UAAU;;;QAIV,UAAU;QAEV,WAAW;QACX,KAAK;;;QAGiB,KAAK;;;QAK3B,eAAe;QAEf,gBAAgB;QAChB,kBAAkB;QAClB,cAAc;;;QAGd,MAAM;QACN,aAAa;QACb,MAAM;;;;;;;;;;;;;;;;;CAiBT,CAAA"}
1
+ {"version":3,"file":"theme-canvas.d.ts","sourceRoot":"","sources":["../../src/inplace/theme-canvas.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,WAAW;;;;;;;;QAkBN,WAAW;QAAO,YAAY;;;QAErB,UAAU;;;QACf,QAAQ;QAAY,UAAU;QAAe,UAAU;;;QACvD,QAAQ;QAAW,UAAU;QAAe,UAAU;;;QACtD,QAAQ;QAAY,UAAU;QAAS,UAAU;;;QACjD,QAAQ;QAAS,UAAU;QAAS,UAAU;;;QAC9C,QAAQ;;;QACR,QAAQ;QAAW,KAAK;;;QAEpB,UAAU;;;QACd,SAAS;;;QACL,cAAc;;;;;;;;;;;;;;;;QA0BpC,UAAU;QACV,mBAAmB;QACnB,oBAAoB;;;QAGpB,aAAa;QACb,sBAAsB;QACtB,uBAAuB;;;QAEF,KAAK;;;QAEF,QAAQ;QAAO,UAAU;;;QAIjD,KAAK;QACL,cAAc;QACd,MAAM;;;QAEkB,KAAK;;;QAG7B,OAAO;QACP,OAAO;QACP,SAAS;;;QAEgC,MAAM;;;QAoB/C,OAAO;QACP,OAAO;;;QAGP,UAAU;QACV,WAAW;;;QAS8C,SAAS;;;QACV,YAAY;;;QAGxC,OAAO;;;QAKZ,QAAQ;QAAO,UAAU;;;QAGrB,QAAQ;QAAO,UAAU;;;QAEpD,OAAO;QAKP,MAAM;QACN,MAAM;QACN,MAAM;QAEN,UAAU;;;QAIV,UAAU;QAEV,WAAW;QACX,KAAK;;;QAGiB,KAAK;;;QAK3B,eAAe;QAEf,gBAAgB;QAChB,kBAAkB;QAClB,cAAc;;;QAGd,MAAM;QACN,aAAa;QACb,MAAM;;;;;;;;;;;;;;;;;CAiBT,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Embed.d.ts","sourceRoot":"","sources":["../../src/render/Embed.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAG7D,UAAU,UAAU;IAClB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC1D;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAID;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,+BAoCvE"}
1
+ {"version":3,"file":"Embed.d.ts","sourceRoot":"","sources":["../../src/render/Embed.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAG7D,UAAU,UAAU;IAClB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC1D;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAID;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,+BAmDvE"}
package/dist/styles.css CHANGED
@@ -1,2 +1,2 @@
1
- ._root_1y1lh_1{min-height:0;color:var(--stylo-text);background:var(--stylo-bg);border:1px solid var(--stylo-border);border-radius:var(--stylo-radius);flex-direction:column;display:flex;overflow:hidden}._root_1y1lh_1 .cm-scroller{scrollbar-width:thin;scrollbar-color:color-mix(in srgb, var(--stylo-border) 90%, transparent) transparent}._root_1y1lh_1 .cm-scroller::-webkit-scrollbar{width:10px;height:10px}._root_1y1lh_1 .cm-scroller::-webkit-scrollbar-thumb{background:color-mix(in srgb, var(--stylo-border) 90%, transparent);background-clip:padding-box;border:3px solid #0000;border-radius:6px}._root_1y1lh_1 .cm-scroller::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb, var(--stylo-text-muted) 55%, transparent);background-clip:padding-box}._root_1y1lh_1 .cm-scroller::-webkit-scrollbar-corner{background:0 0}._source_1y1lh_42{flex:auto;min-height:0;overflow:auto}._source_1y1lh_42 .cm-editor{height:100%}._source_1y1lh_42 .cm-editor.cm-focused{outline:2px solid var(--stylo-ring);outline-offset:-2px}._inplace_1y1lh_57{flex:auto;min-height:0;overflow:auto}._toolbar_1y1lh_63{background:var(--stylo-bg);border-bottom:1px solid var(--stylo-border);flex-wrap:wrap;align-items:center;gap:2px;padding:4px 6px;display:flex}._toolbarButton_1y1lh_73{box-sizing:border-box;border-radius:calc(var(--stylo-radius) - 3px);min-width:28px;height:28px;color:var(--stylo-text-muted);font:inherit;cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:0 5px;font-size:.75rem;font-weight:600;line-height:1;display:inline-flex}._toolbarButton_1y1lh_73:hover:not(:disabled){background:color-mix(in srgb, var(--stylo-border) 45%, transparent);color:var(--stylo-text)}._toolbarButton_1y1lh_73[data-active]{background:color-mix(in srgb, var(--stylo-accent) 12%, transparent);color:var(--stylo-text)}._toolbarButton_1y1lh_73:disabled{opacity:.4;cursor:default}._toolbarButton_1y1lh_73:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-2px}._toolbarButton_1y1lh_73 svg{width:16px;height:16px;display:block}._toolbarButton_1y1lh_73 code{font-family:var(--stylo-font-family-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);font-size:.8125rem;font-weight:500}._toolbarSep_1y1lh_132{background:var(--stylo-border);align-self:stretch;width:1px;margin:4px 3px}._toolbarSticky_1y1lh_142{z-index:50;-webkit-overflow-scrolling:touch;scrollbar-width:none;font-family:var(--stylo-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);flex-wrap:nowrap;transition:opacity .15s;overflow-x:auto}._toolbarSticky_1y1lh_142::-webkit-scrollbar{display:none}._toolbarSticky_1y1lh_142 ._toolbarButton_1y1lh_73{flex:none;min-width:40px;height:40px}._toolbarStickyBottom_1y1lh_142{border-bottom:none;border-top:1px solid var(--stylo-border);box-shadow:0 -2px 8px color-mix(in srgb, var(--stylo-text) 10%, transparent);position:fixed;bottom:0;left:0;right:0}._toolbarStickyTop_1y1lh_142{box-shadow:0 2px 8px color-mix(in srgb, var(--stylo-text) 10%, transparent);position:fixed;top:0;left:0;right:0}._toolbarStickyHidden_1y1lh_211{opacity:0;pointer-events:none}._stickyToolbarRootBottom_1y1lh_222 ._source_1y1lh_42,._stickyToolbarRootBottom_1y1lh_222 ._inplace_1y1lh_57{padding-bottom:52px}._stickyToolbarRootTop_1y1lh_227 ._source_1y1lh_42,._stickyToolbarRootTop_1y1lh_227 ._inplace_1y1lh_57{padding-top:52px}._inplace_1y1lh_57 .cm-editor{height:100%}._inplace_1y1lh_57 .cm-editor.cm-focused{outline:2px solid var(--stylo-ring);outline-offset:-2px}._split_1y1lh_241{flex:1;grid-template-columns:1fr 1fr;min-height:0;display:grid}._splitPane_1y1lh_248{box-sizing:border-box;flex-direction:column;min-height:0;display:flex;overflow:auto}._splitPane_1y1lh_248+._splitPane_1y1lh_248{border-left:1px solid var(--stylo-border)}._splitPane_1y1lh_248>._source_1y1lh_42{flex:1;min-height:0}._preview_1y1lh_268{overflow-wrap:break-word;padding:.75rem 1rem;font-size:.9375rem;line-height:1.75}._preview_1y1lh_268>:first-child{margin-top:0}._preview_1y1lh_268>:last-child{margin-bottom:0}._preview_1y1lh_268 :is(h1,h2,h3,h4,h5,h6){font-weight:600}._preview_1y1lh_268 h1{margin:0 0 .888889em;font-size:2.25em;line-height:1.11111}._preview_1y1lh_268 h2{margin:2em 0 1em;font-size:1.5em;line-height:1.33333}._preview_1y1lh_268 h3{margin:1.6em 0 .6em;font-size:1.25em;line-height:1.6}._preview_1y1lh_268 :is(h4,h5,h6){margin:1.5em 0 .5em;line-height:1.5}._preview_1y1lh_268 p{margin:1.25em 0}._preview_1y1lh_268 :is(ul,ol){margin:1.25em 0;padding-left:1.625em}._preview_1y1lh_268 li{margin:.5em 0}._preview_1y1lh_268 li>:is(ul,ol){margin:.75em 0}._preview_1y1lh_268 a{color:var(--stylo-link);text-decoration:none}._preview_1y1lh_268 code{font-family:var(--stylo-font-family-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);border-radius:calc(var(--stylo-radius) - 3px);background:color-mix(in srgb, var(--stylo-border) 45%, transparent);padding:.1em .35em;font-size:.9em}._preview_1y1lh_268 pre{border-radius:var(--stylo-radius);background:color-mix(in srgb, var(--stylo-border) 35%, transparent);margin:1.71429em 0;padding:.75rem .9rem;overflow-x:auto}._preview_1y1lh_268 pre code{background:0 0;padding:0;font-size:.85em}.stylo-frontmatter{border-left:3px solid var(--stylo-border);border-radius:calc(var(--stylo-radius) - 3px);background:color-mix(in srgb, var(--stylo-border) 22%, transparent);color:var(--stylo-text-muted);font-family:var(--stylo-font-family-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);white-space:pre-wrap;margin:0 0 1.2em;padding:.7rem .9rem;font-size:.8125rem;line-height:1.5;overflow-x:auto}.stylo-frontmatter:before{content:"Frontmatter";font-family:var(--stylo-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);letter-spacing:.04em;text-transform:uppercase;margin-bottom:.5em;font-size:.7rem;font-weight:600;display:block}._preview_1y1lh_268 blockquote{border-left:.25rem solid var(--stylo-border);color:var(--stylo-text-muted);margin:1.6em 0;padding-left:1em}._preview_1y1lh_268 .stylo-callout{border-left:.25rem solid var(--stylo-callout-accent,var(--stylo-border));border-radius:var(--stylo-radius);background:color-mix(in srgb, var(--stylo-callout-accent,var(--stylo-border)) 10%, transparent);color:var(--stylo-text);margin:1.6em 0;padding:.6em 1em}._preview_1y1lh_268 .stylo-callout:before{content:attr(data-callout);letter-spacing:.04em;text-transform:uppercase;color:var(--stylo-callout-accent,var(--stylo-text-muted));margin-bottom:.2em;font-size:.8em;font-weight:700;display:block}._preview_1y1lh_268 .stylo-callout-note{--stylo-callout-accent:var(--stylo-callout-note,#3b82f6)}._preview_1y1lh_268 .stylo-callout-tip{--stylo-callout-accent:var(--stylo-callout-tip,#22c55e)}._preview_1y1lh_268 .stylo-callout-warn{--stylo-callout-accent:var(--stylo-callout-warn,#f59e0b)}._preview_1y1lh_268 .stylo-callout-danger{--stylo-callout-accent:var(--stylo-callout-danger,#ef4444)}._preview_1y1lh_268 .stylo-callout-example{--stylo-callout-accent:var(--stylo-callout-example,#a855f7)}._preview_1y1lh_268 .stylo-embed{border-left:.25rem solid var(--stylo-embed-accent,var(--stylo-border));margin:1.6em 0;padding-left:1em}._preview_1y1lh_268 .stylo-embed-content>:first-child{margin-top:0}._preview_1y1lh_268 .stylo-embed-content>:last-child{margin-bottom:0}._preview_1y1lh_268 table{border-collapse:collapse;margin:2em 0;display:block;overflow-x:auto}._preview_1y1lh_268 :is(th,td){border:1px solid var(--stylo-table-border);text-align:left;padding:.35em .6em}._preview_1y1lh_268 thead th{background:var(--stylo-table-header-bg);font-weight:600}._preview_1y1lh_268 tbody tr:nth-child(2n) td{background:var(--stylo-table-stripe-bg)}._preview_1y1lh_268 hr{border:none;border-top:1px solid var(--stylo-border);margin:1em 0}._preview_1y1lh_268 .katex-display{padding:.25em 0;overflow:auto hidden}.stylo{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--stylo-bg:#fff;--stylo-surface-floating:#fff;--stylo-text:#09090b;--stylo-text-muted:#71717a;--stylo-border:#e4e4e7;--stylo-accent:#18181b;--stylo-link:#2563eb;--stylo-ring:#a1a1aa;--stylo-radius:.5rem;--stylo-font-size:.9375rem;--stylo-font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;--stylo-font-family-mono:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;--stylo-table-border:var(--stylo-border);--stylo-table-header-bg:color-mix(in srgb, var(--stylo-border) 30%, transparent);--stylo-table-stripe-bg:transparent;--stylo-guide:var(--stylo-border);--stylo-syntax-keyword:#7c3aed;--stylo-syntax-string:#0a7c2f;--stylo-syntax-escape:#b45309;--stylo-syntax-comment:#8a8f98;--stylo-syntax-number:#b45309;--stylo-syntax-constant:#b45309;--stylo-syntax-function:#2563eb;--stylo-syntax-type:#a16207;--stylo-syntax-property:#0f766e;--stylo-syntax-tag:#cf222e;--stylo-syntax-invalid:#dc2626}:where(.dark,[data-theme=dark]) .stylo,.stylo:where(.dark,[data-theme=dark]){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--stylo-bg:#09090b;--stylo-surface-floating:#09090b;--stylo-text:#fafafa;--stylo-text-muted:#a1a1aa;--stylo-border:#27272a;--stylo-accent:#fafafa;--stylo-link:#60a5fa;--stylo-ring:#52525b;--stylo-syntax-keyword:#c678dd;--stylo-syntax-string:#98c379;--stylo-syntax-escape:#d19a66;--stylo-syntax-comment:#7f848e;--stylo-syntax-number:#d19a66;--stylo-syntax-constant:#d19a66;--stylo-syntax-function:#61afef;--stylo-syntax-type:#e5c07b;--stylo-syntax-property:#56b6c2;--stylo-syntax-tag:#e06c75;--stylo-syntax-invalid:#e06c75}._root_18hcd_3{color:var(--stylo-text);font:inherit;grid-template-columns:1fr 1fr;gap:12px;display:grid}@media (width<=460px){._root_18hcd_3{grid-template-columns:1fr}}._col_18hcd_17{border:1px solid var(--stylo-border);border-radius:var(--stylo-radius);background:var(--stylo-bg);flex-direction:column;min-width:0;display:flex}._colHead_18hcd_26{border-bottom:1px solid var(--stylo-border);letter-spacing:.04em;text-transform:uppercase;color:var(--stylo-text-muted);margin:0;padding:8px 12px;font-size:.75rem;font-weight:600}._list_18hcd_37{flex-direction:column;flex:1;gap:2px;margin:0;padding:4px;list-style:none;display:flex}._row_18hcd_47{border-radius:calc(var(--stylo-radius) - 3px);background:var(--stylo-bg);align-items:center;gap:8px;padding:5px 6px;display:flex}._row_18hcd_47:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-2px}._row_18hcd_47:hover{background:color-mix(in srgb, var(--stylo-border) 30%, transparent)}._row_18hcd_47[data-dragging]{background:var(--stylo-surface-floating,#fff);opacity:.9;box-shadow:0 4px 16px #00000024}._handle_18hcd_73{border-radius:calc(var(--stylo-radius) - 4px);width:20px;height:22px;color:var(--stylo-text-muted);font:inherit;cursor:grab;touch-action:none;background:0 0;border:1px solid #0000;flex:none;justify-content:center;align-items:center;padding:0;line-height:1;display:inline-flex}._handle_18hcd_73:hover{background:color-mix(in srgb, var(--stylo-border) 45%, transparent);color:var(--stylo-text)}._handle_18hcd_73:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-1px}._handle_18hcd_73:active{cursor:grabbing}._glyph_18hcd_105{width:18px;height:18px;color:var(--stylo-text-muted);flex:none;justify-content:center;align-items:center;display:inline-flex}._glyph_18hcd_105 svg{width:16px;height:16px;display:block}._label_18hcd_121{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:.8125rem;overflow:hidden}._rowActions_18hcd_130{flex:none;gap:2px;display:flex}._iconButton_18hcd_136,._textButton_18hcd_137{box-sizing:border-box;border-radius:calc(var(--stylo-radius) - 4px);color:var(--stylo-text-muted);font:inherit;cursor:pointer;background:0 0;border:1px solid #0000}._iconButton_18hcd_136{width:22px;height:22px;font-size:.8125rem;line-height:1}._textButton_18hcd_137{padding:3px 8px;font-size:.75rem}._iconButton_18hcd_136:hover:not(:disabled),._textButton_18hcd_137:hover:not(:disabled){background:color-mix(in srgb, var(--stylo-border) 45%, transparent);color:var(--stylo-text)}._iconButton_18hcd_136:focus-visible,._textButton_18hcd_137:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-1px}._iconButton_18hcd_136:disabled{opacity:.35;cursor:default}._footer_18hcd_176{border-top:1px solid var(--stylo-border);flex-wrap:wrap;gap:6px;padding:6px;display:flex}._empty_18hcd_184{color:var(--stylo-text-muted);padding:8px 6px;font-size:.8125rem}._srOnly_18hcd_190{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}
1
+ ._root_1lohh_1{min-height:0;color:var(--stylo-text);background:var(--stylo-bg);border:1px solid var(--stylo-border);border-radius:var(--stylo-radius);flex-direction:column;display:flex;overflow:hidden}._root_1lohh_1 .cm-scroller{scrollbar-width:thin;scrollbar-color:color-mix(in srgb, var(--stylo-border) 90%, transparent) transparent}._root_1lohh_1 .cm-scroller::-webkit-scrollbar{width:10px;height:10px}._root_1lohh_1 .cm-scroller::-webkit-scrollbar-thumb{background:color-mix(in srgb, var(--stylo-border) 90%, transparent);background-clip:padding-box;border:3px solid #0000;border-radius:6px}._root_1lohh_1 .cm-scroller::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb, var(--stylo-text-muted) 55%, transparent);background-clip:padding-box}._root_1lohh_1 .cm-scroller::-webkit-scrollbar-corner{background:0 0}._source_1lohh_42{flex:auto;min-height:0;overflow:auto}._source_1lohh_42 .cm-editor{height:100%}._source_1lohh_42 .cm-editor.cm-focused{outline:2px solid var(--stylo-ring);outline-offset:-2px}._inplace_1lohh_57{flex:auto;min-height:0;overflow:auto}._toolbar_1lohh_63{background:var(--stylo-bg);border-bottom:1px solid var(--stylo-border);flex-wrap:wrap;align-items:center;gap:2px;padding:4px 6px;display:flex}._toolbarGroup_1lohh_75{align-items:center;gap:2px;display:flex}._toolbarButton_1lohh_81{box-sizing:border-box;border-radius:calc(var(--stylo-radius) - 3px);min-width:28px;height:28px;color:var(--stylo-text-muted);font:inherit;cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:0 5px;font-size:.75rem;font-weight:600;line-height:1;display:inline-flex}._toolbarButton_1lohh_81:hover:not(:disabled){background:color-mix(in srgb, var(--stylo-border) 45%, transparent);color:var(--stylo-text)}._toolbarButton_1lohh_81[data-active]{background:color-mix(in srgb, var(--stylo-accent) 12%, transparent);color:var(--stylo-text)}._toolbarButton_1lohh_81:disabled{opacity:.4;cursor:default}._toolbarButton_1lohh_81:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-2px}._toolbarButton_1lohh_81 svg{width:16px;height:16px;display:block}._toolbarButton_1lohh_81 code{font-family:var(--stylo-font-family-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);font-size:.8125rem;font-weight:500}._toolbarSep_1lohh_140{background:var(--stylo-border);align-self:stretch;width:1px;margin:4px 3px}._toolbarSticky_1lohh_150{z-index:50;-webkit-overflow-scrolling:touch;scrollbar-width:none;font-family:var(--stylo-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);flex-wrap:nowrap;transition:opacity .15s;overflow-x:auto}._toolbarSticky_1lohh_150::-webkit-scrollbar{display:none}._toolbarSticky_1lohh_150 ._toolbarButton_1lohh_81{flex:none;min-width:40px;height:40px}._toolbarStickyBottom_1lohh_150{border-bottom:none;border-top:1px solid var(--stylo-border);box-shadow:0 -2px 8px color-mix(in srgb, var(--stylo-text) 10%, transparent);position:fixed;bottom:0;left:0;right:0}._toolbarStickyTop_1lohh_150{box-shadow:0 2px 8px color-mix(in srgb, var(--stylo-text) 10%, transparent);position:fixed;top:0;left:0;right:0}._toolbarStickyHidden_1lohh_219{opacity:0;pointer-events:none}._stickyToolbarRootBottom_1lohh_230 ._source_1lohh_42,._stickyToolbarRootBottom_1lohh_230 ._inplace_1lohh_57{padding-bottom:52px}._stickyToolbarRootTop_1lohh_235 ._source_1lohh_42,._stickyToolbarRootTop_1lohh_235 ._inplace_1lohh_57{padding-top:52px}._inplace_1lohh_57 .cm-editor{height:100%}._inplace_1lohh_57 .cm-editor.cm-focused{outline:2px solid var(--stylo-ring);outline-offset:-2px}._split_1lohh_249{flex:1;grid-template-columns:1fr 1fr;min-height:0;display:grid}._splitPane_1lohh_256{box-sizing:border-box;flex-direction:column;min-height:0;display:flex;overflow:auto}._splitPane_1lohh_256+._splitPane_1lohh_256{border-left:1px solid var(--stylo-border)}._splitPane_1lohh_256>._source_1lohh_42{flex:1;min-height:0}._preview_1lohh_276{overflow-wrap:break-word;padding:.75rem 1rem;font-size:.9375rem;line-height:1.75}._preview_1lohh_276>:first-child{margin-top:0}._preview_1lohh_276>:last-child{margin-bottom:0}._preview_1lohh_276 :is(h1,h2,h3,h4,h5,h6){font-weight:600}._preview_1lohh_276 h1{margin:0 0 .888889em;font-size:2.25em;line-height:1.11111}._preview_1lohh_276 h2{margin:2em 0 1em;font-size:1.5em;line-height:1.33333}._preview_1lohh_276 h3{margin:1.6em 0 .6em;font-size:1.25em;line-height:1.6}._preview_1lohh_276 :is(h4,h5,h6){margin:1.5em 0 .5em;line-height:1.5}._preview_1lohh_276 p{margin:1.25em 0}._preview_1lohh_276 :is(ul,ol){margin:1.25em 0;padding-left:1.625em}._preview_1lohh_276 li{margin:.5em 0}._preview_1lohh_276 li>:is(ul,ol){margin:.75em 0}._preview_1lohh_276 a{color:var(--stylo-link);text-decoration:none}._preview_1lohh_276 code{font-family:var(--stylo-font-family-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);border-radius:calc(var(--stylo-radius) - 3px);background:color-mix(in srgb, var(--stylo-border) 45%, transparent);padding:.1em .35em;font-size:.9em}._preview_1lohh_276 pre{border-radius:var(--stylo-radius);background:color-mix(in srgb, var(--stylo-border) 35%, transparent);margin:1.71429em 0;padding:.75rem .9rem;overflow-x:auto}._preview_1lohh_276 pre code{background:0 0;padding:0;font-size:.85em}.stylo-frontmatter{border-left:3px solid var(--stylo-border);border-radius:calc(var(--stylo-radius) - 3px);background:color-mix(in srgb, var(--stylo-border) 22%, transparent);color:var(--stylo-text-muted);font-family:var(--stylo-font-family-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);white-space:pre-wrap;margin:0 0 1.2em;padding:.7rem .9rem;font-size:.8125rem;line-height:1.5;overflow-x:auto}.stylo-frontmatter:before{content:"Frontmatter";font-family:var(--stylo-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);letter-spacing:.04em;text-transform:uppercase;margin-bottom:.5em;font-size:.7rem;font-weight:600;display:block}._preview_1lohh_276 blockquote{border-left:.25rem solid var(--stylo-border);color:var(--stylo-text-muted);margin:1.6em 0;padding-left:1em}._preview_1lohh_276 .stylo-callout{border-left:.25rem solid var(--stylo-callout-accent,var(--stylo-border));border-radius:var(--stylo-radius);background:color-mix(in srgb, var(--stylo-callout-accent,var(--stylo-border)) 10%, transparent);color:var(--stylo-text);margin:1.6em 0;padding:.6em 1em}._preview_1lohh_276 .stylo-callout:before{content:attr(data-callout);letter-spacing:.04em;text-transform:uppercase;color:var(--stylo-callout-accent,var(--stylo-text-muted));margin-bottom:.2em;font-size:.8em;font-weight:700;display:block}._preview_1lohh_276 .stylo-callout-note{--stylo-callout-accent:var(--stylo-callout-note,#3b82f6)}._preview_1lohh_276 .stylo-callout-tip{--stylo-callout-accent:var(--stylo-callout-tip,#22c55e)}._preview_1lohh_276 .stylo-callout-warn{--stylo-callout-accent:var(--stylo-callout-warn,#f59e0b)}._preview_1lohh_276 .stylo-callout-danger{--stylo-callout-accent:var(--stylo-callout-danger,#ef4444)}._preview_1lohh_276 .stylo-callout-example{--stylo-callout-accent:var(--stylo-callout-example,#a855f7)}._preview_1lohh_276 .stylo-embed{border-left:.25rem solid var(--stylo-embed-accent,var(--stylo-border));margin:1.6em 0;padding-left:1em}._preview_1lohh_276 .stylo-embed-content>:first-child{margin-top:0}._preview_1lohh_276 .stylo-embed-content>:last-child{margin-bottom:0}._preview_1lohh_276 table{border-collapse:collapse;margin:2em 0;display:block;overflow-x:auto}._preview_1lohh_276 :is(th,td){border:1px solid var(--stylo-table-border);text-align:left;padding:.35em .6em}._preview_1lohh_276 thead th{background:var(--stylo-table-header-bg);font-weight:600}._preview_1lohh_276 tbody tr:nth-child(2n) td{background:var(--stylo-table-stripe-bg)}._preview_1lohh_276 hr{border:none;border-top:1px solid var(--stylo-border);margin:1em 0}._preview_1lohh_276 .katex-display{padding:.25em 0;overflow:auto hidden}.stylo{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--stylo-bg:#fff;--stylo-surface-floating:#fff;--stylo-text:#09090b;--stylo-text-muted:#71717a;--stylo-border:#e4e4e7;--stylo-accent:#18181b;--stylo-link:#2563eb;--stylo-ring:#a1a1aa;--stylo-radius:.5rem;--stylo-font-size:.9375rem;--stylo-font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;--stylo-font-family-mono:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;--stylo-table-border:var(--stylo-border);--stylo-table-header-bg:color-mix(in srgb, var(--stylo-border) 30%, transparent);--stylo-table-stripe-bg:transparent;--stylo-guide:var(--stylo-border);--stylo-syntax-keyword:#7c3aed;--stylo-syntax-string:#0a7c2f;--stylo-syntax-escape:#b45309;--stylo-syntax-comment:#8a8f98;--stylo-syntax-number:#b45309;--stylo-syntax-constant:#b45309;--stylo-syntax-function:#2563eb;--stylo-syntax-type:#a16207;--stylo-syntax-property:#0f766e;--stylo-syntax-tag:#cf222e;--stylo-syntax-invalid:#dc2626}:where(.dark,[data-theme=dark]) .stylo,.stylo:where(.dark,[data-theme=dark]){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--stylo-bg:#09090b;--stylo-surface-floating:#09090b;--stylo-text:#fafafa;--stylo-text-muted:#a1a1aa;--stylo-border:#27272a;--stylo-accent:#fafafa;--stylo-link:#60a5fa;--stylo-ring:#52525b;--stylo-syntax-keyword:#c678dd;--stylo-syntax-string:#98c379;--stylo-syntax-escape:#d19a66;--stylo-syntax-comment:#7f848e;--stylo-syntax-number:#d19a66;--stylo-syntax-constant:#d19a66;--stylo-syntax-function:#61afef;--stylo-syntax-type:#e5c07b;--stylo-syntax-property:#56b6c2;--stylo-syntax-tag:#e06c75;--stylo-syntax-invalid:#e06c75}._root_18hcd_3{color:var(--stylo-text);font:inherit;grid-template-columns:1fr 1fr;gap:12px;display:grid}@media (width<=460px){._root_18hcd_3{grid-template-columns:1fr}}._col_18hcd_17{border:1px solid var(--stylo-border);border-radius:var(--stylo-radius);background:var(--stylo-bg);flex-direction:column;min-width:0;display:flex}._colHead_18hcd_26{border-bottom:1px solid var(--stylo-border);letter-spacing:.04em;text-transform:uppercase;color:var(--stylo-text-muted);margin:0;padding:8px 12px;font-size:.75rem;font-weight:600}._list_18hcd_37{flex-direction:column;flex:1;gap:2px;margin:0;padding:4px;list-style:none;display:flex}._row_18hcd_47{border-radius:calc(var(--stylo-radius) - 3px);background:var(--stylo-bg);align-items:center;gap:8px;padding:5px 6px;display:flex}._row_18hcd_47:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-2px}._row_18hcd_47:hover{background:color-mix(in srgb, var(--stylo-border) 30%, transparent)}._row_18hcd_47[data-dragging]{background:var(--stylo-surface-floating,#fff);opacity:.9;box-shadow:0 4px 16px #00000024}._handle_18hcd_73{border-radius:calc(var(--stylo-radius) - 4px);width:20px;height:22px;color:var(--stylo-text-muted);font:inherit;cursor:grab;touch-action:none;background:0 0;border:1px solid #0000;flex:none;justify-content:center;align-items:center;padding:0;line-height:1;display:inline-flex}._handle_18hcd_73:hover{background:color-mix(in srgb, var(--stylo-border) 45%, transparent);color:var(--stylo-text)}._handle_18hcd_73:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-1px}._handle_18hcd_73:active{cursor:grabbing}._glyph_18hcd_105{width:18px;height:18px;color:var(--stylo-text-muted);flex:none;justify-content:center;align-items:center;display:inline-flex}._glyph_18hcd_105 svg{width:16px;height:16px;display:block}._label_18hcd_121{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:.8125rem;overflow:hidden}._rowActions_18hcd_130{flex:none;gap:2px;display:flex}._iconButton_18hcd_136,._textButton_18hcd_137{box-sizing:border-box;border-radius:calc(var(--stylo-radius) - 4px);color:var(--stylo-text-muted);font:inherit;cursor:pointer;background:0 0;border:1px solid #0000}._iconButton_18hcd_136{width:22px;height:22px;font-size:.8125rem;line-height:1}._textButton_18hcd_137{padding:3px 8px;font-size:.75rem}._iconButton_18hcd_136:hover:not(:disabled),._textButton_18hcd_137:hover:not(:disabled){background:color-mix(in srgb, var(--stylo-border) 45%, transparent);color:var(--stylo-text)}._iconButton_18hcd_136:focus-visible,._textButton_18hcd_137:focus-visible{outline:2px solid var(--stylo-ring);outline-offset:-1px}._iconButton_18hcd_136:disabled{opacity:.35;cursor:default}._footer_18hcd_176{border-top:1px solid var(--stylo-border);flex-wrap:wrap;gap:6px;padding:6px;display:flex}._empty_18hcd_184{color:var(--stylo-text-muted);padding:8px 6px;font-size:.8125rem}._srOnly_18hcd_190{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}
2
2
  /*$vite$:1*/