@kgalexander/mcreate 0.0.11 → 0.0.13

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 useMemo16, useState as useState15, useEffect as useEffect19, useCallback as useCallback16, useRef as useRef11 } from "react";
2
+ import { useMemo as useMemo16, useState as useState16, useEffect as useEffect20, useCallback as useCallback16, useRef as useRef11 } from "react";
3
3
  import { cloneDeep as cloneDeep2, isEqual, debounce } from "lodash";
4
4
 
5
5
  // src/core/utils/idx.ts
@@ -216,7 +216,7 @@ function formatOpenHouseTime(time24) {
216
216
  function propertyCardMockMjml(block, context) {
217
217
  const a = block.attributes;
218
218
  const trackingClasses = context.mode === "editing" ? getTrackingClasses(context.idx, "property-card") : "";
219
- const href = a["href"] || "#";
219
+ const href = a["href"] || "";
220
220
  const price = formatPrice(a["price"] || "$0");
221
221
  const address = a["address"] || "123 Main Street";
222
222
  const city = a["city"] || "City, ST 00000";
@@ -384,7 +384,7 @@ function propertyCardSingleTwoMockMjml(block, context) {
384
384
  const a = block.attributes;
385
385
  const trackingClasses = context.mode === "editing" ? getTrackingClasses(context.idx, "property-card-single-two") : "";
386
386
  const uniqueId = Math.random().toString(36).slice(2, 8);
387
- const href = a["href"] || a["link"] || "#";
387
+ const href = a["href"] || "";
388
388
  const price = formatPrice(a["price"] || "$0");
389
389
  const address = a["address"] || "123 Main Street";
390
390
  const city = a["city"] || "City, ST 00000";
@@ -577,7 +577,7 @@ function propertyCardSingleTwoMockMjml(block, context) {
577
577
  // src/render/Mockup/mock-property-triple-better.ts
578
578
  function renderCard(child, childIdx, context, uniqueId, borderRadius, imageHeight, border, fontFamily, textColor, backgroundColor, innerBorderRadius) {
579
579
  const attrs = child.attributes;
580
- const href = attrs["href"] || "#";
580
+ const href = attrs["href"] || "";
581
581
  const price = formatPrice(attrs["price"] || "$0");
582
582
  const beds = formatNumber(attrs["beds"] || "--");
583
583
  const baths = formatNumber(attrs["baths"] || "--");
@@ -880,7 +880,7 @@ function propertyCardTripleToMjml(block, context) {
880
880
  const cardNum = index + 1;
881
881
  const childAttrs = child.attributes || {};
882
882
  productionAttrs[`image-src-${cardNum}`] = childAttrs["image-src"] || "";
883
- productionAttrs[`href-${cardNum}`] = childAttrs["href"] || "#";
883
+ productionAttrs[`href-${cardNum}`] = childAttrs["href"] || "";
884
884
  productionAttrs[`price-${cardNum}`] = childAttrs["price"] || "$0";
885
885
  productionAttrs[`beds-${cardNum}`] = childAttrs["beds"] || "--";
886
886
  productionAttrs[`baths-${cardNum}`] = childAttrs["baths"] || "--";
@@ -1008,7 +1008,7 @@ function rootChildrenToMjml(children, parentContext) {
1008
1008
  function json2mjml(template, mode = "production", options = {}) {
1009
1009
  const showCompanyFooter = template.content[0]?.data?.value?.showCompanyFooter ?? true;
1010
1010
  const footerMutation = needsCompanyFooterMutation(template);
1011
- const needsProductionFilter = mode === "production" && options?.isPaid && !showCompanyFooter;
1011
+ const needsProductionFilter = mode === "production" && (options?.isPaidLevel ?? 0) >= 1 && !showCompanyFooter;
1012
1012
  if (footerMutation || needsProductionFilter) {
1013
1013
  template = typeof structuredClone !== "undefined" ? structuredClone(template) : JSON.parse(JSON.stringify(template));
1014
1014
  }
@@ -1061,7 +1061,6 @@ function json2mjml(template, mode = "production", options = {}) {
1061
1061
  p { margin: 0px 0px 0px 0px !important; }
1062
1062
  a { color: ${linkColor}; text-decoration: none; }
1063
1063
  a span { text-decoration: underline; }
1064
- p span { text-decoration: underline; }
1065
1064
 
1066
1065
  .property-details-separator {font-family:Arial,sans-serif;color:#C3C3C3;padding:0 4px 0 2px;}
1067
1066
 
@@ -1115,7 +1114,6 @@ import lodashGet from "lodash/get";
1115
1114
  import lodashSet from "lodash/set";
1116
1115
  import cloneDeep from "lodash/cloneDeep";
1117
1116
  import { castDraft } from "immer";
1118
- import { toast } from "sonner";
1119
1117
 
1120
1118
  // src/core/editor/utils/generate-id.ts
1121
1119
  import { nanoid } from "nanoid";
@@ -1279,6 +1277,7 @@ function createSocialElement(payload) {
1279
1277
  "inner-padding": "4px 4px",
1280
1278
  "icon-padding": "0px 6px",
1281
1279
  "text-padding": "4px 4px",
1280
+ "line-height": "1.4",
1282
1281
  ...payload?.attributes
1283
1282
  },
1284
1283
  children: payload?.children || [
@@ -1313,6 +1312,7 @@ function createSocialItemElement(payload) {
1313
1312
  target: "_blank",
1314
1313
  src: payload?.attributes?.src || "https://cdn-images.mailchimp.com/icons/social-block-v3/block-icons-v3/facebook-icon-color-40.png",
1315
1314
  alt: payload?.attributes?.alt || "Facebook",
1315
+ align: "center",
1316
1316
  ...payload?.attributes
1317
1317
  }
1318
1318
  };
@@ -1406,7 +1406,7 @@ function createPropertyCardElement(payload) {
1406
1406
  "beds": "--",
1407
1407
  "baths": "--",
1408
1408
  "sqft": "--",
1409
- "href": "#",
1409
+ "href": "",
1410
1410
  "status": "Empty",
1411
1411
  "is-status": "show",
1412
1412
  "status-color": "#B8B8B8",
@@ -1435,7 +1435,7 @@ function createPropertyCardSingleTwoElement(payload) {
1435
1435
  "beds": "--",
1436
1436
  "baths": "--",
1437
1437
  "sqft": "--",
1438
- "href": "#",
1438
+ "href": "",
1439
1439
  "status": "Empty",
1440
1440
  "is-status": "show",
1441
1441
  "status-color": "#B8B8B8",
@@ -1522,7 +1522,7 @@ function createPropertyCardTripleItemElement(payload) {
1522
1522
  data: { value: {} },
1523
1523
  attributes: {
1524
1524
  "image-src": payload?.attributes?.["image-src"] || "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg",
1525
- "href": payload?.attributes?.["href"] || "#",
1525
+ "href": payload?.attributes?.["href"] || "",
1526
1526
  "price": payload?.attributes?.["price"] || "$0",
1527
1527
  "beds": payload?.attributes?.["beds"] || "--",
1528
1528
  "baths": payload?.attributes?.["baths"] || "--",
@@ -1542,6 +1542,7 @@ function createPropertyCardTripleElement(payload) {
1542
1542
  "gap": "24px",
1543
1543
  "border-radius": "0px",
1544
1544
  "border": "1px solid #d1d1d5",
1545
+ "background-color": "#ffffff",
1545
1546
  "image-height": "102px",
1546
1547
  ...payload?.attributes
1547
1548
  },
@@ -1870,6 +1871,7 @@ var defaultTemplate = {
1870
1871
  id: page.id || generateId()
1871
1872
  }))
1872
1873
  };
1874
+ var MAX_PAID_LEVEL = 3;
1873
1875
  var useEditorStore = create()(
1874
1876
  devtools(
1875
1877
  immer((set) => ({
@@ -1877,6 +1879,7 @@ var useEditorStore = create()(
1877
1879
  template: defaultTemplate,
1878
1880
  templateId: null,
1879
1881
  onSave: null,
1882
+ onToast: null,
1880
1883
  previewMode: false,
1881
1884
  focusIdx: null,
1882
1885
  hoverIdx: null,
@@ -1898,12 +1901,16 @@ var useEditorStore = create()(
1898
1901
  // Auto-save tracking
1899
1902
  lastSavedSnapshot: null,
1900
1903
  isSaving: false,
1904
+ // Subscription level (0 = free, 1-3 = paid tiers)
1905
+ isPaidLevel: 0,
1901
1906
  // Initialize store with external template (for npm package usage)
1902
- initializeWithTemplate: (templateId, template, onSave) => {
1907
+ initializeWithTemplate: (templateId, template, onSave, onToast, isPaidLevel) => {
1903
1908
  set((state) => {
1904
1909
  state.templateId = templateId;
1905
1910
  state.template = template;
1906
1911
  state.onSave = onSave ?? null;
1912
+ state.onToast = onToast ?? null;
1913
+ state.isPaidLevel = isPaidLevel ?? 0;
1907
1914
  state.templateSize = calculateTemplateSize(template);
1908
1915
  state.isAtSizeLimit = false;
1909
1916
  state.history = [cloneDeep(template)];
@@ -2049,7 +2056,7 @@ var useEditorStore = create()(
2049
2056
  }
2050
2057
  const elementSize = new Blob([JSON.stringify(newElement)]).size;
2051
2058
  if (state.templateSize + elementSize > MAX_TEMPLATE_SIZE) {
2052
- toast.error("Template size limit reached - element would exceed the limit");
2059
+ state.onToast?.({ type: "error", message: "Template size limit reached - element would exceed the limit" });
2053
2060
  return;
2054
2061
  }
2055
2062
  const children = parent.children;
@@ -2088,7 +2095,7 @@ var useEditorStore = create()(
2088
2095
  }
2089
2096
  const sectionSize = new Blob([JSON.stringify(newSection)]).size;
2090
2097
  if (state.templateSize + sectionSize > MAX_TEMPLATE_SIZE) {
2091
- toast.error("Template size limit reached");
2098
+ state.onToast?.({ type: "error", message: "Template size limit reached" });
2092
2099
  return;
2093
2100
  }
2094
2101
  const children = page.children;
@@ -2206,7 +2213,7 @@ var useEditorStore = create()(
2206
2213
  }
2207
2214
  ).length;
2208
2215
  if (regularSectionCount <= 1) {
2209
- toast.error("Cannot delete the last section");
2216
+ state.onToast?.({ type: "error", message: "Cannot delete the last section" });
2210
2217
  return;
2211
2218
  }
2212
2219
  }
@@ -2339,7 +2346,7 @@ var useEditorStore = create()(
2339
2346
  const clonedElement = cloneDeep(sourceElement);
2340
2347
  const elementSize = new Blob([JSON.stringify(clonedElement)]).size;
2341
2348
  if (state.templateSize + elementSize > MAX_TEMPLATE_SIZE) {
2342
- toast.error("Template size limit reached - duplicate would exceed limit");
2349
+ state.onToast?.({ type: "error", message: "Template size limit reached - duplicate would exceed limit" });
2343
2350
  return;
2344
2351
  }
2345
2352
  const parent = getElementAtIdx(state.template, parentIdx);
@@ -2443,13 +2450,14 @@ var useEditorStore = create()(
2443
2450
  if (tempDroppedElement) {
2444
2451
  const elementSize = new Blob([JSON.stringify(tempDroppedElement)]).size;
2445
2452
  if (state.templateSize + elementSize > MAX_TEMPLATE_SIZE) {
2446
- toast.error("Template size limit reached - this element would exceed the limit");
2453
+ state.onToast?.({ type: "error", message: "Template size limit reached - this element would exceed the limit" });
2447
2454
  return;
2448
2455
  }
2449
2456
  }
2450
2457
  }
2451
2458
  textElement.data.value.content = beforeContent;
2452
2459
  let droppedElement = null;
2460
+ let deletedSectionIndex = null;
2453
2461
  if (sourceIdx) {
2454
2462
  const sourceParentIdx = getParentIdx(sourceIdx);
2455
2463
  if (sourceParentIdx) {
@@ -2469,6 +2477,7 @@ var useEditorStore = create()(
2469
2477
  const sectionIndex = getIndexByIdx(sourceSectionIdx);
2470
2478
  const sourcePageChildren = sourcePage.children;
2471
2479
  sourcePageChildren.splice(sectionIndex, 1);
2480
+ deletedSectionIndex = sectionIndex;
2472
2481
  }
2473
2482
  } else if (action === "add-text") {
2474
2483
  const defaultText = createElementByType("text", { data: { value: { content: "" } } });
@@ -2494,7 +2503,20 @@ var useEditorStore = create()(
2494
2503
  console.error("Failed to create new text element");
2495
2504
  return;
2496
2505
  }
2497
- const parentIdx = getParentIdx(textElementIdx);
2506
+ let adjustedTextElementIdx = textElementIdx;
2507
+ if (deletedSectionIndex !== null) {
2508
+ const textSectionMatch = SECTION_INDEX_REGEX.exec(textElementIdx);
2509
+ if (textSectionMatch) {
2510
+ const textSectionIndex = Number(textSectionMatch[1]);
2511
+ if (deletedSectionIndex < textSectionIndex) {
2512
+ adjustedTextElementIdx = textElementIdx.replace(
2513
+ SECTION_INDEX_REGEX,
2514
+ `content.children.[${textSectionIndex - 1}]`
2515
+ );
2516
+ }
2517
+ }
2518
+ }
2519
+ const parentIdx = getParentIdx(adjustedTextElementIdx);
2498
2520
  if (!parentIdx) {
2499
2521
  console.error("Parent not found for text element");
2500
2522
  return;
@@ -2504,7 +2526,7 @@ var useEditorStore = create()(
2504
2526
  console.error("Parent is not a valid container");
2505
2527
  return;
2506
2528
  }
2507
- const currentIndex = getIndexByIdx(textElementIdx);
2529
+ const currentIndex = getIndexByIdx(adjustedTextElementIdx);
2508
2530
  const parentChildren = parent.children;
2509
2531
  let adjustedIndex = currentIndex;
2510
2532
  if (sourceIdx) {
@@ -2591,7 +2613,7 @@ var useEditorStore = create()(
2591
2613
  const elementSize = new Blob([JSON.stringify(sectionColumnElement)]).size;
2592
2614
  const approxNewSectionSize = 200;
2593
2615
  if (state.templateSize + elementSize + approxNewSectionSize > MAX_TEMPLATE_SIZE) {
2594
- toast.error("Template size limit reached");
2616
+ state.onToast?.({ type: "error", message: "Template size limit reached" });
2595
2617
  return;
2596
2618
  }
2597
2619
  }
@@ -2614,7 +2636,7 @@ var useEditorStore = create()(
2614
2636
  const pageChildren = page.children;
2615
2637
  let adjustedSectionIndex = sectionIndex;
2616
2638
  if (sourceIdx) {
2617
- const srcSectionMatch = sourceIdx.match(SECTION_INDEX_REGEX);
2639
+ const srcSectionMatch = SECTION_INDEX_REGEX.exec(sourceIdx);
2618
2640
  if (srcSectionMatch) {
2619
2641
  const srcSectionIndex = parseInt(srcSectionMatch[1], 10);
2620
2642
  if (srcSectionIndex < sectionIndex) {
@@ -2690,7 +2712,7 @@ var useEditorStore = create()(
2690
2712
  if (!sourceIdx) {
2691
2713
  const columnSize = new Blob([JSON.stringify(newColumn)]).size;
2692
2714
  if (state.templateSize + columnSize > MAX_TEMPLATE_SIZE) {
2693
- toast.error("Template size limit reached");
2715
+ state.onToast?.({ type: "error", message: "Template size limit reached" });
2694
2716
  return;
2695
2717
  }
2696
2718
  }
@@ -2783,7 +2805,7 @@ var useEditorStore = create()(
2783
2805
  if (!sourceIdx) {
2784
2806
  const columnSize = new Blob([JSON.stringify(newColumn)]).size;
2785
2807
  if (state.templateSize + columnSize > MAX_TEMPLATE_SIZE) {
2786
- toast.error("Template size limit reached");
2808
+ state.onToast?.({ type: "error", message: "Template size limit reached" });
2787
2809
  return;
2788
2810
  }
2789
2811
  }
@@ -3055,7 +3077,7 @@ function setValueAtPath(template, path, value) {
3055
3077
  }
3056
3078
 
3057
3079
  // src/core/editor/components/ShadowDomRenderer.tsx
3058
- import { useEffect, useRef } from "react";
3080
+ import { useEffect, useRef, memo } from "react";
3059
3081
 
3060
3082
  // src/core/editor/constant/configuration.ts
3061
3083
  import { AlignCenterIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, Heading1Icon, Heading2Icon, Heading3Icon, LinkIcon, ListIcon, ListOrderedIcon, MailIcon, PhoneIcon, Pilcrow } from "lucide-react";
@@ -3145,7 +3167,6 @@ var NOT_DRAGGABLE_ELEMENTS = ["page", "social-item", "text", "property-card", "p
3145
3167
  var IMAGE_SELECTION_VALID_TYPES = ["section", "section-column", "image", "section-property-km", "section-property-single-two", "section-property-triple", "property-card", "property-card-single-two", "property-card-triple", "property-card-triple-item"];
3146
3168
 
3147
3169
  // src/core/editor/components/ShadowDomRenderer.tsx
3148
- import { toast as toast2 } from "sonner";
3149
3170
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3150
3171
  var lastSizeLimitToastTime = 0;
3151
3172
  var cssCache = /* @__PURE__ */ new Map();
@@ -3495,7 +3516,7 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3495
3516
  cssCache.set(cacheKey, css);
3496
3517
  return css;
3497
3518
  }
3498
- function ShadowDomRenderer({
3519
+ var ShadowDomRenderer = memo(function ShadowDomRenderer2({
3499
3520
  html,
3500
3521
  focusIdx,
3501
3522
  hoverIdx,
@@ -3523,6 +3544,8 @@ function ShadowDomRenderer({
3523
3544
  const shadowRootRef = useRef(null);
3524
3545
  const rafRef = useRef(null);
3525
3546
  const lastBlockNodeRef = useRef(null);
3547
+ const hoverRafRef = useRef(null);
3548
+ const lastHoverIdxRef = useRef(null);
3526
3549
  const callbackRefs = useRef({
3527
3550
  onElementClick,
3528
3551
  onElementHover,
@@ -3753,14 +3776,19 @@ function ShadowDomRenderer({
3753
3776
  const handleMouseOver = (e) => {
3754
3777
  const target = e.target;
3755
3778
  const blockNode = target.closest(`.${EMAIL_BLOCK_CLASS_NAME}`);
3756
- if (blockNode && callbackRefs.current.onElementHover) {
3757
- const idx = getIdxFromElement(blockNode);
3758
- callbackRefs.current.onElementHover(idx || null);
3759
- }
3779
+ const newIdx = blockNode ? getIdxFromElement(blockNode) : null;
3780
+ if (newIdx === lastHoverIdxRef.current) return;
3781
+ if (hoverRafRef.current) return;
3782
+ hoverRafRef.current = requestAnimationFrame(() => {
3783
+ hoverRafRef.current = null;
3784
+ lastHoverIdxRef.current = newIdx;
3785
+ callbackRefs.current.onElementHover?.(newIdx);
3786
+ });
3760
3787
  };
3761
3788
  const handleMouseOut = (e) => {
3762
3789
  const relatedTarget = e.relatedTarget;
3763
3790
  if (!relatedTarget || !shadowRoot.contains(relatedTarget)) {
3791
+ lastHoverIdxRef.current = null;
3764
3792
  callbackRefs.current.onElementHover?.(null);
3765
3793
  }
3766
3794
  };
@@ -3907,7 +3935,7 @@ function ShadowDomRenderer({
3907
3935
  const now = Date.now();
3908
3936
  if (now - lastSizeLimitToastTime > 2e3) {
3909
3937
  lastSizeLimitToastTime = now;
3910
- toast2.error("Template size limit reached");
3938
+ useEditorStore.getState().onToast?.({ type: "error", message: "Template size limit reached" });
3911
3939
  }
3912
3940
  return;
3913
3941
  }
@@ -3969,7 +3997,7 @@ function ShadowDomRenderer({
3969
3997
  const now = Date.now();
3970
3998
  if (now - lastSizeLimitToastTime > 2e3) {
3971
3999
  lastSizeLimitToastTime = now;
3972
- toast2.error("Template size limit reached");
4000
+ useEditorStore.getState().onToast?.({ type: "error", message: "Template size limit reached" });
3973
4001
  }
3974
4002
  }
3975
4003
  };
@@ -3991,6 +4019,11 @@ function ShadowDomRenderer({
3991
4019
  rafRef.current = null;
3992
4020
  }
3993
4021
  lastBlockNodeRef.current = null;
4022
+ if (hoverRafRef.current) {
4023
+ cancelAnimationFrame(hoverRafRef.current);
4024
+ hoverRafRef.current = null;
4025
+ }
4026
+ lastHoverIdxRef.current = null;
3994
4027
  shadowRoot.removeEventListener("mousedown", handleMouseDown);
3995
4028
  shadowRoot.removeEventListener("click", handleLinkClick, true);
3996
4029
  shadowRoot.removeEventListener("mouseover", handleMouseOver);
@@ -4067,7 +4100,7 @@ function ShadowDomRenderer({
4067
4100
  }
4068
4101
  )
4069
4102
  ] });
4070
- }
4103
+ });
4071
4104
  function getIdxFromElement(element) {
4072
4105
  const classList = element.classList;
4073
4106
  for (let i = 0; i < classList.length; i++) {
@@ -10982,9 +11015,6 @@ function checkElementPosition(template, elementIdx) {
10982
11015
  return { isFirstInFirstSection, isFirstInSectionColumn };
10983
11016
  }
10984
11017
 
10985
- // src/core/editor/components/tiptap-overlay.tsx
10986
- import { toast as toast3 } from "sonner";
10987
-
10988
11018
  // src/components/ui/tooltip.tsx
10989
11019
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
10990
11020
  import { jsx as jsx14, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -11650,7 +11680,7 @@ var TiptapOverlay = () => {
11650
11680
  if (!textEditing) return null;
11651
11681
  return /* @__PURE__ */ jsx21(TiptapOverlayContent, { ...textEditing }, textEditing.idx);
11652
11682
  };
11653
- var TiptapOverlayContent = ({ idx, getReferenceRect, initialWidth, initialHeight, clickX, clickY, content, styles, cursorPosition }) => {
11683
+ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWidth, initialHeight, clickX, clickY, content, styles, cursorPosition }) => {
11654
11684
  const containerRef = useRef4(null);
11655
11685
  const setTiptapEditor = useEditorStore((s) => s.setTiptapEditor);
11656
11686
  const linkColor = useEditorStore((s) => s.template?.content?.[0]?.data?.value?.linkColor) || "#0000ff";
@@ -11665,6 +11695,24 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, initialWidth, initialHeight
11665
11695
  }
11666
11696
  };
11667
11697
  }, []);
11698
+ useEffect6(() => {
11699
+ const container = containerRef.current;
11700
+ if (!container) return;
11701
+ const observer = new ResizeObserver(() => {
11702
+ const shadowEl = getShadowElement();
11703
+ if (shadowEl) {
11704
+ shadowEl.style.height = `${container.offsetHeight}px`;
11705
+ }
11706
+ });
11707
+ observer.observe(container);
11708
+ return () => {
11709
+ observer.disconnect();
11710
+ const shadowEl = getShadowElement();
11711
+ if (shadowEl) {
11712
+ shadowEl.style.height = "";
11713
+ }
11714
+ };
11715
+ }, [getShadowElement]);
11668
11716
  const cleanedContent = useMemo3(() => {
11669
11717
  return content.replace(NBSP_P_CONTENT_REGEX, "<p$1></p>").replace(IS_EMPTY_P_CLASS_REGEX, "").replace(IS_EMPTY_HEADING_CLASS_REGEX, "");
11670
11718
  }, [content]);
@@ -11725,7 +11773,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, initialWidth, initialHeight
11725
11773
  const now = Date.now();
11726
11774
  if (now - lastSizeLimitToastRef.current > 2e3) {
11727
11775
  lastSizeLimitToastRef.current = now;
11728
- toast3.error("Template size limit reached");
11776
+ useEditorStore.getState().onToast?.({ type: "error", message: "Template size limit reached" });
11729
11777
  }
11730
11778
  return true;
11731
11779
  }
@@ -11782,7 +11830,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, initialWidth, initialHeight
11782
11830
  const now = Date.now();
11783
11831
  if (now - lastSizeLimitToastRef.current > 2e3) {
11784
11832
  lastSizeLimitToastRef.current = now;
11785
- toast3.error("Template size limit reached - paste would exceed the limit");
11833
+ useEditorStore.getState().onToast?.({ type: "error", message: "Template size limit reached - paste would exceed the limit" });
11786
11834
  }
11787
11835
  return true;
11788
11836
  }
@@ -12043,7 +12091,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, initialWidth, initialHeight
12043
12091
  };
12044
12092
 
12045
12093
  // src/core/editor/components/element-float.tsx
12046
- import { useEffect as useEffect11, useMemo as useMemo10 } from "react";
12094
+ import { useEffect as useEffect12, useMemo as useMemo10 } from "react";
12047
12095
  import { useFloating as useFloating4, offset as offset4, shift as shift3, flip as flip2, autoUpdate as autoUpdate3 } from "@floating-ui/react";
12048
12096
 
12049
12097
  // src/core/editor/components/float-ui/actions/delete-button.tsx
@@ -12260,7 +12308,7 @@ var useHref = () => {
12260
12308
  }
12261
12309
  }
12262
12310
  }, [href]);
12263
- const hasHref = Boolean(href && href !== "#" && href.trim() !== "");
12311
+ const hasHref = Boolean(href && href !== "" && href.trim() !== "");
12264
12312
  return {
12265
12313
  href,
12266
12314
  setHref,
@@ -13011,34 +13059,253 @@ var ImageFloat = () => {
13011
13059
  ] });
13012
13060
  };
13013
13061
 
13014
- // src/core/editor/components/element-gear/property/float.tsx
13062
+ // src/core/editor/components/mlsNumber-menu.tsx
13063
+ import { useState as useState8, useEffect as useEffect11 } from "react";
13064
+ import { HousePlusIcon, TrashIcon as TrashIcon5, XIcon as XIcon2, Loader2Icon } from "lucide-react";
13065
+
13066
+ // src/services/repliers/commands.ts
13067
+ async function getListingByMlsNumber(mlsNumber) {
13068
+ const response = await fetch(`/api/mcommends/repliers/getListingByMlsNumber/${mlsNumber}`, {
13069
+ method: "GET",
13070
+ headers: {
13071
+ "accept": "application/json"
13072
+ }
13073
+ });
13074
+ const data = await response.json();
13075
+ return data;
13076
+ }
13077
+
13078
+ // src/core/editor/components/mlsNumber-menu.tsx
13015
13079
  import { Fragment as Fragment14, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
13080
+ var MlsNumberMenu = () => {
13081
+ const { focusIdx, template, updateElement, onToast } = useEditorStore();
13082
+ const [isOpen, setIsOpen] = useState8(false);
13083
+ const [inputValue, setInputValue] = useState8("");
13084
+ const [propertyData, setPropertyData] = useState8(null);
13085
+ const [isLoading, setIsLoading] = useState8(false);
13086
+ const propertyElement = focusIdx && template ? getValueByIdx(template, focusIdx) : null;
13087
+ const currentMlsNumber = propertyElement?.data?.value?.mlsNumber || "";
13088
+ useEffect11(() => {
13089
+ setInputValue(currentMlsNumber);
13090
+ setPropertyData(null);
13091
+ }, [focusIdx, currentMlsNumber]);
13092
+ const handleInputChange = (e) => {
13093
+ setInputValue(e.target.value);
13094
+ };
13095
+ const handleKeyDown = (e) => {
13096
+ if (e.key === "Enter") {
13097
+ handleDone();
13098
+ }
13099
+ if (e.key === "Escape") {
13100
+ setIsOpen(false);
13101
+ }
13102
+ };
13103
+ const handleClear = () => {
13104
+ setInputValue("");
13105
+ setPropertyData(null);
13106
+ };
13107
+ const handleClearPreview = () => {
13108
+ setPropertyData(null);
13109
+ };
13110
+ const handleApplyToCard = () => {
13111
+ if (!focusIdx || !propertyElement || !propertyData) return;
13112
+ console.log(propertyData);
13113
+ const imageUrl = propertyData.images?.[0] ? `https://cdn.repliers.io/${propertyData.images[0]}` : propertyElement.attributes?.["image-src"];
13114
+ updateElement(focusIdx, {
13115
+ data: {
13116
+ value: {
13117
+ ...propertyElement.data?.value,
13118
+ mlsNumber: propertyData.mlsNumber
13119
+ }
13120
+ },
13121
+ attributes: {
13122
+ ...propertyElement.attributes,
13123
+ "image-src": imageUrl,
13124
+ "price": String(propertyData.listPrice || 0),
13125
+ "address": `${propertyData.address?.streetNumber || ""} ${propertyData.address?.streetName || ""}`.trim(),
13126
+ "city": `${propertyData.address?.city || ""}, ${propertyData.address?.state || ""} ${propertyData.address?.zip || ""}`.trim(),
13127
+ "beds": String(propertyData.details?.numBedrooms || "--"),
13128
+ "baths": String(propertyData.details?.numBathrooms || "--"),
13129
+ "sqft": String(propertyData.details?.sqft || "--"),
13130
+ "status": propertyData.standardStatus || propertyData.status || "Active",
13131
+ "brokerage": propertyData.office?.brokerageName || ""
13132
+ }
13133
+ });
13134
+ setPropertyData(null);
13135
+ setIsOpen(false);
13136
+ };
13137
+ const handleDone = async () => {
13138
+ if (inputValue.trim()) {
13139
+ setIsLoading(true);
13140
+ try {
13141
+ const data = await getListingByMlsNumber(inputValue.trim());
13142
+ if (data.error) {
13143
+ onToast?.({ type: "error", message: data.error });
13144
+ return;
13145
+ }
13146
+ setPropertyData(data);
13147
+ } catch (error) {
13148
+ console.warn("Failed to fetch listing:", error);
13149
+ const message = error instanceof Error ? error.message : "Failed to fetch listing";
13150
+ onToast?.({ type: "error", message });
13151
+ } finally {
13152
+ setIsLoading(false);
13153
+ }
13154
+ }
13155
+ };
13156
+ return /* @__PURE__ */ jsxs22(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
13157
+ /* @__PURE__ */ jsxs22(Tooltip, { children: [
13158
+ /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs22(
13159
+ Button,
13160
+ {
13161
+ variant: "ghost",
13162
+ className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
13163
+ children: [
13164
+ /* @__PURE__ */ jsx37(HousePlusIcon, { className: "size-4" }),
13165
+ /* @__PURE__ */ jsx37("p", { children: "MLS" })
13166
+ ]
13167
+ }
13168
+ ) }) }),
13169
+ /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", children: "Enter MLS Number" })
13170
+ ] }),
13171
+ /* @__PURE__ */ jsxs22(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
13172
+ /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
13173
+ /* @__PURE__ */ jsx37(Label, { children: "Enter MLS Number" }),
13174
+ /* @__PURE__ */ jsx37(
13175
+ Input,
13176
+ {
13177
+ type: "text",
13178
+ placeholder: "e.g., W1234567",
13179
+ className: "w-full rounded-[12px] shadow-none h-[44px]",
13180
+ value: inputValue,
13181
+ onChange: handleInputChange,
13182
+ onKeyDown: handleKeyDown,
13183
+ autoFocus: true
13184
+ }
13185
+ )
13186
+ ] }),
13187
+ /* @__PURE__ */ jsx37(Separator, { className: "my-2" }),
13188
+ /* @__PURE__ */ jsxs22("div", { className: "flex flex-row justify-between items-center", children: [
13189
+ /* @__PURE__ */ jsx37("div", { className: "flex flex-row", children: /* @__PURE__ */ jsxs22(Tooltip, { children: [
13190
+ /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(
13191
+ Button,
13192
+ {
13193
+ variant: "ghost",
13194
+ size: "icon",
13195
+ className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
13196
+ onClick: handleClear,
13197
+ disabled: !inputValue,
13198
+ children: /* @__PURE__ */ jsx37(TrashIcon5, {})
13199
+ }
13200
+ ) }),
13201
+ /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", className: "z-50001", children: "Clear" })
13202
+ ] }) }),
13203
+ /* @__PURE__ */ jsx37("div", { children: /* @__PURE__ */ jsx37(
13204
+ Button,
13205
+ {
13206
+ variant: "default",
13207
+ className: "shadow-none transition-none cursor-pointer rounded-[12px] outline-none",
13208
+ onClick: handleDone,
13209
+ disabled: isLoading || !inputValue.trim(),
13210
+ children: isLoading ? /* @__PURE__ */ jsx37(Loader2Icon, { className: "size-4 animate-spin" }) : "Done"
13211
+ }
13212
+ ) })
13213
+ ] }),
13214
+ propertyData && /* @__PURE__ */ jsxs22(Fragment14, { children: [
13215
+ /* @__PURE__ */ jsx37(Separator, { className: "my-2" }),
13216
+ /* @__PURE__ */ jsxs22("div", { className: "rounded-[12px] border overflow-hidden bg-card", children: [
13217
+ /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
13218
+ /* @__PURE__ */ jsx37(
13219
+ "img",
13220
+ {
13221
+ src: `https://cdn.repliers.io/${propertyData.images?.[0]}`,
13222
+ alt: "Property",
13223
+ className: "w-full h-[120px] object-cover"
13224
+ }
13225
+ ),
13226
+ /* @__PURE__ */ jsx37(
13227
+ Button,
13228
+ {
13229
+ variant: "ghost",
13230
+ size: "icon",
13231
+ className: "absolute top-1 right-1 h-6 w-6 bg-black/50 hover:bg-black/70 rounded-full",
13232
+ onClick: handleClearPreview,
13233
+ children: /* @__PURE__ */ jsx37(XIcon2, { className: "size-3 text-white" })
13234
+ }
13235
+ )
13236
+ ] }),
13237
+ /* @__PURE__ */ jsxs22("div", { className: "p-2 flex flex-col gap-1", children: [
13238
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between", children: [
13239
+ /* @__PURE__ */ jsx37("span", { className: "font-semibold text-sm", children: formatPrice(String(propertyData.listPrice || 0)) }),
13240
+ /* @__PURE__ */ jsx37("span", { className: "text-xs px-2 py-0.5 rounded-full bg-green-100 text-green-700", children: propertyData.standardStatus || propertyData.status })
13241
+ ] }),
13242
+ /* @__PURE__ */ jsxs22("div", { className: "text-sm", children: [
13243
+ propertyData.address?.streetNumber,
13244
+ " ",
13245
+ propertyData.address?.streetName
13246
+ ] }),
13247
+ /* @__PURE__ */ jsxs22("div", { className: "text-xs text-muted-foreground", children: [
13248
+ propertyData.address?.city,
13249
+ ", ",
13250
+ propertyData.address?.state,
13251
+ " ",
13252
+ propertyData.address?.zip
13253
+ ] }),
13254
+ /* @__PURE__ */ jsxs22("div", { className: "text-xs text-muted-foreground", children: [
13255
+ propertyData.details?.numBedrooms,
13256
+ " bd | ",
13257
+ propertyData.details?.numBathrooms,
13258
+ " ba | ",
13259
+ formatNumber(String(propertyData.details?.sqft || "--")),
13260
+ " sf"
13261
+ ] }),
13262
+ propertyData.office?.brokerageName && /* @__PURE__ */ jsx37("div", { className: "text-xs text-muted-foreground truncate", children: propertyData.office.brokerageName }),
13263
+ /* @__PURE__ */ jsx37(
13264
+ Button,
13265
+ {
13266
+ variant: "default",
13267
+ size: "sm",
13268
+ className: "w-full mt-2 rounded-[12px]",
13269
+ onClick: handleApplyToCard,
13270
+ children: "Apply to Card"
13271
+ }
13272
+ )
13273
+ ] })
13274
+ ] })
13275
+ ] })
13276
+ ] })
13277
+ ] });
13278
+ };
13279
+
13280
+ // src/core/editor/components/element-gear/property/float.tsx
13281
+ import { Fragment as Fragment15, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
13016
13282
  function PropertyFloat() {
13017
13283
  const { href, hasHref } = useHref();
13018
- return /* @__PURE__ */ jsxs22(Fragment14, { children: [
13019
- hasHref && /* @__PURE__ */ jsx37(FloatLinkPreview, { href }),
13020
- /* @__PURE__ */ jsx37(HrefMenu, {})
13284
+ return /* @__PURE__ */ jsxs23(Fragment15, { children: [
13285
+ hasHref && /* @__PURE__ */ jsx38(FloatLinkPreview, { href }),
13286
+ /* @__PURE__ */ jsx38(HrefMenu, {}),
13287
+ /* @__PURE__ */ jsx38(MlsNumberMenu, {})
13021
13288
  ] });
13022
13289
  }
13023
13290
 
13024
13291
  // src/core/editor/components/element-gear/property/triple/float.tsx
13025
- import { Fragment as Fragment15, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
13292
+ import { Fragment as Fragment16, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
13026
13293
  var PropertyTripleItemFloat = () => {
13027
13294
  const { href, hasHref } = useHref();
13028
- return /* @__PURE__ */ jsxs23(Fragment15, { children: [
13029
- hasHref && /* @__PURE__ */ jsx38(FloatLinkPreview, { href }),
13030
- /* @__PURE__ */ jsx38(HrefMenu, {})
13295
+ return /* @__PURE__ */ jsxs24(Fragment16, { children: [
13296
+ hasHref && /* @__PURE__ */ jsx39(FloatLinkPreview, { href }),
13297
+ /* @__PURE__ */ jsx39(HrefMenu, {})
13031
13298
  ] });
13032
13299
  };
13033
13300
 
13034
13301
  // src/core/editor/components/float-ui/container.tsx
13035
- import { jsx as jsx39 } from "react/jsx-runtime";
13302
+ import { jsx as jsx40 } from "react/jsx-runtime";
13036
13303
  var FloatUIContainer = ({ ref, style, className, children }) => {
13037
- return /* @__PURE__ */ jsx39("div", { ref, style, className, children });
13304
+ return /* @__PURE__ */ jsx40("div", { ref, style, className, children });
13038
13305
  };
13039
13306
 
13040
13307
  // src/core/editor/components/element-float.tsx
13041
- import { jsx as jsx40 } from "react/jsx-runtime";
13308
+ import { jsx as jsx41 } from "react/jsx-runtime";
13042
13309
  var FLOAT_COMPONENTS = {
13043
13310
  "button": ButtonFloat,
13044
13311
  "section": SectionFloat,
@@ -13062,7 +13329,7 @@ var ElementFloat = ({ getReferenceRect, focusIdx, elementType }) => {
13062
13329
  if (!focusIdx || isDragging || textEditing) return null;
13063
13330
  const FloatComponent = FLOAT_COMPONENTS[elementType];
13064
13331
  if (!FloatComponent) return null;
13065
- return /* @__PURE__ */ jsx40(
13332
+ return /* @__PURE__ */ jsx41(
13066
13333
  ElementFloatContent,
13067
13334
  {
13068
13335
  getReferenceRect,
@@ -13091,7 +13358,7 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13091
13358
  // Keep within viewport
13092
13359
  ]
13093
13360
  });
13094
- useEffect11(() => {
13361
+ useEffect12(() => {
13095
13362
  const rect = getReferenceRect();
13096
13363
  if (!rect || !refs.floating.current) return;
13097
13364
  refs.setPositionReference(virtualReference);
@@ -13106,16 +13373,16 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13106
13373
  );
13107
13374
  return cleanup;
13108
13375
  }, [getReferenceRect, refs, update, virtualReference]);
13109
- return /* @__PURE__ */ jsx40(FloatUIContainer, { ref: refs.setFloating, style: floatingStyles, className: "bg-white flex items-center justify-center border border-1 h-[36px] w-fit shadow-md rounded-full z-50", children: /* @__PURE__ */ jsx40(FloatComponent, {}) });
13376
+ return /* @__PURE__ */ jsx41(FloatUIContainer, { ref: refs.setFloating, style: floatingStyles, className: "bg-white flex items-center justify-center border border-1 h-[36px] w-fit shadow-md rounded-full z-50", children: /* @__PURE__ */ jsx41(FloatComponent, {}) });
13110
13377
  };
13111
13378
 
13112
13379
  // src/core/editor/components/scaling/divider-scale.tsx
13113
- import { useMemo as useMemo11, useEffect as useEffect12, useState as useState8, useRef as useRef5, useCallback as useCallback10 } from "react";
13380
+ import { useMemo as useMemo11, useEffect as useEffect13, useState as useState9, useRef as useRef5, useCallback as useCallback10 } from "react";
13114
13381
  import { useFloating as useFloating5, offset as offset5, autoUpdate as autoUpdate4 } from "@floating-ui/react";
13115
- import { jsx as jsx41, jsxs as jsxs24 } from "react/jsx-runtime";
13382
+ import { jsx as jsx42, jsxs as jsxs25 } from "react/jsx-runtime";
13116
13383
  var DividerScale = ({ getReferenceRect }) => {
13117
- const [dimensions, setDimensions] = useState8({ width: 0, height: 0 });
13118
- const [activeSide, setActiveSide] = useState8(null);
13384
+ const [dimensions, setDimensions] = useState9({ width: 0, height: 0 });
13385
+ const [activeSide, setActiveSide] = useState9(null);
13119
13386
  const { focusIdx, template, setIsScaling } = useEditorStore();
13120
13387
  const { currentWidth, currentAlign } = useMemo11(() => {
13121
13388
  if (!focusIdx || !template) return { currentWidth: 100, currentAlign: "center" };
@@ -13177,7 +13444,7 @@ var DividerScale = ({ getReferenceRect }) => {
13177
13444
  document.removeEventListener("pointermove", handlePointerMove);
13178
13445
  document.removeEventListener("pointerup", handlePointerUp);
13179
13446
  }, [handlePointerMove, setIsScaling]);
13180
- useEffect12(() => {
13447
+ useEffect13(() => {
13181
13448
  return () => {
13182
13449
  document.removeEventListener("pointermove", handlePointerMove);
13183
13450
  document.removeEventListener("pointerup", handlePointerUp);
@@ -13198,7 +13465,7 @@ var DividerScale = ({ getReferenceRect }) => {
13198
13465
  offset5(({ rects }) => -rects.reference.height)
13199
13466
  ]
13200
13467
  });
13201
- useEffect12(() => {
13468
+ useEffect13(() => {
13202
13469
  const rect = getReferenceRect();
13203
13470
  if (!rect || !refs.floating.current) return;
13204
13471
  refs.setPositionReference(virtualReference);
@@ -13225,7 +13492,7 @@ var DividerScale = ({ getReferenceRect }) => {
13225
13492
  }, [getReferenceRect, refs, update, virtualReference]);
13226
13493
  const showLeftHandle = currentAlign !== "left";
13227
13494
  const showRightHandle = currentAlign !== "right";
13228
- return /* @__PURE__ */ jsxs24(
13495
+ return /* @__PURE__ */ jsxs25(
13229
13496
  "div",
13230
13497
  {
13231
13498
  ref: refs.setFloating,
@@ -13237,14 +13504,14 @@ var DividerScale = ({ getReferenceRect }) => {
13237
13504
  },
13238
13505
  className: "relative flex flex-row items-center justify-between",
13239
13506
  children: [
13240
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx41(
13507
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx42(
13241
13508
  "div",
13242
13509
  {
13243
13510
  onPointerDown: (e) => handlePointerDown(e, "left"),
13244
13511
  className: `w-[18px] h-[18px] cursor-ew-resize bg-background shadow-md border rounded-full absolute -left-[9px] top-1/2 -translate-y-1/2 touch-none select-none ${activeSide === "left" ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300"}`
13245
13512
  }
13246
13513
  ),
13247
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx41(
13514
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx42(
13248
13515
  "div",
13249
13516
  {
13250
13517
  onPointerDown: (e) => handlePointerDown(e, "right"),
@@ -13257,12 +13524,12 @@ var DividerScale = ({ getReferenceRect }) => {
13257
13524
  };
13258
13525
 
13259
13526
  // src/core/editor/components/scaling/button-scale.tsx
13260
- import { useMemo as useMemo12, useEffect as useEffect13, useState as useState9, useRef as useRef6, useCallback as useCallback11 } from "react";
13527
+ import { useMemo as useMemo12, useEffect as useEffect14, useState as useState10, useRef as useRef6, useCallback as useCallback11 } from "react";
13261
13528
  import { useFloating as useFloating6, offset as offset6, autoUpdate as autoUpdate5 } from "@floating-ui/react";
13262
- import { jsx as jsx42, jsxs as jsxs25 } from "react/jsx-runtime";
13529
+ import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
13263
13530
  var ButtonScale = ({ getReferenceRect }) => {
13264
- const [dimensions, setDimensions] = useState9({ width: 0, height: 0 });
13265
- const [activeSide, setActiveSide] = useState9(null);
13531
+ const [dimensions, setDimensions] = useState10({ width: 0, height: 0 });
13532
+ const [activeSide, setActiveSide] = useState10(null);
13266
13533
  const { focusIdx, template, setIsScaling } = useEditorStore();
13267
13534
  const { currentWidth, currentHeight, currentAlign } = useMemo12(() => {
13268
13535
  if (!focusIdx || !template) {
@@ -13345,7 +13612,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13345
13612
  document.removeEventListener("pointermove", handlePointerMove);
13346
13613
  document.removeEventListener("pointerup", handlePointerUp);
13347
13614
  }, [handlePointerMove, setIsScaling]);
13348
- useEffect13(() => {
13615
+ useEffect14(() => {
13349
13616
  return () => {
13350
13617
  document.removeEventListener("pointermove", handlePointerMove);
13351
13618
  document.removeEventListener("pointerup", handlePointerUp);
@@ -13366,7 +13633,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13366
13633
  offset6(({ rects }) => -rects.reference.height)
13367
13634
  ]
13368
13635
  });
13369
- useEffect13(() => {
13636
+ useEffect14(() => {
13370
13637
  const rect = getReferenceRect();
13371
13638
  if (!rect || !refs.floating.current) return;
13372
13639
  refs.setPositionReference(virtualReference);
@@ -13395,7 +13662,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13395
13662
  const showRightHandle = currentAlign !== "right";
13396
13663
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13397
13664
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13398
- return /* @__PURE__ */ jsxs25(
13665
+ return /* @__PURE__ */ jsxs26(
13399
13666
  "div",
13400
13667
  {
13401
13668
  ref: refs.setFloating,
@@ -13407,28 +13674,28 @@ var ButtonScale = ({ getReferenceRect }) => {
13407
13674
  },
13408
13675
  className: "relative pointer-events-none",
13409
13676
  children: [
13410
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx42(
13677
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx43(
13411
13678
  "div",
13412
13679
  {
13413
13680
  onPointerDown: (e) => handlePointerDown(e, "top"),
13414
13681
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13415
13682
  }
13416
13683
  ),
13417
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx42(
13684
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx43(
13418
13685
  "div",
13419
13686
  {
13420
13687
  onPointerDown: (e) => handlePointerDown(e, "right"),
13421
13688
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
13422
13689
  }
13423
13690
  ),
13424
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx42(
13691
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx43(
13425
13692
  "div",
13426
13693
  {
13427
13694
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
13428
13695
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
13429
13696
  }
13430
13697
  ),
13431
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx42(
13698
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx43(
13432
13699
  "div",
13433
13700
  {
13434
13701
  onPointerDown: (e) => handlePointerDown(e, "left"),
@@ -13441,12 +13708,12 @@ var ButtonScale = ({ getReferenceRect }) => {
13441
13708
  };
13442
13709
 
13443
13710
  // src/core/editor/components/scaling/image-scale.tsx
13444
- import { useMemo as useMemo13, useEffect as useEffect14, useState as useState10, useRef as useRef7, useCallback as useCallback12 } from "react";
13711
+ import { useMemo as useMemo13, useEffect as useEffect15, useState as useState11, useRef as useRef7, useCallback as useCallback12 } from "react";
13445
13712
  import { useFloating as useFloating7, offset as offset7, autoUpdate as autoUpdate6 } from "@floating-ui/react";
13446
- import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
13713
+ import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
13447
13714
  var ImageScale = ({ getReferenceRect }) => {
13448
- const [dimensions, setDimensions] = useState10({ width: 0, height: 0 });
13449
- const [activeSide, setActiveSide] = useState10(null);
13715
+ const [dimensions, setDimensions] = useState11({ width: 0, height: 0 });
13716
+ const [activeSide, setActiveSide] = useState11(null);
13450
13717
  const { focusIdx, template, setIsScaling } = useEditorStore();
13451
13718
  const { currentWidth, currentHeight, currentAlign } = useMemo13(() => {
13452
13719
  if (!focusIdx || !template) {
@@ -13524,7 +13791,7 @@ var ImageScale = ({ getReferenceRect }) => {
13524
13791
  document.removeEventListener("pointermove", handlePointerMove);
13525
13792
  document.removeEventListener("pointerup", handlePointerUp);
13526
13793
  }, [handlePointerMove, setIsScaling]);
13527
- useEffect14(() => {
13794
+ useEffect15(() => {
13528
13795
  return () => {
13529
13796
  document.removeEventListener("pointermove", handlePointerMove);
13530
13797
  document.removeEventListener("pointerup", handlePointerUp);
@@ -13545,7 +13812,7 @@ var ImageScale = ({ getReferenceRect }) => {
13545
13812
  offset7(({ rects }) => -rects.reference.height)
13546
13813
  ]
13547
13814
  });
13548
- useEffect14(() => {
13815
+ useEffect15(() => {
13549
13816
  const rect = getReferenceRect();
13550
13817
  if (!rect || !refs.floating.current) return;
13551
13818
  refs.setPositionReference(virtualReference);
@@ -13574,7 +13841,7 @@ var ImageScale = ({ getReferenceRect }) => {
13574
13841
  const showRightHandle = currentAlign !== "right";
13575
13842
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13576
13843
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13577
- return /* @__PURE__ */ jsxs26(
13844
+ return /* @__PURE__ */ jsxs27(
13578
13845
  "div",
13579
13846
  {
13580
13847
  ref: refs.setFloating,
@@ -13586,28 +13853,28 @@ var ImageScale = ({ getReferenceRect }) => {
13586
13853
  },
13587
13854
  className: "relative pointer-events-none",
13588
13855
  children: [
13589
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx43(
13856
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx44(
13590
13857
  "div",
13591
13858
  {
13592
13859
  onPointerDown: (e) => handlePointerDown(e, "top"),
13593
13860
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13594
13861
  }
13595
13862
  ),
13596
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx43(
13863
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx44(
13597
13864
  "div",
13598
13865
  {
13599
13866
  onPointerDown: (e) => handlePointerDown(e, "right"),
13600
13867
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
13601
13868
  }
13602
13869
  ),
13603
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx43(
13870
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx44(
13604
13871
  "div",
13605
13872
  {
13606
13873
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
13607
13874
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
13608
13875
  }
13609
13876
  ),
13610
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx43(
13877
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx44(
13611
13878
  "div",
13612
13879
  {
13613
13880
  onPointerDown: (e) => handlePointerDown(e, "left"),
@@ -13620,12 +13887,12 @@ var ImageScale = ({ getReferenceRect }) => {
13620
13887
  };
13621
13888
 
13622
13889
  // src/core/editor/components/scaling/spacer-scale.tsx
13623
- import { useMemo as useMemo14, useEffect as useEffect15, useState as useState11, useRef as useRef8, useCallback as useCallback13 } from "react";
13890
+ import { useMemo as useMemo14, useEffect as useEffect16, useState as useState12, useRef as useRef8, useCallback as useCallback13 } from "react";
13624
13891
  import { useFloating as useFloating8, offset as offset8, autoUpdate as autoUpdate7 } from "@floating-ui/react";
13625
- import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
13892
+ import { jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
13626
13893
  var SpacerScale = ({ getReferenceRect }) => {
13627
- const [dimensions, setDimensions] = useState11({ width: 0, height: 0 });
13628
- const [activeSide, setActiveSide] = useState11(null);
13894
+ const [dimensions, setDimensions] = useState12({ width: 0, height: 0 });
13895
+ const [activeSide, setActiveSide] = useState12(null);
13629
13896
  const { focusIdx, template, setIsScaling } = useEditorStore();
13630
13897
  const currentHeight = useMemo14(() => {
13631
13898
  if (!focusIdx || !template) return 12;
@@ -13676,7 +13943,7 @@ var SpacerScale = ({ getReferenceRect }) => {
13676
13943
  document.removeEventListener("pointermove", handlePointerMove);
13677
13944
  document.removeEventListener("pointerup", handlePointerUp);
13678
13945
  }, [handlePointerMove, setIsScaling]);
13679
- useEffect15(() => {
13946
+ useEffect16(() => {
13680
13947
  return () => {
13681
13948
  document.removeEventListener("pointermove", handlePointerMove);
13682
13949
  document.removeEventListener("pointerup", handlePointerUp);
@@ -13697,7 +13964,7 @@ var SpacerScale = ({ getReferenceRect }) => {
13697
13964
  offset8(({ rects }) => -rects.reference.height)
13698
13965
  ]
13699
13966
  });
13700
- useEffect15(() => {
13967
+ useEffect16(() => {
13701
13968
  const rect = getReferenceRect();
13702
13969
  if (!rect || !refs.floating.current) return;
13703
13970
  refs.setPositionReference(virtualReference);
@@ -13724,7 +13991,7 @@ var SpacerScale = ({ getReferenceRect }) => {
13724
13991
  }, [getReferenceRect, refs, update, virtualReference]);
13725
13992
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13726
13993
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13727
- return /* @__PURE__ */ jsxs27(
13994
+ return /* @__PURE__ */ jsxs28(
13728
13995
  "div",
13729
13996
  {
13730
13997
  ref: refs.setFloating,
@@ -13736,14 +14003,14 @@ var SpacerScale = ({ getReferenceRect }) => {
13736
14003
  },
13737
14004
  className: "relative pointer-events-none",
13738
14005
  children: [
13739
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx44(
14006
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx45(
13740
14007
  "div",
13741
14008
  {
13742
14009
  onPointerDown: (e) => handlePointerDown(e, "top"),
13743
14010
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13744
14011
  }
13745
14012
  ),
13746
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx44(
14013
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx45(
13747
14014
  "div",
13748
14015
  {
13749
14016
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
@@ -13756,11 +14023,11 @@ var SpacerScale = ({ getReferenceRect }) => {
13756
14023
  };
13757
14024
 
13758
14025
  // src/core/editor/components/scaling/column-scale.tsx
13759
- import { useMemo as useMemo15, useEffect as useEffect16, useState as useState12, useRef as useRef9, useCallback as useCallback14 } from "react";
13760
- import { Fragment as Fragment16, jsx as jsx45 } from "react/jsx-runtime";
14026
+ import { useMemo as useMemo15, useEffect as useEffect17, useState as useState13, useRef as useRef9, useCallback as useCallback14 } from "react";
14027
+ import { Fragment as Fragment17, jsx as jsx46 } from "react/jsx-runtime";
13761
14028
  var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13762
- const [activeDivider, setActiveDivider] = useState12(null);
13763
- const [columnRects, setColumnRects] = useState12([]);
14029
+ const [activeDivider, setActiveDivider] = useState13(null);
14030
+ const [columnRects, setColumnRects] = useState13([]);
13764
14031
  const { template, setIsScaling, setFocusIdx, stopTextEditing } = useEditorStore();
13765
14032
  const columnWidths = useMemo15(() => {
13766
14033
  if (!template) return [];
@@ -13800,7 +14067,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13800
14067
  });
13801
14068
  setColumnRects(rects);
13802
14069
  }, [shadowRoot, sectionColumnIdx]);
13803
- useEffect16(() => {
14070
+ useEffect17(() => {
13804
14071
  updateColumnRects();
13805
14072
  let animationId;
13806
14073
  const updateLoop = () => {
@@ -13880,7 +14147,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13880
14147
  document.removeEventListener("pointermove", handlePointerMove);
13881
14148
  document.removeEventListener("pointerup", handlePointerUp);
13882
14149
  }, [handlePointerMove, setIsScaling]);
13883
- useEffect16(() => {
14150
+ useEffect17(() => {
13884
14151
  return () => {
13885
14152
  document.removeEventListener("pointermove", handlePointerMove);
13886
14153
  document.removeEventListener("pointerup", handlePointerUp);
@@ -13891,7 +14158,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13891
14158
  }
13892
14159
  const handleBaseClass = "bg-background shadow-md border rounded-full touch-none select-none pointer-events-auto";
13893
14160
  const getHandleActiveClass = (index) => activeDivider === index ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13894
- return /* @__PURE__ */ jsx45(Fragment16, { children: columnRects.slice(0, -1).map((rect, index) => {
14161
+ return /* @__PURE__ */ jsx46(Fragment17, { children: columnRects.slice(0, -1).map((rect, index) => {
13895
14162
  const nextRect = columnRects[index + 1];
13896
14163
  const handleLeft = rect.right;
13897
14164
  const handleTop = Math.min(rect.top, nextRect.top);
@@ -13899,7 +14166,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13899
14166
  if (activeDivider !== null && activeDivider !== index) {
13900
14167
  return null;
13901
14168
  }
13902
- return /* @__PURE__ */ jsx45(
14169
+ return /* @__PURE__ */ jsx46(
13903
14170
  "div",
13904
14171
  {
13905
14172
  onPointerDown: (e) => handlePointerDown(e, index),
@@ -13919,9 +14186,9 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13919
14186
  };
13920
14187
 
13921
14188
  // src/core/editor/hooks/use-undo-redo-keyboard.ts
13922
- import { useEffect as useEffect17 } from "react";
14189
+ import { useEffect as useEffect18 } from "react";
13923
14190
  function useUndoRedoKeyboard() {
13924
- useEffect17(() => {
14191
+ useEffect18(() => {
13925
14192
  const handler = (e) => {
13926
14193
  const isMeta = e.metaKey || e.ctrlKey;
13927
14194
  if (!isMeta || e.key.toLowerCase() !== "z") return;
@@ -13942,11 +14209,11 @@ function useUndoRedoKeyboard() {
13942
14209
  }
13943
14210
 
13944
14211
  // src/components/ui/spinner.tsx
13945
- import { Loader2Icon } from "lucide-react";
13946
- import { jsx as jsx46 } from "react/jsx-runtime";
14212
+ import { Loader2Icon as Loader2Icon2 } from "lucide-react";
14213
+ import { jsx as jsx47 } from "react/jsx-runtime";
13947
14214
  function Spinner({ className, ...props }) {
13948
- return /* @__PURE__ */ jsx46(
13949
- Loader2Icon,
14215
+ return /* @__PURE__ */ jsx47(
14216
+ Loader2Icon2,
13950
14217
  {
13951
14218
  role: "status",
13952
14219
  "aria-label": "Loading",
@@ -13960,7 +14227,7 @@ function Spinner({ className, ...props }) {
13960
14227
  import { EyeIcon } from "lucide-react";
13961
14228
 
13962
14229
  // src/render/useMjmlCompiler.ts
13963
- import { useState as useState13, useCallback as useCallback15 } from "react";
14230
+ import { useState as useState14, useCallback as useCallback15 } from "react";
13964
14231
  async function compileMjml(mjml) {
13965
14232
  console.log("Compiling MJML", mjml);
13966
14233
  const response = await fetch("/api/mrender", {
@@ -13976,24 +14243,15 @@ async function compileMjml(mjml) {
13976
14243
  return result;
13977
14244
  }
13978
14245
 
13979
- // src/core/editor/hooks/use-user.ts
13980
- function useUser() {
13981
- return {
13982
- isPaid: true
13983
- // toggle to true for testing paid features
13984
- };
13985
- }
13986
-
13987
14246
  // src/core/editor/components/preview.tsx
13988
- import { useEffect as useEffect18, useState as useState14, useRef as useRef10 } from "react";
13989
- import { jsx as jsx47, jsxs as jsxs28 } from "react/jsx-runtime";
14247
+ import { useEffect as useEffect19, useState as useState15, useRef as useRef10 } from "react";
14248
+ import { jsx as jsx48, jsxs as jsxs29 } from "react/jsx-runtime";
13990
14249
  function Preview() {
13991
- const { isPaid } = useUser();
13992
- const { template, setPreviewMode, previewMode } = useEditorStore();
13993
- const [html, setHtml] = useState14("");
13994
- const [isLoading, setIsLoading] = useState14(false);
14250
+ const { template, setPreviewMode, previewMode, isPaidLevel } = useEditorStore();
14251
+ const [html, setHtml] = useState15("");
14252
+ const [isLoading, setIsLoading] = useState15(false);
13995
14253
  const lastTemplateRef = useRef10("");
13996
- useEffect18(() => {
14254
+ useEffect19(() => {
13997
14255
  if (typeof window === "undefined" || !previewMode) {
13998
14256
  if (!previewMode) {
13999
14257
  setHtml("");
@@ -14009,7 +14267,7 @@ function Preview() {
14009
14267
  setIsLoading(true);
14010
14268
  const convertMjml = async () => {
14011
14269
  try {
14012
- const mjmlString = json2mjml(template, "production", { isPaid });
14270
+ const mjmlString = json2mjml(template, "production", { isPaidLevel });
14013
14271
  console.log("MJML string:", mjmlString);
14014
14272
  const result = await compileMjml(mjmlString);
14015
14273
  if (result.errors?.length > 0) {
@@ -14026,37 +14284,37 @@ function Preview() {
14026
14284
  };
14027
14285
  convertMjml();
14028
14286
  }, [template, previewMode]);
14029
- return /* @__PURE__ */ jsxs28(Dialog, { open: previewMode, onOpenChange: setPreviewMode, children: [
14030
- /* @__PURE__ */ jsxs28(Tooltip, { children: [
14031
- /* @__PURE__ */ jsx47(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx47(
14287
+ return /* @__PURE__ */ jsxs29(Dialog, { open: previewMode, onOpenChange: setPreviewMode, children: [
14288
+ /* @__PURE__ */ jsxs29(Tooltip, { children: [
14289
+ /* @__PURE__ */ jsx48(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx48(
14032
14290
  Button,
14033
14291
  {
14034
14292
  variant: "ghost",
14035
14293
  className: "shadow-none transition-none cursor-pointer",
14036
14294
  size: "icon",
14037
14295
  onClick: () => setPreviewMode(true),
14038
- children: /* @__PURE__ */ jsx47(EyeIcon, {})
14296
+ children: /* @__PURE__ */ jsx48(EyeIcon, {})
14039
14297
  }
14040
14298
  ) }),
14041
- /* @__PURE__ */ jsx47(TooltipContent, { side: "bottom", className: "z-51", children: "Preview" })
14299
+ /* @__PURE__ */ jsx48(TooltipContent, { side: "bottom", className: "z-51", children: "Preview" })
14042
14300
  ] }),
14043
- /* @__PURE__ */ jsxs28(DialogContent, { className: "max-w-[1200px] sm:max-w-[1200px]", children: [
14044
- /* @__PURE__ */ jsx47(DialogTitle, { children: "Preview" }),
14045
- /* @__PURE__ */ jsx47("div", { className: "w-full h-full max-h-[600px]", children: isLoading ? /* @__PURE__ */ jsx47("div", { className: "flex items-center justify-center h-[600px]", children: /* @__PURE__ */ jsx47("p", { children: "Generating preview..." }) }) : /* @__PURE__ */ jsx47("iframe", { srcDoc: html, className: "w-full h-[600px]" }) })
14301
+ /* @__PURE__ */ jsxs29(DialogContent, { className: "max-w-[1200px] sm:max-w-[1200px]", children: [
14302
+ /* @__PURE__ */ jsx48(DialogTitle, { children: "Preview" }),
14303
+ /* @__PURE__ */ jsx48("div", { className: "w-full h-full max-h-[600px]", children: isLoading ? /* @__PURE__ */ jsx48("div", { className: "flex items-center justify-center h-[600px]", children: /* @__PURE__ */ jsx48("p", { children: "Generating preview..." }) }) : /* @__PURE__ */ jsx48("iframe", { srcDoc: html, className: "w-full h-[600px]" }) })
14046
14304
  ] })
14047
14305
  ] });
14048
14306
  }
14049
14307
 
14050
14308
  // src/core/editor/components/history.tsx
14051
14309
  import { Redo2Icon, Undo2Icon } from "lucide-react";
14052
- import { Fragment as Fragment17, jsx as jsx48, jsxs as jsxs29 } from "react/jsx-runtime";
14310
+ import { Fragment as Fragment18, jsx as jsx49, jsxs as jsxs30 } from "react/jsx-runtime";
14053
14311
  var History = () => {
14054
14312
  const { undo, redo } = useEditorStore();
14055
14313
  const canUndo = useEditorStore((s) => s.historyIndex > 0);
14056
14314
  const canRedo = useEditorStore((s) => s.historyIndex < s.history.length - 1);
14057
- return /* @__PURE__ */ jsxs29(Fragment17, { children: [
14058
- /* @__PURE__ */ jsxs29(Tooltip, { children: [
14059
- /* @__PURE__ */ jsx48(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx48(
14315
+ return /* @__PURE__ */ jsxs30(Fragment18, { children: [
14316
+ /* @__PURE__ */ jsxs30(Tooltip, { children: [
14317
+ /* @__PURE__ */ jsx49(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx49(
14060
14318
  Button,
14061
14319
  {
14062
14320
  variant: "ghost",
@@ -14064,13 +14322,13 @@ var History = () => {
14064
14322
  size: "icon",
14065
14323
  disabled: !canUndo,
14066
14324
  onClick: undo,
14067
- children: /* @__PURE__ */ jsx48(Undo2Icon, {})
14325
+ children: /* @__PURE__ */ jsx49(Undo2Icon, {})
14068
14326
  }
14069
14327
  ) }),
14070
- /* @__PURE__ */ jsx48(TooltipContent, { side: "bottom", children: "Undo (Ctrl+Z)" })
14328
+ /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", children: "Undo (Ctrl+Z)" })
14071
14329
  ] }),
14072
- /* @__PURE__ */ jsxs29(Tooltip, { children: [
14073
- /* @__PURE__ */ jsx48(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx48(
14330
+ /* @__PURE__ */ jsxs30(Tooltip, { children: [
14331
+ /* @__PURE__ */ jsx49(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx49(
14074
14332
  Button,
14075
14333
  {
14076
14334
  variant: "ghost",
@@ -14078,16 +14336,16 @@ var History = () => {
14078
14336
  size: "icon",
14079
14337
  disabled: !canRedo,
14080
14338
  onClick: redo,
14081
- children: /* @__PURE__ */ jsx48(Redo2Icon, {})
14339
+ children: /* @__PURE__ */ jsx49(Redo2Icon, {})
14082
14340
  }
14083
14341
  ) }),
14084
- /* @__PURE__ */ jsx48(TooltipContent, { side: "bottom", children: "Redo (Ctrl+Shift+Z)" })
14342
+ /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", children: "Redo (Ctrl+Shift+Z)" })
14085
14343
  ] })
14086
14344
  ] });
14087
14345
  };
14088
14346
 
14089
14347
  // src/core/index.tsx
14090
- import { jsx as jsx49, jsxs as jsxs30 } from "react/jsx-runtime";
14348
+ import { jsx as jsx50, jsxs as jsxs31 } from "react/jsx-runtime";
14091
14349
  var MAILLOW_EMAIL_EDITOR_VERSION = "0.0.1";
14092
14350
  function getSectionColumnIdx(idx, template) {
14093
14351
  let current = idx;
@@ -14151,12 +14409,12 @@ function Editor({ setEditorLoading }) {
14151
14409
  const startTextEditing = useEditorStore((state) => state.startTextEditing);
14152
14410
  const pendingTextEditRequest = useEditorStore((state) => state.pendingTextEditRequest);
14153
14411
  const clearPendingTextEditRequest = useEditorStore((state) => state.clearPendingTextEditRequest);
14154
- const [renderData, setRenderData] = useState15(null);
14155
- const [isEditing, setIsEditing] = useState15(false);
14156
- const [dropIndicator, setDropIndicator] = useState15(null);
14157
- const [dropTargetIdx, setDropTargetIdx] = useState15(null);
14412
+ const [renderData, setRenderData] = useState16(null);
14413
+ const [isEditing, setIsEditing] = useState16(false);
14414
+ const [dropIndicator, setDropIndicator] = useState16(null);
14415
+ const [dropTargetIdx, setDropTargetIdx] = useState16(null);
14158
14416
  const shadowRootRef = useRef11(null);
14159
- const [hasSelectedElement, setHasSelectedElement] = useState15(false);
14417
+ const [hasSelectedElement, setHasSelectedElement] = useState16(false);
14160
14418
  const dragParentIdxRef = useRef11(null);
14161
14419
  const dragPositionIndexRef = useRef11(0);
14162
14420
  const createNewSectionRef = useRef11(false);
@@ -14171,8 +14429,13 @@ function Editor({ setEditorLoading }) {
14171
14429
  const sectionRectCacheRef = useRef11(/* @__PURE__ */ new Map());
14172
14430
  const companyFooterCacheRef = useRef11(void 0);
14173
14431
  const lastSyncedTemplateRef = useRef11(null);
14174
- useEffect19(() => {
14175
- if (!isEditing) {
14432
+ const prevTextEditingIdxRef = useRef11(null);
14433
+ useEffect20(() => {
14434
+ const currentIdx = textEditing?.idx ?? null;
14435
+ const prevIdx = prevTextEditingIdxRef.current;
14436
+ const switchedTarget = currentIdx !== null && prevIdx !== null && currentIdx !== prevIdx;
14437
+ prevTextEditingIdxRef.current = currentIdx;
14438
+ if (!isEditing && (!textEditing || switchedTarget)) {
14176
14439
  if (template === lastSyncedTemplateRef.current) {
14177
14440
  return;
14178
14441
  }
@@ -14181,13 +14444,13 @@ function Editor({ setEditorLoading }) {
14181
14444
  }
14182
14445
  lastSyncedTemplateRef.current = template;
14183
14446
  }
14184
- }, [template, renderData, isEditing]);
14185
- useEffect19(() => {
14447
+ }, [template, renderData, isEditing, textEditing]);
14448
+ useEffect20(() => {
14186
14449
  if (renderData && setEditorLoading) {
14187
14450
  setEditorLoading(false);
14188
14451
  }
14189
14452
  }, [renderData, setEditorLoading]);
14190
- useEffect19(() => {
14453
+ useEffect20(() => {
14191
14454
  if (!pendingTextEditRequest || !shadowRootRef.current) return;
14192
14455
  const { idx, cursorPosition } = pendingTextEditRequest;
14193
14456
  const blockNode = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
@@ -14229,10 +14492,14 @@ function Editor({ setEditorLoading }) {
14229
14492
  const element = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
14230
14493
  return element ? element.getBoundingClientRect() : null;
14231
14494
  };
14232
- startTextEditing({ idx, getReferenceRect: getReferenceRect2, initialWidth: blockRect.width, initialHeight: blockRect.height, clickX, clickY, content, styles, cursorPosition });
14495
+ const getShadowElement = () => {
14496
+ if (!shadowRootRef.current) return null;
14497
+ return shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
14498
+ };
14499
+ startTextEditing({ idx, getReferenceRect: getReferenceRect2, getShadowElement, initialWidth: blockRect.width, initialHeight: blockRect.height, clickX, clickY, content, styles, cursorPosition });
14233
14500
  clearPendingTextEditRequest();
14234
14501
  }, [pendingTextEditRequest, clearPendingTextEditRequest, startTextEditing]);
14235
- useEffect19(() => {
14502
+ useEffect20(() => {
14236
14503
  if (isDragging && dataTransfer) {
14237
14504
  const currentTemplate = useEditorStore.getState().template;
14238
14505
  templateCacheRef.current = currentTemplate;
@@ -14248,9 +14515,9 @@ function Editor({ setEditorLoading }) {
14248
14515
  sectionRectCacheRef.current.clear();
14249
14516
  }
14250
14517
  }, [isDragging, dataTransfer]);
14251
- const [html, setHtml] = useState15("");
14518
+ const [html, setHtml] = useState16("");
14252
14519
  const lastRenderDataRef = useRef11("");
14253
- useEffect19(() => {
14520
+ useEffect20(() => {
14254
14521
  if (typeof window === "undefined" || !renderData) {
14255
14522
  setHtml("");
14256
14523
  lastRenderDataRef.current = "";
@@ -14347,7 +14614,11 @@ function Editor({ setEditorLoading }) {
14347
14614
  const element = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
14348
14615
  return element ? element.getBoundingClientRect() : null;
14349
14616
  };
14350
- startTextEditing({ idx, getReferenceRect: getReferenceRect2, initialWidth, initialHeight, clickX, clickY, content, styles });
14617
+ const getShadowElement = () => {
14618
+ if (!shadowRootRef.current) return null;
14619
+ return shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
14620
+ };
14621
+ startTextEditing({ idx, getReferenceRect: getReferenceRect2, getShadowElement, initialWidth, initialHeight, clickX, clickY, content, styles });
14351
14622
  },
14352
14623
  [startTextEditing]
14353
14624
  );
@@ -14960,9 +15231,9 @@ function Editor({ setEditorLoading }) {
14960
15231
  [template.content[0]?.data?.value?.showCompanyFooter]
14961
15232
  );
14962
15233
  if (!html) {
14963
- return /* @__PURE__ */ jsx49("div", { className: "maillow-editor flex items-center justify-center h-[500px]", children: /* @__PURE__ */ jsx49(Spinner, {}) });
15234
+ return /* @__PURE__ */ jsx50("div", { className: "maillow-editor flex items-center justify-center h-[500px]", children: /* @__PURE__ */ jsx50(Spinner, {}) });
14964
15235
  }
14965
- return /* @__PURE__ */ jsxs30(
15236
+ return /* @__PURE__ */ jsxs31(
14966
15237
  "div",
14967
15238
  {
14968
15239
  className: "maillow-editor relative ",
@@ -14973,7 +15244,7 @@ function Editor({ setEditorLoading }) {
14973
15244
  justifyContent: "center"
14974
15245
  },
14975
15246
  children: [
14976
- /* @__PURE__ */ jsx49(
15247
+ /* @__PURE__ */ jsx50(
14977
15248
  "div",
14978
15249
  {
14979
15250
  className: `editor-container rounded-b-[12px] border-t-1 border-t-accent max-w-[626px]`,
@@ -14983,7 +15254,7 @@ function Editor({ setEditorLoading }) {
14983
15254
  backgroundColor: "#f5f5f5",
14984
15255
  overflow: "auto"
14985
15256
  },
14986
- children: /* @__PURE__ */ jsx49(
15257
+ children: /* @__PURE__ */ jsx50(
14987
15258
  ShadowDomRenderer,
14988
15259
  {
14989
15260
  html,
@@ -15012,9 +15283,9 @@ function Editor({ setEditorLoading }) {
15012
15283
  )
15013
15284
  }
15014
15285
  ),
15015
- /* @__PURE__ */ jsx49(ElementsSuggestions, {}),
15016
- /* @__PURE__ */ jsx49(TiptapOverlay, {}),
15017
- !isDragging && !isScaling && hasSelectedElement && focusIdx && selectedElement?.type && /* @__PURE__ */ jsx49(
15286
+ /* @__PURE__ */ jsx50(ElementsSuggestions, {}),
15287
+ /* @__PURE__ */ jsx50(TiptapOverlay, {}),
15288
+ !isDragging && !isScaling && hasSelectedElement && focusIdx && selectedElement?.type && /* @__PURE__ */ jsx50(
15018
15289
  ElementFloat,
15019
15290
  {
15020
15291
  getReferenceRect,
@@ -15022,7 +15293,7 @@ function Editor({ setEditorLoading }) {
15022
15293
  elementType: selectedElement.type
15023
15294
  }
15024
15295
  ),
15025
- !isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */ jsx49(
15296
+ !isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */ jsx50(
15026
15297
  DragButton,
15027
15298
  {
15028
15299
  getReferenceRect,
@@ -15031,17 +15302,17 @@ function Editor({ setEditorLoading }) {
15031
15302
  isDragging
15032
15303
  }
15033
15304
  ),
15034
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "divider" && /* @__PURE__ */ jsx49(DividerScale, { getReferenceRect }),
15035
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "button" && /* @__PURE__ */ jsx49(ButtonScale, { getReferenceRect }),
15036
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "image" && /* @__PURE__ */ jsx49(ImageScale, { getReferenceRect }),
15037
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "space" && /* @__PURE__ */ jsx49(SpacerScale, { getReferenceRect }),
15305
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "divider" && /* @__PURE__ */ jsx50(DividerScale, { getReferenceRect }),
15306
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "button" && /* @__PURE__ */ jsx50(ButtonScale, { getReferenceRect }),
15307
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "image" && /* @__PURE__ */ jsx50(ImageScale, { getReferenceRect }),
15308
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "space" && /* @__PURE__ */ jsx50(SpacerScale, { getReferenceRect }),
15038
15309
  !isDragging && hasSelectedElement && focusIdx && renderData && (() => {
15039
15310
  const sectionColumnIdx = getSectionColumnIdx(focusIdx, renderData);
15040
15311
  if (!sectionColumnIdx) return null;
15041
15312
  const sectionColumn = getValueByIdx(renderData, sectionColumnIdx);
15042
15313
  if (!sectionColumn || sectionColumn.type !== "section-column") return null;
15043
15314
  if (!sectionColumn.children || sectionColumn.children.length < 2) return null;
15044
- return /* @__PURE__ */ jsx49(
15315
+ return /* @__PURE__ */ jsx50(
15045
15316
  ColumnScale,
15046
15317
  {
15047
15318
  sectionColumnIdx,
@@ -15065,6 +15336,7 @@ export {
15065
15336
  parsePrice,
15066
15337
  json2mjml,
15067
15338
  MAX_TEMPLATE_SIZE,
15339
+ MAX_PAID_LEVEL,
15068
15340
  useEditorStore,
15069
15341
  BUTTON_ALIGNMENTS,
15070
15342
  ALIGNMENT_ICONS,
@@ -15113,7 +15385,6 @@ export {
15113
15385
  SidebarProvider,
15114
15386
  useSidebarContext,
15115
15387
  Textarea,
15116
- useUser,
15117
15388
  Preview,
15118
15389
  History,
15119
15390
  MAILLOW_EMAIL_EDITOR_VERSION,