@amplifyup/sdk 0.1.56 → 0.1.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import React, { createContext, memo, useState, useEffect, useContext, Fragment as Fragment$1, Component, useRef, useSyncExternalStore } from 'react';
2
+ import React, { createContext, memo, useState, useEffect, Fragment as Fragment$1, useContext, Component, useRef, useSyncExternalStore } from 'react';
3
3
  import { marked } from 'marked';
4
4
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
5
5
 
@@ -2809,7 +2809,7 @@ Available Console Commands:
2809
2809
  if (typeof document === "undefined") return;
2810
2810
  this.teardownComposerDragDrop();
2811
2811
  const slotSelector = "[data-slot-id], [data-amplifyup-slot]";
2812
- const componentSelector = "[data-amplifyup-component], [data-component-id]";
2812
+ const componentSelector = "[data-amplifyup-component], [data-component-id], [data-amplifyup-node], [data-node-id]";
2813
2813
  const clearDragOverState = () => {
2814
2814
  this.clearComposerDragHighlight();
2815
2815
  };
@@ -2858,6 +2858,7 @@ Available Console Commands:
2858
2858
  if (!target?.closest) return;
2859
2859
  const component = target.closest(componentSelector);
2860
2860
  const slot = target.closest(slotSelector);
2861
+ const pageSlot = slot && slot.getAttribute("data-slot-source") === "page" ? slot : null;
2861
2862
  if (this.highlightComponentsEnabled && component) {
2862
2863
  if (!component.classList.contains("amplifyup-component-hover")) {
2863
2864
  clearComponentHover();
@@ -2869,7 +2870,7 @@ Available Console Commands:
2869
2870
  return;
2870
2871
  }
2871
2872
  clearComponentHover();
2872
- if (this.showZonesEnabled && slot) {
2873
+ if (this.showZonesEnabled && slot && !pageSlot) {
2873
2874
  if (!slot.classList.contains("amplifyup-slot-hover")) {
2874
2875
  clearSlotHover();
2875
2876
  slot.classList.add("amplifyup-slot-hover");
@@ -2999,16 +3000,18 @@ Available Console Commands:
2999
3000
  const lines = [];
3000
3001
  if (highlightComponents) {
3001
3002
  lines.push(
3002
- "[data-amplifyup-component], [data-component-id] {",
3003
+ "[data-amplifyup-component], [data-component-id], [data-amplifyup-node], [data-node-id] {",
3003
3004
  " cursor: pointer !important;",
3004
3005
  "}",
3005
- "[data-amplifyup-component].amplifyup-selected, [data-component-id].amplifyup-selected {",
3006
+ "[data-amplifyup-component].amplifyup-selected, [data-component-id].amplifyup-selected, [data-amplifyup-node].amplifyup-selected, [data-node-id].amplifyup-selected {",
3006
3007
  ` outline: 2px solid ${primary} !important;`,
3007
3008
  " outline-offset: -2px !important;",
3008
3009
  " box-shadow: inset 0 0 0 1px hsl(82 100% 52% / 0.25) !important;",
3009
3010
  "}",
3010
3011
  "[data-amplifyup-component].amplifyup-component-hover:not(.amplifyup-selected),",
3011
- "[data-component-id].amplifyup-component-hover:not(.amplifyup-selected) {",
3012
+ "[data-component-id].amplifyup-component-hover:not(.amplifyup-selected),",
3013
+ "[data-amplifyup-node].amplifyup-component-hover:not(.amplifyup-selected),",
3014
+ "[data-node-id].amplifyup-component-hover:not(.amplifyup-selected) {",
3012
3015
  ` outline: 2px solid ${primary} !important;`,
3013
3016
  " outline-offset: -2px !important;",
3014
3017
  "}"
@@ -3211,7 +3214,7 @@ Available Console Commands:
3211
3214
  let current = element;
3212
3215
  let sawPageSlot = false;
3213
3216
  while (current) {
3214
- if (current.hasAttribute("data-amplifyup-component") || current.hasAttribute("data-component-id") || current.hasAttribute("data-amplifyup-slot") || current.hasAttribute("data-slot-id")) {
3217
+ if (current.hasAttribute("data-amplifyup-component") || current.hasAttribute("data-component-id") || current.hasAttribute("data-amplifyup-slot") || current.hasAttribute("data-slot-id") || current.hasAttribute("data-node-id") || current.hasAttribute("data-amplifyup-node")) {
3215
3218
  hierarchy.push(current);
3216
3219
  if (current.getAttribute("data-slot-source") === "page") {
3217
3220
  sawPageSlot = true;
@@ -3236,13 +3239,14 @@ Available Console Commands:
3236
3239
  const componentId = element.getAttribute("data-amplifyup-component") || element.getAttribute("data-component-id");
3237
3240
  const slotName = componentId ? null : element.getAttribute("data-amplifyup-slot") || element.getAttribute("data-slot-id");
3238
3241
  const componentName = element.getAttribute("data-component-name");
3242
+ const nodeId = element.getAttribute("data-node-id") || element.closest("[data-node-id]")?.getAttribute("data-node-id") || null;
3239
3243
  const hierarchyInfo = hierarchy.map((el, index) => {
3240
3244
  const elComponentId = el.getAttribute("data-amplifyup-component") || el.getAttribute("data-component-id");
3241
3245
  const elSlotName = el.getAttribute("data-amplifyup-slot") || el.getAttribute("data-slot-id");
3242
3246
  const elComponentName = el.getAttribute("data-component-name");
3243
3247
  const isSlot = !elComponentId && !!elSlotName;
3244
3248
  const isPageSlot = isSlot && el.getAttribute("data-slot-source") === "page";
3245
- const nodeId = el.getAttribute("data-node-id") || (isSlot ? el.getAttribute("data-parent-node-id") : null);
3249
+ const nodeId2 = el.getAttribute("data-node-id") || (isSlot ? el.getAttribute("data-parent-node-id") : null);
3246
3250
  return {
3247
3251
  index,
3248
3252
  componentId: elComponentId,
@@ -3250,7 +3254,7 @@ Available Console Commands:
3250
3254
  slotName: isSlot ? elSlotName : null,
3251
3255
  isSlot,
3252
3256
  isPageSlot,
3253
- nodeId
3257
+ nodeId: nodeId2
3254
3258
  };
3255
3259
  });
3256
3260
  const rect = element.getBoundingClientRect ? element.getBoundingClientRect() : null;
@@ -3260,6 +3264,7 @@ Available Console Commands:
3260
3264
  componentId,
3261
3265
  componentName,
3262
3266
  slotName,
3267
+ nodeId,
3263
3268
  hierarchy: hierarchyInfo,
3264
3269
  selectedIndex: hierarchy.length - 1,
3265
3270
  ...bounds && { bounds },
@@ -3289,22 +3294,27 @@ Available Console Commands:
3289
3294
  }
3290
3295
  const doc = document;
3291
3296
  if (highlightComponents) {
3292
- const componentElements = doc.querySelectorAll("[data-amplifyup-component], [data-component-id]");
3297
+ const componentElements = doc.querySelectorAll(
3298
+ "[data-amplifyup-component], [data-component-id], [data-amplifyup-node], [data-node-id]"
3299
+ );
3293
3300
  console.log("[AmplifyUp SDK] Found", componentElements.length, "components to highlight");
3294
3301
  componentElements.forEach((el) => {
3295
3302
  const htmlEl = el;
3296
3303
  const componentId = htmlEl.getAttribute("data-amplifyup-component") || htmlEl.getAttribute("data-component-id");
3297
- if (!componentId) return;
3304
+ const isLayoutNode = htmlEl.hasAttribute("data-node-id") || htmlEl.hasAttribute("data-amplifyup-node");
3305
+ if (!componentId && !isLayoutNode) return;
3298
3306
  if (htmlEl.classList.contains("amplifyup-component-highlight")) return;
3299
- const component = this.componentRegistry.find((c) => c.component_id === componentId);
3307
+ const component = componentId ? this.componentRegistry.find((c) => c.component_id === componentId) : void 0;
3300
3308
  htmlEl.classList.add("amplifyup-component-highlight");
3301
- htmlEl.setAttribute("data-component-id", componentId);
3302
- htmlEl.setAttribute("data-component-name", component?.component_name || componentId);
3309
+ if (componentId) {
3310
+ htmlEl.setAttribute("data-component-id", componentId);
3311
+ htmlEl.setAttribute("data-component-name", component?.component_name || componentId);
3312
+ }
3303
3313
  const hierarchy = this.buildComponentHierarchy(htmlEl);
3304
3314
  const handleClick = (e) => {
3305
3315
  e.stopPropagation();
3306
3316
  this.sendSelectionMessage(htmlEl, hierarchy);
3307
- if (window.parent && window.parent !== window) {
3317
+ if (componentId && window.parent && window.parent !== window) {
3308
3318
  window.parent.postMessage({ type: "CHECK_COMPONENT_DELETABLE", componentId }, "*");
3309
3319
  }
3310
3320
  };
@@ -3345,6 +3355,15 @@ Available Console Commands:
3345
3355
  htmlEl.classList.add("amplifyup-slot-highlight");
3346
3356
  const hierarchy = this.buildComponentHierarchy(htmlEl);
3347
3357
  const handleClick = (e) => {
3358
+ const clickTarget = e.target;
3359
+ if (htmlEl.getAttribute("data-slot-source") === "page" && clickTarget?.closest) {
3360
+ const nested = clickTarget.closest(
3361
+ "[data-node-id], [data-amplifyup-node], [data-amplifyup-component], [data-component-id]"
3362
+ );
3363
+ if (nested && nested !== htmlEl && htmlEl.contains(nested)) {
3364
+ return;
3365
+ }
3366
+ }
3348
3367
  e.stopPropagation();
3349
3368
  this.sendSelectionMessage(htmlEl, hierarchy, isEmpty);
3350
3369
  };
@@ -3673,11 +3692,6 @@ function isReactNodeFallback(fallback) {
3673
3692
  function classNameIsBlock(className) {
3674
3693
  return /(?:^|\s)block(?:\s|$)/.test(className || "");
3675
3694
  }
3676
- function htmlHasVisualChrome(html) {
3677
- return /<(input|button|select|textarea|form|svg|iframe|video|audio|img)\b/i.test(
3678
- html
3679
- );
3680
- }
3681
3695
  function canInlineEdit(name, value) {
3682
3696
  if (!name || isLikelyNonTextFieldName(name)) return false;
3683
3697
  if (value !== void 0 && value !== null && typeof value === "object") {
@@ -3746,6 +3760,36 @@ function commitComposerField(layoutNodeId, componentId, name, value) {
3746
3760
  "*"
3747
3761
  );
3748
3762
  }
3763
+ function looksLikeRichCanvasField(name) {
3764
+ const tokens = String(name || "").replace(/([a-z])([A-Z])/g, "$1 $2").split(/[._\-\s/]+/).map((s) => s.toLowerCase()).filter(Boolean);
3765
+ const last = tokens[tokens.length - 1] || "";
3766
+ return last === "body" || last === "content" || last === "copy" || last === "excerpt" || last === "markdown" || last === "richtext";
3767
+ }
3768
+ var lastRichTextRequestAt = 0;
3769
+ function requestCanvasRichTextEdit(opts) {
3770
+ if (typeof window === "undefined" || window.parent === window) return;
3771
+ if (!opts.name) return;
3772
+ const now = Date.now();
3773
+ if (now - lastRichTextRequestAt < 400) return;
3774
+ lastRichTextRequestAt = now;
3775
+ const rect = opts.el.getBoundingClientRect();
3776
+ window.parent.postMessage(
3777
+ {
3778
+ type: "AMPLIFYUP_RICHTEXT_EDIT",
3779
+ layoutNodeId: opts.layoutNodeId,
3780
+ componentId: opts.componentId,
3781
+ fieldName: opts.name,
3782
+ value: opts.value,
3783
+ bounds: {
3784
+ top: rect.top,
3785
+ left: rect.left,
3786
+ width: Math.max(rect.width, 240),
3787
+ height: Math.max(rect.height, 64)
3788
+ }
3789
+ },
3790
+ "*"
3791
+ );
3792
+ }
3749
3793
  function placeCaret(el, atStart = false) {
3750
3794
  const range = document.createRange();
3751
3795
  range.selectNodeContents(el);
@@ -3761,7 +3805,8 @@ function ComposerInlineField({
3761
3805
  className,
3762
3806
  render,
3763
3807
  layoutNodeId,
3764
- componentId
3808
+ componentId,
3809
+ rich = false
3765
3810
  }) {
3766
3811
  const [editing, setEditing] = useState(false);
3767
3812
  const [focused, setFocused] = useState(false);
@@ -3814,6 +3859,19 @@ function ComposerInlineField({
3814
3859
  if (!text && !storedEmpty && next === fallbackText) return;
3815
3860
  commitComposerField(layoutNodeId, componentId, name, next);
3816
3861
  };
3862
+ const openRichEditor = (event) => {
3863
+ if (!isComposerEditMode() || !elRef.current) return;
3864
+ event?.preventDefault();
3865
+ event?.stopPropagation();
3866
+ const source = typeof value === "string" && !storedEmpty ? value : text || "";
3867
+ requestCanvasRichTextEdit({
3868
+ el: elRef.current,
3869
+ layoutNodeId,
3870
+ componentId,
3871
+ name,
3872
+ value: source
3873
+ });
3874
+ };
3817
3875
  return /* @__PURE__ */ jsx(
3818
3876
  "span",
3819
3877
  {
@@ -3822,7 +3880,7 @@ function ComposerInlineField({
3822
3880
  "data-amplifyup-field": name,
3823
3881
  "data-amplifyup-node-id": layoutNodeId || void 0,
3824
3882
  "data-amplifyup-empty-hint": showHint ? "true" : void 0,
3825
- contentEditable: !showRendered,
3883
+ contentEditable: !rich && !showRendered,
3826
3884
  suppressContentEditableWarning: true,
3827
3885
  role: "textbox",
3828
3886
  tabIndex: 0,
@@ -3833,12 +3891,20 @@ function ComposerInlineField({
3833
3891
  if (!isComposerEditMode()) return;
3834
3892
  const link = event.target?.closest?.("a");
3835
3893
  if (link) event.preventDefault();
3894
+ if (rich) {
3895
+ openRichEditor(event);
3896
+ return;
3897
+ }
3836
3898
  if (render) {
3837
3899
  setEditing(true);
3838
3900
  }
3839
3901
  },
3840
3902
  onFocus: () => {
3841
3903
  if (!isComposerEditMode()) return;
3904
+ if (rich) {
3905
+ openRichEditor();
3906
+ return;
3907
+ }
3842
3908
  setFocused(true);
3843
3909
  const el = elRef.current;
3844
3910
  if (el && storedEmpty) {
@@ -3847,7 +3913,7 @@ function ComposerInlineField({
3847
3913
  }
3848
3914
  if (render) setEditing(true);
3849
3915
  },
3850
- onBlur: finishEdit,
3916
+ onBlur: rich ? void 0 : finishEdit,
3851
3917
  onKeyDown: (event) => {
3852
3918
  event.stopPropagation();
3853
3919
  if (event.key === "Enter" && !event.shiftKey) {
@@ -3879,43 +3945,40 @@ function ComposerInlineField({
3879
3945
  function ComposerInlineHtml({
3880
3946
  name,
3881
3947
  html,
3948
+ sourceValue,
3882
3949
  className,
3883
3950
  Tag = "div",
3884
3951
  layoutNodeId,
3885
3952
  componentId
3886
3953
  }) {
3887
3954
  const elRef = useRef(null);
3888
- const sourceTextRef = useRef("");
3889
3955
  useEffect(() => {
3890
3956
  const el = elRef.current;
3891
3957
  if (!el) return;
3892
- if (document.activeElement === el || el.contains(document.activeElement)) {
3893
- return;
3894
- }
3895
3958
  if (el.innerHTML !== html) el.innerHTML = html;
3896
- sourceTextRef.current = (el.innerText ?? "").replace(/\u00a0/g, " ").trim();
3897
3959
  }, [html]);
3898
- const finishEdit = () => {
3899
- const el = elRef.current;
3900
- if (!el) return;
3901
- const nextHtml = el.innerHTML;
3902
- const nextText = (el.innerText ?? "").replace(/\u00a0/g, " ").replace(/\n+$/g, "").trim();
3903
- if (nextText === sourceTextRef.current && nextHtml === html) return;
3904
- const commitValue = htmlHasVisualChrome(html) || /<[a-z][\s\S]*>/i.test(html) ? nextHtml : nextText;
3905
- commitComposerField(layoutNodeId, componentId, name, commitValue);
3960
+ const openRichEditor = (event) => {
3961
+ if (!elRef.current) return;
3962
+ event.preventDefault();
3963
+ event.stopPropagation();
3964
+ requestCanvasRichTextEdit({
3965
+ el: elRef.current,
3966
+ layoutNodeId,
3967
+ componentId,
3968
+ name,
3969
+ value: sourceValue
3970
+ });
3906
3971
  };
3907
3972
  return React.createElement(Tag, {
3908
3973
  ref: elRef,
3909
3974
  className,
3910
3975
  "data-amplifyup-field": name,
3911
3976
  "data-amplifyup-node-id": layoutNodeId || void 0,
3912
- contentEditable: true,
3913
- suppressContentEditableWarning: true,
3914
3977
  dangerouslySetInnerHTML: { __html: html },
3915
3978
  onMouseDown: (event) => {
3916
3979
  event.stopPropagation();
3917
3980
  },
3918
- onBlur: finishEdit,
3981
+ onClick: openRichEditor,
3919
3982
  style: {
3920
3983
  cursor: "text",
3921
3984
  outline: "1px dashed color-mix(in srgb, currentColor 40%, transparent)",
@@ -4011,7 +4074,8 @@ function Field(props) {
4011
4074
  className,
4012
4075
  render,
4013
4076
  layoutNodeId: context.layoutNodeId,
4014
- componentId: context.componentId
4077
+ componentId: context.componentId,
4078
+ rich: looksLikeRichCanvasField(editName)
4015
4079
  }
4016
4080
  );
4017
4081
  }
@@ -4033,7 +4097,8 @@ function Field(props) {
4033
4097
  fallback,
4034
4098
  className,
4035
4099
  layoutNodeId: context.layoutNodeId,
4036
- componentId: context.componentId
4100
+ componentId: context.componentId,
4101
+ rich: looksLikeRichCanvasField(editName)
4037
4102
  }
4038
4103
  );
4039
4104
  }
@@ -4092,7 +4157,8 @@ function RichText(props) {
4092
4157
  fallback: typeof fallback === "string" || typeof fallback === "number" ? fallback : void 0,
4093
4158
  className,
4094
4159
  layoutNodeId: context?.layoutNodeId,
4095
- componentId: context?.componentId
4160
+ componentId: context?.componentId,
4161
+ rich: true
4096
4162
  }
4097
4163
  );
4098
4164
  }
@@ -4119,6 +4185,7 @@ function RichText(props) {
4119
4185
  {
4120
4186
  name: editName,
4121
4187
  html,
4188
+ sourceValue: typeof fieldValue === "string" ? fieldValue : html,
4122
4189
  className,
4123
4190
  Tag,
4124
4191
  layoutNodeId: context?.layoutNodeId,
@@ -4587,23 +4654,32 @@ function AmplifyRendererInner({
4587
4654
  }
4588
4655
  }
4589
4656
  const slotsToPass = Object.keys(slotChildren).length > 0 ? slotChildren : void 0;
4590
- return /* @__PURE__ */ jsx("div", { "data-node-id": node.id, "data-amplifyup-node": "", children: /* @__PURE__ */ jsx(
4591
- ComponentRenderBoundary,
4657
+ return /* @__PURE__ */ jsx(
4658
+ "div",
4592
4659
  {
4593
- componentId: node.componentId,
4594
- nodeId: node.id,
4660
+ "data-node-id": node.id,
4661
+ "data-amplifyup-node": "",
4662
+ "data-component-id": node.componentId,
4663
+ "data-amplifyup-component": node.componentId,
4595
4664
  children: /* @__PURE__ */ jsx(
4596
- LiveNodeRender,
4665
+ ComponentRenderBoundary,
4597
4666
  {
4598
- nodeId: node.id,
4599
4667
  componentId: node.componentId,
4600
- props: nodeRenderProps(node),
4601
- slots: slotsToPass,
4602
- renderComponent
4668
+ nodeId: node.id,
4669
+ children: /* @__PURE__ */ jsx(
4670
+ LiveNodeRender,
4671
+ {
4672
+ nodeId: node.id,
4673
+ componentId: node.componentId,
4674
+ props: nodeRenderProps(node),
4675
+ slots: slotsToPass,
4676
+ renderComponent
4677
+ }
4678
+ )
4603
4679
  }
4604
4680
  )
4605
4681
  }
4606
- ) });
4682
+ );
4607
4683
  };
4608
4684
  const rawTree = pageConfig.layoutTree;
4609
4685
  const layoutTree = Array.isArray(rawTree) ? rawTree : rawTree && typeof rawTree === "object" && rawTree.componentId ? [rawTree] : [];
@@ -4617,9 +4693,9 @@ function AmplifyRendererInner({
4617
4693
  "data-amplifyup-slot": "main",
4618
4694
  "data-slot-source": "page",
4619
4695
  "data-slot-empty": layoutTree.length === 0 ? "true" : void 0,
4620
- children: layoutTree.map((node) => /* @__PURE__ */ jsx("div", { children: renderNode(node) }, node.id))
4696
+ children: layoutTree.map((node) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(node) }, node.id))
4621
4697
  }
4622
- ) : layoutTree.map((node) => /* @__PURE__ */ jsx("div", { children: renderNode(node) }, node.id)) });
4698
+ ) : layoutTree.map((node) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(node) }, node.id)) });
4623
4699
  }
4624
4700
  var AmplifyRenderer = memo(AmplifyRendererInner);
4625
4701
  function defaultPreviewCanvas() {