@aswin.dev/editor 0.6.3 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +3 -3
  2. package/dist/AccessibilityPanel-COL6Wm7p.js +108 -0
  3. package/dist/AiChatSidebar-DWGPVtvC.js +229 -0
  4. package/dist/AiFeatureMenu-duUFSfDf.js +63 -0
  5. package/dist/BlockA11yBadge-Qs6HtXid.js +34 -0
  6. package/dist/CloudEditor-CFldoCOb.js +1207 -0
  7. package/dist/CollaboratorBar-Bw-lbt61.js +95 -0
  8. package/dist/CommentsSidebar-BaD5F53-.js +436 -0
  9. package/dist/CountdownBlock-DaYGxKqo.js +92 -0
  10. package/dist/CountdownToolbar-Dg4F8MTk.js +210 -0
  11. package/dist/DesignReferenceSidebar-BSH7uNP_.js +276 -0
  12. package/dist/LoadingTrack-Ba2pfF57.js +10 -0
  13. package/dist/ModuleBrowserModal-6phxZSKI.js +206 -0
  14. package/dist/ModulePreviewCanvas-BW8L3eQX.js +108 -0
  15. package/dist/NumberWithSuffix-BpUzQOJt.js +422 -0
  16. package/dist/ParagraphEditor-DNSzAB-I.js +695 -0
  17. package/dist/RichTextEditorContent-CrqPQdnk.js +137 -0
  18. package/dist/SaveModuleDialog-zMQTpez7.js +123 -0
  19. package/dist/SnapshotHistory-Do-A5rYU.js +122 -0
  20. package/dist/TemplateScoringPanel-CS7o62zS.js +256 -0
  21. package/dist/TestEmailModal-DGj_9V1u.js +94 -0
  22. package/dist/TitleEditor-C7IDnAoS.js +172 -0
  23. package/dist/TplModal-BAsVzcTb.js +44 -0
  24. package/dist/_plugin-vue_export-helper-BVAJ4lgT.js +8 -0
  25. package/dist/accessibility-BU09xZrQ.js +27 -0
  26. package/dist/blockTypeIcons-C6LDKvmd.js +140 -0
  27. package/dist/bundle-stats.json +10 -0
  28. package/dist/check-DJrpDKO_.js +7 -0
  29. package/dist/chevron-down-C5oBUhT8.js +7 -0
  30. package/dist/chevron-right-BqCptpdp.js +10 -0
  31. package/dist/circle-alert-ZQQc98HC.js +25 -0
  32. package/dist/clock-ik2pRJKG.js +12 -0
  33. package/dist/cloud-6ZmAvF0j.js +1791 -0
  34. package/dist/createLucideIcon-ClREiSx3.js +43 -0
  35. package/dist/de-DWcgp-7T.js +729 -0
  36. package/dist/de-GOtR9DwW.js +207 -0
  37. package/dist/dist-BUzw1buG.js +35 -0
  38. package/dist/dist-BZyY-SS4.js +74 -0
  39. package/dist/dist-BadNx4qo.js +5 -0
  40. package/dist/dist-BesOh2mk.js +35 -0
  41. package/dist/dist-Bz3M4RXG.js +2082 -0
  42. package/dist/dist-C04s_fLA.js +563 -0
  43. package/dist/dist-C3T2AKtB.js +776 -0
  44. package/dist/dist-C9ckKEZL.js +519 -0
  45. package/dist/dist-CBItRG-Z.js +47 -0
  46. package/dist/dist-COSzWQUs.js +5 -0
  47. package/dist/dist-CivF9P8b.js +382 -0
  48. package/dist/dist-DXa1uAMh.js +10658 -0
  49. package/dist/dist-DtiDUrX-.js +189 -0
  50. package/dist/dist-Dzt5foyL.js +61 -0
  51. package/dist/emojiData-DrBuvEoP.js +17 -0
  52. package/dist/en-Cxd4fhNm.js +729 -0
  53. package/dist/en-dFFQVzNn.js +207 -0
  54. package/dist/extensions-D__hOlV1.js +799 -0
  55. package/dist/formatRelativeTime-BhhO8yCl.js +12 -0
  56. package/dist/image-up-DT7gcJLN.js +23 -0
  57. package/dist/index.d.ts +352 -0
  58. package/dist/info-BSPGcsSM.js +19 -0
  59. package/dist/keys-CvX8D-8C.js +10 -0
  60. package/dist/liquid.browser-BvCyLQII.js +3277 -0
  61. package/dist/loader-circle-Balo8p3d.js +7 -0
  62. package/dist/message-circle-B39qAHxs.js +7 -0
  63. package/dist/pencil-BZJPNYWR.js +10 -0
  64. package/dist/readableTextColor-DVuzNX1y.js +30 -0
  65. package/dist/refresh-cw-DwDqGUM0.js +29 -0
  66. package/dist/rolldown-runtime-BZGGJVDF.js +20 -0
  67. package/dist/scan-line-CzfFJO1o.js +25 -0
  68. package/dist/send-D2eSo4GH.js +10 -0
  69. package/dist/shield-check-jkpgcC0-.js +10 -0
  70. package/dist/sparkles-Chm5CZfb.js +23 -0
  71. package/dist/style.css +2 -0
  72. package/dist/styleConstants-34eUKPOZ.js +55 -0
  73. package/dist/styles-B4tjX5SP.js +5224 -0
  74. package/dist/templatical-editor.js +312 -0
  75. package/dist/text-align-start-CzBnJsW8.js +43 -0
  76. package/dist/timeouts-BSGxjuUF.js +4 -0
  77. package/dist/trash-2-CtK2apEH.js +25 -0
  78. package/dist/triangle-alert-KpDVNbpn.js +17 -0
  79. package/dist/useCloudI18n-DOKSZql1.js +23 -0
  80. package/dist/useEditorCore-wslttMH-.js +9517 -0
  81. package/dist/useI18n-C2xQZ6K9.js +17 -0
  82. package/dist/useMergeTag-DX0XG5V9.js +34 -0
  83. package/dist/vue.runtime.esm-bundler-CjauPXjj.js +5775 -0
  84. package/dist/x-BkaOMosX.js +10 -0
  85. package/package.json +10 -10
@@ -0,0 +1,1791 @@
1
+ import { $ as e, Q as t, V as n, Z as r, et as i, m as a } from "./vue.runtime.esm-bundler-CjauPXjj.js";
2
+ import { N as o, a as s, p as c } from "./dist-C04s_fLA.js";
3
+ //#region ../core/dist/cloud/index.js
4
+ var l = class e {
5
+ static DEFAULT_BASE_URL = "https://templatical.com";
6
+ accessToken = null;
7
+ expiresAt = null;
8
+ _projectId = null;
9
+ _tenantId = null;
10
+ _tenantSlug = null;
11
+ _testEmailConfig = null;
12
+ _userConfig = null;
13
+ url;
14
+ baseUrl;
15
+ requestOptions;
16
+ onError;
17
+ refreshPromise = null;
18
+ static REFRESH_THRESHOLD_MS = 60 * 1e3;
19
+ constructor(t) {
20
+ this.url = t.url, this.baseUrl = (t.baseUrl ?? e.DEFAULT_BASE_URL).replace(/\/$/, ""), this.requestOptions = t.requestOptions ?? {}, this.onError = t.onError;
21
+ }
22
+ resolveUrl(e) {
23
+ if (e.startsWith("http://") || e.startsWith("https://")) return e;
24
+ let t = e.startsWith("/") ? e : `/${e}`;
25
+ return `${this.baseUrl}${t}`;
26
+ }
27
+ get projectId() {
28
+ if (!this._projectId) throw Error("Project ID not available. Call initialize() first.");
29
+ return this._projectId;
30
+ }
31
+ get tenantId() {
32
+ if (!this._tenantId) throw Error("Tenant ID not available. Call initialize() first.");
33
+ return this._tenantId;
34
+ }
35
+ get tenantSlug() {
36
+ if (!this._tenantSlug) throw Error("Tenant slug not available. Call initialize() first.");
37
+ return this._tenantSlug;
38
+ }
39
+ get testEmailConfig() {
40
+ return this._testEmailConfig;
41
+ }
42
+ get userConfig() {
43
+ return this._userConfig;
44
+ }
45
+ get accessTokenValue() {
46
+ return this.accessToken;
47
+ }
48
+ async initialize() {
49
+ await this.ensureToken();
50
+ }
51
+ async ensureToken() {
52
+ return this.accessToken && !this.isTokenExpiringSoon() ? this.accessToken : this.refreshToken();
53
+ }
54
+ isTokenExpiringSoon() {
55
+ return this.expiresAt ? this.expiresAt.getTime() - Date.now() < e.REFRESH_THRESHOLD_MS : !0;
56
+ }
57
+ async refreshToken() {
58
+ if (this.refreshPromise) return this.refreshPromise;
59
+ this.refreshPromise = this.performRefresh();
60
+ try {
61
+ return await this.refreshPromise;
62
+ } finally {
63
+ this.refreshPromise = null;
64
+ }
65
+ }
66
+ async performRefresh() {
67
+ try {
68
+ let e = this.requestOptions.method ?? "POST", t = {
69
+ Accept: "application/json",
70
+ ...this.requestOptions.headers
71
+ }, n = {
72
+ method: e,
73
+ headers: t,
74
+ credentials: this.requestOptions.credentials ?? "include"
75
+ };
76
+ e === "POST" && this.requestOptions.body && (t["Content-Type"] = "application/json", n.body = JSON.stringify(this.requestOptions.body));
77
+ let r = await fetch(this.url, n);
78
+ if (!r.ok) throw new s(`Token refresh failed: ${r.status}`, r.status);
79
+ let i = await r.json();
80
+ if (!i.token || !i.expires_at || !i.project_id || !i.tenant) throw Error("Invalid token response: missing token, expires_at, project_id, or tenant");
81
+ return this.accessToken = i.token, this.expiresAt = /* @__PURE__ */ new Date(i.expires_at * 1e3), this._projectId = i.project_id, this._tenantSlug = i.tenant, i.test_email?.allowed_emails && i.test_email?.signature ? this._testEmailConfig = {
82
+ allowedEmails: i.test_email.allowed_emails,
83
+ signature: i.test_email.signature
84
+ } : this._testEmailConfig = null, i.user?.id && i.user?.name && i.user?.signature ? this._userConfig = {
85
+ id: i.user.id,
86
+ name: i.user.name,
87
+ signature: i.user.signature
88
+ } : this._userConfig = null, this.accessToken;
89
+ } catch (e) {
90
+ let t = e instanceof Error ? e : Error("Token refresh failed", { cause: e });
91
+ throw this.onError?.(t), t;
92
+ }
93
+ }
94
+ async authenticatedFetch(e, t = {}) {
95
+ let n = await this.ensureToken(), r = this.resolveUrl(e), i = async (e) => fetch(r, {
96
+ ...t,
97
+ headers: {
98
+ ...t.headers,
99
+ Authorization: `Bearer ${e}`
100
+ }
101
+ }), a = await i(n);
102
+ return a.status === 401 && (a = await i(await this.refreshToken())), a;
103
+ }
104
+ };
105
+ function u(e, t) {
106
+ return e.replace(/\{(\w+)\}/g, (e, n) => encodeURIComponent(t[n] ?? ""));
107
+ }
108
+ var d = "/api/v1/projects/{project}/tenants/{tenant}", f = `${d}/templates/{template}`, p = `${f}/ai`, m = `${d}/media`, h = `${m}/folders`, g = `${d}/saved-modules`, _ = {
109
+ health: "/api/v1/health",
110
+ "projects.config": `${d}/config`,
111
+ "broadcasting.auth": `${d}/broadcasting/auth`,
112
+ "templates.store": `${d}/templates`,
113
+ "templates.show": `${f}`,
114
+ "templates.update": `${f}`,
115
+ "templates.destroy": `${f}`,
116
+ "templates.export": `${f}/export`,
117
+ "templates.importFromBeefree": `${d}/templates/import/from-beefree`,
118
+ "templates.sendTestEmail": `${f}/send-test-email`,
119
+ "snapshots.index": `${f}/snapshots`,
120
+ "snapshots.store": `${f}/snapshots`,
121
+ "snapshots.show": `${f}/snapshots/{snapshot}`,
122
+ "snapshots.restore": `${f}/snapshots/{snapshot}/restore`,
123
+ "comments.index": `${f}/comments`,
124
+ "comments.store": `${f}/comments`,
125
+ "comments.update": `${f}/comments/{comment}`,
126
+ "comments.destroy": `${f}/comments/{comment}`,
127
+ "comments.resolve": `${f}/comments/{comment}/resolve`,
128
+ "ai.generate": `${p}/generate`,
129
+ "ai.conversationMessages": `${p}/conversation-messages`,
130
+ "ai.suggestions": `${p}/suggestions`,
131
+ "ai.rewriteText": `${p}/rewrite-text`,
132
+ "ai.score": `${p}/score`,
133
+ "ai.fixFinding": `${p}/fix-finding`,
134
+ "ai.generateFromDesign": `${p}/generate-from-design`,
135
+ "media.upload": `${m}/upload`,
136
+ "media.browse": `${m}/browse`,
137
+ "media.delete": `${m}/delete`,
138
+ "media.move": `${m}/move`,
139
+ "media.update": `${m}/{media}`,
140
+ "media.replace": `${m}/{media}/replace`,
141
+ "media.checkUsage": `${m}/check-usage`,
142
+ "media.frequentlyUsed": `${m}/frequently-used`,
143
+ "media.importFromUrl": `${m}/import-from-url`,
144
+ "folders.index": `${h}`,
145
+ "folders.store": `${h}`,
146
+ "folders.update": `${h}/{mediaFolder}`,
147
+ "folders.destroy": `${h}/{mediaFolder}`,
148
+ "savedModules.index": `${g}`,
149
+ "savedModules.store": `${g}`,
150
+ "savedModules.update": `${g}/{savedModule}`,
151
+ "savedModules.destroy": `${g}/{savedModule}`
152
+ }, v = class {
153
+ constructor(e) {
154
+ this.authManager = e;
155
+ }
156
+ authManager;
157
+ get projectId() {
158
+ return this.authManager.projectId;
159
+ }
160
+ get tenantSlug() {
161
+ return this.authManager.tenantSlug;
162
+ }
163
+ get baseParams() {
164
+ return {
165
+ project: this.projectId,
166
+ tenant: this.tenantSlug
167
+ };
168
+ }
169
+ async request(e, t = {}) {
170
+ let n = await this.authManager.authenticatedFetch(e, {
171
+ ...t,
172
+ headers: {
173
+ "Content-Type": "application/json",
174
+ Accept: "application/json",
175
+ ...t.headers
176
+ }
177
+ });
178
+ if (!n.ok) {
179
+ let e = await n.json().catch(() => ({ message: `HTTP error ${n.status}` }));
180
+ throw new s(this.extractFirstValidationError(e), n.status);
181
+ }
182
+ if (n.status !== 204) return (await n.json()).data;
183
+ }
184
+ extractFirstValidationError(e) {
185
+ if (e.errors) {
186
+ let t = Object.keys(e.errors)[0];
187
+ if (t && e.errors[t]?.length > 0) return e.errors[t][0];
188
+ }
189
+ return e.message;
190
+ }
191
+ async createTemplate(e) {
192
+ return this.request(u(_["templates.store"], this.baseParams), {
193
+ method: "POST",
194
+ body: JSON.stringify({ content: e })
195
+ });
196
+ }
197
+ async getTemplate(e) {
198
+ return this.request(u(_["templates.show"], {
199
+ ...this.baseParams,
200
+ template: e
201
+ }));
202
+ }
203
+ async updateTemplate(e, t) {
204
+ return this.request(u(_["templates.update"], {
205
+ ...this.baseParams,
206
+ template: e
207
+ }), {
208
+ method: "PUT",
209
+ body: JSON.stringify({ content: t })
210
+ });
211
+ }
212
+ async createSnapshot(e, t) {
213
+ return this.request(u(_["snapshots.store"], {
214
+ ...this.baseParams,
215
+ template: e
216
+ }), {
217
+ method: "POST",
218
+ body: JSON.stringify({ content: t })
219
+ });
220
+ }
221
+ async deleteTemplate(e) {
222
+ return this.request(u(_["templates.destroy"], {
223
+ ...this.baseParams,
224
+ template: e
225
+ }), { method: "DELETE" });
226
+ }
227
+ async getSnapshots(e) {
228
+ return this.request(u(_["snapshots.index"], {
229
+ ...this.baseParams,
230
+ template: e
231
+ }));
232
+ }
233
+ async restoreSnapshot(e, t) {
234
+ return this.request(u(_["snapshots.restore"], {
235
+ ...this.baseParams,
236
+ template: e,
237
+ snapshot: t
238
+ }), { method: "POST" });
239
+ }
240
+ async exportTemplate(e, t) {
241
+ let n = t ? JSON.stringify({
242
+ custom_fonts: t.customFonts,
243
+ default_fallback: t.defaultFallback
244
+ }) : void 0;
245
+ return this.request(u(_["templates.export"], {
246
+ ...this.baseParams,
247
+ template: e
248
+ }), {
249
+ method: "POST",
250
+ body: n
251
+ });
252
+ }
253
+ async sendTestEmail(e, t) {
254
+ await this.request(u(_["templates.sendTestEmail"], {
255
+ ...this.baseParams,
256
+ template: e
257
+ }), {
258
+ method: "POST",
259
+ body: JSON.stringify(t)
260
+ });
261
+ }
262
+ commentsUrl(e, t) {
263
+ return t ? u(_["comments.update"], {
264
+ ...this.baseParams,
265
+ template: e,
266
+ comment: t
267
+ }) : u(_["comments.index"], {
268
+ ...this.baseParams,
269
+ template: e
270
+ });
271
+ }
272
+ async getComments(e) {
273
+ return this.request(this.commentsUrl(e));
274
+ }
275
+ async createComment(e, t, n) {
276
+ return this.request(this.commentsUrl(e), {
277
+ method: "POST",
278
+ body: JSON.stringify(t),
279
+ headers: n
280
+ });
281
+ }
282
+ async updateComment(e, t, n, r) {
283
+ return this.request(this.commentsUrl(e, t), {
284
+ method: "PUT",
285
+ body: JSON.stringify(n),
286
+ headers: r
287
+ });
288
+ }
289
+ async deleteComment(e, t, n, r) {
290
+ return this.request(this.commentsUrl(e, t), {
291
+ method: "DELETE",
292
+ body: JSON.stringify(n),
293
+ headers: r
294
+ });
295
+ }
296
+ async resolveComment(e, t, n, r) {
297
+ return this.request(u(_["comments.resolve"], {
298
+ ...this.baseParams,
299
+ template: e,
300
+ comment: t
301
+ }), {
302
+ method: "POST",
303
+ body: JSON.stringify(n),
304
+ headers: r
305
+ });
306
+ }
307
+ async fetchConfig() {
308
+ return this.request(u(_["projects.config"], this.baseParams));
309
+ }
310
+ async listModules(e) {
311
+ let t = u(_["savedModules.index"], this.baseParams), n = e ? `?search=${encodeURIComponent(e)}` : "";
312
+ return this.request(`${t}${n}`);
313
+ }
314
+ async createModule(e) {
315
+ return this.request(u(_["savedModules.store"], this.baseParams), {
316
+ method: "POST",
317
+ body: JSON.stringify(e)
318
+ });
319
+ }
320
+ async updateModule(e, t) {
321
+ return this.request(u(_["savedModules.update"], {
322
+ ...this.baseParams,
323
+ savedModule: e
324
+ }), {
325
+ method: "PUT",
326
+ body: JSON.stringify(t)
327
+ });
328
+ }
329
+ async deleteModule(e) {
330
+ return this.request(u(_["savedModules.destroy"], {
331
+ ...this.baseParams,
332
+ savedModule: e
333
+ }), { method: "DELETE" });
334
+ }
335
+ };
336
+ function y(e) {
337
+ return {
338
+ host: e.host,
339
+ port: e.port,
340
+ appKey: e.app_key
341
+ };
342
+ }
343
+ var b = class {
344
+ pusher = null;
345
+ authManager;
346
+ config;
347
+ onError;
348
+ constructor(e) {
349
+ this.authManager = e.authManager, this.config = e.config, this.onError = e.onError;
350
+ }
351
+ async connect() {
352
+ if (this.pusher) return;
353
+ let e;
354
+ try {
355
+ ({default: e} = await import("pusher-js"));
356
+ } catch {
357
+ throw Error("Cloud features require the optional peer dependency 'pusher-js'. Install it with: npm install pusher-js");
358
+ }
359
+ let { host: t, port: n, appKey: r } = this.config, i = this.authManager.resolveUrl(u(_["broadcasting.auth"], {
360
+ project: this.authManager.projectId,
361
+ tenant: this.authManager.tenantSlug
362
+ }));
363
+ this.pusher = new e(r, {
364
+ wsHost: t,
365
+ wsPort: n,
366
+ wssPort: n,
367
+ forceTLS: !0,
368
+ disableStats: !0,
369
+ enabledTransports: ["ws", "wss"],
370
+ cluster: "",
371
+ channelAuthorization: {
372
+ transport: "ajax",
373
+ endpoint: i,
374
+ headers: {
375
+ Authorization: `Bearer ${this.authManager.accessTokenValue}`,
376
+ Accept: "application/json"
377
+ },
378
+ params: {
379
+ user_id: this.authManager.userConfig?.id ?? "",
380
+ user_name: this.authManager.userConfig?.name ?? "",
381
+ user_signature: this.authManager.userConfig?.signature ?? ""
382
+ }
383
+ }
384
+ }), this.pusher.connection.bind("error", (e) => {
385
+ this.onError?.(e instanceof Error ? e : /* @__PURE__ */ Error("WebSocket connection error"));
386
+ });
387
+ }
388
+ subscribePresence(e) {
389
+ if (!this.pusher) throw Error("WebSocketClient not connected. Call connect() first.");
390
+ return this.pusher.subscribe(e);
391
+ }
392
+ unsubscribe(e) {
393
+ this.pusher?.unsubscribe(e);
394
+ }
395
+ getChannel(e) {
396
+ return this.pusher?.channel(e);
397
+ }
398
+ disconnect() {
399
+ this.pusher &&= (this.pusher.disconnect(), null);
400
+ }
401
+ getSocketId() {
402
+ return this.pusher?.connection.socket_id ?? null;
403
+ }
404
+ get isConnected() {
405
+ return this.pusher?.connection.state === "connected";
406
+ }
407
+ };
408
+ function x(e, t) {
409
+ let { operation: n, data: r } = t;
410
+ switch (n) {
411
+ case "add_block":
412
+ e.addBlock(r.block, r.section_id, r.column_index, r.index);
413
+ break;
414
+ case "update_block":
415
+ e.updateBlock(r.block_id, r.updates);
416
+ break;
417
+ case "delete_block":
418
+ e.removeBlock(r.block_id);
419
+ break;
420
+ case "move_block":
421
+ e.moveBlock(r.block_id, r.index, r.section_id, r.column_index);
422
+ break;
423
+ case "update_settings":
424
+ e.updateSettings(r.updates);
425
+ break;
426
+ case "set_content":
427
+ e.setContent(r.content);
428
+ break;
429
+ case "update_block_style":
430
+ e.updateBlock(r.block_id, { styles: r.styles });
431
+ break;
432
+ }
433
+ }
434
+ function S(n) {
435
+ let r = new v(n.authManager), i = t({
436
+ template: null,
437
+ content: o(c(n.defaultFontFamily, n.templateDefaults)),
438
+ selectedBlockId: null,
439
+ viewport: "desktop",
440
+ darkMode: !1,
441
+ previewMode: !1,
442
+ isDirty: !1,
443
+ isSaving: !1,
444
+ isLoading: !1,
445
+ uiTheme: "auto"
446
+ }), l = a({
447
+ get: () => i.content,
448
+ set: (e) => {
449
+ i.content = o(e), i.isDirty = !0;
450
+ }
451
+ }), u = a(() => i.selectedBlockId ? f(i.content.blocks, i.selectedBlockId) : null), d = a(() => {
452
+ let e = /* @__PURE__ */ new Set(), t = i.template?.content?.blocks;
453
+ if (!t) return e;
454
+ for (let n of t) if (e.add(n.id), n.type === "section") for (let t of n.children) for (let n of t) e.add(n.id);
455
+ return e;
456
+ });
457
+ function f(e, t) {
458
+ for (let n of e) {
459
+ if (n.id === t) return n;
460
+ if (n.type === "section") for (let e of n.children) {
461
+ let n = f(e, t);
462
+ if (n) return n;
463
+ }
464
+ }
465
+ return null;
466
+ }
467
+ function p(e, t, n = { blocks: e }) {
468
+ for (let r = 0; r < e.length; r++) {
469
+ let i = e[r];
470
+ if (i.id === t) return n;
471
+ if (i.type === "section") for (let e = 0; e < i.children.length; e++) {
472
+ let n = p(i.children[e], t, {
473
+ blocks: i.children[e],
474
+ sectionId: i.id,
475
+ columnIndex: e
476
+ });
477
+ if (n) return n;
478
+ }
479
+ }
480
+ return null;
481
+ }
482
+ function m(e) {
483
+ return n.lockedBlocks?.value.has(e) ?? !1;
484
+ }
485
+ function h(e, t = !0) {
486
+ i.content = o(e), t && (i.isDirty = !0);
487
+ }
488
+ function g(e) {
489
+ e && m(e) || (i.selectedBlockId = e);
490
+ }
491
+ function _(e) {
492
+ i.viewport = e;
493
+ }
494
+ function y(e) {
495
+ i.darkMode = e;
496
+ }
497
+ function b(e) {
498
+ i.uiTheme = e;
499
+ }
500
+ function x(e) {
501
+ i.previewMode = e, e && (i.selectedBlockId = null);
502
+ }
503
+ function S(e, t) {
504
+ if (m(e)) return;
505
+ let n = f(i.content.blocks, e);
506
+ n && (Object.assign(n, t), i.isDirty = !0);
507
+ }
508
+ function C(e) {
509
+ i.content.settings = {
510
+ ...i.content.settings,
511
+ ...e
512
+ }, i.isDirty = !0;
513
+ }
514
+ function w(e, t, n = 0, r) {
515
+ if (t) {
516
+ let a = f(i.content.blocks, t);
517
+ if (a && a.type === "section") {
518
+ a.children[n] = a.children[n] || [];
519
+ let t = a.children[n];
520
+ r !== void 0 && r < t.length ? t.splice(r, 0, e) : t.push(e);
521
+ }
522
+ } else r !== void 0 && r < i.content.blocks.length ? i.content.blocks.splice(r, 0, e) : i.content.blocks.push(e);
523
+ i.isDirty = !0;
524
+ }
525
+ function T(e) {
526
+ if (m(e)) return;
527
+ let t = p(i.content.blocks, e);
528
+ if (t) {
529
+ let n = t.blocks.findIndex((t) => t.id === e);
530
+ n !== -1 && (t.blocks.splice(n, 1), i.selectedBlockId === e && (i.selectedBlockId = null), i.isDirty = !0);
531
+ }
532
+ }
533
+ function E(e, t, n, r = 0) {
534
+ let a = p(i.content.blocks, e);
535
+ if (!a) return;
536
+ let o = a.blocks.findIndex((t) => t.id === e);
537
+ if (o === -1) return;
538
+ let [s] = a.blocks.splice(o, 1);
539
+ if (n) {
540
+ let e = f(i.content.blocks, n);
541
+ e && e.type === "section" && (e.children[r] = e.children[r] || [], e.children[r].splice(t, 0, s));
542
+ } else i.content.blocks.splice(t, 0, s);
543
+ i.isDirty = !0;
544
+ }
545
+ async function D(e) {
546
+ i.isLoading = !0;
547
+ try {
548
+ e && (i.content = o(e));
549
+ let t = await r.createTemplate(i.content);
550
+ return i.template = t, i.isDirty = !1, t;
551
+ } catch (e) {
552
+ throw n.onError?.(e), e;
553
+ } finally {
554
+ i.isLoading = !1;
555
+ }
556
+ }
557
+ async function O(e) {
558
+ i.isLoading = !0;
559
+ try {
560
+ let t = await r.getTemplate(e);
561
+ return i.template = t, i.content = o(t.content), i.isDirty = !1, t;
562
+ } catch (e) {
563
+ throw n.onError?.(e), e;
564
+ } finally {
565
+ i.isLoading = !1;
566
+ }
567
+ }
568
+ async function k() {
569
+ if (!i.template?.id) throw new s("No template loaded. Call create() or load() before saving.");
570
+ i.isSaving = !0;
571
+ try {
572
+ let e = await r.updateTemplate(i.template.id, i.content);
573
+ return i.template = e, i.isDirty = !1, e;
574
+ } catch (e) {
575
+ throw n.onError?.(e), e;
576
+ } finally {
577
+ i.isSaving = !1;
578
+ }
579
+ }
580
+ async function A() {
581
+ if (i.template?.id) try {
582
+ await r.createSnapshot(i.template.id, i.content);
583
+ } catch (e) {
584
+ throw n.onError?.(e), e;
585
+ }
586
+ }
587
+ function j() {
588
+ return i.template?.id !== void 0;
589
+ }
590
+ function M() {
591
+ i.isDirty = !0;
592
+ }
593
+ function N() {
594
+ if (i.content.canvasPages?.length) return;
595
+ let e = crypto.randomUUID(), t = i.content.blocks;
596
+ i.content.canvasPages = [{
597
+ id: e,
598
+ title: "Step 1",
599
+ blocks: t
600
+ }], i.content.activeCanvasPageId = e, i.content.blocks = t, i.isDirty = !0;
601
+ }
602
+ function P(e) {
603
+ let t = i.content.canvasPages;
604
+ if (!t?.length) return;
605
+ let n = t.find((t) => t.id === e);
606
+ n && (i.selectedBlockId = null, i.content.blocks = n.blocks, i.content.activeCanvasPageId = e, i.isDirty = !0);
607
+ }
608
+ function F() {
609
+ N();
610
+ let e = i.content.canvasPages, t = crypto.randomUUID(), n = `Step ${e.length + 1}`;
611
+ e.push({
612
+ id: t,
613
+ title: n,
614
+ blocks: []
615
+ }), P(t);
616
+ }
617
+ function I(e) {
618
+ let t = i.content.canvasPages;
619
+ if (!t || t.length <= 1) return;
620
+ let n = t.findIndex((t) => t.id === e);
621
+ if (n !== -1) if (t.splice(n, 1), i.content.activeCanvasPageId === e) {
622
+ let e = t[Math.min(n, t.length - 1)];
623
+ P(e.id);
624
+ } else i.content.canvasPages = [...t], i.isDirty = !0;
625
+ }
626
+ function L(e, t) {
627
+ let n = i.content.canvasPages;
628
+ if (!n) return;
629
+ let r = n.find((t) => t.id === e);
630
+ r && (r.title = t.trim() || r.title, i.isDirty = !0);
631
+ }
632
+ function R() {
633
+ let e = i.content.canvasPages;
634
+ if (!e?.length) return !1;
635
+ let t = i.content.activeCanvasPageId, n = e.findIndex((e) => e.id === t);
636
+ return n === -1 || n >= e.length - 1 ? !1 : (P(e[n + 1].id), !0);
637
+ }
638
+ function z() {
639
+ let e = i.content.canvasPages;
640
+ if (!e?.length) return !1;
641
+ let t = i.content.activeCanvasPageId, n = e.findIndex((e) => e.id === t);
642
+ return n <= 0 ? !1 : (P(e[n - 1].id), !0);
643
+ }
644
+ return {
645
+ state: e(i),
646
+ content: l,
647
+ selectedBlock: u,
648
+ savedBlockIds: d,
649
+ isBlockLocked: m,
650
+ setContent: h,
651
+ selectBlock: g,
652
+ setViewport: _,
653
+ setDarkMode: y,
654
+ setUiTheme: b,
655
+ setPreviewMode: x,
656
+ updateBlock: S,
657
+ updateSettings: C,
658
+ addBlock: w,
659
+ removeBlock: T,
660
+ moveBlock: E,
661
+ create: D,
662
+ load: O,
663
+ save: k,
664
+ createSnapshot: A,
665
+ hasTemplate: j,
666
+ markDirty: M,
667
+ ensureCanvasPages: N,
668
+ switchCanvasPage: P,
669
+ addCanvasPage: F,
670
+ removeCanvasPage: I,
671
+ renameCanvasPage: L,
672
+ switchToNextCanvasPage: R,
673
+ switchToPreviousCanvasPage: z
674
+ };
675
+ }
676
+ var C = 0;
677
+ function w() {
678
+ return `msg_${Date.now()}_${++C}`;
679
+ }
680
+ function T(e) {
681
+ let { authManager: t, getTemplateId: n, onApply: r, onError: a } = e, o = i([]), s = i(!1), c = i(!1), l = i(null), d = i(null), f = i(null), p = i(null), m = i(null), h = i(null), g = i(!1), v = i([]), y = i(!1);
682
+ function b(e, t) {
683
+ let n = o.value.findIndex((t) => t.id === e);
684
+ if (n === -1) return;
685
+ let r = {
686
+ ...o.value[n],
687
+ ...t
688
+ };
689
+ o.value = [
690
+ ...o.value.slice(0, n),
691
+ r,
692
+ ...o.value.slice(n + 1)
693
+ ];
694
+ }
695
+ async function x() {
696
+ let e = n();
697
+ if (e) {
698
+ c.value = !0;
699
+ try {
700
+ let n = u(_["ai.conversationMessages"], {
701
+ project: t.projectId,
702
+ tenant: t.tenantSlug,
703
+ template: e
704
+ }), r = await t.authenticatedFetch(n, {
705
+ method: "GET",
706
+ headers: { Accept: "application/json" }
707
+ });
708
+ if (!r.ok) return;
709
+ let i = await r.json();
710
+ i.conversation_id && (f.value = i.conversation_id), Array.isArray(i.data) && i.data.length > 0 && (o.value = i.data.map((e) => ({
711
+ id: e.id,
712
+ role: e.role,
713
+ content: e.content,
714
+ timestamp: new Date(e.created_at).getTime()
715
+ })));
716
+ } catch {} finally {
717
+ c.value = !1;
718
+ }
719
+ }
720
+ }
721
+ async function S(e, r) {
722
+ let i = n();
723
+ if (i) {
724
+ y.value = !0;
725
+ try {
726
+ let n = u(_["ai.suggestions"], {
727
+ project: t.projectId,
728
+ tenant: t.tenantSlug,
729
+ template: i
730
+ }), a = await t.authenticatedFetch(n, {
731
+ method: "POST",
732
+ headers: {
733
+ "Content-Type": "application/json",
734
+ Accept: "text/event-stream"
735
+ },
736
+ body: JSON.stringify({
737
+ current_content: e,
738
+ merge_tags: r.map((e) => ({
739
+ label: e.label,
740
+ value: e.value
741
+ }))
742
+ })
743
+ });
744
+ if (!a.ok) return;
745
+ let o = a.body?.getReader();
746
+ if (!o) return;
747
+ let s = new TextDecoder(), c = "";
748
+ for (;;) {
749
+ let { done: e, value: t } = await o.read();
750
+ if (e) break;
751
+ c += s.decode(t, { stream: !0 });
752
+ let n = c.split("\n");
753
+ c = n.pop() ?? "";
754
+ for (let e of n) {
755
+ if (!e.startsWith("data: ")) continue;
756
+ let t;
757
+ try {
758
+ t = JSON.parse(e.slice(6));
759
+ } catch {
760
+ continue;
761
+ }
762
+ t.type === "done" && Array.isArray(t.suggestions) && (v.value = t.suggestions.slice(0, 3));
763
+ }
764
+ }
765
+ } catch {} finally {
766
+ y.value = !1;
767
+ }
768
+ }
769
+ }
770
+ async function C(e, i, c) {
771
+ let y = n();
772
+ if (!y) throw Error("Template must be saved before using AI generation");
773
+ s.value = !0, l.value = null, d.value = null, v.value = [];
774
+ let x = w();
775
+ o.value = [...o.value, {
776
+ id: x,
777
+ role: "user",
778
+ content: e,
779
+ timestamp: Date.now()
780
+ }];
781
+ let S = w();
782
+ o.value = [...o.value, {
783
+ id: S,
784
+ role: "assistant",
785
+ content: "",
786
+ timestamp: Date.now()
787
+ }];
788
+ try {
789
+ let n = u(_["ai.generate"], {
790
+ project: t.projectId,
791
+ tenant: t.tenantSlug,
792
+ template: y
793
+ }), a = await t.authenticatedFetch(n, {
794
+ method: "POST",
795
+ headers: {
796
+ "Content-Type": "application/json",
797
+ Accept: "text/event-stream"
798
+ },
799
+ body: JSON.stringify({
800
+ prompt: e,
801
+ current_content: i,
802
+ merge_tags: c.map((e) => ({
803
+ label: e.label,
804
+ value: e.value
805
+ })),
806
+ conversation_id: f.value
807
+ })
808
+ });
809
+ if (!a.ok) {
810
+ let e = await a.json().catch(() => null);
811
+ throw a.status === 403 ? Error("ai_generation_not_available") : Error(e?.message || "Failed to generate template");
812
+ }
813
+ let s = a.body?.getReader();
814
+ if (!s) throw Error("Failed to read stream");
815
+ let d = new TextDecoder(), v = "", x = null;
816
+ try {
817
+ for (;;) {
818
+ let { done: e, value: t } = await s.read();
819
+ if (e) break;
820
+ v += d.decode(t, { stream: !0 });
821
+ let n = v.split("\n");
822
+ v = n.pop() ?? "";
823
+ for (let e of n) {
824
+ if (!e.startsWith("data: ")) continue;
825
+ let t = e.slice(6), n;
826
+ try {
827
+ n = JSON.parse(t);
828
+ } catch {
829
+ continue;
830
+ }
831
+ if (n.type === "text") b(S, { content: (o.value.find((e) => e.id === S)?.content ?? "") + n.text });
832
+ else if (n.type === "error") throw Error(n.message || "Failed to generate template");
833
+ else n.type === "done" && (n.conversation_id && (f.value = n.conversation_id), b(S, { content: n.text }), x = n.content ?? null, x ? (m.value = i, h.value = x, p.value = S, g.value = !1, r?.(x)) : l.value = "ai_apply_failed");
834
+ }
835
+ }
836
+ } finally {
837
+ s.cancel().catch(() => {});
838
+ }
839
+ return x;
840
+ } catch (t) {
841
+ let n = t instanceof Error ? t : Error("Failed to generate template", { cause: t });
842
+ return l.value = n.message, d.value = e, a?.(n), o.value = o.value.filter((e) => e.id !== x && e.id !== S), null;
843
+ } finally {
844
+ s.value = !1;
845
+ }
846
+ }
847
+ function T() {
848
+ g.value ? (h.value && r?.(h.value), g.value = !1) : (m.value && r?.(m.value), g.value = !0);
849
+ }
850
+ function E() {
851
+ o.value = [], f.value = null, l.value = null, p.value = null, m.value = null, h.value = null, g.value = !1;
852
+ }
853
+ return {
854
+ messages: o,
855
+ isGenerating: s,
856
+ isLoadingHistory: c,
857
+ isLastChangeReverted: g,
858
+ lastApplyMessageId: p,
859
+ error: l,
860
+ failedPrompt: d,
861
+ suggestions: v,
862
+ isLoadingSuggestions: y,
863
+ sendPrompt: C,
864
+ toggleLastRevert: T,
865
+ loadConversation: x,
866
+ loadSuggestions: S,
867
+ clearChat: E
868
+ };
869
+ }
870
+ function E(e) {
871
+ function t(t) {
872
+ return e === !1 ? !1 : e?.[t] !== !1;
873
+ }
874
+ return {
875
+ isFeatureEnabled: t,
876
+ hasAnyMenuFeature: a(() => t("chat") || t("scoring") || t("designToTemplate"))
877
+ };
878
+ }
879
+ function D(e) {
880
+ let { authManager: t, getTemplateId: n } = e, r = i(!1), a = i(null), o = i(null), s = i(null), c = i(""), l = i(null);
881
+ async function d(e, i) {
882
+ let s = n();
883
+ if (!s) return null;
884
+ r.value = !0, o.value = null, a.value = null;
885
+ try {
886
+ let n = u(_["ai.score"], {
887
+ project: t.projectId,
888
+ tenant: t.tenantSlug,
889
+ template: s
890
+ }), r = await t.authenticatedFetch(n, {
891
+ method: "POST",
892
+ headers: {
893
+ "Content-Type": "application/json",
894
+ Accept: "text/event-stream"
895
+ },
896
+ body: JSON.stringify({
897
+ current_content: e,
898
+ merge_tags: i.map((e) => ({
899
+ label: e.label,
900
+ value: e.value
901
+ }))
902
+ })
903
+ });
904
+ if (!r.ok) {
905
+ if (r.status === 403) throw Error("ai_generation_not_available");
906
+ let e = await r.json().catch(() => null);
907
+ throw Error(e?.message || "Failed to score template");
908
+ }
909
+ let o = r.body?.getReader();
910
+ if (!o) throw Error("Failed to read stream");
911
+ let c = new TextDecoder(), l = "", d = null;
912
+ for (;;) {
913
+ let { done: e, value: t } = await o.read();
914
+ if (e) break;
915
+ l += c.decode(t, { stream: !0 });
916
+ let n = l.split("\n");
917
+ l = n.pop() ?? "";
918
+ for (let e of n) {
919
+ if (!e.startsWith("data: ")) continue;
920
+ let t;
921
+ try {
922
+ t = JSON.parse(e.slice(6));
923
+ } catch {
924
+ continue;
925
+ }
926
+ if (t.type === "error") throw Error(t.message || "Failed to score template");
927
+ t.type === "done" && (d = t.result ?? null);
928
+ }
929
+ }
930
+ if (d) for (let [e, t] of Object.entries(d.categories)) for (let n of t.findings) n.category = e;
931
+ return a.value = d, d;
932
+ } catch (e) {
933
+ return o.value = e instanceof Error ? e.message : "Failed to score template", null;
934
+ } finally {
935
+ r.value = !1;
936
+ }
937
+ }
938
+ async function f(e, r, i) {
939
+ let a = n();
940
+ if (!a) return null;
941
+ s.value = r.id, c.value = "", l.value = null;
942
+ try {
943
+ let n = u(_["ai.fixFinding"], {
944
+ project: t.projectId,
945
+ tenant: t.tenantSlug,
946
+ template: a
947
+ }), o = await t.authenticatedFetch(n, {
948
+ method: "POST",
949
+ headers: {
950
+ "Content-Type": "application/json",
951
+ Accept: "text/event-stream"
952
+ },
953
+ body: JSON.stringify({
954
+ content: e,
955
+ finding: {
956
+ id: r.id,
957
+ message: r.message,
958
+ suggestion: r.suggestion,
959
+ category: r.category
960
+ },
961
+ merge_tags: i.map((e) => ({
962
+ label: e.label,
963
+ value: e.value
964
+ }))
965
+ })
966
+ });
967
+ if (!o.ok) {
968
+ if (o.status === 403) throw Error("ai_generation_not_available");
969
+ let e = await o.json().catch(() => null);
970
+ throw Error(e?.message || "Failed to fix finding");
971
+ }
972
+ let s = o.body?.getReader();
973
+ if (!s) throw Error("Failed to read stream");
974
+ let l = new TextDecoder(), d = "", f = null;
975
+ for (;;) {
976
+ let { done: e, value: t } = await s.read();
977
+ if (e) break;
978
+ d += l.decode(t, { stream: !0 });
979
+ let n = d.split("\n");
980
+ d = n.pop() ?? "";
981
+ for (let e of n) {
982
+ if (!e.startsWith("data: ")) continue;
983
+ let t;
984
+ try {
985
+ t = JSON.parse(e.slice(6));
986
+ } catch {
987
+ continue;
988
+ }
989
+ if (t.type === "text") c.value += t.text;
990
+ else if (t.type === "error") throw Error(t.message || "Failed to fix finding");
991
+ else t.type === "done" && (f = t.content ?? null);
992
+ }
993
+ }
994
+ return f;
995
+ } catch (e) {
996
+ return l.value = e instanceof Error ? e.message : "Failed to fix finding", null;
997
+ } finally {
998
+ s.value = null;
999
+ }
1000
+ }
1001
+ function p(e, t) {
1002
+ if (!a.value) return;
1003
+ let n = a.value.categories[e];
1004
+ n && (n.findings = n.findings.filter((e) => e.id !== t));
1005
+ }
1006
+ function m() {
1007
+ r.value = !1, a.value = null, o.value = null, s.value = null, c.value = "", l.value = null;
1008
+ }
1009
+ return {
1010
+ isScoring: r,
1011
+ scoringResult: a,
1012
+ error: o,
1013
+ fixingFindingId: s,
1014
+ fixStreamingText: c,
1015
+ fixError: l,
1016
+ score: d,
1017
+ fixFinding: f,
1018
+ removeFinding: p,
1019
+ reset: m
1020
+ };
1021
+ }
1022
+ function O(e) {
1023
+ let { authManager: t, getTemplateId: n, onApply: r, onError: a } = e, o = i(!1), s = i(null);
1024
+ async function c(e) {
1025
+ let i = n();
1026
+ if (!i) throw Error("Template must be saved before using design reference");
1027
+ o.value = !0, s.value = null;
1028
+ try {
1029
+ let n = new FormData();
1030
+ e.prompt && n.append("prompt", e.prompt), e.imageUpload && n.append("image_upload", e.imageUpload), e.pdfUpload && n.append("pdf_upload", e.pdfUpload);
1031
+ let a = u(_["ai.generateFromDesign"], {
1032
+ project: t.projectId,
1033
+ tenant: t.tenantSlug,
1034
+ template: i
1035
+ }), o = await t.authenticatedFetch(a, {
1036
+ method: "POST",
1037
+ headers: { Accept: "text/event-stream" },
1038
+ body: n
1039
+ });
1040
+ if (!o.ok) {
1041
+ let e = await o.json().catch(() => null);
1042
+ throw o.status === 403 ? Error("ai_generation_not_available") : Error(e?.message || "Failed to generate template from design");
1043
+ }
1044
+ let s = o.body?.getReader();
1045
+ if (!s) throw Error("Failed to read stream");
1046
+ let c = new TextDecoder(), l = "", d = null;
1047
+ for (;;) {
1048
+ let { done: e, value: t } = await s.read();
1049
+ if (e) break;
1050
+ l += c.decode(t, { stream: !0 });
1051
+ let n = l.split("\n");
1052
+ l = n.pop() ?? "";
1053
+ for (let e of n) {
1054
+ if (!e.startsWith("data: ")) continue;
1055
+ let t = e.slice(6), n;
1056
+ try {
1057
+ n = JSON.parse(t);
1058
+ } catch {
1059
+ continue;
1060
+ }
1061
+ if (n.type === "error") throw Error(n.message || "Failed to generate template from design");
1062
+ n.type === "done" && (d = n.content ?? null, d && r?.(d));
1063
+ }
1064
+ }
1065
+ return d;
1066
+ } catch (e) {
1067
+ let t = e instanceof Error ? e : Error("Failed to generate template from design", { cause: e });
1068
+ return s.value = t.message, a?.(t), null;
1069
+ } finally {
1070
+ o.value = !1;
1071
+ }
1072
+ }
1073
+ function l() {
1074
+ o.value = !1, s.value = null;
1075
+ }
1076
+ return {
1077
+ isGenerating: o,
1078
+ error: s,
1079
+ generate: c,
1080
+ reset: l
1081
+ };
1082
+ }
1083
+ function k(e) {
1084
+ let { authManager: t, getTemplateId: n, getSocketId: r, onComment: o, onError: s, hasCommentingFeature: c } = e, l = new v(t), u = i([]), d = i(!1), f = i(!1), p = a(() => (c?.() ?? !1) && t.userConfig !== null), m = a(() => {
1085
+ let e = 0;
1086
+ for (let t of u.value) e += 1 + (t.replies?.length ?? 0);
1087
+ return e;
1088
+ }), h = a(() => u.value.filter((e) => !e.resolved_at).length), g = a(() => {
1089
+ let e = /* @__PURE__ */ new Map();
1090
+ for (let t of u.value) t.block_id && e.set(t.block_id, (e.get(t.block_id) ?? 0) + 1 + (t.replies?.length ?? 0));
1091
+ return e;
1092
+ });
1093
+ function _() {
1094
+ let e = t.userConfig;
1095
+ if (!e) throw Error("User config not available");
1096
+ return {
1097
+ user_id: e.id,
1098
+ user_name: e.name,
1099
+ user_signature: e.signature
1100
+ };
1101
+ }
1102
+ function y() {
1103
+ let e = r?.();
1104
+ if (e) return { "X-Socket-ID": e };
1105
+ }
1106
+ function b(e, t) {
1107
+ o?.({
1108
+ type: e,
1109
+ comment: t
1110
+ });
1111
+ }
1112
+ function x(e) {
1113
+ for (let t of u.value) {
1114
+ if (t.id === e) return t;
1115
+ for (let n of t.replies ?? []) if (n.id === e) return n;
1116
+ }
1117
+ return null;
1118
+ }
1119
+ async function S() {
1120
+ let e = n();
1121
+ if (e) {
1122
+ d.value = !0;
1123
+ try {
1124
+ u.value = await l.getComments(e);
1125
+ } catch (e) {
1126
+ let t = e instanceof Error ? e : Error("Failed to load comments", { cause: e });
1127
+ s?.(t);
1128
+ } finally {
1129
+ d.value = !1;
1130
+ }
1131
+ }
1132
+ }
1133
+ async function C(e, t, r) {
1134
+ let i = n();
1135
+ if (!i) return null;
1136
+ f.value = !0;
1137
+ try {
1138
+ let n = await l.createComment(i, {
1139
+ body: e,
1140
+ block_id: t,
1141
+ parent_id: r,
1142
+ ..._()
1143
+ }, y());
1144
+ if (r) {
1145
+ let e = x(r);
1146
+ e && (e.replies = [...e.replies ?? [], n]);
1147
+ } else u.value = [...u.value, n];
1148
+ return b("created", n), n;
1149
+ } catch (e) {
1150
+ let t = e instanceof Error ? e : Error("Failed to create comment", { cause: e });
1151
+ return s?.(t), null;
1152
+ } finally {
1153
+ f.value = !1;
1154
+ }
1155
+ }
1156
+ async function w(e, t) {
1157
+ let r = n();
1158
+ if (!r) return null;
1159
+ f.value = !0;
1160
+ try {
1161
+ let n = await l.updateComment(r, e, {
1162
+ body: t,
1163
+ ..._()
1164
+ }, y());
1165
+ return A(e, n), b("updated", n), n;
1166
+ } catch (e) {
1167
+ let t = e instanceof Error ? e : Error("Failed to update comment", { cause: e });
1168
+ return s?.(t), null;
1169
+ } finally {
1170
+ f.value = !1;
1171
+ }
1172
+ }
1173
+ async function T(e) {
1174
+ let t = n();
1175
+ if (!t) return !1;
1176
+ let r = x(e);
1177
+ if (!r) return !1;
1178
+ let i = {
1179
+ ...r,
1180
+ replies: [...r.replies ?? []]
1181
+ };
1182
+ f.value = !0;
1183
+ try {
1184
+ if (await l.deleteComment(t, e, _(), y()), r.parent_id) {
1185
+ let t = x(r.parent_id);
1186
+ t && (t.replies = (t.replies ?? []).filter((t) => t.id !== e));
1187
+ } else u.value = u.value.filter((t) => t.id !== e);
1188
+ return b("deleted", i), !0;
1189
+ } catch (e) {
1190
+ let t = e instanceof Error ? e : Error("Failed to delete comment", { cause: e });
1191
+ return s?.(t), !1;
1192
+ } finally {
1193
+ f.value = !1;
1194
+ }
1195
+ }
1196
+ async function E(e) {
1197
+ let t = n();
1198
+ if (!t) return null;
1199
+ f.value = !0;
1200
+ try {
1201
+ let n = await l.resolveComment(t, e, _(), y());
1202
+ return A(e, n), b(n.resolved_at ? "resolved" : "unresolved", n), n;
1203
+ } catch (e) {
1204
+ let t = e instanceof Error ? e : Error("Failed to toggle comment resolution", { cause: e });
1205
+ return s?.(t), null;
1206
+ } finally {
1207
+ f.value = !1;
1208
+ }
1209
+ }
1210
+ function D(e) {
1211
+ if (e.parent_id) {
1212
+ let t = x(e.parent_id);
1213
+ t && (t.replies = [...t.replies ?? [], e]);
1214
+ } else u.value = [...u.value, e];
1215
+ b("created", e);
1216
+ }
1217
+ function O(e) {
1218
+ A(e.id, e), b("updated", e);
1219
+ }
1220
+ function k(e, t) {
1221
+ let n = x(e), r = n ? {
1222
+ ...n,
1223
+ replies: [...n.replies ?? []]
1224
+ } : null;
1225
+ if (t) {
1226
+ let n = x(t);
1227
+ n && (n.replies = (n.replies ?? []).filter((t) => t.id !== e));
1228
+ } else u.value = u.value.filter((t) => t.id !== e);
1229
+ r && b("deleted", r);
1230
+ }
1231
+ function A(e, t) {
1232
+ for (let n = 0; n < u.value.length; n++) {
1233
+ if (u.value[n].id === e) {
1234
+ u.value = [
1235
+ ...u.value.slice(0, n),
1236
+ {
1237
+ ...t,
1238
+ replies: u.value[n].replies
1239
+ },
1240
+ ...u.value.slice(n + 1)
1241
+ ];
1242
+ return;
1243
+ }
1244
+ let r = u.value[n].replies ?? [];
1245
+ for (let i = 0; i < r.length; i++) if (r[i].id === e) {
1246
+ let e = [
1247
+ ...r.slice(0, i),
1248
+ t,
1249
+ ...r.slice(i + 1)
1250
+ ];
1251
+ u.value = [
1252
+ ...u.value.slice(0, n),
1253
+ {
1254
+ ...u.value[n],
1255
+ replies: e
1256
+ },
1257
+ ...u.value.slice(n + 1)
1258
+ ];
1259
+ return;
1260
+ }
1261
+ }
1262
+ }
1263
+ return {
1264
+ comments: u,
1265
+ isLoading: d,
1266
+ isSubmitting: f,
1267
+ isEnabled: p,
1268
+ commentCountByBlock: g,
1269
+ totalCount: m,
1270
+ unresolvedCount: h,
1271
+ loadComments: S,
1272
+ addComment: C,
1273
+ editComment: w,
1274
+ removeComment: T,
1275
+ toggleResolve: E,
1276
+ applyRemoteCreate: D,
1277
+ applyRemoteUpdate: O,
1278
+ applyRemoteDelete: k
1279
+ };
1280
+ }
1281
+ function A(e) {
1282
+ let { comments: t, channel: i } = e;
1283
+ n(i, (e, n) => {
1284
+ n && n.unbind("comment-broadcast"), e && e.bind("comment-broadcast", (e) => {
1285
+ j(t, e);
1286
+ });
1287
+ }), r(() => {
1288
+ i.value?.unbind("comment-broadcast");
1289
+ });
1290
+ }
1291
+ function j(e, t) {
1292
+ switch (t.action) {
1293
+ case "comment_created":
1294
+ e.applyRemoteCreate(t.comment);
1295
+ break;
1296
+ case "comment_updated":
1297
+ e.applyRemoteUpdate(t.comment);
1298
+ break;
1299
+ case "comment_deleted":
1300
+ e.applyRemoteDelete(t.comment.id, t.comment.parent_id);
1301
+ break;
1302
+ case "comment_resolved":
1303
+ case "comment_unresolved":
1304
+ e.applyRemoteUpdate(t.comment);
1305
+ break;
1306
+ }
1307
+ }
1308
+ var M = [
1309
+ "pusher:member_added",
1310
+ "pusher:member_removed",
1311
+ "client-block_locked",
1312
+ "client-block_unlocked",
1313
+ "client-operation",
1314
+ "mcp-operation"
1315
+ ];
1316
+ function N(e) {
1317
+ for (let t of M) e.unbind(t);
1318
+ }
1319
+ var P = [
1320
+ "#3b82f6",
1321
+ "#ef4444",
1322
+ "#10b981",
1323
+ "#f59e0b",
1324
+ "#8b5cf6",
1325
+ "#ec4899",
1326
+ "#06b6d4",
1327
+ "#f97316",
1328
+ "#6366f1",
1329
+ "#14b8a6"
1330
+ ];
1331
+ function F(e) {
1332
+ let { authManager: t, editor: o, channel: s } = e, c = i([]), l = i(/* @__PURE__ */ new Map()), u = 0, d = !1, f = a(() => t.userConfig?.id ?? "");
1333
+ function p() {
1334
+ let e = P[u % P.length];
1335
+ return u++, e;
1336
+ }
1337
+ function m(e) {
1338
+ if (e.id === f.value || c.value.some((t) => t.id === e.id)) return;
1339
+ let t = {
1340
+ id: e.id,
1341
+ name: e.name,
1342
+ color: p(),
1343
+ selectedBlockId: null
1344
+ };
1345
+ return c.value = [...c.value, t], t;
1346
+ }
1347
+ function h(e) {
1348
+ let t = new Map(l.value);
1349
+ for (let [n, r] of t) r.id === e && t.delete(n);
1350
+ l.value = t, c.value = c.value.filter((t) => t.id !== e);
1351
+ }
1352
+ function g(e) {
1353
+ let t = c.value.find((t) => t.id === e.userId);
1354
+ if (!t) return;
1355
+ c.value = c.value.map((t) => t.id === e.userId ? {
1356
+ ...t,
1357
+ selectedBlockId: e.blockId
1358
+ } : t);
1359
+ let n = new Map(l.value);
1360
+ for (let [t, r] of n) r.id === e.userId && n.delete(t);
1361
+ n.set(e.blockId, {
1362
+ ...t,
1363
+ selectedBlockId: e.blockId
1364
+ }), l.value = n, o.state.selectedBlockId === e.blockId && o.selectBlock(null);
1365
+ }
1366
+ function _(e) {
1367
+ let t = new Map(l.value), n = t.get(e.blockId);
1368
+ t.delete(e.blockId), l.value = t, n && (c.value = c.value.map((e) => e.id === n.id ? {
1369
+ ...e,
1370
+ selectedBlockId: null
1371
+ } : e));
1372
+ }
1373
+ function v(e) {
1374
+ d = !0;
1375
+ try {
1376
+ x(o, e);
1377
+ } finally {
1378
+ d = !1;
1379
+ }
1380
+ }
1381
+ function y(e) {
1382
+ !s.value || d || s.value.trigger("client-operation", e);
1383
+ }
1384
+ function b(e) {
1385
+ s.value && s.value.trigger("client-block_locked", {
1386
+ blockId: e,
1387
+ userId: f.value
1388
+ });
1389
+ }
1390
+ function S(e) {
1391
+ s.value && s.value.trigger("client-block_unlocked", { blockId: e });
1392
+ }
1393
+ return n(() => o.state.selectedBlockId, (e, t) => {
1394
+ d || (t && S(t), e && b(e));
1395
+ }), n(s, (t, n) => {
1396
+ if (n && N(n), !t) {
1397
+ c.value = [], l.value = /* @__PURE__ */ new Map(), u = 0;
1398
+ return;
1399
+ }
1400
+ let r = t.members;
1401
+ r && r.each((e) => {
1402
+ m(e.info);
1403
+ }), t.bind("pusher:member_added", (t) => {
1404
+ let n = m(t.info);
1405
+ n && e.onCollaboratorJoined?.(n);
1406
+ }), t.bind("pusher:member_removed", (t) => {
1407
+ let n = c.value.find((e) => e.id === t.id);
1408
+ h(t.id), n && e.onCollaboratorLeft?.(n);
1409
+ }), t.bind("client-block_locked", (t) => {
1410
+ g(t);
1411
+ let n = c.value.find((e) => e.id === t.userId);
1412
+ n && e.onBlockLocked?.({
1413
+ blockId: t.blockId,
1414
+ collaborator: n
1415
+ });
1416
+ }), t.bind("client-block_unlocked", (t) => {
1417
+ let n = l.value.get(t.blockId);
1418
+ _(t), n && e.onBlockUnlocked?.({
1419
+ blockId: t.blockId,
1420
+ collaborator: n
1421
+ });
1422
+ }), t.bind("client-operation", (e) => {
1423
+ v(e);
1424
+ }), t.bind("mcp-operation", (e) => {
1425
+ v(e);
1426
+ });
1427
+ }), r(() => {
1428
+ s.value && N(s.value);
1429
+ }), {
1430
+ collaborators: c,
1431
+ lockedBlocks: l,
1432
+ _broadcastOperation: y,
1433
+ _isProcessingRemoteOperation: () => d
1434
+ };
1435
+ }
1436
+ function I(e, t) {
1437
+ let n = e.addBlock, r = e.updateBlock, i = e.removeBlock, a = e.moveBlock, o = e.updateSettings, s = e.setContent;
1438
+ e.addBlock = (e, r, i) => {
1439
+ n(e, r, i), t._broadcastOperation({
1440
+ operation: "add_block",
1441
+ data: {
1442
+ block: e,
1443
+ section_id: r,
1444
+ column_index: i
1445
+ },
1446
+ timestamp: Date.now()
1447
+ });
1448
+ }, e.updateBlock = (e, n) => {
1449
+ r(e, n), t._broadcastOperation({
1450
+ operation: "update_block",
1451
+ data: {
1452
+ block_id: e,
1453
+ updates: n
1454
+ },
1455
+ timestamp: Date.now()
1456
+ });
1457
+ }, e.removeBlock = (e) => {
1458
+ i(e), t._broadcastOperation({
1459
+ operation: "delete_block",
1460
+ data: { block_id: e },
1461
+ timestamp: Date.now()
1462
+ });
1463
+ }, e.moveBlock = (e, n, r, i) => {
1464
+ a(e, n, r, i), t._broadcastOperation({
1465
+ operation: "move_block",
1466
+ data: {
1467
+ block_id: e,
1468
+ index: n,
1469
+ section_id: r,
1470
+ column_index: i
1471
+ },
1472
+ timestamp: Date.now()
1473
+ });
1474
+ }, e.updateSettings = (e) => {
1475
+ o(e), t._broadcastOperation({
1476
+ operation: "update_settings",
1477
+ data: { updates: e },
1478
+ timestamp: Date.now()
1479
+ });
1480
+ }, e.setContent = (e, n) => {
1481
+ s(e, n), t._broadcastOperation({
1482
+ operation: "set_content",
1483
+ data: { content: e },
1484
+ timestamp: Date.now()
1485
+ });
1486
+ };
1487
+ }
1488
+ function L(e) {
1489
+ let { authManager: t, onError: n } = e, r = i(null), a = i(!1), o = null, s = null;
1490
+ async function c(e, i) {
1491
+ if (o) return;
1492
+ o = new b({
1493
+ authManager: t,
1494
+ config: i,
1495
+ onError: n
1496
+ }), await o.connect(), s = `presence-template.${e}`;
1497
+ let c = o.subscribePresence(s);
1498
+ c.bind("pusher:subscription_succeeded", () => {
1499
+ a.value = !0, r.value = c;
1500
+ }), c.bind("pusher:subscription_error", (e) => {
1501
+ a.value = !1, r.value = null, n?.(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to subscribe to template channel"));
1502
+ });
1503
+ }
1504
+ function l() {
1505
+ s && o && o.unsubscribe(s), o?.disconnect(), o = null, s = null, r.value = null, a.value = !1;
1506
+ }
1507
+ function u() {
1508
+ return o?.getSocketId() ?? null;
1509
+ }
1510
+ return {
1511
+ channel: r,
1512
+ isConnected: a,
1513
+ connect: c,
1514
+ disconnect: l,
1515
+ getSocketId: u
1516
+ };
1517
+ }
1518
+ function R(e) {
1519
+ let t = new v(e.authManager), n = i([]), r = i(!1);
1520
+ async function a(i) {
1521
+ r.value = !0;
1522
+ try {
1523
+ n.value = await t.listModules(i);
1524
+ } catch (t) {
1525
+ throw e.onError?.(t), t;
1526
+ } finally {
1527
+ r.value = !1;
1528
+ }
1529
+ }
1530
+ async function o(r, i) {
1531
+ try {
1532
+ let e = await t.createModule({
1533
+ name: r,
1534
+ content: i
1535
+ });
1536
+ return n.value = [e, ...n.value], e;
1537
+ } catch (t) {
1538
+ throw e.onError?.(t), t;
1539
+ }
1540
+ }
1541
+ async function s(r, i) {
1542
+ try {
1543
+ let e = await t.updateModule(r, i);
1544
+ return n.value = n.value.map((t) => t.id === r ? e : t), e;
1545
+ } catch (t) {
1546
+ throw e.onError?.(t), t;
1547
+ }
1548
+ }
1549
+ async function c(r) {
1550
+ try {
1551
+ await t.deleteModule(r), n.value = n.value.filter((e) => e.id !== r);
1552
+ } catch (t) {
1553
+ throw e.onError?.(t), t;
1554
+ }
1555
+ }
1556
+ return {
1557
+ modules: n,
1558
+ isLoading: r,
1559
+ loadModules: a,
1560
+ createModule: o,
1561
+ updateModule: s,
1562
+ deleteModule: c
1563
+ };
1564
+ }
1565
+ function z(e) {
1566
+ let t = new v(e.authManager), n = i([]), r = i(!1), a = i(!1);
1567
+ async function o() {
1568
+ r.value = !0;
1569
+ try {
1570
+ n.value = await t.getSnapshots(e.templateId);
1571
+ } catch (t) {
1572
+ throw e.onError?.(t), t;
1573
+ } finally {
1574
+ r.value = !1;
1575
+ }
1576
+ }
1577
+ async function s(n) {
1578
+ a.value = !0;
1579
+ try {
1580
+ let r = await t.restoreSnapshot(e.templateId, n);
1581
+ return e.onRestore?.(r), r;
1582
+ } catch (t) {
1583
+ throw e.onError?.(t), t;
1584
+ } finally {
1585
+ a.value = !1;
1586
+ }
1587
+ }
1588
+ return {
1589
+ snapshots: n,
1590
+ isLoading: r,
1591
+ isRestoring: a,
1592
+ loadSnapshots: o,
1593
+ restoreSnapshot: s
1594
+ };
1595
+ }
1596
+ function B(e) {
1597
+ let { authManager: t, getTemplateId: r, save: o, exportHtml: s, onError: c, isAuthReady: l, onBeforeTestEmail: u } = e, d = new v(t), f = i(!1), p = i(null), m = i(null);
1598
+ l && n(l, (e) => {
1599
+ e && (m.value = t.testEmailConfig);
1600
+ }, { immediate: !0 });
1601
+ let h = a(() => m.value !== null), g = a(() => m.value?.allowedEmails ?? []);
1602
+ async function _(e) {
1603
+ if (!m.value) throw Error("Test email is not enabled for this project");
1604
+ let t = r();
1605
+ if (!t) throw Error("Template must be saved before sending a test email");
1606
+ f.value = !0, p.value = null;
1607
+ try {
1608
+ await o();
1609
+ let { html: n } = await s(t);
1610
+ u && (n = await u(n)), await d.sendTestEmail(t, {
1611
+ recipient: e,
1612
+ html: n,
1613
+ allowed_emails: m.value.allowedEmails,
1614
+ signature: m.value.signature
1615
+ });
1616
+ } catch (e) {
1617
+ let t = e instanceof Error ? e : Error("Failed to send test email", { cause: e });
1618
+ throw p.value = t.message, c?.(t), t;
1619
+ } finally {
1620
+ f.value = !1;
1621
+ }
1622
+ }
1623
+ return {
1624
+ isEnabled: h,
1625
+ allowedEmails: g,
1626
+ isSending: f,
1627
+ error: p,
1628
+ sendTestEmail: _
1629
+ };
1630
+ }
1631
+ function V(e) {
1632
+ let { authManager: t, getFontsConfig: n, canUseCustomFonts: r } = e, i = new v(t);
1633
+ function a() {
1634
+ let e = n?.();
1635
+ return {
1636
+ customFonts: (r?.() ?? !0) && e?.customFonts ? e.customFonts : [],
1637
+ defaultFallback: e?.defaultFallback ?? "Arial, sans-serif"
1638
+ };
1639
+ }
1640
+ async function o(e) {
1641
+ let t = a(), n = await i.exportTemplate(e, t);
1642
+ return {
1643
+ html: n.html,
1644
+ mjml: n.mjml
1645
+ };
1646
+ }
1647
+ async function s(e) {
1648
+ let t = a();
1649
+ return (await i.exportTemplate(e, t)).mjml;
1650
+ }
1651
+ return {
1652
+ exportHtml: o,
1653
+ getMjmlSource: s
1654
+ };
1655
+ }
1656
+ function H(e) {
1657
+ let { authManager: t, onError: n } = e, r = i(null), o = i(!1), s = new v(t), c = a(() => r.value?.features ?? null);
1658
+ function l(e) {
1659
+ return r.value?.features[e] ?? !1;
1660
+ }
1661
+ async function u() {
1662
+ if (!o.value) {
1663
+ o.value = !0;
1664
+ try {
1665
+ r.value = await s.fetchConfig();
1666
+ } catch (e) {
1667
+ n?.(e instanceof Error ? e : Error("Failed to fetch config", { cause: e }));
1668
+ } finally {
1669
+ o.value = !1;
1670
+ }
1671
+ }
1672
+ }
1673
+ return {
1674
+ config: r,
1675
+ isLoading: o,
1676
+ hasFeature: l,
1677
+ features: c,
1678
+ fetchConfig: u
1679
+ };
1680
+ }
1681
+ var U = 5e3;
1682
+ function W(e) {
1683
+ return e.authManager ? e.authManager.resolveUrl(_.health) : `${(e.baseUrl ?? "https://templatical.com").replace(/\/$/, "")}${_.health}`;
1684
+ }
1685
+ async function G(e, t) {
1686
+ let n = performance.now();
1687
+ try {
1688
+ let r = t ? await t.authenticatedFetch(_.health, {
1689
+ method: "GET",
1690
+ headers: { Accept: "application/json" }
1691
+ }) : await fetch(e, {
1692
+ method: "GET",
1693
+ headers: { Accept: "application/json" }
1694
+ }), i = Math.round(performance.now() - n);
1695
+ if (r.status === 401) return {
1696
+ api: {
1697
+ ok: !0,
1698
+ latency: i
1699
+ },
1700
+ auth: {
1701
+ ok: !1,
1702
+ error: "HTTP 401"
1703
+ }
1704
+ };
1705
+ if (!r.ok) return {
1706
+ api: {
1707
+ ok: !1,
1708
+ latency: i
1709
+ },
1710
+ auth: {
1711
+ ok: !t,
1712
+ error: t ? `HTTP ${r.status}` : void 0
1713
+ }
1714
+ };
1715
+ let a = await r.json();
1716
+ return {
1717
+ api: {
1718
+ ok: a.status === "ok",
1719
+ latency: i
1720
+ },
1721
+ auth: { ok: !0 },
1722
+ wsConfig: a.websocket
1723
+ };
1724
+ } catch (e) {
1725
+ return {
1726
+ api: {
1727
+ ok: !1,
1728
+ latency: Math.round(performance.now() - n)
1729
+ },
1730
+ auth: {
1731
+ ok: !t,
1732
+ error: t ? e instanceof Error ? e.message : "Authentication check failed" : void 0
1733
+ }
1734
+ };
1735
+ }
1736
+ }
1737
+ async function K(e) {
1738
+ if (!e?.host || !e?.app_key) return {
1739
+ ok: !1,
1740
+ error: "WebSocket configuration not available"
1741
+ };
1742
+ if (typeof WebSocket > "u") return {
1743
+ ok: !1,
1744
+ error: "WebSocket not supported in this environment"
1745
+ };
1746
+ let t = `${e.port === 443 ? "wss" : "ws"}://${e.host}:${e.port}/app/${e.app_key}?protocol=7&client=js&version=8.4.0-rc2&flash=false`;
1747
+ return new Promise((e) => {
1748
+ let n = null, r = setTimeout(() => {
1749
+ n?.close(), e({
1750
+ ok: !1,
1751
+ error: "WebSocket connection timed out"
1752
+ });
1753
+ }, U);
1754
+ try {
1755
+ n = new WebSocket(t);
1756
+ } catch (t) {
1757
+ clearTimeout(r), e({
1758
+ ok: !1,
1759
+ error: t instanceof Error ? t.message : "WebSocket connection failed"
1760
+ });
1761
+ return;
1762
+ }
1763
+ n.onopen = () => {
1764
+ clearTimeout(r), n?.close(), e({ ok: !0 });
1765
+ }, n.onerror = () => {
1766
+ clearTimeout(r), e({
1767
+ ok: !1,
1768
+ error: "WebSocket connection failed"
1769
+ });
1770
+ };
1771
+ });
1772
+ }
1773
+ async function q(e = {}) {
1774
+ let t = await G(W(e), e.authManager), n = await K(t.wsConfig);
1775
+ return {
1776
+ api: t.api,
1777
+ websocket: n,
1778
+ auth: t.auth,
1779
+ overall: t.api.ok && t.auth.ok
1780
+ };
1781
+ }
1782
+ function J(e) {
1783
+ let { editor: t, channel: r, onOperation: i } = e;
1784
+ n(r, (e, n) => {
1785
+ n && n.unbind("mcp-operation"), e && e.bind("mcp-operation", (e) => {
1786
+ x(t, e), i?.(e);
1787
+ });
1788
+ });
1789
+ }
1790
+ //#endregion
1791
+ export { D as _, E as a, A as c, S as d, V as f, z as g, R as h, T as i, k as l, H as m, q as n, F as o, J as p, y as r, I as s, l as t, O as u, B as v, L as y };