@yoamigo.com/core 0.2.2 → 0.3.1
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/{MarkdownText-kV5IiAma.d.ts → MarkdownText-BUTYfqXS.d.ts} +3 -3
- package/dist/index.d.ts +16 -13
- package/dist/index.js +1403 -546
- package/dist/plugin.js +1 -1
- package/dist/prod.d.ts +99 -5
- package/dist/prod.js +300 -4
- 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() {
|
|
@@ -2030,27 +2551,18 @@ var FontWeight = Extension.create({
|
|
|
2030
2551
|
},
|
|
2031
2552
|
unsetFontWeight: () => ({ chain }) => {
|
|
2032
2553
|
return chain().setMark("textStyle", { fontWeight: null }).removeEmptyTextStyle().run();
|
|
2033
|
-
}
|
|
2034
|
-
};
|
|
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
|
-
};
|
|
2554
|
+
}
|
|
2555
|
+
};
|
|
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: "" };
|
|
@@ -2922,12 +3560,12 @@ function YaVideo({
|
|
|
2922
3560
|
fallbackPoster
|
|
2923
3561
|
}) {
|
|
2924
3562
|
const { getValue, mode } = useContentStore();
|
|
2925
|
-
const containerRef =
|
|
2926
|
-
const videoRef =
|
|
2927
|
-
const [isSelected, setIsSelected] =
|
|
2928
|
-
const [isHovered, setIsHovered] =
|
|
2929
|
-
const [isSmallVideo, setIsSmallVideo] =
|
|
2930
|
-
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");
|
|
2931
3569
|
const rawValue = getValue(fieldId);
|
|
2932
3570
|
const parsedValue = parseVideoValue(rawValue);
|
|
2933
3571
|
const videoData = parsedValue.src ? parsedValue : defaultValue || parsedValue;
|
|
@@ -2941,8 +3579,8 @@ function YaVideo({
|
|
|
2941
3579
|
const controls = videoData.controls ?? true;
|
|
2942
3580
|
const playsinline = videoData.playsinline ?? true;
|
|
2943
3581
|
const preload = videoData.preload ?? "metadata";
|
|
2944
|
-
const [prefersReducedMotion, setPrefersReducedMotion] =
|
|
2945
|
-
|
|
3582
|
+
const [prefersReducedMotion, setPrefersReducedMotion] = useState8(false);
|
|
3583
|
+
useEffect9(() => {
|
|
2946
3584
|
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
2947
3585
|
setPrefersReducedMotion(mediaQuery.matches);
|
|
2948
3586
|
const handleChange = (e) => {
|
|
@@ -2952,7 +3590,7 @@ function YaVideo({
|
|
|
2952
3590
|
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
2953
3591
|
}, []);
|
|
2954
3592
|
const effectiveAutoplay = autoplay && !prefersReducedMotion;
|
|
2955
|
-
|
|
3593
|
+
useEffect9(() => {
|
|
2956
3594
|
if (loading === "eager" || isInView) return;
|
|
2957
3595
|
const observer = new IntersectionObserver(
|
|
2958
3596
|
(entries) => {
|
|
@@ -2969,7 +3607,7 @@ function YaVideo({
|
|
|
2969
3607
|
}
|
|
2970
3608
|
return () => observer.disconnect();
|
|
2971
3609
|
}, [loading, isInView]);
|
|
2972
|
-
const handleKeyDown =
|
|
3610
|
+
const handleKeyDown = useCallback10(
|
|
2973
3611
|
(e) => {
|
|
2974
3612
|
if ((e.key === " " || e.key === "Enter") && videoData.type === "upload" && controls) {
|
|
2975
3613
|
e.preventDefault();
|
|
@@ -2985,7 +3623,7 @@ function YaVideo({
|
|
|
2985
3623
|
},
|
|
2986
3624
|
[videoData.type, controls]
|
|
2987
3625
|
);
|
|
2988
|
-
const handleClick =
|
|
3626
|
+
const handleClick = useCallback10(() => {
|
|
2989
3627
|
if (mode !== "inline-edit") return;
|
|
2990
3628
|
if (document.body.classList.contains("builder-selector-active")) return;
|
|
2991
3629
|
setIsSelected(true);
|
|
@@ -3005,7 +3643,7 @@ function YaVideo({
|
|
|
3005
3643
|
"*"
|
|
3006
3644
|
);
|
|
3007
3645
|
}, [mode, fieldId, videoData]);
|
|
3008
|
-
|
|
3646
|
+
useEffect9(() => {
|
|
3009
3647
|
if (mode !== "inline-edit") return;
|
|
3010
3648
|
const handleMessage2 = (event) => {
|
|
3011
3649
|
if (event.data?.type === "YA_VIDEO_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
|
|
@@ -3018,7 +3656,7 @@ function YaVideo({
|
|
|
3018
3656
|
window.addEventListener("message", handleMessage2);
|
|
3019
3657
|
return () => window.removeEventListener("message", handleMessage2);
|
|
3020
3658
|
}, [mode, fieldId]);
|
|
3021
|
-
|
|
3659
|
+
useEffect9(() => {
|
|
3022
3660
|
if (mode !== "inline-edit") return;
|
|
3023
3661
|
const checkSize = () => {
|
|
3024
3662
|
if (containerRef.current) {
|
|
@@ -3030,7 +3668,7 @@ function YaVideo({
|
|
|
3030
3668
|
window.addEventListener("resize", checkSize);
|
|
3031
3669
|
return () => window.removeEventListener("resize", checkSize);
|
|
3032
3670
|
}, [mode]);
|
|
3033
|
-
|
|
3671
|
+
useEffect9(() => {
|
|
3034
3672
|
if (!isSelected || mode !== "inline-edit") return;
|
|
3035
3673
|
let lastRectKey = "";
|
|
3036
3674
|
let lastTime = 0;
|
|
@@ -3066,24 +3704,24 @@ function YaVideo({
|
|
|
3066
3704
|
}, [isSelected, fieldId, mode]);
|
|
3067
3705
|
const renderVideo = (isReadOnly) => {
|
|
3068
3706
|
if (!src && !isReadOnly) {
|
|
3069
|
-
return /* @__PURE__ */
|
|
3070
|
-
/* @__PURE__ */
|
|
3071
|
-
/* @__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" })
|
|
3072
3710
|
] });
|
|
3073
3711
|
}
|
|
3074
3712
|
if (!isInView && loading === "lazy" && !isReadOnly) {
|
|
3075
|
-
return /* @__PURE__ */
|
|
3713
|
+
return /* @__PURE__ */ jsx13(
|
|
3076
3714
|
"div",
|
|
3077
3715
|
{
|
|
3078
3716
|
className: "ya-video-placeholder",
|
|
3079
3717
|
style: { aspectRatio },
|
|
3080
|
-
children: /* @__PURE__ */
|
|
3718
|
+
children: /* @__PURE__ */ jsx13("img", { src: PLACEHOLDER_SVG2, alt: "" })
|
|
3081
3719
|
}
|
|
3082
3720
|
);
|
|
3083
3721
|
}
|
|
3084
3722
|
if (videoData.type === "youtube" && src) {
|
|
3085
3723
|
const embedUrl = buildYouTubeEmbedUrl(src, videoData);
|
|
3086
|
-
return /* @__PURE__ */
|
|
3724
|
+
return /* @__PURE__ */ jsx13(
|
|
3087
3725
|
"iframe",
|
|
3088
3726
|
{
|
|
3089
3727
|
src: embedUrl,
|
|
@@ -3103,7 +3741,7 @@ function YaVideo({
|
|
|
3103
3741
|
}
|
|
3104
3742
|
if (videoData.type === "vimeo" && src) {
|
|
3105
3743
|
const embedUrl = buildVimeoEmbedUrl(src, videoData);
|
|
3106
|
-
return /* @__PURE__ */
|
|
3744
|
+
return /* @__PURE__ */ jsx13(
|
|
3107
3745
|
"iframe",
|
|
3108
3746
|
{
|
|
3109
3747
|
src: embedUrl,
|
|
@@ -3123,7 +3761,7 @@ function YaVideo({
|
|
|
3123
3761
|
}
|
|
3124
3762
|
const resolvedSrc = resolveAssetUrl(src);
|
|
3125
3763
|
const resolvedPoster = poster ? resolveAssetUrl(poster) : void 0;
|
|
3126
|
-
return /* @__PURE__ */
|
|
3764
|
+
return /* @__PURE__ */ jsx13(
|
|
3127
3765
|
"video",
|
|
3128
3766
|
{
|
|
3129
3767
|
ref: videoRef,
|
|
@@ -3158,7 +3796,7 @@ function YaVideo({
|
|
|
3158
3796
|
);
|
|
3159
3797
|
};
|
|
3160
3798
|
if (mode === "read-only") {
|
|
3161
|
-
return /* @__PURE__ */
|
|
3799
|
+
return /* @__PURE__ */ jsx13(
|
|
3162
3800
|
"div",
|
|
3163
3801
|
{
|
|
3164
3802
|
ref: containerRef,
|
|
@@ -3174,7 +3812,7 @@ function YaVideo({
|
|
|
3174
3812
|
}
|
|
3175
3813
|
);
|
|
3176
3814
|
}
|
|
3177
|
-
const videoIcon = /* @__PURE__ */
|
|
3815
|
+
const videoIcon = /* @__PURE__ */ jsxs7(
|
|
3178
3816
|
"svg",
|
|
3179
3817
|
{
|
|
3180
3818
|
width: "24",
|
|
@@ -3186,12 +3824,12 @@ function YaVideo({
|
|
|
3186
3824
|
strokeLinecap: "round",
|
|
3187
3825
|
strokeLinejoin: "round",
|
|
3188
3826
|
children: [
|
|
3189
|
-
/* @__PURE__ */
|
|
3190
|
-
/* @__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" })
|
|
3191
3829
|
]
|
|
3192
3830
|
}
|
|
3193
3831
|
);
|
|
3194
|
-
return /* @__PURE__ */
|
|
3832
|
+
return /* @__PURE__ */ jsxs7(
|
|
3195
3833
|
"div",
|
|
3196
3834
|
{
|
|
3197
3835
|
ref: containerRef,
|
|
@@ -3214,14 +3852,14 @@ function YaVideo({
|
|
|
3214
3852
|
style: { aspectRatio },
|
|
3215
3853
|
children: [
|
|
3216
3854
|
renderVideo(false),
|
|
3217
|
-
isSmallVideo ? /* @__PURE__ */
|
|
3855
|
+
isSmallVideo ? /* @__PURE__ */ jsxs7(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
|
|
3218
3856
|
videoIcon,
|
|
3219
|
-
/* @__PURE__ */
|
|
3857
|
+
/* @__PURE__ */ jsx13("span", { children: "Click to edit" })
|
|
3220
3858
|
] }) : (
|
|
3221
3859
|
/* For large videos: show overlay inside the container */
|
|
3222
|
-
/* @__PURE__ */
|
|
3223
|
-
/* @__PURE__ */
|
|
3224
|
-
/* @__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" })
|
|
3225
3863
|
] })
|
|
3226
3864
|
)
|
|
3227
3865
|
]
|
|
@@ -3230,104 +3868,82 @@ function YaVideo({
|
|
|
3230
3868
|
}
|
|
3231
3869
|
|
|
3232
3870
|
// src/components/YaLink.tsx
|
|
3233
|
-
import { useEffect as
|
|
3871
|
+
import { useEffect as useEffect12, useRef as useRef12, useState as useState11, useCallback as useCallback13, useId } from "react";
|
|
3234
3872
|
import { createPortal as createPortal5 } from "react-dom";
|
|
3235
3873
|
import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
|
|
3236
|
-
import { BubbleMenu
|
|
3874
|
+
import { BubbleMenu } from "@tiptap/react/menus";
|
|
3237
3875
|
import StarterKit2 from "@tiptap/starter-kit";
|
|
3238
3876
|
import { TextStyle as TextStyle2 } from "@tiptap/extension-text-style";
|
|
3239
3877
|
import { Extension as Extension2 } from "@tiptap/core";
|
|
3240
3878
|
import { Link as WouterLink, useLocation } from "wouter";
|
|
3241
3879
|
|
|
3242
3880
|
// src/components/SafeTriangleBelow.tsx
|
|
3243
|
-
import { useEffect as
|
|
3244
|
-
import { createPortal as createPortal4 } from "react-dom";
|
|
3245
|
-
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
3881
|
+
import { useEffect as useEffect10, useState as useState9, useRef as useRef10, useCallback as useCallback11 } from "react";
|
|
3246
3882
|
function SafeTriangleBelow({
|
|
3247
3883
|
triggerRef,
|
|
3248
3884
|
popoverRef,
|
|
3249
3885
|
isVisible,
|
|
3250
|
-
onLeave
|
|
3886
|
+
onLeave,
|
|
3887
|
+
onStayInside
|
|
3251
3888
|
}) {
|
|
3252
|
-
const [
|
|
3253
|
-
const
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
return
|
|
3272
|
-
}
|
|
3273
|
-
const
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
position: "fixed",
|
|
3292
|
-
width: svgWidth,
|
|
3293
|
-
height: svgHeight,
|
|
3294
|
-
top: svgTop,
|
|
3295
|
-
left: svgLeft,
|
|
3296
|
-
pointerEvents: "none",
|
|
3297
|
-
zIndex: 9998
|
|
3298
|
-
},
|
|
3299
|
-
children: /* @__PURE__ */ jsx9(
|
|
3300
|
-
"path",
|
|
3301
|
-
{
|
|
3302
|
-
d: path,
|
|
3303
|
-
fill: "transparent",
|
|
3304
|
-
style: { pointerEvents: "auto" },
|
|
3305
|
-
onMouseLeave: onLeave
|
|
3306
|
-
}
|
|
3307
|
-
)
|
|
3308
|
-
}
|
|
3309
|
-
),
|
|
3310
|
-
document.body
|
|
3311
|
-
);
|
|
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;
|
|
3312
3928
|
}
|
|
3313
3929
|
|
|
3314
3930
|
// src/hooks/useSafeTriangle.ts
|
|
3315
|
-
import { useState as
|
|
3931
|
+
import { useState as useState10, useRef as useRef11, useCallback as useCallback12, useEffect as useEffect11 } from "react";
|
|
3316
3932
|
function useSafeTriangle(options = {}) {
|
|
3317
3933
|
const { showDelay = 0, hideDelay = 150, enabled = true } = options;
|
|
3318
|
-
const [isVisible, setIsVisible] =
|
|
3319
|
-
const [isHovering, setIsHovering] =
|
|
3320
|
-
const triggerRef =
|
|
3321
|
-
const popoverRef =
|
|
3322
|
-
const showTimeoutRef =
|
|
3323
|
-
const hideTimeoutRef =
|
|
3324
|
-
|
|
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(() => {
|
|
3325
3941
|
return () => {
|
|
3326
3942
|
if (showTimeoutRef.current) clearTimeout(showTimeoutRef.current);
|
|
3327
3943
|
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
3328
3944
|
};
|
|
3329
3945
|
}, []);
|
|
3330
|
-
const show =
|
|
3946
|
+
const show = useCallback12(() => {
|
|
3331
3947
|
if (!enabled) return;
|
|
3332
3948
|
if (hideTimeoutRef.current) {
|
|
3333
3949
|
clearTimeout(hideTimeoutRef.current);
|
|
@@ -3335,7 +3951,7 @@ function useSafeTriangle(options = {}) {
|
|
|
3335
3951
|
}
|
|
3336
3952
|
setIsVisible(true);
|
|
3337
3953
|
}, [enabled]);
|
|
3338
|
-
const hide =
|
|
3954
|
+
const hide = useCallback12(() => {
|
|
3339
3955
|
if (showTimeoutRef.current) {
|
|
3340
3956
|
clearTimeout(showTimeoutRef.current);
|
|
3341
3957
|
showTimeoutRef.current = null;
|
|
@@ -3343,7 +3959,7 @@ function useSafeTriangle(options = {}) {
|
|
|
3343
3959
|
setIsVisible(false);
|
|
3344
3960
|
setIsHovering(false);
|
|
3345
3961
|
}, []);
|
|
3346
|
-
const handleMouseEnter =
|
|
3962
|
+
const handleMouseEnter = useCallback12(() => {
|
|
3347
3963
|
if (!enabled) return;
|
|
3348
3964
|
setIsHovering(true);
|
|
3349
3965
|
if (hideTimeoutRef.current) {
|
|
@@ -3358,7 +3974,7 @@ function useSafeTriangle(options = {}) {
|
|
|
3358
3974
|
setIsVisible(true);
|
|
3359
3975
|
}
|
|
3360
3976
|
}, [showDelay, enabled]);
|
|
3361
|
-
const handleMouseLeave =
|
|
3977
|
+
const handleMouseLeave = useCallback12(() => {
|
|
3362
3978
|
setIsHovering(false);
|
|
3363
3979
|
if (showTimeoutRef.current) {
|
|
3364
3980
|
clearTimeout(showTimeoutRef.current);
|
|
@@ -3368,15 +3984,21 @@ function useSafeTriangle(options = {}) {
|
|
|
3368
3984
|
setIsVisible(false);
|
|
3369
3985
|
}, hideDelay);
|
|
3370
3986
|
}, [hideDelay]);
|
|
3371
|
-
const handleFocus =
|
|
3987
|
+
const handleFocus = useCallback12(() => {
|
|
3372
3988
|
if (!enabled) return;
|
|
3373
3989
|
setIsVisible(true);
|
|
3374
3990
|
}, [enabled]);
|
|
3375
|
-
const handleTriangleLeave =
|
|
3991
|
+
const handleTriangleLeave = useCallback12(() => {
|
|
3376
3992
|
if (!isHovering) {
|
|
3377
3993
|
setIsVisible(false);
|
|
3378
3994
|
}
|
|
3379
3995
|
}, [isHovering]);
|
|
3996
|
+
const handleStayInside = useCallback12(() => {
|
|
3997
|
+
if (hideTimeoutRef.current) {
|
|
3998
|
+
clearTimeout(hideTimeoutRef.current);
|
|
3999
|
+
hideTimeoutRef.current = null;
|
|
4000
|
+
}
|
|
4001
|
+
}, []);
|
|
3380
4002
|
return {
|
|
3381
4003
|
triggerRef,
|
|
3382
4004
|
popoverRef,
|
|
@@ -3390,7 +4012,8 @@ function useSafeTriangle(options = {}) {
|
|
|
3390
4012
|
triggerRef,
|
|
3391
4013
|
popoverRef,
|
|
3392
4014
|
isVisible,
|
|
3393
|
-
onLeave: handleTriangleLeave
|
|
4015
|
+
onLeave: handleTriangleLeave,
|
|
4016
|
+
onStayInside: handleStayInside
|
|
3394
4017
|
},
|
|
3395
4018
|
show,
|
|
3396
4019
|
hide
|
|
@@ -3398,10 +4021,10 @@ function useSafeTriangle(options = {}) {
|
|
|
3398
4021
|
}
|
|
3399
4022
|
|
|
3400
4023
|
// src/components/ya-link.css
|
|
3401
|
-
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');
|
|
3402
4025
|
|
|
3403
4026
|
// src/components/YaLink.tsx
|
|
3404
|
-
import { Fragment as
|
|
4027
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3405
4028
|
function isInternalPath(path) {
|
|
3406
4029
|
if (!path) return false;
|
|
3407
4030
|
if (path.startsWith("#")) return false;
|
|
@@ -3502,8 +4125,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3502
4125
|
const { getValue, setValue, mode, saveToWorker, getPages } = useContentStore();
|
|
3503
4126
|
const [, navigate] = useLocation();
|
|
3504
4127
|
const pages = availablePages ?? getPages();
|
|
3505
|
-
const [sections, setSections] =
|
|
3506
|
-
const [sectionsExpanded, setSectionsExpanded] =
|
|
4128
|
+
const [sections, setSections] = useState11([]);
|
|
4129
|
+
const [sectionsExpanded, setSectionsExpanded] = useState11(false);
|
|
3507
4130
|
const textFieldId = `${fieldId}.text`;
|
|
3508
4131
|
const hrefFieldId = `${fieldId}.href`;
|
|
3509
4132
|
const storeText = getValue(textFieldId);
|
|
@@ -3514,14 +4137,20 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3514
4137
|
const isExternal = isExternalHref(href);
|
|
3515
4138
|
const effectiveTarget = target ?? (isExternal ? "_blank" : void 0);
|
|
3516
4139
|
const effectiveRel = rel ?? (isExternal ? "noopener noreferrer" : void 0);
|
|
3517
|
-
const [editingMode, setEditingMode] =
|
|
3518
|
-
const [originalText, setOriginalText] =
|
|
3519
|
-
const [originalHref, setOriginalHref] =
|
|
3520
|
-
const [currentHref, setCurrentHref] =
|
|
3521
|
-
const [isExternalUrl, setIsExternalUrl] =
|
|
3522
|
-
const [externalUrl, setExternalUrl] =
|
|
3523
|
-
const
|
|
3524
|
-
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
|
+
});
|
|
3525
4154
|
const {
|
|
3526
4155
|
popoverRef: editPopoverRef,
|
|
3527
4156
|
isVisible: showEditPopover,
|
|
@@ -3533,6 +4162,22 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3533
4162
|
hideDelay: 150
|
|
3534
4163
|
});
|
|
3535
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]);
|
|
3536
4181
|
const editor = useEditor2({
|
|
3537
4182
|
extensions: [
|
|
3538
4183
|
StarterKit2.configure({
|
|
@@ -3552,22 +4197,62 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3552
4197
|
editorProps: {
|
|
3553
4198
|
attributes: {
|
|
3554
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;
|
|
3555
4219
|
}
|
|
3556
4220
|
}
|
|
3557
4221
|
});
|
|
3558
|
-
|
|
4222
|
+
useEffect12(() => {
|
|
3559
4223
|
if (editor && editingMode !== "text") {
|
|
3560
4224
|
if (editor.getHTML() !== text) {
|
|
3561
4225
|
editor.commands.setContent(text);
|
|
3562
4226
|
}
|
|
3563
4227
|
}
|
|
3564
4228
|
}, [text, editor, editingMode]);
|
|
3565
|
-
|
|
4229
|
+
useEffect12(() => {
|
|
3566
4230
|
if (editingMode !== "link") {
|
|
3567
4231
|
setCurrentHref(href);
|
|
3568
4232
|
}
|
|
3569
4233
|
}, [href, editingMode]);
|
|
3570
|
-
|
|
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);
|
|
4250
|
+
return () => {
|
|
4251
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
4252
|
+
window.removeEventListener("resize", updatePosition);
|
|
4253
|
+
};
|
|
4254
|
+
}, [editingMode]);
|
|
4255
|
+
useEffect12(() => {
|
|
3571
4256
|
if (editingMode !== "link") return;
|
|
3572
4257
|
const handleClickOutside = (event) => {
|
|
3573
4258
|
const target2 = event.target;
|
|
@@ -3581,34 +4266,51 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3581
4266
|
document.addEventListener("mousedown", handleClickOutside);
|
|
3582
4267
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
3583
4268
|
}, [editingMode, originalHref]);
|
|
3584
|
-
|
|
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(() => {
|
|
3585
4283
|
if (!editor) return;
|
|
3586
4284
|
let html = editor.getHTML();
|
|
3587
4285
|
html = html.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
|
|
3588
|
-
setValue(textFieldId, html);
|
|
4286
|
+
setValue(textFieldId, html, "user");
|
|
3589
4287
|
saveToWorker?.(textFieldId, html);
|
|
3590
4288
|
setEditingMode(null);
|
|
3591
4289
|
}, [editor, textFieldId, setValue, saveToWorker]);
|
|
3592
|
-
const handleSaveLink =
|
|
3593
|
-
setValue(hrefFieldId, currentHref);
|
|
4290
|
+
const handleSaveLink = useCallback13(() => {
|
|
4291
|
+
setValue(hrefFieldId, currentHref, "user");
|
|
3594
4292
|
saveToWorker?.(hrefFieldId, currentHref);
|
|
3595
4293
|
setEditingMode(null);
|
|
3596
4294
|
setIsExternalUrl(false);
|
|
3597
4295
|
setExternalUrl("");
|
|
3598
4296
|
}, [hrefFieldId, currentHref, setValue, saveToWorker]);
|
|
3599
|
-
const handleCancelText =
|
|
4297
|
+
const handleCancelText = useCallback13(() => {
|
|
3600
4298
|
if (editor) {
|
|
3601
4299
|
editor.commands.setContent(originalText);
|
|
3602
4300
|
}
|
|
3603
4301
|
setEditingMode(null);
|
|
3604
4302
|
}, [editor, originalText]);
|
|
3605
|
-
const handleCancelLink =
|
|
4303
|
+
const handleCancelLink = useCallback13(() => {
|
|
3606
4304
|
setCurrentHref(originalHref);
|
|
3607
4305
|
setEditingMode(null);
|
|
3608
4306
|
setIsExternalUrl(false);
|
|
3609
4307
|
setExternalUrl("");
|
|
3610
4308
|
}, [originalHref]);
|
|
3611
|
-
|
|
4309
|
+
useEffect12(() => {
|
|
4310
|
+
handleSaveTextRef.current = handleSaveText;
|
|
4311
|
+
handleCancelTextRef.current = handleCancelText;
|
|
4312
|
+
}, [handleSaveText, handleCancelText]);
|
|
4313
|
+
const handleClick = useCallback13(
|
|
3612
4314
|
(e) => {
|
|
3613
4315
|
const selectModeEnabled = window.__builderSelectModeEnabled;
|
|
3614
4316
|
if (selectModeEnabled) {
|
|
@@ -3640,22 +4342,35 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3640
4342
|
},
|
|
3641
4343
|
[href, navigate, onClick]
|
|
3642
4344
|
);
|
|
3643
|
-
const startEditText =
|
|
4345
|
+
const startEditText = useCallback13(() => {
|
|
3644
4346
|
hideEditPopover();
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
}
|
|
3650
|
-
|
|
3651
|
-
|
|
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(() => {
|
|
3652
4360
|
hideEditPopover();
|
|
3653
4361
|
setEditingMode("link");
|
|
3654
4362
|
setOriginalHref(href);
|
|
3655
4363
|
setCurrentHref(href);
|
|
3656
4364
|
setSections(discoverSectionsFromDOM());
|
|
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
|
+
}
|
|
3657
4372
|
}, [href, hideEditPopover]);
|
|
3658
|
-
const handleKeyDown =
|
|
4373
|
+
const handleKeyDown = useCallback13(
|
|
3659
4374
|
(event) => {
|
|
3660
4375
|
if (editingMode !== "text") return;
|
|
3661
4376
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -3676,7 +4391,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3676
4391
|
},
|
|
3677
4392
|
[editingMode, handleSaveText, handleCancelText]
|
|
3678
4393
|
);
|
|
3679
|
-
const handleFontSizeChange =
|
|
4394
|
+
const handleFontSizeChange = useCallback13(
|
|
3680
4395
|
(e) => {
|
|
3681
4396
|
if (!editor) return;
|
|
3682
4397
|
const size = e.target.value;
|
|
@@ -3688,7 +4403,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3688
4403
|
},
|
|
3689
4404
|
[editor]
|
|
3690
4405
|
);
|
|
3691
|
-
const handleFontWeightChange =
|
|
4406
|
+
const handleFontWeightChange = useCallback13(
|
|
3692
4407
|
(e) => {
|
|
3693
4408
|
if (!editor) return;
|
|
3694
4409
|
const weight = e.target.value;
|
|
@@ -3700,11 +4415,11 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3700
4415
|
},
|
|
3701
4416
|
[editor]
|
|
3702
4417
|
);
|
|
3703
|
-
const handlePageSelect =
|
|
4418
|
+
const handlePageSelect = useCallback13((path) => {
|
|
3704
4419
|
setCurrentHref(path);
|
|
3705
4420
|
setIsExternalUrl(false);
|
|
3706
4421
|
}, []);
|
|
3707
|
-
const handleExternalUrlApply =
|
|
4422
|
+
const handleExternalUrlApply = useCallback13(() => {
|
|
3708
4423
|
if (externalUrl) {
|
|
3709
4424
|
setCurrentHref(externalUrl);
|
|
3710
4425
|
}
|
|
@@ -3720,9 +4435,9 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3720
4435
|
return attrs.fontWeight || "";
|
|
3721
4436
|
};
|
|
3722
4437
|
if (mode === "read-only") {
|
|
3723
|
-
const content = isIconMode ? children : /* @__PURE__ */
|
|
4438
|
+
const content = isIconMode ? children : /* @__PURE__ */ jsx14(SafeHtml, { content: text, mode });
|
|
3724
4439
|
if (isInternalPath(href)) {
|
|
3725
|
-
return /* @__PURE__ */
|
|
4440
|
+
return /* @__PURE__ */ jsx14(
|
|
3726
4441
|
WouterLink,
|
|
3727
4442
|
{
|
|
3728
4443
|
href,
|
|
@@ -3734,7 +4449,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3734
4449
|
}
|
|
3735
4450
|
);
|
|
3736
4451
|
}
|
|
3737
|
-
return /* @__PURE__ */
|
|
4452
|
+
return /* @__PURE__ */ jsx14(
|
|
3738
4453
|
Component,
|
|
3739
4454
|
{
|
|
3740
4455
|
ref: containerRef,
|
|
@@ -3749,8 +4464,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3749
4464
|
}
|
|
3750
4465
|
);
|
|
3751
4466
|
}
|
|
3752
|
-
return /* @__PURE__ */
|
|
3753
|
-
/* @__PURE__ */
|
|
4467
|
+
return /* @__PURE__ */ jsxs8("span", { className: "ya-link-wrapper", children: [
|
|
4468
|
+
/* @__PURE__ */ jsx14(
|
|
3754
4469
|
Component,
|
|
3755
4470
|
{
|
|
3756
4471
|
ref: containerRef,
|
|
@@ -3769,38 +4484,38 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3769
4484
|
children: isIconMode ? (
|
|
3770
4485
|
// Icon mode: render children directly, no text editing
|
|
3771
4486
|
children
|
|
3772
|
-
) : editor ? /* @__PURE__ */
|
|
4487
|
+
) : editor ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
3773
4488
|
createPortal5(
|
|
3774
|
-
/* @__PURE__ */
|
|
3775
|
-
|
|
4489
|
+
/* @__PURE__ */ jsxs8(
|
|
4490
|
+
BubbleMenu,
|
|
3776
4491
|
{
|
|
3777
4492
|
editor,
|
|
3778
4493
|
shouldShow: () => editingMode === "text",
|
|
3779
4494
|
options: { offset: 6, placement: "top" },
|
|
3780
4495
|
className: "ya-bubble-menu",
|
|
3781
4496
|
children: [
|
|
3782
|
-
/* @__PURE__ */
|
|
4497
|
+
/* @__PURE__ */ jsx14(
|
|
3783
4498
|
"button",
|
|
3784
4499
|
{
|
|
3785
4500
|
type: "button",
|
|
3786
4501
|
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
3787
4502
|
className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
|
|
3788
4503
|
title: "Bold",
|
|
3789
|
-
children: /* @__PURE__ */
|
|
4504
|
+
children: /* @__PURE__ */ jsx14("strong", { children: "B" })
|
|
3790
4505
|
}
|
|
3791
4506
|
),
|
|
3792
|
-
/* @__PURE__ */
|
|
4507
|
+
/* @__PURE__ */ jsx14(
|
|
3793
4508
|
"button",
|
|
3794
4509
|
{
|
|
3795
4510
|
type: "button",
|
|
3796
4511
|
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
3797
4512
|
className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
|
|
3798
4513
|
title: "Italic",
|
|
3799
|
-
children: /* @__PURE__ */
|
|
4514
|
+
children: /* @__PURE__ */ jsx14("em", { children: "I" })
|
|
3800
4515
|
}
|
|
3801
4516
|
),
|
|
3802
|
-
/* @__PURE__ */
|
|
3803
|
-
/* @__PURE__ */
|
|
4517
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-bubble-divider" }),
|
|
4518
|
+
/* @__PURE__ */ jsxs8(
|
|
3804
4519
|
"select",
|
|
3805
4520
|
{
|
|
3806
4521
|
value: getCurrentFontSize(),
|
|
@@ -3808,12 +4523,12 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3808
4523
|
className: "ya-bubble-select",
|
|
3809
4524
|
title: "Font Size",
|
|
3810
4525
|
children: [
|
|
3811
|
-
/* @__PURE__ */
|
|
3812
|
-
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))
|
|
3813
4528
|
]
|
|
3814
4529
|
}
|
|
3815
4530
|
),
|
|
3816
|
-
/* @__PURE__ */
|
|
4531
|
+
/* @__PURE__ */ jsxs8(
|
|
3817
4532
|
"select",
|
|
3818
4533
|
{
|
|
3819
4534
|
value: getCurrentFontWeight(),
|
|
@@ -3821,8 +4536,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3821
4536
|
className: "ya-bubble-select",
|
|
3822
4537
|
title: "Font Weight",
|
|
3823
4538
|
children: [
|
|
3824
|
-
/* @__PURE__ */
|
|
3825
|
-
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))
|
|
3826
4541
|
]
|
|
3827
4542
|
}
|
|
3828
4543
|
)
|
|
@@ -3831,17 +4546,31 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3831
4546
|
),
|
|
3832
4547
|
document.body
|
|
3833
4548
|
),
|
|
3834
|
-
editingMode === "text" ? /* @__PURE__ */
|
|
3835
|
-
/* @__PURE__ */
|
|
3836
|
-
|
|
3837
|
-
/* @__PURE__ */
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
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 })
|
|
3842
4571
|
}
|
|
3843
4572
|
),
|
|
3844
|
-
showEditPopover && !editingMode && mode === "inline-edit" && /* @__PURE__ */
|
|
4573
|
+
showEditPopover && !editingMode && mode === "inline-edit" && /* @__PURE__ */ jsxs8(
|
|
3845
4574
|
"div",
|
|
3846
4575
|
{
|
|
3847
4576
|
ref: editPopoverRef,
|
|
@@ -3849,39 +4578,40 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3849
4578
|
onMouseEnter: safeTriangleHandlers.onMouseEnter,
|
|
3850
4579
|
onMouseLeave: safeTriangleHandlers.onMouseLeave,
|
|
3851
4580
|
children: [
|
|
3852
|
-
|
|
3853
|
-
/* @__PURE__ */
|
|
4581
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: startEditText, children: "Edit text" }),
|
|
4582
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: startEditLink, children: "Edit link" })
|
|
3854
4583
|
]
|
|
3855
4584
|
}
|
|
3856
4585
|
),
|
|
3857
|
-
/* @__PURE__ */
|
|
4586
|
+
/* @__PURE__ */ jsx14(
|
|
3858
4587
|
SafeTriangleBelow,
|
|
3859
4588
|
{
|
|
3860
4589
|
triggerRef,
|
|
3861
4590
|
popoverRef: editPopoverRef,
|
|
3862
4591
|
isVisible: showEditPopover && !editingMode && mode === "inline-edit",
|
|
3863
|
-
onLeave: triangleProps.onLeave
|
|
4592
|
+
onLeave: triangleProps.onLeave,
|
|
4593
|
+
onStayInside: triangleProps.onStayInside
|
|
3864
4594
|
}
|
|
3865
4595
|
),
|
|
3866
|
-
editingMode === "link" && /* @__PURE__ */
|
|
3867
|
-
/* @__PURE__ */
|
|
3868
|
-
!isExternalUrl ? /* @__PURE__ */
|
|
3869
|
-
sections.length > 0 && /* @__PURE__ */
|
|
3870
|
-
/* @__PURE__ */
|
|
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(
|
|
3871
4601
|
"button",
|
|
3872
4602
|
{
|
|
3873
4603
|
type: "button",
|
|
3874
4604
|
className: "ya-href-popover-label ya-href-collapsible-header",
|
|
3875
4605
|
onClick: () => setSectionsExpanded(!sectionsExpanded),
|
|
3876
4606
|
children: [
|
|
3877
|
-
/* @__PURE__ */
|
|
4607
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-href-chevron", children: sectionsExpanded ? "\u25BC" : "\u25B6" }),
|
|
3878
4608
|
"Scroll to section (",
|
|
3879
4609
|
sections.length,
|
|
3880
4610
|
")"
|
|
3881
4611
|
]
|
|
3882
4612
|
}
|
|
3883
4613
|
),
|
|
3884
|
-
sectionsExpanded && /* @__PURE__ */
|
|
4614
|
+
sectionsExpanded && /* @__PURE__ */ jsx14("div", { className: "ya-href-popover-pages", children: sections.map((section) => /* @__PURE__ */ jsxs8(
|
|
3885
4615
|
"button",
|
|
3886
4616
|
{
|
|
3887
4617
|
type: "button",
|
|
@@ -3889,15 +4619,15 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3889
4619
|
onClick: () => handlePageSelect(section.path),
|
|
3890
4620
|
children: [
|
|
3891
4621
|
section.label,
|
|
3892
|
-
/* @__PURE__ */
|
|
4622
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-href-page-path", children: section.path })
|
|
3893
4623
|
]
|
|
3894
4624
|
},
|
|
3895
4625
|
section.path
|
|
3896
4626
|
)) })
|
|
3897
4627
|
] }),
|
|
3898
|
-
pages.length > 0 && /* @__PURE__ */
|
|
3899
|
-
/* @__PURE__ */
|
|
3900
|
-
/* @__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(
|
|
3901
4631
|
"button",
|
|
3902
4632
|
{
|
|
3903
4633
|
type: "button",
|
|
@@ -3905,13 +4635,13 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3905
4635
|
onClick: () => handlePageSelect(page.path),
|
|
3906
4636
|
children: [
|
|
3907
4637
|
page.label,
|
|
3908
|
-
/* @__PURE__ */
|
|
4638
|
+
/* @__PURE__ */ jsx14("span", { className: "ya-href-page-path", children: page.path })
|
|
3909
4639
|
]
|
|
3910
4640
|
},
|
|
3911
4641
|
page.path
|
|
3912
4642
|
)) })
|
|
3913
4643
|
] }),
|
|
3914
|
-
/* @__PURE__ */
|
|
4644
|
+
/* @__PURE__ */ jsx14(
|
|
3915
4645
|
"button",
|
|
3916
4646
|
{
|
|
3917
4647
|
type: "button",
|
|
@@ -3923,10 +4653,10 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3923
4653
|
children: "Use external URL instead"
|
|
3924
4654
|
}
|
|
3925
4655
|
)
|
|
3926
|
-
] }) : /* @__PURE__ */
|
|
3927
|
-
/* @__PURE__ */
|
|
3928
|
-
/* @__PURE__ */
|
|
3929
|
-
/* @__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(
|
|
3930
4660
|
"input",
|
|
3931
4661
|
{
|
|
3932
4662
|
type: "url",
|
|
@@ -3938,25 +4668,34 @@ function YaLink({ fieldId, href: defaultHref = "#", className, style, as: Compon
|
|
|
3938
4668
|
}
|
|
3939
4669
|
)
|
|
3940
4670
|
] }),
|
|
3941
|
-
/* @__PURE__ */
|
|
4671
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "ya-href-external-toggle", onClick: () => setIsExternalUrl(false), children: "\u2190 Back to pages" })
|
|
3942
4672
|
] }),
|
|
3943
|
-
/* @__PURE__ */
|
|
3944
|
-
/* @__PURE__ */
|
|
3945
|
-
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" })
|
|
3946
4676
|
] })
|
|
3947
4677
|
] })
|
|
3948
4678
|
] });
|
|
3949
4679
|
}
|
|
3950
4680
|
|
|
3951
4681
|
// src/components/YaContainer.tsx
|
|
3952
|
-
import { useCallback as
|
|
4682
|
+
import { useCallback as useCallback14, useEffect as useEffect13, useRef as useRef13, useState as useState12 } from "react";
|
|
3953
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";
|
|
3954
4693
|
|
|
3955
4694
|
// src/components/ya-container.css
|
|
3956
|
-
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');
|
|
3957
4696
|
|
|
3958
4697
|
// src/components/YaContainer.tsx
|
|
3959
|
-
import { jsx as
|
|
4698
|
+
import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3960
4699
|
function parseBackgroundConfig(value) {
|
|
3961
4700
|
if (!value) {
|
|
3962
4701
|
return { type: "none" };
|
|
@@ -3998,8 +4737,60 @@ function deriveContainerLabel(element) {
|
|
|
3998
4737
|
return tagLabels[tagName] || "Section";
|
|
3999
4738
|
}
|
|
4000
4739
|
function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick, onClearClick, hasBackground }) {
|
|
4001
|
-
const [position, setPosition] =
|
|
4002
|
-
|
|
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(() => {
|
|
4003
4794
|
const updatePosition = () => {
|
|
4004
4795
|
if (containerRef.current) {
|
|
4005
4796
|
const rect = containerRef.current.getBoundingClientRect();
|
|
@@ -4019,7 +4810,7 @@ function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick, onClearC
|
|
|
4019
4810
|
}, [containerRef]);
|
|
4020
4811
|
if (!position) return null;
|
|
4021
4812
|
return createPortal6(
|
|
4022
|
-
/* @__PURE__ */
|
|
4813
|
+
/* @__PURE__ */ jsxs9(
|
|
4023
4814
|
"div",
|
|
4024
4815
|
{
|
|
4025
4816
|
className: "ya-container-toolbar",
|
|
@@ -4030,60 +4821,106 @@ function Toolbar({ containerRef, onImageClick, onColorClick, onAIClick, onClearC
|
|
|
4030
4821
|
},
|
|
4031
4822
|
onClick: (e) => e.stopPropagation(),
|
|
4032
4823
|
children: [
|
|
4033
|
-
/* @__PURE__ */
|
|
4824
|
+
/* @__PURE__ */ jsx15(
|
|
4034
4825
|
"button",
|
|
4035
4826
|
{
|
|
4827
|
+
ref: imageRefs.setReference,
|
|
4036
4828
|
type: "button",
|
|
4037
4829
|
onClick: onImageClick,
|
|
4038
4830
|
"aria-label": "Edit background image",
|
|
4039
|
-
|
|
4040
|
-
children: /* @__PURE__ */
|
|
4041
|
-
/* @__PURE__ */
|
|
4042
|
-
/* @__PURE__ */
|
|
4043
|
-
/* @__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" })
|
|
4044
4836
|
] })
|
|
4045
4837
|
}
|
|
4046
4838
|
),
|
|
4047
|
-
/* @__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(
|
|
4048
4850
|
"button",
|
|
4049
4851
|
{
|
|
4852
|
+
ref: colorRefs.setReference,
|
|
4050
4853
|
type: "button",
|
|
4051
4854
|
onClick: onColorClick,
|
|
4052
4855
|
"aria-label": "Edit background color",
|
|
4053
|
-
|
|
4054
|
-
children: /* @__PURE__ */
|
|
4055
|
-
/* @__PURE__ */
|
|
4056
|
-
/* @__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" })
|
|
4057
4860
|
] })
|
|
4058
4861
|
}
|
|
4059
4862
|
),
|
|
4060
|
-
/* @__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(
|
|
4061
4874
|
"button",
|
|
4062
4875
|
{
|
|
4876
|
+
ref: aiRefs.setReference,
|
|
4063
4877
|
type: "button",
|
|
4064
4878
|
onClick: onAIClick,
|
|
4065
4879
|
"aria-label": "Ask AI for help",
|
|
4066
|
-
|
|
4067
|
-
children: /* @__PURE__ */
|
|
4068
|
-
/* @__PURE__ */
|
|
4069
|
-
/* @__PURE__ */
|
|
4070
|
-
/* @__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" })
|
|
4071
4885
|
] })
|
|
4072
4886
|
}
|
|
4073
4887
|
),
|
|
4074
|
-
|
|
4075
|
-
"
|
|
4888
|
+
aiOpen && /* @__PURE__ */ jsx15(FloatingPortal2, { children: /* @__PURE__ */ jsx15(
|
|
4889
|
+
"div",
|
|
4076
4890
|
{
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
children:
|
|
4082
|
-
/* @__PURE__ */ jsx11("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
4083
|
-
/* @__PURE__ */ jsx11("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
4084
|
-
] })
|
|
4891
|
+
ref: aiRefs.setFloating,
|
|
4892
|
+
className: "ya-container-tooltip",
|
|
4893
|
+
style: aiStyles,
|
|
4894
|
+
...getAiFloatProps(),
|
|
4895
|
+
children: "AI Assist"
|
|
4085
4896
|
}
|
|
4086
|
-
)
|
|
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
|
+
] })
|
|
4087
4924
|
]
|
|
4088
4925
|
}
|
|
4089
4926
|
),
|
|
@@ -4099,11 +4936,33 @@ function YaContainer({
|
|
|
4099
4936
|
defaultBackground
|
|
4100
4937
|
}) {
|
|
4101
4938
|
const { getValue, setValue, saveToWorker, mode } = useContentStore();
|
|
4102
|
-
const containerRef =
|
|
4103
|
-
const [isHovered, setIsHovered] =
|
|
4104
|
-
const [isSelected, setIsSelected] =
|
|
4105
|
-
const [isDropMode, setIsDropMode] =
|
|
4106
|
-
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]);
|
|
4107
4966
|
const rawValue = getValue(fieldId);
|
|
4108
4967
|
const backgroundConfig = rawValue ? parseBackgroundConfig(rawValue) : defaultBackground || { type: "none" };
|
|
4109
4968
|
const hasBackground = backgroundConfig.type !== "none";
|
|
@@ -4124,7 +4983,7 @@ function YaContainer({
|
|
|
4124
4983
|
overlayCustomProps["--ya-overlay-color"] = backgroundConfig.overlay.color;
|
|
4125
4984
|
overlayCustomProps["--ya-overlay-opacity"] = backgroundConfig.overlay.opacity;
|
|
4126
4985
|
}
|
|
4127
|
-
const handleImageClick =
|
|
4986
|
+
const handleImageClick = useCallback14(() => {
|
|
4128
4987
|
if (mode !== "inline-edit") return;
|
|
4129
4988
|
setIsSelected(true);
|
|
4130
4989
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
@@ -4144,7 +5003,7 @@ function YaContainer({
|
|
|
4144
5003
|
"*"
|
|
4145
5004
|
);
|
|
4146
5005
|
}, [mode, fieldId, backgroundConfig]);
|
|
4147
|
-
const handleColorClick =
|
|
5006
|
+
const handleColorClick = useCallback14(() => {
|
|
4148
5007
|
if (mode !== "inline-edit") return;
|
|
4149
5008
|
setIsSelected(true);
|
|
4150
5009
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
@@ -4164,7 +5023,7 @@ function YaContainer({
|
|
|
4164
5023
|
"*"
|
|
4165
5024
|
);
|
|
4166
5025
|
}, [mode, fieldId, backgroundConfig]);
|
|
4167
|
-
const handleAIClick =
|
|
5026
|
+
const handleAIClick = useCallback14(() => {
|
|
4168
5027
|
if (mode !== "inline-edit") return;
|
|
4169
5028
|
const label = deriveContainerLabel(containerRef.current);
|
|
4170
5029
|
window.parent.postMessage(
|
|
@@ -4177,14 +5036,14 @@ function YaContainer({
|
|
|
4177
5036
|
"*"
|
|
4178
5037
|
);
|
|
4179
5038
|
}, [mode, fieldId, backgroundConfig]);
|
|
4180
|
-
const handleClearClick =
|
|
5039
|
+
const handleClearClick = useCallback14(() => {
|
|
4181
5040
|
if (mode !== "inline-edit") return;
|
|
4182
5041
|
const clearedConfig = { type: "none" };
|
|
4183
5042
|
const serialized = serializeBackgroundConfig(clearedConfig);
|
|
4184
5043
|
setValue(fieldId, serialized);
|
|
4185
5044
|
saveToWorker?.(fieldId, serialized);
|
|
4186
5045
|
}, [mode, fieldId, setValue, saveToWorker]);
|
|
4187
|
-
|
|
5046
|
+
useEffect13(() => {
|
|
4188
5047
|
if (mode !== "inline-edit") return;
|
|
4189
5048
|
const handleMessage2 = (event) => {
|
|
4190
5049
|
if (event.data?.type === "YA_CONTAINER_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
|
|
@@ -4197,7 +5056,7 @@ function YaContainer({
|
|
|
4197
5056
|
window.addEventListener("message", handleMessage2);
|
|
4198
5057
|
return () => window.removeEventListener("message", handleMessage2);
|
|
4199
5058
|
}, [mode, fieldId]);
|
|
4200
|
-
|
|
5059
|
+
useEffect13(() => {
|
|
4201
5060
|
if (mode !== "inline-edit") return;
|
|
4202
5061
|
const handleDropModeMessage = (event) => {
|
|
4203
5062
|
if (event.data?.type === "DROP_MODE_START") {
|
|
@@ -4211,7 +5070,7 @@ function YaContainer({
|
|
|
4211
5070
|
window.addEventListener("message", handleDropModeMessage);
|
|
4212
5071
|
return () => window.removeEventListener("message", handleDropModeMessage);
|
|
4213
5072
|
}, [mode]);
|
|
4214
|
-
const handleDragEnter =
|
|
5073
|
+
const handleDragEnter = useCallback14(
|
|
4215
5074
|
(e) => {
|
|
4216
5075
|
if (!isDropMode) return;
|
|
4217
5076
|
e.preventDefault();
|
|
@@ -4235,7 +5094,7 @@ function YaContainer({
|
|
|
4235
5094
|
},
|
|
4236
5095
|
[isDropMode, fieldId]
|
|
4237
5096
|
);
|
|
4238
|
-
const handleDragOver =
|
|
5097
|
+
const handleDragOver = useCallback14(
|
|
4239
5098
|
(e) => {
|
|
4240
5099
|
if (!isDropMode) return;
|
|
4241
5100
|
e.preventDefault();
|
|
@@ -4243,7 +5102,7 @@ function YaContainer({
|
|
|
4243
5102
|
},
|
|
4244
5103
|
[isDropMode]
|
|
4245
5104
|
);
|
|
4246
|
-
const handleDragLeave =
|
|
5105
|
+
const handleDragLeave = useCallback14(
|
|
4247
5106
|
(e) => {
|
|
4248
5107
|
if (!isDropMode) return;
|
|
4249
5108
|
e.preventDefault();
|
|
@@ -4257,7 +5116,7 @@ function YaContainer({
|
|
|
4257
5116
|
},
|
|
4258
5117
|
[isDropMode]
|
|
4259
5118
|
);
|
|
4260
|
-
const handleDrop =
|
|
5119
|
+
const handleDrop = useCallback14(
|
|
4261
5120
|
(e) => {
|
|
4262
5121
|
if (!isDropMode) return;
|
|
4263
5122
|
e.preventDefault();
|
|
@@ -4275,7 +5134,7 @@ function YaContainer({
|
|
|
4275
5134
|
},
|
|
4276
5135
|
[isDropMode, fieldId]
|
|
4277
5136
|
);
|
|
4278
|
-
|
|
5137
|
+
useEffect13(() => {
|
|
4279
5138
|
if (!isSelected || mode !== "inline-edit") return;
|
|
4280
5139
|
let lastRectKey = "";
|
|
4281
5140
|
let lastTime = 0;
|
|
@@ -4310,7 +5169,7 @@ function YaContainer({
|
|
|
4310
5169
|
return () => cancelAnimationFrame(rafId);
|
|
4311
5170
|
}, [isSelected, fieldId, mode]);
|
|
4312
5171
|
if (mode === "read-only") {
|
|
4313
|
-
return /* @__PURE__ */
|
|
5172
|
+
return /* @__PURE__ */ jsx15(
|
|
4314
5173
|
Tag,
|
|
4315
5174
|
{
|
|
4316
5175
|
className: `ya-container ${className || ""}`,
|
|
@@ -4334,7 +5193,7 @@ function YaContainer({
|
|
|
4334
5193
|
isDropHover ? "ya-container-drop-hover" : "",
|
|
4335
5194
|
className || ""
|
|
4336
5195
|
].filter(Boolean).join(" ");
|
|
4337
|
-
return /* @__PURE__ */
|
|
5196
|
+
return /* @__PURE__ */ jsxs9(
|
|
4338
5197
|
Tag,
|
|
4339
5198
|
{
|
|
4340
5199
|
ref: containerRef,
|
|
@@ -4347,15 +5206,13 @@ function YaContainer({
|
|
|
4347
5206
|
"data-ya-restricted": "true",
|
|
4348
5207
|
"data-field-id": fieldId,
|
|
4349
5208
|
"data-ya-container": "true",
|
|
4350
|
-
onMouseEnter: () => setIsHovered(true),
|
|
4351
|
-
onMouseLeave: () => setIsHovered(false),
|
|
4352
5209
|
onDragEnter: handleDragEnter,
|
|
4353
5210
|
onDragOver: handleDragOver,
|
|
4354
5211
|
onDragLeave: handleDragLeave,
|
|
4355
5212
|
onDrop: handleDrop,
|
|
4356
5213
|
children: [
|
|
4357
5214
|
children,
|
|
4358
|
-
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(
|
|
4359
5216
|
Toolbar,
|
|
4360
5217
|
{
|
|
4361
5218
|
containerRef,
|
|
@@ -4372,10 +5229,10 @@ function YaContainer({
|
|
|
4372
5229
|
}
|
|
4373
5230
|
|
|
4374
5231
|
// src/components/StaticText.tsx
|
|
4375
|
-
import { jsx as
|
|
5232
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
4376
5233
|
function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
4377
5234
|
const content = getContent(fieldId) || (typeof children === "string" ? children : "");
|
|
4378
|
-
return /* @__PURE__ */
|
|
5235
|
+
return /* @__PURE__ */ jsx16(
|
|
4379
5236
|
Component,
|
|
4380
5237
|
{
|
|
4381
5238
|
className,
|
|
@@ -4386,7 +5243,7 @@ function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
|
4386
5243
|
}
|
|
4387
5244
|
|
|
4388
5245
|
// src/components/StaticImage.tsx
|
|
4389
|
-
import { jsx as
|
|
5246
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
4390
5247
|
function parseImageValue2(value) {
|
|
4391
5248
|
if (!value) {
|
|
4392
5249
|
return { src: "" };
|
|
@@ -4422,7 +5279,7 @@ function MpImage({
|
|
|
4422
5279
|
const altText = imageData.alt || alt || fallbackAlt || "";
|
|
4423
5280
|
const objectFit = imageData.objectFit || propObjectFit || "cover";
|
|
4424
5281
|
const objectPosition = getObjectPosition3(imageData) || propObjectPosition || "50% 50%";
|
|
4425
|
-
return /* @__PURE__ */
|
|
5282
|
+
return /* @__PURE__ */ jsx17(
|
|
4426
5283
|
"img",
|
|
4427
5284
|
{
|
|
4428
5285
|
src: resolveAssetUrl(src),
|
|
@@ -4439,8 +5296,8 @@ function MpImage({
|
|
|
4439
5296
|
}
|
|
4440
5297
|
|
|
4441
5298
|
// src/components/MarkdownText.tsx
|
|
4442
|
-
import { Fragment as
|
|
4443
|
-
import { jsx as
|
|
5299
|
+
import { Fragment as Fragment6 } from "react";
|
|
5300
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
4444
5301
|
function tokenize(text) {
|
|
4445
5302
|
const tokens = [];
|
|
4446
5303
|
let remaining = text;
|
|
@@ -4502,13 +5359,13 @@ function tokensToElements(tokens) {
|
|
|
4502
5359
|
return tokens.map((token, index) => {
|
|
4503
5360
|
switch (token.type) {
|
|
4504
5361
|
case "text":
|
|
4505
|
-
return /* @__PURE__ */
|
|
5362
|
+
return /* @__PURE__ */ jsx18(Fragment6, { children: token.content }, index);
|
|
4506
5363
|
case "bold":
|
|
4507
|
-
return /* @__PURE__ */
|
|
5364
|
+
return /* @__PURE__ */ jsx18("strong", { children: token.content }, index);
|
|
4508
5365
|
case "italic":
|
|
4509
|
-
return /* @__PURE__ */
|
|
5366
|
+
return /* @__PURE__ */ jsx18("em", { children: token.content }, index);
|
|
4510
5367
|
case "link":
|
|
4511
|
-
return /* @__PURE__ */
|
|
5368
|
+
return /* @__PURE__ */ jsx18(
|
|
4512
5369
|
"a",
|
|
4513
5370
|
{
|
|
4514
5371
|
href: token.url,
|
|
@@ -4520,7 +5377,7 @@ function tokensToElements(tokens) {
|
|
|
4520
5377
|
index
|
|
4521
5378
|
);
|
|
4522
5379
|
case "newline":
|
|
4523
|
-
return /* @__PURE__ */
|
|
5380
|
+
return /* @__PURE__ */ jsx18("br", {}, index);
|
|
4524
5381
|
default:
|
|
4525
5382
|
return null;
|
|
4526
5383
|
}
|
|
@@ -4532,15 +5389,15 @@ function parseMarkdownToElements(content) {
|
|
|
4532
5389
|
}
|
|
4533
5390
|
function MarkdownText({ content, className }) {
|
|
4534
5391
|
const elements = parseMarkdownToElements(content);
|
|
4535
|
-
return /* @__PURE__ */
|
|
5392
|
+
return /* @__PURE__ */ jsx18("span", { className, children: elements });
|
|
4536
5393
|
}
|
|
4537
5394
|
|
|
4538
5395
|
// src/router/Link.tsx
|
|
4539
5396
|
import { Link as WouterLink2 } from "wouter";
|
|
4540
|
-
import { jsx as
|
|
5397
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
4541
5398
|
function Link2({ to, href, children, className, onClick, replace, ...props }) {
|
|
4542
5399
|
const target = href ?? to ?? "/";
|
|
4543
|
-
return /* @__PURE__ */
|
|
5400
|
+
return /* @__PURE__ */ jsx19(WouterLink2, { href: target, className, onClick, replace, ...props, children });
|
|
4544
5401
|
}
|
|
4545
5402
|
|
|
4546
5403
|
// src/router/useNavigate.ts
|
|
@@ -4559,7 +5416,7 @@ function useNavigate() {
|
|
|
4559
5416
|
|
|
4560
5417
|
// src/router/Router.tsx
|
|
4561
5418
|
import { Router as WouterRouter } from "wouter";
|
|
4562
|
-
import { jsx as
|
|
5419
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
4563
5420
|
function detectBasename() {
|
|
4564
5421
|
if (typeof window === "undefined") return "";
|
|
4565
5422
|
const sessionMatch = window.location.pathname.match(/^\/session\/[^/]+/);
|
|
@@ -4574,7 +5431,7 @@ function detectBasename() {
|
|
|
4574
5431
|
}
|
|
4575
5432
|
function Router({ children, base }) {
|
|
4576
5433
|
const basename = base ?? detectBasename();
|
|
4577
|
-
return /* @__PURE__ */
|
|
5434
|
+
return /* @__PURE__ */ jsx20(WouterRouter, { base: basename, children });
|
|
4578
5435
|
}
|
|
4579
5436
|
|
|
4580
5437
|
// src/router/index.ts
|