@bettercms-ai/kit 2.0.0-next.0 → 2.0.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/lossy.d.ts +9 -1
- package/dist/adapters/lossy.js +16 -5
- package/dist/adapters/lossy.js.map +1 -1
- package/dist/adapters/prod-types.d.ts +9 -22
- package/dist/adapters/prod-types.js +36 -35
- package/dist/adapters/prod-types.js.map +1 -1
- package/dist/adapters/schema.js +84 -39
- package/dist/adapters/schema.js.map +1 -1
- package/dist/context.d.ts +39 -0
- package/dist/context.js +40 -1
- package/dist/context.js.map +1 -1
- package/dist/controls/link.js +112 -196
- package/dist/controls/link.js.map +1 -1
- package/dist/controls/location.js +3 -8
- package/dist/controls/location.js.map +1 -1
- package/dist/controls/media.d.ts +0 -14
- package/dist/controls/media.js +52 -95
- package/dist/controls/media.js.map +1 -1
- package/dist/controls/rich-text/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +510 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +104 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +19 -2
- package/dist/controls/rich-text/blocks.js +273 -638
- package/dist/controls/rich-text/blocks.js.map +1 -1
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +85 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/dist/controls/rich-text/catalog.d.ts +2 -5
- package/dist/controls/rich-text/catalog.js +120 -6
- package/dist/controls/rich-text/catalog.js.map +1 -1
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/dist/controls/rich-text/codec.d.ts +10 -1
- package/dist/controls/rich-text/codec.js +11 -1
- package/dist/controls/rich-text/codec.js.map +1 -1
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- 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 +84 -4
- package/dist/controls/rich-text/dom.js +171 -10
- 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 +184 -12
- package/dist/controls/rich-text/editor.js.map +1 -1
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/dist/controls/rich-text/link-form.d.ts +3 -1
- package/dist/controls/rich-text/link-form.js +2 -2
- 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 +36 -0
- package/dist/controls/rich-text/related.js +213 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +47 -0
- package/dist/controls/rich-text/toc.js +160 -0
- package/dist/controls/rich-text/toc.js.map +1 -0
- package/dist/core/core.d.ts +11 -3
- package/dist/core/core.js +24 -6
- package/dist/core/core.js.map +1 -1
- package/dist/core/facets.d.ts +16 -0
- package/dist/core/facets.js +17 -1
- package/dist/core/facets.js.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/index.js +4 -4
- package/dist/library/kit-catalog.json +47 -44
- package/dist/schema/types.d.ts +15 -0
- package/dist/schema/types.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui/autocomplete.d.ts +29 -1
- package/dist/ui/autocomplete.js +102 -47
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/button.js +3 -5
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/toast.js +1 -1
- package/package.json +3 -1
|
@@ -9,14 +9,18 @@ import { COMPONENT_INSERT_TOAST } from "../component-services.js";
|
|
|
9
9
|
import { eventKey } from "../../lib/key-event.js";
|
|
10
10
|
import { closestBlock, createIsland, defaultModel, editingHost, esc, hydrate, isEmptyHtml, placeCaret, rangeRect, rid, sanitize, serialize, textBeforeCaret, topBlock } from "./dom.js";
|
|
11
11
|
import { LinkForm } from "./link-form.js";
|
|
12
|
+
import { createOutlineStore, outlineOf } from "./toc.js";
|
|
12
13
|
import { CatalogComponentsProvider, InsertMenuContent, SlashMenuPanel, blockAllowed, catalogKey, noteRecent, useCatalog } from "./catalog.js";
|
|
13
14
|
import { openComponentPanel } from "./component-panel.js";
|
|
14
15
|
import { Island } from "./blocks.js";
|
|
16
|
+
import { duplicateBlock, ensureLineAfter, insertBasic, insertIsland, liveInlineCode, liveMarkdown, moveBlock, restrictHtml, turnInto } from "./ops.js";
|
|
17
|
+
import { ButtonLinkPanel, applyButton, buttonAt, buttonInitial, insertButton, removeButton } from "./button.js";
|
|
18
|
+
import { checklistShortcut, insertChecklist, syncTaskA11y, toggleTaskAtPointer, toggleTaskFromKey } from "./checklist.js";
|
|
15
19
|
import { ALL_FEATURES } from "./codec.js";
|
|
16
20
|
import { htmlToMarkdown, looksLikeMarkdown, markdownToHtml } from "./markdown.js";
|
|
17
|
-
import { duplicateBlock, ensureLineAfter, insertBasic, insertIsland, liveInlineCode, liveMarkdown, moveBlock, restrictHtml, turnInto } from "./ops.js";
|
|
18
21
|
import { EMPTY_FMT, FormatToolbar, MARK_FEATURE, stylesFor } from "./toolbar.js";
|
|
19
22
|
import { SelectionBubble } from "./floating.js";
|
|
23
|
+
import { FN_MARK, FOOTNOTE_POPOVER_CLASS, FOOTNOTE_REFUSED, FootnoteEditor, FootnotesList, backToMarker, caretAfterMarker, insertFootnote, renumberFootnotes } from "./footnote.js";
|
|
20
24
|
import * as React from "react";
|
|
21
25
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
22
26
|
import { IconArrowBarToDown, IconArrowBarToUp, IconCopy, IconGripVertical, IconPlus, IconTransform, IconTrash } from "@tabler/icons-react";
|
|
@@ -112,11 +116,23 @@ function insertHtmlAtCaret(html) {
|
|
|
112
116
|
s.addRange(r);
|
|
113
117
|
}
|
|
114
118
|
}
|
|
115
|
-
var NOT_COUNTED =
|
|
119
|
+
var NOT_COUNTED = [
|
|
120
|
+
"[data-rt=component]",
|
|
121
|
+
"[data-rt=pullquote]",
|
|
122
|
+
"[data-rt=takeaways]",
|
|
123
|
+
"[data-rt=toc]",
|
|
124
|
+
"[data-rt=related]",
|
|
125
|
+
"[data-rt=author]",
|
|
126
|
+
"[data-rt=embed]",
|
|
127
|
+
"[data-rt=video]",
|
|
128
|
+
"[data-rt=file]",
|
|
129
|
+
"[data-rt=footnotes]",
|
|
130
|
+
"sup[data-rt=fn]"
|
|
131
|
+
].join(",");
|
|
116
132
|
var WORDS = (s) => s.replace(/\u200b/g, "").trim().split(/\s+/).filter(Boolean).length;
|
|
117
133
|
function countWords(html) {
|
|
118
134
|
if (!html) return 0;
|
|
119
|
-
if (!/data-rt="(?:component|pullquote|takeaways|embed|video|file)"/.test(html) || typeof DOMParser === "undefined") return WORDS(html.replace(
|
|
135
|
+
if (!/data-rt="(?:component|pullquote|takeaways|toc|related|author|embed|video|file|footnotes|fn)"/.test(html) || typeof DOMParser === "undefined") return WORDS(html.replace(/<[^>]+>/g, " ").replace(/ |&[a-z]+;/g, " "));
|
|
120
136
|
const doc = new DOMParser().parseFromString(`<body>${html}</body>`, "text/html");
|
|
121
137
|
doc.body.querySelectorAll(NOT_COUNTED).forEach((n) => n.remove());
|
|
122
138
|
doc.body.querySelectorAll("p,li,h1,h2,h3,h4,h5,h6,td,th,figcaption,summary,pre,blockquote,div").forEach((n) => n.append(" "));
|
|
@@ -128,7 +144,7 @@ var countComponents = (html) => (html.match(/data-rt="component"/g) ?? []).lengt
|
|
|
128
144
|
var bodyCountLabel = (html) => {
|
|
129
145
|
const w = countWords(html);
|
|
130
146
|
const c = countComponents(html);
|
|
131
|
-
return `${w.toLocaleString("en-US")} ${w === 1 ? "word" : "words"}${c ? ` · ${c} ${c === 1 ? "
|
|
147
|
+
return `${w.toLocaleString("en-US")} ${w === 1 ? "word" : "words"}${c ? ` · ${c} ${c === 1 ? "component" : "components"}` : ""}`;
|
|
132
148
|
};
|
|
133
149
|
function insertTextAtCaret(text) {
|
|
134
150
|
if (exec("insertText", text)) return;
|
|
@@ -161,7 +177,7 @@ function slashPlacement(caret, viewportH) {
|
|
|
161
177
|
maxHeight: Math.max(SLASH_MIN_H, Math.min(SLASH_MENU_H, flipUp ? above : below))
|
|
162
178
|
};
|
|
163
179
|
}
|
|
164
|
-
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 }) {
|
|
180
|
+
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 }) {
|
|
165
181
|
const hints = shortcutHintsOn();
|
|
166
182
|
const ph = placeholder ?? (hints ? "Type '/' for commands" : "Write something…");
|
|
167
183
|
const dense = variant === "panel";
|
|
@@ -249,6 +265,11 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
249
265
|
const t = window.setTimeout(() => setNotice(null), 8e3);
|
|
250
266
|
return () => window.clearTimeout(t);
|
|
251
267
|
}, [notice]);
|
|
268
|
+
/** V2 article-blocks.tsx:45-66: one live outline per editor, so every table of contents follows the headings */
|
|
269
|
+
const outline = React.useRef(createOutlineStore());
|
|
270
|
+
/** V2 rich-text-editor.tsx:271-276: the body's markers in text order, and the one whose note is open */
|
|
271
|
+
const [footnotes, setFootnotes] = React.useState([]);
|
|
272
|
+
const [fnEdit, setFnEdit] = React.useState(null);
|
|
252
273
|
const syncIslands = React.useCallback(() => {
|
|
253
274
|
const el = ref.current;
|
|
254
275
|
if (!el) return setIslands((p) => p.length ? [] : p);
|
|
@@ -272,7 +293,12 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
272
293
|
const el = ref.current;
|
|
273
294
|
if (!el) return;
|
|
274
295
|
el.innerHTML = sanitize(html || "") || "<p><br></p>";
|
|
296
|
+
el.querySelectorAll(":scope > ol[data-rt=\"footnotes\"]").forEach((n) => n.remove());
|
|
297
|
+
el.querySelectorAll(FN_MARK).forEach((m) => m.setAttribute("contenteditable", "false"));
|
|
275
298
|
hydrate(el);
|
|
299
|
+
syncTaskA11y(el);
|
|
300
|
+
setFootnotes(renumberFootnotes(el));
|
|
301
|
+
outline.current.set(outlineOf(el));
|
|
276
302
|
known.current = html;
|
|
277
303
|
setEmpty(isEmptyHtml(html));
|
|
278
304
|
setWords(countWords(html));
|
|
@@ -283,6 +309,9 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
283
309
|
const el = ref.current;
|
|
284
310
|
if (!el) return;
|
|
285
311
|
syncIslands();
|
|
312
|
+
syncTaskA11y(el);
|
|
313
|
+
outline.current.set(outlineOf(el));
|
|
314
|
+
setFootnotes(renumberFootnotes(el));
|
|
286
315
|
const html = serialize(el);
|
|
287
316
|
setEmpty(isEmptyHtml(html) && !el.querySelector(":scope > [data-rt-island], :scope > hr"));
|
|
288
317
|
setWords(countWords(html));
|
|
@@ -568,7 +597,21 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
568
597
|
}
|
|
569
598
|
if (!it.id || !blockAllowed(it.id, allows)) return;
|
|
570
599
|
noteRecent(it);
|
|
571
|
-
|
|
600
|
+
if (it.id === "footnote") {
|
|
601
|
+
const m = insertFootnote(el);
|
|
602
|
+
if (!m) return void notify(FOOTNOTE_REFUSED.title, { description: FOOTNOTE_REFUSED.description });
|
|
603
|
+
emit();
|
|
604
|
+
openFootnote(m, true);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (it.id === "task") insertChecklist(el);
|
|
608
|
+
else if (it.id === "button") {
|
|
609
|
+
const a = insertButton(el);
|
|
610
|
+
emit();
|
|
611
|
+
refresh();
|
|
612
|
+
openButton(a);
|
|
613
|
+
return;
|
|
614
|
+
} else insertBasic(el, it.id);
|
|
572
615
|
emit();
|
|
573
616
|
refresh();
|
|
574
617
|
};
|
|
@@ -645,6 +688,11 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
645
688
|
}
|
|
646
689
|
const mod = e.metaKey || e.ctrlKey;
|
|
647
690
|
const k = eventKey(e);
|
|
691
|
+
if (!mod && !e.altKey && !readOnly && ref.current && toggleTaskFromKey(ref.current, e.key)) {
|
|
692
|
+
e.preventDefault();
|
|
693
|
+
emit();
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
648
696
|
if (mod && !e.altKey && k === "k") {
|
|
649
697
|
e.preventDefault();
|
|
650
698
|
saveSel();
|
|
@@ -750,6 +798,11 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
750
798
|
hist.current.textAt = Date.now();
|
|
751
799
|
hist.current.future = [];
|
|
752
800
|
}
|
|
801
|
+
if (!single && ne.inputType === "insertText" && allows("checklist") && checklistShortcut(ref.current, ne.data)) {
|
|
802
|
+
setSlash(null);
|
|
803
|
+
emit();
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
753
806
|
if (!single && ne.inputType === "insertText" && (ne.data === " " || ne.data === "-") && liveMarkdown(ref.current, ne.data, allows)) {
|
|
754
807
|
setSlash(null);
|
|
755
808
|
emit();
|
|
@@ -789,6 +842,7 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
789
842
|
restoreSel();
|
|
790
843
|
const s = window.getSelection();
|
|
791
844
|
const anchor = (s?.anchorNode?.nodeType === 1 ? s.anchorNode : s?.anchorNode?.parentElement)?.closest("a") ?? null;
|
|
845
|
+
if (anchor && ref.current && buttonAt(ref.current, anchor)) return openButton(anchor);
|
|
792
846
|
if (!anchor && (!s || s.isCollapsed || !s.toString().trim())) {
|
|
793
847
|
notify("Select some text first", { description: hints ? "Then press ⌘K to link it." : "Then link it." });
|
|
794
848
|
return;
|
|
@@ -804,6 +858,50 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
804
858
|
} : { href: "" }
|
|
805
859
|
});
|
|
806
860
|
};
|
|
861
|
+
const openFootnote = (m, fresh = false) => {
|
|
862
|
+
if (readOnly) return;
|
|
863
|
+
setBubble(null);
|
|
864
|
+
setFnEdit({
|
|
865
|
+
el: m,
|
|
866
|
+
rect: m.getBoundingClientRect(),
|
|
867
|
+
fresh
|
|
868
|
+
});
|
|
869
|
+
};
|
|
870
|
+
const removeFootnote = (m) => {
|
|
871
|
+
setFnEdit(null);
|
|
872
|
+
m.remove();
|
|
873
|
+
emit();
|
|
874
|
+
};
|
|
875
|
+
/** closed: a new footnote with no note is taken back out (V2), else the caret goes back after its marker */
|
|
876
|
+
const closeFootnote = () => {
|
|
877
|
+
const f = fnEdit;
|
|
878
|
+
setFnEdit(null);
|
|
879
|
+
if (!f || !ref.current) return;
|
|
880
|
+
if (f.fresh && !(f.el.getAttribute("data-note") ?? "").trim()) return removeFootnote(f.el);
|
|
881
|
+
caretAfterMarker(ref.current, f.el);
|
|
882
|
+
};
|
|
883
|
+
/** V2 rich-text-editor.tsx:865-873: a button's popover, its label above the link form */
|
|
884
|
+
const openButton = (a) => {
|
|
885
|
+
if (readOnly) return;
|
|
886
|
+
const { link: initial, label } = buttonInitial(a);
|
|
887
|
+
setBubble(null);
|
|
888
|
+
setLink({
|
|
889
|
+
rect: a.getBoundingClientRect(),
|
|
890
|
+
existing: a,
|
|
891
|
+
initial,
|
|
892
|
+
button: {
|
|
893
|
+
a,
|
|
894
|
+
label
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
};
|
|
898
|
+
const saveButton = (v, label) => {
|
|
899
|
+
const b = link?.button;
|
|
900
|
+
setLink(null);
|
|
901
|
+
if (!b) return;
|
|
902
|
+
applyButton(b.a, v, label);
|
|
903
|
+
emit();
|
|
904
|
+
};
|
|
807
905
|
const saveLink = (v) => {
|
|
808
906
|
const l = link;
|
|
809
907
|
setLink(null);
|
|
@@ -1072,7 +1170,8 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1072
1170
|
moveBlock: moveBlock$1,
|
|
1073
1171
|
islandUndo,
|
|
1074
1172
|
islandRedo,
|
|
1075
|
-
startDrag
|
|
1173
|
+
startDrag,
|
|
1174
|
+
allows
|
|
1076
1175
|
});
|
|
1077
1176
|
api.current = {
|
|
1078
1177
|
emit,
|
|
@@ -1085,7 +1184,8 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1085
1184
|
moveBlock: moveBlock$1,
|
|
1086
1185
|
islandUndo,
|
|
1087
1186
|
islandRedo,
|
|
1088
|
-
startDrag
|
|
1187
|
+
startDrag,
|
|
1188
|
+
allows
|
|
1089
1189
|
};
|
|
1090
1190
|
const islandCtx = React.useMemo(() => ({
|
|
1091
1191
|
readOnly,
|
|
@@ -1100,8 +1200,15 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1100
1200
|
move: (x, dir) => api.current.moveBlock(x, dir),
|
|
1101
1201
|
undo: () => api.current.islandUndo(),
|
|
1102
1202
|
redo: () => api.current.islandRedo(),
|
|
1103
|
-
drag: (x, e) => api.current.startDrag(x, e)
|
|
1104
|
-
|
|
1203
|
+
drag: (x, e) => api.current.startDrag(x, e),
|
|
1204
|
+
allows: (f) => api.current.allows(f),
|
|
1205
|
+
outline: outline.current,
|
|
1206
|
+
references
|
|
1207
|
+
}), [
|
|
1208
|
+
readOnly,
|
|
1209
|
+
dense,
|
|
1210
|
+
references
|
|
1211
|
+
]);
|
|
1105
1212
|
const commentSel = onComment ? () => {
|
|
1106
1213
|
restoreSel();
|
|
1107
1214
|
const q = window.getSelection()?.toString().trim();
|
|
@@ -1305,6 +1412,22 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1305
1412
|
onKeyDown,
|
|
1306
1413
|
onKeyUp: refresh,
|
|
1307
1414
|
onMouseUp: refresh,
|
|
1415
|
+
onMouseDown: (e) => {
|
|
1416
|
+
if (readOnly || !ref.current || !toggleTaskAtPointer(ref.current, e.target, e.clientX)) return;
|
|
1417
|
+
e.preventDefault();
|
|
1418
|
+
emit();
|
|
1419
|
+
},
|
|
1420
|
+
onClick: (e) => {
|
|
1421
|
+
const fn = e.target.closest?.(FN_MARK);
|
|
1422
|
+
if (fn && ref.current?.contains(fn) && !fn.closest("[data-rt-island]") && !readOnly) {
|
|
1423
|
+
e.preventDefault();
|
|
1424
|
+
return openFootnote(fn);
|
|
1425
|
+
}
|
|
1426
|
+
const a = ref.current ? buttonAt(ref.current, e.target) : null;
|
|
1427
|
+
if (!a || readOnly) return;
|
|
1428
|
+
e.preventDefault();
|
|
1429
|
+
openButton(a);
|
|
1430
|
+
},
|
|
1308
1431
|
onPaste: (e) => {
|
|
1309
1432
|
if (readOnly) return;
|
|
1310
1433
|
if (Array.from(e.clipboardData.files).filter((f) => f.type.startsWith("image/")).length) {
|
|
@@ -1481,6 +1604,13 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1481
1604
|
}), el, key))
|
|
1482
1605
|
]
|
|
1483
1606
|
}),
|
|
1607
|
+
/* @__PURE__ */ jsx(FootnotesList, {
|
|
1608
|
+
notes: footnotes,
|
|
1609
|
+
readOnly,
|
|
1610
|
+
density: dense ? "dense" : "default",
|
|
1611
|
+
onEdit: (m) => openFootnote(m),
|
|
1612
|
+
onBack: (m) => ref.current && backToMarker(ref.current, m)
|
|
1613
|
+
}),
|
|
1484
1614
|
/* @__PURE__ */ jsxs("div", {
|
|
1485
1615
|
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",
|
|
1486
1616
|
children: [notice ? /* @__PURE__ */ jsxs("span", {
|
|
@@ -1506,7 +1636,7 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1506
1636
|
words.toLocaleString("en-US"),
|
|
1507
1637
|
" ",
|
|
1508
1638
|
words === 1 ? "word" : "words",
|
|
1509
|
-
comps ? ` · ${comps} ${comps === 1 ? "
|
|
1639
|
+
comps ? ` · ${comps} ${comps === 1 ? "component" : "components"}` : "",
|
|
1510
1640
|
" · ",
|
|
1511
1641
|
Math.max(1, Math.round(words / 220)),
|
|
1512
1642
|
" min read"
|
|
@@ -1562,6 +1692,35 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1562
1692
|
maxHeight: slashMaxH
|
|
1563
1693
|
})
|
|
1564
1694
|
})] }), document.body) : null,
|
|
1695
|
+
/* @__PURE__ */ jsxs(Popover, {
|
|
1696
|
+
open: !!fnEdit,
|
|
1697
|
+
onOpenChange: (o) => !o && closeFootnote(),
|
|
1698
|
+
children: [/* @__PURE__ */ jsx(PopoverAnchor, { render: /* @__PURE__ */ jsx("span", {
|
|
1699
|
+
className: "pointer-events-none fixed",
|
|
1700
|
+
style: fnEdit ? {
|
|
1701
|
+
top: fnEdit.rect.bottom,
|
|
1702
|
+
left: fnEdit.rect.left,
|
|
1703
|
+
width: Math.max(1, fnEdit.rect.width),
|
|
1704
|
+
height: 1
|
|
1705
|
+
} : {
|
|
1706
|
+
top: 0,
|
|
1707
|
+
left: 0
|
|
1708
|
+
}
|
|
1709
|
+
}) }), /* @__PURE__ */ jsx(PopoverContent, {
|
|
1710
|
+
className: FOOTNOTE_POPOVER_CLASS,
|
|
1711
|
+
finalFocus: false,
|
|
1712
|
+
children: fnEdit ? /* @__PURE__ */ jsx(FootnoteEditor, {
|
|
1713
|
+
n: footnotes.findIndex((f) => f.el === fnEdit.el) + 1,
|
|
1714
|
+
note: fnEdit.el.getAttribute("data-note") ?? "",
|
|
1715
|
+
onChange: (v) => {
|
|
1716
|
+
fnEdit.el.setAttribute("data-note", v);
|
|
1717
|
+
emit();
|
|
1718
|
+
},
|
|
1719
|
+
onRemove: () => removeFootnote(fnEdit.el),
|
|
1720
|
+
onDone: closeFootnote
|
|
1721
|
+
}, footnotes.findIndex((f) => f.el === fnEdit.el)) : null
|
|
1722
|
+
})]
|
|
1723
|
+
}),
|
|
1565
1724
|
/* @__PURE__ */ jsxs(Popover, {
|
|
1566
1725
|
open: !!link,
|
|
1567
1726
|
onOpenChange: (o) => !o && setLink(null),
|
|
@@ -1579,7 +1738,19 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1579
1738
|
}) }), /* @__PURE__ */ jsx(PopoverContent, {
|
|
1580
1739
|
className: "w-[340px] rounded-kit-lg p-3",
|
|
1581
1740
|
finalFocus: false,
|
|
1582
|
-
children: link ? /* @__PURE__ */ jsx(
|
|
1741
|
+
children: link?.button ? /* @__PURE__ */ jsx(ButtonLinkPanel, {
|
|
1742
|
+
initial: link.initial,
|
|
1743
|
+
label: link.button.label,
|
|
1744
|
+
allowNewTab,
|
|
1745
|
+
onSave: saveButton,
|
|
1746
|
+
onCancel: () => setLink(null),
|
|
1747
|
+
onDetach: () => {
|
|
1748
|
+
const a = link.button.a;
|
|
1749
|
+
setLink(null);
|
|
1750
|
+
if (ref.current) removeButton(ref.current, a);
|
|
1751
|
+
emit();
|
|
1752
|
+
}
|
|
1753
|
+
}) : link ? /* @__PURE__ */ jsx("div", {
|
|
1583
1754
|
className: "flex flex-col gap-2",
|
|
1584
1755
|
children: /* @__PURE__ */ jsx(LinkForm, {
|
|
1585
1756
|
initial: link.initial,
|
|
@@ -1609,6 +1780,7 @@ function RichTextEditor({ value, onChange, readOnly, placeholder, docKey, featur
|
|
|
1609
1780
|
placeholder,
|
|
1610
1781
|
docKey: `${docKey}:expanded`,
|
|
1611
1782
|
features,
|
|
1783
|
+
references,
|
|
1612
1784
|
single,
|
|
1613
1785
|
allowNewTab,
|
|
1614
1786
|
expandCrumbs,
|