@blocklet/editor 2.4.89 → 2.4.91

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.
Files changed (44) hide show
  1. package/lib/blocklet-editor-viewer.d.ts +4 -0
  2. package/lib/blocklet-editor-viewer.js +12 -0
  3. package/lib/blocklet-editor.d.ts +2 -0
  4. package/lib/blocklet-editor.js +12 -0
  5. package/lib/ext/CustomComponent/CustomComponentNode.js +1 -0
  6. package/lib/ext/CustomComponent/components/Code.js +2 -1
  7. package/lib/ext/CustomComponent/components/Field.d.ts +9 -0
  8. package/lib/ext/CustomComponent/components/Field.js +32 -0
  9. package/lib/ext/CustomComponent/components/index.d.ts +2 -0
  10. package/lib/ext/CustomComponent/components/index.js +2 -0
  11. package/lib/ext/PagesKitComponent/PagesKitComponentRenderer.js +2 -2
  12. package/lib/index.d.ts +0 -3
  13. package/lib/index.js +2 -2
  14. package/lib/main/editor-root.d.ts +2 -0
  15. package/lib/main/editor-root.js +46 -0
  16. package/lib/main/hooks/use-mobile.d.ts +4 -0
  17. package/lib/main/hooks/use-mobile.js +6 -0
  18. package/lib/main/index.css +0 -954
  19. package/lib/main/index.d.ts +3 -0
  20. package/lib/main/index.js +7 -12
  21. package/lib/main/markdown-editor/index.js +1 -9
  22. package/lib/main/nodes/PlaygroundNodes.js +0 -2
  23. package/lib/main/style/editable.css +476 -0
  24. package/lib/main/themes/code-highlight/index.d.ts +2 -32
  25. package/lib/main/themes/code-highlight/index.js +10 -65
  26. package/lib/main/themes/customTheme.js +17 -18
  27. package/lib/main/viewer/index.d.ts +5 -0
  28. package/lib/main/viewer/index.js +26 -0
  29. package/lib/main/viewer/types.d.ts +14 -0
  30. package/lib/main/viewer/types.js +1 -0
  31. package/lib/main/viewer/viewer.d.ts +3 -0
  32. package/lib/main/viewer/viewer.js +30 -0
  33. package/lib/types.d.ts +2 -1
  34. package/package.json +4 -2
  35. package/lib/main/Settings.d.ts +0 -9
  36. package/lib/main/Settings.js +0 -39
  37. package/lib/main/plugins/KeywordsPlugin/index.d.ts +0 -9
  38. package/lib/main/plugins/KeywordsPlugin/index.js +0 -38
  39. package/lib/main/plugins/PasteLogPlugin/index.d.ts +0 -9
  40. package/lib/main/plugins/PasteLogPlugin/index.js +0 -34
  41. package/lib/main/plugins/TestRecorderPlugin/index.d.ts +0 -10
  42. package/lib/main/plugins/TestRecorderPlugin/index.js +0 -340
  43. package/lib/main/ui/Switch.d.ts +0 -15
  44. package/lib/main/ui/Switch.js +0 -6
@@ -1,340 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
3
- import { $createParagraphNode, $createTextNode, $getRoot } from 'lexical';
4
- import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { IS_APPLE } from '../../../shared/environment';
6
- import useLayoutEffect from '../../../shared/useLayoutEffect';
7
- const copy = (text) => {
8
- const textArea = document.createElement('textarea');
9
- textArea.value = text || '';
10
- textArea.style.position = 'absolute';
11
- textArea.style.opacity = '0';
12
- document.body?.appendChild(textArea);
13
- textArea.focus();
14
- textArea.select();
15
- try {
16
- const result = document.execCommand('copy');
17
- // eslint-disable-next-line no-console
18
- console.log(result);
19
- }
20
- catch (error) {
21
- console.error(error);
22
- }
23
- document.body?.removeChild(textArea);
24
- };
25
- const download = (filename, text) => {
26
- const a = document.createElement('a');
27
- a.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(text || '')}`);
28
- a.setAttribute('download', filename);
29
- a.style.display = 'none';
30
- document.body?.appendChild(a);
31
- a.click();
32
- document.body?.removeChild(a);
33
- };
34
- const formatStep = (step) => {
35
- const formatOneStep = (name, value) => {
36
- switch (name) {
37
- case 'click': {
38
- return ` await page.mouse.click(${value.x}, ${value.y});`;
39
- }
40
- case 'press': {
41
- return ` await page.keyboard.press('${value}');`;
42
- }
43
- case 'keydown': {
44
- return ` await page.keyboard.keydown('${value}');`;
45
- }
46
- case 'keyup': {
47
- return ` await page.keyboard.keyup('${value}');`;
48
- }
49
- case 'type': {
50
- return ` await page.keyboard.type('${value}');`;
51
- }
52
- case 'selectAll': {
53
- return ' await selectAll(page);';
54
- }
55
- case 'snapshot': {
56
- return ` await assertHTMLSnapshot(page);
57
- await assertSelection(page, {
58
- anchorPath: [${value.anchorPath.toString()}],
59
- anchorOffset: ${value.anchorOffset},
60
- focusPath: [${value.focusPath.toString()}],
61
- focusOffset: ${value.focusOffset},
62
- });
63
- `;
64
- }
65
- default:
66
- return '';
67
- }
68
- };
69
- const formattedStep = formatOneStep(step.name, step.value);
70
- switch (step.count) {
71
- case 1:
72
- return formattedStep;
73
- case 2:
74
- return [formattedStep, formattedStep].join('\n');
75
- default:
76
- return ` await repeat(${step.count}, async () => {
77
- ${formattedStep}
78
- );`;
79
- }
80
- };
81
- export function isSelectAll(event) {
82
- return event.keyCode === 65 && (IS_APPLE ? event.metaKey : event.ctrlKey);
83
- }
84
- // stolen from LexicalSelection-test
85
- function sanitizeSelection(selection) {
86
- const { anchorNode, focusNode } = selection;
87
- let { anchorOffset, focusOffset } = selection;
88
- if (anchorOffset !== 0) {
89
- anchorOffset--;
90
- }
91
- if (focusOffset !== 0) {
92
- focusOffset--;
93
- }
94
- return { anchorNode, anchorOffset, focusNode, focusOffset };
95
- }
96
- function getPathFromNodeToEditor(node, rootElement) {
97
- let currentNode = node;
98
- const path = [];
99
- while (currentNode !== rootElement) {
100
- if (currentNode !== null && currentNode !== undefined) {
101
- path.unshift(Array.from(currentNode?.parentNode?.childNodes ?? []).indexOf(currentNode));
102
- }
103
- currentNode = currentNode?.parentNode;
104
- }
105
- return path;
106
- }
107
- const keyPresses = new Set([
108
- 'Enter',
109
- 'Backspace',
110
- 'Delete',
111
- 'Escape',
112
- 'ArrowLeft',
113
- 'ArrowRight',
114
- 'ArrowUp',
115
- 'ArrowDown',
116
- ]);
117
- function useTestRecorder(editor) {
118
- const [steps, setSteps] = useState([]);
119
- const [isRecording, setIsRecording] = useState(false);
120
- const [, setCurrentInnerHTML] = useState('');
121
- const [templatedTest, setTemplatedTest] = useState('');
122
- const previousSelectionRef = useRef(null);
123
- const skipNextSelectionChangeRef = useRef(false);
124
- const preRef = useRef(null);
125
- const getCurrentEditor = useCallback(() => {
126
- return editor;
127
- }, [editor]);
128
- const generateTestContent = useCallback(() => {
129
- const rootElement = editor.getRootElement();
130
- const browserSelection = window.getSelection();
131
- if (rootElement == null ||
132
- browserSelection == null ||
133
- browserSelection.anchorNode == null ||
134
- browserSelection.focusNode == null ||
135
- !rootElement.contains(browserSelection.anchorNode) ||
136
- !rootElement.contains(browserSelection.focusNode)) {
137
- return null;
138
- }
139
- return `
140
- /**
141
- * Copyright (c) Meta Platforms, Inc. and affiliates.
142
- *
143
- * This source code is licensed under the MIT license found in the
144
- * LICENSE file in the root directory of this source tree.
145
- *
146
- */
147
-
148
- import {
149
- initializeE2E,
150
- assertHTMLSnapshot,
151
- assertSelection,
152
- repeat,
153
- } from '../utils';
154
- import {selectAll} from '../keyboardShortcuts';
155
- import { RangeSelection } from 'lexical';
156
- import { NodeSelection } from 'lexical';
157
-
158
- describe('Test case', () => {
159
- initializeE2E((e2e) => {
160
- it('Should pass this test', async () => {
161
- const {page} = e2e;
162
-
163
- await page.focus('div[contenteditable="true"]');
164
- ${steps.map(formatStep).join('\n')}
165
- });
166
- });
167
- `;
168
- }, [editor, steps]);
169
- // just a wrapper around inserting new actions so that we can
170
- // coalesce some actions like insertText/moveNativeSelection
171
- const pushStep = useCallback((name, value) => {
172
- setSteps((currentSteps) => {
173
- // trying to group steps
174
- const currentIndex = steps.length - 1;
175
- const lastStep = steps[currentIndex];
176
- if (lastStep) {
177
- if (lastStep.name === name) {
178
- if (name === 'type') {
179
- // for typing events we just append the text
180
- return [...steps.slice(0, currentIndex), { ...lastStep, value: lastStep.value + value }];
181
- }
182
- // for other events we bump the counter if their values are the same
183
- if (lastStep.value === value) {
184
- return [...steps.slice(0, currentIndex), { ...lastStep, count: lastStep.count + 1 }];
185
- }
186
- }
187
- }
188
- // could not group, just append a new one
189
- return [...currentSteps, { count: 1, name, value }];
190
- });
191
- }, [steps, setSteps]);
192
- useLayoutEffect(() => {
193
- const onKeyDown = (event) => {
194
- if (!isRecording) {
195
- return;
196
- }
197
- const { key } = event;
198
- if (isSelectAll(event)) {
199
- pushStep('selectAll', '');
200
- }
201
- else if (keyPresses.has(key)) {
202
- pushStep('press', event.key);
203
- }
204
- else if ([...key].length > 1) {
205
- pushStep('keydown', event.key);
206
- }
207
- else {
208
- pushStep('type', event.key);
209
- }
210
- };
211
- const onKeyUp = (event) => {
212
- if (!isRecording) {
213
- return;
214
- }
215
- const { key } = event;
216
- if (!keyPresses.has(key) && [...key].length > 1) {
217
- pushStep('keyup', event.key);
218
- }
219
- };
220
- return editor.registerRootListener((rootElement, prevRootElement) => {
221
- if (prevRootElement !== null) {
222
- prevRootElement.removeEventListener('keydown', onKeyDown);
223
- prevRootElement.removeEventListener('keyup', onKeyUp);
224
- }
225
- if (rootElement !== null) {
226
- rootElement.addEventListener('keydown', onKeyDown);
227
- rootElement.addEventListener('keyup', onKeyUp);
228
- }
229
- });
230
- }, [editor, isRecording, pushStep]);
231
- useLayoutEffect(() => {
232
- if (preRef.current) {
233
- preRef.current.scrollTo(0, preRef.current.scrollHeight);
234
- }
235
- }, [generateTestContent]);
236
- useEffect(() => {
237
- if (steps) {
238
- const testContent = generateTestContent();
239
- if (testContent !== null) {
240
- setTemplatedTest(testContent);
241
- }
242
- if (preRef.current) {
243
- preRef.current.scrollTo(0, preRef.current.scrollHeight);
244
- }
245
- }
246
- }, [generateTestContent, steps]);
247
- useEffect(() => {
248
- const removeUpdateListener = editor.registerUpdateListener(({ editorState, dirtyLeaves, dirtyElements }) => {
249
- if (!isRecording) {
250
- return;
251
- }
252
- const currentSelection = editorState._selection;
253
- const previousSelection = previousSelectionRef.current;
254
- const skipNextSelectionChange = skipNextSelectionChangeRef.current;
255
- if (previousSelection !== currentSelection) {
256
- if (dirtyLeaves.size === 0 && dirtyElements.size === 0 && !skipNextSelectionChange) {
257
- const browserSelection = window.getSelection();
258
- if (browserSelection && (browserSelection.anchorNode == null || browserSelection.focusNode == null)) {
259
- return;
260
- }
261
- }
262
- previousSelectionRef.current = currentSelection;
263
- }
264
- skipNextSelectionChangeRef.current = false;
265
- const testContent = generateTestContent();
266
- if (testContent !== null) {
267
- setTemplatedTest(testContent);
268
- }
269
- });
270
- return removeUpdateListener;
271
- }, [editor, generateTestContent, isRecording, pushStep]);
272
- // save innerHTML
273
- useEffect(() => {
274
- if (!isRecording) {
275
- return;
276
- }
277
- const removeUpdateListener = editor.registerUpdateListener(() => {
278
- const rootElement = editor.getRootElement();
279
- if (rootElement !== null) {
280
- setCurrentInnerHTML(rootElement?.innerHTML);
281
- }
282
- });
283
- return removeUpdateListener;
284
- }, [editor, isRecording]);
285
- // clear editor and start recording
286
- const toggleEditorSelection = useCallback((currentEditor) => {
287
- if (!isRecording) {
288
- currentEditor.update(() => {
289
- const root = $getRoot();
290
- root.clear();
291
- const text = $createTextNode();
292
- root.append($createParagraphNode().append(text));
293
- text.select();
294
- });
295
- setSteps([]);
296
- }
297
- setIsRecording((currentIsRecording) => !currentIsRecording);
298
- }, [isRecording]);
299
- const onSnapshotClick = useCallback(() => {
300
- if (!isRecording) {
301
- return;
302
- }
303
- const browserSelection = window.getSelection();
304
- if (browserSelection === null || browserSelection.anchorNode == null || browserSelection.focusNode == null) {
305
- return;
306
- }
307
- const { anchorNode, anchorOffset, focusNode, focusOffset } = sanitizeSelection(browserSelection);
308
- const rootElement = getCurrentEditor().getRootElement();
309
- let anchorPath;
310
- if (anchorNode !== null) {
311
- anchorPath = getPathFromNodeToEditor(anchorNode, rootElement);
312
- }
313
- let focusPath;
314
- if (focusNode !== null) {
315
- focusPath = getPathFromNodeToEditor(focusNode, rootElement);
316
- }
317
- pushStep('snapshot', {
318
- anchorNode,
319
- anchorOffset,
320
- anchorPath,
321
- focusNode,
322
- focusOffset,
323
- focusPath,
324
- });
325
- }, [pushStep, isRecording, getCurrentEditor]);
326
- const onCopyClick = useCallback(() => {
327
- copy(generateTestContent());
328
- }, [generateTestContent]);
329
- const onDownloadClick = useCallback(() => {
330
- download('test.js', generateTestContent());
331
- }, [generateTestContent]);
332
- const button = (_jsx("button", { id: "test-recorder-button", className: `editor-dev-button ${isRecording ? 'active' : ''}`, onClick: () => toggleEditorSelection(getCurrentEditor()), title: isRecording ? 'Disable test recorder' : 'Enable test recorder' }));
333
- const output = isRecording ? (_jsxs("div", { className: "test-recorder-output", children: [_jsxs("div", { className: "test-recorder-toolbar", children: [_jsx("button", { className: "test-recorder-button", id: "test-recorder-button-snapshot", title: "Insert snapshot", onClick: onSnapshotClick }), _jsx("button", { className: "test-recorder-button", id: "test-recorder-button-copy", title: "Copy to clipboard", onClick: onCopyClick }), _jsx("button", { className: "test-recorder-button", id: "test-recorder-button-download", title: "Download as a file", onClick: onDownloadClick })] }), _jsx("pre", { id: "test-recorder", ref: preRef, children: templatedTest })] })) : null;
334
- return [button, output];
335
- }
336
- export default function TestRecorderPlugin() {
337
- const [editor] = useLexicalComposerContext();
338
- const [testRecorderButton, testRecorderOutput] = useTestRecorder(editor);
339
- return (_jsxs(_Fragment, { children: [testRecorderButton, testRecorderOutput] }));
340
- }
@@ -1,15 +0,0 @@
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 * as React from 'react';
9
- import { type JSX } from 'react';
10
- export default function Switch({ checked, onClick, text, id, }: Readonly<{
11
- checked: boolean;
12
- id?: string;
13
- onClick: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
14
- text: string;
15
- }>): JSX.Element;
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
- export default function Switch({ checked, onClick, text, id, }) {
4
- const buttonId = useMemo(() => `id_${Math.floor(Math.random() * 10000)}`, []);
5
- return (_jsxs("div", { className: "switch", id: id, children: [_jsx("label", { htmlFor: buttonId, children: text }), _jsx("button", { role: "switch", "aria-checked": checked, id: buttonId, onClick: onClick, children: _jsx("span", {}) })] }));
6
- }