easy-email-pro-theme 1.59.10 → 1.60.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/lib/index.js +1028 -284
- package/lib/typings/components/AIAgent/applyResult.d.ts +2 -0
- package/lib/typings/components/HoveringToolbar/RichTextBar.d.ts +1 -3
- package/lib/typings/components/HoveringToolbar/popupCoordinator.d.ts +19 -0
- package/lib/typings/hooks/aiBatchUpdate.d.ts +28 -0
- package/lib/typings/hooks/aiEditorTransaction.d.ts +8 -0
- package/lib/typings/hooks/aiExternalHistory.d.ts +10 -0
- package/lib/typings/hooks/aiSubjectUpdate.d.ts +4 -0
- package/lib/typings/hooks/aiTransactionalMutation.d.ts +3 -0
- package/lib/typings/hooks/useApplyAiToolCalls.d.ts +26 -0
- package/lib/typings/typings/custom-types.d.ts +2 -0
- package/package.json +4 -1
package/lib/index.js
CHANGED
|
@@ -58,17 +58,17 @@ import { classnames, useEditorActions, useDragNodePath, useStandaloneElementEdit
|
|
|
58
58
|
import { useSlate, ReactEditor, useSlateStatic, useSelected } from "slate-react";
|
|
59
59
|
import * as React$2 from "react";
|
|
60
60
|
import React__default, { useRef, useState, useEffect, useCallback, useMemo, createContext, useContext, useLayoutEffect, memo, useReducer, cloneElement, forwardRef, createElement, Suspense, Component } from "react";
|
|
61
|
-
import { NodeUtils, BlockManager, ElementType, EditorCore, t, ElementCategory, classnames as classnames$1,
|
|
61
|
+
import { NodeUtils, BlockManager, ElementType, EditorCore, t, StandardType, ElementCategory, classnames as classnames$1, PluginManager, EditorAuth, mjmlToJsonCore, ConditionOperator, ConditionOperatorSymbol, EmailRenderProvider, components, HtmlNodeAdapter, assertAiAgentFeatureEnabled, imageReplacementTarget, imageDecisionChoices, canAutoReplaceImageTarget, imageTargetAttributeKey, normalizeToolCallsPayload, freezeSelectedTargets, selectedTargetFromContext, resolveAiChatResult, choiceImageAttributeKey, I18nManager } from "easy-email-pro-core";
|
|
62
62
|
import { parseEasyEmailAiStream, resolveAiChatResult as resolveAiChatResult2 } from "easy-email-pro-core";
|
|
63
|
-
import { cloneDeep,
|
|
63
|
+
import { cloneDeep, omit as omit$2, get, set, isEqual, merge as merge$1, debounce as debounce$2, isUndefined as isUndefined$1, uniqueId, isFunction as isFunction$5, isString as isString$2, isNumber as isNumber$1, upperFirst, sum, flatMap } from "lodash";
|
|
64
64
|
import { Editor, Range, Node, Transforms, Path, Text as Text$4, createEditor } from "slate";
|
|
65
65
|
import { nanoid } from "nanoid";
|
|
66
66
|
import { Form, Input, Modal, Collapse, Space, Empty, Card, Grid, Button as Button$2, Drawer, Switch, Typography as Typography$1, Tabs, Radio, Tooltip, Divider as Divider$2, Alert, Popconfirm, Message, PageHeader as PageHeader$1, Spin, Layout as Layout$2, ConfigProvider, Popover, ColorPicker as ColorPicker$2, Select as Select$1, Slider, InputNumber, Tag, Link as Link$3, List as List$1, Skeleton, Trigger } from "@arco-design/web-react";
|
|
67
|
+
import { HistoryEditor } from "slate-history";
|
|
67
68
|
import { IconPlus, IconCopy, IconDelete, IconEdit, IconLeft, IconDownload, IconUndo, IconRedo, IconMinus, IconEye, IconSubscribeAdd, IconClose, IconCheckCircleFill, IconDragArrow, IconPalette, IconLock, IconUnlock, IconImage, IconQuestionCircle, IconLink, IconCloud, IconDragDotVertical, IconSend, IconDown, IconCheck, IconSearch } from "@arco-design/web-react/icon";
|
|
68
69
|
import { unstable_batchedUpdates, createPortal } from "react-dom";
|
|
69
70
|
import mjml from "mjml-browser";
|
|
70
71
|
import { getImageUrlsForAmp, mjml2amp } from "mjml2amp";
|
|
71
|
-
import { HistoryEditor } from "slate-history";
|
|
72
72
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
73
73
|
const styleText$h = `@font-face {
|
|
74
74
|
font-family: "iconfont"; /* Project id 4003152 */
|
|
@@ -1366,6 +1366,49 @@ const DraggingProvider = ({
|
|
|
1366
1366
|
}, [dragHandle, isDragging]);
|
|
1367
1367
|
return /* @__PURE__ */ React__default.createElement(DraggingProviderContext.Provider, { value }, children);
|
|
1368
1368
|
};
|
|
1369
|
+
function setEditorFieldValue(editor, path2, name, value) {
|
|
1370
|
+
const node = Node.get(editor, path2);
|
|
1371
|
+
if (NodeUtils.isTextNode(node)) {
|
|
1372
|
+
Transforms.insertText(editor, String(value != null ? value : ""), { at: path2 });
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
if (name === "children") {
|
|
1376
|
+
if (!Array.isArray(value)) {
|
|
1377
|
+
throw new Error("children must be an array");
|
|
1378
|
+
}
|
|
1379
|
+
const children = node.children || [];
|
|
1380
|
+
Editor.withoutNormalizing(editor, () => {
|
|
1381
|
+
for (let index2 = children.length - 1; index2 >= 0; index2 -= 1) {
|
|
1382
|
+
Transforms.removeNodes(editor, { at: [...path2, index2] });
|
|
1383
|
+
}
|
|
1384
|
+
if (value.length) {
|
|
1385
|
+
Transforms.insertNodes(editor, cloneDeep(value), {
|
|
1386
|
+
at: [...path2, 0]
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
if (name === "") {
|
|
1393
|
+
editor.replaceNode({ path: path2, node: value });
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
const cloneNode = cloneDeep(omit$2(node, "children"));
|
|
1397
|
+
if (value === void 0) {
|
|
1398
|
+
const dotIndex = name.lastIndexOf(".");
|
|
1399
|
+
if (dotIndex > -1) {
|
|
1400
|
+
const parent2 = get(cloneNode, name.substring(0, dotIndex));
|
|
1401
|
+
if (parent2 && typeof parent2 === "object") {
|
|
1402
|
+
delete parent2[name.substring(dotIndex + 1)];
|
|
1403
|
+
}
|
|
1404
|
+
} else {
|
|
1405
|
+
delete cloneNode[name];
|
|
1406
|
+
}
|
|
1407
|
+
} else {
|
|
1408
|
+
set(cloneNode, name, value);
|
|
1409
|
+
}
|
|
1410
|
+
Transforms.setNodes(editor, cloneNode, { at: path2 });
|
|
1411
|
+
}
|
|
1369
1412
|
const loop$1 = () => {
|
|
1370
1413
|
};
|
|
1371
1414
|
const getNodePathName = (path2, name) => {
|
|
@@ -1432,58 +1475,30 @@ const EditorContextProvider = (props) => {
|
|
|
1432
1475
|
getFieldValue(path2, name)
|
|
1433
1476
|
);
|
|
1434
1477
|
});
|
|
1435
|
-
const
|
|
1478
|
+
const setFieldValueTransactional = useEventCallback(
|
|
1436
1479
|
(path2, name, val) => {
|
|
1437
1480
|
if (!path2) {
|
|
1438
1481
|
form.setFieldValue(name, val);
|
|
1439
1482
|
return;
|
|
1440
1483
|
}
|
|
1484
|
+
setEditorFieldValue(editor, path2, name, val);
|
|
1485
|
+
form.setFieldValue(getNodePathName(path2, name), val);
|
|
1486
|
+
}
|
|
1487
|
+
);
|
|
1488
|
+
const setFieldValue = useEventCallback(
|
|
1489
|
+
(path2, name, val) => {
|
|
1441
1490
|
try {
|
|
1442
|
-
|
|
1443
|
-
if (NodeUtils.isTextNode(node)) {
|
|
1444
|
-
Transforms.insertText(editor, val, {
|
|
1445
|
-
at: path2
|
|
1446
|
-
});
|
|
1447
|
-
} else {
|
|
1448
|
-
if (name === "children") {
|
|
1449
|
-
const cloneNode = cloneDeep(node);
|
|
1450
|
-
set(cloneNode, name, val);
|
|
1451
|
-
editor.replaceNode({
|
|
1452
|
-
path: path2,
|
|
1453
|
-
node: cloneNode
|
|
1454
|
-
});
|
|
1455
|
-
} else if (name === "") {
|
|
1456
|
-
editor.replaceNode({
|
|
1457
|
-
path: path2,
|
|
1458
|
-
node: val
|
|
1459
|
-
});
|
|
1460
|
-
} else {
|
|
1461
|
-
const cloneNode = cloneDeep(omit$2(node, "children"));
|
|
1462
|
-
if (val === void 0) {
|
|
1463
|
-
const dotIndex = name.lastIndexOf(".");
|
|
1464
|
-
if (dotIndex > -1) {
|
|
1465
|
-
const parentName = name.substring(0, dotIndex);
|
|
1466
|
-
const parent2 = get(cloneNode, parentName);
|
|
1467
|
-
if (parent2) {
|
|
1468
|
-
parent2[name.substring(dotIndex + 1)] = void 0;
|
|
1469
|
-
}
|
|
1470
|
-
} else {
|
|
1471
|
-
cloneNode[name] = void 0;
|
|
1472
|
-
}
|
|
1473
|
-
} else {
|
|
1474
|
-
set(cloneNode, name, val);
|
|
1475
|
-
}
|
|
1476
|
-
Transforms.setNodes(editor, cloneNode, {
|
|
1477
|
-
at: path2
|
|
1478
|
-
});
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
|
-
form.setFieldValue(getNodePathName(path2, name), val);
|
|
1491
|
+
setFieldValueTransactional(path2, name, val);
|
|
1482
1492
|
} catch (error2) {
|
|
1483
1493
|
console.log(error2);
|
|
1484
1494
|
}
|
|
1485
1495
|
}
|
|
1486
1496
|
);
|
|
1497
|
+
const syncValues = useEventCallback(
|
|
1498
|
+
(newValues) => {
|
|
1499
|
+
form.setFieldsValue(newValues);
|
|
1500
|
+
}
|
|
1501
|
+
);
|
|
1487
1502
|
const reset = useEventCallback((newValues) => {
|
|
1488
1503
|
if (isEqual(newValues, values))
|
|
1489
1504
|
return;
|
|
@@ -1551,6 +1566,8 @@ const EditorContextProvider = (props) => {
|
|
|
1551
1566
|
inited,
|
|
1552
1567
|
pageDataVariables,
|
|
1553
1568
|
setFieldValue,
|
|
1569
|
+
setFieldValueTransactional,
|
|
1570
|
+
syncValues,
|
|
1554
1571
|
getFieldDirty,
|
|
1555
1572
|
valid,
|
|
1556
1573
|
reset,
|
|
@@ -1564,6 +1581,8 @@ const EditorContextProvider = (props) => {
|
|
|
1564
1581
|
inited,
|
|
1565
1582
|
pageDataVariables,
|
|
1566
1583
|
setFieldValue,
|
|
1584
|
+
setFieldValueTransactional,
|
|
1585
|
+
syncValues,
|
|
1567
1586
|
getFieldDirty,
|
|
1568
1587
|
valid,
|
|
1569
1588
|
reset,
|
|
@@ -2333,6 +2352,335 @@ const useBlocksDrawer = () => {
|
|
|
2333
2352
|
parentCategory: context.blocksDrawerParentCategory
|
|
2334
2353
|
};
|
|
2335
2354
|
};
|
|
2355
|
+
const MAX_AI_BATCH_TARGETS = 200;
|
|
2356
|
+
const STANDARD_TYPES = new Set(Object.values(StandardType));
|
|
2357
|
+
const CHANGE_FIELDS = [
|
|
2358
|
+
"text",
|
|
2359
|
+
"attributes",
|
|
2360
|
+
"mobileAttributes",
|
|
2361
|
+
"data",
|
|
2362
|
+
"visibility"
|
|
2363
|
+
];
|
|
2364
|
+
function isObject$c(value) {
|
|
2365
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
2366
|
+
}
|
|
2367
|
+
function isSafeFieldKey$1(key2) {
|
|
2368
|
+
return typeof key2 === "string" && key2.length > 0 && key2.length <= 80 && !key2.includes("__proto__") && !key2.includes("prototype") && !key2.includes("constructor") && /^[a-zA-Z0-9_.-]+$/.test(key2);
|
|
2369
|
+
}
|
|
2370
|
+
function validateRecordKeys(value) {
|
|
2371
|
+
if (!isObject$c(value))
|
|
2372
|
+
throw new Error("batch changes must be objects");
|
|
2373
|
+
Object.keys(value).forEach((key2) => {
|
|
2374
|
+
if (!isSafeFieldKey$1(key2))
|
|
2375
|
+
throw new Error(`unsafe field key: ${key2}`);
|
|
2376
|
+
});
|
|
2377
|
+
}
|
|
2378
|
+
function validateFilter(filter2) {
|
|
2379
|
+
if (filter2.field !== "text" && filter2.field !== "attribute" && filter2.field !== "mobileAttribute" && filter2.field !== "data") {
|
|
2380
|
+
throw new Error(`unsupported batch filter field: ${String(filter2.field)}`);
|
|
2381
|
+
}
|
|
2382
|
+
if (filter2.operator !== "equals" && filter2.operator !== "contains" && filter2.operator !== "exists") {
|
|
2383
|
+
throw new Error(
|
|
2384
|
+
`unsupported batch filter operator: ${String(filter2.operator)}`
|
|
2385
|
+
);
|
|
2386
|
+
}
|
|
2387
|
+
if (filter2.field !== "text" && !isSafeFieldKey$1(filter2.key)) {
|
|
2388
|
+
throw new Error("batch filter key is required and must be safe");
|
|
2389
|
+
}
|
|
2390
|
+
if (filter2.operator === "contains" && typeof filter2.value !== "string") {
|
|
2391
|
+
throw new Error("batch contains filter requires a string value");
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
function validateBatchUpdateCall(call) {
|
|
2395
|
+
var _a;
|
|
2396
|
+
if (call.name !== "batch_update") {
|
|
2397
|
+
throw new Error("batch_update tool call is required");
|
|
2398
|
+
}
|
|
2399
|
+
if (call.selector.scope !== "template" && call.selector.scope !== "descendants") {
|
|
2400
|
+
throw new Error("invalid batch selector scope");
|
|
2401
|
+
}
|
|
2402
|
+
if (!Array.isArray(call.selector.types) || call.selector.types.length === 0) {
|
|
2403
|
+
throw new Error("at least one standard block type is required");
|
|
2404
|
+
}
|
|
2405
|
+
call.selector.types.forEach((type) => {
|
|
2406
|
+
if (!STANDARD_TYPES.has(type)) {
|
|
2407
|
+
throw new Error(`unsupported standard block type: ${type}`);
|
|
2408
|
+
}
|
|
2409
|
+
});
|
|
2410
|
+
if (call.selector.scope === "descendants" && !call.selector.root) {
|
|
2411
|
+
throw new Error("descendants scope requires a root target");
|
|
2412
|
+
}
|
|
2413
|
+
(call.selector.where || []).forEach(validateFilter);
|
|
2414
|
+
const changes2 = call.changes || {};
|
|
2415
|
+
if (!CHANGE_FIELDS.some((field) => changes2[field] !== void 0)) {
|
|
2416
|
+
throw new Error("at least one batch change is required");
|
|
2417
|
+
}
|
|
2418
|
+
if (changes2.text !== void 0 && typeof changes2.text !== "string") {
|
|
2419
|
+
throw new Error("batch text change must be a string");
|
|
2420
|
+
}
|
|
2421
|
+
if (changes2.attributes !== void 0)
|
|
2422
|
+
validateRecordKeys(changes2.attributes);
|
|
2423
|
+
if (changes2.mobileAttributes !== void 0)
|
|
2424
|
+
validateRecordKeys(changes2.mobileAttributes);
|
|
2425
|
+
if (changes2.data !== void 0)
|
|
2426
|
+
validateRecordKeys(changes2.data);
|
|
2427
|
+
if (changes2.visibility !== void 0 && (!isObject$c(changes2.visibility) || typeof changes2.visibility.desktop !== "boolean" || typeof changes2.visibility.mobile !== "boolean")) {
|
|
2428
|
+
throw new Error("batch visibility change is invalid");
|
|
2429
|
+
}
|
|
2430
|
+
if (((_a = changes2.visibility) == null ? void 0 : _a.desktop) === false && changes2.visibility.mobile === false) {
|
|
2431
|
+
throw new Error("at least one device must remain visible");
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
function ownValue(record, key2) {
|
|
2435
|
+
if (!isObject$c(record) || !Object.prototype.hasOwnProperty.call(record, key2)) {
|
|
2436
|
+
return { exists: false, value: void 0 };
|
|
2437
|
+
}
|
|
2438
|
+
return { exists: true, value: record[key2] };
|
|
2439
|
+
}
|
|
2440
|
+
function filterValue(element, filter2) {
|
|
2441
|
+
if (filter2.field === "text") {
|
|
2442
|
+
return { exists: true, value: Node.string(element) };
|
|
2443
|
+
}
|
|
2444
|
+
const key2 = filter2.key;
|
|
2445
|
+
if (filter2.field === "attribute")
|
|
2446
|
+
return ownValue(element.attributes, key2);
|
|
2447
|
+
if (filter2.field === "mobileAttribute")
|
|
2448
|
+
return ownValue(element.mobileAttributes, key2);
|
|
2449
|
+
return ownValue(element.data, key2);
|
|
2450
|
+
}
|
|
2451
|
+
function matchesFilter(element, filter2) {
|
|
2452
|
+
const current = filterValue(element, filter2);
|
|
2453
|
+
if (filter2.operator === "exists")
|
|
2454
|
+
return current.exists;
|
|
2455
|
+
if (filter2.operator === "contains") {
|
|
2456
|
+
return typeof current.value === "string" && current.value.includes(filter2.value);
|
|
2457
|
+
}
|
|
2458
|
+
return current.exists && Object.is(current.value, filter2.value);
|
|
2459
|
+
}
|
|
2460
|
+
function resolveBatchUpdateTargets(editor, call, resolveRoot) {
|
|
2461
|
+
validateBatchUpdateCall(call);
|
|
2462
|
+
let at = [];
|
|
2463
|
+
if (call.selector.scope === "descendants") {
|
|
2464
|
+
const root2 = (resolveRoot == null ? void 0 : resolveRoot(call.selector.root)) || null;
|
|
2465
|
+
if (!root2)
|
|
2466
|
+
throw new Error("batch root target not found");
|
|
2467
|
+
at = root2;
|
|
2468
|
+
}
|
|
2469
|
+
const acceptedTypes = new Set(call.selector.types);
|
|
2470
|
+
const filters = call.selector.where || [];
|
|
2471
|
+
const targets = Array.from(
|
|
2472
|
+
Editor.nodes(editor, {
|
|
2473
|
+
at,
|
|
2474
|
+
match: (node) => {
|
|
2475
|
+
if (!NodeUtils.isElement(node))
|
|
2476
|
+
return false;
|
|
2477
|
+
const element = node;
|
|
2478
|
+
return acceptedTypes.has(element.type) && filters.every((filter2) => matchesFilter(element, filter2));
|
|
2479
|
+
}
|
|
2480
|
+
})
|
|
2481
|
+
).map(([node, path2]) => ({
|
|
2482
|
+
element: node,
|
|
2483
|
+
path: [...path2]
|
|
2484
|
+
}));
|
|
2485
|
+
return { call, targets };
|
|
2486
|
+
}
|
|
2487
|
+
function assertBatchTargetLimit(batches, limit = MAX_AI_BATCH_TARGETS) {
|
|
2488
|
+
const count = batches.reduce(
|
|
2489
|
+
(total, batch) => total + batch.targets.length,
|
|
2490
|
+
0
|
|
2491
|
+
);
|
|
2492
|
+
if (count > limit) {
|
|
2493
|
+
throw new Error(`batch target limit exceeded: ${count}/${limit}`);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
function getBatchRecordUpdate(current, key2, nextValue) {
|
|
2497
|
+
const value = nextValue === null ? void 0 : nextValue;
|
|
2498
|
+
const hasCurrent = Object.prototype.hasOwnProperty.call(current, key2);
|
|
2499
|
+
return {
|
|
2500
|
+
changed: !(value === void 0 && !hasCurrent) && !Object.is(current[key2], value),
|
|
2501
|
+
value
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
function applyResolvedBatchUpdate(resolved, applyField) {
|
|
2505
|
+
const result = { applied: 0, skipped: 0, errors: [] };
|
|
2506
|
+
if (!resolved.targets.length)
|
|
2507
|
+
return __spreadProps(__spreadValues({}, result), { skipped: 1 });
|
|
2508
|
+
for (const target of resolved.targets) {
|
|
2509
|
+
let changed = false;
|
|
2510
|
+
for (const field of CHANGE_FIELDS) {
|
|
2511
|
+
if (resolved.call.changes[field] === void 0)
|
|
2512
|
+
continue;
|
|
2513
|
+
const fieldResult = applyField(
|
|
2514
|
+
target,
|
|
2515
|
+
field,
|
|
2516
|
+
resolved.call.changes[field]
|
|
2517
|
+
);
|
|
2518
|
+
if (typeof fieldResult === "boolean") {
|
|
2519
|
+
changed = fieldResult || changed;
|
|
2520
|
+
} else {
|
|
2521
|
+
changed = fieldResult.changed || changed;
|
|
2522
|
+
if (fieldResult.error) {
|
|
2523
|
+
result.errors.push(`${target.element.type}: ${fieldResult.error}`);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
if (changed)
|
|
2528
|
+
result.applied += 1;
|
|
2529
|
+
else
|
|
2530
|
+
result.skipped += 1;
|
|
2531
|
+
}
|
|
2532
|
+
return result;
|
|
2533
|
+
}
|
|
2534
|
+
const changes = /* @__PURE__ */ new WeakMap();
|
|
2535
|
+
const operationChange = Symbol("aiExternalHistoryChange");
|
|
2536
|
+
const setters = /* @__PURE__ */ new WeakMap();
|
|
2537
|
+
const installed = /* @__PURE__ */ new WeakSet();
|
|
2538
|
+
function mergeChanges(earlier, later) {
|
|
2539
|
+
if (!earlier)
|
|
2540
|
+
return later;
|
|
2541
|
+
if (!later)
|
|
2542
|
+
return earlier;
|
|
2543
|
+
return { before: earlier.before, after: later.after };
|
|
2544
|
+
}
|
|
2545
|
+
function getAiExternalHistory(batch) {
|
|
2546
|
+
if (!batch)
|
|
2547
|
+
return void 0;
|
|
2548
|
+
return changes.get(batch) || batch.operations.map(
|
|
2549
|
+
(operation) => operation[operationChange]
|
|
2550
|
+
).find(Boolean);
|
|
2551
|
+
}
|
|
2552
|
+
function installAiExternalHistory(editor, setValue) {
|
|
2553
|
+
setters.set(editor, setValue);
|
|
2554
|
+
if (installed.has(editor))
|
|
2555
|
+
return;
|
|
2556
|
+
installed.add(editor);
|
|
2557
|
+
const undo = editor.undo.bind(editor);
|
|
2558
|
+
const redo = editor.redo.bind(editor);
|
|
2559
|
+
const writeHistory = editor.writeHistory.bind(editor);
|
|
2560
|
+
let activeChange;
|
|
2561
|
+
editor.writeHistory = (stack, batch) => {
|
|
2562
|
+
const beforeLength = editor.history[stack].length;
|
|
2563
|
+
const previousBatch = editor.history[stack].at(-1);
|
|
2564
|
+
const previousChange = getAiExternalHistory(previousBatch);
|
|
2565
|
+
const incomingChange = mergeChanges(
|
|
2566
|
+
getAiExternalHistory(batch),
|
|
2567
|
+
activeChange
|
|
2568
|
+
);
|
|
2569
|
+
writeHistory(stack, batch);
|
|
2570
|
+
const actualBatch = editor.history[stack].at(-1);
|
|
2571
|
+
if (!actualBatch)
|
|
2572
|
+
return;
|
|
2573
|
+
const replacedPrevious = editor.history[stack].length === beforeLength && actualBatch !== previousBatch;
|
|
2574
|
+
const change = replacedPrevious ? mergeChanges(previousChange, incomingChange) : incomingChange;
|
|
2575
|
+
if (change)
|
|
2576
|
+
attachAiExternalHistory(actualBatch, change);
|
|
2577
|
+
};
|
|
2578
|
+
editor.undo = () => {
|
|
2579
|
+
var _a;
|
|
2580
|
+
const batch = editor.history.undos.at(-1);
|
|
2581
|
+
const change = getAiExternalHistory(batch);
|
|
2582
|
+
activeChange = change;
|
|
2583
|
+
try {
|
|
2584
|
+
undo();
|
|
2585
|
+
} finally {
|
|
2586
|
+
activeChange = void 0;
|
|
2587
|
+
}
|
|
2588
|
+
if (change)
|
|
2589
|
+
(_a = setters.get(editor)) == null ? void 0 : _a(change.before);
|
|
2590
|
+
};
|
|
2591
|
+
editor.redo = () => {
|
|
2592
|
+
var _a;
|
|
2593
|
+
const batch = editor.history.redos.at(-1);
|
|
2594
|
+
const change = getAiExternalHistory(batch);
|
|
2595
|
+
activeChange = change;
|
|
2596
|
+
try {
|
|
2597
|
+
redo();
|
|
2598
|
+
} finally {
|
|
2599
|
+
activeChange = void 0;
|
|
2600
|
+
}
|
|
2601
|
+
if (change)
|
|
2602
|
+
(_a = setters.get(editor)) == null ? void 0 : _a(change.after);
|
|
2603
|
+
};
|
|
2604
|
+
}
|
|
2605
|
+
function attachAiExternalHistory(batch, change) {
|
|
2606
|
+
changes.set(batch, change);
|
|
2607
|
+
batch.operations.forEach((operation) => {
|
|
2608
|
+
Object.assign(operation, { [operationChange]: change });
|
|
2609
|
+
});
|
|
2610
|
+
}
|
|
2611
|
+
function runAiEditorTransaction(editor, apply2, options2 = {}) {
|
|
2612
|
+
var _a;
|
|
2613
|
+
const undosBefore = [...editor.history.undos];
|
|
2614
|
+
const redosBefore = [...editor.history.redos];
|
|
2615
|
+
const undoStart = editor.history.undos.length;
|
|
2616
|
+
try {
|
|
2617
|
+
let result;
|
|
2618
|
+
HistoryEditor.withoutMerging(editor, () => {
|
|
2619
|
+
Editor.withoutNormalizing(editor, () => {
|
|
2620
|
+
result = apply2();
|
|
2621
|
+
});
|
|
2622
|
+
});
|
|
2623
|
+
const newBatches = editor.history.undos.splice(undoStart);
|
|
2624
|
+
const externalChange = ((_a = options2.getExternalChange) == null ? void 0 : _a.call(options2)) || null;
|
|
2625
|
+
const hasExternalChange = Boolean(
|
|
2626
|
+
externalChange && externalChange.before !== externalChange.after
|
|
2627
|
+
);
|
|
2628
|
+
const finalBatch = newBatches.length ? {
|
|
2629
|
+
operations: newBatches.flatMap((batch) => batch.operations),
|
|
2630
|
+
selectionBefore: newBatches[0].selectionBefore
|
|
2631
|
+
} : hasExternalChange ? { operations: [], selectionBefore: editor.selection } : null;
|
|
2632
|
+
if (finalBatch) {
|
|
2633
|
+
editor.history.undos.push(finalBatch);
|
|
2634
|
+
if (hasExternalChange && externalChange) {
|
|
2635
|
+
attachAiExternalHistory(finalBatch, externalChange);
|
|
2636
|
+
}
|
|
2637
|
+
if (!newBatches.length) {
|
|
2638
|
+
editor.history.redos = [];
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
return result;
|
|
2642
|
+
} catch (error2) {
|
|
2643
|
+
while (editor.history.undos.length > undoStart) {
|
|
2644
|
+
HistoryEditor.undo(editor);
|
|
2645
|
+
}
|
|
2646
|
+
editor.history.undos = undosBefore;
|
|
2647
|
+
editor.history.redos = redosBefore;
|
|
2648
|
+
throw error2;
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
function validateAiSubject(value) {
|
|
2652
|
+
if (typeof value !== "string") {
|
|
2653
|
+
throw new Error(t("subject must be a string"));
|
|
2654
|
+
}
|
|
2655
|
+
if (!value.trim()) {
|
|
2656
|
+
throw new Error(t("subject cannot be empty"));
|
|
2657
|
+
}
|
|
2658
|
+
return value;
|
|
2659
|
+
}
|
|
2660
|
+
function isAiSubjectChanged(current, next) {
|
|
2661
|
+
return current !== next;
|
|
2662
|
+
}
|
|
2663
|
+
function subjectAfterApplyingTemplate(current, template) {
|
|
2664
|
+
if (!template || typeof template !== "object" || !("subject" in template)) {
|
|
2665
|
+
return current;
|
|
2666
|
+
}
|
|
2667
|
+
return validateAiSubject(template.subject);
|
|
2668
|
+
}
|
|
2669
|
+
function emailAfterApplyingAiTemplate(current, template) {
|
|
2670
|
+
if (!template || typeof template !== "object")
|
|
2671
|
+
return current;
|
|
2672
|
+
const candidate = template;
|
|
2673
|
+
if (!candidate.content || typeof candidate.content !== "object") {
|
|
2674
|
+
return current;
|
|
2675
|
+
}
|
|
2676
|
+
return __spreadProps(__spreadValues({}, current), {
|
|
2677
|
+
subject: subjectAfterApplyingTemplate(
|
|
2678
|
+
typeof current.subject === "string" ? current.subject : "",
|
|
2679
|
+
candidate
|
|
2680
|
+
),
|
|
2681
|
+
content: candidate.content
|
|
2682
|
+
});
|
|
2683
|
+
}
|
|
2336
2684
|
const MAX_TOOL_CALLS = 30;
|
|
2337
2685
|
const MAX_REPLACE_CHILDREN_NODES = 160;
|
|
2338
2686
|
function isObject$b(value) {
|
|
@@ -2423,6 +2771,10 @@ function targetFromElement(element, fallback) {
|
|
|
2423
2771
|
return fallback;
|
|
2424
2772
|
}
|
|
2425
2773
|
function describeAppliedChange(call) {
|
|
2774
|
+
if (call.name === "update_subject")
|
|
2775
|
+
return t("Subject updated");
|
|
2776
|
+
if (call.name === "batch_update")
|
|
2777
|
+
return t("Batch updated");
|
|
2426
2778
|
if (call.name === "update_text")
|
|
2427
2779
|
return t("Text updated");
|
|
2428
2780
|
if (call.name === "update_attribute")
|
|
@@ -2511,13 +2863,21 @@ function normalizeElementBlock(block) {
|
|
|
2511
2863
|
children: Array.isArray(normalized.children) ? normalized.children : []
|
|
2512
2864
|
}));
|
|
2513
2865
|
}
|
|
2866
|
+
function createBlockForInsert(block) {
|
|
2867
|
+
const normalized = normalizeBlock(block);
|
|
2868
|
+
const definition = BlockManager.getBlockByType(normalized.type);
|
|
2869
|
+
return assignIdsToElementTree(definition.create(normalized));
|
|
2870
|
+
}
|
|
2514
2871
|
function useApplyAiToolCalls() {
|
|
2515
2872
|
const editor = useSlate();
|
|
2516
2873
|
const lock = useLockState();
|
|
2517
2874
|
const selectedNodePath = useSelectedNodePath();
|
|
2518
2875
|
const setSelectedNodePath = useSetSelectedNodePath();
|
|
2519
|
-
const
|
|
2520
|
-
const {
|
|
2876
|
+
const setHoverNodePath = useSetHoverNodePath();
|
|
2877
|
+
const { setFieldValueTransactional, syncValues, reset, values } = useEditorContext();
|
|
2878
|
+
installAiExternalHistory(editor, (subject) => {
|
|
2879
|
+
setFieldValueTransactional(null, "subject", subject);
|
|
2880
|
+
});
|
|
2521
2881
|
const resolveTargetPath = useEventCallback((target) => {
|
|
2522
2882
|
if ("selected" in target)
|
|
2523
2883
|
return selectedNodePath;
|
|
@@ -2561,6 +2921,57 @@ function useApplyAiToolCalls() {
|
|
|
2561
2921
|
return [node, path2];
|
|
2562
2922
|
}
|
|
2563
2923
|
);
|
|
2924
|
+
const applyBatchField = useEventCallback(
|
|
2925
|
+
(target, field, value) => {
|
|
2926
|
+
const node = Node.get(editor, target.path);
|
|
2927
|
+
if (!NodeUtils.isElement(node))
|
|
2928
|
+
return false;
|
|
2929
|
+
const element = node;
|
|
2930
|
+
if (field === "text") {
|
|
2931
|
+
if (typeof value !== "string" || !canReplaceWithPlainText(element)) {
|
|
2932
|
+
return {
|
|
2933
|
+
changed: false,
|
|
2934
|
+
error: t("target has no editable plain text")
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
if (Node.string(element) === value)
|
|
2938
|
+
return false;
|
|
2939
|
+
setFieldValueTransactional(
|
|
2940
|
+
target.path,
|
|
2941
|
+
"children",
|
|
2942
|
+
textToChildren(value)
|
|
2943
|
+
);
|
|
2944
|
+
return true;
|
|
2945
|
+
}
|
|
2946
|
+
if (field === "visibility") {
|
|
2947
|
+
if (!isObject$b(value))
|
|
2948
|
+
return false;
|
|
2949
|
+
const visible = value.desktop === true && value.mobile === false ? "desktop" : value.desktop === false && value.mobile === true ? "mobile" : void 0;
|
|
2950
|
+
if (element.visible === visible)
|
|
2951
|
+
return false;
|
|
2952
|
+
setFieldValueTransactional(target.path, "visible", visible);
|
|
2953
|
+
return true;
|
|
2954
|
+
}
|
|
2955
|
+
if (!isObject$b(value))
|
|
2956
|
+
return false;
|
|
2957
|
+
const fieldRoot = field;
|
|
2958
|
+
const source = element[fieldRoot];
|
|
2959
|
+
const current = isObject$b(source) ? source : {};
|
|
2960
|
+
let changed = false;
|
|
2961
|
+
Object.entries(value).forEach(([key2, nextValue]) => {
|
|
2962
|
+
const update = getBatchRecordUpdate(current, key2, nextValue);
|
|
2963
|
+
if (!update.changed)
|
|
2964
|
+
return;
|
|
2965
|
+
setFieldValueTransactional(
|
|
2966
|
+
target.path,
|
|
2967
|
+
`${fieldRoot}.${key2}`,
|
|
2968
|
+
update.value
|
|
2969
|
+
);
|
|
2970
|
+
changed = true;
|
|
2971
|
+
});
|
|
2972
|
+
return changed;
|
|
2973
|
+
}
|
|
2974
|
+
);
|
|
2564
2975
|
return useEventCallback((toolCalls) => {
|
|
2565
2976
|
const result = {
|
|
2566
2977
|
applied: 0,
|
|
@@ -2575,63 +2986,272 @@ function useApplyAiToolCalls() {
|
|
|
2575
2986
|
errors: [t("editor is locked")]
|
|
2576
2987
|
};
|
|
2577
2988
|
}
|
|
2989
|
+
if (toolCalls.some((call) => call.name === "apply_template") && toolCalls.length > 1) {
|
|
2990
|
+
return {
|
|
2991
|
+
applied: 0,
|
|
2992
|
+
skipped: toolCalls.length,
|
|
2993
|
+
errors: [t("apply_template cannot be mixed with other tools")],
|
|
2994
|
+
changes: []
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2578
2997
|
const calls = toolCalls.slice(0, MAX_TOOL_CALLS);
|
|
2579
2998
|
if (toolCalls.length > MAX_TOOL_CALLS) {
|
|
2580
2999
|
result.errors.push(`${t("tool calls truncated to")} ${MAX_TOOL_CALLS}`);
|
|
2581
3000
|
}
|
|
2582
|
-
|
|
3001
|
+
const resolvedBatches = /* @__PURE__ */ new Map();
|
|
3002
|
+
const resolvedTargets = /* @__PURE__ */ new Map();
|
|
3003
|
+
const preflightErrors = [];
|
|
3004
|
+
try {
|
|
2583
3005
|
calls.forEach((call, index2) => {
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
3006
|
+
if (call.name === "update_subject") {
|
|
3007
|
+
validateAiSubject(call.subject);
|
|
3008
|
+
return;
|
|
3009
|
+
}
|
|
3010
|
+
if (call.name === "apply_template") {
|
|
3011
|
+
if (!isObject$b(call.template)) {
|
|
3012
|
+
throw new Error(t("template must be an object"));
|
|
2589
3013
|
}
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
3014
|
+
if (calls.length > 1) {
|
|
3015
|
+
throw new Error(
|
|
3016
|
+
t("apply_template cannot be mixed with other tools")
|
|
3017
|
+
);
|
|
3018
|
+
}
|
|
3019
|
+
return;
|
|
3020
|
+
}
|
|
3021
|
+
if (call.name === "batch_update") {
|
|
3022
|
+
resolvedBatches.set(
|
|
3023
|
+
index2,
|
|
3024
|
+
resolveBatchUpdateTargets(
|
|
3025
|
+
editor,
|
|
3026
|
+
call,
|
|
3027
|
+
(target) => resolveTargetPath(target) || null
|
|
3028
|
+
)
|
|
3029
|
+
);
|
|
3030
|
+
return;
|
|
3031
|
+
}
|
|
3032
|
+
const targetEntry = getTargetElement(call.target);
|
|
3033
|
+
if (!targetEntry) {
|
|
3034
|
+
throw new Error(
|
|
3035
|
+
`${t("target not found")} (${targetLabel(call.target)})`
|
|
3036
|
+
);
|
|
3037
|
+
}
|
|
3038
|
+
const [element, path2] = targetEntry;
|
|
3039
|
+
resolvedTargets.set(index2, targetEntry);
|
|
3040
|
+
if (call.name === "update_text" && !canReplaceWithPlainText(element)) {
|
|
3041
|
+
throw new Error(
|
|
3042
|
+
hasAnyTextNode(element) ? t(
|
|
3043
|
+
"target contains mixed content; use a more specific text node"
|
|
3044
|
+
) : t("target has no editable text")
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
if ((call.name === "update_attribute" || call.name === "update_mobile_attribute" || call.name === "update_data") && !isSafeFieldKey(call.key)) {
|
|
3048
|
+
throw new Error(t("invalid field key"));
|
|
3049
|
+
}
|
|
3050
|
+
if (call.name === "update_attributes") {
|
|
3051
|
+
if (!isObject$b(call.attributes)) {
|
|
3052
|
+
throw new Error(t("attributes must be an object"));
|
|
3053
|
+
}
|
|
3054
|
+
Object.keys(call.attributes).forEach((key2) => {
|
|
3055
|
+
if (!isSafeFieldKey(key2)) {
|
|
3056
|
+
throw new Error(`${t("invalid attribute key")}: ${key2}`);
|
|
3057
|
+
}
|
|
3058
|
+
});
|
|
3059
|
+
}
|
|
3060
|
+
if (call.name === "replace_children") {
|
|
3061
|
+
const total = countNodes(call.children);
|
|
3062
|
+
if (total > MAX_REPLACE_CHILDREN_NODES) {
|
|
3063
|
+
throw new Error(
|
|
3064
|
+
`${t("replace_children is too large")} (${total} ${t("nodes")})`
|
|
2595
3065
|
);
|
|
2596
|
-
return;
|
|
2597
3066
|
}
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
3067
|
+
normalizeChildren(call.children);
|
|
3068
|
+
}
|
|
3069
|
+
if (call.name === "set_visibility" && call.desktop === false && call.mobile === false) {
|
|
3070
|
+
throw new Error(t("at least one device must remain visible"));
|
|
3071
|
+
}
|
|
3072
|
+
if (call.name === "update_link" && typeof call.href !== "string") {
|
|
3073
|
+
throw new Error(t("href is required"));
|
|
3074
|
+
}
|
|
3075
|
+
if ((call.name === "replace_block" || call.name === "move_up" || call.name === "move_down" || call.name === "duplicate" || call.name === "delete_node" || call.name === "add_block_after" || call.name === "add_block_before") && isProtectedForStructureEdit(element)) {
|
|
3076
|
+
throw new Error(t("protected node cannot be structurally edited"));
|
|
3077
|
+
}
|
|
3078
|
+
if (call.name === "replace_block")
|
|
3079
|
+
normalizeElementBlock(call.block);
|
|
3080
|
+
if (call.name === "add_block_after" || call.name === "add_block_before") {
|
|
3081
|
+
createBlockForInsert(call.block);
|
|
3082
|
+
}
|
|
3083
|
+
Node.get(editor, path2);
|
|
3084
|
+
});
|
|
3085
|
+
assertBatchTargetLimit(Array.from(resolvedBatches.values()));
|
|
3086
|
+
} catch (error2) {
|
|
3087
|
+
preflightErrors.push(
|
|
3088
|
+
error2 instanceof Error ? error2.message : String(error2)
|
|
3089
|
+
);
|
|
3090
|
+
}
|
|
3091
|
+
if (preflightErrors.length) {
|
|
3092
|
+
return {
|
|
3093
|
+
applied: 0,
|
|
3094
|
+
skipped: calls.length,
|
|
3095
|
+
errors: preflightErrors,
|
|
3096
|
+
changes: []
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
const targetRefs = /* @__PURE__ */ new Map();
|
|
3100
|
+
const batchRefs = /* @__PURE__ */ new Map();
|
|
3101
|
+
resolvedTargets.forEach(([, path2], index2) => {
|
|
3102
|
+
targetRefs.set(index2, Editor.pathRef(editor, path2));
|
|
3103
|
+
});
|
|
3104
|
+
resolvedBatches.forEach((resolved, index2) => {
|
|
3105
|
+
batchRefs.set(
|
|
3106
|
+
index2,
|
|
3107
|
+
resolved.targets.map((target) => Editor.pathRef(editor, target.path))
|
|
3108
|
+
);
|
|
3109
|
+
});
|
|
3110
|
+
const originalValues = structuredClone(values);
|
|
3111
|
+
const subjectBefore = values.subject;
|
|
3112
|
+
let subjectAfter = subjectBefore;
|
|
3113
|
+
try {
|
|
3114
|
+
runAiEditorTransaction(
|
|
3115
|
+
editor,
|
|
3116
|
+
() => {
|
|
3117
|
+
calls.forEach((call, index2) => {
|
|
3118
|
+
var _a, _b, _c, _d;
|
|
3119
|
+
if (call.name === "update_subject") {
|
|
3120
|
+
const nextSubject = validateAiSubject(call.subject);
|
|
3121
|
+
if (!isAiSubjectChanged(subjectAfter, nextSubject)) {
|
|
3122
|
+
result.skipped += 1;
|
|
3123
|
+
return;
|
|
3124
|
+
}
|
|
3125
|
+
setFieldValueTransactional(null, "subject", nextSubject);
|
|
3126
|
+
subjectAfter = nextSubject;
|
|
3127
|
+
result.applied += 1;
|
|
3128
|
+
if (!((_a = result.changes) == null ? void 0 : _a.some((change) => change.id === "subject"))) {
|
|
3129
|
+
(_b = result.changes) == null ? void 0 : _b.push({
|
|
3130
|
+
id: "subject",
|
|
3131
|
+
label: t("Subject"),
|
|
3132
|
+
description: describeAppliedChange(call),
|
|
3133
|
+
target: { type: "page" }
|
|
3134
|
+
});
|
|
3135
|
+
}
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
if (call.name === "apply_template") {
|
|
3139
|
+
const nextTemplate = emailAfterApplyingAiTemplate(
|
|
3140
|
+
values,
|
|
3141
|
+
call.template
|
|
3142
|
+
);
|
|
3143
|
+
subjectAfter = subjectAfterApplyingTemplate(
|
|
3144
|
+
subjectAfter,
|
|
3145
|
+
nextTemplate
|
|
3146
|
+
);
|
|
3147
|
+
reset(nextTemplate);
|
|
3148
|
+
result.applied += 1;
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
if (call.name === "batch_update") {
|
|
3152
|
+
const resolved = resolvedBatches.get(index2);
|
|
3153
|
+
if (!resolved)
|
|
3154
|
+
throw new Error(t("batch targets not resolved"));
|
|
3155
|
+
const refs = batchRefs.get(index2) || [];
|
|
3156
|
+
const targets = resolved.targets.map((target, targetIndex) => {
|
|
3157
|
+
var _a2;
|
|
3158
|
+
const path22 = (_a2 = refs[targetIndex]) == null ? void 0 : _a2.current;
|
|
3159
|
+
if (!path22)
|
|
3160
|
+
throw new Error(t("batch target no longer exists"));
|
|
3161
|
+
return __spreadProps(__spreadValues({}, target), { path: path22 });
|
|
3162
|
+
});
|
|
3163
|
+
const batchResult = applyResolvedBatchUpdate(
|
|
3164
|
+
__spreadProps(__spreadValues({}, resolved), { targets }),
|
|
3165
|
+
applyBatchField
|
|
3166
|
+
);
|
|
3167
|
+
result.applied += batchResult.applied;
|
|
3168
|
+
result.skipped += batchResult.skipped;
|
|
3169
|
+
result.errors.push(...batchResult.errors);
|
|
3170
|
+
if (batchResult.applied > 0) {
|
|
3171
|
+
const fallbackTarget = resolved.call.selector.root || {
|
|
3172
|
+
type: resolved.call.selector.types[0]
|
|
3173
|
+
};
|
|
3174
|
+
(_c = result.changes) == null ? void 0 : _c.push({
|
|
3175
|
+
id: `batch:${index2}`,
|
|
3176
|
+
label: resolved.call.selector.types.join(", "),
|
|
3177
|
+
description: describeAppliedChange(call),
|
|
3178
|
+
target: fallbackTarget
|
|
3179
|
+
});
|
|
3180
|
+
}
|
|
3181
|
+
return;
|
|
3182
|
+
}
|
|
3183
|
+
const path2 = (_d = targetRefs.get(index2)) == null ? void 0 : _d.current;
|
|
3184
|
+
if (!path2)
|
|
3185
|
+
throw new Error(t("target no longer exists"));
|
|
3186
|
+
const node = Node.get(editor, path2);
|
|
3187
|
+
if (!NodeUtils.isElement(node)) {
|
|
3188
|
+
throw new Error(t("target is no longer an element"));
|
|
3189
|
+
}
|
|
3190
|
+
const element = node;
|
|
2601
3191
|
const [blockElement, blockPath] = closestBlockEntry(
|
|
2602
3192
|
editor,
|
|
2603
3193
|
path2
|
|
2604
3194
|
) || [element, path2];
|
|
2605
|
-
const
|
|
2606
|
-
|
|
2607
|
-
return;
|
|
2608
|
-
(_b = result.changes) == null ? void 0 : _b.push({
|
|
2609
|
-
id: key2,
|
|
3195
|
+
const appliedChange = {
|
|
3196
|
+
id: changeKey(blockPath, describeAppliedChange(call)),
|
|
2610
3197
|
label: elementLabel(blockElement),
|
|
2611
3198
|
description: describeAppliedChange(call),
|
|
2612
3199
|
target: targetFromElement(blockElement, call.target),
|
|
2613
3200
|
path: [...blockPath]
|
|
2614
|
-
}
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
3201
|
+
};
|
|
3202
|
+
const recordChange = () => {
|
|
3203
|
+
var _a2, _b2;
|
|
3204
|
+
if ((_a2 = result.changes) == null ? void 0 : _a2.some((change) => change.id === appliedChange.id)) {
|
|
3205
|
+
return;
|
|
3206
|
+
}
|
|
3207
|
+
(_b2 = result.changes) == null ? void 0 : _b2.push(appliedChange);
|
|
3208
|
+
};
|
|
3209
|
+
if (call.name === "update_text") {
|
|
3210
|
+
if (!canReplaceWithPlainText(element)) {
|
|
3211
|
+
throw new Error(
|
|
3212
|
+
hasAnyTextNode(element) ? t(
|
|
3213
|
+
"target contains mixed content; use a more specific text node"
|
|
3214
|
+
) : t("target has no editable text")
|
|
3215
|
+
);
|
|
3216
|
+
}
|
|
3217
|
+
setFieldValueTransactional(
|
|
3218
|
+
path2,
|
|
3219
|
+
"children",
|
|
3220
|
+
textToChildren(call.text)
|
|
2622
3221
|
);
|
|
3222
|
+
result.applied += 1;
|
|
3223
|
+
recordChange();
|
|
3224
|
+
return;
|
|
2623
3225
|
}
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
3226
|
+
if (call.name === "update_attribute") {
|
|
3227
|
+
if (!isSafeFieldKey(call.key))
|
|
3228
|
+
throw new Error(t("invalid attribute key"));
|
|
3229
|
+
if (call.key.startsWith("mobileAttributes.")) {
|
|
3230
|
+
const mobileKey = normalizeMobileAttributeKey(call.key);
|
|
3231
|
+
setFieldValueTransactional(
|
|
3232
|
+
path2,
|
|
3233
|
+
`mobileAttributes.${mobileKey}`,
|
|
3234
|
+
call.value === null ? void 0 : call.value
|
|
3235
|
+
);
|
|
3236
|
+
result.applied += 1;
|
|
3237
|
+
recordChange();
|
|
3238
|
+
return;
|
|
3239
|
+
}
|
|
3240
|
+
const attributeKey = normalizeAttributeKey(call.key);
|
|
3241
|
+
setFieldValueTransactional(
|
|
3242
|
+
path2,
|
|
3243
|
+
`attributes.${attributeKey}`,
|
|
3244
|
+
call.value === null ? void 0 : call.value
|
|
3245
|
+
);
|
|
3246
|
+
result.applied += 1;
|
|
3247
|
+
recordChange();
|
|
3248
|
+
return;
|
|
3249
|
+
}
|
|
3250
|
+
if (call.name === "update_mobile_attribute") {
|
|
3251
|
+
if (!isSafeFieldKey(call.key))
|
|
3252
|
+
throw new Error(t("invalid mobile attribute key"));
|
|
2633
3253
|
const mobileKey = normalizeMobileAttributeKey(call.key);
|
|
2634
|
-
|
|
3254
|
+
setFieldValueTransactional(
|
|
2635
3255
|
path2,
|
|
2636
3256
|
`mobileAttributes.${mobileKey}`,
|
|
2637
3257
|
call.value === null ? void 0 : call.value
|
|
@@ -2640,164 +3260,182 @@ function useApplyAiToolCalls() {
|
|
|
2640
3260
|
recordChange();
|
|
2641
3261
|
return;
|
|
2642
3262
|
}
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
call.value
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
result.applied += 1;
|
|
2663
|
-
recordChange();
|
|
2664
|
-
return;
|
|
2665
|
-
}
|
|
2666
|
-
if (call.name === "update_attributes") {
|
|
2667
|
-
if (!isObject$b(call.attributes)) {
|
|
2668
|
-
throw new Error(t("attributes must be an object"));
|
|
3263
|
+
if (call.name === "update_attributes") {
|
|
3264
|
+
if (!isObject$b(call.attributes)) {
|
|
3265
|
+
throw new Error(t("attributes must be an object"));
|
|
3266
|
+
}
|
|
3267
|
+
Object.entries(call.attributes).forEach(([key2, value]) => {
|
|
3268
|
+
if (!isSafeFieldKey(key2)) {
|
|
3269
|
+
throw new Error(`${t("invalid attribute key")}: ${key2}`);
|
|
3270
|
+
}
|
|
3271
|
+
const fieldRoot = call.scope === "mobile" || key2.startsWith("mobileAttributes.") ? "mobileAttributes" : "attributes";
|
|
3272
|
+
const normalizedKey = fieldRoot === "mobileAttributes" ? normalizeMobileAttributeKey(key2) : normalizeAttributeKey(key2);
|
|
3273
|
+
setFieldValueTransactional(
|
|
3274
|
+
path2,
|
|
3275
|
+
`${fieldRoot}.${normalizedKey}`,
|
|
3276
|
+
value === null ? void 0 : value
|
|
3277
|
+
);
|
|
3278
|
+
});
|
|
3279
|
+
result.applied += 1;
|
|
3280
|
+
recordChange();
|
|
3281
|
+
return;
|
|
2669
3282
|
}
|
|
2670
|
-
|
|
2671
|
-
if (!isSafeFieldKey(
|
|
2672
|
-
throw new Error(
|
|
3283
|
+
if (call.name === "update_data") {
|
|
3284
|
+
if (!isSafeFieldKey(call.key))
|
|
3285
|
+
throw new Error(t("invalid data key"));
|
|
3286
|
+
setFieldValueTransactional(
|
|
3287
|
+
path2,
|
|
3288
|
+
`data.${call.key}`,
|
|
3289
|
+
call.value === null ? void 0 : call.value
|
|
3290
|
+
);
|
|
3291
|
+
result.applied += 1;
|
|
3292
|
+
recordChange();
|
|
3293
|
+
return;
|
|
3294
|
+
}
|
|
3295
|
+
if (call.name === "replace_children") {
|
|
3296
|
+
const total = countNodes(call.children);
|
|
3297
|
+
if (total > MAX_REPLACE_CHILDREN_NODES) {
|
|
3298
|
+
throw new Error(
|
|
3299
|
+
`${t("replace_children is too large")} (${total} ${t("nodes")})`
|
|
3300
|
+
);
|
|
2673
3301
|
}
|
|
2674
|
-
|
|
2675
|
-
const normalizedKey = fieldRoot === "mobileAttributes" ? normalizeMobileAttributeKey(key2) : normalizeAttributeKey(key2);
|
|
2676
|
-
setFieldValue(
|
|
3302
|
+
setFieldValueTransactional(
|
|
2677
3303
|
path2,
|
|
2678
|
-
|
|
2679
|
-
|
|
3304
|
+
"children",
|
|
3305
|
+
normalizeChildren(call.children)
|
|
2680
3306
|
);
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
path2,
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
3307
|
+
result.applied += 1;
|
|
3308
|
+
recordChange();
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3311
|
+
if (call.name === "set_visibility") {
|
|
3312
|
+
if (call.desktop === false && call.mobile === false) {
|
|
3313
|
+
throw new Error(t("at least one device must remain visible"));
|
|
3314
|
+
}
|
|
3315
|
+
const visible = call.desktop === true && call.mobile === false ? "desktop" : call.desktop === false && call.mobile === true ? "mobile" : void 0;
|
|
3316
|
+
setFieldValueTransactional(path2, "visible", visible);
|
|
3317
|
+
result.applied += 1;
|
|
3318
|
+
recordChange();
|
|
3319
|
+
return;
|
|
3320
|
+
}
|
|
3321
|
+
if (call.name === "update_link") {
|
|
3322
|
+
if (typeof call.href !== "string")
|
|
3323
|
+
throw new Error(t("href is required"));
|
|
3324
|
+
setFieldValueTransactional(path2, "attributes.href", call.href);
|
|
3325
|
+
if (typeof call.blank === "boolean") {
|
|
3326
|
+
setFieldValueTransactional(
|
|
3327
|
+
path2,
|
|
3328
|
+
"attributes.target",
|
|
3329
|
+
call.blank ? "_blank" : "_self"
|
|
3330
|
+
);
|
|
3331
|
+
}
|
|
3332
|
+
if (typeof call.title === "string") {
|
|
3333
|
+
setFieldValueTransactional(
|
|
3334
|
+
path2,
|
|
3335
|
+
"attributes.title",
|
|
3336
|
+
call.title
|
|
3337
|
+
);
|
|
3338
|
+
}
|
|
3339
|
+
result.applied += 1;
|
|
3340
|
+
recordChange();
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
if (call.name === "select_node") {
|
|
3344
|
+
setSelectedNodePath(path2);
|
|
3345
|
+
result.applied += 1;
|
|
3346
|
+
recordChange();
|
|
3347
|
+
return;
|
|
3348
|
+
}
|
|
3349
|
+
if (isProtectedForStructureEdit(element)) {
|
|
2701
3350
|
throw new Error(
|
|
2702
|
-
|
|
3351
|
+
t("protected node cannot be structurally edited")
|
|
2703
3352
|
);
|
|
2704
3353
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
throw new Error(t("at least one device must remain visible"));
|
|
3354
|
+
if (call.name === "replace_block") {
|
|
3355
|
+
const replacement = normalizeElementBlock(call.block);
|
|
3356
|
+
Transforms.removeNodes(editor, { at: path2 });
|
|
3357
|
+
Transforms.insertNodes(editor, replacement, { at: path2 });
|
|
3358
|
+
result.applied += 1;
|
|
3359
|
+
recordChange();
|
|
3360
|
+
return;
|
|
2713
3361
|
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
3362
|
+
if (call.name === "move_up") {
|
|
3363
|
+
const previous = Path.previous(path2);
|
|
3364
|
+
Node.get(editor, previous);
|
|
3365
|
+
Transforms.moveNodes(editor, { at: path2, to: previous });
|
|
3366
|
+
setSelectedNodePath(previous);
|
|
3367
|
+
result.applied += 1;
|
|
3368
|
+
recordChange();
|
|
3369
|
+
return;
|
|
3370
|
+
}
|
|
3371
|
+
if (call.name === "move_down") {
|
|
3372
|
+
const next = Path.next(path2);
|
|
3373
|
+
Node.get(editor, next);
|
|
3374
|
+
Transforms.moveNodes(editor, { at: path2, to: next });
|
|
3375
|
+
setSelectedNodePath(next);
|
|
3376
|
+
result.applied += 1;
|
|
3377
|
+
recordChange();
|
|
3378
|
+
return;
|
|
3379
|
+
}
|
|
3380
|
+
if (call.name === "duplicate") {
|
|
3381
|
+
const next = Path.next(path2);
|
|
3382
|
+
Transforms.insertNodes(
|
|
3383
|
+
editor,
|
|
3384
|
+
assignIdsToElementTree(element, true),
|
|
3385
|
+
{ at: next }
|
|
2729
3386
|
);
|
|
3387
|
+
setSelectedNodePath(next);
|
|
3388
|
+
result.applied += 1;
|
|
3389
|
+
recordChange();
|
|
3390
|
+
return;
|
|
2730
3391
|
}
|
|
2731
|
-
if (
|
|
2732
|
-
|
|
3392
|
+
if (call.name === "delete_node") {
|
|
3393
|
+
editor.removeNode({ path: path2 });
|
|
3394
|
+
setSelectedNodePath(null);
|
|
3395
|
+
setHoverNodePath(null);
|
|
3396
|
+
result.applied += 1;
|
|
3397
|
+
recordChange();
|
|
3398
|
+
return;
|
|
2733
3399
|
}
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
return;
|
|
2760
|
-
}
|
|
2761
|
-
if (call.name === "move_down") {
|
|
2762
|
-
moveDown(path2);
|
|
2763
|
-
result.applied += 1;
|
|
2764
|
-
recordChange();
|
|
2765
|
-
return;
|
|
2766
|
-
}
|
|
2767
|
-
if (call.name === "duplicate") {
|
|
2768
|
-
copyBlock(path2);
|
|
2769
|
-
result.applied += 1;
|
|
2770
|
-
recordChange();
|
|
2771
|
-
return;
|
|
2772
|
-
}
|
|
2773
|
-
if (call.name === "delete_node") {
|
|
2774
|
-
deleteBlock(path2);
|
|
2775
|
-
result.applied += 1;
|
|
2776
|
-
recordChange();
|
|
2777
|
-
return;
|
|
2778
|
-
}
|
|
2779
|
-
if (call.name === "add_block_after") {
|
|
2780
|
-
addBlock(normalizeBlock(call.block), path2, true);
|
|
2781
|
-
result.applied += 1;
|
|
2782
|
-
recordChange();
|
|
2783
|
-
return;
|
|
2784
|
-
}
|
|
2785
|
-
if (call.name === "add_block_before") {
|
|
2786
|
-
addBlock(normalizeBlock(call.block), path2, false);
|
|
2787
|
-
result.applied += 1;
|
|
2788
|
-
recordChange();
|
|
2789
|
-
return;
|
|
2790
|
-
}
|
|
2791
|
-
result.skipped += 1;
|
|
2792
|
-
result.errors.push(`${call.name}: ${t("unsupported tool")}`);
|
|
2793
|
-
} catch (error2) {
|
|
2794
|
-
result.skipped += 1;
|
|
2795
|
-
result.errors.push(
|
|
2796
|
-
`${index2 + 1}. ${call.name}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
2797
|
-
);
|
|
3400
|
+
if (call.name === "add_block_after") {
|
|
3401
|
+
const next = Path.next(path2);
|
|
3402
|
+
Transforms.insertNodes(editor, createBlockForInsert(call.block), {
|
|
3403
|
+
at: next
|
|
3404
|
+
});
|
|
3405
|
+
setSelectedNodePath(next);
|
|
3406
|
+
result.applied += 1;
|
|
3407
|
+
recordChange();
|
|
3408
|
+
return;
|
|
3409
|
+
}
|
|
3410
|
+
if (call.name === "add_block_before") {
|
|
3411
|
+
Transforms.insertNodes(editor, createBlockForInsert(call.block), {
|
|
3412
|
+
at: path2
|
|
3413
|
+
});
|
|
3414
|
+
setSelectedNodePath(path2);
|
|
3415
|
+
result.applied += 1;
|
|
3416
|
+
recordChange();
|
|
3417
|
+
return;
|
|
3418
|
+
}
|
|
3419
|
+
result.skipped += 1;
|
|
3420
|
+
result.errors.push(`${call.name}: ${t("unsupported tool")}`);
|
|
3421
|
+
});
|
|
3422
|
+
},
|
|
3423
|
+
{
|
|
3424
|
+
getExternalChange: () => subjectBefore === subjectAfter ? null : { before: subjectBefore, after: subjectAfter }
|
|
2798
3425
|
}
|
|
2799
|
-
|
|
2800
|
-
})
|
|
3426
|
+
);
|
|
3427
|
+
} catch (error2) {
|
|
3428
|
+
syncValues(originalValues);
|
|
3429
|
+
return {
|
|
3430
|
+
applied: 0,
|
|
3431
|
+
skipped: calls.length,
|
|
3432
|
+
errors: [error2 instanceof Error ? error2.message : String(error2)],
|
|
3433
|
+
changes: []
|
|
3434
|
+
};
|
|
3435
|
+
} finally {
|
|
3436
|
+
targetRefs.forEach((ref) => ref.unref());
|
|
3437
|
+
batchRefs.forEach((refs) => refs.forEach((ref) => ref.unref()));
|
|
3438
|
+
}
|
|
2801
3439
|
return result;
|
|
2802
3440
|
});
|
|
2803
3441
|
}
|
|
@@ -16236,6 +16874,54 @@ const HoveringToolbar = () => {
|
|
|
16236
16874
|
editorContainer || document.body
|
|
16237
16875
|
);
|
|
16238
16876
|
};
|
|
16877
|
+
const RichTextBarContext = React__default.createContext({
|
|
16878
|
+
activePopup: null,
|
|
16879
|
+
setPopupVisible: () => void 0,
|
|
16880
|
+
closePopup: () => void 0
|
|
16881
|
+
});
|
|
16882
|
+
const getNextActivePopup = (activePopup, popupId, visible) => {
|
|
16883
|
+
if (visible)
|
|
16884
|
+
return popupId;
|
|
16885
|
+
return activePopup === popupId ? null : activePopup;
|
|
16886
|
+
};
|
|
16887
|
+
const useRichTextBarPopup = (popupId) => {
|
|
16888
|
+
const { activePopup, setPopupVisible } = useContext(RichTextBarContext);
|
|
16889
|
+
return {
|
|
16890
|
+
popupVisible: activePopup === popupId,
|
|
16891
|
+
onVisibleChange: useCallback(
|
|
16892
|
+
(visible) => setPopupVisible(popupId, visible),
|
|
16893
|
+
[popupId, setPopupVisible]
|
|
16894
|
+
)
|
|
16895
|
+
};
|
|
16896
|
+
};
|
|
16897
|
+
const useRichTextBarPopupCoordinator = () => {
|
|
16898
|
+
const [activePopup, setActivePopup] = useState(
|
|
16899
|
+
null
|
|
16900
|
+
);
|
|
16901
|
+
const setPopupVisible = useCallback(
|
|
16902
|
+
(popupId, visible) => {
|
|
16903
|
+
setActivePopup(
|
|
16904
|
+
(current) => getNextActivePopup(current, popupId, visible)
|
|
16905
|
+
);
|
|
16906
|
+
},
|
|
16907
|
+
[]
|
|
16908
|
+
);
|
|
16909
|
+
const closePopup = useCallback(() => setActivePopup(null), []);
|
|
16910
|
+
return useMemo(
|
|
16911
|
+
() => ({ activePopup, setPopupVisible, closePopup }),
|
|
16912
|
+
[activePopup, closePopup, setPopupVisible]
|
|
16913
|
+
);
|
|
16914
|
+
};
|
|
16915
|
+
const useRichTextBarActionBoundary = (closePopup) => useCallback(
|
|
16916
|
+
(event) => {
|
|
16917
|
+
var _a;
|
|
16918
|
+
const target = event.target;
|
|
16919
|
+
if ((_a = target == null ? void 0 : target.closest) == null ? void 0 : _a.call(target, ".arco-trigger"))
|
|
16920
|
+
return;
|
|
16921
|
+
closePopup();
|
|
16922
|
+
},
|
|
16923
|
+
[closePopup]
|
|
16924
|
+
);
|
|
16239
16925
|
var colorString$1 = { exports: {} };
|
|
16240
16926
|
var colorName = {
|
|
16241
16927
|
"aliceblue": [240, 248, 255],
|
|
@@ -18230,7 +18916,7 @@ const BgColorInner = () => {
|
|
|
18230
18916
|
const { getPopupContainer } = useContext(RichTextBarContext);
|
|
18231
18917
|
const { list: colors, addCurrentColor } = useColorContext();
|
|
18232
18918
|
const { useNewColorPicker = true } = useEditorProps();
|
|
18233
|
-
const
|
|
18919
|
+
const { popupVisible, onVisibleChange: setToolbarPopupVisible } = useRichTextBarPopup("background-color");
|
|
18234
18920
|
let isSelectionCollapsed = true;
|
|
18235
18921
|
if (editor.selection) {
|
|
18236
18922
|
try {
|
|
@@ -18355,7 +19041,7 @@ const BgColorInner = () => {
|
|
|
18355
19041
|
if (!visible) {
|
|
18356
19042
|
debouncedApplyChange.flush();
|
|
18357
19043
|
}
|
|
18358
|
-
|
|
19044
|
+
setToolbarPopupVisible(visible);
|
|
18359
19045
|
});
|
|
18360
19046
|
useEffect(() => {
|
|
18361
19047
|
if (isSelectionCollapsed) {
|
|
@@ -18447,6 +19133,8 @@ const BgColorInner = () => {
|
|
|
18447
19133
|
Popover,
|
|
18448
19134
|
{
|
|
18449
19135
|
trigger: "click",
|
|
19136
|
+
popupVisible,
|
|
19137
|
+
onVisibleChange,
|
|
18450
19138
|
triggerProps: {
|
|
18451
19139
|
popupStyle: { padding: "10px" }
|
|
18452
19140
|
},
|
|
@@ -18500,7 +19188,18 @@ const BgColorInner = () => {
|
|
|
18500
19188
|
triggerElement
|
|
18501
19189
|
}
|
|
18502
19190
|
));
|
|
18503
|
-
}, [
|
|
19191
|
+
}, [
|
|
19192
|
+
colors,
|
|
19193
|
+
getPopupContainer,
|
|
19194
|
+
normalizedColor,
|
|
19195
|
+
onChange,
|
|
19196
|
+
onClose,
|
|
19197
|
+
onLegacyChange,
|
|
19198
|
+
onVisibleChange,
|
|
19199
|
+
pickerValue,
|
|
19200
|
+
popupVisible,
|
|
19201
|
+
useNewColorPicker
|
|
19202
|
+
]);
|
|
18504
19203
|
};
|
|
18505
19204
|
const BgColor = () => {
|
|
18506
19205
|
return /* @__PURE__ */ React__default.createElement(ColorProvider, null, /* @__PURE__ */ React__default.createElement(BgColorInner, null));
|
|
@@ -18523,7 +19222,7 @@ const FontColorInner = () => {
|
|
|
18523
19222
|
const { addCurrentColor, list: colors } = useColorContext();
|
|
18524
19223
|
const { useNewColorPicker = true } = useEditorProps();
|
|
18525
19224
|
const editor = useSlate();
|
|
18526
|
-
const
|
|
19225
|
+
const { popupVisible, onVisibleChange: setToolbarPopupVisible } = useRichTextBarPopup("font-color");
|
|
18527
19226
|
let isSelectionCollapsed = true;
|
|
18528
19227
|
if (editor.selection) {
|
|
18529
19228
|
try {
|
|
@@ -18644,7 +19343,7 @@ const FontColorInner = () => {
|
|
|
18644
19343
|
if (!visible) {
|
|
18645
19344
|
debouncedApplyChange.flush();
|
|
18646
19345
|
}
|
|
18647
|
-
|
|
19346
|
+
setToolbarPopupVisible(visible);
|
|
18648
19347
|
});
|
|
18649
19348
|
useEffect(() => {
|
|
18650
19349
|
if (isSelectionCollapsed) {
|
|
@@ -18694,35 +19393,45 @@ const FontColorInner = () => {
|
|
|
18694
19393
|
}
|
|
18695
19394
|
});
|
|
18696
19395
|
return useMemo(() => {
|
|
18697
|
-
const triggerElement = /* @__PURE__ */ React__default.createElement(
|
|
19396
|
+
const triggerElement = /* @__PURE__ */ React__default.createElement(
|
|
18698
19397
|
"span",
|
|
18699
19398
|
{
|
|
18700
|
-
|
|
18701
|
-
|
|
18702
|
-
|
|
18703
|
-
alignItems: "center",
|
|
18704
|
-
justifyContent: "center",
|
|
18705
|
-
height: "calc(var(--hovering-bar-icon-size) + 4px)",
|
|
18706
|
-
textAlign: "center",
|
|
18707
|
-
fontSize: "calc(var(--hovering-bar-icon-size) + 2px)",
|
|
18708
|
-
borderRadius: "2px",
|
|
18709
|
-
width: "calc(var(--hovering-bar-icon-size) + 4px)",
|
|
18710
|
-
boxSizing: "border-box",
|
|
18711
|
-
fontWeight: "500",
|
|
18712
|
-
color: pickerValue.toLocaleLowerCase() === "#ffffff" ? void 0 : pickerValue,
|
|
18713
|
-
borderColor: pickerValue.toLocaleLowerCase() === "#ffffff" ? void 0 : pickerValue,
|
|
18714
|
-
borderWidth: "1px",
|
|
18715
|
-
borderStyle: "solid",
|
|
18716
|
-
overflow: "hidden"
|
|
18717
|
-
}
|
|
19399
|
+
ref,
|
|
19400
|
+
className: classnames$1("formatButton"),
|
|
19401
|
+
title: t("Font color")
|
|
18718
19402
|
},
|
|
18719
|
-
|
|
18720
|
-
|
|
19403
|
+
/* @__PURE__ */ React__default.createElement(
|
|
19404
|
+
"span",
|
|
19405
|
+
{
|
|
19406
|
+
className: classnames$1("iconfont"),
|
|
19407
|
+
style: {
|
|
19408
|
+
display: "flex",
|
|
19409
|
+
alignItems: "center",
|
|
19410
|
+
justifyContent: "center",
|
|
19411
|
+
height: "calc(var(--hovering-bar-icon-size) + 4px)",
|
|
19412
|
+
textAlign: "center",
|
|
19413
|
+
fontSize: "calc(var(--hovering-bar-icon-size) + 2px)",
|
|
19414
|
+
borderRadius: "2px",
|
|
19415
|
+
width: "calc(var(--hovering-bar-icon-size) + 4px)",
|
|
19416
|
+
boxSizing: "border-box",
|
|
19417
|
+
fontWeight: "500",
|
|
19418
|
+
color: pickerValue.toLocaleLowerCase() === "#ffffff" ? void 0 : pickerValue,
|
|
19419
|
+
borderColor: pickerValue.toLocaleLowerCase() === "#ffffff" ? void 0 : pickerValue,
|
|
19420
|
+
borderWidth: "1px",
|
|
19421
|
+
borderStyle: "solid",
|
|
19422
|
+
overflow: "hidden"
|
|
19423
|
+
}
|
|
19424
|
+
},
|
|
19425
|
+
"A"
|
|
19426
|
+
)
|
|
19427
|
+
);
|
|
18721
19428
|
if (!useNewColorPicker) {
|
|
18722
19429
|
return /* @__PURE__ */ React__default.createElement(
|
|
18723
19430
|
Popover,
|
|
18724
19431
|
{
|
|
18725
19432
|
trigger: "click",
|
|
19433
|
+
popupVisible,
|
|
19434
|
+
onVisibleChange,
|
|
18726
19435
|
triggerProps: {
|
|
18727
19436
|
popupStyle: { padding: "10px" }
|
|
18728
19437
|
},
|
|
@@ -18776,7 +19485,18 @@ const FontColorInner = () => {
|
|
|
18776
19485
|
triggerElement
|
|
18777
19486
|
}
|
|
18778
19487
|
));
|
|
18779
|
-
}, [
|
|
19488
|
+
}, [
|
|
19489
|
+
colors,
|
|
19490
|
+
getPopupContainer,
|
|
19491
|
+
normalizedColor,
|
|
19492
|
+
onChange,
|
|
19493
|
+
onClose,
|
|
19494
|
+
onLegacyChange,
|
|
19495
|
+
onVisibleChange,
|
|
19496
|
+
pickerValue,
|
|
19497
|
+
popupVisible,
|
|
19498
|
+
useNewColorPicker
|
|
19499
|
+
]);
|
|
18780
19500
|
};
|
|
18781
19501
|
const FontColor = () => {
|
|
18782
19502
|
return /* @__PURE__ */ React__default.createElement(ColorProvider, null, /* @__PURE__ */ React__default.createElement(FontColorInner, null));
|
|
@@ -19178,8 +19898,9 @@ const TextLink = () => {
|
|
|
19178
19898
|
const { getPopupContainer } = useContext(RichTextBarContext);
|
|
19179
19899
|
const ref = useRef(null);
|
|
19180
19900
|
const linkNode = linkNodeEntry == null ? void 0 : linkNodeEntry[0];
|
|
19901
|
+
const { popupVisible, onVisibleChange } = useRichTextBarPopup("link");
|
|
19181
19902
|
const selectedNodePath = useSelectedNodePath();
|
|
19182
|
-
const [
|
|
19903
|
+
const [mergeTagPopupVisible, setMergeTagPopupVisible] = useState(false);
|
|
19183
19904
|
const { handleUploadClick, showSelectFileButton, onUpload, mergetags } = useEditorProps();
|
|
19184
19905
|
const [isUploading, setIsUploading] = useState(false);
|
|
19185
19906
|
const uploadHandlerRef = useRef(onUpload);
|
|
@@ -19192,7 +19913,7 @@ const TextLink = () => {
|
|
|
19192
19913
|
const newHref = PluginManager.generateVariable(mergetag);
|
|
19193
19914
|
from.setFieldValue("href", newHref);
|
|
19194
19915
|
setFormState((old) => __spreadProps(__spreadValues({}, old), { href: newHref }));
|
|
19195
|
-
|
|
19916
|
+
setMergeTagPopupVisible(false);
|
|
19196
19917
|
},
|
|
19197
19918
|
[from]
|
|
19198
19919
|
);
|
|
@@ -19287,6 +20008,8 @@ const TextLink = () => {
|
|
|
19287
20008
|
Popover,
|
|
19288
20009
|
{
|
|
19289
20010
|
trigger: "click",
|
|
20011
|
+
popupVisible,
|
|
20012
|
+
onVisibleChange,
|
|
19290
20013
|
triggerProps: {
|
|
19291
20014
|
position: "tr",
|
|
19292
20015
|
popupStyle: { padding: "10px 0px 0px 0px", width: 400 }
|
|
@@ -19333,10 +20056,10 @@ const TextLink = () => {
|
|
|
19333
20056
|
SharedComponents.MergeTagComponent,
|
|
19334
20057
|
{
|
|
19335
20058
|
mergetags: formatMergetags,
|
|
19336
|
-
popupVisible,
|
|
19337
|
-
onVisibleChange:
|
|
20059
|
+
popupVisible: mergeTagPopupVisible,
|
|
20060
|
+
onVisibleChange: setMergeTagPopupVisible,
|
|
19338
20061
|
onChange: onChangeMergeTag,
|
|
19339
|
-
onClose: () =>
|
|
20062
|
+
onClose: () => setMergeTagPopupVisible(false),
|
|
19340
20063
|
value: "",
|
|
19341
20064
|
triggerElement: /* @__PURE__ */ React__default.createElement(
|
|
19342
20065
|
Button$2,
|
|
@@ -19474,6 +20197,7 @@ const options$9 = [
|
|
|
19474
20197
|
];
|
|
19475
20198
|
const TurnInto = () => {
|
|
19476
20199
|
const editor = useSlate();
|
|
20200
|
+
const { popupVisible, onVisibleChange } = useRichTextBarPopup("turn-into");
|
|
19477
20201
|
let nodeEntry = null;
|
|
19478
20202
|
try {
|
|
19479
20203
|
if (editor.selection && Node.has(editor, editor.selection.anchor.path)) {
|
|
@@ -19510,6 +20234,8 @@ const TurnInto = () => {
|
|
|
19510
20234
|
Select$1,
|
|
19511
20235
|
{
|
|
19512
20236
|
value: node.type,
|
|
20237
|
+
popupVisible,
|
|
20238
|
+
onVisibleChange,
|
|
19513
20239
|
className: "easy-email-pro-turnInto",
|
|
19514
20240
|
style: { minWidth: 95 },
|
|
19515
20241
|
onChange,
|
|
@@ -19529,7 +20255,7 @@ const TurnInto = () => {
|
|
|
19529
20255
|
};
|
|
19530
20256
|
const RichTextBar$1 = "";
|
|
19531
20257
|
const MergeTag = React__default.memo(() => {
|
|
19532
|
-
const
|
|
20258
|
+
const { popupVisible, onVisibleChange } = useRichTextBarPopup("merge-tag");
|
|
19533
20259
|
const [mergeTagRef, setMergeTagRef] = useState(null);
|
|
19534
20260
|
const editor = useSlate();
|
|
19535
20261
|
const { mergetags } = useEditorProps();
|
|
@@ -19541,19 +20267,19 @@ const MergeTag = React__default.memo(() => {
|
|
|
19541
20267
|
editor.insertMergetag({
|
|
19542
20268
|
mergetag
|
|
19543
20269
|
});
|
|
19544
|
-
|
|
20270
|
+
onVisibleChange(false);
|
|
19545
20271
|
},
|
|
19546
|
-
[editor]
|
|
20272
|
+
[editor, onVisibleChange]
|
|
19547
20273
|
);
|
|
19548
20274
|
const onClose = useCallback(() => {
|
|
19549
|
-
|
|
19550
|
-
}, []);
|
|
20275
|
+
onVisibleChange(false);
|
|
20276
|
+
}, [onVisibleChange]);
|
|
19551
20277
|
return /* @__PURE__ */ React__default.createElement("div", { ref: setMergeTagRef }, /* @__PURE__ */ React__default.createElement(
|
|
19552
20278
|
SharedComponents.MergeTagComponent,
|
|
19553
20279
|
{
|
|
19554
20280
|
mergetags: formatMergetags,
|
|
19555
20281
|
popupVisible,
|
|
19556
|
-
onVisibleChange
|
|
20282
|
+
onVisibleChange,
|
|
19557
20283
|
onChange,
|
|
19558
20284
|
onClose,
|
|
19559
20285
|
value: "",
|
|
@@ -19563,7 +20289,7 @@ const MergeTag = React__default.memo(() => {
|
|
|
19563
20289
|
{
|
|
19564
20290
|
title: t("Merge Tag"),
|
|
19565
20291
|
icon: "icon-merge-tags",
|
|
19566
|
-
onClick: () =>
|
|
20292
|
+
onClick: () => onVisibleChange(false)
|
|
19567
20293
|
}
|
|
19568
20294
|
)
|
|
19569
20295
|
}
|
|
@@ -19720,6 +20446,7 @@ const TextAlign$1 = () => {
|
|
|
19720
20446
|
};
|
|
19721
20447
|
const options$8 = ["12px", "14px", "16px", "18px", "24px", "32px", "48px"];
|
|
19722
20448
|
const FontSize$2 = () => {
|
|
20449
|
+
const { popupVisible, onVisibleChange } = useRichTextBarPopup("font-size");
|
|
19723
20450
|
const [selectRef, setSelectRef] = useState(null);
|
|
19724
20451
|
const { fontSizeList } = useEditorProps();
|
|
19725
20452
|
const [fontSizeValue, setFontSizeValue] = useState();
|
|
@@ -19832,6 +20559,8 @@ const FontSize$2 = () => {
|
|
|
19832
20559
|
{
|
|
19833
20560
|
className: "easy-email-pro-font-size",
|
|
19834
20561
|
value: fontSizeValue,
|
|
20562
|
+
popupVisible,
|
|
20563
|
+
onVisibleChange,
|
|
19835
20564
|
style: { width: 80 },
|
|
19836
20565
|
onChange,
|
|
19837
20566
|
triggerProps: {
|
|
@@ -19849,6 +20578,7 @@ const FontSize$2 = () => {
|
|
|
19849
20578
|
`));
|
|
19850
20579
|
};
|
|
19851
20580
|
const FontFamily$2 = () => {
|
|
20581
|
+
const { popupVisible, onVisibleChange } = useRichTextBarPopup("font-family");
|
|
19852
20582
|
const { fontList, addFont } = useFontFamily();
|
|
19853
20583
|
const [selectRef, setSelectRef] = useState(null);
|
|
19854
20584
|
const editor = useSlate();
|
|
@@ -19951,6 +20681,8 @@ const FontFamily$2 = () => {
|
|
|
19951
20681
|
{
|
|
19952
20682
|
className: "easy-email-pro-font-family",
|
|
19953
20683
|
value: fontFamilyValue,
|
|
20684
|
+
popupVisible,
|
|
20685
|
+
onVisibleChange,
|
|
19954
20686
|
style: { minWidth: 80 },
|
|
19955
20687
|
onChange,
|
|
19956
20688
|
triggerProps: {
|
|
@@ -20063,6 +20795,7 @@ const Image$4 = () => {
|
|
|
20063
20795
|
const editor = useSlate();
|
|
20064
20796
|
const ref = useRef(null);
|
|
20065
20797
|
const { onUpload } = useEditorProps();
|
|
20798
|
+
const { popupVisible, onVisibleChange } = useRichTextBarPopup("image");
|
|
20066
20799
|
const { lock } = useEditorState();
|
|
20067
20800
|
const [from] = Form.useForm();
|
|
20068
20801
|
const onSubmit = (values) => {
|
|
@@ -20101,6 +20834,8 @@ const Image$4 = () => {
|
|
|
20101
20834
|
Popover,
|
|
20102
20835
|
{
|
|
20103
20836
|
trigger: "click",
|
|
20837
|
+
popupVisible,
|
|
20838
|
+
onVisibleChange,
|
|
20104
20839
|
triggerProps: {
|
|
20105
20840
|
position: "bl",
|
|
20106
20841
|
popupStyle: { padding: "0px" }
|
|
@@ -20201,15 +20936,16 @@ const Image$4 = () => {
|
|
|
20201
20936
|
/* @__PURE__ */ React__default.createElement("span", { ref, className: classnames$1("formatButton") }, /* @__PURE__ */ React__default.createElement("span", { className: classnames$1(" iconfont icon-img") }))
|
|
20202
20937
|
);
|
|
20203
20938
|
};
|
|
20204
|
-
const RichTextBarContext = React__default.createContext({});
|
|
20205
20939
|
const RichTextBar = ({
|
|
20206
20940
|
list,
|
|
20207
20941
|
wrap: wrap2,
|
|
20208
20942
|
getPopupContainer
|
|
20209
20943
|
}) => {
|
|
20944
|
+
const { activePopup, setPopupVisible, closePopup } = useRichTextBarPopupCoordinator();
|
|
20945
|
+
const onClickCapture = useRichTextBarActionBoundary(closePopup);
|
|
20210
20946
|
const contextValue = useMemo(
|
|
20211
|
-
() => ({ getPopupContainer }),
|
|
20212
|
-
[getPopupContainer]
|
|
20947
|
+
() => ({ getPopupContainer, activePopup, setPopupVisible, closePopup }),
|
|
20948
|
+
[activePopup, closePopup, getPopupContainer, setPopupVisible]
|
|
20213
20949
|
);
|
|
20214
20950
|
const { MergetagPopover: MergetagPopover2, mergetags, AIAssistant: AIAssistant2 } = useEditorProps();
|
|
20215
20951
|
const { selectedNode } = useSelectedNode();
|
|
@@ -20315,6 +21051,7 @@ const RichTextBar = ({
|
|
|
20315
21051
|
{
|
|
20316
21052
|
id: "RichTextBar",
|
|
20317
21053
|
className: "RichTextBar",
|
|
21054
|
+
onClickCapture,
|
|
20318
21055
|
style: {
|
|
20319
21056
|
display: "inline-flex",
|
|
20320
21057
|
alignItems: "center",
|
|
@@ -26220,14 +26957,14 @@ var getNative$1 = _getNative, root$2 = _root;
|
|
|
26220
26957
|
var Set$2 = getNative$1(root$2, "Set");
|
|
26221
26958
|
var _Set = Set$2;
|
|
26222
26959
|
var getNative = _getNative, root$1 = _root;
|
|
26223
|
-
var WeakMap$
|
|
26224
|
-
var _WeakMap = WeakMap$
|
|
26225
|
-
var DataView = _DataView, Map$1 = _Map, Promise$1 = _Promise, Set$1 = _Set, WeakMap = _WeakMap, baseGetTag$1 = _baseGetTag, toSource = _toSource;
|
|
26960
|
+
var WeakMap$2 = getNative(root$1, "WeakMap");
|
|
26961
|
+
var _WeakMap = WeakMap$2;
|
|
26962
|
+
var DataView = _DataView, Map$1 = _Map, Promise$1 = _Promise, Set$1 = _Set, WeakMap$1 = _WeakMap, baseGetTag$1 = _baseGetTag, toSource = _toSource;
|
|
26226
26963
|
var mapTag$3 = "[object Map]", objectTag$2 = "[object Object]", promiseTag = "[object Promise]", setTag$3 = "[object Set]", weakMapTag$1 = "[object WeakMap]";
|
|
26227
26964
|
var dataViewTag$2 = "[object DataView]";
|
|
26228
|
-
var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map$1), promiseCtorString = toSource(Promise$1), setCtorString = toSource(Set$1), weakMapCtorString = toSource(WeakMap);
|
|
26965
|
+
var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map$1), promiseCtorString = toSource(Promise$1), setCtorString = toSource(Set$1), weakMapCtorString = toSource(WeakMap$1);
|
|
26229
26966
|
var getTag$3 = baseGetTag$1;
|
|
26230
|
-
if (DataView && getTag$3(new DataView(new ArrayBuffer(1))) != dataViewTag$2 || Map$1 && getTag$3(new Map$1()) != mapTag$3 || Promise$1 && getTag$3(Promise$1.resolve()) != promiseTag || Set$1 && getTag$3(new Set$1()) != setTag$3 || WeakMap && getTag$3(new WeakMap()) != weakMapTag$1) {
|
|
26967
|
+
if (DataView && getTag$3(new DataView(new ArrayBuffer(1))) != dataViewTag$2 || Map$1 && getTag$3(new Map$1()) != mapTag$3 || Promise$1 && getTag$3(Promise$1.resolve()) != promiseTag || Set$1 && getTag$3(new Set$1()) != setTag$3 || WeakMap$1 && getTag$3(new WeakMap$1()) != weakMapTag$1) {
|
|
26231
26968
|
getTag$3 = function(value) {
|
|
26232
26969
|
var result = baseGetTag$1(value), Ctor = result == objectTag$2 ? value.constructor : void 0, ctorString = Ctor ? toSource(Ctor) : "";
|
|
26233
26970
|
if (ctorString) {
|
|
@@ -40280,6 +41017,7 @@ const AIPromptModal = (props) => {
|
|
|
40280
41017
|
};
|
|
40281
41018
|
const SvgMagic = (props) => /* @__PURE__ */ React$2.createElement("svg", __spreadValues({ className: "bi bi-magic", fill: "currentColor", height: 16, viewBox: "0 0 16 16", width: 16, xmlns: "http://www.w3.org/2000/svg" }, props), /* @__PURE__ */ React$2.createElement("path", { d: "M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0v1.829Zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707L14 2.707ZM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707L7.293 4Zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1h1.829Zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1h1.829ZM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707L13.293 10ZM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0v1.829Zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0L8.354 9.06Z" }));
|
|
40282
41019
|
function AIAssistant({ isCollapsed }) {
|
|
41020
|
+
const { popupVisible, onVisibleChange } = useRichTextBarPopup("ai-assistant");
|
|
40283
41021
|
const isEnabled = EditorAuth.getFeatureEnabled("AI_ASSISTANT");
|
|
40284
41022
|
if (!isEnabled) {
|
|
40285
41023
|
throw new Error(`Current plan do not support AIAssistant`);
|
|
@@ -40539,6 +41277,8 @@ function AIAssistant({ isCollapsed }) {
|
|
|
40539
41277
|
return /* @__PURE__ */ React__default.createElement("div", { ref: setRefElement, style: { display: "flex", alignItems: "center" } }, /* @__PURE__ */ React__default.createElement(
|
|
40540
41278
|
Select$1,
|
|
40541
41279
|
{
|
|
41280
|
+
popupVisible,
|
|
41281
|
+
onVisibleChange,
|
|
40542
41282
|
getPopupContainer: (node) => {
|
|
40543
41283
|
return Array.from(document.querySelectorAll(".RichTextBar")).find(
|
|
40544
41284
|
(item2) => item2.contains(node)
|
|
@@ -41921,6 +42661,15 @@ function EasyEmailProAiAgent({
|
|
|
41921
42661
|
"×"
|
|
41922
42662
|
), /* @__PURE__ */ React__default.createElement("img", { src: previewAttachment.url, alt: previewAttachment.name, onClick: (event) => event.stopPropagation() })) : null);
|
|
41923
42663
|
}
|
|
42664
|
+
function formatAiApplyResult(result, summary) {
|
|
42665
|
+
const lines = summary ? [summary] : [t("Updated the email preview.")];
|
|
42666
|
+
lines.push(
|
|
42667
|
+
result.skipped > 0 ? `${t("Updated")} ${result.applied} ${t("blocks")}; ${t("skipped")} ${result.skipped}.` : `${t("Updated")} ${result.applied} ${t("blocks")}.`
|
|
42668
|
+
);
|
|
42669
|
+
if (result.errors.length)
|
|
42670
|
+
lines.push(result.errors.join("\n"));
|
|
42671
|
+
return lines.join("\n\n");
|
|
42672
|
+
}
|
|
41924
42673
|
const doneStatuses = ["FINISHED", "ERROR"];
|
|
41925
42674
|
function getInitialConversation() {
|
|
41926
42675
|
return [
|
|
@@ -42234,18 +42983,13 @@ function useAiAgentSession(options2) {
|
|
|
42234
42983
|
((_a = result == null ? void 0 : result.errors) == null ? void 0 : _a.filter(Boolean)) || []
|
|
42235
42984
|
);
|
|
42236
42985
|
updateMessage(activeRun.assistantMessageId, {
|
|
42237
|
-
content:
|
|
42238
|
-
|
|
42239
|
-
${t(
|
|
42240
|
-
"Some operations were not applied"
|
|
42241
|
-
)}:
|
|
42242
|
-
${errors.join("\n")}` : toolCallsText(__spreadProps(__spreadValues({}, payload), { toolCalls }), result),
|
|
42986
|
+
content: result ? formatAiApplyResult(__spreadProps(__spreadValues({}, result), { errors }), payload.summary) : toolCallsText(__spreadProps(__spreadValues({}, payload), { toolCalls }), result),
|
|
42243
42987
|
status: "ready"
|
|
42244
42988
|
});
|
|
42245
42989
|
setActivity(
|
|
42246
42990
|
errors.length ? t("Some local changes were not applied") : t("Updated the email preview.")
|
|
42247
42991
|
);
|
|
42248
|
-
if (
|
|
42992
|
+
if (!result || result.applied > 0) {
|
|
42249
42993
|
scheduleAfterApplySnapshot(
|
|
42250
42994
|
activeRun.assistantMessageId,
|
|
42251
42995
|
payload.summary
|