diff --git a/.playwright/tests/checkboxList.spec.ts b/.playwright/tests/checkboxList.spec.ts
index 0348da532..8472a7d42 100644
--- a/.playwright/tests/checkboxList.spec.ts
+++ b/.playwright/tests/checkboxList.spec.ts
@@ -59,4 +59,33 @@ test.describe('checkbox list (web)', () => {
const html = await getSerializedHtml(page);
expect(html.match(/
{
+ await setEditorHtml(
+ page,
+ ''
+ );
+
+ const editor = editorLocator(page);
+ const checkbox = editor.locator('input[type="checkbox"]').first();
+ await checkbox.click();
+
+ const selection = await editor.evaluate(() => {
+ const s = window.getSelection();
+ if (!s || s.rangeCount === 0) {
+ return null;
+ }
+ const range = s.getRangeAt(0);
+ return {
+ startOffset: range.startOffset,
+ endOffset: range.endOffset,
+ collapsed: range.collapsed,
+ };
+ });
+ expect(selection).toEqual({
+ startOffset: 3,
+ endOffset: 3,
+ collapsed: true,
+ });
+ });
});
diff --git a/src/web/EnrichedTextInput.tsx b/src/web/EnrichedTextInput.tsx
index 1002b647c..7d118ff3f 100644
--- a/src/web/EnrichedTextInput.tsx
+++ b/src/web/EnrichedTextInput.tsx
@@ -18,12 +18,7 @@ import {
nativePosToTiptapPos,
nativeLeafText,
} from './nativeMappers/positionMapping';
-import {
- useEditor,
- EditorContent,
- type ChainedCommands,
- Editor,
-} from '@tiptap/react';
+import { useEditor, EditorContent, Editor } from '@tiptap/react';
import Document from '@tiptap/extension-document';
import Paragraph from '@tiptap/extension-paragraph';
import Text from '@tiptap/extension-text';
@@ -92,13 +87,8 @@ import {
import { assertBrowserEnvironment } from './utils/assertBrowserEnvironment';
import { runSafelyInEditor } from './utils/runSafelyInEditor';
import { useLinkPress } from './htmlExtensions/useLinkPress';
-
-function runFocused(
- editor: Editor,
- apply: (chain: ChainedCommands) => ChainedCommands
-) {
- runSafelyInEditor(editor, (e) => apply(e.chain().focus()).run());
-}
+import { handleCheckboxPress } from './htmlExtensions/handleCheckboxPress';
+import { runFocused } from './utils/runFocused';
export const EnrichedTextInput = ({
ref,
@@ -292,7 +282,12 @@ export const EnrichedTextInput = ({
editorProps: {
handleKeyDown: (view, event) => handleKeyDown(view.state.doc, event),
handleDOMEvents: {
- click: (_view, event) => handleLinkPress(event),
+ click: (view, event) => {
+ if (handleCheckboxPress(event, editor, view)) {
+ return true;
+ }
+ return handleLinkPress(event);
+ },
mousedown: (_view, event) => handleLinkMouseDown(event),
},
handlePaste: (_view, event) =>
diff --git a/src/web/htmlExtensions/handleCheckboxPress.ts b/src/web/htmlExtensions/handleCheckboxPress.ts
new file mode 100644
index 000000000..5e8f1f14f
--- /dev/null
+++ b/src/web/htmlExtensions/handleCheckboxPress.ts
@@ -0,0 +1,19 @@
+import { Editor } from '@tiptap/core';
+import type { EditorView } from '@tiptap/pm/view';
+import { runFocused } from '../utils/runFocused';
+
+export function handleCheckboxPress(
+ event: MouseEvent,
+ editor: Editor,
+ view: EditorView
+): boolean {
+ const target = event.target;
+ if (target instanceof HTMLInputElement && target.type === 'checkbox') {
+ const position = view.posAtDOM(target, 0);
+ const node = view.state.doc.nodeAt(position);
+ if (!node) return false;
+ runFocused(editor, (c) => c.setTextSelection(position + node.nodeSize - 1));
+ return true;
+ }
+ return false;
+}
diff --git a/src/web/utils/runFocused.ts b/src/web/utils/runFocused.ts
new file mode 100644
index 000000000..a1f97f9da
--- /dev/null
+++ b/src/web/utils/runFocused.ts
@@ -0,0 +1,8 @@
+import { Editor, type ChainedCommands } from '@tiptap/core';
+import { runSafelyInEditor } from './runSafelyInEditor';
+export function runFocused(
+ editor: Editor,
+ apply: (chain: ChainedCommands) => ChainedCommands
+) {
+ runSafelyInEditor(editor, (e) => apply(e.chain().focus()).run());
+}