payload-live-preview 1.0.1 → 1.0.3

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/core.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // package.json
4
4
  var package_default = {
5
- version: "1.0.1"};
5
+ version: "1.0.3"};
6
6
 
7
7
  // src/version.ts
8
8
  var VERSION = package_default.version;
@@ -338,6 +338,12 @@ var MessageBus = class {
338
338
  #handlers;
339
339
  #boundListener;
340
340
  #attached = false;
341
+ /**
342
+ * Tail of the async token-validation chain. Each gated update appends
343
+ * its validation to this promise, guaranteeing validations resolve —
344
+ * and updates dispatch — in the order the messages arrived.
345
+ */
346
+ #validationChain = Promise.resolve();
341
347
  constructor(matcher, handlers) {
342
348
  this.#matcher = matcher;
343
349
  this.#handlers = handlers;
@@ -394,6 +400,10 @@ var MessageBus = class {
394
400
  }
395
401
  switch (data.type) {
396
402
  case "payload-live-preview":
403
+ if (!isLivePreviewMessage(data)) {
404
+ this.#handlers.onInvalid?.("shape", origin);
405
+ return;
406
+ }
397
407
  this.#dispatchUpdate(data, origin);
398
408
  return;
399
409
  case "payload-document-event":
@@ -425,15 +435,17 @@ var MessageBus = class {
425
435
  else this.#handlers.onInvalid?.("token", origin);
426
436
  return;
427
437
  }
428
- void approved.then(
429
- (ok) => {
430
- if (ok) this.#handlers.onUpdate(message, origin);
431
- else this.#handlers.onInvalid?.("token", origin);
432
- },
433
- () => {
438
+ this.#validationChain = this.#validationChain.then(async () => {
439
+ let ok;
440
+ try {
441
+ ok = await approved;
442
+ } catch {
434
443
  this.#handlers.onInvalid?.("token", origin);
444
+ return;
435
445
  }
436
- );
446
+ if (ok) this.#handlers.onUpdate(message, origin);
447
+ else this.#handlers.onInvalid?.("token", origin);
448
+ });
437
449
  }
438
450
  };
439
451
  function isObjectMessage(value) {
@@ -441,6 +453,25 @@ function isObjectMessage(value) {
441
453
  if (!("type" in value)) return false;
442
454
  return typeof value.type === "string";
443
455
  }
456
+ function isLivePreviewMessage(value) {
457
+ const v = value;
458
+ if (v["data"] !== void 0 && v["data"] !== null && !isPlainObject(v["data"])) return false;
459
+ if (!optionalTypeOk(v["fieldSchemaJSON"], (x) => Array.isArray(x))) return false;
460
+ if (!optionalTypeOk(v["globalSlug"], (x) => typeof x === "string")) return false;
461
+ if (!optionalTypeOk(v["collectionSlug"], (x) => typeof x === "string")) return false;
462
+ if (!optionalTypeOk(v["locale"], (x) => typeof x === "string")) return false;
463
+ if (!optionalTypeOk(v["ready"], (x) => typeof x === "boolean")) return false;
464
+ if (!optionalTypeOk(v["previewToken"], (x) => typeof x === "string")) return false;
465
+ if (!optionalTypeOk(v["protocolVersion"], (x) => typeof x === "number")) return false;
466
+ return true;
467
+ }
468
+ function optionalTypeOk(value, check) {
469
+ if (value === void 0 || value === null) return true;
470
+ return check(value);
471
+ }
472
+ function isPlainObject(value) {
473
+ return typeof value === "object" && value !== null && !Array.isArray(value);
474
+ }
444
475
 
445
476
  // src/core/state.ts
446
477
  var DEFAULT_TIMEOUT_MS = 0;
@@ -3172,10 +3203,12 @@ async function runWithTransition(callback) {
3172
3203
  var KEY_ATTRIBUTE = "data-payload-key";
3173
3204
  var NESTED_KEY_ATTRIBUTE = "data-payload-nested-key";
3174
3205
  var NESTED_TEMPLATE_ATTRIBUTE = "data-payload-nested-template";
3175
- var previousItemValues = /* @__PURE__ */ new WeakMap();
3206
+ function createStructuralStore() {
3207
+ return /* @__PURE__ */ new WeakMap();
3208
+ }
3176
3209
  function applyStructuralPatches(options) {
3177
- const { template, container, patches } = options;
3178
- const memory = getMemory(container);
3210
+ const { template, container, patches, store } = options;
3211
+ const memory = getMemory(container, store);
3179
3212
  const removes = [];
3180
3213
  const inserts = [];
3181
3214
  const moves = [];
@@ -3200,7 +3233,7 @@ function applyStructuralPatches(options) {
3200
3233
  const node = container.children[patch.index];
3201
3234
  const replacement = renderItem(template, patch.value, patch.index);
3202
3235
  if (!node || !replacement) continue;
3203
- populateNestedSlots(replacement, patch.value);
3236
+ populateNestedSlots(replacement, patch.value, store);
3204
3237
  container.replaceChild(replacement, node);
3205
3238
  rememberItem(memory, patch.value);
3206
3239
  }
@@ -3209,7 +3242,7 @@ function applyStructuralPatches(options) {
3209
3242
  const oldNode = container.children[patch.index];
3210
3243
  const newNode = renderItem(template, patch.value, patch.index);
3211
3244
  if (!oldNode || !newNode) continue;
3212
- reconcileNestedSlots(oldNode, newNode, patch.value, memory);
3245
+ reconcileNestedSlots(oldNode, newNode, patch.value, memory, store);
3213
3246
  container.replaceChild(newNode, oldNode);
3214
3247
  rememberItem(memory, patch.value);
3215
3248
  }
@@ -3219,7 +3252,7 @@ function applyStructuralPatches(options) {
3219
3252
  const before = container.children[patch.index] ?? null;
3220
3253
  const node = renderItem(template, patch.value, patch.index);
3221
3254
  if (!node) continue;
3222
- populateNestedSlots(node, patch.value);
3255
+ populateNestedSlots(node, patch.value, store);
3223
3256
  container.insertBefore(node, before);
3224
3257
  rememberItem(memory, patch.value);
3225
3258
  }
@@ -3233,7 +3266,7 @@ function applyStructuralPatches(options) {
3233
3266
  container.insertBefore(node, before);
3234
3267
  }
3235
3268
  }
3236
- function populateNestedSlots(item, value) {
3269
+ function populateNestedSlots(item, value, store) {
3237
3270
  const slots = item.querySelectorAll(`[${NESTED_KEY_ATTRIBUTE}]`);
3238
3271
  for (const slot of Array.from(slots)) {
3239
3272
  const key = slot.getAttribute(NESTED_KEY_ATTRIBUTE);
@@ -3247,10 +3280,12 @@ function populateNestedSlots(item, value) {
3247
3280
  applyStructuralPatches({
3248
3281
  template: nestedTemplate,
3249
3282
  container: slot,
3250
- patches});
3283
+ patches,
3284
+ store
3285
+ });
3251
3286
  }
3252
3287
  }
3253
- function reconcileNestedSlots(oldItem, newItem, nextValue, memory) {
3288
+ function reconcileNestedSlots(oldItem, newItem, nextValue, memory, store) {
3254
3289
  const oldSlots = oldItem.querySelectorAll(`[${NESTED_KEY_ATTRIBUTE}]`);
3255
3290
  if (oldSlots.length === 0) return;
3256
3291
  const itemKey = readKey(nextValue);
@@ -3270,7 +3305,9 @@ function reconcileNestedSlots(oldItem, newItem, nextValue, memory) {
3270
3305
  applyStructuralPatches({
3271
3306
  template: nestedTemplate,
3272
3307
  container: oldSlot,
3273
- patches});
3308
+ patches,
3309
+ store
3310
+ });
3274
3311
  }
3275
3312
  }
3276
3313
  function readNestedArray(value, key) {
@@ -3279,11 +3316,11 @@ function readNestedArray(value, key) {
3279
3316
  if (!Array.isArray(nested)) return void 0;
3280
3317
  return nested;
3281
3318
  }
3282
- function getMemory(container) {
3283
- let map = previousItemValues.get(container);
3319
+ function getMemory(container, store) {
3320
+ let map = store.get(container);
3284
3321
  if (!map) {
3285
3322
  map = /* @__PURE__ */ new Map();
3286
- previousItemValues.set(container, map);
3323
+ store.set(container, map);
3287
3324
  }
3288
3325
  return map;
3289
3326
  }
@@ -3354,44 +3391,48 @@ function escapeRegex2(value) {
3354
3391
  }
3355
3392
 
3356
3393
  // src/field-types/structural-array.ts
3357
- var previousValues = /* @__PURE__ */ new WeakMap();
3358
- var warnedContainers = /* @__PURE__ */ new WeakSet();
3359
- var structuralArrayRenderer = {
3360
- name: "structural-array",
3361
- render(target, value) {
3362
- if (!Array.isArray(value)) return;
3363
- const container = target.element;
3364
- const template = target.arrayTemplate;
3365
- if (template === void 0 || template.length === 0) {
3366
- warnMissingTemplate(container, target.fieldName);
3367
- return;
3368
- }
3369
- const previous = previousValues.get(container) ?? [];
3370
- const patches = diffArray(previous, value);
3371
- if (patches.length === 0) {
3394
+ function createStructuralArrayRenderer() {
3395
+ const previousValues = /* @__PURE__ */ new WeakMap();
3396
+ const warnedContainers = /* @__PURE__ */ new WeakSet();
3397
+ const store = createStructuralStore();
3398
+ return {
3399
+ name: "structural-array",
3400
+ render(target, value) {
3401
+ if (!Array.isArray(value)) return;
3402
+ const container = target.element;
3403
+ const template = target.arrayTemplate;
3404
+ if (template === void 0 || template.length === 0) {
3405
+ warnMissingTemplate(warnedContainers, container, target.fieldName);
3406
+ return;
3407
+ }
3408
+ const previous = previousValues.get(container) ?? [];
3409
+ const patches = diffArray(previous, value);
3410
+ if (patches.length === 0) {
3411
+ previousValues.set(container, value.slice());
3412
+ return;
3413
+ }
3414
+ void runWithTransition(() => {
3415
+ applyStructuralPatches({
3416
+ template,
3417
+ container,
3418
+ patches,
3419
+ store
3420
+ });
3421
+ });
3372
3422
  previousValues.set(container, value.slice());
3373
- return;
3374
3423
  }
3375
- void runWithTransition(() => {
3376
- applyStructuralPatches({
3377
- template,
3378
- container,
3379
- patches});
3380
- });
3381
- previousValues.set(container, value.slice());
3382
- }
3383
- };
3384
- function warnMissingTemplate(container, fieldName) {
3424
+ };
3425
+ }
3426
+ function warnMissingTemplate(warnedContainers, container, fieldName) {
3385
3427
  if (warnedContainers.has(container)) return;
3386
3428
  warnedContainers.add(container);
3387
3429
  console.warn(
3388
3430
  `[live-preview] Skipping structural update for "${fieldName}" \u2014 the <${container.tagName.toLowerCase()}> with data-payload-structural is missing data-payload-array-template. Add an inline template (e.g., data-payload-array-template="<li>{{label}}</li>") so the renderer can materialise new items.`
3389
3431
  );
3390
3432
  }
3391
- registerBuiltinRenderer(structuralArrayRenderer);
3392
3433
 
3393
3434
  // src/field-types/index.ts
3394
- var BUILTIN = [
3435
+ var STATELESS_BUILTIN = [
3395
3436
  textRenderer2,
3396
3437
  textareaRenderer,
3397
3438
  richTextRenderer,
@@ -3407,11 +3448,10 @@ var BUILTIN = [
3407
3448
  dateRenderer,
3408
3449
  numberRenderer,
3409
3450
  arrayRenderer,
3410
- { ...arrayRenderer, name: "blocks" },
3411
- structuralArrayRenderer
3451
+ { ...arrayRenderer, name: "blocks" }
3412
3452
  ];
3413
3453
  function buildBuiltinRenderers2() {
3414
- return buildBuiltinRenderers(BUILTIN);
3454
+ return buildBuiltinRenderers([...STATELESS_BUILTIN, createStructuralArrayRenderer()]);
3415
3455
  }
3416
3456
 
3417
3457
  // src/client/index.ts