@monolith-forensics/monolith-ui 1.9.1-dev.8 → 1.9.3-dev.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 (93) hide show
  1. package/dist/DropDownMenu/components/MenuItemList.js +32 -12
  2. package/dist/DropDownMenu/components/StyledContent.js +1 -1
  3. package/dist/DropDownMenu/components/StyledInnerItemContainer.js +1 -0
  4. package/dist/FileViewer/FileViewer.js +32 -8
  5. package/dist/FileViewer/viewers/ImageViewer.d.ts +1 -0
  6. package/dist/FileViewer/viewers/ImageViewer.js +36 -15
  7. package/dist/MonolithUIProvider/MonolithUIProvider.d.ts +23 -0
  8. package/dist/RichTextEditor/Components/BubbleMenu.d.ts +8 -8
  9. package/dist/RichTextEditor/Components/BubbleMenu.js +202 -94
  10. package/dist/RichTextEditor/Components/CodeBlockBaseButton.d.ts +18 -0
  11. package/dist/RichTextEditor/Components/CodeBlockBaseButton.js +6 -0
  12. package/dist/RichTextEditor/Components/CodeBlockCopyButton.d.ts +9 -0
  13. package/dist/RichTextEditor/Components/CodeBlockCopyButton.js +42 -0
  14. package/dist/RichTextEditor/Components/CodeBlockFormatButton.d.ts +10 -0
  15. package/dist/RichTextEditor/Components/CodeBlockFormatButton.js +60 -0
  16. package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.d.ts +9 -0
  17. package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.js +30 -0
  18. package/dist/RichTextEditor/Components/CodeBlockNodeView.d.ts +3 -0
  19. package/dist/RichTextEditor/Components/CodeBlockNodeView.js +28 -0
  20. package/dist/RichTextEditor/Components/CodeBlockWrapButton.d.ts +10 -0
  21. package/dist/RichTextEditor/Components/CodeBlockWrapButton.js +17 -0
  22. package/dist/RichTextEditor/Components/LinkEditor.d.ts +8 -0
  23. package/dist/RichTextEditor/Components/LinkEditor.js +94 -0
  24. package/dist/RichTextEditor/Components/TableCornerMenu.d.ts +16 -0
  25. package/dist/RichTextEditor/Components/TableCornerMenu.js +202 -0
  26. package/dist/RichTextEditor/Components/TableTools/TableCornerMenu.d.ts +2 -0
  27. package/dist/RichTextEditor/Components/TableTools/TableCornerMenu.js +19 -0
  28. package/dist/RichTextEditor/Components/TableTools/TableInsertControls.d.ts +2 -0
  29. package/dist/RichTextEditor/Components/TableTools/TableInsertControls.js +24 -0
  30. package/dist/RichTextEditor/Components/TableTools/TableRails.d.ts +2 -0
  31. package/dist/RichTextEditor/Components/TableTools/TableRails.js +180 -0
  32. package/dist/RichTextEditor/Components/TableTools/TableToolMenu.d.ts +5 -0
  33. package/dist/RichTextEditor/Components/TableTools/TableToolMenu.js +6 -0
  34. package/dist/RichTextEditor/Components/TableTools/TableTools.actions.d.ts +5 -0
  35. package/dist/RichTextEditor/Components/TableTools/TableTools.actions.js +183 -0
  36. package/dist/RichTextEditor/Components/TableTools/TableTools.commands.d.ts +16 -0
  37. package/dist/RichTextEditor/Components/TableTools/TableTools.commands.js +217 -0
  38. package/dist/RichTextEditor/Components/TableTools/TableTools.constants.d.ts +8 -0
  39. package/dist/RichTextEditor/Components/TableTools/TableTools.constants.js +11 -0
  40. package/dist/RichTextEditor/Components/TableTools/TableTools.d.ts +3 -0
  41. package/dist/RichTextEditor/Components/TableTools/TableTools.geometry.d.ts +23 -0
  42. package/dist/RichTextEditor/Components/TableTools/TableTools.geometry.js +75 -0
  43. package/dist/RichTextEditor/Components/TableTools/TableTools.js +3 -0
  44. package/dist/RichTextEditor/Components/TableTools/TableTools.selectors.d.ts +16 -0
  45. package/dist/RichTextEditor/Components/TableTools/TableTools.selectors.js +53 -0
  46. package/dist/RichTextEditor/Components/TableTools/TableTools.styled.d.ts +40 -0
  47. package/dist/RichTextEditor/Components/TableTools/TableTools.styled.js +167 -0
  48. package/dist/RichTextEditor/Components/TableTools/TableTools.types.d.ts +76 -0
  49. package/dist/RichTextEditor/Components/TableTools/TableTools.types.js +1 -0
  50. package/dist/RichTextEditor/Components/TableTools/TableTools.utils.d.ts +4 -0
  51. package/dist/RichTextEditor/Components/TableTools/TableTools.utils.js +4 -0
  52. package/dist/RichTextEditor/Components/TableTools/TableToolsPopover.d.ts +2 -0
  53. package/dist/RichTextEditor/Components/TableTools/TableToolsPopover.js +12 -0
  54. package/dist/RichTextEditor/Components/TableTools/index.d.ts +3 -0
  55. package/dist/RichTextEditor/Components/TableTools/index.js +2 -0
  56. package/dist/RichTextEditor/Components/TableTools.d.ts +44 -0
  57. package/dist/RichTextEditor/Components/TableTools.js +790 -0
  58. package/dist/RichTextEditor/Enums/Controls.d.ts +7 -1
  59. package/dist/RichTextEditor/Enums/Controls.js +6 -0
  60. package/dist/RichTextEditor/Enums/Extensions.d.ts +4 -0
  61. package/dist/RichTextEditor/Enums/Extensions.js +4 -0
  62. package/dist/RichTextEditor/Enums/HighlightColors.d.ts +9 -0
  63. package/dist/RichTextEditor/Enums/HighlightColors.js +10 -0
  64. package/dist/RichTextEditor/Enums/SlashCommands.d.ts +4 -1
  65. package/dist/RichTextEditor/Enums/SlashCommands.js +3 -0
  66. package/dist/RichTextEditor/Extensions/SlashCommandList.js +0 -1
  67. package/dist/RichTextEditor/Extensions/getSlashCommand.js +39 -1
  68. package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +10 -2
  69. package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +157 -30
  70. package/dist/RichTextEditor/Plugins/ImageActionsPlugin.js +4 -7
  71. package/dist/RichTextEditor/RichTextEditor.d.ts +4 -2
  72. package/dist/RichTextEditor/RichTextEditor.js +395 -15
  73. package/dist/RichTextEditor/Toolbar/Control.d.ts +6 -2
  74. package/dist/RichTextEditor/Toolbar/Control.js +13 -6
  75. package/dist/RichTextEditor/Toolbar/Controls.d.ts +6 -0
  76. package/dist/RichTextEditor/Toolbar/Controls.js +118 -1
  77. package/dist/RichTextEditor/Toolbar/ControlsGroup.js +17 -6
  78. package/dist/RichTextEditor/Toolbar/Labels.d.ts +1 -0
  79. package/dist/RichTextEditor/Toolbar/Labels.js +1 -0
  80. package/dist/RichTextEditor/Toolbar/Toolbar.d.ts +1 -2
  81. package/dist/RichTextEditor/Toolbar/Toolbar.js +32 -67
  82. package/dist/RichTextEditor/Utils/codeBlockUtils.d.ts +20 -0
  83. package/dist/RichTextEditor/Utils/codeBlockUtils.js +137 -0
  84. package/dist/RichTextEditor/Utils/codeUtils.d.ts +3 -0
  85. package/dist/RichTextEditor/Utils/codeUtils.js +12 -0
  86. package/dist/RichTextEditor/Utils/linkUtils.d.ts +19 -0
  87. package/dist/RichTextEditor/Utils/linkUtils.js +57 -0
  88. package/dist/RichTextEditor/Utils/tableUtils.d.ts +1 -0
  89. package/dist/RichTextEditor/Utils/tableUtils.js +1 -0
  90. package/dist/theme/variants.js +46 -0
  91. package/package.json +8 -1
  92. package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +0 -7
  93. package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +0 -157
@@ -1,14 +1,17 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import styled, { useTheme } from "styled-components";
3
3
  import { Extensions } from "../Enums";
4
- import { BoldIcon, ItalicIcon, UnderlineIcon, CaseSensitiveIcon, ListIcon, ListOrderedIcon, StrikethroughIcon, Heading1Icon, Heading2Icon, Heading3Icon, Heading4Icon, RemoveFormattingIcon, SquircleIcon, } from "lucide-react";
4
+ import { BoldIcon, CodeIcon, ItalicIcon, UnderlineIcon, CaseSensitiveIcon, ListIcon, ListOrderedIcon, SquareCodeIcon, StrikethroughIcon, Heading1Icon, Heading2Icon, Heading3Icon, Heading4Icon, HighlighterIcon, LinkIcon, PaletteIcon, RemoveFormattingIcon, SquircleIcon, } from "lucide-react";
5
5
  import { DropDownMenu, } from "../../DropDownMenu";
6
- import { FloatingPortal, useFloating } from "@floating-ui/react";
7
- import { useEffect, useRef } from "react";
6
+ import { useEffect, useState } from "react";
8
7
  import { Button } from "../../Button";
9
8
  import TextColors from "../Enums/TextColors";
10
- const getMenuItems = (editor, customMenuItems, theme) => {
11
- var _a, _b, _c, _d, _e, _f, _g;
9
+ import HighlightColors from "../Enums/HighlightColors";
10
+ import LinkEditor from "./LinkEditor";
11
+ import { hasInlineCode, toggleInlineCode } from "../Utils/codeUtils";
12
+ import { hasSyntaxHighlightedCodeBlock, toggleCodeBlock, } from "../Utils/codeBlockUtils";
13
+ const getMenuItems = (editor, customMenuItems, theme, openLinkEditor) => {
14
+ var _a, _b, _c, _d, _e, _f, _g, _h;
12
15
  const node = (_c = (_b = (_a = editor === null || editor === void 0 ? void 0 : editor.state) === null || _a === void 0 ? void 0 : _a.selection) === null || _b === void 0 ? void 0 : _b.$from) === null || _c === void 0 ? void 0 : _c.parent;
13
16
  const pos = (_e = (_d = editor === null || editor === void 0 ? void 0 : editor.state) === null || _d === void 0 ? void 0 : _d.selection) === null || _e === void 0 ? void 0 : _e.$from;
14
17
  let withinUnorderedList = false;
@@ -24,6 +27,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
24
27
  }
25
28
  });
26
29
  const attrs = node === null || node === void 0 ? void 0 : node.attrs;
30
+ const supportsSyntaxCodeBlock = hasSyntaxHighlightedCodeBlock(editor);
31
+ const supportsInlineCode = hasInlineCode(editor);
32
+ const supportsColor = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "color"));
33
+ const supportsHighlight = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "highlight"));
34
+ const supportsLink = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "link"));
27
35
  let nodeTypeLabel = "Select Type";
28
36
  let nodeTypeIcon = null;
29
37
  if (withinOrderedList) {
@@ -38,7 +46,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
38
46
  nodeTypeLabel = "Text";
39
47
  nodeTypeIcon = _jsx(CaseSensitiveIcon, { size: 16 });
40
48
  }
41
- else if (((_g = node === null || node === void 0 ? void 0 : node.type) === null || _g === void 0 ? void 0 : _g.name) === "heading") {
49
+ else if (((_g = node === null || node === void 0 ? void 0 : node.type) === null || _g === void 0 ? void 0 : _g.name) === "codeBlock") {
50
+ nodeTypeLabel = "Code Block";
51
+ nodeTypeIcon = _jsx(SquareCodeIcon, { size: 16 });
52
+ }
53
+ else if (((_h = node === null || node === void 0 ? void 0 : node.type) === null || _h === void 0 ? void 0 : _h.name) === "heading") {
42
54
  const level = attrs === null || attrs === void 0 ? void 0 : attrs.level;
43
55
  nodeTypeLabel = `Heading ${level}`;
44
56
  nodeTypeIcon =
@@ -50,7 +62,6 @@ const getMenuItems = (editor, customMenuItems, theme) => {
50
62
  name: "node_type",
51
63
  label: nodeTypeLabel,
52
64
  type: "menu",
53
- arrow: true,
54
65
  buttonProps: {
55
66
  leftSection: nodeTypeIcon,
56
67
  style: { fontSize: 11, padding: "4px" },
@@ -62,13 +73,17 @@ const getMenuItems = (editor, customMenuItems, theme) => {
62
73
  data: {
63
74
  Icon: CaseSensitiveIcon,
64
75
  command: (editor) => {
65
- // remove ordered list
66
- editor
67
- .chain()
68
- .focus()
69
- .liftListItem("listItem")
70
- .setParagraph()
71
- .run();
76
+ if (editor.isActive("bulletList") ||
77
+ editor.isActive("orderedList")) {
78
+ editor
79
+ .chain()
80
+ .focus()
81
+ .liftListItem("listItem")
82
+ .setParagraph()
83
+ .run();
84
+ return;
85
+ }
86
+ editor.chain().focus().setParagraph().run();
72
87
  },
73
88
  },
74
89
  },
@@ -132,50 +147,107 @@ const getMenuItems = (editor, customMenuItems, theme) => {
132
147
  },
133
148
  },
134
149
  },
150
+ ...(supportsSyntaxCodeBlock
151
+ ? [
152
+ {
153
+ label: "Code Block",
154
+ value: "code_block",
155
+ data: {
156
+ Icon: SquareCodeIcon,
157
+ command: (editor) => {
158
+ toggleCodeBlock(editor);
159
+ },
160
+ },
161
+ },
162
+ ]
163
+ : []),
135
164
  ],
136
165
  dropDownProps: {
137
166
  renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(item.data.Icon, { size: 16 }), item.label] })),
138
167
  },
139
168
  },
140
- {
141
- name: "color",
142
- label: "Color",
143
- type: "menu",
144
- arrow: true,
145
- buttonProps: {
146
- // leftSection: nodeTypeIcon,
147
- style: { fontSize: 11, padding: "4px" },
148
- },
149
- items: [
169
+ ...(supportsColor
170
+ ? [
150
171
  {
151
- label: "Default",
152
- value: "default",
153
- onClick: () => {
154
- editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetColor().run();
172
+ name: "color",
173
+ label: _jsx(PaletteIcon, { size: 14 }),
174
+ type: "menu",
175
+ buttonProps: {
176
+ style: { padding: "1px 6px" },
177
+ },
178
+ items: [
179
+ {
180
+ label: "Default",
181
+ value: "default",
182
+ onClick: () => {
183
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetColor().run();
184
+ },
185
+ },
186
+ ...Object.keys(TextColors).map((color) => {
187
+ const colorKey = color;
188
+ return {
189
+ label: color,
190
+ value: TextColors[colorKey],
191
+ onClick: () => {
192
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().setColor(TextColors[colorKey]).run();
193
+ },
194
+ };
195
+ }),
196
+ ],
197
+ dropDownProps: {
198
+ renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
199
+ ? theme.palette.text.primary
200
+ : item.value, style: {
201
+ backgroundColor: item.value === "default"
202
+ ? theme.palette.text.primary
203
+ : item.value,
204
+ borderRadius: "3px",
205
+ } }), item.label] })),
155
206
  },
156
207
  },
157
- ...Object.keys(TextColors).map((color) => {
158
- const colorKey = color;
159
- return {
160
- label: color,
161
- value: TextColors[colorKey],
162
- onClick: () => {
163
- editor === null || editor === void 0 ? void 0 : editor.chain().focus().setColor(TextColors[colorKey]).run();
208
+ ]
209
+ : []),
210
+ ...(supportsHighlight
211
+ ? [
212
+ {
213
+ name: Extensions.Highlight,
214
+ label: _jsx(HighlighterIcon, { size: 14 }),
215
+ type: "menu",
216
+ buttonProps: {
217
+ style: { padding: "1px 6px" },
218
+ },
219
+ items: [
220
+ {
221
+ label: "Default",
222
+ value: "default",
223
+ onClick: () => {
224
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetHighlight().run();
225
+ },
164
226
  },
165
- };
166
- }),
167
- ],
168
- dropDownProps: {
169
- renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
170
- ? theme.palette.text.primary
171
- : item.value, style: {
172
- backgroundColor: item.value === "default"
173
- ? theme.palette.text.primary
174
- : item.value,
175
- borderRadius: "3px",
176
- } }), item.label] })),
177
- },
178
- },
227
+ ...Object.keys(HighlightColors).map((color) => {
228
+ const colorKey = color;
229
+ return {
230
+ label: color,
231
+ value: HighlightColors[colorKey],
232
+ onClick: () => {
233
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().setHighlight({ color: HighlightColors[colorKey] }).run();
234
+ },
235
+ };
236
+ }),
237
+ ],
238
+ dropDownProps: {
239
+ renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
240
+ ? theme.palette.text.primary
241
+ : item.value, style: {
242
+ backgroundColor: item.value === "default"
243
+ ? "transparent"
244
+ : item.value,
245
+ borderRadius: "3px",
246
+ } }), item.label] })),
247
+ },
248
+ },
249
+ ]
250
+ : []),
179
251
  {
180
252
  name: Extensions.Bold,
181
253
  icon: BoldIcon,
@@ -212,6 +284,45 @@ const getMenuItems = (editor, customMenuItems, theme) => {
212
284
  editor.chain().focus().toggleStrike().run();
213
285
  },
214
286
  },
287
+ ...(supportsLink
288
+ ? [
289
+ {
290
+ name: Extensions.Link,
291
+ icon: LinkIcon,
292
+ type: "button",
293
+ isActive: (editor) => editor.isActive("link"),
294
+ onClick: () => {
295
+ openLinkEditor();
296
+ },
297
+ },
298
+ ]
299
+ : []),
300
+ ...(supportsInlineCode
301
+ ? [
302
+ {
303
+ name: Extensions.Code,
304
+ icon: CodeIcon,
305
+ type: "button",
306
+ isActive: (editor) => editor.isActive("code"),
307
+ onClick: (editor) => {
308
+ toggleInlineCode(editor);
309
+ },
310
+ },
311
+ ]
312
+ : []),
313
+ ...(supportsSyntaxCodeBlock
314
+ ? [
315
+ {
316
+ name: Extensions.CodeBlock,
317
+ icon: SquareCodeIcon,
318
+ type: "button",
319
+ isActive: (editor) => editor.isActive("codeBlock"),
320
+ onClick: (editor) => {
321
+ toggleCodeBlock(editor);
322
+ },
323
+ },
324
+ ]
325
+ : []),
215
326
  {
216
327
  name: Extensions.ClearFormatting,
217
328
  icon: RemoveFormattingIcon,
@@ -224,12 +335,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
224
335
  ];
225
336
  };
226
337
  const BubbleMenuContent = styled.div `
227
- position: fixed;
228
338
  display: flex;
229
339
  justify-content: space-between;
230
340
  align-items: center;
231
341
  padding: 2px;
232
- gap: 2px;
342
+ gap: 4px;
233
343
 
234
344
  color: ${({ theme }) => theme.palette.text.primary};
235
345
  background-color: ${({ theme }) => theme.palette.input.background};
@@ -245,6 +355,11 @@ const BubbleMenuContent = styled.div `
245
355
  transform: scale(0.25); /* Start at half size */
246
356
  animation: fadeInEffect 90ms forwards;
247
357
 
358
+ button {
359
+ min-width: 28px;
360
+ min-height: 28px;
361
+ }
362
+
248
363
  /* Animation to handle the fade in */
249
364
  @keyframes fadeInEffect {
250
365
  0% {
@@ -261,7 +376,8 @@ const BubbleItemButton = styled(Button) `
261
376
  font-size: 0.5rem;
262
377
  font-weight: 500;
263
378
  padding: 4px;
264
- height: auto;
379
+ height: 28px;
380
+ width: 28px;
265
381
 
266
382
  &.is-active {
267
383
  opacity: 1;
@@ -272,51 +388,43 @@ const BubbleItemButton = styled(Button) `
272
388
  background-color: ${({ theme }) => theme.palette.action.hover};
273
389
  }
274
390
  `;
275
- const BubbleMenu = ({ editor, rect, open, onOpen, customMenuItems = [], }) => {
276
- var _a;
277
- const menuRef = useRef(null);
278
- const { refs, elements } = useFloating();
391
+ const CodeBlockBubbleTools = ({ editor, theme, }) => {
392
+ const nodeTypeMenu = getMenuItems(editor, [], theme, () => undefined).find((item) => item.name === "node_type");
393
+ return (_jsx(_Fragment, { children: (nodeTypeMenu === null || nodeTypeMenu === void 0 ? void 0 : nodeTypeMenu.type) === "menu" && (_jsx(DropDownMenu, Object.assign({ data: nodeTypeMenu.items, size: "xs", arrow: nodeTypeMenu.arrow, buttonProps: nodeTypeMenu.buttonProps, variant: "subtle", buttonRender: nodeTypeMenu.buttonRender, onItemSelect: (item) => { var _a, _b; return (_b = (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.command) === null || _b === void 0 ? void 0 : _b.call(_a, editor, ""); }, dropDownProps: {
394
+ style: { width: 135 },
395
+ } }, nodeTypeMenu.dropDownProps, { children: nodeTypeMenu.icon
396
+ ? (_jsx(nodeTypeMenu.icon, { size: 14 }))
397
+ : (nodeTypeMenu.label || nodeTypeMenu.name) }))) }));
398
+ };
399
+ const BubbleMenu = ({ className, editor, customMenuItems = [], }) => {
279
400
  const theme = useTheme();
280
- useEffect(() => {
281
- if (open && onOpen) {
282
- onOpen(elements.floating);
283
- }
284
- }, [open, onOpen, elements.floating]);
285
- const elementWidth = ((_a = elements.floating) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0;
401
+ const [linkEditorOpen, setLinkEditorOpen] = useState(false);
286
402
  const { from, to } = editor.state.selection;
287
403
  const selectedText = editor.state.doc.textBetween(from, to, "\n", "\n");
288
- let top = (rect === null || rect === void 0 ? void 0 : rect.top) ? rect.top - 50 : 0;
289
- if (top < 10) {
290
- top = 10; // add some padding
291
- }
292
- let left = (rect === null || rect === void 0 ? void 0 : rect.left) ? rect.left + rect.width / 2 - elementWidth / 2 : 0;
293
- if (left < 10) {
294
- left = 10; // add some padding
404
+ const isLinkSelection = editor.isActive("link");
405
+ const isCodeBlockSelection = editor.isActive("codeBlock") && hasSyntaxHighlightedCodeBlock(editor);
406
+ useEffect(() => {
407
+ setLinkEditorOpen(false);
408
+ }, [from, to]);
409
+ if (isLinkSelection || linkEditorOpen) {
410
+ return (_jsx(BubbleMenuContent, { className: className, children: _jsx(LinkEditor, { editor: editor, autoFocus: true, onClose: () => setLinkEditorOpen(false) }) }));
295
411
  }
296
- // Check if the menu is overflowing on the right
297
- const rightOverflow = left + elementWidth - window.innerWidth;
298
- if (rightOverflow > -10) {
299
- left -= rightOverflow + 10; // add some padding
412
+ if (isCodeBlockSelection) {
413
+ return (_jsx(BubbleMenuContent, { className: className, children: _jsx(CodeBlockBubbleTools, { editor: editor, theme: theme }) }));
300
414
  }
301
- return (_jsx(FloatingPortal, { preserveTabOrder: true, children: open && (_jsx(BubbleMenuContent, { ref: (ref) => {
302
- refs.setFloating(ref);
303
- menuRef.current = ref;
304
- }, style: {
305
- top,
306
- left,
307
- }, children: getMenuItems(editor, customMenuItems, theme).map((item) => {
308
- var _a;
309
- if (item.type === "button") {
310
- const isActive = (_a = item.isActive) === null || _a === void 0 ? void 0 : _a.call(item, editor);
311
- return (_jsx(BubbleItemButton, { variant: "subtle", onClick: () => { var _a; return (_a = item === null || item === void 0 ? void 0 : item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, editor); }, color: isActive ? "primary" : undefined, selected: isActive, children: item.icon && _jsx(item.icon, { size: 14 }) }, item.name));
312
- }
313
- if (item.type === "menu") {
314
- return (_jsx(DropDownMenu, Object.assign({ data: item.items, size: "xs", arrow: item.arrow, buttonProps: item.buttonProps, variant: "subtle", buttonRender: item.buttonRender, onItemSelect: (item) => { var _a, _b; return (_b = (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.command) === null || _b === void 0 ? void 0 : _b.call(_a, editor, selectedText); }, dropDownProps: {
315
- style: { width: 135 },
316
- } }, item.dropDownProps, { children: item.icon
317
- ? (_jsx(item.icon, { size: 14 }))
318
- : (item.label || item.name) }), item.name));
319
- }
320
- }) })) }));
415
+ return (_jsx(BubbleMenuContent, { className: className, children: getMenuItems(editor, customMenuItems, theme, () => setLinkEditorOpen(true)).map((item) => {
416
+ var _a;
417
+ if (item.type === "button") {
418
+ const isActive = (_a = item.isActive) === null || _a === void 0 ? void 0 : _a.call(item, editor);
419
+ return (_jsx(BubbleItemButton, { variant: "subtle", onClick: () => { var _a; return (_a = item === null || item === void 0 ? void 0 : item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, editor); }, color: isActive ? "primary" : undefined, selected: isActive, children: item.icon && _jsx(item.icon, { size: 14 }) }, item.name));
420
+ }
421
+ if (item.type === "menu") {
422
+ return (_jsx(DropDownMenu, Object.assign({ data: item.items, size: "xs", arrow: item.arrow, buttonProps: item.buttonProps, variant: "subtle", buttonRender: item.buttonRender, onItemSelect: (item) => { var _a, _b; return (_b = (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.command) === null || _b === void 0 ? void 0 : _b.call(_a, editor, selectedText); }, dropDownProps: {
423
+ style: { width: 135 },
424
+ } }, item.dropDownProps, { children: item.icon
425
+ ? (_jsx(item.icon, { size: 14 }))
426
+ : (item.label || item.name) }), item.name));
427
+ }
428
+ }) }));
321
429
  };
322
430
  export default BubbleMenu;
@@ -0,0 +1,18 @@
1
+ export declare const CodeBlockBaseButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").ButtonHTMLAttributes<HTMLButtonElement> & {
2
+ ref?: import("react").RefObject<HTMLButtonElement>;
3
+ children?: import("react").ReactNode | string;
4
+ className?: string;
5
+ loading?: boolean;
6
+ leftSection?: import("react").ReactNode;
7
+ rightSection?: import("react").ReactNode;
8
+ href?: string | null;
9
+ download?: string | null;
10
+ fullWidth?: boolean;
11
+ size?: import("../../core").Size;
12
+ variant?: import("../../core").Variant;
13
+ color?: import("../../Button").ButtonColor;
14
+ disabled?: boolean;
15
+ selected?: boolean;
16
+ justify?: "start" | "center" | "end";
17
+ onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
18
+ }, never>> & string & Omit<import("react").FC<import("../../Button").ButtonProps>, keyof import("react").Component<any, {}, any>>;
@@ -0,0 +1,6 @@
1
+ import styled from "styled-components";
2
+ import { Button } from "../../Button";
3
+ export const CodeBlockBaseButton = styled(Button) `
4
+ padding: 5px;
5
+ background-color: ${({ theme }) => theme.palette.background.paper};
6
+ `;
@@ -0,0 +1,9 @@
1
+ import { Editor } from "@tiptap/react";
2
+ type CodeBlockCopyButtonProps = {
3
+ className?: string;
4
+ editor?: Editor | null;
5
+ text?: string;
6
+ size?: "xs" | "sm";
7
+ };
8
+ declare const CodeBlockCopyButton: ({ className, editor, text, size, }: CodeBlockCopyButtonProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default CodeBlockCopyButton;
@@ -0,0 +1,42 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { useEffect, useState } from "react";
12
+ import { CheckIcon, CopyIcon } from "lucide-react";
13
+ import { copyCodeBlockText, getActiveCodeBlockText, } from "../Utils/codeBlockUtils";
14
+ import { CodeBlockBaseButton } from "./CodeBlockBaseButton";
15
+ const CodeBlockCopyButton = ({ className, editor, text, size = "xs", }) => {
16
+ const [copied, setCopied] = useState(false);
17
+ const [copyFailed, setCopyFailed] = useState(false);
18
+ const code = text !== null && text !== void 0 ? text : getActiveCodeBlockText(editor || null);
19
+ useEffect(() => {
20
+ if (!copied && !copyFailed)
21
+ return;
22
+ const timeout = window.setTimeout(() => {
23
+ setCopied(false);
24
+ setCopyFailed(false);
25
+ }, 1400);
26
+ return () => window.clearTimeout(timeout);
27
+ }, [copied, copyFailed]);
28
+ return (_jsx(CodeBlockBaseButton, { className: className, size: size, variant: "outlined", title: copyFailed ? "Unable to copy" : copied ? "Copied" : "Copy code", "aria-label": copyFailed ? "Unable to copy code" : copied ? "Copied" : "Copy code", disabled: !code, onClick: (event) => __awaiter(void 0, void 0, void 0, function* () {
29
+ event.preventDefault();
30
+ event.stopPropagation();
31
+ try {
32
+ yield copyCodeBlockText(code);
33
+ setCopied(true);
34
+ setCopyFailed(false);
35
+ }
36
+ catch (_a) {
37
+ setCopied(false);
38
+ setCopyFailed(true);
39
+ }
40
+ }), children: copied ? _jsx(CheckIcon, { size: 14 }) : _jsx(CopyIcon, { size: 14 }) }));
41
+ };
42
+ export default CodeBlockCopyButton;
@@ -0,0 +1,10 @@
1
+ import { Editor } from "@tiptap/react";
2
+ type CodeBlockFormatButtonProps = {
3
+ className?: string;
4
+ editor?: Editor | null;
5
+ language?: string;
6
+ onFormat?: () => Promise<void>;
7
+ size?: "xs" | "sm";
8
+ };
9
+ declare const CodeBlockFormatButton: ({ className, editor, language, onFormat, size, }: CodeBlockFormatButtonProps) => import("react/jsx-runtime").JSX.Element;
10
+ export default CodeBlockFormatButton;
@@ -0,0 +1,60 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { useEffect, useState } from "react";
12
+ import { CheckIcon, TriangleAlertIcon, WandSparklesIcon } from "lucide-react";
13
+ import { canFormatCodeBlockLanguage, formatActiveCodeBlock, getCodeBlockLanguage, } from "../Utils/codeBlockUtils";
14
+ import { CodeBlockBaseButton } from "./CodeBlockBaseButton";
15
+ const CodeBlockFormatButton = ({ className, editor, language, onFormat, size = "xs", }) => {
16
+ const [formatted, setFormatted] = useState(false);
17
+ const [formatFailed, setFormatFailed] = useState(false);
18
+ const codeLanguage = language !== null && language !== void 0 ? language : getCodeBlockLanguage(editor || null);
19
+ const canFormat = canFormatCodeBlockLanguage(codeLanguage);
20
+ useEffect(() => {
21
+ if (!formatted && !formatFailed)
22
+ return;
23
+ const timeout = window.setTimeout(() => {
24
+ setFormatted(false);
25
+ setFormatFailed(false);
26
+ }, 1400);
27
+ return () => window.clearTimeout(timeout);
28
+ }, [formatted, formatFailed]);
29
+ return (_jsx(CodeBlockBaseButton, { className: className, size: size, variant: "outlined", title: !canFormat
30
+ ? "Formatting is not supported for this language"
31
+ : formatFailed
32
+ ? "Unable to format code"
33
+ : formatted
34
+ ? "Formatted"
35
+ : "Format code", "aria-label": !canFormat
36
+ ? "Formatting is not supported for this language"
37
+ : formatFailed
38
+ ? "Unable to format code"
39
+ : formatted
40
+ ? "Formatted"
41
+ : "Format code", disabled: !canFormat || (!onFormat && !(editor === null || editor === void 0 ? void 0 : editor.isActive("codeBlock"))), onClick: (event) => __awaiter(void 0, void 0, void 0, function* () {
42
+ event.preventDefault();
43
+ event.stopPropagation();
44
+ try {
45
+ if (onFormat) {
46
+ yield onFormat();
47
+ }
48
+ else {
49
+ yield formatActiveCodeBlock(editor || null);
50
+ }
51
+ setFormatted(true);
52
+ setFormatFailed(false);
53
+ }
54
+ catch (_a) {
55
+ setFormatted(false);
56
+ setFormatFailed(true);
57
+ }
58
+ }), children: formatted ? (_jsx(CheckIcon, { size: 14 })) : formatFailed ? (_jsx(TriangleAlertIcon, { size: 14 })) : (_jsx(WandSparklesIcon, { size: 14 })) }));
59
+ };
60
+ export default CodeBlockFormatButton;
@@ -0,0 +1,9 @@
1
+ import { Editor } from "@tiptap/react";
2
+ type CodeBlockLanguageSelectProps = {
3
+ className?: string;
4
+ editor?: Editor | null;
5
+ language?: string;
6
+ onLanguageChange?: (language: string) => void;
7
+ };
8
+ declare const CodeBlockLanguageSelect: ({ className, editor, language, onLanguageChange, }: CodeBlockLanguageSelectProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default CodeBlockLanguageSelect;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CodeXmlIcon } from "lucide-react";
3
+ import { DropDownMenu } from "../../DropDownMenu";
4
+ import { CODE_BLOCK_LANGUAGES, getCodeBlockLanguage, getCodeBlockLanguageOption, setCodeBlockLanguage, } from "../Utils/codeBlockUtils";
5
+ import { useTheme } from "styled-components";
6
+ const CodeBlockLanguageSelect = ({ className, editor, language, onLanguageChange, }) => {
7
+ const theme = useTheme();
8
+ const codeLanguage = language !== null && language !== void 0 ? language : getCodeBlockLanguage(editor || null);
9
+ const selectedLanguage = getCodeBlockLanguageOption(codeLanguage);
10
+ return (_jsx(DropDownMenu, { className: className, data: CODE_BLOCK_LANGUAGES, value: [selectedLanguage], enableSelectedOptionStyling: true, size: "xs", variant: "outlined", disabled: !onLanguageChange && !(editor === null || editor === void 0 ? void 0 : editor.isActive("codeBlock")), onItemSelect: (item) => {
11
+ if (onLanguageChange) {
12
+ onLanguageChange(item.value);
13
+ return;
14
+ }
15
+ setCodeBlockLanguage(editor || null, item.value);
16
+ }, buttonProps: {
17
+ title: "Select code language",
18
+ leftSection: _jsx(CodeXmlIcon, { size: 12 }),
19
+ style: {
20
+ padding: "1px 6px",
21
+ backgroundColor: theme.palette.background.paper,
22
+ },
23
+ }, dropDownProps: {
24
+ style: {
25
+ width: 150,
26
+ height: 250,
27
+ },
28
+ }, children: selectedLanguage.label }));
29
+ };
30
+ export default CodeBlockLanguageSelect;
@@ -0,0 +1,3 @@
1
+ import { ReactNodeViewProps } from "@tiptap/react";
2
+ declare const CodeBlockNodeView: ({ editor, getPos, node, updateAttributes, }: ReactNodeViewProps) => import("react/jsx-runtime").JSX.Element;
3
+ export default CodeBlockNodeView;
@@ -0,0 +1,28 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { NodeViewContent, NodeViewWrapper, } from "@tiptap/react";
12
+ import CodeBlockCopyButton from "./CodeBlockCopyButton";
13
+ import CodeBlockWrapButton from "./CodeBlockWrapButton";
14
+ import CodeBlockFormatButton from "./CodeBlockFormatButton";
15
+ import CodeBlockLanguageSelect from "./CodeBlockLanguageSelect";
16
+ import { formatCodeBlockText, replaceCodeBlockContent, } from "../Utils/codeBlockUtils";
17
+ const CodeBlockNodeView = ({ editor, getPos, node, updateAttributes, }) => {
18
+ const language = node.attrs.language;
19
+ const wrap = Boolean(node.attrs.wrap);
20
+ return (_jsxs(NodeViewWrapper, { as: "pre", className: "editor-code-block", "data-language": language || "plaintext", "data-wrap": wrap ? "true" : "false", children: [_jsxs("div", { className: "editor-code-block-actions", contentEditable: false, children: [_jsx(CodeBlockLanguageSelect, { language: language, onLanguageChange: (language) => updateAttributes({ language }) }), _jsx(CodeBlockWrapButton, { active: wrap, onToggle: () => updateAttributes({ wrap: !wrap }) }), _jsx(CodeBlockFormatButton, { className: "editor-code-block-action", language: language, onFormat: () => __awaiter(void 0, void 0, void 0, function* () {
21
+ const pos = getPos();
22
+ if (typeof pos !== "number")
23
+ return;
24
+ const formatted = yield formatCodeBlockText(node.textContent, language);
25
+ replaceCodeBlockContent(editor, pos + 1, pos + node.nodeSize - 1, formatted);
26
+ }) }), _jsx(CodeBlockCopyButton, { className: "editor-code-block-action", text: node.textContent })] }), _jsx(NodeViewContent, { as: "code", className: `hljs language-${language || "plaintext"}`, spellCheck: false })] }));
27
+ };
28
+ export default CodeBlockNodeView;
@@ -0,0 +1,10 @@
1
+ import { Editor } from "@tiptap/react";
2
+ type CodeBlockWrapButtonProps = {
3
+ className?: string;
4
+ editor?: Editor | null;
5
+ active?: boolean;
6
+ onToggle?: () => void;
7
+ size?: "xs" | "sm";
8
+ };
9
+ declare const CodeBlockWrapButton: ({ className, editor, active, onToggle, size, }: CodeBlockWrapButtonProps) => import("react/jsx-runtime").JSX.Element;
10
+ export default CodeBlockWrapButton;