feat: Persist collapsible block state in Super notes (#2119)
This commit is contained in:
@@ -20,6 +20,7 @@ type SerializedCollapsibleContainerNode = Spread<
|
|||||||
{
|
{
|
||||||
type: 'collapsible-container';
|
type: 'collapsible-container';
|
||||||
version: 1;
|
version: 1;
|
||||||
|
open: boolean;
|
||||||
},
|
},
|
||||||
SerializedElementNode
|
SerializedElementNode
|
||||||
>;
|
>;
|
||||||
@@ -29,25 +30,27 @@ export class CollapsibleContainerNode extends ElementNode {
|
|||||||
|
|
||||||
constructor(open: boolean, key?: NodeKey) {
|
constructor(open: boolean, key?: NodeKey) {
|
||||||
super(key);
|
super(key);
|
||||||
this.__open = open;
|
this.__open = open ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getType(): string {
|
static override getType(): string {
|
||||||
return 'collapsible-container';
|
return 'collapsible-container';
|
||||||
}
|
}
|
||||||
|
|
||||||
static clone(node: CollapsibleContainerNode): CollapsibleContainerNode {
|
static override clone(
|
||||||
|
node: CollapsibleContainerNode,
|
||||||
|
): CollapsibleContainerNode {
|
||||||
return new CollapsibleContainerNode(node.__open, node.__key);
|
return new CollapsibleContainerNode(node.__open, node.__key);
|
||||||
}
|
}
|
||||||
|
|
||||||
createDOM(config: EditorConfig): HTMLElement {
|
override createDOM(config: EditorConfig): HTMLElement {
|
||||||
const dom = document.createElement('details');
|
const dom = document.createElement('details');
|
||||||
dom.classList.add('Collapsible__container');
|
dom.classList.add('Collapsible__container');
|
||||||
dom.open = this.__open;
|
dom.open = this.__open;
|
||||||
return dom;
|
return dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDOM(
|
override updateDOM(
|
||||||
prevNode: CollapsibleContainerNode,
|
prevNode: CollapsibleContainerNode,
|
||||||
dom: HTMLDetailsElement,
|
dom: HTMLDetailsElement,
|
||||||
): boolean {
|
): boolean {
|
||||||
@@ -62,18 +65,19 @@ export class CollapsibleContainerNode extends ElementNode {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static importJSON(
|
static override importJSON(
|
||||||
serializedNode: SerializedCollapsibleContainerNode,
|
serializedNode: SerializedCollapsibleContainerNode,
|
||||||
): CollapsibleContainerNode {
|
): CollapsibleContainerNode {
|
||||||
const node = $createCollapsibleContainerNode();
|
const node = $createCollapsibleContainerNode(serializedNode.open);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
exportJSON(): SerializedCollapsibleContainerNode {
|
override exportJSON(): SerializedCollapsibleContainerNode {
|
||||||
return {
|
return {
|
||||||
...super.exportJSON(),
|
...super.exportJSON(),
|
||||||
type: 'collapsible-container',
|
type: 'collapsible-container',
|
||||||
version: 1,
|
version: 1,
|
||||||
|
open: this.__open,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,8 +95,10 @@ export class CollapsibleContainerNode extends ElementNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function $createCollapsibleContainerNode(): CollapsibleContainerNode {
|
export function $createCollapsibleContainerNode(
|
||||||
return new CollapsibleContainerNode(true);
|
open: boolean,
|
||||||
|
): CollapsibleContainerNode {
|
||||||
|
return new CollapsibleContainerNode(open);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function $isCollapsibleContainerNode(
|
export function $isCollapsibleContainerNode(
|
||||||
|
|||||||
@@ -24,21 +24,24 @@ type SerializedCollapsibleContentNode = Spread<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
export class CollapsibleContentNode extends ElementNode {
|
export class CollapsibleContentNode extends ElementNode {
|
||||||
static getType(): string {
|
static override getType(): string {
|
||||||
return 'collapsible-content';
|
return 'collapsible-content';
|
||||||
}
|
}
|
||||||
|
|
||||||
static clone(node: CollapsibleContentNode): CollapsibleContentNode {
|
static override clone(node: CollapsibleContentNode): CollapsibleContentNode {
|
||||||
return new CollapsibleContentNode(node.__key);
|
return new CollapsibleContentNode(node.__key);
|
||||||
}
|
}
|
||||||
|
|
||||||
createDOM(config: EditorConfig): HTMLElement {
|
override createDOM(config: EditorConfig): HTMLElement {
|
||||||
const dom = document.createElement('div');
|
const dom = document.createElement('div');
|
||||||
dom.classList.add('Collapsible__content');
|
dom.classList.add('Collapsible__content');
|
||||||
return dom;
|
return dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDOM(prevNode: CollapsibleContentNode, dom: HTMLElement): boolean {
|
override updateDOM(
|
||||||
|
prevNode: CollapsibleContentNode,
|
||||||
|
dom: HTMLElement,
|
||||||
|
): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,17 +49,17 @@ export class CollapsibleContentNode extends ElementNode {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static importJSON(
|
static override importJSON(
|
||||||
serializedNode: SerializedCollapsibleContentNode,
|
serializedNode: SerializedCollapsibleContentNode,
|
||||||
): CollapsibleContentNode {
|
): CollapsibleContentNode {
|
||||||
return $createCollapsibleContentNode();
|
return $createCollapsibleContentNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
isShadowRoot(): boolean {
|
override isShadowRoot(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
exportJSON(): SerializedCollapsibleContentNode {
|
override exportJSON(): SerializedCollapsibleContentNode {
|
||||||
return {
|
return {
|
||||||
...super.exportJSON(),
|
...super.exportJSON(),
|
||||||
type: 'collapsible-content',
|
type: 'collapsible-content',
|
||||||
|
|||||||
@@ -31,21 +31,34 @@ type SerializedCollapsibleTitleNode = Spread<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
export class CollapsibleTitleNode extends ElementNode {
|
export class CollapsibleTitleNode extends ElementNode {
|
||||||
static getType(): string {
|
static override getType(): string {
|
||||||
return 'collapsible-title';
|
return 'collapsible-title';
|
||||||
}
|
}
|
||||||
|
|
||||||
static clone(node: CollapsibleTitleNode): CollapsibleTitleNode {
|
static override clone(node: CollapsibleTitleNode): CollapsibleTitleNode {
|
||||||
return new CollapsibleTitleNode(node.__key);
|
return new CollapsibleTitleNode(node.__key);
|
||||||
}
|
}
|
||||||
|
|
||||||
createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement {
|
override createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement {
|
||||||
const dom = document.createElement('summary');
|
const dom = document.createElement('summary');
|
||||||
dom.classList.add('Collapsible__title');
|
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;
|
return dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDOM(prevNode: CollapsibleTitleNode, dom: HTMLElement): boolean {
|
override updateDOM(
|
||||||
|
prevNode: CollapsibleTitleNode,
|
||||||
|
dom: HTMLElement,
|
||||||
|
): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,13 +66,13 @@ export class CollapsibleTitleNode extends ElementNode {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static importJSON(
|
static override importJSON(
|
||||||
serializedNode: SerializedCollapsibleTitleNode,
|
serializedNode: SerializedCollapsibleTitleNode,
|
||||||
): CollapsibleTitleNode {
|
): CollapsibleTitleNode {
|
||||||
return $createCollapsibleTitleNode();
|
return $createCollapsibleTitleNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
exportJSON(): SerializedCollapsibleTitleNode {
|
override exportJSON(): SerializedCollapsibleTitleNode {
|
||||||
return {
|
return {
|
||||||
...super.exportJSON(),
|
...super.exportJSON(),
|
||||||
type: 'collapsible-title',
|
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);
|
this.getParentOrThrow().insertBefore(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
insertNewAfter(): ElementNode {
|
override insertNewAfter(): ElementNode {
|
||||||
const containerNode = this.getParentOrThrow();
|
const containerNode = this.getParentOrThrow();
|
||||||
|
|
||||||
if (!$isCollapsibleContainerNode(containerNode)) {
|
if (!$isCollapsibleContainerNode(containerNode)) {
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ export default function CollapsiblePlugin(): JSX.Element | null {
|
|||||||
const content = $createCollapsibleContentNode().append(
|
const content = $createCollapsibleContentNode().append(
|
||||||
$createParagraphNode(),
|
$createParagraphNode(),
|
||||||
);
|
);
|
||||||
const container = $createCollapsibleContainerNode().append(
|
const container = $createCollapsibleContainerNode(true).append(
|
||||||
title,
|
title,
|
||||||
content,
|
content,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user