@portabletext/editor 1.1.12 → 1.2.0
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/lib/index.esm.js +51 -7
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +51 -7
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +51 -7
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/editor/behavior/behavior.core.block-objects.ts +106 -0
- package/src/editor/behavior/behavior.core.lists.ts +76 -0
- package/src/editor/behavior/behavior.core.ts +4 -102
package/package.json
CHANGED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {isPortableTextTextBlock} from '@sanity/types'
|
|
2
|
+
import {defineBehavior} from './behavior.types'
|
|
3
|
+
import {
|
|
4
|
+
getFocusBlockObject,
|
|
5
|
+
getFocusTextBlock,
|
|
6
|
+
getNextBlock,
|
|
7
|
+
getPreviousBlock,
|
|
8
|
+
isEmptyTextBlock,
|
|
9
|
+
selectionIsCollapsed,
|
|
10
|
+
} from './behavior.utils'
|
|
11
|
+
|
|
12
|
+
const breakingVoidBlock = defineBehavior({
|
|
13
|
+
on: 'insert break',
|
|
14
|
+
guard: ({context}) => {
|
|
15
|
+
const focusBlockObject = getFocusBlockObject(context)
|
|
16
|
+
|
|
17
|
+
return !!focusBlockObject
|
|
18
|
+
},
|
|
19
|
+
actions: [() => [{type: 'insert text block', decorators: []}]],
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const deletingEmptyTextBlockAfterBlockObject = defineBehavior({
|
|
23
|
+
on: 'delete backward',
|
|
24
|
+
guard: ({context}) => {
|
|
25
|
+
const focusTextBlock = getFocusTextBlock(context)
|
|
26
|
+
const selectionCollapsed = selectionIsCollapsed(context)
|
|
27
|
+
const previousBlock = getPreviousBlock(context)
|
|
28
|
+
|
|
29
|
+
if (!focusTextBlock || !selectionCollapsed || !previousBlock) {
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (
|
|
34
|
+
isEmptyTextBlock(focusTextBlock.node) &&
|
|
35
|
+
!isPortableTextTextBlock(previousBlock.node)
|
|
36
|
+
) {
|
|
37
|
+
return {focusTextBlock, previousBlock}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return false
|
|
41
|
+
},
|
|
42
|
+
actions: [
|
|
43
|
+
(_, {focusTextBlock, previousBlock}) => [
|
|
44
|
+
{
|
|
45
|
+
type: 'delete',
|
|
46
|
+
selection: {
|
|
47
|
+
anchor: {path: focusTextBlock.path, offset: 0},
|
|
48
|
+
focus: {path: focusTextBlock.path, offset: 0},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'select',
|
|
53
|
+
selection: {
|
|
54
|
+
anchor: {path: previousBlock.path, offset: 0},
|
|
55
|
+
focus: {path: previousBlock.path, offset: 0},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
],
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const deletingEmptyTextBlockBeforeBlockObject = defineBehavior({
|
|
63
|
+
on: 'delete forward',
|
|
64
|
+
guard: ({context}) => {
|
|
65
|
+
const focusTextBlock = getFocusTextBlock(context)
|
|
66
|
+
const selectionCollapsed = selectionIsCollapsed(context)
|
|
67
|
+
const nextBlock = getNextBlock(context)
|
|
68
|
+
|
|
69
|
+
if (!focusTextBlock || !selectionCollapsed || !nextBlock) {
|
|
70
|
+
return false
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (
|
|
74
|
+
isEmptyTextBlock(focusTextBlock.node) &&
|
|
75
|
+
!isPortableTextTextBlock(nextBlock.node)
|
|
76
|
+
) {
|
|
77
|
+
return {focusTextBlock, nextBlock}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return false
|
|
81
|
+
},
|
|
82
|
+
actions: [
|
|
83
|
+
(_, {focusTextBlock, nextBlock}) => [
|
|
84
|
+
{
|
|
85
|
+
type: 'delete',
|
|
86
|
+
selection: {
|
|
87
|
+
anchor: {path: focusTextBlock.path, offset: 0},
|
|
88
|
+
focus: {path: focusTextBlock.path, offset: 0},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
type: 'select',
|
|
93
|
+
selection: {
|
|
94
|
+
anchor: {path: nextBlock.path, offset: 0},
|
|
95
|
+
focus: {path: nextBlock.path, offset: 0},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
],
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
export const coreBlockObjectBehaviors = [
|
|
103
|
+
breakingVoidBlock,
|
|
104
|
+
deletingEmptyTextBlockAfterBlockObject,
|
|
105
|
+
deletingEmptyTextBlockBeforeBlockObject,
|
|
106
|
+
]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {defineBehavior} from './behavior.types'
|
|
2
|
+
import {
|
|
3
|
+
getFocusSpan,
|
|
4
|
+
getFocusTextBlock,
|
|
5
|
+
selectionIsCollapsed,
|
|
6
|
+
} from './behavior.utils'
|
|
7
|
+
|
|
8
|
+
const clearListOnBackspace = defineBehavior({
|
|
9
|
+
on: 'delete backward',
|
|
10
|
+
guard: ({context}) => {
|
|
11
|
+
const selectionCollapsed = selectionIsCollapsed(context)
|
|
12
|
+
const focusTextBlock = getFocusTextBlock(context)
|
|
13
|
+
const focusSpan = getFocusSpan(context)
|
|
14
|
+
|
|
15
|
+
if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const atTheBeginningOfBLock =
|
|
20
|
+
focusTextBlock.node.children[0]._key === focusSpan.node._key &&
|
|
21
|
+
context.selection.focus.offset === 0
|
|
22
|
+
|
|
23
|
+
if (atTheBeginningOfBLock && focusTextBlock.node.level === 1) {
|
|
24
|
+
return {focusTextBlock}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return false
|
|
28
|
+
},
|
|
29
|
+
actions: [
|
|
30
|
+
(_, {focusTextBlock}) => [
|
|
31
|
+
{
|
|
32
|
+
type: 'unset block',
|
|
33
|
+
props: ['listItem', 'level'],
|
|
34
|
+
paths: [focusTextBlock.path],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
],
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const unindentListOnBackspace = defineBehavior({
|
|
41
|
+
on: 'delete backward',
|
|
42
|
+
guard: ({context}) => {
|
|
43
|
+
const selectionCollapsed = selectionIsCollapsed(context)
|
|
44
|
+
const focusTextBlock = getFocusTextBlock(context)
|
|
45
|
+
const focusSpan = getFocusSpan(context)
|
|
46
|
+
|
|
47
|
+
if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const atTheBeginningOfBLock =
|
|
52
|
+
focusTextBlock.node.children[0]._key === focusSpan.node._key &&
|
|
53
|
+
context.selection.focus.offset === 0
|
|
54
|
+
|
|
55
|
+
if (
|
|
56
|
+
atTheBeginningOfBLock &&
|
|
57
|
+
focusTextBlock.node.level !== undefined &&
|
|
58
|
+
focusTextBlock.node.level > 1
|
|
59
|
+
) {
|
|
60
|
+
return {focusTextBlock, level: focusTextBlock.node.level - 1}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return false
|
|
64
|
+
},
|
|
65
|
+
actions: [
|
|
66
|
+
(_, {focusTextBlock, level}) => [
|
|
67
|
+
{
|
|
68
|
+
type: 'set block',
|
|
69
|
+
level,
|
|
70
|
+
paths: [focusTextBlock.path],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
],
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
export const coreListBehaviors = [clearListOnBackspace, unindentListOnBackspace]
|
|
@@ -1,112 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {coreBlockObjectBehaviors} from './behavior.core.block-objects'
|
|
2
|
+
import {coreListBehaviors} from './behavior.core.lists'
|
|
2
3
|
import {defineBehavior} from './behavior.types'
|
|
3
|
-
import {
|
|
4
|
-
getFocusBlockObject,
|
|
5
|
-
getFocusTextBlock,
|
|
6
|
-
getNextBlock,
|
|
7
|
-
getPreviousBlock,
|
|
8
|
-
isEmptyTextBlock,
|
|
9
|
-
selectionIsCollapsed,
|
|
10
|
-
} from './behavior.utils'
|
|
11
4
|
|
|
12
5
|
const softReturn = defineBehavior({
|
|
13
6
|
on: 'insert soft break',
|
|
14
7
|
actions: [() => [{type: 'insert text', text: '\n'}]],
|
|
15
8
|
})
|
|
16
9
|
|
|
17
|
-
const breakingVoidBlock = defineBehavior({
|
|
18
|
-
on: 'insert break',
|
|
19
|
-
guard: ({context}) => {
|
|
20
|
-
const focusBlockObject = getFocusBlockObject(context)
|
|
21
|
-
|
|
22
|
-
return !!focusBlockObject
|
|
23
|
-
},
|
|
24
|
-
actions: [() => [{type: 'insert text block', decorators: []}]],
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
const deletingEmptyTextBlockAfterBlockObject = defineBehavior({
|
|
28
|
-
on: 'delete backward',
|
|
29
|
-
guard: ({context}) => {
|
|
30
|
-
const focusTextBlock = getFocusTextBlock(context)
|
|
31
|
-
const selectionCollapsed = selectionIsCollapsed(context)
|
|
32
|
-
const previousBlock = getPreviousBlock(context)
|
|
33
|
-
|
|
34
|
-
if (!focusTextBlock || !selectionCollapsed || !previousBlock) {
|
|
35
|
-
return false
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
isEmptyTextBlock(focusTextBlock.node) &&
|
|
40
|
-
!isPortableTextTextBlock(previousBlock.node)
|
|
41
|
-
) {
|
|
42
|
-
return {focusTextBlock, previousBlock}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return false
|
|
46
|
-
},
|
|
47
|
-
actions: [
|
|
48
|
-
(_, {focusTextBlock, previousBlock}) => [
|
|
49
|
-
{
|
|
50
|
-
type: 'delete',
|
|
51
|
-
selection: {
|
|
52
|
-
anchor: {path: focusTextBlock.path, offset: 0},
|
|
53
|
-
focus: {path: focusTextBlock.path, offset: 0},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
type: 'select',
|
|
58
|
-
selection: {
|
|
59
|
-
anchor: {path: previousBlock.path, offset: 0},
|
|
60
|
-
focus: {path: previousBlock.path, offset: 0},
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
],
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
const deletingEmptyTextBlockBeforeBlockObject = defineBehavior({
|
|
68
|
-
on: 'delete forward',
|
|
69
|
-
guard: ({context}) => {
|
|
70
|
-
const focusTextBlock = getFocusTextBlock(context)
|
|
71
|
-
const selectionCollapsed = selectionIsCollapsed(context)
|
|
72
|
-
const nextBlock = getNextBlock(context)
|
|
73
|
-
|
|
74
|
-
if (!focusTextBlock || !selectionCollapsed || !nextBlock) {
|
|
75
|
-
return false
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
isEmptyTextBlock(focusTextBlock.node) &&
|
|
80
|
-
!isPortableTextTextBlock(nextBlock.node)
|
|
81
|
-
) {
|
|
82
|
-
return {focusTextBlock, nextBlock}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return false
|
|
86
|
-
},
|
|
87
|
-
actions: [
|
|
88
|
-
(_, {focusTextBlock, nextBlock}) => [
|
|
89
|
-
{
|
|
90
|
-
type: 'delete',
|
|
91
|
-
selection: {
|
|
92
|
-
anchor: {path: focusTextBlock.path, offset: 0},
|
|
93
|
-
focus: {path: focusTextBlock.path, offset: 0},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
type: 'select',
|
|
98
|
-
selection: {
|
|
99
|
-
anchor: {path: nextBlock.path, offset: 0},
|
|
100
|
-
focus: {path: nextBlock.path, offset: 0},
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
],
|
|
105
|
-
})
|
|
106
|
-
|
|
107
10
|
export const coreBehaviors = [
|
|
108
11
|
softReturn,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
deletingEmptyTextBlockBeforeBlockObject,
|
|
12
|
+
...coreBlockObjectBehaviors,
|
|
13
|
+
...coreListBehaviors,
|
|
112
14
|
]
|