@preprio/toolkit 0.5.0-rc.10 → 0.5.0-rc.12

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.
Files changed (34) hide show
  1. package/README.md +21 -0
  2. package/dist/astro/index.cjs +31 -2
  3. package/dist/astro/index.js +31 -2
  4. package/dist/{chunk-KD3GK6TO.js → chunk-CABGJW5X.js} +30 -1
  5. package/dist/{chunk-URXSDJOU.js → chunk-H3AFUPYD.js} +9 -0
  6. package/dist/{chunk-F46GJS6Y.js → chunk-HVTNUCF7.js} +1 -1
  7. package/dist/{chunk-IPMB32AZ.js → chunk-LWUSRWFE.js} +2 -2
  8. package/dist/{chunk-IDEC77LZ.js → chunk-M7FT7XXV.js} +93 -20
  9. package/dist/{chunk-TBBU3LDD.js → chunk-TJ7VALNA.js} +1 -1
  10. package/dist/index.cjs +131 -20
  11. package/dist/index.d.cts +6 -1
  12. package/dist/index.d.ts +6 -1
  13. package/dist/index.js +6 -6
  14. package/dist/{live-preview-DLXGXRE5.js → live-preview-SFBGATWC.js} +3 -3
  15. package/dist/nextjs/components.cjs +101 -19
  16. package/dist/nextjs/components.js +3 -3
  17. package/dist/nextjs/index.cjs +31 -2
  18. package/dist/nextjs/index.js +31 -2
  19. package/dist/nextjs/live-action.js +3 -3
  20. package/dist/nextjs/live.cjs +30 -1
  21. package/dist/nextjs/live.js +1 -1
  22. package/dist/nuxt/index.cjs +1 -1
  23. package/dist/nuxt/index.js +1 -1
  24. package/dist/nuxt/{live-preview-2RCU35W5.js → live-preview-XMQQZHMZ.js} +30 -1
  25. package/dist/nuxt/live.cjs +30 -1
  26. package/dist/nuxt/live.js +1 -1
  27. package/dist/react/components.cjs +101 -19
  28. package/dist/react/components.js +101 -19
  29. package/dist/sveltekit/index.cjs +1 -1
  30. package/dist/sveltekit/index.js +1 -1
  31. package/dist/sveltekit/{live-preview-2RCU35W5.js → live-preview-XMQQZHMZ.js} +30 -1
  32. package/dist/sveltekit/live.cjs +30 -1
  33. package/dist/sveltekit/live.js +1 -1
  34. package/package.json +1 -1
@@ -396,6 +396,7 @@ function createIframeBridge(store, options = {}) {
396
396
  const onReferences = options.onReferences;
397
397
  const onAssets = options.onAssets;
398
398
  const onAllowNavigation = options.onAllowNavigation;
399
+ const onItemChanged = options.onItemChanged;
399
400
  let parentOrigin = null;
400
401
  const onKeyDown = (event) => {
401
402
  const key = event.key.toLowerCase();
@@ -486,6 +487,14 @@ function createIframeBridge(store, options = {}) {
486
487
  debug.warn("allowNavigation handler failed", error);
487
488
  }
488
489
  }
490
+ if (data?.event === "prepr:itemChanged") {
491
+ if (typeof data.itemId !== "string" || !data.itemId) return;
492
+ try {
493
+ onItemChanged?.(data.itemId);
494
+ } catch (error) {
495
+ debug.warn("itemChanged handler failed", error);
496
+ }
497
+ }
489
498
  };
490
499
  return {
491
500
  start() {
@@ -2629,6 +2638,7 @@ var ABSOLUTE_HTTP = /^https?:\/\//i;
2629
2638
  var SOURCE_URL_ATTRIBUTES = ["src", "data-src"];
2630
2639
  var SOURCE_SET_ATTRIBUTES = ["srcset", "data-srcset"];
2631
2640
  var ASSET_ATTR = "data-prepr-asset";
2641
+ var REMOVED_ATTR = "data-prepr-removed";
2632
2642
  var ASSET_SOURCE_ATTRIBUTES = [
2633
2643
  ...SOURCE_URL_ATTRIBUTES,
2634
2644
  ...SOURCE_SET_ATTRIBUTES
@@ -2638,7 +2648,8 @@ var TAG_ATTRIBUTES = [
2638
2648
  "data-prepr-id",
2639
2649
  "data-prepr-field",
2640
2650
  "data-prepr-entry-id",
2641
- ASSET_ATTR
2651
+ ASSET_ATTR,
2652
+ REMOVED_ATTR
2642
2653
  ];
2643
2654
  function decodeSegment(segment) {
2644
2655
  try {
@@ -2757,11 +2768,22 @@ function besideOtherItem(img, isCurrentItem) {
2757
2768
  return false;
2758
2769
  }
2759
2770
  function tagAssetImages(index, itemId, keys, options = {}) {
2760
- const { isCurrentItem } = options;
2771
+ const { isCurrentItem, removed } = options;
2772
+ let showsRemoved = false;
2761
2773
  for (const img of document.getElementsByTagName("img")) {
2762
2774
  const ours = img.hasAttribute(ASSET_ATTR);
2763
- if (!ours && img.hasAttribute("data-prepr-encoded")) continue;
2764
- const match = index.size ? matchAsset(img, index, keys) : void 0;
2775
+ let match = index.size ? matchAsset(img, index, keys) : void 0;
2776
+ let isRemoved = false;
2777
+ if (!match && removed?.size) {
2778
+ match = matchAsset(img, removed, keys);
2779
+ isRemoved = match !== void 0;
2780
+ }
2781
+ if (!ours && img.hasAttribute("data-prepr-encoded")) {
2782
+ const mark = isRemoved && (!isCurrentItem || isCurrentItem(img));
2783
+ setIfChanged(img, REMOVED_ATTR, mark ? "" : null);
2784
+ showsRemoved || (showsRemoved = mark);
2785
+ continue;
2786
+ }
2765
2787
  const asset = match && isCurrentItem && besideOtherItem(img, isCurrentItem) ? void 0 : match;
2766
2788
  if (!asset) {
2767
2789
  if (ours) untagAssetImage(img);
@@ -2772,10 +2794,14 @@ function tagAssetImages(index, itemId, keys, options = {}) {
2772
2794
  setIfChanged(img, "data-prepr-id", itemId);
2773
2795
  setIfChanged(img, "data-prepr-field", asset.field);
2774
2796
  setIfChanged(img, "data-prepr-entry-id", asset.entryId ?? null);
2797
+ setIfChanged(img, REMOVED_ATTR, isRemoved ? "" : null);
2798
+ showsRemoved || (showsRemoved = isRemoved);
2775
2799
  }
2800
+ return showsRemoved;
2776
2801
  }
2777
2802
  function untagAssetImages() {
2778
2803
  document.querySelectorAll(`img[${ASSET_ATTR}]`).forEach(untagAssetImage);
2804
+ document.querySelectorAll(`img[${REMOVED_ATTR}]`).forEach((img) => img.removeAttribute(REMOVED_ATTR));
2779
2805
  }
2780
2806
 
2781
2807
  // src/core/visual-editor/navigation-guard.ts
@@ -2945,12 +2971,19 @@ var debug8 = createScopedLogger("visual-editor");
2945
2971
  var ENCODED_SELECTOR2 = "[data-prepr-encoded]";
2946
2972
  var REFERENCE_ATTR = "data-prepr-reference";
2947
2973
  var REFERENCE_SELECTOR = `[${REFERENCE_ATTR}]`;
2974
+ var OTHER_ITEM_ATTR = "data-prepr-other-item";
2975
+ var OTHER_ITEM_SELECTOR = `[${OTHER_ITEM_ATTR}="on"],[${OTHER_ITEM_ATTR}="off"]`;
2976
+ var CHROME_SELECTOR = "header, footer, nav, [role=banner], [role=contentinfo], [role=navigation]";
2977
+ var SECTIONING_SELECTOR = "article, aside, main, nav, section";
2978
+ var PLAIN_HEADER_FOOTER = "header:not([role]), footer:not([role])";
2948
2979
  var CURSOR_STYLE_MARKER = "data-prepr-visual-editor";
2949
- var CURSOR_STYLES = `${ENCODED_SELECTOR2}{cursor:pointer}html[data-prepr-ve-suspended] ${ENCODED_SELECTOR2}{cursor:auto}`;
2980
+ var REMOVED_STYLES = `img[${REMOVED_ATTR}]{opacity:.2!important;transition:opacity .2s ease}@media (prefers-reduced-motion:reduce){img[${REMOVED_ATTR}]{transition:none}}`;
2981
+ var CURSOR_STYLES = `${ENCODED_SELECTOR2}{cursor:pointer}html[data-prepr-ve-suspended] ${ENCODED_SELECTOR2}{cursor:auto}${REMOVED_STYLES}`;
2950
2982
  var SUSPENDED_ATTR = "data-prepr-ve-suspended";
2951
2983
  var FIND_RETRY_MS = 150;
2952
2984
  var FIND_RETRIES = 6;
2953
2985
  var MAX_CACHED_KEYS = 2e3;
2986
+ var SAVED_FADE_MS = 1e4;
2954
2987
  var LAYOUT_MUTATIONS = {
2955
2988
  childList: true,
2956
2989
  subtree: true,
@@ -2993,6 +3026,9 @@ function createVisualEditor(opts) {
2993
3026
  let guardEnabled = false;
2994
3027
  let assetIndex = /* @__PURE__ */ new Map();
2995
3028
  const assetKeys = /* @__PURE__ */ new Map();
3029
+ const removedAssets = /* @__PURE__ */ new Map();
3030
+ let saved = false;
3031
+ let savedTimeout = null;
2996
3032
  const guard = createNavigationGuard({
2997
3033
  onBlocked: (href) => opts.onNavigationBlocked?.(href),
2998
3034
  showsEditedContent: () => showsEditedContent()
@@ -3024,10 +3060,26 @@ function createVisualEditor(opts) {
3024
3060
  }
3025
3061
  return null;
3026
3062
  };
3063
+ const inSiteChrome = (el) => {
3064
+ let chrome = el.closest(CHROME_SELECTOR);
3065
+ while (chrome) {
3066
+ if (!chrome.matches(PLAIN_HEADER_FOOTER) || !chrome.parentElement?.closest(SECTIONING_SELECTOR)) {
3067
+ return true;
3068
+ }
3069
+ chrome = chrome.parentElement?.closest(CHROME_SELECTOR) ?? null;
3070
+ }
3071
+ return false;
3072
+ };
3073
+ const showsOtherItem = (el) => {
3074
+ const choice = el.closest(OTHER_ITEM_SELECTOR);
3075
+ if (choice) return choice.getAttribute(OTHER_ITEM_ATTR) === "on";
3076
+ return !inSiteChrome(el);
3077
+ };
3027
3078
  const itemKind = (el) => {
3028
3079
  if (isCurrentItem(el)) return "current";
3029
3080
  if (!references) return "other";
3030
- return linkedIdOf(el) ? "referenced" : null;
3081
+ if (linkedIdOf(el)) return "referenced";
3082
+ return showsOtherItem(el) ? "other" : null;
3031
3083
  };
3032
3084
  const referenceFieldOf = (el) => {
3033
3085
  const linked = linkedIdOf(el);
@@ -3100,6 +3152,7 @@ function createVisualEditor(opts) {
3100
3152
  }
3101
3153
  return;
3102
3154
  }
3155
+ if (kind === "other" && (e2.ctrlKey || e2.metaKey || e2.shiftKey)) return;
3103
3156
  e2.preventDefault();
3104
3157
  e2.stopPropagation();
3105
3158
  const item = listItemIn(encoded, e2.target);
@@ -3107,11 +3160,13 @@ function createVisualEditor(opts) {
3107
3160
  select(item?.element ?? encoded, encoded, item?.index);
3108
3161
  const referenceField = kind === "referenced" ? referenceFieldOf(encoded) : void 0;
3109
3162
  const linkedId = kind === "referenced" ? linkedIdOf(encoded) : null;
3163
+ const linkHref = kind === "other" ? leavingLinkHref(e2.target) : null;
3110
3164
  opts.onEdit({
3111
3165
  ...readEditPayload(encoded),
3112
3166
  ...linkedId && { id: linkedId },
3113
3167
  ...item && { block: item.index },
3114
- ...referenceField && { referenceField }
3168
+ ...referenceField && { referenceField },
3169
+ ...linkHref && { linkHref }
3115
3170
  });
3116
3171
  };
3117
3172
  const handleKey = (e2) => {
@@ -3172,15 +3227,32 @@ function createVisualEditor(opts) {
3172
3227
  const el = block !== void 0 ? nthListItem(found, block) ?? found : found;
3173
3228
  select(el, found, block);
3174
3229
  }
3230
+ const hasAssets = () => assetIndex.size > 0 || removedAssets.size > 0;
3175
3231
  function tagAssets() {
3176
3232
  if (assetKeys.size > MAX_CACHED_KEYS) assetKeys.clear();
3177
- tagAssetImages(assetIndex, currentItemId, assetKeys, {
3178
- isCurrentItem: (el) => isCurrentItem(el)
3233
+ const showsRemoved = tagAssetImages(assetIndex, currentItemId, assetKeys, {
3234
+ isCurrentItem: (el) => isCurrentItem(el),
3235
+ removed: removedAssets
3179
3236
  });
3237
+ if (saved && !showsRemoved) forgetRemoved();
3238
+ }
3239
+ function forgetRemoved() {
3240
+ saved = false;
3241
+ if (savedTimeout) clearTimeout(savedTimeout);
3242
+ savedTimeout = null;
3243
+ if (!removedAssets.size) return;
3244
+ removedAssets.clear();
3245
+ if (running) tagAssets();
3246
+ }
3247
+ function itemSaved() {
3248
+ if (!removedAssets.size) return;
3249
+ saved = true;
3250
+ if (savedTimeout) clearTimeout(savedTimeout);
3251
+ savedTimeout = setTimeout(forgetRemoved, SAVED_FADE_MS);
3180
3252
  }
3181
3253
  const handleLayoutFrame = () => {
3182
3254
  mutationFrame = null;
3183
- if (assetIndex.size) tagAssets();
3255
+ if (hasAssets()) tagAssets();
3184
3256
  reselect();
3185
3257
  const hovered = overlay.getHoverTarget();
3186
3258
  if (hovered && !hovered.isConnected) {
@@ -3192,7 +3264,7 @@ function createVisualEditor(opts) {
3192
3264
  };
3193
3265
  const handleMutations = () => {
3194
3266
  if (mutationFrame !== null) return;
3195
- if (!selection && !overlay.getHoverTarget() && !assetIndex.size) return;
3267
+ if (!selection && !overlay.getHoverTarget() && !hasAssets()) return;
3196
3268
  mutationFrame = requestAnimationFrame(handleLayoutFrame);
3197
3269
  };
3198
3270
  function injectCursorStyles() {
@@ -3233,7 +3305,7 @@ function createVisualEditor(opts) {
3233
3305
  });
3234
3306
  mutationObserver = new MutationObserver(handleMutations);
3235
3307
  mutationObserver.observe(document.body, LAYOUT_MUTATIONS);
3236
- if (assetIndex.size) tagAssets();
3308
+ if (hasAssets()) tagAssets();
3237
3309
  syncGuard();
3238
3310
  debug8.log("visual editor started");
3239
3311
  }
@@ -3309,18 +3381,24 @@ function createVisualEditor(opts) {
3309
3381
  });
3310
3382
  }
3311
3383
  function setCurrentItem(itemId, referenceList, componentIds) {
3384
+ if (itemId !== currentItemId) forgetRemoved();
3312
3385
  currentItemId = itemId;
3313
3386
  if (referenceList) setReferences(referenceList, componentIds);
3314
3387
  else if (componentIds) ownComponents = new Set(componentIds);
3315
- if (running && assetIndex.size) tagAssets();
3388
+ if (running && hasAssets()) tagAssets();
3316
3389
  const selected = overlay.getSelectedTarget();
3317
3390
  const owner = selected ? encodedFrom(selected) : null;
3318
3391
  if (owner && !isCurrentItem(owner)) clearSelection();
3319
3392
  }
3320
3393
  function setAssets(assets) {
3321
- const hadAssets = assetIndex.size > 0;
3322
- assetIndex = createAssetIndex(assets);
3323
- if (running && (hadAssets || assetIndex.size)) tagAssets();
3394
+ const hadAssets = hasAssets();
3395
+ const next = createAssetIndex(assets);
3396
+ for (const [key, asset] of assetIndex) {
3397
+ if (!next.has(key)) removedAssets.set(key, asset);
3398
+ }
3399
+ for (const key of next.keys()) removedAssets.delete(key);
3400
+ assetIndex = next;
3401
+ if (running && (hadAssets || hasAssets())) tagAssets();
3324
3402
  }
3325
3403
  function setReferences(referenceList, componentIds) {
3326
3404
  if (componentIds) ownComponents = new Set(componentIds);
@@ -3346,6 +3424,7 @@ function createVisualEditor(opts) {
3346
3424
  setCurrentItem,
3347
3425
  setReferences,
3348
3426
  setAssets,
3427
+ itemSaved,
3349
3428
  setLocale,
3350
3429
  focusField,
3351
3430
  setNavigationGuard,
@@ -3432,7 +3511,8 @@ function createPreprPreview(opts = {}) {
3432
3511
  locale: contentLocale,
3433
3512
  block,
3434
3513
  entryId,
3435
- referenceField
3514
+ referenceField,
3515
+ linkHref
3436
3516
  }) => {
3437
3517
  const safeHref = href ? safeEditUrl(href) : null;
3438
3518
  if (href && !safeHref) {
@@ -3446,7 +3526,8 @@ function createPreprPreview(opts = {}) {
3446
3526
  locale: contentLocale,
3447
3527
  ...block !== void 0 && { block },
3448
3528
  ...entryId && { entryId },
3449
- ...referenceField && { referenceField }
3529
+ ...referenceField && { referenceField },
3530
+ ...linkHref && { linkHref }
3450
3531
  });
3451
3532
  } else if (safeHref) {
3452
3533
  window.open(safeHref, "_blank", "noopener,noreferrer");
@@ -3501,6 +3582,7 @@ function createPreprPreview(opts = {}) {
3501
3582
  },
3502
3583
  onAssets: (assets) => visualEditor?.setAssets(assets),
3503
3584
  onAllowNavigation: (href) => visualEditor?.allowNavigation(href),
3585
+ onItemChanged: () => visualEditor?.itemSaved(),
3504
3586
  onReferences: (referencedIds, componentIds) => visualEditor?.setReferences(referencedIds, componentIds),
3505
3587
  // The editor selecting a field scrolls the matching element into view. The
3506
3588
  // lookup relies on the attributes the stega scan writes, so it finds
@@ -3544,7 +3626,7 @@ function createPreprPreview(opts = {}) {
3544
3626
  var import_react = require("react");
3545
3627
 
3546
3628
  // src/version.ts
3547
- var VERSION = "0.5.0-rc.10";
3629
+ var VERSION = "0.5.0-rc.12";
3548
3630
 
3549
3631
  // src/core/pixel.ts
3550
3632
  var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  createPreprPreview,
4
4
  loadTrackingPixel
5
- } from "../chunk-IDEC77LZ.js";
6
- import "../chunk-F46GJS6Y.js";
7
- import "../chunk-URXSDJOU.js";
5
+ } from "../chunk-M7FT7XXV.js";
6
+ import "../chunk-HVTNUCF7.js";
7
+ import "../chunk-H3AFUPYD.js";
8
8
  import "../chunk-S3VT4UWM.js";
9
9
 
10
10
  // src/nextjs/components.ts
@@ -49,7 +49,7 @@ module.exports = __toCommonJS(nextjs_exports);
49
49
  var import_server = require("next/server");
50
50
 
51
51
  // src/version.ts
52
- var VERSION = "0.5.0-rc.10";
52
+ var VERSION = "0.5.0-rc.12";
53
53
 
54
54
  // src/core/constants.ts
55
55
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -405,8 +405,32 @@ function shapeLike(template, incoming) {
405
405
  }
406
406
  return out;
407
407
  }
408
+ function isAsset(value) {
409
+ return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
410
+ }
411
+ function hasId(list, entry) {
412
+ return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
413
+ }
414
+ function isAssetValue(value) {
415
+ return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
416
+ }
417
+ function keepRemovedAssets(current, next) {
418
+ const listed = /* @__PURE__ */ new Set();
419
+ for (const entry of next) {
420
+ if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
421
+ }
422
+ let out = next;
423
+ current.forEach((entry, position) => {
424
+ if (!isPlainObject(entry) || entry._id === void 0) return;
425
+ if (listed.has(entry._id)) return;
426
+ if (out === next) out = [...next];
427
+ out.splice(Math.min(position, out.length), 0, entry);
428
+ });
429
+ return out;
430
+ }
408
431
  function mergeStructured(current, incoming) {
409
432
  if (incoming === null || Array.isArray(incoming) && !incoming.length) {
433
+ if (isAssetValue(current)) return current;
410
434
  if (Array.isArray(current)) return current.length ? [] : current;
411
435
  return null;
412
436
  }
@@ -414,13 +438,18 @@ function mergeStructured(current, incoming) {
414
438
  if (current === null || current === void 0) return incoming;
415
439
  if (Array.isArray(current)) {
416
440
  const template = current.find(isPlainObject);
417
- return list.map((entry) => {
441
+ const next = list.map((entry) => {
418
442
  const match = current.find(
419
443
  (c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
420
444
  );
421
445
  if (isPlainObject(match)) return mergeObject(match, entry);
422
446
  return isPlainObject(template) ? shapeLike(template, entry) : entry;
423
447
  });
448
+ if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
449
+ return next;
450
+ }
451
+ const kept = keepRemovedAssets(current, next);
452
+ return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
424
453
  }
425
454
  if (isPlainObject(current)) return mergeObject(current, list[0]);
426
455
  return current;
@@ -2,7 +2,7 @@
2
2
  import { NextResponse } from "next/server";
3
3
 
4
4
  // src/version.ts
5
- var VERSION = "0.5.0-rc.10";
5
+ var VERSION = "0.5.0-rc.12";
6
6
 
7
7
  // src/core/constants.ts
8
8
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -362,8 +362,32 @@ function shapeLike(template, incoming) {
362
362
  }
363
363
  return out;
364
364
  }
365
+ function isAsset(value) {
366
+ return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
367
+ }
368
+ function hasId(list, entry) {
369
+ return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
370
+ }
371
+ function isAssetValue(value) {
372
+ return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
373
+ }
374
+ function keepRemovedAssets(current, next) {
375
+ const listed = /* @__PURE__ */ new Set();
376
+ for (const entry of next) {
377
+ if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
378
+ }
379
+ let out = next;
380
+ current.forEach((entry, position) => {
381
+ if (!isPlainObject(entry) || entry._id === void 0) return;
382
+ if (listed.has(entry._id)) return;
383
+ if (out === next) out = [...next];
384
+ out.splice(Math.min(position, out.length), 0, entry);
385
+ });
386
+ return out;
387
+ }
365
388
  function mergeStructured(current, incoming) {
366
389
  if (incoming === null || Array.isArray(incoming) && !incoming.length) {
390
+ if (isAssetValue(current)) return current;
367
391
  if (Array.isArray(current)) return current.length ? [] : current;
368
392
  return null;
369
393
  }
@@ -371,13 +395,18 @@ function mergeStructured(current, incoming) {
371
395
  if (current === null || current === void 0) return incoming;
372
396
  if (Array.isArray(current)) {
373
397
  const template = current.find(isPlainObject);
374
- return list.map((entry) => {
398
+ const next = list.map((entry) => {
375
399
  const match = current.find(
376
400
  (c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
377
401
  );
378
402
  if (isPlainObject(match)) return mergeObject(match, entry);
379
403
  return isPlainObject(template) ? shapeLike(template, entry) : entry;
380
404
  });
405
+ if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
406
+ return next;
407
+ }
408
+ const kept = keepRemovedAssets(current, next);
409
+ return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
381
410
  }
382
411
  if (isPlainObject(current)) return mergeObject(current, list[0]);
383
412
  return current;
@@ -1,11 +1,11 @@
1
1
  "use server";
2
2
  import {
3
3
  isPreviewFromHeaders
4
- } from "../chunk-TBBU3LDD.js";
5
- import "../chunk-F46GJS6Y.js";
4
+ } from "../chunk-TJ7VALNA.js";
5
+ import "../chunk-HVTNUCF7.js";
6
6
  import {
7
7
  parsePatchLog
8
- } from "../chunk-KD3GK6TO.js";
8
+ } from "../chunk-CABGJW5X.js";
9
9
  import "../chunk-S3VT4UWM.js";
10
10
 
11
11
  // src/nextjs/live-action.ts
@@ -196,8 +196,32 @@ function shapeLike(template, incoming) {
196
196
  }
197
197
  return out;
198
198
  }
199
+ function isAsset(value) {
200
+ return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
201
+ }
202
+ function hasId(list, entry) {
203
+ return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
204
+ }
205
+ function isAssetValue(value) {
206
+ return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
207
+ }
208
+ function keepRemovedAssets(current, next) {
209
+ const listed = /* @__PURE__ */ new Set();
210
+ for (const entry of next) {
211
+ if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
212
+ }
213
+ let out = next;
214
+ current.forEach((entry, position) => {
215
+ if (!isPlainObject(entry) || entry._id === void 0) return;
216
+ if (listed.has(entry._id)) return;
217
+ if (out === next) out = [...next];
218
+ out.splice(Math.min(position, out.length), 0, entry);
219
+ });
220
+ return out;
221
+ }
199
222
  function mergeStructured(current, incoming) {
200
223
  if (incoming === null || Array.isArray(incoming) && !incoming.length) {
224
+ if (isAssetValue(current)) return current;
201
225
  if (Array.isArray(current)) return current.length ? [] : current;
202
226
  return null;
203
227
  }
@@ -205,13 +229,18 @@ function mergeStructured(current, incoming) {
205
229
  if (current === null || current === void 0) return incoming;
206
230
  if (Array.isArray(current)) {
207
231
  const template = current.find(isPlainObject);
208
- return list.map((entry) => {
232
+ const next = list.map((entry) => {
209
233
  const match = current.find(
210
234
  (c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
211
235
  );
212
236
  if (isPlainObject(match)) return mergeObject(match, entry);
213
237
  return isPlainObject(template) ? shapeLike(template, entry) : entry;
214
238
  });
239
+ if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
240
+ return next;
241
+ }
242
+ const kept = keepRemovedAssets(current, next);
243
+ return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
215
244
  }
216
245
  if (isPlainObject(current)) return mergeObject(current, list[0]);
217
246
  return current;
@@ -27,7 +27,7 @@ function isFramed() {
27
27
  return typeof window !== "undefined" && window.self !== window.top;
28
28
  }
29
29
  function startLive() {
30
- starting ?? (starting = import("../live-preview-DLXGXRE5.js").then(
30
+ starting ?? (starting = import("../live-preview-SFBGATWC.js").then(
31
31
  ({ createLiveBridge, createLiveStore }) => {
32
32
  const skipped = new Set(quarantined());
33
33
  const started = createLiveStore({
@@ -35,7 +35,7 @@ __export(nuxt_exports, {
35
35
  module.exports = __toCommonJS(nuxt_exports);
36
36
 
37
37
  // src/version.ts
38
- var VERSION = "0.5.0-rc.10";
38
+ var VERSION = "0.5.0-rc.12";
39
39
 
40
40
  // src/core/constants.ts
41
41
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.5.0-rc.10";
2
+ var VERSION = "0.5.0-rc.12";
3
3
 
4
4
  // src/core/constants.ts
5
5
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -160,8 +160,32 @@ function shapeLike(template, incoming) {
160
160
  }
161
161
  return out;
162
162
  }
163
+ function isAsset(value) {
164
+ return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
165
+ }
166
+ function hasId(list, entry) {
167
+ return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
168
+ }
169
+ function isAssetValue(value) {
170
+ return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
171
+ }
172
+ function keepRemovedAssets(current, next) {
173
+ const listed = /* @__PURE__ */ new Set();
174
+ for (const entry of next) {
175
+ if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
176
+ }
177
+ let out = next;
178
+ current.forEach((entry, position) => {
179
+ if (!isPlainObject(entry) || entry._id === void 0) return;
180
+ if (listed.has(entry._id)) return;
181
+ if (out === next) out = [...next];
182
+ out.splice(Math.min(position, out.length), 0, entry);
183
+ });
184
+ return out;
185
+ }
163
186
  function mergeStructured(current, incoming) {
164
187
  if (incoming === null || Array.isArray(incoming) && !incoming.length) {
188
+ if (isAssetValue(current)) return current;
165
189
  if (Array.isArray(current)) return current.length ? [] : current;
166
190
  return null;
167
191
  }
@@ -169,13 +193,18 @@ function mergeStructured(current, incoming) {
169
193
  if (current === null || current === void 0) return incoming;
170
194
  if (Array.isArray(current)) {
171
195
  const template = current.find(isPlainObject);
172
- return list.map((entry) => {
196
+ const next = list.map((entry) => {
173
197
  const match = current.find(
174
198
  (c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
175
199
  );
176
200
  if (isPlainObject(match)) return mergeObject(match, entry);
177
201
  return isPlainObject(template) ? shapeLike(template, entry) : entry;
178
202
  });
203
+ if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
204
+ return next;
205
+ }
206
+ const kept = keepRemovedAssets(current, next);
207
+ return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
179
208
  }
180
209
  if (isPlainObject(current)) return mergeObject(current, list[0]);
181
210
  return current;
@@ -536,8 +536,32 @@ function shapeLike(template, incoming) {
536
536
  }
537
537
  return out;
538
538
  }
539
+ function isAsset(value) {
540
+ return isPlainObject(value) && (typeof value.url === "string" || value.__typename === "Asset");
541
+ }
542
+ function hasId(list, entry) {
543
+ return entry._id !== void 0 && list.some((c) => isPlainObject(c) && c._id === entry._id);
544
+ }
545
+ function isAssetValue(value) {
546
+ return Array.isArray(value) ? value.length > 0 && value.every(isAsset) : isAsset(value);
547
+ }
548
+ function keepRemovedAssets(current, next) {
549
+ const listed = /* @__PURE__ */ new Set();
550
+ for (const entry of next) {
551
+ if (isPlainObject(entry) && entry._id !== void 0) listed.add(entry._id);
552
+ }
553
+ let out = next;
554
+ current.forEach((entry, position) => {
555
+ if (!isPlainObject(entry) || entry._id === void 0) return;
556
+ if (listed.has(entry._id)) return;
557
+ if (out === next) out = [...next];
558
+ out.splice(Math.min(position, out.length), 0, entry);
559
+ });
560
+ return out;
561
+ }
539
562
  function mergeStructured(current, incoming) {
540
563
  if (incoming === null || Array.isArray(incoming) && !incoming.length) {
564
+ if (isAssetValue(current)) return current;
541
565
  if (Array.isArray(current)) return current.length ? [] : current;
542
566
  return null;
543
567
  }
@@ -545,13 +569,18 @@ function mergeStructured(current, incoming) {
545
569
  if (current === null || current === void 0) return incoming;
546
570
  if (Array.isArray(current)) {
547
571
  const template = current.find(isPlainObject);
548
- return list.map((entry) => {
572
+ const next = list.map((entry) => {
549
573
  const match = current.find(
550
574
  (c) => isPlainObject(c) && c._id !== void 0 && c._id === entry._id
551
575
  );
552
576
  if (isPlainObject(match)) return mergeObject(match, entry);
553
577
  return isPlainObject(template) ? shapeLike(template, entry) : entry;
554
578
  });
579
+ if (!isAssetValue(current) || list.some((entry) => !hasId(current, entry))) {
580
+ return next;
581
+ }
582
+ const kept = keepRemovedAssets(current, next);
583
+ return kept.length === current.length && kept.every((entry, i) => entry === current[i]) ? current : kept;
555
584
  }
556
585
  if (isPlainObject(current)) return mergeObject(current, list[0]);
557
586
  return current;
package/dist/nuxt/live.js CHANGED
@@ -130,7 +130,7 @@ function isFramed() {
130
130
  return typeof window !== "undefined" && window.self !== window.top;
131
131
  }
132
132
  function startLive() {
133
- starting ?? (starting = import("./live-preview-2RCU35W5.js").then(
133
+ starting ?? (starting = import("./live-preview-XMQQZHMZ.js").then(
134
134
  ({ applyPatchLog, createLiveBridge, createLiveStore }) => {
135
135
  applyLog = applyPatchLog;
136
136
  const started = createLiveStore();