@yoamigo.com/core 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +101 -6
- package/dist/index.js +1522 -504
- package/dist/plugin.js +31 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -779,6 +779,7 @@ function ContentStoreProvider({
|
|
|
779
779
|
);
|
|
780
780
|
const [mode, setModeState] = useState(defaultMode);
|
|
781
781
|
const [listeners, setListeners] = useState(/* @__PURE__ */ new Set());
|
|
782
|
+
const [changeSourceMap, setChangeSourceMap] = useState({});
|
|
782
783
|
const [activeFieldId, setActiveFieldId] = useState(null);
|
|
783
784
|
useEffect(() => {
|
|
784
785
|
const handleContentUpdate = () => {
|
|
@@ -807,16 +808,21 @@ function ContentStoreProvider({
|
|
|
807
808
|
[content]
|
|
808
809
|
);
|
|
809
810
|
const setValue = useCallback(
|
|
810
|
-
(fieldId, value2) => {
|
|
811
|
+
(fieldId, value2, source = "ai") => {
|
|
811
812
|
setContent((prev) => {
|
|
812
813
|
const next = new Map(prev);
|
|
813
814
|
next.set(fieldId, value2);
|
|
814
815
|
return next;
|
|
815
816
|
});
|
|
817
|
+
setChangeSourceMap((prev) => ({ ...prev, [fieldId]: source }));
|
|
816
818
|
notifyListeners();
|
|
817
819
|
},
|
|
818
820
|
[notifyListeners]
|
|
819
821
|
);
|
|
822
|
+
const getChangeSource = useCallback(
|
|
823
|
+
(fieldId) => changeSourceMap[fieldId] || "initial",
|
|
824
|
+
[changeSourceMap]
|
|
825
|
+
);
|
|
820
826
|
const setMode = useCallback(
|
|
821
827
|
(newMode) => {
|
|
822
828
|
setModeState(newMode);
|
|
@@ -904,6 +910,7 @@ function ContentStoreProvider({
|
|
|
904
910
|
window.mpContentStore = {
|
|
905
911
|
getValue,
|
|
906
912
|
setValue,
|
|
913
|
+
getChangeSource,
|
|
907
914
|
getMode: () => mode,
|
|
908
915
|
setMode,
|
|
909
916
|
subscribe,
|
|
@@ -912,11 +919,12 @@ function ContentStoreProvider({
|
|
|
912
919
|
return () => {
|
|
913
920
|
delete window.mpContentStore;
|
|
914
921
|
};
|
|
915
|
-
}, [getValue, setValue, mode, setMode, subscribe, saveToWorker]);
|
|
922
|
+
}, [getValue, setValue, getChangeSource, mode, setMode, subscribe, saveToWorker]);
|
|
916
923
|
const getPages = useCallback(() => pages, [pages]);
|
|
917
924
|
const value = {
|
|
918
925
|
getValue,
|
|
919
926
|
setValue,
|
|
927
|
+
getChangeSource,
|
|
920
928
|
mode,
|
|
921
929
|
setMode,
|
|
922
930
|
subscribe,
|
|
@@ -956,10 +964,60 @@ function ContentStoreProvider2({ children }) {
|
|
|
956
964
|
}
|
|
957
965
|
|
|
958
966
|
// src/components/YaText.tsx
|
|
959
|
-
import { useEffect as
|
|
960
|
-
import { createPortal as
|
|
967
|
+
import { useEffect as useEffect6, useRef as useRef6, useState as useState5, useCallback as useCallback7 } from "react";
|
|
968
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
961
969
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
962
|
-
|
|
970
|
+
|
|
971
|
+
// src/components/ControlledBubbleMenu.tsx
|
|
972
|
+
import { useFloating, autoUpdate, offset, flip, shift } from "@floating-ui/react";
|
|
973
|
+
import { isNodeSelection, posToDOMRect } from "@tiptap/core";
|
|
974
|
+
import { useLayoutEffect } from "react";
|
|
975
|
+
import { createPortal } from "react-dom";
|
|
976
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
977
|
+
function ControlledBubbleMenu({ editor, open, children, className }) {
|
|
978
|
+
const { floatingStyles, refs, isPositioned } = useFloating({
|
|
979
|
+
open,
|
|
980
|
+
// Required for isPositioned to work
|
|
981
|
+
strategy: "fixed",
|
|
982
|
+
whileElementsMounted: autoUpdate,
|
|
983
|
+
placement: "top",
|
|
984
|
+
middleware: [
|
|
985
|
+
offset({ mainAxis: 8 }),
|
|
986
|
+
flip({
|
|
987
|
+
padding: 8,
|
|
988
|
+
fallbackPlacements: ["bottom", "top-start", "bottom-start", "top-end", "bottom-end"]
|
|
989
|
+
}),
|
|
990
|
+
shift({ padding: 8 })
|
|
991
|
+
]
|
|
992
|
+
});
|
|
993
|
+
useLayoutEffect(() => {
|
|
994
|
+
if (!open) return;
|
|
995
|
+
const { ranges } = editor.state.selection;
|
|
996
|
+
const from = Math.min(...ranges.map((range) => range.$from.pos));
|
|
997
|
+
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
|
998
|
+
refs.setReference({
|
|
999
|
+
getBoundingClientRect() {
|
|
1000
|
+
if (isNodeSelection(editor.state.selection)) {
|
|
1001
|
+
const node = editor.view.nodeDOM(from);
|
|
1002
|
+
if (node) return node.getBoundingClientRect();
|
|
1003
|
+
}
|
|
1004
|
+
return posToDOMRect(editor.view, from, to);
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
}, [refs, editor.view, editor.state.selection, open]);
|
|
1008
|
+
if (!open) return null;
|
|
1009
|
+
const style = {
|
|
1010
|
+
...floatingStyles,
|
|
1011
|
+
opacity: isPositioned ? 1 : 0,
|
|
1012
|
+
transition: "opacity 0.15s ease"
|
|
1013
|
+
};
|
|
1014
|
+
return createPortal(
|
|
1015
|
+
/* @__PURE__ */ jsx3("div", { ref: refs.setFloating, style, className, children }),
|
|
1016
|
+
document.body
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// src/components/YaText.tsx
|
|
963
1021
|
import StarterKit from "@tiptap/starter-kit";
|
|
964
1022
|
import Link from "@tiptap/extension-link";
|
|
965
1023
|
import { TextStyle } from "@tiptap/extension-text-style";
|
|
@@ -967,9 +1025,9 @@ import { Extension } from "@tiptap/core";
|
|
|
967
1025
|
|
|
968
1026
|
// src/components/SafeHtml.tsx
|
|
969
1027
|
import { useEffect as useEffect2, useRef as useRef2, useState as useState2, useCallback as useCallback2 } from "react";
|
|
970
|
-
import { createPortal } from "react-dom";
|
|
1028
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
971
1029
|
import DOMPurify from "dompurify";
|
|
972
|
-
import { Fragment, jsx as
|
|
1030
|
+
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
973
1031
|
var ALLOWED_TAGS = ["strong", "em", "a", "span", "br", "b", "i", "u"];
|
|
974
1032
|
var ALLOWED_ATTR = ["href", "style", "class", "target", "rel"];
|
|
975
1033
|
DOMPurify.addHook("uponSanitizeAttribute", (_node, data) => {
|
|
@@ -1015,7 +1073,9 @@ function LinkIcon() {
|
|
|
1015
1073
|
return /* @__PURE__ */ jsxs(
|
|
1016
1074
|
"svg",
|
|
1017
1075
|
{
|
|
1018
|
-
className: "
|
|
1076
|
+
className: "ya-link-popover-icon",
|
|
1077
|
+
width: "14",
|
|
1078
|
+
height: "14",
|
|
1019
1079
|
viewBox: "0 0 24 24",
|
|
1020
1080
|
fill: "none",
|
|
1021
1081
|
stroke: "currentColor",
|
|
@@ -1023,8 +1083,8 @@ function LinkIcon() {
|
|
|
1023
1083
|
strokeLinecap: "round",
|
|
1024
1084
|
strokeLinejoin: "round",
|
|
1025
1085
|
children: [
|
|
1026
|
-
/* @__PURE__ */
|
|
1027
|
-
/* @__PURE__ */
|
|
1086
|
+
/* @__PURE__ */ jsx4("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
|
|
1087
|
+
/* @__PURE__ */ jsx4("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
1028
1088
|
]
|
|
1029
1089
|
}
|
|
1030
1090
|
);
|
|
@@ -1039,7 +1099,7 @@ function LinkPopover({
|
|
|
1039
1099
|
return /* @__PURE__ */ jsxs(
|
|
1040
1100
|
"div",
|
|
1041
1101
|
{
|
|
1042
|
-
className: "
|
|
1102
|
+
className: "ya-link-popover",
|
|
1043
1103
|
style: {
|
|
1044
1104
|
top: position.top,
|
|
1045
1105
|
left: position.left
|
|
@@ -1056,10 +1116,10 @@ function LinkPopover({
|
|
|
1056
1116
|
}
|
|
1057
1117
|
},
|
|
1058
1118
|
children: [
|
|
1059
|
-
/* @__PURE__ */
|
|
1060
|
-
/* @__PURE__ */ jsxs("span", { className: "
|
|
1061
|
-
/* @__PURE__ */
|
|
1062
|
-
/* @__PURE__ */
|
|
1119
|
+
/* @__PURE__ */ jsx4(LinkIcon, {}),
|
|
1120
|
+
/* @__PURE__ */ jsxs("span", { className: "ya-link-popover-text", children: [
|
|
1121
|
+
/* @__PURE__ */ jsx4("span", { className: "ya-link-popover-prefix", children: "Go to " }),
|
|
1122
|
+
/* @__PURE__ */ jsx4("span", { className: "ya-link-popover-name", children: displayText })
|
|
1063
1123
|
] })
|
|
1064
1124
|
]
|
|
1065
1125
|
}
|
|
@@ -1159,7 +1219,7 @@ function SafeHtml({ content, className, mode = "read-only" }) {
|
|
|
1159
1219
|
};
|
|
1160
1220
|
}, [mode, scheduleHide]);
|
|
1161
1221
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1162
|
-
/* @__PURE__ */
|
|
1222
|
+
/* @__PURE__ */ jsx4(
|
|
1163
1223
|
"span",
|
|
1164
1224
|
{
|
|
1165
1225
|
ref: containerRef,
|
|
@@ -1167,8 +1227,8 @@ function SafeHtml({ content, className, mode = "read-only" }) {
|
|
|
1167
1227
|
dangerouslySetInnerHTML: { __html: sanitized }
|
|
1168
1228
|
}
|
|
1169
1229
|
),
|
|
1170
|
-
mode === "inline-edit" && popoverState.isVisible &&
|
|
1171
|
-
/* @__PURE__ */
|
|
1230
|
+
mode === "inline-edit" && popoverState.isVisible && createPortal2(
|
|
1231
|
+
/* @__PURE__ */ jsx4(
|
|
1172
1232
|
LinkPopover,
|
|
1173
1233
|
{
|
|
1174
1234
|
displayText: popoverState.displayText,
|
|
@@ -1191,7 +1251,7 @@ import { useState as useState3, useEffect as useEffect3, useRef as useRef4, useC
|
|
|
1191
1251
|
|
|
1192
1252
|
// src/contexts/AIEditContext.tsx
|
|
1193
1253
|
import { createContext as createContext3, useContext as useContext3, useCallback as useCallback3, useRef as useRef3, useMemo } from "react";
|
|
1194
|
-
import { jsx as
|
|
1254
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1195
1255
|
var AIEditContext = createContext3(null);
|
|
1196
1256
|
function useAIEditContext() {
|
|
1197
1257
|
const context = useContext3(AIEditContext);
|
|
@@ -1313,13 +1373,14 @@ function AIEditProvider({ children, staggerDelay = 100 }) {
|
|
|
1313
1373
|
}),
|
|
1314
1374
|
[queueAnimation, cancelAnimation, isAnimating, getAnimationState, subscribe, completeAnimation]
|
|
1315
1375
|
);
|
|
1316
|
-
return /* @__PURE__ */
|
|
1376
|
+
return /* @__PURE__ */ jsx5(AIEditContext.Provider, { value, children });
|
|
1317
1377
|
}
|
|
1318
1378
|
|
|
1319
1379
|
// src/hooks/useAIEditAnimation.ts
|
|
1320
1380
|
function useAIEditAnimation(fieldId, value, options) {
|
|
1321
1381
|
const { enabled = true, strategy, maxDuration = 2e3, onStart, onComplete } = options;
|
|
1322
1382
|
const context = useAIEditContextOptional();
|
|
1383
|
+
const { getChangeSource } = useContentStore();
|
|
1323
1384
|
const previousValueRef = useRef4(value);
|
|
1324
1385
|
const isFirstRender = useRef4(true);
|
|
1325
1386
|
const [phase, setPhase] = useState3("idle");
|
|
@@ -1374,6 +1435,16 @@ function useAIEditAnimation(fieldId, value, options) {
|
|
|
1374
1435
|
previousValueRef.current = value;
|
|
1375
1436
|
return;
|
|
1376
1437
|
}
|
|
1438
|
+
const source = getChangeSource(fieldId);
|
|
1439
|
+
if (source === "user") {
|
|
1440
|
+
setDisplayValue(value);
|
|
1441
|
+
previousValueRef.current = value;
|
|
1442
|
+
setPhase("complete");
|
|
1443
|
+
setTimeout(() => {
|
|
1444
|
+
setPhase("idle");
|
|
1445
|
+
}, 400);
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1377
1448
|
const oldValue = previousValueRef.current;
|
|
1378
1449
|
const newValue = value;
|
|
1379
1450
|
if (!strategy.canAnimate(oldValue, newValue)) {
|
|
@@ -1402,7 +1473,7 @@ function useAIEditAnimation(fieldId, value, options) {
|
|
|
1402
1473
|
cancelAnimationFrame(animationFrameRef.current);
|
|
1403
1474
|
}
|
|
1404
1475
|
};
|
|
1405
|
-
}, [value, enabled, strategy, context, fieldId, maxDuration, onStart, runAnimation]);
|
|
1476
|
+
}, [value, enabled, strategy, context, fieldId, maxDuration, onStart, runAnimation, getChangeSource]);
|
|
1406
1477
|
useEffect3(() => {
|
|
1407
1478
|
return () => {
|
|
1408
1479
|
if (animationFrameRef.current !== null) {
|
|
@@ -1418,7 +1489,8 @@ function useAIEditAnimation(fieldId, value, options) {
|
|
|
1418
1489
|
[phase]
|
|
1419
1490
|
);
|
|
1420
1491
|
return {
|
|
1421
|
-
|
|
1492
|
+
// When idle, return current value directly to avoid flash of stale state
|
|
1493
|
+
displayValue: phase === "idle" ? value : displayValue,
|
|
1422
1494
|
isAnimating: phase === "animating",
|
|
1423
1495
|
phase,
|
|
1424
1496
|
progress,
|
|
@@ -1700,6 +1772,373 @@ function useAnimatedText(fieldId, content, options = {}) {
|
|
|
1700
1772
|
};
|
|
1701
1773
|
}
|
|
1702
1774
|
|
|
1775
|
+
// src/components/BubbleIcons.tsx
|
|
1776
|
+
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1777
|
+
function BoldIcon({ size = 16, className }) {
|
|
1778
|
+
return /* @__PURE__ */ jsxs2(
|
|
1779
|
+
"svg",
|
|
1780
|
+
{
|
|
1781
|
+
width: size,
|
|
1782
|
+
height: size,
|
|
1783
|
+
viewBox: "0 0 24 24",
|
|
1784
|
+
fill: "none",
|
|
1785
|
+
stroke: "currentColor",
|
|
1786
|
+
strokeWidth: "2.5",
|
|
1787
|
+
strokeLinecap: "round",
|
|
1788
|
+
strokeLinejoin: "round",
|
|
1789
|
+
className,
|
|
1790
|
+
children: [
|
|
1791
|
+
/* @__PURE__ */ jsx6("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
|
|
1792
|
+
/* @__PURE__ */ jsx6("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
|
|
1793
|
+
]
|
|
1794
|
+
}
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
function ItalicIcon({ size = 16, className }) {
|
|
1798
|
+
return /* @__PURE__ */ jsxs2(
|
|
1799
|
+
"svg",
|
|
1800
|
+
{
|
|
1801
|
+
width: size,
|
|
1802
|
+
height: size,
|
|
1803
|
+
viewBox: "0 0 24 24",
|
|
1804
|
+
fill: "none",
|
|
1805
|
+
stroke: "currentColor",
|
|
1806
|
+
strokeWidth: "2",
|
|
1807
|
+
strokeLinecap: "round",
|
|
1808
|
+
strokeLinejoin: "round",
|
|
1809
|
+
className,
|
|
1810
|
+
children: [
|
|
1811
|
+
/* @__PURE__ */ jsx6("line", { x1: "19", y1: "4", x2: "10", y2: "4" }),
|
|
1812
|
+
/* @__PURE__ */ jsx6("line", { x1: "14", y1: "20", x2: "5", y2: "20" }),
|
|
1813
|
+
/* @__PURE__ */ jsx6("line", { x1: "15", y1: "4", x2: "9", y2: "20" })
|
|
1814
|
+
]
|
|
1815
|
+
}
|
|
1816
|
+
);
|
|
1817
|
+
}
|
|
1818
|
+
function LinkIcon2({ size = 16, className }) {
|
|
1819
|
+
return /* @__PURE__ */ jsxs2(
|
|
1820
|
+
"svg",
|
|
1821
|
+
{
|
|
1822
|
+
width: size,
|
|
1823
|
+
height: size,
|
|
1824
|
+
viewBox: "0 0 24 24",
|
|
1825
|
+
fill: "none",
|
|
1826
|
+
stroke: "currentColor",
|
|
1827
|
+
strokeWidth: "2",
|
|
1828
|
+
strokeLinecap: "round",
|
|
1829
|
+
strokeLinejoin: "round",
|
|
1830
|
+
className,
|
|
1831
|
+
children: [
|
|
1832
|
+
/* @__PURE__ */ jsx6("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
|
|
1833
|
+
/* @__PURE__ */ jsx6("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
1834
|
+
]
|
|
1835
|
+
}
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
function ChevronDownIcon({ size = 12, className }) {
|
|
1839
|
+
return /* @__PURE__ */ jsx6(
|
|
1840
|
+
"svg",
|
|
1841
|
+
{
|
|
1842
|
+
width: size,
|
|
1843
|
+
height: size,
|
|
1844
|
+
viewBox: "0 0 24 24",
|
|
1845
|
+
fill: "none",
|
|
1846
|
+
stroke: "currentColor",
|
|
1847
|
+
strokeWidth: "2",
|
|
1848
|
+
strokeLinecap: "round",
|
|
1849
|
+
strokeLinejoin: "round",
|
|
1850
|
+
className,
|
|
1851
|
+
children: /* @__PURE__ */ jsx6("polyline", { points: "6 9 12 15 18 9" })
|
|
1852
|
+
}
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
// src/components/BubbleDropdown.tsx
|
|
1857
|
+
import { useEffect as useEffect4 } from "react";
|
|
1858
|
+
import { useFloating as useFloating2, autoUpdate as autoUpdate2, offset as offset2, flip as flip2, shift as shift2, useClick, useDismiss, useInteractions, FloatingPortal } from "@floating-ui/react";
|
|
1859
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1860
|
+
function BubbleDropdown({
|
|
1861
|
+
label,
|
|
1862
|
+
open,
|
|
1863
|
+
onOpenChange,
|
|
1864
|
+
children,
|
|
1865
|
+
triggerClassName = "",
|
|
1866
|
+
panelClassName = ""
|
|
1867
|
+
}) {
|
|
1868
|
+
const { refs, floatingStyles, context, isPositioned } = useFloating2({
|
|
1869
|
+
open,
|
|
1870
|
+
onOpenChange,
|
|
1871
|
+
placement: "bottom-start",
|
|
1872
|
+
strategy: "fixed",
|
|
1873
|
+
whileElementsMounted: autoUpdate2,
|
|
1874
|
+
middleware: [
|
|
1875
|
+
offset2({ mainAxis: 4 }),
|
|
1876
|
+
flip2({
|
|
1877
|
+
padding: 8,
|
|
1878
|
+
fallbackPlacements: ["bottom-end", "top-start", "top-end"]
|
|
1879
|
+
}),
|
|
1880
|
+
shift2({ padding: 8 })
|
|
1881
|
+
]
|
|
1882
|
+
});
|
|
1883
|
+
const click = useClick(context);
|
|
1884
|
+
const dismiss = useDismiss(context, {
|
|
1885
|
+
// Don't dismiss on ancestor scroll - we're inside a portaled bubble menu
|
|
1886
|
+
ancestorScroll: false
|
|
1887
|
+
});
|
|
1888
|
+
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss]);
|
|
1889
|
+
useEffect4(() => {
|
|
1890
|
+
if (!open) return;
|
|
1891
|
+
const handleKeyDown = (e) => {
|
|
1892
|
+
if (e.key === "Escape") {
|
|
1893
|
+
e.preventDefault();
|
|
1894
|
+
e.stopPropagation();
|
|
1895
|
+
onOpenChange(false);
|
|
1896
|
+
}
|
|
1897
|
+
};
|
|
1898
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1899
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1900
|
+
}, [open, onOpenChange]);
|
|
1901
|
+
const panelStyle = {
|
|
1902
|
+
...floatingStyles,
|
|
1903
|
+
opacity: isPositioned ? 1 : 0,
|
|
1904
|
+
transition: "opacity 0.15s ease"
|
|
1905
|
+
};
|
|
1906
|
+
const handleTriggerClick = (e) => {
|
|
1907
|
+
e.stopPropagation();
|
|
1908
|
+
};
|
|
1909
|
+
const handleTriggerMouseDown = (e) => {
|
|
1910
|
+
e.preventDefault();
|
|
1911
|
+
e.stopPropagation();
|
|
1912
|
+
};
|
|
1913
|
+
const handlePanelClick = (e) => {
|
|
1914
|
+
e.stopPropagation();
|
|
1915
|
+
};
|
|
1916
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1917
|
+
/* @__PURE__ */ jsxs3(
|
|
1918
|
+
"button",
|
|
1919
|
+
{
|
|
1920
|
+
ref: refs.setReference,
|
|
1921
|
+
type: "button",
|
|
1922
|
+
className: `ya-bubble-dropdown-trigger ${open ? "is-open" : ""} ${triggerClassName}`,
|
|
1923
|
+
...getReferenceProps({
|
|
1924
|
+
onClick: handleTriggerClick,
|
|
1925
|
+
onMouseDown: handleTriggerMouseDown
|
|
1926
|
+
}),
|
|
1927
|
+
children: [
|
|
1928
|
+
/* @__PURE__ */ jsx7("span", { className: "ya-bubble-dropdown-label", children: label }),
|
|
1929
|
+
/* @__PURE__ */ jsx7(ChevronDownIcon, { size: 10, className: `ya-bubble-dropdown-arrow ${open ? "is-open" : ""}` })
|
|
1930
|
+
]
|
|
1931
|
+
}
|
|
1932
|
+
),
|
|
1933
|
+
open && /* @__PURE__ */ jsx7(FloatingPortal, { children: /* @__PURE__ */ jsx7(
|
|
1934
|
+
"div",
|
|
1935
|
+
{
|
|
1936
|
+
ref: refs.setFloating,
|
|
1937
|
+
style: panelStyle,
|
|
1938
|
+
className: `ya-bubble-dropdown-panel ${panelClassName}`,
|
|
1939
|
+
...getFloatingProps({
|
|
1940
|
+
onClick: handlePanelClick
|
|
1941
|
+
}),
|
|
1942
|
+
children
|
|
1943
|
+
}
|
|
1944
|
+
) })
|
|
1945
|
+
] });
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// src/components/FontSizePicker.tsx
|
|
1949
|
+
import { useState as useState4, useEffect as useEffect5, useCallback as useCallback5, useRef as useRef5 } from "react";
|
|
1950
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1951
|
+
var SIZE_PRESETS = [
|
|
1952
|
+
{ name: "S", value: "0.875rem" },
|
|
1953
|
+
{ name: "M", value: "1rem" },
|
|
1954
|
+
{ name: "L", value: "1.25rem" },
|
|
1955
|
+
{ name: "XL", value: "1.5rem" }
|
|
1956
|
+
];
|
|
1957
|
+
var UNIT_COMPLETIONS = {
|
|
1958
|
+
r: "rem",
|
|
1959
|
+
re: "rem",
|
|
1960
|
+
rem: "rem",
|
|
1961
|
+
p: "px",
|
|
1962
|
+
px: "px",
|
|
1963
|
+
e: "em",
|
|
1964
|
+
em: "em",
|
|
1965
|
+
v: "vw",
|
|
1966
|
+
vw: "vw",
|
|
1967
|
+
vh: "vh"
|
|
1968
|
+
};
|
|
1969
|
+
function getPresetName(value) {
|
|
1970
|
+
const preset = SIZE_PRESETS.find((p) => p.value === value);
|
|
1971
|
+
return preset?.name ?? null;
|
|
1972
|
+
}
|
|
1973
|
+
function getFontSizeLabel(value) {
|
|
1974
|
+
if (!value) return "Size";
|
|
1975
|
+
const presetName = getPresetName(value);
|
|
1976
|
+
if (presetName) return presetName;
|
|
1977
|
+
return value;
|
|
1978
|
+
}
|
|
1979
|
+
function parseValue(value) {
|
|
1980
|
+
const match = value.match(/^([\d.]+)(rem|px|em|%|vw|vh)?$/);
|
|
1981
|
+
if (!match) return null;
|
|
1982
|
+
const num = parseFloat(match[1]);
|
|
1983
|
+
const unit = match[2] || "rem";
|
|
1984
|
+
return { num, unit };
|
|
1985
|
+
}
|
|
1986
|
+
function autocompleteUnit(input) {
|
|
1987
|
+
const match = input.match(/^([\d.]+)([a-z]*)$/);
|
|
1988
|
+
if (!match) return null;
|
|
1989
|
+
const [, num, partialUnit] = match;
|
|
1990
|
+
if (!partialUnit) return null;
|
|
1991
|
+
const fullUnit = UNIT_COMPLETIONS[partialUnit.toLowerCase()];
|
|
1992
|
+
if (fullUnit && fullUnit !== partialUnit) {
|
|
1993
|
+
return `${num}${fullUnit}`;
|
|
1994
|
+
}
|
|
1995
|
+
return null;
|
|
1996
|
+
}
|
|
1997
|
+
function normalizeValue(input) {
|
|
1998
|
+
if (!input.trim()) return null;
|
|
1999
|
+
const match = input.match(/^([\d.]+)(rem|px|em|%|vw|vh|pt|cm|mm|in)?$/);
|
|
2000
|
+
if (!match) return null;
|
|
2001
|
+
const num = match[1];
|
|
2002
|
+
const unit = match[2] || "rem";
|
|
2003
|
+
if (isNaN(parseFloat(num))) return null;
|
|
2004
|
+
return `${num}${unit}`;
|
|
2005
|
+
}
|
|
2006
|
+
function FontSizePicker({ value, onChange, onClose }) {
|
|
2007
|
+
const [inputValue, setInputValue] = useState4(value || "");
|
|
2008
|
+
const inputRef = useRef5(null);
|
|
2009
|
+
useEffect5(() => {
|
|
2010
|
+
inputRef.current?.focus();
|
|
2011
|
+
inputRef.current?.select();
|
|
2012
|
+
}, []);
|
|
2013
|
+
useEffect5(() => {
|
|
2014
|
+
setInputValue(value || "");
|
|
2015
|
+
}, [value]);
|
|
2016
|
+
const handlePresetClick = useCallback5((e, presetValue) => {
|
|
2017
|
+
e.stopPropagation();
|
|
2018
|
+
onChange(presetValue);
|
|
2019
|
+
onClose();
|
|
2020
|
+
}, [onChange, onClose]);
|
|
2021
|
+
const handlePresetMouseDown = useCallback5((e) => {
|
|
2022
|
+
e.preventDefault();
|
|
2023
|
+
e.stopPropagation();
|
|
2024
|
+
}, []);
|
|
2025
|
+
const handleInputChange = useCallback5((e) => {
|
|
2026
|
+
setInputValue(e.target.value);
|
|
2027
|
+
}, []);
|
|
2028
|
+
const handleInputKeyDown = useCallback5((e) => {
|
|
2029
|
+
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
|
2030
|
+
e.preventDefault();
|
|
2031
|
+
e.stopPropagation();
|
|
2032
|
+
let step = 0.1;
|
|
2033
|
+
if (e.shiftKey) step = 0.01;
|
|
2034
|
+
if (e.ctrlKey || e.metaKey) step = 1;
|
|
2035
|
+
const direction = e.key === "ArrowUp" ? 1 : -1;
|
|
2036
|
+
const parsed = parseValue(inputValue || value || "1rem");
|
|
2037
|
+
if (!parsed) return;
|
|
2038
|
+
const newNum = Math.max(0, parsed.num + step * direction);
|
|
2039
|
+
const formatted = `${Number(newNum.toFixed(2))}${parsed.unit}`;
|
|
2040
|
+
setInputValue(formatted);
|
|
2041
|
+
onChange(formatted);
|
|
2042
|
+
setTimeout(() => inputRef.current?.focus(), 0);
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
if (e.key === "Tab") {
|
|
2046
|
+
const completed = autocompleteUnit(inputValue);
|
|
2047
|
+
if (completed) {
|
|
2048
|
+
e.preventDefault();
|
|
2049
|
+
setInputValue(completed);
|
|
2050
|
+
onChange(completed);
|
|
2051
|
+
}
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
if (e.key === "Enter") {
|
|
2055
|
+
e.preventDefault();
|
|
2056
|
+
const completed = autocompleteUnit(inputValue) || normalizeValue(inputValue);
|
|
2057
|
+
if (completed) {
|
|
2058
|
+
onChange(completed);
|
|
2059
|
+
}
|
|
2060
|
+
onClose();
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
if (e.key === "Escape") {
|
|
2064
|
+
e.preventDefault();
|
|
2065
|
+
onClose();
|
|
2066
|
+
}
|
|
2067
|
+
}, [inputValue, value, onChange, onClose]);
|
|
2068
|
+
const activePreset = getPresetName(value);
|
|
2069
|
+
return /* @__PURE__ */ jsxs4("div", { className: "ya-font-size-picker", children: [
|
|
2070
|
+
/* @__PURE__ */ jsx8("div", { className: "ya-size-presets", children: SIZE_PRESETS.map((preset) => /* @__PURE__ */ jsxs4(
|
|
2071
|
+
"button",
|
|
2072
|
+
{
|
|
2073
|
+
type: "button",
|
|
2074
|
+
className: `ya-size-preset-btn ${activePreset === preset.name ? "is-active" : ""}`,
|
|
2075
|
+
onClick: (e) => handlePresetClick(e, preset.value),
|
|
2076
|
+
onMouseDown: handlePresetMouseDown,
|
|
2077
|
+
children: [
|
|
2078
|
+
/* @__PURE__ */ jsx8("span", { className: "ya-size-preset-name", children: preset.name }),
|
|
2079
|
+
/* @__PURE__ */ jsx8("span", { className: "ya-size-preset-value", children: preset.value })
|
|
2080
|
+
]
|
|
2081
|
+
},
|
|
2082
|
+
preset.name
|
|
2083
|
+
)) }),
|
|
2084
|
+
/* @__PURE__ */ jsx8("div", { className: "ya-size-combobox", children: /* @__PURE__ */ jsx8(
|
|
2085
|
+
"input",
|
|
2086
|
+
{
|
|
2087
|
+
ref: inputRef,
|
|
2088
|
+
type: "text",
|
|
2089
|
+
value: inputValue,
|
|
2090
|
+
onChange: handleInputChange,
|
|
2091
|
+
onKeyDown: handleInputKeyDown,
|
|
2092
|
+
onClick: (e) => e.stopPropagation(),
|
|
2093
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
2094
|
+
className: "ya-size-input",
|
|
2095
|
+
placeholder: "1rem",
|
|
2096
|
+
autoComplete: "off",
|
|
2097
|
+
spellCheck: false
|
|
2098
|
+
}
|
|
2099
|
+
) })
|
|
2100
|
+
] });
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
// src/components/FontWeightPicker.tsx
|
|
2104
|
+
import { useCallback as useCallback6 } from "react";
|
|
2105
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2106
|
+
var WEIGHT_PRESETS = [
|
|
2107
|
+
{ name: "Regular", value: "400" },
|
|
2108
|
+
{ name: "Semi-bold", value: "600" },
|
|
2109
|
+
{ name: "Bold", value: "700" },
|
|
2110
|
+
{ name: "Extra-bold", value: "800" }
|
|
2111
|
+
];
|
|
2112
|
+
function getFontWeightLabel(value) {
|
|
2113
|
+
if (!value) return "Weight";
|
|
2114
|
+
const preset = WEIGHT_PRESETS.find((p) => p.value === value);
|
|
2115
|
+
if (preset) return preset.name;
|
|
2116
|
+
return value;
|
|
2117
|
+
}
|
|
2118
|
+
function FontWeightPicker({ value, onChange, onClose }) {
|
|
2119
|
+
const handleClick = useCallback6((e, weightValue) => {
|
|
2120
|
+
e.stopPropagation();
|
|
2121
|
+
onChange(weightValue);
|
|
2122
|
+
onClose();
|
|
2123
|
+
}, [onChange, onClose]);
|
|
2124
|
+
const handleMouseDown = useCallback6((e) => {
|
|
2125
|
+
e.preventDefault();
|
|
2126
|
+
e.stopPropagation();
|
|
2127
|
+
}, []);
|
|
2128
|
+
return /* @__PURE__ */ jsx9("div", { className: "ya-font-weight-picker", children: WEIGHT_PRESETS.map((preset) => /* @__PURE__ */ jsx9(
|
|
2129
|
+
"button",
|
|
2130
|
+
{
|
|
2131
|
+
type: "button",
|
|
2132
|
+
className: `ya-weight-option ${value === preset.value ? "is-active" : ""}`,
|
|
2133
|
+
style: { fontWeight: preset.value },
|
|
2134
|
+
onClick: (e) => handleClick(e, preset.value),
|
|
2135
|
+
onMouseDown: handleMouseDown,
|
|
2136
|
+
children: preset.name
|
|
2137
|
+
},
|
|
2138
|
+
preset.value
|
|
2139
|
+
)) });
|
|
2140
|
+
}
|
|
2141
|
+
|
|
1703
2142
|
// #style-inject:#style-inject
|
|
1704
2143
|
function styleInject(css, { insertAt } = {}) {
|
|
1705
2144
|
if (!css || typeof document === "undefined") return;
|
|
@@ -1742,6 +2181,16 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1742
2181
|
border-radius: 4px;
|
|
1743
2182
|
position: relative;
|
|
1744
2183
|
}
|
|
2184
|
+
.ya-text-editing .ProseMirror p::selection,
|
|
2185
|
+
.ya-text-editing .ProseMirror::selection {
|
|
2186
|
+
background-color: rgba(212, 165, 116, 0.4);
|
|
2187
|
+
color: inherit;
|
|
2188
|
+
}
|
|
2189
|
+
.ya-text-editing .ProseMirror p::-moz-selection,
|
|
2190
|
+
.ya-text-editing .ProseMirror::-moz-selection {
|
|
2191
|
+
background-color: rgba(212, 165, 116, 0.4);
|
|
2192
|
+
color: inherit;
|
|
2193
|
+
}
|
|
1745
2194
|
.ya-bubble-menu {
|
|
1746
2195
|
display: flex;
|
|
1747
2196
|
gap: 4px;
|
|
@@ -1749,30 +2198,20 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1749
2198
|
background: #1a1a1a;
|
|
1750
2199
|
border-radius: 8px;
|
|
1751
2200
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
1752
|
-
animation: ya-bubble-fade-in 0.15s ease;
|
|
1753
2201
|
font-family:
|
|
1754
2202
|
system-ui,
|
|
1755
2203
|
-apple-system,
|
|
1756
2204
|
BlinkMacSystemFont,
|
|
1757
2205
|
"Segoe UI",
|
|
1758
2206
|
sans-serif;
|
|
1759
|
-
|
|
1760
|
-
@keyframes ya-bubble-fade-in {
|
|
1761
|
-
from {
|
|
1762
|
-
opacity: 0;
|
|
1763
|
-
transform: translateY(4px);
|
|
1764
|
-
}
|
|
1765
|
-
to {
|
|
1766
|
-
opacity: 1;
|
|
1767
|
-
transform: translateY(0);
|
|
1768
|
-
}
|
|
2207
|
+
z-index: 9999;
|
|
1769
2208
|
}
|
|
1770
2209
|
.ya-bubble-btn {
|
|
1771
2210
|
display: flex;
|
|
1772
2211
|
align-items: center;
|
|
1773
2212
|
justify-content: center;
|
|
1774
|
-
width:
|
|
1775
|
-
height:
|
|
2213
|
+
width: 36px;
|
|
2214
|
+
height: 36px;
|
|
1776
2215
|
padding: 0;
|
|
1777
2216
|
border: none;
|
|
1778
2217
|
background: transparent;
|
|
@@ -1796,7 +2235,7 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1796
2235
|
}
|
|
1797
2236
|
.ya-bubble-divider {
|
|
1798
2237
|
width: 1px;
|
|
1799
|
-
height:
|
|
2238
|
+
height: 24px;
|
|
1800
2239
|
background: rgba(255, 255, 255, 0.2);
|
|
1801
2240
|
margin: 6px 4px;
|
|
1802
2241
|
}
|
|
@@ -1845,6 +2284,14 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1845
2284
|
background: rgba(212, 165, 116, 0.3) !important;
|
|
1846
2285
|
color: inherit !important;
|
|
1847
2286
|
}
|
|
2287
|
+
body.builder-selector-active .ya-text-editable:not(.ya-text-editing)::selection,
|
|
2288
|
+
body.builder-selector-active .ya-text-editable:not(.ya-text-editing) *::selection {
|
|
2289
|
+
color: inherit;
|
|
2290
|
+
}
|
|
2291
|
+
body.builder-selector-active .ya-text-editable:not(.ya-text-editing)::-moz-selection,
|
|
2292
|
+
body.builder-selector-active .ya-text-editable:not(.ya-text-editing) *::-moz-selection {
|
|
2293
|
+
color: inherit;
|
|
2294
|
+
}
|
|
1848
2295
|
.ProseMirror p.is-editor-empty:first-child::before {
|
|
1849
2296
|
content: attr(data-placeholder);
|
|
1850
2297
|
float: left;
|
|
@@ -1855,13 +2302,11 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1855
2302
|
.ya-text-actions {
|
|
1856
2303
|
display: flex;
|
|
1857
2304
|
gap: 8px;
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
right: 0;
|
|
1861
|
-
z-index: 10;
|
|
1862
|
-
background: rgba(26, 26, 26, 0.8);
|
|
2305
|
+
z-index: 9999;
|
|
2306
|
+
background: rgba(26, 26, 26, 0.95);
|
|
1863
2307
|
padding: 8px 10px;
|
|
1864
2308
|
border-radius: 8px;
|
|
2309
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
1865
2310
|
font-family:
|
|
1866
2311
|
system-ui,
|
|
1867
2312
|
-apple-system,
|
|
@@ -1870,8 +2315,8 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1870
2315
|
sans-serif;
|
|
1871
2316
|
}
|
|
1872
2317
|
.ya-text-btn {
|
|
1873
|
-
padding:
|
|
1874
|
-
font-size:
|
|
2318
|
+
padding: 8px 18px;
|
|
2319
|
+
font-size: 14px;
|
|
1875
2320
|
font-weight: 500;
|
|
1876
2321
|
border-radius: 6px;
|
|
1877
2322
|
cursor: pointer;
|
|
@@ -1895,59 +2340,135 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1895
2340
|
.ya-text-btn-save:hover {
|
|
1896
2341
|
background: #c4956a;
|
|
1897
2342
|
}
|
|
1898
|
-
.ya-
|
|
1899
|
-
position: fixed;
|
|
1900
|
-
z-index: 9999;
|
|
2343
|
+
.ya-bubble-dropdown-trigger {
|
|
1901
2344
|
display: flex;
|
|
1902
2345
|
align-items: center;
|
|
1903
2346
|
gap: 6px;
|
|
1904
|
-
padding:
|
|
1905
|
-
background:
|
|
2347
|
+
padding: 6px 10px;
|
|
2348
|
+
background: transparent;
|
|
2349
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
2350
|
+
border-radius: 6px;
|
|
1906
2351
|
color: #e0e0e0;
|
|
2352
|
+
font-size: 12px;
|
|
2353
|
+
cursor: pointer;
|
|
2354
|
+
transition: all 0.15s ease;
|
|
2355
|
+
min-width: 70px;
|
|
2356
|
+
}
|
|
2357
|
+
.ya-bubble-dropdown-trigger:hover {
|
|
2358
|
+
border-color: rgba(255, 255, 255, 0.4);
|
|
2359
|
+
background: rgba(255, 255, 255, 0.05);
|
|
2360
|
+
}
|
|
2361
|
+
.ya-bubble-dropdown-trigger.is-open {
|
|
2362
|
+
border-color: var(--color-primary, #D4A574);
|
|
2363
|
+
background: rgba(255, 255, 255, 0.05);
|
|
2364
|
+
}
|
|
2365
|
+
.ya-bubble-dropdown-label {
|
|
2366
|
+
flex: 1;
|
|
2367
|
+
text-align: left;
|
|
2368
|
+
}
|
|
2369
|
+
.ya-bubble-dropdown-arrow {
|
|
2370
|
+
transition: transform 0.15s ease;
|
|
2371
|
+
opacity: 0.7;
|
|
2372
|
+
}
|
|
2373
|
+
.ya-bubble-dropdown-arrow.is-open {
|
|
2374
|
+
transform: rotate(180deg);
|
|
2375
|
+
}
|
|
2376
|
+
.ya-bubble-dropdown-panel {
|
|
2377
|
+
background: #1a1a1a;
|
|
1907
2378
|
border-radius: 8px;
|
|
1908
|
-
|
|
2379
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
|
|
2380
|
+
padding: 8px;
|
|
2381
|
+
min-width: 160px;
|
|
2382
|
+
z-index: 10000;
|
|
2383
|
+
font-family:
|
|
2384
|
+
system-ui,
|
|
2385
|
+
-apple-system,
|
|
2386
|
+
BlinkMacSystemFont,
|
|
2387
|
+
"Segoe UI",
|
|
2388
|
+
sans-serif;
|
|
2389
|
+
}
|
|
2390
|
+
.ya-font-size-picker {
|
|
2391
|
+
display: flex;
|
|
2392
|
+
flex-direction: column;
|
|
2393
|
+
gap: 8px;
|
|
2394
|
+
}
|
|
2395
|
+
.ya-size-presets {
|
|
2396
|
+
display: flex;
|
|
2397
|
+
gap: 4px;
|
|
2398
|
+
}
|
|
2399
|
+
.ya-size-preset-btn {
|
|
2400
|
+
flex: 1;
|
|
2401
|
+
display: flex;
|
|
2402
|
+
flex-direction: column;
|
|
2403
|
+
align-items: center;
|
|
2404
|
+
gap: 2px;
|
|
2405
|
+
padding: 6px 8px;
|
|
2406
|
+
background: rgba(255, 255, 255, 0.05);
|
|
2407
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
2408
|
+
border-radius: 4px;
|
|
2409
|
+
color: #e0e0e0;
|
|
2410
|
+
cursor: pointer;
|
|
2411
|
+
transition: all 0.15s ease;
|
|
2412
|
+
}
|
|
2413
|
+
.ya-size-preset-name {
|
|
2414
|
+
font-size: 12px;
|
|
1909
2415
|
font-weight: 500;
|
|
1910
|
-
|
|
2416
|
+
}
|
|
2417
|
+
.ya-size-preset-value {
|
|
2418
|
+
font-size: 9px;
|
|
2419
|
+
opacity: 0.5;
|
|
2420
|
+
}
|
|
2421
|
+
.ya-size-preset-btn:hover {
|
|
2422
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2423
|
+
border-color: rgba(255, 255, 255, 0.2);
|
|
2424
|
+
}
|
|
2425
|
+
.ya-size-preset-btn.is-active {
|
|
2426
|
+
background: var(--color-primary, #D4A574);
|
|
2427
|
+
color: #1a1a1a;
|
|
2428
|
+
border-color: var(--color-primary, #D4A574);
|
|
2429
|
+
}
|
|
2430
|
+
.ya-size-combobox {
|
|
2431
|
+
position: relative;
|
|
2432
|
+
}
|
|
2433
|
+
.ya-size-input {
|
|
2434
|
+
width: 100%;
|
|
2435
|
+
padding: 6px 8px;
|
|
2436
|
+
background: rgba(255, 255, 255, 0.05);
|
|
2437
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
2438
|
+
border-radius: 4px;
|
|
2439
|
+
color: #e0e0e0;
|
|
2440
|
+
font-size: 12px;
|
|
2441
|
+
box-sizing: border-box;
|
|
2442
|
+
}
|
|
2443
|
+
.ya-size-input:focus {
|
|
2444
|
+
outline: none;
|
|
2445
|
+
border-color: var(--color-primary, #D4A574);
|
|
2446
|
+
}
|
|
2447
|
+
.ya-size-input::placeholder {
|
|
2448
|
+
color: rgba(224, 224, 224, 0.5);
|
|
2449
|
+
}
|
|
2450
|
+
.ya-font-weight-picker {
|
|
2451
|
+
display: flex;
|
|
2452
|
+
flex-direction: column;
|
|
2453
|
+
gap: 2px;
|
|
2454
|
+
}
|
|
2455
|
+
.ya-weight-option {
|
|
2456
|
+
padding: 8px 12px;
|
|
2457
|
+
background: transparent;
|
|
2458
|
+
border: none;
|
|
2459
|
+
border-radius: 4px;
|
|
2460
|
+
color: #e0e0e0;
|
|
2461
|
+
font-size: 13px;
|
|
2462
|
+
text-align: left;
|
|
1911
2463
|
cursor: pointer;
|
|
1912
|
-
|
|
1913
|
-
transform: translateX(-50%);
|
|
1914
|
-
pointer-events: auto;
|
|
1915
|
-
animation: ya-link-popover-fade-in 0.1s ease;
|
|
1916
|
-
}
|
|
1917
|
-
.ya-link-popover:hover {
|
|
1918
|
-
background: #2a2a2a;
|
|
1919
|
-
}
|
|
1920
|
-
@keyframes ya-link-popover-fade-in {
|
|
1921
|
-
from {
|
|
1922
|
-
opacity: 0;
|
|
1923
|
-
transform: translateX(-50%) translateY(-4px);
|
|
1924
|
-
}
|
|
1925
|
-
to {
|
|
1926
|
-
opacity: 1;
|
|
1927
|
-
transform: translateX(-50%) translateY(0);
|
|
1928
|
-
}
|
|
2464
|
+
transition: all 0.15s ease;
|
|
1929
2465
|
}
|
|
1930
|
-
.ya-
|
|
1931
|
-
|
|
1932
|
-
position: absolute;
|
|
1933
|
-
top: -6px;
|
|
1934
|
-
left: 50%;
|
|
1935
|
-
transform: translateX(-50%);
|
|
1936
|
-
border-left: 6px solid transparent;
|
|
1937
|
-
border-right: 6px solid transparent;
|
|
1938
|
-
border-bottom: 6px solid #1a1a1a;
|
|
1939
|
-
}
|
|
1940
|
-
.ya-link-popover-icon {
|
|
1941
|
-
width: 14px;
|
|
1942
|
-
height: 14px;
|
|
1943
|
-
opacity: 0.8;
|
|
1944
|
-
flex-shrink: 0;
|
|
1945
|
-
}
|
|
1946
|
-
.ya-link-popover-prefix {
|
|
1947
|
-
opacity: 0.7;
|
|
2466
|
+
.ya-weight-option:hover {
|
|
2467
|
+
background: rgba(255, 255, 255, 0.1);
|
|
1948
2468
|
}
|
|
1949
|
-
.ya-
|
|
1950
|
-
|
|
2469
|
+
.ya-weight-option.is-active {
|
|
2470
|
+
background: var(--color-primary, #D4A574);
|
|
2471
|
+
color: #1a1a1a;
|
|
1951
2472
|
}
|
|
1952
2473
|
`);
|
|
1953
2474
|
|
|
@@ -1955,7 +2476,7 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1955
2476
|
styleInject('.ya-ai-editing {\n position: relative;\n}\n.ya-ai-editing::before {\n content: "";\n position: absolute;\n inset: -4px;\n border: 2px solid;\n border-radius: 6px;\n animation: ya-ai-focus-pulse 1.5s ease-in-out infinite;\n pointer-events: none;\n z-index: 10;\n}\n@keyframes ya-ai-focus-pulse {\n 0%, 100% {\n border-color: rgba(239, 68, 68, 0.6);\n box-shadow: 0 0 15px rgba(239, 68, 68, 0.2);\n }\n 50% {\n border-color: rgba(249, 115, 22, 0.8);\n box-shadow: 0 0 25px rgba(249, 115, 22, 0.3);\n }\n}\n.ya-typing-cursor {\n display: inline-block;\n width: 2px;\n height: 1.1em;\n background:\n linear-gradient(\n 180deg,\n #EF4444,\n #F97316);\n animation: ya-cursor-blink 0.5s step-end infinite;\n margin-left: 1px;\n vertical-align: text-bottom;\n border-radius: 1px;\n}\n@keyframes ya-cursor-blink {\n 50% {\n opacity: 0;\n }\n}\n.ya-ai-complete {\n animation: ya-complete-glow 0.4s ease-out forwards;\n}\n@keyframes ya-complete-glow {\n 0% {\n box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.5);\n }\n 50% {\n box-shadow: 0 0 20px 5px rgba(16, 185, 129, 0.3);\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .ya-ai-editing::before {\n animation: none;\n border-color: rgba(239, 68, 68, 0.6);\n box-shadow: 0 0 15px rgba(239, 68, 68, 0.2);\n }\n .ya-typing-cursor {\n animation: none;\n opacity: 1;\n }\n .ya-ai-complete {\n animation: ya-complete-glow-reduced 0.2s ease-out forwards;\n }\n @keyframes ya-complete-glow-reduced {\n 0% {\n background-color: rgba(16, 185, 129, 0.1);\n }\n 100% {\n background-color: transparent;\n }\n }\n}\n.ya-ai-hidden {\n opacity: 0;\n visibility: hidden;\n}\n.ya-ai-fade-in {\n animation: ya-fade-in 0.3s ease-out forwards;\n}\n@keyframes ya-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.ya-ai-pulse {\n animation: ya-scale-pulse 0.3s ease-out forwards;\n}\n@keyframes ya-scale-pulse {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.02);\n }\n 100% {\n transform: scale(1);\n }\n}\n');
|
|
1956
2477
|
|
|
1957
2478
|
// src/components/YaText.tsx
|
|
1958
|
-
import { Fragment as
|
|
2479
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1959
2480
|
var FontSize = Extension.create({
|
|
1960
2481
|
name: "fontSize",
|
|
1961
2482
|
addOptions() {
|
|
@@ -2032,25 +2553,16 @@ var FontWeight = Extension.create({
|
|
|
2032
2553
|
return chain().setMark("textStyle", { fontWeight: null }).removeEmptyTextStyle().run();
|
|
2033
2554
|
}
|
|
2034
2555
|
};
|
|
2035
|
-
}
|
|
2036
|
-
});
|
|
2037
|
-
var SIZE_PRESETS = {
|
|
2038
|
-
S: "14px",
|
|
2039
|
-
M: "16px",
|
|
2040
|
-
L: "20px",
|
|
2041
|
-
XL: "24px"
|
|
2042
|
-
};
|
|
2043
|
-
var WEIGHT_PRESETS = {
|
|
2044
|
-
Regular: "400",
|
|
2045
|
-
"Semi-bold": "600",
|
|
2046
|
-
Bold: "700",
|
|
2047
|
-
"Extra-bold": "800"
|
|
2048
|
-
};
|
|
2556
|
+
}
|
|
2557
|
+
});
|
|
2049
2558
|
function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
2050
2559
|
const { getValue, setValue, mode, saveToWorker, activeFieldId, setActiveField } = useContentStore();
|
|
2051
2560
|
const storeContent = getValue(fieldId);
|
|
2052
2561
|
const content = storeContent || (typeof children === "string" ? children : "");
|
|
2053
|
-
const [isEditing, setIsEditing] =
|
|
2562
|
+
const [isEditing, setIsEditing] = useState5(false);
|
|
2563
|
+
const [showBubbleMenu, setShowBubbleMenu] = useState5(false);
|
|
2564
|
+
const [fontSizeOpen, setFontSizeOpen] = useState5(false);
|
|
2565
|
+
const [fontWeightOpen, setFontWeightOpen] = useState5(false);
|
|
2054
2566
|
const {
|
|
2055
2567
|
displayContent,
|
|
2056
2568
|
isAnimating,
|
|
@@ -2058,9 +2570,16 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2058
2570
|
} = useAnimatedText(fieldId, content, {
|
|
2059
2571
|
enabled: mode === "inline-edit" && !isEditing
|
|
2060
2572
|
});
|
|
2061
|
-
const [originalContent, setOriginalContent] =
|
|
2062
|
-
const containerRef =
|
|
2063
|
-
const originalContentRef =
|
|
2573
|
+
const [originalContent, setOriginalContent] = useState5(content);
|
|
2574
|
+
const containerRef = useRef6(null);
|
|
2575
|
+
const originalContentRef = useRef6(content);
|
|
2576
|
+
const [actionButtonsPos, setActionButtonsPos] = useState5(null);
|
|
2577
|
+
const handleSaveRef = useRef6(() => {
|
|
2578
|
+
});
|
|
2579
|
+
const handleCancelRef = useRef6(() => {
|
|
2580
|
+
});
|
|
2581
|
+
const handleCloseRef = useRef6(() => {
|
|
2582
|
+
});
|
|
2064
2583
|
const editor = useEditor({
|
|
2065
2584
|
extensions: [
|
|
2066
2585
|
StarterKit.configure({
|
|
@@ -2090,50 +2609,126 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2090
2609
|
editorProps: {
|
|
2091
2610
|
attributes: {
|
|
2092
2611
|
class: "outline-none"
|
|
2612
|
+
},
|
|
2613
|
+
// Handle keyboard shortcuts at the editor level to prevent default behavior
|
|
2614
|
+
handleKeyDown: (_view, event) => {
|
|
2615
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
2616
|
+
event.preventDefault();
|
|
2617
|
+
handleSaveRef.current();
|
|
2618
|
+
return true;
|
|
2619
|
+
}
|
|
2620
|
+
if (event.key === "Escape") {
|
|
2621
|
+
event.preventDefault();
|
|
2622
|
+
handleCancelRef.current();
|
|
2623
|
+
return true;
|
|
2624
|
+
}
|
|
2625
|
+
if ((event.metaKey || event.ctrlKey) && event.key === "s") {
|
|
2626
|
+
event.preventDefault();
|
|
2627
|
+
handleSaveRef.current();
|
|
2628
|
+
return true;
|
|
2629
|
+
}
|
|
2630
|
+
return false;
|
|
2093
2631
|
}
|
|
2094
2632
|
},
|
|
2095
2633
|
parseOptions: { preserveWhitespace: "full" }
|
|
2096
2634
|
});
|
|
2097
|
-
|
|
2635
|
+
useEffect6(() => {
|
|
2098
2636
|
if (editor && !isEditing) {
|
|
2099
2637
|
if (editor.getHTML() !== content) {
|
|
2100
2638
|
editor.commands.setContent(content, { parseOptions: { preserveWhitespace: "full" } });
|
|
2101
2639
|
}
|
|
2102
2640
|
}
|
|
2103
2641
|
}, [content, editor, isEditing]);
|
|
2104
|
-
|
|
2642
|
+
useEffect6(() => {
|
|
2105
2643
|
if (isEditing && activeFieldId !== null && activeFieldId !== fieldId) {
|
|
2106
2644
|
setIsEditing(false);
|
|
2107
2645
|
}
|
|
2108
2646
|
}, [activeFieldId, fieldId, isEditing]);
|
|
2109
|
-
|
|
2647
|
+
useEffect6(() => {
|
|
2648
|
+
if (!isEditing || !containerRef.current || !editor) {
|
|
2649
|
+
setActionButtonsPos(null);
|
|
2650
|
+
return;
|
|
2651
|
+
}
|
|
2652
|
+
const updatePosition = () => {
|
|
2653
|
+
if (!containerRef.current || !editor) return;
|
|
2654
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
2655
|
+
const { view } = editor;
|
|
2656
|
+
const endPos = view.state.doc.content.size - 1;
|
|
2657
|
+
const endCoords = view.coordsAtPos(Math.max(0, endPos));
|
|
2658
|
+
setActionButtonsPos({
|
|
2659
|
+
top: rect.bottom + 8,
|
|
2660
|
+
left: endCoords.right
|
|
2661
|
+
// Right edge of buttons aligns with text end
|
|
2662
|
+
});
|
|
2663
|
+
};
|
|
2664
|
+
updatePosition();
|
|
2665
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
2666
|
+
window.addEventListener("resize", updatePosition);
|
|
2667
|
+
return () => {
|
|
2668
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
2669
|
+
window.removeEventListener("resize", updatePosition);
|
|
2670
|
+
};
|
|
2671
|
+
}, [isEditing, editor]);
|
|
2672
|
+
const handleSave = useCallback7(() => {
|
|
2110
2673
|
if (!editor) return;
|
|
2111
2674
|
let html = editor.getHTML();
|
|
2112
2675
|
html = html.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
|
|
2113
|
-
|
|
2114
|
-
|
|
2676
|
+
if (html !== originalContentRef.current) {
|
|
2677
|
+
setValue(fieldId, html, "user");
|
|
2678
|
+
saveToWorker?.(fieldId, html);
|
|
2679
|
+
}
|
|
2680
|
+
setShowBubbleMenu(false);
|
|
2115
2681
|
setIsEditing(false);
|
|
2116
2682
|
}, [editor, fieldId, setValue, saveToWorker]);
|
|
2117
|
-
const handleCancel =
|
|
2683
|
+
const handleCancel = useCallback7(() => {
|
|
2118
2684
|
if (editor) {
|
|
2119
2685
|
editor.commands.setContent(originalContent, { parseOptions: { preserveWhitespace: "full" } });
|
|
2120
2686
|
}
|
|
2687
|
+
setShowBubbleMenu(false);
|
|
2121
2688
|
setIsEditing(false);
|
|
2122
2689
|
}, [editor, originalContent]);
|
|
2123
|
-
|
|
2690
|
+
useEffect6(() => {
|
|
2691
|
+
handleSaveRef.current = handleSave;
|
|
2692
|
+
handleCancelRef.current = handleCancel;
|
|
2693
|
+
}, [handleSave, handleCancel]);
|
|
2694
|
+
useEffect6(() => {
|
|
2695
|
+
if (mode !== "inline-edit") return;
|
|
2696
|
+
const handleEditRequest = (event) => {
|
|
2697
|
+
const customEvent = event;
|
|
2698
|
+
const parentFieldId = customEvent.detail.fieldId;
|
|
2699
|
+
const parentLink = containerRef.current?.closest(`[data-field-id="${parentFieldId}"]`);
|
|
2700
|
+
if (!parentLink) return;
|
|
2701
|
+
setOriginalContent(content);
|
|
2702
|
+
originalContentRef.current = content;
|
|
2703
|
+
setActiveField(fieldId, { close: handleCloseRef.current });
|
|
2704
|
+
setIsEditing(true);
|
|
2705
|
+
setTimeout(() => {
|
|
2706
|
+
editor?.chain().focus().selectAll().run();
|
|
2707
|
+
setShowBubbleMenu(true);
|
|
2708
|
+
}, 20);
|
|
2709
|
+
};
|
|
2710
|
+
window.addEventListener("yatext:edit-mode", handleEditRequest);
|
|
2711
|
+
return () => window.removeEventListener("yatext:edit-mode", handleEditRequest);
|
|
2712
|
+
}, [mode, fieldId, content, editor, setActiveField]);
|
|
2713
|
+
const handleClose = useCallback7(() => {
|
|
2124
2714
|
if (!editor) {
|
|
2715
|
+
setShowBubbleMenu(false);
|
|
2125
2716
|
setIsEditing(false);
|
|
2126
2717
|
return;
|
|
2127
2718
|
}
|
|
2128
2719
|
let currentHtml = editor.getHTML();
|
|
2129
2720
|
currentHtml = currentHtml.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
|
|
2130
2721
|
if (currentHtml !== originalContentRef.current) {
|
|
2131
|
-
setValue(fieldId, currentHtml);
|
|
2722
|
+
setValue(fieldId, currentHtml, "user");
|
|
2132
2723
|
saveToWorker?.(fieldId, currentHtml);
|
|
2133
2724
|
}
|
|
2725
|
+
setShowBubbleMenu(false);
|
|
2134
2726
|
setIsEditing(false);
|
|
2135
2727
|
}, [editor, fieldId, setValue, saveToWorker]);
|
|
2136
|
-
|
|
2728
|
+
useEffect6(() => {
|
|
2729
|
+
handleCloseRef.current = handleClose;
|
|
2730
|
+
}, [handleClose]);
|
|
2731
|
+
const handleClick = useCallback7((e) => {
|
|
2137
2732
|
if (isEditing) {
|
|
2138
2733
|
e.preventDefault();
|
|
2139
2734
|
e.stopPropagation();
|
|
@@ -2156,10 +2751,11 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2156
2751
|
setIsEditing(true);
|
|
2157
2752
|
setTimeout(() => {
|
|
2158
2753
|
editor?.chain().focus().selectAll().run();
|
|
2754
|
+
setShowBubbleMenu(true);
|
|
2159
2755
|
}, 20);
|
|
2160
2756
|
}
|
|
2161
2757
|
}, [mode, isEditing, content, editor, fieldId, setActiveField, handleClose]);
|
|
2162
|
-
const handleKeyDown =
|
|
2758
|
+
const handleKeyDown = useCallback7(
|
|
2163
2759
|
(event) => {
|
|
2164
2760
|
if (!isEditing) return;
|
|
2165
2761
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -2180,7 +2776,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2180
2776
|
},
|
|
2181
2777
|
[isEditing, handleSave, handleCancel]
|
|
2182
2778
|
);
|
|
2183
|
-
const handleLink =
|
|
2779
|
+
const handleLink = useCallback7(() => {
|
|
2184
2780
|
if (!editor) return;
|
|
2185
2781
|
const previousUrl = editor.getAttributes("link").href;
|
|
2186
2782
|
const url = window.prompt("Enter URL:", previousUrl || "https://");
|
|
@@ -2191,10 +2787,9 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2191
2787
|
editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
|
|
2192
2788
|
}
|
|
2193
2789
|
}, [editor]);
|
|
2194
|
-
const handleFontSizeChange =
|
|
2195
|
-
(
|
|
2790
|
+
const handleFontSizeChange = useCallback7(
|
|
2791
|
+
(size) => {
|
|
2196
2792
|
if (!editor) return;
|
|
2197
|
-
const size = e.target.value;
|
|
2198
2793
|
if (size === "") {
|
|
2199
2794
|
editor.chain().focus().unsetFontSize().run();
|
|
2200
2795
|
} else {
|
|
@@ -2203,10 +2798,9 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2203
2798
|
},
|
|
2204
2799
|
[editor]
|
|
2205
2800
|
);
|
|
2206
|
-
const handleFontWeightChange =
|
|
2207
|
-
(
|
|
2801
|
+
const handleFontWeightChange = useCallback7(
|
|
2802
|
+
(weight) => {
|
|
2208
2803
|
if (!editor) return;
|
|
2209
|
-
const weight = e.target.value;
|
|
2210
2804
|
if (weight === "") {
|
|
2211
2805
|
editor.chain().focus().unsetFontWeight().run();
|
|
2212
2806
|
} else {
|
|
@@ -2218,22 +2812,45 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2218
2812
|
const getCurrentFontSize = () => {
|
|
2219
2813
|
if (!editor) return "";
|
|
2220
2814
|
const attrs = editor.getAttributes("textStyle");
|
|
2221
|
-
|
|
2815
|
+
if (attrs.fontSize) return attrs.fontSize;
|
|
2816
|
+
try {
|
|
2817
|
+
const { from } = editor.state.selection;
|
|
2818
|
+
const domAtPos = editor.view.domAtPos(from);
|
|
2819
|
+
const element = domAtPos.node instanceof Element ? domAtPos.node : domAtPos.node.parentElement;
|
|
2820
|
+
if (element) {
|
|
2821
|
+
const computed = window.getComputedStyle(element);
|
|
2822
|
+
return computed.fontSize || "";
|
|
2823
|
+
}
|
|
2824
|
+
} catch {
|
|
2825
|
+
}
|
|
2826
|
+
return "";
|
|
2222
2827
|
};
|
|
2223
2828
|
const getCurrentFontWeight = () => {
|
|
2224
2829
|
if (!editor) return "";
|
|
2830
|
+
if (editor.isActive("bold")) return "700";
|
|
2225
2831
|
const attrs = editor.getAttributes("textStyle");
|
|
2226
|
-
|
|
2832
|
+
if (attrs.fontWeight) return attrs.fontWeight;
|
|
2833
|
+
try {
|
|
2834
|
+
const { from } = editor.state.selection;
|
|
2835
|
+
const domAtPos = editor.view.domAtPos(from);
|
|
2836
|
+
const element = domAtPos.node instanceof Element ? domAtPos.node : domAtPos.node.parentElement;
|
|
2837
|
+
if (element) {
|
|
2838
|
+
const computed = window.getComputedStyle(element);
|
|
2839
|
+
return computed.fontWeight || "";
|
|
2840
|
+
}
|
|
2841
|
+
} catch {
|
|
2842
|
+
}
|
|
2843
|
+
return "";
|
|
2227
2844
|
};
|
|
2228
2845
|
if (mode === "read-only") {
|
|
2229
|
-
return /* @__PURE__ */
|
|
2846
|
+
return /* @__PURE__ */ jsx10(
|
|
2230
2847
|
Component,
|
|
2231
2848
|
{
|
|
2232
2849
|
ref: containerRef,
|
|
2233
2850
|
className,
|
|
2234
2851
|
"data-ya-restricted": "true",
|
|
2235
2852
|
"data-field-id": fieldId,
|
|
2236
|
-
children: /* @__PURE__ */
|
|
2853
|
+
children: /* @__PURE__ */ jsx10(SafeHtml, { content, mode })
|
|
2237
2854
|
}
|
|
2238
2855
|
);
|
|
2239
2856
|
}
|
|
@@ -2242,8 +2859,9 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2242
2859
|
isEditing ? "ya-text-editing" : "ya-text-editable",
|
|
2243
2860
|
wrapperClassName
|
|
2244
2861
|
].filter(Boolean).join(" ");
|
|
2245
|
-
|
|
2246
|
-
|
|
2862
|
+
const EditSafeComponent = isEditing && Component === "p" ? "div" : Component;
|
|
2863
|
+
return /* @__PURE__ */ jsx10(
|
|
2864
|
+
EditSafeComponent,
|
|
2247
2865
|
{
|
|
2248
2866
|
ref: containerRef,
|
|
2249
2867
|
className: combinedClassName,
|
|
@@ -2252,114 +2870,135 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2252
2870
|
"data-ai-editing": isAnimating || void 0,
|
|
2253
2871
|
onClick: handleClick,
|
|
2254
2872
|
onKeyDown: handleKeyDown,
|
|
2255
|
-
children: editor ? /* @__PURE__ */
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
"button",
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2873
|
+
children: editor ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2874
|
+
/* @__PURE__ */ jsxs5(
|
|
2875
|
+
ControlledBubbleMenu,
|
|
2876
|
+
{
|
|
2877
|
+
editor,
|
|
2878
|
+
open: showBubbleMenu,
|
|
2879
|
+
className: "ya-bubble-menu",
|
|
2880
|
+
children: [
|
|
2881
|
+
/* @__PURE__ */ jsx10(
|
|
2882
|
+
"button",
|
|
2883
|
+
{
|
|
2884
|
+
type: "button",
|
|
2885
|
+
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
2886
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
2887
|
+
className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
|
|
2888
|
+
title: "Bold",
|
|
2889
|
+
children: /* @__PURE__ */ jsx10(BoldIcon, { size: 16 })
|
|
2890
|
+
}
|
|
2891
|
+
),
|
|
2892
|
+
/* @__PURE__ */ jsx10(
|
|
2893
|
+
"button",
|
|
2894
|
+
{
|
|
2895
|
+
type: "button",
|
|
2896
|
+
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
2897
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
2898
|
+
className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
|
|
2899
|
+
title: "Italic",
|
|
2900
|
+
children: /* @__PURE__ */ jsx10(ItalicIcon, { size: 16 })
|
|
2901
|
+
}
|
|
2902
|
+
),
|
|
2903
|
+
/* @__PURE__ */ jsx10(
|
|
2904
|
+
"button",
|
|
2905
|
+
{
|
|
2906
|
+
type: "button",
|
|
2907
|
+
onClick: handleLink,
|
|
2908
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
2909
|
+
className: `ya-bubble-btn ${editor.isActive("link") ? "is-active" : ""}`,
|
|
2910
|
+
title: "Link",
|
|
2911
|
+
children: /* @__PURE__ */ jsx10(LinkIcon2, { size: 16 })
|
|
2912
|
+
}
|
|
2913
|
+
),
|
|
2914
|
+
/* @__PURE__ */ jsx10("span", { className: "ya-bubble-divider" }),
|
|
2915
|
+
/* @__PURE__ */ jsx10(
|
|
2916
|
+
BubbleDropdown,
|
|
2917
|
+
{
|
|
2918
|
+
label: getFontSizeLabel(getCurrentFontSize()),
|
|
2919
|
+
open: fontSizeOpen,
|
|
2920
|
+
onOpenChange: setFontSizeOpen,
|
|
2921
|
+
children: /* @__PURE__ */ jsx10(
|
|
2922
|
+
FontSizePicker,
|
|
2923
|
+
{
|
|
2924
|
+
value: getCurrentFontSize(),
|
|
2925
|
+
onChange: handleFontSizeChange,
|
|
2926
|
+
onClose: () => setFontSizeOpen(false)
|
|
2927
|
+
}
|
|
2928
|
+
)
|
|
2929
|
+
}
|
|
2930
|
+
),
|
|
2931
|
+
/* @__PURE__ */ jsx10(
|
|
2932
|
+
BubbleDropdown,
|
|
2933
|
+
{
|
|
2934
|
+
label: getFontWeightLabel(getCurrentFontWeight()),
|
|
2935
|
+
open: fontWeightOpen,
|
|
2936
|
+
onOpenChange: setFontWeightOpen,
|
|
2937
|
+
children: /* @__PURE__ */ jsx10(
|
|
2938
|
+
FontWeightPicker,
|
|
2939
|
+
{
|
|
2940
|
+
value: getCurrentFontWeight(),
|
|
2941
|
+
onChange: handleFontWeightChange,
|
|
2942
|
+
onClose: () => setFontWeightOpen(false)
|
|
2943
|
+
}
|
|
2944
|
+
)
|
|
2945
|
+
}
|
|
2946
|
+
)
|
|
2947
|
+
]
|
|
2948
|
+
}
|
|
2326
2949
|
),
|
|
2327
|
-
isEditing ? /* @__PURE__ */
|
|
2328
|
-
/* @__PURE__ */
|
|
2329
|
-
|
|
2330
|
-
/* @__PURE__ */
|
|
2331
|
-
"
|
|
2950
|
+
isEditing ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2951
|
+
/* @__PURE__ */ jsx10(EditorContent, { editor }),
|
|
2952
|
+
actionButtonsPos && createPortal3(
|
|
2953
|
+
/* @__PURE__ */ jsxs5(
|
|
2954
|
+
"div",
|
|
2332
2955
|
{
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2956
|
+
className: "ya-text-actions",
|
|
2957
|
+
style: {
|
|
2958
|
+
position: "fixed",
|
|
2959
|
+
top: actionButtonsPos.top,
|
|
2960
|
+
left: actionButtonsPos.left,
|
|
2961
|
+
transform: "translateX(-100%)"
|
|
2962
|
+
// Right edge aligns with text end
|
|
2963
|
+
},
|
|
2964
|
+
children: [
|
|
2965
|
+
/* @__PURE__ */ jsx10(
|
|
2966
|
+
"button",
|
|
2967
|
+
{
|
|
2968
|
+
type: "button",
|
|
2969
|
+
onClick: handleCancel,
|
|
2970
|
+
className: "ya-text-btn ya-text-btn-cancel",
|
|
2971
|
+
children: "Cancel"
|
|
2972
|
+
}
|
|
2973
|
+
),
|
|
2974
|
+
/* @__PURE__ */ jsx10(
|
|
2975
|
+
"button",
|
|
2976
|
+
{
|
|
2977
|
+
type: "button",
|
|
2978
|
+
onClick: handleSave,
|
|
2979
|
+
className: "ya-text-btn ya-text-btn-save",
|
|
2980
|
+
children: "Save"
|
|
2981
|
+
}
|
|
2982
|
+
)
|
|
2983
|
+
]
|
|
2337
2984
|
}
|
|
2338
2985
|
),
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
className: "ya-text-btn ya-text-btn-save",
|
|
2345
|
-
children: "Save"
|
|
2346
|
-
}
|
|
2347
|
-
)
|
|
2348
|
-
] })
|
|
2349
|
-
] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2350
|
-
/* @__PURE__ */ jsx5(SafeHtml, { content: displayContent, mode }),
|
|
2351
|
-
isAnimating && /* @__PURE__ */ jsx5("span", { className: "ya-typing-cursor" })
|
|
2986
|
+
document.body
|
|
2987
|
+
)
|
|
2988
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2989
|
+
/* @__PURE__ */ jsx10(SafeHtml, { content: displayContent, mode }),
|
|
2990
|
+
isAnimating && /* @__PURE__ */ jsx10("span", { className: "ya-typing-cursor" })
|
|
2352
2991
|
] })
|
|
2353
|
-
] }) : /* @__PURE__ */
|
|
2354
|
-
/* @__PURE__ */
|
|
2355
|
-
isAnimating && /* @__PURE__ */
|
|
2992
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2993
|
+
/* @__PURE__ */ jsx10(SafeHtml, { content: displayContent, mode }),
|
|
2994
|
+
isAnimating && /* @__PURE__ */ jsx10("span", { className: "ya-typing-cursor" })
|
|
2356
2995
|
] })
|
|
2357
2996
|
}
|
|
2358
2997
|
);
|
|
2359
2998
|
}
|
|
2360
2999
|
|
|
2361
3000
|
// src/components/YaImage.tsx
|
|
2362
|
-
import { useCallback as
|
|
3001
|
+
import { useCallback as useCallback9, useEffect as useEffect8, useRef as useRef8, useState as useState7 } from "react";
|
|
2363
3002
|
|
|
2364
3003
|
// src/lib/asset-resolver.ts
|
|
2365
3004
|
var assetResolver = (path) => path;
|
|
@@ -2375,25 +3014,25 @@ function resolveAssetUrl(path) {
|
|
|
2375
3014
|
}
|
|
2376
3015
|
|
|
2377
3016
|
// src/components/YaTooltip.tsx
|
|
2378
|
-
import { useEffect as
|
|
2379
|
-
import { createPortal as
|
|
3017
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState6, useCallback as useCallback8 } from "react";
|
|
3018
|
+
import { createPortal as createPortal4 } from "react-dom";
|
|
2380
3019
|
|
|
2381
3020
|
// src/components/ya-tooltip.css
|
|
2382
|
-
styleInject('.ya-tooltip {\n position: fixed;\n z-index: 9999;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: #1a1a1a;\n color: white;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n white-space: nowrap;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n animation: ya-tooltip-fade-in 0.15s ease;\n pointer-events: none;\n}\n@keyframes ya-tooltip-fade-in {\n from {\n
|
|
3021
|
+
styleInject('.ya-tooltip {\n position: fixed;\n z-index: 9999;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n background: #1a1a1a;\n color: white;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n white-space: nowrap;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n animation: ya-tooltip-fade-in 0.15s ease;\n pointer-events: none;\n}\n@keyframes ya-tooltip-fade-in {\n from {\n transform: scale(0.95);\n }\n to {\n transform: scale(1);\n }\n}\n.ya-tooltip svg {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.ya-tooltip-bottom {\n transform: translateX(-50%);\n}\n.ya-tooltip-bottom::before {\n content: "";\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 6px solid transparent;\n border-bottom-color: #1a1a1a;\n}\n.ya-tooltip-top {\n transform: translateX(-50%);\n}\n.ya-tooltip-top::before {\n content: "";\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 6px solid transparent;\n border-top-color: #1a1a1a;\n}\n.ya-tooltip-right {\n transform: translateY(-50%);\n}\n.ya-tooltip-right::before {\n content: "";\n position: absolute;\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n border: 6px solid transparent;\n border-right-color: #1a1a1a;\n}\n.ya-tooltip-left {\n transform: translateY(-50%);\n}\n.ya-tooltip-left::before {\n content: "";\n position: absolute;\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n border: 6px solid transparent;\n border-left-color: #1a1a1a;\n}\n');
|
|
2383
3022
|
|
|
2384
3023
|
// src/components/YaTooltip.tsx
|
|
2385
|
-
import { jsx as
|
|
3024
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2386
3025
|
function YaTooltip({
|
|
2387
3026
|
anchorRef,
|
|
2388
3027
|
children,
|
|
2389
3028
|
show,
|
|
2390
3029
|
preferredPosition = "bottom"
|
|
2391
3030
|
}) {
|
|
2392
|
-
const [position, setPosition] =
|
|
2393
|
-
const [coords, setCoords] =
|
|
2394
|
-
const [isPositioned, setIsPositioned] =
|
|
2395
|
-
const tooltipRef =
|
|
2396
|
-
const calculatePosition =
|
|
3031
|
+
const [position, setPosition] = useState6(preferredPosition);
|
|
3032
|
+
const [coords, setCoords] = useState6({ top: 0, left: 0 });
|
|
3033
|
+
const [isPositioned, setIsPositioned] = useState6(false);
|
|
3034
|
+
const tooltipRef = useRef7(null);
|
|
3035
|
+
const calculatePosition = useCallback8(() => {
|
|
2397
3036
|
if (!anchorRef.current) return;
|
|
2398
3037
|
const anchor = anchorRef.current.getBoundingClientRect();
|
|
2399
3038
|
const tooltip = tooltipRef.current?.getBoundingClientRect();
|
|
@@ -2468,7 +3107,7 @@ function YaTooltip({
|
|
|
2468
3107
|
setCoords({ top, left });
|
|
2469
3108
|
setIsPositioned(true);
|
|
2470
3109
|
}, [anchorRef, preferredPosition]);
|
|
2471
|
-
|
|
3110
|
+
useEffect7(() => {
|
|
2472
3111
|
if (!show) {
|
|
2473
3112
|
setIsPositioned(false);
|
|
2474
3113
|
return;
|
|
@@ -2481,14 +3120,14 @@ function YaTooltip({
|
|
|
2481
3120
|
window.removeEventListener("resize", calculatePosition);
|
|
2482
3121
|
};
|
|
2483
3122
|
}, [show, calculatePosition]);
|
|
2484
|
-
|
|
3123
|
+
useEffect7(() => {
|
|
2485
3124
|
if (show && tooltipRef.current) {
|
|
2486
3125
|
calculatePosition();
|
|
2487
3126
|
}
|
|
2488
3127
|
}, [show, children, calculatePosition]);
|
|
2489
3128
|
if (!show) return null;
|
|
2490
|
-
return
|
|
2491
|
-
/* @__PURE__ */
|
|
3129
|
+
return createPortal4(
|
|
3130
|
+
/* @__PURE__ */ jsx11(
|
|
2492
3131
|
"div",
|
|
2493
3132
|
{
|
|
2494
3133
|
ref: tooltipRef,
|
|
@@ -2496,8 +3135,7 @@ function YaTooltip({
|
|
|
2496
3135
|
style: {
|
|
2497
3136
|
top: coords.top,
|
|
2498
3137
|
left: coords.left,
|
|
2499
|
-
|
|
2500
|
-
pointerEvents: isPositioned ? "auto" : "none"
|
|
3138
|
+
visibility: isPositioned ? "visible" : "hidden"
|
|
2501
3139
|
},
|
|
2502
3140
|
role: "tooltip",
|
|
2503
3141
|
children
|
|
@@ -2511,7 +3149,7 @@ function YaTooltip({
|
|
|
2511
3149
|
styleInject('.ya-image-container {\n position: relative;\n display: inline-block;\n min-width: 45px;\n min-height: 45px;\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-image-container img {\n display: block;\n}\n.ya-image-editable {\n cursor: pointer;\n}\n.ya-image-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-selected {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: none;\n border-radius: inherit;\n}\n.ya-image-editable:hover .ya-image-overlay {\n opacity: 1;\n}\n.ya-image-selected .ya-image-overlay {\n opacity: 0;\n}\n.ya-image-edit-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n background: white;\n border-radius: 50%;\n color: #1a1a1a;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);\n}\n.ya-image-edit-icon svg {\n width: 24px;\n height: 24px;\n}\n.ya-image-edit-label {\n color: white;\n font-size: 14px;\n font-weight: 500;\n text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\n}\n@keyframes ya-image-success {\n 0% {\n outline-color: var(--color-primary, #D4A574);\n }\n 50% {\n outline-color: #22c55e;\n outline-width: 4px;\n }\n 100% {\n outline-color: var(--color-primary, #D4A574);\n outline-width: 2px;\n }\n}\n.ya-image-success {\n animation: ya-image-success 0.4s ease;\n}\n.ya-image-loading::after {\n content: "";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0) 0%,\n rgba(255, 255, 255, 0.3) 50%,\n rgba(255, 255, 255, 0) 100%);\n background-size: 200% 100%;\n animation: ya-image-shimmer 1.5s infinite;\n}\n@keyframes ya-image-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.ya-image-container:focus {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-container:focus:not(:focus-visible) {\n outline: none;\n}\n.ya-image-container:focus-visible {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-image-small .ya-image-overlay {\n display: none;\n}\n.ya-image-drop-target {\n outline: 2px dashed var(--ya-drop-color, #3b82f6) !important;\n outline-offset: 4px;\n}\n.ya-image-drop-target .ya-image-overlay {\n display: none !important;\n}\n.ya-image-drop-hover {\n outline: 3px solid var(--ya-drop-color, #3b82f6) !important;\n outline-offset: 4px;\n background-color: rgba(59, 130, 246, 0.1);\n}\n.ya-image-drop-hover::before {\n content: "";\n position: absolute;\n inset: -4px;\n border: 2px solid var(--ya-drop-color, #3b82f6);\n border-radius: inherit;\n animation: ya-drop-pulse 1s ease-in-out infinite;\n pointer-events: none;\n}\n@keyframes ya-drop-pulse {\n 0%, 100% {\n opacity: 0.4;\n transform: scale(1);\n }\n 50% {\n opacity: 0.8;\n transform: scale(1.02);\n }\n}\n');
|
|
2512
3150
|
|
|
2513
3151
|
// src/components/YaImage.tsx
|
|
2514
|
-
import { jsx as
|
|
3152
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2515
3153
|
function parseImageValue(value) {
|
|
2516
3154
|
if (!value) {
|
|
2517
3155
|
return { src: "" };
|
|
@@ -2556,20 +3194,20 @@ function YaImage({
|
|
|
2556
3194
|
fallbackAlt
|
|
2557
3195
|
}) {
|
|
2558
3196
|
const { getValue, mode } = useContentStore();
|
|
2559
|
-
const containerRef =
|
|
2560
|
-
const imgRef =
|
|
2561
|
-
const [isSelected, setIsSelected] =
|
|
2562
|
-
const [isHovered, setIsHovered] =
|
|
2563
|
-
const [isSmallImage, setIsSmallImage] =
|
|
2564
|
-
const [isDropMode, setIsDropMode] =
|
|
2565
|
-
const [isDropHover, setIsDropHover] =
|
|
3197
|
+
const containerRef = useRef8(null);
|
|
3198
|
+
const imgRef = useRef8(null);
|
|
3199
|
+
const [isSelected, setIsSelected] = useState7(false);
|
|
3200
|
+
const [isHovered, setIsHovered] = useState7(false);
|
|
3201
|
+
const [isSmallImage, setIsSmallImage] = useState7(false);
|
|
3202
|
+
const [isDropMode, setIsDropMode] = useState7(false);
|
|
3203
|
+
const [isDropHover, setIsDropHover] = useState7(false);
|
|
2566
3204
|
const rawValue = getValue(fieldId);
|
|
2567
3205
|
const imageData = parseImageValue(rawValue);
|
|
2568
3206
|
const src = imageData.src || fallbackSrc || PLACEHOLDER_SVG;
|
|
2569
3207
|
const altText = imageData.alt || alt || fallbackAlt || "";
|
|
2570
3208
|
const objectFit = imageData.objectFit || propObjectFit || "cover";
|
|
2571
3209
|
const objectPosition = getObjectPosition(imageData) || propObjectPosition || "50% 50%";
|
|
2572
|
-
const handleClick =
|
|
3210
|
+
const handleClick = useCallback9(() => {
|
|
2573
3211
|
if (mode !== "inline-edit") return;
|
|
2574
3212
|
if (document.body.classList.contains("builder-selector-active")) return;
|
|
2575
3213
|
setIsSelected(true);
|
|
@@ -2597,7 +3235,7 @@ function YaImage({
|
|
|
2597
3235
|
"*"
|
|
2598
3236
|
);
|
|
2599
3237
|
}, [mode, fieldId, imageData, src, altText, objectFit, objectPosition]);
|
|
2600
|
-
|
|
3238
|
+
useEffect8(() => {
|
|
2601
3239
|
if (mode !== "inline-edit") return;
|
|
2602
3240
|
const handleMessage2 = (event) => {
|
|
2603
3241
|
if (event.data?.type === "YA_IMAGE_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
|
|
@@ -2612,7 +3250,7 @@ function YaImage({
|
|
|
2612
3250
|
window.addEventListener("message", handleMessage2);
|
|
2613
3251
|
return () => window.removeEventListener("message", handleMessage2);
|
|
2614
3252
|
}, [mode, fieldId]);
|
|
2615
|
-
|
|
3253
|
+
useEffect8(() => {
|
|
2616
3254
|
if (mode !== "inline-edit") return;
|
|
2617
3255
|
const handleDropModeMessage = (event) => {
|
|
2618
3256
|
if (event.data?.type === "DROP_MODE_START") {
|
|
@@ -2626,7 +3264,7 @@ function YaImage({
|
|
|
2626
3264
|
window.addEventListener("message", handleDropModeMessage);
|
|
2627
3265
|
return () => window.removeEventListener("message", handleDropModeMessage);
|
|
2628
3266
|
}, [mode]);
|
|
2629
|
-
const handleDragEnter =
|
|
3267
|
+
const handleDragEnter = useCallback9(
|
|
2630
3268
|
(e) => {
|
|
2631
3269
|
if (!isDropMode) return;
|
|
2632
3270
|
e.preventDefault();
|
|
@@ -2650,7 +3288,7 @@ function YaImage({
|
|
|
2650
3288
|
},
|
|
2651
3289
|
[isDropMode, fieldId]
|
|
2652
3290
|
);
|
|
2653
|
-
const handleDragOver =
|
|
3291
|
+
const handleDragOver = useCallback9(
|
|
2654
3292
|
(e) => {
|
|
2655
3293
|
if (!isDropMode) return;
|
|
2656
3294
|
e.preventDefault();
|
|
@@ -2658,7 +3296,7 @@ function YaImage({
|
|
|
2658
3296
|
},
|
|
2659
3297
|
[isDropMode]
|
|
2660
3298
|
);
|
|
2661
|
-
const handleDragLeave =
|
|
3299
|
+
const handleDragLeave = useCallback9(
|
|
2662
3300
|
(e) => {
|
|
2663
3301
|
if (!isDropMode) return;
|
|
2664
3302
|
e.preventDefault();
|
|
@@ -2672,7 +3310,7 @@ function YaImage({
|
|
|
2672
3310
|
},
|
|
2673
3311
|
[isDropMode]
|
|
2674
3312
|
);
|
|
2675
|
-
const handleDrop =
|
|
3313
|
+
const handleDrop = useCallback9(
|
|
2676
3314
|
(e) => {
|
|
2677
3315
|
if (!isDropMode) return;
|
|
2678
3316
|
e.preventDefault();
|
|
@@ -2690,7 +3328,7 @@ function YaImage({
|
|
|
2690
3328
|
},
|
|
2691
3329
|
[isDropMode, fieldId]
|
|
2692
3330
|
);
|
|
2693
|
-
|
|
3331
|
+
useEffect8(() => {
|
|
2694
3332
|
if (mode !== "inline-edit") return;
|
|
2695
3333
|
const checkSize = () => {
|
|
2696
3334
|
if (imgRef.current) {
|
|
@@ -2712,7 +3350,7 @@ function YaImage({
|
|
|
2712
3350
|
window.removeEventListener("resize", checkSize);
|
|
2713
3351
|
};
|
|
2714
3352
|
}, [mode]);
|
|
2715
|
-
|
|
3353
|
+
useEffect8(() => {
|
|
2716
3354
|
if (!isSelected || mode !== "inline-edit") return;
|
|
2717
3355
|
let lastRectKey = "";
|
|
2718
3356
|
let lastTime = 0;
|
|
@@ -2747,7 +3385,7 @@ function YaImage({
|
|
|
2747
3385
|
return () => cancelAnimationFrame(rafId);
|
|
2748
3386
|
}, [isSelected, fieldId, mode]);
|
|
2749
3387
|
if (mode === "read-only") {
|
|
2750
|
-
return /* @__PURE__ */
|
|
3388
|
+
return /* @__PURE__ */ jsx12(
|
|
2751
3389
|
"img",
|
|
2752
3390
|
{
|
|
2753
3391
|
src: resolveAssetUrl(src),
|
|
@@ -2763,7 +3401,7 @@ function YaImage({
|
|
|
2763
3401
|
}
|
|
2764
3402
|
);
|
|
2765
3403
|
}
|
|
2766
|
-
const editIcon = /* @__PURE__ */
|
|
3404
|
+
const editIcon = /* @__PURE__ */ jsxs6(
|
|
2767
3405
|
"svg",
|
|
2768
3406
|
{
|
|
2769
3407
|
width: "24",
|
|
@@ -2775,9 +3413,9 @@ function YaImage({
|
|
|
2775
3413
|
strokeLinecap: "round",
|
|
2776
3414
|
strokeLinejoin: "round",
|
|
2777
3415
|
children: [
|
|
2778
|
-
/* @__PURE__ */
|
|
2779
|
-
/* @__PURE__ */
|
|
2780
|
-
/* @__PURE__ */
|
|
3416
|
+
/* @__PURE__ */ jsx12("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
3417
|
+
/* @__PURE__ */ jsx12("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
|
|
3418
|
+
/* @__PURE__ */ jsx12("polyline", { points: "21 15 16 10 5 21" })
|
|
2781
3419
|
]
|
|
2782
3420
|
}
|
|
2783
3421
|
);
|
|
@@ -2788,7 +3426,7 @@ function YaImage({
|
|
|
2788
3426
|
isDropMode ? "ya-image-drop-target" : "",
|
|
2789
3427
|
isDropHover ? "ya-image-drop-hover" : ""
|
|
2790
3428
|
].filter(Boolean).join(" ");
|
|
2791
|
-
return /* @__PURE__ */
|
|
3429
|
+
return /* @__PURE__ */ jsxs6(
|
|
2792
3430
|
"div",
|
|
2793
3431
|
{
|
|
2794
3432
|
ref: containerRef,
|
|
@@ -2813,7 +3451,7 @@ function YaImage({
|
|
|
2813
3451
|
}
|
|
2814
3452
|
},
|
|
2815
3453
|
children: [
|
|
2816
|
-
/* @__PURE__ */
|
|
3454
|
+
/* @__PURE__ */ jsx12(
|
|
2817
3455
|
"img",
|
|
2818
3456
|
{
|
|
2819
3457
|
ref: imgRef,
|
|
@@ -2827,14 +3465,14 @@ function YaImage({
|
|
|
2827
3465
|
loading
|
|
2828
3466
|
}
|
|
2829
3467
|
),
|
|
2830
|
-
isSmallImage ? /* @__PURE__ */
|
|
3468
|
+
isSmallImage ? /* @__PURE__ */ jsxs6(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
|
|
2831
3469
|
editIcon,
|
|
2832
|
-
/* @__PURE__ */
|
|
3470
|
+
/* @__PURE__ */ jsx12("span", { children: "Click to edit" })
|
|
2833
3471
|
] }) : (
|
|
2834
3472
|
/* For large images: show overlay inside the image */
|
|
2835
|
-
/* @__PURE__ */
|
|
2836
|
-
/* @__PURE__ */
|
|
2837
|
-
/* @__PURE__ */
|
|
3473
|
+
/* @__PURE__ */ jsxs6("div", { className: "ya-image-overlay", children: [
|
|
3474
|
+
/* @__PURE__ */ jsx12("div", { className: "ya-image-edit-icon", children: editIcon }),
|
|
3475
|
+
/* @__PURE__ */ jsx12("span", { className: "ya-image-edit-label", children: "Click to edit" })
|
|
2838
3476
|
] })
|
|
2839
3477
|
)
|
|
2840
3478
|
]
|
|
@@ -2843,13 +3481,13 @@ function YaImage({
|
|
|
2843
3481
|
}
|
|
2844
3482
|
|
|
2845
3483
|
// src/components/YaVideo.tsx
|
|
2846
|
-
import { useCallback as
|
|
3484
|
+
import { useCallback as useCallback10, useEffect as useEffect9, useRef as useRef9, useState as useState8 } from "react";
|
|
2847
3485
|
|
|
2848
3486
|
// src/components/ya-video.css
|
|
2849
3487
|
styleInject('.ya-video-wrapper {\n position: relative;\n display: block;\n width: 100%;\n}\n.ya-video-wrapper video,\n.ya-video-wrapper iframe {\n display: block;\n width: 100%;\n height: 100%;\n}\n.ya-video-container {\n position: relative;\n display: block;\n width: 100%;\n min-width: 80px;\n min-height: 45px;\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-video-container video,\n.ya-video-container iframe {\n display: block;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}\n.ya-video-editable {\n cursor: pointer;\n}\n.ya-video-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-selected {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: none;\n border-radius: inherit;\n}\n.ya-video-editable:hover .ya-video-overlay {\n opacity: 1;\n}\n.ya-video-selected .ya-video-overlay {\n opacity: 0;\n}\n.ya-video-edit-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n background: white;\n border-radius: 50%;\n color: #1a1a1a;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);\n}\n.ya-video-edit-icon svg {\n width: 24px;\n height: 24px;\n}\n.ya-video-edit-label {\n color: white;\n font-size: 14px;\n font-weight: 500;\n text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\n}\n.ya-video-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n height: 100%;\n min-height: 120px;\n background: #f3f4f6;\n border: 2px dashed #d1d5db;\n border-radius: 8px;\n color: #6b7280;\n font-size: 14px;\n}\n.ya-video-placeholder img {\n width: 64px;\n height: auto;\n opacity: 0.5;\n}\n@keyframes ya-video-success {\n 0% {\n outline-color: var(--color-primary, #D4A574);\n }\n 50% {\n outline-color: #22c55e;\n outline-width: 4px;\n }\n 100% {\n outline-color: var(--color-primary, #D4A574);\n outline-width: 2px;\n }\n}\n.ya-video-success {\n animation: ya-video-success 0.4s ease;\n}\n.ya-video-loading::after {\n content: "";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0) 0%,\n rgba(255, 255, 255, 0.3) 50%,\n rgba(255, 255, 255, 0) 100%);\n background-size: 200% 100%;\n animation: ya-video-shimmer 1.5s infinite;\n}\n@keyframes ya-video-shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.ya-video-container:focus {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-container:focus:not(:focus-visible) {\n outline: none;\n}\n.ya-video-container:focus-visible {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n}\n.ya-video-small .ya-video-overlay {\n display: none;\n}\n.ya-video-background {\n position: absolute;\n inset: 0;\n z-index: -1;\n}\n.ya-video-background video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n');
|
|
2850
3488
|
|
|
2851
3489
|
// src/components/YaVideo.tsx
|
|
2852
|
-
import { jsx as
|
|
3490
|
+
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2853
3491
|
function parseVideoValue(value) {
|
|
2854
3492
|
if (!value) {
|
|
2855
3493
|
return { type: "upload", src: "" };
|
|
@@ -2917,18 +3555,20 @@ function YaVideo({
|
|
|
2917
3555
|
aspectRatio: propAspectRatio,
|
|
2918
3556
|
objectFit: propObjectFit,
|
|
2919
3557
|
loading = "lazy",
|
|
3558
|
+
defaultValue,
|
|
2920
3559
|
fallbackSrc,
|
|
2921
3560
|
fallbackPoster
|
|
2922
3561
|
}) {
|
|
2923
3562
|
const { getValue, mode } = useContentStore();
|
|
2924
|
-
const containerRef =
|
|
2925
|
-
const videoRef =
|
|
2926
|
-
const [isSelected, setIsSelected] =
|
|
2927
|
-
const [isHovered, setIsHovered] =
|
|
2928
|
-
const [isSmallVideo, setIsSmallVideo] =
|
|
2929
|
-
const [isInView, setIsInView] =
|
|
3563
|
+
const containerRef = useRef9(null);
|
|
3564
|
+
const videoRef = useRef9(null);
|
|
3565
|
+
const [isSelected, setIsSelected] = useState8(false);
|
|
3566
|
+
const [isHovered, setIsHovered] = useState8(false);
|
|
3567
|
+
const [isSmallVideo, setIsSmallVideo] = useState8(false);
|
|
3568
|
+
const [isInView, setIsInView] = useState8(loading === "eager");
|
|
2930
3569
|
const rawValue = getValue(fieldId);
|
|
2931
|
-
const
|
|
3570
|
+
const parsedValue = parseVideoValue(rawValue);
|
|
3571
|
+
const videoData = parsedValue.src ? parsedValue : defaultValue || parsedValue;
|
|
2932
3572
|
const src = videoData.src || fallbackSrc || "";
|
|
2933
3573
|
const poster = videoData.poster || fallbackPoster || "";
|
|
2934
3574
|
const objectFit = videoData.objectFit || propObjectFit || "cover";
|
|
@@ -2939,8 +3579,8 @@ function YaVideo({
|
|
|
2939
3579
|
const controls = videoData.controls ?? true;
|
|
2940
3580
|
const playsinline = videoData.playsinline ?? true;
|
|
2941
3581
|
const preload = videoData.preload ?? "metadata";
|
|
2942
|
-
const [prefersReducedMotion, setPrefersReducedMotion] =
|
|
2943
|
-
|
|
3582
|
+
const [prefersReducedMotion, setPrefersReducedMotion] = useState8(false);
|
|
3583
|
+
useEffect9(() => {
|
|
2944
3584
|
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
2945
3585
|
setPrefersReducedMotion(mediaQuery.matches);
|
|
2946
3586
|
const handleChange = (e) => {
|
|
@@ -2950,7 +3590,7 @@ function YaVideo({
|
|
|
2950
3590
|
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
2951
3591
|
}, []);
|
|
2952
3592
|
const effectiveAutoplay = autoplay && !prefersReducedMotion;
|
|
2953
|
-
|
|
3593
|
+
useEffect9(() => {
|
|
2954
3594
|
if (loading === "eager" || isInView) return;
|
|
2955
3595
|
const observer = new IntersectionObserver(
|
|
2956
3596
|
(entries) => {
|
|
@@ -2967,7 +3607,7 @@ function YaVideo({
|
|
|
2967
3607
|
}
|
|
2968
3608
|
return () => observer.disconnect();
|
|
2969
3609
|
}, [loading, isInView]);
|
|
2970
|
-
const handleKeyDown =
|
|
3610
|
+
const handleKeyDown = useCallback10(
|
|
2971
3611
|
(e) => {
|
|
2972
3612
|
if ((e.key === " " || e.key === "Enter") && videoData.type === "upload" && controls) {
|
|
2973
3613
|
e.preventDefault();
|
|
@@ -2983,7 +3623,7 @@ function YaVideo({
|
|
|
2983
3623
|
},
|
|
2984
3624
|
[videoData.type, controls]
|
|
2985
3625
|
);
|
|
2986
|
-
const handleClick =
|
|
3626
|
+
const handleClick = useCallback10(() => {
|
|
2987
3627
|
if (mode !== "inline-edit") return;
|
|
2988
3628
|
if (document.body.classList.contains("builder-selector-active")) return;
|
|
2989
3629
|
setIsSelected(true);
|
|
@@ -3003,7 +3643,7 @@ function YaVideo({
|
|
|
3003
3643
|
"*"
|
|
3004
3644
|
);
|
|
3005
3645
|
}, [mode, fieldId, videoData]);
|
|
3006
|
-
|
|
3646
|
+
useEffect9(() => {
|
|
3007
3647
|
if (mode !== "inline-edit") return;
|
|
3008
3648
|
const handleMessage2 = (event) => {
|
|
3009
3649
|
if (event.data?.type === "YA_VIDEO_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
|
|
@@ -3016,7 +3656,7 @@ function YaVideo({
|
|
|
3016
3656
|
window.addEventListener("message", handleMessage2);
|
|
3017
3657
|
return () => window.removeEventListener("message", handleMessage2);
|
|
3018
3658
|
}, [mode, fieldId]);
|
|
3019
|
-
|
|
3659
|
+
useEffect9(() => {
|
|
3020
3660
|
if (mode !== "inline-edit") return;
|
|
3021
3661
|
const checkSize = () => {
|
|
3022
3662
|
if (containerRef.current) {
|
|
@@ -3028,7 +3668,7 @@ function YaVideo({
|
|
|
3028
3668
|
window.addEventListener("resize", checkSize);
|
|
3029
3669
|
return () => window.removeEventListener("resize", checkSize);
|
|
3030
3670
|
}, [mode]);
|
|
3031
|
-
|
|
3671
|
+
useEffect9(() => {
|
|
3032
3672
|
if (!isSelected || mode !== "inline-edit") return;
|
|
3033
3673
|
let lastRectKey = "";
|
|
3034
3674
|
let lastTime = 0;
|
|
@@ -3064,24 +3704,24 @@ function YaVideo({
|
|
|
3064
3704
|
}, [isSelected, fieldId, mode]);
|
|
3065
3705
|
const renderVideo = (isReadOnly) => {
|
|
3066
3706
|
if (!src && !isReadOnly) {
|
|
3067
|
-
return /* @__PURE__ */
|
|
3068
|
-
/* @__PURE__ */
|
|
3069
|
-
/* @__PURE__ */
|
|
3707
|
+
return /* @__PURE__ */ jsxs7("div", { className: "ya-video-placeholder", children: [
|
|
3708
|
+
/* @__PURE__ */ jsx13("img", { src: PLACEHOLDER_SVG2, alt: "" }),
|
|
3709
|
+
/* @__PURE__ */ jsx13("span", { children: "No video selected" })
|
|
3070
3710
|
] });
|
|
3071
3711
|
}
|
|
3072
3712
|
if (!isInView && loading === "lazy" && !isReadOnly) {
|
|
3073
|
-
return /* @__PURE__ */
|
|
3713
|
+
return /* @__PURE__ */ jsx13(
|
|
3074
3714
|
"div",
|
|
3075
3715
|
{
|
|
3076
3716
|
className: "ya-video-placeholder",
|
|
3077
3717
|
style: { aspectRatio },
|
|
3078
|
-
children: /* @__PURE__ */
|
|
3718
|
+
children: /* @__PURE__ */ jsx13("img", { src: PLACEHOLDER_SVG2, alt: "" })
|
|
3079
3719
|
}
|
|
3080
3720
|
);
|
|
3081
3721
|
}
|
|
3082
3722
|
if (videoData.type === "youtube" && src) {
|
|
3083
3723
|
const embedUrl = buildYouTubeEmbedUrl(src, videoData);
|
|
3084
|
-
return /* @__PURE__ */
|
|
3724
|
+
return /* @__PURE__ */ jsx13(
|
|
3085
3725
|
"iframe",
|
|
3086
3726
|
{
|
|
3087
3727
|
src: embedUrl,
|
|
@@ -3101,7 +3741,7 @@ function YaVideo({
|
|
|
3101
3741
|
}
|
|
3102
3742
|
if (videoData.type === "vimeo" && src) {
|
|
3103
3743
|
const embedUrl = buildVimeoEmbedUrl(src, videoData);
|
|
3104
|
-
return /* @__PURE__ */
|
|
3744
|
+
return /* @__PURE__ */ jsx13(
|
|
3105
3745
|
"iframe",
|
|
3106
3746
|
{
|
|
3107
3747
|
src: embedUrl,
|
|
@@ -3121,7 +3761,7 @@ function YaVideo({
|
|
|
3121
3761
|
}
|
|
3122
3762
|
const resolvedSrc = resolveAssetUrl(src);
|
|
3123
3763
|
const resolvedPoster = poster ? resolveAssetUrl(poster) : void 0;
|
|
3124
|
-
return /* @__PURE__ */
|
|
3764
|
+
return /* @__PURE__ */ jsx13(
|
|
3125
3765
|
"video",
|
|
3126
3766
|
{
|
|
3127
3767
|
ref: videoRef,
|
|
@@ -3156,7 +3796,7 @@ function YaVideo({
|
|
|
3156
3796
|
);
|
|
3157
3797
|
};
|
|
3158
3798
|
if (mode === "read-only") {
|
|
3159
|
-
return /* @__PURE__ */
|
|
3799
|
+
return /* @__PURE__ */ jsx13(
|
|
3160
3800
|
"div",
|
|
3161
3801
|
{
|
|
3162
3802
|
ref: containerRef,
|
|
@@ -3172,7 +3812,7 @@ function YaVideo({
|
|
|
3172
3812
|
}
|
|
3173
3813
|
);
|
|
3174
3814
|
}
|
|
3175
|
-
const videoIcon = /* @__PURE__ */
|
|
3815
|
+
const videoIcon = /* @__PURE__ */ jsxs7(
|
|
3176
3816
|
"svg",
|
|
3177
3817
|
{
|
|
3178
3818
|
width: "24",
|
|
@@ -3184,12 +3824,12 @@ function YaVideo({
|
|
|
3184
3824
|
strokeLinecap: "round",
|
|
3185
3825
|
strokeLinejoin: "round",
|
|
3186
3826
|
children: [
|
|
3187
|
-
/* @__PURE__ */
|
|
3188
|
-
/* @__PURE__ */
|
|
3827
|
+
/* @__PURE__ */ jsx13("rect", { x: "2", y: "4", width: "15", height: "13", rx: "2", ry: "2" }),
|
|
3828
|
+
/* @__PURE__ */ jsx13("polygon", { points: "22 7 15 12 22 17 22 7", fill: "currentColor" })
|
|
3189
3829
|
]
|
|
3190
3830
|
}
|
|
3191
3831
|
);
|
|
3192
|
-
return /* @__PURE__ */
|
|
3832
|
+
return /* @__PURE__ */ jsxs7(
|
|
3193
3833
|
"div",
|
|
3194
3834
|
{
|
|
3195
3835
|
ref: containerRef,
|
|
@@ -3212,14 +3852,14 @@ function YaVideo({
|
|
|
3212
3852
|
style: { aspectRatio },
|
|
3213
3853
|
children: [
|
|
3214
3854
|
renderVideo(false),
|
|
3215
|
-
isSmallVideo ? /* @__PURE__ */
|
|
3855
|
+
isSmallVideo ? /* @__PURE__ */ jsxs7(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
|
|
3216
3856
|
videoIcon,
|
|
3217
|
-
/* @__PURE__ */
|
|
3857
|
+
/* @__PURE__ */ jsx13("span", { children: "Click to edit" })
|
|
3218
3858
|
] }) : (
|
|
3219
3859
|
/* For large videos: show overlay inside the container */
|
|
3220
|
-
/* @__PURE__ */
|
|
3221
|
-
/* @__PURE__ */
|
|
3222
|
-
/* @__PURE__ */
|
|
3860
|
+
/* @__PURE__ */ jsxs7("div", { className: "ya-video-overlay", children: [
|
|
3861
|
+
/* @__PURE__ */ jsx13("div", { className: "ya-video-edit-icon", children: videoIcon }),
|
|
3862
|
+
/* @__PURE__ */ jsx13("span", { className: "ya-video-edit-label", children: "Click to edit" })
|
|
3223
3863
|
] })
|
|
3224
3864
|
)
|
|
3225
3865
|
]
|
|
@@ -3228,20 +3868,163 @@ function YaVideo({
|
|
|
3228
3868
|
}
|
|
3229
3869
|
|
|
3230
3870
|
// src/components/YaLink.tsx
|
|
3231
|
-
import { useEffect as
|
|
3232
|
-
import { createPortal as
|
|
3871
|
+
import { useEffect as useEffect12, useRef as useRef12, useState as useState11, useCallback as useCallback13, useId } from "react";
|
|
3872
|
+
import { createPortal as createPortal5 } from "react-dom";
|
|
3233
3873
|
import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
|
|
3234
|
-
import { BubbleMenu
|
|
3874
|
+
import { BubbleMenu } from "@tiptap/react/menus";
|
|
3235
3875
|
import StarterKit2 from "@tiptap/starter-kit";
|
|
3236
3876
|
import { TextStyle as TextStyle2 } from "@tiptap/extension-text-style";
|
|
3237
3877
|
import { Extension as Extension2 } from "@tiptap/core";
|
|
3238
3878
|
import { Link as WouterLink, useLocation } from "wouter";
|
|
3239
3879
|
|
|
3880
|
+
// src/components/SafeTriangleBelow.tsx
|
|
3881
|
+
import { useEffect as useEffect10, useState as useState9, useRef as useRef10, useCallback as useCallback11 } from "react";
|
|
3882
|
+
function SafeTriangleBelow({
|
|
3883
|
+
triggerRef,
|
|
3884
|
+
popoverRef,
|
|
3885
|
+
isVisible,
|
|
3886
|
+
onLeave,
|
|
3887
|
+
onStayInside
|
|
3888
|
+
}) {
|
|
3889
|
+
const [bounds, setBounds] = useState9(null);
|
|
3890
|
+
const boundsRef = useRef10(bounds);
|
|
3891
|
+
boundsRef.current = bounds;
|
|
3892
|
+
useEffect10(() => {
|
|
3893
|
+
if (!isVisible || !triggerRef.current || !popoverRef.current) {
|
|
3894
|
+
setBounds(null);
|
|
3895
|
+
return;
|
|
3896
|
+
}
|
|
3897
|
+
const timer = setTimeout(() => {
|
|
3898
|
+
if (!triggerRef.current || !popoverRef.current) return;
|
|
3899
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
3900
|
+
const popoverRect = popoverRef.current.getBoundingClientRect();
|
|
3901
|
+
setBounds({
|
|
3902
|
+
top: triggerRect.top,
|
|
3903
|
+
bottom: popoverRect.bottom,
|
|
3904
|
+
left: Math.min(triggerRect.left, popoverRect.left),
|
|
3905
|
+
right: Math.max(triggerRect.right, popoverRect.right)
|
|
3906
|
+
});
|
|
3907
|
+
}, 10);
|
|
3908
|
+
return () => clearTimeout(timer);
|
|
3909
|
+
}, [isVisible, triggerRef, popoverRef]);
|
|
3910
|
+
const checkMousePosition = useCallback11((e) => {
|
|
3911
|
+
const b = boundsRef.current;
|
|
3912
|
+
if (!b) return;
|
|
3913
|
+
const { clientX: x, clientY: y } = e;
|
|
3914
|
+
const padding = 5;
|
|
3915
|
+
const isOutside = x < b.left - padding || x > b.right + padding || y < b.top - padding || y > b.bottom + padding;
|
|
3916
|
+
if (isOutside) {
|
|
3917
|
+
onLeave?.();
|
|
3918
|
+
} else {
|
|
3919
|
+
onStayInside?.();
|
|
3920
|
+
}
|
|
3921
|
+
}, [onLeave, onStayInside]);
|
|
3922
|
+
useEffect10(() => {
|
|
3923
|
+
if (!isVisible || !bounds) return;
|
|
3924
|
+
document.addEventListener("mousemove", checkMousePosition);
|
|
3925
|
+
return () => document.removeEventListener("mousemove", checkMousePosition);
|
|
3926
|
+
}, [isVisible, bounds, checkMousePosition]);
|
|
3927
|
+
return null;
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
// src/hooks/useSafeTriangle.ts
|
|
3931
|
+
import { useState as useState10, useRef as useRef11, useCallback as useCallback12, useEffect as useEffect11 } from "react";
|
|
3932
|
+
function useSafeTriangle(options = {}) {
|
|
3933
|
+
const { showDelay = 0, hideDelay = 150, enabled = true } = options;
|
|
3934
|
+
const [isVisible, setIsVisible] = useState10(false);
|
|
3935
|
+
const [isHovering, setIsHovering] = useState10(false);
|
|
3936
|
+
const triggerRef = useRef11(null);
|
|
3937
|
+
const popoverRef = useRef11(null);
|
|
3938
|
+
const showTimeoutRef = useRef11(null);
|
|
3939
|
+
const hideTimeoutRef = useRef11(null);
|
|
3940
|
+
useEffect11(() => {
|
|
3941
|
+
return () => {
|
|
3942
|
+
if (showTimeoutRef.current) clearTimeout(showTimeoutRef.current);
|
|
3943
|
+
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
3944
|
+
};
|
|
3945
|
+
}, []);
|
|
3946
|
+
const show = useCallback12(() => {
|
|
3947
|
+
if (!enabled) return;
|
|
3948
|
+
if (hideTimeoutRef.current) {
|
|
3949
|
+
clearTimeout(hideTimeoutRef.current);
|
|
3950
|
+
hideTimeoutRef.current = null;
|
|
3951
|
+
}
|
|
3952
|
+
setIsVisible(true);
|
|
3953
|
+
}, [enabled]);
|
|
3954
|
+
const hide = useCallback12(() => {
|
|
3955
|
+
if (showTimeoutRef.current) {
|
|
3956
|
+
clearTimeout(showTimeoutRef.current);
|
|
3957
|
+
showTimeoutRef.current = null;
|
|
3958
|
+
}
|
|
3959
|
+
setIsVisible(false);
|
|
3960
|
+
setIsHovering(false);
|
|
3961
|
+
}, []);
|
|
3962
|
+
const handleMouseEnter = useCallback12(() => {
|
|
3963
|
+
if (!enabled) return;
|
|
3964
|
+
setIsHovering(true);
|
|
3965
|
+
if (hideTimeoutRef.current) {
|
|
3966
|
+
clearTimeout(hideTimeoutRef.current);
|
|
3967
|
+
hideTimeoutRef.current = null;
|
|
3968
|
+
}
|
|
3969
|
+
if (showDelay > 0) {
|
|
3970
|
+
showTimeoutRef.current = setTimeout(() => {
|
|
3971
|
+
setIsVisible(true);
|
|
3972
|
+
}, showDelay);
|
|
3973
|
+
} else {
|
|
3974
|
+
setIsVisible(true);
|
|
3975
|
+
}
|
|
3976
|
+
}, [showDelay, enabled]);
|
|
3977
|
+
const handleMouseLeave = useCallback12(() => {
|
|
3978
|
+
setIsHovering(false);
|
|
3979
|
+
if (showTimeoutRef.current) {
|
|
3980
|
+
clearTimeout(showTimeoutRef.current);
|
|
3981
|
+
showTimeoutRef.current = null;
|
|
3982
|
+
}
|
|
3983
|
+
hideTimeoutRef.current = setTimeout(() => {
|
|
3984
|
+
setIsVisible(false);
|
|
3985
|
+
}, hideDelay);
|
|
3986
|
+
}, [hideDelay]);
|
|
3987
|
+
const handleFocus = useCallback12(() => {
|
|
3988
|
+
if (!enabled) return;
|
|
3989
|
+
setIsVisible(true);
|
|
3990
|
+
}, [enabled]);
|
|
3991
|
+
const handleTriangleLeave = useCallback12(() => {
|
|
3992
|
+
if (!isHovering) {
|
|
3993
|
+
setIsVisible(false);
|
|
3994
|
+
}
|
|
3995
|
+
}, [isHovering]);
|
|
3996
|
+
const handleStayInside = useCallback12(() => {
|
|
3997
|
+
if (hideTimeoutRef.current) {
|
|
3998
|
+
clearTimeout(hideTimeoutRef.current);
|
|
3999
|
+
hideTimeoutRef.current = null;
|
|
4000
|
+
}
|
|
4001
|
+
}, []);
|
|
4002
|
+
return {
|
|
4003
|
+
triggerRef,
|
|
4004
|
+
popoverRef,
|
|
4005
|
+
isVisible,
|
|
4006
|
+
handlers: {
|
|
4007
|
+
onMouseEnter: handleMouseEnter,
|
|
4008
|
+
onMouseLeave: handleMouseLeave,
|
|
4009
|
+
onFocus: handleFocus
|
|
4010
|
+
},
|
|
4011
|
+
triangleProps: {
|
|
4012
|
+
triggerRef,
|
|
4013
|
+
popoverRef,
|
|
4014
|
+
isVisible,
|
|
4015
|
+
onLeave: handleTriangleLeave,
|
|
4016
|
+
onStayInside: handleStayInside
|
|
4017
|
+
},
|
|
4018
|
+
show,
|
|
4019
|
+
hide
|
|
4020
|
+
};
|
|
4021
|
+
}
|
|
4022
|
+
|
|
3240
4023
|
// src/components/ya-link.css
|
|
3241
|
-
styleInject('.ya-link-wrapper {\n position: relative;\n display: inline;\n}\n.ya-link-editable {\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-link-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: 4px;\n border-radius: 4px;\n}\nbody.builder-selector-active .ya-link-editable:hover {\n outline: none;\n cursor: inherit;\n}\n.ya-link-editing {\n outline: 2px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n border-radius: 4px;\n position: relative;\n}\n.ya-link-
|
|
4024
|
+
styleInject('.ya-link-wrapper {\n position: relative;\n display: inline;\n}\n.ya-link-editable {\n cursor: pointer;\n transition: outline 0.15s ease;\n}\n.ya-link-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: 4px;\n border-radius: 4px;\n}\nbody.builder-selector-active .ya-link-editable:hover {\n outline: none;\n cursor: inherit;\n}\n.ya-link-editing {\n outline: 2px solid var(--color-primary, #D4A574);\n outline-offset: 4px;\n border-radius: 4px;\n position: relative;\n}\n.ya-link-editing .ProseMirror {\n color: #1a1a1a !important;\n caret-color: #1a1a1a;\n}\n.ya-link-editing .ProseMirror p::selection,\n.ya-link-editing .ProseMirror::selection {\n background-color: rgba(212, 165, 116, 0.4);\n color: inherit;\n}\n.ya-link-editing .ProseMirror p::-moz-selection,\n.ya-link-editing .ProseMirror::-moz-selection {\n background-color: rgba(212, 165, 116, 0.4);\n color: inherit;\n}\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing)::selection,\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing) *::selection {\n color: inherit;\n}\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing)::-moz-selection,\nbody.builder-selector-active .ya-link-editable:not(.ya-link-editing) *::-moz-selection {\n color: inherit;\n}\n.ya-link-actions {\n display: flex;\n gap: 8px;\n z-index: 9999;\n background: rgba(26, 26, 26, 0.95);\n padding: 8px 10px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n.ya-link-btn {\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n border: none;\n}\n.ya-link-btn-cancel {\n background: #333333;\n color: #ffffff;\n border: 1px solid #555555;\n}\n.ya-link-btn-cancel:hover {\n background: #444444;\n color: #ffffff;\n border-color: #666666;\n}\n.ya-link-btn-save {\n background: #D4A574;\n color: #1a1a1a;\n}\n.ya-link-btn-save:hover {\n background: #c4956a;\n}\n.ya-href-popover {\n position: absolute;\n top: 100%;\n left: 50%;\n margin-top: 8px;\n z-index: 100;\n min-width: 280px;\n max-width: 320px;\n background: #1a1a1a;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);\n transform: translateX(-50%);\n animation: ya-href-popover-fade-in 0.15s ease;\n overflow: hidden;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n@keyframes ya-href-popover-fade-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n.ya-href-popover::before {\n content: "";\n position: absolute;\n top: -6px;\n left: 50%;\n transform: translateX(-50%);\n border-left: 8px solid transparent;\n border-right: 8px solid transparent;\n border-bottom: 8px solid #1a1a1a;\n}\n.ya-href-popover-header {\n padding: 12px 16px;\n font-size: 13px;\n font-weight: 600;\n color: #ffffff;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n}\n.ya-href-popover-section {\n padding: 12px 16px;\n}\n.ya-href-popover-label {\n display: block;\n font-size: 11px;\n font-weight: 500;\n color: rgba(255, 255, 255, 0.6);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n}\n.ya-href-collapsible-header {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 0;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: color 0.15s ease;\n}\n.ya-href-collapsible-header:hover {\n color: rgba(255, 255, 255, 0.8);\n}\n.ya-href-chevron {\n font-size: 8px;\n color: rgba(255, 255, 255, 0.4);\n}\n.ya-href-popover-pages {\n display: flex;\n flex-direction: column;\n gap: 4px;\n max-height: 200px;\n overflow-y: auto;\n}\n.ya-href-page-btn {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n width: 100%;\n padding: 10px 12px;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid transparent;\n border-radius: 8px;\n color: #e0e0e0;\n font-size: 13px;\n font-weight: 500;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.ya-href-page-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.2);\n}\n.ya-href-page-btn.is-selected {\n background: #D4A574;\n color: #1a1a1a;\n}\n.ya-href-page-btn.is-selected .ya-href-page-path {\n color: rgba(26, 26, 26, 0.6);\n}\n.ya-href-page-path {\n font-size: 11px;\n color: rgba(255, 255, 255, 0.4);\n font-family: monospace;\n word-break: break-all;\n}\n.ya-href-external-toggle {\n display: block;\n width: 100%;\n padding: 10px 16px;\n background: transparent;\n border: none;\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n color: #D4A574;\n font-size: 12px;\n font-weight: 500;\n text-align: center;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n.ya-href-external-toggle:hover {\n background: rgba(255, 255, 255, 0.05);\n}\n.ya-href-url-input {\n width: 100%;\n padding: 10px 12px;\n background: rgba(255, 255, 255, 0.05);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n color: #ffffff;\n font-size: 13px;\n outline: none;\n transition: border-color 0.15s ease;\n}\n.ya-href-url-input::placeholder {\n color: rgba(255, 255, 255, 0.4);\n}\n.ya-href-url-input:focus {\n border-color: var(--color-primary, #D4A574);\n}\n.ya-href-popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 16px;\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n}\n.ya-href-popover--above {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 8px;\n animation: ya-href-popover-fade-in-above 0.15s ease;\n}\n@keyframes ya-href-popover-fade-in-above {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n.ya-href-popover--above::before {\n top: auto;\n bottom: -6px;\n border-bottom: none;\n border-top: 8px solid #1a1a1a;\n}\n.ya-link-edit-popover {\n position: absolute;\n top: 100%;\n left: 50%;\n margin-top: 8px;\n z-index: 100;\n background: #2a2a2a;\n border-radius: 6px;\n padding: 4px;\n display: flex;\n gap: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n transform: translateX(-50%);\n animation: ya-edit-popover-fade-in 0.1s ease;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n white-space: nowrap;\n}\n@keyframes ya-edit-popover-fade-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n.ya-link-edit-popover::before {\n content: "";\n position: absolute;\n top: -5px;\n left: 50%;\n transform: translateX(-50%);\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-bottom: 6px solid #2a2a2a;\n}\n.ya-link-edit-popover button {\n background: #3a3a3a;\n border: none;\n color: #fff;\n padding: 6px 12px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n transition: background 0.15s ease;\n}\n.ya-link-edit-popover button:hover {\n background: #4a4a4a;\n}\n');
|
|
3242
4025
|
|
|
3243
4026
|
// src/components/YaLink.tsx
|
|
3244
|
-
import { Fragment as
|
|
4027
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3245
4028
|
function isInternalPath(path) {
|
|
3246
4029
|
if (!path) return false;
|
|
3247
4030
|
if (path.startsWith("#")) return false;
|
|
@@ -3342,8 +4125,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3342
4125
|
const { getValue, setValue, mode, saveToWorker, getPages } = useContentStore();
|
|
3343
4126
|
const [, navigate] = useLocation();
|
|
3344
4127
|
const pages = availablePages ?? getPages();
|
|
3345
|
-
const [sections, setSections] =
|
|
3346
|
-
const [sectionsExpanded, setSectionsExpanded] =
|
|
4128
|
+
const [sections, setSections] = useState11([]);
|
|
4129
|
+
const [sectionsExpanded, setSectionsExpanded] = useState11(false);
|
|
3347
4130
|
const textFieldId = `${fieldId}.text`;
|
|
3348
4131
|
const hrefFieldId = `${fieldId}.href`;
|
|
3349
4132
|
const storeText = getValue(textFieldId);
|
|
@@ -3354,16 +4137,47 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3354
4137
|
const isExternal = isExternalHref(href);
|
|
3355
4138
|
const effectiveTarget = target ?? (isExternal ? "_blank" : void 0);
|
|
3356
4139
|
const effectiveRel = rel ?? (isExternal ? "noopener noreferrer" : void 0);
|
|
3357
|
-
const [editingMode, setEditingMode] =
|
|
3358
|
-
const [
|
|
3359
|
-
const [
|
|
3360
|
-
const [
|
|
3361
|
-
const [
|
|
3362
|
-
const [
|
|
3363
|
-
const [
|
|
3364
|
-
const containerRef =
|
|
3365
|
-
const hrefPopoverRef =
|
|
3366
|
-
const
|
|
4140
|
+
const [editingMode, setEditingMode] = useState11(null);
|
|
4141
|
+
const [originalText, setOriginalText] = useState11(text);
|
|
4142
|
+
const [originalHref, setOriginalHref] = useState11(href);
|
|
4143
|
+
const [currentHref, setCurrentHref] = useState11(href);
|
|
4144
|
+
const [isExternalUrl, setIsExternalUrl] = useState11(false);
|
|
4145
|
+
const [externalUrl, setExternalUrl] = useState11("");
|
|
4146
|
+
const [popoverPosition, setPopoverPosition] = useState11("below");
|
|
4147
|
+
const containerRef = useRef12(null);
|
|
4148
|
+
const hrefPopoverRef = useRef12(null);
|
|
4149
|
+
const [actionButtonsPos, setActionButtonsPos] = useState11(null);
|
|
4150
|
+
const handleSaveTextRef = useRef12(() => {
|
|
4151
|
+
});
|
|
4152
|
+
const handleCancelTextRef = useRef12(() => {
|
|
4153
|
+
});
|
|
4154
|
+
const {
|
|
4155
|
+
popoverRef: editPopoverRef,
|
|
4156
|
+
isVisible: showEditPopover,
|
|
4157
|
+
handlers: safeTriangleHandlers,
|
|
4158
|
+
triangleProps,
|
|
4159
|
+
hide: hideEditPopover
|
|
4160
|
+
} = useSafeTriangle({
|
|
4161
|
+
enabled: mode === "inline-edit" && !editingMode,
|
|
4162
|
+
hideDelay: 150
|
|
4163
|
+
});
|
|
4164
|
+
const triggerRef = containerRef;
|
|
4165
|
+
const instanceId = useId();
|
|
4166
|
+
useEffect12(() => {
|
|
4167
|
+
if (showEditPopover && mode === "inline-edit" && !editingMode) {
|
|
4168
|
+
window.dispatchEvent(new CustomEvent("yalink:popover-open", { detail: { id: instanceId } }));
|
|
4169
|
+
}
|
|
4170
|
+
}, [showEditPopover, mode, editingMode, instanceId]);
|
|
4171
|
+
useEffect12(() => {
|
|
4172
|
+
const handleOtherPopoverOpen = (event) => {
|
|
4173
|
+
const customEvent = event;
|
|
4174
|
+
if (customEvent.detail.id !== instanceId && showEditPopover) {
|
|
4175
|
+
hideEditPopover();
|
|
4176
|
+
}
|
|
4177
|
+
};
|
|
4178
|
+
window.addEventListener("yalink:popover-open", handleOtherPopoverOpen);
|
|
4179
|
+
return () => window.removeEventListener("yalink:popover-open", handleOtherPopoverOpen);
|
|
4180
|
+
}, [instanceId, showEditPopover, hideEditPopover]);
|
|
3367
4181
|
const editor = useEditor2({
|
|
3368
4182
|
extensions: [
|
|
3369
4183
|
StarterKit2.configure({
|
|
@@ -3383,29 +4197,62 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3383
4197
|
editorProps: {
|
|
3384
4198
|
attributes: {
|
|
3385
4199
|
class: "outline-none"
|
|
4200
|
+
},
|
|
4201
|
+
// Handle keyboard shortcuts at the editor level to prevent default behavior
|
|
4202
|
+
handleKeyDown: (_view, event) => {
|
|
4203
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
4204
|
+
event.preventDefault();
|
|
4205
|
+
handleSaveTextRef.current();
|
|
4206
|
+
return true;
|
|
4207
|
+
}
|
|
4208
|
+
if (event.key === "Escape") {
|
|
4209
|
+
event.preventDefault();
|
|
4210
|
+
handleCancelTextRef.current();
|
|
4211
|
+
return true;
|
|
4212
|
+
}
|
|
4213
|
+
if ((event.metaKey || event.ctrlKey) && event.key === "s") {
|
|
4214
|
+
event.preventDefault();
|
|
4215
|
+
handleSaveTextRef.current();
|
|
4216
|
+
return true;
|
|
4217
|
+
}
|
|
4218
|
+
return false;
|
|
3386
4219
|
}
|
|
3387
4220
|
}
|
|
3388
4221
|
});
|
|
3389
|
-
|
|
4222
|
+
useEffect12(() => {
|
|
3390
4223
|
if (editor && editingMode !== "text") {
|
|
3391
4224
|
if (editor.getHTML() !== text) {
|
|
3392
4225
|
editor.commands.setContent(text);
|
|
3393
4226
|
}
|
|
3394
4227
|
}
|
|
3395
4228
|
}, [text, editor, editingMode]);
|
|
3396
|
-
|
|
4229
|
+
useEffect12(() => {
|
|
3397
4230
|
if (editingMode !== "link") {
|
|
3398
4231
|
setCurrentHref(href);
|
|
3399
4232
|
}
|
|
3400
4233
|
}, [href, editingMode]);
|
|
3401
|
-
|
|
4234
|
+
useEffect12(() => {
|
|
4235
|
+
if (editingMode !== "text" || !containerRef.current) {
|
|
4236
|
+
setActionButtonsPos(null);
|
|
4237
|
+
return;
|
|
4238
|
+
}
|
|
4239
|
+
const updatePosition = () => {
|
|
4240
|
+
if (!containerRef.current) return;
|
|
4241
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
4242
|
+
setActionButtonsPos({
|
|
4243
|
+
top: rect.bottom + 8,
|
|
4244
|
+
right: window.innerWidth - rect.right
|
|
4245
|
+
});
|
|
4246
|
+
};
|
|
4247
|
+
updatePosition();
|
|
4248
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
4249
|
+
window.addEventListener("resize", updatePosition);
|
|
3402
4250
|
return () => {
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
}
|
|
4251
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
4252
|
+
window.removeEventListener("resize", updatePosition);
|
|
3406
4253
|
};
|
|
3407
|
-
}, []);
|
|
3408
|
-
|
|
4254
|
+
}, [editingMode]);
|
|
4255
|
+
useEffect12(() => {
|
|
3409
4256
|
if (editingMode !== "link") return;
|
|
3410
4257
|
const handleClickOutside = (event) => {
|
|
3411
4258
|
const target2 = event.target;
|
|
@@ -3419,34 +4266,51 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3419
4266
|
document.addEventListener("mousedown", handleClickOutside);
|
|
3420
4267
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
3421
4268
|
}, [editingMode, originalHref]);
|
|
3422
|
-
|
|
4269
|
+
useEffect12(() => {
|
|
4270
|
+
if (editingMode !== "link" || !containerRef.current) return;
|
|
4271
|
+
const updatePosition = () => {
|
|
4272
|
+
if (!containerRef.current) return;
|
|
4273
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
4274
|
+
const popoverHeight = 350;
|
|
4275
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
4276
|
+
const spaceAbove = rect.top;
|
|
4277
|
+
setPopoverPosition(spaceBelow < popoverHeight && spaceAbove > spaceBelow ? "above" : "below");
|
|
4278
|
+
};
|
|
4279
|
+
window.addEventListener("resize", updatePosition);
|
|
4280
|
+
return () => window.removeEventListener("resize", updatePosition);
|
|
4281
|
+
}, [editingMode]);
|
|
4282
|
+
const handleSaveText = useCallback13(() => {
|
|
3423
4283
|
if (!editor) return;
|
|
3424
4284
|
let html = editor.getHTML();
|
|
3425
4285
|
html = html.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
|
|
3426
|
-
setValue(textFieldId, html);
|
|
4286
|
+
setValue(textFieldId, html, "user");
|
|
3427
4287
|
saveToWorker?.(textFieldId, html);
|
|
3428
4288
|
setEditingMode(null);
|
|
3429
4289
|
}, [editor, textFieldId, setValue, saveToWorker]);
|
|
3430
|
-
const handleSaveLink =
|
|
3431
|
-
setValue(hrefFieldId, currentHref);
|
|
4290
|
+
const handleSaveLink = useCallback13(() => {
|
|
4291
|
+
setValue(hrefFieldId, currentHref, "user");
|
|
3432
4292
|
saveToWorker?.(hrefFieldId, currentHref);
|
|
3433
4293
|
setEditingMode(null);
|
|
3434
4294
|
setIsExternalUrl(false);
|
|
3435
4295
|
setExternalUrl("");
|
|
3436
4296
|
}, [hrefFieldId, currentHref, setValue, saveToWorker]);
|
|
3437
|
-
const handleCancelText =
|
|
4297
|
+
const handleCancelText = useCallback13(() => {
|
|
3438
4298
|
if (editor) {
|
|
3439
4299
|
editor.commands.setContent(originalText);
|
|
3440
4300
|
}
|
|
3441
4301
|
setEditingMode(null);
|
|
3442
4302
|
}, [editor, originalText]);
|
|
3443
|
-
const handleCancelLink =
|
|
4303
|
+
const handleCancelLink = useCallback13(() => {
|
|
3444
4304
|
setCurrentHref(originalHref);
|
|
3445
4305
|
setEditingMode(null);
|
|
3446
4306
|
setIsExternalUrl(false);
|
|
3447
4307
|
setExternalUrl("");
|
|
3448
4308
|
}, [originalHref]);
|
|
3449
|
-
|
|
4309
|
+
useEffect12(() => {
|
|
4310
|
+
handleSaveTextRef.current = handleSaveText;
|
|
4311
|
+
handleCancelTextRef.current = handleCancelText;
|
|
4312
|
+
}, [handleSaveText, handleCancelText]);
|
|
4313
|
+
const handleClick = useCallback13(
|
|
3450
4314
|
(e) => {
|
|
3451
4315
|
const selectModeEnabled = window.__builderSelectModeEnabled;
|
|
3452
4316
|
if (selectModeEnabled) {
|
|
@@ -3478,43 +4342,35 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3478
4342
|
},
|
|
3479
4343
|
[href, navigate, onClick]
|
|
3480
4344
|
);
|
|
3481
|
-
const
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
const handleFocus = useCallback9(() => {
|
|
3498
|
-
if (mode === "inline-edit" && !editingMode) {
|
|
3499
|
-
setShowEditPopover(true);
|
|
3500
|
-
}
|
|
3501
|
-
}, [mode, editingMode]);
|
|
3502
|
-
const startEditText = useCallback9(() => {
|
|
3503
|
-
setShowEditPopover(false);
|
|
3504
|
-
setEditingMode("text");
|
|
3505
|
-
setOriginalText(text);
|
|
3506
|
-
setTimeout(() => {
|
|
3507
|
-
editor?.chain().focus().selectAll().run();
|
|
3508
|
-
}, 20);
|
|
3509
|
-
}, [text, editor]);
|
|
3510
|
-
const startEditLink = useCallback9(() => {
|
|
3511
|
-
setShowEditPopover(false);
|
|
4345
|
+
const startEditText = useCallback13(() => {
|
|
4346
|
+
hideEditPopover();
|
|
4347
|
+
if (isIconMode) {
|
|
4348
|
+
window.dispatchEvent(new CustomEvent("yatext:edit-mode", {
|
|
4349
|
+
detail: { fieldId }
|
|
4350
|
+
}));
|
|
4351
|
+
} else {
|
|
4352
|
+
setEditingMode("text");
|
|
4353
|
+
setOriginalText(text);
|
|
4354
|
+
setTimeout(() => {
|
|
4355
|
+
editor?.chain().focus().selectAll().run();
|
|
4356
|
+
}, 20);
|
|
4357
|
+
}
|
|
4358
|
+
}, [text, editor, hideEditPopover, isIconMode, fieldId]);
|
|
4359
|
+
const startEditLink = useCallback13(() => {
|
|
4360
|
+
hideEditPopover();
|
|
3512
4361
|
setEditingMode("link");
|
|
3513
4362
|
setOriginalHref(href);
|
|
3514
4363
|
setCurrentHref(href);
|
|
3515
4364
|
setSections(discoverSectionsFromDOM());
|
|
3516
|
-
|
|
3517
|
-
|
|
4365
|
+
if (containerRef.current) {
|
|
4366
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
4367
|
+
const popoverHeight = 350;
|
|
4368
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
4369
|
+
const spaceAbove = rect.top;
|
|
4370
|
+
setPopoverPosition(spaceBelow < popoverHeight && spaceAbove > spaceBelow ? "above" : "below");
|
|
4371
|
+
}
|
|
4372
|
+
}, [href, hideEditPopover]);
|
|
4373
|
+
const handleKeyDown = useCallback13(
|
|
3518
4374
|
(event) => {
|
|
3519
4375
|
if (editingMode !== "text") return;
|
|
3520
4376
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -3535,7 +4391,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3535
4391
|
},
|
|
3536
4392
|
[editingMode, handleSaveText, handleCancelText]
|
|
3537
4393
|
);
|
|
3538
|
-
const handleFontSizeChange =
|
|
4394
|
+
const handleFontSizeChange = useCallback13(
|
|
3539
4395
|
(e) => {
|
|
3540
4396
|
if (!editor) return;
|
|
3541
4397
|
const size = e.target.value;
|
|
@@ -3547,7 +4403,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3547
4403
|
},
|
|
3548
4404
|
[editor]
|
|
3549
4405
|
);
|
|
3550
|
-
const handleFontWeightChange =
|
|
4406
|
+
const handleFontWeightChange = useCallback13(
|
|
3551
4407
|
(e) => {
|
|
3552
4408
|
if (!editor) return;
|
|
3553
4409
|
const weight = e.target.value;
|
|
@@ -3559,11 +4415,11 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3559
4415
|
},
|
|
3560
4416
|
[editor]
|
|
3561
4417
|
);
|
|
3562
|
-
const handlePageSelect =
|
|
4418
|
+
const handlePageSelect = useCallback13((path) => {
|
|
3563
4419
|
setCurrentHref(path);
|
|
3564
4420
|
setIsExternalUrl(false);
|
|
3565
4421
|
}, []);
|
|
3566
|
-
const handleExternalUrlApply =
|
|
4422
|
+
const handleExternalUrlApply = useCallback13(() => {
|
|
3567
4423
|
if (externalUrl) {
|
|
3568
4424
|
setCurrentHref(externalUrl);
|
|
3569
4425
|
}
|
|
@@ -3579,9 +4435,9 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3579
4435
|
return attrs.fontWeight || "";
|
|
3580
4436
|
};
|
|
3581
4437
|
if (mode === "read-only") {
|
|
3582
|
-
const content = isIconMode ? children : /* @__PURE__ */
|
|
4438
|
+
const content = isIconMode ? children : /* @__PURE__ */ jsx14(SafeHtml, { content: text, mode });
|
|
3583
4439
|
if (isInternalPath(href)) {
|
|
3584
|
-
return /* @__PURE__ */
|
|
4440
|
+
return /* @__PURE__ */ jsx14(
|
|
3585
4441
|
WouterLink,
|
|
3586
4442
|
{
|
|
3587
4443
|
href,
|
|
@@ -3593,7 +4449,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3593
4449
|
}
|
|
3594
4450
|
);
|
|
3595
4451
|
}
|
|
3596
|
-
return /* @__PURE__ */
|
|
4452
|
+
return /* @__PURE__ */ jsx14(
|
|
3597
4453
|
Component,
|
|
3598
4454
|
{
|
|
3599
4455
|
ref: containerRef,
|
|
@@ -3608,8 +4464,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3608
4464
|
}
|
|
3609
4465
|
);
|
|
3610
4466
|
}
|
|
3611
|
-
return /* @__PURE__ */
|
|
3612
|
-
/* @__PURE__ */
|
|
4467
|
+
return /* @__PURE__ */ jsxs8("span", { className: "ya-link-wrapper", children: [
|
|
4468
|
+
/* @__PURE__ */ jsx14(
|
|
3613
4469
|
Component,
|
|
3614
4470
|
{
|
|
3615
4471
|
ref: containerRef,
|
|
@@ -3621,45 +4477,45 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3621
4477
|
"data-ya-restricted": "true",
|
|
3622
4478
|
"data-field-id": fieldId,
|
|
3623
4479
|
onClick: handleClick,
|
|
3624
|
-
onMouseEnter:
|
|
3625
|
-
onMouseLeave:
|
|
3626
|
-
onFocus:
|
|
4480
|
+
onMouseEnter: safeTriangleHandlers.onMouseEnter,
|
|
4481
|
+
onMouseLeave: safeTriangleHandlers.onMouseLeave,
|
|
4482
|
+
onFocus: safeTriangleHandlers.onFocus,
|
|
3627
4483
|
onKeyDown: handleKeyDown,
|
|
3628
4484
|
children: isIconMode ? (
|
|
3629
4485
|
// Icon mode: render children directly, no text editing
|
|
3630
4486
|
children
|
|
3631
|
-
) : editor ? /* @__PURE__ */
|
|
3632
|
-
|
|
3633
|
-
/* @__PURE__ */
|
|
3634
|
-
|
|
4487
|
+
) : editor ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
4488
|
+
createPortal5(
|
|
4489
|
+
/* @__PURE__ */ jsxs8(
|
|
4490
|
+
BubbleMenu,
|
|
3635
4491
|
{
|
|
3636
4492
|
editor,
|
|
3637
4493
|
shouldShow: () => editingMode === "text",
|
|
3638
4494
|
options: { offset: 6, placement: "top" },
|
|
3639
4495
|
className: "ya-bubble-menu",
|
|
3640
4496
|
children: [
|
|
3641
|
-
/* @__PURE__ */
|
|
4497
|
+
/* @__PURE__ */ jsx14(
|
|
3642
4498
|
"button",
|
|
3643
4499
|
{
|
|
3644
4500
|
type: "button",
|
|
3645
4501
|
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
3646
4502
|
className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
|
|
3647
4503
|
title: "Bold",
|
|
3648
|
-
children: /* @__PURE__ */
|
|
4504
|
+
children: /* @__PURE__ */ jsx14("strong", { children: "B" })
|
|
3649
4505
|
}
|
|
3650
4506
|
),
|
|
3651
|
-
/* @__PURE__ */
|
|
4507
|
+
/* @__PURE__ */ jsx14(
|
|
3652
4508
|
"button",
|
|
3653
4509
|
{
|
|
3654
4510
|
type: "button",
|
|
3655
4511
|
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
3656
4512
|
className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
|
|
3657
4513
|
title: "Italic",
|
|
3658
|
-
children: /* @__PURE__ */
|
|
4514
|
+
children: /* @__PURE__ */ jsx14("em", { children: "I" })
|
|
3659
4515
|
}
|
|
3660
4516
|
),
|
|
3661
|
-
/* @__PURE__ */
|
|
3662
|
-
/* @__PURE__ */
|
|
4517
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-bubble-divider" }),
|
|
4518
|
+
/* @__PURE__ */ jsxs8(
|
|
3663
4519
|
"select",
|
|
3664
4520
|
{
|
|
3665
4521
|
value: getCurrentFontSize(),
|
|
@@ -3667,12 +4523,12 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3667
4523
|
className: "ya-bubble-select",
|
|
3668
4524
|
title: "Font Size",
|
|
3669
4525
|
children: [
|
|
3670
|
-
/* @__PURE__ */
|
|
3671
|
-
Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */
|
|
4526
|
+
/* @__PURE__ */ jsx14("option", { value: "", children: "Size" }),
|
|
4527
|
+
Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */ jsx14("option", { value: size, children: name }, name))
|
|
3672
4528
|
]
|
|
3673
4529
|
}
|
|
3674
4530
|
),
|
|
3675
|
-
/* @__PURE__ */
|
|
4531
|
+
/* @__PURE__ */ jsxs8(
|
|
3676
4532
|
"select",
|
|
3677
4533
|
{
|
|
3678
4534
|
value: getCurrentFontWeight(),
|
|
@@ -3680,8 +4536,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3680
4536
|
className: "ya-bubble-select",
|
|
3681
4537
|
title: "Font Weight",
|
|
3682
4538
|
children: [
|
|
3683
|
-
/* @__PURE__ */
|
|
3684
|
-
Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */
|
|
4539
|
+
/* @__PURE__ */ jsx14("option", { value: "", children: "Weight" }),
|
|
4540
|
+
Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */ jsx14("option", { value: weight, children: name }, name))
|
|
3685
4541
|
]
|
|
3686
4542
|
}
|
|
3687
4543
|
)
|
|
@@ -3690,39 +4546,72 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3690
4546
|
),
|
|
3691
4547
|
document.body
|
|
3692
4548
|
),
|
|
3693
|
-
editingMode === "text" ? /* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
|
|
3696
|
-
/* @__PURE__ */
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
4549
|
+
editingMode === "text" ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
4550
|
+
/* @__PURE__ */ jsx14(EditorContent2, { editor }),
|
|
4551
|
+
actionButtonsPos && createPortal5(
|
|
4552
|
+
/* @__PURE__ */ jsxs8(
|
|
4553
|
+
"div",
|
|
4554
|
+
{
|
|
4555
|
+
className: "ya-link-actions",
|
|
4556
|
+
style: {
|
|
4557
|
+
position: "fixed",
|
|
4558
|
+
top: actionButtonsPos.top,
|
|
4559
|
+
right: actionButtonsPos.right
|
|
4560
|
+
},
|
|
4561
|
+
children: [
|
|
4562
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: handleCancelText, className: "ya-link-btn ya-link-btn-cancel", children: "Cancel" }),
|
|
4563
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: handleSaveText, className: "ya-link-btn ya-link-btn-save", children: "Save" })
|
|
4564
|
+
]
|
|
4565
|
+
}
|
|
4566
|
+
),
|
|
4567
|
+
document.body
|
|
4568
|
+
)
|
|
4569
|
+
] }) : /* @__PURE__ */ jsx14(SafeHtml, { content: text, mode })
|
|
4570
|
+
] }) : /* @__PURE__ */ jsx14(SafeHtml, { content: text, mode })
|
|
3701
4571
|
}
|
|
3702
4572
|
),
|
|
3703
|
-
showEditPopover && !editingMode && mode === "inline-edit" && /* @__PURE__ */
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
/* @__PURE__ */
|
|
4573
|
+
showEditPopover && !editingMode && mode === "inline-edit" && /* @__PURE__ */ jsxs8(
|
|
4574
|
+
"div",
|
|
4575
|
+
{
|
|
4576
|
+
ref: editPopoverRef,
|
|
4577
|
+
className: "ya-link-edit-popover",
|
|
4578
|
+
onMouseEnter: safeTriangleHandlers.onMouseEnter,
|
|
4579
|
+
onMouseLeave: safeTriangleHandlers.onMouseLeave,
|
|
4580
|
+
children: [
|
|
4581
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: startEditText, children: "Edit text" }),
|
|
4582
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: startEditLink, children: "Edit link" })
|
|
4583
|
+
]
|
|
4584
|
+
}
|
|
4585
|
+
),
|
|
4586
|
+
/* @__PURE__ */ jsx14(
|
|
4587
|
+
SafeTriangleBelow,
|
|
4588
|
+
{
|
|
4589
|
+
triggerRef,
|
|
4590
|
+
popoverRef: editPopoverRef,
|
|
4591
|
+
isVisible: showEditPopover && !editingMode && mode === "inline-edit",
|
|
4592
|
+
onLeave: triangleProps.onLeave,
|
|
4593
|
+
onStayInside: triangleProps.onStayInside
|
|
4594
|
+
}
|
|
4595
|
+
),
|
|
4596
|
+
editingMode === "link" && /* @__PURE__ */ jsxs8("div", { ref: hrefPopoverRef, className: `ya-href-popover ${popoverPosition === "above" ? "ya-href-popover--above" : ""}`, children: [
|
|
4597
|
+
/* @__PURE__ */ jsx14("div", { className: "ya-href-popover-header", children: "Link destination" }),
|
|
4598
|
+
!isExternalUrl ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
4599
|
+
sections.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "ya-href-popover-section", children: [
|
|
4600
|
+
/* @__PURE__ */ jsxs8(
|
|
3712
4601
|
"button",
|
|
3713
4602
|
{
|
|
3714
4603
|
type: "button",
|
|
3715
4604
|
className: "ya-href-popover-label ya-href-collapsible-header",
|
|
3716
4605
|
onClick: () => setSectionsExpanded(!sectionsExpanded),
|
|
3717
4606
|
children: [
|
|
3718
|
-
/* @__PURE__ */
|
|
4607
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-href-chevron", children: sectionsExpanded ? "\u25BC" : "\u25B6" }),
|
|
3719
4608
|
"Scroll to section (",
|
|
3720
4609
|
sections.length,
|
|
3721
4610
|
")"
|
|
3722
4611
|
]
|
|
3723
4612
|
}
|
|
3724
4613
|
),
|
|
3725
|
-
sectionsExpanded && /* @__PURE__ */
|
|
4614
|
+
sectionsExpanded && /* @__PURE__ */ jsx14("div", { className: "ya-href-popover-pages", children: sections.map((section) => /* @__PURE__ */ jsxs8(
|
|
3726
4615
|
"button",
|
|
3727
4616
|
{
|
|
3728
4617
|
type: "button",
|
|
@@ -3730,15 +4619,15 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3730
4619
|
onClick: () => handlePageSelect(section.path),
|
|
3731
4620
|
children: [
|
|
3732
4621
|
section.label,
|
|
3733
|
-
/* @__PURE__ */
|
|
4622
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-href-page-path", children: section.path })
|
|
3734
4623
|
]
|
|
3735
4624
|
},
|
|
3736
4625
|
section.path
|
|
3737
4626
|
)) })
|
|
3738
4627
|
] }),
|
|
3739
|
-
pages.length > 0 && /* @__PURE__ */
|
|
3740
|
-
/* @__PURE__ */
|
|
3741
|
-
/* @__PURE__ */
|
|
4628
|
+
pages.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "ya-href-popover-section", children: [
|
|
4629
|
+
/* @__PURE__ */ jsx14("label", { className: "ya-href-popover-label", children: "Navigate to page" }),
|
|
4630
|
+
/* @__PURE__ */ jsx14("div", { className: "ya-href-popover-pages", children: pages.map((page) => /* @__PURE__ */ jsxs8(
|
|
3742
4631
|
"button",
|
|
3743
4632
|
{
|
|
3744
4633
|
type: "button",
|
|
@@ -3746,13 +4635,13 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3746
4635
|
onClick: () => handlePageSelect(page.path),
|
|
3747
4636
|
children: [
|
|
3748
4637
|
page.label,
|
|
3749
|
-
/* @__PURE__ */
|
|
4638
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-href-page-path", children: page.path })
|
|
3750
4639
|
]
|
|
3751
4640
|
},
|
|
3752
4641
|
page.path
|
|
3753
4642
|
)) })
|
|
3754
4643
|
] }),
|
|
3755
|
-
/* @__PURE__ */
|
|
4644
|
+
/* @__PURE__ */ jsx14(
|
|
3756
4645
|
"button",
|
|
3757
4646
|
{
|
|
3758
4647
|
type: "button",
|
|
@@ -3764,10 +4653,10 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3764
4653
|
children: "Use external URL instead"
|
|
3765
4654
|
}
|
|
3766
4655
|
)
|
|
3767
|
-
] }) : /* @__PURE__ */
|
|
3768
|
-
/* @__PURE__ */
|
|
3769
|
-
/* @__PURE__ */
|
|
3770
|
-
/* @__PURE__ */
|
|
4656
|
+
] }) : /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
4657
|
+
/* @__PURE__ */ jsxs8("div", { className: "ya-href-popover-section", children: [
|
|
4658
|
+
/* @__PURE__ */ jsx14("label", { className: "ya-href-popover-label", children: "External URL" }),
|
|
4659
|
+
/* @__PURE__ */ jsx14(
|
|
3771
4660
|
"input",
|
|
3772
4661
|
{
|
|
3773
4662
|
type: "url",
|
|
@@ -3779,25 +4668,34 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3779
4668
|
}
|
|
3780
4669
|
)
|
|
3781
4670
|
] }),
|
|
3782
|
-
/* @__PURE__ */
|
|
4671
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "ya-href-external-toggle", onClick: () => setIsExternalUrl(false), children: "\u2190 Back to pages" })
|
|
3783
4672
|
] }),
|
|
3784
|
-
/* @__PURE__ */
|
|
3785
|
-
/* @__PURE__ */
|
|
3786
|
-
isExternalUrl ? /* @__PURE__ */
|
|
4673
|
+
/* @__PURE__ */ jsxs8("div", { className: "ya-href-popover-actions", children: [
|
|
4674
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "ya-link-btn ya-link-btn-cancel", onClick: handleCancelLink, children: "Cancel" }),
|
|
4675
|
+
isExternalUrl ? /* @__PURE__ */ jsx14("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleExternalUrlApply, children: "Apply" }) : /* @__PURE__ */ jsx14("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleSaveLink, children: "Save" })
|
|
3787
4676
|
] })
|
|
3788
4677
|
] })
|
|
3789
4678
|
] });
|
|
3790
4679
|
}
|
|
3791
4680
|
|
|
3792
4681
|
// src/components/YaContainer.tsx
|
|
3793
|
-
import { useCallback as
|
|
3794
|
-
import { createPortal as
|
|
4682
|
+
import { useCallback as useCallback14, useEffect as useEffect13, useRef as useRef13, useState as useState12 } from "react";
|
|
4683
|
+
import { createPortal as createPortal6 } from "react-dom";
|
|
4684
|
+
import {
|
|
4685
|
+
useFloating as useFloating3,
|
|
4686
|
+
useHover,
|
|
4687
|
+
useInteractions as useInteractions2,
|
|
4688
|
+
offset as offset3,
|
|
4689
|
+
flip as flip3,
|
|
4690
|
+
shift as shift3,
|
|
4691
|
+
FloatingPortal as FloatingPortal2
|
|
4692
|
+
} from "@floating-ui/react";
|
|
3795
4693
|
|
|
3796
4694
|
// src/components/ya-container.css
|
|
3797
|
-
styleInject('.ya-container {\n position: relative;\n}\n.ya-container-has-overlay::after {\n content: "";\n position: absolute;\n inset: 0;\n background: var(--ya-overlay-color, transparent);\n opacity: var(--ya-overlay-opacity, 0);\n pointer-events: none;\n z-index: 0;\n}\n.ya-container > *:not(.ya-container-toolbar) {\n position: relative;\n z-index: 1;\n}\n.ya-container-editable {\n transition: outline 0.15s ease;\n}\n.ya-container-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: -2px;\n}\nbody.builder-selector-active .ya-container-editable:hover {\n outline: none;\n}\n.ya-container-selected {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: -3px;\n}\n.ya-container-toolbar {\n display: flex;\n gap: 4px;\n background: rgba(26, 26, 26, 0.95);\n padding: 6px 8px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: ya-container-toolbar-fade-in 0.15s ease;\n}\n@keyframes ya-container-toolbar-fade-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ya-container-toolbar button {\n display: flex;\n align-items: center;\n justify-content: center;\n width:
|
|
4695
|
+
styleInject('.ya-container {\n position: relative;\n}\n.ya-container-has-overlay::after {\n content: "";\n position: absolute;\n inset: 0;\n background: var(--ya-overlay-color, transparent);\n opacity: var(--ya-overlay-opacity, 0);\n pointer-events: none;\n z-index: 0;\n}\n.ya-container > *:not(.ya-container-toolbar) {\n position: relative;\n z-index: 1;\n}\n.ya-container-editable {\n transition: outline 0.15s ease;\n pointer-events: none;\n}\n.ya-container-editable > * {\n pointer-events: auto;\n}\n.ya-container-editable:hover {\n outline: 2px dashed var(--color-primary, #D4A574);\n outline-offset: -2px;\n}\nbody.builder-selector-active .ya-container-editable:hover {\n outline: none;\n}\n.ya-container-selected {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: -3px;\n}\n.ya-container-toolbar {\n display: flex;\n gap: 4px;\n background: rgba(26, 26, 26, 0.95);\n padding: 6px 8px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: ya-container-toolbar-fade-in 0.15s ease;\n}\n@keyframes ya-container-toolbar-fade-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.ya-container-toolbar button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: #3a3a3a;\n border: none;\n border-radius: 6px;\n color: #ffffff;\n cursor: pointer;\n transition: background 0.15s ease, transform 0.1s ease;\n}\n.ya-container-toolbar button:hover {\n background: #4a4a4a;\n transform: scale(1.05);\n}\n.ya-container-toolbar button:active {\n transform: scale(0.98);\n}\n.ya-container-toolbar button.active {\n background: var(--color-primary, #D4A574);\n color: #1a1a1a;\n}\n.ya-container-toolbar button svg {\n width: 18px;\n height: 18px;\n}\n.ya-container-toolbar button[aria-label="Clear background"] {\n background: #3a2a2a;\n}\n.ya-container-toolbar button[aria-label="Clear background"]:hover {\n background: #5a3a3a;\n}\n.ya-container:focus-visible {\n outline: 3px solid var(--color-primary, #D4A574);\n outline-offset: -3px;\n}\n.ya-container-toolbar button:focus-visible {\n outline: 2px solid var(--color-primary, #D4A574);\n outline-offset: 2px;\n}\n.ya-container-drop-target {\n outline: 2px dashed var(--ya-drop-color, #3b82f6) !important;\n outline-offset: -2px;\n pointer-events: auto !important;\n}\n.ya-container-drop-target .ya-container-toolbar {\n display: none !important;\n}\n.ya-container-drop-hover {\n outline: 3px solid var(--ya-drop-color, #3b82f6) !important;\n outline-offset: -3px;\n}\n.ya-container-drop-hover::before {\n content: "";\n position: absolute;\n inset: 0;\n background: rgba(59, 130, 246, 0.08);\n pointer-events: none;\n z-index: 10;\n animation: ya-container-drop-pulse 1s ease-in-out infinite;\n}\n@keyframes ya-container-drop-pulse {\n 0%, 100% {\n background: rgba(59, 130, 246, 0.05);\n }\n 50% {\n background: rgba(59, 130, 246, 0.12);\n }\n}\n.ya-container-tooltip {\n background: #1a1a1a;\n color: white;\n padding: 8px 12px;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n white-space: nowrap;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 10000;\n pointer-events: none;\n animation: ya-container-tooltip-fade-in 0.1s ease;\n}\n@keyframes ya-container-tooltip-fade-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n');
|
|
3798
4696
|
|
|
3799
4697
|
// src/components/YaContainer.tsx
|
|
3800
|
-
import { jsx as
|
|
4698
|
+
import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3801
4699
|
function parseBackgroundConfig(value) {
|
|
3802
4700
|
if (!value) {
|
|
3803
4701
|
return { type: "none" };
|
|
@@ -3839,8 +4737,60 @@ function deriveContainerLabel(element) {
|
|
|
3839
4737
|
return tagLabels[tagName] || "Section";
|
|
3840
4738
|
}
|
|
3841
4739
|
function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick, onClearClick, hasBackground }) {
|
|
3842
|
-
const [position, setPosition] =
|
|
3843
|
-
|
|
4740
|
+
const [position, setPosition] = useState12(null);
|
|
4741
|
+
const [imageOpen, setImageOpen] = useState12(false);
|
|
4742
|
+
const [colorOpen, setColorOpen] = useState12(false);
|
|
4743
|
+
const [aiOpen, setAiOpen] = useState12(false);
|
|
4744
|
+
const [clearOpen, setClearOpen] = useState12(false);
|
|
4745
|
+
const {
|
|
4746
|
+
refs: imageRefs,
|
|
4747
|
+
floatingStyles: imageStyles,
|
|
4748
|
+
context: imageContext
|
|
4749
|
+
} = useFloating3({
|
|
4750
|
+
open: imageOpen,
|
|
4751
|
+
onOpenChange: setImageOpen,
|
|
4752
|
+
middleware: [offset3(8), flip3(), shift3({ padding: 10 })],
|
|
4753
|
+
placement: "bottom"
|
|
4754
|
+
});
|
|
4755
|
+
const imageHover = useHover(imageContext, { delay: { open: 0, close: 0 } });
|
|
4756
|
+
const { getReferenceProps: getImageRefProps, getFloatingProps: getImageFloatProps } = useInteractions2([imageHover]);
|
|
4757
|
+
const {
|
|
4758
|
+
refs: colorRefs,
|
|
4759
|
+
floatingStyles: colorStyles,
|
|
4760
|
+
context: colorContext
|
|
4761
|
+
} = useFloating3({
|
|
4762
|
+
open: colorOpen,
|
|
4763
|
+
onOpenChange: setColorOpen,
|
|
4764
|
+
middleware: [offset3(8), flip3(), shift3({ padding: 10 })],
|
|
4765
|
+
placement: "bottom"
|
|
4766
|
+
});
|
|
4767
|
+
const colorHover = useHover(colorContext, { delay: { open: 0, close: 0 } });
|
|
4768
|
+
const { getReferenceProps: getColorRefProps, getFloatingProps: getColorFloatProps } = useInteractions2([colorHover]);
|
|
4769
|
+
const {
|
|
4770
|
+
refs: aiRefs,
|
|
4771
|
+
floatingStyles: aiStyles,
|
|
4772
|
+
context: aiContext
|
|
4773
|
+
} = useFloating3({
|
|
4774
|
+
open: aiOpen,
|
|
4775
|
+
onOpenChange: setAiOpen,
|
|
4776
|
+
middleware: [offset3(8), flip3(), shift3({ padding: 10 })],
|
|
4777
|
+
placement: "bottom"
|
|
4778
|
+
});
|
|
4779
|
+
const aiHover = useHover(aiContext, { delay: { open: 0, close: 0 } });
|
|
4780
|
+
const { getReferenceProps: getAiRefProps, getFloatingProps: getAiFloatProps } = useInteractions2([aiHover]);
|
|
4781
|
+
const {
|
|
4782
|
+
refs: clearRefs,
|
|
4783
|
+
floatingStyles: clearStyles,
|
|
4784
|
+
context: clearContext
|
|
4785
|
+
} = useFloating3({
|
|
4786
|
+
open: clearOpen,
|
|
4787
|
+
onOpenChange: setClearOpen,
|
|
4788
|
+
middleware: [offset3(8), flip3(), shift3({ padding: 10 })],
|
|
4789
|
+
placement: "bottom"
|
|
4790
|
+
});
|
|
4791
|
+
const clearHover = useHover(clearContext, { delay: { open: 0, close: 0 } });
|
|
4792
|
+
const { getReferenceProps: getClearRefProps, getFloatingProps: getClearFloatProps } = useInteractions2([clearHover]);
|
|
4793
|
+
useEffect13(() => {
|
|
3844
4794
|
const updatePosition = () => {
|
|
3845
4795
|
if (containerRef.current) {
|
|
3846
4796
|
const rect = containerRef.current.getBoundingClientRect();
|
|
@@ -3859,8 +4809,8 @@ function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick, onClearC
|
|
|
3859
4809
|
};
|
|
3860
4810
|
}, [containerRef]);
|
|
3861
4811
|
if (!position) return null;
|
|
3862
|
-
return
|
|
3863
|
-
/* @__PURE__ */
|
|
4812
|
+
return createPortal6(
|
|
4813
|
+
/* @__PURE__ */ jsxs9(
|
|
3864
4814
|
"div",
|
|
3865
4815
|
{
|
|
3866
4816
|
className: "ya-container-toolbar",
|
|
@@ -3871,60 +4821,106 @@ function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick, onClearC
|
|
|
3871
4821
|
},
|
|
3872
4822
|
onClick: (e) => e.stopPropagation(),
|
|
3873
4823
|
children: [
|
|
3874
|
-
/* @__PURE__ */
|
|
4824
|
+
/* @__PURE__ */ jsx15(
|
|
3875
4825
|
"button",
|
|
3876
4826
|
{
|
|
4827
|
+
ref: imageRefs.setReference,
|
|
3877
4828
|
type: "button",
|
|
3878
4829
|
onClick: onImageClick,
|
|
3879
4830
|
"aria-label": "Edit background image",
|
|
3880
|
-
|
|
3881
|
-
children: /* @__PURE__ */
|
|
3882
|
-
/* @__PURE__ */
|
|
3883
|
-
/* @__PURE__ */
|
|
3884
|
-
/* @__PURE__ */
|
|
4831
|
+
...getImageRefProps(),
|
|
4832
|
+
children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4833
|
+
/* @__PURE__ */ jsx15("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
4834
|
+
/* @__PURE__ */ jsx15("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
|
|
4835
|
+
/* @__PURE__ */ jsx15("polyline", { points: "21 15 16 10 5 21" })
|
|
3885
4836
|
] })
|
|
3886
4837
|
}
|
|
3887
4838
|
),
|
|
3888
|
-
/* @__PURE__ */
|
|
4839
|
+
imageOpen && /* @__PURE__ */ jsx15(FloatingPortal2, { children: /* @__PURE__ */ jsx15(
|
|
4840
|
+
"div",
|
|
4841
|
+
{
|
|
4842
|
+
ref: imageRefs.setFloating,
|
|
4843
|
+
className: "ya-container-tooltip",
|
|
4844
|
+
style: imageStyles,
|
|
4845
|
+
...getImageFloatProps(),
|
|
4846
|
+
children: "Background Image"
|
|
4847
|
+
}
|
|
4848
|
+
) }),
|
|
4849
|
+
/* @__PURE__ */ jsx15(
|
|
3889
4850
|
"button",
|
|
3890
4851
|
{
|
|
4852
|
+
ref: colorRefs.setReference,
|
|
3891
4853
|
type: "button",
|
|
3892
4854
|
onClick: onColorClick,
|
|
3893
4855
|
"aria-label": "Edit background color",
|
|
3894
|
-
|
|
3895
|
-
children: /* @__PURE__ */
|
|
3896
|
-
/* @__PURE__ */
|
|
3897
|
-
/* @__PURE__ */
|
|
4856
|
+
...getColorRefProps(),
|
|
4857
|
+
children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4858
|
+
/* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "10" }),
|
|
4859
|
+
/* @__PURE__ */ jsx15("path", { d: "M12 2a10 10 0 0 1 0 20", fill: "currentColor" })
|
|
3898
4860
|
] })
|
|
3899
4861
|
}
|
|
3900
4862
|
),
|
|
3901
|
-
/* @__PURE__ */
|
|
4863
|
+
colorOpen && /* @__PURE__ */ jsx15(FloatingPortal2, { children: /* @__PURE__ */ jsx15(
|
|
4864
|
+
"div",
|
|
4865
|
+
{
|
|
4866
|
+
ref: colorRefs.setFloating,
|
|
4867
|
+
className: "ya-container-tooltip",
|
|
4868
|
+
style: colorStyles,
|
|
4869
|
+
...getColorFloatProps(),
|
|
4870
|
+
children: "Background Color"
|
|
4871
|
+
}
|
|
4872
|
+
) }),
|
|
4873
|
+
/* @__PURE__ */ jsx15(
|
|
3902
4874
|
"button",
|
|
3903
4875
|
{
|
|
4876
|
+
ref: aiRefs.setReference,
|
|
3904
4877
|
type: "button",
|
|
3905
4878
|
onClick: onAIClick,
|
|
3906
4879
|
"aria-label": "Ask AI for help",
|
|
3907
|
-
|
|
3908
|
-
children: /* @__PURE__ */
|
|
3909
|
-
/* @__PURE__ */
|
|
3910
|
-
/* @__PURE__ */
|
|
3911
|
-
/* @__PURE__ */
|
|
4880
|
+
...getAiRefProps(),
|
|
4881
|
+
children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4882
|
+
/* @__PURE__ */ jsx15("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }),
|
|
4883
|
+
/* @__PURE__ */ jsx15("path", { d: "M2 17l10 5 10-5" }),
|
|
4884
|
+
/* @__PURE__ */ jsx15("path", { d: "M2 12l10 5 10-5" })
|
|
3912
4885
|
] })
|
|
3913
4886
|
}
|
|
3914
4887
|
),
|
|
3915
|
-
|
|
3916
|
-
"
|
|
4888
|
+
aiOpen && /* @__PURE__ */ jsx15(FloatingPortal2, { children: /* @__PURE__ */ jsx15(
|
|
4889
|
+
"div",
|
|
3917
4890
|
{
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
children:
|
|
3923
|
-
/* @__PURE__ */ jsx10("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
3924
|
-
/* @__PURE__ */ jsx10("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
3925
|
-
] })
|
|
4891
|
+
ref: aiRefs.setFloating,
|
|
4892
|
+
className: "ya-container-tooltip",
|
|
4893
|
+
style: aiStyles,
|
|
4894
|
+
...getAiFloatProps(),
|
|
4895
|
+
children: "AI Assist"
|
|
3926
4896
|
}
|
|
3927
|
-
)
|
|
4897
|
+
) }),
|
|
4898
|
+
hasBackground && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
4899
|
+
/* @__PURE__ */ jsx15(
|
|
4900
|
+
"button",
|
|
4901
|
+
{
|
|
4902
|
+
ref: clearRefs.setReference,
|
|
4903
|
+
type: "button",
|
|
4904
|
+
onClick: onClearClick,
|
|
4905
|
+
"aria-label": "Clear background",
|
|
4906
|
+
...getClearRefProps(),
|
|
4907
|
+
children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4908
|
+
/* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "10" }),
|
|
4909
|
+
/* @__PURE__ */ jsx15("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
|
|
4910
|
+
] })
|
|
4911
|
+
}
|
|
4912
|
+
),
|
|
4913
|
+
clearOpen && /* @__PURE__ */ jsx15(FloatingPortal2, { children: /* @__PURE__ */ jsx15(
|
|
4914
|
+
"div",
|
|
4915
|
+
{
|
|
4916
|
+
ref: clearRefs.setFloating,
|
|
4917
|
+
className: "ya-container-tooltip",
|
|
4918
|
+
style: clearStyles,
|
|
4919
|
+
...getClearFloatProps(),
|
|
4920
|
+
children: "Remove Background"
|
|
4921
|
+
}
|
|
4922
|
+
) })
|
|
4923
|
+
] })
|
|
3928
4924
|
]
|
|
3929
4925
|
}
|
|
3930
4926
|
),
|
|
@@ -3940,11 +4936,33 @@ function YaContainer({
|
|
|
3940
4936
|
defaultBackground
|
|
3941
4937
|
}) {
|
|
3942
4938
|
const { getValue, setValue, saveToWorker, mode } = useContentStore();
|
|
3943
|
-
const containerRef =
|
|
3944
|
-
const [isHovered, setIsHovered] =
|
|
3945
|
-
const [isSelected, setIsSelected] =
|
|
3946
|
-
const [isDropMode, setIsDropMode] =
|
|
3947
|
-
const [isDropHover, setIsDropHover] =
|
|
4939
|
+
const containerRef = useRef13(null);
|
|
4940
|
+
const [isHovered, setIsHovered] = useState12(false);
|
|
4941
|
+
const [isSelected, setIsSelected] = useState12(false);
|
|
4942
|
+
const [isDropMode, setIsDropMode] = useState12(false);
|
|
4943
|
+
const [isDropHover, setIsDropHover] = useState12(false);
|
|
4944
|
+
useEffect13(() => {
|
|
4945
|
+
if (mode !== "inline-edit") return;
|
|
4946
|
+
const containerEl = containerRef.current;
|
|
4947
|
+
if (!containerEl) return;
|
|
4948
|
+
let lastHovered = false;
|
|
4949
|
+
let lastCheckTime = 0;
|
|
4950
|
+
const THROTTLE_MS = 16;
|
|
4951
|
+
const checkMousePosition = (e) => {
|
|
4952
|
+
const now = performance.now();
|
|
4953
|
+
if (now - lastCheckTime < THROTTLE_MS) return;
|
|
4954
|
+
lastCheckTime = now;
|
|
4955
|
+
const rect = containerEl.getBoundingClientRect();
|
|
4956
|
+
const { clientX: x, clientY: y } = e;
|
|
4957
|
+
const isInside = x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
|
|
4958
|
+
if (isInside !== lastHovered) {
|
|
4959
|
+
lastHovered = isInside;
|
|
4960
|
+
setIsHovered(isInside);
|
|
4961
|
+
}
|
|
4962
|
+
};
|
|
4963
|
+
window.addEventListener("mousemove", checkMousePosition, { passive: true });
|
|
4964
|
+
return () => window.removeEventListener("mousemove", checkMousePosition);
|
|
4965
|
+
}, [mode]);
|
|
3948
4966
|
const rawValue = getValue(fieldId);
|
|
3949
4967
|
const backgroundConfig = rawValue ? parseBackgroundConfig(rawValue) : defaultBackground || { type: "none" };
|
|
3950
4968
|
const hasBackground = backgroundConfig.type !== "none";
|
|
@@ -3965,7 +4983,7 @@ function YaContainer({
|
|
|
3965
4983
|
overlayCustomProps["--ya-overlay-color"] = backgroundConfig.overlay.color;
|
|
3966
4984
|
overlayCustomProps["--ya-overlay-opacity"] = backgroundConfig.overlay.opacity;
|
|
3967
4985
|
}
|
|
3968
|
-
const handleImageClick =
|
|
4986
|
+
const handleImageClick = useCallback14(() => {
|
|
3969
4987
|
if (mode !== "inline-edit") return;
|
|
3970
4988
|
setIsSelected(true);
|
|
3971
4989
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
@@ -3985,7 +5003,7 @@ function YaContainer({
|
|
|
3985
5003
|
"*"
|
|
3986
5004
|
);
|
|
3987
5005
|
}, [mode, fieldId, backgroundConfig]);
|
|
3988
|
-
const handleColorClick =
|
|
5006
|
+
const handleColorClick = useCallback14(() => {
|
|
3989
5007
|
if (mode !== "inline-edit") return;
|
|
3990
5008
|
setIsSelected(true);
|
|
3991
5009
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
@@ -4005,7 +5023,7 @@ function YaContainer({
|
|
|
4005
5023
|
"*"
|
|
4006
5024
|
);
|
|
4007
5025
|
}, [mode, fieldId, backgroundConfig]);
|
|
4008
|
-
const handleAIClick =
|
|
5026
|
+
const handleAIClick = useCallback14(() => {
|
|
4009
5027
|
if (mode !== "inline-edit") return;
|
|
4010
5028
|
const label = deriveContainerLabel(containerRef.current);
|
|
4011
5029
|
window.parent.postMessage(
|
|
@@ -4018,14 +5036,14 @@ function YaContainer({
|
|
|
4018
5036
|
"*"
|
|
4019
5037
|
);
|
|
4020
5038
|
}, [mode, fieldId, backgroundConfig]);
|
|
4021
|
-
const handleClearClick =
|
|
5039
|
+
const handleClearClick = useCallback14(() => {
|
|
4022
5040
|
if (mode !== "inline-edit") return;
|
|
4023
5041
|
const clearedConfig = { type: "none" };
|
|
4024
5042
|
const serialized = serializeBackgroundConfig(clearedConfig);
|
|
4025
5043
|
setValue(fieldId, serialized);
|
|
4026
5044
|
saveToWorker?.(fieldId, serialized);
|
|
4027
5045
|
}, [mode, fieldId, setValue, saveToWorker]);
|
|
4028
|
-
|
|
5046
|
+
useEffect13(() => {
|
|
4029
5047
|
if (mode !== "inline-edit") return;
|
|
4030
5048
|
const handleMessage2 = (event) => {
|
|
4031
5049
|
if (event.data?.type === "YA_CONTAINER_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
|
|
@@ -4038,7 +5056,7 @@ function YaContainer({
|
|
|
4038
5056
|
window.addEventListener("message", handleMessage2);
|
|
4039
5057
|
return () => window.removeEventListener("message", handleMessage2);
|
|
4040
5058
|
}, [mode, fieldId]);
|
|
4041
|
-
|
|
5059
|
+
useEffect13(() => {
|
|
4042
5060
|
if (mode !== "inline-edit") return;
|
|
4043
5061
|
const handleDropModeMessage = (event) => {
|
|
4044
5062
|
if (event.data?.type === "DROP_MODE_START") {
|
|
@@ -4052,7 +5070,7 @@ function YaContainer({
|
|
|
4052
5070
|
window.addEventListener("message", handleDropModeMessage);
|
|
4053
5071
|
return () => window.removeEventListener("message", handleDropModeMessage);
|
|
4054
5072
|
}, [mode]);
|
|
4055
|
-
const handleDragEnter =
|
|
5073
|
+
const handleDragEnter = useCallback14(
|
|
4056
5074
|
(e) => {
|
|
4057
5075
|
if (!isDropMode) return;
|
|
4058
5076
|
e.preventDefault();
|
|
@@ -4076,7 +5094,7 @@ function YaContainer({
|
|
|
4076
5094
|
},
|
|
4077
5095
|
[isDropMode, fieldId]
|
|
4078
5096
|
);
|
|
4079
|
-
const handleDragOver =
|
|
5097
|
+
const handleDragOver = useCallback14(
|
|
4080
5098
|
(e) => {
|
|
4081
5099
|
if (!isDropMode) return;
|
|
4082
5100
|
e.preventDefault();
|
|
@@ -4084,7 +5102,7 @@ function YaContainer({
|
|
|
4084
5102
|
},
|
|
4085
5103
|
[isDropMode]
|
|
4086
5104
|
);
|
|
4087
|
-
const handleDragLeave =
|
|
5105
|
+
const handleDragLeave = useCallback14(
|
|
4088
5106
|
(e) => {
|
|
4089
5107
|
if (!isDropMode) return;
|
|
4090
5108
|
e.preventDefault();
|
|
@@ -4098,7 +5116,7 @@ function YaContainer({
|
|
|
4098
5116
|
},
|
|
4099
5117
|
[isDropMode]
|
|
4100
5118
|
);
|
|
4101
|
-
const handleDrop =
|
|
5119
|
+
const handleDrop = useCallback14(
|
|
4102
5120
|
(e) => {
|
|
4103
5121
|
if (!isDropMode) return;
|
|
4104
5122
|
e.preventDefault();
|
|
@@ -4116,7 +5134,7 @@ function YaContainer({
|
|
|
4116
5134
|
},
|
|
4117
5135
|
[isDropMode, fieldId]
|
|
4118
5136
|
);
|
|
4119
|
-
|
|
5137
|
+
useEffect13(() => {
|
|
4120
5138
|
if (!isSelected || mode !== "inline-edit") return;
|
|
4121
5139
|
let lastRectKey = "";
|
|
4122
5140
|
let lastTime = 0;
|
|
@@ -4151,7 +5169,7 @@ function YaContainer({
|
|
|
4151
5169
|
return () => cancelAnimationFrame(rafId);
|
|
4152
5170
|
}, [isSelected, fieldId, mode]);
|
|
4153
5171
|
if (mode === "read-only") {
|
|
4154
|
-
return /* @__PURE__ */
|
|
5172
|
+
return /* @__PURE__ */ jsx15(
|
|
4155
5173
|
Tag,
|
|
4156
5174
|
{
|
|
4157
5175
|
className: `ya-container ${className || ""}`,
|
|
@@ -4175,7 +5193,7 @@ function YaContainer({
|
|
|
4175
5193
|
isDropHover ? "ya-container-drop-hover" : "",
|
|
4176
5194
|
className || ""
|
|
4177
5195
|
].filter(Boolean).join(" ");
|
|
4178
|
-
return /* @__PURE__ */
|
|
5196
|
+
return /* @__PURE__ */ jsxs9(
|
|
4179
5197
|
Tag,
|
|
4180
5198
|
{
|
|
4181
5199
|
ref: containerRef,
|
|
@@ -4188,15 +5206,13 @@ function YaContainer({
|
|
|
4188
5206
|
"data-ya-restricted": "true",
|
|
4189
5207
|
"data-field-id": fieldId,
|
|
4190
5208
|
"data-ya-container": "true",
|
|
4191
|
-
onMouseEnter: () => setIsHovered(true),
|
|
4192
|
-
onMouseLeave: () => setIsHovered(false),
|
|
4193
5209
|
onDragEnter: handleDragEnter,
|
|
4194
5210
|
onDragOver: handleDragOver,
|
|
4195
5211
|
onDragLeave: handleDragLeave,
|
|
4196
5212
|
onDrop: handleDrop,
|
|
4197
5213
|
children: [
|
|
4198
5214
|
children,
|
|
4199
|
-
mode === "inline-edit" && (isHovered || isSelected) && !document.body.classList.contains("builder-selector-active") && /* @__PURE__ */
|
|
5215
|
+
mode === "inline-edit" && (isHovered || isSelected) && !document.body.classList.contains("builder-selector-active") && /* @__PURE__ */ jsx15(
|
|
4200
5216
|
Toolbar,
|
|
4201
5217
|
{
|
|
4202
5218
|
containerRef,
|
|
@@ -4213,10 +5229,10 @@ function YaContainer({
|
|
|
4213
5229
|
}
|
|
4214
5230
|
|
|
4215
5231
|
// src/components/StaticText.tsx
|
|
4216
|
-
import { jsx as
|
|
5232
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
4217
5233
|
function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
4218
5234
|
const content = getContent(fieldId) || (typeof children === "string" ? children : "");
|
|
4219
|
-
return /* @__PURE__ */
|
|
5235
|
+
return /* @__PURE__ */ jsx16(
|
|
4220
5236
|
Component,
|
|
4221
5237
|
{
|
|
4222
5238
|
className,
|
|
@@ -4227,7 +5243,7 @@ function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
|
4227
5243
|
}
|
|
4228
5244
|
|
|
4229
5245
|
// src/components/StaticImage.tsx
|
|
4230
|
-
import { jsx as
|
|
5246
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
4231
5247
|
function parseImageValue2(value) {
|
|
4232
5248
|
if (!value) {
|
|
4233
5249
|
return { src: "" };
|
|
@@ -4263,7 +5279,7 @@ function MpImage({
|
|
|
4263
5279
|
const altText = imageData.alt || alt || fallbackAlt || "";
|
|
4264
5280
|
const objectFit = imageData.objectFit || propObjectFit || "cover";
|
|
4265
5281
|
const objectPosition = getObjectPosition3(imageData) || propObjectPosition || "50% 50%";
|
|
4266
|
-
return /* @__PURE__ */
|
|
5282
|
+
return /* @__PURE__ */ jsx17(
|
|
4267
5283
|
"img",
|
|
4268
5284
|
{
|
|
4269
5285
|
src: resolveAssetUrl(src),
|
|
@@ -4280,8 +5296,8 @@ function MpImage({
|
|
|
4280
5296
|
}
|
|
4281
5297
|
|
|
4282
5298
|
// src/components/MarkdownText.tsx
|
|
4283
|
-
import { Fragment as
|
|
4284
|
-
import { jsx as
|
|
5299
|
+
import { Fragment as Fragment6 } from "react";
|
|
5300
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
4285
5301
|
function tokenize(text) {
|
|
4286
5302
|
const tokens = [];
|
|
4287
5303
|
let remaining = text;
|
|
@@ -4343,13 +5359,13 @@ function tokensToElements(tokens) {
|
|
|
4343
5359
|
return tokens.map((token, index) => {
|
|
4344
5360
|
switch (token.type) {
|
|
4345
5361
|
case "text":
|
|
4346
|
-
return /* @__PURE__ */
|
|
5362
|
+
return /* @__PURE__ */ jsx18(Fragment6, { children: token.content }, index);
|
|
4347
5363
|
case "bold":
|
|
4348
|
-
return /* @__PURE__ */
|
|
5364
|
+
return /* @__PURE__ */ jsx18("strong", { children: token.content }, index);
|
|
4349
5365
|
case "italic":
|
|
4350
|
-
return /* @__PURE__ */
|
|
5366
|
+
return /* @__PURE__ */ jsx18("em", { children: token.content }, index);
|
|
4351
5367
|
case "link":
|
|
4352
|
-
return /* @__PURE__ */
|
|
5368
|
+
return /* @__PURE__ */ jsx18(
|
|
4353
5369
|
"a",
|
|
4354
5370
|
{
|
|
4355
5371
|
href: token.url,
|
|
@@ -4361,7 +5377,7 @@ function tokensToElements(tokens) {
|
|
|
4361
5377
|
index
|
|
4362
5378
|
);
|
|
4363
5379
|
case "newline":
|
|
4364
|
-
return /* @__PURE__ */
|
|
5380
|
+
return /* @__PURE__ */ jsx18("br", {}, index);
|
|
4365
5381
|
default:
|
|
4366
5382
|
return null;
|
|
4367
5383
|
}
|
|
@@ -4373,15 +5389,15 @@ function parseMarkdownToElements(content) {
|
|
|
4373
5389
|
}
|
|
4374
5390
|
function MarkdownText({ content, className }) {
|
|
4375
5391
|
const elements = parseMarkdownToElements(content);
|
|
4376
|
-
return /* @__PURE__ */
|
|
5392
|
+
return /* @__PURE__ */ jsx18("span", { className, children: elements });
|
|
4377
5393
|
}
|
|
4378
5394
|
|
|
4379
5395
|
// src/router/Link.tsx
|
|
4380
5396
|
import { Link as WouterLink2 } from "wouter";
|
|
4381
|
-
import { jsx as
|
|
5397
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
4382
5398
|
function Link2({ to, href, children, className, onClick, replace, ...props }) {
|
|
4383
5399
|
const target = href ?? to ?? "/";
|
|
4384
|
-
return /* @__PURE__ */
|
|
5400
|
+
return /* @__PURE__ */ jsx19(WouterLink2, { href: target, className, onClick, replace, ...props, children });
|
|
4385
5401
|
}
|
|
4386
5402
|
|
|
4387
5403
|
// src/router/useNavigate.ts
|
|
@@ -4400,7 +5416,7 @@ function useNavigate() {
|
|
|
4400
5416
|
|
|
4401
5417
|
// src/router/Router.tsx
|
|
4402
5418
|
import { Router as WouterRouter } from "wouter";
|
|
4403
|
-
import { jsx as
|
|
5419
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
4404
5420
|
function detectBasename() {
|
|
4405
5421
|
if (typeof window === "undefined") return "";
|
|
4406
5422
|
const sessionMatch = window.location.pathname.match(/^\/session\/[^/]+/);
|
|
@@ -4415,7 +5431,7 @@ function detectBasename() {
|
|
|
4415
5431
|
}
|
|
4416
5432
|
function Router({ children, base }) {
|
|
4417
5433
|
const basename = base ?? detectBasename();
|
|
4418
|
-
return /* @__PURE__ */
|
|
5434
|
+
return /* @__PURE__ */ jsx20(WouterRouter, { base: basename, children });
|
|
4419
5435
|
}
|
|
4420
5436
|
|
|
4421
5437
|
// src/router/index.ts
|
|
@@ -4429,6 +5445,7 @@ export {
|
|
|
4429
5445
|
Route,
|
|
4430
5446
|
Router,
|
|
4431
5447
|
SafeHtml,
|
|
5448
|
+
SafeTriangleBelow,
|
|
4432
5449
|
MpImage as StaticImage,
|
|
4433
5450
|
MpText as StaticText,
|
|
4434
5451
|
Switch,
|
|
@@ -4465,5 +5482,6 @@ export {
|
|
|
4465
5482
|
useContentStore,
|
|
4466
5483
|
useContentStore2 as useContentStoreProd,
|
|
4467
5484
|
useNavigate,
|
|
4468
|
-
useParams
|
|
5485
|
+
useParams,
|
|
5486
|
+
useSafeTriangle
|
|
4469
5487
|
};
|