@amplifyup/sdk 0.1.78 → 0.1.79

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 (48) hide show
  1. package/README.md +91 -28
  2. package/dist/AmplifyRenderer-BNWBrFQN.d.ts +47 -0
  3. package/dist/AmplifyRenderer-CPUr9Bkc.d.mts +47 -0
  4. package/dist/AmplifyRenderer.d.mts +4 -40
  5. package/dist/AmplifyRenderer.d.ts +4 -40
  6. package/dist/AmplifyRenderer.js +106 -14
  7. package/dist/AmplifyRenderer.js.map +1 -1
  8. package/dist/AmplifyRenderer.mjs +106 -14
  9. package/dist/AmplifyRenderer.mjs.map +1 -1
  10. package/dist/cli.d.mts +1 -0
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +266 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/cli.mjs +260 -0
  15. package/dist/cli.mjs.map +1 -0
  16. package/dist/config.d.mts +18 -0
  17. package/dist/config.d.ts +18 -0
  18. package/dist/config.js +10 -0
  19. package/dist/config.js.map +1 -0
  20. package/dist/config.mjs +8 -0
  21. package/dist/config.mjs.map +1 -0
  22. package/dist/index.d.mts +3 -3
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +2 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.mjs +2 -2
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/next.d.mts +9 -0
  29. package/dist/next.d.ts +9 -0
  30. package/dist/next.js +259 -0
  31. package/dist/next.js.map +1 -0
  32. package/dist/next.mjs +253 -0
  33. package/dist/next.mjs.map +1 -0
  34. package/dist/query-DYjs4LQQ.d.mts +262 -0
  35. package/dist/query-Xo9cy-2F.d.ts +262 -0
  36. package/dist/react.d.mts +19 -21
  37. package/dist/react.d.ts +19 -21
  38. package/dist/react.js +1141 -1035
  39. package/dist/react.js.map +1 -1
  40. package/dist/react.mjs +1140 -1035
  41. package/dist/react.mjs.map +1 -1
  42. package/dist/server.d.mts +3 -3
  43. package/dist/server.d.ts +3 -3
  44. package/dist/{types-D4TSd2Yt.d.mts → types-ffQNIQCK.d.mts} +1 -102
  45. package/dist/{types-D4TSd2Yt.d.ts → types-ffQNIQCK.d.ts} +1 -102
  46. package/package.json +17 -2
  47. package/dist/query-B23UsNIv.d.ts +0 -161
  48. package/dist/query-CV8x3oQT.d.mts +0 -161
package/dist/react.mjs CHANGED
@@ -4114,711 +4114,159 @@ function MaybeComposerProvider({
4114
4114
  }) {
4115
4115
  return /* @__PURE__ */ jsx(ComposerProvider, { enabled, children: /* @__PURE__ */ jsx(ComposerNodeContext.Provider, { value: enabled ? layoutNodeId : void 0, children }) });
4116
4116
  }
4117
- function nodeRenderProps(node) {
4118
- const settings = node.settings || {};
4119
- const hydrated = hydratePageResourceProps(
4120
- node.props || {},
4121
- getPageResourceFields()
4122
- );
4123
- const fields = hydrated.fields;
4124
- const branded = isBrandedFields(fields) ? fields : brandFields(
4125
- fields && typeof fields === "object" ? fields : {}
4117
+ function AddComponentIcon({ size = 28 }) {
4118
+ return /* @__PURE__ */ jsxs(
4119
+ "svg",
4120
+ {
4121
+ width: size,
4122
+ height: size,
4123
+ viewBox: "0 0 24 24",
4124
+ fill: "none",
4125
+ xmlns: "http://www.w3.org/2000/svg",
4126
+ "aria-hidden": "true",
4127
+ focusable: "false",
4128
+ children: [
4129
+ /* @__PURE__ */ jsx(
4130
+ "rect",
4131
+ {
4132
+ x: "3",
4133
+ y: "3",
4134
+ width: "18",
4135
+ height: "18",
4136
+ rx: "4",
4137
+ stroke: "currentColor",
4138
+ strokeWidth: "1.75"
4139
+ }
4140
+ ),
4141
+ /* @__PURE__ */ jsx(
4142
+ "path",
4143
+ {
4144
+ d: "M12 8v8M8 12h8",
4145
+ stroke: "currentColor",
4146
+ strokeWidth: "1.75",
4147
+ strokeLinecap: "round"
4148
+ }
4149
+ )
4150
+ ]
4151
+ }
4126
4152
  );
4127
- return {
4128
- ...settings,
4129
- ...hydrated,
4130
- fields: branded
4131
- };
4132
4153
  }
4133
- var ComponentRenderBoundary = class extends Component {
4134
- constructor() {
4135
- super(...arguments);
4136
- this.state = { error: null };
4137
- }
4138
- static getDerivedStateFromError(error) {
4139
- return { error };
4140
- }
4141
- componentDidCatch(error) {
4142
- console.error(
4143
- `[AmplifyRenderer] "${this.props.componentId}" (${this.props.nodeId}) threw while rendering:`,
4144
- error
4145
- );
4146
- }
4147
- render() {
4148
- if (this.state.error) {
4149
- if (process.env.NODE_ENV !== "production") {
4150
- return /* @__PURE__ */ jsxs(
4151
- "div",
4154
+ function EmptySlotHint({
4155
+ label = "Click here to Add Component",
4156
+ compact = false
4157
+ }) {
4158
+ const iconSize = compact ? 20 : 28;
4159
+ return /* @__PURE__ */ jsxs(
4160
+ "div",
4161
+ {
4162
+ className: "amplifyup-slot-placeholder",
4163
+ style: {
4164
+ display: "flex",
4165
+ flexDirection: "column",
4166
+ alignItems: "center",
4167
+ justifyContent: "center",
4168
+ gap: compact ? 8 : 12,
4169
+ minHeight: compact ? 60 : void 0,
4170
+ width: "100%",
4171
+ pointerEvents: "none",
4172
+ textAlign: "center",
4173
+ boxSizing: "border-box",
4174
+ padding: compact ? "12px 8px" : "24px 16px"
4175
+ },
4176
+ children: [
4177
+ /* @__PURE__ */ jsx(
4178
+ "span",
4152
4179
  {
4153
- "data-amplifyup-render-error": "",
4154
- "data-component-id": this.props.componentId,
4155
- "data-node-id": this.props.nodeId,
4180
+ className: "amplifyup-slot-placeholder-icon",
4156
4181
  style: {
4157
- margin: "1rem 0",
4158
- padding: "0.75rem 1rem",
4159
- border: "1px solid #fca5a5",
4160
- borderRadius: "0.5rem",
4161
- background: "#fef2f2",
4162
- color: "#991b1b",
4163
- fontSize: "0.875rem"
4182
+ display: "inline-flex",
4183
+ alignItems: "center",
4184
+ justifyContent: "center",
4185
+ width: compact ? 36 : 48,
4186
+ height: compact ? 36 : 48,
4187
+ borderRadius: 12,
4188
+ border: "1.5px dashed currentColor",
4189
+ opacity: 0.9
4164
4190
  },
4165
- children: [
4166
- 'Component "',
4167
- this.props.componentId,
4168
- '" failed to render:',
4169
- " ",
4170
- this.state.error.message
4171
- ]
4191
+ children: /* @__PURE__ */ jsx(AddComponentIcon, { size: iconSize })
4172
4192
  }
4173
- );
4174
- }
4175
- return null;
4193
+ ),
4194
+ /* @__PURE__ */ jsx(
4195
+ "span",
4196
+ {
4197
+ className: "amplifyup-slot-placeholder-label",
4198
+ style: {
4199
+ fontSize: compact ? 13 : 15,
4200
+ fontWeight: 600,
4201
+ lineHeight: 1.3,
4202
+ letterSpacing: "0.01em"
4203
+ },
4204
+ children: label
4205
+ }
4206
+ )
4207
+ ]
4176
4208
  }
4177
- return this.props.children;
4209
+ );
4210
+ }
4211
+ var ComposerLayoutStatusContext = createContext({
4212
+ ready: true
4213
+ });
4214
+ function ComposerLayoutStatusProvider({
4215
+ ready,
4216
+ children
4217
+ }) {
4218
+ return /* @__PURE__ */ jsx(ComposerLayoutStatusContext.Provider, { value: { ready }, children });
4219
+ }
4220
+ function useComposerLayoutStatus() {
4221
+ return useContext(ComposerLayoutStatusContext);
4222
+ }
4223
+
4224
+ // src/slot-state.ts
4225
+ function resolveSlotState(opts) {
4226
+ if (!opts.layoutReady) return "loading";
4227
+ return opts.hasContent ? "filled" : "empty";
4228
+ }
4229
+ function slotShowsAddComponent(state) {
4230
+ return state === "empty";
4231
+ }
4232
+ function slotStateFromEl(el) {
4233
+ if (!el) return null;
4234
+ const explicit = el.getAttribute("data-slot-state");
4235
+ if (explicit === "loading" || explicit === "empty" || explicit === "filled") {
4236
+ return explicit;
4178
4237
  }
4179
- };
4180
- function NodeWithFields({
4181
- nodeId,
4182
- componentId,
4183
- props,
4238
+ if (el.getAttribute("data-slot-empty") === "true") return "empty";
4239
+ return null;
4240
+ }
4241
+
4242
+ // src/composer-edit-mode.ts
4243
+ function isComposerEditMode() {
4244
+ if (typeof window === "undefined") return false;
4245
+ return isComposerPreview() && window.__AMPLIFYUP_EVENT_SELECTION__ !== true;
4246
+ }
4247
+ function subscribeComposerEdit(onStoreChange) {
4248
+ if (typeof window === "undefined") return () => {
4249
+ };
4250
+ window.addEventListener("amplifyup:composer-edit", onStoreChange);
4251
+ return () => window.removeEventListener("amplifyup:composer-edit", onStoreChange);
4252
+ }
4253
+ function getComposerEditModeServer() {
4254
+ return false;
4255
+ }
4256
+ var ComponentContext = createContext(null);
4257
+ function ComponentContextProvider({
4258
+ children,
4184
4259
  slots,
4185
- renderComponent,
4186
- composerPreview
4187
- }) {
4188
- return /* @__PURE__ */ jsx(MaybeComposerProvider, { enabled: !!composerPreview, layoutNodeId: nodeId, children: renderComponent(componentId, props, slots, {
4189
- layoutNodeId: nodeId
4190
- }) });
4191
- }
4192
- function AmplifyRendererInner({
4193
- renderComponent,
4194
- pageConfig: serverPageConfig,
4195
- loadingComponent,
4196
- errorComponent,
4197
- emptyComponent,
4198
- composerPreview
4260
+ props,
4261
+ layoutNodeId,
4262
+ componentId
4199
4263
  }) {
4200
- const clientHook = useAmplifyUp();
4201
- useRegisterPageContent(!serverPageConfig);
4202
- const composerPreviewFlag = useComposerPreviewFlag(!!composerPreview);
4203
- const pageConfig = serverPageConfig || clientHook.pageConfig || null;
4204
- const loading = serverPageConfig ? false : clientHook.loading;
4205
- const error = serverPageConfig ? null : clientHook.error;
4206
- const contentSource = clientHook.source;
4207
- const [variantCache, setVariantCache] = useState({});
4208
- useEffect(() => {
4209
- if (typeof window !== "undefined") {
4210
- if (window.__AMPLIFYUP_PREVIEW_MODE__ === true) {
4211
- return;
4212
- }
4213
- if (window.location.pathname.includes("/api/pages/proxy")) {
4214
- return;
4215
- }
4216
- if (window.self !== window.top) {
4217
- return;
4218
- }
4219
- const urlParams = new URLSearchParams(window.location.search);
4220
- if (urlParams.get("preview") === "true" || urlParams.get("visualEditor") === "true") {
4221
- return;
4222
- }
4223
- if (window.location.href.includes("preview=true") || window.location.href.includes("visualEditor=true")) {
4224
- return;
4225
- }
4226
- }
4227
- if (pageConfig && pageConfig.id !== "default") {
4228
- trackContentView(pageConfig.id, "page", {
4229
- route: pageConfig.route,
4230
- title: pageConfig.title
4231
- });
4232
- }
4233
- }, [pageConfig]);
4234
- useEffect(() => {
4235
- if (!pageConfig?.eventTracking?.length) return;
4236
- const sdk = getSDK();
4237
- if (!sdk.isInitialized()) return;
4238
- sdk.setupEventTracking(pageConfig.eventTracking);
4239
- const t1 = window.setTimeout(() => {
4240
- sdk.setupComponentViewTracking();
4241
- refreshEventTracking();
4242
- }, 200);
4243
- const t2 = window.setTimeout(() => {
4244
- sdk.setupComponentViewTracking();
4245
- refreshEventTracking();
4246
- }, 1e3);
4247
- return () => {
4248
- window.clearTimeout(t1);
4249
- window.clearTimeout(t2);
4250
- };
4251
- }, [pageConfig?.id, pageConfig?.eventTracking]);
4252
- useEffect(() => {
4253
- if (!pageConfig) return;
4254
- const t = window.setTimeout(() => {
4255
- getSDK().setupComponentViewTracking();
4256
- refreshEventTracking();
4257
- }, 100);
4258
- return () => window.clearTimeout(t);
4259
- }, [variantCache, pageConfig?.id]);
4260
- useEffect(() => {
4261
- if (!isComposerPreview()) {
4262
- return;
4263
- }
4264
- if (!pageConfig) {
4265
- return;
4266
- }
4267
- const rawTree2 = pageConfig.layoutTree;
4268
- const normalizedTree = Array.isArray(rawTree2) ? rawTree2 : rawTree2 && typeof rawTree2 === "object" && rawTree2.componentId ? [rawTree2] : [];
4269
- if (normalizedTree.length === 0) {
4270
- if (typeof window !== "undefined" && window.parent && window.parent !== window) {
4271
- window.parent.postMessage({
4272
- type: "COMPONENT_TREE",
4273
- tree: []
4274
- }, "*");
4275
- }
4276
- return;
4277
- }
4278
- const convertLayoutTreeToComponentTree = (nodes, parentId = null) => {
4279
- const result = [];
4280
- nodes.forEach((node) => {
4281
- if (!node) return;
4282
- const treeNode = {
4283
- id: node.id,
4284
- componentId: node.componentId,
4285
- componentName: node.componentId,
4286
- // Will be enhanced with actual name if available
4287
- parentId,
4288
- children: []
4289
- };
4290
- if (node.slots && node.slots.length > 0) {
4291
- node.slots.forEach((slot) => {
4292
- const kids = Array.isArray(slot?.children) ? slot.children : [];
4293
- if (kids.length > 0) {
4294
- const slotChildren = convertLayoutTreeToComponentTree(kids, node.id);
4295
- treeNode.children.push(...slotChildren);
4296
- }
4297
- });
4298
- }
4299
- result.push(treeNode);
4300
- });
4301
- return result;
4302
- };
4303
- const layoutTree2 = normalizedTree;
4304
- const componentTree = convertLayoutTreeToComponentTree(layoutTree2);
4305
- const describeLayoutTree = (nodes, depth = 0) => {
4306
- if (!nodes?.length) return "";
4307
- const indent = " ".repeat(depth);
4308
- return nodes.map((n) => {
4309
- const slotsDesc = (n.slots || []).map((s) => {
4310
- const childCount = Array.isArray(s.children) ? s.children.length : 0;
4311
- const childrenDesc = childCount > 0 ? describeLayoutTree(s.children || [], depth + 1) : "";
4312
- return `${indent} slot "${s.slotId || s.slotName || "?"}" (${childCount} children)${childrenDesc ? "\n" + childrenDesc : ""}`;
4313
- }).join("\n");
4314
- return `${indent}- ${n.id} (${n.componentId || "?"})${slotsDesc ? "\n" + slotsDesc : ""}`;
4315
- }).join("\n");
4316
- };
4317
- sdkDebugOnce(
4318
- `layoutTree:${pageConfig?.id || ""}:${pageConfig?.route || ""}`,
4319
- "[AmplifyRenderer] layoutTree received:\n%s",
4320
- describeLayoutTree(layoutTree2)
4321
- );
4322
- if (typeof window !== "undefined" && window.parent && window.parent !== window) {
4323
- const message = {
4324
- type: "COMPONENT_TREE",
4325
- tree: componentTree
4326
- };
4327
- window.parent.postMessage(message, "*");
4328
- sdkDebug(
4329
- "[AmplifyRenderer] Sent component tree from layoutTree:",
4330
- componentTree.length,
4331
- "root components"
4332
- );
4333
- }
4334
- }, [pageConfig]);
4335
- useEffect(() => {
4336
- if (!pageConfig?.layoutTree || !pageConfig.layoutId) return;
4337
- const roots = pageConfig.layoutTree;
4338
- const fromEdge = contentSource === "edge" || roots.some((n) => n._contentSource === "edge");
4339
- if (fromEdge) return;
4340
- const sdk = getSDK();
4341
- const instanceId = sdk.getInstanceId();
4342
- const decisionApiUrl = sdk.getDecisionApiUrl();
4343
- const orchestratorUrl = sdk.getOrchestratorUrl();
4344
- if (!decisionApiUrl && !orchestratorUrl || !instanceId) return;
4345
- const fetchVariants = async () => {
4346
- const nodes = pageConfig.layoutTree;
4347
- const newCache = {};
4348
- const findZonedSlots = (nodeList) => {
4349
- const results = [];
4350
- for (const node of nodeList) {
4351
- if (node.slots) {
4352
- for (const slot of node.slots) {
4353
- if (slot.zoneId && slot.variants) {
4354
- const key = `${node.id}-${slot.slotId}`;
4355
- results.push({ node, slot, key });
4356
- }
4357
- }
4358
- }
4359
- }
4360
- return results;
4361
- };
4362
- const zonedSlots = findZonedSlots(nodes);
4363
- await Promise.all(
4364
- zonedSlots.map(async ({ node, slot, key }) => {
4365
- try {
4366
- let personalizationUrl;
4367
- if (decisionApiUrl) {
4368
- const url = new URL(decisionApiUrl);
4369
- url.searchParams.set("instanceId", instanceId);
4370
- const zoneId = slot.zoneId;
4371
- if (zoneId) {
4372
- url.searchParams.set("zoneId", zoneId);
4373
- }
4374
- const campaignId = slot.campaignId;
4375
- if (campaignId) {
4376
- url.searchParams.set("campaignId", campaignId);
4377
- }
4378
- personalizationUrl = url.toString();
4379
- } else if (orchestratorUrl) {
4380
- personalizationUrl = `${orchestratorUrl}/api/personalization/variant?instanceId=${encodeURIComponent(instanceId)}&layoutId=${encodeURIComponent(pageConfig.layoutId)}&slotId=${encodeURIComponent(slot.slotId)}&nodeId=${encodeURIComponent(node.id)}`;
4381
- } else {
4382
- return;
4383
- }
4384
- const response = await fetch(personalizationUrl);
4385
- if (response.ok) {
4386
- const data = await response.json();
4387
- if (data.variantId && data.componentTree) {
4388
- newCache[key] = {
4389
- variantId: data.variantId,
4390
- children: data.componentTree
4391
- };
4392
- if (typeof window !== "undefined") {
4393
- if (window.__AMPLIFYUP_PREVIEW_MODE__ === true) {
4394
- return;
4395
- }
4396
- if (window.location.pathname.includes("/api/pages/proxy")) {
4397
- return;
4398
- }
4399
- if (window.self !== window.top) {
4400
- return;
4401
- }
4402
- }
4403
- sdk.track("Zone Impression", {
4404
- zoneId: slot.zoneId,
4405
- variantId: data.variantId,
4406
- layoutId: pageConfig.layoutId,
4407
- route: pageConfig.route
4408
- });
4409
- } else {
4410
- const defaultVariant = slot.variants?.find((v) => v.isDefault);
4411
- if (defaultVariant) {
4412
- newCache[key] = {
4413
- variantId: defaultVariant.variantId,
4414
- children: defaultVariant.children
4415
- };
4416
- }
4417
- }
4418
- }
4419
- } catch (err) {
4420
- console.error(`Error fetching variant for slot ${key}:`, err);
4421
- const defaultVariant = slot.variants?.find((v) => v.isDefault);
4422
- if (defaultVariant) {
4423
- newCache[key] = {
4424
- variantId: defaultVariant.variantId,
4425
- children: defaultVariant.children
4426
- };
4427
- }
4428
- }
4429
- })
4430
- );
4431
- setVariantCache(newCache);
4432
- };
4433
- fetchVariants();
4434
- }, [pageConfig?.layoutTree, pageConfig?.layoutId, pageConfig?.route, contentSource]);
4435
- if (loading) {
4436
- return /* @__PURE__ */ jsx(Fragment, { children: loadingComponent || /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse", children: [
4437
- /* @__PURE__ */ jsx("div", { className: "h-8 bg-gray-200 rounded w-1/4 mb-4" }),
4438
- /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-1/2 mb-8" }),
4439
- /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4440
- /* @__PURE__ */ jsx("div", { className: "h-64 bg-gray-200 rounded" }),
4441
- /* @__PURE__ */ jsx("div", { className: "h-32 bg-gray-200 rounded" })
4442
- ] })
4443
- ] }) }) }) });
4444
- }
4445
- if (error) {
4446
- return /* @__PURE__ */ jsx(Fragment, { children: errorComponent ? errorComponent(error) : /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsxs("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6", children: [
4447
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-red-900 mb-2", children: "Error Loading Page" }),
4448
- /* @__PURE__ */ jsx("p", { className: "text-red-700", children: error })
4449
- ] }) }) }) });
4450
- }
4451
- if (!pageConfig) {
4452
- return null;
4453
- }
4454
- pageConfig.layout?.header !== false;
4455
- pageConfig.layout?.footer !== false;
4456
- const renderNode = (node) => {
4457
- const zoneIdFromProps = node.componentId === "AmplifyZone" ? String(node.props?.zoneId || "") : "";
4458
- if (node.componentId === "AmplifyZone") {
4459
- const contentSlot = node.slots?.find((s) => s.slotId === "content") || node.slots?.[0];
4460
- const children = Array.isArray(contentSlot?.children) ? contentSlot.children : [];
4461
- return /* @__PURE__ */ jsx(
4462
- "div",
4463
- {
4464
- "data-node-id": node.id,
4465
- "data-amplifyup-node": "",
4466
- "data-amplifyup-component": "AmplifyZone",
4467
- "data-amplifyup-zone": zoneIdFromProps || void 0,
4468
- "data-zone-id": zoneIdFromProps || void 0,
4469
- children: /* @__PURE__ */ jsx(
4470
- "div",
4471
- {
4472
- "data-slot-id": "content",
4473
- "data-amplifyup-slot": "content",
4474
- "data-parent-node-id": node.id,
4475
- "data-parent-component-id": "AmplifyZone",
4476
- children: children.filter(Boolean).map((child) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(child) }, child.id))
4477
- }
4478
- )
4479
- }
4480
- );
4481
- }
4482
- let slotChildren = {};
4483
- sdkDebugOnce(`node:${node.id}`, `[AmplifyRenderer] Rendering node ${node.id} (${node.componentId})`, {
4484
- hasSlots: !!(node.slots && node.slots.length > 0),
4485
- slotCount: node.slots?.length || 0,
4486
- slots: node.slots?.map((s) => ({ slotId: s.slotId, zoneId: s.zoneId, childrenCount: s.children?.length || 0 }))
4487
- });
4488
- if (node.slots && node.slots.length > 0) {
4489
- for (const slot of node.slots) {
4490
- const slotKey = `${node.id}-${slot.slotId}`;
4491
- let childrenToRender = [];
4492
- if (slot.zoneId && slot.variants && variantCache[slotKey]) {
4493
- childrenToRender = variantCache[slotKey].children;
4494
- } else if (slot.zoneId && slot.variants) {
4495
- const defaultVariant = slot.variants.find((v) => v.isDefault);
4496
- childrenToRender = defaultVariant?.children || [];
4497
- } else {
4498
- childrenToRender = Array.isArray(slot.children) ? slot.children : [];
4499
- }
4500
- const safeChildren = Array.isArray(childrenToRender) ? childrenToRender : [];
4501
- slotChildren[slot.slotId] = /* @__PURE__ */ jsx(
4502
- "div",
4503
- {
4504
- "data-slot-id": slot.slotId,
4505
- "data-amplifyup-slot": slot.slotId,
4506
- "data-zone-id": slot.zoneId || void 0,
4507
- "data-parent-node-id": node.id,
4508
- "data-parent-component-id": node.componentId,
4509
- children: safeChildren.filter(Boolean).map((child) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(child) }, child.id))
4510
- },
4511
- slot.slotId
4512
- );
4513
- }
4514
- }
4515
- const slotsToPass = Object.keys(slotChildren).length > 0 ? slotChildren : void 0;
4516
- return /* @__PURE__ */ jsx(
4517
- "div",
4518
- {
4519
- "data-node-id": node.id,
4520
- "data-amplifyup-node": "",
4521
- "data-component-id": node.componentId,
4522
- "data-amplifyup-component": node.componentId,
4523
- children: /* @__PURE__ */ jsx(
4524
- ComponentRenderBoundary,
4525
- {
4526
- componentId: node.componentId,
4527
- nodeId: node.id,
4528
- children: /* @__PURE__ */ jsx(
4529
- NodeWithFields,
4530
- {
4531
- nodeId: node.id,
4532
- componentId: node.componentId,
4533
- props: nodeRenderProps(node),
4534
- slots: slotsToPass,
4535
- renderComponent,
4536
- composerPreview: composerPreviewFlag
4537
- }
4538
- )
4539
- }
4540
- )
4541
- }
4542
- );
4543
- };
4544
- const rawTree = pageConfig.layoutTree;
4545
- const layoutTree = Array.isArray(rawTree) ? rawTree : rawTree && typeof rawTree === "object" && rawTree.componentId ? [rawTree] : [];
4546
- if (layoutTree.length === 0) {
4547
- return /* @__PURE__ */ jsx("main", { children: emptyComponent || /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No content configured for this page." }) }) });
4548
- }
4549
- return /* @__PURE__ */ jsx(ComposerProvider, { children: /* @__PURE__ */ jsx(
4550
- "main",
4551
- {
4552
- "data-slot-id": composerPreviewFlag ? "main" : void 0,
4553
- "data-amplifyup-slot": composerPreviewFlag ? "main" : void 0,
4554
- "data-slot-source": composerPreviewFlag ? "page" : void 0,
4555
- "data-slot-state": composerPreviewFlag ? "filled" : void 0,
4556
- children: layoutTree.map((node) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(node) }, node.id))
4557
- }
4558
- ) });
4559
- }
4560
- var AmplifyRenderer = memo(AmplifyRendererInner);
4561
- function AddComponentIcon({ size = 28 }) {
4562
- return /* @__PURE__ */ jsxs(
4563
- "svg",
4564
- {
4565
- width: size,
4566
- height: size,
4567
- viewBox: "0 0 24 24",
4568
- fill: "none",
4569
- xmlns: "http://www.w3.org/2000/svg",
4570
- "aria-hidden": "true",
4571
- focusable: "false",
4572
- children: [
4573
- /* @__PURE__ */ jsx(
4574
- "rect",
4575
- {
4576
- x: "3",
4577
- y: "3",
4578
- width: "18",
4579
- height: "18",
4580
- rx: "4",
4581
- stroke: "currentColor",
4582
- strokeWidth: "1.75"
4583
- }
4584
- ),
4585
- /* @__PURE__ */ jsx(
4586
- "path",
4587
- {
4588
- d: "M12 8v8M8 12h8",
4589
- stroke: "currentColor",
4590
- strokeWidth: "1.75",
4591
- strokeLinecap: "round"
4592
- }
4593
- )
4594
- ]
4595
- }
4596
- );
4597
- }
4598
- function EmptySlotHint({
4599
- label = "Click here to Add Component",
4600
- compact = false
4601
- }) {
4602
- const iconSize = compact ? 20 : 28;
4603
- return /* @__PURE__ */ jsxs(
4604
- "div",
4605
- {
4606
- className: "amplifyup-slot-placeholder",
4607
- style: {
4608
- display: "flex",
4609
- flexDirection: "column",
4610
- alignItems: "center",
4611
- justifyContent: "center",
4612
- gap: compact ? 8 : 12,
4613
- minHeight: compact ? 60 : void 0,
4614
- width: "100%",
4615
- pointerEvents: "none",
4616
- textAlign: "center",
4617
- boxSizing: "border-box",
4618
- padding: compact ? "12px 8px" : "24px 16px"
4619
- },
4620
- children: [
4621
- /* @__PURE__ */ jsx(
4622
- "span",
4623
- {
4624
- className: "amplifyup-slot-placeholder-icon",
4625
- style: {
4626
- display: "inline-flex",
4627
- alignItems: "center",
4628
- justifyContent: "center",
4629
- width: compact ? 36 : 48,
4630
- height: compact ? 36 : 48,
4631
- borderRadius: 12,
4632
- border: "1.5px dashed currentColor",
4633
- opacity: 0.9
4634
- },
4635
- children: /* @__PURE__ */ jsx(AddComponentIcon, { size: iconSize })
4636
- }
4637
- ),
4638
- /* @__PURE__ */ jsx(
4639
- "span",
4640
- {
4641
- className: "amplifyup-slot-placeholder-label",
4642
- style: {
4643
- fontSize: compact ? 13 : 15,
4644
- fontWeight: 600,
4645
- lineHeight: 1.3,
4646
- letterSpacing: "0.01em"
4647
- },
4648
- children: label
4649
- }
4650
- )
4651
- ]
4652
- }
4653
- );
4654
- }
4655
- var ComposerLayoutStatusContext = createContext({
4656
- ready: true
4657
- });
4658
- function ComposerLayoutStatusProvider({
4659
- ready,
4660
- children
4661
- }) {
4662
- return /* @__PURE__ */ jsx(ComposerLayoutStatusContext.Provider, { value: { ready }, children });
4663
- }
4664
- function useComposerLayoutStatus() {
4665
- return useContext(ComposerLayoutStatusContext);
4666
- }
4667
- function previewPageSlot(state) {
4668
- return /* @__PURE__ */ jsx(
4669
- "div",
4670
- {
4671
- "data-slot-id": "main",
4672
- "data-amplifyup-slot": "main",
4673
- "data-slot-source": "page",
4674
- "data-slot-state": state,
4675
- "data-slot-empty": state === "empty" ? "true" : void 0,
4676
- style: {
4677
- minHeight: state === "empty" ? "50vh" : void 0,
4678
- width: "100%",
4679
- display: "block",
4680
- position: "relative"
4681
- },
4682
- children: state === "empty" ? /* @__PURE__ */ jsx(EmptySlotHint, {}) : null
4683
- }
4684
- );
4685
- }
4686
- function hasAmplifyLayout(pageConfig) {
4687
- return !!(pageConfig && pageConfig.id !== "default" && Array.isArray(pageConfig.layoutTree) && pageConfig.layoutTree.length > 0);
4688
- }
4689
- function normalizeRoutePath(route) {
4690
- if (!route) return "";
4691
- const path = route.split("?")[0] || "/";
4692
- if (path.length > 1 && path.endsWith("/")) return path.replace(/\/+$/, "");
4693
- return path || "/";
4694
- }
4695
- function samePageRoute(a, b) {
4696
- const ar = normalizeRoutePath(a?.route);
4697
- const br = normalizeRoutePath(b?.route);
4698
- return !!ar && !!br && ar === br;
4699
- }
4700
- function layoutTreesEqual(a, b) {
4701
- if (!a || !b) return a === b;
4702
- return JSON.stringify(a.layoutTree) === JSON.stringify(b.layoutTree);
4703
- }
4704
- function AmplifyPageContent({
4705
- fallback,
4706
- renderComponent,
4707
- pageConfig: pageConfigProp,
4708
- forceComposerPreview = false,
4709
- previewLoadingComponent,
4710
- previewEmptyComponent,
4711
- loadingComponent,
4712
- emptyComponent,
4713
- errorComponent
4714
- }) {
4715
- const client = useAmplifyUp();
4716
- useRegisterPageContent();
4717
- const preview = useComposerPreviewFlag(forceComposerPreview);
4718
- const clientLayout = hasAmplifyLayout(client.pageConfig) ? client.pageConfig : null;
4719
- const serverLayout = hasAmplifyLayout(pageConfigProp) ? pageConfigProp : null;
4720
- let pageConfig = serverLayout ?? clientLayout;
4721
- if (preview && clientLayout) {
4722
- pageConfig = clientLayout;
4723
- } else if (clientLayout && serverLayout && samePageRoute(clientLayout, serverLayout) && !layoutTreesEqual(clientLayout, serverLayout)) {
4724
- pageConfig = clientLayout;
4725
- } else if (clientLayout && !serverLayout) {
4726
- pageConfig = clientLayout;
4727
- }
4728
- const loading = !hasAmplifyLayout(pageConfig) && client.loading;
4729
- const error = hasAmplifyLayout(pageConfig) ? null : pageConfigProp ? null : client.error;
4730
- const previewEmpty = previewEmptyComponent ?? previewPageSlot("empty");
4731
- const previewLoading = previewLoadingComponent ?? previewPageSlot("loading");
4732
- if (preview) {
4733
- const ready = previewLayoutReady({
4734
- clientLoading: client.loading,
4735
- hasClientLayout: !!clientLayout,
4736
- hasServerLayout: !!serverLayout
4737
- });
4738
- if (!ready) {
4739
- return /* @__PURE__ */ jsx(ComposerLayoutStatusProvider, { ready: false, children: previewLoading });
4740
- }
4741
- const layoutSettled = !client.loading || !!clientLayout;
4742
- return /* @__PURE__ */ jsx(ComposerLayoutStatusProvider, { ready: layoutSettled, children: /* @__PURE__ */ jsx(
4743
- AmplifyRenderer,
4744
- {
4745
- pageConfig: pageConfig ?? void 0,
4746
- renderComponent,
4747
- composerPreview: true,
4748
- loadingComponent: loadingComponent ?? previewLoading,
4749
- emptyComponent: emptyComponent ?? previewEmpty,
4750
- errorComponent: errorComponent ?? (() => previewEmpty)
4751
- }
4752
- ) });
4753
- }
4754
- if (loading) {
4755
- return loadingComponent ? /* @__PURE__ */ jsx(Fragment, { children: loadingComponent }) : null;
4756
- }
4757
- if (error) {
4758
- if (errorComponent) return /* @__PURE__ */ jsx(Fragment, { children: errorComponent(error) });
4759
- return fallback ? /* @__PURE__ */ jsx(Fragment, { children: fallback }) : null;
4760
- }
4761
- if (!hasAmplifyLayout(pageConfig)) {
4762
- return fallback ? /* @__PURE__ */ jsx(Fragment, { children: fallback }) : null;
4763
- }
4764
- return /* @__PURE__ */ jsx(ComposerLayoutStatusProvider, { ready: true, children: /* @__PURE__ */ jsx(
4765
- AmplifyRenderer,
4766
- {
4767
- pageConfig: pageConfig ?? void 0,
4768
- renderComponent,
4769
- loadingComponent,
4770
- emptyComponent,
4771
- errorComponent
4772
- }
4773
- ) });
4774
- }
4775
-
4776
- // src/slot-state.ts
4777
- function resolveSlotState(opts) {
4778
- if (!opts.layoutReady) return "loading";
4779
- return opts.hasContent ? "filled" : "empty";
4780
- }
4781
- function slotShowsAddComponent(state) {
4782
- return state === "empty";
4783
- }
4784
- function slotStateFromEl(el) {
4785
- if (!el) return null;
4786
- const explicit = el.getAttribute("data-slot-state");
4787
- if (explicit === "loading" || explicit === "empty" || explicit === "filled") {
4788
- return explicit;
4789
- }
4790
- if (el.getAttribute("data-slot-empty") === "true") return "empty";
4791
- return null;
4792
- }
4793
-
4794
- // src/composer-edit-mode.ts
4795
- function isComposerEditMode() {
4796
- if (typeof window === "undefined") return false;
4797
- return isComposerPreview() && window.__AMPLIFYUP_EVENT_SELECTION__ !== true;
4798
- }
4799
- function subscribeComposerEdit(onStoreChange) {
4800
- if (typeof window === "undefined") return () => {
4801
- };
4802
- window.addEventListener("amplifyup:composer-edit", onStoreChange);
4803
- return () => window.removeEventListener("amplifyup:composer-edit", onStoreChange);
4804
- }
4805
- function getComposerEditModeServer() {
4806
- return false;
4807
- }
4808
- var ComponentContext = createContext(null);
4809
- function ComponentContextProvider({
4810
- children,
4811
- slots,
4812
- props,
4813
- layoutNodeId,
4814
- componentId
4815
- }) {
4816
- const next = hydratePageResourceProps(props || {}, getPageResourceFields());
4817
- return /* @__PURE__ */ jsx(
4818
- ComponentContext.Provider,
4819
- {
4820
- value: { slots, props: next, layoutNodeId, componentId },
4821
- children
4264
+ const next = hydratePageResourceProps(props || {}, getPageResourceFields());
4265
+ return /* @__PURE__ */ jsx(
4266
+ ComponentContext.Provider,
4267
+ {
4268
+ value: { slots, props: next, layoutNodeId, componentId },
4269
+ children
4822
4270
  }
4823
4271
  );
4824
4272
  }
@@ -4828,7 +4276,9 @@ function Slot({
4828
4276
  }) {
4829
4277
  const context = useContext(ComponentContext);
4830
4278
  if (!context) {
4831
- console.warn(`[AmplifyUp SDK] Slot "${name}" used outside ComponentContextProvider`);
4279
+ console.warn(
4280
+ `[AmplifyUp SDK] Slot "${name}" only works inside a component rendered from your component registry`
4281
+ );
4832
4282
  return null;
4833
4283
  }
4834
4284
  const slotContent = context.slots?.[name];
@@ -5142,391 +4592,1046 @@ function ComposerInlineField({
5142
4592
  opacity: showHint ? 0.5 : void 0
5143
4593
  }
5144
4594
  }
5145
- );
5146
- }
5147
- function ComposerInlineHtml({
5148
- name,
5149
- html,
5150
- sourceValue,
5151
- className,
5152
- Tag = "div",
5153
- layoutNodeId,
5154
- componentId,
5155
- fieldRef
5156
- }) {
5157
- const elRef = useRef(null);
5158
- useEffect(() => {
5159
- const el = elRef.current;
5160
- if (!el) return;
5161
- if (el.innerHTML !== html) el.innerHTML = html;
5162
- }, [html]);
5163
- const openRichEditor = (event) => {
5164
- if (!elRef.current) return;
5165
- event.preventDefault();
5166
- event.stopPropagation();
5167
- requestCanvasRichTextEdit({
5168
- el: elRef.current,
5169
- layoutNodeId,
5170
- componentId,
5171
- name,
5172
- value: sourceValue,
5173
- fieldRef
5174
- });
5175
- };
5176
- return React3.createElement(Tag, {
5177
- ref: elRef,
5178
- className,
5179
- "data-amplifyup-field": name,
5180
- "data-amplifyup-field-type": "richtext",
5181
- "data-amplifyup-source": sourceValue,
5182
- "data-amplifyup-node-id": layoutNodeId || void 0,
5183
- "data-amplifyup-ref-provider": fieldRef?.providerId || void 0,
5184
- "data-amplifyup-ref-entity": fieldRef?.entity || void 0,
5185
- "data-amplifyup-ref-id": fieldRef?.id || void 0,
5186
- dangerouslySetInnerHTML: { __html: html },
5187
- onMouseDown: (event) => {
5188
- event.stopPropagation();
5189
- },
5190
- onClick: openRichEditor,
5191
- style: {
5192
- cursor: "text",
5193
- outline: "1px dashed color-mix(in srgb, currentColor 40%, transparent)",
5194
- outlineOffset: "6px"
4595
+ );
4596
+ }
4597
+ function ComposerInlineHtml({
4598
+ name,
4599
+ html,
4600
+ sourceValue,
4601
+ className,
4602
+ Tag = "div",
4603
+ layoutNodeId,
4604
+ componentId,
4605
+ fieldRef
4606
+ }) {
4607
+ const elRef = useRef(null);
4608
+ useEffect(() => {
4609
+ const el = elRef.current;
4610
+ if (!el) return;
4611
+ if (el.innerHTML !== html) el.innerHTML = html;
4612
+ }, [html]);
4613
+ const openRichEditor = (event) => {
4614
+ if (!elRef.current) return;
4615
+ event.preventDefault();
4616
+ event.stopPropagation();
4617
+ requestCanvasRichTextEdit({
4618
+ el: elRef.current,
4619
+ layoutNodeId,
4620
+ componentId,
4621
+ name,
4622
+ value: sourceValue,
4623
+ fieldRef
4624
+ });
4625
+ };
4626
+ return React3.createElement(Tag, {
4627
+ ref: elRef,
4628
+ className,
4629
+ "data-amplifyup-field": name,
4630
+ "data-amplifyup-field-type": "richtext",
4631
+ "data-amplifyup-source": sourceValue,
4632
+ "data-amplifyup-node-id": layoutNodeId || void 0,
4633
+ "data-amplifyup-ref-provider": fieldRef?.providerId || void 0,
4634
+ "data-amplifyup-ref-entity": fieldRef?.entity || void 0,
4635
+ "data-amplifyup-ref-id": fieldRef?.id || void 0,
4636
+ dangerouslySetInnerHTML: { __html: html },
4637
+ onMouseDown: (event) => {
4638
+ event.stopPropagation();
4639
+ },
4640
+ onClick: openRichEditor,
4641
+ style: {
4642
+ cursor: "text",
4643
+ outline: "1px dashed color-mix(in srgb, currentColor 40%, transparent)",
4644
+ outlineOffset: "6px"
4645
+ }
4646
+ });
4647
+ }
4648
+ function formatFieldValue(value) {
4649
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
4650
+ return String(value);
4651
+ }
4652
+ if (Array.isArray(value)) {
4653
+ const parts = value.map((item) => {
4654
+ if (typeof item === "string") return item;
4655
+ if (item && typeof item === "object" && "children" in item && Array.isArray(item.children)) {
4656
+ return item.children.map((c) => typeof c?.text === "string" ? c.text : "").join("");
4657
+ }
4658
+ return "";
4659
+ }).filter(Boolean);
4660
+ if (parts.length > 0) return parts.join(" ");
4661
+ }
4662
+ if (value && typeof value === "object") {
4663
+ return "";
4664
+ }
4665
+ return "";
4666
+ }
4667
+ var FIELD_SCALAR_HINT = "Field expects a scalar field. Did you mean <Field field={post.title} />?";
4668
+ function warnNotScalarField(component, field, fieldValue) {
4669
+ if (process.env.NODE_ENV === "production") return false;
4670
+ if (isBrandedFields(field)) {
4671
+ console.error(`[AmplifyUp SDK] ${component}: ${FIELD_SCALAR_HINT}`);
4672
+ return true;
4673
+ }
4674
+ if (isFieldEnvelope(field) && Array.isArray(field.value)) {
4675
+ console.error(`[AmplifyUp SDK] ${component}: ${FIELD_SCALAR_HINT}`);
4676
+ return true;
4677
+ }
4678
+ if (Array.isArray(fieldValue)) {
4679
+ console.error(`[AmplifyUp SDK] ${component}: ${FIELD_SCALAR_HINT}`);
4680
+ return true;
4681
+ }
4682
+ return false;
4683
+ }
4684
+ function assertNamedEnvelope(component, field) {
4685
+ if (process.env.NODE_ENV === "production") return;
4686
+ if (!field || typeof field !== "object" || Array.isArray(field)) return;
4687
+ const rec = field;
4688
+ if (!("value" in rec)) return;
4689
+ if (typeof rec.name === "string" && rec.name) return;
4690
+ throw new Error(
4691
+ `[AmplifyUp SDK] ${component} received an envelope-shaped object with a \`value\` but no \`name\` \u2014 a partial envelope was manufactured upstream (keys: ${Object.keys(
4692
+ rec
4693
+ ).join(", ")}). Find the producer; do not strip or rebuild envelopes.`
4694
+ );
4695
+ }
4696
+ var warnedReadOnlyFields = /* @__PURE__ */ new Set();
4697
+ function warnReadOnlyRowField(name) {
4698
+ if (process.env.NODE_ENV === "production") return;
4699
+ const key = name || "(unnamed)";
4700
+ if (warnedReadOnlyFields.has(key)) return;
4701
+ warnedReadOnlyFields.add(key);
4702
+ console.warn(
4703
+ `[AmplifyUp SDK] ${key} has no write target; rendered read-only.`
4704
+ );
4705
+ }
4706
+ function canComposerBind(field, ref, editName) {
4707
+ if (isReadOnlyRowField(field) || isFieldEnvelope(field) && field.readOnly) {
4708
+ warnReadOnlyRowField(editName || (isFieldEnvelope(field) ? field.name : ""));
4709
+ return false;
4710
+ }
4711
+ return true;
4712
+ }
4713
+ function warnProjectionProps(component, hasField, hasValue, name) {
4714
+ if (process.env.NODE_ENV === "production") return;
4715
+ if (!hasField && !hasValue && !name) {
4716
+ console.warn(
4717
+ `[AmplifyUp SDK] ${component} needs field={fields.yourProp} (or value + name for computed values)`
4718
+ );
4719
+ }
4720
+ }
4721
+ function hasOwnProp(props, key) {
4722
+ return Object.prototype.hasOwnProperty.call(props, key);
4723
+ }
4724
+ function Field(props) {
4725
+ const { field, value, name, className } = props;
4726
+ const context = useContext(ComponentContext);
4727
+ const composerEdit = useComposerEditMode();
4728
+ const hasField = isFieldEnvelope(field);
4729
+ const hasValue = hasOwnProp(props, "value");
4730
+ const { editName, fieldValue, ref } = useBoundField(field, value, name, "Field");
4731
+ assertNamedEnvelope("Field", field);
4732
+ warnProjectionProps("Field", hasField, hasValue, name);
4733
+ if (warnNotScalarField("Field", field, fieldValue)) {
4734
+ return null;
4735
+ }
4736
+ if (!hasField && !hasValue && !name) {
4737
+ return null;
4738
+ }
4739
+ if (isBrandedFields(field) || Array.isArray(fieldValue)) {
4740
+ return null;
4741
+ }
4742
+ const empty = isComposerEmptyText(fieldValue);
4743
+ const bindComposer = composerEdit && editName && context && canInlineEdit(editName, fieldValue) && canComposerBind(field, ref, editName);
4744
+ if (bindComposer) {
4745
+ return /* @__PURE__ */ jsx(
4746
+ ComposerInlineField,
4747
+ {
4748
+ name: editName,
4749
+ value: fieldValue,
4750
+ className,
4751
+ layoutNodeId: context.layoutNodeId,
4752
+ componentId: context.componentId,
4753
+ fieldRef: ref,
4754
+ rich: looksLikeRichCanvasField(editName)
4755
+ }
4756
+ );
4757
+ }
4758
+ if (empty) return null;
4759
+ const text = formatFieldValue(fieldValue);
4760
+ if (!text) return null;
4761
+ return /* @__PURE__ */ jsx("span", { className, children: text });
4762
+ }
4763
+ function markdownToHtml(markdown) {
4764
+ try {
4765
+ const result = marked.parse(markdown, { async: false });
4766
+ return typeof result === "string" ? result : "";
4767
+ } catch {
4768
+ return markdown;
4769
+ }
4770
+ }
4771
+ function RichText(props) {
4772
+ const {
4773
+ field,
4774
+ value,
4775
+ name,
4776
+ className,
4777
+ as: Tag = "div",
4778
+ children
4779
+ } = props;
4780
+ const context = useContext(ComponentContext);
4781
+ const composerEdit = useComposerEditMode();
4782
+ const childrenValue = typeof children === "string" || typeof children === "number" ? String(children) : void 0;
4783
+ const hasField = isFieldEnvelope(field);
4784
+ const hasValueProp = hasOwnProp(props, "value") || childrenValue !== void 0;
4785
+ const boundValue = hasOwnProp(props, "value") ? value : childrenValue !== void 0 ? childrenValue : value;
4786
+ const { editName, fieldValue, ref } = useBoundField(
4787
+ field,
4788
+ boundValue,
4789
+ name,
4790
+ "RichText"
4791
+ );
4792
+ assertNamedEnvelope("RichText", field);
4793
+ if (!hasField && !hasValueProp && !name) {
4794
+ return null;
4795
+ }
4796
+ warnProjectionProps("RichText", hasField, hasValueProp, name);
4797
+ if (warnNotScalarField("RichText", field, fieldValue)) {
4798
+ return null;
4799
+ }
4800
+ const canEdit = !!context && canInlineEditRichText(editName, fieldValue) && canComposerBind(field, ref, editName);
4801
+ if (isComposerEmptyText(fieldValue)) {
4802
+ if (composerEdit && canEdit) {
4803
+ return /* @__PURE__ */ jsx(
4804
+ ComposerInlineField,
4805
+ {
4806
+ name: editName,
4807
+ value: fieldValue,
4808
+ className,
4809
+ layoutNodeId: context?.layoutNodeId,
4810
+ componentId: context?.componentId,
4811
+ fieldRef: ref,
4812
+ rich: true
4813
+ }
4814
+ );
4815
+ }
4816
+ return null;
4817
+ }
4818
+ let html = "";
4819
+ if (typeof fieldValue === "string") {
4820
+ const trimmed = fieldValue.trim();
4821
+ if (trimmed.startsWith("<") && trimmed.includes(">")) {
4822
+ html = fieldValue;
4823
+ } else {
4824
+ html = markdownToHtml(fieldValue);
5195
4825
  }
5196
- });
5197
- }
5198
- function formatFieldValue(value) {
5199
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
5200
- return String(value);
4826
+ } else {
4827
+ const text = formatFieldValue(fieldValue);
4828
+ html = text ? markdownToHtml(text) : "";
5201
4829
  }
5202
- if (Array.isArray(value)) {
5203
- const parts = value.map((item) => {
5204
- if (typeof item === "string") return item;
5205
- if (item && typeof item === "object" && "children" in item && Array.isArray(item.children)) {
5206
- return item.children.map((c) => typeof c?.text === "string" ? c.text : "").join("");
5207
- }
5208
- return "";
5209
- }).filter(Boolean);
5210
- if (parts.length > 0) return parts.join(" ");
4830
+ if (!html) {
4831
+ return null;
5211
4832
  }
5212
- if (value && typeof value === "object") {
5213
- return "";
4833
+ if (composerEdit && canEdit) {
4834
+ return /* @__PURE__ */ jsx(
4835
+ ComposerInlineHtml,
4836
+ {
4837
+ name: editName,
4838
+ html,
4839
+ sourceValue: typeof fieldValue === "string" ? fieldValue : html,
4840
+ className,
4841
+ Tag,
4842
+ layoutNodeId: context?.layoutNodeId,
4843
+ componentId: context?.componentId,
4844
+ fieldRef: ref
4845
+ }
4846
+ );
5214
4847
  }
4848
+ return /* @__PURE__ */ jsx(Tag, { className, dangerouslySetInnerHTML: { __html: html } });
4849
+ }
4850
+ function isPortableImageValue(value) {
4851
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
4852
+ const url = value.url;
4853
+ return typeof url === "string" && url.trim().length > 0;
4854
+ }
4855
+ function imageSrc(value) {
4856
+ if (typeof value === "string") return value.trim();
4857
+ if (isPortableImageValue(value)) return value.url.trim();
5215
4858
  return "";
5216
4859
  }
5217
- var FIELD_SCALAR_HINT = "Field expects a scalar field. Did you mean <Field field={post.title} />?";
5218
- function warnNotScalarField(component, field, fieldValue) {
5219
- if (process.env.NODE_ENV === "production") return false;
5220
- if (isBrandedFields(field)) {
5221
- console.error(`[AmplifyUp SDK] ${component}: ${FIELD_SCALAR_HINT}`);
5222
- return true;
5223
- }
5224
- if (isFieldEnvelope(field) && Array.isArray(field.value)) {
5225
- console.error(`[AmplifyUp SDK] ${component}: ${FIELD_SCALAR_HINT}`);
5226
- return true;
5227
- }
5228
- if (Array.isArray(fieldValue)) {
5229
- console.error(`[AmplifyUp SDK] ${component}: ${FIELD_SCALAR_HINT}`);
5230
- return true;
4860
+ function leafText(field) {
4861
+ if (isFieldEnvelope(field)) return field.value;
4862
+ return field;
4863
+ }
4864
+ function coerceImageField(field, value, name) {
4865
+ if (isFieldEnvelope(field)) return { field, value, name };
4866
+ if (!isBrandedFields(field) || !field || typeof field !== "object") {
4867
+ return { field: void 0, value, name };
5231
4868
  }
5232
- return false;
4869
+ const bag = field;
4870
+ const urlField = bag.url;
4871
+ const urlName = isFieldEnvelope(urlField) && typeof urlField.name === "string" ? urlField.name.replace(/\.url$/, "") : "";
4872
+ const editName = urlName || name || "";
4873
+ if (!editName) return { field: void 0, value, name };
4874
+ const ref = isFieldEnvelope(urlField) ? urlField.ref : void 0;
4875
+ const width = leafText(bag.width);
4876
+ const height = leafText(bag.height);
4877
+ return {
4878
+ field: {
4879
+ value: {
4880
+ url: String(leafText(urlField) ?? ""),
4881
+ alt: leafText(bag.alt),
4882
+ ...typeof width === "number" ? { width } : {},
4883
+ ...typeof height === "number" ? { height } : {}
4884
+ },
4885
+ name: editName,
4886
+ ...ref ? { ref } : {}
4887
+ },
4888
+ value,
4889
+ name: editName
4890
+ };
5233
4891
  }
5234
- function assertNamedEnvelope(component, field) {
5235
- if (process.env.NODE_ENV === "production") return;
5236
- if (!field || typeof field !== "object" || Array.isArray(field)) return;
5237
- const rec = field;
5238
- if (!("value" in rec)) return;
5239
- if (typeof rec.name === "string" && rec.name) return;
5240
- throw new Error(
5241
- `[AmplifyUp SDK] ${component} received an envelope-shaped object with a \`value\` but no \`name\` \u2014 a partial envelope was manufactured upstream (keys: ${Object.keys(
5242
- rec
5243
- ).join(", ")}). Find the producer; do not strip or rebuild envelopes.`
4892
+ function Image(props) {
4893
+ const {
4894
+ field,
4895
+ value,
4896
+ name,
4897
+ alt: altProp,
4898
+ className,
4899
+ width: widthProp,
4900
+ height: heightProp,
4901
+ ...imgProps
4902
+ } = props;
4903
+ const context = useContext(ComponentContext);
4904
+ assertNamedEnvelope("Image", field);
4905
+ const coerced = coerceImageField(field, value, name);
4906
+ const boundField = coerced.field;
4907
+ const hasField = isFieldEnvelope(boundField);
4908
+ const hasValue = hasOwnProp(props, "value");
4909
+ const { editName, fieldValue, ref } = useBoundField(
4910
+ boundField,
4911
+ coerced.value,
4912
+ coerced.name,
4913
+ "Image"
5244
4914
  );
5245
- }
5246
- var warnedReadOnlyFields = /* @__PURE__ */ new Set();
5247
- function warnReadOnlyRowField(name) {
5248
- if (process.env.NODE_ENV === "production") return;
5249
- const key = name || "(unnamed)";
5250
- if (warnedReadOnlyFields.has(key)) return;
5251
- warnedReadOnlyFields.add(key);
5252
- console.warn(
5253
- `[AmplifyUp SDK] ${key} has no write target; rendered read-only.`
4915
+ const composerEdit = useComposerEditMode();
4916
+ warnProjectionProps("Image", hasField || isBrandedFields(field), hasValue, coerced.name || name);
4917
+ if (!isBrandedFields(field) && warnNotScalarField("Image", boundField, fieldValue)) {
4918
+ return null;
4919
+ }
4920
+ if (!hasField && !hasValue && !name && !editName) {
4921
+ return null;
4922
+ }
4923
+ const src = imageSrc(fieldValue);
4924
+ const portable = isPortableImageValue(fieldValue) ? fieldValue : null;
4925
+ const alt = altProp ?? portable?.alt ?? "";
4926
+ const width = widthProp ?? portable?.width;
4927
+ const height = heightProp ?? portable?.height;
4928
+ const fieldAttrs = composerEdit && editName && canComposerBind(boundField, ref, editName) ? {
4929
+ "data-amplifyup-field": editName,
4930
+ "data-amplifyup-field-type": "image",
4931
+ "data-amplifyup-node-id": context?.layoutNodeId || void 0,
4932
+ "data-amplifyup-ref-provider": ref?.providerId || void 0,
4933
+ "data-amplifyup-ref-entity": ref?.entity || void 0,
4934
+ "data-amplifyup-ref-id": ref?.id || void 0
4935
+ } : null;
4936
+ if (composerEdit && !editName && (hasField || hasValue)) {
4937
+ console.warn(
4938
+ '[AmplifyUp SDK] Image value={\u2026} requires name="\u2026" for computed values'
4939
+ );
4940
+ }
4941
+ if (!src) {
4942
+ if (!composerEdit || !fieldAttrs) return null;
4943
+ return /* @__PURE__ */ jsx(
4944
+ "span",
4945
+ {
4946
+ ...fieldAttrs,
4947
+ className,
4948
+ role: "img",
4949
+ "aria-label": alt || editName || "Image",
4950
+ style: {
4951
+ display: "block",
4952
+ boxSizing: "border-box",
4953
+ minWidth: width ? void 0 : 120,
4954
+ minHeight: height ? void 0 : 80,
4955
+ width: width || "100%",
4956
+ height: height || void 0,
4957
+ background: "color-mix(in srgb, currentColor 8%, transparent)",
4958
+ cursor: "pointer"
4959
+ }
4960
+ }
4961
+ );
4962
+ }
4963
+ return /* @__PURE__ */ jsx(
4964
+ "img",
4965
+ {
4966
+ ...imgProps,
4967
+ ...fieldAttrs,
4968
+ src,
4969
+ alt,
4970
+ className,
4971
+ width,
4972
+ height,
4973
+ style: {
4974
+ ...typeof imgProps.style === "object" && imgProps.style ? imgProps.style : {},
4975
+ ...composerEdit && fieldAttrs ? { cursor: "pointer" } : null
4976
+ }
4977
+ }
5254
4978
  );
5255
4979
  }
5256
- function canComposerBind(field, ref, editName) {
5257
- if (isReadOnlyRowField(field) || isFieldEnvelope(field) && field.readOnly) {
5258
- warnReadOnlyRowField(editName || (isFieldEnvelope(field) ? field.name : ""));
5259
- return false;
4980
+
4981
+ // src/component-key.ts
4982
+ var componentKey = (id) => id.toLowerCase().replace(/[^a-z0-9]/g, "");
4983
+ var REGISTRY_BRAND = Symbol.for("amplifyup.componentRegistry");
4984
+ var defineComponentRegistry = (components) => {
4985
+ const index = /* @__PURE__ */ new Map();
4986
+ for (const [name, component] of Object.entries(components)) {
4987
+ const key = componentKey(name);
4988
+ if (index.has(key)) {
4989
+ throw new Error(
4990
+ `[Amplify UP] Component registry has two components named like "${name}". Rebuild it with withAmplifyUp or \`amplifyup registry\`.`
4991
+ );
4992
+ }
4993
+ index.set(key, component);
5260
4994
  }
5261
- return true;
5262
- }
5263
- function warnProjectionProps(component, hasField, hasValue, name) {
5264
- if (process.env.NODE_ENV === "production") return;
5265
- if (!hasField && !hasValue && !name) {
5266
- console.warn(
5267
- `[AmplifyUp SDK] ${component} needs field={fields.yourProp} (or value + name for computed values)`
4995
+ return {
4996
+ [REGISTRY_BRAND]: true,
4997
+ components,
4998
+ resolve: (componentId) => index.get(componentKey(componentId))
4999
+ };
5000
+ };
5001
+ var isComponentRegistry = (value) => !!value && typeof value === "object" && value[REGISTRY_BRAND] === true;
5002
+ var warnedMissing = /* @__PURE__ */ new Set();
5003
+ var warnMissingOnce = (componentId) => {
5004
+ if (warnedMissing.has(componentId)) return;
5005
+ warnedMissing.add(componentId);
5006
+ console.warn(
5007
+ `[Amplify UP] No component in your component registry matches "${componentId}". Add a file with that name to your components folder.`
5008
+ );
5009
+ };
5010
+ var MissingComponentHint = ({ componentId }) => /* @__PURE__ */ jsxs(
5011
+ "div",
5012
+ {
5013
+ "data-amplifyup-missing-component": componentId,
5014
+ style: {
5015
+ margin: "0.5rem 0",
5016
+ padding: "0.75rem 1rem",
5017
+ border: "1.5px dashed currentColor",
5018
+ borderRadius: 8,
5019
+ opacity: 0.7,
5020
+ fontSize: 14,
5021
+ textAlign: "center"
5022
+ },
5023
+ children: [
5024
+ "\u201C",
5025
+ componentId,
5026
+ "\u201D isn\u2019t set up on this site yet."
5027
+ ]
5028
+ }
5029
+ );
5030
+ var RegistryComponent = ({
5031
+ registry,
5032
+ componentId,
5033
+ props,
5034
+ slots,
5035
+ layoutNodeId,
5036
+ composerPreview
5037
+ }) => {
5038
+ const Component2 = registry.resolve(componentId);
5039
+ if (!Component2) {
5040
+ warnMissingOnce(componentId);
5041
+ return composerPreview ? /* @__PURE__ */ jsx(MissingComponentHint, { componentId }) : null;
5042
+ }
5043
+ return /* @__PURE__ */ jsx(
5044
+ ComponentContextProvider,
5045
+ {
5046
+ props,
5047
+ slots,
5048
+ layoutNodeId,
5049
+ componentId,
5050
+ children: /* @__PURE__ */ jsx(Component2, { ...props })
5051
+ }
5052
+ );
5053
+ };
5054
+ var assertComponentRegistry = (owner, props) => {
5055
+ if ("renderComponent" in props) {
5056
+ throw new Error(
5057
+ `[Amplify UP] ${owner}: renderComponent was removed in @amplifyup/sdk 0.2.0. Components now load automatically \u2014 wrap next.config with withAmplifyUp and render <AmplifyPage /> from the generated component registry. See "Upgrading from 0.1" in the SDK README.`
5268
5058
  );
5269
5059
  }
5060
+ if (!isComponentRegistry(props.registry)) {
5061
+ throw new Error(
5062
+ `[Amplify UP] ${owner} needs your component registry. Render <AmplifyPage /> from the generated .amplifyup/component-registry module (created by withAmplifyUp or \`amplifyup registry\`).`
5063
+ );
5064
+ }
5065
+ };
5066
+ function nodeRenderProps(node) {
5067
+ const settings = node.settings || {};
5068
+ const hydrated = hydratePageResourceProps(
5069
+ node.props || {},
5070
+ getPageResourceFields()
5071
+ );
5072
+ const fields = hydrated.fields;
5073
+ const branded = isBrandedFields(fields) ? fields : brandFields(
5074
+ fields && typeof fields === "object" ? fields : {}
5075
+ );
5076
+ return {
5077
+ ...settings,
5078
+ ...hydrated,
5079
+ fields: branded
5080
+ };
5270
5081
  }
5271
- function hasOwnProp(props, key) {
5272
- return Object.prototype.hasOwnProperty.call(props, key);
5273
- }
5274
- function Field(props) {
5275
- const { field, value, name, className } = props;
5276
- const context = useContext(ComponentContext);
5277
- const composerEdit = useComposerEditMode();
5278
- const hasField = isFieldEnvelope(field);
5279
- const hasValue = hasOwnProp(props, "value");
5280
- const { editName, fieldValue, ref } = useBoundField(field, value, name, "Field");
5281
- assertNamedEnvelope("Field", field);
5282
- warnProjectionProps("Field", hasField, hasValue, name);
5283
- if (warnNotScalarField("Field", field, fieldValue)) {
5284
- return null;
5082
+ var ComponentRenderBoundary = class extends Component {
5083
+ constructor() {
5084
+ super(...arguments);
5085
+ this.state = { error: null };
5285
5086
  }
5286
- if (!hasField && !hasValue && !name) {
5287
- return null;
5087
+ static getDerivedStateFromError(error) {
5088
+ return { error };
5288
5089
  }
5289
- if (isBrandedFields(field) || Array.isArray(fieldValue)) {
5290
- return null;
5090
+ componentDidCatch(error) {
5091
+ console.error(
5092
+ `[AmplifyRenderer] "${this.props.componentId}" (${this.props.nodeId}) threw while rendering:`,
5093
+ error
5094
+ );
5291
5095
  }
5292
- const empty = isComposerEmptyText(fieldValue);
5293
- const bindComposer = composerEdit && editName && context && canInlineEdit(editName, fieldValue) && canComposerBind(field, ref, editName);
5294
- if (bindComposer) {
5295
- return /* @__PURE__ */ jsx(
5296
- ComposerInlineField,
5297
- {
5298
- name: editName,
5299
- value: fieldValue,
5300
- className,
5301
- layoutNodeId: context.layoutNodeId,
5302
- componentId: context.componentId,
5303
- fieldRef: ref,
5304
- rich: looksLikeRichCanvasField(editName)
5096
+ render() {
5097
+ if (this.state.error) {
5098
+ if (process.env.NODE_ENV !== "production") {
5099
+ return /* @__PURE__ */ jsxs(
5100
+ "div",
5101
+ {
5102
+ "data-amplifyup-render-error": "",
5103
+ "data-component-id": this.props.componentId,
5104
+ "data-node-id": this.props.nodeId,
5105
+ style: {
5106
+ margin: "1rem 0",
5107
+ padding: "0.75rem 1rem",
5108
+ border: "1px solid #fca5a5",
5109
+ borderRadius: "0.5rem",
5110
+ background: "#fef2f2",
5111
+ color: "#991b1b",
5112
+ fontSize: "0.875rem"
5113
+ },
5114
+ children: [
5115
+ 'Component "',
5116
+ this.props.componentId,
5117
+ '" failed to render:',
5118
+ " ",
5119
+ this.state.error.message
5120
+ ]
5121
+ }
5122
+ );
5123
+ }
5124
+ return null;
5125
+ }
5126
+ return this.props.children;
5127
+ }
5128
+ };
5129
+ function NodeWithFields({
5130
+ nodeId,
5131
+ componentId,
5132
+ props,
5133
+ slots,
5134
+ registry,
5135
+ composerPreview
5136
+ }) {
5137
+ return /* @__PURE__ */ jsx(MaybeComposerProvider, { enabled: !!composerPreview, layoutNodeId: nodeId, children: /* @__PURE__ */ jsx(
5138
+ RegistryComponent,
5139
+ {
5140
+ registry,
5141
+ componentId,
5142
+ props,
5143
+ slots,
5144
+ layoutNodeId: nodeId,
5145
+ composerPreview: !!composerPreview
5146
+ }
5147
+ ) });
5148
+ }
5149
+ function AmplifyRendererInner(rendererProps) {
5150
+ assertComponentRegistry("AmplifyRenderer", rendererProps);
5151
+ const {
5152
+ registry,
5153
+ pageConfig: serverPageConfig,
5154
+ loadingComponent,
5155
+ errorComponent,
5156
+ emptyComponent,
5157
+ composerPreview
5158
+ } = rendererProps;
5159
+ const clientHook = useAmplifyUp();
5160
+ useRegisterPageContent(!serverPageConfig);
5161
+ const composerPreviewFlag = useComposerPreviewFlag(!!composerPreview);
5162
+ const pageConfig = serverPageConfig || clientHook.pageConfig || null;
5163
+ const loading = serverPageConfig ? false : clientHook.loading;
5164
+ const error = serverPageConfig ? null : clientHook.error;
5165
+ const contentSource = clientHook.source;
5166
+ const [variantCache, setVariantCache] = useState({});
5167
+ useEffect(() => {
5168
+ if (typeof window !== "undefined") {
5169
+ if (window.__AMPLIFYUP_PREVIEW_MODE__ === true) {
5170
+ return;
5171
+ }
5172
+ if (window.location.pathname.includes("/api/pages/proxy")) {
5173
+ return;
5174
+ }
5175
+ if (window.self !== window.top) {
5176
+ return;
5177
+ }
5178
+ const urlParams = new URLSearchParams(window.location.search);
5179
+ if (urlParams.get("preview") === "true" || urlParams.get("visualEditor") === "true") {
5180
+ return;
5181
+ }
5182
+ if (window.location.href.includes("preview=true") || window.location.href.includes("visualEditor=true")) {
5183
+ return;
5184
+ }
5185
+ }
5186
+ if (pageConfig && pageConfig.id !== "default") {
5187
+ trackContentView(pageConfig.id, "page", {
5188
+ route: pageConfig.route,
5189
+ title: pageConfig.title
5190
+ });
5191
+ }
5192
+ }, [pageConfig]);
5193
+ useEffect(() => {
5194
+ if (!pageConfig?.eventTracking?.length) return;
5195
+ const sdk = getSDK();
5196
+ if (!sdk.isInitialized()) return;
5197
+ sdk.setupEventTracking(pageConfig.eventTracking);
5198
+ const t1 = window.setTimeout(() => {
5199
+ sdk.setupComponentViewTracking();
5200
+ refreshEventTracking();
5201
+ }, 200);
5202
+ const t2 = window.setTimeout(() => {
5203
+ sdk.setupComponentViewTracking();
5204
+ refreshEventTracking();
5205
+ }, 1e3);
5206
+ return () => {
5207
+ window.clearTimeout(t1);
5208
+ window.clearTimeout(t2);
5209
+ };
5210
+ }, [pageConfig?.id, pageConfig?.eventTracking]);
5211
+ useEffect(() => {
5212
+ if (!pageConfig) return;
5213
+ const t = window.setTimeout(() => {
5214
+ getSDK().setupComponentViewTracking();
5215
+ refreshEventTracking();
5216
+ }, 100);
5217
+ return () => window.clearTimeout(t);
5218
+ }, [variantCache, pageConfig?.id]);
5219
+ useEffect(() => {
5220
+ if (!isComposerPreview()) {
5221
+ return;
5222
+ }
5223
+ if (!pageConfig) {
5224
+ return;
5225
+ }
5226
+ const rawTree2 = pageConfig.layoutTree;
5227
+ const normalizedTree = Array.isArray(rawTree2) ? rawTree2 : rawTree2 && typeof rawTree2 === "object" && rawTree2.componentId ? [rawTree2] : [];
5228
+ if (normalizedTree.length === 0) {
5229
+ if (typeof window !== "undefined" && window.parent && window.parent !== window) {
5230
+ window.parent.postMessage({
5231
+ type: "COMPONENT_TREE",
5232
+ tree: []
5233
+ }, "*");
5305
5234
  }
5235
+ return;
5236
+ }
5237
+ const convertLayoutTreeToComponentTree = (nodes, parentId = null) => {
5238
+ const result = [];
5239
+ nodes.forEach((node) => {
5240
+ if (!node) return;
5241
+ const treeNode = {
5242
+ id: node.id,
5243
+ componentId: node.componentId,
5244
+ componentName: node.componentId,
5245
+ // Will be enhanced with actual name if available
5246
+ parentId,
5247
+ children: []
5248
+ };
5249
+ if (node.slots && node.slots.length > 0) {
5250
+ node.slots.forEach((slot) => {
5251
+ const kids = Array.isArray(slot?.children) ? slot.children : [];
5252
+ if (kids.length > 0) {
5253
+ const slotChildren = convertLayoutTreeToComponentTree(kids, node.id);
5254
+ treeNode.children.push(...slotChildren);
5255
+ }
5256
+ });
5257
+ }
5258
+ result.push(treeNode);
5259
+ });
5260
+ return result;
5261
+ };
5262
+ const layoutTree2 = normalizedTree;
5263
+ const componentTree = convertLayoutTreeToComponentTree(layoutTree2);
5264
+ const describeLayoutTree = (nodes, depth = 0) => {
5265
+ if (!nodes?.length) return "";
5266
+ const indent = " ".repeat(depth);
5267
+ return nodes.map((n) => {
5268
+ const slotsDesc = (n.slots || []).map((s) => {
5269
+ const childCount = Array.isArray(s.children) ? s.children.length : 0;
5270
+ const childrenDesc = childCount > 0 ? describeLayoutTree(s.children || [], depth + 1) : "";
5271
+ return `${indent} slot "${s.slotId || s.slotName || "?"}" (${childCount} children)${childrenDesc ? "\n" + childrenDesc : ""}`;
5272
+ }).join("\n");
5273
+ return `${indent}- ${n.id} (${n.componentId || "?"})${slotsDesc ? "\n" + slotsDesc : ""}`;
5274
+ }).join("\n");
5275
+ };
5276
+ sdkDebugOnce(
5277
+ `layoutTree:${pageConfig?.id || ""}:${pageConfig?.route || ""}`,
5278
+ "[AmplifyRenderer] layoutTree received:\n%s",
5279
+ describeLayoutTree(layoutTree2)
5306
5280
  );
5281
+ if (typeof window !== "undefined" && window.parent && window.parent !== window) {
5282
+ const message = {
5283
+ type: "COMPONENT_TREE",
5284
+ tree: componentTree
5285
+ };
5286
+ window.parent.postMessage(message, "*");
5287
+ sdkDebug(
5288
+ "[AmplifyRenderer] Sent component tree from layoutTree:",
5289
+ componentTree.length,
5290
+ "root components"
5291
+ );
5292
+ }
5293
+ }, [pageConfig]);
5294
+ useEffect(() => {
5295
+ if (!pageConfig?.layoutTree || !pageConfig.layoutId) return;
5296
+ const roots = pageConfig.layoutTree;
5297
+ const fromEdge = contentSource === "edge" || roots.some((n) => n._contentSource === "edge");
5298
+ if (fromEdge) return;
5299
+ const sdk = getSDK();
5300
+ const instanceId = sdk.getInstanceId();
5301
+ const decisionApiUrl = sdk.getDecisionApiUrl();
5302
+ const orchestratorUrl = sdk.getOrchestratorUrl();
5303
+ if (!decisionApiUrl && !orchestratorUrl || !instanceId) return;
5304
+ const fetchVariants = async () => {
5305
+ const nodes = pageConfig.layoutTree;
5306
+ const newCache = {};
5307
+ const findZonedSlots = (nodeList) => {
5308
+ const results = [];
5309
+ for (const node of nodeList) {
5310
+ if (node.slots) {
5311
+ for (const slot of node.slots) {
5312
+ if (slot.zoneId && slot.variants) {
5313
+ const key = `${node.id}-${slot.slotId}`;
5314
+ results.push({ node, slot, key });
5315
+ }
5316
+ }
5317
+ }
5318
+ }
5319
+ return results;
5320
+ };
5321
+ const zonedSlots = findZonedSlots(nodes);
5322
+ await Promise.all(
5323
+ zonedSlots.map(async ({ node, slot, key }) => {
5324
+ try {
5325
+ let personalizationUrl;
5326
+ if (decisionApiUrl) {
5327
+ const url = new URL(decisionApiUrl);
5328
+ url.searchParams.set("instanceId", instanceId);
5329
+ const zoneId = slot.zoneId;
5330
+ if (zoneId) {
5331
+ url.searchParams.set("zoneId", zoneId);
5332
+ }
5333
+ const campaignId = slot.campaignId;
5334
+ if (campaignId) {
5335
+ url.searchParams.set("campaignId", campaignId);
5336
+ }
5337
+ personalizationUrl = url.toString();
5338
+ } else if (orchestratorUrl) {
5339
+ personalizationUrl = `${orchestratorUrl}/api/personalization/variant?instanceId=${encodeURIComponent(instanceId)}&layoutId=${encodeURIComponent(pageConfig.layoutId)}&slotId=${encodeURIComponent(slot.slotId)}&nodeId=${encodeURIComponent(node.id)}`;
5340
+ } else {
5341
+ return;
5342
+ }
5343
+ const response = await fetch(personalizationUrl);
5344
+ if (response.ok) {
5345
+ const data = await response.json();
5346
+ if (data.variantId && data.componentTree) {
5347
+ newCache[key] = {
5348
+ variantId: data.variantId,
5349
+ children: data.componentTree
5350
+ };
5351
+ if (typeof window !== "undefined") {
5352
+ if (window.__AMPLIFYUP_PREVIEW_MODE__ === true) {
5353
+ return;
5354
+ }
5355
+ if (window.location.pathname.includes("/api/pages/proxy")) {
5356
+ return;
5357
+ }
5358
+ if (window.self !== window.top) {
5359
+ return;
5360
+ }
5361
+ }
5362
+ sdk.track("Zone Impression", {
5363
+ zoneId: slot.zoneId,
5364
+ variantId: data.variantId,
5365
+ layoutId: pageConfig.layoutId,
5366
+ route: pageConfig.route
5367
+ });
5368
+ } else {
5369
+ const defaultVariant = slot.variants?.find((v) => v.isDefault);
5370
+ if (defaultVariant) {
5371
+ newCache[key] = {
5372
+ variantId: defaultVariant.variantId,
5373
+ children: defaultVariant.children
5374
+ };
5375
+ }
5376
+ }
5377
+ }
5378
+ } catch (err) {
5379
+ console.error(`Error fetching variant for slot ${key}:`, err);
5380
+ const defaultVariant = slot.variants?.find((v) => v.isDefault);
5381
+ if (defaultVariant) {
5382
+ newCache[key] = {
5383
+ variantId: defaultVariant.variantId,
5384
+ children: defaultVariant.children
5385
+ };
5386
+ }
5387
+ }
5388
+ })
5389
+ );
5390
+ setVariantCache(newCache);
5391
+ };
5392
+ fetchVariants();
5393
+ }, [pageConfig?.layoutTree, pageConfig?.layoutId, pageConfig?.route, contentSource]);
5394
+ if (loading) {
5395
+ return /* @__PURE__ */ jsx(Fragment, { children: loadingComponent || /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse", children: [
5396
+ /* @__PURE__ */ jsx("div", { className: "h-8 bg-gray-200 rounded w-1/4 mb-4" }),
5397
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-1/2 mb-8" }),
5398
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
5399
+ /* @__PURE__ */ jsx("div", { className: "h-64 bg-gray-200 rounded" }),
5400
+ /* @__PURE__ */ jsx("div", { className: "h-32 bg-gray-200 rounded" })
5401
+ ] })
5402
+ ] }) }) }) });
5307
5403
  }
5308
- if (empty) return null;
5309
- const text = formatFieldValue(fieldValue);
5310
- if (!text) return null;
5311
- return /* @__PURE__ */ jsx("span", { className, children: text });
5312
- }
5313
- function markdownToHtml(markdown) {
5314
- try {
5315
- const result = marked.parse(markdown, { async: false });
5316
- return typeof result === "string" ? result : "";
5317
- } catch {
5318
- return markdown;
5319
- }
5320
- }
5321
- function RichText(props) {
5322
- const {
5323
- field,
5324
- value,
5325
- name,
5326
- className,
5327
- as: Tag = "div",
5328
- children
5329
- } = props;
5330
- const context = useContext(ComponentContext);
5331
- const composerEdit = useComposerEditMode();
5332
- const childrenValue = typeof children === "string" || typeof children === "number" ? String(children) : void 0;
5333
- const hasField = isFieldEnvelope(field);
5334
- const hasValueProp = hasOwnProp(props, "value") || childrenValue !== void 0;
5335
- const boundValue = hasOwnProp(props, "value") ? value : childrenValue !== void 0 ? childrenValue : value;
5336
- const { editName, fieldValue, ref } = useBoundField(
5337
- field,
5338
- boundValue,
5339
- name,
5340
- "RichText"
5341
- );
5342
- assertNamedEnvelope("RichText", field);
5343
- if (!hasField && !hasValueProp && !name) {
5344
- return null;
5404
+ if (error) {
5405
+ return /* @__PURE__ */ jsx(Fragment, { children: errorComponent ? errorComponent(error) : /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsxs("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6", children: [
5406
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-red-900 mb-2", children: "Error Loading Page" }),
5407
+ /* @__PURE__ */ jsx("p", { className: "text-red-700", children: error })
5408
+ ] }) }) }) });
5345
5409
  }
5346
- warnProjectionProps("RichText", hasField, hasValueProp, name);
5347
- if (warnNotScalarField("RichText", field, fieldValue)) {
5410
+ if (!pageConfig) {
5348
5411
  return null;
5349
5412
  }
5350
- const canEdit = !!context && canInlineEditRichText(editName, fieldValue) && canComposerBind(field, ref, editName);
5351
- if (isComposerEmptyText(fieldValue)) {
5352
- if (composerEdit && canEdit) {
5413
+ pageConfig.layout?.header !== false;
5414
+ pageConfig.layout?.footer !== false;
5415
+ const renderNode = (node) => {
5416
+ const zoneIdFromProps = node.componentId === "AmplifyZone" ? String(node.props?.zoneId || "") : "";
5417
+ if (node.componentId === "AmplifyZone") {
5418
+ const contentSlot = node.slots?.find((s) => s.slotId === "content") || node.slots?.[0];
5419
+ const children = Array.isArray(contentSlot?.children) ? contentSlot.children : [];
5353
5420
  return /* @__PURE__ */ jsx(
5354
- ComposerInlineField,
5421
+ "div",
5355
5422
  {
5356
- name: editName,
5357
- value: fieldValue,
5358
- className,
5359
- layoutNodeId: context?.layoutNodeId,
5360
- componentId: context?.componentId,
5361
- fieldRef: ref,
5362
- rich: true
5423
+ "data-node-id": node.id,
5424
+ "data-amplifyup-node": "",
5425
+ "data-amplifyup-component": "AmplifyZone",
5426
+ "data-amplifyup-zone": zoneIdFromProps || void 0,
5427
+ "data-zone-id": zoneIdFromProps || void 0,
5428
+ children: /* @__PURE__ */ jsx(
5429
+ "div",
5430
+ {
5431
+ "data-slot-id": "content",
5432
+ "data-amplifyup-slot": "content",
5433
+ "data-parent-node-id": node.id,
5434
+ "data-parent-component-id": "AmplifyZone",
5435
+ children: children.filter(Boolean).map((child) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(child) }, child.id))
5436
+ }
5437
+ )
5363
5438
  }
5364
5439
  );
5365
5440
  }
5366
- return null;
5367
- }
5368
- let html = "";
5369
- if (typeof fieldValue === "string") {
5370
- const trimmed = fieldValue.trim();
5371
- if (trimmed.startsWith("<") && trimmed.includes(">")) {
5372
- html = fieldValue;
5373
- } else {
5374
- html = markdownToHtml(fieldValue);
5375
- }
5376
- } else {
5377
- const text = formatFieldValue(fieldValue);
5378
- html = text ? markdownToHtml(text) : "";
5379
- }
5380
- if (!html) {
5381
- return null;
5382
- }
5383
- if (composerEdit && canEdit) {
5441
+ let slotChildren = {};
5442
+ sdkDebugOnce(`node:${node.id}`, `[AmplifyRenderer] Rendering node ${node.id} (${node.componentId})`, {
5443
+ hasSlots: !!(node.slots && node.slots.length > 0),
5444
+ slotCount: node.slots?.length || 0,
5445
+ slots: node.slots?.map((s) => ({ slotId: s.slotId, zoneId: s.zoneId, childrenCount: s.children?.length || 0 }))
5446
+ });
5447
+ if (node.slots && node.slots.length > 0) {
5448
+ for (const slot of node.slots) {
5449
+ const slotKey = `${node.id}-${slot.slotId}`;
5450
+ let childrenToRender = [];
5451
+ if (slot.zoneId && slot.variants && variantCache[slotKey]) {
5452
+ childrenToRender = variantCache[slotKey].children;
5453
+ } else if (slot.zoneId && slot.variants) {
5454
+ const defaultVariant = slot.variants.find((v) => v.isDefault);
5455
+ childrenToRender = defaultVariant?.children || [];
5456
+ } else {
5457
+ childrenToRender = Array.isArray(slot.children) ? slot.children : [];
5458
+ }
5459
+ const safeChildren = Array.isArray(childrenToRender) ? childrenToRender : [];
5460
+ slotChildren[slot.slotId] = /* @__PURE__ */ jsx(
5461
+ "div",
5462
+ {
5463
+ "data-slot-id": slot.slotId,
5464
+ "data-amplifyup-slot": slot.slotId,
5465
+ "data-zone-id": slot.zoneId || void 0,
5466
+ "data-parent-node-id": node.id,
5467
+ "data-parent-component-id": node.componentId,
5468
+ children: safeChildren.filter(Boolean).map((child) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(child) }, child.id))
5469
+ },
5470
+ slot.slotId
5471
+ );
5472
+ }
5473
+ }
5474
+ const slotsToPass = Object.keys(slotChildren).length > 0 ? slotChildren : void 0;
5384
5475
  return /* @__PURE__ */ jsx(
5385
- ComposerInlineHtml,
5476
+ "div",
5386
5477
  {
5387
- name: editName,
5388
- html,
5389
- sourceValue: typeof fieldValue === "string" ? fieldValue : html,
5390
- className,
5391
- Tag,
5392
- layoutNodeId: context?.layoutNodeId,
5393
- componentId: context?.componentId,
5394
- fieldRef: ref
5478
+ "data-node-id": node.id,
5479
+ "data-amplifyup-node": "",
5480
+ "data-component-id": node.componentId,
5481
+ "data-amplifyup-component": node.componentId,
5482
+ children: /* @__PURE__ */ jsx(
5483
+ ComponentRenderBoundary,
5484
+ {
5485
+ componentId: node.componentId,
5486
+ nodeId: node.id,
5487
+ children: /* @__PURE__ */ jsx(
5488
+ NodeWithFields,
5489
+ {
5490
+ nodeId: node.id,
5491
+ componentId: node.componentId,
5492
+ props: nodeRenderProps(node),
5493
+ slots: slotsToPass,
5494
+ registry,
5495
+ composerPreview: composerPreviewFlag
5496
+ }
5497
+ )
5498
+ }
5499
+ )
5395
5500
  }
5396
5501
  );
5502
+ };
5503
+ const rawTree = pageConfig.layoutTree;
5504
+ const layoutTree = Array.isArray(rawTree) ? rawTree : rawTree && typeof rawTree === "object" && rawTree.componentId ? [rawTree] : [];
5505
+ if (layoutTree.length === 0) {
5506
+ return /* @__PURE__ */ jsx("main", { children: emptyComponent || /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No content configured for this page." }) }) });
5397
5507
  }
5398
- return /* @__PURE__ */ jsx(Tag, { className, dangerouslySetInnerHTML: { __html: html } });
5508
+ return /* @__PURE__ */ jsx(ComposerProvider, { children: /* @__PURE__ */ jsx(
5509
+ "main",
5510
+ {
5511
+ "data-slot-id": composerPreviewFlag ? "main" : void 0,
5512
+ "data-amplifyup-slot": composerPreviewFlag ? "main" : void 0,
5513
+ "data-slot-source": composerPreviewFlag ? "page" : void 0,
5514
+ "data-slot-state": composerPreviewFlag ? "filled" : void 0,
5515
+ children: layoutTree.map((node) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(node) }, node.id))
5516
+ }
5517
+ ) });
5399
5518
  }
5400
- function isPortableImageValue(value) {
5401
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
5402
- const url = value.url;
5403
- return typeof url === "string" && url.trim().length > 0;
5519
+ var AmplifyRenderer = memo(AmplifyRendererInner);
5520
+ function previewPageSlot(state) {
5521
+ return /* @__PURE__ */ jsx(
5522
+ "div",
5523
+ {
5524
+ "data-slot-id": "main",
5525
+ "data-amplifyup-slot": "main",
5526
+ "data-slot-source": "page",
5527
+ "data-slot-state": state,
5528
+ "data-slot-empty": state === "empty" ? "true" : void 0,
5529
+ style: {
5530
+ minHeight: state === "empty" ? "50vh" : void 0,
5531
+ width: "100%",
5532
+ display: "block",
5533
+ position: "relative"
5534
+ },
5535
+ children: state === "empty" ? /* @__PURE__ */ jsx(EmptySlotHint, {}) : null
5536
+ }
5537
+ );
5404
5538
  }
5405
- function imageSrc(value) {
5406
- if (typeof value === "string") return value.trim();
5407
- if (isPortableImageValue(value)) return value.url.trim();
5408
- return "";
5539
+ function hasAmplifyLayout(pageConfig) {
5540
+ return !!(pageConfig && pageConfig.id !== "default" && Array.isArray(pageConfig.layoutTree) && pageConfig.layoutTree.length > 0);
5409
5541
  }
5410
- function leafText(field) {
5411
- if (isFieldEnvelope(field)) return field.value;
5412
- return field;
5542
+ function normalizeRoutePath(route) {
5543
+ if (!route) return "";
5544
+ const path = route.split("?")[0] || "/";
5545
+ if (path.length > 1 && path.endsWith("/")) return path.replace(/\/+$/, "");
5546
+ return path || "/";
5413
5547
  }
5414
- function coerceImageField(field, value, name) {
5415
- if (isFieldEnvelope(field)) return { field, value, name };
5416
- if (!isBrandedFields(field) || !field || typeof field !== "object") {
5417
- return { field: void 0, value, name };
5418
- }
5419
- const bag = field;
5420
- const urlField = bag.url;
5421
- const urlName = isFieldEnvelope(urlField) && typeof urlField.name === "string" ? urlField.name.replace(/\.url$/, "") : "";
5422
- const editName = urlName || name || "";
5423
- if (!editName) return { field: void 0, value, name };
5424
- const ref = isFieldEnvelope(urlField) ? urlField.ref : void 0;
5425
- const width = leafText(bag.width);
5426
- const height = leafText(bag.height);
5427
- return {
5428
- field: {
5429
- value: {
5430
- url: String(leafText(urlField) ?? ""),
5431
- alt: leafText(bag.alt),
5432
- ...typeof width === "number" ? { width } : {},
5433
- ...typeof height === "number" ? { height } : {}
5434
- },
5435
- name: editName,
5436
- ...ref ? { ref } : {}
5437
- },
5438
- value,
5439
- name: editName
5440
- };
5548
+ function samePageRoute(a, b) {
5549
+ const ar = normalizeRoutePath(a?.route);
5550
+ const br = normalizeRoutePath(b?.route);
5551
+ return !!ar && !!br && ar === br;
5441
5552
  }
5442
- function Image(props) {
5553
+ function layoutTreesEqual(a, b) {
5554
+ if (!a || !b) return a === b;
5555
+ return JSON.stringify(a.layoutTree) === JSON.stringify(b.layoutTree);
5556
+ }
5557
+ function AmplifyPageContent(contentProps) {
5558
+ assertComponentRegistry("AmplifyPageContent", contentProps);
5443
5559
  const {
5444
- field,
5445
- value,
5446
- name,
5447
- alt: altProp,
5448
- className,
5449
- width: widthProp,
5450
- height: heightProp,
5451
- ...imgProps
5452
- } = props;
5453
- const context = useContext(ComponentContext);
5454
- assertNamedEnvelope("Image", field);
5455
- const coerced = coerceImageField(field, value, name);
5456
- const boundField = coerced.field;
5457
- const hasField = isFieldEnvelope(boundField);
5458
- const hasValue = hasOwnProp(props, "value");
5459
- const { editName, fieldValue, ref } = useBoundField(
5460
- boundField,
5461
- coerced.value,
5462
- coerced.name,
5463
- "Image"
5464
- );
5465
- const composerEdit = useComposerEditMode();
5466
- warnProjectionProps("Image", hasField || isBrandedFields(field), hasValue, coerced.name || name);
5467
- if (!isBrandedFields(field) && warnNotScalarField("Image", boundField, fieldValue)) {
5468
- return null;
5469
- }
5470
- if (!hasField && !hasValue && !name && !editName) {
5471
- return null;
5472
- }
5473
- const src = imageSrc(fieldValue);
5474
- const portable = isPortableImageValue(fieldValue) ? fieldValue : null;
5475
- const alt = altProp ?? portable?.alt ?? "";
5476
- const width = widthProp ?? portable?.width;
5477
- const height = heightProp ?? portable?.height;
5478
- const fieldAttrs = composerEdit && editName && canComposerBind(boundField, ref, editName) ? {
5479
- "data-amplifyup-field": editName,
5480
- "data-amplifyup-field-type": "image",
5481
- "data-amplifyup-node-id": context?.layoutNodeId || void 0,
5482
- "data-amplifyup-ref-provider": ref?.providerId || void 0,
5483
- "data-amplifyup-ref-entity": ref?.entity || void 0,
5484
- "data-amplifyup-ref-id": ref?.id || void 0
5485
- } : null;
5486
- if (composerEdit && !editName && (hasField || hasValue)) {
5487
- console.warn(
5488
- '[AmplifyUp SDK] Image value={\u2026} requires name="\u2026" for computed values'
5489
- );
5560
+ fallback,
5561
+ registry,
5562
+ pageConfig: pageConfigProp,
5563
+ forceComposerPreview = false,
5564
+ previewLoadingComponent,
5565
+ previewEmptyComponent,
5566
+ loadingComponent,
5567
+ emptyComponent,
5568
+ errorComponent
5569
+ } = contentProps;
5570
+ const client = useAmplifyUp();
5571
+ useRegisterPageContent();
5572
+ const preview = useComposerPreviewFlag(forceComposerPreview);
5573
+ const clientLayout = hasAmplifyLayout(client.pageConfig) ? client.pageConfig : null;
5574
+ const serverLayout = hasAmplifyLayout(pageConfigProp) ? pageConfigProp : null;
5575
+ let pageConfig = serverLayout ?? clientLayout;
5576
+ if (preview && clientLayout) {
5577
+ pageConfig = clientLayout;
5578
+ } else if (clientLayout && serverLayout && samePageRoute(clientLayout, serverLayout) && !layoutTreesEqual(clientLayout, serverLayout)) {
5579
+ pageConfig = clientLayout;
5580
+ } else if (clientLayout && !serverLayout) {
5581
+ pageConfig = clientLayout;
5490
5582
  }
5491
- if (!src) {
5492
- if (!composerEdit || !fieldAttrs) return null;
5493
- return /* @__PURE__ */ jsx(
5494
- "span",
5583
+ const loading = !hasAmplifyLayout(pageConfig) && client.loading;
5584
+ const error = hasAmplifyLayout(pageConfig) ? null : pageConfigProp ? null : client.error;
5585
+ const previewEmpty = previewEmptyComponent ?? previewPageSlot("empty");
5586
+ const previewLoading = previewLoadingComponent ?? previewPageSlot("loading");
5587
+ if (preview) {
5588
+ const ready = previewLayoutReady({
5589
+ clientLoading: client.loading,
5590
+ hasClientLayout: !!clientLayout,
5591
+ hasServerLayout: !!serverLayout
5592
+ });
5593
+ if (!ready) {
5594
+ return /* @__PURE__ */ jsx(ComposerLayoutStatusProvider, { ready: false, children: previewLoading });
5595
+ }
5596
+ const layoutSettled = !client.loading || !!clientLayout;
5597
+ return /* @__PURE__ */ jsx(ComposerLayoutStatusProvider, { ready: layoutSettled, children: /* @__PURE__ */ jsx(
5598
+ AmplifyRenderer,
5495
5599
  {
5496
- ...fieldAttrs,
5497
- className,
5498
- role: "img",
5499
- "aria-label": alt || editName || "Image",
5500
- style: {
5501
- display: "block",
5502
- boxSizing: "border-box",
5503
- minWidth: width ? void 0 : 120,
5504
- minHeight: height ? void 0 : 80,
5505
- width: width || "100%",
5506
- height: height || void 0,
5507
- background: "color-mix(in srgb, currentColor 8%, transparent)",
5508
- cursor: "pointer"
5509
- }
5600
+ pageConfig: pageConfig ?? void 0,
5601
+ registry,
5602
+ composerPreview: true,
5603
+ loadingComponent: loadingComponent ?? previewLoading,
5604
+ emptyComponent: emptyComponent ?? previewEmpty,
5605
+ errorComponent: errorComponent ?? (() => previewEmpty)
5510
5606
  }
5511
- );
5607
+ ) });
5512
5608
  }
5513
- return /* @__PURE__ */ jsx(
5514
- "img",
5609
+ if (loading) {
5610
+ return loadingComponent ? /* @__PURE__ */ jsx(Fragment, { children: loadingComponent }) : null;
5611
+ }
5612
+ if (error) {
5613
+ if (errorComponent) return /* @__PURE__ */ jsx(Fragment, { children: errorComponent(error) });
5614
+ return fallback ? /* @__PURE__ */ jsx(Fragment, { children: fallback }) : null;
5615
+ }
5616
+ if (!hasAmplifyLayout(pageConfig)) {
5617
+ return fallback ? /* @__PURE__ */ jsx(Fragment, { children: fallback }) : null;
5618
+ }
5619
+ return /* @__PURE__ */ jsx(ComposerLayoutStatusProvider, { ready: true, children: /* @__PURE__ */ jsx(
5620
+ AmplifyRenderer,
5515
5621
  {
5516
- ...imgProps,
5517
- ...fieldAttrs,
5518
- src,
5519
- alt,
5520
- className,
5521
- width,
5522
- height,
5523
- style: {
5524
- ...typeof imgProps.style === "object" && imgProps.style ? imgProps.style : {},
5525
- ...composerEdit && fieldAttrs ? { cursor: "pointer" } : null
5526
- }
5622
+ pageConfig: pageConfig ?? void 0,
5623
+ registry,
5624
+ loadingComponent,
5625
+ emptyComponent,
5626
+ errorComponent
5527
5627
  }
5528
- );
5628
+ ) });
5529
5629
  }
5630
+ var bindAmplifyPage = (registry) => {
5631
+ const AmplifyPage = (props) => /* @__PURE__ */ jsx(AmplifyPageContent, { ...props, registry });
5632
+ AmplifyPage.displayName = "AmplifyPage";
5633
+ return AmplifyPage;
5634
+ };
5530
5635
  var usePathname = null;
5531
5636
  if (typeof window !== "undefined") {
5532
5637
  try {
@@ -5821,6 +5926,6 @@ function useAmplifyUp() {
5821
5926
  return context;
5822
5927
  }
5823
5928
 
5824
- export { AmplifyPageContent, AmplifyRenderer, AmplifyUpProvider, ComponentContextProvider, ComposerLayoutStatusProvider, ComposerProvider, Field, Image, MaybeComposerProvider, QueryContentError, RichText, SelectVariantsError, Slot, attachFieldEnvelopes, composerStoreKey, envelopeListRows, isBrandedFields, isComposerPreview, isFieldEnvelope, isPreviewRequest, isReadOnlyRowField, isWorkingContentRequest, listOwnerFromSpec, nextPageSpec, queryContent, resolveSlotState, searchSpec, selectVariants, slotShowsAddComponent, slotStateFromEl, toFieldEnvelopes, useAmplifyUp, useComposerPreviewFlag, useInComposer };
5929
+ export { AmplifyPageContent, AmplifyRenderer, AmplifyUpProvider, ComposerLayoutStatusProvider, ComposerProvider, Field, Image, MaybeComposerProvider, QueryContentError, RichText, SelectVariantsError, Slot, attachFieldEnvelopes, bindAmplifyPage, composerStoreKey, defineComponentRegistry, envelopeListRows, isBrandedFields, isComposerPreview, isFieldEnvelope, isPreviewRequest, isReadOnlyRowField, isWorkingContentRequest, listOwnerFromSpec, nextPageSpec, queryContent, resolveSlotState, searchSpec, selectVariants, slotShowsAddComponent, slotStateFromEl, toFieldEnvelopes, useAmplifyUp, useComposerPreviewFlag, useInComposer };
5825
5930
  //# sourceMappingURL=react.mjs.map
5826
5931
  //# sourceMappingURL=react.mjs.map