@portabletext/editor 1.3.1 → 1.4.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.esm.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { isPortableTextTextBlock, isPortableTextSpan as isPortableTextSpan$1, isKeySegment, isPortableTextListBlock } from "@sanity/types";
1
2
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
3
  import isEqual from "lodash/isEqual.js";
3
4
  import noop from "lodash/noop.js";
@@ -5,7 +6,6 @@ import { useRef, useState, useEffect, useMemo, createContext, useContext, useCal
5
6
  import { Editor, Element as Element$1, Range, Point, Text, Path, Transforms, Node, Operation, createEditor, deleteBackward, deleteForward, insertText } from "slate";
6
7
  import { useSlateStatic, ReactEditor, useSelected, withReact, Slate, useSlate, Editable } from "slate-react";
7
8
  import debug$m from "debug";
8
- import { isKeySegment, isPortableTextTextBlock, isPortableTextSpan as isPortableTextSpan$1, isPortableTextListBlock } from "@sanity/types";
9
9
  import { c } from "react-compiler-runtime";
10
10
  import { styled } from "styled-components";
11
11
  import uniq from "lodash/uniq.js";
@@ -24,6 +24,247 @@ import throttle from "lodash/throttle.js";
24
24
  import { useEffectEvent } from "use-effect-event";
25
25
  import debounce from "lodash/debounce.js";
26
26
  import { randomKey } from "@sanity/util/content";
27
+ import { useActorRef } from "@xstate/react";
28
+ function defineBehavior(behavior) {
29
+ return behavior;
30
+ }
31
+ function selectionIsCollapsed(context) {
32
+ return context.selection?.anchor.path.join() === context.selection?.focus.path.join() && context.selection?.anchor.offset === context.selection?.focus.offset;
33
+ }
34
+ function getFocusBlock(context) {
35
+ const key = context.selection && isKeySegment(context.selection.focus.path[0]) ? context.selection.focus.path[0]._key : void 0, node = key ? context.value.find((block) => block._key === key) : void 0;
36
+ return node && key ? {
37
+ node,
38
+ path: [{
39
+ _key: key
40
+ }]
41
+ } : void 0;
42
+ }
43
+ function getFocusTextBlock(context) {
44
+ const focusBlock = getFocusBlock(context);
45
+ return focusBlock && isPortableTextTextBlock(focusBlock.node) ? {
46
+ node: focusBlock.node,
47
+ path: focusBlock.path
48
+ } : void 0;
49
+ }
50
+ function getFocusBlockObject(context) {
51
+ const focusBlock = getFocusBlock(context);
52
+ return focusBlock && !isPortableTextTextBlock(focusBlock.node) ? {
53
+ node: focusBlock.node,
54
+ path: focusBlock.path
55
+ } : void 0;
56
+ }
57
+ function getFocusChild(context) {
58
+ const focusBlock = getFocusTextBlock(context);
59
+ if (!focusBlock)
60
+ return;
61
+ const key = context.selection && isKeySegment(context.selection.focus.path[2]) ? context.selection.focus.path[2]._key : void 0, node = key ? focusBlock.node.children.find((span) => span._key === key) : void 0;
62
+ return node && key ? {
63
+ node,
64
+ path: [...focusBlock.path, "children", {
65
+ _key: key
66
+ }]
67
+ } : void 0;
68
+ }
69
+ function getFocusSpan(context) {
70
+ const focusChild = getFocusChild(context);
71
+ return focusChild && isPortableTextSpan$1(focusChild.node) ? {
72
+ node: focusChild.node,
73
+ path: focusChild.path
74
+ } : void 0;
75
+ }
76
+ function getSelectionStartBlock(context) {
77
+ const key = context.selection.backward ? isKeySegment(context.selection.focus.path[0]) ? context.selection.focus.path[0]._key : void 0 : isKeySegment(context.selection.anchor.path[0]) ? context.selection.anchor.path[0]._key : void 0, node = key ? context.value.find((block) => block._key === key) : void 0;
78
+ return node && key ? {
79
+ node,
80
+ path: [{
81
+ _key: key
82
+ }]
83
+ } : void 0;
84
+ }
85
+ function getSelectionEndBlock(context) {
86
+ const key = context.selection.backward ? isKeySegment(context.selection.anchor.path[0]) ? context.selection.anchor.path[0]._key : void 0 : isKeySegment(context.selection.focus.path[0]) ? context.selection.focus.path[0]._key : void 0, node = key ? context.value.find((block) => block._key === key) : void 0;
87
+ return node && key ? {
88
+ node,
89
+ path: [{
90
+ _key: key
91
+ }]
92
+ } : void 0;
93
+ }
94
+ function getPreviousBlock(context) {
95
+ let previousBlock;
96
+ const selectionStartBlock = getSelectionStartBlock(context);
97
+ if (!selectionStartBlock)
98
+ return;
99
+ let foundSelectionStartBlock = !1;
100
+ for (const block of context.value) {
101
+ if (block._key === selectionStartBlock.node._key) {
102
+ foundSelectionStartBlock = !0;
103
+ break;
104
+ }
105
+ previousBlock = {
106
+ node: block,
107
+ path: [{
108
+ _key: block._key
109
+ }]
110
+ };
111
+ }
112
+ if (foundSelectionStartBlock && previousBlock)
113
+ return previousBlock;
114
+ }
115
+ function getNextBlock(context) {
116
+ let nextBlock;
117
+ const selectionEndBlock = getSelectionEndBlock(context);
118
+ if (!selectionEndBlock)
119
+ return;
120
+ let foundSelectionEndBlock = !1;
121
+ for (const block of context.value) {
122
+ if (block._key === selectionEndBlock.node._key) {
123
+ foundSelectionEndBlock = !0;
124
+ continue;
125
+ }
126
+ if (foundSelectionEndBlock) {
127
+ nextBlock = {
128
+ node: block,
129
+ path: [{
130
+ _key: block._key
131
+ }]
132
+ };
133
+ break;
134
+ }
135
+ }
136
+ if (foundSelectionEndBlock && nextBlock)
137
+ return nextBlock;
138
+ }
139
+ function isEmptyTextBlock(block) {
140
+ return block.children.length === 1 && block.children[0].text === "";
141
+ }
142
+ function createMarkdownBehaviors(config) {
143
+ const automaticStyleOnSpace = {
144
+ on: "insert text",
145
+ guard: ({
146
+ context,
147
+ event
148
+ }) => {
149
+ if (event.text !== " ")
150
+ return !1;
151
+ const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
152
+ if (!selectionCollapsed || !focusTextBlock || !focusSpan)
153
+ return !1;
154
+ const looksLikeMarkdownHeading = /^#+/.test(focusSpan.node.text), headingStyle = config.mapHeadingStyle(context.schema, focusSpan.node.text.length), looksLikeMarkdownQuote = /^>/.test(focusSpan.node.text), blockquoteStyle = config.mapBlockquoteStyle(context.schema);
155
+ return looksLikeMarkdownHeading && headingStyle !== void 0 ? {
156
+ focusTextBlock,
157
+ focusSpan,
158
+ style: headingStyle
159
+ } : looksLikeMarkdownQuote && blockquoteStyle !== void 0 ? {
160
+ focusTextBlock,
161
+ focusSpan,
162
+ style: blockquoteStyle
163
+ } : !1;
164
+ },
165
+ actions: [() => [{
166
+ type: "insert text",
167
+ text: " "
168
+ }], (_, {
169
+ focusTextBlock,
170
+ focusSpan,
171
+ style
172
+ }) => [{
173
+ type: "set block",
174
+ style,
175
+ paths: [focusTextBlock.path]
176
+ }, {
177
+ type: "delete",
178
+ selection: {
179
+ anchor: {
180
+ path: focusSpan.path,
181
+ offset: 0
182
+ },
183
+ focus: {
184
+ path: focusSpan.path,
185
+ offset: focusSpan.node.text.length + 1
186
+ }
187
+ }
188
+ }]]
189
+ }, clearStyleOnBackspace = {
190
+ on: "delete backward",
191
+ guard: ({
192
+ context
193
+ }) => {
194
+ const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
195
+ if (!selectionCollapsed || !focusTextBlock || !focusSpan)
196
+ return !1;
197
+ const defaultStyle = config.mapDefaultStyle(context.schema);
198
+ return defaultStyle && focusTextBlock.node.children.length === 1 && focusTextBlock.node.style !== config.mapDefaultStyle(context.schema) && focusSpan.node.text === "" ? {
199
+ defaultStyle,
200
+ focusTextBlock
201
+ } : !1;
202
+ },
203
+ actions: [(_, {
204
+ defaultStyle,
205
+ focusTextBlock
206
+ }) => [{
207
+ type: "set block",
208
+ style: defaultStyle,
209
+ paths: [focusTextBlock.path]
210
+ }]]
211
+ }, automaticListOnSpace = {
212
+ on: "insert text",
213
+ guard: ({
214
+ context,
215
+ event
216
+ }) => {
217
+ if (event.text !== " ")
218
+ return !1;
219
+ const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
220
+ if (!selectionCollapsed || !focusTextBlock || !focusSpan)
221
+ return !1;
222
+ const looksLikeUnorderedList = /^-/.test(focusSpan.node.text), unorderedListStyle = config.mapUnorderedListStyle(context.schema);
223
+ if (looksLikeUnorderedList && unorderedListStyle !== void 0)
224
+ return {
225
+ focusTextBlock,
226
+ focusSpan,
227
+ listItem: unorderedListStyle
228
+ };
229
+ const looksLikeOrderedList = /^1./.test(focusSpan.node.text), orderedListStyle = config.mapOrderedListStyle(context.schema);
230
+ return looksLikeOrderedList && orderedListStyle !== void 0 ? {
231
+ focusTextBlock,
232
+ focusSpan,
233
+ listItem: orderedListStyle
234
+ } : !1;
235
+ },
236
+ actions: [() => [{
237
+ type: "insert text",
238
+ text: " "
239
+ }], (_, {
240
+ focusTextBlock,
241
+ focusSpan,
242
+ listItem
243
+ }) => [{
244
+ type: "unset block",
245
+ props: ["style"],
246
+ paths: [focusTextBlock.path]
247
+ }, {
248
+ type: "set block",
249
+ listItem,
250
+ level: 1,
251
+ paths: [focusTextBlock.path]
252
+ }, {
253
+ type: "delete",
254
+ selection: {
255
+ anchor: {
256
+ path: focusSpan.path,
257
+ offset: 0
258
+ },
259
+ focus: {
260
+ path: focusSpan.path,
261
+ offset: focusSpan.node.text.length + 1
262
+ }
263
+ }
264
+ }]]
265
+ };
266
+ return [automaticStyleOnSpace, clearStyleOnBackspace, automaticListOnSpace];
267
+ }
27
268
  const rootName = "sanity-pte:";
28
269
  debug$m(rootName);
29
270
  function debugWithName(name) {
@@ -660,360 +901,119 @@ const EMPTY_ANNOTATIONS = [], inlineBlockStyle = {
660
901
  get() {
661
902
  return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaTypes.block;
662
903
  }
663
- }), propsOrDefaultRendered = renderBlock ? renderBlock(renderProps) : children;
664
- return /* @__PURE__ */ jsx("div", { ...attributes, className, spellCheck, children: /* @__PURE__ */ jsx(DraggableBlock, { element, readOnly, blockRef, children: /* @__PURE__ */ jsx("div", { ref: blockRef, children: propsOrDefaultRendered }) }) }, element._key);
665
- }
666
- const schemaType_0 = schemaTypes.blockObjects.find((_type_0) => _type_0.name === element._type);
667
- if (!schemaType_0)
668
- throw new Error(`Could not find schema type for block element of _type ${element._type}`);
669
- className = "pt-block pt-object-block";
670
- const block_0 = fromSlateValue([element], schemaTypes.block.name, KEY_TO_VALUE_ELEMENT.get(editor))[0];
671
- let renderedBlockFromProps;
672
- if (renderBlock) {
673
- const _props = Object.defineProperty({
674
- children: /* @__PURE__ */ jsx(DefaultObject, { value }),
675
- editorElementRef: blockRef,
676
- focused,
677
- path: blockPath,
678
- schemaType: schemaType_0,
679
- selected,
680
- value: block_0
681
- }, "type", {
682
- enumerable: !1,
683
- get() {
684
- return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaType_0;
685
- }
686
- });
687
- renderedBlockFromProps = renderBlock(_props);
688
- }
689
- return /* @__PURE__ */ jsxs("div", { ...attributes, className, children: [
690
- children,
691
- /* @__PURE__ */ jsxs(DraggableBlock, { element, readOnly, blockRef, children: [
692
- renderedBlockFromProps && /* @__PURE__ */ jsx("div", { ref: blockRef, contentEditable: !1, children: renderedBlockFromProps }),
693
- !renderedBlockFromProps && /* @__PURE__ */ jsx(DefaultBlockObject, { selected, children: /* @__PURE__ */ jsx(DefaultObject, { value }) })
694
- ] })
695
- ] }, element._key);
696
- };
697
- Element.displayName = "Element";
698
- const PortableTextEditorContext = createContext(null), usePortableTextEditor = () => {
699
- const editor = useContext(PortableTextEditorContext);
700
- if (!editor)
701
- throw new Error("The `usePortableTextEditor` hook must be used inside the <PortableTextEditor> component's context.");
702
- return editor;
703
- };
704
- function DefaultAnnotation(props) {
705
- const $ = c(6);
706
- let t0;
707
- $[0] !== props.annotation ? (t0 = () => alert(JSON.stringify(props.annotation)), $[0] = props.annotation, $[1] = t0) : t0 = $[1];
708
- const handleClick = t0;
709
- let t1;
710
- $[2] === Symbol.for("react.memo_cache_sentinel") ? (t1 = {
711
- color: "blue"
712
- }, $[2] = t1) : t1 = $[2];
713
- let t2;
714
- 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;
715
- }
716
- DefaultAnnotation.displayName = "DefaultAnnotation";
717
- function getPortableTextMemberSchemaTypes(portableTextType) {
718
- if (!portableTextType)
719
- throw new Error("Parameter 'portabletextType' missing (required)");
720
- const blockType = portableTextType.of?.find(findBlockType);
721
- if (!blockType)
722
- throw new Error("Block type is not defined in this schema (required)");
723
- const childrenField = blockType.fields?.find((field) => field.name === "children");
724
- if (!childrenField)
725
- throw new Error("Children field for block type found in schema (required)");
726
- const ofType = childrenField.type.of;
727
- if (!ofType)
728
- throw new Error("Valid types for block children not found in schema (required)");
729
- const spanType = ofType.find((memberType) => memberType.name === "span");
730
- if (!spanType)
731
- throw new Error("Span type not found in schema (required)");
732
- const inlineObjectTypes = ofType.filter((memberType) => memberType.name !== "span") || [], blockObjectTypes = portableTextType.of?.filter((field) => field.name !== blockType.name) || [];
733
- return {
734
- styles: resolveEnabledStyles(blockType),
735
- decorators: resolveEnabledDecorators(spanType),
736
- lists: resolveEnabledListItems(blockType),
737
- block: blockType,
738
- span: spanType,
739
- portableText: portableTextType,
740
- inlineObjects: inlineObjectTypes,
741
- blockObjects: blockObjectTypes,
742
- annotations: spanType.annotations
743
- };
744
- }
745
- function resolveEnabledStyles(blockType) {
746
- const styleField = blockType.fields?.find((btField) => btField.name === "style");
747
- if (!styleField)
748
- throw new Error("A field with name 'style' is not defined in the block type (required).");
749
- const textStyles = styleField.type.options?.list && styleField.type.options.list?.filter((style) => style.value);
750
- if (!textStyles || textStyles.length === 0)
751
- throw new Error("The style fields need at least one style defined. I.e: {title: 'Normal', value: 'normal'}.");
752
- return textStyles;
753
- }
754
- function resolveEnabledDecorators(spanType) {
755
- return spanType.decorators;
756
- }
757
- function resolveEnabledListItems(blockType) {
758
- const listField = blockType.fields?.find((btField) => btField.name === "listItem");
759
- if (!listField)
760
- throw new Error("A field with name 'listItem' is not defined in the block type (required).");
761
- const listItems = listField.type.options?.list && listField.type.options.list.filter((list) => list.value);
762
- if (!listItems)
763
- throw new Error("The list field need at least to be an empty array");
764
- return listItems;
765
- }
766
- function findBlockType(type) {
767
- return type.type ? findBlockType(type.type) : type.name === "block" ? type : null;
768
- }
769
- function compileType(rawType) {
770
- return Schema.compile({
771
- name: "blockTypeSchema",
772
- types: [rawType]
773
- }).get(rawType.name);
774
- }
775
- function selectionIsCollapsed(context) {
776
- return context.selection?.anchor.path.join() === context.selection?.focus.path.join() && context.selection?.anchor.offset === context.selection?.focus.offset;
777
- }
778
- function getFocusBlock(context) {
779
- const key = context.selection && isKeySegment(context.selection.focus.path[0]) ? context.selection.focus.path[0]._key : void 0, node = key ? context.value.find((block) => block._key === key) : void 0;
780
- return node && key ? {
781
- node,
782
- path: [{
783
- _key: key
784
- }]
785
- } : void 0;
786
- }
787
- function getFocusTextBlock(context) {
788
- const focusBlock = getFocusBlock(context);
789
- return focusBlock && isPortableTextTextBlock(focusBlock.node) ? {
790
- node: focusBlock.node,
791
- path: focusBlock.path
792
- } : void 0;
793
- }
794
- function getFocusBlockObject(context) {
795
- const focusBlock = getFocusBlock(context);
796
- return focusBlock && !isPortableTextTextBlock(focusBlock.node) ? {
797
- node: focusBlock.node,
798
- path: focusBlock.path
799
- } : void 0;
800
- }
801
- function getFocusChild(context) {
802
- const focusBlock = getFocusTextBlock(context);
803
- if (!focusBlock)
804
- return;
805
- const key = context.selection && isKeySegment(context.selection.focus.path[2]) ? context.selection.focus.path[2]._key : void 0, node = key ? focusBlock.node.children.find((span) => span._key === key) : void 0;
806
- return node && key ? {
807
- node,
808
- path: [...focusBlock.path, "children", {
809
- _key: key
810
- }]
811
- } : void 0;
812
- }
813
- function getFocusSpan(context) {
814
- const focusChild = getFocusChild(context);
815
- return focusChild && isPortableTextSpan$1(focusChild.node) ? {
816
- node: focusChild.node,
817
- path: focusChild.path
818
- } : void 0;
819
- }
820
- function getSelectionStartBlock(context) {
821
- const key = context.selection.backward ? isKeySegment(context.selection.focus.path[0]) ? context.selection.focus.path[0]._key : void 0 : isKeySegment(context.selection.anchor.path[0]) ? context.selection.anchor.path[0]._key : void 0, node = key ? context.value.find((block) => block._key === key) : void 0;
822
- return node && key ? {
823
- node,
824
- path: [{
825
- _key: key
826
- }]
827
- } : void 0;
828
- }
829
- function getSelectionEndBlock(context) {
830
- const key = context.selection.backward ? isKeySegment(context.selection.anchor.path[0]) ? context.selection.anchor.path[0]._key : void 0 : isKeySegment(context.selection.focus.path[0]) ? context.selection.focus.path[0]._key : void 0, node = key ? context.value.find((block) => block._key === key) : void 0;
831
- return node && key ? {
832
- node,
833
- path: [{
834
- _key: key
835
- }]
836
- } : void 0;
837
- }
838
- function getPreviousBlock(context) {
839
- let previousBlock;
840
- const selectionStartBlock = getSelectionStartBlock(context);
841
- if (!selectionStartBlock)
842
- return;
843
- let foundSelectionStartBlock = !1;
844
- for (const block of context.value) {
845
- if (block._key === selectionStartBlock.node._key) {
846
- foundSelectionStartBlock = !0;
847
- break;
848
- }
849
- previousBlock = {
850
- node: block,
851
- path: [{
852
- _key: block._key
853
- }]
854
- };
855
- }
856
- if (foundSelectionStartBlock && previousBlock)
857
- return previousBlock;
858
- }
859
- function getNextBlock(context) {
860
- let nextBlock;
861
- const selectionEndBlock = getSelectionEndBlock(context);
862
- if (!selectionEndBlock)
863
- return;
864
- let foundSelectionEndBlock = !1;
865
- for (const block of context.value) {
866
- if (block._key === selectionEndBlock.node._key) {
867
- foundSelectionEndBlock = !0;
868
- continue;
869
- }
870
- if (foundSelectionEndBlock) {
871
- nextBlock = {
872
- node: block,
873
- path: [{
874
- _key: block._key
875
- }]
876
- };
877
- break;
878
- }
879
- }
880
- if (foundSelectionEndBlock && nextBlock)
881
- return nextBlock;
882
- }
883
- function isEmptyTextBlock(block) {
884
- return block.children.length === 1 && block.children[0].text === "";
885
- }
886
- const breakingVoidBlock = {
887
- on: "insert break",
888
- guard: ({
889
- context
890
- }) => !!getFocusBlockObject(context),
891
- actions: [() => [{
892
- type: "insert text block",
893
- decorators: []
894
- }]]
895
- }, deletingEmptyTextBlockAfterBlockObject = {
896
- on: "delete backward",
897
- guard: ({
898
- context
899
- }) => {
900
- const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), previousBlock = getPreviousBlock(context);
901
- return !focusTextBlock || !selectionCollapsed || !previousBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(previousBlock.node) ? {
902
- focusTextBlock,
903
- previousBlock
904
- } : !1;
905
- },
906
- actions: [(_, {
907
- focusTextBlock,
908
- previousBlock
909
- }) => [{
910
- type: "delete",
911
- selection: {
912
- anchor: {
913
- path: focusTextBlock.path,
914
- offset: 0
915
- },
916
- focus: {
917
- path: focusTextBlock.path,
918
- offset: 0
919
- }
920
- }
921
- }, {
922
- type: "select",
923
- selection: {
924
- anchor: {
925
- path: previousBlock.path,
926
- offset: 0
927
- },
928
- focus: {
929
- path: previousBlock.path,
930
- offset: 0
931
- }
932
- }
933
- }]]
934
- }, deletingEmptyTextBlockBeforeBlockObject = {
935
- on: "delete forward",
936
- guard: ({
937
- context
938
- }) => {
939
- const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), nextBlock = getNextBlock(context);
940
- return !focusTextBlock || !selectionCollapsed || !nextBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(nextBlock.node) ? {
941
- focusTextBlock,
942
- nextBlock
943
- } : !1;
944
- },
945
- actions: [(_, {
946
- focusTextBlock,
947
- nextBlock
948
- }) => [{
949
- type: "delete",
950
- selection: {
951
- anchor: {
952
- path: focusTextBlock.path,
953
- offset: 0
954
- },
955
- focus: {
956
- path: focusTextBlock.path,
957
- offset: 0
958
- }
959
- }
960
- }, {
961
- type: "select",
962
- selection: {
963
- anchor: {
964
- path: nextBlock.path,
965
- offset: 0
966
- },
967
- focus: {
968
- path: nextBlock.path,
969
- offset: 0
970
- }
971
- }
972
- }]]
973
- }, coreBlockObjectBehaviors = [breakingVoidBlock, deletingEmptyTextBlockAfterBlockObject, deletingEmptyTextBlockBeforeBlockObject], clearListOnBackspace = {
974
- on: "delete backward",
975
- guard: ({
976
- context
977
- }) => {
978
- const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
979
- return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level === 1 ? {
980
- focusTextBlock
981
- } : !1;
982
- },
983
- actions: [(_, {
984
- focusTextBlock
985
- }) => [{
986
- type: "unset block",
987
- props: ["listItem", "level"],
988
- paths: [focusTextBlock.path]
989
- }]]
990
- }, unindentListOnBackspace = {
991
- on: "delete backward",
992
- guard: ({
993
- context
994
- }) => {
995
- const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
996
- return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level !== void 0 && focusTextBlock.node.level > 1 ? {
997
- focusTextBlock,
998
- level: focusTextBlock.node.level - 1
999
- } : !1;
1000
- },
1001
- actions: [(_, {
1002
- focusTextBlock,
1003
- level
1004
- }) => [{
1005
- type: "set block",
1006
- level,
1007
- paths: [focusTextBlock.path]
1008
- }]]
1009
- }, coreListBehaviors = [clearListOnBackspace, unindentListOnBackspace], softReturn = {
1010
- on: "insert soft break",
1011
- actions: [() => [{
1012
- type: "insert text",
1013
- text: `
1014
- `
1015
- }]]
1016
- }, coreBehaviors = [softReturn, ...coreBlockObjectBehaviors, ...coreListBehaviors], debug$k = debugWithName("operationToPatches");
904
+ }), propsOrDefaultRendered = renderBlock ? renderBlock(renderProps) : children;
905
+ return /* @__PURE__ */ jsx("div", { ...attributes, className, spellCheck, children: /* @__PURE__ */ jsx(DraggableBlock, { element, readOnly, blockRef, children: /* @__PURE__ */ jsx("div", { ref: blockRef, children: propsOrDefaultRendered }) }) }, element._key);
906
+ }
907
+ const schemaType_0 = schemaTypes.blockObjects.find((_type_0) => _type_0.name === element._type);
908
+ if (!schemaType_0)
909
+ throw new Error(`Could not find schema type for block element of _type ${element._type}`);
910
+ className = "pt-block pt-object-block";
911
+ const block_0 = fromSlateValue([element], schemaTypes.block.name, KEY_TO_VALUE_ELEMENT.get(editor))[0];
912
+ let renderedBlockFromProps;
913
+ if (renderBlock) {
914
+ const _props = Object.defineProperty({
915
+ children: /* @__PURE__ */ jsx(DefaultObject, { value }),
916
+ editorElementRef: blockRef,
917
+ focused,
918
+ path: blockPath,
919
+ schemaType: schemaType_0,
920
+ selected,
921
+ value: block_0
922
+ }, "type", {
923
+ enumerable: !1,
924
+ get() {
925
+ return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaType_0;
926
+ }
927
+ });
928
+ renderedBlockFromProps = renderBlock(_props);
929
+ }
930
+ return /* @__PURE__ */ jsxs("div", { ...attributes, className, children: [
931
+ children,
932
+ /* @__PURE__ */ jsxs(DraggableBlock, { element, readOnly, blockRef, children: [
933
+ renderedBlockFromProps && /* @__PURE__ */ jsx("div", { ref: blockRef, contentEditable: !1, children: renderedBlockFromProps }),
934
+ !renderedBlockFromProps && /* @__PURE__ */ jsx(DefaultBlockObject, { selected, children: /* @__PURE__ */ jsx(DefaultObject, { value }) })
935
+ ] })
936
+ ] }, element._key);
937
+ };
938
+ Element.displayName = "Element";
939
+ const PortableTextEditorContext = createContext(null), usePortableTextEditor = () => {
940
+ const editor = useContext(PortableTextEditorContext);
941
+ if (!editor)
942
+ throw new Error("The `usePortableTextEditor` hook must be used inside the <PortableTextEditor> component's context.");
943
+ return editor;
944
+ };
945
+ function DefaultAnnotation(props) {
946
+ const $ = c(6);
947
+ let t0;
948
+ $[0] !== props.annotation ? (t0 = () => alert(JSON.stringify(props.annotation)), $[0] = props.annotation, $[1] = t0) : t0 = $[1];
949
+ const handleClick = t0;
950
+ let t1;
951
+ $[2] === Symbol.for("react.memo_cache_sentinel") ? (t1 = {
952
+ color: "blue"
953
+ }, $[2] = t1) : t1 = $[2];
954
+ let t2;
955
+ 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
+ }
957
+ 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
+ function compileType(rawType) {
1011
+ return Schema.compile({
1012
+ name: "blockTypeSchema",
1013
+ types: [rawType]
1014
+ }).get(rawType.name);
1015
+ }
1016
+ const debug$k = debugWithName("operationToPatches");
1017
1017
  function createOperationToPatches(types) {
1018
1018
  const textBlockName = types.block.name;
1019
1019
  function insertTextPatch(editor, operation, beforeValue) {
@@ -5282,7 +5282,137 @@ function performDefaultAction({
5282
5282
  });
5283
5283
  }
5284
5284
  }
5285
- const networkLogic = fromCallback(({
5285
+ const breakingVoidBlock = {
5286
+ on: "insert break",
5287
+ guard: ({
5288
+ context
5289
+ }) => !!getFocusBlockObject(context),
5290
+ actions: [() => [{
5291
+ type: "insert text block",
5292
+ decorators: []
5293
+ }]]
5294
+ }, deletingEmptyTextBlockAfterBlockObject = {
5295
+ on: "delete backward",
5296
+ guard: ({
5297
+ context
5298
+ }) => {
5299
+ const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), previousBlock = getPreviousBlock(context);
5300
+ return !focusTextBlock || !selectionCollapsed || !previousBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(previousBlock.node) ? {
5301
+ focusTextBlock,
5302
+ previousBlock
5303
+ } : !1;
5304
+ },
5305
+ actions: [(_, {
5306
+ focusTextBlock,
5307
+ previousBlock
5308
+ }) => [{
5309
+ type: "delete",
5310
+ selection: {
5311
+ anchor: {
5312
+ path: focusTextBlock.path,
5313
+ offset: 0
5314
+ },
5315
+ focus: {
5316
+ path: focusTextBlock.path,
5317
+ offset: 0
5318
+ }
5319
+ }
5320
+ }, {
5321
+ type: "select",
5322
+ selection: {
5323
+ anchor: {
5324
+ path: previousBlock.path,
5325
+ offset: 0
5326
+ },
5327
+ focus: {
5328
+ path: previousBlock.path,
5329
+ offset: 0
5330
+ }
5331
+ }
5332
+ }]]
5333
+ }, deletingEmptyTextBlockBeforeBlockObject = {
5334
+ on: "delete forward",
5335
+ guard: ({
5336
+ context
5337
+ }) => {
5338
+ const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), nextBlock = getNextBlock(context);
5339
+ return !focusTextBlock || !selectionCollapsed || !nextBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(nextBlock.node) ? {
5340
+ focusTextBlock,
5341
+ nextBlock
5342
+ } : !1;
5343
+ },
5344
+ actions: [(_, {
5345
+ focusTextBlock,
5346
+ nextBlock
5347
+ }) => [{
5348
+ type: "delete",
5349
+ selection: {
5350
+ anchor: {
5351
+ path: focusTextBlock.path,
5352
+ offset: 0
5353
+ },
5354
+ focus: {
5355
+ path: focusTextBlock.path,
5356
+ offset: 0
5357
+ }
5358
+ }
5359
+ }, {
5360
+ type: "select",
5361
+ selection: {
5362
+ anchor: {
5363
+ path: nextBlock.path,
5364
+ offset: 0
5365
+ },
5366
+ focus: {
5367
+ path: nextBlock.path,
5368
+ offset: 0
5369
+ }
5370
+ }
5371
+ }]]
5372
+ }, coreBlockObjectBehaviors = [breakingVoidBlock, deletingEmptyTextBlockAfterBlockObject, deletingEmptyTextBlockBeforeBlockObject], clearListOnBackspace = {
5373
+ on: "delete backward",
5374
+ guard: ({
5375
+ context
5376
+ }) => {
5377
+ const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
5378
+ return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level === 1 ? {
5379
+ focusTextBlock
5380
+ } : !1;
5381
+ },
5382
+ actions: [(_, {
5383
+ focusTextBlock
5384
+ }) => [{
5385
+ type: "unset block",
5386
+ props: ["listItem", "level"],
5387
+ paths: [focusTextBlock.path]
5388
+ }]]
5389
+ }, unindentListOnBackspace = {
5390
+ on: "delete backward",
5391
+ guard: ({
5392
+ context
5393
+ }) => {
5394
+ const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
5395
+ return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level !== void 0 && focusTextBlock.node.level > 1 ? {
5396
+ focusTextBlock,
5397
+ level: focusTextBlock.node.level - 1
5398
+ } : !1;
5399
+ },
5400
+ actions: [(_, {
5401
+ focusTextBlock,
5402
+ level
5403
+ }) => [{
5404
+ type: "set block",
5405
+ level,
5406
+ paths: [focusTextBlock.path]
5407
+ }]]
5408
+ }, coreListBehaviors = [clearListOnBackspace, unindentListOnBackspace], softReturn = {
5409
+ on: "insert soft break",
5410
+ actions: [() => [{
5411
+ type: "insert text",
5412
+ text: `
5413
+ `
5414
+ }]]
5415
+ }, coreBehaviors = [softReturn, ...coreBlockObjectBehaviors, ...coreListBehaviors], networkLogic = fromCallback(({
5286
5416
  sendBack
5287
5417
  }) => {
5288
5418
  const onlineHandler = () => {
@@ -5305,6 +5435,11 @@ const networkLogic = fromCallback(({
5305
5435
  input: {}
5306
5436
  },
5307
5437
  actions: {
5438
+ "assign behaviors": assign({
5439
+ behaviors: ({
5440
+ event
5441
+ }) => (assertEvent(event, "update behaviors"), [...coreBehaviors, ...event.behaviors])
5442
+ }),
5308
5443
  "assign schema": assign({
5309
5444
  schema: ({
5310
5445
  event
@@ -5397,7 +5532,7 @@ const networkLogic = fromCallback(({
5397
5532
  context: ({
5398
5533
  input
5399
5534
  }) => ({
5400
- behaviors: input.behaviors,
5535
+ behaviors: input.behaviors ? [...coreBehaviors, ...input.behaviors] : coreBehaviors,
5401
5536
  keyGenerator: input.keyGenerator,
5402
5537
  pendingEvents: [],
5403
5538
  schema: input.schema
@@ -5472,6 +5607,9 @@ const networkLogic = fromCallback(({
5472
5607
  type: "done loading"
5473
5608
  })
5474
5609
  },
5610
+ "update behaviors": {
5611
+ actions: "assign behaviors"
5612
+ },
5475
5613
  "update schema": {
5476
5614
  actions: "assign schema"
5477
5615
  },
@@ -5582,18 +5720,21 @@ class PortableTextEditor extends Component {
5582
5720
  * The editor API (currently implemented with Slate).
5583
5721
  */
5584
5722
  constructor(props) {
5585
- if (super(props), !props.schemaType)
5586
- throw new Error('PortableTextEditor: missing "schemaType" property');
5587
- props.incomingPatches$ && console.warn("The prop 'incomingPatches$' is deprecated and renamed to 'patches$'"), this.schemaTypes = getPortableTextMemberSchemaTypes(props.schemaType.hasOwnProperty("jsonType") ? props.schemaType : compileType(props.schemaType)), this.editorActor = createActor(editorMachine, {
5588
- input: {
5589
- behaviors: coreBehaviors,
5590
- keyGenerator: props.keyGenerator || defaultKeyGenerator,
5591
- schema: this.schemaTypes
5592
- }
5593
- }), this.editorActor.start();
5723
+ if (super(props), props.editor)
5724
+ this.editorActor = props.editor, this.editorActor.start(), this.schemaTypes = this.editorActor.getSnapshot().context.schema;
5725
+ else {
5726
+ if (!props.schemaType)
5727
+ throw new Error('PortableTextEditor: missing "schemaType" property');
5728
+ props.incomingPatches$ && console.warn("The prop 'incomingPatches$' is deprecated and renamed to 'patches$'"), this.schemaTypes = getPortableTextMemberSchemaTypes(props.schemaType.hasOwnProperty("jsonType") ? props.schemaType : compileType(props.schemaType)), this.editorActor = props.editor ?? createActor(editorMachine, {
5729
+ input: {
5730
+ keyGenerator: props.keyGenerator || defaultKeyGenerator,
5731
+ schema: this.schemaTypes
5732
+ }
5733
+ }), this.editorActor.start();
5734
+ }
5594
5735
  }
5595
5736
  componentDidUpdate(prevProps) {
5596
- this.props.schemaType !== prevProps.schemaType && (this.schemaTypes = getPortableTextMemberSchemaTypes(this.props.schemaType.hasOwnProperty("jsonType") ? this.props.schemaType : compileType(this.props.schemaType)), this.editorActor.send({
5737
+ !this.props.editor && !prevProps.editor && this.props.schemaType !== prevProps.schemaType && (this.schemaTypes = getPortableTextMemberSchemaTypes(this.props.schemaType.hasOwnProperty("jsonType") ? this.props.schemaType : compileType(this.props.schemaType)), this.editorActor.send({
5597
5738
  type: "update schema",
5598
5739
  schema: this.schemaTypes
5599
5740
  })), this.props.editorRef !== prevProps.editorRef && this.props.editorRef && (this.props.editorRef.current = this);
@@ -5609,19 +5750,14 @@ class PortableTextEditor extends Component {
5609
5750
  return this.editable.getValue();
5610
5751
  };
5611
5752
  render() {
5612
- const {
5613
- value,
5614
- children,
5615
- patches$,
5616
- incomingPatches$
5617
- } = this.props, _patches$ = incomingPatches$ || patches$, maxBlocks = typeof this.props.maxBlocks > "u" ? void 0 : Number.parseInt(this.props.maxBlocks.toString(), 10) || void 0, readOnly = !!this.props.readOnly;
5753
+ const maxBlocks = this.props.editor || typeof this.props.maxBlocks > "u" ? void 0 : Number.parseInt(this.props.maxBlocks.toString(), 10) || void 0, readOnly = !!this.props.readOnly, legacyPatches = this.props.editor ? void 0 : this.props.incomingPatches$ ?? this.props.patches$;
5618
5754
  return /* @__PURE__ */ jsxs(Fragment, { children: [
5619
- _patches$ ? /* @__PURE__ */ jsx(RoutePatchesObservableToEditorActor, { editorActor: this.editorActor, patches$: _patches$ }) : null,
5755
+ legacyPatches ? /* @__PURE__ */ jsx(RoutePatchesObservableToEditorActor, { editorActor: this.editorActor, patches$: legacyPatches }) : null,
5620
5756
  /* @__PURE__ */ jsx(EditorActorContext.Provider, { value: this.editorActor, children: /* @__PURE__ */ jsx(SlateContainer, { editorActor: this.editorActor, maxBlocks, portableTextEditor: this, readOnly, children: /* @__PURE__ */ jsx(PortableTextEditorContext.Provider, { value: this, children: /* @__PURE__ */ jsx(PortableTextEditorReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsxs(PortableTextEditorSelectionProvider, { editorActor: this.editorActor, children: [
5621
5757
  /* @__PURE__ */ jsx(Synchronizer, { editorActor: this.editorActor, getValue: this.getValue, onChange: (change) => {
5622
- this.props.onChange(change), this.change$.next(change);
5623
- }, value }),
5624
- children
5758
+ this.props.editor || this.props.onChange(change), this.change$.next(change);
5759
+ }, value: this.props.value }),
5760
+ this.props.children
5625
5761
  ] }) }) }) }) })
5626
5762
  ] });
5627
5763
  }
@@ -6079,11 +6215,30 @@ const debug = debugWithName("component:Editable"), PLACEHOLDER_STYLE = {
6079
6215
  ) : null;
6080
6216
  });
6081
6217
  PortableTextEditable.displayName = "ForwardRef(PortableTextEditable)";
6218
+ function useEditor(config) {
6219
+ const $ = c(8);
6220
+ 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 = {
6227
+ input: {
6228
+ behaviors: config.behaviors,
6229
+ keyGenerator: t2,
6230
+ schema
6231
+ }
6232
+ }, $[4] = config.behaviors, $[5] = t2, $[6] = schema, $[7] = t3) : t3 = $[7], useActorRef(editorMachine, t3);
6233
+ }
6082
6234
  export {
6083
6235
  PortableTextEditable,
6084
6236
  PortableTextEditor,
6237
+ createMarkdownBehaviors,
6238
+ defineBehavior,
6085
6239
  editorMachine,
6086
6240
  defaultKeyGenerator as keyGenerator,
6241
+ useEditor,
6087
6242
  usePortableTextEditor,
6088
6243
  usePortableTextEditorSelection
6089
6244
  };