@elabs-ai/components-editor 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-C62O7IOQ.js → chunk-FO5S3YZM.js} +241 -158
- package/dist/chunk-FO5S3YZM.js.map +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +57 -39
- package/dist/index.js.map +1 -1
- package/dist/markdown/index.d.ts +2 -2
- package/dist/markdown/index.js +265 -188
- package/dist/markdown/index.js.map +1 -1
- package/dist/{markdown-editor-CBp_4eDv.d.ts → markdown-editor-Dn-0L_MM.d.ts} +8 -1
- package/dist/monaco.d.ts +2 -0
- package/dist/monaco.js +9 -0
- package/dist/monaco.js.map +1 -0
- package/package.json +9 -5
- package/src/ai-objects/decision-card.tsx +15 -9
- package/src/ai-objects/knowledge-card.tsx +18 -9
- package/src/barrel-monaco-lazy.test.ts +50 -0
- package/src/calc-block/calc-block.tsx +11 -7
- package/src/code-editor/code-editor.test.tsx +141 -14
- package/src/code-editor/code-editor.tsx +166 -35
- package/src/code-workspace/code-workspace.test.tsx +31 -12
- package/src/copy-button/copy-button.tsx +6 -3
- package/src/diff-editor/diff-editor.test.tsx +9 -3
- package/src/diff-editor/diff-editor.tsx +47 -23
- package/src/editor-toolbar/editor-toolbar.tsx +8 -2
- package/src/index.ts +4 -3
- package/src/markdown-academic/citations.tsx +14 -7
- package/src/markdown-academic/footnotes.tsx +1 -1
- package/src/markdown-academic/math.tsx +7 -4
- package/src/markdown-editor/completions/completions-menu.tsx +5 -2
- package/src/markdown-editor/directive-views.tsx +33 -19
- package/src/markdown-editor/markdown-editor.stories.tsx +9 -3
- package/src/markdown-editor/slash/slash-menu.tsx +5 -2
- package/src/markdown-editor/table-view.tsx +28 -15
- package/src/markdown-iteration/iteration-builder-dialog.tsx +39 -18
- package/src/markdown-iteration/template-dialog.tsx +25 -7
- package/src/markdown-outline/document-outline.tsx +6 -2
- package/src/markdown-preview/markdown-preview-academic.test.tsx +3 -3
- package/src/markdown-toolbar/markdown-toolbar.tsx +42 -24
- package/src/markdown-workspace/markdown-workspace.test.tsx +22 -3
- package/src/markdown-workspace/markdown-workspace.tsx +6 -3
- package/src/mermaid-diagram/mermaid-diagram-fixes.test.tsx +130 -0
- package/src/mermaid-diagram/mermaid-diagram.test.tsx +2 -1
- package/src/mermaid-diagram/mermaid-diagram.tsx +89 -40
- package/src/mermaid-diagram/mermaid-viewer.tsx +21 -20
- package/src/monaco.ts +21 -0
- package/dist/chunk-C62O7IOQ.js.map +0 -1
|
@@ -7,9 +7,10 @@ const renderMock = vi.fn(async (_id: string, chart: string) => {
|
|
|
7
7
|
svg: `<svg data-chart="ok"><g class="node"><rect></rect><text>Microsoft Graph API</text></g><g class="node"><rect></rect><text>Worker</text></g></svg>`,
|
|
8
8
|
};
|
|
9
9
|
});
|
|
10
|
+
const initializeMock = vi.fn();
|
|
10
11
|
|
|
11
12
|
vi.mock("mermaid", () => ({
|
|
12
|
-
default: { initialize:
|
|
13
|
+
default: { initialize: initializeMock, render: renderMock },
|
|
13
14
|
}));
|
|
14
15
|
|
|
15
16
|
import { MermaidDiagram } from "./mermaid-diagram";
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* never show a diagram never download the engine. Invalid sources render an
|
|
14
14
|
* inline error block (message + source), never a thrown render.
|
|
15
15
|
*/
|
|
16
|
-
import { Button, Dialog, DialogContent, DialogTitle } from "@elabs-ai/components-ui";
|
|
16
|
+
import { Button, Dialog, DialogContent, DialogTitle, useLocale } from "@elabs-ai/components-ui";
|
|
17
17
|
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
18
18
|
import { Download, Maximize2 } from "lucide-react";
|
|
19
19
|
import { forwardRef, useEffect, useRef, useState, type HTMLAttributes } from "react";
|
|
@@ -67,6 +67,39 @@ const TOKEN_VARS: Record<string, string> = {
|
|
|
67
67
|
|
|
68
68
|
let renderSeq = 0;
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Serializes every `mermaid.initialize()` + `mermaid.render()` pair across
|
|
72
|
+
* every `MermaidDiagram` instance on the page.
|
|
73
|
+
*
|
|
74
|
+
* The `mermaid` package configures itself through ONE module-level global
|
|
75
|
+
* (`mermaid.initialize`/`setConfig`) — `render()` takes no per-call config —
|
|
76
|
+
* so two diagrams rendering concurrently (e.g. under different `data-theme`
|
|
77
|
+
* scopes, or just two diagrams mounting together) can interleave: instance A
|
|
78
|
+
* calls `initialize({theme: A})`, then before A's `render()` finishes reading
|
|
79
|
+
* it, instance B calls `initialize({theme: B})` and A's diagram comes out
|
|
80
|
+
* themed as B. Routing every render through this queue makes "initialize,
|
|
81
|
+
* then render" atomic with respect to every other instance.
|
|
82
|
+
*/
|
|
83
|
+
let mermaidRenderQueue: Promise<unknown> = Promise.resolve();
|
|
84
|
+
|
|
85
|
+
function withMermaidLock<T>(task: () => Promise<T>): Promise<T> {
|
|
86
|
+
const result = mermaidRenderQueue.then(task, task);
|
|
87
|
+
// Never let a failed render break the chain for the next caller.
|
|
88
|
+
mermaidRenderQueue = result.then(
|
|
89
|
+
() => undefined,
|
|
90
|
+
() => undefined,
|
|
91
|
+
);
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* How long to let `chart` sit unchanged before actually rendering it — a
|
|
97
|
+
* source streamed in token-by-token (an LLM authoring one live) would
|
|
98
|
+
* otherwise trigger a full mermaid parse + layout on every partial,
|
|
99
|
+
* malformed intermediate string.
|
|
100
|
+
*/
|
|
101
|
+
const RENDER_DEBOUNCE_MS = 300;
|
|
102
|
+
|
|
70
103
|
/**
|
|
71
104
|
* Search-hit strokes for rendered nodes — token-driven, shared by the inline
|
|
72
105
|
* render and the expanded viewer (a `<style>` is document-global wherever it
|
|
@@ -127,7 +160,7 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
127
160
|
function MermaidDiagram(
|
|
128
161
|
{
|
|
129
162
|
chart,
|
|
130
|
-
label
|
|
163
|
+
label: labelProp,
|
|
131
164
|
copyable = true,
|
|
132
165
|
expandable = true,
|
|
133
166
|
highlightTerm,
|
|
@@ -137,6 +170,8 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
137
170
|
},
|
|
138
171
|
ref,
|
|
139
172
|
) {
|
|
173
|
+
const { t } = useLocale();
|
|
174
|
+
const label = labelProp ?? t("editor.mermaidDiagram.label");
|
|
140
175
|
const hostRef = useRef<HTMLDivElement | null>(null);
|
|
141
176
|
const svgHostRef = useRef<HTMLDivElement | null>(null);
|
|
142
177
|
const [svg, setSvg] = useState<string | null>(null);
|
|
@@ -151,7 +186,10 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
151
186
|
a.href = url;
|
|
152
187
|
a.download = `${label.toLowerCase().replace(/[^a-z0-9]+/g, "-") || "diagram"}.svg`;
|
|
153
188
|
a.click();
|
|
154
|
-
|
|
189
|
+
// Defer the revoke past the current task: some browsers (Safari) start
|
|
190
|
+
// the save asynchronously off the click and cancel it if the object URL
|
|
191
|
+
// is invalidated too early.
|
|
192
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
155
193
|
};
|
|
156
194
|
// Bumped by the observer when the governing data-theme changes.
|
|
157
195
|
const [themeVersion, setThemeVersion] = useState(0);
|
|
@@ -173,43 +211,52 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
173
211
|
setError(null);
|
|
174
212
|
return;
|
|
175
213
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
214
|
+
// Debounce: a `chart` fed from a streaming source changes on every
|
|
215
|
+
// token, and a mermaid parse + layout is not cheap enough to run on
|
|
216
|
+
// every one of those partial, often-invalid intermediate strings — wait
|
|
217
|
+
// for the source to sit still for RENDER_DEBOUNCE_MS first.
|
|
218
|
+
const timer = setTimeout(() => {
|
|
219
|
+
void withMermaidLock(async () => {
|
|
179
220
|
if (cancelled) return;
|
|
180
|
-
mermaid.initialize({
|
|
181
|
-
startOnLoad: false,
|
|
182
|
-
securityLevel: "strict",
|
|
183
|
-
suppressErrorRendering: true,
|
|
184
|
-
theme: "base",
|
|
185
|
-
themeVariables: resolveThemeVariables(host),
|
|
186
|
-
});
|
|
187
|
-
const render = (source: string) => mermaid.render(`brand-mermaid-${++renderSeq}`, source);
|
|
188
|
-
let out;
|
|
189
221
|
try {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
222
|
+
const mermaid = (await import("mermaid")).default;
|
|
223
|
+
if (cancelled) return;
|
|
224
|
+
mermaid.initialize({
|
|
225
|
+
startOnLoad: false,
|
|
226
|
+
securityLevel: "strict",
|
|
227
|
+
suppressErrorRendering: true,
|
|
228
|
+
theme: "base",
|
|
229
|
+
themeVariables: resolveThemeVariables(host),
|
|
230
|
+
});
|
|
231
|
+
const render = (source: string) =>
|
|
232
|
+
mermaid.render(`brand-mermaid-${++renderSeq}`, source);
|
|
233
|
+
let out;
|
|
234
|
+
try {
|
|
235
|
+
out = await render(chart);
|
|
236
|
+
} catch (firstErr) {
|
|
237
|
+
// Reserved-keyword node ids ("graph[...]", "end[...]") are the
|
|
238
|
+
// most common authoring mistake — remediate the id (labels stay)
|
|
239
|
+
// and retry once instead of failing the reader.
|
|
240
|
+
const token = offendingToken(
|
|
241
|
+
firstErr instanceof Error ? firstErr.message : String(firstErr),
|
|
242
|
+
);
|
|
243
|
+
const fixed = token ? remediateReservedIds(chart, token) : null;
|
|
244
|
+
if (!fixed) throw firstErr;
|
|
245
|
+
out = await render(fixed);
|
|
246
|
+
}
|
|
247
|
+
if (cancelled) return;
|
|
248
|
+
setSvg(out.svg);
|
|
249
|
+
setError(null);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
if (cancelled) return;
|
|
252
|
+
setSvg(null);
|
|
253
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
201
254
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
setError(null);
|
|
205
|
-
} catch (err) {
|
|
206
|
-
if (cancelled) return;
|
|
207
|
-
setSvg(null);
|
|
208
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
209
|
-
}
|
|
210
|
-
})();
|
|
255
|
+
});
|
|
256
|
+
}, RENDER_DEBOUNCE_MS);
|
|
211
257
|
return () => {
|
|
212
258
|
cancelled = true;
|
|
259
|
+
clearTimeout(timer);
|
|
213
260
|
};
|
|
214
261
|
}, [chart, themeVersion]);
|
|
215
262
|
|
|
@@ -248,7 +295,7 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
248
295
|
<Button
|
|
249
296
|
variant="outline"
|
|
250
297
|
size="icon-sm"
|
|
251
|
-
aria-label="
|
|
298
|
+
aria-label={t("editor.mermaidDiagram.expand")}
|
|
252
299
|
onClick={() => setExpanded(true)}
|
|
253
300
|
>
|
|
254
301
|
<Maximize2 className="size-3.5" />
|
|
@@ -257,7 +304,7 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
257
304
|
<Button
|
|
258
305
|
variant="outline"
|
|
259
306
|
size="icon-sm"
|
|
260
|
-
aria-label="
|
|
307
|
+
aria-label={t("editor.mermaidDiagram.downloadSvg")}
|
|
261
308
|
onClick={downloadSvg}
|
|
262
309
|
>
|
|
263
310
|
<Download className="size-3.5" />
|
|
@@ -266,7 +313,7 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
266
313
|
<CopyButton
|
|
267
314
|
value={chart}
|
|
268
315
|
label={false}
|
|
269
|
-
aria-label="
|
|
316
|
+
aria-label={t("editor.mermaidDiagram.copySource")}
|
|
270
317
|
size="icon-sm"
|
|
271
318
|
/>
|
|
272
319
|
) : null}
|
|
@@ -277,7 +324,9 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
277
324
|
role="alert"
|
|
278
325
|
className="space-y-2 border-s-2 border-s-destructive bg-destructive/10 p-3 text-body"
|
|
279
326
|
>
|
|
280
|
-
<p className="font-medium text-destructive-text">
|
|
327
|
+
<p className="font-medium text-destructive-text">
|
|
328
|
+
{t("editor.mermaidDiagram.renderFailed")}
|
|
329
|
+
</p>
|
|
281
330
|
<p className="text-muted-foreground">{error}</p>
|
|
282
331
|
<pre className="overflow-x-auto rounded bg-muted p-2 font-mono text-code text-foreground">
|
|
283
332
|
{chart}
|
|
@@ -298,7 +347,7 @@ export const MermaidDiagram = forwardRef<HTMLDivElement, MermaidDiagramProps>(
|
|
|
298
347
|
) : (
|
|
299
348
|
<div
|
|
300
349
|
role="status"
|
|
301
|
-
aria-label="
|
|
350
|
+
aria-label={t("editor.mermaidDiagram.rendering")}
|
|
302
351
|
className="h-24 animate-pulse rounded-md bg-surface-muted motion-reduce:animate-none"
|
|
303
352
|
/>
|
|
304
353
|
)}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* drag-pan, fit/100% controls, and a left search panel that filters the
|
|
6
6
|
* RENDERED nodes, highlights every hit and zooms to the selected one.
|
|
7
7
|
*/
|
|
8
|
-
import { Button, Input } from "@elabs-ai/components-ui";
|
|
8
|
+
import { Button, Input, useLocale } from "@elabs-ai/components-ui";
|
|
9
9
|
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
10
10
|
import { Maximize, Minus, Plus } from "lucide-react";
|
|
11
11
|
import {
|
|
@@ -79,6 +79,7 @@ export function diagramNodeLabel(node: Element): string {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
82
|
+
const { t } = useLocale();
|
|
82
83
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
83
84
|
const stageRef = useRef<HTMLDivElement | null>(null);
|
|
84
85
|
const [transform, setTransform] = useState<Transform>({ scale: 1, tx: 0, ty: 0 });
|
|
@@ -188,10 +189,10 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
188
189
|
if (!container) return;
|
|
189
190
|
userDrivenRef.current = true;
|
|
190
191
|
const rect = container.getBoundingClientRect();
|
|
191
|
-
setTransform((
|
|
192
|
-
const scale = clampScale(
|
|
193
|
-
const px = (clientX - rect.left -
|
|
194
|
-
const py = (clientY - rect.top -
|
|
192
|
+
setTransform((prev) => {
|
|
193
|
+
const scale = clampScale(prev.scale * factor);
|
|
194
|
+
const px = (clientX - rect.left - prev.tx) / prev.scale;
|
|
195
|
+
const py = (clientY - rect.top - prev.ty) / prev.scale;
|
|
195
196
|
return { scale, tx: clientX - rect.left - px * scale, ty: clientY - rect.top - py * scale };
|
|
196
197
|
});
|
|
197
198
|
}, []);
|
|
@@ -210,13 +211,13 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
210
211
|
if (!container || !svgEl || !node) return;
|
|
211
212
|
userDrivenRef.current = true;
|
|
212
213
|
setActiveHit(id);
|
|
213
|
-
setTransform((
|
|
214
|
+
setTransform((prev) => {
|
|
214
215
|
const nodeRect = node.getBoundingClientRect();
|
|
215
216
|
const containerRect = container.getBoundingClientRect();
|
|
216
217
|
// Node center in svg-space (invert the current transform).
|
|
217
|
-
const cx = (nodeRect.left + nodeRect.width / 2 - containerRect.left -
|
|
218
|
-
const cy = (nodeRect.top + nodeRect.height / 2 - containerRect.top -
|
|
219
|
-
const scale = clampScale(Math.max(
|
|
218
|
+
const cx = (nodeRect.left + nodeRect.width / 2 - containerRect.left - prev.tx) / prev.scale;
|
|
219
|
+
const cy = (nodeRect.top + nodeRect.height / 2 - containerRect.top - prev.ty) / prev.scale;
|
|
220
|
+
const scale = clampScale(Math.max(prev.scale, 1.25));
|
|
220
221
|
return {
|
|
221
222
|
scale,
|
|
222
223
|
tx: containerRect.width / 2 - cx * scale,
|
|
@@ -239,8 +240,8 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
239
240
|
const onPointerMove = (e: ReactPointerEvent<HTMLDivElement>) => {
|
|
240
241
|
const drag = dragRef.current;
|
|
241
242
|
if (!drag) return;
|
|
242
|
-
setTransform((
|
|
243
|
-
...
|
|
243
|
+
setTransform((prev) => ({
|
|
244
|
+
...prev,
|
|
244
245
|
tx: drag.tx + (e.clientX - drag.x),
|
|
245
246
|
ty: drag.ty + (e.clientY - drag.y),
|
|
246
247
|
}));
|
|
@@ -256,8 +257,8 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
256
257
|
<Input
|
|
257
258
|
autoFocus
|
|
258
259
|
type="search"
|
|
259
|
-
placeholder="
|
|
260
|
-
aria-label="
|
|
260
|
+
placeholder={t("editor.mermaidViewer.findPlaceholder")}
|
|
261
|
+
aria-label={t("editor.mermaidViewer.findLabel")}
|
|
261
262
|
value={query}
|
|
262
263
|
onChange={(e) => setQuery(e.target.value)}
|
|
263
264
|
spellCheck={false}
|
|
@@ -265,8 +266,8 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
265
266
|
/>
|
|
266
267
|
<p aria-live="polite" className="px-1 pt-1.5 text-meta text-muted-foreground tabular-nums">
|
|
267
268
|
{q.length >= 2
|
|
268
|
-
?
|
|
269
|
-
:
|
|
269
|
+
? t("editor.mermaidViewer.matchCount", { count: matches.length })
|
|
270
|
+
: t("editor.mermaidViewer.nodeCountHint", { count: hits.length })}
|
|
270
271
|
</p>
|
|
271
272
|
<ul className="m-0 mt-1 min-h-0 flex-1 list-none overflow-auto p-0">
|
|
272
273
|
{(q.length >= 2 ? matches : hits).map((hit) => (
|
|
@@ -297,7 +298,7 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
297
298
|
<Button
|
|
298
299
|
variant="outline"
|
|
299
300
|
size="icon-sm"
|
|
300
|
-
aria-label="
|
|
301
|
+
aria-label={t("editor.mermaidViewer.zoomOut")}
|
|
301
302
|
onClick={() => zoomCenter(1 / 1.25)}
|
|
302
303
|
>
|
|
303
304
|
<Minus className="size-3.5" />
|
|
@@ -305,7 +306,7 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
305
306
|
<Button
|
|
306
307
|
variant="outline"
|
|
307
308
|
size="icon-sm"
|
|
308
|
-
aria-label="
|
|
309
|
+
aria-label={t("editor.mermaidViewer.zoomIn")}
|
|
309
310
|
onClick={() => zoomCenter(1.25)}
|
|
310
311
|
>
|
|
311
312
|
<Plus className="size-3.5" />
|
|
@@ -314,10 +315,10 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
314
315
|
variant="outline"
|
|
315
316
|
size="sm"
|
|
316
317
|
className="h-7 px-2 font-mono text-meta tabular-nums"
|
|
317
|
-
aria-label="
|
|
318
|
+
aria-label={t("editor.mermaidViewer.resetZoom")}
|
|
318
319
|
onClick={() => {
|
|
319
320
|
userDrivenRef.current = true;
|
|
320
|
-
setTransform((
|
|
321
|
+
setTransform((prev) => ({ ...prev, scale: 1 }));
|
|
321
322
|
}}
|
|
322
323
|
>
|
|
323
324
|
{Math.round(transform.scale * 100)}%
|
|
@@ -325,7 +326,7 @@ export function MermaidViewer({ svg, label }: { svg: string; label: string }) {
|
|
|
325
326
|
<Button
|
|
326
327
|
variant="outline"
|
|
327
328
|
size="icon-sm"
|
|
328
|
-
aria-label="
|
|
329
|
+
aria-label={t("editor.mermaidViewer.fitDiagram")}
|
|
329
330
|
onClick={() => {
|
|
330
331
|
// An explicit fit hands control back: keep fitting on resize.
|
|
331
332
|
userDrivenRef.current = false;
|
package/src/monaco.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `monaco-editor` namespace, as its own subpath (ADR 0006 subpath exports).
|
|
5
|
+
*
|
|
6
|
+
* The root barrel (`.`) exports lightweight chrome — `CopyButton`,
|
|
7
|
+
* `EDITOR_LANGUAGES`, `languageLabel` — that a consumer should be able to
|
|
8
|
+
* import WITHOUT pulling Monaco in at all: the editing surfaces
|
|
9
|
+
* (`CodeEditor`, `DiffEditor`, `MarkdownEditor`) already own lazy-loading the
|
|
10
|
+
* engine themselves. Re-exporting the whole `monaco-editor` namespace from
|
|
11
|
+
* that SAME barrel defeated that split — `import { CopyButton } from
|
|
12
|
+
* "@elabs-ai/components-editor"` pulled megabytes of Monaco and touched
|
|
13
|
+
* browser globals at import time, breaking SSR/RSC for a component that never
|
|
14
|
+
* renders the editor.
|
|
15
|
+
*
|
|
16
|
+
* A consumer that needs to build a custom editor, or wire Monaco commands
|
|
17
|
+
* directly, imports this subpath instead:
|
|
18
|
+
*
|
|
19
|
+
* import { monaco } from "@elabs-ai/components-editor/monaco";
|
|
20
|
+
*/
|
|
21
|
+
export * as monaco from "monaco-editor";
|