@ekz/lexical-plain-text 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ var lexicalClipboard = require('@ekz/lexical-clipboard');
12
+ var lexicalDragon = require('@ekz/lexical-dragon');
13
+ var lexicalSelection = require('@ekz/lexical-selection');
14
+ var lexicalUtils = require('@ekz/lexical-utils');
15
+ var lexical = require('@ekz/lexical');
16
+
17
+ /**
18
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
19
+ *
20
+ * This source code is licensed under the MIT license found in the
21
+ * LICENSE file in the root directory of this source tree.
22
+ *
23
+ */
24
+
25
+ const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
26
+
27
+ /**
28
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
29
+ *
30
+ * This source code is licensed under the MIT license found in the
31
+ * LICENSE file in the root directory of this source tree.
32
+ *
33
+ */
34
+
35
+ const documentMode = CAN_USE_DOM && 'documentMode' in document ? document.documentMode : null;
36
+ const IS_APPLE = CAN_USE_DOM && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
37
+ const CAN_USE_BEFORE_INPUT = CAN_USE_DOM && 'InputEvent' in window && !documentMode ? 'getTargetRanges' in new window.InputEvent('input') : false;
38
+ const IS_SAFARI = CAN_USE_DOM && /Version\/[\d.]+.*Safari/.test(navigator.userAgent);
39
+ const IS_IOS = CAN_USE_DOM && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
40
+
41
+ // Keep these in case we need to use them in the future.
42
+ // export const IS_WINDOWS: boolean = CAN_USE_DOM && /Win/.test(navigator.platform);
43
+ const IS_CHROME = CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent);
44
+ const IS_APPLE_WEBKIT = CAN_USE_DOM && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && IS_APPLE && !IS_CHROME;
45
+
46
+ /**
47
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
48
+ *
49
+ * This source code is licensed under the MIT license found in the
50
+ * LICENSE file in the root directory of this source tree.
51
+ *
52
+ */
53
+
54
+ function onCopyForPlainText(event, editor) {
55
+ editor.update(() => {
56
+ if (event !== null) {
57
+ const clipboardData = lexicalUtils.objectKlassEquals(event, KeyboardEvent) ? null : event.clipboardData;
58
+ const selection = lexical.$getSelection();
59
+ if (selection !== null && !selection.isCollapsed() && clipboardData != null) {
60
+ event.preventDefault();
61
+ const htmlString = lexicalClipboard.$getHtmlContent(editor);
62
+ if (htmlString !== null) {
63
+ clipboardData.setData('text/html', htmlString);
64
+ }
65
+ clipboardData.setData('text/plain', selection.getTextContent());
66
+ }
67
+ }
68
+ });
69
+ }
70
+ function onPasteForPlainText(event, editor) {
71
+ event.preventDefault();
72
+ editor.update(() => {
73
+ const selection = lexical.$getSelection();
74
+ const clipboardData = lexicalUtils.objectKlassEquals(event, ClipboardEvent) ? event.clipboardData : null;
75
+ if (clipboardData != null && lexical.$isRangeSelection(selection)) {
76
+ lexicalClipboard.$insertDataTransferForPlainText(clipboardData, selection);
77
+ }
78
+ }, {
79
+ tag: lexical.PASTE_TAG
80
+ });
81
+ }
82
+ function onCutForPlainText(event, editor) {
83
+ onCopyForPlainText(event, editor);
84
+ editor.update(() => {
85
+ const selection = lexical.$getSelection();
86
+ if (lexical.$isRangeSelection(selection)) {
87
+ selection.removeText();
88
+ }
89
+ });
90
+ }
91
+ function registerPlainText(editor) {
92
+ const removeListener = lexicalUtils.mergeRegister(editor.registerCommand(lexical.DELETE_CHARACTER_COMMAND, isBackward => {
93
+ const selection = lexical.$getSelection();
94
+ if (!lexical.$isRangeSelection(selection)) {
95
+ return false;
96
+ }
97
+ selection.deleteCharacter(isBackward);
98
+ return true;
99
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.DELETE_WORD_COMMAND, isBackward => {
100
+ const selection = lexical.$getSelection();
101
+ if (!lexical.$isRangeSelection(selection)) {
102
+ return false;
103
+ }
104
+ selection.deleteWord(isBackward);
105
+ return true;
106
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.DELETE_LINE_COMMAND, isBackward => {
107
+ const selection = lexical.$getSelection();
108
+ if (!lexical.$isRangeSelection(selection)) {
109
+ return false;
110
+ }
111
+ selection.deleteLine(isBackward);
112
+ return true;
113
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.CONTROLLED_TEXT_INSERTION_COMMAND, eventOrText => {
114
+ const selection = lexical.$getSelection();
115
+ if (!lexical.$isRangeSelection(selection)) {
116
+ return false;
117
+ }
118
+ if (typeof eventOrText === 'string') {
119
+ selection.insertText(eventOrText);
120
+ } else {
121
+ const dataTransfer = eventOrText.dataTransfer;
122
+ if (dataTransfer != null) {
123
+ lexicalClipboard.$insertDataTransferForPlainText(dataTransfer, selection);
124
+ } else {
125
+ const data = eventOrText.data;
126
+ if (data) {
127
+ selection.insertText(data);
128
+ }
129
+ }
130
+ }
131
+ return true;
132
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.REMOVE_TEXT_COMMAND, () => {
133
+ const selection = lexical.$getSelection();
134
+ if (!lexical.$isRangeSelection(selection)) {
135
+ return false;
136
+ }
137
+ selection.removeText();
138
+ return true;
139
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.INSERT_LINE_BREAK_COMMAND, selectStart => {
140
+ const selection = lexical.$getSelection();
141
+ if (!lexical.$isRangeSelection(selection)) {
142
+ return false;
143
+ }
144
+ selection.insertLineBreak(selectStart);
145
+ return true;
146
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.INSERT_PARAGRAPH_COMMAND, () => {
147
+ const selection = lexical.$getSelection();
148
+ if (!lexical.$isRangeSelection(selection)) {
149
+ return false;
150
+ }
151
+ selection.insertLineBreak();
152
+ return true;
153
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.KEY_ARROW_LEFT_COMMAND, payload => {
154
+ const selection = lexical.$getSelection();
155
+ if (!lexical.$isRangeSelection(selection)) {
156
+ return false;
157
+ }
158
+ const event = payload;
159
+ const isHoldingShift = event.shiftKey;
160
+ if (lexicalSelection.$shouldOverrideDefaultCharacterSelection(selection, true)) {
161
+ event.preventDefault();
162
+ lexicalSelection.$moveCharacter(selection, isHoldingShift, true);
163
+ return true;
164
+ }
165
+ return false;
166
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.KEY_ARROW_RIGHT_COMMAND, payload => {
167
+ const selection = lexical.$getSelection();
168
+ if (!lexical.$isRangeSelection(selection)) {
169
+ return false;
170
+ }
171
+ const event = payload;
172
+ const isHoldingShift = event.shiftKey;
173
+ if (lexicalSelection.$shouldOverrideDefaultCharacterSelection(selection, false)) {
174
+ event.preventDefault();
175
+ lexicalSelection.$moveCharacter(selection, isHoldingShift, false);
176
+ return true;
177
+ }
178
+ return false;
179
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.KEY_BACKSPACE_COMMAND, event => {
180
+ const selection = lexical.$getSelection();
181
+ if (!lexical.$isRangeSelection(selection)) {
182
+ return false;
183
+ }
184
+
185
+ // Exception handling for iOS native behavior instead of Lexical's behavior when using Korean on iOS devices.
186
+ // more details - https://github.com/facebook/lexical/issues/5841
187
+ if (IS_IOS && navigator.language === 'ko-KR') {
188
+ return false;
189
+ }
190
+ event.preventDefault();
191
+ return editor.dispatchCommand(lexical.DELETE_CHARACTER_COMMAND, true);
192
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.KEY_DELETE_COMMAND, event => {
193
+ const selection = lexical.$getSelection();
194
+ if (!lexical.$isRangeSelection(selection)) {
195
+ return false;
196
+ }
197
+ event.preventDefault();
198
+ return editor.dispatchCommand(lexical.DELETE_CHARACTER_COMMAND, false);
199
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.KEY_ENTER_COMMAND, event => {
200
+ const selection = lexical.$getSelection();
201
+ if (!lexical.$isRangeSelection(selection)) {
202
+ return false;
203
+ }
204
+ if (event !== null) {
205
+ // If we have beforeinput, then we can avoid blocking
206
+ // the default behavior. This ensures that the iOS can
207
+ // intercept that we're actually inserting a paragraph,
208
+ // and autocomplete, autocapitalize etc work as intended.
209
+ // This can also cause a strange performance issue in
210
+ // Safari, where there is a noticeable pause due to
211
+ // preventing the key down of enter.
212
+ if ((IS_IOS || IS_SAFARI || IS_APPLE_WEBKIT) && CAN_USE_BEFORE_INPUT) {
213
+ return false;
214
+ }
215
+ event.preventDefault();
216
+ }
217
+ return editor.dispatchCommand(lexical.INSERT_LINE_BREAK_COMMAND, false);
218
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.SELECT_ALL_COMMAND, () => {
219
+ lexical.$selectAll();
220
+ return true;
221
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.COPY_COMMAND, event => {
222
+ const selection = lexical.$getSelection();
223
+ if (!lexical.$isRangeSelection(selection)) {
224
+ return false;
225
+ }
226
+ onCopyForPlainText(event, editor);
227
+ return true;
228
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.CUT_COMMAND, event => {
229
+ const selection = lexical.$getSelection();
230
+ if (!lexical.$isRangeSelection(selection)) {
231
+ return false;
232
+ }
233
+ onCutForPlainText(event, editor);
234
+ return true;
235
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.PASTE_COMMAND, event => {
236
+ const selection = lexical.$getSelection();
237
+ if (!lexical.$isRangeSelection(selection)) {
238
+ return false;
239
+ }
240
+ onPasteForPlainText(event, editor);
241
+ return true;
242
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.DROP_COMMAND, event => {
243
+ const selection = lexical.$getSelection();
244
+ if (!lexical.$isRangeSelection(selection)) {
245
+ return false;
246
+ }
247
+
248
+ // TODO: Make drag and drop work at some point.
249
+ event.preventDefault();
250
+ return true;
251
+ }, lexical.COMMAND_PRIORITY_EDITOR), editor.registerCommand(lexical.DRAGSTART_COMMAND, event => {
252
+ const selection = lexical.$getSelection();
253
+ if (!lexical.$isRangeSelection(selection)) {
254
+ return false;
255
+ }
256
+
257
+ // TODO: Make drag and drop work at some point.
258
+ event.preventDefault();
259
+ return true;
260
+ }, lexical.COMMAND_PRIORITY_EDITOR));
261
+ return removeListener;
262
+ }
263
+
264
+ /**
265
+ * An extension to register \@lexical/plain-text behavior
266
+ */
267
+ const PlainTextExtension = lexical.defineExtension({
268
+ conflictsWith: ['@ekz/lexical-rich-text'],
269
+ dependencies: [lexicalDragon.DragonExtension],
270
+ name: '@ekz/lexical-plain-text',
271
+ register: registerPlainText
272
+ });
273
+
274
+ exports.PlainTextExtension = PlainTextExtension;
275
+ exports.registerPlainText = registerPlainText;
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { $insertDataTransferForPlainText, $getHtmlContent } from '@ekz/lexical-clipboard';
10
+ import { DragonExtension } from '@ekz/lexical-dragon';
11
+ import { $shouldOverrideDefaultCharacterSelection, $moveCharacter } from '@ekz/lexical-selection';
12
+ import { mergeRegister, objectKlassEquals } from '@ekz/lexical-utils';
13
+ import { defineExtension, DELETE_CHARACTER_COMMAND, $getSelection, $isRangeSelection, COMMAND_PRIORITY_EDITOR, DELETE_WORD_COMMAND, DELETE_LINE_COMMAND, CONTROLLED_TEXT_INSERTION_COMMAND, REMOVE_TEXT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_ENTER_COMMAND, SELECT_ALL_COMMAND, $selectAll, COPY_COMMAND, CUT_COMMAND, PASTE_COMMAND, DROP_COMMAND, DRAGSTART_COMMAND, PASTE_TAG } from '@ekz/lexical';
14
+
15
+ /**
16
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
17
+ *
18
+ * This source code is licensed under the MIT license found in the
19
+ * LICENSE file in the root directory of this source tree.
20
+ *
21
+ */
22
+
23
+ const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
24
+
25
+ /**
26
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
27
+ *
28
+ * This source code is licensed under the MIT license found in the
29
+ * LICENSE file in the root directory of this source tree.
30
+ *
31
+ */
32
+
33
+ const documentMode = CAN_USE_DOM && 'documentMode' in document ? document.documentMode : null;
34
+ const IS_APPLE = CAN_USE_DOM && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
35
+ const CAN_USE_BEFORE_INPUT = CAN_USE_DOM && 'InputEvent' in window && !documentMode ? 'getTargetRanges' in new window.InputEvent('input') : false;
36
+ const IS_SAFARI = CAN_USE_DOM && /Version\/[\d.]+.*Safari/.test(navigator.userAgent);
37
+ const IS_IOS = CAN_USE_DOM && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
38
+
39
+ // Keep these in case we need to use them in the future.
40
+ // export const IS_WINDOWS: boolean = CAN_USE_DOM && /Win/.test(navigator.platform);
41
+ const IS_CHROME = CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent);
42
+ const IS_APPLE_WEBKIT = CAN_USE_DOM && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && IS_APPLE && !IS_CHROME;
43
+
44
+ /**
45
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
46
+ *
47
+ * This source code is licensed under the MIT license found in the
48
+ * LICENSE file in the root directory of this source tree.
49
+ *
50
+ */
51
+
52
+ function onCopyForPlainText(event, editor) {
53
+ editor.update(() => {
54
+ if (event !== null) {
55
+ const clipboardData = objectKlassEquals(event, KeyboardEvent) ? null : event.clipboardData;
56
+ const selection = $getSelection();
57
+ if (selection !== null && !selection.isCollapsed() && clipboardData != null) {
58
+ event.preventDefault();
59
+ const htmlString = $getHtmlContent(editor);
60
+ if (htmlString !== null) {
61
+ clipboardData.setData('text/html', htmlString);
62
+ }
63
+ clipboardData.setData('text/plain', selection.getTextContent());
64
+ }
65
+ }
66
+ });
67
+ }
68
+ function onPasteForPlainText(event, editor) {
69
+ event.preventDefault();
70
+ editor.update(() => {
71
+ const selection = $getSelection();
72
+ const clipboardData = objectKlassEquals(event, ClipboardEvent) ? event.clipboardData : null;
73
+ if (clipboardData != null && $isRangeSelection(selection)) {
74
+ $insertDataTransferForPlainText(clipboardData, selection);
75
+ }
76
+ }, {
77
+ tag: PASTE_TAG
78
+ });
79
+ }
80
+ function onCutForPlainText(event, editor) {
81
+ onCopyForPlainText(event, editor);
82
+ editor.update(() => {
83
+ const selection = $getSelection();
84
+ if ($isRangeSelection(selection)) {
85
+ selection.removeText();
86
+ }
87
+ });
88
+ }
89
+ function registerPlainText(editor) {
90
+ const removeListener = mergeRegister(editor.registerCommand(DELETE_CHARACTER_COMMAND, isBackward => {
91
+ const selection = $getSelection();
92
+ if (!$isRangeSelection(selection)) {
93
+ return false;
94
+ }
95
+ selection.deleteCharacter(isBackward);
96
+ return true;
97
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(DELETE_WORD_COMMAND, isBackward => {
98
+ const selection = $getSelection();
99
+ if (!$isRangeSelection(selection)) {
100
+ return false;
101
+ }
102
+ selection.deleteWord(isBackward);
103
+ return true;
104
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(DELETE_LINE_COMMAND, isBackward => {
105
+ const selection = $getSelection();
106
+ if (!$isRangeSelection(selection)) {
107
+ return false;
108
+ }
109
+ selection.deleteLine(isBackward);
110
+ return true;
111
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(CONTROLLED_TEXT_INSERTION_COMMAND, eventOrText => {
112
+ const selection = $getSelection();
113
+ if (!$isRangeSelection(selection)) {
114
+ return false;
115
+ }
116
+ if (typeof eventOrText === 'string') {
117
+ selection.insertText(eventOrText);
118
+ } else {
119
+ const dataTransfer = eventOrText.dataTransfer;
120
+ if (dataTransfer != null) {
121
+ $insertDataTransferForPlainText(dataTransfer, selection);
122
+ } else {
123
+ const data = eventOrText.data;
124
+ if (data) {
125
+ selection.insertText(data);
126
+ }
127
+ }
128
+ }
129
+ return true;
130
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(REMOVE_TEXT_COMMAND, () => {
131
+ const selection = $getSelection();
132
+ if (!$isRangeSelection(selection)) {
133
+ return false;
134
+ }
135
+ selection.removeText();
136
+ return true;
137
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(INSERT_LINE_BREAK_COMMAND, selectStart => {
138
+ const selection = $getSelection();
139
+ if (!$isRangeSelection(selection)) {
140
+ return false;
141
+ }
142
+ selection.insertLineBreak(selectStart);
143
+ return true;
144
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(INSERT_PARAGRAPH_COMMAND, () => {
145
+ const selection = $getSelection();
146
+ if (!$isRangeSelection(selection)) {
147
+ return false;
148
+ }
149
+ selection.insertLineBreak();
150
+ return true;
151
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_ARROW_LEFT_COMMAND, payload => {
152
+ const selection = $getSelection();
153
+ if (!$isRangeSelection(selection)) {
154
+ return false;
155
+ }
156
+ const event = payload;
157
+ const isHoldingShift = event.shiftKey;
158
+ if ($shouldOverrideDefaultCharacterSelection(selection, true)) {
159
+ event.preventDefault();
160
+ $moveCharacter(selection, isHoldingShift, true);
161
+ return true;
162
+ }
163
+ return false;
164
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_ARROW_RIGHT_COMMAND, payload => {
165
+ const selection = $getSelection();
166
+ if (!$isRangeSelection(selection)) {
167
+ return false;
168
+ }
169
+ const event = payload;
170
+ const isHoldingShift = event.shiftKey;
171
+ if ($shouldOverrideDefaultCharacterSelection(selection, false)) {
172
+ event.preventDefault();
173
+ $moveCharacter(selection, isHoldingShift, false);
174
+ return true;
175
+ }
176
+ return false;
177
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_BACKSPACE_COMMAND, event => {
178
+ const selection = $getSelection();
179
+ if (!$isRangeSelection(selection)) {
180
+ return false;
181
+ }
182
+
183
+ // Exception handling for iOS native behavior instead of Lexical's behavior when using Korean on iOS devices.
184
+ // more details - https://github.com/facebook/lexical/issues/5841
185
+ if (IS_IOS && navigator.language === 'ko-KR') {
186
+ return false;
187
+ }
188
+ event.preventDefault();
189
+ return editor.dispatchCommand(DELETE_CHARACTER_COMMAND, true);
190
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_DELETE_COMMAND, event => {
191
+ const selection = $getSelection();
192
+ if (!$isRangeSelection(selection)) {
193
+ return false;
194
+ }
195
+ event.preventDefault();
196
+ return editor.dispatchCommand(DELETE_CHARACTER_COMMAND, false);
197
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_ENTER_COMMAND, event => {
198
+ const selection = $getSelection();
199
+ if (!$isRangeSelection(selection)) {
200
+ return false;
201
+ }
202
+ if (event !== null) {
203
+ // If we have beforeinput, then we can avoid blocking
204
+ // the default behavior. This ensures that the iOS can
205
+ // intercept that we're actually inserting a paragraph,
206
+ // and autocomplete, autocapitalize etc work as intended.
207
+ // This can also cause a strange performance issue in
208
+ // Safari, where there is a noticeable pause due to
209
+ // preventing the key down of enter.
210
+ if ((IS_IOS || IS_SAFARI || IS_APPLE_WEBKIT) && CAN_USE_BEFORE_INPUT) {
211
+ return false;
212
+ }
213
+ event.preventDefault();
214
+ }
215
+ return editor.dispatchCommand(INSERT_LINE_BREAK_COMMAND, false);
216
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(SELECT_ALL_COMMAND, () => {
217
+ $selectAll();
218
+ return true;
219
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(COPY_COMMAND, event => {
220
+ const selection = $getSelection();
221
+ if (!$isRangeSelection(selection)) {
222
+ return false;
223
+ }
224
+ onCopyForPlainText(event, editor);
225
+ return true;
226
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(CUT_COMMAND, event => {
227
+ const selection = $getSelection();
228
+ if (!$isRangeSelection(selection)) {
229
+ return false;
230
+ }
231
+ onCutForPlainText(event, editor);
232
+ return true;
233
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(PASTE_COMMAND, event => {
234
+ const selection = $getSelection();
235
+ if (!$isRangeSelection(selection)) {
236
+ return false;
237
+ }
238
+ onPasteForPlainText(event, editor);
239
+ return true;
240
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(DROP_COMMAND, event => {
241
+ const selection = $getSelection();
242
+ if (!$isRangeSelection(selection)) {
243
+ return false;
244
+ }
245
+
246
+ // TODO: Make drag and drop work at some point.
247
+ event.preventDefault();
248
+ return true;
249
+ }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(DRAGSTART_COMMAND, event => {
250
+ const selection = $getSelection();
251
+ if (!$isRangeSelection(selection)) {
252
+ return false;
253
+ }
254
+
255
+ // TODO: Make drag and drop work at some point.
256
+ event.preventDefault();
257
+ return true;
258
+ }, COMMAND_PRIORITY_EDITOR));
259
+ return removeListener;
260
+ }
261
+
262
+ /**
263
+ * An extension to register \@lexical/plain-text behavior
264
+ */
265
+ const PlainTextExtension = defineExtension({
266
+ conflictsWith: ['@ekz/lexical-rich-text'],
267
+ dependencies: [DragonExtension],
268
+ name: '@ekz/lexical-plain-text',
269
+ register: registerPlainText
270
+ });
271
+
272
+ export { PlainTextExtension, registerPlainText };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ 'use strict'
10
+ const EkzLexicalPlainText = process.env.NODE_ENV !== 'production' ? require('./EkzLexicalPlainText.dev.js') : require('./EkzLexicalPlainText.prod.js');
11
+ module.exports = EkzLexicalPlainText;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import * as modDev from './EkzLexicalPlainText.dev.mjs';
10
+ import * as modProd from './EkzLexicalPlainText.prod.mjs';
11
+ const mod = process.env.NODE_ENV !== 'production' ? modDev : modProd;
12
+ export const PlainTextExtension = mod.PlainTextExtension;
13
+ export const registerPlainText = mod.registerPlainText;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ const mod = await (process.env.NODE_ENV !== 'production' ? import('./EkzLexicalPlainText.dev.mjs') : import('./EkzLexicalPlainText.prod.mjs'));
10
+ export const PlainTextExtension = mod.PlainTextExtension;
11
+ export const registerPlainText = mod.registerPlainText;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ "use strict";var e=require("@ekz/lexical-clipboard"),t=require("@ekz/lexical-dragon"),n=require("@ekz/lexical-selection"),i=require("@ekz/lexical-utils"),r=require("@ekz/lexical");const o="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,a=o&&"documentMode"in document?document.documentMode:null,l=o&&/Mac|iPod|iPhone|iPad/.test(navigator.platform),s=!(!o||!("InputEvent"in window)||a)&&"getTargetRanges"in new window.InputEvent("input"),c=o&&/Version\/[\d.]+.*Safari/.test(navigator.userAgent),R=o&&/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream,O=o&&/^(?=.*Chrome).*/i.test(navigator.userAgent),D=o&&/AppleWebKit\/[\d.]+/.test(navigator.userAgent)&&l&&!O;function M(t,n){n.update(()=>{if(null!==t){const o=i.objectKlassEquals(t,KeyboardEvent)?null:t.clipboardData,a=r.$getSelection();if(null!==a&&!a.isCollapsed()&&null!=o){t.preventDefault();const i=e.$getHtmlContent(n);null!==i&&o.setData("text/html",i),o.setData("text/plain",a.getTextContent())}}})}function g(t){return i.mergeRegister(t.registerCommand(r.DELETE_CHARACTER_COMMAND,e=>{const t=r.$getSelection();return!!r.$isRangeSelection(t)&&(t.deleteCharacter(e),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.DELETE_WORD_COMMAND,e=>{const t=r.$getSelection();return!!r.$isRangeSelection(t)&&(t.deleteWord(e),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.DELETE_LINE_COMMAND,e=>{const t=r.$getSelection();return!!r.$isRangeSelection(t)&&(t.deleteLine(e),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.CONTROLLED_TEXT_INSERTION_COMMAND,t=>{const n=r.$getSelection();if(!r.$isRangeSelection(n))return!1;if("string"==typeof t)n.insertText(t);else{const i=t.dataTransfer;if(null!=i)e.$insertDataTransferForPlainText(i,n);else{const e=t.data;e&&n.insertText(e)}}return!0},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.REMOVE_TEXT_COMMAND,()=>{const e=r.$getSelection();return!!r.$isRangeSelection(e)&&(e.removeText(),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.INSERT_LINE_BREAK_COMMAND,e=>{const t=r.$getSelection();return!!r.$isRangeSelection(t)&&(t.insertLineBreak(e),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.INSERT_PARAGRAPH_COMMAND,()=>{const e=r.$getSelection();return!!r.$isRangeSelection(e)&&(e.insertLineBreak(),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.KEY_ARROW_LEFT_COMMAND,e=>{const t=r.$getSelection();if(!r.$isRangeSelection(t))return!1;const i=e,o=i.shiftKey;return!!n.$shouldOverrideDefaultCharacterSelection(t,!0)&&(i.preventDefault(),n.$moveCharacter(t,o,!0),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.KEY_ARROW_RIGHT_COMMAND,e=>{const t=r.$getSelection();if(!r.$isRangeSelection(t))return!1;const i=e,o=i.shiftKey;return!!n.$shouldOverrideDefaultCharacterSelection(t,!1)&&(i.preventDefault(),n.$moveCharacter(t,o,!1),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.KEY_BACKSPACE_COMMAND,e=>{const n=r.$getSelection();return!!r.$isRangeSelection(n)&&((!R||"ko-KR"!==navigator.language)&&(e.preventDefault(),t.dispatchCommand(r.DELETE_CHARACTER_COMMAND,!0)))},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.KEY_DELETE_COMMAND,e=>{const n=r.$getSelection();return!!r.$isRangeSelection(n)&&(e.preventDefault(),t.dispatchCommand(r.DELETE_CHARACTER_COMMAND,!1))},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.KEY_ENTER_COMMAND,e=>{const n=r.$getSelection();if(!r.$isRangeSelection(n))return!1;if(null!==e){if((R||c||D)&&s)return!1;e.preventDefault()}return t.dispatchCommand(r.INSERT_LINE_BREAK_COMMAND,!1)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.SELECT_ALL_COMMAND,()=>(r.$selectAll(),!0),r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.COPY_COMMAND,e=>{const n=r.$getSelection();return!!r.$isRangeSelection(n)&&(M(e,t),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.CUT_COMMAND,e=>{const n=r.$getSelection();return!!r.$isRangeSelection(n)&&(function(e,t){M(e,t),t.update(()=>{const e=r.$getSelection();r.$isRangeSelection(e)&&e.removeText()})}(e,t),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.PASTE_COMMAND,n=>{const o=r.$getSelection();return!!r.$isRangeSelection(o)&&(function(t,n){t.preventDefault(),n.update(()=>{const n=r.$getSelection(),o=i.objectKlassEquals(t,ClipboardEvent)?t.clipboardData:null;null!=o&&r.$isRangeSelection(n)&&e.$insertDataTransferForPlainText(o,n)},{tag:r.PASTE_TAG})}(n,t),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.DROP_COMMAND,e=>{const t=r.$getSelection();return!!r.$isRangeSelection(t)&&(e.preventDefault(),!0)},r.COMMAND_PRIORITY_EDITOR),t.registerCommand(r.DRAGSTART_COMMAND,e=>{const t=r.$getSelection();return!!r.$isRangeSelection(t)&&(e.preventDefault(),!0)},r.COMMAND_PRIORITY_EDITOR))}const C=r.defineExtension({conflictsWith:["@ekz/lexical-rich-text"],dependencies:[t.DragonExtension],name:"@ekz/lexical-plain-text",register:g});exports.PlainTextExtension=C,exports.registerPlainText=g;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import{$insertDataTransferForPlainText as e,$getHtmlContent as t}from"@ekz/lexical-clipboard";import{DragonExtension as n}from"@ekz/lexical-dragon";import{$shouldOverrideDefaultCharacterSelection as r,$moveCharacter as o}from"@ekz/lexical-selection";import{mergeRegister as i,objectKlassEquals as a}from"@ekz/lexical-utils";import{defineExtension as s,DELETE_CHARACTER_COMMAND as d,$getSelection as m,$isRangeSelection as u,COMMAND_PRIORITY_EDITOR as l,DELETE_WORD_COMMAND as c,DELETE_LINE_COMMAND as g,CONTROLLED_TEXT_INSERTION_COMMAND as f,REMOVE_TEXT_COMMAND as p,INSERT_LINE_BREAK_COMMAND as C,INSERT_PARAGRAPH_COMMAND as v,KEY_ARROW_LEFT_COMMAND as x,KEY_ARROW_RIGHT_COMMAND as w,KEY_BACKSPACE_COMMAND as D,KEY_DELETE_COMMAND as h,KEY_ENTER_COMMAND as k,SELECT_ALL_COMMAND as z,$selectAll as T,COPY_COMMAND as b,CUT_COMMAND as P,PASTE_COMMAND as y,DROP_COMMAND as A,DRAGSTART_COMMAND as E,PASTE_TAG as K}from"@ekz/lexical";const M="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,L=M&&"documentMode"in document?document.documentMode:null,S=M&&/Mac|iPod|iPhone|iPad/.test(navigator.platform),W=!(!M||!("InputEvent"in window)||L)&&"getTargetRanges"in new window.InputEvent("input"),B=M&&/Version\/[\d.]+.*Safari/.test(navigator.userAgent),I=M&&/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream,R=M&&/^(?=.*Chrome).*/i.test(navigator.userAgent),V=M&&/AppleWebKit\/[\d.]+/.test(navigator.userAgent)&&S&&!R;function j(e,n){n.update(()=>{if(null!==e){const r=a(e,KeyboardEvent)?null:e.clipboardData,o=m();if(null!==o&&!o.isCollapsed()&&null!=r){e.preventDefault();const i=t(n);null!==i&&r.setData("text/html",i),r.setData("text/plain",o.getTextContent())}}})}function q(t){return i(t.registerCommand(d,e=>{const t=m();return!!u(t)&&(t.deleteCharacter(e),!0)},l),t.registerCommand(c,e=>{const t=m();return!!u(t)&&(t.deleteWord(e),!0)},l),t.registerCommand(g,e=>{const t=m();return!!u(t)&&(t.deleteLine(e),!0)},l),t.registerCommand(f,t=>{const n=m();if(!u(n))return!1;if("string"==typeof t)n.insertText(t);else{const r=t.dataTransfer;if(null!=r)e(r,n);else{const e=t.data;e&&n.insertText(e)}}return!0},l),t.registerCommand(p,()=>{const e=m();return!!u(e)&&(e.removeText(),!0)},l),t.registerCommand(C,e=>{const t=m();return!!u(t)&&(t.insertLineBreak(e),!0)},l),t.registerCommand(v,()=>{const e=m();return!!u(e)&&(e.insertLineBreak(),!0)},l),t.registerCommand(x,e=>{const t=m();if(!u(t))return!1;const n=e,i=n.shiftKey;return!!r(t,!0)&&(n.preventDefault(),o(t,i,!0),!0)},l),t.registerCommand(w,e=>{const t=m();if(!u(t))return!1;const n=e,i=n.shiftKey;return!!r(t,!1)&&(n.preventDefault(),o(t,i,!1),!0)},l),t.registerCommand(D,e=>{const n=m();return!!u(n)&&((!I||"ko-KR"!==navigator.language)&&(e.preventDefault(),t.dispatchCommand(d,!0)))},l),t.registerCommand(h,e=>{const n=m();return!!u(n)&&(e.preventDefault(),t.dispatchCommand(d,!1))},l),t.registerCommand(k,e=>{const n=m();if(!u(n))return!1;if(null!==e){if((I||B||V)&&W)return!1;e.preventDefault()}return t.dispatchCommand(C,!1)},l),t.registerCommand(z,()=>(T(),!0),l),t.registerCommand(b,e=>{const n=m();return!!u(n)&&(j(e,t),!0)},l),t.registerCommand(P,e=>{const n=m();return!!u(n)&&(function(e,t){j(e,t),t.update(()=>{const e=m();u(e)&&e.removeText()})}(e,t),!0)},l),t.registerCommand(y,n=>{const r=m();return!!u(r)&&(function(t,n){t.preventDefault(),n.update(()=>{const n=m(),r=a(t,ClipboardEvent)?t.clipboardData:null;null!=r&&u(n)&&e(r,n)},{tag:K})}(n,t),!0)},l),t.registerCommand(A,e=>{const t=m();return!!u(t)&&(e.preventDefault(),!0)},l),t.registerCommand(E,e=>{const t=m();return!!u(t)&&(e.preventDefault(),!0)},l))}const F=s({conflictsWith:["@ekz/lexical-rich-text"],dependencies:[n],name:"@ekz/lexical-plain-text",register:q});export{F as PlainTextExtension,q as registerPlainText};
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Meta Platforms, Inc. and affiliates.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ */
9
+ import type {LexicalExtension, ExtensionConfigBase, EditorState, LexicalEditor} from '@ekz/lexical';
10
+
11
+ declare export function registerPlainText(editor: LexicalEditor): () => void;
12
+
13
+ declare export var PlainTextExtension: LexicalExtension<ExtensionConfigBase, "@ekz/lexical-plain-text", void, void>;
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # `@lexical/plain-text`
2
+
3
+ This package provides a starting point for Lexical users by registering listeners for a set of basic commands that cover simple text-editing behavior such as entering text, deleting characters, copy + paste, or changing the selection with arrow keys.
4
+
5
+ You can use this package as a starting point, and then add additional command listeners to customize the functionality of your editor. If you want to add rich-text features, such as headings, blockquotes, or formatted text, you may want to consider using [@lexical/rich-text](https://lexical.dev/docs/packages/lexical-rich-text) instead.
package/index.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalEditor } from '@ekz/lexical';
9
+ export declare function registerPlainText(editor: LexicalEditor): () => void;
10
+ /**
11
+ * An extension to register \@lexical/plain-text behavior
12
+ */
13
+ export declare const PlainTextExtension: import("@ekz/lexical").LexicalExtension<import("@ekz/lexical").ExtensionConfigBase, "@ekz/lexical-plain-text", unknown, unknown>;
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@ekz/lexical-plain-text",
3
+ "description": "This package contains plain text helpers for Lexical.",
4
+ "keywords": [
5
+ "lexical",
6
+ "editor",
7
+ "plain-text"
8
+ ],
9
+ "license": "MIT",
10
+ "version": "0.40.0",
11
+ "main": "LexicalPlainText.js",
12
+ "types": "index.d.ts",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/facebook/lexical.git",
16
+ "directory": "packages/lexical-plain-text"
17
+ },
18
+ "module": "LexicalPlainText.mjs",
19
+ "sideEffects": false,
20
+ "exports": {
21
+ ".": {
22
+ "import": {
23
+ "types": "./index.d.ts",
24
+ "development": "./LexicalPlainText.dev.mjs",
25
+ "production": "./LexicalPlainText.prod.mjs",
26
+ "node": "./LexicalPlainText.node.mjs",
27
+ "default": "./LexicalPlainText.mjs"
28
+ },
29
+ "require": {
30
+ "types": "./index.d.ts",
31
+ "development": "./LexicalPlainText.dev.js",
32
+ "production": "./LexicalPlainText.prod.js",
33
+ "default": "./LexicalPlainText.js"
34
+ }
35
+ }
36
+ },
37
+ "dependencies": {
38
+ "@ekz/lexical-clipboard": "0.40.0",
39
+ "@ekz/lexical-dragon": "0.40.0",
40
+ "@ekz/lexical-selection": "0.40.0",
41
+ "@ekz/lexical-utils": "0.40.0",
42
+ "@ekz/lexical": "0.40.0"
43
+ }
44
+ }