@monolith-forensics/monolith-ui 1.1.47 → 1.1.49
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.d.ts +1 -0
- package/dist/Button/Button.js +3 -1
- package/dist/DropDownMenu/DropDownMenu.d.ts +6 -10
- package/dist/DropDownMenu/DropDownMenu.js +13 -6
- package/dist/DropDownMenu/index.d.ts +1 -0
- package/dist/DropDownMenu/types.d.ts +9 -0
- package/dist/DropDownMenu/types.js +1 -0
- package/dist/Grid/Grid.js +2 -1
- package/dist/Modal/Modal.d.ts +1 -0
- package/dist/Modal/Modal.js +16 -1
- package/dist/RichTextEditor/Components/BubbleMenu.d.ts +34 -0
- package/dist/RichTextEditor/Components/BubbleMenu.js +276 -0
- package/dist/RichTextEditor/Components/SaveBadge.d.ts +6 -0
- package/dist/RichTextEditor/Components/SaveBadge.js +16 -0
- package/dist/RichTextEditor/Enums/Extensions.d.ts +12 -1
- package/dist/RichTextEditor/Enums/Extensions.js +11 -0
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +7 -0
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +157 -0
- package/dist/RichTextEditor/Extensions/SlashCommandList.d.ts +1 -1
- package/dist/RichTextEditor/Extensions/SlashCommandList.js +67 -72
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +50 -50
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +2 -0
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +14 -12
- package/dist/RichTextEditor/RichTextEditor.d.ts +2 -0
- package/dist/RichTextEditor/RichTextEditor.js +8 -2
- package/dist/SelectBox/SelectBox.js +6 -3
- package/dist/TagBox/TagBox.js +4 -2
- package/dist/index.d.ts +2 -0
- package/package.json +3 -1
package/dist/Button/Button.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
13
13
|
variant?: Variant;
|
|
14
14
|
color?: string;
|
|
15
15
|
disabled?: boolean;
|
|
16
|
+
selected?: boolean;
|
|
16
17
|
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
17
18
|
}
|
|
18
19
|
declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
package/dist/Button/Button.js
CHANGED
|
@@ -117,7 +117,7 @@ const StyledButton = styled.button `
|
|
|
117
117
|
}
|
|
118
118
|
}};
|
|
119
119
|
|
|
120
|
-
background-color: ${({ theme, variant, color }) => {
|
|
120
|
+
background-color: ${({ theme, variant, color, selected }) => {
|
|
121
121
|
var _a, _b, _c, _d, _e, _f;
|
|
122
122
|
if (variant === "default")
|
|
123
123
|
return "transparent";
|
|
@@ -144,6 +144,8 @@ const StyledButton = styled.button `
|
|
|
144
144
|
return "transparent";
|
|
145
145
|
case "text":
|
|
146
146
|
return "transparent";
|
|
147
|
+
case "subtle":
|
|
148
|
+
return selected ? theme.palette.action.hover : "transparent";
|
|
147
149
|
default:
|
|
148
150
|
return "transparent";
|
|
149
151
|
}
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
import { ComponentPropsWithoutRef, ComponentType, ReactNode, UIEvent } from "react";
|
|
1
|
+
import { ComponentPropsWithoutRef, ComponentType, ReactElement, ReactNode, UIEvent } from "react";
|
|
2
2
|
import { ButtonProps } from "../Button";
|
|
3
3
|
import { Size, Variant } from "../core";
|
|
4
|
+
import { DropDownItem } from "./types";
|
|
4
5
|
interface StyledContentProps {
|
|
5
6
|
maxDropdownHeight?: number | string;
|
|
6
7
|
variant?: Variant;
|
|
7
8
|
}
|
|
8
9
|
declare const StyledContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, StyledContentProps>> & string;
|
|
9
|
-
interface
|
|
10
|
-
toLowerCase?: () => string;
|
|
11
|
-
label: string;
|
|
12
|
-
value: string;
|
|
13
|
-
data?: any;
|
|
14
|
-
}
|
|
15
|
-
interface DropDownMenuProps {
|
|
10
|
+
export interface DropDownMenuProps {
|
|
16
11
|
className?: string;
|
|
17
|
-
children?: ReactNode;
|
|
12
|
+
children?: ReactNode | string;
|
|
18
13
|
data?: DropDownItem[];
|
|
19
14
|
variant?: Variant;
|
|
20
15
|
defaultValue?: DropDownItem[];
|
|
@@ -30,7 +25,8 @@ interface DropDownMenuProps {
|
|
|
30
25
|
arrow?: boolean;
|
|
31
26
|
searchable?: boolean;
|
|
32
27
|
dropDownProps?: ComponentPropsWithoutRef<typeof StyledContent>;
|
|
28
|
+
buttonRender?: (props: any) => ReactElement;
|
|
33
29
|
buttonProps?: ButtonProps;
|
|
34
30
|
}
|
|
35
|
-
declare const DropDownMenu: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<DropDownMenuProps, never>> & string & Omit<({ className, children, data, variant, defaultValue, multiselect, size, TooltipContent, renderOption, onChange, onItemSelect, onScroll, loading, arrow, searchable, dropDownProps, buttonProps, }: DropDownMenuProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
31
|
+
declare const DropDownMenu: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<DropDownMenuProps, never>> & string & Omit<({ className, children, data, variant, defaultValue, multiselect, size, TooltipContent, renderOption, onChange, onItemSelect, onScroll, loading, arrow, searchable, dropDownProps, buttonRender, buttonProps, }: DropDownMenuProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
36
32
|
export default DropDownMenu;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { FloatingFocusManager, FloatingPortal, flip, useFloating, } from "@floating-ui/react";
|
|
2
|
+
import { FloatingFocusManager, FloatingPortal, flip, offset, useFloating, } from "@floating-ui/react";
|
|
3
3
|
import { forwardRef, useEffect, useRef, useState, } from "react";
|
|
4
4
|
import styled from "styled-components";
|
|
5
5
|
import { Button, Tooltip, CheckBox, Input } from "..";
|
|
6
6
|
import { useDebouncedCallback } from "use-debounce";
|
|
7
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
7
8
|
const StyledFloatContainer = styled.div `
|
|
8
9
|
z-index: 1500;
|
|
9
10
|
`;
|
|
@@ -107,7 +108,7 @@ const StyledContent = styled.div `
|
|
|
107
108
|
display: none;
|
|
108
109
|
}
|
|
109
110
|
`;
|
|
110
|
-
const DropDownMenu = styled(({ className, children, data = [], variant = "outlined", defaultValue, multiselect = false, size = "xs", TooltipContent, renderOption, onChange, onItemSelect, onScroll, loading, arrow, searchable, dropDownProps, buttonProps, }) => {
|
|
111
|
+
const DropDownMenu = styled(({ className, children, data = [], variant = "outlined", defaultValue, multiselect = false, size = "xs", TooltipContent, renderOption, onChange, onItemSelect, onScroll, loading, arrow, searchable, dropDownProps, buttonRender, buttonProps, }) => {
|
|
111
112
|
var _a, _b, _c;
|
|
112
113
|
const isObjectArray = (_a = Object.keys((data === null || data === void 0 ? void 0 : data[0]) || {})) === null || _a === void 0 ? void 0 : _a.includes("label");
|
|
113
114
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -121,7 +122,7 @@ const DropDownMenu = styled(({ className, children, data = [], variant = "outlin
|
|
|
121
122
|
placement: "bottom-start",
|
|
122
123
|
strategy: "absolute",
|
|
123
124
|
// Handle collisions with the viewport
|
|
124
|
-
middleware: [flip()],
|
|
125
|
+
middleware: [flip(), offset(3)],
|
|
125
126
|
});
|
|
126
127
|
const handleAddItem = (item) => {
|
|
127
128
|
setSelected((prev) => {
|
|
@@ -171,9 +172,13 @@ const DropDownMenu = styled(({ className, children, data = [], variant = "outlin
|
|
|
171
172
|
}, [isOpen, searchable]);
|
|
172
173
|
const scrollActive = (((_b = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current) === null || _b === void 0 ? void 0 : _b.scrollHeight) || 0) >
|
|
173
174
|
(((_c = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current) === null || _c === void 0 ? void 0 : _c.clientHeight) || 0);
|
|
174
|
-
return (_jsxs("div", { className: className + " mfDropDownMenu", children: [
|
|
175
|
+
return (_jsxs("div", { className: className + " mfDropDownMenu", children: [buttonRender ? (buttonRender({
|
|
176
|
+
onClick: () => setIsOpen(!isOpen),
|
|
177
|
+
buttonRef: refs.setReference,
|
|
178
|
+
isOpen,
|
|
179
|
+
})) : (_jsx(Button, Object.assign({ ref: (ref) => {
|
|
175
180
|
refs.setReference(ref);
|
|
176
|
-
},
|
|
181
|
+
}, onClick: () => setIsOpen(!isOpen), rightSection: arrow ? _jsx(ChevronDownIcon, { size: 12 }) : null, size: size, variant: variant, selected: isOpen }, buttonProps, { children: children }))), isOpen && (_jsx(FloatingPortal, { preserveTabOrder: true, children: _jsx(FloatingFocusManager, { context: context, modal: false, children: _jsx(StyledFloatContainer, { ref: refs.setFloating, style: floatingStyles, className: "mfFloating", children: _jsx(StyledContent, Object.assign({ className: "mfFloatingContent", style: { width: 150, maxWidth: 400 } }, dropDownProps, { children: _jsxs(StyledInnerItemContainer, { ref: scrollContainerRef, "data-scroll-active": scrollActive, onScroll: onScroll, children: [loading && _jsx("div", { children: "Loading..." }), searchable && (_jsx(SearchInput, { ref: searchInputRef, variant: "outlined", size: size, placeholder: "Search", onChange: handleSearch })), !loading &&
|
|
177
182
|
data
|
|
178
183
|
.filter((item) => {
|
|
179
184
|
var _a, _b, _c;
|
|
@@ -191,6 +196,7 @@ const DropDownMenu = styled(({ className, children, data = [], variant = "outlin
|
|
|
191
196
|
? (s === null || s === void 0 ? void 0 : s.value) === (item === null || item === void 0 ? void 0 : item.value)
|
|
192
197
|
: s === item));
|
|
193
198
|
return (_jsx(Tooltip, { content: TooltipContent ? (_jsx(TooltipContent, { data: item.data })) : null, side: "left", children: _jsxs(StyledItem, { className: "mfFloatingItem", onClick: (e) => {
|
|
199
|
+
var _a;
|
|
194
200
|
e.preventDefault();
|
|
195
201
|
e.stopPropagation();
|
|
196
202
|
if (multiselect) {
|
|
@@ -202,7 +208,8 @@ const DropDownMenu = styled(({ className, children, data = [], variant = "outlin
|
|
|
202
208
|
setIsOpen(false);
|
|
203
209
|
}
|
|
204
210
|
onItemSelect === null || onItemSelect === void 0 ? void 0 : onItemSelect(item);
|
|
205
|
-
|
|
211
|
+
(_a = item === null || item === void 0 ? void 0 : item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, item);
|
|
212
|
+
}, "data-selected": isSelected, size: size, children: [multiselect && _jsx(CheckBox, { value: isSelected }), (item === null || item === void 0 ? void 0 : item.leftSection) || null, _jsx(_Fragment, { children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || (item === null || item === void 0 ? void 0 : item.label) || item }), (item === null || item === void 0 ? void 0 : item.rightSection) || null] }) }, index));
|
|
206
213
|
})] }) })) }) }) }))] }));
|
|
207
214
|
}) ``;
|
|
208
215
|
export default DropDownMenu;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/Grid/Grid.js
CHANGED
|
@@ -5,7 +5,8 @@ const Grid = styled(({ className, children }) => {
|
|
|
5
5
|
}) `
|
|
6
6
|
display: grid;
|
|
7
7
|
grid-template-columns: repeat(${({ col }) => col || 1}, minmax(0, 1fr));
|
|
8
|
-
gap: 20px;
|
|
8
|
+
column-gap: 20px;
|
|
9
|
+
row-gap: 15px;
|
|
9
10
|
|
|
10
11
|
width: ${({ width }) => Number.isInteger(width) ? `${width}px` : width || "100%"};
|
|
11
12
|
height: auto;
|
package/dist/Modal/Modal.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ declare const Modal: {
|
|
|
10
10
|
({ children, open, onClose, style, showCloseButton, FocusProps, }: ModalProps): import("react/jsx-runtime").JSX.Element;
|
|
11
11
|
Title: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never>> & string;
|
|
12
12
|
SubTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never>> & string;
|
|
13
|
+
Content: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
13
14
|
};
|
|
14
15
|
export default Modal;
|
package/dist/Modal/Modal.js
CHANGED
|
@@ -70,11 +70,20 @@ const StyledClose = styled.div `
|
|
|
70
70
|
color: ${(props) => props.theme.palette.text.secondary};
|
|
71
71
|
`;
|
|
72
72
|
const StyledButton = styled.button `
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
color: ${(props) => props.theme.palette.text.secondary};
|
|
73
77
|
background-color: transparent;
|
|
78
|
+
border-radius: 4px;
|
|
74
79
|
border: none;
|
|
75
80
|
outline: none;
|
|
76
81
|
cursor: pointer;
|
|
77
|
-
padding:
|
|
82
|
+
padding: 2px;
|
|
83
|
+
|
|
84
|
+
&:hover {
|
|
85
|
+
background-color: ${(props) => props.theme.palette.action.hover};
|
|
86
|
+
}
|
|
78
87
|
`;
|
|
79
88
|
const Title = styled.h1 `
|
|
80
89
|
font-size: 20px;
|
|
@@ -87,6 +96,11 @@ const SubTitle = styled.h2 `
|
|
|
87
96
|
margin: 0px;
|
|
88
97
|
color: ${(props) => props.theme.palette.text.secondary};
|
|
89
98
|
`;
|
|
99
|
+
const ModalContent = styled.div `
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-direction: column;
|
|
102
|
+
gap: 1rem;
|
|
103
|
+
`;
|
|
90
104
|
const Modal = ({ children, open = false, onClose, style = {}, showCloseButton = false, FocusProps = {}, }) => {
|
|
91
105
|
const { refs, floatingStyles, context } = useFloating({
|
|
92
106
|
open,
|
|
@@ -103,4 +117,5 @@ const Modal = ({ children, open = false, onClose, style = {}, showCloseButton =
|
|
|
103
117
|
};
|
|
104
118
|
Modal.Title = Title;
|
|
105
119
|
Modal.SubTitle = SubTitle;
|
|
120
|
+
Modal.Content = ModalContent;
|
|
106
121
|
export default Modal;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Extensions from "../Enums/Extensions";
|
|
2
|
+
import { DropDownItem } from "../../DropDownMenu";
|
|
3
|
+
import { ReactElement } from "react";
|
|
4
|
+
import { ButtonProps } from "../../Button";
|
|
5
|
+
import { Editor } from "@tiptap/react";
|
|
6
|
+
import { DropDownMenuProps } from "../../DropDownMenu/DropDownMenu";
|
|
7
|
+
export interface BubbleMenuProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
editor: Editor;
|
|
10
|
+
rect: DOMRect;
|
|
11
|
+
open: boolean;
|
|
12
|
+
onOpen?: (element: HTMLElement) => void;
|
|
13
|
+
customMenuItems?: BubbleItem[];
|
|
14
|
+
}
|
|
15
|
+
interface BubbleMenuDropDownItem extends DropDownItem {
|
|
16
|
+
data?: {
|
|
17
|
+
command?: (editor: Editor, selectedText: string) => void;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export type BubbleItem = {
|
|
21
|
+
name: Extensions | string;
|
|
22
|
+
icon?: React.FC<any>;
|
|
23
|
+
type?: "button" | "menu";
|
|
24
|
+
label?: string | Element;
|
|
25
|
+
items?: BubbleMenuDropDownItem[];
|
|
26
|
+
arrow?: boolean;
|
|
27
|
+
isActive?: (editor: Editor) => boolean;
|
|
28
|
+
buttonRender?: (props: any) => ReactElement;
|
|
29
|
+
buttonProps?: ButtonProps;
|
|
30
|
+
dropDownProps?: DropDownMenuProps;
|
|
31
|
+
onClick?: (editor: Editor) => void;
|
|
32
|
+
};
|
|
33
|
+
declare const BubbleMenu: React.FC<BubbleMenuProps>;
|
|
34
|
+
export default BubbleMenu;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import Extensions from "../Enums/Extensions";
|
|
4
|
+
import { BoldIcon, ItalicIcon, UnderlineIcon, CaseSensitiveIcon, ListIcon, ListOrderedIcon, StrikethroughIcon, Heading1Icon, Heading2Icon, Heading3Icon, Heading4Icon, RemoveFormattingIcon, } from "lucide-react";
|
|
5
|
+
import DropDownMenu from "../../DropDownMenu";
|
|
6
|
+
import { FloatingPortal, useFloating } from "@floating-ui/react";
|
|
7
|
+
import { useEffect, useRef } from "react";
|
|
8
|
+
import Button from "../../Button";
|
|
9
|
+
const getMenuItems = (editor, customMenuItems) => {
|
|
10
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
11
|
+
const node = (_c = (_b = (_a = editor === null || editor === void 0 ? void 0 : editor.state) === null || _a === void 0 ? void 0 : _a.selection) === null || _b === void 0 ? void 0 : _b.$from) === null || _c === void 0 ? void 0 : _c.parent;
|
|
12
|
+
const pos = (_e = (_d = editor === null || editor === void 0 ? void 0 : editor.state) === null || _d === void 0 ? void 0 : _d.selection) === null || _e === void 0 ? void 0 : _e.$from;
|
|
13
|
+
let withinUnorderedList = false;
|
|
14
|
+
let withinOrderedList = false;
|
|
15
|
+
// Traverse the node ancestors
|
|
16
|
+
pos.path.forEach((node) => {
|
|
17
|
+
var _a, _b;
|
|
18
|
+
if (((_a = node === null || node === void 0 ? void 0 : node.type) === null || _a === void 0 ? void 0 : _a.name) === "bulletList") {
|
|
19
|
+
withinUnorderedList = true;
|
|
20
|
+
}
|
|
21
|
+
else if (((_b = node === null || node === void 0 ? void 0 : node.type) === null || _b === void 0 ? void 0 : _b.name) === "orderedList") {
|
|
22
|
+
withinOrderedList = true;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const attrs = node === null || node === void 0 ? void 0 : node.attrs;
|
|
26
|
+
let nodeTypeLabel = "Select Type";
|
|
27
|
+
let nodeTypeIcon = null;
|
|
28
|
+
if (withinOrderedList) {
|
|
29
|
+
nodeTypeLabel = "Ordered List";
|
|
30
|
+
nodeTypeIcon = _jsx(ListOrderedIcon, { size: 16 });
|
|
31
|
+
}
|
|
32
|
+
else if (withinUnorderedList) {
|
|
33
|
+
nodeTypeLabel = "Bullet List";
|
|
34
|
+
nodeTypeIcon = _jsx(ListIcon, { size: 16 });
|
|
35
|
+
}
|
|
36
|
+
else if (((_f = node === null || node === void 0 ? void 0 : node.type) === null || _f === void 0 ? void 0 : _f.name) === "paragraph") {
|
|
37
|
+
nodeTypeLabel = "Text";
|
|
38
|
+
nodeTypeIcon = _jsx(CaseSensitiveIcon, { size: 16 });
|
|
39
|
+
}
|
|
40
|
+
else if (((_g = node === null || node === void 0 ? void 0 : node.type) === null || _g === void 0 ? void 0 : _g.name) === "heading") {
|
|
41
|
+
const level = attrs === null || attrs === void 0 ? void 0 : attrs.level;
|
|
42
|
+
nodeTypeLabel = `Heading ${level}`;
|
|
43
|
+
nodeTypeIcon =
|
|
44
|
+
level === 1 ? (_jsx(Heading1Icon, { size: 16 })) : level === 2 ? (_jsx(Heading2Icon, { size: 16 })) : level === 3 ? (_jsx(Heading3Icon, { size: 16 })) : (_jsx(Heading4Icon, { size: 16 }));
|
|
45
|
+
}
|
|
46
|
+
return [
|
|
47
|
+
...customMenuItems,
|
|
48
|
+
{
|
|
49
|
+
name: "node_type",
|
|
50
|
+
label: nodeTypeLabel,
|
|
51
|
+
type: "menu",
|
|
52
|
+
arrow: true,
|
|
53
|
+
buttonProps: {
|
|
54
|
+
leftSection: nodeTypeIcon,
|
|
55
|
+
style: { fontSize: 11, padding: "4px" },
|
|
56
|
+
},
|
|
57
|
+
items: [
|
|
58
|
+
{
|
|
59
|
+
label: "Text",
|
|
60
|
+
value: "text",
|
|
61
|
+
leftSection: _jsx(CaseSensitiveIcon, { size: 16 }),
|
|
62
|
+
data: {
|
|
63
|
+
command: (editor) => {
|
|
64
|
+
// remove ordered list
|
|
65
|
+
editor
|
|
66
|
+
.chain()
|
|
67
|
+
.focus()
|
|
68
|
+
.liftListItem("listItem")
|
|
69
|
+
.setParagraph()
|
|
70
|
+
.run();
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
label: "Heading 1",
|
|
76
|
+
value: "heading_1",
|
|
77
|
+
leftSection: _jsx(Heading1Icon, { size: 16 }),
|
|
78
|
+
data: {
|
|
79
|
+
command: (editor) => {
|
|
80
|
+
editor.chain().focus().setHeading({ level: 1 }).run();
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
label: "Heading 2",
|
|
86
|
+
value: "heading_2",
|
|
87
|
+
leftSection: _jsx(Heading2Icon, { size: 16 }),
|
|
88
|
+
data: {
|
|
89
|
+
command: (editor) => {
|
|
90
|
+
editor.chain().focus().setHeading({ level: 2 }).run();
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: "Heading 3",
|
|
96
|
+
value: "heading_3",
|
|
97
|
+
leftSection: _jsx(Heading3Icon, { size: 16 }),
|
|
98
|
+
data: {
|
|
99
|
+
command: (editor) => {
|
|
100
|
+
editor.chain().focus().setHeading({ level: 3 }).run();
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
label: "Heading 4",
|
|
106
|
+
value: "heading_4",
|
|
107
|
+
leftSection: _jsx(Heading4Icon, { size: 16 }),
|
|
108
|
+
data: {
|
|
109
|
+
command: (editor) => {
|
|
110
|
+
editor.chain().focus().setHeading({ level: 4 }).run();
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
label: "Bullet List",
|
|
116
|
+
value: "bullet_list",
|
|
117
|
+
leftSection: _jsx(ListIcon, { size: 16 }),
|
|
118
|
+
data: {
|
|
119
|
+
command: (editor) => {
|
|
120
|
+
editor.chain().focus().toggleBulletList().run();
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
label: "Ordered List",
|
|
126
|
+
value: "ordered_list",
|
|
127
|
+
leftSection: _jsx(ListOrderedIcon, { size: 16 }),
|
|
128
|
+
data: {
|
|
129
|
+
command: (editor) => {
|
|
130
|
+
editor.chain().focus().toggleOrderedList().run();
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: Extensions.Bold,
|
|
138
|
+
icon: BoldIcon,
|
|
139
|
+
type: "button",
|
|
140
|
+
isActive: (editor) => editor.isActive("bold"),
|
|
141
|
+
onClick: (editor) => {
|
|
142
|
+
editor.chain().focus().toggleBold().run();
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: Extensions.Italic,
|
|
147
|
+
icon: ItalicIcon,
|
|
148
|
+
type: "button",
|
|
149
|
+
isActive: (editor) => editor.isActive("italic"),
|
|
150
|
+
onClick: (editor) => {
|
|
151
|
+
editor.chain().focus().toggleItalic().run();
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: Extensions.Underline,
|
|
156
|
+
icon: UnderlineIcon,
|
|
157
|
+
type: "button",
|
|
158
|
+
isActive: (editor) => editor.isActive("underline"),
|
|
159
|
+
onClick: (editor) => {
|
|
160
|
+
editor.chain().focus().toggleUnderline().run();
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: Extensions.Strike,
|
|
165
|
+
icon: StrikethroughIcon,
|
|
166
|
+
type: "button",
|
|
167
|
+
isActive: (editor) => editor.isActive("strike"),
|
|
168
|
+
onClick: (editor) => {
|
|
169
|
+
editor.chain().focus().toggleStrike().run();
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: Extensions.ClearFormatting,
|
|
174
|
+
icon: RemoveFormattingIcon,
|
|
175
|
+
type: "button",
|
|
176
|
+
onClick: (editor) => {
|
|
177
|
+
editor.chain().focus().setParagraph().run();
|
|
178
|
+
editor.chain().focus().unsetAllMarks().run();
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
];
|
|
182
|
+
};
|
|
183
|
+
const BubbleMenuContent = styled.div `
|
|
184
|
+
position: fixed;
|
|
185
|
+
display: flex;
|
|
186
|
+
justify-content: space-between;
|
|
187
|
+
align-items: center;
|
|
188
|
+
padding: 2px;
|
|
189
|
+
gap: 2px;
|
|
190
|
+
|
|
191
|
+
color: ${({ theme }) => theme.palette.text.primary};
|
|
192
|
+
background-color: ${({ theme }) => theme.palette.input.background};
|
|
193
|
+
|
|
194
|
+
border-radius: 5px;
|
|
195
|
+
border: 1px solid ${(props) => props.theme.palette.divider};
|
|
196
|
+
|
|
197
|
+
font-size: 0.8rem;
|
|
198
|
+
|
|
199
|
+
min-height: 30px;
|
|
200
|
+
|
|
201
|
+
opacity: 0;
|
|
202
|
+
transform: scale(0.25); /* Start at half size */
|
|
203
|
+
animation: fadeInEffect 90ms forwards;
|
|
204
|
+
|
|
205
|
+
/* Animation to handle the fade in */
|
|
206
|
+
@keyframes fadeInEffect {
|
|
207
|
+
0% {
|
|
208
|
+
opacity: 0;
|
|
209
|
+
transform: scale(0.25);
|
|
210
|
+
}
|
|
211
|
+
100% {
|
|
212
|
+
opacity: 1;
|
|
213
|
+
transform: scale(1);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
`;
|
|
217
|
+
const BubbleItemButton = styled(Button) `
|
|
218
|
+
font-size: 0.5rem;
|
|
219
|
+
font-weight: 500;
|
|
220
|
+
padding: 4px;
|
|
221
|
+
height: auto;
|
|
222
|
+
|
|
223
|
+
&.is-active {
|
|
224
|
+
opacity: 1;
|
|
225
|
+
color: ${({ theme }) => theme.palette.primary.main};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
&:hover {
|
|
229
|
+
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
230
|
+
}
|
|
231
|
+
`;
|
|
232
|
+
const BubbleMenu = ({ editor, rect, open, onOpen, customMenuItems = [], }) => {
|
|
233
|
+
var _a;
|
|
234
|
+
const menuRef = useRef(null);
|
|
235
|
+
const { refs, elements } = useFloating();
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
if (open && onOpen) {
|
|
238
|
+
onOpen(elements.floating);
|
|
239
|
+
}
|
|
240
|
+
}, [open, onOpen, elements.floating]);
|
|
241
|
+
const elementWidth = ((_a = elements.floating) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0;
|
|
242
|
+
const { from, to } = editor.state.selection;
|
|
243
|
+
const selectedText = editor.state.doc.textBetween(from, to);
|
|
244
|
+
let top = (rect === null || rect === void 0 ? void 0 : rect.top) ? rect.top - 50 : 0;
|
|
245
|
+
if (top < 10) {
|
|
246
|
+
top = 10; // add some padding
|
|
247
|
+
}
|
|
248
|
+
let left = (rect === null || rect === void 0 ? void 0 : rect.left) ? rect.left + rect.width / 2 - elementWidth / 2 : 0;
|
|
249
|
+
if (left < 10) {
|
|
250
|
+
left = 10; // add some padding
|
|
251
|
+
}
|
|
252
|
+
// Check if the menu is overflowing on the right
|
|
253
|
+
const rightOverflow = left + elementWidth - window.innerWidth;
|
|
254
|
+
if (rightOverflow > -10) {
|
|
255
|
+
left -= rightOverflow + 10; // add some padding
|
|
256
|
+
}
|
|
257
|
+
return (_jsx(FloatingPortal, { preserveTabOrder: true, children: open && (_jsx(BubbleMenuContent, { ref: (ref) => {
|
|
258
|
+
refs.setFloating(ref);
|
|
259
|
+
menuRef.current = ref;
|
|
260
|
+
}, style: {
|
|
261
|
+
top,
|
|
262
|
+
left,
|
|
263
|
+
}, children: getMenuItems(editor, customMenuItems).map((item) => {
|
|
264
|
+
var _a;
|
|
265
|
+
if (item.type === "button") {
|
|
266
|
+
const isActive = (_a = item.isActive) === null || _a === void 0 ? void 0 : _a.call(item, editor);
|
|
267
|
+
return (_jsx(BubbleItemButton, { variant: "subtle", onClick: () => { var _a; return (_a = item === null || item === void 0 ? void 0 : item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, editor); }, color: isActive ? "primary" : undefined, selected: isActive, children: item.icon && _jsx(item.icon, { size: 14 }) }, item.name));
|
|
268
|
+
}
|
|
269
|
+
if (item.type === "menu") {
|
|
270
|
+
return (_jsx(DropDownMenu, Object.assign({ data: item.items, size: "xs", arrow: item.arrow, buttonProps: item.buttonProps, variant: "subtle", buttonRender: item.buttonRender, onItemSelect: (item) => { var _a, _b; return (_b = (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.command) === null || _b === void 0 ? void 0 : _b.call(_a, editor, selectedText); } }, item.dropDownProps, { children: item.icon
|
|
271
|
+
? (_jsx(item.icon, { size: 14 }))
|
|
272
|
+
: (item.label || item.name) }), item.name));
|
|
273
|
+
}
|
|
274
|
+
}) })) }));
|
|
275
|
+
};
|
|
276
|
+
export default BubbleMenu;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const SavingBadge: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<{
|
|
2
|
+
className?: string;
|
|
3
|
+
}, never>> & string & Omit<({ className }: {
|
|
4
|
+
className?: string;
|
|
5
|
+
}) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
6
|
+
export default SavingBadge;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
const SavingBadge = styled(({ className }) => {
|
|
4
|
+
return (_jsx("div", { className: className, children: _jsx("div", { className: "saving-badge", children: _jsx("span", { children: "Saving..." }) }) }));
|
|
5
|
+
}) `
|
|
6
|
+
position: absolute;
|
|
7
|
+
top: 0px;
|
|
8
|
+
left: 10px;
|
|
9
|
+
display: flex;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
align-items: center;
|
|
12
|
+
font-size: 0.75rem;
|
|
13
|
+
font-weight: 500;
|
|
14
|
+
color: ${({ theme }) => theme.palette.text.secondary};
|
|
15
|
+
`;
|
|
16
|
+
export default SavingBadge;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
declare enum Extensions {
|
|
2
|
+
ClearFormatting = "clearFormatting",
|
|
2
3
|
HorizontalRule = "horizontalRule",
|
|
3
4
|
Underline = "underline",
|
|
5
|
+
Bold = "bold",
|
|
6
|
+
Italic = "italic",
|
|
7
|
+
Strike = "strike",
|
|
8
|
+
BulletList = "bulletList",
|
|
9
|
+
OrderedList = "orderedList",
|
|
10
|
+
AlignLeft = "alignLeft",
|
|
11
|
+
AlignCenter = "alignCenter",
|
|
12
|
+
AlignRight = "alignRight",
|
|
13
|
+
AlignJustify = "alignJustify",
|
|
4
14
|
TextAlign = "textAlign",
|
|
5
15
|
Table = "table",
|
|
6
16
|
TableCell = "tableCell",
|
|
@@ -10,6 +20,7 @@ declare enum Extensions {
|
|
|
10
20
|
Focus = "focus",
|
|
11
21
|
Image = "image",
|
|
12
22
|
CustomStorage = "storage",
|
|
13
|
-
SlashCommand = "slashCommand"
|
|
23
|
+
SlashCommand = "slashCommand",
|
|
24
|
+
BubbleMenu = "bubbleMenu"
|
|
14
25
|
}
|
|
15
26
|
export default Extensions;
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
var Extensions;
|
|
2
2
|
(function (Extensions) {
|
|
3
|
+
Extensions["ClearFormatting"] = "clearFormatting";
|
|
3
4
|
Extensions["HorizontalRule"] = "horizontalRule";
|
|
4
5
|
Extensions["Underline"] = "underline";
|
|
6
|
+
Extensions["Bold"] = "bold";
|
|
7
|
+
Extensions["Italic"] = "italic";
|
|
8
|
+
Extensions["Strike"] = "strike";
|
|
9
|
+
Extensions["BulletList"] = "bulletList";
|
|
10
|
+
Extensions["OrderedList"] = "orderedList";
|
|
11
|
+
Extensions["AlignLeft"] = "alignLeft";
|
|
12
|
+
Extensions["AlignCenter"] = "alignCenter";
|
|
13
|
+
Extensions["AlignRight"] = "alignRight";
|
|
14
|
+
Extensions["AlignJustify"] = "alignJustify";
|
|
5
15
|
Extensions["TextAlign"] = "textAlign";
|
|
6
16
|
Extensions["Table"] = "table";
|
|
7
17
|
Extensions["TableCell"] = "tableCell";
|
|
@@ -12,5 +22,6 @@ var Extensions;
|
|
|
12
22
|
Extensions["Image"] = "image";
|
|
13
23
|
Extensions["CustomStorage"] = "storage";
|
|
14
24
|
Extensions["SlashCommand"] = "slashCommand";
|
|
25
|
+
Extensions["BubbleMenu"] = "bubbleMenu";
|
|
15
26
|
})(Extensions || (Extensions = {}));
|
|
16
27
|
export default Extensions;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Extension, isNodeSelection, isTextSelection, posToDOMRect, } from "@tiptap/core";
|
|
2
|
+
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
3
|
+
import { ReactRenderer } from "@tiptap/react";
|
|
4
|
+
import BubbleMenuComponent from "../Components/BubbleMenu";
|
|
5
|
+
class Menu {
|
|
6
|
+
constructor({ view, editor, customMenuItems, }) {
|
|
7
|
+
this.mousedownHandler = (event) => {
|
|
8
|
+
this.preventShow = true;
|
|
9
|
+
};
|
|
10
|
+
this.mouseUpHandler = (event) => {
|
|
11
|
+
this.preventShow = false;
|
|
12
|
+
this.update(this.editor.view);
|
|
13
|
+
};
|
|
14
|
+
this.focusHandler = () => {
|
|
15
|
+
// this.editor.commands.setTextSelection({ from: 0, to: 0 });
|
|
16
|
+
// we use `setTimeout` to make sure `selection` is already updated
|
|
17
|
+
setTimeout(() => this.update(this.editor.view));
|
|
18
|
+
};
|
|
19
|
+
this.blurHandler = ({ event }) => {
|
|
20
|
+
var _a;
|
|
21
|
+
if (this.preventShow) {
|
|
22
|
+
this.preventShow = false;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if ((event === null || event === void 0 ? void 0 : event.relatedTarget) &&
|
|
26
|
+
((_a = this.floating) === null || _a === void 0 ? void 0 : _a.contains(event === null || event === void 0 ? void 0 : event.relatedTarget))) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// clear text selection
|
|
30
|
+
// this.editor.commands.setTextSelection({ from: 0, to: 0 });
|
|
31
|
+
this.hide();
|
|
32
|
+
};
|
|
33
|
+
this.editor = editor;
|
|
34
|
+
this.view = view;
|
|
35
|
+
this.rect = null;
|
|
36
|
+
this.preventShow = false;
|
|
37
|
+
this.floating = null;
|
|
38
|
+
this.isOpen = false;
|
|
39
|
+
// create and mount react component
|
|
40
|
+
if (!this.component) {
|
|
41
|
+
this.component = new ReactRenderer(BubbleMenuComponent, {
|
|
42
|
+
props: {
|
|
43
|
+
editor: this.editor,
|
|
44
|
+
open: false,
|
|
45
|
+
onOpen: (ref) => {
|
|
46
|
+
this.floating = ref;
|
|
47
|
+
},
|
|
48
|
+
customMenuItems,
|
|
49
|
+
},
|
|
50
|
+
editor: this.editor,
|
|
51
|
+
});
|
|
52
|
+
document.body.appendChild(this.component.element);
|
|
53
|
+
}
|
|
54
|
+
// don't show the bubble during selection of text
|
|
55
|
+
this.view.dom.addEventListener("mousedown", this.mousedownHandler, {
|
|
56
|
+
capture: true,
|
|
57
|
+
});
|
|
58
|
+
this.view.dom.addEventListener("mouseup", this.mouseUpHandler);
|
|
59
|
+
this.editor.on("blur", this.blurHandler);
|
|
60
|
+
this.editor.on("focus", this.focusHandler);
|
|
61
|
+
}
|
|
62
|
+
update(view, oldState) {
|
|
63
|
+
var _a;
|
|
64
|
+
const { state, composing } = view;
|
|
65
|
+
const { doc, selection } = state;
|
|
66
|
+
const { empty, ranges } = selection;
|
|
67
|
+
const from = Math.min(...ranges.map((range) => range.$from.pos));
|
|
68
|
+
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
|
69
|
+
const selectionChanged = !(oldState === null || oldState === void 0 ? void 0 : oldState.selection.eq(view.state.selection));
|
|
70
|
+
const docChanged = !(oldState === null || oldState === void 0 ? void 0 : oldState.doc.eq(view.state.doc));
|
|
71
|
+
const isSame = !selectionChanged && !docChanged;
|
|
72
|
+
if (composing || isSame) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Sometime check for `empty` is not enough.
|
|
76
|
+
// Doubleclick an empty paragraph returns a node size of 2.
|
|
77
|
+
// So we check also for an empty text size.
|
|
78
|
+
const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(state.selection);
|
|
79
|
+
// When clicking on a element inside the bubble menu the editor "blur" event
|
|
80
|
+
// is called and the bubble menu item is focussed. In this case we should
|
|
81
|
+
// consider the menu as part of the editor and keep showing the menu
|
|
82
|
+
const isChildOfMenu = (_a = this === null || this === void 0 ? void 0 : this.floating) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);
|
|
83
|
+
const hasEditorFocus = view.hasFocus() || isChildOfMenu;
|
|
84
|
+
if (!hasEditorFocus ||
|
|
85
|
+
empty ||
|
|
86
|
+
isEmptyTextBlock ||
|
|
87
|
+
!this.editor.isEditable ||
|
|
88
|
+
this.preventShow) {
|
|
89
|
+
this.hide();
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// only set position when it is not already open
|
|
93
|
+
// otherwise the menu will jump around when the selection changes or text formatting is applied
|
|
94
|
+
if (!this.isOpen) {
|
|
95
|
+
if (isNodeSelection(state.selection)) {
|
|
96
|
+
let node = view.nodeDOM(from);
|
|
97
|
+
const nodeViewWrapper = node.dataset.nodeViewWrapper
|
|
98
|
+
? node
|
|
99
|
+
: node.querySelector("[data-node-view-wrapper]");
|
|
100
|
+
if (nodeViewWrapper) {
|
|
101
|
+
node = nodeViewWrapper.firstChild;
|
|
102
|
+
}
|
|
103
|
+
if (node) {
|
|
104
|
+
this.rect = node.getBoundingClientRect();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.rect = posToDOMRect(view, from, to);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
this.show();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
show() {
|
|
115
|
+
if (this.component) {
|
|
116
|
+
this.component.updateProps({ open: true, rect: this.rect });
|
|
117
|
+
this.isOpen = true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
hide() {
|
|
121
|
+
if (this.component) {
|
|
122
|
+
this.component.updateProps({ open: false, rect: null });
|
|
123
|
+
this.isOpen = false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
destroy() {
|
|
127
|
+
if (this.component) {
|
|
128
|
+
this.view.dom.removeEventListener("mousedown", this.mousedownHandler);
|
|
129
|
+
this.view.dom.removeEventListener("mouseup", this.mouseUpHandler);
|
|
130
|
+
this.component.destroy();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const BubbleMenu = Extension.create({
|
|
135
|
+
name: "bubbleMenu",
|
|
136
|
+
addOptions() {
|
|
137
|
+
return {
|
|
138
|
+
bubbleMenuOptions: {},
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
addProseMirrorPlugins() {
|
|
142
|
+
return [
|
|
143
|
+
new Plugin({
|
|
144
|
+
key: new PluginKey("bubbleMenu"),
|
|
145
|
+
view: (view) => {
|
|
146
|
+
var _a;
|
|
147
|
+
return new Menu({
|
|
148
|
+
view,
|
|
149
|
+
editor: this.editor,
|
|
150
|
+
customMenuItems: ((_a = this === null || this === void 0 ? void 0 : this.options) === null || _a === void 0 ? void 0 : _a.customMenuItems) || [],
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
}),
|
|
154
|
+
];
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
export default BubbleMenu;
|
|
@@ -5,5 +5,5 @@ interface SlashCommandListProps {
|
|
|
5
5
|
editor: any;
|
|
6
6
|
range: any;
|
|
7
7
|
}
|
|
8
|
-
declare const SlashCommandList:
|
|
8
|
+
declare const SlashCommandList: ({ items, command, editor, range, }: SlashCommandListProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
9
9
|
export default SlashCommandList;
|
|
@@ -1,6 +1,69 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react";
|
|
3
3
|
import styled from "styled-components";
|
|
4
|
+
const SlashCommandListContainer = styled.div `
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: 0.25rem;
|
|
8
|
+
z-index: 16001;
|
|
9
|
+
height: auto;
|
|
10
|
+
max-height: 330px;
|
|
11
|
+
width: 18rem;
|
|
12
|
+
overflow-y: auto;
|
|
13
|
+
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
14
|
+
border-radius: 0.375rem;
|
|
15
|
+
background-color: ${({ theme }) => theme.palette.background.default};
|
|
16
|
+
padding: 0.5rem;
|
|
17
|
+
transition: all 0.2s ease-in-out;
|
|
18
|
+
`;
|
|
19
|
+
const SlashCommandItem = styled.button `
|
|
20
|
+
display: flex;
|
|
21
|
+
width: 100%;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: flex-start;
|
|
24
|
+
border-radius: 0.375rem;
|
|
25
|
+
padding: 0.25rem 0.5rem;
|
|
26
|
+
text-align: left;
|
|
27
|
+
font-size: 0.875rem;
|
|
28
|
+
color: ${({ theme }) => theme.palette.text.primary};
|
|
29
|
+
background-color: ${({ theme }) => theme.palette.background.default};
|
|
30
|
+
outline: none;
|
|
31
|
+
border: none;
|
|
32
|
+
|
|
33
|
+
&:hover {
|
|
34
|
+
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&.selected {
|
|
39
|
+
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
const CommandIcon = styled.div `
|
|
43
|
+
display: flex;
|
|
44
|
+
width: 2.5rem;
|
|
45
|
+
height: 2.5rem;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
border-radius: 0.375rem;
|
|
49
|
+
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
50
|
+
margin-right: 0.5rem;
|
|
51
|
+
`;
|
|
52
|
+
const CommandTitle = styled.div `
|
|
53
|
+
font-weight: 500;
|
|
54
|
+
font-size: 0.8rem;
|
|
55
|
+
margin-bottom: 0.125rem;
|
|
56
|
+
text-overflow: ellipsis;
|
|
57
|
+
overflow: hidden;
|
|
58
|
+
white-space: nowrap;
|
|
59
|
+
`;
|
|
60
|
+
const CommandDescription = styled.div `
|
|
61
|
+
font-size: 0.75rem;
|
|
62
|
+
color: ${({ theme }) => theme.palette.text.secondary};
|
|
63
|
+
text-overflow: ellipsis;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
white-space: nowrap;
|
|
66
|
+
`;
|
|
4
67
|
const updateScrollView = (container, item) => {
|
|
5
68
|
const containerHeight = container.offsetHeight;
|
|
6
69
|
const itemHeight = item ? item.offsetHeight : 0;
|
|
@@ -13,7 +76,7 @@ const updateScrollView = (container, item) => {
|
|
|
13
76
|
container.scrollTop += bottom - containerHeight - container.scrollTop + 5;
|
|
14
77
|
}
|
|
15
78
|
};
|
|
16
|
-
const SlashCommandList =
|
|
79
|
+
const SlashCommandList = ({ items, command, editor, range, }) => {
|
|
17
80
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
18
81
|
const selectItem = useCallback((index) => {
|
|
19
82
|
const item = items[index];
|
|
@@ -63,76 +126,8 @@ const SlashCommandList = styled(({ className, items, command, editor, range }) =
|
|
|
63
126
|
if (item && container)
|
|
64
127
|
updateScrollView(container, item);
|
|
65
128
|
}, [selectedIndex]);
|
|
66
|
-
return items.length > 0 ? (_jsx(
|
|
67
|
-
return (_jsxs(
|
|
129
|
+
return items.length > 0 ? (_jsx(SlashCommandListContainer, { ref: commandListContainer, className: "slash-command", children: items.map((item, index) => {
|
|
130
|
+
return (_jsxs(SlashCommandItem, { className: `slash-command-item ${index === selectedIndex ? "selected" : ""}`, onClick: () => selectItem(index), children: [_jsx(CommandIcon, { className: "item-icon", children: _jsx(item.icon, { size: 18 }) }), _jsxs("div", { children: [_jsx(CommandTitle, { className: "item-title", children: item.title }), _jsx(CommandDescription, { className: "item-description", children: item.description })] })] }, index));
|
|
68
131
|
}) })) : null;
|
|
69
|
-
}
|
|
70
|
-
&.slash-command {
|
|
71
|
-
display: flex;
|
|
72
|
-
flex-direction: column;
|
|
73
|
-
gap: 0.25rem;
|
|
74
|
-
z-index: 16001;
|
|
75
|
-
height: auto;
|
|
76
|
-
max-height: 330px;
|
|
77
|
-
width: 18rem;
|
|
78
|
-
overflow-y: auto;
|
|
79
|
-
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
80
|
-
border-radius: 0.375rem;
|
|
81
|
-
background-color: ${({ theme }) => theme.palette.background.default};
|
|
82
|
-
padding: 0.5rem;
|
|
83
|
-
transition: all 0.2s ease-in-out;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.slash-command-item {
|
|
87
|
-
display: flex;
|
|
88
|
-
width: 100%;
|
|
89
|
-
align-items: center;
|
|
90
|
-
justify-content: flex-start;
|
|
91
|
-
border-radius: 0.375rem;
|
|
92
|
-
padding: 0.25rem 0.5rem;
|
|
93
|
-
text-align: left;
|
|
94
|
-
font-size: 0.875rem;
|
|
95
|
-
color: ${({ theme }) => theme.palette.text.primary};
|
|
96
|
-
background-color: ${({ theme }) => theme.palette.background.default};
|
|
97
|
-
outline: none;
|
|
98
|
-
border: none;
|
|
99
|
-
|
|
100
|
-
&:hover {
|
|
101
|
-
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
102
|
-
cursor: pointer;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.slash-command-item.selected {
|
|
107
|
-
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.item-icon {
|
|
111
|
-
display: flex;
|
|
112
|
-
width: 2.5rem;
|
|
113
|
-
height: 2.5rem;
|
|
114
|
-
align-items: center;
|
|
115
|
-
justify-content: center;
|
|
116
|
-
border-radius: 0.375rem;
|
|
117
|
-
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
118
|
-
margin-right: 0.5rem;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.item-title {
|
|
122
|
-
font-weight: 600;
|
|
123
|
-
font-size: 0.8rem;
|
|
124
|
-
margin-bottom: 0.125rem;
|
|
125
|
-
text-overflow: ellipsis;
|
|
126
|
-
overflow: hidden;
|
|
127
|
-
white-space: nowrap;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.item-description {
|
|
131
|
-
font-size: 0.75rem;
|
|
132
|
-
color: ${({ theme }) => theme.palette.text.secondary};
|
|
133
|
-
text-overflow: ellipsis;
|
|
134
|
-
overflow: hidden;
|
|
135
|
-
white-space: nowrap;
|
|
136
|
-
}
|
|
137
|
-
`;
|
|
132
|
+
};
|
|
138
133
|
export default SlashCommandList;
|
|
@@ -18,55 +18,6 @@ import SlashCommandList from "./SlashCommandList";
|
|
|
18
18
|
import SlashCommands from "../Enums/SlashCommands";
|
|
19
19
|
import moment from "moment/moment.js";
|
|
20
20
|
const SlashCommandPluginKey = new PluginKey("slash-command");
|
|
21
|
-
const Command = Extension.create({
|
|
22
|
-
name: "slash-command",
|
|
23
|
-
priority: 1000,
|
|
24
|
-
addKeyboardShortcuts() {
|
|
25
|
-
return {
|
|
26
|
-
Enter: ({ editor }) => {
|
|
27
|
-
// Prevent Enter key when slash command is active
|
|
28
|
-
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
29
|
-
if (slashCommandState && slashCommandState.active) {
|
|
30
|
-
return true; // Returning true prevents default behavior.
|
|
31
|
-
}
|
|
32
|
-
return false; // Returning false allows default behavior.
|
|
33
|
-
},
|
|
34
|
-
ArrowUp: ({ editor }) => {
|
|
35
|
-
// Prevent ArrowUp key when slash command is active
|
|
36
|
-
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
37
|
-
if (slashCommandState && slashCommandState.active) {
|
|
38
|
-
return true; // Returning true prevents default behavior.
|
|
39
|
-
}
|
|
40
|
-
return false; // Returning false allows default behavior.
|
|
41
|
-
},
|
|
42
|
-
ArrowDown: ({ editor }) => {
|
|
43
|
-
// Prevent ArrowDown key when slash command is active
|
|
44
|
-
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
45
|
-
if (slashCommandState && slashCommandState.active) {
|
|
46
|
-
return true; // Returning true prevents default behavior.
|
|
47
|
-
}
|
|
48
|
-
return false; // Returning false allows default behavior.
|
|
49
|
-
},
|
|
50
|
-
// Add more keys here as needed
|
|
51
|
-
};
|
|
52
|
-
},
|
|
53
|
-
addOptions() {
|
|
54
|
-
return {
|
|
55
|
-
suggestion: {
|
|
56
|
-
char: "/",
|
|
57
|
-
pluginKey: SlashCommandPluginKey,
|
|
58
|
-
command: ({ editor, range, props }) => {
|
|
59
|
-
props.command({ editor, range });
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
addProseMirrorPlugins() {
|
|
65
|
-
return [
|
|
66
|
-
Suggestion(Object.assign({ editor: this.editor }, this.options.suggestion)),
|
|
67
|
-
];
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
21
|
const getCommandItems = (values, options) => {
|
|
71
22
|
var _a;
|
|
72
23
|
if ((_a = options === null || options === void 0 ? void 0 : options.commands) === null || _a === void 0 ? void 0 : _a.includes(SlashCommands.Image)) {
|
|
@@ -285,8 +236,57 @@ const renderItems = () => {
|
|
|
285
236
|
},
|
|
286
237
|
};
|
|
287
238
|
};
|
|
239
|
+
const SlashCommand = Extension.create({
|
|
240
|
+
name: "slash-command",
|
|
241
|
+
priority: 1000,
|
|
242
|
+
addKeyboardShortcuts() {
|
|
243
|
+
return {
|
|
244
|
+
Enter: ({ editor }) => {
|
|
245
|
+
// Prevent Enter key when slash command is active
|
|
246
|
+
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
247
|
+
if (slashCommandState && slashCommandState.active) {
|
|
248
|
+
return true; // Returning true prevents default behavior.
|
|
249
|
+
}
|
|
250
|
+
return false; // Returning false allows default behavior.
|
|
251
|
+
},
|
|
252
|
+
ArrowUp: ({ editor }) => {
|
|
253
|
+
// Prevent ArrowUp key when slash command is active
|
|
254
|
+
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
255
|
+
if (slashCommandState && slashCommandState.active) {
|
|
256
|
+
return true; // Returning true prevents default behavior.
|
|
257
|
+
}
|
|
258
|
+
return false; // Returning false allows default behavior.
|
|
259
|
+
},
|
|
260
|
+
ArrowDown: ({ editor }) => {
|
|
261
|
+
// Prevent ArrowDown key when slash command is active
|
|
262
|
+
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
263
|
+
if (slashCommandState && slashCommandState.active) {
|
|
264
|
+
return true; // Returning true prevents default behavior.
|
|
265
|
+
}
|
|
266
|
+
return false; // Returning false allows default behavior.
|
|
267
|
+
},
|
|
268
|
+
// Add more keys here as needed
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
addOptions() {
|
|
272
|
+
return {
|
|
273
|
+
suggestion: {
|
|
274
|
+
char: "/",
|
|
275
|
+
pluginKey: SlashCommandPluginKey,
|
|
276
|
+
command: ({ editor, range, props }) => {
|
|
277
|
+
props.command({ editor, range });
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
},
|
|
282
|
+
addProseMirrorPlugins() {
|
|
283
|
+
return [
|
|
284
|
+
Suggestion(Object.assign({ editor: this.editor }, this.options.suggestion)),
|
|
285
|
+
];
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
288
|
const getSlashCommand = (options) => {
|
|
289
|
-
return
|
|
289
|
+
return SlashCommand.configure({
|
|
290
290
|
suggestion: {
|
|
291
291
|
items: (e) => getCommandItems(e, options),
|
|
292
292
|
render: renderItems,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Extension } from "@tiptap/core";
|
|
2
2
|
import { HandleImageUpload } from "../Plugins/UploadImagesPlugin";
|
|
3
3
|
import Extensions from "../Enums/Extensions";
|
|
4
|
+
import { BubbleMenuOptions } from "./BubbleMenuExtension";
|
|
4
5
|
export type ExtensionType = (typeof Extensions)[keyof typeof Extensions];
|
|
5
6
|
interface GetTipTapExtensionsProps {
|
|
6
7
|
extensions?: ExtensionType[];
|
|
7
8
|
slashCommands?: any[];
|
|
9
|
+
bubbleMenuOptions?: BubbleMenuOptions;
|
|
8
10
|
handleImageUpload?: HandleImageUpload;
|
|
9
11
|
}
|
|
10
12
|
declare const getTipTapExtensions: (props: GetTipTapExtensionsProps) => Extension[];
|
|
@@ -13,6 +13,7 @@ import Focus from "@tiptap/extension-focus";
|
|
|
13
13
|
import UploadImagesPlugin from "../Plugins/UploadImagesPlugin";
|
|
14
14
|
import getSlashCommand from "./getSlashCommand";
|
|
15
15
|
import Extensions from "../Enums/Extensions";
|
|
16
|
+
import BubbleMenu from "./BubbleMenuExtension";
|
|
16
17
|
const CustomImage = TiptapImage.extend({
|
|
17
18
|
// Add data-uuid attribute to image
|
|
18
19
|
addAttributes() {
|
|
@@ -42,7 +43,7 @@ const CustomStorage = Extension.create({
|
|
|
42
43
|
};
|
|
43
44
|
},
|
|
44
45
|
});
|
|
45
|
-
const getTipTapExtensions = ({ extensions = [], slashCommands = [], handleImageUpload, }) => {
|
|
46
|
+
const getTipTapExtensions = ({ extensions = [], slashCommands = [], bubbleMenuOptions, handleImageUpload, }) => {
|
|
46
47
|
return [
|
|
47
48
|
{
|
|
48
49
|
name: "starterKit",
|
|
@@ -138,20 +139,16 @@ const getTipTapExtensions = ({ extensions = [], slashCommands = [], handleImageU
|
|
|
138
139
|
name: Extensions.Placeholder,
|
|
139
140
|
extension: Placeholder.configure({
|
|
140
141
|
placeholder: ({ node }) => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
// other it shows two placeholders wihtin the cell
|
|
145
|
-
if (node.type.name === "tableCell") {
|
|
146
|
-
return "";
|
|
147
|
-
}
|
|
148
|
-
if (!extensions.includes(Extensions.SlashCommand)) {
|
|
149
|
-
return "Enter text...";
|
|
150
|
-
}
|
|
142
|
+
const text = !extensions.includes(Extensions.SlashCommand)
|
|
143
|
+
? "Enter text..."
|
|
144
|
+
: "Press '/' for commands...";
|
|
151
145
|
if (node.type.name === "heading") {
|
|
152
146
|
return `Heading ${node.attrs.level}`;
|
|
153
147
|
}
|
|
154
|
-
|
|
148
|
+
if (node.type.name === "paragraph") {
|
|
149
|
+
return text;
|
|
150
|
+
}
|
|
151
|
+
return "";
|
|
155
152
|
},
|
|
156
153
|
includeChildren: true,
|
|
157
154
|
}),
|
|
@@ -161,6 +158,11 @@ const getTipTapExtensions = ({ extensions = [], slashCommands = [], handleImageU
|
|
|
161
158
|
category: "default",
|
|
162
159
|
extension: CustomStorage,
|
|
163
160
|
},
|
|
161
|
+
{
|
|
162
|
+
name: Extensions.BubbleMenu,
|
|
163
|
+
category: "default",
|
|
164
|
+
extension: BubbleMenu.configure(bubbleMenuOptions),
|
|
165
|
+
},
|
|
164
166
|
{
|
|
165
167
|
name: Extensions.SlashCommand,
|
|
166
168
|
extension: getSlashCommand({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Editor } from "@tiptap/react";
|
|
2
2
|
import { ExtensionType } from "./Extensions/getTiptapExtensions";
|
|
3
3
|
import { HandleImageUpload } from "./Plugins/UploadImagesPlugin";
|
|
4
|
+
import { BubbleMenuOptions } from "./Extensions/BubbleMenuExtension";
|
|
4
5
|
interface RichTextEditorProps {
|
|
5
6
|
className?: string;
|
|
6
7
|
editorInstanceRef?: React.RefObject<Editor>;
|
|
@@ -14,6 +15,7 @@ interface RichTextEditorProps {
|
|
|
14
15
|
saving?: boolean;
|
|
15
16
|
onChange?: (value: string) => void;
|
|
16
17
|
handleImageUpload?: HandleImageUpload;
|
|
18
|
+
bubbleMenuOptions?: BubbleMenuOptions;
|
|
17
19
|
style?: React.CSSProperties;
|
|
18
20
|
}
|
|
19
21
|
declare const RichTextEditor: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<Omit<RichTextEditorProps & import("react").RefAttributes<unknown>, "ref"> & {
|
|
@@ -5,7 +5,8 @@ import { EditorContent, useEditor } from "@tiptap/react";
|
|
|
5
5
|
import Toolbar from "./Toolbar";
|
|
6
6
|
import getTipTapExtensions from "./Extensions/getTiptapExtensions";
|
|
7
7
|
import Extensions from "./Enums/Extensions";
|
|
8
|
-
|
|
8
|
+
import SaveBadge from "./Components/SaveBadge";
|
|
9
|
+
const RichTextEditor = styled(forwardRef(({ className, editorInstanceRef, defaultValue = "", readOnly = false, font, showToolbar = true, saving = false, extensions = [], slashCommands = [], bubbleMenuOptions, onChange, handleImageUpload, style, }, ref) => {
|
|
9
10
|
// check if image extension is included
|
|
10
11
|
if (extensions === null || extensions === void 0 ? void 0 : extensions.includes(Extensions.Image)) {
|
|
11
12
|
// Ensure that handleImageUpload is provided
|
|
@@ -19,6 +20,7 @@ const RichTextEditor = styled(forwardRef(({ className, editorInstanceRef, defaul
|
|
|
19
20
|
extensions: getTipTapExtensions({
|
|
20
21
|
extensions,
|
|
21
22
|
slashCommands,
|
|
23
|
+
bubbleMenuOptions,
|
|
22
24
|
handleImageUpload,
|
|
23
25
|
}),
|
|
24
26
|
onUpdate: ({ editor }) => {
|
|
@@ -31,7 +33,7 @@ const RichTextEditor = styled(forwardRef(({ className, editorInstanceRef, defaul
|
|
|
31
33
|
_ref.current = editor;
|
|
32
34
|
}
|
|
33
35
|
}, [editor]);
|
|
34
|
-
return (_jsxs("div", { className: className, children: [showToolbar && _jsx(Toolbar, { editor: editor }), _jsx(EditorContent, { className: "editor-content", editor: editor, "data-font": font || null, style: style })] }));
|
|
36
|
+
return (_jsxs("div", { className: className, children: [showToolbar && _jsx(Toolbar, { editor: editor }), saving && _jsx(SaveBadge, {}), _jsx(EditorContent, { className: "editor-content", editor: editor, "data-font": font || null, style: style })] }));
|
|
35
37
|
})) `
|
|
36
38
|
position: relative;
|
|
37
39
|
display: flex;
|
|
@@ -41,6 +43,10 @@ const RichTextEditor = styled(forwardRef(({ className, editorInstanceRef, defaul
|
|
|
41
43
|
justify-content: flex-start;
|
|
42
44
|
align-items: center;
|
|
43
45
|
|
|
46
|
+
::selection {
|
|
47
|
+
background-color: #705324;
|
|
48
|
+
}
|
|
49
|
+
|
|
44
50
|
.editor-content {
|
|
45
51
|
height: ${({ height }) => height || "100%"};
|
|
46
52
|
width: 100%;
|
|
@@ -166,7 +166,7 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
166
166
|
.concat(customItems) // Add custom items to the list
|
|
167
167
|
.filter((item) => {
|
|
168
168
|
const itemValue = (isObjectArray ? item.label : item);
|
|
169
|
-
return itemValue.toLowerCase().includes(searchValue.toLowerCase());
|
|
169
|
+
return itemValue === null || itemValue === void 0 ? void 0 : itemValue.toLowerCase().includes(searchValue.toLowerCase());
|
|
170
170
|
})
|
|
171
171
|
.sort((a, b) => {
|
|
172
172
|
if (grouped) {
|
|
@@ -219,9 +219,9 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
219
219
|
};
|
|
220
220
|
const handleClear = (e) => {
|
|
221
221
|
e.preventDefault();
|
|
222
|
-
e.stopPropagation();
|
|
223
222
|
if (inputRef.current)
|
|
224
223
|
inputRef.current.value = "";
|
|
224
|
+
setIsOpen(false);
|
|
225
225
|
handleChangeSelection(null);
|
|
226
226
|
setSelected(null);
|
|
227
227
|
setSearchValue("");
|
|
@@ -434,7 +434,10 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
434
434
|
setDropDownHeight(bottomHeight);
|
|
435
435
|
};
|
|
436
436
|
}, [topHeight, bottomHeight, isOpen]);
|
|
437
|
-
return (_jsxs("div", { className: className, children: [label && (_jsx(FieldLabel, { error: error, asterisk: required, size: size, description: description, children: label })), _jsxs(StyledInputContainer, { ref: refs.setReference, onMouseDown: () => setIsOpen(true), width: width, onKeyDown: handleKeyDown, "data-open": isOpen, children: [_jsx(Input, { ref: inputRef, onChange: debouncedHandleOnChange, onFocus: handleFocus, autoFocus: focused, placeholder: placeholder, size: size, readOnly: !searchable, "data-button-right": arrow || clearable }), clearable && (selected || !!((_h = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _h === void 0 ? void 0 : _h.value)) ? (_jsx(ClearButton, { className: "input-btn", onClick: handleClear
|
|
437
|
+
return (_jsxs("div", { className: className, children: [label && (_jsx(FieldLabel, { error: error, asterisk: required, size: size, description: description, children: label })), _jsxs(StyledInputContainer, { ref: refs.setReference, onMouseDown: () => setIsOpen(true), width: width, onKeyDown: handleKeyDown, "data-open": isOpen, children: [_jsx(Input, { ref: inputRef, onChange: debouncedHandleOnChange, onFocus: handleFocus, autoFocus: focused, placeholder: placeholder, size: size, readOnly: !searchable, "data-button-right": arrow || clearable }), clearable && (selected || !!((_h = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _h === void 0 ? void 0 : _h.value)) ? (_jsx(ClearButton, { className: "input-btn", onClick: handleClear, onMouseDown: (e) => {
|
|
438
|
+
e.preventDefault();
|
|
439
|
+
e.stopPropagation();
|
|
440
|
+
} })) : arrow ? (_jsx(ArrowButton, { onClick: (e) => {
|
|
438
441
|
e.preventDefault();
|
|
439
442
|
// e.stopPropagation();
|
|
440
443
|
}, onMouseDown: (e) => {
|
package/dist/TagBox/TagBox.js
CHANGED
|
@@ -359,7 +359,6 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
359
359
|
};
|
|
360
360
|
const handleClear = (e) => {
|
|
361
361
|
e.preventDefault();
|
|
362
|
-
e.stopPropagation();
|
|
363
362
|
if (inputRef === null || inputRef === void 0 ? void 0 : inputRef.current)
|
|
364
363
|
inputRef.current.value = "";
|
|
365
364
|
onChange === null || onChange === void 0 ? void 0 : onChange([]);
|
|
@@ -551,7 +550,10 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
551
550
|
}
|
|
552
551
|
update();
|
|
553
552
|
}, placeholder: placeholder, size: size, readOnly: !(searchable || allowCustomValue) }))] }) }), clearable &&
|
|
554
|
-
(selectedItems.length > 0 || !!((_f = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _f === void 0 ? void 0 : _f.value)) ? (_jsx(ClearButton, { onClick: handleClear
|
|
553
|
+
(selectedItems.length > 0 || !!((_f = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _f === void 0 ? void 0 : _f.value)) ? (_jsx(ClearButton, { onClick: handleClear, onMouseDown: (e) => {
|
|
554
|
+
e.preventDefault();
|
|
555
|
+
e.stopPropagation();
|
|
556
|
+
} })) : arrow ? (_jsx(ArrowButton, { onClick: (e) => {
|
|
555
557
|
e.preventDefault();
|
|
556
558
|
}, onMouseDown: (e) => {
|
|
557
559
|
e.preventDefault();
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,10 @@ export { default as Grid } from "./Grid";
|
|
|
3
3
|
export { default as TextInput } from "./TextInput";
|
|
4
4
|
export { default as SelectBox } from "./SelectBox";
|
|
5
5
|
export { default as Button } from "./Button";
|
|
6
|
+
export type { ButtonProps } from "./Button";
|
|
6
7
|
export { default as IconButton } from "./IconButton";
|
|
7
8
|
export { default as DropDownMenu } from "./DropDownMenu";
|
|
9
|
+
export type { DropDownItem } from "./DropDownMenu";
|
|
8
10
|
export { default as DateInput } from "./DateInput";
|
|
9
11
|
export { default as TextArea } from "./TextArea";
|
|
10
12
|
export { default as TextAreaInput } from "./TextAreaInput";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monolith-forensics/monolith-ui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.49",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Matt Danner (Monolith Forensics LLC)",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"moment": "^2.29.1",
|
|
45
45
|
"overlayscrollbars": "^2.6.0",
|
|
46
46
|
"overlayscrollbars-react": "^0.5.6",
|
|
47
|
+
"react-dom": "^18.3.1",
|
|
47
48
|
"react-dropzone": "^14.2.3",
|
|
48
49
|
"react-icons": "^5.2.1",
|
|
49
50
|
"react-textarea-autosize": "^8.5.3",
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
63
|
"@types/overlayscrollbars": "^1.12.5",
|
|
64
|
+
"@types/react-dom": "^18.3.0",
|
|
63
65
|
"@types/react-window": "^1.8.8",
|
|
64
66
|
"@types/spark-md5": "^3.0.4",
|
|
65
67
|
"typescript": "^5.5.4"
|