@portabletext/editor 1.39.0 → 1.40.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/_chunks-cjs/behavior.core.cjs +16 -5
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/editor-provider.cjs +158 -153
- package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.get-text-before.cjs +0 -1
- package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +0 -3
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs +0 -4
- package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs.map +1 -1
- package/lib/_chunks-cjs/{parse-blocks.cjs → util.selection-point-to-block-offset.cjs} +74 -4
- package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -0
- package/lib/_chunks-cjs/util.slice-blocks.cjs +2 -2
- package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/util.split-text-block.cjs +68 -0
- package/lib/_chunks-cjs/util.split-text-block.cjs.map +1 -0
- package/lib/_chunks-es/behavior.core.js +17 -6
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/editor-provider.js +155 -150
- package/lib/_chunks-es/editor-provider.js.map +1 -1
- package/lib/_chunks-es/selector.get-text-before.js +1 -2
- package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js +1 -4
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
- package/lib/_chunks-es/selector.is-overlapping-selection.js +1 -5
- package/lib/_chunks-es/selector.is-overlapping-selection.js.map +1 -1
- package/lib/_chunks-es/{parse-blocks.js → util.selection-point-to-block-offset.js} +76 -5
- package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -0
- package/lib/_chunks-es/util.slice-blocks.js +2 -2
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/_chunks-es/util.split-text-block.js +70 -0
- package/lib/_chunks-es/util.split-text-block.js.map +1 -0
- package/lib/behaviors/index.d.cts +1516 -911
- package/lib/behaviors/index.d.ts +1516 -911
- package/lib/index.cjs +197 -200
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +1247 -717
- package/lib/index.d.ts +1247 -717
- package/lib/index.js +204 -207
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.cjs +11 -12
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +1238 -721
- package/lib/plugins/index.d.ts +1238 -721
- package/lib/plugins/index.js +3 -4
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.d.cts +1237 -710
- package/lib/selectors/index.d.ts +1237 -710
- package/lib/utils/index.cjs +15 -87
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/index.d.cts +1290 -713
- package/lib/utils/index.d.ts +1290 -713
- package/lib/utils/index.js +13 -86
- package/lib/utils/index.js.map +1 -1
- package/package.json +10 -10
- package/src/behavior-actions/behavior.action.decorator.add.ts +13 -2
- package/src/behaviors/behavior.core.block-objects.ts +32 -2
- package/src/behaviors/behavior.default.ts +59 -16
- package/src/behaviors/behavior.types.ts +67 -30
- package/src/editor/Editable.tsx +122 -68
- package/src/editor/PortableTextEditor.tsx +8 -8
- package/src/editor/__tests__/self-solving.test.tsx +1 -1
- package/src/editor/components/Element.tsx +1 -3
- package/src/editor/create-editor.ts +13 -5
- package/src/editor/editor-machine.ts +13 -3
- package/src/editor/editor-provider.tsx +11 -7
- package/src/editor/editor-selector.ts +4 -3
- package/src/editor/editor-snapshot.ts +2 -2
- package/src/editor/plugins/create-with-event-listeners.ts +18 -3
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +1 -2
- package/src/internal-utils/block-keys.ts +9 -0
- package/src/internal-utils/collapse-selection.ts +36 -0
- package/src/internal-utils/compound-client-rect.ts +28 -0
- package/src/internal-utils/drag-selection.test.ts +507 -0
- package/src/internal-utils/drag-selection.ts +66 -0
- package/src/internal-utils/editor-selection.test.ts +40 -0
- package/src/internal-utils/editor-selection.ts +60 -0
- package/src/internal-utils/event-position.ts +55 -80
- package/src/internal-utils/inline-object-selection.ts +115 -0
- package/src/internal-utils/selection-block-keys.ts +20 -0
- package/src/internal-utils/selection-elements.ts +61 -0
- package/src/internal-utils/selection-focus-text.ts +38 -0
- package/src/internal-utils/selection-text.test.ts +23 -0
- package/src/internal-utils/selection-text.ts +90 -0
- package/src/internal-utils/split-string.ts +12 -0
- package/src/internal-utils/string-overlap.test.ts +14 -0
- package/src/internal-utils/string-overlap.ts +28 -0
- package/src/internal-utils/string-utils.ts +7 -0
- package/src/internal-utils/terse-pt.test.ts +60 -0
- package/src/internal-utils/terse-pt.ts +36 -0
- package/src/internal-utils/text-block-key.test.ts +30 -0
- package/src/internal-utils/text-block-key.ts +30 -0
- package/src/internal-utils/text-marks.test.ts +33 -0
- package/src/internal-utils/text-marks.ts +26 -0
- package/src/internal-utils/text-selection.test.ts +175 -0
- package/src/internal-utils/text-selection.ts +122 -0
- package/src/internal-utils/value-annotations.ts +31 -0
- package/src/internal-utils/values.ts +16 -5
- package/src/utils/index.ts +5 -0
- package/src/utils/util.block-offset-to-block-selection-point.ts +28 -0
- package/src/utils/util.block-offset-to-selection-point.ts +33 -0
- package/src/utils/util.block-offsets-to-selection.ts +3 -3
- package/src/utils/util.is-equal-selections.ts +20 -0
- package/src/utils/util.is-selection-collapsed.ts +15 -0
- package/src/utils/util.reverse-selection.ts +9 -5
- package/src/utils/util.selection-point-to-block-offset.ts +31 -0
- package/lib/_chunks-cjs/parse-blocks.cjs.map +0 -1
- package/lib/_chunks-es/parse-blocks.js.map +0 -1
- package/src/editor/components/use-draggable.ts +0 -123
package/lib/utils/index.js
CHANGED
|
@@ -1,92 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { blockOffsetToSpanSelectionPoint, getBlockEndPoint, getBlockStartPoint, getTextBlockText, isEmptyTextBlock,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
value,
|
|
8
|
-
selectionPoint
|
|
9
|
-
}) {
|
|
10
|
-
let offset = 0;
|
|
11
|
-
const blockKey = isKeyedSegment(selectionPoint.path[0]) ? selectionPoint.path[0]._key : void 0, childKey = isKeyedSegment(selectionPoint.path[2]) ? selectionPoint.path[2]._key : void 0;
|
|
12
|
-
if (!(!blockKey || !childKey)) {
|
|
13
|
-
for (const block of value)
|
|
14
|
-
if (block._key === blockKey && isPortableTextTextBlock(block))
|
|
15
|
-
for (const child of block.children) {
|
|
16
|
-
if (child._key === childKey)
|
|
17
|
-
return {
|
|
18
|
-
path: [{
|
|
19
|
-
_key: block._key
|
|
20
|
-
}],
|
|
21
|
-
offset: offset + selectionPoint.offset
|
|
22
|
-
};
|
|
23
|
-
isPortableTextSpan(child) && (offset += child.text.length);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
1
|
+
import { isEqualSelectionPoints } from "../_chunks-es/util.slice-blocks.js";
|
|
2
|
+
import { blockOffsetToSpanSelectionPoint, getBlockEndPoint, getBlockStartPoint, getTextBlockText, isEmptyTextBlock, isKeyedSegment, isSpan, reverseSelection, sliceBlocks, spanSelectionPointToBlockOffset } from "../_chunks-es/util.slice-blocks.js";
|
|
3
|
+
import { blockOffsetToBlockSelectionPoint, blockOffsetToSelectionPoint, blockOffsetsToSelection, childSelectionPointToBlockOffset, selectionPointToBlockOffset } from "../_chunks-es/util.selection-point-to-block-offset.js";
|
|
4
|
+
import { isTextBlock, mergeTextBlocks, splitTextBlock } from "../_chunks-es/util.split-text-block.js";
|
|
5
|
+
function isEqualSelections(a, b) {
|
|
6
|
+
return !a && !b ? !0 : !a || !b ? !1 : isEqualSelectionPoints(a.anchor, b.anchor) && isEqualSelectionPoints(a.focus, b.focus);
|
|
26
7
|
}
|
|
27
|
-
function
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
function mergeTextBlocks({
|
|
31
|
-
context,
|
|
32
|
-
targetBlock,
|
|
33
|
-
incomingBlock
|
|
34
|
-
}) {
|
|
35
|
-
const parsedIncomingBlock = parseBlock({
|
|
36
|
-
context,
|
|
37
|
-
block: incomingBlock,
|
|
38
|
-
options: {
|
|
39
|
-
refreshKeys: !0
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return !parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock) ? targetBlock : {
|
|
43
|
-
...targetBlock,
|
|
44
|
-
children: [...targetBlock.children, ...parsedIncomingBlock.children],
|
|
45
|
-
markDefs: [...targetBlock.markDefs ?? [], ...parsedIncomingBlock.markDefs ?? []]
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
function splitTextBlock({
|
|
49
|
-
context,
|
|
50
|
-
block,
|
|
51
|
-
point
|
|
52
|
-
}) {
|
|
53
|
-
const firstChild = block.children.at(0), lastChild = block.children.at(block.children.length - 1);
|
|
54
|
-
if (!firstChild || !lastChild)
|
|
55
|
-
return;
|
|
56
|
-
const before = sliceBlocks({
|
|
57
|
-
blocks: [block],
|
|
58
|
-
selection: {
|
|
59
|
-
anchor: {
|
|
60
|
-
path: [{
|
|
61
|
-
_key: block._key
|
|
62
|
-
}, "children", {
|
|
63
|
-
_key: firstChild._key
|
|
64
|
-
}],
|
|
65
|
-
offset: 0
|
|
66
|
-
},
|
|
67
|
-
focus: point
|
|
68
|
-
}
|
|
69
|
-
}).at(0), after = sliceBlocks({
|
|
70
|
-
blocks: [block],
|
|
71
|
-
selection: {
|
|
72
|
-
anchor: point,
|
|
73
|
-
focus: {
|
|
74
|
-
path: [{
|
|
75
|
-
_key: block._key
|
|
76
|
-
}, "children", {
|
|
77
|
-
_key: lastChild._key
|
|
78
|
-
}],
|
|
79
|
-
offset: isSpan(context, lastChild) ? lastChild.text.length : 0
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}).at(0);
|
|
83
|
-
if (!(!before || !after) && !(!isTextBlock(context, before) || !isTextBlock(context, after)))
|
|
84
|
-
return {
|
|
85
|
-
before,
|
|
86
|
-
after
|
|
87
|
-
};
|
|
8
|
+
function isSelectionCollapsed(selection) {
|
|
9
|
+
return selection ? selection.anchor.path.join() === selection.focus.path.join() && selection.anchor.offset === selection.focus.offset : !1;
|
|
88
10
|
}
|
|
89
11
|
export {
|
|
12
|
+
blockOffsetToBlockSelectionPoint,
|
|
13
|
+
blockOffsetToSelectionPoint,
|
|
90
14
|
blockOffsetToSpanSelectionPoint,
|
|
91
15
|
blockOffsetsToSelection,
|
|
92
16
|
childSelectionPointToBlockOffset,
|
|
@@ -95,11 +19,14 @@ export {
|
|
|
95
19
|
getTextBlockText,
|
|
96
20
|
isEmptyTextBlock,
|
|
97
21
|
isEqualSelectionPoints,
|
|
22
|
+
isEqualSelections,
|
|
98
23
|
isKeyedSegment,
|
|
24
|
+
isSelectionCollapsed,
|
|
99
25
|
isSpan,
|
|
100
26
|
isTextBlock,
|
|
101
27
|
mergeTextBlocks,
|
|
102
28
|
reverseSelection,
|
|
29
|
+
selectionPointToBlockOffset,
|
|
103
30
|
sliceBlocks,
|
|
104
31
|
spanSelectionPointToBlockOffset,
|
|
105
32
|
splitTextBlock
|
package/lib/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/utils/util.
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/utils/util.is-equal-selections.ts","../../src/utils/util.is-selection-collapsed.ts"],"sourcesContent":["import type {EditorSelection} from '../types/editor'\nimport {isEqualSelectionPoints} from './util.is-equal-selection-points'\n\n/**\n * @public\n */\nexport function isEqualSelections(a: EditorSelection, b: EditorSelection) {\n if (!a && !b) {\n return true\n }\n\n if (!a || !b) {\n return false\n }\n\n return (\n isEqualSelectionPoints(a.anchor, b.anchor) &&\n isEqualSelectionPoints(a.focus, b.focus)\n )\n}\n","import type {EditorSelection} from '../types/editor'\n\n/**\n * @public\n */\nexport function isSelectionCollapsed(selection: EditorSelection) {\n if (!selection) {\n return false\n }\n\n return (\n selection.anchor.path.join() === selection.focus.path.join() &&\n selection.anchor.offset === selection.focus.offset\n )\n}\n"],"names":["isEqualSelections","a","b","isEqualSelectionPoints","anchor","focus","isSelectionCollapsed","selection","path","join","offset"],"mappings":";;;;AAMgBA,SAAAA,kBAAkBC,GAAoBC,GAAoB;AACpE,SAAA,CAACD,KAAK,CAACC,IACF,KAGL,CAACD,KAAK,CAACC,IACF,KAIPC,uBAAuBF,EAAEG,QAAQF,EAAEE,MAAM,KACzCD,uBAAuBF,EAAEI,OAAOH,EAAEG,KAAK;AAE3C;ACdO,SAASC,qBAAqBC,WAA4B;AAC/D,SAAKA,YAKHA,UAAUH,OAAOI,KAAKC,KAAAA,MAAWF,UAAUF,MAAMG,KAAKC,KAAAA,KACtDF,UAAUH,OAAOM,WAAWH,UAAUF,MAAMK,SALrC;AAOX;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.0",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -73,19 +73,19 @@
|
|
|
73
73
|
"get-random-values-esm": "^1.0.2",
|
|
74
74
|
"lodash": "^4.17.21",
|
|
75
75
|
"lodash.startcase": "^4.4.0",
|
|
76
|
-
"react-compiler-runtime": "19.0.0-beta-
|
|
76
|
+
"react-compiler-runtime": "19.0.0-beta-3229e95-20250315",
|
|
77
77
|
"slate": "0.112.0",
|
|
78
78
|
"slate-dom": "^0.112.2",
|
|
79
79
|
"slate-react": "0.112.1",
|
|
80
80
|
"use-effect-event": "^1.0.2",
|
|
81
81
|
"xstate": "^5.19.2",
|
|
82
|
-
"@portabletext/
|
|
83
|
-
"@portabletext/
|
|
82
|
+
"@portabletext/patches": "1.1.3",
|
|
83
|
+
"@portabletext/block-tools": "1.1.13"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"@portabletext/toolkit": "^2.0.17",
|
|
87
87
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
88
|
-
"@sanity/pkg-utils": "^7.0
|
|
88
|
+
"@sanity/pkg-utils": "^7.1.0",
|
|
89
89
|
"@sanity/schema": "^3.79.0",
|
|
90
90
|
"@sanity/types": "^3.79.0",
|
|
91
91
|
"@testing-library/jest-dom": "^6.6.3",
|
|
@@ -95,20 +95,20 @@
|
|
|
95
95
|
"@types/lodash.startcase": "^4.4.9",
|
|
96
96
|
"@types/react": "^19.0.10",
|
|
97
97
|
"@types/react-dom": "^19.0.4",
|
|
98
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
99
|
-
"@typescript-eslint/parser": "^8.
|
|
98
|
+
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
|
99
|
+
"@typescript-eslint/parser": "^8.26.1",
|
|
100
100
|
"@vitejs/plugin-react": "^4.3.4",
|
|
101
101
|
"@vitest/browser": "^3.0.8",
|
|
102
102
|
"@vitest/coverage-istanbul": "^3.0.8",
|
|
103
|
-
"babel-plugin-react-compiler": "19.0.0-beta-
|
|
103
|
+
"babel-plugin-react-compiler": "19.0.0-beta-3229e95-20250315",
|
|
104
104
|
"eslint": "8.57.1",
|
|
105
|
-
"eslint-plugin-react-compiler": "19.0.0-beta-
|
|
105
|
+
"eslint-plugin-react-compiler": "19.0.0-beta-3229e95-20250315",
|
|
106
106
|
"eslint-plugin-react-hooks": "experimental",
|
|
107
107
|
"jsdom": "^26.0.0",
|
|
108
108
|
"react": "^19.0.0",
|
|
109
109
|
"react-dom": "^19.0.0",
|
|
110
110
|
"rxjs": "^7.8.2",
|
|
111
|
-
"typescript": "5.
|
|
111
|
+
"typescript": "5.8.2",
|
|
112
112
|
"vite": "^6.2.0",
|
|
113
113
|
"vitest": "^3.0.8",
|
|
114
114
|
"vitest-browser-react": "^0.1.1",
|
|
@@ -49,13 +49,13 @@ export const decoratorAddActionImplementation: BehaviorActionImplementation<
|
|
|
49
49
|
|
|
50
50
|
const editorSelection = toPortableTextRange(value, selection, context.schema)
|
|
51
51
|
const anchorOffset = editorSelection
|
|
52
|
-
? utils.
|
|
52
|
+
? utils.selectionPointToBlockOffset({
|
|
53
53
|
value,
|
|
54
54
|
selectionPoint: editorSelection.anchor,
|
|
55
55
|
})
|
|
56
56
|
: undefined
|
|
57
57
|
const focusOffset = editorSelection
|
|
58
|
-
? utils.
|
|
58
|
+
? utils.selectionPointToBlockOffset({
|
|
59
59
|
value,
|
|
60
60
|
selectionPoint: editorSelection.focus,
|
|
61
61
|
})
|
|
@@ -134,6 +134,17 @@ export const decoratorAddActionImplementation: BehaviorActionImplementation<
|
|
|
134
134
|
)
|
|
135
135
|
}
|
|
136
136
|
} else {
|
|
137
|
+
const selectedSpan = Array.from(
|
|
138
|
+
Editor.nodes(editor, {
|
|
139
|
+
at: selection,
|
|
140
|
+
match: (node) => editor.isTextSpan(node),
|
|
141
|
+
}),
|
|
142
|
+
)?.at(0)
|
|
143
|
+
|
|
144
|
+
if (!selectedSpan) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
137
148
|
const [block, blockPath] = Editor.node(editor, selection, {
|
|
138
149
|
depth: 1,
|
|
139
150
|
})
|
|
@@ -8,10 +8,21 @@ const arrowDownOnLonelyBlockObject = defineBehavior({
|
|
|
8
8
|
on: 'keyboard.keydown',
|
|
9
9
|
guard: ({snapshot, event}) => {
|
|
10
10
|
const isArrowDown = isHotkey('ArrowDown', event.originEvent)
|
|
11
|
+
|
|
12
|
+
if (!isArrowDown) {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const collapsedSelection = selectors.isSelectionCollapsed(snapshot)
|
|
17
|
+
|
|
18
|
+
if (!collapsedSelection) {
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
const focusBlockObject = selectors.getFocusBlockObject(snapshot)
|
|
12
23
|
const nextBlock = selectors.getNextBlock(snapshot)
|
|
13
24
|
|
|
14
|
-
return
|
|
25
|
+
return focusBlockObject && !nextBlock
|
|
15
26
|
},
|
|
16
27
|
actions: [() => [raise({type: 'insert.text block', placement: 'after'})]],
|
|
17
28
|
})
|
|
@@ -20,10 +31,21 @@ const arrowUpOnLonelyBlockObject = defineBehavior({
|
|
|
20
31
|
on: 'keyboard.keydown',
|
|
21
32
|
guard: ({snapshot, event}) => {
|
|
22
33
|
const isArrowUp = isHotkey('ArrowUp', event.originEvent)
|
|
34
|
+
|
|
35
|
+
if (!isArrowUp) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const collapsedSelection = selectors.isSelectionCollapsed(snapshot)
|
|
40
|
+
|
|
41
|
+
if (!collapsedSelection) {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
|
|
23
45
|
const focusBlockObject = selectors.getFocusBlockObject(snapshot)
|
|
24
46
|
const previousBlock = selectors.getPreviousBlock(snapshot)
|
|
25
47
|
|
|
26
|
-
return
|
|
48
|
+
return focusBlockObject && !previousBlock
|
|
27
49
|
},
|
|
28
50
|
actions: [() => [raise({type: 'insert.text block', placement: 'before'})]],
|
|
29
51
|
})
|
|
@@ -42,6 +64,10 @@ const breakingBlockObject = defineBehavior({
|
|
|
42
64
|
const clickingAboveLonelyBlockObject = defineBehavior({
|
|
43
65
|
on: 'mouse.click',
|
|
44
66
|
guard: ({snapshot, event}) => {
|
|
67
|
+
if (!selectors.isSelectionCollapsed(snapshot)) {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
|
|
45
71
|
const focusBlockObject = selectors.getFocusBlockObject(snapshot)
|
|
46
72
|
const previousBlock = selectors.getPreviousBlock(snapshot)
|
|
47
73
|
|
|
@@ -58,6 +84,10 @@ const clickingAboveLonelyBlockObject = defineBehavior({
|
|
|
58
84
|
const clickingBelowLonelyBlockObject = defineBehavior({
|
|
59
85
|
on: 'mouse.click',
|
|
60
86
|
guard: ({snapshot, event}) => {
|
|
87
|
+
if (!selectors.isSelectionCollapsed(snapshot)) {
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
|
|
61
91
|
const focusBlockObject = selectors.getFocusBlockObject(snapshot)
|
|
62
92
|
const nextBlock = selectors.getNextBlock(snapshot)
|
|
63
93
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as selectors from '../selectors'
|
|
2
|
+
import {blockOffsetsToSelection} from '../utils'
|
|
2
3
|
import {raiseInsertSoftBreak} from './behavior.default.raise-soft-break'
|
|
3
4
|
import {defineBehavior, raise} from './behavior.types'
|
|
4
5
|
|
|
@@ -37,10 +38,33 @@ const toggleDecoratorOff = defineBehavior({
|
|
|
37
38
|
|
|
38
39
|
const toggleDecoratorOn = defineBehavior({
|
|
39
40
|
on: 'decorator.toggle',
|
|
40
|
-
guard: ({snapshot, event}) =>
|
|
41
|
-
|
|
41
|
+
guard: ({snapshot, event}) => {
|
|
42
|
+
const manualSelection = event.offsets
|
|
43
|
+
? blockOffsetsToSelection({
|
|
44
|
+
value: snapshot.context.value,
|
|
45
|
+
offsets: event.offsets,
|
|
46
|
+
})
|
|
47
|
+
: null
|
|
48
|
+
|
|
49
|
+
if (manualSelection) {
|
|
50
|
+
return !selectors.isActiveDecorator(event.decorator)({
|
|
51
|
+
...snapshot,
|
|
52
|
+
context: {
|
|
53
|
+
...snapshot.context,
|
|
54
|
+
selection: manualSelection,
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return !selectors.isActiveDecorator(event.decorator)(snapshot)
|
|
60
|
+
},
|
|
42
61
|
actions: [
|
|
43
|
-
({event}) => [
|
|
62
|
+
({event}) => [
|
|
63
|
+
raise({
|
|
64
|
+
...event,
|
|
65
|
+
type: 'decorator.add',
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
44
68
|
],
|
|
45
69
|
})
|
|
46
70
|
|
|
@@ -316,24 +340,21 @@ export const defaultBehaviors = [
|
|
|
316
340
|
})
|
|
317
341
|
|
|
318
342
|
if (!droppingOnDragOrigin) {
|
|
319
|
-
return {
|
|
343
|
+
return {
|
|
344
|
+
draggingEntireBlocks,
|
|
345
|
+
draggedBlocks,
|
|
346
|
+
dragOrigin,
|
|
347
|
+
originEvent: event.originEvent,
|
|
348
|
+
}
|
|
320
349
|
}
|
|
321
350
|
|
|
322
351
|
return false
|
|
323
352
|
},
|
|
324
353
|
actions: [
|
|
325
|
-
(
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
placement: draggingEntireBlocks
|
|
330
|
-
? event.originEvent.position.block === 'start'
|
|
331
|
-
? 'before'
|
|
332
|
-
: event.originEvent.position.block === 'end'
|
|
333
|
-
? 'after'
|
|
334
|
-
: 'auto'
|
|
335
|
-
: 'auto',
|
|
336
|
-
}),
|
|
354
|
+
(
|
|
355
|
+
{event},
|
|
356
|
+
{draggingEntireBlocks, draggedBlocks, dragOrigin, originEvent},
|
|
357
|
+
) => [
|
|
337
358
|
...(draggingEntireBlocks
|
|
338
359
|
? draggedBlocks.map((block) =>
|
|
339
360
|
raise({
|
|
@@ -347,6 +368,17 @@ export const defaultBehaviors = [
|
|
|
347
368
|
selection: dragOrigin.selection,
|
|
348
369
|
}),
|
|
349
370
|
]),
|
|
371
|
+
raise({
|
|
372
|
+
type: 'insert.blocks',
|
|
373
|
+
blocks: event.data,
|
|
374
|
+
placement: draggingEntireBlocks
|
|
375
|
+
? originEvent.position.block === 'start'
|
|
376
|
+
? 'before'
|
|
377
|
+
: originEvent.position.block === 'end'
|
|
378
|
+
? 'after'
|
|
379
|
+
: 'auto'
|
|
380
|
+
: 'auto',
|
|
381
|
+
}),
|
|
350
382
|
],
|
|
351
383
|
],
|
|
352
384
|
}),
|
|
@@ -394,6 +426,17 @@ export const defaultBehaviors = [
|
|
|
394
426
|
],
|
|
395
427
|
],
|
|
396
428
|
}),
|
|
429
|
+
defineBehavior({
|
|
430
|
+
on: 'input.*',
|
|
431
|
+
actions: [
|
|
432
|
+
({event}) => [
|
|
433
|
+
raise({
|
|
434
|
+
type: 'deserialize',
|
|
435
|
+
originEvent: event,
|
|
436
|
+
}),
|
|
437
|
+
],
|
|
438
|
+
],
|
|
439
|
+
}),
|
|
397
440
|
toggleAnnotationOff,
|
|
398
441
|
toggleAnnotationOn,
|
|
399
442
|
toggleDecoratorOff,
|
|
@@ -68,6 +68,7 @@ export type SyntheticBehaviorEvent =
|
|
|
68
68
|
| {
|
|
69
69
|
type: 'decorator.toggle'
|
|
70
70
|
decorator: string
|
|
71
|
+
offsets?: {anchor: BlockOffset; focus: BlockOffset}
|
|
71
72
|
}
|
|
72
73
|
| {
|
|
73
74
|
type: 'delete'
|
|
@@ -206,11 +207,13 @@ export type SyntheticBehaviorEvent =
|
|
|
206
207
|
'type',
|
|
207
208
|
'deserialization.failure' | 'deserialization.success'
|
|
208
209
|
> & {
|
|
209
|
-
originEvent:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
originEvent:
|
|
211
|
+
| PickFromUnion<
|
|
212
|
+
NativeBehaviorEvent,
|
|
213
|
+
'type',
|
|
214
|
+
'drag.drop' | 'clipboard.paste'
|
|
215
|
+
>
|
|
216
|
+
| InputBehaviorEvent
|
|
214
217
|
})
|
|
215
218
|
| {
|
|
216
219
|
type: 'serialization.success'
|
|
@@ -241,21 +244,21 @@ type ClipboardBehaviorEvent =
|
|
|
241
244
|
originEvent: {
|
|
242
245
|
dataTransfer: DataTransfer
|
|
243
246
|
}
|
|
244
|
-
position: EventPosition
|
|
247
|
+
position: Pick<EventPosition, 'selection'>
|
|
245
248
|
}
|
|
246
249
|
| {
|
|
247
250
|
type: 'clipboard.cut'
|
|
248
251
|
originEvent: {
|
|
249
252
|
dataTransfer: DataTransfer
|
|
250
253
|
}
|
|
251
|
-
position: EventPosition
|
|
254
|
+
position: Pick<EventPosition, 'selection'>
|
|
252
255
|
}
|
|
253
256
|
| {
|
|
254
257
|
type: 'clipboard.paste'
|
|
255
258
|
originEvent: {
|
|
256
259
|
dataTransfer: DataTransfer
|
|
257
260
|
}
|
|
258
|
-
position: EventPosition
|
|
261
|
+
position: Pick<EventPosition, 'selection'>
|
|
259
262
|
}
|
|
260
263
|
|
|
261
264
|
export function isClipboardBehaviorEvent(
|
|
@@ -270,7 +273,7 @@ type DragBehaviorEvent =
|
|
|
270
273
|
originEvent: {
|
|
271
274
|
dataTransfer: DataTransfer
|
|
272
275
|
}
|
|
273
|
-
position: EventPosition
|
|
276
|
+
position: Pick<EventPosition, 'selection'>
|
|
274
277
|
}
|
|
275
278
|
| {
|
|
276
279
|
type: 'drag.drag'
|
|
@@ -318,6 +321,30 @@ export function isDragBehaviorEvent(
|
|
|
318
321
|
return event.type.startsWith('drag.')
|
|
319
322
|
}
|
|
320
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Used to represent native InputEvents that hold a DataTransfer object.
|
|
326
|
+
*
|
|
327
|
+
* These can either be one of:
|
|
328
|
+
*
|
|
329
|
+
* - insertFromPaste
|
|
330
|
+
* - insertFromPasteAsQuotation
|
|
331
|
+
* - insertFromDrop
|
|
332
|
+
* - insertReplacementText
|
|
333
|
+
* - insertFromYank
|
|
334
|
+
*/
|
|
335
|
+
export type InputBehaviorEvent = {
|
|
336
|
+
type: 'input.*'
|
|
337
|
+
originEvent: {
|
|
338
|
+
dataTransfer: DataTransfer
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function isInputBehaviorEvent(
|
|
343
|
+
event: BehaviorEvent,
|
|
344
|
+
): event is InputBehaviorEvent {
|
|
345
|
+
return event.type.startsWith('input.')
|
|
346
|
+
}
|
|
347
|
+
|
|
321
348
|
export type KeyboardBehaviorEvent =
|
|
322
349
|
| {
|
|
323
350
|
type: 'keyboard.keydown'
|
|
@@ -343,11 +370,13 @@ export function isKeyboardBehaviorEvent(
|
|
|
343
370
|
export type DataBehaviorEvent =
|
|
344
371
|
| {
|
|
345
372
|
type: 'deserialize'
|
|
346
|
-
originEvent:
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
373
|
+
originEvent:
|
|
374
|
+
| PickFromUnion<
|
|
375
|
+
NativeBehaviorEvent,
|
|
376
|
+
'type',
|
|
377
|
+
'drag.drop' | 'clipboard.paste'
|
|
378
|
+
>
|
|
379
|
+
| InputBehaviorEvent
|
|
351
380
|
}
|
|
352
381
|
| {
|
|
353
382
|
type: 'serialize'
|
|
@@ -374,9 +403,10 @@ export function isMouseBehaviorEvent(
|
|
|
374
403
|
*/
|
|
375
404
|
export type NativeBehaviorEvent =
|
|
376
405
|
| ClipboardBehaviorEvent
|
|
406
|
+
| DragBehaviorEvent
|
|
407
|
+
| InputBehaviorEvent
|
|
377
408
|
| KeyboardBehaviorEvent
|
|
378
409
|
| MouseBehaviorEvent
|
|
379
|
-
| DragBehaviorEvent
|
|
380
410
|
|
|
381
411
|
/**
|
|
382
412
|
* @beta
|
|
@@ -440,6 +470,7 @@ export type BehaviorEvent =
|
|
|
440
470
|
| {type: '*'}
|
|
441
471
|
| {type: 'clipboard.*'}
|
|
442
472
|
| {type: 'drag.*'}
|
|
473
|
+
| {type: 'input.*'}
|
|
443
474
|
| {type: 'keyboard.*'}
|
|
444
475
|
| {type: 'mouse.*'}
|
|
445
476
|
|
|
@@ -455,11 +486,13 @@ export type Behavior<
|
|
|
455
486
|
? ClipboardBehaviorEvent
|
|
456
487
|
: TBehaviorEventType extends 'drag.*'
|
|
457
488
|
? DragBehaviorEvent
|
|
458
|
-
: TBehaviorEventType extends '
|
|
459
|
-
?
|
|
460
|
-
: TBehaviorEventType extends '
|
|
461
|
-
?
|
|
462
|
-
:
|
|
489
|
+
: TBehaviorEventType extends 'input.*'
|
|
490
|
+
? InputBehaviorEvent
|
|
491
|
+
: TBehaviorEventType extends 'keyboard.*'
|
|
492
|
+
? KeyboardBehaviorEvent
|
|
493
|
+
: TBehaviorEventType extends 'mouse.*'
|
|
494
|
+
? MouseBehaviorEvent
|
|
495
|
+
: PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
|
|
463
496
|
> = {
|
|
464
497
|
/**
|
|
465
498
|
* The internal editor event that triggers this behavior.
|
|
@@ -541,11 +574,13 @@ export function defineBehavior<
|
|
|
541
574
|
? ClipboardBehaviorEvent
|
|
542
575
|
: TBehaviorEventType extends `drag.*`
|
|
543
576
|
? DragBehaviorEvent
|
|
544
|
-
: TBehaviorEventType extends '
|
|
545
|
-
?
|
|
546
|
-
: TBehaviorEventType extends '
|
|
547
|
-
?
|
|
548
|
-
:
|
|
577
|
+
: TBehaviorEventType extends 'input.*'
|
|
578
|
+
? InputBehaviorEvent
|
|
579
|
+
: TBehaviorEventType extends 'keyboard.*'
|
|
580
|
+
? KeyboardBehaviorEvent
|
|
581
|
+
: TBehaviorEventType extends 'mouse.*'
|
|
582
|
+
? MouseBehaviorEvent
|
|
583
|
+
: PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>
|
|
549
584
|
>,
|
|
550
585
|
): Behavior
|
|
551
586
|
export function defineBehavior<
|
|
@@ -561,11 +596,13 @@ export function defineBehavior<
|
|
|
561
596
|
? ClipboardBehaviorEvent
|
|
562
597
|
: TBehaviorEventType extends `drag.*`
|
|
563
598
|
? DragBehaviorEvent
|
|
564
|
-
: TBehaviorEventType extends '
|
|
565
|
-
?
|
|
566
|
-
: TBehaviorEventType extends '
|
|
567
|
-
?
|
|
568
|
-
:
|
|
599
|
+
: TBehaviorEventType extends 'input.*'
|
|
600
|
+
? InputBehaviorEvent
|
|
601
|
+
: TBehaviorEventType extends 'keyboard.*'
|
|
602
|
+
? KeyboardBehaviorEvent
|
|
603
|
+
: TBehaviorEventType extends 'mouse.*'
|
|
604
|
+
? MouseBehaviorEvent
|
|
605
|
+
: PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>,
|
|
569
606
|
>(
|
|
570
607
|
behavior: Behavior<TBehaviorEventType, TGuardResponse, TBehaviorEvent>,
|
|
571
608
|
): Behavior {
|