@mjml-agent-editor/editor 0.1.4 → 0.1.6
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/README.md +25 -0
- package/dist/canvas.cjs +97 -19
- package/dist/canvas.cjs.map +1 -1
- package/dist/canvas.js +19 -15
- package/dist/canvas.js.map +1 -1
- package/dist/{chunk-YAKRVIM2.js → chunk-XAEUCHL4.js} +152 -58
- package/dist/chunk-XAEUCHL4.js.map +1 -0
- package/dist/index.cjs +152 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -2
- package/dist/index.d.ts +87 -2
- package/dist/index.js +9 -3
- package/package.json +2 -2
- package/dist/chunk-YAKRVIM2.js.map +0 -1
|
@@ -18,14 +18,88 @@ import {
|
|
|
18
18
|
} from "./chunk-V6RR4VRD.js";
|
|
19
19
|
|
|
20
20
|
// src/stores.tsx
|
|
21
|
-
import { createContext, useContext } from "react";
|
|
21
|
+
import { createContext, useContext, useMemo } from "react";
|
|
22
|
+
|
|
23
|
+
// src/labels.ts
|
|
24
|
+
var DEFAULT_LABELS = {
|
|
25
|
+
appName: "MJML Editor",
|
|
26
|
+
emailNameAria: "Email name",
|
|
27
|
+
renameFailed: "Failed to rename.",
|
|
28
|
+
saving: "Saving\u2026",
|
|
29
|
+
saved: "Saved",
|
|
30
|
+
saveFailed: "Save failed",
|
|
31
|
+
undo: "Undo",
|
|
32
|
+
redo: "Redo",
|
|
33
|
+
contentWidth: "Content width",
|
|
34
|
+
preview: "Preview",
|
|
35
|
+
closePreview: "Close preview",
|
|
36
|
+
previewFrameTitle: "Email preview",
|
|
37
|
+
sourceCode: "Source code",
|
|
38
|
+
exportHtml: "Export HTML",
|
|
39
|
+
exportMjml: "Export MJML",
|
|
40
|
+
copied: (kind) => `${kind} copied.`,
|
|
41
|
+
searchBlocks: "Search blocks\u2026",
|
|
42
|
+
expandAll: "Expand all",
|
|
43
|
+
selectAnElement: "Select an element\u2026",
|
|
44
|
+
attributes: "Attributes",
|
|
45
|
+
style: "Style",
|
|
46
|
+
rteFont: "Font",
|
|
47
|
+
rteSize: "Size",
|
|
48
|
+
rteTextColor: "Text color",
|
|
49
|
+
rteBackgroundColor: "Background color",
|
|
50
|
+
documentLoadFailed: "Failed to load the document.",
|
|
51
|
+
documentSaveFailed: "Failed to save changes.",
|
|
52
|
+
commentOnSection: "Comment on the whole section",
|
|
53
|
+
closeComments: "Close",
|
|
54
|
+
noCommentsYet: "No comments yet \u2014 add the first one.",
|
|
55
|
+
resolveComment: "Resolve",
|
|
56
|
+
addComment: "Add",
|
|
57
|
+
addCommentPlaceholder: "Add a comment\u2026 (\u2318/Ctrl+Enter to send)",
|
|
58
|
+
chatEmptyTitle: "Start a conversation with the agent",
|
|
59
|
+
chatEmptyDescription: "Describe the email (goal, tone, content) and paste your data \u2014 the agent will design the sections and images.",
|
|
60
|
+
agentWorking: "Agent is working\u2026",
|
|
61
|
+
reasoning: "Reasoning",
|
|
62
|
+
completedSteps: (count, failed) => failed > 0 ? `Completed steps (${count}, ${failed} failed)` : `Completed steps (${count})`,
|
|
63
|
+
applyComments: "Apply changes from comments",
|
|
64
|
+
chatPlaceholder: "Describe what you want to change\u2026 (Enter = send, Shift+Enter = new line)",
|
|
65
|
+
stop: "Stop",
|
|
66
|
+
send: "Send",
|
|
67
|
+
chatError: "Agent chat error.",
|
|
68
|
+
toolLabels: {
|
|
69
|
+
get_document: "Reading document",
|
|
70
|
+
get_section: "Reading section",
|
|
71
|
+
set_document: "Saving whole email",
|
|
72
|
+
set_section: "Replacing section",
|
|
73
|
+
insert_section: "Adding section",
|
|
74
|
+
remove_section: "Removing section",
|
|
75
|
+
generate_image: "Generating image",
|
|
76
|
+
list_open_comments: "Reading comments",
|
|
77
|
+
resolve_comment: "Resolving comment"
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
function mergeLabels(overrides) {
|
|
81
|
+
if (!overrides) return DEFAULT_LABELS;
|
|
82
|
+
return {
|
|
83
|
+
...DEFAULT_LABELS,
|
|
84
|
+
...overrides,
|
|
85
|
+
toolLabels: { ...DEFAULT_LABELS.toolLabels, ...overrides.toolLabels }
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/stores.tsx
|
|
22
90
|
import { jsx } from "react/jsx-runtime";
|
|
23
91
|
var StoreContext = createContext(null);
|
|
92
|
+
var LabelContext = createContext(null);
|
|
24
93
|
function EditorStoreProvider({
|
|
25
94
|
stores,
|
|
95
|
+
labels,
|
|
26
96
|
children
|
|
27
97
|
}) {
|
|
28
|
-
|
|
98
|
+
const merged = useMemo(() => mergeLabels(labels), [labels]);
|
|
99
|
+
return /* @__PURE__ */ jsx(StoreContext.Provider, { value: stores, children: /* @__PURE__ */ jsx(LabelContext.Provider, { value: merged, children }) });
|
|
100
|
+
}
|
|
101
|
+
function useLabels() {
|
|
102
|
+
return useContext(LabelContext) ?? mergeLabels();
|
|
29
103
|
}
|
|
30
104
|
function useStores() {
|
|
31
105
|
const stores = useContext(StoreContext);
|
|
@@ -349,29 +423,24 @@ function DialogTitle({ className, ...props }) {
|
|
|
349
423
|
|
|
350
424
|
// src/components/editor/EditorHeader.tsx
|
|
351
425
|
import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
352
|
-
var SAVE_LABEL = {
|
|
353
|
-
idle: "",
|
|
354
|
-
saving: "Saving\u2026",
|
|
355
|
-
saved: "Saved",
|
|
356
|
-
error: "Save failed"
|
|
357
|
-
};
|
|
358
426
|
var WIDTHS = ["600px", "640px", "680px", "720px"];
|
|
359
427
|
var DEVICE_ICON = {
|
|
360
428
|
Desktop: /* @__PURE__ */ jsx7(Monitor, { className: "size-3.5" }),
|
|
361
429
|
Mobile: /* @__PURE__ */ jsx7(Smartphone, { className: "size-3.5" })
|
|
362
430
|
};
|
|
363
431
|
function SaveBadge({ status }) {
|
|
432
|
+
const labels = useLabels();
|
|
364
433
|
if (status === "idle") return null;
|
|
365
434
|
if (status === "saving")
|
|
366
435
|
return /* @__PURE__ */ jsxs2("span", { className: "flex items-center gap-1 text-xs text-panel-muted-fg", children: [
|
|
367
436
|
/* @__PURE__ */ jsx7(Spinner, { className: "size-3" }),
|
|
368
437
|
" ",
|
|
369
|
-
|
|
438
|
+
labels.saving
|
|
370
439
|
] });
|
|
371
|
-
if (status === "error") return /* @__PURE__ */ jsx7(Badge, { variant: "destructive", children:
|
|
440
|
+
if (status === "error") return /* @__PURE__ */ jsx7(Badge, { variant: "destructive", children: labels.saveFailed });
|
|
372
441
|
return /* @__PURE__ */ jsxs2("span", { className: "text-xs text-emerald-400", children: [
|
|
373
442
|
"\u2713 ",
|
|
374
|
-
|
|
443
|
+
labels.saved
|
|
375
444
|
] });
|
|
376
445
|
}
|
|
377
446
|
function slugify(name) {
|
|
@@ -394,6 +463,7 @@ function EditorHeader({
|
|
|
394
463
|
homeLink
|
|
395
464
|
}) {
|
|
396
465
|
const documents = useDocumentStore();
|
|
466
|
+
const labels = useLabels();
|
|
397
467
|
const [name, setName] = useState("");
|
|
398
468
|
const [state, setState] = useState({
|
|
399
469
|
device: "Desktop",
|
|
@@ -419,7 +489,7 @@ function EditorHeader({
|
|
|
419
489
|
try {
|
|
420
490
|
await documents.save(docId, { name: n });
|
|
421
491
|
} catch {
|
|
422
|
-
toast.error(
|
|
492
|
+
toast.error(labels.renameFailed);
|
|
423
493
|
}
|
|
424
494
|
};
|
|
425
495
|
const devices = api?.getDevices() ?? [];
|
|
@@ -427,7 +497,7 @@ function EditorHeader({
|
|
|
427
497
|
const openCode = () => setCode({ mjml: api?.getMjml() ?? "", html: api?.getCompiledHtml() ?? "" });
|
|
428
498
|
return /* @__PURE__ */ jsxs2("header", { className: "flex h-14 shrink-0 items-center gap-2 border-b border-panel-border bg-panel px-3 text-panel-fg", children: [
|
|
429
499
|
/* @__PURE__ */ jsx7("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-brand to-indigo-400 text-brand-fg shadow-sm", children: /* @__PURE__ */ jsx7(Mail, { className: "size-4" }) }),
|
|
430
|
-
/* @__PURE__ */ jsx7("span", { className: "hidden text-sm font-semibold sm:inline", children:
|
|
500
|
+
/* @__PURE__ */ jsx7("span", { className: "hidden text-sm font-semibold sm:inline", children: labels.appName }),
|
|
431
501
|
/* @__PURE__ */ jsx7(Separator, { orientation: "vertical", className: "mx-1 !h-5 bg-panel-border" }),
|
|
432
502
|
/* @__PURE__ */ jsx7(
|
|
433
503
|
Input,
|
|
@@ -437,7 +507,7 @@ function EditorHeader({
|
|
|
437
507
|
onBlur: () => void commitName(),
|
|
438
508
|
onKeyDown: (e) => e.key === "Enter" && e.currentTarget.blur(),
|
|
439
509
|
className: "h-8 w-44 border-transparent bg-transparent text-sm font-medium text-panel-fg hover:border-panel-border focus-visible:border-panel-border",
|
|
440
|
-
"aria-label":
|
|
510
|
+
"aria-label": labels.emailNameAria
|
|
441
511
|
}
|
|
442
512
|
),
|
|
443
513
|
/* @__PURE__ */ jsx7(Separator, { orientation: "vertical", className: "mx-1 !h-5 bg-panel-border" }),
|
|
@@ -475,7 +545,7 @@ function EditorHeader({
|
|
|
475
545
|
children: /* @__PURE__ */ jsx7(Undo2, {})
|
|
476
546
|
}
|
|
477
547
|
) }),
|
|
478
|
-
/* @__PURE__ */ jsx7(TooltipContent, { children:
|
|
548
|
+
/* @__PURE__ */ jsx7(TooltipContent, { children: labels.undo })
|
|
479
549
|
] }),
|
|
480
550
|
/* @__PURE__ */ jsxs2(Tooltip, { children: [
|
|
481
551
|
/* @__PURE__ */ jsx7(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
@@ -489,7 +559,7 @@ function EditorHeader({
|
|
|
489
559
|
children: /* @__PURE__ */ jsx7(Redo2, {})
|
|
490
560
|
}
|
|
491
561
|
) }),
|
|
492
|
-
/* @__PURE__ */ jsx7(TooltipContent, { children:
|
|
562
|
+
/* @__PURE__ */ jsx7(TooltipContent, { children: labels.redo })
|
|
493
563
|
] }),
|
|
494
564
|
/* @__PURE__ */ jsx7(Separator, { orientation: "vertical", className: "mx-1 !h-5 bg-panel-border max-xl:hidden" }),
|
|
495
565
|
/* @__PURE__ */ jsxs2(Popover, { children: [
|
|
@@ -500,7 +570,7 @@ function EditorHeader({
|
|
|
500
570
|
size: "sm",
|
|
501
571
|
className: cn(darkGhost, "gap-1.5 rounded-md border border-panel-border max-xl:hidden"),
|
|
502
572
|
children: [
|
|
503
|
-
/* @__PURE__ */ jsx7("span", { className: "text-panel-muted-fg", children:
|
|
573
|
+
/* @__PURE__ */ jsx7("span", { className: "text-panel-muted-fg", children: labels.contentWidth }),
|
|
504
574
|
state.contentWidth,
|
|
505
575
|
/* @__PURE__ */ jsx7(ChevronDown, { className: "size-3.5" })
|
|
506
576
|
]
|
|
@@ -562,7 +632,8 @@ function EditorHeader({
|
|
|
562
632
|
onClick: () => setPreview(api?.getCompiledHtml() ?? ""),
|
|
563
633
|
children: [
|
|
564
634
|
/* @__PURE__ */ jsx7(Eye, {}),
|
|
565
|
-
"
|
|
635
|
+
" ",
|
|
636
|
+
labels.preview
|
|
566
637
|
]
|
|
567
638
|
}
|
|
568
639
|
) }),
|
|
@@ -574,7 +645,8 @@ function EditorHeader({
|
|
|
574
645
|
children: [
|
|
575
646
|
/* @__PURE__ */ jsxs2("div", { className: "flex h-12 shrink-0 items-center justify-between border-b bg-white px-4", children: [
|
|
576
647
|
/* @__PURE__ */ jsxs2(DialogTitle, { className: "text-sm", children: [
|
|
577
|
-
|
|
648
|
+
labels.preview,
|
|
649
|
+
" \u2014 ",
|
|
578
650
|
name
|
|
579
651
|
] }),
|
|
580
652
|
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
|
|
@@ -601,13 +673,13 @@ function EditorHeader({
|
|
|
601
673
|
]
|
|
602
674
|
}
|
|
603
675
|
),
|
|
604
|
-
/* @__PURE__ */ jsx7(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx7(Button, { variant: "ghost", size: "icon", "aria-label":
|
|
676
|
+
/* @__PURE__ */ jsx7(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx7(Button, { variant: "ghost", size: "icon", "aria-label": labels.closePreview, children: /* @__PURE__ */ jsx7(X, {}) }) })
|
|
605
677
|
] })
|
|
606
678
|
] }),
|
|
607
679
|
/* @__PURE__ */ jsx7("div", { className: "min-h-0 flex-1 overflow-auto p-6", children: /* @__PURE__ */ jsx7(
|
|
608
680
|
"iframe",
|
|
609
681
|
{
|
|
610
|
-
title:
|
|
682
|
+
title: labels.previewFrameTitle,
|
|
611
683
|
srcDoc: preview,
|
|
612
684
|
className: cn(
|
|
613
685
|
"mx-auto block h-full min-h-[80vh] rounded-md border bg-white shadow-sm",
|
|
@@ -634,7 +706,7 @@ function EditorHeader({
|
|
|
634
706
|
}
|
|
635
707
|
) }),
|
|
636
708
|
/* @__PURE__ */ jsxs2(DialogContent, { className: "flex !max-w-4xl flex-col", children: [
|
|
637
|
-
/* @__PURE__ */ jsx7(DialogHeader, { children: /* @__PURE__ */ jsx7(DialogTitle, { children:
|
|
709
|
+
/* @__PURE__ */ jsx7(DialogHeader, { children: /* @__PURE__ */ jsx7(DialogTitle, { children: labels.sourceCode }) }),
|
|
638
710
|
/* @__PURE__ */ jsxs2(Tabs, { defaultValue: "mjml", className: "min-h-0 flex-1", children: [
|
|
639
711
|
/* @__PURE__ */ jsxs2(TabsList, { children: [
|
|
640
712
|
/* @__PURE__ */ jsx7(TabsTrigger, { value: "mjml", children: "MJML" }),
|
|
@@ -667,7 +739,7 @@ function EditorHeader({
|
|
|
667
739
|
size: "sm",
|
|
668
740
|
onClick: () => {
|
|
669
741
|
void navigator.clipboard?.writeText(code[kind]);
|
|
670
|
-
toast.success(
|
|
742
|
+
toast.success(labels.copied(kind.toUpperCase()));
|
|
671
743
|
},
|
|
672
744
|
children: [
|
|
673
745
|
/* @__PURE__ */ jsx7(Copy, {}),
|
|
@@ -693,7 +765,7 @@ function EditorHeader({
|
|
|
693
765
|
onClick: () => download(`${base}.html`, api?.getCompiledHtml() ?? "", "text/html"),
|
|
694
766
|
className: "flex w-full flex-col rounded px-2 py-1.5 text-left text-sm hover:bg-muted",
|
|
695
767
|
children: [
|
|
696
|
-
/* @__PURE__ */ jsx7("span", { className: "font-medium", children:
|
|
768
|
+
/* @__PURE__ */ jsx7("span", { className: "font-medium", children: labels.exportHtml }),
|
|
697
769
|
/* @__PURE__ */ jsxs2("span", { className: "text-xs text-muted-foreground", children: [
|
|
698
770
|
base,
|
|
699
771
|
".html"
|
|
@@ -707,7 +779,7 @@ function EditorHeader({
|
|
|
707
779
|
onClick: () => download(`${base}.mjml`, api?.getMjml() ?? "", "text/plain"),
|
|
708
780
|
className: "flex w-full flex-col rounded px-2 py-1.5 text-left text-sm hover:bg-muted",
|
|
709
781
|
children: [
|
|
710
|
-
/* @__PURE__ */ jsx7("span", { className: "font-medium", children:
|
|
782
|
+
/* @__PURE__ */ jsx7("span", { className: "font-medium", children: labels.exportMjml }),
|
|
711
783
|
/* @__PURE__ */ jsxs2("span", { className: "text-xs text-muted-foreground", children: [
|
|
712
784
|
base,
|
|
713
785
|
".mjml"
|
|
@@ -1080,17 +1152,6 @@ function MessageScrollerButton({
|
|
|
1080
1152
|
|
|
1081
1153
|
// src/components/chat/ChatPanel.tsx
|
|
1082
1154
|
import { jsx as jsx14, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1083
|
-
var TOOL_LABELS = {
|
|
1084
|
-
get_document: "Reading document",
|
|
1085
|
-
get_section: "Reading section",
|
|
1086
|
-
set_document: "Saving whole email",
|
|
1087
|
-
set_section: "Replacing section",
|
|
1088
|
-
insert_section: "Adding section",
|
|
1089
|
-
remove_section: "Removing section",
|
|
1090
|
-
generate_image: "Generating image",
|
|
1091
|
-
list_open_comments: "Reading comments",
|
|
1092
|
-
resolve_comment: "Resolving comment"
|
|
1093
|
-
};
|
|
1094
1155
|
var APPLY_COMMENTS_PROMPT = "Apply changes based on all open section comments. After each successful change mark the comment as resolved and summarize what you changed.";
|
|
1095
1156
|
var MUTATING_TOOLS = /* @__PURE__ */ new Set([
|
|
1096
1157
|
"set_document",
|
|
@@ -1124,30 +1185,41 @@ function toBlocks(parts) {
|
|
|
1124
1185
|
}
|
|
1125
1186
|
if (part.type === "text") {
|
|
1126
1187
|
if (!part.text.trim()) continue;
|
|
1127
|
-
blocks.push({ kind: "text", text: part.text });
|
|
1188
|
+
blocks.push({ kind: "text", text: part.text, narration: false });
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
let seenTools = false;
|
|
1192
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
1193
|
+
const block = blocks[i];
|
|
1194
|
+
if (block.kind === "tools") seenTools = true;
|
|
1195
|
+
else if (block.kind === "text" && seenTools) {
|
|
1196
|
+
blocks[i] = { kind: "text", text: block.text, narration: true };
|
|
1128
1197
|
}
|
|
1129
1198
|
}
|
|
1130
1199
|
return blocks;
|
|
1131
1200
|
}
|
|
1132
1201
|
function ToolMarker({ tool }) {
|
|
1202
|
+
const labels = useLabels();
|
|
1133
1203
|
const name = tool.type.slice(5);
|
|
1134
1204
|
const done = tool.state === "output-available";
|
|
1135
1205
|
const failed = tool.state === "output-error";
|
|
1136
1206
|
return /* @__PURE__ */ jsxs4(Marker, { className: cn(failed ? "text-destructive" : "text-panel-fg"), children: [
|
|
1137
1207
|
/* @__PURE__ */ jsx14(MarkerIcon, { children: failed ? /* @__PURE__ */ jsx14(TriangleAlert, {}) : done ? /* @__PURE__ */ jsx14(Check, { className: "text-emerald-400" }) : /* @__PURE__ */ jsx14(Loader2, { className: "animate-spin" }) }),
|
|
1138
1208
|
/* @__PURE__ */ jsxs4(MarkerContent, { children: [
|
|
1139
|
-
|
|
1209
|
+
labels.toolLabels[name] ?? name,
|
|
1140
1210
|
failed && tool.errorText ? `: ${tool.errorText}` : ""
|
|
1141
1211
|
] })
|
|
1142
1212
|
] });
|
|
1143
1213
|
}
|
|
1144
1214
|
function BusyMarker() {
|
|
1215
|
+
const labels = useLabels();
|
|
1145
1216
|
return /* @__PURE__ */ jsxs4(Marker, { className: "text-panel-fg", children: [
|
|
1146
1217
|
/* @__PURE__ */ jsx14(MarkerIcon, { children: /* @__PURE__ */ jsx14(Loader2, { className: "animate-spin" }) }),
|
|
1147
|
-
/* @__PURE__ */ jsx14(MarkerContent, { children:
|
|
1218
|
+
/* @__PURE__ */ jsx14(MarkerContent, { children: labels.agentWorking })
|
|
1148
1219
|
] });
|
|
1149
1220
|
}
|
|
1150
1221
|
function ToolActivity({ tools }) {
|
|
1222
|
+
const labels = useLabels();
|
|
1151
1223
|
const running = tools.filter((t) => t.state !== "output-available" && t.state !== "output-error");
|
|
1152
1224
|
const finished = tools.filter(
|
|
1153
1225
|
(t) => t.state === "output-available" || t.state === "output-error"
|
|
@@ -1157,7 +1229,7 @@ function ToolActivity({ tools }) {
|
|
|
1157
1229
|
finished.length > 0 && /* @__PURE__ */ jsxs4(Collapsible, { children: [
|
|
1158
1230
|
/* @__PURE__ */ jsxs4(CollapsibleTrigger, { className: "group/col flex w-full items-center gap-1.5 text-left text-xs font-medium text-panel-fg hover:text-panel-fg", children: [
|
|
1159
1231
|
/* @__PURE__ */ jsx14(ChevronRight, { className: "size-3.5 shrink-0 transition-transform group-data-[state=open]/col:rotate-90" }),
|
|
1160
|
-
/* @__PURE__ */ jsx14("span", { children:
|
|
1232
|
+
/* @__PURE__ */ jsx14("span", { children: labels.completedSteps(finished.length, failedCount) })
|
|
1161
1233
|
] }),
|
|
1162
1234
|
/* @__PURE__ */ jsx14(CollapsibleContent, { className: "mt-1 space-y-0.5 pl-1", children: finished.map((t, i) => /* @__PURE__ */ jsx14(ToolMarker, { tool: t }, `f${i}`)) })
|
|
1163
1235
|
] }),
|
|
@@ -1165,11 +1237,12 @@ function ToolActivity({ tools }) {
|
|
|
1165
1237
|
] });
|
|
1166
1238
|
}
|
|
1167
1239
|
function ReasoningBlock({ text }) {
|
|
1240
|
+
const labels = useLabels();
|
|
1168
1241
|
return /* @__PURE__ */ jsx14("div", { className: "rounded-lg border border-panel-border bg-panel-elevated/60 p-2", children: /* @__PURE__ */ jsxs4(Collapsible, { children: [
|
|
1169
1242
|
/* @__PURE__ */ jsxs4(CollapsibleTrigger, { className: "group/col flex w-full items-center gap-1.5 text-left text-xs font-medium text-panel-muted-fg hover:text-panel-fg", children: [
|
|
1170
1243
|
/* @__PURE__ */ jsx14(ChevronRight, { className: "size-3.5 shrink-0 transition-transform group-data-[state=open]/col:rotate-90" }),
|
|
1171
1244
|
/* @__PURE__ */ jsx14(Brain, { className: "size-3.5 shrink-0" }),
|
|
1172
|
-
/* @__PURE__ */ jsx14("span", { children:
|
|
1245
|
+
/* @__PURE__ */ jsx14("span", { children: labels.reasoning })
|
|
1173
1246
|
] }),
|
|
1174
1247
|
/* @__PURE__ */ jsx14(CollapsibleContent, { className: "mt-1.5 pl-1 text-xs whitespace-pre-wrap text-panel-muted-fg", children: text })
|
|
1175
1248
|
] }) });
|
|
@@ -1184,6 +1257,7 @@ function ChatPanel({
|
|
|
1184
1257
|
onSectionEditStart,
|
|
1185
1258
|
onSectionEditEnd
|
|
1186
1259
|
}) {
|
|
1260
|
+
const labels = useLabels();
|
|
1187
1261
|
const [input, setInput] = useState2("");
|
|
1188
1262
|
const taRef = useRef(null);
|
|
1189
1263
|
const times = useRef(/* @__PURE__ */ new Map());
|
|
@@ -1206,7 +1280,7 @@ function ChatPanel({
|
|
|
1206
1280
|
onFinish: onAgentFinish,
|
|
1207
1281
|
onError: (e) => {
|
|
1208
1282
|
console.error("chat error:", e);
|
|
1209
|
-
toast2.error(
|
|
1283
|
+
toast2.error(labels.chatError);
|
|
1210
1284
|
}
|
|
1211
1285
|
});
|
|
1212
1286
|
const firedTools = useRef(/* @__PURE__ */ new Set());
|
|
@@ -1268,8 +1342,8 @@ function ChatPanel({
|
|
|
1268
1342
|
/* @__PURE__ */ jsx14(MessageScrollerViewport, { children: /* @__PURE__ */ jsxs4(MessageScrollerContent, { className: "p-3", children: [
|
|
1269
1343
|
messages.length === 0 ? /* @__PURE__ */ jsx14(Empty, { className: "h-full", children: /* @__PURE__ */ jsxs4(EmptyHeader, { children: [
|
|
1270
1344
|
/* @__PURE__ */ jsx14(EmptyMedia, { variant: "icon", children: /* @__PURE__ */ jsx14(MessageSquare2, {}) }),
|
|
1271
|
-
/* @__PURE__ */ jsx14(EmptyTitle, { children:
|
|
1272
|
-
/* @__PURE__ */ jsx14(EmptyDescription, { children:
|
|
1345
|
+
/* @__PURE__ */ jsx14(EmptyTitle, { children: labels.chatEmptyTitle }),
|
|
1346
|
+
/* @__PURE__ */ jsx14(EmptyDescription, { children: labels.chatEmptyDescription })
|
|
1273
1347
|
] }) }) : messages.map((message, mi) => {
|
|
1274
1348
|
const isUser = message.role === "user";
|
|
1275
1349
|
const isLast = mi === messages.length - 1;
|
|
@@ -1293,6 +1367,17 @@ function ChatPanel({
|
|
|
1293
1367
|
if (block.kind === "reasoning") {
|
|
1294
1368
|
return /* @__PURE__ */ jsx14(ReasoningBlock, { text: block.text }, i);
|
|
1295
1369
|
}
|
|
1370
|
+
if (block.narration && !isUser) {
|
|
1371
|
+
return /* @__PURE__ */ jsx14(
|
|
1372
|
+
"div",
|
|
1373
|
+
{
|
|
1374
|
+
"data-slot": "narration",
|
|
1375
|
+
className: "px-1 text-xs leading-relaxed text-panel-muted-fg [&_a]:text-brand [&_code]:!bg-white/10 [&_p]:my-0.5",
|
|
1376
|
+
children: /* @__PURE__ */ jsx14(Markdown, { children: block.text })
|
|
1377
|
+
},
|
|
1378
|
+
i
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1296
1381
|
return /* @__PURE__ */ jsx14(
|
|
1297
1382
|
Bubble,
|
|
1298
1383
|
{
|
|
@@ -1333,7 +1418,8 @@ function ChatPanel({
|
|
|
1333
1418
|
onClick: () => void send(APPLY_COMMENTS_PROMPT),
|
|
1334
1419
|
children: [
|
|
1335
1420
|
/* @__PURE__ */ jsx14(Sparkles, {}),
|
|
1336
|
-
"
|
|
1421
|
+
" ",
|
|
1422
|
+
labels.applyComments
|
|
1337
1423
|
]
|
|
1338
1424
|
}
|
|
1339
1425
|
),
|
|
@@ -1352,7 +1438,7 @@ function ChatPanel({
|
|
|
1352
1438
|
ref: taRef,
|
|
1353
1439
|
rows: 2,
|
|
1354
1440
|
className: "max-h-40 min-h-14 resize-none border-0 bg-transparent px-3 pt-2.5 text-panel-fg shadow-none placeholder:text-panel-muted-fg focus-visible:ring-0",
|
|
1355
|
-
placeholder:
|
|
1441
|
+
placeholder: labels.chatPlaceholder,
|
|
1356
1442
|
value: input,
|
|
1357
1443
|
onChange: (e) => {
|
|
1358
1444
|
setInput(e.target.value);
|
|
@@ -1377,7 +1463,8 @@ function ChatPanel({
|
|
|
1377
1463
|
onClick: () => void stop(),
|
|
1378
1464
|
children: [
|
|
1379
1465
|
/* @__PURE__ */ jsx14(Square, {}),
|
|
1380
|
-
"
|
|
1466
|
+
" ",
|
|
1467
|
+
labels.stop
|
|
1381
1468
|
]
|
|
1382
1469
|
}
|
|
1383
1470
|
),
|
|
@@ -1390,7 +1477,8 @@ function ChatPanel({
|
|
|
1390
1477
|
className: "bg-brand text-brand-fg hover:bg-brand/90",
|
|
1391
1478
|
children: [
|
|
1392
1479
|
/* @__PURE__ */ jsx14(Send, {}),
|
|
1393
|
-
"
|
|
1480
|
+
" ",
|
|
1481
|
+
labels.send
|
|
1394
1482
|
]
|
|
1395
1483
|
}
|
|
1396
1484
|
)
|
|
@@ -1404,7 +1492,7 @@ function ChatPanel({
|
|
|
1404
1492
|
|
|
1405
1493
|
// src/components/comments/CanvasComments.tsx
|
|
1406
1494
|
import { useEditorMaybe } from "@grapesjs/react";
|
|
1407
|
-
import { useCallback, useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3 } from "react";
|
|
1495
|
+
import { useCallback, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
|
|
1408
1496
|
import { Check as Check2, MessageSquarePlus, X as X2 } from "lucide-react";
|
|
1409
1497
|
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1410
1498
|
var keyOf = (c) => c.objectId ? `obj-${c.objectId}` : `sec-${c.sectionId}`;
|
|
@@ -1417,6 +1505,7 @@ function CanvasComments({
|
|
|
1417
1505
|
onOpenCountChange
|
|
1418
1506
|
}) {
|
|
1419
1507
|
const commentStore = useCommentStore();
|
|
1508
|
+
const labels = useLabels();
|
|
1420
1509
|
const editor = useEditorMaybe();
|
|
1421
1510
|
const containerRef = useRef2(null);
|
|
1422
1511
|
const [comments, setComments] = useState3([]);
|
|
@@ -1430,11 +1519,11 @@ function CanvasComments({
|
|
|
1430
1519
|
useEffect3(() => {
|
|
1431
1520
|
reload();
|
|
1432
1521
|
}, [reload, refreshSignal]);
|
|
1433
|
-
const open =
|
|
1522
|
+
const open = useMemo2(() => comments.filter((c) => c.status === "open"), [comments]);
|
|
1434
1523
|
useEffect3(() => {
|
|
1435
1524
|
onOpenCountChange(open.length);
|
|
1436
1525
|
}, [open.length, onOpenCountChange]);
|
|
1437
|
-
const pins =
|
|
1526
|
+
const pins = useMemo2(() => {
|
|
1438
1527
|
const map = /* @__PURE__ */ new Map();
|
|
1439
1528
|
for (const c of open) {
|
|
1440
1529
|
const k = keyOf(c);
|
|
@@ -1605,7 +1694,7 @@ function CanvasComments({
|
|
|
1605
1694
|
" ",
|
|
1606
1695
|
/* @__PURE__ */ jsx15("span", { className: "font-medium text-foreground", children: activeTarget.objectLabel })
|
|
1607
1696
|
] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1608
|
-
|
|
1697
|
+
labels.commentOnSection,
|
|
1609
1698
|
" ",
|
|
1610
1699
|
/* @__PURE__ */ jsx15("code", { className: "font-mono", children: activeTarget?.sectionId })
|
|
1611
1700
|
] }) }),
|
|
@@ -1614,14 +1703,14 @@ function CanvasComments({
|
|
|
1614
1703
|
{
|
|
1615
1704
|
type: "button",
|
|
1616
1705
|
onClick: closePopover,
|
|
1617
|
-
"aria-label":
|
|
1706
|
+
"aria-label": labels.closeComments,
|
|
1618
1707
|
className: "-mr-1 -mt-0.5 shrink-0 rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
1619
1708
|
children: /* @__PURE__ */ jsx15(X2, { className: "size-4" })
|
|
1620
1709
|
}
|
|
1621
1710
|
)
|
|
1622
1711
|
] }),
|
|
1623
1712
|
/* @__PURE__ */ jsxs5("div", { className: "max-h-64 space-y-2 overflow-y-auto p-3", children: [
|
|
1624
|
-
activeComments.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-xs text-muted-foreground", children:
|
|
1713
|
+
activeComments.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-xs text-muted-foreground", children: labels.noCommentsYet }),
|
|
1625
1714
|
activeComments.map((c) => /* @__PURE__ */ jsxs5("div", { className: "rounded-md border bg-muted/40 p-2 text-sm", children: [
|
|
1626
1715
|
/* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: c.body }),
|
|
1627
1716
|
/* @__PURE__ */ jsxs5(
|
|
@@ -1631,7 +1720,8 @@ function CanvasComments({
|
|
|
1631
1720
|
className: "mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
|
|
1632
1721
|
children: [
|
|
1633
1722
|
/* @__PURE__ */ jsx15(Check2, { className: "size-3" }),
|
|
1634
|
-
"
|
|
1723
|
+
" ",
|
|
1724
|
+
labels.resolveComment
|
|
1635
1725
|
]
|
|
1636
1726
|
}
|
|
1637
1727
|
)
|
|
@@ -1644,7 +1734,7 @@ function CanvasComments({
|
|
|
1644
1734
|
autoFocus: true,
|
|
1645
1735
|
value: body,
|
|
1646
1736
|
onChange: (e) => setBody(e.target.value),
|
|
1647
|
-
placeholder:
|
|
1737
|
+
placeholder: labels.addCommentPlaceholder,
|
|
1648
1738
|
className: "min-h-14 resize-none text-sm",
|
|
1649
1739
|
onKeyDown: (e) => {
|
|
1650
1740
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
@@ -1656,7 +1746,8 @@ function CanvasComments({
|
|
|
1656
1746
|
),
|
|
1657
1747
|
/* @__PURE__ */ jsx15("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsxs5(Button, { size: "sm", disabled: !body.trim(), onClick: () => void submit(), children: [
|
|
1658
1748
|
/* @__PURE__ */ jsx15(MessageSquarePlus, {}),
|
|
1659
|
-
"
|
|
1749
|
+
" ",
|
|
1750
|
+
labels.addComment
|
|
1660
1751
|
] }) })
|
|
1661
1752
|
] })
|
|
1662
1753
|
]
|
|
@@ -1667,7 +1758,10 @@ function CanvasComments({
|
|
|
1667
1758
|
}
|
|
1668
1759
|
|
|
1669
1760
|
export {
|
|
1761
|
+
DEFAULT_LABELS,
|
|
1762
|
+
mergeLabels,
|
|
1670
1763
|
EditorStoreProvider,
|
|
1764
|
+
useLabels,
|
|
1671
1765
|
useDocumentStore,
|
|
1672
1766
|
useCommentStore,
|
|
1673
1767
|
EditorHeader,
|
|
@@ -1676,4 +1770,4 @@ export {
|
|
|
1676
1770
|
CanvasComments,
|
|
1677
1771
|
STARTER_MJML
|
|
1678
1772
|
};
|
|
1679
|
-
//# sourceMappingURL=chunk-
|
|
1773
|
+
//# sourceMappingURL=chunk-XAEUCHL4.js.map
|