@monolith-forensics/monolith-ui 1.9.3-dev.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/Button/Button.js +11 -4
  2. package/dist/DropDownMenu/DropDownMenu.js +12 -2
  3. package/dist/DropDownMenu/components/MenuComponent.js +7 -1
  4. package/dist/DropDownMenu/components/MenuItem.js +4 -2
  5. package/dist/DropDownMenu/components/MenuItemList.d.ts +1 -0
  6. package/dist/DropDownMenu/components/MenuItemList.js +17 -7
  7. package/dist/DropDownMenu/components/SearchInput.js +2 -1
  8. package/dist/DropDownMenu/components/StyledContent.js +3 -2
  9. package/dist/DropDownMenu/constants.d.ts +4 -0
  10. package/dist/DropDownMenu/constants.js +4 -0
  11. package/dist/QueryFilter/DefaultOperators.d.ts +76 -0
  12. package/dist/QueryFilter/DefaultOperators.js +21 -0
  13. package/dist/QueryFilter/types.d.ts +66 -0
  14. package/dist/QueryFilter/types.js +1 -0
  15. package/dist/RichTextEditor/Enums/Controls.d.ts +2 -0
  16. package/dist/RichTextEditor/Enums/Controls.js +2 -0
  17. package/dist/RichTextEditor/Enums/Extensions.d.ts +1 -0
  18. package/dist/RichTextEditor/Enums/Extensions.js +1 -0
  19. package/dist/RichTextEditor/Enums/SlashCommands.d.ts +2 -0
  20. package/dist/RichTextEditor/Enums/SlashCommands.js +2 -0
  21. package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +7 -0
  22. package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +157 -0
  23. package/dist/RichTextEditor/Extensions/getSlashCommand.js +19 -1
  24. package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +16 -1
  25. package/dist/RichTextEditor/RichTextEditor.js +65 -28
  26. package/dist/RichTextEditor/Toolbar/Controls.d.ts +14 -0
  27. package/dist/RichTextEditor/Toolbar/Controls.js +147 -3
  28. package/dist/RichTextEditor/Toolbar/Labels.d.ts +1 -0
  29. package/dist/RichTextEditor/Toolbar/Labels.js +1 -0
  30. package/dist/RichTextEditor/Toolbar/Toolbar.js +28 -2
  31. package/dist/Table/Utils/resizeHandler.d.ts +3 -0
  32. package/dist/Table/Utils/resizeHandler.js +84 -0
  33. package/package.json +4 -1
@@ -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: background-color 0.2s, border 0.2s;
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" }, dropDownProps, { children: children })) })) }) })) }) })] }));
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 ? "auto" : `${getControlSizeTokens(size).menuRowHeight}px`};
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;
@@ -24,5 +24,6 @@ export declare const MenuItemList: React.FC<{
24
24
  onScroll?: (e: Event) => void;
25
25
  onScrollToTop?: (e: Event) => void;
26
26
  onScrollToBottom?: (e: Event) => void;
27
+ maxDropdownHeight?: number;
27
28
  query?: DropDownMenuProps["query"];
28
29
  }>;
@@ -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) ? itemHeight : estimatedDynamicItemHeight);
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 height = viewPortDimensions.height
262
- ? viewPortDimensions.height
263
- : estimatedHeight < 200
264
- ? estimatedHeight
265
- : 200;
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
- export const SearchInput = forwardRef((props, ref) => _jsx(Input, Object.assign({ ref: ref, style: { marginBottom: 8 } }, props)));
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 || "250px"};
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: 5px;
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,4 @@
1
+ export declare const DEFAULT_DROPDOWN_MAX_HEIGHT = 250;
2
+ export declare const DROPDOWN_CONTENT_PADDING = 5;
3
+ export declare const DROPDOWN_CONTENT_VERTICAL_PADDING: number;
4
+ export declare const SEARCH_INPUT_MARGIN_BOTTOM = 8;
@@ -0,0 +1,4 @@
1
+ export const DEFAULT_DROPDOWN_MAX_HEIGHT = 250;
2
+ export const DROPDOWN_CONTENT_PADDING = 5;
3
+ export const DROPDOWN_CONTENT_VERTICAL_PADDING = DROPDOWN_CONTENT_PADDING * 2;
4
+ export const SEARCH_INPUT_MARGIN_BOTTOM = 8;
@@ -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 {};
@@ -8,6 +8,7 @@ export declare enum Controls {
8
8
  CLEAR_FORMATTING = "clearFormatting",
9
9
  CODE = "code",
10
10
  CODE_BLOCK = "codeBlock",
11
+ HORIZONTAL_RULE = "horizontalRule",
11
12
  BLOCKQUOTE = "blockquote",
12
13
  HEADING_1 = "heading_1",
13
14
  HEADING_2 = "heading_2",
@@ -15,6 +16,7 @@ export declare enum Controls {
15
16
  HEADING_4 = "heading_4",
16
17
  BULLET_LIST = "bulletList",
17
18
  ORDERED_LIST = "orderedList",
19
+ TASK_LIST = "taskList",
18
20
  TEXT_ALIGN_LEFT = "textAlignLeft",
19
21
  TEXT_ALIGN_CENTER = "textAlignCenter",
20
22
  TEXT_ALIGN_RIGHT = "textAlignRight",
@@ -9,6 +9,7 @@ export var Controls;
9
9
  Controls["CLEAR_FORMATTING"] = "clearFormatting";
10
10
  Controls["CODE"] = "code";
11
11
  Controls["CODE_BLOCK"] = "codeBlock";
12
+ Controls["HORIZONTAL_RULE"] = "horizontalRule";
12
13
  Controls["BLOCKQUOTE"] = "blockquote";
13
14
  Controls["HEADING_1"] = "heading_1";
14
15
  Controls["HEADING_2"] = "heading_2";
@@ -16,6 +17,7 @@ export var Controls;
16
17
  Controls["HEADING_4"] = "heading_4";
17
18
  Controls["BULLET_LIST"] = "bulletList";
18
19
  Controls["ORDERED_LIST"] = "orderedList";
20
+ Controls["TASK_LIST"] = "taskList";
19
21
  Controls["TEXT_ALIGN_LEFT"] = "textAlignLeft";
20
22
  Controls["TEXT_ALIGN_CENTER"] = "textAlignCenter";
21
23
  Controls["TEXT_ALIGN_RIGHT"] = "textAlignRight";
@@ -14,6 +14,7 @@ export declare enum Extensions {
14
14
  Strike = "strike",
15
15
  BulletList = "bulletList",
16
16
  OrderedList = "orderedList",
17
+ TaskList = "taskList",
17
18
  AlignLeft = "alignLeft",
18
19
  AlignCenter = "alignCenter",
19
20
  AlignRight = "alignRight",
@@ -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";
@@ -6,8 +6,10 @@ export declare enum SlashCommands {
6
6
  Heading4 = "Heading 4",
7
7
  BulletList = "Bullet List",
8
8
  NumberedList = "Numbered List",
9
+ TaskList = "Task List",
9
10
  Code = "Code",
10
11
  CodeBlock = "Code Block",
12
+ HorizontalRule = "Horizontal Rule",
11
13
  Blockquote = "Blockquote",
12
14
  CurrentDate = "Current Date",
13
15
  CurrentTimestamp = "Current Timestamp",
@@ -7,8 +7,10 @@ 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";
13
+ SlashCommands["HorizontalRule"] = "Horizontal Rule";
12
14
  SlashCommands["Blockquote"] = "Blockquote";
13
15
  SlashCommands["CurrentDate"] = "Current Date";
14
16
  SlashCommands["CurrentTimestamp"] = "Current Timestamp";
@@ -0,0 +1,7 @@
1
+ import { Extension } from "@tiptap/core";
2
+ import { BubbleItem } from "../Components/BubbleMenu";
3
+ export type BubbleMenuOptions = {
4
+ customMenuItems?: BubbleItem[];
5
+ };
6
+ declare const BubbleMenu: Extension<any, any>;
7
+ export default BubbleMenu;
@@ -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;