@aswin.dev/core 0.7.0

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/LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ Functional Source License, Version 1.1, MIT Future License
2
+
3
+ Copyright (c) 2026-present Templatical
4
+
5
+ ## Terms and Conditions
6
+
7
+ ### Licensor ("We")
8
+
9
+ Templatical
10
+
11
+ ### The Software
12
+
13
+ Templatical Email Editor — the visual drag-and-drop email template editor
14
+ (@aswin.dev/core, @aswin.dev/editor, and @aswin.dev/media-library
15
+ packages).
16
+
17
+ ### Grant of Rights
18
+
19
+ Subject to the terms and conditions of this License, We hereby grant You a
20
+ non-exclusive, worldwide, non-transferable license to use, copy, modify,
21
+ create derivative works, and redistribute the Software, subject to the
22
+ following conditions:
23
+
24
+ ### Permitted Uses
25
+
26
+ You may use the Software for any purpose, including commercial purposes,
27
+ **provided that** you do not offer the Software, or a substantially similar
28
+ product built using the Software, as a hosted or managed service that
29
+ competes with Templatical's commercial offerings.
30
+
31
+ ### Change Date
32
+
33
+ Two (2) years from the date of each release of the Software.
34
+
35
+ ### Change License
36
+
37
+ MIT License
38
+
39
+ On the Change Date, the above copyright notice and this permission notice
40
+ shall be replaced with the MIT License, and the Software will be available
41
+ under the MIT License for all purposes without restriction.
42
+
43
+ ### Notices
44
+
45
+ You must retain this license notice in all copies or substantial portions
46
+ of the Software.
47
+
48
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
49
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
50
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
51
+
52
+ ---
53
+
54
+ Note: The @aswin.dev/types, @aswin.dev/renderer, and
55
+ @aswin.dev/import-beefree packages are licensed separately under the MIT
56
+ License. See LICENSE-MIT for those packages' terms.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # @aswin.dev/core
2
+
3
+ > Framework-agnostic editor logic — state, history, auto-save. The reactive engine behind `@aswin.dev/editor`.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@aswin.dev/core?label=npm&color=cb3837)](https://www.npmjs.com/package/@aswin.dev/core)
6
+ [![License](https://img.shields.io/badge/license-FSL--1.1--MIT-blue)](https://github.com/templatical/sdk/blob/main/LICENSE)
7
+
8
+ Powers [`@aswin.dev/editor`](https://www.npmjs.com/package/@aswin.dev/editor). Use this package directly if you want to build a custom UI on top of the Templatical state model — for example, a CLI tool, automation pipeline, or your own visual editor.
9
+
10
+ Built on `@vue/reactivity` (no full Vue runtime), so it works anywhere reactive primitives do.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install @aswin.dev/core @aswin.dev/types
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```ts
21
+ import { useEditor } from '@aswin.dev/core';
22
+ import { createDefaultTemplateContent, createTitleBlock } from '@aswin.dev/types';
23
+ import { watch } from '@vue/reactivity';
24
+
25
+ const editor = useEditor({
26
+ content: createDefaultTemplateContent(),
27
+ });
28
+
29
+ // Mutate state — these methods live on the editor return value
30
+ editor.addBlock(createTitleBlock({ text: 'Welcome!' }));
31
+ editor.selectBlock(editor.content.value.blocks[0].id);
32
+
33
+ // Read reactive state
34
+ console.log(editor.content.value); // current TemplateContent
35
+ console.log(editor.selectedBlock.value); // currently selected Block | null
36
+ console.log(editor.state.isDirty); // dirty flag
37
+
38
+ // React to changes
39
+ watch(editor.content, (next) => {
40
+ console.log('Template updated', next);
41
+ });
42
+ ```
43
+
44
+ ## Exports
45
+
46
+ - `useEditor` — reactive state (content, selection, viewport, darkMode, isDirty) + mutation methods (`addBlock`, `removeBlock`, `moveBlock`, `updateBlock`, `updateSettings`, `selectBlock`, …)
47
+ - `useHistory` — undo/redo stack
48
+ - `useHistoryInterceptor` — wraps mutation methods so they push onto the history stack automatically
49
+ - `useBlockActions` — higher-level helpers built on top of `useEditor` (`createAndAddBlock(type)`, `duplicateBlock`, `deleteBlock`, `updateBlockProperty`)
50
+ - `useAutoSave` — debounced save with onSave callback
51
+ - `useConditionPreview` — display condition preview state
52
+ - `useDataSourceFetch` — fetch helper for custom block data sources
53
+
54
+ ## Cloud subpath
55
+
56
+ The `@aswin.dev/core/cloud` subpath provides Templatical Cloud integrations (Auth, API client, WebSocket, AI chat/rewrite, collaboration, comments, scoring). Used by `@aswin.dev/editor`'s `initCloud()`. See [Cloud docs](https://docs.templatical.com/cloud/).
57
+
58
+ ## Documentation
59
+
60
+ Full reference at **[docs.templatical.com](https://docs.templatical.com)**.
61
+
62
+ ## License
63
+
64
+ [FSL-1.1-MIT](https://github.com/templatical/sdk/blob/main/LICENSE) — free for any non-competing commercial use, automatically converts to MIT after 2 years per release.
@@ -0,0 +1,487 @@
1
+ import { AuthConfig, TestEmailConfig, UserConfig, SdkAuthConfig, TemplateContent, Template, TemplateSnapshot, CustomFont, Comment, PlanConfig, SavedModule, Block, WebSocketServerConfig, EditorState, ViewportSize, UiTheme, TemplateSettings, TemplateDefaults, McpOperationPayload, MergeTag, AiConfig, ScoringResult, ScoringFinding, ScoringCategory, CommentThread, CommentEvent, Collaborator, ExportResult, FontsConfig, PlanFeatures, HealthCheckResult } from '@aswin.dev/types';
2
+ export { AuthConfig, AuthRequestOptions, SdkAuthConfig, TestEmailConfig, UserConfig } from '@aswin.dev/types';
3
+ import { PresenceChannel, Channel } from 'pusher-js';
4
+ import { DeepReadonly, Ref, ref, ComputedRef } from 'vue';
5
+ import { U as UseEditorReturn$1 } from '../editor-Cp6y4tLN.js';
6
+ import '@vue/reactivity';
7
+
8
+ declare class AuthManager {
9
+ private static readonly DEFAULT_BASE_URL;
10
+ private accessToken;
11
+ private expiresAt;
12
+ private _projectId;
13
+ private _tenantId;
14
+ private _tenantSlug;
15
+ private _testEmailConfig;
16
+ private _userConfig;
17
+ private readonly url;
18
+ private readonly baseUrl;
19
+ private readonly requestOptions;
20
+ private readonly onError?;
21
+ private refreshPromise;
22
+ private static readonly REFRESH_THRESHOLD_MS;
23
+ constructor(config: AuthConfig);
24
+ resolveUrl(path: string): string;
25
+ get projectId(): string;
26
+ get tenantId(): string;
27
+ get tenantSlug(): string;
28
+ get testEmailConfig(): TestEmailConfig | null;
29
+ get userConfig(): UserConfig | null;
30
+ get accessTokenValue(): string | null;
31
+ initialize(): Promise<void>;
32
+ private ensureToken;
33
+ private isTokenExpiringSoon;
34
+ refreshToken(): Promise<string>;
35
+ private performRefresh;
36
+ authenticatedFetch(url: string, options?: RequestInit): Promise<Response>;
37
+ }
38
+ declare function createSdkAuthManager(config: SdkAuthConfig, onError?: (error: Error) => void): AuthManager;
39
+
40
+ declare class ApiClient {
41
+ private readonly authManager;
42
+ constructor(authManager: AuthManager);
43
+ private get projectId();
44
+ private get tenantSlug();
45
+ private get baseParams();
46
+ private request;
47
+ private extractFirstValidationError;
48
+ createTemplate(content: TemplateContent): Promise<Template>;
49
+ getTemplate(id: string): Promise<Template>;
50
+ updateTemplate(id: string, content: TemplateContent): Promise<Template>;
51
+ createSnapshot(templateId: string, content: TemplateContent): Promise<TemplateSnapshot>;
52
+ deleteTemplate(id: string): Promise<void>;
53
+ getSnapshots(templateId: string): Promise<TemplateSnapshot[]>;
54
+ restoreSnapshot(templateId: string, snapshotId: string): Promise<Template>;
55
+ exportTemplate(templateId: string, fontsPayload?: {
56
+ customFonts: CustomFont[];
57
+ defaultFallback: string;
58
+ }): Promise<{
59
+ html: string;
60
+ mjml: string;
61
+ }>;
62
+ sendTestEmail(templateId: string, payload: {
63
+ recipient: string;
64
+ html: string;
65
+ allowed_emails: string[];
66
+ signature: string;
67
+ }): Promise<void>;
68
+ private commentsUrl;
69
+ getComments(templateId: string): Promise<Comment[]>;
70
+ createComment(templateId: string, data: {
71
+ body: string;
72
+ block_id?: string;
73
+ parent_id?: string;
74
+ user_id: string;
75
+ user_name: string;
76
+ user_signature: string;
77
+ }, headers?: Record<string, string>): Promise<Comment>;
78
+ updateComment(templateId: string, commentId: string, data: {
79
+ body: string;
80
+ user_id: string;
81
+ user_name: string;
82
+ user_signature: string;
83
+ }, headers?: Record<string, string>): Promise<Comment>;
84
+ deleteComment(templateId: string, commentId: string, data: {
85
+ user_id: string;
86
+ user_name: string;
87
+ user_signature: string;
88
+ }, headers?: Record<string, string>): Promise<void>;
89
+ resolveComment(templateId: string, commentId: string, data: {
90
+ user_id: string;
91
+ user_name: string;
92
+ user_signature: string;
93
+ }, headers?: Record<string, string>): Promise<Comment>;
94
+ fetchConfig(): Promise<PlanConfig>;
95
+ listModules(search?: string): Promise<SavedModule[]>;
96
+ createModule(data: {
97
+ name: string;
98
+ content: Block[];
99
+ }): Promise<SavedModule>;
100
+ updateModule(id: string, data: Partial<{
101
+ name: string;
102
+ content: Block[];
103
+ }>): Promise<SavedModule>;
104
+ deleteModule(id: string): Promise<void>;
105
+ }
106
+
107
+ declare function buildUrl(template: string, params: Record<string, string>): string;
108
+ declare const API_ROUTES: {
109
+ readonly health: "/api/v1/health";
110
+ readonly "projects.config": "/api/v1/projects/{project}/tenants/{tenant}/config";
111
+ readonly "broadcasting.auth": "/api/v1/projects/{project}/tenants/{tenant}/broadcasting/auth";
112
+ readonly "templates.store": "/api/v1/projects/{project}/tenants/{tenant}/templates";
113
+ readonly "templates.show": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}";
114
+ readonly "templates.update": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}";
115
+ readonly "templates.destroy": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}";
116
+ readonly "templates.export": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/export";
117
+ readonly "templates.importFromBeefree": "/api/v1/projects/{project}/tenants/{tenant}/templates/import/from-beefree";
118
+ readonly "templates.sendTestEmail": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/send-test-email";
119
+ readonly "snapshots.index": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/snapshots";
120
+ readonly "snapshots.store": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/snapshots";
121
+ readonly "snapshots.show": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/snapshots/{snapshot}";
122
+ readonly "snapshots.restore": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/snapshots/{snapshot}/restore";
123
+ readonly "comments.index": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/comments";
124
+ readonly "comments.store": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/comments";
125
+ readonly "comments.update": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/comments/{comment}";
126
+ readonly "comments.destroy": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/comments/{comment}";
127
+ readonly "comments.resolve": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/comments/{comment}/resolve";
128
+ readonly "ai.generate": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/ai/generate";
129
+ readonly "ai.conversationMessages": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/ai/conversation-messages";
130
+ readonly "ai.suggestions": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/ai/suggestions";
131
+ readonly "ai.rewriteText": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/ai/rewrite-text";
132
+ readonly "ai.score": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/ai/score";
133
+ readonly "ai.fixFinding": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/ai/fix-finding";
134
+ readonly "ai.generateFromDesign": "/api/v1/projects/{project}/tenants/{tenant}/templates/{template}/ai/generate-from-design";
135
+ readonly "media.upload": "/api/v1/projects/{project}/tenants/{tenant}/media/upload";
136
+ readonly "media.browse": "/api/v1/projects/{project}/tenants/{tenant}/media/browse";
137
+ readonly "media.delete": "/api/v1/projects/{project}/tenants/{tenant}/media/delete";
138
+ readonly "media.move": "/api/v1/projects/{project}/tenants/{tenant}/media/move";
139
+ readonly "media.update": "/api/v1/projects/{project}/tenants/{tenant}/media/{media}";
140
+ readonly "media.replace": "/api/v1/projects/{project}/tenants/{tenant}/media/{media}/replace";
141
+ readonly "media.checkUsage": "/api/v1/projects/{project}/tenants/{tenant}/media/check-usage";
142
+ readonly "media.frequentlyUsed": "/api/v1/projects/{project}/tenants/{tenant}/media/frequently-used";
143
+ readonly "media.importFromUrl": "/api/v1/projects/{project}/tenants/{tenant}/media/import-from-url";
144
+ readonly "folders.index": "/api/v1/projects/{project}/tenants/{tenant}/media/folders";
145
+ readonly "folders.store": "/api/v1/projects/{project}/tenants/{tenant}/media/folders";
146
+ readonly "folders.update": "/api/v1/projects/{project}/tenants/{tenant}/media/folders/{mediaFolder}";
147
+ readonly "folders.destroy": "/api/v1/projects/{project}/tenants/{tenant}/media/folders/{mediaFolder}";
148
+ readonly "savedModules.index": "/api/v1/projects/{project}/tenants/{tenant}/saved-modules";
149
+ readonly "savedModules.store": "/api/v1/projects/{project}/tenants/{tenant}/saved-modules";
150
+ readonly "savedModules.update": "/api/v1/projects/{project}/tenants/{tenant}/saved-modules/{savedModule}";
151
+ readonly "savedModules.destroy": "/api/v1/projects/{project}/tenants/{tenant}/saved-modules/{savedModule}";
152
+ };
153
+
154
+ interface WebSocketConfig {
155
+ host: string;
156
+ port: number;
157
+ appKey: string;
158
+ }
159
+ declare function resolveWebSocketConfig(serverConfig: WebSocketServerConfig): WebSocketConfig;
160
+ interface PresenceMember {
161
+ id: string;
162
+ name: string;
163
+ type: "user" | "mcp";
164
+ }
165
+ interface WebSocketClientOptions {
166
+ authManager: AuthManager;
167
+ config: WebSocketConfig;
168
+ onError?: (error: Error) => void;
169
+ }
170
+ declare class WebSocketClient {
171
+ private pusher;
172
+ private readonly authManager;
173
+ private readonly config;
174
+ private readonly onError?;
175
+ constructor(options: WebSocketClientOptions);
176
+ connect(): Promise<void>;
177
+ subscribePresence(channelName: string): PresenceChannel;
178
+ unsubscribe(channelName: string): void;
179
+ getChannel(channelName: string): Channel | undefined;
180
+ disconnect(): void;
181
+ getSocketId(): string | null;
182
+ get isConnected(): boolean;
183
+ }
184
+
185
+ interface UseEditorOptions {
186
+ authManager: AuthManager;
187
+ defaultFontFamily?: string;
188
+ templateDefaults?: TemplateDefaults;
189
+ onError?: (error: Error) => void;
190
+ lockedBlocks?: Ref<Map<string, unknown>>;
191
+ }
192
+ interface UseEditorReturn {
193
+ state: DeepReadonly<EditorState>;
194
+ content: Ref<TemplateContent>;
195
+ selectedBlock: Ref<Block | null>;
196
+ setContent: (content: TemplateContent, markDirty?: boolean) => void;
197
+ selectBlock: (blockId: string | null) => void;
198
+ setViewport: (viewport: ViewportSize) => void;
199
+ setDarkMode: (darkMode: boolean) => void;
200
+ setPreviewMode: (previewMode: boolean) => void;
201
+ setUiTheme: (theme: UiTheme) => void;
202
+ updateBlock: (blockId: string, updates: Partial<Block>) => void;
203
+ updateSettings: (updates: Partial<TemplateSettings>) => void;
204
+ addBlock: (block: Block, targetSectionId?: string, columnIndex?: number, index?: number) => void;
205
+ removeBlock: (blockId: string) => void;
206
+ moveBlock: (blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number) => void;
207
+ savedBlockIds: Ref<Set<string>>;
208
+ isBlockLocked: (blockId: string) => boolean;
209
+ create: (content?: TemplateContent) => Promise<Template>;
210
+ load: (templateId: string) => Promise<Template>;
211
+ save: () => Promise<Template>;
212
+ createSnapshot: () => Promise<void>;
213
+ hasTemplate: () => boolean;
214
+ markDirty: () => void;
215
+ ensureCanvasPages: () => void;
216
+ switchCanvasPage: (pageId: string) => void;
217
+ addCanvasPage: () => void;
218
+ removeCanvasPage: (pageId: string) => void;
219
+ renameCanvasPage: (pageId: string, title: string) => void;
220
+ switchToNextCanvasPage: () => boolean;
221
+ switchToPreviousCanvasPage: () => boolean;
222
+ }
223
+ declare function useEditor(options: UseEditorOptions): UseEditorReturn;
224
+
225
+ declare function handleOperation(editor: UseEditorReturn, payload: McpOperationPayload): void;
226
+
227
+ interface UseAiChatOptions {
228
+ authManager: AuthManager;
229
+ getTemplateId: () => string | null;
230
+ onApply?: (content: TemplateContent) => void;
231
+ onError?: (error: Error) => void;
232
+ }
233
+ interface UseAiChatReturn {
234
+ messages: ReturnType<typeof ref<AiChatMessage[]>>;
235
+ isGenerating: ReturnType<typeof ref<boolean>>;
236
+ isLoadingHistory: ReturnType<typeof ref<boolean>>;
237
+ isLastChangeReverted: ReturnType<typeof ref<boolean>>;
238
+ lastApplyMessageId: ReturnType<typeof ref<string | null>>;
239
+ error: ReturnType<typeof ref<string | null>>;
240
+ failedPrompt: ReturnType<typeof ref<string | null>>;
241
+ suggestions: ReturnType<typeof ref<string[]>>;
242
+ isLoadingSuggestions: ReturnType<typeof ref<boolean>>;
243
+ sendPrompt: (prompt: string, currentContent: TemplateContent, mergeTags: MergeTag[]) => Promise<TemplateContent | null>;
244
+ toggleLastRevert: () => void;
245
+ loadConversation: () => Promise<void>;
246
+ loadSuggestions: (currentContent: TemplateContent, mergeTags: MergeTag[]) => Promise<void>;
247
+ clearChat: () => void;
248
+ }
249
+ declare function useAiChat(options: UseAiChatOptions): UseAiChatReturn;
250
+
251
+ interface UseAiRewriteOptions {
252
+ authManager: AuthManager;
253
+ getTemplateId: () => string | null;
254
+ }
255
+ interface UseAiRewriteReturn {
256
+ isRewriting: ReturnType<typeof ref<boolean>>;
257
+ streamingText: ReturnType<typeof ref<string>>;
258
+ previousContent: ReturnType<typeof ref<string | null>>;
259
+ rewrittenContent: ReturnType<typeof ref<string | null>>;
260
+ isReverted: ReturnType<typeof ref<boolean>>;
261
+ error: ReturnType<typeof ref<string | null>>;
262
+ rewrite: (content: string, instruction: string, mergeTags: MergeTag[]) => Promise<string | null>;
263
+ undo: () => string | null;
264
+ redo: () => string | null;
265
+ reset: () => void;
266
+ }
267
+ declare function useAiRewrite(options: UseAiRewriteOptions): UseAiRewriteReturn;
268
+
269
+ interface UseAiConfigReturn {
270
+ isFeatureEnabled: (feature: keyof AiConfig) => boolean;
271
+ hasAnyMenuFeature: ComputedRef<boolean>;
272
+ }
273
+ declare function useAiConfig(config?: AiConfig | false): UseAiConfigReturn;
274
+
275
+ interface UseTemplateScoringOptions {
276
+ authManager: AuthManager;
277
+ getTemplateId: () => string | null;
278
+ }
279
+ interface UseTemplateScoringReturn {
280
+ isScoring: ReturnType<typeof ref<boolean>>;
281
+ scoringResult: ReturnType<typeof ref<ScoringResult | null>>;
282
+ error: ReturnType<typeof ref<string | null>>;
283
+ fixingFindingId: ReturnType<typeof ref<string | null>>;
284
+ fixStreamingText: ReturnType<typeof ref<string>>;
285
+ fixError: ReturnType<typeof ref<string | null>>;
286
+ score: (content: TemplateContent, mergeTags: MergeTag[]) => Promise<ScoringResult | null>;
287
+ fixFinding: (blockContent: string, finding: ScoringFinding, mergeTags: MergeTag[]) => Promise<string | null>;
288
+ removeFinding: (category: ScoringCategory, findingId: string) => void;
289
+ reset: () => void;
290
+ }
291
+ declare function useTemplateScoring(options: UseTemplateScoringOptions): UseTemplateScoringReturn;
292
+
293
+ interface UseDesignReferenceOptions {
294
+ authManager: AuthManager;
295
+ getTemplateId: () => string | null;
296
+ onApply?: (content: TemplateContent) => void;
297
+ onError?: (error: Error) => void;
298
+ }
299
+ interface UseDesignReferenceReturn {
300
+ isGenerating: ReturnType<typeof ref<boolean>>;
301
+ error: ReturnType<typeof ref<string | null>>;
302
+ generate: (input: DesignReferenceInput) => Promise<TemplateContent | null>;
303
+ reset: () => void;
304
+ }
305
+ interface DesignReferenceInput {
306
+ prompt?: string;
307
+ imageUpload?: File;
308
+ pdfUpload?: File;
309
+ }
310
+ declare function useDesignReference(options: UseDesignReferenceOptions): UseDesignReferenceReturn;
311
+
312
+ interface UseCommentsOptions {
313
+ authManager: AuthManager;
314
+ getTemplateId: () => string | null;
315
+ getSocketId?: () => string | null;
316
+ onComment?: (event: CommentEvent) => void;
317
+ onError?: (error: Error) => void;
318
+ isAuthReady?: Ref<boolean>;
319
+ hasCommentingFeature?: () => boolean;
320
+ }
321
+ interface UseCommentsReturn {
322
+ comments: Ref<CommentThread[]>;
323
+ isLoading: Ref<boolean>;
324
+ isSubmitting: Ref<boolean>;
325
+ isEnabled: ComputedRef<boolean>;
326
+ commentCountByBlock: ComputedRef<Map<string, number>>;
327
+ totalCount: ComputedRef<number>;
328
+ unresolvedCount: ComputedRef<number>;
329
+ loadComments: () => Promise<void>;
330
+ addComment: (body: string, blockId?: string, parentId?: string) => Promise<Comment | null>;
331
+ editComment: (commentId: string, body: string) => Promise<Comment | null>;
332
+ removeComment: (commentId: string) => Promise<boolean>;
333
+ toggleResolve: (commentId: string) => Promise<Comment | null>;
334
+ applyRemoteCreate: (comment: Comment) => void;
335
+ applyRemoteUpdate: (comment: Comment) => void;
336
+ applyRemoteDelete: (commentId: string, parentId: string | null) => void;
337
+ }
338
+ declare function useComments(options: UseCommentsOptions): UseCommentsReturn;
339
+
340
+ interface CommentBroadcastPayload {
341
+ action: "comment_created" | "comment_updated" | "comment_deleted" | "comment_resolved" | "comment_unresolved";
342
+ comment: Comment;
343
+ }
344
+ interface UseCommentListenerOptions {
345
+ comments: UseCommentsReturn;
346
+ channel: Ref<PresenceChannel | null>;
347
+ }
348
+ declare function useCommentListener(options: UseCommentListenerOptions): void;
349
+
350
+ interface UseCollaborationOptions {
351
+ authManager: AuthManager;
352
+ editor: UseEditorReturn;
353
+ channel: Ref<PresenceChannel | null>;
354
+ onError?: (error: Error) => void;
355
+ onCollaboratorJoined?: (collaborator: Collaborator) => void;
356
+ onCollaboratorLeft?: (collaborator: Collaborator) => void;
357
+ onBlockLocked?: (event: {
358
+ blockId: string;
359
+ collaborator: Collaborator;
360
+ }) => void;
361
+ onBlockUnlocked?: (event: {
362
+ blockId: string;
363
+ collaborator: Collaborator;
364
+ }) => void;
365
+ }
366
+ interface UseCollaborationReturn {
367
+ collaborators: Ref<Collaborator[]>;
368
+ lockedBlocks: Ref<Map<string, Collaborator>>;
369
+ }
370
+ declare function useCollaboration(options: UseCollaborationOptions): UseCollaborationReturn & {
371
+ _broadcastOperation: (payload: McpOperationPayload) => void;
372
+ _isProcessingRemoteOperation: () => boolean;
373
+ };
374
+
375
+ interface BroadcastTarget {
376
+ _broadcastOperation: (payload: McpOperationPayload) => void;
377
+ }
378
+ /**
379
+ * Wraps editor mutation methods to broadcast operations to collaboration
380
+ * peers after each mutation executes. Mutates the editor object in place.
381
+ *
382
+ * Must be applied **before** the history interceptor so the call chain is:
383
+ * history.record() → broadcast + original mutation.
384
+ */
385
+ declare function useCollaborationBroadcast(editor: UseEditorReturn$1, collaboration: BroadcastTarget): void;
386
+
387
+ interface UseWebSocketOptions {
388
+ authManager: AuthManager;
389
+ onError?: (error: Error) => void;
390
+ }
391
+ interface UseWebSocketReturn {
392
+ channel: Ref<PresenceChannel | null>;
393
+ isConnected: Ref<boolean>;
394
+ connect: (templateId: string, config: WebSocketConfig) => Promise<void>;
395
+ disconnect: () => void;
396
+ getSocketId: () => string | null;
397
+ }
398
+ declare function useWebSocket(options: UseWebSocketOptions): UseWebSocketReturn;
399
+
400
+ interface UseSavedModulesOptions {
401
+ authManager: AuthManager;
402
+ onError?: (error: Error) => void;
403
+ }
404
+ interface UseSavedModulesReturn {
405
+ modules: Ref<SavedModule[]>;
406
+ isLoading: Ref<boolean>;
407
+ loadModules: (search?: string) => Promise<void>;
408
+ createModule: (name: string, content: Block[]) => Promise<SavedModule>;
409
+ updateModule: (id: string, data: Partial<{
410
+ name: string;
411
+ content: Block[];
412
+ }>) => Promise<SavedModule>;
413
+ deleteModule: (id: string) => Promise<void>;
414
+ }
415
+ declare function useSavedModules(options: UseSavedModulesOptions): UseSavedModulesReturn;
416
+
417
+ interface UseSnapshotHistoryOptions {
418
+ authManager: AuthManager;
419
+ templateId: string;
420
+ onRestore?: (template: Template) => void;
421
+ onError?: (error: Error) => void;
422
+ }
423
+ interface UseSnapshotHistoryReturn {
424
+ snapshots: Ref<TemplateSnapshot[]>;
425
+ isLoading: Ref<boolean>;
426
+ isRestoring: Ref<boolean>;
427
+ loadSnapshots: () => Promise<void>;
428
+ restoreSnapshot: (snapshotId: string) => Promise<Template>;
429
+ }
430
+ declare function useSnapshotHistory(options: UseSnapshotHistoryOptions): UseSnapshotHistoryReturn;
431
+
432
+ interface UseTestEmailOptions {
433
+ authManager: AuthManager;
434
+ getTemplateId: () => string | null;
435
+ save: () => Promise<Template>;
436
+ exportHtml: (templateId: string) => Promise<ExportResult>;
437
+ onError?: (error: Error) => void;
438
+ isAuthReady?: Ref<boolean>;
439
+ onBeforeTestEmail?: (html: string) => string | Promise<string>;
440
+ }
441
+ interface UseTestEmailReturn {
442
+ isEnabled: ComputedRef<boolean>;
443
+ allowedEmails: ComputedRef<string[]>;
444
+ isSending: Ref<boolean>;
445
+ error: Ref<string | null>;
446
+ sendTestEmail: (recipient: string) => Promise<void>;
447
+ }
448
+ declare function useTestEmail(options: UseTestEmailOptions): UseTestEmailReturn;
449
+
450
+ interface UseExportOptions {
451
+ authManager: AuthManager;
452
+ getFontsConfig?: () => FontsConfig | undefined;
453
+ canUseCustomFonts?: () => boolean;
454
+ }
455
+ interface UseExportReturn {
456
+ exportHtml: (templateId: string) => Promise<ExportResult>;
457
+ getMjmlSource: (templateId: string) => Promise<string>;
458
+ }
459
+ declare function useExport(options: UseExportOptions): UseExportReturn;
460
+
461
+ interface UsePlanConfigOptions {
462
+ authManager: AuthManager;
463
+ onError?: (error: Error) => void;
464
+ }
465
+ interface UsePlanConfigReturn {
466
+ config: Ref<PlanConfig | null>;
467
+ isLoading: Ref<boolean>;
468
+ hasFeature: (feature: keyof PlanFeatures) => boolean;
469
+ features: ComputedRef<PlanFeatures | null>;
470
+ fetchConfig: () => Promise<void>;
471
+ }
472
+ declare function usePlanConfig(options: UsePlanConfigOptions): UsePlanConfigReturn;
473
+
474
+ interface HealthCheckOptions {
475
+ authManager?: AuthManager;
476
+ baseUrl?: string;
477
+ }
478
+ declare function performHealthCheck(options?: HealthCheckOptions): Promise<HealthCheckResult>;
479
+
480
+ interface UseMcpListenerOptions {
481
+ editor: UseEditorReturn;
482
+ channel: Ref<PresenceChannel | null>;
483
+ onOperation?: (payload: McpOperationPayload) => void;
484
+ }
485
+ declare function useMcpListener(options: UseMcpListenerOptions): void;
486
+
487
+ export { API_ROUTES, ApiClient, AuthManager, type CommentBroadcastPayload, type DesignReferenceInput, type PresenceMember, type UseAiChatOptions, type UseAiChatReturn, type UseAiConfigReturn, type UseAiRewriteOptions, type UseAiRewriteReturn, type UseCollaborationOptions, type UseCollaborationReturn, type UseCommentListenerOptions, type UseCommentsOptions, type UseCommentsReturn, type UseDesignReferenceOptions, type UseDesignReferenceReturn, type UseEditorOptions, type UseEditorReturn, type UseExportOptions, type UseExportReturn, type UseMcpListenerOptions, type UsePlanConfigOptions, type UsePlanConfigReturn, type UseSavedModulesOptions, type UseSavedModulesReturn, type UseSnapshotHistoryOptions, type UseSnapshotHistoryReturn, type UseTemplateScoringOptions, type UseTemplateScoringReturn, type UseTestEmailOptions, type UseTestEmailReturn, type UseWebSocketOptions, type UseWebSocketReturn, WebSocketClient, type WebSocketClientOptions, type WebSocketConfig, buildUrl, createSdkAuthManager, handleOperation, performHealthCheck, resolveWebSocketConfig, useAiChat, useAiConfig, useAiRewrite, useCollaboration, useCollaborationBroadcast, useCommentListener, useComments, useDesignReference, useEditor, useExport, useMcpListener, usePlanConfig, useSavedModules, useSnapshotHistory, useTemplateScoring, useTestEmail, useWebSocket };