tiptap-markdown-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1417 @@
1
+ "use client";
2
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
+ import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
4
+ import Image from "@tiptap/extension-image";
5
+ import { TableOfContents } from "@tiptap/extension-table-of-contents";
6
+ import { Markdown } from "@tiptap/markdown";
7
+ import { NodeViewWrapper, NodeViewContent, useEditor, EditorContent, ReactNodeViewRenderer, useEditorState } from "@tiptap/react";
8
+ import { forwardRef, useEffect, useImperativeHandle, useState, useRef, useCallback, useContext, createContext } from "react";
9
+ import { s as styles$4, b as baseExtensions, l as lowlight, m as makeTocGetId, p as pureCodeBlock, a as pureImage } from "./extractToc-C7e1DuVc.js";
10
+ import { R, e } from "./extractToc-C7e1DuVc.js";
11
+ import * as Popover from "@radix-ui/react-popover";
12
+ import { createPortal } from "react-dom";
13
+ function Svg({ size = "1em", children, ...rest }) {
14
+ return /* @__PURE__ */ jsx(
15
+ "svg",
16
+ {
17
+ xmlns: "http://www.w3.org/2000/svg",
18
+ width: size,
19
+ height: size,
20
+ viewBox: "0 0 24 24",
21
+ fill: "none",
22
+ stroke: "currentColor",
23
+ strokeWidth: 2,
24
+ strokeLinecap: "round",
25
+ strokeLinejoin: "round",
26
+ "aria-hidden": "true",
27
+ focusable: "false",
28
+ ...rest,
29
+ children
30
+ }
31
+ );
32
+ }
33
+ const BoldIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
34
+ /* @__PURE__ */ jsx("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
35
+ /* @__PURE__ */ jsx("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
36
+ ] });
37
+ const ItalicIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
38
+ /* @__PURE__ */ jsx("line", { x1: "19", x2: "10", y1: "4", y2: "4" }),
39
+ /* @__PURE__ */ jsx("line", { x1: "14", x2: "5", y1: "20", y2: "20" }),
40
+ /* @__PURE__ */ jsx("line", { x1: "15", x2: "9", y1: "4", y2: "20" })
41
+ ] });
42
+ const UnderlineIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
43
+ /* @__PURE__ */ jsx("path", { d: "M6 4v6a6 6 0 0 0 12 0V4" }),
44
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "20", y2: "20" })
45
+ ] });
46
+ const StrikethroughIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
47
+ /* @__PURE__ */ jsx("path", { d: "M16 4H9a3 3 0 0 0-2.83 4" }),
48
+ /* @__PURE__ */ jsx("path", { d: "M14 12a4 4 0 0 1 0 8H6" }),
49
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" })
50
+ ] });
51
+ const CodeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
52
+ /* @__PURE__ */ jsx("polyline", { points: "16 18 22 12 16 6" }),
53
+ /* @__PURE__ */ jsx("polyline", { points: "8 6 2 12 8 18" })
54
+ ] });
55
+ const LinkIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
56
+ /* @__PURE__ */ jsx("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
57
+ /* @__PURE__ */ jsx("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
58
+ ] });
59
+ const ImageIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
60
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
61
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
62
+ /* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
63
+ ] });
64
+ const ListUnorderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
65
+ /* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "6", y2: "6" }),
66
+ /* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "12", y2: "12" }),
67
+ /* @__PURE__ */ jsx("line", { x1: "8", x2: "21", y1: "18", y2: "18" }),
68
+ /* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "6", y2: "6" }),
69
+ /* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "12", y2: "12" }),
70
+ /* @__PURE__ */ jsx("line", { x1: "3", x2: "3.01", y1: "18", y2: "18" })
71
+ ] });
72
+ const ListOrderedIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
73
+ /* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "6", y2: "6" }),
74
+ /* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "12", y2: "12" }),
75
+ /* @__PURE__ */ jsx("line", { x1: "10", x2: "21", y1: "18", y2: "18" }),
76
+ /* @__PURE__ */ jsx("path", { d: "M4 6h1v4" }),
77
+ /* @__PURE__ */ jsx("path", { d: "M4 10h2" }),
78
+ /* @__PURE__ */ jsx("path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1" })
79
+ ] });
80
+ const ListChecksIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
81
+ /* @__PURE__ */ jsx("path", { d: "m3 17 2 2 4-4" }),
82
+ /* @__PURE__ */ jsx("path", { d: "m3 7 2 2 4-4" }),
83
+ /* @__PURE__ */ jsx("path", { d: "M13 6h8" }),
84
+ /* @__PURE__ */ jsx("path", { d: "M13 12h8" }),
85
+ /* @__PURE__ */ jsx("path", { d: "M13 18h8" })
86
+ ] });
87
+ const UndoIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
88
+ /* @__PURE__ */ jsx("path", { d: "M9 14 4 9l5-5" }),
89
+ /* @__PURE__ */ jsx("path", { d: "M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1-5.5 5.5H11" })
90
+ ] });
91
+ const RedoIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
92
+ /* @__PURE__ */ jsx("path", { d: "m15 14 5-5-5-5" }),
93
+ /* @__PURE__ */ jsx("path", { d: "M20 9H9.5A5.5 5.5 0 0 0 4 14.5 5.5 5.5 0 0 0 9.5 20H13" })
94
+ ] });
95
+ const ChevronDownIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
96
+ const TrashIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
97
+ /* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
98
+ /* @__PURE__ */ jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
99
+ /* @__PURE__ */ jsx("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }),
100
+ /* @__PURE__ */ jsx("line", { x1: "10", x2: "10", y1: "11", y2: "17" }),
101
+ /* @__PURE__ */ jsx("line", { x1: "14", x2: "14", y1: "11", y2: "17" })
102
+ ] });
103
+ const LockIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
104
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2" }),
105
+ /* @__PURE__ */ jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
106
+ ] });
107
+ const MenuIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
108
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
109
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
110
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
111
+ ] });
112
+ const ColumnBeforeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
113
+ /* @__PURE__ */ jsx("rect", { x: "10", y: "4", width: "11", height: "16", rx: "1" }),
114
+ /* @__PURE__ */ jsx("path", { d: "M14 4v16" }),
115
+ /* @__PURE__ */ jsx("path", { d: "M5 9v6" }),
116
+ /* @__PURE__ */ jsx("path", { d: "M2 12h6" })
117
+ ] });
118
+ const ColumnAfterIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
119
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "11", height: "16", rx: "1" }),
120
+ /* @__PURE__ */ jsx("path", { d: "M10 4v16" }),
121
+ /* @__PURE__ */ jsx("path", { d: "M19 9v6" }),
122
+ /* @__PURE__ */ jsx("path", { d: "M16 12h6" })
123
+ ] });
124
+ const ColumnDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
125
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "1" }),
126
+ /* @__PURE__ */ jsx("path", { d: "M12 4v16" }),
127
+ /* @__PURE__ */ jsx("path", { d: "m8 9 8 6" }),
128
+ /* @__PURE__ */ jsx("path", { d: "m16 9-8 6" })
129
+ ] });
130
+ const RowBeforeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
131
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "10", width: "16", height: "11", rx: "1" }),
132
+ /* @__PURE__ */ jsx("path", { d: "M4 14h16" }),
133
+ /* @__PURE__ */ jsx("path", { d: "M9 5h6" }),
134
+ /* @__PURE__ */ jsx("path", { d: "M12 2v6" })
135
+ ] });
136
+ const RowAfterIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
137
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "3", width: "16", height: "11", rx: "1" }),
138
+ /* @__PURE__ */ jsx("path", { d: "M4 10h16" }),
139
+ /* @__PURE__ */ jsx("path", { d: "M9 19h6" }),
140
+ /* @__PURE__ */ jsx("path", { d: "M12 16v6" })
141
+ ] });
142
+ const RowDeleteIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
143
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "1" }),
144
+ /* @__PURE__ */ jsx("path", { d: "M4 12h16" }),
145
+ /* @__PURE__ */ jsx("path", { d: "m9 8 6 8" }),
146
+ /* @__PURE__ */ jsx("path", { d: "m15 8-6 8" })
147
+ ] });
148
+ const defaultToolbarLabels = {
149
+ undo: "Undo",
150
+ redo: "Redo",
151
+ style: "Style",
152
+ normalText: "Normal text",
153
+ headingLabel: (level) => `Heading ${level}`,
154
+ fontSize: "Font size",
155
+ fontSizeDefault: "Default",
156
+ bold: "Bold",
157
+ italic: "Italic",
158
+ underline: "Underline",
159
+ strike: "Strikethrough",
160
+ code: "Inline code",
161
+ textColor: "Text color",
162
+ highlight: "Highlight",
163
+ colorNone: "None",
164
+ colorTheme: "THEME",
165
+ scriptMenu: "Superscript / Subscript",
166
+ scriptNormal: "Normal",
167
+ superscript: "Superscript",
168
+ subscript: "Subscript",
169
+ link: "Link",
170
+ linkPrompt: "Enter URL",
171
+ image: "Image",
172
+ imageUploadFailed: "Image upload failed",
173
+ blockquote: "Blockquote",
174
+ bulletList: "Bullet list",
175
+ orderedList: "Ordered list",
176
+ taskList: "Task list",
177
+ more: "More",
178
+ codeBlock: "Code block",
179
+ hr: "Divider",
180
+ tableInsert: "Insert table",
181
+ tableAddColumnBefore: "Add column before",
182
+ tableAddColumnAfter: "Add column after",
183
+ tableDeleteColumn: "Delete column",
184
+ tableAddRowBefore: "Add row before",
185
+ tableAddRowAfter: "Add row after",
186
+ tableDeleteRow: "Delete row"
187
+ };
188
+ const defaultColorPaletteLabels = {
189
+ none: "None",
190
+ theme: "THEME"
191
+ };
192
+ const defaultTocLabels = {
193
+ title: "Contents",
194
+ expand: "Expand",
195
+ collapse: "Collapse"
196
+ };
197
+ const defaultCodeBlockLabels = {
198
+ autoDetect: "Auto-detect",
199
+ delete: "Delete code block"
200
+ };
201
+ const wrapper = "_wrapper_6ikds_2";
202
+ const header$1 = "_header_6ikds_18";
203
+ const langSelect = "_langSelect_6ikds_28";
204
+ const deleteBtn = "_deleteBtn_6ikds_52";
205
+ const pre = "_pre_6ikds_72";
206
+ const styles$3 = {
207
+ wrapper,
208
+ header: header$1,
209
+ langSelect,
210
+ deleteBtn,
211
+ pre
212
+ };
213
+ const LANGUAGES = [
214
+ { value: "", label: "Auto-detect" },
215
+ { value: "javascript", label: "JavaScript" },
216
+ { value: "typescript", label: "TypeScript" },
217
+ { value: "python", label: "Python" },
218
+ { value: "java", label: "Java" },
219
+ { value: "go", label: "Go" },
220
+ { value: "rust", label: "Rust" },
221
+ { value: "c", label: "C" },
222
+ { value: "cpp", label: "C++" },
223
+ { value: "csharp", label: "C#" },
224
+ { value: "sql", label: "SQL" },
225
+ { value: "json", label: "JSON" },
226
+ { value: "yaml", label: "YAML" },
227
+ { value: "bash", label: "Bash" },
228
+ { value: "shell", label: "Shell" },
229
+ { value: "html", label: "HTML" },
230
+ { value: "css", label: "CSS" },
231
+ { value: "markdown", label: "Markdown" }
232
+ ];
233
+ function CodeBlockView({
234
+ node,
235
+ updateAttributes,
236
+ deleteNode,
237
+ extension
238
+ }) {
239
+ var _a;
240
+ const labels = {
241
+ ...defaultCodeBlockLabels,
242
+ ...((_a = extension == null ? void 0 : extension.options) == null ? void 0 : _a.codeBlockLabels) ?? {}
243
+ };
244
+ const language = node.attrs.language || "";
245
+ return /* @__PURE__ */ jsxs(NodeViewWrapper, { className: styles$3.wrapper, children: [
246
+ /* @__PURE__ */ jsxs("div", { className: styles$3.header, contentEditable: false, children: [
247
+ /* @__PURE__ */ jsx(
248
+ "select",
249
+ {
250
+ className: styles$3.langSelect,
251
+ value: language,
252
+ onChange: (e2) => updateAttributes({ language: e2.target.value }),
253
+ onMouseDown: (e2) => e2.stopPropagation(),
254
+ "aria-label": "Code language",
255
+ children: LANGUAGES.map((l) => /* @__PURE__ */ jsx("option", { value: l.value, children: l.value === "" ? labels.autoDetect : l.label }, l.value))
256
+ }
257
+ ),
258
+ /* @__PURE__ */ jsx(
259
+ "button",
260
+ {
261
+ type: "button",
262
+ className: styles$3.deleteBtn,
263
+ title: labels.delete,
264
+ "aria-label": labels.delete,
265
+ onClick: () => deleteNode(),
266
+ children: /* @__PURE__ */ jsx(TrashIcon, {})
267
+ }
268
+ )
269
+ ] }),
270
+ /* @__PURE__ */ jsx("pre", { className: styles$3.pre, children: /* @__PURE__ */ jsx(NodeViewContent, { as: "code" }) })
271
+ ] });
272
+ }
273
+ const CodeBlock = CodeBlockLowlight.extend({
274
+ addOptions() {
275
+ var _a;
276
+ return {
277
+ ...(_a = this.parent) == null ? void 0 : _a.call(this),
278
+ codeBlockLabels: void 0
279
+ };
280
+ },
281
+ addNodeView() {
282
+ return ReactNodeViewRenderer(CodeBlockView);
283
+ },
284
+ addKeyboardShortcuts() {
285
+ return {
286
+ Backspace: () => {
287
+ const { state } = this.editor;
288
+ const { selection } = state;
289
+ const { empty, $anchor } = selection;
290
+ if (empty && $anchor.parent.type.name === this.name && $anchor.parentOffset === 0 && $anchor.parent.content.size > 0) {
291
+ return true;
292
+ }
293
+ if (empty && $anchor.parentOffset === 0) {
294
+ const before = $anchor.before($anchor.depth);
295
+ const prevNode = state.doc.resolve(before).nodeBefore;
296
+ if ((prevNode == null ? void 0 : prevNode.type.name) === this.name) {
297
+ const codeBlockPos = before - prevNode.nodeSize;
298
+ this.editor.chain().setNodeSelection(codeBlockPos).run();
299
+ return true;
300
+ }
301
+ }
302
+ return false;
303
+ }
304
+ };
305
+ }
306
+ });
307
+ const ImageWithConfirmDelete = Image.extend({
308
+ addKeyboardShortcuts() {
309
+ return {
310
+ Backspace: () => {
311
+ const { state } = this.editor;
312
+ const { selection } = state;
313
+ const { empty, $anchor } = selection;
314
+ if (empty) {
315
+ const nodeBefore = $anchor.nodeBefore;
316
+ if ((nodeBefore == null ? void 0 : nodeBefore.type.name) === this.name) {
317
+ const imagePos = $anchor.pos - nodeBefore.nodeSize;
318
+ this.editor.chain().setNodeSelection(imagePos).run();
319
+ return true;
320
+ }
321
+ }
322
+ return false;
323
+ }
324
+ };
325
+ }
326
+ });
327
+ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
328
+ initialMarkdown = "",
329
+ placeholder,
330
+ onEditorReady,
331
+ onTocChange,
332
+ extraExtensions,
333
+ codeBlockLabels,
334
+ className
335
+ }, ref) {
336
+ const editor = useEditor({
337
+ extensions: [
338
+ ...baseExtensions,
339
+ CodeBlock.configure({ lowlight, codeBlockLabels }),
340
+ ImageWithConfirmDelete.configure({ inline: false }),
341
+ Markdown,
342
+ TableOfContents.configure({
343
+ getId: makeTocGetId(),
344
+ onUpdate: (anchors) => {
345
+ onTocChange == null ? void 0 : onTocChange(
346
+ anchors.filter((a) => a.level <= 6).map((a) => ({ id: a.id, level: a.level, text: a.textContent }))
347
+ );
348
+ }
349
+ }),
350
+ ...extraExtensions ?? []
351
+ ],
352
+ content: initialMarkdown,
353
+ contentType: "markdown",
354
+ // Next.js SSR:服务端不立即渲染,避免 hydration 不一致
355
+ immediatelyRender: false,
356
+ editorProps: {
357
+ attributes: {
358
+ class: styles$4.editorContent,
359
+ "data-placeholder": placeholder ?? ""
360
+ }
361
+ }
362
+ });
363
+ useEffect(() => {
364
+ onEditorReady == null ? void 0 : onEditorReady(editor);
365
+ return () => onEditorReady == null ? void 0 : onEditorReady(null);
366
+ }, [editor, onEditorReady]);
367
+ useImperativeHandle(
368
+ ref,
369
+ () => ({
370
+ getMarkdown: () => {
371
+ var _a;
372
+ return ((_a = editor == null ? void 0 : editor.getMarkdown) == null ? void 0 : _a.call(editor)) ?? "";
373
+ },
374
+ getHTML: () => {
375
+ var _a;
376
+ return ((_a = editor == null ? void 0 : editor.getHTML) == null ? void 0 : _a.call(editor)) ?? "";
377
+ },
378
+ getJSON: () => {
379
+ var _a;
380
+ return ((_a = editor == null ? void 0 : editor.getJSON) == null ? void 0 : _a.call(editor)) ?? {};
381
+ },
382
+ getEditor: () => editor ?? null
383
+ }),
384
+ [editor]
385
+ );
386
+ return /* @__PURE__ */ jsx(
387
+ EditorContent,
388
+ {
389
+ editor,
390
+ className: className ? `${styles$4.editorScroll} ${className}` : styles$4.editorScroll
391
+ }
392
+ );
393
+ });
394
+ function MarkdownPreview({ markdown, className }) {
395
+ const editor = useEditor({
396
+ extensions: [...baseExtensions, pureCodeBlock, pureImage, Markdown],
397
+ content: markdown,
398
+ contentType: "markdown",
399
+ editable: false,
400
+ immediatelyRender: false,
401
+ // 关键:内部 ProseMirror DOM 挂与编辑器一字不差的 editorContent class,
402
+ // 所有内容样式都作用在该选择器下,预览才能与编辑/插入后逐像素一致。
403
+ editorProps: {
404
+ attributes: { class: styles$4.editorContent }
405
+ }
406
+ });
407
+ useEffect(() => {
408
+ if (!editor) return;
409
+ editor.commands.setContent(markdown, { contentType: "markdown" });
410
+ }, [editor, markdown]);
411
+ return /* @__PURE__ */ jsx(
412
+ EditorContent,
413
+ {
414
+ editor,
415
+ className: className ?? styles$4.editorScroll
416
+ }
417
+ );
418
+ }
419
+ const toolbar = "_toolbar_i2emf_2";
420
+ const inner = "_inner_i2emf_15";
421
+ const btn = "_btn_i2emf_27";
422
+ const btnActive = "_btnActive_i2emf_50";
423
+ const tableBubble = "_tableBubble_i2emf_66";
424
+ const txtIcon = "_txtIcon_i2emf_78";
425
+ const colorIcon = "_colorIcon_i2emf_86";
426
+ const colorIconGlyph = "_colorIconGlyph_i2emf_94";
427
+ const colorIconBar = "_colorIconBar_i2emf_100";
428
+ const scriptTrigger = "_scriptTrigger_i2emf_107";
429
+ const scriptTriggerGlyph = "_scriptTriggerGlyph_i2emf_127";
430
+ const divider = "_divider_i2emf_135";
431
+ const styleTrigger = "_styleTrigger_i2emf_144";
432
+ const styleTriggerLabel = "_styleTriggerLabel_i2emf_173";
433
+ const styleTriggerCaret = "_styleTriggerCaret_i2emf_181";
434
+ const styleItem = "_styleItem_i2emf_187";
435
+ const styleIcon = "_styleIcon_i2emf_193";
436
+ const scriptGlyph = "_scriptGlyph_i2emf_203";
437
+ const menu = "_menu_i2emf_215";
438
+ const menuItem = "_menuItem_i2emf_226";
439
+ const menuItemSelected = "_menuItemSelected_i2emf_252";
440
+ const popoverContent = "_popoverContent_i2emf_266";
441
+ const styles$2 = {
442
+ toolbar,
443
+ inner,
444
+ btn,
445
+ btnActive,
446
+ tableBubble,
447
+ txtIcon,
448
+ colorIcon,
449
+ colorIconGlyph,
450
+ colorIconBar,
451
+ scriptTrigger,
452
+ scriptTriggerGlyph,
453
+ divider,
454
+ styleTrigger,
455
+ styleTriggerLabel,
456
+ styleTriggerCaret,
457
+ styleItem,
458
+ styleIcon,
459
+ scriptGlyph,
460
+ menu,
461
+ menuItem,
462
+ menuItemSelected,
463
+ popoverContent
464
+ };
465
+ const palette = "_palette_x5lrq_2";
466
+ const noneRow = "_noneRow_x5lrq_11";
467
+ const noneIcon = "_noneIcon_x5lrq_23";
468
+ const noneLabel = "_noneLabel_x5lrq_43";
469
+ const grid = "_grid_x5lrq_48";
470
+ const swatch = "_swatch_x5lrq_54";
471
+ const swatchActive = "_swatchActive_x5lrq_70";
472
+ const themeLabel = "_themeLabel_x5lrq_76";
473
+ const themeRow = "_themeRow_x5lrq_84";
474
+ const styles$1 = {
475
+ palette,
476
+ noneRow,
477
+ noneIcon,
478
+ noneLabel,
479
+ grid,
480
+ swatch,
481
+ swatchActive,
482
+ themeLabel,
483
+ themeRow
484
+ };
485
+ const PALETTE = [
486
+ ["#8b0000", "#ff0000", "#ff9100", "#ffeb00", "#00e000", "#00e5ff", "#4a86e8", "#0000ff", "#9900ff", "#ff00ff"],
487
+ ["#dba0a0", "#e8b4c0", "#f5d9b8", "#f7f0c0", "#cfe8c4", "#bcd9d4", "#c4d4ec", "#cdd4e8", "#d6c4e0", "#e8c4dc"],
488
+ ["#d28a8a", "#dd8c9c", "#eec49a", "#f0e29c", "#a9d4a0", "#94c0bc", "#a0bce4", "#a4b0d8", "#bca0d0", "#d49cc0"],
489
+ ["#cc4444", "#d4506c", "#e89a5c", "#e8d05c", "#7cc06c", "#5ca09c", "#5c90e0", "#6478c8", "#9460c0", "#c45c98"],
490
+ ["#a02020", "#b01030", "#c87410", "#c8a810", "#449030", "#2c706c", "#3060c0", "#1850a0", "#6428a0", "#a02868"],
491
+ ["#5c1010", "#700818", "#7c4808", "#7c6808", "#205818", "#10403c", "#183c78", "#0c3060", "#3c1460", "#601838"]
492
+ ];
493
+ const THEME_COLORS = ["#ff6719", "#ff5500"];
494
+ function ColorPalette({ value, onPick, labels }) {
495
+ const t = { ...defaultColorPaletteLabels, ...labels };
496
+ const current = value == null ? void 0 : value.toLowerCase();
497
+ return /* @__PURE__ */ jsxs("div", { className: styles$1.palette, children: [
498
+ /* @__PURE__ */ jsxs(
499
+ "button",
500
+ {
501
+ type: "button",
502
+ className: styles$1.noneRow,
503
+ onMouseDown: (e2) => e2.preventDefault(),
504
+ onClick: () => onPick(null),
505
+ children: [
506
+ /* @__PURE__ */ jsx("span", { className: styles$1.noneIcon, "aria-hidden": true }),
507
+ /* @__PURE__ */ jsx("span", { className: styles$1.noneLabel, children: t.none })
508
+ ]
509
+ }
510
+ ),
511
+ /* @__PURE__ */ jsx("div", { className: styles$1.grid, children: PALETTE.flat().map((c) => /* @__PURE__ */ jsx(
512
+ "button",
513
+ {
514
+ type: "button",
515
+ className: `${styles$1.swatch} ${current === c.toLowerCase() ? styles$1.swatchActive : ""}`,
516
+ style: { background: c },
517
+ title: c,
518
+ "aria-label": c,
519
+ onMouseDown: (e2) => e2.preventDefault(),
520
+ onClick: () => onPick(c)
521
+ },
522
+ c
523
+ )) }),
524
+ /* @__PURE__ */ jsx("div", { className: styles$1.themeLabel, children: t.theme }),
525
+ /* @__PURE__ */ jsx("div", { className: styles$1.themeRow, children: THEME_COLORS.map((c) => /* @__PURE__ */ jsx(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ className: `${styles$1.swatch} ${current === c.toLowerCase() ? styles$1.swatchActive : ""}`,
530
+ style: { background: c },
531
+ title: c,
532
+ "aria-label": c,
533
+ onMouseDown: (e2) => e2.preventDefault(),
534
+ onClick: () => onPick(c)
535
+ },
536
+ c
537
+ )) })
538
+ ] });
539
+ }
540
+ function ToolbarButton({
541
+ title,
542
+ active: active2,
543
+ disabled,
544
+ onClick,
545
+ children
546
+ }) {
547
+ return /* @__PURE__ */ jsx(
548
+ "button",
549
+ {
550
+ type: "button",
551
+ title,
552
+ "aria-label": title,
553
+ "aria-pressed": active2,
554
+ disabled,
555
+ className: `${styles$2.btn} ${active2 ? styles$2.btnActive : ""}`,
556
+ onMouseDown: (e2) => e2.preventDefault(),
557
+ onClick,
558
+ children
559
+ }
560
+ );
561
+ }
562
+ function Divider() {
563
+ return /* @__PURE__ */ jsx("span", { className: styles$2.divider, "aria-hidden": true });
564
+ }
565
+ const MenuCloseCtx = createContext(() => {
566
+ });
567
+ function MenuPopover({
568
+ trigger,
569
+ children
570
+ }) {
571
+ const [open, setOpen] = useState(false);
572
+ const close = useCallback(() => setOpen(false), []);
573
+ return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
574
+ /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: trigger }),
575
+ /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
576
+ Popover.Content,
577
+ {
578
+ className: styles$2.menu,
579
+ sideOffset: 4,
580
+ align: "start",
581
+ onOpenAutoFocus: (e2) => e2.preventDefault(),
582
+ onCloseAutoFocus: (e2) => e2.preventDefault(),
583
+ children: /* @__PURE__ */ jsx(MenuCloseCtx.Provider, { value: close, children })
584
+ }
585
+ ) })
586
+ ] });
587
+ }
588
+ function MenuItem({
589
+ selected,
590
+ disabled,
591
+ onSelect,
592
+ children
593
+ }) {
594
+ const close = useContext(MenuCloseCtx);
595
+ return /* @__PURE__ */ jsx(
596
+ "button",
597
+ {
598
+ type: "button",
599
+ disabled,
600
+ className: `${styles$2.menuItem} ${selected ? styles$2.menuItemSelected : ""}`,
601
+ onMouseDown: (e2) => e2.preventDefault(),
602
+ onClick: () => {
603
+ onSelect();
604
+ close();
605
+ },
606
+ children
607
+ }
608
+ );
609
+ }
610
+ function ColorPopover({
611
+ title,
612
+ glyph,
613
+ bar,
614
+ value,
615
+ onPick,
616
+ paletteLabels
617
+ }) {
618
+ const [open, setOpen] = useState(false);
619
+ return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
620
+ /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
621
+ "button",
622
+ {
623
+ type: "button",
624
+ className: styles$2.btn,
625
+ title,
626
+ "aria-label": title,
627
+ onMouseDown: (e2) => e2.preventDefault(),
628
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.colorIcon, children: [
629
+ /* @__PURE__ */ jsx("span", { className: styles$2.colorIconGlyph, children: glyph }),
630
+ /* @__PURE__ */ jsx("span", { className: styles$2.colorIconBar, style: { background: bar } })
631
+ ] })
632
+ }
633
+ ) }),
634
+ /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
635
+ Popover.Content,
636
+ {
637
+ className: styles$2.popoverContent,
638
+ sideOffset: 4,
639
+ align: "start",
640
+ onOpenAutoFocus: (e2) => e2.preventDefault(),
641
+ onCloseAutoFocus: (e2) => e2.preventDefault(),
642
+ children: /* @__PURE__ */ jsx(
643
+ ColorPalette,
644
+ {
645
+ value,
646
+ onPick: (c) => {
647
+ onPick(c);
648
+ setOpen(false);
649
+ },
650
+ labels: paletteLabels
651
+ }
652
+ )
653
+ }
654
+ ) })
655
+ ] });
656
+ }
657
+ const HEADING_LEVELS = [1, 2, 3, 4, 5, 6];
658
+ const FONT_SIZES = ["12px", "14px", "16px", "18px", "20px", "24px", "30px"];
659
+ function EditorToolbar({
660
+ editor,
661
+ onImageUpload,
662
+ onError,
663
+ labels,
664
+ extraToolbarItems,
665
+ className
666
+ }) {
667
+ const t = { ...defaultToolbarLabels, ...labels };
668
+ const state = useEditorState({
669
+ editor,
670
+ selector: ({ editor: e2 }) => ({
671
+ bold: e2.isActive("bold"),
672
+ italic: e2.isActive("italic"),
673
+ underline: e2.isActive("underline"),
674
+ strike: e2.isActive("strike"),
675
+ code: e2.isActive("code"),
676
+ link: e2.isActive("link"),
677
+ taskList: e2.isActive("taskList"),
678
+ headingLevel: [1, 2, 3, 4, 5, 6].find(
679
+ (lv) => e2.isActive("heading", { level: lv })
680
+ ),
681
+ fontSize: e2.getAttributes("textStyle").fontSize || void 0,
682
+ isParagraph: e2.isActive("paragraph"),
683
+ bulletList: e2.isActive("bulletList"),
684
+ orderedList: e2.isActive("orderedList"),
685
+ blockquote: e2.isActive("blockquote"),
686
+ textColor: e2.getAttributes("textStyle").color || void 0,
687
+ highlightColor: e2.getAttributes("highlight").color || void 0,
688
+ superscript: e2.isActive("superscript"),
689
+ subscript: e2.isActive("subscript"),
690
+ inTable: e2.isActive("table"),
691
+ inTableHeader: e2.isActive("tableHeader"),
692
+ canUndo: e2.can().undo(),
693
+ canRedo: e2.can().redo()
694
+ })
695
+ });
696
+ const [editorFocused, setEditorFocused] = useState(() => editor.isFocused);
697
+ useEffect(() => {
698
+ const onFocus = () => setEditorFocused(true);
699
+ const onBlur = () => setEditorFocused(false);
700
+ editor.on("focus", onFocus);
701
+ editor.on("blur", onBlur);
702
+ return () => {
703
+ editor.off("focus", onFocus);
704
+ editor.off("blur", onBlur);
705
+ };
706
+ }, [editor]);
707
+ const fileInputRef = useRef(null);
708
+ const chain = () => editor.chain().focus();
709
+ const [tableMenu, setTableMenu] = useState(
710
+ null
711
+ );
712
+ const closeTableMenu = useCallback(() => setTableMenu(null), []);
713
+ useEffect(() => {
714
+ const dom = editor.view.dom;
715
+ const onContextMenu = (e2) => {
716
+ const coords = editor.view.posAtCoords({
717
+ left: e2.clientX,
718
+ top: e2.clientY
719
+ });
720
+ if (!coords) return;
721
+ const $pos = editor.state.doc.resolve(coords.pos);
722
+ let inTable = false;
723
+ for (let d = $pos.depth; d > 0; d--) {
724
+ if ($pos.node(d).type.name === "table") {
725
+ inTable = true;
726
+ break;
727
+ }
728
+ }
729
+ if (!inTable) return;
730
+ e2.preventDefault();
731
+ editor.chain().focus().setTextSelection(coords.pos).run();
732
+ setTableMenu({ x: e2.clientX, y: e2.clientY });
733
+ };
734
+ dom.addEventListener("contextmenu", onContextMenu);
735
+ return () => dom.removeEventListener("contextmenu", onContextMenu);
736
+ }, [editor]);
737
+ useEffect(() => {
738
+ if (!tableMenu) return;
739
+ const onKey = (e2) => {
740
+ if (e2.key === "Escape") closeTableMenu();
741
+ };
742
+ document.addEventListener("mousedown", closeTableMenu);
743
+ document.addEventListener("keydown", onKey, true);
744
+ return () => {
745
+ document.removeEventListener("mousedown", closeTableMenu);
746
+ document.removeEventListener("keydown", onKey, true);
747
+ };
748
+ }, [tableMenu, closeTableMenu]);
749
+ const runTable = useCallback(
750
+ (fn) => {
751
+ fn();
752
+ closeTableMenu();
753
+ },
754
+ [closeTableMenu]
755
+ );
756
+ const handlePickImage = () => {
757
+ var _a;
758
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
759
+ };
760
+ const handleImageChange = async (e2) => {
761
+ var _a;
762
+ const file = (_a = e2.target.files) == null ? void 0 : _a[0];
763
+ e2.target.value = "";
764
+ if (!file || !onImageUpload) return;
765
+ try {
766
+ const url = await onImageUpload(file);
767
+ if (!url) throw new Error("empty url");
768
+ chain().setImage({ src: url }).run();
769
+ } catch (err) {
770
+ console.error("image upload failed:", err);
771
+ onError == null ? void 0 : onError(err);
772
+ }
773
+ };
774
+ const applyTextColor = (color) => {
775
+ if (color) chain().setColor(color).run();
776
+ else chain().unsetColor().run();
777
+ };
778
+ const applyHighlight = (color) => {
779
+ if (color) chain().setHighlight({ color }).run();
780
+ else chain().unsetHighlight().run();
781
+ };
782
+ const toggleLink = () => {
783
+ if (state.link) {
784
+ chain().unsetLink().run();
785
+ return;
786
+ }
787
+ const url = window.prompt(t.linkPrompt);
788
+ if (url) chain().setLink({ href: url }).run();
789
+ };
790
+ const setBlockStyle = (level) => {
791
+ if (level === 0) chain().setParagraph().run();
792
+ else
793
+ chain().toggleHeading({ level }).run();
794
+ };
795
+ const applyFontSize = (size) => {
796
+ if (size) chain().setFontSize(size).run();
797
+ else chain().unsetFontSize().run();
798
+ };
799
+ const canEditFontSize = editorFocused && state.isParagraph;
800
+ const scriptActive = state.superscript ? "superscript" : state.subscript ? "subscript" : "normal";
801
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
802
+ /* @__PURE__ */ jsx(
803
+ "div",
804
+ {
805
+ className: className ? `${styles$2.toolbar} ${className}` : styles$2.toolbar,
806
+ children: /* @__PURE__ */ jsxs("div", { className: styles$2.inner, children: [
807
+ /* @__PURE__ */ jsx(
808
+ ToolbarButton,
809
+ {
810
+ title: t.undo,
811
+ disabled: !state.canUndo,
812
+ onClick: () => chain().undo().run(),
813
+ children: /* @__PURE__ */ jsx(UndoIcon, {})
814
+ }
815
+ ),
816
+ /* @__PURE__ */ jsx(
817
+ ToolbarButton,
818
+ {
819
+ title: t.redo,
820
+ disabled: !state.canRedo,
821
+ onClick: () => chain().redo().run(),
822
+ children: /* @__PURE__ */ jsx(RedoIcon, {})
823
+ }
824
+ ),
825
+ /* @__PURE__ */ jsx(Divider, {}),
826
+ /* @__PURE__ */ jsxs(
827
+ MenuPopover,
828
+ {
829
+ trigger: /* @__PURE__ */ jsxs(
830
+ "button",
831
+ {
832
+ type: "button",
833
+ className: styles$2.styleTrigger,
834
+ title: t.style,
835
+ onMouseDown: (e2) => e2.preventDefault(),
836
+ children: [
837
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleTriggerLabel, children: t.style }),
838
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$2.styleTriggerCaret })
839
+ ]
840
+ }
841
+ ),
842
+ children: [
843
+ /* @__PURE__ */ jsx(
844
+ MenuItem,
845
+ {
846
+ selected: (state.headingLevel ?? 0) === 0,
847
+ onSelect: () => setBlockStyle(0),
848
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
849
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: "¶" }),
850
+ t.normalText
851
+ ] })
852
+ }
853
+ ),
854
+ HEADING_LEVELS.map((lv) => /* @__PURE__ */ jsx(
855
+ MenuItem,
856
+ {
857
+ selected: state.headingLevel === lv,
858
+ onSelect: () => setBlockStyle(lv),
859
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
860
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: `H${lv}` }),
861
+ t.headingLabel(lv)
862
+ ] })
863
+ },
864
+ lv
865
+ ))
866
+ ]
867
+ }
868
+ ),
869
+ /* @__PURE__ */ jsxs(
870
+ MenuPopover,
871
+ {
872
+ trigger: /* @__PURE__ */ jsxs(
873
+ "button",
874
+ {
875
+ type: "button",
876
+ className: styles$2.styleTrigger,
877
+ title: t.fontSize,
878
+ "aria-label": t.fontSize,
879
+ disabled: !canEditFontSize,
880
+ onMouseDown: (e2) => e2.preventDefault(),
881
+ children: [
882
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleTriggerLabel, children: state.fontSize || "Size" }),
883
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$2.styleTriggerCaret })
884
+ ]
885
+ }
886
+ ),
887
+ children: [
888
+ /* @__PURE__ */ jsx(
889
+ MenuItem,
890
+ {
891
+ selected: !state.fontSize,
892
+ onSelect: () => applyFontSize(""),
893
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
894
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: "A" }),
895
+ t.fontSizeDefault
896
+ ] })
897
+ }
898
+ ),
899
+ FONT_SIZES.map((size) => /* @__PURE__ */ jsx(
900
+ MenuItem,
901
+ {
902
+ selected: state.fontSize === size,
903
+ onSelect: () => applyFontSize(size),
904
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
905
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: parseInt(size, 10) }),
906
+ size
907
+ ] })
908
+ },
909
+ size
910
+ ))
911
+ ]
912
+ }
913
+ ),
914
+ /* @__PURE__ */ jsx(Divider, {}),
915
+ /* @__PURE__ */ jsx(
916
+ ToolbarButton,
917
+ {
918
+ title: t.bold,
919
+ active: state.bold,
920
+ onClick: () => chain().toggleBold().run(),
921
+ children: /* @__PURE__ */ jsx(BoldIcon, {})
922
+ }
923
+ ),
924
+ /* @__PURE__ */ jsx(
925
+ ToolbarButton,
926
+ {
927
+ title: t.italic,
928
+ active: state.italic,
929
+ onClick: () => chain().toggleItalic().run(),
930
+ children: /* @__PURE__ */ jsx(ItalicIcon, {})
931
+ }
932
+ ),
933
+ /* @__PURE__ */ jsx(
934
+ ToolbarButton,
935
+ {
936
+ title: t.underline,
937
+ active: state.underline,
938
+ onClick: () => chain().toggleUnderline().run(),
939
+ children: /* @__PURE__ */ jsx(UnderlineIcon, {})
940
+ }
941
+ ),
942
+ /* @__PURE__ */ jsx(
943
+ ToolbarButton,
944
+ {
945
+ title: t.strike,
946
+ active: state.strike,
947
+ onClick: () => chain().toggleStrike().run(),
948
+ children: /* @__PURE__ */ jsx(StrikethroughIcon, {})
949
+ }
950
+ ),
951
+ /* @__PURE__ */ jsx(
952
+ ToolbarButton,
953
+ {
954
+ title: t.code,
955
+ active: state.code,
956
+ onClick: () => chain().toggleCode().run(),
957
+ children: /* @__PURE__ */ jsx(CodeIcon, {})
958
+ }
959
+ ),
960
+ /* @__PURE__ */ jsx(
961
+ ColorPopover,
962
+ {
963
+ title: t.textColor,
964
+ glyph: "T",
965
+ bar: state.textColor || "#ff3b30",
966
+ value: state.textColor,
967
+ onPick: applyTextColor,
968
+ paletteLabels: { none: t.colorNone, theme: t.colorTheme }
969
+ }
970
+ ),
971
+ /* @__PURE__ */ jsx(
972
+ ColorPopover,
973
+ {
974
+ title: t.highlight,
975
+ glyph: "✎",
976
+ bar: state.highlightColor || "#ffd83d",
977
+ value: state.highlightColor,
978
+ onPick: applyHighlight,
979
+ paletteLabels: { none: t.colorNone, theme: t.colorTheme }
980
+ }
981
+ ),
982
+ /* @__PURE__ */ jsxs(
983
+ MenuPopover,
984
+ {
985
+ trigger: /* @__PURE__ */ jsxs(
986
+ "button",
987
+ {
988
+ type: "button",
989
+ className: `${styles$2.scriptTrigger} ${scriptActive !== "normal" ? styles$2.btnActive : ""}`,
990
+ title: t.scriptMenu,
991
+ "aria-label": t.scriptMenu,
992
+ onMouseDown: (e2) => e2.preventDefault(),
993
+ children: [
994
+ /* @__PURE__ */ jsx("span", { className: styles$2.scriptTriggerGlyph, children: "A" }),
995
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$2.styleTriggerCaret })
996
+ ]
997
+ }
998
+ ),
999
+ children: [
1000
+ /* @__PURE__ */ jsx(
1001
+ MenuItem,
1002
+ {
1003
+ selected: scriptActive === "normal",
1004
+ onSelect: () => chain().unsetSuperscript().unsetSubscript().run(),
1005
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
1006
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: "A" }),
1007
+ t.scriptNormal
1008
+ ] })
1009
+ }
1010
+ ),
1011
+ /* @__PURE__ */ jsx(
1012
+ MenuItem,
1013
+ {
1014
+ selected: scriptActive === "superscript",
1015
+ onSelect: () => chain().unsetSubscript().toggleSuperscript().run(),
1016
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
1017
+ /* @__PURE__ */ jsxs("span", { className: `${styles$2.styleIcon} ${styles$2.scriptGlyph}`, children: [
1018
+ "x",
1019
+ /* @__PURE__ */ jsx("sup", { children: "2" })
1020
+ ] }),
1021
+ t.superscript
1022
+ ] })
1023
+ }
1024
+ ),
1025
+ /* @__PURE__ */ jsx(
1026
+ MenuItem,
1027
+ {
1028
+ selected: scriptActive === "subscript",
1029
+ onSelect: () => chain().unsetSuperscript().toggleSubscript().run(),
1030
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
1031
+ /* @__PURE__ */ jsxs("span", { className: `${styles$2.styleIcon} ${styles$2.scriptGlyph}`, children: [
1032
+ "x",
1033
+ /* @__PURE__ */ jsx("sub", { children: "2" })
1034
+ ] }),
1035
+ t.subscript
1036
+ ] })
1037
+ }
1038
+ )
1039
+ ]
1040
+ }
1041
+ ),
1042
+ /* @__PURE__ */ jsx(Divider, {}),
1043
+ /* @__PURE__ */ jsx(ToolbarButton, { title: t.link, active: state.link, onClick: toggleLink, children: /* @__PURE__ */ jsx(LinkIcon, {}) }),
1044
+ onImageUpload ? /* @__PURE__ */ jsxs(Fragment, { children: [
1045
+ /* @__PURE__ */ jsx(ToolbarButton, { title: t.image, onClick: handlePickImage, children: /* @__PURE__ */ jsx(ImageIcon, {}) }),
1046
+ /* @__PURE__ */ jsx(
1047
+ "input",
1048
+ {
1049
+ ref: fileInputRef,
1050
+ type: "file",
1051
+ accept: "image/*",
1052
+ hidden: true,
1053
+ onChange: handleImageChange
1054
+ }
1055
+ )
1056
+ ] }) : null,
1057
+ /* @__PURE__ */ jsx(
1058
+ ToolbarButton,
1059
+ {
1060
+ title: t.blockquote,
1061
+ active: state.blockquote,
1062
+ onClick: () => chain().toggleBlockquote().run(),
1063
+ children: /* @__PURE__ */ jsx("span", { className: styles$2.txtIcon, children: "❝" })
1064
+ }
1065
+ ),
1066
+ /* @__PURE__ */ jsx(Divider, {}),
1067
+ /* @__PURE__ */ jsx(
1068
+ ToolbarButton,
1069
+ {
1070
+ title: t.bulletList,
1071
+ active: state.bulletList,
1072
+ onClick: () => chain().toggleBulletList().run(),
1073
+ children: /* @__PURE__ */ jsx(ListUnorderedIcon, {})
1074
+ }
1075
+ ),
1076
+ /* @__PURE__ */ jsx(
1077
+ ToolbarButton,
1078
+ {
1079
+ title: t.orderedList,
1080
+ active: state.orderedList,
1081
+ onClick: () => chain().toggleOrderedList().run(),
1082
+ children: /* @__PURE__ */ jsx(ListOrderedIcon, {})
1083
+ }
1084
+ ),
1085
+ /* @__PURE__ */ jsx(
1086
+ ToolbarButton,
1087
+ {
1088
+ title: t.taskList,
1089
+ active: state.taskList,
1090
+ onClick: () => chain().toggleTaskList().run(),
1091
+ children: /* @__PURE__ */ jsx(ListChecksIcon, {})
1092
+ }
1093
+ ),
1094
+ /* @__PURE__ */ jsx(Divider, {}),
1095
+ /* @__PURE__ */ jsxs(
1096
+ MenuPopover,
1097
+ {
1098
+ trigger: /* @__PURE__ */ jsxs(
1099
+ "button",
1100
+ {
1101
+ type: "button",
1102
+ className: styles$2.styleTrigger,
1103
+ title: t.more,
1104
+ onMouseDown: (e2) => e2.preventDefault(),
1105
+ children: [
1106
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleTriggerLabel, children: t.more }),
1107
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: styles$2.styleTriggerCaret })
1108
+ ]
1109
+ }
1110
+ ),
1111
+ children: [
1112
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().toggleCodeBlock().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
1113
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: "{ }" }),
1114
+ t.codeBlock
1115
+ ] }) }),
1116
+ /* @__PURE__ */ jsx(MenuItem, { onSelect: () => chain().setHorizontalRule().run(), children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
1117
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: "—" }),
1118
+ t.hr
1119
+ ] }) }),
1120
+ /* @__PURE__ */ jsx(
1121
+ MenuItem,
1122
+ {
1123
+ disabled: state.inTable,
1124
+ onSelect: () => chain().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run(),
1125
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
1126
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: "⊞" }),
1127
+ t.tableInsert
1128
+ ] })
1129
+ }
1130
+ ),
1131
+ extraToolbarItems == null ? void 0 : extraToolbarItems.map((item2) => /* @__PURE__ */ jsx(
1132
+ MenuItem,
1133
+ {
1134
+ disabled: item2.disabled,
1135
+ onSelect: () => item2.onSelect(editor),
1136
+ children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
1137
+ /* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: item2.icon }),
1138
+ item2.label
1139
+ ] })
1140
+ },
1141
+ item2.key
1142
+ ))
1143
+ ]
1144
+ }
1145
+ )
1146
+ ] })
1147
+ }
1148
+ ),
1149
+ tableMenu && createPortal(
1150
+ /* @__PURE__ */ jsxs(
1151
+ "div",
1152
+ {
1153
+ className: styles$2.tableBubble,
1154
+ style: { position: "fixed", left: tableMenu.x, top: tableMenu.y },
1155
+ onMouseDown: (e2) => e2.stopPropagation(),
1156
+ onContextMenu: (e2) => e2.preventDefault(),
1157
+ children: [
1158
+ /* @__PURE__ */ jsx(
1159
+ ToolbarButton,
1160
+ {
1161
+ title: t.tableAddColumnBefore,
1162
+ onClick: () => runTable(() => chain().addColumnBefore().run()),
1163
+ children: /* @__PURE__ */ jsx(ColumnBeforeIcon, {})
1164
+ }
1165
+ ),
1166
+ /* @__PURE__ */ jsx(
1167
+ ToolbarButton,
1168
+ {
1169
+ title: t.tableAddColumnAfter,
1170
+ onClick: () => runTable(() => chain().addColumnAfter().run()),
1171
+ children: /* @__PURE__ */ jsx(ColumnAfterIcon, {})
1172
+ }
1173
+ ),
1174
+ /* @__PURE__ */ jsx(
1175
+ ToolbarButton,
1176
+ {
1177
+ title: t.tableDeleteColumn,
1178
+ onClick: () => runTable(() => chain().deleteColumn().run()),
1179
+ children: /* @__PURE__ */ jsx(ColumnDeleteIcon, {})
1180
+ }
1181
+ ),
1182
+ /* @__PURE__ */ jsx(Divider, {}),
1183
+ /* @__PURE__ */ jsx(
1184
+ ToolbarButton,
1185
+ {
1186
+ title: t.tableAddRowBefore,
1187
+ disabled: state.inTableHeader,
1188
+ onClick: () => runTable(() => chain().addRowBefore().run()),
1189
+ children: /* @__PURE__ */ jsx(RowBeforeIcon, {})
1190
+ }
1191
+ ),
1192
+ /* @__PURE__ */ jsx(
1193
+ ToolbarButton,
1194
+ {
1195
+ title: t.tableAddRowAfter,
1196
+ onClick: () => runTable(() => chain().addRowAfter().run()),
1197
+ children: /* @__PURE__ */ jsx(RowAfterIcon, {})
1198
+ }
1199
+ ),
1200
+ /* @__PURE__ */ jsx(
1201
+ ToolbarButton,
1202
+ {
1203
+ title: t.tableDeleteRow,
1204
+ disabled: state.inTableHeader,
1205
+ onClick: () => runTable(() => chain().deleteRow().run()),
1206
+ children: /* @__PURE__ */ jsx(RowDeleteIcon, {})
1207
+ }
1208
+ )
1209
+ ]
1210
+ }
1211
+ ),
1212
+ document.body
1213
+ )
1214
+ ] });
1215
+ }
1216
+ function useIsMobile(breakpoint = 768) {
1217
+ const [isMobile, setIsMobile] = useState(false);
1218
+ useEffect(() => {
1219
+ const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
1220
+ const update = () => setIsMobile(mq.matches);
1221
+ update();
1222
+ mq.addEventListener("change", update);
1223
+ return () => mq.removeEventListener("change", update);
1224
+ }, [breakpoint]);
1225
+ return isMobile;
1226
+ }
1227
+ const desktop = "_desktop_euqdt_3";
1228
+ const header = "_header_euqdt_19";
1229
+ const headerTitle = "_headerTitle_euqdt_27";
1230
+ const collapseBtn = "_collapseBtn_euqdt_35";
1231
+ const collapsedRail = "_collapsedRail_euqdt_55";
1232
+ const list = "_list_euqdt_75";
1233
+ const item = "_item_euqdt_81";
1234
+ const itemText = "_itemText_euqdt_102";
1235
+ const active = "_active_euqdt_109";
1236
+ const locked = "_locked_euqdt_116";
1237
+ const lockIcon = "_lockIcon_euqdt_126";
1238
+ const mobile = "_mobile_euqdt_133";
1239
+ const mobileBar = "_mobileBar_euqdt_138";
1240
+ const mobileBarIcon = "_mobileBarIcon_euqdt_154";
1241
+ const chevron = "_chevron_euqdt_159";
1242
+ const chevronUp = "_chevronUp_euqdt_166";
1243
+ const mobilePanel = "_mobilePanel_euqdt_170";
1244
+ const mobilePanelOpen = "_mobilePanelOpen_euqdt_176";
1245
+ const styles = {
1246
+ desktop,
1247
+ header,
1248
+ headerTitle,
1249
+ collapseBtn,
1250
+ collapsedRail,
1251
+ list,
1252
+ item,
1253
+ itemText,
1254
+ active,
1255
+ locked,
1256
+ lockIcon,
1257
+ mobile,
1258
+ mobileBar,
1259
+ mobileBarIcon,
1260
+ chevron,
1261
+ chevronUp,
1262
+ mobilePanel,
1263
+ mobilePanelOpen
1264
+ };
1265
+ function TocPanel({ items, activeId, onItemClick, labels }) {
1266
+ const t = { ...defaultTocLabels, ...labels };
1267
+ const isMobile = useIsMobile();
1268
+ const [collapsed, setCollapsed] = useState(false);
1269
+ const [mobileOpen, setMobileOpen] = useState(false);
1270
+ const desktopNavRef = useRef(null);
1271
+ const mobilePanelRef = useRef(null);
1272
+ useEffect(() => {
1273
+ if (!activeId) return;
1274
+ const reduce = window.matchMedia(
1275
+ "(prefers-reduced-motion: reduce)"
1276
+ ).matches;
1277
+ const container = desktopNavRef.current || mobilePanelRef.current;
1278
+ if (!container) return;
1279
+ const el = container.querySelector(`a[href="#${CSS.escape(activeId)}"]`);
1280
+ if (!el) return;
1281
+ el.scrollIntoView({
1282
+ block: "nearest",
1283
+ behavior: reduce ? "auto" : "smooth"
1284
+ });
1285
+ }, [activeId]);
1286
+ if (!items.length) return null;
1287
+ const minLevel = Math.min(...items.map((i) => i.level));
1288
+ const handleClick = (item2) => {
1289
+ if (item2.locked) return;
1290
+ onItemClick == null ? void 0 : onItemClick(item2);
1291
+ if (isMobile) setMobileOpen(false);
1292
+ };
1293
+ const list2 = /* @__PURE__ */ jsx("ul", { className: styles.list, children: items.map((item2) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
1294
+ "a",
1295
+ {
1296
+ href: item2.locked ? void 0 : `#${item2.id}`,
1297
+ className: `${styles.item} ${item2.id === activeId ? styles.active : ""} ${item2.locked ? styles.locked : ""}`,
1298
+ style: { paddingLeft: `${(item2.level - minLevel) * 12 + 12}px` },
1299
+ "aria-current": item2.id === activeId ? "true" : void 0,
1300
+ "aria-disabled": item2.locked ? "true" : void 0,
1301
+ onClick: (e2) => {
1302
+ e2.preventDefault();
1303
+ handleClick(item2);
1304
+ },
1305
+ children: [
1306
+ /* @__PURE__ */ jsx("span", { className: styles.itemText, children: item2.text }),
1307
+ item2.locked ? /* @__PURE__ */ jsx(LockIcon, { className: styles.lockIcon, "aria-hidden": true }) : null
1308
+ ]
1309
+ }
1310
+ ) }, item2.id)) });
1311
+ if (isMobile) {
1312
+ return /* @__PURE__ */ jsxs("nav", { className: styles.mobile, "aria-label": t.title, children: [
1313
+ /* @__PURE__ */ jsxs(
1314
+ "button",
1315
+ {
1316
+ type: "button",
1317
+ className: styles.mobileBar,
1318
+ "aria-expanded": mobileOpen,
1319
+ onClick: () => setMobileOpen((v) => !v),
1320
+ children: [
1321
+ /* @__PURE__ */ jsx(MenuIcon, { className: styles.mobileBarIcon, "aria-hidden": true }),
1322
+ /* @__PURE__ */ jsx("span", { children: t.title }),
1323
+ /* @__PURE__ */ jsx(
1324
+ "span",
1325
+ {
1326
+ className: `${styles.chevron} ${mobileOpen ? styles.chevronUp : ""}`,
1327
+ "aria-hidden": true,
1328
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 16 })
1329
+ }
1330
+ )
1331
+ ]
1332
+ }
1333
+ ),
1334
+ /* @__PURE__ */ jsx(
1335
+ "div",
1336
+ {
1337
+ ref: mobilePanelRef,
1338
+ className: `${styles.mobilePanel} ${mobileOpen ? styles.mobilePanelOpen : ""}`,
1339
+ children: list2
1340
+ }
1341
+ )
1342
+ ] });
1343
+ }
1344
+ if (collapsed) {
1345
+ return /* @__PURE__ */ jsx(
1346
+ "button",
1347
+ {
1348
+ type: "button",
1349
+ className: styles.collapsedRail,
1350
+ "aria-label": t.expand,
1351
+ title: t.expand,
1352
+ onClick: () => setCollapsed(false),
1353
+ children: /* @__PURE__ */ jsx(ListUnorderedIcon, {})
1354
+ }
1355
+ );
1356
+ }
1357
+ return /* @__PURE__ */ jsxs("nav", { className: styles.desktop, "aria-label": t.title, ref: desktopNavRef, children: [
1358
+ /* @__PURE__ */ jsxs("div", { className: styles.header, children: [
1359
+ /* @__PURE__ */ jsx("span", { className: styles.headerTitle, children: t.title }),
1360
+ /* @__PURE__ */ jsx(
1361
+ "button",
1362
+ {
1363
+ type: "button",
1364
+ className: styles.collapseBtn,
1365
+ "aria-label": t.collapse,
1366
+ title: t.collapse,
1367
+ onClick: () => setCollapsed(true),
1368
+ children: "«"
1369
+ }
1370
+ )
1371
+ ] }),
1372
+ list2
1373
+ ] });
1374
+ }
1375
+ export {
1376
+ BoldIcon,
1377
+ ChevronDownIcon,
1378
+ CodeBlockView,
1379
+ CodeIcon,
1380
+ ColorPalette,
1381
+ ColumnAfterIcon,
1382
+ ColumnBeforeIcon,
1383
+ ColumnDeleteIcon,
1384
+ EditorToolbar,
1385
+ ImageIcon,
1386
+ ItalicIcon,
1387
+ LinkIcon,
1388
+ ListChecksIcon,
1389
+ ListOrderedIcon,
1390
+ ListUnorderedIcon,
1391
+ LockIcon,
1392
+ MarkdownPreview,
1393
+ MarkdownWysiwygEditor,
1394
+ MenuIcon,
1395
+ RedoIcon,
1396
+ R as ReportContent,
1397
+ RowAfterIcon,
1398
+ RowBeforeIcon,
1399
+ RowDeleteIcon,
1400
+ StrikethroughIcon,
1401
+ TocPanel,
1402
+ TrashIcon,
1403
+ UnderlineIcon,
1404
+ UndoIcon,
1405
+ baseExtensions,
1406
+ defaultCodeBlockLabels,
1407
+ defaultColorPaletteLabels,
1408
+ defaultTocLabels,
1409
+ defaultToolbarLabels,
1410
+ e as extractToc,
1411
+ lowlight,
1412
+ makeTocGetId,
1413
+ pureCodeBlock,
1414
+ pureImage,
1415
+ useIsMobile
1416
+ };
1417
+ //# sourceMappingURL=index.js.map