Skip to content

Commit 33912b8

Browse files
committed
Implemented PR feedback
1 parent 09608a5 commit 33912b8

File tree

5 files changed

+113
-73
lines changed

5 files changed

+113
-73
lines changed

packages/core/src/blocks/HeadingBlockContent/HeadingBlockContent.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({
159159

160160
addNodeView() {
161161
return ({ node, HTMLAttributes, getPos }) => {
162-
const renderedElement = createDefaultBlockDOMOutputSpec(
162+
const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
163163
this.name,
164164
`h${node.attrs.level}`,
165165
{
@@ -168,22 +168,21 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({
168168
},
169169
this.options.domAttributes?.inlineContent || {},
170170
);
171-
172-
const contentDOM = renderedElement.contentDOM;
173-
const contentDOMParentElement = contentDOM.parentElement!;
171+
dom.removeChild(contentDOM);
174172

175173
const editor = this.options.editor;
176174
const block = getBlockFromPos(getPos, editor, this.editor, this.name);
177175

178-
const toggleWrapper = createToggleWrapper(block as any, editor, {
179-
dom: contentDOM,
176+
const toggleWrapper = createToggleWrapper(
177+
block as any,
178+
editor,
180179
contentDOM,
181-
});
182-
contentDOMParentElement.appendChild(toggleWrapper.dom);
180+
);
181+
dom.appendChild(toggleWrapper.dom);
183182

184183
return {
185-
dom: renderedElement.dom,
186-
contentDOM: toggleWrapper.contentDOM,
184+
dom,
185+
contentDOM,
187186
ignoreMutation: toggleWrapper.ignoreMutation,
188187
destroy: toggleWrapper.destroy,
189188
};

packages/core/src/blocks/ListItemBlockContent/ToggleListItemBlockContent/ToggleListItemBlockContent.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const ToggleListItemBlockContent = createStronglyTypedTiptapNode({
6868

6969
addNodeView() {
7070
return ({ HTMLAttributes, getPos }) => {
71-
const renderedElement = createDefaultBlockDOMOutputSpec(
71+
const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
7272
this.name,
7373
"p",
7474
{
@@ -78,21 +78,19 @@ const ToggleListItemBlockContent = createStronglyTypedTiptapNode({
7878
this.options.domAttributes?.inlineContent || {},
7979
);
8080

81-
const contentDOM = renderedElement.contentDOM;
82-
const contentDOMParentElement = contentDOM.parentElement!;
83-
8481
const editor = this.options.editor;
8582
const block = getBlockFromPos(getPos, editor, this.editor, this.name);
8683

87-
const toggleWrapper = createToggleWrapper(block as any, editor, {
88-
dom: contentDOM,
84+
const toggleWrapper = createToggleWrapper(
85+
block as any,
86+
editor,
8987
contentDOM,
90-
});
91-
contentDOMParentElement.appendChild(toggleWrapper.dom);
88+
);
89+
dom.appendChild(toggleWrapper.dom);
9290

9391
return {
94-
dom: renderedElement.dom,
95-
contentDOM: toggleWrapper.contentDOM,
92+
dom,
93+
contentDOM,
9694
ignoreMutation: toggleWrapper.ignoreMutation,
9795
destroy: toggleWrapper.destroy,
9896
};

packages/core/src/blocks/ToggleWrapper/createToggleWrapper.ts

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,34 @@ import { ViewMutationRecord } from "@tiptap/pm/view";
33
import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
44
import { Block } from "../defaultBlocks.js";
55

6+
type ToggledState = {
7+
set: (block: Block<any, any, any>, isToggled: boolean) => void;
8+
get: (block: Block<any, any, any>) => boolean;
9+
};
10+
11+
export const defaultToggledState: ToggledState = {
12+
set: (block, isToggled: boolean) =>
13+
window.localStorage.setItem(
14+
`toggle-${block.id}`,
15+
isToggled ? "true" : "false",
16+
),
17+
get: (block) => window.localStorage.getItem(`toggle-${block.id}`) === "true",
18+
};
19+
620
export const createToggleWrapper = (
721
block: Block<any, any, any>,
822
editor: BlockNoteEditor<any, any, any>,
9-
renderedElement: {
10-
dom: HTMLElement;
11-
contentDOM?: HTMLElement;
12-
ignoreMutation?: (mutation: ViewMutationRecord) => boolean;
13-
destroy?: () => void;
14-
},
15-
toggledState?: {
16-
set: (block: Block<any, any, any>, isToggled: boolean) => void;
17-
get: (block: Block<any, any, any>) => boolean;
18-
},
23+
renderedElement: HTMLElement,
24+
toggledState: ToggledState = defaultToggledState,
1925
): {
2026
dom: HTMLElement;
2127
contentDOM?: HTMLElement;
2228
ignoreMutation?: (mutation: ViewMutationRecord) => boolean;
2329
destroy?: () => void;
2430
} => {
2531
if ("isToggleable" in block.props && !block.props.isToggleable) {
26-
return renderedElement;
27-
}
28-
29-
if (!toggledState) {
30-
toggledState = {
31-
set: (block, isToggled: boolean) => {
32-
window.localStorage.setItem(`toggle-${block.id}`, String(isToggled));
33-
},
34-
get: (block) => {
35-
return window.localStorage.getItem(`toggle-${block.id}`) === "true";
36-
},
32+
return {
33+
dom: renderedElement,
3734
};
3835
}
3936

@@ -74,7 +71,7 @@ export const createToggleWrapper = (
7471
toggleButton.addEventListener("click", toggleButtonOnClick);
7572

7673
toggleWrapper.appendChild(toggleButton);
77-
toggleWrapper.appendChild(renderedElement.dom);
74+
toggleWrapper.appendChild(renderedElement);
7875

7976
const toggleAddBlockButton = document.createElement("button");
8077
toggleAddBlockButton.className = "bn-toggle-add-block-button";
@@ -150,13 +147,8 @@ export const createToggleWrapper = (
150147

151148
return {
152149
dom,
153-
contentDOM: renderedElement.contentDOM,
154150
// Prevents re-renders when the toggle button is clicked.
155151
ignoreMutation: (mutation) => {
156-
if (renderedElement.ignoreMutation) {
157-
return renderedElement.ignoreMutation(mutation);
158-
}
159-
160152
if (
161153
mutation instanceof MutationRecord &&
162154
// We want to prevent re-renders when the view changes, so we ignore
@@ -185,7 +177,6 @@ export const createToggleWrapper = (
185177
toggleAddBlockButtonOnClick,
186178
);
187179
onEditorChange?.();
188-
renderedElement.destroy?.();
189180
},
190181
};
191182
};

packages/core/src/editor/Block.css

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ NESTED BLOCKS
177177
.bn-block-content[data-content-type="numberedListItem"]::before {
178178
display: flex;
179179
justify-content: center;
180-
width: 25px;
180+
min-width: 24px;
181+
padding-right: 4px;
181182
}
182183

183184
[data-content-type="numberedListItem"] {
@@ -208,7 +209,8 @@ NESTED BLOCKS
208209
.bn-block-content[data-content-type="bulletListItem"]::before {
209210
display: flex;
210211
justify-content: center;
211-
width: 25px;
212+
min-width: 24px;
213+
padding-right: 4px;
212214
}
213215

214216
/* Checked */
@@ -220,7 +222,8 @@ NESTED BLOCKS
220222
.bn-block-content[data-content-type="checkListItem"] > div > div {
221223
display: flex;
222224
justify-content: center;
223-
width: 25px;
225+
min-width: 24px;
226+
padding-right: 4px;
224227
}
225228

226229
.bn-block-content[data-content-type="checkListItem"] > div > div > input {

packages/react/src/blocks/ToggleWrapper/ToggleWrapper.tsx

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,41 @@
1-
import { Block } from "@blocknote/core";
2-
import { ReactNode, useEffect, useMemo, useState } from "react";
1+
import {
2+
Block,
3+
defaultToggledState,
4+
UnreachableCaseError,
5+
} from "@blocknote/core";
6+
import { ReactNode, useReducer, useState } from "react";
37

48
import { ReactCustomBlockRenderProps } from "../../schema/ReactBlockSpec.js";
59
import { useEditorChange } from "../../hooks/useEditorChange.js";
610

11+
const showChildrenReducer = (
12+
showChildren: boolean,
13+
action:
14+
| {
15+
type: "toggled";
16+
}
17+
| {
18+
type: "childAdded";
19+
}
20+
| {
21+
type: "lastChildRemoved";
22+
},
23+
) => {
24+
if (action.type === "toggled") {
25+
return !showChildren;
26+
}
27+
28+
if (action.type === "childAdded") {
29+
return true;
30+
}
31+
32+
if (action.type === "lastChildRemoved") {
33+
return false;
34+
}
35+
36+
throw new UnreachableCaseError(action);
37+
};
38+
739
export const ToggleWrapper = (
840
props: Omit<ReactCustomBlockRenderProps<any, any, any>, "contentRef"> & {
941
children: ReactNode;
@@ -13,39 +45,56 @@ export const ToggleWrapper = (
1345
};
1446
},
1547
) => {
16-
const { block, editor, children } = props;
17-
18-
const toggledState = useMemo(
19-
() =>
20-
props.toggledState || {
21-
set: (block, isToggled: boolean) =>
22-
window.localStorage.setItem(`toggle-${block.id}`, String(isToggled)),
23-
get: (block) =>
24-
window.localStorage.getItem(`toggle-${block.id}`) === "true",
25-
},
26-
[props.toggledState],
27-
);
48+
const { block, editor, children, toggledState } = props;
2849

29-
const [showChildren, setShowChildren] = useState(toggledState.get(block));
50+
const [showChildren, dispatch] = useReducer(
51+
showChildrenReducer,
52+
(toggledState || defaultToggledState).get(block),
53+
);
3054
const [childCount, setChildCount] = useState(block.children.length);
3155

32-
useEffect(() => {
33-
toggledState.set(editor.getBlock(block)!, showChildren);
34-
}, [block, block.id, editor, showChildren, toggledState]);
56+
const handleToggle = (block: Block<any, any, any>) => {
57+
(toggledState || defaultToggledState).set(
58+
editor.getBlock(block)!,
59+
!showChildren,
60+
);
61+
dispatch({
62+
type: "toggled",
63+
});
64+
};
65+
66+
const handleChildAdded = (block: Block<any, any, any>) => {
67+
(toggledState || defaultToggledState).set(block, true);
68+
dispatch({
69+
type: "childAdded",
70+
});
71+
};
72+
73+
const handleLastChildRemoved = (block: Block<any, any, any>) => {
74+
(toggledState || defaultToggledState).set(block, false);
75+
dispatch({
76+
type: "lastChildRemoved",
77+
});
78+
};
3579

3680
useEditorChange(() => {
37-
const newChildCount = editor.getBlock(block)?.children.length ?? 0;
81+
if ("isToggleable" in block.props && !block.props.isToggleable) {
82+
return;
83+
}
84+
85+
const newBlock = editor.getBlock(block)!;
86+
const newChildCount = newBlock.children.length ?? 0;
3887

3988
if (newChildCount > childCount) {
4089
// If a child block is added while children are hidden, show children.
4190
if (!showChildren) {
42-
setShowChildren(true);
91+
handleChildAdded(newBlock);
4392
}
4493
} else if (newChildCount === 0 && newChildCount < childCount) {
4594
// If the last child block is removed while children are shown, hide
4695
// children.
4796
if (showChildren) {
48-
setShowChildren(false);
97+
handleLastChildRemoved(newBlock);
4998
}
5099
}
51100

@@ -62,7 +111,7 @@ export const ToggleWrapper = (
62111
<button
63112
className="bn-toggle-button"
64113
onMouseDown={(event) => event.preventDefault()}
65-
onClick={() => setShowChildren((showChildren) => !showChildren)}
114+
onClick={() => handleToggle(editor.getBlock(block)!)}
66115
>
67116
<svg
68117
xmlns="http://www.w3.org/2000/svg"

0 commit comments

Comments
 (0)