@portabletext/editor 2.18.1 → 2.19.1
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.
- package/README.md +7 -0
- package/lib/_chunks-dts/index.d.ts +57 -55
- package/lib/index.js +68 -0
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/behaviors/behavior.abstract.keyboard.ts +15 -0
- package/src/behaviors/behavior.types.event.ts +1 -0
- package/src/keyboard-shortcuts/default-keyboard-shortcuts.ts +42 -0
- package/src/operations/behavior.operation.annotation.add.ts +1 -0
- package/src/operations/behavior.operation.delete.ts +18 -0
- package/src/test/gherkin-parameter-types.ts +5 -0
- package/src/test/vitest/step-definitions.tsx +17 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.1",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"vitest": "^4.0.6",
|
|
108
108
|
"vitest-browser-react": "^2.0.2",
|
|
109
109
|
"@portabletext/sanity-bridge": "1.2.0",
|
|
110
|
-
"@portabletext/test": "^
|
|
110
|
+
"@portabletext/test": "^1.0.0",
|
|
111
111
|
"racejar": "2.0.0"
|
|
112
112
|
},
|
|
113
113
|
"peerDependencies": {
|
|
@@ -37,6 +37,7 @@ export const abstractKeyboardBehaviors = [
|
|
|
37
37
|
getFocusInlineObject(snapshot),
|
|
38
38
|
actions: [() => [raise({type: 'delete.backward', unit: 'character'})]],
|
|
39
39
|
}),
|
|
40
|
+
|
|
40
41
|
/**
|
|
41
42
|
* When Delete is pressed on an inline object, Slate will raise a
|
|
42
43
|
* `delete.forward` event with `unit: 'block'`. This is wrong and this
|
|
@@ -51,6 +52,20 @@ export const abstractKeyboardBehaviors = [
|
|
|
51
52
|
actions: [() => [raise({type: 'delete.forward', unit: 'character'})]],
|
|
52
53
|
}),
|
|
53
54
|
|
|
55
|
+
defineBehavior({
|
|
56
|
+
on: 'keyboard.keydown',
|
|
57
|
+
guard: ({event}) =>
|
|
58
|
+
defaultKeyboardShortcuts.deleteWord.backward.guard(event.originEvent),
|
|
59
|
+
actions: [() => [raise({type: 'delete.backward', unit: 'word'})]],
|
|
60
|
+
}),
|
|
61
|
+
|
|
62
|
+
defineBehavior({
|
|
63
|
+
on: 'keyboard.keydown',
|
|
64
|
+
guard: ({event}) =>
|
|
65
|
+
defaultKeyboardShortcuts.deleteWord.forward.guard(event.originEvent),
|
|
66
|
+
actions: [() => [raise({type: 'delete.forward', unit: 'word'})]],
|
|
67
|
+
}),
|
|
68
|
+
|
|
54
69
|
/**
|
|
55
70
|
* Allow raising an `insert.break` event when pressing Enter on an inline
|
|
56
71
|
* object.
|
|
@@ -75,6 +75,48 @@ export const defaultKeyboardShortcuts = {
|
|
|
75
75
|
},
|
|
76
76
|
],
|
|
77
77
|
}),
|
|
78
|
+
deleteWord: {
|
|
79
|
+
backward: createKeyboardShortcut({
|
|
80
|
+
default: [
|
|
81
|
+
{
|
|
82
|
+
key: 'Backspace',
|
|
83
|
+
alt: false,
|
|
84
|
+
ctrl: true,
|
|
85
|
+
meta: false,
|
|
86
|
+
// shift is optional
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
apple: [
|
|
90
|
+
{
|
|
91
|
+
key: 'Backspace',
|
|
92
|
+
alt: true,
|
|
93
|
+
ctrl: false,
|
|
94
|
+
meta: false,
|
|
95
|
+
// shift is optional
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
}),
|
|
99
|
+
forward: createKeyboardShortcut({
|
|
100
|
+
default: [
|
|
101
|
+
{
|
|
102
|
+
key: 'Delete',
|
|
103
|
+
alt: false,
|
|
104
|
+
ctrl: true,
|
|
105
|
+
meta: false,
|
|
106
|
+
// shift is optional
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
apple: [
|
|
110
|
+
{
|
|
111
|
+
key: 'Delete',
|
|
112
|
+
alt: true,
|
|
113
|
+
ctrl: false,
|
|
114
|
+
meta: false,
|
|
115
|
+
// shift is optional
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
}),
|
|
119
|
+
},
|
|
78
120
|
history: {
|
|
79
121
|
undo,
|
|
80
122
|
redo,
|
|
@@ -8,6 +8,7 @@ export const addAnnotationOperationImplementation: BehaviorOperationImplementati
|
|
|
8
8
|
const parsedAnnotation = parseAnnotation({
|
|
9
9
|
annotation: {
|
|
10
10
|
_type: operation.annotation.name,
|
|
11
|
+
_key: operation.annotation._key,
|
|
11
12
|
...operation.annotation.value,
|
|
12
13
|
},
|
|
13
14
|
context,
|
|
@@ -106,6 +106,24 @@ export const deleteOperationImplementation: BehaviorOperationImplementation<
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
if (operation.unit === 'word') {
|
|
110
|
+
const range = at ?? operation.editor.selection ?? undefined
|
|
111
|
+
|
|
112
|
+
if (!range) {
|
|
113
|
+
throw new Error('Unable to delete word without a selection')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (Range.isCollapsed(range)) {
|
|
117
|
+
deleteText(operation.editor, {
|
|
118
|
+
at: range,
|
|
119
|
+
unit: 'word',
|
|
120
|
+
reverse: operation.direction === 'backward',
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
109
127
|
const hanging = reverse
|
|
110
128
|
? endPoint
|
|
111
129
|
? isTextBlock(context, endBlock)
|
|
@@ -64,6 +64,10 @@ const parameterType = {
|
|
|
64
64
|
name: 'select-position',
|
|
65
65
|
matcher: /"(start|end|none)"/,
|
|
66
66
|
}),
|
|
67
|
+
shortcut: createParameterType<'deleteWord.backward' | 'deleteWord.forward'>({
|
|
68
|
+
name: 'shortcut',
|
|
69
|
+
matcher: /"(deleteWord\.backward|deleteWord\.forward)"/,
|
|
70
|
+
}),
|
|
67
71
|
style: createParameterType({
|
|
68
72
|
name: 'style',
|
|
69
73
|
matcher: /"(normal|blockquote|h\d)"/,
|
|
@@ -96,6 +100,7 @@ export const parameterTypes = [
|
|
|
96
100
|
parameterType.marks,
|
|
97
101
|
parameterType.placement,
|
|
98
102
|
parameterType.selectPosition,
|
|
103
|
+
parameterType.shortcut,
|
|
99
104
|
parameterType.style,
|
|
100
105
|
parameterType.tersePt,
|
|
101
106
|
parameterType.text,
|
|
@@ -4,6 +4,7 @@ import {Given, Then, When} from 'racejar'
|
|
|
4
4
|
import {assert, expect, vi} from 'vitest'
|
|
5
5
|
import {userEvent} from 'vitest/browser'
|
|
6
6
|
import {getEditorSelection} from '../../internal-utils/editor-selection'
|
|
7
|
+
import {IS_MAC} from '../../internal-utils/is-hotkey'
|
|
7
8
|
import {getSelectionText} from '../../internal-utils/selection-text'
|
|
8
9
|
import {getTextBlockKey} from '../../internal-utils/text-block-key'
|
|
9
10
|
import {getTextMarks} from '../../internal-utils/text-marks'
|
|
@@ -235,6 +236,22 @@ export const stepDefinitions = [
|
|
|
235
236
|
}
|
|
236
237
|
},
|
|
237
238
|
),
|
|
239
|
+
When(
|
|
240
|
+
'{shortcut} is pressed',
|
|
241
|
+
async (_: Context, shortcut: Parameter['shortcut']) => {
|
|
242
|
+
const shortcuts: Record<Parameter['shortcut'], string> = {
|
|
243
|
+
'deleteWord.backward': IS_MAC
|
|
244
|
+
? '{Alt>}{Backspace}{/Alt}'
|
|
245
|
+
: '{Control>}{Backspace}{/Control}',
|
|
246
|
+
'deleteWord.forward': IS_MAC
|
|
247
|
+
? '{Alt>}{Delete}{/Alt}'
|
|
248
|
+
: '{Control>}{Delete}{/Control}',
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
await userEvent.keyboard(shortcuts[shortcut])
|
|
252
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
253
|
+
},
|
|
254
|
+
),
|
|
238
255
|
|
|
239
256
|
/**
|
|
240
257
|
* Selection steps
|