@kgalexander/mcreate 0.0.15 → 0.0.17

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 useMemo17, useState as useState16, useEffect as useEffect20, useCallback as useCallback17, useRef as useRef11 } 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
@@ -212,6 +212,117 @@ function formatOpenHouseTime(time24) {
212
212
  return `${hour12}${period}`;
213
213
  }
214
214
 
215
+ // src/core/editor/constant/configuration.ts
216
+ import { AlignCenterIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, Heading1Icon, Heading2Icon, Heading3Icon, LinkIcon, ListIcon, ListOrderedIcon, MailIcon, PhoneIcon, Pilcrow } from "lucide-react";
217
+ var MAX_TEMPLATE_SIZE = 50 * 1024;
218
+ var BUTTON_ALIGNMENTS = ["left", "center", "right"];
219
+ var ALIGNMENT_ICONS = {
220
+ left: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-left.svg",
221
+ center: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-center.svg",
222
+ right: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-right.svg"
223
+ };
224
+ var FONTS = [
225
+ "Arial",
226
+ "Helvetica",
227
+ "Times New Roman",
228
+ "Courier New",
229
+ "Verdana",
230
+ "Tahoma",
231
+ "Trebuchet MS",
232
+ "Georgia"
233
+ ];
234
+ var TEXT_ALIGNMENT_ICONS = {
235
+ left: AlignLeftIcon,
236
+ center: AlignCenterIcon,
237
+ right: AlignRightIcon,
238
+ justify: AlignJustifyIcon
239
+ };
240
+ var TEXT_TYPE_OPTIONS = [
241
+ { type: "paragraph", label: "Paragraph", Icon: Pilcrow, disabled: false },
242
+ { type: "h1", label: "Heading 1", Icon: Heading1Icon, disabled: false },
243
+ { type: "h2", label: "Heading 2", Icon: Heading2Icon, disabled: false },
244
+ { type: "h3", label: "Heading 3", Icon: Heading3Icon, disabled: false },
245
+ { type: "list", label: "Bulleted", Icon: ListIcon, disabled: true },
246
+ { type: "ordered", label: "Numbered", Icon: ListOrderedIcon, disabled: true }
247
+ ];
248
+ var DEFAULT_FONT_SIZE = 14;
249
+ var MIN_FONT_SIZE = 6;
250
+ var MAX_FONT_SIZE = 72;
251
+ var FONT_SIZE_STEP = 1;
252
+ var LINK_TYPES = [
253
+ {
254
+ name: "Email",
255
+ placeholder: "email@example.com",
256
+ icon: MailIcon,
257
+ inputType: "email",
258
+ prefix: "mailto:"
259
+ },
260
+ {
261
+ name: "Website",
262
+ placeholder: "https://example.com",
263
+ icon: LinkIcon,
264
+ inputType: "url",
265
+ prefix: ""
266
+ },
267
+ {
268
+ name: "Phone",
269
+ placeholder: "+1234567890",
270
+ icon: PhoneIcon,
271
+ inputType: "tel",
272
+ prefix: "tel:"
273
+ }
274
+ ];
275
+ var LINK_PRESETS = {
276
+ Phone: [
277
+ { label: "Personal Phone", key: "personal_phone_number" },
278
+ { label: "Office Phone", key: "office_phone_number" },
279
+ { label: "Business Phone", key: "business_phone_number" }
280
+ ],
281
+ Website: [
282
+ { label: "Team Website", key: "team_website" },
283
+ { label: "Brokerage Website", key: "brokerage_website" }
284
+ ]
285
+ };
286
+ var detectLinkType = (href) => {
287
+ if (href.startsWith("mailto:")) return LINK_TYPES[0];
288
+ if (href.startsWith("tel:")) return LINK_TYPES[2];
289
+ return LINK_TYPES[1];
290
+ };
291
+ var stripPrefix = (href) => {
292
+ if (href.startsWith("mailto:")) return href.slice(7);
293
+ if (href.startsWith("tel:")) return href.slice(4);
294
+ return href;
295
+ };
296
+ var normalizeWebsiteUrl = (url) => {
297
+ if (!url) return "";
298
+ if (url.match(/^https?:\/\//i)) return url;
299
+ if (url.startsWith("mailto:") || url.startsWith("tel:")) return url;
300
+ return "https://" + url;
301
+ };
302
+ var DEFAULT_LETTER_SPACING = 0;
303
+ var MIN_LETTER_SPACING = -2;
304
+ var MAX_LETTER_SPACING = 10;
305
+ var LETTER_SPACING_STEP = 0.1;
306
+ var DEFAULT_LINE_HEIGHT = 1.4;
307
+ var MIN_LINE_HEIGHT = 0.8;
308
+ var MAX_LINE_HEIGHT = 3;
309
+ var LINE_HEIGHT_STEP = 0.1;
310
+ var HIDDEN_SELECTION_VISUAL_ELEMENTS = ["text", "divider", "column"];
311
+ var NOT_DRAGGABLE_ELEMENTS = ["page", "social-item", "text", "property-card", "property-card-single-two", "property-card-triple", "property-card-triple-item"];
312
+ var EDITOR_COLORS = {
313
+ /** Purple — drag/drop state */
314
+ drag: {
315
+ solid: "rgb(59, 130, 246)",
316
+ half: "rgba(59, 130, 246, 0.5)"
317
+ },
318
+ /** Blue — hover/selection state */
319
+ hover: {
320
+ solid: "rgb(59, 130, 246)",
321
+ half: "rgba(59, 130, 246, 0.5)"
322
+ }
323
+ };
324
+ var DEFAULT_PROPERTY_PLACEHOLDER_IMAGE = "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg";
325
+
215
326
  // src/render/Mockup/mock-property-better.ts
216
327
  function propertyCardMockMjml(block, context) {
217
328
  const a = block.attributes;
@@ -225,7 +336,7 @@ function propertyCardMockMjml(block, context) {
225
336
  const baths = formatNumber(a["baths"] || "");
226
337
  const sqft = formatNumber(a["sqft"] || "");
227
338
  const description = a["description"] || "";
228
- const imageSrc = a["image-src"] || "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg";
339
+ const imageSrc = a["image-src"] || DEFAULT_PROPERTY_PLACEHOLDER_IMAGE;
229
340
  const imageAlt = a["image-alt"] || "Photo of a Property";
230
341
  const status = a["status"] || "Empty";
231
342
  const statusColor = a["status-color"] || "#B8B8B8";
@@ -393,7 +504,7 @@ function propertyCardSingleTwoMockMjml(block, context) {
393
504
  const baths = formatNumber(a["baths"] || "");
394
505
  const sqft = formatNumber(a["sqft"] || "");
395
506
  const description = a["description"] || "";
396
- const imageSrc = a["image-src"] || "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg";
507
+ const imageSrc = a["image-src"] || DEFAULT_PROPERTY_PLACEHOLDER_IMAGE;
397
508
  const imageAlt = a["image-alt"] || "Photo of a Property";
398
509
  const status = a["status"] || "Empty";
399
510
  const statusColor = a["status-color"] || "#B8B8B8";
@@ -583,7 +694,7 @@ function renderCard(child, childIdx, context, uniqueId, borderRadius, imageHeigh
583
694
  const baths = formatNumber(attrs["baths"] || "--");
584
695
  const sqft = formatNumber(attrs["sqft"] || "--");
585
696
  const city = attrs["city"] || "City";
586
- const imageSrc = attrs["image-src"] || "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg";
697
+ const imageSrc = attrs["image-src"] || DEFAULT_PROPERTY_PLACEHOLDER_IMAGE;
587
698
  const childTrackingClasses = context.mode === "editing" ? getTrackingClasses(childIdx, "property-card-triple-item") : "";
588
699
  return `
589
700
  <table class="property-triple-card-${uniqueId} property-triple-table ${childTrackingClasses}" role="presentation" align="center" cellpadding="0" cellspacing="0" border="0" style="width:100%; border:${border}; border-radius:${borderRadius}; border-collapse:separate;${backgroundColor !== "transparent" ? ` background-color:${backgroundColor};` : ""}">
@@ -1249,7 +1360,7 @@ function createImageElement(payload) {
1249
1360
  type: "image",
1250
1361
  tagName: "mj-image",
1251
1362
  attributes: {
1252
- src: "https://placehold.co/600x200",
1363
+ src: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/placeholder_image.png",
1253
1364
  alt: "",
1254
1365
  padding: "0px 0px",
1255
1366
  "fluid-on-mobile": "true",
@@ -1397,7 +1508,7 @@ function createPropertyCardElement(payload) {
1397
1508
  tagName: "mj-colproperty",
1398
1509
  data: { value: {} },
1399
1510
  attributes: {
1400
- "image-src": "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg",
1511
+ "image-src": DEFAULT_PROPERTY_PLACEHOLDER_IMAGE,
1401
1512
  "image-alt": "Property image",
1402
1513
  "price": "$0",
1403
1514
  "address": "123 Main Street",
@@ -1426,7 +1537,7 @@ function createPropertyCardSingleTwoElement(payload) {
1426
1537
  tagName: "mj-propertysingletwo",
1427
1538
  data: { value: {} },
1428
1539
  attributes: {
1429
- "image-src": "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg",
1540
+ "image-src": DEFAULT_PROPERTY_PLACEHOLDER_IMAGE,
1430
1541
  "image-alt": "Property image",
1431
1542
  "price": "$0",
1432
1543
  "address": "123 Main Street",
@@ -1521,7 +1632,7 @@ function createPropertyCardTripleItemElement(payload) {
1521
1632
  tagName: "mj-propertytripleitem",
1522
1633
  data: { value: {} },
1523
1634
  attributes: {
1524
- "image-src": payload?.attributes?.["image-src"] || "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg",
1635
+ "image-src": payload?.attributes?.["image-src"] || DEFAULT_PROPERTY_PLACEHOLDER_IMAGE,
1525
1636
  "href": payload?.attributes?.["href"] || "",
1526
1637
  "price": payload?.attributes?.["price"] || "$0",
1527
1638
  "beds": payload?.attributes?.["beds"] || "--",
@@ -1685,7 +1796,6 @@ var empty_default = {
1685
1796
 
1686
1797
  // src/core/editor/state/editor.ts
1687
1798
  var SECTION_INDEX_REGEX = /^content\.children\.\[(\d+)\]/;
1688
- var MAX_TEMPLATE_SIZE = 50 * 1024;
1689
1799
  function calculateTemplateSize(template) {
1690
1800
  const str = JSON.stringify(template);
1691
1801
  return new Blob([str]).size;
@@ -1706,6 +1816,7 @@ var useEditorStore = create()(
1706
1816
  onSave: null,
1707
1817
  onToast: null,
1708
1818
  onExit: null,
1819
+ onImageUpload: null,
1709
1820
  previewMode: false,
1710
1821
  focusIdx: null,
1711
1822
  hoverIdx: null,
@@ -1714,6 +1825,7 @@ var useEditorStore = create()(
1714
1825
  dataTransfer: null,
1715
1826
  isScaling: false,
1716
1827
  slashCommand: null,
1828
+ mergeFieldSuggestion: null,
1717
1829
  textEditing: null,
1718
1830
  pendingTextEditRequest: null,
1719
1831
  tiptapEditor: null,
@@ -1732,21 +1844,27 @@ var useEditorStore = create()(
1732
1844
  // User data
1733
1845
  images: [],
1734
1846
  userData: null,
1847
+ mergeFields: [],
1735
1848
  // Render sync
1736
1849
  renderSyncNeeded: 0,
1737
1850
  // Initialize store with external template (for npm package usage)
1738
- initializeWithTemplate: (templateId, template, onSave, onToast, data, onExit) => {
1851
+ initializeWithTemplate: (templateId, template, onSave, onToast, data, onExit, onImageUpload) => {
1739
1852
  set((state) => {
1740
1853
  state.templateId = templateId;
1741
1854
  state.template = template;
1742
1855
  state.onSave = onSave ?? null;
1743
1856
  state.onToast = onToast ?? null;
1744
1857
  state.onExit = onExit ?? null;
1858
+ state.onImageUpload = onImageUpload ?? null;
1745
1859
  state.isPaidLevel = data?.isPaidLevel ?? 0;
1746
1860
  state.images = data?.images ?? [];
1747
1861
  state.userData = data?.userData ?? null;
1862
+ state.mergeFields = (data?.mergefields ?? []).map((f) => ({
1863
+ label: (f.name || "").replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
1864
+ value: (f.merge_tag || "").replace(/^\{\{|\}\}$/g, "")
1865
+ }));
1748
1866
  state.templateSize = calculateTemplateSize(template);
1749
- state.isAtSizeLimit = false;
1867
+ state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
1750
1868
  state.history = [cloneDeep(template)];
1751
1869
  state.historyIndex = 0;
1752
1870
  state.focusIdx = null;
@@ -1755,6 +1873,11 @@ var useEditorStore = create()(
1755
1873
  state.lastSavedSnapshot = JSON.stringify(template);
1756
1874
  });
1757
1875
  },
1876
+ addImage: (image2) => {
1877
+ set((state) => {
1878
+ state.images.push(castDraft(image2));
1879
+ });
1880
+ },
1758
1881
  // Template metadata actions
1759
1882
  setTemplateName: (name) => {
1760
1883
  set((state) => {
@@ -1835,6 +1958,17 @@ var useEditorStore = create()(
1835
1958
  }, 0);
1836
1959
  }
1837
1960
  },
1961
+ // Merge field suggestion actions
1962
+ setMergeFieldSuggestion: (suggestionState) => {
1963
+ set((state) => {
1964
+ state.mergeFieldSuggestion = suggestionState;
1965
+ });
1966
+ },
1967
+ clearMergeFieldSuggestion: () => {
1968
+ set((state) => {
1969
+ state.mergeFieldSuggestion = null;
1970
+ });
1971
+ },
1838
1972
  // Text editing actions (Tiptap overlay)
1839
1973
  startTextEditing: (textEditingState) => {
1840
1974
  set((state) => {
@@ -2913,117 +3047,6 @@ function setValueAtPath(template, path, value) {
2913
3047
 
2914
3048
  // src/core/editor/components/ShadowDomRenderer.tsx
2915
3049
  import { useEffect, useRef, memo } from "react";
2916
-
2917
- // src/core/editor/constant/configuration.ts
2918
- import { AlignCenterIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, Heading1Icon, Heading2Icon, Heading3Icon, LinkIcon, ListIcon, ListOrderedIcon, MailIcon, PhoneIcon, Pilcrow } from "lucide-react";
2919
- var BUTTON_ALIGNMENTS = ["left", "center", "right"];
2920
- var ALIGNMENT_ICONS = {
2921
- left: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-left.svg",
2922
- center: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-center.svg",
2923
- right: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-right.svg"
2924
- };
2925
- var FONTS = [
2926
- "Arial",
2927
- "Helvetica",
2928
- "Times New Roman",
2929
- "Courier New",
2930
- "Verdana",
2931
- "Tahoma",
2932
- "Trebuchet MS",
2933
- "Georgia"
2934
- ];
2935
- var TEXT_ALIGNMENT_ICONS = {
2936
- left: AlignLeftIcon,
2937
- center: AlignCenterIcon,
2938
- right: AlignRightIcon,
2939
- justify: AlignJustifyIcon
2940
- };
2941
- var TEXT_TYPE_OPTIONS = [
2942
- { type: "paragraph", label: "Paragraph", Icon: Pilcrow, disabled: false },
2943
- { type: "h1", label: "Heading 1", Icon: Heading1Icon, disabled: false },
2944
- { type: "h2", label: "Heading 2", Icon: Heading2Icon, disabled: false },
2945
- { type: "h3", label: "Heading 3", Icon: Heading3Icon, disabled: false },
2946
- { type: "list", label: "Bulleted", Icon: ListIcon, disabled: true },
2947
- { type: "ordered", label: "Numbered", Icon: ListOrderedIcon, disabled: true }
2948
- ];
2949
- var DEFAULT_FONT_SIZE = 14;
2950
- var MIN_FONT_SIZE = 6;
2951
- var MAX_FONT_SIZE = 72;
2952
- var FONT_SIZE_STEP = 1;
2953
- var LINK_TYPES = [
2954
- {
2955
- name: "Email",
2956
- placeholder: "email@example.com",
2957
- icon: MailIcon,
2958
- inputType: "email",
2959
- prefix: "mailto:"
2960
- },
2961
- {
2962
- name: "Website",
2963
- placeholder: "https://example.com",
2964
- icon: LinkIcon,
2965
- inputType: "url",
2966
- prefix: ""
2967
- },
2968
- {
2969
- name: "Phone",
2970
- placeholder: "+1234567890",
2971
- icon: PhoneIcon,
2972
- inputType: "tel",
2973
- prefix: "tel:"
2974
- }
2975
- ];
2976
- var LINK_PRESETS = {
2977
- Phone: [
2978
- { label: "Personal Phone", key: "personal_phone_number" },
2979
- { label: "Office Phone", key: "office_phone_number" },
2980
- { label: "Business Phone", key: "business_phone_number" }
2981
- ],
2982
- Website: [
2983
- { label: "Team Website", key: "team_website" },
2984
- { label: "Brokerage Website", key: "brokerage_website" }
2985
- ]
2986
- };
2987
- var detectLinkType = (href) => {
2988
- if (href.startsWith("mailto:")) return LINK_TYPES[0];
2989
- if (href.startsWith("tel:")) return LINK_TYPES[2];
2990
- return LINK_TYPES[1];
2991
- };
2992
- var stripPrefix = (href) => {
2993
- if (href.startsWith("mailto:")) return href.slice(7);
2994
- if (href.startsWith("tel:")) return href.slice(4);
2995
- return href;
2996
- };
2997
- var normalizeWebsiteUrl = (url) => {
2998
- if (!url) return "";
2999
- if (url.match(/^https?:\/\//i)) return url;
3000
- if (url.startsWith("mailto:") || url.startsWith("tel:")) return url;
3001
- return "https://" + url;
3002
- };
3003
- var DEFAULT_LETTER_SPACING = 0;
3004
- var MIN_LETTER_SPACING = -2;
3005
- var MAX_LETTER_SPACING = 10;
3006
- var LETTER_SPACING_STEP = 0.1;
3007
- var DEFAULT_LINE_HEIGHT = 1.4;
3008
- var MIN_LINE_HEIGHT = 0.8;
3009
- var MAX_LINE_HEIGHT = 3;
3010
- var LINE_HEIGHT_STEP = 0.1;
3011
- var HIDDEN_SELECTION_VISUAL_ELEMENTS = ["text", "divider", "column"];
3012
- var NOT_DRAGGABLE_ELEMENTS = ["page", "social-item", "text", "property-card", "property-card-single-two", "property-card-triple", "property-card-triple-item"];
3013
- var EDITOR_COLORS = {
3014
- /** Purple — drag/drop state */
3015
- drag: {
3016
- solid: "rgb(59, 130, 246)",
3017
- half: "rgba(59, 130, 246, 0.5)"
3018
- },
3019
- /** Blue — hover/selection state */
3020
- hover: {
3021
- solid: "rgb(59, 130, 246)",
3022
- half: "rgba(59, 130, 246, 0.5)"
3023
- }
3024
- };
3025
-
3026
- // src/core/editor/components/ShadowDomRenderer.tsx
3027
3050
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3028
3051
  var lastSizeLimitToastTime = 0;
3029
3052
  var cssCache = /* @__PURE__ */ new Map();
@@ -3358,6 +3381,19 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3358
3381
  }
3359
3382
  ` : ""}
3360
3383
 
3384
+ /* Merge field tags - dashed underline for {{variable}} patterns */
3385
+ .merge-field-tag {
3386
+
3387
+ background-color: var(--background);
3388
+ border-radius: 4px;
3389
+ padding: 0px;
3390
+ border: 1px solid var(--border);
3391
+ color: #000000;
3392
+ }
3393
+ .merge-field-tag:hover {
3394
+ cursor: pointer;
3395
+ }
3396
+
3361
3397
  /* Company footer - hide selection/hover outlines and make non-interactive */
3362
3398
  .is-company-footer,
3363
3399
  .is-company-footer .${EMAIL_BLOCK_CLASS_NAME} {
@@ -3983,6 +4019,7 @@ function isTextContentEmpty(element) {
3983
4019
  const text2 = element.textContent?.trim() || "";
3984
4020
  return text2.length === 0;
3985
4021
  }
4022
+ var MERGE_FIELD_REGEX_SHADOW = /\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}/g;
3986
4023
  function isParagraphEmpty(p) {
3987
4024
  const text2 = p.textContent || "";
3988
4025
  return text2.trim() === "" || text2 === "\xA0" || text2 === "&nbsp;";
@@ -4004,6 +4041,40 @@ function injectContentEditable(container) {
4004
4041
  }
4005
4042
  }
4006
4043
  });
4044
+ if (contentDiv.textContent?.includes("{{")) {
4045
+ const walker = document.createTreeWalker(contentDiv, NodeFilter.SHOW_TEXT);
4046
+ const textNodes = [];
4047
+ let tNode;
4048
+ while (tNode = walker.nextNode()) {
4049
+ if (tNode.textContent && MERGE_FIELD_REGEX_SHADOW.test(tNode.textContent)) {
4050
+ textNodes.push(tNode);
4051
+ }
4052
+ MERGE_FIELD_REGEX_SHADOW.lastIndex = 0;
4053
+ }
4054
+ for (const textNode of textNodes) {
4055
+ const text2 = textNode.textContent || "";
4056
+ const fragment = document.createDocumentFragment();
4057
+ let lastIndex = 0;
4058
+ MERGE_FIELD_REGEX_SHADOW.lastIndex = 0;
4059
+ let match;
4060
+ while ((match = MERGE_FIELD_REGEX_SHADOW.exec(text2)) !== null) {
4061
+ if (match.index > lastIndex) {
4062
+ fragment.appendChild(document.createTextNode(text2.slice(lastIndex, match.index)));
4063
+ }
4064
+ const span = document.createElement("span");
4065
+ span.className = "merge-field-tag";
4066
+ const fieldName = match[0].slice(2, -2);
4067
+ span.setAttribute("data-tooltip", fieldName.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
4068
+ span.textContent = match[0];
4069
+ fragment.appendChild(span);
4070
+ lastIndex = match.index + match[0].length;
4071
+ }
4072
+ if (lastIndex < text2.length) {
4073
+ fragment.appendChild(document.createTextNode(text2.slice(lastIndex)));
4074
+ }
4075
+ textNode.parentNode?.replaceChild(fragment, textNode);
4076
+ }
4077
+ }
4007
4078
  }
4008
4079
  });
4009
4080
  container.querySelectorAll(".node-type-button").forEach((buttonEl) => {
@@ -4825,20 +4896,172 @@ var ElementsSuggestionsContent = () => {
4825
4896
  );
4826
4897
  };
4827
4898
 
4828
- // src/core/editor/components/tiptap-overlay.tsx
4829
- import { useEditor, EditorContent } from "@tiptap/react";
4830
- import { BubbleMenu } from "@tiptap/react/menus";
4831
- import { TextSelection as TextSelection8 } from "@tiptap/pm/state";
4832
- import StarterKit from "@tiptap/starter-kit";
4833
- import { TextStyle, FontSize, LineHeight } from "@tiptap/extension-text-style";
4834
- import { Color } from "@tiptap/extension-color";
4835
- import TextAlign from "@tiptap/extension-text-align";
4836
- import Underline from "@tiptap/extension-underline";
4837
-
4838
- // node_modules/@tiptap/core/dist/index.js
4839
- import { liftTarget } from "@tiptap/pm/transform";
4840
- import { createParagraphNear as originalCreateParagraphNear } from "@tiptap/pm/commands";
4841
- import { TextSelection } from "@tiptap/pm/state";
4899
+ // src/core/editor/components/merge-field-suggestions.tsx
4900
+ import { useMemo as useMemo3, useEffect as useEffect4, useRef as useRef3, useState, useCallback as useCallback3 } from "react";
4901
+ import { useFloating as useFloating3, offset as offset3, shift as shift3, flip as flip2 } from "@floating-ui/react";
4902
+ import { BracesIcon } from "lucide-react";
4903
+ import { jsx as jsx14, jsxs as jsxs5 } from "react/jsx-runtime";
4904
+ var MergeFieldSuggestions = () => {
4905
+ const isActive = useEditorStore((state) => state.mergeFieldSuggestion?.isActive);
4906
+ if (!isActive) return null;
4907
+ return /* @__PURE__ */ jsx14(MergeFieldSuggestionsContent, {});
4908
+ };
4909
+ var MergeFieldSuggestionsContent = () => {
4910
+ const mergeFieldSuggestion = useEditorStore((state) => state.mergeFieldSuggestion);
4911
+ const clearMergeFieldSuggestion = useEditorStore((state) => state.clearMergeFieldSuggestion);
4912
+ const tiptapEditor = useEditorStore((state) => state.tiptapEditor);
4913
+ const mergeFields = useEditorStore((state) => state.mergeFields);
4914
+ const containerRef = useRef3(null);
4915
+ const [searchQuery, setSearchQuery] = useState("");
4916
+ useEffect4(() => {
4917
+ if (!tiptapEditor || !mergeFieldSuggestion) return;
4918
+ const updateQuery = () => {
4919
+ const { from } = tiptapEditor.state.selection;
4920
+ const triggerEnd = mergeFieldSuggestion.triggerPosition + 2;
4921
+ if (from > triggerEnd) {
4922
+ const typed = tiptapEditor.state.doc.textBetween(triggerEnd, from);
4923
+ setSearchQuery(typed);
4924
+ } else {
4925
+ setSearchQuery("");
4926
+ }
4927
+ };
4928
+ updateQuery();
4929
+ tiptapEditor.on("selectionUpdate", updateQuery);
4930
+ tiptapEditor.on("update", updateQuery);
4931
+ return () => {
4932
+ tiptapEditor.off("selectionUpdate", updateQuery);
4933
+ tiptapEditor.off("update", updateQuery);
4934
+ };
4935
+ }, [tiptapEditor, mergeFieldSuggestion]);
4936
+ const filteredFields = useMemo3(() => {
4937
+ if (!searchQuery) return mergeFields;
4938
+ const q = searchQuery.toLowerCase();
4939
+ return mergeFields.filter(
4940
+ (f) => f.label.toLowerCase().includes(q) || f.value.toLowerCase().includes(q)
4941
+ );
4942
+ }, [searchQuery, mergeFields]);
4943
+ const handleSelect = useCallback3((fieldValue) => {
4944
+ if (!tiptapEditor || !mergeFieldSuggestion) return;
4945
+ const { from } = tiptapEditor.state.selection;
4946
+ const triggerPos = mergeFieldSuggestion.triggerPosition;
4947
+ tiptapEditor.chain().focus().deleteRange({ from: triggerPos, to: from }).insertContent(`{{${fieldValue}}}`).run();
4948
+ clearMergeFieldSuggestion();
4949
+ }, [tiptapEditor, mergeFieldSuggestion, clearMergeFieldSuggestion]);
4950
+ const virtualReference = useMemo3(() => ({
4951
+ getBoundingClientRect: () => {
4952
+ if (!mergeFieldSuggestion?.cursorRect) {
4953
+ return { x: 0, y: 0, top: 0, left: 0, bottom: 0, right: 0, width: 0, height: 0, toJSON: () => ({}) };
4954
+ }
4955
+ const { top, left, height } = mergeFieldSuggestion.cursorRect;
4956
+ return {
4957
+ x: left,
4958
+ y: top,
4959
+ top,
4960
+ left,
4961
+ bottom: top + height,
4962
+ right: left,
4963
+ width: 0,
4964
+ height,
4965
+ toJSON: () => ({})
4966
+ };
4967
+ }
4968
+ }), [mergeFieldSuggestion?.cursorRect]);
4969
+ const { floatingStyles, refs, update } = useFloating3({
4970
+ placement: "bottom-start",
4971
+ middleware: [
4972
+ offset3(4),
4973
+ flip2({ padding: 8 }),
4974
+ shift3({ padding: 8 })
4975
+ ]
4976
+ });
4977
+ const floatingRefsRef = useRef3(refs);
4978
+ useEffect4(() => {
4979
+ floatingRefsRef.current = refs;
4980
+ }, [refs]);
4981
+ useEffect4(() => {
4982
+ if (mergeFieldSuggestion?.cursorRect) {
4983
+ floatingRefsRef.current.setPositionReference(virtualReference);
4984
+ update();
4985
+ }
4986
+ }, [mergeFieldSuggestion?.cursorRect, virtualReference, update]);
4987
+ const clearRef = useRef3(clearMergeFieldSuggestion);
4988
+ useEffect4(() => {
4989
+ clearRef.current = clearMergeFieldSuggestion;
4990
+ }, [clearMergeFieldSuggestion]);
4991
+ useEffect4(() => {
4992
+ const handleClickOutside = (e) => {
4993
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
4994
+ clearRef.current();
4995
+ }
4996
+ };
4997
+ const timeoutId = setTimeout(() => {
4998
+ document.addEventListener("mousedown", handleClickOutside);
4999
+ }, 0);
5000
+ return () => {
5001
+ clearTimeout(timeoutId);
5002
+ document.removeEventListener("mousedown", handleClickOutside);
5003
+ };
5004
+ }, []);
5005
+ useEffect4(() => {
5006
+ const handleEscape = (e) => {
5007
+ if (e.key === "Escape") {
5008
+ clearRef.current();
5009
+ }
5010
+ };
5011
+ document.addEventListener("keydown", handleEscape);
5012
+ return () => document.removeEventListener("keydown", handleEscape);
5013
+ }, []);
5014
+ return /* @__PURE__ */ jsx14(
5015
+ "div",
5016
+ {
5017
+ ref: (node) => {
5018
+ containerRef.current = node;
5019
+ refs.setFloating(node);
5020
+ },
5021
+ style: {
5022
+ ...floatingStyles,
5023
+ zIndex: 9999
5024
+ },
5025
+ className: "bg-popover border rounded-md shadow-md overflow-hidden",
5026
+ children: /* @__PURE__ */ jsx14(Command, { className: "w-[240px]", children: /* @__PURE__ */ jsxs5(CommandList, { className: "max-h-[300px]", children: [
5027
+ /* @__PURE__ */ jsx14(CommandEmpty, { children: "No matching fields." }),
5028
+ /* @__PURE__ */ jsx14(CommandGroup, { heading: "Merge fields", children: filteredFields.map(({ label, value }) => /* @__PURE__ */ jsxs5(
5029
+ CommandItem,
5030
+ {
5031
+ value,
5032
+ keywords: [label],
5033
+ className: "flex items-center gap-2 cursor-pointer",
5034
+ onSelect: () => handleSelect(value),
5035
+ onMouseDown: (e) => {
5036
+ e.preventDefault();
5037
+ handleSelect(value);
5038
+ },
5039
+ children: [
5040
+ /* @__PURE__ */ jsx14(BracesIcon, { className: "w-4 h-4" }),
5041
+ label
5042
+ ]
5043
+ },
5044
+ value
5045
+ )) })
5046
+ ] }) })
5047
+ }
5048
+ );
5049
+ };
5050
+
5051
+ // src/core/editor/components/tiptap-overlay.tsx
5052
+ import { useEditor, EditorContent } from "@tiptap/react";
5053
+ import { BubbleMenu } from "@tiptap/react/menus";
5054
+ import { TextSelection as TextSelection8 } from "@tiptap/pm/state";
5055
+ import StarterKit from "@tiptap/starter-kit";
5056
+ import { TextStyle, FontSize, LineHeight } from "@tiptap/extension-text-style";
5057
+ import { Color } from "@tiptap/extension-color";
5058
+ import TextAlign from "@tiptap/extension-text-align";
5059
+ import Underline from "@tiptap/extension-underline";
5060
+
5061
+ // node_modules/@tiptap/core/dist/index.js
5062
+ import { liftTarget } from "@tiptap/pm/transform";
5063
+ import { createParagraphNear as originalCreateParagraphNear } from "@tiptap/pm/commands";
5064
+ import { TextSelection } from "@tiptap/pm/state";
4842
5065
  import { deleteSelection as originalDeleteSelection } from "@tiptap/pm/commands";
4843
5066
  import { exitCode as originalExitCode } from "@tiptap/pm/commands";
4844
5067
  import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
@@ -5691,7 +5914,7 @@ function normalizeKeyName(name) {
5691
5914
  }
5692
5915
  let alt;
5693
5916
  let ctrl;
5694
- let shift4;
5917
+ let shift5;
5695
5918
  let meta;
5696
5919
  for (let i = 0; i < parts.length - 1; i += 1) {
5697
5920
  const mod = parts[i];
@@ -5702,7 +5925,7 @@ function normalizeKeyName(name) {
5702
5925
  } else if (/^(c|ctrl|control)$/i.test(mod)) {
5703
5926
  ctrl = true;
5704
5927
  } else if (/^s(hift)?$/i.test(mod)) {
5705
- shift4 = true;
5928
+ shift5 = true;
5706
5929
  } else if (/^mod$/i.test(mod)) {
5707
5930
  if (isiOS() || isMacOS()) {
5708
5931
  meta = true;
@@ -5722,7 +5945,7 @@ function normalizeKeyName(name) {
5722
5945
  if (meta) {
5723
5946
  result = `Meta-${result}`;
5724
5947
  }
5725
- if (shift4) {
5948
+ if (shift5) {
5726
5949
  result = `Shift-${result}`;
5727
5950
  }
5728
5951
  return result;
@@ -10574,8 +10797,8 @@ var Link = Mark.create({
10574
10797
  var index_default = Link;
10575
10798
 
10576
10799
  // src/core/editor/components/tiptap-overlay.tsx
10577
- import { useFloating as useFloating3, autoUpdate as autoUpdate2, offset as offset3 } from "@floating-ui/react";
10578
- import { useEffect as useEffect6, useRef as useRef4, useMemo as useMemo3, useState as useState2 } from "react";
10800
+ import { useFloating as useFloating4, autoUpdate as autoUpdate2, offset as offset4 } from "@floating-ui/react";
10801
+ import { useEffect as useEffect6, useRef as useRef5, useMemo as useMemo4, useState as useState3 } from "react";
10579
10802
 
10580
10803
  // src/core/editor/extensions/inverse-placeholder.ts
10581
10804
  import { Plugin as Plugin12, PluginKey as PluginKey10 } from "@tiptap/pm/state";
@@ -10785,25 +11008,69 @@ var HeadingParagraph = Node3.create({
10785
11008
  }
10786
11009
  });
10787
11010
 
11011
+ // src/core/editor/extensions/merge-field-decoration.ts
11012
+ import { Plugin as Plugin13, PluginKey as PluginKey11 } from "@tiptap/pm/state";
11013
+ import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "@tiptap/pm/view";
11014
+ var MERGE_FIELD_REGEX = /\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}/g;
11015
+ var MergeFieldDecoration = Extension.create({
11016
+ name: "mergeFieldDecoration",
11017
+ addProseMirrorPlugins() {
11018
+ let cached = null;
11019
+ return [
11020
+ new Plugin13({
11021
+ key: new PluginKey11("mergeFieldDecoration"),
11022
+ props: {
11023
+ decorations: (state) => {
11024
+ const { doc } = state;
11025
+ const docNodeSize = doc.nodeSize;
11026
+ if (cached && cached.docNodeSize === docNodeSize) {
11027
+ return cached.decorations;
11028
+ }
11029
+ const decorations = [];
11030
+ doc.descendants((node, pos) => {
11031
+ if (!node.isText || !node.text) return;
11032
+ MERGE_FIELD_REGEX.lastIndex = 0;
11033
+ let match;
11034
+ while ((match = MERGE_FIELD_REGEX.exec(node.text)) !== null) {
11035
+ const from = pos + match.index;
11036
+ const to = from + match[0].length;
11037
+ decorations.push(
11038
+ Decoration2.inline(from, to, { class: "merge-field-tag" })
11039
+ );
11040
+ }
11041
+ });
11042
+ const decorationSet = DecorationSet2.create(doc, decorations);
11043
+ cached = { docNodeSize, decorations: decorationSet };
11044
+ return decorationSet;
11045
+ }
11046
+ }
11047
+ })
11048
+ ];
11049
+ }
11050
+ });
11051
+
10788
11052
  // src/core/editor/hooks/use-editor-store-refs.ts
10789
- import { useRef as useRef3, useEffect as useEffect4 } from "react";
11053
+ import { useRef as useRef4, useEffect as useEffect5 } from "react";
10790
11054
  function useEditorStoreRefs() {
10791
11055
  const store = useEditorStore();
10792
11056
  const refs = {
10793
- stopTextEditing: useRef3(store.stopTextEditing),
10794
- updateElementContent: useRef3(store.updateElementContent),
10795
- setSlashCommand: useRef3(store.setSlashCommand),
10796
- clearSlashCommand: useRef3(store.clearSlashCommand),
10797
- findAdjacentElement: useRef3(store.findAdjacentElement),
10798
- deleteElement: useRef3(store.deleteElement),
10799
- setFocusIdx: useRef3(store.setFocusIdx),
10800
- requestTextEditingOnElement: useRef3(store.requestTextEditingOnElement),
10801
- clearPendingTextEditRequest: useRef3(store.clearPendingTextEditRequest),
10802
- template: useRef3(store.template),
10803
- slashCommand: useRef3(store.slashCommand),
10804
- pushHistory: useRef3(store.pushHistory)
11057
+ stopTextEditing: useRef4(store.stopTextEditing),
11058
+ updateElementContent: useRef4(store.updateElementContent),
11059
+ setSlashCommand: useRef4(store.setSlashCommand),
11060
+ clearSlashCommand: useRef4(store.clearSlashCommand),
11061
+ findAdjacentElement: useRef4(store.findAdjacentElement),
11062
+ deleteElement: useRef4(store.deleteElement),
11063
+ setFocusIdx: useRef4(store.setFocusIdx),
11064
+ requestTextEditingOnElement: useRef4(store.requestTextEditingOnElement),
11065
+ clearPendingTextEditRequest: useRef4(store.clearPendingTextEditRequest),
11066
+ template: useRef4(store.template),
11067
+ slashCommand: useRef4(store.slashCommand),
11068
+ mergeFieldSuggestion: useRef4(store.mergeFieldSuggestion),
11069
+ setMergeFieldSuggestion: useRef4(store.setMergeFieldSuggestion),
11070
+ clearMergeFieldSuggestion: useRef4(store.clearMergeFieldSuggestion),
11071
+ pushHistory: useRef4(store.pushHistory)
10805
11072
  };
10806
- useEffect4(() => {
11073
+ useEffect5(() => {
10807
11074
  refs.stopTextEditing.current = store.stopTextEditing;
10808
11075
  refs.updateElementContent.current = store.updateElementContent;
10809
11076
  refs.setSlashCommand.current = store.setSlashCommand;
@@ -10815,6 +11082,9 @@ function useEditorStoreRefs() {
10815
11082
  refs.clearPendingTextEditRequest.current = store.clearPendingTextEditRequest;
10816
11083
  refs.template.current = store.template;
10817
11084
  refs.slashCommand.current = store.slashCommand;
11085
+ refs.mergeFieldSuggestion.current = store.mergeFieldSuggestion;
11086
+ refs.setMergeFieldSuggestion.current = store.setMergeFieldSuggestion;
11087
+ refs.clearMergeFieldSuggestion.current = store.clearMergeFieldSuggestion;
10818
11088
  refs.pushHistory.current = store.pushHistory;
10819
11089
  }, [
10820
11090
  store.stopTextEditing,
@@ -10828,6 +11098,9 @@ function useEditorStoreRefs() {
10828
11098
  store.clearPendingTextEditRequest,
10829
11099
  store.template,
10830
11100
  store.slashCommand,
11101
+ store.mergeFieldSuggestion,
11102
+ store.setMergeFieldSuggestion,
11103
+ store.clearMergeFieldSuggestion,
10831
11104
  store.pushHistory
10832
11105
  ]);
10833
11106
  return refs;
@@ -10875,12 +11148,12 @@ function checkElementPosition(template, elementIdx) {
10875
11148
 
10876
11149
  // src/components/ui/tooltip.tsx
10877
11150
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
10878
- import { jsx as jsx14, jsxs as jsxs5 } from "react/jsx-runtime";
11151
+ import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
10879
11152
  function TooltipProvider({
10880
11153
  delayDuration = 0,
10881
11154
  ...props
10882
11155
  }) {
10883
- return /* @__PURE__ */ jsx14(
11156
+ return /* @__PURE__ */ jsx15(
10884
11157
  TooltipPrimitive.Provider,
10885
11158
  {
10886
11159
  "data-slot": "tooltip-provider",
@@ -10892,12 +11165,12 @@ function TooltipProvider({
10892
11165
  function Tooltip({
10893
11166
  ...props
10894
11167
  }) {
10895
- return /* @__PURE__ */ jsx14(TooltipProvider, { children: /* @__PURE__ */ jsx14(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
11168
+ return /* @__PURE__ */ jsx15(TooltipProvider, { children: /* @__PURE__ */ jsx15(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
10896
11169
  }
10897
11170
  function TooltipTrigger({
10898
11171
  ...props
10899
11172
  }) {
10900
- return /* @__PURE__ */ jsx14(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
11173
+ return /* @__PURE__ */ jsx15(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
10901
11174
  }
10902
11175
  function TooltipContent({
10903
11176
  className,
@@ -10905,7 +11178,7 @@ function TooltipContent({
10905
11178
  children,
10906
11179
  ...props
10907
11180
  }) {
10908
- return /* @__PURE__ */ jsx14(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs5(
11181
+ return /* @__PURE__ */ jsx15(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs6(
10909
11182
  TooltipPrimitive.Content,
10910
11183
  {
10911
11184
  "data-slot": "tooltip-content",
@@ -10917,7 +11190,7 @@ function TooltipContent({
10917
11190
  ...props,
10918
11191
  children: [
10919
11192
  children,
10920
- /* @__PURE__ */ jsx14(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
11193
+ /* @__PURE__ */ jsx15(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
10921
11194
  ]
10922
11195
  }
10923
11196
  ) });
@@ -10927,12 +11200,12 @@ function TooltipContent({
10927
11200
  import { BotIcon } from "lucide-react";
10928
11201
 
10929
11202
  // src/core/editor/components/text-link-menu.tsx
10930
- import { useState, useEffect as useEffect5 } from "react";
11203
+ import { useState as useState2, useCallback as useCallback4 } from "react";
10931
11204
 
10932
11205
  // src/components/ui/input.tsx
10933
- import { jsx as jsx15 } from "react/jsx-runtime";
11206
+ import { jsx as jsx16 } from "react/jsx-runtime";
10934
11207
  function Input({ className, type, ...props }) {
10935
- return /* @__PURE__ */ jsx15(
11208
+ return /* @__PURE__ */ jsx16(
10936
11209
  "input",
10937
11210
  {
10938
11211
  type,
@@ -10953,12 +11226,12 @@ import { CheckIcon, CopyIcon, LinkIcon as LinkIcon2, PencilIcon, TrashIcon } fro
10953
11226
 
10954
11227
  // src/components/ui/label.tsx
10955
11228
  import * as LabelPrimitive from "@radix-ui/react-label";
10956
- import { jsx as jsx16 } from "react/jsx-runtime";
11229
+ import { jsx as jsx17 } from "react/jsx-runtime";
10957
11230
  function Label({
10958
11231
  className,
10959
11232
  ...props
10960
11233
  }) {
10961
- return /* @__PURE__ */ jsx16(
11234
+ return /* @__PURE__ */ jsx17(
10962
11235
  LabelPrimitive.Root,
10963
11236
  {
10964
11237
  "data-slot": "label",
@@ -10973,14 +11246,14 @@ function Label({
10973
11246
 
10974
11247
  // src/components/ui/separator.tsx
10975
11248
  import * as SeparatorPrimitive from "@radix-ui/react-separator";
10976
- import { jsx as jsx17 } from "react/jsx-runtime";
11249
+ import { jsx as jsx18 } from "react/jsx-runtime";
10977
11250
  function Separator({
10978
11251
  className,
10979
11252
  orientation = "horizontal",
10980
11253
  decorative = true,
10981
11254
  ...props
10982
11255
  }) {
10983
- return /* @__PURE__ */ jsx17(
11256
+ return /* @__PURE__ */ jsx18(
10984
11257
  SeparatorPrimitive.Root,
10985
11258
  {
10986
11259
  "data-slot": "separator",
@@ -11000,16 +11273,16 @@ var floatButtonVariants = "shadow-none transition-none cursor-pointer rounded-fu
11000
11273
 
11001
11274
  // src/components/ui/popover.tsx
11002
11275
  import * as PopoverPrimitive from "@radix-ui/react-popover";
11003
- import { jsx as jsx18 } from "react/jsx-runtime";
11276
+ import { jsx as jsx19 } from "react/jsx-runtime";
11004
11277
  function Popover({
11005
11278
  ...props
11006
11279
  }) {
11007
- return /* @__PURE__ */ jsx18(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
11280
+ return /* @__PURE__ */ jsx19(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
11008
11281
  }
11009
11282
  function PopoverTrigger({
11010
11283
  ...props
11011
11284
  }) {
11012
- return /* @__PURE__ */ jsx18(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
11285
+ return /* @__PURE__ */ jsx19(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
11013
11286
  }
11014
11287
  function PopoverContent({
11015
11288
  className,
@@ -11017,7 +11290,7 @@ function PopoverContent({
11017
11290
  sideOffset = 4,
11018
11291
  ...props
11019
11292
  }) {
11020
- return /* @__PURE__ */ jsx18(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx18(
11293
+ return /* @__PURE__ */ jsx19(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx19(
11021
11294
  PopoverPrimitive.Content,
11022
11295
  {
11023
11296
  "data-slot": "popover-content",
@@ -11033,21 +11306,22 @@ function PopoverContent({
11033
11306
  }
11034
11307
 
11035
11308
  // src/core/editor/components/text-link-menu.tsx
11036
- import { jsx as jsx19, jsxs as jsxs6 } from "react/jsx-runtime";
11309
+ import { jsx as jsx20, jsxs as jsxs7 } from "react/jsx-runtime";
11037
11310
  var TextLinkMenu = ({ editor }) => {
11038
- const [isOpen, setIsOpen] = useState(false);
11039
- const [inputValue, setInputValue] = useState("");
11040
- const [showCopied, setShowCopied] = useState(false);
11041
- const [linkType, setLinkType] = useState(LINK_TYPES[1]);
11042
- const [isLinkTypeOpen, setIsLinkTypeOpen] = useState(false);
11311
+ const [isOpen, setIsOpen] = useState2(false);
11312
+ const [inputValue, setInputValue] = useState2("");
11313
+ const [showCopied, setShowCopied] = useState2(false);
11314
+ const [linkType, setLinkType] = useState2(LINK_TYPES[1]);
11315
+ const [isLinkTypeOpen, setIsLinkTypeOpen] = useState2(false);
11043
11316
  const currentHref = editor.getAttributes("link").href || "";
11044
11317
  const hasLink = !!currentHref;
11045
- useEffect5(() => {
11046
- if (isOpen) {
11318
+ const handleOpenChange = useCallback4((open) => {
11319
+ setIsOpen(open);
11320
+ if (open) {
11047
11321
  setLinkType(detectLinkType(currentHref));
11048
11322
  setInputValue(stripPrefix(currentHref));
11049
11323
  }
11050
- }, [isOpen, currentHref]);
11324
+ }, [currentHref]);
11051
11325
  const handleInputChange = (e) => {
11052
11326
  setInputValue(e.target.value);
11053
11327
  };
@@ -11084,42 +11358,42 @@ var TextLinkMenu = ({ editor }) => {
11084
11358
  editor.chain().focus().unsetLink().run();
11085
11359
  setInputValue("");
11086
11360
  };
11087
- return /* @__PURE__ */ jsxs6(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
11088
- /* @__PURE__ */ jsxs6(Tooltip, { children: [
11089
- /* @__PURE__ */ jsx19(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(PopoverTrigger, { asChild: true, children: hasLink ? /* @__PURE__ */ jsx19(
11361
+ return /* @__PURE__ */ jsxs7(Popover, { open: isOpen, onOpenChange: handleOpenChange, children: [
11362
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11363
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(PopoverTrigger, { asChild: true, children: hasLink ? /* @__PURE__ */ jsx20(
11090
11364
  Button,
11091
11365
  {
11092
11366
  variant: "ghost",
11093
11367
  size: "icon",
11094
11368
  className: floatButtonVariants,
11095
11369
  onMouseDown: (e) => e.preventDefault(),
11096
- children: /* @__PURE__ */ jsx19(PencilIcon, { className: "size-4" })
11370
+ children: /* @__PURE__ */ jsx20(PencilIcon, { className: "size-4" })
11097
11371
  }
11098
- ) : /* @__PURE__ */ jsxs6(
11372
+ ) : /* @__PURE__ */ jsxs7(
11099
11373
  Button,
11100
11374
  {
11101
11375
  variant: "ghost",
11102
11376
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
11103
11377
  onMouseDown: (e) => e.preventDefault(),
11104
11378
  children: [
11105
- /* @__PURE__ */ jsx19(LinkIcon2, { className: "size-4" }),
11106
- /* @__PURE__ */ jsx19("p", { children: "Add link" })
11379
+ /* @__PURE__ */ jsx20(LinkIcon2, { className: "size-4" }),
11380
+ /* @__PURE__ */ jsx20("p", { children: "Add link" })
11107
11381
  ]
11108
11382
  }
11109
11383
  ) }) }),
11110
- /* @__PURE__ */ jsx19(TooltipContent, { side: "bottom", children: hasLink ? "Edit link" : "Add link" })
11384
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", children: hasLink ? "Edit link" : "Add link" })
11111
11385
  ] }),
11112
- /* @__PURE__ */ jsxs6(
11386
+ /* @__PURE__ */ jsxs7(
11113
11387
  PopoverContent,
11114
11388
  {
11115
11389
  side: "bottom",
11116
11390
  className: "w-[250px] p-3 shadow-lg z-50001",
11117
11391
  "data-editor-toolbar": true,
11118
11392
  children: [
11119
- /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-2", children: [
11120
- /* @__PURE__ */ jsx19(Label, { children: "Enter a link" }),
11121
- /* @__PURE__ */ jsxs6("div", { className: "relative", children: [
11122
- /* @__PURE__ */ jsx19(
11393
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-2", children: [
11394
+ /* @__PURE__ */ jsx20(Label, { children: "Enter a link" }),
11395
+ /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
11396
+ /* @__PURE__ */ jsx20(
11123
11397
  Input,
11124
11398
  {
11125
11399
  type: linkType.inputType,
@@ -11131,12 +11405,12 @@ var TextLinkMenu = ({ editor }) => {
11131
11405
  autoFocus: true
11132
11406
  }
11133
11407
  ),
11134
- /* @__PURE__ */ jsxs6(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
11135
- /* @__PURE__ */ jsxs6(Tooltip, { children: [
11136
- /* @__PURE__ */ jsx19(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(Button, { size: "icon", variant: "ghost", className: "absolute shadow-none rounded-[12px] left-1.5 top-1/2 -translate-y-1/2 h-[34px] w-[34px] cursor-pointer", children: /* @__PURE__ */ jsx19(linkType.icon, {}) }) }) }),
11137
- /* @__PURE__ */ jsx19(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
11408
+ /* @__PURE__ */ jsxs7(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
11409
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11410
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(Button, { size: "icon", variant: "ghost", className: "absolute shadow-none rounded-[12px] left-1.5 top-1/2 -translate-y-1/2 h-[34px] w-[34px] cursor-pointer", children: /* @__PURE__ */ jsx20(linkType.icon, {}) }) }) }),
11411
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
11138
11412
  ] }),
11139
- /* @__PURE__ */ jsx19(
11413
+ /* @__PURE__ */ jsx20(
11140
11414
  PopoverContent,
11141
11415
  {
11142
11416
  side: "bottom",
@@ -11144,7 +11418,7 @@ var TextLinkMenu = ({ editor }) => {
11144
11418
  className: "w-[160px] p-1 z-50001",
11145
11419
  onPointerDownOutside: (e) => e.preventDefault(),
11146
11420
  "data-editor-toolbar": true,
11147
- children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs6(
11421
+ children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs7(
11148
11422
  Button,
11149
11423
  {
11150
11424
  variant: "ghost",
@@ -11155,11 +11429,11 @@ var TextLinkMenu = ({ editor }) => {
11155
11429
  setIsLinkTypeOpen(false);
11156
11430
  },
11157
11431
  children: [
11158
- /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-2", children: [
11159
- /* @__PURE__ */ jsx19(type.icon, { className: "size-4" }),
11432
+ /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-2", children: [
11433
+ /* @__PURE__ */ jsx20(type.icon, { className: "size-4" }),
11160
11434
  type.name
11161
11435
  ] }),
11162
- linkType.name === type.name && /* @__PURE__ */ jsx19(CheckIcon, { className: "size-4" })
11436
+ linkType.name === type.name && /* @__PURE__ */ jsx20(CheckIcon, { className: "size-4" })
11163
11437
  ]
11164
11438
  },
11165
11439
  type.name
@@ -11169,11 +11443,11 @@ var TextLinkMenu = ({ editor }) => {
11169
11443
  ] })
11170
11444
  ] })
11171
11445
  ] }),
11172
- /* @__PURE__ */ jsx19(Separator, { className: "my-2" }),
11173
- /* @__PURE__ */ jsxs6("div", { className: "flex flex-row justify-between items-center", children: [
11174
- /* @__PURE__ */ jsxs6("div", { className: "flex flex-row", children: [
11175
- /* @__PURE__ */ jsxs6(Tooltip, { children: [
11176
- /* @__PURE__ */ jsx19(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(
11446
+ /* @__PURE__ */ jsx20(Separator, { className: "my-2" }),
11447
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-row justify-between items-center", children: [
11448
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-row", children: [
11449
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11450
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(
11177
11451
  Button,
11178
11452
  {
11179
11453
  variant: "ghost",
@@ -11181,13 +11455,13 @@ var TextLinkMenu = ({ editor }) => {
11181
11455
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
11182
11456
  onClick: handleCopy,
11183
11457
  disabled: !hasLink,
11184
- children: showCopied ? /* @__PURE__ */ jsx19(CheckIcon, { className: "text-green-600" }) : /* @__PURE__ */ jsx19(CopyIcon, {})
11458
+ children: showCopied ? /* @__PURE__ */ jsx20(CheckIcon, { className: "text-green-600" }) : /* @__PURE__ */ jsx20(CopyIcon, {})
11185
11459
  }
11186
11460
  ) }),
11187
- /* @__PURE__ */ jsx19(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
11461
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
11188
11462
  ] }),
11189
- /* @__PURE__ */ jsxs6(Tooltip, { children: [
11190
- /* @__PURE__ */ jsx19(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(
11463
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11464
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(
11191
11465
  Button,
11192
11466
  {
11193
11467
  variant: "ghost",
@@ -11195,13 +11469,13 @@ var TextLinkMenu = ({ editor }) => {
11195
11469
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
11196
11470
  onClick: handleRemoveLink,
11197
11471
  disabled: !hasLink,
11198
- children: /* @__PURE__ */ jsx19(TrashIcon, {})
11472
+ children: /* @__PURE__ */ jsx20(TrashIcon, {})
11199
11473
  }
11200
11474
  ) }),
11201
- /* @__PURE__ */ jsx19(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
11475
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
11202
11476
  ] })
11203
11477
  ] }),
11204
- /* @__PURE__ */ jsx19("div", { children: /* @__PURE__ */ jsx19(
11478
+ /* @__PURE__ */ jsx20("div", { children: /* @__PURE__ */ jsx20(
11205
11479
  Button,
11206
11480
  {
11207
11481
  variant: "default",
@@ -11218,16 +11492,16 @@ var TextLinkMenu = ({ editor }) => {
11218
11492
  };
11219
11493
 
11220
11494
  // src/core/editor/components/float-link-preview.tsx
11221
- import { jsx as jsx20, jsxs as jsxs7 } from "react/jsx-runtime";
11495
+ import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
11222
11496
  var FloatLinkPreview = ({ href }) => {
11223
- return /* @__PURE__ */ jsxs7(Tooltip, { children: [
11224
- /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20("div", { className: "max-w-[150px] min-w-[25px] h-[34px] px-4 hover:bg-accent rounded-full flex items-center justify-start", children: /* @__PURE__ */ jsx20("a", { href, target: "_blank", className: "shadow-none transition-none cursor-pointer outline-none text-[16px] text-blue-400 truncate", children: href }) }) }),
11225
- /* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", children: href })
11497
+ return /* @__PURE__ */ jsxs8(Tooltip, { children: [
11498
+ /* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21("div", { className: "max-w-[150px] min-w-[25px] h-[34px] px-4 hover:bg-accent rounded-full flex items-center justify-start", children: /* @__PURE__ */ jsx21("a", { href, target: "_blank", className: "shadow-none transition-none cursor-pointer outline-none text-[16px] text-blue-400 truncate", children: href }) }) }),
11499
+ /* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", children: href })
11226
11500
  ] });
11227
11501
  };
11228
11502
 
11229
11503
  // src/core/editor/components/tiptap-overlay.tsx
11230
- import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
11504
+ import { jsx as jsx22, jsxs as jsxs9 } from "react/jsx-runtime";
11231
11505
  var FontFamily = Extension.create({
11232
11506
  name: "fontFamily",
11233
11507
  addGlobalAttributes() {
@@ -11405,7 +11679,8 @@ var TIPTAP_EXTENSIONS = [
11405
11679
  emptyNodeClass: "is-empty-placeholder",
11406
11680
  paragraphPlaceholder: "Start typing...",
11407
11681
  headingPlaceholder: "Heading"
11408
- })
11682
+ }),
11683
+ MergeFieldDecoration
11409
11684
  ];
11410
11685
  function isNodeEmpty2(node) {
11411
11686
  if (!node) return true;
@@ -11536,14 +11811,14 @@ function handleBackspaceOrDelete(view, event, currentElementIdx, storeRefs) {
11536
11811
  var TiptapOverlay = () => {
11537
11812
  const textEditing = useEditorStore((s) => s.textEditing);
11538
11813
  if (!textEditing) return null;
11539
- return /* @__PURE__ */ jsx21(TiptapOverlayContent, { ...textEditing }, textEditing.idx);
11814
+ return /* @__PURE__ */ jsx22(TiptapOverlayContent, { ...textEditing }, textEditing.idx);
11540
11815
  };
11541
11816
  var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWidth, initialHeight, clickX, clickY, content, styles, cursorPosition }) => {
11542
- const containerRef = useRef4(null);
11817
+ const containerRef = useRef5(null);
11543
11818
  const setTiptapEditor = useEditorStore((s) => s.setTiptapEditor);
11544
11819
  const linkColor = useEditorStore((s) => s.template?.content?.[0]?.data?.value?.linkColor) || "#0000ff";
11545
- const lastSizeLimitToastRef = useRef4(0);
11546
- const hasContentChangedRef = useRef4(false);
11820
+ const lastSizeLimitToastRef = useRef5(0);
11821
+ const hasContentChangedRef = useRef5(false);
11547
11822
  const storeRefs = useEditorStoreRefs();
11548
11823
  useEffect6(() => {
11549
11824
  return () => {
@@ -11571,10 +11846,10 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11571
11846
  }
11572
11847
  };
11573
11848
  }, [getShadowElement]);
11574
- const cleanedContent = useMemo3(() => {
11849
+ const cleanedContent = useMemo4(() => {
11575
11850
  return content.replace(NBSP_P_CONTENT_REGEX, "<p$1></p>").replace(IS_EMPTY_P_CLASS_REGEX, "").replace(IS_EMPTY_HEADING_CLASS_REGEX, "");
11576
11851
  }, [content]);
11577
- const lineHeightRatio = useMemo3(() => {
11852
+ const lineHeightRatio = useMemo4(() => {
11578
11853
  const lineHeightPx = parseFloat(styles.lineHeight);
11579
11854
  const fontSizePx = parseFloat(styles.fontSize);
11580
11855
  if (isNaN(lineHeightPx) || isNaN(fontSizePx) || fontSizePx === 0) {
@@ -11582,7 +11857,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11582
11857
  }
11583
11858
  return lineHeightPx / fontSizePx;
11584
11859
  }, [styles.lineHeight, styles.fontSize]);
11585
- const virtualReference = useMemo3(() => ({
11860
+ const virtualReference = useMemo4(() => ({
11586
11861
  getBoundingClientRect: () => {
11587
11862
  const rect = getReferenceRect();
11588
11863
  if (!rect) {
@@ -11591,10 +11866,10 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11591
11866
  return rect;
11592
11867
  }
11593
11868
  }), [getReferenceRect]);
11594
- const { floatingStyles, refs, update } = useFloating3({
11869
+ const { floatingStyles, refs, update } = useFloating4({
11595
11870
  placement: "bottom-start",
11596
11871
  middleware: [
11597
- offset3(({ rects }) => -rects.reference.height)
11872
+ offset4(({ rects }) => -rects.reference.height)
11598
11873
  // Move up by reference height to overlay exactly
11599
11874
  ]
11600
11875
  });
@@ -11637,17 +11912,36 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11637
11912
  }
11638
11913
  }
11639
11914
  const isSlashCommandActive = storeRefs.slashCommand.current?.isActive;
11640
- if (event.key === "Escape" && isSlashCommandActive) {
11641
- storeRefs.clearSlashCommand.current();
11642
- return true;
11915
+ const isMergeFieldActive = storeRefs.mergeFieldSuggestion.current?.isActive;
11916
+ if (event.key === "Escape") {
11917
+ if (isSlashCommandActive) {
11918
+ storeRefs.clearSlashCommand.current();
11919
+ return true;
11920
+ }
11921
+ if (isMergeFieldActive) {
11922
+ storeRefs.clearMergeFieldSuggestion.current();
11923
+ return true;
11924
+ }
11643
11925
  }
11644
- if (event.key === " " && isSlashCommandActive) {
11645
- storeRefs.clearSlashCommand.current();
11646
- return false;
11926
+ if (event.key === " ") {
11927
+ if (isSlashCommandActive) {
11928
+ storeRefs.clearSlashCommand.current();
11929
+ return false;
11930
+ }
11931
+ if (isMergeFieldActive) {
11932
+ storeRefs.clearMergeFieldSuggestion.current();
11933
+ return false;
11934
+ }
11647
11935
  }
11648
- if ((event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") && isSlashCommandActive) {
11649
- storeRefs.clearSlashCommand.current();
11650
- return false;
11936
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
11937
+ if (isSlashCommandActive) {
11938
+ storeRefs.clearSlashCommand.current();
11939
+ return false;
11940
+ }
11941
+ if (isMergeFieldActive) {
11942
+ storeRefs.clearMergeFieldSuggestion.current();
11943
+ return false;
11944
+ }
11651
11945
  }
11652
11946
  if (event.key === "/") {
11653
11947
  const { from } = view.state.selection;
@@ -11669,6 +11963,33 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11669
11963
  });
11670
11964
  }
11671
11965
  }
11966
+ if (event.key === "{") {
11967
+ const { from } = view.state.selection;
11968
+ const textBefore = view.state.doc.textBetween(Math.max(0, from - 1), from);
11969
+ if (textBefore === "{") {
11970
+ const coords = view.coordsAtPos(from);
11971
+ if (coords && coords.left > 0 && coords.top > 0) {
11972
+ const lineHeight = parseInt(styles.lineHeight) || 20;
11973
+ storeRefs.setMergeFieldSuggestion.current({
11974
+ isActive: true,
11975
+ cursorRect: { top: coords.top, left: coords.left, height: lineHeight },
11976
+ triggerPosition: from - 1
11977
+ // Position of first "{"
11978
+ });
11979
+ }
11980
+ }
11981
+ }
11982
+ if (event.key === "}" && isMergeFieldActive) {
11983
+ storeRefs.clearMergeFieldSuggestion.current();
11984
+ return false;
11985
+ }
11986
+ if (event.key === "Backspace" && isMergeFieldActive) {
11987
+ const { from } = view.state.selection;
11988
+ const triggerPos = storeRefs.mergeFieldSuggestion.current?.triggerPosition ?? 0;
11989
+ if (from <= triggerPos + 2) {
11990
+ storeRefs.clearMergeFieldSuggestion.current();
11991
+ }
11992
+ }
11672
11993
  if (event.key === "Backspace" || event.key === "Delete") {
11673
11994
  const handled = handleBackspaceOrDelete(
11674
11995
  view,
@@ -11735,7 +12056,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11735
12056
  storeRefs.updateElementContent.current(`${idx}.data.value.content`, html);
11736
12057
  }
11737
12058
  });
11738
- const [currentLinkHref, setCurrentLinkHref] = useState2("");
12059
+ const [currentLinkHref, setCurrentLinkHref] = useState3("");
11739
12060
  useEffect6(() => {
11740
12061
  if (!editor) return;
11741
12062
  setTiptapEditor(editor);
@@ -11802,7 +12123,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11802
12123
  document.removeEventListener("mousedown", handleClickOutside);
11803
12124
  };
11804
12125
  }, []);
11805
- return /* @__PURE__ */ jsxs8(
12126
+ return /* @__PURE__ */ jsxs9(
11806
12127
  "div",
11807
12128
  {
11808
12129
  ref: (node) => {
@@ -11835,7 +12156,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11835
12156
  boxSizing: "border-box"
11836
12157
  },
11837
12158
  children: [
11838
- /* @__PURE__ */ jsx21("style", { children: `
12159
+ /* @__PURE__ */ jsx22("style", { children: `
11839
12160
  .tiptap-overlay {
11840
12161
  margin: 0;
11841
12162
  padding: 0;
@@ -11901,6 +12222,16 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11901
12222
  transform: translateY(-50%);
11902
12223
  text-align: inherit;
11903
12224
  }
12225
+ .tiptap-overlay .ProseMirror .merge-field-tag {
12226
+ background-color: var(--background);
12227
+ border-radius: 4px;
12228
+ padding: 0px;
12229
+ border: 1px solid var(--border);
12230
+ color: #000000;
12231
+ }
12232
+ .tiptap-overlay .ProseMirror .merge-field-tag:hover {
12233
+ cursor: pointer;
12234
+ }
11904
12235
  .tiptap-overlay .ProseMirror a {
11905
12236
  color: ${linkColor};
11906
12237
  text-decoration: none;
@@ -11910,36 +12241,36 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11910
12241
  text-decoration: underline;
11911
12242
  }
11912
12243
  ` }),
11913
- /* @__PURE__ */ jsx21(
12244
+ /* @__PURE__ */ jsx22(
11914
12245
  EditorContent,
11915
12246
  {
11916
12247
  editor,
11917
12248
  className: "tiptap-overlay"
11918
12249
  }
11919
12250
  ),
11920
- editor && /* @__PURE__ */ jsx21(
12251
+ editor && /* @__PURE__ */ jsx22(
11921
12252
  BubbleMenu,
11922
12253
  {
11923
12254
  editor,
11924
12255
  options: { placement: "top", offset: 8, flip: true },
11925
12256
  updateDelay: 0,
11926
- children: /* @__PURE__ */ jsxs8("div", { className: "bg-white flex items-center justify-center border h-[36px] w-fit shadow-md rounded-full text-[16px]", children: [
11927
- /* @__PURE__ */ jsxs8(Tooltip, { children: [
11928
- /* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(
12257
+ children: /* @__PURE__ */ jsxs9("div", { className: "bg-white flex items-center justify-center border h-[36px] w-fit shadow-md rounded-full text-[16px]", children: [
12258
+ /* @__PURE__ */ jsxs9(Tooltip, { children: [
12259
+ /* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
11929
12260
  Button,
11930
12261
  {
11931
12262
  variant: "ghost",
11932
12263
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
11933
12264
  children: [
11934
- /* @__PURE__ */ jsx21(BotIcon, { className: "size-4" }),
11935
- /* @__PURE__ */ jsx21("p", { children: "Magic Write" })
12265
+ /* @__PURE__ */ jsx22(BotIcon, { className: "size-4" }),
12266
+ /* @__PURE__ */ jsx22("p", { children: "Magic Write" })
11936
12267
  ]
11937
12268
  }
11938
12269
  ) }),
11939
- /* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", children: "Ask Maillow" })
12270
+ /* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", children: "Ask Maillow" })
11940
12271
  ] }),
11941
- currentLinkHref && /* @__PURE__ */ jsx21(FloatLinkPreview, { href: currentLinkHref }),
11942
- /* @__PURE__ */ jsx21(TextLinkMenu, { editor })
12272
+ currentLinkHref && /* @__PURE__ */ jsx22(FloatLinkPreview, { href: currentLinkHref }),
12273
+ /* @__PURE__ */ jsx22(TextLinkMenu, { editor })
11943
12274
  ] })
11944
12275
  }
11945
12276
  )
@@ -11949,12 +12280,12 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11949
12280
  };
11950
12281
 
11951
12282
  // src/core/editor/components/element-float.tsx
11952
- import { useEffect as useEffect12, useMemo as useMemo11 } from "react";
11953
- import { useFloating as useFloating4, offset as offset4, shift as shift3, flip as flip2, autoUpdate as autoUpdate3 } from "@floating-ui/react";
12283
+ import { useEffect as useEffect8, useMemo as useMemo12 } from "react";
12284
+ import { useFloating as useFloating5, offset as offset5, shift as shift4, flip as flip3, autoUpdate as autoUpdate3 } from "@floating-ui/react";
11954
12285
 
11955
12286
  // src/core/editor/components/float-ui/actions/delete-button.tsx
11956
12287
  import { TrashIcon as TrashIcon2 } from "lucide-react";
11957
- import { jsx as jsx22, jsxs as jsxs9 } from "react/jsx-runtime";
12288
+ import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
11958
12289
  var DeleteButton = () => {
11959
12290
  const { focusIdx, deleteElement } = useEditorStore();
11960
12291
  const handleDelete = () => {
@@ -11962,23 +12293,23 @@ var DeleteButton = () => {
11962
12293
  deleteElement(focusIdx);
11963
12294
  }
11964
12295
  };
11965
- return /* @__PURE__ */ jsxs9(Tooltip, { children: [
11966
- /* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
12296
+ return /* @__PURE__ */ jsxs10(Tooltip, { children: [
12297
+ /* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
11967
12298
  Button,
11968
12299
  {
11969
12300
  variant: "ghost",
11970
12301
  className: floatButtonVariants,
11971
12302
  onClick: handleDelete,
11972
- children: /* @__PURE__ */ jsx22(TrashIcon2, { className: "size-4" })
12303
+ children: /* @__PURE__ */ jsx23(TrashIcon2, { className: "size-4" })
11973
12304
  }
11974
12305
  ) }),
11975
- /* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", children: "Delete" })
12306
+ /* @__PURE__ */ jsx23(TooltipContent, { side: "bottom", children: "Delete" })
11976
12307
  ] });
11977
12308
  };
11978
12309
 
11979
12310
  // src/core/editor/components/float-ui/actions/dulicate-button.tsx
11980
12311
  import { CopyIcon as CopyIcon2 } from "lucide-react";
11981
- import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
12312
+ import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
11982
12313
  var DuplicateButton = () => {
11983
12314
  const { focusIdx, duplicateElement } = useEditorStore();
11984
12315
  const isAtSizeLimit = useEditorStore((state) => state.isAtSizeLimit);
@@ -11987,42 +12318,42 @@ var DuplicateButton = () => {
11987
12318
  duplicateElement(focusIdx);
11988
12319
  }
11989
12320
  };
11990
- return /* @__PURE__ */ jsxs10(Tooltip, { children: [
11991
- /* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
12321
+ return /* @__PURE__ */ jsxs11(Tooltip, { children: [
12322
+ /* @__PURE__ */ jsx24(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx24(
11992
12323
  Button,
11993
12324
  {
11994
12325
  variant: "ghost",
11995
12326
  className: floatButtonVariants,
11996
12327
  onClick: handleDuplicate,
11997
12328
  disabled: isAtSizeLimit,
11998
- children: /* @__PURE__ */ jsx23(CopyIcon2, { className: "size-4" })
12329
+ children: /* @__PURE__ */ jsx24(CopyIcon2, { className: "size-4" })
11999
12330
  }
12000
12331
  ) }),
12001
- /* @__PURE__ */ jsx23(TooltipContent, { side: "bottom", children: "Duplicate" })
12332
+ /* @__PURE__ */ jsx24(TooltipContent, { side: "bottom", children: "Duplicate" })
12002
12333
  ] });
12003
12334
  };
12004
12335
 
12005
12336
  // src/core/editor/components/href-menu.tsx
12006
- import { useState as useState3, useEffect as useEffect7, useCallback as useCallback4, useMemo as useMemo5 } from "react";
12337
+ import { useState as useState4, useCallback as useCallback6, useMemo as useMemo6 } from "react";
12007
12338
 
12008
12339
  // src/components/ui/dropdown-menu.tsx
12009
12340
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
12010
12341
  import { CheckIcon as CheckIcon2, ChevronRightIcon, CircleIcon } from "lucide-react";
12011
- import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
12342
+ import { jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
12012
12343
  function DropdownMenu({
12013
12344
  ...props
12014
12345
  }) {
12015
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
12346
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
12016
12347
  }
12017
12348
  function DropdownMenuPortal({
12018
12349
  ...props
12019
12350
  }) {
12020
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
12351
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
12021
12352
  }
12022
12353
  function DropdownMenuTrigger({
12023
12354
  ...props
12024
12355
  }) {
12025
- return /* @__PURE__ */ jsx24(
12356
+ return /* @__PURE__ */ jsx25(
12026
12357
  DropdownMenuPrimitive.Trigger,
12027
12358
  {
12028
12359
  "data-slot": "dropdown-menu-trigger",
@@ -12035,7 +12366,7 @@ function DropdownMenuContent({
12035
12366
  sideOffset = 4,
12036
12367
  ...props
12037
12368
  }) {
12038
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx24(
12369
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx25(
12039
12370
  DropdownMenuPrimitive.Content,
12040
12371
  {
12041
12372
  "data-slot": "dropdown-menu-content",
@@ -12054,7 +12385,7 @@ function DropdownMenuItem({
12054
12385
  variant = "default",
12055
12386
  ...props
12056
12387
  }) {
12057
- return /* @__PURE__ */ jsx24(
12388
+ return /* @__PURE__ */ jsx25(
12058
12389
  DropdownMenuPrimitive.Item,
12059
12390
  {
12060
12391
  "data-slot": "dropdown-menu-item",
@@ -12072,7 +12403,7 @@ function DropdownMenuSeparator({
12072
12403
  className,
12073
12404
  ...props
12074
12405
  }) {
12075
- return /* @__PURE__ */ jsx24(
12406
+ return /* @__PURE__ */ jsx25(
12076
12407
  DropdownMenuPrimitive.Separator,
12077
12408
  {
12078
12409
  "data-slot": "dropdown-menu-separator",
@@ -12084,7 +12415,7 @@ function DropdownMenuSeparator({
12084
12415
  function DropdownMenuSub({
12085
12416
  ...props
12086
12417
  }) {
12087
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
12418
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
12088
12419
  }
12089
12420
  function DropdownMenuSubTrigger({
12090
12421
  className,
@@ -12092,7 +12423,7 @@ function DropdownMenuSubTrigger({
12092
12423
  children,
12093
12424
  ...props
12094
12425
  }) {
12095
- return /* @__PURE__ */ jsxs11(
12426
+ return /* @__PURE__ */ jsxs12(
12096
12427
  DropdownMenuPrimitive.SubTrigger,
12097
12428
  {
12098
12429
  "data-slot": "dropdown-menu-sub-trigger",
@@ -12104,7 +12435,7 @@ function DropdownMenuSubTrigger({
12104
12435
  ...props,
12105
12436
  children: [
12106
12437
  children,
12107
- /* @__PURE__ */ jsx24(ChevronRightIcon, { className: "ml-auto size-4" })
12438
+ /* @__PURE__ */ jsx25(ChevronRightIcon, { className: "ml-auto size-4" })
12108
12439
  ]
12109
12440
  }
12110
12441
  );
@@ -12113,7 +12444,7 @@ function DropdownMenuSubContent({
12113
12444
  className,
12114
12445
  ...props
12115
12446
  }) {
12116
- return /* @__PURE__ */ jsx24(
12447
+ return /* @__PURE__ */ jsx25(
12117
12448
  DropdownMenuPrimitive.SubContent,
12118
12449
  {
12119
12450
  "data-slot": "dropdown-menu-sub-content",
@@ -12130,11 +12461,11 @@ function DropdownMenuSubContent({
12130
12461
  import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon3, LinkIcon as LinkIcon3, PencilIcon as PencilIcon2, TrashIcon as TrashIcon3 } from "lucide-react";
12131
12462
 
12132
12463
  // src/core/editor/hooks/use-href.ts
12133
- import { useMemo as useMemo4, useCallback as useCallback3 } from "react";
12464
+ import { useMemo as useMemo5, useCallback as useCallback5 } from "react";
12134
12465
  import { get as lodashGet2 } from "lodash";
12135
12466
  var useHref = () => {
12136
12467
  const { focusIdx, updateElement, template } = useEditorStore();
12137
- const { element, href } = useMemo4(() => {
12468
+ const { element, href } = useMemo5(() => {
12138
12469
  if (!focusIdx || !template) {
12139
12470
  return { element: null, href: "" };
12140
12471
  }
@@ -12145,19 +12476,19 @@ var useHref = () => {
12145
12476
  href: el?.attributes?.href || ""
12146
12477
  };
12147
12478
  }, [focusIdx, template]);
12148
- const setHref = useCallback3((url) => {
12479
+ const setHref = useCallback5((url) => {
12149
12480
  if (!focusIdx || !element) return;
12150
12481
  updateElement(focusIdx, {
12151
12482
  attributes: { ...element.attributes, href: url }
12152
12483
  });
12153
12484
  }, [focusIdx, element, updateElement]);
12154
- const clearHref = useCallback3(() => {
12485
+ const clearHref = useCallback5(() => {
12155
12486
  if (!focusIdx || !element) return;
12156
12487
  updateElement(focusIdx, {
12157
12488
  attributes: { ...element.attributes, href: "" }
12158
12489
  });
12159
12490
  }, [focusIdx, element, updateElement]);
12160
- const copyHref = useCallback3(async () => {
12491
+ const copyHref = useCallback5(async () => {
12161
12492
  if (href) {
12162
12493
  try {
12163
12494
  await navigator.clipboard.writeText(href);
@@ -12177,18 +12508,18 @@ var useHref = () => {
12177
12508
  };
12178
12509
 
12179
12510
  // src/core/editor/components/href-menu.tsx
12180
- import { jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
12511
+ import { jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
12181
12512
  var HrefMenu = () => {
12182
12513
  const { href, setHref, clearHref, copyHref, hasHref } = useHref();
12183
12514
  const userData = useEditorStore((s) => s.userData);
12184
- const [isOpen, setIsOpen] = useState3(false);
12185
- const [inputValue, setInputValue] = useState3("");
12186
- const [showCopied, setShowCopied] = useState3(false);
12187
- const [linkType, setLinkType] = useState3(LINK_TYPES[1]);
12188
- const [isLinkTypeOpen, setIsLinkTypeOpen] = useState3(false);
12189
- const [isPresetOpen, setIsPresetOpen] = useState3(false);
12515
+ const [isOpen, setIsOpen] = useState4(false);
12516
+ const [inputValue, setInputValue] = useState4("");
12517
+ const [showCopied, setShowCopied] = useState4(false);
12518
+ const [linkType, setLinkType] = useState4(LINK_TYPES[1]);
12519
+ const [isLinkTypeOpen, setIsLinkTypeOpen] = useState4(false);
12520
+ const [isPresetOpen, setIsPresetOpen] = useState4(false);
12190
12521
  console.log("userData", userData);
12191
- const availablePresets = useMemo5(() => {
12522
+ const availablePresets = useMemo6(() => {
12192
12523
  const presetDefs = LINK_PRESETS[linkType.name] ?? [];
12193
12524
  if (!userData) return [];
12194
12525
  const all = presetDefs.filter((p) => userData[p.key]).map((p) => ({ ...p, value: String(userData[p.key]) }));
@@ -12196,17 +12527,18 @@ var HrefMenu = () => {
12196
12527
  const query = inputValue.toLowerCase();
12197
12528
  return all.filter((p) => p.value.toLowerCase().includes(query));
12198
12529
  }, [linkType.name, userData, inputValue]);
12199
- const handlePresetSelect = useCallback4((value) => {
12530
+ const handlePresetSelect = useCallback6((value) => {
12200
12531
  setInputValue(value);
12201
12532
  setIsPresetOpen(false);
12202
12533
  }, []);
12203
- useEffect7(() => {
12204
- if (isOpen) {
12534
+ const handleOpenChange = useCallback6((open) => {
12535
+ setIsOpen(open);
12536
+ if (open) {
12205
12537
  setLinkType(detectLinkType(href));
12206
12538
  setInputValue(stripPrefix(href));
12207
12539
  setIsPresetOpen(true);
12208
12540
  }
12209
- }, [isOpen, href]);
12541
+ }, [href]);
12210
12542
  const handleInputChange = (e) => {
12211
12543
  setInputValue(e.target.value);
12212
12544
  setIsPresetOpen(true);
@@ -12251,35 +12583,35 @@ var HrefMenu = () => {
12251
12583
  setHref(buildHref(inputValue));
12252
12584
  setIsOpen(false);
12253
12585
  };
12254
- return /* @__PURE__ */ jsxs12(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
12255
- /* @__PURE__ */ jsxs12(Tooltip, { children: [
12256
- /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx25(
12586
+ return /* @__PURE__ */ jsxs13(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [
12587
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12588
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx26(
12257
12589
  Button,
12258
12590
  {
12259
12591
  variant: "ghost",
12260
12592
  size: "icon",
12261
12593
  className: floatButtonVariants,
12262
- children: /* @__PURE__ */ jsx25(PencilIcon2, { className: "size-4" })
12594
+ children: /* @__PURE__ */ jsx26(PencilIcon2, { className: "size-4" })
12263
12595
  }
12264
- ) : /* @__PURE__ */ jsxs12(
12596
+ ) : /* @__PURE__ */ jsxs13(
12265
12597
  Button,
12266
12598
  {
12267
12599
  variant: "ghost",
12268
12600
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
12269
12601
  children: [
12270
- /* @__PURE__ */ jsx25(LinkIcon3, { className: "size-4" }),
12271
- /* @__PURE__ */ jsx25("p", { children: "Add link" })
12602
+ /* @__PURE__ */ jsx26(LinkIcon3, { className: "size-4" }),
12603
+ /* @__PURE__ */ jsx26("p", { children: "Add link" })
12272
12604
  ]
12273
12605
  }
12274
12606
  ) }) }),
12275
- /* @__PURE__ */ jsx25(TooltipContent, { side: "bottom", children: hasHref ? `Edit link` : "Add link" })
12607
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", children: hasHref ? `Edit link` : "Add link" })
12276
12608
  ] }),
12277
- /* @__PURE__ */ jsxs12(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
12278
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-2", children: [
12279
- /* @__PURE__ */ jsx25(Label, { children: "Enter a link" }),
12280
- /* @__PURE__ */ jsxs12(Popover, { open: isPresetOpen && availablePresets.length > 0, onOpenChange: setIsPresetOpen, children: [
12281
- /* @__PURE__ */ jsx25(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
12282
- /* @__PURE__ */ jsx25(
12609
+ /* @__PURE__ */ jsxs13(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
12610
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2", children: [
12611
+ /* @__PURE__ */ jsx26(Label, { children: "Enter a link" }),
12612
+ /* @__PURE__ */ jsxs13(Popover, { open: isPresetOpen && availablePresets.length > 0, onOpenChange: setIsPresetOpen, children: [
12613
+ /* @__PURE__ */ jsx26(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
12614
+ /* @__PURE__ */ jsx26(
12283
12615
  Input,
12284
12616
  {
12285
12617
  type: linkType.inputType,
@@ -12293,19 +12625,19 @@ var HrefMenu = () => {
12293
12625
  autoFocus: true
12294
12626
  }
12295
12627
  ),
12296
- /* @__PURE__ */ jsxs12(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
12297
- /* @__PURE__ */ jsxs12(Tooltip, { children: [
12298
- /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(Button, { size: "icon", variant: "ghost", className: "absolute shadow-none rounded-[12px] left-1.5 top-1/2 -translate-y-1/2 h-[34px] w-[34px] cursor-pointer", children: /* @__PURE__ */ jsx25(linkType.icon, {}) }) }) }),
12299
- /* @__PURE__ */ jsx25(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
12628
+ /* @__PURE__ */ jsxs13(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
12629
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12630
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(Button, { size: "icon", variant: "ghost", className: "absolute shadow-none rounded-[12px] left-1.5 top-1/2 -translate-y-1/2 h-[34px] w-[34px] cursor-pointer", children: /* @__PURE__ */ jsx26(linkType.icon, {}) }) }) }),
12631
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
12300
12632
  ] }),
12301
- /* @__PURE__ */ jsx25(
12633
+ /* @__PURE__ */ jsx26(
12302
12634
  PopoverContent,
12303
12635
  {
12304
12636
  side: "bottom",
12305
12637
  align: "start",
12306
12638
  className: "w-[160px] p-1 z-50001",
12307
12639
  onPointerDownOutside: (e) => e.preventDefault(),
12308
- children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs12(
12640
+ children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs13(
12309
12641
  Button,
12310
12642
  {
12311
12643
  variant: "ghost",
@@ -12316,11 +12648,11 @@ var HrefMenu = () => {
12316
12648
  setIsLinkTypeOpen(false);
12317
12649
  },
12318
12650
  children: [
12319
- /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-2", children: [
12320
- /* @__PURE__ */ jsx25(type.icon, { className: "size-4" }),
12651
+ /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-2", children: [
12652
+ /* @__PURE__ */ jsx26(type.icon, { className: "size-4" }),
12321
12653
  type.name
12322
12654
  ] }),
12323
- linkType.name === type.name && /* @__PURE__ */ jsx25(CheckIcon3, { className: "size-4" })
12655
+ linkType.name === type.name && /* @__PURE__ */ jsx26(CheckIcon3, { className: "size-4" })
12324
12656
  ]
12325
12657
  },
12326
12658
  type.name
@@ -12329,14 +12661,14 @@ var HrefMenu = () => {
12329
12661
  )
12330
12662
  ] })
12331
12663
  ] }) }),
12332
- /* @__PURE__ */ jsx25(
12664
+ /* @__PURE__ */ jsx26(
12333
12665
  PopoverContent,
12334
12666
  {
12335
12667
  side: "bottom",
12336
12668
  align: "start",
12337
12669
  className: "w-[var(--radix-popover-trigger-width)] p-0 overflow-hidden z-50001",
12338
12670
  onOpenAutoFocus: (e) => e.preventDefault(),
12339
- children: /* @__PURE__ */ jsx25("div", { className: "flex flex-col max-h-[200px] overflow-y-auto", children: availablePresets.map((preset) => /* @__PURE__ */ jsxs12(
12671
+ children: /* @__PURE__ */ jsx26("div", { className: "flex flex-col max-h-[200px] overflow-y-auto", children: availablePresets.map((preset) => /* @__PURE__ */ jsxs13(
12340
12672
  "button",
12341
12673
  {
12342
12674
  className: `flex items-center justify-between px-3 py-2 text-sm hover:bg-accent cursor-pointer ${inputValue === preset.value ? "bg-accent font-medium" : ""}`,
@@ -12345,11 +12677,11 @@ var HrefMenu = () => {
12345
12677
  handlePresetSelect(preset.value);
12346
12678
  },
12347
12679
  children: [
12348
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-start gap-0.5", children: [
12349
- /* @__PURE__ */ jsx25("span", { className: "text-xs text-muted-foreground", children: preset.label }),
12350
- /* @__PURE__ */ jsx25("span", { className: "text-sm", children: preset.value })
12680
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-start gap-0.5", children: [
12681
+ /* @__PURE__ */ jsx26("span", { className: "text-xs text-muted-foreground", children: preset.label }),
12682
+ /* @__PURE__ */ jsx26("span", { className: "text-sm", children: preset.value })
12351
12683
  ] }),
12352
- inputValue === preset.value && /* @__PURE__ */ jsx25(CheckIcon3, { className: "w-4 h-4 shrink-0" })
12684
+ inputValue === preset.value && /* @__PURE__ */ jsx26(CheckIcon3, { className: "w-4 h-4 shrink-0" })
12353
12685
  ]
12354
12686
  },
12355
12687
  preset.key
@@ -12358,11 +12690,11 @@ var HrefMenu = () => {
12358
12690
  )
12359
12691
  ] })
12360
12692
  ] }),
12361
- /* @__PURE__ */ jsx25(Separator, { className: "my-2" }),
12362
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-row justify-between items-center", children: [
12363
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-row", children: [
12364
- /* @__PURE__ */ jsxs12(Tooltip, { children: [
12365
- /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(
12693
+ /* @__PURE__ */ jsx26(Separator, { className: "my-2" }),
12694
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-row justify-between items-center", children: [
12695
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-row", children: [
12696
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12697
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
12366
12698
  Button,
12367
12699
  {
12368
12700
  variant: "ghost",
@@ -12370,13 +12702,13 @@ var HrefMenu = () => {
12370
12702
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12371
12703
  onClick: handleCopy,
12372
12704
  disabled: !hasHref,
12373
- children: showCopied ? /* @__PURE__ */ jsx25(CheckIcon3, { className: "text-green-600" }) : /* @__PURE__ */ jsx25(CopyIcon3, {})
12705
+ children: showCopied ? /* @__PURE__ */ jsx26(CheckIcon3, { className: "text-green-600" }) : /* @__PURE__ */ jsx26(CopyIcon3, {})
12374
12706
  }
12375
12707
  ) }),
12376
- /* @__PURE__ */ jsx25(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
12708
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
12377
12709
  ] }),
12378
- /* @__PURE__ */ jsxs12(Tooltip, { children: [
12379
- /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(
12710
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12711
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
12380
12712
  Button,
12381
12713
  {
12382
12714
  variant: "ghost",
@@ -12384,13 +12716,13 @@ var HrefMenu = () => {
12384
12716
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12385
12717
  onClick: handleClear,
12386
12718
  disabled: !href,
12387
- children: /* @__PURE__ */ jsx25(TrashIcon3, {})
12719
+ children: /* @__PURE__ */ jsx26(TrashIcon3, {})
12388
12720
  }
12389
12721
  ) }),
12390
- /* @__PURE__ */ jsx25(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
12722
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
12391
12723
  ] })
12392
12724
  ] }),
12393
- /* @__PURE__ */ jsx25("div", { children: /* @__PURE__ */ jsx25(
12725
+ /* @__PURE__ */ jsx26("div", { children: /* @__PURE__ */ jsx26(
12394
12726
  Button,
12395
12727
  {
12396
12728
  variant: "default",
@@ -12405,14 +12737,14 @@ var HrefMenu = () => {
12405
12737
  };
12406
12738
 
12407
12739
  // src/core/editor/components/element-gear/button/float.tsx
12408
- import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
12740
+ import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
12409
12741
  var ButtonFloat = () => {
12410
12742
  const { href, hasHref } = useHref();
12411
- return /* @__PURE__ */ jsxs13(Fragment6, { children: [
12412
- hasHref && /* @__PURE__ */ jsx26(FloatLinkPreview, { href }),
12413
- /* @__PURE__ */ jsx26(HrefMenu, {}),
12414
- /* @__PURE__ */ jsx26(DuplicateButton, {}),
12415
- /* @__PURE__ */ jsx26(DeleteButton, {})
12743
+ return /* @__PURE__ */ jsxs14(Fragment6, { children: [
12744
+ hasHref && /* @__PURE__ */ jsx27(FloatLinkPreview, { href }),
12745
+ /* @__PURE__ */ jsx27(HrefMenu, {}),
12746
+ /* @__PURE__ */ jsx27(DuplicateButton, {}),
12747
+ /* @__PURE__ */ jsx27(DeleteButton, {})
12416
12748
  ] });
12417
12749
  };
12418
12750
 
@@ -12420,11 +12752,11 @@ var ButtonFloat = () => {
12420
12752
  import { ChevronsLeftRightIcon, ChevronsRightLeftIcon, MoreHorizontalIcon } from "lucide-react";
12421
12753
 
12422
12754
  // src/core/editor/hooks/use-full-width-toggle.ts
12423
- import { useCallback as useCallback5, useMemo as useMemo6 } from "react";
12755
+ import { useCallback as useCallback7, useMemo as useMemo7 } from "react";
12424
12756
  import { get as lodashGet3 } from "lodash";
12425
12757
  function useFullWidthToggle() {
12426
12758
  const { focusIdx, template, updateElement } = useEditorStore();
12427
- const { element, isFullWidth } = useMemo6(() => {
12759
+ const { element, isFullWidth } = useMemo7(() => {
12428
12760
  if (!focusIdx || !template) return { element: null, isFullWidth: false };
12429
12761
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
12430
12762
  const el = lodashGet3(template, path);
@@ -12433,7 +12765,7 @@ function useFullWidthToggle() {
12433
12765
  isFullWidth: el?.attributes?.["full-width"] === "full-width"
12434
12766
  };
12435
12767
  }, [focusIdx, template]);
12436
- const handleToggleFullWidth = useCallback5(() => {
12768
+ const handleToggleFullWidth = useCallback7(() => {
12437
12769
  if (!focusIdx || !element) return;
12438
12770
  const newAttributes = { ...element.attributes };
12439
12771
  if (isFullWidth) {
@@ -12447,20 +12779,20 @@ function useFullWidthToggle() {
12447
12779
  }
12448
12780
 
12449
12781
  // src/core/editor/components/element-gear/section/float.tsx
12450
- import { Fragment as Fragment7, jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
12782
+ import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
12451
12783
  var SectionFloat = () => {
12452
12784
  const { isFullWidth, handleToggleFullWidth } = useFullWidthToggle();
12453
- return /* @__PURE__ */ jsxs14(Fragment7, { children: [
12454
- /* @__PURE__ */ jsx27(DuplicateButton, {}),
12455
- /* @__PURE__ */ jsx27(DeleteButton, {}),
12456
- /* @__PURE__ */ jsxs14(DropdownMenu, { children: [
12457
- /* @__PURE__ */ jsxs14(Tooltip, { children: [
12458
- /* @__PURE__ */ jsx27(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx27(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx27(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx27(MoreHorizontalIcon, { className: "w-4 h-4" }) }) }) }),
12459
- /* @__PURE__ */ jsx27(TooltipContent, { side: "bottom", children: "More" })
12785
+ return /* @__PURE__ */ jsxs15(Fragment7, { children: [
12786
+ /* @__PURE__ */ jsx28(DuplicateButton, {}),
12787
+ /* @__PURE__ */ jsx28(DeleteButton, {}),
12788
+ /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
12789
+ /* @__PURE__ */ jsxs15(Tooltip, { children: [
12790
+ /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx28(MoreHorizontalIcon, { className: "w-4 h-4" }) }) }) }),
12791
+ /* @__PURE__ */ jsx28(TooltipContent, { side: "bottom", children: "More" })
12460
12792
  ] }),
12461
- /* @__PURE__ */ jsx27(DropdownMenuContent, { side: "bottom", className: "w-[200px]", children: /* @__PURE__ */ jsxs14(DropdownMenuItem, { onClick: handleToggleFullWidth, children: [
12462
- isFullWidth ? /* @__PURE__ */ jsx27(ChevronsRightLeftIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx27(ChevronsLeftRightIcon, { className: "w-4 h-4" }),
12463
- /* @__PURE__ */ jsx27("p", { children: isFullWidth ? "Reset to original width" : "Expand to full width" })
12793
+ /* @__PURE__ */ jsx28(DropdownMenuContent, { side: "bottom", className: "w-[200px]", children: /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: handleToggleFullWidth, children: [
12794
+ isFullWidth ? /* @__PURE__ */ jsx28(ChevronsRightLeftIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx28(ChevronsLeftRightIcon, { className: "w-4 h-4" }),
12795
+ /* @__PURE__ */ jsx28("p", { children: isFullWidth ? "Reset to original width" : "Expand to full width" })
12464
12796
  ] }) })
12465
12797
  ] })
12466
12798
  ] });
@@ -12470,11 +12802,11 @@ var SectionFloat = () => {
12470
12802
  import { CheckIcon as CheckIcon4, ChevronsLeftRightIcon as ChevronsLeftRightIcon2, ChevronsRightLeftIcon as ChevronsRightLeftIcon2, Layers2Icon, MoreHorizontalIcon as MoreHorizontalIcon2 } from "lucide-react";
12471
12803
 
12472
12804
  // src/core/editor/hooks/use-no-wrap.ts
12473
- import { useCallback as useCallback6, useMemo as useMemo7 } from "react";
12805
+ import { useCallback as useCallback8, useMemo as useMemo8 } from "react";
12474
12806
  import { get as lodashGet4 } from "lodash";
12475
12807
  function useNoWrap() {
12476
12808
  const { focusIdx, template, updateElement } = useEditorStore();
12477
- const { element, noWrap } = useMemo7(() => {
12809
+ const { element, noWrap } = useMemo8(() => {
12478
12810
  if (!focusIdx || !template) return { element: null, noWrap: false };
12479
12811
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
12480
12812
  const el = lodashGet4(template, path);
@@ -12483,7 +12815,7 @@ function useNoWrap() {
12483
12815
  noWrap: el?.data?.value?.noWrap === true
12484
12816
  };
12485
12817
  }, [focusIdx, template]);
12486
- const handleToggleNoWrap = useCallback6(() => {
12818
+ const handleToggleNoWrap = useCallback8(() => {
12487
12819
  if (!focusIdx || !element) return;
12488
12820
  updateElement(focusIdx, {
12489
12821
  data: {
@@ -12498,30 +12830,30 @@ function useNoWrap() {
12498
12830
  }
12499
12831
 
12500
12832
  // src/core/editor/components/element-gear/section-column/float.tsx
12501
- import { Fragment as Fragment8, jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
12833
+ import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
12502
12834
  var SectionColumnFloat = () => {
12503
12835
  const { isFullWidth, handleToggleFullWidth } = useFullWidthToggle();
12504
12836
  const { noWrap, handleToggleNoWrap } = useNoWrap();
12505
- return /* @__PURE__ */ jsxs15(Fragment8, { children: [
12506
- /* @__PURE__ */ jsx28(DuplicateButton, {}),
12507
- /* @__PURE__ */ jsx28(DeleteButton, {}),
12508
- /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
12509
- /* @__PURE__ */ jsxs15(Tooltip, { children: [
12510
- /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx28(MoreHorizontalIcon2, { className: "w-4 h-4" }) }) }) }),
12511
- /* @__PURE__ */ jsx28(TooltipContent, { side: "bottom", children: "More" })
12837
+ return /* @__PURE__ */ jsxs16(Fragment8, { children: [
12838
+ /* @__PURE__ */ jsx29(DuplicateButton, {}),
12839
+ /* @__PURE__ */ jsx29(DeleteButton, {}),
12840
+ /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
12841
+ /* @__PURE__ */ jsxs16(Tooltip, { children: [
12842
+ /* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx29(MoreHorizontalIcon2, { className: "w-4 h-4" }) }) }) }),
12843
+ /* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", children: "More" })
12512
12844
  ] }),
12513
- /* @__PURE__ */ jsxs15(DropdownMenuContent, { side: "bottom", className: "w-[250px]", children: [
12514
- /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: handleToggleNoWrap, children: [
12515
- /* @__PURE__ */ jsx28(Layers2Icon, { className: "w-4 h-4" }),
12516
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 w-full", children: [
12517
- /* @__PURE__ */ jsx28("p", { className: "w-full", children: noWrap ? "Columns collapse" : "Columns collapse" }),
12518
- !noWrap && /* @__PURE__ */ jsx28(CheckIcon4, { className: "w-4 h-4" })
12845
+ /* @__PURE__ */ jsxs16(DropdownMenuContent, { side: "bottom", className: "w-[250px]", children: [
12846
+ /* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: handleToggleNoWrap, children: [
12847
+ /* @__PURE__ */ jsx29(Layers2Icon, { className: "w-4 h-4" }),
12848
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 w-full", children: [
12849
+ /* @__PURE__ */ jsx29("p", { className: "w-full", children: noWrap ? "Columns collapse" : "Columns collapse" }),
12850
+ !noWrap && /* @__PURE__ */ jsx29(CheckIcon4, { className: "w-4 h-4" })
12519
12851
  ] })
12520
12852
  ] }),
12521
- /* @__PURE__ */ jsx28(DropdownMenuSeparator, {}),
12522
- /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: handleToggleFullWidth, children: [
12523
- isFullWidth ? /* @__PURE__ */ jsx28(ChevronsRightLeftIcon2, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx28(ChevronsLeftRightIcon2, { className: "w-4 h-4" }),
12524
- /* @__PURE__ */ jsx28("p", { children: isFullWidth ? "Reset to original width" : "Expand to full width" })
12853
+ /* @__PURE__ */ jsx29(DropdownMenuSeparator, {}),
12854
+ /* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: handleToggleFullWidth, children: [
12855
+ isFullWidth ? /* @__PURE__ */ jsx29(ChevronsRightLeftIcon2, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx29(ChevronsLeftRightIcon2, { className: "w-4 h-4" }),
12856
+ /* @__PURE__ */ jsx29("p", { children: isFullWidth ? "Reset to original width" : "Expand to full width" })
12525
12857
  ] })
12526
12858
  ] })
12527
12859
  ] })
@@ -12529,11 +12861,11 @@ var SectionColumnFloat = () => {
12529
12861
  };
12530
12862
 
12531
12863
  // src/core/editor/components/element-gear/spacer/float.tsx
12532
- import { Fragment as Fragment9, jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
12864
+ import { Fragment as Fragment9, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
12533
12865
  var SpacerFloat = () => {
12534
- return /* @__PURE__ */ jsxs16(Fragment9, { children: [
12535
- /* @__PURE__ */ jsx29(DuplicateButton, {}),
12536
- /* @__PURE__ */ jsx29(DeleteButton, {})
12866
+ return /* @__PURE__ */ jsxs17(Fragment9, { children: [
12867
+ /* @__PURE__ */ jsx30(DuplicateButton, {}),
12868
+ /* @__PURE__ */ jsx30(DeleteButton, {})
12537
12869
  ] });
12538
12870
  };
12539
12871
 
@@ -12541,16 +12873,16 @@ var SpacerFloat = () => {
12541
12873
  import { MoreHorizontalIcon as MoreHorizontalIcon3, PlusCircleIcon } from "lucide-react";
12542
12874
 
12543
12875
  // src/core/editor/components/email-template-v2/context/sidebar-context.tsx
12544
- import { createContext, useContext, useState as useState4 } from "react";
12545
- import { jsx as jsx30 } from "react/jsx-runtime";
12876
+ import { createContext, useContext, useState as useState5 } from "react";
12877
+ import { jsx as jsx31 } from "react/jsx-runtime";
12546
12878
  var SidebarContext = createContext(null);
12547
12879
  var PICKER_VIEWS = ["color", "images", "add-social"];
12548
12880
  function SidebarProvider({ children }) {
12549
- const [activeView, setActiveViewState] = useState4("elements");
12550
- const [lastView, setLastView] = useState4("elements");
12551
- const [colorType, setColorType] = useState4("Color");
12552
- const [colorTarget, setColorTarget] = useState4(null);
12553
- const [imageTarget, setImageTarget] = useState4(null);
12881
+ const [activeView, setActiveViewState] = useState5("elements");
12882
+ const [lastView, setLastView] = useState5("elements");
12883
+ const [colorType, setColorType] = useState5("Color");
12884
+ const [colorTarget, setColorTarget] = useState5(null);
12885
+ const [imageTarget, setImageTarget] = useState5(null);
12554
12886
  const setActiveView = (view) => {
12555
12887
  if (view !== activeView) {
12556
12888
  if (!PICKER_VIEWS.includes(activeView)) {
@@ -12559,7 +12891,7 @@ function SidebarProvider({ children }) {
12559
12891
  }
12560
12892
  setActiveViewState(view);
12561
12893
  };
12562
- return /* @__PURE__ */ jsx30(SidebarContext.Provider, { value: { activeView, setActiveView, lastView, colorType, setColorType, colorTarget, setColorTarget, imageTarget, setImageTarget }, children });
12894
+ return /* @__PURE__ */ jsx31(SidebarContext.Provider, { value: { activeView, setActiveView, lastView, colorType, setColorType, colorTarget, setColorTarget, imageTarget, setImageTarget }, children });
12563
12895
  }
12564
12896
  function useSidebarContext() {
12565
12897
  const context = useContext(SidebarContext);
@@ -12570,33 +12902,33 @@ function useSidebarContext() {
12570
12902
  }
12571
12903
 
12572
12904
  // src/core/editor/components/element-gear/social/float.tsx
12573
- import { Fragment as Fragment10, jsx as jsx31, jsxs as jsxs17 } from "react/jsx-runtime";
12905
+ import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
12574
12906
  var SocialFloat = () => {
12575
12907
  const { setActiveView } = useSidebarContext();
12576
- return /* @__PURE__ */ jsxs17(Fragment10, { children: [
12577
- /* @__PURE__ */ jsxs17(Tooltip, { children: [
12578
- /* @__PURE__ */ jsx31(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx31(Button, { variant: "ghost", className: floatButtonVariants, onClick: () => setActiveView("add-social"), children: /* @__PURE__ */ jsx31(PlusCircleIcon, {}) }) }),
12579
- /* @__PURE__ */ jsx31(TooltipContent, { side: "bottom", children: "Add Social" })
12908
+ return /* @__PURE__ */ jsxs18(Fragment10, { children: [
12909
+ /* @__PURE__ */ jsxs18(Tooltip, { children: [
12910
+ /* @__PURE__ */ jsx32(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(Button, { variant: "ghost", className: floatButtonVariants, onClick: () => setActiveView("add-social"), children: /* @__PURE__ */ jsx32(PlusCircleIcon, {}) }) }),
12911
+ /* @__PURE__ */ jsx32(TooltipContent, { side: "bottom", children: "Add Social" })
12580
12912
  ] }),
12581
- /* @__PURE__ */ jsx31(DuplicateButton, {}),
12582
- /* @__PURE__ */ jsx31(DeleteButton, {}),
12583
- /* @__PURE__ */ jsxs17(DropdownMenu, { children: [
12584
- /* @__PURE__ */ jsxs17(Tooltip, { children: [
12585
- /* @__PURE__ */ jsx31(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx31(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx31(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx31(MoreHorizontalIcon3, { className: "w-4 h-4" }) }) }) }),
12586
- /* @__PURE__ */ jsx31(TooltipContent, { side: "bottom", children: "More" })
12913
+ /* @__PURE__ */ jsx32(DuplicateButton, {}),
12914
+ /* @__PURE__ */ jsx32(DeleteButton, {}),
12915
+ /* @__PURE__ */ jsxs18(DropdownMenu, { children: [
12916
+ /* @__PURE__ */ jsxs18(Tooltip, { children: [
12917
+ /* @__PURE__ */ jsx32(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx32(MoreHorizontalIcon3, { className: "w-4 h-4" }) }) }) }),
12918
+ /* @__PURE__ */ jsx32(TooltipContent, { side: "bottom", children: "More" })
12587
12919
  ] }),
12588
- /* @__PURE__ */ jsx31(DropdownMenuContent, { side: "bottom", className: "w-[200px]", children: /* @__PURE__ */ jsxs17(DropdownMenuItem, { onClick: () => setActiveView("add-social"), children: [
12589
- /* @__PURE__ */ jsx31(PlusCircleIcon, { className: "w-4 h-4" }),
12590
- /* @__PURE__ */ jsx31("p", { children: "Add Social" })
12920
+ /* @__PURE__ */ jsx32(DropdownMenuContent, { side: "bottom", className: "w-[200px]", children: /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => setActiveView("add-social"), children: [
12921
+ /* @__PURE__ */ jsx32(PlusCircleIcon, { className: "w-4 h-4" }),
12922
+ /* @__PURE__ */ jsx32("p", { children: "Add Social" })
12591
12923
  ] }) })
12592
12924
  ] })
12593
12925
  ] });
12594
12926
  };
12595
12927
 
12596
12928
  // src/components/ui/textarea.tsx
12597
- import { jsx as jsx32 } from "react/jsx-runtime";
12929
+ import { jsx as jsx33 } from "react/jsx-runtime";
12598
12930
  function Textarea({ className, ...props }) {
12599
- return /* @__PURE__ */ jsx32(
12931
+ return /* @__PURE__ */ jsx33(
12600
12932
  "textarea",
12601
12933
  {
12602
12934
  "data-slot": "textarea",
@@ -12611,38 +12943,39 @@ function Textarea({ className, ...props }) {
12611
12943
 
12612
12944
  // src/core/editor/components/element-gear/social-item/float.tsx
12613
12945
  import { Accessibility, MoreHorizontalIcon as MoreHorizontalIcon4, TrashIcon as TrashIcon4 } from "lucide-react";
12614
- import { useState as useState6, useEffect as useEffect9 } from "react";
12946
+ import { useState as useState7, useCallback as useCallback11 } from "react";
12615
12947
 
12616
12948
  // src/core/editor/components/social-item-menu.tsx
12617
- import { useState as useState5, useEffect as useEffect8, useMemo as useMemo8, useCallback as useCallback7 } from "react";
12949
+ import { useState as useState6, useMemo as useMemo9, useCallback as useCallback9 } from "react";
12618
12950
  import { PencilIcon as PencilIcon3, CheckIcon as CheckIcon5, CopyIcon as CopyIcon4 } from "lucide-react";
12619
12951
  import { get as lodashGet5 } from "lodash";
12620
- import { jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
12952
+ import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
12621
12953
  var SocialItemMenu = ({ hasHref }) => {
12622
- const [isOpen, setIsOpen] = useState5(false);
12623
- const [showCopied, setShowCopied] = useState5(false);
12624
- const [hrefInputValue, setHrefInputValue] = useState5("");
12625
- const [contentInputValue, setContentInputValue] = useState5("");
12954
+ const [isOpen, setIsOpen] = useState6(false);
12955
+ const [showCopied, setShowCopied] = useState6(false);
12956
+ const [hrefInputValue, setHrefInputValue] = useState6("");
12957
+ const [contentInputValue, setContentInputValue] = useState6("");
12626
12958
  const { href, setHref, copyHref } = useHref();
12627
12959
  const { focusIdx, template, updateElement } = useEditorStore();
12628
- const element = useMemo8(() => {
12960
+ const element = useMemo9(() => {
12629
12961
  if (!focusIdx || !template) return null;
12630
12962
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.?\[(\d+)\]/g, "[$1]") : focusIdx;
12631
12963
  return lodashGet5(template, path);
12632
12964
  }, [focusIdx, template]);
12633
12965
  const content = element?.data?.value?.content || "";
12634
- useEffect8(() => {
12635
- if (isOpen) {
12966
+ const handleOpenChange = useCallback9((open) => {
12967
+ setIsOpen(open);
12968
+ if (open) {
12636
12969
  setHrefInputValue(href);
12637
12970
  setContentInputValue(content);
12638
12971
  }
12639
- }, [isOpen, href, content]);
12640
- const handleCopy = useCallback7(async () => {
12972
+ }, [href, content]);
12973
+ const handleCopy = useCallback9(async () => {
12641
12974
  await copyHref();
12642
12975
  setShowCopied(true);
12643
12976
  setTimeout(() => setShowCopied(false), 2e3);
12644
12977
  }, [copyHref]);
12645
- const handleDone = useCallback7(() => {
12978
+ const handleDone = useCallback9(() => {
12646
12979
  setHref(normalizeWebsiteUrl(hrefInputValue));
12647
12980
  if (focusIdx && element) {
12648
12981
  updateElement(focusIdx, {
@@ -12656,33 +12989,33 @@ var SocialItemMenu = ({ hasHref }) => {
12656
12989
  }
12657
12990
  setIsOpen(false);
12658
12991
  }, [hrefInputValue, contentInputValue, setHref, focusIdx, element, updateElement]);
12659
- return /* @__PURE__ */ jsxs18(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
12660
- /* @__PURE__ */ jsxs18(Tooltip, { children: [
12661
- /* @__PURE__ */ jsx33(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx33(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx33(
12992
+ return /* @__PURE__ */ jsxs19(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [
12993
+ /* @__PURE__ */ jsxs19(Tooltip, { children: [
12994
+ /* @__PURE__ */ jsx34(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx34(
12662
12995
  Button,
12663
12996
  {
12664
12997
  variant: "ghost",
12665
12998
  size: "icon",
12666
12999
  className: floatButtonVariants,
12667
- children: /* @__PURE__ */ jsx33(PencilIcon3, { className: "size-4" })
13000
+ children: /* @__PURE__ */ jsx34(PencilIcon3, { className: "size-4" })
12668
13001
  }
12669
- ) : /* @__PURE__ */ jsxs18(
13002
+ ) : /* @__PURE__ */ jsxs19(
12670
13003
  Button,
12671
13004
  {
12672
13005
  variant: "ghost",
12673
13006
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12674
13007
  children: [
12675
- /* @__PURE__ */ jsx33(PencilIcon3, { className: "size-4" }),
12676
- /* @__PURE__ */ jsx33("p", { children: "Edit" })
13008
+ /* @__PURE__ */ jsx34(PencilIcon3, { className: "size-4" }),
13009
+ /* @__PURE__ */ jsx34("p", { children: "Edit" })
12677
13010
  ]
12678
13011
  }
12679
13012
  ) }) }),
12680
- /* @__PURE__ */ jsx33(TooltipContent, { side: "bottom", children: "Edit" })
13013
+ /* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", children: "Edit" })
12681
13014
  ] }),
12682
- /* @__PURE__ */ jsxs18(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
12683
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-2 mb-2", children: [
12684
- /* @__PURE__ */ jsx33(Label, { className: "text-xs font-medium", children: "Enter a link" }),
12685
- /* @__PURE__ */ jsx33(
13015
+ /* @__PURE__ */ jsxs19(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
13016
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2 mb-2", children: [
13017
+ /* @__PURE__ */ jsx34(Label, { className: "text-xs font-medium", children: "Enter a link" }),
13018
+ /* @__PURE__ */ jsx34(
12686
13019
  Input,
12687
13020
  {
12688
13021
  type: "text",
@@ -12694,9 +13027,9 @@ var SocialItemMenu = ({ hasHref }) => {
12694
13027
  }
12695
13028
  )
12696
13029
  ] }),
12697
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-2", children: [
12698
- /* @__PURE__ */ jsx33(Label, { className: "text-xs font-medium", children: "Content" }),
12699
- /* @__PURE__ */ jsx33(
13030
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2", children: [
13031
+ /* @__PURE__ */ jsx34(Label, { className: "text-xs font-medium", children: "Content" }),
13032
+ /* @__PURE__ */ jsx34(
12700
13033
  Input,
12701
13034
  {
12702
13035
  type: "text",
@@ -12707,10 +13040,10 @@ var SocialItemMenu = ({ hasHref }) => {
12707
13040
  }
12708
13041
  )
12709
13042
  ] }),
12710
- /* @__PURE__ */ jsx33(Separator, { className: "my-2" }),
12711
- /* @__PURE__ */ jsxs18("div", { className: "flex flex-row justify-between items-center", children: [
12712
- /* @__PURE__ */ jsx33("div", { className: "flex flex-row", children: /* @__PURE__ */ jsxs18(Tooltip, { children: [
12713
- /* @__PURE__ */ jsx33(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx33(
13043
+ /* @__PURE__ */ jsx34(Separator, { className: "my-2" }),
13044
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-row justify-between items-center", children: [
13045
+ /* @__PURE__ */ jsx34("div", { className: "flex flex-row", children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
13046
+ /* @__PURE__ */ jsx34(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(
12714
13047
  Button,
12715
13048
  {
12716
13049
  variant: "ghost",
@@ -12718,12 +13051,12 @@ var SocialItemMenu = ({ hasHref }) => {
12718
13051
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12719
13052
  onClick: handleCopy,
12720
13053
  disabled: !hasHref,
12721
- children: showCopied ? /* @__PURE__ */ jsx33(CheckIcon5, { className: "text-green-600" }) : /* @__PURE__ */ jsx33(CopyIcon4, {})
13054
+ children: showCopied ? /* @__PURE__ */ jsx34(CheckIcon5, { className: "text-green-600" }) : /* @__PURE__ */ jsx34(CopyIcon4, {})
12722
13055
  }
12723
13056
  ) }),
12724
- /* @__PURE__ */ jsx33(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
13057
+ /* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
12725
13058
  ] }) }),
12726
- /* @__PURE__ */ jsx33("div", { children: /* @__PURE__ */ jsx33(
13059
+ /* @__PURE__ */ jsx34("div", { children: /* @__PURE__ */ jsx34(
12727
13060
  Button,
12728
13061
  {
12729
13062
  variant: "default",
@@ -12738,11 +13071,11 @@ var SocialItemMenu = ({ hasHref }) => {
12738
13071
  };
12739
13072
 
12740
13073
  // src/core/editor/hooks/use-alt.ts
12741
- import { useMemo as useMemo9, useCallback as useCallback8 } from "react";
13074
+ import { useMemo as useMemo10, useCallback as useCallback10 } from "react";
12742
13075
  import { get as lodashGet6 } from "lodash";
12743
13076
  var useAlt = () => {
12744
13077
  const { focusIdx, updateElement, template } = useEditorStore();
12745
- const { element, alt } = useMemo9(() => {
13078
+ const { element, alt } = useMemo10(() => {
12746
13079
  if (!focusIdx || !template) {
12747
13080
  return { element: null, alt: "" };
12748
13081
  }
@@ -12753,13 +13086,13 @@ var useAlt = () => {
12753
13086
  alt: el?.attributes?.alt || ""
12754
13087
  };
12755
13088
  }, [focusIdx, template]);
12756
- const setAlt = useCallback8((text2) => {
13089
+ const setAlt = useCallback10((text2) => {
12757
13090
  if (!focusIdx || !element) return;
12758
13091
  updateElement(focusIdx, {
12759
13092
  attributes: { ...element.attributes, alt: text2 }
12760
13093
  });
12761
13094
  }, [focusIdx, element, updateElement]);
12762
- const clearAlt = useCallback8(() => {
13095
+ const clearAlt = useCallback10(() => {
12763
13096
  if (!focusIdx || !element) return;
12764
13097
  updateElement(focusIdx, {
12765
13098
  attributes: { ...element.attributes, alt: "" }
@@ -12775,21 +13108,22 @@ var useAlt = () => {
12775
13108
  };
12776
13109
 
12777
13110
  // src/core/editor/components/element-gear/social-item/float.tsx
12778
- import { Fragment as Fragment11, jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
13111
+ import { Fragment as Fragment11, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
12779
13112
  var SocialItemFloat = () => {
12780
13113
  const { href, hasHref } = useHref();
12781
13114
  const { alt, setAlt } = useAlt();
12782
13115
  const { focusIdx, template, deleteElement } = useEditorStore();
12783
- const [dropdownOpen, setDropdownOpen] = useState6(false);
12784
- const [altInputValue, setAltInputValue] = useState6("");
13116
+ const [dropdownOpen, setDropdownOpen] = useState7(false);
13117
+ const [altInputValue, setAltInputValue] = useState7("");
12785
13118
  const parentSocial = focusIdx ? getParentByIdx(template, focusIdx) : null;
12786
13119
  const childrenCount = parentSocial?.children?.length || 0;
12787
13120
  const canDelete = childrenCount > 1;
12788
- useEffect9(() => {
12789
- if (dropdownOpen) {
13121
+ const handleDropdownOpenChange = useCallback11((open) => {
13122
+ setDropdownOpen(open);
13123
+ if (open) {
12790
13124
  setAltInputValue(alt);
12791
13125
  }
12792
- }, [dropdownOpen, alt]);
13126
+ }, [alt]);
12793
13127
  const handleSaveAlt = () => {
12794
13128
  setAlt(altInputValue);
12795
13129
  setDropdownOpen(false);
@@ -12799,37 +13133,37 @@ var SocialItemFloat = () => {
12799
13133
  deleteElement(focusIdx);
12800
13134
  }
12801
13135
  };
12802
- return /* @__PURE__ */ jsxs19(Fragment11, { children: [
12803
- hasHref && /* @__PURE__ */ jsx34(FloatLinkPreview, { href }),
12804
- /* @__PURE__ */ jsx34(SocialItemMenu, { hasHref }),
12805
- /* @__PURE__ */ jsxs19(Tooltip, { children: [
12806
- /* @__PURE__ */ jsx34(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(
13136
+ return /* @__PURE__ */ jsxs20(Fragment11, { children: [
13137
+ hasHref && /* @__PURE__ */ jsx35(FloatLinkPreview, { href }),
13138
+ /* @__PURE__ */ jsx35(SocialItemMenu, { hasHref }),
13139
+ /* @__PURE__ */ jsxs20(Tooltip, { children: [
13140
+ /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35(
12807
13141
  Button,
12808
13142
  {
12809
13143
  variant: "ghost",
12810
13144
  className: floatButtonVariants,
12811
13145
  onClick: handleDelete,
12812
13146
  disabled: !canDelete,
12813
- children: /* @__PURE__ */ jsx34(TrashIcon4, { className: "size-4" })
13147
+ children: /* @__PURE__ */ jsx35(TrashIcon4, { className: "size-4" })
12814
13148
  }
12815
13149
  ) }),
12816
- /* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", children: canDelete ? "Delete" : "Cannot delete last item" })
13150
+ /* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", children: canDelete ? "Delete" : "Cannot delete last item" })
12817
13151
  ] }),
12818
- /* @__PURE__ */ jsxs19(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
12819
- /* @__PURE__ */ jsxs19(Tooltip, { children: [
12820
- /* @__PURE__ */ jsx34(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx34(MoreHorizontalIcon4, { className: "w-4 h-4" }) }) }) }),
12821
- /* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", children: "More" })
13152
+ /* @__PURE__ */ jsxs20(DropdownMenu, { open: dropdownOpen, onOpenChange: handleDropdownOpenChange, children: [
13153
+ /* @__PURE__ */ jsxs20(Tooltip, { children: [
13154
+ /* @__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" }) }) }) }),
13155
+ /* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", children: "More" })
12822
13156
  ] }),
12823
- /* @__PURE__ */ jsx34(DropdownMenuContent, { side: "bottom", className: "w-[250px] z-50001", children: /* @__PURE__ */ jsxs19(DropdownMenuSub, { children: [
12824
- /* @__PURE__ */ jsxs19(DropdownMenuSubTrigger, { children: [
12825
- /* @__PURE__ */ jsx34(Accessibility, { className: "w-4 h-4" }),
12826
- /* @__PURE__ */ jsx34("p", { children: "Alternative Text" })
13157
+ /* @__PURE__ */ jsx35(DropdownMenuContent, { side: "bottom", className: "w-[250px] z-50001", children: /* @__PURE__ */ jsxs20(DropdownMenuSub, { children: [
13158
+ /* @__PURE__ */ jsxs20(DropdownMenuSubTrigger, { children: [
13159
+ /* @__PURE__ */ jsx35(Accessibility, { className: "w-4 h-4" }),
13160
+ /* @__PURE__ */ jsx35("p", { children: "Alternative Text" })
12827
13161
  ] }),
12828
- /* @__PURE__ */ jsx34(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs19(DropdownMenuSubContent, { className: "p-3 w-[250px] z-50001", children: [
12829
- /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2 mb-2", children: [
12830
- /* @__PURE__ */ jsx34(Label, { children: "Alternative Text" }),
12831
- /* @__PURE__ */ jsxs19("div", { className: "relative", children: [
12832
- /* @__PURE__ */ jsx34(
13162
+ /* @__PURE__ */ jsx35(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs20(DropdownMenuSubContent, { className: "p-3 w-[250px] z-50001", children: [
13163
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-2 mb-2", children: [
13164
+ /* @__PURE__ */ jsx35(Label, { children: "Alternative Text" }),
13165
+ /* @__PURE__ */ jsxs20("div", { className: "relative", children: [
13166
+ /* @__PURE__ */ jsx35(
12833
13167
  Textarea,
12834
13168
  {
12835
13169
  placeholder: "Icon image alt, for example: 'Facebook icon'",
@@ -12839,14 +13173,14 @@ var SocialItemFloat = () => {
12839
13173
  onChange: (e) => setAltInputValue(e.target.value)
12840
13174
  }
12841
13175
  ),
12842
- /* @__PURE__ */ jsxs19("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
13176
+ /* @__PURE__ */ jsxs20("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
12843
13177
  altInputValue.length,
12844
13178
  "/250"
12845
13179
  ] })
12846
13180
  ] }),
12847
- /* @__PURE__ */ jsx34("p", { className: "text-xs text-muted-foreground mb-4", children: "Be descriptive and add context to keep your alt text clear for clients who use screen readers." })
13181
+ /* @__PURE__ */ jsx35("p", { className: "text-xs text-muted-foreground mb-4", children: "Be descriptive and add context to keep your alt text clear for clients who use screen readers." })
12848
13182
  ] }),
12849
- /* @__PURE__ */ jsx34(
13183
+ /* @__PURE__ */ jsx35(
12850
13184
  Button,
12851
13185
  {
12852
13186
  variant: "default",
@@ -12862,27 +13196,27 @@ var SocialItemFloat = () => {
12862
13196
  };
12863
13197
 
12864
13198
  // src/core/editor/components/element-gear/divider/float.tsx
12865
- import { Fragment as Fragment12, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
13199
+ import { Fragment as Fragment12, jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
12866
13200
  var DividerFloat = () => {
12867
- return /* @__PURE__ */ jsxs20(Fragment12, { children: [
12868
- /* @__PURE__ */ jsx35(DuplicateButton, {}),
12869
- /* @__PURE__ */ jsx35(DeleteButton, {})
13201
+ return /* @__PURE__ */ jsxs21(Fragment12, { children: [
13202
+ /* @__PURE__ */ jsx36(DuplicateButton, {}),
13203
+ /* @__PURE__ */ jsx36(DeleteButton, {})
12870
13204
  ] });
12871
13205
  };
12872
13206
 
12873
13207
  // src/core/editor/components/element-gear/image/float.tsx
12874
13208
  import { Accessibility as Accessibility2, CheckIcon as CheckIcon6, MoreHorizontalIcon as MoreHorizontalIcon5, Proportions } from "lucide-react";
12875
13209
  import lodashGet7 from "lodash/get";
12876
- import { useState as useState7, useEffect as useEffect10, useMemo as useMemo10, useCallback as useCallback9 } from "react";
12877
- import { Fragment as Fragment13, jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
13210
+ import { useState as useState8, useMemo as useMemo11, useCallback as useCallback12 } from "react";
13211
+ import { Fragment as Fragment13, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
12878
13212
  var ImageFloat = () => {
12879
13213
  const { href, hasHref } = useHref();
12880
13214
  const { alt, setAlt, hasAlt } = useAlt();
12881
13215
  const { focusIdx, updateElement, template } = useEditorStore();
12882
- const [showMoreView, setShowMoreView] = useState7(null);
12883
- const [dropdownOpen, setDropdownOpen] = useState7(false);
12884
- const [altInputValue, setAltInputValue] = useState7("");
12885
- const { element, isFluidOnMobile } = useMemo10(() => {
13216
+ const [showMoreView, setShowMoreView] = useState8(null);
13217
+ const [dropdownOpen, setDropdownOpen] = useState8(false);
13218
+ const [altInputValue, setAltInputValue] = useState8("");
13219
+ const { element, isFluidOnMobile } = useMemo11(() => {
12886
13220
  if (!focusIdx || !template) return { element: null, isFluidOnMobile: false };
12887
13221
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
12888
13222
  const el = lodashGet7(template, path);
@@ -12891,7 +13225,7 @@ var ImageFloat = () => {
12891
13225
  isFluidOnMobile: el?.attributes?.["fluid-on-mobile"] === "true"
12892
13226
  };
12893
13227
  }, [focusIdx, template]);
12894
- const toggleFluidOnMobile = useCallback9(() => {
13228
+ const toggleFluidOnMobile = useCallback12(() => {
12895
13229
  if (!focusIdx || !element) return;
12896
13230
  const newAttributes = { ...element.attributes };
12897
13231
  if (isFluidOnMobile) {
@@ -12901,44 +13235,45 @@ var ImageFloat = () => {
12901
13235
  }
12902
13236
  updateElement(focusIdx, { attributes: newAttributes });
12903
13237
  }, [focusIdx, element, isFluidOnMobile, updateElement]);
12904
- useEffect10(() => {
12905
- if (dropdownOpen) {
13238
+ const handleDropdownOpenChange = useCallback12((open) => {
13239
+ setDropdownOpen(open);
13240
+ if (open) {
12906
13241
  setAltInputValue(alt);
12907
13242
  }
12908
- }, [dropdownOpen, alt]);
13243
+ }, [alt]);
12909
13244
  const handleSaveAlt = () => {
12910
13245
  setAlt(altInputValue);
12911
13246
  setDropdownOpen(false);
12912
13247
  };
12913
- return /* @__PURE__ */ jsxs21(Fragment13, { children: [
12914
- hasHref && /* @__PURE__ */ jsx36(FloatLinkPreview, { href }),
12915
- /* @__PURE__ */ jsx36(HrefMenu, {}),
12916
- /* @__PURE__ */ jsx36(DuplicateButton, {}),
12917
- /* @__PURE__ */ jsx36(DeleteButton, {}),
12918
- /* @__PURE__ */ jsxs21(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
12919
- /* @__PURE__ */ jsxs21(Tooltip, { children: [
12920
- /* @__PURE__ */ jsx36(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx36(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx36(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx36(MoreHorizontalIcon5, { className: "w-4 h-4" }) }) }) }),
12921
- /* @__PURE__ */ jsx36(TooltipContent, { side: "bottom", children: "More" })
13248
+ return /* @__PURE__ */ jsxs22(Fragment13, { children: [
13249
+ hasHref && /* @__PURE__ */ jsx37(FloatLinkPreview, { href }),
13250
+ /* @__PURE__ */ jsx37(HrefMenu, {}),
13251
+ /* @__PURE__ */ jsx37(DuplicateButton, {}),
13252
+ /* @__PURE__ */ jsx37(DeleteButton, {}),
13253
+ /* @__PURE__ */ jsxs22(DropdownMenu, { open: dropdownOpen, onOpenChange: handleDropdownOpenChange, children: [
13254
+ /* @__PURE__ */ jsxs22(Tooltip, { children: [
13255
+ /* @__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" }) }) }) }),
13256
+ /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", children: "More" })
12922
13257
  ] }),
12923
- /* @__PURE__ */ jsxs21(DropdownMenuContent, { side: "bottom", className: "w-[250px] z-50001", children: [
12924
- /* @__PURE__ */ jsxs21(DropdownMenuItem, { onClick: toggleFluidOnMobile, children: [
12925
- /* @__PURE__ */ jsx36(Proportions, { className: "w-4 h-4" }),
12926
- /* @__PURE__ */ jsxs21("div", { className: "flex flex-row items-center justify-between gap-2 w-full", children: [
12927
- /* @__PURE__ */ jsx36("p", { children: "Full width on mobile" }),
12928
- isFluidOnMobile && /* @__PURE__ */ jsx36(CheckIcon6, { className: "w-4 h-4" })
13258
+ /* @__PURE__ */ jsxs22(DropdownMenuContent, { side: "bottom", className: "w-[250px] z-50001", children: [
13259
+ /* @__PURE__ */ jsxs22(DropdownMenuItem, { onClick: toggleFluidOnMobile, children: [
13260
+ /* @__PURE__ */ jsx37(Proportions, { className: "w-4 h-4" }),
13261
+ /* @__PURE__ */ jsxs22("div", { className: "flex flex-row items-center justify-between gap-2 w-full", children: [
13262
+ /* @__PURE__ */ jsx37("p", { children: "Full width on mobile" }),
13263
+ isFluidOnMobile && /* @__PURE__ */ jsx37(CheckIcon6, { className: "w-4 h-4" })
12929
13264
  ] })
12930
13265
  ] }),
12931
- /* @__PURE__ */ jsx36(DropdownMenuSeparator, {}),
12932
- /* @__PURE__ */ jsxs21(DropdownMenuSub, { children: [
12933
- /* @__PURE__ */ jsxs21(DropdownMenuSubTrigger, { children: [
12934
- /* @__PURE__ */ jsx36(Accessibility2, { className: "w-4 h-4" }),
12935
- /* @__PURE__ */ jsx36("p", { children: "Alternative Text" })
13266
+ /* @__PURE__ */ jsx37(DropdownMenuSeparator, {}),
13267
+ /* @__PURE__ */ jsxs22(DropdownMenuSub, { children: [
13268
+ /* @__PURE__ */ jsxs22(DropdownMenuSubTrigger, { children: [
13269
+ /* @__PURE__ */ jsx37(Accessibility2, { className: "w-4 h-4" }),
13270
+ /* @__PURE__ */ jsx37("p", { children: "Alternative Text" })
12936
13271
  ] }),
12937
- /* @__PURE__ */ jsx36(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs21(DropdownMenuSubContent, { className: "p-3 w-[250px] z-50001", children: [
12938
- /* @__PURE__ */ jsxs21("div", { className: "flex flex-col gap-2 mb-2", children: [
12939
- /* @__PURE__ */ jsx36(Label, { children: "Alternative Text" }),
12940
- /* @__PURE__ */ jsxs21("div", { className: "relative", children: [
12941
- /* @__PURE__ */ jsx36(
13272
+ /* @__PURE__ */ jsx37(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs22(DropdownMenuSubContent, { className: "p-3 w-[250px] z-50001", children: [
13273
+ /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2 mb-2", children: [
13274
+ /* @__PURE__ */ jsx37(Label, { children: "Alternative Text" }),
13275
+ /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
13276
+ /* @__PURE__ */ jsx37(
12942
13277
  Textarea,
12943
13278
  {
12944
13279
  placeholder: "Spacious living room with hardwood floors, large windows, and a cozy fireplace",
@@ -12948,14 +13283,14 @@ var ImageFloat = () => {
12948
13283
  onChange: (e) => setAltInputValue(e.target.value)
12949
13284
  }
12950
13285
  ),
12951
- /* @__PURE__ */ jsxs21("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
13286
+ /* @__PURE__ */ jsxs22("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
12952
13287
  altInputValue.length,
12953
13288
  "/250"
12954
13289
  ] })
12955
13290
  ] }),
12956
- /* @__PURE__ */ jsx36("p", { className: "text-xs text-muted-foreground mb-4", children: "Be descriptive and add context to keep your alt text clear for clients who use screen readers." })
13291
+ /* @__PURE__ */ jsx37("p", { className: "text-xs text-muted-foreground mb-4", children: "Be descriptive and add context to keep your alt text clear for clients who use screen readers." })
12957
13292
  ] }),
12958
- /* @__PURE__ */ jsx36(
13293
+ /* @__PURE__ */ jsx37(
12959
13294
  Button,
12960
13295
  {
12961
13296
  variant: "default",
@@ -12972,7 +13307,7 @@ var ImageFloat = () => {
12972
13307
  };
12973
13308
 
12974
13309
  // src/core/editor/components/mlsNumber-menu.tsx
12975
- import { useState as useState8, useEffect as useEffect11 } from "react";
13310
+ import { useState as useState9, useEffect as useEffect7 } from "react";
12976
13311
  import { HousePlusIcon, TrashIcon as TrashIcon5, XIcon as XIcon2, Loader2Icon } from "lucide-react";
12977
13312
 
12978
13313
  // src/services/repliers/commands.ts
@@ -12988,16 +13323,16 @@ async function getListingByMlsNumber(mlsNumber) {
12988
13323
  }
12989
13324
 
12990
13325
  // src/core/editor/components/mlsNumber-menu.tsx
12991
- import { Fragment as Fragment14, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
13326
+ import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
12992
13327
  var MlsNumberMenu = () => {
12993
13328
  const { focusIdx, template, updateElement, onToast } = useEditorStore();
12994
- const [isOpen, setIsOpen] = useState8(false);
12995
- const [inputValue, setInputValue] = useState8("");
12996
- const [propertyData, setPropertyData] = useState8(null);
12997
- const [isLoading, setIsLoading] = useState8(false);
13329
+ const [isOpen, setIsOpen] = useState9(false);
13330
+ const [inputValue, setInputValue] = useState9("");
13331
+ const [propertyData, setPropertyData] = useState9(null);
13332
+ const [isLoading, setIsLoading] = useState9(false);
12998
13333
  const propertyElement = focusIdx && template ? getValueByIdx(template, focusIdx) : null;
12999
13334
  const currentMlsNumber = propertyElement?.data?.value?.mlsNumber || "";
13000
- useEffect11(() => {
13335
+ useEffect7(() => {
13001
13336
  setInputValue(currentMlsNumber);
13002
13337
  setPropertyData(null);
13003
13338
  }, [focusIdx, currentMlsNumber]);
@@ -13065,25 +13400,25 @@ var MlsNumberMenu = () => {
13065
13400
  }
13066
13401
  }
13067
13402
  };
13068
- return /* @__PURE__ */ jsxs22(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
13069
- /* @__PURE__ */ jsxs22(Tooltip, { children: [
13070
- /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs22(
13403
+ return /* @__PURE__ */ jsxs23(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
13404
+ /* @__PURE__ */ jsxs23(Tooltip, { children: [
13405
+ /* @__PURE__ */ jsx38(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx38(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs23(
13071
13406
  Button,
13072
13407
  {
13073
13408
  variant: "ghost",
13074
13409
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
13075
13410
  children: [
13076
- /* @__PURE__ */ jsx37(HousePlusIcon, { className: "size-4" }),
13077
- /* @__PURE__ */ jsx37("p", { children: "MLS" })
13411
+ /* @__PURE__ */ jsx38(HousePlusIcon, { className: "size-4" }),
13412
+ /* @__PURE__ */ jsx38("p", { children: "MLS" })
13078
13413
  ]
13079
13414
  }
13080
13415
  ) }) }),
13081
- /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", children: "Enter MLS Number" })
13416
+ /* @__PURE__ */ jsx38(TooltipContent, { side: "bottom", children: "Enter MLS Number" })
13082
13417
  ] }),
13083
- /* @__PURE__ */ jsxs22(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
13084
- /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
13085
- /* @__PURE__ */ jsx37(Label, { children: "Enter MLS Number" }),
13086
- /* @__PURE__ */ jsx37(
13418
+ /* @__PURE__ */ jsxs23(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
13419
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2", children: [
13420
+ /* @__PURE__ */ jsx38(Label, { children: "Enter MLS Number" }),
13421
+ /* @__PURE__ */ jsx38(
13087
13422
  Input,
13088
13423
  {
13089
13424
  type: "text",
@@ -13096,10 +13431,10 @@ var MlsNumberMenu = () => {
13096
13431
  }
13097
13432
  )
13098
13433
  ] }),
13099
- /* @__PURE__ */ jsx37(Separator, { className: "my-2" }),
13100
- /* @__PURE__ */ jsxs22("div", { className: "flex flex-row justify-between items-center", children: [
13101
- /* @__PURE__ */ jsx37("div", { className: "flex flex-row", children: /* @__PURE__ */ jsxs22(Tooltip, { children: [
13102
- /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(
13434
+ /* @__PURE__ */ jsx38(Separator, { className: "my-2" }),
13435
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-row justify-between items-center", children: [
13436
+ /* @__PURE__ */ jsx38("div", { className: "flex flex-row", children: /* @__PURE__ */ jsxs23(Tooltip, { children: [
13437
+ /* @__PURE__ */ jsx38(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx38(
13103
13438
  Button,
13104
13439
  {
13105
13440
  variant: "ghost",
@@ -13107,27 +13442,27 @@ var MlsNumberMenu = () => {
13107
13442
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
13108
13443
  onClick: handleClear,
13109
13444
  disabled: !inputValue,
13110
- children: /* @__PURE__ */ jsx37(TrashIcon5, {})
13445
+ children: /* @__PURE__ */ jsx38(TrashIcon5, {})
13111
13446
  }
13112
13447
  ) }),
13113
- /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", className: "z-50001", children: "Clear" })
13448
+ /* @__PURE__ */ jsx38(TooltipContent, { side: "bottom", className: "z-50001", children: "Clear" })
13114
13449
  ] }) }),
13115
- /* @__PURE__ */ jsx37("div", { children: /* @__PURE__ */ jsx37(
13450
+ /* @__PURE__ */ jsx38("div", { children: /* @__PURE__ */ jsx38(
13116
13451
  Button,
13117
13452
  {
13118
13453
  variant: "default",
13119
13454
  className: "shadow-none transition-none cursor-pointer rounded-[12px] outline-none",
13120
13455
  onClick: handleDone,
13121
13456
  disabled: isLoading || !inputValue.trim(),
13122
- children: isLoading ? /* @__PURE__ */ jsx37(Loader2Icon, { className: "size-4 animate-spin" }) : "Done"
13457
+ children: isLoading ? /* @__PURE__ */ jsx38(Loader2Icon, { className: "size-4 animate-spin" }) : "Done"
13123
13458
  }
13124
13459
  ) })
13125
13460
  ] }),
13126
- propertyData && /* @__PURE__ */ jsxs22(Fragment14, { children: [
13127
- /* @__PURE__ */ jsx37(Separator, { className: "my-2" }),
13128
- /* @__PURE__ */ jsxs22("div", { className: "rounded-[12px] border overflow-hidden bg-card", children: [
13129
- /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
13130
- /* @__PURE__ */ jsx37(
13461
+ propertyData && /* @__PURE__ */ jsxs23(Fragment14, { children: [
13462
+ /* @__PURE__ */ jsx38(Separator, { className: "my-2" }),
13463
+ /* @__PURE__ */ jsxs23("div", { className: "rounded-[12px] border overflow-hidden bg-card", children: [
13464
+ /* @__PURE__ */ jsxs23("div", { className: "relative", children: [
13465
+ /* @__PURE__ */ jsx38(
13131
13466
  "img",
13132
13467
  {
13133
13468
  src: `https://cdn.repliers.io/${propertyData.images?.[0]}`,
@@ -13135,35 +13470,35 @@ var MlsNumberMenu = () => {
13135
13470
  className: "w-full h-[120px] object-cover"
13136
13471
  }
13137
13472
  ),
13138
- /* @__PURE__ */ jsx37(
13473
+ /* @__PURE__ */ jsx38(
13139
13474
  Button,
13140
13475
  {
13141
13476
  variant: "ghost",
13142
13477
  size: "icon",
13143
13478
  className: "absolute top-1 right-1 h-6 w-6 bg-black/50 hover:bg-black/70 rounded-full",
13144
13479
  onClick: handleClearPreview,
13145
- children: /* @__PURE__ */ jsx37(XIcon2, { className: "size-3 text-white" })
13480
+ children: /* @__PURE__ */ jsx38(XIcon2, { className: "size-3 text-white" })
13146
13481
  }
13147
13482
  )
13148
13483
  ] }),
13149
- /* @__PURE__ */ jsxs22("div", { className: "p-2 flex flex-col gap-1", children: [
13150
- /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between", children: [
13151
- /* @__PURE__ */ jsx37("span", { className: "font-semibold text-sm", children: formatPrice(String(propertyData.listPrice || 0)) }),
13152
- /* @__PURE__ */ jsx37("span", { className: "text-xs px-2 py-0.5 rounded-full bg-green-100 text-green-700", children: propertyData.standardStatus || propertyData.status })
13484
+ /* @__PURE__ */ jsxs23("div", { className: "p-2 flex flex-col gap-1", children: [
13485
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between", children: [
13486
+ /* @__PURE__ */ jsx38("span", { className: "font-semibold text-sm", children: formatPrice(String(propertyData.listPrice || 0)) }),
13487
+ /* @__PURE__ */ jsx38("span", { className: "text-xs px-2 py-0.5 rounded-full bg-green-100 text-green-700", children: propertyData.standardStatus || propertyData.status })
13153
13488
  ] }),
13154
- /* @__PURE__ */ jsxs22("div", { className: "text-sm", children: [
13489
+ /* @__PURE__ */ jsxs23("div", { className: "text-sm", children: [
13155
13490
  propertyData.address?.streetNumber,
13156
13491
  " ",
13157
13492
  propertyData.address?.streetName
13158
13493
  ] }),
13159
- /* @__PURE__ */ jsxs22("div", { className: "text-xs text-muted-foreground", children: [
13494
+ /* @__PURE__ */ jsxs23("div", { className: "text-xs text-muted-foreground", children: [
13160
13495
  propertyData.address?.city,
13161
13496
  ", ",
13162
13497
  propertyData.address?.state,
13163
13498
  " ",
13164
13499
  propertyData.address?.zip
13165
13500
  ] }),
13166
- /* @__PURE__ */ jsxs22("div", { className: "text-xs text-muted-foreground", children: [
13501
+ /* @__PURE__ */ jsxs23("div", { className: "text-xs text-muted-foreground", children: [
13167
13502
  propertyData.details?.numBedrooms,
13168
13503
  " bd | ",
13169
13504
  propertyData.details?.numBathrooms,
@@ -13171,8 +13506,8 @@ var MlsNumberMenu = () => {
13171
13506
  formatNumber(String(propertyData.details?.sqft || "--")),
13172
13507
  " sf"
13173
13508
  ] }),
13174
- propertyData.office?.brokerageName && /* @__PURE__ */ jsx37("div", { className: "text-xs text-muted-foreground truncate", children: propertyData.office.brokerageName }),
13175
- /* @__PURE__ */ jsx37(
13509
+ propertyData.office?.brokerageName && /* @__PURE__ */ jsx38("div", { className: "text-xs text-muted-foreground truncate", children: propertyData.office.brokerageName }),
13510
+ /* @__PURE__ */ jsx38(
13176
13511
  Button,
13177
13512
  {
13178
13513
  variant: "default",
@@ -13190,34 +13525,34 @@ var MlsNumberMenu = () => {
13190
13525
  };
13191
13526
 
13192
13527
  // src/core/editor/components/element-gear/property/float.tsx
13193
- import { Fragment as Fragment15, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
13528
+ import { Fragment as Fragment15, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
13194
13529
  function PropertyFloat() {
13195
13530
  const { href, hasHref } = useHref();
13196
- return /* @__PURE__ */ jsxs23(Fragment15, { children: [
13197
- hasHref && /* @__PURE__ */ jsx38(FloatLinkPreview, { href }),
13198
- /* @__PURE__ */ jsx38(HrefMenu, {}),
13199
- /* @__PURE__ */ jsx38(MlsNumberMenu, {})
13531
+ return /* @__PURE__ */ jsxs24(Fragment15, { children: [
13532
+ hasHref && /* @__PURE__ */ jsx39(FloatLinkPreview, { href }),
13533
+ /* @__PURE__ */ jsx39(HrefMenu, {}),
13534
+ /* @__PURE__ */ jsx39(MlsNumberMenu, {})
13200
13535
  ] });
13201
13536
  }
13202
13537
 
13203
13538
  // src/core/editor/components/element-gear/property/triple/float.tsx
13204
- import { Fragment as Fragment16, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
13539
+ import { Fragment as Fragment16, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
13205
13540
  var PropertyTripleItemFloat = () => {
13206
13541
  const { href, hasHref } = useHref();
13207
- return /* @__PURE__ */ jsxs24(Fragment16, { children: [
13208
- hasHref && /* @__PURE__ */ jsx39(FloatLinkPreview, { href }),
13209
- /* @__PURE__ */ jsx39(HrefMenu, {})
13542
+ return /* @__PURE__ */ jsxs25(Fragment16, { children: [
13543
+ hasHref && /* @__PURE__ */ jsx40(FloatLinkPreview, { href }),
13544
+ /* @__PURE__ */ jsx40(HrefMenu, {})
13210
13545
  ] });
13211
13546
  };
13212
13547
 
13213
13548
  // src/core/editor/components/float-ui/container.tsx
13214
- import { jsx as jsx40 } from "react/jsx-runtime";
13549
+ import { jsx as jsx41 } from "react/jsx-runtime";
13215
13550
  var FloatUIContainer = ({ ref, style, className, children }) => {
13216
- return /* @__PURE__ */ jsx40("div", { ref, style, className, children });
13551
+ return /* @__PURE__ */ jsx41("div", { ref, style, className, children });
13217
13552
  };
13218
13553
 
13219
13554
  // src/core/editor/components/element-float.tsx
13220
- import { jsx as jsx41 } from "react/jsx-runtime";
13555
+ import { jsx as jsx42 } from "react/jsx-runtime";
13221
13556
  var FLOAT_COMPONENTS = {
13222
13557
  "button": ButtonFloat,
13223
13558
  "section": SectionFloat,
@@ -13241,7 +13576,7 @@ var ElementFloat = ({ getReferenceRect, focusIdx, elementType }) => {
13241
13576
  if (!focusIdx || isDragging || textEditing) return null;
13242
13577
  const FloatComponent = FLOAT_COMPONENTS[elementType];
13243
13578
  if (!FloatComponent) return null;
13244
- return /* @__PURE__ */ jsx41(
13579
+ return /* @__PURE__ */ jsx42(
13245
13580
  ElementFloatContent,
13246
13581
  {
13247
13582
  getReferenceRect,
@@ -13250,7 +13585,7 @@ var ElementFloat = ({ getReferenceRect, focusIdx, elementType }) => {
13250
13585
  );
13251
13586
  };
13252
13587
  var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13253
- const virtualReference = useMemo11(() => ({
13588
+ const virtualReference = useMemo12(() => ({
13254
13589
  getBoundingClientRect: () => {
13255
13590
  const rect = getReferenceRect();
13256
13591
  if (!rect) {
@@ -13259,18 +13594,18 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13259
13594
  return rect;
13260
13595
  }
13261
13596
  }), [getReferenceRect]);
13262
- const { floatingStyles, refs, update } = useFloating4({
13597
+ const { floatingStyles, refs, update } = useFloating5({
13263
13598
  placement: "top",
13264
13599
  middleware: [
13265
- offset4(16),
13600
+ offset5(16),
13266
13601
  // 8px above the element
13267
- flip2({ padding: 8 }),
13602
+ flip3({ padding: 8 }),
13268
13603
  // Flip to bottom if not enough space above
13269
- shift3({ padding: 8 })
13604
+ shift4({ padding: 8 })
13270
13605
  // Keep within viewport
13271
13606
  ]
13272
13607
  });
13273
- useEffect12(() => {
13608
+ useEffect8(() => {
13274
13609
  const rect = getReferenceRect();
13275
13610
  if (!rect || !refs.floating.current) return;
13276
13611
  refs.setPositionReference(virtualReference);
@@ -13285,18 +13620,18 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13285
13620
  );
13286
13621
  return cleanup;
13287
13622
  }, [getReferenceRect, refs, update, virtualReference]);
13288
- 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, {}) });
13623
+ return /* @__PURE__ */ jsx42(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__ */ jsx42(FloatComponent, {}) });
13289
13624
  };
13290
13625
 
13291
13626
  // src/core/editor/components/scaling/divider-scale.tsx
13292
- import { useMemo as useMemo12, useEffect as useEffect13, useState as useState9, useRef as useRef5, useCallback as useCallback11 } from "react";
13293
- import { useFloating as useFloating5, offset as offset5, autoUpdate as autoUpdate4 } from "@floating-ui/react";
13294
- import { jsx as jsx42, jsxs as jsxs25 } from "react/jsx-runtime";
13627
+ import { useMemo as useMemo13, useEffect as useEffect9, useState as useState10, useRef as useRef6, useCallback as useCallback14 } from "react";
13628
+ import { useFloating as useFloating6, offset as offset6, autoUpdate as autoUpdate4 } from "@floating-ui/react";
13629
+ import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
13295
13630
  var DividerScale = ({ getReferenceRect }) => {
13296
- const [dimensions, setDimensions] = useState9({ width: 0, height: 0 });
13297
- const [activeSide, setActiveSide] = useState9(null);
13631
+ const [dimensions, setDimensions] = useState10({ width: 0, height: 0 });
13632
+ const [activeSide, setActiveSide] = useState10(null);
13298
13633
  const { focusIdx, template, setIsScaling } = useEditorStore();
13299
- const { currentWidth, currentAlign } = useMemo12(() => {
13634
+ const { currentWidth, currentAlign } = useMemo13(() => {
13300
13635
  if (!focusIdx || !template) return { currentWidth: 100, currentAlign: "center" };
13301
13636
  const element = getValueByIdx(template, focusIdx);
13302
13637
  const rawWidth = element?.attributes?.width;
@@ -13305,13 +13640,13 @@ var DividerScale = ({ getReferenceRect }) => {
13305
13640
  const align = element?.attributes?.align || "center";
13306
13641
  return { currentWidth: width, currentAlign: align };
13307
13642
  }, [focusIdx, template]);
13308
- const dragRef = useRef5(null);
13309
- const getContainerWidth = useCallback11(() => {
13643
+ const dragRef = useRef6(null);
13644
+ const getContainerWidth = useCallback14(() => {
13310
13645
  const rect = getReferenceRect();
13311
13646
  if (!rect || currentWidth <= 0) return null;
13312
13647
  return rect.width / (currentWidth / 100);
13313
13648
  }, [getReferenceRect, currentWidth]);
13314
- const handlePointerDown = useCallback11((e, side) => {
13649
+ const handlePointerDown = useCallback14((e, side) => {
13315
13650
  e.preventDefault();
13316
13651
  e.stopPropagation();
13317
13652
  const containerWidth = getContainerWidth();
@@ -13329,7 +13664,7 @@ var DividerScale = ({ getReferenceRect }) => {
13329
13664
  document.addEventListener("pointermove", handlePointerMove);
13330
13665
  document.addEventListener("pointerup", handlePointerUp);
13331
13666
  }, [getContainerWidth, currentWidth, currentAlign, setIsScaling]);
13332
- const handlePointerMove = useCallback11((e) => {
13667
+ const handlePointerMove = useCallback14((e) => {
13333
13668
  if (!dragRef.current) return;
13334
13669
  const { startX, startWidth, containerWidth, side, align } = dragRef.current;
13335
13670
  const deltaX = e.clientX - startX;
@@ -13349,20 +13684,20 @@ var DividerScale = ({ getReferenceRect }) => {
13349
13684
  }
13350
13685
  });
13351
13686
  }, []);
13352
- const handlePointerUp = useCallback11(() => {
13687
+ const handlePointerUp = useCallback14(() => {
13353
13688
  setActiveSide(null);
13354
13689
  setIsScaling(false);
13355
13690
  dragRef.current = null;
13356
13691
  document.removeEventListener("pointermove", handlePointerMove);
13357
13692
  document.removeEventListener("pointerup", handlePointerUp);
13358
13693
  }, [handlePointerMove, setIsScaling]);
13359
- useEffect13(() => {
13694
+ useEffect9(() => {
13360
13695
  return () => {
13361
13696
  document.removeEventListener("pointermove", handlePointerMove);
13362
13697
  document.removeEventListener("pointerup", handlePointerUp);
13363
13698
  };
13364
13699
  }, [handlePointerMove, handlePointerUp]);
13365
- const virtualReference = useMemo12(() => ({
13700
+ const virtualReference = useMemo13(() => ({
13366
13701
  getBoundingClientRect: () => {
13367
13702
  const rect = getReferenceRect();
13368
13703
  if (!rect) {
@@ -13371,13 +13706,13 @@ var DividerScale = ({ getReferenceRect }) => {
13371
13706
  return rect;
13372
13707
  }
13373
13708
  }), [getReferenceRect]);
13374
- const { floatingStyles, refs, update } = useFloating5({
13709
+ const { floatingStyles, refs, update } = useFloating6({
13375
13710
  placement: "bottom-start",
13376
13711
  middleware: [
13377
- offset5(({ rects }) => -rects.reference.height)
13712
+ offset6(({ rects }) => -rects.reference.height)
13378
13713
  ]
13379
13714
  });
13380
- useEffect13(() => {
13715
+ useEffect9(() => {
13381
13716
  const rect = getReferenceRect();
13382
13717
  if (!rect || !refs.floating.current) return;
13383
13718
  refs.setPositionReference(virtualReference);
@@ -13404,7 +13739,7 @@ var DividerScale = ({ getReferenceRect }) => {
13404
13739
  }, [getReferenceRect, refs, update, virtualReference]);
13405
13740
  const showLeftHandle = currentAlign !== "left";
13406
13741
  const showRightHandle = currentAlign !== "right";
13407
- return /* @__PURE__ */ jsxs25(
13742
+ return /* @__PURE__ */ jsxs26(
13408
13743
  "div",
13409
13744
  {
13410
13745
  ref: refs.setFloating,
@@ -13416,14 +13751,14 @@ var DividerScale = ({ getReferenceRect }) => {
13416
13751
  },
13417
13752
  className: "relative flex flex-row items-center justify-between",
13418
13753
  children: [
13419
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx42(
13754
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx43(
13420
13755
  "div",
13421
13756
  {
13422
13757
  onPointerDown: (e) => handlePointerDown(e, "left"),
13423
13758
  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"}`
13424
13759
  }
13425
13760
  ),
13426
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx42(
13761
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx43(
13427
13762
  "div",
13428
13763
  {
13429
13764
  onPointerDown: (e) => handlePointerDown(e, "right"),
@@ -13436,14 +13771,14 @@ var DividerScale = ({ getReferenceRect }) => {
13436
13771
  };
13437
13772
 
13438
13773
  // src/core/editor/components/scaling/button-scale.tsx
13439
- import { useMemo as useMemo13, useEffect as useEffect14, useState as useState10, useRef as useRef6, useCallback as useCallback12 } from "react";
13440
- import { useFloating as useFloating6, offset as offset6, autoUpdate as autoUpdate5 } from "@floating-ui/react";
13441
- import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
13774
+ import { useMemo as useMemo14, useEffect as useEffect10, useState as useState11, useRef as useRef7, useCallback as useCallback15 } from "react";
13775
+ import { useFloating as useFloating7, offset as offset7, autoUpdate as autoUpdate5 } from "@floating-ui/react";
13776
+ import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
13442
13777
  var ButtonScale = ({ getReferenceRect }) => {
13443
- const [dimensions, setDimensions] = useState10({ width: 0, height: 0 });
13444
- const [activeSide, setActiveSide] = useState10(null);
13778
+ const [dimensions, setDimensions] = useState11({ width: 0, height: 0 });
13779
+ const [activeSide, setActiveSide] = useState11(null);
13445
13780
  const { focusIdx, template, setIsScaling } = useEditorStore();
13446
- const { currentWidth, currentHeight, currentAlign } = useMemo13(() => {
13781
+ const { currentWidth, currentHeight, currentAlign } = useMemo14(() => {
13447
13782
  if (!focusIdx || !template) {
13448
13783
  return { currentWidth: 24, currentHeight: 44, currentAlign: "center" };
13449
13784
  }
@@ -13457,13 +13792,13 @@ var ButtonScale = ({ getReferenceRect }) => {
13457
13792
  const align = element?.attributes?.align || "center";
13458
13793
  return { currentWidth: width, currentHeight: height, currentAlign: align };
13459
13794
  }, [focusIdx, template]);
13460
- const dragRef = useRef6(null);
13461
- const getContainerWidth = useCallback12(() => {
13795
+ const dragRef = useRef7(null);
13796
+ const getContainerWidth = useCallback15(() => {
13462
13797
  const rect = getReferenceRect();
13463
13798
  if (!rect || currentWidth <= 0) return null;
13464
13799
  return rect.width / (currentWidth / 100);
13465
13800
  }, [getReferenceRect, currentWidth]);
13466
- const handlePointerDown = useCallback12((e, side) => {
13801
+ const handlePointerDown = useCallback15((e, side) => {
13467
13802
  e.preventDefault();
13468
13803
  e.stopPropagation();
13469
13804
  if (document.activeElement instanceof HTMLElement) {
@@ -13485,7 +13820,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13485
13820
  document.addEventListener("pointermove", handlePointerMove);
13486
13821
  document.addEventListener("pointerup", handlePointerUp);
13487
13822
  }, [getContainerWidth, currentWidth, currentHeight, currentAlign, setIsScaling]);
13488
- const handlePointerMove = useCallback12((e) => {
13823
+ const handlePointerMove = useCallback15((e) => {
13489
13824
  if (!dragRef.current) return;
13490
13825
  const { startX, startY, startWidth, startHeight, containerWidth, side, align } = dragRef.current;
13491
13826
  const state = useEditorStore.getState();
@@ -13517,20 +13852,20 @@ var ButtonScale = ({ getReferenceRect }) => {
13517
13852
  });
13518
13853
  }
13519
13854
  }, []);
13520
- const handlePointerUp = useCallback12(() => {
13855
+ const handlePointerUp = useCallback15(() => {
13521
13856
  setActiveSide(null);
13522
13857
  setIsScaling(false);
13523
13858
  dragRef.current = null;
13524
13859
  document.removeEventListener("pointermove", handlePointerMove);
13525
13860
  document.removeEventListener("pointerup", handlePointerUp);
13526
13861
  }, [handlePointerMove, setIsScaling]);
13527
- useEffect14(() => {
13862
+ useEffect10(() => {
13528
13863
  return () => {
13529
13864
  document.removeEventListener("pointermove", handlePointerMove);
13530
13865
  document.removeEventListener("pointerup", handlePointerUp);
13531
13866
  };
13532
13867
  }, [handlePointerMove, handlePointerUp]);
13533
- const virtualReference = useMemo13(() => ({
13868
+ const virtualReference = useMemo14(() => ({
13534
13869
  getBoundingClientRect: () => {
13535
13870
  const rect = getReferenceRect();
13536
13871
  if (!rect) {
@@ -13539,13 +13874,13 @@ var ButtonScale = ({ getReferenceRect }) => {
13539
13874
  return rect;
13540
13875
  }
13541
13876
  }), [getReferenceRect]);
13542
- const { floatingStyles, refs, update } = useFloating6({
13877
+ const { floatingStyles, refs, update } = useFloating7({
13543
13878
  placement: "bottom-start",
13544
13879
  middleware: [
13545
- offset6(({ rects }) => -rects.reference.height)
13880
+ offset7(({ rects }) => -rects.reference.height)
13546
13881
  ]
13547
13882
  });
13548
- useEffect14(() => {
13883
+ useEffect10(() => {
13549
13884
  const rect = getReferenceRect();
13550
13885
  if (!rect || !refs.floating.current) return;
13551
13886
  refs.setPositionReference(virtualReference);
@@ -13574,7 +13909,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13574
13909
  const showRightHandle = currentAlign !== "right";
13575
13910
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13576
13911
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13577
- return /* @__PURE__ */ jsxs26(
13912
+ return /* @__PURE__ */ jsxs27(
13578
13913
  "div",
13579
13914
  {
13580
13915
  ref: refs.setFloating,
@@ -13586,28 +13921,28 @@ var ButtonScale = ({ getReferenceRect }) => {
13586
13921
  },
13587
13922
  className: "relative pointer-events-none",
13588
13923
  children: [
13589
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx43(
13924
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx44(
13590
13925
  "div",
13591
13926
  {
13592
13927
  onPointerDown: (e) => handlePointerDown(e, "top"),
13593
13928
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13594
13929
  }
13595
13930
  ),
13596
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx43(
13931
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx44(
13597
13932
  "div",
13598
13933
  {
13599
13934
  onPointerDown: (e) => handlePointerDown(e, "right"),
13600
13935
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
13601
13936
  }
13602
13937
  ),
13603
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx43(
13938
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx44(
13604
13939
  "div",
13605
13940
  {
13606
13941
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
13607
13942
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
13608
13943
  }
13609
13944
  ),
13610
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx43(
13945
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx44(
13611
13946
  "div",
13612
13947
  {
13613
13948
  onPointerDown: (e) => handlePointerDown(e, "left"),
@@ -13620,14 +13955,15 @@ var ButtonScale = ({ getReferenceRect }) => {
13620
13955
  };
13621
13956
 
13622
13957
  // src/core/editor/components/scaling/image-scale.tsx
13623
- import { useMemo as useMemo14, useEffect as useEffect15, useState as useState11, useRef as useRef7, useCallback as useCallback13 } from "react";
13624
- import { useFloating as useFloating7, offset as offset7, autoUpdate as autoUpdate6 } from "@floating-ui/react";
13625
- import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
13958
+ import { useMemo as useMemo15, useEffect as useEffect11, useState as useState12, useRef as useRef8, useCallback as useCallback16 } from "react";
13959
+ import { useFloating as useFloating8, offset as offset8, autoUpdate as autoUpdate6 } from "@floating-ui/react";
13960
+ import { jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
13961
+ var isCorner = (side) => side === "top-left" || side === "top-right" || side === "bottom-left" || side === "bottom-right";
13626
13962
  var ImageScale = ({ getReferenceRect }) => {
13627
- const [dimensions, setDimensions] = useState11({ width: 0, height: 0 });
13628
- const [activeSide, setActiveSide] = useState11(null);
13963
+ const [dimensions, setDimensions] = useState12({ width: 0, height: 0 });
13964
+ const [activeSide, setActiveSide] = useState12(null);
13629
13965
  const { focusIdx, template, setIsScaling } = useEditorStore();
13630
- const { currentWidth, currentHeight, currentAlign } = useMemo14(() => {
13966
+ const { currentWidth, currentHeight, currentAlign } = useMemo15(() => {
13631
13967
  if (!focusIdx || !template) {
13632
13968
  return { currentWidth: 0, currentHeight: 0, currentAlign: "center" };
13633
13969
  }
@@ -13641,8 +13977,8 @@ var ImageScale = ({ getReferenceRect }) => {
13641
13977
  const align = element?.attributes?.align || "center";
13642
13978
  return { currentWidth: width, currentHeight: height, currentAlign: align };
13643
13979
  }, [focusIdx, template]);
13644
- const dragRef = useRef7(null);
13645
- const handlePointerDown = useCallback13((e, side) => {
13980
+ const dragRef = useRef8(null);
13981
+ const handlePointerDown = useCallback16((e, side) => {
13646
13982
  e.preventDefault();
13647
13983
  e.stopPropagation();
13648
13984
  if (document.activeElement instanceof HTMLElement) {
@@ -13660,12 +13996,13 @@ var ImageScale = ({ getReferenceRect }) => {
13660
13996
  startWidth: effectiveWidth,
13661
13997
  startHeight: effectiveHeight,
13662
13998
  side,
13663
- align: currentAlign
13999
+ align: currentAlign,
14000
+ aspectRatio: effectiveHeight > 0 ? effectiveWidth / effectiveHeight : 1
13664
14001
  };
13665
14002
  document.addEventListener("pointermove", handlePointerMove);
13666
14003
  document.addEventListener("pointerup", handlePointerUp);
13667
14004
  }, [getReferenceRect, currentWidth, currentHeight, currentAlign, setIsScaling]);
13668
- const handlePointerMove = useCallback13((e) => {
14005
+ const handlePointerMove = useCallback16((e) => {
13669
14006
  if (!dragRef.current) return;
13670
14007
  const { startX, startY, startWidth, startHeight, side, align } = dragRef.current;
13671
14008
  const state = useEditorStore.getState();
@@ -13673,7 +14010,35 @@ var ImageScale = ({ getReferenceRect }) => {
13673
14010
  if (!currentFocusIdx || !currentTemplate) return;
13674
14011
  const element = getValueByIdx(currentTemplate, currentFocusIdx);
13675
14012
  if (!element) return;
13676
- if (side === "left" || side === "right") {
14013
+ if (isCorner(side)) {
14014
+ const { aspectRatio } = dragRef.current;
14015
+ const deltaX = e.clientX - startX;
14016
+ const deltaY = e.clientY - startY;
14017
+ const signX = side.includes("left") ? -1 : 1;
14018
+ const signY = side.includes("top") ? -1 : 1;
14019
+ const alignMultiplier = align === "center" ? 2 : 1;
14020
+ const absDX = Math.abs(deltaX);
14021
+ const absDY = Math.abs(deltaY);
14022
+ let newWidth;
14023
+ let newHeight;
14024
+ if (absDX >= absDY) {
14025
+ newWidth = startWidth + signX * deltaX * alignMultiplier;
14026
+ newHeight = newWidth / aspectRatio;
14027
+ } else {
14028
+ newHeight = startHeight + signY * deltaY;
14029
+ newWidth = newHeight * aspectRatio;
14030
+ }
14031
+ const clampedWidth = Math.max(20, Math.min(600, newWidth));
14032
+ const clampedHeight = Math.max(20, Math.min(600, clampedWidth / aspectRatio));
14033
+ const finalWidth = clampedHeight * aspectRatio;
14034
+ updateElement(currentFocusIdx, {
14035
+ attributes: {
14036
+ ...element.attributes,
14037
+ width: `${Math.round(finalWidth)}px`,
14038
+ height: `${Math.round(clampedHeight)}px`
14039
+ }
14040
+ });
14041
+ } else if (side === "left" || side === "right") {
13677
14042
  const deltaX = e.clientX - startX;
13678
14043
  const alignMultiplier = align === "center" ? 2 : 1;
13679
14044
  const newWidth = side === "left" ? startWidth - deltaX * alignMultiplier : startWidth + deltaX * alignMultiplier;
@@ -13696,20 +14061,20 @@ var ImageScale = ({ getReferenceRect }) => {
13696
14061
  });
13697
14062
  }
13698
14063
  }, []);
13699
- const handlePointerUp = useCallback13(() => {
14064
+ const handlePointerUp = useCallback16(() => {
13700
14065
  setActiveSide(null);
13701
14066
  setIsScaling(false);
13702
14067
  dragRef.current = null;
13703
14068
  document.removeEventListener("pointermove", handlePointerMove);
13704
14069
  document.removeEventListener("pointerup", handlePointerUp);
13705
14070
  }, [handlePointerMove, setIsScaling]);
13706
- useEffect15(() => {
14071
+ useEffect11(() => {
13707
14072
  return () => {
13708
14073
  document.removeEventListener("pointermove", handlePointerMove);
13709
14074
  document.removeEventListener("pointerup", handlePointerUp);
13710
14075
  };
13711
14076
  }, [handlePointerMove, handlePointerUp]);
13712
- const virtualReference = useMemo14(() => ({
14077
+ const virtualReference = useMemo15(() => ({
13713
14078
  getBoundingClientRect: () => {
13714
14079
  const rect = getReferenceRect();
13715
14080
  if (!rect) {
@@ -13718,13 +14083,13 @@ var ImageScale = ({ getReferenceRect }) => {
13718
14083
  return rect;
13719
14084
  }
13720
14085
  }), [getReferenceRect]);
13721
- const { floatingStyles, refs, update } = useFloating7({
14086
+ const { floatingStyles, refs, update } = useFloating8({
13722
14087
  placement: "bottom-start",
13723
14088
  middleware: [
13724
- offset7(({ rects }) => -rects.reference.height)
14089
+ offset8(({ rects }) => -rects.reference.height)
13725
14090
  ]
13726
14091
  });
13727
- useEffect15(() => {
14092
+ useEffect11(() => {
13728
14093
  const rect = getReferenceRect();
13729
14094
  if (!rect || !refs.floating.current) return;
13730
14095
  refs.setPositionReference(virtualReference);
@@ -13751,9 +14116,13 @@ var ImageScale = ({ getReferenceRect }) => {
13751
14116
  }, [getReferenceRect, refs, update, virtualReference]);
13752
14117
  const showLeftHandle = currentAlign !== "left";
13753
14118
  const showRightHandle = currentAlign !== "right";
14119
+ const showTopLeft = currentAlign !== "left";
14120
+ const showTopRight = currentAlign !== "right";
14121
+ const showBottomLeft = currentAlign !== "left";
14122
+ const showBottomRight = currentAlign !== "right";
13754
14123
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13755
14124
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13756
- return /* @__PURE__ */ jsxs27(
14125
+ return /* @__PURE__ */ jsxs28(
13757
14126
  "div",
13758
14127
  {
13759
14128
  ref: refs.setFloating,
@@ -13765,33 +14134,61 @@ var ImageScale = ({ getReferenceRect }) => {
13765
14134
  },
13766
14135
  className: "relative pointer-events-none",
13767
14136
  children: [
13768
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx44(
14137
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx45(
13769
14138
  "div",
13770
14139
  {
13771
14140
  onPointerDown: (e) => handlePointerDown(e, "top"),
13772
14141
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13773
14142
  }
13774
14143
  ),
13775
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx44(
14144
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx45(
13776
14145
  "div",
13777
14146
  {
13778
14147
  onPointerDown: (e) => handlePointerDown(e, "right"),
13779
14148
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
13780
14149
  }
13781
14150
  ),
13782
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx44(
14151
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx45(
13783
14152
  "div",
13784
14153
  {
13785
14154
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
13786
14155
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
13787
14156
  }
13788
14157
  ),
13789
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx44(
14158
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx45(
13790
14159
  "div",
13791
14160
  {
13792
14161
  onPointerDown: (e) => handlePointerDown(e, "left"),
13793
14162
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -left-[4px] ${getHandleActiveClass("left")}`
13794
14163
  }
14164
+ ),
14165
+ showTopLeft && (activeSide === null || activeSide === "top-left") && /* @__PURE__ */ jsx45(
14166
+ "div",
14167
+ {
14168
+ onPointerDown: (e) => handlePointerDown(e, "top-left"),
14169
+ className: `w-[10px] h-[10px] cursor-nwse-resize ${handleBaseClass} -top-[5px] -left-[5px] ${getHandleActiveClass("top-left")}`
14170
+ }
14171
+ ),
14172
+ showTopRight && (activeSide === null || activeSide === "top-right") && /* @__PURE__ */ jsx45(
14173
+ "div",
14174
+ {
14175
+ onPointerDown: (e) => handlePointerDown(e, "top-right"),
14176
+ className: `w-[10px] h-[10px] cursor-nesw-resize ${handleBaseClass} -top-[5px] -right-[5px] ${getHandleActiveClass("top-right")}`
14177
+ }
14178
+ ),
14179
+ showBottomLeft && (activeSide === null || activeSide === "bottom-left") && /* @__PURE__ */ jsx45(
14180
+ "div",
14181
+ {
14182
+ onPointerDown: (e) => handlePointerDown(e, "bottom-left"),
14183
+ className: `w-[10px] h-[10px] cursor-nesw-resize ${handleBaseClass} -bottom-[5px] -left-[5px] ${getHandleActiveClass("bottom-left")}`
14184
+ }
14185
+ ),
14186
+ showBottomRight && (activeSide === null || activeSide === "bottom-right") && /* @__PURE__ */ jsx45(
14187
+ "div",
14188
+ {
14189
+ onPointerDown: (e) => handlePointerDown(e, "bottom-right"),
14190
+ className: `w-[10px] h-[10px] cursor-nwse-resize ${handleBaseClass} -bottom-[5px] -right-[5px] ${getHandleActiveClass("bottom-right")}`
14191
+ }
13795
14192
  )
13796
14193
  ]
13797
14194
  }
@@ -13799,22 +14196,22 @@ var ImageScale = ({ getReferenceRect }) => {
13799
14196
  };
13800
14197
 
13801
14198
  // src/core/editor/components/scaling/spacer-scale.tsx
13802
- import { useMemo as useMemo15, useEffect as useEffect16, useState as useState12, useRef as useRef8, useCallback as useCallback14 } from "react";
13803
- import { useFloating as useFloating8, offset as offset8, autoUpdate as autoUpdate7 } from "@floating-ui/react";
13804
- import { jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
14199
+ import { useMemo as useMemo16, useEffect as useEffect12, useState as useState13, useRef as useRef9, useCallback as useCallback17 } from "react";
14200
+ import { useFloating as useFloating9, offset as offset9, autoUpdate as autoUpdate7 } from "@floating-ui/react";
14201
+ import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
13805
14202
  var SpacerScale = ({ getReferenceRect }) => {
13806
- const [dimensions, setDimensions] = useState12({ width: 0, height: 0 });
13807
- const [activeSide, setActiveSide] = useState12(null);
14203
+ const [dimensions, setDimensions] = useState13({ width: 0, height: 0 });
14204
+ const [activeSide, setActiveSide] = useState13(null);
13808
14205
  const { focusIdx, template, setIsScaling } = useEditorStore();
13809
- const currentHeight = useMemo15(() => {
14206
+ const currentHeight = useMemo16(() => {
13810
14207
  if (!focusIdx || !template) return 12;
13811
14208
  const element = getValueByIdx(template, focusIdx);
13812
14209
  const rawHeight = element?.attributes?.height;
13813
14210
  const parsedHeight = rawHeight ? parseFloat(rawHeight.replace("px", "")) : 12;
13814
14211
  return isNaN(parsedHeight) ? 12 : Math.max(12, Math.min(200, parsedHeight));
13815
14212
  }, [focusIdx, template]);
13816
- const dragRef = useRef8(null);
13817
- const handlePointerDown = useCallback14((e, side) => {
14213
+ const dragRef = useRef9(null);
14214
+ const handlePointerDown = useCallback17((e, side) => {
13818
14215
  e.preventDefault();
13819
14216
  e.stopPropagation();
13820
14217
  if (document.activeElement instanceof HTMLElement) {
@@ -13830,7 +14227,7 @@ var SpacerScale = ({ getReferenceRect }) => {
13830
14227
  document.addEventListener("pointermove", handlePointerMove);
13831
14228
  document.addEventListener("pointerup", handlePointerUp);
13832
14229
  }, [currentHeight, setIsScaling]);
13833
- const handlePointerMove = useCallback14((e) => {
14230
+ const handlePointerMove = useCallback17((e) => {
13834
14231
  if (!dragRef.current) return;
13835
14232
  const { startY, startHeight, side } = dragRef.current;
13836
14233
  const state = useEditorStore.getState();
@@ -13848,20 +14245,20 @@ var SpacerScale = ({ getReferenceRect }) => {
13848
14245
  }
13849
14246
  });
13850
14247
  }, []);
13851
- const handlePointerUp = useCallback14(() => {
14248
+ const handlePointerUp = useCallback17(() => {
13852
14249
  setActiveSide(null);
13853
14250
  setIsScaling(false);
13854
14251
  dragRef.current = null;
13855
14252
  document.removeEventListener("pointermove", handlePointerMove);
13856
14253
  document.removeEventListener("pointerup", handlePointerUp);
13857
14254
  }, [handlePointerMove, setIsScaling]);
13858
- useEffect16(() => {
14255
+ useEffect12(() => {
13859
14256
  return () => {
13860
14257
  document.removeEventListener("pointermove", handlePointerMove);
13861
14258
  document.removeEventListener("pointerup", handlePointerUp);
13862
14259
  };
13863
14260
  }, [handlePointerMove, handlePointerUp]);
13864
- const virtualReference = useMemo15(() => ({
14261
+ const virtualReference = useMemo16(() => ({
13865
14262
  getBoundingClientRect: () => {
13866
14263
  const rect = getReferenceRect();
13867
14264
  if (!rect) {
@@ -13870,13 +14267,13 @@ var SpacerScale = ({ getReferenceRect }) => {
13870
14267
  return rect;
13871
14268
  }
13872
14269
  }), [getReferenceRect]);
13873
- const { floatingStyles, refs, update } = useFloating8({
14270
+ const { floatingStyles, refs, update } = useFloating9({
13874
14271
  placement: "bottom-start",
13875
14272
  middleware: [
13876
- offset8(({ rects }) => -rects.reference.height)
14273
+ offset9(({ rects }) => -rects.reference.height)
13877
14274
  ]
13878
14275
  });
13879
- useEffect16(() => {
14276
+ useEffect12(() => {
13880
14277
  const rect = getReferenceRect();
13881
14278
  if (!rect || !refs.floating.current) return;
13882
14279
  refs.setPositionReference(virtualReference);
@@ -13903,7 +14300,7 @@ var SpacerScale = ({ getReferenceRect }) => {
13903
14300
  }, [getReferenceRect, refs, update, virtualReference]);
13904
14301
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13905
14302
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13906
- return /* @__PURE__ */ jsxs28(
14303
+ return /* @__PURE__ */ jsxs29(
13907
14304
  "div",
13908
14305
  {
13909
14306
  ref: refs.setFloating,
@@ -13915,14 +14312,14 @@ var SpacerScale = ({ getReferenceRect }) => {
13915
14312
  },
13916
14313
  className: "relative pointer-events-none",
13917
14314
  children: [
13918
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx45(
14315
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx46(
13919
14316
  "div",
13920
14317
  {
13921
14318
  onPointerDown: (e) => handlePointerDown(e, "top"),
13922
14319
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13923
14320
  }
13924
14321
  ),
13925
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx45(
14322
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx46(
13926
14323
  "div",
13927
14324
  {
13928
14325
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
@@ -13935,19 +14332,19 @@ var SpacerScale = ({ getReferenceRect }) => {
13935
14332
  };
13936
14333
 
13937
14334
  // src/core/editor/components/scaling/column-scale.tsx
13938
- import { useMemo as useMemo16, useEffect as useEffect17, useState as useState13, useRef as useRef9, useCallback as useCallback15 } from "react";
13939
- import { Fragment as Fragment17, jsx as jsx46 } from "react/jsx-runtime";
14335
+ import { useMemo as useMemo17, useEffect as useEffect13, useState as useState14, useRef as useRef10, useCallback as useCallback18 } from "react";
14336
+ import { Fragment as Fragment17, jsx as jsx47 } from "react/jsx-runtime";
13940
14337
  var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13941
- const [activeDivider, setActiveDivider] = useState13(null);
13942
- const [columnRects, setColumnRects] = useState13([]);
14338
+ const [activeDivider, setActiveDivider] = useState14(null);
14339
+ const [columnRects, setColumnRects] = useState14([]);
13943
14340
  const { template, setIsScaling, setFocusIdx, stopTextEditing } = useEditorStore();
13944
- const columnWidths = useMemo16(() => {
14341
+ const columnWidths = useMemo17(() => {
13945
14342
  if (!template) return [];
13946
14343
  const sectionColumn = getValueByIdx(template, sectionColumnIdx);
13947
14344
  return sectionColumn?.data?.value?.columnWidths || [];
13948
14345
  }, [template, sectionColumnIdx]);
13949
- const dragRef = useRef9(null);
13950
- const updateColumnRects = useCallback15(() => {
14346
+ const dragRef = useRef10(null);
14347
+ const updateColumnRects = useCallback18(() => {
13951
14348
  if (!shadowRoot) return;
13952
14349
  const allColumns = shadowRoot.querySelectorAll(".node-type-column");
13953
14350
  const matchingColumns = [];
@@ -13979,7 +14376,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13979
14376
  });
13980
14377
  setColumnRects(rects);
13981
14378
  }, [shadowRoot, sectionColumnIdx]);
13982
- useEffect17(() => {
14379
+ useEffect13(() => {
13983
14380
  updateColumnRects();
13984
14381
  let animationId;
13985
14382
  const updateLoop = () => {
@@ -13992,7 +14389,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13992
14389
  const parseWidth = (width) => {
13993
14390
  return parseFloat(width.replace("%", ""));
13994
14391
  };
13995
- const handlePointerDown = useCallback15((e, dividerIndex) => {
14392
+ const handlePointerDown = useCallback18((e, dividerIndex) => {
13996
14393
  e.preventDefault();
13997
14394
  e.stopPropagation();
13998
14395
  stopTextEditing();
@@ -14018,7 +14415,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14018
14415
  document.addEventListener("pointermove", handlePointerMove);
14019
14416
  document.addEventListener("pointerup", handlePointerUp);
14020
14417
  }, [columnRects, columnWidths, setIsScaling]);
14021
- const handlePointerMove = useCallback15((e) => {
14418
+ const handlePointerMove = useCallback18((e) => {
14022
14419
  if (!dragRef.current) return;
14023
14420
  const { startX, leftColIndex, rightColIndex, startLeftWidth, startRightWidth, sectionWidth, allWidths } = dragRef.current;
14024
14421
  const deltaX = e.clientX - startX;
@@ -14052,14 +14449,14 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14052
14449
  }
14053
14450
  });
14054
14451
  }, [sectionColumnIdx]);
14055
- const handlePointerUp = useCallback15(() => {
14452
+ const handlePointerUp = useCallback18(() => {
14056
14453
  setActiveDivider(null);
14057
14454
  setIsScaling(false);
14058
14455
  dragRef.current = null;
14059
14456
  document.removeEventListener("pointermove", handlePointerMove);
14060
14457
  document.removeEventListener("pointerup", handlePointerUp);
14061
14458
  }, [handlePointerMove, setIsScaling]);
14062
- useEffect17(() => {
14459
+ useEffect13(() => {
14063
14460
  return () => {
14064
14461
  document.removeEventListener("pointermove", handlePointerMove);
14065
14462
  document.removeEventListener("pointerup", handlePointerUp);
@@ -14070,7 +14467,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14070
14467
  }
14071
14468
  const handleBaseClass = "bg-background shadow-md border rounded-full touch-none select-none pointer-events-auto";
14072
14469
  const getHandleActiveClass = (index) => activeDivider === index ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
14073
- return /* @__PURE__ */ jsx46(Fragment17, { children: columnRects.slice(0, -1).map((rect, index) => {
14470
+ return /* @__PURE__ */ jsx47(Fragment17, { children: columnRects.slice(0, -1).map((rect, index) => {
14074
14471
  const nextRect = columnRects[index + 1];
14075
14472
  const handleLeft = rect.right;
14076
14473
  const handleTop = Math.min(rect.top, nextRect.top);
@@ -14078,7 +14475,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14078
14475
  if (activeDivider !== null && activeDivider !== index) {
14079
14476
  return null;
14080
14477
  }
14081
- return /* @__PURE__ */ jsx46(
14478
+ return /* @__PURE__ */ jsx47(
14082
14479
  "div",
14083
14480
  {
14084
14481
  onPointerDown: (e) => handlePointerDown(e, index),
@@ -14098,9 +14495,9 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14098
14495
  };
14099
14496
 
14100
14497
  // src/core/editor/hooks/use-undo-redo-keyboard.ts
14101
- import { useEffect as useEffect18 } from "react";
14498
+ import { useEffect as useEffect14 } from "react";
14102
14499
  function useUndoRedoKeyboard() {
14103
- useEffect18(() => {
14500
+ useEffect14(() => {
14104
14501
  const handler = (e) => {
14105
14502
  const isMeta = e.metaKey || e.ctrlKey;
14106
14503
  if (!isMeta || e.key.toLowerCase() !== "z") return;
@@ -14122,9 +14519,9 @@ function useUndoRedoKeyboard() {
14122
14519
 
14123
14520
  // src/components/ui/spinner.tsx
14124
14521
  import { Loader2Icon as Loader2Icon2 } from "lucide-react";
14125
- import { jsx as jsx47 } from "react/jsx-runtime";
14522
+ import { jsx as jsx48 } from "react/jsx-runtime";
14126
14523
  function Spinner({ className, ...props }) {
14127
- return /* @__PURE__ */ jsx47(
14524
+ return /* @__PURE__ */ jsx48(
14128
14525
  Loader2Icon2,
14129
14526
  {
14130
14527
  role: "status",
@@ -14136,10 +14533,10 @@ function Spinner({ className, ...props }) {
14136
14533
  }
14137
14534
 
14138
14535
  // src/core/editor/components/preview.tsx
14139
- import { EyeIcon } from "lucide-react";
14536
+ import { EyeIcon, SendIcon, Monitor, Smartphone } from "lucide-react";
14140
14537
 
14141
14538
  // src/render/useMjmlCompiler.ts
14142
- import { useState as useState14, useCallback as useCallback16 } from "react";
14539
+ import { useState as useState15, useCallback as useCallback19 } from "react";
14143
14540
  async function compileMjml(mjml) {
14144
14541
  console.log("Compiling MJML", mjml);
14145
14542
  const response = await fetch("/api/mrender", {
@@ -14156,14 +14553,101 @@ async function compileMjml(mjml) {
14156
14553
  }
14157
14554
 
14158
14555
  // src/core/editor/components/preview.tsx
14159
- import { useEffect as useEffect19, useState as useState15, useRef as useRef10 } from "react";
14160
- import { jsx as jsx48, jsxs as jsxs29 } from "react/jsx-runtime";
14556
+ import { useEffect as useEffect15, useState as useState16, useRef as useRef11 } from "react";
14557
+
14558
+ // src/validate/helpers.ts
14559
+ var MERGE_FIELD_REGEX2 = /\{\{([a-zA-Z_][a-zA-Z0-9_]*)\}\}/g;
14560
+ function extractMergeFields(node) {
14561
+ const fields = [];
14562
+ if (!node || typeof node !== "object") return fields;
14563
+ const content = node?.data?.value?.content;
14564
+ if (typeof content === "string") {
14565
+ let match;
14566
+ MERGE_FIELD_REGEX2.lastIndex = 0;
14567
+ while ((match = MERGE_FIELD_REGEX2.exec(content)) !== null) {
14568
+ fields.push(match[1]);
14569
+ }
14570
+ }
14571
+ if (Array.isArray(node.children)) {
14572
+ for (const child of node.children) {
14573
+ fields.push(...extractMergeFields(child));
14574
+ }
14575
+ }
14576
+ if (Array.isArray(node.content)) {
14577
+ for (const page of node.content) {
14578
+ fields.push(...extractMergeFields(page));
14579
+ }
14580
+ }
14581
+ return fields;
14582
+ }
14583
+ function extractEmptyLinks(node) {
14584
+ const results = [];
14585
+ if (!node || typeof node !== "object") return results;
14586
+ if (node.type === "button" || node.type === "social-item") {
14587
+ const href = node.attributes?.href;
14588
+ if (!href || href.trim() === "") {
14589
+ const label = node.type === "button" ? node.data?.value?.content || "Untitled Button" : node.attributes?.alt || node.data?.value?.socialType || "Social Link";
14590
+ results.push({ type: node.type, label });
14591
+ }
14592
+ }
14593
+ if (Array.isArray(node.children)) {
14594
+ for (const child of node.children) {
14595
+ results.push(...extractEmptyLinks(child));
14596
+ }
14597
+ }
14598
+ if (Array.isArray(node.content)) {
14599
+ for (const page of node.content) {
14600
+ results.push(...extractEmptyLinks(page));
14601
+ }
14602
+ }
14603
+ return results;
14604
+ }
14605
+
14606
+ // src/validate/index.ts
14607
+ var PROPERTY_CARD_TYPES = /* @__PURE__ */ new Set(["property-card", "property-card-single-two", "property-card-triple-item"]);
14608
+ function countPlaceholderPropertyImages(node) {
14609
+ let count = 0;
14610
+ if (!node || typeof node !== "object") return count;
14611
+ if (PROPERTY_CARD_TYPES.has(node.type)) {
14612
+ const imageSrc = node.attributes?.["image-src"];
14613
+ if (!imageSrc || imageSrc === DEFAULT_PROPERTY_PLACEHOLDER_IMAGE) {
14614
+ count++;
14615
+ }
14616
+ }
14617
+ if (Array.isArray(node.children)) {
14618
+ for (const child of node.children) {
14619
+ count += countPlaceholderPropertyImages(child);
14620
+ }
14621
+ }
14622
+ if (Array.isArray(node.content)) {
14623
+ for (const page of node.content) {
14624
+ count += countPlaceholderPropertyImages(page);
14625
+ }
14626
+ }
14627
+ return count;
14628
+ }
14629
+ function validate_editor_onPreview(template, mergeFields) {
14630
+ const usedFields = [...new Set(extractMergeFields(template))];
14631
+ const validValues = new Set(mergeFields.map((f) => f.value));
14632
+ const invalid_merge_fields = usedFields.filter((field) => !validValues.has(field));
14633
+ const missing_links = extractEmptyLinks(template);
14634
+ const placeholder_property_images = countPlaceholderPropertyImages(template);
14635
+ const templateSize = new Blob([JSON.stringify(template)]).size;
14636
+ const is_over_size_limit = templateSize > 50 * 1024;
14637
+ return { invalid_merge_fields, missing_links, is_over_size_limit, placeholder_property_images };
14638
+ }
14639
+
14640
+ // src/core/editor/components/preview.tsx
14641
+ import { jsx as jsx49, jsxs as jsxs30 } from "react/jsx-runtime";
14161
14642
  function Preview() {
14162
- const { template, setPreviewMode, previewMode, isPaidLevel } = useEditorStore();
14163
- const [html, setHtml] = useState15("");
14164
- const [isLoading, setIsLoading] = useState15(false);
14165
- const lastTemplateRef = useRef10("");
14166
- useEffect19(() => {
14643
+ const { template, setPreviewMode, previewMode, isPaidLevel, mergeFields } = useEditorStore();
14644
+ const [html, setHtml] = useState16("");
14645
+ const [isLoading, setIsLoading] = useState16(false);
14646
+ const lastTemplateRef = useRef11("");
14647
+ const [deviceMode, setDeviceMode] = useState16("desktop");
14648
+ const [preview_validations, setPreviewValidations] = useState16({ invalid_merge_fields: [], missing_links: [], is_over_size_limit: false, placeholder_property_images: 0 });
14649
+ const [mjmlErrors, setMjmlErrors] = useState16([]);
14650
+ useEffect15(() => {
14167
14651
  if (typeof window === "undefined" || !previewMode) {
14168
14652
  if (!previewMode) {
14169
14653
  setHtml("");
@@ -14177,56 +14661,165 @@ function Preview() {
14177
14661
  }
14178
14662
  lastTemplateRef.current = templateString;
14179
14663
  setIsLoading(true);
14664
+ const validatePreview = () => {
14665
+ const validations = validate_editor_onPreview(template, mergeFields);
14666
+ setPreviewValidations(validations);
14667
+ };
14180
14668
  const convertMjml = async () => {
14181
14669
  try {
14182
14670
  const mjmlString = json2mjml(template, "production", { isPaidLevel });
14183
14671
  console.log("MJML string:", mjmlString);
14184
14672
  const result = await compileMjml(mjmlString);
14673
+ console.log("MJML errors:", result);
14674
+ setMjmlErrors(result.errors ?? []);
14185
14675
  if (result.errors?.length > 0) {
14186
- console.warn("MJML warnings:", result.errors);
14676
+ console.warn("MJML warnings 1:", result.errors);
14187
14677
  }
14188
14678
  console.log(result.html);
14189
14679
  setHtml(result.html);
14190
14680
  } catch (error) {
14191
14681
  console.error("MJML compilation error:", error);
14682
+ setMjmlErrors([]);
14192
14683
  setHtml('<p style="color: red; padding: 20px;">Error generating preview</p>');
14193
14684
  } finally {
14194
14685
  setIsLoading(false);
14195
14686
  }
14196
14687
  };
14688
+ validatePreview();
14197
14689
  convertMjml();
14198
14690
  }, [template, previewMode]);
14199
- return /* @__PURE__ */ jsxs29(Dialog, { open: previewMode, onOpenChange: setPreviewMode, children: [
14200
- /* @__PURE__ */ jsxs29(Tooltip, { children: [
14201
- /* @__PURE__ */ jsx48(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx48(
14691
+ const hasValidations = preview_validations.invalid_merge_fields.length > 0 || preview_validations.missing_links.length > 0 || preview_validations.is_over_size_limit || preview_validations.placeholder_property_images > 0 || mjmlErrors.length > 0;
14692
+ return /* @__PURE__ */ jsxs30(Dialog, { open: previewMode, onOpenChange: setPreviewMode, children: [
14693
+ /* @__PURE__ */ jsxs30(Tooltip, { children: [
14694
+ /* @__PURE__ */ jsx49(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx49(
14202
14695
  Button,
14203
14696
  {
14204
14697
  variant: "ghost",
14205
14698
  className: "shadow-none transition-none cursor-pointer",
14206
14699
  size: "icon",
14207
14700
  onClick: () => setPreviewMode(true),
14208
- children: /* @__PURE__ */ jsx48(EyeIcon, {})
14701
+ children: /* @__PURE__ */ jsx49(EyeIcon, {})
14209
14702
  }
14210
14703
  ) }),
14211
- /* @__PURE__ */ jsx48(TooltipContent, { side: "bottom", className: "z-51", children: "Preview" })
14704
+ /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", className: "z-51", children: "Preview" })
14212
14705
  ] }),
14213
- /* @__PURE__ */ jsxs29(DialogContent, { className: "max-w-[1200px] sm:max-w-[1200px]", children: [
14214
- /* @__PURE__ */ jsx48(DialogTitle, { children: "Preview" }),
14215
- /* @__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]" }) })
14216
- ] })
14706
+ /* @__PURE__ */ jsxs30(
14707
+ DialogContent,
14708
+ {
14709
+ showCloseButton: true,
14710
+ className: "flex flex-col !fixed !top-14 !left-12 !right-12 !bottom-0 !transform-none !translate-x-0 !translate-y-0 !w-auto !h-auto !max-w-none !max-h-none rounded-b-none p-0 gap-0",
14711
+ children: [
14712
+ /* @__PURE__ */ jsx49(DialogHeader, { className: "border-b p-4", children: /* @__PURE__ */ jsx49(DialogTitle, { children: "Preview" }) }),
14713
+ /* @__PURE__ */ jsxs30("div", { className: "flex gap-2 justify-between border-b p-4", children: [
14714
+ /* @__PURE__ */ jsx49("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxs30(Button, { variant: "ghost", onClick: () => {
14715
+ }, children: [
14716
+ /* @__PURE__ */ jsx49(SendIcon, { className: "w-4 h-4" }),
14717
+ "Send a Test Email"
14718
+ ] }) }),
14719
+ /* @__PURE__ */ jsxs30("div", { className: "flex gap-2", children: [
14720
+ /* @__PURE__ */ jsxs30(
14721
+ Button,
14722
+ {
14723
+ variant: deviceMode === "desktop" ? "default" : "ghost",
14724
+ onClick: () => setDeviceMode("desktop"),
14725
+ className: "gap-2 cursor-pointer",
14726
+ children: [
14727
+ /* @__PURE__ */ jsx49(Monitor, { className: "w-4 h-4" }),
14728
+ "Desktop"
14729
+ ]
14730
+ }
14731
+ ),
14732
+ /* @__PURE__ */ jsxs30(
14733
+ Button,
14734
+ {
14735
+ variant: deviceMode === "mobile" ? "default" : "ghost",
14736
+ onClick: () => setDeviceMode("mobile"),
14737
+ className: "gap-2 cursor-pointer",
14738
+ children: [
14739
+ /* @__PURE__ */ jsx49(Smartphone, { className: "w-4 h-4" }),
14740
+ "Mobile"
14741
+ ]
14742
+ }
14743
+ )
14744
+ ] })
14745
+ ] }),
14746
+ /* @__PURE__ */ jsxs30("div", { className: "flex flex-1 overflow-hidden", children: [
14747
+ /* @__PURE__ */ jsx49(
14748
+ "div",
14749
+ {
14750
+ className: "flex-1 flex items-start justify-center overflow-auto w-full",
14751
+ style: { backgroundColor: template?.content?.[0]?.attributes?.["background-color"] || "#965D5D" },
14752
+ children: isLoading ? /* @__PURE__ */ jsx49("div", { className: "flex items-center justify-center h-full w-full", children: /* @__PURE__ */ jsx49("p", { children: "Generating preview..." }) }) : /* @__PURE__ */ jsx49(
14753
+ "div",
14754
+ {
14755
+ className: "flex items-center justify-center bg-white transition-all duration-300 h-full w-full",
14756
+ children: /* @__PURE__ */ jsx49(
14757
+ "iframe",
14758
+ {
14759
+ srcDoc: html,
14760
+ className: "w-full border-0 transition-all duration-200",
14761
+ style: { height: "100%", minHeight: "600px", width: deviceMode === "desktop" ? "100%" : "360px", maxWidth: deviceMode === "desktop" ? "100%" : "360px" },
14762
+ title: "Email Preview",
14763
+ sandbox: "allow-same-origin"
14764
+ }
14765
+ )
14766
+ }
14767
+ )
14768
+ }
14769
+ ),
14770
+ hasValidations && /* @__PURE__ */ jsxs30("div", { className: "w-[300px] border-l p-4 overflow-y-auto flex flex-col gap-4", children: [
14771
+ mjmlErrors.length > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border border-red-600 p-2", children: [
14772
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold text-red-600", children: "MJML Errors" }),
14773
+ /* @__PURE__ */ jsx49("p", { className: "text-sm mt-1 text-red-600", children: "The following errors occurred during email compilation:" }),
14774
+ /* @__PURE__ */ jsx49("ul", { className: "flex flex-col gap-2 my-2", children: mjmlErrors.map((err, i) => /* @__PURE__ */ jsxs30("li", { className: "text-sm font-mono bg-red-100 rounded border border-red-200 text-red-700 p-2", children: [
14775
+ /* @__PURE__ */ jsx49("span", { className: "font-semibold", children: err.tagName }),
14776
+ " (line ",
14777
+ err.line,
14778
+ "): ",
14779
+ err.message
14780
+ ] }, i)) }),
14781
+ /* @__PURE__ */ jsx49("p", { className: "text-xs text-red-500 italic", children: "You may need to contact support to fix these errors. You'll still be able to send the email, but it may not look as expected." })
14782
+ ] }),
14783
+ preview_validations.is_over_size_limit && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border border-red-300 p-2", children: [
14784
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold text-red-600", children: "Template Too Large" }),
14785
+ /* @__PURE__ */ jsx49("p", { className: "text-sm mt-1 text-red-600", children: "This template exceeds the size limit. Reduce your content to use this template, otherwise it will be auto-trimmed." })
14786
+ ] }),
14787
+ preview_validations.placeholder_property_images > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border p-2", children: [
14788
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold", children: "Placeholder Property Image" }),
14789
+ /* @__PURE__ */ jsx49("p", { className: "text-sm mt-1", children: preview_validations.placeholder_property_images === 1 ? "1 property card is still using the default placeholder image. Upload an image of the property." : `${preview_validations.placeholder_property_images} property cards are still using the default placeholder image. Upload images for each property.` })
14790
+ ] }),
14791
+ preview_validations.invalid_merge_fields.length > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border p-2", children: [
14792
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold", children: "Invalid Merge Fields" }),
14793
+ /* @__PURE__ */ jsx49("p", { className: "text-sm mt-1", children: "The following merge fields are used in the template but don't exist in your merge field data:" }),
14794
+ /* @__PURE__ */ jsx49("ul", { className: "flex flex-wrap gap-2 mt-2 space-y-1", children: preview_validations.invalid_merge_fields.map((field) => /* @__PURE__ */ jsx49("li", { className: "text-sm font-mono flex items-center justify-center no-wrap whitespace-nowrap bg-background text-nowrap text-ellipsis overflow-hidden rounded border border-border text-black p-2 h-[30px]", children: `{{${field}}}` }, field)) })
14795
+ ] }),
14796
+ preview_validations.missing_links.length > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border p-2", children: [
14797
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold", children: "Missing Links" }),
14798
+ /* @__PURE__ */ jsx49("p", { className: "text-sm mt-1", children: "The following elements have no link set:" }),
14799
+ /* @__PURE__ */ jsx49("ul", { className: "flex flex-wrap gap-2 mt-2", children: preview_validations.missing_links.map((item, i) => /* @__PURE__ */ jsxs30("li", { className: "text-sm w-full font-mono flex items-center justify-start no-wrap whitespace-nowrap bg-background text-nowrap text-ellipsis overflow-hidden rounded border border-border text-black p-2 h-[30px]", children: [
14800
+ item.type === "button" ? "Button" : "Social",
14801
+ ": ",
14802
+ item.label
14803
+ ] }, i)) })
14804
+ ] })
14805
+ ] })
14806
+ ] })
14807
+ ]
14808
+ }
14809
+ )
14217
14810
  ] });
14218
14811
  }
14219
14812
 
14220
14813
  // src/core/editor/components/history.tsx
14221
14814
  import { Redo2Icon, Undo2Icon } from "lucide-react";
14222
- import { Fragment as Fragment18, jsx as jsx49, jsxs as jsxs30 } from "react/jsx-runtime";
14815
+ import { Fragment as Fragment18, jsx as jsx50, jsxs as jsxs31 } from "react/jsx-runtime";
14223
14816
  var History = () => {
14224
14817
  const { undo, redo } = useEditorStore();
14225
14818
  const canUndo = useEditorStore((s) => s.historyIndex > 0);
14226
14819
  const canRedo = useEditorStore((s) => s.historyIndex < s.history.length - 1);
14227
- return /* @__PURE__ */ jsxs30(Fragment18, { children: [
14228
- /* @__PURE__ */ jsxs30(Tooltip, { children: [
14229
- /* @__PURE__ */ jsx49(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx49(
14820
+ return /* @__PURE__ */ jsxs31(Fragment18, { children: [
14821
+ /* @__PURE__ */ jsxs31(Tooltip, { children: [
14822
+ /* @__PURE__ */ jsx50(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(
14230
14823
  Button,
14231
14824
  {
14232
14825
  variant: "ghost",
@@ -14234,13 +14827,13 @@ var History = () => {
14234
14827
  size: "icon",
14235
14828
  disabled: !canUndo,
14236
14829
  onClick: undo,
14237
- children: /* @__PURE__ */ jsx49(Undo2Icon, {})
14830
+ children: /* @__PURE__ */ jsx50(Undo2Icon, {})
14238
14831
  }
14239
14832
  ) }),
14240
- /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", children: "Undo (Ctrl+Z)" })
14833
+ /* @__PURE__ */ jsx50(TooltipContent, { side: "bottom", children: "Undo (Ctrl+Z)" })
14241
14834
  ] }),
14242
- /* @__PURE__ */ jsxs30(Tooltip, { children: [
14243
- /* @__PURE__ */ jsx49(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx49(
14835
+ /* @__PURE__ */ jsxs31(Tooltip, { children: [
14836
+ /* @__PURE__ */ jsx50(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(
14244
14837
  Button,
14245
14838
  {
14246
14839
  variant: "ghost",
@@ -14248,16 +14841,16 @@ var History = () => {
14248
14841
  size: "icon",
14249
14842
  disabled: !canRedo,
14250
14843
  onClick: redo,
14251
- children: /* @__PURE__ */ jsx49(Redo2Icon, {})
14844
+ children: /* @__PURE__ */ jsx50(Redo2Icon, {})
14252
14845
  }
14253
14846
  ) }),
14254
- /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", children: "Redo (Ctrl+Shift+Z)" })
14847
+ /* @__PURE__ */ jsx50(TooltipContent, { side: "bottom", children: "Redo (Ctrl+Shift+Z)" })
14255
14848
  ] })
14256
14849
  ] });
14257
14850
  };
14258
14851
 
14259
14852
  // src/core/index.tsx
14260
- import { jsx as jsx50, jsxs as jsxs31 } from "react/jsx-runtime";
14853
+ import { jsx as jsx51, jsxs as jsxs32 } from "react/jsx-runtime";
14261
14854
  var MAILLOW_EMAIL_EDITOR_VERSION = "0.0.1";
14262
14855
  function getSectionColumnIdx(idx, template) {
14263
14856
  let current = idx;
@@ -14293,6 +14886,20 @@ function getCompanyFooterSection(template) {
14293
14886
  }
14294
14887
  return null;
14295
14888
  }
14889
+ function restoreImagePreview(shadowRoot, targetIdx, originalSrc) {
14890
+ const targetEl = shadowRoot.querySelector(`.node-idx-${CSS.escape(targetIdx)}`);
14891
+ if (!targetEl) return;
14892
+ const bgEl = targetEl.querySelector("td[background], th[background]");
14893
+ if (bgEl) {
14894
+ bgEl.setAttribute("background", originalSrc);
14895
+ bgEl.style.backgroundImage = `url(${originalSrc})`;
14896
+ return;
14897
+ }
14898
+ const img = targetEl.querySelector("img");
14899
+ if (img) {
14900
+ img.src = originalSrc;
14901
+ }
14902
+ }
14296
14903
  function Editor({ setEditorLoading }) {
14297
14904
  useUndoRedoKeyboard();
14298
14905
  const template = useEditorStore((state) => state.template);
@@ -14323,29 +14930,32 @@ function Editor({ setEditorLoading }) {
14323
14930
  const startTextEditing = useEditorStore((state) => state.startTextEditing);
14324
14931
  const pendingTextEditRequest = useEditorStore((state) => state.pendingTextEditRequest);
14325
14932
  const clearPendingTextEditRequest = useEditorStore((state) => state.clearPendingTextEditRequest);
14326
- const [renderData, setRenderData] = useState16(null);
14327
- const [isEditing, setIsEditing] = useState16(false);
14328
- const [dropIndicator, setDropIndicator] = useState16(null);
14329
- const [dropTargetIdx, setDropTargetIdx] = useState16(null);
14330
- const shadowRootRef = useRef11(null);
14331
- const [hasSelectedElement, setHasSelectedElement] = useState16(false);
14332
- const dragParentIdxRef = useRef11(null);
14333
- const dragPositionIndexRef = useRef11(0);
14334
- const createNewSectionRef = useRef11(false);
14335
- const splitAtParagraphRef = useRef11(null);
14336
- const isHorizontalDropRef = useRef11(false);
14337
- const horizontalDropPositionRef = useRef11(null);
14338
- const isSplitSectionDropRef = useRef11(false);
14339
- const splitSectionAtElementRef = useRef11(null);
14340
- const templateCacheRef = useRef11(null);
14341
- const parentSectionCacheRef = useRef11(/* @__PURE__ */ new Map());
14342
- const sectionElementCacheRef = useRef11(/* @__PURE__ */ new Map());
14343
- const sectionRectCacheRef = useRef11(/* @__PURE__ */ new Map());
14344
- const companyFooterCacheRef = useRef11(void 0);
14345
- const lastSyncedTemplateRef = useRef11(null);
14346
- const prevTextEditingIdxRef = useRef11(null);
14347
- const lastRenderSyncNeededRef = useRef11(0);
14348
- useEffect20(() => {
14933
+ const [renderData, setRenderData] = useState17(null);
14934
+ const [isEditing, setIsEditing] = useState17(false);
14935
+ const [dropIndicator, setDropIndicator] = useState17(null);
14936
+ const [dropTargetIdx, setDropTargetIdx] = useState17(null);
14937
+ const shadowRootRef = useRef12(null);
14938
+ const [hasSelectedElement, setHasSelectedElement] = useState17(false);
14939
+ const dragParentIdxRef = useRef12(null);
14940
+ const dragPositionIndexRef = useRef12(0);
14941
+ const createNewSectionRef = useRef12(false);
14942
+ const splitAtParagraphRef = useRef12(null);
14943
+ const isHorizontalDropRef = useRef12(false);
14944
+ const horizontalDropPositionRef = useRef12(null);
14945
+ const isSplitSectionDropRef = useRef12(false);
14946
+ const splitSectionAtElementRef = useRef12(null);
14947
+ const templateCacheRef = useRef12(null);
14948
+ const parentSectionCacheRef = useRef12(/* @__PURE__ */ new Map());
14949
+ const sectionElementCacheRef = useRef12(/* @__PURE__ */ new Map());
14950
+ const sectionRectCacheRef = useRef12(/* @__PURE__ */ new Map());
14951
+ const companyFooterCacheRef = useRef12(void 0);
14952
+ const lastSyncedTemplateRef = useRef12(null);
14953
+ const prevTextEditingIdxRef = useRef12(null);
14954
+ const lastRenderSyncNeededRef = useRef12(0);
14955
+ const hasNotifiedLoadedRef = useRef12(false);
14956
+ const imageReplaceTargetRef = useRef12(null);
14957
+ const imagePreviewOriginalSrcRef = useRef12(null);
14958
+ useEffect16(() => {
14349
14959
  const currentIdx = textEditing?.idx ?? null;
14350
14960
  const prevIdx = prevTextEditingIdxRef.current;
14351
14961
  const switchedTarget = currentIdx !== null && prevIdx !== null && currentIdx !== prevIdx;
@@ -14360,16 +14970,15 @@ function Editor({ setEditorLoading }) {
14360
14970
  }
14361
14971
  if (!isEqual(template, renderData)) {
14362
14972
  setRenderData(cloneDeep2(template));
14973
+ if (!hasNotifiedLoadedRef.current && setEditorLoading) {
14974
+ hasNotifiedLoadedRef.current = true;
14975
+ setEditorLoading(false);
14976
+ }
14363
14977
  }
14364
14978
  lastSyncedTemplateRef.current = template;
14365
14979
  }
14366
- }, [template, renderData, isEditing, textEditing, renderSyncNeeded]);
14367
- useEffect20(() => {
14368
- if (renderData && setEditorLoading) {
14369
- setEditorLoading(false);
14370
- }
14371
- }, [renderData, setEditorLoading]);
14372
- useEffect20(() => {
14980
+ }, [template, renderData, isEditing, textEditing, renderSyncNeeded, setEditorLoading]);
14981
+ useEffect16(() => {
14373
14982
  if (!pendingTextEditRequest || !shadowRootRef.current) return;
14374
14983
  const { idx, cursorPosition } = pendingTextEditRequest;
14375
14984
  const blockNode = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
@@ -14418,7 +15027,7 @@ function Editor({ setEditorLoading }) {
14418
15027
  startTextEditing({ idx, getReferenceRect: getReferenceRect2, getShadowElement, initialWidth: blockRect.width, initialHeight: blockRect.height, clickX, clickY, content, styles, cursorPosition });
14419
15028
  clearPendingTextEditRequest();
14420
15029
  }, [pendingTextEditRequest, clearPendingTextEditRequest, startTextEditing]);
14421
- useEffect20(() => {
15030
+ useEffect16(() => {
14422
15031
  if (isDragging && dataTransfer) {
14423
15032
  const currentTemplate = useEditorStore.getState().template;
14424
15033
  templateCacheRef.current = currentTemplate;
@@ -14434,9 +15043,9 @@ function Editor({ setEditorLoading }) {
14434
15043
  sectionRectCacheRef.current.clear();
14435
15044
  }
14436
15045
  }, [isDragging, dataTransfer]);
14437
- const [html, setHtml] = useState16("");
14438
- const lastRenderDataRef = useRef11("");
14439
- useEffect20(() => {
15046
+ const [html, setHtml] = useState17("");
15047
+ const lastRenderDataRef = useRef12("");
15048
+ useEffect16(() => {
14440
15049
  if (typeof window === "undefined" || !renderData) {
14441
15050
  setHtml("");
14442
15051
  lastRenderDataRef.current = "";
@@ -14463,13 +15072,13 @@ function Editor({ setEditorLoading }) {
14463
15072
  };
14464
15073
  convertMjml();
14465
15074
  }, [renderData]);
14466
- const debouncedUpdateContent = useMemo17(
15075
+ const debouncedUpdateContent = useMemo18(
14467
15076
  () => debounce((contentIdx, content) => {
14468
15077
  updateElementContent(contentIdx, content);
14469
15078
  }, 200),
14470
15079
  [updateElementContent]
14471
15080
  );
14472
- const handleElementClick = useCallback17(
15081
+ const handleElementClick = useCallback20(
14473
15082
  (idx) => {
14474
15083
  if (isInsideCompanyFooter(idx, template)) {
14475
15084
  return;
@@ -14482,7 +15091,7 @@ function Editor({ setEditorLoading }) {
14482
15091
  },
14483
15092
  [setFocusIdx, template]
14484
15093
  );
14485
- const handleElementHover = useCallback17(
15094
+ const handleElementHover = useCallback20(
14486
15095
  (idx) => {
14487
15096
  if (!isDragging) {
14488
15097
  if (idx) {
@@ -14496,19 +15105,19 @@ function Editor({ setEditorLoading }) {
14496
15105
  },
14497
15106
  [isDragging, setHoverIdx, template]
14498
15107
  );
14499
- const handleContentInput = useCallback17(
15108
+ const handleContentInput = useCallback20(
14500
15109
  (contentIdx, content) => {
14501
15110
  debouncedUpdateContent(contentIdx, content);
14502
15111
  },
14503
15112
  [debouncedUpdateContent]
14504
15113
  );
14505
- const handleEditingStart = useCallback17(() => {
15114
+ const handleEditingStart = useCallback20(() => {
14506
15115
  setIsEditing(true);
14507
15116
  }, []);
14508
- const handleEditingEnd = useCallback17(() => {
15117
+ const handleEditingEnd = useCallback20(() => {
14509
15118
  setIsEditing(false);
14510
15119
  }, []);
14511
- const handleSlashCommand = useCallback17(
15120
+ const handleSlashCommand = useCallback20(
14512
15121
  (cursorRect) => {
14513
15122
  setSlashCommand({
14514
15123
  isActive: true,
@@ -14523,10 +15132,10 @@ function Editor({ setEditorLoading }) {
14523
15132
  },
14524
15133
  [setSlashCommand]
14525
15134
  );
14526
- const handleSlashCommandClose = useCallback17(() => {
15135
+ const handleSlashCommandClose = useCallback20(() => {
14527
15136
  clearSlashCommand();
14528
15137
  }, [clearSlashCommand]);
14529
- const handleTextEditStart = useCallback17(
15138
+ const handleTextEditStart = useCallback20(
14530
15139
  (idx, initialWidth, initialHeight, clickX, clickY, content, styles) => {
14531
15140
  const getReferenceRect2 = () => {
14532
15141
  if (!shadowRootRef.current) return null;
@@ -14541,11 +15150,11 @@ function Editor({ setEditorLoading }) {
14541
15150
  },
14542
15151
  [startTextEditing]
14543
15152
  );
14544
- const findParentSectionIdx = useCallback17((idx) => {
15153
+ const findParentSectionIdx = useCallback20((idx) => {
14545
15154
  const match = /^(content\.children\.\[\d+\])/.exec(idx);
14546
15155
  return match ? match[1] : null;
14547
15156
  }, []);
14548
- const handleDragOver = useCallback17(
15157
+ const handleDragOver = useCallback20(
14549
15158
  (_e, dragInfo) => {
14550
15159
  const currentDataTransfer = useEditorStore.getState().dataTransfer;
14551
15160
  if (!currentDataTransfer) return;
@@ -14554,6 +15163,11 @@ function Editor({ setEditorLoading }) {
14554
15163
  setDropIndicator(null);
14555
15164
  setDropTargetIdx(null);
14556
15165
  splitAtParagraphRef.current = null;
15166
+ if (imageReplaceTargetRef.current && shadowRootRef.current && imagePreviewOriginalSrcRef.current !== null) {
15167
+ restoreImagePreview(shadowRootRef.current, imageReplaceTargetRef.current, imagePreviewOriginalSrcRef.current);
15168
+ }
15169
+ imageReplaceTargetRef.current = null;
15170
+ imagePreviewOriginalSrcRef.current = null;
14557
15171
  return;
14558
15172
  }
14559
15173
  const template2 = templateCacheRef.current || useEditorStore.getState().template;
@@ -14585,21 +15199,64 @@ function Editor({ setEditorLoading }) {
14585
15199
  }
14586
15200
  }
14587
15201
  if (hoveredType === "column" || hoveredType === "property-card" || hoveredType === "property-card-single-two" || hoveredType === "property-card-triple") {
14588
- const columnIdx = hoveredType === "column" ? idx : getParentIdx(idx);
14589
- if (columnIdx) {
14590
- const columnParentIdx = getParentIdx(columnIdx);
14591
- if (columnParentIdx) {
14592
- const columnParent = getValueByIdx(template2, columnParentIdx);
14593
- if (columnParent?.type === "section-property-km" || columnParent?.type === "section-property-single-two" || columnParent?.type === "section-property-triple") {
14594
- setDropIndicator(null);
14595
- setDropTargetIdx(null);
14596
- splitAtParagraphRef.current = null;
14597
- return;
15202
+ const isImageReplaceDrop = currentDataTransfer.type === "image" && currentDataTransfer.payload?.attributes?.src && (hoveredType === "property-card" || hoveredType === "property-card-single-two");
15203
+ if (!isImageReplaceDrop) {
15204
+ const columnIdx = hoveredType === "column" ? idx : getParentIdx(idx);
15205
+ if (columnIdx) {
15206
+ const columnParentIdx = getParentIdx(columnIdx);
15207
+ if (columnParentIdx) {
15208
+ const columnParent = getValueByIdx(template2, columnParentIdx);
15209
+ if (columnParent?.type === "section-property-km" || columnParent?.type === "section-property-single-two" || columnParent?.type === "section-property-triple") {
15210
+ setDropIndicator(null);
15211
+ setDropTargetIdx(null);
15212
+ splitAtParagraphRef.current = null;
15213
+ return;
15214
+ }
14598
15215
  }
14599
15216
  }
14600
15217
  }
14601
15218
  }
14602
15219
  const dragType = currentDataTransfer.type;
15220
+ const hasImagePayload = currentDataTransfer.payload?.attributes?.src;
15221
+ const PROPERTY_CARD_IMAGE_TYPES = ["property-card", "property-card-single-two", "property-card-triple-item"];
15222
+ const isImageReplaceTarget = hoveredType === "image" || PROPERTY_CARD_IMAGE_TYPES.includes(hoveredType);
15223
+ if (dragType === "image" && hasImagePayload && isImageReplaceTarget) {
15224
+ const newSrc = currentDataTransfer.payload.attributes.src;
15225
+ const prevTarget = imageReplaceTargetRef.current;
15226
+ if (prevTarget !== idx) {
15227
+ if (prevTarget && imagePreviewOriginalSrcRef.current !== null && shadowRootRef.current) {
15228
+ restoreImagePreview(shadowRootRef.current, prevTarget, imagePreviewOriginalSrcRef.current);
15229
+ }
15230
+ if (shadowRootRef.current) {
15231
+ const targetEl = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
15232
+ if (targetEl) {
15233
+ const img = targetEl.querySelector("img");
15234
+ if (img && hoveredType === "image") {
15235
+ imagePreviewOriginalSrcRef.current = img.src;
15236
+ img.src = newSrc;
15237
+ } else {
15238
+ const bgEl = targetEl.querySelector("td[background], th[background]");
15239
+ if (bgEl) {
15240
+ imagePreviewOriginalSrcRef.current = bgEl.getAttribute("background") || "";
15241
+ bgEl.setAttribute("background", newSrc);
15242
+ bgEl.style.backgroundImage = `url(${newSrc})`;
15243
+ }
15244
+ }
15245
+ }
15246
+ }
15247
+ imageReplaceTargetRef.current = idx;
15248
+ }
15249
+ setDropIndicator(null);
15250
+ setDropTargetIdx(idx);
15251
+ return;
15252
+ }
15253
+ if (imageReplaceTargetRef.current) {
15254
+ if (shadowRootRef.current && imagePreviewOriginalSrcRef.current !== null) {
15255
+ restoreImagePreview(shadowRootRef.current, imageReplaceTargetRef.current, imagePreviewOriginalSrcRef.current);
15256
+ }
15257
+ imageReplaceTargetRef.current = null;
15258
+ imagePreviewOriginalSrcRef.current = null;
15259
+ }
14603
15260
  const validParents = VALID_PARENT_TYPES[dragType] || [];
14604
15261
  let parentIdx;
14605
15262
  let positionIndex;
@@ -14956,10 +15613,51 @@ function Editor({ setEditorLoading }) {
14956
15613
  [findParentSectionIdx]
14957
15614
  // Only dependency is the helper function
14958
15615
  );
14959
- const handleDrop = useCallback17(
15616
+ const handleDrop = useCallback20(
14960
15617
  (_e, _dragInfo) => {
14961
15618
  const currentDataTransfer = useEditorStore.getState().dataTransfer;
14962
15619
  if (!currentDataTransfer) return;
15620
+ if (imageReplaceTargetRef.current && currentDataTransfer.payload?.attributes?.src) {
15621
+ const targetIdx = imageReplaceTargetRef.current;
15622
+ const newSrc = currentDataTransfer.payload.attributes.src;
15623
+ const template2 = useEditorStore.getState().template;
15624
+ const PROPERTY_CARD_IMAGE_TYPES = ["property-card", "property-card-single-two", "property-card-triple-item"];
15625
+ if (template2) {
15626
+ const targetElement = getValueByIdx(template2, targetIdx);
15627
+ if (targetElement?.type === "image") {
15628
+ useEditorStore.getState().updateElement(targetIdx, {
15629
+ attributes: { ...targetElement.attributes, src: newSrc }
15630
+ });
15631
+ useEditorStore.getState().setFocusIdx(targetIdx);
15632
+ } else if (targetElement && PROPERTY_CARD_IMAGE_TYPES.includes(targetElement.type)) {
15633
+ useEditorStore.getState().updateElement(targetIdx, {
15634
+ attributes: { ...targetElement.attributes, "image-src": newSrc }
15635
+ });
15636
+ useEditorStore.getState().setFocusIdx(targetIdx);
15637
+ }
15638
+ }
15639
+ setDropIndicator(null);
15640
+ setDropTargetIdx(null);
15641
+ setIsDragging(false);
15642
+ setIsDragButtonHovered(false);
15643
+ setDataTransfer(null);
15644
+ setHoverIdx(null);
15645
+ dragParentIdxRef.current = null;
15646
+ dragPositionIndexRef.current = 0;
15647
+ createNewSectionRef.current = false;
15648
+ splitAtParagraphRef.current = null;
15649
+ isHorizontalDropRef.current = false;
15650
+ horizontalDropPositionRef.current = null;
15651
+ isSplitSectionDropRef.current = false;
15652
+ splitSectionAtElementRef.current = null;
15653
+ imageReplaceTargetRef.current = null;
15654
+ imagePreviewOriginalSrcRef.current = null;
15655
+ templateCacheRef.current = null;
15656
+ parentSectionCacheRef.current.clear();
15657
+ sectionElementCacheRef.current.clear();
15658
+ sectionRectCacheRef.current.clear();
15659
+ return;
15660
+ }
14963
15661
  if (isHorizontalDropRef.current && horizontalDropPositionRef.current) {
14964
15662
  const parentIdx2 = dragParentIdxRef.current;
14965
15663
  const dropPosition = horizontalDropPositionRef.current;
@@ -14980,6 +15678,8 @@ function Editor({ setEditorLoading }) {
14980
15678
  horizontalDropPositionRef.current = null;
14981
15679
  isSplitSectionDropRef.current = false;
14982
15680
  splitSectionAtElementRef.current = null;
15681
+ imageReplaceTargetRef.current = null;
15682
+ imagePreviewOriginalSrcRef.current = null;
14983
15683
  templateCacheRef.current = null;
14984
15684
  parentSectionCacheRef.current.clear();
14985
15685
  sectionElementCacheRef.current.clear();
@@ -15040,6 +15740,8 @@ function Editor({ setEditorLoading }) {
15040
15740
  splitAtParagraphRef.current = null;
15041
15741
  isSplitSectionDropRef.current = false;
15042
15742
  splitSectionAtElementRef.current = null;
15743
+ imageReplaceTargetRef.current = null;
15744
+ imagePreviewOriginalSrcRef.current = null;
15043
15745
  templateCacheRef.current = null;
15044
15746
  parentSectionCacheRef.current.clear();
15045
15747
  sectionElementCacheRef.current.clear();
@@ -15095,7 +15797,7 @@ function Editor({ setEditorLoading }) {
15095
15797
  },
15096
15798
  [addElement, addElementInNewSection, moveElement, moveElementToNewSection, splitTextAndInsertElement, splitSectionAndInsertElement, setIsDragging, setIsDragButtonHovered, setDataTransfer, setHoverIdx]
15097
15799
  );
15098
- const handleDragLeave = useCallback17(() => {
15800
+ const handleDragLeave = useCallback20(() => {
15099
15801
  setDropIndicator(null);
15100
15802
  setDropTargetIdx(null);
15101
15803
  dragParentIdxRef.current = null;
@@ -15106,18 +15808,23 @@ function Editor({ setEditorLoading }) {
15106
15808
  horizontalDropPositionRef.current = null;
15107
15809
  isSplitSectionDropRef.current = false;
15108
15810
  splitSectionAtElementRef.current = null;
15811
+ if (imageReplaceTargetRef.current && shadowRootRef.current && imagePreviewOriginalSrcRef.current !== null) {
15812
+ restoreImagePreview(shadowRootRef.current, imageReplaceTargetRef.current, imagePreviewOriginalSrcRef.current);
15813
+ }
15814
+ imageReplaceTargetRef.current = null;
15815
+ imagePreviewOriginalSrcRef.current = null;
15109
15816
  templateCacheRef.current = null;
15110
15817
  parentSectionCacheRef.current.clear();
15111
15818
  sectionElementCacheRef.current.clear();
15112
15819
  sectionRectCacheRef.current.clear();
15113
15820
  }, []);
15114
- const handleShadowRootRef = useCallback17((shadowRoot) => {
15821
+ const handleShadowRootRef = useCallback20((shadowRoot) => {
15115
15822
  shadowRootRef.current = shadowRoot;
15116
15823
  }, []);
15117
- const handleSelectionRectChange = useCallback17((rect) => {
15824
+ const handleSelectionRectChange = useCallback20((rect) => {
15118
15825
  setHasSelectedElement(rect !== null);
15119
15826
  }, []);
15120
- const getReferenceRect = useCallback17(() => {
15827
+ const getReferenceRect = useCallback20(() => {
15121
15828
  if (!shadowRootRef.current || !focusIdx) return null;
15122
15829
  const selectedEl = shadowRootRef.current.querySelector(
15123
15830
  `.node-idx-${CSS.escape(focusIdx)}`
@@ -15145,14 +15852,14 @@ function Editor({ setEditorLoading }) {
15145
15852
  }, [focusIdx]);
15146
15853
  const selectedElement = focusIdx && renderData ? getValueByIdx(renderData, focusIdx) : null;
15147
15854
  const canDragSelectedElement = selectedElement && selectedElement.type !== "column" && !(focusIdx && renderData && isInsideCompanyFooter(focusIdx, renderData));
15148
- const showCompanyFooter = useMemo17(
15855
+ const showCompanyFooter = useMemo18(
15149
15856
  () => template.content[0]?.data?.value?.showCompanyFooter ?? true,
15150
15857
  [template.content[0]?.data?.value?.showCompanyFooter]
15151
15858
  );
15152
15859
  if (!html) {
15153
- return /* @__PURE__ */ jsx50("div", { className: "maillow-editor flex items-center justify-center h-[500px]", children: /* @__PURE__ */ jsx50(Spinner, {}) });
15860
+ return /* @__PURE__ */ jsx51("div", { className: "maillow-editor flex items-center justify-center h-[500px]", children: /* @__PURE__ */ jsx51(Spinner, {}) });
15154
15861
  }
15155
- return /* @__PURE__ */ jsxs31(
15862
+ return /* @__PURE__ */ jsxs32(
15156
15863
  "div",
15157
15864
  {
15158
15865
  className: "maillow-editor relative ",
@@ -15163,7 +15870,7 @@ function Editor({ setEditorLoading }) {
15163
15870
  justifyContent: "center"
15164
15871
  },
15165
15872
  children: [
15166
- /* @__PURE__ */ jsxs31(
15873
+ /* @__PURE__ */ jsxs32(
15167
15874
  "div",
15168
15875
  {
15169
15876
  className: `editor-container rounded-b-[12px] max-w-[626px] w-[626px] [@media(max-width:950px)]:max-w-[100%] [@media(max-width:950px)]:w-[100%] `,
@@ -15173,8 +15880,8 @@ function Editor({ setEditorLoading }) {
15173
15880
  overflow: "auto"
15174
15881
  },
15175
15882
  children: [
15176
- /* @__PURE__ */ jsx50("div", { className: "w-full h-[4px] bg-black opacity-10" }),
15177
- /* @__PURE__ */ jsx50(
15883
+ /* @__PURE__ */ jsx51("div", { className: "w-full h-[2px] bg-black opacity-10" }),
15884
+ /* @__PURE__ */ jsx51(
15178
15885
  ShadowDomRenderer,
15179
15886
  {
15180
15887
  html,
@@ -15204,9 +15911,10 @@ function Editor({ setEditorLoading }) {
15204
15911
  ]
15205
15912
  }
15206
15913
  ),
15207
- /* @__PURE__ */ jsx50(ElementsSuggestions, {}),
15208
- /* @__PURE__ */ jsx50(TiptapOverlay, {}),
15209
- !isDragging && !isScaling && hasSelectedElement && focusIdx && selectedElement?.type && /* @__PURE__ */ jsx50(
15914
+ /* @__PURE__ */ jsx51(ElementsSuggestions, {}),
15915
+ /* @__PURE__ */ jsx51(MergeFieldSuggestions, {}),
15916
+ /* @__PURE__ */ jsx51(TiptapOverlay, {}),
15917
+ !isDragging && !isScaling && hasSelectedElement && focusIdx && selectedElement?.type && /* @__PURE__ */ jsx51(
15210
15918
  ElementFloat,
15211
15919
  {
15212
15920
  getReferenceRect,
@@ -15214,7 +15922,7 @@ function Editor({ setEditorLoading }) {
15214
15922
  elementType: selectedElement.type
15215
15923
  }
15216
15924
  ),
15217
- !isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */ jsx50(
15925
+ !isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */ jsx51(
15218
15926
  DragButton,
15219
15927
  {
15220
15928
  getReferenceRect,
@@ -15223,17 +15931,17 @@ function Editor({ setEditorLoading }) {
15223
15931
  isDragging
15224
15932
  }
15225
15933
  ),
15226
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "divider" && /* @__PURE__ */ jsx50(DividerScale, { getReferenceRect }),
15227
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "button" && /* @__PURE__ */ jsx50(ButtonScale, { getReferenceRect }),
15228
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "image" && /* @__PURE__ */ jsx50(ImageScale, { getReferenceRect }),
15229
- !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "space" && /* @__PURE__ */ jsx50(SpacerScale, { getReferenceRect }),
15934
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "divider" && /* @__PURE__ */ jsx51(DividerScale, { getReferenceRect }),
15935
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "button" && /* @__PURE__ */ jsx51(ButtonScale, { getReferenceRect }),
15936
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "image" && /* @__PURE__ */ jsx51(ImageScale, { getReferenceRect }),
15937
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "space" && /* @__PURE__ */ jsx51(SpacerScale, { getReferenceRect }),
15230
15938
  !isDragging && hasSelectedElement && focusIdx && renderData && (() => {
15231
15939
  const sectionColumnIdx = getSectionColumnIdx(focusIdx, renderData);
15232
15940
  if (!sectionColumnIdx) return null;
15233
15941
  const sectionColumn = getValueByIdx(renderData, sectionColumnIdx);
15234
15942
  if (!sectionColumn || sectionColumn.type !== "section-column") return null;
15235
15943
  if (!sectionColumn.children || sectionColumn.children.length < 2) return null;
15236
- return /* @__PURE__ */ jsx50(
15944
+ return /* @__PURE__ */ jsx51(
15237
15945
  ColumnScale,
15238
15946
  {
15239
15947
  sectionColumnIdx,
@@ -15255,9 +15963,7 @@ export {
15255
15963
  parseBorder,
15256
15964
  formatBorder,
15257
15965
  parsePrice,
15258
- json2mjml,
15259
15966
  MAX_TEMPLATE_SIZE,
15260
- useEditorStore,
15261
15967
  BUTTON_ALIGNMENTS,
15262
15968
  ALIGNMENT_ICONS,
15263
15969
  FONTS,
@@ -15275,6 +15981,9 @@ export {
15275
15981
  MIN_LINE_HEIGHT,
15276
15982
  MAX_LINE_HEIGHT,
15277
15983
  LINE_HEIGHT_STEP,
15984
+ DEFAULT_PROPERTY_PLACEHOLDER_IMAGE,
15985
+ json2mjml,
15986
+ useEditorStore,
15278
15987
  setupDragImage,
15279
15988
  getElementDisplayName,
15280
15989
  cn,