@blocknote/core 0.1.0-alpha.3 → 0.1.1
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/LICENSE +373 -0
- package/README.md +4 -2
- package/dist/blocknote.js +3461 -2429
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +35 -71
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +9 -7
- package/src/BlockNoteExtensions.ts +10 -17
- package/src/BlockNoteTheme.ts +150 -0
- package/src/EditorContent.tsx +2 -1
- package/src/extensions/Blocks/BlockAttributes.ts +12 -0
- package/src/extensions/Blocks/MultipleNodeSelection.ts +87 -0
- package/src/extensions/Blocks/OrderedListPlugin.ts +2 -2
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +8 -2
- package/src/extensions/Blocks/helpers/findBlock.ts +1 -1
- package/src/extensions/Blocks/nodes/Block.module.css +37 -37
- package/src/extensions/Blocks/nodes/Block.ts +89 -45
- package/src/extensions/Blocks/nodes/BlockGroup.ts +19 -2
- package/src/extensions/Blocks/nodes/Content.ts +15 -2
- package/src/extensions/BubbleMenu/BubbleMenuExtension.tsx +10 -2
- package/src/extensions/BubbleMenu/component/BubbleMenu.tsx +122 -98
- package/src/extensions/BubbleMenu/component/LinkToolbarButton.tsx +8 -8
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.tsx +143 -33
- package/src/extensions/DraggableBlocks/components/DragHandle.tsx +15 -21
- package/src/extensions/DraggableBlocks/components/DragHandleMenu.tsx +8 -7
- package/src/extensions/Hyperlinks/HyperlinkMenuPlugin.tsx +31 -66
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenu.tsx +44 -0
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItem.tsx +34 -0
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemIcon.tsx +31 -0
- package/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemInput.tsx +40 -0
- package/src/extensions/Hyperlinks/menus/HoverHyperlinkMenu.tsx +37 -0
- package/src/extensions/Hyperlinks/menus/HyperlinkMenu.tsx +63 -0
- package/src/extensions/SlashMenu/SlashMenuItem.ts +3 -1
- package/src/extensions/SlashMenu/defaultCommands.tsx +4 -4
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +8 -5
- package/src/shared/components/toolbar/Toolbar.tsx +8 -3
- package/src/shared/components/toolbar/ToolbarButton.tsx +57 -0
- package/src/shared/components/toolbar/ToolbarDropdown.tsx +35 -0
- package/src/shared/components/toolbar/ToolbarDropdownItem.tsx +35 -0
- package/src/shared/components/toolbar/ToolbarDropdownTarget.tsx +31 -0
- package/src/shared/plugins/suggestion/SuggestionItem.ts +3 -1
- package/src/shared/plugins/suggestion/{SuggestionListReactRenderer.ts → SuggestionListReactRenderer.tsx} +13 -4
- package/src/shared/plugins/suggestion/components/SuggestionGroup.tsx +6 -93
- package/src/shared/plugins/suggestion/components/SuggestionGroupItem.tsx +82 -0
- package/src/shared/plugins/suggestion/components/SuggestionList.tsx +24 -23
- package/src/useEditor.ts +4 -0
- package/src/utils.ts +12 -0
- package/types/src/BlockNoteExtensions.d.ts +3 -0
- package/types/src/BlockNoteTheme.d.ts +2 -0
- package/types/src/commands/indentation.d.ts +2 -0
- package/types/src/extensions/Blocks/BlockAttributes.d.ts +2 -0
- package/types/src/extensions/Blocks/MultipleNodeSelection.d.ts +24 -0
- package/types/src/extensions/Blocks/nodes/Block.d.ts +1 -1
- package/types/src/extensions/BubbleMenu/component/LinkToolbarButton.d.ts +2 -2
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenu.d.ts +11 -0
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItem.d.ts +13 -0
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemIcon.d.ts +8 -0
- package/types/src/extensions/Hyperlinks/menus/EditHyperlinkMenuItemInput.d.ts +9 -0
- package/types/src/extensions/Hyperlinks/menus/HoverHyperlinkMenu.d.ts +12 -0
- package/types/src/extensions/Hyperlinks/menus/HyperlinkMenu.d.ts +21 -0
- package/types/src/extensions/Hyperlinks/menus/helpers/PanelTextInput.d.ts +39 -0
- package/types/src/extensions/Hyperlinks/menus/helpers/PanelTextInputStyles.d.ts +3 -0
- package/types/src/extensions/Hyperlinks/menus/helpers/ToolbarComponent.d.ts +13 -0
- package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +4 -7
- package/types/src/extensions/TrailingNode/TrailingNodeExtension.d.ts +3 -0
- package/types/src/nodes/ChildgroupNode.d.ts +28 -0
- package/types/src/nodes/patchNodes.d.ts +1 -0
- package/types/src/plugins/TreeViewPlugin/index.d.ts +2 -0
- package/types/src/plugins/animation.d.ts +2 -0
- package/types/src/react/BlockNoteComposer.d.ts +17 -0
- package/types/src/react/BlockNotePlugin.d.ts +1 -0
- package/types/src/react/index.d.ts +3 -0
- package/types/src/react/useBlockNoteSetup.d.ts +2 -0
- package/types/src/registerBlockNote.d.ts +2 -0
- package/types/src/shared/components/toolbar/SimpleToolbarButton.d.ts +2 -3
- package/types/src/shared/components/toolbar/SimpleToolbarDropdown.d.ts +11 -0
- package/types/src/shared/components/toolbar/SimpleToolbarDropdownItem.d.ts +11 -0
- package/types/src/shared/components/toolbar/Toolbar.d.ts +2 -2
- package/types/src/shared/components/toolbar/ToolbarButton.d.ts +15 -0
- package/types/src/shared/components/toolbar/ToolbarDropdown.d.ts +17 -0
- package/types/src/shared/components/toolbar/ToolbarDropdownItem.d.ts +11 -0
- package/types/src/shared/components/toolbar/ToolbarDropdownTarget.d.ts +8 -0
- package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +2 -4
- package/types/src/shared/plugins/suggestion/components/SuggestionGroupItem.d.ts +9 -0
- package/types/src/shared/plugins/suggestion/components/SuggestionList.d.ts +0 -15
- package/types/src/themes/BlockNoteEditorTheme.d.ts +11 -0
- package/types/src/useEditor.d.ts +3 -0
- package/types/src/utils.d.ts +2 -0
- package/src/extensions/Blocks/nodes/README.md +0 -26
- package/src/extensions/BubbleMenu/component/DropdownBlockItem.module.css +0 -13
- package/src/extensions/BubbleMenu/component/DropdownBlockItem.tsx +0 -25
- package/src/extensions/DraggableBlocks/components/DragHandle.module.css +0 -33
- package/src/extensions/DraggableBlocks/components/DragHandleMenu.module.css +0 -10
- package/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.tsx +0 -59
- package/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.tsx +0 -72
- package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.tsx +0 -173
- package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.ts +0 -36
- package/src/extensions/Hyperlinks/menus/atlaskit/README.md +0 -1
- package/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.tsx +0 -61
- package/src/extensions/helpers/formatKeyboardShortcut.ts +0 -9
- package/src/lib/atlaskit/browser.ts +0 -47
- package/src/shared/components/toolbar/SimpleToolbarButton.module.css +0 -13
- package/src/shared/components/toolbar/SimpleToolbarButton.tsx +0 -56
- package/src/shared/components/toolbar/Toolbar.module.css +0 -10
- package/src/shared/components/toolbar/ToolbarSeparator.module.css +0 -13
- package/src/shared/components/toolbar/ToolbarSeparator.tsx +0 -7
- package/src/shared/plugins/suggestion/components/SuggestionGroup.module.css +0 -45
- package/src/shared/plugins/suggestion/components/SuggestionList.module.css +0 -10
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocknote/core",
|
|
3
|
+
"homepage": "https://github.com/yousefed/blocknote",
|
|
3
4
|
"private": false,
|
|
4
|
-
"license": "
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"license": "MPL-2.0",
|
|
6
|
+
"version": "0.1.1",
|
|
6
7
|
"files": [
|
|
7
8
|
"dist",
|
|
8
9
|
"types",
|
|
@@ -44,10 +45,10 @@
|
|
|
44
45
|
"lint": "eslint src --max-warnings 0"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
48
|
+
"@emotion/cache": "^11.10.5",
|
|
49
|
+
"@emotion/serialize": "^1.1.1",
|
|
50
|
+
"@emotion/utils": "^1.2.0",
|
|
51
|
+
"@mantine/core": "^5.6.1",
|
|
51
52
|
"@tippyjs/react": "^4.2.6",
|
|
52
53
|
"@tiptap/core": "^2.0.0-beta.182",
|
|
53
54
|
"@tiptap/extension-bold": "^2.0.0-beta.28",
|
|
@@ -88,6 +89,7 @@
|
|
|
88
89
|
"@types/uuid": "^8.3.4",
|
|
89
90
|
"eslint": "^8.10.0",
|
|
90
91
|
"eslint-config-react-app": "^7.0.0",
|
|
92
|
+
"prettier": "^2.7.1",
|
|
91
93
|
"typescript": "^4.5.4",
|
|
92
94
|
"vite": "^3.0.5",
|
|
93
95
|
"vite-plugin-eslint": "^1.7.0"
|
|
@@ -105,5 +107,5 @@
|
|
|
105
107
|
"access": "public",
|
|
106
108
|
"registry": "https://registry.npmjs.org/"
|
|
107
109
|
},
|
|
108
|
-
"gitHead": "
|
|
110
|
+
"gitHead": "1772342279fad8724893d91773614546e8a2ff67"
|
|
109
111
|
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { Extensions, extensions } from "@tiptap/core";
|
|
2
2
|
|
|
3
|
+
import { Node } from "@tiptap/core";
|
|
3
4
|
import Bold from "@tiptap/extension-bold";
|
|
4
5
|
import Code from "@tiptap/extension-code";
|
|
5
6
|
import DropCursor from "@tiptap/extension-dropcursor";
|
|
6
7
|
import GapCursor from "@tiptap/extension-gapcursor";
|
|
7
8
|
import HardBreak from "@tiptap/extension-hard-break";
|
|
8
|
-
import Italic from "@tiptap/extension-italic";
|
|
9
|
-
import Underline from "@tiptap/extension-underline";
|
|
10
|
-
// import Placeholder from "@tiptap/extension-placeholder";
|
|
11
|
-
import { Node } from "@tiptap/core";
|
|
12
9
|
import { History } from "@tiptap/extension-history";
|
|
10
|
+
import Italic from "@tiptap/extension-italic";
|
|
13
11
|
import Strike from "@tiptap/extension-strike";
|
|
14
12
|
import Text from "@tiptap/extension-text";
|
|
13
|
+
import Underline from "@tiptap/extension-underline";
|
|
15
14
|
import { blocks } from "./extensions/Blocks";
|
|
16
15
|
import blockStyles from "./extensions/Blocks/nodes/Block.module.css";
|
|
17
16
|
import { BubbleMenuExtension } from "./extensions/BubbleMenu/BubbleMenuExtension";
|
|
@@ -22,12 +21,16 @@ import { Placeholder } from "./extensions/Placeholder/PlaceholderExtension";
|
|
|
22
21
|
import SlashMenuExtension from "./extensions/SlashMenu";
|
|
23
22
|
import { TrailingNode } from "./extensions/TrailingNode/TrailingNodeExtension";
|
|
24
23
|
import UniqueID from "./extensions/UniqueID/UniqueID";
|
|
24
|
+
|
|
25
25
|
export const Document = Node.create({
|
|
26
26
|
name: "doc",
|
|
27
27
|
topNode: true,
|
|
28
28
|
content: "block+",
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Get all the Tiptap extensions BlockNote is configured with by default
|
|
33
|
+
*/
|
|
31
34
|
export const getBlockNoteExtensions = () => {
|
|
32
35
|
const ret: Extensions = [
|
|
33
36
|
extensions.ClipboardTextSerializer,
|
|
@@ -48,7 +51,7 @@ export const getBlockNoteExtensions = () => {
|
|
|
48
51
|
showOnlyCurrent: false,
|
|
49
52
|
}),
|
|
50
53
|
UniqueID.configure({
|
|
51
|
-
types: ["
|
|
54
|
+
types: ["block"],
|
|
52
55
|
}),
|
|
53
56
|
HardBreak,
|
|
54
57
|
// Comments,
|
|
@@ -64,26 +67,16 @@ export const getBlockNoteExtensions = () => {
|
|
|
64
67
|
Underline,
|
|
65
68
|
HyperlinkMark,
|
|
66
69
|
FixedParagraph,
|
|
70
|
+
|
|
67
71
|
// custom blocks:
|
|
68
72
|
...blocks,
|
|
69
73
|
DraggableBlocksExtension,
|
|
70
74
|
DropCursor.configure({ width: 5, color: "#ddeeff" }),
|
|
71
75
|
BubbleMenuExtension,
|
|
72
76
|
History,
|
|
73
|
-
SlashMenuExtension,
|
|
74
77
|
// This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),
|
|
75
78
|
// should be handled before Enter handlers in other components like splitListItem
|
|
76
|
-
|
|
77
|
-
// // Extra commands can be registered here
|
|
78
|
-
// commands: {},
|
|
79
|
-
// }),
|
|
80
|
-
// MentionsExtension.configure({
|
|
81
|
-
// providers: {
|
|
82
|
-
// people: (query) => {
|
|
83
|
-
// return PEOPLE.filter((mention) => mention.match(query));
|
|
84
|
-
// },
|
|
85
|
-
// },
|
|
86
|
-
// }),
|
|
79
|
+
SlashMenuExtension,
|
|
87
80
|
TrailingNode,
|
|
88
81
|
];
|
|
89
82
|
return ret;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { MantineThemeOverride } from "@mantine/core";
|
|
2
|
+
|
|
3
|
+
export const BlockNoteTheme: MantineThemeOverride = {
|
|
4
|
+
activeStyles: {
|
|
5
|
+
// Removes button press effect.
|
|
6
|
+
transform: "none",
|
|
7
|
+
},
|
|
8
|
+
colorScheme: "light",
|
|
9
|
+
colors: {
|
|
10
|
+
brandFinal: [
|
|
11
|
+
"#F6F6F8",
|
|
12
|
+
"#ECEDF0",
|
|
13
|
+
"#DFE1E6",
|
|
14
|
+
"#C2C7D0",
|
|
15
|
+
"#A6ADBA",
|
|
16
|
+
"#8993A4",
|
|
17
|
+
"#6D798F",
|
|
18
|
+
"#505F79",
|
|
19
|
+
"#344563",
|
|
20
|
+
"#172B4D",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
components: {
|
|
24
|
+
Menu: {
|
|
25
|
+
styles: (theme) => ({
|
|
26
|
+
dropdown: {
|
|
27
|
+
backgroundColor: "white",
|
|
28
|
+
boxShadow: `0px 4px 8px ${theme.colors.brandFinal[2]}, 0px 0px 1px ${theme.colors.brandFinal[2]}`,
|
|
29
|
+
border: `1px solid ${theme.colors.brandFinal[1]}`,
|
|
30
|
+
borderRadius: "6px",
|
|
31
|
+
padding: "2px",
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
DragHandleMenu: {
|
|
36
|
+
styles: (theme) => ({
|
|
37
|
+
root: {
|
|
38
|
+
".mantine-Menu-item": {
|
|
39
|
+
color: theme.colors.brandFinal,
|
|
40
|
+
fontSize: "12px",
|
|
41
|
+
height: "34px",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
EditHyperlinkMenu: {
|
|
47
|
+
styles: (theme) => ({
|
|
48
|
+
root: {
|
|
49
|
+
backgroundColor: "white",
|
|
50
|
+
boxShadow: `0px 4px 8px ${theme.colors.brandFinal[2]}, 0px 0px 1px ${theme.colors.brandFinal[2]}`,
|
|
51
|
+
border: `1px solid ${theme.colors.brandFinal[1]}`,
|
|
52
|
+
borderRadius: "6px",
|
|
53
|
+
gap: "4px",
|
|
54
|
+
minWidth: "145px",
|
|
55
|
+
padding: "2px",
|
|
56
|
+
// Row
|
|
57
|
+
".mantine-Group-root": {
|
|
58
|
+
flexWrap: "nowrap",
|
|
59
|
+
gap: "8px",
|
|
60
|
+
paddingInline: "6px",
|
|
61
|
+
// Row icon
|
|
62
|
+
".mantine-Container-root": {
|
|
63
|
+
color: theme.colors.brandFinal,
|
|
64
|
+
display: "flex",
|
|
65
|
+
justifyContent: "center",
|
|
66
|
+
padding: "0",
|
|
67
|
+
width: "fit-content",
|
|
68
|
+
},
|
|
69
|
+
// Row input field
|
|
70
|
+
".mantine-TextInput-root": {
|
|
71
|
+
background: "transparent",
|
|
72
|
+
width: "300px",
|
|
73
|
+
".mantine-TextInput-wrapper": {
|
|
74
|
+
".mantine-TextInput-input": {
|
|
75
|
+
fontSize: "12px",
|
|
76
|
+
border: 0,
|
|
77
|
+
padding: 0,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
84
|
+
},
|
|
85
|
+
Toolbar: {
|
|
86
|
+
styles: (theme) => ({
|
|
87
|
+
root: {
|
|
88
|
+
backgroundColor: "white",
|
|
89
|
+
boxShadow: `0px 4px 8px ${theme.colors.brandFinal[2]}, 0px 0px 1px ${theme.colors.brandFinal[2]}`,
|
|
90
|
+
border: `1px solid ${theme.colors.brandFinal[1]}`,
|
|
91
|
+
borderRadius: "6px",
|
|
92
|
+
flexWrap: "nowrap",
|
|
93
|
+
gap: "2px",
|
|
94
|
+
padding: "2px",
|
|
95
|
+
width: "fit-content",
|
|
96
|
+
// Button (including dropdown target)
|
|
97
|
+
".mantine-UnstyledButton-root": {
|
|
98
|
+
borderRadius: "4px",
|
|
99
|
+
},
|
|
100
|
+
// Dropdown
|
|
101
|
+
".mantine-Menu-dropdown": {
|
|
102
|
+
// Dropdown item
|
|
103
|
+
".mantine-Menu-item": {
|
|
104
|
+
color: theme.colors.brandFinal,
|
|
105
|
+
fontSize: "12px",
|
|
106
|
+
height: "34px",
|
|
107
|
+
".mantine-Menu-itemRightSection": {
|
|
108
|
+
paddingLeft: "5px",
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
},
|
|
115
|
+
SuggestionList: {
|
|
116
|
+
styles: (theme) => ({
|
|
117
|
+
root: {
|
|
118
|
+
// ...theme.other.defaultMenuStyles(theme),
|
|
119
|
+
".mantine-Menu-item": {
|
|
120
|
+
// Icon
|
|
121
|
+
".mantine-Menu-itemIcon": {
|
|
122
|
+
padding: "8px",
|
|
123
|
+
border: `1px solid ${theme.colors.brandFinal[2]}`,
|
|
124
|
+
backgroundColor: theme.colors.brandFinal[0],
|
|
125
|
+
borderRadius: "4px",
|
|
126
|
+
color: theme.colors.brandFinal,
|
|
127
|
+
},
|
|
128
|
+
// Text
|
|
129
|
+
".mantine-Menu-itemLabel": {
|
|
130
|
+
color: theme.colors.brandFinal,
|
|
131
|
+
paddingRight: "16px",
|
|
132
|
+
".mantine-Stack-root": {
|
|
133
|
+
gap: "0",
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
// Badge (keyboard shortcut)
|
|
137
|
+
".mantine-Menu-itemRightSection": {
|
|
138
|
+
".mantine-Badge-root": {
|
|
139
|
+
border: `1px solid ${theme.colors.brandFinal[2]}`,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
fontFamily: "Inter",
|
|
148
|
+
primaryColor: "brandFinal",
|
|
149
|
+
primaryShade: 9,
|
|
150
|
+
};
|
package/src/EditorContent.tsx
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
// BlockNote uses a similar pattern as Tiptap, so for now we can just export that
|
|
2
|
+
export { EditorContent } from "@tiptap/react";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Object containing all possible block attributes.
|
|
2
|
+
const BlockAttributes: Record<string, string> = {
|
|
3
|
+
listType: "data-list-type",
|
|
4
|
+
blockColor: "data-block-color",
|
|
5
|
+
blockStyle: "data-block-style",
|
|
6
|
+
headingType: "data-heading-type",
|
|
7
|
+
id: "data-id",
|
|
8
|
+
depth: "data-depth",
|
|
9
|
+
depthChange: "data-depth-change",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default BlockAttributes;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Selection } from "prosemirror-state";
|
|
2
|
+
import { Fragment, Node, ResolvedPos, Slice } from "prosemirror-model";
|
|
3
|
+
import { Mappable } from "prosemirror-transform";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* This class represents an editor selection which spans multiple nodes/blocks. It's currently only used to allow users
|
|
7
|
+
* to drag multiple blocks at the same time. Expects the selection anchor and head to be between nodes, i.e. just before
|
|
8
|
+
* the first target node and just after the last, and that anchor and head are at the same nesting level.
|
|
9
|
+
*
|
|
10
|
+
* Partially based on ProseMirror's NodeSelection implementation:
|
|
11
|
+
* (https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.ts)
|
|
12
|
+
* MultipleNodeSelection differs from NodeSelection in the following ways:
|
|
13
|
+
* 1. Stores which nodes are included in the selection instead of just a single node.
|
|
14
|
+
* 2. Already expects the selection to start just before the first target node and ends just after the last, while a
|
|
15
|
+
* NodeSelection automatically sets both anchor and head to just before the single target node.
|
|
16
|
+
*/
|
|
17
|
+
export class MultipleNodeSelection extends Selection {
|
|
18
|
+
nodes: Array<Node>;
|
|
19
|
+
|
|
20
|
+
constructor($anchor: ResolvedPos, $head: ResolvedPos) {
|
|
21
|
+
super($anchor, $head);
|
|
22
|
+
|
|
23
|
+
// Parent is at the same nesting level as anchor/head since they are just before/ just after target nodes.
|
|
24
|
+
const parentNode = $anchor.node();
|
|
25
|
+
|
|
26
|
+
this.nodes = [];
|
|
27
|
+
$anchor.doc.nodesBetween($anchor.pos, $head.pos, (node, _pos, parent) => {
|
|
28
|
+
if (parent !== null && parent.eq(parentNode)) {
|
|
29
|
+
this.nodes.push(node);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static create(doc: Node, from: number, to = from): MultipleNodeSelection {
|
|
37
|
+
return new MultipleNodeSelection(doc.resolve(from), doc.resolve(to));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
content(): Slice {
|
|
41
|
+
return new Slice(Fragment.from(this.nodes), 0, 0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
eq(selection: Selection): boolean {
|
|
45
|
+
if (!(selection instanceof MultipleNodeSelection)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this.nodes.length !== selection.nodes.length) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (this.from !== selection.from || this.to !== selection.to) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (let i = 0; i < this.nodes.length; i++) {
|
|
58
|
+
if (!this.nodes[i].eq(selection.nodes[i])) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
map(doc: Node, mapping: Mappable): Selection {
|
|
67
|
+
let fromResult = mapping.mapResult(this.from);
|
|
68
|
+
let toResult = mapping.mapResult(this.to);
|
|
69
|
+
|
|
70
|
+
if (toResult.deleted) {
|
|
71
|
+
return Selection.near(doc.resolve(fromResult.pos));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (fromResult.deleted) {
|
|
75
|
+
return Selection.near(doc.resolve(toResult.pos));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return new MultipleNodeSelection(
|
|
79
|
+
doc.resolve(fromResult.pos),
|
|
80
|
+
doc.resolve(toResult.pos)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
toJSON(): any {
|
|
85
|
+
return { type: "node", anchor: this.anchor, head: this.head };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -11,12 +11,12 @@ export const OrderedListPlugin = () => {
|
|
|
11
11
|
let count = 1;
|
|
12
12
|
let skip = 0;
|
|
13
13
|
newState.doc.descendants((node, pos) => {
|
|
14
|
-
if (node.type.name === "
|
|
14
|
+
if (node.type.name === "block" && !node.attrs.listType) {
|
|
15
15
|
count = 1;
|
|
16
16
|
}
|
|
17
17
|
if (
|
|
18
18
|
skip === 0 &&
|
|
19
|
-
node.type.name === "
|
|
19
|
+
node.type.name === "block" &&
|
|
20
20
|
node.attrs.listType === "oli"
|
|
21
21
|
) {
|
|
22
22
|
skip = node.content.childCount;
|
|
@@ -5,9 +5,14 @@ import {
|
|
|
5
5
|
} from "@tiptap/core";
|
|
6
6
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
7
7
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
8
|
+
import BlockAttributes from "./BlockAttributes";
|
|
8
9
|
|
|
9
10
|
const PLUGIN_KEY = new PluginKey(`previous-blocks`);
|
|
10
11
|
|
|
12
|
+
// Inserts "prev-" string into an HTML attribute name with a "data-" prefix, e.g. "data-depth" -> "data-prev-depth".
|
|
13
|
+
// Assumes "data-" prefix is in the attribute name.
|
|
14
|
+
const insertPrev = (attr: string) => attr.slice(0, 5) + "prev-" + attr.slice(5);
|
|
15
|
+
|
|
11
16
|
/**
|
|
12
17
|
* This plugin tracks transformation of Block node attributes, so we can support CSS transitions.
|
|
13
18
|
*
|
|
@@ -129,8 +134,9 @@ export const PreviousBlockTypePlugin = () => {
|
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
const decorationAttributes: any = {};
|
|
132
|
-
for (let [
|
|
133
|
-
decorationAttributes[
|
|
137
|
+
for (let [nodeAttr, val] of Object.entries(prevAttrs)) {
|
|
138
|
+
decorationAttributes[insertPrev(BlockAttributes[nodeAttr])] =
|
|
139
|
+
val || "none";
|
|
134
140
|
}
|
|
135
141
|
const decoration = Decoration.node(pos, pos + node.nodeSize, {
|
|
136
142
|
...decorationAttributes,
|
|
@@ -40,7 +40,7 @@ NESTED BLOCKS
|
|
|
40
40
|
position: relative;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
.blockGroup .blockGroup > .blockOuter:not([data-prev-
|
|
43
|
+
.blockGroup .blockGroup > .blockOuter:not([data-prev-depth-changed])::before {
|
|
44
44
|
content: " ";
|
|
45
45
|
display: inline;
|
|
46
46
|
border-left: 1px solid #ccc;
|
|
@@ -50,71 +50,71 @@ NESTED BLOCKS
|
|
|
50
50
|
transition: all 0.2s 0.1s;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
.blockGroup .blockGroup > .blockOuter[data-prev-
|
|
53
|
+
.blockGroup .blockGroup > .blockOuter[data-prev-depth-change="-2"]::before {
|
|
54
54
|
height: 0;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/* NESTED BLOCK ANIMATIONS */
|
|
58
58
|
|
|
59
|
-
[data-prev-
|
|
59
|
+
[data-prev-depth-change="1"] {
|
|
60
60
|
--x: 1;
|
|
61
61
|
}
|
|
62
|
-
[data-prev-
|
|
62
|
+
[data-prev-depth-change="2"] {
|
|
63
63
|
--x: 2;
|
|
64
64
|
}
|
|
65
|
-
[data-prev-
|
|
65
|
+
[data-prev-depth-change="3"] {
|
|
66
66
|
--x: 3;
|
|
67
67
|
}
|
|
68
|
-
[data-prev-
|
|
68
|
+
[data-prev-depth-change="4"] {
|
|
69
69
|
--x: 4;
|
|
70
70
|
}
|
|
71
|
-
[data-prev-
|
|
71
|
+
[data-prev-depth-change="5"] {
|
|
72
72
|
--x: 5;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
[data-prev-
|
|
75
|
+
[data-prev-depth-change="-1"] {
|
|
76
76
|
--x: -1;
|
|
77
77
|
}
|
|
78
|
-
[data-prev-
|
|
78
|
+
[data-prev-depth-change="-2"] {
|
|
79
79
|
--x: -2;
|
|
80
80
|
}
|
|
81
|
-
[data-prev-
|
|
81
|
+
[data-prev-depth-change="-3"] {
|
|
82
82
|
--x: -3;
|
|
83
83
|
}
|
|
84
|
-
[data-prev-
|
|
84
|
+
[data-prev-depth-change="-4"] {
|
|
85
85
|
--x: -4;
|
|
86
86
|
}
|
|
87
|
-
[data-prev-
|
|
87
|
+
[data-prev-depth-change="-5"] {
|
|
88
88
|
--x: -5;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
.blockOuter[data-prev-
|
|
91
|
+
.blockOuter[data-prev-depth-change] {
|
|
92
92
|
margin-left: calc(10px * var(--x));
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
.blockOuter[data-prev-
|
|
95
|
+
.blockOuter[data-prev-depth-change] .blockOuter[data-prev-depth-change] {
|
|
96
96
|
margin-left: 0;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
/* HEADINGS*/
|
|
100
|
-
.blockOuter[data-prev-
|
|
101
|
-
.blockOuter[data-
|
|
100
|
+
.blockOuter[data-prev-heading-type="1"] > .block > div:first-child,
|
|
101
|
+
.blockOuter[data-heading-type="1"]:not([data-prev-heading-type])
|
|
102
102
|
> .block
|
|
103
103
|
> div:first-child {
|
|
104
104
|
font-size: 3em;
|
|
105
105
|
font-weight: bold;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
.blockOuter[data-prev-
|
|
109
|
-
.blockOuter[data-
|
|
108
|
+
.blockOuter[data-prev-heading-type="2"] > .block > div:first-child,
|
|
109
|
+
.blockOuter[data-heading-type="2"]:not([data-prev-heading-type])
|
|
110
110
|
> .block
|
|
111
111
|
> div:first-child {
|
|
112
112
|
font-size: 2em;
|
|
113
113
|
font-weight: bold;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
.blockOuter[data-prev-
|
|
117
|
-
.blockOuter[data-
|
|
116
|
+
.blockOuter[data-prev-heading-type="3"] > .block > div:first-child,
|
|
117
|
+
.blockOuter[data-heading-type="3"]:not([data-prev-heading-type])
|
|
118
118
|
> .block
|
|
119
119
|
> div:first-child {
|
|
120
120
|
font-size: 1.3em;
|
|
@@ -129,8 +129,8 @@ NESTED BLOCKS
|
|
|
129
129
|
margin-left: 0px;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
.blockOuter[data-prev-
|
|
133
|
-
.blockOuter[data-
|
|
132
|
+
.blockOuter[data-prev-list-type="oli"] > .block > div:first-child::before,
|
|
133
|
+
.blockOuter[data-list-type="oli"]:not([data-prev-list-type])
|
|
134
134
|
> .block
|
|
135
135
|
> div:first-child::before {
|
|
136
136
|
content: attr(data-position);
|
|
@@ -138,8 +138,8 @@ NESTED BLOCKS
|
|
|
138
138
|
padding-left: 0px;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
.blockOuter[data-prev-
|
|
142
|
-
.blockOuter[data-
|
|
141
|
+
.blockOuter[data-prev-list-type="li"] > .block > div:first-child::before,
|
|
142
|
+
.blockOuter[data-list-type="li"]:not([data-prev-list-type])
|
|
143
143
|
> .block
|
|
144
144
|
> div:first-child::before {
|
|
145
145
|
content: "•";
|
|
@@ -151,16 +151,16 @@ NESTED BLOCKS
|
|
|
151
151
|
/* margin-left: 0.2em; */
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
.blockOuter[data-
|
|
154
|
+
.blockOuter[data-list-type="li"]
|
|
155
155
|
> .block
|
|
156
156
|
> .blockGroup
|
|
157
|
-
> .blockOuter[data-prev-
|
|
157
|
+
> .blockOuter[data-prev-list-type="li"]
|
|
158
158
|
> .block
|
|
159
159
|
> div:first-child::before,
|
|
160
|
-
.blockOuter[data-
|
|
160
|
+
.blockOuter[data-list-type="li"]
|
|
161
161
|
> .block
|
|
162
162
|
> .blockGroup
|
|
163
|
-
> .blockOuter[data-
|
|
163
|
+
> .blockOuter[data-list-type="li"]:not([data-prev-list-type])
|
|
164
164
|
> .block
|
|
165
165
|
> div:first-child::before {
|
|
166
166
|
content: "◦";
|
|
@@ -168,22 +168,22 @@ NESTED BLOCKS
|
|
|
168
168
|
font-family: arial;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
.blockOuter[data-
|
|
171
|
+
.blockOuter[data-list-type="li"]
|
|
172
172
|
> .block
|
|
173
173
|
> .blockGroup
|
|
174
|
-
> .blockOuter[data-
|
|
174
|
+
> .blockOuter[data-list-type="li"]
|
|
175
175
|
> .block
|
|
176
176
|
> .blockGroup
|
|
177
|
-
.blockOuter[data-prev-
|
|
177
|
+
.blockOuter[data-prev-list-type="li"]
|
|
178
178
|
> .block
|
|
179
179
|
> div:first-child::before,
|
|
180
|
-
.blockOuter[data-
|
|
180
|
+
.blockOuter[data-list-type="li"]
|
|
181
181
|
> .block
|
|
182
182
|
> .blockGroup
|
|
183
|
-
> .blockOuter[data-
|
|
183
|
+
> .blockOuter[data-list-type="li"]
|
|
184
184
|
> .block
|
|
185
185
|
> .blockGroup
|
|
186
|
-
.blockOuter[data-
|
|
186
|
+
.blockOuter[data-list-type="li"]:not([data-prev-list-type])
|
|
187
187
|
> .block
|
|
188
188
|
> div:first-child::before {
|
|
189
189
|
content: "▪";
|
|
@@ -217,10 +217,10 @@ NESTED BLOCKS
|
|
|
217
217
|
content: "Type to filter";
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
[data-
|
|
220
|
+
[data-heading-type] > .blockContent.isEmpty div::before {
|
|
221
221
|
content: "Heading";
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
[data-
|
|
224
|
+
[data-list-type] > .blockContent.isEmpty div::before {
|
|
225
225
|
content: "List";
|
|
226
|
-
}
|
|
226
|
+
}
|