-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlexical_base_controller.ts
97 lines (81 loc) · 2.88 KB
/
lexical_base_controller.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* Don't use this controller! It's to illustrate the issues outlined in the README.
* It's designed to be extended by a subclass to extend the Lexical plugins and configuration whilst providing a stable base.
*/
import { Controller } from "@hotwired/stimulus"
import { $getRoot, $insertNodes, createEditor, CreateEditorArgs, LexicalEditor } from 'lexical';
import {$generateHtmlFromNodes, $generateNodesFromDOM} from '@lexical/html';
export default class LexicalBaseController extends Controller {
static targets = ["editor", "input"]
/**
* The element to render the editor within.
*/
declare readonly editorTarget: HTMLElement;
/**
* The input field to output the rendered from the editor HTML to.
*/
declare readonly inputTarget: HTMLInputElement;
editor: LexicalEditor;
listeners: (()=>void)[] = []
connect() {
this.initEditor()
this.loadInitialState()
this.registerPlugins();
this.registerUpdateListener()
}
initEditor() {
this.editor = createEditor(this.config());
this.editor.setRootElement(this.editorTarget);
}
/**
* Load the HTML markup into the editor.
* @param html Pass a string of HTML here to initialize the editor with the given markup. If this value is falsey, the HTML markup is read from the inputTarget's value.
*/
loadInitialState(html?: string) {
this.editor.update(() => {
// In the browser you can use the native DOMParser API to parse the HTML string.
const parser = new DOMParser();
const dom = parser.parseFromString(html || this.inputTarget.value, "text/html");
// Once you have the DOM instance it's easy to generate LexicalNodes.
const nodes = $generateNodesFromDOM(this.editor, dom);
// Select the root
$getRoot().select();
// Insert them at a selection.
$insertNodes(nodes);
});
}
registerUpdateListener() {
this.listeners.push(
this.editor.registerUpdateListener(({editorState}) => {
editorState.read(() => {
const htmlString = $generateHtmlFromNodes(this.editor, null);
this.inputTarget.value = htmlString;
})
})
)
}
/**
* Override this method to register Lexical plugins.
* Please ensure to use `this.listeners.push(<registration method callback>)` so they are cleaned up properly when unmounting.
*/
registerPlugins() {}
/**
* The configuration to pass to `createEditor`.
* @returns The configuration object.
*/
config(): CreateEditorArgs {
throw new Error('Please implement the #config method in your subclassed controller. This method should return the configuration to pass to Lexical.')
}
disconnect() {
this.cleanup()
this.clearListeners()
}
/**
* Perform any clean up you wish to before the editor is unmounted.
*/
cleanup() {}
clearListeners() {
this.listeners.forEach(listener => listener())
this.listeners = [];
}
}