@mjml-agent-editor/editor 0.1.12 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -49,6 +49,29 @@ interface EditorLabels {
49
49
  readonly rteBackgroundColor: string;
50
50
  readonly documentLoadFailed: string;
51
51
  readonly documentSaveFailed: string;
52
+ readonly retry: string;
53
+ readonly chooseImage: string;
54
+ readonly imagePickerTitle: string;
55
+ readonly imagePickerDrop: string;
56
+ readonly imagePickerBrowse: string;
57
+ readonly imagePickerUrlPlaceholder: string;
58
+ readonly imagePickerUseUrl: string;
59
+ readonly imagePickerGallery: string;
60
+ readonly imagePickerEmpty: string;
61
+ readonly imagePickerQuota: (used: number, limit: number) => string;
62
+ readonly imagePickerQuotaFull: string;
63
+ readonly imagePickerDelete: string;
64
+ readonly imagePickerConfirmDelete: string;
65
+ readonly imagePickerLoadFailed: string;
66
+ readonly imageUploadFailed: string;
67
+ readonly imageDeleteFailed: string;
68
+ readonly imagePickerUnsupported: (fileName: string) => string;
69
+ readonly imageFieldRemove: string;
70
+ readonly colorPickerOpen: string;
71
+ readonly colorPickerEyedropper: string;
72
+ readonly colorPickerDocument: string;
73
+ readonly colorPickerPresets: string;
74
+ readonly colorPickerTransparent: string;
52
75
  readonly commentOnSection: string;
53
76
  readonly closeComments: string;
54
77
  readonly noCommentsYet: string;
@@ -60,6 +83,8 @@ interface EditorLabels {
60
83
  readonly agentWorking: string;
61
84
  readonly reasoning: string;
62
85
  readonly completedSteps: (count: number, failed: number) => string;
86
+ /** Under a turn that hit the backend's step ceiling before it could reply. */
87
+ readonly stepLimitReached: string;
63
88
  readonly applyComments: string;
64
89
  readonly chatPlaceholder: string;
65
90
  readonly stop: string;
@@ -75,9 +100,43 @@ declare const DEFAULT_LABELS: EditorLabels;
75
100
  */
76
101
  declare function mergeLabels(overrides?: Partial<EditorLabels>): EditorLabels;
77
102
 
103
+ /** An image the host has stored on the user's behalf. */
104
+ interface ImageAsset {
105
+ readonly id: string;
106
+ readonly url: string;
107
+ readonly name?: string;
108
+ }
109
+ /**
110
+ * The user's own images: uploaded once, then picked from a gallery in any email.
111
+ *
112
+ * Without one the picker accepts only URLs. GrapesJS would otherwise inline a dropped file
113
+ * as base64: most mail clients block `data:` images, and every agent turn pays for the bytes.
114
+ */
115
+ interface ImageLibrary {
116
+ /** Newest first. `quota` is shown in the picker when given. */
117
+ list(): Promise<{
118
+ readonly images: readonly ImageAsset[];
119
+ readonly quota?: {
120
+ readonly used: number;
121
+ readonly limit: number;
122
+ };
123
+ }>;
124
+ upload(file: File): Promise<ImageAsset>;
125
+ /**
126
+ * What `upload` takes, as an `<input accept>` value ("image/png,image/jpeg"). The picker
127
+ * refuses anything else before sending it. Defaults to any image.
128
+ */
129
+ readonly accept?: string;
130
+ /**
131
+ * Omit to make the gallery read-only — for a host that caps uploads and cannot reclaim
132
+ * the storage, deleting would only be a way round the cap.
133
+ */
134
+ remove?(id: string): Promise<void>;
135
+ }
78
136
  interface EditorStores {
79
137
  readonly documents: DocumentStore;
80
138
  readonly comments: CommentStore;
139
+ readonly images?: ImageLibrary;
81
140
  }
82
141
  declare function EditorStoreProvider({ stores, labels, children, }: {
83
142
  stores: EditorStores;
@@ -101,6 +160,7 @@ declare function EditorStoreProvider({ stores, labels, children, }: {
101
160
  declare function useLabels(): EditorLabels;
102
161
  declare function useDocumentStore(): DocumentStore;
103
162
  declare function useCommentStore(): CommentStore;
163
+ declare function useImageLibrary(): ImageLibrary | undefined;
104
164
 
105
165
  declare function EditorHeader({ docId, api, openCount, homeLink, logo, }: {
106
166
  docId: string;
@@ -158,7 +218,11 @@ type Props$1 = {
158
218
  * means there was nothing to re-attach to — which is the ordinary case and not an error.
159
219
  */
160
220
  resume?: boolean;
161
- /** Flushes unsaved editor changes before the agent starts. */
221
+ /**
222
+ * Flushes unsaved editor changes before the agent starts. A rejection stops the turn and
223
+ * keeps the prompt; its message is shown when it carries a 4xx `status` or an
224
+ * `{"error": "..."}` body, otherwise `labels.documentSaveFailed`.
225
+ */
162
226
  onBeforeSend: () => Promise<void>;
163
227
  /** After the agent's turn finishes (refresh the editor and comments). */
164
228
  onAgentFinish: () => void;
@@ -187,4 +251,4 @@ declare function MarkdownImpl({ children }: {
187
251
  }): React.JSX.Element;
188
252
  declare const Markdown: React.MemoExoticComponent<typeof MarkdownImpl>;
189
253
 
190
- export { CanvasComments, ChatPanel, DEFAULT_LABELS, EditorApi, EditorHeader, type EditorLabels, EditorStoreProvider, type EditorStores, Markdown, mergeLabels, useCommentStore, useDocumentStore, useLabels };
254
+ export { CanvasComments, ChatPanel, DEFAULT_LABELS, EditorApi, EditorHeader, type EditorLabels, EditorStoreProvider, type EditorStores, type ImageAsset, type ImageLibrary, Markdown, mergeLabels, useCommentStore, useDocumentStore, useImageLibrary, useLabels };
package/dist/index.d.ts CHANGED
@@ -49,6 +49,29 @@ interface EditorLabels {
49
49
  readonly rteBackgroundColor: string;
50
50
  readonly documentLoadFailed: string;
51
51
  readonly documentSaveFailed: string;
52
+ readonly retry: string;
53
+ readonly chooseImage: string;
54
+ readonly imagePickerTitle: string;
55
+ readonly imagePickerDrop: string;
56
+ readonly imagePickerBrowse: string;
57
+ readonly imagePickerUrlPlaceholder: string;
58
+ readonly imagePickerUseUrl: string;
59
+ readonly imagePickerGallery: string;
60
+ readonly imagePickerEmpty: string;
61
+ readonly imagePickerQuota: (used: number, limit: number) => string;
62
+ readonly imagePickerQuotaFull: string;
63
+ readonly imagePickerDelete: string;
64
+ readonly imagePickerConfirmDelete: string;
65
+ readonly imagePickerLoadFailed: string;
66
+ readonly imageUploadFailed: string;
67
+ readonly imageDeleteFailed: string;
68
+ readonly imagePickerUnsupported: (fileName: string) => string;
69
+ readonly imageFieldRemove: string;
70
+ readonly colorPickerOpen: string;
71
+ readonly colorPickerEyedropper: string;
72
+ readonly colorPickerDocument: string;
73
+ readonly colorPickerPresets: string;
74
+ readonly colorPickerTransparent: string;
52
75
  readonly commentOnSection: string;
53
76
  readonly closeComments: string;
54
77
  readonly noCommentsYet: string;
@@ -60,6 +83,8 @@ interface EditorLabels {
60
83
  readonly agentWorking: string;
61
84
  readonly reasoning: string;
62
85
  readonly completedSteps: (count: number, failed: number) => string;
86
+ /** Under a turn that hit the backend's step ceiling before it could reply. */
87
+ readonly stepLimitReached: string;
63
88
  readonly applyComments: string;
64
89
  readonly chatPlaceholder: string;
65
90
  readonly stop: string;
@@ -75,9 +100,43 @@ declare const DEFAULT_LABELS: EditorLabels;
75
100
  */
76
101
  declare function mergeLabels(overrides?: Partial<EditorLabels>): EditorLabels;
77
102
 
103
+ /** An image the host has stored on the user's behalf. */
104
+ interface ImageAsset {
105
+ readonly id: string;
106
+ readonly url: string;
107
+ readonly name?: string;
108
+ }
109
+ /**
110
+ * The user's own images: uploaded once, then picked from a gallery in any email.
111
+ *
112
+ * Without one the picker accepts only URLs. GrapesJS would otherwise inline a dropped file
113
+ * as base64: most mail clients block `data:` images, and every agent turn pays for the bytes.
114
+ */
115
+ interface ImageLibrary {
116
+ /** Newest first. `quota` is shown in the picker when given. */
117
+ list(): Promise<{
118
+ readonly images: readonly ImageAsset[];
119
+ readonly quota?: {
120
+ readonly used: number;
121
+ readonly limit: number;
122
+ };
123
+ }>;
124
+ upload(file: File): Promise<ImageAsset>;
125
+ /**
126
+ * What `upload` takes, as an `<input accept>` value ("image/png,image/jpeg"). The picker
127
+ * refuses anything else before sending it. Defaults to any image.
128
+ */
129
+ readonly accept?: string;
130
+ /**
131
+ * Omit to make the gallery read-only — for a host that caps uploads and cannot reclaim
132
+ * the storage, deleting would only be a way round the cap.
133
+ */
134
+ remove?(id: string): Promise<void>;
135
+ }
78
136
  interface EditorStores {
79
137
  readonly documents: DocumentStore;
80
138
  readonly comments: CommentStore;
139
+ readonly images?: ImageLibrary;
81
140
  }
82
141
  declare function EditorStoreProvider({ stores, labels, children, }: {
83
142
  stores: EditorStores;
@@ -101,6 +160,7 @@ declare function EditorStoreProvider({ stores, labels, children, }: {
101
160
  declare function useLabels(): EditorLabels;
102
161
  declare function useDocumentStore(): DocumentStore;
103
162
  declare function useCommentStore(): CommentStore;
163
+ declare function useImageLibrary(): ImageLibrary | undefined;
104
164
 
105
165
  declare function EditorHeader({ docId, api, openCount, homeLink, logo, }: {
106
166
  docId: string;
@@ -158,7 +218,11 @@ type Props$1 = {
158
218
  * means there was nothing to re-attach to — which is the ordinary case and not an error.
159
219
  */
160
220
  resume?: boolean;
161
- /** Flushes unsaved editor changes before the agent starts. */
221
+ /**
222
+ * Flushes unsaved editor changes before the agent starts. A rejection stops the turn and
223
+ * keeps the prompt; its message is shown when it carries a 4xx `status` or an
224
+ * `{"error": "..."}` body, otherwise `labels.documentSaveFailed`.
225
+ */
162
226
  onBeforeSend: () => Promise<void>;
163
227
  /** After the agent's turn finishes (refresh the editor and comments). */
164
228
  onAgentFinish: () => void;
@@ -187,4 +251,4 @@ declare function MarkdownImpl({ children }: {
187
251
  }): React.JSX.Element;
188
252
  declare const Markdown: React.MemoExoticComponent<typeof MarkdownImpl>;
189
253
 
190
- export { CanvasComments, ChatPanel, DEFAULT_LABELS, EditorApi, EditorHeader, type EditorLabels, EditorStoreProvider, type EditorStores, Markdown, mergeLabels, useCommentStore, useDocumentStore, useLabels };
254
+ export { CanvasComments, ChatPanel, DEFAULT_LABELS, EditorApi, EditorHeader, type EditorLabels, EditorStoreProvider, type EditorStores, type ImageAsset, type ImageLibrary, Markdown, mergeLabels, useCommentStore, useDocumentStore, useImageLibrary, useLabels };
package/dist/index.js CHANGED
@@ -10,8 +10,9 @@ import {
10
10
  mergeLabels,
11
11
  useCommentStore,
12
12
  useDocumentStore,
13
+ useImageLibrary,
13
14
  useLabels
14
- } from "./chunk-4N2OJT22.js";
15
+ } from "./chunk-3RCKZYM4.js";
15
16
  import "./chunk-V6RR4VRD.js";
16
17
  export {
17
18
  CanvasComments,
@@ -24,6 +25,7 @@ export {
24
25
  mergeLabels,
25
26
  useCommentStore,
26
27
  useDocumentStore,
28
+ useImageLibrary,
27
29
  useLabels
28
30
  };
29
31
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mjml-agent-editor/editor",
3
- "version": "0.1.12",
3
+ "version": "0.1.15",
4
4
  "description": "React MJML editor with an agent chat panel and canvas comments.",
5
5
  "keywords": [
6
6
  "mjml",
@@ -66,27 +66,30 @@
66
66
  "grapesjs-mjml": "^1.0.8",
67
67
  "lucide-react": "^1.25.0",
68
68
  "radix-ui": "^1.6.2",
69
+ "react-colorful": "^5.8.1",
69
70
  "react-markdown": "^10.1.0",
70
71
  "remark-gfm": "^4.0.1",
71
72
  "sonner": "^2.0.7",
72
73
  "tailwind-merge": "^3.6.0",
73
- "@mjml-agent-editor/core": "0.1.8"
74
+ "@mjml-agent-editor/core": "0.1.9"
74
75
  },
75
76
  "peerDependencies": {
77
+ "ai": "^6.0.230",
76
78
  "react": "^19",
77
- "react-dom": "^19",
78
- "ai": "^6.0.230"
79
+ "react-dom": "^19"
79
80
  },
80
81
  "devDependencies": {
81
82
  "@types/react": "^19",
82
83
  "@types/react-dom": "^19",
84
+ "ai": "^6.0.230",
83
85
  "react": "19.2.4",
84
86
  "tsup": "^8.3.5",
85
87
  "typescript": "^5.7.2",
86
- "ai": "^6.0.230"
88
+ "vitest": "^2.1.8"
87
89
  },
88
90
  "scripts": {
89
91
  "build": "tsup",
92
+ "test": "vitest run",
90
93
  "dev": "tsup --watch",
91
94
  "typecheck": "tsc --noEmit"
92
95
  }
@@ -409,3 +409,32 @@
409
409
  background: transparent;
410
410
  cursor: pointer;
411
411
  }
412
+
413
+ /* ── Color picker (react-colorful), compact to fit beside the sidebar ──── */
414
+ .color-field-picker.react-colorful {
415
+ width: 100%;
416
+ height: 120px;
417
+ }
418
+ .color-field-picker .react-colorful__saturation {
419
+ border-radius: 6px 6px 0 0;
420
+ border-bottom: none;
421
+ }
422
+ .color-field-picker .react-colorful__hue {
423
+ height: 10px;
424
+ border-radius: 0 0 6px 6px;
425
+ }
426
+ .color-field-picker .react-colorful__pointer {
427
+ width: 12px;
428
+ height: 12px;
429
+ border-width: 2px;
430
+ }
431
+
432
+ /* Image properties take the full row: a thumbnail at half the sidebar is too small to judge. */
433
+ .editor-dark .gjs-sm-property.gjs-sm-file {
434
+ width: 100%;
435
+ flex-basis: 100%;
436
+ }
437
+ .editor-dark .gjs-sm-property.gjs-sm-file .gjs-fields > * {
438
+ flex: 1 1 auto;
439
+ width: 100%;
440
+ }