@monolith-forensics/monolith-ui 1.9.3-dev.3 → 2.0.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.
- package/dist/Button/Button.js +11 -4
- package/dist/DropDownMenu/DropDownMenu.js +12 -2
- package/dist/DropDownMenu/components/MenuComponent.js +7 -1
- package/dist/DropDownMenu/components/MenuItem.js +4 -2
- package/dist/DropDownMenu/components/MenuItemList.d.ts +1 -0
- package/dist/DropDownMenu/components/MenuItemList.js +17 -7
- package/dist/DropDownMenu/components/SearchInput.js +2 -1
- package/dist/DropDownMenu/components/StyledContent.js +3 -2
- package/dist/DropDownMenu/constants.d.ts +4 -0
- package/dist/DropDownMenu/constants.js +4 -0
- package/dist/QueryFilter/DefaultOperators.d.ts +76 -0
- package/dist/QueryFilter/DefaultOperators.js +21 -0
- package/dist/QueryFilter/types.d.ts +66 -0
- package/dist/QueryFilter/types.js +1 -0
- package/dist/RichTextEditor/Enums/Controls.d.ts +2 -0
- package/dist/RichTextEditor/Enums/Controls.js +2 -0
- package/dist/RichTextEditor/Enums/Extensions.d.ts +1 -0
- package/dist/RichTextEditor/Enums/Extensions.js +1 -0
- package/dist/RichTextEditor/Enums/SlashCommands.d.ts +2 -0
- package/dist/RichTextEditor/Enums/SlashCommands.js +2 -0
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +7 -0
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +157 -0
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +19 -1
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +16 -1
- package/dist/RichTextEditor/RichTextEditor.js +65 -28
- package/dist/RichTextEditor/Toolbar/Controls.d.ts +14 -0
- package/dist/RichTextEditor/Toolbar/Controls.js +147 -3
- package/dist/RichTextEditor/Toolbar/Labels.d.ts +1 -0
- package/dist/RichTextEditor/Toolbar/Labels.js +1 -0
- package/dist/RichTextEditor/Toolbar/Toolbar.js +28 -2
- package/dist/Table/Utils/resizeHandler.d.ts +3 -0
- package/dist/Table/Utils/resizeHandler.js +84 -0
- package/package.json +4 -1
|
@@ -11,7 +11,7 @@ import { Extension } from "@tiptap/core";
|
|
|
11
11
|
import Suggestion from "@tiptap/suggestion";
|
|
12
12
|
import { ReactRenderer } from "@tiptap/react";
|
|
13
13
|
import tippy from "tippy.js";
|
|
14
|
-
import { Heading1, Heading2, Heading3, Heading4, List, ListOrdered, Text, TextQuote, Image as ImageIcon, Calendar, CodeIcon, ClockIcon, SquareCodeIcon, Table2Icon, } from "lucide-react";
|
|
14
|
+
import { Heading1, Heading2, Heading3, Heading4, List, ListOrdered, Text, TextQuote, Image as ImageIcon, Calendar, CodeIcon, ClockIcon, ListChecksIcon, SeparatorHorizontalIcon, SquareCodeIcon, Table2Icon, } from "lucide-react";
|
|
15
15
|
import { startImageUpload, } from "../Plugins/UploadImagesPlugin.js";
|
|
16
16
|
import { PluginKey } from "@tiptap/pm/state";
|
|
17
17
|
import SlashCommandList from "./SlashCommandList";
|
|
@@ -116,6 +116,15 @@ const getCommandItems = (values, options) => {
|
|
|
116
116
|
editor.chain().focus().deleteRange(range).toggleOrderedList().run();
|
|
117
117
|
},
|
|
118
118
|
},
|
|
119
|
+
{
|
|
120
|
+
title: SlashCommands.TaskList,
|
|
121
|
+
description: "Create a checklist with tasks.",
|
|
122
|
+
searchTerms: ["todo", "checklist", "checkbox"],
|
|
123
|
+
icon: ListChecksIcon,
|
|
124
|
+
command: ({ editor, range }) => {
|
|
125
|
+
editor.chain().focus().deleteRange(range).toggleTaskList().run();
|
|
126
|
+
},
|
|
127
|
+
},
|
|
119
128
|
{
|
|
120
129
|
title: SlashCommands.Code,
|
|
121
130
|
description: "Start typing inline code.",
|
|
@@ -148,6 +157,15 @@ const getCommandItems = (values, options) => {
|
|
|
148
157
|
editor.chain().focus().deleteRange(range).toggleBlockquote().run();
|
|
149
158
|
},
|
|
150
159
|
},
|
|
160
|
+
{
|
|
161
|
+
title: SlashCommands.HorizontalRule,
|
|
162
|
+
description: "Insert a horizontal divider.",
|
|
163
|
+
searchTerms: ["divider", "line", "rule", "separator"],
|
|
164
|
+
icon: SeparatorHorizontalIcon,
|
|
165
|
+
command: ({ editor, range }) => {
|
|
166
|
+
editor.chain().focus().deleteRange(range).setHorizontalRule().run();
|
|
167
|
+
},
|
|
168
|
+
},
|
|
151
169
|
{
|
|
152
170
|
title: SlashCommands.CurrentDate,
|
|
153
171
|
description: "Insert the current date.",
|
|
@@ -4,6 +4,8 @@ import { CodeBlockLowlight } from "@tiptap/extension-code-block-lowlight";
|
|
|
4
4
|
import HorizontalRule from "@tiptap/extension-horizontal-rule";
|
|
5
5
|
import TextAlign from "@tiptap/extension-text-align";
|
|
6
6
|
import { Table, TableCell, TableHeader, TableRow, } from "@tiptap/extension-table";
|
|
7
|
+
import TaskList from "@tiptap/extension-task-list";
|
|
8
|
+
import TaskItem from "@tiptap/extension-task-item";
|
|
7
9
|
import { Focus, Placeholder } from "@tiptap/extensions";
|
|
8
10
|
import { Color } from "@tiptap/extension-color";
|
|
9
11
|
import { Highlight } from "@tiptap/extension-highlight";
|
|
@@ -71,6 +73,7 @@ export const BASIC_EXTENSIONS = [
|
|
|
71
73
|
Extensions.Strike,
|
|
72
74
|
Extensions.Code,
|
|
73
75
|
Extensions.Blockquote,
|
|
76
|
+
Extensions.HorizontalRule,
|
|
74
77
|
Extensions.BulletList,
|
|
75
78
|
Extensions.OrderedList,
|
|
76
79
|
Extensions.TextStyle,
|
|
@@ -88,7 +91,7 @@ export const MINIMAL_EXTENSIONS = [
|
|
|
88
91
|
export const FULL_EXTENSIONS = [
|
|
89
92
|
...BASIC_EXTENSIONS,
|
|
90
93
|
Extensions.CodeBlock,
|
|
91
|
-
Extensions.
|
|
94
|
+
Extensions.TaskList,
|
|
92
95
|
Extensions.Table,
|
|
93
96
|
Extensions.TableCell,
|
|
94
97
|
Extensions.TableHeader,
|
|
@@ -269,6 +272,16 @@ const getTipTapExtensions = ({ disabledExtensions = [], extensions = [], slashCo
|
|
|
269
272
|
name: Extensions.TableCell,
|
|
270
273
|
extension: TableCell,
|
|
271
274
|
},
|
|
275
|
+
{
|
|
276
|
+
name: Extensions.TaskList,
|
|
277
|
+
extension: TaskList,
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: "taskItem",
|
|
281
|
+
extension: TaskItem.configure({
|
|
282
|
+
nested: true,
|
|
283
|
+
}),
|
|
284
|
+
},
|
|
272
285
|
{
|
|
273
286
|
name: Extensions.Image,
|
|
274
287
|
extension: CustomImage.configure({
|
|
@@ -314,6 +327,8 @@ const getTipTapExtensions = ({ disabledExtensions = [], extensions = [], slashCo
|
|
|
314
327
|
.filter((ext) => {
|
|
315
328
|
if (ext.name === "starterKit")
|
|
316
329
|
return true;
|
|
330
|
+
if (ext.name === "taskItem")
|
|
331
|
+
return isEnabled(Extensions.TaskList);
|
|
317
332
|
return isEnabled(ext.name);
|
|
318
333
|
})
|
|
319
334
|
.map((ext) => ext.extension);
|
|
@@ -14,7 +14,7 @@ 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
|
+
import { NodeSelection, TextSelection } from "@tiptap/pm/state";
|
|
18
18
|
import { Toolbar } from "./Toolbar";
|
|
19
19
|
import getTipTapExtensions, { resolveExtensions, } from "./Extensions/getTiptapExtensions";
|
|
20
20
|
import { Controls, Extensions, SlashCommands } from "./Enums";
|
|
@@ -26,6 +26,7 @@ import Fonts from "./Enums/Fonts";
|
|
|
26
26
|
import RichTextEditorContext from "./Contexts/RichTextEditorContext";
|
|
27
27
|
import { getLinkAttributesAtPosition, getLinkRangeAtPosition, openLink, } from "./Utils/linkUtils";
|
|
28
28
|
import { TABLE_CELL_MIN_WIDTH } from "./Utils/tableUtils";
|
|
29
|
+
import { getControlSizeTokens } from "../core";
|
|
29
30
|
const codeBlockFallbacks = {
|
|
30
31
|
light: {
|
|
31
32
|
background: "#f6f8fa",
|
|
@@ -74,6 +75,7 @@ const codeBlockFallbacks = {
|
|
|
74
75
|
},
|
|
75
76
|
},
|
|
76
77
|
};
|
|
78
|
+
const TASK_CHECKBOX_SIZE = getControlSizeTokens("sm").checkboxIconSize;
|
|
77
79
|
const getCodeBlockTheme = (theme) => {
|
|
78
80
|
if (theme.palette.codeBlock)
|
|
79
81
|
return theme.palette.codeBlock;
|
|
@@ -435,6 +437,12 @@ const StyledContent = styled.div `
|
|
|
435
437
|
margin: 0;
|
|
436
438
|
line-height: 1.5rem;
|
|
437
439
|
}
|
|
440
|
+
|
|
441
|
+
hr {
|
|
442
|
+
border: 1px solid ${({ theme }) => theme.palette.action.hover};
|
|
443
|
+
margin: 1rem 0;
|
|
444
|
+
}
|
|
445
|
+
|
|
438
446
|
.editor-inline-code,
|
|
439
447
|
:not(pre) > code {
|
|
440
448
|
padding: 0.1rem 0.25rem;
|
|
@@ -752,59 +760,77 @@ const StyledContent = styled.div `
|
|
|
752
760
|
|
|
753
761
|
ul[data-type="taskList"] {
|
|
754
762
|
list-style: none;
|
|
763
|
+
margin: 0.25rem 0;
|
|
755
764
|
padding: 0;
|
|
756
765
|
|
|
757
766
|
li {
|
|
758
767
|
display: flex;
|
|
759
|
-
align-items:
|
|
768
|
+
align-items: flex-start;
|
|
760
769
|
margin: 0.25rem 0;
|
|
761
770
|
|
|
762
771
|
> label {
|
|
772
|
+
display: inline-flex;
|
|
773
|
+
align-items: center;
|
|
774
|
+
justify-content: center;
|
|
763
775
|
flex: 0 0 auto;
|
|
776
|
+
height: 1.5rem;
|
|
764
777
|
margin-right: 0.5rem;
|
|
765
778
|
user-select: none;
|
|
766
779
|
}
|
|
767
780
|
|
|
768
781
|
> div {
|
|
769
782
|
flex: 1 1 auto;
|
|
783
|
+
min-width: 0;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
> div > ul[data-type="taskList"] {
|
|
787
|
+
margin: 0.25rem 0 0;
|
|
770
788
|
}
|
|
771
789
|
}
|
|
772
790
|
|
|
773
791
|
input[type="checkbox"] {
|
|
774
|
-
cursor: pointer;
|
|
775
|
-
margin: 0;
|
|
776
792
|
-webkit-appearance: none;
|
|
777
793
|
appearance: none;
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
794
|
+
position: relative;
|
|
795
|
+
display: inline-flex;
|
|
796
|
+
align-items: center;
|
|
797
|
+
justify-content: center;
|
|
798
|
+
box-sizing: border-box;
|
|
799
|
+
width: ${TASK_CHECKBOX_SIZE}px;
|
|
800
|
+
height: ${TASK_CHECKBOX_SIZE}px;
|
|
801
|
+
margin: 0;
|
|
802
|
+
border: 1px solid ${({ theme }) => theme.palette.text.secondary};
|
|
803
|
+
border-radius: 2px;
|
|
804
|
+
background-color: transparent;
|
|
805
|
+
cursor: pointer;
|
|
806
|
+
|
|
807
|
+
&::after {
|
|
808
|
+
content: "";
|
|
809
|
+
position: absolute;
|
|
810
|
+
left: 50%;
|
|
811
|
+
top: 45%;
|
|
812
|
+
width: 32%;
|
|
813
|
+
height: 56%;
|
|
814
|
+
border: solid
|
|
815
|
+
${({ theme }) => (theme.name === "DARK" ? "#000000" : "#ffffff")};
|
|
816
|
+
border-width: 0 2px 2px 0;
|
|
817
|
+
opacity: 0;
|
|
818
|
+
transform: translate(-50%, -50%) rotate(45deg);
|
|
819
|
+
transform-origin: center;
|
|
788
820
|
}
|
|
789
821
|
|
|
790
|
-
&:
|
|
791
|
-
background-color: ${({ theme }) => theme.
|
|
822
|
+
&:checked {
|
|
823
|
+
background-color: ${({ theme }) => theme.name === "DARK" ? "#cdcdcd" : "#646464"};
|
|
824
|
+
border-color: ${({ theme }) => theme.name === "DARK" ? "#cdcdcd" : "#646464"};
|
|
792
825
|
}
|
|
793
826
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
width: 0.75em;
|
|
797
|
-
height: 0.75em;
|
|
798
|
-
transform: scale(0);
|
|
799
|
-
transition: 120ms transform ease-in-out;
|
|
800
|
-
box-shadow: inset 1em 1em;
|
|
801
|
-
transform-origin: center;
|
|
802
|
-
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
|
803
|
-
color: ${({ theme }) => theme.palette.text.primary};
|
|
827
|
+
&:checked::after {
|
|
828
|
+
opacity: 1;
|
|
804
829
|
}
|
|
805
830
|
|
|
806
|
-
&:
|
|
807
|
-
|
|
831
|
+
&:focus-visible {
|
|
832
|
+
outline: 2px solid ${({ theme }) => theme.palette.primary.main}40;
|
|
833
|
+
outline-offset: 2px;
|
|
808
834
|
}
|
|
809
835
|
}
|
|
810
836
|
}
|
|
@@ -844,9 +870,15 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
|
|
|
844
870
|
if (command === SlashCommands.Blockquote) {
|
|
845
871
|
return resolvedExtensionSet.has(Extensions.Blockquote);
|
|
846
872
|
}
|
|
873
|
+
if (command === SlashCommands.HorizontalRule) {
|
|
874
|
+
return resolvedExtensionSet.has(Extensions.HorizontalRule);
|
|
875
|
+
}
|
|
847
876
|
if (command === SlashCommands.Table) {
|
|
848
877
|
return resolvedExtensionSet.has(Extensions.Table);
|
|
849
878
|
}
|
|
879
|
+
if (command === SlashCommands.TaskList) {
|
|
880
|
+
return resolvedExtensionSet.has(Extensions.TaskList);
|
|
881
|
+
}
|
|
850
882
|
return true;
|
|
851
883
|
}), [resolvedExtensionSet, slashCommands]);
|
|
852
884
|
const resolvedToolbarOptions = useMemo(() => {
|
|
@@ -860,8 +892,10 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
|
|
|
860
892
|
[Controls.CODE]: Extensions.Code,
|
|
861
893
|
[Controls.CODE_BLOCK]: Extensions.CodeBlock,
|
|
862
894
|
[Controls.BLOCKQUOTE]: Extensions.Blockquote,
|
|
895
|
+
[Controls.HORIZONTAL_RULE]: Extensions.HorizontalRule,
|
|
863
896
|
[Controls.BULLET_LIST]: Extensions.BulletList,
|
|
864
897
|
[Controls.ORDERED_LIST]: Extensions.OrderedList,
|
|
898
|
+
[Controls.TASK_LIST]: Extensions.TaskList,
|
|
865
899
|
[Controls.COLOR]: Extensions.Color,
|
|
866
900
|
[Controls.HIGHLIGHT]: Extensions.Highlight,
|
|
867
901
|
[Controls.LINK]: Extensions.Link,
|
|
@@ -917,8 +951,11 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
|
|
|
917
951
|
const hasEditorFocus = view.hasFocus() || isChildOfMenu;
|
|
918
952
|
const selectedText = state.doc.textBetween(from, to).trim();
|
|
919
953
|
const isEmptyTextBlock = !selectedText && isTextSelection(state.selection);
|
|
954
|
+
const isHorizontalRuleSelection = selection instanceof NodeSelection &&
|
|
955
|
+
selection.node.type.name === "horizontalRule";
|
|
920
956
|
if (!hasEditorFocus ||
|
|
921
957
|
selection.empty ||
|
|
958
|
+
isHorizontalRuleSelection ||
|
|
922
959
|
isEmptyTextBlock ||
|
|
923
960
|
!editor.isEditable) {
|
|
924
961
|
return false;
|
|
@@ -2,6 +2,9 @@ import { Editor } from "@tiptap/react";
|
|
|
2
2
|
interface ControlProps {
|
|
3
3
|
editor: Editor | null;
|
|
4
4
|
}
|
|
5
|
+
export type HeadingLevel = 1 | 2 | 3 | 4;
|
|
6
|
+
export type TextAlignment = "left" | "center" | "right" | "justify";
|
|
7
|
+
export type ListType = "bullet" | "ordered" | "task";
|
|
5
8
|
export declare const UndoControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
9
|
export declare const RedoControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
10
|
export declare const FontControl: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -15,14 +18,25 @@ export declare const StrikeThroughControl: ({ editor }: ControlProps) => import(
|
|
|
15
18
|
export declare const CodeControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
19
|
export declare const CodeBlockControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
20
|
export declare const BlockquoteControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare const HorizontalRuleControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
22
|
export declare const Heading1Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
23
|
export declare const Heading2Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
24
|
export declare const Heading3Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
21
25
|
export declare const Heading4Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export declare const HeadingControl: ({ editor, levels, }: ControlProps & {
|
|
27
|
+
levels?: HeadingLevel[];
|
|
28
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
22
29
|
export declare const BulletListControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
30
|
export declare const OrderedListControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export declare const TaskListControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
export declare const ListControl: ({ editor, listTypes, }: ControlProps & {
|
|
33
|
+
listTypes?: ListType[];
|
|
34
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
24
35
|
export declare const AlignLeftControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
25
36
|
export declare const AlignRightControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
26
37
|
export declare const AlignCenterControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
27
38
|
export declare const AlignJustifiedControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare const AlignmentControl: ({ editor, alignments, }: ControlProps & {
|
|
40
|
+
alignments?: TextAlignment[];
|
|
41
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
28
42
|
export {};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { IconBold, IconItalic, IconUnderline, IconStrikethrough, IconH1, IconH2, IconH3, IconH4, IconList, IconListNumbers, IconAlignLeft, IconAlignRight, IconAlignCenter, IconAlignJustified, IconCornerUpLeft, IconCornerUpRight, IconBlockquote, } from "@tabler/icons-react";
|
|
3
|
-
import { CodeIcon, HighlighterIcon, PaletteIcon, RemoveFormattingIcon, SquircleIcon, TypeIcon, } from "lucide-react";
|
|
4
|
-
import { SquareCodeIcon } from "lucide-react";
|
|
2
|
+
import { IconBold, IconItalic, IconUnderline, IconStrikethrough, IconH1, IconH2, IconH3, IconH4, IconHeading, IconList, IconListNumbers, IconAlignLeft, IconAlignRight, IconAlignCenter, IconAlignJustified, IconCornerUpLeft, IconCornerUpRight, IconBlockquote, IconSeparatorHorizontal, } from "@tabler/icons-react";
|
|
3
|
+
import { CodeIcon, HighlighterIcon, ListChecksIcon, PaletteIcon, RemoveFormattingIcon, SquareCodeIcon, SquircleIcon, TypeIcon, } from "lucide-react";
|
|
5
4
|
import { Control } from "./Control";
|
|
6
5
|
import { hasInlineCode, toggleInlineCode } from "../Utils/codeUtils";
|
|
7
6
|
import { hasSyntaxHighlightedCodeBlock, toggleCodeBlock, } from "../Utils/codeBlockUtils";
|
|
@@ -12,6 +11,38 @@ import RichTextEditorContext from "../Contexts/RichTextEditorContext";
|
|
|
12
11
|
import Fonts from "../Enums/Fonts";
|
|
13
12
|
import TextColors from "../Enums/TextColors";
|
|
14
13
|
import HighlightColors from "../Enums/HighlightColors";
|
|
14
|
+
const headingControlOptions = [
|
|
15
|
+
{ level: 1, label: "Heading 1", icon: IconH1 },
|
|
16
|
+
{ level: 2, label: "Heading 2", icon: IconH2 },
|
|
17
|
+
{ level: 3, label: "Heading 3", icon: IconH3 },
|
|
18
|
+
{ level: 4, label: "Heading 4", icon: IconH4 },
|
|
19
|
+
];
|
|
20
|
+
const alignmentControlOptions = [
|
|
21
|
+
{ value: "left", label: "Align text: left", icon: IconAlignLeft },
|
|
22
|
+
{ value: "center", label: "Align text: center", icon: IconAlignCenter },
|
|
23
|
+
{ value: "right", label: "Align text: right", icon: IconAlignRight },
|
|
24
|
+
{ value: "justify", label: "Align text: justify", icon: IconAlignJustified },
|
|
25
|
+
];
|
|
26
|
+
const listControlOptions = [
|
|
27
|
+
{
|
|
28
|
+
value: "bullet",
|
|
29
|
+
label: "Bullet list",
|
|
30
|
+
nodeName: "bulletList",
|
|
31
|
+
icon: IconList,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: "ordered",
|
|
35
|
+
label: "Ordered list",
|
|
36
|
+
nodeName: "orderedList",
|
|
37
|
+
icon: IconListNumbers,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
value: "task",
|
|
41
|
+
label: "Task list",
|
|
42
|
+
nodeName: "taskList",
|
|
43
|
+
icon: ListChecksIcon,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
15
46
|
export const UndoControl = ({ editor }) => {
|
|
16
47
|
return (_jsx(Control, { editor: editor, label: "undoControlLabel", operation: {
|
|
17
48
|
name: "undo",
|
|
@@ -163,6 +194,11 @@ export const BlockquoteControl = ({ editor }) => {
|
|
|
163
194
|
name: "toggleBlockquote",
|
|
164
195
|
}, icon: IconBlockquote }));
|
|
165
196
|
};
|
|
197
|
+
export const HorizontalRuleControl = ({ editor }) => {
|
|
198
|
+
return (_jsx(Control, { editor: editor, label: "hrControlLabel", operation: {
|
|
199
|
+
name: "setHorizontalRule",
|
|
200
|
+
}, icon: IconSeparatorHorizontal }));
|
|
201
|
+
};
|
|
166
202
|
export const Heading1Control = ({ editor }) => {
|
|
167
203
|
return (_jsx(Control, { editor: editor, label: "h1ControlLabel", isActive: {
|
|
168
204
|
name: "heading",
|
|
@@ -199,6 +235,37 @@ export const Heading4Control = ({ editor }) => {
|
|
|
199
235
|
attributes: { level: 4 },
|
|
200
236
|
}, icon: IconH4 }));
|
|
201
237
|
};
|
|
238
|
+
export const HeadingControl = ({ editor, levels = [1, 2, 3, 4], }) => {
|
|
239
|
+
const options = headingControlOptions.filter((option) => levels.includes(option.level));
|
|
240
|
+
const currentHeading = headingControlOptions.find((option) => editor === null || editor === void 0 ? void 0 : editor.isActive("heading", { level: option.level }));
|
|
241
|
+
const selectedHeading = options.find((option) => option.level === (currentHeading === null || currentHeading === void 0 ? void 0 : currentHeading.level));
|
|
242
|
+
const ButtonIcon = (currentHeading === null || currentHeading === void 0 ? void 0 : currentHeading.icon) || IconHeading;
|
|
243
|
+
if (!options.length)
|
|
244
|
+
return null;
|
|
245
|
+
return (_jsx(DropDownMenu, { data: options.map((option) => ({
|
|
246
|
+
label: option.label,
|
|
247
|
+
value: option.level,
|
|
248
|
+
onClick: () => {
|
|
249
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleHeading({ level: option.level }).run();
|
|
250
|
+
},
|
|
251
|
+
})), value: selectedHeading
|
|
252
|
+
? [{ label: selectedHeading.label, value: selectedHeading.level }]
|
|
253
|
+
: [], enableSelectedOptionStyling: true, renderOption: (item) => {
|
|
254
|
+
const option = options.find((option) => option.level === item.value);
|
|
255
|
+
const Icon = (option === null || option === void 0 ? void 0 : option.icon) || IconH1;
|
|
256
|
+
return (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [_jsx(Icon, { size: 14 }), item.label] }));
|
|
257
|
+
}, size: "xs", variant: "outlined", buttonProps: {
|
|
258
|
+
title: (currentHeading === null || currentHeading === void 0 ? void 0 : currentHeading.label) || "Heading",
|
|
259
|
+
"aria-label": "Heading",
|
|
260
|
+
disabled: !editor,
|
|
261
|
+
selected: Boolean(currentHeading),
|
|
262
|
+
style: { padding: "1px 6px" },
|
|
263
|
+
}, dropDownProps: {
|
|
264
|
+
style: {
|
|
265
|
+
width: 150,
|
|
266
|
+
},
|
|
267
|
+
}, children: _jsx(ButtonIcon, { size: 14 }) }));
|
|
268
|
+
};
|
|
202
269
|
export const BulletListControl = ({ editor }) => {
|
|
203
270
|
return (_jsx(Control, { editor: editor, label: "bulletListControlLabel", isActive: {
|
|
204
271
|
name: "bulletList",
|
|
@@ -213,6 +280,51 @@ export const OrderedListControl = ({ editor }) => {
|
|
|
213
280
|
name: "toggleOrderedList",
|
|
214
281
|
}, icon: IconListNumbers }));
|
|
215
282
|
};
|
|
283
|
+
export const TaskListControl = ({ editor }) => {
|
|
284
|
+
return (_jsx(Control, { editor: editor, label: "taskListControlLabel", isActive: {
|
|
285
|
+
name: "taskList",
|
|
286
|
+
}, operation: {
|
|
287
|
+
name: "toggleTaskList",
|
|
288
|
+
}, icon: ListChecksIcon }));
|
|
289
|
+
};
|
|
290
|
+
export const ListControl = ({ editor, listTypes = ["bullet", "ordered", "task"], }) => {
|
|
291
|
+
const options = listControlOptions.filter((option) => listTypes.includes(option.value));
|
|
292
|
+
const currentList = listControlOptions.find((option) => editor === null || editor === void 0 ? void 0 : editor.isActive(option.nodeName));
|
|
293
|
+
const selectedList = options.find((option) => option.value === (currentList === null || currentList === void 0 ? void 0 : currentList.value));
|
|
294
|
+
const fallbackList = options[0] || listControlOptions[0];
|
|
295
|
+
const ButtonIcon = (currentList === null || currentList === void 0 ? void 0 : currentList.icon) || fallbackList.icon;
|
|
296
|
+
if (!options.length)
|
|
297
|
+
return null;
|
|
298
|
+
return (_jsx(DropDownMenu, { data: options.map((option) => ({
|
|
299
|
+
label: option.label,
|
|
300
|
+
value: option.value,
|
|
301
|
+
onClick: () => {
|
|
302
|
+
const chain = editor === null || editor === void 0 ? void 0 : editor.chain().focus();
|
|
303
|
+
if (option.value === "bullet")
|
|
304
|
+
chain === null || chain === void 0 ? void 0 : chain.toggleBulletList().run();
|
|
305
|
+
if (option.value === "ordered")
|
|
306
|
+
chain === null || chain === void 0 ? void 0 : chain.toggleOrderedList().run();
|
|
307
|
+
if (option.value === "task")
|
|
308
|
+
chain === null || chain === void 0 ? void 0 : chain.toggleTaskList().run();
|
|
309
|
+
},
|
|
310
|
+
})), value: selectedList
|
|
311
|
+
? [{ label: selectedList.label, value: selectedList.value }]
|
|
312
|
+
: [], enableSelectedOptionStyling: true, renderOption: (item) => {
|
|
313
|
+
const option = options.find((option) => option.value === item.value);
|
|
314
|
+
const Icon = (option === null || option === void 0 ? void 0 : option.icon) || IconList;
|
|
315
|
+
return (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [_jsx(Icon, { size: 14 }), item.label] }));
|
|
316
|
+
}, size: "xs", variant: "outlined", buttonProps: {
|
|
317
|
+
title: (currentList === null || currentList === void 0 ? void 0 : currentList.label) || "List",
|
|
318
|
+
"aria-label": "List",
|
|
319
|
+
disabled: !editor,
|
|
320
|
+
selected: Boolean(currentList),
|
|
321
|
+
style: { padding: "1px 6px" },
|
|
322
|
+
}, dropDownProps: {
|
|
323
|
+
style: {
|
|
324
|
+
width: 150,
|
|
325
|
+
},
|
|
326
|
+
}, children: _jsx(ButtonIcon, { size: 14 }) }));
|
|
327
|
+
};
|
|
216
328
|
export const AlignLeftControl = ({ editor }) => {
|
|
217
329
|
return (_jsx(Control, { editor: editor, label: "alignLeftControlLabel", isActive: {
|
|
218
330
|
name: { textAlign: "left" },
|
|
@@ -242,3 +354,35 @@ export const AlignJustifiedControl = ({ editor }) => {
|
|
|
242
354
|
name: { textAlign: "justify" },
|
|
243
355
|
}, operation: { name: "setTextAlign", attributes: "justify" }, icon: IconAlignJustified }));
|
|
244
356
|
};
|
|
357
|
+
export const AlignmentControl = ({ editor, alignments = ["left", "center", "right", "justify"], }) => {
|
|
358
|
+
const options = alignmentControlOptions.filter((option) => alignments.includes(option.value));
|
|
359
|
+
const activeAlignment = alignmentControlOptions.find((option) => editor === null || editor === void 0 ? void 0 : editor.isActive({ textAlign: option.value }));
|
|
360
|
+
const currentAlignment = activeAlignment || alignmentControlOptions[0];
|
|
361
|
+
const selectedAlignment = options.find((option) => option.value === currentAlignment.value);
|
|
362
|
+
const ButtonIcon = currentAlignment.icon;
|
|
363
|
+
if (!options.length)
|
|
364
|
+
return null;
|
|
365
|
+
return (_jsx(DropDownMenu, { data: options.map((option) => ({
|
|
366
|
+
label: option.label,
|
|
367
|
+
value: option.value,
|
|
368
|
+
onClick: () => {
|
|
369
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().setTextAlign(option.value).run();
|
|
370
|
+
},
|
|
371
|
+
})), value: selectedAlignment
|
|
372
|
+
? [{ label: selectedAlignment.label, value: selectedAlignment.value }]
|
|
373
|
+
: [], enableSelectedOptionStyling: true, renderOption: (item) => {
|
|
374
|
+
const option = options.find((option) => option.value === item.value);
|
|
375
|
+
const Icon = (option === null || option === void 0 ? void 0 : option.icon) || IconAlignLeft;
|
|
376
|
+
return (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [_jsx(Icon, { size: 14 }), item.label] }));
|
|
377
|
+
}, size: "xs", variant: "outlined", buttonProps: {
|
|
378
|
+
title: currentAlignment.label,
|
|
379
|
+
"aria-label": "Text alignment",
|
|
380
|
+
disabled: !editor,
|
|
381
|
+
selected: Boolean(activeAlignment),
|
|
382
|
+
style: { padding: "1px 6px" },
|
|
383
|
+
}, dropDownProps: {
|
|
384
|
+
style: {
|
|
385
|
+
width: 170,
|
|
386
|
+
},
|
|
387
|
+
}, children: _jsx(ButtonIcon, { size: 14 }) }));
|
|
388
|
+
};
|
|
@@ -12,6 +12,7 @@ const Labels = {
|
|
|
12
12
|
unlinkControlLabel: "Remove link",
|
|
13
13
|
bulletListControlLabel: "Bullet list",
|
|
14
14
|
orderedListControlLabel: "Ordered list",
|
|
15
|
+
taskListControlLabel: "Task list",
|
|
15
16
|
h1ControlLabel: "Heading 1",
|
|
16
17
|
h2ControlLabel: "Heading 2",
|
|
17
18
|
h3ControlLabel: "Heading 3",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
import ControlsGroup from "./ControlsGroup";
|
|
4
|
-
import { UndoControl, RedoControl, FontControl, TextColorControl, HighlightControl, BoldControl, ItalicControl, UnderlineControl, StrikeThroughControl, ClearFormattingControl, CodeControl, CodeBlockControl, BlockquoteControl,
|
|
4
|
+
import { UndoControl, RedoControl, FontControl, TextColorControl, HighlightControl, BoldControl, ItalicControl, UnderlineControl, StrikeThroughControl, ClearFormattingControl, CodeControl, CodeBlockControl, BlockquoteControl, HorizontalRuleControl, HeadingControl, ListControl, AlignmentControl, } from "./Controls";
|
|
5
5
|
import { Controls } from "../Enums";
|
|
6
6
|
import { DropDownMenu } from "../../DropDownMenu";
|
|
7
7
|
import { useState } from "react";
|
|
@@ -10,6 +10,23 @@ import { Popover } from "../../Popover";
|
|
|
10
10
|
import LinkEditor from "../Components/LinkEditor";
|
|
11
11
|
import { TableToolsPopover } from "../Components/TableTools";
|
|
12
12
|
import { LinkIcon } from "lucide-react";
|
|
13
|
+
const headingControlLevels = [
|
|
14
|
+
{ control: Controls.HEADING_1, level: 1 },
|
|
15
|
+
{ control: Controls.HEADING_2, level: 2 },
|
|
16
|
+
{ control: Controls.HEADING_3, level: 3 },
|
|
17
|
+
{ control: Controls.HEADING_4, level: 4 },
|
|
18
|
+
];
|
|
19
|
+
const alignmentControls = [
|
|
20
|
+
{ control: Controls.TEXT_ALIGN_LEFT, alignment: "left" },
|
|
21
|
+
{ control: Controls.TEXT_ALIGN_CENTER, alignment: "center" },
|
|
22
|
+
{ control: Controls.TEXT_ALIGN_RIGHT, alignment: "right" },
|
|
23
|
+
{ control: Controls.TEXT_ALIGN_JUSTIFIED, alignment: "justify" },
|
|
24
|
+
];
|
|
25
|
+
const listControls = [
|
|
26
|
+
{ control: Controls.BULLET_LIST, listType: "bullet" },
|
|
27
|
+
{ control: Controls.ORDERED_LIST, listType: "ordered" },
|
|
28
|
+
{ control: Controls.TASK_LIST, listType: "task" },
|
|
29
|
+
];
|
|
13
30
|
const ToolbarContainer = styled.div `
|
|
14
31
|
display: flex;
|
|
15
32
|
flex-direction: row;
|
|
@@ -32,6 +49,15 @@ export const Toolbar = ({ editor, toolbarOptions }) => {
|
|
|
32
49
|
var _a;
|
|
33
50
|
const { controls } = toolbarOptions || {};
|
|
34
51
|
const [linkPopoverOpen, setLinkPopoverOpen] = useState(false);
|
|
52
|
+
const headingLevels = headingControlLevels
|
|
53
|
+
.filter(({ control }) => controls === null || controls === void 0 ? void 0 : controls.includes(control))
|
|
54
|
+
.map(({ level }) => level);
|
|
55
|
+
const alignments = alignmentControls
|
|
56
|
+
.filter(({ control }) => controls === null || controls === void 0 ? void 0 : controls.includes(control))
|
|
57
|
+
.map(({ alignment }) => alignment);
|
|
58
|
+
const listTypes = listControls
|
|
59
|
+
.filter(({ control }) => controls === null || controls === void 0 ? void 0 : controls.includes(control))
|
|
60
|
+
.map(({ listType }) => listType);
|
|
35
61
|
const customItems = controls === null || controls === void 0 ? void 0 : controls.filter((control) => typeof control !== "string" &&
|
|
36
62
|
(control.type === "menu" || control.type === "button"));
|
|
37
63
|
return (_jsxs(ToolbarContainer, { children: [(_a = customItems === null || customItems === void 0 ? void 0 : customItems.map) === null || _a === void 0 ? void 0 : _a.call(customItems, (item, index) => {
|
|
@@ -46,5 +72,5 @@ export const Toolbar = ({ editor, toolbarOptions }) => {
|
|
|
46
72
|
},
|
|
47
73
|
} }, item.options, { size: "xs", children: (_b = item === null || item === void 0 ? void 0 : item.options) === null || _b === void 0 ? void 0 : _b.label }), index));
|
|
48
74
|
}
|
|
49
|
-
}), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDO)) && _jsx(UndoControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.REDO)) && _jsx(RedoControl, { editor: editor })] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.FONT)) && _jsx(FontControl, {}), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.COLOR)) && (_jsx(TextColorControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HIGHLIGHT)) && (_jsx(HighlightControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BOLD)) && _jsx(BoldControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ITALIC)) && (_jsx(ItalicControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDERLINE)) && (_jsx(UnderlineControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.STRIKE)) && (_jsx(StrikeThroughControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [
|
|
75
|
+
}), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDO)) && _jsx(UndoControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.REDO)) && _jsx(RedoControl, { editor: editor })] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.FONT)) && _jsx(FontControl, {}), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.COLOR)) && (_jsx(TextColorControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HIGHLIGHT)) && (_jsx(HighlightControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BOLD)) && _jsx(BoldControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.ITALIC)) && (_jsx(ItalicControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.UNDERLINE)) && (_jsx(UnderlineControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.STRIKE)) && (_jsx(StrikeThroughControl, { editor: editor }))] }), _jsxs(ControlsGroup, { children: [headingLevels.length > 0 && (_jsx(HeadingControl, { editor: editor, levels: headingLevels })), alignments.length > 0 && (_jsx(AlignmentControl, { editor: editor, alignments: alignments })), listTypes.length > 0 && (_jsx(ListControl, { editor: editor, listTypes: listTypes })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.BLOCKQUOTE)) && (_jsx(BlockquoteControl, { editor: editor }))] }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.LINK)) && (_jsxs(Popover, { opened: linkPopoverOpen, onChange: setLinkPopoverOpen, position: "bottom", width: 330, trapFocus: true, children: [_jsx(Popover.Target, { children: _jsx(Button, { size: "xs", variant: "outlined", title: "Link", "aria-label": "Link", selected: linkPopoverOpen || Boolean(editor === null || editor === void 0 ? void 0 : editor.isActive("link")), disabled: !editor, style: { padding: "1px 6px" }, children: _jsx(LinkIcon, { size: 14 }) }) }), _jsx(Popover.Dropdown, { children: editor && (_jsx(LinkEditor, { editor: editor, autoFocus: linkPopoverOpen, onClose: () => setLinkPopoverOpen(false) })) })] })), _jsxs(ControlsGroup, { children: [(controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE)) && _jsx(CodeControl, { editor: editor }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CODE_BLOCK)) && (_jsx(CodeBlockControl, { editor: editor }))] }), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.TABLE)) && (_jsx(TableToolsPopover, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.HORIZONTAL_RULE)) && (_jsx(HorizontalRuleControl, { editor: editor })), (controls === null || controls === void 0 ? void 0 : controls.includes(Controls.CLEAR_FORMATTING)) && (_jsx(ClearFormattingControl, { editor: editor }))] }));
|
|
50
76
|
};
|