@portabletext/editor 1.57.3 → 1.57.4

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.
Files changed (43) hide show
  1. package/lib/_chunks-cjs/selector.get-text-before.cjs +3 -3
  2. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  3. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +114 -114
  4. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  5. package/lib/_chunks-cjs/{selector.get-focus-span.cjs → selector.is-selection-expanded.cjs} +25 -25
  6. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -0
  7. package/lib/_chunks-es/selector.get-text-before.js +1 -1
  8. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +93 -93
  9. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  10. package/lib/_chunks-es/{selector.get-focus-span.js → selector.is-selection-expanded.js} +26 -26
  11. package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -0
  12. package/lib/index.cjs +130 -135
  13. package/lib/index.cjs.map +1 -1
  14. package/lib/index.js +95 -100
  15. package/lib/index.js.map +1 -1
  16. package/lib/plugins/index.cjs +16 -16
  17. package/lib/plugins/index.cjs.map +1 -1
  18. package/lib/plugins/index.js +1 -1
  19. package/lib/selectors/index.cjs +14 -14
  20. package/lib/selectors/index.cjs.map +1 -1
  21. package/lib/selectors/index.js +2 -2
  22. package/package.json +8 -8
  23. package/src/editor/Editable.tsx +1 -1
  24. package/src/editor/editor-dom.ts +1 -1
  25. package/src/editor/plugins/createWithEditableAPI.ts +1 -1
  26. package/src/editor/range-decorations-machine.ts +2 -1
  27. package/src/internal-utils/__tests__/ranges.test.ts +1 -1
  28. package/src/internal-utils/move-range-by-operation.ts +19 -0
  29. package/src/internal-utils/{ranges.test.ts → to-slate-range.test.ts} +101 -1
  30. package/src/internal-utils/to-slate-range.ts +171 -0
  31. package/src/operations/behavior.operation.block.set.ts +1 -1
  32. package/src/operations/behavior.operation.block.unset.ts +1 -1
  33. package/src/operations/behavior.operation.child.set.ts +1 -1
  34. package/src/operations/behavior.operation.child.unset.ts +1 -1
  35. package/src/operations/behavior.operation.decorator.add.ts +1 -1
  36. package/src/operations/behavior.operation.delete.ts +1 -1
  37. package/src/operations/behavior.operation.move.block.ts +34 -28
  38. package/src/operations/behavior.operation.select.ts +1 -1
  39. package/src/selectors/selector.get-mark-state.ts +3 -1
  40. package/lib/_chunks-cjs/selector.get-focus-span.cjs.map +0 -1
  41. package/lib/_chunks-es/selector.get-focus-span.js.map +0 -1
  42. package/src/internal-utils/paths.ts +0 -110
  43. package/src/internal-utils/ranges.ts +0 -70
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.57.3",
3
+ "version": "1.57.4",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -109,7 +109,7 @@
109
109
  "react-dom": "^19.1.0",
110
110
  "rxjs": "^7.8.2",
111
111
  "typescript": "5.8.3",
112
- "vite": "^6.2.5",
112
+ "vite": "^7.0.3",
113
113
  "vitest": "^3.2.4",
114
114
  "vitest-browser-react": "^1.0.0",
115
115
  "racejar": "1.2.10"
@@ -129,25 +129,25 @@
129
129
  "scripts": {
130
130
  "build": "pkg-utils build --strict --check --clean",
131
131
  "check:lint": "biome lint .",
132
+ "check:react-compiler": "eslint --cache --no-inline-config --no-eslintrc --ignore-pattern '**/__tests__/**' --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-hooks --rule 'react-hooks/react-compiler: [error]' --rule 'react-hooks/rules-of-hooks: [error]' --rule 'react-hooks/exhaustive-deps: [error]' src",
132
133
  "check:types": "tsc",
133
134
  "check:types:watch": "tsc --watch",
134
- "check:react-compiler": "eslint --cache --no-inline-config --no-eslintrc --ignore-pattern '**/__tests__/**' --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-hooks --rule 'react-hooks/react-compiler: [error]' --rule 'react-hooks/rules-of-hooks: [error]' --rule 'react-hooks/exhaustive-deps: [error]' src",
135
135
  "clean": "del .turbo && del lib && del node_modules",
136
136
  "dev": "pkg-utils watch",
137
137
  "lint:fix": "biome lint --write .",
138
138
  "test": "vitest --run",
139
- "test:watch": "vitest",
140
- "test:e2e:chromium": "vitest --run --project \"browser.bak (chromium)\"",
141
- "test:e2e:chromium:watch": "vitest --project \"browser.bak (chromium)\"",
142
139
  "test:browser": "vitest --run --project browser",
143
- "test:browser:watch": "vitest --project browser",
144
140
  "test:browser:chromium": "vitest --run --project \"browser (chromium)\"",
145
141
  "test:browser:chromium:watch": "vitest --project \"browser (chromium)\"",
146
142
  "test:browser:firefox": "vitest --run --project \"browser (firefox)\"",
147
143
  "test:browser:firefox:watch": "vitest --project \"browser (firefox)\"",
144
+ "test:browser:watch": "vitest --project browser",
148
145
  "test:browser:webkit": "vitest --run --project \"browser (webkit)\"",
149
146
  "test:browser:webkit:watch": "vitest --project \"browser (webkit)\"",
147
+ "test:e2e:chromium": "vitest --run --project \"browser.bak (chromium)\"",
148
+ "test:e2e:chromium:watch": "vitest --project \"browser.bak (chromium)\"",
150
149
  "test:unit": "vitest --run --project unit",
151
- "test:unit:watch": "vitest --project unit"
150
+ "test:unit:watch": "vitest --project unit",
151
+ "test:watch": "vitest"
152
152
  }
153
153
  }
@@ -26,9 +26,9 @@ import {
26
26
  import {debugWithName} from '../internal-utils/debug'
27
27
  import {getEventPosition} from '../internal-utils/event-position'
28
28
  import {parseBlocks} from '../internal-utils/parse-blocks'
29
- import {toSlateRange} from '../internal-utils/ranges'
30
29
  import {normalizeSelection} from '../internal-utils/selection'
31
30
  import {slateRangeToSelection} from '../internal-utils/slate-utils'
31
+ import {toSlateRange} from '../internal-utils/to-slate-range'
32
32
  import {fromSlateValue, isEqualToEmptyEditor} from '../internal-utils/values'
33
33
  import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
34
34
  import type {
@@ -2,7 +2,7 @@ import {Editor} from 'slate'
2
2
  import {DOMEditor} from 'slate-dom'
3
3
  import type {EditorSnapshot} from '..'
4
4
  import type {BehaviorEvent} from '../behaviors'
5
- import {toSlateRange} from '../internal-utils/ranges'
5
+ import {toSlateRange} from '../internal-utils/to-slate-range'
6
6
  import type {PickFromUnion} from '../type-utils'
7
7
  import type {PortableTextSlateEditor} from '../types/editor'
8
8
 
@@ -18,12 +18,12 @@ import {ReactEditor} from 'slate-react'
18
18
  import {buildIndexMaps} from '../../internal-utils/build-index-maps'
19
19
  import {createPlaceholderBlock} from '../../internal-utils/create-placeholder-block'
20
20
  import {debugWithName} from '../../internal-utils/debug'
21
- import {toSlateRange} from '../../internal-utils/ranges'
22
21
  import {
23
22
  isListItemActive,
24
23
  isStyleActive,
25
24
  slateRangeToSelection,
26
25
  } from '../../internal-utils/slate-utils'
26
+ import {toSlateRange} from '../../internal-utils/to-slate-range'
27
27
  import {fromSlateValue, toSlateValue} from '../../internal-utils/values'
28
28
  import {
29
29
  KEY_TO_VALUE_ELEMENT,
@@ -15,8 +15,9 @@ import {
15
15
  type AnyEventObject,
16
16
  type CallbackLogicFunction,
17
17
  } from 'xstate'
18
- import {moveRangeByOperation, toSlateRange} from '../internal-utils/ranges'
18
+ import {moveRangeByOperation} from '../internal-utils/move-range-by-operation'
19
19
  import {slateRangeToSelection} from '../internal-utils/slate-utils'
20
+ import {toSlateRange} from '../internal-utils/to-slate-range'
20
21
  import {isEqualToEmptyEditor} from '../internal-utils/values'
21
22
  import type {PortableTextSlateEditor, RangeDecoration} from '../types/editor'
22
23
  import type {EditorSchema} from './editor-schema'
@@ -1,6 +1,6 @@
1
1
  import type {InsertTextOperation, Range} from 'slate'
2
2
  import {describe, expect, it} from 'vitest'
3
- import {moveRangeByOperation} from '../ranges'
3
+ import {moveRangeByOperation} from '../move-range-by-operation'
4
4
 
5
5
  describe('moveRangeByOperation', () => {
6
6
  it('should move range when inserting text in front of it', () => {
@@ -0,0 +1,19 @@
1
+ import {Point, type Operation, type Range} from 'slate'
2
+
3
+ export function moveRangeByOperation(
4
+ range: Range,
5
+ operation: Operation,
6
+ ): Range | null {
7
+ const anchor = Point.transform(range.anchor, operation)
8
+ const focus = Point.transform(range.focus, operation)
9
+
10
+ if (anchor === null || focus === null) {
11
+ return null
12
+ }
13
+
14
+ if (Point.equals(anchor, range.anchor) && Point.equals(focus, range.focus)) {
15
+ return range
16
+ }
17
+
18
+ return {anchor, focus}
19
+ }
@@ -1,8 +1,8 @@
1
1
  import {describe, expect, test} from 'vitest'
2
2
  import {compileSchemaDefinition} from '../editor/editor-schema'
3
3
  import {defineSchema} from '../editor/editor-schema-definition'
4
- import {toSlateRange} from './ranges'
5
4
  import {createTestKeyGenerator} from './test-key-generator'
5
+ import {toSlateRange} from './to-slate-range'
6
6
 
7
7
  describe(toSlateRange.name, () => {
8
8
  const schema = compileSchemaDefinition(
@@ -14,6 +14,106 @@ describe(toSlateRange.name, () => {
14
14
  }),
15
15
  )
16
16
 
17
+ test('Scenario: Ambiguous offset inside text block', () => {
18
+ const keyGenerator = createTestKeyGenerator()
19
+ const blockKey = keyGenerator()
20
+
21
+ const range = toSlateRange({
22
+ context: {
23
+ schema,
24
+ value: [
25
+ {
26
+ _key: blockKey,
27
+ _type: 'block',
28
+ children: [
29
+ {
30
+ _key: keyGenerator(),
31
+ _type: 'span',
32
+ text: 'foo',
33
+ },
34
+ {
35
+ _key: keyGenerator(),
36
+ _type: 'stock-ticker',
37
+ },
38
+ {
39
+ _key: keyGenerator(),
40
+ _type: 'span',
41
+ text: 'bar',
42
+ },
43
+ ],
44
+ },
45
+ ],
46
+ selection: {
47
+ anchor: {
48
+ path: [{_key: blockKey}],
49
+ // Could point to either before or after the inline object
50
+ offset: 3,
51
+ },
52
+ focus: {
53
+ path: [{_key: blockKey}],
54
+ // Could point to either before or after the inline object
55
+ offset: 3,
56
+ },
57
+ },
58
+ },
59
+ blockIndexMap: new Map([[blockKey, 0]]),
60
+ })
61
+
62
+ expect(range).toEqual({
63
+ anchor: {path: [0, 2], offset: 0},
64
+ focus: {path: [0, 2], offset: 0},
65
+ })
66
+ })
67
+
68
+ test('Scenario: Offset right before inline object', () => {
69
+ const keyGenerator = createTestKeyGenerator()
70
+ const blockKey = keyGenerator()
71
+
72
+ const range = toSlateRange({
73
+ context: {
74
+ schema,
75
+ value: [
76
+ {
77
+ _key: blockKey,
78
+ _type: 'block',
79
+ children: [
80
+ {
81
+ _key: keyGenerator(),
82
+ _type: 'span',
83
+ text: "'",
84
+ },
85
+ {
86
+ _key: keyGenerator(),
87
+ _type: 'stock-ticker',
88
+ },
89
+ {
90
+ _key: keyGenerator(),
91
+ _type: 'span',
92
+ text: "foo'",
93
+ },
94
+ ],
95
+ },
96
+ ],
97
+ selection: {
98
+ anchor: {
99
+ path: [{_key: blockKey}],
100
+ offset: 0,
101
+ },
102
+ focus: {
103
+ path: [{_key: blockKey}],
104
+ offset: 1,
105
+ },
106
+ },
107
+ },
108
+ blockIndexMap: new Map([[blockKey, 0]]),
109
+ })
110
+
111
+ expect(range).toEqual({
112
+ anchor: {path: [0, 0], offset: 0},
113
+ focus: {path: [0, 0], offset: 1},
114
+ })
115
+ })
116
+
17
117
  test("Scenario: Block object offset that doesn't exist", () => {
18
118
  const keyGenerator = createTestKeyGenerator()
19
119
  const blockObjectKey = keyGenerator()
@@ -0,0 +1,171 @@
1
+ import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
2
+ import type {Path, Range} from 'slate'
3
+ import type {EditorContext, EditorSnapshot} from '../editor/editor-snapshot'
4
+ import {
5
+ getBlockKeyFromSelectionPoint,
6
+ getChildKeyFromSelectionPoint,
7
+ } from '../selection/selection-point'
8
+ import type {EditorSelectionPoint} from '../types/editor'
9
+ import {isEqualSelectionPoints} from '../utils'
10
+ import {blockOffsetToSpanSelectionPoint} from '../utils/util.block-offset'
11
+ import {isSpan, isTextBlock} from './parse-blocks'
12
+
13
+ export function toSlateRange(
14
+ snapshot: {
15
+ context: Pick<EditorContext, 'schema' | 'value' | 'selection'>
16
+ } & Pick<EditorSnapshot, 'blockIndexMap'>,
17
+ ): Range | null {
18
+ if (!snapshot.context.selection) {
19
+ return null
20
+ }
21
+
22
+ if (
23
+ isEqualSelectionPoints(
24
+ snapshot.context.selection.anchor,
25
+ snapshot.context.selection.focus,
26
+ )
27
+ ) {
28
+ const anchorPoint = toSlateSelectionPoint(
29
+ snapshot,
30
+ snapshot.context.selection.anchor,
31
+ snapshot.context.selection.backward ? 'forward' : 'backward',
32
+ )
33
+
34
+ if (!anchorPoint) {
35
+ return null
36
+ }
37
+
38
+ return {
39
+ anchor: anchorPoint,
40
+ focus: anchorPoint,
41
+ }
42
+ }
43
+
44
+ const anchorPoint = toSlateSelectionPoint(
45
+ snapshot,
46
+ snapshot.context.selection.anchor,
47
+ snapshot.context.selection.backward ? 'forward' : 'backward',
48
+ )
49
+ const focusPoint = toSlateSelectionPoint(
50
+ snapshot,
51
+ snapshot.context.selection.focus,
52
+ snapshot.context.selection.backward ? 'backward' : 'forward',
53
+ )
54
+
55
+ if (!anchorPoint || !focusPoint) {
56
+ return null
57
+ }
58
+
59
+ return {
60
+ anchor: anchorPoint,
61
+ focus: focusPoint,
62
+ }
63
+ }
64
+
65
+ function toSlateSelectionPoint(
66
+ snapshot: {
67
+ context: Pick<EditorContext, 'schema' | 'value'>
68
+ } & Pick<EditorSnapshot, 'blockIndexMap'>,
69
+ selectionPoint: EditorSelectionPoint,
70
+ direction: 'forward' | 'backward',
71
+ ):
72
+ | {
73
+ path: Path
74
+ offset: number
75
+ }
76
+ | undefined {
77
+ const blockKey = getBlockKeyFromSelectionPoint(selectionPoint)
78
+
79
+ if (!blockKey) {
80
+ return undefined
81
+ }
82
+
83
+ const blockIndex = snapshot.blockIndexMap.get(blockKey)
84
+
85
+ if (blockIndex === undefined) {
86
+ return undefined
87
+ }
88
+
89
+ const block = snapshot.context.value.at(blockIndex)
90
+
91
+ if (!block) {
92
+ return undefined
93
+ }
94
+
95
+ if (!isTextBlock(snapshot.context, block)) {
96
+ return {
97
+ path: [blockIndex, 0],
98
+ offset: 0,
99
+ }
100
+ }
101
+
102
+ let childKey = getChildKeyFromSelectionPoint({
103
+ path: selectionPoint.path,
104
+ offset: 0,
105
+ })
106
+
107
+ // If the block is a text block, but there is no child key in the selection
108
+ // point path, then we can try to find a span selection point by the offset.
109
+ const spanSelectionPoint = !childKey
110
+ ? blockOffsetToSpanSelectionPoint({
111
+ context: {
112
+ schema: snapshot.context.schema,
113
+ value: [block],
114
+ },
115
+ blockOffset: {
116
+ path: [{_key: blockKey}],
117
+ offset: selectionPoint.offset,
118
+ },
119
+ direction,
120
+ })
121
+ : undefined
122
+
123
+ childKey = spanSelectionPoint
124
+ ? getChildKeyFromSelectionPoint(spanSelectionPoint)
125
+ : childKey
126
+
127
+ // If we still don't have a child key, then we have to resort to selecting
128
+ // the first child of the block (which by Slate convention is a span).
129
+ if (!childKey) {
130
+ return {
131
+ path: [blockIndex, 0],
132
+ offset: 0,
133
+ }
134
+ }
135
+
136
+ let offset = spanSelectionPoint?.offset ?? selectionPoint.offset
137
+ let childPath: Array<number> = []
138
+ let childIndex = -1
139
+ let pathChild: PortableTextSpan | PortableTextObject | undefined = undefined
140
+
141
+ for (const child of block.children) {
142
+ childIndex++
143
+ if (child._key === childKey) {
144
+ pathChild = child
145
+ if (isSpan(snapshot.context, child)) {
146
+ childPath = [childIndex]
147
+ } else {
148
+ childPath = [childIndex, 0]
149
+ offset = 0
150
+ }
151
+ break
152
+ }
153
+ }
154
+
155
+ // If we for some unforeseen reason didn't manage to produce a child path,
156
+ // then we have to resort to selecting the first child of the block (which
157
+ // by Slate convention is a span).
158
+ if (childPath.length === 0) {
159
+ return {
160
+ path: [blockIndex, 0],
161
+ offset: 0,
162
+ }
163
+ }
164
+
165
+ return {
166
+ path: [blockIndex].concat(childPath),
167
+ offset: isSpan(snapshot.context, pathChild)
168
+ ? Math.min(pathChild.text.length, offset)
169
+ : offset,
170
+ }
171
+ }
@@ -1,6 +1,6 @@
1
1
  import {Editor, Transforms, type Element as SlateElement} from 'slate'
2
2
  import {parseBlock} from '../internal-utils/parse-blocks'
3
- import {toSlateRange} from '../internal-utils/ranges'
3
+ import {toSlateRange} from '../internal-utils/to-slate-range'
4
4
  import {fromSlateValue, toSlateValue} from '../internal-utils/values'
5
5
  import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
6
6
  import type {BehaviorOperationImplementation} from './behavior.operations'
@@ -1,7 +1,7 @@
1
1
  import {omit} from 'lodash'
2
2
  import {Editor, Transforms} from 'slate'
3
3
  import {isTextBlock, parseBlock} from '../internal-utils/parse-blocks'
4
- import {toSlateRange} from '../internal-utils/ranges'
4
+ import {toSlateRange} from '../internal-utils/to-slate-range'
5
5
  import {fromSlateValue} from '../internal-utils/values'
6
6
  import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
7
7
  import type {BehaviorOperationImplementation} from './behavior.operations'
@@ -1,5 +1,5 @@
1
1
  import {Editor, Element, Transforms} from 'slate'
2
- import {toSlateRange} from '../internal-utils/ranges'
2
+ import {toSlateRange} from '../internal-utils/to-slate-range'
3
3
  import type {BehaviorOperationImplementation} from './behavior.operations'
4
4
 
5
5
  export const childSetOperationImplementation: BehaviorOperationImplementation<
@@ -1,6 +1,6 @@
1
1
  import {applyAll} from '@portabletext/patches'
2
2
  import {Editor, Element, Transforms} from 'slate'
3
- import {toSlateRange} from '../internal-utils/ranges'
3
+ import {toSlateRange} from '../internal-utils/to-slate-range'
4
4
  import type {BehaviorOperationImplementation} from './behavior.operations'
5
5
 
6
6
  export const childUnsetOperationImplementation: BehaviorOperationImplementation<
@@ -1,6 +1,6 @@
1
1
  import {Editor, Range, Text, Transforms} from 'slate'
2
- import {toSlateRange} from '../internal-utils/ranges'
3
2
  import {slateRangeToSelection} from '../internal-utils/slate-utils'
3
+ import {toSlateRange} from '../internal-utils/to-slate-range'
4
4
  import {fromSlateValue} from '../internal-utils/values'
5
5
  import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
6
6
  import * as selectors from '../selectors'
@@ -1,7 +1,7 @@
1
1
  import {Transforms} from 'slate'
2
2
  import {createPlaceholderBlock} from '../internal-utils/create-placeholder-block'
3
- import {toSlateRange} from '../internal-utils/ranges'
4
3
  import {getBlockPath} from '../internal-utils/slate-utils'
4
+ import {toSlateRange} from '../internal-utils/to-slate-range'
5
5
  import {getBlockKeyFromSelectionPoint} from '../selection/selection-point'
6
6
  import type {BehaviorOperationImplementation} from './behavior.operations'
7
7
 
@@ -1,38 +1,44 @@
1
1
  import {Transforms} from 'slate'
2
- import {toSlatePath} from '../internal-utils/paths'
2
+ import {getBlockKeyFromSelectionPoint} from '../selection/selection-point'
3
3
  import type {BehaviorOperationImplementation} from './behavior.operations'
4
4
 
5
5
  export const moveBlockOperationImplementation: BehaviorOperationImplementation<
6
6
  'move.block'
7
- > = ({context, operation}) => {
8
- const at = [
9
- toSlatePath(
10
- {
11
- context: {
12
- schema: context.schema,
13
- value: operation.editor.value,
14
- },
15
- blockIndexMap: operation.editor.blockIndexMap,
16
- },
17
- operation.at,
18
- ).path[0],
19
- ]
20
- const to = [
21
- toSlatePath(
22
- {
23
- context: {
24
- schema: context.schema,
25
- value: operation.editor.value,
26
- },
27
- blockIndexMap: operation.editor.blockIndexMap,
28
- },
29
- operation.to,
30
- ).path[0],
31
- ]
7
+ > = ({operation}) => {
8
+ const originKey = getBlockKeyFromSelectionPoint({
9
+ path: operation.at,
10
+ offset: 0,
11
+ })
12
+
13
+ if (!originKey) {
14
+ throw new Error('Failed to get block key from selection point')
15
+ }
16
+
17
+ const originBlockIndex = operation.editor.blockIndexMap.get(originKey)
18
+
19
+ if (originBlockIndex === undefined) {
20
+ throw new Error('Failed to get block index from block key')
21
+ }
22
+
23
+ const destinationKey = getBlockKeyFromSelectionPoint({
24
+ path: operation.to,
25
+ offset: 0,
26
+ })
27
+
28
+ if (!destinationKey) {
29
+ throw new Error('Failed to get block key from selection point')
30
+ }
31
+
32
+ const destinationBlockIndex =
33
+ operation.editor.blockIndexMap.get(destinationKey)
34
+
35
+ if (destinationBlockIndex === undefined) {
36
+ throw new Error('Failed to get block index from block key')
37
+ }
32
38
 
33
39
  Transforms.moveNodes(operation.editor, {
34
- at,
35
- to,
40
+ at: [originBlockIndex],
41
+ to: [destinationBlockIndex],
36
42
  mode: 'highest',
37
43
  })
38
44
  }
@@ -1,5 +1,5 @@
1
1
  import {Transforms} from 'slate'
2
- import {toSlateRange} from '../internal-utils/ranges'
2
+ import {toSlateRange} from '../internal-utils/to-slate-range'
3
3
  import type {BehaviorOperationImplementation} from './behavior.operations'
4
4
 
5
5
  export const selectOperationImplementation: BehaviorOperationImplementation<
@@ -1,8 +1,10 @@
1
1
  import type {EditorSelector} from '../editor/editor-selector'
2
- import {getFocusSpan, getFocusTextBlock, getSelectedSpans} from '../selectors'
3
2
  import {isSelectionExpanded} from '../utils/util.is-selection-expanded'
3
+ import {getFocusSpan} from './selector.get-focus-span'
4
+ import {getFocusTextBlock} from './selector.get-focus-text-block'
4
5
  import {getNextSpan} from './selector.get-next-span'
5
6
  import {getPreviousSpan} from './selector.get-previous-span'
7
+ import {getSelectedSpans} from './selector.get-selected-spans'
6
8
 
7
9
  export type MarkState = {
8
10
  state: 'changed' | 'unchanged'
@@ -1 +0,0 @@
1
- {"version":3,"file":"selector.get-focus-span.cjs","sources":["../../src/selectors/selector.get-focus-block.ts","../../src/selectors/selector.get-selection-start-point.ts","../../src/selectors/selector.get-focus-text-block.ts","../../src/selectors/selector.get-previous-inline-object.ts","../../src/selectors/selector.get-selected-value.ts","../../src/selectors/selector.get-selection-text.ts","../../src/selectors/selector.is-selection-collapsed.ts","../../src/selectors/selector.is-selection-expanded.ts","../../src/selectors/selector.get-focus-child.ts","../../src/selectors/selector.get-focus-span.ts"],"sourcesContent":["import type {PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getBlockKeyFromSelectionPoint} from '../selection/selection-point'\nimport type {BlockPath} from '../types/paths'\n\n/**\n * @public\n */\nexport const getFocusBlock: EditorSelector<\n {node: PortableTextBlock; path: BlockPath} | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n const key = getBlockKeyFromSelectionPoint(snapshot.context.selection.focus)\n const index = key ? snapshot.blockIndexMap.get(key) : undefined\n\n const node =\n index !== undefined ? snapshot.context.value.at(index) : undefined\n\n return node && key ? {node, path: [{_key: key}]} : undefined\n}\n","import type {EditorSelectionPoint} from '..'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getSelectionStartPoint: EditorSelector<\n EditorSelectionPoint | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n return snapshot.context.selection.backward\n ? snapshot.context.selection.focus\n : snapshot.context.selection.anchor\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isTextBlock} from '../internal-utils/parse-blocks'\nimport type {BlockPath} from '../types/paths'\nimport {getFocusBlock} from './selector.get-focus-block'\n\n/**\n * @public\n */\nexport const getFocusTextBlock: EditorSelector<\n {node: PortableTextTextBlock; path: BlockPath} | undefined\n> = (snapshot) => {\n const focusBlock = getFocusBlock(snapshot)\n\n return focusBlock && isTextBlock(snapshot.context, focusBlock.node)\n ? {node: focusBlock.node, path: focusBlock.path}\n : undefined\n}\n","import {isKeySegment, type PortableTextObject} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport type {ChildPath} from '../types/paths'\nimport {isSpan} from '../utils'\nimport {getFocusTextBlock} from './selector.get-focus-text-block'\nimport {getSelectionStartPoint} from './selector.get-selection-start-point'\n\n/**\n * @public\n */\nexport const getPreviousInlineObject: EditorSelector<\n | {\n node: PortableTextObject\n path: ChildPath\n }\n | undefined\n> = (snapshot) => {\n const focusTextBlock = getFocusTextBlock(snapshot)\n const selectionStartPoint = getSelectionStartPoint(snapshot)\n const selectionStartPointChildKey =\n selectionStartPoint && isKeySegment(selectionStartPoint.path[2])\n ? selectionStartPoint.path[2]._key\n : undefined\n\n if (!focusTextBlock || !selectionStartPointChildKey) {\n return undefined\n }\n\n let inlineObject:\n | {\n node: PortableTextObject\n path: ChildPath\n }\n | undefined\n\n for (const child of focusTextBlock.node.children) {\n if (child._key === selectionStartPointChildKey) {\n break\n }\n\n if (!isSpan(snapshot.context, child)) {\n inlineObject = {\n node: child,\n path: [...focusTextBlock.path, 'children', {_key: child._key}],\n }\n }\n }\n\n return inlineObject\n}\n","import type {PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getBlockKeyFromSelectionPoint} from '../selection/selection-point'\nimport {\n getSelectionEndPoint,\n getSelectionStartPoint,\n sliceBlocks,\n} from '../utils'\n\n/**\n * @public\n */\nexport const getSelectedValue: EditorSelector<Array<PortableTextBlock>> = (\n snapshot,\n) => {\n const selection = snapshot.context.selection\n\n if (!selection) {\n return []\n }\n\n const startPoint = getSelectionStartPoint(selection)\n const endPoint = getSelectionEndPoint(selection)\n const startBlockKey = getBlockKeyFromSelectionPoint(startPoint)\n const endBlockKey = getBlockKeyFromSelectionPoint(endPoint)\n\n if (!startBlockKey || !endBlockKey) {\n return []\n }\n\n const startBlockIndex = snapshot.blockIndexMap.get(startBlockKey)\n const endBlockIndex = snapshot.blockIndexMap.get(endBlockKey)\n\n if (startBlockIndex === undefined || endBlockIndex === undefined) {\n return []\n }\n\n const slicedValue = snapshot.context.value.slice(\n startBlockIndex,\n endBlockIndex + 1,\n )\n\n return sliceBlocks({\n context: snapshot.context,\n blocks: slicedValue,\n })\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {isSpan, isTextBlock} from '../internal-utils/parse-blocks'\nimport {getSelectedValue} from './selector.get-selected-value'\n\n/**\n * @public\n */\nexport const getSelectionText: EditorSelector<string> = (snapshot) => {\n const selectedValue = getSelectedValue(snapshot)\n\n return selectedValue.reduce((text, block) => {\n if (!isTextBlock(snapshot.context, block)) {\n return text\n }\n\n return (\n text +\n block.children.reduce((text, child) => {\n if (isSpan(snapshot.context, child)) {\n return text + child.text\n }\n\n return text\n }, '')\n )\n }, '')\n}\n","import type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const isSelectionCollapsed: EditorSelector<boolean> = (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n return (\n JSON.stringify(snapshot.context.selection.anchor.path) ===\n JSON.stringify(snapshot.context.selection.focus.path) &&\n snapshot.context.selection?.anchor.offset ===\n snapshot.context.selection?.focus.offset\n )\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {isSelectionCollapsed} from './selector.is-selection-collapsed'\n\n/**\n * @public\n */\nexport const isSelectionExpanded: EditorSelector<boolean> = (snapshot) => {\n return !isSelectionCollapsed(snapshot)\n}\n","import type {PortableTextObject, PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getChildKeyFromSelectionPoint} from '../selection/selection-point'\nimport type {ChildPath} from '../types/paths'\nimport {getFocusTextBlock} from './selector.get-focus-text-block'\n\n/**\n * @public\n */\nexport const getFocusChild: EditorSelector<\n | {\n node: PortableTextObject | PortableTextSpan\n path: ChildPath\n }\n | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n const focusBlock = getFocusTextBlock(snapshot)\n\n if (!focusBlock) {\n return undefined\n }\n\n const key = getChildKeyFromSelectionPoint(snapshot.context.selection.focus)\n\n const node = key\n ? focusBlock.node.children.find((span) => span._key === key)\n : undefined\n\n return node && key\n ? {node, path: [...focusBlock.path, 'children', {_key: key}]}\n : undefined\n}\n","import type {PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isSpan} from '../internal-utils/parse-blocks'\nimport type {ChildPath} from '../types/paths'\nimport {getFocusChild} from './selector.get-focus-child'\n\n/**\n * @public\n */\nexport const getFocusSpan: EditorSelector<\n {node: PortableTextSpan; path: ChildPath} | undefined\n> = (snapshot) => {\n const focusChild = getFocusChild(snapshot)\n\n return focusChild && isSpan(snapshot.context, focusChild.node)\n ? {node: focusChild.node, path: focusChild.path}\n : undefined\n}\n"],"names":["getFocusBlock","snapshot","context","selection","key","getBlockKeyFromSelectionPoint","focus","index","blockIndexMap","get","undefined","node","value","at","path","_key","getSelectionStartPoint","backward","anchor","getFocusTextBlock","focusBlock","isTextBlock","getPreviousInlineObject","focusTextBlock","selectionStartPoint","selectionStartPointChildKey","isKeySegment","inlineObject","child","children","isSpan","getSelectedValue","startPoint","endPoint","getSelectionEndPoint","startBlockKey","endBlockKey","startBlockIndex","endBlockIndex","slicedValue","slice","sliceBlocks","blocks","getSelectionText","reduce","text","block","isSelectionCollapsed","JSON","stringify","offset","isSelectionExpanded","getFocusChild","getChildKeyFromSelectionPoint","find","span","getFocusSpan","focusChild"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"selector.get-focus-span.js","sources":["../../src/selectors/selector.get-focus-block.ts","../../src/selectors/selector.get-selection-start-point.ts","../../src/selectors/selector.get-focus-text-block.ts","../../src/selectors/selector.get-previous-inline-object.ts","../../src/selectors/selector.get-selected-value.ts","../../src/selectors/selector.get-selection-text.ts","../../src/selectors/selector.is-selection-collapsed.ts","../../src/selectors/selector.is-selection-expanded.ts","../../src/selectors/selector.get-focus-child.ts","../../src/selectors/selector.get-focus-span.ts"],"sourcesContent":["import type {PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getBlockKeyFromSelectionPoint} from '../selection/selection-point'\nimport type {BlockPath} from '../types/paths'\n\n/**\n * @public\n */\nexport const getFocusBlock: EditorSelector<\n {node: PortableTextBlock; path: BlockPath} | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n const key = getBlockKeyFromSelectionPoint(snapshot.context.selection.focus)\n const index = key ? snapshot.blockIndexMap.get(key) : undefined\n\n const node =\n index !== undefined ? snapshot.context.value.at(index) : undefined\n\n return node && key ? {node, path: [{_key: key}]} : undefined\n}\n","import type {EditorSelectionPoint} from '..'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getSelectionStartPoint: EditorSelector<\n EditorSelectionPoint | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n return snapshot.context.selection.backward\n ? snapshot.context.selection.focus\n : snapshot.context.selection.anchor\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isTextBlock} from '../internal-utils/parse-blocks'\nimport type {BlockPath} from '../types/paths'\nimport {getFocusBlock} from './selector.get-focus-block'\n\n/**\n * @public\n */\nexport const getFocusTextBlock: EditorSelector<\n {node: PortableTextTextBlock; path: BlockPath} | undefined\n> = (snapshot) => {\n const focusBlock = getFocusBlock(snapshot)\n\n return focusBlock && isTextBlock(snapshot.context, focusBlock.node)\n ? {node: focusBlock.node, path: focusBlock.path}\n : undefined\n}\n","import {isKeySegment, type PortableTextObject} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport type {ChildPath} from '../types/paths'\nimport {isSpan} from '../utils'\nimport {getFocusTextBlock} from './selector.get-focus-text-block'\nimport {getSelectionStartPoint} from './selector.get-selection-start-point'\n\n/**\n * @public\n */\nexport const getPreviousInlineObject: EditorSelector<\n | {\n node: PortableTextObject\n path: ChildPath\n }\n | undefined\n> = (snapshot) => {\n const focusTextBlock = getFocusTextBlock(snapshot)\n const selectionStartPoint = getSelectionStartPoint(snapshot)\n const selectionStartPointChildKey =\n selectionStartPoint && isKeySegment(selectionStartPoint.path[2])\n ? selectionStartPoint.path[2]._key\n : undefined\n\n if (!focusTextBlock || !selectionStartPointChildKey) {\n return undefined\n }\n\n let inlineObject:\n | {\n node: PortableTextObject\n path: ChildPath\n }\n | undefined\n\n for (const child of focusTextBlock.node.children) {\n if (child._key === selectionStartPointChildKey) {\n break\n }\n\n if (!isSpan(snapshot.context, child)) {\n inlineObject = {\n node: child,\n path: [...focusTextBlock.path, 'children', {_key: child._key}],\n }\n }\n }\n\n return inlineObject\n}\n","import type {PortableTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getBlockKeyFromSelectionPoint} from '../selection/selection-point'\nimport {\n getSelectionEndPoint,\n getSelectionStartPoint,\n sliceBlocks,\n} from '../utils'\n\n/**\n * @public\n */\nexport const getSelectedValue: EditorSelector<Array<PortableTextBlock>> = (\n snapshot,\n) => {\n const selection = snapshot.context.selection\n\n if (!selection) {\n return []\n }\n\n const startPoint = getSelectionStartPoint(selection)\n const endPoint = getSelectionEndPoint(selection)\n const startBlockKey = getBlockKeyFromSelectionPoint(startPoint)\n const endBlockKey = getBlockKeyFromSelectionPoint(endPoint)\n\n if (!startBlockKey || !endBlockKey) {\n return []\n }\n\n const startBlockIndex = snapshot.blockIndexMap.get(startBlockKey)\n const endBlockIndex = snapshot.blockIndexMap.get(endBlockKey)\n\n if (startBlockIndex === undefined || endBlockIndex === undefined) {\n return []\n }\n\n const slicedValue = snapshot.context.value.slice(\n startBlockIndex,\n endBlockIndex + 1,\n )\n\n return sliceBlocks({\n context: snapshot.context,\n blocks: slicedValue,\n })\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {isSpan, isTextBlock} from '../internal-utils/parse-blocks'\nimport {getSelectedValue} from './selector.get-selected-value'\n\n/**\n * @public\n */\nexport const getSelectionText: EditorSelector<string> = (snapshot) => {\n const selectedValue = getSelectedValue(snapshot)\n\n return selectedValue.reduce((text, block) => {\n if (!isTextBlock(snapshot.context, block)) {\n return text\n }\n\n return (\n text +\n block.children.reduce((text, child) => {\n if (isSpan(snapshot.context, child)) {\n return text + child.text\n }\n\n return text\n }, '')\n )\n }, '')\n}\n","import type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const isSelectionCollapsed: EditorSelector<boolean> = (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n return (\n JSON.stringify(snapshot.context.selection.anchor.path) ===\n JSON.stringify(snapshot.context.selection.focus.path) &&\n snapshot.context.selection?.anchor.offset ===\n snapshot.context.selection?.focus.offset\n )\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {isSelectionCollapsed} from './selector.is-selection-collapsed'\n\n/**\n * @public\n */\nexport const isSelectionExpanded: EditorSelector<boolean> = (snapshot) => {\n return !isSelectionCollapsed(snapshot)\n}\n","import type {PortableTextObject, PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getChildKeyFromSelectionPoint} from '../selection/selection-point'\nimport type {ChildPath} from '../types/paths'\nimport {getFocusTextBlock} from './selector.get-focus-text-block'\n\n/**\n * @public\n */\nexport const getFocusChild: EditorSelector<\n | {\n node: PortableTextObject | PortableTextSpan\n path: ChildPath\n }\n | undefined\n> = (snapshot) => {\n if (!snapshot.context.selection) {\n return undefined\n }\n\n const focusBlock = getFocusTextBlock(snapshot)\n\n if (!focusBlock) {\n return undefined\n }\n\n const key = getChildKeyFromSelectionPoint(snapshot.context.selection.focus)\n\n const node = key\n ? focusBlock.node.children.find((span) => span._key === key)\n : undefined\n\n return node && key\n ? {node, path: [...focusBlock.path, 'children', {_key: key}]}\n : undefined\n}\n","import type {PortableTextSpan} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {isSpan} from '../internal-utils/parse-blocks'\nimport type {ChildPath} from '../types/paths'\nimport {getFocusChild} from './selector.get-focus-child'\n\n/**\n * @public\n */\nexport const getFocusSpan: EditorSelector<\n {node: PortableTextSpan; path: ChildPath} | undefined\n> = (snapshot) => {\n const focusChild = getFocusChild(snapshot)\n\n return focusChild && isSpan(snapshot.context, focusChild.node)\n ? {node: focusChild.node, path: focusChild.path}\n : undefined\n}\n"],"names":["getFocusBlock","snapshot","context","selection","key","getBlockKeyFromSelectionPoint","focus","index","blockIndexMap","get","undefined","node","value","at","path","_key","getSelectionStartPoint","backward","anchor","getFocusTextBlock","focusBlock","isTextBlock","getPreviousInlineObject","focusTextBlock","selectionStartPoint","selectionStartPointChildKey","isKeySegment","inlineObject","child","children","isSpan","getSelectedValue","startPoint","endPoint","getSelectionEndPoint","startBlockKey","endBlockKey","startBlockIndex","endBlockIndex","slicedValue","slice","sliceBlocks","blocks","getSelectionText","reduce","text","block","isSelectionCollapsed","JSON","stringify","offset","isSelectionExpanded","getFocusChild","getChildKeyFromSelectionPoint","find","span","getFocusSpan","focusChild"],"mappings":";;AAQO,MAAMA,gBAERC,CAAAA,aAAa;AAChB,MAAI,CAACA,SAASC,QAAQC;AACpB;AAGF,QAAMC,MAAMC,8BAA8BJ,SAASC,QAAQC,UAAUG,KAAK,GACpEC,QAAQH,MAAMH,SAASO,cAAcC,IAAIL,GAAG,IAAIM,QAEhDC,OACJJ,UAAUG,SAAYT,SAASC,QAAQU,MAAMC,GAAGN,KAAK,IAAIG;AAE3D,SAAOC,QAAQP,MAAM;AAAA,IAACO;AAAAA,IAAMG,MAAM,CAAC;AAAA,MAACC,MAAMX;AAAAA,IAAAA,CAAI;AAAA,EAAA,IAAKM;AACrD,GChBaM,yBAERf,CAAAA,aAAa;AAChB,MAAKA,SAASC,QAAQC;AAItB,WAAOF,SAASC,QAAQC,UAAUc,WAC9BhB,SAASC,QAAQC,UAAUG,QAC3BL,SAASC,QAAQC,UAAUe;AACjC,GCPaC,oBAERlB,CAAAA,aAAa;AAChB,QAAMmB,aAAapB,cAAcC,QAAQ;AAEzC,SAAOmB,cAAcC,YAAYpB,SAASC,SAASkB,WAAWT,IAAI,IAC9D;AAAA,IAACA,MAAMS,WAAWT;AAAAA,IAAMG,MAAMM,WAAWN;AAAAA,EAAAA,IACzCJ;AACN,GCPaY,0BAMRrB,CAAAA,aAAa;AAChB,QAAMsB,iBAAiBJ,kBAAkBlB,QAAQ,GAC3CuB,sBAAsBR,uBAAuBf,QAAQ,GACrDwB,8BACJD,uBAAuBE,aAAaF,oBAAoBV,KAAK,CAAC,CAAC,IAC3DU,oBAAoBV,KAAK,CAAC,EAAEC,OAC5BL;AAEN,MAAI,CAACa,kBAAkB,CAACE;AACtB;AAGF,MAAIE;AAOJ,aAAWC,SAASL,eAAeZ,KAAKkB,UAAU;AAChD,QAAID,MAAMb,SAASU;AACjB;AAGGK,WAAO7B,SAASC,SAAS0B,KAAK,MACjCD,eAAe;AAAA,MACbhB,MAAMiB;AAAAA,MACNd,MAAM,CAAC,GAAGS,eAAeT,MAAM,YAAY;AAAA,QAACC,MAAMa,MAAMb;AAAAA,MAAAA,CAAK;AAAA,IAAA;AAAA,EAGnE;AAEA,SAAOY;AACT,GCrCaI,mBACX9B,CAAAA,aACG;AACH,QAAME,YAAYF,SAASC,QAAQC;AAEnC,MAAI,CAACA;AACH,WAAO,CAAA;AAGT,QAAM6B,aAAahB,yBAAuBb,SAAS,GAC7C8B,WAAWC,qBAAqB/B,SAAS,GACzCgC,gBAAgB9B,8BAA8B2B,UAAU,GACxDI,cAAc/B,8BAA8B4B,QAAQ;AAE1D,MAAI,CAACE,iBAAiB,CAACC;AACrB,WAAO,CAAA;AAGT,QAAMC,kBAAkBpC,SAASO,cAAcC,IAAI0B,aAAa,GAC1DG,gBAAgBrC,SAASO,cAAcC,IAAI2B,WAAW;AAE5D,MAAIC,oBAAoB3B,UAAa4B,kBAAkB5B;AACrD,WAAO,CAAA;AAGT,QAAM6B,cAActC,SAASC,QAAQU,MAAM4B,MACzCH,iBACAC,gBAAgB,CAClB;AAEA,SAAOG,YAAY;AAAA,IACjBvC,SAASD,SAASC;AAAAA,IAClBwC,QAAQH;AAAAA,EAAAA,CACT;AACH,GCvCaI,mBAA4C1C,CAAAA,aACjC8B,iBAAiB9B,QAAQ,EAE1B2C,OAAO,CAACC,MAAMC,UAC5BzB,YAAYpB,SAASC,SAAS4C,KAAK,IAKtCD,OACAC,MAAMjB,SAASe,OAAO,CAACC,OAAMjB,UACvBE,SAAO7B,SAASC,SAAS0B,KAAK,IACzBiB,QAAOjB,MAAMiB,OAGfA,OACN,EAAE,IAXEA,MAaR,EAAE,GCpBME,uBAAiD9C,CAAAA,aACvDA,SAASC,QAAQC,YAKpB6C,KAAKC,UAAUhD,SAASC,QAAQC,UAAUe,OAAOJ,IAAI,MACnDkC,KAAKC,UAAUhD,SAASC,QAAQC,UAAUG,MAAMQ,IAAI,KACtDb,SAASC,QAAQC,WAAWe,OAAOgC,WACjCjD,SAASC,QAAQC,WAAWG,MAAM4C,SAP7B,ICDEC,sBAAgDlD,CAAAA,aACpD,CAAC8C,qBAAqB9C,QAAQ,GCE1BmD,gBAMRnD,CAAAA,aAAa;AAChB,MAAI,CAACA,SAASC,QAAQC;AACpB;AAGF,QAAMiB,aAAaD,kBAAkBlB,QAAQ;AAE7C,MAAI,CAACmB;AACH;AAGF,QAAMhB,MAAMiD,8BAA8BpD,SAASC,QAAQC,UAAUG,KAAK,GAEpEK,OAAOP,MACTgB,WAAWT,KAAKkB,SAASyB,KAAMC,UAASA,KAAKxC,SAASX,GAAG,IACzDM;AAEJ,SAAOC,QAAQP,MACX;AAAA,IAACO;AAAAA,IAAMG,MAAM,CAAC,GAAGM,WAAWN,MAAM,YAAY;AAAA,MAACC,MAAMX;AAAAA,IAAAA,CAAI;AAAA,EAAA,IACzDM;AACN,GC1Ba8C,eAERvD,CAAAA,aAAa;AAChB,QAAMwD,aAAaL,cAAcnD,QAAQ;AAEzC,SAAOwD,cAAc3B,SAAO7B,SAASC,SAASuD,WAAW9C,IAAI,IACzD;AAAA,IAACA,MAAM8C,WAAW9C;AAAAA,IAAMG,MAAM2C,WAAW3C;AAAAA,EAAAA,IACzCJ;AACN;"}