From 577318e208367dc52caf2d76fd87419eaead7ed4 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Sat, 24 Dec 2022 20:35:41 +0530 Subject: [PATCH] feat: Persist collapsible block state in Super notes (#2119) --- .../CollapsibleContainerNode.ts | 26 ++++++++++------- .../CollapsibleContentNode.ts | 17 ++++++----- .../CollapsiblePlugin/CollapsibleTitleNode.ts | 29 ++++++++++++++----- .../Plugins/CollapsiblePlugin/index.ts | 2 +- 4 files changed, 48 insertions(+), 26 deletions(-) diff --git a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContainerNode.ts b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContainerNode.ts index 407cabc65..bfea8a80d 100644 --- a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContainerNode.ts +++ b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContainerNode.ts @@ -20,6 +20,7 @@ type SerializedCollapsibleContainerNode = Spread< { type: 'collapsible-container'; version: 1; + open: boolean; }, SerializedElementNode >; @@ -29,25 +30,27 @@ export class CollapsibleContainerNode extends ElementNode { constructor(open: boolean, key?: NodeKey) { super(key); - this.__open = open; + this.__open = open ?? false; } - static getType(): string { + static override getType(): string { return 'collapsible-container'; } - static clone(node: CollapsibleContainerNode): CollapsibleContainerNode { + static override clone( + node: CollapsibleContainerNode, + ): CollapsibleContainerNode { return new CollapsibleContainerNode(node.__open, node.__key); } - createDOM(config: EditorConfig): HTMLElement { + override createDOM(config: EditorConfig): HTMLElement { const dom = document.createElement('details'); dom.classList.add('Collapsible__container'); dom.open = this.__open; return dom; } - updateDOM( + override updateDOM( prevNode: CollapsibleContainerNode, dom: HTMLDetailsElement, ): boolean { @@ -62,18 +65,19 @@ export class CollapsibleContainerNode extends ElementNode { return {}; } - static importJSON( + static override importJSON( serializedNode: SerializedCollapsibleContainerNode, ): CollapsibleContainerNode { - const node = $createCollapsibleContainerNode(); + const node = $createCollapsibleContainerNode(serializedNode.open); return node; } - exportJSON(): SerializedCollapsibleContainerNode { + override exportJSON(): SerializedCollapsibleContainerNode { return { ...super.exportJSON(), type: 'collapsible-container', version: 1, + open: this.__open, }; } @@ -91,8 +95,10 @@ export class CollapsibleContainerNode extends ElementNode { } } -export function $createCollapsibleContainerNode(): CollapsibleContainerNode { - return new CollapsibleContainerNode(true); +export function $createCollapsibleContainerNode( + open: boolean, +): CollapsibleContainerNode { + return new CollapsibleContainerNode(open); } export function $isCollapsibleContainerNode( diff --git a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContentNode.ts b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContentNode.ts index 3760d4c3f..86eb9e51f 100644 --- a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContentNode.ts +++ b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleContentNode.ts @@ -24,21 +24,24 @@ type SerializedCollapsibleContentNode = Spread< >; export class CollapsibleContentNode extends ElementNode { - static getType(): string { + static override getType(): string { return 'collapsible-content'; } - static clone(node: CollapsibleContentNode): CollapsibleContentNode { + static override clone(node: CollapsibleContentNode): CollapsibleContentNode { return new CollapsibleContentNode(node.__key); } - createDOM(config: EditorConfig): HTMLElement { + override createDOM(config: EditorConfig): HTMLElement { const dom = document.createElement('div'); dom.classList.add('Collapsible__content'); return dom; } - updateDOM(prevNode: CollapsibleContentNode, dom: HTMLElement): boolean { + override updateDOM( + prevNode: CollapsibleContentNode, + dom: HTMLElement, + ): boolean { return false; } @@ -46,17 +49,17 @@ export class CollapsibleContentNode extends ElementNode { return {}; } - static importJSON( + static override importJSON( serializedNode: SerializedCollapsibleContentNode, ): CollapsibleContentNode { return $createCollapsibleContentNode(); } - isShadowRoot(): boolean { + override isShadowRoot(): boolean { return true; } - exportJSON(): SerializedCollapsibleContentNode { + override exportJSON(): SerializedCollapsibleContentNode { return { ...super.exportJSON(), type: 'collapsible-content', diff --git a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleTitleNode.ts b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleTitleNode.ts index 5903c3f46..16e47d3fc 100644 --- a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleTitleNode.ts +++ b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/CollapsibleTitleNode.ts @@ -31,21 +31,34 @@ type SerializedCollapsibleTitleNode = Spread< >; export class CollapsibleTitleNode extends ElementNode { - static getType(): string { + static override getType(): string { return 'collapsible-title'; } - static clone(node: CollapsibleTitleNode): CollapsibleTitleNode { + static override clone(node: CollapsibleTitleNode): CollapsibleTitleNode { return new CollapsibleTitleNode(node.__key); } - createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement { + override createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement { const dom = document.createElement('summary'); dom.classList.add('Collapsible__title'); + dom.onclick = (event) => { + event.preventDefault(); + event.stopPropagation(); + editor.update(() => { + const containerNode = this.getParentOrThrow(); + if ($isCollapsibleContainerNode(containerNode)) { + containerNode.toggleOpen(); + } + }); + }; return dom; } - updateDOM(prevNode: CollapsibleTitleNode, dom: HTMLElement): boolean { + override updateDOM( + prevNode: CollapsibleTitleNode, + dom: HTMLElement, + ): boolean { return false; } @@ -53,13 +66,13 @@ export class CollapsibleTitleNode extends ElementNode { return {}; } - static importJSON( + static override importJSON( serializedNode: SerializedCollapsibleTitleNode, ): CollapsibleTitleNode { return $createCollapsibleTitleNode(); } - exportJSON(): SerializedCollapsibleTitleNode { + override exportJSON(): SerializedCollapsibleTitleNode { return { ...super.exportJSON(), type: 'collapsible-title', @@ -67,12 +80,12 @@ export class CollapsibleTitleNode extends ElementNode { }; } - collapseAtStart(_selection: RangeSelection): boolean { + override collapseAtStart(_selection: RangeSelection): boolean { this.getParentOrThrow().insertBefore(this); return true; } - insertNewAfter(): ElementNode { + override insertNewAfter(): ElementNode { const containerNode = this.getParentOrThrow(); if (!$isCollapsibleContainerNode(containerNode)) { diff --git a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/index.ts b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/index.ts index eb6b8f94e..817eb4aa6 100644 --- a/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/index.ts +++ b/packages/blocks-editor/src/Lexical/Plugins/CollapsiblePlugin/index.ts @@ -204,7 +204,7 @@ export default function CollapsiblePlugin(): JSX.Element | null { const content = $createCollapsibleContentNode().append( $createParagraphNode(), ); - const container = $createCollapsibleContainerNode().append( + const container = $createCollapsibleContainerNode(true).append( title, content, );