@bigbinary/neeto-editor 0.2.0 → 0.2.4
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/index.js +28 -7
- package/package.json +7 -5
- package/tailwind.config.js +13 -9
- package/webpack.config.js +9 -1
- package/webpack.dev.config.js +9 -1
- package/public/favicon.ico +0 -0
- package/public/index.html +0 -28
- package/public/robots.txt +0 -3
- package/src/App.js +0 -8
- package/src/Common/Avatar.js +0 -168
- package/src/Common/CodeBlock.js +0 -11
- package/src/Common/Description.js +0 -12
- package/src/Common/Dropdown/index.js +0 -118
- package/src/Common/Heading.js +0 -13
- package/src/Common/HighlightText.js +0 -7
- package/src/Common/Icons/HashtagFilled.js +0 -59
- package/src/Common/Icons/TextColor.js +0 -35
- package/src/Common/Icons/index.js +0 -2
- package/src/Common/ListItems.js +0 -17
- package/src/Editor/CustomExtensions/BubbleMenu/index.js +0 -92
- package/src/Editor/CustomExtensions/CodeBlock/CodeBlockComponent.js +0 -12
- package/src/Editor/CustomExtensions/CodeBlock/ExtensionConfig.js +0 -10
- package/src/Editor/CustomExtensions/Embeds.js +0 -72
- package/src/Editor/CustomExtensions/FixedMenu/FontSizeOption.js +0 -32
- package/src/Editor/CustomExtensions/FixedMenu/TextColorOption.js +0 -29
- package/src/Editor/CustomExtensions/FixedMenu/constants.js +0 -3
- package/src/Editor/CustomExtensions/FixedMenu/index.js +0 -186
- package/src/Editor/CustomExtensions/Image/ExtensionConfig.js +0 -47
- package/src/Editor/CustomExtensions/Image/Uploader.js +0 -41
- package/src/Editor/CustomExtensions/Mention/ExtensionConfig.js +0 -67
- package/src/Editor/CustomExtensions/Mention/MentionList.js +0 -96
- package/src/Editor/CustomExtensions/Mention/helpers.js +0 -23
- package/src/Editor/CustomExtensions/Placeholder/ExtensionConfig.js +0 -81
- package/src/Editor/CustomExtensions/Placeholder/helpers.js +0 -18
- package/src/Editor/CustomExtensions/SlashCommands/Commands.js +0 -20
- package/src/Editor/CustomExtensions/SlashCommands/CommandsList.js +0 -109
- package/src/Editor/CustomExtensions/SlashCommands/ExtensionConfig.js +0 -205
- package/src/Editor/CustomExtensions/Variable/ExtensionConfig.js +0 -208
- package/src/Editor/CustomExtensions/Variable/VariableList.js +0 -45
- package/src/Editor/CustomExtensions/Variable/VariableSuggestion.js +0 -20
- package/src/Editor/CustomExtensions/Variable/helpers.js +0 -31
- package/src/Editor/CustomExtensions/Variable/index.js +0 -35
- package/src/Editor/CustomExtensions/useCustomExtensions.js +0 -87
- package/src/Editor/index.js +0 -92
- package/src/Editor/sharedState.js +0 -8
- package/src/examples/constants.js +0 -95
- package/src/examples/index.js +0 -186
- package/src/hooks/useOutsideClick.js +0 -19
- package/src/index.js +0 -10
- package/src/index.scss +0 -41
- package/src/styles/abstracts/_mixins.scss +0 -20
- package/src/styles/abstracts/_neeto-ui-variables.scss +0 -36
- package/src/styles/abstracts/_variables.scss +0 -10
- package/src/styles/components/_avatar.scss +0 -105
- package/src/styles/components/_codeblock.scss +0 -16
- package/src/styles/components/_command-list.scss +0 -19
- package/src/styles/components/_dropdown.scss +0 -69
- package/src/styles/components/_editor-variables.scss +0 -12
- package/src/styles/components/_editor.scss +0 -98
- package/src/styles/components/_fixed-menu.scss +0 -13
- package/src/utils/common.js +0 -13
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import VariableList from "./VariableList";
|
|
4
|
-
|
|
5
|
-
const VariableSuggestion = ({ items, command }) => {
|
|
6
|
-
return (
|
|
7
|
-
<div className="shadow-md">
|
|
8
|
-
<VariableList
|
|
9
|
-
variables={items}
|
|
10
|
-
onClickVariable={(variable) => {
|
|
11
|
-
const { category_key, key } = variable;
|
|
12
|
-
const variableName = category_key ? `${category_key}.${key}` : key;
|
|
13
|
-
command({ label: variableName, id: variableName });
|
|
14
|
-
}}
|
|
15
|
-
/>
|
|
16
|
-
</div>
|
|
17
|
-
);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default VariableSuggestion;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/* Helper function that accepts an array of variables and injects category to each item in the group
|
|
2
|
-
And also performs grouping of indvidual variables under common category as 'Others'. */
|
|
3
|
-
|
|
4
|
-
export const parseVariables = (variableArr = []) => {
|
|
5
|
-
const uncategorized = [];
|
|
6
|
-
const groupedVariables = [];
|
|
7
|
-
variableArr.forEach((variable) => {
|
|
8
|
-
const { category_key, category_label, variables } = variable;
|
|
9
|
-
if (category_key && variables) {
|
|
10
|
-
const parsedVariables = variables.map((categoryVariable) => ({
|
|
11
|
-
...categoryVariable,
|
|
12
|
-
category_key,
|
|
13
|
-
}));
|
|
14
|
-
groupedVariables.push({
|
|
15
|
-
label: category_label,
|
|
16
|
-
variables: parsedVariables,
|
|
17
|
-
});
|
|
18
|
-
} else uncategorized.push(variable);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
/* If there are other categorised variables already present, group all uncategorized variables under title 'Others'.
|
|
22
|
-
otherwise, if all available variables are uncategorised, do not render 'Others' title */
|
|
23
|
-
|
|
24
|
-
if (uncategorized.length) {
|
|
25
|
-
groupedVariables.push({
|
|
26
|
-
label: groupedVariables.length ? "Others" : null,
|
|
27
|
-
variables: uncategorized,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
return groupedVariables;
|
|
31
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import VariableList from "./VariableList";
|
|
4
|
-
import Dropdown from "../../../Common/Dropdown";
|
|
5
|
-
import { HashtagFilled } from "../../../Common/Icons";
|
|
6
|
-
|
|
7
|
-
import { MENU_ICON_SIZE } from "../FixedMenu/constants";
|
|
8
|
-
|
|
9
|
-
const Variables = ({ editor, variables }) => {
|
|
10
|
-
const handleClickItem = (item) => {
|
|
11
|
-
const { category_key, key } = item;
|
|
12
|
-
const variableName = category_key ? `${category_key}.${key}` : key;
|
|
13
|
-
editor.chain().focus().setVariable({ label: variableName }).run();
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
if (!(variables && variables.length)) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<Dropdown
|
|
22
|
-
customTarget={() => (
|
|
23
|
-
<button className="relative p-3 editor-fixed-menu--item variable-selection-popup">
|
|
24
|
-
<HashtagFilled size={MENU_ICON_SIZE} />
|
|
25
|
-
</button>
|
|
26
|
-
)}
|
|
27
|
-
>
|
|
28
|
-
<div className="items-container">
|
|
29
|
-
<VariableList onClickVariable={handleClickItem} variables={variables} />
|
|
30
|
-
</div>
|
|
31
|
-
</Dropdown>
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export default Variables;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import StarterKit from "@tiptap/starter-kit";
|
|
2
|
-
import Document from "@tiptap/extension-document";
|
|
3
|
-
import Typography from "@tiptap/extension-typography";
|
|
4
|
-
import Highlight from "@tiptap/extension-highlight";
|
|
5
|
-
import Dropcursor from "@tiptap/extension-dropcursor";
|
|
6
|
-
import Link from "@tiptap/extension-link";
|
|
7
|
-
import Color from "@tiptap/extension-color";
|
|
8
|
-
import TextStyle from "@tiptap/extension-text-style";
|
|
9
|
-
import isEmpty from "lodash.isempty";
|
|
10
|
-
|
|
11
|
-
import ImageExtension from "./Image/ExtensionConfig";
|
|
12
|
-
import Underline from "@tiptap/extension-underline";
|
|
13
|
-
import SlashCommands from "./SlashCommands/ExtensionConfig";
|
|
14
|
-
import CodeBlock from "./CodeBlock/ExtensionConfig";
|
|
15
|
-
import Variable from "./Variable/ExtensionConfig";
|
|
16
|
-
import Placeholder, {
|
|
17
|
-
placeholderGenerator,
|
|
18
|
-
} from "./Placeholder/ExtensionConfig";
|
|
19
|
-
import Mention, { createMentionSuggestions } from "./Mention/ExtensionConfig";
|
|
20
|
-
import Embeds from "./Embeds";
|
|
21
|
-
|
|
22
|
-
export default function useCustomExtensions({
|
|
23
|
-
forceTitle,
|
|
24
|
-
placeholder,
|
|
25
|
-
extensions,
|
|
26
|
-
mentions,
|
|
27
|
-
variables,
|
|
28
|
-
isSlashCommandsActive,
|
|
29
|
-
showImageInMention,
|
|
30
|
-
}) {
|
|
31
|
-
let customExtensions;
|
|
32
|
-
|
|
33
|
-
if (extensions) {
|
|
34
|
-
customExtensions = [...extensions];
|
|
35
|
-
} else {
|
|
36
|
-
customExtensions = [
|
|
37
|
-
StarterKit.configure({
|
|
38
|
-
document: !forceTitle,
|
|
39
|
-
}),
|
|
40
|
-
Underline,
|
|
41
|
-
Typography,
|
|
42
|
-
TextStyle,
|
|
43
|
-
Highlight,
|
|
44
|
-
CodeBlock,
|
|
45
|
-
ImageExtension,
|
|
46
|
-
Dropcursor,
|
|
47
|
-
Embeds,
|
|
48
|
-
Link,
|
|
49
|
-
Color,
|
|
50
|
-
Placeholder.configure({
|
|
51
|
-
placeholder: placeholderGenerator(placeholder),
|
|
52
|
-
}),
|
|
53
|
-
];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (forceTitle) {
|
|
57
|
-
customExtensions.unshift(
|
|
58
|
-
Document.extend({
|
|
59
|
-
content: "heading block*",
|
|
60
|
-
})
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (isSlashCommandsActive) {
|
|
65
|
-
customExtensions.push(SlashCommands);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (!isEmpty(mentions)) {
|
|
69
|
-
customExtensions.push(
|
|
70
|
-
Mention.configure({
|
|
71
|
-
suggestion: {
|
|
72
|
-
items: createMentionSuggestions(mentions, {
|
|
73
|
-
showImage: showImageInMention,
|
|
74
|
-
}),
|
|
75
|
-
},
|
|
76
|
-
})
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (!isEmpty(variables)) {
|
|
81
|
-
customExtensions.push(
|
|
82
|
-
Variable.configure({ suggestion: { items: () => variables } })
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return customExtensions;
|
|
87
|
-
}
|
package/src/Editor/index.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import classNames from "classnames";
|
|
3
|
-
import { useEditor, EditorContent } from "@tiptap/react";
|
|
4
|
-
|
|
5
|
-
import BubbleMenu from "./CustomExtensions/BubbleMenu";
|
|
6
|
-
import FixedMenu from "./CustomExtensions/FixedMenu";
|
|
7
|
-
import ImageUploader from "./CustomExtensions/Image/Uploader";
|
|
8
|
-
import useCustomExtensions from "./CustomExtensions/useCustomExtensions";
|
|
9
|
-
|
|
10
|
-
const Tiptap = (
|
|
11
|
-
{
|
|
12
|
-
forceTitle = false,
|
|
13
|
-
hideSlashCommands = false,
|
|
14
|
-
hideBubbleMenu = false,
|
|
15
|
-
formatterOptions = [
|
|
16
|
-
"bold",
|
|
17
|
-
"italic",
|
|
18
|
-
"code",
|
|
19
|
-
"highlight",
|
|
20
|
-
"strike",
|
|
21
|
-
"link",
|
|
22
|
-
],
|
|
23
|
-
className,
|
|
24
|
-
uploadEndpoint,
|
|
25
|
-
initialValue = "",
|
|
26
|
-
onChange = () => {},
|
|
27
|
-
menuType = "fixed",
|
|
28
|
-
variables,
|
|
29
|
-
mentions,
|
|
30
|
-
showImageInMention = false,
|
|
31
|
-
placeholder,
|
|
32
|
-
extensions,
|
|
33
|
-
...otherProps
|
|
34
|
-
},
|
|
35
|
-
ref
|
|
36
|
-
) => {
|
|
37
|
-
const isFixedMenuActive = menuType === "fixed";
|
|
38
|
-
const isBubbleMenuActive = menuType === "bubble";
|
|
39
|
-
const isSlashCommandsActive = !hideSlashCommands;
|
|
40
|
-
const showSlashCommandPlaceholder = !placeholder && isSlashCommandsActive;
|
|
41
|
-
|
|
42
|
-
const customExtensions = useCustomExtensions({
|
|
43
|
-
forceTitle,
|
|
44
|
-
placeholder,
|
|
45
|
-
extensions,
|
|
46
|
-
mentions,
|
|
47
|
-
variables,
|
|
48
|
-
isSlashCommandsActive,
|
|
49
|
-
showImageInMention,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const editor = useEditor({
|
|
53
|
-
extensions: customExtensions,
|
|
54
|
-
content: initialValue,
|
|
55
|
-
injectCSS: false,
|
|
56
|
-
editorProps: {
|
|
57
|
-
attributes: {
|
|
58
|
-
class:
|
|
59
|
-
className ||
|
|
60
|
-
classNames(
|
|
61
|
-
"prose focus:outline-none whitespace-pre-wrap border p-3",
|
|
62
|
-
{
|
|
63
|
-
"slash-active": showSlashCommandPlaceholder,
|
|
64
|
-
"fixed-menu-active": isFixedMenuActive,
|
|
65
|
-
"bubble-menu-active": isBubbleMenuActive,
|
|
66
|
-
}
|
|
67
|
-
),
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
onUpdate: ({ editor }) => onChange(editor.getHTML()),
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
/* Make editor object available to the parent */
|
|
74
|
-
React.useImperativeHandle(ref, () => ({
|
|
75
|
-
editor: editor,
|
|
76
|
-
}));
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<>
|
|
80
|
-
{isFixedMenuActive ? (
|
|
81
|
-
<FixedMenu editor={editor} variables={variables} />
|
|
82
|
-
) : null}
|
|
83
|
-
{isBubbleMenuActive ? (
|
|
84
|
-
<BubbleMenu editor={editor} formatterOptions={formatterOptions} />
|
|
85
|
-
) : null}
|
|
86
|
-
<ImageUploader editor={editor} imageUploadUrl={uploadEndpoint} />
|
|
87
|
-
<EditorContent editor={editor} {...otherProps} />
|
|
88
|
-
</>
|
|
89
|
-
);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
export default React.forwardRef(Tiptap);
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
export const EDITOR_FEATURES = [
|
|
2
|
-
"Multiple Menu options such as Fixed, Bubble",
|
|
3
|
-
"Support for inline styles: Bold, Italic, Underline, StrikeThrough",
|
|
4
|
-
"Support for diffent font sizes, Blockquote and Code",
|
|
5
|
-
"Support for font color option",
|
|
6
|
-
"Support for adding Links and Images",
|
|
7
|
-
"Ordered and Unordered List Support",
|
|
8
|
-
"Undo and Redo available",
|
|
9
|
-
"Inbuilt variable support",
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
export const SAMPLE_VARIABLES = [
|
|
13
|
-
{
|
|
14
|
-
category_key: "ticket",
|
|
15
|
-
category_label: "Ticket",
|
|
16
|
-
variables: [
|
|
17
|
-
{ label: "ID", key: "id" },
|
|
18
|
-
{ label: "Number", key: "number" },
|
|
19
|
-
],
|
|
20
|
-
},
|
|
21
|
-
{ label: "Subdomain", key: "subdomain" },
|
|
22
|
-
{
|
|
23
|
-
category_key: "organisation",
|
|
24
|
-
category_label: "Organisation",
|
|
25
|
-
variables: [
|
|
26
|
-
{ label: "ID", key: "id" },
|
|
27
|
-
{ label: "Name", key: "name" },
|
|
28
|
-
{ label: "Slug", key: "slug" },
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
export const SAMPLE_MENTIONS = [
|
|
34
|
-
{
|
|
35
|
-
label: "Oliver Smith",
|
|
36
|
-
key: "oliver-smith",
|
|
37
|
-
imageUrl: "https://via.placeholder.com/150/0000FF/808080",
|
|
38
|
-
},
|
|
39
|
-
"Jaden Smith",
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
export const STRINGS = {
|
|
43
|
-
fixedMenuSampleCode: `
|
|
44
|
-
<Editor />`,
|
|
45
|
-
|
|
46
|
-
bubbleMenuSampleCode: `
|
|
47
|
-
<Editor menuType='bubble'/>`,
|
|
48
|
-
|
|
49
|
-
hideSlashCommandSampleCode: `
|
|
50
|
-
<Editor hideSlashCommands />`,
|
|
51
|
-
|
|
52
|
-
variableSampleCode: `
|
|
53
|
-
const variables = [
|
|
54
|
-
{
|
|
55
|
-
category_key: "ticket",
|
|
56
|
-
category_label: "Ticket",
|
|
57
|
-
variables: [
|
|
58
|
-
{ label: "ID", key: "id" },
|
|
59
|
-
{ label: "Number", key: "number" },
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
{ label: "Subdomain", key: "subdomain" },
|
|
63
|
-
{
|
|
64
|
-
category_key: "organisation",
|
|
65
|
-
category_label: "Organisation",
|
|
66
|
-
variables: [
|
|
67
|
-
{ label: "ID", key: "id" },
|
|
68
|
-
{ label: "Name", key: "name" },
|
|
69
|
-
{ label: "Slug", key: "slug" },
|
|
70
|
-
],
|
|
71
|
-
},
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
<Editor variables={variables} />`,
|
|
75
|
-
|
|
76
|
-
mentionsSampleCode: `
|
|
77
|
-
const mentions = [
|
|
78
|
-
{
|
|
79
|
-
label: "Oliver Smith",
|
|
80
|
-
key: "oliver-smith",
|
|
81
|
-
imageUrl: "https://via.placeholder.com/150/0000FF/808080"
|
|
82
|
-
},
|
|
83
|
-
"Jaden Smith",
|
|
84
|
-
]
|
|
85
|
-
|
|
86
|
-
<Editor mentions={mentions} showImageInMention />`,
|
|
87
|
-
|
|
88
|
-
placeholderSampleCode: `
|
|
89
|
-
<Editor placeholder="Input text here" />`,
|
|
90
|
-
|
|
91
|
-
forceTitleSampleCode: `
|
|
92
|
-
const placeholder = { header: 'Input title here' };
|
|
93
|
-
|
|
94
|
-
<Editor placeholder={placeholder} forceTitle />`,
|
|
95
|
-
};
|
package/src/examples/index.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import React, { useRef } from "react";
|
|
2
|
-
|
|
3
|
-
import CodeBlock from "../Common/CodeBlock";
|
|
4
|
-
import Description from "../Common/Description";
|
|
5
|
-
import Heading from "../Common/Heading";
|
|
6
|
-
import HighlightText from "../Common/HighlightText";
|
|
7
|
-
import ListItems from "../Common/ListItems";
|
|
8
|
-
import Editor from "../Editor";
|
|
9
|
-
import {
|
|
10
|
-
EDITOR_FEATURES,
|
|
11
|
-
SAMPLE_MENTIONS,
|
|
12
|
-
SAMPLE_VARIABLES,
|
|
13
|
-
STRINGS,
|
|
14
|
-
} from "./constants";
|
|
15
|
-
|
|
16
|
-
const Example = () => {
|
|
17
|
-
const ref = useRef();
|
|
18
|
-
|
|
19
|
-
const getHTML = () => {
|
|
20
|
-
return ref.current.editor.getHTML();
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div style={{ margin: "48px 60px" }}>
|
|
25
|
-
<Heading>Neeto Editor</Heading>
|
|
26
|
-
<div className="flex justify-end">
|
|
27
|
-
<button
|
|
28
|
-
className="px-3 py-1 text-sm font-medium border border-gray-200 rounded shadow-sm"
|
|
29
|
-
onClick={() => {
|
|
30
|
-
// eslint-disable-next-line no-console
|
|
31
|
-
console.log({
|
|
32
|
-
html: getHTML(),
|
|
33
|
-
});
|
|
34
|
-
}}
|
|
35
|
-
>
|
|
36
|
-
Print output to console
|
|
37
|
-
</button>
|
|
38
|
-
</div>
|
|
39
|
-
<hr className="my-2 border-gray-100" />
|
|
40
|
-
<Editor ref={ref} variables={SAMPLE_VARIABLES} />
|
|
41
|
-
<Heading type="sub">Features</Heading>
|
|
42
|
-
<ListItems items={EDITOR_FEATURES} ordered />
|
|
43
|
-
|
|
44
|
-
<Heading>Installation</Heading>
|
|
45
|
-
<CodeBlock>yarn add https://github.com/bigbinary/neeto-editor</CodeBlock>
|
|
46
|
-
|
|
47
|
-
<Heading>Usage</Heading>
|
|
48
|
-
<CodeBlock>import Editor from 'bigbinary/neeto-editor'</CodeBlock>
|
|
49
|
-
<Heading type="sub">Fixed Menu</Heading>
|
|
50
|
-
<Description>
|
|
51
|
-
The default Neeto Editor layout comes with a set of always-on-top fixed
|
|
52
|
-
menu controls to interact with the editor
|
|
53
|
-
</Description>
|
|
54
|
-
<div className="flex">
|
|
55
|
-
<CodeBlock>{STRINGS.fixedMenuSampleCode}</CodeBlock>
|
|
56
|
-
<SampleEditor />
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
<Heading type="sub">Bubble Menu</Heading>
|
|
60
|
-
<Description>
|
|
61
|
-
If you would like to use an on-demand menu to interact with the editor
|
|
62
|
-
rather than an always-on-top fixed menu, Neeto Editor support Bubble
|
|
63
|
-
Menu option that appears when user selects part of text.
|
|
64
|
-
</Description>
|
|
65
|
-
<div className="flex">
|
|
66
|
-
<CodeBlock>{STRINGS.bubbleMenuSampleCode}</CodeBlock>
|
|
67
|
-
<SampleEditor menuType="bubble" />
|
|
68
|
-
</div>
|
|
69
|
-
|
|
70
|
-
<Heading type="sub">Slash Commands</Heading>
|
|
71
|
-
<Description>
|
|
72
|
-
Slash commands are actions that can be applied to block of text. This
|
|
73
|
-
menu is enabled by default and appears when user types{" "}
|
|
74
|
-
<HighlightText>/</HighlightText> at start of new line. Slash commands
|
|
75
|
-
can be disabled using <HighlightText>hideSlashCommands</HighlightText>{" "}
|
|
76
|
-
prop.
|
|
77
|
-
</Description>
|
|
78
|
-
<div className="flex">
|
|
79
|
-
<CodeBlock>{STRINGS.hideSlashCommandSampleCode}</CodeBlock>
|
|
80
|
-
<SampleEditor hideSlashCommands />
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
<Heading type="sub">Variable Support</Heading>
|
|
84
|
-
<Description>
|
|
85
|
-
Neeto Editor supports variable placement. Pass array of variables as{" "}
|
|
86
|
-
<HighlightText>variables</HighlightText> prop. Users can choose from
|
|
87
|
-
available variables from the <HighlightText>{"{}"}</HighlightText> menu.
|
|
88
|
-
Alternatively, the available variable options can be displayed by typing{" "}
|
|
89
|
-
<HighlightText>{"{{"}</HighlightText> within the editor.
|
|
90
|
-
</Description>
|
|
91
|
-
<div className="flex">
|
|
92
|
-
<CodeBlock>{STRINGS.variableSampleCode}</CodeBlock>
|
|
93
|
-
<SampleEditor variables={SAMPLE_VARIABLES} />
|
|
94
|
-
</div>
|
|
95
|
-
<Description>
|
|
96
|
-
Variables that belong to a spefic category can be categorised by passing
|
|
97
|
-
a <HighlightText>category_key</HighlightText> and{" "}
|
|
98
|
-
<HighlightText>category_label</HighlightText> attributes. All other
|
|
99
|
-
variables are shown under 'Others'
|
|
100
|
-
</Description>
|
|
101
|
-
|
|
102
|
-
<Heading type="sub">Support for Mentions</Heading>
|
|
103
|
-
<Description>
|
|
104
|
-
Neeto Editor comes with inbuilt support for mentions marking. Editor
|
|
105
|
-
accepts a list of mention-able values as{" "}
|
|
106
|
-
<HighlightText>mentions</HighlightText> prop. The list could either be
|
|
107
|
-
items of shape{" "}
|
|
108
|
-
<HighlightText>
|
|
109
|
-
{
|
|
110
|
-
"{label: 'Mention 1', key: 'mention1', imageUrl: 'optional_image_url.jpg'}"
|
|
111
|
-
}
|
|
112
|
-
</HighlightText>{" "}
|
|
113
|
-
or items can be just plain text like{" "}
|
|
114
|
-
<HighlightText>'Mention1'</HighlightText>. The available mention
|
|
115
|
-
suggestions are shown in editor when user types a{" "}
|
|
116
|
-
<HighlightText>@</HighlightText> character within editor content. The
|
|
117
|
-
avatar image in the mention suggestion list is enabled by providing
|
|
118
|
-
truthy value to the <HighlightText>showImageInMention</HighlightText>{" "}
|
|
119
|
-
prop.
|
|
120
|
-
</Description>
|
|
121
|
-
<div className="flex">
|
|
122
|
-
<CodeBlock>{STRINGS.mentionsSampleCode}</CodeBlock>
|
|
123
|
-
<SampleEditor mentions={SAMPLE_MENTIONS} showImageInMention />
|
|
124
|
-
</div>
|
|
125
|
-
|
|
126
|
-
<Heading type="sub">Support for placeholder</Heading>
|
|
127
|
-
<Description>
|
|
128
|
-
The editor can have placeholder texts for different nodes. These value
|
|
129
|
-
is accepted as <HighlightText>placeholder</HighlightText> prop.
|
|
130
|
-
<ul className="list-disc list-inside">
|
|
131
|
-
<li>
|
|
132
|
-
Value as object: Each type of node can have corresponding
|
|
133
|
-
placeholder, in which case the value should be of type{" "}
|
|
134
|
-
<HighlightText>{"{node_name: placeholder_text}"}</HighlightText>.
|
|
135
|
-
</li>
|
|
136
|
-
<li>
|
|
137
|
-
Value as string: When plain string is provided as value for
|
|
138
|
-
placeholder, all the nodes will be using the same placeholder text
|
|
139
|
-
irrespective of their type in which case the value should be of type{" "}
|
|
140
|
-
</li>
|
|
141
|
-
<li>
|
|
142
|
-
Value as function: the <HighlightText>placeholder</HighlightText>{" "}
|
|
143
|
-
prop can also accepts a function. For each node in the document, the
|
|
144
|
-
function receives node as argument and return the corresponding
|
|
145
|
-
placeholder string. eg:{" "}
|
|
146
|
-
<HighlightText>{"({node}) => placeholder_text"}</HighlightText>
|
|
147
|
-
</li>
|
|
148
|
-
</ul>
|
|
149
|
-
</Description>
|
|
150
|
-
|
|
151
|
-
<div className="flex">
|
|
152
|
-
<CodeBlock>{STRINGS.placeholderSampleCode}</CodeBlock>
|
|
153
|
-
<SampleEditor placeholder="Input text here" />
|
|
154
|
-
</div>
|
|
155
|
-
|
|
156
|
-
<Heading type="sub">Force a title</Heading>
|
|
157
|
-
<Description>
|
|
158
|
-
Neeto editor can be configured to force user to include a document title
|
|
159
|
-
. This can be achieved by providing a truthy value to the{" "}
|
|
160
|
-
<HighlightText>forceTitle</HighlightText> prop. Along with that, inorder
|
|
161
|
-
to show the placeholder text on the title, the{" "}
|
|
162
|
-
<HighlightText>placeholder</HighlightText> prop should also be provided.
|
|
163
|
-
</Description>
|
|
164
|
-
<div className="flex">
|
|
165
|
-
<CodeBlock>{STRINGS.forceTitleSampleCode}</CodeBlock>
|
|
166
|
-
<SampleEditor
|
|
167
|
-
initialValue="Title Text"
|
|
168
|
-
placeholder={{ heading: "Input title here" }}
|
|
169
|
-
forceTitle
|
|
170
|
-
/>
|
|
171
|
-
</div>
|
|
172
|
-
</div>
|
|
173
|
-
);
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
export default Example;
|
|
177
|
-
|
|
178
|
-
const SampleEditor = (props) => {
|
|
179
|
-
const ref = useRef();
|
|
180
|
-
|
|
181
|
-
return (
|
|
182
|
-
<div className="flex-1 mx-3 my-2 h-60">
|
|
183
|
-
<Editor ref={ref} initialValue="Edit Text Content" {...props} />
|
|
184
|
-
</div>
|
|
185
|
-
);
|
|
186
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
|
|
3
|
-
const useOutsideClick = ({ ref, onClick }) => {
|
|
4
|
-
useEffect(() => {
|
|
5
|
-
const listener = ({ target }) => {
|
|
6
|
-
if (!ref.current || !onClick) return;
|
|
7
|
-
// Check if event target is inside reference node
|
|
8
|
-
if (ref.current.contains(target)) return;
|
|
9
|
-
onClick();
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
document.addEventListener("click", listener);
|
|
13
|
-
return () => {
|
|
14
|
-
document.removeEventListener("click", listener);
|
|
15
|
-
};
|
|
16
|
-
}, []);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default useOutsideClick;
|
package/src/index.js
DELETED
package/src/index.scss
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@import "./styles/abstracts/mixins";
|
|
6
|
-
@import "./styles/abstracts/variables";
|
|
7
|
-
@import "./styles/abstracts/neeto-ui-variables";
|
|
8
|
-
|
|
9
|
-
@import "./styles/components/dropdown";
|
|
10
|
-
@import "./styles/components/codeblock";
|
|
11
|
-
@import "./styles/components/editor-variables";
|
|
12
|
-
@import "./styles/components/command-list";
|
|
13
|
-
@import "./styles/components/editor";
|
|
14
|
-
@import "./styles/components/avatar";
|
|
15
|
-
@import "./styles/components/fixed-menu";
|
|
16
|
-
|
|
17
|
-
body {
|
|
18
|
-
margin: 0;
|
|
19
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
|
20
|
-
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
21
|
-
sans-serif;
|
|
22
|
-
-webkit-font-smoothing: antialiased;
|
|
23
|
-
-moz-osx-font-smoothing: grayscale;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
code {
|
|
27
|
-
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
|
28
|
-
monospace;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.ProseMirror {
|
|
32
|
-
@include scrollbars(4px);
|
|
33
|
-
|
|
34
|
-
overflow-y: auto;
|
|
35
|
-
min-height: 150px;
|
|
36
|
-
max-height: 500px;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.ProseMirror:focus {
|
|
40
|
-
outline: none;
|
|
41
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
@mixin scrollbars(
|
|
2
|
-
$size,
|
|
3
|
-
$foreground-color: $neeto-ui-gray-300,
|
|
4
|
-
$background-color: "transparent"
|
|
5
|
-
) {
|
|
6
|
-
// For Google Chrome
|
|
7
|
-
&::-webkit-scrollbar {
|
|
8
|
-
width: $size;
|
|
9
|
-
height: $size;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
&::-webkit-scrollbar-thumb {
|
|
13
|
-
background: $foreground-color;
|
|
14
|
-
border-radius: 50px;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
&::-webkit-scrollbar-track {
|
|
18
|
-
background: $background-color;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
$neeto-ui-white: #ffffff;
|
|
2
|
-
$neeto-ui-black: #1b1f23;
|
|
3
|
-
|
|
4
|
-
$neeto-ui-gray-800: #2f3941;
|
|
5
|
-
$neeto-ui-gray-700: #49545c;
|
|
6
|
-
$neeto-ui-gray-600: #68737d;
|
|
7
|
-
$neeto-ui-gray-500: #87929d;
|
|
8
|
-
$neeto-ui-gray-300: #d8dcde;
|
|
9
|
-
$neeto-ui-gray-200: #e9ebed;
|
|
10
|
-
$neeto-ui-gray-100: #f8f9f9;
|
|
11
|
-
// states
|
|
12
|
-
$neeto-ui-success: #00ba88;
|
|
13
|
-
$neeto-ui-warning: #f3cd82;
|
|
14
|
-
|
|
15
|
-
// Font Sizes
|
|
16
|
-
$neeto-ui-text-xxs: 10px;
|
|
17
|
-
$neeto-ui-text-xs: 12px;
|
|
18
|
-
$neeto-ui-text-sm: 14px;
|
|
19
|
-
$neeto-ui-text-lg: 18px;
|
|
20
|
-
$neeto-ui-text-2xl: 24px;
|
|
21
|
-
|
|
22
|
-
// Shadow
|
|
23
|
-
$box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0px 10px 20px rgba(0, 0, 0, 0.1);
|
|
24
|
-
$neeto-ui-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
25
|
-
0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
26
|
-
|
|
27
|
-
// Border Radius
|
|
28
|
-
$neeto-ui-rounded-sm: 2px;
|
|
29
|
-
$neeto-ui-rounded-full: 999px;
|
|
30
|
-
|
|
31
|
-
// Font Weights
|
|
32
|
-
$neeto-ui-font-normal: 400;
|
|
33
|
-
$neeto-ui-font-semibold: 600;
|
|
34
|
-
|
|
35
|
-
// Transition
|
|
36
|
-
$neeto-ui-transition: all 0.3s ease-in-out;
|