@amplifyup/sdk 0.1.61 → 0.1.62

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.
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { createContext, memo, useState, useEffect, Fragment as Fragment$1, useContext, Component } from 'react';
2
+ import { createContext, memo, useState, useEffect, Fragment as Fragment$1, useContext, Component, useMemo, useRef } from 'react';
3
3
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
4
  import 'marked';
5
5
 
@@ -405,6 +405,106 @@ function isComposerPreview() {
405
405
  return false;
406
406
  }
407
407
 
408
+ // src/field-envelope.ts
409
+ var FIELDS_BRAND = Symbol("amplifyup.fields");
410
+ function isBrandedFields(value) {
411
+ return !!value && typeof value === "object" && FIELDS_BRAND in value;
412
+ }
413
+ function brandFields(bag) {
414
+ if (isBrandedFields(bag)) return bag;
415
+ Object.defineProperty(bag, FIELDS_BRAND, {
416
+ value: true,
417
+ enumerable: false,
418
+ configurable: false
419
+ });
420
+ return bag;
421
+ }
422
+ function isFieldEnvelope(value) {
423
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
424
+ const rec = value;
425
+ return typeof rec.name === "string" && "value" in rec && !("url" in rec);
426
+ }
427
+ function isPortableImageShape(value) {
428
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
429
+ return "url" in value;
430
+ }
431
+ function joinPath(prefix, key) {
432
+ return prefix ? `${prefix}.${key}` : key;
433
+ }
434
+ function emptyValue(raw) {
435
+ if (raw === void 0) return null;
436
+ return raw;
437
+ }
438
+ function toFieldEnvelopes(source, prefix = "") {
439
+ const input = source && typeof source === "object" && !Array.isArray(source) ? source : {};
440
+ if (isBrandedFields(input)) {
441
+ return input;
442
+ }
443
+ const out = {};
444
+ for (const [key, raw] of Object.entries(input)) {
445
+ const path = joinPath(prefix, key);
446
+ if (isFieldEnvelope(raw)) {
447
+ out[key] = { value: raw.value ?? null, name: raw.name || path };
448
+ continue;
449
+ }
450
+ if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
451
+ out[key] = toFieldEnvelopes(raw, path);
452
+ continue;
453
+ }
454
+ out[key] = { value: emptyValue(raw), name: path };
455
+ }
456
+ return brandFields(out);
457
+ }
458
+ function attachFieldEnvelopes(props) {
459
+ const raw = props && typeof props === "object" ? { ...props } : {};
460
+ if (isBrandedFields(raw.fields)) return raw;
461
+ const { fields: existing, ...content } = raw;
462
+ const source = existing && typeof existing === "object" && !isFieldEnvelope(existing) ? existing : content;
463
+ return { ...raw, fields: toFieldEnvelopes(source) };
464
+ }
465
+ function walkLayoutNodes(nodes) {
466
+ if (!Array.isArray(nodes)) return;
467
+ for (const node of nodes) {
468
+ if (!node || typeof node !== "object") continue;
469
+ const rec = node;
470
+ rec.props = attachFieldEnvelopes(rec.props);
471
+ for (const slot of rec.slots || []) {
472
+ walkLayoutNodes(slot.children);
473
+ }
474
+ }
475
+ }
476
+ function envelopePageConfig(page) {
477
+ if (!page || typeof page !== "object") return page ?? null;
478
+ const tree = page.layoutTree;
479
+ if (Array.isArray(tree)) walkLayoutNodes(tree);
480
+ return page;
481
+ }
482
+ function collectFieldPatches(props) {
483
+ const out = [];
484
+ const walk = (obj, prefix) => {
485
+ for (const [key, raw] of Object.entries(obj)) {
486
+ if (key === "fields" && raw && typeof raw === "object" && !Array.isArray(raw) && !isFieldEnvelope(raw)) {
487
+ walk(raw, prefix);
488
+ continue;
489
+ }
490
+ const path = joinPath(prefix, key);
491
+ if (isFieldEnvelope(raw)) {
492
+ out.push({ name: raw.name || path, value: raw.value });
493
+ continue;
494
+ }
495
+ if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
496
+ walk(raw, path);
497
+ continue;
498
+ }
499
+ out.push({ name: path, value: emptyValue(raw) });
500
+ }
501
+ };
502
+ if (props && typeof props === "object" && !Array.isArray(props)) {
503
+ walk(props, "");
504
+ }
505
+ return out;
506
+ }
507
+
408
508
  // src/page-context.ts
409
509
  var defaultLog = {
410
510
  warn: (...args) => {
@@ -553,7 +653,70 @@ function mergeEventContext(properties, attached) {
553
653
  ...attached.pageRoute ? { pageRoute: attached.pageRoute } : {}
554
654
  };
555
655
  }
656
+ var PAGE_RESOURCE_MARKER = "__amplifyupPageResource";
657
+ function isPageResourceSentinel(value) {
658
+ return !!value && typeof value === "object" && !Array.isArray(value) && typeof value[PAGE_RESOURCE_MARKER] === "string";
659
+ }
660
+ function getByDotPath(source, path) {
661
+ if (!path) return source;
662
+ const parts = path.split(".").filter(Boolean);
663
+ let cur = source;
664
+ for (const part of parts) {
665
+ if (cur == null || typeof cur !== "object" || Array.isArray(cur)) {
666
+ return void 0;
667
+ }
668
+ cur = cur[part];
669
+ }
670
+ return cur;
671
+ }
672
+ function hydratePageResourceValue(value, fields) {
673
+ if (!isPageResourceSentinel(value)) return value;
674
+ if (!fields) return null;
675
+ if (value.path) return getByDotPath(fields, value.path) ?? null;
676
+ return fields;
677
+ }
678
+ function hydrateFieldsBag(bag, fields) {
679
+ const out = {};
680
+ for (const [key, val] of Object.entries(bag)) {
681
+ if (val && typeof val === "object" && !Array.isArray(val) && typeof val.name === "string" && "value" in val && !("url" in val)) {
682
+ const env = val;
683
+ out[key] = {
684
+ name: env.name,
685
+ value: isPageResourceSentinel(env.value) ? hydratePageResourceValue(env.value, fields) : env.value
686
+ };
687
+ continue;
688
+ }
689
+ if (val && typeof val === "object" && !Array.isArray(val) && !("url" in val)) {
690
+ out[key] = hydrateFieldsBag(val, fields);
691
+ continue;
692
+ }
693
+ out[key] = isPageResourceSentinel(val) ? hydratePageResourceValue(val, fields) : val;
694
+ }
695
+ return out;
696
+ }
697
+ function hydratePageResourceProps(props, fields) {
698
+ const source = props && typeof props === "object" ? props : {};
699
+ const out = { ...source };
700
+ if (out.fields && typeof out.fields === "object" && !Array.isArray(out.fields)) {
701
+ const next = hydrateFieldsBag(out.fields, fields);
702
+ out.fields = isBrandedFields(out.fields) ? brandFields(next) : next;
703
+ }
704
+ for (const [key, val] of Object.entries(out)) {
705
+ if (key === "fields") continue;
706
+ if (isPageResourceSentinel(val)) {
707
+ out[key] = hydratePageResourceValue(val, fields);
708
+ }
709
+ }
710
+ return out;
711
+ }
712
+
713
+ // src/page-resource-runtime.ts
714
+ var pageResourceFields = null;
556
715
  function setPageResourceFields(fields) {
716
+ pageResourceFields = fields && typeof fields === "object" ? fields : null;
717
+ }
718
+ function getPageResourceFields() {
719
+ return pageResourceFields;
557
720
  }
558
721
 
559
722
  // src/debug.ts
@@ -1236,6 +1399,7 @@ var AmplifyUpSDK = class {
1236
1399
  this.resolvedPageData,
1237
1400
  this.resolvedPageRoute
1238
1401
  );
1402
+ setPageResourceFields(null);
1239
1403
  return;
1240
1404
  }
1241
1405
  this.attachedPageContext = applyPageContext(this.pendingPageContext, {
@@ -1664,7 +1828,7 @@ Available Console Commands:
1664
1828
  this.refreshEventTracking();
1665
1829
  }, 800);
1666
1830
  }
1667
- return pageConfig;
1831
+ return envelopePageConfig(pageConfig);
1668
1832
  }
1669
1833
  /**
1670
1834
  * Set up view-level event tracking based on configuration
@@ -3037,31 +3201,66 @@ function getSDK(adapter) {
3037
3201
  var trackContentView = (contentId, contentType, properties) => getSDK().trackContentView(contentId, contentType, properties);
3038
3202
  var refreshEventTracking = () => getSDK().refreshEventTracking();
3039
3203
  getSDK();
3040
- createContext(null);
3041
- function useLiveComposerProps(layoutNodeId, props) {
3042
- const [patch, setPatch] = useState(null);
3043
- useEffect(() => {
3044
- setPatch(null);
3045
- const matchesNode = (nodeId) => {
3046
- if (nodeId && layoutNodeId && String(nodeId) !== String(layoutNodeId)) {
3047
- return false;
3048
- }
3049
- return true;
3204
+
3205
+ // src/composer-store.ts
3206
+ var ComposerFieldStore = class {
3207
+ constructor() {
3208
+ this.values = /* @__PURE__ */ new Map();
3209
+ this.listeners = /* @__PURE__ */ new Map();
3210
+ }
3211
+ get(name) {
3212
+ return this.values.has(name) ? this.values.get(name) : void 0;
3213
+ }
3214
+ set(name, value) {
3215
+ if (!name) return;
3216
+ this.values.set(name, value);
3217
+ const set = this.listeners.get(name);
3218
+ if (!set) return;
3219
+ for (const fn of set) fn();
3220
+ }
3221
+ subscribe(name, fn) {
3222
+ if (!name) return () => {
3050
3223
  };
3224
+ let set = this.listeners.get(name);
3225
+ if (!set) {
3226
+ set = /* @__PURE__ */ new Set();
3227
+ this.listeners.set(name, set);
3228
+ }
3229
+ set.add(fn);
3230
+ return () => {
3231
+ set.delete(fn);
3232
+ if (set.size === 0) this.listeners.delete(name);
3233
+ };
3234
+ }
3235
+ };
3236
+ var ComposerStoreContext = createContext(null);
3237
+ function matchesNode(eventNodeId, layoutNodeId) {
3238
+ if (eventNodeId && layoutNodeId && String(eventNodeId) !== String(layoutNodeId)) {
3239
+ return false;
3240
+ }
3241
+ return true;
3242
+ }
3243
+ function ComposerProvider({
3244
+ layoutNodeId,
3245
+ children
3246
+ }) {
3247
+ const storeRef = useRef(null);
3248
+ if (!storeRef.current) storeRef.current = new ComposerFieldStore();
3249
+ const store = storeRef.current;
3250
+ useEffect(() => {
3051
3251
  const applyField = (fieldName, value, nodeId) => {
3052
3252
  if (!fieldName || typeof fieldName !== "string") return;
3053
- if (!matchesNode(nodeId)) return;
3054
- setPatch((prev) => ({ ...prev || {}, [fieldName]: value }));
3253
+ if (!matchesNode(nodeId, layoutNodeId)) return;
3254
+ store.set(fieldName, value);
3055
3255
  };
3056
3256
  const applyProps = (nextProps, nodeId) => {
3057
3257
  if (!nextProps || typeof nextProps !== "object" || Array.isArray(nextProps)) {
3058
3258
  return;
3059
3259
  }
3060
- if (!matchesNode(nodeId)) return;
3061
- setPatch((prev) => ({
3062
- ...prev || {},
3063
- ...nextProps
3064
- }));
3260
+ if (!matchesNode(nodeId, layoutNodeId)) return;
3261
+ for (const patch of collectFieldPatches(nextProps)) {
3262
+ store.set(patch.name, patch.value);
3263
+ }
3065
3264
  };
3066
3265
  const onPatch = (event) => {
3067
3266
  const detail = event.detail || {};
@@ -3087,9 +3286,19 @@ function useLiveComposerProps(layoutNodeId, props) {
3087
3286
  window.removeEventListener("amplifyup:props-patch", onPropsPatch);
3088
3287
  window.removeEventListener("message", onMessage);
3089
3288
  };
3090
- }, [layoutNodeId]);
3091
- return patch ? { ...props, ...patch } : props;
3289
+ }, [layoutNodeId, store]);
3290
+ return /* @__PURE__ */ jsx(ComposerStoreContext.Provider, { value: store, children });
3092
3291
  }
3292
+ function MaybeComposerProvider({
3293
+ enabled,
3294
+ layoutNodeId,
3295
+ children
3296
+ }) {
3297
+ const content = useMemo(() => children, [children]);
3298
+ if (!enabled) return /* @__PURE__ */ jsx(Fragment, { children: content });
3299
+ return /* @__PURE__ */ jsx(ComposerProvider, { layoutNodeId, children });
3300
+ }
3301
+ createContext(null);
3093
3302
  var usePathname = null;
3094
3303
  if (typeof window !== "undefined") {
3095
3304
  try {
@@ -3109,9 +3318,19 @@ function useAmplifyUp() {
3109
3318
  return context;
3110
3319
  }
3111
3320
  function nodeRenderProps(node) {
3321
+ const settings = node.settings || {};
3322
+ const hydrated = hydratePageResourceProps(
3323
+ node.props || {},
3324
+ getPageResourceFields()
3325
+ );
3326
+ const fields = hydrated.fields;
3327
+ const branded = isBrandedFields(fields) ? fields : brandFields(
3328
+ fields && typeof fields === "object" ? fields : {}
3329
+ );
3112
3330
  return {
3113
- ...node.settings || {},
3114
- ...node.props || {}
3331
+ ...settings,
3332
+ ...hydrated,
3333
+ fields: branded
3115
3334
  };
3116
3335
  }
3117
3336
  var ComponentRenderBoundary = class extends Component {
@@ -3161,17 +3380,24 @@ var ComponentRenderBoundary = class extends Component {
3161
3380
  return this.props.children;
3162
3381
  }
3163
3382
  };
3164
- function LiveNodeRender({
3383
+ function NodeWithFields({
3165
3384
  nodeId,
3166
3385
  componentId,
3167
3386
  props,
3168
3387
  slots,
3169
- renderComponent
3388
+ renderComponent,
3389
+ composerPreview
3170
3390
  }) {
3171
- const liveProps = useLiveComposerProps(nodeId, props);
3172
- return /* @__PURE__ */ jsx(Fragment, { children: renderComponent(componentId, liveProps, slots, {
3173
- layoutNodeId: nodeId
3174
- }) });
3391
+ return /* @__PURE__ */ jsx(
3392
+ MaybeComposerProvider,
3393
+ {
3394
+ enabled: !!(composerPreview || isComposerPreview()),
3395
+ layoutNodeId: nodeId,
3396
+ children: renderComponent(componentId, props, slots, {
3397
+ layoutNodeId: nodeId
3398
+ })
3399
+ }
3400
+ );
3175
3401
  }
3176
3402
  function AmplifyRendererInner({
3177
3403
  renderComponent,
@@ -3527,13 +3753,14 @@ function AmplifyRendererInner({
3527
3753
  componentId: node.componentId,
3528
3754
  nodeId: node.id,
3529
3755
  children: /* @__PURE__ */ jsx(
3530
- LiveNodeRender,
3756
+ NodeWithFields,
3531
3757
  {
3532
3758
  nodeId: node.id,
3533
3759
  componentId: node.componentId,
3534
3760
  props: nodeRenderProps(node),
3535
3761
  slots: slotsToPass,
3536
- renderComponent
3762
+ renderComponent,
3763
+ composerPreview
3537
3764
  }
3538
3765
  )
3539
3766
  }