@kgalexander/mcreate 0.0.14 → 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.
- package/dist/{chunk-QGWWLZOW.mjs → chunk-L3OWFBEU.mjs} +1516 -973
- package/dist/{core-WHUOFMYJ.mjs → core-AMEHYBIM.mjs} +1 -1
- package/dist/index.d.mts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +6074 -3274
- package/dist/index.mjs +4361 -2174
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/core/index.tsx
|
|
2
|
-
import { useMemo as
|
|
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"] ||
|
|
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"] ||
|
|
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"] ||
|
|
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://
|
|
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":
|
|
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":
|
|
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"] ||
|
|
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"] || "--",
|
|
@@ -1587,8 +1698,8 @@ function createSectionPropertyTripleElement(payload) {
|
|
|
1587
1698
|
|
|
1588
1699
|
// templates/empty.json
|
|
1589
1700
|
var empty_default = {
|
|
1590
|
-
id: "
|
|
1591
|
-
name: "
|
|
1701
|
+
id: "1",
|
|
1702
|
+
name: "Playground Demo",
|
|
1592
1703
|
version: "1.0.0",
|
|
1593
1704
|
published: true,
|
|
1594
1705
|
creator: "Kevin Guerrero",
|
|
@@ -1633,7 +1744,7 @@ var empty_default = {
|
|
|
1633
1744
|
tagName: "mj-text",
|
|
1634
1745
|
data: {
|
|
1635
1746
|
value: {
|
|
1636
|
-
content: '<p class="paragraph" style=" padding: 4px 0; font-family: Arial, sans-serif;"
|
|
1747
|
+
content: '<p class="paragraph" style=" padding: 4px 0; font-family: Arial, sans-serif;">Welcome to our Open House! Please join us for a tour of this beautiful home.</p>'
|
|
1637
1748
|
}
|
|
1638
1749
|
},
|
|
1639
1750
|
attributes: {
|
|
@@ -1646,180 +1757,6 @@ var empty_default = {
|
|
|
1646
1757
|
}
|
|
1647
1758
|
]
|
|
1648
1759
|
},
|
|
1649
|
-
{
|
|
1650
|
-
type: "section-property-km",
|
|
1651
|
-
tagName: "mj-section",
|
|
1652
|
-
data: { value: { columnRows: 1, columnWidths: [] } },
|
|
1653
|
-
attributes: { "background-color": "#FFFFFF", padding: "12px 12px 12px 12px" },
|
|
1654
|
-
children: [
|
|
1655
|
-
{
|
|
1656
|
-
type: "column",
|
|
1657
|
-
tagName: "mj-column",
|
|
1658
|
-
data: { value: {} },
|
|
1659
|
-
attributes: { "background-color": "#FFFFFF", width: "500px", padding: "0px", border: "1px solid #dddddd", "border-radius": "0px" },
|
|
1660
|
-
children: [
|
|
1661
|
-
{
|
|
1662
|
-
type: "property-card",
|
|
1663
|
-
tagName: "mj-colproperty",
|
|
1664
|
-
data: { value: {} },
|
|
1665
|
-
attributes: {
|
|
1666
|
-
"image-src": "https://cornerstonepropertymgmt.com/wp-content/themes/cornerstone/assets/img/nofeaturedimage.jpg",
|
|
1667
|
-
"image-alt": "Beautiful modern home with pool",
|
|
1668
|
-
description: "Beautiful modern home with pool",
|
|
1669
|
-
price: "1000000",
|
|
1670
|
-
address: "123 Main Street",
|
|
1671
|
-
city: "Austin, TX 78701",
|
|
1672
|
-
beds: "",
|
|
1673
|
-
baths: "2",
|
|
1674
|
-
sqft: "1,850",
|
|
1675
|
-
href: "https://www.zillow.com/homedetails/126-Cara-Mia-Ln-Galloway-NJ-08205/68297408_zpid/?rtoken=6acd62a8-1848-41ed-919b-0034083eafca~X1-ZUu7aphk9l2689_9ej1i&utm_campaign=emo-instantsearchdigest&utm_source=email&utm_term=urn%3Amsg%3A20251026011813e84b11d632bb8725&utm_medium=email&utm_content=forsaleimage&sse=X1-SSsyx4z97dhglz0000000000_1pt02&srp=H4sIAAAAAAAAAHWRwXKDIBCGn8ZjokKQeOh0YpOZ9Nihh94yRNfozAoOYFrz9FXR1h7KgVn%2B799lF8JKN2DDUpuLlQjhswVp8uqtA9MLJx08BTwLCGlkm%2BlOFXaIA3rw4idY588bvtuyNElSEpCXQQK5JpTtk4h6YnXnKo9ouiWcUco8UdqsSMIp2fOAHz00cKu1EoCQuyGYu2CZb8TT18LLSRwtt3nw3rfg0VSQzTXLGh2Yacr1VLU9IJ7HZ1mrd4ndbHNmiJbGQMkrgsgrrfG%2FhFKi%2Fc24wt9XbOp5HDZaFpeVdyjE9BknZTRiA8otEw77R7wRwvZfu0fKi%2BqGj%2BhnXeLWRWR08uM33zV%2BmeABAAA%3D",
|
|
1676
|
-
status: "Empty",
|
|
1677
|
-
"status-color": "#B8B8B8",
|
|
1678
|
-
"is-new": "",
|
|
1679
|
-
"is-open-house": "1",
|
|
1680
|
-
"open-house-date": "2026-01-29",
|
|
1681
|
-
"open-house-time": "01:00-13:07",
|
|
1682
|
-
brokerage: "Keller Williams Atlantic Shore",
|
|
1683
|
-
"mls-logo": "https://t4.ftcdn.net/jpg/06/71/92/37/360_F_671923740_x0zOL3OIuUAnSF6sr7PuznCI5bQFKhI0.jpg",
|
|
1684
|
-
"border-radius": "0px",
|
|
1685
|
-
border: "1px solid #dddddd",
|
|
1686
|
-
"font-family": "Arial, sans-serif",
|
|
1687
|
-
"text-color": "#000000",
|
|
1688
|
-
"price-text-color": "",
|
|
1689
|
-
"details-text-color": "",
|
|
1690
|
-
"address-text-color": "",
|
|
1691
|
-
"brokerage-text-color": "#535364",
|
|
1692
|
-
"description-text-color": "",
|
|
1693
|
-
"mls-logo-text-color": "",
|
|
1694
|
-
"status-text-color": "",
|
|
1695
|
-
"new-text-color": "",
|
|
1696
|
-
"open-house-text-color": ""
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
]
|
|
1700
|
-
}
|
|
1701
|
-
]
|
|
1702
|
-
},
|
|
1703
|
-
{
|
|
1704
|
-
type: "section-property-single-two",
|
|
1705
|
-
tagName: "mj-section",
|
|
1706
|
-
data: { value: { columnRows: 1, columnWidths: [] } },
|
|
1707
|
-
attributes: { "background-color": "#FFFFFF", padding: "12px 12px 12px 12px" },
|
|
1708
|
-
children: [
|
|
1709
|
-
{
|
|
1710
|
-
type: "column",
|
|
1711
|
-
tagName: "mj-column",
|
|
1712
|
-
data: { value: {} },
|
|
1713
|
-
attributes: { "background-color": "#FFFFFF", width: "500px", padding: "0px", border: "1px solid #dddddd", "border-radius": "12px" },
|
|
1714
|
-
children: [
|
|
1715
|
-
{
|
|
1716
|
-
type: "property-card-single-two",
|
|
1717
|
-
tagName: "mj-propertysingletwo",
|
|
1718
|
-
data: { value: {} },
|
|
1719
|
-
attributes: {
|
|
1720
|
-
"image-src": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXddI94MwjUVz5M4CyDxZhSkIIwWbyDF59_w&s",
|
|
1721
|
-
"image-alt": "Beautiful modern home with pool",
|
|
1722
|
-
description: "Beautiful modern home with pool",
|
|
1723
|
-
price: "324203492034",
|
|
1724
|
-
address: "123 Main Street",
|
|
1725
|
-
city: "Austin, TX 78701",
|
|
1726
|
-
beds: "",
|
|
1727
|
-
baths: "",
|
|
1728
|
-
sqft: "",
|
|
1729
|
-
href: "https://www.zillow.com/homedetails/126-Cara-Mia-Ln-Galloway-NJ-08205/68297408_zpid/?rtoken=6acd62a8-1848-41ed-919b-0034083eafca~X1-ZUu7aphk9l2689_9ej1i&utm_campaign=emo-instantsearchdigest&utm_source=email&utm_term=urn%3Amsg%3A20251026011813e84b11d632bb8725&utm_medium=email&utm_content=forsaleimage&sse=X1-SSsyx4z97dhglz0000000000_1pt02&srp=H4sIAAAAAAAAAHWRwXKDIBCGn8ZjokKQeOh0YpOZ9Nihh94yRNfozAoOYFrz9FXR1h7KgVn%2B799lF8JKN2DDUpuLlQjhswVp8uqtA9MLJx08BTwLCGlkm%2BlOFXaIA3rw4idY588bvtuyNElSEpCXQQK5JpTtk4h6YnXnKo9ouiWcUco8UdqsSMIp2fOAHz00cKu1EoCQuyGYu2CZb8TT18LLSRwtt3nw3rfg0VSQzTXLGh2Yacr1VLU9IJ7HZ1mrd4ndbHNmiJbGQMkrgsgrrfG%2FhFKi%2Fc24wt9XbOp5HDZaFpeVdyjE9BknZTRiA8otEw77R7wRwvZfu0fKi%2BqGj%2BhnXeLWRWR08uM33zV%2BmeABAAA%3D",
|
|
1730
|
-
status: "Just Listed",
|
|
1731
|
-
"status-color": "#008000",
|
|
1732
|
-
"is-new": "1",
|
|
1733
|
-
"is-open-house": "",
|
|
1734
|
-
"open-house-date": "03/25",
|
|
1735
|
-
"open-house-time": "12pm-1pm",
|
|
1736
|
-
brokerage: "Keller Williams Atlantic Shore",
|
|
1737
|
-
"mls-logo": "https://t4.ftcdn.net/jpg/06/71/92/37/360_F_671923740_x0zOL3OIuUAnSF6sr7PuznCI5bQFKhI0.jpg",
|
|
1738
|
-
"border-radius": "12px",
|
|
1739
|
-
border: "1x solid #dddddd",
|
|
1740
|
-
"font-family": "Arial, sans-serif",
|
|
1741
|
-
"text-color": "#000000"
|
|
1742
|
-
}
|
|
1743
|
-
}
|
|
1744
|
-
]
|
|
1745
|
-
}
|
|
1746
|
-
]
|
|
1747
|
-
},
|
|
1748
|
-
{
|
|
1749
|
-
type: "section-property-triple",
|
|
1750
|
-
tagName: "mj-section",
|
|
1751
|
-
data: { value: { columnRows: 1, columnWidths: [] } },
|
|
1752
|
-
attributes: { "background-color": "#FFFFFF", padding: "12px" },
|
|
1753
|
-
children: [
|
|
1754
|
-
{
|
|
1755
|
-
type: "column",
|
|
1756
|
-
tagName: "mj-column",
|
|
1757
|
-
data: { value: {} },
|
|
1758
|
-
attributes: { "background-color": "transparent", padding: "0px", "css-class": "property-triple-section-column", width: "500px" },
|
|
1759
|
-
children: [
|
|
1760
|
-
{
|
|
1761
|
-
type: "property-card-triple",
|
|
1762
|
-
tagName: "mj-propertytriple",
|
|
1763
|
-
data: { value: {} },
|
|
1764
|
-
attributes: {
|
|
1765
|
-
width: "100%",
|
|
1766
|
-
gap: "24px",
|
|
1767
|
-
"border-radius": "8px",
|
|
1768
|
-
border: "1px solid #d1d1d5",
|
|
1769
|
-
"image-height": "102px",
|
|
1770
|
-
"font-family": "Arial, sans-serif",
|
|
1771
|
-
"text-color": "#000000",
|
|
1772
|
-
"background-color": "#FFFFFF"
|
|
1773
|
-
},
|
|
1774
|
-
children: [
|
|
1775
|
-
{
|
|
1776
|
-
type: "property-card-triple-item",
|
|
1777
|
-
tagName: "mj-propertytripleitem",
|
|
1778
|
-
data: { value: {} },
|
|
1779
|
-
attributes: {
|
|
1780
|
-
"image-src": "https://photos.zillowstatic.com/fp/a8e605d336d0b5a94d91828aee3c0afb-p_i.jpg",
|
|
1781
|
-
href: "",
|
|
1782
|
-
price: "$320,000",
|
|
1783
|
-
beds: "3",
|
|
1784
|
-
baths: "2",
|
|
1785
|
-
sqft: "1,385",
|
|
1786
|
-
city: "Egg Harbor City"
|
|
1787
|
-
}
|
|
1788
|
-
},
|
|
1789
|
-
{
|
|
1790
|
-
type: "property-card-triple-item",
|
|
1791
|
-
tagName: "mj-propertytripleitem",
|
|
1792
|
-
data: { value: {} },
|
|
1793
|
-
attributes: {
|
|
1794
|
-
"image-src": "https://photos.zillowstatic.com/fp/4d72133271685e778a0126b3defd9854-p_i.jpg",
|
|
1795
|
-
href: "",
|
|
1796
|
-
price: "$282,000",
|
|
1797
|
-
beds: "2",
|
|
1798
|
-
baths: "2",
|
|
1799
|
-
sqft: "1,224",
|
|
1800
|
-
city: "Egg Harbor"
|
|
1801
|
-
}
|
|
1802
|
-
},
|
|
1803
|
-
{
|
|
1804
|
-
type: "property-card-triple-item",
|
|
1805
|
-
tagName: "mj-propertytripleitem",
|
|
1806
|
-
data: { value: {} },
|
|
1807
|
-
attributes: {
|
|
1808
|
-
"image-src": "https://photos.zillowstatic.com/fp/26e69f22548989c0e4d1ec372ce178e0-p_i.jpg",
|
|
1809
|
-
href: "",
|
|
1810
|
-
price: "$484,900",
|
|
1811
|
-
beds: "3",
|
|
1812
|
-
baths: "1",
|
|
1813
|
-
sqft: "1,417",
|
|
1814
|
-
city: "Egg Harbor"
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
]
|
|
1818
|
-
}
|
|
1819
|
-
]
|
|
1820
|
-
}
|
|
1821
|
-
]
|
|
1822
|
-
},
|
|
1823
1760
|
{
|
|
1824
1761
|
type: "section",
|
|
1825
1762
|
tagName: "mj-section",
|
|
@@ -1859,7 +1796,6 @@ var empty_default = {
|
|
|
1859
1796
|
|
|
1860
1797
|
// src/core/editor/state/editor.ts
|
|
1861
1798
|
var SECTION_INDEX_REGEX = /^content\.children\.\[(\d+)\]/;
|
|
1862
|
-
var MAX_TEMPLATE_SIZE = 50 * 1024;
|
|
1863
1799
|
function calculateTemplateSize(template) {
|
|
1864
1800
|
const str = JSON.stringify(template);
|
|
1865
1801
|
return new Blob([str]).size;
|
|
@@ -1880,6 +1816,7 @@ var useEditorStore = create()(
|
|
|
1880
1816
|
onSave: null,
|
|
1881
1817
|
onToast: null,
|
|
1882
1818
|
onExit: null,
|
|
1819
|
+
onImageUpload: null,
|
|
1883
1820
|
previewMode: false,
|
|
1884
1821
|
focusIdx: null,
|
|
1885
1822
|
hoverIdx: null,
|
|
@@ -1888,6 +1825,7 @@ var useEditorStore = create()(
|
|
|
1888
1825
|
dataTransfer: null,
|
|
1889
1826
|
isScaling: false,
|
|
1890
1827
|
slashCommand: null,
|
|
1828
|
+
mergeFieldSuggestion: null,
|
|
1891
1829
|
textEditing: null,
|
|
1892
1830
|
pendingTextEditRequest: null,
|
|
1893
1831
|
tiptapEditor: null,
|
|
@@ -1906,19 +1844,27 @@ var useEditorStore = create()(
|
|
|
1906
1844
|
// User data
|
|
1907
1845
|
images: [],
|
|
1908
1846
|
userData: null,
|
|
1847
|
+
mergeFields: [],
|
|
1848
|
+
// Render sync
|
|
1849
|
+
renderSyncNeeded: 0,
|
|
1909
1850
|
// Initialize store with external template (for npm package usage)
|
|
1910
|
-
initializeWithTemplate: (templateId, template, onSave, onToast, data, onExit) => {
|
|
1851
|
+
initializeWithTemplate: (templateId, template, onSave, onToast, data, onExit, onImageUpload) => {
|
|
1911
1852
|
set((state) => {
|
|
1912
1853
|
state.templateId = templateId;
|
|
1913
1854
|
state.template = template;
|
|
1914
1855
|
state.onSave = onSave ?? null;
|
|
1915
1856
|
state.onToast = onToast ?? null;
|
|
1916
1857
|
state.onExit = onExit ?? null;
|
|
1858
|
+
state.onImageUpload = onImageUpload ?? null;
|
|
1917
1859
|
state.isPaidLevel = data?.isPaidLevel ?? 0;
|
|
1918
1860
|
state.images = data?.images ?? [];
|
|
1919
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
|
+
}));
|
|
1920
1866
|
state.templateSize = calculateTemplateSize(template);
|
|
1921
|
-
state.isAtSizeLimit =
|
|
1867
|
+
state.isAtSizeLimit = state.templateSize >= MAX_TEMPLATE_SIZE;
|
|
1922
1868
|
state.history = [cloneDeep(template)];
|
|
1923
1869
|
state.historyIndex = 0;
|
|
1924
1870
|
state.focusIdx = null;
|
|
@@ -1927,6 +1873,11 @@ var useEditorStore = create()(
|
|
|
1927
1873
|
state.lastSavedSnapshot = JSON.stringify(template);
|
|
1928
1874
|
});
|
|
1929
1875
|
},
|
|
1876
|
+
addImage: (image2) => {
|
|
1877
|
+
set((state) => {
|
|
1878
|
+
state.images.push(castDraft(image2));
|
|
1879
|
+
});
|
|
1880
|
+
},
|
|
1930
1881
|
// Template metadata actions
|
|
1931
1882
|
setTemplateName: (name) => {
|
|
1932
1883
|
set((state) => {
|
|
@@ -2007,6 +1958,17 @@ var useEditorStore = create()(
|
|
|
2007
1958
|
}, 0);
|
|
2008
1959
|
}
|
|
2009
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
|
+
},
|
|
2010
1972
|
// Text editing actions (Tiptap overlay)
|
|
2011
1973
|
startTextEditing: (textEditingState) => {
|
|
2012
1974
|
set((state) => {
|
|
@@ -2182,6 +2144,7 @@ var useEditorStore = create()(
|
|
|
2182
2144
|
return;
|
|
2183
2145
|
}
|
|
2184
2146
|
Object.assign(element, updates);
|
|
2147
|
+
state2.renderSyncNeeded += 1;
|
|
2185
2148
|
});
|
|
2186
2149
|
},
|
|
2187
2150
|
// Update element content (for contenteditable)
|
|
@@ -3084,129 +3047,19 @@ function setValueAtPath(template, path, value) {
|
|
|
3084
3047
|
|
|
3085
3048
|
// src/core/editor/components/ShadowDomRenderer.tsx
|
|
3086
3049
|
import { useEffect, useRef, memo } from "react";
|
|
3050
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3051
|
+
var lastSizeLimitToastTime = 0;
|
|
3052
|
+
var cssCache = /* @__PURE__ */ new Map();
|
|
3053
|
+
function getEditorStyles(isDragButtonHovered, textEditingIdx) {
|
|
3054
|
+
const cacheKey = `${isDragButtonHovered}-${textEditingIdx ?? "null"}`;
|
|
3055
|
+
const cached = cssCache.get(cacheKey);
|
|
3056
|
+
if (cached) return cached;
|
|
3057
|
+
const hiddenSelectors = !isDragButtonHovered && HIDDEN_SELECTION_VISUAL_ELEMENTS.length > 0 ? HIDDEN_SELECTION_VISUAL_ELEMENTS.map((type) => `.node-type-${type}`).join(", ") : null;
|
|
3058
|
+
const css = `
|
|
3087
3059
|
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
var ALIGNMENT_ICONS = {
|
|
3092
|
-
left: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-left.svg",
|
|
3093
|
-
center: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-center.svg",
|
|
3094
|
-
right: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-right.svg"
|
|
3095
|
-
};
|
|
3096
|
-
var FONTS = [
|
|
3097
|
-
"Arial",
|
|
3098
|
-
"Helvetica",
|
|
3099
|
-
"Times New Roman",
|
|
3100
|
-
"Courier New",
|
|
3101
|
-
"Verdana",
|
|
3102
|
-
"Tahoma",
|
|
3103
|
-
"Trebuchet MS",
|
|
3104
|
-
"Georgia"
|
|
3105
|
-
];
|
|
3106
|
-
var TEXT_ALIGNMENT_ICONS = {
|
|
3107
|
-
left: AlignLeftIcon,
|
|
3108
|
-
center: AlignCenterIcon,
|
|
3109
|
-
right: AlignRightIcon,
|
|
3110
|
-
justify: AlignJustifyIcon
|
|
3111
|
-
};
|
|
3112
|
-
var TEXT_TYPE_OPTIONS = [
|
|
3113
|
-
{ type: "paragraph", label: "Paragraph", Icon: Pilcrow, disabled: false },
|
|
3114
|
-
{ type: "h1", label: "Heading 1", Icon: Heading1Icon, disabled: false },
|
|
3115
|
-
{ type: "h2", label: "Heading 2", Icon: Heading2Icon, disabled: false },
|
|
3116
|
-
{ type: "h3", label: "Heading 3", Icon: Heading3Icon, disabled: false },
|
|
3117
|
-
{ type: "list", label: "Bulleted", Icon: ListIcon, disabled: true },
|
|
3118
|
-
{ type: "ordered", label: "Numbered", Icon: ListOrderedIcon, disabled: true }
|
|
3119
|
-
];
|
|
3120
|
-
var DEFAULT_FONT_SIZE = 14;
|
|
3121
|
-
var MIN_FONT_SIZE = 6;
|
|
3122
|
-
var MAX_FONT_SIZE = 72;
|
|
3123
|
-
var FONT_SIZE_STEP = 1;
|
|
3124
|
-
var LINK_TYPES = [
|
|
3125
|
-
{
|
|
3126
|
-
name: "Email",
|
|
3127
|
-
placeholder: "email@example.com",
|
|
3128
|
-
icon: MailIcon,
|
|
3129
|
-
inputType: "email",
|
|
3130
|
-
prefix: "mailto:"
|
|
3131
|
-
},
|
|
3132
|
-
{
|
|
3133
|
-
name: "Website",
|
|
3134
|
-
placeholder: "https://example.com",
|
|
3135
|
-
icon: LinkIcon,
|
|
3136
|
-
inputType: "url",
|
|
3137
|
-
prefix: ""
|
|
3138
|
-
},
|
|
3139
|
-
{
|
|
3140
|
-
name: "Phone",
|
|
3141
|
-
placeholder: "+1234567890",
|
|
3142
|
-
icon: PhoneIcon,
|
|
3143
|
-
inputType: "tel",
|
|
3144
|
-
prefix: "tel:"
|
|
3145
|
-
}
|
|
3146
|
-
];
|
|
3147
|
-
var LINK_PRESETS = {
|
|
3148
|
-
Phone: [
|
|
3149
|
-
{ label: "Personal Phone", key: "personal_phone_number" },
|
|
3150
|
-
{ label: "Office Phone", key: "office_phone_number" },
|
|
3151
|
-
{ label: "Business Phone", key: "business_phone_number" }
|
|
3152
|
-
],
|
|
3153
|
-
Website: [
|
|
3154
|
-
{ label: "Team Website", key: "team_website" },
|
|
3155
|
-
{ label: "Brokerage Website", key: "brokerage_website" }
|
|
3156
|
-
]
|
|
3157
|
-
};
|
|
3158
|
-
var detectLinkType = (href) => {
|
|
3159
|
-
if (href.startsWith("mailto:")) return LINK_TYPES[0];
|
|
3160
|
-
if (href.startsWith("tel:")) return LINK_TYPES[2];
|
|
3161
|
-
return LINK_TYPES[1];
|
|
3162
|
-
};
|
|
3163
|
-
var stripPrefix = (href) => {
|
|
3164
|
-
if (href.startsWith("mailto:")) return href.slice(7);
|
|
3165
|
-
if (href.startsWith("tel:")) return href.slice(4);
|
|
3166
|
-
return href;
|
|
3167
|
-
};
|
|
3168
|
-
var normalizeWebsiteUrl = (url) => {
|
|
3169
|
-
if (!url) return "";
|
|
3170
|
-
if (url.match(/^https?:\/\//i)) return url;
|
|
3171
|
-
if (url.startsWith("mailto:") || url.startsWith("tel:")) return url;
|
|
3172
|
-
return "https://" + url;
|
|
3173
|
-
};
|
|
3174
|
-
var DEFAULT_LETTER_SPACING = 0;
|
|
3175
|
-
var MIN_LETTER_SPACING = -2;
|
|
3176
|
-
var MAX_LETTER_SPACING = 10;
|
|
3177
|
-
var LETTER_SPACING_STEP = 0.1;
|
|
3178
|
-
var DEFAULT_LINE_HEIGHT = 1.4;
|
|
3179
|
-
var MIN_LINE_HEIGHT = 0.8;
|
|
3180
|
-
var MAX_LINE_HEIGHT = 3;
|
|
3181
|
-
var LINE_HEIGHT_STEP = 0.1;
|
|
3182
|
-
var HIDDEN_SELECTION_VISUAL_ELEMENTS = ["text", "divider", "column"];
|
|
3183
|
-
var NOT_DRAGGABLE_ELEMENTS = ["page", "social-item", "text", "property-card", "property-card-single-two", "property-card-triple", "property-card-triple-item"];
|
|
3184
|
-
var EDITOR_COLORS = {
|
|
3185
|
-
/** Purple — drag/drop state */
|
|
3186
|
-
drag: {
|
|
3187
|
-
solid: "rgb(59, 130, 246)",
|
|
3188
|
-
half: "rgba(59, 130, 246, 0.5)"
|
|
3189
|
-
},
|
|
3190
|
-
/** Blue — hover/selection state */
|
|
3191
|
-
hover: {
|
|
3192
|
-
solid: "rgb(59, 130, 246)",
|
|
3193
|
-
half: "rgba(59, 130, 246, 0.5)"
|
|
3194
|
-
}
|
|
3195
|
-
};
|
|
3196
|
-
|
|
3197
|
-
// src/core/editor/components/ShadowDomRenderer.tsx
|
|
3198
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3199
|
-
var lastSizeLimitToastTime = 0;
|
|
3200
|
-
var cssCache = /* @__PURE__ */ new Map();
|
|
3201
|
-
function getEditorStyles(isDragButtonHovered, textEditingIdx) {
|
|
3202
|
-
const cacheKey = `${isDragButtonHovered}-${textEditingIdx ?? "null"}`;
|
|
3203
|
-
const cached = cssCache.get(cacheKey);
|
|
3204
|
-
if (cached) return cached;
|
|
3205
|
-
const hiddenSelectors = !isDragButtonHovered && HIDDEN_SELECTION_VISUAL_ELEMENTS.length > 0 ? HIDDEN_SELECTION_VISUAL_ELEMENTS.map((type) => `.node-type-${type}`).join(", ") : null;
|
|
3206
|
-
const css = `
|
|
3207
|
-
/* Base reset for email content */
|
|
3208
|
-
* {
|
|
3209
|
-
box-sizing: border-box;
|
|
3060
|
+
/* Base reset for email content */
|
|
3061
|
+
* {
|
|
3062
|
+
box-sizing: border-box;
|
|
3210
3063
|
}
|
|
3211
3064
|
|
|
3212
3065
|
/* Make all email blocks interactive */
|
|
@@ -3528,6 +3381,19 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
|
|
|
3528
3381
|
}
|
|
3529
3382
|
` : ""}
|
|
3530
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
|
+
|
|
3531
3397
|
/* Company footer - hide selection/hover outlines and make non-interactive */
|
|
3532
3398
|
.is-company-footer,
|
|
3533
3399
|
.is-company-footer .${EMAIL_BLOCK_CLASS_NAME} {
|
|
@@ -4153,6 +4019,7 @@ function isTextContentEmpty(element) {
|
|
|
4153
4019
|
const text2 = element.textContent?.trim() || "";
|
|
4154
4020
|
return text2.length === 0;
|
|
4155
4021
|
}
|
|
4022
|
+
var MERGE_FIELD_REGEX_SHADOW = /\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}/g;
|
|
4156
4023
|
function isParagraphEmpty(p) {
|
|
4157
4024
|
const text2 = p.textContent || "";
|
|
4158
4025
|
return text2.trim() === "" || text2 === "\xA0" || text2 === " ";
|
|
@@ -4174,6 +4041,40 @@ function injectContentEditable(container) {
|
|
|
4174
4041
|
}
|
|
4175
4042
|
}
|
|
4176
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
|
+
}
|
|
4177
4078
|
}
|
|
4178
4079
|
});
|
|
4179
4080
|
container.querySelectorAll(".node-type-button").forEach((buttonEl) => {
|
|
@@ -4995,6 +4896,158 @@ var ElementsSuggestionsContent = () => {
|
|
|
4995
4896
|
);
|
|
4996
4897
|
};
|
|
4997
4898
|
|
|
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
|
+
|
|
4998
5051
|
// src/core/editor/components/tiptap-overlay.tsx
|
|
4999
5052
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
5000
5053
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
@@ -5861,7 +5914,7 @@ function normalizeKeyName(name) {
|
|
|
5861
5914
|
}
|
|
5862
5915
|
let alt;
|
|
5863
5916
|
let ctrl;
|
|
5864
|
-
let
|
|
5917
|
+
let shift5;
|
|
5865
5918
|
let meta;
|
|
5866
5919
|
for (let i = 0; i < parts.length - 1; i += 1) {
|
|
5867
5920
|
const mod = parts[i];
|
|
@@ -5872,7 +5925,7 @@ function normalizeKeyName(name) {
|
|
|
5872
5925
|
} else if (/^(c|ctrl|control)$/i.test(mod)) {
|
|
5873
5926
|
ctrl = true;
|
|
5874
5927
|
} else if (/^s(hift)?$/i.test(mod)) {
|
|
5875
|
-
|
|
5928
|
+
shift5 = true;
|
|
5876
5929
|
} else if (/^mod$/i.test(mod)) {
|
|
5877
5930
|
if (isiOS() || isMacOS()) {
|
|
5878
5931
|
meta = true;
|
|
@@ -5892,7 +5945,7 @@ function normalizeKeyName(name) {
|
|
|
5892
5945
|
if (meta) {
|
|
5893
5946
|
result = `Meta-${result}`;
|
|
5894
5947
|
}
|
|
5895
|
-
if (
|
|
5948
|
+
if (shift5) {
|
|
5896
5949
|
result = `Shift-${result}`;
|
|
5897
5950
|
}
|
|
5898
5951
|
return result;
|
|
@@ -10744,8 +10797,8 @@ var Link = Mark.create({
|
|
|
10744
10797
|
var index_default = Link;
|
|
10745
10798
|
|
|
10746
10799
|
// src/core/editor/components/tiptap-overlay.tsx
|
|
10747
|
-
import { useFloating as
|
|
10748
|
-
import { useEffect as
|
|
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";
|
|
10749
10802
|
|
|
10750
10803
|
// src/core/editor/extensions/inverse-placeholder.ts
|
|
10751
10804
|
import { Plugin as Plugin12, PluginKey as PluginKey10 } from "@tiptap/pm/state";
|
|
@@ -10955,25 +11008,69 @@ var HeadingParagraph = Node3.create({
|
|
|
10955
11008
|
}
|
|
10956
11009
|
});
|
|
10957
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
|
+
|
|
10958
11052
|
// src/core/editor/hooks/use-editor-store-refs.ts
|
|
10959
|
-
import { useRef as
|
|
11053
|
+
import { useRef as useRef4, useEffect as useEffect5 } from "react";
|
|
10960
11054
|
function useEditorStoreRefs() {
|
|
10961
11055
|
const store = useEditorStore();
|
|
10962
11056
|
const refs = {
|
|
10963
|
-
stopTextEditing:
|
|
10964
|
-
updateElementContent:
|
|
10965
|
-
setSlashCommand:
|
|
10966
|
-
clearSlashCommand:
|
|
10967
|
-
findAdjacentElement:
|
|
10968
|
-
deleteElement:
|
|
10969
|
-
setFocusIdx:
|
|
10970
|
-
requestTextEditingOnElement:
|
|
10971
|
-
clearPendingTextEditRequest:
|
|
10972
|
-
template:
|
|
10973
|
-
slashCommand:
|
|
10974
|
-
|
|
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)
|
|
10975
11072
|
};
|
|
10976
|
-
|
|
11073
|
+
useEffect5(() => {
|
|
10977
11074
|
refs.stopTextEditing.current = store.stopTextEditing;
|
|
10978
11075
|
refs.updateElementContent.current = store.updateElementContent;
|
|
10979
11076
|
refs.setSlashCommand.current = store.setSlashCommand;
|
|
@@ -10985,6 +11082,9 @@ function useEditorStoreRefs() {
|
|
|
10985
11082
|
refs.clearPendingTextEditRequest.current = store.clearPendingTextEditRequest;
|
|
10986
11083
|
refs.template.current = store.template;
|
|
10987
11084
|
refs.slashCommand.current = store.slashCommand;
|
|
11085
|
+
refs.mergeFieldSuggestion.current = store.mergeFieldSuggestion;
|
|
11086
|
+
refs.setMergeFieldSuggestion.current = store.setMergeFieldSuggestion;
|
|
11087
|
+
refs.clearMergeFieldSuggestion.current = store.clearMergeFieldSuggestion;
|
|
10988
11088
|
refs.pushHistory.current = store.pushHistory;
|
|
10989
11089
|
}, [
|
|
10990
11090
|
store.stopTextEditing,
|
|
@@ -10998,6 +11098,9 @@ function useEditorStoreRefs() {
|
|
|
10998
11098
|
store.clearPendingTextEditRequest,
|
|
10999
11099
|
store.template,
|
|
11000
11100
|
store.slashCommand,
|
|
11101
|
+
store.mergeFieldSuggestion,
|
|
11102
|
+
store.setMergeFieldSuggestion,
|
|
11103
|
+
store.clearMergeFieldSuggestion,
|
|
11001
11104
|
store.pushHistory
|
|
11002
11105
|
]);
|
|
11003
11106
|
return refs;
|
|
@@ -11045,12 +11148,12 @@ function checkElementPosition(template, elementIdx) {
|
|
|
11045
11148
|
|
|
11046
11149
|
// src/components/ui/tooltip.tsx
|
|
11047
11150
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
11048
|
-
import { jsx as
|
|
11151
|
+
import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
11049
11152
|
function TooltipProvider({
|
|
11050
11153
|
delayDuration = 0,
|
|
11051
11154
|
...props
|
|
11052
11155
|
}) {
|
|
11053
|
-
return /* @__PURE__ */
|
|
11156
|
+
return /* @__PURE__ */ jsx15(
|
|
11054
11157
|
TooltipPrimitive.Provider,
|
|
11055
11158
|
{
|
|
11056
11159
|
"data-slot": "tooltip-provider",
|
|
@@ -11062,12 +11165,12 @@ function TooltipProvider({
|
|
|
11062
11165
|
function Tooltip({
|
|
11063
11166
|
...props
|
|
11064
11167
|
}) {
|
|
11065
|
-
return /* @__PURE__ */
|
|
11168
|
+
return /* @__PURE__ */ jsx15(TooltipProvider, { children: /* @__PURE__ */ jsx15(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
|
|
11066
11169
|
}
|
|
11067
11170
|
function TooltipTrigger({
|
|
11068
11171
|
...props
|
|
11069
11172
|
}) {
|
|
11070
|
-
return /* @__PURE__ */
|
|
11173
|
+
return /* @__PURE__ */ jsx15(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
11071
11174
|
}
|
|
11072
11175
|
function TooltipContent({
|
|
11073
11176
|
className,
|
|
@@ -11075,7 +11178,7 @@ function TooltipContent({
|
|
|
11075
11178
|
children,
|
|
11076
11179
|
...props
|
|
11077
11180
|
}) {
|
|
11078
|
-
return /* @__PURE__ */
|
|
11181
|
+
return /* @__PURE__ */ jsx15(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs6(
|
|
11079
11182
|
TooltipPrimitive.Content,
|
|
11080
11183
|
{
|
|
11081
11184
|
"data-slot": "tooltip-content",
|
|
@@ -11087,7 +11190,7 @@ function TooltipContent({
|
|
|
11087
11190
|
...props,
|
|
11088
11191
|
children: [
|
|
11089
11192
|
children,
|
|
11090
|
-
/* @__PURE__ */
|
|
11193
|
+
/* @__PURE__ */ jsx15(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
11091
11194
|
]
|
|
11092
11195
|
}
|
|
11093
11196
|
) });
|
|
@@ -11097,12 +11200,12 @@ function TooltipContent({
|
|
|
11097
11200
|
import { BotIcon } from "lucide-react";
|
|
11098
11201
|
|
|
11099
11202
|
// src/core/editor/components/text-link-menu.tsx
|
|
11100
|
-
import { useState, useEffect as
|
|
11203
|
+
import { useState as useState2, useEffect as useEffect6 } from "react";
|
|
11101
11204
|
|
|
11102
11205
|
// src/components/ui/input.tsx
|
|
11103
|
-
import { jsx as
|
|
11206
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
11104
11207
|
function Input({ className, type, ...props }) {
|
|
11105
|
-
return /* @__PURE__ */
|
|
11208
|
+
return /* @__PURE__ */ jsx16(
|
|
11106
11209
|
"input",
|
|
11107
11210
|
{
|
|
11108
11211
|
type,
|
|
@@ -11123,12 +11226,12 @@ import { CheckIcon, CopyIcon, LinkIcon as LinkIcon2, PencilIcon, TrashIcon } fro
|
|
|
11123
11226
|
|
|
11124
11227
|
// src/components/ui/label.tsx
|
|
11125
11228
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
11126
|
-
import { jsx as
|
|
11229
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
11127
11230
|
function Label({
|
|
11128
11231
|
className,
|
|
11129
11232
|
...props
|
|
11130
11233
|
}) {
|
|
11131
|
-
return /* @__PURE__ */
|
|
11234
|
+
return /* @__PURE__ */ jsx17(
|
|
11132
11235
|
LabelPrimitive.Root,
|
|
11133
11236
|
{
|
|
11134
11237
|
"data-slot": "label",
|
|
@@ -11143,14 +11246,14 @@ function Label({
|
|
|
11143
11246
|
|
|
11144
11247
|
// src/components/ui/separator.tsx
|
|
11145
11248
|
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
11146
|
-
import { jsx as
|
|
11249
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
11147
11250
|
function Separator({
|
|
11148
11251
|
className,
|
|
11149
11252
|
orientation = "horizontal",
|
|
11150
11253
|
decorative = true,
|
|
11151
11254
|
...props
|
|
11152
11255
|
}) {
|
|
11153
|
-
return /* @__PURE__ */
|
|
11256
|
+
return /* @__PURE__ */ jsx18(
|
|
11154
11257
|
SeparatorPrimitive.Root,
|
|
11155
11258
|
{
|
|
11156
11259
|
"data-slot": "separator",
|
|
@@ -11170,16 +11273,16 @@ var floatButtonVariants = "shadow-none transition-none cursor-pointer rounded-fu
|
|
|
11170
11273
|
|
|
11171
11274
|
// src/components/ui/popover.tsx
|
|
11172
11275
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
11173
|
-
import { jsx as
|
|
11276
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
11174
11277
|
function Popover({
|
|
11175
11278
|
...props
|
|
11176
11279
|
}) {
|
|
11177
|
-
return /* @__PURE__ */
|
|
11280
|
+
return /* @__PURE__ */ jsx19(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
|
|
11178
11281
|
}
|
|
11179
11282
|
function PopoverTrigger({
|
|
11180
11283
|
...props
|
|
11181
11284
|
}) {
|
|
11182
|
-
return /* @__PURE__ */
|
|
11285
|
+
return /* @__PURE__ */ jsx19(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
11183
11286
|
}
|
|
11184
11287
|
function PopoverContent({
|
|
11185
11288
|
className,
|
|
@@ -11187,7 +11290,7 @@ function PopoverContent({
|
|
|
11187
11290
|
sideOffset = 4,
|
|
11188
11291
|
...props
|
|
11189
11292
|
}) {
|
|
11190
|
-
return /* @__PURE__ */
|
|
11293
|
+
return /* @__PURE__ */ jsx19(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx19(
|
|
11191
11294
|
PopoverPrimitive.Content,
|
|
11192
11295
|
{
|
|
11193
11296
|
"data-slot": "popover-content",
|
|
@@ -11203,16 +11306,16 @@ function PopoverContent({
|
|
|
11203
11306
|
}
|
|
11204
11307
|
|
|
11205
11308
|
// src/core/editor/components/text-link-menu.tsx
|
|
11206
|
-
import { jsx as
|
|
11309
|
+
import { jsx as jsx20, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
11207
11310
|
var TextLinkMenu = ({ editor }) => {
|
|
11208
|
-
const [isOpen, setIsOpen] =
|
|
11209
|
-
const [inputValue, setInputValue] =
|
|
11210
|
-
const [showCopied, setShowCopied] =
|
|
11211
|
-
const [linkType, setLinkType] =
|
|
11212
|
-
const [isLinkTypeOpen, setIsLinkTypeOpen] =
|
|
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);
|
|
11213
11316
|
const currentHref = editor.getAttributes("link").href || "";
|
|
11214
11317
|
const hasLink = !!currentHref;
|
|
11215
|
-
|
|
11318
|
+
useEffect6(() => {
|
|
11216
11319
|
if (isOpen) {
|
|
11217
11320
|
setLinkType(detectLinkType(currentHref));
|
|
11218
11321
|
setInputValue(stripPrefix(currentHref));
|
|
@@ -11254,42 +11357,42 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11254
11357
|
editor.chain().focus().unsetLink().run();
|
|
11255
11358
|
setInputValue("");
|
|
11256
11359
|
};
|
|
11257
|
-
return /* @__PURE__ */
|
|
11258
|
-
/* @__PURE__ */
|
|
11259
|
-
/* @__PURE__ */
|
|
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(
|
|
11260
11363
|
Button,
|
|
11261
11364
|
{
|
|
11262
11365
|
variant: "ghost",
|
|
11263
11366
|
size: "icon",
|
|
11264
11367
|
className: floatButtonVariants,
|
|
11265
11368
|
onMouseDown: (e) => e.preventDefault(),
|
|
11266
|
-
children: /* @__PURE__ */
|
|
11369
|
+
children: /* @__PURE__ */ jsx20(PencilIcon, { className: "size-4" })
|
|
11267
11370
|
}
|
|
11268
|
-
) : /* @__PURE__ */
|
|
11371
|
+
) : /* @__PURE__ */ jsxs7(
|
|
11269
11372
|
Button,
|
|
11270
11373
|
{
|
|
11271
11374
|
variant: "ghost",
|
|
11272
11375
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
|
|
11273
11376
|
onMouseDown: (e) => e.preventDefault(),
|
|
11274
11377
|
children: [
|
|
11275
|
-
/* @__PURE__ */
|
|
11276
|
-
/* @__PURE__ */
|
|
11378
|
+
/* @__PURE__ */ jsx20(LinkIcon2, { className: "size-4" }),
|
|
11379
|
+
/* @__PURE__ */ jsx20("p", { children: "Add link" })
|
|
11277
11380
|
]
|
|
11278
11381
|
}
|
|
11279
11382
|
) }) }),
|
|
11280
|
-
/* @__PURE__ */
|
|
11383
|
+
/* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", children: hasLink ? "Edit link" : "Add link" })
|
|
11281
11384
|
] }),
|
|
11282
|
-
/* @__PURE__ */
|
|
11385
|
+
/* @__PURE__ */ jsxs7(
|
|
11283
11386
|
PopoverContent,
|
|
11284
11387
|
{
|
|
11285
11388
|
side: "bottom",
|
|
11286
11389
|
className: "w-[250px] p-3 shadow-lg z-50001",
|
|
11287
11390
|
"data-editor-toolbar": true,
|
|
11288
11391
|
children: [
|
|
11289
|
-
/* @__PURE__ */
|
|
11290
|
-
/* @__PURE__ */
|
|
11291
|
-
/* @__PURE__ */
|
|
11292
|
-
/* @__PURE__ */
|
|
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(
|
|
11293
11396
|
Input,
|
|
11294
11397
|
{
|
|
11295
11398
|
type: linkType.inputType,
|
|
@@ -11301,12 +11404,12 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11301
11404
|
autoFocus: true
|
|
11302
11405
|
}
|
|
11303
11406
|
),
|
|
11304
|
-
/* @__PURE__ */
|
|
11305
|
-
/* @__PURE__ */
|
|
11306
|
-
/* @__PURE__ */
|
|
11307
|
-
/* @__PURE__ */
|
|
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" })
|
|
11308
11411
|
] }),
|
|
11309
|
-
/* @__PURE__ */
|
|
11412
|
+
/* @__PURE__ */ jsx20(
|
|
11310
11413
|
PopoverContent,
|
|
11311
11414
|
{
|
|
11312
11415
|
side: "bottom",
|
|
@@ -11314,7 +11417,7 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11314
11417
|
className: "w-[160px] p-1 z-50001",
|
|
11315
11418
|
onPointerDownOutside: (e) => e.preventDefault(),
|
|
11316
11419
|
"data-editor-toolbar": true,
|
|
11317
|
-
children: LINK_TYPES.map((type) => /* @__PURE__ */
|
|
11420
|
+
children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs7(
|
|
11318
11421
|
Button,
|
|
11319
11422
|
{
|
|
11320
11423
|
variant: "ghost",
|
|
@@ -11325,11 +11428,11 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11325
11428
|
setIsLinkTypeOpen(false);
|
|
11326
11429
|
},
|
|
11327
11430
|
children: [
|
|
11328
|
-
/* @__PURE__ */
|
|
11329
|
-
/* @__PURE__ */
|
|
11431
|
+
/* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-2", children: [
|
|
11432
|
+
/* @__PURE__ */ jsx20(type.icon, { className: "size-4" }),
|
|
11330
11433
|
type.name
|
|
11331
11434
|
] }),
|
|
11332
|
-
linkType.name === type.name && /* @__PURE__ */
|
|
11435
|
+
linkType.name === type.name && /* @__PURE__ */ jsx20(CheckIcon, { className: "size-4" })
|
|
11333
11436
|
]
|
|
11334
11437
|
},
|
|
11335
11438
|
type.name
|
|
@@ -11339,11 +11442,11 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11339
11442
|
] })
|
|
11340
11443
|
] })
|
|
11341
11444
|
] }),
|
|
11342
|
-
/* @__PURE__ */
|
|
11343
|
-
/* @__PURE__ */
|
|
11344
|
-
/* @__PURE__ */
|
|
11345
|
-
/* @__PURE__ */
|
|
11346
|
-
/* @__PURE__ */
|
|
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(
|
|
11347
11450
|
Button,
|
|
11348
11451
|
{
|
|
11349
11452
|
variant: "ghost",
|
|
@@ -11351,13 +11454,13 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11351
11454
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
|
|
11352
11455
|
onClick: handleCopy,
|
|
11353
11456
|
disabled: !hasLink,
|
|
11354
|
-
children: showCopied ? /* @__PURE__ */
|
|
11457
|
+
children: showCopied ? /* @__PURE__ */ jsx20(CheckIcon, { className: "text-green-600" }) : /* @__PURE__ */ jsx20(CopyIcon, {})
|
|
11355
11458
|
}
|
|
11356
11459
|
) }),
|
|
11357
|
-
/* @__PURE__ */
|
|
11460
|
+
/* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
|
|
11358
11461
|
] }),
|
|
11359
|
-
/* @__PURE__ */
|
|
11360
|
-
/* @__PURE__ */
|
|
11462
|
+
/* @__PURE__ */ jsxs7(Tooltip, { children: [
|
|
11463
|
+
/* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(
|
|
11361
11464
|
Button,
|
|
11362
11465
|
{
|
|
11363
11466
|
variant: "ghost",
|
|
@@ -11365,13 +11468,13 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11365
11468
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
|
|
11366
11469
|
onClick: handleRemoveLink,
|
|
11367
11470
|
disabled: !hasLink,
|
|
11368
|
-
children: /* @__PURE__ */
|
|
11471
|
+
children: /* @__PURE__ */ jsx20(TrashIcon, {})
|
|
11369
11472
|
}
|
|
11370
11473
|
) }),
|
|
11371
|
-
/* @__PURE__ */
|
|
11474
|
+
/* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
|
|
11372
11475
|
] })
|
|
11373
11476
|
] }),
|
|
11374
|
-
/* @__PURE__ */
|
|
11477
|
+
/* @__PURE__ */ jsx20("div", { children: /* @__PURE__ */ jsx20(
|
|
11375
11478
|
Button,
|
|
11376
11479
|
{
|
|
11377
11480
|
variant: "default",
|
|
@@ -11388,16 +11491,16 @@ var TextLinkMenu = ({ editor }) => {
|
|
|
11388
11491
|
};
|
|
11389
11492
|
|
|
11390
11493
|
// src/core/editor/components/float-link-preview.tsx
|
|
11391
|
-
import { jsx as
|
|
11494
|
+
import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
11392
11495
|
var FloatLinkPreview = ({ href }) => {
|
|
11393
|
-
return /* @__PURE__ */
|
|
11394
|
-
/* @__PURE__ */
|
|
11395
|
-
/* @__PURE__ */
|
|
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 })
|
|
11396
11499
|
] });
|
|
11397
11500
|
};
|
|
11398
11501
|
|
|
11399
11502
|
// src/core/editor/components/tiptap-overlay.tsx
|
|
11400
|
-
import { jsx as
|
|
11503
|
+
import { jsx as jsx22, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
11401
11504
|
var FontFamily = Extension.create({
|
|
11402
11505
|
name: "fontFamily",
|
|
11403
11506
|
addGlobalAttributes() {
|
|
@@ -11575,7 +11678,8 @@ var TIPTAP_EXTENSIONS = [
|
|
|
11575
11678
|
emptyNodeClass: "is-empty-placeholder",
|
|
11576
11679
|
paragraphPlaceholder: "Start typing...",
|
|
11577
11680
|
headingPlaceholder: "Heading"
|
|
11578
|
-
})
|
|
11681
|
+
}),
|
|
11682
|
+
MergeFieldDecoration
|
|
11579
11683
|
];
|
|
11580
11684
|
function isNodeEmpty2(node) {
|
|
11581
11685
|
if (!node) return true;
|
|
@@ -11706,16 +11810,16 @@ function handleBackspaceOrDelete(view, event, currentElementIdx, storeRefs) {
|
|
|
11706
11810
|
var TiptapOverlay = () => {
|
|
11707
11811
|
const textEditing = useEditorStore((s) => s.textEditing);
|
|
11708
11812
|
if (!textEditing) return null;
|
|
11709
|
-
return /* @__PURE__ */
|
|
11813
|
+
return /* @__PURE__ */ jsx22(TiptapOverlayContent, { ...textEditing }, textEditing.idx);
|
|
11710
11814
|
};
|
|
11711
11815
|
var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWidth, initialHeight, clickX, clickY, content, styles, cursorPosition }) => {
|
|
11712
|
-
const containerRef =
|
|
11816
|
+
const containerRef = useRef5(null);
|
|
11713
11817
|
const setTiptapEditor = useEditorStore((s) => s.setTiptapEditor);
|
|
11714
11818
|
const linkColor = useEditorStore((s) => s.template?.content?.[0]?.data?.value?.linkColor) || "#0000ff";
|
|
11715
|
-
const lastSizeLimitToastRef =
|
|
11716
|
-
const hasContentChangedRef =
|
|
11819
|
+
const lastSizeLimitToastRef = useRef5(0);
|
|
11820
|
+
const hasContentChangedRef = useRef5(false);
|
|
11717
11821
|
const storeRefs = useEditorStoreRefs();
|
|
11718
|
-
|
|
11822
|
+
useEffect7(() => {
|
|
11719
11823
|
return () => {
|
|
11720
11824
|
const isUndoRedoAction = useEditorStore.getState().isUndoRedoAction;
|
|
11721
11825
|
if (hasContentChangedRef.current && !isUndoRedoAction) {
|
|
@@ -11723,7 +11827,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11723
11827
|
}
|
|
11724
11828
|
};
|
|
11725
11829
|
}, []);
|
|
11726
|
-
|
|
11830
|
+
useEffect7(() => {
|
|
11727
11831
|
const container = containerRef.current;
|
|
11728
11832
|
if (!container) return;
|
|
11729
11833
|
const observer = new ResizeObserver(() => {
|
|
@@ -11741,10 +11845,10 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11741
11845
|
}
|
|
11742
11846
|
};
|
|
11743
11847
|
}, [getShadowElement]);
|
|
11744
|
-
const cleanedContent =
|
|
11848
|
+
const cleanedContent = useMemo4(() => {
|
|
11745
11849
|
return content.replace(NBSP_P_CONTENT_REGEX, "<p$1></p>").replace(IS_EMPTY_P_CLASS_REGEX, "").replace(IS_EMPTY_HEADING_CLASS_REGEX, "");
|
|
11746
11850
|
}, [content]);
|
|
11747
|
-
const lineHeightRatio =
|
|
11851
|
+
const lineHeightRatio = useMemo4(() => {
|
|
11748
11852
|
const lineHeightPx = parseFloat(styles.lineHeight);
|
|
11749
11853
|
const fontSizePx = parseFloat(styles.fontSize);
|
|
11750
11854
|
if (isNaN(lineHeightPx) || isNaN(fontSizePx) || fontSizePx === 0) {
|
|
@@ -11752,7 +11856,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11752
11856
|
}
|
|
11753
11857
|
return lineHeightPx / fontSizePx;
|
|
11754
11858
|
}, [styles.lineHeight, styles.fontSize]);
|
|
11755
|
-
const virtualReference =
|
|
11859
|
+
const virtualReference = useMemo4(() => ({
|
|
11756
11860
|
getBoundingClientRect: () => {
|
|
11757
11861
|
const rect = getReferenceRect();
|
|
11758
11862
|
if (!rect) {
|
|
@@ -11761,14 +11865,14 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11761
11865
|
return rect;
|
|
11762
11866
|
}
|
|
11763
11867
|
}), [getReferenceRect]);
|
|
11764
|
-
const { floatingStyles, refs, update } =
|
|
11868
|
+
const { floatingStyles, refs, update } = useFloating4({
|
|
11765
11869
|
placement: "bottom-start",
|
|
11766
11870
|
middleware: [
|
|
11767
|
-
|
|
11871
|
+
offset4(({ rects }) => -rects.reference.height)
|
|
11768
11872
|
// Move up by reference height to overlay exactly
|
|
11769
11873
|
]
|
|
11770
11874
|
});
|
|
11771
|
-
|
|
11875
|
+
useEffect7(() => {
|
|
11772
11876
|
const rect = getReferenceRect();
|
|
11773
11877
|
if (!rect || !refs.floating.current) return;
|
|
11774
11878
|
refs.setPositionReference(virtualReference);
|
|
@@ -11807,17 +11911,36 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11807
11911
|
}
|
|
11808
11912
|
}
|
|
11809
11913
|
const isSlashCommandActive = storeRefs.slashCommand.current?.isActive;
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
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
|
+
}
|
|
11813
11924
|
}
|
|
11814
|
-
if (event.key === " "
|
|
11815
|
-
|
|
11816
|
-
|
|
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
|
+
}
|
|
11817
11934
|
}
|
|
11818
|
-
if (
|
|
11819
|
-
|
|
11820
|
-
|
|
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
|
+
}
|
|
11821
11944
|
}
|
|
11822
11945
|
if (event.key === "/") {
|
|
11823
11946
|
const { from } = view.state.selection;
|
|
@@ -11839,6 +11962,33 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11839
11962
|
});
|
|
11840
11963
|
}
|
|
11841
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
|
+
}
|
|
11842
11992
|
if (event.key === "Backspace" || event.key === "Delete") {
|
|
11843
11993
|
const handled = handleBackspaceOrDelete(
|
|
11844
11994
|
view,
|
|
@@ -11905,8 +12055,8 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11905
12055
|
storeRefs.updateElementContent.current(`${idx}.data.value.content`, html);
|
|
11906
12056
|
}
|
|
11907
12057
|
});
|
|
11908
|
-
const [currentLinkHref, setCurrentLinkHref] =
|
|
11909
|
-
|
|
12058
|
+
const [currentLinkHref, setCurrentLinkHref] = useState3("");
|
|
12059
|
+
useEffect7(() => {
|
|
11910
12060
|
if (!editor) return;
|
|
11911
12061
|
setTiptapEditor(editor);
|
|
11912
12062
|
const updateLinkHref = () => {
|
|
@@ -11921,7 +12071,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11921
12071
|
editor.off("transaction", updateLinkHref);
|
|
11922
12072
|
};
|
|
11923
12073
|
}, [editor, setTiptapEditor]);
|
|
11924
|
-
|
|
12074
|
+
useEffect7(() => {
|
|
11925
12075
|
if (editor) {
|
|
11926
12076
|
const timer = setTimeout(() => {
|
|
11927
12077
|
if (cursorPosition === "end") {
|
|
@@ -11950,7 +12100,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11950
12100
|
return () => clearTimeout(timer);
|
|
11951
12101
|
}
|
|
11952
12102
|
}, [editor, clickX, clickY, cursorPosition]);
|
|
11953
|
-
|
|
12103
|
+
useEffect7(() => {
|
|
11954
12104
|
const handleClickOutside = (e) => {
|
|
11955
12105
|
const target = e.target;
|
|
11956
12106
|
if (containerRef.current && containerRef.current.contains(target)) {
|
|
@@ -11972,7 +12122,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
11972
12122
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
11973
12123
|
};
|
|
11974
12124
|
}, []);
|
|
11975
|
-
return /* @__PURE__ */
|
|
12125
|
+
return /* @__PURE__ */ jsxs9(
|
|
11976
12126
|
"div",
|
|
11977
12127
|
{
|
|
11978
12128
|
ref: (node) => {
|
|
@@ -12005,7 +12155,7 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
12005
12155
|
boxSizing: "border-box"
|
|
12006
12156
|
},
|
|
12007
12157
|
children: [
|
|
12008
|
-
/* @__PURE__ */
|
|
12158
|
+
/* @__PURE__ */ jsx22("style", { children: `
|
|
12009
12159
|
.tiptap-overlay {
|
|
12010
12160
|
margin: 0;
|
|
12011
12161
|
padding: 0;
|
|
@@ -12071,6 +12221,16 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
12071
12221
|
transform: translateY(-50%);
|
|
12072
12222
|
text-align: inherit;
|
|
12073
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
|
+
}
|
|
12074
12234
|
.tiptap-overlay .ProseMirror a {
|
|
12075
12235
|
color: ${linkColor};
|
|
12076
12236
|
text-decoration: none;
|
|
@@ -12080,36 +12240,36 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
12080
12240
|
text-decoration: underline;
|
|
12081
12241
|
}
|
|
12082
12242
|
` }),
|
|
12083
|
-
/* @__PURE__ */
|
|
12243
|
+
/* @__PURE__ */ jsx22(
|
|
12084
12244
|
EditorContent,
|
|
12085
12245
|
{
|
|
12086
12246
|
editor,
|
|
12087
12247
|
className: "tiptap-overlay"
|
|
12088
12248
|
}
|
|
12089
12249
|
),
|
|
12090
|
-
editor && /* @__PURE__ */
|
|
12250
|
+
editor && /* @__PURE__ */ jsx22(
|
|
12091
12251
|
BubbleMenu,
|
|
12092
12252
|
{
|
|
12093
12253
|
editor,
|
|
12094
12254
|
options: { placement: "top", offset: 8, flip: true },
|
|
12095
12255
|
updateDelay: 0,
|
|
12096
|
-
children: /* @__PURE__ */
|
|
12097
|
-
/* @__PURE__ */
|
|
12098
|
-
/* @__PURE__ */
|
|
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(
|
|
12099
12259
|
Button,
|
|
12100
12260
|
{
|
|
12101
12261
|
variant: "ghost",
|
|
12102
12262
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
|
|
12103
12263
|
children: [
|
|
12104
|
-
/* @__PURE__ */
|
|
12105
|
-
/* @__PURE__ */
|
|
12264
|
+
/* @__PURE__ */ jsx22(BotIcon, { className: "size-4" }),
|
|
12265
|
+
/* @__PURE__ */ jsx22("p", { children: "Magic Write" })
|
|
12106
12266
|
]
|
|
12107
12267
|
}
|
|
12108
12268
|
) }),
|
|
12109
|
-
/* @__PURE__ */
|
|
12269
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", children: "Ask Maillow" })
|
|
12110
12270
|
] }),
|
|
12111
|
-
currentLinkHref && /* @__PURE__ */
|
|
12112
|
-
/* @__PURE__ */
|
|
12271
|
+
currentLinkHref && /* @__PURE__ */ jsx22(FloatLinkPreview, { href: currentLinkHref }),
|
|
12272
|
+
/* @__PURE__ */ jsx22(TextLinkMenu, { editor })
|
|
12113
12273
|
] })
|
|
12114
12274
|
}
|
|
12115
12275
|
)
|
|
@@ -12119,12 +12279,12 @@ var TiptapOverlayContent = ({ idx, getReferenceRect, getShadowElement, initialWi
|
|
|
12119
12279
|
};
|
|
12120
12280
|
|
|
12121
12281
|
// src/core/editor/components/element-float.tsx
|
|
12122
|
-
import { useEffect as
|
|
12123
|
-
import { useFloating as
|
|
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";
|
|
12124
12284
|
|
|
12125
12285
|
// src/core/editor/components/float-ui/actions/delete-button.tsx
|
|
12126
12286
|
import { TrashIcon as TrashIcon2 } from "lucide-react";
|
|
12127
|
-
import { jsx as
|
|
12287
|
+
import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
12128
12288
|
var DeleteButton = () => {
|
|
12129
12289
|
const { focusIdx, deleteElement } = useEditorStore();
|
|
12130
12290
|
const handleDelete = () => {
|
|
@@ -12132,23 +12292,23 @@ var DeleteButton = () => {
|
|
|
12132
12292
|
deleteElement(focusIdx);
|
|
12133
12293
|
}
|
|
12134
12294
|
};
|
|
12135
|
-
return /* @__PURE__ */
|
|
12136
|
-
/* @__PURE__ */
|
|
12295
|
+
return /* @__PURE__ */ jsxs10(Tooltip, { children: [
|
|
12296
|
+
/* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
|
|
12137
12297
|
Button,
|
|
12138
12298
|
{
|
|
12139
12299
|
variant: "ghost",
|
|
12140
12300
|
className: floatButtonVariants,
|
|
12141
12301
|
onClick: handleDelete,
|
|
12142
|
-
children: /* @__PURE__ */
|
|
12302
|
+
children: /* @__PURE__ */ jsx23(TrashIcon2, { className: "size-4" })
|
|
12143
12303
|
}
|
|
12144
12304
|
) }),
|
|
12145
|
-
/* @__PURE__ */
|
|
12305
|
+
/* @__PURE__ */ jsx23(TooltipContent, { side: "bottom", children: "Delete" })
|
|
12146
12306
|
] });
|
|
12147
12307
|
};
|
|
12148
12308
|
|
|
12149
12309
|
// src/core/editor/components/float-ui/actions/dulicate-button.tsx
|
|
12150
12310
|
import { CopyIcon as CopyIcon2 } from "lucide-react";
|
|
12151
|
-
import { jsx as
|
|
12311
|
+
import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
12152
12312
|
var DuplicateButton = () => {
|
|
12153
12313
|
const { focusIdx, duplicateElement } = useEditorStore();
|
|
12154
12314
|
const isAtSizeLimit = useEditorStore((state) => state.isAtSizeLimit);
|
|
@@ -12157,42 +12317,42 @@ var DuplicateButton = () => {
|
|
|
12157
12317
|
duplicateElement(focusIdx);
|
|
12158
12318
|
}
|
|
12159
12319
|
};
|
|
12160
|
-
return /* @__PURE__ */
|
|
12161
|
-
/* @__PURE__ */
|
|
12320
|
+
return /* @__PURE__ */ jsxs11(Tooltip, { children: [
|
|
12321
|
+
/* @__PURE__ */ jsx24(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx24(
|
|
12162
12322
|
Button,
|
|
12163
12323
|
{
|
|
12164
12324
|
variant: "ghost",
|
|
12165
12325
|
className: floatButtonVariants,
|
|
12166
12326
|
onClick: handleDuplicate,
|
|
12167
12327
|
disabled: isAtSizeLimit,
|
|
12168
|
-
children: /* @__PURE__ */
|
|
12328
|
+
children: /* @__PURE__ */ jsx24(CopyIcon2, { className: "size-4" })
|
|
12169
12329
|
}
|
|
12170
12330
|
) }),
|
|
12171
|
-
/* @__PURE__ */
|
|
12331
|
+
/* @__PURE__ */ jsx24(TooltipContent, { side: "bottom", children: "Duplicate" })
|
|
12172
12332
|
] });
|
|
12173
12333
|
};
|
|
12174
12334
|
|
|
12175
12335
|
// src/core/editor/components/href-menu.tsx
|
|
12176
|
-
import { useState as
|
|
12336
|
+
import { useState as useState4, useEffect as useEffect8, useCallback as useCallback5, useMemo as useMemo6 } from "react";
|
|
12177
12337
|
|
|
12178
12338
|
// src/components/ui/dropdown-menu.tsx
|
|
12179
12339
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
12180
12340
|
import { CheckIcon as CheckIcon2, ChevronRightIcon, CircleIcon } from "lucide-react";
|
|
12181
|
-
import { jsx as
|
|
12341
|
+
import { jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
12182
12342
|
function DropdownMenu({
|
|
12183
12343
|
...props
|
|
12184
12344
|
}) {
|
|
12185
|
-
return /* @__PURE__ */
|
|
12345
|
+
return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
12186
12346
|
}
|
|
12187
12347
|
function DropdownMenuPortal({
|
|
12188
12348
|
...props
|
|
12189
12349
|
}) {
|
|
12190
|
-
return /* @__PURE__ */
|
|
12350
|
+
return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
|
|
12191
12351
|
}
|
|
12192
12352
|
function DropdownMenuTrigger({
|
|
12193
12353
|
...props
|
|
12194
12354
|
}) {
|
|
12195
|
-
return /* @__PURE__ */
|
|
12355
|
+
return /* @__PURE__ */ jsx25(
|
|
12196
12356
|
DropdownMenuPrimitive.Trigger,
|
|
12197
12357
|
{
|
|
12198
12358
|
"data-slot": "dropdown-menu-trigger",
|
|
@@ -12205,7 +12365,7 @@ function DropdownMenuContent({
|
|
|
12205
12365
|
sideOffset = 4,
|
|
12206
12366
|
...props
|
|
12207
12367
|
}) {
|
|
12208
|
-
return /* @__PURE__ */
|
|
12368
|
+
return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx25(
|
|
12209
12369
|
DropdownMenuPrimitive.Content,
|
|
12210
12370
|
{
|
|
12211
12371
|
"data-slot": "dropdown-menu-content",
|
|
@@ -12224,7 +12384,7 @@ function DropdownMenuItem({
|
|
|
12224
12384
|
variant = "default",
|
|
12225
12385
|
...props
|
|
12226
12386
|
}) {
|
|
12227
|
-
return /* @__PURE__ */
|
|
12387
|
+
return /* @__PURE__ */ jsx25(
|
|
12228
12388
|
DropdownMenuPrimitive.Item,
|
|
12229
12389
|
{
|
|
12230
12390
|
"data-slot": "dropdown-menu-item",
|
|
@@ -12242,7 +12402,7 @@ function DropdownMenuSeparator({
|
|
|
12242
12402
|
className,
|
|
12243
12403
|
...props
|
|
12244
12404
|
}) {
|
|
12245
|
-
return /* @__PURE__ */
|
|
12405
|
+
return /* @__PURE__ */ jsx25(
|
|
12246
12406
|
DropdownMenuPrimitive.Separator,
|
|
12247
12407
|
{
|
|
12248
12408
|
"data-slot": "dropdown-menu-separator",
|
|
@@ -12254,7 +12414,7 @@ function DropdownMenuSeparator({
|
|
|
12254
12414
|
function DropdownMenuSub({
|
|
12255
12415
|
...props
|
|
12256
12416
|
}) {
|
|
12257
|
-
return /* @__PURE__ */
|
|
12417
|
+
return /* @__PURE__ */ jsx25(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
|
|
12258
12418
|
}
|
|
12259
12419
|
function DropdownMenuSubTrigger({
|
|
12260
12420
|
className,
|
|
@@ -12262,7 +12422,7 @@ function DropdownMenuSubTrigger({
|
|
|
12262
12422
|
children,
|
|
12263
12423
|
...props
|
|
12264
12424
|
}) {
|
|
12265
|
-
return /* @__PURE__ */
|
|
12425
|
+
return /* @__PURE__ */ jsxs12(
|
|
12266
12426
|
DropdownMenuPrimitive.SubTrigger,
|
|
12267
12427
|
{
|
|
12268
12428
|
"data-slot": "dropdown-menu-sub-trigger",
|
|
@@ -12274,7 +12434,7 @@ function DropdownMenuSubTrigger({
|
|
|
12274
12434
|
...props,
|
|
12275
12435
|
children: [
|
|
12276
12436
|
children,
|
|
12277
|
-
/* @__PURE__ */
|
|
12437
|
+
/* @__PURE__ */ jsx25(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
12278
12438
|
]
|
|
12279
12439
|
}
|
|
12280
12440
|
);
|
|
@@ -12283,7 +12443,7 @@ function DropdownMenuSubContent({
|
|
|
12283
12443
|
className,
|
|
12284
12444
|
...props
|
|
12285
12445
|
}) {
|
|
12286
|
-
return /* @__PURE__ */
|
|
12446
|
+
return /* @__PURE__ */ jsx25(
|
|
12287
12447
|
DropdownMenuPrimitive.SubContent,
|
|
12288
12448
|
{
|
|
12289
12449
|
"data-slot": "dropdown-menu-sub-content",
|
|
@@ -12300,11 +12460,11 @@ function DropdownMenuSubContent({
|
|
|
12300
12460
|
import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon3, LinkIcon as LinkIcon3, PencilIcon as PencilIcon2, TrashIcon as TrashIcon3 } from "lucide-react";
|
|
12301
12461
|
|
|
12302
12462
|
// src/core/editor/hooks/use-href.ts
|
|
12303
|
-
import { useMemo as
|
|
12463
|
+
import { useMemo as useMemo5, useCallback as useCallback4 } from "react";
|
|
12304
12464
|
import { get as lodashGet2 } from "lodash";
|
|
12305
12465
|
var useHref = () => {
|
|
12306
12466
|
const { focusIdx, updateElement, template } = useEditorStore();
|
|
12307
|
-
const { element, href } =
|
|
12467
|
+
const { element, href } = useMemo5(() => {
|
|
12308
12468
|
if (!focusIdx || !template) {
|
|
12309
12469
|
return { element: null, href: "" };
|
|
12310
12470
|
}
|
|
@@ -12315,19 +12475,19 @@ var useHref = () => {
|
|
|
12315
12475
|
href: el?.attributes?.href || ""
|
|
12316
12476
|
};
|
|
12317
12477
|
}, [focusIdx, template]);
|
|
12318
|
-
const setHref =
|
|
12478
|
+
const setHref = useCallback4((url) => {
|
|
12319
12479
|
if (!focusIdx || !element) return;
|
|
12320
12480
|
updateElement(focusIdx, {
|
|
12321
12481
|
attributes: { ...element.attributes, href: url }
|
|
12322
12482
|
});
|
|
12323
12483
|
}, [focusIdx, element, updateElement]);
|
|
12324
|
-
const clearHref =
|
|
12484
|
+
const clearHref = useCallback4(() => {
|
|
12325
12485
|
if (!focusIdx || !element) return;
|
|
12326
12486
|
updateElement(focusIdx, {
|
|
12327
12487
|
attributes: { ...element.attributes, href: "" }
|
|
12328
12488
|
});
|
|
12329
12489
|
}, [focusIdx, element, updateElement]);
|
|
12330
|
-
const copyHref =
|
|
12490
|
+
const copyHref = useCallback4(async () => {
|
|
12331
12491
|
if (href) {
|
|
12332
12492
|
try {
|
|
12333
12493
|
await navigator.clipboard.writeText(href);
|
|
@@ -12347,18 +12507,18 @@ var useHref = () => {
|
|
|
12347
12507
|
};
|
|
12348
12508
|
|
|
12349
12509
|
// src/core/editor/components/href-menu.tsx
|
|
12350
|
-
import { jsx as
|
|
12510
|
+
import { jsx as jsx26, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
12351
12511
|
var HrefMenu = () => {
|
|
12352
12512
|
const { href, setHref, clearHref, copyHref, hasHref } = useHref();
|
|
12353
12513
|
const userData = useEditorStore((s) => s.userData);
|
|
12354
|
-
const [isOpen, setIsOpen] =
|
|
12355
|
-
const [inputValue, setInputValue] =
|
|
12356
|
-
const [showCopied, setShowCopied] =
|
|
12357
|
-
const [linkType, setLinkType] =
|
|
12358
|
-
const [isLinkTypeOpen, setIsLinkTypeOpen] =
|
|
12359
|
-
const [isPresetOpen, setIsPresetOpen] =
|
|
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);
|
|
12360
12520
|
console.log("userData", userData);
|
|
12361
|
-
const availablePresets =
|
|
12521
|
+
const availablePresets = useMemo6(() => {
|
|
12362
12522
|
const presetDefs = LINK_PRESETS[linkType.name] ?? [];
|
|
12363
12523
|
if (!userData) return [];
|
|
12364
12524
|
const all = presetDefs.filter((p) => userData[p.key]).map((p) => ({ ...p, value: String(userData[p.key]) }));
|
|
@@ -12366,11 +12526,11 @@ var HrefMenu = () => {
|
|
|
12366
12526
|
const query = inputValue.toLowerCase();
|
|
12367
12527
|
return all.filter((p) => p.value.toLowerCase().includes(query));
|
|
12368
12528
|
}, [linkType.name, userData, inputValue]);
|
|
12369
|
-
const handlePresetSelect =
|
|
12529
|
+
const handlePresetSelect = useCallback5((value) => {
|
|
12370
12530
|
setInputValue(value);
|
|
12371
12531
|
setIsPresetOpen(false);
|
|
12372
12532
|
}, []);
|
|
12373
|
-
|
|
12533
|
+
useEffect8(() => {
|
|
12374
12534
|
if (isOpen) {
|
|
12375
12535
|
setLinkType(detectLinkType(href));
|
|
12376
12536
|
setInputValue(stripPrefix(href));
|
|
@@ -12421,35 +12581,35 @@ var HrefMenu = () => {
|
|
|
12421
12581
|
setHref(buildHref(inputValue));
|
|
12422
12582
|
setIsOpen(false);
|
|
12423
12583
|
};
|
|
12424
|
-
return /* @__PURE__ */
|
|
12425
|
-
/* @__PURE__ */
|
|
12426
|
-
/* @__PURE__ */
|
|
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(
|
|
12427
12587
|
Button,
|
|
12428
12588
|
{
|
|
12429
12589
|
variant: "ghost",
|
|
12430
12590
|
size: "icon",
|
|
12431
12591
|
className: floatButtonVariants,
|
|
12432
|
-
children: /* @__PURE__ */
|
|
12592
|
+
children: /* @__PURE__ */ jsx26(PencilIcon2, { className: "size-4" })
|
|
12433
12593
|
}
|
|
12434
|
-
) : /* @__PURE__ */
|
|
12594
|
+
) : /* @__PURE__ */ jsxs13(
|
|
12435
12595
|
Button,
|
|
12436
12596
|
{
|
|
12437
12597
|
variant: "ghost",
|
|
12438
12598
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
|
|
12439
12599
|
children: [
|
|
12440
|
-
/* @__PURE__ */
|
|
12441
|
-
/* @__PURE__ */
|
|
12600
|
+
/* @__PURE__ */ jsx26(LinkIcon3, { className: "size-4" }),
|
|
12601
|
+
/* @__PURE__ */ jsx26("p", { children: "Add link" })
|
|
12442
12602
|
]
|
|
12443
12603
|
}
|
|
12444
12604
|
) }) }),
|
|
12445
|
-
/* @__PURE__ */
|
|
12605
|
+
/* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", children: hasHref ? `Edit link` : "Add link" })
|
|
12446
12606
|
] }),
|
|
12447
|
-
/* @__PURE__ */
|
|
12448
|
-
/* @__PURE__ */
|
|
12449
|
-
/* @__PURE__ */
|
|
12450
|
-
/* @__PURE__ */
|
|
12451
|
-
/* @__PURE__ */
|
|
12452
|
-
/* @__PURE__ */
|
|
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(
|
|
12453
12613
|
Input,
|
|
12454
12614
|
{
|
|
12455
12615
|
type: linkType.inputType,
|
|
@@ -12463,19 +12623,19 @@ var HrefMenu = () => {
|
|
|
12463
12623
|
autoFocus: true
|
|
12464
12624
|
}
|
|
12465
12625
|
),
|
|
12466
|
-
/* @__PURE__ */
|
|
12467
|
-
/* @__PURE__ */
|
|
12468
|
-
/* @__PURE__ */
|
|
12469
|
-
/* @__PURE__ */
|
|
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" })
|
|
12470
12630
|
] }),
|
|
12471
|
-
/* @__PURE__ */
|
|
12631
|
+
/* @__PURE__ */ jsx26(
|
|
12472
12632
|
PopoverContent,
|
|
12473
12633
|
{
|
|
12474
12634
|
side: "bottom",
|
|
12475
12635
|
align: "start",
|
|
12476
12636
|
className: "w-[160px] p-1 z-50001",
|
|
12477
12637
|
onPointerDownOutside: (e) => e.preventDefault(),
|
|
12478
|
-
children: LINK_TYPES.map((type) => /* @__PURE__ */
|
|
12638
|
+
children: LINK_TYPES.map((type) => /* @__PURE__ */ jsxs13(
|
|
12479
12639
|
Button,
|
|
12480
12640
|
{
|
|
12481
12641
|
variant: "ghost",
|
|
@@ -12486,11 +12646,11 @@ var HrefMenu = () => {
|
|
|
12486
12646
|
setIsLinkTypeOpen(false);
|
|
12487
12647
|
},
|
|
12488
12648
|
children: [
|
|
12489
|
-
/* @__PURE__ */
|
|
12490
|
-
/* @__PURE__ */
|
|
12649
|
+
/* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-2", children: [
|
|
12650
|
+
/* @__PURE__ */ jsx26(type.icon, { className: "size-4" }),
|
|
12491
12651
|
type.name
|
|
12492
12652
|
] }),
|
|
12493
|
-
linkType.name === type.name && /* @__PURE__ */
|
|
12653
|
+
linkType.name === type.name && /* @__PURE__ */ jsx26(CheckIcon3, { className: "size-4" })
|
|
12494
12654
|
]
|
|
12495
12655
|
},
|
|
12496
12656
|
type.name
|
|
@@ -12499,14 +12659,14 @@ var HrefMenu = () => {
|
|
|
12499
12659
|
)
|
|
12500
12660
|
] })
|
|
12501
12661
|
] }) }),
|
|
12502
|
-
/* @__PURE__ */
|
|
12662
|
+
/* @__PURE__ */ jsx26(
|
|
12503
12663
|
PopoverContent,
|
|
12504
12664
|
{
|
|
12505
12665
|
side: "bottom",
|
|
12506
12666
|
align: "start",
|
|
12507
12667
|
className: "w-[var(--radix-popover-trigger-width)] p-0 overflow-hidden z-50001",
|
|
12508
12668
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
12509
|
-
children: /* @__PURE__ */
|
|
12669
|
+
children: /* @__PURE__ */ jsx26("div", { className: "flex flex-col max-h-[200px] overflow-y-auto", children: availablePresets.map((preset) => /* @__PURE__ */ jsxs13(
|
|
12510
12670
|
"button",
|
|
12511
12671
|
{
|
|
12512
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" : ""}`,
|
|
@@ -12515,11 +12675,11 @@ var HrefMenu = () => {
|
|
|
12515
12675
|
handlePresetSelect(preset.value);
|
|
12516
12676
|
},
|
|
12517
12677
|
children: [
|
|
12518
|
-
/* @__PURE__ */
|
|
12519
|
-
/* @__PURE__ */
|
|
12520
|
-
/* @__PURE__ */
|
|
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 })
|
|
12521
12681
|
] }),
|
|
12522
|
-
inputValue === preset.value && /* @__PURE__ */
|
|
12682
|
+
inputValue === preset.value && /* @__PURE__ */ jsx26(CheckIcon3, { className: "w-4 h-4 shrink-0" })
|
|
12523
12683
|
]
|
|
12524
12684
|
},
|
|
12525
12685
|
preset.key
|
|
@@ -12528,11 +12688,11 @@ var HrefMenu = () => {
|
|
|
12528
12688
|
)
|
|
12529
12689
|
] })
|
|
12530
12690
|
] }),
|
|
12531
|
-
/* @__PURE__ */
|
|
12532
|
-
/* @__PURE__ */
|
|
12533
|
-
/* @__PURE__ */
|
|
12534
|
-
/* @__PURE__ */
|
|
12535
|
-
/* @__PURE__ */
|
|
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(
|
|
12536
12696
|
Button,
|
|
12537
12697
|
{
|
|
12538
12698
|
variant: "ghost",
|
|
@@ -12540,13 +12700,13 @@ var HrefMenu = () => {
|
|
|
12540
12700
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
|
|
12541
12701
|
onClick: handleCopy,
|
|
12542
12702
|
disabled: !hasHref,
|
|
12543
|
-
children: showCopied ? /* @__PURE__ */
|
|
12703
|
+
children: showCopied ? /* @__PURE__ */ jsx26(CheckIcon3, { className: "text-green-600" }) : /* @__PURE__ */ jsx26(CopyIcon3, {})
|
|
12544
12704
|
}
|
|
12545
12705
|
) }),
|
|
12546
|
-
/* @__PURE__ */
|
|
12706
|
+
/* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
|
|
12547
12707
|
] }),
|
|
12548
|
-
/* @__PURE__ */
|
|
12549
|
-
/* @__PURE__ */
|
|
12708
|
+
/* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
12709
|
+
/* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
|
|
12550
12710
|
Button,
|
|
12551
12711
|
{
|
|
12552
12712
|
variant: "ghost",
|
|
@@ -12554,13 +12714,13 @@ var HrefMenu = () => {
|
|
|
12554
12714
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
|
|
12555
12715
|
onClick: handleClear,
|
|
12556
12716
|
disabled: !href,
|
|
12557
|
-
children: /* @__PURE__ */
|
|
12717
|
+
children: /* @__PURE__ */ jsx26(TrashIcon3, {})
|
|
12558
12718
|
}
|
|
12559
12719
|
) }),
|
|
12560
|
-
/* @__PURE__ */
|
|
12720
|
+
/* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", className: "z-50001", children: "Remove link" })
|
|
12561
12721
|
] })
|
|
12562
12722
|
] }),
|
|
12563
|
-
/* @__PURE__ */
|
|
12723
|
+
/* @__PURE__ */ jsx26("div", { children: /* @__PURE__ */ jsx26(
|
|
12564
12724
|
Button,
|
|
12565
12725
|
{
|
|
12566
12726
|
variant: "default",
|
|
@@ -12575,14 +12735,14 @@ var HrefMenu = () => {
|
|
|
12575
12735
|
};
|
|
12576
12736
|
|
|
12577
12737
|
// src/core/editor/components/element-gear/button/float.tsx
|
|
12578
|
-
import { Fragment as Fragment6, jsx as
|
|
12738
|
+
import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
12579
12739
|
var ButtonFloat = () => {
|
|
12580
12740
|
const { href, hasHref } = useHref();
|
|
12581
|
-
return /* @__PURE__ */
|
|
12582
|
-
hasHref && /* @__PURE__ */
|
|
12583
|
-
/* @__PURE__ */
|
|
12584
|
-
/* @__PURE__ */
|
|
12585
|
-
/* @__PURE__ */
|
|
12741
|
+
return /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
12742
|
+
hasHref && /* @__PURE__ */ jsx27(FloatLinkPreview, { href }),
|
|
12743
|
+
/* @__PURE__ */ jsx27(HrefMenu, {}),
|
|
12744
|
+
/* @__PURE__ */ jsx27(DuplicateButton, {}),
|
|
12745
|
+
/* @__PURE__ */ jsx27(DeleteButton, {})
|
|
12586
12746
|
] });
|
|
12587
12747
|
};
|
|
12588
12748
|
|
|
@@ -12590,11 +12750,11 @@ var ButtonFloat = () => {
|
|
|
12590
12750
|
import { ChevronsLeftRightIcon, ChevronsRightLeftIcon, MoreHorizontalIcon } from "lucide-react";
|
|
12591
12751
|
|
|
12592
12752
|
// src/core/editor/hooks/use-full-width-toggle.ts
|
|
12593
|
-
import { useCallback as
|
|
12753
|
+
import { useCallback as useCallback6, useMemo as useMemo7 } from "react";
|
|
12594
12754
|
import { get as lodashGet3 } from "lodash";
|
|
12595
12755
|
function useFullWidthToggle() {
|
|
12596
12756
|
const { focusIdx, template, updateElement } = useEditorStore();
|
|
12597
|
-
const { element, isFullWidth } =
|
|
12757
|
+
const { element, isFullWidth } = useMemo7(() => {
|
|
12598
12758
|
if (!focusIdx || !template) return { element: null, isFullWidth: false };
|
|
12599
12759
|
const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
|
|
12600
12760
|
const el = lodashGet3(template, path);
|
|
@@ -12603,7 +12763,7 @@ function useFullWidthToggle() {
|
|
|
12603
12763
|
isFullWidth: el?.attributes?.["full-width"] === "full-width"
|
|
12604
12764
|
};
|
|
12605
12765
|
}, [focusIdx, template]);
|
|
12606
|
-
const handleToggleFullWidth =
|
|
12766
|
+
const handleToggleFullWidth = useCallback6(() => {
|
|
12607
12767
|
if (!focusIdx || !element) return;
|
|
12608
12768
|
const newAttributes = { ...element.attributes };
|
|
12609
12769
|
if (isFullWidth) {
|
|
@@ -12617,20 +12777,20 @@ function useFullWidthToggle() {
|
|
|
12617
12777
|
}
|
|
12618
12778
|
|
|
12619
12779
|
// src/core/editor/components/element-gear/section/float.tsx
|
|
12620
|
-
import { Fragment as Fragment7, jsx as
|
|
12780
|
+
import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
12621
12781
|
var SectionFloat = () => {
|
|
12622
12782
|
const { isFullWidth, handleToggleFullWidth } = useFullWidthToggle();
|
|
12623
|
-
return /* @__PURE__ */
|
|
12624
|
-
/* @__PURE__ */
|
|
12625
|
-
/* @__PURE__ */
|
|
12626
|
-
/* @__PURE__ */
|
|
12627
|
-
/* @__PURE__ */
|
|
12628
|
-
/* @__PURE__ */
|
|
12629
|
-
/* @__PURE__ */
|
|
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" })
|
|
12630
12790
|
] }),
|
|
12631
|
-
/* @__PURE__ */
|
|
12632
|
-
isFullWidth ? /* @__PURE__ */
|
|
12633
|
-
/* @__PURE__ */
|
|
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" })
|
|
12634
12794
|
] }) })
|
|
12635
12795
|
] })
|
|
12636
12796
|
] });
|
|
@@ -12640,11 +12800,11 @@ var SectionFloat = () => {
|
|
|
12640
12800
|
import { CheckIcon as CheckIcon4, ChevronsLeftRightIcon as ChevronsLeftRightIcon2, ChevronsRightLeftIcon as ChevronsRightLeftIcon2, Layers2Icon, MoreHorizontalIcon as MoreHorizontalIcon2 } from "lucide-react";
|
|
12641
12801
|
|
|
12642
12802
|
// src/core/editor/hooks/use-no-wrap.ts
|
|
12643
|
-
import { useCallback as
|
|
12803
|
+
import { useCallback as useCallback7, useMemo as useMemo8 } from "react";
|
|
12644
12804
|
import { get as lodashGet4 } from "lodash";
|
|
12645
12805
|
function useNoWrap() {
|
|
12646
12806
|
const { focusIdx, template, updateElement } = useEditorStore();
|
|
12647
|
-
const { element, noWrap } =
|
|
12807
|
+
const { element, noWrap } = useMemo8(() => {
|
|
12648
12808
|
if (!focusIdx || !template) return { element: null, noWrap: false };
|
|
12649
12809
|
const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
|
|
12650
12810
|
const el = lodashGet4(template, path);
|
|
@@ -12653,7 +12813,7 @@ function useNoWrap() {
|
|
|
12653
12813
|
noWrap: el?.data?.value?.noWrap === true
|
|
12654
12814
|
};
|
|
12655
12815
|
}, [focusIdx, template]);
|
|
12656
|
-
const handleToggleNoWrap =
|
|
12816
|
+
const handleToggleNoWrap = useCallback7(() => {
|
|
12657
12817
|
if (!focusIdx || !element) return;
|
|
12658
12818
|
updateElement(focusIdx, {
|
|
12659
12819
|
data: {
|
|
@@ -12668,30 +12828,30 @@ function useNoWrap() {
|
|
|
12668
12828
|
}
|
|
12669
12829
|
|
|
12670
12830
|
// src/core/editor/components/element-gear/section-column/float.tsx
|
|
12671
|
-
import { Fragment as Fragment8, jsx as
|
|
12831
|
+
import { Fragment as Fragment8, jsx as jsx29, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
12672
12832
|
var SectionColumnFloat = () => {
|
|
12673
12833
|
const { isFullWidth, handleToggleFullWidth } = useFullWidthToggle();
|
|
12674
12834
|
const { noWrap, handleToggleNoWrap } = useNoWrap();
|
|
12675
|
-
return /* @__PURE__ */
|
|
12676
|
-
/* @__PURE__ */
|
|
12677
|
-
/* @__PURE__ */
|
|
12678
|
-
/* @__PURE__ */
|
|
12679
|
-
/* @__PURE__ */
|
|
12680
|
-
/* @__PURE__ */
|
|
12681
|
-
/* @__PURE__ */
|
|
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" })
|
|
12682
12842
|
] }),
|
|
12683
|
-
/* @__PURE__ */
|
|
12684
|
-
/* @__PURE__ */
|
|
12685
|
-
/* @__PURE__ */
|
|
12686
|
-
/* @__PURE__ */
|
|
12687
|
-
/* @__PURE__ */
|
|
12688
|
-
!noWrap && /* @__PURE__ */
|
|
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" })
|
|
12689
12849
|
] })
|
|
12690
12850
|
] }),
|
|
12691
|
-
/* @__PURE__ */
|
|
12692
|
-
/* @__PURE__ */
|
|
12693
|
-
isFullWidth ? /* @__PURE__ */
|
|
12694
|
-
/* @__PURE__ */
|
|
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" })
|
|
12695
12855
|
] })
|
|
12696
12856
|
] })
|
|
12697
12857
|
] })
|
|
@@ -12699,11 +12859,11 @@ var SectionColumnFloat = () => {
|
|
|
12699
12859
|
};
|
|
12700
12860
|
|
|
12701
12861
|
// src/core/editor/components/element-gear/spacer/float.tsx
|
|
12702
|
-
import { Fragment as Fragment9, jsx as
|
|
12862
|
+
import { Fragment as Fragment9, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
12703
12863
|
var SpacerFloat = () => {
|
|
12704
|
-
return /* @__PURE__ */
|
|
12705
|
-
/* @__PURE__ */
|
|
12706
|
-
/* @__PURE__ */
|
|
12864
|
+
return /* @__PURE__ */ jsxs17(Fragment9, { children: [
|
|
12865
|
+
/* @__PURE__ */ jsx30(DuplicateButton, {}),
|
|
12866
|
+
/* @__PURE__ */ jsx30(DeleteButton, {})
|
|
12707
12867
|
] });
|
|
12708
12868
|
};
|
|
12709
12869
|
|
|
@@ -12711,16 +12871,16 @@ var SpacerFloat = () => {
|
|
|
12711
12871
|
import { MoreHorizontalIcon as MoreHorizontalIcon3, PlusCircleIcon } from "lucide-react";
|
|
12712
12872
|
|
|
12713
12873
|
// src/core/editor/components/email-template-v2/context/sidebar-context.tsx
|
|
12714
|
-
import { createContext, useContext, useState as
|
|
12715
|
-
import { jsx as
|
|
12874
|
+
import { createContext, useContext, useState as useState5 } from "react";
|
|
12875
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
12716
12876
|
var SidebarContext = createContext(null);
|
|
12717
12877
|
var PICKER_VIEWS = ["color", "images", "add-social"];
|
|
12718
12878
|
function SidebarProvider({ children }) {
|
|
12719
|
-
const [activeView, setActiveViewState] =
|
|
12720
|
-
const [lastView, setLastView] =
|
|
12721
|
-
const [colorType, setColorType] =
|
|
12722
|
-
const [colorTarget, setColorTarget] =
|
|
12723
|
-
const [imageTarget, setImageTarget] =
|
|
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);
|
|
12724
12884
|
const setActiveView = (view) => {
|
|
12725
12885
|
if (view !== activeView) {
|
|
12726
12886
|
if (!PICKER_VIEWS.includes(activeView)) {
|
|
@@ -12729,7 +12889,7 @@ function SidebarProvider({ children }) {
|
|
|
12729
12889
|
}
|
|
12730
12890
|
setActiveViewState(view);
|
|
12731
12891
|
};
|
|
12732
|
-
return /* @__PURE__ */
|
|
12892
|
+
return /* @__PURE__ */ jsx31(SidebarContext.Provider, { value: { activeView, setActiveView, lastView, colorType, setColorType, colorTarget, setColorTarget, imageTarget, setImageTarget }, children });
|
|
12733
12893
|
}
|
|
12734
12894
|
function useSidebarContext() {
|
|
12735
12895
|
const context = useContext(SidebarContext);
|
|
@@ -12740,33 +12900,33 @@ function useSidebarContext() {
|
|
|
12740
12900
|
}
|
|
12741
12901
|
|
|
12742
12902
|
// src/core/editor/components/element-gear/social/float.tsx
|
|
12743
|
-
import { Fragment as Fragment10, jsx as
|
|
12903
|
+
import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
12744
12904
|
var SocialFloat = () => {
|
|
12745
12905
|
const { setActiveView } = useSidebarContext();
|
|
12746
|
-
return /* @__PURE__ */
|
|
12747
|
-
/* @__PURE__ */
|
|
12748
|
-
/* @__PURE__ */
|
|
12749
|
-
/* @__PURE__ */
|
|
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" })
|
|
12750
12910
|
] }),
|
|
12751
|
-
/* @__PURE__ */
|
|
12752
|
-
/* @__PURE__ */
|
|
12753
|
-
/* @__PURE__ */
|
|
12754
|
-
/* @__PURE__ */
|
|
12755
|
-
/* @__PURE__ */
|
|
12756
|
-
/* @__PURE__ */
|
|
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" })
|
|
12757
12917
|
] }),
|
|
12758
|
-
/* @__PURE__ */
|
|
12759
|
-
/* @__PURE__ */
|
|
12760
|
-
/* @__PURE__ */
|
|
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" })
|
|
12761
12921
|
] }) })
|
|
12762
12922
|
] })
|
|
12763
12923
|
] });
|
|
12764
12924
|
};
|
|
12765
12925
|
|
|
12766
12926
|
// src/components/ui/textarea.tsx
|
|
12767
|
-
import { jsx as
|
|
12927
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
12768
12928
|
function Textarea({ className, ...props }) {
|
|
12769
|
-
return /* @__PURE__ */
|
|
12929
|
+
return /* @__PURE__ */ jsx33(
|
|
12770
12930
|
"textarea",
|
|
12771
12931
|
{
|
|
12772
12932
|
"data-slot": "textarea",
|
|
@@ -12781,38 +12941,38 @@ function Textarea({ className, ...props }) {
|
|
|
12781
12941
|
|
|
12782
12942
|
// src/core/editor/components/element-gear/social-item/float.tsx
|
|
12783
12943
|
import { Accessibility, MoreHorizontalIcon as MoreHorizontalIcon4, TrashIcon as TrashIcon4 } from "lucide-react";
|
|
12784
|
-
import { useState as
|
|
12944
|
+
import { useState as useState7, useEffect as useEffect10 } from "react";
|
|
12785
12945
|
|
|
12786
12946
|
// src/core/editor/components/social-item-menu.tsx
|
|
12787
|
-
import { useState as
|
|
12947
|
+
import { useState as useState6, useEffect as useEffect9, useMemo as useMemo9, useCallback as useCallback8 } from "react";
|
|
12788
12948
|
import { PencilIcon as PencilIcon3, CheckIcon as CheckIcon5, CopyIcon as CopyIcon4 } from "lucide-react";
|
|
12789
12949
|
import { get as lodashGet5 } from "lodash";
|
|
12790
|
-
import { jsx as
|
|
12950
|
+
import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
12791
12951
|
var SocialItemMenu = ({ hasHref }) => {
|
|
12792
|
-
const [isOpen, setIsOpen] =
|
|
12793
|
-
const [showCopied, setShowCopied] =
|
|
12794
|
-
const [hrefInputValue, setHrefInputValue] =
|
|
12795
|
-
const [contentInputValue, setContentInputValue] =
|
|
12952
|
+
const [isOpen, setIsOpen] = useState6(false);
|
|
12953
|
+
const [showCopied, setShowCopied] = useState6(false);
|
|
12954
|
+
const [hrefInputValue, setHrefInputValue] = useState6("");
|
|
12955
|
+
const [contentInputValue, setContentInputValue] = useState6("");
|
|
12796
12956
|
const { href, setHref, copyHref } = useHref();
|
|
12797
12957
|
const { focusIdx, template, updateElement } = useEditorStore();
|
|
12798
|
-
const element =
|
|
12958
|
+
const element = useMemo9(() => {
|
|
12799
12959
|
if (!focusIdx || !template) return null;
|
|
12800
12960
|
const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.?\[(\d+)\]/g, "[$1]") : focusIdx;
|
|
12801
12961
|
return lodashGet5(template, path);
|
|
12802
12962
|
}, [focusIdx, template]);
|
|
12803
12963
|
const content = element?.data?.value?.content || "";
|
|
12804
|
-
|
|
12964
|
+
useEffect9(() => {
|
|
12805
12965
|
if (isOpen) {
|
|
12806
12966
|
setHrefInputValue(href);
|
|
12807
12967
|
setContentInputValue(content);
|
|
12808
12968
|
}
|
|
12809
12969
|
}, [isOpen, href, content]);
|
|
12810
|
-
const handleCopy =
|
|
12970
|
+
const handleCopy = useCallback8(async () => {
|
|
12811
12971
|
await copyHref();
|
|
12812
12972
|
setShowCopied(true);
|
|
12813
12973
|
setTimeout(() => setShowCopied(false), 2e3);
|
|
12814
12974
|
}, [copyHref]);
|
|
12815
|
-
const handleDone =
|
|
12975
|
+
const handleDone = useCallback8(() => {
|
|
12816
12976
|
setHref(normalizeWebsiteUrl(hrefInputValue));
|
|
12817
12977
|
if (focusIdx && element) {
|
|
12818
12978
|
updateElement(focusIdx, {
|
|
@@ -12826,33 +12986,33 @@ var SocialItemMenu = ({ hasHref }) => {
|
|
|
12826
12986
|
}
|
|
12827
12987
|
setIsOpen(false);
|
|
12828
12988
|
}, [hrefInputValue, contentInputValue, setHref, focusIdx, element, updateElement]);
|
|
12829
|
-
return /* @__PURE__ */
|
|
12830
|
-
/* @__PURE__ */
|
|
12831
|
-
/* @__PURE__ */
|
|
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(
|
|
12832
12992
|
Button,
|
|
12833
12993
|
{
|
|
12834
12994
|
variant: "ghost",
|
|
12835
12995
|
size: "icon",
|
|
12836
12996
|
className: floatButtonVariants,
|
|
12837
|
-
children: /* @__PURE__ */
|
|
12997
|
+
children: /* @__PURE__ */ jsx34(PencilIcon3, { className: "size-4" })
|
|
12838
12998
|
}
|
|
12839
|
-
) : /* @__PURE__ */
|
|
12999
|
+
) : /* @__PURE__ */ jsxs19(
|
|
12840
13000
|
Button,
|
|
12841
13001
|
{
|
|
12842
13002
|
variant: "ghost",
|
|
12843
13003
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
|
|
12844
13004
|
children: [
|
|
12845
|
-
/* @__PURE__ */
|
|
12846
|
-
/* @__PURE__ */
|
|
13005
|
+
/* @__PURE__ */ jsx34(PencilIcon3, { className: "size-4" }),
|
|
13006
|
+
/* @__PURE__ */ jsx34("p", { children: "Edit" })
|
|
12847
13007
|
]
|
|
12848
13008
|
}
|
|
12849
13009
|
) }) }),
|
|
12850
|
-
/* @__PURE__ */
|
|
13010
|
+
/* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", children: "Edit" })
|
|
12851
13011
|
] }),
|
|
12852
|
-
/* @__PURE__ */
|
|
12853
|
-
/* @__PURE__ */
|
|
12854
|
-
/* @__PURE__ */
|
|
12855
|
-
/* @__PURE__ */
|
|
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(
|
|
12856
13016
|
Input,
|
|
12857
13017
|
{
|
|
12858
13018
|
type: "text",
|
|
@@ -12864,9 +13024,9 @@ var SocialItemMenu = ({ hasHref }) => {
|
|
|
12864
13024
|
}
|
|
12865
13025
|
)
|
|
12866
13026
|
] }),
|
|
12867
|
-
/* @__PURE__ */
|
|
12868
|
-
/* @__PURE__ */
|
|
12869
|
-
/* @__PURE__ */
|
|
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(
|
|
12870
13030
|
Input,
|
|
12871
13031
|
{
|
|
12872
13032
|
type: "text",
|
|
@@ -12877,10 +13037,10 @@ var SocialItemMenu = ({ hasHref }) => {
|
|
|
12877
13037
|
}
|
|
12878
13038
|
)
|
|
12879
13039
|
] }),
|
|
12880
|
-
/* @__PURE__ */
|
|
12881
|
-
/* @__PURE__ */
|
|
12882
|
-
/* @__PURE__ */
|
|
12883
|
-
/* @__PURE__ */
|
|
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(
|
|
12884
13044
|
Button,
|
|
12885
13045
|
{
|
|
12886
13046
|
variant: "ghost",
|
|
@@ -12888,12 +13048,12 @@ var SocialItemMenu = ({ hasHref }) => {
|
|
|
12888
13048
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
|
|
12889
13049
|
onClick: handleCopy,
|
|
12890
13050
|
disabled: !hasHref,
|
|
12891
|
-
children: showCopied ? /* @__PURE__ */
|
|
13051
|
+
children: showCopied ? /* @__PURE__ */ jsx34(CheckIcon5, { className: "text-green-600" }) : /* @__PURE__ */ jsx34(CopyIcon4, {})
|
|
12892
13052
|
}
|
|
12893
13053
|
) }),
|
|
12894
|
-
/* @__PURE__ */
|
|
13054
|
+
/* @__PURE__ */ jsx34(TooltipContent, { side: "bottom", className: "z-50001", children: showCopied ? "Copied!" : "Copy link" })
|
|
12895
13055
|
] }) }),
|
|
12896
|
-
/* @__PURE__ */
|
|
13056
|
+
/* @__PURE__ */ jsx34("div", { children: /* @__PURE__ */ jsx34(
|
|
12897
13057
|
Button,
|
|
12898
13058
|
{
|
|
12899
13059
|
variant: "default",
|
|
@@ -12908,11 +13068,11 @@ var SocialItemMenu = ({ hasHref }) => {
|
|
|
12908
13068
|
};
|
|
12909
13069
|
|
|
12910
13070
|
// src/core/editor/hooks/use-alt.ts
|
|
12911
|
-
import { useMemo as
|
|
13071
|
+
import { useMemo as useMemo10, useCallback as useCallback9 } from "react";
|
|
12912
13072
|
import { get as lodashGet6 } from "lodash";
|
|
12913
13073
|
var useAlt = () => {
|
|
12914
13074
|
const { focusIdx, updateElement, template } = useEditorStore();
|
|
12915
|
-
const { element, alt } =
|
|
13075
|
+
const { element, alt } = useMemo10(() => {
|
|
12916
13076
|
if (!focusIdx || !template) {
|
|
12917
13077
|
return { element: null, alt: "" };
|
|
12918
13078
|
}
|
|
@@ -12923,13 +13083,13 @@ var useAlt = () => {
|
|
|
12923
13083
|
alt: el?.attributes?.alt || ""
|
|
12924
13084
|
};
|
|
12925
13085
|
}, [focusIdx, template]);
|
|
12926
|
-
const setAlt =
|
|
13086
|
+
const setAlt = useCallback9((text2) => {
|
|
12927
13087
|
if (!focusIdx || !element) return;
|
|
12928
13088
|
updateElement(focusIdx, {
|
|
12929
13089
|
attributes: { ...element.attributes, alt: text2 }
|
|
12930
13090
|
});
|
|
12931
13091
|
}, [focusIdx, element, updateElement]);
|
|
12932
|
-
const clearAlt =
|
|
13092
|
+
const clearAlt = useCallback9(() => {
|
|
12933
13093
|
if (!focusIdx || !element) return;
|
|
12934
13094
|
updateElement(focusIdx, {
|
|
12935
13095
|
attributes: { ...element.attributes, alt: "" }
|
|
@@ -12945,17 +13105,17 @@ var useAlt = () => {
|
|
|
12945
13105
|
};
|
|
12946
13106
|
|
|
12947
13107
|
// src/core/editor/components/element-gear/social-item/float.tsx
|
|
12948
|
-
import { Fragment as Fragment11, jsx as
|
|
13108
|
+
import { Fragment as Fragment11, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
12949
13109
|
var SocialItemFloat = () => {
|
|
12950
13110
|
const { href, hasHref } = useHref();
|
|
12951
13111
|
const { alt, setAlt } = useAlt();
|
|
12952
13112
|
const { focusIdx, template, deleteElement } = useEditorStore();
|
|
12953
|
-
const [dropdownOpen, setDropdownOpen] =
|
|
12954
|
-
const [altInputValue, setAltInputValue] =
|
|
13113
|
+
const [dropdownOpen, setDropdownOpen] = useState7(false);
|
|
13114
|
+
const [altInputValue, setAltInputValue] = useState7("");
|
|
12955
13115
|
const parentSocial = focusIdx ? getParentByIdx(template, focusIdx) : null;
|
|
12956
13116
|
const childrenCount = parentSocial?.children?.length || 0;
|
|
12957
13117
|
const canDelete = childrenCount > 1;
|
|
12958
|
-
|
|
13118
|
+
useEffect10(() => {
|
|
12959
13119
|
if (dropdownOpen) {
|
|
12960
13120
|
setAltInputValue(alt);
|
|
12961
13121
|
}
|
|
@@ -12969,37 +13129,37 @@ var SocialItemFloat = () => {
|
|
|
12969
13129
|
deleteElement(focusIdx);
|
|
12970
13130
|
}
|
|
12971
13131
|
};
|
|
12972
|
-
return /* @__PURE__ */
|
|
12973
|
-
hasHref && /* @__PURE__ */
|
|
12974
|
-
/* @__PURE__ */
|
|
12975
|
-
/* @__PURE__ */
|
|
12976
|
-
/* @__PURE__ */
|
|
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(
|
|
12977
13137
|
Button,
|
|
12978
13138
|
{
|
|
12979
13139
|
variant: "ghost",
|
|
12980
13140
|
className: floatButtonVariants,
|
|
12981
13141
|
onClick: handleDelete,
|
|
12982
13142
|
disabled: !canDelete,
|
|
12983
|
-
children: /* @__PURE__ */
|
|
13143
|
+
children: /* @__PURE__ */ jsx35(TrashIcon4, { className: "size-4" })
|
|
12984
13144
|
}
|
|
12985
13145
|
) }),
|
|
12986
|
-
/* @__PURE__ */
|
|
13146
|
+
/* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", children: canDelete ? "Delete" : "Cannot delete last item" })
|
|
12987
13147
|
] }),
|
|
12988
|
-
/* @__PURE__ */
|
|
12989
|
-
/* @__PURE__ */
|
|
12990
|
-
/* @__PURE__ */
|
|
12991
|
-
/* @__PURE__ */
|
|
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" })
|
|
12992
13152
|
] }),
|
|
12993
|
-
/* @__PURE__ */
|
|
12994
|
-
/* @__PURE__ */
|
|
12995
|
-
/* @__PURE__ */
|
|
12996
|
-
/* @__PURE__ */
|
|
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" })
|
|
12997
13157
|
] }),
|
|
12998
|
-
/* @__PURE__ */
|
|
12999
|
-
/* @__PURE__ */
|
|
13000
|
-
/* @__PURE__ */
|
|
13001
|
-
/* @__PURE__ */
|
|
13002
|
-
/* @__PURE__ */
|
|
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(
|
|
13003
13163
|
Textarea,
|
|
13004
13164
|
{
|
|
13005
13165
|
placeholder: "Icon image alt, for example: 'Facebook icon'",
|
|
@@ -13009,14 +13169,14 @@ var SocialItemFloat = () => {
|
|
|
13009
13169
|
onChange: (e) => setAltInputValue(e.target.value)
|
|
13010
13170
|
}
|
|
13011
13171
|
),
|
|
13012
|
-
/* @__PURE__ */
|
|
13172
|
+
/* @__PURE__ */ jsxs20("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
|
|
13013
13173
|
altInputValue.length,
|
|
13014
13174
|
"/250"
|
|
13015
13175
|
] })
|
|
13016
13176
|
] }),
|
|
13017
|
-
/* @__PURE__ */
|
|
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." })
|
|
13018
13178
|
] }),
|
|
13019
|
-
/* @__PURE__ */
|
|
13179
|
+
/* @__PURE__ */ jsx35(
|
|
13020
13180
|
Button,
|
|
13021
13181
|
{
|
|
13022
13182
|
variant: "default",
|
|
@@ -13032,27 +13192,27 @@ var SocialItemFloat = () => {
|
|
|
13032
13192
|
};
|
|
13033
13193
|
|
|
13034
13194
|
// src/core/editor/components/element-gear/divider/float.tsx
|
|
13035
|
-
import { Fragment as Fragment12, jsx as
|
|
13195
|
+
import { Fragment as Fragment12, jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
13036
13196
|
var DividerFloat = () => {
|
|
13037
|
-
return /* @__PURE__ */
|
|
13038
|
-
/* @__PURE__ */
|
|
13039
|
-
/* @__PURE__ */
|
|
13197
|
+
return /* @__PURE__ */ jsxs21(Fragment12, { children: [
|
|
13198
|
+
/* @__PURE__ */ jsx36(DuplicateButton, {}),
|
|
13199
|
+
/* @__PURE__ */ jsx36(DeleteButton, {})
|
|
13040
13200
|
] });
|
|
13041
13201
|
};
|
|
13042
13202
|
|
|
13043
13203
|
// src/core/editor/components/element-gear/image/float.tsx
|
|
13044
13204
|
import { Accessibility as Accessibility2, CheckIcon as CheckIcon6, MoreHorizontalIcon as MoreHorizontalIcon5, Proportions } from "lucide-react";
|
|
13045
13205
|
import lodashGet7 from "lodash/get";
|
|
13046
|
-
import { useState as
|
|
13047
|
-
import { Fragment as Fragment13, jsx as
|
|
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";
|
|
13048
13208
|
var ImageFloat = () => {
|
|
13049
13209
|
const { href, hasHref } = useHref();
|
|
13050
13210
|
const { alt, setAlt, hasAlt } = useAlt();
|
|
13051
13211
|
const { focusIdx, updateElement, template } = useEditorStore();
|
|
13052
|
-
const [showMoreView, setShowMoreView] =
|
|
13053
|
-
const [dropdownOpen, setDropdownOpen] =
|
|
13054
|
-
const [altInputValue, setAltInputValue] =
|
|
13055
|
-
const { element, isFluidOnMobile } =
|
|
13212
|
+
const [showMoreView, setShowMoreView] = useState8(null);
|
|
13213
|
+
const [dropdownOpen, setDropdownOpen] = useState8(false);
|
|
13214
|
+
const [altInputValue, setAltInputValue] = useState8("");
|
|
13215
|
+
const { element, isFluidOnMobile } = useMemo11(() => {
|
|
13056
13216
|
if (!focusIdx || !template) return { element: null, isFluidOnMobile: false };
|
|
13057
13217
|
const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
|
|
13058
13218
|
const el = lodashGet7(template, path);
|
|
@@ -13061,7 +13221,7 @@ var ImageFloat = () => {
|
|
|
13061
13221
|
isFluidOnMobile: el?.attributes?.["fluid-on-mobile"] === "true"
|
|
13062
13222
|
};
|
|
13063
13223
|
}, [focusIdx, template]);
|
|
13064
|
-
const toggleFluidOnMobile =
|
|
13224
|
+
const toggleFluidOnMobile = useCallback10(() => {
|
|
13065
13225
|
if (!focusIdx || !element) return;
|
|
13066
13226
|
const newAttributes = { ...element.attributes };
|
|
13067
13227
|
if (isFluidOnMobile) {
|
|
@@ -13071,7 +13231,7 @@ var ImageFloat = () => {
|
|
|
13071
13231
|
}
|
|
13072
13232
|
updateElement(focusIdx, { attributes: newAttributes });
|
|
13073
13233
|
}, [focusIdx, element, isFluidOnMobile, updateElement]);
|
|
13074
|
-
|
|
13234
|
+
useEffect11(() => {
|
|
13075
13235
|
if (dropdownOpen) {
|
|
13076
13236
|
setAltInputValue(alt);
|
|
13077
13237
|
}
|
|
@@ -13080,35 +13240,35 @@ var ImageFloat = () => {
|
|
|
13080
13240
|
setAlt(altInputValue);
|
|
13081
13241
|
setDropdownOpen(false);
|
|
13082
13242
|
};
|
|
13083
|
-
return /* @__PURE__ */
|
|
13084
|
-
hasHref && /* @__PURE__ */
|
|
13085
|
-
/* @__PURE__ */
|
|
13086
|
-
/* @__PURE__ */
|
|
13087
|
-
/* @__PURE__ */
|
|
13088
|
-
/* @__PURE__ */
|
|
13089
|
-
/* @__PURE__ */
|
|
13090
|
-
/* @__PURE__ */
|
|
13091
|
-
/* @__PURE__ */
|
|
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" })
|
|
13092
13252
|
] }),
|
|
13093
|
-
/* @__PURE__ */
|
|
13094
|
-
/* @__PURE__ */
|
|
13095
|
-
/* @__PURE__ */
|
|
13096
|
-
/* @__PURE__ */
|
|
13097
|
-
/* @__PURE__ */
|
|
13098
|
-
isFluidOnMobile && /* @__PURE__ */
|
|
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" })
|
|
13099
13259
|
] })
|
|
13100
13260
|
] }),
|
|
13101
|
-
/* @__PURE__ */
|
|
13102
|
-
/* @__PURE__ */
|
|
13103
|
-
/* @__PURE__ */
|
|
13104
|
-
/* @__PURE__ */
|
|
13105
|
-
/* @__PURE__ */
|
|
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" })
|
|
13106
13266
|
] }),
|
|
13107
|
-
/* @__PURE__ */
|
|
13108
|
-
/* @__PURE__ */
|
|
13109
|
-
/* @__PURE__ */
|
|
13110
|
-
/* @__PURE__ */
|
|
13111
|
-
/* @__PURE__ */
|
|
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(
|
|
13112
13272
|
Textarea,
|
|
13113
13273
|
{
|
|
13114
13274
|
placeholder: "Spacious living room with hardwood floors, large windows, and a cozy fireplace",
|
|
@@ -13118,14 +13278,14 @@ var ImageFloat = () => {
|
|
|
13118
13278
|
onChange: (e) => setAltInputValue(e.target.value)
|
|
13119
13279
|
}
|
|
13120
13280
|
),
|
|
13121
|
-
/* @__PURE__ */
|
|
13281
|
+
/* @__PURE__ */ jsxs22("span", { className: "bg-white rounded-[12px] p-1 shadow-sm absolute bottom-2 right-2 text-xs text-muted-foreground", children: [
|
|
13122
13282
|
altInputValue.length,
|
|
13123
13283
|
"/250"
|
|
13124
13284
|
] })
|
|
13125
13285
|
] }),
|
|
13126
|
-
/* @__PURE__ */
|
|
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." })
|
|
13127
13287
|
] }),
|
|
13128
|
-
/* @__PURE__ */
|
|
13288
|
+
/* @__PURE__ */ jsx37(
|
|
13129
13289
|
Button,
|
|
13130
13290
|
{
|
|
13131
13291
|
variant: "default",
|
|
@@ -13142,7 +13302,7 @@ var ImageFloat = () => {
|
|
|
13142
13302
|
};
|
|
13143
13303
|
|
|
13144
13304
|
// src/core/editor/components/mlsNumber-menu.tsx
|
|
13145
|
-
import { useState as
|
|
13305
|
+
import { useState as useState9, useEffect as useEffect12 } from "react";
|
|
13146
13306
|
import { HousePlusIcon, TrashIcon as TrashIcon5, XIcon as XIcon2, Loader2Icon } from "lucide-react";
|
|
13147
13307
|
|
|
13148
13308
|
// src/services/repliers/commands.ts
|
|
@@ -13158,16 +13318,16 @@ async function getListingByMlsNumber(mlsNumber) {
|
|
|
13158
13318
|
}
|
|
13159
13319
|
|
|
13160
13320
|
// src/core/editor/components/mlsNumber-menu.tsx
|
|
13161
|
-
import { Fragment as Fragment14, jsx as
|
|
13321
|
+
import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
13162
13322
|
var MlsNumberMenu = () => {
|
|
13163
13323
|
const { focusIdx, template, updateElement, onToast } = useEditorStore();
|
|
13164
|
-
const [isOpen, setIsOpen] =
|
|
13165
|
-
const [inputValue, setInputValue] =
|
|
13166
|
-
const [propertyData, setPropertyData] =
|
|
13167
|
-
const [isLoading, setIsLoading] =
|
|
13324
|
+
const [isOpen, setIsOpen] = useState9(false);
|
|
13325
|
+
const [inputValue, setInputValue] = useState9("");
|
|
13326
|
+
const [propertyData, setPropertyData] = useState9(null);
|
|
13327
|
+
const [isLoading, setIsLoading] = useState9(false);
|
|
13168
13328
|
const propertyElement = focusIdx && template ? getValueByIdx(template, focusIdx) : null;
|
|
13169
13329
|
const currentMlsNumber = propertyElement?.data?.value?.mlsNumber || "";
|
|
13170
|
-
|
|
13330
|
+
useEffect12(() => {
|
|
13171
13331
|
setInputValue(currentMlsNumber);
|
|
13172
13332
|
setPropertyData(null);
|
|
13173
13333
|
}, [focusIdx, currentMlsNumber]);
|
|
@@ -13235,25 +13395,25 @@ var MlsNumberMenu = () => {
|
|
|
13235
13395
|
}
|
|
13236
13396
|
}
|
|
13237
13397
|
};
|
|
13238
|
-
return /* @__PURE__ */
|
|
13239
|
-
/* @__PURE__ */
|
|
13240
|
-
/* @__PURE__ */
|
|
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(
|
|
13241
13401
|
Button,
|
|
13242
13402
|
{
|
|
13243
13403
|
variant: "ghost",
|
|
13244
13404
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none h-[34px]",
|
|
13245
13405
|
children: [
|
|
13246
|
-
/* @__PURE__ */
|
|
13247
|
-
/* @__PURE__ */
|
|
13406
|
+
/* @__PURE__ */ jsx38(HousePlusIcon, { className: "size-4" }),
|
|
13407
|
+
/* @__PURE__ */ jsx38("p", { children: "MLS" })
|
|
13248
13408
|
]
|
|
13249
13409
|
}
|
|
13250
13410
|
) }) }),
|
|
13251
|
-
/* @__PURE__ */
|
|
13411
|
+
/* @__PURE__ */ jsx38(TooltipContent, { side: "bottom", children: "Enter MLS Number" })
|
|
13252
13412
|
] }),
|
|
13253
|
-
/* @__PURE__ */
|
|
13254
|
-
/* @__PURE__ */
|
|
13255
|
-
/* @__PURE__ */
|
|
13256
|
-
/* @__PURE__ */
|
|
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(
|
|
13257
13417
|
Input,
|
|
13258
13418
|
{
|
|
13259
13419
|
type: "text",
|
|
@@ -13266,10 +13426,10 @@ var MlsNumberMenu = () => {
|
|
|
13266
13426
|
}
|
|
13267
13427
|
)
|
|
13268
13428
|
] }),
|
|
13269
|
-
/* @__PURE__ */
|
|
13270
|
-
/* @__PURE__ */
|
|
13271
|
-
/* @__PURE__ */
|
|
13272
|
-
/* @__PURE__ */
|
|
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(
|
|
13273
13433
|
Button,
|
|
13274
13434
|
{
|
|
13275
13435
|
variant: "ghost",
|
|
@@ -13277,27 +13437,27 @@ var MlsNumberMenu = () => {
|
|
|
13277
13437
|
className: "shadow-none transition-none cursor-pointer rounded-full outline-none",
|
|
13278
13438
|
onClick: handleClear,
|
|
13279
13439
|
disabled: !inputValue,
|
|
13280
|
-
children: /* @__PURE__ */
|
|
13440
|
+
children: /* @__PURE__ */ jsx38(TrashIcon5, {})
|
|
13281
13441
|
}
|
|
13282
13442
|
) }),
|
|
13283
|
-
/* @__PURE__ */
|
|
13443
|
+
/* @__PURE__ */ jsx38(TooltipContent, { side: "bottom", className: "z-50001", children: "Clear" })
|
|
13284
13444
|
] }) }),
|
|
13285
|
-
/* @__PURE__ */
|
|
13445
|
+
/* @__PURE__ */ jsx38("div", { children: /* @__PURE__ */ jsx38(
|
|
13286
13446
|
Button,
|
|
13287
13447
|
{
|
|
13288
13448
|
variant: "default",
|
|
13289
13449
|
className: "shadow-none transition-none cursor-pointer rounded-[12px] outline-none",
|
|
13290
13450
|
onClick: handleDone,
|
|
13291
13451
|
disabled: isLoading || !inputValue.trim(),
|
|
13292
|
-
children: isLoading ? /* @__PURE__ */
|
|
13452
|
+
children: isLoading ? /* @__PURE__ */ jsx38(Loader2Icon, { className: "size-4 animate-spin" }) : "Done"
|
|
13293
13453
|
}
|
|
13294
13454
|
) })
|
|
13295
13455
|
] }),
|
|
13296
|
-
propertyData && /* @__PURE__ */
|
|
13297
|
-
/* @__PURE__ */
|
|
13298
|
-
/* @__PURE__ */
|
|
13299
|
-
/* @__PURE__ */
|
|
13300
|
-
/* @__PURE__ */
|
|
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(
|
|
13301
13461
|
"img",
|
|
13302
13462
|
{
|
|
13303
13463
|
src: `https://cdn.repliers.io/${propertyData.images?.[0]}`,
|
|
@@ -13305,35 +13465,35 @@ var MlsNumberMenu = () => {
|
|
|
13305
13465
|
className: "w-full h-[120px] object-cover"
|
|
13306
13466
|
}
|
|
13307
13467
|
),
|
|
13308
|
-
/* @__PURE__ */
|
|
13468
|
+
/* @__PURE__ */ jsx38(
|
|
13309
13469
|
Button,
|
|
13310
13470
|
{
|
|
13311
13471
|
variant: "ghost",
|
|
13312
13472
|
size: "icon",
|
|
13313
13473
|
className: "absolute top-1 right-1 h-6 w-6 bg-black/50 hover:bg-black/70 rounded-full",
|
|
13314
13474
|
onClick: handleClearPreview,
|
|
13315
|
-
children: /* @__PURE__ */
|
|
13475
|
+
children: /* @__PURE__ */ jsx38(XIcon2, { className: "size-3 text-white" })
|
|
13316
13476
|
}
|
|
13317
13477
|
)
|
|
13318
13478
|
] }),
|
|
13319
|
-
/* @__PURE__ */
|
|
13320
|
-
/* @__PURE__ */
|
|
13321
|
-
/* @__PURE__ */
|
|
13322
|
-
/* @__PURE__ */
|
|
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 })
|
|
13323
13483
|
] }),
|
|
13324
|
-
/* @__PURE__ */
|
|
13484
|
+
/* @__PURE__ */ jsxs23("div", { className: "text-sm", children: [
|
|
13325
13485
|
propertyData.address?.streetNumber,
|
|
13326
13486
|
" ",
|
|
13327
13487
|
propertyData.address?.streetName
|
|
13328
13488
|
] }),
|
|
13329
|
-
/* @__PURE__ */
|
|
13489
|
+
/* @__PURE__ */ jsxs23("div", { className: "text-xs text-muted-foreground", children: [
|
|
13330
13490
|
propertyData.address?.city,
|
|
13331
13491
|
", ",
|
|
13332
13492
|
propertyData.address?.state,
|
|
13333
13493
|
" ",
|
|
13334
13494
|
propertyData.address?.zip
|
|
13335
13495
|
] }),
|
|
13336
|
-
/* @__PURE__ */
|
|
13496
|
+
/* @__PURE__ */ jsxs23("div", { className: "text-xs text-muted-foreground", children: [
|
|
13337
13497
|
propertyData.details?.numBedrooms,
|
|
13338
13498
|
" bd | ",
|
|
13339
13499
|
propertyData.details?.numBathrooms,
|
|
@@ -13341,8 +13501,8 @@ var MlsNumberMenu = () => {
|
|
|
13341
13501
|
formatNumber(String(propertyData.details?.sqft || "--")),
|
|
13342
13502
|
" sf"
|
|
13343
13503
|
] }),
|
|
13344
|
-
propertyData.office?.brokerageName && /* @__PURE__ */
|
|
13345
|
-
/* @__PURE__ */
|
|
13504
|
+
propertyData.office?.brokerageName && /* @__PURE__ */ jsx38("div", { className: "text-xs text-muted-foreground truncate", children: propertyData.office.brokerageName }),
|
|
13505
|
+
/* @__PURE__ */ jsx38(
|
|
13346
13506
|
Button,
|
|
13347
13507
|
{
|
|
13348
13508
|
variant: "default",
|
|
@@ -13360,34 +13520,34 @@ var MlsNumberMenu = () => {
|
|
|
13360
13520
|
};
|
|
13361
13521
|
|
|
13362
13522
|
// src/core/editor/components/element-gear/property/float.tsx
|
|
13363
|
-
import { Fragment as Fragment15, jsx as
|
|
13523
|
+
import { Fragment as Fragment15, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
13364
13524
|
function PropertyFloat() {
|
|
13365
13525
|
const { href, hasHref } = useHref();
|
|
13366
|
-
return /* @__PURE__ */
|
|
13367
|
-
hasHref && /* @__PURE__ */
|
|
13368
|
-
/* @__PURE__ */
|
|
13369
|
-
/* @__PURE__ */
|
|
13526
|
+
return /* @__PURE__ */ jsxs24(Fragment15, { children: [
|
|
13527
|
+
hasHref && /* @__PURE__ */ jsx39(FloatLinkPreview, { href }),
|
|
13528
|
+
/* @__PURE__ */ jsx39(HrefMenu, {}),
|
|
13529
|
+
/* @__PURE__ */ jsx39(MlsNumberMenu, {})
|
|
13370
13530
|
] });
|
|
13371
13531
|
}
|
|
13372
13532
|
|
|
13373
13533
|
// src/core/editor/components/element-gear/property/triple/float.tsx
|
|
13374
|
-
import { Fragment as Fragment16, jsx as
|
|
13534
|
+
import { Fragment as Fragment16, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
13375
13535
|
var PropertyTripleItemFloat = () => {
|
|
13376
13536
|
const { href, hasHref } = useHref();
|
|
13377
|
-
return /* @__PURE__ */
|
|
13378
|
-
hasHref && /* @__PURE__ */
|
|
13379
|
-
/* @__PURE__ */
|
|
13537
|
+
return /* @__PURE__ */ jsxs25(Fragment16, { children: [
|
|
13538
|
+
hasHref && /* @__PURE__ */ jsx40(FloatLinkPreview, { href }),
|
|
13539
|
+
/* @__PURE__ */ jsx40(HrefMenu, {})
|
|
13380
13540
|
] });
|
|
13381
13541
|
};
|
|
13382
13542
|
|
|
13383
13543
|
// src/core/editor/components/float-ui/container.tsx
|
|
13384
|
-
import { jsx as
|
|
13544
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
13385
13545
|
var FloatUIContainer = ({ ref, style, className, children }) => {
|
|
13386
|
-
return /* @__PURE__ */
|
|
13546
|
+
return /* @__PURE__ */ jsx41("div", { ref, style, className, children });
|
|
13387
13547
|
};
|
|
13388
13548
|
|
|
13389
13549
|
// src/core/editor/components/element-float.tsx
|
|
13390
|
-
import { jsx as
|
|
13550
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
13391
13551
|
var FLOAT_COMPONENTS = {
|
|
13392
13552
|
"button": ButtonFloat,
|
|
13393
13553
|
"section": SectionFloat,
|
|
@@ -13411,7 +13571,7 @@ var ElementFloat = ({ getReferenceRect, focusIdx, elementType }) => {
|
|
|
13411
13571
|
if (!focusIdx || isDragging || textEditing) return null;
|
|
13412
13572
|
const FloatComponent = FLOAT_COMPONENTS[elementType];
|
|
13413
13573
|
if (!FloatComponent) return null;
|
|
13414
|
-
return /* @__PURE__ */
|
|
13574
|
+
return /* @__PURE__ */ jsx42(
|
|
13415
13575
|
ElementFloatContent,
|
|
13416
13576
|
{
|
|
13417
13577
|
getReferenceRect,
|
|
@@ -13420,7 +13580,7 @@ var ElementFloat = ({ getReferenceRect, focusIdx, elementType }) => {
|
|
|
13420
13580
|
);
|
|
13421
13581
|
};
|
|
13422
13582
|
var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
|
|
13423
|
-
const virtualReference =
|
|
13583
|
+
const virtualReference = useMemo12(() => ({
|
|
13424
13584
|
getBoundingClientRect: () => {
|
|
13425
13585
|
const rect = getReferenceRect();
|
|
13426
13586
|
if (!rect) {
|
|
@@ -13429,18 +13589,18 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
|
|
|
13429
13589
|
return rect;
|
|
13430
13590
|
}
|
|
13431
13591
|
}), [getReferenceRect]);
|
|
13432
|
-
const { floatingStyles, refs, update } =
|
|
13592
|
+
const { floatingStyles, refs, update } = useFloating5({
|
|
13433
13593
|
placement: "top",
|
|
13434
13594
|
middleware: [
|
|
13435
|
-
|
|
13595
|
+
offset5(16),
|
|
13436
13596
|
// 8px above the element
|
|
13437
|
-
|
|
13597
|
+
flip3({ padding: 8 }),
|
|
13438
13598
|
// Flip to bottom if not enough space above
|
|
13439
|
-
|
|
13599
|
+
shift4({ padding: 8 })
|
|
13440
13600
|
// Keep within viewport
|
|
13441
13601
|
]
|
|
13442
13602
|
});
|
|
13443
|
-
|
|
13603
|
+
useEffect13(() => {
|
|
13444
13604
|
const rect = getReferenceRect();
|
|
13445
13605
|
if (!rect || !refs.floating.current) return;
|
|
13446
13606
|
refs.setPositionReference(virtualReference);
|
|
@@ -13455,18 +13615,18 @@ var ElementFloatContent = ({ getReferenceRect, FloatComponent }) => {
|
|
|
13455
13615
|
);
|
|
13456
13616
|
return cleanup;
|
|
13457
13617
|
}, [getReferenceRect, refs, update, virtualReference]);
|
|
13458
|
-
return /* @__PURE__ */
|
|
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, {}) });
|
|
13459
13619
|
};
|
|
13460
13620
|
|
|
13461
13621
|
// src/core/editor/components/scaling/divider-scale.tsx
|
|
13462
|
-
import { useMemo as
|
|
13463
|
-
import { useFloating as
|
|
13464
|
-
import { jsx as
|
|
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";
|
|
13465
13625
|
var DividerScale = ({ getReferenceRect }) => {
|
|
13466
|
-
const [dimensions, setDimensions] =
|
|
13467
|
-
const [activeSide, setActiveSide] =
|
|
13626
|
+
const [dimensions, setDimensions] = useState10({ width: 0, height: 0 });
|
|
13627
|
+
const [activeSide, setActiveSide] = useState10(null);
|
|
13468
13628
|
const { focusIdx, template, setIsScaling } = useEditorStore();
|
|
13469
|
-
const { currentWidth, currentAlign } =
|
|
13629
|
+
const { currentWidth, currentAlign } = useMemo13(() => {
|
|
13470
13630
|
if (!focusIdx || !template) return { currentWidth: 100, currentAlign: "center" };
|
|
13471
13631
|
const element = getValueByIdx(template, focusIdx);
|
|
13472
13632
|
const rawWidth = element?.attributes?.width;
|
|
@@ -13475,13 +13635,13 @@ var DividerScale = ({ getReferenceRect }) => {
|
|
|
13475
13635
|
const align = element?.attributes?.align || "center";
|
|
13476
13636
|
return { currentWidth: width, currentAlign: align };
|
|
13477
13637
|
}, [focusIdx, template]);
|
|
13478
|
-
const dragRef =
|
|
13479
|
-
const getContainerWidth =
|
|
13638
|
+
const dragRef = useRef6(null);
|
|
13639
|
+
const getContainerWidth = useCallback12(() => {
|
|
13480
13640
|
const rect = getReferenceRect();
|
|
13481
13641
|
if (!rect || currentWidth <= 0) return null;
|
|
13482
13642
|
return rect.width / (currentWidth / 100);
|
|
13483
13643
|
}, [getReferenceRect, currentWidth]);
|
|
13484
|
-
const handlePointerDown =
|
|
13644
|
+
const handlePointerDown = useCallback12((e, side) => {
|
|
13485
13645
|
e.preventDefault();
|
|
13486
13646
|
e.stopPropagation();
|
|
13487
13647
|
const containerWidth = getContainerWidth();
|
|
@@ -13499,7 +13659,7 @@ var DividerScale = ({ getReferenceRect }) => {
|
|
|
13499
13659
|
document.addEventListener("pointermove", handlePointerMove);
|
|
13500
13660
|
document.addEventListener("pointerup", handlePointerUp);
|
|
13501
13661
|
}, [getContainerWidth, currentWidth, currentAlign, setIsScaling]);
|
|
13502
|
-
const handlePointerMove =
|
|
13662
|
+
const handlePointerMove = useCallback12((e) => {
|
|
13503
13663
|
if (!dragRef.current) return;
|
|
13504
13664
|
const { startX, startWidth, containerWidth, side, align } = dragRef.current;
|
|
13505
13665
|
const deltaX = e.clientX - startX;
|
|
@@ -13519,20 +13679,20 @@ var DividerScale = ({ getReferenceRect }) => {
|
|
|
13519
13679
|
}
|
|
13520
13680
|
});
|
|
13521
13681
|
}, []);
|
|
13522
|
-
const handlePointerUp =
|
|
13682
|
+
const handlePointerUp = useCallback12(() => {
|
|
13523
13683
|
setActiveSide(null);
|
|
13524
13684
|
setIsScaling(false);
|
|
13525
13685
|
dragRef.current = null;
|
|
13526
13686
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
13527
13687
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
13528
13688
|
}, [handlePointerMove, setIsScaling]);
|
|
13529
|
-
|
|
13689
|
+
useEffect14(() => {
|
|
13530
13690
|
return () => {
|
|
13531
13691
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
13532
13692
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
13533
13693
|
};
|
|
13534
13694
|
}, [handlePointerMove, handlePointerUp]);
|
|
13535
|
-
const virtualReference =
|
|
13695
|
+
const virtualReference = useMemo13(() => ({
|
|
13536
13696
|
getBoundingClientRect: () => {
|
|
13537
13697
|
const rect = getReferenceRect();
|
|
13538
13698
|
if (!rect) {
|
|
@@ -13541,13 +13701,13 @@ var DividerScale = ({ getReferenceRect }) => {
|
|
|
13541
13701
|
return rect;
|
|
13542
13702
|
}
|
|
13543
13703
|
}), [getReferenceRect]);
|
|
13544
|
-
const { floatingStyles, refs, update } =
|
|
13704
|
+
const { floatingStyles, refs, update } = useFloating6({
|
|
13545
13705
|
placement: "bottom-start",
|
|
13546
13706
|
middleware: [
|
|
13547
|
-
|
|
13707
|
+
offset6(({ rects }) => -rects.reference.height)
|
|
13548
13708
|
]
|
|
13549
13709
|
});
|
|
13550
|
-
|
|
13710
|
+
useEffect14(() => {
|
|
13551
13711
|
const rect = getReferenceRect();
|
|
13552
13712
|
if (!rect || !refs.floating.current) return;
|
|
13553
13713
|
refs.setPositionReference(virtualReference);
|
|
@@ -13574,7 +13734,7 @@ var DividerScale = ({ getReferenceRect }) => {
|
|
|
13574
13734
|
}, [getReferenceRect, refs, update, virtualReference]);
|
|
13575
13735
|
const showLeftHandle = currentAlign !== "left";
|
|
13576
13736
|
const showRightHandle = currentAlign !== "right";
|
|
13577
|
-
return /* @__PURE__ */
|
|
13737
|
+
return /* @__PURE__ */ jsxs26(
|
|
13578
13738
|
"div",
|
|
13579
13739
|
{
|
|
13580
13740
|
ref: refs.setFloating,
|
|
@@ -13586,14 +13746,14 @@ var DividerScale = ({ getReferenceRect }) => {
|
|
|
13586
13746
|
},
|
|
13587
13747
|
className: "relative flex flex-row items-center justify-between",
|
|
13588
13748
|
children: [
|
|
13589
|
-
showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */
|
|
13749
|
+
showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx43(
|
|
13590
13750
|
"div",
|
|
13591
13751
|
{
|
|
13592
13752
|
onPointerDown: (e) => handlePointerDown(e, "left"),
|
|
13593
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"}`
|
|
13594
13754
|
}
|
|
13595
13755
|
),
|
|
13596
|
-
showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */
|
|
13756
|
+
showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx43(
|
|
13597
13757
|
"div",
|
|
13598
13758
|
{
|
|
13599
13759
|
onPointerDown: (e) => handlePointerDown(e, "right"),
|
|
@@ -13606,14 +13766,14 @@ var DividerScale = ({ getReferenceRect }) => {
|
|
|
13606
13766
|
};
|
|
13607
13767
|
|
|
13608
13768
|
// src/core/editor/components/scaling/button-scale.tsx
|
|
13609
|
-
import { useMemo as
|
|
13610
|
-
import { useFloating as
|
|
13611
|
-
import { jsx as
|
|
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";
|
|
13612
13772
|
var ButtonScale = ({ getReferenceRect }) => {
|
|
13613
|
-
const [dimensions, setDimensions] =
|
|
13614
|
-
const [activeSide, setActiveSide] =
|
|
13773
|
+
const [dimensions, setDimensions] = useState11({ width: 0, height: 0 });
|
|
13774
|
+
const [activeSide, setActiveSide] = useState11(null);
|
|
13615
13775
|
const { focusIdx, template, setIsScaling } = useEditorStore();
|
|
13616
|
-
const { currentWidth, currentHeight, currentAlign } =
|
|
13776
|
+
const { currentWidth, currentHeight, currentAlign } = useMemo14(() => {
|
|
13617
13777
|
if (!focusIdx || !template) {
|
|
13618
13778
|
return { currentWidth: 24, currentHeight: 44, currentAlign: "center" };
|
|
13619
13779
|
}
|
|
@@ -13627,13 +13787,13 @@ var ButtonScale = ({ getReferenceRect }) => {
|
|
|
13627
13787
|
const align = element?.attributes?.align || "center";
|
|
13628
13788
|
return { currentWidth: width, currentHeight: height, currentAlign: align };
|
|
13629
13789
|
}, [focusIdx, template]);
|
|
13630
|
-
const dragRef =
|
|
13631
|
-
const getContainerWidth =
|
|
13790
|
+
const dragRef = useRef7(null);
|
|
13791
|
+
const getContainerWidth = useCallback13(() => {
|
|
13632
13792
|
const rect = getReferenceRect();
|
|
13633
13793
|
if (!rect || currentWidth <= 0) return null;
|
|
13634
13794
|
return rect.width / (currentWidth / 100);
|
|
13635
13795
|
}, [getReferenceRect, currentWidth]);
|
|
13636
|
-
const handlePointerDown =
|
|
13796
|
+
const handlePointerDown = useCallback13((e, side) => {
|
|
13637
13797
|
e.preventDefault();
|
|
13638
13798
|
e.stopPropagation();
|
|
13639
13799
|
if (document.activeElement instanceof HTMLElement) {
|
|
@@ -13655,7 +13815,7 @@ var ButtonScale = ({ getReferenceRect }) => {
|
|
|
13655
13815
|
document.addEventListener("pointermove", handlePointerMove);
|
|
13656
13816
|
document.addEventListener("pointerup", handlePointerUp);
|
|
13657
13817
|
}, [getContainerWidth, currentWidth, currentHeight, currentAlign, setIsScaling]);
|
|
13658
|
-
const handlePointerMove =
|
|
13818
|
+
const handlePointerMove = useCallback13((e) => {
|
|
13659
13819
|
if (!dragRef.current) return;
|
|
13660
13820
|
const { startX, startY, startWidth, startHeight, containerWidth, side, align } = dragRef.current;
|
|
13661
13821
|
const state = useEditorStore.getState();
|
|
@@ -13687,20 +13847,20 @@ var ButtonScale = ({ getReferenceRect }) => {
|
|
|
13687
13847
|
});
|
|
13688
13848
|
}
|
|
13689
13849
|
}, []);
|
|
13690
|
-
const handlePointerUp =
|
|
13850
|
+
const handlePointerUp = useCallback13(() => {
|
|
13691
13851
|
setActiveSide(null);
|
|
13692
13852
|
setIsScaling(false);
|
|
13693
13853
|
dragRef.current = null;
|
|
13694
13854
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
13695
13855
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
13696
13856
|
}, [handlePointerMove, setIsScaling]);
|
|
13697
|
-
|
|
13857
|
+
useEffect15(() => {
|
|
13698
13858
|
return () => {
|
|
13699
13859
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
13700
13860
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
13701
13861
|
};
|
|
13702
13862
|
}, [handlePointerMove, handlePointerUp]);
|
|
13703
|
-
const virtualReference =
|
|
13863
|
+
const virtualReference = useMemo14(() => ({
|
|
13704
13864
|
getBoundingClientRect: () => {
|
|
13705
13865
|
const rect = getReferenceRect();
|
|
13706
13866
|
if (!rect) {
|
|
@@ -13709,13 +13869,13 @@ var ButtonScale = ({ getReferenceRect }) => {
|
|
|
13709
13869
|
return rect;
|
|
13710
13870
|
}
|
|
13711
13871
|
}), [getReferenceRect]);
|
|
13712
|
-
const { floatingStyles, refs, update } =
|
|
13872
|
+
const { floatingStyles, refs, update } = useFloating7({
|
|
13713
13873
|
placement: "bottom-start",
|
|
13714
13874
|
middleware: [
|
|
13715
|
-
|
|
13875
|
+
offset7(({ rects }) => -rects.reference.height)
|
|
13716
13876
|
]
|
|
13717
13877
|
});
|
|
13718
|
-
|
|
13878
|
+
useEffect15(() => {
|
|
13719
13879
|
const rect = getReferenceRect();
|
|
13720
13880
|
if (!rect || !refs.floating.current) return;
|
|
13721
13881
|
refs.setPositionReference(virtualReference);
|
|
@@ -13744,7 +13904,7 @@ var ButtonScale = ({ getReferenceRect }) => {
|
|
|
13744
13904
|
const showRightHandle = currentAlign !== "right";
|
|
13745
13905
|
const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
|
|
13746
13906
|
const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
|
|
13747
|
-
return /* @__PURE__ */
|
|
13907
|
+
return /* @__PURE__ */ jsxs27(
|
|
13748
13908
|
"div",
|
|
13749
13909
|
{
|
|
13750
13910
|
ref: refs.setFloating,
|
|
@@ -13756,28 +13916,28 @@ var ButtonScale = ({ getReferenceRect }) => {
|
|
|
13756
13916
|
},
|
|
13757
13917
|
className: "relative pointer-events-none",
|
|
13758
13918
|
children: [
|
|
13759
|
-
(activeSide === null || activeSide === "top") && /* @__PURE__ */
|
|
13919
|
+
(activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx44(
|
|
13760
13920
|
"div",
|
|
13761
13921
|
{
|
|
13762
13922
|
onPointerDown: (e) => handlePointerDown(e, "top"),
|
|
13763
13923
|
className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
|
|
13764
13924
|
}
|
|
13765
13925
|
),
|
|
13766
|
-
showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */
|
|
13926
|
+
showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx44(
|
|
13767
13927
|
"div",
|
|
13768
13928
|
{
|
|
13769
13929
|
onPointerDown: (e) => handlePointerDown(e, "right"),
|
|
13770
13930
|
className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
|
|
13771
13931
|
}
|
|
13772
13932
|
),
|
|
13773
|
-
(activeSide === null || activeSide === "bottom") && /* @__PURE__ */
|
|
13933
|
+
(activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx44(
|
|
13774
13934
|
"div",
|
|
13775
13935
|
{
|
|
13776
13936
|
onPointerDown: (e) => handlePointerDown(e, "bottom"),
|
|
13777
13937
|
className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
|
|
13778
13938
|
}
|
|
13779
13939
|
),
|
|
13780
|
-
showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */
|
|
13940
|
+
showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx44(
|
|
13781
13941
|
"div",
|
|
13782
13942
|
{
|
|
13783
13943
|
onPointerDown: (e) => handlePointerDown(e, "left"),
|
|
@@ -13790,14 +13950,15 @@ var ButtonScale = ({ getReferenceRect }) => {
|
|
|
13790
13950
|
};
|
|
13791
13951
|
|
|
13792
13952
|
// src/core/editor/components/scaling/image-scale.tsx
|
|
13793
|
-
import { useMemo as
|
|
13794
|
-
import { useFloating as
|
|
13795
|
-
import { jsx as
|
|
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";
|
|
13796
13957
|
var ImageScale = ({ getReferenceRect }) => {
|
|
13797
|
-
const [dimensions, setDimensions] =
|
|
13798
|
-
const [activeSide, setActiveSide] =
|
|
13958
|
+
const [dimensions, setDimensions] = useState12({ width: 0, height: 0 });
|
|
13959
|
+
const [activeSide, setActiveSide] = useState12(null);
|
|
13799
13960
|
const { focusIdx, template, setIsScaling } = useEditorStore();
|
|
13800
|
-
const { currentWidth, currentHeight, currentAlign } =
|
|
13961
|
+
const { currentWidth, currentHeight, currentAlign } = useMemo15(() => {
|
|
13801
13962
|
if (!focusIdx || !template) {
|
|
13802
13963
|
return { currentWidth: 0, currentHeight: 0, currentAlign: "center" };
|
|
13803
13964
|
}
|
|
@@ -13811,8 +13972,8 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13811
13972
|
const align = element?.attributes?.align || "center";
|
|
13812
13973
|
return { currentWidth: width, currentHeight: height, currentAlign: align };
|
|
13813
13974
|
}, [focusIdx, template]);
|
|
13814
|
-
const dragRef =
|
|
13815
|
-
const handlePointerDown =
|
|
13975
|
+
const dragRef = useRef8(null);
|
|
13976
|
+
const handlePointerDown = useCallback14((e, side) => {
|
|
13816
13977
|
e.preventDefault();
|
|
13817
13978
|
e.stopPropagation();
|
|
13818
13979
|
if (document.activeElement instanceof HTMLElement) {
|
|
@@ -13830,12 +13991,13 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13830
13991
|
startWidth: effectiveWidth,
|
|
13831
13992
|
startHeight: effectiveHeight,
|
|
13832
13993
|
side,
|
|
13833
|
-
align: currentAlign
|
|
13994
|
+
align: currentAlign,
|
|
13995
|
+
aspectRatio: effectiveHeight > 0 ? effectiveWidth / effectiveHeight : 1
|
|
13834
13996
|
};
|
|
13835
13997
|
document.addEventListener("pointermove", handlePointerMove);
|
|
13836
13998
|
document.addEventListener("pointerup", handlePointerUp);
|
|
13837
13999
|
}, [getReferenceRect, currentWidth, currentHeight, currentAlign, setIsScaling]);
|
|
13838
|
-
const handlePointerMove =
|
|
14000
|
+
const handlePointerMove = useCallback14((e) => {
|
|
13839
14001
|
if (!dragRef.current) return;
|
|
13840
14002
|
const { startX, startY, startWidth, startHeight, side, align } = dragRef.current;
|
|
13841
14003
|
const state = useEditorStore.getState();
|
|
@@ -13843,7 +14005,35 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13843
14005
|
if (!currentFocusIdx || !currentTemplate) return;
|
|
13844
14006
|
const element = getValueByIdx(currentTemplate, currentFocusIdx);
|
|
13845
14007
|
if (!element) return;
|
|
13846
|
-
if (side
|
|
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") {
|
|
13847
14037
|
const deltaX = e.clientX - startX;
|
|
13848
14038
|
const alignMultiplier = align === "center" ? 2 : 1;
|
|
13849
14039
|
const newWidth = side === "left" ? startWidth - deltaX * alignMultiplier : startWidth + deltaX * alignMultiplier;
|
|
@@ -13866,20 +14056,20 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13866
14056
|
});
|
|
13867
14057
|
}
|
|
13868
14058
|
}, []);
|
|
13869
|
-
const handlePointerUp =
|
|
14059
|
+
const handlePointerUp = useCallback14(() => {
|
|
13870
14060
|
setActiveSide(null);
|
|
13871
14061
|
setIsScaling(false);
|
|
13872
14062
|
dragRef.current = null;
|
|
13873
14063
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
13874
14064
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
13875
14065
|
}, [handlePointerMove, setIsScaling]);
|
|
13876
|
-
|
|
14066
|
+
useEffect16(() => {
|
|
13877
14067
|
return () => {
|
|
13878
14068
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
13879
14069
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
13880
14070
|
};
|
|
13881
14071
|
}, [handlePointerMove, handlePointerUp]);
|
|
13882
|
-
const virtualReference =
|
|
14072
|
+
const virtualReference = useMemo15(() => ({
|
|
13883
14073
|
getBoundingClientRect: () => {
|
|
13884
14074
|
const rect = getReferenceRect();
|
|
13885
14075
|
if (!rect) {
|
|
@@ -13888,13 +14078,13 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13888
14078
|
return rect;
|
|
13889
14079
|
}
|
|
13890
14080
|
}), [getReferenceRect]);
|
|
13891
|
-
const { floatingStyles, refs, update } =
|
|
14081
|
+
const { floatingStyles, refs, update } = useFloating8({
|
|
13892
14082
|
placement: "bottom-start",
|
|
13893
14083
|
middleware: [
|
|
13894
|
-
|
|
14084
|
+
offset8(({ rects }) => -rects.reference.height)
|
|
13895
14085
|
]
|
|
13896
14086
|
});
|
|
13897
|
-
|
|
14087
|
+
useEffect16(() => {
|
|
13898
14088
|
const rect = getReferenceRect();
|
|
13899
14089
|
if (!rect || !refs.floating.current) return;
|
|
13900
14090
|
refs.setPositionReference(virtualReference);
|
|
@@ -13921,9 +14111,13 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13921
14111
|
}, [getReferenceRect, refs, update, virtualReference]);
|
|
13922
14112
|
const showLeftHandle = currentAlign !== "left";
|
|
13923
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";
|
|
13924
14118
|
const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
|
|
13925
14119
|
const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
|
|
13926
|
-
return /* @__PURE__ */
|
|
14120
|
+
return /* @__PURE__ */ jsxs28(
|
|
13927
14121
|
"div",
|
|
13928
14122
|
{
|
|
13929
14123
|
ref: refs.setFloating,
|
|
@@ -13935,33 +14129,61 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13935
14129
|
},
|
|
13936
14130
|
className: "relative pointer-events-none",
|
|
13937
14131
|
children: [
|
|
13938
|
-
(activeSide === null || activeSide === "top") && /* @__PURE__ */
|
|
14132
|
+
(activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx45(
|
|
13939
14133
|
"div",
|
|
13940
14134
|
{
|
|
13941
14135
|
onPointerDown: (e) => handlePointerDown(e, "top"),
|
|
13942
14136
|
className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
|
|
13943
14137
|
}
|
|
13944
14138
|
),
|
|
13945
|
-
showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */
|
|
14139
|
+
showRightHandle && (activeSide === null || activeSide === "right") && /* @__PURE__ */ jsx45(
|
|
13946
14140
|
"div",
|
|
13947
14141
|
{
|
|
13948
14142
|
onPointerDown: (e) => handlePointerDown(e, "right"),
|
|
13949
14143
|
className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -right-[4px] ${getHandleActiveClass("right")}`
|
|
13950
14144
|
}
|
|
13951
14145
|
),
|
|
13952
|
-
(activeSide === null || activeSide === "bottom") && /* @__PURE__ */
|
|
14146
|
+
(activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx45(
|
|
13953
14147
|
"div",
|
|
13954
14148
|
{
|
|
13955
14149
|
onPointerDown: (e) => handlePointerDown(e, "bottom"),
|
|
13956
14150
|
className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -bottom-[4px] ${getHandleActiveClass("bottom")}`
|
|
13957
14151
|
}
|
|
13958
14152
|
),
|
|
13959
|
-
showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */
|
|
14153
|
+
showLeftHandle && (activeSide === null || activeSide === "left") && /* @__PURE__ */ jsx45(
|
|
13960
14154
|
"div",
|
|
13961
14155
|
{
|
|
13962
14156
|
onPointerDown: (e) => handlePointerDown(e, "left"),
|
|
13963
14157
|
className: `w-[8px] h-[18px] cursor-ew-resize ${handleBaseClass} top-1/2 -translate-y-1/2 -left-[4px] ${getHandleActiveClass("left")}`
|
|
13964
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
|
+
}
|
|
13965
14187
|
)
|
|
13966
14188
|
]
|
|
13967
14189
|
}
|
|
@@ -13969,22 +14191,22 @@ var ImageScale = ({ getReferenceRect }) => {
|
|
|
13969
14191
|
};
|
|
13970
14192
|
|
|
13971
14193
|
// src/core/editor/components/scaling/spacer-scale.tsx
|
|
13972
|
-
import { useMemo as
|
|
13973
|
-
import { useFloating as
|
|
13974
|
-
import { jsx as
|
|
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";
|
|
13975
14197
|
var SpacerScale = ({ getReferenceRect }) => {
|
|
13976
|
-
const [dimensions, setDimensions] =
|
|
13977
|
-
const [activeSide, setActiveSide] =
|
|
14198
|
+
const [dimensions, setDimensions] = useState13({ width: 0, height: 0 });
|
|
14199
|
+
const [activeSide, setActiveSide] = useState13(null);
|
|
13978
14200
|
const { focusIdx, template, setIsScaling } = useEditorStore();
|
|
13979
|
-
const currentHeight =
|
|
14201
|
+
const currentHeight = useMemo16(() => {
|
|
13980
14202
|
if (!focusIdx || !template) return 12;
|
|
13981
14203
|
const element = getValueByIdx(template, focusIdx);
|
|
13982
14204
|
const rawHeight = element?.attributes?.height;
|
|
13983
14205
|
const parsedHeight = rawHeight ? parseFloat(rawHeight.replace("px", "")) : 12;
|
|
13984
14206
|
return isNaN(parsedHeight) ? 12 : Math.max(12, Math.min(200, parsedHeight));
|
|
13985
14207
|
}, [focusIdx, template]);
|
|
13986
|
-
const dragRef =
|
|
13987
|
-
const handlePointerDown =
|
|
14208
|
+
const dragRef = useRef9(null);
|
|
14209
|
+
const handlePointerDown = useCallback15((e, side) => {
|
|
13988
14210
|
e.preventDefault();
|
|
13989
14211
|
e.stopPropagation();
|
|
13990
14212
|
if (document.activeElement instanceof HTMLElement) {
|
|
@@ -14000,7 +14222,7 @@ var SpacerScale = ({ getReferenceRect }) => {
|
|
|
14000
14222
|
document.addEventListener("pointermove", handlePointerMove);
|
|
14001
14223
|
document.addEventListener("pointerup", handlePointerUp);
|
|
14002
14224
|
}, [currentHeight, setIsScaling]);
|
|
14003
|
-
const handlePointerMove =
|
|
14225
|
+
const handlePointerMove = useCallback15((e) => {
|
|
14004
14226
|
if (!dragRef.current) return;
|
|
14005
14227
|
const { startY, startHeight, side } = dragRef.current;
|
|
14006
14228
|
const state = useEditorStore.getState();
|
|
@@ -14018,20 +14240,20 @@ var SpacerScale = ({ getReferenceRect }) => {
|
|
|
14018
14240
|
}
|
|
14019
14241
|
});
|
|
14020
14242
|
}, []);
|
|
14021
|
-
const handlePointerUp =
|
|
14243
|
+
const handlePointerUp = useCallback15(() => {
|
|
14022
14244
|
setActiveSide(null);
|
|
14023
14245
|
setIsScaling(false);
|
|
14024
14246
|
dragRef.current = null;
|
|
14025
14247
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
14026
14248
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
14027
14249
|
}, [handlePointerMove, setIsScaling]);
|
|
14028
|
-
|
|
14250
|
+
useEffect17(() => {
|
|
14029
14251
|
return () => {
|
|
14030
14252
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
14031
14253
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
14032
14254
|
};
|
|
14033
14255
|
}, [handlePointerMove, handlePointerUp]);
|
|
14034
|
-
const virtualReference =
|
|
14256
|
+
const virtualReference = useMemo16(() => ({
|
|
14035
14257
|
getBoundingClientRect: () => {
|
|
14036
14258
|
const rect = getReferenceRect();
|
|
14037
14259
|
if (!rect) {
|
|
@@ -14040,13 +14262,13 @@ var SpacerScale = ({ getReferenceRect }) => {
|
|
|
14040
14262
|
return rect;
|
|
14041
14263
|
}
|
|
14042
14264
|
}), [getReferenceRect]);
|
|
14043
|
-
const { floatingStyles, refs, update } =
|
|
14265
|
+
const { floatingStyles, refs, update } = useFloating9({
|
|
14044
14266
|
placement: "bottom-start",
|
|
14045
14267
|
middleware: [
|
|
14046
|
-
|
|
14268
|
+
offset9(({ rects }) => -rects.reference.height)
|
|
14047
14269
|
]
|
|
14048
14270
|
});
|
|
14049
|
-
|
|
14271
|
+
useEffect17(() => {
|
|
14050
14272
|
const rect = getReferenceRect();
|
|
14051
14273
|
if (!rect || !refs.floating.current) return;
|
|
14052
14274
|
refs.setPositionReference(virtualReference);
|
|
@@ -14073,7 +14295,7 @@ var SpacerScale = ({ getReferenceRect }) => {
|
|
|
14073
14295
|
}, [getReferenceRect, refs, update, virtualReference]);
|
|
14074
14296
|
const handleBaseClass = "bg-background shadow-md border rounded-full absolute touch-none select-none pointer-events-auto";
|
|
14075
14297
|
const getHandleActiveClass = (side) => activeSide === side ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
|
|
14076
|
-
return /* @__PURE__ */
|
|
14298
|
+
return /* @__PURE__ */ jsxs29(
|
|
14077
14299
|
"div",
|
|
14078
14300
|
{
|
|
14079
14301
|
ref: refs.setFloating,
|
|
@@ -14085,14 +14307,14 @@ var SpacerScale = ({ getReferenceRect }) => {
|
|
|
14085
14307
|
},
|
|
14086
14308
|
className: "relative pointer-events-none",
|
|
14087
14309
|
children: [
|
|
14088
|
-
(activeSide === null || activeSide === "top") && /* @__PURE__ */
|
|
14310
|
+
(activeSide === null || activeSide === "top") && /* @__PURE__ */ jsx46(
|
|
14089
14311
|
"div",
|
|
14090
14312
|
{
|
|
14091
14313
|
onPointerDown: (e) => handlePointerDown(e, "top"),
|
|
14092
14314
|
className: `w-[18px] h-[8px] cursor-ns-resize ${handleBaseClass} left-1/2 -translate-x-1/2 -top-[4px] ${getHandleActiveClass("top")}`
|
|
14093
14315
|
}
|
|
14094
14316
|
),
|
|
14095
|
-
(activeSide === null || activeSide === "bottom") && /* @__PURE__ */
|
|
14317
|
+
(activeSide === null || activeSide === "bottom") && /* @__PURE__ */ jsx46(
|
|
14096
14318
|
"div",
|
|
14097
14319
|
{
|
|
14098
14320
|
onPointerDown: (e) => handlePointerDown(e, "bottom"),
|
|
@@ -14105,19 +14327,19 @@ var SpacerScale = ({ getReferenceRect }) => {
|
|
|
14105
14327
|
};
|
|
14106
14328
|
|
|
14107
14329
|
// src/core/editor/components/scaling/column-scale.tsx
|
|
14108
|
-
import { useMemo as
|
|
14109
|
-
import { Fragment as Fragment17, jsx as
|
|
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";
|
|
14110
14332
|
var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
14111
|
-
const [activeDivider, setActiveDivider] =
|
|
14112
|
-
const [columnRects, setColumnRects] =
|
|
14333
|
+
const [activeDivider, setActiveDivider] = useState14(null);
|
|
14334
|
+
const [columnRects, setColumnRects] = useState14([]);
|
|
14113
14335
|
const { template, setIsScaling, setFocusIdx, stopTextEditing } = useEditorStore();
|
|
14114
|
-
const columnWidths =
|
|
14336
|
+
const columnWidths = useMemo17(() => {
|
|
14115
14337
|
if (!template) return [];
|
|
14116
14338
|
const sectionColumn = getValueByIdx(template, sectionColumnIdx);
|
|
14117
14339
|
return sectionColumn?.data?.value?.columnWidths || [];
|
|
14118
14340
|
}, [template, sectionColumnIdx]);
|
|
14119
|
-
const dragRef =
|
|
14120
|
-
const updateColumnRects =
|
|
14341
|
+
const dragRef = useRef10(null);
|
|
14342
|
+
const updateColumnRects = useCallback16(() => {
|
|
14121
14343
|
if (!shadowRoot) return;
|
|
14122
14344
|
const allColumns = shadowRoot.querySelectorAll(".node-type-column");
|
|
14123
14345
|
const matchingColumns = [];
|
|
@@ -14149,7 +14371,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
|
14149
14371
|
});
|
|
14150
14372
|
setColumnRects(rects);
|
|
14151
14373
|
}, [shadowRoot, sectionColumnIdx]);
|
|
14152
|
-
|
|
14374
|
+
useEffect18(() => {
|
|
14153
14375
|
updateColumnRects();
|
|
14154
14376
|
let animationId;
|
|
14155
14377
|
const updateLoop = () => {
|
|
@@ -14162,7 +14384,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
|
14162
14384
|
const parseWidth = (width) => {
|
|
14163
14385
|
return parseFloat(width.replace("%", ""));
|
|
14164
14386
|
};
|
|
14165
|
-
const handlePointerDown =
|
|
14387
|
+
const handlePointerDown = useCallback16((e, dividerIndex) => {
|
|
14166
14388
|
e.preventDefault();
|
|
14167
14389
|
e.stopPropagation();
|
|
14168
14390
|
stopTextEditing();
|
|
@@ -14188,7 +14410,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
|
14188
14410
|
document.addEventListener("pointermove", handlePointerMove);
|
|
14189
14411
|
document.addEventListener("pointerup", handlePointerUp);
|
|
14190
14412
|
}, [columnRects, columnWidths, setIsScaling]);
|
|
14191
|
-
const handlePointerMove =
|
|
14413
|
+
const handlePointerMove = useCallback16((e) => {
|
|
14192
14414
|
if (!dragRef.current) return;
|
|
14193
14415
|
const { startX, leftColIndex, rightColIndex, startLeftWidth, startRightWidth, sectionWidth, allWidths } = dragRef.current;
|
|
14194
14416
|
const deltaX = e.clientX - startX;
|
|
@@ -14222,14 +14444,14 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
|
14222
14444
|
}
|
|
14223
14445
|
});
|
|
14224
14446
|
}, [sectionColumnIdx]);
|
|
14225
|
-
const handlePointerUp =
|
|
14447
|
+
const handlePointerUp = useCallback16(() => {
|
|
14226
14448
|
setActiveDivider(null);
|
|
14227
14449
|
setIsScaling(false);
|
|
14228
14450
|
dragRef.current = null;
|
|
14229
14451
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
14230
14452
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
14231
14453
|
}, [handlePointerMove, setIsScaling]);
|
|
14232
|
-
|
|
14454
|
+
useEffect18(() => {
|
|
14233
14455
|
return () => {
|
|
14234
14456
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
14235
14457
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
@@ -14240,7 +14462,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
|
14240
14462
|
}
|
|
14241
14463
|
const handleBaseClass = "bg-background shadow-md border rounded-full touch-none select-none pointer-events-auto";
|
|
14242
14464
|
const getHandleActiveClass = (index) => activeDivider === index ? "bg-blue-400 border-blue-300" : "hover:bg-blue-400 hover:border-blue-300";
|
|
14243
|
-
return /* @__PURE__ */
|
|
14465
|
+
return /* @__PURE__ */ jsx47(Fragment17, { children: columnRects.slice(0, -1).map((rect, index) => {
|
|
14244
14466
|
const nextRect = columnRects[index + 1];
|
|
14245
14467
|
const handleLeft = rect.right;
|
|
14246
14468
|
const handleTop = Math.min(rect.top, nextRect.top);
|
|
@@ -14248,7 +14470,7 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
|
14248
14470
|
if (activeDivider !== null && activeDivider !== index) {
|
|
14249
14471
|
return null;
|
|
14250
14472
|
}
|
|
14251
|
-
return /* @__PURE__ */
|
|
14473
|
+
return /* @__PURE__ */ jsx47(
|
|
14252
14474
|
"div",
|
|
14253
14475
|
{
|
|
14254
14476
|
onPointerDown: (e) => handlePointerDown(e, index),
|
|
@@ -14268,9 +14490,9 @@ var ColumnScale = ({ sectionColumnIdx, shadowRoot }) => {
|
|
|
14268
14490
|
};
|
|
14269
14491
|
|
|
14270
14492
|
// src/core/editor/hooks/use-undo-redo-keyboard.ts
|
|
14271
|
-
import { useEffect as
|
|
14493
|
+
import { useEffect as useEffect19 } from "react";
|
|
14272
14494
|
function useUndoRedoKeyboard() {
|
|
14273
|
-
|
|
14495
|
+
useEffect19(() => {
|
|
14274
14496
|
const handler = (e) => {
|
|
14275
14497
|
const isMeta = e.metaKey || e.ctrlKey;
|
|
14276
14498
|
if (!isMeta || e.key.toLowerCase() !== "z") return;
|
|
@@ -14292,9 +14514,9 @@ function useUndoRedoKeyboard() {
|
|
|
14292
14514
|
|
|
14293
14515
|
// src/components/ui/spinner.tsx
|
|
14294
14516
|
import { Loader2Icon as Loader2Icon2 } from "lucide-react";
|
|
14295
|
-
import { jsx as
|
|
14517
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
14296
14518
|
function Spinner({ className, ...props }) {
|
|
14297
|
-
return /* @__PURE__ */
|
|
14519
|
+
return /* @__PURE__ */ jsx48(
|
|
14298
14520
|
Loader2Icon2,
|
|
14299
14521
|
{
|
|
14300
14522
|
role: "status",
|
|
@@ -14306,10 +14528,10 @@ function Spinner({ className, ...props }) {
|
|
|
14306
14528
|
}
|
|
14307
14529
|
|
|
14308
14530
|
// src/core/editor/components/preview.tsx
|
|
14309
|
-
import { EyeIcon } from "lucide-react";
|
|
14531
|
+
import { EyeIcon, SendIcon, Monitor, Smartphone } from "lucide-react";
|
|
14310
14532
|
|
|
14311
14533
|
// src/render/useMjmlCompiler.ts
|
|
14312
|
-
import { useState as
|
|
14534
|
+
import { useState as useState15, useCallback as useCallback17 } from "react";
|
|
14313
14535
|
async function compileMjml(mjml) {
|
|
14314
14536
|
console.log("Compiling MJML", mjml);
|
|
14315
14537
|
const response = await fetch("/api/mrender", {
|
|
@@ -14326,14 +14548,101 @@ async function compileMjml(mjml) {
|
|
|
14326
14548
|
}
|
|
14327
14549
|
|
|
14328
14550
|
// src/core/editor/components/preview.tsx
|
|
14329
|
-
import { useEffect as
|
|
14330
|
-
|
|
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";
|
|
14331
14637
|
function Preview() {
|
|
14332
|
-
const { template, setPreviewMode, previewMode, isPaidLevel } = useEditorStore();
|
|
14333
|
-
const [html, setHtml] =
|
|
14334
|
-
const [isLoading, setIsLoading] =
|
|
14335
|
-
const lastTemplateRef =
|
|
14336
|
-
|
|
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(() => {
|
|
14337
14646
|
if (typeof window === "undefined" || !previewMode) {
|
|
14338
14647
|
if (!previewMode) {
|
|
14339
14648
|
setHtml("");
|
|
@@ -14347,56 +14656,165 @@ function Preview() {
|
|
|
14347
14656
|
}
|
|
14348
14657
|
lastTemplateRef.current = templateString;
|
|
14349
14658
|
setIsLoading(true);
|
|
14659
|
+
const validatePreview = () => {
|
|
14660
|
+
const validations = validate_editor_onPreview(template, mergeFields);
|
|
14661
|
+
setPreviewValidations(validations);
|
|
14662
|
+
};
|
|
14350
14663
|
const convertMjml = async () => {
|
|
14351
14664
|
try {
|
|
14352
14665
|
const mjmlString = json2mjml(template, "production", { isPaidLevel });
|
|
14353
14666
|
console.log("MJML string:", mjmlString);
|
|
14354
14667
|
const result = await compileMjml(mjmlString);
|
|
14668
|
+
console.log("MJML errors:", result);
|
|
14669
|
+
setMjmlErrors(result.errors ?? []);
|
|
14355
14670
|
if (result.errors?.length > 0) {
|
|
14356
|
-
console.warn("MJML warnings:", result.errors);
|
|
14671
|
+
console.warn("MJML warnings 1:", result.errors);
|
|
14357
14672
|
}
|
|
14358
14673
|
console.log(result.html);
|
|
14359
14674
|
setHtml(result.html);
|
|
14360
14675
|
} catch (error) {
|
|
14361
14676
|
console.error("MJML compilation error:", error);
|
|
14677
|
+
setMjmlErrors([]);
|
|
14362
14678
|
setHtml('<p style="color: red; padding: 20px;">Error generating preview</p>');
|
|
14363
14679
|
} finally {
|
|
14364
14680
|
setIsLoading(false);
|
|
14365
14681
|
}
|
|
14366
14682
|
};
|
|
14683
|
+
validatePreview();
|
|
14367
14684
|
convertMjml();
|
|
14368
14685
|
}, [template, previewMode]);
|
|
14369
|
-
|
|
14370
|
-
|
|
14371
|
-
|
|
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(
|
|
14372
14690
|
Button,
|
|
14373
14691
|
{
|
|
14374
14692
|
variant: "ghost",
|
|
14375
14693
|
className: "shadow-none transition-none cursor-pointer",
|
|
14376
14694
|
size: "icon",
|
|
14377
14695
|
onClick: () => setPreviewMode(true),
|
|
14378
|
-
children: /* @__PURE__ */
|
|
14696
|
+
children: /* @__PURE__ */ jsx49(EyeIcon, {})
|
|
14379
14697
|
}
|
|
14380
14698
|
) }),
|
|
14381
|
-
/* @__PURE__ */
|
|
14699
|
+
/* @__PURE__ */ jsx49(TooltipContent, { side: "bottom", className: "z-51", children: "Preview" })
|
|
14382
14700
|
] }),
|
|
14383
|
-
/* @__PURE__ */
|
|
14384
|
-
|
|
14385
|
-
|
|
14386
|
-
|
|
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
|
+
)
|
|
14387
14805
|
] });
|
|
14388
14806
|
}
|
|
14389
14807
|
|
|
14390
14808
|
// src/core/editor/components/history.tsx
|
|
14391
14809
|
import { Redo2Icon, Undo2Icon } from "lucide-react";
|
|
14392
|
-
import { Fragment as Fragment18, jsx as
|
|
14810
|
+
import { Fragment as Fragment18, jsx as jsx50, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
14393
14811
|
var History = () => {
|
|
14394
14812
|
const { undo, redo } = useEditorStore();
|
|
14395
14813
|
const canUndo = useEditorStore((s) => s.historyIndex > 0);
|
|
14396
14814
|
const canRedo = useEditorStore((s) => s.historyIndex < s.history.length - 1);
|
|
14397
|
-
return /* @__PURE__ */
|
|
14398
|
-
/* @__PURE__ */
|
|
14399
|
-
/* @__PURE__ */
|
|
14815
|
+
return /* @__PURE__ */ jsxs31(Fragment18, { children: [
|
|
14816
|
+
/* @__PURE__ */ jsxs31(Tooltip, { children: [
|
|
14817
|
+
/* @__PURE__ */ jsx50(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(
|
|
14400
14818
|
Button,
|
|
14401
14819
|
{
|
|
14402
14820
|
variant: "ghost",
|
|
@@ -14404,13 +14822,13 @@ var History = () => {
|
|
|
14404
14822
|
size: "icon",
|
|
14405
14823
|
disabled: !canUndo,
|
|
14406
14824
|
onClick: undo,
|
|
14407
|
-
children: /* @__PURE__ */
|
|
14825
|
+
children: /* @__PURE__ */ jsx50(Undo2Icon, {})
|
|
14408
14826
|
}
|
|
14409
14827
|
) }),
|
|
14410
|
-
/* @__PURE__ */
|
|
14828
|
+
/* @__PURE__ */ jsx50(TooltipContent, { side: "bottom", children: "Undo (Ctrl+Z)" })
|
|
14411
14829
|
] }),
|
|
14412
|
-
/* @__PURE__ */
|
|
14413
|
-
/* @__PURE__ */
|
|
14830
|
+
/* @__PURE__ */ jsxs31(Tooltip, { children: [
|
|
14831
|
+
/* @__PURE__ */ jsx50(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(
|
|
14414
14832
|
Button,
|
|
14415
14833
|
{
|
|
14416
14834
|
variant: "ghost",
|
|
@@ -14418,16 +14836,16 @@ var History = () => {
|
|
|
14418
14836
|
size: "icon",
|
|
14419
14837
|
disabled: !canRedo,
|
|
14420
14838
|
onClick: redo,
|
|
14421
|
-
children: /* @__PURE__ */
|
|
14839
|
+
children: /* @__PURE__ */ jsx50(Redo2Icon, {})
|
|
14422
14840
|
}
|
|
14423
14841
|
) }),
|
|
14424
|
-
/* @__PURE__ */
|
|
14842
|
+
/* @__PURE__ */ jsx50(TooltipContent, { side: "bottom", children: "Redo (Ctrl+Shift+Z)" })
|
|
14425
14843
|
] })
|
|
14426
14844
|
] });
|
|
14427
14845
|
};
|
|
14428
14846
|
|
|
14429
14847
|
// src/core/index.tsx
|
|
14430
|
-
import { jsx as
|
|
14848
|
+
import { jsx as jsx51, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
14431
14849
|
var MAILLOW_EMAIL_EDITOR_VERSION = "0.0.1";
|
|
14432
14850
|
function getSectionColumnIdx(idx, template) {
|
|
14433
14851
|
let current = idx;
|
|
@@ -14463,6 +14881,20 @@ function getCompanyFooterSection(template) {
|
|
|
14463
14881
|
}
|
|
14464
14882
|
return null;
|
|
14465
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
|
+
}
|
|
14466
14898
|
function Editor({ setEditorLoading }) {
|
|
14467
14899
|
useUndoRedoKeyboard();
|
|
14468
14900
|
const template = useEditorStore((state) => state.template);
|
|
@@ -14474,6 +14906,8 @@ function Editor({ setEditorLoading }) {
|
|
|
14474
14906
|
const dataTransfer = useEditorStore((state) => state.dataTransfer);
|
|
14475
14907
|
const textEditing = useEditorStore((state) => state.textEditing);
|
|
14476
14908
|
const isScaling = useEditorStore((state) => state.isScaling);
|
|
14909
|
+
const canvasBackgroundColor = useEditorStore((s) => s.template?.content?.[0]?.attributes?.["background-color"]) || "#f5f5f5";
|
|
14910
|
+
const renderSyncNeeded = useEditorStore((state) => state.renderSyncNeeded);
|
|
14477
14911
|
const setFocusIdx = useEditorStore((state) => state.setFocusIdx);
|
|
14478
14912
|
const setHoverIdx = useEditorStore((state) => state.setHoverIdx);
|
|
14479
14913
|
const updateElementContent = useEditorStore((state) => state.updateElementContent);
|
|
@@ -14491,33 +14925,40 @@ function Editor({ setEditorLoading }) {
|
|
|
14491
14925
|
const startTextEditing = useEditorStore((state) => state.startTextEditing);
|
|
14492
14926
|
const pendingTextEditRequest = useEditorStore((state) => state.pendingTextEditRequest);
|
|
14493
14927
|
const clearPendingTextEditRequest = useEditorStore((state) => state.clearPendingTextEditRequest);
|
|
14494
|
-
const [renderData, setRenderData] =
|
|
14495
|
-
const [isEditing, setIsEditing] =
|
|
14496
|
-
const [dropIndicator, setDropIndicator] =
|
|
14497
|
-
const [dropTargetIdx, setDropTargetIdx] =
|
|
14498
|
-
const shadowRootRef =
|
|
14499
|
-
const [hasSelectedElement, setHasSelectedElement] =
|
|
14500
|
-
const dragParentIdxRef =
|
|
14501
|
-
const dragPositionIndexRef =
|
|
14502
|
-
const createNewSectionRef =
|
|
14503
|
-
const splitAtParagraphRef =
|
|
14504
|
-
const isHorizontalDropRef =
|
|
14505
|
-
const horizontalDropPositionRef =
|
|
14506
|
-
const isSplitSectionDropRef =
|
|
14507
|
-
const splitSectionAtElementRef =
|
|
14508
|
-
const templateCacheRef =
|
|
14509
|
-
const parentSectionCacheRef =
|
|
14510
|
-
const sectionElementCacheRef =
|
|
14511
|
-
const sectionRectCacheRef =
|
|
14512
|
-
const companyFooterCacheRef =
|
|
14513
|
-
const lastSyncedTemplateRef =
|
|
14514
|
-
const prevTextEditingIdxRef =
|
|
14515
|
-
|
|
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(() => {
|
|
14516
14953
|
const currentIdx = textEditing?.idx ?? null;
|
|
14517
14954
|
const prevIdx = prevTextEditingIdxRef.current;
|
|
14518
14955
|
const switchedTarget = currentIdx !== null && prevIdx !== null && currentIdx !== prevIdx;
|
|
14519
14956
|
prevTextEditingIdxRef.current = currentIdx;
|
|
14520
|
-
|
|
14957
|
+
const forceSync = renderSyncNeeded > lastRenderSyncNeededRef.current;
|
|
14958
|
+
if (forceSync) {
|
|
14959
|
+
lastRenderSyncNeededRef.current = renderSyncNeeded;
|
|
14960
|
+
}
|
|
14961
|
+
if (forceSync || !isEditing && (!textEditing || switchedTarget)) {
|
|
14521
14962
|
if (template === lastSyncedTemplateRef.current) {
|
|
14522
14963
|
return;
|
|
14523
14964
|
}
|
|
@@ -14526,13 +14967,13 @@ function Editor({ setEditorLoading }) {
|
|
|
14526
14967
|
}
|
|
14527
14968
|
lastSyncedTemplateRef.current = template;
|
|
14528
14969
|
}
|
|
14529
|
-
}, [template, renderData, isEditing, textEditing]);
|
|
14530
|
-
|
|
14970
|
+
}, [template, renderData, isEditing, textEditing, renderSyncNeeded]);
|
|
14971
|
+
useEffect21(() => {
|
|
14531
14972
|
if (renderData && setEditorLoading) {
|
|
14532
14973
|
setEditorLoading(false);
|
|
14533
14974
|
}
|
|
14534
14975
|
}, [renderData, setEditorLoading]);
|
|
14535
|
-
|
|
14976
|
+
useEffect21(() => {
|
|
14536
14977
|
if (!pendingTextEditRequest || !shadowRootRef.current) return;
|
|
14537
14978
|
const { idx, cursorPosition } = pendingTextEditRequest;
|
|
14538
14979
|
const blockNode = shadowRootRef.current.querySelector(`.node-idx-${CSS.escape(idx)}`);
|
|
@@ -14581,7 +15022,7 @@ function Editor({ setEditorLoading }) {
|
|
|
14581
15022
|
startTextEditing({ idx, getReferenceRect: getReferenceRect2, getShadowElement, initialWidth: blockRect.width, initialHeight: blockRect.height, clickX, clickY, content, styles, cursorPosition });
|
|
14582
15023
|
clearPendingTextEditRequest();
|
|
14583
15024
|
}, [pendingTextEditRequest, clearPendingTextEditRequest, startTextEditing]);
|
|
14584
|
-
|
|
15025
|
+
useEffect21(() => {
|
|
14585
15026
|
if (isDragging && dataTransfer) {
|
|
14586
15027
|
const currentTemplate = useEditorStore.getState().template;
|
|
14587
15028
|
templateCacheRef.current = currentTemplate;
|
|
@@ -14597,9 +15038,9 @@ function Editor({ setEditorLoading }) {
|
|
|
14597
15038
|
sectionRectCacheRef.current.clear();
|
|
14598
15039
|
}
|
|
14599
15040
|
}, [isDragging, dataTransfer]);
|
|
14600
|
-
const [html, setHtml] =
|
|
14601
|
-
const lastRenderDataRef =
|
|
14602
|
-
|
|
15041
|
+
const [html, setHtml] = useState17("");
|
|
15042
|
+
const lastRenderDataRef = useRef12("");
|
|
15043
|
+
useEffect21(() => {
|
|
14603
15044
|
if (typeof window === "undefined" || !renderData) {
|
|
14604
15045
|
setHtml("");
|
|
14605
15046
|
lastRenderDataRef.current = "";
|
|
@@ -14626,13 +15067,13 @@ function Editor({ setEditorLoading }) {
|
|
|
14626
15067
|
};
|
|
14627
15068
|
convertMjml();
|
|
14628
15069
|
}, [renderData]);
|
|
14629
|
-
const debouncedUpdateContent =
|
|
15070
|
+
const debouncedUpdateContent = useMemo18(
|
|
14630
15071
|
() => debounce((contentIdx, content) => {
|
|
14631
15072
|
updateElementContent(contentIdx, content);
|
|
14632
15073
|
}, 200),
|
|
14633
15074
|
[updateElementContent]
|
|
14634
15075
|
);
|
|
14635
|
-
const handleElementClick =
|
|
15076
|
+
const handleElementClick = useCallback18(
|
|
14636
15077
|
(idx) => {
|
|
14637
15078
|
if (isInsideCompanyFooter(idx, template)) {
|
|
14638
15079
|
return;
|
|
@@ -14645,7 +15086,7 @@ function Editor({ setEditorLoading }) {
|
|
|
14645
15086
|
},
|
|
14646
15087
|
[setFocusIdx, template]
|
|
14647
15088
|
);
|
|
14648
|
-
const handleElementHover =
|
|
15089
|
+
const handleElementHover = useCallback18(
|
|
14649
15090
|
(idx) => {
|
|
14650
15091
|
if (!isDragging) {
|
|
14651
15092
|
if (idx) {
|
|
@@ -14659,19 +15100,19 @@ function Editor({ setEditorLoading }) {
|
|
|
14659
15100
|
},
|
|
14660
15101
|
[isDragging, setHoverIdx, template]
|
|
14661
15102
|
);
|
|
14662
|
-
const handleContentInput =
|
|
15103
|
+
const handleContentInput = useCallback18(
|
|
14663
15104
|
(contentIdx, content) => {
|
|
14664
15105
|
debouncedUpdateContent(contentIdx, content);
|
|
14665
15106
|
},
|
|
14666
15107
|
[debouncedUpdateContent]
|
|
14667
15108
|
);
|
|
14668
|
-
const handleEditingStart =
|
|
15109
|
+
const handleEditingStart = useCallback18(() => {
|
|
14669
15110
|
setIsEditing(true);
|
|
14670
15111
|
}, []);
|
|
14671
|
-
const handleEditingEnd =
|
|
15112
|
+
const handleEditingEnd = useCallback18(() => {
|
|
14672
15113
|
setIsEditing(false);
|
|
14673
15114
|
}, []);
|
|
14674
|
-
const handleSlashCommand =
|
|
15115
|
+
const handleSlashCommand = useCallback18(
|
|
14675
15116
|
(cursorRect) => {
|
|
14676
15117
|
setSlashCommand({
|
|
14677
15118
|
isActive: true,
|
|
@@ -14686,10 +15127,10 @@ function Editor({ setEditorLoading }) {
|
|
|
14686
15127
|
},
|
|
14687
15128
|
[setSlashCommand]
|
|
14688
15129
|
);
|
|
14689
|
-
const handleSlashCommandClose =
|
|
15130
|
+
const handleSlashCommandClose = useCallback18(() => {
|
|
14690
15131
|
clearSlashCommand();
|
|
14691
15132
|
}, [clearSlashCommand]);
|
|
14692
|
-
const handleTextEditStart =
|
|
15133
|
+
const handleTextEditStart = useCallback18(
|
|
14693
15134
|
(idx, initialWidth, initialHeight, clickX, clickY, content, styles) => {
|
|
14694
15135
|
const getReferenceRect2 = () => {
|
|
14695
15136
|
if (!shadowRootRef.current) return null;
|
|
@@ -14704,11 +15145,11 @@ function Editor({ setEditorLoading }) {
|
|
|
14704
15145
|
},
|
|
14705
15146
|
[startTextEditing]
|
|
14706
15147
|
);
|
|
14707
|
-
const findParentSectionIdx =
|
|
15148
|
+
const findParentSectionIdx = useCallback18((idx) => {
|
|
14708
15149
|
const match = /^(content\.children\.\[\d+\])/.exec(idx);
|
|
14709
15150
|
return match ? match[1] : null;
|
|
14710
15151
|
}, []);
|
|
14711
|
-
const handleDragOver =
|
|
15152
|
+
const handleDragOver = useCallback18(
|
|
14712
15153
|
(_e, dragInfo) => {
|
|
14713
15154
|
const currentDataTransfer = useEditorStore.getState().dataTransfer;
|
|
14714
15155
|
if (!currentDataTransfer) return;
|
|
@@ -14717,6 +15158,11 @@ function Editor({ setEditorLoading }) {
|
|
|
14717
15158
|
setDropIndicator(null);
|
|
14718
15159
|
setDropTargetIdx(null);
|
|
14719
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;
|
|
14720
15166
|
return;
|
|
14721
15167
|
}
|
|
14722
15168
|
const template2 = templateCacheRef.current || useEditorStore.getState().template;
|
|
@@ -14748,21 +15194,64 @@ function Editor({ setEditorLoading }) {
|
|
|
14748
15194
|
}
|
|
14749
15195
|
}
|
|
14750
15196
|
if (hoveredType === "column" || hoveredType === "property-card" || hoveredType === "property-card-single-two" || hoveredType === "property-card-triple") {
|
|
14751
|
-
const
|
|
14752
|
-
if (
|
|
14753
|
-
const
|
|
14754
|
-
if (
|
|
14755
|
-
const
|
|
14756
|
-
if (
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
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
|
+
}
|
|
14761
15210
|
}
|
|
14762
15211
|
}
|
|
14763
15212
|
}
|
|
14764
15213
|
}
|
|
14765
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
|
+
}
|
|
14766
15255
|
const validParents = VALID_PARENT_TYPES[dragType] || [];
|
|
14767
15256
|
let parentIdx;
|
|
14768
15257
|
let positionIndex;
|
|
@@ -15119,10 +15608,51 @@ function Editor({ setEditorLoading }) {
|
|
|
15119
15608
|
[findParentSectionIdx]
|
|
15120
15609
|
// Only dependency is the helper function
|
|
15121
15610
|
);
|
|
15122
|
-
const handleDrop =
|
|
15611
|
+
const handleDrop = useCallback18(
|
|
15123
15612
|
(_e, _dragInfo) => {
|
|
15124
15613
|
const currentDataTransfer = useEditorStore.getState().dataTransfer;
|
|
15125
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
|
+
}
|
|
15126
15656
|
if (isHorizontalDropRef.current && horizontalDropPositionRef.current) {
|
|
15127
15657
|
const parentIdx2 = dragParentIdxRef.current;
|
|
15128
15658
|
const dropPosition = horizontalDropPositionRef.current;
|
|
@@ -15143,6 +15673,8 @@ function Editor({ setEditorLoading }) {
|
|
|
15143
15673
|
horizontalDropPositionRef.current = null;
|
|
15144
15674
|
isSplitSectionDropRef.current = false;
|
|
15145
15675
|
splitSectionAtElementRef.current = null;
|
|
15676
|
+
imageReplaceTargetRef.current = null;
|
|
15677
|
+
imagePreviewOriginalSrcRef.current = null;
|
|
15146
15678
|
templateCacheRef.current = null;
|
|
15147
15679
|
parentSectionCacheRef.current.clear();
|
|
15148
15680
|
sectionElementCacheRef.current.clear();
|
|
@@ -15203,6 +15735,8 @@ function Editor({ setEditorLoading }) {
|
|
|
15203
15735
|
splitAtParagraphRef.current = null;
|
|
15204
15736
|
isSplitSectionDropRef.current = false;
|
|
15205
15737
|
splitSectionAtElementRef.current = null;
|
|
15738
|
+
imageReplaceTargetRef.current = null;
|
|
15739
|
+
imagePreviewOriginalSrcRef.current = null;
|
|
15206
15740
|
templateCacheRef.current = null;
|
|
15207
15741
|
parentSectionCacheRef.current.clear();
|
|
15208
15742
|
sectionElementCacheRef.current.clear();
|
|
@@ -15258,7 +15792,7 @@ function Editor({ setEditorLoading }) {
|
|
|
15258
15792
|
},
|
|
15259
15793
|
[addElement, addElementInNewSection, moveElement, moveElementToNewSection, splitTextAndInsertElement, splitSectionAndInsertElement, setIsDragging, setIsDragButtonHovered, setDataTransfer, setHoverIdx]
|
|
15260
15794
|
);
|
|
15261
|
-
const handleDragLeave =
|
|
15795
|
+
const handleDragLeave = useCallback18(() => {
|
|
15262
15796
|
setDropIndicator(null);
|
|
15263
15797
|
setDropTargetIdx(null);
|
|
15264
15798
|
dragParentIdxRef.current = null;
|
|
@@ -15269,18 +15803,23 @@ function Editor({ setEditorLoading }) {
|
|
|
15269
15803
|
horizontalDropPositionRef.current = null;
|
|
15270
15804
|
isSplitSectionDropRef.current = false;
|
|
15271
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;
|
|
15272
15811
|
templateCacheRef.current = null;
|
|
15273
15812
|
parentSectionCacheRef.current.clear();
|
|
15274
15813
|
sectionElementCacheRef.current.clear();
|
|
15275
15814
|
sectionRectCacheRef.current.clear();
|
|
15276
15815
|
}, []);
|
|
15277
|
-
const handleShadowRootRef =
|
|
15816
|
+
const handleShadowRootRef = useCallback18((shadowRoot) => {
|
|
15278
15817
|
shadowRootRef.current = shadowRoot;
|
|
15279
15818
|
}, []);
|
|
15280
|
-
const handleSelectionRectChange =
|
|
15819
|
+
const handleSelectionRectChange = useCallback18((rect) => {
|
|
15281
15820
|
setHasSelectedElement(rect !== null);
|
|
15282
15821
|
}, []);
|
|
15283
|
-
const getReferenceRect =
|
|
15822
|
+
const getReferenceRect = useCallback18(() => {
|
|
15284
15823
|
if (!shadowRootRef.current || !focusIdx) return null;
|
|
15285
15824
|
const selectedEl = shadowRootRef.current.querySelector(
|
|
15286
15825
|
`.node-idx-${CSS.escape(focusIdx)}`
|
|
@@ -15308,14 +15847,14 @@ function Editor({ setEditorLoading }) {
|
|
|
15308
15847
|
}, [focusIdx]);
|
|
15309
15848
|
const selectedElement = focusIdx && renderData ? getValueByIdx(renderData, focusIdx) : null;
|
|
15310
15849
|
const canDragSelectedElement = selectedElement && selectedElement.type !== "column" && !(focusIdx && renderData && isInsideCompanyFooter(focusIdx, renderData));
|
|
15311
|
-
const showCompanyFooter =
|
|
15850
|
+
const showCompanyFooter = useMemo18(
|
|
15312
15851
|
() => template.content[0]?.data?.value?.showCompanyFooter ?? true,
|
|
15313
15852
|
[template.content[0]?.data?.value?.showCompanyFooter]
|
|
15314
15853
|
);
|
|
15315
15854
|
if (!html) {
|
|
15316
|
-
return /* @__PURE__ */
|
|
15855
|
+
return /* @__PURE__ */ jsx51("div", { className: "maillow-editor flex items-center justify-center h-[500px]", children: /* @__PURE__ */ jsx51(Spinner, {}) });
|
|
15317
15856
|
}
|
|
15318
|
-
return /* @__PURE__ */
|
|
15857
|
+
return /* @__PURE__ */ jsxs32(
|
|
15319
15858
|
"div",
|
|
15320
15859
|
{
|
|
15321
15860
|
className: "maillow-editor relative ",
|
|
@@ -15326,48 +15865,51 @@ function Editor({ setEditorLoading }) {
|
|
|
15326
15865
|
justifyContent: "center"
|
|
15327
15866
|
},
|
|
15328
15867
|
children: [
|
|
15329
|
-
/* @__PURE__ */
|
|
15868
|
+
/* @__PURE__ */ jsxs32(
|
|
15330
15869
|
"div",
|
|
15331
15870
|
{
|
|
15332
|
-
className: `editor-container rounded-b-[12px]
|
|
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%] `,
|
|
15333
15872
|
style: {
|
|
15334
|
-
width: "626px",
|
|
15335
15873
|
height: "100%",
|
|
15336
|
-
backgroundColor:
|
|
15874
|
+
backgroundColor: canvasBackgroundColor,
|
|
15337
15875
|
overflow: "auto"
|
|
15338
15876
|
},
|
|
15339
|
-
children:
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
|
|
15348
|
-
|
|
15349
|
-
|
|
15350
|
-
|
|
15351
|
-
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
|
|
15877
|
+
children: [
|
|
15878
|
+
/* @__PURE__ */ jsx51("div", { className: "w-full h-[2px] bg-black opacity-10" }),
|
|
15879
|
+
/* @__PURE__ */ jsx51(
|
|
15880
|
+
ShadowDomRenderer,
|
|
15881
|
+
{
|
|
15882
|
+
html,
|
|
15883
|
+
focusIdx,
|
|
15884
|
+
hoverIdx,
|
|
15885
|
+
dropIndicator,
|
|
15886
|
+
dropTargetIdx,
|
|
15887
|
+
isDragging,
|
|
15888
|
+
isDragButtonHovered,
|
|
15889
|
+
textEditingIdx: textEditing?.idx || null,
|
|
15890
|
+
showCompanyFooter,
|
|
15891
|
+
onElementClick: handleElementClick,
|
|
15892
|
+
onElementHover: handleElementHover,
|
|
15893
|
+
onContentInput: handleContentInput,
|
|
15894
|
+
onEditingStart: handleEditingStart,
|
|
15895
|
+
onEditingEnd: handleEditingEnd,
|
|
15896
|
+
onDragOver: handleDragOver,
|
|
15897
|
+
onDrop: handleDrop,
|
|
15898
|
+
onDragLeave: handleDragLeave,
|
|
15899
|
+
onSelectionRectChange: handleSelectionRectChange,
|
|
15900
|
+
onShadowRootRef: handleShadowRootRef,
|
|
15901
|
+
onSlashCommand: handleSlashCommand,
|
|
15902
|
+
onSlashCommandClose: handleSlashCommandClose,
|
|
15903
|
+
onTextEditStart: handleTextEditStart
|
|
15904
|
+
}
|
|
15905
|
+
)
|
|
15906
|
+
]
|
|
15366
15907
|
}
|
|
15367
15908
|
),
|
|
15368
|
-
/* @__PURE__ */
|
|
15369
|
-
/* @__PURE__ */
|
|
15370
|
-
|
|
15909
|
+
/* @__PURE__ */ jsx51(ElementsSuggestions, {}),
|
|
15910
|
+
/* @__PURE__ */ jsx51(MergeFieldSuggestions, {}),
|
|
15911
|
+
/* @__PURE__ */ jsx51(TiptapOverlay, {}),
|
|
15912
|
+
!isDragging && !isScaling && hasSelectedElement && focusIdx && selectedElement?.type && /* @__PURE__ */ jsx51(
|
|
15371
15913
|
ElementFloat,
|
|
15372
15914
|
{
|
|
15373
15915
|
getReferenceRect,
|
|
@@ -15375,7 +15917,7 @@ function Editor({ setEditorLoading }) {
|
|
|
15375
15917
|
elementType: selectedElement.type
|
|
15376
15918
|
}
|
|
15377
15919
|
),
|
|
15378
|
-
!isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */
|
|
15920
|
+
!isScaling && hasSelectedElement && focusIdx && canDragSelectedElement && !NOT_DRAGGABLE_ELEMENTS.includes(selectedElement.type) && /* @__PURE__ */ jsx51(
|
|
15379
15921
|
DragButton,
|
|
15380
15922
|
{
|
|
15381
15923
|
getReferenceRect,
|
|
@@ -15384,17 +15926,17 @@ function Editor({ setEditorLoading }) {
|
|
|
15384
15926
|
isDragging
|
|
15385
15927
|
}
|
|
15386
15928
|
),
|
|
15387
|
-
!isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "divider" && /* @__PURE__ */
|
|
15388
|
-
!isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "button" && /* @__PURE__ */
|
|
15389
|
-
!isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "image" && /* @__PURE__ */
|
|
15390
|
-
!isDragging && hasSelectedElement && focusIdx && selectedElement?.type === "space" && /* @__PURE__ */
|
|
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 }),
|
|
15391
15933
|
!isDragging && hasSelectedElement && focusIdx && renderData && (() => {
|
|
15392
15934
|
const sectionColumnIdx = getSectionColumnIdx(focusIdx, renderData);
|
|
15393
15935
|
if (!sectionColumnIdx) return null;
|
|
15394
15936
|
const sectionColumn = getValueByIdx(renderData, sectionColumnIdx);
|
|
15395
15937
|
if (!sectionColumn || sectionColumn.type !== "section-column") return null;
|
|
15396
15938
|
if (!sectionColumn.children || sectionColumn.children.length < 2) return null;
|
|
15397
|
-
return /* @__PURE__ */
|
|
15939
|
+
return /* @__PURE__ */ jsx51(
|
|
15398
15940
|
ColumnScale,
|
|
15399
15941
|
{
|
|
15400
15942
|
sectionColumnIdx,
|
|
@@ -15416,9 +15958,7 @@ export {
|
|
|
15416
15958
|
parseBorder,
|
|
15417
15959
|
formatBorder,
|
|
15418
15960
|
parsePrice,
|
|
15419
|
-
json2mjml,
|
|
15420
15961
|
MAX_TEMPLATE_SIZE,
|
|
15421
|
-
useEditorStore,
|
|
15422
15962
|
BUTTON_ALIGNMENTS,
|
|
15423
15963
|
ALIGNMENT_ICONS,
|
|
15424
15964
|
FONTS,
|
|
@@ -15436,6 +15976,9 @@ export {
|
|
|
15436
15976
|
MIN_LINE_HEIGHT,
|
|
15437
15977
|
MAX_LINE_HEIGHT,
|
|
15438
15978
|
LINE_HEIGHT_STEP,
|
|
15979
|
+
DEFAULT_PROPERTY_PLACEHOLDER_IMAGE,
|
|
15980
|
+
json2mjml,
|
|
15981
|
+
useEditorStore,
|
|
15439
15982
|
setupDragImage,
|
|
15440
15983
|
getElementDisplayName,
|
|
15441
15984
|
cn,
|