@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
@@ -8,17 +8,79 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
- import { useEffect, useRef, useState } from "react";
11
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
12
12
  import styled from "styled-components";
13
13
  import { EditorContent, useEditor } from "@tiptap/react";
14
+ import { BubbleMenu as TiptapBubbleMenu, } from "@tiptap/react/menus";
15
+ import { isTextSelection } from "@tiptap/core";
14
16
  import { DOMParser as ProseMirrorDOMParser } from "@tiptap/pm/model";
17
+ import { TextSelection } from "@tiptap/pm/state";
15
18
  import { Toolbar } from "./Toolbar";
16
- import getTipTapExtensions from "./Extensions/getTiptapExtensions";
17
- import { Extensions, SlashCommands } from "./Enums";
19
+ import getTipTapExtensions, { resolveExtensions, } from "./Extensions/getTiptapExtensions";
20
+ import { Controls, Extensions, SlashCommands } from "./Enums";
18
21
  import { addImagePlaceholder, removeImagePlaceholder, startImageUpload, } from "./Plugins/UploadImagesPlugin";
19
22
  import SaveBadge from "./Components/SaveBadge";
23
+ import BubbleMenuContent from "./Components/BubbleMenu";
24
+ import { TableRails } from "./Components/TableTools";
20
25
  import Fonts from "./Enums/Fonts";
21
26
  import RichTextEditorContext from "./Contexts/RichTextEditorContext";
27
+ import { getLinkAttributesAtPosition, getLinkRangeAtPosition, openLink, } from "./Utils/linkUtils";
28
+ import { TABLE_CELL_MIN_WIDTH } from "./Utils/tableUtils";
29
+ const codeBlockFallbacks = {
30
+ light: {
31
+ background: "#f6f8fa",
32
+ text: "#24292f",
33
+ border: "#d0d7de",
34
+ selection: "#0969da2e",
35
+ syntax: {
36
+ comment: "#6e7781",
37
+ punctuation: "#24292f",
38
+ property: "#0550ae",
39
+ selector: "#116329",
40
+ operator: "#cf222e",
41
+ keyword: "#cf222e",
42
+ string: "#0a3069",
43
+ number: "#0550ae",
44
+ function: "#8250df",
45
+ variable: "#953800",
46
+ tag: "#116329",
47
+ attribute: "#0550ae",
48
+ literal: "#0550ae",
49
+ deleted: "#82071e",
50
+ inserted: "#116329",
51
+ },
52
+ },
53
+ dark: {
54
+ background: "#0d1117",
55
+ text: "#c9d1d9",
56
+ border: "#30363d",
57
+ selection: "#1f6feb40",
58
+ syntax: {
59
+ comment: "#8b949e",
60
+ punctuation: "#c9d1d9",
61
+ property: "#79c0ff",
62
+ selector: "#7ee787",
63
+ operator: "#ff7b72",
64
+ keyword: "#ff7b72",
65
+ string: "#a5d6ff",
66
+ number: "#79c0ff",
67
+ function: "#d2a8ff",
68
+ variable: "#ffa657",
69
+ tag: "#7ee787",
70
+ attribute: "#79c0ff",
71
+ literal: "#79c0ff",
72
+ deleted: "#ffa198",
73
+ inserted: "#aff5b4",
74
+ },
75
+ },
76
+ };
77
+ const getCodeBlockTheme = (theme) => {
78
+ if (theme.palette.codeBlock)
79
+ return theme.palette.codeBlock;
80
+ return theme.palette.mode === "DARK"
81
+ ? codeBlockFallbacks.dark
82
+ : codeBlockFallbacks.light;
83
+ };
22
84
  const getImageFilesFromClipboard = (clipboardData) => {
23
85
  return Array.from(clipboardData.files).filter((file) => file.type.includes("image/"));
24
86
  };
@@ -272,25 +334,86 @@ const StyledContent = styled.div `
272
334
  word-break: break-word;
273
335
  text-rendering: optimizeLegibility;
274
336
 
337
+ .tableWrapper {
338
+ max-width: 100%;
339
+ overflow-x: auto;
340
+ padding: 5px 0px;
341
+ cursor: default;
342
+
343
+ table {
344
+ cursor: text;
345
+ }
346
+ }
347
+
275
348
  table {
276
349
  border-collapse: collapse;
350
+ table-layout: fixed;
277
351
  width: 100%;
352
+ overflow: hidden;
278
353
 
279
354
  th,
280
355
  td {
281
356
  border: 1px solid ${({ theme }) => theme.palette.divider};
357
+ box-sizing: border-box;
282
358
  padding: 0.5rem;
283
- min-width: 100px;
359
+ min-width: ${TABLE_CELL_MIN_WIDTH}px;
360
+ position: relative;
361
+ vertical-align: top;
284
362
  }
285
363
 
286
364
  // for table header
287
365
  th {
288
366
  border: 1px solid ${({ theme }) => theme.palette.divider};
289
367
  padding: 0.5rem;
290
- min-width: 100px;
368
+ min-width: ${TABLE_CELL_MIN_WIDTH}px;
291
369
  background-color: ${({ theme }) => theme.palette.action.hover};
292
370
  font-weight: 500;
293
371
  }
372
+
373
+ [align="left"] {
374
+ text-align: left;
375
+ }
376
+
377
+ [align="center"] {
378
+ text-align: center;
379
+ }
380
+
381
+ [align="right"] {
382
+ text-align: right;
383
+ }
384
+ }
385
+
386
+ .column-resize-handle {
387
+ position: absolute;
388
+ top: 0;
389
+ right: -1px;
390
+ bottom: 0;
391
+ z-index: 20;
392
+ width: 2px;
393
+ background-color: ${({ theme }) => theme.palette.primary.main};
394
+ pointer-events: none;
395
+ }
396
+
397
+ &.resize-cursor {
398
+ cursor: col-resize;
399
+ }
400
+
401
+ .selectedCell::after {
402
+ position: absolute;
403
+ inset: 0;
404
+ z-index: 2;
405
+ background-color: ${({ theme }) => theme.palette.primary.main}22;
406
+ content: "";
407
+ pointer-events: none;
408
+ }
409
+
410
+ .monolith-table-rail-target::after {
411
+ position: absolute;
412
+ inset: 0;
413
+ z-index: 3;
414
+ background-color: ${({ theme }) => theme.palette.primary.main}18;
415
+ content: "";
416
+ pointer-events: none;
294
417
  }
295
418
 
296
419
  h1 {
@@ -317,6 +440,158 @@ const StyledContent = styled.div `
317
440
  margin: 0;
318
441
  line-height: 1.5rem;
319
442
  }
443
+ .editor-inline-code,
444
+ :not(pre) > code {
445
+ padding: 0.1rem 0.25rem;
446
+ border: 1px solid ${({ theme }) => theme.palette.divider};
447
+ border-radius: 4px;
448
+ background-color: ${({ theme }) => theme.palette.action.hover};
449
+ color: ${({ theme }) => theme.palette.text.secondary};
450
+ font-family:
451
+ ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas,
452
+ "Liberation Mono", "Courier New", monospace;
453
+ font-size: 0.9em;
454
+ box-decoration-break: clone;
455
+ }
456
+ .editor-code-block {
457
+ position: relative;
458
+ margin: 0.5rem 0;
459
+ padding: 1rem 0.875rem;
460
+ overflow-x: auto;
461
+ border: 1px solid ${({ theme }) => getCodeBlockTheme(theme).border};
462
+ border-radius: 6px;
463
+ background-color: ${({ theme }) => getCodeBlockTheme(theme).background};
464
+ color: ${({ theme }) => getCodeBlockTheme(theme).text};
465
+ font-family:
466
+ ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas,
467
+ "Liberation Mono", "Courier New", monospace;
468
+ font-size: 0.85rem;
469
+ line-height: 1.45rem;
470
+ white-space: pre;
471
+
472
+ ::selection {
473
+ background-color: ${({ theme }) => getCodeBlockTheme(theme).selection};
474
+ }
475
+
476
+ &[data-wrap="true"] {
477
+ white-space: pre-wrap;
478
+ word-break: break-word;
479
+ overflow-wrap: anywhere;
480
+ }
481
+
482
+ code {
483
+ display: block;
484
+ min-width: max-content;
485
+ padding: 0;
486
+ border: 0;
487
+ background-color: transparent;
488
+ color: inherit;
489
+ font: inherit;
490
+ }
491
+
492
+ &[data-wrap="true"] code {
493
+ min-width: 0;
494
+ white-space: inherit;
495
+ }
496
+
497
+ .editor-code-block-actions {
498
+ display: flex;
499
+ align-items: center;
500
+ position: absolute;
501
+ top: 0.4rem;
502
+ right: 0.4rem;
503
+ z-index: 1;
504
+ gap: 0.25rem;
505
+ opacity: 0;
506
+ transition: opacity 120ms ease-in-out;
507
+ }
508
+
509
+ &:hover .editor-code-block-actions,
510
+ &:focus-within .editor-code-block-actions {
511
+ opacity: 1;
512
+ }
513
+
514
+ .hljs-comment,
515
+ .hljs-quote {
516
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.comment};
517
+ }
518
+
519
+ .hljs-punctuation {
520
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.punctuation};
521
+ }
522
+
523
+ .hljs-property,
524
+ .hljs-attr,
525
+ .hljs-attribute,
526
+ .hljs-doctag {
527
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.property};
528
+ }
529
+
530
+ .hljs-selector-tag,
531
+ .hljs-selector-id,
532
+ .hljs-selector-class,
533
+ .hljs-selector-attr,
534
+ .hljs-selector-pseudo {
535
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.selector};
536
+ }
537
+
538
+ .hljs-operator,
539
+ .hljs-params {
540
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.operator};
541
+ }
542
+
543
+ .hljs-keyword,
544
+ .hljs-meta .hljs-keyword,
545
+ .hljs-template-tag,
546
+ .hljs-template-variable {
547
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.keyword};
548
+ }
549
+
550
+ .hljs-string,
551
+ .hljs-regexp {
552
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.string};
553
+ }
554
+
555
+ .hljs-number {
556
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.number};
557
+ }
558
+
559
+ .hljs-title,
560
+ .hljs-title.function_,
561
+ .hljs-title.class_ {
562
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.function};
563
+ }
564
+
565
+ .hljs-variable,
566
+ .hljs-name,
567
+ .hljs-section,
568
+ .hljs-symbol {
569
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.variable};
570
+ }
571
+
572
+ .hljs-tag {
573
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.tag};
574
+ }
575
+
576
+ .hljs-built_in,
577
+ .hljs-type,
578
+ .hljs-literal {
579
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.literal};
580
+ }
581
+
582
+ .hljs-meta,
583
+ .hljs-link {
584
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.attribute};
585
+ }
586
+
587
+ .hljs-deletion {
588
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.deleted};
589
+ }
590
+
591
+ .hljs-addition {
592
+ color: ${({ theme }) => getCodeBlockTheme(theme).syntax.inserted};
593
+ }
594
+ }
320
595
  ul {
321
596
  margin: 0;
322
597
  }
@@ -330,8 +605,6 @@ const StyledContent = styled.div `
330
605
  color: ${({ theme }) => theme.palette.text.primary};
331
606
  text-decoration: underline;
332
607
  cursor: pointer;
333
- // Set title attribute
334
- title: "Click to open link";
335
608
  }
336
609
  img {
337
610
  max-width: 100%;
@@ -349,6 +622,7 @@ const StyledContent = styled.div `
349
622
  color: #888;
350
623
  pointer-events: none;
351
624
  height: 0;
625
+ white-space: nowrap;
352
626
  }
353
627
  .ProseMirror .is-empty::before {
354
628
  content: attr(data-placeholder);
@@ -356,6 +630,7 @@ const StyledContent = styled.div `
356
630
  color: #888;
357
631
  pointer-events: none;
358
632
  height: 0;
633
+ white-space: nowrap;
359
634
  }
360
635
 
361
636
  .ProseMirror .monolith-image.uploading {
@@ -543,16 +818,104 @@ const StyledContent = styled.div `
543
818
  margin: 0 0.125rem;
544
819
  }
545
820
  `;
546
- export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = "", value, readOnly = false, font, showToolbar = true, saving = false, extensions = [], slashCommands = [], bubbleMenuOptions, toolbarOptions, autoFocus, onChange, handleImageUpload, handleImageUrlUpload, style, }) => {
821
+ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = "", value, readOnly = false, font, showToolbar = true, saving = false, disabledExtensions = [], extensionPreset = "basic", extensions = [], slashCommands = [], bubbleMenuOptions, toolbarOptions, autoFocus, onChange, handleImageUpload, handleImageUrlUpload, style, }) => {
822
+ const resolvedExtensions = useMemo(() => resolveExtensions({
823
+ disabledExtensions,
824
+ extensionPreset,
825
+ extensions,
826
+ }), [disabledExtensions, extensionPreset, extensions]);
827
+ const resolvedExtensionSet = useMemo(() => new Set(resolvedExtensions), [resolvedExtensions]);
828
+ const resolvedSlashCommands = useMemo(() => slashCommands.filter((command) => {
829
+ if (command === SlashCommands.Code) {
830
+ return resolvedExtensionSet.has(Extensions.Code);
831
+ }
832
+ if (command === SlashCommands.CodeBlock) {
833
+ return resolvedExtensionSet.has(Extensions.CodeBlock);
834
+ }
835
+ if (command === SlashCommands.Table) {
836
+ return resolvedExtensionSet.has(Extensions.Table);
837
+ }
838
+ return true;
839
+ }), [resolvedExtensionSet, slashCommands]);
840
+ const resolvedToolbarOptions = useMemo(() => {
841
+ if (!(toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.controls))
842
+ return toolbarOptions;
843
+ const controlExtensionMap = {
844
+ [Controls.BOLD]: Extensions.Bold,
845
+ [Controls.ITALIC]: Extensions.Italic,
846
+ [Controls.UNDERLINE]: Extensions.Underline,
847
+ [Controls.STRIKE]: Extensions.Strike,
848
+ [Controls.CODE]: Extensions.Code,
849
+ [Controls.CODE_BLOCK]: Extensions.CodeBlock,
850
+ [Controls.BULLET_LIST]: Extensions.BulletList,
851
+ [Controls.ORDERED_LIST]: Extensions.OrderedList,
852
+ [Controls.COLOR]: Extensions.Color,
853
+ [Controls.HIGHLIGHT]: Extensions.Highlight,
854
+ [Controls.LINK]: Extensions.Link,
855
+ [Controls.TEXT_ALIGN_LEFT]: Extensions.TextAlign,
856
+ [Controls.TEXT_ALIGN_CENTER]: Extensions.TextAlign,
857
+ [Controls.TEXT_ALIGN_RIGHT]: Extensions.TextAlign,
858
+ [Controls.TEXT_ALIGN_JUSTIFIED]: Extensions.TextAlign,
859
+ [Controls.TABLE]: Extensions.Table,
860
+ };
861
+ return Object.assign(Object.assign({}, toolbarOptions), { controls: toolbarOptions.controls.filter((control) => {
862
+ if (typeof control !== "string")
863
+ return true;
864
+ const extension = controlExtensionMap[control];
865
+ return !extension || resolvedExtensionSet.has(extension);
866
+ }) });
867
+ }, [resolvedExtensionSet, toolbarOptions]);
547
868
  const isControlled = value !== undefined;
548
- const hasImageExtension = extensions.includes(Extensions.Image);
549
- const hasSlashCommandExtension = extensions.includes(Extensions.SlashCommand);
550
- const hasImageSlashCommand = hasSlashCommandExtension && slashCommands.includes(SlashCommands.Image);
869
+ const hasImageExtension = resolvedExtensionSet.has(Extensions.Image);
870
+ const hasSlashCommandExtension = resolvedExtensionSet.has(Extensions.SlashCommand);
871
+ const hasBubbleMenuExtension = resolvedExtensionSet.has(Extensions.BubbleMenu);
872
+ const hasTableExtension = resolvedExtensionSet.has(Extensions.Table);
873
+ const hasImageSlashCommand = hasSlashCommandExtension &&
874
+ resolvedSlashCommands.includes(SlashCommands.Image);
551
875
  const onChangeRef = useRef(onChange);
876
+ const bubbleMenuPortalRef = useRef(null);
552
877
  const [fontState, setFontState] = useState(font || Fonts.DEFAULT);
553
878
  useEffect(() => {
554
879
  onChangeRef.current = onChange;
555
880
  }, [onChange]);
881
+ const getBubbleMenuPortalRoot = useCallback(() => {
882
+ if (bubbleMenuPortalRef.current) {
883
+ return bubbleMenuPortalRef.current;
884
+ }
885
+ const portal = document.createElement("div");
886
+ portal.setAttribute("data-monolith-bubble-menu-portal", "");
887
+ document.body.appendChild(portal);
888
+ bubbleMenuPortalRef.current = portal;
889
+ return portal;
890
+ }, []);
891
+ useEffect(() => {
892
+ return () => {
893
+ var _a;
894
+ (_a = bubbleMenuPortalRef.current) === null || _a === void 0 ? void 0 : _a.remove();
895
+ bubbleMenuPortalRef.current = null;
896
+ };
897
+ }, []);
898
+ const shouldShowBubbleMenu = useCallback(({ editor, element, view, state, from, to }) => {
899
+ const { selection } = state;
900
+ const isChildOfMenu = element.contains(document.activeElement);
901
+ const hasEditorFocus = view.hasFocus() || isChildOfMenu;
902
+ const selectedText = state.doc.textBetween(from, to).trim();
903
+ const isEmptyTextBlock = !selectedText && isTextSelection(state.selection);
904
+ if (!hasEditorFocus ||
905
+ selection.empty ||
906
+ isEmptyTextBlock ||
907
+ !editor.isEditable) {
908
+ return false;
909
+ }
910
+ return true;
911
+ }, []);
912
+ const bubbleMenuPositionOptions = useMemo(() => ({
913
+ strategy: "fixed",
914
+ placement: "top",
915
+ offset: 8,
916
+ flip: false,
917
+ shift: { padding: 10 },
918
+ }), []);
556
919
  if (hasImageSlashCommand && !hasImageExtension) {
557
920
  throw new Error("Extensions.Image is required when using the Image slash command.");
558
921
  }
@@ -566,12 +929,29 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
566
929
  editable: !readOnly,
567
930
  shouldRerenderOnTransaction: true,
568
931
  extensions: getTipTapExtensions({
569
- extensions,
570
- slashCommands,
571
- bubbleMenuOptions,
932
+ disabledExtensions,
933
+ extensions: resolvedExtensions,
934
+ slashCommands: resolvedSlashCommands,
572
935
  handleImageUpload,
573
936
  }),
574
937
  editorProps: {
938
+ handleClick: (view, pos, event) => {
939
+ const linkRange = getLinkRangeAtPosition(view.state, pos);
940
+ const linkAttributes = getLinkAttributesAtPosition(view.state, pos);
941
+ if (!linkRange || !(linkAttributes === null || linkAttributes === void 0 ? void 0 : linkAttributes.href))
942
+ return false;
943
+ const mouseEvent = event;
944
+ mouseEvent.preventDefault();
945
+ mouseEvent.stopPropagation();
946
+ const shouldOpenLink = mouseEvent.metaKey || mouseEvent.ctrlKey || !view.editable;
947
+ if (shouldOpenLink) {
948
+ openLink(linkAttributes.href);
949
+ return true;
950
+ }
951
+ view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.doc, linkRange.from, linkRange.to)));
952
+ view.focus();
953
+ return true;
954
+ },
575
955
  handlePaste: (view, event) => {
576
956
  if (!hasImageExtension || !handleImageUpload)
577
957
  return false;
@@ -632,5 +1012,5 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
632
1012
  return (_jsx(StyledContent, { className: className, children: _jsxs(RichTextEditorContext.Provider, { value: {
633
1013
  font: fontState,
634
1014
  setFont: setFontState,
635
- }, children: [showToolbar && (_jsx(Toolbar, { editor: editor, toolbarOptions: toolbarOptions })), saving && _jsx(SaveBadge, {}), _jsx(EditorContent, { className: "editor-content", editor: editor, "data-font": fontState || null, style: style })] }) }));
1015
+ }, children: [showToolbar && (_jsx(Toolbar, { editor: editor, toolbarOptions: resolvedToolbarOptions })), saving && _jsx(SaveBadge, {}), editor && hasBubbleMenuExtension && (_jsx(TiptapBubbleMenu, { editor: editor, pluginKey: "bubbleMenu", updateDelay: 200, appendTo: getBubbleMenuPortalRoot, shouldShow: shouldShowBubbleMenu, options: bubbleMenuPositionOptions, children: _jsx(BubbleMenuContent, { editor: editor, customMenuItems: bubbleMenuOptions === null || bubbleMenuOptions === void 0 ? void 0 : bubbleMenuOptions.customMenuItems }) })), editor && hasTableExtension && _jsx(TableRails, { editor: editor }), _jsx(EditorContent, { className: "editor-content", editor: editor, "data-font": fontState || null, style: style })] }) }));
636
1016
  };
@@ -1,13 +1,17 @@
1
1
  import { Editor } from "@tiptap/react";
2
+ import { ButtonProps } from "../../Button";
2
3
  export type ControlProps = {
3
4
  className?: string;
4
5
  editor: Editor | null;
5
6
  isActive?: any;
6
- operation: {
7
+ operation?: {
7
8
  name: string;
8
9
  attributes?: any;
9
10
  };
11
+ onClick?: (editor: Editor | null) => void;
12
+ disabled?: boolean;
10
13
  label: string;
11
14
  icon: any;
15
+ size?: ButtonProps["size"];
12
16
  };
13
- export declare const Control: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<ControlProps, never>> & string & Omit<({ className, editor, isActive, operation, label, icon: Icon, }: ControlProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
17
+ export declare const Control: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<ControlProps, never>> & string & Omit<({ className, editor, isActive, operation, onClick, disabled, label, icon: Icon, size, }: ControlProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
@@ -1,23 +1,30 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import styled from "styled-components";
3
3
  import Labels from "./Labels";
4
- export const Control = styled(({ className, editor, isActive, operation, label, icon: Icon, }) => {
4
+ import { Button } from "../../Button";
5
+ export const Control = styled(({ className, editor, isActive, operation, onClick, disabled, label, icon: Icon, size = "xs", }) => {
5
6
  var _a;
6
7
  const _label = Labels[label];
7
8
  const active = (isActive === null || isActive === void 0 ? void 0 : isActive.name)
8
9
  ? (_a = editor === null || editor === void 0 ? void 0 : editor.isActive) === null || _a === void 0 ? void 0 : _a.call(editor, isActive.name, isActive.attributes)
9
10
  : false;
10
- return (_jsx("button", { className: className + (active ? " active" : ""), "aria-label": _label, "data-active": active, title: _label, onClick: () => {
11
+ return (_jsx(Button, { className: className + (active ? " active" : ""), "aria-label": _label, "data-active": active, title: _label, disabled: disabled, onClick: () => {
12
+ if (onClick) {
13
+ onClick(editor);
14
+ return;
15
+ }
16
+ if (!operation)
17
+ return;
11
18
  const focus = editor === null || editor === void 0 ? void 0 : editor.chain().focus();
12
19
  focus[operation.name](operation.attributes).run();
13
- }, children: _jsx(Icon, { size: "16px" }) }));
20
+ }, size: size, children: _jsx(Icon, { size: "16px" }) }));
14
21
  }) `
15
22
  display: flex;
16
23
  justify-content: center;
17
24
  align-items: center;
18
- width: 1.5rem;
19
- height: 1.5rem;
20
- padding: 0px;
25
+
26
+ padding: 5px;
27
+
21
28
  background-color: transparent;
22
29
  cursor: pointer;
23
30
  color: ${({ theme }) => theme.palette.text.primary};
@@ -4,10 +4,16 @@ interface ControlProps {
4
4
  }
5
5
  export declare const UndoControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
6
6
  export declare const RedoControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
7
+ export declare const FontControl: () => import("react/jsx-runtime").JSX.Element;
8
+ export declare const TextColorControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
9
+ export declare const HighlightControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
10
+ export declare const ClearFormattingControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
7
11
  export declare const BoldControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
8
12
  export declare const ItalicControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
9
13
  export declare const UnderlineControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
10
14
  export declare const StrikeThroughControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
15
+ export declare const CodeControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
16
+ export declare const CodeBlockControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
11
17
  export declare const Heading1Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
12
18
  export declare const Heading2Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
13
19
  export declare const Heading3Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;