neuphlo-editor 2.5.0 → 2.5.1

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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/dist/highlight.css +83 -1
  3. package/package.json +9 -11
  4. package/dist/chunk-2DWEJI45.js +0 -1296
  5. package/dist/chunk-2DWEJI45.js.map +0 -1
  6. package/dist/chunk-3CLWAYRP.js +0 -1387
  7. package/dist/chunk-3CLWAYRP.js.map +0 -1
  8. package/dist/chunk-457ETWB6.js +0 -1351
  9. package/dist/chunk-457ETWB6.js.map +0 -1
  10. package/dist/chunk-4L7FHW5M.js +0 -1388
  11. package/dist/chunk-4L7FHW5M.js.map +0 -1
  12. package/dist/chunk-4MV3UUZN.js +0 -1073
  13. package/dist/chunk-4MV3UUZN.js.map +0 -1
  14. package/dist/chunk-62DYB7FY.js +0 -1305
  15. package/dist/chunk-62DYB7FY.js.map +0 -1
  16. package/dist/chunk-BVFTQKY7.js +0 -1387
  17. package/dist/chunk-BVFTQKY7.js.map +0 -1
  18. package/dist/chunk-DWGPGRTQ.js +0 -1302
  19. package/dist/chunk-DWGPGRTQ.js.map +0 -1
  20. package/dist/chunk-EG7NQJRA.js +0 -1324
  21. package/dist/chunk-EG7NQJRA.js.map +0 -1
  22. package/dist/chunk-FLLPFFI5.js +0 -1296
  23. package/dist/chunk-FLLPFFI5.js.map +0 -1
  24. package/dist/chunk-FVQHB6VC.js +0 -1128
  25. package/dist/chunk-FVQHB6VC.js.map +0 -1
  26. package/dist/chunk-G5E32MLB.js +0 -1352
  27. package/dist/chunk-G5E32MLB.js.map +0 -1
  28. package/dist/chunk-GXJGZHKR.js +0 -1326
  29. package/dist/chunk-GXJGZHKR.js.map +0 -1
  30. package/dist/chunk-KCPPTLGY.js +0 -1299
  31. package/dist/chunk-KCPPTLGY.js.map +0 -1
  32. package/dist/chunk-LHG2NX6C.js +0 -1123
  33. package/dist/chunk-LHG2NX6C.js.map +0 -1
  34. package/dist/chunk-MSNTVITF.js +0 -1352
  35. package/dist/chunk-MSNTVITF.js.map +0 -1
  36. package/dist/chunk-N4RDYJ5Z.js +0 -1351
  37. package/dist/chunk-N4RDYJ5Z.js.map +0 -1
  38. package/dist/chunk-OCNM37WJ.js +0 -1289
  39. package/dist/chunk-OCNM37WJ.js.map +0 -1
  40. package/dist/chunk-P3YFYEUB.js +0 -1351
  41. package/dist/chunk-P3YFYEUB.js.map +0 -1
  42. package/dist/chunk-RW6QBMJB.js +0 -1300
  43. package/dist/chunk-RW6QBMJB.js.map +0 -1
  44. package/dist/chunk-SJQQVB3M.js +0 -1353
  45. package/dist/chunk-SJQQVB3M.js.map +0 -1
  46. package/dist/chunk-SOXTEP7H.js +0 -6705
  47. package/dist/chunk-SOXTEP7H.js.map +0 -1
  48. package/dist/chunk-VPI26I4P.js +0 -1350
  49. package/dist/chunk-VPI26I4P.js.map +0 -1
@@ -1,1300 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all2) => {
6
- for (var name in all2)
7
- __defProp(target, name, { get: all2[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
18
-
19
- // src/headless/index.ts
20
- import { useCurrentEditor as useCurrentEditor4 } from "@tiptap/react";
21
-
22
- // src/headless/components/editor.tsx
23
- import { EditorProvider } from "@tiptap/react";
24
- import { forwardRef } from "react";
25
- import { Provider } from "jotai";
26
-
27
- // src/headless/utils/store.ts
28
- var store_exports = {};
29
- __export(store_exports, {
30
- novelStore: () => novelStore
31
- });
32
- __reExport(store_exports, jotai_star);
33
- import { createStore } from "jotai";
34
- import * as jotai_star from "jotai";
35
- var novelStore = createStore();
36
-
37
- // src/headless/components/editor.tsx
38
- import { jsx } from "react/jsx-runtime";
39
- var EditorRoot = ({ children }) => {
40
- return /* @__PURE__ */ jsx(Provider, { store: novelStore, children });
41
- };
42
- var EditorContent = forwardRef(
43
- ({ className, children, initialContent, content, ...rest }, ref) => {
44
- const effectiveContent = content ?? initialContent;
45
- return /* @__PURE__ */ jsx("div", { ref, className, children: /* @__PURE__ */ jsx(EditorProvider, { ...rest, content: effectiveContent, children }) });
46
- }
47
- );
48
- EditorContent.displayName = "EditorContent";
49
-
50
- // src/headless/components/editor-bubble.tsx
51
- import { useCurrentEditor } from "@tiptap/react";
52
- import { BubbleMenu as BubbleMenuReact } from "@tiptap/react/menus";
53
- import { jsx as jsx2 } from "react/jsx-runtime";
54
- function EditorBubble({ className, children, ...rest }) {
55
- const { editor } = useCurrentEditor();
56
- if (!editor) return null;
57
- return /* @__PURE__ */ jsx2(BubbleMenuReact, { editor, ...rest, children: /* @__PURE__ */ jsx2("div", { className, children }) });
58
- }
59
-
60
- // src/headless/components/editor-bubble-item.tsx
61
- import { forwardRef as forwardRef2, isValidElement, cloneElement } from "react";
62
- import { useCurrentEditor as useCurrentEditor2 } from "@tiptap/react";
63
- import { jsx as jsx3 } from "react/jsx-runtime";
64
- var EditorBubbleItem = forwardRef2(({ children, asChild, onSelect, ...rest }, ref) => {
65
- const { editor } = useCurrentEditor2();
66
- if (!editor) return null;
67
- const handleClick = (e) => {
68
- e.preventDefault();
69
- onSelect?.(editor);
70
- };
71
- if (asChild && isValidElement(children)) {
72
- const child = children;
73
- const childOnClick = child.props?.onClick;
74
- const mergedOnClick = (e) => {
75
- childOnClick?.(e);
76
- if (!e?.defaultPrevented) onSelect?.(editor);
77
- };
78
- return cloneElement(child, {
79
- ...rest,
80
- ref: child.ref ?? ref,
81
- onClick: mergedOnClick
82
- });
83
- }
84
- return /* @__PURE__ */ jsx3("div", { ref, ...rest, onClick: handleClick, children });
85
- });
86
- EditorBubbleItem.displayName = "EditorBubbleItem";
87
-
88
- // src/headless/components/editor-command.tsx
89
- import { useAtom, useSetAtom } from "jotai";
90
- import { useEffect, forwardRef as forwardRef3 } from "react";
91
- import { Command } from "cmdk";
92
-
93
- // src/headless/utils/atoms.ts
94
- import { atom } from "jotai";
95
- var queryAtom = atom("");
96
- var rangeAtom = atom(null);
97
-
98
- // src/headless/components/editor-command.tsx
99
- import tunnel from "tunnel-rat";
100
- import { jsx as jsx4, jsxs } from "react/jsx-runtime";
101
- var commandTunnel = tunnel();
102
- var EditorCommandOut = ({
103
- query,
104
- range
105
- }) => {
106
- const setQuery = useSetAtom(queryAtom, { store: novelStore });
107
- const setRange = useSetAtom(rangeAtom, { store: novelStore });
108
- useEffect(() => {
109
- setQuery(query);
110
- }, [query, setQuery]);
111
- useEffect(() => {
112
- setRange(range);
113
- }, [range, setRange]);
114
- useEffect(() => {
115
- const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"];
116
- const onKeyDown = (e) => {
117
- if (navigationKeys.includes(e.key)) {
118
- e.preventDefault();
119
- const commandRef = document.querySelector("#slash-command");
120
- if (commandRef)
121
- commandRef.dispatchEvent(
122
- new KeyboardEvent("keydown", {
123
- key: e.key,
124
- cancelable: true,
125
- bubbles: true
126
- })
127
- );
128
- return false;
129
- }
130
- };
131
- document.addEventListener("keydown", onKeyDown);
132
- return () => {
133
- document.removeEventListener("keydown", onKeyDown);
134
- };
135
- }, []);
136
- return /* @__PURE__ */ jsx4(commandTunnel.Out, {});
137
- };
138
- var CommandAny = Command;
139
- var EditorCommand = forwardRef3(
140
- ({ children, className, ...rest }, ref) => {
141
- const [query, setQuery] = useAtom(queryAtom);
142
- return /* @__PURE__ */ jsx4(commandTunnel.In, { children: /* @__PURE__ */ jsxs(
143
- CommandAny,
144
- {
145
- ref,
146
- onKeyDown: (e) => {
147
- e.stopPropagation();
148
- },
149
- id: "slash-command",
150
- className,
151
- ...rest,
152
- children: [
153
- /* @__PURE__ */ jsx4(
154
- CommandAny.Input,
155
- {
156
- value: query,
157
- onValueChange: setQuery,
158
- style: { display: "none" }
159
- }
160
- ),
161
- children
162
- ]
163
- }
164
- ) });
165
- }
166
- );
167
- var EditorCommandList = Command.List;
168
- EditorCommand.displayName = "EditorCommand";
169
-
170
- // src/headless/components/editor-command-item.tsx
171
- import { forwardRef as forwardRef4 } from "react";
172
- import { CommandEmpty, CommandItem } from "cmdk";
173
- import { useCurrentEditor as useCurrentEditor3 } from "@tiptap/react";
174
- import { useAtomValue } from "jotai";
175
- import { jsx as jsx5 } from "react/jsx-runtime";
176
- var CommandItemAny = CommandItem;
177
- var CommandEmptyAny = CommandEmpty;
178
- var EditorCommandItem = forwardRef4(({ children, onCommand, ...rest }, ref) => {
179
- const { editor } = useCurrentEditor3();
180
- const range = useAtomValue(rangeAtom);
181
- if (!editor || !range) return null;
182
- return /* @__PURE__ */ jsx5(
183
- CommandItemAny,
184
- {
185
- ref,
186
- ...rest,
187
- onSelect: () => onCommand({ editor, range }),
188
- children
189
- }
190
- );
191
- });
192
- EditorCommandItem.displayName = "EditorCommandItem";
193
- var EditorCommandEmpty = CommandEmptyAny;
194
-
195
- // src/headless/extensions/index.ts
196
- import { StarterKit } from "@tiptap/starter-kit";
197
- import { Placeholder } from "@tiptap/extension-placeholder";
198
-
199
- // src/headless/extensions/CodeBlock/CodeBlock.ts
200
- import { CodeBlockLowlight } from "@tiptap/extension-code-block-lowlight";
201
- import { all, createLowlight } from "lowlight";
202
- var lowlight = createLowlight(all);
203
- var CodeBlock = CodeBlockLowlight.configure({
204
- lowlight
205
- });
206
-
207
- // src/headless/extensions/Link/Link.ts
208
- import { mergeAttributes } from "@tiptap/core";
209
- import TiptapLink from "@tiptap/extension-link";
210
- import { Plugin } from "@tiptap/pm/state";
211
- var Link = TiptapLink.extend({
212
- inclusive: false,
213
- parseHTML() {
214
- return [
215
- {
216
- tag: 'a[href]:not([data-type="button"]):not([href *= "javascript:" i])'
217
- }
218
- ];
219
- },
220
- renderHTML({ HTMLAttributes }) {
221
- return [
222
- "a",
223
- mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
224
- class: "link"
225
- }),
226
- 0
227
- ];
228
- },
229
- addProseMirrorPlugins() {
230
- const { editor } = this;
231
- return [
232
- ...this.parent?.() || [],
233
- new Plugin({
234
- props: {
235
- handleKeyDown: (view, event) => {
236
- const { selection } = editor.state;
237
- if (event.key === "Escape" && selection.empty !== true) {
238
- editor.commands.focus(selection.to, { scrollIntoView: false });
239
- }
240
- return false;
241
- }
242
- }
243
- })
244
- ];
245
- }
246
- }).configure({
247
- openOnClick: false,
248
- autolink: true,
249
- enableClickSelection: true
250
- });
251
-
252
- // src/headless/extensions/ImageBlock/ImageBlock.ts
253
- import { mergeAttributes as mergeAttributes2 } from "@tiptap/core";
254
- import { Image as TiptapImage } from "@tiptap/extension-image";
255
- import { ReactNodeViewRenderer } from "@tiptap/react";
256
- import { Plugin as Plugin2, PluginKey } from "@tiptap/pm/state";
257
- var ImageBlock = TiptapImage.extend({
258
- name: "imageBlock",
259
- group: "block",
260
- defining: true,
261
- isolating: true,
262
- addOptions() {
263
- return {
264
- ...this.parent?.(),
265
- uploadImage: void 0,
266
- inline: false
267
- };
268
- },
269
- addAttributes() {
270
- return {
271
- src: {
272
- default: "",
273
- parseHTML: (element) => element.getAttribute("src"),
274
- renderHTML: (attributes) => ({
275
- src: attributes.src
276
- })
277
- },
278
- width: {
279
- default: "100%",
280
- parseHTML: (element) => element.getAttribute("data-width"),
281
- renderHTML: (attributes) => ({
282
- "data-width": attributes.width
283
- })
284
- },
285
- align: {
286
- default: "center",
287
- parseHTML: (element) => element.getAttribute("data-align"),
288
- renderHTML: (attributes) => ({
289
- "data-align": attributes.align
290
- })
291
- },
292
- alt: {
293
- default: void 0,
294
- parseHTML: (element) => element.getAttribute("alt"),
295
- renderHTML: (attributes) => ({
296
- alt: attributes.alt
297
- })
298
- },
299
- loading: {
300
- default: false,
301
- parseHTML: () => false,
302
- renderHTML: () => ({})
303
- }
304
- };
305
- },
306
- parseHTML() {
307
- return [
308
- {
309
- tag: 'img[src]:not([src^="data:"])',
310
- getAttrs: (element) => {
311
- const el = element;
312
- return {
313
- src: el.getAttribute("src"),
314
- alt: el.getAttribute("alt"),
315
- width: el.getAttribute("data-width") || "100%",
316
- align: el.getAttribute("data-align") || "center"
317
- };
318
- }
319
- }
320
- ];
321
- },
322
- renderHTML({ HTMLAttributes }) {
323
- return ["img", mergeAttributes2(HTMLAttributes)];
324
- },
325
- addCommands() {
326
- return {
327
- setImageBlock: (attrs) => ({ commands }) => {
328
- return commands.insertContent({
329
- type: "imageBlock",
330
- attrs: { src: attrs.src }
331
- });
332
- },
333
- setImageBlockAt: (attrs) => ({ commands }) => {
334
- return commands.insertContentAt(attrs.pos, {
335
- type: "imageBlock",
336
- attrs: { src: attrs.src }
337
- });
338
- },
339
- setImageBlockAlign: (align) => ({ commands }) => commands.updateAttributes("imageBlock", { align }),
340
- setImageBlockWidth: (width) => ({ commands }) => commands.updateAttributes("imageBlock", {
341
- width: `${Math.max(0, Math.min(100, width))}%`
342
- })
343
- };
344
- },
345
- addNodeView() {
346
- if (this.options.nodeView) {
347
- return ReactNodeViewRenderer(this.options.nodeView);
348
- }
349
- return null;
350
- },
351
- addProseMirrorPlugins() {
352
- return [
353
- new Plugin2({
354
- key: new PluginKey("imageBlockDrop"),
355
- props: {
356
- handleDOMEvents: {
357
- drop: (view, event) => {
358
- const hasFiles = event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length;
359
- if (!hasFiles) {
360
- return false;
361
- }
362
- const images = Array.from(event.dataTransfer.files).filter(
363
- (file) => /image/i.test(file.type)
364
- );
365
- if (images.length === 0) {
366
- return false;
367
- }
368
- event.preventDefault();
369
- const { schema } = view.state;
370
- const coordinates = view.posAtCoords({
371
- left: event.clientX,
372
- top: event.clientY
373
- });
374
- if (!coordinates) return false;
375
- images.forEach(async (image) => {
376
- if (this.options.uploadImage) {
377
- try {
378
- const placeholderNode = schema.nodes.imageBlock.create({
379
- src: "",
380
- loading: true
381
- });
382
- const placeholderTr = view.state.tr.insert(
383
- coordinates.pos,
384
- placeholderNode
385
- );
386
- view.dispatch(placeholderTr);
387
- const url = await this.options.uploadImage(image);
388
- const node = schema.nodes.imageBlock.create({ src: url });
389
- const currentState = view.state;
390
- let foundPos = -1;
391
- currentState.doc.descendants((node2, pos) => {
392
- if (node2.type.name === "imageBlock" && node2.attrs.loading) {
393
- foundPos = pos;
394
- return false;
395
- }
396
- });
397
- if (foundPos !== -1) {
398
- const transaction = view.state.tr.replaceWith(
399
- foundPos,
400
- foundPos + 1,
401
- node
402
- );
403
- view.dispatch(transaction);
404
- }
405
- } catch (error) {
406
- console.error("Failed to upload image:", error);
407
- const currentState = view.state;
408
- let foundPos = -1;
409
- currentState.doc.descendants((node, pos) => {
410
- if (node.type.name === "imageBlock" && node.attrs.loading) {
411
- foundPos = pos;
412
- return false;
413
- }
414
- });
415
- if (foundPos !== -1) {
416
- const transaction = view.state.tr.delete(
417
- foundPos,
418
- foundPos + 1
419
- );
420
- view.dispatch(transaction);
421
- }
422
- }
423
- }
424
- });
425
- return true;
426
- },
427
- paste: (view, event) => {
428
- const hasFiles = event.clipboardData && event.clipboardData.files && event.clipboardData.files.length;
429
- if (!hasFiles) {
430
- return false;
431
- }
432
- const images = Array.from(event.clipboardData.files).filter(
433
- (file) => /image/i.test(file.type)
434
- );
435
- if (images.length === 0) {
436
- return false;
437
- }
438
- event.preventDefault();
439
- images.forEach(async (image) => {
440
- if (this.options.uploadImage) {
441
- try {
442
- const placeholderNode = view.state.schema.nodes.imageBlock.create({
443
- src: "",
444
- loading: true
445
- });
446
- view.dispatch(
447
- view.state.tr.replaceSelectionWith(placeholderNode)
448
- );
449
- const url = await this.options.uploadImage(image);
450
- const node = view.state.schema.nodes.imageBlock.create({
451
- src: url
452
- });
453
- const currentState = view.state;
454
- let foundPos = -1;
455
- currentState.doc.descendants((node2, pos) => {
456
- if (node2.type.name === "imageBlock" && node2.attrs.loading) {
457
- foundPos = pos;
458
- return false;
459
- }
460
- });
461
- if (foundPos !== -1) {
462
- const transaction = view.state.tr.replaceWith(
463
- foundPos,
464
- foundPos + 1,
465
- node
466
- );
467
- view.dispatch(transaction);
468
- }
469
- } catch (error) {
470
- console.error("Failed to upload image:", error);
471
- const currentState = view.state;
472
- let foundPos = -1;
473
- currentState.doc.descendants((node, pos) => {
474
- if (node.type.name === "imageBlock" && node.attrs.loading) {
475
- foundPos = pos;
476
- return false;
477
- }
478
- });
479
- if (foundPos !== -1) {
480
- const transaction = view.state.tr.delete(
481
- foundPos,
482
- foundPos + 1
483
- );
484
- view.dispatch(transaction);
485
- }
486
- }
487
- }
488
- });
489
- return true;
490
- }
491
- }
492
- }
493
- })
494
- ];
495
- }
496
- });
497
-
498
- // src/headless/extensions/Mention/mention.tsx
499
- import { ReactRenderer, ReactNodeViewRenderer as ReactNodeViewRenderer2 } from "@tiptap/react";
500
- import Mention from "@tiptap/extension-mention";
501
-
502
- // src/headless/extensions/Mention/mention-command.tsx
503
- import { forwardRef as forwardRef5, useEffect as useEffect2, useImperativeHandle, useState } from "react";
504
- import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
505
- function Avatar({ src, fallback }) {
506
- return /* @__PURE__ */ jsx6("div", { style: {
507
- position: "relative",
508
- display: "flex",
509
- height: "24px",
510
- width: "24px",
511
- flexShrink: 0,
512
- overflow: "hidden",
513
- borderRadius: "9999px"
514
- }, children: src ? /* @__PURE__ */ jsx6(
515
- "img",
516
- {
517
- style: {
518
- aspectRatio: "1",
519
- height: "100%",
520
- width: "100%"
521
- },
522
- src,
523
- alt: fallback
524
- }
525
- ) : /* @__PURE__ */ jsx6("div", { style: {
526
- display: "flex",
527
- height: "100%",
528
- width: "100%",
529
- alignItems: "center",
530
- justifyContent: "center",
531
- borderRadius: "9999px",
532
- backgroundColor: "var(--muted)",
533
- color: "var(--muted-foreground)",
534
- fontSize: "10px",
535
- fontWeight: 600
536
- }, children: fallback }) });
537
- }
538
- function ReferenceIcon({ type }) {
539
- if (type === "node") {
540
- return /* @__PURE__ */ jsxs2("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0 }, children: [
541
- /* @__PURE__ */ jsx6("path", { d: "M12 3l8 4.5v9l-8 4.5l-8-4.5v-9l8-4.5" }),
542
- /* @__PURE__ */ jsx6("path", { d: "M12 12l8-4.5" }),
543
- /* @__PURE__ */ jsx6("path", { d: "M12 12v9" }),
544
- /* @__PURE__ */ jsx6("path", { d: "M12 12l-8-4.5" })
545
- ] });
546
- }
547
- return /* @__PURE__ */ jsxs2("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0 }, children: [
548
- /* @__PURE__ */ jsx6("path", { d: "M14 3v4a1 1 0 0 0 1 1h4" }),
549
- /* @__PURE__ */ jsx6("path", { d: "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z" }),
550
- /* @__PURE__ */ jsx6("path", { d: "M9 9l1 0" }),
551
- /* @__PURE__ */ jsx6("path", { d: "M9 13l6 0" }),
552
- /* @__PURE__ */ jsx6("path", { d: "M9 17l6 0" })
553
- ] });
554
- }
555
- var MentionCommand = forwardRef5((props, ref) => {
556
- const [selectedIndex, setSelectedIndex] = useState(0);
557
- const selectItem = (index) => {
558
- const item = props.items[index];
559
- if (item) {
560
- props.command(item);
561
- }
562
- };
563
- const upHandler = () => {
564
- setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length);
565
- };
566
- const downHandler = () => {
567
- setSelectedIndex((selectedIndex + 1) % props.items.length);
568
- };
569
- const enterHandler = () => {
570
- selectItem(selectedIndex);
571
- };
572
- useEffect2(() => setSelectedIndex(0), [props.items]);
573
- useImperativeHandle(ref, () => ({
574
- onKeyDown: ({ event }) => {
575
- if (event.key === "ArrowUp") {
576
- upHandler();
577
- return true;
578
- }
579
- if (event.key === "ArrowDown") {
580
- downHandler();
581
- return true;
582
- }
583
- if (event.key === "Enter") {
584
- enterHandler();
585
- return true;
586
- }
587
- return false;
588
- }
589
- }));
590
- return /* @__PURE__ */ jsx6(
591
- "div",
592
- {
593
- id: "mention-list",
594
- style: {
595
- backgroundColor: "var(--popover)",
596
- color: "var(--foreground)",
597
- maxHeight: "300px",
598
- minWidth: "280px",
599
- overflow: "hidden",
600
- overflowY: "auto",
601
- borderRadius: "12px",
602
- border: "1px solid var(--border)",
603
- padding: "4px",
604
- boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)"
605
- },
606
- children: props.items.length ? props.items.map((item, index) => /* @__PURE__ */ jsxs2(
607
- "button",
608
- {
609
- type: "button",
610
- onClick: () => selectItem(index),
611
- onMouseEnter: () => setSelectedIndex(index),
612
- style: {
613
- position: "relative",
614
- display: "flex",
615
- width: "100%",
616
- cursor: "default",
617
- userSelect: "none",
618
- alignItems: "center",
619
- gap: "8px",
620
- borderRadius: "4px",
621
- padding: "10px 8px",
622
- fontSize: "14px",
623
- outline: "none",
624
- backgroundColor: index === selectedIndex ? "var(--accent)" : "transparent",
625
- color: index === selectedIndex ? "var(--accent-foreground)" : "inherit",
626
- border: "none",
627
- textAlign: "left"
628
- },
629
- children: [
630
- item.type ? /* @__PURE__ */ jsx6(ReferenceIcon, { type: item.type }) : /* @__PURE__ */ jsx6(
631
- Avatar,
632
- {
633
- src: item.avatar,
634
- fallback: item.label.slice(0, 2).toUpperCase()
635
- }
636
- ),
637
- /* @__PURE__ */ jsx6("span", { style: {
638
- flex: 1,
639
- overflow: "hidden",
640
- textOverflow: "ellipsis",
641
- whiteSpace: "nowrap"
642
- }, children: item.label })
643
- ]
644
- },
645
- item.id
646
- )) : /* @__PURE__ */ jsx6("div", { style: {
647
- padding: "24px 0",
648
- textAlign: "center",
649
- fontSize: "14px",
650
- color: "var(--muted-foreground)"
651
- }, children: "No results found" })
652
- }
653
- );
654
- });
655
- MentionCommand.displayName = "MentionCommand";
656
-
657
- // src/headless/extensions/Mention/mention-node-view.tsx
658
- import { NodeViewWrapper } from "@tiptap/react";
659
- import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
660
- function NodeIcon() {
661
- return /* @__PURE__ */ jsxs3("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0 }, children: [
662
- /* @__PURE__ */ jsx7("path", { d: "M12 3l8 4.5v9l-8 4.5l-8-4.5v-9l8-4.5" }),
663
- /* @__PURE__ */ jsx7("path", { d: "M12 12l8-4.5" }),
664
- /* @__PURE__ */ jsx7("path", { d: "M12 12v9" }),
665
- /* @__PURE__ */ jsx7("path", { d: "M12 12l-8-4.5" })
666
- ] });
667
- }
668
- function ArticleIcon() {
669
- return /* @__PURE__ */ jsxs3("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0 }, children: [
670
- /* @__PURE__ */ jsx7("path", { d: "M14 3v4a1 1 0 0 0 1 1h4" }),
671
- /* @__PURE__ */ jsx7("path", { d: "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z" }),
672
- /* @__PURE__ */ jsx7("path", { d: "M9 9l1 0" }),
673
- /* @__PURE__ */ jsx7("path", { d: "M9 13l6 0" }),
674
- /* @__PURE__ */ jsx7("path", { d: "M9 17l6 0" })
675
- ] });
676
- }
677
- var MentionNodeView = (props) => {
678
- const { node } = props;
679
- const { id, label, avatar, type } = node.attrs;
680
- const isNode = type === "node";
681
- const isArticle = type === "article";
682
- const isReference = isNode || isArticle;
683
- const backgroundColor = isArticle ? "rgba(249, 115, 22, 0.15)" : isNode ? "rgba(107, 114, 128, 0.15)" : "var(--accent)";
684
- const color = isArticle ? "rgb(234, 88, 12)" : isNode ? "rgb(75, 85, 99)" : "var(--accent-foreground)";
685
- const border = isArticle ? "1px solid rgba(249, 115, 22, 0.3)" : isNode ? "1px solid rgba(107, 114, 128, 0.3)" : "none";
686
- return /* @__PURE__ */ jsxs3(
687
- NodeViewWrapper,
688
- {
689
- as: "span",
690
- style: {
691
- display: "inline-flex",
692
- alignItems: "center",
693
- gap: "3px",
694
- backgroundColor,
695
- color,
696
- border,
697
- padding: isReference ? "1px 6px" : "1px 6px 1px 1px",
698
- borderRadius: "12px",
699
- fontSize: "13px",
700
- fontWeight: 500,
701
- verticalAlign: "middle"
702
- },
703
- children: [
704
- isNode && /* @__PURE__ */ jsx7(NodeIcon, {}),
705
- isArticle && /* @__PURE__ */ jsx7(ArticleIcon, {}),
706
- !isReference && avatar && /* @__PURE__ */ jsx7(
707
- "img",
708
- {
709
- src: avatar,
710
- alt: label || id,
711
- style: {
712
- width: "20px",
713
- height: "20px",
714
- borderRadius: "50%",
715
- flexShrink: 0
716
- }
717
- }
718
- ),
719
- !isReference && !avatar && /* @__PURE__ */ jsx7(
720
- "div",
721
- {
722
- style: {
723
- width: "20px",
724
- height: "20px",
725
- borderRadius: "50%",
726
- backgroundColor: "var(--muted)",
727
- color: "var(--muted-foreground)",
728
- display: "flex",
729
- alignItems: "center",
730
- justifyContent: "center",
731
- fontSize: "10px",
732
- fontWeight: 600,
733
- flexShrink: 0
734
- },
735
- children: (label || id).slice(0, 2).toUpperCase()
736
- }
737
- ),
738
- /* @__PURE__ */ jsx7("span", { children: label || id })
739
- ]
740
- }
741
- );
742
- };
743
-
744
- // src/headless/extensions/Mention/mention.tsx
745
- var createMentionExtension = (options) => {
746
- const extensionName = options?.name ?? "mention";
747
- return Mention.extend({
748
- name: extensionName,
749
- addAttributes() {
750
- return {
751
- id: {
752
- default: null,
753
- parseHTML: (element) => element.getAttribute("data-id"),
754
- renderHTML: (attributes) => {
755
- if (!attributes.id) {
756
- return {};
757
- }
758
- return {
759
- "data-id": attributes.id
760
- };
761
- }
762
- },
763
- label: {
764
- default: null,
765
- parseHTML: (element) => element.getAttribute("data-label"),
766
- renderHTML: (attributes) => {
767
- if (!attributes.label) {
768
- return {};
769
- }
770
- return {
771
- "data-label": attributes.label
772
- };
773
- }
774
- },
775
- avatar: {
776
- default: null,
777
- parseHTML: (element) => element.getAttribute("data-avatar"),
778
- renderHTML: (attributes) => {
779
- if (!attributes.avatar) {
780
- return {};
781
- }
782
- return {
783
- "data-avatar": attributes.avatar
784
- };
785
- }
786
- },
787
- type: {
788
- default: null,
789
- parseHTML: (element) => element.getAttribute("data-ref-type"),
790
- renderHTML: (attributes) => {
791
- if (!attributes.type) {
792
- return {};
793
- }
794
- return {
795
- "data-ref-type": attributes.type
796
- };
797
- }
798
- },
799
- nodeId: {
800
- default: null,
801
- parseHTML: (element) => element.getAttribute("data-node-id"),
802
- renderHTML: (attributes) => {
803
- if (!attributes.nodeId) {
804
- return {};
805
- }
806
- return {
807
- "data-node-id": attributes.nodeId
808
- };
809
- }
810
- },
811
- slug: {
812
- default: null,
813
- parseHTML: (element) => element.getAttribute("data-slug"),
814
- renderHTML: (attributes) => {
815
- if (!attributes.slug) {
816
- return {};
817
- }
818
- return {
819
- "data-slug": attributes.slug
820
- };
821
- }
822
- }
823
- };
824
- },
825
- addNodeView() {
826
- return ReactNodeViewRenderer2(MentionNodeView);
827
- }
828
- }).configure({
829
- HTMLAttributes: {
830
- class: "mention"
831
- },
832
- suggestion: {
833
- char: options?.char ?? "@",
834
- items: async ({ query }) => {
835
- if (!options?.items) return [];
836
- const items = await options.items(query);
837
- return items;
838
- },
839
- command: ({ editor, range, props: item }) => {
840
- editor.chain().focus().insertContentAt(range, [
841
- {
842
- type: extensionName,
843
- attrs: {
844
- id: item.id,
845
- label: item.label,
846
- avatar: item.avatar,
847
- type: item.type,
848
- nodeId: item.nodeId,
849
- slug: item.slug
850
- }
851
- }
852
- ]).run();
853
- },
854
- render: renderMentionSuggestion
855
- },
856
- renderLabel: options?.renderLabel ?? ((props) => {
857
- return `@${props.node.attrs.label ?? props.node.attrs.id}`;
858
- })
859
- });
860
- };
861
- var renderMentionSuggestion = () => {
862
- let component = null;
863
- let container = null;
864
- const destroy = () => {
865
- component?.destroy();
866
- component = null;
867
- if (container) {
868
- container.remove();
869
- container = null;
870
- }
871
- };
872
- const updatePosition = (clientRect) => {
873
- if (!container || !clientRect) return;
874
- const gap = 8;
875
- const maxDropdownHeight = 300;
876
- const spaceBelow = window.innerHeight - clientRect.bottom;
877
- const spaceAbove = clientRect.top;
878
- const shouldPositionAbove = spaceBelow < maxDropdownHeight && spaceAbove > spaceBelow;
879
- const left = Math.round(clientRect.left);
880
- if (shouldPositionAbove) {
881
- const bottom = Math.round(window.innerHeight - clientRect.top + gap);
882
- container.style.bottom = `${bottom}px`;
883
- container.style.top = "auto";
884
- } else {
885
- const top = Math.round(clientRect.bottom + gap);
886
- container.style.top = `${top}px`;
887
- container.style.bottom = "auto";
888
- }
889
- container.style.left = `${left}px`;
890
- };
891
- return {
892
- onStart: (props) => {
893
- component = new ReactRenderer(MentionCommand, {
894
- props: {
895
- items: props.items ?? [],
896
- command: props.command ?? (() => {
897
- }),
898
- query: props.query ?? ""
899
- },
900
- editor: props.editor
901
- });
902
- container = document.createElement("div");
903
- container.style.position = "fixed";
904
- container.style.zIndex = "9999";
905
- document.body.appendChild(container);
906
- container.appendChild(component.element);
907
- const rect = typeof props.clientRect === "function" ? props.clientRect() : null;
908
- if (rect) updatePosition(rect);
909
- },
910
- onUpdate: (props) => {
911
- component?.updateProps({
912
- items: props.items ?? [],
913
- command: props.command ?? (() => {
914
- }),
915
- query: props.query ?? ""
916
- });
917
- const rect = typeof props.clientRect === "function" ? props.clientRect() : null;
918
- if (rect) updatePosition(rect);
919
- },
920
- onKeyDown: ({ event }) => {
921
- if (!component) return false;
922
- if (event.key === "Escape") {
923
- event.preventDefault();
924
- event.stopPropagation();
925
- destroy();
926
- return true;
927
- }
928
- if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
929
- event.preventDefault();
930
- event.stopPropagation();
931
- return component.ref?.onKeyDown?.({ event }) ?? false;
932
- }
933
- return false;
934
- },
935
- onExit: () => {
936
- destroy();
937
- }
938
- };
939
- };
940
-
941
- // src/headless/extensions/DragHandle/DragHandle.ts
942
- import BaseDragHandle from "@tiptap/extension-drag-handle";
943
- var currentCallbacks = {};
944
- var currentNode = null;
945
- var currentEditor = null;
946
- function setDragHandleCallbacks(callbacks) {
947
- currentCallbacks = callbacks;
948
- }
949
- function createDragHandleElement() {
950
- const container = document.createElement("div");
951
- container.className = "nph-drag-handle";
952
- const plusBtn = document.createElement("button");
953
- plusBtn.className = "nph-drag-handle__btn";
954
- plusBtn.type = "button";
955
- plusBtn.setAttribute("aria-label", "Add block");
956
- plusBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg>`;
957
- plusBtn.addEventListener("click", (e) => {
958
- e.preventDefault();
959
- e.stopPropagation();
960
- if (currentEditor) {
961
- currentCallbacks.onAddBlock?.(currentEditor, currentNode);
962
- }
963
- });
964
- const gripBtn = document.createElement("button");
965
- gripBtn.className = "nph-drag-handle__btn nph-drag-handle__grip";
966
- gripBtn.type = "button";
967
- gripBtn.setAttribute("aria-label", "Drag to reorder");
968
- gripBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="5" r="1"/><circle cx="9" cy="12" r="1"/><circle cx="9" cy="19" r="1"/><circle cx="15" cy="5" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="19" r="1"/></svg>`;
969
- gripBtn.addEventListener("click", (e) => {
970
- e.preventDefault();
971
- e.stopPropagation();
972
- if (currentEditor) {
973
- currentCallbacks.onGripClick?.(currentEditor, currentNode, container);
974
- }
975
- });
976
- container.appendChild(plusBtn);
977
- container.appendChild(gripBtn);
978
- return container;
979
- }
980
- var DragHandle = BaseDragHandle.configure({
981
- render: createDragHandleElement,
982
- nested: true,
983
- onNodeChange: ({ node, editor }) => {
984
- currentNode = node;
985
- currentEditor = editor;
986
- }
987
- });
988
-
989
- // src/headless/extensions/Table/index.ts
990
- import { TableKit } from "@tiptap/extension-table";
991
- import { Table, TableCell, TableHeader, TableRow } from "@tiptap/extension-table";
992
-
993
- // src/headless/extensions/MarkdownPaste.ts
994
- import { Extension } from "@tiptap/core";
995
- import { Plugin as Plugin3, PluginKey as PluginKey2 } from "@tiptap/pm/state";
996
- import { MarkdownParser, defaultMarkdownParser } from "@tiptap/pm/markdown";
997
- var markdownPastePluginKey = new PluginKey2("markdownPaste");
998
- function looksLikeMarkdown(text) {
999
- const patterns = [
1000
- /^#{1,6}\s/m,
1001
- // headings
1002
- /^\s*[-*+]\s/m,
1003
- // unordered list
1004
- /^\s*\d+\.\s/m,
1005
- // ordered list
1006
- /^\s*>\s/m,
1007
- // blockquote
1008
- /\|.+\|/m,
1009
- // table
1010
- /^```/m,
1011
- // fenced code block
1012
- /\*\*.+\*\*/,
1013
- // bold
1014
- /\*.+\*/,
1015
- // italic
1016
- /~~.+~~/,
1017
- // strikethrough
1018
- /`[^`]+`/,
1019
- // inline code
1020
- /^\s*---\s*$/m,
1021
- // horizontal rule
1022
- /^\s*\*\*\*\s*$/m,
1023
- // horizontal rule alt
1024
- /\[.+\]\(.+\)/,
1025
- // links
1026
- /!\[.*\]\(.+\)/
1027
- // images
1028
- ];
1029
- const hasMarkdown = patterns.some((p) => p.test(text));
1030
- const isHtml = /^<[a-z][\s\S]*>/i.test(text.trim());
1031
- return hasMarkdown && !isHtml;
1032
- }
1033
- function buildParser(schema) {
1034
- const md = defaultMarkdownParser.tokenizer;
1035
- const tokens = {};
1036
- if (schema.nodes.paragraph) tokens.paragraph = { block: "paragraph" };
1037
- if (schema.nodes.heading) {
1038
- tokens.heading = {
1039
- block: "heading",
1040
- getAttrs: (tok) => ({ level: Number(tok.tag.slice(1)) })
1041
- };
1042
- }
1043
- if (schema.nodes.blockquote) tokens.blockquote = { block: "blockquote" };
1044
- if (schema.nodes.bulletList) tokens.bullet_list = { block: "bulletList" };
1045
- if (schema.nodes.orderedList) {
1046
- tokens.ordered_list = {
1047
- block: "orderedList",
1048
- getAttrs: (tok) => ({ start: Number(tok.attrGet("start") || 1) })
1049
- };
1050
- }
1051
- if (schema.nodes.listItem) tokens.list_item = { block: "listItem" };
1052
- if (schema.nodes.codeBlock) {
1053
- tokens.code_block = { block: "codeBlock", noCloseToken: true };
1054
- tokens.fence = {
1055
- block: "codeBlock",
1056
- getAttrs: (tok) => ({ language: tok.info || "" }),
1057
- noCloseToken: true
1058
- };
1059
- }
1060
- if (schema.nodes.horizontalRule) {
1061
- tokens.hr = { node: "horizontalRule" };
1062
- }
1063
- if (schema.nodes.hardBreak) {
1064
- tokens.hardbreak = { node: "hardBreak" };
1065
- }
1066
- if (schema.nodes.image) {
1067
- tokens.image = {
1068
- node: "image",
1069
- getAttrs: (tok) => ({
1070
- src: tok.attrGet("src"),
1071
- title: tok.attrGet("title") || null,
1072
- alt: tok.children?.[0]?.content || null
1073
- })
1074
- };
1075
- }
1076
- if (schema.nodes.table) {
1077
- tokens.table = { block: "table" };
1078
- tokens.thead = { ignore: true };
1079
- tokens.tbody = { ignore: true };
1080
- tokens.tr = { block: "tableRow" };
1081
- tokens.th = { block: "tableHeader" };
1082
- tokens.td = { block: "tableCell" };
1083
- }
1084
- if (schema.marks.bold || schema.marks.strong) {
1085
- tokens.strong = { mark: schema.marks.bold ? "bold" : "strong" };
1086
- }
1087
- if (schema.marks.italic || schema.marks.em) {
1088
- tokens.em = { mark: schema.marks.italic ? "italic" : "em" };
1089
- }
1090
- if (schema.marks.code) {
1091
- tokens.code_inline = { mark: "code", noCloseToken: true };
1092
- }
1093
- if (schema.marks.link) {
1094
- tokens.link = {
1095
- mark: "link",
1096
- getAttrs: (tok) => ({
1097
- href: tok.attrGet("href"),
1098
- title: tok.attrGet("title") || null
1099
- })
1100
- };
1101
- }
1102
- if (schema.marks.strike || schema.marks.strikethrough) {
1103
- tokens.s = { mark: schema.marks.strike ? "strike" : "strikethrough" };
1104
- }
1105
- try {
1106
- return new MarkdownParser(schema, md, tokens);
1107
- } catch {
1108
- return null;
1109
- }
1110
- }
1111
- var MarkdownPaste = Extension.create({
1112
- name: "markdownPaste",
1113
- addProseMirrorPlugins() {
1114
- const schema = this.editor.schema;
1115
- let parser = null;
1116
- return [
1117
- new Plugin3({
1118
- key: markdownPastePluginKey,
1119
- props: {
1120
- handlePaste(view, event) {
1121
- const clipboardData = event.clipboardData;
1122
- if (!clipboardData) return false;
1123
- const html = clipboardData.getData("text/html");
1124
- if (html && html.trim().length > 0) return false;
1125
- const text = clipboardData.getData("text/plain");
1126
- if (!text || !looksLikeMarkdown(text)) return false;
1127
- if (!parser) {
1128
- parser = buildParser(schema);
1129
- }
1130
- if (!parser) return false;
1131
- try {
1132
- const doc = parser.parse(text);
1133
- if (!doc || doc.content.size === 0) return false;
1134
- const { tr } = view.state;
1135
- const slice = doc.slice(0, doc.content.size);
1136
- tr.replaceSelection(slice);
1137
- view.dispatch(tr);
1138
- return true;
1139
- } catch {
1140
- return false;
1141
- }
1142
- }
1143
- }
1144
- })
1145
- ];
1146
- }
1147
- });
1148
-
1149
- // src/headless/extensions/slash-command.tsx
1150
- import { ReactRenderer as ReactRenderer2 } from "@tiptap/react";
1151
- import Suggestion from "@tiptap/suggestion";
1152
- import { Extension as Extension2 } from "@tiptap/core";
1153
- var Command2 = Extension2.create({
1154
- name: "slash-command",
1155
- addOptions() {
1156
- return {
1157
- suggestion: {
1158
- char: "/",
1159
- command: (ctx) => {
1160
- ctx.props.command({ editor: ctx.editor, range: ctx.range });
1161
- }
1162
- }
1163
- };
1164
- },
1165
- addProseMirrorPlugins() {
1166
- const base = this.options.suggestion ?? {};
1167
- return [
1168
- Suggestion({
1169
- editor: this.editor,
1170
- char: base.char ?? "/",
1171
- // Only trigger slash command at start of line or after whitespace
1172
- startOfLine: base.startOfLine ?? true,
1173
- items: base.items ?? (() => ["/"]),
1174
- command: (ctx) => {
1175
- if (typeof ctx?.props?.command === "function") {
1176
- ctx.props.command({ editor: ctx.editor, range: ctx.range });
1177
- }
1178
- },
1179
- ...base
1180
- })
1181
- ];
1182
- }
1183
- });
1184
- var renderItems = (elementRef) => {
1185
- let component = null;
1186
- let container = null;
1187
- const destroy = () => {
1188
- component?.destroy();
1189
- component = null;
1190
- if (container) {
1191
- container.remove();
1192
- container = null;
1193
- }
1194
- };
1195
- const updatePosition = (clientRect) => {
1196
- if (!container || !clientRect) return;
1197
- const menuHeight = container.offsetHeight || 360;
1198
- const viewportHeight = window.innerHeight;
1199
- const spaceBelow = viewportHeight - clientRect.bottom;
1200
- const spaceAbove = clientRect.top;
1201
- let top;
1202
- if (spaceBelow < menuHeight + 16 && spaceAbove > spaceBelow) {
1203
- top = Math.round(clientRect.top - menuHeight - 8);
1204
- if (top < 8) top = 8;
1205
- } else {
1206
- top = Math.round(clientRect.bottom + 8);
1207
- }
1208
- let left = Math.round(clientRect.left);
1209
- const menuWidth = container.offsetWidth || 280;
1210
- if (left + menuWidth > window.innerWidth - 8) {
1211
- left = window.innerWidth - menuWidth - 8;
1212
- }
1213
- if (left < 8) left = 8;
1214
- container.style.top = `${top}px`;
1215
- container.style.left = `${left}px`;
1216
- };
1217
- return {
1218
- onStart: (props) => {
1219
- const { selection } = props.editor.state;
1220
- const parentNode = selection.$from.node(selection.$from.depth);
1221
- const blockType = parentNode.type.name;
1222
- if (blockType === "codeBlock") return false;
1223
- const { $from } = selection;
1224
- const marks = $from.marks();
1225
- if (marks.some((mark) => mark.type.name === "code" || mark.type.name === "link")) {
1226
- return false;
1227
- }
1228
- component = new ReactRenderer2(EditorCommandOut, {
1229
- props: {
1230
- query: props.query ?? "",
1231
- range: props.range
1232
- },
1233
- editor: props.editor
1234
- });
1235
- container = document.createElement("div");
1236
- container.style.position = "fixed";
1237
- container.style.zIndex = "9999";
1238
- container.style.minWidth = "240px";
1239
- (elementRef?.current ?? document.body).appendChild(container);
1240
- container.appendChild(component.element);
1241
- const rect = typeof props.clientRect === "function" ? props.clientRect() : null;
1242
- if (rect) updatePosition(rect);
1243
- },
1244
- onUpdate: (props) => {
1245
- component?.updateProps({
1246
- query: props.query ?? "",
1247
- range: props.range
1248
- });
1249
- const rect = typeof props.clientRect === "function" ? props.clientRect() : null;
1250
- if (rect) updatePosition(rect);
1251
- },
1252
- onKeyDown: ({ event }) => {
1253
- if (event.key === "Escape") {
1254
- destroy();
1255
- return true;
1256
- }
1257
- return false;
1258
- },
1259
- onExit: () => {
1260
- destroy();
1261
- }
1262
- };
1263
- };
1264
- var createSuggestionItems = (items) => items;
1265
- var handleCommandNavigation = (event) => {
1266
- if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
1267
- const slashCommand = document.querySelector("#slash-command");
1268
- if (slashCommand) return true;
1269
- }
1270
- };
1271
-
1272
- export {
1273
- EditorRoot,
1274
- EditorContent,
1275
- EditorBubble,
1276
- EditorBubbleItem,
1277
- EditorCommandOut,
1278
- EditorCommand,
1279
- EditorCommandList,
1280
- EditorCommandItem,
1281
- EditorCommandEmpty,
1282
- CodeBlock,
1283
- Link,
1284
- ImageBlock,
1285
- MentionCommand,
1286
- createMentionExtension,
1287
- renderMentionSuggestion,
1288
- setDragHandleCallbacks,
1289
- DragHandle,
1290
- TableKit,
1291
- MarkdownPaste,
1292
- StarterKit,
1293
- Placeholder,
1294
- Command2 as Command,
1295
- renderItems,
1296
- createSuggestionItems,
1297
- handleCommandNavigation,
1298
- useCurrentEditor4 as useCurrentEditor
1299
- };
1300
- //# sourceMappingURL=chunk-RW6QBMJB.js.map