@portabletext/editor 2.7.1 → 2.8.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.
Files changed (48) hide show
  1. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +3 -1
  2. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  3. package/lib/_chunks-cjs/util.slice-blocks.cjs +60 -6
  4. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  5. package/lib/_chunks-dts/behavior.types.action.d.cts +95 -95
  6. package/lib/_chunks-dts/behavior.types.action.d.ts +86 -86
  7. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +4 -2
  8. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  9. package/lib/_chunks-es/util.slice-blocks.js +56 -5
  10. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  11. package/lib/index.cjs +94 -121
  12. package/lib/index.cjs.map +1 -1
  13. package/lib/index.js +90 -118
  14. package/lib/index.js.map +1 -1
  15. package/lib/plugins/index.d.cts +3 -3
  16. package/lib/selectors/index.d.cts +13 -3
  17. package/lib/selectors/index.d.ts +13 -3
  18. package/package.json +12 -13
  19. package/src/behaviors/behavior.abstract.insert.ts +58 -1
  20. package/src/behaviors/behavior.core.annotations.ts +24 -2
  21. package/src/behaviors/behavior.core.ts +1 -1
  22. package/src/behaviors/behavior.types.event.ts +18 -18
  23. package/src/converters/converter.text-html.serialize.test.ts +27 -17
  24. package/src/converters/converter.text-plain.test.ts +1 -1
  25. package/src/editor/plugins/createWithEditableAPI.ts +16 -0
  26. package/src/internal-utils/parse-blocks.ts +2 -1
  27. package/src/operations/behavior.operation.annotation.add.ts +1 -12
  28. package/src/operations/behavior.operations.ts +0 -18
  29. package/src/selectors/selector.is-active-annotation.test.ts +320 -0
  30. package/src/selectors/selector.is-active-annotation.ts +24 -0
  31. package/src/utils/util.slice-blocks.test.ts +39 -5
  32. package/src/utils/util.slice-blocks.ts +36 -3
  33. package/src/editor/__tests__/PortableTextEditor.test.tsx +0 -430
  34. package/src/editor/__tests__/PortableTextEditorTester.tsx +0 -58
  35. package/src/editor/__tests__/RangeDecorations.test.tsx +0 -213
  36. package/src/editor/__tests__/insert-block.test.tsx +0 -224
  37. package/src/editor/__tests__/self-solving.test.tsx +0 -183
  38. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +0 -298
  39. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +0 -177
  40. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +0 -538
  41. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +0 -162
  42. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +0 -65
  43. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +0 -612
  44. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +0 -103
  45. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +0 -147
  46. package/src/internal-utils/__tests__/valueNormalization.test.tsx +0 -79
  47. package/src/operations/behavior.operation.insert-inline-object.ts +0 -59
  48. package/src/operations/behavior.operation.insert-span.ts +0 -48
@@ -1,147 +0,0 @@
1
- import {createTestKeyGenerator} from '@portabletext/test'
2
- import {render, waitFor} from '@testing-library/react'
3
- import {createRef, type RefObject} from 'react'
4
- import {describe, expect, it, vi} from 'vitest'
5
- import {PortableTextEditorTester} from '../../__tests__/PortableTextEditorTester'
6
- import {PortableTextEditor} from '../../PortableTextEditor'
7
-
8
- const initialValue = [
9
- {
10
- _key: 'a',
11
- _type: 'block',
12
- children: [
13
- {
14
- _key: 'a1',
15
- _type: 'span',
16
- marks: [],
17
- text: 'Block A',
18
- },
19
- ],
20
- markDefs: [],
21
- style: 'normal',
22
- },
23
- {
24
- _key: 'b',
25
- _type: 'block',
26
- children: [
27
- {
28
- _key: 'b1',
29
- _type: 'span',
30
- marks: [],
31
- text: 'Block B',
32
- },
33
- ],
34
- markDefs: [],
35
- style: 'normal',
36
- },
37
- ]
38
-
39
- const initialSelection = {
40
- focus: {path: [{_key: 'b'}, 'children', {_key: 'b1'}], offset: 7},
41
- anchor: {path: [{_key: 'b'}, 'children', {_key: 'b1'}], offset: 7},
42
- }
43
-
44
- describe('plugin:withUndoRedo', () => {
45
- it('preserves the keys when undoing ', async () => {
46
- const editorRef: RefObject<PortableTextEditor | null> = createRef()
47
- const onChange = vi.fn()
48
- render(
49
- <PortableTextEditorTester
50
- keyGenerator={createTestKeyGenerator()}
51
- onChange={onChange}
52
- ref={editorRef}
53
- value={initialValue}
54
- />,
55
- )
56
-
57
- await waitFor(() => {
58
- if (editorRef.current) {
59
- expect(onChange).toHaveBeenCalledWith({
60
- type: 'value',
61
- value: initialValue,
62
- })
63
- expect(onChange).toHaveBeenCalledWith({type: 'ready'})
64
- }
65
- })
66
-
67
- await waitFor(() => {
68
- if (editorRef.current) {
69
- PortableTextEditor.focus(editorRef.current)
70
- PortableTextEditor.select(editorRef.current, initialSelection)
71
- PortableTextEditor.delete(
72
- editorRef.current,
73
- PortableTextEditor.getSelection(editorRef.current),
74
- {mode: 'blocks'},
75
- )
76
- expect(PortableTextEditor.getValue(editorRef.current))
77
- .toMatchInlineSnapshot(`
78
- [
79
- {
80
- "_key": "a",
81
- "_type": "block",
82
- "children": [
83
- {
84
- "_key": "a1",
85
- "_type": "span",
86
- "marks": [],
87
- "text": "Block A",
88
- },
89
- ],
90
- "markDefs": [],
91
- "style": "normal",
92
- },
93
- ]
94
- `)
95
- PortableTextEditor.undo(editorRef.current)
96
- expect(PortableTextEditor.getValue(editorRef.current)).toEqual(
97
- initialValue,
98
- )
99
- }
100
- })
101
- })
102
- it('preserves the keys when redoing ', async () => {
103
- const editorRef: RefObject<PortableTextEditor | null> = createRef()
104
- const onChange = vi.fn()
105
-
106
- render(
107
- <PortableTextEditorTester
108
- keyGenerator={createTestKeyGenerator()}
109
- onChange={onChange}
110
- ref={editorRef}
111
- value={initialValue}
112
- />,
113
- )
114
-
115
- await waitFor(() => {
116
- if (editorRef.current) {
117
- expect(onChange).toHaveBeenCalledWith({
118
- type: 'value',
119
- value: initialValue,
120
- })
121
- expect(onChange).toHaveBeenCalledWith({type: 'ready'})
122
- }
123
- })
124
-
125
- await waitFor(() => {
126
- if (editorRef.current) {
127
- PortableTextEditor.focus(editorRef.current)
128
- PortableTextEditor.select(editorRef.current, initialSelection)
129
- PortableTextEditor.insertBlock(
130
- editorRef.current,
131
- editorRef.current.schemaTypes.block,
132
- {
133
- children: [{_key: 'c1', _type: 'span', marks: [], text: 'Block C'}],
134
- },
135
- )
136
- const producedKey = PortableTextEditor.getValue(
137
- editorRef.current,
138
- )?.slice(-1)[0]?._key
139
- PortableTextEditor.undo(editorRef.current)
140
- PortableTextEditor.redo(editorRef.current)
141
- expect(
142
- PortableTextEditor.getValue(editorRef.current)?.slice(-1)[0]?._key,
143
- ).toEqual(producedKey)
144
- }
145
- })
146
- })
147
- })
@@ -1,79 +0,0 @@
1
- import {createTestKeyGenerator} from '@portabletext/test'
2
- import {render, waitFor} from '@testing-library/react'
3
- import {createRef, type RefObject} from 'react'
4
- import {describe, expect, it, vi} from 'vitest'
5
- import {PortableTextEditorTester} from '../../editor/__tests__/PortableTextEditorTester'
6
- import {PortableTextEditor} from '../../editor/PortableTextEditor'
7
-
8
- describe('values: normalization', () => {
9
- it("accepts incoming value with blocks without a style or markDefs prop, but doesn't leave them without them when editing them", async () => {
10
- const editorRef: RefObject<PortableTextEditor | null> = createRef()
11
- const initialValue = [
12
- {
13
- _key: '5fc57af23597',
14
- _type: 'block',
15
- children: [
16
- {
17
- _key: 'be1c67c6971a',
18
- _type: 'span',
19
- marks: [],
20
- text: 'Hello',
21
- },
22
- ],
23
- markDefs: [],
24
- },
25
- ]
26
- const onChange = vi.fn()
27
- render(
28
- <PortableTextEditorTester
29
- keyGenerator={createTestKeyGenerator()}
30
- onChange={onChange}
31
- ref={editorRef}
32
- value={initialValue}
33
- />,
34
- )
35
-
36
- await waitFor(() => {
37
- if (editorRef.current) {
38
- expect(onChange).toHaveBeenCalledWith({
39
- type: 'value',
40
- value: initialValue,
41
- })
42
- expect(onChange).toHaveBeenCalledWith({type: 'ready'})
43
- }
44
- })
45
-
46
- await waitFor(() => {
47
- if (editorRef.current) {
48
- PortableTextEditor.focus(editorRef.current)
49
- PortableTextEditor.select(editorRef.current, {
50
- focus: {
51
- path: [{_key: '5fc57af23597'}, 'children', {_key: 'be1c67c6971a'}],
52
- offset: 0,
53
- },
54
- anchor: {
55
- path: [{_key: '5fc57af23597'}, 'children', {_key: 'be1c67c6971a'}],
56
- offset: 5,
57
- },
58
- })
59
- PortableTextEditor.toggleMark(editorRef.current, 'strong')
60
- expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
61
- {
62
- _key: '5fc57af23597',
63
- _type: 'block',
64
- children: [
65
- {
66
- _key: 'be1c67c6971a',
67
- _type: 'span',
68
- marks: ['strong'],
69
- text: 'Hello',
70
- },
71
- ],
72
- markDefs: [],
73
- style: 'normal',
74
- },
75
- ])
76
- }
77
- })
78
- })
79
- })
@@ -1,59 +0,0 @@
1
- import {Editor, Transforms, type Element} from 'slate'
2
- import {parseInlineObject} from '../internal-utils/parse-blocks'
3
- import {toSlateValue} from '../internal-utils/values'
4
- import type {BehaviorOperationImplementation} from './behavior.operations'
5
-
6
- export const insertInlineObjectOperationImplementation: BehaviorOperationImplementation<
7
- 'insert.inline object'
8
- > = ({context, operation}) => {
9
- const parsedInlineObject = parseInlineObject({
10
- context,
11
- inlineObject: {
12
- _type: operation.inlineObject.name,
13
- ...(operation.inlineObject.value ?? {}),
14
- },
15
- options: {refreshKeys: false, validateFields: true},
16
- })
17
-
18
- if (!parsedInlineObject) {
19
- throw new Error(
20
- `Failed to parse inline object ${JSON.stringify(operation.inlineObject)}`,
21
- )
22
- }
23
-
24
- if (!operation.editor.selection) {
25
- console.error('Unable to insert inline object without selection')
26
- return
27
- }
28
-
29
- const [focusTextBlock] = Array.from(
30
- Editor.nodes(operation.editor, {
31
- at: operation.editor.selection.focus.path,
32
- match: (node) => operation.editor.isTextBlock(node),
33
- }),
34
- ).at(0) ?? [undefined, undefined]
35
-
36
- if (!focusTextBlock) {
37
- console.error('Unable to perform action without focus text block')
38
- return
39
- }
40
-
41
- const block = toSlateValue(
42
- [
43
- {
44
- _type: context.schema.block.name,
45
- _key: context.keyGenerator(),
46
- children: [parsedInlineObject],
47
- },
48
- ],
49
- {schemaTypes: context.schema},
50
- ).at(0) as unknown as Element
51
- const child = block?.children.at(0)
52
-
53
- if (!child) {
54
- console.error('Unable to insert inline object')
55
- return
56
- }
57
-
58
- Transforms.insertNodes(operation.editor, child)
59
- }
@@ -1,48 +0,0 @@
1
- import {Editor, Transforms} from 'slate'
2
- import type {BehaviorOperationImplementation} from './behavior.operations'
3
-
4
- export const insertSpanOperationImplementation: BehaviorOperationImplementation<
5
- 'insert.span'
6
- > = ({context, operation}) => {
7
- if (!operation.editor.selection) {
8
- console.error('Unable to perform action without selection', operation)
9
- return
10
- }
11
-
12
- const [focusBlock, focusBlockPath] = Array.from(
13
- Editor.nodes(operation.editor, {
14
- at: operation.editor.selection.focus.path,
15
- match: (node) => operation.editor.isTextBlock(node),
16
- }),
17
- )[0] ?? [undefined, undefined]
18
-
19
- if (!focusBlock || !focusBlockPath) {
20
- console.error('Unable to perform action without focus block', operation)
21
- return
22
- }
23
-
24
- const markDefs = focusBlock.markDefs ?? []
25
- const annotations = operation.annotations
26
- ? operation.annotations.map((annotation) => ({
27
- _type: annotation.name,
28
- _key: context.keyGenerator(),
29
- ...annotation.value,
30
- }))
31
- : undefined
32
-
33
- if (annotations && annotations.length > 0) {
34
- Transforms.setNodes(operation.editor, {
35
- markDefs: [...markDefs, ...annotations],
36
- })
37
- }
38
-
39
- Transforms.insertNodes(operation.editor, {
40
- _type: 'span',
41
- _key: context.keyGenerator(),
42
- text: operation.text,
43
- marks: [
44
- ...(annotations?.map((annotation) => annotation._key) ?? []),
45
- ...(operation.decorators ?? []),
46
- ],
47
- })
48
- }