@portabletext/editor 1.4.1 → 1.5.1

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/index.d.ts CHANGED
@@ -2,21 +2,22 @@ import {Patch} from '@portabletext/patches'
2
2
  import type {
3
3
  ArrayDefinition,
4
4
  ArraySchemaType,
5
- BlockDecoratorDefinition,
6
5
  BlockListDefinition,
7
- BlockSchemaType,
8
6
  BlockStyleDefinition,
9
7
  KeyedSegment,
10
8
  ObjectSchemaType,
11
9
  Path,
12
- PortableTextBlock,
13
- PortableTextChild,
14
10
  PortableTextListBlock,
15
11
  PortableTextObject,
16
- SpanSchemaType,
17
12
  TypedObject,
18
13
  } from '@sanity/types'
19
- import {PortableTextSpan, PortableTextTextBlock} from '@sanity/types'
14
+ import {
15
+ BlockDecoratorDefinition,
16
+ PortableTextBlock,
17
+ PortableTextChild,
18
+ PortableTextSpan,
19
+ PortableTextTextBlock,
20
+ } from '@sanity/types'
20
21
  import type {
21
22
  BaseSyntheticEvent,
22
23
  ClipboardEvent as ClipboardEvent_2,
@@ -64,6 +65,15 @@ import {
64
65
  Values,
65
66
  } from 'xstate'
66
67
 
68
+ /**
69
+ * @alpha
70
+ */
71
+ export declare type BaseDefinition = {
72
+ name: string
73
+ title?: string
74
+ icon?: BlockDecoratorDefinition['icon']
75
+ }
76
+
67
77
  /**
68
78
  * @alpha
69
79
  */
@@ -303,10 +313,10 @@ export declare type createEditorOptions = {
303
313
  export declare function createMarkdownBehaviors(
304
314
  config: MarkdownBehaviorsConfig,
305
315
  ): Behavior<
306
- | 'insert break'
307
- | 'insert soft break'
308
316
  | 'delete backward'
309
317
  | 'delete forward'
318
+ | 'insert soft break'
319
+ | 'insert break'
310
320
  | 'insert text',
311
321
  true
312
322
  >[]
@@ -319,12 +329,23 @@ export declare function defineBehavior<
319
329
  TGuardResponse = true,
320
330
  >(behavior: Behavior<TBehaviorEventType, TGuardResponse>): Behavior
321
331
 
332
+ /**
333
+ * @alpha
334
+ */
335
+ export declare function defineSchema<
336
+ const TSchemaDefinition extends SchemaDefinition,
337
+ >(definition: TSchemaDefinition): TSchemaDefinition
338
+
322
339
  /** @beta */
323
340
  export declare interface EditableAPI {
324
341
  activeAnnotations: () => PortableTextObject[]
325
342
  isAnnotationActive: (annotationType: PortableTextObject['_type']) => boolean
326
- addAnnotation: (
327
- type: ObjectSchemaType,
343
+ addAnnotation: <
344
+ TSchemaType extends {
345
+ name: string
346
+ },
347
+ >(
348
+ type: TSchemaType,
328
349
  value?: {
329
350
  [prop: string]: unknown
330
351
  },
@@ -354,14 +375,22 @@ export declare interface EditableAPI {
354
375
  getValue: () => PortableTextBlock[] | undefined
355
376
  hasBlockStyle: (style: string) => boolean
356
377
  hasListStyle: (listStyle: string) => boolean
357
- insertBlock: (
358
- type: BlockSchemaType | ObjectSchemaType,
378
+ insertBlock: <
379
+ TSchemaType extends {
380
+ name: string
381
+ },
382
+ >(
383
+ type: TSchemaType,
359
384
  value?: {
360
385
  [prop: string]: unknown
361
386
  },
362
387
  ) => Path
363
- insertChild: (
364
- type: SpanSchemaType | ObjectSchemaType,
388
+ insertChild: <
389
+ TSchemaType extends {
390
+ name: string
391
+ },
392
+ >(
393
+ type: TSchemaType,
365
394
  value?: {
366
395
  [prop: string]: unknown
367
396
  },
@@ -377,7 +406,13 @@ export declare interface EditableAPI {
377
406
  isVoid: (element: PortableTextBlock | PortableTextChild) => boolean
378
407
  marks: () => string[]
379
408
  redo: () => void
380
- removeAnnotation: (type: ObjectSchemaType) => void
409
+ removeAnnotation: <
410
+ TSchemaType extends {
411
+ name: string
412
+ },
413
+ >(
414
+ type: TSchemaType,
415
+ ) => void
381
416
  select: (selection: EditorSelection) => void
382
417
  toggleBlockStyle: (blockStyle: string) => void
383
418
  toggleList: (listStyle: string) => void
@@ -430,8 +465,16 @@ export declare type EditorChanges = Subject<EditorChange>
430
465
  export declare type EditorConfig = {
431
466
  behaviors?: Array<Behavior>
432
467
  keyGenerator?: () => string
433
- schema: ArraySchemaType<PortableTextBlock> | ArrayDefinition
434
- }
468
+ } & (
469
+ | {
470
+ schemaDefinition: SchemaDefinition
471
+ schema?: undefined
472
+ }
473
+ | {
474
+ schemaDefinition?: undefined
475
+ schema: ArraySchemaType<PortableTextBlock> | ArrayDefinition
476
+ }
477
+ )
435
478
 
436
479
  /**
437
480
  * @internal
@@ -867,10 +910,10 @@ export declare const editorMachine: StateMachine<
867
910
  >
868
911
  }) => {
869
912
  behaviors: Behavior<
870
- | 'insert break'
871
- | 'insert soft break'
872
913
  | 'delete backward'
873
914
  | 'delete forward'
915
+ | 'insert soft break'
916
+ | 'insert break'
874
917
  | 'insert text',
875
918
  true
876
919
  >[]
@@ -3092,6 +3135,10 @@ export declare type PickFromUnion<
3092
3135
  TPickedTags extends TUnion[TTagKey],
3093
3136
  > = TUnion extends Record<TTagKey, TPickedTags> ? TUnion : never
3094
3137
 
3138
+ export {PortableTextBlock}
3139
+
3140
+ export {PortableTextChild}
3141
+
3095
3142
  /**
3096
3143
  * @public
3097
3144
  */
@@ -3156,9 +3203,13 @@ export declare class PortableTextEditor extends Component<
3156
3203
  editor: PortableTextEditor,
3157
3204
  annotationType: PortableTextObject['_type'],
3158
3205
  ) => boolean
3159
- static addAnnotation: (
3206
+ static addAnnotation: <
3207
+ TSchemaType extends {
3208
+ name: string
3209
+ },
3210
+ >(
3160
3211
  editor: PortableTextEditor,
3161
- type: ObjectSchemaType,
3212
+ type: TSchemaType,
3162
3213
  value?: {
3163
3214
  [prop: string]: unknown
3164
3215
  },
@@ -3231,16 +3282,24 @@ export declare class PortableTextEditor extends Component<
3231
3282
  editor: PortableTextEditor,
3232
3283
  mark: string,
3233
3284
  ) => boolean | undefined
3234
- static insertChild: (
3285
+ static insertChild: <
3286
+ TSchemaType extends {
3287
+ name: string
3288
+ },
3289
+ >(
3235
3290
  editor: PortableTextEditor,
3236
- type: SpanSchemaType | ObjectSchemaType,
3291
+ type: TSchemaType,
3237
3292
  value?: {
3238
3293
  [prop: string]: unknown
3239
3294
  },
3240
3295
  ) => Path | undefined
3241
- static insertBlock: (
3296
+ static insertBlock: <
3297
+ TSchemaType extends {
3298
+ name: string
3299
+ },
3300
+ >(
3242
3301
  editor: PortableTextEditor,
3243
- type: BlockSchemaType | ObjectSchemaType,
3302
+ type: TSchemaType,
3244
3303
  value?: {
3245
3304
  [prop: string]: unknown
3246
3305
  },
@@ -3256,9 +3315,13 @@ export declare class PortableTextEditor extends Component<
3256
3315
  editor: PortableTextEditor,
3257
3316
  selection: EditorSelection | null,
3258
3317
  ) => void
3259
- static removeAnnotation: (
3318
+ static removeAnnotation: <
3319
+ TSchemaType extends {
3320
+ name: string
3321
+ },
3322
+ >(
3260
3323
  editor: PortableTextEditor,
3261
- type: ObjectSchemaType,
3324
+ type: TSchemaType,
3262
3325
  ) => void | undefined
3263
3326
  static toggleBlockStyle: (
3264
3327
  editor: PortableTextEditor,
@@ -3551,6 +3614,20 @@ export declare type RenderStyleFunction = (
3551
3614
  props: BlockStyleRenderProps,
3552
3615
  ) => JSX.Element
3553
3616
 
3617
+ /**
3618
+ * @alpha
3619
+ */
3620
+ export declare type SchemaDefinition<
3621
+ TBaseDefinition extends BaseDefinition = BaseDefinition,
3622
+ > = {
3623
+ decorators?: ReadonlyArray<TBaseDefinition>
3624
+ blockObjects?: ReadonlyArray<TBaseDefinition>
3625
+ inlineObjects?: ReadonlyArray<TBaseDefinition>
3626
+ annotations?: ReadonlyArray<TBaseDefinition>
3627
+ lists?: ReadonlyArray<TBaseDefinition>
3628
+ styles?: ReadonlyArray<TBaseDefinition>
3629
+ }
3630
+
3554
3631
  /** @beta */
3555
3632
  export declare type ScrollSelectionIntoViewFunction = (
3556
3633
  editor: PortableTextEditor,
@@ -4015,10 +4092,10 @@ export declare function useEditor(config: EditorConfig): Actor<
4015
4092
  >
4016
4093
  }) => {
4017
4094
  behaviors: Behavior<
4018
- | 'insert break'
4019
- | 'insert soft break'
4020
4095
  | 'delete backward'
4021
4096
  | 'delete forward'
4097
+ | 'insert soft break'
4098
+ | 'insert break'
4022
4099
  | 'insert text',
4023
4100
  true
4024
4101
  >[]
package/lib/index.esm.js CHANGED
@@ -1,4 +1,6 @@
1
- import { isPortableTextTextBlock, isPortableTextSpan as isPortableTextSpan$1, isKeySegment, isPortableTextListBlock } from "@sanity/types";
1
+ import { isPortableTextTextBlock, isPortableTextSpan as isPortableTextSpan$1, isKeySegment, defineType, defineField, isPortableTextListBlock } from "@sanity/types";
2
+ import { Schema } from "@sanity/schema";
3
+ import startCase from "lodash.startcase";
2
4
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
3
5
  import isEqual from "lodash/isEqual.js";
4
6
  import noop from "lodash/noop.js";
@@ -11,7 +13,6 @@ import { styled } from "styled-components";
11
13
  import uniq from "lodash/uniq.js";
12
14
  import { Subject } from "rxjs";
13
15
  import { fromCallback, setup, assign, assertEvent, emit, enqueueActions, createActor } from "xstate";
14
- import { Schema } from "@sanity/schema";
15
16
  import { diffMatchPatch as diffMatchPatch$1, set, insert, setIfMissing, unset, applyAll } from "@portabletext/patches";
16
17
  import get from "lodash/get.js";
17
18
  import isUndefined from "lodash/isUndefined.js";
@@ -265,6 +266,114 @@ function createMarkdownBehaviors(config) {
265
266
  };
266
267
  return [automaticStyleOnSpace, clearStyleOnBackspace, automaticListOnSpace];
267
268
  }
269
+ function getPortableTextMemberSchemaTypes(portableTextType) {
270
+ if (!portableTextType)
271
+ throw new Error("Parameter 'portabletextType' missing (required)");
272
+ const blockType = portableTextType.of?.find(findBlockType);
273
+ if (!blockType)
274
+ throw new Error("Block type is not defined in this schema (required)");
275
+ const childrenField = blockType.fields?.find((field) => field.name === "children");
276
+ if (!childrenField)
277
+ throw new Error("Children field for block type found in schema (required)");
278
+ const ofType = childrenField.type.of;
279
+ if (!ofType)
280
+ throw new Error("Valid types for block children not found in schema (required)");
281
+ const spanType = ofType.find((memberType) => memberType.name === "span");
282
+ if (!spanType)
283
+ throw new Error("Span type not found in schema (required)");
284
+ const inlineObjectTypes = ofType.filter((memberType) => memberType.name !== "span") || [], blockObjectTypes = portableTextType.of?.filter((field) => field.name !== blockType.name) || [];
285
+ return {
286
+ styles: resolveEnabledStyles(blockType),
287
+ decorators: resolveEnabledDecorators(spanType),
288
+ lists: resolveEnabledListItems(blockType),
289
+ block: blockType,
290
+ span: spanType,
291
+ portableText: portableTextType,
292
+ inlineObjects: inlineObjectTypes,
293
+ blockObjects: blockObjectTypes,
294
+ annotations: spanType.annotations
295
+ };
296
+ }
297
+ function resolveEnabledStyles(blockType) {
298
+ const styleField = blockType.fields?.find((btField) => btField.name === "style");
299
+ if (!styleField)
300
+ throw new Error("A field with name 'style' is not defined in the block type (required).");
301
+ const textStyles = styleField.type.options?.list && styleField.type.options.list?.filter((style) => style.value);
302
+ if (!textStyles || textStyles.length === 0)
303
+ throw new Error("The style fields need at least one style defined. I.e: {title: 'Normal', value: 'normal'}.");
304
+ return textStyles;
305
+ }
306
+ function resolveEnabledDecorators(spanType) {
307
+ return spanType.decorators;
308
+ }
309
+ function resolveEnabledListItems(blockType) {
310
+ const listField = blockType.fields?.find((btField) => btField.name === "listItem");
311
+ if (!listField)
312
+ throw new Error("A field with name 'listItem' is not defined in the block type (required).");
313
+ const listItems = listField.type.options?.list && listField.type.options.list.filter((list) => list.value);
314
+ if (!listItems)
315
+ throw new Error("The list field need at least to be an empty array");
316
+ return listItems;
317
+ }
318
+ function findBlockType(type) {
319
+ return type.type ? findBlockType(type.type) : type.name === "block" ? type : null;
320
+ }
321
+ function defineSchema(definition) {
322
+ return definition;
323
+ }
324
+ function compileSchemaDefinition(definition) {
325
+ const blockObjects = definition?.blockObjects?.map((blockObject) => defineType({
326
+ type: "object",
327
+ name: blockObject.name,
328
+ title: blockObject.title,
329
+ icon: blockObject.icon,
330
+ fields: []
331
+ })) ?? [], inlineObjects = definition?.inlineObjects?.map((inlineObject) => defineType({
332
+ type: "object",
333
+ name: inlineObject.name,
334
+ title: inlineObject.title,
335
+ icon: inlineObject.icon,
336
+ fields: []
337
+ })) ?? [], portableTextSchema = defineField({
338
+ type: "array",
339
+ name: "portable-text",
340
+ of: [...blockObjects.map((blockObject) => ({
341
+ type: blockObject.name
342
+ })), {
343
+ type: "block",
344
+ name: "block",
345
+ of: inlineObjects.map((inlineObject) => ({
346
+ type: inlineObject.name
347
+ })),
348
+ marks: {
349
+ decorators: definition?.decorators?.map((decorator) => ({
350
+ title: decorator.title ?? startCase(decorator.name),
351
+ value: decorator.name,
352
+ icon: decorator.icon
353
+ })) ?? [],
354
+ annotations: definition?.annotations?.map((annotation) => ({
355
+ name: annotation.name,
356
+ type: "object",
357
+ title: annotation.title,
358
+ icon: annotation.icon
359
+ })) ?? []
360
+ },
361
+ lists: definition?.lists?.map((list) => ({
362
+ value: list.name,
363
+ title: list.title ?? startCase(list.name),
364
+ icon: list.icon
365
+ })) ?? [],
366
+ styles: definition?.styles?.map((style) => ({
367
+ value: style.name,
368
+ title: style.title ?? startCase(style.name),
369
+ icon: style.icon
370
+ })) ?? []
371
+ }]
372
+ }), schema = Schema.compile({
373
+ types: [portableTextSchema, ...blockObjects, ...inlineObjects]
374
+ }).get("portable-text");
375
+ return getPortableTextMemberSchemaTypes(schema);
376
+ }
268
377
  const rootName = "sanity-pte:";
269
378
  debug$m(rootName);
270
379
  function debugWithName(name) {
@@ -955,58 +1064,6 @@ function DefaultAnnotation(props) {
955
1064
  return $[3] !== handleClick || $[4] !== props.children ? (t2 = /* @__PURE__ */ jsx("span", { style: t1, onClick: handleClick, children: props.children }), $[3] = handleClick, $[4] = props.children, $[5] = t2) : t2 = $[5], t2;
956
1065
  }
957
1066
  DefaultAnnotation.displayName = "DefaultAnnotation";
958
- function getPortableTextMemberSchemaTypes(portableTextType) {
959
- if (!portableTextType)
960
- throw new Error("Parameter 'portabletextType' missing (required)");
961
- const blockType = portableTextType.of?.find(findBlockType);
962
- if (!blockType)
963
- throw new Error("Block type is not defined in this schema (required)");
964
- const childrenField = blockType.fields?.find((field) => field.name === "children");
965
- if (!childrenField)
966
- throw new Error("Children field for block type found in schema (required)");
967
- const ofType = childrenField.type.of;
968
- if (!ofType)
969
- throw new Error("Valid types for block children not found in schema (required)");
970
- const spanType = ofType.find((memberType) => memberType.name === "span");
971
- if (!spanType)
972
- throw new Error("Span type not found in schema (required)");
973
- const inlineObjectTypes = ofType.filter((memberType) => memberType.name !== "span") || [], blockObjectTypes = portableTextType.of?.filter((field) => field.name !== blockType.name) || [];
974
- return {
975
- styles: resolveEnabledStyles(blockType),
976
- decorators: resolveEnabledDecorators(spanType),
977
- lists: resolveEnabledListItems(blockType),
978
- block: blockType,
979
- span: spanType,
980
- portableText: portableTextType,
981
- inlineObjects: inlineObjectTypes,
982
- blockObjects: blockObjectTypes,
983
- annotations: spanType.annotations
984
- };
985
- }
986
- function resolveEnabledStyles(blockType) {
987
- const styleField = blockType.fields?.find((btField) => btField.name === "style");
988
- if (!styleField)
989
- throw new Error("A field with name 'style' is not defined in the block type (required).");
990
- const textStyles = styleField.type.options?.list && styleField.type.options.list?.filter((style) => style.value);
991
- if (!textStyles || textStyles.length === 0)
992
- throw new Error("The style fields need at least one style defined. I.e: {title: 'Normal', value: 'normal'}.");
993
- return textStyles;
994
- }
995
- function resolveEnabledDecorators(spanType) {
996
- return spanType.decorators;
997
- }
998
- function resolveEnabledListItems(blockType) {
999
- const listField = blockType.fields?.find((btField) => btField.name === "listItem");
1000
- if (!listField)
1001
- throw new Error("A field with name 'listItem' is not defined in the block type (required).");
1002
- const listItems = listField.type.options?.list && listField.type.options.list.filter((list) => list.value);
1003
- if (!listItems)
1004
- throw new Error("The list field need at least to be an empty array");
1005
- return listItems;
1006
- }
1007
- function findBlockType(type) {
1008
- return type.type ? findBlockType(type.type) : type.name === "block" ? type : null;
1009
- }
1010
1067
  function compileType(rawType) {
1011
1068
  return Schema.compile({
1012
1069
  name: "blockTypeSchema",
@@ -6216,26 +6273,25 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
6216
6273
  });
6217
6274
  PortableTextEditable.displayName = "ForwardRef(PortableTextEditable)";
6218
6275
  function useEditor(config) {
6219
- const $ = c(8);
6276
+ const $ = c(7);
6220
6277
  let t0;
6221
- $[0] !== config.schema ? (t0 = config.schema.hasOwnProperty("jsonType") ? config.schema : compileType(config.schema), $[0] = config.schema, $[1] = t0) : t0 = $[1];
6222
- let t1;
6223
- $[2] !== t0 ? (t1 = getPortableTextMemberSchemaTypes(t0), $[2] = t0, $[3] = t1) : t1 = $[3];
6224
- const schema = t1, t2 = config.keyGenerator ?? defaultKeyGenerator;
6225
- let t3;
6226
- return $[4] !== config.behaviors || $[5] !== t2 || $[6] !== schema ? (t3 = {
6278
+ $[0] !== config.schemaDefinition || $[1] !== config.schema ? (t0 = config.schemaDefinition ? compileSchemaDefinition(config.schemaDefinition) : getPortableTextMemberSchemaTypes(config.schema.hasOwnProperty("jsonType") ? config.schema : compileType(config.schema)), $[0] = config.schemaDefinition, $[1] = config.schema, $[2] = t0) : t0 = $[2];
6279
+ const schema = t0, t1 = config.keyGenerator ?? defaultKeyGenerator;
6280
+ let t2;
6281
+ return $[3] !== config.behaviors || $[4] !== t1 || $[5] !== schema ? (t2 = {
6227
6282
  input: {
6228
6283
  behaviors: config.behaviors,
6229
- keyGenerator: t2,
6284
+ keyGenerator: t1,
6230
6285
  schema
6231
6286
  }
6232
- }, $[4] = config.behaviors, $[5] = t2, $[6] = schema, $[7] = t3) : t3 = $[7], useActorRef(editorMachine, t3);
6287
+ }, $[3] = config.behaviors, $[4] = t1, $[5] = schema, $[6] = t2) : t2 = $[6], useActorRef(editorMachine, t2);
6233
6288
  }
6234
6289
  export {
6235
6290
  PortableTextEditable,
6236
6291
  PortableTextEditor,
6237
6292
  createMarkdownBehaviors,
6238
6293
  defineBehavior,
6294
+ defineSchema,
6239
6295
  editorMachine,
6240
6296
  defaultKeyGenerator as keyGenerator,
6241
6297
  useEditor,