@portabletext/plugin-sdk-value 7.0.34 → 7.0.36-crx.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/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import {DocumentHandle} from '@sanity/sdk-react'
2
2
  import {JSX} from 'react'
3
+ import {Patch} from '@portabletext/editor'
3
4
  import {PortableTextBlock} from '@portabletext/editor'
4
5
 
5
6
  /**
@@ -18,6 +19,22 @@ declare type ValueSyncConfig = {
18
19
  getRemoteValue: () => PortableTextBlock[] | null | undefined
19
20
  pushValue: (value: PortableTextBlock[]) => void
20
21
  onRemoteValueChange: (callback: () => void) => () => void
22
+ /**
23
+ * Optional patch channel. When provided, operational patches from other
24
+ * clients are applied directly to the editor (in every state) instead of
25
+ * waiting for a whole-value diff, and local editor patches are pushed
26
+ * through `pushPatches`. The whole-value sync remains as a fallback for
27
+ * anything the patch channel cannot express.
28
+ */
29
+ onRemotePatches?: (
30
+ callback: (patches: Patch[]) => void,
31
+ ) => (() => void) | undefined
32
+ /**
33
+ * Pushes the editor's own operational patches to the remote store. May
34
+ * throw when a patch cannot be converted, in which case the plugin falls
35
+ * back to pushing the whole value.
36
+ */
37
+ pushPatches?: (patches: Patch[]) => void
21
38
  }
22
39
 
23
40
  /**
package/dist/index.js CHANGED
@@ -3,10 +3,10 @@ import { c } from "react/compiler-runtime";
3
3
  import { useEditor } from "@portabletext/editor";
4
4
  import { diffValue } from "@sanity/diff-patch";
5
5
  import { parsePath } from "@sanity/json-match";
6
- import { useEditDocument, useSanityInstance, getDocumentState } from "@sanity/sdk-react";
6
+ import { useEditDocument, useSanityInstance, useApplyDocumentActions, getDocumentState, subscribeDocumentEvents, editDocument } from "@sanity/sdk-react";
7
7
  import { useActorRef } from "@xstate/react";
8
+ import "react";
8
9
  import { fromCallback, setup } from "xstate";
9
- const ARRAYIFY_ERROR_MESSAGE = "Unexpected path format from diffValue output. Please report this issue.";
10
10
  function* getSegments(node) {
11
11
  node.base && (yield* getSegments(node.base)), node.segment.type !== "This" && (yield node.segment);
12
12
  }
@@ -14,77 +14,192 @@ function isKeyPath(node) {
14
14
  return node.type !== "Path" || node.base || node.recursive || node.segment.type !== "Identifier" ? !1 : node.segment.name === "_key";
15
15
  }
16
16
  function arrayifyPath(pathExpr) {
17
- const node = parsePath(pathExpr);
18
- if (!node)
19
- return [];
20
- if (node.type !== "Path")
21
- throw new Error(ARRAYIFY_ERROR_MESSAGE);
22
- return Array.from(getSegments(node)).map((segment) => {
23
- if (segment.type === "Identifier")
24
- return segment.name;
25
- if (segment.type !== "Subscript")
26
- throw new Error(ARRAYIFY_ERROR_MESSAGE);
27
- if (segment.elements.length !== 1)
28
- throw new Error(ARRAYIFY_ERROR_MESSAGE);
17
+ let node;
18
+ try {
19
+ node = parsePath(pathExpr);
20
+ } catch {
21
+ return null;
22
+ }
23
+ if (!node || node.type !== "Path")
24
+ return null;
25
+ const path = [];
26
+ for (const segment of getSegments(node)) {
27
+ if (segment.type === "Identifier") {
28
+ path.push(segment.name);
29
+ continue;
30
+ }
31
+ if (segment.type !== "Subscript" || segment.elements.length !== 1)
32
+ return null;
29
33
  const [element] = segment.elements;
30
- if (element.type === "Number")
31
- return element.value;
32
- if (element.type !== "Comparison")
33
- throw new Error(ARRAYIFY_ERROR_MESSAGE);
34
- if (element.operator !== "==")
35
- throw new Error(ARRAYIFY_ERROR_MESSAGE);
34
+ if (element.type === "Number") {
35
+ path.push(element.value);
36
+ continue;
37
+ }
38
+ if (element.type !== "Comparison" || element.operator !== "==")
39
+ return null;
36
40
  const keyPathNode = [element.left, element.right].find(isKeyPath);
37
41
  if (!keyPathNode)
38
- throw new Error(ARRAYIFY_ERROR_MESSAGE);
42
+ return null;
39
43
  const other = element.left === keyPathNode ? element.right : element.left;
40
44
  if (other.type !== "String")
41
- throw new Error(ARRAYIFY_ERROR_MESSAGE);
42
- return {
45
+ return null;
46
+ path.push({
43
47
  _key: other.value
44
- };
45
- });
48
+ });
49
+ }
50
+ return path;
46
51
  }
47
52
  function convertPatches(patches) {
48
- return patches.flatMap((p) => Object.entries(p).flatMap(([type, values]) => {
49
- const origin = "remote";
50
- switch (type) {
53
+ let incomplete = !1;
54
+ return {
55
+ patches: patches.flatMap((operation) => Object.entries(operation).flatMap(([type, values]) => {
56
+ const origin = "remote";
57
+ switch (type) {
58
+ case "set":
59
+ case "setIfMissing":
60
+ case "diffMatchPatch":
61
+ case "inc":
62
+ case "dec":
63
+ return Object.entries(values).flatMap(([pathExpr, value]) => {
64
+ const path = arrayifyPath(pathExpr);
65
+ return path ? [{
66
+ type,
67
+ value,
68
+ origin,
69
+ path
70
+ }] : (incomplete = !0, []);
71
+ });
72
+ case "unset":
73
+ return Array.isArray(values) ? values.flatMap((pathExpr) => {
74
+ const path = arrayifyPath(pathExpr);
75
+ return path ? [{
76
+ type,
77
+ origin,
78
+ path
79
+ }] : (incomplete = !0, []);
80
+ }) : [];
81
+ case "insert": {
82
+ const {
83
+ items,
84
+ ...rest
85
+ } = values, position = Object.keys(rest).at(0);
86
+ if (!position)
87
+ return [];
88
+ const pathExpr = rest[position], path = arrayifyPath(pathExpr);
89
+ return path ? [{
90
+ type,
91
+ origin,
92
+ position,
93
+ path,
94
+ items
95
+ }] : (incomplete = !0, []);
96
+ }
97
+ default:
98
+ return [];
99
+ }
100
+ })),
101
+ incomplete
102
+ };
103
+ }
104
+ const STRINGIFY_ERROR_MESSAGE = "Unable to convert an editor patch path to a Sanity path expression.";
105
+ function stringifyPatchPath(path) {
106
+ let result = "";
107
+ for (const segment of path)
108
+ if (typeof segment == "string")
109
+ result = result === "" ? segment : `${result}.${segment}`;
110
+ else if (typeof segment == "number")
111
+ result = `${result}[${segment}]`;
112
+ else if (typeof segment == "object" && segment !== null && "_key" in segment)
113
+ result = `${result}[_key=="${segment._key}"]`;
114
+ else
115
+ throw new Error(STRINGIFY_ERROR_MESSAGE);
116
+ return result;
117
+ }
118
+ function prefixPathExpression(prefix, expression) {
119
+ return expression === "" ? prefix : expression.startsWith("[") ? `${prefix}${expression}` : `${prefix}.${expression}`;
120
+ }
121
+ function convertPatchesToSanity(patches, options) {
122
+ return patches.map((patch) => {
123
+ const pathExpression = prefixPathExpression(options.prefix, stringifyPatchPath(patch.path));
124
+ switch (patch.type) {
51
125
  case "set":
126
+ return {
127
+ set: {
128
+ [pathExpression]: patch.value
129
+ }
130
+ };
52
131
  case "setIfMissing":
132
+ return {
133
+ setIfMissing: {
134
+ [pathExpression]: patch.value
135
+ }
136
+ };
53
137
  case "diffMatchPatch":
138
+ return {
139
+ diffMatchPatch: {
140
+ [pathExpression]: patch.value
141
+ }
142
+ };
54
143
  case "inc":
144
+ return {
145
+ inc: {
146
+ [pathExpression]: patch.value
147
+ }
148
+ };
55
149
  case "dec":
56
- return Object.entries(values).map(([pathExpr, value]) => ({
57
- type,
58
- value,
59
- origin,
60
- path: arrayifyPath(pathExpr)
61
- }));
150
+ return {
151
+ dec: {
152
+ [pathExpression]: patch.value
153
+ }
154
+ };
62
155
  case "unset":
63
- return Array.isArray(values) ? values.map(arrayifyPath).map((path) => ({
64
- type,
65
- origin,
66
- path
67
- })) : [];
68
- case "insert": {
69
- const {
70
- items,
71
- ...rest
72
- } = values, position = Object.keys(rest).at(0);
73
- if (!position)
74
- return [];
75
- const pathExpr = rest[position];
76
- return [{
77
- type,
78
- origin,
79
- position,
80
- path: arrayifyPath(pathExpr),
81
- items
82
- }];
83
- }
156
+ return {
157
+ unset: [pathExpression]
158
+ };
159
+ case "insert":
160
+ return {
161
+ insert: {
162
+ [patch.position]: pathExpression,
163
+ items: patch.items
164
+ }
165
+ };
84
166
  default:
85
- return [];
167
+ throw new Error(STRINGIFY_ERROR_MESSAGE);
168
+ }
169
+ });
170
+ }
171
+ function segmentsEqual(a, b) {
172
+ return typeof a == "string" || typeof a == "number" ? a === b : typeof b == "string" || typeof b == "number" || Array.isArray(a) || Array.isArray(b) ? !1 : a._key === b._key;
173
+ }
174
+ function scopeRemotePatches(patches, fieldPath) {
175
+ const prefix = arrayifyPath(fieldPath);
176
+ if (!prefix)
177
+ return null;
178
+ const {
179
+ patches: converted,
180
+ incomplete
181
+ } = convertPatches(patches);
182
+ if (incomplete)
183
+ return null;
184
+ const scoped = [];
185
+ for (const patch of converted) {
186
+ const overlap = Math.min(patch.path.length, prefix.length);
187
+ let touchesField = !0;
188
+ for (let index = 0; index < overlap; index++)
189
+ if (!segmentsEqual(patch.path[index], prefix[index])) {
190
+ touchesField = !1;
191
+ break;
192
+ }
193
+ if (touchesField) {
194
+ if (patch.path.length <= prefix.length)
195
+ return null;
196
+ scoped.push({
197
+ ...patch,
198
+ path: patch.path.slice(prefix.length)
199
+ });
86
200
  }
87
- }));
201
+ }
202
+ return scoped;
88
203
  }
89
204
  function applySync({
90
205
  editor,
@@ -93,13 +208,32 @@ function applySync({
93
208
  const remoteValue = getRemoteValue();
94
209
  if (!remoteValue)
95
210
  return;
96
- const snapshot = editor.getSnapshot().context.value, patches = convertPatches(diffValue(snapshot, remoteValue));
211
+ const snapshot = editor.getSnapshot().context.value, {
212
+ patches,
213
+ incomplete
214
+ } = convertPatches(diffValue(snapshot, remoteValue));
215
+ if (incomplete || editor.getSnapshot().context.value !== snapshot) {
216
+ updateValueFromRemote({
217
+ editor,
218
+ getRemoteValue
219
+ });
220
+ return;
221
+ }
97
222
  patches.length && editor.send({
98
223
  type: "patches",
99
224
  patches,
100
225
  snapshot
101
226
  });
102
227
  }
228
+ function updateValueFromRemote({
229
+ editor,
230
+ getRemoteValue
231
+ }) {
232
+ editor.send({
233
+ type: "update value",
234
+ value: getRemoteValue() ?? []
235
+ });
236
+ }
103
237
  const listenToEditor = fromCallback(({
104
238
  sendBack,
105
239
  input
@@ -111,7 +245,8 @@ const listenToEditor = fromCallback(({
111
245
  }), mutationSubscription = input.editor.on("mutation", (event) => {
112
246
  sendBack({
113
247
  type: "mutation flushed",
114
- value: event.value
248
+ value: event.value,
249
+ patches: event.patches
115
250
  });
116
251
  });
117
252
  return () => {
@@ -124,6 +259,14 @@ const listenToEditor = fromCallback(({
124
259
  sendBack({
125
260
  type: "remote value changed"
126
261
  });
262
+ })), listenToRemotePatches = fromCallback(({
263
+ sendBack,
264
+ input
265
+ }) => input.onRemotePatches?.((patches) => {
266
+ sendBack({
267
+ type: "remote patches received",
268
+ patches
269
+ });
127
270
  })), valueSyncMachine = setup({
128
271
  types: {
129
272
  context: {},
@@ -134,9 +277,9 @@ const listenToEditor = fromCallback(({
134
277
  "send initial value": ({
135
278
  context
136
279
  }) => {
137
- context.editor.send({
138
- type: "update value",
139
- value: context.getRemoteValue() ?? []
280
+ updateValueFromRemote({
281
+ editor: context.editor,
282
+ getRemoteValue: context.getRemoteValue
140
283
  });
141
284
  },
142
285
  "push to remote": () => {
@@ -159,11 +302,22 @@ const listenToEditor = fromCallback(({
159
302
  getRemoteValue: context.getRemoteValue
160
303
  });
161
304
  });
305
+ },
306
+ "apply remote patches": ({
307
+ context,
308
+ event
309
+ }) => {
310
+ event.type === "remote patches received" && event.patches.length !== 0 && context.editor.send({
311
+ type: "patches",
312
+ patches: event.patches,
313
+ snapshot: context.editor.getSnapshot().context.value
314
+ });
162
315
  }
163
316
  },
164
317
  actors: {
165
318
  "listen to editor": listenToEditor,
166
- "listen to remote": listenToRemote
319
+ "listen to remote": listenToRemote,
320
+ "listen to remote patches": listenToRemotePatches
167
321
  }
168
322
  }).createMachine({
169
323
  id: "value sync",
@@ -172,7 +326,8 @@ const listenToEditor = fromCallback(({
172
326
  }) => ({
173
327
  editor: input.editor,
174
328
  getRemoteValue: input.getRemoteValue,
175
- onRemoteValueChange: input.onRemoteValueChange
329
+ onRemoteValueChange: input.onRemoteValueChange,
330
+ onRemotePatches: input.onRemotePatches
176
331
  }),
177
332
  entry: ["send initial value"],
178
333
  invoke: [{
@@ -189,7 +344,21 @@ const listenToEditor = fromCallback(({
189
344
  }) => ({
190
345
  onRemoteValueChange: context.onRemoteValueChange
191
346
  })
347
+ }, {
348
+ src: "listen to remote patches",
349
+ input: ({
350
+ context
351
+ }) => ({
352
+ onRemotePatches: context.onRemotePatches
353
+ })
192
354
  }],
355
+ // operational patches from other clients apply immediately in every state;
356
+ // the editor merges them with any in-flight local changes
357
+ on: {
358
+ "remote patches received": {
359
+ actions: ["apply remote patches"]
360
+ }
361
+ },
193
362
  initial: "idle",
194
363
  states: {
195
364
  idle: {
@@ -236,12 +405,18 @@ const listenToEditor = fromCallback(({
236
405
  }
237
406
  }
238
407
  });
408
+ function isRemotePatchesEvent(event) {
409
+ return event.type === "remote-patches";
410
+ }
411
+ function getPublishedDocumentId(id) {
412
+ return id.startsWith("drafts.") ? id.slice(7) : id.startsWith("versions.") ? id.split(".").slice(2).join(".") : id;
413
+ }
239
414
  function SDKValuePlugin(props) {
240
- const $ = c(9), {
415
+ const $ = c(20), {
241
416
  documentId,
242
417
  documentType,
243
418
  path
244
- } = props, setSdkValue = useEditDocument(props), instance = useSanityInstance(props);
419
+ } = props, setSdkValue = useEditDocument(props), instance = useSanityInstance(props), applyActions = useApplyDocumentActions();
245
420
  let t0;
246
421
  $[0] !== documentId || $[1] !== documentType || $[2] !== instance || $[3] !== path ? (t0 = getDocumentState(instance, {
247
422
  documentId,
@@ -253,34 +428,75 @@ function SDKValuePlugin(props) {
253
428
  subscribe
254
429
  } = t0;
255
430
  let t1;
256
- return $[5] !== getCurrent || $[6] !== setSdkValue || $[7] !== subscribe ? (t1 = /* @__PURE__ */ jsx(ValueSyncPlugin, { getRemoteValue: getCurrent, pushValue: setSdkValue, onRemoteValueChange: subscribe }), $[5] = getCurrent, $[6] = setSdkValue, $[7] = subscribe, $[8] = t1) : t1 = $[8], t1;
431
+ $[5] !== documentId || $[6] !== instance || $[7] !== path ? (t1 = (callback) => subscribeDocumentEvents(instance, {
432
+ eventHandler: (event) => {
433
+ const candidate = event;
434
+ if (!isRemotePatchesEvent(candidate) || candidate.origin !== "remote" || getPublishedDocumentId(candidate.documentId) !== getPublishedDocumentId(documentId))
435
+ return;
436
+ let patches;
437
+ try {
438
+ patches = scopeRemotePatches(candidate.patches, path);
439
+ } catch {
440
+ return;
441
+ }
442
+ patches && patches.length > 0 && callback(patches);
443
+ }
444
+ }), $[5] = documentId, $[6] = instance, $[7] = path, $[8] = t1) : t1 = $[8];
445
+ const onRemotePatches = t1;
446
+ let t2;
447
+ $[9] !== applyActions || $[10] !== documentId || $[11] !== documentType || $[12] !== path ? (t2 = (patches_0) => {
448
+ const sanityPatches = convertPatchesToSanity(patches_0, {
449
+ prefix: path
450
+ }), action = {
451
+ ...editDocument({
452
+ documentId,
453
+ documentType
454
+ }, sanityPatches),
455
+ preserveOperations: !0
456
+ };
457
+ applyActions(action);
458
+ }, $[9] = applyActions, $[10] = documentId, $[11] = documentType, $[12] = path, $[13] = t2) : t2 = $[13];
459
+ const pushPatches = t2;
460
+ let t3;
461
+ return $[14] !== getCurrent || $[15] !== onRemotePatches || $[16] !== pushPatches || $[17] !== setSdkValue || $[18] !== subscribe ? (t3 = /* @__PURE__ */ jsx(ValueSyncPlugin, { getRemoteValue: getCurrent, pushValue: setSdkValue, onRemoteValueChange: subscribe, onRemotePatches, pushPatches }), $[14] = getCurrent, $[15] = onRemotePatches, $[16] = pushPatches, $[17] = setSdkValue, $[18] = subscribe, $[19] = t3) : t3 = $[19], t3;
257
462
  }
258
463
  function ValueSyncPlugin(props) {
259
- const $ = c(6), {
464
+ const $ = c(8), {
260
465
  getRemoteValue,
261
466
  pushValue,
262
- onRemoteValueChange
467
+ onRemoteValueChange,
468
+ onRemotePatches,
469
+ pushPatches
263
470
  } = props, editor = useEditor();
264
471
  let t0;
265
- $[0] !== pushValue ? (t0 = valueSyncMachine.provide({
472
+ $[0] !== pushPatches || $[1] !== pushValue ? (t0 = valueSyncMachine.provide({
266
473
  actions: {
267
474
  "push to remote": (t12) => {
268
475
  const {
269
476
  context,
270
477
  event
271
478
  } = t12;
272
- event.type === "mutation flushed" && pushValue(event.value ?? context.editor.getSnapshot().context.value);
479
+ if (event.type === "mutation flushed") {
480
+ if (pushPatches && event.patches.length > 0)
481
+ try {
482
+ pushPatches(event.patches);
483
+ return;
484
+ } catch {
485
+ }
486
+ pushValue(event.value ?? context.editor.getSnapshot().context.value);
487
+ }
273
488
  }
274
489
  }
275
- }), $[0] = pushValue, $[1] = t0) : t0 = $[1];
490
+ }), $[0] = pushPatches, $[1] = pushValue, $[2] = t0) : t0 = $[2];
276
491
  let t1;
277
- return $[2] !== editor || $[3] !== getRemoteValue || $[4] !== onRemoteValueChange ? (t1 = {
492
+ return $[3] !== editor || $[4] !== getRemoteValue || $[5] !== onRemotePatches || $[6] !== onRemoteValueChange ? (t1 = {
278
493
  input: {
279
494
  editor,
280
495
  getRemoteValue,
281
- onRemoteValueChange
496
+ onRemoteValueChange,
497
+ onRemotePatches
282
498
  }
283
- }, $[2] = editor, $[3] = getRemoteValue, $[4] = onRemoteValueChange, $[5] = t1) : t1 = $[5], useActorRef(t0, t1), null;
499
+ }, $[3] = editor, $[4] = getRemoteValue, $[5] = onRemotePatches, $[6] = onRemoteValueChange, $[7] = t1) : t1 = $[7], useActorRef(t0, t1), null;
284
500
  }
285
501
  export {
286
502
  SDKValuePlugin,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/plugin.sdk-value.tsx"],"sourcesContent":["import {\n useEditor,\n type Editor,\n type PortableTextBlock,\n type Patch as PtePatch,\n} from '@portabletext/editor'\nimport type {\n JSONValue,\n Path,\n PathSegment,\n InsertPatch as PteInsertPatch,\n} from '@portabletext/patches'\nimport {diffValue, type SanityPatchOperations} from '@sanity/diff-patch'\nimport {\n parsePath,\n type ExprNode,\n type PathNode,\n type SegmentNode,\n type ThisNode,\n} from '@sanity/json-match'\nimport {\n getDocumentState,\n useEditDocument,\n useSanityInstance,\n type DocumentHandle,\n} from '@sanity/sdk-react'\nimport {useActorRef} from '@xstate/react'\nimport {fromCallback, setup, type AnyEventObject} from 'xstate'\n\ntype InsertPatch = Required<Pick<SanityPatchOperations, 'insert'>>\n\nconst ARRAYIFY_ERROR_MESSAGE =\n 'Unexpected path format from diffValue output. Please report this issue.'\n\nfunction* getSegments(\n node: PathNode,\n): Generator<Exclude<SegmentNode, ThisNode>> {\n if (node.base) {\n yield* getSegments(node.base)\n }\n if (node.segment.type !== 'This') {\n yield node.segment\n }\n}\n\nfunction isKeyPath(node: ExprNode): node is PathNode {\n if (node.type !== 'Path') {\n return false\n }\n if (node.base) {\n return false\n }\n if (node.recursive) {\n return false\n }\n if (node.segment.type !== 'Identifier') {\n return false\n }\n return node.segment.name === '_key'\n}\n\nexport function arrayifyPath(pathExpr: string): Path {\n const node = parsePath(pathExpr)\n if (!node) {\n return []\n }\n if (node.type !== 'Path') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n\n return Array.from(getSegments(node)).map((segment): PathSegment => {\n if (segment.type === 'Identifier') {\n return segment.name\n }\n if (segment.type !== 'Subscript') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n if (segment.elements.length !== 1) {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n\n const [element] = segment.elements\n if (element.type === 'Number') {\n return element.value\n }\n\n if (element.type !== 'Comparison') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n if (element.operator !== '==') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n const keyPathNode = [element.left, element.right].find(isKeyPath)\n if (!keyPathNode) {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n const other = element.left === keyPathNode ? element.right : element.left\n if (other.type !== 'String') {\n throw new Error(ARRAYIFY_ERROR_MESSAGE)\n }\n return {_key: other.value}\n })\n}\n\nexport function convertPatches(patches: SanityPatchOperations[]): PtePatch[] {\n return patches.flatMap((p) => {\n return Object.entries(p).flatMap(([type, values]): PtePatch[] => {\n const origin = 'remote'\n\n switch (type) {\n case 'set':\n case 'setIfMissing':\n case 'diffMatchPatch':\n case 'inc':\n case 'dec': {\n return Object.entries(values).map(\n ([pathExpr, value]) =>\n ({type, value, origin, path: arrayifyPath(pathExpr)}) as PtePatch,\n )\n }\n case 'unset': {\n if (!Array.isArray(values)) {\n return []\n }\n return values.map(arrayifyPath).map((path) => ({type, origin, path}))\n }\n case 'insert': {\n const {items, ...rest} = values as InsertPatch['insert']\n type InsertPosition = PteInsertPatch['position']\n const position = Object.keys(rest).at(0) as InsertPosition | undefined\n\n if (!position) {\n return []\n }\n const pathExpr = (rest as {[K in InsertPosition]: string})[position]\n const insertPatch: PteInsertPatch = {\n type,\n origin,\n position,\n path: arrayifyPath(pathExpr),\n items: items as JSONValue[],\n }\n\n return [insertPatch]\n }\n\n default: {\n return []\n }\n }\n })\n })\n}\n\nfunction applySync({\n editor,\n getRemoteValue,\n}: {\n editor: Editor\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n}) {\n const remoteValue = getRemoteValue()\n\n if (!remoteValue) {\n return\n }\n\n const snapshot = editor.getSnapshot().context.value\n const patches = convertPatches(diffValue(snapshot, remoteValue))\n\n if (patches.length) {\n editor.send({type: 'patches', patches, snapshot})\n }\n}\n\nconst listenToEditor = fromCallback<AnyEventObject, {editor: Editor}>(\n ({sendBack, input}) => {\n const patchSubscription = input.editor.on('patch', () => {\n sendBack({type: 'patch emitted'})\n })\n\n const mutationSubscription = input.editor.on('mutation', (event) => {\n sendBack({type: 'mutation flushed', value: event.value})\n })\n\n return () => {\n patchSubscription.unsubscribe()\n mutationSubscription.unsubscribe()\n }\n },\n)\n\nconst listenToRemote = fromCallback<\n AnyEventObject,\n {onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']}\n>(({sendBack, input}) => {\n return input.onRemoteValueChange(() => {\n sendBack({type: 'remote value changed'})\n })\n})\n\nconst valueSyncMachine = setup({\n types: {\n context: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n },\n input: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n },\n events: {} as\n | {type: 'patch emitted'}\n | {type: 'mutation flushed'; value: PortableTextBlock[] | undefined}\n | {type: 'remote value changed'},\n },\n actions: {\n 'send initial value': ({context}) => {\n context.editor.send({\n type: 'update value',\n value: context.getRemoteValue() ?? [],\n })\n },\n 'push to remote': () => {\n throw new Error('push to remote must be provided via .provide()')\n },\n 'apply sync': ({context}) => {\n applySync({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n },\n 'defer then apply sync': ({context}) => {\n queueMicrotask(() => {\n applySync({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n })\n },\n },\n actors: {\n 'listen to editor': listenToEditor,\n 'listen to remote': listenToRemote,\n },\n}).createMachine({\n id: 'value sync',\n context: ({input}) => ({\n editor: input.editor,\n getRemoteValue: input.getRemoteValue,\n onRemoteValueChange: input.onRemoteValueChange,\n }),\n entry: ['send initial value'],\n invoke: [\n {\n src: 'listen to editor',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'listen to remote',\n input: ({context}) => ({\n onRemoteValueChange: context.onRemoteValueChange,\n }),\n },\n ],\n initial: 'idle',\n states: {\n 'idle': {\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n 'remote value changed': {\n actions: ['apply sync'],\n },\n },\n },\n 'local write': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote'],\n },\n 'remote value changed': {\n target: 'pending sync',\n },\n },\n },\n 'pushing to remote': {\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n 'remote value changed': {\n target: 'idle',\n },\n },\n },\n 'pending sync': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote', 'defer then apply sync'],\n },\n 'remote value changed': {},\n },\n },\n },\n})\n\ninterface SDKValuePluginProps extends DocumentHandle {\n path: string\n}\n\n/**\n * @public\n */\nexport function SDKValuePlugin(props: SDKValuePluginProps) {\n const {documentId, documentType, path} = props\n const setSdkValue = useEditDocument(props)\n const instance = useSanityInstance(props)\n\n const handle = {documentId, documentType, path}\n const {getCurrent, subscribe} = getDocumentState<PortableTextBlock[]>(\n instance,\n handle,\n )\n\n return (\n <ValueSyncPlugin\n getRemoteValue={getCurrent}\n pushValue={setSdkValue}\n onRemoteValueChange={subscribe}\n />\n )\n}\n\n/**\n * @internal\n */\ntype ValueSyncConfig = {\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n pushValue: (value: PortableTextBlock[]) => void\n onRemoteValueChange: (callback: () => void) => () => void\n}\n\n/**\n * NOTE: You are probably looking for SDKValuePlugin instead of this.\n * This is a lower-level plugin that only handles syncing the value\n * between the editor and a remote source. It does not know anything\n * about Sanity documents or how to fetch/update them.\n *\n * May be removed in the future, do not rely on this directly.\n *\n * @internal\n */\nexport function ValueSyncPlugin(props: ValueSyncConfig) {\n const {getRemoteValue, pushValue, onRemoteValueChange} = props\n const editor = useEditor()\n\n useActorRef(\n valueSyncMachine.provide({\n actions: {\n 'push to remote': ({context, event}) => {\n if (event.type !== 'mutation flushed') {\n return\n }\n\n pushValue(event.value ?? context.editor.getSnapshot().context.value)\n },\n },\n }),\n {\n input: {\n editor,\n getRemoteValue,\n onRemoteValueChange,\n },\n },\n )\n\n return null\n}\n"],"names":["ARRAYIFY_ERROR_MESSAGE","getSegments","node","base","segment","type","isKeyPath","recursive","name","arrayifyPath","pathExpr","parsePath","Error","Array","from","map","elements","length","element","value","operator","keyPathNode","left","right","find","other","_key","convertPatches","patches","flatMap","p","Object","entries","values","origin","path","isArray","items","rest","position","keys","at","applySync","editor","getRemoteValue","remoteValue","snapshot","getSnapshot","context","diffValue","send","listenToEditor","fromCallback","sendBack","input","patchSubscription","on","mutationSubscription","event","unsubscribe","listenToRemote","onRemoteValueChange","valueSyncMachine","setup","types","events","actions","send initial value","push to remote","apply sync","defer then apply sync","queueMicrotask","actors","createMachine","id","entry","invoke","src","initial","states","target","SDKValuePlugin","props","$","_c","documentId","documentType","setSdkValue","useEditDocument","instance","useSanityInstance","t0","getDocumentState","getCurrent","subscribe","t1","ValueSyncPlugin","pushValue","useEditor","provide","useActorRef"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/plugin.sdk-value.tsx"],"sourcesContent":["import {\n useEditor,\n type Editor,\n type PortableTextBlock,\n type Patch as PtePatch,\n} from '@portabletext/editor'\nimport type {\n JSONValue,\n Path,\n PathSegment,\n InsertPatch as PteInsertPatch,\n} from '@portabletext/patches'\nimport {diffValue, type SanityPatchOperations} from '@sanity/diff-patch'\nimport {\n parsePath,\n type ExprNode,\n type PathNode,\n type SegmentNode,\n type ThisNode,\n} from '@sanity/json-match'\nimport {\n editDocument,\n getDocumentState,\n subscribeDocumentEvents,\n useApplyDocumentActions,\n useEditDocument,\n useSanityInstance,\n type DocumentHandle,\n type EditDocumentAction,\n} from '@sanity/sdk-react'\nimport {useActorRef} from '@xstate/react'\nimport {useCallback} from 'react'\nimport {fromCallback, setup, type AnyEventObject} from 'xstate'\n\ntype InsertPatch = Required<Pick<SanityPatchOperations, 'insert'>>\n\nfunction* getSegments(\n node: PathNode,\n): Generator<Exclude<SegmentNode, ThisNode>> {\n if (node.base) {\n yield* getSegments(node.base)\n }\n if (node.segment.type !== 'This') {\n yield node.segment\n }\n}\n\nfunction isKeyPath(node: ExprNode): node is PathNode {\n if (node.type !== 'Path') {\n return false\n }\n if (node.base) {\n return false\n }\n if (node.recursive) {\n return false\n }\n if (node.segment.type !== 'Identifier') {\n return false\n }\n return node.segment.name === '_key'\n}\n\n/**\n * Converts a `diffValue` path expression (e.g. `[_key==\"a\"].children[0]`) into\n * a keyed Portable Text Editor path.\n *\n * Returns `null` – rather than throwing – for any expression that can't be\n * represented as a keyed PTE path. `diffValue` can emit such expressions in\n * practice: removing several non-keyed array items at once (e.g. clearing\n * multiple span `marks`) produces an array slice like `...marks[1:]`. Throwing\n * here would escape the synchronous `applySync` and break syncing entirely, so\n * we signal failure via `null` and let the caller skip the offending patch and\n * recover.\n */\nexport function arrayifyPath(pathExpr: string): Path | null {\n let node: ExprNode | undefined\n try {\n node = parsePath(pathExpr)\n } catch {\n // `parsePath` throws on malformed input such as an empty expression.\n return null\n }\n if (!node) {\n return null\n }\n if (node.type !== 'Path') {\n return null\n }\n\n const path: Path = []\n for (const segment of getSegments(node)) {\n if (segment.type === 'Identifier') {\n path.push(segment.name)\n continue\n }\n if (segment.type !== 'Subscript') {\n return null\n }\n if (segment.elements.length !== 1) {\n return null\n }\n\n const [element] = segment.elements\n if (element.type === 'Number') {\n path.push(element.value)\n continue\n }\n if (element.type !== 'Comparison') {\n // e.g. an array slice (`Slice`) that `diffValue` emits when removing\n // multiple non-keyed items at once.\n return null\n }\n if (element.operator !== '==') {\n return null\n }\n const keyPathNode = [element.left, element.right].find(isKeyPath)\n if (!keyPathNode) {\n return null\n }\n const other = element.left === keyPathNode ? element.right : element.left\n if (other.type !== 'String') {\n return null\n }\n path.push({_key: other.value})\n }\n\n return path\n}\n\n/**\n * Converts a batch of `diffValue` patch operations into PTE patches.\n *\n * `incomplete` is `true` when one or more operations had to be dropped because\n * their path couldn't be converted (see `arrayifyPath`). The caller uses this\n * to fall back to an authoritative full value update instead of persisting a\n * partial diff.\n */\nexport function convertPatches(patches: SanityPatchOperations[]): {\n patches: PtePatch[]\n incomplete: boolean\n} {\n let incomplete = false\n\n const converted = patches.flatMap((operation) => {\n return Object.entries(operation).flatMap(([type, values]): PtePatch[] => {\n const origin = 'remote'\n\n switch (type) {\n case 'set':\n case 'setIfMissing':\n case 'diffMatchPatch':\n case 'inc':\n case 'dec': {\n return Object.entries(values).flatMap(([pathExpr, value]) => {\n const path = arrayifyPath(pathExpr)\n if (!path) {\n incomplete = true\n return []\n }\n return [{type, value, origin, path} as PtePatch]\n })\n }\n case 'unset': {\n if (!Array.isArray(values)) {\n return []\n }\n return values.flatMap((pathExpr) => {\n const path = arrayifyPath(pathExpr)\n if (!path) {\n incomplete = true\n return []\n }\n return [{type, origin, path} as PtePatch]\n })\n }\n case 'insert': {\n const {items, ...rest} = values as InsertPatch['insert']\n type InsertPosition = PteInsertPatch['position']\n const position = Object.keys(rest).at(0) as InsertPosition | undefined\n\n if (!position) {\n return []\n }\n const pathExpr = (rest as {[K in InsertPosition]: string})[position]\n const path = arrayifyPath(pathExpr)\n if (!path) {\n incomplete = true\n return []\n }\n const insertPatch: PteInsertPatch = {\n type,\n origin,\n position,\n path,\n items: items as JSONValue[],\n }\n\n return [insertPatch]\n }\n\n default: {\n return []\n }\n }\n })\n })\n\n return {patches: converted, incomplete}\n}\n\nconst STRINGIFY_ERROR_MESSAGE =\n 'Unable to convert an editor patch path to a Sanity path expression.'\n\n/**\n * Converts a Portable Text Editor patch path (an array of segments) into a\n * Sanity json-match path expression. The inverse of `arrayifyPath`.\n *\n * @internal\n */\nexport function stringifyPatchPath(path: Path): string {\n let result = ''\n for (const segment of path) {\n if (typeof segment === 'string') {\n result = result === '' ? segment : `${result}.${segment}`\n } else if (typeof segment === 'number') {\n result = `${result}[${segment}]`\n } else if (\n typeof segment === 'object' &&\n segment !== null &&\n '_key' in segment\n ) {\n result = `${result}[_key==\"${segment._key}\"]`\n } else {\n throw new Error(STRINGIFY_ERROR_MESSAGE)\n }\n }\n return result\n}\n\nfunction prefixPathExpression(prefix: string, expression: string): string {\n if (expression === '') {\n return prefix\n }\n return expression.startsWith('[')\n ? `${prefix}${expression}`\n : `${prefix}.${expression}`\n}\n\n/**\n * `SanityPatchOperations` from `@sanity/diff-patch` only covers the\n * operations `diffValue` emits; the editor can additionally produce these.\n */\ntype SanityPatchOperationsWithExtras = SanityPatchOperations & {\n setIfMissing?: {[path: string]: unknown}\n inc?: {[path: string]: number}\n dec?: {[path: string]: number}\n}\n\n/**\n * Converts Portable Text Editor patches into Sanity patch operations rooted\n * at the given document field path. Throws if a patch cannot be converted;\n * callers should fall back to pushing the whole value.\n *\n * @internal\n */\nexport function convertPatchesToSanity(\n patches: PtePatch[],\n options: {prefix: string},\n): SanityPatchOperationsWithExtras[] {\n return patches.map((patch): SanityPatchOperationsWithExtras => {\n const pathExpression = prefixPathExpression(\n options.prefix,\n stringifyPatchPath(patch.path),\n )\n\n switch (patch.type) {\n case 'set':\n return {set: {[pathExpression]: patch.value}}\n case 'setIfMissing':\n return {setIfMissing: {[pathExpression]: patch.value}}\n case 'diffMatchPatch':\n return {diffMatchPatch: {[pathExpression]: patch.value}}\n case 'inc':\n return {inc: {[pathExpression]: patch.value as number}}\n case 'dec':\n return {dec: {[pathExpression]: patch.value as number}}\n case 'unset':\n return {unset: [pathExpression]}\n case 'insert':\n return {\n insert: {\n [patch.position]: pathExpression,\n items: patch.items,\n } as SanityPatchOperations['insert'],\n }\n default:\n throw new Error(STRINGIFY_ERROR_MESSAGE)\n }\n })\n}\n\nfunction segmentsEqual(a: PathSegment, b: PathSegment): boolean {\n if (typeof a === 'string' || typeof a === 'number') {\n return a === b\n }\n if (typeof b === 'string' || typeof b === 'number') {\n return false\n }\n if (Array.isArray(a) || Array.isArray(b)) {\n return false\n }\n return a._key === b._key\n}\n\n/**\n * Scopes document-rooted Sanity patches to the given field path, returning\n * field-relative Portable Text Editor patches. Patches outside the field are\n * dropped. Returns `null` when the field (or an ancestor of it) is replaced\n * wholesale, when the field path itself can't be converted, or when any patch\n * op can't be converted to a keyed editor path — in all of which the caller\n * should fall back to a full value sync rather than apply a partial batch.\n *\n * @internal\n */\nexport function scopeRemotePatches(\n patches: SanityPatchOperations[],\n fieldPath: string,\n): PtePatch[] | null {\n const prefix = arrayifyPath(fieldPath)\n if (!prefix) {\n return null\n }\n const {patches: converted, incomplete} = convertPatches(patches)\n if (incomplete) {\n // a patch op couldn't be converted to a keyed editor path; applying the\n // rest would leave the field partially updated, so fall back to full sync\n return null\n }\n const scoped: PtePatch[] = []\n\n for (const patch of converted) {\n const overlap = Math.min(patch.path.length, prefix.length)\n let touchesField = true\n for (let index = 0; index < overlap; index++) {\n if (!segmentsEqual(patch.path[index], prefix[index])) {\n touchesField = false\n break\n }\n }\n if (!touchesField) {\n continue\n }\n if (patch.path.length <= prefix.length) {\n // the patch targets the field itself or an ancestor of it, which\n // cannot be expressed as a field-relative operation\n return null\n }\n scoped.push({...patch, path: patch.path.slice(prefix.length)})\n }\n\n return scoped\n}\n\nfunction applySync({\n editor,\n getRemoteValue,\n}: {\n editor: Editor\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n}) {\n const remoteValue = getRemoteValue()\n\n if (!remoteValue) {\n return\n }\n\n const snapshot = editor.getSnapshot().context.value\n const {patches, incomplete} = convertPatches(diffValue(snapshot, remoteValue))\n\n // Recover with an authoritative full value update when the diff can't be\n // applied faithfully. Either a patch was dropped – replaying the rest would\n // leave the editor in a partial/garbled state – or the editor moved on from\n // `snapshot` while we were diffing, so the patches were computed against a\n // value the editor no longer holds and can't be reconciled safely.\n if (incomplete || editor.getSnapshot().context.value !== snapshot) {\n updateValueFromRemote({editor, getRemoteValue})\n return\n }\n\n if (patches.length) {\n editor.send({type: 'patches', patches, snapshot})\n }\n}\n\nfunction updateValueFromRemote({\n editor,\n getRemoteValue,\n}: {\n editor: Editor\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n}) {\n editor.send({type: 'update value', value: getRemoteValue() ?? []})\n}\n\nconst listenToEditor = fromCallback<AnyEventObject, {editor: Editor}>(\n ({sendBack, input}) => {\n const patchSubscription = input.editor.on('patch', () => {\n sendBack({type: 'patch emitted'})\n })\n\n const mutationSubscription = input.editor.on('mutation', (event) => {\n sendBack({\n type: 'mutation flushed',\n value: event.value,\n patches: event.patches,\n })\n })\n\n return () => {\n patchSubscription.unsubscribe()\n mutationSubscription.unsubscribe()\n }\n },\n)\n\nconst listenToRemote = fromCallback<\n AnyEventObject,\n {onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']}\n>(({sendBack, input}) => {\n return input.onRemoteValueChange(() => {\n sendBack({type: 'remote value changed'})\n })\n})\n\nconst listenToRemotePatches = fromCallback<\n AnyEventObject,\n {onRemotePatches: ValueSyncConfig['onRemotePatches']}\n>(({sendBack, input}) => {\n return input.onRemotePatches?.((patches) => {\n sendBack({type: 'remote patches received', patches})\n })\n})\n\nconst valueSyncMachine = setup({\n types: {\n context: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n onRemotePatches: ValueSyncConfig['onRemotePatches']\n },\n input: {} as {\n editor: Editor\n getRemoteValue: ValueSyncConfig['getRemoteValue']\n onRemoteValueChange: ValueSyncConfig['onRemoteValueChange']\n onRemotePatches: ValueSyncConfig['onRemotePatches']\n },\n events: {} as\n | {type: 'patch emitted'}\n | {\n type: 'mutation flushed'\n value: PortableTextBlock[] | undefined\n patches: PtePatch[]\n }\n | {type: 'remote value changed'}\n | {type: 'remote patches received'; patches: PtePatch[]},\n },\n actions: {\n 'send initial value': ({context}) => {\n updateValueFromRemote({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n },\n 'push to remote': () => {\n throw new Error('push to remote must be provided via .provide()')\n },\n 'apply sync': ({context}) => {\n applySync({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n },\n 'defer then apply sync': ({context}) => {\n queueMicrotask(() => {\n applySync({\n editor: context.editor,\n getRemoteValue: context.getRemoteValue,\n })\n })\n },\n 'apply remote patches': ({context, event}) => {\n if (event.type !== 'remote patches received') {\n return\n }\n if (event.patches.length === 0) {\n return\n }\n context.editor.send({\n type: 'patches',\n patches: event.patches,\n snapshot: context.editor.getSnapshot().context.value,\n })\n },\n },\n actors: {\n 'listen to editor': listenToEditor,\n 'listen to remote': listenToRemote,\n 'listen to remote patches': listenToRemotePatches,\n },\n}).createMachine({\n id: 'value sync',\n context: ({input}) => ({\n editor: input.editor,\n getRemoteValue: input.getRemoteValue,\n onRemoteValueChange: input.onRemoteValueChange,\n onRemotePatches: input.onRemotePatches,\n }),\n entry: ['send initial value'],\n invoke: [\n {\n src: 'listen to editor',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'listen to remote',\n input: ({context}) => ({\n onRemoteValueChange: context.onRemoteValueChange,\n }),\n },\n {\n src: 'listen to remote patches',\n input: ({context}) => ({\n onRemotePatches: context.onRemotePatches,\n }),\n },\n ],\n // operational patches from other clients apply immediately in every state;\n // the editor merges them with any in-flight local changes\n on: {\n 'remote patches received': {\n actions: ['apply remote patches'],\n },\n },\n initial: 'idle',\n states: {\n 'idle': {\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n 'remote value changed': {\n actions: ['apply sync'],\n },\n },\n },\n 'local write': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote'],\n },\n 'remote value changed': {\n target: 'pending sync',\n },\n },\n },\n 'pushing to remote': {\n on: {\n 'patch emitted': {\n target: 'local write',\n },\n 'remote value changed': {\n target: 'idle',\n },\n },\n },\n 'pending sync': {\n on: {\n 'patch emitted': {},\n 'mutation flushed': {\n target: 'pushing to remote',\n actions: ['push to remote', 'defer then apply sync'],\n },\n 'remote value changed': {},\n },\n },\n },\n})\n\ninterface SDKValuePluginProps extends DocumentHandle {\n path: string\n}\n\n/**\n * The shape of the `remote-patches` document event emitted by\n * `@sanity/sdk` >= 2.17. Declared structurally so the plugin stays\n * compatible with older SDK typings until its dependency is bumped.\n */\ntype RemotePatchesDocumentEvent = {\n type: 'remote-patches'\n documentId: string\n transactionId: string\n timestamp: string\n previousRev?: string\n patches: SanityPatchOperations[]\n origin: 'local' | 'remote'\n}\n\nfunction isRemotePatchesEvent(event: {\n type: string\n}): event is RemotePatchesDocumentEvent {\n return event.type === 'remote-patches'\n}\n\nfunction getPublishedDocumentId(id: string): string {\n if (id.startsWith('drafts.')) {\n return id.slice('drafts.'.length)\n }\n if (id.startsWith('versions.')) {\n return id.split('.').slice(2).join('.')\n }\n return id\n}\n\n/**\n * @public\n */\nexport function SDKValuePlugin(props: SDKValuePluginProps) {\n const {documentId, documentType, path} = props\n const setSdkValue = useEditDocument(props)\n const instance = useSanityInstance(props)\n const applyActions = useApplyDocumentActions()\n\n const handle = {documentId, documentType, path}\n const {getCurrent, subscribe} = getDocumentState<PortableTextBlock[]>(\n instance,\n handle,\n )\n\n const onRemotePatches = useCallback(\n (callback: (patches: PtePatch[]) => void) => {\n return subscribeDocumentEvents(instance, {\n eventHandler: (event) => {\n // widen before narrowing: `remote-patches` is not part of the\n // `DocumentEvent` union in older SDK typings\n const candidate: {type: string} = event\n if (!isRemotePatchesEvent(candidate)) {\n return\n }\n // our own transactions are already reflected in the editor\n if (candidate.origin !== 'remote') {\n return\n }\n if (\n getPublishedDocumentId(candidate.documentId) !==\n getPublishedDocumentId(documentId)\n ) {\n return\n }\n\n let patches: PtePatch[] | null\n try {\n patches = scopeRemotePatches(candidate.patches, path)\n } catch {\n // unconvertible patch shapes fall back to the whole-value sync\n // driven by `onRemoteValueChange`\n return\n }\n if (patches && patches.length > 0) {\n callback(patches)\n }\n },\n })\n },\n [instance, documentId, path],\n )\n\n const pushPatches = useCallback(\n (patches: PtePatch[]) => {\n const sanityPatches = convertPatchesToSanity(patches, {prefix: path})\n // `preserveOperations` ships in @sanity/sdk >= 2.17; the intersection\n // type keeps the plugin compatible with older SDK typings\n const action: EditDocumentAction & {preserveOperations?: boolean} = {\n ...editDocument(\n {documentId, documentType},\n sanityPatches as Parameters<typeof editDocument>[1],\n ),\n preserveOperations: true,\n }\n applyActions(action)\n },\n [applyActions, documentId, documentType, path],\n )\n\n return (\n <ValueSyncPlugin\n getRemoteValue={getCurrent}\n pushValue={setSdkValue}\n onRemoteValueChange={subscribe}\n onRemotePatches={onRemotePatches}\n pushPatches={pushPatches}\n />\n )\n}\n\n/**\n * @internal\n */\ntype ValueSyncConfig = {\n getRemoteValue: () => PortableTextBlock[] | null | undefined\n pushValue: (value: PortableTextBlock[]) => void\n onRemoteValueChange: (callback: () => void) => () => void\n /**\n * Optional patch channel. When provided, operational patches from other\n * clients are applied directly to the editor (in every state) instead of\n * waiting for a whole-value diff, and local editor patches are pushed\n * through `pushPatches`. The whole-value sync remains as a fallback for\n * anything the patch channel cannot express.\n */\n onRemotePatches?: (\n callback: (patches: PtePatch[]) => void,\n ) => (() => void) | undefined\n /**\n * Pushes the editor's own operational patches to the remote store. May\n * throw when a patch cannot be converted, in which case the plugin falls\n * back to pushing the whole value.\n */\n pushPatches?: (patches: PtePatch[]) => void\n}\n\n/**\n * NOTE: You are probably looking for SDKValuePlugin instead of this.\n * This is a lower-level plugin that only handles syncing the value\n * between the editor and a remote source. It does not know anything\n * about Sanity documents or how to fetch/update them.\n *\n * May be removed in the future, do not rely on this directly.\n *\n * @internal\n */\nexport function ValueSyncPlugin(props: ValueSyncConfig) {\n const {\n getRemoteValue,\n pushValue,\n onRemoteValueChange,\n onRemotePatches,\n pushPatches,\n } = props\n const editor = useEditor()\n\n useActorRef(\n valueSyncMachine.provide({\n actions: {\n 'push to remote': ({context, event}) => {\n if (event.type !== 'mutation flushed') {\n return\n }\n\n if (pushPatches && event.patches.length > 0) {\n try {\n pushPatches(event.patches)\n return\n } catch {\n // fall back to pushing the whole value below\n }\n }\n\n pushValue(event.value ?? context.editor.getSnapshot().context.value)\n },\n },\n }),\n {\n input: {\n editor,\n getRemoteValue,\n onRemoteValueChange,\n onRemotePatches,\n },\n },\n )\n\n return null\n}\n"],"names":["getSegments","node","base","segment","type","isKeyPath","recursive","name","arrayifyPath","pathExpr","parsePath","path","push","elements","length","element","value","operator","keyPathNode","left","right","find","other","_key","convertPatches","patches","incomplete","flatMap","operation","Object","entries","values","origin","Array","isArray","items","rest","position","keys","at","STRINGIFY_ERROR_MESSAGE","stringifyPatchPath","result","Error","prefixPathExpression","prefix","expression","startsWith","convertPatchesToSanity","options","map","patch","pathExpression","set","setIfMissing","diffMatchPatch","inc","dec","unset","insert","segmentsEqual","a","b","scopeRemotePatches","fieldPath","converted","scoped","overlap","Math","min","touchesField","index","slice","applySync","editor","getRemoteValue","remoteValue","snapshot","getSnapshot","context","diffValue","updateValueFromRemote","send","listenToEditor","fromCallback","sendBack","input","patchSubscription","on","mutationSubscription","event","unsubscribe","listenToRemote","onRemoteValueChange","listenToRemotePatches","onRemotePatches","valueSyncMachine","setup","types","events","actions","send initial value","push to remote","apply sync","defer then apply sync","queueMicrotask","apply remote patches","actors","createMachine","id","entry","invoke","src","initial","states","target","isRemotePatchesEvent","getPublishedDocumentId","split","join","SDKValuePlugin","props","$","_c","documentId","documentType","setSdkValue","useEditDocument","instance","useSanityInstance","applyActions","useApplyDocumentActions","t0","getDocumentState","getCurrent","subscribe","t1","callback","subscribeDocumentEvents","eventHandler","candidate","t2","patches_0","sanityPatches","action","editDocument","preserveOperations","pushPatches","t3","ValueSyncPlugin","pushValue","useEditor","provide","useActorRef"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/plugin-sdk-value",
3
- "version": "7.0.34",
3
+ "version": "7.0.36-crx.0",
4
4
  "description": "Connect a Portable Text Editor with a Sanity document using the SDK",
5
5
  "keywords": [
6
6
  "@sanity/sdk",
@@ -58,7 +58,7 @@
58
58
  "typescript-eslint": "^8.62.0",
59
59
  "vitest": "^4.1.10",
60
60
  "vitest-browser-react": "^2.2.0",
61
- "@portabletext/editor": "^7.10.7",
61
+ "@portabletext/editor": "^7.10.8-crx.0",
62
62
  "@portabletext/patches": "^2.0.5",
63
63
  "@portabletext/schema": "^2.2.3",
64
64
  "@portabletext/test": "^1.0.4"
@@ -67,7 +67,7 @@
67
67
  "@sanity/sdk-react": "^2.1.2",
68
68
  "react": "^19.2",
69
69
  "react-dom": "^19.2",
70
- "@portabletext/editor": "^7.10.7"
70
+ "@portabletext/editor": "^7.10.8-crx.0"
71
71
  },
72
72
  "engines": {
73
73
  "node": ">=20.19 <22 || >=22.12"