| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |     DOMConversion, | 
					
						
							|  |  |  |     DOMConversionMap, DOMConversionOutput, | 
					
						
							|  |  |  |     ElementNode, | 
					
						
							|  |  |  |     LexicalEditor, | 
					
						
							|  |  |  |     LexicalNode, | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |     SerializedElementNode, Spread, | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |     EditorConfig, DOMExportOutput, | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  | } from 'lexical'; | 
					
						
							| 
									
										
										
										
											2024-08-04 01:14:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-05 02:53:59 +08:00
										 |  |  | import {extractDirectionFromElement} from "lexical/nodes/common"; | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  | export type SerializedDetailsNode = Spread<{ | 
					
						
							|  |  |  |     id: string; | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |     summary: string; | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  | }, SerializedElementNode> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  | export class DetailsNode extends ElementNode { | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |     __id: string = ''; | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |     __summary: string = ''; | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  |     __open: boolean = false; | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     static getType() { | 
					
						
							|  |  |  |         return 'details'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |     setId(id: string) { | 
					
						
							|  |  |  |         const self = this.getWritable(); | 
					
						
							|  |  |  |         self.__id = id; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getId(): string { | 
					
						
							|  |  |  |         const self = this.getLatest(); | 
					
						
							|  |  |  |         return self.__id; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |     setSummary(summary: string) { | 
					
						
							|  |  |  |         const self = this.getWritable(); | 
					
						
							|  |  |  |         self.__summary = summary; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getSummary(): string { | 
					
						
							|  |  |  |         const self = this.getLatest(); | 
					
						
							|  |  |  |         return self.__summary; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  |     setOpen(open: boolean) { | 
					
						
							|  |  |  |         const self = this.getWritable(); | 
					
						
							|  |  |  |         self.__open = open; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getOpen(): boolean { | 
					
						
							|  |  |  |         const self = this.getLatest(); | 
					
						
							|  |  |  |         return self.__open; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |     static clone(node: DetailsNode): DetailsNode { | 
					
						
							|  |  |  |         const newNode =  new DetailsNode(node.__key); | 
					
						
							|  |  |  |         newNode.__id = node.__id; | 
					
						
							| 
									
										
										
										
											2024-09-22 19:07:24 +08:00
										 |  |  |         newNode.__dir = node.__dir; | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |         newNode.__summary = node.__summary; | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  |         newNode.__open = node.__open; | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |         return newNode; | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     createDOM(_config: EditorConfig, _editor: LexicalEditor) { | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |         const el = document.createElement('details'); | 
					
						
							|  |  |  |         if (this.__id) { | 
					
						
							|  |  |  |             el.setAttribute('id', this.__id); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-22 19:07:24 +08:00
										 |  |  |         if (this.__dir) { | 
					
						
							|  |  |  |             el.setAttribute('dir', this.__dir); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  |         if (this.__open) { | 
					
						
							|  |  |  |             el.setAttribute('open', 'true'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |         const summary = document.createElement('summary'); | 
					
						
							|  |  |  |         summary.textContent = this.__summary; | 
					
						
							|  |  |  |         summary.setAttribute('contenteditable', 'false'); | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  |         summary.addEventListener('click', event => { | 
					
						
							|  |  |  |             event.preventDefault(); | 
					
						
							|  |  |  |             _editor.update(() => { | 
					
						
							|  |  |  |                 this.select(); | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |         el.append(summary); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |         return el; | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     updateDOM(prevNode: DetailsNode, dom: HTMLElement) { | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (prevNode.__open !== this.__open) { | 
					
						
							|  |  |  |             dom.toggleAttribute('open', this.__open); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-22 19:07:24 +08:00
										 |  |  |         return prevNode.__id !== this.__id | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  |         || prevNode.__dir !== this.__dir | 
					
						
							|  |  |  |         || prevNode.__summary !== this.__summary; | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static importDOM(): DOMConversionMap|null { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             details(node: HTMLElement): DOMConversion|null { | 
					
						
							|  |  |  |                 return { | 
					
						
							|  |  |  |                     conversion: (element: HTMLElement): DOMConversionOutput|null => { | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |                         const node = new DetailsNode(); | 
					
						
							|  |  |  |                         if (element.id) { | 
					
						
							|  |  |  |                             node.setId(element.id); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-22 19:07:24 +08:00
										 |  |  |                         if (element.dir) { | 
					
						
							|  |  |  |                             node.setDirection(extractDirectionFromElement(element)); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |                         const summaryElem = Array.from(element.children).find(e => e.nodeName === 'SUMMARY'); | 
					
						
							|  |  |  |                         node.setSummary(summaryElem?.textContent || ''); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |                         return {node}; | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |                     }, | 
					
						
							|  |  |  |                     priority: 3, | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |             summary(node: HTMLElement): DOMConversion|null { | 
					
						
							|  |  |  |                 return { | 
					
						
							|  |  |  |                     conversion: (element: HTMLElement): DOMConversionOutput|null => { | 
					
						
							|  |  |  |                         return {node: 'ignore'}; | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                     priority: 3, | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |     exportDOM(editor: LexicalEditor): DOMExportOutput { | 
					
						
							|  |  |  |         const element = this.createDOM(editor._config, editor); | 
					
						
							|  |  |  |         const editable = element.querySelectorAll('[contenteditable]'); | 
					
						
							|  |  |  |         for (const elem of editable) { | 
					
						
							|  |  |  |             elem.removeAttribute('contenteditable'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 02:13:49 +08:00
										 |  |  |         element.removeAttribute('open'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |         return {element}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |     exportJSON(): SerializedDetailsNode { | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |         return { | 
					
						
							|  |  |  |             ...super.exportJSON(), | 
					
						
							|  |  |  |             type: 'details', | 
					
						
							|  |  |  |             version: 1, | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |             id: this.__id, | 
					
						
							| 
									
										
										
										
											2024-12-16 01:11:02 +08:00
										 |  |  |             summary: this.__summary, | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |     static importJSON(serializedNode: SerializedDetailsNode): DetailsNode { | 
					
						
							|  |  |  |         const node = $createDetailsNode(); | 
					
						
							|  |  |  |         node.setId(serializedNode.id); | 
					
						
							| 
									
										
										
										
											2024-09-22 19:07:24 +08:00
										 |  |  |         node.setDirection(serializedNode.direction); | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  |         return node; | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export function $createDetailsNode() { | 
					
						
							|  |  |  |     return new DetailsNode(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 23:08:51 +08:00
										 |  |  | export function $isDetailsNode(node: LexicalNode | null | undefined): node is DetailsNode { | 
					
						
							| 
									
										
										
										
											2024-06-06 21:43:50 +08:00
										 |  |  |     return node instanceof DetailsNode; | 
					
						
							|  |  |  | } |