@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.js CHANGED
@@ -2815,7 +2815,7 @@ Available Console Commands:
2815
2815
  if (typeof document === "undefined") return;
2816
2816
  this.teardownComposerDragDrop();
2817
2817
  const slotSelector = "[data-slot-id], [data-amplifyup-slot]";
2818
- const componentSelector = "[data-amplifyup-component], [data-component-id]";
2818
+ const componentSelector = "[data-amplifyup-component], [data-component-id], [data-amplifyup-node], [data-node-id]";
2819
2819
  const clearDragOverState = () => {
2820
2820
  this.clearComposerDragHighlight();
2821
2821
  };
@@ -2864,6 +2864,7 @@ Available Console Commands:
2864
2864
  if (!target?.closest) return;
2865
2865
  const component = target.closest(componentSelector);
2866
2866
  const slot = target.closest(slotSelector);
2867
+ const pageSlot = slot && slot.getAttribute("data-slot-source") === "page" ? slot : null;
2867
2868
  if (this.highlightComponentsEnabled && component) {
2868
2869
  if (!component.classList.contains("amplifyup-component-hover")) {
2869
2870
  clearComponentHover();
@@ -2875,7 +2876,7 @@ Available Console Commands:
2875
2876
  return;
2876
2877
  }
2877
2878
  clearComponentHover();
2878
- if (this.showZonesEnabled && slot) {
2879
+ if (this.showZonesEnabled && slot && !pageSlot) {
2879
2880
  if (!slot.classList.contains("amplifyup-slot-hover")) {
2880
2881
  clearSlotHover();
2881
2882
  slot.classList.add("amplifyup-slot-hover");
@@ -3005,16 +3006,18 @@ Available Console Commands:
3005
3006
  const lines = [];
3006
3007
  if (highlightComponents) {
3007
3008
  lines.push(
3008
- "[data-amplifyup-component], [data-component-id] {",
3009
+ "[data-amplifyup-component], [data-component-id], [data-amplifyup-node], [data-node-id] {",
3009
3010
  " cursor: pointer !important;",
3010
3011
  "}",
3011
- "[data-amplifyup-component].amplifyup-selected, [data-component-id].amplifyup-selected {",
3012
+ "[data-amplifyup-component].amplifyup-selected, [data-component-id].amplifyup-selected, [data-amplifyup-node].amplifyup-selected, [data-node-id].amplifyup-selected {",
3012
3013
  ` outline: 2px solid ${primary} !important;`,
3013
3014
  " outline-offset: -2px !important;",
3014
3015
  " box-shadow: inset 0 0 0 1px hsl(82 100% 52% / 0.25) !important;",
3015
3016
  "}",
3016
3017
  "[data-amplifyup-component].amplifyup-component-hover:not(.amplifyup-selected),",
3017
- "[data-component-id].amplifyup-component-hover:not(.amplifyup-selected) {",
3018
+ "[data-component-id].amplifyup-component-hover:not(.amplifyup-selected),",
3019
+ "[data-amplifyup-node].amplifyup-component-hover:not(.amplifyup-selected),",
3020
+ "[data-node-id].amplifyup-component-hover:not(.amplifyup-selected) {",
3018
3021
  ` outline: 2px solid ${primary} !important;`,
3019
3022
  " outline-offset: -2px !important;",
3020
3023
  "}"
@@ -3217,7 +3220,7 @@ Available Console Commands:
3217
3220
  let current = element;
3218
3221
  let sawPageSlot = false;
3219
3222
  while (current) {
3220
- if (current.hasAttribute("data-amplifyup-component") || current.hasAttribute("data-component-id") || current.hasAttribute("data-amplifyup-slot") || current.hasAttribute("data-slot-id")) {
3223
+ 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")) {
3221
3224
  hierarchy.push(current);
3222
3225
  if (current.getAttribute("data-slot-source") === "page") {
3223
3226
  sawPageSlot = true;
@@ -3242,13 +3245,14 @@ Available Console Commands:
3242
3245
  const componentId = element.getAttribute("data-amplifyup-component") || element.getAttribute("data-component-id");
3243
3246
  const slotName = componentId ? null : element.getAttribute("data-amplifyup-slot") || element.getAttribute("data-slot-id");
3244
3247
  const componentName = element.getAttribute("data-component-name");
3248
+ const nodeId = element.getAttribute("data-node-id") || element.closest("[data-node-id]")?.getAttribute("data-node-id") || null;
3245
3249
  const hierarchyInfo = hierarchy.map((el, index) => {
3246
3250
  const elComponentId = el.getAttribute("data-amplifyup-component") || el.getAttribute("data-component-id");
3247
3251
  const elSlotName = el.getAttribute("data-amplifyup-slot") || el.getAttribute("data-slot-id");
3248
3252
  const elComponentName = el.getAttribute("data-component-name");
3249
3253
  const isSlot = !elComponentId && !!elSlotName;
3250
3254
  const isPageSlot = isSlot && el.getAttribute("data-slot-source") === "page";
3251
- const nodeId = el.getAttribute("data-node-id") || (isSlot ? el.getAttribute("data-parent-node-id") : null);
3255
+ const nodeId2 = el.getAttribute("data-node-id") || (isSlot ? el.getAttribute("data-parent-node-id") : null);
3252
3256
  return {
3253
3257
  index,
3254
3258
  componentId: elComponentId,
@@ -3256,7 +3260,7 @@ Available Console Commands:
3256
3260
  slotName: isSlot ? elSlotName : null,
3257
3261
  isSlot,
3258
3262
  isPageSlot,
3259
- nodeId
3263
+ nodeId: nodeId2
3260
3264
  };
3261
3265
  });
3262
3266
  const rect = element.getBoundingClientRect ? element.getBoundingClientRect() : null;
@@ -3266,6 +3270,7 @@ Available Console Commands:
3266
3270
  componentId,
3267
3271
  componentName,
3268
3272
  slotName,
3273
+ nodeId,
3269
3274
  hierarchy: hierarchyInfo,
3270
3275
  selectedIndex: hierarchy.length - 1,
3271
3276
  ...bounds && { bounds },
@@ -3295,22 +3300,27 @@ Available Console Commands:
3295
3300
  }
3296
3301
  const doc = document;
3297
3302
  if (highlightComponents) {
3298
- const componentElements = doc.querySelectorAll("[data-amplifyup-component], [data-component-id]");
3303
+ const componentElements = doc.querySelectorAll(
3304
+ "[data-amplifyup-component], [data-component-id], [data-amplifyup-node], [data-node-id]"
3305
+ );
3299
3306
  console.log("[AmplifyUp SDK] Found", componentElements.length, "components to highlight");
3300
3307
  componentElements.forEach((el) => {
3301
3308
  const htmlEl = el;
3302
3309
  const componentId = htmlEl.getAttribute("data-amplifyup-component") || htmlEl.getAttribute("data-component-id");
3303
- if (!componentId) return;
3310
+ const isLayoutNode = htmlEl.hasAttribute("data-node-id") || htmlEl.hasAttribute("data-amplifyup-node");
3311
+ if (!componentId && !isLayoutNode) return;
3304
3312
  if (htmlEl.classList.contains("amplifyup-component-highlight")) return;
3305
- const component = this.componentRegistry.find((c) => c.component_id === componentId);
3313
+ const component = componentId ? this.componentRegistry.find((c) => c.component_id === componentId) : void 0;
3306
3314
  htmlEl.classList.add("amplifyup-component-highlight");
3307
- htmlEl.setAttribute("data-component-id", componentId);
3308
- htmlEl.setAttribute("data-component-name", component?.component_name || componentId);
3315
+ if (componentId) {
3316
+ htmlEl.setAttribute("data-component-id", componentId);
3317
+ htmlEl.setAttribute("data-component-name", component?.component_name || componentId);
3318
+ }
3309
3319
  const hierarchy = this.buildComponentHierarchy(htmlEl);
3310
3320
  const handleClick = (e) => {
3311
3321
  e.stopPropagation();
3312
3322
  this.sendSelectionMessage(htmlEl, hierarchy);
3313
- if (window.parent && window.parent !== window) {
3323
+ if (componentId && window.parent && window.parent !== window) {
3314
3324
  window.parent.postMessage({ type: "CHECK_COMPONENT_DELETABLE", componentId }, "*");
3315
3325
  }
3316
3326
  };
@@ -3351,6 +3361,15 @@ Available Console Commands:
3351
3361
  htmlEl.classList.add("amplifyup-slot-highlight");
3352
3362
  const hierarchy = this.buildComponentHierarchy(htmlEl);
3353
3363
  const handleClick = (e) => {
3364
+ const clickTarget = e.target;
3365
+ if (htmlEl.getAttribute("data-slot-source") === "page" && clickTarget?.closest) {
3366
+ const nested = clickTarget.closest(
3367
+ "[data-node-id], [data-amplifyup-node], [data-amplifyup-component], [data-component-id]"
3368
+ );
3369
+ if (nested && nested !== htmlEl && htmlEl.contains(nested)) {
3370
+ return;
3371
+ }
3372
+ }
3354
3373
  e.stopPropagation();
3355
3374
  this.sendSelectionMessage(htmlEl, hierarchy, isEmpty);
3356
3375
  };
@@ -3679,11 +3698,6 @@ function isReactNodeFallback(fallback) {
3679
3698
  function classNameIsBlock(className) {
3680
3699
  return /(?:^|\s)block(?:\s|$)/.test(className || "");
3681
3700
  }
3682
- function htmlHasVisualChrome(html) {
3683
- return /<(input|button|select|textarea|form|svg|iframe|video|audio|img)\b/i.test(
3684
- html
3685
- );
3686
- }
3687
3701
  function canInlineEdit(name, value) {
3688
3702
  if (!name || isLikelyNonTextFieldName(name)) return false;
3689
3703
  if (value !== void 0 && value !== null && typeof value === "object") {
@@ -3752,6 +3766,36 @@ function commitComposerField(layoutNodeId, componentId, name, value) {
3752
3766
  "*"
3753
3767
  );
3754
3768
  }
3769
+ function looksLikeRichCanvasField(name) {
3770
+ const tokens = String(name || "").replace(/([a-z])([A-Z])/g, "$1 $2").split(/[._\-\s/]+/).map((s) => s.toLowerCase()).filter(Boolean);
3771
+ const last = tokens[tokens.length - 1] || "";
3772
+ return last === "body" || last === "content" || last === "copy" || last === "excerpt" || last === "markdown" || last === "richtext";
3773
+ }
3774
+ var lastRichTextRequestAt = 0;
3775
+ function requestCanvasRichTextEdit(opts) {
3776
+ if (typeof window === "undefined" || window.parent === window) return;
3777
+ if (!opts.name) return;
3778
+ const now = Date.now();
3779
+ if (now - lastRichTextRequestAt < 400) return;
3780
+ lastRichTextRequestAt = now;
3781
+ const rect = opts.el.getBoundingClientRect();
3782
+ window.parent.postMessage(
3783
+ {
3784
+ type: "AMPLIFYUP_RICHTEXT_EDIT",
3785
+ layoutNodeId: opts.layoutNodeId,
3786
+ componentId: opts.componentId,
3787
+ fieldName: opts.name,
3788
+ value: opts.value,
3789
+ bounds: {
3790
+ top: rect.top,
3791
+ left: rect.left,
3792
+ width: Math.max(rect.width, 240),
3793
+ height: Math.max(rect.height, 64)
3794
+ }
3795
+ },
3796
+ "*"
3797
+ );
3798
+ }
3755
3799
  function placeCaret(el, atStart = false) {
3756
3800
  const range = document.createRange();
3757
3801
  range.selectNodeContents(el);
@@ -3767,7 +3811,8 @@ function ComposerInlineField({
3767
3811
  className,
3768
3812
  render,
3769
3813
  layoutNodeId,
3770
- componentId
3814
+ componentId,
3815
+ rich = false
3771
3816
  }) {
3772
3817
  const [editing, setEditing] = React.useState(false);
3773
3818
  const [focused, setFocused] = React.useState(false);
@@ -3820,6 +3865,19 @@ function ComposerInlineField({
3820
3865
  if (!text && !storedEmpty && next === fallbackText) return;
3821
3866
  commitComposerField(layoutNodeId, componentId, name, next);
3822
3867
  };
3868
+ const openRichEditor = (event) => {
3869
+ if (!isComposerEditMode() || !elRef.current) return;
3870
+ event?.preventDefault();
3871
+ event?.stopPropagation();
3872
+ const source = typeof value === "string" && !storedEmpty ? value : text || "";
3873
+ requestCanvasRichTextEdit({
3874
+ el: elRef.current,
3875
+ layoutNodeId,
3876
+ componentId,
3877
+ name,
3878
+ value: source
3879
+ });
3880
+ };
3823
3881
  return /* @__PURE__ */ jsxRuntime.jsx(
3824
3882
  "span",
3825
3883
  {
@@ -3828,7 +3886,7 @@ function ComposerInlineField({
3828
3886
  "data-amplifyup-field": name,
3829
3887
  "data-amplifyup-node-id": layoutNodeId || void 0,
3830
3888
  "data-amplifyup-empty-hint": showHint ? "true" : void 0,
3831
- contentEditable: !showRendered,
3889
+ contentEditable: !rich && !showRendered,
3832
3890
  suppressContentEditableWarning: true,
3833
3891
  role: "textbox",
3834
3892
  tabIndex: 0,
@@ -3839,12 +3897,20 @@ function ComposerInlineField({
3839
3897
  if (!isComposerEditMode()) return;
3840
3898
  const link = event.target?.closest?.("a");
3841
3899
  if (link) event.preventDefault();
3900
+ if (rich) {
3901
+ openRichEditor(event);
3902
+ return;
3903
+ }
3842
3904
  if (render) {
3843
3905
  setEditing(true);
3844
3906
  }
3845
3907
  },
3846
3908
  onFocus: () => {
3847
3909
  if (!isComposerEditMode()) return;
3910
+ if (rich) {
3911
+ openRichEditor();
3912
+ return;
3913
+ }
3848
3914
  setFocused(true);
3849
3915
  const el = elRef.current;
3850
3916
  if (el && storedEmpty) {
@@ -3853,7 +3919,7 @@ function ComposerInlineField({
3853
3919
  }
3854
3920
  if (render) setEditing(true);
3855
3921
  },
3856
- onBlur: finishEdit,
3922
+ onBlur: rich ? void 0 : finishEdit,
3857
3923
  onKeyDown: (event) => {
3858
3924
  event.stopPropagation();
3859
3925
  if (event.key === "Enter" && !event.shiftKey) {
@@ -3885,43 +3951,40 @@ function ComposerInlineField({
3885
3951
  function ComposerInlineHtml({
3886
3952
  name,
3887
3953
  html,
3954
+ sourceValue,
3888
3955
  className,
3889
3956
  Tag = "div",
3890
3957
  layoutNodeId,
3891
3958
  componentId
3892
3959
  }) {
3893
3960
  const elRef = React.useRef(null);
3894
- const sourceTextRef = React.useRef("");
3895
3961
  React.useEffect(() => {
3896
3962
  const el = elRef.current;
3897
3963
  if (!el) return;
3898
- if (document.activeElement === el || el.contains(document.activeElement)) {
3899
- return;
3900
- }
3901
3964
  if (el.innerHTML !== html) el.innerHTML = html;
3902
- sourceTextRef.current = (el.innerText ?? "").replace(/\u00a0/g, " ").trim();
3903
3965
  }, [html]);
3904
- const finishEdit = () => {
3905
- const el = elRef.current;
3906
- if (!el) return;
3907
- const nextHtml = el.innerHTML;
3908
- const nextText = (el.innerText ?? "").replace(/\u00a0/g, " ").replace(/\n+$/g, "").trim();
3909
- if (nextText === sourceTextRef.current && nextHtml === html) return;
3910
- const commitValue = htmlHasVisualChrome(html) || /<[a-z][\s\S]*>/i.test(html) ? nextHtml : nextText;
3911
- commitComposerField(layoutNodeId, componentId, name, commitValue);
3966
+ const openRichEditor = (event) => {
3967
+ if (!elRef.current) return;
3968
+ event.preventDefault();
3969
+ event.stopPropagation();
3970
+ requestCanvasRichTextEdit({
3971
+ el: elRef.current,
3972
+ layoutNodeId,
3973
+ componentId,
3974
+ name,
3975
+ value: sourceValue
3976
+ });
3912
3977
  };
3913
3978
  return React__default.default.createElement(Tag, {
3914
3979
  ref: elRef,
3915
3980
  className,
3916
3981
  "data-amplifyup-field": name,
3917
3982
  "data-amplifyup-node-id": layoutNodeId || void 0,
3918
- contentEditable: true,
3919
- suppressContentEditableWarning: true,
3920
3983
  dangerouslySetInnerHTML: { __html: html },
3921
3984
  onMouseDown: (event) => {
3922
3985
  event.stopPropagation();
3923
3986
  },
3924
- onBlur: finishEdit,
3987
+ onClick: openRichEditor,
3925
3988
  style: {
3926
3989
  cursor: "text",
3927
3990
  outline: "1px dashed color-mix(in srgb, currentColor 40%, transparent)",
@@ -4017,7 +4080,8 @@ function Field(props) {
4017
4080
  className,
4018
4081
  render,
4019
4082
  layoutNodeId: context.layoutNodeId,
4020
- componentId: context.componentId
4083
+ componentId: context.componentId,
4084
+ rich: looksLikeRichCanvasField(editName)
4021
4085
  }
4022
4086
  );
4023
4087
  }
@@ -4039,7 +4103,8 @@ function Field(props) {
4039
4103
  fallback,
4040
4104
  className,
4041
4105
  layoutNodeId: context.layoutNodeId,
4042
- componentId: context.componentId
4106
+ componentId: context.componentId,
4107
+ rich: looksLikeRichCanvasField(editName)
4043
4108
  }
4044
4109
  );
4045
4110
  }
@@ -4098,7 +4163,8 @@ function RichText(props) {
4098
4163
  fallback: typeof fallback === "string" || typeof fallback === "number" ? fallback : void 0,
4099
4164
  className,
4100
4165
  layoutNodeId: context?.layoutNodeId,
4101
- componentId: context?.componentId
4166
+ componentId: context?.componentId,
4167
+ rich: true
4102
4168
  }
4103
4169
  );
4104
4170
  }
@@ -4125,6 +4191,7 @@ function RichText(props) {
4125
4191
  {
4126
4192
  name: editName,
4127
4193
  html,
4194
+ sourceValue: typeof fieldValue === "string" ? fieldValue : html,
4128
4195
  className,
4129
4196
  Tag,
4130
4197
  layoutNodeId: context?.layoutNodeId,
@@ -4593,23 +4660,32 @@ function AmplifyRendererInner({
4593
4660
  }
4594
4661
  }
4595
4662
  const slotsToPass = Object.keys(slotChildren).length > 0 ? slotChildren : void 0;
4596
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-node-id": node.id, "data-amplifyup-node": "", children: /* @__PURE__ */ jsxRuntime.jsx(
4597
- ComponentRenderBoundary,
4663
+ return /* @__PURE__ */ jsxRuntime.jsx(
4664
+ "div",
4598
4665
  {
4599
- componentId: node.componentId,
4600
- nodeId: node.id,
4666
+ "data-node-id": node.id,
4667
+ "data-amplifyup-node": "",
4668
+ "data-component-id": node.componentId,
4669
+ "data-amplifyup-component": node.componentId,
4601
4670
  children: /* @__PURE__ */ jsxRuntime.jsx(
4602
- LiveNodeRender,
4671
+ ComponentRenderBoundary,
4603
4672
  {
4604
- nodeId: node.id,
4605
4673
  componentId: node.componentId,
4606
- props: nodeRenderProps(node),
4607
- slots: slotsToPass,
4608
- renderComponent
4674
+ nodeId: node.id,
4675
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4676
+ LiveNodeRender,
4677
+ {
4678
+ nodeId: node.id,
4679
+ componentId: node.componentId,
4680
+ props: nodeRenderProps(node),
4681
+ slots: slotsToPass,
4682
+ renderComponent
4683
+ }
4684
+ )
4609
4685
  }
4610
4686
  )
4611
4687
  }
4612
- ) });
4688
+ );
4613
4689
  };
4614
4690
  const rawTree = pageConfig.layoutTree;
4615
4691
  const layoutTree = Array.isArray(rawTree) ? rawTree : rawTree && typeof rawTree === "object" && rawTree.componentId ? [rawTree] : [];
@@ -4623,9 +4699,9 @@ function AmplifyRendererInner({
4623
4699
  "data-amplifyup-slot": "main",
4624
4700
  "data-slot-source": "page",
4625
4701
  "data-slot-empty": layoutTree.length === 0 ? "true" : void 0,
4626
- children: layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderNode(node) }, node.id))
4702
+ children: layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: renderNode(node) }, node.id))
4627
4703
  }
4628
- ) : layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderNode(node) }, node.id)) });
4704
+ ) : layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: renderNode(node) }, node.id)) });
4629
4705
  }
4630
4706
  var AmplifyRenderer = React.memo(AmplifyRendererInner);
4631
4707
  function defaultPreviewCanvas() {