@mjml-agent-editor/editor 0.1.5 → 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.
@@ -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
- return /* @__PURE__ */ jsx(StoreContext.Provider, { value: stores, children });
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
- SAVE_LABEL.saving
438
+ labels.saving
370
439
  ] });
371
- if (status === "error") return /* @__PURE__ */ jsx7(Badge, { variant: "destructive", children: SAVE_LABEL.error });
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
- SAVE_LABEL.saved
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("Failed to rename.");
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: "MJML Editor" }),
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": "Email name"
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: "Undo" })
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: "Redo" })
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: "Content width" }),
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
- " Preview"
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
- "Preview \u2014 ",
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": "Close preview", children: /* @__PURE__ */ jsx7(X, {}) }) })
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: "Email preview",
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: "Source code" }) }),
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(`${kind.toUpperCase()} copied.`);
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: "Export HTML" }),
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: "Export MJML" }),
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",
@@ -1138,24 +1199,27 @@ function toBlocks(parts) {
1138
1199
  return blocks;
1139
1200
  }
1140
1201
  function ToolMarker({ tool }) {
1202
+ const labels = useLabels();
1141
1203
  const name = tool.type.slice(5);
1142
1204
  const done = tool.state === "output-available";
1143
1205
  const failed = tool.state === "output-error";
1144
1206
  return /* @__PURE__ */ jsxs4(Marker, { className: cn(failed ? "text-destructive" : "text-panel-fg"), children: [
1145
1207
  /* @__PURE__ */ jsx14(MarkerIcon, { children: failed ? /* @__PURE__ */ jsx14(TriangleAlert, {}) : done ? /* @__PURE__ */ jsx14(Check, { className: "text-emerald-400" }) : /* @__PURE__ */ jsx14(Loader2, { className: "animate-spin" }) }),
1146
1208
  /* @__PURE__ */ jsxs4(MarkerContent, { children: [
1147
- TOOL_LABELS[name] ?? name,
1209
+ labels.toolLabels[name] ?? name,
1148
1210
  failed && tool.errorText ? `: ${tool.errorText}` : ""
1149
1211
  ] })
1150
1212
  ] });
1151
1213
  }
1152
1214
  function BusyMarker() {
1215
+ const labels = useLabels();
1153
1216
  return /* @__PURE__ */ jsxs4(Marker, { className: "text-panel-fg", children: [
1154
1217
  /* @__PURE__ */ jsx14(MarkerIcon, { children: /* @__PURE__ */ jsx14(Loader2, { className: "animate-spin" }) }),
1155
- /* @__PURE__ */ jsx14(MarkerContent, { children: "Agent is working\u2026" })
1218
+ /* @__PURE__ */ jsx14(MarkerContent, { children: labels.agentWorking })
1156
1219
  ] });
1157
1220
  }
1158
1221
  function ToolActivity({ tools }) {
1222
+ const labels = useLabels();
1159
1223
  const running = tools.filter((t) => t.state !== "output-available" && t.state !== "output-error");
1160
1224
  const finished = tools.filter(
1161
1225
  (t) => t.state === "output-available" || t.state === "output-error"
@@ -1165,7 +1229,7 @@ function ToolActivity({ tools }) {
1165
1229
  finished.length > 0 && /* @__PURE__ */ jsxs4(Collapsible, { children: [
1166
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: [
1167
1231
  /* @__PURE__ */ jsx14(ChevronRight, { className: "size-3.5 shrink-0 transition-transform group-data-[state=open]/col:rotate-90" }),
1168
- /* @__PURE__ */ jsx14("span", { children: failedCount > 0 ? `Completed steps (${finished.length}, ${failedCount} failed)` : `Completed steps (${finished.length})` })
1232
+ /* @__PURE__ */ jsx14("span", { children: labels.completedSteps(finished.length, failedCount) })
1169
1233
  ] }),
1170
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}`)) })
1171
1235
  ] }),
@@ -1173,11 +1237,12 @@ function ToolActivity({ tools }) {
1173
1237
  ] });
1174
1238
  }
1175
1239
  function ReasoningBlock({ text }) {
1240
+ const labels = useLabels();
1176
1241
  return /* @__PURE__ */ jsx14("div", { className: "rounded-lg border border-panel-border bg-panel-elevated/60 p-2", children: /* @__PURE__ */ jsxs4(Collapsible, { children: [
1177
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: [
1178
1243
  /* @__PURE__ */ jsx14(ChevronRight, { className: "size-3.5 shrink-0 transition-transform group-data-[state=open]/col:rotate-90" }),
1179
1244
  /* @__PURE__ */ jsx14(Brain, { className: "size-3.5 shrink-0" }),
1180
- /* @__PURE__ */ jsx14("span", { children: "Reasoning" })
1245
+ /* @__PURE__ */ jsx14("span", { children: labels.reasoning })
1181
1246
  ] }),
1182
1247
  /* @__PURE__ */ jsx14(CollapsibleContent, { className: "mt-1.5 pl-1 text-xs whitespace-pre-wrap text-panel-muted-fg", children: text })
1183
1248
  ] }) });
@@ -1192,6 +1257,7 @@ function ChatPanel({
1192
1257
  onSectionEditStart,
1193
1258
  onSectionEditEnd
1194
1259
  }) {
1260
+ const labels = useLabels();
1195
1261
  const [input, setInput] = useState2("");
1196
1262
  const taRef = useRef(null);
1197
1263
  const times = useRef(/* @__PURE__ */ new Map());
@@ -1214,7 +1280,7 @@ function ChatPanel({
1214
1280
  onFinish: onAgentFinish,
1215
1281
  onError: (e) => {
1216
1282
  console.error("chat error:", e);
1217
- toast2.error("Agent chat error.");
1283
+ toast2.error(labels.chatError);
1218
1284
  }
1219
1285
  });
1220
1286
  const firedTools = useRef(/* @__PURE__ */ new Set());
@@ -1276,8 +1342,8 @@ function ChatPanel({
1276
1342
  /* @__PURE__ */ jsx14(MessageScrollerViewport, { children: /* @__PURE__ */ jsxs4(MessageScrollerContent, { className: "p-3", children: [
1277
1343
  messages.length === 0 ? /* @__PURE__ */ jsx14(Empty, { className: "h-full", children: /* @__PURE__ */ jsxs4(EmptyHeader, { children: [
1278
1344
  /* @__PURE__ */ jsx14(EmptyMedia, { variant: "icon", children: /* @__PURE__ */ jsx14(MessageSquare2, {}) }),
1279
- /* @__PURE__ */ jsx14(EmptyTitle, { children: "Start a conversation with the agent" }),
1280
- /* @__PURE__ */ jsx14(EmptyDescription, { children: "Describe the email (goal, tone, content) and paste your data \u2014 the agent will design the sections and images." })
1345
+ /* @__PURE__ */ jsx14(EmptyTitle, { children: labels.chatEmptyTitle }),
1346
+ /* @__PURE__ */ jsx14(EmptyDescription, { children: labels.chatEmptyDescription })
1281
1347
  ] }) }) : messages.map((message, mi) => {
1282
1348
  const isUser = message.role === "user";
1283
1349
  const isLast = mi === messages.length - 1;
@@ -1352,7 +1418,8 @@ function ChatPanel({
1352
1418
  onClick: () => void send(APPLY_COMMENTS_PROMPT),
1353
1419
  children: [
1354
1420
  /* @__PURE__ */ jsx14(Sparkles, {}),
1355
- " Apply changes from comments"
1421
+ " ",
1422
+ labels.applyComments
1356
1423
  ]
1357
1424
  }
1358
1425
  ),
@@ -1371,7 +1438,7 @@ function ChatPanel({
1371
1438
  ref: taRef,
1372
1439
  rows: 2,
1373
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",
1374
- placeholder: "Describe what you want to change\u2026 (Enter = send, Shift+Enter = new line)",
1441
+ placeholder: labels.chatPlaceholder,
1375
1442
  value: input,
1376
1443
  onChange: (e) => {
1377
1444
  setInput(e.target.value);
@@ -1396,7 +1463,8 @@ function ChatPanel({
1396
1463
  onClick: () => void stop(),
1397
1464
  children: [
1398
1465
  /* @__PURE__ */ jsx14(Square, {}),
1399
- " Stop"
1466
+ " ",
1467
+ labels.stop
1400
1468
  ]
1401
1469
  }
1402
1470
  ),
@@ -1409,7 +1477,8 @@ function ChatPanel({
1409
1477
  className: "bg-brand text-brand-fg hover:bg-brand/90",
1410
1478
  children: [
1411
1479
  /* @__PURE__ */ jsx14(Send, {}),
1412
- " Send"
1480
+ " ",
1481
+ labels.send
1413
1482
  ]
1414
1483
  }
1415
1484
  )
@@ -1423,7 +1492,7 @@ function ChatPanel({
1423
1492
 
1424
1493
  // src/components/comments/CanvasComments.tsx
1425
1494
  import { useEditorMaybe } from "@grapesjs/react";
1426
- 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";
1427
1496
  import { Check as Check2, MessageSquarePlus, X as X2 } from "lucide-react";
1428
1497
  import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs5 } from "react/jsx-runtime";
1429
1498
  var keyOf = (c) => c.objectId ? `obj-${c.objectId}` : `sec-${c.sectionId}`;
@@ -1436,6 +1505,7 @@ function CanvasComments({
1436
1505
  onOpenCountChange
1437
1506
  }) {
1438
1507
  const commentStore = useCommentStore();
1508
+ const labels = useLabels();
1439
1509
  const editor = useEditorMaybe();
1440
1510
  const containerRef = useRef2(null);
1441
1511
  const [comments, setComments] = useState3([]);
@@ -1449,11 +1519,11 @@ function CanvasComments({
1449
1519
  useEffect3(() => {
1450
1520
  reload();
1451
1521
  }, [reload, refreshSignal]);
1452
- const open = useMemo(() => comments.filter((c) => c.status === "open"), [comments]);
1522
+ const open = useMemo2(() => comments.filter((c) => c.status === "open"), [comments]);
1453
1523
  useEffect3(() => {
1454
1524
  onOpenCountChange(open.length);
1455
1525
  }, [open.length, onOpenCountChange]);
1456
- const pins = useMemo(() => {
1526
+ const pins = useMemo2(() => {
1457
1527
  const map = /* @__PURE__ */ new Map();
1458
1528
  for (const c of open) {
1459
1529
  const k = keyOf(c);
@@ -1624,7 +1694,7 @@ function CanvasComments({
1624
1694
  " ",
1625
1695
  /* @__PURE__ */ jsx15("span", { className: "font-medium text-foreground", children: activeTarget.objectLabel })
1626
1696
  ] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
1627
- "Comment on the whole section",
1697
+ labels.commentOnSection,
1628
1698
  " ",
1629
1699
  /* @__PURE__ */ jsx15("code", { className: "font-mono", children: activeTarget?.sectionId })
1630
1700
  ] }) }),
@@ -1633,14 +1703,14 @@ function CanvasComments({
1633
1703
  {
1634
1704
  type: "button",
1635
1705
  onClick: closePopover,
1636
- "aria-label": "Close",
1706
+ "aria-label": labels.closeComments,
1637
1707
  className: "-mr-1 -mt-0.5 shrink-0 rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",
1638
1708
  children: /* @__PURE__ */ jsx15(X2, { className: "size-4" })
1639
1709
  }
1640
1710
  )
1641
1711
  ] }),
1642
1712
  /* @__PURE__ */ jsxs5("div", { className: "max-h-64 space-y-2 overflow-y-auto p-3", children: [
1643
- activeComments.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-xs text-muted-foreground", children: "No comments yet \u2014 add the first one." }),
1713
+ activeComments.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-xs text-muted-foreground", children: labels.noCommentsYet }),
1644
1714
  activeComments.map((c) => /* @__PURE__ */ jsxs5("div", { className: "rounded-md border bg-muted/40 p-2 text-sm", children: [
1645
1715
  /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: c.body }),
1646
1716
  /* @__PURE__ */ jsxs5(
@@ -1650,7 +1720,8 @@ function CanvasComments({
1650
1720
  className: "mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
1651
1721
  children: [
1652
1722
  /* @__PURE__ */ jsx15(Check2, { className: "size-3" }),
1653
- " Resolve"
1723
+ " ",
1724
+ labels.resolveComment
1654
1725
  ]
1655
1726
  }
1656
1727
  )
@@ -1663,7 +1734,7 @@ function CanvasComments({
1663
1734
  autoFocus: true,
1664
1735
  value: body,
1665
1736
  onChange: (e) => setBody(e.target.value),
1666
- placeholder: "Add a comment\u2026 (\u2318/Ctrl+Enter to send)",
1737
+ placeholder: labels.addCommentPlaceholder,
1667
1738
  className: "min-h-14 resize-none text-sm",
1668
1739
  onKeyDown: (e) => {
1669
1740
  if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
@@ -1675,7 +1746,8 @@ function CanvasComments({
1675
1746
  ),
1676
1747
  /* @__PURE__ */ jsx15("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsxs5(Button, { size: "sm", disabled: !body.trim(), onClick: () => void submit(), children: [
1677
1748
  /* @__PURE__ */ jsx15(MessageSquarePlus, {}),
1678
- " Add"
1749
+ " ",
1750
+ labels.addComment
1679
1751
  ] }) })
1680
1752
  ] })
1681
1753
  ]
@@ -1686,7 +1758,10 @@ function CanvasComments({
1686
1758
  }
1687
1759
 
1688
1760
  export {
1761
+ DEFAULT_LABELS,
1762
+ mergeLabels,
1689
1763
  EditorStoreProvider,
1764
+ useLabels,
1690
1765
  useDocumentStore,
1691
1766
  useCommentStore,
1692
1767
  EditorHeader,
@@ -1695,4 +1770,4 @@ export {
1695
1770
  CanvasComments,
1696
1771
  STARTER_MJML
1697
1772
  };
1698
- //# sourceMappingURL=chunk-2SXJHEF5.js.map
1773
+ //# sourceMappingURL=chunk-XAEUCHL4.js.map