@kgalexander/mcreate 0.0.16 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  // src/core/index.tsx
2
- import { useMemo as useMemo18, useState as useState17, useEffect as useEffect21, useCallback as useCallback18, useRef as useRef12 } from "react";
2
+ import { useMemo as useMemo18, useState as useState17, useEffect as useEffect16, useCallback as useCallback20, useRef as useRef12 } from "react";
3
3
  import { cloneDeep as cloneDeep2, isEqual, debounce } from "lodash";
4
4
 
5
5
  // src/core/utils/idx.ts
@@ -215,6 +215,7 @@ function formatOpenHouseTime(time24) {
215
215
  // src/core/editor/constant/configuration.ts
216
216
  import { AlignCenterIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, Heading1Icon, Heading2Icon, Heading3Icon, LinkIcon, ListIcon, ListOrderedIcon, MailIcon, PhoneIcon, Pilcrow } from "lucide-react";
217
217
  var MAX_TEMPLATE_SIZE = 50 * 1024;
218
+ var SIZE_TRACKING_THRESHOLD = 40 * 1024;
218
219
  var BUTTON_ALIGNMENTS = ["left", "center", "right"];
219
220
  var ALIGNMENT_ICONS = {
220
221
  left: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-left.svg",
@@ -472,8 +473,8 @@ function propertyCardMockMjml(block, context) {
472
473
  ${isBrokerage ? brokerageHtml : ""}
473
474
  ${isDescription && description ? `
474
475
  <tr>
475
- <td style="padding: 0px 0px 0px 0px; font-size: 14px; line-height: 1.5; text-align: left; color: ${textColor};">
476
- ${description}
476
+ <td style="padding: 0px 0px 0px 0px; font-size: 14px; line-height: 1.5; text-align: left; color: ${textColor}; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;">
477
+ ${description.length > 200 ? description.slice(0, 200) + "..." : description}
477
478
  </td>
478
479
  </tr>
479
480
  ` : ""}
@@ -592,8 +593,8 @@ function propertyCardSingleTwoMockMjml(block, context) {
592
593
  ` : "";
593
594
  const descriptionHtml = description ? `
594
595
  <tr>
595
- <td style="padding: 0px 0px 0px 0px; font-weight: 400; font-size: 14px; line-height: 1.5; text-align: left; color: ${textColor};">
596
- ${description}
596
+ <td style="padding: 0px 0px 0px 0px; font-weight: 400; font-size: 14px; line-height: 1.5; text-align: left; color: ${textColor}; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;">
597
+ ${description.length > 200 ? description.slice(0, 200) + "..." : description}
597
598
  </td>
598
599
  </tr>
599
600
  ` : "";
@@ -727,7 +728,7 @@ function renderCard(child, childIdx, context, uniqueId, borderRadius, imageHeigh
727
728
  <span style="color:#d1d1d5">|</span>
728
729
  <b>${sqft}</b>&nbsp;<abbr title="square feet" style="text-decoration:none">sqft</abbr>
729
730
  </p>
730
- <p style="font-family:${fontFamily};font-size:12px;line-height:16px;font-weight:400;color:${textColor};font-style:normal;margin:0;padding:0">${city}</p>
731
+ <p class="property-triple-city-${uniqueId}" style="width: 140px; font-family:${fontFamily};font-size:12px;line-height:16px;font-weight:400;color:${textColor};font-style:normal;margin:0;padding:0;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${city}</p>
731
732
  </td>
732
733
  </tr>
733
734
  </tbody>
@@ -803,6 +804,9 @@ function propertyCardTripleMockMjml(block, context) {
803
804
  .property-triple-section-column {
804
805
  width: 100% !important;
805
806
  }
807
+ .property-triple-city-${uniqueId} {
808
+ width: 135px !important;
809
+ }
806
810
  }
807
811
  </style>
808
812
  </mj-raw>
@@ -1817,6 +1821,8 @@ var useEditorStore = create()(
1817
1821
  onToast: null,
1818
1822
  onExit: null,
1819
1823
  onImageUpload: null,
1824
+ onDuplicate: null,
1825
+ onDelete: null,
1820
1826
  previewMode: false,
1821
1827
  focusIdx: null,
1822
1828
  hoverIdx: null,
@@ -1831,6 +1837,7 @@ var useEditorStore = create()(
1831
1837
  tiptapEditor: null,
1832
1838
  templateSize: calculateTemplateSize(defaultTemplate),
1833
1839
  isAtSizeLimit: false,
1840
+ sizeTrackingMode: calculateTemplateSize(defaultTemplate) >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling",
1834
1841
  // Undo/Redo history
1835
1842
  history: [],
1836
1843
  historyIndex: -1,
@@ -1847,8 +1854,16 @@ var useEditorStore = create()(
1847
1854
  mergeFields: [],
1848
1855
  // Render sync
1849
1856
  renderSyncNeeded: 0,
1857
+ // Unconditionally recalculate template size and update tracking mode
1858
+ recheckTemplateSize: () => {
1859
+ set((state) => {
1860
+ state.templateSize = calculateTemplateSize(state.template);
1861
+ state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
1862
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
1863
+ });
1864
+ },
1850
1865
  // Initialize store with external template (for npm package usage)
1851
- initializeWithTemplate: (templateId, template, onSave, onToast, data, onExit, onImageUpload) => {
1866
+ initializeWithTemplate: (templateId, template, onSave, onToast, data, onExit, onImageUpload, onDuplicate, onDelete) => {
1852
1867
  set((state) => {
1853
1868
  state.templateId = templateId;
1854
1869
  state.template = template;
@@ -1856,6 +1871,8 @@ var useEditorStore = create()(
1856
1871
  state.onToast = onToast ?? null;
1857
1872
  state.onExit = onExit ?? null;
1858
1873
  state.onImageUpload = onImageUpload ?? null;
1874
+ state.onDuplicate = onDuplicate ?? null;
1875
+ state.onDelete = onDelete ?? null;
1859
1876
  state.isPaidLevel = data?.isPaidLevel ?? 0;
1860
1877
  state.images = data?.images ?? [];
1861
1878
  state.userData = data?.userData ?? null;
@@ -1865,6 +1882,7 @@ var useEditorStore = create()(
1865
1882
  }));
1866
1883
  state.templateSize = calculateTemplateSize(template);
1867
1884
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
1885
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
1868
1886
  state.history = [cloneDeep(template)];
1869
1887
  state.historyIndex = 0;
1870
1888
  state.focusIdx = null;
@@ -2031,6 +2049,7 @@ var useEditorStore = create()(
2031
2049
  children.splice(positionIndex, 0, newElement);
2032
2050
  state.templateSize = calculateTemplateSize(state.template);
2033
2051
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2052
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2034
2053
  if (type !== "text") {
2035
2054
  state.focusIdx = `${parentIdx}.children.[${positionIndex}]`;
2036
2055
  }
@@ -2070,6 +2089,7 @@ var useEditorStore = create()(
2070
2089
  children.splice(sectionPositionIndex, 0, newSection);
2071
2090
  state.templateSize = calculateTemplateSize(state.template);
2072
2091
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2092
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2073
2093
  if (type !== "text") {
2074
2094
  state.focusIdx = `${pageIdx}.children.[${sectionPositionIndex}].children.[0].children.[0]`;
2075
2095
  }
@@ -2151,8 +2171,11 @@ var useEditorStore = create()(
2151
2171
  updateElementContent: (contentIdx, content) => {
2152
2172
  set((state) => {
2153
2173
  setValueAtPath(state.template, contentIdx, content);
2154
- state.templateSize = calculateTemplateSize(state.template);
2155
- state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2174
+ if (state.sizeTrackingMode === "realtime") {
2175
+ state.templateSize = calculateTemplateSize(state.template);
2176
+ state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2177
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2178
+ }
2156
2179
  });
2157
2180
  },
2158
2181
  // Delete element
@@ -2298,8 +2321,11 @@ var useEditorStore = create()(
2298
2321
  state.focusIdx = null;
2299
2322
  }
2300
2323
  }
2301
- state.templateSize = calculateTemplateSize(state.template);
2302
- state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2324
+ if (state.sizeTrackingMode === "realtime") {
2325
+ state.templateSize = calculateTemplateSize(state.template);
2326
+ state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2327
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2328
+ }
2303
2329
  });
2304
2330
  useEditorStore.getState().pushHistory();
2305
2331
  },
@@ -2324,6 +2350,7 @@ var useEditorStore = create()(
2324
2350
  children.splice(sourceIndex + 1, 0, clonedElement);
2325
2351
  state.templateSize = calculateTemplateSize(state.template);
2326
2352
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2353
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2327
2354
  state.focusIdx = `${parentIdx}.children.[${sourceIndex + 1}]`;
2328
2355
  });
2329
2356
  useEditorStore.getState().pushHistory();
@@ -2511,6 +2538,7 @@ var useEditorStore = create()(
2511
2538
  state.focusIdx = `${parentIdx}.children.[${adjustedIndex + 1}]`;
2512
2539
  state.templateSize = calculateTemplateSize(state.template);
2513
2540
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2541
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2514
2542
  });
2515
2543
  useEditorStore.getState().pushHistory();
2516
2544
  },
@@ -2617,6 +2645,7 @@ var useEditorStore = create()(
2617
2645
  state.focusIdx = `${pageIdx}.children.[${adjustedSectionIndex + 1}]`;
2618
2646
  state.templateSize = calculateTemplateSize(state.template);
2619
2647
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2648
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2620
2649
  });
2621
2650
  useEditorStore.getState().pushHistory();
2622
2651
  },
@@ -2705,6 +2734,7 @@ var useEditorStore = create()(
2705
2734
  }
2706
2735
  state.templateSize = calculateTemplateSize(state.template);
2707
2736
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2737
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2708
2738
  });
2709
2739
  useEditorStore.getState().pushHistory();
2710
2740
  },
@@ -2793,6 +2823,7 @@ var useEditorStore = create()(
2793
2823
  }
2794
2824
  state.templateSize = calculateTemplateSize(state.template);
2795
2825
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2826
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2796
2827
  });
2797
2828
  useEditorStore.getState().pushHistory();
2798
2829
  },
@@ -2956,6 +2987,7 @@ var useEditorStore = create()(
2956
2987
  state.textEditing = null;
2957
2988
  state.templateSize = calculateTemplateSize(state.template);
2958
2989
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
2990
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2959
2991
  });
2960
2992
  setTimeout(() => {
2961
2993
  set((state) => {
@@ -2975,6 +3007,7 @@ var useEditorStore = create()(
2975
3007
  state.textEditing = null;
2976
3008
  state.templateSize = calculateTemplateSize(state.template);
2977
3009
  state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
3010
+ state.sizeTrackingMode = state.templateSize >= SIZE_TRACKING_THRESHOLD ? "realtime" : "polling";
2978
3011
  });
2979
3012
  setTimeout(() => {
2980
3013
  set((state) => {
@@ -3386,7 +3419,7 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3386
3419
 
3387
3420
  background-color: var(--background);
3388
3421
  border-radius: 4px;
3389
- padding: 4px;
3422
+ padding: 0px;
3390
3423
  border: 1px solid var(--border);
3391
3424
  color: #000000;
3392
3425
  }
@@ -10798,7 +10831,7 @@ var index_default = Link;
10798
10831
 
10799
10832
  // src/core/editor/components/tiptap-overlay.tsx
10800
10833
  import { useFloating as useFloating4, autoUpdate as autoUpdate2, offset as offset4 } from "@floating-ui/react";
10801
- import { useEffect as useEffect7, useRef as useRef5, useMemo as useMemo4, useState as useState3 } from "react";
10834
+ import { useEffect as useEffect6, useRef as useRef5, useMemo as useMemo4, useState as useState3 } from "react";
10802
10835
 
10803
10836
  // src/core/editor/extensions/inverse-placeholder.ts
10804
10837
  import { Plugin as Plugin12, PluginKey as PluginKey10 } from "@tiptap/pm/state";
@@ -11200,7 +11233,7 @@ function TooltipContent({
11200
11233
  import { BotIcon } from "lucide-react";
11201
11234
 
11202
11235
  // src/core/editor/components/text-link-menu.tsx
11203
- import { useState as useState2, useEffect as useEffect6 } from "react";
11236
+ import { useState as useState2, useCallback as useCallback4 } from "react";
11204
11237
 
11205
11238
  // src/components/ui/input.tsx
11206
11239
  import { jsx as jsx16 } from "react/jsx-runtime";
@@ -11315,12 +11348,13 @@ var TextLinkMenu = ({ editor }) => {
11315
11348
  const [isLinkTypeOpen, setIsLinkTypeOpen] = useState2(false);
11316
11349
  const currentHref = editor.getAttributes("link").href || "";
11317
11350
  const hasLink = !!currentHref;
11318
- useEffect6(() => {
11319
- if (isOpen) {
11351
+ const handleOpenChange = useCallback4((open) => {
11352
+ setIsOpen(open);
11353
+ if (open) {
11320
11354
  setLinkType(detectLinkType(currentHref));
11321
11355
  setInputValue(stripPrefix(currentHref));
11322
11356
  }
11323
- }, [isOpen, currentHref]);
11357
+ }, [currentHref]);
11324
11358
  const handleInputChange = (e) => {
11325
11359
  setInputValue(e.target.value);
11326
11360
  };
@@ -11357,7 +11391,7 @@ var TextLinkMenu = ({ editor }) => {
11357
11391
  editor.chain().focus().unsetLink().run();
11358
11392
  setInputValue("");
11359
11393
  };
11360
- return /* @__PURE__ */ jsxs7(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
11394
+ return /* @__PURE__ */ jsxs7(Popover, { open: isOpen, onOpenChange: handleOpenChange, children: [
11361
11395
  /* @__PURE__ */ jsxs7(Tooltip, { children: [
11362
11396
  /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(PopoverTrigger, { asChild: true, children: hasLink ? /* @__PURE__ */ jsx20(
11363
11397
  Button,
@@ -11696,6 +11730,27 @@ function focusAdjacentElement(adjacentIdx, storeRefs) {
11696
11730
  storeRefs.setFocusIdx.current(adjacentIdx);
11697
11731
  }
11698
11732
  }
11733
+ var SHADOW_INNER_DIV = ":scope > div";
11734
+ function syncShadowHeight(shadowEl, heightPx) {
11735
+ shadowEl.style.height = heightPx;
11736
+ shadowEl.style.minHeight = heightPx;
11737
+ shadowEl.style.overflow = "hidden";
11738
+ const inner = shadowEl.querySelector(SHADOW_INNER_DIV);
11739
+ if (inner) {
11740
+ inner.style.height = heightPx;
11741
+ inner.style.minHeight = "0";
11742
+ }
11743
+ }
11744
+ function clearShadowHeight(shadowEl) {
11745
+ shadowEl.style.height = "";
11746
+ shadowEl.style.minHeight = "";
11747
+ shadowEl.style.overflow = "";
11748
+ const inner = shadowEl.querySelector(SHADOW_INNER_DIV);
11749
+ if (inner) {
11750
+ inner.style.height = "";
11751
+ inner.style.minHeight = "";
11752
+ }
11753
+ }
11699
11754
  function handleDeleteEntireElement(currentElementIdx, storeRefs, event, skipAutoFocus) {
11700
11755
  event.preventDefault();
11701
11756
  const parentIdx = getParentIdx(currentElementIdx);
@@ -11819,7 +11874,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11819
11874
  const lastSizeLimitToastRef = useRef5(0);
11820
11875
  const hasContentChangedRef = useRef5(false);
11821
11876
  const storeRefs = useEditorStoreRefs();
11822
- useEffect7(() => {
11877
+ useEffect6(() => {
11823
11878
  return () => {
11824
11879
  const isUndoRedoAction = useEditorStore.getState().isUndoRedoAction;
11825
11880
  if (hasContentChangedRef.current && !isUndoRedoAction) {
@@ -11827,24 +11882,32 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11827
11882
  }
11828
11883
  };
11829
11884
  }, []);
11830
- useEffect7(() => {
11885
+ useEffect6(() => {
11831
11886
  const container = containerRef.current;
11832
11887
  if (!container) return;
11833
11888
  const observer = new ResizeObserver(() => {
11834
11889
  const shadowEl = getShadowElement();
11835
- if (shadowEl) {
11836
- shadowEl.style.height = `${container.offsetHeight}px`;
11837
- }
11890
+ if (shadowEl) syncShadowHeight(shadowEl, `${container.offsetHeight}px`);
11838
11891
  });
11839
11892
  observer.observe(container);
11840
11893
  return () => {
11841
11894
  observer.disconnect();
11842
11895
  const shadowEl = getShadowElement();
11843
- if (shadowEl) {
11844
- shadowEl.style.height = "";
11845
- }
11896
+ if (shadowEl) clearShadowHeight(shadowEl);
11846
11897
  };
11847
11898
  }, [getShadowElement]);
11899
+ const contentAtIdx = useEditorStore((s) => {
11900
+ const el = getValueByIdx(s.template, idx);
11901
+ return el?.data?.value?.content ?? "";
11902
+ });
11903
+ useEffect6(() => {
11904
+ const raf = requestAnimationFrame(() => {
11905
+ const container = containerRef.current;
11906
+ const shadowEl = getShadowElement();
11907
+ if (container && shadowEl) syncShadowHeight(shadowEl, `${container.offsetHeight}px`);
11908
+ });
11909
+ return () => cancelAnimationFrame(raf);
11910
+ }, [contentAtIdx, getShadowElement]);
11848
11911
  const cleanedContent = useMemo4(() => {
11849
11912
  return content.replace(NBSP_P_CONTENT_REGEX, "<p$1></p>").replace(IS_EMPTY_P_CLASS_REGEX, "").replace(IS_EMPTY_HEADING_CLASS_REGEX, "");
11850
11913
  }, [content]);
@@ -11872,7 +11935,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11872
11935
  // Move up by reference height to overlay exactly
11873
11936
  ]
11874
11937
  });
11875
- useEffect7(() => {
11938
+ useEffect6(() => {
11876
11939
  const rect = getReferenceRect();
11877
11940
  if (!rect || !refs.floating.current) return;
11878
11941
  refs.setPositionReference(virtualReference);
@@ -12012,6 +12075,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
12012
12075
  }
12013
12076
  return true;
12014
12077
  }
12078
+ requestAnimationFrame(() => useEditorStore.getState().recheckTemplateSize());
12015
12079
  return false;
12016
12080
  }
12017
12081
  },
@@ -12056,7 +12120,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
12056
12120
  }
12057
12121
  });
12058
12122
  const [currentLinkHref, setCurrentLinkHref] = useState3("");
12059
- useEffect7(() => {
12123
+ useEffect6(() => {
12060
12124
  if (!editor) return;
12061
12125
  setTiptapEditor(editor);
12062
12126
  const updateLinkHref = () => {
@@ -12071,7 +12135,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
12071
12135
  editor.off("transaction", updateLinkHref);
12072
12136
  };
12073
12137
  }, [editor, setTiptapEditor]);
12074
- useEffect7(() => {
12138
+ useEffect6(() => {
12075
12139
  if (editor) {
12076
12140
  const timer = setTimeout(() => {
12077
12141
  if (cursorPosition === "end") {
@@ -12100,7 +12164,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
12100
12164
  return () => clearTimeout(timer);
12101
12165
  }
12102
12166
  }, [editor, clickX, clickY, cursorPosition]);
12103
- useEffect7(() => {
12167
+ useEffect6(() => {
12104
12168
  const handleClickOutside = (e) => {
12105
12169
  const target = e.target;
12106
12170
  if (containerRef.current && containerRef.current.contains(target)) {
@@ -12132,7 +12196,9 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
12132
12196
  style: {
12133
12197
  ...floatingStyles,
12134
12198
  width: initialWidth,
12135
- minHeight: initialHeight,
12199
+ // Do not use minHeight: initialHeight — it prevents the container from shrinking when
12200
+ // line spacing (or content) is reduced while editing; height only updated on exit otherwise.
12201
+ minHeight: 0,
12136
12202
  zIndex: 50,
12137
12203
  // Apply all container styles for exact matching
12138
12204
  fontFamily: styles.fontFamily,
@@ -12224,7 +12290,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
12224
12290
  .tiptap-overlay .ProseMirror .merge-field-tag {
12225
12291
  background-color: var(--background);
12226
12292
  border-radius: 4px;
12227
- padding: 4px;
12293
+ padding: 0px;
12228
12294
  border: 1px solid var(--border);
12229
12295
  color: #000000;
12230
12296
  }
@@ -12279,7 +12345,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
12279
12345
  };
12280
12346
 
12281
12347
  // src/core/editor/components/element-float.tsx
12282
- import { useEffect as useEffect13, useMemo as useMemo12 } from "react";
12348
+ import { useEffect as useEffect8, useMemo as useMemo12 } from "react";
12283
12349
  import { useFloating as useFloating5, offset as offset5, shift as shift4, flip as flip3, autoUpdate as autoUpdate3 } from "@floating-ui/react";
12284
12350
 
12285
12351
  // src/core/editor/components/float-ui/actions/delete-button.tsx
@@ -12333,7 +12399,7 @@ var DuplicateButton = () => {
12333
12399
  };
12334
12400
 
12335
12401
  // src/core/editor/components/href-menu.tsx
12336
- import { useState as useState4, useEffect as useEffect8, useCallback as useCallback5, useMemo as useMemo6 } from "react";
12402
+ import { useState as useState4, useCallback as useCallback6, useMemo as useMemo6 } from "react";
12337
12403
 
12338
12404
  // src/components/ui/dropdown-menu.tsx
12339
12405
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
@@ -12460,7 +12526,7 @@ function DropdownMenuSubContent({
12460
12526
  import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon3, LinkIcon as LinkIcon3, PencilIcon as PencilIcon2, TrashIcon as TrashIcon3 } from "lucide-react";
12461
12527
 
12462
12528
  // src/core/editor/hooks/use-href.ts
12463
- import { useMemo as useMemo5, useCallback as useCallback4 } from "react";
12529
+ import { useMemo as useMemo5, useCallback as useCallback5 } from "react";
12464
12530
  import { get as lodashGet2 } from "lodash";
12465
12531
  var useHref = () => {
12466
12532
  const { focusIdx, updateElement, template } = useEditorStore();
@@ -12475,19 +12541,19 @@ var useHref = () => {
12475
12541
  href: el?.attributes?.href || ""
12476
12542
  };
12477
12543
  }, [focusIdx, template]);
12478
- const setHref = useCallback4((url) => {
12544
+ const setHref = useCallback5((url) => {
12479
12545
  if (!focusIdx || !element) return;
12480
12546
  updateElement(focusIdx, {
12481
12547
  attributes: { ...element.attributes, href: url }
12482
12548
  });
12483
12549
  }, [focusIdx, element, updateElement]);
12484
- const clearHref = useCallback4(() => {
12550
+ const clearHref = useCallback5(() => {
12485
12551
  if (!focusIdx || !element) return;
12486
12552
  updateElement(focusIdx, {
12487
12553
  attributes: { ...element.attributes, href: "" }
12488
12554
  });
12489
12555
  }, [focusIdx, element, updateElement]);
12490
- const copyHref = useCallback4(async () => {
12556
+ const copyHref = useCallback5(async () => {
12491
12557
  if (href) {
12492
12558
  try {
12493
12559
  await navigator.clipboard.writeText(href);
@@ -12526,17 +12592,18 @@ var HrefMenu = () => {
12526
12592
  const query = inputValue.toLowerCase();
12527
12593
  return all.filter((p) => p.value.toLowerCase().includes(query));
12528
12594
  }, [linkType.name, userData, inputValue]);
12529
- const handlePresetSelect = useCallback5((value) => {
12595
+ const handlePresetSelect = useCallback6((value) => {
12530
12596
  setInputValue(value);
12531
12597
  setIsPresetOpen(false);
12532
12598
  }, []);
12533
- useEffect8(() => {
12534
- if (isOpen) {
12599
+ const handleOpenChange = useCallback6((open) => {
12600
+ setIsOpen(open);
12601
+ if (open) {
12535
12602
  setLinkType(detectLinkType(href));
12536
12603
  setInputValue(stripPrefix(href));
12537
12604
  setIsPresetOpen(true);
12538
12605
  }
12539
- }, [isOpen, href]);
12606
+ }, [href]);
12540
12607
  const handleInputChange = (e) => {
12541
12608
  setInputValue(e.target.value);
12542
12609
  setIsPresetOpen(true);
@@ -12581,7 +12648,7 @@ var HrefMenu = () => {
12581
12648
  setHref(buildHref(inputValue));
12582
12649
  setIsOpen(false);
12583
12650
  };
12584
- return /* @__PURE__ */ jsxs13(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
12651
+ return /* @__PURE__ */ jsxs13(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [
12585
12652
  /* @__PURE__ */ jsxs13(Tooltip, { children: [
12586
12653
  /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx26(
12587
12654
  Button,
@@ -12750,7 +12817,7 @@ var ButtonFloat = () => {
12750
12817
  import { ChevronsLeftRightIcon, ChevronsRightLeftIcon, MoreHorizontalIcon } from "lucide-react";
12751
12818
 
12752
12819
  // src/core/editor/hooks/use-full-width-toggle.ts
12753
- import { useCallback as useCallback6, useMemo as useMemo7 } from "react";
12820
+ import { useCallback as useCallback7, useMemo as useMemo7 } from "react";
12754
12821
  import { get as lodashGet3 } from "lodash";
12755
12822
  function useFullWidthToggle() {
12756
12823
  const { focusIdx, template, updateElement } = useEditorStore();
@@ -12763,7 +12830,7 @@ function useFullWidthToggle() {
12763
12830
  isFullWidth: el?.attributes?.["full-width"] === "full-width"
12764
12831
  };
12765
12832
  }, [focusIdx, template]);
12766
- const handleToggleFullWidth = useCallback6(() => {
12833
+ const handleToggleFullWidth = useCallback7(() => {
12767
12834
  if (!focusIdx || !element) return;
12768
12835
  const newAttributes = { ...element.attributes };
12769
12836
  if (isFullWidth) {
@@ -12800,7 +12867,7 @@ var SectionFloat = () => {
12800
12867
  import { CheckIcon as CheckIcon4, ChevronsLeftRightIcon as ChevronsLeftRightIcon2, ChevronsRightLeftIcon as ChevronsRightLeftIcon2, Layers2Icon, MoreHorizontalIcon as MoreHorizontalIcon2 } from "lucide-react";
12801
12868
 
12802
12869
  // src/core/editor/hooks/use-no-wrap.ts
12803
- import { useCallback as useCallback7, useMemo as useMemo8 } from "react";
12870
+ import { useCallback as useCallback8, useMemo as useMemo8 } from "react";
12804
12871
  import { get as lodashGet4 } from "lodash";
12805
12872
  function useNoWrap() {
12806
12873
  const { focusIdx, template, updateElement } = useEditorStore();
@@ -12813,7 +12880,7 @@ function useNoWrap() {
12813
12880
  noWrap: el?.data?.value?.noWrap === true
12814
12881
  };
12815
12882
  }, [focusIdx, template]);
12816
- const handleToggleNoWrap = useCallback7(() => {
12883
+ const handleToggleNoWrap = useCallback8(() => {
12817
12884
  if (!focusIdx || !element) return;
12818
12885
  updateElement(focusIdx, {
12819
12886
  data: {
@@ -12941,10 +13008,10 @@ function Textarea({ className, ...props }) {
12941
13008
 
12942
13009
  // src/core/editor/components/element-gear/social-item/float.tsx
12943
13010
  import { Accessibility, MoreHorizontalIcon as MoreHorizontalIcon4, TrashIcon as TrashIcon4 } from "lucide-react";
12944
- import { useState as useState7, useEffect as useEffect10 } from "react";
13011
+ import { useState as useState7, useCallback as useCallback11 } from "react";
12945
13012
 
12946
13013
  // src/core/editor/components/social-item-menu.tsx
12947
- import { useState as useState6, useEffect as useEffect9, useMemo as useMemo9, useCallback as useCallback8 } from "react";
13014
+ import { useState as useState6, useMemo as useMemo9, useCallback as useCallback9 } from "react";
12948
13015
  import { PencilIcon as PencilIcon3, CheckIcon as CheckIcon5, CopyIcon as CopyIcon4 } from "lucide-react";
12949
13016
  import { get as lodashGet5 } from "lodash";
12950
13017
  import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
@@ -12961,18 +13028,19 @@ var SocialItemMenu = ({ hasHref }) => {
12961
13028
  return lodashGet5(template, path);
12962
13029
  }, [focusIdx, template]);
12963
13030
  const content = element?.data?.value?.content || "";
12964
- useEffect9(() => {
12965
- if (isOpen) {
13031
+ const handleOpenChange = useCallback9((open) => {
13032
+ setIsOpen(open);
13033
+ if (open) {
12966
13034
  setHrefInputValue(href);
12967
13035
  setContentInputValue(content);
12968
13036
  }
12969
- }, [isOpen, href, content]);
12970
- const handleCopy = useCallback8(async () => {
13037
+ }, [href, content]);
13038
+ const handleCopy = useCallback9(async () => {
12971
13039
  await copyHref();
12972
13040
  setShowCopied(true);
12973
13041
  setTimeout(() => setShowCopied(false), 2e3);
12974
13042
  }, [copyHref]);
12975
- const handleDone = useCallback8(() => {
13043
+ const handleDone = useCallback9(() => {
12976
13044
  setHref(normalizeWebsiteUrl(hrefInputValue));
12977
13045
  if (focusIdx && element) {
12978
13046
  updateElement(focusIdx, {
@@ -12986,7 +13054,7 @@ var SocialItemMenu = ({ hasHref }) => {
12986
13054
  }
12987
13055
  setIsOpen(false);
12988
13056
  }, [hrefInputValue, contentInputValue, setHref, focusIdx, element, updateElement]);
12989
- return /* @__PURE__ */ jsxs19(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
13057
+ return /* @__PURE__ */ jsxs19(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [
12990
13058
  /* @__PURE__ */ jsxs19(Tooltip, { children: [
12991
13059
  /* @__PURE__ */ jsx34(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx34(
12992
13060
  Button,
@@ -13068,7 +13136,7 @@ var SocialItemMenu = ({ hasHref }) => {
13068
13136
  };
13069
13137
 
13070
13138
  // src/core/editor/hooks/use-alt.ts
13071
- import { useMemo as useMemo10, useCallback as useCallback9 } from "react";
13139
+ import { useMemo as useMemo10, useCallback as useCallback10 } from "react";
13072
13140
  import { get as lodashGet6 } from "lodash";
13073
13141
  var useAlt = () => {
13074
13142
  const { focusIdx, updateElement, template } = useEditorStore();
@@ -13083,13 +13151,13 @@ var useAlt = () => {
13083
13151
  alt: el?.attributes?.alt || ""
13084
13152
  };
13085
13153
  }, [focusIdx, template]);
13086
- const setAlt = useCallback9((text2) => {
13154
+ const setAlt = useCallback10((text2) => {
13087
13155
  if (!focusIdx || !element) return;
13088
13156
  updateElement(focusIdx, {
13089
13157
  attributes: { ...element.attributes, alt: text2 }
13090
13158
  });
13091
13159
  }, [focusIdx, element, updateElement]);
13092
- const clearAlt = useCallback9(() => {
13160
+ const clearAlt = useCallback10(() => {
13093
13161
  if (!focusIdx || !element) return;
13094
13162
  updateElement(focusIdx, {
13095
13163
  attributes: { ...element.attributes, alt: "" }
@@ -13115,11 +13183,12 @@ var SocialItemFloat = () => {
13115
13183
  const parentSocial = focusIdx ? getParentByIdx(template, focusIdx) : null;
13116
13184
  const childrenCount = parentSocial?.children?.length || 0;
13117
13185
  const canDelete = childrenCount > 1;
13118
- useEffect10(() => {
13119
- if (dropdownOpen) {
13186
+ const handleDropdownOpenChange = useCallback11((open) => {
13187
+ setDropdownOpen(open);
13188
+ if (open) {
13120
13189
  setAltInputValue(alt);
13121
13190
  }
13122
- }, [dropdownOpen, alt]);
13191
+ }, [alt]);
13123
13192
  const handleSaveAlt = () => {
13124
13193
  setAlt(altInputValue);
13125
13194
  setDropdownOpen(false);
@@ -13145,7 +13214,7 @@ var SocialItemFloat = () => {
13145
13214
  ) }),
13146
13215
  /* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", children: canDelete ? "Delete" : "Cannot delete last item" })
13147
13216
  ] }),
13148
- /* @__PURE__ */ jsxs20(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
13217
+ /* @__PURE__ */ jsxs20(DropdownMenu, { open: dropdownOpen, onOpenChange: handleDropdownOpenChange, children: [
13149
13218
  /* @__PURE__ */ jsxs20(Tooltip, { children: [
13150
13219
  /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx35(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx35(MoreHorizontalIcon4, { className: "w-4 h-4" }) }) }) }),
13151
13220
  /* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", children: "More" })
@@ -13203,7 +13272,7 @@ var DividerFloat = () => {
13203
13272
  // src/core/editor/components/element-gear/image/float.tsx
13204
13273
  import { Accessibility as Accessibility2, CheckIcon as CheckIcon6, MoreHorizontalIcon as MoreHorizontalIcon5, Proportions } from "lucide-react";
13205
13274
  import lodashGet7 from "lodash/get";
13206
- import { useState as useState8, useEffect as useEffect11, useMemo as useMemo11, useCallback as useCallback10 } from "react";
13275
+ import { useState as useState8, useMemo as useMemo11, useCallback as useCallback12 } from "react";
13207
13276
  import { Fragment as Fragment13, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
13208
13277
  var ImageFloat = () => {
13209
13278
  const { href, hasHref } = useHref();
@@ -13221,7 +13290,7 @@ var ImageFloat = () => {
13221
13290
  isFluidOnMobile: el?.attributes?.["fluid-on-mobile"] === "true"
13222
13291
  };
13223
13292
  }, [focusIdx, template]);
13224
- const toggleFluidOnMobile = useCallback10(() => {
13293
+ const toggleFluidOnMobile = useCallback12(() => {
13225
13294
  if (!focusIdx || !element) return;
13226
13295
  const newAttributes = { ...element.attributes };
13227
13296
  if (isFluidOnMobile) {
@@ -13231,11 +13300,12 @@ var ImageFloat = () => {
13231
13300
  }
13232
13301
  updateElement(focusIdx, { attributes: newAttributes });
13233
13302
  }, [focusIdx, element, isFluidOnMobile, updateElement]);
13234
- useEffect11(() => {
13235
- if (dropdownOpen) {
13303
+ const handleDropdownOpenChange = useCallback12((open) => {
13304
+ setDropdownOpen(open);
13305
+ if (open) {
13236
13306
  setAltInputValue(alt);
13237
13307
  }
13238
- }, [dropdownOpen, alt]);
13308
+ }, [alt]);
13239
13309
  const handleSaveAlt = () => {
13240
13310
  setAlt(altInputValue);
13241
13311
  setDropdownOpen(false);
@@ -13245,7 +13315,7 @@ var ImageFloat = () => {
13245
13315
  /* @__PURE__ */ jsx37(HrefMenu, {}),
13246
13316
  /* @__PURE__ */ jsx37(DuplicateButton, {}),
13247
13317
  /* @__PURE__ */ jsx37(DeleteButton, {}),
13248
- /* @__PURE__ */ jsxs22(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
13318
+ /* @__PURE__ */ jsxs22(DropdownMenu, { open: dropdownOpen, onOpenChange: handleDropdownOpenChange, children: [
13249
13319
  /* @__PURE__ */ jsxs22(Tooltip, { children: [
13250
13320
  /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx37(MoreHorizontalIcon5, { className: "w-4 h-4" }) }) }) }),
13251
13321
  /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", children: "More" })
@@ -13302,7 +13372,7 @@ var ImageFloat = () => {
13302
13372
  };
13303
13373
 
13304
13374
  // src/core/editor/components/mlsNumber-menu.tsx
13305
- import { useState as useState9, useEffect as useEffect12 } from "react";
13375
+ import { useState as useState9, useEffect as useEffect7 } from "react";
13306
13376
  import { HousePlusIcon, TrashIcon as TrashIcon5, XIcon as XIcon2, Loader2Icon } from "lucide-react";
13307
13377
 
13308
13378
  // src/services/repliers/commands.ts
@@ -13327,7 +13397,7 @@ var MlsNumberMenu = () => {
13327
13397
  const [isLoading, setIsLoading] = useState9(false);
13328
13398
  const propertyElement = focusIdx && template ? getValueByIdx(template, focusIdx) : null;
13329
13399
  const currentMlsNumber = propertyElement?.data?.value?.mlsNumber || "";
13330
- useEffect12(() => {
13400
+ useEffect7(() => {
13331
13401
  setInputValue(currentMlsNumber);
13332
13402
  setPropertyData(null);
13333
13403
  }, [focusIdx, currentMlsNumber]);
@@ -13600,7 +13670,7 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13600
13670
  // Keep within viewport
13601
13671
  ]
13602
13672
  });
13603
- useEffect13(() => {
13673
+ useEffect8(() => {
13604
13674
  const rect = getReferenceRect();
13605
13675
  if (!rect || !refs.floating.current) return;
13606
13676
  refs.setPositionReference(virtualReference);
@@ -13619,7 +13689,7 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13619
13689
  };
13620
13690
 
13621
13691
  // src/core/editor/components/scaling/divider-scale.tsx
13622
- import { useMemo as useMemo13, useEffect as useEffect14, useState as useState10, useRef as useRef6, useCallback as useCallback12 } from "react";
13692
+ import { useMemo as useMemo13, useEffect as useEffect9, useState as useState10, useRef as useRef6, useCallback as useCallback14 } from "react";
13623
13693
  import { useFloating as useFloating6, offset as offset6, autoUpdate as autoUpdate4 } from "@floating-ui/react";
13624
13694
  import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
13625
13695
  var DividerScale = ({ getReferenceRect }) => {
@@ -13636,12 +13706,12 @@ var DividerScale = ({ getReferenceRect }) => {
13636
13706
  return { currentWidth: width, currentAlign: align };
13637
13707
  }, [focusIdx, template]);
13638
13708
  const dragRef = useRef6(null);
13639
- const getContainerWidth = useCallback12(() => {
13709
+ const getContainerWidth = useCallback14(() => {
13640
13710
  const rect = getReferenceRect();
13641
13711
  if (!rect || currentWidth <= 0) return null;
13642
13712
  return rect.width / (currentWidth / 100);
13643
13713
  }, [getReferenceRect, currentWidth]);
13644
- const handlePointerDown = useCallback12((e, side) => {
13714
+ const handlePointerDown = useCallback14((e, side) => {
13645
13715
  e.preventDefault();
13646
13716
  e.stopPropagation();
13647
13717
  const containerWidth = getContainerWidth();
@@ -13659,7 +13729,7 @@ var DividerScale = ({ getReferenceRect }) => {
13659
13729
  document.addEventListener("pointermove", handlePointerMove);
13660
13730
  document.addEventListener("pointerup", handlePointerUp);
13661
13731
  }, [getContainerWidth, currentWidth, currentAlign, setIsScaling]);
13662
- const handlePointerMove = useCallback12((e) => {
13732
+ const handlePointerMove = useCallback14((e) => {
13663
13733
  if (!dragRef.current) return;
13664
13734
  const { startX, startWidth, containerWidth, side, align } = dragRef.current;
13665
13735
  const deltaX = e.clientX - startX;
@@ -13679,14 +13749,14 @@ var DividerScale = ({ getReferenceRect }) => {
13679
13749
  }
13680
13750
  });
13681
13751
  }, []);
13682
- const handlePointerUp = useCallback12(() => {
13752
+ const handlePointerUp = useCallback14(() => {
13683
13753
  setActiveSide(null);
13684
13754
  setIsScaling(false);
13685
13755
  dragRef.current = null;
13686
13756
  document.removeEventListener("pointermove", handlePointerMove);
13687
13757
  document.removeEventListener("pointerup", handlePointerUp);
13688
13758
  }, [handlePointerMove, setIsScaling]);
13689
- useEffect14(() => {
13759
+ useEffect9(() => {
13690
13760
  return () => {
13691
13761
  document.removeEventListener("pointermove", handlePointerMove);
13692
13762
  document.removeEventListener("pointerup", handlePointerUp);
@@ -13707,7 +13777,7 @@ var DividerScale = ({ getReferenceRect }) => {
13707
13777
  offset6(({ rects }) => -rects.reference.height)
13708
13778
  ]
13709
13779
  });
13710
- useEffect14(() => {
13780
+ useEffect9(() => {
13711
13781
  const rect = getReferenceRect();
13712
13782
  if (!rect || !refs.floating.current) return;
13713
13783
  refs.setPositionReference(virtualReference);
@@ -13766,7 +13836,7 @@ var DividerScale = ({ getReferenceRect }) => {
13766
13836
  };
13767
13837
 
13768
13838
  // src/core/editor/components/scaling/button-scale.tsx
13769
- import { useMemo as useMemo14, useEffect as useEffect15, useState as useState11, useRef as useRef7, useCallback as useCallback13 } from "react";
13839
+ import { useMemo as useMemo14, useEffect as useEffect10, useState as useState11, useRef as useRef7, useCallback as useCallback15 } from "react";
13770
13840
  import { useFloating as useFloating7, offset as offset7, autoUpdate as autoUpdate5 } from "@floating-ui/react";
13771
13841
  import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
13772
13842
  var ButtonScale = ({ getReferenceRect }) => {
@@ -13788,12 +13858,12 @@ var ButtonScale = ({ getReferenceRect }) => {
13788
13858
  return { currentWidth: width, currentHeight: height, currentAlign: align };
13789
13859
  }, [focusIdx, template]);
13790
13860
  const dragRef = useRef7(null);
13791
- const getContainerWidth = useCallback13(() => {
13861
+ const getContainerWidth = useCallback15(() => {
13792
13862
  const rect = getReferenceRect();
13793
13863
  if (!rect || currentWidth <= 0) return null;
13794
13864
  return rect.width / (currentWidth / 100);
13795
13865
  }, [getReferenceRect, currentWidth]);
13796
- const handlePointerDown = useCallback13((e, side) => {
13866
+ const handlePointerDown = useCallback15((e, side) => {
13797
13867
  e.preventDefault();
13798
13868
  e.stopPropagation();
13799
13869
  if (document.activeElement instanceof HTMLElement) {
@@ -13815,7 +13885,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13815
13885
  document.addEventListener("pointermove", handlePointerMove);
13816
13886
  document.addEventListener("pointerup", handlePointerUp);
13817
13887
  }, [getContainerWidth, currentWidth, currentHeight, currentAlign, setIsScaling]);
13818
- const handlePointerMove = useCallback13((e) => {
13888
+ const handlePointerMove = useCallback15((e) => {
13819
13889
  if (!dragRef.current) return;
13820
13890
  const { startX, startY, startWidth, startHeight, containerWidth, side, align } = dragRef.current;
13821
13891
  const state = useEditorStore.getState();
@@ -13847,14 +13917,14 @@ var ButtonScale = ({ getReferenceRect }) => {
13847
13917
  });
13848
13918
  }
13849
13919
  }, []);
13850
- const handlePointerUp = useCallback13(() => {
13920
+ const handlePointerUp = useCallback15(() => {
13851
13921
  setActiveSide(null);
13852
13922
  setIsScaling(false);
13853
13923
  dragRef.current = null;
13854
13924
  document.removeEventListener("pointermove", handlePointerMove);
13855
13925
  document.removeEventListener("pointerup", handlePointerUp);
13856
13926
  }, [handlePointerMove, setIsScaling]);
13857
- useEffect15(() => {
13927
+ useEffect10(() => {
13858
13928
  return () => {
13859
13929
  document.removeEventListener("pointermove", handlePointerMove);
13860
13930
  document.removeEventListener("pointerup", handlePointerUp);
@@ -13875,7 +13945,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13875
13945
  offset7(({ rects }) => -rects.reference.height)
13876
13946
  ]
13877
13947
  });
13878
- useEffect15(() => {
13948
+ useEffect10(() => {
13879
13949
  const rect = getReferenceRect();
13880
13950
  if (!rect || !refs.floating.current) return;
13881
13951
  refs.setPositionReference(virtualReference);
@@ -13950,7 +14020,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13950
14020
  };
13951
14021
 
13952
14022
  // src/core/editor/components/scaling/image-scale.tsx
13953
- import { useMemo as useMemo15, useEffect as useEffect16, useState as useState12, useRef as useRef8, useCallback as useCallback14 } from "react";
14023
+ import { useMemo as useMemo15, useEffect as useEffect11, useState as useState12, useRef as useRef8, useCallback as useCallback16 } from "react";
13954
14024
  import { useFloating as useFloating8, offset as offset8, autoUpdate as autoUpdate6 } from "@floating-ui/react";
13955
14025
  import { jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
13956
14026
  var isCorner = (side) => side === "top-left" || side === "top-right" || side === "bottom-left" || side === "bottom-right";
@@ -13973,7 +14043,7 @@ var ImageScale = ({ getReferenceRect }) => {
13973
14043
  return { currentWidth: width, currentHeight: height, currentAlign: align };
13974
14044
  }, [focusIdx, template]);
13975
14045
  const dragRef = useRef8(null);
13976
- const handlePointerDown = useCallback14((e, side) => {
14046
+ const handlePointerDown = useCallback16((e, side) => {
13977
14047
  e.preventDefault();
13978
14048
  e.stopPropagation();
13979
14049
  if (document.activeElement instanceof HTMLElement) {
@@ -13997,7 +14067,7 @@ var ImageScale = ({ getReferenceRect }) => {
13997
14067
  document.addEventListener("pointermove", handlePointerMove);
13998
14068
  document.addEventListener("pointerup", handlePointerUp);
13999
14069
  }, [getReferenceRect, currentWidth, currentHeight, currentAlign, setIsScaling]);
14000
- const handlePointerMove = useCallback14((e) => {
14070
+ const handlePointerMove = useCallback16((e) => {
14001
14071
  if (!dragRef.current) return;
14002
14072
  const { startX, startY, startWidth, startHeight, side, align } = dragRef.current;
14003
14073
  const state = useEditorStore.getState();
@@ -14056,14 +14126,14 @@ var ImageScale = ({ getReferenceRect }) => {
14056
14126
  });
14057
14127
  }
14058
14128
  }, []);
14059
- const handlePointerUp = useCallback14(() => {
14129
+ const handlePointerUp = useCallback16(() => {
14060
14130
  setActiveSide(null);
14061
14131
  setIsScaling(false);
14062
14132
  dragRef.current = null;
14063
14133
  document.removeEventListener("pointermove", handlePointerMove);
14064
14134
  document.removeEventListener("pointerup", handlePointerUp);
14065
14135
  }, [handlePointerMove, setIsScaling]);
14066
- useEffect16(() => {
14136
+ useEffect11(() => {
14067
14137
  return () => {
14068
14138
  document.removeEventListener("pointermove", handlePointerMove);
14069
14139
  document.removeEventListener("pointerup", handlePointerUp);
@@ -14084,7 +14154,7 @@ var ImageScale = ({ getReferenceRect }) => {
14084
14154
  offset8(({ rects }) => -rects.reference.height)
14085
14155
  ]
14086
14156
  });
14087
- useEffect16(() => {
14157
+ useEffect11(() => {
14088
14158
  const rect = getReferenceRect();
14089
14159
  if (!rect || !refs.floating.current) return;
14090
14160
  refs.setPositionReference(virtualReference);
@@ -14191,7 +14261,7 @@ var ImageScale = ({ getReferenceRect }) => {
14191
14261
  };
14192
14262
 
14193
14263
  // src/core/editor/components/scaling/spacer-scale.tsx
14194
- import { useMemo as useMemo16, useEffect as useEffect17, useState as useState13, useRef as useRef9, useCallback as useCallback15 } from "react";
14264
+ import { useMemo as useMemo16, useEffect as useEffect12, useState as useState13, useRef as useRef9, useCallback as useCallback17 } from "react";
14195
14265
  import { useFloating as useFloating9, offset as offset9, autoUpdate as autoUpdate7 } from "@floating-ui/react";
14196
14266
  import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
14197
14267
  var SpacerScale = ({ getReferenceRect }) => {
@@ -14206,7 +14276,7 @@ var SpacerScale = ({ getReferenceRect }) => {
14206
14276
  return isNaN(parsedHeight) ? 12 : Math.max(12, Math.min(200, parsedHeight));
14207
14277
  }, [focusIdx, template]);
14208
14278
  const dragRef = useRef9(null);
14209
- const handlePointerDown = useCallback15((e, side) => {
14279
+ const handlePointerDown = useCallback17((e, side) => {
14210
14280
  e.preventDefault();
14211
14281
  e.stopPropagation();
14212
14282
  if (document.activeElement instanceof HTMLElement) {
@@ -14222,7 +14292,7 @@ var SpacerScale = ({ getReferenceRect }) => {
14222
14292
  document.addEventListener("pointermove", handlePointerMove);
14223
14293
  document.addEventListener("pointerup", handlePointerUp);
14224
14294
  }, [currentHeight, setIsScaling]);
14225
- const handlePointerMove = useCallback15((e) => {
14295
+ const handlePointerMove = useCallback17((e) => {
14226
14296
  if (!dragRef.current) return;
14227
14297
  const { startY, startHeight, side } = dragRef.current;
14228
14298
  const state = useEditorStore.getState();
@@ -14240,14 +14310,14 @@ var SpacerScale = ({ getReferenceRect }) => {
14240
14310
  }
14241
14311
  });
14242
14312
  }, []);
14243
- const handlePointerUp = useCallback15(() => {
14313
+ const handlePointerUp = useCallback17(() => {
14244
14314
  setActiveSide(null);
14245
14315
  setIsScaling(false);
14246
14316
  dragRef.current = null;
14247
14317
  document.removeEventListener("pointermove", handlePointerMove);
14248
14318
  document.removeEventListener("pointerup", handlePointerUp);
14249
14319
  }, [handlePointerMove, setIsScaling]);
14250
- useEffect17(() => {
14320
+ useEffect12(() => {
14251
14321
  return () => {
14252
14322
  document.removeEventListener("pointermove", handlePointerMove);
14253
14323
  document.removeEventListener("pointerup", handlePointerUp);
@@ -14268,7 +14338,7 @@ var SpacerScale = ({ getReferenceRect }) => {
14268
14338
  offset9(({ rects }) => -rects.reference.height)
14269
14339
  ]
14270
14340
  });
14271
- useEffect17(() => {
14341
+ useEffect12(() => {
14272
14342
  const rect = getReferenceRect();
14273
14343
  if (!rect || !refs.floating.current) return;
14274
14344
  refs.setPositionReference(virtualReference);
@@ -14327,7 +14397,7 @@ var SpacerScale = ({ getReferenceRect }) => {
14327
14397
  };
14328
14398
 
14329
14399
  // src/core/editor/components/scaling/column-scale.tsx
14330
- import { useMemo as useMemo17, useEffect as useEffect18, useState as useState14, useRef as useRef10, useCallback as useCallback16 } from "react";
14400
+ import { useMemo as useMemo17, useEffect as useEffect13, useState as useState14, useRef as useRef10, useCallback as useCallback18 } from "react";
14331
14401
  import { Fragment as Fragment17, jsx as jsx47 } from "react/jsx-runtime";
14332
14402
  var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14333
14403
  const [activeDivider, setActiveDivider] = useState14(null);
@@ -14339,7 +14409,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14339
14409
  return sectionColumn?.data?.value?.columnWidths || [];
14340
14410
  }, [template, sectionColumnIdx]);
14341
14411
  const dragRef = useRef10(null);
14342
- const updateColumnRects = useCallback16(() => {
14412
+ const updateColumnRects = useCallback18(() => {
14343
14413
  if (!shadowRoot) return;
14344
14414
  const allColumns = shadowRoot.querySelectorAll(".node-type-column");
14345
14415
  const matchingColumns = [];
@@ -14371,7 +14441,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14371
14441
  });
14372
14442
  setColumnRects(rects);
14373
14443
  }, [shadowRoot, sectionColumnIdx]);
14374
- useEffect18(() => {
14444
+ useEffect13(() => {
14375
14445
  updateColumnRects();
14376
14446
  let animationId;
14377
14447
  const updateLoop = () => {
@@ -14384,7 +14454,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14384
14454
  const parseWidth = (width) => {
14385
14455
  return parseFloat(width.replace("%", ""));
14386
14456
  };
14387
- const handlePointerDown = useCallback16((e, dividerIndex) => {
14457
+ const handlePointerDown = useCallback18((e, dividerIndex) => {
14388
14458
  e.preventDefault();
14389
14459
  e.stopPropagation();
14390
14460
  stopTextEditing();
@@ -14410,7 +14480,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14410
14480
  document.addEventListener("pointermove", handlePointerMove);
14411
14481
  document.addEventListener("pointerup", handlePointerUp);
14412
14482
  }, [columnRects, columnWidths, setIsScaling]);
14413
- const handlePointerMove = useCallback16((e) => {
14483
+ const handlePointerMove = useCallback18((e) => {
14414
14484
  if (!dragRef.current) return;
14415
14485
  const { startX, leftColIndex, rightColIndex, startLeftWidth, startRightWidth, sectionWidth, allWidths } = dragRef.current;
14416
14486
  const deltaX = e.clientX - startX;
@@ -14444,14 +14514,14 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14444
14514
  }
14445
14515
  });
14446
14516
  }, [sectionColumnIdx]);
14447
- const handlePointerUp = useCallback16(() => {
14517
+ const handlePointerUp = useCallback18(() => {
14448
14518
  setActiveDivider(null);
14449
14519
  setIsScaling(false);
14450
14520
  dragRef.current = null;
14451
14521
  document.removeEventListener("pointermove", handlePointerMove);
14452
14522
  document.removeEventListener("pointerup", handlePointerUp);
14453
14523
  }, [handlePointerMove, setIsScaling]);
14454
- useEffect18(() => {
14524
+ useEffect13(() => {
14455
14525
  return () => {
14456
14526
  document.removeEventListener("pointermove", handlePointerMove);
14457
14527
  document.removeEventListener("pointerup", handlePointerUp);
@@ -14490,9 +14560,9 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14490
14560
  };
14491
14561
 
14492
14562
  // src/core/editor/hooks/use-undo-redo-keyboard.ts
14493
- import { useEffect as useEffect19 } from "react";
14563
+ import { useEffect as useEffect14 } from "react";
14494
14564
  function useUndoRedoKeyboard() {
14495
- useEffect19(() => {
14565
+ useEffect14(() => {
14496
14566
  const handler = (e) => {
14497
14567
  const isMeta = e.metaKey || e.ctrlKey;
14498
14568
  if (!isMeta || e.key.toLowerCase() !== "z") return;
@@ -14531,7 +14601,7 @@ function Spinner({ className, ...props }) {
14531
14601
  import { EyeIcon, SendIcon, Monitor, Smartphone } from "lucide-react";
14532
14602
 
14533
14603
  // src/render/useMjmlCompiler.ts
14534
- import { useState as useState15, useCallback as useCallback17 } from "react";
14604
+ import { useState as useState15, useCallback as useCallback19 } from "react";
14535
14605
  async function compileMjml(mjml) {
14536
14606
  console.log("Compiling MJML", mjml);
14537
14607
  const response = await fetch("/api/mrender", {
@@ -14548,7 +14618,7 @@ async function compileMjml(mjml) {
14548
14618
  }
14549
14619
 
14550
14620
  // src/core/editor/components/preview.tsx
14551
- import { useEffect as useEffect20, useState as useState16, useRef as useRef11 } from "react";
14621
+ import { useEffect as useEffect15, useState as useState16, useRef as useRef11 } from "react";
14552
14622
 
14553
14623
  // src/validate/helpers.ts
14554
14624
  var MERGE_FIELD_REGEX2 = /\{\{([a-zA-Z_][a-zA-Z0-9_]*)\}\}/g;
@@ -14642,7 +14712,7 @@ function Preview() {
14642
14712
  const [deviceMode, setDeviceMode] = useState16("desktop");
14643
14713
  const [preview_validations, setPreviewValidations] = useState16({ invalid_merge_fields: [], missing_links: [], is_over_size_limit: false, placeholder_property_images: 0 });
14644
14714
  const [mjmlErrors, setMjmlErrors] = useState16([]);
14645
- useEffect20(() => {
14715
+ useEffect15(() => {
14646
14716
  if (typeof window === "undefined" || !previewMode) {
14647
14717
  if (!previewMode) {
14648
14718
  setHtml("");
@@ -14947,9 +15017,10 @@ function Editor({ setEditorLoading }) {
14947
15017
  const lastSyncedTemplateRef = useRef12(null);
14948
15018
  const prevTextEditingIdxRef = useRef12(null);
14949
15019
  const lastRenderSyncNeededRef = useRef12(0);
15020
+ const hasNotifiedLoadedRef = useRef12(false);
14950
15021
  const imageReplaceTargetRef = useRef12(null);
14951
15022
  const imagePreviewOriginalSrcRef = useRef12(null);
14952
- useEffect21(() => {
15023
+ useEffect16(() => {
14953
15024
  const currentIdx = textEditing?.idx ?? null;
14954
15025
  const prevIdx = prevTextEditingIdxRef.current;
14955
15026
  const switchedTarget = currentIdx !== null && prevIdx !== null && currentIdx !== prevIdx;
@@ -14964,16 +15035,15 @@ function Editor({ setEditorLoading }) {
14964
15035
  }
14965
15036
  if (!isEqual(template, renderData)) {
14966
15037
  setRenderData(cloneDeep2(template));
15038
+ if (!hasNotifiedLoadedRef.current && setEditorLoading) {
15039
+ hasNotifiedLoadedRef.current = true;
15040
+ setEditorLoading(false);
15041
+ }
14967
15042
  }
14968
15043
  lastSyncedTemplateRef.current = template;
14969
15044
  }
14970
- }, [template, renderData, isEditing, textEditing, renderSyncNeeded]);
14971
- useEffect21(() => {
14972
- if (renderData && setEditorLoading) {
14973
- setEditorLoading(false);
14974
- }
14975
- }, [renderData, setEditorLoading]);
14976
- useEffect21(() => {
15045
+ }, [template, renderData, isEditing, textEditing, renderSyncNeeded, setEditorLoading]);
15046
+ useEffect16(() => {
14977
15047
  if (!pendingTextEditRequest || !shadowRootRef.current) return;
14978
15048
  const { idx, cursorPosition } = pendingTextEditRequest;
14979
15049
  const blockNode = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
@@ -15022,7 +15092,7 @@ function Editor({ setEditorLoading }) {
15022
15092
  startTextEditing({ idx, getReferenceRect: getReferenceRect2, getShadowElement, initialWidth: blockRect.width, initialHeight: blockRect.height, clickX, clickY, content, styles, cursorPosition });
15023
15093
  clearPendingTextEditRequest();
15024
15094
  }, [pendingTextEditRequest, clearPendingTextEditRequest, startTextEditing]);
15025
- useEffect21(() => {
15095
+ useEffect16(() => {
15026
15096
  if (isDragging && dataTransfer) {
15027
15097
  const currentTemplate = useEditorStore.getState().template;
15028
15098
  templateCacheRef.current = currentTemplate;
@@ -15040,7 +15110,7 @@ function Editor({ setEditorLoading }) {
15040
15110
  }, [isDragging, dataTransfer]);
15041
15111
  const [html, setHtml] = useState17("");
15042
15112
  const lastRenderDataRef = useRef12("");
15043
- useEffect21(() => {
15113
+ useEffect16(() => {
15044
15114
  if (typeof window === "undefined" || !renderData) {
15045
15115
  setHtml("");
15046
15116
  lastRenderDataRef.current = "";
@@ -15073,7 +15143,7 @@ function Editor({ setEditorLoading }) {
15073
15143
  }, 200),
15074
15144
  [updateElementContent]
15075
15145
  );
15076
- const handleElementClick = useCallback18(
15146
+ const handleElementClick = useCallback20(
15077
15147
  (idx) => {
15078
15148
  if (isInsideCompanyFooter(idx, template)) {
15079
15149
  return;
@@ -15086,7 +15156,7 @@ function Editor({ setEditorLoading }) {
15086
15156
  },
15087
15157
  [setFocusIdx, template]
15088
15158
  );
15089
- const handleElementHover = useCallback18(
15159
+ const handleElementHover = useCallback20(
15090
15160
  (idx) => {
15091
15161
  if (!isDragging) {
15092
15162
  if (idx) {
@@ -15100,19 +15170,19 @@ function Editor({ setEditorLoading }) {
15100
15170
  },
15101
15171
  [isDragging, setHoverIdx, template]
15102
15172
  );
15103
- const handleContentInput = useCallback18(
15173
+ const handleContentInput = useCallback20(
15104
15174
  (contentIdx, content) => {
15105
15175
  debouncedUpdateContent(contentIdx, content);
15106
15176
  },
15107
15177
  [debouncedUpdateContent]
15108
15178
  );
15109
- const handleEditingStart = useCallback18(() => {
15179
+ const handleEditingStart = useCallback20(() => {
15110
15180
  setIsEditing(true);
15111
15181
  }, []);
15112
- const handleEditingEnd = useCallback18(() => {
15182
+ const handleEditingEnd = useCallback20(() => {
15113
15183
  setIsEditing(false);
15114
15184
  }, []);
15115
- const handleSlashCommand = useCallback18(
15185
+ const handleSlashCommand = useCallback20(
15116
15186
  (cursorRect) => {
15117
15187
  setSlashCommand({
15118
15188
  isActive: true,
@@ -15127,10 +15197,10 @@ function Editor({ setEditorLoading }) {
15127
15197
  },
15128
15198
  [setSlashCommand]
15129
15199
  );
15130
- const handleSlashCommandClose = useCallback18(() => {
15200
+ const handleSlashCommandClose = useCallback20(() => {
15131
15201
  clearSlashCommand();
15132
15202
  }, [clearSlashCommand]);
15133
- const handleTextEditStart = useCallback18(
15203
+ const handleTextEditStart = useCallback20(
15134
15204
  (idx, initialWidth, initialHeight, clickX, clickY, content, styles) => {
15135
15205
  const getReferenceRect2 = () => {
15136
15206
  if (!shadowRootRef.current) return null;
@@ -15145,11 +15215,11 @@ function Editor({ setEditorLoading }) {
15145
15215
  },
15146
15216
  [startTextEditing]
15147
15217
  );
15148
- const findParentSectionIdx = useCallback18((idx) => {
15218
+ const findParentSectionIdx = useCallback20((idx) => {
15149
15219
  const match = /^(content\.children\.\[\d+\])/.exec(idx);
15150
15220
  return match ? match[1] : null;
15151
15221
  }, []);
15152
- const handleDragOver = useCallback18(
15222
+ const handleDragOver = useCallback20(
15153
15223
  (_e, dragInfo) => {
15154
15224
  const currentDataTransfer = useEditorStore.getState().dataTransfer;
15155
15225
  if (!currentDataTransfer) return;
@@ -15608,7 +15678,7 @@ function Editor({ setEditorLoading }) {
15608
15678
  [findParentSectionIdx]
15609
15679
  // Only dependency is the helper function
15610
15680
  );
15611
- const handleDrop = useCallback18(
15681
+ const handleDrop = useCallback20(
15612
15682
  (_e, _dragInfo) => {
15613
15683
  const currentDataTransfer = useEditorStore.getState().dataTransfer;
15614
15684
  if (!currentDataTransfer) return;
@@ -15792,7 +15862,7 @@ function Editor({ setEditorLoading }) {
15792
15862
  },
15793
15863
  [addElement, addElementInNewSection, moveElement, moveElementToNewSection, splitTextAndInsertElement, splitSectionAndInsertElement, setIsDragging, setIsDragButtonHovered, setDataTransfer, setHoverIdx]
15794
15864
  );
15795
- const handleDragLeave = useCallback18(() => {
15865
+ const handleDragLeave = useCallback20(() => {
15796
15866
  setDropIndicator(null);
15797
15867
  setDropTargetIdx(null);
15798
15868
  dragParentIdxRef.current = null;
@@ -15813,13 +15883,13 @@ function Editor({ setEditorLoading }) {
15813
15883
  sectionElementCacheRef.current.clear();
15814
15884
  sectionRectCacheRef.current.clear();
15815
15885
  }, []);
15816
- const handleShadowRootRef = useCallback18((shadowRoot) => {
15886
+ const handleShadowRootRef = useCallback20((shadowRoot) => {
15817
15887
  shadowRootRef.current = shadowRoot;
15818
15888
  }, []);
15819
- const handleSelectionRectChange = useCallback18((rect) => {
15889
+ const handleSelectionRectChange = useCallback20((rect) => {
15820
15890
  setHasSelectedElement(rect !== null);
15821
15891
  }, []);
15822
- const getReferenceRect = useCallback18(() => {
15892
+ const getReferenceRect = useCallback20(() => {
15823
15893
  if (!shadowRootRef.current || !focusIdx) return null;
15824
15894
  const selectedEl = shadowRootRef.current.querySelector(
15825
15895
  `.node-idx-${CSS.escape(focusIdx)}`