@portabletext/editor 1.26.3 → 1.28.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 (66) hide show
  1. package/README.md +5 -5
  2. package/lib/_chunks-cjs/behavior.markdown.cjs +327 -0
  3. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -0
  4. package/lib/_chunks-cjs/plugin.event-listener.cjs +6827 -0
  5. package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -0
  6. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +88 -88
  7. package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
  8. package/lib/_chunks-es/behavior.markdown.js +332 -0
  9. package/lib/_chunks-es/behavior.markdown.js.map +1 -0
  10. package/lib/_chunks-es/plugin.event-listener.js +6851 -0
  11. package/lib/_chunks-es/plugin.event-listener.js.map +1 -0
  12. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +88 -88
  13. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
  14. package/lib/behaviors/index.cjs +2 -325
  15. package/lib/behaviors/index.cjs.map +1 -1
  16. package/lib/behaviors/index.d.cts +1 -1
  17. package/lib/behaviors/index.d.ts +1 -1
  18. package/lib/behaviors/index.js +2 -326
  19. package/lib/behaviors/index.js.map +1 -1
  20. package/lib/index.cjs +261 -6782
  21. package/lib/index.cjs.map +1 -1
  22. package/lib/index.d.cts +3509 -2161
  23. package/lib/index.d.ts +3509 -2161
  24. package/lib/index.js +223 -6761
  25. package/lib/index.js.map +1 -1
  26. package/lib/plugins/index.cjs +29 -0
  27. package/lib/plugins/index.cjs.map +1 -0
  28. package/lib/plugins/index.d.cts +19411 -0
  29. package/lib/plugins/index.d.ts +19411 -0
  30. package/lib/plugins/index.js +29 -0
  31. package/lib/plugins/index.js.map +1 -0
  32. package/lib/selectors/index.cjs +15 -3
  33. package/lib/selectors/index.cjs.map +1 -1
  34. package/lib/selectors/index.d.cts +19 -1
  35. package/lib/selectors/index.d.ts +19 -1
  36. package/lib/selectors/index.js +17 -4
  37. package/lib/selectors/index.js.map +1 -1
  38. package/package.json +14 -8
  39. package/src/behavior-actions/behavior.action.insert-break.ts +93 -83
  40. package/src/editor/Editable.tsx +6 -6
  41. package/src/editor/PortableTextEditor.tsx +288 -1
  42. package/src/editor/__tests__/PortableTextEditor.test.tsx +0 -1
  43. package/src/editor/components/DefaultObject.tsx +21 -0
  44. package/src/editor/components/Element.tsx +5 -5
  45. package/src/editor/components/Leaf.tsx +1 -6
  46. package/src/editor/components/Synchronizer.tsx +16 -1
  47. package/src/editor/create-editor.ts +8 -48
  48. package/src/editor/editor-machine.ts +118 -131
  49. package/src/editor/plugins/create-with-event-listeners.ts +19 -38
  50. package/src/editor/plugins/createWithPatches.ts +1 -1
  51. package/src/editor/plugins/createWithPortableTextSelections.ts +2 -2
  52. package/src/editor/sync-machine.ts +3 -5
  53. package/src/index.ts +5 -11
  54. package/src/plugins/_exports/index.ts +1 -0
  55. package/src/plugins/index.ts +3 -0
  56. package/src/plugins/plugin.editor-ref.tsx +17 -0
  57. package/src/{editor/editor-event-listener.tsx → plugins/plugin.event-listener.tsx} +7 -6
  58. package/src/plugins/plugin.markdown.tsx +70 -0
  59. package/src/selectors/index.ts +4 -2
  60. package/src/selectors/selector.get-active-annotations.test.ts +122 -0
  61. package/src/selectors/selector.get-active-annotations.ts +30 -0
  62. package/src/selectors/selector.get-selection.ts +8 -0
  63. package/src/selectors/selector.get-value.ts +11 -0
  64. package/src/type-utils.ts +12 -2
  65. package/src/editor/nodes/DefaultAnnotation.tsx +0 -20
  66. package/src/editor/nodes/DefaultObject.tsx +0 -18
@@ -0,0 +1,122 @@
1
+ import type {PortableTextBlock} from '@sanity/types'
2
+ import {expect, test} from 'vitest'
3
+ import type {EditorSchema} from '../editor/define-schema'
4
+ import type {EditorSnapshot} from '../editor/editor-snapshot'
5
+ import {createTestKeyGenerator} from '../internal-utils/test-key-generator'
6
+ import type {EditorSelection} from '../utils'
7
+ import {getActiveAnnotations} from './selector.get-active-annotations'
8
+
9
+ function snapshot(
10
+ value: Array<PortableTextBlock>,
11
+ selection: EditorSelection,
12
+ ): EditorSnapshot {
13
+ return {
14
+ context: {
15
+ converters: [],
16
+ schema: {} as EditorSchema,
17
+ keyGenerator: createTestKeyGenerator(),
18
+ activeDecorators: [],
19
+ value,
20
+ selection,
21
+ },
22
+ }
23
+ }
24
+
25
+ const link = {
26
+ _key: 'k4',
27
+ _type: 'link',
28
+ href: 'https://example.com',
29
+ }
30
+
31
+ const comment = {
32
+ _key: 'k5',
33
+ _type: 'comment',
34
+ comment: 'Consider rewriting this',
35
+ }
36
+
37
+ const block = {
38
+ _type: 'block',
39
+ _key: 'k0',
40
+ children: [
41
+ {
42
+ _key: 'k1',
43
+ _type: 'span',
44
+ text: 'foo',
45
+ marks: ['strong'],
46
+ },
47
+ {
48
+ _type: 'span',
49
+ _key: 'k2',
50
+ text: 'bar',
51
+ marks: [link._key, comment._key, 'strong'],
52
+ },
53
+ {
54
+ _key: 'k3',
55
+ _type: 'span',
56
+ text: 'baz',
57
+ marks: [comment._key, 'strong'],
58
+ },
59
+ ],
60
+ markDefs: [link, comment],
61
+ }
62
+
63
+ test(getActiveAnnotations.name, () => {
64
+ expect(getActiveAnnotations(snapshot([], null))).toEqual([])
65
+ expect(getActiveAnnotations(snapshot([block], null))).toEqual([])
66
+ expect(
67
+ getActiveAnnotations(
68
+ snapshot([block], {
69
+ anchor: {
70
+ path: [{_key: 'k0'}, 'children', {_key: 'k1'}],
71
+ offset: 0,
72
+ },
73
+ focus: {
74
+ path: [{_key: 'k0'}, 'children', {_key: 'k1'}],
75
+ offset: 3,
76
+ },
77
+ }),
78
+ ),
79
+ ).toEqual([])
80
+ expect(
81
+ getActiveAnnotations(
82
+ snapshot([block], {
83
+ anchor: {
84
+ path: [{_key: 'k0'}, 'children', {_key: 'k1'}],
85
+ offset: 0,
86
+ },
87
+ focus: {
88
+ path: [{_key: 'k0'}, 'children', {_key: 'k2'}],
89
+ offset: 3,
90
+ },
91
+ }),
92
+ ),
93
+ ).toEqual([link, comment])
94
+ expect(
95
+ getActiveAnnotations(
96
+ snapshot([block], {
97
+ anchor: {
98
+ path: [{_key: 'k0'}, 'children', {_key: 'k1'}],
99
+ offset: 0,
100
+ },
101
+ focus: {
102
+ path: [{_key: 'k0'}, 'children', {_key: 'k3'}],
103
+ offset: 3,
104
+ },
105
+ }),
106
+ ),
107
+ ).toEqual([link, comment])
108
+ expect(
109
+ getActiveAnnotations(
110
+ snapshot([block], {
111
+ anchor: {
112
+ path: [{_key: 'k0'}, 'children', {_key: 'k3'}],
113
+ offset: 0,
114
+ },
115
+ focus: {
116
+ path: [{_key: 'k0'}, 'children', {_key: 'k3'}],
117
+ offset: 3,
118
+ },
119
+ }),
120
+ ),
121
+ ).toEqual([comment])
122
+ })
@@ -0,0 +1,30 @@
1
+ import {isPortableTextTextBlock, type PortableTextObject} from '@sanity/types'
2
+ import type {EditorSelector} from '../editor/editor-selector'
3
+ import {getSelectedSpans} from './selector.get-selected-spans'
4
+ import {getSelectedBlocks} from './selectors'
5
+
6
+ /**
7
+ * @public
8
+ */
9
+ export const getActiveAnnotations: EditorSelector<Array<PortableTextObject>> = (
10
+ snapshot,
11
+ ) => {
12
+ if (!snapshot.context.selection) {
13
+ return []
14
+ }
15
+
16
+ const selectedBlocks = getSelectedBlocks(snapshot)
17
+ const selectedSpans = getSelectedSpans(snapshot)
18
+
19
+ if (selectedSpans.length === 0) {
20
+ return []
21
+ }
22
+
23
+ const selectionMarkDefs = selectedBlocks.flatMap((block) =>
24
+ isPortableTextTextBlock(block.node) ? (block.node.markDefs ?? []) : [],
25
+ )
26
+
27
+ return selectionMarkDefs.filter((markDef) =>
28
+ selectedSpans.some((span) => span.node.marks?.includes(markDef._key)),
29
+ )
30
+ }
@@ -0,0 +1,8 @@
1
+ import type {EditorSelection, EditorSelector} from './_exports'
2
+
3
+ /**
4
+ * @public
5
+ */
6
+ export const getSelection: EditorSelector<EditorSelection> = ({context}) => {
7
+ return context.selection
8
+ }
@@ -0,0 +1,11 @@
1
+ import type {PortableTextBlock} from '@sanity/types'
2
+ import type {EditorSelector} from './_exports'
3
+
4
+ /**
5
+ * @public
6
+ */
7
+ export const getValue: EditorSelector<Array<PortableTextBlock>> = ({
8
+ context,
9
+ }) => {
10
+ return context.value
11
+ }
package/src/type-utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @alpha
2
+ * @internal
3
3
  */
4
4
  export type PickFromUnion<
5
5
  TUnion,
@@ -8,10 +8,20 @@ export type PickFromUnion<
8
8
  > = TUnion extends Record<TTagKey, TPickedTags> ? TUnion : never
9
9
 
10
10
  /**
11
- * @alpha
11
+ * @internal
12
12
  */
13
13
  export type OmitFromUnion<
14
14
  TUnion,
15
15
  TTagKey extends keyof TUnion,
16
16
  TOmittedTags extends TUnion[TTagKey],
17
17
  > = TUnion extends Record<TTagKey, TOmittedTags> ? never : TUnion
18
+
19
+ export type NamespaceEvent<TEvent, TNamespace extends string> = TEvent extends {
20
+ type: infer TEventType
21
+ }
22
+ ? {
23
+ [K in keyof TEvent]: K extends 'type'
24
+ ? `${TNamespace}.${TEventType & string}`
25
+ : TEvent[K]
26
+ }
27
+ : never
@@ -1,20 +0,0 @@
1
- import type {PortableTextObject} from '@sanity/types'
2
- import {useCallback, type ReactNode} from 'react'
3
-
4
- type Props = {
5
- annotation: PortableTextObject
6
- children: ReactNode
7
- }
8
- export function DefaultAnnotation(props: Props) {
9
- const handleClick = useCallback(
10
- () => alert(JSON.stringify(props.annotation)),
11
- [props.annotation],
12
- )
13
- return (
14
- <span style={{color: 'blue'}} onClick={handleClick}>
15
- {props.children}
16
- </span>
17
- )
18
- }
19
-
20
- DefaultAnnotation.displayName = 'DefaultAnnotation'
@@ -1,18 +0,0 @@
1
- import type {PortableTextBlock, PortableTextChild} from '@sanity/types'
2
- import type {JSX} from 'react'
3
-
4
- type Props = {
5
- value: PortableTextBlock | PortableTextChild
6
- }
7
-
8
- const DefaultObject = (props: Props): JSX.Element => {
9
- return (
10
- <div style={{userSelect: 'none'}}>
11
- [{props.value._type}: {props.value._key}]
12
- </div>
13
- )
14
- }
15
-
16
- DefaultObject.displayName = 'DefaultObject'
17
-
18
- export default DefaultObject