@yoamigo.com/core 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +390 -1
- package/dist/index.js +699 -146
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -938,7 +938,7 @@ function ContentStoreProvider2({ children }) {
|
|
|
938
938
|
}
|
|
939
939
|
|
|
940
940
|
// src/components/YaText.tsx
|
|
941
|
-
import { useEffect as
|
|
941
|
+
import { useEffect as useEffect4, useRef as useRef5, useState as useState4, useCallback as useCallback5 } from "react";
|
|
942
942
|
import { createPortal as createPortal2 } from "react-dom";
|
|
943
943
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
944
944
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
@@ -1165,6 +1165,523 @@ function SafeHtml({ content, className, mode = "read-only" }) {
|
|
|
1165
1165
|
] });
|
|
1166
1166
|
}
|
|
1167
1167
|
|
|
1168
|
+
// src/hooks/useAnimatedText.ts
|
|
1169
|
+
import { useMemo as useMemo3 } from "react";
|
|
1170
|
+
|
|
1171
|
+
// src/hooks/useAIEditAnimation.ts
|
|
1172
|
+
import { useState as useState3, useEffect as useEffect3, useRef as useRef4, useCallback as useCallback4, useMemo as useMemo2 } from "react";
|
|
1173
|
+
|
|
1174
|
+
// src/contexts/AIEditContext.tsx
|
|
1175
|
+
import { createContext as createContext3, useContext as useContext3, useCallback as useCallback3, useRef as useRef3, useMemo } from "react";
|
|
1176
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1177
|
+
var AIEditContext = createContext3(null);
|
|
1178
|
+
function useAIEditContext() {
|
|
1179
|
+
const context = useContext3(AIEditContext);
|
|
1180
|
+
if (!context) {
|
|
1181
|
+
throw new Error("useAIEditContext must be used within an AIEditProvider");
|
|
1182
|
+
}
|
|
1183
|
+
return context;
|
|
1184
|
+
}
|
|
1185
|
+
function useAIEditContextOptional() {
|
|
1186
|
+
return useContext3(AIEditContext);
|
|
1187
|
+
}
|
|
1188
|
+
function AIEditProvider({ children, staggerDelay = 100 }) {
|
|
1189
|
+
const animationsRef = useRef3(/* @__PURE__ */ new Map());
|
|
1190
|
+
const listenersRef = useRef3(/* @__PURE__ */ new Map());
|
|
1191
|
+
const queueRef = useRef3([]);
|
|
1192
|
+
const processingRef = useRef3(false);
|
|
1193
|
+
const notifyListeners = useCallback3((fieldId) => {
|
|
1194
|
+
const listeners = listenersRef.current.get(fieldId);
|
|
1195
|
+
if (listeners) {
|
|
1196
|
+
listeners.forEach((listener) => listener());
|
|
1197
|
+
}
|
|
1198
|
+
}, []);
|
|
1199
|
+
const processQueue = useCallback3(() => {
|
|
1200
|
+
if (processingRef.current || queueRef.current.length === 0) return;
|
|
1201
|
+
processingRef.current = true;
|
|
1202
|
+
const fieldId = queueRef.current.shift();
|
|
1203
|
+
const state = animationsRef.current.get(fieldId);
|
|
1204
|
+
if (state && state.status === "pending") {
|
|
1205
|
+
state.status = "animating";
|
|
1206
|
+
state.startTime = performance.now();
|
|
1207
|
+
notifyListeners(fieldId);
|
|
1208
|
+
}
|
|
1209
|
+
setTimeout(() => {
|
|
1210
|
+
processingRef.current = false;
|
|
1211
|
+
processQueue();
|
|
1212
|
+
}, staggerDelay);
|
|
1213
|
+
}, [staggerDelay, notifyListeners]);
|
|
1214
|
+
const queueAnimation = useCallback3(
|
|
1215
|
+
(fieldId, config) => {
|
|
1216
|
+
const existing = animationsRef.current.get(fieldId);
|
|
1217
|
+
if (existing && existing.status === "animating") {
|
|
1218
|
+
animationsRef.current.delete(fieldId);
|
|
1219
|
+
}
|
|
1220
|
+
const state = {
|
|
1221
|
+
fieldId,
|
|
1222
|
+
status: "pending",
|
|
1223
|
+
startTime: 0,
|
|
1224
|
+
duration: config.duration,
|
|
1225
|
+
onComplete: config.onComplete
|
|
1226
|
+
};
|
|
1227
|
+
animationsRef.current.set(fieldId, state);
|
|
1228
|
+
config.onStart?.();
|
|
1229
|
+
if (!queueRef.current.includes(fieldId)) {
|
|
1230
|
+
queueRef.current.push(fieldId);
|
|
1231
|
+
}
|
|
1232
|
+
notifyListeners(fieldId);
|
|
1233
|
+
processQueue();
|
|
1234
|
+
},
|
|
1235
|
+
[notifyListeners, processQueue]
|
|
1236
|
+
);
|
|
1237
|
+
const cancelAnimation = useCallback3(
|
|
1238
|
+
(fieldId) => {
|
|
1239
|
+
const state = animationsRef.current.get(fieldId);
|
|
1240
|
+
if (state) {
|
|
1241
|
+
animationsRef.current.delete(fieldId);
|
|
1242
|
+
const queueIndex = queueRef.current.indexOf(fieldId);
|
|
1243
|
+
if (queueIndex >= 0) {
|
|
1244
|
+
queueRef.current.splice(queueIndex, 1);
|
|
1245
|
+
}
|
|
1246
|
+
notifyListeners(fieldId);
|
|
1247
|
+
}
|
|
1248
|
+
},
|
|
1249
|
+
[notifyListeners]
|
|
1250
|
+
);
|
|
1251
|
+
const isAnimating = useCallback3((fieldId) => {
|
|
1252
|
+
const state = animationsRef.current.get(fieldId);
|
|
1253
|
+
return state?.status === "animating" || state?.status === "pending";
|
|
1254
|
+
}, []);
|
|
1255
|
+
const getAnimationState = useCallback3((fieldId) => {
|
|
1256
|
+
return animationsRef.current.get(fieldId);
|
|
1257
|
+
}, []);
|
|
1258
|
+
const subscribe = useCallback3((fieldId, listener) => {
|
|
1259
|
+
let listeners = listenersRef.current.get(fieldId);
|
|
1260
|
+
if (!listeners) {
|
|
1261
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1262
|
+
listenersRef.current.set(fieldId, listeners);
|
|
1263
|
+
}
|
|
1264
|
+
listeners.add(listener);
|
|
1265
|
+
return () => {
|
|
1266
|
+
listeners?.delete(listener);
|
|
1267
|
+
if (listeners?.size === 0) {
|
|
1268
|
+
listenersRef.current.delete(fieldId);
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
}, []);
|
|
1272
|
+
const completeAnimation = useCallback3(
|
|
1273
|
+
(fieldId) => {
|
|
1274
|
+
const state = animationsRef.current.get(fieldId);
|
|
1275
|
+
if (state) {
|
|
1276
|
+
state.status = "complete";
|
|
1277
|
+
state.onComplete?.();
|
|
1278
|
+
setTimeout(() => {
|
|
1279
|
+
animationsRef.current.delete(fieldId);
|
|
1280
|
+
notifyListeners(fieldId);
|
|
1281
|
+
}, 500);
|
|
1282
|
+
notifyListeners(fieldId);
|
|
1283
|
+
}
|
|
1284
|
+
},
|
|
1285
|
+
[notifyListeners]
|
|
1286
|
+
);
|
|
1287
|
+
const value = useMemo(
|
|
1288
|
+
() => ({
|
|
1289
|
+
queueAnimation,
|
|
1290
|
+
cancelAnimation,
|
|
1291
|
+
isAnimating,
|
|
1292
|
+
getAnimationState,
|
|
1293
|
+
subscribe,
|
|
1294
|
+
completeAnimation
|
|
1295
|
+
}),
|
|
1296
|
+
[queueAnimation, cancelAnimation, isAnimating, getAnimationState, subscribe, completeAnimation]
|
|
1297
|
+
);
|
|
1298
|
+
return /* @__PURE__ */ jsx4(AIEditContext.Provider, { value, children });
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// src/hooks/useAIEditAnimation.ts
|
|
1302
|
+
function useAIEditAnimation(fieldId, value, options) {
|
|
1303
|
+
const { enabled = true, strategy, maxDuration = 2e3, onStart, onComplete } = options;
|
|
1304
|
+
const context = useAIEditContextOptional();
|
|
1305
|
+
const previousValueRef = useRef4(value);
|
|
1306
|
+
const isFirstRender = useRef4(true);
|
|
1307
|
+
const [phase, setPhase] = useState3("idle");
|
|
1308
|
+
const [progress, setProgress] = useState3(0);
|
|
1309
|
+
const [displayValue, setDisplayValue] = useState3(value);
|
|
1310
|
+
const metadataRef = useRef4(null);
|
|
1311
|
+
const animationFrameRef = useRef4(null);
|
|
1312
|
+
const startTimeRef = useRef4(0);
|
|
1313
|
+
const cancel = useCallback4(() => {
|
|
1314
|
+
if (animationFrameRef.current !== null) {
|
|
1315
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
1316
|
+
animationFrameRef.current = null;
|
|
1317
|
+
}
|
|
1318
|
+
setPhase("idle");
|
|
1319
|
+
setProgress(0);
|
|
1320
|
+
setDisplayValue(value);
|
|
1321
|
+
metadataRef.current = null;
|
|
1322
|
+
context?.cancelAnimation(fieldId);
|
|
1323
|
+
}, [value, context, fieldId]);
|
|
1324
|
+
const runAnimation = useCallback4(() => {
|
|
1325
|
+
if (!metadataRef.current) return;
|
|
1326
|
+
const metadata = metadataRef.current;
|
|
1327
|
+
const elapsed = performance.now() - startTimeRef.current;
|
|
1328
|
+
const duration = Math.min(metadata.duration, maxDuration);
|
|
1329
|
+
if (elapsed >= duration) {
|
|
1330
|
+
setProgress(1);
|
|
1331
|
+
setDisplayValue(metadata.newValue);
|
|
1332
|
+
setPhase("complete");
|
|
1333
|
+
metadataRef.current = null;
|
|
1334
|
+
animationFrameRef.current = null;
|
|
1335
|
+
context?.completeAnimation(fieldId);
|
|
1336
|
+
onComplete?.();
|
|
1337
|
+
setTimeout(() => {
|
|
1338
|
+
setPhase("idle");
|
|
1339
|
+
}, 400);
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
const currentProgress = elapsed / duration;
|
|
1343
|
+
setProgress(currentProgress);
|
|
1344
|
+
const interpolatedValue = strategy.interpolate(metadata, currentProgress);
|
|
1345
|
+
setDisplayValue(interpolatedValue);
|
|
1346
|
+
animationFrameRef.current = requestAnimationFrame(runAnimation);
|
|
1347
|
+
}, [strategy, maxDuration, context, fieldId, onComplete]);
|
|
1348
|
+
useEffect3(() => {
|
|
1349
|
+
if (isFirstRender.current) {
|
|
1350
|
+
isFirstRender.current = false;
|
|
1351
|
+
previousValueRef.current = value;
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
if (!enabled) {
|
|
1355
|
+
setDisplayValue(value);
|
|
1356
|
+
previousValueRef.current = value;
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
const oldValue = previousValueRef.current;
|
|
1360
|
+
const newValue = value;
|
|
1361
|
+
if (!strategy.canAnimate(oldValue, newValue)) {
|
|
1362
|
+
setDisplayValue(newValue);
|
|
1363
|
+
previousValueRef.current = newValue;
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
if (animationFrameRef.current !== null) {
|
|
1367
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
1368
|
+
}
|
|
1369
|
+
const metadata = strategy.prepare(oldValue, newValue);
|
|
1370
|
+
metadataRef.current = metadata;
|
|
1371
|
+
startTimeRef.current = performance.now();
|
|
1372
|
+
context?.queueAnimation(fieldId, {
|
|
1373
|
+
duration: Math.min(metadata.duration, maxDuration),
|
|
1374
|
+
onComplete: () => {
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
onStart?.();
|
|
1378
|
+
setPhase("animating");
|
|
1379
|
+
setProgress(0);
|
|
1380
|
+
animationFrameRef.current = requestAnimationFrame(runAnimation);
|
|
1381
|
+
previousValueRef.current = newValue;
|
|
1382
|
+
return () => {
|
|
1383
|
+
if (animationFrameRef.current !== null) {
|
|
1384
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
}, [value, enabled, strategy, context, fieldId, maxDuration, onStart, runAnimation]);
|
|
1388
|
+
useEffect3(() => {
|
|
1389
|
+
return () => {
|
|
1390
|
+
if (animationFrameRef.current !== null) {
|
|
1391
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
}, []);
|
|
1395
|
+
const wrapperProps = useMemo2(
|
|
1396
|
+
() => ({
|
|
1397
|
+
className: phase === "animating" ? "ya-ai-editing" : phase === "complete" ? "ya-ai-complete" : "",
|
|
1398
|
+
"data-ai-editing": phase === "animating"
|
|
1399
|
+
}),
|
|
1400
|
+
[phase]
|
|
1401
|
+
);
|
|
1402
|
+
return {
|
|
1403
|
+
displayValue,
|
|
1404
|
+
isAnimating: phase === "animating",
|
|
1405
|
+
phase,
|
|
1406
|
+
progress,
|
|
1407
|
+
cancel,
|
|
1408
|
+
wrapperProps
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
// src/lib/text-diff.ts
|
|
1413
|
+
function containsHtml(text) {
|
|
1414
|
+
return /<[^>]+>/.test(text);
|
|
1415
|
+
}
|
|
1416
|
+
function stripHtml(html) {
|
|
1417
|
+
const withNewlines = html.replace(/<br\s*\/?>/gi, "\n");
|
|
1418
|
+
return withNewlines.replace(/<[^>]+>/g, "");
|
|
1419
|
+
}
|
|
1420
|
+
function commonPrefixLength(a, b) {
|
|
1421
|
+
const minLen = Math.min(a.length, b.length);
|
|
1422
|
+
let i = 0;
|
|
1423
|
+
while (i < minLen && a[i] === b[i]) {
|
|
1424
|
+
i++;
|
|
1425
|
+
}
|
|
1426
|
+
return i;
|
|
1427
|
+
}
|
|
1428
|
+
function commonSuffixLength(a, b, prefixLen) {
|
|
1429
|
+
const maxSuffixA = a.length - prefixLen;
|
|
1430
|
+
const maxSuffixB = b.length - prefixLen;
|
|
1431
|
+
const maxSuffix = Math.min(maxSuffixA, maxSuffixB);
|
|
1432
|
+
let i = 0;
|
|
1433
|
+
while (i < maxSuffix && a[a.length - 1 - i] === b[b.length - 1 - i]) {
|
|
1434
|
+
i++;
|
|
1435
|
+
}
|
|
1436
|
+
return i;
|
|
1437
|
+
}
|
|
1438
|
+
function computeTextDiff(oldText, newText) {
|
|
1439
|
+
const normalizedOld = oldText ?? "";
|
|
1440
|
+
const normalizedNew = newText ?? "";
|
|
1441
|
+
const hasHtml = containsHtml(normalizedOld) || containsHtml(normalizedNew);
|
|
1442
|
+
if (hasHtml) {
|
|
1443
|
+
return {
|
|
1444
|
+
type: "complex",
|
|
1445
|
+
deletions: normalizedOld,
|
|
1446
|
+
additions: normalizedNew,
|
|
1447
|
+
commonPrefix: "",
|
|
1448
|
+
commonSuffix: "",
|
|
1449
|
+
oldText: normalizedOld,
|
|
1450
|
+
newText: normalizedNew
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
const prefixLen = commonPrefixLength(normalizedOld, normalizedNew);
|
|
1454
|
+
const suffixLen = commonSuffixLength(normalizedOld, normalizedNew, prefixLen);
|
|
1455
|
+
const commonPrefix = normalizedOld.slice(0, prefixLen);
|
|
1456
|
+
const commonSuffix = suffixLen > 0 ? normalizedOld.slice(-suffixLen) : "";
|
|
1457
|
+
const deletions = normalizedOld.slice(prefixLen, normalizedOld.length - suffixLen);
|
|
1458
|
+
const additions = normalizedNew.slice(prefixLen, normalizedNew.length - suffixLen);
|
|
1459
|
+
return {
|
|
1460
|
+
type: "simple",
|
|
1461
|
+
deletions,
|
|
1462
|
+
additions,
|
|
1463
|
+
commonPrefix,
|
|
1464
|
+
commonSuffix,
|
|
1465
|
+
oldText: normalizedOld,
|
|
1466
|
+
newText: normalizedNew
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function buildIntermediateText(diff, deleteProgress, typeProgress) {
|
|
1470
|
+
if (diff.type === "complex") {
|
|
1471
|
+
return typeProgress >= 1 ? diff.newText : diff.oldText;
|
|
1472
|
+
}
|
|
1473
|
+
const deletionsRemaining = Math.floor(diff.deletions.length * (1 - deleteProgress));
|
|
1474
|
+
const additionsShown = Math.floor(diff.additions.length * typeProgress);
|
|
1475
|
+
const remainingDeletions = diff.deletions.slice(0, deletionsRemaining);
|
|
1476
|
+
const typedAdditions = diff.additions.slice(0, additionsShown);
|
|
1477
|
+
return diff.commonPrefix + remainingDeletions + typedAdditions + diff.commonSuffix;
|
|
1478
|
+
}
|
|
1479
|
+
function calculateAnimationTiming(diff, options = {}) {
|
|
1480
|
+
const { charDelay = 50, maxDuration = 2e3 } = options;
|
|
1481
|
+
if (diff.type === "complex") {
|
|
1482
|
+
return { deleteDuration: 150, typeDuration: 150 };
|
|
1483
|
+
}
|
|
1484
|
+
const deleteChars = diff.deletions.length;
|
|
1485
|
+
const typeChars = diff.additions.length;
|
|
1486
|
+
const totalChars = deleteChars + typeChars;
|
|
1487
|
+
if (totalChars === 0) {
|
|
1488
|
+
return { deleteDuration: 0, typeDuration: 0 };
|
|
1489
|
+
}
|
|
1490
|
+
const baseDuration = totalChars * charDelay;
|
|
1491
|
+
const scale = baseDuration > maxDuration ? maxDuration / baseDuration : 1;
|
|
1492
|
+
const deleteDuration = Math.round(deleteChars * charDelay * scale);
|
|
1493
|
+
const typeDuration = Math.round(typeChars * charDelay * scale);
|
|
1494
|
+
return { deleteDuration, typeDuration };
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
// src/lib/animation-strategies.ts
|
|
1498
|
+
var textTypingStrategy = {
|
|
1499
|
+
name: "text-typing",
|
|
1500
|
+
canAnimate(oldValue, newValue) {
|
|
1501
|
+
if (oldValue === newValue) return false;
|
|
1502
|
+
if (!oldValue && !newValue) return false;
|
|
1503
|
+
return true;
|
|
1504
|
+
},
|
|
1505
|
+
prepare(oldValue, newValue) {
|
|
1506
|
+
const diff = computeTextDiff(oldValue, newValue);
|
|
1507
|
+
const { deleteDuration, typeDuration } = calculateAnimationTiming(diff, {
|
|
1508
|
+
charDelay: 50,
|
|
1509
|
+
// Fast & snappy
|
|
1510
|
+
maxDuration: 2e3
|
|
1511
|
+
});
|
|
1512
|
+
return {
|
|
1513
|
+
oldValue,
|
|
1514
|
+
newValue,
|
|
1515
|
+
duration: deleteDuration + typeDuration,
|
|
1516
|
+
data: {
|
|
1517
|
+
diff,
|
|
1518
|
+
deleteDuration,
|
|
1519
|
+
typeDuration
|
|
1520
|
+
}
|
|
1521
|
+
};
|
|
1522
|
+
},
|
|
1523
|
+
interpolate(metadata, progress) {
|
|
1524
|
+
const data = metadata.data;
|
|
1525
|
+
const { diff, deleteDuration, typeDuration } = data;
|
|
1526
|
+
const totalDuration = deleteDuration + typeDuration;
|
|
1527
|
+
if (totalDuration === 0) {
|
|
1528
|
+
return metadata.newValue;
|
|
1529
|
+
}
|
|
1530
|
+
const deleteEnd = deleteDuration / totalDuration;
|
|
1531
|
+
let deleteProgress;
|
|
1532
|
+
let typeProgress;
|
|
1533
|
+
if (progress <= deleteEnd) {
|
|
1534
|
+
deleteProgress = deleteEnd > 0 ? progress / deleteEnd : 1;
|
|
1535
|
+
typeProgress = 0;
|
|
1536
|
+
} else {
|
|
1537
|
+
deleteProgress = 1;
|
|
1538
|
+
const typeStart = deleteEnd;
|
|
1539
|
+
const typeRange = 1 - deleteEnd;
|
|
1540
|
+
typeProgress = typeRange > 0 ? (progress - typeStart) / typeRange : 1;
|
|
1541
|
+
}
|
|
1542
|
+
return buildIntermediateText(diff, deleteProgress, typeProgress);
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
var imageCrossfadeStrategy = {
|
|
1546
|
+
name: "image-crossfade",
|
|
1547
|
+
canAnimate(oldValue, newValue) {
|
|
1548
|
+
if (oldValue?.src === newValue?.src) return false;
|
|
1549
|
+
return true;
|
|
1550
|
+
},
|
|
1551
|
+
prepare(oldValue, newValue) {
|
|
1552
|
+
return {
|
|
1553
|
+
oldValue,
|
|
1554
|
+
newValue,
|
|
1555
|
+
duration: 300
|
|
1556
|
+
// Quick crossfade
|
|
1557
|
+
};
|
|
1558
|
+
},
|
|
1559
|
+
interpolate(metadata, progress) {
|
|
1560
|
+
return progress >= 0.5 ? metadata.newValue : metadata.oldValue;
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
var linkTransitionStrategy = {
|
|
1564
|
+
name: "link-transition",
|
|
1565
|
+
canAnimate(oldValue, newValue) {
|
|
1566
|
+
if (oldValue?.text === newValue?.text && oldValue?.href === newValue?.href) {
|
|
1567
|
+
return false;
|
|
1568
|
+
}
|
|
1569
|
+
return true;
|
|
1570
|
+
},
|
|
1571
|
+
prepare(oldValue, newValue) {
|
|
1572
|
+
const textDiff = computeTextDiff(oldValue?.text ?? "", newValue?.text ?? "");
|
|
1573
|
+
const { deleteDuration, typeDuration } = calculateAnimationTiming(textDiff, {
|
|
1574
|
+
charDelay: 50,
|
|
1575
|
+
maxDuration: 1500
|
|
1576
|
+
});
|
|
1577
|
+
return {
|
|
1578
|
+
oldValue,
|
|
1579
|
+
newValue,
|
|
1580
|
+
duration: deleteDuration + typeDuration + 100,
|
|
1581
|
+
// Extra for href highlight
|
|
1582
|
+
data: { textDiff }
|
|
1583
|
+
};
|
|
1584
|
+
},
|
|
1585
|
+
interpolate(metadata, progress) {
|
|
1586
|
+
return progress >= 0.5 ? metadata.newValue : metadata.oldValue;
|
|
1587
|
+
}
|
|
1588
|
+
};
|
|
1589
|
+
function getTextCursorPosition(metadata, progress) {
|
|
1590
|
+
const { diff, deleteDuration, typeDuration } = metadata.data;
|
|
1591
|
+
const totalDuration = deleteDuration + typeDuration;
|
|
1592
|
+
if (totalDuration === 0) return null;
|
|
1593
|
+
const deleteEnd = deleteDuration / totalDuration;
|
|
1594
|
+
let textLength;
|
|
1595
|
+
if (progress <= deleteEnd) {
|
|
1596
|
+
const deleteProgress = deleteEnd > 0 ? progress / deleteEnd : 1;
|
|
1597
|
+
const deletionsRemaining = Math.floor(diff.deletions.length * (1 - deleteProgress));
|
|
1598
|
+
textLength = diff.commonPrefix.length + deletionsRemaining;
|
|
1599
|
+
} else {
|
|
1600
|
+
const typeProgress = (progress - deleteEnd) / (1 - deleteEnd);
|
|
1601
|
+
const additionsShown = Math.floor(diff.additions.length * typeProgress);
|
|
1602
|
+
textLength = diff.commonPrefix.length + additionsShown;
|
|
1603
|
+
}
|
|
1604
|
+
return textLength;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
// src/hooks/useAnimatedText.ts
|
|
1608
|
+
function useAnimatedText(fieldId, content, options = {}) {
|
|
1609
|
+
const {
|
|
1610
|
+
enabled = true,
|
|
1611
|
+
charDelay = 50,
|
|
1612
|
+
maxDuration = 2e3,
|
|
1613
|
+
onStart,
|
|
1614
|
+
onComplete
|
|
1615
|
+
} = options;
|
|
1616
|
+
const customStrategy = useMemo3(() => {
|
|
1617
|
+
if (charDelay === 50) {
|
|
1618
|
+
return textTypingStrategy;
|
|
1619
|
+
}
|
|
1620
|
+
return {
|
|
1621
|
+
...textTypingStrategy,
|
|
1622
|
+
prepare(oldValue, newValue) {
|
|
1623
|
+
const diff = computeTextDiff(oldValue, newValue);
|
|
1624
|
+
const { deleteDuration, typeDuration } = calculateAnimationTiming(diff, {
|
|
1625
|
+
charDelay,
|
|
1626
|
+
maxDuration
|
|
1627
|
+
});
|
|
1628
|
+
return {
|
|
1629
|
+
oldValue,
|
|
1630
|
+
newValue,
|
|
1631
|
+
duration: deleteDuration + typeDuration,
|
|
1632
|
+
data: {
|
|
1633
|
+
diff,
|
|
1634
|
+
deleteDuration,
|
|
1635
|
+
typeDuration
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
};
|
|
1640
|
+
}, [charDelay, maxDuration]);
|
|
1641
|
+
const {
|
|
1642
|
+
displayValue,
|
|
1643
|
+
isAnimating,
|
|
1644
|
+
phase,
|
|
1645
|
+
progress,
|
|
1646
|
+
cancel,
|
|
1647
|
+
wrapperProps
|
|
1648
|
+
} = useAIEditAnimation(fieldId, content, {
|
|
1649
|
+
enabled,
|
|
1650
|
+
strategy: customStrategy,
|
|
1651
|
+
maxDuration,
|
|
1652
|
+
onStart,
|
|
1653
|
+
onComplete
|
|
1654
|
+
});
|
|
1655
|
+
const cursorPosition = useMemo3(() => {
|
|
1656
|
+
if (!isAnimating) return null;
|
|
1657
|
+
const diff = computeTextDiff(content, displayValue);
|
|
1658
|
+
const { deleteDuration, typeDuration } = calculateAnimationTiming(diff, {
|
|
1659
|
+
charDelay,
|
|
1660
|
+
maxDuration
|
|
1661
|
+
});
|
|
1662
|
+
const metadata = {
|
|
1663
|
+
oldValue: content,
|
|
1664
|
+
newValue: displayValue,
|
|
1665
|
+
duration: deleteDuration + typeDuration,
|
|
1666
|
+
data: {
|
|
1667
|
+
diff,
|
|
1668
|
+
deleteDuration,
|
|
1669
|
+
typeDuration
|
|
1670
|
+
}
|
|
1671
|
+
};
|
|
1672
|
+
return getTextCursorPosition(metadata, progress);
|
|
1673
|
+
}, [isAnimating, content, displayValue, charDelay, maxDuration, progress]);
|
|
1674
|
+
return {
|
|
1675
|
+
displayContent: displayValue,
|
|
1676
|
+
isAnimating,
|
|
1677
|
+
phase,
|
|
1678
|
+
progress,
|
|
1679
|
+
cursorPosition,
|
|
1680
|
+
wrapperClassName: wrapperProps.className,
|
|
1681
|
+
cancel
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1168
1685
|
// #style-inject:#style-inject
|
|
1169
1686
|
function styleInject(css, { insertAt } = {}) {
|
|
1170
1687
|
if (!css || typeof document === "undefined") return;
|
|
@@ -1415,8 +1932,11 @@ body.builder-selector-active .ya-text-editable:hover {
|
|
|
1415
1932
|
}
|
|
1416
1933
|
`);
|
|
1417
1934
|
|
|
1935
|
+
// src/styles/ai-animations.css
|
|
1936
|
+
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');
|
|
1937
|
+
|
|
1418
1938
|
// src/components/YaText.tsx
|
|
1419
|
-
import { Fragment as Fragment2, jsx as
|
|
1939
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1420
1940
|
var FontSize = Extension.create({
|
|
1421
1941
|
name: "fontSize",
|
|
1422
1942
|
addOptions() {
|
|
@@ -1511,10 +2031,17 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1511
2031
|
const { getValue, setValue, mode, saveToWorker, activeFieldId, setActiveField } = useContentStore();
|
|
1512
2032
|
const storeContent = getValue(fieldId);
|
|
1513
2033
|
const content = storeContent || (typeof children === "string" ? children : "");
|
|
1514
|
-
const [isEditing, setIsEditing] =
|
|
1515
|
-
const
|
|
1516
|
-
|
|
1517
|
-
|
|
2034
|
+
const [isEditing, setIsEditing] = useState4(false);
|
|
2035
|
+
const {
|
|
2036
|
+
displayContent,
|
|
2037
|
+
isAnimating,
|
|
2038
|
+
wrapperClassName
|
|
2039
|
+
} = useAnimatedText(fieldId, content, {
|
|
2040
|
+
enabled: mode === "inline-edit" && !isEditing
|
|
2041
|
+
});
|
|
2042
|
+
const [originalContent, setOriginalContent] = useState4(content);
|
|
2043
|
+
const containerRef = useRef5(null);
|
|
2044
|
+
const originalContentRef = useRef5(content);
|
|
1518
2045
|
const editor = useEditor({
|
|
1519
2046
|
extensions: [
|
|
1520
2047
|
StarterKit.configure({
|
|
@@ -1548,19 +2075,19 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1548
2075
|
},
|
|
1549
2076
|
parseOptions: { preserveWhitespace: "full" }
|
|
1550
2077
|
});
|
|
1551
|
-
|
|
2078
|
+
useEffect4(() => {
|
|
1552
2079
|
if (editor && !isEditing) {
|
|
1553
2080
|
if (editor.getHTML() !== content) {
|
|
1554
2081
|
editor.commands.setContent(content, { parseOptions: { preserveWhitespace: "full" } });
|
|
1555
2082
|
}
|
|
1556
2083
|
}
|
|
1557
2084
|
}, [content, editor, isEditing]);
|
|
1558
|
-
|
|
2085
|
+
useEffect4(() => {
|
|
1559
2086
|
if (isEditing && activeFieldId !== null && activeFieldId !== fieldId) {
|
|
1560
2087
|
setIsEditing(false);
|
|
1561
2088
|
}
|
|
1562
2089
|
}, [activeFieldId, fieldId, isEditing]);
|
|
1563
|
-
const handleSave =
|
|
2090
|
+
const handleSave = useCallback5(() => {
|
|
1564
2091
|
if (!editor) return;
|
|
1565
2092
|
let html = editor.getHTML();
|
|
1566
2093
|
html = html.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
|
|
@@ -1568,13 +2095,13 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1568
2095
|
saveToWorker?.(fieldId, html);
|
|
1569
2096
|
setIsEditing(false);
|
|
1570
2097
|
}, [editor, fieldId, setValue, saveToWorker]);
|
|
1571
|
-
const handleCancel =
|
|
2098
|
+
const handleCancel = useCallback5(() => {
|
|
1572
2099
|
if (editor) {
|
|
1573
2100
|
editor.commands.setContent(originalContent, { parseOptions: { preserveWhitespace: "full" } });
|
|
1574
2101
|
}
|
|
1575
2102
|
setIsEditing(false);
|
|
1576
2103
|
}, [editor, originalContent]);
|
|
1577
|
-
const handleClose =
|
|
2104
|
+
const handleClose = useCallback5(() => {
|
|
1578
2105
|
if (!editor) {
|
|
1579
2106
|
setIsEditing(false);
|
|
1580
2107
|
return;
|
|
@@ -1587,7 +2114,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1587
2114
|
}
|
|
1588
2115
|
setIsEditing(false);
|
|
1589
2116
|
}, [editor, fieldId, setValue, saveToWorker]);
|
|
1590
|
-
const handleClick =
|
|
2117
|
+
const handleClick = useCallback5((e) => {
|
|
1591
2118
|
if (isEditing) {
|
|
1592
2119
|
e.preventDefault();
|
|
1593
2120
|
e.stopPropagation();
|
|
@@ -1613,7 +2140,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1613
2140
|
}, 20);
|
|
1614
2141
|
}
|
|
1615
2142
|
}, [mode, isEditing, content, editor, fieldId, setActiveField, handleClose]);
|
|
1616
|
-
const handleKeyDown =
|
|
2143
|
+
const handleKeyDown = useCallback5(
|
|
1617
2144
|
(event) => {
|
|
1618
2145
|
if (!isEditing) return;
|
|
1619
2146
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -1634,7 +2161,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1634
2161
|
},
|
|
1635
2162
|
[isEditing, handleSave, handleCancel]
|
|
1636
2163
|
);
|
|
1637
|
-
const handleLink =
|
|
2164
|
+
const handleLink = useCallback5(() => {
|
|
1638
2165
|
if (!editor) return;
|
|
1639
2166
|
const previousUrl = editor.getAttributes("link").href;
|
|
1640
2167
|
const url = window.prompt("Enter URL:", previousUrl || "https://");
|
|
@@ -1645,7 +2172,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1645
2172
|
editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
|
|
1646
2173
|
}
|
|
1647
2174
|
}, [editor]);
|
|
1648
|
-
const handleFontSizeChange =
|
|
2175
|
+
const handleFontSizeChange = useCallback5(
|
|
1649
2176
|
(e) => {
|
|
1650
2177
|
if (!editor) return;
|
|
1651
2178
|
const size = e.target.value;
|
|
@@ -1657,7 +2184,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1657
2184
|
},
|
|
1658
2185
|
[editor]
|
|
1659
2186
|
);
|
|
1660
|
-
const handleFontWeightChange =
|
|
2187
|
+
const handleFontWeightChange = useCallback5(
|
|
1661
2188
|
(e) => {
|
|
1662
2189
|
if (!editor) return;
|
|
1663
2190
|
const weight = e.target.value;
|
|
@@ -1680,24 +2207,30 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1680
2207
|
return attrs.fontWeight || "";
|
|
1681
2208
|
};
|
|
1682
2209
|
if (mode === "read-only") {
|
|
1683
|
-
return /* @__PURE__ */
|
|
2210
|
+
return /* @__PURE__ */ jsx5(
|
|
1684
2211
|
Component,
|
|
1685
2212
|
{
|
|
1686
2213
|
ref: containerRef,
|
|
1687
2214
|
className,
|
|
1688
2215
|
"data-ya-restricted": "true",
|
|
1689
2216
|
"data-field-id": fieldId,
|
|
1690
|
-
children: /* @__PURE__ */
|
|
2217
|
+
children: /* @__PURE__ */ jsx5(SafeHtml, { content, mode })
|
|
1691
2218
|
}
|
|
1692
2219
|
);
|
|
1693
2220
|
}
|
|
1694
|
-
|
|
2221
|
+
const combinedClassName = [
|
|
2222
|
+
className || "",
|
|
2223
|
+
isEditing ? "ya-text-editing" : "ya-text-editable",
|
|
2224
|
+
wrapperClassName
|
|
2225
|
+
].filter(Boolean).join(" ");
|
|
2226
|
+
return /* @__PURE__ */ jsx5(
|
|
1695
2227
|
Component,
|
|
1696
2228
|
{
|
|
1697
2229
|
ref: containerRef,
|
|
1698
|
-
className:
|
|
2230
|
+
className: combinedClassName,
|
|
1699
2231
|
"data-ya-restricted": "true",
|
|
1700
2232
|
"data-field-id": fieldId,
|
|
2233
|
+
"data-ai-editing": isAnimating || void 0,
|
|
1701
2234
|
onClick: handleClick,
|
|
1702
2235
|
onKeyDown: handleKeyDown,
|
|
1703
2236
|
children: editor ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
@@ -1710,37 +2243,37 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1710
2243
|
options: { offset: 6, placement: "top" },
|
|
1711
2244
|
className: "ya-bubble-menu",
|
|
1712
2245
|
children: [
|
|
1713
|
-
/* @__PURE__ */
|
|
2246
|
+
/* @__PURE__ */ jsx5(
|
|
1714
2247
|
"button",
|
|
1715
2248
|
{
|
|
1716
2249
|
type: "button",
|
|
1717
2250
|
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
1718
2251
|
className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
|
|
1719
2252
|
title: "Bold",
|
|
1720
|
-
children: /* @__PURE__ */
|
|
2253
|
+
children: /* @__PURE__ */ jsx5("strong", { children: "B" })
|
|
1721
2254
|
}
|
|
1722
2255
|
),
|
|
1723
|
-
/* @__PURE__ */
|
|
2256
|
+
/* @__PURE__ */ jsx5(
|
|
1724
2257
|
"button",
|
|
1725
2258
|
{
|
|
1726
2259
|
type: "button",
|
|
1727
2260
|
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
1728
2261
|
className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
|
|
1729
2262
|
title: "Italic",
|
|
1730
|
-
children: /* @__PURE__ */
|
|
2263
|
+
children: /* @__PURE__ */ jsx5("em", { children: "I" })
|
|
1731
2264
|
}
|
|
1732
2265
|
),
|
|
1733
|
-
/* @__PURE__ */
|
|
2266
|
+
/* @__PURE__ */ jsx5(
|
|
1734
2267
|
"button",
|
|
1735
2268
|
{
|
|
1736
2269
|
type: "button",
|
|
1737
2270
|
onClick: handleLink,
|
|
1738
2271
|
className: `ya-bubble-btn ${editor.isActive("link") ? "is-active" : ""}`,
|
|
1739
2272
|
title: "Link",
|
|
1740
|
-
children: /* @__PURE__ */
|
|
2273
|
+
children: /* @__PURE__ */ jsx5("span", { children: "\u{1F517}" })
|
|
1741
2274
|
}
|
|
1742
2275
|
),
|
|
1743
|
-
/* @__PURE__ */
|
|
2276
|
+
/* @__PURE__ */ jsx5("span", { className: "ya-bubble-divider" }),
|
|
1744
2277
|
/* @__PURE__ */ jsxs2(
|
|
1745
2278
|
"select",
|
|
1746
2279
|
{
|
|
@@ -1749,8 +2282,8 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1749
2282
|
className: "ya-bubble-select",
|
|
1750
2283
|
title: "Font Size",
|
|
1751
2284
|
children: [
|
|
1752
|
-
/* @__PURE__ */
|
|
1753
|
-
Object.entries(SIZE_PRESETS).map(([name, size]) => /* @__PURE__ */
|
|
2285
|
+
/* @__PURE__ */ jsx5("option", { value: "", children: "Size" }),
|
|
2286
|
+
Object.entries(SIZE_PRESETS).map(([name, size]) => /* @__PURE__ */ jsx5("option", { value: size, children: name }, name))
|
|
1754
2287
|
]
|
|
1755
2288
|
}
|
|
1756
2289
|
),
|
|
@@ -1762,8 +2295,8 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1762
2295
|
className: "ya-bubble-select",
|
|
1763
2296
|
title: "Font Weight",
|
|
1764
2297
|
children: [
|
|
1765
|
-
/* @__PURE__ */
|
|
1766
|
-
Object.entries(WEIGHT_PRESETS).map(([name, weight]) => /* @__PURE__ */
|
|
2298
|
+
/* @__PURE__ */ jsx5("option", { value: "", children: "Weight" }),
|
|
2299
|
+
Object.entries(WEIGHT_PRESETS).map(([name, weight]) => /* @__PURE__ */ jsx5("option", { value: weight, children: name }, name))
|
|
1767
2300
|
]
|
|
1768
2301
|
}
|
|
1769
2302
|
)
|
|
@@ -1773,9 +2306,9 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1773
2306
|
document.body
|
|
1774
2307
|
),
|
|
1775
2308
|
isEditing ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1776
|
-
/* @__PURE__ */
|
|
2309
|
+
/* @__PURE__ */ jsx5(EditorContent, { editor }),
|
|
1777
2310
|
/* @__PURE__ */ jsxs2("div", { className: "ya-text-actions", children: [
|
|
1778
|
-
/* @__PURE__ */
|
|
2311
|
+
/* @__PURE__ */ jsx5(
|
|
1779
2312
|
"button",
|
|
1780
2313
|
{
|
|
1781
2314
|
type: "button",
|
|
@@ -1784,7 +2317,7 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1784
2317
|
children: "Cancel"
|
|
1785
2318
|
}
|
|
1786
2319
|
),
|
|
1787
|
-
/* @__PURE__ */
|
|
2320
|
+
/* @__PURE__ */ jsx5(
|
|
1788
2321
|
"button",
|
|
1789
2322
|
{
|
|
1790
2323
|
type: "button",
|
|
@@ -1794,14 +2327,20 @@ function YaText({ fieldId, className, as: Component = "span", children }) {
|
|
|
1794
2327
|
}
|
|
1795
2328
|
)
|
|
1796
2329
|
] })
|
|
1797
|
-
] }) : /* @__PURE__ */
|
|
1798
|
-
|
|
2330
|
+
] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2331
|
+
/* @__PURE__ */ jsx5(SafeHtml, { content: displayContent, mode }),
|
|
2332
|
+
isAnimating && /* @__PURE__ */ jsx5("span", { className: "ya-typing-cursor" })
|
|
2333
|
+
] })
|
|
2334
|
+
] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2335
|
+
/* @__PURE__ */ jsx5(SafeHtml, { content: displayContent, mode }),
|
|
2336
|
+
isAnimating && /* @__PURE__ */ jsx5("span", { className: "ya-typing-cursor" })
|
|
2337
|
+
] })
|
|
1799
2338
|
}
|
|
1800
2339
|
);
|
|
1801
2340
|
}
|
|
1802
2341
|
|
|
1803
2342
|
// src/components/YaImage.tsx
|
|
1804
|
-
import { useCallback as
|
|
2343
|
+
import { useCallback as useCallback7, useEffect as useEffect6, useRef as useRef7, useState as useState6 } from "react";
|
|
1805
2344
|
|
|
1806
2345
|
// src/lib/asset-resolver.ts
|
|
1807
2346
|
var assetResolver = (path) => path;
|
|
@@ -1817,25 +2356,25 @@ function resolveAssetUrl(path) {
|
|
|
1817
2356
|
}
|
|
1818
2357
|
|
|
1819
2358
|
// src/components/YaTooltip.tsx
|
|
1820
|
-
import { useEffect as
|
|
2359
|
+
import { useEffect as useEffect5, useRef as useRef6, useState as useState5, useCallback as useCallback6 } from "react";
|
|
1821
2360
|
import { createPortal as createPortal3 } from "react-dom";
|
|
1822
2361
|
|
|
1823
2362
|
// src/components/ya-tooltip.css
|
|
1824
2363
|
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 opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\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');
|
|
1825
2364
|
|
|
1826
2365
|
// src/components/YaTooltip.tsx
|
|
1827
|
-
import { jsx as
|
|
2366
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1828
2367
|
function YaTooltip({
|
|
1829
2368
|
anchorRef,
|
|
1830
2369
|
children,
|
|
1831
2370
|
show,
|
|
1832
2371
|
preferredPosition = "bottom"
|
|
1833
2372
|
}) {
|
|
1834
|
-
const [position, setPosition] =
|
|
1835
|
-
const [coords, setCoords] =
|
|
1836
|
-
const [isPositioned, setIsPositioned] =
|
|
1837
|
-
const tooltipRef =
|
|
1838
|
-
const calculatePosition =
|
|
2373
|
+
const [position, setPosition] = useState5(preferredPosition);
|
|
2374
|
+
const [coords, setCoords] = useState5({ top: 0, left: 0 });
|
|
2375
|
+
const [isPositioned, setIsPositioned] = useState5(false);
|
|
2376
|
+
const tooltipRef = useRef6(null);
|
|
2377
|
+
const calculatePosition = useCallback6(() => {
|
|
1839
2378
|
if (!anchorRef.current) return;
|
|
1840
2379
|
const anchor = anchorRef.current.getBoundingClientRect();
|
|
1841
2380
|
const tooltip = tooltipRef.current?.getBoundingClientRect();
|
|
@@ -1910,7 +2449,7 @@ function YaTooltip({
|
|
|
1910
2449
|
setCoords({ top, left });
|
|
1911
2450
|
setIsPositioned(true);
|
|
1912
2451
|
}, [anchorRef, preferredPosition]);
|
|
1913
|
-
|
|
2452
|
+
useEffect5(() => {
|
|
1914
2453
|
if (!show) {
|
|
1915
2454
|
setIsPositioned(false);
|
|
1916
2455
|
return;
|
|
@@ -1923,14 +2462,14 @@ function YaTooltip({
|
|
|
1923
2462
|
window.removeEventListener("resize", calculatePosition);
|
|
1924
2463
|
};
|
|
1925
2464
|
}, [show, calculatePosition]);
|
|
1926
|
-
|
|
2465
|
+
useEffect5(() => {
|
|
1927
2466
|
if (show && tooltipRef.current) {
|
|
1928
2467
|
calculatePosition();
|
|
1929
2468
|
}
|
|
1930
2469
|
}, [show, children, calculatePosition]);
|
|
1931
2470
|
if (!show) return null;
|
|
1932
2471
|
return createPortal3(
|
|
1933
|
-
/* @__PURE__ */
|
|
2472
|
+
/* @__PURE__ */ jsx6(
|
|
1934
2473
|
"div",
|
|
1935
2474
|
{
|
|
1936
2475
|
ref: tooltipRef,
|
|
@@ -1953,7 +2492,7 @@ function YaTooltip({
|
|
|
1953
2492
|
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');
|
|
1954
2493
|
|
|
1955
2494
|
// src/components/YaImage.tsx
|
|
1956
|
-
import { jsx as
|
|
2495
|
+
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1957
2496
|
function parseImageValue(value) {
|
|
1958
2497
|
if (!value) {
|
|
1959
2498
|
return { src: "" };
|
|
@@ -1988,18 +2527,18 @@ function YaImage({
|
|
|
1988
2527
|
fallbackAlt
|
|
1989
2528
|
}) {
|
|
1990
2529
|
const { getValue, mode } = useContentStore();
|
|
1991
|
-
const containerRef =
|
|
1992
|
-
const imgRef =
|
|
1993
|
-
const [isSelected, setIsSelected] =
|
|
1994
|
-
const [isHovered, setIsHovered] =
|
|
1995
|
-
const [isSmallImage, setIsSmallImage] =
|
|
2530
|
+
const containerRef = useRef7(null);
|
|
2531
|
+
const imgRef = useRef7(null);
|
|
2532
|
+
const [isSelected, setIsSelected] = useState6(false);
|
|
2533
|
+
const [isHovered, setIsHovered] = useState6(false);
|
|
2534
|
+
const [isSmallImage, setIsSmallImage] = useState6(false);
|
|
1996
2535
|
const rawValue = getValue(fieldId);
|
|
1997
2536
|
const imageData = parseImageValue(rawValue);
|
|
1998
2537
|
const src = imageData.src || fallbackSrc || "";
|
|
1999
2538
|
const altText = imageData.alt || alt || fallbackAlt || "";
|
|
2000
2539
|
const objectFit = imageData.objectFit || propObjectFit || "cover";
|
|
2001
2540
|
const objectPosition = getObjectPosition(imageData) || propObjectPosition || "50% 50%";
|
|
2002
|
-
const handleClick =
|
|
2541
|
+
const handleClick = useCallback7(() => {
|
|
2003
2542
|
if (mode !== "inline-edit") return;
|
|
2004
2543
|
if (document.body.classList.contains("builder-selector-active")) return;
|
|
2005
2544
|
setIsSelected(true);
|
|
@@ -2027,7 +2566,7 @@ function YaImage({
|
|
|
2027
2566
|
"*"
|
|
2028
2567
|
);
|
|
2029
2568
|
}, [mode, fieldId, imageData, src, altText, objectFit, objectPosition]);
|
|
2030
|
-
|
|
2569
|
+
useEffect6(() => {
|
|
2031
2570
|
if (mode !== "inline-edit") return;
|
|
2032
2571
|
const handleMessage2 = (event) => {
|
|
2033
2572
|
if (event.data?.type === "YA_IMAGE_EDIT_COMPLETE" && event.data.fieldId === fieldId) {
|
|
@@ -2042,7 +2581,7 @@ function YaImage({
|
|
|
2042
2581
|
window.addEventListener("message", handleMessage2);
|
|
2043
2582
|
return () => window.removeEventListener("message", handleMessage2);
|
|
2044
2583
|
}, [mode, fieldId]);
|
|
2045
|
-
|
|
2584
|
+
useEffect6(() => {
|
|
2046
2585
|
if (mode !== "inline-edit") return;
|
|
2047
2586
|
const checkSize = () => {
|
|
2048
2587
|
if (imgRef.current) {
|
|
@@ -2064,7 +2603,7 @@ function YaImage({
|
|
|
2064
2603
|
window.removeEventListener("resize", checkSize);
|
|
2065
2604
|
};
|
|
2066
2605
|
}, [mode]);
|
|
2067
|
-
|
|
2606
|
+
useEffect6(() => {
|
|
2068
2607
|
if (!isSelected || mode !== "inline-edit") return;
|
|
2069
2608
|
let lastRectKey = "";
|
|
2070
2609
|
let lastTime = 0;
|
|
@@ -2099,7 +2638,7 @@ function YaImage({
|
|
|
2099
2638
|
return () => cancelAnimationFrame(rafId);
|
|
2100
2639
|
}, [isSelected, fieldId, mode]);
|
|
2101
2640
|
if (mode === "read-only") {
|
|
2102
|
-
return /* @__PURE__ */
|
|
2641
|
+
return /* @__PURE__ */ jsx7(
|
|
2103
2642
|
"img",
|
|
2104
2643
|
{
|
|
2105
2644
|
src: resolveAssetUrl(src),
|
|
@@ -2127,9 +2666,9 @@ function YaImage({
|
|
|
2127
2666
|
strokeLinecap: "round",
|
|
2128
2667
|
strokeLinejoin: "round",
|
|
2129
2668
|
children: [
|
|
2130
|
-
/* @__PURE__ */
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2669
|
+
/* @__PURE__ */ jsx7("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
2670
|
+
/* @__PURE__ */ jsx7("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
|
|
2671
|
+
/* @__PURE__ */ jsx7("polyline", { points: "21 15 16 10 5 21" })
|
|
2133
2672
|
]
|
|
2134
2673
|
}
|
|
2135
2674
|
);
|
|
@@ -2154,7 +2693,7 @@ function YaImage({
|
|
|
2154
2693
|
}
|
|
2155
2694
|
},
|
|
2156
2695
|
children: [
|
|
2157
|
-
/* @__PURE__ */
|
|
2696
|
+
/* @__PURE__ */ jsx7(
|
|
2158
2697
|
"img",
|
|
2159
2698
|
{
|
|
2160
2699
|
ref: imgRef,
|
|
@@ -2170,12 +2709,12 @@ function YaImage({
|
|
|
2170
2709
|
),
|
|
2171
2710
|
isSmallImage ? /* @__PURE__ */ jsxs3(YaTooltip, { anchorRef: containerRef, show: isHovered && !isSelected, children: [
|
|
2172
2711
|
editIcon,
|
|
2173
|
-
/* @__PURE__ */
|
|
2712
|
+
/* @__PURE__ */ jsx7("span", { children: "Click to edit" })
|
|
2174
2713
|
] }) : (
|
|
2175
2714
|
/* For large images: show overlay inside the image */
|
|
2176
2715
|
/* @__PURE__ */ jsxs3("div", { className: "ya-image-overlay", children: [
|
|
2177
|
-
/* @__PURE__ */
|
|
2178
|
-
/* @__PURE__ */
|
|
2716
|
+
/* @__PURE__ */ jsx7("div", { className: "ya-image-edit-icon", children: editIcon }),
|
|
2717
|
+
/* @__PURE__ */ jsx7("span", { className: "ya-image-edit-label", children: "Click to edit" })
|
|
2179
2718
|
] })
|
|
2180
2719
|
)
|
|
2181
2720
|
]
|
|
@@ -2184,7 +2723,7 @@ function YaImage({
|
|
|
2184
2723
|
}
|
|
2185
2724
|
|
|
2186
2725
|
// src/components/YaLink.tsx
|
|
2187
|
-
import { useEffect as
|
|
2726
|
+
import { useEffect as useEffect7, useRef as useRef8, useState as useState7, useCallback as useCallback8 } from "react";
|
|
2188
2727
|
import { createPortal as createPortal4 } from "react-dom";
|
|
2189
2728
|
import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
|
|
2190
2729
|
import { BubbleMenu as BubbleMenu2 } from "@tiptap/react/menus";
|
|
@@ -2197,7 +2736,7 @@ import { Link as WouterLink, useLocation } from "wouter";
|
|
|
2197
2736
|
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-actions {\n display: flex;\n gap: 8px;\n position: absolute;\n bottom: -60px;\n right: 0;\n z-index: 10;\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: 10;\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-link-edit-popover {\n position: absolute;\n top: 100%;\n left: 50%;\n margin-top: 8px;\n z-index: 10;\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');
|
|
2198
2737
|
|
|
2199
2738
|
// src/components/YaLink.tsx
|
|
2200
|
-
import { Fragment as Fragment3, jsx as
|
|
2739
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2201
2740
|
function isInternalPath(path) {
|
|
2202
2741
|
if (!path) return false;
|
|
2203
2742
|
if (path.startsWith("#")) return false;
|
|
@@ -2292,8 +2831,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2292
2831
|
const { getValue, setValue, mode, saveToWorker, getPages } = useContentStore();
|
|
2293
2832
|
const [, navigate] = useLocation();
|
|
2294
2833
|
const pages = availablePages ?? getPages();
|
|
2295
|
-
const [sections, setSections] =
|
|
2296
|
-
const [sectionsExpanded, setSectionsExpanded] =
|
|
2834
|
+
const [sections, setSections] = useState7([]);
|
|
2835
|
+
const [sectionsExpanded, setSectionsExpanded] = useState7(false);
|
|
2297
2836
|
const textFieldId = `${fieldId}.text`;
|
|
2298
2837
|
const hrefFieldId = `${fieldId}.href`;
|
|
2299
2838
|
const storeText = getValue(textFieldId);
|
|
@@ -2301,16 +2840,16 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2301
2840
|
const isIconMode = children != null && typeof children !== "string";
|
|
2302
2841
|
const text = storeText || (typeof children === "string" ? children : "");
|
|
2303
2842
|
const href = storeHref || defaultHref;
|
|
2304
|
-
const [editingMode, setEditingMode] =
|
|
2305
|
-
const [showEditPopover, setShowEditPopover] =
|
|
2306
|
-
const [originalText, setOriginalText] =
|
|
2307
|
-
const [originalHref, setOriginalHref] =
|
|
2308
|
-
const [currentHref, setCurrentHref] =
|
|
2309
|
-
const [isExternalUrl, setIsExternalUrl] =
|
|
2310
|
-
const [externalUrl, setExternalUrl] =
|
|
2311
|
-
const containerRef =
|
|
2312
|
-
const hrefPopoverRef =
|
|
2313
|
-
const hidePopoverTimeoutRef =
|
|
2843
|
+
const [editingMode, setEditingMode] = useState7(null);
|
|
2844
|
+
const [showEditPopover, setShowEditPopover] = useState7(false);
|
|
2845
|
+
const [originalText, setOriginalText] = useState7(text);
|
|
2846
|
+
const [originalHref, setOriginalHref] = useState7(href);
|
|
2847
|
+
const [currentHref, setCurrentHref] = useState7(href);
|
|
2848
|
+
const [isExternalUrl, setIsExternalUrl] = useState7(false);
|
|
2849
|
+
const [externalUrl, setExternalUrl] = useState7("");
|
|
2850
|
+
const containerRef = useRef8(null);
|
|
2851
|
+
const hrefPopoverRef = useRef8(null);
|
|
2852
|
+
const hidePopoverTimeoutRef = useRef8(null);
|
|
2314
2853
|
const editor = useEditor2({
|
|
2315
2854
|
extensions: [
|
|
2316
2855
|
StarterKit2.configure({
|
|
@@ -2333,26 +2872,26 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2333
2872
|
}
|
|
2334
2873
|
}
|
|
2335
2874
|
});
|
|
2336
|
-
|
|
2875
|
+
useEffect7(() => {
|
|
2337
2876
|
if (editor && editingMode !== "text") {
|
|
2338
2877
|
if (editor.getHTML() !== text) {
|
|
2339
2878
|
editor.commands.setContent(text);
|
|
2340
2879
|
}
|
|
2341
2880
|
}
|
|
2342
2881
|
}, [text, editor, editingMode]);
|
|
2343
|
-
|
|
2882
|
+
useEffect7(() => {
|
|
2344
2883
|
if (editingMode !== "link") {
|
|
2345
2884
|
setCurrentHref(href);
|
|
2346
2885
|
}
|
|
2347
2886
|
}, [href, editingMode]);
|
|
2348
|
-
|
|
2887
|
+
useEffect7(() => {
|
|
2349
2888
|
return () => {
|
|
2350
2889
|
if (hidePopoverTimeoutRef.current) {
|
|
2351
2890
|
clearTimeout(hidePopoverTimeoutRef.current);
|
|
2352
2891
|
}
|
|
2353
2892
|
};
|
|
2354
2893
|
}, []);
|
|
2355
|
-
|
|
2894
|
+
useEffect7(() => {
|
|
2356
2895
|
if (editingMode !== "link") return;
|
|
2357
2896
|
const handleClickOutside = (event) => {
|
|
2358
2897
|
const target = event.target;
|
|
@@ -2366,7 +2905,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2366
2905
|
document.addEventListener("mousedown", handleClickOutside);
|
|
2367
2906
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
2368
2907
|
}, [editingMode, originalHref]);
|
|
2369
|
-
const handleSaveText =
|
|
2908
|
+
const handleSaveText = useCallback8(() => {
|
|
2370
2909
|
if (!editor) return;
|
|
2371
2910
|
let html = editor.getHTML();
|
|
2372
2911
|
html = html.replace(/<\/p><p>/g, "<br><br>").replace(/^<p>/, "").replace(/<\/p>$/, "");
|
|
@@ -2374,26 +2913,26 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2374
2913
|
saveToWorker?.(textFieldId, html);
|
|
2375
2914
|
setEditingMode(null);
|
|
2376
2915
|
}, [editor, textFieldId, setValue, saveToWorker]);
|
|
2377
|
-
const handleSaveLink =
|
|
2916
|
+
const handleSaveLink = useCallback8(() => {
|
|
2378
2917
|
setValue(hrefFieldId, currentHref);
|
|
2379
2918
|
saveToWorker?.(hrefFieldId, currentHref);
|
|
2380
2919
|
setEditingMode(null);
|
|
2381
2920
|
setIsExternalUrl(false);
|
|
2382
2921
|
setExternalUrl("");
|
|
2383
2922
|
}, [hrefFieldId, currentHref, setValue, saveToWorker]);
|
|
2384
|
-
const handleCancelText =
|
|
2923
|
+
const handleCancelText = useCallback8(() => {
|
|
2385
2924
|
if (editor) {
|
|
2386
2925
|
editor.commands.setContent(originalText);
|
|
2387
2926
|
}
|
|
2388
2927
|
setEditingMode(null);
|
|
2389
2928
|
}, [editor, originalText]);
|
|
2390
|
-
const handleCancelLink =
|
|
2929
|
+
const handleCancelLink = useCallback8(() => {
|
|
2391
2930
|
setCurrentHref(originalHref);
|
|
2392
2931
|
setEditingMode(null);
|
|
2393
2932
|
setIsExternalUrl(false);
|
|
2394
2933
|
setExternalUrl("");
|
|
2395
2934
|
}, [originalHref]);
|
|
2396
|
-
const handleClick =
|
|
2935
|
+
const handleClick = useCallback8(
|
|
2397
2936
|
(e) => {
|
|
2398
2937
|
const selectModeEnabled = window.__builderSelectModeEnabled;
|
|
2399
2938
|
if (selectModeEnabled) {
|
|
@@ -2425,7 +2964,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2425
2964
|
},
|
|
2426
2965
|
[href, navigate, onClick]
|
|
2427
2966
|
);
|
|
2428
|
-
const handleMouseEnter =
|
|
2967
|
+
const handleMouseEnter = useCallback8(() => {
|
|
2429
2968
|
if (hidePopoverTimeoutRef.current) {
|
|
2430
2969
|
clearTimeout(hidePopoverTimeoutRef.current);
|
|
2431
2970
|
hidePopoverTimeoutRef.current = null;
|
|
@@ -2434,19 +2973,19 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2434
2973
|
setShowEditPopover(true);
|
|
2435
2974
|
}
|
|
2436
2975
|
}, [mode, editingMode]);
|
|
2437
|
-
const handleMouseLeave =
|
|
2976
|
+
const handleMouseLeave = useCallback8(() => {
|
|
2438
2977
|
hidePopoverTimeoutRef.current = window.setTimeout(() => {
|
|
2439
2978
|
if (!editingMode) {
|
|
2440
2979
|
setShowEditPopover(false);
|
|
2441
2980
|
}
|
|
2442
2981
|
}, 150);
|
|
2443
2982
|
}, [editingMode]);
|
|
2444
|
-
const handleFocus =
|
|
2983
|
+
const handleFocus = useCallback8(() => {
|
|
2445
2984
|
if (mode === "inline-edit" && !editingMode) {
|
|
2446
2985
|
setShowEditPopover(true);
|
|
2447
2986
|
}
|
|
2448
2987
|
}, [mode, editingMode]);
|
|
2449
|
-
const startEditText =
|
|
2988
|
+
const startEditText = useCallback8(() => {
|
|
2450
2989
|
setShowEditPopover(false);
|
|
2451
2990
|
setEditingMode("text");
|
|
2452
2991
|
setOriginalText(text);
|
|
@@ -2454,14 +2993,14 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2454
2993
|
editor?.chain().focus().selectAll().run();
|
|
2455
2994
|
}, 20);
|
|
2456
2995
|
}, [text, editor]);
|
|
2457
|
-
const startEditLink =
|
|
2996
|
+
const startEditLink = useCallback8(() => {
|
|
2458
2997
|
setShowEditPopover(false);
|
|
2459
2998
|
setEditingMode("link");
|
|
2460
2999
|
setOriginalHref(href);
|
|
2461
3000
|
setCurrentHref(href);
|
|
2462
3001
|
setSections(discoverSectionsFromDOM());
|
|
2463
3002
|
}, [href]);
|
|
2464
|
-
const handleKeyDown =
|
|
3003
|
+
const handleKeyDown = useCallback8(
|
|
2465
3004
|
(event) => {
|
|
2466
3005
|
if (editingMode !== "text") return;
|
|
2467
3006
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -2482,7 +3021,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2482
3021
|
},
|
|
2483
3022
|
[editingMode, handleSaveText, handleCancelText]
|
|
2484
3023
|
);
|
|
2485
|
-
const handleFontSizeChange =
|
|
3024
|
+
const handleFontSizeChange = useCallback8(
|
|
2486
3025
|
(e) => {
|
|
2487
3026
|
if (!editor) return;
|
|
2488
3027
|
const size = e.target.value;
|
|
@@ -2494,7 +3033,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2494
3033
|
},
|
|
2495
3034
|
[editor]
|
|
2496
3035
|
);
|
|
2497
|
-
const handleFontWeightChange =
|
|
3036
|
+
const handleFontWeightChange = useCallback8(
|
|
2498
3037
|
(e) => {
|
|
2499
3038
|
if (!editor) return;
|
|
2500
3039
|
const weight = e.target.value;
|
|
@@ -2506,11 +3045,11 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2506
3045
|
},
|
|
2507
3046
|
[editor]
|
|
2508
3047
|
);
|
|
2509
|
-
const handlePageSelect =
|
|
3048
|
+
const handlePageSelect = useCallback8((path) => {
|
|
2510
3049
|
setCurrentHref(path);
|
|
2511
3050
|
setIsExternalUrl(false);
|
|
2512
3051
|
}, []);
|
|
2513
|
-
const handleExternalUrlApply =
|
|
3052
|
+
const handleExternalUrlApply = useCallback8(() => {
|
|
2514
3053
|
if (externalUrl) {
|
|
2515
3054
|
setCurrentHref(externalUrl);
|
|
2516
3055
|
}
|
|
@@ -2526,9 +3065,9 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2526
3065
|
return attrs.fontWeight || "";
|
|
2527
3066
|
};
|
|
2528
3067
|
if (mode === "read-only") {
|
|
2529
|
-
const content = isIconMode ? children : /* @__PURE__ */
|
|
3068
|
+
const content = isIconMode ? children : /* @__PURE__ */ jsx8(SafeHtml, { content: text, mode });
|
|
2530
3069
|
if (isInternalPath(href)) {
|
|
2531
|
-
return /* @__PURE__ */
|
|
3070
|
+
return /* @__PURE__ */ jsx8(
|
|
2532
3071
|
WouterLink,
|
|
2533
3072
|
{
|
|
2534
3073
|
href,
|
|
@@ -2539,7 +3078,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2539
3078
|
}
|
|
2540
3079
|
);
|
|
2541
3080
|
}
|
|
2542
|
-
return /* @__PURE__ */
|
|
3081
|
+
return /* @__PURE__ */ jsx8(
|
|
2543
3082
|
Component,
|
|
2544
3083
|
{
|
|
2545
3084
|
ref: containerRef,
|
|
@@ -2552,7 +3091,7 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2552
3091
|
);
|
|
2553
3092
|
}
|
|
2554
3093
|
return /* @__PURE__ */ jsxs4("span", { className: "ya-link-wrapper", children: [
|
|
2555
|
-
/* @__PURE__ */
|
|
3094
|
+
/* @__PURE__ */ jsx8(
|
|
2556
3095
|
Component,
|
|
2557
3096
|
{
|
|
2558
3097
|
ref: containerRef,
|
|
@@ -2578,27 +3117,27 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2578
3117
|
options: { offset: 6, placement: "top" },
|
|
2579
3118
|
className: "ya-bubble-menu",
|
|
2580
3119
|
children: [
|
|
2581
|
-
/* @__PURE__ */
|
|
3120
|
+
/* @__PURE__ */ jsx8(
|
|
2582
3121
|
"button",
|
|
2583
3122
|
{
|
|
2584
3123
|
type: "button",
|
|
2585
3124
|
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
2586
3125
|
className: `ya-bubble-btn ${editor.isActive("bold") ? "is-active" : ""}`,
|
|
2587
3126
|
title: "Bold",
|
|
2588
|
-
children: /* @__PURE__ */
|
|
3127
|
+
children: /* @__PURE__ */ jsx8("strong", { children: "B" })
|
|
2589
3128
|
}
|
|
2590
3129
|
),
|
|
2591
|
-
/* @__PURE__ */
|
|
3130
|
+
/* @__PURE__ */ jsx8(
|
|
2592
3131
|
"button",
|
|
2593
3132
|
{
|
|
2594
3133
|
type: "button",
|
|
2595
3134
|
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
2596
3135
|
className: `ya-bubble-btn ${editor.isActive("italic") ? "is-active" : ""}`,
|
|
2597
3136
|
title: "Italic",
|
|
2598
|
-
children: /* @__PURE__ */
|
|
3137
|
+
children: /* @__PURE__ */ jsx8("em", { children: "I" })
|
|
2599
3138
|
}
|
|
2600
3139
|
),
|
|
2601
|
-
/* @__PURE__ */
|
|
3140
|
+
/* @__PURE__ */ jsx8("span", { className: "ya-bubble-divider" }),
|
|
2602
3141
|
/* @__PURE__ */ jsxs4(
|
|
2603
3142
|
"select",
|
|
2604
3143
|
{
|
|
@@ -2607,8 +3146,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2607
3146
|
className: "ya-bubble-select",
|
|
2608
3147
|
title: "Font Size",
|
|
2609
3148
|
children: [
|
|
2610
|
-
/* @__PURE__ */
|
|
2611
|
-
Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */
|
|
3149
|
+
/* @__PURE__ */ jsx8("option", { value: "", children: "Size" }),
|
|
3150
|
+
Object.entries(SIZE_PRESETS2).map(([name, size]) => /* @__PURE__ */ jsx8("option", { value: size, children: name }, name))
|
|
2612
3151
|
]
|
|
2613
3152
|
}
|
|
2614
3153
|
),
|
|
@@ -2620,8 +3159,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2620
3159
|
className: "ya-bubble-select",
|
|
2621
3160
|
title: "Font Weight",
|
|
2622
3161
|
children: [
|
|
2623
|
-
/* @__PURE__ */
|
|
2624
|
-
Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */
|
|
3162
|
+
/* @__PURE__ */ jsx8("option", { value: "", children: "Weight" }),
|
|
3163
|
+
Object.entries(WEIGHT_PRESETS2).map(([name, weight]) => /* @__PURE__ */ jsx8("option", { value: weight, children: name }, name))
|
|
2625
3164
|
]
|
|
2626
3165
|
}
|
|
2627
3166
|
)
|
|
@@ -2631,21 +3170,21 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2631
3170
|
document.body
|
|
2632
3171
|
),
|
|
2633
3172
|
editingMode === "text" ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
2634
|
-
/* @__PURE__ */
|
|
3173
|
+
/* @__PURE__ */ jsx8(EditorContent2, { editor }),
|
|
2635
3174
|
/* @__PURE__ */ jsxs4("div", { className: "ya-link-actions", children: [
|
|
2636
|
-
/* @__PURE__ */
|
|
2637
|
-
/* @__PURE__ */
|
|
3175
|
+
/* @__PURE__ */ jsx8("button", { type: "button", onClick: handleCancelText, className: "ya-link-btn ya-link-btn-cancel", children: "Cancel" }),
|
|
3176
|
+
/* @__PURE__ */ jsx8("button", { type: "button", onClick: handleSaveText, className: "ya-link-btn ya-link-btn-save", children: "Save" })
|
|
2638
3177
|
] })
|
|
2639
|
-
] }) : /* @__PURE__ */
|
|
2640
|
-
] }) : /* @__PURE__ */
|
|
3178
|
+
] }) : /* @__PURE__ */ jsx8(SafeHtml, { content: text, mode })
|
|
3179
|
+
] }) : /* @__PURE__ */ jsx8(SafeHtml, { content: text, mode })
|
|
2641
3180
|
}
|
|
2642
3181
|
),
|
|
2643
3182
|
showEditPopover && !editingMode && mode === "inline-edit" && /* @__PURE__ */ jsxs4("div", { className: "ya-link-edit-popover", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [
|
|
2644
|
-
!isIconMode && /* @__PURE__ */
|
|
2645
|
-
/* @__PURE__ */
|
|
3183
|
+
!isIconMode && /* @__PURE__ */ jsx8("button", { type: "button", onClick: startEditText, children: "Edit text" }),
|
|
3184
|
+
/* @__PURE__ */ jsx8("button", { type: "button", onClick: startEditLink, children: "Edit link" })
|
|
2646
3185
|
] }),
|
|
2647
3186
|
editingMode === "link" && /* @__PURE__ */ jsxs4("div", { ref: hrefPopoverRef, className: "ya-href-popover", children: [
|
|
2648
|
-
/* @__PURE__ */
|
|
3187
|
+
/* @__PURE__ */ jsx8("div", { className: "ya-href-popover-header", children: "Link destination" }),
|
|
2649
3188
|
!isExternalUrl ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
2650
3189
|
sections.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "ya-href-popover-section", children: [
|
|
2651
3190
|
/* @__PURE__ */ jsxs4(
|
|
@@ -2655,14 +3194,14 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2655
3194
|
className: "ya-href-popover-label ya-href-collapsible-header",
|
|
2656
3195
|
onClick: () => setSectionsExpanded(!sectionsExpanded),
|
|
2657
3196
|
children: [
|
|
2658
|
-
/* @__PURE__ */
|
|
3197
|
+
/* @__PURE__ */ jsx8("span", { className: "ya-href-chevron", children: sectionsExpanded ? "\u25BC" : "\u25B6" }),
|
|
2659
3198
|
"Scroll to section (",
|
|
2660
3199
|
sections.length,
|
|
2661
3200
|
")"
|
|
2662
3201
|
]
|
|
2663
3202
|
}
|
|
2664
3203
|
),
|
|
2665
|
-
sectionsExpanded && /* @__PURE__ */
|
|
3204
|
+
sectionsExpanded && /* @__PURE__ */ jsx8("div", { className: "ya-href-popover-pages", children: sections.map((section) => /* @__PURE__ */ jsxs4(
|
|
2666
3205
|
"button",
|
|
2667
3206
|
{
|
|
2668
3207
|
type: "button",
|
|
@@ -2670,15 +3209,15 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2670
3209
|
onClick: () => handlePageSelect(section.path),
|
|
2671
3210
|
children: [
|
|
2672
3211
|
section.label,
|
|
2673
|
-
/* @__PURE__ */
|
|
3212
|
+
/* @__PURE__ */ jsx8("span", { className: "ya-href-page-path", children: section.path })
|
|
2674
3213
|
]
|
|
2675
3214
|
},
|
|
2676
3215
|
section.path
|
|
2677
3216
|
)) })
|
|
2678
3217
|
] }),
|
|
2679
3218
|
pages.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "ya-href-popover-section", children: [
|
|
2680
|
-
/* @__PURE__ */
|
|
2681
|
-
/* @__PURE__ */
|
|
3219
|
+
/* @__PURE__ */ jsx8("label", { className: "ya-href-popover-label", children: "Navigate to page" }),
|
|
3220
|
+
/* @__PURE__ */ jsx8("div", { className: "ya-href-popover-pages", children: pages.map((page) => /* @__PURE__ */ jsxs4(
|
|
2682
3221
|
"button",
|
|
2683
3222
|
{
|
|
2684
3223
|
type: "button",
|
|
@@ -2686,13 +3225,13 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2686
3225
|
onClick: () => handlePageSelect(page.path),
|
|
2687
3226
|
children: [
|
|
2688
3227
|
page.label,
|
|
2689
|
-
/* @__PURE__ */
|
|
3228
|
+
/* @__PURE__ */ jsx8("span", { className: "ya-href-page-path", children: page.path })
|
|
2690
3229
|
]
|
|
2691
3230
|
},
|
|
2692
3231
|
page.path
|
|
2693
3232
|
)) })
|
|
2694
3233
|
] }),
|
|
2695
|
-
/* @__PURE__ */
|
|
3234
|
+
/* @__PURE__ */ jsx8(
|
|
2696
3235
|
"button",
|
|
2697
3236
|
{
|
|
2698
3237
|
type: "button",
|
|
@@ -2706,8 +3245,8 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2706
3245
|
)
|
|
2707
3246
|
] }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
2708
3247
|
/* @__PURE__ */ jsxs4("div", { className: "ya-href-popover-section", children: [
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
3248
|
+
/* @__PURE__ */ jsx8("label", { className: "ya-href-popover-label", children: "External URL" }),
|
|
3249
|
+
/* @__PURE__ */ jsx8(
|
|
2711
3250
|
"input",
|
|
2712
3251
|
{
|
|
2713
3252
|
type: "url",
|
|
@@ -2719,21 +3258,21 @@ function YaLink({ fieldId, href: defaultHref = "#", className, as: Component = "
|
|
|
2719
3258
|
}
|
|
2720
3259
|
)
|
|
2721
3260
|
] }),
|
|
2722
|
-
/* @__PURE__ */
|
|
3261
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "ya-href-external-toggle", onClick: () => setIsExternalUrl(false), children: "\u2190 Back to pages" })
|
|
2723
3262
|
] }),
|
|
2724
3263
|
/* @__PURE__ */ jsxs4("div", { className: "ya-href-popover-actions", children: [
|
|
2725
|
-
/* @__PURE__ */
|
|
2726
|
-
isExternalUrl ? /* @__PURE__ */
|
|
3264
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "ya-link-btn ya-link-btn-cancel", onClick: handleCancelLink, children: "Cancel" }),
|
|
3265
|
+
isExternalUrl ? /* @__PURE__ */ jsx8("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleExternalUrlApply, children: "Apply" }) : /* @__PURE__ */ jsx8("button", { type: "button", className: "ya-link-btn ya-link-btn-save", onClick: handleSaveLink, children: "Save" })
|
|
2727
3266
|
] })
|
|
2728
3267
|
] })
|
|
2729
3268
|
] });
|
|
2730
3269
|
}
|
|
2731
3270
|
|
|
2732
3271
|
// src/components/StaticText.tsx
|
|
2733
|
-
import { jsx as
|
|
3272
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2734
3273
|
function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
2735
3274
|
const content = getContent(fieldId) || (typeof children === "string" ? children : "");
|
|
2736
|
-
return /* @__PURE__ */
|
|
3275
|
+
return /* @__PURE__ */ jsx9(
|
|
2737
3276
|
Component,
|
|
2738
3277
|
{
|
|
2739
3278
|
className,
|
|
@@ -2744,7 +3283,7 @@ function MpText({ fieldId, className, as: Component = "span", children }) {
|
|
|
2744
3283
|
}
|
|
2745
3284
|
|
|
2746
3285
|
// src/components/StaticImage.tsx
|
|
2747
|
-
import { jsx as
|
|
3286
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
2748
3287
|
function parseImageValue2(value) {
|
|
2749
3288
|
if (!value) {
|
|
2750
3289
|
return { src: "" };
|
|
@@ -2780,7 +3319,7 @@ function MpImage({
|
|
|
2780
3319
|
const altText = imageData.alt || alt || fallbackAlt || "";
|
|
2781
3320
|
const objectFit = imageData.objectFit || propObjectFit || "cover";
|
|
2782
3321
|
const objectPosition = getObjectPosition2(imageData) || propObjectPosition || "50% 50%";
|
|
2783
|
-
return /* @__PURE__ */
|
|
3322
|
+
return /* @__PURE__ */ jsx10(
|
|
2784
3323
|
"img",
|
|
2785
3324
|
{
|
|
2786
3325
|
src: resolveAssetUrl(src),
|
|
@@ -2798,7 +3337,7 @@ function MpImage({
|
|
|
2798
3337
|
|
|
2799
3338
|
// src/components/MarkdownText.tsx
|
|
2800
3339
|
import { Fragment as Fragment4 } from "react";
|
|
2801
|
-
import { jsx as
|
|
3340
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2802
3341
|
function tokenize(text) {
|
|
2803
3342
|
const tokens = [];
|
|
2804
3343
|
let remaining = text;
|
|
@@ -2860,13 +3399,13 @@ function tokensToElements(tokens) {
|
|
|
2860
3399
|
return tokens.map((token, index) => {
|
|
2861
3400
|
switch (token.type) {
|
|
2862
3401
|
case "text":
|
|
2863
|
-
return /* @__PURE__ */
|
|
3402
|
+
return /* @__PURE__ */ jsx11(Fragment4, { children: token.content }, index);
|
|
2864
3403
|
case "bold":
|
|
2865
|
-
return /* @__PURE__ */
|
|
3404
|
+
return /* @__PURE__ */ jsx11("strong", { children: token.content }, index);
|
|
2866
3405
|
case "italic":
|
|
2867
|
-
return /* @__PURE__ */
|
|
3406
|
+
return /* @__PURE__ */ jsx11("em", { children: token.content }, index);
|
|
2868
3407
|
case "link":
|
|
2869
|
-
return /* @__PURE__ */
|
|
3408
|
+
return /* @__PURE__ */ jsx11(
|
|
2870
3409
|
"a",
|
|
2871
3410
|
{
|
|
2872
3411
|
href: token.url,
|
|
@@ -2878,7 +3417,7 @@ function tokensToElements(tokens) {
|
|
|
2878
3417
|
index
|
|
2879
3418
|
);
|
|
2880
3419
|
case "newline":
|
|
2881
|
-
return /* @__PURE__ */
|
|
3420
|
+
return /* @__PURE__ */ jsx11("br", {}, index);
|
|
2882
3421
|
default:
|
|
2883
3422
|
return null;
|
|
2884
3423
|
}
|
|
@@ -2890,15 +3429,15 @@ function parseMarkdownToElements(content) {
|
|
|
2890
3429
|
}
|
|
2891
3430
|
function MarkdownText({ content, className }) {
|
|
2892
3431
|
const elements = parseMarkdownToElements(content);
|
|
2893
|
-
return /* @__PURE__ */
|
|
3432
|
+
return /* @__PURE__ */ jsx11("span", { className, children: elements });
|
|
2894
3433
|
}
|
|
2895
3434
|
|
|
2896
3435
|
// src/router/Link.tsx
|
|
2897
3436
|
import { Link as WouterLink2 } from "wouter";
|
|
2898
|
-
import { jsx as
|
|
3437
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2899
3438
|
function Link2({ to, href, children, className, onClick, replace, ...props }) {
|
|
2900
3439
|
const target = href ?? to ?? "/";
|
|
2901
|
-
return /* @__PURE__ */
|
|
3440
|
+
return /* @__PURE__ */ jsx12(WouterLink2, { href: target, className, onClick, replace, ...props, children });
|
|
2902
3441
|
}
|
|
2903
3442
|
|
|
2904
3443
|
// src/router/useNavigate.ts
|
|
@@ -2917,7 +3456,7 @@ function useNavigate() {
|
|
|
2917
3456
|
|
|
2918
3457
|
// src/router/Router.tsx
|
|
2919
3458
|
import { Router as WouterRouter } from "wouter";
|
|
2920
|
-
import { jsx as
|
|
3459
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
2921
3460
|
function detectBasename() {
|
|
2922
3461
|
if (typeof window === "undefined") return "";
|
|
2923
3462
|
const sessionMatch = window.location.pathname.match(/^\/session\/[^/]+/);
|
|
@@ -2932,12 +3471,13 @@ function detectBasename() {
|
|
|
2932
3471
|
}
|
|
2933
3472
|
function Router({ children, base }) {
|
|
2934
3473
|
const basename = base ?? detectBasename();
|
|
2935
|
-
return /* @__PURE__ */
|
|
3474
|
+
return /* @__PURE__ */ jsx13(WouterRouter, { base: basename, children });
|
|
2936
3475
|
}
|
|
2937
3476
|
|
|
2938
3477
|
// src/router/index.ts
|
|
2939
3478
|
import { Route, Switch } from "wouter";
|
|
2940
3479
|
export {
|
|
3480
|
+
AIEditProvider,
|
|
2941
3481
|
ContentStoreProvider,
|
|
2942
3482
|
ContentStoreProvider2 as ContentStoreProviderProd,
|
|
2943
3483
|
Link2 as Link,
|
|
@@ -2951,15 +3491,28 @@ export {
|
|
|
2951
3491
|
YaImage,
|
|
2952
3492
|
YaLink,
|
|
2953
3493
|
YaText,
|
|
3494
|
+
buildIntermediateText,
|
|
3495
|
+
calculateAnimationTiming,
|
|
3496
|
+
computeTextDiff,
|
|
3497
|
+
containsHtml,
|
|
2954
3498
|
contentRegistry,
|
|
2955
3499
|
getAllContent,
|
|
2956
3500
|
getContent,
|
|
3501
|
+
getTextCursorPosition,
|
|
2957
3502
|
hasContent,
|
|
3503
|
+
imageCrossfadeStrategy,
|
|
2958
3504
|
initBuilderSelection,
|
|
3505
|
+
linkTransitionStrategy,
|
|
2959
3506
|
registerContent,
|
|
2960
3507
|
resolveAssetUrl,
|
|
2961
3508
|
serializeImageValue,
|
|
2962
3509
|
setAssetResolver,
|
|
3510
|
+
stripHtml,
|
|
3511
|
+
textTypingStrategy,
|
|
3512
|
+
useAIEditAnimation,
|
|
3513
|
+
useAIEditContext,
|
|
3514
|
+
useAIEditContextOptional,
|
|
3515
|
+
useAnimatedText,
|
|
2963
3516
|
useContentStore,
|
|
2964
3517
|
useContentStore2 as useContentStoreProd,
|
|
2965
3518
|
useNavigate
|