@amplifyup/sdk 0.1.26 → 0.1.27

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 { createContext, useState, useEffect, useContext, Fragment as Fragment$1, Component } from 'react';
2
+ import { createContext, useState, useEffect, useContext, Fragment as Fragment$1, useRef, Component } from 'react';
3
3
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
4
  import { marked } from 'marked';
5
5
 
@@ -1781,6 +1781,12 @@ Available Console Commands:
1781
1781
  return;
1782
1782
  }
1783
1783
  try {
1784
+ if (event.data?.type === "AMPLIFYUP_FIELD_PATCH") {
1785
+ window.dispatchEvent(
1786
+ new CustomEvent("amplifyup:field-patch", { detail: event.data })
1787
+ );
1788
+ return;
1789
+ }
1784
1790
  if (event.data?.type === "COMPONENT_DELETABLE_STATUS") {
1785
1791
  const { componentId, deletable, nodeId } = event.data;
1786
1792
  const element = document.querySelector(`[data-component-id="${componentId}"]`);
@@ -1967,6 +1973,10 @@ Available Console Commands:
1967
1973
  setEventSelectionMode(enabled) {
1968
1974
  if (typeof document === "undefined") return;
1969
1975
  this.eventSelectionMode = enabled;
1976
+ if (typeof window !== "undefined") {
1977
+ window.__AMPLIFYUP_EVENT_SELECTION__ = enabled;
1978
+ window.dispatchEvent(new CustomEvent("amplifyup:composer-edit"));
1979
+ }
1970
1980
  if (this.eventSelectionClickHandler) {
1971
1981
  document.removeEventListener("click", this.eventSelectionClickHandler, true);
1972
1982
  this.eventSelectionClickHandler = null;
@@ -2204,6 +2214,14 @@ Available Console Commands:
2204
2214
  el.classList.add("amplifyup-selected");
2205
2215
  }
2206
2216
  });
2217
+ if (typeof window !== "undefined") {
2218
+ window.__AMPLIFYUP_COMPOSER_EDIT__ = highlightComponents;
2219
+ window.dispatchEvent(
2220
+ new CustomEvent("amplifyup:composer-edit", {
2221
+ detail: { enabled: highlightComponents }
2222
+ })
2223
+ );
2224
+ }
2207
2225
  }
2208
2226
  /** Document-level drag/drop for cross-iframe drags from Composer sidebar. */
2209
2227
  setupComposerDragDrop() {
@@ -2512,6 +2530,12 @@ Available Console Commands:
2512
2530
  const clearSelection = opts?.clearSelection !== false;
2513
2531
  this.highlightingEnabled = false;
2514
2532
  this.teardownComposerDragDrop();
2533
+ if (opts?.clearSelection !== false && typeof window !== "undefined") {
2534
+ window.__AMPLIFYUP_COMPOSER_EDIT__ = false;
2535
+ window.dispatchEvent(
2536
+ new CustomEvent("amplifyup:composer-edit", { detail: { enabled: false } })
2537
+ );
2538
+ }
2515
2539
  if (this.mutationObserver) {
2516
2540
  this.mutationObserver.disconnect();
2517
2541
  this.mutationObserver = null;
@@ -3379,6 +3403,152 @@ function Slot({
3379
3403
  }
3380
3404
  );
3381
3405
  }
3406
+ function isComposerEditMode() {
3407
+ if (typeof window === "undefined") return false;
3408
+ return isComposerPreview() && window.__AMPLIFYUP_COMPOSER_EDIT__ === true && window.__AMPLIFYUP_EVENT_SELECTION__ !== true;
3409
+ }
3410
+ function isLikelyNonTextFieldName(name) {
3411
+ const n = name.toLowerCase();
3412
+ return n.includes("href") || n.includes("url") || n.includes("src") || n.includes("image") || n.includes("icon") || n.includes("overlay") || n.includes("color");
3413
+ }
3414
+ function canInlineEdit(name, value) {
3415
+ if (isLikelyNonTextFieldName(name)) return false;
3416
+ if (value !== void 0 && value !== null && typeof value === "object") {
3417
+ return false;
3418
+ }
3419
+ if (typeof value === "boolean") return false;
3420
+ return true;
3421
+ }
3422
+ function useComposerEditMode() {
3423
+ const [enabled, setEnabled] = useState(false);
3424
+ useEffect(() => {
3425
+ const sync = () => setEnabled(isComposerEditMode());
3426
+ sync();
3427
+ window.addEventListener("amplifyup:composer-edit", sync);
3428
+ return () => window.removeEventListener("amplifyup:composer-edit", sync);
3429
+ }, []);
3430
+ return enabled;
3431
+ }
3432
+ function useFieldOverlay(layoutNodeId, name, source) {
3433
+ const [overlay, setOverlay] = useState(void 0);
3434
+ useEffect(() => {
3435
+ const onPatch = (event) => {
3436
+ const detail = event.detail || {};
3437
+ if (detail.fieldName !== name) return;
3438
+ if (detail.layoutNodeId && layoutNodeId && String(detail.layoutNodeId) !== String(layoutNodeId)) {
3439
+ return;
3440
+ }
3441
+ setOverlay(detail.value);
3442
+ };
3443
+ window.addEventListener("amplifyup:field-patch", onPatch);
3444
+ return () => window.removeEventListener("amplifyup:field-patch", onPatch);
3445
+ }, [layoutNodeId, name]);
3446
+ return overlay !== void 0 ? overlay : source;
3447
+ }
3448
+ function commitComposerField(layoutNodeId, componentId, name, value) {
3449
+ if (typeof window === "undefined" || window.parent === window) return;
3450
+ window.parent.postMessage(
3451
+ {
3452
+ type: "AMPLIFYUP_FIELD_COMMIT",
3453
+ layoutNodeId,
3454
+ componentId,
3455
+ fieldName: name,
3456
+ value
3457
+ },
3458
+ "*"
3459
+ );
3460
+ }
3461
+ function ComposerInlineField({
3462
+ name,
3463
+ value,
3464
+ fallback,
3465
+ className,
3466
+ render,
3467
+ layoutNodeId,
3468
+ componentId
3469
+ }) {
3470
+ const [editing, setEditing] = useState(false);
3471
+ const elRef = useRef(null);
3472
+ const text = formatFieldValue(value);
3473
+ const fallbackText = typeof fallback === "string" || typeof fallback === "number" ? String(fallback) : "";
3474
+ const display = text || fallbackText;
3475
+ const showRendered = !!render && !editing;
3476
+ useEffect(() => {
3477
+ const el = elRef.current;
3478
+ if (!el || showRendered) return;
3479
+ if (document.activeElement === el) return;
3480
+ const next = display || "";
3481
+ if (el.textContent !== next) el.textContent = next;
3482
+ }, [display, showRendered]);
3483
+ useEffect(() => {
3484
+ if (!editing || !elRef.current) return;
3485
+ const el = elRef.current;
3486
+ el.textContent = display || "";
3487
+ el.focus();
3488
+ const range = document.createRange();
3489
+ range.selectNodeContents(el);
3490
+ const sel = window.getSelection();
3491
+ sel?.removeAllRanges();
3492
+ sel?.addRange(range);
3493
+ }, [editing]);
3494
+ const finishEdit = () => {
3495
+ const raw = (elRef.current?.innerText ?? "").replace(/\u00a0/g, " ").replace(/\n+$/g, "");
3496
+ const next = raw.trim() === "" ? "" : raw;
3497
+ setEditing(false);
3498
+ if (next === text) return;
3499
+ if (!text && next === fallbackText) return;
3500
+ commitComposerField(layoutNodeId, componentId, name, next);
3501
+ };
3502
+ return /* @__PURE__ */ jsx(
3503
+ "span",
3504
+ {
3505
+ ref: elRef,
3506
+ className,
3507
+ "data-amplifyup-field": name,
3508
+ "data-amplifyup-node-id": layoutNodeId || void 0,
3509
+ contentEditable: !showRendered,
3510
+ suppressContentEditableWarning: true,
3511
+ role: "textbox",
3512
+ tabIndex: 0,
3513
+ onMouseDown: (event) => {
3514
+ event.stopPropagation();
3515
+ },
3516
+ onClick: (event) => {
3517
+ const link = event.target?.closest?.("a");
3518
+ if (link) event.preventDefault();
3519
+ if (render && isComposerEditMode()) {
3520
+ setEditing(true);
3521
+ }
3522
+ },
3523
+ onFocus: () => {
3524
+ if (!isComposerEditMode()) return;
3525
+ if (render) setEditing(true);
3526
+ },
3527
+ onBlur: finishEdit,
3528
+ onKeyDown: (event) => {
3529
+ event.stopPropagation();
3530
+ if (event.key === "Enter" && !event.shiftKey) {
3531
+ event.preventDefault();
3532
+ event.currentTarget.blur();
3533
+ }
3534
+ if (event.key === "Escape") {
3535
+ event.preventDefault();
3536
+ if (elRef.current) elRef.current.textContent = display || "";
3537
+ setEditing(false);
3538
+ event.currentTarget.blur();
3539
+ }
3540
+ },
3541
+ style: {
3542
+ cursor: "text",
3543
+ outline: "1px dashed color-mix(in srgb, currentColor 40%, transparent)",
3544
+ outlineOffset: "2px",
3545
+ minWidth: "1ch",
3546
+ display: render ? void 0 : "inline"
3547
+ },
3548
+ children: showRendered ? value != null && value !== "" ? render(value) : fallback ?? display : null
3549
+ }
3550
+ );
3551
+ }
3382
3552
  function formatFieldValue(value) {
3383
3553
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3384
3554
  return String(value);
@@ -3405,11 +3575,30 @@ function Field({
3405
3575
  render
3406
3576
  }) {
3407
3577
  const context = useContext(ComponentContext);
3578
+ const composerEdit = useComposerEditMode();
3579
+ const fieldValue = useFieldOverlay(
3580
+ context?.layoutNodeId,
3581
+ name,
3582
+ context?.props?.[name]
3583
+ );
3408
3584
  if (!context) {
3409
3585
  console.warn(`[AmplifyUp SDK] Field "${name}" used outside ComponentContextProvider`);
3410
3586
  return fallback ? /* @__PURE__ */ jsx(Fragment, { children: fallback }) : null;
3411
3587
  }
3412
- const fieldValue = context.props?.[name];
3588
+ if (composerEdit && canInlineEdit(name, fieldValue)) {
3589
+ return /* @__PURE__ */ jsx(
3590
+ ComposerInlineField,
3591
+ {
3592
+ name,
3593
+ value: fieldValue,
3594
+ fallback,
3595
+ className,
3596
+ render,
3597
+ layoutNodeId: context.layoutNodeId,
3598
+ componentId: context.componentId
3599
+ }
3600
+ );
3601
+ }
3413
3602
  if (fieldValue === void 0 || fieldValue === null) {
3414
3603
  return fallback ? /* @__PURE__ */ jsx("span", { className, children: fallback }) : null;
3415
3604
  }
@@ -3437,11 +3626,29 @@ function RichText({
3437
3626
  as: Tag = "div"
3438
3627
  }) {
3439
3628
  const context = useContext(ComponentContext);
3629
+ const composerEdit = useComposerEditMode();
3630
+ const fieldValue = useFieldOverlay(
3631
+ context?.layoutNodeId,
3632
+ name,
3633
+ context?.props?.[name]
3634
+ );
3440
3635
  if (!context) {
3441
3636
  console.warn(`[AmplifyUp SDK] RichText "${name}" used outside ComponentContextProvider`);
3442
3637
  return fallback ? /* @__PURE__ */ jsx(Fragment, { children: fallback }) : null;
3443
3638
  }
3444
- const fieldValue = context.props?.[name];
3639
+ if (composerEdit && canInlineEdit(name, fieldValue)) {
3640
+ return /* @__PURE__ */ jsx(
3641
+ ComposerInlineField,
3642
+ {
3643
+ name,
3644
+ value: fieldValue,
3645
+ fallback,
3646
+ className,
3647
+ layoutNodeId: context.layoutNodeId,
3648
+ componentId: context.componentId
3649
+ }
3650
+ );
3651
+ }
3445
3652
  if (fieldValue === void 0 || fieldValue === null || fieldValue === "") {
3446
3653
  return fallback ? /* @__PURE__ */ jsx(Tag, { className, children: fallback }) : null;
3447
3654
  }