@portabletext/editor 1.7.1 → 1.9.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.
@@ -206,77 +206,18 @@ export function createEditableAPI(
206
206
  type: TSchemaType,
207
207
  value?: {[prop: string]: any},
208
208
  ): Path => {
209
- const block = toSlateValue(
210
- [
211
- {
212
- _key: editorActor.getSnapshot().context.keyGenerator(),
213
- _type: type.name,
214
- ...(value ? value : {}),
215
- },
216
- ],
217
- {schemaTypes: editorActor.getSnapshot().context.schema},
218
- )[0] as unknown as Node
219
-
220
- if (!editor.selection) {
221
- const lastBlock = Array.from(
222
- Editor.nodes(editor, {
223
- match: (n) => !Editor.isEditor(n),
224
- at: [],
225
- reverse: true,
226
- }),
227
- )[0]
228
-
229
- // If there is no selection, let's just insert the new block at the
230
- // end of the document
231
- Editor.insertNode(editor, block)
232
-
233
- if (lastBlock && isEqualToEmptyEditor([lastBlock[0]], types)) {
234
- // And if the last block was an empty text block, let's remove
235
- // that too
236
- Transforms.removeNodes(editor, {at: lastBlock[1]})
237
- }
238
-
239
- editor.onChange()
240
-
241
- return (
242
- toPortableTextRange(
243
- fromSlateValue(
244
- editor.children,
245
- types.block.name,
246
- KEY_TO_VALUE_ELEMENT.get(editor),
247
- ),
248
- editor.selection,
249
- types,
250
- )?.focus.path ?? []
251
- )
252
- }
253
-
254
- const focusBlock = Array.from(
255
- Editor.nodes(editor, {
256
- at: editor.selection.focus.path.slice(0, 1),
257
- match: (n) => n._type === types.block.name,
258
- }),
259
- )[0]
260
-
261
- Editor.insertNode(editor, block)
262
-
263
- if (focusBlock && isEqualToEmptyEditor([focusBlock[0]], types)) {
264
- Transforms.removeNodes(editor, {at: focusBlock[1]})
265
- }
266
-
267
- editor.onChange()
268
-
269
- return (
270
- toPortableTextRange(
271
- fromSlateValue(
272
- editor.children,
273
- types.block.name,
274
- KEY_TO_VALUE_ELEMENT.get(editor),
275
- ),
276
- editor.selection,
277
- types,
278
- )?.focus.path || []
279
- )
209
+ return insertBlockObjectActionImplementation({
210
+ context: {
211
+ keyGenerator: editorActor.getSnapshot().context.keyGenerator,
212
+ schema: types,
213
+ },
214
+ action: {
215
+ type: 'insert block object',
216
+ name: type.name,
217
+ value,
218
+ editor,
219
+ },
220
+ })
280
221
  },
281
222
  hasBlockStyle: (style: string): boolean => {
282
223
  try {
@@ -546,6 +487,85 @@ export function createEditableAPI(
546
487
  return editableApi
547
488
  }
548
489
 
490
+ export const insertBlockObjectActionImplementation: BehaviourActionImplementation<
491
+ 'insert block object',
492
+ Path
493
+ > = ({context, action}) => {
494
+ const editor = action.editor
495
+ const types = context.schema
496
+ const block = toSlateValue(
497
+ [
498
+ {
499
+ _key: context.keyGenerator(),
500
+ _type: action.name,
501
+ ...(action.value ? action.value : {}),
502
+ },
503
+ ],
504
+ {schemaTypes: context.schema},
505
+ )[0] as unknown as Node
506
+
507
+ if (!editor.selection) {
508
+ const lastBlock = Array.from(
509
+ Editor.nodes(editor, {
510
+ match: (n) => !Editor.isEditor(n),
511
+ at: [],
512
+ reverse: true,
513
+ }),
514
+ )[0]
515
+
516
+ // If there is no selection, let's just insert the new block at the
517
+ // end of the document
518
+ Editor.insertNode(editor, block)
519
+
520
+ if (lastBlock && isEqualToEmptyEditor([lastBlock[0]], types)) {
521
+ // And if the last block was an empty text block, let's remove
522
+ // that too
523
+ Transforms.removeNodes(editor, {at: lastBlock[1]})
524
+ }
525
+
526
+ editor.onChange()
527
+
528
+ return (
529
+ toPortableTextRange(
530
+ fromSlateValue(
531
+ editor.children,
532
+ types.block.name,
533
+ KEY_TO_VALUE_ELEMENT.get(editor),
534
+ ),
535
+ editor.selection,
536
+ types,
537
+ )?.focus.path ?? []
538
+ )
539
+ }
540
+
541
+ const focusBlock = Array.from(
542
+ Editor.nodes(editor, {
543
+ at: editor.selection.focus.path.slice(0, 1),
544
+ match: (n) => n._type === types.block.name,
545
+ }),
546
+ )[0]
547
+
548
+ Editor.insertNode(editor, block)
549
+
550
+ if (focusBlock && isEqualToEmptyEditor([focusBlock[0]], types)) {
551
+ Transforms.removeNodes(editor, {at: focusBlock[1]})
552
+ }
553
+
554
+ editor.onChange()
555
+
556
+ return (
557
+ toPortableTextRange(
558
+ fromSlateValue(
559
+ editor.children,
560
+ types.block.name,
561
+ KEY_TO_VALUE_ELEMENT.get(editor),
562
+ ),
563
+ editor.selection,
564
+ types,
565
+ )?.focus.path || []
566
+ )
567
+ }
568
+
549
569
  function isAnnotationActive({
550
570
  editor,
551
571
  annotation,
@@ -837,12 +837,16 @@ export function isDecoratorActive({
837
837
  return false
838
838
  }
839
839
 
840
- const selectedNodes = Array.from(
840
+ const selectedTextNodes = Array.from(
841
841
  Editor.nodes(editor, {match: Text.isText, at: editor.selection}),
842
842
  )
843
843
 
844
+ if (selectedTextNodes.length === 0) {
845
+ return false
846
+ }
847
+
844
848
  if (Range.isExpanded(editor.selection)) {
845
- return selectedNodes.every((n) => {
849
+ return selectedTextNodes.every((n) => {
846
850
  const [node] = n
847
851
 
848
852
  return node.marks?.includes(decorator)
@@ -1,7 +1,7 @@
1
1
  import type {BaseOperation, Editor, Node, NodeEntry} from 'slate'
2
2
  import type {PortableTextSlateEditor} from '../../types/editor'
3
- import type {createEditorOptions} from '../../types/options'
4
3
  import {createOperationToPatches} from '../../utils/operationToPatches'
4
+ import type {EditorActor} from '../editor-machine'
5
5
  import {createWithEventListeners} from './create-with-event-listeners'
6
6
  import {createWithMaxBlocks} from './createWithMaxBlocks'
7
7
  import {createWithObjectKeys} from './createWithObjectKeys'
@@ -26,9 +26,14 @@ const originalFnMap = new WeakMap<
26
26
  OriginalEditorFunctions
27
27
  >()
28
28
 
29
+ type PluginsOptions = {
30
+ editorActor: EditorActor
31
+ subscriptions: Array<() => () => void>
32
+ }
33
+
29
34
  export const withPlugins = <T extends Editor>(
30
35
  editor: T,
31
- options: createEditorOptions,
36
+ options: PluginsOptions,
32
37
  ): PortableTextSlateEditor => {
33
38
  const e = editor as T & PortableTextSlateEditor
34
39
  const {editorActor} = options
package/src/index.ts CHANGED
@@ -5,6 +5,10 @@ export {
5
5
  createMarkdownBehaviors,
6
6
  type MarkdownBehaviorsConfig,
7
7
  } from './editor/behavior/behavior.markdown'
8
+ export {
9
+ createLinkBehaviors,
10
+ type LinkBehaviorsConfig,
11
+ } from './editor/behavior/behavior.links'
8
12
  export {
9
13
  defineBehavior,
10
14
  type Behavior,
@@ -45,4 +49,4 @@ export {
45
49
  type EditorEvent,
46
50
  } from './editor/use-editor'
47
51
  export * from './types/editor'
48
- export * from './types/options'
52
+ export type {HotkeyOptions} from './types/options'
@@ -1,15 +1,6 @@
1
1
  import type {BaseSyntheticEvent} from 'react'
2
- import type {EditorActor} from '../editor/editor-machine'
3
2
  import type {PortableTextEditor} from '../editor/PortableTextEditor'
4
3
 
5
- /**
6
- * @internal
7
- */
8
- export type createEditorOptions = {
9
- editorActor: EditorActor
10
- subscriptions: Array<() => () => void>
11
- }
12
-
13
4
  /**
14
5
  * @beta
15
6
  */
@@ -2,9 +2,9 @@ import type {PortableTextTextBlock} from '@sanity/types'
2
2
  import {createEditor, type Descendant} from 'slate'
3
3
  import {beforeEach, describe, expect, it} from 'vitest'
4
4
  import {createActor} from 'xstate'
5
- import {editorMachine} from '../..'
6
5
  import {schemaType} from '../../editor/__tests__/PortableTextEditorTester'
7
6
  import {coreBehaviors} from '../../editor/behavior/behavior.core'
7
+ import {editorMachine} from '../../editor/editor-machine'
8
8
  import {defaultKeyGenerator} from '../../editor/key-generator'
9
9
  import {withPlugins} from '../../editor/plugins/with-plugins'
10
10
  import {getPortableTextMemberSchemaTypes} from '../getPortableTextMemberSchemaTypes'
@@ -2,9 +2,9 @@ import type {Patch} from '@portabletext/patches'
2
2
  import {createEditor, type Descendant} from 'slate'
3
3
  import {beforeEach, describe, expect, it} from 'vitest'
4
4
  import {createActor} from 'xstate'
5
- import {editorMachine} from '../..'
6
5
  import {schemaType} from '../../editor/__tests__/PortableTextEditorTester'
7
6
  import {coreBehaviors} from '../../editor/behavior/behavior.core'
7
+ import {editorMachine} from '../../editor/editor-machine'
8
8
  import {defaultKeyGenerator} from '../../editor/key-generator'
9
9
  import {withPlugins} from '../../editor/plugins/with-plugins'
10
10
  import {createApplyPatch} from '../applyPatch'