diff --git a/.changeset/twelve-elephants-burn.md b/.changeset/twelve-elephants-burn.md
new file mode 100644
index 000000000..91b0e4c4b
--- /dev/null
+++ b/.changeset/twelve-elephants-burn.md
@@ -0,0 +1,6 @@
+---
+'slate': patch
+---
+
+Fix deleteBackward behavior for Thai script where deleting N character(s) backward should delete
+N code point(s) instead of an entire grapheme cluster
diff --git a/packages/slate/src/transforms/text.ts b/packages/slate/src/transforms/text.ts
index c93589b08..1fa4197ef 100644
--- a/packages/slate/src/transforms/text.ts
+++ b/packages/slate/src/transforms/text.ts
@@ -65,7 +65,9 @@ export const TextTransforms: TextTransforms = {
return
}
+ let isCollapsed = false
if (Range.isRange(at) && Range.isCollapsed(at)) {
+ isCollapsed = true
at = at.anchor
}
@@ -170,14 +172,18 @@ export const TextTransforms: TextTransforms = {
const startRef = Editor.pointRef(editor, start)
const endRef = Editor.pointRef(editor, end)
+ let removedText = ''
+
if (!isSingleText && !startVoid) {
const point = startRef.current!
const [node] = Editor.leaf(editor, point)
const { path } = point
const { offset } = start
const text = node.text.slice(offset)
- if (text.length > 0)
+ if (text.length > 0) {
editor.apply({ type: 'remove_text', path, offset, text })
+ removedText = text
+ }
}
for (const pathRef of pathRefs) {
@@ -191,8 +197,10 @@ export const TextTransforms: TextTransforms = {
const { path } = point
const offset = isSingleText ? start.offset : 0
const text = node.text.slice(offset, end.offset)
- if (text.length > 0)
+ if (text.length > 0) {
editor.apply({ type: 'remove_text', path, offset, text })
+ removedText = text
+ }
}
if (
@@ -208,6 +216,22 @@ export const TextTransforms: TextTransforms = {
})
}
+ // For Thai script, deleting N character(s) backward should delete
+ // N code point(s) instead of an entire grapheme cluster.
+ // Therefore, the remaining code points should be inserted back.
+ if (
+ isCollapsed &&
+ reverse &&
+ unit === 'character' &&
+ removedText.length > 1 &&
+ removedText.match(/[\u0E00-\u0E7F]+/)
+ ) {
+ Transforms.insertText(
+ editor,
+ removedText.slice(0, removedText.length - distance)
+ )
+ }
+
const startUnref = startRef.unref()
const endUnref = endRef.unref()
const point = reverse ? startUnref || endUnref : endUnref || startUnref
diff --git a/packages/slate/test/transforms/delete/unit-character/thai-multiple-reverse.tsx b/packages/slate/test/transforms/delete/unit-character/thai-multiple-reverse.tsx
new file mode 100644
index 000000000..ef9abf591
--- /dev/null
+++ b/packages/slate/test/transforms/delete/unit-character/thai-multiple-reverse.tsx
@@ -0,0 +1,23 @@
+/** @jsx jsx */
+import { Transforms } from 'slate'
+import { jsx } from '../../..'
+
+export const run = editor => {
+ Transforms.delete(editor, { unit: 'character', distance: 2, reverse: true })
+}
+export const input = (
+
+
+ พี่
+
+
+
+)
+export const output = (
+
+
+ พ
+
+
+
+)
diff --git a/packages/slate/test/transforms/delete/unit-character/thai-reverse.tsx b/packages/slate/test/transforms/delete/unit-character/thai-reverse.tsx
new file mode 100644
index 000000000..ad8fc2650
--- /dev/null
+++ b/packages/slate/test/transforms/delete/unit-character/thai-reverse.tsx
@@ -0,0 +1,23 @@
+/** @jsx jsx */
+import { Transforms } from 'slate'
+import { jsx } from '../../..'
+
+export const run = editor => {
+ Transforms.delete(editor, { unit: 'character', reverse: true })
+}
+export const input = (
+
+
+ พี่
+
+
+
+)
+export const output = (
+
+
+ พี
+
+
+
+)