@monolith-forensics/monolith-ui 1.9.3-dev.4 → 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 +1 -0
- package/dist/RichTextEditor/Enums/Controls.js +1 -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 +1 -0
- package/dist/RichTextEditor/Enums/SlashCommands.js +1 -0
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +7 -0
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +157 -0
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +10 -1
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +15 -0
- package/dist/RichTextEditor/RichTextEditor.js +51 -27
- package/dist/RichTextEditor/Toolbar/Controls.d.ts +13 -0
- package/dist/RichTextEditor/Toolbar/Controls.js +142 -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
package/dist/Button/Button.js
CHANGED
|
@@ -46,14 +46,16 @@ const StyledButton = styled.button `
|
|
|
46
46
|
return `0px ${getControlSizeTokens(size).buttonPaddingX}px`;
|
|
47
47
|
}};
|
|
48
48
|
|
|
49
|
-
color: ${({ theme, variant, color }) => {
|
|
49
|
+
color: ${({ theme, variant, color, selected }) => {
|
|
50
50
|
var _a, _b;
|
|
51
|
-
if (variant === "default")
|
|
52
|
-
return theme.palette.text.primary;
|
|
53
51
|
if (variant === "contained")
|
|
54
52
|
return "white";
|
|
55
53
|
if (variant === "filled")
|
|
56
54
|
return "white";
|
|
55
|
+
if (selected)
|
|
56
|
+
return theme.palette.primary.main;
|
|
57
|
+
if (variant === "default")
|
|
58
|
+
return theme.palette.text.primary;
|
|
57
59
|
if (color) {
|
|
58
60
|
return (((_b = (_a = theme === null || theme === void 0 ? void 0 : theme.button) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b[color]) ||
|
|
59
61
|
colors[color] ||
|
|
@@ -69,6 +71,9 @@ const StyledButton = styled.button `
|
|
|
69
71
|
resolvedColor =
|
|
70
72
|
((_b = (_a = theme === null || theme === void 0 ? void 0 : theme.button) === null || _a === void 0 ? void 0 : _a.background) === null || _b === void 0 ? void 0 : _b[color]) || colors[color];
|
|
71
73
|
}
|
|
74
|
+
if (selected && variant !== "contained" && variant !== "filled") {
|
|
75
|
+
return theme.palette.primary.main + "20";
|
|
76
|
+
}
|
|
72
77
|
switch (variant) {
|
|
73
78
|
case "default":
|
|
74
79
|
return theme.button.background.default;
|
|
@@ -121,7 +126,9 @@ const StyledButton = styled.button `
|
|
|
121
126
|
|
|
122
127
|
cursor: pointer;
|
|
123
128
|
|
|
124
|
-
transition:
|
|
129
|
+
transition:
|
|
130
|
+
background-color 0.2s,
|
|
131
|
+
border 0.2s;
|
|
125
132
|
|
|
126
133
|
.inner-span {
|
|
127
134
|
display: flex;
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { Menu, MenuItemList, StyledInnerItemContainer } from "./components";
|
|
4
|
+
import { DEFAULT_DROPDOWN_MAX_HEIGHT } from "./constants";
|
|
5
|
+
const getNumericCssLength = (value) => {
|
|
6
|
+
if (typeof value === "number")
|
|
7
|
+
return value;
|
|
8
|
+
if (typeof value !== "string")
|
|
9
|
+
return undefined;
|
|
10
|
+
const pixelMatch = value.trim().match(/^(\d+(?:\.\d+)?)px$/);
|
|
11
|
+
return pixelMatch ? Number(pixelMatch[1]) : undefined;
|
|
12
|
+
};
|
|
4
13
|
export const DropDownMenu = ({ data, children, defaultValue, value, variant, arrow, size, searchable, grouped, onAddNew, loading, onScroll, onScrollToTop, onScrollToBottom, onSearch, manualSearch, multiselect, enableSelectAll, enableSelectedOptionStyling, renderOption, dynamicOptionHeight, onItemSelect, onChange, buttonProps, TooltipContent, dropDownProps, query, disabled, }) => {
|
|
5
|
-
var _a;
|
|
14
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6
15
|
const isObjectArray = (_a = Object.keys((data === null || data === void 0 ? void 0 : data[0]) || {})) === null || _a === void 0 ? void 0 : _a.includes("label");
|
|
16
|
+
const maxDropdownHeight = (_f = (_e = (_c = getNumericCssLength((_b = dropDownProps === null || dropDownProps === void 0 ? void 0 : dropDownProps.style) === null || _b === void 0 ? void 0 : _b.height)) !== null && _c !== void 0 ? _c : getNumericCssLength((_d = dropDownProps === null || dropDownProps === void 0 ? void 0 : dropDownProps.style) === null || _d === void 0 ? void 0 : _d.maxHeight)) !== null && _e !== void 0 ? _e : getNumericCssLength(dropDownProps === null || dropDownProps === void 0 ? void 0 : dropDownProps.maxDropdownHeight)) !== null && _f !== void 0 ? _f : DEFAULT_DROPDOWN_MAX_HEIGHT;
|
|
7
17
|
const [internalSelected, setInternalSelected] = useState(defaultValue || []);
|
|
8
18
|
const isControlled = value !== undefined;
|
|
9
19
|
const selected = isControlled ? value || [] : internalSelected;
|
|
@@ -35,5 +45,5 @@ export const DropDownMenu = ({ data, children, defaultValue, value, variant, arr
|
|
|
35
45
|
const handleScrollToBottom = (e) => {
|
|
36
46
|
onScrollToBottom === null || onScrollToBottom === void 0 ? void 0 : onScrollToBottom(e);
|
|
37
47
|
};
|
|
38
|
-
return (_jsx(Menu, { label: children, disabled: disabled, arrow: arrow, buttonSize: size, variant: variant, multiselect: multiselect, buttonProps: buttonProps, onMenuClose: handleMenuClose, dropDownProps: dropDownProps, children: _jsxs(StyledInnerItemContainer, { children: [loading && _jsx("div", { children: "Loading..." }), !loading && (_jsx(MenuItemList, { menuItems: data, searchable: searchable, grouped: grouped, onAddNew: onAddNew, onSearch: onSearch, manualSearch: manualSearch, dynamicOptionHeight: dynamicOptionHeight, selected: selected, TooltipContent: TooltipContent, multiselect: multiselect, enableSelectAll: enableSelectAll, enableSelectedOptionStyling: enableSelectedOptionStyling, size: size, handleAddItem: handleAddItem, handleRemoveItem: handleRemoveItem, handleSetSelected: handleSetSelected, onItemSelect: onItemSelect, renderOption: renderOption, onScroll: onScroll, onScrollToTop: onScrollToTop, onScrollToBottom: handleScrollToBottom, query: query }))] }) }));
|
|
48
|
+
return (_jsx(Menu, { label: children, disabled: disabled, arrow: arrow, buttonSize: size, variant: variant, multiselect: multiselect, buttonProps: buttonProps, onMenuClose: handleMenuClose, dropDownProps: dropDownProps, children: _jsxs(StyledInnerItemContainer, { children: [loading && _jsx("div", { children: "Loading..." }), !loading && (_jsx(MenuItemList, { menuItems: data, searchable: searchable, grouped: grouped, onAddNew: onAddNew, onSearch: onSearch, manualSearch: manualSearch, dynamicOptionHeight: dynamicOptionHeight, maxDropdownHeight: maxDropdownHeight, selected: selected, TooltipContent: TooltipContent, multiselect: multiselect, enableSelectAll: enableSelectAll, enableSelectedOptionStyling: enableSelectedOptionStyling, size: size, handleAddItem: handleAddItem, handleRemoveItem: handleRemoveItem, handleSetSelected: handleSetSelected, onItemSelect: onItemSelect, renderOption: renderOption, onScroll: onScroll, onScrollToTop: onScrollToTop, onScrollToBottom: handleScrollToBottom, query: query }))] }) }));
|
|
39
49
|
};
|
|
@@ -18,8 +18,14 @@ import { MenuContext } from "./MenuContext";
|
|
|
18
18
|
import { StyledFloatContainer } from "./StyledFloatContainer";
|
|
19
19
|
import { StyledContent } from "./StyledContent";
|
|
20
20
|
import { MenuItem } from "./MenuItem";
|
|
21
|
+
import { DEFAULT_DROPDOWN_MAX_HEIGHT } from "../constants";
|
|
21
22
|
export const MenuComponent = forwardRef((_a, forwardedRef) => {
|
|
22
23
|
var { children, label, arrow, size, buttonSize, variant, buttonProps, buttonRender, multiselect, onMenuClose, dropDownProps, disabled } = _a, props = __rest(_a, ["children", "label", "arrow", "size", "buttonSize", "variant", "buttonProps", "buttonRender", "multiselect", "onMenuClose", "dropDownProps", "disabled"]);
|
|
24
|
+
const _b = dropDownProps || {}, { style: dropDownStyle } = _b, contentProps = __rest(_b, ["style"]);
|
|
25
|
+
const contentStyle = Object.assign({ height: "fit-content", maxHeight: (dropDownStyle === null || dropDownStyle === void 0 ? void 0 : dropDownStyle.maxHeight) ||
|
|
26
|
+
(dropDownStyle === null || dropDownStyle === void 0 ? void 0 : dropDownStyle.height) ||
|
|
27
|
+
(dropDownProps === null || dropDownProps === void 0 ? void 0 : dropDownProps.maxDropdownHeight) ||
|
|
28
|
+
DEFAULT_DROPDOWN_MAX_HEIGHT }, dropDownStyle);
|
|
23
29
|
const [isOpen, setIsOpen] = useState(false);
|
|
24
30
|
const [hasFocusInside, setHasFocusInside] = useState(false);
|
|
25
31
|
const [activeIndex, setActiveIndex] = useState(null);
|
|
@@ -119,5 +125,5 @@ export const MenuComponent = forwardRef((_a, forwardedRef) => {
|
|
|
119
125
|
getItemProps,
|
|
120
126
|
setHasFocusInside,
|
|
121
127
|
isOpen,
|
|
122
|
-
}, children: _jsx(FloatingList, { elementsRef: elementsRef, labelsRef: labelsRef, children: isOpen && (_jsx(FloatingPortal, { children: _jsx(FloatingFocusManager, { context: context, modal: false, initialFocus: isNested ? -1 : 0, returnFocus: !isNested, children: _jsx(StyledFloatContainer, Object.assign({ ref: refs.setFloating, className: "Menu", style: floatingStyles }, getFloatingProps(), { children: _jsx(StyledContent, Object.assign({ className: "mfFloatingContent" },
|
|
128
|
+
}, children: _jsx(FloatingList, { elementsRef: elementsRef, labelsRef: labelsRef, children: isOpen && (_jsx(FloatingPortal, { children: _jsx(FloatingFocusManager, { context: context, modal: false, initialFocus: isNested ? -1 : 0, returnFocus: !isNested, children: _jsx(StyledFloatContainer, Object.assign({ ref: refs.setFloating, className: "Menu", style: floatingStyles }, getFloatingProps(), { children: _jsx(StyledContent, Object.assign({ className: "mfFloatingContent", style: contentStyle }, contentProps, { children: children })) })) }) })) }) })] }));
|
|
123
129
|
});
|
|
@@ -26,7 +26,7 @@ export const MenuItem = styled(forwardRef((_a, forwardedRef) => {
|
|
|
26
26
|
return (_jsx(Tooltip, { content: TooltipContent ? _jsx(TooltipContent, { data: itemData }) : null, side: "left", children: _jsx(Button, Object.assign({}, props, { ref: useMergeRefs([
|
|
27
27
|
item.ref,
|
|
28
28
|
forwardedRef,
|
|
29
|
-
]), type: "button", role: "menuitem", tabIndex: isActive ? 0 : -1, disabled: disabled, justify: "start", color: props.color }, menu.getItemProps({
|
|
29
|
+
]), type: "button", role: "menuitem", tabIndex: isActive ? 0 : -1, disabled: disabled, justify: "start", color: props.color, selected: false }, menu.getItemProps({
|
|
30
30
|
onClick(event) {
|
|
31
31
|
var _a;
|
|
32
32
|
(_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, event);
|
|
@@ -49,7 +49,9 @@ export const MenuItem = styled(forwardRef((_a, forwardedRef) => {
|
|
|
49
49
|
min-height: ${({ size = "sm" }) => `${getControlSizeTokens(size).menuRowHeight}px`};
|
|
50
50
|
width: 100%;
|
|
51
51
|
min-width: 100%;
|
|
52
|
-
height: ${({ size = "sm", $dynamicHeight }) => $dynamicHeight
|
|
52
|
+
height: ${({ size = "sm", $dynamicHeight }) => $dynamicHeight
|
|
53
|
+
? "auto"
|
|
54
|
+
: `${getControlSizeTokens(size).menuRowHeight}px`};
|
|
53
55
|
box-sizing: border-box;
|
|
54
56
|
position: relative;
|
|
55
57
|
user-select: none;
|
|
@@ -22,6 +22,7 @@ import { useInfiniteQuery } from "@tanstack/react-query";
|
|
|
22
22
|
import { useDebouncedCallback } from "use-debounce";
|
|
23
23
|
import { SearchInput } from "./SearchInput";
|
|
24
24
|
import Loader from "../../Loader";
|
|
25
|
+
import { DEFAULT_DROPDOWN_MAX_HEIGHT, DROPDOWN_CONTENT_VERTICAL_PADDING, SEARCH_INPUT_MARGIN_BOTTOM, } from "../constants";
|
|
25
26
|
const getItemKey = (item) => item && typeof item === "object" && "value" in item ? item.value : item;
|
|
26
27
|
const filterMenuItems = (menuItems, searchValue) => {
|
|
27
28
|
return menuItems.filter((item) => {
|
|
@@ -128,7 +129,7 @@ const MeasuredRow = ({ children, index, setItemSize, style }) => {
|
|
|
128
129
|
}, [children, index, setItemSize]);
|
|
129
130
|
return (_jsx("div", { style: Object.assign(Object.assign({}, style), { overflow: "visible" }), children: _jsx("div", { ref: rowRef, children: children }) }));
|
|
130
131
|
};
|
|
131
|
-
export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dynamicOptionHeight, selected, TooltipContent, multiselect, enableSelectAll, enableSelectedOptionStyling, grouped, onAddNew, size, handleAddItem, handleRemoveItem, handleSetSelected, onItemSelect, renderOption, onScroll, onScrollToTop, onScrollToBottom, query, }) => {
|
|
132
|
+
export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dynamicOptionHeight, selected, TooltipContent, multiselect, enableSelectAll, enableSelectedOptionStyling, grouped, onAddNew, size, handleAddItem, handleRemoveItem, handleSetSelected, onItemSelect, renderOption, onScroll, onScrollToTop, onScrollToBottom, maxDropdownHeight = DEFAULT_DROPDOWN_MAX_HEIGHT, query, }) => {
|
|
132
133
|
const [searchValue, setSearchValue] = useState("");
|
|
133
134
|
const _a = query !== null && query !== void 0 ? query : {}, { queryKey, queryFn, getNextPageParam, initialPageParam } = _a, rest = __rest(_a, ["queryKey", "queryFn", "getNextPageParam", "initialPageParam"]);
|
|
134
135
|
const targetElm = useRef(null);
|
|
@@ -253,16 +254,25 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dy
|
|
|
253
254
|
const getDynamicItemSize = (index) => {
|
|
254
255
|
var _a;
|
|
255
256
|
return itemSizeMap.current[index] ||
|
|
256
|
-
(((_a = displayItems[index]) === null || _a === void 0 ? void 0 : _a._isGroupHeader)
|
|
257
|
+
(((_a = displayItems[index]) === null || _a === void 0 ? void 0 : _a._isGroupHeader)
|
|
258
|
+
? itemHeight
|
|
259
|
+
: estimatedDynamicItemHeight);
|
|
257
260
|
};
|
|
258
261
|
const estimatedHeight = dynamicListEnabled
|
|
259
262
|
? displayItems.reduce((total, _, index) => total + getDynamicItemSize(index), 0)
|
|
260
263
|
: itemCount * itemHeight;
|
|
261
|
-
const
|
|
262
|
-
?
|
|
263
|
-
:
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
const searchHeight = searchable
|
|
265
|
+
? sizeTokens.height + SEARCH_INPUT_MARGIN_BOTTOM
|
|
266
|
+
: 0;
|
|
267
|
+
const selectAllHeight = multiselect && enableSelectAll && selectableItems.length > 0
|
|
268
|
+
? itemHeight
|
|
269
|
+
: 0;
|
|
270
|
+
const maxListHeight = Math.max(itemHeight, maxDropdownHeight -
|
|
271
|
+
DROPDOWN_CONTENT_VERTICAL_PADDING -
|
|
272
|
+
searchHeight -
|
|
273
|
+
selectAllHeight);
|
|
274
|
+
const availableHeight = viewPortDimensions.height || maxListHeight;
|
|
275
|
+
const height = Math.min(estimatedHeight, availableHeight, maxListHeight);
|
|
266
276
|
const width = "100%";
|
|
267
277
|
useLayoutEffect(() => {
|
|
268
278
|
const target = targetElm.current;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import Input from "../../Input";
|
|
4
|
-
|
|
4
|
+
import { SEARCH_INPUT_MARGIN_BOTTOM } from "../constants";
|
|
5
|
+
export const SearchInput = forwardRef((props, ref) => (_jsx(Input, Object.assign({ ref: ref, style: { marginBottom: SEARCH_INPUT_MARGIN_BOTTOM } }, props))));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
|
+
import { DEFAULT_DROPDOWN_MAX_HEIGHT, DROPDOWN_CONTENT_PADDING, } from "../constants";
|
|
2
3
|
export const StyledContent = styled.div `
|
|
3
4
|
position: relative;
|
|
4
5
|
display: flex;
|
|
@@ -11,7 +12,7 @@ export const StyledContent = styled.div `
|
|
|
11
12
|
max-width: 400px;
|
|
12
13
|
max-height: ${({ maxDropdownHeight }) => Number.isInteger(maxDropdownHeight)
|
|
13
14
|
? `${maxDropdownHeight}px`
|
|
14
|
-
: maxDropdownHeight ||
|
|
15
|
+
: maxDropdownHeight || `${DEFAULT_DROPDOWN_MAX_HEIGHT}px`};
|
|
15
16
|
|
|
16
17
|
background-color: ${(props) => props.theme.palette.background.default};
|
|
17
18
|
background-color: ${({ theme, variant }) => {
|
|
@@ -30,7 +31,7 @@ export const StyledContent = styled.div `
|
|
|
30
31
|
border-radius: 5px;
|
|
31
32
|
border: 1px solid ${(props) => props.theme.palette.divider};
|
|
32
33
|
outline: none;
|
|
33
|
-
padding:
|
|
34
|
+
padding: ${DROPDOWN_CONTENT_PADDING}px;
|
|
34
35
|
animation-duration: 400ms;
|
|
35
36
|
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
|
36
37
|
will-change: transform, opacity;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Operator } from "./types";
|
|
2
|
+
export declare const Operators: {
|
|
3
|
+
Equals: {
|
|
4
|
+
value: string;
|
|
5
|
+
label: string;
|
|
6
|
+
};
|
|
7
|
+
NotEquals: {
|
|
8
|
+
value: string;
|
|
9
|
+
label: string;
|
|
10
|
+
};
|
|
11
|
+
LessThan: {
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
};
|
|
15
|
+
GreaterThan: {
|
|
16
|
+
value: string;
|
|
17
|
+
label: string;
|
|
18
|
+
};
|
|
19
|
+
LessThanOrEqual: {
|
|
20
|
+
value: string;
|
|
21
|
+
label: string;
|
|
22
|
+
};
|
|
23
|
+
GreaterThanOrEqual: {
|
|
24
|
+
value: string;
|
|
25
|
+
label: string;
|
|
26
|
+
};
|
|
27
|
+
Contains: {
|
|
28
|
+
value: string;
|
|
29
|
+
label: string;
|
|
30
|
+
};
|
|
31
|
+
BeginsWith: {
|
|
32
|
+
value: string;
|
|
33
|
+
label: string;
|
|
34
|
+
};
|
|
35
|
+
EndsWith: {
|
|
36
|
+
value: string;
|
|
37
|
+
label: string;
|
|
38
|
+
};
|
|
39
|
+
DoesNotContain: {
|
|
40
|
+
value: string;
|
|
41
|
+
label: string;
|
|
42
|
+
};
|
|
43
|
+
DoesNotBeginWith: {
|
|
44
|
+
value: string;
|
|
45
|
+
label: string;
|
|
46
|
+
};
|
|
47
|
+
DoesNotEndWith: {
|
|
48
|
+
value: string;
|
|
49
|
+
label: string;
|
|
50
|
+
};
|
|
51
|
+
IsEmpty: {
|
|
52
|
+
value: string;
|
|
53
|
+
label: string;
|
|
54
|
+
};
|
|
55
|
+
IsNotEmpty: {
|
|
56
|
+
value: string;
|
|
57
|
+
label: string;
|
|
58
|
+
};
|
|
59
|
+
In: {
|
|
60
|
+
value: string;
|
|
61
|
+
label: string;
|
|
62
|
+
};
|
|
63
|
+
NIn: {
|
|
64
|
+
value: string;
|
|
65
|
+
label: string;
|
|
66
|
+
};
|
|
67
|
+
Between: {
|
|
68
|
+
value: string;
|
|
69
|
+
label: string;
|
|
70
|
+
};
|
|
71
|
+
NotBetween: {
|
|
72
|
+
value: string;
|
|
73
|
+
label: string;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
export declare const DefaultOperators: Operator[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const Operators = {
|
|
2
|
+
Equals: { value: "=", label: "is" },
|
|
3
|
+
NotEquals: { value: "!=", label: "is not" },
|
|
4
|
+
LessThan: { value: "<", label: "less than" },
|
|
5
|
+
GreaterThan: { value: ">", label: "greater than" },
|
|
6
|
+
LessThanOrEqual: { value: "<=", label: "less than or equal" },
|
|
7
|
+
GreaterThanOrEqual: { value: ">=", label: "greater than or equal" },
|
|
8
|
+
Contains: { value: "contains", label: "contains" },
|
|
9
|
+
BeginsWith: { value: "beginsWith", label: "begins with" },
|
|
10
|
+
EndsWith: { value: "endsWith", label: "ends with" },
|
|
11
|
+
DoesNotContain: { value: "doesNotContain", label: "does not contain" },
|
|
12
|
+
DoesNotBeginWith: { value: "doesNotBeginWith", label: "does not begin with" },
|
|
13
|
+
DoesNotEndWith: { value: "doesNotEndWith", label: "does not end with" },
|
|
14
|
+
IsEmpty: { value: "isEmpty", label: "is empty" },
|
|
15
|
+
IsNotEmpty: { value: "isNotEmpty", label: "is not empty" },
|
|
16
|
+
In: { value: "in", label: "is any of" },
|
|
17
|
+
NIn: { value: "nin", label: "is none of" },
|
|
18
|
+
Between: { value: "between", label: "between" },
|
|
19
|
+
NotBetween: { value: "notBetween", label: "not between" },
|
|
20
|
+
};
|
|
21
|
+
export const DefaultOperators = Object.values(Operators);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DropDownItem, DropDownMenuProps } from "../DropDownMenu";
|
|
2
|
+
export interface UseQueryFilterProps {
|
|
3
|
+
defaultFilter?: Query | null;
|
|
4
|
+
/**
|
|
5
|
+
* Filter definitions for the available fields. Pass `undefined` while the
|
|
6
|
+
* definitions are still loading (e.g. async fetch in flight) — any rules
|
|
7
|
+
* already in state will render nothing until definitions resolve. An empty
|
|
8
|
+
* array means "loaded, no definitions": every rule will render as an
|
|
9
|
+
* orphan chip and `onUnknownField` will fire for each.
|
|
10
|
+
*/
|
|
11
|
+
filterDefinitions: FilterDefinition[] | undefined;
|
|
12
|
+
showCombinator?: boolean;
|
|
13
|
+
onFilterChange?: (filter: any) => void;
|
|
14
|
+
onUnknownField?: (rule: Rule) => void;
|
|
15
|
+
}
|
|
16
|
+
export type QueryFilterType = {
|
|
17
|
+
filter: Query;
|
|
18
|
+
filterDefinitions: FilterDefinition[] | undefined;
|
|
19
|
+
showCombinator?: boolean;
|
|
20
|
+
addRule: (rule: Rule) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Remove a rule by `id` (preferred) or by passing the `Rule` object. The
|
|
23
|
+
* object form falls back to reference equality when `rule.id` is missing,
|
|
24
|
+
* so chips for un-normalized orphan rules can still delete themselves.
|
|
25
|
+
*/
|
|
26
|
+
removeRule: (target: string | Rule) => void;
|
|
27
|
+
updateRule: (rule: Rule) => void;
|
|
28
|
+
updateRootCombinator: (combinator: Combinator) => void;
|
|
29
|
+
onUnknownField?: (rule: Rule) => void;
|
|
30
|
+
};
|
|
31
|
+
export type UseQueryFilter = (args: UseQueryFilterProps) => QueryFilterType;
|
|
32
|
+
export type Combinator = "and" | "or";
|
|
33
|
+
export type Operator = {
|
|
34
|
+
label: string;
|
|
35
|
+
value: string;
|
|
36
|
+
};
|
|
37
|
+
export type InputType = "text" | "number" | "date" | "datetime" | "multiselect";
|
|
38
|
+
export interface FilterDefinition {
|
|
39
|
+
dataField: string;
|
|
40
|
+
label: string;
|
|
41
|
+
pluralLabel?: string;
|
|
42
|
+
operators?: Operator[];
|
|
43
|
+
inputType?: InputType;
|
|
44
|
+
resolution?: "day" | "second" | "millisecond";
|
|
45
|
+
isoString?: boolean;
|
|
46
|
+
placeholder?: string;
|
|
47
|
+
selectOptions?: DropDownItem[];
|
|
48
|
+
dropDownOptions?: {
|
|
49
|
+
style?: React.CSSProperties;
|
|
50
|
+
};
|
|
51
|
+
query?: DropDownMenuProps["query"];
|
|
52
|
+
}
|
|
53
|
+
export interface Rule {
|
|
54
|
+
id?: string;
|
|
55
|
+
dataField: string;
|
|
56
|
+
value?: string[];
|
|
57
|
+
options?: DropDownItem[];
|
|
58
|
+
operator: Operator;
|
|
59
|
+
label: string;
|
|
60
|
+
}
|
|
61
|
+
export interface RuleGroup {
|
|
62
|
+
rules: Rule[];
|
|
63
|
+
combinator: Combinator;
|
|
64
|
+
}
|
|
65
|
+
export interface Query extends RuleGroup {
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -16,6 +16,7 @@ export declare enum Controls {
|
|
|
16
16
|
HEADING_4 = "heading_4",
|
|
17
17
|
BULLET_LIST = "bulletList",
|
|
18
18
|
ORDERED_LIST = "orderedList",
|
|
19
|
+
TASK_LIST = "taskList",
|
|
19
20
|
TEXT_ALIGN_LEFT = "textAlignLeft",
|
|
20
21
|
TEXT_ALIGN_CENTER = "textAlignCenter",
|
|
21
22
|
TEXT_ALIGN_RIGHT = "textAlignRight",
|
|
@@ -17,6 +17,7 @@ export var Controls;
|
|
|
17
17
|
Controls["HEADING_4"] = "heading_4";
|
|
18
18
|
Controls["BULLET_LIST"] = "bulletList";
|
|
19
19
|
Controls["ORDERED_LIST"] = "orderedList";
|
|
20
|
+
Controls["TASK_LIST"] = "taskList";
|
|
20
21
|
Controls["TEXT_ALIGN_LEFT"] = "textAlignLeft";
|
|
21
22
|
Controls["TEXT_ALIGN_CENTER"] = "textAlignCenter";
|
|
22
23
|
Controls["TEXT_ALIGN_RIGHT"] = "textAlignRight";
|
|
@@ -15,6 +15,7 @@ export var Extensions;
|
|
|
15
15
|
Extensions["Strike"] = "strike";
|
|
16
16
|
Extensions["BulletList"] = "bulletList";
|
|
17
17
|
Extensions["OrderedList"] = "orderedList";
|
|
18
|
+
Extensions["TaskList"] = "taskList";
|
|
18
19
|
Extensions["AlignLeft"] = "alignLeft";
|
|
19
20
|
Extensions["AlignCenter"] = "alignCenter";
|
|
20
21
|
Extensions["AlignRight"] = "alignRight";
|
|
@@ -7,6 +7,7 @@ export var SlashCommands;
|
|
|
7
7
|
SlashCommands["Heading4"] = "Heading 4";
|
|
8
8
|
SlashCommands["BulletList"] = "Bullet List";
|
|
9
9
|
SlashCommands["NumberedList"] = "Numbered List";
|
|
10
|
+
SlashCommands["TaskList"] = "Task List";
|
|
10
11
|
SlashCommands["Code"] = "Code";
|
|
11
12
|
SlashCommands["CodeBlock"] = "Code Block";
|
|
12
13
|
SlashCommands["HorizontalRule"] = "Horizontal Rule";
|
|
@@ -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;
|
|
@@ -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, SeparatorHorizontalIcon, 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.",
|
|
@@ -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";
|
|
@@ -89,6 +91,7 @@ export const MINIMAL_EXTENSIONS = [
|
|
|
89
91
|
export const FULL_EXTENSIONS = [
|
|
90
92
|
...BASIC_EXTENSIONS,
|
|
91
93
|
Extensions.CodeBlock,
|
|
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);
|
|
@@ -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;
|
|
@@ -758,59 +760,77 @@ const StyledContent = styled.div `
|
|
|
758
760
|
|
|
759
761
|
ul[data-type="taskList"] {
|
|
760
762
|
list-style: none;
|
|
763
|
+
margin: 0.25rem 0;
|
|
761
764
|
padding: 0;
|
|
762
765
|
|
|
763
766
|
li {
|
|
764
767
|
display: flex;
|
|
765
|
-
align-items:
|
|
768
|
+
align-items: flex-start;
|
|
766
769
|
margin: 0.25rem 0;
|
|
767
770
|
|
|
768
771
|
> label {
|
|
772
|
+
display: inline-flex;
|
|
773
|
+
align-items: center;
|
|
774
|
+
justify-content: center;
|
|
769
775
|
flex: 0 0 auto;
|
|
776
|
+
height: 1.5rem;
|
|
770
777
|
margin-right: 0.5rem;
|
|
771
778
|
user-select: none;
|
|
772
779
|
}
|
|
773
780
|
|
|
774
781
|
> div {
|
|
775
782
|
flex: 1 1 auto;
|
|
783
|
+
min-width: 0;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
> div > ul[data-type="taskList"] {
|
|
787
|
+
margin: 0.25rem 0 0;
|
|
776
788
|
}
|
|
777
789
|
}
|
|
778
790
|
|
|
779
791
|
input[type="checkbox"] {
|
|
780
|
-
cursor: pointer;
|
|
781
|
-
margin: 0;
|
|
782
792
|
-webkit-appearance: none;
|
|
783
793
|
appearance: none;
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
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;
|
|
794
820
|
}
|
|
795
821
|
|
|
796
|
-
&:
|
|
797
|
-
background-color: ${({ theme }) => theme.
|
|
822
|
+
&:checked {
|
|
823
|
+
background-color: ${({ theme }) => theme.name === "DARK" ? "#cdcdcd" : "#646464"};
|
|
824
|
+
border-color: ${({ theme }) => theme.name === "DARK" ? "#cdcdcd" : "#646464"};
|
|
798
825
|
}
|
|
799
826
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
width: 0.75em;
|
|
803
|
-
height: 0.75em;
|
|
804
|
-
transform: scale(0);
|
|
805
|
-
transition: 120ms transform ease-in-out;
|
|
806
|
-
box-shadow: inset 1em 1em;
|
|
807
|
-
transform-origin: center;
|
|
808
|
-
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
|
809
|
-
color: ${({ theme }) => theme.palette.text.primary};
|
|
827
|
+
&:checked::after {
|
|
828
|
+
opacity: 1;
|
|
810
829
|
}
|
|
811
830
|
|
|
812
|
-
&:
|
|
813
|
-
|
|
831
|
+
&:focus-visible {
|
|
832
|
+
outline: 2px solid ${({ theme }) => theme.palette.primary.main}40;
|
|
833
|
+
outline-offset: 2px;
|
|
814
834
|
}
|
|
815
835
|
}
|
|
816
836
|
}
|
|
@@ -856,6 +876,9 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
|
|
|
856
876
|
if (command === SlashCommands.Table) {
|
|
857
877
|
return resolvedExtensionSet.has(Extensions.Table);
|
|
858
878
|
}
|
|
879
|
+
if (command === SlashCommands.TaskList) {
|
|
880
|
+
return resolvedExtensionSet.has(Extensions.TaskList);
|
|
881
|
+
}
|
|
859
882
|
return true;
|
|
860
883
|
}), [resolvedExtensionSet, slashCommands]);
|
|
861
884
|
const resolvedToolbarOptions = useMemo(() => {
|
|
@@ -872,6 +895,7 @@ export const RichTextEditor = ({ className, editorInstanceRef, defaultValue = ""
|
|
|
872
895
|
[Controls.HORIZONTAL_RULE]: Extensions.HorizontalRule,
|
|
873
896
|
[Controls.BULLET_LIST]: Extensions.BulletList,
|
|
874
897
|
[Controls.ORDERED_LIST]: Extensions.OrderedList,
|
|
898
|
+
[Controls.TASK_LIST]: Extensions.TaskList,
|
|
875
899
|
[Controls.COLOR]: Extensions.Color,
|
|
876
900
|
[Controls.HIGHLIGHT]: Extensions.Highlight,
|
|
877
901
|
[Controls.LINK]: Extensions.Link,
|
|
@@ -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;
|
|
@@ -20,10 +23,20 @@ export declare const Heading1Control: ({ editor }: ControlProps) => import("reac
|
|
|
20
23
|
export declare const Heading2Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
21
24
|
export declare const Heading3Control: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
22
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;
|
|
23
29
|
export declare const BulletListControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
24
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;
|
|
25
35
|
export declare const AlignLeftControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
26
36
|
export declare const AlignRightControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
27
37
|
export declare const AlignCenterControl: ({ editor }: ControlProps) => import("react/jsx-runtime").JSX.Element;
|
|
28
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;
|
|
29
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, IconSeparatorHorizontal, } 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",
|
|
@@ -204,6 +235,37 @@ export const Heading4Control = ({ editor }) => {
|
|
|
204
235
|
attributes: { level: 4 },
|
|
205
236
|
}, icon: IconH4 }));
|
|
206
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
|
+
};
|
|
207
269
|
export const BulletListControl = ({ editor }) => {
|
|
208
270
|
return (_jsx(Control, { editor: editor, label: "bulletListControlLabel", isActive: {
|
|
209
271
|
name: "bulletList",
|
|
@@ -218,6 +280,51 @@ export const OrderedListControl = ({ editor }) => {
|
|
|
218
280
|
name: "toggleOrderedList",
|
|
219
281
|
}, icon: IconListNumbers }));
|
|
220
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
|
+
};
|
|
221
328
|
export const AlignLeftControl = ({ editor }) => {
|
|
222
329
|
return (_jsx(Control, { editor: editor, label: "alignLeftControlLabel", isActive: {
|
|
223
330
|
name: { textAlign: "left" },
|
|
@@ -247,3 +354,35 @@ export const AlignJustifiedControl = ({ editor }) => {
|
|
|
247
354
|
name: { textAlign: "justify" },
|
|
248
355
|
}, operation: { name: "setTextAlign", attributes: "justify" }, icon: IconAlignJustified }));
|
|
249
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, HorizontalRuleControl,
|
|
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
|
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import TableDefaults from "../TableDefaults";
|
|
2
|
+
const enableResizeClass = (dataField) => {
|
|
3
|
+
if (dataField === undefined) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
document.querySelectorAll(`.resizer.col-${dataField}`).forEach((resizer) => {
|
|
7
|
+
resizer.classList.add("isResizing");
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
const disableResizeClass = (dataField) => {
|
|
11
|
+
if (dataField === undefined) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
document.querySelectorAll(`.resizer.col-${dataField}`).forEach((resizer) => {
|
|
15
|
+
resizer.classList.remove("isResizing");
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const resizeHandler = ({ event, columnId, columnProps, onResize, onResizeFinished, }) => {
|
|
19
|
+
let col = event.target
|
|
20
|
+
.parentElement;
|
|
21
|
+
let newColumns = [];
|
|
22
|
+
let x = 0;
|
|
23
|
+
let w = 0;
|
|
24
|
+
const mouseMoveHandler = function (e) {
|
|
25
|
+
const selectedColumn = document.querySelectorAll(`.column-${columnId}`);
|
|
26
|
+
const columnHeaders = document.querySelectorAll(`.mfui-th.column-${columnId}`);
|
|
27
|
+
const dx = e.clientX - x;
|
|
28
|
+
let newWidth = w + dx;
|
|
29
|
+
// Calculate what the minimum width should be
|
|
30
|
+
// min width should be the defined column width or the default min width
|
|
31
|
+
if (columnProps.minWidth === undefined) {
|
|
32
|
+
if (newWidth < TableDefaults.td.minWidth)
|
|
33
|
+
newWidth = TableDefaults.td.minWidth;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
if (newWidth < columnProps.minWidth)
|
|
37
|
+
newWidth = columnProps.minWidth;
|
|
38
|
+
}
|
|
39
|
+
selectedColumn.forEach((col) => {
|
|
40
|
+
var _a;
|
|
41
|
+
col.style.width = `${newWidth}px`;
|
|
42
|
+
col.style.flex = "0 0 auto";
|
|
43
|
+
// col.style.maxWidth = `${newWidth}px`;
|
|
44
|
+
// col.style.minWidth = `${newWidth}px`;
|
|
45
|
+
newColumns.push({
|
|
46
|
+
dataField: ((_a = col === null || col === void 0 ? void 0 : col.dataset) === null || _a === void 0 ? void 0 : _a.field) || "",
|
|
47
|
+
width: newWidth,
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
newColumns = Array.from(columnHeaders).map((col) => {
|
|
51
|
+
var _a;
|
|
52
|
+
return {
|
|
53
|
+
dataField: ((_a = col === null || col === void 0 ? void 0 : col.dataset) === null || _a === void 0 ? void 0 : _a.field) || "",
|
|
54
|
+
width: newWidth,
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
onResize({
|
|
58
|
+
columns: newColumns,
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
const mouseUpHandler = function () {
|
|
62
|
+
var _a, _b, _c;
|
|
63
|
+
let newWidth = ((_c = (_b = (_a = document === null || document === void 0 ? void 0 : document.querySelector) === null || _a === void 0 ? void 0 : _a.call(document, `.column-${columnId}`)) === null || _b === void 0 ? void 0 : _b.style) === null || _c === void 0 ? void 0 : _c.width) || null;
|
|
64
|
+
if (newWidth) {
|
|
65
|
+
newWidth = newWidth.replace("px", "");
|
|
66
|
+
}
|
|
67
|
+
disableResizeClass(columnId);
|
|
68
|
+
document.removeEventListener("mousemove", mouseMoveHandler);
|
|
69
|
+
document.removeEventListener("mouseup", mouseUpHandler);
|
|
70
|
+
onResizeFinished === null || onResizeFinished === void 0 ? void 0 : onResizeFinished({
|
|
71
|
+
column: columnProps,
|
|
72
|
+
columnId: columnId,
|
|
73
|
+
targetColumn: document.querySelector(`.column-${columnId}`),
|
|
74
|
+
newWidth,
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
x = event.clientX;
|
|
78
|
+
const styles = window.getComputedStyle(col);
|
|
79
|
+
w = parseInt(styles.width, 10);
|
|
80
|
+
document.addEventListener("mousemove", mouseMoveHandler);
|
|
81
|
+
document.addEventListener("mouseup", mouseUpHandler);
|
|
82
|
+
enableResizeClass(columnId);
|
|
83
|
+
};
|
|
84
|
+
export default resizeHandler;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monolith-forensics/monolith-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Matt Danner (Monolith Forensics LLC)",
|
|
@@ -48,7 +48,10 @@
|
|
|
48
48
|
"@tiptap/extension-horizontal-rule": "3.22.4",
|
|
49
49
|
"@tiptap/extension-image": "3.22.4",
|
|
50
50
|
"@tiptap/extension-link": "3.22.4",
|
|
51
|
+
"@tiptap/extension-list": "3.22.4",
|
|
51
52
|
"@tiptap/extension-table": "3.22.4",
|
|
53
|
+
"@tiptap/extension-task-item": "3.22.4",
|
|
54
|
+
"@tiptap/extension-task-list": "3.22.4",
|
|
52
55
|
"@tiptap/extension-text-align": "3.22.4",
|
|
53
56
|
"@tiptap/extension-text-style": "3.22.4",
|
|
54
57
|
"@tiptap/extensions": "3.22.4",
|