@bettercms-ai/kit 2.0.0-next.1 → 2.0.0-next.3
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/adapters/lossy.d.ts +4 -0
- package/dist/adapters/lossy.js +8 -2
- package/dist/adapters/lossy.js.map +1 -1
- package/dist/adapters/schema.js +28 -0
- package/dist/adapters/schema.js.map +1 -1
- package/dist/controls/link.d.ts +11 -4
- package/dist/controls/link.js +8 -6
- package/dist/controls/link.js.map +1 -1
- package/dist/controls/rich-text/article-shell.js +1 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -1
- package/dist/controls/rich-text/blocks.d.ts +6 -0
- package/dist/controls/rich-text/blocks.js +188 -0
- package/dist/controls/rich-text/blocks.js.map +1 -1
- package/dist/controls/rich-text/button.d.ts +2 -2
- package/dist/controls/rich-text/button.js +10 -14
- package/dist/controls/rich-text/button.js.map +1 -1
- package/dist/controls/rich-text/catalog.d.ts +2 -5
- package/dist/controls/rich-text/catalog.js +105 -7
- package/dist/controls/rich-text/catalog.js.map +1 -1
- package/dist/controls/rich-text/codec.d.ts +13 -1
- package/dist/controls/rich-text/codec.js +7 -0
- package/dist/controls/rich-text/codec.js.map +1 -1
- package/dist/controls/rich-text/control.js +1 -0
- package/dist/controls/rich-text/control.js.map +1 -1
- package/dist/controls/rich-text/dom.d.ts +79 -0
- package/dist/controls/rich-text/dom.js +159 -7
- package/dist/controls/rich-text/dom.js.map +1 -1
- package/dist/controls/rich-text/editor.d.ts +4 -2
- package/dist/controls/rich-text/editor.js +109 -18
- package/dist/controls/rich-text/editor.js.map +1 -1
- package/dist/controls/rich-text/link-form.d.ts +10 -0
- package/dist/controls/rich-text/link-form.js +39 -5
- package/dist/controls/rich-text/link-form.js.map +1 -1
- package/dist/controls/rich-text/ops.js +6 -0
- package/dist/controls/rich-text/ops.js.map +1 -1
- package/dist/controls/rich-text/related.d.ts +12 -4
- package/dist/controls/rich-text/related.js +22 -11
- package/dist/controls/rich-text/related.js.map +1 -1
- package/dist/controls/rich-text/toc.d.ts +3 -2
- package/dist/controls/rich-text/toc.js +1 -2
- package/dist/controls/rich-text/toc.js.map +1 -1
- package/dist/core/core.d.ts +1 -0
- package/dist/core/core.js +2 -0
- package/dist/core/core.js.map +1 -1
- package/dist/core/facets.d.ts +8 -0
- package/dist/core/facets.js +8 -0
- package/dist/core/facets.js.map +1 -1
- package/dist/library/kit-catalog.json +4 -2
- package/dist/schema/types.d.ts +8 -0
- package/dist/schema/types.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui/overlay.d.ts +4 -1
- package/dist/ui/overlay.js +2 -1
- package/dist/ui/overlay.js.map +1 -1
- package/package.json +2 -2
|
@@ -4,11 +4,13 @@ import { Button } from "../../ui/button.js";
|
|
|
4
4
|
import { shortcutHintsOn } from "../../ui/shortcut-hint.js";
|
|
5
5
|
import { Menu, MenuContent, MenuItem, MenuSeparator, MenuSub, MenuSubContent, MenuSubTrigger, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from "../../ui/overlay.js";
|
|
6
6
|
import { Textarea } from "../../ui/input.js";
|
|
7
|
+
import { LinkPopoverBody } from "../link.js";
|
|
7
8
|
import { ExpandedEditorModal } from "../../ui/expanded-editor-modal.js";
|
|
8
9
|
import { COMPONENT_INSERT_TOAST } from "../component-services.js";
|
|
9
10
|
import { eventKey } from "../../lib/key-event.js";
|
|
10
11
|
import { closestBlock, createIsland, defaultModel, editingHost, esc, hydrate, isEmptyHtml, placeCaret, rangeRect, rid, sanitize, serialize, textBeforeCaret, topBlock } from "./dom.js";
|
|
11
|
-
import {
|
|
12
|
+
import { applyTextLink, fromLinkValue, textLinkOf, toLinkValue } from "./link-form.js";
|
|
13
|
+
import { createOutlineStore, outlineOf } from "./toc.js";
|
|
12
14
|
import { CatalogComponentsProvider, InsertMenuContent, SlashMenuPanel, blockAllowed, catalogKey, noteRecent, useCatalog } from "./catalog.js";
|
|
13
15
|
import { openComponentPanel } from "./component-panel.js";
|
|
14
16
|
import { Island } from "./blocks.js";
|
|
@@ -19,6 +21,7 @@ import { ALL_FEATURES } from "./codec.js";
|
|
|
19
21
|
import { htmlToMarkdown, looksLikeMarkdown, markdownToHtml } from "./markdown.js";
|
|
20
22
|
import { EMPTY_FMT, FormatToolbar, MARK_FEATURE, stylesFor } from "./toolbar.js";
|
|
21
23
|
import { SelectionBubble } from "./floating.js";
|
|
24
|
+
import { FN_MARK, FOOTNOTE_POPOVER_CLASS, FOOTNOTE_REFUSED, FootnoteEditor, FootnotesList, backToMarker, caretAfterMarker, insertFootnote, renumberFootnotes } from "./footnote.js";
|
|
22
25
|
import * as React from "react";
|
|
23
26
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
24
27
|
import { IconArrowBarToDown, IconArrowBarToUp, IconCopy, IconGripVertical, IconPlus, IconTransform, IconTrash } from "@tabler/icons-react";
|
|
@@ -175,7 +178,7 @@ function slashPlacement(caret, viewportH) {
|
|
|
175
178
|
maxHeight: Math.max(SLASH_MIN_H, Math.min(SLASH_MENU_H, flipUp ? above : below))
|
|
176
179
|
};
|
|
177
180
|
}
|
|
178
|
-
function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, features = ALL_FEATURES, single, allowNewTab = true, id, invalid, variant = "document", expandCrumbs, expandedOpen, onExpandedOpenChange, inModal, hideFullscreen, maxHeight, autoFocus, onComment, components }) {
|
|
181
|
+
function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, features = ALL_FEATURES, references, single, allowNewTab = true, id, invalid, variant = "document", expandCrumbs, expandedOpen, onExpandedOpenChange, inModal, hideFullscreen, maxHeight, autoFocus, onComment, components }) {
|
|
179
182
|
const hints = shortcutHintsOn();
|
|
180
183
|
const ph = placeholder ?? (hints ? "Type '/' for commands" : "Write something…");
|
|
181
184
|
const dense = variant === "panel";
|
|
@@ -263,6 +266,11 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
263
266
|
const t = window.setTimeout(() => setNotice(null), 8e3);
|
|
264
267
|
return () => window.clearTimeout(t);
|
|
265
268
|
}, [notice]);
|
|
269
|
+
/** V2 article-blocks.tsx:45-66: one live outline per editor, so every table of contents follows the headings */
|
|
270
|
+
const outline = React.useRef(createOutlineStore());
|
|
271
|
+
/** V2 rich-text-editor.tsx:271-276: the body's markers in text order, and the one whose note is open */
|
|
272
|
+
const [footnotes, setFootnotes] = React.useState([]);
|
|
273
|
+
const [fnEdit, setFnEdit] = React.useState(null);
|
|
266
274
|
const syncIslands = React.useCallback(() => {
|
|
267
275
|
const el = ref.current;
|
|
268
276
|
if (!el) return setIslands((p) => p.length ? [] : p);
|
|
@@ -286,8 +294,12 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
286
294
|
const el = ref.current;
|
|
287
295
|
if (!el) return;
|
|
288
296
|
el.innerHTML = sanitize(html || "") || "<p><br></p>";
|
|
297
|
+
el.querySelectorAll(":scope > ol[data-rt=\"footnotes\"]").forEach((n) => n.remove());
|
|
298
|
+
el.querySelectorAll(FN_MARK).forEach((m) => m.setAttribute("contenteditable", "false"));
|
|
289
299
|
hydrate(el);
|
|
290
300
|
syncTaskA11y(el);
|
|
301
|
+
setFootnotes(renumberFootnotes(el));
|
|
302
|
+
outline.current.set(outlineOf(el));
|
|
291
303
|
known.current = html;
|
|
292
304
|
setEmpty(isEmptyHtml(html));
|
|
293
305
|
setWords(countWords(html));
|
|
@@ -299,6 +311,8 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
299
311
|
if (!el) return;
|
|
300
312
|
syncIslands();
|
|
301
313
|
syncTaskA11y(el);
|
|
314
|
+
outline.current.set(outlineOf(el));
|
|
315
|
+
setFootnotes(renumberFootnotes(el));
|
|
302
316
|
const html = serialize(el);
|
|
303
317
|
setEmpty(isEmptyHtml(html) && !el.querySelector(":scope > [data-rt-island], :scope > hr"));
|
|
304
318
|
setWords(countWords(html));
|
|
@@ -584,6 +598,13 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
584
598
|
}
|
|
585
599
|
if (!it.id || !blockAllowed(it.id, allows)) return;
|
|
586
600
|
noteRecent(it);
|
|
601
|
+
if (it.id === "footnote") {
|
|
602
|
+
const m = insertFootnote(el);
|
|
603
|
+
if (!m) return void notify(FOOTNOTE_REFUSED.title, { description: FOOTNOTE_REFUSED.description });
|
|
604
|
+
emit();
|
|
605
|
+
openFootnote(m, true);
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
587
608
|
if (it.id === "task") insertChecklist(el);
|
|
588
609
|
else if (it.id === "button") {
|
|
589
610
|
const a = insertButton(el);
|
|
@@ -591,7 +612,11 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
591
612
|
refresh();
|
|
592
613
|
openButton(a);
|
|
593
614
|
return;
|
|
594
|
-
} else
|
|
615
|
+
} else if (it.id === "related" && references?.topic === false) insertIsland(el, "related", {
|
|
616
|
+
...defaultModel("related"),
|
|
617
|
+
mode: "newest"
|
|
618
|
+
});
|
|
619
|
+
else insertBasic(el, it.id);
|
|
595
620
|
emit();
|
|
596
621
|
refresh();
|
|
597
622
|
};
|
|
@@ -832,12 +857,31 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
832
857
|
setLink({
|
|
833
858
|
rect,
|
|
834
859
|
existing: anchor,
|
|
835
|
-
initial: anchor ? {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
860
|
+
initial: anchor ? textLinkOf(anchor) : { href: "" }
|
|
861
|
+
});
|
|
862
|
+
};
|
|
863
|
+
const openFootnote = (m, fresh = false) => {
|
|
864
|
+
if (readOnly) return;
|
|
865
|
+
setBubble(null);
|
|
866
|
+
setFnEdit({
|
|
867
|
+
el: m,
|
|
868
|
+
rect: m.getBoundingClientRect(),
|
|
869
|
+
fresh
|
|
839
870
|
});
|
|
840
871
|
};
|
|
872
|
+
const removeFootnote = (m) => {
|
|
873
|
+
setFnEdit(null);
|
|
874
|
+
m.remove();
|
|
875
|
+
emit();
|
|
876
|
+
};
|
|
877
|
+
/** closed: a new footnote with no note is taken back out (V2), else the caret goes back after its marker */
|
|
878
|
+
const closeFootnote = () => {
|
|
879
|
+
const f = fnEdit;
|
|
880
|
+
setFnEdit(null);
|
|
881
|
+
if (!f || !ref.current) return;
|
|
882
|
+
if (f.fresh && !(f.el.getAttribute("data-note") ?? "").trim()) return removeFootnote(f.el);
|
|
883
|
+
caretAfterMarker(ref.current, f.el);
|
|
884
|
+
};
|
|
841
885
|
/** V2 rich-text-editor.tsx:865-873: a button's popover, its label above the link form */
|
|
842
886
|
const openButton = (a) => {
|
|
843
887
|
if (readOnly) return;
|
|
@@ -865,15 +909,14 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
865
909
|
setLink(null);
|
|
866
910
|
if (!l) return;
|
|
867
911
|
if (l.existing) {
|
|
868
|
-
l.existing
|
|
869
|
-
if (v.newTab) l.existing.setAttribute("target", "_blank");
|
|
870
|
-
else l.existing.removeAttribute("target");
|
|
912
|
+
applyTextLink(l.existing, v);
|
|
871
913
|
emit();
|
|
872
914
|
return;
|
|
873
915
|
}
|
|
874
916
|
run(() => {
|
|
875
917
|
const text = window.getSelection()?.toString() || v.href;
|
|
876
|
-
|
|
918
|
+
const attr = (s) => esc(s).replace(/"/g, """);
|
|
919
|
+
insertHtmlAtCaret(`<a href="${attr(v.href)}"${v.newTab ? ` target="_blank"` : ""}${v.rel ? ` rel="${attr(v.rel)}"` : ""}>${esc(text)}</a>`);
|
|
877
920
|
});
|
|
878
921
|
};
|
|
879
922
|
const aiRewrite = (preset) => {
|
|
@@ -1159,8 +1202,14 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1159
1202
|
undo: () => api.current.islandUndo(),
|
|
1160
1203
|
redo: () => api.current.islandRedo(),
|
|
1161
1204
|
drag: (x, e) => api.current.startDrag(x, e),
|
|
1162
|
-
allows: (f) => api.current.allows(f)
|
|
1163
|
-
|
|
1205
|
+
allows: (f) => api.current.allows(f),
|
|
1206
|
+
outline: outline.current,
|
|
1207
|
+
references
|
|
1208
|
+
}), [
|
|
1209
|
+
readOnly,
|
|
1210
|
+
dense,
|
|
1211
|
+
references
|
|
1212
|
+
]);
|
|
1164
1213
|
const commentSel = onComment ? () => {
|
|
1165
1214
|
restoreSel();
|
|
1166
1215
|
const q = window.getSelection()?.toString().trim();
|
|
@@ -1370,6 +1419,11 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1370
1419
|
emit();
|
|
1371
1420
|
},
|
|
1372
1421
|
onClick: (e) => {
|
|
1422
|
+
const fn = e.target.closest?.(FN_MARK);
|
|
1423
|
+
if (fn && ref.current?.contains(fn) && !fn.closest("[data-rt-island]") && !readOnly) {
|
|
1424
|
+
e.preventDefault();
|
|
1425
|
+
return openFootnote(fn);
|
|
1426
|
+
}
|
|
1373
1427
|
const a = ref.current ? buttonAt(ref.current, e.target) : null;
|
|
1374
1428
|
if (!a || readOnly) return;
|
|
1375
1429
|
e.preventDefault();
|
|
@@ -1422,7 +1476,7 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1422
1476
|
notify("That drop is not an image from the media library");
|
|
1423
1477
|
}
|
|
1424
1478
|
},
|
|
1425
|
-
className: cn(RT_PROSE, dense && "text-kit-sm leading-[1.6] [&_h1:not([data-rt-isolate]_*)]:text-kit-xl [&_h1:not([data-rt-isolate]_*)]:leading-7 [&_h2:not([data-rt-isolate]_*)]:text-kit-lg [&_h2:not([data-rt-isolate]_*)]:leading-7 [&_h3:not([data-rt-isolate]_*)]:text-kit-md [&_h4:not([data-rt-isolate]_*)]:text-kit-base [&_h5:not([data-rt-isolate]_*)]:text-kit-sm [&_h6:not([data-rt-isolate]_*)]:text-kit-xs", "peer relative outline-none focus-visible:shadow-none [&_*:not([data-rt-isolate]_*)]:outline-none", "[&>p[data-hint]]:before:pointer-events-none [&>p[data-hint]]:before:float-left [&>p[data-hint]]:before:h-0 [&>p[data-hint]]:before:text-kit-fg-4 [&>p[data-hint]]:before:content-[attr(data-hint)]", "[&_a[data-button]:not([data-rt-isolate]_*)]:cursor-pointer [&_ul[data-task]>li:not([data-rt-isolate]_*)]:before:cursor-pointer", "[&_sup[data-rt=fn]]:mx-px [&_sup[data-rt=fn]]:cursor-pointer [&_sup[data-rt=fn]]:rounded-kit-sm [&_sup[data-rt=fn]]:px-0.5 [&_sup[data-rt=fn]]:text-[0.72em] [&_sup[data-rt=fn]]:font-semibold [&_sup[data-rt=fn]]:text-kit-accent-fg [&_sup[data-rt=fn]:hover]:bg-kit-accent-soft", dense ? "px-2.5 py-2" : "px-4 py-3.5", minH)
|
|
1479
|
+
className: cn(RT_PROSE, dense && "text-kit-sm leading-[1.6] [&_h1:not([data-rt-isolate]_*)]:text-kit-xl [&_h1:not([data-rt-isolate]_*)]:leading-7 [&_h2:not([data-rt-isolate]_*)]:text-kit-lg [&_h2:not([data-rt-isolate]_*)]:leading-7 [&_h3:not([data-rt-isolate]_*)]:text-kit-md [&_h4:not([data-rt-isolate]_*)]:text-kit-base [&_h5:not([data-rt-isolate]_*)]:text-kit-sm [&_h6:not([data-rt-isolate]_*)]:text-kit-xs", "peer relative outline-none focus-visible:shadow-none [&_*:not([data-rt-isolate]_*)]:outline-none", "[&>p[data-hint]]:before:pointer-events-none [&>p[data-hint]]:before:float-left [&>p[data-hint]]:before:h-0 [&>p[data-hint]]:before:text-kit-fg-4 [&>p[data-hint]]:before:content-[attr(data-hint)]", "[&_a[data-button]:not([data-rt-isolate]_*)]:cursor-pointer [&_ul[data-task]>li:not([data-rt-isolate]_*)]:before:cursor-pointer", "[&_sup[data-rt=fn]]:mx-px [&_sup[data-rt=fn]]:cursor-pointer [&_sup[data-rt=fn]]:rounded-kit-sm [&_sup[data-rt=fn]]:px-0.5 [&_sup[data-rt=fn]]:text-[0.72em] [&_sup[data-rt=fn]]:leading-[0] [&_sup[data-rt=fn]]:font-semibold [&_sup[data-rt=fn]]:text-kit-accent-fg [&_sup[data-rt=fn]:hover]:bg-kit-accent-soft", dense ? "px-2.5 py-2" : "px-4 py-3.5", minH)
|
|
1426
1480
|
}),
|
|
1427
1481
|
empty ? /* @__PURE__ */ jsx("div", {
|
|
1428
1482
|
"aria-hidden": true,
|
|
@@ -1551,6 +1605,13 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1551
1605
|
}), el, key))
|
|
1552
1606
|
]
|
|
1553
1607
|
}),
|
|
1608
|
+
/* @__PURE__ */ jsx(FootnotesList, {
|
|
1609
|
+
notes: footnotes,
|
|
1610
|
+
readOnly,
|
|
1611
|
+
density: dense ? "dense" : "default",
|
|
1612
|
+
onEdit: (m) => openFootnote(m),
|
|
1613
|
+
onBack: (m) => ref.current && backToMarker(ref.current, m)
|
|
1614
|
+
}),
|
|
1554
1615
|
/* @__PURE__ */ jsxs("div", {
|
|
1555
1616
|
className: "flex h-7 items-center justify-end gap-3 rounded-b-kit-lg border-t border-kit-line-subtle px-3 text-kit-2xs text-kit-fg-3",
|
|
1556
1617
|
children: [notice ? /* @__PURE__ */ jsxs("span", {
|
|
@@ -1632,6 +1693,35 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1632
1693
|
maxHeight: slashMaxH
|
|
1633
1694
|
})
|
|
1634
1695
|
})] }), document.body) : null,
|
|
1696
|
+
/* @__PURE__ */ jsxs(Popover, {
|
|
1697
|
+
open: !!fnEdit,
|
|
1698
|
+
onOpenChange: (o) => !o && closeFootnote(),
|
|
1699
|
+
children: [/* @__PURE__ */ jsx(PopoverAnchor, { render: /* @__PURE__ */ jsx("span", {
|
|
1700
|
+
className: "pointer-events-none fixed",
|
|
1701
|
+
style: fnEdit ? {
|
|
1702
|
+
top: fnEdit.rect.bottom,
|
|
1703
|
+
left: fnEdit.rect.left,
|
|
1704
|
+
width: Math.max(1, fnEdit.rect.width),
|
|
1705
|
+
height: 1
|
|
1706
|
+
} : {
|
|
1707
|
+
top: 0,
|
|
1708
|
+
left: 0
|
|
1709
|
+
}
|
|
1710
|
+
}) }), /* @__PURE__ */ jsx(PopoverContent, {
|
|
1711
|
+
className: FOOTNOTE_POPOVER_CLASS,
|
|
1712
|
+
finalFocus: false,
|
|
1713
|
+
children: fnEdit ? /* @__PURE__ */ jsx(FootnoteEditor, {
|
|
1714
|
+
n: footnotes.findIndex((f) => f.el === fnEdit.el) + 1,
|
|
1715
|
+
note: fnEdit.el.getAttribute("data-note") ?? "",
|
|
1716
|
+
onChange: (v) => {
|
|
1717
|
+
fnEdit.el.setAttribute("data-note", v);
|
|
1718
|
+
emit();
|
|
1719
|
+
},
|
|
1720
|
+
onRemove: () => removeFootnote(fnEdit.el),
|
|
1721
|
+
onDone: closeFootnote
|
|
1722
|
+
}, footnotes.findIndex((f) => f.el === fnEdit.el)) : null
|
|
1723
|
+
})]
|
|
1724
|
+
}),
|
|
1635
1725
|
/* @__PURE__ */ jsxs(Popover, {
|
|
1636
1726
|
open: !!link,
|
|
1637
1727
|
onOpenChange: (o) => !o && setLink(null),
|
|
@@ -1663,10 +1753,10 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1663
1753
|
}
|
|
1664
1754
|
}) : link ? /* @__PURE__ */ jsx("div", {
|
|
1665
1755
|
className: "flex flex-col gap-2",
|
|
1666
|
-
children: /* @__PURE__ */ jsx(
|
|
1667
|
-
initial: link.initial,
|
|
1668
|
-
allowNewTab,
|
|
1669
|
-
onSave: saveLink,
|
|
1756
|
+
children: /* @__PURE__ */ jsx(LinkPopoverBody, {
|
|
1757
|
+
initial: toLinkValue(link.initial),
|
|
1758
|
+
hideNewTab: !allowNewTab,
|
|
1759
|
+
onSave: (v) => saveLink(fromLinkValue(v, allowNewTab)),
|
|
1670
1760
|
onCancel: () => setLink(null),
|
|
1671
1761
|
onDetach: link.existing ? () => {
|
|
1672
1762
|
const a = link.existing;
|
|
@@ -1691,6 +1781,7 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1691
1781
|
placeholder,
|
|
1692
1782
|
docKey: `${docKey}:expanded`,
|
|
1693
1783
|
features,
|
|
1784
|
+
references,
|
|
1694
1785
|
single,
|
|
1695
1786
|
allowNewTab,
|
|
1696
1787
|
expandCrumbs,
|