@elabs-ai/components-editor 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -7
- package/dist/{chunk-LBC5VJBD.js → chunk-C62O7IOQ.js} +110 -21
- package/dist/chunk-C62O7IOQ.js.map +1 -0
- package/dist/index.css +4 -2
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +57 -20
- package/dist/index.js.map +1 -1
- package/dist/markdown/index.css +4 -2
- package/dist/markdown/index.css.map +1 -1
- package/dist/markdown/index.d.ts +2 -2
- package/dist/markdown/index.js +9 -9
- package/dist/markdown/index.js.map +1 -1
- package/dist/{markdown-editor-DfBZibAn.d.ts → markdown-editor-CBp_4eDv.d.ts} +1 -1
- package/package.json +6 -6
- package/src/ai-objects/entity.tsx +1 -1
- package/src/ai-objects/knowledge-card.tsx +1 -1
- package/src/calc-block/calc-editor.css +1 -1
- package/src/code-editor/code-editor.stories.tsx +76 -1
- package/src/code-editor/code-editor.tsx +1 -1
- package/src/code-workspace/code-workspace.test.tsx +83 -0
- package/src/code-workspace/code-workspace.tsx +73 -20
- package/src/diff-editor/diff-editor.stories.tsx +9 -1
- package/src/lib/monaco-deep-imports.d.ts +59 -0
- package/src/lib/monaco-theme-bridge.test.ts +307 -0
- package/src/lib/monaco-theme-bridge.ts +154 -10
- package/src/markdown-academic/citations.tsx +2 -2
- package/src/markdown-academic/footnotes.tsx +2 -2
- package/src/markdown-academic/toc.tsx +1 -1
- package/src/markdown-editor/directive-views.tsx +2 -5
- package/src/markdown-editor/markdown-editor.css +26 -3
- package/src/markdown-editor/markdown-editor.focus.test.ts +49 -0
- package/src/markdown-editor/markdown-editor.stories.tsx +128 -7
- package/src/markdown-editor/markdown-editor.tsx +8 -5
- package/src/markdown-editor/milkdown-react/use-get-editor.timer-leak.test.ts +80 -0
- package/src/markdown-editor/milkdown-react/use-get-editor.ts +37 -1
- package/src/markdown-editor/paste-embed.ts +2 -1
- package/src/markdown-editor/slash/slash-menu.stories.tsx +8 -3
- package/src/markdown-editor/slash/slash-menu.test.tsx +27 -0
- package/src/markdown-editor/slash/slash-menu.tsx +13 -1
- package/src/markdown-editor/table-view.tsx +3 -2
- package/src/markdown-iteration/iteration-builder-dialog.stories.tsx +57 -19
- package/src/markdown-outline/document-outline.stories.tsx +1 -1
- package/src/markdown-outline/document-outline.tsx +1 -1
- package/src/markdown-preview/markdown-preview-transclusion.test.tsx +1 -1
- package/src/markdown-preview/markdown-preview.stories.tsx +24 -2
- package/src/markdown-preview/markdown-preview.test.tsx +20 -3
- package/src/markdown-toolbar/markdown-toolbar.stories.tsx +3 -0
- package/src/markdown-workspace/markdown-workspace.test.tsx +31 -1
- package/src/mermaid-diagram/mermaid-viewer.tsx +1 -1
- package/src/prose/prose.stories.tsx +3 -0
- package/src/prose/prose.test.ts +54 -0
- package/src/prose/prose.tsx +7 -0
- package/dist/chunk-LBC5VJBD.js.map +0 -1
package/dist/index.css
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
max-width: var(--md-measure, 48rem);
|
|
12
12
|
margin-inline: auto;
|
|
13
13
|
}
|
|
14
|
-
.milkdown-host .ProseMirror:focus {
|
|
15
|
-
outline:
|
|
14
|
+
.milkdown-host .ProseMirror:focus-visible {
|
|
15
|
+
outline: 1px solid var(--ring-contour);
|
|
16
|
+
outline-offset: -3px;
|
|
17
|
+
box-shadow: inset 0 0 0 2px var(--ring);
|
|
16
18
|
}
|
|
17
19
|
.milkdown-host {
|
|
18
20
|
display: flex;
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/markdown-editor/markdown-editor.css","../src/calc-block/calc-editor.css"],"sourcesContent":["/**\n * Token-driven theme for the Milkdown (ProseMirror) WYSIWYG surface.\n *\n * Milkdown core ships ZERO styles (headless), so this is where brand-ui owns the\n * look. Every value is a semantic design token (var(--foreground), --border,\n * --radius, …) — NO raw colors — so the editor matches all three themes\n * (light/dark) for free. Every rule\n * is scoped under `.milkdown-host` so nothing leaks globally.\n */\n\n.milkdown-host .ProseMirror {\n outline: none;\n padding: 1rem 1.1rem;\n min-height: 9rem;\n color: var(--foreground);\n font-size: 0.875rem;\n line-height: 1.65;\n caret-color: var(--primary);\n word-break: break-word;\n /* Same reading measure as the preview (max-w-3xl). Driven by the shared scale\n (--md-measure, set via markdownScaleVars) so editor + preview match (#18). */\n max-width: var(--md-measure, 48rem);\n margin-inline: auto;\n}\n\n.milkdown-host .ProseMirror:focus {\n outline: none;\n}\n\n/* ----------------------------------------------------------------------------\n * Fill height — the editable grows to fill a definite-height parent.\n *\n * Milkdown's host box is otherwise content-sized (the `.ProseMirror` floor below\n * is `min-height: 9rem`), so inside a tall pane a short document leaves a large\n * dead area below the editable AND the caret-anchored `/` slash menu clips inside\n * the short box near the bottom edge. Making `.milkdown-host` a column flex that\n * fills its parent — and letting the intermediate Milkdown wrapper + the\n * ProseMirror surface grow inside it — means the editable fills the pane\n * (clickable everywhere) and the slash menu has room to open / flip.\n *\n * `min-height: 100%` only resolves against a parent with a DEFINITE height (the\n * workspace's `h-full` wysiwyg pane, or any sized container). In an\n * indefinite-height parent it resolves to `auto`, so the standalone / short\n * editor still sizes to its content above the 9rem floor — no regression for the\n * autodocs / inline cases. (elabs-components: editor-fill-height)\n * ------------------------------------------------------------------------- */\n.milkdown-host {\n display: flex;\n flex-direction: column;\n min-height: 100%;\n}\n.milkdown-host > div,\n.milkdown-host .milkdown {\n display: flex;\n min-height: 0;\n flex: 1 1 auto;\n flex-direction: column;\n}\n.milkdown-host .ProseMirror.editor {\n flex: 1 1 auto;\n}\n\n.milkdown-host .ProseMirror > * + * {\n margin-top: 0.7em;\n}\n\n/* Headings — sizes/weight/tracking come from the SHARED markdown scale\n (markdown-scale.ts → --md-* vars on .milkdown-host), so the editor matches the\n prose `Heading` exactly and can't drift on the next edit to either side (#18).\n Fallbacks equal the canonical scale for use without the vars (e.g. clipboard). */\n.milkdown-host .ProseMirror h1,\n.milkdown-host .ProseMirror h2,\n.milkdown-host .ProseMirror h3,\n.milkdown-host .ProseMirror h4,\n.milkdown-host .ProseMirror h5,\n.milkdown-host .ProseMirror h6 {\n font-weight: var(--md-heading-weight, 600);\n letter-spacing: var(--md-heading-tracking, -0.025em);\n line-height: 1.25;\n color: var(--foreground);\n margin-top: 1.1em;\n}\n.milkdown-host .ProseMirror h1 {\n font-size: var(--md-h1, 1.5rem);\n}\n.milkdown-host .ProseMirror h2 {\n font-size: var(--md-h2, 1.25rem);\n}\n.milkdown-host .ProseMirror h3 {\n font-size: var(--md-h3, 1.125rem);\n}\n.milkdown-host .ProseMirror h4 {\n font-size: var(--md-h4, 1rem);\n}\n.milkdown-host .ProseMirror h5 {\n font-size: var(--md-h5, 0.875rem);\n}\n.milkdown-host .ProseMirror h6 {\n font-size: var(--md-h6, 0.875rem);\n color: var(--muted-foreground);\n}\n\n/* Inline */\n.milkdown-host .ProseMirror a {\n color: var(--primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.milkdown-host .ProseMirror strong {\n font-weight: 650;\n}\n.milkdown-host .ProseMirror code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n background: var(--muted);\n color: var(--foreground);\n padding: 0.12em 0.36em;\n border-radius: calc(var(--radius) - 4px);\n}\n\n/* Blocks */\n.milkdown-host .ProseMirror blockquote {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n color: var(--muted-foreground);\n}\n.milkdown-host .ProseMirror pre {\n background: var(--surface-muted);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 0.85rem 1rem;\n overflow: auto;\n}\n.milkdown-host .ProseMirror pre code {\n background: transparent;\n padding: 0;\n font-size: 0.82rem;\n}\n.milkdown-host .ProseMirror hr {\n border: none;\n border-top: 1px solid var(--border);\n margin: 1.25em 0;\n}\n\n/* Lists */\n.milkdown-host .ProseMirror ul,\n.milkdown-host .ProseMirror ol {\n padding-left: 1.4rem;\n}\n.milkdown-host .ProseMirror ul {\n list-style: disc;\n}\n.milkdown-host .ProseMirror ol {\n list-style: decimal;\n}\n.milkdown-host .ProseMirror li > * + * {\n margin-top: 0.35em;\n}\n\n/* Tables (GFM) */\n.milkdown-host .ProseMirror table {\n border-collapse: collapse;\n width: 100%;\n font-size: 0.85rem;\n}\n.milkdown-host .ProseMirror th,\n.milkdown-host .ProseMirror td {\n border: 1px solid var(--border);\n padding: 0.4rem 0.6rem;\n text-align: left;\n}\n.milkdown-host .ProseMirror th {\n background: var(--surface-muted);\n font-weight: 600;\n}\n\n/* Task lists (GFM) */\n.milkdown-host .ProseMirror ul[data-item-type=\"task\"] {\n list-style: none;\n padding-left: 0.25rem;\n}\n\n/* Read-only mode dims the caret affordance */\n.milkdown-host .ProseMirror[contenteditable=\"false\"] {\n caret-color: transparent;\n}\n\n/* ---- Brand `:::` directives ----------------------------------------------------\n * These now render as LIVE @brand React components via @prosemirror-adapter/react\n * (see directive-views.tsx), so the box-model chrome (card/callout/metric borders,\n * fills, type accents) comes from the components themselves — NOT from here. This\n * section only owns what the editor adds on top: outer spacing, the editable-body\n * rhythm, the timeline frame (an editable list, not a derived <Timeline>), and the\n * inline-edit affordance for editable attributes (card/callout title, metric\n * label/value). The `toDOM` defs in directive-nodes.ts keep their own marker classes\n * for clipboard serialization but are not visually rendered while node-views are on.\n */\n.milkdown-host .brand-directive {\n margin: 0.85em 0;\n}\n.milkdown-host .brand-directive__body > * + * {\n margin-top: 0.6em;\n}\n/* The first/last editable block inside a card/callout shouldn't add stray margin\n * on top of the component's own padding. */\n.milkdown-host .brand-directive__body > :first-child {\n margin-top: 0;\n}\n\n/* timeline → keep the list editable inside a subtle frame */\n.milkdown-host .brand-directive--timeline {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n}\n\n/* Inline-editable directive attribute (seamless, caret-friendly). */\n.milkdown-host .brand-inline-edit {\n cursor: text;\n min-width: 1ch;\n /* inherit the surrounding component's type (CardTitle, MetricBlock label/value) */\n font: inherit;\n color: inherit;\n letter-spacing: inherit;\n}\n.milkdown-host .brand-inline-edit:empty::before {\n content: attr(data-placeholder);\n color: var(--muted-foreground);\n opacity: 0.65;\n pointer-events: none;\n}\n\n/* ------------------------------------------------------------------------- */\n/* Focus writing (Ulysses Phase A): under a `[data-focus-writing]` ancestor */\n/* (the workspace's wysiwyg pane), every top-level block dims except the one */\n/* owning the selection (`.wb-fw-active`, set by the workspace) — paragraph */\n/* focus. Hover un-dims for mouse repositioning. Token-driven, motion-safe. */\n/* ------------------------------------------------------------------------- */\n[data-focus-writing] .milkdown-host .ProseMirror > * {\n opacity: 0.35;\n transition: opacity var(--t-base, 200ms) var(--ease-standard, ease);\n}\n[data-focus-writing] .milkdown-host .ProseMirror > .wb-fw-active,\n[data-focus-writing] .milkdown-host .ProseMirror > *:hover {\n opacity: 1;\n}\n@media (prefers-reduced-motion: reduce) {\n [data-focus-writing] .milkdown-host .ProseMirror > * {\n transition: none;\n }\n}\n","/**\n * Calc authoring decorations (#220) — shared by the Monaco source surface\n * (decoration `inlineClassName`) and the Milkdown WYSIWYG surface (ProseMirror\n * inline decorations + result-inlay widgets).\n *\n * Colors come from the `--calc-*` syntax tokens — the SAME tokens `CalcBlock`\n * paints with (#221), already AA-verified against `--background` (the editor\n * surface) and `--card` in all three themes — so highlighting tracks the theme via\n * the cascade with no hardcoded hex. The compound `.brand-calc-tok.brand-calc-tok--x`\n * selector raises specificity above Monaco's own token color class (`.mtkN`) so\n * the calc color wins regardless of stylesheet load order (no `!important`).\n *\n * Hue is never the SOLE cue (var-def = weight, unresolved = dotted underline), so\n * roles stay distinct in the high-contrast theme where the calc colors collapse\n * toward the foreground — mirroring `CalcBlock.tokenClass`.\n */\n\n.brand-calc-tok.brand-calc-tok--number,\n.brand-calc-tok.brand-calc-tok--constant {\n color: var(--calc-number);\n}\n.brand-calc-tok.brand-calc-tok--unit {\n color: var(--calc-unit);\n}\n.brand-calc-tok.brand-calc-tok--currency {\n color: var(--calc-currency);\n}\n.brand-calc-tok.brand-calc-tok--operator {\n color: var(--calc-operator);\n}\n.brand-calc-tok.brand-calc-tok--function {\n color: var(--calc-function);\n}\n.brand-calc-tok.brand-calc-tok--var-ref {\n color: var(--calc-variable);\n}\n.brand-calc-tok.brand-calc-tok--var-def {\n color: var(--calc-variable);\n font-weight: 500;\n}\n.brand-calc-tok.brand-calc-tok--line-ref {\n color: var(--calc-reference);\n font-variant-numeric: tabular-nums;\n}\n.brand-calc-tok.brand-calc-tok--comment {\n color: var(--calc-comment);\n font-style: italic;\n}\n.brand-calc-tok.brand-calc-tok--unknown {\n color: var(--calc-warning);\n}\n\n/* Non-hue cue for unresolved identifiers / dangling refs — carries the role in\n high-contrast, where hue is flattened. */\n.brand-calc-tok.brand-calc-tok--unresolved {\n text-decoration: underline dotted;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n}\n\n/**\n * WYSIWYG result inlay — a ProseMirror widget after each calc line showing the\n * computed answer. The number IS the signal (shown as text), color is only an\n * enhancement, and it is non-editable / non-selectable so it never enters the\n * document. (The Monaco surface uses Monaco's own inlay hints, themed via the\n * theme bridge's `editorInlayHint.*` colors — not this class.)\n */\n.brand-calc-inlay {\n /* Full strength (no opacity de-emphasis): the result is the answer, and the\n `--calc-result` token is AA-verified at FULL opacity (#221) — reducing it\n would drop effective contrast below what the contrast gate models. */\n margin-inline-start: 1ch;\n color: var(--calc-result);\n font-variant-numeric: tabular-nums;\n user-select: none;\n white-space: pre;\n}\n.brand-calc-inlay--error {\n color: var(--calc-warning);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/markdown-editor/markdown-editor.css","../src/calc-block/calc-editor.css"],"sourcesContent":["/**\n * Token-driven theme for the Milkdown (ProseMirror) WYSIWYG surface.\n *\n * Milkdown core ships ZERO styles (headless), so this is where brand-ui owns the\n * look. Every value is a semantic design token (var(--foreground), --border,\n * --radius, …) — NO raw colors — so the editor matches every theme\n * (light/dark) for free. Every rule\n * is scoped under `.milkdown-host` so nothing leaks globally.\n */\n\n.milkdown-host .ProseMirror {\n /* Suppresses the platform default outline — NOT a bare removal: the\n `:focus-visible` rule below is the replacement, drawn on this same\n element (#309). It owns the indicator unconditionally, so it can't be\n clipped by an ancestor and can't be deleted by a consumer `className`\n reaching `cn()` on the wrapper (`markdown-editor.tsx`'s root `div`\n intentionally carries no focus-ring utility of its own — see #67/#309). */\n outline: none;\n padding: 1rem 1.1rem;\n min-height: 9rem;\n color: var(--foreground);\n font-size: 0.875rem;\n line-height: 1.65;\n caret-color: var(--primary);\n word-break: break-word;\n /* Same reading measure as the preview (max-w-3xl). Driven by the shared scale\n (--md-measure, set via markdownScaleVars) so editor + preview match (#18). */\n max-width: var(--md-measure, 48rem);\n margin-inline: auto;\n}\n\n/* Focus indicator (#309) — a compound two-layer shape mirroring the\n `focus-ring-inset` Tailwind utility (`packages/tokens/src/themes.css`,\n ADR 0027), hand-written because this stylesheet is a plain side-effect CSS\n import resolved by the CONSUMER's bundler — not guaranteed to run through\n Tailwind, so `@apply`/utility classes aren't reachable here (verified:\n `@apply` appears zero times in any .css file in this repo). Drawn INSIDE\n the editable's own box (`outline-offset: -3px`, an inset `box-shadow`), so\n it can't be clipped by an ancestor and survives a consumer `className`\n deleting the wrapper's classes (`MarkdownWorkspace` already does this via\n `className=\"border-0\"`). Two layers of opposite value so at least one edge\n clears 3:1 against the ground whatever `--ring` resolves to in a given\n theme (`--ring-contour` is the dedicated contour token — `themes-contrast.\n test.ts`'s `INDICATOR_SURFACES` locks `max(ring, contour) >= 3:1` at the\n token level; `markdown-editor.stories.tsx`'s `FocusIndicator` play\n re-measures it on this rendered surface, both themes). */\n.milkdown-host .ProseMirror:focus-visible {\n outline: 1px solid var(--ring-contour);\n outline-offset: -3px;\n box-shadow: inset 0 0 0 2px var(--ring);\n}\n\n/* ----------------------------------------------------------------------------\n * Fill height — the editable grows to fill a definite-height parent.\n *\n * Milkdown's host box is otherwise content-sized (the `.ProseMirror` floor below\n * is `min-height: 9rem`), so inside a tall pane a short document leaves a large\n * dead area below the editable AND the caret-anchored `/` slash menu clips inside\n * the short box near the bottom edge. Making `.milkdown-host` a column flex that\n * fills its parent — and letting the intermediate Milkdown wrapper + the\n * ProseMirror surface grow inside it — means the editable fills the pane\n * (clickable everywhere) and the slash menu has room to open / flip.\n *\n * `min-height: 100%` only resolves against a parent with a DEFINITE height (the\n * workspace's `h-full` wysiwyg pane, or any sized container). In an\n * indefinite-height parent it resolves to `auto`, so the standalone / short\n * editor still sizes to its content above the 9rem floor — no regression for the\n * autodocs / inline cases. (elabs-components: editor-fill-height)\n * ------------------------------------------------------------------------- */\n.milkdown-host {\n display: flex;\n flex-direction: column;\n min-height: 100%;\n}\n.milkdown-host > div,\n.milkdown-host .milkdown {\n display: flex;\n min-height: 0;\n flex: 1 1 auto;\n flex-direction: column;\n}\n.milkdown-host .ProseMirror.editor {\n flex: 1 1 auto;\n}\n\n.milkdown-host .ProseMirror > * + * {\n margin-top: 0.7em;\n}\n\n/* Headings — sizes/weight/tracking come from the SHARED markdown scale\n (markdown-scale.ts → --md-* vars on .milkdown-host), so the editor matches the\n prose `Heading` exactly and can't drift on the next edit to either side (#18).\n Fallbacks equal the canonical scale for use without the vars (e.g. clipboard). */\n.milkdown-host .ProseMirror h1,\n.milkdown-host .ProseMirror h2,\n.milkdown-host .ProseMirror h3,\n.milkdown-host .ProseMirror h4,\n.milkdown-host .ProseMirror h5,\n.milkdown-host .ProseMirror h6 {\n font-weight: var(--md-heading-weight, 600);\n letter-spacing: var(--md-heading-tracking, -0.025em);\n line-height: 1.25;\n color: var(--foreground);\n margin-top: 1.1em;\n}\n.milkdown-host .ProseMirror h1 {\n font-size: var(--md-h1, 1.5rem);\n}\n.milkdown-host .ProseMirror h2 {\n font-size: var(--md-h2, 1.25rem);\n}\n.milkdown-host .ProseMirror h3 {\n font-size: var(--md-h3, 1.125rem);\n}\n.milkdown-host .ProseMirror h4 {\n font-size: var(--md-h4, 1rem);\n}\n.milkdown-host .ProseMirror h5 {\n font-size: var(--md-h5, 0.875rem);\n}\n.milkdown-host .ProseMirror h6 {\n font-size: var(--md-h6, 0.875rem);\n color: var(--muted-foreground);\n}\n\n/* Inline */\n.milkdown-host .ProseMirror a {\n color: var(--primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.milkdown-host .ProseMirror strong {\n font-weight: 650;\n}\n.milkdown-host .ProseMirror code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n background: var(--muted);\n color: var(--foreground);\n padding: 0.12em 0.36em;\n border-radius: calc(var(--radius) - 4px);\n}\n\n/* Blocks */\n.milkdown-host .ProseMirror blockquote {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n color: var(--muted-foreground);\n}\n.milkdown-host .ProseMirror pre {\n background: var(--surface-muted);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 0.85rem 1rem;\n overflow: auto;\n}\n.milkdown-host .ProseMirror pre code {\n background: transparent;\n padding: 0;\n font-size: 0.82rem;\n}\n.milkdown-host .ProseMirror hr {\n border: none;\n border-top: 1px solid var(--border);\n margin: 1.25em 0;\n}\n\n/* Lists */\n.milkdown-host .ProseMirror ul,\n.milkdown-host .ProseMirror ol {\n padding-left: 1.4rem;\n}\n.milkdown-host .ProseMirror ul {\n list-style: disc;\n}\n.milkdown-host .ProseMirror ol {\n list-style: decimal;\n}\n.milkdown-host .ProseMirror li > * + * {\n margin-top: 0.35em;\n}\n\n/* Tables (GFM) */\n.milkdown-host .ProseMirror table {\n border-collapse: collapse;\n width: 100%;\n font-size: 0.85rem;\n}\n.milkdown-host .ProseMirror th,\n.milkdown-host .ProseMirror td {\n border: 1px solid var(--border);\n padding: 0.4rem 0.6rem;\n text-align: left;\n}\n.milkdown-host .ProseMirror th {\n background: var(--surface-muted);\n font-weight: 600;\n}\n\n/* Task lists (GFM) */\n.milkdown-host .ProseMirror ul[data-item-type=\"task\"] {\n list-style: none;\n padding-left: 0.25rem;\n}\n\n/* Read-only mode dims the caret affordance */\n.milkdown-host .ProseMirror[contenteditable=\"false\"] {\n caret-color: transparent;\n}\n\n/* ---- Brand `:::` directives ----------------------------------------------------\n * These now render as LIVE @brand React components via @prosemirror-adapter/react\n * (see directive-views.tsx), so the box-model chrome (card/callout/metric borders,\n * fills, type accents) comes from the components themselves — NOT from here. This\n * section only owns what the editor adds on top: outer spacing, the editable-body\n * rhythm, the timeline frame (an editable list, not a derived <Timeline>), and the\n * inline-edit affordance for editable attributes (card/callout title, metric\n * label/value). The `toDOM` defs in directive-nodes.ts keep their own marker classes\n * for clipboard serialization but are not visually rendered while node-views are on.\n */\n.milkdown-host .brand-directive {\n margin: 0.85em 0;\n}\n.milkdown-host .brand-directive__body > * + * {\n margin-top: 0.6em;\n}\n/* The first/last editable block inside a card/callout shouldn't add stray margin\n * on top of the component's own padding. */\n.milkdown-host .brand-directive__body > :first-child {\n margin-top: 0;\n}\n\n/* timeline → keep the list editable inside a subtle frame */\n.milkdown-host .brand-directive--timeline {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n}\n\n/* Inline-editable directive attribute (seamless, caret-friendly). */\n.milkdown-host .brand-inline-edit {\n cursor: text;\n min-width: 1ch;\n /* inherit the surrounding component's type (CardTitle, MetricBlock label/value) */\n font: inherit;\n color: inherit;\n letter-spacing: inherit;\n}\n.milkdown-host .brand-inline-edit:empty::before {\n content: attr(data-placeholder);\n color: var(--muted-foreground);\n opacity: 0.65;\n pointer-events: none;\n}\n\n/* ------------------------------------------------------------------------- */\n/* Focus writing (Ulysses Phase A): under a `[data-focus-writing]` ancestor */\n/* (the workspace's wysiwyg pane), every top-level block dims except the one */\n/* owning the selection (`.wb-fw-active`, set by the workspace) — paragraph */\n/* focus. Hover un-dims for mouse repositioning. Token-driven, motion-safe. */\n/* ------------------------------------------------------------------------- */\n[data-focus-writing] .milkdown-host .ProseMirror > * {\n opacity: 0.35;\n transition: opacity var(--t-base, 200ms) var(--ease-standard, ease);\n}\n[data-focus-writing] .milkdown-host .ProseMirror > .wb-fw-active,\n[data-focus-writing] .milkdown-host .ProseMirror > *:hover {\n opacity: 1;\n}\n@media (prefers-reduced-motion: reduce) {\n [data-focus-writing] .milkdown-host .ProseMirror > * {\n transition: none;\n }\n}\n","/**\n * Calc authoring decorations (#220) — shared by the Monaco source surface\n * (decoration `inlineClassName`) and the Milkdown WYSIWYG surface (ProseMirror\n * inline decorations + result-inlay widgets).\n *\n * Colors come from the `--calc-*` syntax tokens — the SAME tokens `CalcBlock`\n * paints with (#221), already AA-verified against `--background` (the editor\n * surface) and `--card` in every theme — so highlighting tracks the theme via\n * the cascade with no hardcoded hex. The compound `.brand-calc-tok.brand-calc-tok--x`\n * selector raises specificity above Monaco's own token color class (`.mtkN`) so\n * the calc color wins regardless of stylesheet load order (no `!important`).\n *\n * Hue is never the SOLE cue (var-def = weight, unresolved = dotted underline), so\n * roles stay distinct in the high-contrast theme where the calc colors collapse\n * toward the foreground — mirroring `CalcBlock.tokenClass`.\n */\n\n.brand-calc-tok.brand-calc-tok--number,\n.brand-calc-tok.brand-calc-tok--constant {\n color: var(--calc-number);\n}\n.brand-calc-tok.brand-calc-tok--unit {\n color: var(--calc-unit);\n}\n.brand-calc-tok.brand-calc-tok--currency {\n color: var(--calc-currency);\n}\n.brand-calc-tok.brand-calc-tok--operator {\n color: var(--calc-operator);\n}\n.brand-calc-tok.brand-calc-tok--function {\n color: var(--calc-function);\n}\n.brand-calc-tok.brand-calc-tok--var-ref {\n color: var(--calc-variable);\n}\n.brand-calc-tok.brand-calc-tok--var-def {\n color: var(--calc-variable);\n font-weight: 500;\n}\n.brand-calc-tok.brand-calc-tok--line-ref {\n color: var(--calc-reference);\n font-variant-numeric: tabular-nums;\n}\n.brand-calc-tok.brand-calc-tok--comment {\n color: var(--calc-comment);\n font-style: italic;\n}\n.brand-calc-tok.brand-calc-tok--unknown {\n color: var(--calc-warning);\n}\n\n/* Non-hue cue for unresolved identifiers / dangling refs — carries the role in\n high-contrast, where hue is flattened. */\n.brand-calc-tok.brand-calc-tok--unresolved {\n text-decoration: underline dotted;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n}\n\n/**\n * WYSIWYG result inlay — a ProseMirror widget after each calc line showing the\n * computed answer. The number IS the signal (shown as text), color is only an\n * enhancement, and it is non-editable / non-selectable so it never enters the\n * document. (The Monaco surface uses Monaco's own inlay hints, themed via the\n * theme bridge's `editorInlayHint.*` colors — not this class.)\n */\n.brand-calc-inlay {\n /* Full strength (no opacity de-emphasis): the result is the answer, and the\n `--calc-result` token is AA-verified at FULL opacity (#221) — reducing it\n would drop effective contrast below what the contrast gate models. */\n margin-inline-start: 1ch;\n color: var(--calc-result);\n font-variant-numeric: tabular-nums;\n user-select: none;\n white-space: pre;\n}\n.brand-calc-inlay--error {\n color: var(--calc-warning);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as EditorContentAccess, M as MonacoCodeEditor } from './markdown-editor-
|
|
2
|
-
export { C as CodeEditor, a as CodeEditorProps, b as EditorAction, c as EditorSelection, d as EmbedAssetFn, e as MarkdownEditor, f as MarkdownEditorHandle, g as MarkdownEditorProps, m as monacoContentAccess } from './markdown-editor-
|
|
1
|
+
import { E as EditorContentAccess, M as MonacoCodeEditor } from './markdown-editor-CBp_4eDv.js';
|
|
2
|
+
export { C as CodeEditor, a as CodeEditorProps, b as EditorAction, c as EditorSelection, d as EmbedAssetFn, e as MarkdownEditor, f as MarkdownEditorHandle, g as MarkdownEditorProps, m as monacoContentAccess } from './markdown-editor-CBp_4eDv.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { HTMLAttributes, ReactNode, ComponentProps } from 'react';
|
|
5
5
|
import * as monaco from 'monaco-editor';
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
buildBrandThemeData,
|
|
11
11
|
monacoContentAccess,
|
|
12
12
|
useDataTheme
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-C62O7IOQ.js";
|
|
14
14
|
|
|
15
15
|
// src/diff-editor/diff-editor.tsx
|
|
16
16
|
import * as monaco from "monaco-editor";
|
|
@@ -116,7 +116,7 @@ var DiffEditor = forwardRef(function DiffEditor2({
|
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
// src/code-workspace/code-workspace.tsx
|
|
119
|
-
import { Tabs, TabsList, TabsTrigger } from "@elabs-ai/components-ui";
|
|
119
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@elabs-ai/components-ui";
|
|
120
120
|
import { cn as cn2 } from "@elabs-ai/components-ui/lib/cn";
|
|
121
121
|
import {
|
|
122
122
|
forwardRef as forwardRef2,
|
|
@@ -150,6 +150,13 @@ var EXT_LANGUAGE = {
|
|
|
150
150
|
sh: "shell"
|
|
151
151
|
};
|
|
152
152
|
var basename = (path) => path.split("/").pop() || path;
|
|
153
|
+
function tabIdForFile(path) {
|
|
154
|
+
let out = "";
|
|
155
|
+
for (const char of path) {
|
|
156
|
+
out += /[A-Za-z0-9-]/.test(char) ? char : `_${char.codePointAt(0).toString(16)}_`;
|
|
157
|
+
}
|
|
158
|
+
return `tab-${out}`;
|
|
159
|
+
}
|
|
153
160
|
function inferLanguage(file) {
|
|
154
161
|
if (file.language) return file.language;
|
|
155
162
|
const ext = file.path.split(".").pop()?.toLowerCase() ?? "";
|
|
@@ -181,6 +188,8 @@ var CodeWorkspace = forwardRef2(
|
|
|
181
188
|
const requested = isControlled ? activePath : internalActive;
|
|
182
189
|
const activeFile = files.find((f) => f.path === requested) ?? files[0];
|
|
183
190
|
const active = activeFile?.path ?? "";
|
|
191
|
+
const tabs = files.map((file) => ({ file, id: tabIdForFile(file.path) }));
|
|
192
|
+
const activeTabId = tabs.find((t) => t.file.path === active)?.id ?? "";
|
|
184
193
|
const rootRef = useRef2(null);
|
|
185
194
|
const [activeEditor, setActiveEditor] = useState2(null);
|
|
186
195
|
useEffect2(() => {
|
|
@@ -236,35 +245,63 @@ var CodeWorkspace = forwardRef2(
|
|
|
236
245
|
children: /* @__PURE__ */ jsxs(
|
|
237
246
|
Tabs,
|
|
238
247
|
{
|
|
239
|
-
value:
|
|
240
|
-
onValueChange:
|
|
248
|
+
value: activeTabId,
|
|
249
|
+
onValueChange: (id) => {
|
|
250
|
+
const found = tabs.find((t) => t.id === id);
|
|
251
|
+
if (found) selectTab(found.file.path);
|
|
252
|
+
},
|
|
241
253
|
className: "flex min-h-0 flex-1 flex-col gap-0",
|
|
242
254
|
children: [
|
|
243
255
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center border-b border-border bg-surface", children: [
|
|
244
|
-
/* @__PURE__ */ jsx2(TabsList, { className: "h-9 flex-1 justify-start gap-0 rounded-none bg-transparent p-0", children:
|
|
256
|
+
/* @__PURE__ */ jsx2(TabsList, { className: "h-9 flex-1 justify-start gap-0 rounded-none bg-transparent p-0", children: tabs.map(({ file, id }) => /* @__PURE__ */ jsx2(
|
|
245
257
|
TabsTrigger,
|
|
246
258
|
{
|
|
247
|
-
value:
|
|
259
|
+
value: id,
|
|
248
260
|
className: "h-9 rounded-none border-e border-border px-3 text-xs data-[state=active]:bg-background data-[state=active]:shadow-none",
|
|
249
261
|
children: basename(file.path)
|
|
250
262
|
},
|
|
251
|
-
|
|
263
|
+
id
|
|
252
264
|
)) }),
|
|
253
265
|
activeFile ? /* @__PURE__ */ jsx2(CopyButton, { value: activeFile.value, className: "me-1.5" }) : null
|
|
254
266
|
] }),
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
267
|
+
tabs.map(({ file, id }) => {
|
|
268
|
+
const isActive = file.path === activeFile?.path;
|
|
269
|
+
return (
|
|
270
|
+
// `forceMount` keeps every tab's content in the DOM so each
|
|
271
|
+
// trigger's `aria-controls` resolves to a real element, not only
|
|
272
|
+
// the active one (#154). Radix derives its own `hidden` from
|
|
273
|
+
// `forceMount || isSelected`, so under `forceMount` it hides
|
|
274
|
+
// NOTHING: without the explicit `hidden` below every inactive
|
|
275
|
+
// panel stays a visible `flex-1` child and the editor height is
|
|
276
|
+
// split across all of them. `tabIndex={-1}` keeps the empty
|
|
277
|
+
// panels out of the tab sequence for the same reason. Only the
|
|
278
|
+
// active file mounts a (single) Monaco instance.
|
|
279
|
+
/* @__PURE__ */ jsx2(
|
|
280
|
+
TabsContent,
|
|
281
|
+
{
|
|
282
|
+
value: id,
|
|
283
|
+
forceMount: true,
|
|
284
|
+
hidden: !isActive,
|
|
285
|
+
tabIndex: isActive ? 0 : -1,
|
|
286
|
+
className: "mt-0 min-h-0 flex-1",
|
|
287
|
+
children: isActive ? /* @__PURE__ */ jsx2(
|
|
288
|
+
CodeEditor,
|
|
289
|
+
{
|
|
290
|
+
path: file.path,
|
|
291
|
+
language: inferLanguage(file),
|
|
292
|
+
value: file.value,
|
|
293
|
+
readOnly,
|
|
294
|
+
onChange: (next) => onFileChange?.(file.path, next),
|
|
295
|
+
onMount: (editor2) => setActiveEditor(editor2),
|
|
296
|
+
height: "100%"
|
|
297
|
+
},
|
|
298
|
+
file.path
|
|
299
|
+
) : null
|
|
300
|
+
},
|
|
301
|
+
id
|
|
302
|
+
)
|
|
303
|
+
);
|
|
304
|
+
})
|
|
268
305
|
]
|
|
269
306
|
}
|
|
270
307
|
)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/diff-editor/diff-editor.tsx","../src/code-workspace/code-workspace.tsx","../src/editor-toolbar/editor-toolbar.tsx","../src/lib/languages.ts","../src/index.ts"],"sourcesContent":["\"use client\";\n\nimport * as monaco from \"monaco-editor\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n} from \"react\";\nimport { applyBrandTheme } from \"../lib/monaco-theme-bridge\";\nimport { useDataTheme } from \"../lib/use-data-theme\";\n\nexport type MonacoDiffEditor = monaco.editor.IStandaloneDiffEditor;\n\nexport interface DiffEditorProps extends Omit<HTMLAttributes<HTMLDivElement>, \"defaultValue\"> {\n /** Left/original document. */\n original: string;\n /** Right/modified document. */\n modified: string;\n /** Monaco language id applied to both sides. Defaults to \"typescript\". */\n language?: string;\n /** Read-only (diffs are read-only by default). */\n readOnly?: boolean;\n /** Side-by-side (true) vs inline (false) diff. Defaults to side-by-side. */\n renderSideBySide?: boolean;\n /** Editor height. Number → px. Defaults to \"100%\". */\n height?: number | string;\n /** Passthrough Monaco diff options (merged over the defaults). */\n options?: monaco.editor.IStandaloneDiffEditorConstructionOptions;\n /** Called once the diff editor + monaco namespace are ready. */\n onMount?: (editor: MonacoDiffEditor, monacoApi: typeof monaco) => void;\n}\n\nconst BASE_OPTIONS: monaco.editor.IStandaloneDiffEditorConstructionOptions = {\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n fontSize: 13,\n ignoreTrimWhitespace: false,\n padding: { top: 12, bottom: 12 },\n scrollbar: { verticalScrollbarSize: 10, horizontalScrollbarSize: 10 },\n};\n\n/**\n * A token-themed Monaco diff editor (original ↔ modified). Same theming bridge\n * and chrome story as {@link CodeEditor}; reads as a side-by-side or inline diff.\n */\nexport const DiffEditor = forwardRef<MonacoDiffEditor | null, DiffEditorProps>(function DiffEditor(\n {\n original,\n modified,\n language = \"typescript\",\n readOnly = true,\n renderSideBySide = true,\n height = \"100%\",\n options,\n onMount,\n className,\n style,\n ...props\n },\n ref,\n) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [editor, setEditor] = useState<MonacoDiffEditor | null>(null);\n const { theme, revision } = useDataTheme();\n\n const onMountRef = useRef(onMount);\n onMountRef.current = onMount;\n\n useImperativeHandle<MonacoDiffEditor | null, MonacoDiffEditor | null>(ref, () => editor, [\n editor,\n ]);\n\n // Mount once.\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const instance = monaco.editor.createDiffEditor(container, {\n ...BASE_OPTIONS,\n readOnly,\n renderSideBySide,\n ...options,\n });\n const originalModel = monaco.editor.createModel(original, language);\n const modifiedModel = monaco.editor.createModel(modified, language);\n instance.setModel({ original: originalModel, modified: modifiedModel });\n // Theme is applied by the effect below once `setEditor` runs.\n setEditor(instance);\n onMountRef.current?.(instance, monaco);\n\n return () => {\n instance.dispose();\n originalModel.dispose();\n modifiedModel.dispose();\n setEditor(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n const original_ = editor?.getModel()?.original;\n if (original_ && original_.getValue() !== original) original_.setValue(original);\n }, [editor, original]);\n\n useEffect(() => {\n const modified_ = editor?.getModel()?.modified;\n if (modified_ && modified_.getValue() !== modified) modified_.setValue(modified);\n }, [editor, modified]);\n\n useEffect(() => {\n const models = editor?.getModel();\n if (!models) return;\n monaco.editor.setModelLanguage(models.original, language);\n monaco.editor.setModelLanguage(models.modified, language);\n }, [editor, language]);\n\n useEffect(() => {\n editor?.updateOptions({ readOnly, renderSideBySide });\n }, [editor, readOnly, renderSideBySide]);\n\n useEffect(() => {\n if (!editor) return;\n try {\n applyBrandTheme(monaco, theme);\n } catch (err) {\n console.error(\"[@elabs-ai/components-editor] failed to apply brand theme\", err);\n }\n // `revision` re-applies once the data-theme attribute settles. See CodeEditor.\n }, [editor, theme, revision]);\n\n const resolvedStyle: CSSProperties = {\n height: typeof height === \"number\" ? `${height}px` : height,\n ...style,\n };\n\n return (\n <div\n ref={containerRef}\n data-testid=\"diff-editor\"\n className={cn(\"h-full w-full overflow-hidden bg-background text-foreground\", className)}\n style={resolvedStyle}\n {...props}\n />\n );\n});\n","\"use client\";\n\nimport { Tabs, TabsList, TabsTrigger } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n} from \"react\";\nimport { CodeEditor, type MonacoCodeEditor } from \"../code-editor\";\nimport { CopyButton } from \"../copy-button\";\nimport {\n monacoContentAccess,\n type EditorContentAccess,\n type EditorSelection,\n} from \"../lib/editor-content-access\";\n\nexport interface EditorFile {\n /** Unique path/name; shown (basename) on the tab and used as the model path. */\n path: string;\n /** Monaco language id. Inferred from the extension when omitted. */\n language?: string;\n /** File content. */\n value: string;\n}\n\nexport interface CodeWorkspaceProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\" | \"defaultValue\"\n> {\n /** Open files, one tab each. */\n files: EditorFile[];\n /** Controlled active file path. */\n activePath?: string;\n /** Initial active path for uncontrolled use. Defaults to the first file. */\n defaultActivePath?: string;\n /** Called when the active tab changes. */\n onActivePathChange?: (path: string) => void;\n /** Called on every edit with the file path + new content. */\n onFileChange?: (path: string, value: string) => void;\n /** Render all files read-only. */\n readOnly?: boolean;\n /** Workspace height. Number → px. Defaults to \"100%\". */\n height?: number | string;\n}\n\nconst EXT_LANGUAGE: Record<string, string> = {\n ts: \"typescript\",\n tsx: \"typescript\",\n mts: \"typescript\",\n cts: \"typescript\",\n js: \"javascript\",\n jsx: \"javascript\",\n mjs: \"javascript\",\n cjs: \"javascript\",\n json: \"json\",\n css: \"css\",\n scss: \"scss\",\n less: \"less\",\n html: \"html\",\n md: \"markdown\",\n py: \"python\",\n sql: \"sql\",\n yml: \"yaml\",\n yaml: \"yaml\",\n xml: \"xml\",\n sh: \"shell\",\n};\n\nconst basename = (path: string) => path.split(\"/\").pop() || path;\n\nfunction inferLanguage(file: EditorFile): string {\n if (file.language) return file.language;\n const ext = file.path.split(\".\").pop()?.toLowerCase() ?? \"\";\n return EXT_LANGUAGE[ext] ?? \"plaintext\";\n}\n\n/**\n * Imperative handle exposed via `CodeWorkspace`'s `ref`.\n *\n * **Migration note:** the forwarded `ref` type changed from `HTMLDivElement` to\n * `CodeWorkspaceHandle` (mirrors the #273 `MarkdownWorkspaceHandle` precedent).\n * Replace any `ref.current` / `ref.current.scrollIntoView()` DOM access with\n * `ref.current?.getElement()`. This is the only breaking change in this work.\n */\nexport interface CodeWorkspaceHandle extends EditorContentAccess {\n /**\n * The live Monaco editor for the currently active tab, or `null` while booting\n * or when no files are open. Consumers needing the full Monaco API can use this\n * and pass it to `monacoContentAccess(handle.getActiveEditor()!)`.\n */\n getActiveEditor(): MonacoCodeEditor | null;\n /**\n * The workspace root DOM element. Preserves the old `HTMLDivElement` ref access\n * that existed before the ref-type change (#273 `MarkdownWorkspace` playbook).\n */\n getElement(): HTMLDivElement | null;\n}\n\n/** No-op EditorContentAccess returned when no Monaco editor is mounted. */\nconst NULL_ACCESS: EditorContentAccess = {\n getText: () => \"\",\n getSelection: () => ({ text: \"\", empty: true }),\n replaceSelection: () => undefined,\n insertAtCursor: () => undefined,\n focus: () => undefined,\n onSelectionChange: () => () => undefined,\n};\n\n/**\n * Multi-file editor shell: brand-ui `Tabs` for the file bar above a single\n * {@link CodeEditor} that swaps to the active file. This is the \"reuse our\n * components for the chrome\" surface — Tabs/Button are ours; the editing surface\n * is Monaco. Edits bubble through `onFileChange`.\n *\n * The forwarded `ref` exposes a {@link CodeWorkspaceHandle} (not `HTMLDivElement`).\n * Use `ref.current?.getElement()` to access the root DOM node.\n */\nexport const CodeWorkspace = forwardRef<CodeWorkspaceHandle, CodeWorkspaceProps>(\n function CodeWorkspace(\n {\n files,\n activePath,\n defaultActivePath,\n onActivePathChange,\n onFileChange,\n readOnly = false,\n height = \"100%\",\n className,\n style,\n ...props\n },\n ref,\n ) {\n const [internalActive, setInternalActive] = useState(defaultActivePath ?? files[0]?.path ?? \"\");\n const isControlled = activePath !== undefined;\n const requested = isControlled ? activePath : internalActive;\n const activeFile = files.find((f) => f.path === requested) ?? files[0];\n const active = activeFile?.path ?? \"\";\n\n // The root div ref (getElement() preserves old HTMLDivElement access).\n const rootRef = useRef<HTMLDivElement | null>(null);\n\n // The live Monaco editor for the active tab. Nulled when there is no active file.\n const [activeEditor, setActiveEditor] = useState<MonacoCodeEditor | null>(null);\n\n // Defensive: if the active file is removed (no `activeFile`), null the held instance\n // so getActiveEditor() and content-access methods don't act on a disposed editor.\n useEffect(() => {\n if (!activeFile) setActiveEditor(null);\n }, [activeFile]);\n\n // A STABLE listener set for onSelectionChange. The handle adds/removes here;\n // the binding effect below forwards the ACTIVE editor's selection changes into\n // it. This is what makes a subscribe-in-mount-effect survive the editor's async\n // mount (and tab swaps): the consumer subscribes once; binding re-attaches as\n // `activeEditor` changes. (Delegating onSelectionChange to a call-time snapshot\n // would bind to the not-yet-mounted editor and silently never fire.)\n const [selectionListeners] = useState(() => new Set<(sel: EditorSelection) => void>());\n useEffect(() => {\n if (!activeEditor) return;\n const unsub = monacoContentAccess(activeEditor).onSelectionChange((sel) =>\n selectionListeners.forEach((l) => l(sel)),\n );\n return unsub;\n }, [activeEditor, selectionListeners]);\n\n const selectTab = useCallback(\n (path: string) => {\n if (!isControlled) setInternalActive(path);\n onActivePathChange?.(path);\n },\n [isControlled, onActivePathChange],\n );\n\n useImperativeHandle(ref, () => {\n const access = activeEditor ? monacoContentAccess(activeEditor) : NULL_ACCESS;\n return {\n getActiveEditor: () => activeEditor,\n getElement: () => rootRef.current,\n getText: () => access.getText(),\n getSelection: () => access.getSelection(),\n replaceSelection: (text: string) => access.replaceSelection(text),\n insertAtCursor: (text: string) => access.insertAtCursor(text),\n focus: () => access.focus(),\n // Stable set (not the call-time `access`) so a subscription survives the\n // editor's async mount + tab swaps; the binding effect forwards events.\n onSelectionChange: (listener) => {\n selectionListeners.add(listener);\n return () => selectionListeners.delete(listener);\n },\n };\n }, [activeEditor, selectionListeners]);\n\n const resolvedStyle: CSSProperties = {\n height: typeof height === \"number\" ? `${height}px` : height,\n ...style,\n };\n\n return (\n <div\n ref={rootRef}\n className={cn(\n \"flex flex-col overflow-hidden rounded-lg border border-border bg-surface\",\n className,\n )}\n style={resolvedStyle}\n {...props}\n >\n <Tabs\n value={active}\n onValueChange={selectTab}\n className=\"flex min-h-0 flex-1 flex-col gap-0\"\n >\n <div className=\"flex items-center border-b border-border bg-surface\">\n <TabsList className=\"h-9 flex-1 justify-start gap-0 rounded-none bg-transparent p-0\">\n {files.map((file) => (\n <TabsTrigger\n key={file.path}\n value={file.path}\n className=\"h-9 rounded-none border-e border-border px-3 text-xs data-[state=active]:bg-background data-[state=active]:shadow-none\"\n >\n {basename(file.path)}\n </TabsTrigger>\n ))}\n </TabsList>\n {activeFile ? <CopyButton value={activeFile.value} className=\"me-1.5\" /> : null}\n </div>\n\n <div className=\"min-h-0 flex-1\">\n {activeFile ? (\n <CodeEditor\n key={activeFile.path}\n path={activeFile.path}\n language={inferLanguage(activeFile)}\n value={activeFile.value}\n readOnly={readOnly}\n onChange={(next) => onFileChange?.(activeFile.path, next)}\n onMount={(editor) => setActiveEditor(editor)}\n height=\"100%\"\n />\n ) : null}\n </div>\n </Tabs>\n </div>\n );\n },\n);\n","\"use client\";\n\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\nimport { CopyButton } from \"../copy-button\";\nimport { EDITOR_LANGUAGES, type EditorLanguage } from \"../lib/languages\";\n\nexport interface EditorToolbarProps extends HTMLAttributes<HTMLDivElement> {\n /** Filename shown on the left (e.g. \"index.ts\"). */\n filename?: ReactNode;\n /** Active language id; shows a language picker when `onLanguageChange` is set. */\n language?: string;\n /** Called when the user picks a language. Omit to hide the picker. */\n onLanguageChange?: (language: string) => void;\n /** Languages offered in the picker. Defaults to {@link EDITOR_LANGUAGES}. */\n languages?: EditorLanguage[];\n /** Text copied by the copy button. Omit to hide the button. */\n copyValue?: string;\n /** Extra actions rendered before the copy button (brand-ui buttons, etc.). */\n actions?: ReactNode;\n}\n\n/**\n * Brand-ui chrome for the editors — the part that genuinely reuses our\n * components. Renders a filename label, an optional language `Select` and a copy\n * `Button`. The editing surface itself is Monaco; this is the frame around it.\n */\nexport const EditorToolbar = forwardRef<HTMLDivElement, EditorToolbarProps>(function EditorToolbar(\n {\n filename,\n language,\n onLanguageChange,\n languages = EDITOR_LANGUAGES,\n copyValue,\n actions,\n className,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex h-10 shrink-0 items-center gap-2 border-b border-border bg-surface px-3\",\n className,\n )}\n {...props}\n >\n {filename != null ? (\n <span className=\"truncate text-sm font-medium text-foreground\">{filename}</span>\n ) : null}\n\n <div className=\"ml-auto flex items-center gap-1.5\">\n {actions}\n\n {onLanguageChange ? (\n <Select value={language} onValueChange={onLanguageChange}>\n <SelectTrigger size=\"sm\" className=\"h-7 w-[140px]\" aria-label=\"Language\">\n <SelectValue placeholder=\"Language\" />\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l.id} value={l.id}>\n {l.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : null}\n\n {copyValue != null ? <CopyButton value={copyValue} /> : null}\n </div>\n </div>\n );\n});\n","/**\n * Curated language list for the editor toolbar's language picker. Ids are\n * Monaco's built-in language ids (`monaco.languages.getLanguages()`), so they\n * map straight onto `setModelLanguage` / model creation.\n */\nexport interface EditorLanguage {\n /** Monaco language id (e.g. \"typescript\"). */\n id: string;\n /** Human-readable label for the picker. */\n label: string;\n}\n\nexport const EDITOR_LANGUAGES: EditorLanguage[] = [\n { id: \"typescript\", label: \"TypeScript\" },\n { id: \"javascript\", label: \"JavaScript\" },\n { id: \"json\", label: \"JSON\" },\n { id: \"html\", label: \"HTML\" },\n { id: \"css\", label: \"CSS\" },\n { id: \"scss\", label: \"SCSS\" },\n { id: \"markdown\", label: \"Markdown\" },\n { id: \"python\", label: \"Python\" },\n { id: \"sql\", label: \"SQL\" },\n { id: \"yaml\", label: \"YAML\" },\n { id: \"xml\", label: \"XML\" },\n { id: \"shell\", label: \"Shell\" },\n { id: \"plaintext\", label: \"Plain text\" },\n];\n\n/** Look up a language's label, falling back to the raw id. */\nexport function languageLabel(id: string): string {\n return EDITOR_LANGUAGES.find((l) => l.id === id)?.label ?? id;\n}\n","/**\n * @elabs-ai/components-editor — a token-themed Monaco (VS Code) editor wrapped as brand-ui\n * components.\n *\n * Monaco is a self-rendering editor engine; this package wraps it the way\n * @elabs-ai/components-flow wraps React Flow and @elabs-ai/components-data wraps TanStack. The editing\n * surface + widgets are Monaco's, recolored from the active brand theme via the\n * theming bridge; the chrome (toolbar, file tabs, copy button) is brand-ui.\n *\n * Worker setup (for completions/diagnostics) — import ONCE at the app entry:\n * import \"@elabs-ai/components-editor/monaco-environment\"; // Vite apps\n */\nexport {\n CodeEditor,\n type CodeEditorProps,\n type MonacoCodeEditor,\n type EditorAction,\n} from \"./code-editor\";\nexport { DiffEditor, type DiffEditorProps, type MonacoDiffEditor } from \"./diff-editor\";\nexport {\n MarkdownEditor,\n type MarkdownEditorProps,\n type MarkdownEditorHandle,\n type EmbedAssetFn,\n} from \"./markdown-editor\";\nexport {\n CodeWorkspace,\n type CodeWorkspaceHandle,\n type CodeWorkspaceProps,\n type EditorFile,\n} from \"./code-workspace\";\nexport {\n monacoContentAccess,\n type EditorContentAccess,\n type EditorSelection,\n} from \"./lib/editor-content-access\";\nexport { EditorToolbar, type EditorToolbarProps } from \"./editor-toolbar\";\nexport { EditorContextMenu, type EditorContextMenuProps } from \"./editor-context-menu\";\nexport { CopyButton, type CopyButtonProps } from \"./copy-button\";\n\n// Theming bridge + language helpers (advanced consumers / custom chrome).\nexport { applyBrandTheme, buildBrandThemeData, brandThemeId } from \"./lib/monaco-theme-bridge\";\nexport { useDataTheme, type DataThemeState } from \"./lib/use-data-theme\";\nexport { EDITOR_LANGUAGES, languageLabel, type EditorLanguage } from \"./lib/languages\";\n\n// Re-export the monaco namespace so consumers can build custom editors / wire\n// commands without adding a direct dependency.\nexport * as monaco from \"monaco-editor\";\n"],"mappings":"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","names":["DiffEditor","editor","cn","forwardRef","useEffect","useImperativeHandle","useRef","useState","jsx","forwardRef","CodeWorkspace","useState","useRef","useEffect","useImperativeHandle","cn","editor","cn","forwardRef","jsx","jsxs","forwardRef","EditorToolbar","cn","monaco"]}
|
|
1
|
+
{"version":3,"sources":["../src/diff-editor/diff-editor.tsx","../src/code-workspace/code-workspace.tsx","../src/editor-toolbar/editor-toolbar.tsx","../src/lib/languages.ts","../src/index.ts"],"sourcesContent":["\"use client\";\n\nimport * as monaco from \"monaco-editor\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n} from \"react\";\nimport { applyBrandTheme } from \"../lib/monaco-theme-bridge\";\nimport { useDataTheme } from \"../lib/use-data-theme\";\n\nexport type MonacoDiffEditor = monaco.editor.IStandaloneDiffEditor;\n\nexport interface DiffEditorProps extends Omit<HTMLAttributes<HTMLDivElement>, \"defaultValue\"> {\n /** Left/original document. */\n original: string;\n /** Right/modified document. */\n modified: string;\n /** Monaco language id applied to both sides. Defaults to \"typescript\". */\n language?: string;\n /** Read-only (diffs are read-only by default). */\n readOnly?: boolean;\n /** Side-by-side (true) vs inline (false) diff. Defaults to side-by-side. */\n renderSideBySide?: boolean;\n /** Editor height. Number → px. Defaults to \"100%\". */\n height?: number | string;\n /** Passthrough Monaco diff options (merged over the defaults). */\n options?: monaco.editor.IStandaloneDiffEditorConstructionOptions;\n /** Called once the diff editor + monaco namespace are ready. */\n onMount?: (editor: MonacoDiffEditor, monacoApi: typeof monaco) => void;\n}\n\nconst BASE_OPTIONS: monaco.editor.IStandaloneDiffEditorConstructionOptions = {\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n fontSize: 13,\n ignoreTrimWhitespace: false,\n padding: { top: 12, bottom: 12 },\n scrollbar: { verticalScrollbarSize: 10, horizontalScrollbarSize: 10 },\n};\n\n/**\n * A token-themed Monaco diff editor (original ↔ modified). Same theming bridge\n * and chrome story as {@link CodeEditor}; reads as a side-by-side or inline diff.\n */\nexport const DiffEditor = forwardRef<MonacoDiffEditor | null, DiffEditorProps>(function DiffEditor(\n {\n original,\n modified,\n language = \"typescript\",\n readOnly = true,\n renderSideBySide = true,\n height = \"100%\",\n options,\n onMount,\n className,\n style,\n ...props\n },\n ref,\n) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [editor, setEditor] = useState<MonacoDiffEditor | null>(null);\n const { theme, revision } = useDataTheme();\n\n const onMountRef = useRef(onMount);\n onMountRef.current = onMount;\n\n useImperativeHandle<MonacoDiffEditor | null, MonacoDiffEditor | null>(ref, () => editor, [\n editor,\n ]);\n\n // Mount once.\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const instance = monaco.editor.createDiffEditor(container, {\n ...BASE_OPTIONS,\n readOnly,\n renderSideBySide,\n ...options,\n });\n const originalModel = monaco.editor.createModel(original, language);\n const modifiedModel = monaco.editor.createModel(modified, language);\n instance.setModel({ original: originalModel, modified: modifiedModel });\n // Theme is applied by the effect below once `setEditor` runs.\n setEditor(instance);\n onMountRef.current?.(instance, monaco);\n\n return () => {\n instance.dispose();\n originalModel.dispose();\n modifiedModel.dispose();\n setEditor(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n const original_ = editor?.getModel()?.original;\n if (original_ && original_.getValue() !== original) original_.setValue(original);\n }, [editor, original]);\n\n useEffect(() => {\n const modified_ = editor?.getModel()?.modified;\n if (modified_ && modified_.getValue() !== modified) modified_.setValue(modified);\n }, [editor, modified]);\n\n useEffect(() => {\n const models = editor?.getModel();\n if (!models) return;\n monaco.editor.setModelLanguage(models.original, language);\n monaco.editor.setModelLanguage(models.modified, language);\n }, [editor, language]);\n\n useEffect(() => {\n editor?.updateOptions({ readOnly, renderSideBySide });\n }, [editor, readOnly, renderSideBySide]);\n\n useEffect(() => {\n if (!editor) return;\n try {\n applyBrandTheme(monaco, theme);\n } catch (err) {\n console.error(\"[@elabs-ai/components-editor] failed to apply brand theme\", err);\n }\n // `revision` re-applies once the data-theme attribute settles. See CodeEditor.\n }, [editor, theme, revision]);\n\n const resolvedStyle: CSSProperties = {\n height: typeof height === \"number\" ? `${height}px` : height,\n ...style,\n };\n\n return (\n <div\n ref={containerRef}\n data-testid=\"diff-editor\"\n className={cn(\"h-full w-full overflow-hidden bg-background text-foreground\", className)}\n style={resolvedStyle}\n {...props}\n />\n );\n});\n","\"use client\";\n\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n} from \"react\";\nimport { CodeEditor, type MonacoCodeEditor } from \"../code-editor\";\nimport { CopyButton } from \"../copy-button\";\nimport {\n monacoContentAccess,\n type EditorContentAccess,\n type EditorSelection,\n} from \"../lib/editor-content-access\";\n\nexport interface EditorFile {\n /** Unique path/name; shown (basename) on the tab and used as the model path. */\n path: string;\n /** Monaco language id. Inferred from the extension when omitted. */\n language?: string;\n /** File content. */\n value: string;\n}\n\nexport interface CodeWorkspaceProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\" | \"defaultValue\"\n> {\n /** Open files, one tab each. */\n files: EditorFile[];\n /** Controlled active file path. */\n activePath?: string;\n /** Initial active path for uncontrolled use. Defaults to the first file. */\n defaultActivePath?: string;\n /** Called when the active tab changes. */\n onActivePathChange?: (path: string) => void;\n /** Called on every edit with the file path + new content. */\n onFileChange?: (path: string, value: string) => void;\n /** Render all files read-only. */\n readOnly?: boolean;\n /** Workspace height. Number → px. Defaults to \"100%\". */\n height?: number | string;\n}\n\nconst EXT_LANGUAGE: Record<string, string> = {\n ts: \"typescript\",\n tsx: \"typescript\",\n mts: \"typescript\",\n cts: \"typescript\",\n js: \"javascript\",\n jsx: \"javascript\",\n mjs: \"javascript\",\n cjs: \"javascript\",\n json: \"json\",\n css: \"css\",\n scss: \"scss\",\n less: \"less\",\n html: \"html\",\n md: \"markdown\",\n py: \"python\",\n sql: \"sql\",\n yml: \"yaml\",\n yaml: \"yaml\",\n xml: \"xml\",\n sh: \"shell\",\n};\n\nconst basename = (path: string) => path.split(\"/\").pop() || path;\n\n/**\n * Radix composes each `TabsContent`'s DOM id from the `Tabs`/`TabsTrigger`\n * `value` (see #154): a raw `file.path` leaks `/`, `.`, spaces and non-ASCII\n * characters straight into that id, which is what a screen reader gets back\n * via `aria-controls`. `path` stays the display label and the lookup key in\n * component state (`active`); this is only ever a DOM-id-safe Tabs value.\n *\n * The encoding is INJECTIVE and depends only on the path — never on the\n * file's position in `files`. Every character outside `[A-Za-z0-9-]` becomes\n * `_<hex code point>_`, and `_` itself is never emitted literally, so the\n * mapping is reversible and two distinct paths can never produce the same\n * value (\"a/b\" → `tab-a_2f_b`, \"a.b\" → `tab-a_2e_b`). An index-derived value\n * would have been collision-safe too, but it changes when the list is\n * reordered or a file is inserted, which re-keys the active `TabsContent` and\n * throws away Monaco's selection, scroll position and undo history on an\n * otherwise harmless `files` update.\n */\nfunction tabIdForFile(path: string): string {\n let out = \"\";\n for (const char of path) {\n out += /[A-Za-z0-9-]/.test(char) ? char : `_${char.codePointAt(0)!.toString(16)}_`;\n }\n return `tab-${out}`;\n}\n\nfunction inferLanguage(file: EditorFile): string {\n if (file.language) return file.language;\n const ext = file.path.split(\".\").pop()?.toLowerCase() ?? \"\";\n return EXT_LANGUAGE[ext] ?? \"plaintext\";\n}\n\n/**\n * Imperative handle exposed via `CodeWorkspace`'s `ref`.\n *\n * **Migration note:** the forwarded `ref` type changed from `HTMLDivElement` to\n * `CodeWorkspaceHandle` (mirrors the #273 `MarkdownWorkspaceHandle` precedent).\n * Replace any `ref.current` / `ref.current.scrollIntoView()` DOM access with\n * `ref.current?.getElement()`. This is the only breaking change in this work.\n */\nexport interface CodeWorkspaceHandle extends EditorContentAccess {\n /**\n * The live Monaco editor for the currently active tab, or `null` while booting\n * or when no files are open. Consumers needing the full Monaco API can use this\n * and pass it to `monacoContentAccess(handle.getActiveEditor()!)`.\n */\n getActiveEditor(): MonacoCodeEditor | null;\n /**\n * The workspace root DOM element. Preserves the old `HTMLDivElement` ref access\n * that existed before the ref-type change (#273 `MarkdownWorkspace` playbook).\n */\n getElement(): HTMLDivElement | null;\n}\n\n/** No-op EditorContentAccess returned when no Monaco editor is mounted. */\nconst NULL_ACCESS: EditorContentAccess = {\n getText: () => \"\",\n getSelection: () => ({ text: \"\", empty: true }),\n replaceSelection: () => undefined,\n insertAtCursor: () => undefined,\n focus: () => undefined,\n onSelectionChange: () => () => undefined,\n};\n\n/**\n * Multi-file editor shell: brand-ui `Tabs` for the file bar above a single\n * {@link CodeEditor} that swaps to the active file. This is the \"reuse our\n * components for the chrome\" surface — Tabs/Button are ours; the editing surface\n * is Monaco. Edits bubble through `onFileChange`.\n *\n * The forwarded `ref` exposes a {@link CodeWorkspaceHandle} (not `HTMLDivElement`).\n * Use `ref.current?.getElement()` to access the root DOM node.\n */\nexport const CodeWorkspace = forwardRef<CodeWorkspaceHandle, CodeWorkspaceProps>(\n function CodeWorkspace(\n {\n files,\n activePath,\n defaultActivePath,\n onActivePathChange,\n onFileChange,\n readOnly = false,\n height = \"100%\",\n className,\n style,\n ...props\n },\n ref,\n ) {\n const [internalActive, setInternalActive] = useState(defaultActivePath ?? files[0]?.path ?? \"\");\n const isControlled = activePath !== undefined;\n const requested = isControlled ? activePath : internalActive;\n const activeFile = files.find((f) => f.path === requested) ?? files[0];\n const active = activeFile?.path ?? \"\";\n\n // DOM-id-safe Tabs value per file (#154); `path` stays the lookup key.\n const tabs = files.map((file) => ({ file, id: tabIdForFile(file.path) }));\n const activeTabId = tabs.find((t) => t.file.path === active)?.id ?? \"\";\n\n // The root div ref (getElement() preserves old HTMLDivElement access).\n const rootRef = useRef<HTMLDivElement | null>(null);\n\n // The live Monaco editor for the active tab. Nulled when there is no active file.\n const [activeEditor, setActiveEditor] = useState<MonacoCodeEditor | null>(null);\n\n // Defensive: if the active file is removed (no `activeFile`), null the held instance\n // so getActiveEditor() and content-access methods don't act on a disposed editor.\n useEffect(() => {\n if (!activeFile) setActiveEditor(null);\n }, [activeFile]);\n\n // A STABLE listener set for onSelectionChange. The handle adds/removes here;\n // the binding effect below forwards the ACTIVE editor's selection changes into\n // it. This is what makes a subscribe-in-mount-effect survive the editor's async\n // mount (and tab swaps): the consumer subscribes once; binding re-attaches as\n // `activeEditor` changes. (Delegating onSelectionChange to a call-time snapshot\n // would bind to the not-yet-mounted editor and silently never fire.)\n const [selectionListeners] = useState(() => new Set<(sel: EditorSelection) => void>());\n useEffect(() => {\n if (!activeEditor) return;\n const unsub = monacoContentAccess(activeEditor).onSelectionChange((sel) =>\n selectionListeners.forEach((l) => l(sel)),\n );\n return unsub;\n }, [activeEditor, selectionListeners]);\n\n const selectTab = useCallback(\n (path: string) => {\n if (!isControlled) setInternalActive(path);\n onActivePathChange?.(path);\n },\n [isControlled, onActivePathChange],\n );\n\n useImperativeHandle(ref, () => {\n const access = activeEditor ? monacoContentAccess(activeEditor) : NULL_ACCESS;\n return {\n getActiveEditor: () => activeEditor,\n getElement: () => rootRef.current,\n getText: () => access.getText(),\n getSelection: () => access.getSelection(),\n replaceSelection: (text: string) => access.replaceSelection(text),\n insertAtCursor: (text: string) => access.insertAtCursor(text),\n focus: () => access.focus(),\n // Stable set (not the call-time `access`) so a subscription survives the\n // editor's async mount + tab swaps; the binding effect forwards events.\n onSelectionChange: (listener) => {\n selectionListeners.add(listener);\n return () => selectionListeners.delete(listener);\n },\n };\n }, [activeEditor, selectionListeners]);\n\n const resolvedStyle: CSSProperties = {\n height: typeof height === \"number\" ? `${height}px` : height,\n ...style,\n };\n\n return (\n <div\n ref={rootRef}\n className={cn(\n \"flex flex-col overflow-hidden rounded-lg border border-border bg-surface\",\n className,\n )}\n style={resolvedStyle}\n {...props}\n >\n <Tabs\n value={activeTabId}\n onValueChange={(id) => {\n const found = tabs.find((t) => t.id === id);\n if (found) selectTab(found.file.path);\n }}\n className=\"flex min-h-0 flex-1 flex-col gap-0\"\n >\n <div className=\"flex items-center border-b border-border bg-surface\">\n <TabsList className=\"h-9 flex-1 justify-start gap-0 rounded-none bg-transparent p-0\">\n {tabs.map(({ file, id }) => (\n <TabsTrigger\n key={id}\n value={id}\n className=\"h-9 rounded-none border-e border-border px-3 text-xs data-[state=active]:bg-background data-[state=active]:shadow-none\"\n >\n {basename(file.path)}\n </TabsTrigger>\n ))}\n </TabsList>\n {activeFile ? <CopyButton value={activeFile.value} className=\"me-1.5\" /> : null}\n </div>\n\n {tabs.map(({ file, id }) => {\n const isActive = file.path === activeFile?.path;\n return (\n // `forceMount` keeps every tab's content in the DOM so each\n // trigger's `aria-controls` resolves to a real element, not only\n // the active one (#154). Radix derives its own `hidden` from\n // `forceMount || isSelected`, so under `forceMount` it hides\n // NOTHING: without the explicit `hidden` below every inactive\n // panel stays a visible `flex-1` child and the editor height is\n // split across all of them. `tabIndex={-1}` keeps the empty\n // panels out of the tab sequence for the same reason. Only the\n // active file mounts a (single) Monaco instance.\n <TabsContent\n key={id}\n value={id}\n forceMount\n hidden={!isActive}\n tabIndex={isActive ? 0 : -1}\n className=\"mt-0 min-h-0 flex-1\"\n >\n {isActive ? (\n <CodeEditor\n key={file.path}\n path={file.path}\n language={inferLanguage(file)}\n value={file.value}\n readOnly={readOnly}\n onChange={(next) => onFileChange?.(file.path, next)}\n onMount={(editor) => setActiveEditor(editor)}\n height=\"100%\"\n />\n ) : null}\n </TabsContent>\n );\n })}\n </Tabs>\n </div>\n );\n },\n);\n","\"use client\";\n\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\nimport { CopyButton } from \"../copy-button\";\nimport { EDITOR_LANGUAGES, type EditorLanguage } from \"../lib/languages\";\n\nexport interface EditorToolbarProps extends HTMLAttributes<HTMLDivElement> {\n /** Filename shown on the left (e.g. \"index.ts\"). */\n filename?: ReactNode;\n /** Active language id; shows a language picker when `onLanguageChange` is set. */\n language?: string;\n /** Called when the user picks a language. Omit to hide the picker. */\n onLanguageChange?: (language: string) => void;\n /** Languages offered in the picker. Defaults to {@link EDITOR_LANGUAGES}. */\n languages?: EditorLanguage[];\n /** Text copied by the copy button. Omit to hide the button. */\n copyValue?: string;\n /** Extra actions rendered before the copy button (brand-ui buttons, etc.). */\n actions?: ReactNode;\n}\n\n/**\n * Brand-ui chrome for the editors — the part that genuinely reuses our\n * components. Renders a filename label, an optional language `Select` and a copy\n * `Button`. The editing surface itself is Monaco; this is the frame around it.\n */\nexport const EditorToolbar = forwardRef<HTMLDivElement, EditorToolbarProps>(function EditorToolbar(\n {\n filename,\n language,\n onLanguageChange,\n languages = EDITOR_LANGUAGES,\n copyValue,\n actions,\n className,\n ...props\n },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex h-10 shrink-0 items-center gap-2 border-b border-border bg-surface px-3\",\n className,\n )}\n {...props}\n >\n {filename != null ? (\n <span className=\"truncate text-sm font-medium text-foreground\">{filename}</span>\n ) : null}\n\n <div className=\"ml-auto flex items-center gap-1.5\">\n {actions}\n\n {onLanguageChange ? (\n <Select value={language} onValueChange={onLanguageChange}>\n <SelectTrigger size=\"sm\" className=\"h-7 w-[140px]\" aria-label=\"Language\">\n <SelectValue placeholder=\"Language\" />\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l.id} value={l.id}>\n {l.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : null}\n\n {copyValue != null ? <CopyButton value={copyValue} /> : null}\n </div>\n </div>\n );\n});\n","/**\n * Curated language list for the editor toolbar's language picker. Ids are\n * Monaco's built-in language ids (`monaco.languages.getLanguages()`), so they\n * map straight onto `setModelLanguage` / model creation.\n */\nexport interface EditorLanguage {\n /** Monaco language id (e.g. \"typescript\"). */\n id: string;\n /** Human-readable label for the picker. */\n label: string;\n}\n\nexport const EDITOR_LANGUAGES: EditorLanguage[] = [\n { id: \"typescript\", label: \"TypeScript\" },\n { id: \"javascript\", label: \"JavaScript\" },\n { id: \"json\", label: \"JSON\" },\n { id: \"html\", label: \"HTML\" },\n { id: \"css\", label: \"CSS\" },\n { id: \"scss\", label: \"SCSS\" },\n { id: \"markdown\", label: \"Markdown\" },\n { id: \"python\", label: \"Python\" },\n { id: \"sql\", label: \"SQL\" },\n { id: \"yaml\", label: \"YAML\" },\n { id: \"xml\", label: \"XML\" },\n { id: \"shell\", label: \"Shell\" },\n { id: \"plaintext\", label: \"Plain text\" },\n];\n\n/** Look up a language's label, falling back to the raw id. */\nexport function languageLabel(id: string): string {\n return EDITOR_LANGUAGES.find((l) => l.id === id)?.label ?? id;\n}\n","/**\n * @elabs-ai/components-editor — a token-themed Monaco (VS Code) editor wrapped as brand-ui\n * components.\n *\n * Monaco is a self-rendering editor engine; this package wraps it the way\n * @elabs-ai/components-flow wraps React Flow and @elabs-ai/components-data wraps TanStack. The editing\n * surface + widgets are Monaco's, recolored from the active brand theme via the\n * theming bridge; the chrome (toolbar, file tabs, copy button) is brand-ui.\n *\n * Worker setup (for completions/diagnostics) — import ONCE at the app entry:\n * import \"@elabs-ai/components-editor/monaco-environment\"; // Vite apps\n */\nexport {\n CodeEditor,\n type CodeEditorProps,\n type MonacoCodeEditor,\n type EditorAction,\n} from \"./code-editor\";\nexport { DiffEditor, type DiffEditorProps, type MonacoDiffEditor } from \"./diff-editor\";\nexport {\n MarkdownEditor,\n type MarkdownEditorProps,\n type MarkdownEditorHandle,\n type EmbedAssetFn,\n} from \"./markdown-editor\";\nexport {\n CodeWorkspace,\n type CodeWorkspaceHandle,\n type CodeWorkspaceProps,\n type EditorFile,\n} from \"./code-workspace\";\nexport {\n monacoContentAccess,\n type EditorContentAccess,\n type EditorSelection,\n} from \"./lib/editor-content-access\";\nexport { EditorToolbar, type EditorToolbarProps } from \"./editor-toolbar\";\nexport { EditorContextMenu, type EditorContextMenuProps } from \"./editor-context-menu\";\nexport { CopyButton, type CopyButtonProps } from \"./copy-button\";\n\n// Theming bridge + language helpers (advanced consumers / custom chrome).\nexport { applyBrandTheme, buildBrandThemeData, brandThemeId } from \"./lib/monaco-theme-bridge\";\nexport { useDataTheme, type DataThemeState } from \"./lib/use-data-theme\";\nexport { EDITOR_LANGUAGES, languageLabel, type EditorLanguage } from \"./lib/languages\";\n\n// Re-export the monaco namespace so consumers can build custom editors / wire\n// commands without adding a direct dependency.\nexport * as monaco from \"monaco-editor\";\n"],"mappings":"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","names":["DiffEditor","editor","cn","forwardRef","useEffect","useImperativeHandle","useRef","useState","jsx","forwardRef","CodeWorkspace","useState","useRef","useEffect","useImperativeHandle","cn","editor","cn","forwardRef","jsx","jsxs","forwardRef","EditorToolbar","cn","monaco"]}
|
package/dist/markdown/index.css
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
max-width: var(--md-measure, 48rem);
|
|
12
12
|
margin-inline: auto;
|
|
13
13
|
}
|
|
14
|
-
.milkdown-host .ProseMirror:focus {
|
|
15
|
-
outline:
|
|
14
|
+
.milkdown-host .ProseMirror:focus-visible {
|
|
15
|
+
outline: 1px solid var(--ring-contour);
|
|
16
|
+
outline-offset: -3px;
|
|
17
|
+
box-shadow: inset 0 0 0 2px var(--ring);
|
|
16
18
|
}
|
|
17
19
|
.milkdown-host {
|
|
18
20
|
display: flex;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/markdown-editor/markdown-editor.css","../../src/calc-block/calc-editor.css"],"sourcesContent":["/**\n * Token-driven theme for the Milkdown (ProseMirror) WYSIWYG surface.\n *\n * Milkdown core ships ZERO styles (headless), so this is where brand-ui owns the\n * look. Every value is a semantic design token (var(--foreground), --border,\n * --radius, …) — NO raw colors — so the editor matches all three themes\n * (light/dark) for free. Every rule\n * is scoped under `.milkdown-host` so nothing leaks globally.\n */\n\n.milkdown-host .ProseMirror {\n outline: none;\n padding: 1rem 1.1rem;\n min-height: 9rem;\n color: var(--foreground);\n font-size: 0.875rem;\n line-height: 1.65;\n caret-color: var(--primary);\n word-break: break-word;\n /* Same reading measure as the preview (max-w-3xl). Driven by the shared scale\n (--md-measure, set via markdownScaleVars) so editor + preview match (#18). */\n max-width: var(--md-measure, 48rem);\n margin-inline: auto;\n}\n\n.milkdown-host .ProseMirror:focus {\n outline: none;\n}\n\n/* ----------------------------------------------------------------------------\n * Fill height — the editable grows to fill a definite-height parent.\n *\n * Milkdown's host box is otherwise content-sized (the `.ProseMirror` floor below\n * is `min-height: 9rem`), so inside a tall pane a short document leaves a large\n * dead area below the editable AND the caret-anchored `/` slash menu clips inside\n * the short box near the bottom edge. Making `.milkdown-host` a column flex that\n * fills its parent — and letting the intermediate Milkdown wrapper + the\n * ProseMirror surface grow inside it — means the editable fills the pane\n * (clickable everywhere) and the slash menu has room to open / flip.\n *\n * `min-height: 100%` only resolves against a parent with a DEFINITE height (the\n * workspace's `h-full` wysiwyg pane, or any sized container). In an\n * indefinite-height parent it resolves to `auto`, so the standalone / short\n * editor still sizes to its content above the 9rem floor — no regression for the\n * autodocs / inline cases. (elabs-components: editor-fill-height)\n * ------------------------------------------------------------------------- */\n.milkdown-host {\n display: flex;\n flex-direction: column;\n min-height: 100%;\n}\n.milkdown-host > div,\n.milkdown-host .milkdown {\n display: flex;\n min-height: 0;\n flex: 1 1 auto;\n flex-direction: column;\n}\n.milkdown-host .ProseMirror.editor {\n flex: 1 1 auto;\n}\n\n.milkdown-host .ProseMirror > * + * {\n margin-top: 0.7em;\n}\n\n/* Headings — sizes/weight/tracking come from the SHARED markdown scale\n (markdown-scale.ts → --md-* vars on .milkdown-host), so the editor matches the\n prose `Heading` exactly and can't drift on the next edit to either side (#18).\n Fallbacks equal the canonical scale for use without the vars (e.g. clipboard). */\n.milkdown-host .ProseMirror h1,\n.milkdown-host .ProseMirror h2,\n.milkdown-host .ProseMirror h3,\n.milkdown-host .ProseMirror h4,\n.milkdown-host .ProseMirror h5,\n.milkdown-host .ProseMirror h6 {\n font-weight: var(--md-heading-weight, 600);\n letter-spacing: var(--md-heading-tracking, -0.025em);\n line-height: 1.25;\n color: var(--foreground);\n margin-top: 1.1em;\n}\n.milkdown-host .ProseMirror h1 {\n font-size: var(--md-h1, 1.5rem);\n}\n.milkdown-host .ProseMirror h2 {\n font-size: var(--md-h2, 1.25rem);\n}\n.milkdown-host .ProseMirror h3 {\n font-size: var(--md-h3, 1.125rem);\n}\n.milkdown-host .ProseMirror h4 {\n font-size: var(--md-h4, 1rem);\n}\n.milkdown-host .ProseMirror h5 {\n font-size: var(--md-h5, 0.875rem);\n}\n.milkdown-host .ProseMirror h6 {\n font-size: var(--md-h6, 0.875rem);\n color: var(--muted-foreground);\n}\n\n/* Inline */\n.milkdown-host .ProseMirror a {\n color: var(--primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.milkdown-host .ProseMirror strong {\n font-weight: 650;\n}\n.milkdown-host .ProseMirror code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n background: var(--muted);\n color: var(--foreground);\n padding: 0.12em 0.36em;\n border-radius: calc(var(--radius) - 4px);\n}\n\n/* Blocks */\n.milkdown-host .ProseMirror blockquote {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n color: var(--muted-foreground);\n}\n.milkdown-host .ProseMirror pre {\n background: var(--surface-muted);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 0.85rem 1rem;\n overflow: auto;\n}\n.milkdown-host .ProseMirror pre code {\n background: transparent;\n padding: 0;\n font-size: 0.82rem;\n}\n.milkdown-host .ProseMirror hr {\n border: none;\n border-top: 1px solid var(--border);\n margin: 1.25em 0;\n}\n\n/* Lists */\n.milkdown-host .ProseMirror ul,\n.milkdown-host .ProseMirror ol {\n padding-left: 1.4rem;\n}\n.milkdown-host .ProseMirror ul {\n list-style: disc;\n}\n.milkdown-host .ProseMirror ol {\n list-style: decimal;\n}\n.milkdown-host .ProseMirror li > * + * {\n margin-top: 0.35em;\n}\n\n/* Tables (GFM) */\n.milkdown-host .ProseMirror table {\n border-collapse: collapse;\n width: 100%;\n font-size: 0.85rem;\n}\n.milkdown-host .ProseMirror th,\n.milkdown-host .ProseMirror td {\n border: 1px solid var(--border);\n padding: 0.4rem 0.6rem;\n text-align: left;\n}\n.milkdown-host .ProseMirror th {\n background: var(--surface-muted);\n font-weight: 600;\n}\n\n/* Task lists (GFM) */\n.milkdown-host .ProseMirror ul[data-item-type=\"task\"] {\n list-style: none;\n padding-left: 0.25rem;\n}\n\n/* Read-only mode dims the caret affordance */\n.milkdown-host .ProseMirror[contenteditable=\"false\"] {\n caret-color: transparent;\n}\n\n/* ---- Brand `:::` directives ----------------------------------------------------\n * These now render as LIVE @brand React components via @prosemirror-adapter/react\n * (see directive-views.tsx), so the box-model chrome (card/callout/metric borders,\n * fills, type accents) comes from the components themselves — NOT from here. This\n * section only owns what the editor adds on top: outer spacing, the editable-body\n * rhythm, the timeline frame (an editable list, not a derived <Timeline>), and the\n * inline-edit affordance for editable attributes (card/callout title, metric\n * label/value). The `toDOM` defs in directive-nodes.ts keep their own marker classes\n * for clipboard serialization but are not visually rendered while node-views are on.\n */\n.milkdown-host .brand-directive {\n margin: 0.85em 0;\n}\n.milkdown-host .brand-directive__body > * + * {\n margin-top: 0.6em;\n}\n/* The first/last editable block inside a card/callout shouldn't add stray margin\n * on top of the component's own padding. */\n.milkdown-host .brand-directive__body > :first-child {\n margin-top: 0;\n}\n\n/* timeline → keep the list editable inside a subtle frame */\n.milkdown-host .brand-directive--timeline {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n}\n\n/* Inline-editable directive attribute (seamless, caret-friendly). */\n.milkdown-host .brand-inline-edit {\n cursor: text;\n min-width: 1ch;\n /* inherit the surrounding component's type (CardTitle, MetricBlock label/value) */\n font: inherit;\n color: inherit;\n letter-spacing: inherit;\n}\n.milkdown-host .brand-inline-edit:empty::before {\n content: attr(data-placeholder);\n color: var(--muted-foreground);\n opacity: 0.65;\n pointer-events: none;\n}\n\n/* ------------------------------------------------------------------------- */\n/* Focus writing (Ulysses Phase A): under a `[data-focus-writing]` ancestor */\n/* (the workspace's wysiwyg pane), every top-level block dims except the one */\n/* owning the selection (`.wb-fw-active`, set by the workspace) — paragraph */\n/* focus. Hover un-dims for mouse repositioning. Token-driven, motion-safe. */\n/* ------------------------------------------------------------------------- */\n[data-focus-writing] .milkdown-host .ProseMirror > * {\n opacity: 0.35;\n transition: opacity var(--t-base, 200ms) var(--ease-standard, ease);\n}\n[data-focus-writing] .milkdown-host .ProseMirror > .wb-fw-active,\n[data-focus-writing] .milkdown-host .ProseMirror > *:hover {\n opacity: 1;\n}\n@media (prefers-reduced-motion: reduce) {\n [data-focus-writing] .milkdown-host .ProseMirror > * {\n transition: none;\n }\n}\n","/**\n * Calc authoring decorations (#220) — shared by the Monaco source surface\n * (decoration `inlineClassName`) and the Milkdown WYSIWYG surface (ProseMirror\n * inline decorations + result-inlay widgets).\n *\n * Colors come from the `--calc-*` syntax tokens — the SAME tokens `CalcBlock`\n * paints with (#221), already AA-verified against `--background` (the editor\n * surface) and `--card` in all three themes — so highlighting tracks the theme via\n * the cascade with no hardcoded hex. The compound `.brand-calc-tok.brand-calc-tok--x`\n * selector raises specificity above Monaco's own token color class (`.mtkN`) so\n * the calc color wins regardless of stylesheet load order (no `!important`).\n *\n * Hue is never the SOLE cue (var-def = weight, unresolved = dotted underline), so\n * roles stay distinct in the high-contrast theme where the calc colors collapse\n * toward the foreground — mirroring `CalcBlock.tokenClass`.\n */\n\n.brand-calc-tok.brand-calc-tok--number,\n.brand-calc-tok.brand-calc-tok--constant {\n color: var(--calc-number);\n}\n.brand-calc-tok.brand-calc-tok--unit {\n color: var(--calc-unit);\n}\n.brand-calc-tok.brand-calc-tok--currency {\n color: var(--calc-currency);\n}\n.brand-calc-tok.brand-calc-tok--operator {\n color: var(--calc-operator);\n}\n.brand-calc-tok.brand-calc-tok--function {\n color: var(--calc-function);\n}\n.brand-calc-tok.brand-calc-tok--var-ref {\n color: var(--calc-variable);\n}\n.brand-calc-tok.brand-calc-tok--var-def {\n color: var(--calc-variable);\n font-weight: 500;\n}\n.brand-calc-tok.brand-calc-tok--line-ref {\n color: var(--calc-reference);\n font-variant-numeric: tabular-nums;\n}\n.brand-calc-tok.brand-calc-tok--comment {\n color: var(--calc-comment);\n font-style: italic;\n}\n.brand-calc-tok.brand-calc-tok--unknown {\n color: var(--calc-warning);\n}\n\n/* Non-hue cue for unresolved identifiers / dangling refs — carries the role in\n high-contrast, where hue is flattened. */\n.brand-calc-tok.brand-calc-tok--unresolved {\n text-decoration: underline dotted;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n}\n\n/**\n * WYSIWYG result inlay — a ProseMirror widget after each calc line showing the\n * computed answer. The number IS the signal (shown as text), color is only an\n * enhancement, and it is non-editable / non-selectable so it never enters the\n * document. (The Monaco surface uses Monaco's own inlay hints, themed via the\n * theme bridge's `editorInlayHint.*` colors — not this class.)\n */\n.brand-calc-inlay {\n /* Full strength (no opacity de-emphasis): the result is the answer, and the\n `--calc-result` token is AA-verified at FULL opacity (#221) — reducing it\n would drop effective contrast below what the contrast gate models. */\n margin-inline-start: 1ch;\n color: var(--calc-result);\n font-variant-numeric: tabular-nums;\n user-select: none;\n white-space: pre;\n}\n.brand-calc-inlay--error {\n color: var(--calc-warning);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/markdown-editor/markdown-editor.css","../../src/calc-block/calc-editor.css"],"sourcesContent":["/**\n * Token-driven theme for the Milkdown (ProseMirror) WYSIWYG surface.\n *\n * Milkdown core ships ZERO styles (headless), so this is where brand-ui owns the\n * look. Every value is a semantic design token (var(--foreground), --border,\n * --radius, …) — NO raw colors — so the editor matches every theme\n * (light/dark) for free. Every rule\n * is scoped under `.milkdown-host` so nothing leaks globally.\n */\n\n.milkdown-host .ProseMirror {\n /* Suppresses the platform default outline — NOT a bare removal: the\n `:focus-visible` rule below is the replacement, drawn on this same\n element (#309). It owns the indicator unconditionally, so it can't be\n clipped by an ancestor and can't be deleted by a consumer `className`\n reaching `cn()` on the wrapper (`markdown-editor.tsx`'s root `div`\n intentionally carries no focus-ring utility of its own — see #67/#309). */\n outline: none;\n padding: 1rem 1.1rem;\n min-height: 9rem;\n color: var(--foreground);\n font-size: 0.875rem;\n line-height: 1.65;\n caret-color: var(--primary);\n word-break: break-word;\n /* Same reading measure as the preview (max-w-3xl). Driven by the shared scale\n (--md-measure, set via markdownScaleVars) so editor + preview match (#18). */\n max-width: var(--md-measure, 48rem);\n margin-inline: auto;\n}\n\n/* Focus indicator (#309) — a compound two-layer shape mirroring the\n `focus-ring-inset` Tailwind utility (`packages/tokens/src/themes.css`,\n ADR 0027), hand-written because this stylesheet is a plain side-effect CSS\n import resolved by the CONSUMER's bundler — not guaranteed to run through\n Tailwind, so `@apply`/utility classes aren't reachable here (verified:\n `@apply` appears zero times in any .css file in this repo). Drawn INSIDE\n the editable's own box (`outline-offset: -3px`, an inset `box-shadow`), so\n it can't be clipped by an ancestor and survives a consumer `className`\n deleting the wrapper's classes (`MarkdownWorkspace` already does this via\n `className=\"border-0\"`). Two layers of opposite value so at least one edge\n clears 3:1 against the ground whatever `--ring` resolves to in a given\n theme (`--ring-contour` is the dedicated contour token — `themes-contrast.\n test.ts`'s `INDICATOR_SURFACES` locks `max(ring, contour) >= 3:1` at the\n token level; `markdown-editor.stories.tsx`'s `FocusIndicator` play\n re-measures it on this rendered surface, both themes). */\n.milkdown-host .ProseMirror:focus-visible {\n outline: 1px solid var(--ring-contour);\n outline-offset: -3px;\n box-shadow: inset 0 0 0 2px var(--ring);\n}\n\n/* ----------------------------------------------------------------------------\n * Fill height — the editable grows to fill a definite-height parent.\n *\n * Milkdown's host box is otherwise content-sized (the `.ProseMirror` floor below\n * is `min-height: 9rem`), so inside a tall pane a short document leaves a large\n * dead area below the editable AND the caret-anchored `/` slash menu clips inside\n * the short box near the bottom edge. Making `.milkdown-host` a column flex that\n * fills its parent — and letting the intermediate Milkdown wrapper + the\n * ProseMirror surface grow inside it — means the editable fills the pane\n * (clickable everywhere) and the slash menu has room to open / flip.\n *\n * `min-height: 100%` only resolves against a parent with a DEFINITE height (the\n * workspace's `h-full` wysiwyg pane, or any sized container). In an\n * indefinite-height parent it resolves to `auto`, so the standalone / short\n * editor still sizes to its content above the 9rem floor — no regression for the\n * autodocs / inline cases. (elabs-components: editor-fill-height)\n * ------------------------------------------------------------------------- */\n.milkdown-host {\n display: flex;\n flex-direction: column;\n min-height: 100%;\n}\n.milkdown-host > div,\n.milkdown-host .milkdown {\n display: flex;\n min-height: 0;\n flex: 1 1 auto;\n flex-direction: column;\n}\n.milkdown-host .ProseMirror.editor {\n flex: 1 1 auto;\n}\n\n.milkdown-host .ProseMirror > * + * {\n margin-top: 0.7em;\n}\n\n/* Headings — sizes/weight/tracking come from the SHARED markdown scale\n (markdown-scale.ts → --md-* vars on .milkdown-host), so the editor matches the\n prose `Heading` exactly and can't drift on the next edit to either side (#18).\n Fallbacks equal the canonical scale for use without the vars (e.g. clipboard). */\n.milkdown-host .ProseMirror h1,\n.milkdown-host .ProseMirror h2,\n.milkdown-host .ProseMirror h3,\n.milkdown-host .ProseMirror h4,\n.milkdown-host .ProseMirror h5,\n.milkdown-host .ProseMirror h6 {\n font-weight: var(--md-heading-weight, 600);\n letter-spacing: var(--md-heading-tracking, -0.025em);\n line-height: 1.25;\n color: var(--foreground);\n margin-top: 1.1em;\n}\n.milkdown-host .ProseMirror h1 {\n font-size: var(--md-h1, 1.5rem);\n}\n.milkdown-host .ProseMirror h2 {\n font-size: var(--md-h2, 1.25rem);\n}\n.milkdown-host .ProseMirror h3 {\n font-size: var(--md-h3, 1.125rem);\n}\n.milkdown-host .ProseMirror h4 {\n font-size: var(--md-h4, 1rem);\n}\n.milkdown-host .ProseMirror h5 {\n font-size: var(--md-h5, 0.875rem);\n}\n.milkdown-host .ProseMirror h6 {\n font-size: var(--md-h6, 0.875rem);\n color: var(--muted-foreground);\n}\n\n/* Inline */\n.milkdown-host .ProseMirror a {\n color: var(--primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.milkdown-host .ProseMirror strong {\n font-weight: 650;\n}\n.milkdown-host .ProseMirror code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n background: var(--muted);\n color: var(--foreground);\n padding: 0.12em 0.36em;\n border-radius: calc(var(--radius) - 4px);\n}\n\n/* Blocks */\n.milkdown-host .ProseMirror blockquote {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n color: var(--muted-foreground);\n}\n.milkdown-host .ProseMirror pre {\n background: var(--surface-muted);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 0.85rem 1rem;\n overflow: auto;\n}\n.milkdown-host .ProseMirror pre code {\n background: transparent;\n padding: 0;\n font-size: 0.82rem;\n}\n.milkdown-host .ProseMirror hr {\n border: none;\n border-top: 1px solid var(--border);\n margin: 1.25em 0;\n}\n\n/* Lists */\n.milkdown-host .ProseMirror ul,\n.milkdown-host .ProseMirror ol {\n padding-left: 1.4rem;\n}\n.milkdown-host .ProseMirror ul {\n list-style: disc;\n}\n.milkdown-host .ProseMirror ol {\n list-style: decimal;\n}\n.milkdown-host .ProseMirror li > * + * {\n margin-top: 0.35em;\n}\n\n/* Tables (GFM) */\n.milkdown-host .ProseMirror table {\n border-collapse: collapse;\n width: 100%;\n font-size: 0.85rem;\n}\n.milkdown-host .ProseMirror th,\n.milkdown-host .ProseMirror td {\n border: 1px solid var(--border);\n padding: 0.4rem 0.6rem;\n text-align: left;\n}\n.milkdown-host .ProseMirror th {\n background: var(--surface-muted);\n font-weight: 600;\n}\n\n/* Task lists (GFM) */\n.milkdown-host .ProseMirror ul[data-item-type=\"task\"] {\n list-style: none;\n padding-left: 0.25rem;\n}\n\n/* Read-only mode dims the caret affordance */\n.milkdown-host .ProseMirror[contenteditable=\"false\"] {\n caret-color: transparent;\n}\n\n/* ---- Brand `:::` directives ----------------------------------------------------\n * These now render as LIVE @brand React components via @prosemirror-adapter/react\n * (see directive-views.tsx), so the box-model chrome (card/callout/metric borders,\n * fills, type accents) comes from the components themselves — NOT from here. This\n * section only owns what the editor adds on top: outer spacing, the editable-body\n * rhythm, the timeline frame (an editable list, not a derived <Timeline>), and the\n * inline-edit affordance for editable attributes (card/callout title, metric\n * label/value). The `toDOM` defs in directive-nodes.ts keep their own marker classes\n * for clipboard serialization but are not visually rendered while node-views are on.\n */\n.milkdown-host .brand-directive {\n margin: 0.85em 0;\n}\n.milkdown-host .brand-directive__body > * + * {\n margin-top: 0.6em;\n}\n/* The first/last editable block inside a card/callout shouldn't add stray margin\n * on top of the component's own padding. */\n.milkdown-host .brand-directive__body > :first-child {\n margin-top: 0;\n}\n\n/* timeline → keep the list editable inside a subtle frame */\n.milkdown-host .brand-directive--timeline {\n border-left: 2px solid var(--border);\n padding-left: 1rem;\n}\n\n/* Inline-editable directive attribute (seamless, caret-friendly). */\n.milkdown-host .brand-inline-edit {\n cursor: text;\n min-width: 1ch;\n /* inherit the surrounding component's type (CardTitle, MetricBlock label/value) */\n font: inherit;\n color: inherit;\n letter-spacing: inherit;\n}\n.milkdown-host .brand-inline-edit:empty::before {\n content: attr(data-placeholder);\n color: var(--muted-foreground);\n opacity: 0.65;\n pointer-events: none;\n}\n\n/* ------------------------------------------------------------------------- */\n/* Focus writing (Ulysses Phase A): under a `[data-focus-writing]` ancestor */\n/* (the workspace's wysiwyg pane), every top-level block dims except the one */\n/* owning the selection (`.wb-fw-active`, set by the workspace) — paragraph */\n/* focus. Hover un-dims for mouse repositioning. Token-driven, motion-safe. */\n/* ------------------------------------------------------------------------- */\n[data-focus-writing] .milkdown-host .ProseMirror > * {\n opacity: 0.35;\n transition: opacity var(--t-base, 200ms) var(--ease-standard, ease);\n}\n[data-focus-writing] .milkdown-host .ProseMirror > .wb-fw-active,\n[data-focus-writing] .milkdown-host .ProseMirror > *:hover {\n opacity: 1;\n}\n@media (prefers-reduced-motion: reduce) {\n [data-focus-writing] .milkdown-host .ProseMirror > * {\n transition: none;\n }\n}\n","/**\n * Calc authoring decorations (#220) — shared by the Monaco source surface\n * (decoration `inlineClassName`) and the Milkdown WYSIWYG surface (ProseMirror\n * inline decorations + result-inlay widgets).\n *\n * Colors come from the `--calc-*` syntax tokens — the SAME tokens `CalcBlock`\n * paints with (#221), already AA-verified against `--background` (the editor\n * surface) and `--card` in every theme — so highlighting tracks the theme via\n * the cascade with no hardcoded hex. The compound `.brand-calc-tok.brand-calc-tok--x`\n * selector raises specificity above Monaco's own token color class (`.mtkN`) so\n * the calc color wins regardless of stylesheet load order (no `!important`).\n *\n * Hue is never the SOLE cue (var-def = weight, unresolved = dotted underline), so\n * roles stay distinct in the high-contrast theme where the calc colors collapse\n * toward the foreground — mirroring `CalcBlock.tokenClass`.\n */\n\n.brand-calc-tok.brand-calc-tok--number,\n.brand-calc-tok.brand-calc-tok--constant {\n color: var(--calc-number);\n}\n.brand-calc-tok.brand-calc-tok--unit {\n color: var(--calc-unit);\n}\n.brand-calc-tok.brand-calc-tok--currency {\n color: var(--calc-currency);\n}\n.brand-calc-tok.brand-calc-tok--operator {\n color: var(--calc-operator);\n}\n.brand-calc-tok.brand-calc-tok--function {\n color: var(--calc-function);\n}\n.brand-calc-tok.brand-calc-tok--var-ref {\n color: var(--calc-variable);\n}\n.brand-calc-tok.brand-calc-tok--var-def {\n color: var(--calc-variable);\n font-weight: 500;\n}\n.brand-calc-tok.brand-calc-tok--line-ref {\n color: var(--calc-reference);\n font-variant-numeric: tabular-nums;\n}\n.brand-calc-tok.brand-calc-tok--comment {\n color: var(--calc-comment);\n font-style: italic;\n}\n.brand-calc-tok.brand-calc-tok--unknown {\n color: var(--calc-warning);\n}\n\n/* Non-hue cue for unresolved identifiers / dangling refs — carries the role in\n high-contrast, where hue is flattened. */\n.brand-calc-tok.brand-calc-tok--unresolved {\n text-decoration: underline dotted;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n}\n\n/**\n * WYSIWYG result inlay — a ProseMirror widget after each calc line showing the\n * computed answer. The number IS the signal (shown as text), color is only an\n * enhancement, and it is non-editable / non-selectable so it never enters the\n * document. (The Monaco surface uses Monaco's own inlay hints, themed via the\n * theme bridge's `editorInlayHint.*` colors — not this class.)\n */\n.brand-calc-inlay {\n /* Full strength (no opacity de-emphasis): the result is the answer, and the\n `--calc-result` token is AA-verified at FULL opacity (#221) — reducing it\n would drop effective contrast below what the contrast gate models. */\n margin-inline-start: 1ch;\n color: var(--calc-result);\n font-variant-numeric: tabular-nums;\n user-select: none;\n white-space: pre;\n}\n.brand-calc-inlay--error {\n color: var(--calc-warning);\n}\n"],"mappings":"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","names":[]}
|
package/dist/markdown/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SlashCommand, I as IterationEditHandler, c as EditorSelection, E as EditorContentAccess, h as EditorCompletionProvider, M as MonacoCodeEditor, i as CalcEditorHooks, d as EmbedAssetFn, j as EvaluateCalc, k as CalcValue, l as CalcTokenKind } from '../markdown-editor-
|
|
2
|
-
export { B as BRAND_SLASH_COMMANDS, n as BasicBlockId, o as CALC_FENCE_SEED, p as CalcComplete, q as CalcCompletion, r as CalcCompletionContext, s as CalcCompletionKind, t as CalcContext, u as CalcLineResult, v as CalcRule, w as CalcSheet, x as CalcTint, y as CalcToken, z as CalcTokenize, A as CalcValueKind, D as CompletionMatch, F as CompletionReplaceRange, G as EditorCompletionContext, H as EditorCompletionItem, J as InsertableDirective, K as IterationEditContext, L as IterationEditRequest, e as MarkdownEditor, f as MarkdownEditorHandle, g as MarkdownEditorProps, N as SlashInsertContext, O as SlashRange, P as SourceSlashContext, Q as collectCompletions, R as filterSlashCommands, T as groupSlashCommands, U as insertBasicBlock, V as insertBrandDirective, W as insertCalcFence, m as monacoContentAccess, X as resolveCalcInsert, Y as resolveReplaceRange, Z as triggerQueryStart } from '../markdown-editor-
|
|
1
|
+
import { S as SlashCommand, I as IterationEditHandler, c as EditorSelection, E as EditorContentAccess, h as EditorCompletionProvider, M as MonacoCodeEditor, i as CalcEditorHooks, d as EmbedAssetFn, j as EvaluateCalc, k as CalcValue, l as CalcTokenKind } from '../markdown-editor-CBp_4eDv.js';
|
|
2
|
+
export { B as BRAND_SLASH_COMMANDS, n as BasicBlockId, o as CALC_FENCE_SEED, p as CalcComplete, q as CalcCompletion, r as CalcCompletionContext, s as CalcCompletionKind, t as CalcContext, u as CalcLineResult, v as CalcRule, w as CalcSheet, x as CalcTint, y as CalcToken, z as CalcTokenize, A as CalcValueKind, D as CompletionMatch, F as CompletionReplaceRange, G as EditorCompletionContext, H as EditorCompletionItem, J as InsertableDirective, K as IterationEditContext, L as IterationEditRequest, e as MarkdownEditor, f as MarkdownEditorHandle, g as MarkdownEditorProps, N as SlashInsertContext, O as SlashRange, P as SourceSlashContext, Q as collectCompletions, R as filterSlashCommands, T as groupSlashCommands, U as insertBasicBlock, V as insertBrandDirective, W as insertCalcFence, m as monacoContentAccess, X as resolveCalcInsert, Y as resolveReplaceRange, Z as triggerQueryStart } from '../markdown-editor-CBp_4eDv.js';
|
|
3
3
|
import { MilkdownPlugin } from '@milkdown/kit/ctx';
|
|
4
4
|
import { EditorView } from '@milkdown/kit/prose/view';
|
|
5
5
|
import * as monaco from 'monaco-editor';
|
package/dist/markdown/index.js
CHANGED
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
transposeIterationValue,
|
|
55
55
|
triggerQueryStart,
|
|
56
56
|
useMarkdownOutline
|
|
57
|
-
} from "../chunk-
|
|
57
|
+
} from "../chunk-C62O7IOQ.js";
|
|
58
58
|
|
|
59
59
|
// src/lib/editor-completions-monaco.ts
|
|
60
60
|
import * as monaco from "monaco-editor";
|
|
@@ -1530,7 +1530,7 @@ function MermaidViewer({ svg, label }) {
|
|
|
1530
1530
|
className: cn4(
|
|
1531
1531
|
"w-full truncate rounded-md px-2 py-1.5 text-start text-caption transition-colors duration-fast ease-standard motion-reduce:transition-none",
|
|
1532
1532
|
"hover:bg-accent hover:text-accent-foreground",
|
|
1533
|
-
"focus-
|
|
1533
|
+
"focus-ring-inset",
|
|
1534
1534
|
activeHit === hit.id ? "bg-accent font-medium text-foreground" : "text-muted-foreground"
|
|
1535
1535
|
),
|
|
1536
1536
|
children: hit.label
|
|
@@ -2205,7 +2205,7 @@ function CiteLink({ entry, label }) {
|
|
|
2205
2205
|
href: `#ref-${cssId(entry.key)}`,
|
|
2206
2206
|
title: entry.data ? hoverTitle(entry.data) : void 0,
|
|
2207
2207
|
"aria-label": `Citation: ${name}`,
|
|
2208
|
-
className: "text-primary-text underline hover:underline focus-visible:rounded-sm focus-
|
|
2208
|
+
className: "text-primary-text underline hover:underline focus-visible:rounded-sm focus-ring",
|
|
2209
2209
|
children: label
|
|
2210
2210
|
}
|
|
2211
2211
|
);
|
|
@@ -2310,7 +2310,7 @@ var Bibliography = forwardRef4(function Bibliography2({ entries, style, title =
|
|
|
2310
2310
|
href,
|
|
2311
2311
|
target: "_blank",
|
|
2312
2312
|
rel: "noopener noreferrer",
|
|
2313
|
-
className: "break-words text-primary-text underline underline-offset-2 hover:underline focus-visible:rounded-sm focus-
|
|
2313
|
+
className: "break-words text-primary-text underline underline-offset-2 hover:underline focus-visible:rounded-sm focus-ring",
|
|
2314
2314
|
children: data.url ?? `doi:${data.doi}`
|
|
2315
2315
|
}
|
|
2316
2316
|
) : null
|
|
@@ -2413,7 +2413,7 @@ function FootnoteRef({ node: _n, children: _c, ...rest }) {
|
|
|
2413
2413
|
href: `#fn-${id}`,
|
|
2414
2414
|
"data-footnote-ref": "",
|
|
2415
2415
|
"aria-label": `Footnote ${n}`,
|
|
2416
|
-
className: "px-0.5 font-medium text-primary-text underline tabular-nums hover:underline focus-visible:rounded-sm focus-
|
|
2416
|
+
className: "px-0.5 font-medium text-primary-text underline tabular-nums hover:underline focus-visible:rounded-sm focus-ring",
|
|
2417
2417
|
children: n
|
|
2418
2418
|
}
|
|
2419
2419
|
) });
|
|
@@ -2437,7 +2437,7 @@ function FootnoteItem({ node: _n, children, ...rest }) {
|
|
|
2437
2437
|
href: `#${refId}`,
|
|
2438
2438
|
"data-footnote-backref": "",
|
|
2439
2439
|
"aria-label": refList.length > 1 ? `Back to reference ${n}, mention ${i + 1}` : `Back to reference ${n}`,
|
|
2440
|
-
className: "ms-0.5 inline-flex items-center text-muted-foreground no-underline hover:text-foreground focus-visible:rounded-sm focus-
|
|
2440
|
+
className: "ms-0.5 inline-flex items-center text-muted-foreground no-underline hover:text-foreground focus-visible:rounded-sm focus-ring",
|
|
2441
2441
|
children: [
|
|
2442
2442
|
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "\u21A9" }),
|
|
2443
2443
|
refList.length > 1 ? /* @__PURE__ */ jsx8("sub", { className: "ms-0.5 leading-none tabular-nums", children: i + 1 }) : null
|
|
@@ -2596,7 +2596,7 @@ var TableOfContents = forwardRef6(
|
|
|
2596
2596
|
"a",
|
|
2597
2597
|
{
|
|
2598
2598
|
href: `#${it.id}`,
|
|
2599
|
-
className: "text-muted-foreground underline hover:text-foreground hover:underline focus-visible:rounded-sm focus-
|
|
2599
|
+
className: "text-muted-foreground underline hover:text-foreground hover:underline focus-visible:rounded-sm focus-ring",
|
|
2600
2600
|
children: it.text
|
|
2601
2601
|
}
|
|
2602
2602
|
) }, it.id)) })
|
|
@@ -4277,7 +4277,7 @@ function kindMeta(kind) {
|
|
|
4277
4277
|
var entityChipVariants = cva2(
|
|
4278
4278
|
// inline-flex + align-middle keeps the chip in the text baseline;
|
|
4279
4279
|
// no `block` wrapper so it is valid inside <p>.
|
|
4280
|
-
"inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 text-meta font-medium align-middle focus-
|
|
4280
|
+
"inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 text-meta font-medium align-middle focus-ring",
|
|
4281
4281
|
{
|
|
4282
4282
|
variants: {
|
|
4283
4283
|
kind: {
|
|
@@ -4375,7 +4375,7 @@ function SourceRow({ path, resolve }) {
|
|
|
4375
4375
|
href: resolved.href,
|
|
4376
4376
|
rel: "noopener noreferrer",
|
|
4377
4377
|
target: "_blank",
|
|
4378
|
-
className: "flex min-w-0 items-center gap-1.5 text-meta text-primary-text underline-offset-2 hover:underline focus-
|
|
4378
|
+
className: "flex min-w-0 items-center gap-1.5 text-meta text-primary-text underline-offset-2 hover:underline focus-ring",
|
|
4379
4379
|
"aria-label": `Source: ${display}`,
|
|
4380
4380
|
children: [
|
|
4381
4381
|
/* @__PURE__ */ jsx18(FileText, { className: "size-3 shrink-0", "aria-hidden": "true" }),
|