Skip to content

Commit 89ced5e

Browse files
authored
fix(richtext-lexical): enable select inputs with ctrl+a or cmd+a (#12453)
Fixes #6871 To review this PR, use `pnpm dev lexical` and the auto-created document in the `lexical fields` collection. Select any input within the blocks and press `cmd+a`. The selection should contain the entire input. I made sure that `cmd+a` still works fine inside the editor but outside of inputs.
1 parent 836fd86 commit 89ced5e

File tree

6 files changed

+56
-4
lines changed

6 files changed

+56
-4
lines changed

docs/authentication/overview.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ export default buildConfig({
151151
prefillOnly: true,
152152
}
153153
: false,
154-
}
155-
154+
},
155+
156156
// highlight-end
157157
})
158158
```

packages/richtext-lexical/src/lexical/LexicalEditor.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { DraggableBlockPlugin } from './plugins/handles/DraggableBlockPlugin/ind
1919
import { InsertParagraphAtEndPlugin } from './plugins/InsertParagraphAtEnd/index.js'
2020
import { MarkdownShortcutPlugin } from './plugins/MarkdownShortcut/index.js'
2121
import { NormalizeSelectionPlugin } from './plugins/NormalizeSelection/index.js'
22+
import { SelectAllPlugin } from './plugins/SelectAllPlugin/index.js'
2223
import { SlashMenuPlugin } from './plugins/SlashMenu/index.js'
2324
import { TextPlugin } from './plugins/TextPlugin/index.js'
2425
import { LexicalContentEditable } from './ui/ContentEditable.js'
@@ -111,6 +112,7 @@ export const LexicalEditor: React.FC<
111112
<InsertParagraphAtEndPlugin />
112113
<DecoratorPlugin />
113114
<TextPlugin features={editorConfig.features} />
115+
<SelectAllPlugin />
114116
<OnChangePlugin
115117
// Selection changes can be ignored here, reducing the
116118
// frequency that the FieldComponent and Payload receive updates.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
2+
import { $getSelection, COMMAND_PRIORITY_LOW, SELECT_ALL_COMMAND } from 'lexical'
3+
import { useEffect } from 'react'
4+
5+
/**
6+
* Allows to select inputs with `ctrl+a` or `cmd+a`.
7+
* Required because Lexical preventDefault the event.
8+
* see: https://github.com/payloadcms/payload/issues/6871
9+
*/
10+
export function SelectAllPlugin() {
11+
const [editor] = useLexicalComposerContext()
12+
13+
useEffect(() => {
14+
return editor.registerCommand(
15+
SELECT_ALL_COMMAND,
16+
() => {
17+
const selection = $getSelection()
18+
if (selection) {
19+
return false
20+
}
21+
const activeElement = document.activeElement
22+
if (activeElement instanceof HTMLInputElement) {
23+
activeElement.select()
24+
}
25+
return true
26+
},
27+
COMMAND_PRIORITY_LOW,
28+
)
29+
}, [editor])
30+
31+
return null
32+
}

test/database/up-down-migration/migrations/20250528_153134.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { MigrateDownArgs, MigrateUpArgs} from '@payloadcms/db-postgres';
1+
import type { MigrateDownArgs, MigrateUpArgs } from '@payloadcms/db-postgres'
22

33
import { sql } from '@payloadcms/db-postgres'
44

test/lexical/collections/_LexicalFullyFeatured/e2e.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,24 @@ describe('Lexical Fully Featured', () => {
6262
const paragraph = lexical.editor.locator('> p')
6363
await expect(paragraph).toHaveText('')
6464
})
65+
66+
test('ControlOrMeta+A inside input should select all the text inside the input', async ({
67+
page,
68+
}) => {
69+
const lexical = new LexicalHelpers(page)
70+
await lexical.editor.first().focus()
71+
await page.keyboard.type('Hello')
72+
await page.keyboard.press('Enter')
73+
await lexical.slashCommand('block')
74+
await page.locator('#field-someText').first().focus()
75+
await page.keyboard.type('World')
76+
await page.keyboard.press('ControlOrMeta+A')
77+
await page.keyboard.press('Backspace')
78+
const paragraph = lexical.editor.locator('> p').first()
79+
await expect(paragraph).toHaveText('Hello')
80+
await expect(page.getByText('World')).toHaveCount(0)
81+
})
82+
6583
test('text state feature', async ({ page }) => {
6684
await page.keyboard.type('Hello')
6785
await page.keyboard.press('ControlOrMeta+A')

tsconfig.base.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
}
3232
],
3333
"paths": {
34-
"@payload-config": ["./test/query-presets/config.ts"],
34+
"@payload-config": ["./test/_community/config.ts"],
3535
"@payloadcms/admin-bar": ["./packages/admin-bar/src"],
3636
"@payloadcms/live-preview": ["./packages/live-preview/src"],
3737
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],

0 commit comments

Comments
 (0)