@godxjp/block-editor 31.27.0 → 31.28.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/index.d.ts +73 -0
- package/dist/index.js +619 -104
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -59,6 +59,27 @@ declare const BLOCK_EDITOR_MESSAGES: {
|
|
|
59
59
|
readonly calloutImportant: "重要";
|
|
60
60
|
readonly calloutWarning: "警告";
|
|
61
61
|
readonly calloutCaution: "注意";
|
|
62
|
+
readonly calloutKind: "コールアウトの種類";
|
|
63
|
+
readonly calloutTitle: "コールアウトの見出し";
|
|
64
|
+
readonly addColumn: "列を追加";
|
|
65
|
+
readonly removeColumn: "この列を削除";
|
|
66
|
+
readonly columnWidth: "この列の幅";
|
|
67
|
+
readonly widthAuto: "自動";
|
|
68
|
+
readonly expandToggle: "開く";
|
|
69
|
+
readonly collapseToggle: "閉じる";
|
|
70
|
+
readonly editLink: "リンクを編集";
|
|
71
|
+
readonly linkText: "表示テキスト";
|
|
72
|
+
readonly linkTitle: "タイトル(ツールチップ)";
|
|
73
|
+
readonly openLink: "リンクを開く";
|
|
74
|
+
readonly save: "保存";
|
|
75
|
+
readonly editImage: "画像を編集";
|
|
76
|
+
readonly imageSrc: "画像のURL";
|
|
77
|
+
readonly imageAlt: "代替テキスト";
|
|
78
|
+
readonly imageAltHint: "画像が見えない人のための説明。装飾だけの画像なら空にします。";
|
|
79
|
+
readonly imageTitle: "タイトル(ツールチップ)";
|
|
80
|
+
readonly replaceImage: "画像を差し替え";
|
|
81
|
+
readonly removeImage: "画像を削除";
|
|
82
|
+
readonly properties: "プロパティ(YAML)";
|
|
62
83
|
};
|
|
63
84
|
readonly en: {
|
|
64
85
|
readonly editor: "Editor";
|
|
@@ -112,6 +133,27 @@ declare const BLOCK_EDITOR_MESSAGES: {
|
|
|
112
133
|
readonly calloutImportant: "Important";
|
|
113
134
|
readonly calloutWarning: "Warning";
|
|
114
135
|
readonly calloutCaution: "Caution";
|
|
136
|
+
readonly calloutKind: "Callout type";
|
|
137
|
+
readonly calloutTitle: "Callout title";
|
|
138
|
+
readonly addColumn: "Add a column";
|
|
139
|
+
readonly removeColumn: "Remove this column";
|
|
140
|
+
readonly columnWidth: "This column's width";
|
|
141
|
+
readonly widthAuto: "Auto";
|
|
142
|
+
readonly expandToggle: "Expand";
|
|
143
|
+
readonly collapseToggle: "Collapse";
|
|
144
|
+
readonly editLink: "Edit link";
|
|
145
|
+
readonly linkText: "Text";
|
|
146
|
+
readonly linkTitle: "Title (tooltip)";
|
|
147
|
+
readonly openLink: "Open link";
|
|
148
|
+
readonly save: "Save";
|
|
149
|
+
readonly editImage: "Edit image";
|
|
150
|
+
readonly imageSrc: "Image URL";
|
|
151
|
+
readonly imageAlt: "Alternative text";
|
|
152
|
+
readonly imageAltHint: "Describes the image for people who cannot see it. Leave empty for a purely decorative image.";
|
|
153
|
+
readonly imageTitle: "Title (tooltip)";
|
|
154
|
+
readonly replaceImage: "Replace image";
|
|
155
|
+
readonly removeImage: "Remove image";
|
|
156
|
+
readonly properties: "Properties (YAML)";
|
|
115
157
|
};
|
|
116
158
|
readonly vi: {
|
|
117
159
|
readonly editor: "Trình soạn thảo";
|
|
@@ -165,6 +207,27 @@ declare const BLOCK_EDITOR_MESSAGES: {
|
|
|
165
207
|
readonly calloutImportant: "Quan trọng";
|
|
166
208
|
readonly calloutWarning: "Cảnh báo";
|
|
167
209
|
readonly calloutCaution: "Thận trọng";
|
|
210
|
+
readonly calloutKind: "Loại chú thích";
|
|
211
|
+
readonly calloutTitle: "Tiêu đề chú thích";
|
|
212
|
+
readonly addColumn: "Thêm cột";
|
|
213
|
+
readonly removeColumn: "Xoá cột này";
|
|
214
|
+
readonly columnWidth: "Độ rộng cột này";
|
|
215
|
+
readonly widthAuto: "Tự động";
|
|
216
|
+
readonly expandToggle: "Mở";
|
|
217
|
+
readonly collapseToggle: "Thu gọn";
|
|
218
|
+
readonly editLink: "Sửa liên kết";
|
|
219
|
+
readonly linkText: "Văn bản hiển thị";
|
|
220
|
+
readonly linkTitle: "Tiêu đề (chú giải)";
|
|
221
|
+
readonly openLink: "Mở liên kết";
|
|
222
|
+
readonly save: "Lưu";
|
|
223
|
+
readonly editImage: "Sửa ảnh";
|
|
224
|
+
readonly imageSrc: "URL ảnh";
|
|
225
|
+
readonly imageAlt: "Văn bản thay thế";
|
|
226
|
+
readonly imageAltHint: "Mô tả ảnh cho người không nhìn thấy. Để trống nếu ảnh chỉ để trang trí.";
|
|
227
|
+
readonly imageTitle: "Tiêu đề (chú giải)";
|
|
228
|
+
readonly replaceImage: "Thay ảnh";
|
|
229
|
+
readonly removeImage: "Xoá ảnh";
|
|
230
|
+
readonly properties: "Thuộc tính (YAML)";
|
|
168
231
|
};
|
|
169
232
|
};
|
|
170
233
|
type BlockEditorLabels = {
|
|
@@ -224,6 +287,11 @@ type BlockEditorProps = {
|
|
|
224
287
|
actions?: readonly BlockEditorAction[];
|
|
225
288
|
/** Override any string the editor renders (defaults: the kit's ja / en / vi catalogue). */
|
|
226
289
|
labels?: Partial<BlockEditorLabels>;
|
|
290
|
+
/**
|
|
291
|
+
* `framed` (default): a field's border and padding, so the editor reads as an editor inside a
|
|
292
|
+
* form. `plain`: no frame — the borderless Notion-style canvas for a full-page editor.
|
|
293
|
+
*/
|
|
294
|
+
appearance?: "framed" | "plain";
|
|
227
295
|
disabled?: boolean;
|
|
228
296
|
readOnly?: boolean;
|
|
229
297
|
autoFocus?: boolean;
|
|
@@ -273,6 +341,11 @@ declare function schemaExtensions(options: {
|
|
|
273
341
|
rawBlock?: Node;
|
|
274
342
|
/** Resolves a stored image URL (`asset:<id>`) to one the browser can load; the doc keeps the original. */
|
|
275
343
|
resolveUrl?: (url: string) => string | undefined;
|
|
344
|
+
callout?: Node;
|
|
345
|
+
columns?: Node;
|
|
346
|
+
frontmatter?: Node;
|
|
347
|
+
/** The toggle button's accessible name, open and closed. */
|
|
348
|
+
toggleLabel?: (open: boolean) => string;
|
|
276
349
|
}): Extensions;
|
|
277
350
|
|
|
278
351
|
export { BLOCK_EDITOR_MESSAGES, BlockEditor, type BlockEditorAction, type BlockEditorApi, type BlockEditorHandle, type BlockEditorLabels, type BlockEditorProps, type BlockEditorUploadResult, type CalloutTitles, type WikilinkSuggestion, schemaExtensions };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/block-editor.tsx
|
|
4
4
|
import * as React6 from "react";
|
|
5
|
+
import { getMarkRange } from "@tiptap/core";
|
|
5
6
|
import { EditorContent, useEditor } from "@tiptap/react";
|
|
6
7
|
import { FileText } from "lucide-react";
|
|
7
8
|
import { normalize, parse as parse2, serialize } from "@godxjp/markdown/codec";
|
|
@@ -20,8 +21,22 @@ function blockStartAt(editor, pos) {
|
|
|
20
21
|
}
|
|
21
22
|
return $pos.before(1);
|
|
22
23
|
}
|
|
24
|
+
function liveSelection(editor) {
|
|
25
|
+
let { from, to } = editor.state.selection;
|
|
26
|
+
const dom = editor.view.dom.ownerDocument.getSelection();
|
|
27
|
+
if (dom?.anchorNode && dom.focusNode && editor.view.dom.contains(dom.anchorNode)) {
|
|
28
|
+
try {
|
|
29
|
+
const anchor = editor.view.posAtDOM(dom.anchorNode, dom.anchorOffset);
|
|
30
|
+
const head = editor.view.posAtDOM(dom.focusNode, dom.focusOffset);
|
|
31
|
+
from = Math.min(anchor, head);
|
|
32
|
+
to = Math.max(anchor, head);
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { from, to };
|
|
37
|
+
}
|
|
23
38
|
function selectionBlockStart(editor) {
|
|
24
|
-
return blockStartAt(editor, editor.
|
|
39
|
+
return blockStartAt(editor, liveSelection(editor).from);
|
|
25
40
|
}
|
|
26
41
|
function nodeAt(editor, start) {
|
|
27
42
|
const node = editor.state.doc.nodeAt(start);
|
|
@@ -88,7 +103,7 @@ function startBlockDrag(editor, start, event) {
|
|
|
88
103
|
var BlockKeys = Extension.create({
|
|
89
104
|
name: "blockKeys",
|
|
90
105
|
addOptions() {
|
|
91
|
-
return { openMenu: () => void 0 };
|
|
106
|
+
return { openMenu: () => void 0, editLink: () => void 0 };
|
|
92
107
|
},
|
|
93
108
|
addKeyboardShortcuts() {
|
|
94
109
|
const move = (direction) => () => {
|
|
@@ -98,6 +113,11 @@ var BlockKeys = Extension.create({
|
|
|
98
113
|
return {
|
|
99
114
|
"Alt-Shift-ArrowUp": move(-1),
|
|
100
115
|
"Alt-Shift-ArrowDown": move(1),
|
|
116
|
+
// The link drawer for the link under the caret, or a new link on the selection.
|
|
117
|
+
"Mod-k": () => {
|
|
118
|
+
this.options.editLink();
|
|
119
|
+
return true;
|
|
120
|
+
},
|
|
101
121
|
"Mod-/": () => {
|
|
102
122
|
const start = selectionBlockStart(this.editor);
|
|
103
123
|
if (start == null) return false;
|
|
@@ -575,6 +595,27 @@ var Embed = Node.create({
|
|
|
575
595
|
];
|
|
576
596
|
}
|
|
577
597
|
});
|
|
598
|
+
var Frontmatter = Node.create({
|
|
599
|
+
name: "frontmatter",
|
|
600
|
+
group: "block",
|
|
601
|
+
atom: true,
|
|
602
|
+
addAttributes() {
|
|
603
|
+
return { source: { default: "" } };
|
|
604
|
+
},
|
|
605
|
+
parseHTML() {
|
|
606
|
+
return [{ tag: "pre[data-frontmatter]" }];
|
|
607
|
+
},
|
|
608
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
609
|
+
return [
|
|
610
|
+
"pre",
|
|
611
|
+
mergeAttributes(HTMLAttributes, {
|
|
612
|
+
"data-frontmatter": "",
|
|
613
|
+
class: "ui-block-editor-raw-block"
|
|
614
|
+
}),
|
|
615
|
+
node.attrs.source
|
|
616
|
+
];
|
|
617
|
+
}
|
|
618
|
+
});
|
|
578
619
|
var RawBlock = Node.create({
|
|
579
620
|
name: "rawBlock",
|
|
580
621
|
group: "block",
|
|
@@ -623,17 +664,28 @@ function schemaExtensions(options) {
|
|
|
623
664
|
];
|
|
624
665
|
}
|
|
625
666
|
}).configure({ inline: true, allowBase64: false }),
|
|
626
|
-
Details.configure({
|
|
667
|
+
Details.configure({
|
|
668
|
+
persist: false,
|
|
669
|
+
renderToggleButton: ({ element, isOpen }) => {
|
|
670
|
+
element.className = "ui-block-editor-toggle-button";
|
|
671
|
+
element.setAttribute("aria-expanded", String(isOpen));
|
|
672
|
+
element.setAttribute(
|
|
673
|
+
"aria-label",
|
|
674
|
+
options.toggleLabel?.(isOpen) ?? (isOpen ? "Collapse" : "Expand")
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
}),
|
|
627
678
|
DetailsSummary,
|
|
628
679
|
DetailsContent,
|
|
629
|
-
Callout.configure({ titles: options.calloutTitles }),
|
|
630
|
-
Columns,
|
|
680
|
+
(options.callout ?? Callout).configure({ titles: options.calloutTitles }),
|
|
681
|
+
options.columns ?? Columns,
|
|
631
682
|
Column,
|
|
632
683
|
Wikilink,
|
|
633
684
|
EmbedInline,
|
|
634
685
|
RawInline,
|
|
635
686
|
options.embed ?? Embed,
|
|
636
687
|
options.rawBlock ?? RawBlock,
|
|
688
|
+
options.frontmatter ?? Frontmatter,
|
|
637
689
|
Placeholder.configure({
|
|
638
690
|
includeChildren: true,
|
|
639
691
|
placeholder: ({ node }) => {
|
|
@@ -860,7 +912,28 @@ var BLOCK_EDITOR_MESSAGES = {
|
|
|
860
912
|
calloutTip: "\u30D2\u30F3\u30C8",
|
|
861
913
|
calloutImportant: "\u91CD\u8981",
|
|
862
914
|
calloutWarning: "\u8B66\u544A",
|
|
863
|
-
calloutCaution: "\u6CE8\u610F"
|
|
915
|
+
calloutCaution: "\u6CE8\u610F",
|
|
916
|
+
calloutKind: "\u30B3\u30FC\u30EB\u30A2\u30A6\u30C8\u306E\u7A2E\u985E",
|
|
917
|
+
calloutTitle: "\u30B3\u30FC\u30EB\u30A2\u30A6\u30C8\u306E\u898B\u51FA\u3057",
|
|
918
|
+
addColumn: "\u5217\u3092\u8FFD\u52A0",
|
|
919
|
+
removeColumn: "\u3053\u306E\u5217\u3092\u524A\u9664",
|
|
920
|
+
columnWidth: "\u3053\u306E\u5217\u306E\u5E45",
|
|
921
|
+
widthAuto: "\u81EA\u52D5",
|
|
922
|
+
expandToggle: "\u958B\u304F",
|
|
923
|
+
collapseToggle: "\u9589\u3058\u308B",
|
|
924
|
+
editLink: "\u30EA\u30F3\u30AF\u3092\u7DE8\u96C6",
|
|
925
|
+
linkText: "\u8868\u793A\u30C6\u30AD\u30B9\u30C8",
|
|
926
|
+
linkTitle: "\u30BF\u30A4\u30C8\u30EB\uFF08\u30C4\u30FC\u30EB\u30C1\u30C3\u30D7\uFF09",
|
|
927
|
+
openLink: "\u30EA\u30F3\u30AF\u3092\u958B\u304F",
|
|
928
|
+
save: "\u4FDD\u5B58",
|
|
929
|
+
editImage: "\u753B\u50CF\u3092\u7DE8\u96C6",
|
|
930
|
+
imageSrc: "\u753B\u50CF\u306EURL",
|
|
931
|
+
imageAlt: "\u4EE3\u66FF\u30C6\u30AD\u30B9\u30C8",
|
|
932
|
+
imageAltHint: "\u753B\u50CF\u304C\u898B\u3048\u306A\u3044\u4EBA\u306E\u305F\u3081\u306E\u8AAC\u660E\u3002\u88C5\u98FE\u3060\u3051\u306E\u753B\u50CF\u306A\u3089\u7A7A\u306B\u3057\u307E\u3059\u3002",
|
|
933
|
+
imageTitle: "\u30BF\u30A4\u30C8\u30EB\uFF08\u30C4\u30FC\u30EB\u30C1\u30C3\u30D7\uFF09",
|
|
934
|
+
replaceImage: "\u753B\u50CF\u3092\u5DEE\u3057\u66FF\u3048",
|
|
935
|
+
removeImage: "\u753B\u50CF\u3092\u524A\u9664",
|
|
936
|
+
properties: "\u30D7\u30ED\u30D1\u30C6\u30A3\uFF08YAML\uFF09"
|
|
864
937
|
},
|
|
865
938
|
en: {
|
|
866
939
|
editor: "Editor",
|
|
@@ -913,7 +986,28 @@ var BLOCK_EDITOR_MESSAGES = {
|
|
|
913
986
|
calloutTip: "Tip",
|
|
914
987
|
calloutImportant: "Important",
|
|
915
988
|
calloutWarning: "Warning",
|
|
916
|
-
calloutCaution: "Caution"
|
|
989
|
+
calloutCaution: "Caution",
|
|
990
|
+
calloutKind: "Callout type",
|
|
991
|
+
calloutTitle: "Callout title",
|
|
992
|
+
addColumn: "Add a column",
|
|
993
|
+
removeColumn: "Remove this column",
|
|
994
|
+
columnWidth: "This column's width",
|
|
995
|
+
widthAuto: "Auto",
|
|
996
|
+
expandToggle: "Expand",
|
|
997
|
+
collapseToggle: "Collapse",
|
|
998
|
+
editLink: "Edit link",
|
|
999
|
+
linkText: "Text",
|
|
1000
|
+
linkTitle: "Title (tooltip)",
|
|
1001
|
+
openLink: "Open link",
|
|
1002
|
+
save: "Save",
|
|
1003
|
+
editImage: "Edit image",
|
|
1004
|
+
imageSrc: "Image URL",
|
|
1005
|
+
imageAlt: "Alternative text",
|
|
1006
|
+
imageAltHint: "Describes the image for people who cannot see it. Leave empty for a purely decorative image.",
|
|
1007
|
+
imageTitle: "Title (tooltip)",
|
|
1008
|
+
replaceImage: "Replace image",
|
|
1009
|
+
removeImage: "Remove image",
|
|
1010
|
+
properties: "Properties (YAML)"
|
|
917
1011
|
},
|
|
918
1012
|
vi: {
|
|
919
1013
|
editor: "Tr\xECnh so\u1EA1n th\u1EA3o",
|
|
@@ -966,7 +1060,28 @@ var BLOCK_EDITOR_MESSAGES = {
|
|
|
966
1060
|
calloutTip: "M\u1EB9o",
|
|
967
1061
|
calloutImportant: "Quan tr\u1ECDng",
|
|
968
1062
|
calloutWarning: "C\u1EA3nh b\xE1o",
|
|
969
|
-
calloutCaution: "Th\u1EADn tr\u1ECDng"
|
|
1063
|
+
calloutCaution: "Th\u1EADn tr\u1ECDng",
|
|
1064
|
+
calloutKind: "Lo\u1EA1i ch\xFA th\xEDch",
|
|
1065
|
+
calloutTitle: "Ti\xEAu \u0111\u1EC1 ch\xFA th\xEDch",
|
|
1066
|
+
addColumn: "Th\xEAm c\u1ED9t",
|
|
1067
|
+
removeColumn: "Xo\xE1 c\u1ED9t n\xE0y",
|
|
1068
|
+
columnWidth: "\u0110\u1ED9 r\u1ED9ng c\u1ED9t n\xE0y",
|
|
1069
|
+
widthAuto: "T\u1EF1 \u0111\u1ED9ng",
|
|
1070
|
+
expandToggle: "M\u1EDF",
|
|
1071
|
+
collapseToggle: "Thu g\u1ECDn",
|
|
1072
|
+
editLink: "S\u1EEDa li\xEAn k\u1EBFt",
|
|
1073
|
+
linkText: "V\u0103n b\u1EA3n hi\u1EC3n th\u1ECB",
|
|
1074
|
+
linkTitle: "Ti\xEAu \u0111\u1EC1 (ch\xFA gi\u1EA3i)",
|
|
1075
|
+
openLink: "M\u1EDF li\xEAn k\u1EBFt",
|
|
1076
|
+
save: "L\u01B0u",
|
|
1077
|
+
editImage: "S\u1EEDa \u1EA3nh",
|
|
1078
|
+
imageSrc: "URL \u1EA3nh",
|
|
1079
|
+
imageAlt: "V\u0103n b\u1EA3n thay th\u1EBF",
|
|
1080
|
+
imageAltHint: "M\xF4 t\u1EA3 \u1EA3nh cho ng\u01B0\u1EDDi kh\xF4ng nh\xECn th\u1EA5y. \u0110\u1EC3 tr\u1ED1ng n\u1EBFu \u1EA3nh ch\u1EC9 \u0111\u1EC3 trang tr\xED.",
|
|
1081
|
+
imageTitle: "Ti\xEAu \u0111\u1EC1 (ch\xFA gi\u1EA3i)",
|
|
1082
|
+
replaceImage: "Thay \u1EA3nh",
|
|
1083
|
+
removeImage: "Xo\xE1 \u1EA3nh",
|
|
1084
|
+
properties: "Thu\u1ED9c t\xEDnh (YAML)"
|
|
970
1085
|
}
|
|
971
1086
|
};
|
|
972
1087
|
var registered = false;
|
|
@@ -1091,18 +1206,15 @@ function SuggestionMenu({
|
|
|
1091
1206
|
}
|
|
1092
1207
|
|
|
1093
1208
|
// src/toolbar.tsx
|
|
1094
|
-
import * as React4 from "react";
|
|
1095
1209
|
import { useEditorState } from "@tiptap/react";
|
|
1096
1210
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
1097
1211
|
import { Bold, Code as Code2, Italic, Link2, Strikethrough } from "lucide-react";
|
|
1098
|
-
import {
|
|
1212
|
+
import { ToggleGroup, ToggleGroupItem } from "@godxjp/ui/data-entry";
|
|
1099
1213
|
import { Button as Button2 } from "@godxjp/ui/general";
|
|
1100
1214
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1101
1215
|
var MARKS = ["bold", "italic", "strike", "code"];
|
|
1102
|
-
function FormatToolbar({ editor }) {
|
|
1216
|
+
function FormatToolbar({ editor, onEditLink }) {
|
|
1103
1217
|
const label = useLabel();
|
|
1104
|
-
const [linking, setLinking] = React4.useState(false);
|
|
1105
|
-
const [href, setHref] = React4.useState("");
|
|
1106
1218
|
const state = useEditorState({
|
|
1107
1219
|
editor,
|
|
1108
1220
|
selector: ({ editor: e }) => ({
|
|
@@ -1122,13 +1234,6 @@ function FormatToolbar({ editor }) {
|
|
|
1122
1234
|
}
|
|
1123
1235
|
chain.run();
|
|
1124
1236
|
};
|
|
1125
|
-
const applyLink = () => {
|
|
1126
|
-
const url = href.trim();
|
|
1127
|
-
const chain = editor.chain().focus().extendMarkRange("link");
|
|
1128
|
-
if (url) chain.setLink({ href: url }).run();
|
|
1129
|
-
else chain.unsetLink().run();
|
|
1130
|
-
setLinking(false);
|
|
1131
|
-
};
|
|
1132
1237
|
return /* @__PURE__ */ jsx4(
|
|
1133
1238
|
BubbleMenu,
|
|
1134
1239
|
{
|
|
@@ -1136,49 +1241,7 @@ function FormatToolbar({ editor }) {
|
|
|
1136
1241
|
className: "ui-block-editor-toolbar",
|
|
1137
1242
|
shouldShow: ({ editor: e, state: s }) => e.isEditable && !s.selection.empty && !e.isActive("codeBlock") && s.selection.content().size > 0,
|
|
1138
1243
|
options: { placement: "top" },
|
|
1139
|
-
children:
|
|
1140
|
-
"form",
|
|
1141
|
-
{
|
|
1142
|
-
className: "ui-block-editor-toolbar-link",
|
|
1143
|
-
onSubmit: (event) => {
|
|
1144
|
-
event.preventDefault();
|
|
1145
|
-
applyLink();
|
|
1146
|
-
},
|
|
1147
|
-
children: [
|
|
1148
|
-
/* @__PURE__ */ jsx4(
|
|
1149
|
-
Input,
|
|
1150
|
-
{
|
|
1151
|
-
size: "sm",
|
|
1152
|
-
type: "url",
|
|
1153
|
-
inputMode: "url",
|
|
1154
|
-
"aria-label": label("linkUrl"),
|
|
1155
|
-
value: href,
|
|
1156
|
-
onValueChange: setHref,
|
|
1157
|
-
onKeyDown: (event) => {
|
|
1158
|
-
if (event.key === "Escape") {
|
|
1159
|
-
setLinking(false);
|
|
1160
|
-
editor.commands.focus();
|
|
1161
|
-
}
|
|
1162
|
-
},
|
|
1163
|
-
autoFocus: true
|
|
1164
|
-
}
|
|
1165
|
-
),
|
|
1166
|
-
/* @__PURE__ */ jsx4(Button2, { size: "sm", type: "submit", children: label("applyLink") }),
|
|
1167
|
-
state.link ? /* @__PURE__ */ jsx4(
|
|
1168
|
-
Button2,
|
|
1169
|
-
{
|
|
1170
|
-
size: "sm",
|
|
1171
|
-
variant: "ghost",
|
|
1172
|
-
onClick: () => {
|
|
1173
|
-
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
1174
|
-
setLinking(false);
|
|
1175
|
-
},
|
|
1176
|
-
children: label("removeLink")
|
|
1177
|
-
}
|
|
1178
|
-
) : null
|
|
1179
|
-
]
|
|
1180
|
-
}
|
|
1181
|
-
) : /* @__PURE__ */ jsxs3("div", { className: "ui-block-editor-toolbar-row", children: [
|
|
1244
|
+
children: /* @__PURE__ */ jsxs3("div", { className: "ui-block-editor-toolbar-row", children: [
|
|
1182
1245
|
/* @__PURE__ */ jsxs3(
|
|
1183
1246
|
ToggleGroup,
|
|
1184
1247
|
{
|
|
@@ -1202,10 +1265,7 @@ function FormatToolbar({ editor }) {
|
|
|
1202
1265
|
variant: state.link ? "secondary" : "ghost",
|
|
1203
1266
|
"aria-label": label("link"),
|
|
1204
1267
|
"aria-pressed": state.link != null,
|
|
1205
|
-
onClick:
|
|
1206
|
-
setHref(state.link ?? "");
|
|
1207
|
-
setLinking(true);
|
|
1208
|
-
},
|
|
1268
|
+
onClick: onEditLink,
|
|
1209
1269
|
children: /* @__PURE__ */ jsx4(Link2, {})
|
|
1210
1270
|
}
|
|
1211
1271
|
)
|
|
@@ -1214,15 +1274,163 @@ function FormatToolbar({ editor }) {
|
|
|
1214
1274
|
);
|
|
1215
1275
|
}
|
|
1216
1276
|
|
|
1277
|
+
// src/edit-drawer.tsx
|
|
1278
|
+
import * as React4 from "react";
|
|
1279
|
+
import { ExternalLink, ImageUp, Trash2 as Trash22 } from "lucide-react";
|
|
1280
|
+
import { Image as Image2 } from "@godxjp/ui/data-display";
|
|
1281
|
+
import { FormField, Input } from "@godxjp/ui/data-entry";
|
|
1282
|
+
import { Sheet, SheetBody, SheetContent, SheetFooter, SheetHeader } from "@godxjp/ui/feedback";
|
|
1283
|
+
import { Button as Button3 } from "@godxjp/ui/general";
|
|
1284
|
+
import { Flex } from "@godxjp/ui/layout";
|
|
1285
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1286
|
+
function EditDrawer({
|
|
1287
|
+
editor,
|
|
1288
|
+
target,
|
|
1289
|
+
onClose,
|
|
1290
|
+
resolveUrl,
|
|
1291
|
+
replaceImage
|
|
1292
|
+
}) {
|
|
1293
|
+
const label = useLabel();
|
|
1294
|
+
const [draft, setDraft] = React4.useState(target);
|
|
1295
|
+
React4.useEffect(() => setDraft(target), [target]);
|
|
1296
|
+
if (!draft) return /* @__PURE__ */ jsx5(Sheet, { open: false, onOpenChange: () => void 0 });
|
|
1297
|
+
const set = (patch) => setDraft((d) => d ? { ...d, ...patch } : d);
|
|
1298
|
+
const save = () => {
|
|
1299
|
+
if (draft.kind === "link") {
|
|
1300
|
+
const href = draft.href.trim();
|
|
1301
|
+
const text = draft.text === "" ? href : draft.text;
|
|
1302
|
+
const chain = editor.chain().focus();
|
|
1303
|
+
if (!href) chain.setTextSelection({ from: draft.from, to: draft.to }).unsetLink();
|
|
1304
|
+
else
|
|
1305
|
+
chain.insertContentAt(
|
|
1306
|
+
{ from: draft.from, to: draft.to },
|
|
1307
|
+
{
|
|
1308
|
+
type: "text",
|
|
1309
|
+
text,
|
|
1310
|
+
marks: [{ type: "link", attrs: { href, title: draft.title.trim() || null } }]
|
|
1311
|
+
}
|
|
1312
|
+
);
|
|
1313
|
+
chain.run();
|
|
1314
|
+
} else {
|
|
1315
|
+
const { tr } = editor.state;
|
|
1316
|
+
tr.setNodeMarkup(draft.pos, void 0, {
|
|
1317
|
+
...editor.state.doc.nodeAt(draft.pos)?.attrs,
|
|
1318
|
+
src: draft.src.trim(),
|
|
1319
|
+
alt: draft.alt,
|
|
1320
|
+
title: draft.title.trim() || null
|
|
1321
|
+
});
|
|
1322
|
+
editor.view.dispatch(tr);
|
|
1323
|
+
}
|
|
1324
|
+
onClose();
|
|
1325
|
+
};
|
|
1326
|
+
const remove = () => {
|
|
1327
|
+
if (draft.kind === "link") {
|
|
1328
|
+
editor.chain().focus().setTextSelection({ from: draft.from, to: draft.to }).unsetLink().run();
|
|
1329
|
+
} else {
|
|
1330
|
+
const node = editor.state.doc.nodeAt(draft.pos);
|
|
1331
|
+
if (node)
|
|
1332
|
+
editor.chain().focus().deleteRange({ from: draft.pos, to: draft.pos + node.nodeSize }).run();
|
|
1333
|
+
}
|
|
1334
|
+
onClose();
|
|
1335
|
+
};
|
|
1336
|
+
const preview = draft.kind === "image" ? resolveUrl?.(draft.src) ?? draft.src : "";
|
|
1337
|
+
return /* @__PURE__ */ jsx5(Sheet, { open: true, onOpenChange: (open) => open ? void 0 : onClose(), children: /* @__PURE__ */ jsxs4(SheetContent, { side: "right", responsive: "auto", className: "ui-block-editor-drawer", children: [
|
|
1338
|
+
/* @__PURE__ */ jsx5(SheetHeader, { title: label(draft.kind === "link" ? "editLink" : "editImage") }),
|
|
1339
|
+
/* @__PURE__ */ jsx5(SheetBody, { children: /* @__PURE__ */ jsx5(
|
|
1340
|
+
"form",
|
|
1341
|
+
{
|
|
1342
|
+
id: "block-editor-edit",
|
|
1343
|
+
onSubmit: (event) => {
|
|
1344
|
+
event.preventDefault();
|
|
1345
|
+
save();
|
|
1346
|
+
},
|
|
1347
|
+
children: /* @__PURE__ */ jsx5(Flex, { direction: "col", gap: "md", children: draft.kind === "link" ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1348
|
+
/* @__PURE__ */ jsx5(FormField, { id: "block-editor-link-text", label: label("linkText"), children: /* @__PURE__ */ jsx5(Input, { value: draft.text, onValueChange: (text) => set({ text }) }) }),
|
|
1349
|
+
/* @__PURE__ */ jsx5(FormField, { id: "block-editor-link-href", label: label("linkUrl"), required: true, children: /* @__PURE__ */ jsx5(
|
|
1350
|
+
Input,
|
|
1351
|
+
{
|
|
1352
|
+
type: "url",
|
|
1353
|
+
inputMode: "url",
|
|
1354
|
+
value: draft.href,
|
|
1355
|
+
onValueChange: (href) => set({ href }),
|
|
1356
|
+
autoFocus: true
|
|
1357
|
+
}
|
|
1358
|
+
) }),
|
|
1359
|
+
/* @__PURE__ */ jsx5(FormField, { id: "block-editor-link-title", label: label("linkTitle"), children: /* @__PURE__ */ jsx5(Input, { value: draft.title, onValueChange: (title) => set({ title }) }) })
|
|
1360
|
+
] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1361
|
+
preview ? /* @__PURE__ */ jsx5(
|
|
1362
|
+
Image2,
|
|
1363
|
+
{
|
|
1364
|
+
src: preview,
|
|
1365
|
+
alt: draft.alt,
|
|
1366
|
+
className: "ui-block-editor-drawer-preview"
|
|
1367
|
+
}
|
|
1368
|
+
) : null,
|
|
1369
|
+
/* @__PURE__ */ jsx5(FormField, { id: "block-editor-image-src", label: label("imageSrc"), required: true, children: /* @__PURE__ */ jsx5(Input, { value: draft.src, onValueChange: (src) => set({ src }) }) }),
|
|
1370
|
+
/* @__PURE__ */ jsx5(
|
|
1371
|
+
FormField,
|
|
1372
|
+
{
|
|
1373
|
+
id: "block-editor-image-alt",
|
|
1374
|
+
label: label("imageAlt"),
|
|
1375
|
+
helper: label("imageAltHint"),
|
|
1376
|
+
children: /* @__PURE__ */ jsx5(Input, { value: draft.alt, onValueChange: (alt) => set({ alt }), autoFocus: true })
|
|
1377
|
+
}
|
|
1378
|
+
),
|
|
1379
|
+
/* @__PURE__ */ jsx5(FormField, { id: "block-editor-image-title", label: label("imageTitle"), children: /* @__PURE__ */ jsx5(Input, { value: draft.title, onValueChange: (title) => set({ title }) }) })
|
|
1380
|
+
] }) })
|
|
1381
|
+
}
|
|
1382
|
+
) }),
|
|
1383
|
+
/* @__PURE__ */ jsx5(SheetFooter, { children: /* @__PURE__ */ jsxs4(Flex, { gap: "sm", wrap: true, justify: "between", className: "ui-block-editor-drawer-actions", children: [
|
|
1384
|
+
/* @__PURE__ */ jsxs4(Flex, { gap: "sm", wrap: true, children: [
|
|
1385
|
+
draft.kind === "link" && draft.href.trim() ? /* @__PURE__ */ jsx5(Button3, { variant: "ghost", size: "sm", asChild: true, children: /* @__PURE__ */ jsxs4("a", { href: draft.href.trim(), target: "_blank", rel: "noopener noreferrer", children: [
|
|
1386
|
+
/* @__PURE__ */ jsx5(ExternalLink, { "aria-hidden": "true" }),
|
|
1387
|
+
label("openLink")
|
|
1388
|
+
] }) }) : null,
|
|
1389
|
+
draft.kind === "image" && replaceImage ? /* @__PURE__ */ jsxs4(
|
|
1390
|
+
Button3,
|
|
1391
|
+
{
|
|
1392
|
+
variant: "ghost",
|
|
1393
|
+
size: "sm",
|
|
1394
|
+
onClick: () => {
|
|
1395
|
+
replaceImage(draft.pos);
|
|
1396
|
+
onClose();
|
|
1397
|
+
},
|
|
1398
|
+
children: [
|
|
1399
|
+
/* @__PURE__ */ jsx5(ImageUp, { "aria-hidden": "true" }),
|
|
1400
|
+
label("replaceImage")
|
|
1401
|
+
]
|
|
1402
|
+
}
|
|
1403
|
+
) : null,
|
|
1404
|
+
/* @__PURE__ */ jsxs4(Button3, { variant: "ghost", size: "sm", onClick: remove, children: [
|
|
1405
|
+
/* @__PURE__ */ jsx5(Trash22, { "aria-hidden": "true" }),
|
|
1406
|
+
label(draft.kind === "link" ? "removeLink" : "removeImage")
|
|
1407
|
+
] })
|
|
1408
|
+
] }),
|
|
1409
|
+
/* @__PURE__ */ jsx5(Button3, { type: "submit", form: "block-editor-edit", size: "sm", children: label("save") })
|
|
1410
|
+
] }) })
|
|
1411
|
+
] }) });
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1217
1414
|
// src/views.tsx
|
|
1218
1415
|
import * as React5 from "react";
|
|
1219
1416
|
import { Node as Node2, mergeAttributes as mergeAttributes2 } from "@tiptap/core";
|
|
1220
|
-
import {
|
|
1221
|
-
|
|
1417
|
+
import {
|
|
1418
|
+
NodeViewContent,
|
|
1419
|
+
NodeViewWrapper,
|
|
1420
|
+
ReactNodeViewRenderer
|
|
1421
|
+
} from "@tiptap/react";
|
|
1422
|
+
import { ChevronDown, LoaderCircle, TriangleAlert } from "lucide-react";
|
|
1222
1423
|
import { parse } from "@godxjp/markdown/codec";
|
|
1223
|
-
import { Textarea } from "@godxjp/ui/data-entry";
|
|
1224
|
-
import {
|
|
1225
|
-
|
|
1424
|
+
import { Input as Input2, Select, Textarea } from "@godxjp/ui/data-entry";
|
|
1425
|
+
import {
|
|
1426
|
+
DropdownMenu as DropdownMenu2,
|
|
1427
|
+
DropdownMenuContent as DropdownMenuContent2,
|
|
1428
|
+
DropdownMenuRadioGroup,
|
|
1429
|
+
DropdownMenuRadioItem,
|
|
1430
|
+
DropdownMenuTrigger as DropdownMenuTrigger2
|
|
1431
|
+
} from "@godxjp/ui/navigation";
|
|
1432
|
+
import { Button as Button4, Text } from "@godxjp/ui/general";
|
|
1433
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1226
1434
|
function RawBlockView({ node, editor, getPos, updateAttributes, selected }) {
|
|
1227
1435
|
const tr = useLabel();
|
|
1228
1436
|
const [editing, setEditing] = React5.useState(false);
|
|
@@ -1238,16 +1446,16 @@ function RawBlockView({ node, editor, getPos, updateAttributes, selected }) {
|
|
|
1238
1446
|
}
|
|
1239
1447
|
editor.chain().focus().insertContentAt({ from: pos, to: pos + node.nodeSize }, doc.content).run();
|
|
1240
1448
|
};
|
|
1241
|
-
return /* @__PURE__ */
|
|
1449
|
+
return /* @__PURE__ */ jsxs5(
|
|
1242
1450
|
NodeViewWrapper,
|
|
1243
1451
|
{
|
|
1244
1452
|
className: "ui-block-editor-raw-block",
|
|
1245
1453
|
"data-selected": selected ? "" : void 0,
|
|
1246
1454
|
children: [
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
/* @__PURE__ */
|
|
1249
|
-
editor.isEditable ? /* @__PURE__ */
|
|
1250
|
-
|
|
1455
|
+
/* @__PURE__ */ jsxs5("div", { className: "ui-block-editor-raw-block-head", contentEditable: false, children: [
|
|
1456
|
+
/* @__PURE__ */ jsx6(Text, { size: "xs", tone: "muted", children: tr("rawBlock") }),
|
|
1457
|
+
editor.isEditable ? /* @__PURE__ */ jsx6(
|
|
1458
|
+
Button4,
|
|
1251
1459
|
{
|
|
1252
1460
|
size: "xs",
|
|
1253
1461
|
variant: "ghost",
|
|
@@ -1256,7 +1464,7 @@ function RawBlockView({ node, editor, getPos, updateAttributes, selected }) {
|
|
|
1256
1464
|
}
|
|
1257
1465
|
) : null
|
|
1258
1466
|
] }),
|
|
1259
|
-
editing ? /* @__PURE__ */
|
|
1467
|
+
editing ? /* @__PURE__ */ jsx6(
|
|
1260
1468
|
Textarea,
|
|
1261
1469
|
{
|
|
1262
1470
|
"aria-label": tr("rawBlock"),
|
|
@@ -1269,7 +1477,7 @@ function RawBlockView({ node, editor, getPos, updateAttributes, selected }) {
|
|
|
1269
1477
|
},
|
|
1270
1478
|
autoFocus: true
|
|
1271
1479
|
}
|
|
1272
|
-
) : /* @__PURE__ */
|
|
1480
|
+
) : /* @__PURE__ */ jsx6("pre", { className: "ui-block-editor-raw-block-source", contentEditable: false, children: node.attrs.source })
|
|
1273
1481
|
]
|
|
1274
1482
|
}
|
|
1275
1483
|
);
|
|
@@ -1277,17 +1485,65 @@ function RawBlockView({ node, editor, getPos, updateAttributes, selected }) {
|
|
|
1277
1485
|
function rawBlockNode() {
|
|
1278
1486
|
return RawBlock.extend({ addNodeView: () => ReactNodeViewRenderer(RawBlockView) });
|
|
1279
1487
|
}
|
|
1488
|
+
function FrontmatterView({ node, updateAttributes, editor, selected }) {
|
|
1489
|
+
const label = useLabel();
|
|
1490
|
+
const [editing, setEditing] = React5.useState(false);
|
|
1491
|
+
const [draft, setDraft] = React5.useState(node.attrs.source);
|
|
1492
|
+
const commit = () => {
|
|
1493
|
+
setEditing(false);
|
|
1494
|
+
updateAttributes({ source: draft });
|
|
1495
|
+
};
|
|
1496
|
+
return /* @__PURE__ */ jsxs5(
|
|
1497
|
+
NodeViewWrapper,
|
|
1498
|
+
{
|
|
1499
|
+
className: "ui-block-editor-raw-block",
|
|
1500
|
+
"data-frontmatter": "",
|
|
1501
|
+
"data-selected": selected ? "" : void 0,
|
|
1502
|
+
children: [
|
|
1503
|
+
/* @__PURE__ */ jsxs5("div", { className: "ui-block-editor-raw-block-head", contentEditable: false, children: [
|
|
1504
|
+
/* @__PURE__ */ jsx6(Text, { size: "xs", tone: "muted", children: label("properties") }),
|
|
1505
|
+
editor.isEditable ? /* @__PURE__ */ jsx6(
|
|
1506
|
+
Button4,
|
|
1507
|
+
{
|
|
1508
|
+
size: "xs",
|
|
1509
|
+
variant: "ghost",
|
|
1510
|
+
onClick: () => editing ? commit() : (setDraft(node.attrs.source), setEditing(true)),
|
|
1511
|
+
children: editing ? label("done") : label("editSource")
|
|
1512
|
+
}
|
|
1513
|
+
) : null
|
|
1514
|
+
] }),
|
|
1515
|
+
editing ? /* @__PURE__ */ jsx6(
|
|
1516
|
+
Textarea,
|
|
1517
|
+
{
|
|
1518
|
+
"aria-label": label("properties"),
|
|
1519
|
+
value: draft,
|
|
1520
|
+
rows: Math.min(12, Math.max(3, draft.split("\n").length)),
|
|
1521
|
+
onValueChange: setDraft,
|
|
1522
|
+
onKeyDown: (event) => {
|
|
1523
|
+
event.stopPropagation();
|
|
1524
|
+
if (event.key === "Escape") commit();
|
|
1525
|
+
},
|
|
1526
|
+
autoFocus: true
|
|
1527
|
+
}
|
|
1528
|
+
) : /* @__PURE__ */ jsx6("pre", { className: "ui-block-editor-raw-block-source", contentEditable: false, children: node.attrs.source })
|
|
1529
|
+
]
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
function frontmatterNode() {
|
|
1534
|
+
return Frontmatter.extend({ addNodeView: () => ReactNodeViewRenderer(FrontmatterView) });
|
|
1535
|
+
}
|
|
1280
1536
|
function embedNode(render) {
|
|
1281
1537
|
function EmbedView({ node, selected }) {
|
|
1282
1538
|
const tr = useLabel();
|
|
1283
1539
|
const target = node.attrs.target;
|
|
1284
|
-
return /* @__PURE__ */
|
|
1540
|
+
return /* @__PURE__ */ jsx6(
|
|
1285
1541
|
NodeViewWrapper,
|
|
1286
1542
|
{
|
|
1287
1543
|
className: "ui-block-editor-embed",
|
|
1288
1544
|
"data-selected": selected ? "" : void 0,
|
|
1289
1545
|
contentEditable: false,
|
|
1290
|
-
children: render ? render(target) : /* @__PURE__ */
|
|
1546
|
+
children: render ? render(target) : /* @__PURE__ */ jsx6(Text, { size: "sm", tone: "muted", children: tr("embed", { target }) })
|
|
1291
1547
|
}
|
|
1292
1548
|
);
|
|
1293
1549
|
}
|
|
@@ -1300,21 +1556,21 @@ function uploadNode(actions) {
|
|
|
1300
1556
|
return (
|
|
1301
1557
|
// A plain span, not NodeViewWrapper: Tiptap's wrapper spreads its `as` prop onto the DOM as an
|
|
1302
1558
|
// invalid attribute, and this inline view needs nothing else it adds (no drag).
|
|
1303
|
-
/* @__PURE__ */
|
|
1559
|
+
/* @__PURE__ */ jsx6(
|
|
1304
1560
|
"span",
|
|
1305
1561
|
{
|
|
1306
1562
|
"data-node-view-wrapper": "",
|
|
1307
1563
|
className: "ui-block-editor-upload",
|
|
1308
1564
|
"data-status": status,
|
|
1309
1565
|
contentEditable: false,
|
|
1310
|
-
children: status === "uploading" ? /* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1312
|
-
/* @__PURE__ */
|
|
1313
|
-
] }) : /* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
/* @__PURE__ */
|
|
1317
|
-
/* @__PURE__ */
|
|
1566
|
+
children: status === "uploading" ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1567
|
+
/* @__PURE__ */ jsx6(LoaderCircle, { className: "ui-block-editor-upload-spinner", "aria-hidden": "true" }),
|
|
1568
|
+
/* @__PURE__ */ jsx6(Text, { as: "span", size: "sm", tone: "muted", role: "status", children: tr("uploading", { name }) })
|
|
1569
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1570
|
+
/* @__PURE__ */ jsx6(TriangleAlert, { "aria-hidden": "true" }),
|
|
1571
|
+
/* @__PURE__ */ jsx6(Text, { as: "span", size: "sm", tone: "destructive", role: "alert", children: tr("uploadFailed", { name }) }),
|
|
1572
|
+
/* @__PURE__ */ jsx6(Button4, { size: "xs", variant: "ghost", onClick: () => actions.retry(id), children: tr("retry") }),
|
|
1573
|
+
/* @__PURE__ */ jsx6(Button4, { size: "xs", variant: "ghost", onClick: () => actions.remove(id), children: tr("remove") })
|
|
1318
1574
|
] })
|
|
1319
1575
|
}
|
|
1320
1576
|
)
|
|
@@ -1338,9 +1594,143 @@ function uploadNode(actions) {
|
|
|
1338
1594
|
addNodeView: () => ReactNodeViewRenderer(UploadView, { as: "span" })
|
|
1339
1595
|
});
|
|
1340
1596
|
}
|
|
1597
|
+
var CALLOUT_KINDS = ["note", "tip", "important", "warning", "caution"];
|
|
1598
|
+
var kindLabelKey = {
|
|
1599
|
+
note: "calloutNote",
|
|
1600
|
+
tip: "calloutTip",
|
|
1601
|
+
important: "calloutImportant",
|
|
1602
|
+
warning: "calloutWarning",
|
|
1603
|
+
caution: "calloutCaution"
|
|
1604
|
+
};
|
|
1605
|
+
function CalloutView({ node, updateAttributes, editor }) {
|
|
1606
|
+
const label = useLabel();
|
|
1607
|
+
const kind = node.attrs.kind;
|
|
1608
|
+
const title = node.attrs.title ?? "";
|
|
1609
|
+
const defaultTitle = label(kindLabelKey[kind] ?? "calloutNote");
|
|
1610
|
+
return /* @__PURE__ */ jsxs5(NodeViewWrapper, { className: "ui-prose-callout", "data-type": "callout", "data-kind": kind, role: "note", children: [
|
|
1611
|
+
editor.isEditable ? /* @__PURE__ */ jsxs5("div", { className: "ui-block-editor-callout-head", contentEditable: false, children: [
|
|
1612
|
+
/* @__PURE__ */ jsxs5(DropdownMenu2, { children: [
|
|
1613
|
+
/* @__PURE__ */ jsx6(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs5(
|
|
1614
|
+
Button4,
|
|
1615
|
+
{
|
|
1616
|
+
size: "xs",
|
|
1617
|
+
variant: "ghost",
|
|
1618
|
+
"aria-label": `${label("calloutKind")}: ${defaultTitle}`,
|
|
1619
|
+
children: [
|
|
1620
|
+
defaultTitle,
|
|
1621
|
+
/* @__PURE__ */ jsx6(ChevronDown, { "aria-hidden": "true" })
|
|
1622
|
+
]
|
|
1623
|
+
}
|
|
1624
|
+
) }),
|
|
1625
|
+
/* @__PURE__ */ jsx6(DropdownMenuContent2, { align: "start", "aria-label": label("calloutKind"), children: /* @__PURE__ */ jsx6(
|
|
1626
|
+
DropdownMenuRadioGroup,
|
|
1627
|
+
{
|
|
1628
|
+
value: kind,
|
|
1629
|
+
onValueChange: (next) => updateAttributes({ kind: next }),
|
|
1630
|
+
children: CALLOUT_KINDS.map((k) => /* @__PURE__ */ jsx6(DropdownMenuRadioItem, { value: k, children: label(kindLabelKey[k]) }, k))
|
|
1631
|
+
}
|
|
1632
|
+
) })
|
|
1633
|
+
] }),
|
|
1634
|
+
/* @__PURE__ */ jsx6(
|
|
1635
|
+
Input2,
|
|
1636
|
+
{
|
|
1637
|
+
size: "sm",
|
|
1638
|
+
className: "ui-block-editor-callout-title",
|
|
1639
|
+
"aria-label": label("calloutTitle"),
|
|
1640
|
+
placeholder: defaultTitle,
|
|
1641
|
+
value: title,
|
|
1642
|
+
onValueChange: (next) => updateAttributes({ title: next.trim() === "" ? null : next })
|
|
1643
|
+
}
|
|
1644
|
+
)
|
|
1645
|
+
] }) : /* @__PURE__ */ jsx6("p", { className: "ui-prose-callout-title", contentEditable: false, children: title || defaultTitle }),
|
|
1646
|
+
/* @__PURE__ */ jsx6(NodeViewContent, { className: "ui-block-editor-callout-body" })
|
|
1647
|
+
] });
|
|
1648
|
+
}
|
|
1649
|
+
function calloutNode(base) {
|
|
1650
|
+
return base.extend({ addNodeView: () => ReactNodeViewRenderer(CalloutView) });
|
|
1651
|
+
}
|
|
1652
|
+
var WIDTHS = [25, 33, 50, 67, 75];
|
|
1653
|
+
function ColumnsView({ node, editor, getPos }) {
|
|
1654
|
+
const label = useLabel();
|
|
1655
|
+
const [current, setCurrent] = React5.useState(null);
|
|
1656
|
+
React5.useEffect(() => {
|
|
1657
|
+
const read = () => {
|
|
1658
|
+
const pos = getPos();
|
|
1659
|
+
if (typeof pos !== "number") return setCurrent(null);
|
|
1660
|
+
const { $from } = editor.state.selection;
|
|
1661
|
+
for (let depth = $from.depth; depth > 0; depth--) {
|
|
1662
|
+
if ($from.node(depth).type.name === "columns" && $from.before(depth) === pos) {
|
|
1663
|
+
return setCurrent($from.index(depth));
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
setCurrent(null);
|
|
1667
|
+
};
|
|
1668
|
+
read();
|
|
1669
|
+
editor.on("selectionUpdate", read);
|
|
1670
|
+
editor.on("update", read);
|
|
1671
|
+
return () => {
|
|
1672
|
+
editor.off("selectionUpdate", read);
|
|
1673
|
+
editor.off("update", read);
|
|
1674
|
+
};
|
|
1675
|
+
}, [editor, getPos]);
|
|
1676
|
+
const columnPos = (index) => {
|
|
1677
|
+
const pos = getPos();
|
|
1678
|
+
if (typeof pos !== "number") return null;
|
|
1679
|
+
let at = pos + 1;
|
|
1680
|
+
for (let i = 0; i < index; i++) at += node.child(i).nodeSize;
|
|
1681
|
+
return at;
|
|
1682
|
+
};
|
|
1683
|
+
const addColumn = () => {
|
|
1684
|
+
const pos = getPos();
|
|
1685
|
+
if (typeof pos !== "number" || node.childCount >= 4) return;
|
|
1686
|
+
const end = pos + node.nodeSize - 1;
|
|
1687
|
+
const column = editor.schema.nodes.column.create(
|
|
1688
|
+
null,
|
|
1689
|
+
editor.schema.nodes.paragraph.create()
|
|
1690
|
+
);
|
|
1691
|
+
editor.view.dispatch(editor.state.tr.insert(end, column));
|
|
1692
|
+
};
|
|
1693
|
+
const removeColumn = () => {
|
|
1694
|
+
if (current == null || node.childCount <= 2) return;
|
|
1695
|
+
const at = columnPos(current);
|
|
1696
|
+
if (at == null) return;
|
|
1697
|
+
editor.view.dispatch(editor.state.tr.delete(at, at + node.child(current).nodeSize));
|
|
1698
|
+
};
|
|
1699
|
+
const setWidth = (value) => {
|
|
1700
|
+
if (current == null) return;
|
|
1701
|
+
const at = columnPos(current);
|
|
1702
|
+
if (at == null) return;
|
|
1703
|
+
const width2 = value === "auto" ? null : Number(value);
|
|
1704
|
+
editor.view.dispatch(editor.state.tr.setNodeAttribute(at, "width", width2));
|
|
1705
|
+
};
|
|
1706
|
+
const width = current == null ? null : node.child(current).attrs.width ?? null;
|
|
1707
|
+
return /* @__PURE__ */ jsxs5(NodeViewWrapper, { className: "ui-block-editor-columns", "data-type": "columns", children: [
|
|
1708
|
+
editor.isEditable && current != null ? /* @__PURE__ */ jsxs5("div", { className: "ui-block-editor-columns-bar", contentEditable: false, children: [
|
|
1709
|
+
/* @__PURE__ */ jsx6(Button4, { size: "xs", variant: "ghost", disabled: node.childCount >= 4, onClick: addColumn, children: label("addColumn") }),
|
|
1710
|
+
/* @__PURE__ */ jsx6(Button4, { size: "xs", variant: "ghost", disabled: node.childCount <= 2, onClick: removeColumn, children: label("removeColumn") }),
|
|
1711
|
+
/* @__PURE__ */ jsx6(
|
|
1712
|
+
Select,
|
|
1713
|
+
{
|
|
1714
|
+
size: "xs",
|
|
1715
|
+
"aria-label": label("columnWidth"),
|
|
1716
|
+
value: width == null ? "auto" : String(width),
|
|
1717
|
+
onValueChange: setWidth,
|
|
1718
|
+
options: [
|
|
1719
|
+
{ value: "auto", label: label("widthAuto") },
|
|
1720
|
+
...WIDTHS.map((w) => ({ value: String(w), label: `${w}%` }))
|
|
1721
|
+
]
|
|
1722
|
+
}
|
|
1723
|
+
)
|
|
1724
|
+
] }) : null,
|
|
1725
|
+
/* @__PURE__ */ jsx6(NodeViewContent, { className: "ui-block-editor-columns-content" })
|
|
1726
|
+
] });
|
|
1727
|
+
}
|
|
1728
|
+
function columnsNode(base) {
|
|
1729
|
+
return base.extend({ addNodeView: () => ReactNodeViewRenderer(ColumnsView) });
|
|
1730
|
+
}
|
|
1341
1731
|
|
|
1342
1732
|
// src/block-editor.tsx
|
|
1343
|
-
import { Fragment as
|
|
1733
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1344
1734
|
function useSuggestion(toMenuItem, items, pick) {
|
|
1345
1735
|
const [menu, setMenu] = React6.useState(null);
|
|
1346
1736
|
const menuRef = React6.useRef(menu);
|
|
@@ -1402,6 +1792,7 @@ var BlockEditor = React6.forwardRef(
|
|
|
1402
1792
|
resolveUrl,
|
|
1403
1793
|
actions = [],
|
|
1404
1794
|
labels,
|
|
1795
|
+
appearance = "framed",
|
|
1405
1796
|
disabled = false,
|
|
1406
1797
|
readOnly = false,
|
|
1407
1798
|
autoFocus = false,
|
|
@@ -1426,6 +1817,8 @@ var BlockEditor = React6.forwardRef(
|
|
|
1426
1817
|
null
|
|
1427
1818
|
);
|
|
1428
1819
|
const fileInput = React6.useRef(null);
|
|
1820
|
+
const [editTarget, setEditTarget] = React6.useState(null);
|
|
1821
|
+
const replacing = React6.useRef(null);
|
|
1429
1822
|
const live = React6.useRef({
|
|
1430
1823
|
onValueChange,
|
|
1431
1824
|
upload,
|
|
@@ -1547,6 +1940,65 @@ var BlockEditor = React6.forwardRef(
|
|
|
1547
1940
|
}
|
|
1548
1941
|
fileInput.current?.click();
|
|
1549
1942
|
}, []);
|
|
1943
|
+
const linkTargetAt = React6.useCallback(
|
|
1944
|
+
(editor2, pos, selection) => {
|
|
1945
|
+
const { state } = editor2;
|
|
1946
|
+
const type = state.schema.marks.link;
|
|
1947
|
+
const $pos = state.doc.resolve(pos);
|
|
1948
|
+
const range = getMarkRange($pos, type);
|
|
1949
|
+
if (range) {
|
|
1950
|
+
const mark = $pos.marks().find((m) => m.type === type) ?? state.doc.nodeAt(range.from)?.marks.find((m) => m.type === type);
|
|
1951
|
+
return {
|
|
1952
|
+
kind: "link",
|
|
1953
|
+
from: range.from,
|
|
1954
|
+
to: range.to,
|
|
1955
|
+
text: state.doc.textBetween(range.from, range.to),
|
|
1956
|
+
href: mark?.attrs.href ?? "",
|
|
1957
|
+
title: mark?.attrs.title ?? ""
|
|
1958
|
+
};
|
|
1959
|
+
}
|
|
1960
|
+
if (selection && selection.from !== selection.to) {
|
|
1961
|
+
return {
|
|
1962
|
+
kind: "link",
|
|
1963
|
+
from: selection.from,
|
|
1964
|
+
to: selection.to,
|
|
1965
|
+
text: state.doc.textBetween(selection.from, selection.to),
|
|
1966
|
+
href: "",
|
|
1967
|
+
title: ""
|
|
1968
|
+
};
|
|
1969
|
+
}
|
|
1970
|
+
return null;
|
|
1971
|
+
},
|
|
1972
|
+
[]
|
|
1973
|
+
);
|
|
1974
|
+
const editLinkAtSelection = React6.useCallback(() => {
|
|
1975
|
+
const editor2 = editorRef.current;
|
|
1976
|
+
if (!editor2) return;
|
|
1977
|
+
const { from, to } = liveSelection(editor2);
|
|
1978
|
+
const target = linkTargetAt(editor2, from, { from, to });
|
|
1979
|
+
if (target) setEditTarget(target);
|
|
1980
|
+
}, [linkTargetAt]);
|
|
1981
|
+
const replaceImage = React6.useCallback((pos) => {
|
|
1982
|
+
const editor2 = editorRef.current;
|
|
1983
|
+
if (!editor2) return;
|
|
1984
|
+
const pick = live.current.pickMedia;
|
|
1985
|
+
if (pick) {
|
|
1986
|
+
void pick().then((media) => {
|
|
1987
|
+
const node = editor2.state.doc.nodeAt(pos);
|
|
1988
|
+
if (!media || node?.type.name !== "image") return;
|
|
1989
|
+
editor2.view.dispatch(
|
|
1990
|
+
editor2.state.tr.setNodeMarkup(pos, void 0, {
|
|
1991
|
+
...node.attrs,
|
|
1992
|
+
src: media.url,
|
|
1993
|
+
alt: media.name ?? node.attrs.alt
|
|
1994
|
+
})
|
|
1995
|
+
);
|
|
1996
|
+
});
|
|
1997
|
+
return;
|
|
1998
|
+
}
|
|
1999
|
+
replacing.current = pos;
|
|
2000
|
+
fileInput.current?.click();
|
|
2001
|
+
}, []);
|
|
1550
2002
|
const canInsertImage = Boolean(pickMedia || upload);
|
|
1551
2003
|
const commands = React6.useMemo(() => {
|
|
1552
2004
|
const builtin = builtinCommands(
|
|
@@ -1590,7 +2042,7 @@ var BlockEditor = React6.forwardRef(
|
|
|
1590
2042
|
value: `${s.target}#${s.heading ?? ""}`,
|
|
1591
2043
|
label: s.label ?? s.target,
|
|
1592
2044
|
description: s.description,
|
|
1593
|
-
icon: /* @__PURE__ */
|
|
2045
|
+
icon: /* @__PURE__ */ jsx7(FileText, {})
|
|
1594
2046
|
}),
|
|
1595
2047
|
(query) => live.current.suggestWikilinks?.(query) ?? [],
|
|
1596
2048
|
(editor2, range, item) => {
|
|
@@ -1619,10 +2071,17 @@ var BlockEditor = React6.forwardRef(
|
|
|
1619
2071
|
},
|
|
1620
2072
|
embed: embedNode(renderEmbed),
|
|
1621
2073
|
rawBlock: rawBlockNode(),
|
|
2074
|
+
frontmatter: frontmatterNode(),
|
|
2075
|
+
callout: calloutNode(Callout),
|
|
2076
|
+
columns: columnsNode(Columns),
|
|
2077
|
+
toggleLabel: (open) => labelRef.current(open ? "collapseToggle" : "expandToggle"),
|
|
1622
2078
|
resolveUrl
|
|
1623
2079
|
}),
|
|
1624
2080
|
uploadNode(uploadActions),
|
|
1625
|
-
BlockKeys.configure({
|
|
2081
|
+
BlockKeys.configure({
|
|
2082
|
+
openMenu: (start) => setMenuRequest({ start, nonce: Date.now() }),
|
|
2083
|
+
editLink: () => editLinkRef.current()
|
|
2084
|
+
}),
|
|
1626
2085
|
suggestionTrigger("slashMenu", "/", slash.bridge),
|
|
1627
2086
|
// A Japanese keyboard types the full-width slash; it opens the same menu.
|
|
1628
2087
|
suggestionTrigger("slashMenuWide", "\uFF0F", slash.bridge),
|
|
@@ -1635,6 +2094,8 @@ var BlockEditor = React6.forwardRef(
|
|
|
1635
2094
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1636
2095
|
[]
|
|
1637
2096
|
);
|
|
2097
|
+
const editLinkRef = React6.useRef(editLinkAtSelection);
|
|
2098
|
+
editLinkRef.current = editLinkAtSelection;
|
|
1638
2099
|
const editor = useEditor({
|
|
1639
2100
|
extensions,
|
|
1640
2101
|
content: parse2(initial),
|
|
@@ -1650,6 +2111,38 @@ var BlockEditor = React6.forwardRef(
|
|
|
1650
2111
|
...ariaLabelledby ? { "aria-labelledby": ariaLabelledby } : { "aria-label": ariaLabel ?? label("editor") },
|
|
1651
2112
|
...ariaDescribedby ? { "aria-describedby": ariaDescribedby } : {}
|
|
1652
2113
|
},
|
|
2114
|
+
// While editing, a link is TEXT, not a way out: the browser follows an <a href> even inside
|
|
2115
|
+
// contenteditable, which left the page mid-edit and lost the work. Cancel the navigation and
|
|
2116
|
+
// let ProseMirror see the click (it opens the link drawer). Read-only, links navigate.
|
|
2117
|
+
handleDOMEvents: {
|
|
2118
|
+
click: (view, event) => {
|
|
2119
|
+
if (view.editable && event.target?.closest?.("a[href]")) {
|
|
2120
|
+
event.preventDefault();
|
|
2121
|
+
}
|
|
2122
|
+
return false;
|
|
2123
|
+
}
|
|
2124
|
+
},
|
|
2125
|
+
// A click on a link or an image opens its settings drawer (text / URL / title; src / alt /
|
|
2126
|
+
// title). Read-only, links behave as links.
|
|
2127
|
+
handleClick: (view, pos) => {
|
|
2128
|
+
const instance = editorRef.current;
|
|
2129
|
+
if (!instance || !view.editable) return false;
|
|
2130
|
+
const target = linkTargetAt(instance, pos);
|
|
2131
|
+
if (!target) return false;
|
|
2132
|
+
setEditTarget(target);
|
|
2133
|
+
return true;
|
|
2134
|
+
},
|
|
2135
|
+
handleClickOn: (view, pos, node) => {
|
|
2136
|
+
if (!view.editable || node.type.name !== "image") return false;
|
|
2137
|
+
setEditTarget({
|
|
2138
|
+
kind: "image",
|
|
2139
|
+
pos,
|
|
2140
|
+
src: node.attrs.src ?? "",
|
|
2141
|
+
alt: node.attrs.alt ?? "",
|
|
2142
|
+
title: node.attrs.title ?? ""
|
|
2143
|
+
});
|
|
2144
|
+
return true;
|
|
2145
|
+
},
|
|
1653
2146
|
// Copy writes Markdown, so a block pasted into a plain-text field reads as the body does.
|
|
1654
2147
|
clipboardTextSerializer: (slice) => serialize({ type: "doc", content: slice.content.toJSON() }).trimEnd(),
|
|
1655
2148
|
handlePaste: (view, event) => {
|
|
@@ -1715,7 +2208,7 @@ var BlockEditor = React6.forwardRef(
|
|
|
1715
2208
|
editor.chain().focus().insertContent("/").run();
|
|
1716
2209
|
};
|
|
1717
2210
|
const menuItems = (state) => (state?.items ?? []).map((c) => ({ value: c.key, label: c.label, icon: c.icon }));
|
|
1718
|
-
return /* @__PURE__ */
|
|
2211
|
+
return /* @__PURE__ */ jsx7(LabelsContext.Provider, { value: label, children: /* @__PURE__ */ jsxs6(
|
|
1719
2212
|
"div",
|
|
1720
2213
|
{
|
|
1721
2214
|
ref: (node) => {
|
|
@@ -1723,10 +2216,11 @@ var BlockEditor = React6.forwardRef(
|
|
|
1723
2216
|
setHost(node);
|
|
1724
2217
|
},
|
|
1725
2218
|
className: ["ui-block-editor", className].filter(Boolean).join(" "),
|
|
2219
|
+
"data-appearance": appearance,
|
|
1726
2220
|
"data-disabled": disabled ? "" : void 0,
|
|
1727
2221
|
children: [
|
|
1728
|
-
editor ? /* @__PURE__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
2222
|
+
editor ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
2223
|
+
/* @__PURE__ */ jsx7(
|
|
1730
2224
|
BlockHandle,
|
|
1731
2225
|
{
|
|
1732
2226
|
editor,
|
|
@@ -1736,10 +2230,20 @@ var BlockEditor = React6.forwardRef(
|
|
|
1736
2230
|
menuRequest
|
|
1737
2231
|
}
|
|
1738
2232
|
),
|
|
1739
|
-
/* @__PURE__ */
|
|
2233
|
+
/* @__PURE__ */ jsx7(FormatToolbar, { editor, onEditLink: editLinkAtSelection }),
|
|
2234
|
+
/* @__PURE__ */ jsx7(
|
|
2235
|
+
EditDrawer,
|
|
2236
|
+
{
|
|
2237
|
+
editor,
|
|
2238
|
+
target: editTarget,
|
|
2239
|
+
onClose: () => setEditTarget(null),
|
|
2240
|
+
resolveUrl,
|
|
2241
|
+
replaceImage: pickMedia || upload ? replaceImage : null
|
|
2242
|
+
}
|
|
2243
|
+
)
|
|
1740
2244
|
] }) : null,
|
|
1741
|
-
/* @__PURE__ */
|
|
1742
|
-
/* @__PURE__ */
|
|
2245
|
+
/* @__PURE__ */ jsx7(EditorContent, { editor }),
|
|
2246
|
+
/* @__PURE__ */ jsx7(
|
|
1743
2247
|
SuggestionMenu,
|
|
1744
2248
|
{
|
|
1745
2249
|
open: slash.menu != null,
|
|
@@ -1761,7 +2265,7 @@ var BlockEditor = React6.forwardRef(
|
|
|
1761
2265
|
editable: editor?.view.dom ?? null
|
|
1762
2266
|
}
|
|
1763
2267
|
),
|
|
1764
|
-
/* @__PURE__ */
|
|
2268
|
+
/* @__PURE__ */ jsx7(
|
|
1765
2269
|
SuggestionMenu,
|
|
1766
2270
|
{
|
|
1767
2271
|
open: wiki.menu != null,
|
|
@@ -1771,7 +2275,7 @@ var BlockEditor = React6.forwardRef(
|
|
|
1771
2275
|
value: `${s.target}#${s.heading ?? ""}`,
|
|
1772
2276
|
label: s.label ?? s.target,
|
|
1773
2277
|
description: s.description,
|
|
1774
|
-
icon: /* @__PURE__ */
|
|
2278
|
+
icon: /* @__PURE__ */ jsx7(FileText, {})
|
|
1775
2279
|
})),
|
|
1776
2280
|
active: wiki.menu?.active,
|
|
1777
2281
|
onActiveChange: (active) => wiki.setMenu((m) => m ? { ...m, active } : m),
|
|
@@ -1788,8 +2292,8 @@ var BlockEditor = React6.forwardRef(
|
|
|
1788
2292
|
editable: editor?.view.dom ?? null
|
|
1789
2293
|
}
|
|
1790
2294
|
),
|
|
1791
|
-
status ? /* @__PURE__ */
|
|
1792
|
-
canInsertImage && !pickMedia ? /* @__PURE__ */
|
|
2295
|
+
status ? /* @__PURE__ */ jsx7(Text2, { size: "sm", tone: "destructive", role: "alert", className: "ui-block-editor-status", children: status }) : null,
|
|
2296
|
+
canInsertImage && !pickMedia ? /* @__PURE__ */ jsx7(
|
|
1793
2297
|
"input",
|
|
1794
2298
|
{
|
|
1795
2299
|
ref: fileInput,
|
|
@@ -1801,7 +2305,18 @@ var BlockEditor = React6.forwardRef(
|
|
|
1801
2305
|
onChange: (event) => {
|
|
1802
2306
|
const files = [...event.currentTarget.files ?? []];
|
|
1803
2307
|
event.currentTarget.value = "";
|
|
1804
|
-
if (editor)
|
|
2308
|
+
if (!editor) return;
|
|
2309
|
+
const at = replacing.current;
|
|
2310
|
+
replacing.current = null;
|
|
2311
|
+
if (at != null && files.length) {
|
|
2312
|
+
const node = editor.state.doc.nodeAt(at);
|
|
2313
|
+
if (node?.type.name === "image") {
|
|
2314
|
+
editor.view.dispatch(editor.state.tr.delete(at, at + node.nodeSize));
|
|
2315
|
+
}
|
|
2316
|
+
startUploads(editor, files.slice(0, 1), at);
|
|
2317
|
+
return;
|
|
2318
|
+
}
|
|
2319
|
+
startUploads(editor, files);
|
|
1805
2320
|
}
|
|
1806
2321
|
}
|
|
1807
2322
|
) : null
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/block-editor",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.28.0",
|
|
4
4
|
"description": "Block editor for GoDX apps (Notion / note.com style) on Tiptap: slash menu, block handles, floating format toolbar; reads and writes Markdown through @godxjp/markdown/codec, IME-safe, ja / en / vi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"lucide-react": "^1.37.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@godxjp/markdown": "~31.
|
|
49
|
-
"@godxjp/ui": "~31.
|
|
48
|
+
"@godxjp/markdown": "~31.28.0",
|
|
49
|
+
"@godxjp/ui": "~31.28.0",
|
|
50
50
|
"react": ">=19.0.0",
|
|
51
51
|
"react-dom": ">=19.0.0"
|
|
52
52
|
},
|