neuphlo-editor 2.5.0 → 2.6.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.
Files changed (171) hide show
  1. package/dist/Markdown-BAW0cb-U.d.cts +153 -0
  2. package/dist/Markdown-BAW0cb-U.d.ts +153 -0
  3. package/dist/{chunk-4L7FHW5M.js → chunk-ABL4D65Z.js} +113 -47
  4. package/dist/chunk-ABL4D65Z.js.map +1 -0
  5. package/dist/{chunk-BVFTQKY7.js → chunk-Z2DR2FK3.js} +245 -50
  6. package/dist/chunk-Z2DR2FK3.js.map +1 -0
  7. package/dist/headless/components/editor-bubble-item.d.ts +9 -0
  8. package/dist/headless/components/editor-bubble-item.js +29 -0
  9. package/dist/headless/components/editor-bubble.d.ts +9 -0
  10. package/dist/headless/components/editor-bubble.js +9 -0
  11. package/dist/headless/components/editor-command-item.d.ts +3 -0
  12. package/dist/headless/components/editor-command-item.js +27 -0
  13. package/dist/headless/components/editor-command.d.ts +3 -0
  14. package/dist/headless/components/editor-command.js +136 -0
  15. package/dist/headless/components/editor.d.ts +24 -0
  16. package/dist/headless/components/editor.js +13 -0
  17. package/dist/headless/extensions/AISuggestion/AISuggestion.d.ts +82 -0
  18. package/dist/headless/extensions/AISuggestion/AISuggestion.js +244 -0
  19. package/dist/headless/extensions/AISuggestion/index.d.ts +2 -0
  20. package/dist/headless/extensions/AISuggestion/index.js +1 -0
  21. package/dist/headless/extensions/CodeBlock/CodeBlock.d.ts +1 -0
  22. package/dist/headless/extensions/CodeBlock/CodeBlock.js +6 -0
  23. package/dist/headless/extensions/CodeBlock/index.d.ts +1 -0
  24. package/dist/headless/extensions/CodeBlock/index.js +1 -0
  25. package/dist/headless/extensions/DragHandle/DragHandle.d.ts +9 -0
  26. package/dist/headless/extensions/DragHandle/DragHandle.js +47 -0
  27. package/dist/headless/extensions/DragHandle/index.d.ts +2 -0
  28. package/dist/headless/extensions/DragHandle/index.js +1 -0
  29. package/dist/headless/extensions/Image/Image.d.ts +6 -0
  30. package/dist/headless/extensions/Image/Image.js +197 -0
  31. package/dist/headless/extensions/ImageBlock/ImageBlock.d.ts +23 -0
  32. package/dist/headless/extensions/ImageBlock/ImageBlock.js +242 -0
  33. package/dist/headless/extensions/ImageBlock/index.d.ts +2 -0
  34. package/dist/headless/extensions/ImageBlock/index.js +1 -0
  35. package/dist/headless/extensions/Link/Link.d.ts +2 -0
  36. package/dist/headless/extensions/Link/Link.js +44 -0
  37. package/dist/headless/extensions/Link/index.d.ts +1 -0
  38. package/dist/headless/extensions/Link/index.js +1 -0
  39. package/dist/headless/extensions/Markdown.d.ts +9 -0
  40. package/dist/headless/extensions/Markdown.js +138 -0
  41. package/dist/headless/extensions/MarkdownPaste.d.ts +3 -0
  42. package/dist/headless/extensions/MarkdownPaste.js +168 -0
  43. package/dist/headless/extensions/Mention/index.d.ts +4 -0
  44. package/dist/headless/extensions/Mention/index.js +3 -0
  45. package/dist/headless/extensions/Mention/mention-command.d.ts +8 -0
  46. package/dist/headless/extensions/Mention/mention-command.js +165 -0
  47. package/dist/headless/extensions/Mention/mention-list.d.ts +8 -0
  48. package/dist/headless/extensions/Mention/mention-list.js +150 -0
  49. package/dist/headless/extensions/Mention/mention-node-view.d.ts +2 -0
  50. package/dist/headless/extensions/Mention/mention-node-view.js +92 -0
  51. package/dist/headless/extensions/Mention/mention.d.ts +46 -0
  52. package/dist/headless/extensions/Mention/mention.js +218 -0
  53. package/dist/headless/extensions/Table/index.d.ts +2 -0
  54. package/dist/headless/extensions/Table/index.js +2 -0
  55. package/dist/headless/extensions/VideoBlock/VideoBlock.d.ts +17 -0
  56. package/dist/headless/extensions/VideoBlock/VideoBlock.js +73 -0
  57. package/dist/headless/extensions/VideoBlock/index.d.ts +2 -0
  58. package/dist/headless/extensions/VideoBlock/index.js +1 -0
  59. package/dist/headless/extensions/extension-kit.d.ts +29 -0
  60. package/dist/headless/extensions/extension-kit.js +132 -0
  61. package/dist/headless/extensions/index.d.ts +16 -0
  62. package/dist/headless/extensions/index.js +12 -0
  63. package/dist/headless/extensions/slash-command.d.ts +24 -0
  64. package/dist/headless/extensions/slash-command.js +99 -0
  65. package/dist/headless/index.cjs +143 -2
  66. package/dist/headless/index.cjs.map +1 -1
  67. package/dist/headless/index.d.cts +3 -2
  68. package/dist/headless/index.d.ts +3 -2
  69. package/dist/headless/index.js +5 -1
  70. package/dist/headless/utils/atoms.d.ts +13 -0
  71. package/dist/headless/utils/atoms.js +5 -0
  72. package/dist/headless/utils/store.d.ts +2 -0
  73. package/dist/headless/utils/store.js +4 -0
  74. package/dist/highlight.css +77 -1
  75. package/dist/react/Editor.d.ts +43 -0
  76. package/dist/react/Editor.js +119 -0
  77. package/dist/react/TableOfContents.d.ts +7 -0
  78. package/dist/react/TableOfContents.js +96 -0
  79. package/dist/react/index.cjs +156 -9
  80. package/dist/react/index.cjs.map +1 -1
  81. package/dist/react/index.d.cts +5 -2
  82. package/dist/react/index.d.ts +5 -2
  83. package/dist/react/index.js +14 -4
  84. package/dist/react/index.js.map +1 -1
  85. package/dist/react/menus/DragHandle/BlockActionMenu.d.ts +7 -0
  86. package/dist/react/menus/DragHandle/BlockActionMenu.js +111 -0
  87. package/dist/react/menus/DragHandle/DragHandleMenu.d.ts +7 -0
  88. package/dist/react/menus/DragHandle/DragHandleMenu.js +97 -0
  89. package/dist/react/menus/ImageBlock/ImageBlockLoading.d.ts +2 -0
  90. package/dist/react/menus/ImageBlock/ImageBlockLoading.js +6 -0
  91. package/dist/react/menus/ImageBlock/ImageBlockMenu.d.ts +8 -0
  92. package/dist/react/menus/ImageBlock/ImageBlockMenu.js +75 -0
  93. package/dist/react/menus/ImageBlock/ImageBlockView.d.ts +10 -0
  94. package/dist/react/menus/ImageBlock/ImageBlockView.js +60 -0
  95. package/dist/react/menus/ImageBlock/ImageBlockWidth.d.ts +6 -0
  96. package/dist/react/menus/ImageBlock/ImageBlockWidth.js +29 -0
  97. package/dist/react/menus/ImageBlock/ImageResizeHandle.d.ts +8 -0
  98. package/dist/react/menus/ImageBlock/ImageResizeHandle.js +37 -0
  99. package/dist/react/menus/ImageBlock/ImageUploader.d.ts +7 -0
  100. package/dist/react/menus/ImageBlock/ImageUploader.js +73 -0
  101. package/dist/react/menus/ImageBlock/index.d.ts +4 -0
  102. package/dist/react/menus/ImageBlock/index.js +4 -0
  103. package/dist/react/menus/ImageMenu.d.ts +10 -0
  104. package/dist/react/menus/ImageMenu.js +77 -0
  105. package/dist/react/menus/ImagePopover.d.ts +8 -0
  106. package/dist/react/menus/ImagePopover.js +146 -0
  107. package/dist/react/menus/LinkMenu.d.ts +2 -0
  108. package/dist/react/menus/LinkMenu.js +69 -0
  109. package/dist/react/menus/MenuList.d.ts +10 -0
  110. package/dist/react/menus/MenuList.js +94 -0
  111. package/dist/react/menus/SlashMenu.d.ts +5 -0
  112. package/dist/react/menus/SlashMenu.js +156 -0
  113. package/dist/react/menus/TableMenu.d.ts +5 -0
  114. package/dist/react/menus/TableMenu.js +462 -0
  115. package/dist/react/menus/TaskItem/TaskItemView.d.ts +12 -0
  116. package/dist/react/menus/TaskItem/TaskItemView.js +11 -0
  117. package/dist/react/menus/TextMenu.d.ts +10 -0
  118. package/dist/react/menus/TextMenu.js +139 -0
  119. package/dist/react/menus/VideoBlock/VideoBlockMenu.d.ts +7 -0
  120. package/dist/react/menus/VideoBlock/VideoBlockMenu.js +72 -0
  121. package/dist/react/menus/VideoBlock/VideoBlockView.d.ts +10 -0
  122. package/dist/react/menus/VideoBlock/VideoBlockView.js +87 -0
  123. package/dist/react/menus/VideoBlock/index.d.ts +2 -0
  124. package/dist/react/menus/VideoBlock/index.js +2 -0
  125. package/dist/react/menus/index.d.ts +15 -0
  126. package/dist/react/menus/index.js +9 -0
  127. package/package.json +3 -1
  128. package/dist/chunk-2DWEJI45.js +0 -1296
  129. package/dist/chunk-2DWEJI45.js.map +0 -1
  130. package/dist/chunk-3CLWAYRP.js +0 -1387
  131. package/dist/chunk-3CLWAYRP.js.map +0 -1
  132. package/dist/chunk-457ETWB6.js +0 -1351
  133. package/dist/chunk-457ETWB6.js.map +0 -1
  134. package/dist/chunk-4L7FHW5M.js.map +0 -1
  135. package/dist/chunk-4MV3UUZN.js +0 -1073
  136. package/dist/chunk-4MV3UUZN.js.map +0 -1
  137. package/dist/chunk-62DYB7FY.js +0 -1305
  138. package/dist/chunk-62DYB7FY.js.map +0 -1
  139. package/dist/chunk-BVFTQKY7.js.map +0 -1
  140. package/dist/chunk-DWGPGRTQ.js +0 -1302
  141. package/dist/chunk-DWGPGRTQ.js.map +0 -1
  142. package/dist/chunk-EG7NQJRA.js +0 -1324
  143. package/dist/chunk-EG7NQJRA.js.map +0 -1
  144. package/dist/chunk-FLLPFFI5.js +0 -1296
  145. package/dist/chunk-FLLPFFI5.js.map +0 -1
  146. package/dist/chunk-FVQHB6VC.js +0 -1128
  147. package/dist/chunk-FVQHB6VC.js.map +0 -1
  148. package/dist/chunk-G5E32MLB.js +0 -1352
  149. package/dist/chunk-G5E32MLB.js.map +0 -1
  150. package/dist/chunk-GXJGZHKR.js +0 -1326
  151. package/dist/chunk-GXJGZHKR.js.map +0 -1
  152. package/dist/chunk-KCPPTLGY.js +0 -1299
  153. package/dist/chunk-KCPPTLGY.js.map +0 -1
  154. package/dist/chunk-LHG2NX6C.js +0 -1123
  155. package/dist/chunk-LHG2NX6C.js.map +0 -1
  156. package/dist/chunk-MSNTVITF.js +0 -1352
  157. package/dist/chunk-MSNTVITF.js.map +0 -1
  158. package/dist/chunk-N4RDYJ5Z.js +0 -1351
  159. package/dist/chunk-N4RDYJ5Z.js.map +0 -1
  160. package/dist/chunk-OCNM37WJ.js +0 -1289
  161. package/dist/chunk-OCNM37WJ.js.map +0 -1
  162. package/dist/chunk-P3YFYEUB.js +0 -1351
  163. package/dist/chunk-P3YFYEUB.js.map +0 -1
  164. package/dist/chunk-RW6QBMJB.js +0 -1300
  165. package/dist/chunk-RW6QBMJB.js.map +0 -1
  166. package/dist/chunk-SJQQVB3M.js +0 -1353
  167. package/dist/chunk-SJQQVB3M.js.map +0 -1
  168. package/dist/chunk-SOXTEP7H.js +0 -6705
  169. package/dist/chunk-SOXTEP7H.js.map +0 -1
  170. package/dist/chunk-VPI26I4P.js +0 -1350
  171. package/dist/chunk-VPI26I4P.js.map +0 -1
@@ -0,0 +1,165 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
3
+ const GRADIENT_MAP = {
4
+ red: "linear-gradient(135deg, #ef4444, #fb7185)",
5
+ coral: "linear-gradient(135deg, #f87171, #fb923c)",
6
+ orange: "linear-gradient(135deg, #f97316, #fbbf24)",
7
+ amber: "linear-gradient(135deg, #f59e0b, #facc15)",
8
+ lime: "linear-gradient(135deg, #84cc16, #4ade80)",
9
+ green: "linear-gradient(135deg, #10b981, #2dd4bf)",
10
+ teal: "linear-gradient(135deg, #14b8a6, #22d3ee)",
11
+ cyan: "linear-gradient(135deg, #06b6d4, #60a5fa)",
12
+ blue: "linear-gradient(135deg, #3b82f6, #818cf8)",
13
+ indigo: "linear-gradient(135deg, #6366f1, #a78bfa)",
14
+ violet: "linear-gradient(135deg, #8b5cf6, #a855f7)",
15
+ purple: "linear-gradient(135deg, #a855f7, #d946ef)",
16
+ fuchsia: "linear-gradient(135deg, #d946ef, #f472b6)",
17
+ pink: "linear-gradient(135deg, #ec4899, #fb7185)",
18
+ slate: "linear-gradient(135deg, #64748b, #71717a)",
19
+ stone: "linear-gradient(135deg, #78716c, #a3a3a3)",
20
+ };
21
+ function isGradientKey(avatar) {
22
+ return !!avatar && avatar in GRADIENT_MAP;
23
+ }
24
+ function isAgentItem(item) {
25
+ return !!item.email?.endsWith("@ai.neuphlo.local");
26
+ }
27
+ function getInitials(name) {
28
+ if (!name)
29
+ return "AG";
30
+ return name.split(/\s+/).map((w) => w[0]).join("").slice(0, 2).toUpperCase();
31
+ }
32
+ // Simple Avatar component with inline styles
33
+ function Avatar({ src, fallback, isAgent }) {
34
+ const gradient = src && isGradientKey(src) ? GRADIENT_MAP[src] : isAgent ? GRADIENT_MAP.violet : null;
35
+ return (_jsx("div", { style: {
36
+ position: "relative",
37
+ display: "flex",
38
+ height: "24px",
39
+ width: "24px",
40
+ flexShrink: 0,
41
+ overflow: "hidden",
42
+ borderRadius: "9999px",
43
+ }, children: gradient ? (_jsx("div", { style: {
44
+ display: "flex",
45
+ height: "100%",
46
+ width: "100%",
47
+ alignItems: "center",
48
+ justifyContent: "center",
49
+ borderRadius: "9999px",
50
+ background: gradient,
51
+ color: "#ffffff",
52
+ fontSize: "10px",
53
+ fontWeight: 600,
54
+ }, children: fallback })) : src ? (_jsx("img", { style: {
55
+ aspectRatio: "1",
56
+ height: "100%",
57
+ width: "100%",
58
+ }, src: src, alt: fallback })) : (_jsx("div", { style: {
59
+ display: "flex",
60
+ height: "100%",
61
+ width: "100%",
62
+ alignItems: "center",
63
+ justifyContent: "center",
64
+ borderRadius: "9999px",
65
+ backgroundColor: "var(--muted)",
66
+ color: "var(--muted-foreground)",
67
+ fontSize: "10px",
68
+ fontWeight: 600,
69
+ }, children: fallback })) }));
70
+ }
71
+ // Icon component for reference types
72
+ function ReferenceIcon({ type }) {
73
+ if (type === "node") {
74
+ return (_jsxs("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: [_jsx("path", { d: "M12 3l8 4.5v9l-8 4.5l-8-4.5v-9l8-4.5" }), _jsx("path", { d: "M12 12l8-4.5" }), _jsx("path", { d: "M12 12v9" }), _jsx("path", { d: "M12 12l-8-4.5" })] }));
75
+ }
76
+ return (_jsxs("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: [_jsx("path", { d: "M14 3v4a1 1 0 0 0 1 1h4" }), _jsx("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" }), _jsx("path", { d: "M9 9l1 0" }), _jsx("path", { d: "M9 13l6 0" }), _jsx("path", { d: "M9 17l6 0" })] }));
77
+ }
78
+ export const MentionCommand = forwardRef((props, ref) => {
79
+ const [selectedIndex, setSelectedIndex] = useState(0);
80
+ const selectItem = (index) => {
81
+ const item = props.items[index];
82
+ if (item) {
83
+ props.command(item);
84
+ }
85
+ };
86
+ const upHandler = () => {
87
+ setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length);
88
+ };
89
+ const downHandler = () => {
90
+ setSelectedIndex((selectedIndex + 1) % props.items.length);
91
+ };
92
+ const enterHandler = () => {
93
+ selectItem(selectedIndex);
94
+ };
95
+ useEffect(() => setSelectedIndex(0), [props.items]);
96
+ useImperativeHandle(ref, () => ({
97
+ onKeyDown: ({ event }) => {
98
+ if (event.key === "ArrowUp") {
99
+ upHandler();
100
+ return true;
101
+ }
102
+ if (event.key === "ArrowDown") {
103
+ downHandler();
104
+ return true;
105
+ }
106
+ if (event.key === "Enter") {
107
+ enterHandler();
108
+ return true;
109
+ }
110
+ return false;
111
+ },
112
+ }));
113
+ return (_jsx("div", { id: "mention-list", style: {
114
+ backgroundColor: "var(--popover)",
115
+ color: "var(--foreground)",
116
+ maxHeight: "300px",
117
+ minWidth: "280px",
118
+ overflow: "hidden",
119
+ overflowY: "auto",
120
+ borderRadius: "12px",
121
+ border: "1px solid var(--border)",
122
+ padding: "4px",
123
+ boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
124
+ }, children: props.items.length ? ((() => {
125
+ const agents = props.items.filter(i => !i.type && isAgentItem(i));
126
+ const others = props.items.filter(i => i.type || !isAgentItem(i));
127
+ const sections = [];
128
+ if (agents.length)
129
+ sections.push({ label: "Agents", items: agents, startIndex: 0 });
130
+ if (others.length)
131
+ sections.push({ label: agents.length ? "Members" : null, items: others, startIndex: agents.length });
132
+ return sections.map((section) => (_jsxs("div", { children: [section.label && (_jsx("div", { style: { padding: "6px 8px 2px", fontSize: "11px", fontWeight: 600, color: "var(--muted-foreground)", textTransform: "uppercase", letterSpacing: "0.05em" }, children: section.label })), section.items.map((item, i) => {
133
+ const index = section.startIndex + i;
134
+ const agent = isAgentItem(item);
135
+ return (_jsxs("button", { type: "button", onClick: () => selectItem(index), onMouseEnter: () => setSelectedIndex(index), style: {
136
+ position: "relative",
137
+ display: "flex",
138
+ width: "100%",
139
+ cursor: "default",
140
+ userSelect: "none",
141
+ alignItems: "center",
142
+ gap: "8px",
143
+ borderRadius: "4px",
144
+ padding: "10px 8px",
145
+ fontSize: "14px",
146
+ outline: "none",
147
+ backgroundColor: index === selectedIndex ? "var(--accent)" : "transparent",
148
+ color: index === selectedIndex ? "var(--accent-foreground)" : "inherit",
149
+ border: "none",
150
+ textAlign: "left",
151
+ }, children: [item.type ? (_jsx(ReferenceIcon, { type: item.type })) : (_jsx(Avatar, { src: item.avatar, fallback: getInitials(item.label), isAgent: agent })), _jsx("span", { style: {
152
+ flex: 1,
153
+ overflow: "hidden",
154
+ textOverflow: "ellipsis",
155
+ whiteSpace: "nowrap",
156
+ }, children: item.label })] }, item.id));
157
+ })] }, section.label ?? "default")));
158
+ })()) : (_jsx("div", { style: {
159
+ padding: "24px 0",
160
+ textAlign: "center",
161
+ fontSize: "14px",
162
+ color: "var(--muted-foreground)",
163
+ }, children: "No results found" })) }));
164
+ });
165
+ MentionCommand.displayName = "MentionCommand";
@@ -0,0 +1,8 @@
1
+ import type { MentionItem } from "./mention";
2
+ interface MentionListProps {
3
+ items: MentionItem[];
4
+ command: (item: MentionItem) => void;
5
+ query: string;
6
+ }
7
+ export declare const MentionList: import("react").ForwardRefExoticComponent<MentionListProps & import("react").RefAttributes<any>>;
8
+ export {};
@@ -0,0 +1,150 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
3
+ // Gradient map for agent avatars (avatar field stores a gradient key like "violet")
4
+ const GRADIENT_MAP = {
5
+ red: "linear-gradient(135deg, #ef4444, #fb7185)",
6
+ coral: "linear-gradient(135deg, #f87171, #fb923c)",
7
+ orange: "linear-gradient(135deg, #f97316, #fbbf24)",
8
+ amber: "linear-gradient(135deg, #f59e0b, #facc15)",
9
+ lime: "linear-gradient(135deg, #84cc16, #4ade80)",
10
+ green: "linear-gradient(135deg, #10b981, #2dd4bf)",
11
+ teal: "linear-gradient(135deg, #14b8a6, #22d3ee)",
12
+ cyan: "linear-gradient(135deg, #06b6d4, #60a5fa)",
13
+ blue: "linear-gradient(135deg, #3b82f6, #818cf8)",
14
+ indigo: "linear-gradient(135deg, #6366f1, #a78bfa)",
15
+ violet: "linear-gradient(135deg, #8b5cf6, #a855f7)",
16
+ purple: "linear-gradient(135deg, #a855f7, #d946ef)",
17
+ fuchsia: "linear-gradient(135deg, #d946ef, #f472b6)",
18
+ pink: "linear-gradient(135deg, #ec4899, #fb7185)",
19
+ slate: "linear-gradient(135deg, #64748b, #71717a)",
20
+ stone: "linear-gradient(135deg, #78716c, #a3a3a3)",
21
+ };
22
+ function isAgent(item) {
23
+ return !!item.email?.endsWith("@ai.neuphlo.local");
24
+ }
25
+ function isGradientKey(avatar) {
26
+ return !!avatar && avatar in GRADIENT_MAP;
27
+ }
28
+ function getAgentGradient(item) {
29
+ return GRADIENT_MAP[item.avatar || "violet"] || GRADIENT_MAP.violet;
30
+ }
31
+ function getInitials(name) {
32
+ if (!name)
33
+ return "AG";
34
+ return name.split(/\s+/).map(w => w[0]).join("").slice(0, 2).toUpperCase();
35
+ }
36
+ export const MentionList = forwardRef((props, ref) => {
37
+ const [selectedIndex, setSelectedIndex] = useState(0);
38
+ const selectItem = (index) => {
39
+ const item = props.items[index];
40
+ if (item) {
41
+ props.command(item);
42
+ }
43
+ };
44
+ const upHandler = () => {
45
+ setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length);
46
+ };
47
+ const downHandler = () => {
48
+ setSelectedIndex((selectedIndex + 1) % props.items.length);
49
+ };
50
+ const enterHandler = () => {
51
+ selectItem(selectedIndex);
52
+ };
53
+ useEffect(() => setSelectedIndex(0), [props.items]);
54
+ useImperativeHandle(ref, () => ({
55
+ onKeyDown: ({ event }) => {
56
+ if (event.key === "ArrowUp") {
57
+ upHandler();
58
+ return true;
59
+ }
60
+ if (event.key === "ArrowDown") {
61
+ downHandler();
62
+ return true;
63
+ }
64
+ if (event.key === "Enter") {
65
+ enterHandler();
66
+ return true;
67
+ }
68
+ return false;
69
+ },
70
+ }));
71
+ return (_jsx("div", { id: "mention-list", className: "nph-mention-list", style: {
72
+ background: "white",
73
+ border: "1px solid #e2e8f0",
74
+ borderRadius: "8px",
75
+ boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
76
+ maxHeight: "320px",
77
+ overflowY: "auto",
78
+ padding: "4px",
79
+ }, children: props.items.length ? ((() => {
80
+ const agents = props.items.filter(i => isAgent(i));
81
+ const members = props.items.filter(i => !isAgent(i));
82
+ const sections = [];
83
+ if (agents.length)
84
+ sections.push({ label: "Agents", items: agents, startIndex: 0 });
85
+ if (members.length)
86
+ sections.push({ label: "Members", items: members, startIndex: agents.length });
87
+ return sections.map((section) => (_jsxs("div", { children: [_jsx("div", { style: { padding: "6px 8px 4px", fontSize: "11px", fontWeight: "600", color: "#94a3b8", textTransform: "uppercase", letterSpacing: "0.05em" }, children: section.label }), section.items.map((item, i) => {
88
+ const index = section.startIndex + i;
89
+ return (_jsxs("button", { type: "button", onClick: () => selectItem(index), className: "nph-mention-item", style: {
90
+ display: "flex",
91
+ alignItems: "center",
92
+ gap: "8px",
93
+ width: "100%",
94
+ padding: "8px",
95
+ border: "none",
96
+ borderRadius: "6px",
97
+ background: index === selectedIndex ? "#f1f5f9" : "transparent",
98
+ cursor: "pointer",
99
+ textAlign: "left",
100
+ transition: "background 0.15s",
101
+ }, onMouseEnter: () => setSelectedIndex(index), children: [(isGradientKey(item.avatar) || isAgent(item)) ? (_jsx("div", { style: {
102
+ width: "24px",
103
+ height: "24px",
104
+ borderRadius: "50%",
105
+ background: getAgentGradient(item),
106
+ display: "flex",
107
+ alignItems: "center",
108
+ justifyContent: "center",
109
+ fontSize: "10px",
110
+ fontWeight: "600",
111
+ color: "#ffffff",
112
+ }, children: getInitials(item.label) })) : item.avatar ? (_jsx("img", { src: item.avatar, alt: item.label, style: {
113
+ width: "24px",
114
+ height: "24px",
115
+ borderRadius: "50%",
116
+ objectFit: "cover",
117
+ } })) : (_jsx("div", { style: {
118
+ width: "24px",
119
+ height: "24px",
120
+ borderRadius: "50%",
121
+ background: "#e2e8f0",
122
+ display: "flex",
123
+ alignItems: "center",
124
+ justifyContent: "center",
125
+ fontSize: "10px",
126
+ fontWeight: "600",
127
+ color: "#64748b",
128
+ }, children: item.label.slice(0, 2).toUpperCase() })), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: {
129
+ fontSize: "14px",
130
+ fontWeight: "500",
131
+ color: "#0f172a",
132
+ overflow: "hidden",
133
+ textOverflow: "ellipsis",
134
+ whiteSpace: "nowrap",
135
+ }, children: item.label }), item.email && !isAgent(item) && (_jsx("div", { style: {
136
+ fontSize: "12px",
137
+ color: "#64748b",
138
+ overflow: "hidden",
139
+ textOverflow: "ellipsis",
140
+ whiteSpace: "nowrap",
141
+ }, children: item.email }))] })] }, item.id));
142
+ })] }, section.label)));
143
+ })()) : (_jsx("div", { style: {
144
+ padding: "12px",
145
+ fontSize: "14px",
146
+ color: "#64748b",
147
+ textAlign: "center",
148
+ }, children: "No results found" })) }));
149
+ });
150
+ MentionList.displayName = "MentionList";
@@ -0,0 +1,2 @@
1
+ import type { NodeViewProps } from "@tiptap/react";
2
+ export declare const MentionNodeView: (props: NodeViewProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,92 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { NodeViewWrapper } from "@tiptap/react";
3
+ const GRADIENT_MAP = {
4
+ red: "linear-gradient(135deg, #ef4444, #fb7185)",
5
+ coral: "linear-gradient(135deg, #f87171, #fb923c)",
6
+ orange: "linear-gradient(135deg, #f97316, #fbbf24)",
7
+ amber: "linear-gradient(135deg, #f59e0b, #facc15)",
8
+ lime: "linear-gradient(135deg, #84cc16, #4ade80)",
9
+ green: "linear-gradient(135deg, #10b981, #2dd4bf)",
10
+ teal: "linear-gradient(135deg, #14b8a6, #22d3ee)",
11
+ cyan: "linear-gradient(135deg, #06b6d4, #60a5fa)",
12
+ blue: "linear-gradient(135deg, #3b82f6, #818cf8)",
13
+ indigo: "linear-gradient(135deg, #6366f1, #a78bfa)",
14
+ violet: "linear-gradient(135deg, #8b5cf6, #a855f7)",
15
+ purple: "linear-gradient(135deg, #a855f7, #d946ef)",
16
+ fuchsia: "linear-gradient(135deg, #d946ef, #f472b6)",
17
+ pink: "linear-gradient(135deg, #ec4899, #fb7185)",
18
+ slate: "linear-gradient(135deg, #64748b, #71717a)",
19
+ stone: "linear-gradient(135deg, #78716c, #a3a3a3)",
20
+ };
21
+ // Icon components
22
+ function NodeIcon() {
23
+ return (_jsxs("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: [_jsx("path", { d: "M12 3l8 4.5v9l-8 4.5l-8-4.5v-9l8-4.5" }), _jsx("path", { d: "M12 12l8-4.5" }), _jsx("path", { d: "M12 12v9" }), _jsx("path", { d: "M12 12l-8-4.5" })] }));
24
+ }
25
+ function ArticleIcon() {
26
+ return (_jsxs("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: [_jsx("path", { d: "M14 3v4a1 1 0 0 0 1 1h4" }), _jsx("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" }), _jsx("path", { d: "M9 9l1 0" }), _jsx("path", { d: "M9 13l6 0" }), _jsx("path", { d: "M9 17l6 0" })] }));
27
+ }
28
+ export const MentionNodeView = (props) => {
29
+ const { node } = props;
30
+ const { id, label, avatar, type } = node.attrs;
31
+ // Determine styling based on type
32
+ const isNode = type === "node";
33
+ const isArticle = type === "article";
34
+ const isReference = isNode || isArticle;
35
+ const backgroundColor = isArticle
36
+ ? "rgba(249, 115, 22, 0.15)" // Orange for articles
37
+ : isNode
38
+ ? "rgba(107, 114, 128, 0.15)" // Gray for nodes
39
+ : "var(--accent)"; // Default for user mentions
40
+ const color = isArticle
41
+ ? "rgb(234, 88, 12)" // Orange text
42
+ : isNode
43
+ ? "rgb(75, 85, 99)" // Gray text
44
+ : "var(--accent-foreground)"; // Default
45
+ const border = isArticle
46
+ ? "1px solid rgba(249, 115, 22, 0.3)"
47
+ : isNode
48
+ ? "1px solid rgba(107, 114, 128, 0.3)"
49
+ : "none";
50
+ return (_jsxs(NodeViewWrapper, { as: "span", style: {
51
+ display: "inline-flex",
52
+ alignItems: "center",
53
+ gap: "3px",
54
+ backgroundColor,
55
+ color,
56
+ border,
57
+ padding: isReference ? "1px 6px" : "1px 6px 1px 1px",
58
+ borderRadius: "12px",
59
+ fontSize: "13px",
60
+ fontWeight: 500,
61
+ verticalAlign: "middle",
62
+ }, children: [isNode && _jsx(NodeIcon, {}), isArticle && _jsx(ArticleIcon, {}), !isReference && avatar && avatar in GRADIENT_MAP && (_jsx("div", { style: {
63
+ width: "20px",
64
+ height: "20px",
65
+ borderRadius: "50%",
66
+ background: GRADIENT_MAP[avatar],
67
+ color: "#ffffff",
68
+ display: "flex",
69
+ alignItems: "center",
70
+ justifyContent: "center",
71
+ fontSize: "8px",
72
+ fontWeight: 600,
73
+ flexShrink: 0,
74
+ }, children: (label || id).split(/\s+/).map((w) => w[0]).join("").slice(0, 2).toUpperCase() })), !isReference && avatar && !(avatar in GRADIENT_MAP) && (_jsx("img", { src: avatar, alt: label || id, style: {
75
+ width: "20px",
76
+ height: "20px",
77
+ borderRadius: "50%",
78
+ flexShrink: 0,
79
+ } })), !isReference && !avatar && (_jsx("div", { style: {
80
+ width: "20px",
81
+ height: "20px",
82
+ borderRadius: "50%",
83
+ backgroundColor: "var(--muted)",
84
+ color: "var(--muted-foreground)",
85
+ display: "flex",
86
+ alignItems: "center",
87
+ justifyContent: "center",
88
+ fontSize: "10px",
89
+ fontWeight: 600,
90
+ flexShrink: 0,
91
+ }, children: (label || id).slice(0, 2).toUpperCase() })), _jsx("span", { children: label || id })] }));
92
+ };
@@ -0,0 +1,46 @@
1
+ export interface MentionItem {
2
+ id: string;
3
+ label: string;
4
+ avatar?: string;
5
+ email?: string;
6
+ type?: "node" | "article";
7
+ nodeId?: string;
8
+ slug?: string;
9
+ }
10
+ export interface MentionOptions {
11
+ /**
12
+ * Function to fetch/filter mentionable items based on query
13
+ */
14
+ items?: (query: string) => MentionItem[] | Promise<MentionItem[]>;
15
+ /**
16
+ * Custom render function for mention nodes
17
+ */
18
+ renderLabel?: (props: {
19
+ node: any;
20
+ options: any;
21
+ }) => string;
22
+ /**
23
+ * Character that triggers the mention autocomplete (default: @)
24
+ */
25
+ char?: string;
26
+ /**
27
+ * Custom name for the extension (to avoid duplicates)
28
+ */
29
+ name?: string;
30
+ }
31
+ /**
32
+ * Create the mention extension with custom suggestion rendering
33
+ */
34
+ export declare const createMentionExtension: (options?: MentionOptions) => import("@tiptap/core").Node<import("@tiptap/extension-mention").MentionOptions<any, import("@tiptap/extension-mention").MentionNodeAttrs>, any>;
35
+ /**
36
+ * Render function for mention suggestions (autocomplete dropdown)
37
+ */
38
+ export declare const renderMentionSuggestion: () => {
39
+ onStart: (props: any) => void;
40
+ onUpdate: (props: any) => void;
41
+ onKeyDown: ({ event }: {
42
+ event: KeyboardEvent;
43
+ }) => any;
44
+ onExit: () => void;
45
+ };
46
+ export default createMentionExtension;