@templatical/core 0.7.1 → 0.7.3

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.
@@ -2,7 +2,7 @@ import { AuthConfig, TestEmailConfig, UserConfig, SdkAuthConfig, TemplateContent
2
2
  export { AuthConfig, AuthRequestOptions, SdkAuthConfig, TestEmailConfig, UserConfig } from '@templatical/types';
3
3
  import { PresenceChannel, Channel } from 'pusher-js';
4
4
  import { DeepReadonly, Ref, ref, ComputedRef } from 'vue';
5
- import { U as UseEditorReturn$1 } from '../editor-K644r-hl.js';
5
+ import { U as UseEditorReturn$1 } from '../editor-DoKPR8pJ.js';
6
6
  import '@vue/reactivity';
7
7
 
8
8
  declare class AuthManager {
@@ -206,6 +206,11 @@ interface UseEditorReturn {
206
206
  moveBlock: (blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number) => void;
207
207
  savedBlockIds: Ref<Set<string>>;
208
208
  isBlockLocked: (blockId: string) => boolean;
209
+ findBlockLocation: (blockId: string) => {
210
+ targetSectionId?: string;
211
+ columnIndex?: number;
212
+ index: number;
213
+ } | null;
209
214
  create: (content?: TemplateContent) => Promise<Template>;
210
215
  load: (templateId: string) => Promise<Template>;
211
216
  save: () => Promise<Template>;
@@ -883,12 +883,24 @@ function useEditor(options) {
883
883
  function markDirty() {
884
884
  state.isDirty = true;
885
885
  }
886
+ function findBlockLocation(blockId) {
887
+ const parent = findBlockParent(state.content.blocks, blockId);
888
+ if (!parent) return null;
889
+ const index = parent.blocks.findIndex((b) => b.id === blockId);
890
+ if (index === -1) return null;
891
+ return {
892
+ targetSectionId: parent.sectionId,
893
+ columnIndex: parent.columnIndex,
894
+ index
895
+ };
896
+ }
886
897
  return {
887
898
  state: readonly(state),
888
899
  content,
889
900
  selectedBlock,
890
901
  savedBlockIds,
891
902
  isBlockLocked,
903
+ findBlockLocation,
892
904
  setContent,
893
905
  selectBlock,
894
906
  setViewport,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cloud/auth.ts","../../src/cloud/api.ts","../../src/cloud/url-builder.ts","../../src/cloud/websocket-client.ts","../../src/cloud/mcp-operation-handler.ts","../../src/cloud/editor.ts","../../src/cloud/ai-chat.ts","../../src/cloud/ai-rewrite.ts","../../src/cloud/ai-config.ts","../../src/cloud/template-scoring.ts","../../src/cloud/design-reference.ts","../../src/cloud/comments.ts","../../src/cloud/comment-listener.ts","../../src/cloud/collaboration.ts","../../src/cloud/collaboration-broadcast.ts","../../src/cloud/web-socket.ts","../../src/cloud/saved-modules.ts","../../src/cloud/snapshots.ts","../../src/cloud/test-email.ts","../../src/cloud/export.ts","../../src/cloud/plan-config.ts","../../src/cloud/health-check.ts","../../src/cloud/mcp-listener.ts"],"sourcesContent":["import type {\n AuthConfig,\n AuthRequestOptions,\n SdkAuthConfig,\n TestEmailConfig,\n TokenData,\n UserConfig,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\n\nexport type {\n AuthConfig,\n AuthRequestOptions,\n SdkAuthConfig,\n TestEmailConfig,\n UserConfig,\n};\n\nexport class AuthManager {\n private static readonly DEFAULT_BASE_URL = \"https://templatical.com\";\n\n private accessToken: string | null = null;\n private expiresAt: Date | null = null;\n private _projectId: string | null = null;\n private _tenantId: string | null = null;\n private _tenantSlug: string | null = null;\n private _testEmailConfig: TestEmailConfig | null = null;\n private _userConfig: UserConfig | null = null;\n private readonly url: string;\n private readonly baseUrl: string;\n private readonly requestOptions: AuthRequestOptions;\n private readonly onError?: (error: Error) => void;\n private refreshPromise: Promise<string> | null = null;\n\n private static readonly REFRESH_THRESHOLD_MS = 60 * 1000;\n\n constructor(config: AuthConfig) {\n this.url = config.url;\n this.baseUrl = (config.baseUrl ?? AuthManager.DEFAULT_BASE_URL).replace(\n /\\/$/,\n \"\",\n );\n this.requestOptions = config.requestOptions ?? {};\n this.onError = config.onError;\n }\n\n resolveUrl(path: string): string {\n if (path.startsWith(\"http://\") || path.startsWith(\"https://\")) {\n return path;\n }\n\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${this.baseUrl}${normalizedPath}`;\n }\n\n get projectId(): string {\n if (!this._projectId) {\n throw new Error(\"Project ID not available. Call initialize() first.\");\n }\n return this._projectId;\n }\n\n get tenantId(): string {\n if (!this._tenantId) {\n throw new Error(\"Tenant ID not available. Call initialize() first.\");\n }\n return this._tenantId;\n }\n\n get tenantSlug(): string {\n if (!this._tenantSlug) {\n throw new Error(\"Tenant slug not available. Call initialize() first.\");\n }\n return this._tenantSlug;\n }\n\n get testEmailConfig(): TestEmailConfig | null {\n return this._testEmailConfig;\n }\n\n get userConfig(): UserConfig | null {\n return this._userConfig;\n }\n\n get accessTokenValue(): string | null {\n return this.accessToken;\n }\n\n async initialize(): Promise<void> {\n await this.ensureToken();\n }\n\n private async ensureToken(): Promise<string> {\n if (this.accessToken && !this.isTokenExpiringSoon()) {\n return this.accessToken;\n }\n return this.refreshToken();\n }\n\n private isTokenExpiringSoon(): boolean {\n if (!this.expiresAt) {\n return true;\n }\n const timeUntilExpiry = this.expiresAt.getTime() - Date.now();\n return timeUntilExpiry < AuthManager.REFRESH_THRESHOLD_MS;\n }\n\n async refreshToken(): Promise<string> {\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.performRefresh();\n\n try {\n const token = await this.refreshPromise;\n return token;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async performRefresh(): Promise<string> {\n try {\n const method = this.requestOptions.method ?? \"POST\";\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...this.requestOptions.headers,\n };\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n credentials: this.requestOptions.credentials ?? \"include\",\n };\n\n if (method === \"POST\" && this.requestOptions.body) {\n headers[\"Content-Type\"] = \"application/json\";\n fetchOptions.body = JSON.stringify(this.requestOptions.body);\n }\n\n const response = await fetch(this.url, fetchOptions);\n\n if (!response.ok) {\n throw new SdkError(\n `Token refresh failed: ${response.status}`,\n response.status,\n );\n }\n\n const data: TokenData = await response.json();\n\n if (!data.token || !data.expires_at || !data.project_id || !data.tenant) {\n throw new Error(\n \"Invalid token response: missing token, expires_at, project_id, or tenant\",\n );\n }\n\n this.accessToken = data.token;\n this.expiresAt = new Date(data.expires_at * 1000);\n this._projectId = data.project_id;\n this._tenantSlug = data.tenant;\n\n if (data.test_email?.allowed_emails && data.test_email?.signature) {\n this._testEmailConfig = {\n allowedEmails: data.test_email.allowed_emails,\n signature: data.test_email.signature,\n };\n } else {\n this._testEmailConfig = null;\n }\n\n if (data.user?.id && data.user?.name && data.user?.signature) {\n this._userConfig = {\n id: data.user.id,\n name: data.user.name,\n signature: data.user.signature,\n };\n } else {\n this._userConfig = null;\n }\n\n return this.accessToken;\n } catch (error) {\n const wrappedError =\n error instanceof Error\n ? error\n : new Error(\"Token refresh failed\", { cause: error });\n this.onError?.(wrappedError);\n throw wrappedError;\n }\n }\n\n async authenticatedFetch(\n url: string,\n options: RequestInit = {},\n ): Promise<Response> {\n const token = await this.ensureToken();\n const resolvedUrl = this.resolveUrl(url);\n\n const makeRequest = async (authToken: string): Promise<Response> => {\n return fetch(resolvedUrl, {\n ...options,\n headers: {\n ...options.headers,\n Authorization: `Bearer ${authToken}`,\n },\n });\n };\n\n let response = await makeRequest(token);\n\n if (response.status === 401) {\n const newToken = await this.refreshToken();\n response = await makeRequest(newToken);\n }\n\n return response;\n }\n}\n\nexport function createSdkAuthManager(\n config: SdkAuthConfig,\n onError?: (error: Error) => void,\n): AuthManager {\n if (config.mode === \"direct\") {\n const baseUrl = (config.baseUrl ?? \"https://templatical.com\").replace(\n /\\/$/,\n \"\",\n );\n\n return new AuthManager({\n url: `${baseUrl}/api/v1/auth/token`,\n baseUrl: config.baseUrl,\n requestOptions: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: {\n client_id: config.clientId,\n client_secret: config.clientSecret,\n tenant: config.tenant,\n client_type: \"sdk\",\n },\n },\n onError,\n });\n }\n\n return new AuthManager({\n url: config.url,\n baseUrl: config.baseUrl,\n requestOptions: config.requestOptions,\n onError,\n });\n}\n","import type {\n ApiError,\n ApiResponse,\n Comment,\n CustomFont,\n PlanConfig,\n SavedModule,\n Template,\n TemplateContent,\n TemplateSnapshot,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\n\nexport class ApiClient {\n constructor(private readonly authManager: AuthManager) {}\n\n private get projectId(): string {\n return this.authManager.projectId;\n }\n\n private get tenantSlug(): string {\n return this.authManager.tenantSlug;\n }\n\n private get baseParams(): Record<string, string> {\n return { project: this.projectId, tenant: this.tenantSlug };\n }\n\n private async request<T>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const response = await this.authManager.authenticatedFetch(path, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error: ApiError = await response.json().catch(() => ({\n message: `HTTP error ${response.status}`,\n }));\n\n const errorMessage = this.extractFirstValidationError(error);\n throw new SdkError(errorMessage, response.status);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const json: ApiResponse<T> = await response.json();\n return json.data;\n }\n\n private extractFirstValidationError(error: ApiError): string {\n if (error.errors) {\n const firstField = Object.keys(error.errors)[0];\n if (firstField && error.errors[firstField]?.length > 0) {\n return error.errors[firstField][0];\n }\n }\n return error.message;\n }\n\n async createTemplate(content: TemplateContent): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.store\"], this.baseParams),\n {\n method: \"POST\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async getTemplate(id: string): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.show\"], {\n ...this.baseParams,\n template: id,\n }),\n );\n }\n\n async updateTemplate(\n id: string,\n content: TemplateContent,\n ): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.update\"], {\n ...this.baseParams,\n template: id,\n }),\n {\n method: \"PUT\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async createSnapshot(\n templateId: string,\n content: TemplateContent,\n ): Promise<TemplateSnapshot> {\n return this.request<TemplateSnapshot>(\n buildUrl(API_ROUTES[\"snapshots.store\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async deleteTemplate(id: string): Promise<void> {\n return this.request<void>(\n buildUrl(API_ROUTES[\"templates.destroy\"], {\n ...this.baseParams,\n template: id,\n }),\n {\n method: \"DELETE\",\n },\n );\n }\n\n async getSnapshots(templateId: string): Promise<TemplateSnapshot[]> {\n return this.request<TemplateSnapshot[]>(\n buildUrl(API_ROUTES[\"snapshots.index\"], {\n ...this.baseParams,\n template: templateId,\n }),\n );\n }\n\n async restoreSnapshot(\n templateId: string,\n snapshotId: string,\n ): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"snapshots.restore\"], {\n ...this.baseParams,\n template: templateId,\n snapshot: snapshotId,\n }),\n {\n method: \"POST\",\n },\n );\n }\n\n async exportTemplate(\n templateId: string,\n fontsPayload?: {\n customFonts: CustomFont[];\n defaultFallback: string;\n },\n ): Promise<{ html: string; mjml: string }> {\n const body = fontsPayload\n ? JSON.stringify({\n custom_fonts: fontsPayload.customFonts,\n default_fallback: fontsPayload.defaultFallback,\n })\n : undefined;\n\n return this.request<{ html: string; mjml: string }>(\n buildUrl(API_ROUTES[\"templates.export\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body,\n },\n );\n }\n\n async sendTestEmail(\n templateId: string,\n payload: {\n recipient: string;\n html: string;\n allowed_emails: string[];\n signature: string;\n },\n ): Promise<void> {\n await this.request<void>(\n buildUrl(API_ROUTES[\"templates.sendTestEmail\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify(payload),\n },\n );\n }\n\n private commentsUrl(templateId: string, commentId?: string): string {\n if (commentId) {\n return buildUrl(API_ROUTES[\"comments.update\"], {\n ...this.baseParams,\n template: templateId,\n comment: commentId,\n });\n }\n return buildUrl(API_ROUTES[\"comments.index\"], {\n ...this.baseParams,\n template: templateId,\n });\n }\n\n async getComments(templateId: string): Promise<Comment[]> {\n return this.request<Comment[]>(this.commentsUrl(templateId));\n }\n\n async createComment(\n templateId: string,\n data: {\n body: string;\n block_id?: string;\n parent_id?: string;\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(this.commentsUrl(templateId), {\n method: \"POST\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async updateComment(\n templateId: string,\n commentId: string,\n data: {\n body: string;\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(this.commentsUrl(templateId, commentId), {\n method: \"PUT\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async deleteComment(\n templateId: string,\n commentId: string,\n data: {\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<void> {\n return this.request<void>(this.commentsUrl(templateId, commentId), {\n method: \"DELETE\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async resolveComment(\n templateId: string,\n commentId: string,\n data: {\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(\n buildUrl(API_ROUTES[\"comments.resolve\"], {\n ...this.baseParams,\n template: templateId,\n comment: commentId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify(data),\n headers,\n },\n );\n }\n\n async fetchConfig(): Promise<PlanConfig> {\n return this.request<PlanConfig>(\n buildUrl(API_ROUTES[\"projects.config\"], this.baseParams),\n );\n }\n\n async listModules(search?: string): Promise<SavedModule[]> {\n const url = buildUrl(API_ROUTES[\"savedModules.index\"], this.baseParams);\n const query = search ? `?search=${encodeURIComponent(search)}` : \"\";\n return this.request<SavedModule[]>(`${url}${query}`);\n }\n\n async createModule(data: {\n name: string;\n content: Block[];\n }): Promise<SavedModule> {\n return this.request<SavedModule>(\n buildUrl(API_ROUTES[\"savedModules.store\"], this.baseParams),\n {\n method: \"POST\",\n body: JSON.stringify(data),\n },\n );\n }\n\n async updateModule(\n id: string,\n data: Partial<{ name: string; content: Block[] }>,\n ): Promise<SavedModule> {\n return this.request<SavedModule>(\n buildUrl(API_ROUTES[\"savedModules.update\"], {\n ...this.baseParams,\n savedModule: id,\n }),\n {\n method: \"PUT\",\n body: JSON.stringify(data),\n },\n );\n }\n\n async deleteModule(id: string): Promise<void> {\n return this.request<void>(\n buildUrl(API_ROUTES[\"savedModules.destroy\"], {\n ...this.baseParams,\n savedModule: id,\n }),\n {\n method: \"DELETE\",\n },\n );\n }\n}\n","export function buildUrl(\n template: string,\n params: Record<string, string>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) =>\n encodeURIComponent(params[key] ?? \"\"),\n );\n}\n\nconst BASE = \"/api/v1/projects/{project}/tenants/{tenant}\";\nconst TEMPLATE = `${BASE}/templates/{template}`;\nconst AI = `${TEMPLATE}/ai`;\nconst MEDIA = `${BASE}/media`;\nconst FOLDERS = `${MEDIA}/folders`;\nconst MODULES = `${BASE}/saved-modules`;\n\nexport const API_ROUTES = {\n health: \"/api/v1/health\",\n \"projects.config\": `${BASE}/config`,\n \"broadcasting.auth\": `${BASE}/broadcasting/auth`,\n \"templates.store\": `${BASE}/templates`,\n \"templates.show\": `${TEMPLATE}`,\n \"templates.update\": `${TEMPLATE}`,\n \"templates.destroy\": `${TEMPLATE}`,\n \"templates.export\": `${TEMPLATE}/export`,\n \"templates.importFromBeefree\": `${BASE}/templates/import/from-beefree`,\n \"templates.sendTestEmail\": `${TEMPLATE}/send-test-email`,\n \"snapshots.index\": `${TEMPLATE}/snapshots`,\n \"snapshots.store\": `${TEMPLATE}/snapshots`,\n \"snapshots.show\": `${TEMPLATE}/snapshots/{snapshot}`,\n \"snapshots.restore\": `${TEMPLATE}/snapshots/{snapshot}/restore`,\n \"comments.index\": `${TEMPLATE}/comments`,\n \"comments.store\": `${TEMPLATE}/comments`,\n \"comments.update\": `${TEMPLATE}/comments/{comment}`,\n \"comments.destroy\": `${TEMPLATE}/comments/{comment}`,\n \"comments.resolve\": `${TEMPLATE}/comments/{comment}/resolve`,\n \"ai.generate\": `${AI}/generate`,\n \"ai.conversationMessages\": `${AI}/conversation-messages`,\n \"ai.suggestions\": `${AI}/suggestions`,\n \"ai.rewriteText\": `${AI}/rewrite-text`,\n \"ai.score\": `${AI}/score`,\n \"ai.fixFinding\": `${AI}/fix-finding`,\n \"ai.generateFromDesign\": `${AI}/generate-from-design`,\n \"media.upload\": `${MEDIA}/upload`,\n \"media.browse\": `${MEDIA}/browse`,\n \"media.delete\": `${MEDIA}/delete`,\n \"media.move\": `${MEDIA}/move`,\n \"media.update\": `${MEDIA}/{media}`,\n \"media.replace\": `${MEDIA}/{media}/replace`,\n \"media.checkUsage\": `${MEDIA}/check-usage`,\n \"media.frequentlyUsed\": `${MEDIA}/frequently-used`,\n \"media.importFromUrl\": `${MEDIA}/import-from-url`,\n \"folders.index\": `${FOLDERS}`,\n \"folders.store\": `${FOLDERS}`,\n \"folders.update\": `${FOLDERS}/{mediaFolder}`,\n \"folders.destroy\": `${FOLDERS}/{mediaFolder}`,\n \"savedModules.index\": `${MODULES}`,\n \"savedModules.store\": `${MODULES}`,\n \"savedModules.update\": `${MODULES}/{savedModule}`,\n \"savedModules.destroy\": `${MODULES}/{savedModule}`,\n} as const;\n","import type { WebSocketServerConfig } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel, PresenceChannel } from \"pusher-js\";\n\ntype PusherType = Pusher;\n\nexport interface WebSocketConfig {\n host: string;\n port: number;\n appKey: string;\n}\n\nexport function resolveWebSocketConfig(\n serverConfig: WebSocketServerConfig,\n): WebSocketConfig {\n return {\n host: serverConfig.host,\n port: serverConfig.port,\n appKey: serverConfig.app_key,\n };\n}\n\nexport interface PresenceMember {\n id: string;\n name: string;\n type: \"user\" | \"mcp\";\n}\n\nexport interface WebSocketClientOptions {\n authManager: AuthManager;\n config: WebSocketConfig;\n onError?: (error: Error) => void;\n}\n\nexport class WebSocketClient {\n private pusher: PusherType | null = null;\n private readonly authManager: AuthManager;\n private readonly config: WebSocketConfig;\n private readonly onError?: (error: Error) => void;\n\n constructor(options: WebSocketClientOptions) {\n this.authManager = options.authManager;\n this.config = options.config;\n this.onError = options.onError;\n }\n\n async connect(): Promise<void> {\n if (this.pusher) {\n return;\n }\n\n let Pusher: typeof import(\"pusher-js\").default;\n try {\n ({ default: Pusher } = await import(\"pusher-js\"));\n } catch {\n throw new Error(\n \"Cloud features require the optional peer dependency 'pusher-js'. Install it with: npm install pusher-js\",\n );\n }\n\n const { host, port, appKey } = this.config;\n const authEndpoint = this.authManager.resolveUrl(\n buildUrl(API_ROUTES[\"broadcasting.auth\"], {\n project: this.authManager.projectId,\n tenant: this.authManager.tenantSlug,\n }),\n );\n\n this.pusher = new Pusher(appKey, {\n wsHost: host,\n wsPort: port,\n wssPort: port,\n forceTLS: true,\n disableStats: true,\n enabledTransports: [\"ws\", \"wss\"],\n cluster: \"\",\n channelAuthorization: {\n transport: \"ajax\",\n endpoint: authEndpoint,\n headers: {\n Authorization: `Bearer ${this.authManager.accessTokenValue}`,\n Accept: \"application/json\",\n },\n params: {\n user_id: this.authManager.userConfig?.id ?? \"\",\n user_name: this.authManager.userConfig?.name ?? \"\",\n user_signature: this.authManager.userConfig?.signature ?? \"\",\n },\n },\n });\n\n this.pusher.connection.bind(\"error\", (error: unknown) => {\n this.onError?.(\n error instanceof Error\n ? error\n : new Error(\"WebSocket connection error\"),\n );\n });\n }\n\n subscribePresence(channelName: string): PresenceChannel {\n if (!this.pusher) {\n throw new Error(\"WebSocketClient not connected. Call connect() first.\");\n }\n\n return this.pusher.subscribe(channelName) as PresenceChannel;\n }\n\n unsubscribe(channelName: string): void {\n this.pusher?.unsubscribe(channelName);\n }\n\n getChannel(channelName: string): Channel | undefined {\n return this.pusher?.channel(channelName);\n }\n\n disconnect(): void {\n if (this.pusher) {\n this.pusher.disconnect();\n this.pusher = null;\n }\n }\n\n getSocketId(): string | null {\n return this.pusher?.connection.socket_id ?? null;\n }\n\n get isConnected(): boolean {\n return this.pusher?.connection.state === \"connected\";\n }\n}\n","import type { McpOperationPayload } from \"@templatical/types\";\nimport type {\n Block,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport type { UseEditorReturn } from \"./editor\";\n\nexport function handleOperation(\n editor: UseEditorReturn,\n payload: McpOperationPayload,\n): void {\n const { operation, data } = payload;\n\n switch (operation) {\n case \"add_block\":\n editor.addBlock(\n data.block as Block,\n data.section_id as string | undefined,\n data.column_index as number | undefined,\n data.index as number | undefined,\n );\n break;\n\n case \"update_block\":\n editor.updateBlock(\n data.block_id as string,\n data.updates as Partial<Block>,\n );\n break;\n\n case \"delete_block\":\n editor.removeBlock(data.block_id as string);\n break;\n\n case \"move_block\":\n editor.moveBlock(\n data.block_id as string,\n data.index as number,\n data.section_id as string | undefined,\n data.column_index as number | undefined,\n );\n break;\n\n case \"update_settings\":\n editor.updateSettings(data.updates as Partial<TemplateSettings>);\n break;\n\n case \"set_content\":\n editor.setContent(data.content as TemplateContent);\n break;\n\n case \"update_block_style\":\n editor.updateBlock(\n data.block_id as string,\n {\n styles: data.styles,\n } as Partial<Block>,\n );\n break;\n }\n}\n","import type {\n EditorState,\n Template,\n TemplateDefaults,\n UiTheme,\n ViewportSize,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport type {\n Block,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport { computed, reactive, readonly, type DeepReadonly, type Ref } from \"vue\";\n\nexport interface UseEditorOptions {\n authManager: AuthManager;\n defaultFontFamily?: string;\n templateDefaults?: TemplateDefaults;\n onError?: (error: Error) => void;\n lockedBlocks?: Ref<Map<string, unknown>>;\n}\n\nexport interface UseEditorReturn {\n state: DeepReadonly<EditorState>;\n content: Ref<TemplateContent>;\n selectedBlock: Ref<Block | null>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n selectBlock: (blockId: string | null) => void;\n setViewport: (viewport: ViewportSize) => void;\n setDarkMode: (darkMode: boolean) => void;\n setPreviewMode: (previewMode: boolean) => void;\n setUiTheme: (theme: UiTheme) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n updateSettings: (updates: Partial<TemplateSettings>) => void;\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n moveBlock: (\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n savedBlockIds: Ref<Set<string>>;\n isBlockLocked: (blockId: string) => boolean;\n create: (content?: TemplateContent) => Promise<Template>;\n load: (templateId: string) => Promise<Template>;\n save: () => Promise<Template>;\n createSnapshot: () => Promise<void>;\n hasTemplate: () => boolean;\n markDirty: () => void;\n}\n\nexport function useEditor(options: UseEditorOptions): UseEditorReturn {\n const api = new ApiClient(options.authManager);\n\n const state = reactive<EditorState>({\n template: null,\n content: createDefaultTemplateContent(\n options.defaultFontFamily,\n options.templateDefaults,\n ),\n selectedBlockId: null,\n viewport: \"desktop\",\n darkMode: false,\n previewMode: false,\n isDirty: false,\n isSaving: false,\n isLoading: false,\n uiTheme: \"auto\",\n });\n\n const content = computed({\n get: () => state.content,\n set: (value: TemplateContent) => {\n state.content = value;\n state.isDirty = true;\n },\n });\n\n const selectedBlock = computed(() => {\n if (!state.selectedBlockId) return null;\n return findBlockById(state.content.blocks, state.selectedBlockId);\n });\n\n const savedBlockIds = computed<Set<string>>(() => {\n const ids = new Set<string>();\n const blocks = state.template?.content?.blocks;\n if (!blocks) {\n return ids;\n }\n for (const block of blocks) {\n ids.add(block.id);\n if (block.type === \"section\") {\n for (const column of block.children) {\n for (const child of column) {\n ids.add(child.id);\n }\n }\n }\n }\n return ids;\n });\n\n function findBlockById(blocks: Block[], id: string): Block | null {\n for (const block of blocks) {\n if (block.id === id) return block;\n if (block.type === \"section\") {\n for (const column of block.children) {\n const found = findBlockById(column, id);\n if (found) return found;\n }\n }\n }\n return null;\n }\n\n function findBlockParent(\n blocks: Block[],\n id: string,\n parent: {\n blocks: Block[];\n sectionId?: string;\n columnIndex?: number;\n } = { blocks },\n ): { blocks: Block[]; sectionId?: string; columnIndex?: number } | null {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block.id === id) return parent;\n if (block.type === \"section\") {\n for (let colIdx = 0; colIdx < block.children.length; colIdx++) {\n const result = findBlockParent(block.children[colIdx], id, {\n blocks: block.children[colIdx],\n sectionId: block.id,\n columnIndex: colIdx,\n });\n if (result) return result;\n }\n }\n }\n return null;\n }\n\n function isBlockLocked(blockId: string): boolean {\n return options.lockedBlocks?.value.has(blockId) ?? false;\n }\n\n function setContent(newContent: TemplateContent, markDirty = true): void {\n state.content = newContent;\n if (markDirty) {\n state.isDirty = true;\n }\n }\n\n function selectBlock(blockId: string | null): void {\n if (blockId && isBlockLocked(blockId)) {\n return;\n }\n state.selectedBlockId = blockId;\n }\n\n function setViewport(viewport: ViewportSize): void {\n state.viewport = viewport;\n }\n\n function setDarkMode(darkMode: boolean): void {\n state.darkMode = darkMode;\n }\n\n function setUiTheme(theme: UiTheme): void {\n state.uiTheme = theme;\n }\n\n function setPreviewMode(previewMode: boolean): void {\n state.previewMode = previewMode;\n if (previewMode) {\n state.selectedBlockId = null;\n }\n }\n\n function updateBlock(blockId: string, updates: Partial<Block>): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const block = findBlockById(state.content.blocks, blockId);\n if (block) {\n Object.assign(block, updates);\n state.isDirty = true;\n }\n }\n\n function updateSettings(updates: Partial<TemplateSettings>): void {\n state.content.settings = { ...state.content.settings, ...updates };\n state.isDirty = true;\n }\n\n function addBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex = 0,\n index?: number,\n ): void {\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n const targetArray = section.children[columnIndex];\n if (index !== undefined && index < targetArray.length) {\n targetArray.splice(index, 0, block);\n } else {\n targetArray.push(block);\n }\n }\n } else {\n if (index !== undefined && index < state.content.blocks.length) {\n state.content.blocks.splice(index, 0, block);\n } else {\n state.content.blocks.push(block);\n }\n }\n state.isDirty = true;\n }\n\n function removeBlock(blockId: string): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const parent = findBlockParent(state.content.blocks, blockId);\n if (parent) {\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index !== -1) {\n parent.blocks.splice(index, 1);\n if (state.selectedBlockId === blockId) {\n state.selectedBlockId = null;\n }\n state.isDirty = true;\n }\n }\n }\n\n function moveBlock(\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex = 0,\n ): void {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return;\n\n const oldIndex = parent.blocks.findIndex((b) => b.id === blockId);\n if (oldIndex === -1) return;\n\n const [block] = parent.blocks.splice(oldIndex, 1);\n\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n section.children[columnIndex].splice(newIndex, 0, block);\n }\n } else {\n state.content.blocks.splice(newIndex, 0, block);\n }\n\n state.isDirty = true;\n }\n\n async function create(content?: TemplateContent): Promise<Template> {\n state.isLoading = true;\n try {\n if (content) {\n state.content = content;\n }\n const template = await api.createTemplate(state.content);\n state.template = template;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isLoading = false;\n }\n }\n\n async function load(templateId: string): Promise<Template> {\n state.isLoading = true;\n try {\n const template = await api.getTemplate(templateId);\n state.template = template;\n state.content = template.content;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isLoading = false;\n }\n }\n\n async function save(): Promise<Template> {\n if (!state.template?.id) {\n throw new SdkError(\n \"No template loaded. Call create() or load() before saving.\",\n );\n }\n\n state.isSaving = true;\n try {\n const template = await api.updateTemplate(\n state.template.id,\n state.content,\n );\n state.template = template;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isSaving = false;\n }\n }\n\n async function createSnapshot(): Promise<void> {\n if (!state.template?.id) {\n return;\n }\n\n try {\n await api.createSnapshot(state.template.id, state.content);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n function hasTemplate(): boolean {\n return state.template?.id !== undefined;\n }\n\n function markDirty(): void {\n state.isDirty = true;\n }\n\n return {\n state: readonly(state),\n content,\n selectedBlock,\n savedBlockIds,\n isBlockLocked,\n setContent,\n selectBlock,\n setViewport,\n setDarkMode,\n setUiTheme,\n setPreviewMode,\n updateBlock,\n updateSettings,\n addBlock,\n removeBlock,\n moveBlock,\n create,\n load,\n save,\n createSnapshot,\n hasTemplate,\n markDirty,\n };\n}\n","import type { AiChatMessage } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { MergeTag, TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseAiChatOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n onApply?: (content: TemplateContent) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseAiChatReturn {\n messages: ReturnType<typeof ref<AiChatMessage[]>>;\n isGenerating: ReturnType<typeof ref<boolean>>;\n isLoadingHistory: ReturnType<typeof ref<boolean>>;\n isLastChangeReverted: ReturnType<typeof ref<boolean>>;\n lastApplyMessageId: ReturnType<typeof ref<string | null>>;\n error: ReturnType<typeof ref<string | null>>;\n failedPrompt: ReturnType<typeof ref<string | null>>;\n suggestions: ReturnType<typeof ref<string[]>>;\n isLoadingSuggestions: ReturnType<typeof ref<boolean>>;\n sendPrompt: (\n prompt: string,\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<TemplateContent | null>;\n toggleLastRevert: () => void;\n loadConversation: () => Promise<void>;\n loadSuggestions: (\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<void>;\n clearChat: () => void;\n}\n\nlet messageIdCounter = 0;\n\nfunction generateMessageId(): string {\n return `msg_${Date.now()}_${++messageIdCounter}`;\n}\n\nexport function useAiChat(options: UseAiChatOptions): UseAiChatReturn {\n const { authManager, getTemplateId, onApply, onError } = options;\n\n const messages = ref<AiChatMessage[]>([]);\n const isGenerating = ref(false);\n const isLoadingHistory = ref(false);\n const error = ref<string | null>(null);\n const failedPrompt = ref<string | null>(null);\n const conversationId = ref<string | null>(null);\n const lastApplyMessageId = ref<string | null>(null);\n const lastPreviousContent = ref<TemplateContent | null>(null);\n const lastAppliedContent = ref<TemplateContent | null>(null);\n const isLastChangeReverted = ref(false);\n const suggestions = ref<string[]>([]);\n const isLoadingSuggestions = ref(false);\n\n function updateMessage(msgId: string, updates: Partial<AiChatMessage>): void {\n const idx = messages.value.findIndex((m) => m.id === msgId);\n if (idx === -1) {\n return;\n }\n\n const updated = { ...messages.value[idx], ...updates };\n messages.value = [\n ...messages.value.slice(0, idx),\n updated,\n ...messages.value.slice(idx + 1),\n ];\n }\n\n async function loadConversation(): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoadingHistory.value = true;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.conversationMessages\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n },\n });\n\n if (!response.ok) {\n return;\n }\n\n const data = await response.json();\n\n if (data.conversation_id) {\n conversationId.value = data.conversation_id;\n }\n\n if (Array.isArray(data.data) && data.data.length > 0) {\n messages.value = data.data.map(\n (msg: {\n id: string;\n role: \"user\" | \"assistant\";\n content: string;\n created_at: string;\n }) => ({\n id: msg.id,\n role: msg.role,\n content: msg.content,\n timestamp: new Date(msg.created_at).getTime(),\n }),\n );\n }\n } catch {\n // Silently fail - chat will start fresh\n } finally {\n isLoadingHistory.value = false;\n }\n }\n\n async function loadSuggestions(\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoadingSuggestions.value = true;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.suggestions\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n current_content: currentContent,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n return;\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n return;\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"done\" && Array.isArray(event.suggestions)) {\n suggestions.value = event.suggestions.slice(0, 3);\n }\n }\n }\n } catch {\n // Silently fail - suggestions are non-critical\n } finally {\n isLoadingSuggestions.value = false;\n }\n }\n\n async function sendPrompt(\n prompt: string,\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<TemplateContent | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before using AI generation\");\n }\n\n isGenerating.value = true;\n error.value = null;\n failedPrompt.value = null;\n suggestions.value = [];\n\n const userMsgId = generateMessageId();\n messages.value = [\n ...messages.value,\n {\n id: userMsgId,\n role: \"user\",\n content: prompt,\n timestamp: Date.now(),\n },\n ];\n\n const assistantMsgId = generateMessageId();\n messages.value = [\n ...messages.value,\n {\n id: assistantMsgId,\n role: \"assistant\",\n content: \"\",\n timestamp: Date.now(),\n },\n ];\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.generate\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n prompt,\n current_content: currentContent,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n conversation_id: conversationId.value,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => null);\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n throw new Error(errorData?.message || \"Failed to generate template\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: TemplateContent | null = null;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n const jsonStr = line.slice(6);\n\n let event;\n try {\n event = JSON.parse(jsonStr);\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n updateMessage(assistantMsgId, {\n content:\n (messages.value.find((m) => m.id === assistantMsgId)\n ?.content ?? \"\") + event.text,\n });\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to generate template\");\n } else if (event.type === \"done\") {\n if (event.conversation_id) {\n conversationId.value = event.conversation_id;\n }\n\n updateMessage(assistantMsgId, {\n content: event.text,\n });\n\n result = event.content ?? null;\n\n if (result) {\n lastPreviousContent.value = currentContent;\n lastAppliedContent.value = result;\n lastApplyMessageId.value = assistantMsgId;\n isLastChangeReverted.value = false;\n onApply?.(result);\n } else {\n error.value = \"ai_apply_failed\";\n }\n }\n }\n }\n } finally {\n // Release the underlying network resource even on early exit.\n // Without this, throwing out of the loop (e.g. on an `error` SSE\n // event) leaves the socket and read buffer attached until GC.\n reader.cancel().catch(() => {});\n }\n\n return result;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to generate template\", { cause: err });\n error.value = wrappedError.message;\n failedPrompt.value = prompt;\n onError?.(wrappedError);\n\n messages.value = messages.value.filter(\n (m) => m.id !== userMsgId && m.id !== assistantMsgId,\n );\n\n return null;\n } finally {\n isGenerating.value = false;\n }\n }\n\n function toggleLastRevert(): void {\n if (isLastChangeReverted.value) {\n if (lastAppliedContent.value) {\n onApply?.(lastAppliedContent.value);\n }\n isLastChangeReverted.value = false;\n } else {\n if (lastPreviousContent.value) {\n onApply?.(lastPreviousContent.value);\n }\n isLastChangeReverted.value = true;\n }\n }\n\n function clearChat(): void {\n messages.value = [];\n conversationId.value = null;\n error.value = null;\n lastApplyMessageId.value = null;\n lastPreviousContent.value = null;\n lastAppliedContent.value = null;\n isLastChangeReverted.value = false;\n }\n\n return {\n messages,\n isGenerating,\n isLoadingHistory,\n isLastChangeReverted,\n lastApplyMessageId,\n error,\n failedPrompt,\n suggestions,\n isLoadingSuggestions,\n sendPrompt,\n toggleLastRevert,\n loadConversation,\n loadSuggestions,\n clearChat,\n };\n}\n","import type { MergeTag } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport { ref } from \"vue\";\n\nexport interface UseAiRewriteOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n}\n\nexport interface UseAiRewriteReturn {\n isRewriting: ReturnType<typeof ref<boolean>>;\n streamingText: ReturnType<typeof ref<string>>;\n previousContent: ReturnType<typeof ref<string | null>>;\n rewrittenContent: ReturnType<typeof ref<string | null>>;\n isReverted: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<string | null>>;\n rewrite: (\n content: string,\n instruction: string,\n mergeTags: MergeTag[],\n ) => Promise<string | null>;\n undo: () => string | null;\n redo: () => string | null;\n reset: () => void;\n}\n\nexport function useAiRewrite(options: UseAiRewriteOptions): UseAiRewriteReturn {\n const { authManager, getTemplateId } = options;\n\n const isRewriting = ref(false);\n const streamingText = ref(\"\");\n const previousContent = ref<string | null>(null);\n const rewrittenContent = ref<string | null>(null);\n const isReverted = ref(false);\n const error = ref<string | null>(null);\n\n async function rewrite(\n content: string,\n instruction: string,\n mergeTags: MergeTag[],\n ): Promise<string | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isRewriting.value = true;\n streamingText.value = \"\";\n error.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.rewriteText\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n content,\n instruction,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to rewrite text\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: string | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n streamingText.value += event.text;\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to rewrite text\");\n } else if (event.type === \"done\") {\n result = event.content ?? null;\n\n if (result) {\n previousContent.value = content;\n rewrittenContent.value = result;\n isReverted.value = false;\n }\n }\n }\n }\n\n return result;\n } catch (err) {\n error.value =\n err instanceof Error ? err.message : \"Failed to rewrite text\";\n return null;\n } finally {\n isRewriting.value = false;\n }\n }\n\n function undo(): string | null {\n if (!previousContent.value) {\n return null;\n }\n\n isReverted.value = true;\n return previousContent.value;\n }\n\n function redo(): string | null {\n if (!rewrittenContent.value) {\n return null;\n }\n\n isReverted.value = false;\n return rewrittenContent.value;\n }\n\n function reset(): void {\n isRewriting.value = false;\n streamingText.value = \"\";\n previousContent.value = null;\n rewrittenContent.value = null;\n isReverted.value = false;\n error.value = null;\n }\n\n return {\n isRewriting,\n streamingText,\n previousContent,\n rewrittenContent,\n isReverted,\n error,\n rewrite,\n undo,\n redo,\n reset,\n };\n}\n","import type { AiConfig } from \"@templatical/types\";\nimport { computed, type ComputedRef } from \"vue\";\n\nexport interface UseAiConfigReturn {\n isFeatureEnabled: (feature: keyof AiConfig) => boolean;\n hasAnyMenuFeature: ComputedRef<boolean>;\n}\n\nexport function useAiConfig(config?: AiConfig | false): UseAiConfigReturn {\n function isFeatureEnabled(feature: keyof AiConfig): boolean {\n if (config === false) {\n return false;\n }\n\n return config?.[feature] !== false;\n }\n\n const hasAnyMenuFeature = computed(\n () =>\n isFeatureEnabled(\"chat\") ||\n isFeatureEnabled(\"scoring\") ||\n isFeatureEnabled(\"designToTemplate\"),\n );\n\n return {\n isFeatureEnabled,\n hasAnyMenuFeature,\n };\n}\n","import type {\n ScoringCategory,\n ScoringFinding,\n ScoringResult,\n} from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { MergeTag, TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseTemplateScoringOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n}\n\nexport interface UseTemplateScoringReturn {\n isScoring: ReturnType<typeof ref<boolean>>;\n scoringResult: ReturnType<typeof ref<ScoringResult | null>>;\n error: ReturnType<typeof ref<string | null>>;\n fixingFindingId: ReturnType<typeof ref<string | null>>;\n fixStreamingText: ReturnType<typeof ref<string>>;\n fixError: ReturnType<typeof ref<string | null>>;\n score: (\n content: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<ScoringResult | null>;\n fixFinding: (\n blockContent: string,\n finding: ScoringFinding,\n mergeTags: MergeTag[],\n ) => Promise<string | null>;\n removeFinding: (category: ScoringCategory, findingId: string) => void;\n reset: () => void;\n}\n\nexport function useTemplateScoring(\n options: UseTemplateScoringOptions,\n): UseTemplateScoringReturn {\n const { authManager, getTemplateId } = options;\n\n const isScoring = ref(false);\n const scoringResult = ref<ScoringResult | null>(null);\n const error = ref<string | null>(null);\n const fixingFindingId = ref<string | null>(null);\n const fixStreamingText = ref(\"\");\n const fixError = ref<string | null>(null);\n\n async function score(\n content: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<ScoringResult | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isScoring.value = true;\n error.value = null;\n scoringResult.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.score\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n current_content: content,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to score template\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: ScoringResult | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to score template\");\n }\n\n if (event.type === \"done\") {\n result = event.result ?? null;\n }\n }\n }\n\n if (result) {\n for (const [category, categoryData] of Object.entries(\n result.categories,\n )) {\n for (const finding of categoryData.findings) {\n finding.category = category as ScoringCategory;\n }\n }\n }\n\n scoringResult.value = result;\n return result;\n } catch (err) {\n error.value =\n err instanceof Error ? err.message : \"Failed to score template\";\n return null;\n } finally {\n isScoring.value = false;\n }\n }\n\n async function fixFinding(\n blockContent: string,\n finding: ScoringFinding,\n mergeTags: MergeTag[],\n ): Promise<string | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n fixingFindingId.value = finding.id;\n fixStreamingText.value = \"\";\n fixError.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.fixFinding\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n content: blockContent,\n finding: {\n id: finding.id,\n message: finding.message,\n suggestion: finding.suggestion,\n category: finding.category,\n },\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to fix finding\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: string | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n fixStreamingText.value += event.text;\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to fix finding\");\n } else if (event.type === \"done\") {\n result = event.content ?? null;\n }\n }\n }\n\n return result;\n } catch (err) {\n fixError.value =\n err instanceof Error ? err.message : \"Failed to fix finding\";\n return null;\n } finally {\n fixingFindingId.value = null;\n }\n }\n\n function removeFinding(category: ScoringCategory, findingId: string): void {\n if (!scoringResult.value) {\n return;\n }\n\n const cat = scoringResult.value.categories[category];\n if (!cat) {\n return;\n }\n\n cat.findings = cat.findings.filter((f) => f.id !== findingId);\n }\n\n function reset(): void {\n isScoring.value = false;\n scoringResult.value = null;\n error.value = null;\n fixingFindingId.value = null;\n fixStreamingText.value = \"\";\n fixError.value = null;\n }\n\n return {\n isScoring,\n scoringResult,\n error,\n fixingFindingId,\n fixStreamingText,\n fixError,\n score,\n fixFinding,\n removeFinding,\n reset,\n };\n}\n","import type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseDesignReferenceOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n onApply?: (content: TemplateContent) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseDesignReferenceReturn {\n isGenerating: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<string | null>>;\n generate: (input: DesignReferenceInput) => Promise<TemplateContent | null>;\n reset: () => void;\n}\n\nexport interface DesignReferenceInput {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n}\n\nexport function useDesignReference(\n options: UseDesignReferenceOptions,\n): UseDesignReferenceReturn {\n const { authManager, getTemplateId, onApply, onError } = options;\n\n const isGenerating = ref(false);\n const error = ref<string | null>(null);\n\n async function generate(\n input: DesignReferenceInput,\n ): Promise<TemplateContent | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before using design reference\");\n }\n\n isGenerating.value = true;\n error.value = null;\n\n try {\n const formData = new FormData();\n\n if (input.prompt) {\n formData.append(\"prompt\", input.prompt);\n }\n\n if (input.imageUpload) {\n formData.append(\"image_upload\", input.imageUpload);\n }\n\n if (input.pdfUpload) {\n formData.append(\"pdf_upload\", input.pdfUpload);\n }\n\n const url = buildUrl(API_ROUTES[\"ai.generateFromDesign\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n Accept: \"text/event-stream\",\n },\n body: formData,\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => null);\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n throw new Error(\n errorData?.message || \"Failed to generate template from design\",\n );\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: TemplateContent | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n const jsonStr = line.slice(6);\n\n let event;\n try {\n event = JSON.parse(jsonStr);\n } catch {\n continue;\n }\n\n if (event.type === \"error\") {\n throw new Error(\n event.message || \"Failed to generate template from design\",\n );\n }\n\n if (event.type === \"done\") {\n result = event.content ?? null;\n\n if (result) {\n onApply?.(result);\n }\n }\n }\n }\n\n return result;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to generate template from design\", {\n cause: err,\n });\n error.value = wrappedError.message;\n onError?.(wrappedError);\n\n return null;\n } finally {\n isGenerating.value = false;\n }\n }\n\n function reset(): void {\n isGenerating.value = false;\n error.value = null;\n }\n\n return {\n isGenerating,\n error,\n generate,\n reset,\n };\n}\n","import type {\n Comment,\n CommentEvent,\n CommentThread,\n UserConfig,\n} from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { computed, ref, type ComputedRef, type Ref } from \"vue\";\n\nexport interface UseCommentsOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n getSocketId?: () => string | null;\n onComment?: (event: CommentEvent) => void;\n onError?: (error: Error) => void;\n isAuthReady?: Ref<boolean>;\n hasCommentingFeature?: () => boolean;\n}\n\nexport interface UseCommentsReturn {\n comments: Ref<CommentThread[]>;\n isLoading: Ref<boolean>;\n isSubmitting: Ref<boolean>;\n isEnabled: ComputedRef<boolean>;\n commentCountByBlock: ComputedRef<Map<string, number>>;\n totalCount: ComputedRef<number>;\n unresolvedCount: ComputedRef<number>;\n loadComments: () => Promise<void>;\n addComment: (\n body: string,\n blockId?: string,\n parentId?: string,\n ) => Promise<Comment | null>;\n editComment: (commentId: string, body: string) => Promise<Comment | null>;\n removeComment: (commentId: string) => Promise<boolean>;\n toggleResolve: (commentId: string) => Promise<Comment | null>;\n applyRemoteCreate: (comment: Comment) => void;\n applyRemoteUpdate: (comment: Comment) => void;\n applyRemoteDelete: (commentId: string, parentId: string | null) => void;\n}\n\nexport function useComments(options: UseCommentsOptions): UseCommentsReturn {\n const {\n authManager,\n getTemplateId,\n getSocketId,\n onComment,\n onError,\n hasCommentingFeature,\n } = options;\n\n const api = new ApiClient(authManager);\n const comments = ref<CommentThread[]>([]);\n const isLoading = ref(false);\n const isSubmitting = ref(false);\n\n const isEnabled = computed<boolean>(() => {\n const featureAvailable = hasCommentingFeature?.() ?? false;\n return featureAvailable && authManager.userConfig !== null;\n });\n\n const totalCount = computed<number>(() => {\n let count = 0;\n for (const thread of comments.value) {\n count += 1 + (thread.replies?.length ?? 0);\n }\n return count;\n });\n\n const unresolvedCount = computed<number>(() => {\n return comments.value.filter((c) => !c.resolved_at).length;\n });\n\n const commentCountByBlock = computed<Map<string, number>>(() => {\n const map = new Map<string, number>();\n for (const thread of comments.value) {\n if (thread.block_id) {\n map.set(\n thread.block_id,\n (map.get(thread.block_id) ?? 0) + 1 + (thread.replies?.length ?? 0),\n );\n }\n }\n return map;\n });\n\n function getUserPayload(): {\n user_id: string;\n user_name: string;\n user_signature: string;\n } {\n const user: UserConfig | null = authManager.userConfig;\n if (!user) {\n throw new Error(\"User config not available\");\n }\n return {\n user_id: user.id,\n user_name: user.name,\n user_signature: user.signature,\n };\n }\n\n function socketHeaders(): Record<string, string> | undefined {\n const socketId = getSocketId?.();\n if (!socketId) {\n return undefined;\n }\n return { \"X-Socket-ID\": socketId };\n }\n\n function emitEvent(type: CommentEvent[\"type\"], comment: Comment): void {\n onComment?.({ type, comment });\n }\n\n function findComment(commentId: string): Comment | null {\n for (const thread of comments.value) {\n if (thread.id === commentId) {\n return thread;\n }\n for (const reply of thread.replies ?? []) {\n if (reply.id === commentId) {\n return reply;\n }\n }\n }\n return null;\n }\n\n async function loadComments(): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoading.value = true;\n\n try {\n comments.value = await api.getComments(templateId);\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to load comments\", { cause: err });\n onError?.(wrappedError);\n } finally {\n isLoading.value = false;\n }\n }\n\n async function addComment(\n body: string,\n blockId?: string,\n parentId?: string,\n ): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const comment = await api.createComment(\n templateId,\n {\n body,\n block_id: blockId,\n parent_id: parentId,\n ...getUserPayload(),\n },\n socketHeaders(),\n );\n\n if (parentId) {\n const parent = findComment(parentId);\n if (parent) {\n parent.replies = [...(parent.replies ?? []), comment];\n }\n } else {\n comments.value = [...comments.value, comment];\n }\n\n emitEvent(\"created\", comment);\n return comment;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to create comment\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function editComment(\n commentId: string,\n body: string,\n ): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const updated = await api.updateComment(\n templateId,\n commentId,\n {\n body,\n ...getUserPayload(),\n },\n socketHeaders(),\n );\n\n updateCommentInState(commentId, updated);\n emitEvent(\"updated\", updated);\n return updated;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to update comment\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function removeComment(commentId: string): Promise<boolean> {\n const templateId = getTemplateId();\n if (!templateId) {\n return false;\n }\n\n const comment = findComment(commentId);\n if (!comment) {\n return false;\n }\n\n const commentSnapshot = {\n ...comment,\n replies: [...(comment.replies ?? [])],\n };\n\n isSubmitting.value = true;\n\n try {\n await api.deleteComment(\n templateId,\n commentId,\n getUserPayload(),\n socketHeaders(),\n );\n\n if (comment.parent_id) {\n const parent = findComment(comment.parent_id);\n if (parent) {\n parent.replies = (parent.replies ?? []).filter(\n (r) => r.id !== commentId,\n );\n }\n } else {\n comments.value = comments.value.filter((c) => c.id !== commentId);\n }\n\n emitEvent(\"deleted\", commentSnapshot);\n return true;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to delete comment\", { cause: err });\n onError?.(wrappedError);\n return false;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function toggleResolve(commentId: string): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const updated = await api.resolveComment(\n templateId,\n commentId,\n getUserPayload(),\n socketHeaders(),\n );\n\n updateCommentInState(commentId, updated);\n\n const eventType = updated.resolved_at ? \"resolved\" : \"unresolved\";\n emitEvent(eventType, updated);\n return updated;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to toggle comment resolution\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n function applyRemoteCreate(comment: Comment): void {\n if (comment.parent_id) {\n const parent = findComment(comment.parent_id);\n if (parent) {\n parent.replies = [...(parent.replies ?? []), comment];\n }\n } else {\n comments.value = [...comments.value, comment];\n }\n emitEvent(\"created\", comment);\n }\n\n function applyRemoteUpdate(comment: Comment): void {\n updateCommentInState(comment.id, comment);\n emitEvent(\"updated\", comment);\n }\n\n function applyRemoteDelete(commentId: string, parentId: string | null): void {\n const comment = findComment(commentId);\n const snapshot = comment\n ? { ...comment, replies: [...(comment.replies ?? [])] }\n : null;\n\n if (parentId) {\n const parent = findComment(parentId);\n if (parent) {\n parent.replies = (parent.replies ?? []).filter(\n (r) => r.id !== commentId,\n );\n }\n } else {\n comments.value = comments.value.filter((c) => c.id !== commentId);\n }\n\n if (snapshot) {\n emitEvent(\"deleted\", snapshot);\n }\n }\n\n function updateCommentInState(commentId: string, updated: Comment): void {\n for (let i = 0; i < comments.value.length; i++) {\n if (comments.value[i].id === commentId) {\n comments.value = [\n ...comments.value.slice(0, i),\n { ...updated, replies: comments.value[i].replies },\n ...comments.value.slice(i + 1),\n ];\n return;\n }\n\n const replies = comments.value[i].replies ?? [];\n for (let j = 0; j < replies.length; j++) {\n if (replies[j].id === commentId) {\n const newReplies = [\n ...replies.slice(0, j),\n updated,\n ...replies.slice(j + 1),\n ];\n comments.value = [\n ...comments.value.slice(0, i),\n { ...comments.value[i], replies: newReplies },\n ...comments.value.slice(i + 1),\n ];\n return;\n }\n }\n }\n }\n\n return {\n comments,\n isLoading,\n isSubmitting,\n isEnabled,\n commentCountByBlock,\n totalCount,\n unresolvedCount,\n loadComments,\n addComment,\n editComment,\n removeComment,\n toggleResolve,\n applyRemoteCreate,\n applyRemoteUpdate,\n applyRemoteDelete,\n };\n}\n","import type { UseCommentsReturn } from \"./comments\";\nimport type { Comment } from \"@templatical/types\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { onScopeDispose, watch, type Ref } from \"vue\";\n\nexport interface CommentBroadcastPayload {\n action:\n | \"comment_created\"\n | \"comment_updated\"\n | \"comment_deleted\"\n | \"comment_resolved\"\n | \"comment_unresolved\";\n comment: Comment;\n}\n\nexport interface UseCommentListenerOptions {\n comments: UseCommentsReturn;\n channel: Ref<PresenceChannel | null>;\n}\n\nexport function useCommentListener(options: UseCommentListenerOptions): void {\n const { comments, channel } = options;\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n oldChannel.unbind(\"comment-broadcast\");\n }\n\n if (newChannel) {\n newChannel.bind(\n \"comment-broadcast\",\n (payload: CommentBroadcastPayload) => {\n handleCommentBroadcast(comments, payload);\n },\n );\n }\n });\n\n // The watch only unbinds on channel *transitions*. On scope dispose the\n // currently-bound handler stays attached, processing broadcasts on a\n // dead component. Explicitly tear it down.\n onScopeDispose(() => {\n channel.value?.unbind(\"comment-broadcast\");\n });\n}\n\nfunction handleCommentBroadcast(\n comments: UseCommentsReturn,\n payload: CommentBroadcastPayload,\n): void {\n switch (payload.action) {\n case \"comment_created\":\n comments.applyRemoteCreate(payload.comment);\n break;\n case \"comment_updated\":\n comments.applyRemoteUpdate(payload.comment);\n break;\n case \"comment_deleted\":\n comments.applyRemoteDelete(payload.comment.id, payload.comment.parent_id);\n break;\n case \"comment_resolved\":\n case \"comment_unresolved\":\n comments.applyRemoteUpdate(payload.comment);\n break;\n }\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { AuthManager } from \"./auth\";\nimport type { Collaborator, McpOperationPayload } from \"@templatical/types\";\nimport { handleOperation } from \"./mcp-operation-handler\";\nimport type { PresenceMember } from \"./websocket-client\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { computed, onScopeDispose, ref, watch, type Ref } from \"vue\";\n\nconst COLLAB_EVENTS = [\n \"pusher:member_added\",\n \"pusher:member_removed\",\n \"client-block_locked\",\n \"client-block_unlocked\",\n \"client-operation\",\n \"mcp-operation\",\n] as const;\n\nfunction unbindCollabEvents(channel: PresenceChannel): void {\n for (const event of COLLAB_EVENTS) {\n channel.unbind(event);\n }\n}\n\nconst COLLABORATOR_COLORS = [\n \"#3b82f6\",\n \"#ef4444\",\n \"#10b981\",\n \"#f59e0b\",\n \"#8b5cf6\",\n \"#ec4899\",\n \"#06b6d4\",\n \"#f97316\",\n \"#6366f1\",\n \"#14b8a6\",\n];\n\nexport interface UseCollaborationOptions {\n authManager: AuthManager;\n editor: UseEditorReturn;\n channel: Ref<PresenceChannel | null>;\n onError?: (error: Error) => void;\n onCollaboratorJoined?: (collaborator: Collaborator) => void;\n onCollaboratorLeft?: (collaborator: Collaborator) => void;\n onBlockLocked?: (event: {\n blockId: string;\n collaborator: Collaborator;\n }) => void;\n onBlockUnlocked?: (event: {\n blockId: string;\n collaborator: Collaborator;\n }) => void;\n}\n\nexport interface UseCollaborationReturn {\n collaborators: Ref<Collaborator[]>;\n lockedBlocks: Ref<Map<string, Collaborator>>;\n}\n\nexport function useCollaboration(\n options: UseCollaborationOptions,\n): UseCollaborationReturn & {\n _broadcastOperation: (payload: McpOperationPayload) => void;\n _isProcessingRemoteOperation: () => boolean;\n} {\n const { authManager, editor, channel } = options;\n\n const collaborators = ref<Collaborator[]>([]);\n const lockedBlocks = ref<Map<string, Collaborator>>(new Map());\n\n let colorIndex = 0;\n let isProcessingRemoteOperation = false;\n\n const myUserId = computed(() => authManager.userConfig?.id ?? \"\");\n\n function assignColor(): string {\n const color = COLLABORATOR_COLORS[colorIndex % COLLABORATOR_COLORS.length];\n colorIndex++;\n return color;\n }\n\n function addCollaborator(member: PresenceMember): Collaborator | undefined {\n if (member.id === myUserId.value) {\n return undefined;\n }\n\n if (collaborators.value.some((c) => c.id === member.id)) {\n return undefined;\n }\n\n const collaborator: Collaborator = {\n id: member.id,\n name: member.name,\n color: assignColor(),\n selectedBlockId: null,\n };\n\n collaborators.value = [...collaborators.value, collaborator];\n\n return collaborator;\n }\n\n function removeCollaborator(memberId: string): void {\n const newLockedBlocks = new Map(lockedBlocks.value);\n for (const [blockId, collaborator] of newLockedBlocks) {\n if (collaborator.id === memberId) {\n newLockedBlocks.delete(blockId);\n }\n }\n lockedBlocks.value = newLockedBlocks;\n\n collaborators.value = collaborators.value.filter((c) => c.id !== memberId);\n }\n\n function handleBlockLocked(data: { blockId: string; userId: string }): void {\n const collaborator = collaborators.value.find((c) => c.id === data.userId);\n if (!collaborator) {\n return;\n }\n\n collaborators.value = collaborators.value.map((c) =>\n c.id === data.userId ? { ...c, selectedBlockId: data.blockId } : c,\n );\n\n const newLockedBlocks = new Map(lockedBlocks.value);\n for (const [blockId, holder] of newLockedBlocks) {\n if (holder.id === data.userId) {\n newLockedBlocks.delete(blockId);\n }\n }\n\n newLockedBlocks.set(data.blockId, {\n ...collaborator,\n selectedBlockId: data.blockId,\n });\n lockedBlocks.value = newLockedBlocks;\n\n if (editor.state.selectedBlockId === data.blockId) {\n editor.selectBlock(null);\n }\n }\n\n function handleBlockUnlocked(data: { blockId: string }): void {\n const newLockedBlocks = new Map(lockedBlocks.value);\n const holder = newLockedBlocks.get(data.blockId);\n newLockedBlocks.delete(data.blockId);\n lockedBlocks.value = newLockedBlocks;\n\n if (holder) {\n collaborators.value = collaborators.value.map((c) =>\n c.id === holder.id ? { ...c, selectedBlockId: null } : c,\n );\n }\n }\n\n function handleRemoteOperation(payload: McpOperationPayload): void {\n isProcessingRemoteOperation = true;\n try {\n handleOperation(editor, payload);\n } finally {\n isProcessingRemoteOperation = false;\n }\n }\n\n function broadcastOperation(payload: McpOperationPayload): void {\n if (!channel.value || isProcessingRemoteOperation) {\n return;\n }\n\n channel.value.trigger(\"client-operation\", payload);\n }\n\n function broadcastBlockLocked(blockId: string): void {\n if (!channel.value) {\n return;\n }\n\n channel.value.trigger(\"client-block_locked\", {\n blockId,\n userId: myUserId.value,\n });\n }\n\n function broadcastBlockUnlocked(blockId: string): void {\n if (!channel.value) {\n return;\n }\n\n channel.value.trigger(\"client-block_unlocked\", { blockId });\n }\n\n watch(\n () => editor.state.selectedBlockId,\n (newBlockId, oldBlockId) => {\n if (isProcessingRemoteOperation) {\n return;\n }\n\n if (oldBlockId) {\n broadcastBlockUnlocked(oldBlockId);\n }\n\n if (newBlockId) {\n broadcastBlockLocked(newBlockId);\n }\n },\n );\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n unbindCollabEvents(oldChannel);\n }\n\n if (!newChannel) {\n collaborators.value = [];\n lockedBlocks.value = new Map();\n colorIndex = 0;\n return;\n }\n\n const members = (\n newChannel as PresenceChannel & {\n members: {\n each: (\n callback: (member: { id: string; info: PresenceMember }) => void,\n ) => void;\n };\n }\n ).members;\n if (members) {\n members.each((member: { id: string; info: PresenceMember }) => {\n addCollaborator(member.info);\n });\n }\n\n newChannel.bind(\n \"pusher:member_added\",\n (member: { id: string; info: PresenceMember }) => {\n const collaborator = addCollaborator(member.info);\n if (collaborator) {\n options.onCollaboratorJoined?.(collaborator);\n }\n },\n );\n\n newChannel.bind(\n \"pusher:member_removed\",\n (member: { id: string; info: PresenceMember }) => {\n const collaborator = collaborators.value.find(\n (c) => c.id === member.id,\n );\n removeCollaborator(member.id);\n if (collaborator) {\n options.onCollaboratorLeft?.(collaborator);\n }\n },\n );\n\n newChannel.bind(\n \"client-block_locked\",\n (data: { blockId: string; userId: string }) => {\n handleBlockLocked(data);\n const collaborator = collaborators.value.find(\n (c) => c.id === data.userId,\n );\n if (collaborator) {\n options.onBlockLocked?.({\n blockId: data.blockId,\n collaborator,\n });\n }\n },\n );\n\n newChannel.bind(\"client-block_unlocked\", (data: { blockId: string }) => {\n const holder = lockedBlocks.value.get(data.blockId);\n handleBlockUnlocked(data);\n if (holder) {\n options.onBlockUnlocked?.({\n blockId: data.blockId,\n collaborator: holder,\n });\n }\n });\n\n newChannel.bind(\"client-operation\", (payload: McpOperationPayload) => {\n handleRemoteOperation(payload);\n });\n\n newChannel.bind(\"mcp-operation\", (payload: McpOperationPayload) => {\n handleRemoteOperation(payload);\n });\n });\n\n // The watch above only unbinds when the channel ref *changes*. On scope\n // dispose (component unmount) the watch is auto-stopped but the currently\n // bound listeners stay attached forever — handlers fire on a dead component\n // and accumulate on remount. Tear them down explicitly.\n onScopeDispose(() => {\n if (channel.value) {\n unbindCollabEvents(channel.value);\n }\n });\n\n return {\n collaborators,\n lockedBlocks,\n _broadcastOperation: broadcastOperation,\n _isProcessingRemoteOperation: () => isProcessingRemoteOperation,\n };\n}\n","import type { McpOperationPayload } from \"@templatical/types\";\nimport type { UseEditorReturn } from \"../editor\";\n\ninterface BroadcastTarget {\n _broadcastOperation: (payload: McpOperationPayload) => void;\n}\n\n/**\n * Wraps editor mutation methods to broadcast operations to collaboration\n * peers after each mutation executes. Mutates the editor object in place.\n *\n * Must be applied **before** the history interceptor so the call chain is:\n * history.record() → broadcast + original mutation.\n */\nexport function useCollaborationBroadcast(\n editor: UseEditorReturn,\n collaboration: BroadcastTarget,\n): void {\n const originalAddBlock = editor.addBlock;\n const originalUpdateBlock = editor.updateBlock;\n const originalRemoveBlock = editor.removeBlock;\n const originalMoveBlock = editor.moveBlock;\n const originalUpdateSettings = editor.updateSettings;\n const originalSetContent = editor.setContent;\n\n editor.addBlock = (block, targetSectionId?, columnIndex?) => {\n originalAddBlock(block, targetSectionId, columnIndex);\n collaboration._broadcastOperation({\n operation: \"add_block\",\n data: {\n block,\n section_id: targetSectionId,\n column_index: columnIndex,\n },\n timestamp: Date.now(),\n });\n };\n\n editor.updateBlock = (blockId, updates) => {\n originalUpdateBlock(blockId, updates);\n collaboration._broadcastOperation({\n operation: \"update_block\",\n data: { block_id: blockId, updates },\n timestamp: Date.now(),\n });\n };\n\n editor.removeBlock = (blockId) => {\n originalRemoveBlock(blockId);\n collaboration._broadcastOperation({\n operation: \"delete_block\",\n data: { block_id: blockId },\n timestamp: Date.now(),\n });\n };\n\n editor.moveBlock = (blockId, newIndex, targetSectionId?, columnIndex?) => {\n originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);\n collaboration._broadcastOperation({\n operation: \"move_block\",\n data: {\n block_id: blockId,\n index: newIndex,\n section_id: targetSectionId,\n column_index: columnIndex,\n },\n timestamp: Date.now(),\n });\n };\n\n editor.updateSettings = (updates) => {\n originalUpdateSettings(updates);\n collaboration._broadcastOperation({\n operation: \"update_settings\",\n data: { updates },\n timestamp: Date.now(),\n });\n };\n\n editor.setContent = (content, markDirty?) => {\n originalSetContent(content, markDirty);\n collaboration._broadcastOperation({\n operation: \"set_content\",\n data: { content },\n timestamp: Date.now(),\n });\n };\n}\n","import type { AuthManager } from \"./auth\";\nimport type { WebSocketConfig } from \"./websocket-client\";\nimport { WebSocketClient } from \"./websocket-client\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseWebSocketOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UseWebSocketReturn {\n channel: Ref<PresenceChannel | null>;\n isConnected: Ref<boolean>;\n connect: (templateId: string, config: WebSocketConfig) => Promise<void>;\n disconnect: () => void;\n getSocketId: () => string | null;\n}\n\nexport function useWebSocket(options: UseWebSocketOptions): UseWebSocketReturn {\n const { authManager, onError } = options;\n\n const channel = ref<PresenceChannel | null>(\n null,\n ) as Ref<PresenceChannel | null>;\n const isConnected = ref(false);\n\n let wsClient: WebSocketClient | null = null;\n let channelName: string | null = null;\n\n async function connect(\n templateId: string,\n config: WebSocketConfig,\n ): Promise<void> {\n if (wsClient) {\n return;\n }\n\n wsClient = new WebSocketClient({\n authManager,\n config,\n onError,\n });\n\n await wsClient.connect();\n\n channelName = `presence-template.${templateId}`;\n const presenceChannel = wsClient.subscribePresence(channelName);\n\n presenceChannel.bind(\"pusher:subscription_succeeded\", () => {\n isConnected.value = true;\n channel.value = presenceChannel;\n });\n\n presenceChannel.bind(\"pusher:subscription_error\", (error: unknown) => {\n isConnected.value = false;\n channel.value = null;\n onError?.(\n error instanceof Error\n ? error\n : new Error(\"Failed to subscribe to template channel\"),\n );\n });\n }\n\n function disconnect(): void {\n if (channelName && wsClient) {\n wsClient.unsubscribe(channelName);\n }\n\n wsClient?.disconnect();\n wsClient = null;\n channelName = null;\n channel.value = null;\n isConnected.value = false;\n }\n\n function getSocketId(): string | null {\n return wsClient?.getSocketId() ?? null;\n }\n\n return {\n channel,\n isConnected,\n connect,\n disconnect,\n getSocketId,\n };\n}\n","import type { SavedModule } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport type { Block } from \"@templatical/types\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseSavedModulesOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UseSavedModulesReturn {\n modules: Ref<SavedModule[]>;\n isLoading: Ref<boolean>;\n loadModules: (search?: string) => Promise<void>;\n createModule: (name: string, content: Block[]) => Promise<SavedModule>;\n updateModule: (\n id: string,\n data: Partial<{ name: string; content: Block[] }>,\n ) => Promise<SavedModule>;\n deleteModule: (id: string) => Promise<void>;\n}\n\nexport function useSavedModules(\n options: UseSavedModulesOptions,\n): UseSavedModulesReturn {\n const api = new ApiClient(options.authManager);\n\n const modules = ref<SavedModule[]>([]);\n const isLoading = ref(false);\n\n async function loadModules(search?: string): Promise<void> {\n isLoading.value = true;\n try {\n modules.value = await api.listModules(search);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isLoading.value = false;\n }\n }\n\n async function createModule(\n name: string,\n content: Block[],\n ): Promise<SavedModule> {\n try {\n const module = await api.createModule({ name, content });\n modules.value = [module, ...modules.value];\n return module;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n async function updateModule(\n id: string,\n data: Partial<{ name: string; content: Block[] }>,\n ): Promise<SavedModule> {\n try {\n const updated = await api.updateModule(id, data);\n modules.value = modules.value.map((m) => (m.id === id ? updated : m));\n return updated;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n async function deleteModule(id: string): Promise<void> {\n try {\n await api.deleteModule(id);\n modules.value = modules.value.filter((m) => m.id !== id);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n return {\n modules,\n isLoading,\n loadModules,\n createModule,\n updateModule,\n deleteModule,\n };\n}\n","import type { Template, TemplateSnapshot } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseSnapshotHistoryOptions {\n authManager: AuthManager;\n templateId: string;\n onRestore?: (template: Template) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseSnapshotHistoryReturn {\n snapshots: Ref<TemplateSnapshot[]>;\n isLoading: Ref<boolean>;\n isRestoring: Ref<boolean>;\n loadSnapshots: () => Promise<void>;\n restoreSnapshot: (snapshotId: string) => Promise<Template>;\n}\n\nexport function useSnapshotHistory(\n options: UseSnapshotHistoryOptions,\n): UseSnapshotHistoryReturn {\n const api = new ApiClient(options.authManager);\n\n const snapshots = ref<TemplateSnapshot[]>([]);\n const isLoading = ref(false);\n const isRestoring = ref(false);\n\n async function loadSnapshots(): Promise<void> {\n isLoading.value = true;\n try {\n snapshots.value = await api.getSnapshots(options.templateId);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isLoading.value = false;\n }\n }\n\n async function restoreSnapshot(snapshotId: string): Promise<Template> {\n isRestoring.value = true;\n try {\n const template = await api.restoreSnapshot(\n options.templateId,\n snapshotId,\n );\n options.onRestore?.(template);\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isRestoring.value = false;\n }\n }\n\n return {\n snapshots,\n isLoading,\n isRestoring,\n loadSnapshots,\n restoreSnapshot,\n };\n}\n","import type {\n ExportResult,\n Template,\n TestEmailConfig,\n} from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { ApiClient } from \"./api\";\nimport type { ComputedRef, Ref } from \"vue\";\nimport { computed, ref, watch } from \"vue\";\n\nexport interface UseTestEmailOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n save: () => Promise<Template>;\n exportHtml: (templateId: string) => Promise<ExportResult>;\n onError?: (error: Error) => void;\n isAuthReady?: Ref<boolean>;\n onBeforeTestEmail?: (html: string) => string | Promise<string>;\n}\n\nexport interface UseTestEmailReturn {\n isEnabled: ComputedRef<boolean>;\n allowedEmails: ComputedRef<string[]>;\n isSending: Ref<boolean>;\n error: Ref<string | null>;\n sendTestEmail: (recipient: string) => Promise<void>;\n}\n\nexport function useTestEmail(options: UseTestEmailOptions): UseTestEmailReturn {\n const {\n authManager,\n getTemplateId,\n save,\n exportHtml,\n onError,\n isAuthReady,\n onBeforeTestEmail,\n } = options;\n const api = new ApiClient(authManager);\n\n const isSending = ref(false);\n const error = ref<string | null>(null);\n\n const testEmailConfig = ref<TestEmailConfig | null>(null);\n\n if (isAuthReady) {\n watch(\n isAuthReady,\n (ready) => {\n if (ready) {\n testEmailConfig.value = authManager.testEmailConfig;\n }\n },\n { immediate: true },\n );\n }\n\n const isEnabled = computed<boolean>(() => testEmailConfig.value !== null);\n\n const allowedEmails = computed<string[]>(\n () => testEmailConfig.value?.allowedEmails ?? [],\n );\n\n async function sendTestEmail(recipient: string): Promise<void> {\n if (!testEmailConfig.value) {\n throw new Error(\"Test email is not enabled for this project\");\n }\n\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before sending a test email\");\n }\n\n isSending.value = true;\n error.value = null;\n\n try {\n await save();\n\n let { html } = await exportHtml(templateId);\n\n if (onBeforeTestEmail) {\n html = await onBeforeTestEmail(html);\n }\n\n await api.sendTestEmail(templateId, {\n recipient,\n html,\n allowed_emails: testEmailConfig.value.allowedEmails,\n signature: testEmailConfig.value.signature,\n });\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to send test email\", { cause: err });\n error.value = wrappedError.message;\n onError?.(wrappedError);\n throw wrappedError;\n } finally {\n isSending.value = false;\n }\n }\n\n return {\n isEnabled,\n allowedEmails,\n isSending,\n error,\n sendTestEmail,\n };\n}\n","import type { CustomFont, ExportResult, FontsConfig } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\n\nexport interface UseExportOptions {\n authManager: AuthManager;\n getFontsConfig?: () => FontsConfig | undefined;\n canUseCustomFonts?: () => boolean;\n}\n\nexport interface UseExportReturn {\n exportHtml: (templateId: string) => Promise<ExportResult>;\n getMjmlSource: (templateId: string) => Promise<string>;\n}\n\nexport function useExport(options: UseExportOptions): UseExportReturn {\n const { authManager, getFontsConfig, canUseCustomFonts } = options;\n const api = new ApiClient(authManager);\n\n function getExportFontsPayload(): {\n customFonts: CustomFont[];\n defaultFallback: string;\n } {\n const fontsConfig = getFontsConfig?.();\n const customFontsAllowed = canUseCustomFonts?.() ?? true;\n\n return {\n customFonts:\n customFontsAllowed && fontsConfig?.customFonts\n ? fontsConfig.customFonts\n : [],\n defaultFallback: fontsConfig?.defaultFallback ?? \"Arial, sans-serif\",\n };\n }\n\n async function exportHtml(templateId: string): Promise<ExportResult> {\n const fontsPayload = getExportFontsPayload();\n const result = await api.exportTemplate(templateId, fontsPayload);\n\n return {\n html: result.html,\n mjml: result.mjml,\n };\n }\n\n async function getMjmlSource(templateId: string): Promise<string> {\n const fontsPayload = getExportFontsPayload();\n const result = await api.exportTemplate(templateId, fontsPayload);\n return result.mjml;\n }\n\n return {\n exportHtml,\n getMjmlSource,\n };\n}\n","import type { PlanConfig, PlanFeatures } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { computed, ref, type ComputedRef, type Ref } from \"vue\";\n\nexport interface UsePlanConfigOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UsePlanConfigReturn {\n config: Ref<PlanConfig | null>;\n isLoading: Ref<boolean>;\n hasFeature: (feature: keyof PlanFeatures) => boolean;\n features: ComputedRef<PlanFeatures | null>;\n fetchConfig: () => Promise<void>;\n}\n\nexport function usePlanConfig(\n options: UsePlanConfigOptions,\n): UsePlanConfigReturn {\n const { authManager, onError } = options;\n\n const config = ref<PlanConfig | null>(null);\n const isLoading = ref(false);\n\n const apiClient = new ApiClient(authManager);\n\n const features = computed(() => config.value?.features ?? null);\n\n function hasFeature(feature: keyof PlanFeatures): boolean {\n return config.value?.features[feature] ?? false;\n }\n\n async function fetchConfig(): Promise<void> {\n if (isLoading.value) {\n return;\n }\n\n isLoading.value = true;\n\n try {\n config.value = await apiClient.fetchConfig();\n } catch (error) {\n onError?.(\n error instanceof Error\n ? error\n : new Error(\"Failed to fetch config\", { cause: error }),\n );\n } finally {\n isLoading.value = false;\n }\n }\n\n return {\n config,\n isLoading,\n hasFeature,\n features,\n fetchConfig,\n };\n}\n","import type { HealthCheckResult } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES } from \"./url-builder\";\n\ninterface HealthCheckOptions {\n authManager?: AuthManager;\n baseUrl?: string;\n}\n\nconst WS_HANDSHAKE_TIMEOUT = 5000;\n\nfunction resolveHealthUrl(options: HealthCheckOptions): string {\n if (options.authManager) {\n return options.authManager.resolveUrl(API_ROUTES.health);\n }\n\n const base = (options.baseUrl ?? \"https://templatical.com\").replace(\n /\\/$/,\n \"\",\n );\n return `${base}${API_ROUTES.health}`;\n}\n\nasync function checkApiAndAuth(\n url: string,\n authManager?: AuthManager,\n): Promise<{\n api: { ok: boolean; latency: number };\n auth: { ok: boolean; error?: string };\n wsConfig?: { host: string; port: number; app_key: string };\n}> {\n const start = performance.now();\n\n try {\n const response = authManager\n ? await authManager.authenticatedFetch(API_ROUTES.health, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n })\n : await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n });\n\n const latency = Math.round(performance.now() - start);\n\n if (response.status === 401) {\n return {\n api: { ok: true, latency },\n auth: { ok: false, error: \"HTTP 401\" },\n };\n }\n\n if (!response.ok) {\n return {\n api: { ok: false, latency },\n auth: {\n ok: !authManager,\n error: authManager ? `HTTP ${response.status}` : undefined,\n },\n };\n }\n\n const data = await response.json();\n\n return {\n api: { ok: data.status === \"ok\", latency },\n auth: { ok: true },\n wsConfig: data.websocket,\n };\n } catch (error) {\n const latency = Math.round(performance.now() - start);\n\n return {\n api: { ok: false, latency },\n auth: {\n ok: !authManager,\n error: authManager\n ? error instanceof Error\n ? error.message\n : \"Authentication check failed\"\n : undefined,\n },\n };\n }\n}\n\nasync function checkWebSocket(wsConfig?: {\n host: string;\n port: number;\n app_key: string;\n}): Promise<{ ok: boolean; error?: string }> {\n if (!wsConfig?.host || !wsConfig?.app_key) {\n return { ok: false, error: \"WebSocket configuration not available\" };\n }\n\n if (typeof WebSocket === \"undefined\") {\n return {\n ok: false,\n error: \"WebSocket not supported in this environment\",\n };\n }\n\n const protocol = wsConfig.port === 443 ? \"wss\" : \"ws\";\n const url = `${protocol}://${wsConfig.host}:${wsConfig.port}/app/${wsConfig.app_key}?protocol=7&client=js&version=8.4.0-rc2&flash=false`;\n\n return new Promise((resolve) => {\n let ws: WebSocket | null = null;\n\n const timeout = setTimeout(() => {\n ws?.close();\n resolve({ ok: false, error: \"WebSocket connection timed out\" });\n }, WS_HANDSHAKE_TIMEOUT);\n\n try {\n ws = new WebSocket(url);\n } catch (error) {\n // Some browsers throw synchronously from `new WebSocket(...)`\n // (e.g. SecurityError on mixed content, InvalidAccessError on\n // malformed URL). Without this catch the queued timeout would\n // later access `ws` in TDZ and the outer promise would hang.\n clearTimeout(timeout);\n resolve({\n ok: false,\n error:\n error instanceof Error\n ? error.message\n : \"WebSocket connection failed\",\n });\n return;\n }\n\n ws.onopen = () => {\n clearTimeout(timeout);\n ws?.close();\n resolve({ ok: true });\n };\n\n ws.onerror = () => {\n clearTimeout(timeout);\n resolve({ ok: false, error: \"WebSocket connection failed\" });\n };\n });\n}\n\nexport async function performHealthCheck(\n options: HealthCheckOptions = {},\n): Promise<HealthCheckResult> {\n const healthUrl = resolveHealthUrl(options);\n\n const result = await checkApiAndAuth(healthUrl, options.authManager);\n const wsResult = await checkWebSocket(result.wsConfig);\n\n return {\n api: result.api,\n websocket: wsResult,\n auth: result.auth,\n overall: result.api.ok && result.auth.ok,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { McpOperationPayload } from \"@templatical/types\";\nimport { handleOperation } from \"./mcp-operation-handler\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { watch, type Ref } from \"vue\";\n\nexport interface UseMcpListenerOptions {\n editor: UseEditorReturn;\n channel: Ref<PresenceChannel | null>;\n onOperation?: (payload: McpOperationPayload) => void;\n}\n\nexport function useMcpListener(options: UseMcpListenerOptions): void {\n const { editor, channel, onOperation } = options;\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n oldChannel.unbind(\"mcp-operation\");\n }\n\n if (newChannel) {\n newChannel.bind(\"mcp-operation\", (payload: McpOperationPayload) => {\n handleOperation(editor, payload);\n onOperation?.(payload);\n });\n }\n });\n}\n"],"mappings":";AAQA,SAAS,gBAAgB;AAUlB,IAAM,cAAN,MAAM,aAAY;AAAA,EACvB,OAAwB,mBAAmB;AAAA,EAEnC,cAA6B;AAAA,EAC7B,YAAyB;AAAA,EACzB,aAA4B;AAAA,EAC5B,YAA2B;AAAA,EAC3B,cAA6B;AAAA,EAC7B,mBAA2C;AAAA,EAC3C,cAAiC;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,iBAAyC;AAAA,EAEjD,OAAwB,uBAAuB,KAAK;AAAA,EAEpD,YAAY,QAAoB;AAC9B,SAAK,MAAM,OAAO;AAClB,SAAK,WAAW,OAAO,WAAW,aAAY,kBAAkB;AAAA,MAC9D;AAAA,MACA;AAAA,IACF;AACA,SAAK,iBAAiB,OAAO,kBAAkB,CAAC;AAChD,SAAK,UAAU,OAAO;AAAA,EACxB;AAAA,EAEA,WAAW,MAAsB;AAC/B,QAAI,KAAK,WAAW,SAAS,KAAK,KAAK,WAAW,UAAU,GAAG;AAC7D,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiB,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAC7D,WAAO,GAAG,KAAK,OAAO,GAAG,cAAc;AAAA,EACzC;AAAA,EAEA,IAAI,YAAoB;AACtB,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAmB;AACrB,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,mDAAmD;AAAA,IACrE;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,aAAqB;AACvB,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,kBAA0C;AAC5C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,aAAgC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,mBAAkC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,YAAY;AAAA,EACzB;AAAA,EAEA,MAAc,cAA+B;AAC3C,QAAI,KAAK,eAAe,CAAC,KAAK,oBAAoB,GAAG;AACnD,aAAO,KAAK;AAAA,IACd;AACA,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEQ,sBAA+B;AACrC,QAAI,CAAC,KAAK,WAAW;AACnB,aAAO;AAAA,IACT;AACA,UAAM,kBAAkB,KAAK,UAAU,QAAQ,IAAI,KAAK,IAAI;AAC5D,WAAO,kBAAkB,aAAY;AAAA,EACvC;AAAA,EAEA,MAAM,eAAgC;AACpC,QAAI,KAAK,gBAAgB;AACvB,aAAO,KAAK;AAAA,IACd;AAEA,SAAK,iBAAiB,KAAK,eAAe;AAE1C,QAAI;AACF,YAAM,QAAQ,MAAM,KAAK;AACzB,aAAO;AAAA,IACT,UAAE;AACA,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAc,iBAAkC;AAC9C,QAAI;AACF,YAAM,SAAS,KAAK,eAAe,UAAU;AAC7C,YAAM,UAAkC;AAAA,QACtC,QAAQ;AAAA,QACR,GAAG,KAAK,eAAe;AAAA,MACzB;AAEA,YAAM,eAA4B;AAAA,QAChC;AAAA,QACA;AAAA,QACA,aAAa,KAAK,eAAe,eAAe;AAAA,MAClD;AAEA,UAAI,WAAW,UAAU,KAAK,eAAe,MAAM;AACjD,gBAAQ,cAAc,IAAI;AAC1B,qBAAa,OAAO,KAAK,UAAU,KAAK,eAAe,IAAI;AAAA,MAC7D;AAEA,YAAM,WAAW,MAAM,MAAM,KAAK,KAAK,YAAY;AAEnD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI;AAAA,UACR,yBAAyB,SAAS,MAAM;AAAA,UACxC,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,OAAkB,MAAM,SAAS,KAAK;AAE5C,UAAI,CAAC,KAAK,SAAS,CAAC,KAAK,cAAc,CAAC,KAAK,cAAc,CAAC,KAAK,QAAQ;AACvE,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,WAAK,cAAc,KAAK;AACxB,WAAK,YAAY,IAAI,KAAK,KAAK,aAAa,GAAI;AAChD,WAAK,aAAa,KAAK;AACvB,WAAK,cAAc,KAAK;AAExB,UAAI,KAAK,YAAY,kBAAkB,KAAK,YAAY,WAAW;AACjE,aAAK,mBAAmB;AAAA,UACtB,eAAe,KAAK,WAAW;AAAA,UAC/B,WAAW,KAAK,WAAW;AAAA,QAC7B;AAAA,MACF,OAAO;AACL,aAAK,mBAAmB;AAAA,MAC1B;AAEA,UAAI,KAAK,MAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,MAAM,WAAW;AAC5D,aAAK,cAAc;AAAA,UACjB,IAAI,KAAK,KAAK;AAAA,UACd,MAAM,KAAK,KAAK;AAAA,UAChB,WAAW,KAAK,KAAK;AAAA,QACvB;AAAA,MACF,OAAO;AACL,aAAK,cAAc;AAAA,MACrB;AAEA,aAAO,KAAK;AAAA,IACd,SAAS,OAAO;AACd,YAAM,eACJ,iBAAiB,QACb,QACA,IAAI,MAAM,wBAAwB,EAAE,OAAO,MAAM,CAAC;AACxD,WAAK,UAAU,YAAY;AAC3B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,KACA,UAAuB,CAAC,GACL;AACnB,UAAM,QAAQ,MAAM,KAAK,YAAY;AACrC,UAAM,cAAc,KAAK,WAAW,GAAG;AAEvC,UAAM,cAAc,OAAO,cAAyC;AAClE,aAAO,MAAM,aAAa;AAAA,QACxB,GAAG;AAAA,QACH,SAAS;AAAA,UACP,GAAG,QAAQ;AAAA,UACX,eAAe,UAAU,SAAS;AAAA,QACpC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,MAAM,YAAY,KAAK;AAEtC,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,WAAW,MAAM,KAAK,aAAa;AACzC,iBAAW,MAAM,YAAY,QAAQ;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,qBACd,QACA,SACa;AACb,MAAI,OAAO,SAAS,UAAU;AAC5B,UAAM,WAAW,OAAO,WAAW,2BAA2B;AAAA,MAC5D;AAAA,MACA;AAAA,IACF;AAEA,WAAO,IAAI,YAAY;AAAA,MACrB,KAAK,GAAG,OAAO;AAAA,MACf,SAAS,OAAO;AAAA,MAChB,gBAAgB;AAAA,QACd,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM;AAAA,UACJ,WAAW,OAAO;AAAA,UAClB,eAAe,OAAO;AAAA,UACtB,QAAQ,OAAO;AAAA,UACf,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,YAAY;AAAA,IACrB,KAAK,OAAO;AAAA,IACZ,SAAS,OAAO;AAAA,IAChB,gBAAgB,OAAO;AAAA,IACvB;AAAA,EACF,CAAC;AACH;;;ACrPA,SAAS,YAAAA,iBAAgB;;;ACXlB,SAAS,SACd,UACA,QACQ;AACR,SAAO,SAAS;AAAA,IAAQ;AAAA,IAAc,CAAC,GAAG,QACxC,mBAAmB,OAAO,GAAG,KAAK,EAAE;AAAA,EACtC;AACF;AAEA,IAAM,OAAO;AACb,IAAM,WAAW,GAAG,IAAI;AACxB,IAAM,KAAK,GAAG,QAAQ;AACtB,IAAM,QAAQ,GAAG,IAAI;AACrB,IAAM,UAAU,GAAG,KAAK;AACxB,IAAM,UAAU,GAAG,IAAI;AAEhB,IAAM,aAAa;AAAA,EACxB,QAAQ;AAAA,EACR,mBAAmB,GAAG,IAAI;AAAA,EAC1B,qBAAqB,GAAG,IAAI;AAAA,EAC5B,mBAAmB,GAAG,IAAI;AAAA,EAC1B,kBAAkB,GAAG,QAAQ;AAAA,EAC7B,oBAAoB,GAAG,QAAQ;AAAA,EAC/B,qBAAqB,GAAG,QAAQ;AAAA,EAChC,oBAAoB,GAAG,QAAQ;AAAA,EAC/B,+BAA+B,GAAG,IAAI;AAAA,EACtC,2BAA2B,GAAG,QAAQ;AAAA,EACtC,mBAAmB,GAAG,QAAQ;AAAA,EAC9B,mBAAmB,GAAG,QAAQ;AAAA,EAC9B,kBAAkB,GAAG,QAAQ;AAAA,EAC7B,qBAAqB,GAAG,QAAQ;AAAA,EAChC,kBAAkB,GAAG,QAAQ;AAAA,EAC7B,kBAAkB,GAAG,QAAQ;AAAA,EAC7B,mBAAmB,GAAG,QAAQ;AAAA,EAC9B,oBAAoB,GAAG,QAAQ;AAAA,EAC/B,oBAAoB,GAAG,QAAQ;AAAA,EAC/B,eAAe,GAAG,EAAE;AAAA,EACpB,2BAA2B,GAAG,EAAE;AAAA,EAChC,kBAAkB,GAAG,EAAE;AAAA,EACvB,kBAAkB,GAAG,EAAE;AAAA,EACvB,YAAY,GAAG,EAAE;AAAA,EACjB,iBAAiB,GAAG,EAAE;AAAA,EACtB,yBAAyB,GAAG,EAAE;AAAA,EAC9B,gBAAgB,GAAG,KAAK;AAAA,EACxB,gBAAgB,GAAG,KAAK;AAAA,EACxB,gBAAgB,GAAG,KAAK;AAAA,EACxB,cAAc,GAAG,KAAK;AAAA,EACtB,gBAAgB,GAAG,KAAK;AAAA,EACxB,iBAAiB,GAAG,KAAK;AAAA,EACzB,oBAAoB,GAAG,KAAK;AAAA,EAC5B,wBAAwB,GAAG,KAAK;AAAA,EAChC,uBAAuB,GAAG,KAAK;AAAA,EAC/B,iBAAiB,GAAG,OAAO;AAAA,EAC3B,iBAAiB,GAAG,OAAO;AAAA,EAC3B,kBAAkB,GAAG,OAAO;AAAA,EAC5B,mBAAmB,GAAG,OAAO;AAAA,EAC7B,sBAAsB,GAAG,OAAO;AAAA,EAChC,sBAAsB,GAAG,OAAO;AAAA,EAChC,uBAAuB,GAAG,OAAO;AAAA,EACjC,wBAAwB,GAAG,OAAO;AACpC;;;AD5CO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,aAA0B;AAA1B;AAAA,EAA2B;AAAA,EAA3B;AAAA,EAE7B,IAAY,YAAoB;AAC9B,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,IAAY,aAAqB;AAC/B,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,IAAY,aAAqC;AAC/C,WAAO,EAAE,SAAS,KAAK,WAAW,QAAQ,KAAK,WAAW;AAAA,EAC5D;AAAA,EAEA,MAAc,QACZ,MACA,UAAuB,CAAC,GACZ;AACZ,UAAM,WAAW,MAAM,KAAK,YAAY,mBAAmB,MAAM;AAAA,MAC/D,GAAG;AAAA,MACH,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,GAAG,QAAQ;AAAA,MACb;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAkB,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO;AAAA,QACzD,SAAS,cAAc,SAAS,MAAM;AAAA,MACxC,EAAE;AAEF,YAAM,eAAe,KAAK,4BAA4B,KAAK;AAC3D,YAAM,IAAIC,UAAS,cAAc,SAAS,MAAM;AAAA,IAClD;AAEA,QAAI,SAAS,WAAW,KAAK;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,OAAuB,MAAM,SAAS,KAAK;AACjD,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,4BAA4B,OAAyB;AAC3D,QAAI,MAAM,QAAQ;AAChB,YAAM,aAAa,OAAO,KAAK,MAAM,MAAM,EAAE,CAAC;AAC9C,UAAI,cAAc,MAAM,OAAO,UAAU,GAAG,SAAS,GAAG;AACtD,eAAO,MAAM,OAAO,UAAU,EAAE,CAAC;AAAA,MACnC;AAAA,IACF;AACA,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,eAAe,SAA6C;AAChE,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,iBAAiB,GAAG,KAAK,UAAU;AAAA,MACvD;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,EAAE,QAAQ,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,IAA+B;AAC/C,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,gBAAgB,GAAG;AAAA,QACrC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,IACA,SACmB;AACnB,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,kBAAkB,GAAG;AAAA,QACvC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,MACZ,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,EAAE,QAAQ,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,YACA,SAC2B;AAC3B,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,iBAAiB,GAAG;AAAA,QACtC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,MACZ,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,EAAE,QAAQ,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,IAA2B;AAC9C,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,mBAAmB,GAAG;AAAA,QACxC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,MACZ,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,YAAiD;AAClE,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,iBAAiB,GAAG;AAAA,QACtC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,YACA,YACmB;AACnB,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,mBAAmB,GAAG;AAAA,QACxC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,QACV,UAAU;AAAA,MACZ,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,YACA,cAIyC;AACzC,UAAM,OAAO,eACT,KAAK,UAAU;AAAA,MACb,cAAc,aAAa;AAAA,MAC3B,kBAAkB,aAAa;AAAA,IACjC,CAAC,IACD;AAEJ,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,kBAAkB,GAAG;AAAA,QACvC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,MACZ,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,YACA,SAMe;AACf,UAAM,KAAK;AAAA,MACT,SAAS,WAAW,yBAAyB,GAAG;AAAA,QAC9C,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,MACZ,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAY,YAAoB,WAA4B;AAClE,QAAI,WAAW;AACb,aAAO,SAAS,WAAW,iBAAiB,GAAG;AAAA,QAC7C,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,QACV,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO,SAAS,WAAW,gBAAgB,GAAG;AAAA,MAC5C,GAAG,KAAK;AAAA,MACR,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YAAY,YAAwC;AACxD,WAAO,KAAK,QAAmB,KAAK,YAAY,UAAU,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,cACJ,YACA,MAQA,SACkB;AAClB,WAAO,KAAK,QAAiB,KAAK,YAAY,UAAU,GAAG;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cACJ,YACA,WACA,MAMA,SACkB;AAClB,WAAO,KAAK,QAAiB,KAAK,YAAY,YAAY,SAAS,GAAG;AAAA,MACpE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cACJ,YACA,WACA,MAKA,SACe;AACf,WAAO,KAAK,QAAc,KAAK,YAAY,YAAY,SAAS,GAAG;AAAA,MACjE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eACJ,YACA,WACA,MAKA,SACkB;AAClB,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,kBAAkB,GAAG;AAAA,QACvC,GAAG,KAAK;AAAA,QACR,UAAU;AAAA,QACV,SAAS;AAAA,MACX,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,cAAmC;AACvC,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,iBAAiB,GAAG,KAAK,UAAU;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,QAAyC;AACzD,UAAM,MAAM,SAAS,WAAW,oBAAoB,GAAG,KAAK,UAAU;AACtE,UAAM,QAAQ,SAAS,WAAW,mBAAmB,MAAM,CAAC,KAAK;AACjE,WAAO,KAAK,QAAuB,GAAG,GAAG,GAAG,KAAK,EAAE;AAAA,EACrD;AAAA,EAEA,MAAM,aAAa,MAGM;AACvB,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,oBAAoB,GAAG,KAAK,UAAU;AAAA,MAC1D;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aACJ,IACA,MACsB;AACtB,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,qBAAqB,GAAG;AAAA,QAC1C,GAAG,KAAK;AAAA,QACR,aAAa;AAAA,MACf,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,IAA2B;AAC5C,WAAO,KAAK;AAAA,MACV,SAAS,WAAW,sBAAsB,GAAG;AAAA,QAC3C,GAAG,KAAK;AAAA,QACR,aAAa;AAAA,MACf,CAAC;AAAA,MACD;AAAA,QACE,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;;;AEpVO,SAAS,uBACd,cACiB;AACjB,SAAO;AAAA,IACL,MAAM,aAAa;AAAA,IACnB,MAAM,aAAa;AAAA,IACnB,QAAQ,aAAa;AAAA,EACvB;AACF;AAcO,IAAM,kBAAN,MAAsB;AAAA,EACnB,SAA4B;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAAiC;AAC3C,SAAK,cAAc,QAAQ;AAC3B,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,OAAC,EAAE,SAAS,OAAO,IAAI,MAAM,OAAO,WAAW;AAAA,IACjD,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,MAAM,OAAO,IAAI,KAAK;AACpC,UAAM,eAAe,KAAK,YAAY;AAAA,MACpC,SAAS,WAAW,mBAAmB,GAAG;AAAA,QACxC,SAAS,KAAK,YAAY;AAAA,QAC1B,QAAQ,KAAK,YAAY;AAAA,MAC3B,CAAC;AAAA,IACH;AAEA,SAAK,SAAS,IAAI,OAAO,QAAQ;AAAA,MAC/B,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,cAAc;AAAA,MACd,mBAAmB,CAAC,MAAM,KAAK;AAAA,MAC/B,SAAS;AAAA,MACT,sBAAsB;AAAA,QACpB,WAAW;AAAA,QACX,UAAU;AAAA,QACV,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,YAAY,gBAAgB;AAAA,UAC1D,QAAQ;AAAA,QACV;AAAA,QACA,QAAQ;AAAA,UACN,SAAS,KAAK,YAAY,YAAY,MAAM;AAAA,UAC5C,WAAW,KAAK,YAAY,YAAY,QAAQ;AAAA,UAChD,gBAAgB,KAAK,YAAY,YAAY,aAAa;AAAA,QAC5D;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,OAAO,WAAW,KAAK,SAAS,CAAC,UAAmB;AACvD,WAAK;AAAA,QACH,iBAAiB,QACb,QACA,IAAI,MAAM,4BAA4B;AAAA,MAC5C;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB,aAAsC;AACtD,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAEA,WAAO,KAAK,OAAO,UAAU,WAAW;AAAA,EAC1C;AAAA,EAEA,YAAY,aAA2B;AACrC,SAAK,QAAQ,YAAY,WAAW;AAAA,EACtC;AAAA,EAEA,WAAW,aAA0C;AACnD,WAAO,KAAK,QAAQ,QAAQ,WAAW;AAAA,EACzC;AAAA,EAEA,aAAmB;AACjB,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,WAAW;AACvB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,cAA6B;AAC3B,WAAO,KAAK,QAAQ,WAAW,aAAa;AAAA,EAC9C;AAAA,EAEA,IAAI,cAAuB;AACzB,WAAO,KAAK,QAAQ,WAAW,UAAU;AAAA,EAC3C;AACF;;;AC5HO,SAAS,gBACd,QACA,SACM;AACN,QAAM,EAAE,WAAW,KAAK,IAAI;AAE5B,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA;AAAA,IAEF,KAAK;AACH,aAAO;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA;AAAA,IAEF,KAAK;AACH,aAAO,YAAY,KAAK,QAAkB;AAC1C;AAAA,IAEF,KAAK;AACH,aAAO;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA;AAAA,IAEF,KAAK;AACH,aAAO,eAAe,KAAK,OAAoC;AAC/D;AAAA,IAEF,KAAK;AACH,aAAO,WAAW,KAAK,OAA0B;AACjD;AAAA,IAEF,KAAK;AACH,aAAO;AAAA,QACL,KAAK;AAAA,QACL;AAAA,UACE,QAAQ,KAAK;AAAA,QACf;AAAA,MACF;AACA;AAAA,EACJ;AACF;;;ACtDA,SAAS,YAAAC,iBAAgB;AAQzB,SAAS,oCAAoC;AAC7C,SAAS,UAAU,UAAU,gBAA6C;AA6CnE,SAAS,UAAU,SAA4C;AACpE,QAAM,MAAM,IAAI,UAAU,QAAQ,WAAW;AAE7C,QAAM,QAAQ,SAAsB;AAAA,IAClC,UAAU;AAAA,IACV,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,IACb,SAAS;AAAA,IACT,UAAU;AAAA,IACV,WAAW;AAAA,IACX,SAAS;AAAA,EACX,CAAC;AAED,QAAM,UAAU,SAAS;AAAA,IACvB,KAAK,MAAM,MAAM;AAAA,IACjB,KAAK,CAAC,UAA2B;AAC/B,YAAM,UAAU;AAChB,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,gBAAgB,SAAS,MAAM;AACnC,QAAI,CAAC,MAAM,gBAAiB,QAAO;AACnC,WAAO,cAAc,MAAM,QAAQ,QAAQ,MAAM,eAAe;AAAA,EAClE,CAAC;AAED,QAAM,gBAAgB,SAAsB,MAAM;AAChD,UAAM,MAAM,oBAAI,IAAY;AAC5B,UAAM,SAAS,MAAM,UAAU,SAAS;AACxC,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AACA,eAAW,SAAS,QAAQ;AAC1B,UAAI,IAAI,MAAM,EAAE;AAChB,UAAI,MAAM,SAAS,WAAW;AAC5B,mBAAW,UAAU,MAAM,UAAU;AACnC,qBAAW,SAAS,QAAQ;AAC1B,gBAAI,IAAI,MAAM,EAAE;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAED,WAAS,cAAc,QAAiB,IAA0B;AAChE,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,OAAO,GAAI,QAAO;AAC5B,UAAI,MAAM,SAAS,WAAW;AAC5B,mBAAW,UAAU,MAAM,UAAU;AACnC,gBAAM,QAAQ,cAAc,QAAQ,EAAE;AACtC,cAAI,MAAO,QAAO;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,gBACP,QACA,IACA,SAII,EAAE,OAAO,GACyD;AACtE,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,QAAQ,OAAO,CAAC;AACtB,UAAI,MAAM,OAAO,GAAI,QAAO;AAC5B,UAAI,MAAM,SAAS,WAAW;AAC5B,iBAAS,SAAS,GAAG,SAAS,MAAM,SAAS,QAAQ,UAAU;AAC7D,gBAAM,SAAS,gBAAgB,MAAM,SAAS,MAAM,GAAG,IAAI;AAAA,YACzD,QAAQ,MAAM,SAAS,MAAM;AAAA,YAC7B,WAAW,MAAM;AAAA,YACjB,aAAa;AAAA,UACf,CAAC;AACD,cAAI,OAAQ,QAAO;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,cAAc,SAA0B;AAC/C,WAAO,QAAQ,cAAc,MAAM,IAAI,OAAO,KAAK;AAAA,EACrD;AAEA,WAAS,WAAW,YAA6BC,aAAY,MAAY;AACvE,UAAM,UAAU;AAChB,QAAIA,YAAW;AACb,YAAM,UAAU;AAAA,IAClB;AAAA,EACF;AAEA,WAAS,YAAY,SAA8B;AACjD,QAAI,WAAW,cAAc,OAAO,GAAG;AACrC;AAAA,IACF;AACA,UAAM,kBAAkB;AAAA,EAC1B;AAEA,WAAS,YAAY,UAA8B;AACjD,UAAM,WAAW;AAAA,EACnB;AAEA,WAAS,YAAY,UAAyB;AAC5C,UAAM,WAAW;AAAA,EACnB;AAEA,WAAS,WAAW,OAAsB;AACxC,UAAM,UAAU;AAAA,EAClB;AAEA,WAAS,eAAe,aAA4B;AAClD,UAAM,cAAc;AACpB,QAAI,aAAa;AACf,YAAM,kBAAkB;AAAA,IAC1B;AAAA,EACF;AAEA,WAAS,YAAY,SAAiB,SAA+B;AACnE,QAAI,cAAc,OAAO,GAAG;AAC1B;AAAA,IACF;AACA,UAAM,QAAQ,cAAc,MAAM,QAAQ,QAAQ,OAAO;AACzD,QAAI,OAAO;AACT,aAAO,OAAO,OAAO,OAAO;AAC5B,YAAM,UAAU;AAAA,IAClB;AAAA,EACF;AAEA,WAAS,eAAe,SAA0C;AAChE,UAAM,QAAQ,WAAW,EAAE,GAAG,MAAM,QAAQ,UAAU,GAAG,QAAQ;AACjE,UAAM,UAAU;AAAA,EAClB;AAEA,WAAS,SACP,OACA,iBACA,cAAc,GACd,OACM;AACN,QAAI,iBAAiB;AACnB,YAAM,UAAU,cAAc,MAAM,QAAQ,QAAQ,eAAe;AACnE,UAAI,WAAW,QAAQ,SAAS,WAAW;AACzC,gBAAQ,SAAS,WAAW,IAAI,QAAQ,SAAS,WAAW,KAAK,CAAC;AAClE,cAAM,cAAc,QAAQ,SAAS,WAAW;AAChD,YAAI,UAAU,UAAa,QAAQ,YAAY,QAAQ;AACrD,sBAAY,OAAO,OAAO,GAAG,KAAK;AAAA,QACpC,OAAO;AACL,sBAAY,KAAK,KAAK;AAAA,QACxB;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,UAAU,UAAa,QAAQ,MAAM,QAAQ,OAAO,QAAQ;AAC9D,cAAM,QAAQ,OAAO,OAAO,OAAO,GAAG,KAAK;AAAA,MAC7C,OAAO;AACL,cAAM,QAAQ,OAAO,KAAK,KAAK;AAAA,MACjC;AAAA,IACF;AACA,UAAM,UAAU;AAAA,EAClB;AAEA,WAAS,YAAY,SAAuB;AAC1C,QAAI,cAAc,OAAO,GAAG;AAC1B;AAAA,IACF;AACA,UAAM,SAAS,gBAAgB,MAAM,QAAQ,QAAQ,OAAO;AAC5D,QAAI,QAAQ;AACV,YAAM,QAAQ,OAAO,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AAC7D,UAAI,UAAU,IAAI;AAChB,eAAO,OAAO,OAAO,OAAO,CAAC;AAC7B,YAAI,MAAM,oBAAoB,SAAS;AACrC,gBAAM,kBAAkB;AAAA,QAC1B;AACA,cAAM,UAAU;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,WAAS,UACP,SACA,UACA,iBACA,cAAc,GACR;AACN,UAAM,SAAS,gBAAgB,MAAM,QAAQ,QAAQ,OAAO;AAC5D,QAAI,CAAC,OAAQ;AAEb,UAAM,WAAW,OAAO,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AAChE,QAAI,aAAa,GAAI;AAErB,UAAM,CAAC,KAAK,IAAI,OAAO,OAAO,OAAO,UAAU,CAAC;AAEhD,QAAI,iBAAiB;AACnB,YAAM,UAAU,cAAc,MAAM,QAAQ,QAAQ,eAAe;AACnE,UAAI,WAAW,QAAQ,SAAS,WAAW;AACzC,gBAAQ,SAAS,WAAW,IAAI,QAAQ,SAAS,WAAW,KAAK,CAAC;AAClE,gBAAQ,SAAS,WAAW,EAAE,OAAO,UAAU,GAAG,KAAK;AAAA,MACzD;AAAA,IACF,OAAO;AACL,YAAM,QAAQ,OAAO,OAAO,UAAU,GAAG,KAAK;AAAA,IAChD;AAEA,UAAM,UAAU;AAAA,EAClB;AAEA,iBAAe,OAAOC,UAA8C;AAClE,UAAM,YAAY;AAClB,QAAI;AACF,UAAIA,UAAS;AACX,cAAM,UAAUA;AAAA,MAClB;AACA,YAAM,WAAW,MAAM,IAAI,eAAe,MAAM,OAAO;AACvD,YAAM,WAAW;AACjB,YAAM,UAAU;AAChB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR,UAAE;AACA,YAAM,YAAY;AAAA,IACpB;AAAA,EACF;AAEA,iBAAe,KAAK,YAAuC;AACzD,UAAM,YAAY;AAClB,QAAI;AACF,YAAM,WAAW,MAAM,IAAI,YAAY,UAAU;AACjD,YAAM,WAAW;AACjB,YAAM,UAAU,SAAS;AACzB,YAAM,UAAU;AAChB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR,UAAE;AACA,YAAM,YAAY;AAAA,IACpB;AAAA,EACF;AAEA,iBAAe,OAA0B;AACvC,QAAI,CAAC,MAAM,UAAU,IAAI;AACvB,YAAM,IAAIC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW;AACjB,QAAI;AACF,YAAM,WAAW,MAAM,IAAI;AAAA,QACzB,MAAM,SAAS;AAAA,QACf,MAAM;AAAA,MACR;AACA,YAAM,WAAW;AACjB,YAAM,UAAU;AAChB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR,UAAE;AACA,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAEA,iBAAe,iBAAgC;AAC7C,QAAI,CAAC,MAAM,UAAU,IAAI;AACvB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,IAAI,eAAe,MAAM,SAAS,IAAI,MAAM,OAAO;AAAA,IAC3D,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAEA,WAAS,cAAuB;AAC9B,WAAO,MAAM,UAAU,OAAO;AAAA,EAChC;AAEA,WAAS,YAAkB;AACzB,UAAM,UAAU;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,OAAO,SAAS,KAAK;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACtXA,SAAS,WAAW;AAiCpB,IAAI,mBAAmB;AAEvB,SAAS,oBAA4B;AACnC,SAAO,OAAO,KAAK,IAAI,CAAC,IAAI,EAAE,gBAAgB;AAChD;AAEO,SAAS,UAAU,SAA4C;AACpE,QAAM,EAAE,aAAa,eAAe,SAAS,QAAQ,IAAI;AAEzD,QAAM,WAAW,IAAqB,CAAC,CAAC;AACxC,QAAM,eAAe,IAAI,KAAK;AAC9B,QAAM,mBAAmB,IAAI,KAAK;AAClC,QAAM,QAAQ,IAAmB,IAAI;AACrC,QAAM,eAAe,IAAmB,IAAI;AAC5C,QAAM,iBAAiB,IAAmB,IAAI;AAC9C,QAAM,qBAAqB,IAAmB,IAAI;AAClD,QAAM,sBAAsB,IAA4B,IAAI;AAC5D,QAAM,qBAAqB,IAA4B,IAAI;AAC3D,QAAM,uBAAuB,IAAI,KAAK;AACtC,QAAM,cAAc,IAAc,CAAC,CAAC;AACpC,QAAM,uBAAuB,IAAI,KAAK;AAEtC,WAAS,cAAc,OAAe,SAAuC;AAC3E,UAAM,MAAM,SAAS,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,KAAK;AAC1D,QAAI,QAAQ,IAAI;AACd;AAAA,IACF;AAEA,UAAM,UAAU,EAAE,GAAG,SAAS,MAAM,GAAG,GAAG,GAAG,QAAQ;AACrD,aAAS,QAAQ;AAAA,MACf,GAAG,SAAS,MAAM,MAAM,GAAG,GAAG;AAAA,MAC9B;AAAA,MACA,GAAG,SAAS,MAAM,MAAM,MAAM,CAAC;AAAA,IACjC;AAAA,EACF;AAEA,iBAAe,mBAAkC;AAC/C,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf;AAAA,IACF;AAEA,qBAAiB,QAAQ;AAEzB,QAAI;AACF,YAAM,MAAM,SAAS,WAAW,yBAAyB,GAAG;AAAA,QAC1D,SAAS,YAAY;AAAA,QACrB,QAAQ,YAAY;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,WAAW,MAAM,YAAY,mBAAmB,KAAK;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,UAAI,KAAK,iBAAiB;AACxB,uBAAe,QAAQ,KAAK;AAAA,MAC9B;AAEA,UAAI,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,GAAG;AACpD,iBAAS,QAAQ,KAAK,KAAK;AAAA,UACzB,CAAC,SAKM;AAAA,YACL,IAAI,IAAI;AAAA,YACR,MAAM,IAAI;AAAA,YACV,SAAS,IAAI;AAAA,YACb,WAAW,IAAI,KAAK,IAAI,UAAU,EAAE,QAAQ;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER,UAAE;AACA,uBAAiB,QAAQ;AAAA,IAC3B;AAAA,EACF;AAEA,iBAAe,gBACb,gBACA,WACe;AACf,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf;AAAA,IACF;AAEA,yBAAqB,QAAQ;AAE7B,QAAI;AACF,YAAM,MAAM,SAAS,WAAW,gBAAgB,GAAG;AAAA,QACjD,SAAS,YAAY;AAAA,QACrB,QAAQ,YAAY;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,WAAW,MAAM,YAAY,mBAAmB,KAAK;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QACV;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,iBAAiB;AAAA,UACjB,YAAY,UAAU,IAAI,CAAC,OAAO;AAAA,YAChC,OAAO,EAAE;AAAA,YACT,OAAO,EAAE;AAAA,UACX,EAAE;AAAA,QACJ,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB;AAAA,MACF;AAEA,YAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AAEA,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AAEb,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,MAAM;AACR;AAAA,QACF;AAEA,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACxB,cAAI,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC9B;AAAA,UACF;AAEA,cAAI;AACJ,cAAI;AACF,oBAAQ,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AAAA,UAClC,QAAQ;AACN;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,UAAU,MAAM,QAAQ,MAAM,WAAW,GAAG;AAC7D,wBAAY,QAAQ,MAAM,YAAY,MAAM,GAAG,CAAC;AAAA,UAClD;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER,UAAE;AACA,2BAAqB,QAAQ;AAAA,IAC/B;AAAA,EACF;AAEA,iBAAe,WACb,QACA,gBACA,WACiC;AACjC,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,mDAAmD;AAAA,IACrE;AAEA,iBAAa,QAAQ;AACrB,UAAM,QAAQ;AACd,iBAAa,QAAQ;AACrB,gBAAY,QAAQ,CAAC;AAErB,UAAM,YAAY,kBAAkB;AACpC,aAAS,QAAQ;AAAA,MACf,GAAG,SAAS;AAAA,MACZ;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,KAAK,IAAI;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,iBAAiB,kBAAkB;AACzC,aAAS,QAAQ;AAAA,MACf,GAAG,SAAS;AAAA,MACZ;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,KAAK,IAAI;AAAA,MACtB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,SAAS,WAAW,aAAa,GAAG;AAAA,QAC9C,SAAS,YAAY;AAAA,QACrB,QAAQ,YAAY;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,WAAW,MAAM,YAAY,mBAAmB,KAAK;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QACV;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,iBAAiB;AAAA,UACjB,YAAY,UAAU,IAAI,CAAC,OAAO;AAAA,YAChC,OAAO,EAAE;AAAA,YACT,OAAO,EAAE;AAAA,UACX,EAAE;AAAA,UACF,iBAAiB,eAAe;AAAA,QAClC,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,YAAI,SAAS,WAAW,KAAK;AAC3B,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AACA,cAAM,IAAI,MAAM,WAAW,WAAW,6BAA6B;AAAA,MACrE;AAEA,YAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AACb,UAAI,SAAiC;AAErC,UAAI;AACF,eAAO,MAAM;AACX,gBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,cAAI,MAAM;AACR;AAAA,UACF;AAEA,oBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,gBAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,mBAAS,MAAM,IAAI,KAAK;AAExB,qBAAW,QAAQ,OAAO;AACxB,gBAAI,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC9B;AAAA,YACF;AAEA,kBAAM,UAAU,KAAK,MAAM,CAAC;AAE5B,gBAAI;AACJ,gBAAI;AACF,sBAAQ,KAAK,MAAM,OAAO;AAAA,YAC5B,QAAQ;AACN;AAAA,YACF;AAEA,gBAAI,MAAM,SAAS,QAAQ;AACzB,4BAAc,gBAAgB;AAAA,gBAC5B,UACG,SAAS,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc,GAC/C,WAAW,MAAM,MAAM;AAAA,cAC/B,CAAC;AAAA,YACH,WAAW,MAAM,SAAS,SAAS;AACjC,oBAAM,IAAI,MAAM,MAAM,WAAW,6BAA6B;AAAA,YAChE,WAAW,MAAM,SAAS,QAAQ;AAChC,kBAAI,MAAM,iBAAiB;AACzB,+BAAe,QAAQ,MAAM;AAAA,cAC/B;AAEA,4BAAc,gBAAgB;AAAA,gBAC5B,SAAS,MAAM;AAAA,cACjB,CAAC;AAED,uBAAS,MAAM,WAAW;AAE1B,kBAAI,QAAQ;AACV,oCAAoB,QAAQ;AAC5B,mCAAmB,QAAQ;AAC3B,mCAAmB,QAAQ;AAC3B,qCAAqB,QAAQ;AAC7B,0BAAU,MAAM;AAAA,cAClB,OAAO;AACL,sBAAM,QAAQ;AAAA,cAChB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF,UAAE;AAIA,eAAO,OAAO,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAChC;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,+BAA+B,EAAE,OAAO,IAAI,CAAC;AAC7D,YAAM,QAAQ,aAAa;AAC3B,mBAAa,QAAQ;AACrB,gBAAU,YAAY;AAEtB,eAAS,QAAQ,SAAS,MAAM;AAAA,QAC9B,CAAC,MAAM,EAAE,OAAO,aAAa,EAAE,OAAO;AAAA,MACxC;AAEA,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAEA,WAAS,mBAAyB;AAChC,QAAI,qBAAqB,OAAO;AAC9B,UAAI,mBAAmB,OAAO;AAC5B,kBAAU,mBAAmB,KAAK;AAAA,MACpC;AACA,2BAAqB,QAAQ;AAAA,IAC/B,OAAO;AACL,UAAI,oBAAoB,OAAO;AAC7B,kBAAU,oBAAoB,KAAK;AAAA,MACrC;AACA,2BAAqB,QAAQ;AAAA,IAC/B;AAAA,EACF;AAEA,WAAS,YAAkB;AACzB,aAAS,QAAQ,CAAC;AAClB,mBAAe,QAAQ;AACvB,UAAM,QAAQ;AACd,uBAAmB,QAAQ;AAC3B,wBAAoB,QAAQ;AAC5B,uBAAmB,QAAQ;AAC3B,yBAAqB,QAAQ;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACtZA,SAAS,OAAAC,YAAW;AAwBb,SAAS,aAAa,SAAkD;AAC7E,QAAM,EAAE,aAAa,cAAc,IAAI;AAEvC,QAAM,cAAcA,KAAI,KAAK;AAC7B,QAAM,gBAAgBA,KAAI,EAAE;AAC5B,QAAM,kBAAkBA,KAAmB,IAAI;AAC/C,QAAM,mBAAmBA,KAAmB,IAAI;AAChD,QAAM,aAAaA,KAAI,KAAK;AAC5B,QAAM,QAAQA,KAAmB,IAAI;AAErC,iBAAe,QACb,SACA,aACA,WACwB;AACxB,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,gBAAY,QAAQ;AACpB,kBAAc,QAAQ;AACtB,UAAM,QAAQ;AAEd,QAAI;AACF,YAAM,MAAM,SAAS,WAAW,gBAAgB,GAAG;AAAA,QACjD,SAAS,YAAY;AAAA,QACrB,QAAQ,YAAY;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,WAAW,MAAM,YAAY,mBAAmB,KAAK;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QACV;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA,YAAY,UAAU,IAAI,CAAC,OAAO;AAAA,YAChC,OAAO,EAAE;AAAA,YACT,OAAO,EAAE;AAAA,UACX,EAAE;AAAA,QACJ,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,YAAI,SAAS,WAAW,KAAK;AAC3B,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AACA,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,cAAM,IAAI,MAAM,WAAW,WAAW,wBAAwB;AAAA,MAChE;AAEA,YAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AACb,UAAI,SAAwB;AAE5B,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,MAAM;AACR;AAAA,QACF;AAEA,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACxB,cAAI,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC9B;AAAA,UACF;AAEA,cAAI;AACJ,cAAI;AACF,oBAAQ,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AAAA,UAClC,QAAQ;AACN;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,QAAQ;AACzB,0BAAc,SAAS,MAAM;AAAA,UAC/B,WAAW,MAAM,SAAS,SAAS;AACjC,kBAAM,IAAI,MAAM,MAAM,WAAW,wBAAwB;AAAA,UAC3D,WAAW,MAAM,SAAS,QAAQ;AAChC,qBAAS,MAAM,WAAW;AAE1B,gBAAI,QAAQ;AACV,8BAAgB,QAAQ;AACxB,+BAAiB,QAAQ;AACzB,yBAAW,QAAQ;AAAA,YACrB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,QACJ,eAAe,QAAQ,IAAI,UAAU;AACvC,aAAO;AAAA,IACT,UAAE;AACA,kBAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AAEA,WAAS,OAAsB;AAC7B,QAAI,CAAC,gBAAgB,OAAO;AAC1B,aAAO;AAAA,IACT;AAEA,eAAW,QAAQ;AACnB,WAAO,gBAAgB;AAAA,EACzB;AAEA,WAAS,OAAsB;AAC7B,QAAI,CAAC,iBAAiB,OAAO;AAC3B,aAAO;AAAA,IACT;AAEA,eAAW,QAAQ;AACnB,WAAO,iBAAiB;AAAA,EAC1B;AAEA,WAAS,QAAc;AACrB,gBAAY,QAAQ;AACpB,kBAAc,QAAQ;AACtB,oBAAgB,QAAQ;AACxB,qBAAiB,QAAQ;AACzB,eAAW,QAAQ;AACnB,UAAM,QAAQ;AAAA,EAChB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AClLA,SAAS,YAAAC,iBAAkC;AAOpC,SAAS,YAAY,QAA8C;AACxE,WAAS,iBAAiB,SAAkC;AAC1D,QAAI,WAAW,OAAO;AACpB,aAAO;AAAA,IACT;AAEA,WAAO,SAAS,OAAO,MAAM;AAAA,EAC/B;AAEA,QAAM,oBAAoBA;AAAA,IACxB,MACE,iBAAiB,MAAM,KACvB,iBAAiB,SAAS,KAC1B,iBAAiB,kBAAkB;AAAA,EACvC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;;;ACpBA,SAAS,OAAAC,YAAW;AA2Bb,SAAS,mBACd,SAC0B;AAC1B,QAAM,EAAE,aAAa,cAAc,IAAI;AAEvC,QAAM,YAAYA,KAAI,KAAK;AAC3B,QAAM,gBAAgBA,KAA0B,IAAI;AACpD,QAAM,QAAQA,KAAmB,IAAI;AACrC,QAAM,kBAAkBA,KAAmB,IAAI;AAC/C,QAAM,mBAAmBA,KAAI,EAAE;AAC/B,QAAM,WAAWA,KAAmB,IAAI;AAExC,iBAAe,MACb,SACA,WAC+B;AAC/B,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,cAAU,QAAQ;AAClB,UAAM,QAAQ;AACd,kBAAc,QAAQ;AAEtB,QAAI;AACF,YAAM,MAAM,SAAS,WAAW,UAAU,GAAG;AAAA,QAC3C,SAAS,YAAY;AAAA,QACrB,QAAQ,YAAY;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,WAAW,MAAM,YAAY,mBAAmB,KAAK;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QACV;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,iBAAiB;AAAA,UACjB,YAAY,UAAU,IAAI,CAAC,OAAO;AAAA,YAChC,OAAO,EAAE;AAAA,YACT,OAAO,EAAE;AAAA,UACX,EAAE;AAAA,QACJ,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,YAAI,SAAS,WAAW,KAAK;AAC3B,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AACA,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,cAAM,IAAI,MAAM,WAAW,WAAW,0BAA0B;AAAA,MAClE;AAEA,YAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AACb,UAAI,SAA+B;AAEnC,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,MAAM;AACR;AAAA,QACF;AAEA,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACxB,cAAI,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC9B;AAAA,UACF;AAEA,cAAI;AACJ,cAAI;AACF,oBAAQ,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AAAA,UAClC,QAAQ;AACN;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,SAAS;AAC1B,kBAAM,IAAI,MAAM,MAAM,WAAW,0BAA0B;AAAA,UAC7D;AAEA,cAAI,MAAM,SAAS,QAAQ;AACzB,qBAAS,MAAM,UAAU;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAEA,UAAI,QAAQ;AACV,mBAAW,CAAC,UAAU,YAAY,KAAK,OAAO;AAAA,UAC5C,OAAO;AAAA,QACT,GAAG;AACD,qBAAW,WAAW,aAAa,UAAU;AAC3C,oBAAQ,WAAW;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAEA,oBAAc,QAAQ;AACtB,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,QACJ,eAAe,QAAQ,IAAI,UAAU;AACvC,aAAO;AAAA,IACT,UAAE;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,iBAAe,WACb,cACA,SACA,WACwB;AACxB,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,oBAAgB,QAAQ,QAAQ;AAChC,qBAAiB,QAAQ;AACzB,aAAS,QAAQ;AAEjB,QAAI;AACF,YAAM,MAAM,SAAS,WAAW,eAAe,GAAG;AAAA,QAChD,SAAS,YAAY;AAAA,QACrB,QAAQ,YAAY;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,WAAW,MAAM,YAAY,mBAAmB,KAAK;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,QACV;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS;AAAA,UACT,SAAS;AAAA,YACP,IAAI,QAAQ;AAAA,YACZ,SAAS,QAAQ;AAAA,YACjB,YAAY,QAAQ;AAAA,YACpB,UAAU,QAAQ;AAAA,UACpB;AAAA,UACA,YAAY,UAAU,IAAI,CAAC,OAAO;AAAA,YAChC,OAAO,EAAE;AAAA,YACT,OAAO,EAAE;AAAA,UACX,EAAE;AAAA,QACJ,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,YAAI,SAAS,WAAW,KAAK;AAC3B,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AACA,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,cAAM,IAAI,MAAM,WAAW,WAAW,uBAAuB;AAAA,MAC/D;AAEA,YAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AACb,UAAI,SAAwB;AAE5B,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,MAAM;AACR;AAAA,QACF;AAEA,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACxB,cAAI,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC9B;AAAA,UACF;AAEA,cAAI;AACJ,cAAI;AACF,oBAAQ,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AAAA,UAClC,QAAQ;AACN;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,QAAQ;AACzB,6BAAiB,SAAS,MAAM;AAAA,UAClC,WAAW,MAAM,SAAS,SAAS;AACjC,kBAAM,IAAI,MAAM,MAAM,WAAW,uBAAuB;AAAA,UAC1D,WAAW,MAAM,SAAS,QAAQ;AAChC,qBAAS,MAAM,WAAW;AAAA,UAC5B;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,eAAS,QACP,eAAe,QAAQ,IAAI,UAAU;AACvC,aAAO;AAAA,IACT,UAAE;AACA,sBAAgB,QAAQ;AAAA,IAC1B;AAAA,EACF;AAEA,WAAS,cAAc,UAA2B,WAAyB;AACzE,QAAI,CAAC,cAAc,OAAO;AACxB;AAAA,IACF;AAEA,UAAM,MAAM,cAAc,MAAM,WAAW,QAAQ;AACnD,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AAEA,QAAI,WAAW,IAAI,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,EAC9D;AAEA,WAAS,QAAc;AACrB,cAAU,QAAQ;AAClB,kBAAc,QAAQ;AACtB,UAAM,QAAQ;AACd,oBAAgB,QAAQ;AACxB,qBAAiB,QAAQ;AACzB,aAAS,QAAQ;AAAA,EACnB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC9RA,SAAS,OAAAC,YAAW;AAsBb,SAAS,mBACd,SAC0B;AAC1B,QAAM,EAAE,aAAa,eAAe,SAAS,QAAQ,IAAI;AAEzD,QAAM,eAAeA,KAAI,KAAK;AAC9B,QAAM,QAAQA,KAAmB,IAAI;AAErC,iBAAe,SACb,OACiC;AACjC,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAEA,iBAAa,QAAQ;AACrB,UAAM,QAAQ;AAEd,QAAI;AACF,YAAM,WAAW,IAAI,SAAS;AAE9B,UAAI,MAAM,QAAQ;AAChB,iBAAS,OAAO,UAAU,MAAM,MAAM;AAAA,MACxC;AAEA,UAAI,MAAM,aAAa;AACrB,iBAAS,OAAO,gBAAgB,MAAM,WAAW;AAAA,MACnD;AAEA,UAAI,MAAM,WAAW;AACnB,iBAAS,OAAO,cAAc,MAAM,SAAS;AAAA,MAC/C;AAEA,YAAM,MAAM,SAAS,WAAW,uBAAuB,GAAG;AAAA,QACxD,SAAS,YAAY;AAAA,QACrB,QAAQ,YAAY;AAAA,QACpB,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,WAAW,MAAM,YAAY,mBAAmB,KAAK;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,YAAI,SAAS,WAAW,KAAK;AAC3B,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AACA,cAAM,IAAI;AAAA,UACR,WAAW,WAAW;AAAA,QACxB;AAAA,MACF;AAEA,YAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AACb,UAAI,SAAiC;AAErC,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,MAAM;AACR;AAAA,QACF;AAEA,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACxB,cAAI,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC9B;AAAA,UACF;AAEA,gBAAM,UAAU,KAAK,MAAM,CAAC;AAE5B,cAAI;AACJ,cAAI;AACF,oBAAQ,KAAK,MAAM,OAAO;AAAA,UAC5B,QAAQ;AACN;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,SAAS;AAC1B,kBAAM,IAAI;AAAA,cACR,MAAM,WAAW;AAAA,YACnB;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,QAAQ;AACzB,qBAAS,MAAM,WAAW;AAE1B,gBAAI,QAAQ;AACV,wBAAU,MAAM;AAAA,YAClB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,2CAA2C;AAAA,QACnD,OAAO;AAAA,MACT,CAAC;AACP,YAAM,QAAQ,aAAa;AAC3B,gBAAU,YAAY;AAEtB,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAEA,WAAS,QAAc;AACrB,iBAAa,QAAQ;AACrB,UAAM,QAAQ;AAAA,EAChB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzJA,SAAS,YAAAC,WAAU,OAAAC,YAAuC;AAkCnD,SAAS,YAAY,SAAgD;AAC1E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,MAAM,IAAI,UAAU,WAAW;AACrC,QAAM,WAAWA,KAAqB,CAAC,CAAC;AACxC,QAAM,YAAYA,KAAI,KAAK;AAC3B,QAAM,eAAeA,KAAI,KAAK;AAE9B,QAAM,YAAYD,UAAkB,MAAM;AACxC,UAAM,mBAAmB,uBAAuB,KAAK;AACrD,WAAO,oBAAoB,YAAY,eAAe;AAAA,EACxD,CAAC;AAED,QAAM,aAAaA,UAAiB,MAAM;AACxC,QAAI,QAAQ;AACZ,eAAW,UAAU,SAAS,OAAO;AACnC,eAAS,KAAK,OAAO,SAAS,UAAU;AAAA,IAC1C;AACA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,kBAAkBA,UAAiB,MAAM;AAC7C,WAAO,SAAS,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE;AAAA,EACtD,CAAC;AAED,QAAM,sBAAsBA,UAA8B,MAAM;AAC9D,UAAM,MAAM,oBAAI,IAAoB;AACpC,eAAW,UAAU,SAAS,OAAO;AACnC,UAAI,OAAO,UAAU;AACnB,YAAI;AAAA,UACF,OAAO;AAAA,WACN,IAAI,IAAI,OAAO,QAAQ,KAAK,KAAK,KAAK,OAAO,SAAS,UAAU;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAED,WAAS,iBAIP;AACA,UAAM,OAA0B,YAAY;AAC5C,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AACA,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,gBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,WAAS,gBAAoD;AAC3D,UAAM,WAAW,cAAc;AAC/B,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,IACT;AACA,WAAO,EAAE,eAAe,SAAS;AAAA,EACnC;AAEA,WAAS,UAAU,MAA4B,SAAwB;AACrE,gBAAY,EAAE,MAAM,QAAQ,CAAC;AAAA,EAC/B;AAEA,WAAS,YAAY,WAAmC;AACtD,eAAW,UAAU,SAAS,OAAO;AACnC,UAAI,OAAO,OAAO,WAAW;AAC3B,eAAO;AAAA,MACT;AACA,iBAAW,SAAS,OAAO,WAAW,CAAC,GAAG;AACxC,YAAI,MAAM,OAAO,WAAW;AAC1B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,iBAAe,eAA8B;AAC3C,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf;AAAA,IACF;AAEA,cAAU,QAAQ;AAElB,QAAI;AACF,eAAS,QAAQ,MAAM,IAAI,YAAY,UAAU;AAAA,IACnD,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,2BAA2B,EAAE,OAAO,IAAI,CAAC;AACzD,gBAAU,YAAY;AAAA,IACxB,UAAE;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,iBAAe,WACb,MACA,SACA,UACyB;AACzB,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,iBAAa,QAAQ;AAErB,QAAI;AACF,YAAM,UAAU,MAAM,IAAI;AAAA,QACxB;AAAA,QACA;AAAA,UACE;AAAA,UACA,UAAU;AAAA,UACV,WAAW;AAAA,UACX,GAAG,eAAe;AAAA,QACpB;AAAA,QACA,cAAc;AAAA,MAChB;AAEA,UAAI,UAAU;AACZ,cAAM,SAAS,YAAY,QAAQ;AACnC,YAAI,QAAQ;AACV,iBAAO,UAAU,CAAC,GAAI,OAAO,WAAW,CAAC,GAAI,OAAO;AAAA,QACtD;AAAA,MACF,OAAO;AACL,iBAAS,QAAQ,CAAC,GAAG,SAAS,OAAO,OAAO;AAAA,MAC9C;AAEA,gBAAU,WAAW,OAAO;AAC5B,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,4BAA4B,EAAE,OAAO,IAAI,CAAC;AAC1D,gBAAU,YAAY;AACtB,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAEA,iBAAe,YACb,WACA,MACyB;AACzB,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,iBAAa,QAAQ;AAErB,QAAI;AACF,YAAM,UAAU,MAAM,IAAI;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,UACA,GAAG,eAAe;AAAA,QACpB;AAAA,QACA,cAAc;AAAA,MAChB;AAEA,2BAAqB,WAAW,OAAO;AACvC,gBAAU,WAAW,OAAO;AAC5B,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,4BAA4B,EAAE,OAAO,IAAI,CAAC;AAC1D,gBAAU,YAAY;AACtB,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAEA,iBAAe,cAAc,WAAqC;AAChE,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,YAAY,SAAS;AACrC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AAEA,UAAM,kBAAkB;AAAA,MACtB,GAAG;AAAA,MACH,SAAS,CAAC,GAAI,QAAQ,WAAW,CAAC,CAAE;AAAA,IACtC;AAEA,iBAAa,QAAQ;AAErB,QAAI;AACF,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA,eAAe;AAAA,QACf,cAAc;AAAA,MAChB;AAEA,UAAI,QAAQ,WAAW;AACrB,cAAM,SAAS,YAAY,QAAQ,SAAS;AAC5C,YAAI,QAAQ;AACV,iBAAO,WAAW,OAAO,WAAW,CAAC,GAAG;AAAA,YACtC,CAAC,MAAM,EAAE,OAAO;AAAA,UAClB;AAAA,QACF;AAAA,MACF,OAAO;AACL,iBAAS,QAAQ,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,MAClE;AAEA,gBAAU,WAAW,eAAe;AACpC,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,4BAA4B,EAAE,OAAO,IAAI,CAAC;AAC1D,gBAAU,YAAY;AACtB,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAEA,iBAAe,cAAc,WAA4C;AACvE,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,iBAAa,QAAQ;AAErB,QAAI;AACF,YAAM,UAAU,MAAM,IAAI;AAAA,QACxB;AAAA,QACA;AAAA,QACA,eAAe;AAAA,QACf,cAAc;AAAA,MAChB;AAEA,2BAAqB,WAAW,OAAO;AAEvC,YAAM,YAAY,QAAQ,cAAc,aAAa;AACrD,gBAAU,WAAW,OAAO;AAC5B,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,uCAAuC,EAAE,OAAO,IAAI,CAAC;AACrE,gBAAU,YAAY;AACtB,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAEA,WAAS,kBAAkB,SAAwB;AACjD,QAAI,QAAQ,WAAW;AACrB,YAAM,SAAS,YAAY,QAAQ,SAAS;AAC5C,UAAI,QAAQ;AACV,eAAO,UAAU,CAAC,GAAI,OAAO,WAAW,CAAC,GAAI,OAAO;AAAA,MACtD;AAAA,IACF,OAAO;AACL,eAAS,QAAQ,CAAC,GAAG,SAAS,OAAO,OAAO;AAAA,IAC9C;AACA,cAAU,WAAW,OAAO;AAAA,EAC9B;AAEA,WAAS,kBAAkB,SAAwB;AACjD,yBAAqB,QAAQ,IAAI,OAAO;AACxC,cAAU,WAAW,OAAO;AAAA,EAC9B;AAEA,WAAS,kBAAkB,WAAmB,UAA+B;AAC3E,UAAM,UAAU,YAAY,SAAS;AACrC,UAAM,WAAW,UACb,EAAE,GAAG,SAAS,SAAS,CAAC,GAAI,QAAQ,WAAW,CAAC,CAAE,EAAE,IACpD;AAEJ,QAAI,UAAU;AACZ,YAAM,SAAS,YAAY,QAAQ;AACnC,UAAI,QAAQ;AACV,eAAO,WAAW,OAAO,WAAW,CAAC,GAAG;AAAA,UACtC,CAAC,MAAM,EAAE,OAAO;AAAA,QAClB;AAAA,MACF;AAAA,IACF,OAAO;AACL,eAAS,QAAQ,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,IAClE;AAEA,QAAI,UAAU;AACZ,gBAAU,WAAW,QAAQ;AAAA,IAC/B;AAAA,EACF;AAEA,WAAS,qBAAqB,WAAmB,SAAwB;AACvE,aAAS,IAAI,GAAG,IAAI,SAAS,MAAM,QAAQ,KAAK;AAC9C,UAAI,SAAS,MAAM,CAAC,EAAE,OAAO,WAAW;AACtC,iBAAS,QAAQ;AAAA,UACf,GAAG,SAAS,MAAM,MAAM,GAAG,CAAC;AAAA,UAC5B,EAAE,GAAG,SAAS,SAAS,SAAS,MAAM,CAAC,EAAE,QAAQ;AAAA,UACjD,GAAG,SAAS,MAAM,MAAM,IAAI,CAAC;AAAA,QAC/B;AACA;AAAA,MACF;AAEA,YAAM,UAAU,SAAS,MAAM,CAAC,EAAE,WAAW,CAAC;AAC9C,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,YAAI,QAAQ,CAAC,EAAE,OAAO,WAAW;AAC/B,gBAAM,aAAa;AAAA,YACjB,GAAG,QAAQ,MAAM,GAAG,CAAC;AAAA,YACrB;AAAA,YACA,GAAG,QAAQ,MAAM,IAAI,CAAC;AAAA,UACxB;AACA,mBAAS,QAAQ;AAAA,YACf,GAAG,SAAS,MAAM,MAAM,GAAG,CAAC;AAAA,YAC5B,EAAE,GAAG,SAAS,MAAM,CAAC,GAAG,SAAS,WAAW;AAAA,YAC5C,GAAG,SAAS,MAAM,MAAM,IAAI,CAAC;AAAA,UAC/B;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACjZA,SAAS,gBAAgB,aAAuB;AAiBzC,SAAS,mBAAmB,SAA0C;AAC3E,QAAM,EAAE,UAAU,QAAQ,IAAI;AAE9B,QAAM,SAAS,CAAC,YAAY,eAAe;AACzC,QAAI,YAAY;AACd,iBAAW,OAAO,mBAAmB;AAAA,IACvC;AAEA,QAAI,YAAY;AACd,iBAAW;AAAA,QACT;AAAA,QACA,CAAC,YAAqC;AACpC,iCAAuB,UAAU,OAAO;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAKD,iBAAe,MAAM;AACnB,YAAQ,OAAO,OAAO,mBAAmB;AAAA,EAC3C,CAAC;AACH;AAEA,SAAS,uBACP,UACA,SACM;AACN,UAAQ,QAAQ,QAAQ;AAAA,IACtB,KAAK;AACH,eAAS,kBAAkB,QAAQ,OAAO;AAC1C;AAAA,IACF,KAAK;AACH,eAAS,kBAAkB,QAAQ,OAAO;AAC1C;AAAA,IACF,KAAK;AACH,eAAS,kBAAkB,QAAQ,QAAQ,IAAI,QAAQ,QAAQ,SAAS;AACxE;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH,eAAS,kBAAkB,QAAQ,OAAO;AAC1C;AAAA,EACJ;AACF;;;AC3DA,SAAS,YAAAE,WAAU,kBAAAC,iBAAgB,OAAAC,MAAK,SAAAC,cAAuB;AAE/D,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,mBAAmB,SAAgC;AAC1D,aAAW,SAAS,eAAe;AACjC,YAAQ,OAAO,KAAK;AAAA,EACtB;AACF;AAEA,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAwBO,SAAS,iBACd,SAIA;AACA,QAAM,EAAE,aAAa,QAAQ,QAAQ,IAAI;AAEzC,QAAM,gBAAgBD,KAAoB,CAAC,CAAC;AAC5C,QAAM,eAAeA,KAA+B,oBAAI,IAAI,CAAC;AAE7D,MAAI,aAAa;AACjB,MAAI,8BAA8B;AAElC,QAAM,WAAWF,UAAS,MAAM,YAAY,YAAY,MAAM,EAAE;AAEhE,WAAS,cAAsB;AAC7B,UAAM,QAAQ,oBAAoB,aAAa,oBAAoB,MAAM;AACzE;AACA,WAAO;AAAA,EACT;AAEA,WAAS,gBAAgB,QAAkD;AACzE,QAAI,OAAO,OAAO,SAAS,OAAO;AAChC,aAAO;AAAA,IACT;AAEA,QAAI,cAAc,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE,GAAG;AACvD,aAAO;AAAA,IACT;AAEA,UAAM,eAA6B;AAAA,MACjC,IAAI,OAAO;AAAA,MACX,MAAM,OAAO;AAAA,MACb,OAAO,YAAY;AAAA,MACnB,iBAAiB;AAAA,IACnB;AAEA,kBAAc,QAAQ,CAAC,GAAG,cAAc,OAAO,YAAY;AAE3D,WAAO;AAAA,EACT;AAEA,WAAS,mBAAmB,UAAwB;AAClD,UAAM,kBAAkB,IAAI,IAAI,aAAa,KAAK;AAClD,eAAW,CAAC,SAAS,YAAY,KAAK,iBAAiB;AACrD,UAAI,aAAa,OAAO,UAAU;AAChC,wBAAgB,OAAO,OAAO;AAAA,MAChC;AAAA,IACF;AACA,iBAAa,QAAQ;AAErB,kBAAc,QAAQ,cAAc,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ;AAAA,EAC3E;AAEA,WAAS,kBAAkB,MAAiD;AAC1E,UAAM,eAAe,cAAc,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM;AACzE,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,kBAAc,QAAQ,cAAc,MAAM;AAAA,MAAI,CAAC,MAC7C,EAAE,OAAO,KAAK,SAAS,EAAE,GAAG,GAAG,iBAAiB,KAAK,QAAQ,IAAI;AAAA,IACnE;AAEA,UAAM,kBAAkB,IAAI,IAAI,aAAa,KAAK;AAClD,eAAW,CAAC,SAAS,MAAM,KAAK,iBAAiB;AAC/C,UAAI,OAAO,OAAO,KAAK,QAAQ;AAC7B,wBAAgB,OAAO,OAAO;AAAA,MAChC;AAAA,IACF;AAEA,oBAAgB,IAAI,KAAK,SAAS;AAAA,MAChC,GAAG;AAAA,MACH,iBAAiB,KAAK;AAAA,IACxB,CAAC;AACD,iBAAa,QAAQ;AAErB,QAAI,OAAO,MAAM,oBAAoB,KAAK,SAAS;AACjD,aAAO,YAAY,IAAI;AAAA,IACzB;AAAA,EACF;AAEA,WAAS,oBAAoB,MAAiC;AAC5D,UAAM,kBAAkB,IAAI,IAAI,aAAa,KAAK;AAClD,UAAM,SAAS,gBAAgB,IAAI,KAAK,OAAO;AAC/C,oBAAgB,OAAO,KAAK,OAAO;AACnC,iBAAa,QAAQ;AAErB,QAAI,QAAQ;AACV,oBAAc,QAAQ,cAAc,MAAM;AAAA,QAAI,CAAC,MAC7C,EAAE,OAAO,OAAO,KAAK,EAAE,GAAG,GAAG,iBAAiB,KAAK,IAAI;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAEA,WAAS,sBAAsB,SAAoC;AACjE,kCAA8B;AAC9B,QAAI;AACF,sBAAgB,QAAQ,OAAO;AAAA,IACjC,UAAE;AACA,oCAA8B;AAAA,IAChC;AAAA,EACF;AAEA,WAAS,mBAAmB,SAAoC;AAC9D,QAAI,CAAC,QAAQ,SAAS,6BAA6B;AACjD;AAAA,IACF;AAEA,YAAQ,MAAM,QAAQ,oBAAoB,OAAO;AAAA,EACnD;AAEA,WAAS,qBAAqB,SAAuB;AACnD,QAAI,CAAC,QAAQ,OAAO;AAClB;AAAA,IACF;AAEA,YAAQ,MAAM,QAAQ,uBAAuB;AAAA,MAC3C;AAAA,MACA,QAAQ,SAAS;AAAA,IACnB,CAAC;AAAA,EACH;AAEA,WAAS,uBAAuB,SAAuB;AACrD,QAAI,CAAC,QAAQ,OAAO;AAClB;AAAA,IACF;AAEA,YAAQ,MAAM,QAAQ,yBAAyB,EAAE,QAAQ,CAAC;AAAA,EAC5D;AAEA,EAAAG;AAAA,IACE,MAAM,OAAO,MAAM;AAAA,IACnB,CAAC,YAAY,eAAe;AAC1B,UAAI,6BAA6B;AAC/B;AAAA,MACF;AAEA,UAAI,YAAY;AACd,+BAAuB,UAAU;AAAA,MACnC;AAEA,UAAI,YAAY;AACd,6BAAqB,UAAU;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,EAAAA,OAAM,SAAS,CAAC,YAAY,eAAe;AACzC,QAAI,YAAY;AACd,yBAAmB,UAAU;AAAA,IAC/B;AAEA,QAAI,CAAC,YAAY;AACf,oBAAc,QAAQ,CAAC;AACvB,mBAAa,QAAQ,oBAAI,IAAI;AAC7B,mBAAa;AACb;AAAA,IACF;AAEA,UAAM,UACJ,WAOA;AACF,QAAI,SAAS;AACX,cAAQ,KAAK,CAAC,WAAiD;AAC7D,wBAAgB,OAAO,IAAI;AAAA,MAC7B,CAAC;AAAA,IACH;AAEA,eAAW;AAAA,MACT;AAAA,MACA,CAAC,WAAiD;AAChD,cAAM,eAAe,gBAAgB,OAAO,IAAI;AAChD,YAAI,cAAc;AAChB,kBAAQ,uBAAuB,YAAY;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAEA,eAAW;AAAA,MACT;AAAA,MACA,CAAC,WAAiD;AAChD,cAAM,eAAe,cAAc,MAAM;AAAA,UACvC,CAAC,MAAM,EAAE,OAAO,OAAO;AAAA,QACzB;AACA,2BAAmB,OAAO,EAAE;AAC5B,YAAI,cAAc;AAChB,kBAAQ,qBAAqB,YAAY;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,eAAW;AAAA,MACT;AAAA,MACA,CAAC,SAA8C;AAC7C,0BAAkB,IAAI;AACtB,cAAM,eAAe,cAAc,MAAM;AAAA,UACvC,CAAC,MAAM,EAAE,OAAO,KAAK;AAAA,QACvB;AACA,YAAI,cAAc;AAChB,kBAAQ,gBAAgB;AAAA,YACtB,SAAS,KAAK;AAAA,YACd;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,eAAW,KAAK,yBAAyB,CAAC,SAA8B;AACtE,YAAM,SAAS,aAAa,MAAM,IAAI,KAAK,OAAO;AAClD,0BAAoB,IAAI;AACxB,UAAI,QAAQ;AACV,gBAAQ,kBAAkB;AAAA,UACxB,SAAS,KAAK;AAAA,UACd,cAAc;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,eAAW,KAAK,oBAAoB,CAAC,YAAiC;AACpE,4BAAsB,OAAO;AAAA,IAC/B,CAAC;AAED,eAAW,KAAK,iBAAiB,CAAC,YAAiC;AACjE,4BAAsB,OAAO;AAAA,IAC/B,CAAC;AAAA,EACH,CAAC;AAMD,EAAAF,gBAAe,MAAM;AACnB,QAAI,QAAQ,OAAO;AACjB,yBAAmB,QAAQ,KAAK;AAAA,IAClC;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA,IACrB,8BAA8B,MAAM;AAAA,EACtC;AACF;;;ACvSO,SAAS,0BACd,QACA,eACM;AACN,QAAM,mBAAmB,OAAO;AAChC,QAAM,sBAAsB,OAAO;AACnC,QAAM,sBAAsB,OAAO;AACnC,QAAM,oBAAoB,OAAO;AACjC,QAAM,yBAAyB,OAAO;AACtC,QAAM,qBAAqB,OAAO;AAElC,SAAO,WAAW,CAAC,OAAO,iBAAkB,gBAAiB;AAC3D,qBAAiB,OAAO,iBAAiB,WAAW;AACpD,kBAAc,oBAAoB;AAAA,MAChC,WAAW;AAAA,MACX,MAAM;AAAA,QACJ;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO,cAAc,CAAC,SAAS,YAAY;AACzC,wBAAoB,SAAS,OAAO;AACpC,kBAAc,oBAAoB;AAAA,MAChC,WAAW;AAAA,MACX,MAAM,EAAE,UAAU,SAAS,QAAQ;AAAA,MACnC,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO,cAAc,CAAC,YAAY;AAChC,wBAAoB,OAAO;AAC3B,kBAAc,oBAAoB;AAAA,MAChC,WAAW;AAAA,MACX,MAAM,EAAE,UAAU,QAAQ;AAAA,MAC1B,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO,YAAY,CAAC,SAAS,UAAU,iBAAkB,gBAAiB;AACxE,sBAAkB,SAAS,UAAU,iBAAiB,WAAW;AACjE,kBAAc,oBAAoB;AAAA,MAChC,WAAW;AAAA,MACX,MAAM;AAAA,QACJ,UAAU;AAAA,QACV,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO,iBAAiB,CAAC,YAAY;AACnC,2BAAuB,OAAO;AAC9B,kBAAc,oBAAoB;AAAA,MAChC,WAAW;AAAA,MACX,MAAM,EAAE,QAAQ;AAAA,MAChB,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO,aAAa,CAAC,SAAS,cAAe;AAC3C,uBAAmB,SAAS,SAAS;AACrC,kBAAc,oBAAoB;AAAA,MAChC,WAAW;AAAA,MACX,MAAM,EAAE,QAAQ;AAAA,MAChB,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AACF;;;ACnFA,SAAS,OAAAG,YAAqB;AAevB,SAAS,aAAa,SAAkD;AAC7E,QAAM,EAAE,aAAa,QAAQ,IAAI;AAEjC,QAAM,UAAUA;AAAA,IACd;AAAA,EACF;AACA,QAAM,cAAcA,KAAI,KAAK;AAE7B,MAAI,WAAmC;AACvC,MAAI,cAA6B;AAEjC,iBAAe,QACb,YACA,QACe;AACf,QAAI,UAAU;AACZ;AAAA,IACF;AAEA,eAAW,IAAI,gBAAgB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,SAAS,QAAQ;AAEvB,kBAAc,qBAAqB,UAAU;AAC7C,UAAM,kBAAkB,SAAS,kBAAkB,WAAW;AAE9D,oBAAgB,KAAK,iCAAiC,MAAM;AAC1D,kBAAY,QAAQ;AACpB,cAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,oBAAgB,KAAK,6BAA6B,CAAC,UAAmB;AACpE,kBAAY,QAAQ;AACpB,cAAQ,QAAQ;AAChB;AAAA,QACE,iBAAiB,QACb,QACA,IAAI,MAAM,yCAAyC;AAAA,MACzD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,aAAmB;AAC1B,QAAI,eAAe,UAAU;AAC3B,eAAS,YAAY,WAAW;AAAA,IAClC;AAEA,cAAU,WAAW;AACrB,eAAW;AACX,kBAAc;AACd,YAAQ,QAAQ;AAChB,gBAAY,QAAQ;AAAA,EACtB;AAEA,WAAS,cAA6B;AACpC,WAAO,UAAU,YAAY,KAAK;AAAA,EACpC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACpFA,SAAS,OAAAC,YAAqB;AAmBvB,SAAS,gBACd,SACuB;AACvB,QAAM,MAAM,IAAI,UAAU,QAAQ,WAAW;AAE7C,QAAM,UAAUA,KAAmB,CAAC,CAAC;AACrC,QAAM,YAAYA,KAAI,KAAK;AAE3B,iBAAe,YAAY,QAAgC;AACzD,cAAU,QAAQ;AAClB,QAAI;AACF,cAAQ,QAAQ,MAAM,IAAI,YAAY,MAAM;AAAA,IAC9C,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR,UAAE;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,iBAAe,aACb,MACA,SACsB;AACtB,QAAI;AACF,YAAM,SAAS,MAAM,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvD,cAAQ,QAAQ,CAAC,QAAQ,GAAG,QAAQ,KAAK;AACzC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,aACb,IACA,MACsB;AACtB,QAAI;AACF,YAAM,UAAU,MAAM,IAAI,aAAa,IAAI,IAAI;AAC/C,cAAQ,QAAQ,QAAQ,MAAM,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,UAAU,CAAE;AACpE,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,aAAa,IAA2B;AACrD,QAAI;AACF,YAAM,IAAI,aAAa,EAAE;AACzB,cAAQ,QAAQ,QAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,IACzD,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACtFA,SAAS,OAAAC,YAAqB;AAiBvB,SAAS,mBACd,SAC0B;AAC1B,QAAM,MAAM,IAAI,UAAU,QAAQ,WAAW;AAE7C,QAAM,YAAYA,KAAwB,CAAC,CAAC;AAC5C,QAAM,YAAYA,KAAI,KAAK;AAC3B,QAAM,cAAcA,KAAI,KAAK;AAE7B,iBAAe,gBAA+B;AAC5C,cAAU,QAAQ;AAClB,QAAI;AACF,gBAAU,QAAQ,MAAM,IAAI,aAAa,QAAQ,UAAU;AAAA,IAC7D,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR,UAAE;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,iBAAe,gBAAgB,YAAuC;AACpE,gBAAY,QAAQ;AACpB,QAAI;AACF,YAAM,WAAW,MAAM,IAAI;AAAA,QACzB,QAAQ;AAAA,QACR;AAAA,MACF;AACA,cAAQ,YAAY,QAAQ;AAC5B,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAChC,YAAM;AAAA,IACR,UAAE;AACA,kBAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzDA,SAAS,YAAAC,WAAU,OAAAC,OAAK,SAAAC,cAAa;AAoB9B,SAAS,aAAa,SAAkD;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,MAAM,IAAI,UAAU,WAAW;AAErC,QAAM,YAAYD,MAAI,KAAK;AAC3B,QAAM,QAAQA,MAAmB,IAAI;AAErC,QAAM,kBAAkBA,MAA4B,IAAI;AAExD,MAAI,aAAa;AACf,IAAAC;AAAA,MACE;AAAA,MACA,CAAC,UAAU;AACT,YAAI,OAAO;AACT,0BAAgB,QAAQ,YAAY;AAAA,QACtC;AAAA,MACF;AAAA,MACA,EAAE,WAAW,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,YAAYF,UAAkB,MAAM,gBAAgB,UAAU,IAAI;AAExE,QAAM,gBAAgBA;AAAA,IACpB,MAAM,gBAAgB,OAAO,iBAAiB,CAAC;AAAA,EACjD;AAEA,iBAAe,cAAc,WAAkC;AAC7D,QAAI,CAAC,gBAAgB,OAAO;AAC1B,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,UAAM,aAAa,cAAc;AACjC,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAEA,cAAU,QAAQ;AAClB,UAAM,QAAQ;AAEd,QAAI;AACF,YAAM,KAAK;AAEX,UAAI,EAAE,KAAK,IAAI,MAAM,WAAW,UAAU;AAE1C,UAAI,mBAAmB;AACrB,eAAO,MAAM,kBAAkB,IAAI;AAAA,MACrC;AAEA,YAAM,IAAI,cAAc,YAAY;AAAA,QAClC;AAAA,QACA;AAAA,QACA,gBAAgB,gBAAgB,MAAM;AAAA,QACtC,WAAW,gBAAgB,MAAM;AAAA,MACnC,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,eACJ,eAAe,QACX,MACA,IAAI,MAAM,6BAA6B,EAAE,OAAO,IAAI,CAAC;AAC3D,YAAM,QAAQ,aAAa;AAC3B,gBAAU,YAAY;AACtB,YAAM;AAAA,IACR,UAAE;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AChGO,SAAS,UAAU,SAA4C;AACpE,QAAM,EAAE,aAAa,gBAAgB,kBAAkB,IAAI;AAC3D,QAAM,MAAM,IAAI,UAAU,WAAW;AAErC,WAAS,wBAGP;AACA,UAAM,cAAc,iBAAiB;AACrC,UAAM,qBAAqB,oBAAoB,KAAK;AAEpD,WAAO;AAAA,MACL,aACE,sBAAsB,aAAa,cAC/B,YAAY,cACZ,CAAC;AAAA,MACP,iBAAiB,aAAa,mBAAmB;AAAA,IACnD;AAAA,EACF;AAEA,iBAAe,WAAW,YAA2C;AACnE,UAAM,eAAe,sBAAsB;AAC3C,UAAM,SAAS,MAAM,IAAI,eAAe,YAAY,YAAY;AAEhE,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AAEA,iBAAe,cAAc,YAAqC;AAChE,UAAM,eAAe,sBAAsB;AAC3C,UAAM,SAAS,MAAM,IAAI,eAAe,YAAY,YAAY;AAChE,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;;;ACpDA,SAAS,YAAAG,WAAU,OAAAC,aAAuC;AAenD,SAAS,cACd,SACqB;AACrB,QAAM,EAAE,aAAa,QAAQ,IAAI;AAEjC,QAAM,SAASA,MAAuB,IAAI;AAC1C,QAAM,YAAYA,MAAI,KAAK;AAE3B,QAAM,YAAY,IAAI,UAAU,WAAW;AAE3C,QAAM,WAAWD,UAAS,MAAM,OAAO,OAAO,YAAY,IAAI;AAE9D,WAAS,WAAW,SAAsC;AACxD,WAAO,OAAO,OAAO,SAAS,OAAO,KAAK;AAAA,EAC5C;AAEA,iBAAe,cAA6B;AAC1C,QAAI,UAAU,OAAO;AACnB;AAAA,IACF;AAEA,cAAU,QAAQ;AAElB,QAAI;AACF,aAAO,QAAQ,MAAM,UAAU,YAAY;AAAA,IAC7C,SAAS,OAAO;AACd;AAAA,QACE,iBAAiB,QACb,QACA,IAAI,MAAM,0BAA0B,EAAE,OAAO,MAAM,CAAC;AAAA,MAC1D;AAAA,IACF,UAAE;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACpDA,IAAM,uBAAuB;AAE7B,SAAS,iBAAiB,SAAqC;AAC7D,MAAI,QAAQ,aAAa;AACvB,WAAO,QAAQ,YAAY,WAAW,WAAW,MAAM;AAAA,EACzD;AAEA,QAAM,QAAQ,QAAQ,WAAW,2BAA2B;AAAA,IAC1D;AAAA,IACA;AAAA,EACF;AACA,SAAO,GAAG,IAAI,GAAG,WAAW,MAAM;AACpC;AAEA,eAAe,gBACb,KACA,aAKC;AACD,QAAM,QAAQ,YAAY,IAAI;AAE9B,MAAI;AACF,UAAM,WAAW,cACb,MAAM,YAAY,mBAAmB,WAAW,QAAQ;AAAA,MACtD,QAAQ;AAAA,MACR,SAAS,EAAE,QAAQ,mBAAmB;AAAA,IACxC,CAAC,IACD,MAAM,MAAM,KAAK;AAAA,MACf,QAAQ;AAAA,MACR,SAAS,EAAE,QAAQ,mBAAmB;AAAA,IACxC,CAAC;AAEL,UAAM,UAAU,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAEpD,QAAI,SAAS,WAAW,KAAK;AAC3B,aAAO;AAAA,QACL,KAAK,EAAE,IAAI,MAAM,QAAQ;AAAA,QACzB,MAAM,EAAE,IAAI,OAAO,OAAO,WAAW;AAAA,MACvC;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,QACL,KAAK,EAAE,IAAI,OAAO,QAAQ;AAAA,QAC1B,MAAM;AAAA,UACJ,IAAI,CAAC;AAAA,UACL,OAAO,cAAc,QAAQ,SAAS,MAAM,KAAK;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,WAAO;AAAA,MACL,KAAK,EAAE,IAAI,KAAK,WAAW,MAAM,QAAQ;AAAA,MACzC,MAAM,EAAE,IAAI,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,IACjB;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAEpD,WAAO;AAAA,MACL,KAAK,EAAE,IAAI,OAAO,QAAQ;AAAA,MAC1B,MAAM;AAAA,QACJ,IAAI,CAAC;AAAA,QACL,OAAO,cACH,iBAAiB,QACf,MAAM,UACN,gCACF;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,eAAe,UAIe;AAC3C,MAAI,CAAC,UAAU,QAAQ,CAAC,UAAU,SAAS;AACzC,WAAO,EAAE,IAAI,OAAO,OAAO,wCAAwC;AAAA,EACrE;AAEA,MAAI,OAAO,cAAc,aAAa;AACpC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,SAAS,MAAM,QAAQ;AACjD,QAAM,MAAM,GAAG,QAAQ,MAAM,SAAS,IAAI,IAAI,SAAS,IAAI,QAAQ,SAAS,OAAO;AAEnF,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,KAAuB;AAE3B,UAAM,UAAU,WAAW,MAAM;AAC/B,UAAI,MAAM;AACV,cAAQ,EAAE,IAAI,OAAO,OAAO,iCAAiC,CAAC;AAAA,IAChE,GAAG,oBAAoB;AAEvB,QAAI;AACF,WAAK,IAAI,UAAU,GAAG;AAAA,IACxB,SAAS,OAAO;AAKd,mBAAa,OAAO;AACpB,cAAQ;AAAA,QACN,IAAI;AAAA,QACJ,OACE,iBAAiB,QACb,MAAM,UACN;AAAA,MACR,CAAC;AACD;AAAA,IACF;AAEA,OAAG,SAAS,MAAM;AAChB,mBAAa,OAAO;AACpB,UAAI,MAAM;AACV,cAAQ,EAAE,IAAI,KAAK,CAAC;AAAA,IACtB;AAEA,OAAG,UAAU,MAAM;AACjB,mBAAa,OAAO;AACpB,cAAQ,EAAE,IAAI,OAAO,OAAO,8BAA8B,CAAC;AAAA,IAC7D;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,mBACpB,UAA8B,CAAC,GACH;AAC5B,QAAM,YAAY,iBAAiB,OAAO;AAE1C,QAAM,SAAS,MAAM,gBAAgB,WAAW,QAAQ,WAAW;AACnE,QAAM,WAAW,MAAM,eAAe,OAAO,QAAQ;AAErD,SAAO;AAAA,IACL,KAAK,OAAO;AAAA,IACZ,WAAW;AAAA,IACX,MAAM,OAAO;AAAA,IACb,SAAS,OAAO,IAAI,MAAM,OAAO,KAAK;AAAA,EACxC;AACF;;;AC3JA,SAAS,SAAAE,cAAuB;AAQzB,SAAS,eAAe,SAAsC;AACnE,QAAM,EAAE,QAAQ,SAAS,YAAY,IAAI;AAEzC,EAAAA,OAAM,SAAS,CAAC,YAAY,eAAe;AACzC,QAAI,YAAY;AACd,iBAAW,OAAO,eAAe;AAAA,IACnC;AAEA,QAAI,YAAY;AACd,iBAAW,KAAK,iBAAiB,CAAC,YAAiC;AACjE,wBAAgB,QAAQ,OAAO;AAC/B,sBAAc,OAAO;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;","names":["SdkError","SdkError","SdkError","markDirty","content","SdkError","ref","computed","ref","ref","computed","ref","computed","onScopeDispose","ref","watch","ref","ref","ref","computed","ref","watch","computed","ref","watch"]}
1
+ {"version":3,"sources":["../../src/cloud/auth.ts","../../src/cloud/api.ts","../../src/cloud/url-builder.ts","../../src/cloud/websocket-client.ts","../../src/cloud/mcp-operation-handler.ts","../../src/cloud/editor.ts","../../src/cloud/ai-chat.ts","../../src/cloud/ai-rewrite.ts","../../src/cloud/ai-config.ts","../../src/cloud/template-scoring.ts","../../src/cloud/design-reference.ts","../../src/cloud/comments.ts","../../src/cloud/comment-listener.ts","../../src/cloud/collaboration.ts","../../src/cloud/collaboration-broadcast.ts","../../src/cloud/web-socket.ts","../../src/cloud/saved-modules.ts","../../src/cloud/snapshots.ts","../../src/cloud/test-email.ts","../../src/cloud/export.ts","../../src/cloud/plan-config.ts","../../src/cloud/health-check.ts","../../src/cloud/mcp-listener.ts"],"sourcesContent":["import type {\n AuthConfig,\n AuthRequestOptions,\n SdkAuthConfig,\n TestEmailConfig,\n TokenData,\n UserConfig,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\n\nexport type {\n AuthConfig,\n AuthRequestOptions,\n SdkAuthConfig,\n TestEmailConfig,\n UserConfig,\n};\n\nexport class AuthManager {\n private static readonly DEFAULT_BASE_URL = \"https://templatical.com\";\n\n private accessToken: string | null = null;\n private expiresAt: Date | null = null;\n private _projectId: string | null = null;\n private _tenantId: string | null = null;\n private _tenantSlug: string | null = null;\n private _testEmailConfig: TestEmailConfig | null = null;\n private _userConfig: UserConfig | null = null;\n private readonly url: string;\n private readonly baseUrl: string;\n private readonly requestOptions: AuthRequestOptions;\n private readonly onError?: (error: Error) => void;\n private refreshPromise: Promise<string> | null = null;\n\n private static readonly REFRESH_THRESHOLD_MS = 60 * 1000;\n\n constructor(config: AuthConfig) {\n this.url = config.url;\n this.baseUrl = (config.baseUrl ?? AuthManager.DEFAULT_BASE_URL).replace(\n /\\/$/,\n \"\",\n );\n this.requestOptions = config.requestOptions ?? {};\n this.onError = config.onError;\n }\n\n resolveUrl(path: string): string {\n if (path.startsWith(\"http://\") || path.startsWith(\"https://\")) {\n return path;\n }\n\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${this.baseUrl}${normalizedPath}`;\n }\n\n get projectId(): string {\n if (!this._projectId) {\n throw new Error(\"Project ID not available. Call initialize() first.\");\n }\n return this._projectId;\n }\n\n get tenantId(): string {\n if (!this._tenantId) {\n throw new Error(\"Tenant ID not available. Call initialize() first.\");\n }\n return this._tenantId;\n }\n\n get tenantSlug(): string {\n if (!this._tenantSlug) {\n throw new Error(\"Tenant slug not available. Call initialize() first.\");\n }\n return this._tenantSlug;\n }\n\n get testEmailConfig(): TestEmailConfig | null {\n return this._testEmailConfig;\n }\n\n get userConfig(): UserConfig | null {\n return this._userConfig;\n }\n\n get accessTokenValue(): string | null {\n return this.accessToken;\n }\n\n async initialize(): Promise<void> {\n await this.ensureToken();\n }\n\n private async ensureToken(): Promise<string> {\n if (this.accessToken && !this.isTokenExpiringSoon()) {\n return this.accessToken;\n }\n return this.refreshToken();\n }\n\n private isTokenExpiringSoon(): boolean {\n if (!this.expiresAt) {\n return true;\n }\n const timeUntilExpiry = this.expiresAt.getTime() - Date.now();\n return timeUntilExpiry < AuthManager.REFRESH_THRESHOLD_MS;\n }\n\n async refreshToken(): Promise<string> {\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.performRefresh();\n\n try {\n const token = await this.refreshPromise;\n return token;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async performRefresh(): Promise<string> {\n try {\n const method = this.requestOptions.method ?? \"POST\";\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...this.requestOptions.headers,\n };\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n credentials: this.requestOptions.credentials ?? \"include\",\n };\n\n if (method === \"POST\" && this.requestOptions.body) {\n headers[\"Content-Type\"] = \"application/json\";\n fetchOptions.body = JSON.stringify(this.requestOptions.body);\n }\n\n const response = await fetch(this.url, fetchOptions);\n\n if (!response.ok) {\n throw new SdkError(\n `Token refresh failed: ${response.status}`,\n response.status,\n );\n }\n\n const data: TokenData = await response.json();\n\n if (!data.token || !data.expires_at || !data.project_id || !data.tenant) {\n throw new Error(\n \"Invalid token response: missing token, expires_at, project_id, or tenant\",\n );\n }\n\n this.accessToken = data.token;\n this.expiresAt = new Date(data.expires_at * 1000);\n this._projectId = data.project_id;\n this._tenantSlug = data.tenant;\n\n if (data.test_email?.allowed_emails && data.test_email?.signature) {\n this._testEmailConfig = {\n allowedEmails: data.test_email.allowed_emails,\n signature: data.test_email.signature,\n };\n } else {\n this._testEmailConfig = null;\n }\n\n if (data.user?.id && data.user?.name && data.user?.signature) {\n this._userConfig = {\n id: data.user.id,\n name: data.user.name,\n signature: data.user.signature,\n };\n } else {\n this._userConfig = null;\n }\n\n return this.accessToken;\n } catch (error) {\n const wrappedError =\n error instanceof Error\n ? error\n : new Error(\"Token refresh failed\", { cause: error });\n this.onError?.(wrappedError);\n throw wrappedError;\n }\n }\n\n async authenticatedFetch(\n url: string,\n options: RequestInit = {},\n ): Promise<Response> {\n const token = await this.ensureToken();\n const resolvedUrl = this.resolveUrl(url);\n\n const makeRequest = async (authToken: string): Promise<Response> => {\n return fetch(resolvedUrl, {\n ...options,\n headers: {\n ...options.headers,\n Authorization: `Bearer ${authToken}`,\n },\n });\n };\n\n let response = await makeRequest(token);\n\n if (response.status === 401) {\n const newToken = await this.refreshToken();\n response = await makeRequest(newToken);\n }\n\n return response;\n }\n}\n\nexport function createSdkAuthManager(\n config: SdkAuthConfig,\n onError?: (error: Error) => void,\n): AuthManager {\n if (config.mode === \"direct\") {\n const baseUrl = (config.baseUrl ?? \"https://templatical.com\").replace(\n /\\/$/,\n \"\",\n );\n\n return new AuthManager({\n url: `${baseUrl}/api/v1/auth/token`,\n baseUrl: config.baseUrl,\n requestOptions: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: {\n client_id: config.clientId,\n client_secret: config.clientSecret,\n tenant: config.tenant,\n client_type: \"sdk\",\n },\n },\n onError,\n });\n }\n\n return new AuthManager({\n url: config.url,\n baseUrl: config.baseUrl,\n requestOptions: config.requestOptions,\n onError,\n });\n}\n","import type {\n ApiError,\n ApiResponse,\n Comment,\n CustomFont,\n PlanConfig,\n SavedModule,\n Template,\n TemplateContent,\n TemplateSnapshot,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\nimport type { Block } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\n\nexport class ApiClient {\n constructor(private readonly authManager: AuthManager) {}\n\n private get projectId(): string {\n return this.authManager.projectId;\n }\n\n private get tenantSlug(): string {\n return this.authManager.tenantSlug;\n }\n\n private get baseParams(): Record<string, string> {\n return { project: this.projectId, tenant: this.tenantSlug };\n }\n\n private async request<T>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const response = await this.authManager.authenticatedFetch(path, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error: ApiError = await response.json().catch(() => ({\n message: `HTTP error ${response.status}`,\n }));\n\n const errorMessage = this.extractFirstValidationError(error);\n throw new SdkError(errorMessage, response.status);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const json: ApiResponse<T> = await response.json();\n return json.data;\n }\n\n private extractFirstValidationError(error: ApiError): string {\n if (error.errors) {\n const firstField = Object.keys(error.errors)[0];\n if (firstField && error.errors[firstField]?.length > 0) {\n return error.errors[firstField][0];\n }\n }\n return error.message;\n }\n\n async createTemplate(content: TemplateContent): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.store\"], this.baseParams),\n {\n method: \"POST\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async getTemplate(id: string): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.show\"], {\n ...this.baseParams,\n template: id,\n }),\n );\n }\n\n async updateTemplate(\n id: string,\n content: TemplateContent,\n ): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"templates.update\"], {\n ...this.baseParams,\n template: id,\n }),\n {\n method: \"PUT\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async createSnapshot(\n templateId: string,\n content: TemplateContent,\n ): Promise<TemplateSnapshot> {\n return this.request<TemplateSnapshot>(\n buildUrl(API_ROUTES[\"snapshots.store\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify({ content }),\n },\n );\n }\n\n async deleteTemplate(id: string): Promise<void> {\n return this.request<void>(\n buildUrl(API_ROUTES[\"templates.destroy\"], {\n ...this.baseParams,\n template: id,\n }),\n {\n method: \"DELETE\",\n },\n );\n }\n\n async getSnapshots(templateId: string): Promise<TemplateSnapshot[]> {\n return this.request<TemplateSnapshot[]>(\n buildUrl(API_ROUTES[\"snapshots.index\"], {\n ...this.baseParams,\n template: templateId,\n }),\n );\n }\n\n async restoreSnapshot(\n templateId: string,\n snapshotId: string,\n ): Promise<Template> {\n return this.request<Template>(\n buildUrl(API_ROUTES[\"snapshots.restore\"], {\n ...this.baseParams,\n template: templateId,\n snapshot: snapshotId,\n }),\n {\n method: \"POST\",\n },\n );\n }\n\n async exportTemplate(\n templateId: string,\n fontsPayload?: {\n customFonts: CustomFont[];\n defaultFallback: string;\n },\n ): Promise<{ html: string; mjml: string }> {\n const body = fontsPayload\n ? JSON.stringify({\n custom_fonts: fontsPayload.customFonts,\n default_fallback: fontsPayload.defaultFallback,\n })\n : undefined;\n\n return this.request<{ html: string; mjml: string }>(\n buildUrl(API_ROUTES[\"templates.export\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body,\n },\n );\n }\n\n async sendTestEmail(\n templateId: string,\n payload: {\n recipient: string;\n html: string;\n allowed_emails: string[];\n signature: string;\n },\n ): Promise<void> {\n await this.request<void>(\n buildUrl(API_ROUTES[\"templates.sendTestEmail\"], {\n ...this.baseParams,\n template: templateId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify(payload),\n },\n );\n }\n\n private commentsUrl(templateId: string, commentId?: string): string {\n if (commentId) {\n return buildUrl(API_ROUTES[\"comments.update\"], {\n ...this.baseParams,\n template: templateId,\n comment: commentId,\n });\n }\n return buildUrl(API_ROUTES[\"comments.index\"], {\n ...this.baseParams,\n template: templateId,\n });\n }\n\n async getComments(templateId: string): Promise<Comment[]> {\n return this.request<Comment[]>(this.commentsUrl(templateId));\n }\n\n async createComment(\n templateId: string,\n data: {\n body: string;\n block_id?: string;\n parent_id?: string;\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(this.commentsUrl(templateId), {\n method: \"POST\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async updateComment(\n templateId: string,\n commentId: string,\n data: {\n body: string;\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(this.commentsUrl(templateId, commentId), {\n method: \"PUT\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async deleteComment(\n templateId: string,\n commentId: string,\n data: {\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<void> {\n return this.request<void>(this.commentsUrl(templateId, commentId), {\n method: \"DELETE\",\n body: JSON.stringify(data),\n headers,\n });\n }\n\n async resolveComment(\n templateId: string,\n commentId: string,\n data: {\n user_id: string;\n user_name: string;\n user_signature: string;\n },\n headers?: Record<string, string>,\n ): Promise<Comment> {\n return this.request<Comment>(\n buildUrl(API_ROUTES[\"comments.resolve\"], {\n ...this.baseParams,\n template: templateId,\n comment: commentId,\n }),\n {\n method: \"POST\",\n body: JSON.stringify(data),\n headers,\n },\n );\n }\n\n async fetchConfig(): Promise<PlanConfig> {\n return this.request<PlanConfig>(\n buildUrl(API_ROUTES[\"projects.config\"], this.baseParams),\n );\n }\n\n async listModules(search?: string): Promise<SavedModule[]> {\n const url = buildUrl(API_ROUTES[\"savedModules.index\"], this.baseParams);\n const query = search ? `?search=${encodeURIComponent(search)}` : \"\";\n return this.request<SavedModule[]>(`${url}${query}`);\n }\n\n async createModule(data: {\n name: string;\n content: Block[];\n }): Promise<SavedModule> {\n return this.request<SavedModule>(\n buildUrl(API_ROUTES[\"savedModules.store\"], this.baseParams),\n {\n method: \"POST\",\n body: JSON.stringify(data),\n },\n );\n }\n\n async updateModule(\n id: string,\n data: Partial<{ name: string; content: Block[] }>,\n ): Promise<SavedModule> {\n return this.request<SavedModule>(\n buildUrl(API_ROUTES[\"savedModules.update\"], {\n ...this.baseParams,\n savedModule: id,\n }),\n {\n method: \"PUT\",\n body: JSON.stringify(data),\n },\n );\n }\n\n async deleteModule(id: string): Promise<void> {\n return this.request<void>(\n buildUrl(API_ROUTES[\"savedModules.destroy\"], {\n ...this.baseParams,\n savedModule: id,\n }),\n {\n method: \"DELETE\",\n },\n );\n }\n}\n","export function buildUrl(\n template: string,\n params: Record<string, string>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) =>\n encodeURIComponent(params[key] ?? \"\"),\n );\n}\n\nconst BASE = \"/api/v1/projects/{project}/tenants/{tenant}\";\nconst TEMPLATE = `${BASE}/templates/{template}`;\nconst AI = `${TEMPLATE}/ai`;\nconst MEDIA = `${BASE}/media`;\nconst FOLDERS = `${MEDIA}/folders`;\nconst MODULES = `${BASE}/saved-modules`;\n\nexport const API_ROUTES = {\n health: \"/api/v1/health\",\n \"projects.config\": `${BASE}/config`,\n \"broadcasting.auth\": `${BASE}/broadcasting/auth`,\n \"templates.store\": `${BASE}/templates`,\n \"templates.show\": `${TEMPLATE}`,\n \"templates.update\": `${TEMPLATE}`,\n \"templates.destroy\": `${TEMPLATE}`,\n \"templates.export\": `${TEMPLATE}/export`,\n \"templates.importFromBeefree\": `${BASE}/templates/import/from-beefree`,\n \"templates.sendTestEmail\": `${TEMPLATE}/send-test-email`,\n \"snapshots.index\": `${TEMPLATE}/snapshots`,\n \"snapshots.store\": `${TEMPLATE}/snapshots`,\n \"snapshots.show\": `${TEMPLATE}/snapshots/{snapshot}`,\n \"snapshots.restore\": `${TEMPLATE}/snapshots/{snapshot}/restore`,\n \"comments.index\": `${TEMPLATE}/comments`,\n \"comments.store\": `${TEMPLATE}/comments`,\n \"comments.update\": `${TEMPLATE}/comments/{comment}`,\n \"comments.destroy\": `${TEMPLATE}/comments/{comment}`,\n \"comments.resolve\": `${TEMPLATE}/comments/{comment}/resolve`,\n \"ai.generate\": `${AI}/generate`,\n \"ai.conversationMessages\": `${AI}/conversation-messages`,\n \"ai.suggestions\": `${AI}/suggestions`,\n \"ai.rewriteText\": `${AI}/rewrite-text`,\n \"ai.score\": `${AI}/score`,\n \"ai.fixFinding\": `${AI}/fix-finding`,\n \"ai.generateFromDesign\": `${AI}/generate-from-design`,\n \"media.upload\": `${MEDIA}/upload`,\n \"media.browse\": `${MEDIA}/browse`,\n \"media.delete\": `${MEDIA}/delete`,\n \"media.move\": `${MEDIA}/move`,\n \"media.update\": `${MEDIA}/{media}`,\n \"media.replace\": `${MEDIA}/{media}/replace`,\n \"media.checkUsage\": `${MEDIA}/check-usage`,\n \"media.frequentlyUsed\": `${MEDIA}/frequently-used`,\n \"media.importFromUrl\": `${MEDIA}/import-from-url`,\n \"folders.index\": `${FOLDERS}`,\n \"folders.store\": `${FOLDERS}`,\n \"folders.update\": `${FOLDERS}/{mediaFolder}`,\n \"folders.destroy\": `${FOLDERS}/{mediaFolder}`,\n \"savedModules.index\": `${MODULES}`,\n \"savedModules.store\": `${MODULES}`,\n \"savedModules.update\": `${MODULES}/{savedModule}`,\n \"savedModules.destroy\": `${MODULES}/{savedModule}`,\n} as const;\n","import type { WebSocketServerConfig } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel, PresenceChannel } from \"pusher-js\";\n\ntype PusherType = Pusher;\n\nexport interface WebSocketConfig {\n host: string;\n port: number;\n appKey: string;\n}\n\nexport function resolveWebSocketConfig(\n serverConfig: WebSocketServerConfig,\n): WebSocketConfig {\n return {\n host: serverConfig.host,\n port: serverConfig.port,\n appKey: serverConfig.app_key,\n };\n}\n\nexport interface PresenceMember {\n id: string;\n name: string;\n type: \"user\" | \"mcp\";\n}\n\nexport interface WebSocketClientOptions {\n authManager: AuthManager;\n config: WebSocketConfig;\n onError?: (error: Error) => void;\n}\n\nexport class WebSocketClient {\n private pusher: PusherType | null = null;\n private readonly authManager: AuthManager;\n private readonly config: WebSocketConfig;\n private readonly onError?: (error: Error) => void;\n\n constructor(options: WebSocketClientOptions) {\n this.authManager = options.authManager;\n this.config = options.config;\n this.onError = options.onError;\n }\n\n async connect(): Promise<void> {\n if (this.pusher) {\n return;\n }\n\n let Pusher: typeof import(\"pusher-js\").default;\n try {\n ({ default: Pusher } = await import(\"pusher-js\"));\n } catch {\n throw new Error(\n \"Cloud features require the optional peer dependency 'pusher-js'. Install it with: npm install pusher-js\",\n );\n }\n\n const { host, port, appKey } = this.config;\n const authEndpoint = this.authManager.resolveUrl(\n buildUrl(API_ROUTES[\"broadcasting.auth\"], {\n project: this.authManager.projectId,\n tenant: this.authManager.tenantSlug,\n }),\n );\n\n this.pusher = new Pusher(appKey, {\n wsHost: host,\n wsPort: port,\n wssPort: port,\n forceTLS: true,\n disableStats: true,\n enabledTransports: [\"ws\", \"wss\"],\n cluster: \"\",\n channelAuthorization: {\n transport: \"ajax\",\n endpoint: authEndpoint,\n headers: {\n Authorization: `Bearer ${this.authManager.accessTokenValue}`,\n Accept: \"application/json\",\n },\n params: {\n user_id: this.authManager.userConfig?.id ?? \"\",\n user_name: this.authManager.userConfig?.name ?? \"\",\n user_signature: this.authManager.userConfig?.signature ?? \"\",\n },\n },\n });\n\n this.pusher.connection.bind(\"error\", (error: unknown) => {\n this.onError?.(\n error instanceof Error\n ? error\n : new Error(\"WebSocket connection error\"),\n );\n });\n }\n\n subscribePresence(channelName: string): PresenceChannel {\n if (!this.pusher) {\n throw new Error(\"WebSocketClient not connected. Call connect() first.\");\n }\n\n return this.pusher.subscribe(channelName) as PresenceChannel;\n }\n\n unsubscribe(channelName: string): void {\n this.pusher?.unsubscribe(channelName);\n }\n\n getChannel(channelName: string): Channel | undefined {\n return this.pusher?.channel(channelName);\n }\n\n disconnect(): void {\n if (this.pusher) {\n this.pusher.disconnect();\n this.pusher = null;\n }\n }\n\n getSocketId(): string | null {\n return this.pusher?.connection.socket_id ?? null;\n }\n\n get isConnected(): boolean {\n return this.pusher?.connection.state === \"connected\";\n }\n}\n","import type { McpOperationPayload } from \"@templatical/types\";\nimport type {\n Block,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport type { UseEditorReturn } from \"./editor\";\n\nexport function handleOperation(\n editor: UseEditorReturn,\n payload: McpOperationPayload,\n): void {\n const { operation, data } = payload;\n\n switch (operation) {\n case \"add_block\":\n editor.addBlock(\n data.block as Block,\n data.section_id as string | undefined,\n data.column_index as number | undefined,\n data.index as number | undefined,\n );\n break;\n\n case \"update_block\":\n editor.updateBlock(\n data.block_id as string,\n data.updates as Partial<Block>,\n );\n break;\n\n case \"delete_block\":\n editor.removeBlock(data.block_id as string);\n break;\n\n case \"move_block\":\n editor.moveBlock(\n data.block_id as string,\n data.index as number,\n data.section_id as string | undefined,\n data.column_index as number | undefined,\n );\n break;\n\n case \"update_settings\":\n editor.updateSettings(data.updates as Partial<TemplateSettings>);\n break;\n\n case \"set_content\":\n editor.setContent(data.content as TemplateContent);\n break;\n\n case \"update_block_style\":\n editor.updateBlock(\n data.block_id as string,\n {\n styles: data.styles,\n } as Partial<Block>,\n );\n break;\n }\n}\n","import type {\n EditorState,\n Template,\n TemplateDefaults,\n UiTheme,\n ViewportSize,\n} from \"@templatical/types\";\nimport { SdkError } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport type {\n Block,\n TemplateContent,\n TemplateSettings,\n} from \"@templatical/types\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport { computed, reactive, readonly, type DeepReadonly, type Ref } from \"vue\";\n\nexport interface UseEditorOptions {\n authManager: AuthManager;\n defaultFontFamily?: string;\n templateDefaults?: TemplateDefaults;\n onError?: (error: Error) => void;\n lockedBlocks?: Ref<Map<string, unknown>>;\n}\n\nexport interface UseEditorReturn {\n state: DeepReadonly<EditorState>;\n content: Ref<TemplateContent>;\n selectedBlock: Ref<Block | null>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n selectBlock: (blockId: string | null) => void;\n setViewport: (viewport: ViewportSize) => void;\n setDarkMode: (darkMode: boolean) => void;\n setPreviewMode: (previewMode: boolean) => void;\n setUiTheme: (theme: UiTheme) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n updateSettings: (updates: Partial<TemplateSettings>) => void;\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n moveBlock: (\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n savedBlockIds: Ref<Set<string>>;\n isBlockLocked: (blockId: string) => boolean;\n findBlockLocation: (blockId: string) => {\n targetSectionId?: string;\n columnIndex?: number;\n index: number;\n } | null;\n create: (content?: TemplateContent) => Promise<Template>;\n load: (templateId: string) => Promise<Template>;\n save: () => Promise<Template>;\n createSnapshot: () => Promise<void>;\n hasTemplate: () => boolean;\n markDirty: () => void;\n}\n\nexport function useEditor(options: UseEditorOptions): UseEditorReturn {\n const api = new ApiClient(options.authManager);\n\n const state = reactive<EditorState>({\n template: null,\n content: createDefaultTemplateContent(\n options.defaultFontFamily,\n options.templateDefaults,\n ),\n selectedBlockId: null,\n viewport: \"desktop\",\n darkMode: false,\n previewMode: false,\n isDirty: false,\n isSaving: false,\n isLoading: false,\n uiTheme: \"auto\",\n });\n\n const content = computed({\n get: () => state.content,\n set: (value: TemplateContent) => {\n state.content = value;\n state.isDirty = true;\n },\n });\n\n const selectedBlock = computed(() => {\n if (!state.selectedBlockId) return null;\n return findBlockById(state.content.blocks, state.selectedBlockId);\n });\n\n const savedBlockIds = computed<Set<string>>(() => {\n const ids = new Set<string>();\n const blocks = state.template?.content?.blocks;\n if (!blocks) {\n return ids;\n }\n for (const block of blocks) {\n ids.add(block.id);\n if (block.type === \"section\") {\n for (const column of block.children) {\n for (const child of column) {\n ids.add(child.id);\n }\n }\n }\n }\n return ids;\n });\n\n function findBlockById(blocks: Block[], id: string): Block | null {\n for (const block of blocks) {\n if (block.id === id) return block;\n if (block.type === \"section\") {\n for (const column of block.children) {\n const found = findBlockById(column, id);\n if (found) return found;\n }\n }\n }\n return null;\n }\n\n function findBlockParent(\n blocks: Block[],\n id: string,\n parent: {\n blocks: Block[];\n sectionId?: string;\n columnIndex?: number;\n } = { blocks },\n ): { blocks: Block[]; sectionId?: string; columnIndex?: number } | null {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block.id === id) return parent;\n if (block.type === \"section\") {\n for (let colIdx = 0; colIdx < block.children.length; colIdx++) {\n const result = findBlockParent(block.children[colIdx], id, {\n blocks: block.children[colIdx],\n sectionId: block.id,\n columnIndex: colIdx,\n });\n if (result) return result;\n }\n }\n }\n return null;\n }\n\n function isBlockLocked(blockId: string): boolean {\n return options.lockedBlocks?.value.has(blockId) ?? false;\n }\n\n function setContent(newContent: TemplateContent, markDirty = true): void {\n state.content = newContent;\n if (markDirty) {\n state.isDirty = true;\n }\n }\n\n function selectBlock(blockId: string | null): void {\n if (blockId && isBlockLocked(blockId)) {\n return;\n }\n state.selectedBlockId = blockId;\n }\n\n function setViewport(viewport: ViewportSize): void {\n state.viewport = viewport;\n }\n\n function setDarkMode(darkMode: boolean): void {\n state.darkMode = darkMode;\n }\n\n function setUiTheme(theme: UiTheme): void {\n state.uiTheme = theme;\n }\n\n function setPreviewMode(previewMode: boolean): void {\n state.previewMode = previewMode;\n if (previewMode) {\n state.selectedBlockId = null;\n }\n }\n\n function updateBlock(blockId: string, updates: Partial<Block>): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const block = findBlockById(state.content.blocks, blockId);\n if (block) {\n Object.assign(block, updates);\n state.isDirty = true;\n }\n }\n\n function updateSettings(updates: Partial<TemplateSettings>): void {\n state.content.settings = { ...state.content.settings, ...updates };\n state.isDirty = true;\n }\n\n function addBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex = 0,\n index?: number,\n ): void {\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n const targetArray = section.children[columnIndex];\n if (index !== undefined && index < targetArray.length) {\n targetArray.splice(index, 0, block);\n } else {\n targetArray.push(block);\n }\n }\n } else {\n if (index !== undefined && index < state.content.blocks.length) {\n state.content.blocks.splice(index, 0, block);\n } else {\n state.content.blocks.push(block);\n }\n }\n state.isDirty = true;\n }\n\n function removeBlock(blockId: string): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const parent = findBlockParent(state.content.blocks, blockId);\n if (parent) {\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index !== -1) {\n parent.blocks.splice(index, 1);\n if (state.selectedBlockId === blockId) {\n state.selectedBlockId = null;\n }\n state.isDirty = true;\n }\n }\n }\n\n function moveBlock(\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex = 0,\n ): void {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return;\n\n const oldIndex = parent.blocks.findIndex((b) => b.id === blockId);\n if (oldIndex === -1) return;\n\n const [block] = parent.blocks.splice(oldIndex, 1);\n\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n section.children[columnIndex].splice(newIndex, 0, block);\n }\n } else {\n state.content.blocks.splice(newIndex, 0, block);\n }\n\n state.isDirty = true;\n }\n\n async function create(content?: TemplateContent): Promise<Template> {\n state.isLoading = true;\n try {\n if (content) {\n state.content = content;\n }\n const template = await api.createTemplate(state.content);\n state.template = template;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isLoading = false;\n }\n }\n\n async function load(templateId: string): Promise<Template> {\n state.isLoading = true;\n try {\n const template = await api.getTemplate(templateId);\n state.template = template;\n state.content = template.content;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isLoading = false;\n }\n }\n\n async function save(): Promise<Template> {\n if (!state.template?.id) {\n throw new SdkError(\n \"No template loaded. Call create() or load() before saving.\",\n );\n }\n\n state.isSaving = true;\n try {\n const template = await api.updateTemplate(\n state.template.id,\n state.content,\n );\n state.template = template;\n state.isDirty = false;\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n state.isSaving = false;\n }\n }\n\n async function createSnapshot(): Promise<void> {\n if (!state.template?.id) {\n return;\n }\n\n try {\n await api.createSnapshot(state.template.id, state.content);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n function hasTemplate(): boolean {\n return state.template?.id !== undefined;\n }\n\n function markDirty(): void {\n state.isDirty = true;\n }\n\n function findBlockLocation(blockId: string): {\n targetSectionId?: string;\n columnIndex?: number;\n index: number;\n } | null {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return null;\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index === -1) return null;\n return {\n targetSectionId: parent.sectionId,\n columnIndex: parent.columnIndex,\n index,\n };\n }\n\n return {\n state: readonly(state),\n content,\n selectedBlock,\n savedBlockIds,\n isBlockLocked,\n findBlockLocation,\n setContent,\n selectBlock,\n setViewport,\n setDarkMode,\n setUiTheme,\n setPreviewMode,\n updateBlock,\n updateSettings,\n addBlock,\n removeBlock,\n moveBlock,\n create,\n load,\n save,\n createSnapshot,\n hasTemplate,\n markDirty,\n };\n}\n","import type { AiChatMessage } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { MergeTag, TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseAiChatOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n onApply?: (content: TemplateContent) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseAiChatReturn {\n messages: ReturnType<typeof ref<AiChatMessage[]>>;\n isGenerating: ReturnType<typeof ref<boolean>>;\n isLoadingHistory: ReturnType<typeof ref<boolean>>;\n isLastChangeReverted: ReturnType<typeof ref<boolean>>;\n lastApplyMessageId: ReturnType<typeof ref<string | null>>;\n error: ReturnType<typeof ref<string | null>>;\n failedPrompt: ReturnType<typeof ref<string | null>>;\n suggestions: ReturnType<typeof ref<string[]>>;\n isLoadingSuggestions: ReturnType<typeof ref<boolean>>;\n sendPrompt: (\n prompt: string,\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<TemplateContent | null>;\n toggleLastRevert: () => void;\n loadConversation: () => Promise<void>;\n loadSuggestions: (\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<void>;\n clearChat: () => void;\n}\n\nlet messageIdCounter = 0;\n\nfunction generateMessageId(): string {\n return `msg_${Date.now()}_${++messageIdCounter}`;\n}\n\nexport function useAiChat(options: UseAiChatOptions): UseAiChatReturn {\n const { authManager, getTemplateId, onApply, onError } = options;\n\n const messages = ref<AiChatMessage[]>([]);\n const isGenerating = ref(false);\n const isLoadingHistory = ref(false);\n const error = ref<string | null>(null);\n const failedPrompt = ref<string | null>(null);\n const conversationId = ref<string | null>(null);\n const lastApplyMessageId = ref<string | null>(null);\n const lastPreviousContent = ref<TemplateContent | null>(null);\n const lastAppliedContent = ref<TemplateContent | null>(null);\n const isLastChangeReverted = ref(false);\n const suggestions = ref<string[]>([]);\n const isLoadingSuggestions = ref(false);\n\n function updateMessage(msgId: string, updates: Partial<AiChatMessage>): void {\n const idx = messages.value.findIndex((m) => m.id === msgId);\n if (idx === -1) {\n return;\n }\n\n const updated = { ...messages.value[idx], ...updates };\n messages.value = [\n ...messages.value.slice(0, idx),\n updated,\n ...messages.value.slice(idx + 1),\n ];\n }\n\n async function loadConversation(): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoadingHistory.value = true;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.conversationMessages\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n },\n });\n\n if (!response.ok) {\n return;\n }\n\n const data = await response.json();\n\n if (data.conversation_id) {\n conversationId.value = data.conversation_id;\n }\n\n if (Array.isArray(data.data) && data.data.length > 0) {\n messages.value = data.data.map(\n (msg: {\n id: string;\n role: \"user\" | \"assistant\";\n content: string;\n created_at: string;\n }) => ({\n id: msg.id,\n role: msg.role,\n content: msg.content,\n timestamp: new Date(msg.created_at).getTime(),\n }),\n );\n }\n } catch {\n // Silently fail - chat will start fresh\n } finally {\n isLoadingHistory.value = false;\n }\n }\n\n async function loadSuggestions(\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoadingSuggestions.value = true;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.suggestions\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n current_content: currentContent,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n return;\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n return;\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"done\" && Array.isArray(event.suggestions)) {\n suggestions.value = event.suggestions.slice(0, 3);\n }\n }\n }\n } catch {\n // Silently fail - suggestions are non-critical\n } finally {\n isLoadingSuggestions.value = false;\n }\n }\n\n async function sendPrompt(\n prompt: string,\n currentContent: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<TemplateContent | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before using AI generation\");\n }\n\n isGenerating.value = true;\n error.value = null;\n failedPrompt.value = null;\n suggestions.value = [];\n\n const userMsgId = generateMessageId();\n messages.value = [\n ...messages.value,\n {\n id: userMsgId,\n role: \"user\",\n content: prompt,\n timestamp: Date.now(),\n },\n ];\n\n const assistantMsgId = generateMessageId();\n messages.value = [\n ...messages.value,\n {\n id: assistantMsgId,\n role: \"assistant\",\n content: \"\",\n timestamp: Date.now(),\n },\n ];\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.generate\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n prompt,\n current_content: currentContent,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n conversation_id: conversationId.value,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => null);\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n throw new Error(errorData?.message || \"Failed to generate template\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: TemplateContent | null = null;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n const jsonStr = line.slice(6);\n\n let event;\n try {\n event = JSON.parse(jsonStr);\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n updateMessage(assistantMsgId, {\n content:\n (messages.value.find((m) => m.id === assistantMsgId)\n ?.content ?? \"\") + event.text,\n });\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to generate template\");\n } else if (event.type === \"done\") {\n if (event.conversation_id) {\n conversationId.value = event.conversation_id;\n }\n\n updateMessage(assistantMsgId, {\n content: event.text,\n });\n\n result = event.content ?? null;\n\n if (result) {\n lastPreviousContent.value = currentContent;\n lastAppliedContent.value = result;\n lastApplyMessageId.value = assistantMsgId;\n isLastChangeReverted.value = false;\n onApply?.(result);\n } else {\n error.value = \"ai_apply_failed\";\n }\n }\n }\n }\n } finally {\n // Release the underlying network resource even on early exit.\n // Without this, throwing out of the loop (e.g. on an `error` SSE\n // event) leaves the socket and read buffer attached until GC.\n reader.cancel().catch(() => {});\n }\n\n return result;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to generate template\", { cause: err });\n error.value = wrappedError.message;\n failedPrompt.value = prompt;\n onError?.(wrappedError);\n\n messages.value = messages.value.filter(\n (m) => m.id !== userMsgId && m.id !== assistantMsgId,\n );\n\n return null;\n } finally {\n isGenerating.value = false;\n }\n }\n\n function toggleLastRevert(): void {\n if (isLastChangeReverted.value) {\n if (lastAppliedContent.value) {\n onApply?.(lastAppliedContent.value);\n }\n isLastChangeReverted.value = false;\n } else {\n if (lastPreviousContent.value) {\n onApply?.(lastPreviousContent.value);\n }\n isLastChangeReverted.value = true;\n }\n }\n\n function clearChat(): void {\n messages.value = [];\n conversationId.value = null;\n error.value = null;\n lastApplyMessageId.value = null;\n lastPreviousContent.value = null;\n lastAppliedContent.value = null;\n isLastChangeReverted.value = false;\n }\n\n return {\n messages,\n isGenerating,\n isLoadingHistory,\n isLastChangeReverted,\n lastApplyMessageId,\n error,\n failedPrompt,\n suggestions,\n isLoadingSuggestions,\n sendPrompt,\n toggleLastRevert,\n loadConversation,\n loadSuggestions,\n clearChat,\n };\n}\n","import type { MergeTag } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport { ref } from \"vue\";\n\nexport interface UseAiRewriteOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n}\n\nexport interface UseAiRewriteReturn {\n isRewriting: ReturnType<typeof ref<boolean>>;\n streamingText: ReturnType<typeof ref<string>>;\n previousContent: ReturnType<typeof ref<string | null>>;\n rewrittenContent: ReturnType<typeof ref<string | null>>;\n isReverted: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<string | null>>;\n rewrite: (\n content: string,\n instruction: string,\n mergeTags: MergeTag[],\n ) => Promise<string | null>;\n undo: () => string | null;\n redo: () => string | null;\n reset: () => void;\n}\n\nexport function useAiRewrite(options: UseAiRewriteOptions): UseAiRewriteReturn {\n const { authManager, getTemplateId } = options;\n\n const isRewriting = ref(false);\n const streamingText = ref(\"\");\n const previousContent = ref<string | null>(null);\n const rewrittenContent = ref<string | null>(null);\n const isReverted = ref(false);\n const error = ref<string | null>(null);\n\n async function rewrite(\n content: string,\n instruction: string,\n mergeTags: MergeTag[],\n ): Promise<string | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isRewriting.value = true;\n streamingText.value = \"\";\n error.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.rewriteText\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n content,\n instruction,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to rewrite text\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: string | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n streamingText.value += event.text;\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to rewrite text\");\n } else if (event.type === \"done\") {\n result = event.content ?? null;\n\n if (result) {\n previousContent.value = content;\n rewrittenContent.value = result;\n isReverted.value = false;\n }\n }\n }\n }\n\n return result;\n } catch (err) {\n error.value =\n err instanceof Error ? err.message : \"Failed to rewrite text\";\n return null;\n } finally {\n isRewriting.value = false;\n }\n }\n\n function undo(): string | null {\n if (!previousContent.value) {\n return null;\n }\n\n isReverted.value = true;\n return previousContent.value;\n }\n\n function redo(): string | null {\n if (!rewrittenContent.value) {\n return null;\n }\n\n isReverted.value = false;\n return rewrittenContent.value;\n }\n\n function reset(): void {\n isRewriting.value = false;\n streamingText.value = \"\";\n previousContent.value = null;\n rewrittenContent.value = null;\n isReverted.value = false;\n error.value = null;\n }\n\n return {\n isRewriting,\n streamingText,\n previousContent,\n rewrittenContent,\n isReverted,\n error,\n rewrite,\n undo,\n redo,\n reset,\n };\n}\n","import type { AiConfig } from \"@templatical/types\";\nimport { computed, type ComputedRef } from \"vue\";\n\nexport interface UseAiConfigReturn {\n isFeatureEnabled: (feature: keyof AiConfig) => boolean;\n hasAnyMenuFeature: ComputedRef<boolean>;\n}\n\nexport function useAiConfig(config?: AiConfig | false): UseAiConfigReturn {\n function isFeatureEnabled(feature: keyof AiConfig): boolean {\n if (config === false) {\n return false;\n }\n\n return config?.[feature] !== false;\n }\n\n const hasAnyMenuFeature = computed(\n () =>\n isFeatureEnabled(\"chat\") ||\n isFeatureEnabled(\"scoring\") ||\n isFeatureEnabled(\"designToTemplate\"),\n );\n\n return {\n isFeatureEnabled,\n hasAnyMenuFeature,\n };\n}\n","import type {\n ScoringCategory,\n ScoringFinding,\n ScoringResult,\n} from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { MergeTag, TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseTemplateScoringOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n}\n\nexport interface UseTemplateScoringReturn {\n isScoring: ReturnType<typeof ref<boolean>>;\n scoringResult: ReturnType<typeof ref<ScoringResult | null>>;\n error: ReturnType<typeof ref<string | null>>;\n fixingFindingId: ReturnType<typeof ref<string | null>>;\n fixStreamingText: ReturnType<typeof ref<string>>;\n fixError: ReturnType<typeof ref<string | null>>;\n score: (\n content: TemplateContent,\n mergeTags: MergeTag[],\n ) => Promise<ScoringResult | null>;\n fixFinding: (\n blockContent: string,\n finding: ScoringFinding,\n mergeTags: MergeTag[],\n ) => Promise<string | null>;\n removeFinding: (category: ScoringCategory, findingId: string) => void;\n reset: () => void;\n}\n\nexport function useTemplateScoring(\n options: UseTemplateScoringOptions,\n): UseTemplateScoringReturn {\n const { authManager, getTemplateId } = options;\n\n const isScoring = ref(false);\n const scoringResult = ref<ScoringResult | null>(null);\n const error = ref<string | null>(null);\n const fixingFindingId = ref<string | null>(null);\n const fixStreamingText = ref(\"\");\n const fixError = ref<string | null>(null);\n\n async function score(\n content: TemplateContent,\n mergeTags: MergeTag[],\n ): Promise<ScoringResult | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isScoring.value = true;\n error.value = null;\n scoringResult.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.score\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n current_content: content,\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to score template\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: ScoringResult | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to score template\");\n }\n\n if (event.type === \"done\") {\n result = event.result ?? null;\n }\n }\n }\n\n if (result) {\n for (const [category, categoryData] of Object.entries(\n result.categories,\n )) {\n for (const finding of categoryData.findings) {\n finding.category = category as ScoringCategory;\n }\n }\n }\n\n scoringResult.value = result;\n return result;\n } catch (err) {\n error.value =\n err instanceof Error ? err.message : \"Failed to score template\";\n return null;\n } finally {\n isScoring.value = false;\n }\n }\n\n async function fixFinding(\n blockContent: string,\n finding: ScoringFinding,\n mergeTags: MergeTag[],\n ): Promise<string | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n fixingFindingId.value = finding.id;\n fixStreamingText.value = \"\";\n fixError.value = null;\n\n try {\n const url = buildUrl(API_ROUTES[\"ai.fixFinding\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n },\n body: JSON.stringify({\n content: blockContent,\n finding: {\n id: finding.id,\n message: finding.message,\n suggestion: finding.suggestion,\n category: finding.category,\n },\n merge_tags: mergeTags.map((p) => ({\n label: p.label,\n value: p.value,\n })),\n }),\n });\n\n if (!response.ok) {\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n const errorData = await response.json().catch(() => null);\n throw new Error(errorData?.message || \"Failed to fix finding\");\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: string | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n let event;\n try {\n event = JSON.parse(line.slice(6));\n } catch {\n continue;\n }\n\n if (event.type === \"text\") {\n fixStreamingText.value += event.text;\n } else if (event.type === \"error\") {\n throw new Error(event.message || \"Failed to fix finding\");\n } else if (event.type === \"done\") {\n result = event.content ?? null;\n }\n }\n }\n\n return result;\n } catch (err) {\n fixError.value =\n err instanceof Error ? err.message : \"Failed to fix finding\";\n return null;\n } finally {\n fixingFindingId.value = null;\n }\n }\n\n function removeFinding(category: ScoringCategory, findingId: string): void {\n if (!scoringResult.value) {\n return;\n }\n\n const cat = scoringResult.value.categories[category];\n if (!cat) {\n return;\n }\n\n cat.findings = cat.findings.filter((f) => f.id !== findingId);\n }\n\n function reset(): void {\n isScoring.value = false;\n scoringResult.value = null;\n error.value = null;\n fixingFindingId.value = null;\n fixStreamingText.value = \"\";\n fixError.value = null;\n }\n\n return {\n isScoring,\n scoringResult,\n error,\n fixingFindingId,\n fixStreamingText,\n fixError,\n score,\n fixFinding,\n removeFinding,\n reset,\n };\n}\n","import type { AuthManager } from \"./auth\";\nimport { API_ROUTES, buildUrl } from \"./url-builder\";\nimport type { TemplateContent } from \"@templatical/types\";\nimport { ref } from \"vue\";\n\nexport interface UseDesignReferenceOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n onApply?: (content: TemplateContent) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseDesignReferenceReturn {\n isGenerating: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<string | null>>;\n generate: (input: DesignReferenceInput) => Promise<TemplateContent | null>;\n reset: () => void;\n}\n\nexport interface DesignReferenceInput {\n prompt?: string;\n imageUpload?: File;\n pdfUpload?: File;\n}\n\nexport function useDesignReference(\n options: UseDesignReferenceOptions,\n): UseDesignReferenceReturn {\n const { authManager, getTemplateId, onApply, onError } = options;\n\n const isGenerating = ref(false);\n const error = ref<string | null>(null);\n\n async function generate(\n input: DesignReferenceInput,\n ): Promise<TemplateContent | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before using design reference\");\n }\n\n isGenerating.value = true;\n error.value = null;\n\n try {\n const formData = new FormData();\n\n if (input.prompt) {\n formData.append(\"prompt\", input.prompt);\n }\n\n if (input.imageUpload) {\n formData.append(\"image_upload\", input.imageUpload);\n }\n\n if (input.pdfUpload) {\n formData.append(\"pdf_upload\", input.pdfUpload);\n }\n\n const url = buildUrl(API_ROUTES[\"ai.generateFromDesign\"], {\n project: authManager.projectId,\n tenant: authManager.tenantSlug,\n template: templateId,\n });\n\n const response = await authManager.authenticatedFetch(url, {\n method: \"POST\",\n headers: {\n Accept: \"text/event-stream\",\n },\n body: formData,\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => null);\n if (response.status === 403) {\n throw new Error(\"ai_generation_not_available\");\n }\n throw new Error(\n errorData?.message || \"Failed to generate template from design\",\n );\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Failed to read stream\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let result: TemplateContent | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) {\n continue;\n }\n\n const jsonStr = line.slice(6);\n\n let event;\n try {\n event = JSON.parse(jsonStr);\n } catch {\n continue;\n }\n\n if (event.type === \"error\") {\n throw new Error(\n event.message || \"Failed to generate template from design\",\n );\n }\n\n if (event.type === \"done\") {\n result = event.content ?? null;\n\n if (result) {\n onApply?.(result);\n }\n }\n }\n }\n\n return result;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to generate template from design\", {\n cause: err,\n });\n error.value = wrappedError.message;\n onError?.(wrappedError);\n\n return null;\n } finally {\n isGenerating.value = false;\n }\n }\n\n function reset(): void {\n isGenerating.value = false;\n error.value = null;\n }\n\n return {\n isGenerating,\n error,\n generate,\n reset,\n };\n}\n","import type {\n Comment,\n CommentEvent,\n CommentThread,\n UserConfig,\n} from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { computed, ref, type ComputedRef, type Ref } from \"vue\";\n\nexport interface UseCommentsOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n getSocketId?: () => string | null;\n onComment?: (event: CommentEvent) => void;\n onError?: (error: Error) => void;\n isAuthReady?: Ref<boolean>;\n hasCommentingFeature?: () => boolean;\n}\n\nexport interface UseCommentsReturn {\n comments: Ref<CommentThread[]>;\n isLoading: Ref<boolean>;\n isSubmitting: Ref<boolean>;\n isEnabled: ComputedRef<boolean>;\n commentCountByBlock: ComputedRef<Map<string, number>>;\n totalCount: ComputedRef<number>;\n unresolvedCount: ComputedRef<number>;\n loadComments: () => Promise<void>;\n addComment: (\n body: string,\n blockId?: string,\n parentId?: string,\n ) => Promise<Comment | null>;\n editComment: (commentId: string, body: string) => Promise<Comment | null>;\n removeComment: (commentId: string) => Promise<boolean>;\n toggleResolve: (commentId: string) => Promise<Comment | null>;\n applyRemoteCreate: (comment: Comment) => void;\n applyRemoteUpdate: (comment: Comment) => void;\n applyRemoteDelete: (commentId: string, parentId: string | null) => void;\n}\n\nexport function useComments(options: UseCommentsOptions): UseCommentsReturn {\n const {\n authManager,\n getTemplateId,\n getSocketId,\n onComment,\n onError,\n hasCommentingFeature,\n } = options;\n\n const api = new ApiClient(authManager);\n const comments = ref<CommentThread[]>([]);\n const isLoading = ref(false);\n const isSubmitting = ref(false);\n\n const isEnabled = computed<boolean>(() => {\n const featureAvailable = hasCommentingFeature?.() ?? false;\n return featureAvailable && authManager.userConfig !== null;\n });\n\n const totalCount = computed<number>(() => {\n let count = 0;\n for (const thread of comments.value) {\n count += 1 + (thread.replies?.length ?? 0);\n }\n return count;\n });\n\n const unresolvedCount = computed<number>(() => {\n return comments.value.filter((c) => !c.resolved_at).length;\n });\n\n const commentCountByBlock = computed<Map<string, number>>(() => {\n const map = new Map<string, number>();\n for (const thread of comments.value) {\n if (thread.block_id) {\n map.set(\n thread.block_id,\n (map.get(thread.block_id) ?? 0) + 1 + (thread.replies?.length ?? 0),\n );\n }\n }\n return map;\n });\n\n function getUserPayload(): {\n user_id: string;\n user_name: string;\n user_signature: string;\n } {\n const user: UserConfig | null = authManager.userConfig;\n if (!user) {\n throw new Error(\"User config not available\");\n }\n return {\n user_id: user.id,\n user_name: user.name,\n user_signature: user.signature,\n };\n }\n\n function socketHeaders(): Record<string, string> | undefined {\n const socketId = getSocketId?.();\n if (!socketId) {\n return undefined;\n }\n return { \"X-Socket-ID\": socketId };\n }\n\n function emitEvent(type: CommentEvent[\"type\"], comment: Comment): void {\n onComment?.({ type, comment });\n }\n\n function findComment(commentId: string): Comment | null {\n for (const thread of comments.value) {\n if (thread.id === commentId) {\n return thread;\n }\n for (const reply of thread.replies ?? []) {\n if (reply.id === commentId) {\n return reply;\n }\n }\n }\n return null;\n }\n\n async function loadComments(): Promise<void> {\n const templateId = getTemplateId();\n if (!templateId) {\n return;\n }\n\n isLoading.value = true;\n\n try {\n comments.value = await api.getComments(templateId);\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to load comments\", { cause: err });\n onError?.(wrappedError);\n } finally {\n isLoading.value = false;\n }\n }\n\n async function addComment(\n body: string,\n blockId?: string,\n parentId?: string,\n ): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const comment = await api.createComment(\n templateId,\n {\n body,\n block_id: blockId,\n parent_id: parentId,\n ...getUserPayload(),\n },\n socketHeaders(),\n );\n\n if (parentId) {\n const parent = findComment(parentId);\n if (parent) {\n parent.replies = [...(parent.replies ?? []), comment];\n }\n } else {\n comments.value = [...comments.value, comment];\n }\n\n emitEvent(\"created\", comment);\n return comment;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to create comment\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function editComment(\n commentId: string,\n body: string,\n ): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const updated = await api.updateComment(\n templateId,\n commentId,\n {\n body,\n ...getUserPayload(),\n },\n socketHeaders(),\n );\n\n updateCommentInState(commentId, updated);\n emitEvent(\"updated\", updated);\n return updated;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to update comment\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function removeComment(commentId: string): Promise<boolean> {\n const templateId = getTemplateId();\n if (!templateId) {\n return false;\n }\n\n const comment = findComment(commentId);\n if (!comment) {\n return false;\n }\n\n const commentSnapshot = {\n ...comment,\n replies: [...(comment.replies ?? [])],\n };\n\n isSubmitting.value = true;\n\n try {\n await api.deleteComment(\n templateId,\n commentId,\n getUserPayload(),\n socketHeaders(),\n );\n\n if (comment.parent_id) {\n const parent = findComment(comment.parent_id);\n if (parent) {\n parent.replies = (parent.replies ?? []).filter(\n (r) => r.id !== commentId,\n );\n }\n } else {\n comments.value = comments.value.filter((c) => c.id !== commentId);\n }\n\n emitEvent(\"deleted\", commentSnapshot);\n return true;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to delete comment\", { cause: err });\n onError?.(wrappedError);\n return false;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n async function toggleResolve(commentId: string): Promise<Comment | null> {\n const templateId = getTemplateId();\n if (!templateId) {\n return null;\n }\n\n isSubmitting.value = true;\n\n try {\n const updated = await api.resolveComment(\n templateId,\n commentId,\n getUserPayload(),\n socketHeaders(),\n );\n\n updateCommentInState(commentId, updated);\n\n const eventType = updated.resolved_at ? \"resolved\" : \"unresolved\";\n emitEvent(eventType, updated);\n return updated;\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to toggle comment resolution\", { cause: err });\n onError?.(wrappedError);\n return null;\n } finally {\n isSubmitting.value = false;\n }\n }\n\n function applyRemoteCreate(comment: Comment): void {\n if (comment.parent_id) {\n const parent = findComment(comment.parent_id);\n if (parent) {\n parent.replies = [...(parent.replies ?? []), comment];\n }\n } else {\n comments.value = [...comments.value, comment];\n }\n emitEvent(\"created\", comment);\n }\n\n function applyRemoteUpdate(comment: Comment): void {\n updateCommentInState(comment.id, comment);\n emitEvent(\"updated\", comment);\n }\n\n function applyRemoteDelete(commentId: string, parentId: string | null): void {\n const comment = findComment(commentId);\n const snapshot = comment\n ? { ...comment, replies: [...(comment.replies ?? [])] }\n : null;\n\n if (parentId) {\n const parent = findComment(parentId);\n if (parent) {\n parent.replies = (parent.replies ?? []).filter(\n (r) => r.id !== commentId,\n );\n }\n } else {\n comments.value = comments.value.filter((c) => c.id !== commentId);\n }\n\n if (snapshot) {\n emitEvent(\"deleted\", snapshot);\n }\n }\n\n function updateCommentInState(commentId: string, updated: Comment): void {\n for (let i = 0; i < comments.value.length; i++) {\n if (comments.value[i].id === commentId) {\n comments.value = [\n ...comments.value.slice(0, i),\n { ...updated, replies: comments.value[i].replies },\n ...comments.value.slice(i + 1),\n ];\n return;\n }\n\n const replies = comments.value[i].replies ?? [];\n for (let j = 0; j < replies.length; j++) {\n if (replies[j].id === commentId) {\n const newReplies = [\n ...replies.slice(0, j),\n updated,\n ...replies.slice(j + 1),\n ];\n comments.value = [\n ...comments.value.slice(0, i),\n { ...comments.value[i], replies: newReplies },\n ...comments.value.slice(i + 1),\n ];\n return;\n }\n }\n }\n }\n\n return {\n comments,\n isLoading,\n isSubmitting,\n isEnabled,\n commentCountByBlock,\n totalCount,\n unresolvedCount,\n loadComments,\n addComment,\n editComment,\n removeComment,\n toggleResolve,\n applyRemoteCreate,\n applyRemoteUpdate,\n applyRemoteDelete,\n };\n}\n","import type { UseCommentsReturn } from \"./comments\";\nimport type { Comment } from \"@templatical/types\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { onScopeDispose, watch, type Ref } from \"vue\";\n\nexport interface CommentBroadcastPayload {\n action:\n | \"comment_created\"\n | \"comment_updated\"\n | \"comment_deleted\"\n | \"comment_resolved\"\n | \"comment_unresolved\";\n comment: Comment;\n}\n\nexport interface UseCommentListenerOptions {\n comments: UseCommentsReturn;\n channel: Ref<PresenceChannel | null>;\n}\n\nexport function useCommentListener(options: UseCommentListenerOptions): void {\n const { comments, channel } = options;\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n oldChannel.unbind(\"comment-broadcast\");\n }\n\n if (newChannel) {\n newChannel.bind(\n \"comment-broadcast\",\n (payload: CommentBroadcastPayload) => {\n handleCommentBroadcast(comments, payload);\n },\n );\n }\n });\n\n // The watch only unbinds on channel *transitions*. On scope dispose the\n // currently-bound handler stays attached, processing broadcasts on a\n // dead component. Explicitly tear it down.\n onScopeDispose(() => {\n channel.value?.unbind(\"comment-broadcast\");\n });\n}\n\nfunction handleCommentBroadcast(\n comments: UseCommentsReturn,\n payload: CommentBroadcastPayload,\n): void {\n switch (payload.action) {\n case \"comment_created\":\n comments.applyRemoteCreate(payload.comment);\n break;\n case \"comment_updated\":\n comments.applyRemoteUpdate(payload.comment);\n break;\n case \"comment_deleted\":\n comments.applyRemoteDelete(payload.comment.id, payload.comment.parent_id);\n break;\n case \"comment_resolved\":\n case \"comment_unresolved\":\n comments.applyRemoteUpdate(payload.comment);\n break;\n }\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { AuthManager } from \"./auth\";\nimport type { Collaborator, McpOperationPayload } from \"@templatical/types\";\nimport { handleOperation } from \"./mcp-operation-handler\";\nimport type { PresenceMember } from \"./websocket-client\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { computed, onScopeDispose, ref, watch, type Ref } from \"vue\";\n\nconst COLLAB_EVENTS = [\n \"pusher:member_added\",\n \"pusher:member_removed\",\n \"client-block_locked\",\n \"client-block_unlocked\",\n \"client-operation\",\n \"mcp-operation\",\n] as const;\n\nfunction unbindCollabEvents(channel: PresenceChannel): void {\n for (const event of COLLAB_EVENTS) {\n channel.unbind(event);\n }\n}\n\nconst COLLABORATOR_COLORS = [\n \"#3b82f6\",\n \"#ef4444\",\n \"#10b981\",\n \"#f59e0b\",\n \"#8b5cf6\",\n \"#ec4899\",\n \"#06b6d4\",\n \"#f97316\",\n \"#6366f1\",\n \"#14b8a6\",\n];\n\nexport interface UseCollaborationOptions {\n authManager: AuthManager;\n editor: UseEditorReturn;\n channel: Ref<PresenceChannel | null>;\n onError?: (error: Error) => void;\n onCollaboratorJoined?: (collaborator: Collaborator) => void;\n onCollaboratorLeft?: (collaborator: Collaborator) => void;\n onBlockLocked?: (event: {\n blockId: string;\n collaborator: Collaborator;\n }) => void;\n onBlockUnlocked?: (event: {\n blockId: string;\n collaborator: Collaborator;\n }) => void;\n}\n\nexport interface UseCollaborationReturn {\n collaborators: Ref<Collaborator[]>;\n lockedBlocks: Ref<Map<string, Collaborator>>;\n}\n\nexport function useCollaboration(\n options: UseCollaborationOptions,\n): UseCollaborationReturn & {\n _broadcastOperation: (payload: McpOperationPayload) => void;\n _isProcessingRemoteOperation: () => boolean;\n} {\n const { authManager, editor, channel } = options;\n\n const collaborators = ref<Collaborator[]>([]);\n const lockedBlocks = ref<Map<string, Collaborator>>(new Map());\n\n let colorIndex = 0;\n let isProcessingRemoteOperation = false;\n\n const myUserId = computed(() => authManager.userConfig?.id ?? \"\");\n\n function assignColor(): string {\n const color = COLLABORATOR_COLORS[colorIndex % COLLABORATOR_COLORS.length];\n colorIndex++;\n return color;\n }\n\n function addCollaborator(member: PresenceMember): Collaborator | undefined {\n if (member.id === myUserId.value) {\n return undefined;\n }\n\n if (collaborators.value.some((c) => c.id === member.id)) {\n return undefined;\n }\n\n const collaborator: Collaborator = {\n id: member.id,\n name: member.name,\n color: assignColor(),\n selectedBlockId: null,\n };\n\n collaborators.value = [...collaborators.value, collaborator];\n\n return collaborator;\n }\n\n function removeCollaborator(memberId: string): void {\n const newLockedBlocks = new Map(lockedBlocks.value);\n for (const [blockId, collaborator] of newLockedBlocks) {\n if (collaborator.id === memberId) {\n newLockedBlocks.delete(blockId);\n }\n }\n lockedBlocks.value = newLockedBlocks;\n\n collaborators.value = collaborators.value.filter((c) => c.id !== memberId);\n }\n\n function handleBlockLocked(data: { blockId: string; userId: string }): void {\n const collaborator = collaborators.value.find((c) => c.id === data.userId);\n if (!collaborator) {\n return;\n }\n\n collaborators.value = collaborators.value.map((c) =>\n c.id === data.userId ? { ...c, selectedBlockId: data.blockId } : c,\n );\n\n const newLockedBlocks = new Map(lockedBlocks.value);\n for (const [blockId, holder] of newLockedBlocks) {\n if (holder.id === data.userId) {\n newLockedBlocks.delete(blockId);\n }\n }\n\n newLockedBlocks.set(data.blockId, {\n ...collaborator,\n selectedBlockId: data.blockId,\n });\n lockedBlocks.value = newLockedBlocks;\n\n if (editor.state.selectedBlockId === data.blockId) {\n editor.selectBlock(null);\n }\n }\n\n function handleBlockUnlocked(data: { blockId: string }): void {\n const newLockedBlocks = new Map(lockedBlocks.value);\n const holder = newLockedBlocks.get(data.blockId);\n newLockedBlocks.delete(data.blockId);\n lockedBlocks.value = newLockedBlocks;\n\n if (holder) {\n collaborators.value = collaborators.value.map((c) =>\n c.id === holder.id ? { ...c, selectedBlockId: null } : c,\n );\n }\n }\n\n function handleRemoteOperation(payload: McpOperationPayload): void {\n isProcessingRemoteOperation = true;\n try {\n handleOperation(editor, payload);\n } finally {\n isProcessingRemoteOperation = false;\n }\n }\n\n function broadcastOperation(payload: McpOperationPayload): void {\n if (!channel.value || isProcessingRemoteOperation) {\n return;\n }\n\n channel.value.trigger(\"client-operation\", payload);\n }\n\n function broadcastBlockLocked(blockId: string): void {\n if (!channel.value) {\n return;\n }\n\n channel.value.trigger(\"client-block_locked\", {\n blockId,\n userId: myUserId.value,\n });\n }\n\n function broadcastBlockUnlocked(blockId: string): void {\n if (!channel.value) {\n return;\n }\n\n channel.value.trigger(\"client-block_unlocked\", { blockId });\n }\n\n watch(\n () => editor.state.selectedBlockId,\n (newBlockId, oldBlockId) => {\n if (isProcessingRemoteOperation) {\n return;\n }\n\n if (oldBlockId) {\n broadcastBlockUnlocked(oldBlockId);\n }\n\n if (newBlockId) {\n broadcastBlockLocked(newBlockId);\n }\n },\n );\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n unbindCollabEvents(oldChannel);\n }\n\n if (!newChannel) {\n collaborators.value = [];\n lockedBlocks.value = new Map();\n colorIndex = 0;\n return;\n }\n\n const members = (\n newChannel as PresenceChannel & {\n members: {\n each: (\n callback: (member: { id: string; info: PresenceMember }) => void,\n ) => void;\n };\n }\n ).members;\n if (members) {\n members.each((member: { id: string; info: PresenceMember }) => {\n addCollaborator(member.info);\n });\n }\n\n newChannel.bind(\n \"pusher:member_added\",\n (member: { id: string; info: PresenceMember }) => {\n const collaborator = addCollaborator(member.info);\n if (collaborator) {\n options.onCollaboratorJoined?.(collaborator);\n }\n },\n );\n\n newChannel.bind(\n \"pusher:member_removed\",\n (member: { id: string; info: PresenceMember }) => {\n const collaborator = collaborators.value.find(\n (c) => c.id === member.id,\n );\n removeCollaborator(member.id);\n if (collaborator) {\n options.onCollaboratorLeft?.(collaborator);\n }\n },\n );\n\n newChannel.bind(\n \"client-block_locked\",\n (data: { blockId: string; userId: string }) => {\n handleBlockLocked(data);\n const collaborator = collaborators.value.find(\n (c) => c.id === data.userId,\n );\n if (collaborator) {\n options.onBlockLocked?.({\n blockId: data.blockId,\n collaborator,\n });\n }\n },\n );\n\n newChannel.bind(\"client-block_unlocked\", (data: { blockId: string }) => {\n const holder = lockedBlocks.value.get(data.blockId);\n handleBlockUnlocked(data);\n if (holder) {\n options.onBlockUnlocked?.({\n blockId: data.blockId,\n collaborator: holder,\n });\n }\n });\n\n newChannel.bind(\"client-operation\", (payload: McpOperationPayload) => {\n handleRemoteOperation(payload);\n });\n\n newChannel.bind(\"mcp-operation\", (payload: McpOperationPayload) => {\n handleRemoteOperation(payload);\n });\n });\n\n // The watch above only unbinds when the channel ref *changes*. On scope\n // dispose (component unmount) the watch is auto-stopped but the currently\n // bound listeners stay attached forever — handlers fire on a dead component\n // and accumulate on remount. Tear them down explicitly.\n onScopeDispose(() => {\n if (channel.value) {\n unbindCollabEvents(channel.value);\n }\n });\n\n return {\n collaborators,\n lockedBlocks,\n _broadcastOperation: broadcastOperation,\n _isProcessingRemoteOperation: () => isProcessingRemoteOperation,\n };\n}\n","import type { McpOperationPayload } from \"@templatical/types\";\nimport type { UseEditorReturn } from \"../editor\";\n\ninterface BroadcastTarget {\n _broadcastOperation: (payload: McpOperationPayload) => void;\n}\n\n/**\n * Wraps editor mutation methods to broadcast operations to collaboration\n * peers after each mutation executes. Mutates the editor object in place.\n *\n * Must be applied **before** the history interceptor so the call chain is:\n * history.record() → broadcast + original mutation.\n */\nexport function useCollaborationBroadcast(\n editor: UseEditorReturn,\n collaboration: BroadcastTarget,\n): void {\n const originalAddBlock = editor.addBlock;\n const originalUpdateBlock = editor.updateBlock;\n const originalRemoveBlock = editor.removeBlock;\n const originalMoveBlock = editor.moveBlock;\n const originalUpdateSettings = editor.updateSettings;\n const originalSetContent = editor.setContent;\n\n editor.addBlock = (block, targetSectionId?, columnIndex?) => {\n originalAddBlock(block, targetSectionId, columnIndex);\n collaboration._broadcastOperation({\n operation: \"add_block\",\n data: {\n block,\n section_id: targetSectionId,\n column_index: columnIndex,\n },\n timestamp: Date.now(),\n });\n };\n\n editor.updateBlock = (blockId, updates) => {\n originalUpdateBlock(blockId, updates);\n collaboration._broadcastOperation({\n operation: \"update_block\",\n data: { block_id: blockId, updates },\n timestamp: Date.now(),\n });\n };\n\n editor.removeBlock = (blockId) => {\n originalRemoveBlock(blockId);\n collaboration._broadcastOperation({\n operation: \"delete_block\",\n data: { block_id: blockId },\n timestamp: Date.now(),\n });\n };\n\n editor.moveBlock = (blockId, newIndex, targetSectionId?, columnIndex?) => {\n originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);\n collaboration._broadcastOperation({\n operation: \"move_block\",\n data: {\n block_id: blockId,\n index: newIndex,\n section_id: targetSectionId,\n column_index: columnIndex,\n },\n timestamp: Date.now(),\n });\n };\n\n editor.updateSettings = (updates) => {\n originalUpdateSettings(updates);\n collaboration._broadcastOperation({\n operation: \"update_settings\",\n data: { updates },\n timestamp: Date.now(),\n });\n };\n\n editor.setContent = (content, markDirty?) => {\n originalSetContent(content, markDirty);\n collaboration._broadcastOperation({\n operation: \"set_content\",\n data: { content },\n timestamp: Date.now(),\n });\n };\n}\n","import type { AuthManager } from \"./auth\";\nimport type { WebSocketConfig } from \"./websocket-client\";\nimport { WebSocketClient } from \"./websocket-client\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseWebSocketOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UseWebSocketReturn {\n channel: Ref<PresenceChannel | null>;\n isConnected: Ref<boolean>;\n connect: (templateId: string, config: WebSocketConfig) => Promise<void>;\n disconnect: () => void;\n getSocketId: () => string | null;\n}\n\nexport function useWebSocket(options: UseWebSocketOptions): UseWebSocketReturn {\n const { authManager, onError } = options;\n\n const channel = ref<PresenceChannel | null>(\n null,\n ) as Ref<PresenceChannel | null>;\n const isConnected = ref(false);\n\n let wsClient: WebSocketClient | null = null;\n let channelName: string | null = null;\n\n async function connect(\n templateId: string,\n config: WebSocketConfig,\n ): Promise<void> {\n if (wsClient) {\n return;\n }\n\n wsClient = new WebSocketClient({\n authManager,\n config,\n onError,\n });\n\n await wsClient.connect();\n\n channelName = `presence-template.${templateId}`;\n const presenceChannel = wsClient.subscribePresence(channelName);\n\n presenceChannel.bind(\"pusher:subscription_succeeded\", () => {\n isConnected.value = true;\n channel.value = presenceChannel;\n });\n\n presenceChannel.bind(\"pusher:subscription_error\", (error: unknown) => {\n isConnected.value = false;\n channel.value = null;\n onError?.(\n error instanceof Error\n ? error\n : new Error(\"Failed to subscribe to template channel\"),\n );\n });\n }\n\n function disconnect(): void {\n if (channelName && wsClient) {\n wsClient.unsubscribe(channelName);\n }\n\n wsClient?.disconnect();\n wsClient = null;\n channelName = null;\n channel.value = null;\n isConnected.value = false;\n }\n\n function getSocketId(): string | null {\n return wsClient?.getSocketId() ?? null;\n }\n\n return {\n channel,\n isConnected,\n connect,\n disconnect,\n getSocketId,\n };\n}\n","import type { SavedModule } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport type { Block } from \"@templatical/types\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseSavedModulesOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UseSavedModulesReturn {\n modules: Ref<SavedModule[]>;\n isLoading: Ref<boolean>;\n loadModules: (search?: string) => Promise<void>;\n createModule: (name: string, content: Block[]) => Promise<SavedModule>;\n updateModule: (\n id: string,\n data: Partial<{ name: string; content: Block[] }>,\n ) => Promise<SavedModule>;\n deleteModule: (id: string) => Promise<void>;\n}\n\nexport function useSavedModules(\n options: UseSavedModulesOptions,\n): UseSavedModulesReturn {\n const api = new ApiClient(options.authManager);\n\n const modules = ref<SavedModule[]>([]);\n const isLoading = ref(false);\n\n async function loadModules(search?: string): Promise<void> {\n isLoading.value = true;\n try {\n modules.value = await api.listModules(search);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isLoading.value = false;\n }\n }\n\n async function createModule(\n name: string,\n content: Block[],\n ): Promise<SavedModule> {\n try {\n const module = await api.createModule({ name, content });\n modules.value = [module, ...modules.value];\n return module;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n async function updateModule(\n id: string,\n data: Partial<{ name: string; content: Block[] }>,\n ): Promise<SavedModule> {\n try {\n const updated = await api.updateModule(id, data);\n modules.value = modules.value.map((m) => (m.id === id ? updated : m));\n return updated;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n async function deleteModule(id: string): Promise<void> {\n try {\n await api.deleteModule(id);\n modules.value = modules.value.filter((m) => m.id !== id);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n }\n }\n\n return {\n modules,\n isLoading,\n loadModules,\n createModule,\n updateModule,\n deleteModule,\n };\n}\n","import type { Template, TemplateSnapshot } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { ref, type Ref } from \"vue\";\n\nexport interface UseSnapshotHistoryOptions {\n authManager: AuthManager;\n templateId: string;\n onRestore?: (template: Template) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseSnapshotHistoryReturn {\n snapshots: Ref<TemplateSnapshot[]>;\n isLoading: Ref<boolean>;\n isRestoring: Ref<boolean>;\n loadSnapshots: () => Promise<void>;\n restoreSnapshot: (snapshotId: string) => Promise<Template>;\n}\n\nexport function useSnapshotHistory(\n options: UseSnapshotHistoryOptions,\n): UseSnapshotHistoryReturn {\n const api = new ApiClient(options.authManager);\n\n const snapshots = ref<TemplateSnapshot[]>([]);\n const isLoading = ref(false);\n const isRestoring = ref(false);\n\n async function loadSnapshots(): Promise<void> {\n isLoading.value = true;\n try {\n snapshots.value = await api.getSnapshots(options.templateId);\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isLoading.value = false;\n }\n }\n\n async function restoreSnapshot(snapshotId: string): Promise<Template> {\n isRestoring.value = true;\n try {\n const template = await api.restoreSnapshot(\n options.templateId,\n snapshotId,\n );\n options.onRestore?.(template);\n return template;\n } catch (error) {\n options.onError?.(error as Error);\n throw error;\n } finally {\n isRestoring.value = false;\n }\n }\n\n return {\n snapshots,\n isLoading,\n isRestoring,\n loadSnapshots,\n restoreSnapshot,\n };\n}\n","import type {\n ExportResult,\n Template,\n TestEmailConfig,\n} from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { ApiClient } from \"./api\";\nimport type { ComputedRef, Ref } from \"vue\";\nimport { computed, ref, watch } from \"vue\";\n\nexport interface UseTestEmailOptions {\n authManager: AuthManager;\n getTemplateId: () => string | null;\n save: () => Promise<Template>;\n exportHtml: (templateId: string) => Promise<ExportResult>;\n onError?: (error: Error) => void;\n isAuthReady?: Ref<boolean>;\n onBeforeTestEmail?: (html: string) => string | Promise<string>;\n}\n\nexport interface UseTestEmailReturn {\n isEnabled: ComputedRef<boolean>;\n allowedEmails: ComputedRef<string[]>;\n isSending: Ref<boolean>;\n error: Ref<string | null>;\n sendTestEmail: (recipient: string) => Promise<void>;\n}\n\nexport function useTestEmail(options: UseTestEmailOptions): UseTestEmailReturn {\n const {\n authManager,\n getTemplateId,\n save,\n exportHtml,\n onError,\n isAuthReady,\n onBeforeTestEmail,\n } = options;\n const api = new ApiClient(authManager);\n\n const isSending = ref(false);\n const error = ref<string | null>(null);\n\n const testEmailConfig = ref<TestEmailConfig | null>(null);\n\n if (isAuthReady) {\n watch(\n isAuthReady,\n (ready) => {\n if (ready) {\n testEmailConfig.value = authManager.testEmailConfig;\n }\n },\n { immediate: true },\n );\n }\n\n const isEnabled = computed<boolean>(() => testEmailConfig.value !== null);\n\n const allowedEmails = computed<string[]>(\n () => testEmailConfig.value?.allowedEmails ?? [],\n );\n\n async function sendTestEmail(recipient: string): Promise<void> {\n if (!testEmailConfig.value) {\n throw new Error(\"Test email is not enabled for this project\");\n }\n\n const templateId = getTemplateId();\n if (!templateId) {\n throw new Error(\"Template must be saved before sending a test email\");\n }\n\n isSending.value = true;\n error.value = null;\n\n try {\n await save();\n\n let { html } = await exportHtml(templateId);\n\n if (onBeforeTestEmail) {\n html = await onBeforeTestEmail(html);\n }\n\n await api.sendTestEmail(templateId, {\n recipient,\n html,\n allowed_emails: testEmailConfig.value.allowedEmails,\n signature: testEmailConfig.value.signature,\n });\n } catch (err) {\n const wrappedError =\n err instanceof Error\n ? err\n : new Error(\"Failed to send test email\", { cause: err });\n error.value = wrappedError.message;\n onError?.(wrappedError);\n throw wrappedError;\n } finally {\n isSending.value = false;\n }\n }\n\n return {\n isEnabled,\n allowedEmails,\n isSending,\n error,\n sendTestEmail,\n };\n}\n","import type { CustomFont, ExportResult, FontsConfig } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\n\nexport interface UseExportOptions {\n authManager: AuthManager;\n getFontsConfig?: () => FontsConfig | undefined;\n canUseCustomFonts?: () => boolean;\n}\n\nexport interface UseExportReturn {\n exportHtml: (templateId: string) => Promise<ExportResult>;\n getMjmlSource: (templateId: string) => Promise<string>;\n}\n\nexport function useExport(options: UseExportOptions): UseExportReturn {\n const { authManager, getFontsConfig, canUseCustomFonts } = options;\n const api = new ApiClient(authManager);\n\n function getExportFontsPayload(): {\n customFonts: CustomFont[];\n defaultFallback: string;\n } {\n const fontsConfig = getFontsConfig?.();\n const customFontsAllowed = canUseCustomFonts?.() ?? true;\n\n return {\n customFonts:\n customFontsAllowed && fontsConfig?.customFonts\n ? fontsConfig.customFonts\n : [],\n defaultFallback: fontsConfig?.defaultFallback ?? \"Arial, sans-serif\",\n };\n }\n\n async function exportHtml(templateId: string): Promise<ExportResult> {\n const fontsPayload = getExportFontsPayload();\n const result = await api.exportTemplate(templateId, fontsPayload);\n\n return {\n html: result.html,\n mjml: result.mjml,\n };\n }\n\n async function getMjmlSource(templateId: string): Promise<string> {\n const fontsPayload = getExportFontsPayload();\n const result = await api.exportTemplate(templateId, fontsPayload);\n return result.mjml;\n }\n\n return {\n exportHtml,\n getMjmlSource,\n };\n}\n","import type { PlanConfig, PlanFeatures } from \"@templatical/types\";\nimport { ApiClient } from \"./api\";\nimport type { AuthManager } from \"./auth\";\nimport { computed, ref, type ComputedRef, type Ref } from \"vue\";\n\nexport interface UsePlanConfigOptions {\n authManager: AuthManager;\n onError?: (error: Error) => void;\n}\n\nexport interface UsePlanConfigReturn {\n config: Ref<PlanConfig | null>;\n isLoading: Ref<boolean>;\n hasFeature: (feature: keyof PlanFeatures) => boolean;\n features: ComputedRef<PlanFeatures | null>;\n fetchConfig: () => Promise<void>;\n}\n\nexport function usePlanConfig(\n options: UsePlanConfigOptions,\n): UsePlanConfigReturn {\n const { authManager, onError } = options;\n\n const config = ref<PlanConfig | null>(null);\n const isLoading = ref(false);\n\n const apiClient = new ApiClient(authManager);\n\n const features = computed(() => config.value?.features ?? null);\n\n function hasFeature(feature: keyof PlanFeatures): boolean {\n return config.value?.features[feature] ?? false;\n }\n\n async function fetchConfig(): Promise<void> {\n if (isLoading.value) {\n return;\n }\n\n isLoading.value = true;\n\n try {\n config.value = await apiClient.fetchConfig();\n } catch (error) {\n onError?.(\n error instanceof Error\n ? error\n : new Error(\"Failed to fetch config\", { cause: error }),\n );\n } finally {\n isLoading.value = false;\n }\n }\n\n return {\n config,\n isLoading,\n hasFeature,\n features,\n fetchConfig,\n };\n}\n","import type { HealthCheckResult } from \"@templatical/types\";\nimport type { AuthManager } from \"./auth\";\nimport { API_ROUTES } from \"./url-builder\";\n\ninterface HealthCheckOptions {\n authManager?: AuthManager;\n baseUrl?: string;\n}\n\nconst WS_HANDSHAKE_TIMEOUT = 5000;\n\nfunction resolveHealthUrl(options: HealthCheckOptions): string {\n if (options.authManager) {\n return options.authManager.resolveUrl(API_ROUTES.health);\n }\n\n const base = (options.baseUrl ?? \"https://templatical.com\").replace(\n /\\/$/,\n \"\",\n );\n return `${base}${API_ROUTES.health}`;\n}\n\nasync function checkApiAndAuth(\n url: string,\n authManager?: AuthManager,\n): Promise<{\n api: { ok: boolean; latency: number };\n auth: { ok: boolean; error?: string };\n wsConfig?: { host: string; port: number; app_key: string };\n}> {\n const start = performance.now();\n\n try {\n const response = authManager\n ? await authManager.authenticatedFetch(API_ROUTES.health, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n })\n : await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n });\n\n const latency = Math.round(performance.now() - start);\n\n if (response.status === 401) {\n return {\n api: { ok: true, latency },\n auth: { ok: false, error: \"HTTP 401\" },\n };\n }\n\n if (!response.ok) {\n return {\n api: { ok: false, latency },\n auth: {\n ok: !authManager,\n error: authManager ? `HTTP ${response.status}` : undefined,\n },\n };\n }\n\n const data = await response.json();\n\n return {\n api: { ok: data.status === \"ok\", latency },\n auth: { ok: true },\n wsConfig: data.websocket,\n };\n } catch (error) {\n const latency = Math.round(performance.now() - start);\n\n return {\n api: { ok: false, latency },\n auth: {\n ok: !authManager,\n error: authManager\n ? error instanceof Error\n ? error.message\n : \"Authentication check failed\"\n : undefined,\n },\n };\n }\n}\n\nasync function checkWebSocket(wsConfig?: {\n host: string;\n port: number;\n app_key: string;\n}): Promise<{ ok: boolean; error?: string }> {\n if (!wsConfig?.host || !wsConfig?.app_key) {\n return { ok: false, error: \"WebSocket configuration not available\" };\n }\n\n if (typeof WebSocket === \"undefined\") {\n return {\n ok: false,\n error: \"WebSocket not supported in this environment\",\n };\n }\n\n const protocol = wsConfig.port === 443 ? \"wss\" : \"ws\";\n const url = `${protocol}://${wsConfig.host}:${wsConfig.port}/app/${wsConfig.app_key}?protocol=7&client=js&version=8.4.0-rc2&flash=false`;\n\n return new Promise((resolve) => {\n let ws: WebSocket | null = null;\n\n const timeout = setTimeout(() => {\n ws?.close();\n resolve({ ok: false, error: \"WebSocket connection timed out\" });\n }, WS_HANDSHAKE_TIMEOUT);\n\n try {\n ws = new WebSocket(url);\n } catch (error) {\n // Some browsers throw synchronously from `new WebSocket(...)`\n // (e.g. SecurityError on mixed content, InvalidAccessError on\n // malformed URL). Without this catch the queued timeout would\n // later access `ws` in TDZ and the outer promise would hang.\n clearTimeout(timeout);\n resolve({\n ok: false,\n error:\n error instanceof Error\n ? error.message\n : \"WebSocket connection failed\",\n });\n return;\n }\n\n ws.onopen = () => {\n clearTimeout(timeout);\n ws?.close();\n resolve({ ok: true });\n };\n\n ws.onerror = () => {\n clearTimeout(timeout);\n resolve({ ok: false, error: \"WebSocket connection failed\" });\n };\n });\n}\n\nexport async function performHealthCheck(\n options: HealthCheckOptions = {},\n): Promise<HealthCheckResult> {\n const healthUrl = resolveHealthUrl(options);\n\n const result = await checkApiAndAuth(healthUrl, options.authManager);\n const wsResult = await checkWebSocket(result.wsConfig);\n\n return {\n api: result.api,\n websocket: wsResult,\n auth: result.auth,\n overall: result.api.ok && result.auth.ok,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { McpOperationPayload } from \"@templatical/types\";\nimport { handleOperation } from \"./mcp-operation-handler\";\nimport type { PresenceChannel } from \"pusher-js\";\nimport { watch, type Ref } from \"vue\";\n\nexport interface UseMcpListenerOptions {\n editor: UseEditorReturn;\n channel: Ref<PresenceChannel | null>;\n onOperation?: (payload: McpOperationPayload) => void;\n}\n\nexport function useMcpListener(options: UseMcpListenerOptions): void {\n const { editor, channel, onOperation } = options;\n\n watch(channel, (newChannel, oldChannel) => {\n if (oldChannel) {\n oldChannel.unbind(\"mcp-operation\");\n }\n\n if (newChannel) {\n newChannel.bind(\"mcp-operation\", (payload: McpOperationPayload) => {\n handleOperation(editor, payload);\n onOperation?.(payload);\n });\n }\n });\n}\n"],"mappings":"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","names":["SdkError","SdkError","SdkError","markDirty","content","SdkError","ref","computed","ref","ref","computed","ref","computed","onScopeDispose","ref","watch","ref","ref","ref","computed","ref","watch","computed","ref","watch"]}
@@ -33,6 +33,11 @@ interface UseEditorReturn {
33
33
  moveBlock: (blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number) => void;
34
34
  isBlockLocked: (blockId: string) => boolean;
35
35
  markDirty: () => void;
36
+ findBlockLocation: (blockId: string) => {
37
+ targetSectionId?: string;
38
+ columnIndex?: number;
39
+ index: number;
40
+ } | null;
36
41
  }
37
42
  declare function useEditor(options: UseEditorOptions): UseEditorReturn;
38
43
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { U as UseEditorReturn } from './editor-K644r-hl.js';
2
- export { E as EditorState, a as UseEditorOptions, u as useEditor } from './editor-K644r-hl.js';
1
+ import { U as UseEditorReturn } from './editor-DoKPR8pJ.js';
2
+ export { E as EditorState, a as UseEditorOptions, u as useEditor } from './editor-DoKPR8pJ.js';
3
3
  import { TemplateContent, Block, BlockDefaults, BlockType, CustomBlockDefinition, CustomBlock } from '@templatical/types';
4
4
  import { Ref, ComputedRef } from '@vue/reactivity';
5
5
 
@@ -23,10 +23,17 @@ interface UseHistoryReturn {
23
23
  declare function useHistory(options: UseHistoryOptions): UseHistoryReturn;
24
24
 
25
25
  interface UseBlockActionsOptions {
26
- addBlock: (block: Block, targetSectionId?: string, columnIndex?: number) => void;
26
+ addBlock: (block: Block, targetSectionId?: string, columnIndex?: number, index?: number) => void;
27
27
  removeBlock: (blockId: string) => void;
28
28
  updateBlock: (blockId: string, updates: Partial<Block>) => void;
29
29
  selectBlock: (blockId: string | null) => void;
30
+ /** Locate a block in the tree — used by `duplicateBlock` to insert the
31
+ * clone right after the source instead of appending to the end. */
32
+ findBlockLocation?: (blockId: string) => {
33
+ targetSectionId?: string;
34
+ columnIndex?: number;
35
+ index: number;
36
+ } | null;
30
37
  blockDefaults?: BlockDefaults;
31
38
  }
32
39
  interface UseBlockActionsReturn {
package/dist/index.js CHANGED
@@ -5,6 +5,11 @@ import {
5
5
  reactive,
6
6
  readonly
7
7
  } from "@vue/reactivity";
8
+ function getColumnCount(layout) {
9
+ if (layout === "1") return 1;
10
+ if (layout === "3") return 3;
11
+ return 2;
12
+ }
8
13
  function useEditor(options) {
9
14
  const state = reactive({
10
15
  content: options.content ?? createDefaultTemplateContent(
@@ -41,6 +46,16 @@ function useEditor(options) {
41
46
  }
42
47
  return null;
43
48
  }
49
+ function collectBlockIds(block, ids) {
50
+ ids.add(block.id);
51
+ if (block.type === "section") {
52
+ for (const column of block.children) {
53
+ for (const child of column) {
54
+ collectBlockIds(child, ids);
55
+ }
56
+ }
57
+ }
58
+ }
44
59
  function findBlockParent(blocks, id, parent = { blocks }) {
45
60
  for (let i = 0; i < blocks.length; i++) {
46
61
  const block = blocks[i];
@@ -61,6 +76,17 @@ function useEditor(options) {
61
76
  function isBlockLocked(blockId) {
62
77
  return options.lockedBlocks?.value.has(blockId) ?? false;
63
78
  }
79
+ function findBlockLocation(blockId) {
80
+ const parent = findBlockParent(state.content.blocks, blockId);
81
+ if (!parent) return null;
82
+ const index = parent.blocks.findIndex((b) => b.id === blockId);
83
+ if (index === -1) return null;
84
+ return {
85
+ targetSectionId: parent.sectionId,
86
+ columnIndex: parent.columnIndex,
87
+ index
88
+ };
89
+ }
64
90
  function setContent(newContent, markDirty2 = true) {
65
91
  state.content = newContent;
66
92
  if (markDirty2) {
@@ -109,6 +135,9 @@ function useEditor(options) {
109
135
  }
110
136
  const section = findBlockById(state.content.blocks, targetSectionId);
111
137
  if (section && section.type === "section") {
138
+ if (columnIndex < 0 || columnIndex >= getColumnCount(section.columns)) {
139
+ return;
140
+ }
112
141
  section.children[columnIndex] = section.children[columnIndex] || [];
113
142
  const targetArray = section.children[columnIndex];
114
143
  if (index !== void 0 && index < targetArray.length) {
@@ -134,9 +163,13 @@ function useEditor(options) {
134
163
  if (parent) {
135
164
  const index = parent.blocks.findIndex((b) => b.id === blockId);
136
165
  if (index !== -1) {
137
- parent.blocks.splice(index, 1);
138
- if (state.selectedBlockId === blockId) {
139
- state.selectedBlockId = null;
166
+ const [removed] = parent.blocks.splice(index, 1);
167
+ if (state.selectedBlockId) {
168
+ const removedIds = /* @__PURE__ */ new Set();
169
+ collectBlockIds(removed, removedIds);
170
+ if (removedIds.has(state.selectedBlockId)) {
171
+ state.selectedBlockId = null;
172
+ }
140
173
  }
141
174
  state.isDirty = true;
142
175
  }
@@ -157,6 +190,9 @@ function useEditor(options) {
157
190
  if (targetSectionId) {
158
191
  const section = findBlockById(state.content.blocks, targetSectionId);
159
192
  if (!section || section.type !== "section") return;
193
+ if (columnIndex < 0 || columnIndex >= getColumnCount(section.columns)) {
194
+ return;
195
+ }
160
196
  section.children[columnIndex] = section.children[columnIndex] || [];
161
197
  targetArray = section.children[columnIndex];
162
198
  } else {
@@ -185,7 +221,8 @@ function useEditor(options) {
185
221
  addBlock,
186
222
  removeBlock,
187
223
  moveBlock,
188
- markDirty
224
+ markDirty,
225
+ findBlockLocation
189
226
  };
190
227
  }
191
228
 
@@ -209,7 +246,16 @@ function useHistory(options) {
209
246
  const canUndo = computed2(() => undoStack.value.length > 0);
210
247
  const canRedo = computed2(() => redoStack.value.length > 0);
211
248
  function cloneContent() {
212
- return JSON.parse(JSON.stringify(content.value));
249
+ const seen = /* @__PURE__ */ new WeakSet();
250
+ return JSON.parse(
251
+ JSON.stringify(content.value, (_key, value) => {
252
+ if (typeof value === "object" && value !== null) {
253
+ if (seen.has(value)) return void 0;
254
+ seen.add(value);
255
+ }
256
+ return value;
257
+ })
258
+ );
213
259
  }
214
260
  function pushToUndoStack(snapshot) {
215
261
  undoStack.value.push(snapshot);
@@ -309,8 +355,21 @@ function useHistory(options) {
309
355
 
310
356
  // src/block-actions.ts
311
357
  import { createBlock, generateId } from "@templatical/types";
358
+ function regenerateNestedIds(block) {
359
+ if (block.type === "table") {
360
+ block.rows = block.rows.map((row) => ({
361
+ ...row,
362
+ id: generateId(),
363
+ cells: row.cells.map((cell) => ({ ...cell, id: generateId() }))
364
+ }));
365
+ } else if (block.type === "social") {
366
+ block.icons = block.icons.map((icon) => ({ ...icon, id: generateId() }));
367
+ } else if (block.type === "menu") {
368
+ block.items = block.items.map((item) => ({ ...item, id: generateId() }));
369
+ }
370
+ }
312
371
  function useBlockActions(options) {
313
- const { addBlock, removeBlock, updateBlock, selectBlock } = options;
372
+ const { addBlock, removeBlock, updateBlock, selectBlock, findBlockLocation } = options;
314
373
  function createAndAddBlock(type, targetSectionId, columnIndex) {
315
374
  const block = createBlock(type, options.blockDefaults);
316
375
  addBlock(block, targetSectionId, columnIndex);
@@ -320,16 +379,32 @@ function useBlockActions(options) {
320
379
  function duplicateBlock(block, targetSectionId, columnIndex) {
321
380
  const cloned = JSON.parse(JSON.stringify(block));
322
381
  cloned.id = generateId();
382
+ regenerateNestedIds(cloned);
323
383
  if (cloned.type === "section") {
324
384
  cloned.children = cloned.children.map(
325
385
  (column) => column.map((child) => {
326
386
  const clonedChild = JSON.parse(JSON.stringify(child));
327
387
  clonedChild.id = generateId();
388
+ regenerateNestedIds(clonedChild);
328
389
  return clonedChild;
329
390
  })
330
391
  );
331
392
  }
332
- addBlock(cloned, targetSectionId, columnIndex);
393
+ if (targetSectionId !== void 0 || columnIndex !== void 0) {
394
+ addBlock(cloned, targetSectionId, columnIndex);
395
+ } else {
396
+ const sourceLocation = findBlockLocation?.(block.id) ?? null;
397
+ if (sourceLocation) {
398
+ addBlock(
399
+ cloned,
400
+ sourceLocation.targetSectionId,
401
+ sourceLocation.columnIndex,
402
+ sourceLocation.index + 1
403
+ );
404
+ } else {
405
+ addBlock(cloned, targetSectionId, columnIndex);
406
+ }
407
+ }
333
408
  selectBlock(cloned.id);
334
409
  return cloned;
335
410
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/editor.ts","../src/history.ts","../src/block-actions.ts","../src/auto-save.ts","../src/condition-preview.ts","../src/data-source-fetch.ts","../src/history-interceptor.ts"],"sourcesContent":["import type {\n Block,\n TemplateContent,\n TemplateDefaults,\n TemplateSettings,\n UiTheme,\n ViewportSize,\n} from \"@templatical/types\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport {\n computed,\n reactive,\n readonly,\n type DeepReadonly,\n type Ref,\n} from \"@vue/reactivity\";\n\nexport interface EditorState {\n content: TemplateContent;\n selectedBlockId: string | null;\n viewport: ViewportSize;\n darkMode: boolean;\n previewMode: boolean;\n isDirty: boolean;\n uiTheme: UiTheme;\n}\n\nexport interface UseEditorOptions {\n content: TemplateContent;\n defaultFontFamily?: string;\n templateDefaults?: TemplateDefaults;\n lockedBlocks?: Ref<Map<string, unknown>>;\n}\n\nexport interface UseEditorReturn {\n state: DeepReadonly<EditorState>;\n content: Ref<TemplateContent>;\n selectedBlock: Ref<Block | null>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n selectBlock: (blockId: string | null) => void;\n setViewport: (viewport: ViewportSize) => void;\n setDarkMode: (darkMode: boolean) => void;\n setPreviewMode: (previewMode: boolean) => void;\n setUiTheme: (theme: UiTheme) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n updateSettings: (updates: Partial<TemplateSettings>) => void;\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n moveBlock: (\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n isBlockLocked: (blockId: string) => boolean;\n markDirty: () => void;\n}\n\nexport function useEditor(options: UseEditorOptions): UseEditorReturn {\n const state = reactive<EditorState>({\n content:\n options.content ??\n createDefaultTemplateContent(\n options.defaultFontFamily,\n options.templateDefaults,\n ),\n selectedBlockId: null,\n viewport: \"desktop\",\n darkMode: false,\n previewMode: false,\n isDirty: false,\n uiTheme: \"auto\",\n });\n\n const content = computed({\n get: () => state.content,\n set: (value: TemplateContent) => {\n state.content = value;\n state.isDirty = true;\n },\n });\n\n const selectedBlock = computed(() => {\n if (!state.selectedBlockId) return null;\n return findBlockById(state.content.blocks, state.selectedBlockId);\n });\n\n function findBlockById(blocks: Block[], id: string): Block | null {\n for (const block of blocks) {\n if (block.id === id) return block;\n if (block.type === \"section\") {\n for (const column of block.children) {\n const found = findBlockById(column, id);\n if (found) return found;\n }\n }\n }\n return null;\n }\n\n function findBlockParent(\n blocks: Block[],\n id: string,\n parent: {\n blocks: Block[];\n sectionId?: string;\n columnIndex?: number;\n } = { blocks },\n ): { blocks: Block[]; sectionId?: string; columnIndex?: number } | null {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block.id === id) return parent;\n if (block.type === \"section\") {\n for (let colIdx = 0; colIdx < block.children.length; colIdx++) {\n const result = findBlockParent(block.children[colIdx], id, {\n blocks: block.children[colIdx],\n sectionId: block.id,\n columnIndex: colIdx,\n });\n if (result) return result;\n }\n }\n }\n return null;\n }\n\n function isBlockLocked(blockId: string): boolean {\n return options.lockedBlocks?.value.has(blockId) ?? false;\n }\n\n // TODO(collab): the lock checks in addBlock/moveBlock/removeBlock/updateBlock\n // are shallow — they only consider the directly-targeted block id. A section\n // can still be removed, moved, or have its `children` array rewritten while a\n // peer is editing one of its descendants, which silently disrupts that peer's\n // edit. Add a `hasLockedDescendant(blockId)` helper and gate section-level\n // operations on it (and on the parent of each affected child) so cascades\n // through the tree are also blocked.\n\n function setContent(newContent: TemplateContent, markDirty = true): void {\n state.content = newContent;\n if (markDirty) {\n state.isDirty = true;\n }\n }\n\n function selectBlock(blockId: string | null): void {\n if (blockId && isBlockLocked(blockId)) {\n return;\n }\n state.selectedBlockId = blockId;\n }\n\n function setViewport(viewport: ViewportSize): void {\n state.viewport = viewport;\n }\n\n function setDarkMode(darkMode: boolean): void {\n state.darkMode = darkMode;\n }\n\n function setUiTheme(theme: UiTheme): void {\n state.uiTheme = theme;\n }\n\n function setPreviewMode(previewMode: boolean): void {\n state.previewMode = previewMode;\n if (previewMode) {\n state.selectedBlockId = null;\n }\n }\n\n function updateBlock(blockId: string, updates: Partial<Block>): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const block = findBlockById(state.content.blocks, blockId);\n if (block) {\n Object.assign(block, updates);\n state.isDirty = true;\n }\n }\n\n function updateSettings(updates: Partial<TemplateSettings>): void {\n state.content.settings = { ...state.content.settings, ...updates };\n state.isDirty = true;\n }\n\n function addBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex = 0,\n index?: number,\n ): void {\n if (targetSectionId) {\n if (isBlockLocked(targetSectionId)) {\n return;\n }\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n const targetArray = section.children[columnIndex];\n if (index !== undefined && index < targetArray.length) {\n targetArray.splice(index, 0, block);\n } else {\n targetArray.push(block);\n }\n }\n } else {\n if (index !== undefined && index < state.content.blocks.length) {\n state.content.blocks.splice(index, 0, block);\n } else {\n state.content.blocks.push(block);\n }\n }\n state.isDirty = true;\n }\n\n function removeBlock(blockId: string): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const parent = findBlockParent(state.content.blocks, blockId);\n if (parent) {\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index !== -1) {\n parent.blocks.splice(index, 1);\n if (state.selectedBlockId === blockId) {\n state.selectedBlockId = null;\n }\n state.isDirty = true;\n }\n }\n }\n\n function moveBlock(\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex = 0,\n ): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n if (targetSectionId && isBlockLocked(targetSectionId)) {\n return;\n }\n\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return;\n\n const oldIndex = parent.blocks.findIndex((b) => b.id === blockId);\n if (oldIndex === -1) return;\n\n // Resolve target before mutating the source — otherwise an invalid\n // targetSectionId leaves the block spliced-out and unrecoverable.\n let targetArray: Block[];\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (!section || section.type !== \"section\") return;\n section.children[columnIndex] = section.children[columnIndex] || [];\n targetArray = section.children[columnIndex];\n } else {\n targetArray = state.content.blocks;\n }\n\n const [block] = parent.blocks.splice(oldIndex, 1);\n targetArray.splice(newIndex, 0, block);\n\n state.isDirty = true;\n }\n\n function markDirty(): void {\n state.isDirty = true;\n }\n\n return {\n state: readonly(state),\n content,\n selectedBlock,\n isBlockLocked,\n setContent,\n selectBlock,\n setViewport,\n setDarkMode,\n setUiTheme,\n setPreviewMode,\n updateBlock,\n updateSettings,\n addBlock,\n removeBlock,\n moveBlock,\n markDirty,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { computed, ref, type ComputedRef, type Ref } from \"@vue/reactivity\";\n\nexport interface UseHistoryOptions {\n content: Ref<TemplateContent>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n isRemoteOperation?: () => boolean;\n maxSize?: number;\n}\n\nexport interface UseHistoryReturn {\n canUndo: ComputedRef<boolean>;\n canRedo: ComputedRef<boolean>;\n isNavigating: Ref<boolean>;\n undo: () => void;\n redo: () => void;\n record: () => void;\n recordDebounced: (blockId: string) => void;\n clear: () => void;\n destroy: () => void;\n}\n\ninterface DebouncedSnapshot {\n blockId: string;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\nconst MAX_STACK_SIZE = 50;\nconst DEBOUNCE_MS = 300;\nconst NAVIGATE_IDLE_MS = 1500;\n\nexport function useHistory(options: UseHistoryOptions): UseHistoryReturn {\n const {\n content,\n setContent,\n isRemoteOperation,\n maxSize = MAX_STACK_SIZE,\n } = options;\n\n const undoStack = ref<TemplateContent[]>([]);\n const redoStack = ref<TemplateContent[]>([]);\n const isNavigating = ref(false);\n let navigatingTimeoutId: ReturnType<typeof setTimeout> | null = null;\n let pendingDebounce: DebouncedSnapshot | null = null;\n\n const canUndo = computed(() => undoStack.value.length > 0);\n const canRedo = computed(() => redoStack.value.length > 0);\n\n function cloneContent(): TemplateContent {\n return JSON.parse(JSON.stringify(content.value)) as TemplateContent;\n }\n\n function pushToUndoStack(snapshot: TemplateContent): void {\n undoStack.value.push(snapshot);\n if (undoStack.value.length > maxSize) {\n undoStack.value.splice(0, undoStack.value.length - maxSize);\n }\n }\n\n function flushPendingDebounce(): void {\n if (pendingDebounce) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce = null;\n }\n }\n\n function record(): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n flushPendingDebounce();\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n }\n\n function recordDebounced(blockId: string): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n if (pendingDebounce && pendingDebounce.blockId === blockId) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce.timeoutId = setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS);\n return;\n }\n\n flushPendingDebounce();\n\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n\n pendingDebounce = {\n blockId,\n timeoutId: setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS),\n };\n }\n\n function setNavigating(): void {\n isNavigating.value = true;\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n }\n navigatingTimeoutId = setTimeout(() => {\n isNavigating.value = false;\n navigatingTimeoutId = null;\n }, NAVIGATE_IDLE_MS);\n }\n\n function undo(): void {\n if (undoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = undoStack.value.pop()!;\n redoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function redo(): void {\n if (redoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = redoStack.value.pop()!;\n undoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function clear(): void {\n undoStack.value = [];\n redoStack.value = [];\n flushPendingDebounce();\n }\n\n function destroy(): void {\n clear();\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n navigatingTimeoutId = null;\n }\n }\n\n return {\n canUndo,\n canRedo,\n isNavigating,\n undo,\n redo,\n record,\n recordDebounced,\n clear,\n destroy,\n };\n}\n","import type { Block, BlockDefaults, BlockType } from \"@templatical/types\";\nimport { createBlock, generateId } from \"@templatical/types\";\n\nexport interface UseBlockActionsOptions {\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n selectBlock: (blockId: string | null) => void;\n blockDefaults?: BlockDefaults;\n}\n\nexport interface UseBlockActionsReturn {\n createAndAddBlock: (\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n duplicateBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n deleteBlock: (blockId: string) => void;\n updateBlockProperty: <K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ) => void;\n}\n\nexport function useBlockActions(\n options: UseBlockActionsOptions,\n): UseBlockActionsReturn {\n const { addBlock, removeBlock, updateBlock, selectBlock } = options;\n\n function createAndAddBlock(\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const block = createBlock(type, options.blockDefaults);\n addBlock(block, targetSectionId, columnIndex);\n selectBlock(block.id);\n return block;\n }\n\n function duplicateBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const cloned = JSON.parse(JSON.stringify(block)) as Block;\n cloned.id = generateId();\n\n if (cloned.type === \"section\") {\n cloned.children = cloned.children.map((column) =>\n column.map((child) => {\n const clonedChild = JSON.parse(JSON.stringify(child)) as Block;\n clonedChild.id = generateId();\n return clonedChild;\n }),\n );\n }\n\n addBlock(cloned, targetSectionId, columnIndex);\n selectBlock(cloned.id);\n return cloned;\n }\n\n function deleteBlock(blockId: string): void {\n removeBlock(blockId);\n }\n\n function updateBlockProperty<K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ): void {\n updateBlock(blockId, { [key]: value } as Partial<Block>);\n }\n\n return {\n createAndAddBlock,\n duplicateBlock,\n deleteBlock,\n updateBlockProperty,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { watch, type Ref } from \"@vue/reactivity\";\n\nexport interface UseAutoSaveOptions {\n content: Ref<TemplateContent>;\n isDirty: () => boolean;\n onChange: (content: TemplateContent) => void;\n debounce?: number;\n enabled?: boolean | (() => boolean);\n}\n\nexport interface UseAutoSaveReturn {\n flush: () => void;\n cancel: () => void;\n pause: () => void;\n resume: () => void;\n destroy: () => void;\n}\n\nexport function useAutoSave(options: UseAutoSaveOptions): UseAutoSaveReturn {\n const {\n content,\n isDirty,\n onChange,\n debounce = 1000,\n enabled = true,\n } = options;\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let paused = false;\n\n function isEnabled(): boolean {\n return typeof enabled === \"function\" ? enabled() : enabled;\n }\n\n function pause(): void {\n paused = true;\n cancel();\n }\n\n function resume(): void {\n paused = false;\n }\n\n function cancel(): void {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function flush(): void {\n cancel();\n if (isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }\n\n function scheduleOnChange(): void {\n if (!isEnabled() || paused) return;\n\n cancel();\n timeoutId = setTimeout(() => {\n timeoutId = null;\n if (isEnabled() && !paused && isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }, debounce);\n }\n\n const stopWatch = watch(\n content,\n () => {\n if (isEnabled() && !paused && isDirty()) {\n scheduleOnChange();\n }\n },\n { deep: true },\n );\n\n function destroy(): void {\n stopWatch();\n cancel();\n }\n\n return {\n flush,\n cancel,\n pause,\n resume,\n destroy,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport { computed, reactive, type ComputedRef } from \"@vue/reactivity\";\n\nexport interface UseConditionPreviewReturn {\n isHidden: (blockId: string) => boolean;\n toggleBlock: (blockId: string) => void;\n reset: () => void;\n hasHiddenBlocks: ComputedRef<boolean>;\n}\n\nexport function useConditionPreview(\n editor: UseEditorReturn,\n): UseConditionPreviewReturn {\n const hiddenBlockIds = reactive(new Set<string>());\n\n const hasHiddenBlocks = computed(() => hiddenBlockIds.size > 0);\n\n function isHidden(blockId: string): boolean {\n return hiddenBlockIds.has(blockId);\n }\n\n function toggleBlock(blockId: string): void {\n if (hiddenBlockIds.has(blockId)) {\n hiddenBlockIds.delete(blockId);\n } else {\n hiddenBlockIds.add(blockId);\n\n if (editor.state.selectedBlockId === blockId) {\n editor.selectBlock(null);\n }\n }\n }\n\n function reset(): void {\n hiddenBlockIds.clear();\n }\n\n return {\n isHidden,\n toggleBlock,\n reset,\n hasHiddenBlocks,\n };\n}\n","import type { CustomBlock, CustomBlockDefinition } from \"@templatical/types\";\nimport type { ComputedRef, Ref } from \"@vue/reactivity\";\nimport { computed, ref } from \"@vue/reactivity\";\n\nexport function useDataSourceFetch(options: {\n definition: ComputedRef<CustomBlockDefinition | undefined>;\n block: ComputedRef<CustomBlock>;\n onUpdate: (fieldValues: Record<string, unknown>, fetched: boolean) => void;\n}): {\n isFetching: Ref<boolean>;\n fetchError: Ref<boolean>;\n fetch: () => Promise<void>;\n hasDataSource: ComputedRef<boolean>;\n needsFetch: ComputedRef<boolean>;\n} {\n const isFetching = ref(false);\n const fetchError = ref(false);\n\n const hasDataSource = computed(() => !!options.definition.value?.dataSource);\n\n const needsFetch = computed(\n () => hasDataSource.value && !options.block.value.dataSourceFetched,\n );\n\n async function fetch(): Promise<void> {\n const def = options.definition.value;\n if (!def?.dataSource) {\n return;\n }\n\n isFetching.value = true;\n fetchError.value = false;\n\n try {\n const result = await def.dataSource.onFetch({\n fieldValues: { ...options.block.value.fieldValues },\n blockId: options.block.value.id,\n });\n\n if (result == null) {\n return;\n }\n\n const merged = { ...options.block.value.fieldValues };\n for (const key of Object.keys(merged)) {\n if (key in result) {\n merged[key] = result[key];\n }\n }\n\n options.onUpdate(merged, true);\n } catch (error) {\n console.warn(\"[Templatical] Data source fetch error:\", error);\n fetchError.value = true;\n } finally {\n isFetching.value = false;\n }\n }\n\n return {\n isFetching,\n fetchError,\n fetch,\n hasDataSource,\n needsFetch,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { UseHistoryReturn } from \"./history\";\n\n/**\n * Wraps editor mutation methods to record history snapshots before each\n * operation. Mutates the editor object in place.\n *\n * Must be applied **after** any collaboration broadcast wrapping so the\n * call chain is: history.record() → broadcast → original mutation.\n */\nexport function useHistoryInterceptor(\n editor: UseEditorReturn,\n history: UseHistoryReturn,\n): void {\n const originalAddBlock = editor.addBlock;\n const originalRemoveBlock = editor.removeBlock;\n const originalMoveBlock = editor.moveBlock;\n const originalUpdateBlock = editor.updateBlock;\n const originalUpdateSettings = editor.updateSettings;\n\n // Skip recording when the underlying op is a no-op (e.g., a peer-locked\n // block or section), otherwise the undo stack fills with snapshots that\n // are identical to current state and undo silently does nothing.\n editor.addBlock = (block, targetSectionId?, columnIndex?, index?) => {\n if (targetSectionId && editor.isBlockLocked(targetSectionId)) {\n return;\n }\n history.record();\n originalAddBlock(block, targetSectionId, columnIndex, index);\n };\n\n editor.removeBlock = (blockId) => {\n if (editor.isBlockLocked(blockId)) {\n return;\n }\n history.record();\n originalRemoveBlock(blockId);\n };\n\n editor.moveBlock = (blockId, newIndex, targetSectionId?, columnIndex?) => {\n if (editor.isBlockLocked(blockId)) {\n return;\n }\n if (targetSectionId && editor.isBlockLocked(targetSectionId)) {\n return;\n }\n history.record();\n originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);\n };\n\n editor.updateBlock = (blockId, updates) => {\n if (editor.isBlockLocked(blockId)) {\n return;\n }\n history.recordDebounced(blockId);\n originalUpdateBlock(blockId, updates);\n };\n\n editor.updateSettings = (updates) => {\n history.record();\n originalUpdateSettings(updates);\n };\n}\n"],"mappings":";AAQA,SAAS,oCAAoC;AAC7C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAgDA,SAAS,UAAU,SAA4C;AACpE,QAAM,QAAQ,SAAsB;AAAA,IAClC,SACE,QAAQ,WACR;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACF,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,IACb,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAED,QAAM,UAAU,SAAS;AAAA,IACvB,KAAK,MAAM,MAAM;AAAA,IACjB,KAAK,CAAC,UAA2B;AAC/B,YAAM,UAAU;AAChB,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,gBAAgB,SAAS,MAAM;AACnC,QAAI,CAAC,MAAM,gBAAiB,QAAO;AACnC,WAAO,cAAc,MAAM,QAAQ,QAAQ,MAAM,eAAe;AAAA,EAClE,CAAC;AAED,WAAS,cAAc,QAAiB,IAA0B;AAChE,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,OAAO,GAAI,QAAO;AAC5B,UAAI,MAAM,SAAS,WAAW;AAC5B,mBAAW,UAAU,MAAM,UAAU;AACnC,gBAAM,QAAQ,cAAc,QAAQ,EAAE;AACtC,cAAI,MAAO,QAAO;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,gBACP,QACA,IACA,SAII,EAAE,OAAO,GACyD;AACtE,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,QAAQ,OAAO,CAAC;AACtB,UAAI,MAAM,OAAO,GAAI,QAAO;AAC5B,UAAI,MAAM,SAAS,WAAW;AAC5B,iBAAS,SAAS,GAAG,SAAS,MAAM,SAAS,QAAQ,UAAU;AAC7D,gBAAM,SAAS,gBAAgB,MAAM,SAAS,MAAM,GAAG,IAAI;AAAA,YACzD,QAAQ,MAAM,SAAS,MAAM;AAAA,YAC7B,WAAW,MAAM;AAAA,YACjB,aAAa;AAAA,UACf,CAAC;AACD,cAAI,OAAQ,QAAO;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,cAAc,SAA0B;AAC/C,WAAO,QAAQ,cAAc,MAAM,IAAI,OAAO,KAAK;AAAA,EACrD;AAUA,WAAS,WAAW,YAA6BA,aAAY,MAAY;AACvE,UAAM,UAAU;AAChB,QAAIA,YAAW;AACb,YAAM,UAAU;AAAA,IAClB;AAAA,EACF;AAEA,WAAS,YAAY,SAA8B;AACjD,QAAI,WAAW,cAAc,OAAO,GAAG;AACrC;AAAA,IACF;AACA,UAAM,kBAAkB;AAAA,EAC1B;AAEA,WAAS,YAAY,UAA8B;AACjD,UAAM,WAAW;AAAA,EACnB;AAEA,WAAS,YAAY,UAAyB;AAC5C,UAAM,WAAW;AAAA,EACnB;AAEA,WAAS,WAAW,OAAsB;AACxC,UAAM,UAAU;AAAA,EAClB;AAEA,WAAS,eAAe,aAA4B;AAClD,UAAM,cAAc;AACpB,QAAI,aAAa;AACf,YAAM,kBAAkB;AAAA,IAC1B;AAAA,EACF;AAEA,WAAS,YAAY,SAAiB,SAA+B;AACnE,QAAI,cAAc,OAAO,GAAG;AAC1B;AAAA,IACF;AACA,UAAM,QAAQ,cAAc,MAAM,QAAQ,QAAQ,OAAO;AACzD,QAAI,OAAO;AACT,aAAO,OAAO,OAAO,OAAO;AAC5B,YAAM,UAAU;AAAA,IAClB;AAAA,EACF;AAEA,WAAS,eAAe,SAA0C;AAChE,UAAM,QAAQ,WAAW,EAAE,GAAG,MAAM,QAAQ,UAAU,GAAG,QAAQ;AACjE,UAAM,UAAU;AAAA,EAClB;AAEA,WAAS,SACP,OACA,iBACA,cAAc,GACd,OACM;AACN,QAAI,iBAAiB;AACnB,UAAI,cAAc,eAAe,GAAG;AAClC;AAAA,MACF;AACA,YAAM,UAAU,cAAc,MAAM,QAAQ,QAAQ,eAAe;AACnE,UAAI,WAAW,QAAQ,SAAS,WAAW;AACzC,gBAAQ,SAAS,WAAW,IAAI,QAAQ,SAAS,WAAW,KAAK,CAAC;AAClE,cAAM,cAAc,QAAQ,SAAS,WAAW;AAChD,YAAI,UAAU,UAAa,QAAQ,YAAY,QAAQ;AACrD,sBAAY,OAAO,OAAO,GAAG,KAAK;AAAA,QACpC,OAAO;AACL,sBAAY,KAAK,KAAK;AAAA,QACxB;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,UAAU,UAAa,QAAQ,MAAM,QAAQ,OAAO,QAAQ;AAC9D,cAAM,QAAQ,OAAO,OAAO,OAAO,GAAG,KAAK;AAAA,MAC7C,OAAO;AACL,cAAM,QAAQ,OAAO,KAAK,KAAK;AAAA,MACjC;AAAA,IACF;AACA,UAAM,UAAU;AAAA,EAClB;AAEA,WAAS,YAAY,SAAuB;AAC1C,QAAI,cAAc,OAAO,GAAG;AAC1B;AAAA,IACF;AACA,UAAM,SAAS,gBAAgB,MAAM,QAAQ,QAAQ,OAAO;AAC5D,QAAI,QAAQ;AACV,YAAM,QAAQ,OAAO,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AAC7D,UAAI,UAAU,IAAI;AAChB,eAAO,OAAO,OAAO,OAAO,CAAC;AAC7B,YAAI,MAAM,oBAAoB,SAAS;AACrC,gBAAM,kBAAkB;AAAA,QAC1B;AACA,cAAM,UAAU;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,WAAS,UACP,SACA,UACA,iBACA,cAAc,GACR;AACN,QAAI,cAAc,OAAO,GAAG;AAC1B;AAAA,IACF;AACA,QAAI,mBAAmB,cAAc,eAAe,GAAG;AACrD;AAAA,IACF;AAEA,UAAM,SAAS,gBAAgB,MAAM,QAAQ,QAAQ,OAAO;AAC5D,QAAI,CAAC,OAAQ;AAEb,UAAM,WAAW,OAAO,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AAChE,QAAI,aAAa,GAAI;AAIrB,QAAI;AACJ,QAAI,iBAAiB;AACnB,YAAM,UAAU,cAAc,MAAM,QAAQ,QAAQ,eAAe;AACnE,UAAI,CAAC,WAAW,QAAQ,SAAS,UAAW;AAC5C,cAAQ,SAAS,WAAW,IAAI,QAAQ,SAAS,WAAW,KAAK,CAAC;AAClE,oBAAc,QAAQ,SAAS,WAAW;AAAA,IAC5C,OAAO;AACL,oBAAc,MAAM,QAAQ;AAAA,IAC9B;AAEA,UAAM,CAAC,KAAK,IAAI,OAAO,OAAO,OAAO,UAAU,CAAC;AAChD,gBAAY,OAAO,UAAU,GAAG,KAAK;AAErC,UAAM,UAAU;AAAA,EAClB;AAEA,WAAS,YAAkB;AACzB,UAAM,UAAU;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,OAAO,SAAS,KAAK;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzSA,SAAS,YAAAC,WAAU,WAAuC;AA0B1D,IAAM,iBAAiB;AACvB,IAAM,cAAc;AACpB,IAAM,mBAAmB;AAElB,SAAS,WAAW,SAA8C;AACvE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ,IAAI;AAEJ,QAAM,YAAY,IAAuB,CAAC,CAAC;AAC3C,QAAM,YAAY,IAAuB,CAAC,CAAC;AAC3C,QAAM,eAAe,IAAI,KAAK;AAC9B,MAAI,sBAA4D;AAChE,MAAI,kBAA4C;AAEhD,QAAM,UAAUA,UAAS,MAAM,UAAU,MAAM,SAAS,CAAC;AACzD,QAAM,UAAUA,UAAS,MAAM,UAAU,MAAM,SAAS,CAAC;AAEzD,WAAS,eAAgC;AACvC,WAAO,KAAK,MAAM,KAAK,UAAU,QAAQ,KAAK,CAAC;AAAA,EACjD;AAEA,WAAS,gBAAgB,UAAiC;AACxD,cAAU,MAAM,KAAK,QAAQ;AAC7B,QAAI,UAAU,MAAM,SAAS,SAAS;AACpC,gBAAU,MAAM,OAAO,GAAG,UAAU,MAAM,SAAS,OAAO;AAAA,IAC5D;AAAA,EACF;AAEA,WAAS,uBAA6B;AACpC,QAAI,iBAAiB;AACnB,mBAAa,gBAAgB,SAAS;AACtC,wBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,WAAS,SAAe;AACtB,QAAI,oBAAoB,GAAG;AACzB;AAAA,IACF;AAEA,yBAAqB;AACrB,oBAAgB,aAAa,CAAC;AAC9B,cAAU,QAAQ,CAAC;AAAA,EACrB;AAEA,WAAS,gBAAgB,SAAuB;AAC9C,QAAI,oBAAoB,GAAG;AACzB;AAAA,IACF;AAEA,QAAI,mBAAmB,gBAAgB,YAAY,SAAS;AAC1D,mBAAa,gBAAgB,SAAS;AACtC,sBAAgB,YAAY,WAAW,MAAM;AAC3C,0BAAkB;AAAA,MACpB,GAAG,WAAW;AACd;AAAA,IACF;AAEA,yBAAqB;AAErB,oBAAgB,aAAa,CAAC;AAC9B,cAAU,QAAQ,CAAC;AAEnB,sBAAkB;AAAA,MAChB;AAAA,MACA,WAAW,WAAW,MAAM;AAC1B,0BAAkB;AAAA,MACpB,GAAG,WAAW;AAAA,IAChB;AAAA,EACF;AAEA,WAAS,gBAAsB;AAC7B,iBAAa,QAAQ;AACrB,QAAI,qBAAqB;AACvB,mBAAa,mBAAmB;AAAA,IAClC;AACA,0BAAsB,WAAW,MAAM;AACrC,mBAAa,QAAQ;AACrB,4BAAsB;AAAA,IACxB,GAAG,gBAAgB;AAAA,EACrB;AAEA,WAAS,OAAa;AACpB,QAAI,UAAU,MAAM,WAAW,GAAG;AAChC;AAAA,IACF;AAEA,yBAAqB;AAErB,UAAM,WAAW,UAAU,MAAM,IAAI;AACrC,cAAU,MAAM,KAAK,aAAa,CAAC;AACnC,eAAW,UAAU,IAAI;AACzB,kBAAc;AAAA,EAChB;AAEA,WAAS,OAAa;AACpB,QAAI,UAAU,MAAM,WAAW,GAAG;AAChC;AAAA,IACF;AAEA,yBAAqB;AAErB,UAAM,WAAW,UAAU,MAAM,IAAI;AACrC,cAAU,MAAM,KAAK,aAAa,CAAC;AACnC,eAAW,UAAU,IAAI;AACzB,kBAAc;AAAA,EAChB;AAEA,WAAS,QAAc;AACrB,cAAU,QAAQ,CAAC;AACnB,cAAU,QAAQ,CAAC;AACnB,yBAAqB;AAAA,EACvB;AAEA,WAAS,UAAgB;AACvB,UAAM;AACN,QAAI,qBAAqB;AACvB,mBAAa,mBAAmB;AAChC,4BAAsB;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACnKA,SAAS,aAAa,kBAAkB;AAiCjC,SAAS,gBACd,SACuB;AACvB,QAAM,EAAE,UAAU,aAAa,aAAa,YAAY,IAAI;AAE5D,WAAS,kBACP,MACA,iBACA,aACO;AACP,UAAM,QAAQ,YAAY,MAAM,QAAQ,aAAa;AACrD,aAAS,OAAO,iBAAiB,WAAW;AAC5C,gBAAY,MAAM,EAAE;AACpB,WAAO;AAAA,EACT;AAEA,WAAS,eACP,OACA,iBACA,aACO;AACP,UAAM,SAAS,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAC/C,WAAO,KAAK,WAAW;AAEvB,QAAI,OAAO,SAAS,WAAW;AAC7B,aAAO,WAAW,OAAO,SAAS;AAAA,QAAI,CAAC,WACrC,OAAO,IAAI,CAAC,UAAU;AACpB,gBAAM,cAAc,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AACpD,sBAAY,KAAK,WAAW;AAC5B,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAEA,aAAS,QAAQ,iBAAiB,WAAW;AAC7C,gBAAY,OAAO,EAAE;AACrB,WAAO;AAAA,EACT;AAEA,WAAS,YAAY,SAAuB;AAC1C,gBAAY,OAAO;AAAA,EACrB;AAEA,WAAS,oBACP,SACA,KACA,OACM;AACN,gBAAY,SAAS,EAAE,CAAC,GAAG,GAAG,MAAM,CAAmB;AAAA,EACzD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC1FA,SAAS,aAAuB;AAkBzB,SAAS,YAAY,SAAgD;AAC1E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,EACZ,IAAI;AAEJ,MAAI,YAAkD;AACtD,MAAI,SAAS;AAEb,WAAS,YAAqB;AAC5B,WAAO,OAAO,YAAY,aAAa,QAAQ,IAAI;AAAA,EACrD;AAEA,WAAS,QAAc;AACrB,aAAS;AACT,WAAO;AAAA,EACT;AAEA,WAAS,SAAe;AACtB,aAAS;AAAA,EACX;AAEA,WAAS,SAAe;AACtB,QAAI,WAAW;AACb,mBAAa,SAAS;AACtB,kBAAY;AAAA,IACd;AAAA,EACF;AAEA,WAAS,QAAc;AACrB,WAAO;AACP,QAAI,QAAQ,GAAG;AACb,eAAS,KAAK,MAAM,KAAK,UAAU,QAAQ,KAAK,CAAC,CAAC;AAAA,IACpD;AAAA,EACF;AAEA,WAAS,mBAAyB;AAChC,QAAI,CAAC,UAAU,KAAK,OAAQ;AAE5B,WAAO;AACP,gBAAY,WAAW,MAAM;AAC3B,kBAAY;AACZ,UAAI,UAAU,KAAK,CAAC,UAAU,QAAQ,GAAG;AACvC,iBAAS,KAAK,MAAM,KAAK,UAAU,QAAQ,KAAK,CAAC,CAAC;AAAA,MACpD;AAAA,IACF,GAAG,QAAQ;AAAA,EACb;AAEA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,MAAM;AACJ,UAAI,UAAU,KAAK,CAAC,UAAU,QAAQ,GAAG;AACvC,yBAAiB;AAAA,MACnB;AAAA,IACF;AAAA,IACA,EAAE,MAAM,KAAK;AAAA,EACf;AAEA,WAAS,UAAgB;AACvB,cAAU;AACV,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC3FA,SAAS,YAAAC,WAAU,YAAAC,iBAAkC;AAS9C,SAAS,oBACd,QAC2B;AAC3B,QAAM,iBAAiBA,UAAS,oBAAI,IAAY,CAAC;AAEjD,QAAM,kBAAkBD,UAAS,MAAM,eAAe,OAAO,CAAC;AAE9D,WAAS,SAAS,SAA0B;AAC1C,WAAO,eAAe,IAAI,OAAO;AAAA,EACnC;AAEA,WAAS,YAAY,SAAuB;AAC1C,QAAI,eAAe,IAAI,OAAO,GAAG;AAC/B,qBAAe,OAAO,OAAO;AAAA,IAC/B,OAAO;AACL,qBAAe,IAAI,OAAO;AAE1B,UAAI,OAAO,MAAM,oBAAoB,SAAS;AAC5C,eAAO,YAAY,IAAI;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,WAAS,QAAc;AACrB,mBAAe,MAAM;AAAA,EACvB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzCA,SAAS,YAAAE,WAAU,OAAAC,YAAW;AAEvB,SAAS,mBAAmB,SAUjC;AACA,QAAM,aAAaA,KAAI,KAAK;AAC5B,QAAM,aAAaA,KAAI,KAAK;AAE5B,QAAM,gBAAgBD,UAAS,MAAM,CAAC,CAAC,QAAQ,WAAW,OAAO,UAAU;AAE3E,QAAM,aAAaA;AAAA,IACjB,MAAM,cAAc,SAAS,CAAC,QAAQ,MAAM,MAAM;AAAA,EACpD;AAEA,iBAAe,QAAuB;AACpC,UAAM,MAAM,QAAQ,WAAW;AAC/B,QAAI,CAAC,KAAK,YAAY;AACpB;AAAA,IACF;AAEA,eAAW,QAAQ;AACnB,eAAW,QAAQ;AAEnB,QAAI;AACF,YAAM,SAAS,MAAM,IAAI,WAAW,QAAQ;AAAA,QAC1C,aAAa,EAAE,GAAG,QAAQ,MAAM,MAAM,YAAY;AAAA,QAClD,SAAS,QAAQ,MAAM,MAAM;AAAA,MAC/B,CAAC;AAED,UAAI,UAAU,MAAM;AAClB;AAAA,MACF;AAEA,YAAM,SAAS,EAAE,GAAG,QAAQ,MAAM,MAAM,YAAY;AACpD,iBAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,YAAI,OAAO,QAAQ;AACjB,iBAAO,GAAG,IAAI,OAAO,GAAG;AAAA,QAC1B;AAAA,MACF;AAEA,cAAQ,SAAS,QAAQ,IAAI;AAAA,IAC/B,SAAS,OAAO;AACd,cAAQ,KAAK,0CAA0C,KAAK;AAC5D,iBAAW,QAAQ;AAAA,IACrB,UAAE;AACA,iBAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACxDO,SAAS,sBACd,QACA,SACM;AACN,QAAM,mBAAmB,OAAO;AAChC,QAAM,sBAAsB,OAAO;AACnC,QAAM,oBAAoB,OAAO;AACjC,QAAM,sBAAsB,OAAO;AACnC,QAAM,yBAAyB,OAAO;AAKtC,SAAO,WAAW,CAAC,OAAO,iBAAkB,aAAc,UAAW;AACnE,QAAI,mBAAmB,OAAO,cAAc,eAAe,GAAG;AAC5D;AAAA,IACF;AACA,YAAQ,OAAO;AACf,qBAAiB,OAAO,iBAAiB,aAAa,KAAK;AAAA,EAC7D;AAEA,SAAO,cAAc,CAAC,YAAY;AAChC,QAAI,OAAO,cAAc,OAAO,GAAG;AACjC;AAAA,IACF;AACA,YAAQ,OAAO;AACf,wBAAoB,OAAO;AAAA,EAC7B;AAEA,SAAO,YAAY,CAAC,SAAS,UAAU,iBAAkB,gBAAiB;AACxE,QAAI,OAAO,cAAc,OAAO,GAAG;AACjC;AAAA,IACF;AACA,QAAI,mBAAmB,OAAO,cAAc,eAAe,GAAG;AAC5D;AAAA,IACF;AACA,YAAQ,OAAO;AACf,sBAAkB,SAAS,UAAU,iBAAiB,WAAW;AAAA,EACnE;AAEA,SAAO,cAAc,CAAC,SAAS,YAAY;AACzC,QAAI,OAAO,cAAc,OAAO,GAAG;AACjC;AAAA,IACF;AACA,YAAQ,gBAAgB,OAAO;AAC/B,wBAAoB,SAAS,OAAO;AAAA,EACtC;AAEA,SAAO,iBAAiB,CAAC,YAAY;AACnC,YAAQ,OAAO;AACf,2BAAuB,OAAO;AAAA,EAChC;AACF;","names":["markDirty","computed","computed","reactive","computed","ref"]}
1
+ {"version":3,"sources":["../src/editor.ts","../src/history.ts","../src/block-actions.ts","../src/auto-save.ts","../src/condition-preview.ts","../src/data-source-fetch.ts","../src/history-interceptor.ts"],"sourcesContent":["import type {\n Block,\n ColumnLayout,\n TemplateContent,\n TemplateDefaults,\n TemplateSettings,\n UiTheme,\n ViewportSize,\n} from \"@templatical/types\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\n\nfunction getColumnCount(layout: ColumnLayout): number {\n if (layout === \"1\") return 1;\n if (layout === \"3\") return 3;\n return 2;\n}\nimport {\n computed,\n reactive,\n readonly,\n type DeepReadonly,\n type Ref,\n} from \"@vue/reactivity\";\n\nexport interface EditorState {\n content: TemplateContent;\n selectedBlockId: string | null;\n viewport: ViewportSize;\n darkMode: boolean;\n previewMode: boolean;\n isDirty: boolean;\n uiTheme: UiTheme;\n}\n\nexport interface UseEditorOptions {\n content: TemplateContent;\n defaultFontFamily?: string;\n templateDefaults?: TemplateDefaults;\n lockedBlocks?: Ref<Map<string, unknown>>;\n}\n\nexport interface UseEditorReturn {\n state: DeepReadonly<EditorState>;\n content: Ref<TemplateContent>;\n selectedBlock: Ref<Block | null>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n selectBlock: (blockId: string | null) => void;\n setViewport: (viewport: ViewportSize) => void;\n setDarkMode: (darkMode: boolean) => void;\n setPreviewMode: (previewMode: boolean) => void;\n setUiTheme: (theme: UiTheme) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n updateSettings: (updates: Partial<TemplateSettings>) => void;\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n moveBlock: (\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n isBlockLocked: (blockId: string) => boolean;\n markDirty: () => void;\n findBlockLocation: (blockId: string) => {\n targetSectionId?: string;\n columnIndex?: number;\n index: number;\n } | null;\n}\n\nexport function useEditor(options: UseEditorOptions): UseEditorReturn {\n const state = reactive<EditorState>({\n content:\n options.content ??\n createDefaultTemplateContent(\n options.defaultFontFamily,\n options.templateDefaults,\n ),\n selectedBlockId: null,\n viewport: \"desktop\",\n darkMode: false,\n previewMode: false,\n isDirty: false,\n uiTheme: \"auto\",\n });\n\n const content = computed({\n get: () => state.content,\n set: (value: TemplateContent) => {\n state.content = value;\n state.isDirty = true;\n },\n });\n\n const selectedBlock = computed(() => {\n if (!state.selectedBlockId) return null;\n return findBlockById(state.content.blocks, state.selectedBlockId);\n });\n\n function findBlockById(blocks: Block[], id: string): Block | null {\n for (const block of blocks) {\n if (block.id === id) return block;\n if (block.type === \"section\") {\n for (const column of block.children) {\n const found = findBlockById(column, id);\n if (found) return found;\n }\n }\n }\n return null;\n }\n\n function collectBlockIds(block: Block, ids: Set<string>): void {\n ids.add(block.id);\n if (block.type === \"section\") {\n for (const column of block.children) {\n for (const child of column) {\n collectBlockIds(child, ids);\n }\n }\n }\n }\n\n function findBlockParent(\n blocks: Block[],\n id: string,\n parent: {\n blocks: Block[];\n sectionId?: string;\n columnIndex?: number;\n } = { blocks },\n ): { blocks: Block[]; sectionId?: string; columnIndex?: number } | null {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block.id === id) return parent;\n if (block.type === \"section\") {\n for (let colIdx = 0; colIdx < block.children.length; colIdx++) {\n const result = findBlockParent(block.children[colIdx], id, {\n blocks: block.children[colIdx],\n sectionId: block.id,\n columnIndex: colIdx,\n });\n if (result) return result;\n }\n }\n }\n return null;\n }\n\n function isBlockLocked(blockId: string): boolean {\n return options.lockedBlocks?.value.has(blockId) ?? false;\n }\n\n function findBlockLocation(blockId: string): {\n targetSectionId?: string;\n columnIndex?: number;\n index: number;\n } | null {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return null;\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index === -1) return null;\n return {\n targetSectionId: parent.sectionId,\n columnIndex: parent.columnIndex,\n index,\n };\n }\n\n // TODO(collab): the lock checks in addBlock/moveBlock/removeBlock/updateBlock\n // are shallow — they only consider the directly-targeted block id. A section\n // can still be removed, moved, or have its `children` array rewritten while a\n // peer is editing one of its descendants, which silently disrupts that peer's\n // edit. Add a `hasLockedDescendant(blockId)` helper and gate section-level\n // operations on it (and on the parent of each affected child) so cascades\n // through the tree are also blocked.\n\n function setContent(newContent: TemplateContent, markDirty = true): void {\n state.content = newContent;\n if (markDirty) {\n state.isDirty = true;\n }\n }\n\n function selectBlock(blockId: string | null): void {\n if (blockId && isBlockLocked(blockId)) {\n return;\n }\n state.selectedBlockId = blockId;\n }\n\n function setViewport(viewport: ViewportSize): void {\n state.viewport = viewport;\n }\n\n function setDarkMode(darkMode: boolean): void {\n state.darkMode = darkMode;\n }\n\n function setUiTheme(theme: UiTheme): void {\n state.uiTheme = theme;\n }\n\n function setPreviewMode(previewMode: boolean): void {\n state.previewMode = previewMode;\n if (previewMode) {\n state.selectedBlockId = null;\n }\n }\n\n function updateBlock(blockId: string, updates: Partial<Block>): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const block = findBlockById(state.content.blocks, blockId);\n if (block) {\n Object.assign(block, updates);\n state.isDirty = true;\n }\n }\n\n function updateSettings(updates: Partial<TemplateSettings>): void {\n state.content.settings = { ...state.content.settings, ...updates };\n state.isDirty = true;\n }\n\n function addBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex = 0,\n index?: number,\n ): void {\n if (targetSectionId) {\n if (isBlockLocked(targetSectionId)) {\n return;\n }\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n if (columnIndex < 0 || columnIndex >= getColumnCount(section.columns)) {\n return;\n }\n section.children[columnIndex] = section.children[columnIndex] || [];\n const targetArray = section.children[columnIndex];\n if (index !== undefined && index < targetArray.length) {\n targetArray.splice(index, 0, block);\n } else {\n targetArray.push(block);\n }\n }\n } else {\n if (index !== undefined && index < state.content.blocks.length) {\n state.content.blocks.splice(index, 0, block);\n } else {\n state.content.blocks.push(block);\n }\n }\n state.isDirty = true;\n }\n\n function removeBlock(blockId: string): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const parent = findBlockParent(state.content.blocks, blockId);\n if (parent) {\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index !== -1) {\n const [removed] = parent.blocks.splice(index, 1);\n if (state.selectedBlockId) {\n const removedIds = new Set<string>();\n collectBlockIds(removed, removedIds);\n if (removedIds.has(state.selectedBlockId)) {\n state.selectedBlockId = null;\n }\n }\n state.isDirty = true;\n }\n }\n }\n\n function moveBlock(\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex = 0,\n ): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n if (targetSectionId && isBlockLocked(targetSectionId)) {\n return;\n }\n\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return;\n\n const oldIndex = parent.blocks.findIndex((b) => b.id === blockId);\n if (oldIndex === -1) return;\n\n // Resolve target before mutating the source — otherwise an invalid\n // targetSectionId leaves the block spliced-out and unrecoverable.\n let targetArray: Block[];\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (!section || section.type !== \"section\") return;\n if (columnIndex < 0 || columnIndex >= getColumnCount(section.columns)) {\n return;\n }\n section.children[columnIndex] = section.children[columnIndex] || [];\n targetArray = section.children[columnIndex];\n } else {\n targetArray = state.content.blocks;\n }\n\n const [block] = parent.blocks.splice(oldIndex, 1);\n targetArray.splice(newIndex, 0, block);\n\n state.isDirty = true;\n }\n\n function markDirty(): void {\n state.isDirty = true;\n }\n\n return {\n state: readonly(state),\n content,\n selectedBlock,\n isBlockLocked,\n setContent,\n selectBlock,\n setViewport,\n setDarkMode,\n setUiTheme,\n setPreviewMode,\n updateBlock,\n updateSettings,\n addBlock,\n removeBlock,\n moveBlock,\n markDirty,\n findBlockLocation,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { computed, ref, type ComputedRef, type Ref } from \"@vue/reactivity\";\n\nexport interface UseHistoryOptions {\n content: Ref<TemplateContent>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n isRemoteOperation?: () => boolean;\n maxSize?: number;\n}\n\nexport interface UseHistoryReturn {\n canUndo: ComputedRef<boolean>;\n canRedo: ComputedRef<boolean>;\n isNavigating: Ref<boolean>;\n undo: () => void;\n redo: () => void;\n record: () => void;\n recordDebounced: (blockId: string) => void;\n clear: () => void;\n destroy: () => void;\n}\n\ninterface DebouncedSnapshot {\n blockId: string;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\nconst MAX_STACK_SIZE = 50;\nconst DEBOUNCE_MS = 300;\nconst NAVIGATE_IDLE_MS = 1500;\n\nexport function useHistory(options: UseHistoryOptions): UseHistoryReturn {\n const {\n content,\n setContent,\n isRemoteOperation,\n maxSize = MAX_STACK_SIZE,\n } = options;\n\n const undoStack = ref<TemplateContent[]>([]);\n const redoStack = ref<TemplateContent[]>([]);\n const isNavigating = ref(false);\n let navigatingTimeoutId: ReturnType<typeof setTimeout> | null = null;\n let pendingDebounce: DebouncedSnapshot | null = null;\n\n const canUndo = computed(() => undoStack.value.length > 0);\n const canRedo = computed(() => redoStack.value.length > 0);\n\n function cloneContent(): TemplateContent {\n // Cycle-safe deep clone. A naked JSON.stringify throws\n // `Converting circular structure to JSON` if anything in the tree\n // is self-referencing — e.g. a DOM element with a Sortable expando\n // back-ref ever sneaks into block data via a drag handler. We'd\n // rather drop the back-ref from the snapshot than freeze the undo\n // stack (the visible symptom: any subsequent mutation that calls\n // `record()` throws, breaking clone/move/etc.).\n const seen = new WeakSet<object>();\n return JSON.parse(\n JSON.stringify(content.value, (_key, value) => {\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) return undefined;\n seen.add(value);\n }\n return value;\n }),\n ) as TemplateContent;\n }\n\n function pushToUndoStack(snapshot: TemplateContent): void {\n undoStack.value.push(snapshot);\n if (undoStack.value.length > maxSize) {\n undoStack.value.splice(0, undoStack.value.length - maxSize);\n }\n }\n\n function flushPendingDebounce(): void {\n if (pendingDebounce) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce = null;\n }\n }\n\n function record(): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n flushPendingDebounce();\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n }\n\n function recordDebounced(blockId: string): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n if (pendingDebounce && pendingDebounce.blockId === blockId) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce.timeoutId = setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS);\n return;\n }\n\n flushPendingDebounce();\n\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n\n pendingDebounce = {\n blockId,\n timeoutId: setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS),\n };\n }\n\n function setNavigating(): void {\n isNavigating.value = true;\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n }\n navigatingTimeoutId = setTimeout(() => {\n isNavigating.value = false;\n navigatingTimeoutId = null;\n }, NAVIGATE_IDLE_MS);\n }\n\n function undo(): void {\n if (undoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = undoStack.value.pop()!;\n redoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function redo(): void {\n if (redoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = redoStack.value.pop()!;\n undoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function clear(): void {\n undoStack.value = [];\n redoStack.value = [];\n flushPendingDebounce();\n }\n\n function destroy(): void {\n clear();\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n navigatingTimeoutId = null;\n }\n }\n\n return {\n canUndo,\n canRedo,\n isNavigating,\n undo,\n redo,\n record,\n recordDebounced,\n clear,\n destroy,\n };\n}\n","import type { Block, BlockDefaults, BlockType } from \"@templatical/types\";\nimport { createBlock, generateId } from \"@templatical/types\";\n\nfunction regenerateNestedIds(block: Block): void {\n if (block.type === \"table\") {\n block.rows = block.rows.map((row) => ({\n ...row,\n id: generateId(),\n cells: row.cells.map((cell) => ({ ...cell, id: generateId() })),\n }));\n } else if (block.type === \"social\") {\n block.icons = block.icons.map((icon) => ({ ...icon, id: generateId() }));\n } else if (block.type === \"menu\") {\n block.items = block.items.map((item) => ({ ...item, id: generateId() }));\n }\n}\n\nexport interface UseBlockActionsOptions {\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n selectBlock: (blockId: string | null) => void;\n /** Locate a block in the tree — used by `duplicateBlock` to insert the\n * clone right after the source instead of appending to the end. */\n findBlockLocation?: (blockId: string) => {\n targetSectionId?: string;\n columnIndex?: number;\n index: number;\n } | null;\n blockDefaults?: BlockDefaults;\n}\n\nexport interface UseBlockActionsReturn {\n createAndAddBlock: (\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n duplicateBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n deleteBlock: (blockId: string) => void;\n updateBlockProperty: <K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ) => void;\n}\n\nexport function useBlockActions(\n options: UseBlockActionsOptions,\n): UseBlockActionsReturn {\n const { addBlock, removeBlock, updateBlock, selectBlock, findBlockLocation } =\n options;\n\n function createAndAddBlock(\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const block = createBlock(type, options.blockDefaults);\n addBlock(block, targetSectionId, columnIndex);\n selectBlock(block.id);\n return block;\n }\n\n function duplicateBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const cloned = JSON.parse(JSON.stringify(block)) as Block;\n cloned.id = generateId();\n regenerateNestedIds(cloned);\n\n if (cloned.type === \"section\") {\n cloned.children = cloned.children.map((column) =>\n column.map((child) => {\n const clonedChild = JSON.parse(JSON.stringify(child)) as Block;\n clonedChild.id = generateId();\n regenerateNestedIds(clonedChild);\n return clonedChild;\n }),\n );\n }\n\n // Insert directly after the source block. Explicit target args win;\n // otherwise, resolve the source's location and bump index by 1. Falls\n // back to appending at the end if location is unknown.\n if (targetSectionId !== undefined || columnIndex !== undefined) {\n addBlock(cloned, targetSectionId, columnIndex);\n } else {\n const sourceLocation = findBlockLocation?.(block.id) ?? null;\n if (sourceLocation) {\n addBlock(\n cloned,\n sourceLocation.targetSectionId,\n sourceLocation.columnIndex,\n sourceLocation.index + 1,\n );\n } else {\n addBlock(cloned, targetSectionId, columnIndex);\n }\n }\n selectBlock(cloned.id);\n return cloned;\n }\n\n function deleteBlock(blockId: string): void {\n removeBlock(blockId);\n }\n\n function updateBlockProperty<K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ): void {\n updateBlock(blockId, { [key]: value } as Partial<Block>);\n }\n\n return {\n createAndAddBlock,\n duplicateBlock,\n deleteBlock,\n updateBlockProperty,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { watch, type Ref } from \"@vue/reactivity\";\n\nexport interface UseAutoSaveOptions {\n content: Ref<TemplateContent>;\n isDirty: () => boolean;\n onChange: (content: TemplateContent) => void;\n debounce?: number;\n enabled?: boolean | (() => boolean);\n}\n\nexport interface UseAutoSaveReturn {\n flush: () => void;\n cancel: () => void;\n pause: () => void;\n resume: () => void;\n destroy: () => void;\n}\n\nexport function useAutoSave(options: UseAutoSaveOptions): UseAutoSaveReturn {\n const {\n content,\n isDirty,\n onChange,\n debounce = 1000,\n enabled = true,\n } = options;\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let paused = false;\n\n function isEnabled(): boolean {\n return typeof enabled === \"function\" ? enabled() : enabled;\n }\n\n function pause(): void {\n paused = true;\n cancel();\n }\n\n function resume(): void {\n paused = false;\n }\n\n function cancel(): void {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function flush(): void {\n cancel();\n if (isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }\n\n function scheduleOnChange(): void {\n if (!isEnabled() || paused) return;\n\n cancel();\n timeoutId = setTimeout(() => {\n timeoutId = null;\n if (isEnabled() && !paused && isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }, debounce);\n }\n\n const stopWatch = watch(\n content,\n () => {\n if (isEnabled() && !paused && isDirty()) {\n scheduleOnChange();\n }\n },\n { deep: true },\n );\n\n function destroy(): void {\n stopWatch();\n cancel();\n }\n\n return {\n flush,\n cancel,\n pause,\n resume,\n destroy,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport { computed, reactive, type ComputedRef } from \"@vue/reactivity\";\n\nexport interface UseConditionPreviewReturn {\n isHidden: (blockId: string) => boolean;\n toggleBlock: (blockId: string) => void;\n reset: () => void;\n hasHiddenBlocks: ComputedRef<boolean>;\n}\n\nexport function useConditionPreview(\n editor: UseEditorReturn,\n): UseConditionPreviewReturn {\n const hiddenBlockIds = reactive(new Set<string>());\n\n const hasHiddenBlocks = computed(() => hiddenBlockIds.size > 0);\n\n function isHidden(blockId: string): boolean {\n return hiddenBlockIds.has(blockId);\n }\n\n function toggleBlock(blockId: string): void {\n if (hiddenBlockIds.has(blockId)) {\n hiddenBlockIds.delete(blockId);\n } else {\n hiddenBlockIds.add(blockId);\n\n if (editor.state.selectedBlockId === blockId) {\n editor.selectBlock(null);\n }\n }\n }\n\n function reset(): void {\n hiddenBlockIds.clear();\n }\n\n return {\n isHidden,\n toggleBlock,\n reset,\n hasHiddenBlocks,\n };\n}\n","import type { CustomBlock, CustomBlockDefinition } from \"@templatical/types\";\nimport type { ComputedRef, Ref } from \"@vue/reactivity\";\nimport { computed, ref } from \"@vue/reactivity\";\n\nexport function useDataSourceFetch(options: {\n definition: ComputedRef<CustomBlockDefinition | undefined>;\n block: ComputedRef<CustomBlock>;\n onUpdate: (fieldValues: Record<string, unknown>, fetched: boolean) => void;\n}): {\n isFetching: Ref<boolean>;\n fetchError: Ref<boolean>;\n fetch: () => Promise<void>;\n hasDataSource: ComputedRef<boolean>;\n needsFetch: ComputedRef<boolean>;\n} {\n const isFetching = ref(false);\n const fetchError = ref(false);\n\n const hasDataSource = computed(() => !!options.definition.value?.dataSource);\n\n const needsFetch = computed(\n () => hasDataSource.value && !options.block.value.dataSourceFetched,\n );\n\n async function fetch(): Promise<void> {\n const def = options.definition.value;\n if (!def?.dataSource) {\n return;\n }\n\n isFetching.value = true;\n fetchError.value = false;\n\n try {\n const result = await def.dataSource.onFetch({\n fieldValues: { ...options.block.value.fieldValues },\n blockId: options.block.value.id,\n });\n\n if (result == null) {\n return;\n }\n\n const merged = { ...options.block.value.fieldValues };\n for (const key of Object.keys(merged)) {\n if (key in result) {\n merged[key] = result[key];\n }\n }\n\n options.onUpdate(merged, true);\n } catch (error) {\n console.warn(\"[Templatical] Data source fetch error:\", error);\n fetchError.value = true;\n } finally {\n isFetching.value = false;\n }\n }\n\n return {\n isFetching,\n fetchError,\n fetch,\n hasDataSource,\n needsFetch,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { UseHistoryReturn } from \"./history\";\n\n/**\n * Wraps editor mutation methods to record history snapshots before each\n * operation. Mutates the editor object in place.\n *\n * Must be applied **after** any collaboration broadcast wrapping so the\n * call chain is: history.record() → broadcast → original mutation.\n */\nexport function useHistoryInterceptor(\n editor: UseEditorReturn,\n history: UseHistoryReturn,\n): void {\n const originalAddBlock = editor.addBlock;\n const originalRemoveBlock = editor.removeBlock;\n const originalMoveBlock = editor.moveBlock;\n const originalUpdateBlock = editor.updateBlock;\n const originalUpdateSettings = editor.updateSettings;\n\n // Skip recording when the underlying op is a no-op (e.g., a peer-locked\n // block or section), otherwise the undo stack fills with snapshots that\n // are identical to current state and undo silently does nothing.\n editor.addBlock = (block, targetSectionId?, columnIndex?, index?) => {\n if (targetSectionId && editor.isBlockLocked(targetSectionId)) {\n return;\n }\n history.record();\n originalAddBlock(block, targetSectionId, columnIndex, index);\n };\n\n editor.removeBlock = (blockId) => {\n if (editor.isBlockLocked(blockId)) {\n return;\n }\n history.record();\n originalRemoveBlock(blockId);\n };\n\n editor.moveBlock = (blockId, newIndex, targetSectionId?, columnIndex?) => {\n if (editor.isBlockLocked(blockId)) {\n return;\n }\n if (targetSectionId && editor.isBlockLocked(targetSectionId)) {\n return;\n }\n history.record();\n originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);\n };\n\n editor.updateBlock = (blockId, updates) => {\n if (editor.isBlockLocked(blockId)) {\n return;\n }\n history.recordDebounced(blockId);\n originalUpdateBlock(blockId, updates);\n };\n\n editor.updateSettings = (updates) => {\n history.record();\n originalUpdateSettings(updates);\n };\n}\n"],"mappings":"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","names":["markDirty","computed","computed","reactive","computed","ref"]}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@templatical/core",
3
3
  "description": "Framework-agnostic editor logic for Templatical email editor",
4
- "version": "0.7.1",
4
+ "version": "0.7.3",
5
5
  "bugs": "https://github.com/templatical/sdk/issues",
6
6
  "dependencies": {
7
7
  "@vue/reactivity": "^3.5.33",
8
- "@templatical/types": "0.7.1"
8
+ "@templatical/types": "0.7.3"
9
9
  },
10
10
  "devDependencies": {
11
11
  "pusher-js": "^8.5.0",