@monolith-forensics/monolith-ui 1.9.1-dev.9 → 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 (91) 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 +3 -3
  9. package/dist/RichTextEditor/Components/BubbleMenu.js +190 -51
  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 -0
  69. package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +157 -24
  70. package/dist/RichTextEditor/Plugins/ImageActionsPlugin.js +4 -7
  71. package/dist/RichTextEditor/RichTextEditor.d.ts +3 -1
  72. package/dist/RichTextEditor/RichTextEditor.js +352 -14
  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
@@ -14,14 +14,73 @@ import { EditorContent, useEditor } from "@tiptap/react";
14
14
  import { BubbleMenu as TiptapBubbleMenu, } from "@tiptap/react/menus";
15
15
  import { isTextSelection } from "@tiptap/core";
16
16
  import { DOMParser as ProseMirrorDOMParser } from "@tiptap/pm/model";
17
+ import { TextSelection } from "@tiptap/pm/state";
17
18
  import { Toolbar } from "./Toolbar";
18
- import getTipTapExtensions from "./Extensions/getTiptapExtensions";
19
- import { Extensions, SlashCommands } from "./Enums";
19
+ import getTipTapExtensions, { resolveExtensions, } from "./Extensions/getTiptapExtensions";
20
+ import { Controls, Extensions, SlashCommands } from "./Enums";
20
21
  import { addImagePlaceholder, removeImagePlaceholder, startImageUpload, } from "./Plugins/UploadImagesPlugin";
21
22
  import SaveBadge from "./Components/SaveBadge";
22
23
  import BubbleMenuContent from "./Components/BubbleMenu";
24
+ import { TableRails } from "./Components/TableTools";
23
25
  import Fonts from "./Enums/Fonts";
24
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
+ };
25
84
  const getImageFilesFromClipboard = (clipboardData) => {
26
85
  return Array.from(clipboardData.files).filter((file) => file.type.includes("image/"));
27
86
  };
@@ -275,25 +334,86 @@ const StyledContent = styled.div `
275
334
  word-break: break-word;
276
335
  text-rendering: optimizeLegibility;
277
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
+
278
348
  table {
279
349
  border-collapse: collapse;
350
+ table-layout: fixed;
280
351
  width: 100%;
352
+ overflow: hidden;
281
353
 
282
354
  th,
283
355
  td {
284
356
  border: 1px solid ${({ theme }) => theme.palette.divider};
357
+ box-sizing: border-box;
285
358
  padding: 0.5rem;
286
- min-width: 100px;
359
+ min-width: ${TABLE_CELL_MIN_WIDTH}px;
360
+ position: relative;
361
+ vertical-align: top;
287
362
  }
288
363
 
289
364
  // for table header
290
365
  th {
291
366
  border: 1px solid ${({ theme }) => theme.palette.divider};
292
367
  padding: 0.5rem;
293
- min-width: 100px;
368
+ min-width: ${TABLE_CELL_MIN_WIDTH}px;
294
369
  background-color: ${({ theme }) => theme.palette.action.hover};
295
370
  font-weight: 500;
296
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;
297
417
  }
298
418
 
299
419
  h1 {
@@ -320,6 +440,158 @@ const StyledContent = styled.div `
320
440
  margin: 0;
321
441
  line-height: 1.5rem;
322
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
+ }
323
595
  ul {
324
596
  margin: 0;
325
597
  }
@@ -333,8 +605,6 @@ const StyledContent = styled.div `
333
605
  color: ${({ theme }) => theme.palette.text.primary};
334
606
  text-decoration: underline;
335
607
  cursor: pointer;
336
- // Set title attribute
337
- title: "Click to open link";
338
608
  }
339
609
  img {
340
610
  max-width: 100%;
@@ -352,6 +622,7 @@ const StyledContent = styled.div `
352
622
  color: #888;
353
623
  pointer-events: none;
354
624
  height: 0;
625
+ white-space: nowrap;
355
626
  }
356
627
  .ProseMirror .is-empty::before {
357
628
  content: attr(data-placeholder);
@@ -359,6 +630,7 @@ const StyledContent = styled.div `
359
630
  color: #888;
360
631
  pointer-events: none;
361
632
  height: 0;
633
+ white-space: nowrap;
362
634
  }
363
635
 
364
636
  .ProseMirror .monolith-image.uploading {
@@ -546,12 +818,60 @@ const StyledContent = styled.div `
546
818
  margin: 0 0.125rem;
547
819
  }
548
820
  `;
549
- 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]);
550
868
  const isControlled = value !== undefined;
551
- const hasImageExtension = extensions.includes(Extensions.Image);
552
- const hasSlashCommandExtension = extensions.includes(Extensions.SlashCommand);
553
- const hasBubbleMenuExtension = extensions.includes(Extensions.BubbleMenu);
554
- 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);
555
875
  const onChangeRef = useRef(onChange);
556
876
  const bubbleMenuPortalRef = useRef(null);
557
877
  const [fontState, setFontState] = useState(font || Fonts.DEFAULT);
@@ -609,11 +929,29 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
609
929
  editable: !readOnly,
610
930
  shouldRerenderOnTransaction: true,
611
931
  extensions: getTipTapExtensions({
612
- extensions,
613
- slashCommands,
932
+ disabledExtensions,
933
+ extensions: resolvedExtensions,
934
+ slashCommands: resolvedSlashCommands,
614
935
  handleImageUpload,
615
936
  }),
616
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
+ },
617
955
  handlePaste: (view, event) => {
618
956
  if (!hasImageExtension || !handleImageUpload)
619
957
  return false;
@@ -674,5 +1012,5 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
674
1012
  return (_jsx(StyledContent, { className: className, children: _jsxs(RichTextEditorContext.Provider, { value: {
675
1013
  font: fontState,
676
1014
  setFont: setFontState,
677
- }, children: [showToolbar && (_jsx(Toolbar, { editor: editor, toolbarOptions: toolbarOptions })), saving && _jsx(SaveBadge, {}), editor && hasBubbleMenuExtension && (_jsx(TiptapBubbleMenu, { editor: editor, pluginKey: "bubbleMenu", updateDelay: 150, appendTo: getBubbleMenuPortalRoot, shouldShow: shouldShowBubbleMenu, options: bubbleMenuPositionOptions, children: _jsx(BubbleMenuContent, { editor: editor, customMenuItems: bubbleMenuOptions === null || bubbleMenuOptions === void 0 ? void 0 : bubbleMenuOptions.customMenuItems }) })), _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 })] }) }));
678
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;
@@ -1,6 +1,17 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { IconBold, IconItalic, IconUnderline, IconStrikethrough, IconH1, IconH2, IconH3, IconH4, IconList, IconListNumbers, IconAlignLeft, IconAlignRight, IconAlignCenter, IconAlignJustified, IconCornerUpLeft, IconCornerUpRight, } from "@tabler/icons-react";
3
+ import { CodeIcon, HighlighterIcon, PaletteIcon, RemoveFormattingIcon, SquircleIcon, TypeIcon, } from "lucide-react";
4
+ import { SquareCodeIcon } from "lucide-react";
3
5
  import { Control } from "./Control";
6
+ import { hasInlineCode, toggleInlineCode } from "../Utils/codeUtils";
7
+ import { hasSyntaxHighlightedCodeBlock, toggleCodeBlock, } from "../Utils/codeBlockUtils";
8
+ import { useContext } from "react";
9
+ import { useTheme } from "styled-components";
10
+ import { DropDownMenu } from "../../DropDownMenu";
11
+ import RichTextEditorContext from "../Contexts/RichTextEditorContext";
12
+ import Fonts from "../Enums/Fonts";
13
+ import TextColors from "../Enums/TextColors";
14
+ import HighlightColors from "../Enums/HighlightColors";
4
15
  export const UndoControl = ({ editor }) => {
5
16
  return (_jsx(Control, { editor: editor, label: "undoControlLabel", operation: {
6
17
  name: "undo",
@@ -11,6 +22,102 @@ export const RedoControl = ({ editor }) => {
11
22
  name: "redo",
12
23
  }, icon: IconCornerUpRight }));
13
24
  };
25
+ export const FontControl = () => {
26
+ const { font, setFont } = useContext(RichTextEditorContext);
27
+ return (_jsx(DropDownMenu, { data: Object.values(Fonts).map((font) => ({
28
+ label: font,
29
+ value: font,
30
+ onClick: () => {
31
+ setFont(font);
32
+ },
33
+ })), size: "xs", variant: "outlined", dropDownProps: {
34
+ style: {
35
+ width: 135,
36
+ },
37
+ }, buttonProps: {
38
+ title: "Select Font",
39
+ leftSection: _jsx(TypeIcon, { size: 12 }),
40
+ }, children: (font || Fonts.DEFAULT) }));
41
+ };
42
+ export const TextColorControl = ({ editor }) => {
43
+ const theme = useTheme();
44
+ return (_jsx(DropDownMenu, { data: [
45
+ {
46
+ label: "Default",
47
+ value: "default",
48
+ onClick: () => {
49
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetColor().run();
50
+ },
51
+ },
52
+ ...Object.keys(TextColors).map((color) => {
53
+ const colorKey = color;
54
+ return {
55
+ label: color,
56
+ value: TextColors[colorKey],
57
+ onClick: () => {
58
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().setColor(TextColors[colorKey]).run();
59
+ },
60
+ };
61
+ }),
62
+ ], renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
63
+ ? theme.palette.text.primary
64
+ : item.value, style: {
65
+ backgroundColor: item.value === "default"
66
+ ? theme.palette.text.primary
67
+ : item.value,
68
+ borderRadius: "3px",
69
+ } }), item.label] })), size: "xs", variant: "outlined", buttonProps: {
70
+ title: "Select Color",
71
+ style: { padding: "1px 6px" },
72
+ }, dropDownProps: {
73
+ style: {
74
+ width: 120,
75
+ },
76
+ }, children: _jsx(PaletteIcon, { size: 14 }) }));
77
+ };
78
+ export const HighlightControl = ({ editor }) => {
79
+ const theme = useTheme();
80
+ return (_jsx(DropDownMenu, { data: [
81
+ {
82
+ label: "Default",
83
+ value: "default",
84
+ onClick: () => {
85
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetHighlight().run();
86
+ },
87
+ },
88
+ ...Object.keys(HighlightColors).map((color) => {
89
+ const colorKey = color;
90
+ return {
91
+ label: color,
92
+ value: HighlightColors[colorKey],
93
+ onClick: () => {
94
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().setHighlight({ color: HighlightColors[colorKey] }).run();
95
+ },
96
+ };
97
+ }),
98
+ ], renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
99
+ ? theme.palette.text.primary
100
+ : item.value, style: {
101
+ backgroundColor: item.value === "default"
102
+ ? "transparent"
103
+ : item.value,
104
+ borderRadius: "3px",
105
+ } }), item.label] })), size: "xs", variant: "outlined", buttonProps: {
106
+ title: "Select Highlight",
107
+ style: { padding: "1px 6px" },
108
+ }, dropDownProps: {
109
+ style: {
110
+ width: 100,
111
+ height: 210,
112
+ },
113
+ }, children: _jsx(HighlighterIcon, { size: 14 }) }));
114
+ };
115
+ export const ClearFormattingControl = ({ editor }) => {
116
+ return (_jsx(Control, { editor: editor, label: "clearFormattingControlLabel", onClick: (editor) => {
117
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().setParagraph().run();
118
+ editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetAllMarks().run();
119
+ }, icon: RemoveFormattingIcon }));
120
+ };
14
121
  export const BoldControl = ({ editor }) => {
15
122
  return (_jsx(Control, { editor: editor, label: "boldControlLabel", isActive: {
16
123
  name: "bold",
@@ -39,6 +146,16 @@ export const StrikeThroughControl = ({ editor }) => {
39
146
  name: "toggleStrike",
40
147
  }, icon: IconStrikethrough }));
41
148
  };
149
+ export const CodeControl = ({ editor }) => {
150
+ return (_jsx(Control, { editor: editor, label: "codeControlLabel", isActive: {
151
+ name: "code",
152
+ }, onClick: toggleInlineCode, disabled: !hasInlineCode(editor), icon: CodeIcon }));
153
+ };
154
+ export const CodeBlockControl = ({ editor }) => {
155
+ return (_jsx(Control, { editor: editor, label: "codeBlockControlLabel", isActive: {
156
+ name: "codeBlock",
157
+ }, onClick: toggleCodeBlock, disabled: !hasSyntaxHighlightedCodeBlock(editor), icon: SquareCodeIcon }));
158
+ };
42
159
  export const Heading1Control = ({ editor }) => {
43
160
  return (_jsx(Control, { editor: editor, label: "h1ControlLabel", isActive: {
44
161
  name: "heading",