@blocknote/core 0.1.0-alpha.3
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/README.md +99 -0
- package/dist/blocknote.js +4485 -0
- package/dist/blocknote.js.map +1 -0
- package/dist/blocknote.umd.cjs +90 -0
- package/dist/blocknote.umd.cjs.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +109 -0
- package/src/BlockNoteExtensions.ts +90 -0
- package/src/EditorContent.tsx +1 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-100.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-100.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-200.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-200.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-300.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-300.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-500.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-500.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-600.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-600.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-700.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-700.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-800.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-800.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-900.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-900.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-regular.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-regular.woff2 +0 -0
- package/src/editor.module.css +3 -0
- package/src/extensions/Blocks/OrderedListPlugin.ts +46 -0
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +146 -0
- package/src/extensions/Blocks/commands/joinBackward.ts +274 -0
- package/src/extensions/Blocks/helpers/findBlock.ts +3 -0
- package/src/extensions/Blocks/helpers/setBlockHeading.ts +30 -0
- package/src/extensions/Blocks/index.ts +15 -0
- package/src/extensions/Blocks/nodes/Block.module.css +226 -0
- package/src/extensions/Blocks/nodes/Block.ts +390 -0
- package/src/extensions/Blocks/nodes/BlockGroup.ts +28 -0
- package/src/extensions/Blocks/nodes/Content.ts +50 -0
- package/src/extensions/Blocks/nodes/README.md +26 -0
- package/src/extensions/Blocks/rule.ts +48 -0
- package/src/extensions/BubbleMenu/BubbleMenuExtension.tsx +28 -0
- package/src/extensions/BubbleMenu/BubbleMenuPlugin.ts +245 -0
- package/src/extensions/BubbleMenu/component/BubbleMenu.tsx +216 -0
- package/src/extensions/BubbleMenu/component/DropdownBlockItem.module.css +13 -0
- package/src/extensions/BubbleMenu/component/DropdownBlockItem.tsx +25 -0
- package/src/extensions/BubbleMenu/component/LinkToolbarButton.tsx +67 -0
- package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +15 -0
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.tsx +266 -0
- package/src/extensions/DraggableBlocks/components/DragHandle.module.css +33 -0
- package/src/extensions/DraggableBlocks/components/DragHandle.tsx +108 -0
- package/src/extensions/DraggableBlocks/components/DragHandleMenu.module.css +10 -0
- package/src/extensions/DraggableBlocks/components/DragHandleMenu.tsx +18 -0
- package/src/extensions/Hyperlinks/HyperlinkMark.tsx +16 -0
- package/src/extensions/Hyperlinks/HyperlinkMenuPlugin.tsx +200 -0
- package/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.tsx +59 -0
- package/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.tsx +72 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.tsx +173 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.ts +36 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/README.md +1 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.tsx +61 -0
- package/src/extensions/Paragraph/FixedParagraph.ts +12 -0
- package/src/extensions/Placeholder/PlaceholderExtension.ts +127 -0
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +43 -0
- package/src/extensions/SlashMenu/SlashMenuItem.ts +56 -0
- package/src/extensions/SlashMenu/defaultCommands.tsx +229 -0
- package/src/extensions/SlashMenu/index.ts +11 -0
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +70 -0
- package/src/extensions/UniqueID/UniqueID.ts +281 -0
- package/src/extensions/helpers/formatKeyboardShortcut.ts +9 -0
- package/src/fonts-inter.css +94 -0
- package/src/globals.css +28 -0
- package/src/index.ts +5 -0
- package/src/lib/atlaskit/browser.ts +47 -0
- package/src/root.module.css +19 -0
- package/src/shared/components/toolbar/SimpleToolbarButton.module.css +13 -0
- package/src/shared/components/toolbar/SimpleToolbarButton.tsx +56 -0
- package/src/shared/components/toolbar/Toolbar.module.css +10 -0
- package/src/shared/components/toolbar/Toolbar.tsx +5 -0
- package/src/shared/components/toolbar/ToolbarSeparator.module.css +13 -0
- package/src/shared/components/toolbar/ToolbarSeparator.tsx +7 -0
- package/src/shared/components/tooltip/TooltipContent.module.css +15 -0
- package/src/shared/components/tooltip/TooltipContent.tsx +23 -0
- package/src/shared/hooks/useEditorForceUpdate.tsx +30 -0
- package/src/shared/plugins/suggestion/SuggestionItem.ts +31 -0
- package/src/shared/plugins/suggestion/SuggestionListReactRenderer.ts +227 -0
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +365 -0
- package/src/shared/plugins/suggestion/components/SuggestionGroup.module.css +45 -0
- package/src/shared/plugins/suggestion/components/SuggestionGroup.tsx +134 -0
- package/src/shared/plugins/suggestion/components/SuggestionList.module.css +10 -0
- package/src/shared/plugins/suggestion/components/SuggestionList.tsx +91 -0
- package/src/style.css +7 -0
- package/src/useEditor.ts +47 -0
- package/src/vite-env.d.ts +1 -0
- package/types/src/BlockNoteExtensions.d.ts +4 -0
- package/types/src/EditorContent.d.ts +1 -0
- package/types/src/extensions/Blocks/OrderedListPlugin.d.ts +2 -0
- package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +13 -0
- package/types/src/extensions/Blocks/commands/joinBackward.d.ts +14 -0
- package/types/src/extensions/Blocks/helpers/findBlock.d.ts +6 -0
- package/types/src/extensions/Blocks/helpers/setBlockHeading.d.ts +5 -0
- package/types/src/extensions/Blocks/index.d.ts +1 -0
- package/types/src/extensions/Blocks/nodes/Block.d.ts +32 -0
- package/types/src/extensions/Blocks/nodes/BlockGroup.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/Content.d.ts +5 -0
- package/types/src/extensions/Blocks/rule.d.ts +16 -0
- package/types/src/extensions/BubbleMenu/BubbleMenuExtension.d.ts +5 -0
- package/types/src/extensions/BubbleMenu/BubbleMenuPlugin.d.ts +46 -0
- package/types/src/extensions/BubbleMenu/component/BubbleMenu.d.ts +5 -0
- package/types/src/extensions/BubbleMenu/component/DropdownBlockItem.d.ts +10 -0
- package/types/src/extensions/BubbleMenu/component/LinkToolbarButton.d.ts +11 -0
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +7 -0
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +18 -0
- package/types/src/extensions/DraggableBlocks/components/DragHandle.d.ts +12 -0
- package/types/src/extensions/DraggableBlocks/components/DragHandleMenu.d.ts +6 -0
- package/types/src/extensions/Hyperlinks/HyperlinkMark.d.ts +7 -0
- package/types/src/extensions/Hyperlinks/HyperlinkMenuPlugin.d.ts +2 -0
- package/types/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.d.ts +12 -0
- package/types/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.d.ts +10 -0
- package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.d.ts +39 -0
- package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.d.ts +1 -0
- package/types/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.d.ts +11 -0
- package/types/src/extensions/Paragraph/FixedParagraph.d.ts +1 -0
- package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +25 -0
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +10 -0
- package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +43 -0
- package/types/src/extensions/SlashMenu/defaultCommands.d.ts +8 -0
- package/types/src/extensions/SlashMenu/index.d.ts +5 -0
- package/types/src/extensions/TrailingNode/TrailingNodeExtension.d.ts +10 -0
- package/types/src/extensions/UniqueID/UniqueID.d.ts +3 -0
- package/types/src/extensions/helpers/formatKeyboardShortcut.d.ts +1 -0
- package/types/src/index.d.ts +4 -0
- package/types/src/lib/atlaskit/browser.d.ts +12 -0
- package/types/src/shared/components/toolbar/SimpleToolbarButton.d.ts +16 -0
- package/types/src/shared/components/toolbar/Toolbar.d.ts +4 -0
- package/types/src/shared/components/toolbar/ToolbarSeparator.d.ts +2 -0
- package/types/src/shared/components/tooltip/TooltipContent.d.ts +15 -0
- package/types/src/shared/hooks/useEditorForceUpdate.d.ts +2 -0
- package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +29 -0
- package/types/src/shared/plugins/suggestion/SuggestionListReactRenderer.d.ts +71 -0
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +74 -0
- package/types/src/shared/plugins/suggestion/components/SuggestionGroup.d.ts +23 -0
- package/types/src/shared/plugins/suggestion/components/SuggestionList.d.ts +26 -0
- package/types/src/useEditor.d.ts +8 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { Fragment, Node, ResolvedPos, Slice } from "prosemirror-model";
|
|
2
|
+
import { EditorState, NodeSelection, Selection } from "prosemirror-state";
|
|
3
|
+
import {
|
|
4
|
+
canJoin,
|
|
5
|
+
liftTarget,
|
|
6
|
+
ReplaceAroundStep,
|
|
7
|
+
replaceStep,
|
|
8
|
+
} from "prosemirror-transform";
|
|
9
|
+
|
|
10
|
+
import { Command, TextSelection, Transaction } from "prosemirror-state";
|
|
11
|
+
import { ReplaceStep } from "prosemirror-transform";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Code taken from https://github.com/ProseMirror/prosemirror-commands/blob/97a8cb5fac25e697d4693ce343e2e3b020a7fa2f/src/commands.ts
|
|
15
|
+
* Reason for modification: https://github.com/YousefED/BlockNote/pull/11
|
|
16
|
+
*
|
|
17
|
+
* BlockA
|
|
18
|
+
* BlockB
|
|
19
|
+
* Order of behavior has been switched to make first and second blocks content
|
|
20
|
+
* merge before trying to add second block as child of first
|
|
21
|
+
*
|
|
22
|
+
* behavior responsible for joining BlockB as A child of BlockA moved to (line 379 - 393 original file) after
|
|
23
|
+
* behavior responsible for joining content of BlockA and BlockB (line 402 - 422 original file)
|
|
24
|
+
*/
|
|
25
|
+
export const joinBackward: Command = (state, dispatch, view) => {
|
|
26
|
+
let { $cursor } = state.selection as TextSelection;
|
|
27
|
+
if (
|
|
28
|
+
!$cursor ||
|
|
29
|
+
(view ? !view.endOfTextblock("backward", state) : $cursor.parentOffset > 0)
|
|
30
|
+
) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let $cut = findCutBefore($cursor);
|
|
35
|
+
|
|
36
|
+
// If there is no node before this, try to lift
|
|
37
|
+
if (!$cut) {
|
|
38
|
+
let range = $cursor.blockRange(),
|
|
39
|
+
target = range && liftTarget(range);
|
|
40
|
+
if (target === null) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (dispatch) {
|
|
44
|
+
dispatch(state.tr.lift(range!, target).scrollIntoView());
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let before = $cut.nodeBefore!;
|
|
50
|
+
// Apply the joining algorithm
|
|
51
|
+
if (!before.type.spec.isolating && deleteBarrier(state, $cut, dispatch)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// If the node below has no content and the node above is
|
|
56
|
+
// selectable, delete the node below and select the one above.
|
|
57
|
+
if (
|
|
58
|
+
$cursor.parent.content.size === 0 &&
|
|
59
|
+
(textblockAt(before, "end") || NodeSelection.isSelectable(before))
|
|
60
|
+
) {
|
|
61
|
+
let delStep = replaceStep(
|
|
62
|
+
state.doc,
|
|
63
|
+
$cursor.before(),
|
|
64
|
+
$cursor.after(),
|
|
65
|
+
Slice.empty
|
|
66
|
+
);
|
|
67
|
+
if (
|
|
68
|
+
delStep &&
|
|
69
|
+
(delStep as ReplaceStep).slice.size <
|
|
70
|
+
(delStep as ReplaceStep).to - (delStep as ReplaceStep).from
|
|
71
|
+
) {
|
|
72
|
+
if (dispatch) {
|
|
73
|
+
let tr = state.tr.step(delStep);
|
|
74
|
+
tr.setSelection(
|
|
75
|
+
textblockAt(before, "end")
|
|
76
|
+
? Selection.findFrom(
|
|
77
|
+
tr.doc.resolve(tr.mapping.map($cut.pos, -1)),
|
|
78
|
+
-1
|
|
79
|
+
)!
|
|
80
|
+
: NodeSelection.create(tr.doc, $cut.pos - before.nodeSize)
|
|
81
|
+
);
|
|
82
|
+
dispatch(tr.scrollIntoView());
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// If the node before is an atom, delete it
|
|
89
|
+
if (before.isAtom && $cut.depth === $cursor.depth - 1) {
|
|
90
|
+
if (dispatch) {
|
|
91
|
+
dispatch(
|
|
92
|
+
state.tr.delete($cut.pos - before.nodeSize, $cut.pos).scrollIntoView()
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return false;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
function findCutBefore($pos: ResolvedPos): ResolvedPos | null {
|
|
102
|
+
if (!$pos.parent.type.spec.isolating) {
|
|
103
|
+
for (let i = $pos.depth - 1; i >= 0; i--) {
|
|
104
|
+
if ($pos.index(i) > 0) {
|
|
105
|
+
return $pos.doc.resolve($pos.before(i + 1));
|
|
106
|
+
}
|
|
107
|
+
if ($pos.node(i).type.spec.isolating) {
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function deleteBarrier(
|
|
116
|
+
state: EditorState,
|
|
117
|
+
$cut: ResolvedPos,
|
|
118
|
+
dispatch: ((tr: Transaction) => void) | undefined
|
|
119
|
+
) {
|
|
120
|
+
let before = $cut.nodeBefore!,
|
|
121
|
+
after = $cut.nodeAfter!,
|
|
122
|
+
conn,
|
|
123
|
+
match;
|
|
124
|
+
if (before.type.spec.isolating || after.type.spec.isolating) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
if (joinMaybeClear(state, $cut, dispatch)) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let canDelAfter = $cut.parent.canReplace($cut.index(), $cut.index() + 1);
|
|
132
|
+
|
|
133
|
+
let selAfter = Selection.findFrom($cut, 1);
|
|
134
|
+
let range = selAfter && selAfter.$from.blockRange(selAfter.$to),
|
|
135
|
+
target = range && liftTarget(range);
|
|
136
|
+
if (target != null && target >= $cut.depth) {
|
|
137
|
+
if (dispatch) {
|
|
138
|
+
dispatch(state.tr.lift(range!, target).scrollIntoView());
|
|
139
|
+
}
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
canDelAfter &&
|
|
145
|
+
textblockAt(after, "start", true) &&
|
|
146
|
+
textblockAt(before, "end")
|
|
147
|
+
) {
|
|
148
|
+
let at = before,
|
|
149
|
+
wrap = [];
|
|
150
|
+
for (;;) {
|
|
151
|
+
wrap.push(at);
|
|
152
|
+
if (at.isTextblock) {
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
at = at.lastChild!;
|
|
156
|
+
}
|
|
157
|
+
let afterText = after,
|
|
158
|
+
afterDepth = 1;
|
|
159
|
+
for (; !afterText.isTextblock; afterText = afterText.firstChild!) {
|
|
160
|
+
afterDepth++;
|
|
161
|
+
}
|
|
162
|
+
if (at.canReplace(at.childCount, at.childCount, afterText.content)) {
|
|
163
|
+
if (dispatch) {
|
|
164
|
+
let end = Fragment.empty;
|
|
165
|
+
for (let i = wrap.length - 1; i >= 0; i--) {
|
|
166
|
+
end = Fragment.from(wrap[i].copy(end));
|
|
167
|
+
}
|
|
168
|
+
let tr = state.tr.step(
|
|
169
|
+
new ReplaceAroundStep(
|
|
170
|
+
$cut.pos - wrap.length,
|
|
171
|
+
$cut.pos + after.nodeSize,
|
|
172
|
+
$cut.pos + afterDepth,
|
|
173
|
+
$cut.pos + after.nodeSize - afterDepth,
|
|
174
|
+
new Slice(end, wrap.length, 0),
|
|
175
|
+
0,
|
|
176
|
+
true
|
|
177
|
+
)
|
|
178
|
+
);
|
|
179
|
+
dispatch(tr.scrollIntoView());
|
|
180
|
+
}
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (
|
|
186
|
+
canDelAfter &&
|
|
187
|
+
(conn = (match = before.contentMatchAt(before.childCount)).findWrapping(
|
|
188
|
+
after.type
|
|
189
|
+
)) &&
|
|
190
|
+
match.matchType(conn[0] || after.type)!.validEnd
|
|
191
|
+
) {
|
|
192
|
+
if (dispatch) {
|
|
193
|
+
let end = $cut.pos + after.nodeSize,
|
|
194
|
+
wrap = Fragment.empty;
|
|
195
|
+
for (let i = conn.length - 1; i >= 0; i--) {
|
|
196
|
+
wrap = Fragment.from(conn[i].create(null, wrap));
|
|
197
|
+
}
|
|
198
|
+
wrap = Fragment.from(before.copy(wrap));
|
|
199
|
+
let tr = state.tr.step(
|
|
200
|
+
new ReplaceAroundStep(
|
|
201
|
+
$cut.pos - 1,
|
|
202
|
+
end,
|
|
203
|
+
$cut.pos,
|
|
204
|
+
end,
|
|
205
|
+
new Slice(wrap, 1, 0),
|
|
206
|
+
conn.length,
|
|
207
|
+
true
|
|
208
|
+
)
|
|
209
|
+
);
|
|
210
|
+
let joinAt = end + 2 * conn.length;
|
|
211
|
+
if (canJoin(tr.doc, joinAt)) {
|
|
212
|
+
tr.join(joinAt);
|
|
213
|
+
}
|
|
214
|
+
dispatch(tr.scrollIntoView());
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function textblockAt(node: Node, side: "start" | "end", only = false) {
|
|
222
|
+
for (
|
|
223
|
+
let scan: Node | null = node;
|
|
224
|
+
scan;
|
|
225
|
+
scan = side === "start" ? scan.firstChild : scan.lastChild
|
|
226
|
+
) {
|
|
227
|
+
if (scan.isTextblock) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
if (only && scan.childCount !== 1) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
function joinMaybeClear(
|
|
237
|
+
state: EditorState,
|
|
238
|
+
$pos: ResolvedPos,
|
|
239
|
+
dispatch: ((tr: Transaction) => void) | undefined
|
|
240
|
+
) {
|
|
241
|
+
let before = $pos.nodeBefore,
|
|
242
|
+
after = $pos.nodeAfter,
|
|
243
|
+
index = $pos.index();
|
|
244
|
+
if (!before || !after || !before.type.compatibleContent(after.type)) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
if (!before.content.size && $pos.parent.canReplace(index - 1, index)) {
|
|
248
|
+
if (dispatch) {
|
|
249
|
+
dispatch(
|
|
250
|
+
state.tr.delete($pos.pos - before.nodeSize, $pos.pos).scrollIntoView()
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
if (
|
|
256
|
+
!$pos.parent.canReplace(index, index + 1) ||
|
|
257
|
+
!(after.isTextblock || canJoin(state.doc, $pos.pos))
|
|
258
|
+
) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
if (dispatch) {
|
|
262
|
+
dispatch(
|
|
263
|
+
state.tr
|
|
264
|
+
.clearIncompatible(
|
|
265
|
+
$pos.pos,
|
|
266
|
+
before.type,
|
|
267
|
+
before.contentMatchAt(before.childCount)
|
|
268
|
+
)
|
|
269
|
+
.join($pos.pos)
|
|
270
|
+
.scrollIntoView()
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Transaction } from "prosemirror-state";
|
|
2
|
+
import { Level } from "../nodes/Block";
|
|
3
|
+
import { findBlock } from "./findBlock";
|
|
4
|
+
|
|
5
|
+
type Dispatch = ((args?: any) => any) | undefined;
|
|
6
|
+
|
|
7
|
+
export function setBlockHeading(
|
|
8
|
+
tr: Transaction,
|
|
9
|
+
dispatch: Dispatch,
|
|
10
|
+
level?: Level
|
|
11
|
+
) {
|
|
12
|
+
// Get parent of TextNode
|
|
13
|
+
const containingBlock = findBlock(tr.selection);
|
|
14
|
+
|
|
15
|
+
// Should not be possible because schema dictates
|
|
16
|
+
// that each text node is nested in a BlockContent
|
|
17
|
+
// node which is nested inside a BlockNode
|
|
18
|
+
if (!containingBlock) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Add heading attribute to Block
|
|
23
|
+
if (dispatch) {
|
|
24
|
+
tr.setNodeMarkup(containingBlock.pos, undefined, {
|
|
25
|
+
...containingBlock.node.attrs,
|
|
26
|
+
headingType: level,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Node } from "@tiptap/core";
|
|
2
|
+
import { Block } from "./nodes/Block";
|
|
3
|
+
import { BlockGroup } from "./nodes/BlockGroup";
|
|
4
|
+
import { ContentBlock } from "./nodes/Content";
|
|
5
|
+
|
|
6
|
+
export const blocks: any[] = [
|
|
7
|
+
ContentBlock,
|
|
8
|
+
Block,
|
|
9
|
+
BlockGroup,
|
|
10
|
+
Node.create({
|
|
11
|
+
name: "doc",
|
|
12
|
+
topNode: true,
|
|
13
|
+
content: "blockgroup",
|
|
14
|
+
}),
|
|
15
|
+
];
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/*
|
|
2
|
+
BASIC STYLES
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.blockOuter {
|
|
6
|
+
/* padding-bottom: 15px; */
|
|
7
|
+
font-size: 16px;
|
|
8
|
+
line-height: 1.5;
|
|
9
|
+
transition: all 0.2s;
|
|
10
|
+
font-weight: normal;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.block {
|
|
14
|
+
border-left: 2px solid white;
|
|
15
|
+
border-color: white;
|
|
16
|
+
transition: all 0.2s;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.block {
|
|
20
|
+
/* content: ""; */
|
|
21
|
+
transition: all 0.2s;
|
|
22
|
+
margin: 0px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.blockContent {
|
|
26
|
+
padding: 3px 0;
|
|
27
|
+
transition: font-size 0.2s;
|
|
28
|
+
/* display: inline-block; */
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
NESTED BLOCKS
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
.blockGroup .blockGroup {
|
|
36
|
+
margin-left: 1.5em;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.blockGroup .blockGroup > .blockOuter {
|
|
40
|
+
position: relative;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.blockGroup .blockGroup > .blockOuter:not([data-prev-depthchanged])::before {
|
|
44
|
+
content: " ";
|
|
45
|
+
display: inline;
|
|
46
|
+
border-left: 1px solid #ccc;
|
|
47
|
+
position: absolute;
|
|
48
|
+
left: -20px;
|
|
49
|
+
height: 100%;
|
|
50
|
+
transition: all 0.2s 0.1s;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.blockGroup .blockGroup > .blockOuter[data-prev-depthchange="-2"]::before {
|
|
54
|
+
height: 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* NESTED BLOCK ANIMATIONS */
|
|
58
|
+
|
|
59
|
+
[data-prev-depthchange="1"] {
|
|
60
|
+
--x: 1;
|
|
61
|
+
}
|
|
62
|
+
[data-prev-depthchange="2"] {
|
|
63
|
+
--x: 2;
|
|
64
|
+
}
|
|
65
|
+
[data-prev-depthchange="3"] {
|
|
66
|
+
--x: 3;
|
|
67
|
+
}
|
|
68
|
+
[data-prev-depthchange="4"] {
|
|
69
|
+
--x: 4;
|
|
70
|
+
}
|
|
71
|
+
[data-prev-depthchange="5"] {
|
|
72
|
+
--x: 5;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
[data-prev-depthchange="-1"] {
|
|
76
|
+
--x: -1;
|
|
77
|
+
}
|
|
78
|
+
[data-prev-depthchange="-2"] {
|
|
79
|
+
--x: -2;
|
|
80
|
+
}
|
|
81
|
+
[data-prev-depthchange="-3"] {
|
|
82
|
+
--x: -3;
|
|
83
|
+
}
|
|
84
|
+
[data-prev-depthchange="-4"] {
|
|
85
|
+
--x: -4;
|
|
86
|
+
}
|
|
87
|
+
[data-prev-depthchange="-5"] {
|
|
88
|
+
--x: -5;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.blockOuter[data-prev-depthchange] {
|
|
92
|
+
margin-left: calc(10px * var(--x));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.blockOuter[data-prev-depthchange] .blockOuter[data-prev-depthchange] {
|
|
96
|
+
margin-left: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* HEADINGS*/
|
|
100
|
+
.blockOuter[data-prev-headingtype="1"] > .block > div:first-child,
|
|
101
|
+
.blockOuter[data-headingtype="1"]:not([data-prev-headingtype])
|
|
102
|
+
> .block
|
|
103
|
+
> div:first-child {
|
|
104
|
+
font-size: 3em;
|
|
105
|
+
font-weight: bold;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.blockOuter[data-prev-headingtype="2"] > .block > div:first-child,
|
|
109
|
+
.blockOuter[data-headingtype="2"]:not([data-prev-headingtype])
|
|
110
|
+
> .block
|
|
111
|
+
> div:first-child {
|
|
112
|
+
font-size: 2em;
|
|
113
|
+
font-weight: bold;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.blockOuter[data-prev-headingtype="3"] > .block > div:first-child,
|
|
117
|
+
.blockOuter[data-headingtype="3"]:not([data-prev-headingtype])
|
|
118
|
+
> .block
|
|
119
|
+
> div:first-child {
|
|
120
|
+
font-size: 1.3em;
|
|
121
|
+
font-weight: bold;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* LISTS */
|
|
125
|
+
|
|
126
|
+
.block > div:first-child::before {
|
|
127
|
+
content: "";
|
|
128
|
+
transition: all 0.2s;
|
|
129
|
+
margin-left: 0px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.blockOuter[data-prev-listtype="oli"] > .block > div:first-child::before,
|
|
133
|
+
.blockOuter[data-listtype="oli"]:not([data-prev-listtype])
|
|
134
|
+
> .block
|
|
135
|
+
> div:first-child::before {
|
|
136
|
+
content: attr(data-position);
|
|
137
|
+
margin-right: 1.2em;
|
|
138
|
+
padding-left: 0px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.blockOuter[data-prev-listtype="li"] > .block > div:first-child::before,
|
|
142
|
+
.blockOuter[data-listtype="li"]:not([data-prev-listtype])
|
|
143
|
+
> .block
|
|
144
|
+
> div:first-child::before {
|
|
145
|
+
content: "•";
|
|
146
|
+
margin-right: 1.2em;
|
|
147
|
+
/* display: list-item; */
|
|
148
|
+
/* list-style-type: circle; */
|
|
149
|
+
/* list-style-position: inside; */
|
|
150
|
+
padding-left: 0px;
|
|
151
|
+
/* margin-left: 0.2em; */
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.blockOuter[data-listtype="li"]
|
|
155
|
+
> .block
|
|
156
|
+
> .blockGroup
|
|
157
|
+
> .blockOuter[data-prev-listtype="li"]
|
|
158
|
+
> .block
|
|
159
|
+
> div:first-child::before,
|
|
160
|
+
.blockOuter[data-listtype="li"]
|
|
161
|
+
> .block
|
|
162
|
+
> .blockGroup
|
|
163
|
+
> .blockOuter[data-listtype="li"]:not([data-prev-listtype])
|
|
164
|
+
> .block
|
|
165
|
+
> div:first-child::before {
|
|
166
|
+
content: "◦";
|
|
167
|
+
/* font-size: 1.2em; */
|
|
168
|
+
font-family: arial;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.blockOuter[data-listtype="li"]
|
|
172
|
+
> .block
|
|
173
|
+
> .blockGroup
|
|
174
|
+
> .blockOuter[data-listtype="li"]
|
|
175
|
+
> .block
|
|
176
|
+
> .blockGroup
|
|
177
|
+
.blockOuter[data-prev-listtype="li"]
|
|
178
|
+
> .block
|
|
179
|
+
> div:first-child::before,
|
|
180
|
+
.blockOuter[data-listtype="li"]
|
|
181
|
+
> .block
|
|
182
|
+
> .blockGroup
|
|
183
|
+
> .blockOuter[data-listtype="li"]
|
|
184
|
+
> .block
|
|
185
|
+
> .blockGroup
|
|
186
|
+
.blockOuter[data-listtype="li"]:not([data-prev-listtype])
|
|
187
|
+
> .block
|
|
188
|
+
> div:first-child::before {
|
|
189
|
+
content: "▪";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* PLACEHOLDERS*/
|
|
193
|
+
|
|
194
|
+
.blockContent > div {
|
|
195
|
+
display: inline;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.blockContent.isEmpty div::before,
|
|
199
|
+
.blockContent.isFilter div::before {
|
|
200
|
+
/*float: left; */
|
|
201
|
+
content: "";
|
|
202
|
+
color: #aeb8c2;
|
|
203
|
+
pointer-events: none;
|
|
204
|
+
height: 0;
|
|
205
|
+
/* width: 0; */
|
|
206
|
+
position: absolute;
|
|
207
|
+
font-style: italic;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* TODO: would be nicer if defined from code */
|
|
211
|
+
|
|
212
|
+
.blockContent.isEmpty.hasAnchor div::before {
|
|
213
|
+
content: "Enter text or type '/' for commands";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.blockContent.isFilter.hasAnchor div::before {
|
|
217
|
+
content: "Type to filter";
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
[data-headingtype] > .blockContent.isEmpty div::before {
|
|
221
|
+
content: "Heading";
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
[data-listtype] > .blockContent.isEmpty div::before {
|
|
225
|
+
content: "List";
|
|
226
|
+
}
|