@portabletext/editor 1.44.16 → 1.45.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 +5 -5
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/behavior.markdown.cjs +28 -22
- package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
- package/lib/_chunks-cjs/editor-provider.cjs +62 -38
- package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
- package/lib/_chunks-cjs/parse-blocks.cjs +74 -22
- package/lib/_chunks-cjs/parse-blocks.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js +5 -5
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/behavior.markdown.js +28 -22
- package/lib/_chunks-es/behavior.markdown.js.map +1 -1
- package/lib/_chunks-es/editor-provider.js +63 -39
- package/lib/_chunks-es/editor-provider.js.map +1 -1
- package/lib/_chunks-es/parse-blocks.js +75 -23
- package/lib/_chunks-es/parse-blocks.js.map +1 -1
- package/lib/behaviors/index.cjs +18 -14
- package/lib/behaviors/index.cjs.map +1 -1
- package/lib/behaviors/index.d.cts +53 -41
- package/lib/behaviors/index.d.ts +53 -41
- package/lib/behaviors/index.js +18 -14
- package/lib/behaviors/index.js.map +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +28 -9
- package/lib/index.d.ts +28 -9
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.cjs +7 -7
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +8 -6
- package/lib/plugins/index.d.ts +8 -6
- package/lib/plugins/index.js +7 -7
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.d.cts +8 -6
- package/lib/selectors/index.d.ts +8 -6
- package/lib/utils/index.d.cts +8 -6
- package/lib/utils/index.d.ts +8 -6
- package/package.json +3 -3
- package/src/behavior-actions/behavior.action.annotation.add.ts +26 -5
- package/src/behavior-actions/behavior.action.decorator.add.ts +4 -4
- package/src/behavior-actions/behavior.action.delete.text.ts +1 -4
- package/src/behavior-actions/behavior.action.delete.ts +2 -2
- package/src/behavior-actions/behavior.action.insert-inline-object.ts +14 -13
- package/src/behavior-actions/behavior.action.select.ts +1 -1
- package/src/behaviors/behavior.abstract.decorator.ts +2 -2
- package/src/behaviors/behavior.abstract.select.ts +2 -2
- package/src/behaviors/behavior.core.annotations.ts +1 -1
- package/src/behaviors/behavior.core.block-objects.ts +4 -4
- package/src/behaviors/behavior.decorator-pair.ts +3 -3
- package/src/behaviors/behavior.default.ts +4 -4
- package/src/behaviors/behavior.emoji-picker.ts +18 -14
- package/src/behaviors/behavior.markdown.ts +28 -22
- package/src/behaviors/behavior.types.event.ts +11 -6
- package/src/converters/converter.portable-text.deserialize.test.ts +12 -3
- package/src/converters/converter.text-html.deserialize.test.ts +3 -1
- package/src/editor/Editable.tsx +1 -1
- package/src/editor/define-schema.ts +29 -5
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +2 -2
- package/src/editor/plugins/create-with-event-listeners.ts +1 -1
- package/src/internal-utils/parse-blocks.ts +109 -39
- package/src/plugins/plugin.decorator-shortcut.ts +3 -3
- package/src/plugins/plugin.one-line.tsx +1 -1
|
@@ -119,7 +119,10 @@ export type SyntheticBehaviorEvent =
|
|
|
119
119
|
| {
|
|
120
120
|
type: StrictExtract<SyntheticBehaviorEventType, 'decorator.add'>
|
|
121
121
|
decorator: string
|
|
122
|
-
|
|
122
|
+
at?: {
|
|
123
|
+
anchor: BlockOffset
|
|
124
|
+
focus: BlockOffset
|
|
125
|
+
}
|
|
123
126
|
}
|
|
124
127
|
| {
|
|
125
128
|
type: StrictExtract<SyntheticBehaviorEventType, 'decorator.remove'>
|
|
@@ -127,7 +130,7 @@ export type SyntheticBehaviorEvent =
|
|
|
127
130
|
}
|
|
128
131
|
| {
|
|
129
132
|
type: StrictExtract<SyntheticBehaviorEventType, 'delete'>
|
|
130
|
-
|
|
133
|
+
at: NonNullable<EditorSelection>
|
|
131
134
|
}
|
|
132
135
|
| {
|
|
133
136
|
type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'>
|
|
@@ -143,8 +146,10 @@ export type SyntheticBehaviorEvent =
|
|
|
143
146
|
}
|
|
144
147
|
| {
|
|
145
148
|
type: StrictExtract<SyntheticBehaviorEventType, 'delete.text'>
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
at: {
|
|
150
|
+
anchor: BlockOffset
|
|
151
|
+
focus: BlockOffset
|
|
152
|
+
}
|
|
148
153
|
}
|
|
149
154
|
| {
|
|
150
155
|
type: StrictExtract<SyntheticBehaviorEventType, 'focus'>
|
|
@@ -188,7 +193,7 @@ export type SyntheticBehaviorEvent =
|
|
|
188
193
|
}
|
|
189
194
|
| {
|
|
190
195
|
type: StrictExtract<SyntheticBehaviorEventType, 'select'>
|
|
191
|
-
|
|
196
|
+
at: EditorSelection
|
|
192
197
|
}
|
|
193
198
|
| {
|
|
194
199
|
type: StrictExtract<SyntheticBehaviorEventType, 'split.block'>
|
|
@@ -246,7 +251,7 @@ export type AbstractBehaviorEvent =
|
|
|
246
251
|
| {
|
|
247
252
|
type: StrictExtract<AbstractBehaviorEventType, 'decorator.toggle'>
|
|
248
253
|
decorator: string
|
|
249
|
-
|
|
254
|
+
at?: {anchor: BlockOffset; focus: BlockOffset}
|
|
250
255
|
}
|
|
251
256
|
| {
|
|
252
257
|
type: StrictExtract<AbstractBehaviorEventType, 'deserialize'>
|
|
@@ -143,7 +143,9 @@ describe(converterPortableText.deserialize, () => {
|
|
|
143
143
|
converterPortableText.deserialize({
|
|
144
144
|
snapshot: createSnapshot(
|
|
145
145
|
defineSchema({
|
|
146
|
-
blockObjects: [
|
|
146
|
+
blockObjects: [
|
|
147
|
+
{name: 'image', fields: [{name: 'src', type: 'string'}]},
|
|
148
|
+
],
|
|
147
149
|
}),
|
|
148
150
|
),
|
|
149
151
|
event: {
|
|
@@ -204,7 +206,12 @@ describe(converterPortableText.deserialize, () => {
|
|
|
204
206
|
converterPortableText.deserialize({
|
|
205
207
|
snapshot: createSnapshot(
|
|
206
208
|
defineSchema({
|
|
207
|
-
inlineObjects: [
|
|
209
|
+
inlineObjects: [
|
|
210
|
+
{
|
|
211
|
+
name: 'stock-ticker',
|
|
212
|
+
fields: [{name: 'symbol', type: 'string'}],
|
|
213
|
+
},
|
|
214
|
+
],
|
|
208
215
|
}),
|
|
209
216
|
),
|
|
210
217
|
event: {
|
|
@@ -523,7 +530,9 @@ describe(converterPortableText.deserialize, () => {
|
|
|
523
530
|
converterPortableText.deserialize({
|
|
524
531
|
snapshot: createSnapshot(
|
|
525
532
|
defineSchema({
|
|
526
|
-
annotations: [
|
|
533
|
+
annotations: [
|
|
534
|
+
{name: 'link', fields: [{name: 'href', type: 'string'}]},
|
|
535
|
+
],
|
|
527
536
|
}),
|
|
528
537
|
),
|
|
529
538
|
event: {
|
|
@@ -152,7 +152,9 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
152
152
|
converterTextHtml.deserialize({
|
|
153
153
|
snapshot: createSnapshot(
|
|
154
154
|
defineSchema({
|
|
155
|
-
annotations: [
|
|
155
|
+
annotations: [
|
|
156
|
+
{name: 'link', fields: [{name: 'href', type: 'string'}]},
|
|
157
|
+
],
|
|
156
158
|
}),
|
|
157
159
|
),
|
|
158
160
|
event: {
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -940,7 +940,7 @@ export const PortableTextEditable = forwardRef<
|
|
|
940
940
|
type: 'behavior event',
|
|
941
941
|
behaviorEvent: {
|
|
942
942
|
type: 'select',
|
|
943
|
-
|
|
943
|
+
at: isSelectionCollapsed(dragSelection)
|
|
944
944
|
? dragSelection
|
|
945
945
|
: {
|
|
946
946
|
anchor: getSelectionEndPoint(dragSelection),
|
|
@@ -13,6 +13,11 @@ export type BaseDefinition = {
|
|
|
13
13
|
title?: string
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export type FieldDefinition = {
|
|
17
|
+
name: string
|
|
18
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'object'
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
/**
|
|
17
22
|
* @public
|
|
18
23
|
*/
|
|
@@ -20,9 +25,15 @@ export type SchemaDefinition<
|
|
|
20
25
|
TBaseDefinition extends BaseDefinition = BaseDefinition,
|
|
21
26
|
> = {
|
|
22
27
|
decorators?: ReadonlyArray<TBaseDefinition>
|
|
23
|
-
blockObjects?: ReadonlyArray<
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
blockObjects?: ReadonlyArray<
|
|
29
|
+
TBaseDefinition & {fields?: ReadonlyArray<FieldDefinition>}
|
|
30
|
+
>
|
|
31
|
+
inlineObjects?: ReadonlyArray<
|
|
32
|
+
TBaseDefinition & {fields?: ReadonlyArray<FieldDefinition>}
|
|
33
|
+
>
|
|
34
|
+
annotations?: ReadonlyArray<
|
|
35
|
+
TBaseDefinition & {fields?: ReadonlyArray<FieldDefinition>}
|
|
36
|
+
>
|
|
26
37
|
lists?: ReadonlyArray<TBaseDefinition>
|
|
27
38
|
styles?: ReadonlyArray<TBaseDefinition>
|
|
28
39
|
}
|
|
@@ -94,7 +105,11 @@ export function compileSchemaDefinition<
|
|
|
94
105
|
? // This avoids the default title which is a title case of the object name
|
|
95
106
|
defaultObjectTitles[blockObject.name]
|
|
96
107
|
: blockObject.title,
|
|
97
|
-
fields:
|
|
108
|
+
fields:
|
|
109
|
+
blockObject.fields?.map((field) => ({
|
|
110
|
+
name: field.name,
|
|
111
|
+
type: field.type,
|
|
112
|
+
})) ?? [],
|
|
98
113
|
}),
|
|
99
114
|
) ?? []
|
|
100
115
|
|
|
@@ -111,7 +126,11 @@ export function compileSchemaDefinition<
|
|
|
111
126
|
? // This avoids the default title which is a title case of the object name
|
|
112
127
|
defaultObjectTitles[inlineObject.name]
|
|
113
128
|
: inlineObject.title,
|
|
114
|
-
fields:
|
|
129
|
+
fields:
|
|
130
|
+
inlineObject.fields?.map((field) => ({
|
|
131
|
+
name: field.name,
|
|
132
|
+
type: field.type,
|
|
133
|
+
})) ?? [],
|
|
115
134
|
}),
|
|
116
135
|
) ?? []
|
|
117
136
|
|
|
@@ -135,6 +154,11 @@ export function compileSchemaDefinition<
|
|
|
135
154
|
name: annotation.name,
|
|
136
155
|
type: 'object',
|
|
137
156
|
title: annotation.title,
|
|
157
|
+
fields:
|
|
158
|
+
annotation.fields?.map((field) => ({
|
|
159
|
+
name: field.name,
|
|
160
|
+
type: field.type,
|
|
161
|
+
})) ?? [],
|
|
138
162
|
})) ?? [],
|
|
139
163
|
},
|
|
140
164
|
lists:
|
|
@@ -113,7 +113,7 @@ describe('plugin:withEditableAPI: .insertChild()', () => {
|
|
|
113
113
|
text: 'Block A',
|
|
114
114
|
},
|
|
115
115
|
{
|
|
116
|
-
_key: '
|
|
116
|
+
_key: 'k2',
|
|
117
117
|
_type: 'someObject',
|
|
118
118
|
color: 'red',
|
|
119
119
|
},
|
|
@@ -157,7 +157,7 @@ describe('plugin:withEditableAPI: .insertChild()', () => {
|
|
|
157
157
|
text: 'Block A',
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
|
-
_key: '
|
|
160
|
+
_key: 'k2',
|
|
161
161
|
_type: 'someObject',
|
|
162
162
|
color: 'red',
|
|
163
163
|
},
|
|
@@ -160,7 +160,7 @@ export function createWithEventListeners(editorActor: EditorActor) {
|
|
|
160
160
|
type: 'behavior event',
|
|
161
161
|
behaviorEvent: {
|
|
162
162
|
type: 'select',
|
|
163
|
-
|
|
163
|
+
at: slateRangeToSelection({
|
|
164
164
|
schema: editorActor.getSnapshot().context.schema,
|
|
165
165
|
editor,
|
|
166
166
|
range,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
ObjectSchemaType,
|
|
2
3
|
PortableTextBlock,
|
|
3
4
|
PortableTextObject,
|
|
4
5
|
PortableTextSpan,
|
|
5
6
|
PortableTextTextBlock,
|
|
7
|
+
TypedObject,
|
|
6
8
|
} from '@sanity/types'
|
|
7
9
|
import type {EditorSchema} from '../editor/define-schema'
|
|
8
10
|
import type {EditorContext} from '../editor/editor-snapshot'
|
|
@@ -60,22 +62,22 @@ function parseBlockObject({
|
|
|
60
62
|
return undefined
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
) {
|
|
65
|
+
const schemaType = context.schema.blockObjects.find(
|
|
66
|
+
({name}) => name === blockObject._type,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if (!schemaType) {
|
|
68
70
|
return undefined
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
return {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
73
|
+
return parseObject({
|
|
74
|
+
object: blockObject,
|
|
75
|
+
context: {
|
|
76
|
+
keyGenerator: context.keyGenerator,
|
|
77
|
+
schemaType,
|
|
78
|
+
},
|
|
79
|
+
options,
|
|
80
|
+
})
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
export function isTextBlock(
|
|
@@ -123,27 +125,36 @@ function parseTextBlock({
|
|
|
123
125
|
return []
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
const schemaType = context.schema.annotations.find(
|
|
129
|
+
({name}) => name === markDef._type,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
if (!schemaType) {
|
|
133
|
+
return []
|
|
134
|
+
}
|
|
135
|
+
|
|
126
136
|
if (typeof markDef._key !== 'string') {
|
|
137
|
+
// If the `markDef` doesn't have a `_key` then we don't know what spans
|
|
138
|
+
// it belongs to and therefore we have to discard it.
|
|
127
139
|
return []
|
|
128
140
|
}
|
|
129
141
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
_key,
|
|
142
|
-
},
|
|
143
|
-
]
|
|
142
|
+
const parsedAnnotation = parseObject({
|
|
143
|
+
object: markDef,
|
|
144
|
+
context: {
|
|
145
|
+
schemaType,
|
|
146
|
+
keyGenerator: context.keyGenerator,
|
|
147
|
+
},
|
|
148
|
+
options,
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
if (!parsedAnnotation) {
|
|
152
|
+
return []
|
|
144
153
|
}
|
|
145
154
|
|
|
146
|
-
|
|
155
|
+
markDefKeyMap.set(markDef._key, parsedAnnotation._key)
|
|
156
|
+
|
|
157
|
+
return [parsedAnnotation]
|
|
147
158
|
})
|
|
148
159
|
|
|
149
160
|
const unparsedChildren: Array<unknown> = Array.isArray(block.children)
|
|
@@ -283,7 +294,7 @@ export function parseSpan({
|
|
|
283
294
|
}
|
|
284
295
|
}
|
|
285
296
|
|
|
286
|
-
function parseInlineObject({
|
|
297
|
+
export function parseInlineObject({
|
|
287
298
|
inlineObject,
|
|
288
299
|
context,
|
|
289
300
|
options,
|
|
@@ -296,22 +307,81 @@ function parseInlineObject({
|
|
|
296
307
|
return undefined
|
|
297
308
|
}
|
|
298
309
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
) {
|
|
310
|
+
const schemaType = context.schema.inlineObjects.find(
|
|
311
|
+
({name}) => name === inlineObject._type,
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
if (!schemaType) {
|
|
305
315
|
return undefined
|
|
306
316
|
}
|
|
307
317
|
|
|
318
|
+
return parseObject({
|
|
319
|
+
object: inlineObject,
|
|
320
|
+
context: {
|
|
321
|
+
keyGenerator: context.keyGenerator,
|
|
322
|
+
schemaType,
|
|
323
|
+
},
|
|
324
|
+
options,
|
|
325
|
+
})
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function parseAnnotation({
|
|
329
|
+
annotation,
|
|
330
|
+
context,
|
|
331
|
+
options,
|
|
332
|
+
}: {
|
|
333
|
+
annotation: TypedObject
|
|
334
|
+
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
|
|
335
|
+
options: {refreshKeys: boolean}
|
|
336
|
+
}): PortableTextObject | undefined {
|
|
337
|
+
if (!isTypedObject(annotation)) {
|
|
338
|
+
return undefined
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const schemaType = context.schema.annotations.find(
|
|
342
|
+
({name}) => name === annotation._type,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
if (!schemaType) {
|
|
346
|
+
return undefined
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return parseObject({
|
|
350
|
+
object: annotation,
|
|
351
|
+
context: {
|
|
352
|
+
keyGenerator: context.keyGenerator,
|
|
353
|
+
schemaType,
|
|
354
|
+
},
|
|
355
|
+
options,
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function parseObject({
|
|
360
|
+
object,
|
|
361
|
+
context,
|
|
362
|
+
options,
|
|
363
|
+
}: {
|
|
364
|
+
object: TypedObject
|
|
365
|
+
context: Pick<EditorContext, 'keyGenerator'> & {schemaType: ObjectSchemaType}
|
|
366
|
+
options: {refreshKeys: boolean}
|
|
367
|
+
}): PortableTextObject {
|
|
368
|
+
// Validates all props on the object and only takes those that match
|
|
369
|
+
// the name of a field
|
|
370
|
+
const values = context.schemaType.fields.reduce<Record<string, unknown>>(
|
|
371
|
+
(fieldValues, field) => {
|
|
372
|
+
fieldValues[field.name] = object[field.name]
|
|
373
|
+
return fieldValues
|
|
374
|
+
},
|
|
375
|
+
{},
|
|
376
|
+
)
|
|
377
|
+
|
|
308
378
|
return {
|
|
309
|
-
|
|
310
|
-
...inlineObject,
|
|
379
|
+
_type: context.schemaType.name,
|
|
311
380
|
_key: options.refreshKeys
|
|
312
381
|
? context.keyGenerator()
|
|
313
|
-
: typeof
|
|
314
|
-
?
|
|
382
|
+
: typeof object._key === 'string'
|
|
383
|
+
? object._key
|
|
315
384
|
: context.keyGenerator(),
|
|
385
|
+
...values,
|
|
316
386
|
}
|
|
317
387
|
}
|
|
@@ -82,17 +82,17 @@ const selectionListenerCallback: CallbackLogicFunction<
|
|
|
82
82
|
behavior: defineBehavior({
|
|
83
83
|
on: 'select',
|
|
84
84
|
guard: ({snapshot, event}) => {
|
|
85
|
-
if (!event.
|
|
85
|
+
if (!event.at) {
|
|
86
86
|
return {blockOffsets: undefined}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
const anchor = utils.spanSelectionPointToBlockOffset({
|
|
90
90
|
value: snapshot.context.value,
|
|
91
|
-
selectionPoint: event.
|
|
91
|
+
selectionPoint: event.at.anchor,
|
|
92
92
|
})
|
|
93
93
|
const focus = utils.spanSelectionPointToBlockOffset({
|
|
94
94
|
value: snapshot.context.value,
|
|
95
|
-
selectionPoint: event.
|
|
95
|
+
selectionPoint: event.at.focus,
|
|
96
96
|
})
|
|
97
97
|
|
|
98
98
|
if (!anchor || !focus) {
|
|
@@ -14,7 +14,7 @@ const oneLineBehaviors = [
|
|
|
14
14
|
snapshot.context.selection && selectors.isSelectionExpanded(snapshot)
|
|
15
15
|
? {selection: snapshot.context.selection}
|
|
16
16
|
: false,
|
|
17
|
-
actions: [(_, {selection}) => [{type: 'delete', selection}]],
|
|
17
|
+
actions: [(_, {selection}) => [{type: 'delete', at: selection}]],
|
|
18
18
|
}),
|
|
19
19
|
/**
|
|
20
20
|
* All other cases of `insert.break` should be aborted.
|