@portabletext/editor 1.44.6 → 1.44.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.44.6",
3
+ "version": "1.44.8",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -131,7 +131,7 @@
131
131
  "check:lint": "biome lint .",
132
132
  "check:types": "tsc",
133
133
  "check:types:watch": "tsc --watch",
134
- "check:react-compiler": "eslint --cache --no-inline-config --no-eslintrc --ignore-pattern '**/__tests__/**' --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-compiler --plugin react-hooks --rule 'react-compiler/react-compiler: [warn,{__unstable_donotuse_reportAllBailouts: true}]' --rule 'react-hooks/rules-of-hooks: [error]' --rule 'react-hooks/exhaustive-deps: [error]' src",
134
+ "check:react-compiler": "eslint --cache --no-inline-config --no-eslintrc --ignore-pattern '**/__tests__/**' --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-compiler --plugin react-hooks --rule 'react-compiler/react-compiler: [warn]' --rule 'react-hooks/rules-of-hooks: [error]' --rule 'react-hooks/exhaustive-deps: [error]' src",
135
135
  "clean": "del .turbo && del lib && del node_modules",
136
136
  "dev": "pkg-utils watch",
137
137
  "lint:fix": "biome lint --write .",
@@ -181,6 +181,7 @@ export const PortableTextEditable = forwardRef<
181
181
  rangeDecorations: rangeDecorations ?? [],
182
182
  },
183
183
  })
184
+ useSelector(rangeDecorationsActor, (s) => s.context.updateCount)
184
185
  const decorate = useMemo(
185
186
  () => createDecorate(rangeDecorationsActor),
186
187
  [rangeDecorationsActor],
@@ -120,7 +120,7 @@ describe('RangeDecorations', () => {
120
120
  )
121
121
  await waitFor(() => {
122
122
  expect([rangeDecorationIteration, 'updated-with-different']).toEqual([
123
- 1,
123
+ 3,
124
124
  'updated-with-different',
125
125
  ])
126
126
  })
@@ -146,7 +146,7 @@ describe('RangeDecorations', () => {
146
146
  )
147
147
  await waitFor(() => {
148
148
  expect([rangeDecorationIteration, 'updated-with-different']).toEqual([
149
- 2,
149
+ 4,
150
150
  'updated-with-different',
151
151
  ])
152
152
  })
@@ -1,5 +1,6 @@
1
1
  import {isEqual} from 'lodash'
2
2
  import {
3
+ Element,
3
4
  Path,
4
5
  Range,
5
6
  type BaseRange,
@@ -52,6 +53,7 @@ export const rangeDecorationsMachine = setup({
52
53
  readOnly: boolean
53
54
  schema: EditorSchema
54
55
  slateEditor: PortableTextSlateEditor
56
+ updateCount: number
55
57
  },
56
58
  input: {} as {
57
59
  rangeDecorations: Array<RangeDecoration>
@@ -192,7 +194,14 @@ export const rangeDecorationsMachine = setup({
192
194
  if (newRange !== null) {
193
195
  rangeDecorationState.push({
194
196
  ...(newRange || slateRange),
195
- rangeDecoration: decoratedRange.rangeDecoration,
197
+ rangeDecoration: {
198
+ ...decoratedRange.rangeDecoration,
199
+ selection: slateRangeToSelection({
200
+ schema: context.schema,
201
+ editor: context.slateEditor,
202
+ range: newRange,
203
+ }),
204
+ },
196
205
  })
197
206
  }
198
207
  }
@@ -206,16 +215,39 @@ export const rangeDecorationsMachine = setup({
206
215
  return event.readOnly
207
216
  },
208
217
  }),
218
+ 'increment update count': assign({
219
+ updateCount: ({context}) => {
220
+ return context.updateCount + 1
221
+ },
222
+ }),
209
223
  },
210
224
  actors: {
211
225
  'slate operation listener': fromCallback(slateOperationCallback),
212
226
  },
213
227
  guards: {
228
+ 'has pending range decorations': ({context}) =>
229
+ context.pendingRangeDecorations.length > 0,
214
230
  'has range decorations': ({context}) => context.decoratedRanges.length > 0,
215
231
  'has different decorations': ({context, event}) => {
216
232
  assertEvent(event, 'range decorations updated')
217
233
 
218
- return !isEqual(context.pendingRangeDecorations, event.rangeDecorations)
234
+ const existingRangeDecorations = context.decoratedRanges.map(
235
+ (decoratedRange) => ({
236
+ anchor: decoratedRange.rangeDecoration.selection?.anchor,
237
+ focus: decoratedRange.rangeDecoration.selection?.focus,
238
+ }),
239
+ )
240
+
241
+ const newRangeDecorations = event.rangeDecorations.map(
242
+ (rangeDecoration) => ({
243
+ anchor: rangeDecoration.selection?.anchor,
244
+ focus: rangeDecoration.selection?.focus,
245
+ }),
246
+ )
247
+
248
+ const different = !isEqual(existingRangeDecorations, newRangeDecorations)
249
+
250
+ return different
219
251
  },
220
252
  'not read only': ({context}) => !context.readOnly,
221
253
  },
@@ -227,6 +259,7 @@ export const rangeDecorationsMachine = setup({
227
259
  decoratedRanges: [],
228
260
  schema: input.schema,
229
261
  slateEditor: input.slateEditor,
262
+ updateCount: 0,
230
263
  }),
231
264
  invoke: {
232
265
  src: 'slate operation listener',
@@ -244,10 +277,19 @@ export const rangeDecorationsMachine = setup({
244
277
  'range decorations updated': {
245
278
  actions: ['update pending range decorations'],
246
279
  },
247
- 'ready': {
248
- target: 'ready',
249
- actions: ['set up initial range decorations'],
250
- },
280
+ 'ready': [
281
+ {
282
+ target: 'ready',
283
+ guard: 'has pending range decorations',
284
+ actions: [
285
+ 'set up initial range decorations',
286
+ 'increment update count',
287
+ ],
288
+ },
289
+ {
290
+ target: 'ready',
291
+ },
292
+ ],
251
293
  },
252
294
  },
253
295
  ready: {
@@ -256,10 +298,7 @@ export const rangeDecorationsMachine = setup({
256
298
  'range decorations updated': {
257
299
  target: '.idle',
258
300
  guard: 'has different decorations',
259
- actions: [
260
- 'update range decorations',
261
- 'update pending range decorations',
262
- ],
301
+ actions: ['update range decorations', 'increment update count'],
263
302
  },
264
303
  },
265
304
  states: {
@@ -285,7 +324,7 @@ export const rangeDecorationsMachine = setup({
285
324
  export function createDecorate(
286
325
  rangeDecorationActor: ActorRefFrom<typeof rangeDecorationsMachine>,
287
326
  ) {
288
- return function decorate([, path]: NodeEntry): Array<BaseRange> {
327
+ return function decorate([node, path]: NodeEntry): Array<BaseRange> {
289
328
  if (
290
329
  isEqualToEmptyEditor(
291
330
  rangeDecorationActor.getSnapshot().context.slateEditor.children,
@@ -312,35 +351,38 @@ export function createDecorate(
312
351
  return []
313
352
  }
314
353
 
315
- const result = rangeDecorationActor
354
+ if (!Element.isElement(node) || node.children.length === 0) {
355
+ return []
356
+ }
357
+
358
+ const blockIndex = path.at(0)
359
+
360
+ if (blockIndex === undefined) {
361
+ return []
362
+ }
363
+
364
+ return rangeDecorationActor
316
365
  .getSnapshot()
317
- .context.decoratedRanges.filter((item) => {
366
+ .context.decoratedRanges.filter((decoratedRange) => {
318
367
  // Special case in order to only return one decoration for collapsed ranges
319
- if (Range.isCollapsed(item)) {
368
+ if (Range.isCollapsed(decoratedRange)) {
320
369
  // Collapsed ranges should only be decorated if they are on a block child level (length 2)
321
- if (path.length !== 2) {
322
- return false
323
- }
324
-
325
- return (
326
- Path.equals(item.focus.path, path) &&
327
- Path.equals(item.anchor.path, path)
370
+ return node.children.some(
371
+ (_, childIndex) =>
372
+ Path.equals(decoratedRange.anchor.path, [
373
+ blockIndex,
374
+ childIndex,
375
+ ]) &&
376
+ Path.equals(decoratedRange.focus.path, [blockIndex, childIndex]),
328
377
  )
329
378
  }
330
379
 
331
- // Include decorations that either include or intersects with this path
332
380
  return (
333
- Range.intersection(item, {
381
+ Range.intersection(decoratedRange, {
334
382
  anchor: {path, offset: 0},
335
383
  focus: {path, offset: 0},
336
- }) || Range.includes(item, path)
384
+ }) || Range.includes(decoratedRange, path)
337
385
  )
338
386
  })
339
-
340
- if (result.length > 0) {
341
- return result
342
- }
343
-
344
- return []
345
387
  }
346
388
  }