@kgalexander/mcreate 0.0.15 → 0.0.16

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 useEffect21, useCallback as useCallback18, 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: 4px;
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 useEffect7, 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, useEffect as useEffect6 } 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,16 +11306,16 @@ 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(() => {
11318
+ useEffect6(() => {
11046
11319
  if (isOpen) {
11047
11320
  setLinkType(detectLinkType(currentHref));
11048
11321
  setInputValue(stripPrefix(currentHref));
@@ -11084,42 +11357,42 @@ var TextLinkMenu = ({ editor }) => {
11084
11357
  editor.chain().focus().unsetLink().run();
11085
11358
  setInputValue("");
11086
11359
  };
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(
11360
+ return /* @__PURE__ */ jsxs7(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
11361
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11362
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(PopoverTrigger, { asChild: true, children: hasLink ? /* @__PURE__ */ jsx20(
11090
11363
  Button,
11091
11364
  {
11092
11365
  variant: "ghost",
11093
11366
  size: "icon",
11094
11367
  className: floatButtonVariants,
11095
11368
  onMouseDown: (e) => e.preventDefault(),
11096
- children: /* @__PURE__ */ jsx19(PencilIcon, { className: "size-4" })
11369
+ children: /* @__PURE__ */ jsx20(PencilIcon, { className: "size-4" })
11097
11370
  }
11098
- ) : /* @__PURE__ */ jsxs6(
11371
+ ) : /* @__PURE__ */ jsxs7(
11099
11372
  Button,
11100
11373
  {
11101
11374
  variant: "ghost",
11102
11375
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
11103
11376
  onMouseDown: (e) => e.preventDefault(),
11104
11377
  children: [
11105
- /* @__PURE__ */ jsx19(LinkIcon2, { className: "size-4" }),
11106
- /* @__PURE__ */ jsx19("p", { children: "Add link" })
11378
+ /* @__PURE__ */ jsx20(LinkIcon2, { className: "size-4" }),
11379
+ /* @__PURE__ */ jsx20("p", { children: "Add link" })
11107
11380
  ]
11108
11381
  }
11109
11382
  ) }) }),
11110
- /* @__PURE__ */ jsx19(TooltipContent, { side: "bottom", children: hasLink ? "Edit link" : "Add link" })
11383
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", children: hasLink ? "Edit link" : "Add link" })
11111
11384
  ] }),
11112
- /* @__PURE__ */ jsxs6(
11385
+ /* @__PURE__ */ jsxs7(
11113
11386
  PopoverContent,
11114
11387
  {
11115
11388
  side: "bottom",
11116
11389
  className: "w-[250px] p-3 shadow-lg z-50001",
11117
11390
  "data-editor-toolbar": true,
11118
11391
  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(
11392
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-2", children: [
11393
+ /* @__PURE__ */ jsx20(Label, { children: "Enter a link" }),
11394
+ /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
11395
+ /* @__PURE__ */ jsx20(
11123
11396
  Input,
11124
11397
  {
11125
11398
  type: linkType.inputType,
@@ -11131,12 +11404,12 @@ var TextLinkMenu = ({ editor }) => {
11131
11404
  autoFocus: true
11132
11405
  }
11133
11406
  ),
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" })
11407
+ /* @__PURE__ */ jsxs7(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
11408
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11409
+ /* @__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, {}) }) }) }),
11410
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
11138
11411
  ] }),
11139
- /* @__PURE__ */ jsx19(
11412
+ /* @__PURE__ */ jsx20(
11140
11413
  PopoverContent,
11141
11414
  {
11142
11415
  side: "bottom",
@@ -11144,7 +11417,7 @@ var TextLinkMenu = ({ editor }) => {
11144
11417
  className: "w-[160px] p-1 z-50001",
11145
11418
  onPointerDownOutside: (e) => e.preventDefault(),
11146
11419
  "data-editor-toolbar": true,
11147
- children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs6(
11420
+ children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs7(
11148
11421
  Button,
11149
11422
  {
11150
11423
  variant: "ghost",
@@ -11155,11 +11428,11 @@ var TextLinkMenu = ({ editor }) => {
11155
11428
  setIsLinkTypeOpen(false);
11156
11429
  },
11157
11430
  children: [
11158
- /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-2", children: [
11159
- /* @__PURE__ */ jsx19(type.icon, { className: "size-4" }),
11431
+ /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-2", children: [
11432
+ /* @__PURE__ */ jsx20(type.icon, { className: "size-4" }),
11160
11433
  type.name
11161
11434
  ] }),
11162
- linkType.name === type.name && /* @__PURE__ */ jsx19(CheckIcon, { className: "size-4" })
11435
+ linkType.name === type.name && /* @__PURE__ */ jsx20(CheckIcon, { className: "size-4" })
11163
11436
  ]
11164
11437
  },
11165
11438
  type.name
@@ -11169,11 +11442,11 @@ var TextLinkMenu = ({ editor }) => {
11169
11442
  ] })
11170
11443
  ] })
11171
11444
  ] }),
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(
11445
+ /* @__PURE__ */ jsx20(Separator, { className: "my-2" }),
11446
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-row justify-between items-center", children: [
11447
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-row", children: [
11448
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11449
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(
11177
11450
  Button,
11178
11451
  {
11179
11452
  variant: "ghost",
@@ -11181,13 +11454,13 @@ var TextLinkMenu = ({ editor }) => {
11181
11454
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
11182
11455
  onClick: handleCopy,
11183
11456
  disabled: !hasLink,
11184
- children: showCopied ? /* @__PURE__ */ jsx19(CheckIcon, { className: "text-green-600" }) : /* @__PURE__ */ jsx19(CopyIcon, {})
11457
+ children: showCopied ? /* @__PURE__ */ jsx20(CheckIcon, { className: "text-green-600" }) : /* @__PURE__ */ jsx20(CopyIcon, {})
11185
11458
  }
11186
11459
  ) }),
11187
- /* @__PURE__ */ jsx19(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
11460
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
11188
11461
  ] }),
11189
- /* @__PURE__ */ jsxs6(Tooltip, { children: [
11190
- /* @__PURE__ */ jsx19(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx19(
11462
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
11463
+ /* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(
11191
11464
  Button,
11192
11465
  {
11193
11466
  variant: "ghost",
@@ -11195,13 +11468,13 @@ var TextLinkMenu = ({ editor }) => {
11195
11468
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
11196
11469
  onClick: handleRemoveLink,
11197
11470
  disabled: !hasLink,
11198
- children: /* @__PURE__ */ jsx19(TrashIcon, {})
11471
+ children: /* @__PURE__ */ jsx20(TrashIcon, {})
11199
11472
  }
11200
11473
  ) }),
11201
- /* @__PURE__ */ jsx19(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
11474
+ /* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
11202
11475
  ] })
11203
11476
  ] }),
11204
- /* @__PURE__ */ jsx19("div", { children: /* @__PURE__ */ jsx19(
11477
+ /* @__PURE__ */ jsx20("div", { children: /* @__PURE__ */ jsx20(
11205
11478
  Button,
11206
11479
  {
11207
11480
  variant: "default",
@@ -11218,16 +11491,16 @@ var TextLinkMenu = ({ editor }) => {
11218
11491
  };
11219
11492
 
11220
11493
  // src/core/editor/components/float-link-preview.tsx
11221
- import { jsx as jsx20, jsxs as jsxs7 } from "react/jsx-runtime";
11494
+ import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
11222
11495
  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 })
11496
+ return /* @__PURE__ */ jsxs8(Tooltip, { children: [
11497
+ /* @__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 }) }) }),
11498
+ /* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", children: href })
11226
11499
  ] });
11227
11500
  };
11228
11501
 
11229
11502
  // src/core/editor/components/tiptap-overlay.tsx
11230
- import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
11503
+ import { jsx as jsx22, jsxs as jsxs9 } from "react/jsx-runtime";
11231
11504
  var FontFamily = Extension.create({
11232
11505
  name: "fontFamily",
11233
11506
  addGlobalAttributes() {
@@ -11405,7 +11678,8 @@ var TIPTAP_EXTENSIONS = [
11405
11678
  emptyNodeClass: "is-empty-placeholder",
11406
11679
  paragraphPlaceholder: "Start typing...",
11407
11680
  headingPlaceholder: "Heading"
11408
- })
11681
+ }),
11682
+ MergeFieldDecoration
11409
11683
  ];
11410
11684
  function isNodeEmpty2(node) {
11411
11685
  if (!node) return true;
@@ -11536,16 +11810,16 @@ function handleBackspaceOrDelete(view, event, currentElementIdx, storeRefs) {
11536
11810
  var TiptapOverlay = () => {
11537
11811
  const textEditing = useEditorStore((s) => s.textEditing);
11538
11812
  if (!textEditing) return null;
11539
- return /* @__PURE__ */ jsx21(TiptapOverlayContent, { ...textEditing }, textEditing.idx);
11813
+ return /* @__PURE__ */ jsx22(TiptapOverlayContent, { ...textEditing }, textEditing.idx);
11540
11814
  };
11541
11815
  var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWidth, initialHeight, clickX, clickY, content, styles, cursorPosition }) => {
11542
- const containerRef = useRef4(null);
11816
+ const containerRef = useRef5(null);
11543
11817
  const setTiptapEditor = useEditorStore((s) => s.setTiptapEditor);
11544
11818
  const linkColor = useEditorStore((s) => s.template?.content?.[0]?.data?.value?.linkColor) || "#0000ff";
11545
- const lastSizeLimitToastRef = useRef4(0);
11546
- const hasContentChangedRef = useRef4(false);
11819
+ const lastSizeLimitToastRef = useRef5(0);
11820
+ const hasContentChangedRef = useRef5(false);
11547
11821
  const storeRefs = useEditorStoreRefs();
11548
- useEffect6(() => {
11822
+ useEffect7(() => {
11549
11823
  return () => {
11550
11824
  const isUndoRedoAction = useEditorStore.getState().isUndoRedoAction;
11551
11825
  if (hasContentChangedRef.current && !isUndoRedoAction) {
@@ -11553,7 +11827,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11553
11827
  }
11554
11828
  };
11555
11829
  }, []);
11556
- useEffect6(() => {
11830
+ useEffect7(() => {
11557
11831
  const container = containerRef.current;
11558
11832
  if (!container) return;
11559
11833
  const observer = new ResizeObserver(() => {
@@ -11571,10 +11845,10 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11571
11845
  }
11572
11846
  };
11573
11847
  }, [getShadowElement]);
11574
- const cleanedContent = useMemo3(() => {
11848
+ const cleanedContent = useMemo4(() => {
11575
11849
  return content.replace(NBSP_P_CONTENT_REGEX, "<p$1></p>").replace(IS_EMPTY_P_CLASS_REGEX, "").replace(IS_EMPTY_HEADING_CLASS_REGEX, "");
11576
11850
  }, [content]);
11577
- const lineHeightRatio = useMemo3(() => {
11851
+ const lineHeightRatio = useMemo4(() => {
11578
11852
  const lineHeightPx = parseFloat(styles.lineHeight);
11579
11853
  const fontSizePx = parseFloat(styles.fontSize);
11580
11854
  if (isNaN(lineHeightPx) || isNaN(fontSizePx) || fontSizePx === 0) {
@@ -11582,7 +11856,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11582
11856
  }
11583
11857
  return lineHeightPx / fontSizePx;
11584
11858
  }, [styles.lineHeight, styles.fontSize]);
11585
- const virtualReference = useMemo3(() => ({
11859
+ const virtualReference = useMemo4(() => ({
11586
11860
  getBoundingClientRect: () => {
11587
11861
  const rect = getReferenceRect();
11588
11862
  if (!rect) {
@@ -11591,14 +11865,14 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11591
11865
  return rect;
11592
11866
  }
11593
11867
  }), [getReferenceRect]);
11594
- const { floatingStyles, refs, update } = useFloating3({
11868
+ const { floatingStyles, refs, update } = useFloating4({
11595
11869
  placement: "bottom-start",
11596
11870
  middleware: [
11597
- offset3(({ rects }) => -rects.reference.height)
11871
+ offset4(({ rects }) => -rects.reference.height)
11598
11872
  // Move up by reference height to overlay exactly
11599
11873
  ]
11600
11874
  });
11601
- useEffect6(() => {
11875
+ useEffect7(() => {
11602
11876
  const rect = getReferenceRect();
11603
11877
  if (!rect || !refs.floating.current) return;
11604
11878
  refs.setPositionReference(virtualReference);
@@ -11637,17 +11911,36 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11637
11911
  }
11638
11912
  }
11639
11913
  const isSlashCommandActive = storeRefs.slashCommand.current?.isActive;
11640
- if (event.key === "Escape" && isSlashCommandActive) {
11641
- storeRefs.clearSlashCommand.current();
11642
- return true;
11914
+ const isMergeFieldActive = storeRefs.mergeFieldSuggestion.current?.isActive;
11915
+ if (event.key === "Escape") {
11916
+ if (isSlashCommandActive) {
11917
+ storeRefs.clearSlashCommand.current();
11918
+ return true;
11919
+ }
11920
+ if (isMergeFieldActive) {
11921
+ storeRefs.clearMergeFieldSuggestion.current();
11922
+ return true;
11923
+ }
11643
11924
  }
11644
- if (event.key === " " && isSlashCommandActive) {
11645
- storeRefs.clearSlashCommand.current();
11646
- return false;
11925
+ if (event.key === " ") {
11926
+ if (isSlashCommandActive) {
11927
+ storeRefs.clearSlashCommand.current();
11928
+ return false;
11929
+ }
11930
+ if (isMergeFieldActive) {
11931
+ storeRefs.clearMergeFieldSuggestion.current();
11932
+ return false;
11933
+ }
11647
11934
  }
11648
- if ((event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") && isSlashCommandActive) {
11649
- storeRefs.clearSlashCommand.current();
11650
- return false;
11935
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
11936
+ if (isSlashCommandActive) {
11937
+ storeRefs.clearSlashCommand.current();
11938
+ return false;
11939
+ }
11940
+ if (isMergeFieldActive) {
11941
+ storeRefs.clearMergeFieldSuggestion.current();
11942
+ return false;
11943
+ }
11651
11944
  }
11652
11945
  if (event.key === "/") {
11653
11946
  const { from } = view.state.selection;
@@ -11669,6 +11962,33 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11669
11962
  });
11670
11963
  }
11671
11964
  }
11965
+ if (event.key === "{") {
11966
+ const { from } = view.state.selection;
11967
+ const textBefore = view.state.doc.textBetween(Math.max(0, from - 1), from);
11968
+ if (textBefore === "{") {
11969
+ const coords = view.coordsAtPos(from);
11970
+ if (coords && coords.left > 0 && coords.top > 0) {
11971
+ const lineHeight = parseInt(styles.lineHeight) || 20;
11972
+ storeRefs.setMergeFieldSuggestion.current({
11973
+ isActive: true,
11974
+ cursorRect: { top: coords.top, left: coords.left, height: lineHeight },
11975
+ triggerPosition: from - 1
11976
+ // Position of first "{"
11977
+ });
11978
+ }
11979
+ }
11980
+ }
11981
+ if (event.key === "}" && isMergeFieldActive) {
11982
+ storeRefs.clearMergeFieldSuggestion.current();
11983
+ return false;
11984
+ }
11985
+ if (event.key === "Backspace" && isMergeFieldActive) {
11986
+ const { from } = view.state.selection;
11987
+ const triggerPos = storeRefs.mergeFieldSuggestion.current?.triggerPosition ?? 0;
11988
+ if (from <= triggerPos + 2) {
11989
+ storeRefs.clearMergeFieldSuggestion.current();
11990
+ }
11991
+ }
11672
11992
  if (event.key === "Backspace" || event.key === "Delete") {
11673
11993
  const handled = handleBackspaceOrDelete(
11674
11994
  view,
@@ -11735,8 +12055,8 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11735
12055
  storeRefs.updateElementContent.current(`${idx}.data.value.content`, html);
11736
12056
  }
11737
12057
  });
11738
- const [currentLinkHref, setCurrentLinkHref] = useState2("");
11739
- useEffect6(() => {
12058
+ const [currentLinkHref, setCurrentLinkHref] = useState3("");
12059
+ useEffect7(() => {
11740
12060
  if (!editor) return;
11741
12061
  setTiptapEditor(editor);
11742
12062
  const updateLinkHref = () => {
@@ -11751,7 +12071,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11751
12071
  editor.off("transaction", updateLinkHref);
11752
12072
  };
11753
12073
  }, [editor, setTiptapEditor]);
11754
- useEffect6(() => {
12074
+ useEffect7(() => {
11755
12075
  if (editor) {
11756
12076
  const timer = setTimeout(() => {
11757
12077
  if (cursorPosition === "end") {
@@ -11780,7 +12100,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11780
12100
  return () => clearTimeout(timer);
11781
12101
  }
11782
12102
  }, [editor, clickX, clickY, cursorPosition]);
11783
- useEffect6(() => {
12103
+ useEffect7(() => {
11784
12104
  const handleClickOutside = (e) => {
11785
12105
  const target = e.target;
11786
12106
  if (containerRef.current && containerRef.current.contains(target)) {
@@ -11802,7 +12122,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11802
12122
  document.removeEventListener("mousedown", handleClickOutside);
11803
12123
  };
11804
12124
  }, []);
11805
- return /* @__PURE__ */ jsxs8(
12125
+ return /* @__PURE__ */ jsxs9(
11806
12126
  "div",
11807
12127
  {
11808
12128
  ref: (node) => {
@@ -11835,7 +12155,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11835
12155
  boxSizing: "border-box"
11836
12156
  },
11837
12157
  children: [
11838
- /* @__PURE__ */ jsx21("style", { children: `
12158
+ /* @__PURE__ */ jsx22("style", { children: `
11839
12159
  .tiptap-overlay {
11840
12160
  margin: 0;
11841
12161
  padding: 0;
@@ -11901,6 +12221,16 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11901
12221
  transform: translateY(-50%);
11902
12222
  text-align: inherit;
11903
12223
  }
12224
+ .tiptap-overlay .ProseMirror .merge-field-tag {
12225
+ background-color: var(--background);
12226
+ border-radius: 4px;
12227
+ padding: 4px;
12228
+ border: 1px solid var(--border);
12229
+ color: #000000;
12230
+ }
12231
+ .tiptap-overlay .ProseMirror .merge-field-tag:hover {
12232
+ cursor: pointer;
12233
+ }
11904
12234
  .tiptap-overlay .ProseMirror a {
11905
12235
  color: ${linkColor};
11906
12236
  text-decoration: none;
@@ -11910,36 +12240,36 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11910
12240
  text-decoration: underline;
11911
12241
  }
11912
12242
  ` }),
11913
- /* @__PURE__ */ jsx21(
12243
+ /* @__PURE__ */ jsx22(
11914
12244
  EditorContent,
11915
12245
  {
11916
12246
  editor,
11917
12247
  className: "tiptap-overlay"
11918
12248
  }
11919
12249
  ),
11920
- editor && /* @__PURE__ */ jsx21(
12250
+ editor && /* @__PURE__ */ jsx22(
11921
12251
  BubbleMenu,
11922
12252
  {
11923
12253
  editor,
11924
12254
  options: { placement: "top", offset: 8, flip: true },
11925
12255
  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(
12256
+ children: /* @__PURE__ */ jsxs9("div", { className: "bg-white flex items-center justify-center border h-[36px] w-fit shadow-md rounded-full text-[16px]", children: [
12257
+ /* @__PURE__ */ jsxs9(Tooltip, { children: [
12258
+ /* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
11929
12259
  Button,
11930
12260
  {
11931
12261
  variant: "ghost",
11932
12262
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
11933
12263
  children: [
11934
- /* @__PURE__ */ jsx21(BotIcon, { className: "size-4" }),
11935
- /* @__PURE__ */ jsx21("p", { children: "Magic Write" })
12264
+ /* @__PURE__ */ jsx22(BotIcon, { className: "size-4" }),
12265
+ /* @__PURE__ */ jsx22("p", { children: "Magic Write" })
11936
12266
  ]
11937
12267
  }
11938
12268
  ) }),
11939
- /* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", children: "Ask Maillow" })
12269
+ /* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", children: "Ask Maillow" })
11940
12270
  ] }),
11941
- currentLinkHref && /* @__PURE__ */ jsx21(FloatLinkPreview, { href: currentLinkHref }),
11942
- /* @__PURE__ */ jsx21(TextLinkMenu, { editor })
12271
+ currentLinkHref && /* @__PURE__ */ jsx22(FloatLinkPreview, { href: currentLinkHref }),
12272
+ /* @__PURE__ */ jsx22(TextLinkMenu, { editor })
11943
12273
  ] })
11944
12274
  }
11945
12275
  )
@@ -11949,12 +12279,12 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
11949
12279
  };
11950
12280
 
11951
12281
  // 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";
12282
+ import { useEffect as useEffect13, useMemo as useMemo12 } from "react";
12283
+ import { useFloating as useFloating5, offset as offset5, shift as shift4, flip as flip3, autoUpdate as autoUpdate3 } from "@floating-ui/react";
11954
12284
 
11955
12285
  // src/core/editor/components/float-ui/actions/delete-button.tsx
11956
12286
  import { TrashIcon as TrashIcon2 } from "lucide-react";
11957
- import { jsx as jsx22, jsxs as jsxs9 } from "react/jsx-runtime";
12287
+ import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
11958
12288
  var DeleteButton = () => {
11959
12289
  const { focusIdx, deleteElement } = useEditorStore();
11960
12290
  const handleDelete = () => {
@@ -11962,23 +12292,23 @@ var DeleteButton = () => {
11962
12292
  deleteElement(focusIdx);
11963
12293
  }
11964
12294
  };
11965
- return /* @__PURE__ */ jsxs9(Tooltip, { children: [
11966
- /* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
12295
+ return /* @__PURE__ */ jsxs10(Tooltip, { children: [
12296
+ /* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
11967
12297
  Button,
11968
12298
  {
11969
12299
  variant: "ghost",
11970
12300
  className: floatButtonVariants,
11971
12301
  onClick: handleDelete,
11972
- children: /* @__PURE__ */ jsx22(TrashIcon2, { className: "size-4" })
12302
+ children: /* @__PURE__ */ jsx23(TrashIcon2, { className: "size-4" })
11973
12303
  }
11974
12304
  ) }),
11975
- /* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", children: "Delete" })
12305
+ /* @__PURE__ */ jsx23(TooltipContent, { side: "bottom", children: "Delete" })
11976
12306
  ] });
11977
12307
  };
11978
12308
 
11979
12309
  // src/core/editor/components/float-ui/actions/dulicate-button.tsx
11980
12310
  import { CopyIcon as CopyIcon2 } from "lucide-react";
11981
- import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
12311
+ import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
11982
12312
  var DuplicateButton = () => {
11983
12313
  const { focusIdx, duplicateElement } = useEditorStore();
11984
12314
  const isAtSizeLimit = useEditorStore((state) => state.isAtSizeLimit);
@@ -11987,42 +12317,42 @@ var DuplicateButton = () => {
11987
12317
  duplicateElement(focusIdx);
11988
12318
  }
11989
12319
  };
11990
- return /* @__PURE__ */ jsxs10(Tooltip, { children: [
11991
- /* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
12320
+ return /* @__PURE__ */ jsxs11(Tooltip, { children: [
12321
+ /* @__PURE__ */ jsx24(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx24(
11992
12322
  Button,
11993
12323
  {
11994
12324
  variant: "ghost",
11995
12325
  className: floatButtonVariants,
11996
12326
  onClick: handleDuplicate,
11997
12327
  disabled: isAtSizeLimit,
11998
- children: /* @__PURE__ */ jsx23(CopyIcon2, { className: "size-4" })
12328
+ children: /* @__PURE__ */ jsx24(CopyIcon2, { className: "size-4" })
11999
12329
  }
12000
12330
  ) }),
12001
- /* @__PURE__ */ jsx23(TooltipContent, { side: "bottom", children: "Duplicate" })
12331
+ /* @__PURE__ */ jsx24(TooltipContent, { side: "bottom", children: "Duplicate" })
12002
12332
  ] });
12003
12333
  };
12004
12334
 
12005
12335
  // src/core/editor/components/href-menu.tsx
12006
- import { useState as useState3, useEffect as useEffect7, useCallback as useCallback4, useMemo as useMemo5 } from "react";
12336
+ import { useState as useState4, useEffect as useEffect8, useCallback as useCallback5, useMemo as useMemo6 } from "react";
12007
12337
 
12008
12338
  // src/components/ui/dropdown-menu.tsx
12009
12339
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
12010
12340
  import { CheckIcon as CheckIcon2, ChevronRightIcon, CircleIcon } from "lucide-react";
12011
- import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
12341
+ import { jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
12012
12342
  function DropdownMenu({
12013
12343
  ...props
12014
12344
  }) {
12015
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
12345
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
12016
12346
  }
12017
12347
  function DropdownMenuPortal({
12018
12348
  ...props
12019
12349
  }) {
12020
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
12350
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
12021
12351
  }
12022
12352
  function DropdownMenuTrigger({
12023
12353
  ...props
12024
12354
  }) {
12025
- return /* @__PURE__ */ jsx24(
12355
+ return /* @__PURE__ */ jsx25(
12026
12356
  DropdownMenuPrimitive.Trigger,
12027
12357
  {
12028
12358
  "data-slot": "dropdown-menu-trigger",
@@ -12035,7 +12365,7 @@ function DropdownMenuContent({
12035
12365
  sideOffset = 4,
12036
12366
  ...props
12037
12367
  }) {
12038
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx24(
12368
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx25(
12039
12369
  DropdownMenuPrimitive.Content,
12040
12370
  {
12041
12371
  "data-slot": "dropdown-menu-content",
@@ -12054,7 +12384,7 @@ function DropdownMenuItem({
12054
12384
  variant = "default",
12055
12385
  ...props
12056
12386
  }) {
12057
- return /* @__PURE__ */ jsx24(
12387
+ return /* @__PURE__ */ jsx25(
12058
12388
  DropdownMenuPrimitive.Item,
12059
12389
  {
12060
12390
  "data-slot": "dropdown-menu-item",
@@ -12072,7 +12402,7 @@ function DropdownMenuSeparator({
12072
12402
  className,
12073
12403
  ...props
12074
12404
  }) {
12075
- return /* @__PURE__ */ jsx24(
12405
+ return /* @__PURE__ */ jsx25(
12076
12406
  DropdownMenuPrimitive.Separator,
12077
12407
  {
12078
12408
  "data-slot": "dropdown-menu-separator",
@@ -12084,7 +12414,7 @@ function DropdownMenuSeparator({
12084
12414
  function DropdownMenuSub({
12085
12415
  ...props
12086
12416
  }) {
12087
- return /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
12417
+ return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
12088
12418
  }
12089
12419
  function DropdownMenuSubTrigger({
12090
12420
  className,
@@ -12092,7 +12422,7 @@ function DropdownMenuSubTrigger({
12092
12422
  children,
12093
12423
  ...props
12094
12424
  }) {
12095
- return /* @__PURE__ */ jsxs11(
12425
+ return /* @__PURE__ */ jsxs12(
12096
12426
  DropdownMenuPrimitive.SubTrigger,
12097
12427
  {
12098
12428
  "data-slot": "dropdown-menu-sub-trigger",
@@ -12104,7 +12434,7 @@ function DropdownMenuSubTrigger({
12104
12434
  ...props,
12105
12435
  children: [
12106
12436
  children,
12107
- /* @__PURE__ */ jsx24(ChevronRightIcon, { className: "ml-auto size-4" })
12437
+ /* @__PURE__ */ jsx25(ChevronRightIcon, { className: "ml-auto size-4" })
12108
12438
  ]
12109
12439
  }
12110
12440
  );
@@ -12113,7 +12443,7 @@ function DropdownMenuSubContent({
12113
12443
  className,
12114
12444
  ...props
12115
12445
  }) {
12116
- return /* @__PURE__ */ jsx24(
12446
+ return /* @__PURE__ */ jsx25(
12117
12447
  DropdownMenuPrimitive.SubContent,
12118
12448
  {
12119
12449
  "data-slot": "dropdown-menu-sub-content",
@@ -12130,11 +12460,11 @@ function DropdownMenuSubContent({
12130
12460
  import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon3, LinkIcon as LinkIcon3, PencilIcon as PencilIcon2, TrashIcon as TrashIcon3 } from "lucide-react";
12131
12461
 
12132
12462
  // src/core/editor/hooks/use-href.ts
12133
- import { useMemo as useMemo4, useCallback as useCallback3 } from "react";
12463
+ import { useMemo as useMemo5, useCallback as useCallback4 } from "react";
12134
12464
  import { get as lodashGet2 } from "lodash";
12135
12465
  var useHref = () => {
12136
12466
  const { focusIdx, updateElement, template } = useEditorStore();
12137
- const { element, href } = useMemo4(() => {
12467
+ const { element, href } = useMemo5(() => {
12138
12468
  if (!focusIdx || !template) {
12139
12469
  return { element: null, href: "" };
12140
12470
  }
@@ -12145,19 +12475,19 @@ var useHref = () => {
12145
12475
  href: el?.attributes?.href || ""
12146
12476
  };
12147
12477
  }, [focusIdx, template]);
12148
- const setHref = useCallback3((url) => {
12478
+ const setHref = useCallback4((url) => {
12149
12479
  if (!focusIdx || !element) return;
12150
12480
  updateElement(focusIdx, {
12151
12481
  attributes: { ...element.attributes, href: url }
12152
12482
  });
12153
12483
  }, [focusIdx, element, updateElement]);
12154
- const clearHref = useCallback3(() => {
12484
+ const clearHref = useCallback4(() => {
12155
12485
  if (!focusIdx || !element) return;
12156
12486
  updateElement(focusIdx, {
12157
12487
  attributes: { ...element.attributes, href: "" }
12158
12488
  });
12159
12489
  }, [focusIdx, element, updateElement]);
12160
- const copyHref = useCallback3(async () => {
12490
+ const copyHref = useCallback4(async () => {
12161
12491
  if (href) {
12162
12492
  try {
12163
12493
  await navigator.clipboard.writeText(href);
@@ -12177,18 +12507,18 @@ var useHref = () => {
12177
12507
  };
12178
12508
 
12179
12509
  // src/core/editor/components/href-menu.tsx
12180
- import { jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
12510
+ import { jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
12181
12511
  var HrefMenu = () => {
12182
12512
  const { href, setHref, clearHref, copyHref, hasHref } = useHref();
12183
12513
  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);
12514
+ const [isOpen, setIsOpen] = useState4(false);
12515
+ const [inputValue, setInputValue] = useState4("");
12516
+ const [showCopied, setShowCopied] = useState4(false);
12517
+ const [linkType, setLinkType] = useState4(LINK_TYPES[1]);
12518
+ const [isLinkTypeOpen, setIsLinkTypeOpen] = useState4(false);
12519
+ const [isPresetOpen, setIsPresetOpen] = useState4(false);
12190
12520
  console.log("userData", userData);
12191
- const availablePresets = useMemo5(() => {
12521
+ const availablePresets = useMemo6(() => {
12192
12522
  const presetDefs = LINK_PRESETS[linkType.name] ?? [];
12193
12523
  if (!userData) return [];
12194
12524
  const all = presetDefs.filter((p) => userData[p.key]).map((p) => ({ ...p, value: String(userData[p.key]) }));
@@ -12196,11 +12526,11 @@ var HrefMenu = () => {
12196
12526
  const query = inputValue.toLowerCase();
12197
12527
  return all.filter((p) => p.value.toLowerCase().includes(query));
12198
12528
  }, [linkType.name, userData, inputValue]);
12199
- const handlePresetSelect = useCallback4((value) => {
12529
+ const handlePresetSelect = useCallback5((value) => {
12200
12530
  setInputValue(value);
12201
12531
  setIsPresetOpen(false);
12202
12532
  }, []);
12203
- useEffect7(() => {
12533
+ useEffect8(() => {
12204
12534
  if (isOpen) {
12205
12535
  setLinkType(detectLinkType(href));
12206
12536
  setInputValue(stripPrefix(href));
@@ -12251,35 +12581,35 @@ var HrefMenu = () => {
12251
12581
  setHref(buildHref(inputValue));
12252
12582
  setIsOpen(false);
12253
12583
  };
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(
12584
+ return /* @__PURE__ */ jsxs13(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
12585
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12586
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx26(
12257
12587
  Button,
12258
12588
  {
12259
12589
  variant: "ghost",
12260
12590
  size: "icon",
12261
12591
  className: floatButtonVariants,
12262
- children: /* @__PURE__ */ jsx25(PencilIcon2, { className: "size-4" })
12592
+ children: /* @__PURE__ */ jsx26(PencilIcon2, { className: "size-4" })
12263
12593
  }
12264
- ) : /* @__PURE__ */ jsxs12(
12594
+ ) : /* @__PURE__ */ jsxs13(
12265
12595
  Button,
12266
12596
  {
12267
12597
  variant: "ghost",
12268
12598
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
12269
12599
  children: [
12270
- /* @__PURE__ */ jsx25(LinkIcon3, { className: "size-4" }),
12271
- /* @__PURE__ */ jsx25("p", { children: "Add link" })
12600
+ /* @__PURE__ */ jsx26(LinkIcon3, { className: "size-4" }),
12601
+ /* @__PURE__ */ jsx26("p", { children: "Add link" })
12272
12602
  ]
12273
12603
  }
12274
12604
  ) }) }),
12275
- /* @__PURE__ */ jsx25(TooltipContent, { side: "bottom", children: hasHref ? `Edit link` : "Add link" })
12605
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", children: hasHref ? `Edit link` : "Add link" })
12276
12606
  ] }),
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(
12607
+ /* @__PURE__ */ jsxs13(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
12608
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2", children: [
12609
+ /* @__PURE__ */ jsx26(Label, { children: "Enter a link" }),
12610
+ /* @__PURE__ */ jsxs13(Popover, { open: isPresetOpen && availablePresets.length > 0, onOpenChange: setIsPresetOpen, children: [
12611
+ /* @__PURE__ */ jsx26(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
12612
+ /* @__PURE__ */ jsx26(
12283
12613
  Input,
12284
12614
  {
12285
12615
  type: linkType.inputType,
@@ -12293,19 +12623,19 @@ var HrefMenu = () => {
12293
12623
  autoFocus: true
12294
12624
  }
12295
12625
  ),
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" })
12626
+ /* @__PURE__ */ jsxs13(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
12627
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12628
+ /* @__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, {}) }) }) }),
12629
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
12300
12630
  ] }),
12301
- /* @__PURE__ */ jsx25(
12631
+ /* @__PURE__ */ jsx26(
12302
12632
  PopoverContent,
12303
12633
  {
12304
12634
  side: "bottom",
12305
12635
  align: "start",
12306
12636
  className: "w-[160px] p-1 z-50001",
12307
12637
  onPointerDownOutside: (e) => e.preventDefault(),
12308
- children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs12(
12638
+ children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs13(
12309
12639
  Button,
12310
12640
  {
12311
12641
  variant: "ghost",
@@ -12316,11 +12646,11 @@ var HrefMenu = () => {
12316
12646
  setIsLinkTypeOpen(false);
12317
12647
  },
12318
12648
  children: [
12319
- /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-2", children: [
12320
- /* @__PURE__ */ jsx25(type.icon, { className: "size-4" }),
12649
+ /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-2", children: [
12650
+ /* @__PURE__ */ jsx26(type.icon, { className: "size-4" }),
12321
12651
  type.name
12322
12652
  ] }),
12323
- linkType.name === type.name && /* @__PURE__ */ jsx25(CheckIcon3, { className: "size-4" })
12653
+ linkType.name === type.name && /* @__PURE__ */ jsx26(CheckIcon3, { className: "size-4" })
12324
12654
  ]
12325
12655
  },
12326
12656
  type.name
@@ -12329,14 +12659,14 @@ var HrefMenu = () => {
12329
12659
  )
12330
12660
  ] })
12331
12661
  ] }) }),
12332
- /* @__PURE__ */ jsx25(
12662
+ /* @__PURE__ */ jsx26(
12333
12663
  PopoverContent,
12334
12664
  {
12335
12665
  side: "bottom",
12336
12666
  align: "start",
12337
12667
  className: "w-[var(--radix-popover-trigger-width)] p-0 overflow-hidden z-50001",
12338
12668
  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(
12669
+ children: /* @__PURE__ */ jsx26("div", { className: "flex flex-col max-h-[200px] overflow-y-auto", children: availablePresets.map((preset) => /* @__PURE__ */ jsxs13(
12340
12670
  "button",
12341
12671
  {
12342
12672
  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 +12675,11 @@ var HrefMenu = () => {
12345
12675
  handlePresetSelect(preset.value);
12346
12676
  },
12347
12677
  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 })
12678
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-start gap-0.5", children: [
12679
+ /* @__PURE__ */ jsx26("span", { className: "text-xs text-muted-foreground", children: preset.label }),
12680
+ /* @__PURE__ */ jsx26("span", { className: "text-sm", children: preset.value })
12351
12681
  ] }),
12352
- inputValue === preset.value && /* @__PURE__ */ jsx25(CheckIcon3, { className: "w-4 h-4 shrink-0" })
12682
+ inputValue === preset.value && /* @__PURE__ */ jsx26(CheckIcon3, { className: "w-4 h-4 shrink-0" })
12353
12683
  ]
12354
12684
  },
12355
12685
  preset.key
@@ -12358,11 +12688,11 @@ var HrefMenu = () => {
12358
12688
  )
12359
12689
  ] })
12360
12690
  ] }),
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(
12691
+ /* @__PURE__ */ jsx26(Separator, { className: "my-2" }),
12692
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-row justify-between items-center", children: [
12693
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-row", children: [
12694
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12695
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
12366
12696
  Button,
12367
12697
  {
12368
12698
  variant: "ghost",
@@ -12370,13 +12700,13 @@ var HrefMenu = () => {
12370
12700
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12371
12701
  onClick: handleCopy,
12372
12702
  disabled: !hasHref,
12373
- children: showCopied ? /* @__PURE__ */ jsx25(CheckIcon3, { className: "text-green-600" }) : /* @__PURE__ */ jsx25(CopyIcon3, {})
12703
+ children: showCopied ? /* @__PURE__ */ jsx26(CheckIcon3, { className: "text-green-600" }) : /* @__PURE__ */ jsx26(CopyIcon3, {})
12374
12704
  }
12375
12705
  ) }),
12376
- /* @__PURE__ */ jsx25(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
12706
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
12377
12707
  ] }),
12378
- /* @__PURE__ */ jsxs12(Tooltip, { children: [
12379
- /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(
12708
+ /* @__PURE__ */ jsxs13(Tooltip, { children: [
12709
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
12380
12710
  Button,
12381
12711
  {
12382
12712
  variant: "ghost",
@@ -12384,13 +12714,13 @@ var HrefMenu = () => {
12384
12714
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12385
12715
  onClick: handleClear,
12386
12716
  disabled: !href,
12387
- children: /* @__PURE__ */ jsx25(TrashIcon3, {})
12717
+ children: /* @__PURE__ */ jsx26(TrashIcon3, {})
12388
12718
  }
12389
12719
  ) }),
12390
- /* @__PURE__ */ jsx25(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
12720
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
12391
12721
  ] })
12392
12722
  ] }),
12393
- /* @__PURE__ */ jsx25("div", { children: /* @__PURE__ */ jsx25(
12723
+ /* @__PURE__ */ jsx26("div", { children: /* @__PURE__ */ jsx26(
12394
12724
  Button,
12395
12725
  {
12396
12726
  variant: "default",
@@ -12405,14 +12735,14 @@ var HrefMenu = () => {
12405
12735
  };
12406
12736
 
12407
12737
  // src/core/editor/components/element-gear/button/float.tsx
12408
- import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
12738
+ import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
12409
12739
  var ButtonFloat = () => {
12410
12740
  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, {})
12741
+ return /* @__PURE__ */ jsxs14(Fragment6, { children: [
12742
+ hasHref && /* @__PURE__ */ jsx27(FloatLinkPreview, { href }),
12743
+ /* @__PURE__ */ jsx27(HrefMenu, {}),
12744
+ /* @__PURE__ */ jsx27(DuplicateButton, {}),
12745
+ /* @__PURE__ */ jsx27(DeleteButton, {})
12416
12746
  ] });
12417
12747
  };
12418
12748
 
@@ -12420,11 +12750,11 @@ var ButtonFloat = () => {
12420
12750
  import { ChevronsLeftRightIcon, ChevronsRightLeftIcon, MoreHorizontalIcon } from "lucide-react";
12421
12751
 
12422
12752
  // src/core/editor/hooks/use-full-width-toggle.ts
12423
- import { useCallback as useCallback5, useMemo as useMemo6 } from "react";
12753
+ import { useCallback as useCallback6, useMemo as useMemo7 } from "react";
12424
12754
  import { get as lodashGet3 } from "lodash";
12425
12755
  function useFullWidthToggle() {
12426
12756
  const { focusIdx, template, updateElement } = useEditorStore();
12427
- const { element, isFullWidth } = useMemo6(() => {
12757
+ const { element, isFullWidth } = useMemo7(() => {
12428
12758
  if (!focusIdx || !template) return { element: null, isFullWidth: false };
12429
12759
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
12430
12760
  const el = lodashGet3(template, path);
@@ -12433,7 +12763,7 @@ function useFullWidthToggle() {
12433
12763
  isFullWidth: el?.attributes?.["full-width"] === "full-width"
12434
12764
  };
12435
12765
  }, [focusIdx, template]);
12436
- const handleToggleFullWidth = useCallback5(() => {
12766
+ const handleToggleFullWidth = useCallback6(() => {
12437
12767
  if (!focusIdx || !element) return;
12438
12768
  const newAttributes = { ...element.attributes };
12439
12769
  if (isFullWidth) {
@@ -12447,20 +12777,20 @@ function useFullWidthToggle() {
12447
12777
  }
12448
12778
 
12449
12779
  // src/core/editor/components/element-gear/section/float.tsx
12450
- import { Fragment as Fragment7, jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
12780
+ import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
12451
12781
  var SectionFloat = () => {
12452
12782
  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" })
12783
+ return /* @__PURE__ */ jsxs15(Fragment7, { children: [
12784
+ /* @__PURE__ */ jsx28(DuplicateButton, {}),
12785
+ /* @__PURE__ */ jsx28(DeleteButton, {}),
12786
+ /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
12787
+ /* @__PURE__ */ jsxs15(Tooltip, { children: [
12788
+ /* @__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" }) }) }) }),
12789
+ /* @__PURE__ */ jsx28(TooltipContent, { side: "bottom", children: "More" })
12460
12790
  ] }),
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" })
12791
+ /* @__PURE__ */ jsx28(DropdownMenuContent, { side: "bottom", className: "w-[200px]", children: /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: handleToggleFullWidth, children: [
12792
+ isFullWidth ? /* @__PURE__ */ jsx28(ChevronsRightLeftIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx28(ChevronsLeftRightIcon, { className: "w-4 h-4" }),
12793
+ /* @__PURE__ */ jsx28("p", { children: isFullWidth ? "Reset to original width" : "Expand to full width" })
12464
12794
  ] }) })
12465
12795
  ] })
12466
12796
  ] });
@@ -12470,11 +12800,11 @@ var SectionFloat = () => {
12470
12800
  import { CheckIcon as CheckIcon4, ChevronsLeftRightIcon as ChevronsLeftRightIcon2, ChevronsRightLeftIcon as ChevronsRightLeftIcon2, Layers2Icon, MoreHorizontalIcon as MoreHorizontalIcon2 } from "lucide-react";
12471
12801
 
12472
12802
  // src/core/editor/hooks/use-no-wrap.ts
12473
- import { useCallback as useCallback6, useMemo as useMemo7 } from "react";
12803
+ import { useCallback as useCallback7, useMemo as useMemo8 } from "react";
12474
12804
  import { get as lodashGet4 } from "lodash";
12475
12805
  function useNoWrap() {
12476
12806
  const { focusIdx, template, updateElement } = useEditorStore();
12477
- const { element, noWrap } = useMemo7(() => {
12807
+ const { element, noWrap } = useMemo8(() => {
12478
12808
  if (!focusIdx || !template) return { element: null, noWrap: false };
12479
12809
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
12480
12810
  const el = lodashGet4(template, path);
@@ -12483,7 +12813,7 @@ function useNoWrap() {
12483
12813
  noWrap: el?.data?.value?.noWrap === true
12484
12814
  };
12485
12815
  }, [focusIdx, template]);
12486
- const handleToggleNoWrap = useCallback6(() => {
12816
+ const handleToggleNoWrap = useCallback7(() => {
12487
12817
  if (!focusIdx || !element) return;
12488
12818
  updateElement(focusIdx, {
12489
12819
  data: {
@@ -12498,30 +12828,30 @@ function useNoWrap() {
12498
12828
  }
12499
12829
 
12500
12830
  // 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";
12831
+ import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
12502
12832
  var SectionColumnFloat = () => {
12503
12833
  const { isFullWidth, handleToggleFullWidth } = useFullWidthToggle();
12504
12834
  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" })
12835
+ return /* @__PURE__ */ jsxs16(Fragment8, { children: [
12836
+ /* @__PURE__ */ jsx29(DuplicateButton, {}),
12837
+ /* @__PURE__ */ jsx29(DeleteButton, {}),
12838
+ /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
12839
+ /* @__PURE__ */ jsxs16(Tooltip, { children: [
12840
+ /* @__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" }) }) }) }),
12841
+ /* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", children: "More" })
12512
12842
  ] }),
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" })
12843
+ /* @__PURE__ */ jsxs16(DropdownMenuContent, { side: "bottom", className: "w-[250px]", children: [
12844
+ /* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: handleToggleNoWrap, children: [
12845
+ /* @__PURE__ */ jsx29(Layers2Icon, { className: "w-4 h-4" }),
12846
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 w-full", children: [
12847
+ /* @__PURE__ */ jsx29("p", { className: "w-full", children: noWrap ? "Columns collapse" : "Columns collapse" }),
12848
+ !noWrap && /* @__PURE__ */ jsx29(CheckIcon4, { className: "w-4 h-4" })
12519
12849
  ] })
12520
12850
  ] }),
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" })
12851
+ /* @__PURE__ */ jsx29(DropdownMenuSeparator, {}),
12852
+ /* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: handleToggleFullWidth, children: [
12853
+ isFullWidth ? /* @__PURE__ */ jsx29(ChevronsRightLeftIcon2, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx29(ChevronsLeftRightIcon2, { className: "w-4 h-4" }),
12854
+ /* @__PURE__ */ jsx29("p", { children: isFullWidth ? "Reset to original width" : "Expand to full width" })
12525
12855
  ] })
12526
12856
  ] })
12527
12857
  ] })
@@ -12529,11 +12859,11 @@ var SectionColumnFloat = () => {
12529
12859
  };
12530
12860
 
12531
12861
  // src/core/editor/components/element-gear/spacer/float.tsx
12532
- import { Fragment as Fragment9, jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
12862
+ import { Fragment as Fragment9, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
12533
12863
  var SpacerFloat = () => {
12534
- return /* @__PURE__ */ jsxs16(Fragment9, { children: [
12535
- /* @__PURE__ */ jsx29(DuplicateButton, {}),
12536
- /* @__PURE__ */ jsx29(DeleteButton, {})
12864
+ return /* @__PURE__ */ jsxs17(Fragment9, { children: [
12865
+ /* @__PURE__ */ jsx30(DuplicateButton, {}),
12866
+ /* @__PURE__ */ jsx30(DeleteButton, {})
12537
12867
  ] });
12538
12868
  };
12539
12869
 
@@ -12541,16 +12871,16 @@ var SpacerFloat = () => {
12541
12871
  import { MoreHorizontalIcon as MoreHorizontalIcon3, PlusCircleIcon } from "lucide-react";
12542
12872
 
12543
12873
  // 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";
12874
+ import { createContext, useContext, useState as useState5 } from "react";
12875
+ import { jsx as jsx31 } from "react/jsx-runtime";
12546
12876
  var SidebarContext = createContext(null);
12547
12877
  var PICKER_VIEWS = ["color", "images", "add-social"];
12548
12878
  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);
12879
+ const [activeView, setActiveViewState] = useState5("elements");
12880
+ const [lastView, setLastView] = useState5("elements");
12881
+ const [colorType, setColorType] = useState5("Color");
12882
+ const [colorTarget, setColorTarget] = useState5(null);
12883
+ const [imageTarget, setImageTarget] = useState5(null);
12554
12884
  const setActiveView = (view) => {
12555
12885
  if (view !== activeView) {
12556
12886
  if (!PICKER_VIEWS.includes(activeView)) {
@@ -12559,7 +12889,7 @@ function SidebarProvider({ children }) {
12559
12889
  }
12560
12890
  setActiveViewState(view);
12561
12891
  };
12562
- return /* @__PURE__ */ jsx30(SidebarContext.Provider, { value: { activeView, setActiveView, lastView, colorType, setColorType, colorTarget, setColorTarget, imageTarget, setImageTarget }, children });
12892
+ return /* @__PURE__ */ jsx31(SidebarContext.Provider, { value: { activeView, setActiveView, lastView, colorType, setColorType, colorTarget, setColorTarget, imageTarget, setImageTarget }, children });
12563
12893
  }
12564
12894
  function useSidebarContext() {
12565
12895
  const context = useContext(SidebarContext);
@@ -12570,33 +12900,33 @@ function useSidebarContext() {
12570
12900
  }
12571
12901
 
12572
12902
  // src/core/editor/components/element-gear/social/float.tsx
12573
- import { Fragment as Fragment10, jsx as jsx31, jsxs as jsxs17 } from "react/jsx-runtime";
12903
+ import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
12574
12904
  var SocialFloat = () => {
12575
12905
  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" })
12906
+ return /* @__PURE__ */ jsxs18(Fragment10, { children: [
12907
+ /* @__PURE__ */ jsxs18(Tooltip, { children: [
12908
+ /* @__PURE__ */ jsx32(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(Button, { variant: "ghost", className: floatButtonVariants, onClick: () => setActiveView("add-social"), children: /* @__PURE__ */ jsx32(PlusCircleIcon, {}) }) }),
12909
+ /* @__PURE__ */ jsx32(TooltipContent, { side: "bottom", children: "Add Social" })
12580
12910
  ] }),
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" })
12911
+ /* @__PURE__ */ jsx32(DuplicateButton, {}),
12912
+ /* @__PURE__ */ jsx32(DeleteButton, {}),
12913
+ /* @__PURE__ */ jsxs18(DropdownMenu, { children: [
12914
+ /* @__PURE__ */ jsxs18(Tooltip, { children: [
12915
+ /* @__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" }) }) }) }),
12916
+ /* @__PURE__ */ jsx32(TooltipContent, { side: "bottom", children: "More" })
12587
12917
  ] }),
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" })
12918
+ /* @__PURE__ */ jsx32(DropdownMenuContent, { side: "bottom", className: "w-[200px]", children: /* @__PURE__ */ jsxs18(DropdownMenuItem, { onClick: () => setActiveView("add-social"), children: [
12919
+ /* @__PURE__ */ jsx32(PlusCircleIcon, { className: "w-4 h-4" }),
12920
+ /* @__PURE__ */ jsx32("p", { children: "Add Social" })
12591
12921
  ] }) })
12592
12922
  ] })
12593
12923
  ] });
12594
12924
  };
12595
12925
 
12596
12926
  // src/components/ui/textarea.tsx
12597
- import { jsx as jsx32 } from "react/jsx-runtime";
12927
+ import { jsx as jsx33 } from "react/jsx-runtime";
12598
12928
  function Textarea({ className, ...props }) {
12599
- return /* @__PURE__ */ jsx32(
12929
+ return /* @__PURE__ */ jsx33(
12600
12930
  "textarea",
12601
12931
  {
12602
12932
  "data-slot": "textarea",
@@ -12611,38 +12941,38 @@ function Textarea({ className, ...props }) {
12611
12941
 
12612
12942
  // src/core/editor/components/element-gear/social-item/float.tsx
12613
12943
  import { Accessibility, MoreHorizontalIcon as MoreHorizontalIcon4, TrashIcon as TrashIcon4 } from "lucide-react";
12614
- import { useState as useState6, useEffect as useEffect9 } from "react";
12944
+ import { useState as useState7, useEffect as useEffect10 } from "react";
12615
12945
 
12616
12946
  // src/core/editor/components/social-item-menu.tsx
12617
- import { useState as useState5, useEffect as useEffect8, useMemo as useMemo8, useCallback as useCallback7 } from "react";
12947
+ import { useState as useState6, useEffect as useEffect9, useMemo as useMemo9, useCallback as useCallback8 } from "react";
12618
12948
  import { PencilIcon as PencilIcon3, CheckIcon as CheckIcon5, CopyIcon as CopyIcon4 } from "lucide-react";
12619
12949
  import { get as lodashGet5 } from "lodash";
12620
- import { jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
12950
+ import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
12621
12951
  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("");
12952
+ const [isOpen, setIsOpen] = useState6(false);
12953
+ const [showCopied, setShowCopied] = useState6(false);
12954
+ const [hrefInputValue, setHrefInputValue] = useState6("");
12955
+ const [contentInputValue, setContentInputValue] = useState6("");
12626
12956
  const { href, setHref, copyHref } = useHref();
12627
12957
  const { focusIdx, template, updateElement } = useEditorStore();
12628
- const element = useMemo8(() => {
12958
+ const element = useMemo9(() => {
12629
12959
  if (!focusIdx || !template) return null;
12630
12960
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.?\[(\d+)\]/g, "[$1]") : focusIdx;
12631
12961
  return lodashGet5(template, path);
12632
12962
  }, [focusIdx, template]);
12633
12963
  const content = element?.data?.value?.content || "";
12634
- useEffect8(() => {
12964
+ useEffect9(() => {
12635
12965
  if (isOpen) {
12636
12966
  setHrefInputValue(href);
12637
12967
  setContentInputValue(content);
12638
12968
  }
12639
12969
  }, [isOpen, href, content]);
12640
- const handleCopy = useCallback7(async () => {
12970
+ const handleCopy = useCallback8(async () => {
12641
12971
  await copyHref();
12642
12972
  setShowCopied(true);
12643
12973
  setTimeout(() => setShowCopied(false), 2e3);
12644
12974
  }, [copyHref]);
12645
- const handleDone = useCallback7(() => {
12975
+ const handleDone = useCallback8(() => {
12646
12976
  setHref(normalizeWebsiteUrl(hrefInputValue));
12647
12977
  if (focusIdx && element) {
12648
12978
  updateElement(focusIdx, {
@@ -12656,33 +12986,33 @@ var SocialItemMenu = ({ hasHref }) => {
12656
12986
  }
12657
12987
  setIsOpen(false);
12658
12988
  }, [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(
12989
+ return /* @__PURE__ */ jsxs19(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
12990
+ /* @__PURE__ */ jsxs19(Tooltip, { children: [
12991
+ /* @__PURE__ */ jsx34(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ jsx34(
12662
12992
  Button,
12663
12993
  {
12664
12994
  variant: "ghost",
12665
12995
  size: "icon",
12666
12996
  className: floatButtonVariants,
12667
- children: /* @__PURE__ */ jsx33(PencilIcon3, { className: "size-4" })
12997
+ children: /* @__PURE__ */ jsx34(PencilIcon3, { className: "size-4" })
12668
12998
  }
12669
- ) : /* @__PURE__ */ jsxs18(
12999
+ ) : /* @__PURE__ */ jsxs19(
12670
13000
  Button,
12671
13001
  {
12672
13002
  variant: "ghost",
12673
13003
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12674
13004
  children: [
12675
- /* @__PURE__ */ jsx33(PencilIcon3, { className: "size-4" }),
12676
- /* @__PURE__ */ jsx33("p", { children: "Edit" })
13005
+ /* @__PURE__ */ jsx34(PencilIcon3, { className: "size-4" }),
13006
+ /* @__PURE__ */ jsx34("p", { children: "Edit" })
12677
13007
  ]
12678
13008
  }
12679
13009
  ) }) }),
12680
- /* @__PURE__ */ jsx33(TooltipContent, { side: "bottom", children: "Edit" })
13010
+ /* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", children: "Edit" })
12681
13011
  ] }),
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(
13012
+ /* @__PURE__ */ jsxs19(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
13013
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2 mb-2", children: [
13014
+ /* @__PURE__ */ jsx34(Label, { className: "text-xs font-medium", children: "Enter a link" }),
13015
+ /* @__PURE__ */ jsx34(
12686
13016
  Input,
12687
13017
  {
12688
13018
  type: "text",
@@ -12694,9 +13024,9 @@ var SocialItemMenu = ({ hasHref }) => {
12694
13024
  }
12695
13025
  )
12696
13026
  ] }),
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(
13027
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2", children: [
13028
+ /* @__PURE__ */ jsx34(Label, { className: "text-xs font-medium", children: "Content" }),
13029
+ /* @__PURE__ */ jsx34(
12700
13030
  Input,
12701
13031
  {
12702
13032
  type: "text",
@@ -12707,10 +13037,10 @@ var SocialItemMenu = ({ hasHref }) => {
12707
13037
  }
12708
13038
  )
12709
13039
  ] }),
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(
13040
+ /* @__PURE__ */ jsx34(Separator, { className: "my-2" }),
13041
+ /* @__PURE__ */ jsxs19("div", { className: "flex flex-row justify-between items-center", children: [
13042
+ /* @__PURE__ */ jsx34("div", { className: "flex flex-row", children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
13043
+ /* @__PURE__ */ jsx34(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(
12714
13044
  Button,
12715
13045
  {
12716
13046
  variant: "ghost",
@@ -12718,12 +13048,12 @@ var SocialItemMenu = ({ hasHref }) => {
12718
13048
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
12719
13049
  onClick: handleCopy,
12720
13050
  disabled: !hasHref,
12721
- children: showCopied ? /* @__PURE__ */ jsx33(CheckIcon5, { className: "text-green-600" }) : /* @__PURE__ */ jsx33(CopyIcon4, {})
13051
+ children: showCopied ? /* @__PURE__ */ jsx34(CheckIcon5, { className: "text-green-600" }) : /* @__PURE__ */ jsx34(CopyIcon4, {})
12722
13052
  }
12723
13053
  ) }),
12724
- /* @__PURE__ */ jsx33(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
13054
+ /* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
12725
13055
  ] }) }),
12726
- /* @__PURE__ */ jsx33("div", { children: /* @__PURE__ */ jsx33(
13056
+ /* @__PURE__ */ jsx34("div", { children: /* @__PURE__ */ jsx34(
12727
13057
  Button,
12728
13058
  {
12729
13059
  variant: "default",
@@ -12738,11 +13068,11 @@ var SocialItemMenu = ({ hasHref }) => {
12738
13068
  };
12739
13069
 
12740
13070
  // src/core/editor/hooks/use-alt.ts
12741
- import { useMemo as useMemo9, useCallback as useCallback8 } from "react";
13071
+ import { useMemo as useMemo10, useCallback as useCallback9 } from "react";
12742
13072
  import { get as lodashGet6 } from "lodash";
12743
13073
  var useAlt = () => {
12744
13074
  const { focusIdx, updateElement, template } = useEditorStore();
12745
- const { element, alt } = useMemo9(() => {
13075
+ const { element, alt } = useMemo10(() => {
12746
13076
  if (!focusIdx || !template) {
12747
13077
  return { element: null, alt: "" };
12748
13078
  }
@@ -12753,13 +13083,13 @@ var useAlt = () => {
12753
13083
  alt: el?.attributes?.alt || ""
12754
13084
  };
12755
13085
  }, [focusIdx, template]);
12756
- const setAlt = useCallback8((text2) => {
13086
+ const setAlt = useCallback9((text2) => {
12757
13087
  if (!focusIdx || !element) return;
12758
13088
  updateElement(focusIdx, {
12759
13089
  attributes: { ...element.attributes, alt: text2 }
12760
13090
  });
12761
13091
  }, [focusIdx, element, updateElement]);
12762
- const clearAlt = useCallback8(() => {
13092
+ const clearAlt = useCallback9(() => {
12763
13093
  if (!focusIdx || !element) return;
12764
13094
  updateElement(focusIdx, {
12765
13095
  attributes: { ...element.attributes, alt: "" }
@@ -12775,17 +13105,17 @@ var useAlt = () => {
12775
13105
  };
12776
13106
 
12777
13107
  // 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";
13108
+ import { Fragment as Fragment11, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
12779
13109
  var SocialItemFloat = () => {
12780
13110
  const { href, hasHref } = useHref();
12781
13111
  const { alt, setAlt } = useAlt();
12782
13112
  const { focusIdx, template, deleteElement } = useEditorStore();
12783
- const [dropdownOpen, setDropdownOpen] = useState6(false);
12784
- const [altInputValue, setAltInputValue] = useState6("");
13113
+ const [dropdownOpen, setDropdownOpen] = useState7(false);
13114
+ const [altInputValue, setAltInputValue] = useState7("");
12785
13115
  const parentSocial = focusIdx ? getParentByIdx(template, focusIdx) : null;
12786
13116
  const childrenCount = parentSocial?.children?.length || 0;
12787
13117
  const canDelete = childrenCount > 1;
12788
- useEffect9(() => {
13118
+ useEffect10(() => {
12789
13119
  if (dropdownOpen) {
12790
13120
  setAltInputValue(alt);
12791
13121
  }
@@ -12799,37 +13129,37 @@ var SocialItemFloat = () => {
12799
13129
  deleteElement(focusIdx);
12800
13130
  }
12801
13131
  };
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(
13132
+ return /* @__PURE__ */ jsxs20(Fragment11, { children: [
13133
+ hasHref && /* @__PURE__ */ jsx35(FloatLinkPreview, { href }),
13134
+ /* @__PURE__ */ jsx35(SocialItemMenu, { hasHref }),
13135
+ /* @__PURE__ */ jsxs20(Tooltip, { children: [
13136
+ /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35(
12807
13137
  Button,
12808
13138
  {
12809
13139
  variant: "ghost",
12810
13140
  className: floatButtonVariants,
12811
13141
  onClick: handleDelete,
12812
13142
  disabled: !canDelete,
12813
- children: /* @__PURE__ */ jsx34(TrashIcon4, { className: "size-4" })
13143
+ children: /* @__PURE__ */ jsx35(TrashIcon4, { className: "size-4" })
12814
13144
  }
12815
13145
  ) }),
12816
- /* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", children: canDelete ? "Delete" : "Cannot delete last item" })
13146
+ /* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", children: canDelete ? "Delete" : "Cannot delete last item" })
12817
13147
  ] }),
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" })
13148
+ /* @__PURE__ */ jsxs20(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
13149
+ /* @__PURE__ */ jsxs20(Tooltip, { children: [
13150
+ /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx35(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx35(MoreHorizontalIcon4, { className: "w-4 h-4" }) }) }) }),
13151
+ /* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", children: "More" })
12822
13152
  ] }),
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" })
13153
+ /* @__PURE__ */ jsx35(DropdownMenuContent, { side: "bottom", className: "w-[250px] z-50001", children: /* @__PURE__ */ jsxs20(DropdownMenuSub, { children: [
13154
+ /* @__PURE__ */ jsxs20(DropdownMenuSubTrigger, { children: [
13155
+ /* @__PURE__ */ jsx35(Accessibility, { className: "w-4 h-4" }),
13156
+ /* @__PURE__ */ jsx35("p", { children: "Alternative Text" })
12827
13157
  ] }),
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(
13158
+ /* @__PURE__ */ jsx35(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs20(DropdownMenuSubContent, { className: "p-3 w-[250px] z-50001", children: [
13159
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-2 mb-2", children: [
13160
+ /* @__PURE__ */ jsx35(Label, { children: "Alternative Text" }),
13161
+ /* @__PURE__ */ jsxs20("div", { className: "relative", children: [
13162
+ /* @__PURE__ */ jsx35(
12833
13163
  Textarea,
12834
13164
  {
12835
13165
  placeholder: "Icon image alt, for example: 'Facebook icon'",
@@ -12839,14 +13169,14 @@ var SocialItemFloat = () => {
12839
13169
  onChange: (e) => setAltInputValue(e.target.value)
12840
13170
  }
12841
13171
  ),
12842
- /* @__PURE__ */ jsxs19("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
13172
+ /* @__PURE__ */ jsxs20("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
12843
13173
  altInputValue.length,
12844
13174
  "/250"
12845
13175
  ] })
12846
13176
  ] }),
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." })
13177
+ /* @__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
13178
  ] }),
12849
- /* @__PURE__ */ jsx34(
13179
+ /* @__PURE__ */ jsx35(
12850
13180
  Button,
12851
13181
  {
12852
13182
  variant: "default",
@@ -12862,27 +13192,27 @@ var SocialItemFloat = () => {
12862
13192
  };
12863
13193
 
12864
13194
  // src/core/editor/components/element-gear/divider/float.tsx
12865
- import { Fragment as Fragment12, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
13195
+ import { Fragment as Fragment12, jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
12866
13196
  var DividerFloat = () => {
12867
- return /* @__PURE__ */ jsxs20(Fragment12, { children: [
12868
- /* @__PURE__ */ jsx35(DuplicateButton, {}),
12869
- /* @__PURE__ */ jsx35(DeleteButton, {})
13197
+ return /* @__PURE__ */ jsxs21(Fragment12, { children: [
13198
+ /* @__PURE__ */ jsx36(DuplicateButton, {}),
13199
+ /* @__PURE__ */ jsx36(DeleteButton, {})
12870
13200
  ] });
12871
13201
  };
12872
13202
 
12873
13203
  // src/core/editor/components/element-gear/image/float.tsx
12874
13204
  import { Accessibility as Accessibility2, CheckIcon as CheckIcon6, MoreHorizontalIcon as MoreHorizontalIcon5, Proportions } from "lucide-react";
12875
13205
  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";
13206
+ import { useState as useState8, useEffect as useEffect11, useMemo as useMemo11, useCallback as useCallback10 } from "react";
13207
+ import { Fragment as Fragment13, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
12878
13208
  var ImageFloat = () => {
12879
13209
  const { href, hasHref } = useHref();
12880
13210
  const { alt, setAlt, hasAlt } = useAlt();
12881
13211
  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(() => {
13212
+ const [showMoreView, setShowMoreView] = useState8(null);
13213
+ const [dropdownOpen, setDropdownOpen] = useState8(false);
13214
+ const [altInputValue, setAltInputValue] = useState8("");
13215
+ const { element, isFluidOnMobile } = useMemo11(() => {
12886
13216
  if (!focusIdx || !template) return { element: null, isFluidOnMobile: false };
12887
13217
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
12888
13218
  const el = lodashGet7(template, path);
@@ -12891,7 +13221,7 @@ var ImageFloat = () => {
12891
13221
  isFluidOnMobile: el?.attributes?.["fluid-on-mobile"] === "true"
12892
13222
  };
12893
13223
  }, [focusIdx, template]);
12894
- const toggleFluidOnMobile = useCallback9(() => {
13224
+ const toggleFluidOnMobile = useCallback10(() => {
12895
13225
  if (!focusIdx || !element) return;
12896
13226
  const newAttributes = { ...element.attributes };
12897
13227
  if (isFluidOnMobile) {
@@ -12901,7 +13231,7 @@ var ImageFloat = () => {
12901
13231
  }
12902
13232
  updateElement(focusIdx, { attributes: newAttributes });
12903
13233
  }, [focusIdx, element, isFluidOnMobile, updateElement]);
12904
- useEffect10(() => {
13234
+ useEffect11(() => {
12905
13235
  if (dropdownOpen) {
12906
13236
  setAltInputValue(alt);
12907
13237
  }
@@ -12910,35 +13240,35 @@ var ImageFloat = () => {
12910
13240
  setAlt(altInputValue);
12911
13241
  setDropdownOpen(false);
12912
13242
  };
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" })
13243
+ return /* @__PURE__ */ jsxs22(Fragment13, { children: [
13244
+ hasHref && /* @__PURE__ */ jsx37(FloatLinkPreview, { href }),
13245
+ /* @__PURE__ */ jsx37(HrefMenu, {}),
13246
+ /* @__PURE__ */ jsx37(DuplicateButton, {}),
13247
+ /* @__PURE__ */ jsx37(DeleteButton, {}),
13248
+ /* @__PURE__ */ jsxs22(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
13249
+ /* @__PURE__ */ jsxs22(Tooltip, { children: [
13250
+ /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ jsx37(MoreHorizontalIcon5, { className: "w-4 h-4" }) }) }) }),
13251
+ /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", children: "More" })
12922
13252
  ] }),
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" })
13253
+ /* @__PURE__ */ jsxs22(DropdownMenuContent, { side: "bottom", className: "w-[250px] z-50001", children: [
13254
+ /* @__PURE__ */ jsxs22(DropdownMenuItem, { onClick: toggleFluidOnMobile, children: [
13255
+ /* @__PURE__ */ jsx37(Proportions, { className: "w-4 h-4" }),
13256
+ /* @__PURE__ */ jsxs22("div", { className: "flex flex-row items-center justify-between gap-2 w-full", children: [
13257
+ /* @__PURE__ */ jsx37("p", { children: "Full width on mobile" }),
13258
+ isFluidOnMobile && /* @__PURE__ */ jsx37(CheckIcon6, { className: "w-4 h-4" })
12929
13259
  ] })
12930
13260
  ] }),
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" })
13261
+ /* @__PURE__ */ jsx37(DropdownMenuSeparator, {}),
13262
+ /* @__PURE__ */ jsxs22(DropdownMenuSub, { children: [
13263
+ /* @__PURE__ */ jsxs22(DropdownMenuSubTrigger, { children: [
13264
+ /* @__PURE__ */ jsx37(Accessibility2, { className: "w-4 h-4" }),
13265
+ /* @__PURE__ */ jsx37("p", { children: "Alternative Text" })
12936
13266
  ] }),
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(
13267
+ /* @__PURE__ */ jsx37(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs22(DropdownMenuSubContent, { className: "p-3 w-[250px] z-50001", children: [
13268
+ /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2 mb-2", children: [
13269
+ /* @__PURE__ */ jsx37(Label, { children: "Alternative Text" }),
13270
+ /* @__PURE__ */ jsxs22("div", { className: "relative", children: [
13271
+ /* @__PURE__ */ jsx37(
12942
13272
  Textarea,
12943
13273
  {
12944
13274
  placeholder: "Spacious living room with hardwood floors, large windows, and a cozy fireplace",
@@ -12948,14 +13278,14 @@ var ImageFloat = () => {
12948
13278
  onChange: (e) => setAltInputValue(e.target.value)
12949
13279
  }
12950
13280
  ),
12951
- /* @__PURE__ */ jsxs21("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
13281
+ /* @__PURE__ */ jsxs22("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
12952
13282
  altInputValue.length,
12953
13283
  "/250"
12954
13284
  ] })
12955
13285
  ] }),
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." })
13286
+ /* @__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
13287
  ] }),
12958
- /* @__PURE__ */ jsx36(
13288
+ /* @__PURE__ */ jsx37(
12959
13289
  Button,
12960
13290
  {
12961
13291
  variant: "default",
@@ -12972,7 +13302,7 @@ var ImageFloat = () => {
12972
13302
  };
12973
13303
 
12974
13304
  // src/core/editor/components/mlsNumber-menu.tsx
12975
- import { useState as useState8, useEffect as useEffect11 } from "react";
13305
+ import { useState as useState9, useEffect as useEffect12 } from "react";
12976
13306
  import { HousePlusIcon, TrashIcon as TrashIcon5, XIcon as XIcon2, Loader2Icon } from "lucide-react";
12977
13307
 
12978
13308
  // src/services/repliers/commands.ts
@@ -12988,16 +13318,16 @@ async function getListingByMlsNumber(mlsNumber) {
12988
13318
  }
12989
13319
 
12990
13320
  // src/core/editor/components/mlsNumber-menu.tsx
12991
- import { Fragment as Fragment14, jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
13321
+ import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
12992
13322
  var MlsNumberMenu = () => {
12993
13323
  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);
13324
+ const [isOpen, setIsOpen] = useState9(false);
13325
+ const [inputValue, setInputValue] = useState9("");
13326
+ const [propertyData, setPropertyData] = useState9(null);
13327
+ const [isLoading, setIsLoading] = useState9(false);
12998
13328
  const propertyElement = focusIdx && template ? getValueByIdx(template, focusIdx) : null;
12999
13329
  const currentMlsNumber = propertyElement?.data?.value?.mlsNumber || "";
13000
- useEffect11(() => {
13330
+ useEffect12(() => {
13001
13331
  setInputValue(currentMlsNumber);
13002
13332
  setPropertyData(null);
13003
13333
  }, [focusIdx, currentMlsNumber]);
@@ -13065,25 +13395,25 @@ var MlsNumberMenu = () => {
13065
13395
  }
13066
13396
  }
13067
13397
  };
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(
13398
+ return /* @__PURE__ */ jsxs23(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
13399
+ /* @__PURE__ */ jsxs23(Tooltip, { children: [
13400
+ /* @__PURE__ */ jsx38(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx38(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs23(
13071
13401
  Button,
13072
13402
  {
13073
13403
  variant: "ghost",
13074
13404
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
13075
13405
  children: [
13076
- /* @__PURE__ */ jsx37(HousePlusIcon, { className: "size-4" }),
13077
- /* @__PURE__ */ jsx37("p", { children: "MLS" })
13406
+ /* @__PURE__ */ jsx38(HousePlusIcon, { className: "size-4" }),
13407
+ /* @__PURE__ */ jsx38("p", { children: "MLS" })
13078
13408
  ]
13079
13409
  }
13080
13410
  ) }) }),
13081
- /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", children: "Enter MLS Number" })
13411
+ /* @__PURE__ */ jsx38(TooltipContent, { side: "bottom", children: "Enter MLS Number" })
13082
13412
  ] }),
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(
13413
+ /* @__PURE__ */ jsxs23(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
13414
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2", children: [
13415
+ /* @__PURE__ */ jsx38(Label, { children: "Enter MLS Number" }),
13416
+ /* @__PURE__ */ jsx38(
13087
13417
  Input,
13088
13418
  {
13089
13419
  type: "text",
@@ -13096,10 +13426,10 @@ var MlsNumberMenu = () => {
13096
13426
  }
13097
13427
  )
13098
13428
  ] }),
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(
13429
+ /* @__PURE__ */ jsx38(Separator, { className: "my-2" }),
13430
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-row justify-between items-center", children: [
13431
+ /* @__PURE__ */ jsx38("div", { className: "flex flex-row", children: /* @__PURE__ */ jsxs23(Tooltip, { children: [
13432
+ /* @__PURE__ */ jsx38(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx38(
13103
13433
  Button,
13104
13434
  {
13105
13435
  variant: "ghost",
@@ -13107,27 +13437,27 @@ var MlsNumberMenu = () => {
13107
13437
  className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
13108
13438
  onClick: handleClear,
13109
13439
  disabled: !inputValue,
13110
- children: /* @__PURE__ */ jsx37(TrashIcon5, {})
13440
+ children: /* @__PURE__ */ jsx38(TrashIcon5, {})
13111
13441
  }
13112
13442
  ) }),
13113
- /* @__PURE__ */ jsx37(TooltipContent, { side: "bottom", className: "z-50001", children: "Clear" })
13443
+ /* @__PURE__ */ jsx38(TooltipContent, { side: "bottom", className: "z-50001", children: "Clear" })
13114
13444
  ] }) }),
13115
- /* @__PURE__ */ jsx37("div", { children: /* @__PURE__ */ jsx37(
13445
+ /* @__PURE__ */ jsx38("div", { children: /* @__PURE__ */ jsx38(
13116
13446
  Button,
13117
13447
  {
13118
13448
  variant: "default",
13119
13449
  className: "shadow-none transition-none cursor-pointer rounded-[12px] outline-none",
13120
13450
  onClick: handleDone,
13121
13451
  disabled: isLoading || !inputValue.trim(),
13122
- children: isLoading ? /* @__PURE__ */ jsx37(Loader2Icon, { className: "size-4 animate-spin" }) : "Done"
13452
+ children: isLoading ? /* @__PURE__ */ jsx38(Loader2Icon, { className: "size-4 animate-spin" }) : "Done"
13123
13453
  }
13124
13454
  ) })
13125
13455
  ] }),
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(
13456
+ propertyData && /* @__PURE__ */ jsxs23(Fragment14, { children: [
13457
+ /* @__PURE__ */ jsx38(Separator, { className: "my-2" }),
13458
+ /* @__PURE__ */ jsxs23("div", { className: "rounded-[12px] border overflow-hidden bg-card", children: [
13459
+ /* @__PURE__ */ jsxs23("div", { className: "relative", children: [
13460
+ /* @__PURE__ */ jsx38(
13131
13461
  "img",
13132
13462
  {
13133
13463
  src: `https://cdn.repliers.io/${propertyData.images?.[0]}`,
@@ -13135,35 +13465,35 @@ var MlsNumberMenu = () => {
13135
13465
  className: "w-full h-[120px] object-cover"
13136
13466
  }
13137
13467
  ),
13138
- /* @__PURE__ */ jsx37(
13468
+ /* @__PURE__ */ jsx38(
13139
13469
  Button,
13140
13470
  {
13141
13471
  variant: "ghost",
13142
13472
  size: "icon",
13143
13473
  className: "absolute top-1 right-1 h-6 w-6 bg-black/50 hover:bg-black/70 rounded-full",
13144
13474
  onClick: handleClearPreview,
13145
- children: /* @__PURE__ */ jsx37(XIcon2, { className: "size-3 text-white" })
13475
+ children: /* @__PURE__ */ jsx38(XIcon2, { className: "size-3 text-white" })
13146
13476
  }
13147
13477
  )
13148
13478
  ] }),
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 })
13479
+ /* @__PURE__ */ jsxs23("div", { className: "p-2 flex flex-col gap-1", children: [
13480
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between", children: [
13481
+ /* @__PURE__ */ jsx38("span", { className: "font-semibold text-sm", children: formatPrice(String(propertyData.listPrice || 0)) }),
13482
+ /* @__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
13483
  ] }),
13154
- /* @__PURE__ */ jsxs22("div", { className: "text-sm", children: [
13484
+ /* @__PURE__ */ jsxs23("div", { className: "text-sm", children: [
13155
13485
  propertyData.address?.streetNumber,
13156
13486
  " ",
13157
13487
  propertyData.address?.streetName
13158
13488
  ] }),
13159
- /* @__PURE__ */ jsxs22("div", { className: "text-xs text-muted-foreground", children: [
13489
+ /* @__PURE__ */ jsxs23("div", { className: "text-xs text-muted-foreground", children: [
13160
13490
  propertyData.address?.city,
13161
13491
  ", ",
13162
13492
  propertyData.address?.state,
13163
13493
  " ",
13164
13494
  propertyData.address?.zip
13165
13495
  ] }),
13166
- /* @__PURE__ */ jsxs22("div", { className: "text-xs text-muted-foreground", children: [
13496
+ /* @__PURE__ */ jsxs23("div", { className: "text-xs text-muted-foreground", children: [
13167
13497
  propertyData.details?.numBedrooms,
13168
13498
  " bd | ",
13169
13499
  propertyData.details?.numBathrooms,
@@ -13171,8 +13501,8 @@ var MlsNumberMenu = () => {
13171
13501
  formatNumber(String(propertyData.details?.sqft || "--")),
13172
13502
  " sf"
13173
13503
  ] }),
13174
- propertyData.office?.brokerageName && /* @__PURE__ */ jsx37("div", { className: "text-xs text-muted-foreground truncate", children: propertyData.office.brokerageName }),
13175
- /* @__PURE__ */ jsx37(
13504
+ propertyData.office?.brokerageName && /* @__PURE__ */ jsx38("div", { className: "text-xs text-muted-foreground truncate", children: propertyData.office.brokerageName }),
13505
+ /* @__PURE__ */ jsx38(
13176
13506
  Button,
13177
13507
  {
13178
13508
  variant: "default",
@@ -13190,34 +13520,34 @@ var MlsNumberMenu = () => {
13190
13520
  };
13191
13521
 
13192
13522
  // src/core/editor/components/element-gear/property/float.tsx
13193
- import { Fragment as Fragment15, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
13523
+ import { Fragment as Fragment15, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
13194
13524
  function PropertyFloat() {
13195
13525
  const { href, hasHref } = useHref();
13196
- return /* @__PURE__ */ jsxs23(Fragment15, { children: [
13197
- hasHref && /* @__PURE__ */ jsx38(FloatLinkPreview, { href }),
13198
- /* @__PURE__ */ jsx38(HrefMenu, {}),
13199
- /* @__PURE__ */ jsx38(MlsNumberMenu, {})
13526
+ return /* @__PURE__ */ jsxs24(Fragment15, { children: [
13527
+ hasHref && /* @__PURE__ */ jsx39(FloatLinkPreview, { href }),
13528
+ /* @__PURE__ */ jsx39(HrefMenu, {}),
13529
+ /* @__PURE__ */ jsx39(MlsNumberMenu, {})
13200
13530
  ] });
13201
13531
  }
13202
13532
 
13203
13533
  // 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";
13534
+ import { Fragment as Fragment16, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
13205
13535
  var PropertyTripleItemFloat = () => {
13206
13536
  const { href, hasHref } = useHref();
13207
- return /* @__PURE__ */ jsxs24(Fragment16, { children: [
13208
- hasHref && /* @__PURE__ */ jsx39(FloatLinkPreview, { href }),
13209
- /* @__PURE__ */ jsx39(HrefMenu, {})
13537
+ return /* @__PURE__ */ jsxs25(Fragment16, { children: [
13538
+ hasHref && /* @__PURE__ */ jsx40(FloatLinkPreview, { href }),
13539
+ /* @__PURE__ */ jsx40(HrefMenu, {})
13210
13540
  ] });
13211
13541
  };
13212
13542
 
13213
13543
  // src/core/editor/components/float-ui/container.tsx
13214
- import { jsx as jsx40 } from "react/jsx-runtime";
13544
+ import { jsx as jsx41 } from "react/jsx-runtime";
13215
13545
  var FloatUIContainer = ({ ref, style, className, children }) => {
13216
- return /* @__PURE__ */ jsx40("div", { ref, style, className, children });
13546
+ return /* @__PURE__ */ jsx41("div", { ref, style, className, children });
13217
13547
  };
13218
13548
 
13219
13549
  // src/core/editor/components/element-float.tsx
13220
- import { jsx as jsx41 } from "react/jsx-runtime";
13550
+ import { jsx as jsx42 } from "react/jsx-runtime";
13221
13551
  var FLOAT_COMPONENTS = {
13222
13552
  "button": ButtonFloat,
13223
13553
  "section": SectionFloat,
@@ -13241,7 +13571,7 @@ var ElementFloat = ({ getReferenceRect, focusIdx, elementType }) => {
13241
13571
  if (!focusIdx || isDragging || textEditing) return null;
13242
13572
  const FloatComponent = FLOAT_COMPONENTS[elementType];
13243
13573
  if (!FloatComponent) return null;
13244
- return /* @__PURE__ */ jsx41(
13574
+ return /* @__PURE__ */ jsx42(
13245
13575
  ElementFloatContent,
13246
13576
  {
13247
13577
  getReferenceRect,
@@ -13250,7 +13580,7 @@ var ElementFloat = ({ getReferenceRect, focusIdx, elementType }) => {
13250
13580
  );
13251
13581
  };
13252
13582
  var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13253
- const virtualReference = useMemo11(() => ({
13583
+ const virtualReference = useMemo12(() => ({
13254
13584
  getBoundingClientRect: () => {
13255
13585
  const rect = getReferenceRect();
13256
13586
  if (!rect) {
@@ -13259,18 +13589,18 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13259
13589
  return rect;
13260
13590
  }
13261
13591
  }), [getReferenceRect]);
13262
- const { floatingStyles, refs, update } = useFloating4({
13592
+ const { floatingStyles, refs, update } = useFloating5({
13263
13593
  placement: "top",
13264
13594
  middleware: [
13265
- offset4(16),
13595
+ offset5(16),
13266
13596
  // 8px above the element
13267
- flip2({ padding: 8 }),
13597
+ flip3({ padding: 8 }),
13268
13598
  // Flip to bottom if not enough space above
13269
- shift3({ padding: 8 })
13599
+ shift4({ padding: 8 })
13270
13600
  // Keep within viewport
13271
13601
  ]
13272
13602
  });
13273
- useEffect12(() => {
13603
+ useEffect13(() => {
13274
13604
  const rect = getReferenceRect();
13275
13605
  if (!rect || !refs.floating.current) return;
13276
13606
  refs.setPositionReference(virtualReference);
@@ -13285,18 +13615,18 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
13285
13615
  );
13286
13616
  return cleanup;
13287
13617
  }, [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, {}) });
13618
+ 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
13619
  };
13290
13620
 
13291
13621
  // 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";
13622
+ import { useMemo as useMemo13, useEffect as useEffect14, useState as useState10, useRef as useRef6, useCallback as useCallback12 } from "react";
13623
+ import { useFloating as useFloating6, offset as offset6, autoUpdate as autoUpdate4 } from "@floating-ui/react";
13624
+ import { jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
13295
13625
  var DividerScale = ({ getReferenceRect }) => {
13296
- const [dimensions, setDimensions] = useState9({ width: 0, height: 0 });
13297
- const [activeSide, setActiveSide] = useState9(null);
13626
+ const [dimensions, setDimensions] = useState10({ width: 0, height: 0 });
13627
+ const [activeSide, setActiveSide] = useState10(null);
13298
13628
  const { focusIdx, template, setIsScaling } = useEditorStore();
13299
- const { currentWidth, currentAlign } = useMemo12(() => {
13629
+ const { currentWidth, currentAlign } = useMemo13(() => {
13300
13630
  if (!focusIdx || !template) return { currentWidth: 100, currentAlign: "center" };
13301
13631
  const element = getValueByIdx(template, focusIdx);
13302
13632
  const rawWidth = element?.attributes?.width;
@@ -13305,13 +13635,13 @@ var DividerScale = ({ getReferenceRect }) => {
13305
13635
  const align = element?.attributes?.align || "center";
13306
13636
  return { currentWidth: width, currentAlign: align };
13307
13637
  }, [focusIdx, template]);
13308
- const dragRef = useRef5(null);
13309
- const getContainerWidth = useCallback11(() => {
13638
+ const dragRef = useRef6(null);
13639
+ const getContainerWidth = useCallback12(() => {
13310
13640
  const rect = getReferenceRect();
13311
13641
  if (!rect || currentWidth <= 0) return null;
13312
13642
  return rect.width / (currentWidth / 100);
13313
13643
  }, [getReferenceRect, currentWidth]);
13314
- const handlePointerDown = useCallback11((e, side) => {
13644
+ const handlePointerDown = useCallback12((e, side) => {
13315
13645
  e.preventDefault();
13316
13646
  e.stopPropagation();
13317
13647
  const containerWidth = getContainerWidth();
@@ -13329,7 +13659,7 @@ var DividerScale = ({ getReferenceRect }) => {
13329
13659
  document.addEventListener("pointermove", handlePointerMove);
13330
13660
  document.addEventListener("pointerup", handlePointerUp);
13331
13661
  }, [getContainerWidth, currentWidth, currentAlign, setIsScaling]);
13332
- const handlePointerMove = useCallback11((e) => {
13662
+ const handlePointerMove = useCallback12((e) => {
13333
13663
  if (!dragRef.current) return;
13334
13664
  const { startX, startWidth, containerWidth, side, align } = dragRef.current;
13335
13665
  const deltaX = e.clientX - startX;
@@ -13349,20 +13679,20 @@ var DividerScale = ({ getReferenceRect }) => {
13349
13679
  }
13350
13680
  });
13351
13681
  }, []);
13352
- const handlePointerUp = useCallback11(() => {
13682
+ const handlePointerUp = useCallback12(() => {
13353
13683
  setActiveSide(null);
13354
13684
  setIsScaling(false);
13355
13685
  dragRef.current = null;
13356
13686
  document.removeEventListener("pointermove", handlePointerMove);
13357
13687
  document.removeEventListener("pointerup", handlePointerUp);
13358
13688
  }, [handlePointerMove, setIsScaling]);
13359
- useEffect13(() => {
13689
+ useEffect14(() => {
13360
13690
  return () => {
13361
13691
  document.removeEventListener("pointermove", handlePointerMove);
13362
13692
  document.removeEventListener("pointerup", handlePointerUp);
13363
13693
  };
13364
13694
  }, [handlePointerMove, handlePointerUp]);
13365
- const virtualReference = useMemo12(() => ({
13695
+ const virtualReference = useMemo13(() => ({
13366
13696
  getBoundingClientRect: () => {
13367
13697
  const rect = getReferenceRect();
13368
13698
  if (!rect) {
@@ -13371,13 +13701,13 @@ var DividerScale = ({ getReferenceRect }) => {
13371
13701
  return rect;
13372
13702
  }
13373
13703
  }), [getReferenceRect]);
13374
- const { floatingStyles, refs, update } = useFloating5({
13704
+ const { floatingStyles, refs, update } = useFloating6({
13375
13705
  placement: "bottom-start",
13376
13706
  middleware: [
13377
- offset5(({ rects }) => -rects.reference.height)
13707
+ offset6(({ rects }) => -rects.reference.height)
13378
13708
  ]
13379
13709
  });
13380
- useEffect13(() => {
13710
+ useEffect14(() => {
13381
13711
  const rect = getReferenceRect();
13382
13712
  if (!rect || !refs.floating.current) return;
13383
13713
  refs.setPositionReference(virtualReference);
@@ -13404,7 +13734,7 @@ var DividerScale = ({ getReferenceRect }) => {
13404
13734
  }, [getReferenceRect, refs, update, virtualReference]);
13405
13735
  const showLeftHandle = currentAlign !== "left";
13406
13736
  const showRightHandle = currentAlign !== "right";
13407
- return /* @__PURE__ */ jsxs25(
13737
+ return /* @__PURE__ */ jsxs26(
13408
13738
  "div",
13409
13739
  {
13410
13740
  ref: refs.setFloating,
@@ -13416,14 +13746,14 @@ var DividerScale = ({ getReferenceRect }) => {
13416
13746
  },
13417
13747
  className: "relative flex flex-row items-center justify-between",
13418
13748
  children: [
13419
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx42(
13749
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx43(
13420
13750
  "div",
13421
13751
  {
13422
13752
  onPointerDown: (e) => handlePointerDown(e, "left"),
13423
13753
  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
13754
  }
13425
13755
  ),
13426
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx42(
13756
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx43(
13427
13757
  "div",
13428
13758
  {
13429
13759
  onPointerDown: (e) => handlePointerDown(e, "right"),
@@ -13436,14 +13766,14 @@ var DividerScale = ({ getReferenceRect }) => {
13436
13766
  };
13437
13767
 
13438
13768
  // 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";
13769
+ import { useMemo as useMemo14, useEffect as useEffect15, useState as useState11, useRef as useRef7, useCallback as useCallback13 } from "react";
13770
+ import { useFloating as useFloating7, offset as offset7, autoUpdate as autoUpdate5 } from "@floating-ui/react";
13771
+ import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
13442
13772
  var ButtonScale = ({ getReferenceRect }) => {
13443
- const [dimensions, setDimensions] = useState10({ width: 0, height: 0 });
13444
- const [activeSide, setActiveSide] = useState10(null);
13773
+ const [dimensions, setDimensions] = useState11({ width: 0, height: 0 });
13774
+ const [activeSide, setActiveSide] = useState11(null);
13445
13775
  const { focusIdx, template, setIsScaling } = useEditorStore();
13446
- const { currentWidth, currentHeight, currentAlign } = useMemo13(() => {
13776
+ const { currentWidth, currentHeight, currentAlign } = useMemo14(() => {
13447
13777
  if (!focusIdx || !template) {
13448
13778
  return { currentWidth: 24, currentHeight: 44, currentAlign: "center" };
13449
13779
  }
@@ -13457,13 +13787,13 @@ var ButtonScale = ({ getReferenceRect }) => {
13457
13787
  const align = element?.attributes?.align || "center";
13458
13788
  return { currentWidth: width, currentHeight: height, currentAlign: align };
13459
13789
  }, [focusIdx, template]);
13460
- const dragRef = useRef6(null);
13461
- const getContainerWidth = useCallback12(() => {
13790
+ const dragRef = useRef7(null);
13791
+ const getContainerWidth = useCallback13(() => {
13462
13792
  const rect = getReferenceRect();
13463
13793
  if (!rect || currentWidth <= 0) return null;
13464
13794
  return rect.width / (currentWidth / 100);
13465
13795
  }, [getReferenceRect, currentWidth]);
13466
- const handlePointerDown = useCallback12((e, side) => {
13796
+ const handlePointerDown = useCallback13((e, side) => {
13467
13797
  e.preventDefault();
13468
13798
  e.stopPropagation();
13469
13799
  if (document.activeElement instanceof HTMLElement) {
@@ -13485,7 +13815,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13485
13815
  document.addEventListener("pointermove", handlePointerMove);
13486
13816
  document.addEventListener("pointerup", handlePointerUp);
13487
13817
  }, [getContainerWidth, currentWidth, currentHeight, currentAlign, setIsScaling]);
13488
- const handlePointerMove = useCallback12((e) => {
13818
+ const handlePointerMove = useCallback13((e) => {
13489
13819
  if (!dragRef.current) return;
13490
13820
  const { startX, startY, startWidth, startHeight, containerWidth, side, align } = dragRef.current;
13491
13821
  const state = useEditorStore.getState();
@@ -13517,20 +13847,20 @@ var ButtonScale = ({ getReferenceRect }) => {
13517
13847
  });
13518
13848
  }
13519
13849
  }, []);
13520
- const handlePointerUp = useCallback12(() => {
13850
+ const handlePointerUp = useCallback13(() => {
13521
13851
  setActiveSide(null);
13522
13852
  setIsScaling(false);
13523
13853
  dragRef.current = null;
13524
13854
  document.removeEventListener("pointermove", handlePointerMove);
13525
13855
  document.removeEventListener("pointerup", handlePointerUp);
13526
13856
  }, [handlePointerMove, setIsScaling]);
13527
- useEffect14(() => {
13857
+ useEffect15(() => {
13528
13858
  return () => {
13529
13859
  document.removeEventListener("pointermove", handlePointerMove);
13530
13860
  document.removeEventListener("pointerup", handlePointerUp);
13531
13861
  };
13532
13862
  }, [handlePointerMove, handlePointerUp]);
13533
- const virtualReference = useMemo13(() => ({
13863
+ const virtualReference = useMemo14(() => ({
13534
13864
  getBoundingClientRect: () => {
13535
13865
  const rect = getReferenceRect();
13536
13866
  if (!rect) {
@@ -13539,13 +13869,13 @@ var ButtonScale = ({ getReferenceRect }) => {
13539
13869
  return rect;
13540
13870
  }
13541
13871
  }), [getReferenceRect]);
13542
- const { floatingStyles, refs, update } = useFloating6({
13872
+ const { floatingStyles, refs, update } = useFloating7({
13543
13873
  placement: "bottom-start",
13544
13874
  middleware: [
13545
- offset6(({ rects }) => -rects.reference.height)
13875
+ offset7(({ rects }) => -rects.reference.height)
13546
13876
  ]
13547
13877
  });
13548
- useEffect14(() => {
13878
+ useEffect15(() => {
13549
13879
  const rect = getReferenceRect();
13550
13880
  if (!rect || !refs.floating.current) return;
13551
13881
  refs.setPositionReference(virtualReference);
@@ -13574,7 +13904,7 @@ var ButtonScale = ({ getReferenceRect }) => {
13574
13904
  const showRightHandle = currentAlign !== "right";
13575
13905
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13576
13906
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13577
- return /* @__PURE__ */ jsxs26(
13907
+ return /* @__PURE__ */ jsxs27(
13578
13908
  "div",
13579
13909
  {
13580
13910
  ref: refs.setFloating,
@@ -13586,28 +13916,28 @@ var ButtonScale = ({ getReferenceRect }) => {
13586
13916
  },
13587
13917
  className: "relative pointer-events-none",
13588
13918
  children: [
13589
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx43(
13919
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx44(
13590
13920
  "div",
13591
13921
  {
13592
13922
  onPointerDown: (e) => handlePointerDown(e, "top"),
13593
13923
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13594
13924
  }
13595
13925
  ),
13596
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx43(
13926
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx44(
13597
13927
  "div",
13598
13928
  {
13599
13929
  onPointerDown: (e) => handlePointerDown(e, "right"),
13600
13930
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
13601
13931
  }
13602
13932
  ),
13603
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx43(
13933
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx44(
13604
13934
  "div",
13605
13935
  {
13606
13936
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
13607
13937
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
13608
13938
  }
13609
13939
  ),
13610
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx43(
13940
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx44(
13611
13941
  "div",
13612
13942
  {
13613
13943
  onPointerDown: (e) => handlePointerDown(e, "left"),
@@ -13620,14 +13950,15 @@ var ButtonScale = ({ getReferenceRect }) => {
13620
13950
  };
13621
13951
 
13622
13952
  // 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";
13953
+ import { useMemo as useMemo15, useEffect as useEffect16, useState as useState12, useRef as useRef8, useCallback as useCallback14 } from "react";
13954
+ import { useFloating as useFloating8, offset as offset8, autoUpdate as autoUpdate6 } from "@floating-ui/react";
13955
+ import { jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
13956
+ var isCorner = (side) => side === "top-left" || side === "top-right" || side === "bottom-left" || side === "bottom-right";
13626
13957
  var ImageScale = ({ getReferenceRect }) => {
13627
- const [dimensions, setDimensions] = useState11({ width: 0, height: 0 });
13628
- const [activeSide, setActiveSide] = useState11(null);
13958
+ const [dimensions, setDimensions] = useState12({ width: 0, height: 0 });
13959
+ const [activeSide, setActiveSide] = useState12(null);
13629
13960
  const { focusIdx, template, setIsScaling } = useEditorStore();
13630
- const { currentWidth, currentHeight, currentAlign } = useMemo14(() => {
13961
+ const { currentWidth, currentHeight, currentAlign } = useMemo15(() => {
13631
13962
  if (!focusIdx || !template) {
13632
13963
  return { currentWidth: 0, currentHeight: 0, currentAlign: "center" };
13633
13964
  }
@@ -13641,8 +13972,8 @@ var ImageScale = ({ getReferenceRect }) => {
13641
13972
  const align = element?.attributes?.align || "center";
13642
13973
  return { currentWidth: width, currentHeight: height, currentAlign: align };
13643
13974
  }, [focusIdx, template]);
13644
- const dragRef = useRef7(null);
13645
- const handlePointerDown = useCallback13((e, side) => {
13975
+ const dragRef = useRef8(null);
13976
+ const handlePointerDown = useCallback14((e, side) => {
13646
13977
  e.preventDefault();
13647
13978
  e.stopPropagation();
13648
13979
  if (document.activeElement instanceof HTMLElement) {
@@ -13660,12 +13991,13 @@ var ImageScale = ({ getReferenceRect }) => {
13660
13991
  startWidth: effectiveWidth,
13661
13992
  startHeight: effectiveHeight,
13662
13993
  side,
13663
- align: currentAlign
13994
+ align: currentAlign,
13995
+ aspectRatio: effectiveHeight > 0 ? effectiveWidth / effectiveHeight : 1
13664
13996
  };
13665
13997
  document.addEventListener("pointermove", handlePointerMove);
13666
13998
  document.addEventListener("pointerup", handlePointerUp);
13667
13999
  }, [getReferenceRect, currentWidth, currentHeight, currentAlign, setIsScaling]);
13668
- const handlePointerMove = useCallback13((e) => {
14000
+ const handlePointerMove = useCallback14((e) => {
13669
14001
  if (!dragRef.current) return;
13670
14002
  const { startX, startY, startWidth, startHeight, side, align } = dragRef.current;
13671
14003
  const state = useEditorStore.getState();
@@ -13673,7 +14005,35 @@ var ImageScale = ({ getReferenceRect }) => {
13673
14005
  if (!currentFocusIdx || !currentTemplate) return;
13674
14006
  const element = getValueByIdx(currentTemplate, currentFocusIdx);
13675
14007
  if (!element) return;
13676
- if (side === "left" || side === "right") {
14008
+ if (isCorner(side)) {
14009
+ const { aspectRatio } = dragRef.current;
14010
+ const deltaX = e.clientX - startX;
14011
+ const deltaY = e.clientY - startY;
14012
+ const signX = side.includes("left") ? -1 : 1;
14013
+ const signY = side.includes("top") ? -1 : 1;
14014
+ const alignMultiplier = align === "center" ? 2 : 1;
14015
+ const absDX = Math.abs(deltaX);
14016
+ const absDY = Math.abs(deltaY);
14017
+ let newWidth;
14018
+ let newHeight;
14019
+ if (absDX >= absDY) {
14020
+ newWidth = startWidth + signX * deltaX * alignMultiplier;
14021
+ newHeight = newWidth / aspectRatio;
14022
+ } else {
14023
+ newHeight = startHeight + signY * deltaY;
14024
+ newWidth = newHeight * aspectRatio;
14025
+ }
14026
+ const clampedWidth = Math.max(20, Math.min(600, newWidth));
14027
+ const clampedHeight = Math.max(20, Math.min(600, clampedWidth / aspectRatio));
14028
+ const finalWidth = clampedHeight * aspectRatio;
14029
+ updateElement(currentFocusIdx, {
14030
+ attributes: {
14031
+ ...element.attributes,
14032
+ width: `${Math.round(finalWidth)}px`,
14033
+ height: `${Math.round(clampedHeight)}px`
14034
+ }
14035
+ });
14036
+ } else if (side === "left" || side === "right") {
13677
14037
  const deltaX = e.clientX - startX;
13678
14038
  const alignMultiplier = align === "center" ? 2 : 1;
13679
14039
  const newWidth = side === "left" ? startWidth - deltaX * alignMultiplier : startWidth + deltaX * alignMultiplier;
@@ -13696,20 +14056,20 @@ var ImageScale = ({ getReferenceRect }) => {
13696
14056
  });
13697
14057
  }
13698
14058
  }, []);
13699
- const handlePointerUp = useCallback13(() => {
14059
+ const handlePointerUp = useCallback14(() => {
13700
14060
  setActiveSide(null);
13701
14061
  setIsScaling(false);
13702
14062
  dragRef.current = null;
13703
14063
  document.removeEventListener("pointermove", handlePointerMove);
13704
14064
  document.removeEventListener("pointerup", handlePointerUp);
13705
14065
  }, [handlePointerMove, setIsScaling]);
13706
- useEffect15(() => {
14066
+ useEffect16(() => {
13707
14067
  return () => {
13708
14068
  document.removeEventListener("pointermove", handlePointerMove);
13709
14069
  document.removeEventListener("pointerup", handlePointerUp);
13710
14070
  };
13711
14071
  }, [handlePointerMove, handlePointerUp]);
13712
- const virtualReference = useMemo14(() => ({
14072
+ const virtualReference = useMemo15(() => ({
13713
14073
  getBoundingClientRect: () => {
13714
14074
  const rect = getReferenceRect();
13715
14075
  if (!rect) {
@@ -13718,13 +14078,13 @@ var ImageScale = ({ getReferenceRect }) => {
13718
14078
  return rect;
13719
14079
  }
13720
14080
  }), [getReferenceRect]);
13721
- const { floatingStyles, refs, update } = useFloating7({
14081
+ const { floatingStyles, refs, update } = useFloating8({
13722
14082
  placement: "bottom-start",
13723
14083
  middleware: [
13724
- offset7(({ rects }) => -rects.reference.height)
14084
+ offset8(({ rects }) => -rects.reference.height)
13725
14085
  ]
13726
14086
  });
13727
- useEffect15(() => {
14087
+ useEffect16(() => {
13728
14088
  const rect = getReferenceRect();
13729
14089
  if (!rect || !refs.floating.current) return;
13730
14090
  refs.setPositionReference(virtualReference);
@@ -13751,9 +14111,13 @@ var ImageScale = ({ getReferenceRect }) => {
13751
14111
  }, [getReferenceRect, refs, update, virtualReference]);
13752
14112
  const showLeftHandle = currentAlign !== "left";
13753
14113
  const showRightHandle = currentAlign !== "right";
14114
+ const showTopLeft = currentAlign !== "left";
14115
+ const showTopRight = currentAlign !== "right";
14116
+ const showBottomLeft = currentAlign !== "left";
14117
+ const showBottomRight = currentAlign !== "right";
13754
14118
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13755
14119
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13756
- return /* @__PURE__ */ jsxs27(
14120
+ return /* @__PURE__ */ jsxs28(
13757
14121
  "div",
13758
14122
  {
13759
14123
  ref: refs.setFloating,
@@ -13765,33 +14129,61 @@ var ImageScale = ({ getReferenceRect }) => {
13765
14129
  },
13766
14130
  className: "relative pointer-events-none",
13767
14131
  children: [
13768
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx44(
14132
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx45(
13769
14133
  "div",
13770
14134
  {
13771
14135
  onPointerDown: (e) => handlePointerDown(e, "top"),
13772
14136
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13773
14137
  }
13774
14138
  ),
13775
- showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx44(
14139
+ showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx45(
13776
14140
  "div",
13777
14141
  {
13778
14142
  onPointerDown: (e) => handlePointerDown(e, "right"),
13779
14143
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
13780
14144
  }
13781
14145
  ),
13782
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx44(
14146
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx45(
13783
14147
  "div",
13784
14148
  {
13785
14149
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
13786
14150
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
13787
14151
  }
13788
14152
  ),
13789
- showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx44(
14153
+ showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx45(
13790
14154
  "div",
13791
14155
  {
13792
14156
  onPointerDown: (e) => handlePointerDown(e, "left"),
13793
14157
  className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -left-[4px] ${getHandleActiveClass("left")}`
13794
14158
  }
14159
+ ),
14160
+ showTopLeft && (activeSide === null || activeSide === "top-left") && /* @__PURE__ */ jsx45(
14161
+ "div",
14162
+ {
14163
+ onPointerDown: (e) => handlePointerDown(e, "top-left"),
14164
+ className: `w-[10px] h-[10px] cursor-nwse-resize ${handleBaseClass} -top-[5px] -left-[5px] ${getHandleActiveClass("top-left")}`
14165
+ }
14166
+ ),
14167
+ showTopRight && (activeSide === null || activeSide === "top-right") && /* @__PURE__ */ jsx45(
14168
+ "div",
14169
+ {
14170
+ onPointerDown: (e) => handlePointerDown(e, "top-right"),
14171
+ className: `w-[10px] h-[10px] cursor-nesw-resize ${handleBaseClass} -top-[5px] -right-[5px] ${getHandleActiveClass("top-right")}`
14172
+ }
14173
+ ),
14174
+ showBottomLeft && (activeSide === null || activeSide === "bottom-left") && /* @__PURE__ */ jsx45(
14175
+ "div",
14176
+ {
14177
+ onPointerDown: (e) => handlePointerDown(e, "bottom-left"),
14178
+ className: `w-[10px] h-[10px] cursor-nesw-resize ${handleBaseClass} -bottom-[5px] -left-[5px] ${getHandleActiveClass("bottom-left")}`
14179
+ }
14180
+ ),
14181
+ showBottomRight && (activeSide === null || activeSide === "bottom-right") && /* @__PURE__ */ jsx45(
14182
+ "div",
14183
+ {
14184
+ onPointerDown: (e) => handlePointerDown(e, "bottom-right"),
14185
+ className: `w-[10px] h-[10px] cursor-nwse-resize ${handleBaseClass} -bottom-[5px] -right-[5px] ${getHandleActiveClass("bottom-right")}`
14186
+ }
13795
14187
  )
13796
14188
  ]
13797
14189
  }
@@ -13799,22 +14191,22 @@ var ImageScale = ({ getReferenceRect }) => {
13799
14191
  };
13800
14192
 
13801
14193
  // 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";
14194
+ import { useMemo as useMemo16, useEffect as useEffect17, useState as useState13, useRef as useRef9, useCallback as useCallback15 } from "react";
14195
+ import { useFloating as useFloating9, offset as offset9, autoUpdate as autoUpdate7 } from "@floating-ui/react";
14196
+ import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
13805
14197
  var SpacerScale = ({ getReferenceRect }) => {
13806
- const [dimensions, setDimensions] = useState12({ width: 0, height: 0 });
13807
- const [activeSide, setActiveSide] = useState12(null);
14198
+ const [dimensions, setDimensions] = useState13({ width: 0, height: 0 });
14199
+ const [activeSide, setActiveSide] = useState13(null);
13808
14200
  const { focusIdx, template, setIsScaling } = useEditorStore();
13809
- const currentHeight = useMemo15(() => {
14201
+ const currentHeight = useMemo16(() => {
13810
14202
  if (!focusIdx || !template) return 12;
13811
14203
  const element = getValueByIdx(template, focusIdx);
13812
14204
  const rawHeight = element?.attributes?.height;
13813
14205
  const parsedHeight = rawHeight ? parseFloat(rawHeight.replace("px", "")) : 12;
13814
14206
  return isNaN(parsedHeight) ? 12 : Math.max(12, Math.min(200, parsedHeight));
13815
14207
  }, [focusIdx, template]);
13816
- const dragRef = useRef8(null);
13817
- const handlePointerDown = useCallback14((e, side) => {
14208
+ const dragRef = useRef9(null);
14209
+ const handlePointerDown = useCallback15((e, side) => {
13818
14210
  e.preventDefault();
13819
14211
  e.stopPropagation();
13820
14212
  if (document.activeElement instanceof HTMLElement) {
@@ -13830,7 +14222,7 @@ var SpacerScale = ({ getReferenceRect }) => {
13830
14222
  document.addEventListener("pointermove", handlePointerMove);
13831
14223
  document.addEventListener("pointerup", handlePointerUp);
13832
14224
  }, [currentHeight, setIsScaling]);
13833
- const handlePointerMove = useCallback14((e) => {
14225
+ const handlePointerMove = useCallback15((e) => {
13834
14226
  if (!dragRef.current) return;
13835
14227
  const { startY, startHeight, side } = dragRef.current;
13836
14228
  const state = useEditorStore.getState();
@@ -13848,20 +14240,20 @@ var SpacerScale = ({ getReferenceRect }) => {
13848
14240
  }
13849
14241
  });
13850
14242
  }, []);
13851
- const handlePointerUp = useCallback14(() => {
14243
+ const handlePointerUp = useCallback15(() => {
13852
14244
  setActiveSide(null);
13853
14245
  setIsScaling(false);
13854
14246
  dragRef.current = null;
13855
14247
  document.removeEventListener("pointermove", handlePointerMove);
13856
14248
  document.removeEventListener("pointerup", handlePointerUp);
13857
14249
  }, [handlePointerMove, setIsScaling]);
13858
- useEffect16(() => {
14250
+ useEffect17(() => {
13859
14251
  return () => {
13860
14252
  document.removeEventListener("pointermove", handlePointerMove);
13861
14253
  document.removeEventListener("pointerup", handlePointerUp);
13862
14254
  };
13863
14255
  }, [handlePointerMove, handlePointerUp]);
13864
- const virtualReference = useMemo15(() => ({
14256
+ const virtualReference = useMemo16(() => ({
13865
14257
  getBoundingClientRect: () => {
13866
14258
  const rect = getReferenceRect();
13867
14259
  if (!rect) {
@@ -13870,13 +14262,13 @@ var SpacerScale = ({ getReferenceRect }) => {
13870
14262
  return rect;
13871
14263
  }
13872
14264
  }), [getReferenceRect]);
13873
- const { floatingStyles, refs, update } = useFloating8({
14265
+ const { floatingStyles, refs, update } = useFloating9({
13874
14266
  placement: "bottom-start",
13875
14267
  middleware: [
13876
- offset8(({ rects }) => -rects.reference.height)
14268
+ offset9(({ rects }) => -rects.reference.height)
13877
14269
  ]
13878
14270
  });
13879
- useEffect16(() => {
14271
+ useEffect17(() => {
13880
14272
  const rect = getReferenceRect();
13881
14273
  if (!rect || !refs.floating.current) return;
13882
14274
  refs.setPositionReference(virtualReference);
@@ -13903,7 +14295,7 @@ var SpacerScale = ({ getReferenceRect }) => {
13903
14295
  }, [getReferenceRect, refs, update, virtualReference]);
13904
14296
  const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
13905
14297
  const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
13906
- return /* @__PURE__ */ jsxs28(
14298
+ return /* @__PURE__ */ jsxs29(
13907
14299
  "div",
13908
14300
  {
13909
14301
  ref: refs.setFloating,
@@ -13915,14 +14307,14 @@ var SpacerScale = ({ getReferenceRect }) => {
13915
14307
  },
13916
14308
  className: "relative pointer-events-none",
13917
14309
  children: [
13918
- (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx45(
14310
+ (activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx46(
13919
14311
  "div",
13920
14312
  {
13921
14313
  onPointerDown: (e) => handlePointerDown(e, "top"),
13922
14314
  className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
13923
14315
  }
13924
14316
  ),
13925
- (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx45(
14317
+ (activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx46(
13926
14318
  "div",
13927
14319
  {
13928
14320
  onPointerDown: (e) => handlePointerDown(e, "bottom"),
@@ -13935,19 +14327,19 @@ var SpacerScale = ({ getReferenceRect }) => {
13935
14327
  };
13936
14328
 
13937
14329
  // 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";
14330
+ import { useMemo as useMemo17, useEffect as useEffect18, useState as useState14, useRef as useRef10, useCallback as useCallback16 } from "react";
14331
+ import { Fragment as Fragment17, jsx as jsx47 } from "react/jsx-runtime";
13940
14332
  var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13941
- const [activeDivider, setActiveDivider] = useState13(null);
13942
- const [columnRects, setColumnRects] = useState13([]);
14333
+ const [activeDivider, setActiveDivider] = useState14(null);
14334
+ const [columnRects, setColumnRects] = useState14([]);
13943
14335
  const { template, setIsScaling, setFocusIdx, stopTextEditing } = useEditorStore();
13944
- const columnWidths = useMemo16(() => {
14336
+ const columnWidths = useMemo17(() => {
13945
14337
  if (!template) return [];
13946
14338
  const sectionColumn = getValueByIdx(template, sectionColumnIdx);
13947
14339
  return sectionColumn?.data?.value?.columnWidths || [];
13948
14340
  }, [template, sectionColumnIdx]);
13949
- const dragRef = useRef9(null);
13950
- const updateColumnRects = useCallback15(() => {
14341
+ const dragRef = useRef10(null);
14342
+ const updateColumnRects = useCallback16(() => {
13951
14343
  if (!shadowRoot) return;
13952
14344
  const allColumns = shadowRoot.querySelectorAll(".node-type-column");
13953
14345
  const matchingColumns = [];
@@ -13979,7 +14371,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13979
14371
  });
13980
14372
  setColumnRects(rects);
13981
14373
  }, [shadowRoot, sectionColumnIdx]);
13982
- useEffect17(() => {
14374
+ useEffect18(() => {
13983
14375
  updateColumnRects();
13984
14376
  let animationId;
13985
14377
  const updateLoop = () => {
@@ -13992,7 +14384,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
13992
14384
  const parseWidth = (width) => {
13993
14385
  return parseFloat(width.replace("%", ""));
13994
14386
  };
13995
- const handlePointerDown = useCallback15((e, dividerIndex) => {
14387
+ const handlePointerDown = useCallback16((e, dividerIndex) => {
13996
14388
  e.preventDefault();
13997
14389
  e.stopPropagation();
13998
14390
  stopTextEditing();
@@ -14018,7 +14410,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14018
14410
  document.addEventListener("pointermove", handlePointerMove);
14019
14411
  document.addEventListener("pointerup", handlePointerUp);
14020
14412
  }, [columnRects, columnWidths, setIsScaling]);
14021
- const handlePointerMove = useCallback15((e) => {
14413
+ const handlePointerMove = useCallback16((e) => {
14022
14414
  if (!dragRef.current) return;
14023
14415
  const { startX, leftColIndex, rightColIndex, startLeftWidth, startRightWidth, sectionWidth, allWidths } = dragRef.current;
14024
14416
  const deltaX = e.clientX - startX;
@@ -14052,14 +14444,14 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14052
14444
  }
14053
14445
  });
14054
14446
  }, [sectionColumnIdx]);
14055
- const handlePointerUp = useCallback15(() => {
14447
+ const handlePointerUp = useCallback16(() => {
14056
14448
  setActiveDivider(null);
14057
14449
  setIsScaling(false);
14058
14450
  dragRef.current = null;
14059
14451
  document.removeEventListener("pointermove", handlePointerMove);
14060
14452
  document.removeEventListener("pointerup", handlePointerUp);
14061
14453
  }, [handlePointerMove, setIsScaling]);
14062
- useEffect17(() => {
14454
+ useEffect18(() => {
14063
14455
  return () => {
14064
14456
  document.removeEventListener("pointermove", handlePointerMove);
14065
14457
  document.removeEventListener("pointerup", handlePointerUp);
@@ -14070,7 +14462,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14070
14462
  }
14071
14463
  const handleBaseClass = "bg-background shadow-md border rounded-full touch-none select-none pointer-events-auto";
14072
14464
  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) => {
14465
+ return /* @__PURE__ */ jsx47(Fragment17, { children: columnRects.slice(0, -1).map((rect, index) => {
14074
14466
  const nextRect = columnRects[index + 1];
14075
14467
  const handleLeft = rect.right;
14076
14468
  const handleTop = Math.min(rect.top, nextRect.top);
@@ -14078,7 +14470,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14078
14470
  if (activeDivider !== null && activeDivider !== index) {
14079
14471
  return null;
14080
14472
  }
14081
- return /* @__PURE__ */ jsx46(
14473
+ return /* @__PURE__ */ jsx47(
14082
14474
  "div",
14083
14475
  {
14084
14476
  onPointerDown: (e) => handlePointerDown(e, index),
@@ -14098,9 +14490,9 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
14098
14490
  };
14099
14491
 
14100
14492
  // src/core/editor/hooks/use-undo-redo-keyboard.ts
14101
- import { useEffect as useEffect18 } from "react";
14493
+ import { useEffect as useEffect19 } from "react";
14102
14494
  function useUndoRedoKeyboard() {
14103
- useEffect18(() => {
14495
+ useEffect19(() => {
14104
14496
  const handler = (e) => {
14105
14497
  const isMeta = e.metaKey || e.ctrlKey;
14106
14498
  if (!isMeta || e.key.toLowerCase() !== "z") return;
@@ -14122,9 +14514,9 @@ function useUndoRedoKeyboard() {
14122
14514
 
14123
14515
  // src/components/ui/spinner.tsx
14124
14516
  import { Loader2Icon as Loader2Icon2 } from "lucide-react";
14125
- import { jsx as jsx47 } from "react/jsx-runtime";
14517
+ import { jsx as jsx48 } from "react/jsx-runtime";
14126
14518
  function Spinner({ className, ...props }) {
14127
- return /* @__PURE__ */ jsx47(
14519
+ return /* @__PURE__ */ jsx48(
14128
14520
  Loader2Icon2,
14129
14521
  {
14130
14522
  role: "status",
@@ -14136,10 +14528,10 @@ function Spinner({ className, ...props }) {
14136
14528
  }
14137
14529
 
14138
14530
  // src/core/editor/components/preview.tsx
14139
- import { EyeIcon } from "lucide-react";
14531
+ import { EyeIcon, SendIcon, Monitor, Smartphone } from "lucide-react";
14140
14532
 
14141
14533
  // src/render/useMjmlCompiler.ts
14142
- import { useState as useState14, useCallback as useCallback16 } from "react";
14534
+ import { useState as useState15, useCallback as useCallback17 } from "react";
14143
14535
  async function compileMjml(mjml) {
14144
14536
  console.log("Compiling MJML", mjml);
14145
14537
  const response = await fetch("/api/mrender", {
@@ -14156,14 +14548,101 @@ async function compileMjml(mjml) {
14156
14548
  }
14157
14549
 
14158
14550
  // 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";
14551
+ import { useEffect as useEffect20, useState as useState16, useRef as useRef11 } from "react";
14552
+
14553
+ // src/validate/helpers.ts
14554
+ var MERGE_FIELD_REGEX2 = /\{\{([a-zA-Z_][a-zA-Z0-9_]*)\}\}/g;
14555
+ function extractMergeFields(node) {
14556
+ const fields = [];
14557
+ if (!node || typeof node !== "object") return fields;
14558
+ const content = node?.data?.value?.content;
14559
+ if (typeof content === "string") {
14560
+ let match;
14561
+ MERGE_FIELD_REGEX2.lastIndex = 0;
14562
+ while ((match = MERGE_FIELD_REGEX2.exec(content)) !== null) {
14563
+ fields.push(match[1]);
14564
+ }
14565
+ }
14566
+ if (Array.isArray(node.children)) {
14567
+ for (const child of node.children) {
14568
+ fields.push(...extractMergeFields(child));
14569
+ }
14570
+ }
14571
+ if (Array.isArray(node.content)) {
14572
+ for (const page of node.content) {
14573
+ fields.push(...extractMergeFields(page));
14574
+ }
14575
+ }
14576
+ return fields;
14577
+ }
14578
+ function extractEmptyLinks(node) {
14579
+ const results = [];
14580
+ if (!node || typeof node !== "object") return results;
14581
+ if (node.type === "button" || node.type === "social-item") {
14582
+ const href = node.attributes?.href;
14583
+ if (!href || href.trim() === "") {
14584
+ const label = node.type === "button" ? node.data?.value?.content || "Untitled Button" : node.attributes?.alt || node.data?.value?.socialType || "Social Link";
14585
+ results.push({ type: node.type, label });
14586
+ }
14587
+ }
14588
+ if (Array.isArray(node.children)) {
14589
+ for (const child of node.children) {
14590
+ results.push(...extractEmptyLinks(child));
14591
+ }
14592
+ }
14593
+ if (Array.isArray(node.content)) {
14594
+ for (const page of node.content) {
14595
+ results.push(...extractEmptyLinks(page));
14596
+ }
14597
+ }
14598
+ return results;
14599
+ }
14600
+
14601
+ // src/validate/index.ts
14602
+ var PROPERTY_CARD_TYPES = /* @__PURE__ */ new Set(["property-card", "property-card-single-two", "property-card-triple-item"]);
14603
+ function countPlaceholderPropertyImages(node) {
14604
+ let count = 0;
14605
+ if (!node || typeof node !== "object") return count;
14606
+ if (PROPERTY_CARD_TYPES.has(node.type)) {
14607
+ const imageSrc = node.attributes?.["image-src"];
14608
+ if (!imageSrc || imageSrc === DEFAULT_PROPERTY_PLACEHOLDER_IMAGE) {
14609
+ count++;
14610
+ }
14611
+ }
14612
+ if (Array.isArray(node.children)) {
14613
+ for (const child of node.children) {
14614
+ count += countPlaceholderPropertyImages(child);
14615
+ }
14616
+ }
14617
+ if (Array.isArray(node.content)) {
14618
+ for (const page of node.content) {
14619
+ count += countPlaceholderPropertyImages(page);
14620
+ }
14621
+ }
14622
+ return count;
14623
+ }
14624
+ function validate_editor_onPreview(template, mergeFields) {
14625
+ const usedFields = [...new Set(extractMergeFields(template))];
14626
+ const validValues = new Set(mergeFields.map((f) => f.value));
14627
+ const invalid_merge_fields = usedFields.filter((field) => !validValues.has(field));
14628
+ const missing_links = extractEmptyLinks(template);
14629
+ const placeholder_property_images = countPlaceholderPropertyImages(template);
14630
+ const templateSize = new Blob([JSON.stringify(template)]).size;
14631
+ const is_over_size_limit = templateSize > 50 * 1024;
14632
+ return { invalid_merge_fields, missing_links, is_over_size_limit, placeholder_property_images };
14633
+ }
14634
+
14635
+ // src/core/editor/components/preview.tsx
14636
+ import { jsx as jsx49, jsxs as jsxs30 } from "react/jsx-runtime";
14161
14637
  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(() => {
14638
+ const { template, setPreviewMode, previewMode, isPaidLevel, mergeFields } = useEditorStore();
14639
+ const [html, setHtml] = useState16("");
14640
+ const [isLoading, setIsLoading] = useState16(false);
14641
+ const lastTemplateRef = useRef11("");
14642
+ const [deviceMode, setDeviceMode] = useState16("desktop");
14643
+ const [preview_validations, setPreviewValidations] = useState16({ invalid_merge_fields: [], missing_links: [], is_over_size_limit: false, placeholder_property_images: 0 });
14644
+ const [mjmlErrors, setMjmlErrors] = useState16([]);
14645
+ useEffect20(() => {
14167
14646
  if (typeof window === "undefined" || !previewMode) {
14168
14647
  if (!previewMode) {
14169
14648
  setHtml("");
@@ -14177,56 +14656,165 @@ function Preview() {
14177
14656
  }
14178
14657
  lastTemplateRef.current = templateString;
14179
14658
  setIsLoading(true);
14659
+ const validatePreview = () => {
14660
+ const validations = validate_editor_onPreview(template, mergeFields);
14661
+ setPreviewValidations(validations);
14662
+ };
14180
14663
  const convertMjml = async () => {
14181
14664
  try {
14182
14665
  const mjmlString = json2mjml(template, "production", { isPaidLevel });
14183
14666
  console.log("MJML string:", mjmlString);
14184
14667
  const result = await compileMjml(mjmlString);
14668
+ console.log("MJML errors:", result);
14669
+ setMjmlErrors(result.errors ?? []);
14185
14670
  if (result.errors?.length > 0) {
14186
- console.warn("MJML warnings:", result.errors);
14671
+ console.warn("MJML warnings 1:", result.errors);
14187
14672
  }
14188
14673
  console.log(result.html);
14189
14674
  setHtml(result.html);
14190
14675
  } catch (error) {
14191
14676
  console.error("MJML compilation error:", error);
14677
+ setMjmlErrors([]);
14192
14678
  setHtml('<p style="color: red; padding: 20px;">Error generating preview</p>');
14193
14679
  } finally {
14194
14680
  setIsLoading(false);
14195
14681
  }
14196
14682
  };
14683
+ validatePreview();
14197
14684
  convertMjml();
14198
14685
  }, [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(
14686
+ 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;
14687
+ return /* @__PURE__ */ jsxs30(Dialog, { open: previewMode, onOpenChange: setPreviewMode, children: [
14688
+ /* @__PURE__ */ jsxs30(Tooltip, { children: [
14689
+ /* @__PURE__ */ jsx49(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx49(
14202
14690
  Button,
14203
14691
  {
14204
14692
  variant: "ghost",
14205
14693
  className: "shadow-none transition-none cursor-pointer",
14206
14694
  size: "icon",
14207
14695
  onClick: () => setPreviewMode(true),
14208
- children: /* @__PURE__ */ jsx48(EyeIcon, {})
14696
+ children: /* @__PURE__ */ jsx49(EyeIcon, {})
14209
14697
  }
14210
14698
  ) }),
14211
- /* @__PURE__ */ jsx48(TooltipContent, { side: "bottom", className: "z-51", children: "Preview" })
14699
+ /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", className: "z-51", children: "Preview" })
14212
14700
  ] }),
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
- ] })
14701
+ /* @__PURE__ */ jsxs30(
14702
+ DialogContent,
14703
+ {
14704
+ showCloseButton: true,
14705
+ 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",
14706
+ children: [
14707
+ /* @__PURE__ */ jsx49(DialogHeader, { className: "border-b p-4", children: /* @__PURE__ */ jsx49(DialogTitle, { children: "Preview" }) }),
14708
+ /* @__PURE__ */ jsxs30("div", { className: "flex gap-2 justify-between border-b p-4", children: [
14709
+ /* @__PURE__ */ jsx49("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxs30(Button, { variant: "ghost", onClick: () => {
14710
+ }, children: [
14711
+ /* @__PURE__ */ jsx49(SendIcon, { className: "w-4 h-4" }),
14712
+ "Send a Test Email"
14713
+ ] }) }),
14714
+ /* @__PURE__ */ jsxs30("div", { className: "flex gap-2", children: [
14715
+ /* @__PURE__ */ jsxs30(
14716
+ Button,
14717
+ {
14718
+ variant: deviceMode === "desktop" ? "default" : "ghost",
14719
+ onClick: () => setDeviceMode("desktop"),
14720
+ className: "gap-2 cursor-pointer",
14721
+ children: [
14722
+ /* @__PURE__ */ jsx49(Monitor, { className: "w-4 h-4" }),
14723
+ "Desktop"
14724
+ ]
14725
+ }
14726
+ ),
14727
+ /* @__PURE__ */ jsxs30(
14728
+ Button,
14729
+ {
14730
+ variant: deviceMode === "mobile" ? "default" : "ghost",
14731
+ onClick: () => setDeviceMode("mobile"),
14732
+ className: "gap-2 cursor-pointer",
14733
+ children: [
14734
+ /* @__PURE__ */ jsx49(Smartphone, { className: "w-4 h-4" }),
14735
+ "Mobile"
14736
+ ]
14737
+ }
14738
+ )
14739
+ ] })
14740
+ ] }),
14741
+ /* @__PURE__ */ jsxs30("div", { className: "flex flex-1 overflow-hidden", children: [
14742
+ /* @__PURE__ */ jsx49(
14743
+ "div",
14744
+ {
14745
+ className: "flex-1 flex items-start justify-center overflow-auto w-full",
14746
+ style: { backgroundColor: template?.content?.[0]?.attributes?.["background-color"] || "#965D5D" },
14747
+ children: isLoading ? /* @__PURE__ */ jsx49("div", { className: "flex items-center justify-center h-full w-full", children: /* @__PURE__ */ jsx49("p", { children: "Generating preview..." }) }) : /* @__PURE__ */ jsx49(
14748
+ "div",
14749
+ {
14750
+ className: "flex items-center justify-center bg-white transition-all duration-300 h-full w-full",
14751
+ children: /* @__PURE__ */ jsx49(
14752
+ "iframe",
14753
+ {
14754
+ srcDoc: html,
14755
+ className: "w-full border-0 transition-all duration-200",
14756
+ style: { height: "100%", minHeight: "600px", width: deviceMode === "desktop" ? "100%" : "360px", maxWidth: deviceMode === "desktop" ? "100%" : "360px" },
14757
+ title: "Email Preview",
14758
+ sandbox: "allow-same-origin"
14759
+ }
14760
+ )
14761
+ }
14762
+ )
14763
+ }
14764
+ ),
14765
+ hasValidations && /* @__PURE__ */ jsxs30("div", { className: "w-[300px] border-l p-4 overflow-y-auto flex flex-col gap-4", children: [
14766
+ mjmlErrors.length > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border border-red-600 p-2", children: [
14767
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold text-red-600", children: "MJML Errors" }),
14768
+ /* @__PURE__ */ jsx49("p", { className: "text-sm mt-1 text-red-600", children: "The following errors occurred during email compilation:" }),
14769
+ /* @__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: [
14770
+ /* @__PURE__ */ jsx49("span", { className: "font-semibold", children: err.tagName }),
14771
+ " (line ",
14772
+ err.line,
14773
+ "): ",
14774
+ err.message
14775
+ ] }, i)) }),
14776
+ /* @__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." })
14777
+ ] }),
14778
+ preview_validations.is_over_size_limit && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border border-red-300 p-2", children: [
14779
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold text-red-600", children: "Template Too Large" }),
14780
+ /* @__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." })
14781
+ ] }),
14782
+ preview_validations.placeholder_property_images > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border p-2", children: [
14783
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold", children: "Placeholder Property Image" }),
14784
+ /* @__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.` })
14785
+ ] }),
14786
+ preview_validations.invalid_merge_fields.length > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border p-2", children: [
14787
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold", children: "Invalid Merge Fields" }),
14788
+ /* @__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:" }),
14789
+ /* @__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)) })
14790
+ ] }),
14791
+ preview_validations.missing_links.length > 0 && /* @__PURE__ */ jsxs30("div", { className: "w-full rounded-md border p-2", children: [
14792
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-semibold", children: "Missing Links" }),
14793
+ /* @__PURE__ */ jsx49("p", { className: "text-sm mt-1", children: "The following elements have no link set:" }),
14794
+ /* @__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: [
14795
+ item.type === "button" ? "Button" : "Social",
14796
+ ": ",
14797
+ item.label
14798
+ ] }, i)) })
14799
+ ] })
14800
+ ] })
14801
+ ] })
14802
+ ]
14803
+ }
14804
+ )
14217
14805
  ] });
14218
14806
  }
14219
14807
 
14220
14808
  // src/core/editor/components/history.tsx
14221
14809
  import { Redo2Icon, Undo2Icon } from "lucide-react";
14222
- import { Fragment as Fragment18, jsx as jsx49, jsxs as jsxs30 } from "react/jsx-runtime";
14810
+ import { Fragment as Fragment18, jsx as jsx50, jsxs as jsxs31 } from "react/jsx-runtime";
14223
14811
  var History = () => {
14224
14812
  const { undo, redo } = useEditorStore();
14225
14813
  const canUndo = useEditorStore((s) => s.historyIndex > 0);
14226
14814
  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(
14815
+ return /* @__PURE__ */ jsxs31(Fragment18, { children: [
14816
+ /* @__PURE__ */ jsxs31(Tooltip, { children: [
14817
+ /* @__PURE__ */ jsx50(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(
14230
14818
  Button,
14231
14819
  {
14232
14820
  variant: "ghost",
@@ -14234,13 +14822,13 @@ var History = () => {
14234
14822
  size: "icon",
14235
14823
  disabled: !canUndo,
14236
14824
  onClick: undo,
14237
- children: /* @__PURE__ */ jsx49(Undo2Icon, {})
14825
+ children: /* @__PURE__ */ jsx50(Undo2Icon, {})
14238
14826
  }
14239
14827
  ) }),
14240
- /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", children: "Undo (Ctrl+Z)" })
14828
+ /* @__PURE__ */ jsx50(TooltipContent, { side: "bottom", children: "Undo (Ctrl+Z)" })
14241
14829
  ] }),
14242
- /* @__PURE__ */ jsxs30(Tooltip, { children: [
14243
- /* @__PURE__ */ jsx49(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx49(
14830
+ /* @__PURE__ */ jsxs31(Tooltip, { children: [
14831
+ /* @__PURE__ */ jsx50(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(
14244
14832
  Button,
14245
14833
  {
14246
14834
  variant: "ghost",
@@ -14248,16 +14836,16 @@ var History = () => {
14248
14836
  size: "icon",
14249
14837
  disabled: !canRedo,
14250
14838
  onClick: redo,
14251
- children: /* @__PURE__ */ jsx49(Redo2Icon, {})
14839
+ children: /* @__PURE__ */ jsx50(Redo2Icon, {})
14252
14840
  }
14253
14841
  ) }),
14254
- /* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", children: "Redo (Ctrl+Shift+Z)" })
14842
+ /* @__PURE__ */ jsx50(TooltipContent, { side: "bottom", children: "Redo (Ctrl+Shift+Z)" })
14255
14843
  ] })
14256
14844
  ] });
14257
14845
  };
14258
14846
 
14259
14847
  // src/core/index.tsx
14260
- import { jsx as jsx50, jsxs as jsxs31 } from "react/jsx-runtime";
14848
+ import { jsx as jsx51, jsxs as jsxs32 } from "react/jsx-runtime";
14261
14849
  var MAILLOW_EMAIL_EDITOR_VERSION = "0.0.1";
14262
14850
  function getSectionColumnIdx(idx, template) {
14263
14851
  let current = idx;
@@ -14293,6 +14881,20 @@ function getCompanyFooterSection(template) {
14293
14881
  }
14294
14882
  return null;
14295
14883
  }
14884
+ function restoreImagePreview(shadowRoot, targetIdx, originalSrc) {
14885
+ const targetEl = shadowRoot.querySelector(`.node-idx-${CSS.escape(targetIdx)}`);
14886
+ if (!targetEl) return;
14887
+ const bgEl = targetEl.querySelector("td[background], th[background]");
14888
+ if (bgEl) {
14889
+ bgEl.setAttribute("background", originalSrc);
14890
+ bgEl.style.backgroundImage = `url(${originalSrc})`;
14891
+ return;
14892
+ }
14893
+ const img = targetEl.querySelector("img");
14894
+ if (img) {
14895
+ img.src = originalSrc;
14896
+ }
14897
+ }
14296
14898
  function Editor({ setEditorLoading }) {
14297
14899
  useUndoRedoKeyboard();
14298
14900
  const template = useEditorStore((state) => state.template);
@@ -14323,29 +14925,31 @@ function Editor({ setEditorLoading }) {
14323
14925
  const startTextEditing = useEditorStore((state) => state.startTextEditing);
14324
14926
  const pendingTextEditRequest = useEditorStore((state) => state.pendingTextEditRequest);
14325
14927
  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(() => {
14928
+ const [renderData, setRenderData] = useState17(null);
14929
+ const [isEditing, setIsEditing] = useState17(false);
14930
+ const [dropIndicator, setDropIndicator] = useState17(null);
14931
+ const [dropTargetIdx, setDropTargetIdx] = useState17(null);
14932
+ const shadowRootRef = useRef12(null);
14933
+ const [hasSelectedElement, setHasSelectedElement] = useState17(false);
14934
+ const dragParentIdxRef = useRef12(null);
14935
+ const dragPositionIndexRef = useRef12(0);
14936
+ const createNewSectionRef = useRef12(false);
14937
+ const splitAtParagraphRef = useRef12(null);
14938
+ const isHorizontalDropRef = useRef12(false);
14939
+ const horizontalDropPositionRef = useRef12(null);
14940
+ const isSplitSectionDropRef = useRef12(false);
14941
+ const splitSectionAtElementRef = useRef12(null);
14942
+ const templateCacheRef = useRef12(null);
14943
+ const parentSectionCacheRef = useRef12(/* @__PURE__ */ new Map());
14944
+ const sectionElementCacheRef = useRef12(/* @__PURE__ */ new Map());
14945
+ const sectionRectCacheRef = useRef12(/* @__PURE__ */ new Map());
14946
+ const companyFooterCacheRef = useRef12(void 0);
14947
+ const lastSyncedTemplateRef = useRef12(null);
14948
+ const prevTextEditingIdxRef = useRef12(null);
14949
+ const lastRenderSyncNeededRef = useRef12(0);
14950
+ const imageReplaceTargetRef = useRef12(null);
14951
+ const imagePreviewOriginalSrcRef = useRef12(null);
14952
+ useEffect21(() => {
14349
14953
  const currentIdx = textEditing?.idx ?? null;
14350
14954
  const prevIdx = prevTextEditingIdxRef.current;
14351
14955
  const switchedTarget = currentIdx !== null && prevIdx !== null && currentIdx !== prevIdx;
@@ -14364,12 +14968,12 @@ function Editor({ setEditorLoading }) {
14364
14968
  lastSyncedTemplateRef.current = template;
14365
14969
  }
14366
14970
  }, [template, renderData, isEditing, textEditing, renderSyncNeeded]);
14367
- useEffect20(() => {
14971
+ useEffect21(() => {
14368
14972
  if (renderData && setEditorLoading) {
14369
14973
  setEditorLoading(false);
14370
14974
  }
14371
14975
  }, [renderData, setEditorLoading]);
14372
- useEffect20(() => {
14976
+ useEffect21(() => {
14373
14977
  if (!pendingTextEditRequest || !shadowRootRef.current) return;
14374
14978
  const { idx, cursorPosition } = pendingTextEditRequest;
14375
14979
  const blockNode = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
@@ -14418,7 +15022,7 @@ function Editor({ setEditorLoading }) {
14418
15022
  startTextEditing({ idx, getReferenceRect: getReferenceRect2, getShadowElement, initialWidth: blockRect.width, initialHeight: blockRect.height, clickX, clickY, content, styles, cursorPosition });
14419
15023
  clearPendingTextEditRequest();
14420
15024
  }, [pendingTextEditRequest, clearPendingTextEditRequest, startTextEditing]);
14421
- useEffect20(() => {
15025
+ useEffect21(() => {
14422
15026
  if (isDragging && dataTransfer) {
14423
15027
  const currentTemplate = useEditorStore.getState().template;
14424
15028
  templateCacheRef.current = currentTemplate;
@@ -14434,9 +15038,9 @@ function Editor({ setEditorLoading }) {
14434
15038
  sectionRectCacheRef.current.clear();
14435
15039
  }
14436
15040
  }, [isDragging, dataTransfer]);
14437
- const [html, setHtml] = useState16("");
14438
- const lastRenderDataRef = useRef11("");
14439
- useEffect20(() => {
15041
+ const [html, setHtml] = useState17("");
15042
+ const lastRenderDataRef = useRef12("");
15043
+ useEffect21(() => {
14440
15044
  if (typeof window === "undefined" || !renderData) {
14441
15045
  setHtml("");
14442
15046
  lastRenderDataRef.current = "";
@@ -14463,13 +15067,13 @@ function Editor({ setEditorLoading }) {
14463
15067
  };
14464
15068
  convertMjml();
14465
15069
  }, [renderData]);
14466
- const debouncedUpdateContent = useMemo17(
15070
+ const debouncedUpdateContent = useMemo18(
14467
15071
  () => debounce((contentIdx, content) => {
14468
15072
  updateElementContent(contentIdx, content);
14469
15073
  }, 200),
14470
15074
  [updateElementContent]
14471
15075
  );
14472
- const handleElementClick = useCallback17(
15076
+ const handleElementClick = useCallback18(
14473
15077
  (idx) => {
14474
15078
  if (isInsideCompanyFooter(idx, template)) {
14475
15079
  return;
@@ -14482,7 +15086,7 @@ function Editor({ setEditorLoading }) {
14482
15086
  },
14483
15087
  [setFocusIdx, template]
14484
15088
  );
14485
- const handleElementHover = useCallback17(
15089
+ const handleElementHover = useCallback18(
14486
15090
  (idx) => {
14487
15091
  if (!isDragging) {
14488
15092
  if (idx) {
@@ -14496,19 +15100,19 @@ function Editor({ setEditorLoading }) {
14496
15100
  },
14497
15101
  [isDragging, setHoverIdx, template]
14498
15102
  );
14499
- const handleContentInput = useCallback17(
15103
+ const handleContentInput = useCallback18(
14500
15104
  (contentIdx, content) => {
14501
15105
  debouncedUpdateContent(contentIdx, content);
14502
15106
  },
14503
15107
  [debouncedUpdateContent]
14504
15108
  );
14505
- const handleEditingStart = useCallback17(() => {
15109
+ const handleEditingStart = useCallback18(() => {
14506
15110
  setIsEditing(true);
14507
15111
  }, []);
14508
- const handleEditingEnd = useCallback17(() => {
15112
+ const handleEditingEnd = useCallback18(() => {
14509
15113
  setIsEditing(false);
14510
15114
  }, []);
14511
- const handleSlashCommand = useCallback17(
15115
+ const handleSlashCommand = useCallback18(
14512
15116
  (cursorRect) => {
14513
15117
  setSlashCommand({
14514
15118
  isActive: true,
@@ -14523,10 +15127,10 @@ function Editor({ setEditorLoading }) {
14523
15127
  },
14524
15128
  [setSlashCommand]
14525
15129
  );
14526
- const handleSlashCommandClose = useCallback17(() => {
15130
+ const handleSlashCommandClose = useCallback18(() => {
14527
15131
  clearSlashCommand();
14528
15132
  }, [clearSlashCommand]);
14529
- const handleTextEditStart = useCallback17(
15133
+ const handleTextEditStart = useCallback18(
14530
15134
  (idx, initialWidth, initialHeight, clickX, clickY, content, styles) => {
14531
15135
  const getReferenceRect2 = () => {
14532
15136
  if (!shadowRootRef.current) return null;
@@ -14541,11 +15145,11 @@ function Editor({ setEditorLoading }) {
14541
15145
  },
14542
15146
  [startTextEditing]
14543
15147
  );
14544
- const findParentSectionIdx = useCallback17((idx) => {
15148
+ const findParentSectionIdx = useCallback18((idx) => {
14545
15149
  const match = /^(content\.children\.\[\d+\])/.exec(idx);
14546
15150
  return match ? match[1] : null;
14547
15151
  }, []);
14548
- const handleDragOver = useCallback17(
15152
+ const handleDragOver = useCallback18(
14549
15153
  (_e, dragInfo) => {
14550
15154
  const currentDataTransfer = useEditorStore.getState().dataTransfer;
14551
15155
  if (!currentDataTransfer) return;
@@ -14554,6 +15158,11 @@ function Editor({ setEditorLoading }) {
14554
15158
  setDropIndicator(null);
14555
15159
  setDropTargetIdx(null);
14556
15160
  splitAtParagraphRef.current = null;
15161
+ if (imageReplaceTargetRef.current && shadowRootRef.current && imagePreviewOriginalSrcRef.current !== null) {
15162
+ restoreImagePreview(shadowRootRef.current, imageReplaceTargetRef.current, imagePreviewOriginalSrcRef.current);
15163
+ }
15164
+ imageReplaceTargetRef.current = null;
15165
+ imagePreviewOriginalSrcRef.current = null;
14557
15166
  return;
14558
15167
  }
14559
15168
  const template2 = templateCacheRef.current || useEditorStore.getState().template;
@@ -14585,21 +15194,64 @@ function Editor({ setEditorLoading }) {
14585
15194
  }
14586
15195
  }
14587
15196
  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;
15197
+ const isImageReplaceDrop = currentDataTransfer.type === "image" && currentDataTransfer.payload?.attributes?.src && (hoveredType === "property-card" || hoveredType === "property-card-single-two");
15198
+ if (!isImageReplaceDrop) {
15199
+ const columnIdx = hoveredType === "column" ? idx : getParentIdx(idx);
15200
+ if (columnIdx) {
15201
+ const columnParentIdx = getParentIdx(columnIdx);
15202
+ if (columnParentIdx) {
15203
+ const columnParent = getValueByIdx(template2, columnParentIdx);
15204
+ if (columnParent?.type === "section-property-km" || columnParent?.type === "section-property-single-two" || columnParent?.type === "section-property-triple") {
15205
+ setDropIndicator(null);
15206
+ setDropTargetIdx(null);
15207
+ splitAtParagraphRef.current = null;
15208
+ return;
15209
+ }
14598
15210
  }
14599
15211
  }
14600
15212
  }
14601
15213
  }
14602
15214
  const dragType = currentDataTransfer.type;
15215
+ const hasImagePayload = currentDataTransfer.payload?.attributes?.src;
15216
+ const PROPERTY_CARD_IMAGE_TYPES = ["property-card", "property-card-single-two", "property-card-triple-item"];
15217
+ const isImageReplaceTarget = hoveredType === "image" || PROPERTY_CARD_IMAGE_TYPES.includes(hoveredType);
15218
+ if (dragType === "image" && hasImagePayload && isImageReplaceTarget) {
15219
+ const newSrc = currentDataTransfer.payload.attributes.src;
15220
+ const prevTarget = imageReplaceTargetRef.current;
15221
+ if (prevTarget !== idx) {
15222
+ if (prevTarget && imagePreviewOriginalSrcRef.current !== null && shadowRootRef.current) {
15223
+ restoreImagePreview(shadowRootRef.current, prevTarget, imagePreviewOriginalSrcRef.current);
15224
+ }
15225
+ if (shadowRootRef.current) {
15226
+ const targetEl = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
15227
+ if (targetEl) {
15228
+ const img = targetEl.querySelector("img");
15229
+ if (img && hoveredType === "image") {
15230
+ imagePreviewOriginalSrcRef.current = img.src;
15231
+ img.src = newSrc;
15232
+ } else {
15233
+ const bgEl = targetEl.querySelector("td[background], th[background]");
15234
+ if (bgEl) {
15235
+ imagePreviewOriginalSrcRef.current = bgEl.getAttribute("background") || "";
15236
+ bgEl.setAttribute("background", newSrc);
15237
+ bgEl.style.backgroundImage = `url(${newSrc})`;
15238
+ }
15239
+ }
15240
+ }
15241
+ }
15242
+ imageReplaceTargetRef.current = idx;
15243
+ }
15244
+ setDropIndicator(null);
15245
+ setDropTargetIdx(idx);
15246
+ return;
15247
+ }
15248
+ if (imageReplaceTargetRef.current) {
15249
+ if (shadowRootRef.current && imagePreviewOriginalSrcRef.current !== null) {
15250
+ restoreImagePreview(shadowRootRef.current, imageReplaceTargetRef.current, imagePreviewOriginalSrcRef.current);
15251
+ }
15252
+ imageReplaceTargetRef.current = null;
15253
+ imagePreviewOriginalSrcRef.current = null;
15254
+ }
14603
15255
  const validParents = VALID_PARENT_TYPES[dragType] || [];
14604
15256
  let parentIdx;
14605
15257
  let positionIndex;
@@ -14956,10 +15608,51 @@ function Editor({ setEditorLoading }) {
14956
15608
  [findParentSectionIdx]
14957
15609
  // Only dependency is the helper function
14958
15610
  );
14959
- const handleDrop = useCallback17(
15611
+ const handleDrop = useCallback18(
14960
15612
  (_e, _dragInfo) => {
14961
15613
  const currentDataTransfer = useEditorStore.getState().dataTransfer;
14962
15614
  if (!currentDataTransfer) return;
15615
+ if (imageReplaceTargetRef.current && currentDataTransfer.payload?.attributes?.src) {
15616
+ const targetIdx = imageReplaceTargetRef.current;
15617
+ const newSrc = currentDataTransfer.payload.attributes.src;
15618
+ const template2 = useEditorStore.getState().template;
15619
+ const PROPERTY_CARD_IMAGE_TYPES = ["property-card", "property-card-single-two", "property-card-triple-item"];
15620
+ if (template2) {
15621
+ const targetElement = getValueByIdx(template2, targetIdx);
15622
+ if (targetElement?.type === "image") {
15623
+ useEditorStore.getState().updateElement(targetIdx, {
15624
+ attributes: { ...targetElement.attributes, src: newSrc }
15625
+ });
15626
+ useEditorStore.getState().setFocusIdx(targetIdx);
15627
+ } else if (targetElement && PROPERTY_CARD_IMAGE_TYPES.includes(targetElement.type)) {
15628
+ useEditorStore.getState().updateElement(targetIdx, {
15629
+ attributes: { ...targetElement.attributes, "image-src": newSrc }
15630
+ });
15631
+ useEditorStore.getState().setFocusIdx(targetIdx);
15632
+ }
15633
+ }
15634
+ setDropIndicator(null);
15635
+ setDropTargetIdx(null);
15636
+ setIsDragging(false);
15637
+ setIsDragButtonHovered(false);
15638
+ setDataTransfer(null);
15639
+ setHoverIdx(null);
15640
+ dragParentIdxRef.current = null;
15641
+ dragPositionIndexRef.current = 0;
15642
+ createNewSectionRef.current = false;
15643
+ splitAtParagraphRef.current = null;
15644
+ isHorizontalDropRef.current = false;
15645
+ horizontalDropPositionRef.current = null;
15646
+ isSplitSectionDropRef.current = false;
15647
+ splitSectionAtElementRef.current = null;
15648
+ imageReplaceTargetRef.current = null;
15649
+ imagePreviewOriginalSrcRef.current = null;
15650
+ templateCacheRef.current = null;
15651
+ parentSectionCacheRef.current.clear();
15652
+ sectionElementCacheRef.current.clear();
15653
+ sectionRectCacheRef.current.clear();
15654
+ return;
15655
+ }
14963
15656
  if (isHorizontalDropRef.current && horizontalDropPositionRef.current) {
14964
15657
  const parentIdx2 = dragParentIdxRef.current;
14965
15658
  const dropPosition = horizontalDropPositionRef.current;
@@ -14980,6 +15673,8 @@ function Editor({ setEditorLoading }) {
14980
15673
  horizontalDropPositionRef.current = null;
14981
15674
  isSplitSectionDropRef.current = false;
14982
15675
  splitSectionAtElementRef.current = null;
15676
+ imageReplaceTargetRef.current = null;
15677
+ imagePreviewOriginalSrcRef.current = null;
14983
15678
  templateCacheRef.current = null;
14984
15679
  parentSectionCacheRef.current.clear();
14985
15680
  sectionElementCacheRef.current.clear();
@@ -15040,6 +15735,8 @@ function Editor({ setEditorLoading }) {
15040
15735
  splitAtParagraphRef.current = null;
15041
15736
  isSplitSectionDropRef.current = false;
15042
15737
  splitSectionAtElementRef.current = null;
15738
+ imageReplaceTargetRef.current = null;
15739
+ imagePreviewOriginalSrcRef.current = null;
15043
15740
  templateCacheRef.current = null;
15044
15741
  parentSectionCacheRef.current.clear();
15045
15742
  sectionElementCacheRef.current.clear();
@@ -15095,7 +15792,7 @@ function Editor({ setEditorLoading }) {
15095
15792
  },
15096
15793
  [addElement, addElementInNewSection, moveElement, moveElementToNewSection, splitTextAndInsertElement, splitSectionAndInsertElement, setIsDragging, setIsDragButtonHovered, setDataTransfer, setHoverIdx]
15097
15794
  );
15098
- const handleDragLeave = useCallback17(() => {
15795
+ const handleDragLeave = useCallback18(() => {
15099
15796
  setDropIndicator(null);
15100
15797
  setDropTargetIdx(null);
15101
15798
  dragParentIdxRef.current = null;
@@ -15106,18 +15803,23 @@ function Editor({ setEditorLoading }) {
15106
15803
  horizontalDropPositionRef.current = null;
15107
15804
  isSplitSectionDropRef.current = false;
15108
15805
  splitSectionAtElementRef.current = null;
15806
+ if (imageReplaceTargetRef.current && shadowRootRef.current && imagePreviewOriginalSrcRef.current !== null) {
15807
+ restoreImagePreview(shadowRootRef.current, imageReplaceTargetRef.current, imagePreviewOriginalSrcRef.current);
15808
+ }
15809
+ imageReplaceTargetRef.current = null;
15810
+ imagePreviewOriginalSrcRef.current = null;
15109
15811
  templateCacheRef.current = null;
15110
15812
  parentSectionCacheRef.current.clear();
15111
15813
  sectionElementCacheRef.current.clear();
15112
15814
  sectionRectCacheRef.current.clear();
15113
15815
  }, []);
15114
- const handleShadowRootRef = useCallback17((shadowRoot) => {
15816
+ const handleShadowRootRef = useCallback18((shadowRoot) => {
15115
15817
  shadowRootRef.current = shadowRoot;
15116
15818
  }, []);
15117
- const handleSelectionRectChange = useCallback17((rect) => {
15819
+ const handleSelectionRectChange = useCallback18((rect) => {
15118
15820
  setHasSelectedElement(rect !== null);
15119
15821
  }, []);
15120
- const getReferenceRect = useCallback17(() => {
15822
+ const getReferenceRect = useCallback18(() => {
15121
15823
  if (!shadowRootRef.current || !focusIdx) return null;
15122
15824
  const selectedEl = shadowRootRef.current.querySelector(
15123
15825
  `.node-idx-${CSS.escape(focusIdx)}`
@@ -15145,14 +15847,14 @@ function Editor({ setEditorLoading }) {
15145
15847
  }, [focusIdx]);
15146
15848
  const selectedElement = focusIdx && renderData ? getValueByIdx(renderData, focusIdx) : null;
15147
15849
  const canDragSelectedElement = selectedElement && selectedElement.type !== "column" && !(focusIdx && renderData && isInsideCompanyFooter(focusIdx, renderData));
15148
- const showCompanyFooter = useMemo17(
15850
+ const showCompanyFooter = useMemo18(
15149
15851
  () => template.content[0]?.data?.value?.showCompanyFooter ?? true,
15150
15852
  [template.content[0]?.data?.value?.showCompanyFooter]
15151
15853
  );
15152
15854
  if (!html) {
15153
- return /* @__PURE__ */ jsx50("div", { className: "maillow-editor flex items-center justify-center h-[500px]", children: /* @__PURE__ */ jsx50(Spinner, {}) });
15855
+ return /* @__PURE__ */ jsx51("div", { className: "maillow-editor flex items-center justify-center h-[500px]", children: /* @__PURE__ */ jsx51(Spinner, {}) });
15154
15856
  }
15155
- return /* @__PURE__ */ jsxs31(
15857
+ return /* @__PURE__ */ jsxs32(
15156
15858
  "div",
15157
15859
  {
15158
15860
  className: "maillow-editor relative ",
@@ -15163,7 +15865,7 @@ function Editor({ setEditorLoading }) {
15163
15865
  justifyContent: "center"
15164
15866
  },
15165
15867
  children: [
15166
- /* @__PURE__ */ jsxs31(
15868
+ /* @__PURE__ */ jsxs32(
15167
15869
  "div",
15168
15870
  {
15169
15871
  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 +15875,8 @@ function Editor({ setEditorLoading }) {
15173
15875
  overflow: "auto"
15174
15876
  },
15175
15877
  children: [
15176
- /* @__PURE__ */ jsx50("div", { className: "w-full h-[4px] bg-black opacity-10" }),
15177
- /* @__PURE__ */ jsx50(
15878
+ /* @__PURE__ */ jsx51("div", { className: "w-full h-[2px] bg-black opacity-10" }),
15879
+ /* @__PURE__ */ jsx51(
15178
15880
  ShadowDomRenderer,
15179
15881
  {
15180
15882
  html,
@@ -15204,9 +15906,10 @@ function Editor({ setEditorLoading }) {
15204
15906
  ]
15205
15907
  }
15206
15908
  ),
15207
- /* @__PURE__ */ jsx50(ElementsSuggestions, {}),
15208
- /* @__PURE__ */ jsx50(TiptapOverlay, {}),
15209
- !isDragging && !isScaling && hasSelectedElement && focusIdx && selectedElement?.type && /* @__PURE__ */ jsx50(
15909
+ /* @__PURE__ */ jsx51(ElementsSuggestions, {}),
15910
+ /* @__PURE__ */ jsx51(MergeFieldSuggestions, {}),
15911
+ /* @__PURE__ */ jsx51(TiptapOverlay, {}),
15912
+ !isDragging && !isScaling && hasSelectedElement && focusIdx && selectedElement?.type && /* @__PURE__ */ jsx51(
15210
15913
  ElementFloat,
15211
15914
  {
15212
15915
  getReferenceRect,
@@ -15214,7 +15917,7 @@ function Editor({ setEditorLoading }) {
15214
15917
  elementType: selectedElement.type
15215
15918
  }
15216
15919
  ),
15217
- !isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */ jsx50(
15920
+ !isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */ jsx51(
15218
15921
  DragButton,
15219
15922
  {
15220
15923
  getReferenceRect,
@@ -15223,17 +15926,17 @@ function Editor({ setEditorLoading }) {
15223
15926
  isDragging
15224
15927
  }
15225
15928
  ),
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 }),
15929
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "divider" && /* @__PURE__ */ jsx51(DividerScale, { getReferenceRect }),
15930
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "button" && /* @__PURE__ */ jsx51(ButtonScale, { getReferenceRect }),
15931
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "image" && /* @__PURE__ */ jsx51(ImageScale, { getReferenceRect }),
15932
+ !isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "space" && /* @__PURE__ */ jsx51(SpacerScale, { getReferenceRect }),
15230
15933
  !isDragging && hasSelectedElement && focusIdx && renderData && (() => {
15231
15934
  const sectionColumnIdx = getSectionColumnIdx(focusIdx, renderData);
15232
15935
  if (!sectionColumnIdx) return null;
15233
15936
  const sectionColumn = getValueByIdx(renderData, sectionColumnIdx);
15234
15937
  if (!sectionColumn || sectionColumn.type !== "section-column") return null;
15235
15938
  if (!sectionColumn.children || sectionColumn.children.length < 2) return null;
15236
- return /* @__PURE__ */ jsx50(
15939
+ return /* @__PURE__ */ jsx51(
15237
15940
  ColumnScale,
15238
15941
  {
15239
15942
  sectionColumnIdx,
@@ -15255,9 +15958,7 @@ export {
15255
15958
  parseBorder,
15256
15959
  formatBorder,
15257
15960
  parsePrice,
15258
- json2mjml,
15259
15961
  MAX_TEMPLATE_SIZE,
15260
- useEditorStore,
15261
15962
  BUTTON_ALIGNMENTS,
15262
15963
  ALIGNMENT_ICONS,
15263
15964
  FONTS,
@@ -15275,6 +15976,9 @@ export {
15275
15976
  MIN_LINE_HEIGHT,
15276
15977
  MAX_LINE_HEIGHT,
15277
15978
  LINE_HEIGHT_STEP,
15979
+ DEFAULT_PROPERTY_PLACEHOLDER_IMAGE,
15980
+ json2mjml,
15981
+ useEditorStore,
15278
15982
  setupDragImage,
15279
15983
  getElementDisplayName,
15280
15984
  cn,