Skip to content

Commit

Permalink
[lexical-playground] Bug Fix: autocomplete format before and after in…
Browse files Browse the repository at this point in the history
…sertion (#6845)
  • Loading branch information
bedre7 authored Nov 26, 2024
1 parent 3c78cbb commit ff10b1d
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 151 deletions.
112 changes: 102 additions & 10 deletions packages/lexical-playground/__tests__/e2e/Autocomplete.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
*
*/

import {
decreaseFontSize,
increaseFontSize,
toggleBold,
toggleItalic,
toggleStrikethrough,
toggleUnderline,
} from '../keyboardShortcuts/index.mjs';
import {
assertHTML,
focusEditor,
Expand All @@ -30,23 +38,20 @@ test.describe('Autocomplete', () => {
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span data-lexical-text="true">Sort by alpha</span>
<span contenteditable="false" data-lexical-decorator="true">
<span
class="PlaygroundEditorTheme__autocomplete"
spellcheck="false">
betical (TAB)
</span>
<span
class="PlaygroundEditorTheme__autocomplete"
style="font-size: 15px"
data-lexical-text="true">
betical (TAB)
</span>
<br />
</p>
`,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span data-lexical-text="true">Sort by alpha</span>
<span contenteditable="false" data-lexical-decorator="true"></span>
<br />
<span data-lexical-text="true"></span>
</p>
`,
);
Expand All @@ -58,7 +63,94 @@ test.describe('Autocomplete', () => {
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span data-lexical-text="true">Sort by alphabetical order:</span>
<span data-lexical-text="true">Sort by alpha</span>
<span style="font-size: 15px" data-lexical-text="true">
betical order:
</span>
</p>
`,
);
});

test('Can autocomplete in the same format as the original text', async ({
page,
isPlainText,
}) => {
test.skip(isPlainText);
await focusEditor(page);
await toggleBold(page);
await toggleItalic(page);
await toggleUnderline(page);
await toggleStrikethrough(page);
await increaseFontSize(page);

await page.keyboard.type('Test');
await sleep(500);

await assertHTML(
page,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<strong
class="PlaygroundEditorTheme__textUnderlineStrikethrough PlaygroundEditorTheme__textBold PlaygroundEditorTheme__textItalic"
style="font-size: 17px;"
data-lexical-text="true">
Test
</strong>
<strong
class="PlaygroundEditorTheme__textUnderlineStrikethrough PlaygroundEditorTheme__textBold PlaygroundEditorTheme__textItalic PlaygroundEditorTheme__autocomplete"
style="font-size: 17px;"
data-lexical-text="true">
imonials (TAB)
</strong>
</p>
`,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<strong
class="PlaygroundEditorTheme__textUnderlineStrikethrough PlaygroundEditorTheme__textBold PlaygroundEditorTheme__textItalic"
style="font-size: 17px;"
data-lexical-text="true">
Test
</strong>
<span data-lexical-text="true"></span>
</p>
`,
);

await page.keyboard.press('Tab');

await toggleBold(page);
await toggleItalic(page);
await toggleUnderline(page);
await toggleStrikethrough(page);
await decreaseFontSize(page);

await page.keyboard.type(' 2024');

await assertHTML(
page,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<strong
class="PlaygroundEditorTheme__textUnderlineStrikethrough PlaygroundEditorTheme__textBold PlaygroundEditorTheme__textItalic"
style="font-size: 17px;"
data-lexical-text="true">
Test
</strong>
<strong
class="PlaygroundEditorTheme__textUnderlineStrikethrough PlaygroundEditorTheme__textBold PlaygroundEditorTheme__textItalic"
style="font-size: 17px;"
data-lexical-text="true">
imonials
</strong>
<span style="font-size: 15px;" data-lexical-text="true">2024</span>
</p>
`,
);
Expand Down
33 changes: 15 additions & 18 deletions packages/lexical-playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
import {isDevPlayground} from './appSettings';
import {FlashMessageContext} from './context/FlashMessageContext';
import {SettingsContext, useSettings} from './context/SettingsContext';
import {SharedAutocompleteContext} from './context/SharedAutocompleteContext';
import {SharedHistoryContext} from './context/SharedHistoryContext';
import {ToolbarContext} from './context/ToolbarContext';
import Editor from './Editor';
Expand Down Expand Up @@ -211,24 +210,22 @@ function App(): JSX.Element {
<LexicalComposer initialConfig={initialConfig}>
<SharedHistoryContext>
<TableContext>
<SharedAutocompleteContext>
<ToolbarContext>
<header>
<a href="https://lexical.dev" target="_blank" rel="noreferrer">
<img src={logo} alt="Lexical Logo" />
</a>
</header>
<div className="editor-shell">
<Editor />
</div>
<Settings />
{isDevPlayground ? <DocsPlugin /> : null}
{isDevPlayground ? <PasteLogPlugin /> : null}
{isDevPlayground ? <TestRecorderPlugin /> : null}
<ToolbarContext>
<header>
<a href="https://lexical.dev" target="_blank" rel="noreferrer">
<img src={logo} alt="Lexical Logo" />
</a>
</header>
<div className="editor-shell">
<Editor />
</div>
<Settings />
{isDevPlayground ? <DocsPlugin /> : null}
{isDevPlayground ? <PasteLogPlugin /> : null}
{isDevPlayground ? <TestRecorderPlugin /> : null}

{measureTypingPerf ? <TypingPerfPlugin /> : null}
</ToolbarContext>
</SharedAutocompleteContext>
{measureTypingPerf ? <TypingPerfPlugin /> : null}
</ToolbarContext>
</TableContext>
</SharedHistoryContext>
</LexicalComposer>
Expand Down

This file was deleted.

72 changes: 28 additions & 44 deletions packages/lexical-playground/src/nodes/AutocompleteNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,26 @@
*/

import type {
DOMExportOutput,
EditorConfig,
EditorThemeClassName,
LexicalEditor,
NodeKey,
SerializedLexicalNode,
SerializedTextNode,
Spread,
} from 'lexical';

import {DecoratorNode} from 'lexical';
import * as React from 'react';
import {TextNode} from 'lexical';

import {useSharedAutocompleteContext} from '../context/SharedAutocompleteContext';
import {uuid as UUID} from '../plugins/AutocompletePlugin';

declare global {
interface Navigator {
userAgentData?: {
mobile: boolean;
};
}
}

export type SerializedAutocompleteNode = Spread<
{
uuid: string;
},
SerializedLexicalNode
SerializedTextNode
>;

export class AutocompleteNode extends DecoratorNode<JSX.Element | null> {
export class AutocompleteNode extends TextNode {
/**
* A unique uuid is generated for each session and assigned to the instance.
* This helps to:
Expand All @@ -48,7 +38,7 @@ export class AutocompleteNode extends DecoratorNode<JSX.Element | null> {
__uuid: string;

static clone(node: AutocompleteNode): AutocompleteNode {
return new AutocompleteNode(node.__uuid, node.__key);
return new AutocompleteNode(node.__text, node.__uuid, node.__key);
}

static getType(): 'autocomplete' {
Expand All @@ -58,7 +48,14 @@ export class AutocompleteNode extends DecoratorNode<JSX.Element | null> {
static importJSON(
serializedNode: SerializedAutocompleteNode,
): AutocompleteNode {
const node = $createAutocompleteNode(serializedNode.uuid);
const node = $createAutocompleteNode(
serializedNode.text,
serializedNode.uuid,
);
node.setFormat(serializedNode.format);
node.setDetail(serializedNode.detail);
node.setMode(serializedNode.mode);
node.setStyle(serializedNode.style);
return node;
}

Expand All @@ -71,8 +68,8 @@ export class AutocompleteNode extends DecoratorNode<JSX.Element | null> {
};
}

constructor(uuid: string, key?: NodeKey) {
super(key);
constructor(text: string, uuid: string, key?: NodeKey) {
super(text, key);
this.__uuid = uuid;
}

Expand All @@ -84,36 +81,23 @@ export class AutocompleteNode extends DecoratorNode<JSX.Element | null> {
return false;
}

createDOM(config: EditorConfig): HTMLElement {
return document.createElement('span');
exportDOM(_: LexicalEditor): DOMExportOutput {
return {element: null};
}

decorate(editor: LexicalEditor, config: EditorConfig): JSX.Element | null {
createDOM(config: EditorConfig): HTMLElement {
if (this.__uuid !== UUID) {
return null;
return document.createElement('span');
}
return <AutocompleteComponent className={config.theme.autocomplete} />;
const dom = super.createDOM(config);
dom.classList.add(config.theme.autocomplete);
return dom;
}
}

export function $createAutocompleteNode(uuid: string): AutocompleteNode {
return new AutocompleteNode(uuid);
}

function AutocompleteComponent({
className,
}: {
className: EditorThemeClassName;
}): JSX.Element {
const [suggestion] = useSharedAutocompleteContext();
const userAgentData = window.navigator.userAgentData;
const isMobile =
userAgentData !== undefined
? userAgentData.mobile
: window.innerWidth <= 800 && window.innerHeight <= 600;
return (
<span className={className} spellCheck="false">
{suggestion} {isMobile ? '(SWIPE \u2B95)' : '(TAB)'}
</span>
);
export function $createAutocompleteNode(
text: string,
uuid: string,
): AutocompleteNode {
return new AutocompleteNode(text, uuid);
}
Loading

0 comments on commit ff10b1d

Please sign in to comment.