@snowcone-app/canvas 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/{CanvasStateV1-D5GzvmnY.cjs → CanvasStateV1-BmE5V6me.cjs} +2 -2
  2. package/dist/{CanvasStateV1-D5GzvmnY.cjs.map → CanvasStateV1-BmE5V6me.cjs.map} +1 -1
  3. package/dist/{CanvasStateV1-ejb4d_LM.js → CanvasStateV1-CD3Q94F4.js} +2 -2
  4. package/dist/{CanvasStateV1-ejb4d_LM.js.map → CanvasStateV1-CD3Q94F4.js.map} +1 -1
  5. package/dist/{ElementFactory-uJTXU-nP.js → ElementFactory-Ckv6sSev.js} +698 -696
  6. package/dist/ElementFactory-Ckv6sSev.js.map +1 -0
  7. package/dist/{ElementFactory-B7UOaJSD.cjs → ElementFactory-DEjwp-Wg.cjs} +5 -5
  8. package/dist/ElementFactory-DEjwp-Wg.cjs.map +1 -0
  9. package/dist/{ImportManager-CxiaRg1N.js → ImportManager-64OYjELO.js} +2 -2
  10. package/dist/{ImportManager-CxiaRg1N.js.map → ImportManager-64OYjELO.js.map} +1 -1
  11. package/dist/{ImportManager-BYwuK6n4.cjs → ImportManager-wSzrR-5a.cjs} +2 -2
  12. package/dist/{ImportManager-BYwuK6n4.cjs.map → ImportManager-wSzrR-5a.cjs.map} +1 -1
  13. package/dist/advanced.js +14 -14
  14. package/dist/advanced.js.map +1 -1
  15. package/dist/advanced.mjs +1847 -1854
  16. package/dist/advanced.mjs.map +1 -1
  17. package/dist/{compose-Bo108juW.cjs → compose-DHBRwi_A.cjs} +5 -5
  18. package/dist/compose-DHBRwi_A.cjs.map +1 -0
  19. package/dist/{compose-DQ1FZS3O.js → compose-DIPiisIw.js} +355 -355
  20. package/dist/compose-DIPiisIw.js.map +1 -0
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +44 -45
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/internals.js +1 -1
  26. package/dist/internals.mjs +3 -3
  27. package/dist/rendering/serialize-for-server.d.ts +2 -2
  28. package/package.json +2 -2
  29. package/dist/ElementFactory-B7UOaJSD.cjs.map +0 -1
  30. package/dist/ElementFactory-uJTXU-nP.js.map +0 -1
  31. package/dist/components/stories/utils/MockEditorProvider.d.ts +0 -32
  32. package/dist/components/stories/utils/QACanvasCard.d.ts +0 -41
  33. package/dist/components/stories/utils/VisualQACard.d.ts +0 -24
  34. package/dist/components/stories/utils/element-factories.d.ts +0 -188
  35. package/dist/components/stories/utils/spec-to-elements.d.ts +0 -74
  36. package/dist/components/stories/utils/themeDecorator.d.ts +0 -45
  37. package/dist/components/stories/utils/unified-test-cases.d.ts +0 -27
  38. package/dist/compose-Bo108juW.cjs.map +0 -1
  39. package/dist/compose-DQ1FZS3O.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { E as m } from "./ElementFactory-uJTXU-nP.js";
1
+ import { E as m } from "./ElementFactory-Ckv6sSev.js";
2
2
  import { c as f, i as l } from "./HybridHistoryManager-BV6XV0nD.js";
3
3
  const h = f("ImportManager"), c = class c {
4
4
  /**
@@ -219,4 +219,4 @@ let g = c;
219
219
  export {
220
220
  g as I
221
221
  };
222
- //# sourceMappingURL=ImportManager-CxiaRg1N.js.map
222
+ //# sourceMappingURL=ImportManager-64OYjELO.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ImportManager-CxiaRg1N.js","sources":["../src/utils/ImportManager.ts"],"sourcesContent":["/**\n * ImportManager - Handles importing workspace from JSON and images\n */\n\nimport { ElementFactory } from '../core/ElementFactory.js';\nimport { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { CanvasDocument } from './ExportManager.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { GroupElement } from '../core/GroupElement.js';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('ImportManager');\n\n/** V1 document format (pre-artboard) */\ninterface V1CanvasDocument {\n metadata: { version: string };\n canvas?: { width?: number; height?: number; backgroundColor?: string };\n elements?: Record<string, unknown>[];\n}\n\nexport interface ImportResult {\n success: boolean;\n artboards?: ArtboardElement[];\n elements?: (TextElement | ImageElement | GroupElement)[];\n activeArtboardId?: string | null;\n error?: string;\n}\n\nexport interface ImageImportResult {\n success: boolean;\n dataUrl?: string;\n filename?: string;\n width?: number;\n height?: number;\n error?: string;\n}\n\nexport class ImportManager {\n private static readonly SUPPORTED_VERSIONS = ['1.0.0', '2.0.0'];\n\n /**\n * Import workspace from JSON file\n */\n static async importFromJSON(file: File): Promise<ImportResult> {\n try {\n // Read file as text\n const text = await this.readFileAsText(file);\n\n // Parse JSON\n const document: CanvasDocument = JSON.parse(text);\n\n // Validate structure\n this.validateDocument(document);\n\n // Check version compatibility\n if (!this.SUPPORTED_VERSIONS.includes(document.metadata.version)) {\n throw new Error(\n `Unsupported version: ${document.metadata.version}. ` +\n `Supported versions: ${this.SUPPORTED_VERSIONS.join(', ')}`\n );\n }\n\n // Handle version 1.0.0 (no artboards) - migrate to artboards\n if (document.metadata.version === '1.0.0') {\n return this.migrateV1Document(document as unknown as V1CanvasDocument);\n }\n\n // Deserialize artboards and elements\n const artboards: ArtboardElement[] = [];\n const allElements: (TextElement | ImageElement | GroupElement)[] = [];\n\n document.artboards.forEach((artboardData) => {\n // Create artboard\n const artboard = ArtboardElement.fromJSON({\n id: artboardData.id,\n name: artboardData.name,\n x: artboardData.x,\n y: artboardData.y,\n width: artboardData.width,\n height: artboardData.height,\n backgroundColor: artboardData.backgroundColor,\n elementIds: artboardData.elements.map((e) => e.id || ''),\n });\n\n // Deserialize elements for this artboard\n const elements = artboardData.elements\n .map((elementConfig) => {\n try {\n return ElementFactory.createFromJSON(elementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element) => element !== null) as (TextElement | ImageElement | GroupElement)[];\n\n artboards.push(artboard);\n allElements.push(...elements);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(allElements);\n\n return {\n success: true,\n artboards,\n elements: allElements,\n activeArtboardId: document.activeArtboardId,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Migrate v1 document (no artboards) to v2 (with artboards)\n */\n private static async migrateV1Document(document: V1CanvasDocument): Promise<ImportResult> {\n try {\n // V1 format: { metadata, canvas, elements }\n const elements = document.elements || [];\n\n // Create a default artboard containing all elements\n const artboard = new ArtboardElement({\n id: 'artboard-migrated',\n name: 'Artboard 1',\n x: 0,\n y: 0,\n width: document.canvas?.width || 1920,\n height: document.canvas?.height || 1080,\n backgroundColor: document.canvas?.backgroundColor || '#ffffff',\n });\n\n // Deserialize elements\n const deserializedElements = elements\n .map((elementConfig: Record<string, unknown>) => {\n try {\n return ElementFactory.createFromJSON(elementConfig as unknown as import('../types/index.js').AnyElementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element): element is TextElement | ImageElement | GroupElement => element !== null);\n\n // Add all element IDs to artboard\n deserializedElements.forEach((element) => {\n artboard.addElementId(element.id);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(deserializedElements);\n\n return {\n success: true,\n artboards: [artboard],\n elements: deserializedElements,\n activeArtboardId: artboard.id,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Migration failed',\n };\n }\n }\n\n /**\n * Import image file\n */\n static async importImage(file: File): Promise<ImageImportResult> {\n try {\n // Validate file type\n if (!file.type.startsWith('image/')) {\n throw new Error('File is not an image');\n }\n\n // Check file size (max 10MB)\n const maxSize = 10 * 1024 * 1024; // 10MB\n if (file.size > maxSize) {\n throw new Error('Image file is too large (max 10MB)');\n }\n\n // Read as data URL\n const dataUrl = await this.readFileAsDataURL(file);\n\n // Get image dimensions\n const { width, height } = await this.getImageDimensions(dataUrl);\n\n return {\n success: true,\n dataUrl,\n filename: file.name,\n width,\n height,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Validate document structure\n */\n private static validateDocument(document: unknown): asserts document is CanvasDocument {\n if (!document || typeof document !== 'object') {\n throw new Error('Invalid document');\n }\n const doc = document as Record<string, unknown>;\n if (!doc.metadata) {\n throw new Error('Missing metadata');\n }\n if (!(doc.metadata as Record<string, unknown>).version) {\n throw new Error('Missing version in metadata');\n }\n if (!doc.artboards && !doc.elements) {\n throw new Error('Missing artboards or elements array');\n }\n if (doc.artboards && !Array.isArray(doc.artboards)) {\n throw new Error('Invalid artboards array');\n }\n }\n\n /**\n * Read file as text\n */\n private static readFileAsText(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n }\n\n /**\n * Read file as data URL\n */\n private static readFileAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Get image dimensions from data URL\n */\n private static getImageDimensions(dataUrl: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.width, height: img.height });\n };\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = dataUrl;\n });\n }\n\n /**\n * Validate imported data before applying to state\n */\n static validateImportedData(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check for duplicate artboard IDs\n const artboardIds = new Set();\n artboards.forEach((artboard) => {\n if (artboardIds.has(artboard.id)) {\n errors.push(`Duplicate artboard ID: ${artboard.id}`);\n }\n artboardIds.add(artboard.id);\n });\n\n // Check for duplicate element IDs\n const elementIds = new Set();\n elements.forEach((element) => {\n if (elementIds.has(element.id)) {\n errors.push(`Duplicate element ID: ${element.id}`);\n }\n elementIds.add(element.id);\n });\n\n // Validate element-to-artboard references\n artboards.forEach((artboard) => {\n artboard.getElementIds().forEach((elementId: string) => {\n if (!elementIds.has(elementId)) {\n errors.push(`Artboard \"${artboard.name}\" references missing element: ${elementId}`);\n }\n });\n });\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Get import summary (for UI display before confirming)\n */\n static getImportSummary(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): {\n artboardCount: number;\n elementCount: number;\n artboardNames: string[];\n warnings: string[];\n } {\n const validation = this.validateImportedData(artboards, elements);\n\n return {\n artboardCount: artboards.length,\n elementCount: elements.length,\n artboardNames: artboards.map((a) => a.name),\n warnings: validation.errors,\n };\n }\n\n /**\n * Preload all images in parallel for fast artboard switching\n * Recursively finds all ImageElements (including those in groups)\n */\n private static async preloadAllImages(elements: (TextElement | ImageElement | GroupElement)[]): Promise<void> {\n const imageElements: ImageElement[] = [];\n\n // Recursively find all image elements\n const findImages = (el: TextElement | ImageElement | GroupElement) => {\n if (el.transformType === 'image') {\n imageElements.push(el as ImageElement);\n } else if (el.transformType === 'group' && 'children' in el) {\n (el as GroupElement).children.forEach((child) => findImages(child as TextElement | ImageElement | GroupElement));\n }\n };\n\n elements.forEach(findImages);\n\n // Wait for all images to load in parallel\n const loadPromises = imageElements.map((img: ImageElement) => {\n return new Promise<void>((resolve) => {\n if (img.imageLoaded) {\n resolve();\n } else if (img.imageElement) {\n // Image is currently loading\n const imgEl = img.imageElement;\n const onLoad = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve();\n };\n const onError = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve(); // Resolve even on error to not block other images\n };\n imgEl.addEventListener('load', onLoad);\n imgEl.addEventListener('error', onError);\n } else {\n resolve();\n }\n });\n });\n\n await Promise.all(loadPromises);\n }\n}\n\nexport default ImportManager;\n"],"names":["logger","createLogger","_ImportManager","file","text","document","artboards","allElements","artboardData","artboard","ArtboardElement","e","elements","elementConfig","ElementFactory","error","element","_a","_b","_c","deserializedElements","maxSize","dataUrl","width","height","doc","resolve","reject","reader","img","errors","artboardIds","elementIds","elementId","validation","a","imageElements","findImages","el","child","loadPromises","imgEl","onLoad","onError","ImportManager"],"mappings":"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"}
1
+ {"version":3,"file":"ImportManager-64OYjELO.js","sources":["../src/utils/ImportManager.ts"],"sourcesContent":["/**\n * ImportManager - Handles importing workspace from JSON and images\n */\n\nimport { ElementFactory } from '../core/ElementFactory.js';\nimport { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { CanvasDocument } from './ExportManager.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { GroupElement } from '../core/GroupElement.js';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('ImportManager');\n\n/** V1 document format (pre-artboard) */\ninterface V1CanvasDocument {\n metadata: { version: string };\n canvas?: { width?: number; height?: number; backgroundColor?: string };\n elements?: Record<string, unknown>[];\n}\n\nexport interface ImportResult {\n success: boolean;\n artboards?: ArtboardElement[];\n elements?: (TextElement | ImageElement | GroupElement)[];\n activeArtboardId?: string | null;\n error?: string;\n}\n\nexport interface ImageImportResult {\n success: boolean;\n dataUrl?: string;\n filename?: string;\n width?: number;\n height?: number;\n error?: string;\n}\n\nexport class ImportManager {\n private static readonly SUPPORTED_VERSIONS = ['1.0.0', '2.0.0'];\n\n /**\n * Import workspace from JSON file\n */\n static async importFromJSON(file: File): Promise<ImportResult> {\n try {\n // Read file as text\n const text = await this.readFileAsText(file);\n\n // Parse JSON\n const document: CanvasDocument = JSON.parse(text);\n\n // Validate structure\n this.validateDocument(document);\n\n // Check version compatibility\n if (!this.SUPPORTED_VERSIONS.includes(document.metadata.version)) {\n throw new Error(\n `Unsupported version: ${document.metadata.version}. ` +\n `Supported versions: ${this.SUPPORTED_VERSIONS.join(', ')}`\n );\n }\n\n // Handle version 1.0.0 (no artboards) - migrate to artboards\n if (document.metadata.version === '1.0.0') {\n return this.migrateV1Document(document as unknown as V1CanvasDocument);\n }\n\n // Deserialize artboards and elements\n const artboards: ArtboardElement[] = [];\n const allElements: (TextElement | ImageElement | GroupElement)[] = [];\n\n document.artboards.forEach((artboardData) => {\n // Create artboard\n const artboard = ArtboardElement.fromJSON({\n id: artboardData.id,\n name: artboardData.name,\n x: artboardData.x,\n y: artboardData.y,\n width: artboardData.width,\n height: artboardData.height,\n backgroundColor: artboardData.backgroundColor,\n elementIds: artboardData.elements.map((e) => e.id || ''),\n });\n\n // Deserialize elements for this artboard\n const elements = artboardData.elements\n .map((elementConfig) => {\n try {\n return ElementFactory.createFromJSON(elementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element) => element !== null) as (TextElement | ImageElement | GroupElement)[];\n\n artboards.push(artboard);\n allElements.push(...elements);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(allElements);\n\n return {\n success: true,\n artboards,\n elements: allElements,\n activeArtboardId: document.activeArtboardId,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Migrate v1 document (no artboards) to v2 (with artboards)\n */\n private static async migrateV1Document(document: V1CanvasDocument): Promise<ImportResult> {\n try {\n // V1 format: { metadata, canvas, elements }\n const elements = document.elements || [];\n\n // Create a default artboard containing all elements\n const artboard = new ArtboardElement({\n id: 'artboard-migrated',\n name: 'Artboard 1',\n x: 0,\n y: 0,\n width: document.canvas?.width || 1920,\n height: document.canvas?.height || 1080,\n backgroundColor: document.canvas?.backgroundColor || '#ffffff',\n });\n\n // Deserialize elements\n const deserializedElements = elements\n .map((elementConfig: Record<string, unknown>) => {\n try {\n return ElementFactory.createFromJSON(elementConfig as unknown as import('../types/index.js').AnyElementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element): element is TextElement | ImageElement | GroupElement => element !== null);\n\n // Add all element IDs to artboard\n deserializedElements.forEach((element) => {\n artboard.addElementId(element.id);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(deserializedElements);\n\n return {\n success: true,\n artboards: [artboard],\n elements: deserializedElements,\n activeArtboardId: artboard.id,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Migration failed',\n };\n }\n }\n\n /**\n * Import image file\n */\n static async importImage(file: File): Promise<ImageImportResult> {\n try {\n // Validate file type\n if (!file.type.startsWith('image/')) {\n throw new Error('File is not an image');\n }\n\n // Check file size (max 10MB)\n const maxSize = 10 * 1024 * 1024; // 10MB\n if (file.size > maxSize) {\n throw new Error('Image file is too large (max 10MB)');\n }\n\n // Read as data URL\n const dataUrl = await this.readFileAsDataURL(file);\n\n // Get image dimensions\n const { width, height } = await this.getImageDimensions(dataUrl);\n\n return {\n success: true,\n dataUrl,\n filename: file.name,\n width,\n height,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Validate document structure\n */\n private static validateDocument(document: unknown): asserts document is CanvasDocument {\n if (!document || typeof document !== 'object') {\n throw new Error('Invalid document');\n }\n const doc = document as Record<string, unknown>;\n if (!doc.metadata) {\n throw new Error('Missing metadata');\n }\n if (!(doc.metadata as Record<string, unknown>).version) {\n throw new Error('Missing version in metadata');\n }\n if (!doc.artboards && !doc.elements) {\n throw new Error('Missing artboards or elements array');\n }\n if (doc.artboards && !Array.isArray(doc.artboards)) {\n throw new Error('Invalid artboards array');\n }\n }\n\n /**\n * Read file as text\n */\n private static readFileAsText(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n }\n\n /**\n * Read file as data URL\n */\n private static readFileAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Get image dimensions from data URL\n */\n private static getImageDimensions(dataUrl: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.width, height: img.height });\n };\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = dataUrl;\n });\n }\n\n /**\n * Validate imported data before applying to state\n */\n static validateImportedData(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check for duplicate artboard IDs\n const artboardIds = new Set();\n artboards.forEach((artboard) => {\n if (artboardIds.has(artboard.id)) {\n errors.push(`Duplicate artboard ID: ${artboard.id}`);\n }\n artboardIds.add(artboard.id);\n });\n\n // Check for duplicate element IDs\n const elementIds = new Set();\n elements.forEach((element) => {\n if (elementIds.has(element.id)) {\n errors.push(`Duplicate element ID: ${element.id}`);\n }\n elementIds.add(element.id);\n });\n\n // Validate element-to-artboard references\n artboards.forEach((artboard) => {\n artboard.getElementIds().forEach((elementId: string) => {\n if (!elementIds.has(elementId)) {\n errors.push(`Artboard \"${artboard.name}\" references missing element: ${elementId}`);\n }\n });\n });\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Get import summary (for UI display before confirming)\n */\n static getImportSummary(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): {\n artboardCount: number;\n elementCount: number;\n artboardNames: string[];\n warnings: string[];\n } {\n const validation = this.validateImportedData(artboards, elements);\n\n return {\n artboardCount: artboards.length,\n elementCount: elements.length,\n artboardNames: artboards.map((a) => a.name),\n warnings: validation.errors,\n };\n }\n\n /**\n * Preload all images in parallel for fast artboard switching\n * Recursively finds all ImageElements (including those in groups)\n */\n private static async preloadAllImages(elements: (TextElement | ImageElement | GroupElement)[]): Promise<void> {\n const imageElements: ImageElement[] = [];\n\n // Recursively find all image elements\n const findImages = (el: TextElement | ImageElement | GroupElement) => {\n if (el.transformType === 'image') {\n imageElements.push(el as ImageElement);\n } else if (el.transformType === 'group' && 'children' in el) {\n (el as GroupElement).children.forEach((child) => findImages(child as TextElement | ImageElement | GroupElement));\n }\n };\n\n elements.forEach(findImages);\n\n // Wait for all images to load in parallel\n const loadPromises = imageElements.map((img: ImageElement) => {\n return new Promise<void>((resolve) => {\n if (img.imageLoaded) {\n resolve();\n } else if (img.imageElement) {\n // Image is currently loading\n const imgEl = img.imageElement;\n const onLoad = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve();\n };\n const onError = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve(); // Resolve even on error to not block other images\n };\n imgEl.addEventListener('load', onLoad);\n imgEl.addEventListener('error', onError);\n } else {\n resolve();\n }\n });\n });\n\n await Promise.all(loadPromises);\n }\n}\n\nexport default ImportManager;\n"],"names":["logger","createLogger","_ImportManager","file","text","document","artboards","allElements","artboardData","artboard","ArtboardElement","e","elements","elementConfig","ElementFactory","error","element","_a","_b","_c","deserializedElements","maxSize","dataUrl","width","height","doc","resolve","reject","reader","img","errors","artboardIds","elementIds","elementId","validation","a","imageElements","findImages","el","child","loadPromises","imgEl","onLoad","onError","ImportManager"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";const h=require("./ElementFactory-B7UOaJSD.cjs"),d=require("./HybridHistoryManager-BXD93pp8.cjs"),u=d.createLogger("ImportManager"),m=class m{static async importFromJSON(t){try{const r=await this.readFileAsText(t),a=JSON.parse(r);if(this.validateDocument(a),!this.SUPPORTED_VERSIONS.includes(a.metadata.version))throw new Error(`Unsupported version: ${a.metadata.version}. Supported versions: ${this.SUPPORTED_VERSIONS.join(", ")}`);if(a.metadata.version==="1.0.0")return this.migrateV1Document(a);const s=[],n=[];return a.artboards.forEach(e=>{const o=d.ArtboardElement.fromJSON({id:e.id,name:e.name,x:e.x,y:e.y,width:e.width,height:e.height,backgroundColor:e.backgroundColor,elementIds:e.elements.map(c=>c.id||"")}),i=e.elements.map(c=>{try{return h.ElementFactory.createFromJSON(c)}catch(g){return u.error("Failed to create element:",c,g),null}}).filter(c=>c!==null);s.push(o),n.push(...i)}),await this.preloadAllImages(n),{success:!0,artboards:s,elements:n,activeArtboardId:a.activeArtboardId}}catch(r){return{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}static async migrateV1Document(t){var r,a,s;try{const n=t.elements||[],e=new d.ArtboardElement({id:"artboard-migrated",name:"Artboard 1",x:0,y:0,width:((r=t.canvas)==null?void 0:r.width)||1920,height:((a=t.canvas)==null?void 0:a.height)||1080,backgroundColor:((s=t.canvas)==null?void 0:s.backgroundColor)||"#ffffff"}),o=n.map(i=>{try{return h.ElementFactory.createFromJSON(i)}catch(c){return u.error("Failed to create element:",i,c),null}}).filter(i=>i!==null);return o.forEach(i=>{e.addElementId(i.id)}),await this.preloadAllImages(o),{success:!0,artboards:[e],elements:o,activeArtboardId:e.id}}catch(n){return{success:!1,error:n instanceof Error?n.message:"Migration failed"}}}static async importImage(t){try{if(!t.type.startsWith("image/"))throw new Error("File is not an image");const r=10*1024*1024;if(t.size>r)throw new Error("Image file is too large (max 10MB)");const a=await this.readFileAsDataURL(t),{width:s,height:n}=await this.getImageDimensions(a);return{success:!0,dataUrl:a,filename:t.name,width:s,height:n}}catch(r){return{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}static validateDocument(t){if(!t||typeof t!="object")throw new Error("Invalid document");const r=t;if(!r.metadata)throw new Error("Missing metadata");if(!r.metadata.version)throw new Error("Missing version in metadata");if(!r.artboards&&!r.elements)throw new Error("Missing artboards or elements array");if(r.artboards&&!Array.isArray(r.artboards))throw new Error("Invalid artboards array")}static readFileAsText(t){return new Promise((r,a)=>{const s=new FileReader;s.onload=n=>{var e;return r((e=n.target)==null?void 0:e.result)},s.onerror=()=>a(new Error("Failed to read file")),s.readAsText(t)})}static readFileAsDataURL(t){return new Promise((r,a)=>{const s=new FileReader;s.onload=n=>{var e;return r((e=n.target)==null?void 0:e.result)},s.onerror=()=>a(new Error("Failed to read file")),s.readAsDataURL(t)})}static getImageDimensions(t){return new Promise((r,a)=>{const s=new Image;s.onload=()=>{r({width:s.width,height:s.height})},s.onerror=()=>a(new Error("Failed to load image")),s.src=t})}static validateImportedData(t,r){const a=[],s=new Set;t.forEach(e=>{s.has(e.id)&&a.push(`Duplicate artboard ID: ${e.id}`),s.add(e.id)});const n=new Set;return r.forEach(e=>{n.has(e.id)&&a.push(`Duplicate element ID: ${e.id}`),n.add(e.id)}),t.forEach(e=>{e.getElementIds().forEach(o=>{n.has(o)||a.push(`Artboard "${e.name}" references missing element: ${o}`)})}),{valid:a.length===0,errors:a}}static getImportSummary(t,r){const a=this.validateImportedData(t,r);return{artboardCount:t.length,elementCount:r.length,artboardNames:t.map(s=>s.name),warnings:a.errors}}static async preloadAllImages(t){const r=[],a=n=>{n.transformType==="image"?r.push(n):n.transformType==="group"&&"children"in n&&n.children.forEach(e=>a(e))};t.forEach(a);const s=r.map(n=>new Promise(e=>{if(n.imageLoaded)e();else if(n.imageElement){const o=n.imageElement,i=()=>{o.removeEventListener("load",i),o.removeEventListener("error",c),e()},c=()=>{o.removeEventListener("load",i),o.removeEventListener("error",c),e()};o.addEventListener("load",i),o.addEventListener("error",c)}else e()}));await Promise.all(s)}};m.SUPPORTED_VERSIONS=["1.0.0","2.0.0"];let l=m;exports.ImportManager=l;
2
- //# sourceMappingURL=ImportManager-BYwuK6n4.cjs.map
1
+ "use strict";const h=require("./ElementFactory-DEjwp-Wg.cjs"),d=require("./HybridHistoryManager-BXD93pp8.cjs"),u=d.createLogger("ImportManager"),m=class m{static async importFromJSON(t){try{const r=await this.readFileAsText(t),a=JSON.parse(r);if(this.validateDocument(a),!this.SUPPORTED_VERSIONS.includes(a.metadata.version))throw new Error(`Unsupported version: ${a.metadata.version}. Supported versions: ${this.SUPPORTED_VERSIONS.join(", ")}`);if(a.metadata.version==="1.0.0")return this.migrateV1Document(a);const s=[],n=[];return a.artboards.forEach(e=>{const o=d.ArtboardElement.fromJSON({id:e.id,name:e.name,x:e.x,y:e.y,width:e.width,height:e.height,backgroundColor:e.backgroundColor,elementIds:e.elements.map(c=>c.id||"")}),i=e.elements.map(c=>{try{return h.ElementFactory.createFromJSON(c)}catch(g){return u.error("Failed to create element:",c,g),null}}).filter(c=>c!==null);s.push(o),n.push(...i)}),await this.preloadAllImages(n),{success:!0,artboards:s,elements:n,activeArtboardId:a.activeArtboardId}}catch(r){return{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}static async migrateV1Document(t){var r,a,s;try{const n=t.elements||[],e=new d.ArtboardElement({id:"artboard-migrated",name:"Artboard 1",x:0,y:0,width:((r=t.canvas)==null?void 0:r.width)||1920,height:((a=t.canvas)==null?void 0:a.height)||1080,backgroundColor:((s=t.canvas)==null?void 0:s.backgroundColor)||"#ffffff"}),o=n.map(i=>{try{return h.ElementFactory.createFromJSON(i)}catch(c){return u.error("Failed to create element:",i,c),null}}).filter(i=>i!==null);return o.forEach(i=>{e.addElementId(i.id)}),await this.preloadAllImages(o),{success:!0,artboards:[e],elements:o,activeArtboardId:e.id}}catch(n){return{success:!1,error:n instanceof Error?n.message:"Migration failed"}}}static async importImage(t){try{if(!t.type.startsWith("image/"))throw new Error("File is not an image");const r=10*1024*1024;if(t.size>r)throw new Error("Image file is too large (max 10MB)");const a=await this.readFileAsDataURL(t),{width:s,height:n}=await this.getImageDimensions(a);return{success:!0,dataUrl:a,filename:t.name,width:s,height:n}}catch(r){return{success:!1,error:r instanceof Error?r.message:"Unknown error"}}}static validateDocument(t){if(!t||typeof t!="object")throw new Error("Invalid document");const r=t;if(!r.metadata)throw new Error("Missing metadata");if(!r.metadata.version)throw new Error("Missing version in metadata");if(!r.artboards&&!r.elements)throw new Error("Missing artboards or elements array");if(r.artboards&&!Array.isArray(r.artboards))throw new Error("Invalid artboards array")}static readFileAsText(t){return new Promise((r,a)=>{const s=new FileReader;s.onload=n=>{var e;return r((e=n.target)==null?void 0:e.result)},s.onerror=()=>a(new Error("Failed to read file")),s.readAsText(t)})}static readFileAsDataURL(t){return new Promise((r,a)=>{const s=new FileReader;s.onload=n=>{var e;return r((e=n.target)==null?void 0:e.result)},s.onerror=()=>a(new Error("Failed to read file")),s.readAsDataURL(t)})}static getImageDimensions(t){return new Promise((r,a)=>{const s=new Image;s.onload=()=>{r({width:s.width,height:s.height})},s.onerror=()=>a(new Error("Failed to load image")),s.src=t})}static validateImportedData(t,r){const a=[],s=new Set;t.forEach(e=>{s.has(e.id)&&a.push(`Duplicate artboard ID: ${e.id}`),s.add(e.id)});const n=new Set;return r.forEach(e=>{n.has(e.id)&&a.push(`Duplicate element ID: ${e.id}`),n.add(e.id)}),t.forEach(e=>{e.getElementIds().forEach(o=>{n.has(o)||a.push(`Artboard "${e.name}" references missing element: ${o}`)})}),{valid:a.length===0,errors:a}}static getImportSummary(t,r){const a=this.validateImportedData(t,r);return{artboardCount:t.length,elementCount:r.length,artboardNames:t.map(s=>s.name),warnings:a.errors}}static async preloadAllImages(t){const r=[],a=n=>{n.transformType==="image"?r.push(n):n.transformType==="group"&&"children"in n&&n.children.forEach(e=>a(e))};t.forEach(a);const s=r.map(n=>new Promise(e=>{if(n.imageLoaded)e();else if(n.imageElement){const o=n.imageElement,i=()=>{o.removeEventListener("load",i),o.removeEventListener("error",c),e()},c=()=>{o.removeEventListener("load",i),o.removeEventListener("error",c),e()};o.addEventListener("load",i),o.addEventListener("error",c)}else e()}));await Promise.all(s)}};m.SUPPORTED_VERSIONS=["1.0.0","2.0.0"];let l=m;exports.ImportManager=l;
2
+ //# sourceMappingURL=ImportManager-wSzrR-5a.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ImportManager-BYwuK6n4.cjs","sources":["../src/utils/ImportManager.ts"],"sourcesContent":["/**\n * ImportManager - Handles importing workspace from JSON and images\n */\n\nimport { ElementFactory } from '../core/ElementFactory.js';\nimport { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { CanvasDocument } from './ExportManager.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { GroupElement } from '../core/GroupElement.js';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('ImportManager');\n\n/** V1 document format (pre-artboard) */\ninterface V1CanvasDocument {\n metadata: { version: string };\n canvas?: { width?: number; height?: number; backgroundColor?: string };\n elements?: Record<string, unknown>[];\n}\n\nexport interface ImportResult {\n success: boolean;\n artboards?: ArtboardElement[];\n elements?: (TextElement | ImageElement | GroupElement)[];\n activeArtboardId?: string | null;\n error?: string;\n}\n\nexport interface ImageImportResult {\n success: boolean;\n dataUrl?: string;\n filename?: string;\n width?: number;\n height?: number;\n error?: string;\n}\n\nexport class ImportManager {\n private static readonly SUPPORTED_VERSIONS = ['1.0.0', '2.0.0'];\n\n /**\n * Import workspace from JSON file\n */\n static async importFromJSON(file: File): Promise<ImportResult> {\n try {\n // Read file as text\n const text = await this.readFileAsText(file);\n\n // Parse JSON\n const document: CanvasDocument = JSON.parse(text);\n\n // Validate structure\n this.validateDocument(document);\n\n // Check version compatibility\n if (!this.SUPPORTED_VERSIONS.includes(document.metadata.version)) {\n throw new Error(\n `Unsupported version: ${document.metadata.version}. ` +\n `Supported versions: ${this.SUPPORTED_VERSIONS.join(', ')}`\n );\n }\n\n // Handle version 1.0.0 (no artboards) - migrate to artboards\n if (document.metadata.version === '1.0.0') {\n return this.migrateV1Document(document as unknown as V1CanvasDocument);\n }\n\n // Deserialize artboards and elements\n const artboards: ArtboardElement[] = [];\n const allElements: (TextElement | ImageElement | GroupElement)[] = [];\n\n document.artboards.forEach((artboardData) => {\n // Create artboard\n const artboard = ArtboardElement.fromJSON({\n id: artboardData.id,\n name: artboardData.name,\n x: artboardData.x,\n y: artboardData.y,\n width: artboardData.width,\n height: artboardData.height,\n backgroundColor: artboardData.backgroundColor,\n elementIds: artboardData.elements.map((e) => e.id || ''),\n });\n\n // Deserialize elements for this artboard\n const elements = artboardData.elements\n .map((elementConfig) => {\n try {\n return ElementFactory.createFromJSON(elementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element) => element !== null) as (TextElement | ImageElement | GroupElement)[];\n\n artboards.push(artboard);\n allElements.push(...elements);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(allElements);\n\n return {\n success: true,\n artboards,\n elements: allElements,\n activeArtboardId: document.activeArtboardId,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Migrate v1 document (no artboards) to v2 (with artboards)\n */\n private static async migrateV1Document(document: V1CanvasDocument): Promise<ImportResult> {\n try {\n // V1 format: { metadata, canvas, elements }\n const elements = document.elements || [];\n\n // Create a default artboard containing all elements\n const artboard = new ArtboardElement({\n id: 'artboard-migrated',\n name: 'Artboard 1',\n x: 0,\n y: 0,\n width: document.canvas?.width || 1920,\n height: document.canvas?.height || 1080,\n backgroundColor: document.canvas?.backgroundColor || '#ffffff',\n });\n\n // Deserialize elements\n const deserializedElements = elements\n .map((elementConfig: Record<string, unknown>) => {\n try {\n return ElementFactory.createFromJSON(elementConfig as unknown as import('../types/index.js').AnyElementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element): element is TextElement | ImageElement | GroupElement => element !== null);\n\n // Add all element IDs to artboard\n deserializedElements.forEach((element) => {\n artboard.addElementId(element.id);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(deserializedElements);\n\n return {\n success: true,\n artboards: [artboard],\n elements: deserializedElements,\n activeArtboardId: artboard.id,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Migration failed',\n };\n }\n }\n\n /**\n * Import image file\n */\n static async importImage(file: File): Promise<ImageImportResult> {\n try {\n // Validate file type\n if (!file.type.startsWith('image/')) {\n throw new Error('File is not an image');\n }\n\n // Check file size (max 10MB)\n const maxSize = 10 * 1024 * 1024; // 10MB\n if (file.size > maxSize) {\n throw new Error('Image file is too large (max 10MB)');\n }\n\n // Read as data URL\n const dataUrl = await this.readFileAsDataURL(file);\n\n // Get image dimensions\n const { width, height } = await this.getImageDimensions(dataUrl);\n\n return {\n success: true,\n dataUrl,\n filename: file.name,\n width,\n height,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Validate document structure\n */\n private static validateDocument(document: unknown): asserts document is CanvasDocument {\n if (!document || typeof document !== 'object') {\n throw new Error('Invalid document');\n }\n const doc = document as Record<string, unknown>;\n if (!doc.metadata) {\n throw new Error('Missing metadata');\n }\n if (!(doc.metadata as Record<string, unknown>).version) {\n throw new Error('Missing version in metadata');\n }\n if (!doc.artboards && !doc.elements) {\n throw new Error('Missing artboards or elements array');\n }\n if (doc.artboards && !Array.isArray(doc.artboards)) {\n throw new Error('Invalid artboards array');\n }\n }\n\n /**\n * Read file as text\n */\n private static readFileAsText(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n }\n\n /**\n * Read file as data URL\n */\n private static readFileAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Get image dimensions from data URL\n */\n private static getImageDimensions(dataUrl: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.width, height: img.height });\n };\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = dataUrl;\n });\n }\n\n /**\n * Validate imported data before applying to state\n */\n static validateImportedData(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check for duplicate artboard IDs\n const artboardIds = new Set();\n artboards.forEach((artboard) => {\n if (artboardIds.has(artboard.id)) {\n errors.push(`Duplicate artboard ID: ${artboard.id}`);\n }\n artboardIds.add(artboard.id);\n });\n\n // Check for duplicate element IDs\n const elementIds = new Set();\n elements.forEach((element) => {\n if (elementIds.has(element.id)) {\n errors.push(`Duplicate element ID: ${element.id}`);\n }\n elementIds.add(element.id);\n });\n\n // Validate element-to-artboard references\n artboards.forEach((artboard) => {\n artboard.getElementIds().forEach((elementId: string) => {\n if (!elementIds.has(elementId)) {\n errors.push(`Artboard \"${artboard.name}\" references missing element: ${elementId}`);\n }\n });\n });\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Get import summary (for UI display before confirming)\n */\n static getImportSummary(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): {\n artboardCount: number;\n elementCount: number;\n artboardNames: string[];\n warnings: string[];\n } {\n const validation = this.validateImportedData(artboards, elements);\n\n return {\n artboardCount: artboards.length,\n elementCount: elements.length,\n artboardNames: artboards.map((a) => a.name),\n warnings: validation.errors,\n };\n }\n\n /**\n * Preload all images in parallel for fast artboard switching\n * Recursively finds all ImageElements (including those in groups)\n */\n private static async preloadAllImages(elements: (TextElement | ImageElement | GroupElement)[]): Promise<void> {\n const imageElements: ImageElement[] = [];\n\n // Recursively find all image elements\n const findImages = (el: TextElement | ImageElement | GroupElement) => {\n if (el.transformType === 'image') {\n imageElements.push(el as ImageElement);\n } else if (el.transformType === 'group' && 'children' in el) {\n (el as GroupElement).children.forEach((child) => findImages(child as TextElement | ImageElement | GroupElement));\n }\n };\n\n elements.forEach(findImages);\n\n // Wait for all images to load in parallel\n const loadPromises = imageElements.map((img: ImageElement) => {\n return new Promise<void>((resolve) => {\n if (img.imageLoaded) {\n resolve();\n } else if (img.imageElement) {\n // Image is currently loading\n const imgEl = img.imageElement;\n const onLoad = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve();\n };\n const onError = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve(); // Resolve even on error to not block other images\n };\n imgEl.addEventListener('load', onLoad);\n imgEl.addEventListener('error', onError);\n } else {\n resolve();\n }\n });\n });\n\n await Promise.all(loadPromises);\n }\n}\n\nexport default ImportManager;\n"],"names":["logger","createLogger","_ImportManager","file","text","document","artboards","allElements","artboardData","artboard","ArtboardElement","e","elements","elementConfig","ElementFactory","error","element","_a","_b","_c","deserializedElements","maxSize","dataUrl","width","height","doc","resolve","reject","reader","img","errors","artboardIds","elementIds","elementId","validation","a","imageElements","findImages","el","child","loadPromises","imgEl","onLoad","onError","ImportManager"],"mappings":"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"}
1
+ {"version":3,"file":"ImportManager-wSzrR-5a.cjs","sources":["../src/utils/ImportManager.ts"],"sourcesContent":["/**\n * ImportManager - Handles importing workspace from JSON and images\n */\n\nimport { ElementFactory } from '../core/ElementFactory.js';\nimport { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { CanvasDocument } from './ExportManager.js';\nimport type { TextElement } from '../core/TextElement.js';\nimport type { ImageElement } from '../core/ImageElement.js';\nimport type { GroupElement } from '../core/GroupElement.js';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('ImportManager');\n\n/** V1 document format (pre-artboard) */\ninterface V1CanvasDocument {\n metadata: { version: string };\n canvas?: { width?: number; height?: number; backgroundColor?: string };\n elements?: Record<string, unknown>[];\n}\n\nexport interface ImportResult {\n success: boolean;\n artboards?: ArtboardElement[];\n elements?: (TextElement | ImageElement | GroupElement)[];\n activeArtboardId?: string | null;\n error?: string;\n}\n\nexport interface ImageImportResult {\n success: boolean;\n dataUrl?: string;\n filename?: string;\n width?: number;\n height?: number;\n error?: string;\n}\n\nexport class ImportManager {\n private static readonly SUPPORTED_VERSIONS = ['1.0.0', '2.0.0'];\n\n /**\n * Import workspace from JSON file\n */\n static async importFromJSON(file: File): Promise<ImportResult> {\n try {\n // Read file as text\n const text = await this.readFileAsText(file);\n\n // Parse JSON\n const document: CanvasDocument = JSON.parse(text);\n\n // Validate structure\n this.validateDocument(document);\n\n // Check version compatibility\n if (!this.SUPPORTED_VERSIONS.includes(document.metadata.version)) {\n throw new Error(\n `Unsupported version: ${document.metadata.version}. ` +\n `Supported versions: ${this.SUPPORTED_VERSIONS.join(', ')}`\n );\n }\n\n // Handle version 1.0.0 (no artboards) - migrate to artboards\n if (document.metadata.version === '1.0.0') {\n return this.migrateV1Document(document as unknown as V1CanvasDocument);\n }\n\n // Deserialize artboards and elements\n const artboards: ArtboardElement[] = [];\n const allElements: (TextElement | ImageElement | GroupElement)[] = [];\n\n document.artboards.forEach((artboardData) => {\n // Create artboard\n const artboard = ArtboardElement.fromJSON({\n id: artboardData.id,\n name: artboardData.name,\n x: artboardData.x,\n y: artboardData.y,\n width: artboardData.width,\n height: artboardData.height,\n backgroundColor: artboardData.backgroundColor,\n elementIds: artboardData.elements.map((e) => e.id || ''),\n });\n\n // Deserialize elements for this artboard\n const elements = artboardData.elements\n .map((elementConfig) => {\n try {\n return ElementFactory.createFromJSON(elementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element) => element !== null) as (TextElement | ImageElement | GroupElement)[];\n\n artboards.push(artboard);\n allElements.push(...elements);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(allElements);\n\n return {\n success: true,\n artboards,\n elements: allElements,\n activeArtboardId: document.activeArtboardId,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Migrate v1 document (no artboards) to v2 (with artboards)\n */\n private static async migrateV1Document(document: V1CanvasDocument): Promise<ImportResult> {\n try {\n // V1 format: { metadata, canvas, elements }\n const elements = document.elements || [];\n\n // Create a default artboard containing all elements\n const artboard = new ArtboardElement({\n id: 'artboard-migrated',\n name: 'Artboard 1',\n x: 0,\n y: 0,\n width: document.canvas?.width || 1920,\n height: document.canvas?.height || 1080,\n backgroundColor: document.canvas?.backgroundColor || '#ffffff',\n });\n\n // Deserialize elements\n const deserializedElements = elements\n .map((elementConfig: Record<string, unknown>) => {\n try {\n return ElementFactory.createFromJSON(elementConfig as unknown as import('../types/index.js').AnyElementConfig);\n } catch (error) {\n logger.error('Failed to create element:', elementConfig, error);\n return null;\n }\n })\n .filter((element): element is TextElement | ImageElement | GroupElement => element !== null);\n\n // Add all element IDs to artboard\n deserializedElements.forEach((element) => {\n artboard.addElementId(element.id);\n });\n\n // PERFORMANCE: Wait for all images to load in parallel before returning\n await this.preloadAllImages(deserializedElements);\n\n return {\n success: true,\n artboards: [artboard],\n elements: deserializedElements,\n activeArtboardId: artboard.id,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Migration failed',\n };\n }\n }\n\n /**\n * Import image file\n */\n static async importImage(file: File): Promise<ImageImportResult> {\n try {\n // Validate file type\n if (!file.type.startsWith('image/')) {\n throw new Error('File is not an image');\n }\n\n // Check file size (max 10MB)\n const maxSize = 10 * 1024 * 1024; // 10MB\n if (file.size > maxSize) {\n throw new Error('Image file is too large (max 10MB)');\n }\n\n // Read as data URL\n const dataUrl = await this.readFileAsDataURL(file);\n\n // Get image dimensions\n const { width, height } = await this.getImageDimensions(dataUrl);\n\n return {\n success: true,\n dataUrl,\n filename: file.name,\n width,\n height,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n /**\n * Validate document structure\n */\n private static validateDocument(document: unknown): asserts document is CanvasDocument {\n if (!document || typeof document !== 'object') {\n throw new Error('Invalid document');\n }\n const doc = document as Record<string, unknown>;\n if (!doc.metadata) {\n throw new Error('Missing metadata');\n }\n if (!(doc.metadata as Record<string, unknown>).version) {\n throw new Error('Missing version in metadata');\n }\n if (!doc.artboards && !doc.elements) {\n throw new Error('Missing artboards or elements array');\n }\n if (doc.artboards && !Array.isArray(doc.artboards)) {\n throw new Error('Invalid artboards array');\n }\n }\n\n /**\n * Read file as text\n */\n private static readFileAsText(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n }\n\n /**\n * Read file as data URL\n */\n private static readFileAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target?.result as string);\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Get image dimensions from data URL\n */\n private static getImageDimensions(dataUrl: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.width, height: img.height });\n };\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = dataUrl;\n });\n }\n\n /**\n * Validate imported data before applying to state\n */\n static validateImportedData(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check for duplicate artboard IDs\n const artboardIds = new Set();\n artboards.forEach((artboard) => {\n if (artboardIds.has(artboard.id)) {\n errors.push(`Duplicate artboard ID: ${artboard.id}`);\n }\n artboardIds.add(artboard.id);\n });\n\n // Check for duplicate element IDs\n const elementIds = new Set();\n elements.forEach((element) => {\n if (elementIds.has(element.id)) {\n errors.push(`Duplicate element ID: ${element.id}`);\n }\n elementIds.add(element.id);\n });\n\n // Validate element-to-artboard references\n artboards.forEach((artboard) => {\n artboard.getElementIds().forEach((elementId: string) => {\n if (!elementIds.has(elementId)) {\n errors.push(`Artboard \"${artboard.name}\" references missing element: ${elementId}`);\n }\n });\n });\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Get import summary (for UI display before confirming)\n */\n static getImportSummary(\n artboards: ArtboardElement[],\n elements: (TextElement | ImageElement | GroupElement)[]\n ): {\n artboardCount: number;\n elementCount: number;\n artboardNames: string[];\n warnings: string[];\n } {\n const validation = this.validateImportedData(artboards, elements);\n\n return {\n artboardCount: artboards.length,\n elementCount: elements.length,\n artboardNames: artboards.map((a) => a.name),\n warnings: validation.errors,\n };\n }\n\n /**\n * Preload all images in parallel for fast artboard switching\n * Recursively finds all ImageElements (including those in groups)\n */\n private static async preloadAllImages(elements: (TextElement | ImageElement | GroupElement)[]): Promise<void> {\n const imageElements: ImageElement[] = [];\n\n // Recursively find all image elements\n const findImages = (el: TextElement | ImageElement | GroupElement) => {\n if (el.transformType === 'image') {\n imageElements.push(el as ImageElement);\n } else if (el.transformType === 'group' && 'children' in el) {\n (el as GroupElement).children.forEach((child) => findImages(child as TextElement | ImageElement | GroupElement));\n }\n };\n\n elements.forEach(findImages);\n\n // Wait for all images to load in parallel\n const loadPromises = imageElements.map((img: ImageElement) => {\n return new Promise<void>((resolve) => {\n if (img.imageLoaded) {\n resolve();\n } else if (img.imageElement) {\n // Image is currently loading\n const imgEl = img.imageElement;\n const onLoad = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve();\n };\n const onError = () => {\n imgEl.removeEventListener('load', onLoad);\n imgEl.removeEventListener('error', onError);\n resolve(); // Resolve even on error to not block other images\n };\n imgEl.addEventListener('load', onLoad);\n imgEl.addEventListener('error', onError);\n } else {\n resolve();\n }\n });\n });\n\n await Promise.all(loadPromises);\n }\n}\n\nexport default ImportManager;\n"],"names":["logger","createLogger","_ImportManager","file","text","document","artboards","allElements","artboardData","artboard","ArtboardElement","e","elements","elementConfig","ElementFactory","error","element","_a","_b","_c","deserializedElements","maxSize","dataUrl","width","height","doc","resolve","reject","reader","img","errors","artboardIds","elementIds","elementId","validation","a","imageElements","findImages","el","child","loadPromises","imgEl","onLoad","onError","ImportManager"],"mappings":"+GAYMA,EAASC,EAAAA,aAAa,eAAe,EA0B9BC,EAAN,MAAMA,CAAc,CAMzB,aAAa,eAAeC,EAAmC,CAC7D,GAAI,CAEF,MAAMC,EAAO,MAAM,KAAK,eAAeD,CAAI,EAGrCE,EAA2B,KAAK,MAAMD,CAAI,EAMhD,GAHA,KAAK,iBAAiBC,CAAQ,EAG1B,CAAC,KAAK,mBAAmB,SAASA,EAAS,SAAS,OAAO,EAC7D,MAAM,IAAI,MACR,wBAAwBA,EAAS,SAAS,OAAO,yBACxB,KAAK,mBAAmB,KAAK,IAAI,CAAC,EAAA,EAK/D,GAAIA,EAAS,SAAS,UAAY,QAChC,OAAO,KAAK,kBAAkBA,CAAuC,EAIvE,MAAMC,EAA+B,CAAA,EAC/BC,EAA6D,CAAA,EAEnE,OAAAF,EAAS,UAAU,QAASG,GAAiB,CAE3C,MAAMC,EAAWC,EAAAA,gBAAgB,SAAS,CACxC,GAAIF,EAAa,GACjB,KAAMA,EAAa,KACnB,EAAGA,EAAa,EAChB,EAAGA,EAAa,EAChB,MAAOA,EAAa,MACpB,OAAQA,EAAa,OACrB,gBAAiBA,EAAa,gBAC9B,WAAYA,EAAa,SAAS,IAAKG,GAAMA,EAAE,IAAM,EAAE,CAAA,CACxD,EAGKC,EAAWJ,EAAa,SAC3B,IAAKK,GAAkB,CACtB,GAAI,CACF,OAAOC,EAAAA,eAAe,eAAeD,CAAa,CACpD,OAASE,EAAO,CACd,OAAAf,EAAO,MAAM,4BAA6Ba,EAAeE,CAAK,EACvD,IACT,CACF,CAAC,EACA,OAAQC,GAAYA,IAAY,IAAI,EAEvCV,EAAU,KAAKG,CAAQ,EACvBF,EAAY,KAAK,GAAGK,CAAQ,CAC9B,CAAC,EAGD,MAAM,KAAK,iBAAiBL,CAAW,EAEhC,CACL,QAAS,GACT,UAAAD,EACA,SAAUC,EACV,iBAAkBF,EAAS,gBAAA,CAE/B,OAASU,EAAO,CACd,MAAO,CACL,QAAS,GACT,MAAOA,aAAiB,MAAQA,EAAM,QAAU,eAAA,CAEpD,CACF,CAKA,aAAqB,kBAAkBV,EAAmD,WACxF,GAAI,CAEF,MAAMO,EAAWP,EAAS,UAAY,CAAA,EAGhCI,EAAW,IAAIC,kBAAgB,CACnC,GAAI,oBACJ,KAAM,aACN,EAAG,EACH,EAAG,EACH,QAAOO,EAAAZ,EAAS,SAAT,YAAAY,EAAiB,QAAS,KACjC,SAAQC,EAAAb,EAAS,SAAT,YAAAa,EAAiB,SAAU,KACnC,kBAAiBC,EAAAd,EAAS,SAAT,YAAAc,EAAiB,kBAAmB,SAAA,CACtD,EAGKC,EAAuBR,EAC1B,IAAKC,GAA2C,CAC/C,GAAI,CACF,OAAOC,EAAAA,eAAe,eAAeD,CAAwE,CAC/G,OAASE,EAAO,CACd,OAAAf,EAAO,MAAM,4BAA6Ba,EAAeE,CAAK,EACvD,IACT,CACF,CAAC,EACA,OAAQC,GAAkEA,IAAY,IAAI,EAG7F,OAAAI,EAAqB,QAASJ,GAAY,CACxCP,EAAS,aAAaO,EAAQ,EAAE,CAClC,CAAC,EAGD,MAAM,KAAK,iBAAiBI,CAAoB,EAEzC,CACL,QAAS,GACT,UAAW,CAACX,CAAQ,EACpB,SAAUW,EACV,iBAAkBX,EAAS,EAAA,CAE/B,OAASM,EAAO,CACd,MAAO,CACL,QAAS,GACT,MAAOA,aAAiB,MAAQA,EAAM,QAAU,kBAAA,CAEpD,CACF,CAKA,aAAa,YAAYZ,EAAwC,CAC/D,GAAI,CAEF,GAAI,CAACA,EAAK,KAAK,WAAW,QAAQ,EAChC,MAAM,IAAI,MAAM,sBAAsB,EAIxC,MAAMkB,EAAU,GAAK,KAAO,KAC5B,GAAIlB,EAAK,KAAOkB,EACd,MAAM,IAAI,MAAM,oCAAoC,EAItD,MAAMC,EAAU,MAAM,KAAK,kBAAkBnB,CAAI,EAG3C,CAAE,MAAAoB,EAAO,OAAAC,CAAA,EAAW,MAAM,KAAK,mBAAmBF,CAAO,EAE/D,MAAO,CACL,QAAS,GACT,QAAAA,EACA,SAAUnB,EAAK,KACf,MAAAoB,EACA,OAAAC,CAAA,CAEJ,OAAST,EAAO,CACd,MAAO,CACL,QAAS,GACT,MAAOA,aAAiB,MAAQA,EAAM,QAAU,eAAA,CAEpD,CACF,CAKA,OAAe,iBAAiBV,EAAuD,CACrF,GAAI,CAACA,GAAY,OAAOA,GAAa,SACnC,MAAM,IAAI,MAAM,kBAAkB,EAEpC,MAAMoB,EAAMpB,EACZ,GAAI,CAACoB,EAAI,SACP,MAAM,IAAI,MAAM,kBAAkB,EAEpC,GAAI,CAAEA,EAAI,SAAqC,QAC7C,MAAM,IAAI,MAAM,6BAA6B,EAE/C,GAAI,CAACA,EAAI,WAAa,CAACA,EAAI,SACzB,MAAM,IAAI,MAAM,qCAAqC,EAEvD,GAAIA,EAAI,WAAa,CAAC,MAAM,QAAQA,EAAI,SAAS,EAC/C,MAAM,IAAI,MAAM,yBAAyB,CAE7C,CAKA,OAAe,eAAetB,EAA6B,CACzD,OAAO,IAAI,QAAQ,CAACuB,EAASC,IAAW,CACtC,MAAMC,EAAS,IAAI,WACnBA,EAAO,OAAUjB,GAAA,OAAM,OAAAe,GAAQT,EAAAN,EAAE,SAAF,YAAAM,EAAU,MAAgB,GACzDW,EAAO,QAAU,IAAMD,EAAO,IAAI,MAAM,qBAAqB,CAAC,EAC9DC,EAAO,WAAWzB,CAAI,CACxB,CAAC,CACH,CAKA,OAAe,kBAAkBA,EAA6B,CAC5D,OAAO,IAAI,QAAQ,CAACuB,EAASC,IAAW,CACtC,MAAMC,EAAS,IAAI,WACnBA,EAAO,OAAUjB,GAAA,OAAM,OAAAe,GAAQT,EAAAN,EAAE,SAAF,YAAAM,EAAU,MAAgB,GACzDW,EAAO,QAAU,IAAMD,EAAO,IAAI,MAAM,qBAAqB,CAAC,EAC9DC,EAAO,cAAczB,CAAI,CAC3B,CAAC,CACH,CAKA,OAAe,mBAAmBmB,EAA6D,CAC7F,OAAO,IAAI,QAAQ,CAACI,EAASC,IAAW,CACtC,MAAME,EAAM,IAAI,MAChBA,EAAI,OAAS,IAAM,CACjBH,EAAQ,CAAE,MAAOG,EAAI,MAAO,OAAQA,EAAI,OAAQ,CAClD,EACAA,EAAI,QAAU,IAAMF,EAAO,IAAI,MAAM,sBAAsB,CAAC,EAC5DE,EAAI,IAAMP,CACZ,CAAC,CACH,CAKA,OAAO,qBACLhB,EACAM,EACsC,CACtC,MAAMkB,EAAmB,CAAA,EAGnBC,MAAkB,IACxBzB,EAAU,QAASG,GAAa,CAC1BsB,EAAY,IAAItB,EAAS,EAAE,GAC7BqB,EAAO,KAAK,0BAA0BrB,EAAS,EAAE,EAAE,EAErDsB,EAAY,IAAItB,EAAS,EAAE,CAC7B,CAAC,EAGD,MAAMuB,MAAiB,IACvB,OAAApB,EAAS,QAASI,GAAY,CACxBgB,EAAW,IAAIhB,EAAQ,EAAE,GAC3Bc,EAAO,KAAK,yBAAyBd,EAAQ,EAAE,EAAE,EAEnDgB,EAAW,IAAIhB,EAAQ,EAAE,CAC3B,CAAC,EAGDV,EAAU,QAASG,GAAa,CAC9BA,EAAS,cAAA,EAAgB,QAASwB,GAAsB,CACjDD,EAAW,IAAIC,CAAS,GAC3BH,EAAO,KAAK,aAAarB,EAAS,IAAI,iCAAiCwB,CAAS,EAAE,CAEtF,CAAC,CACH,CAAC,EAEM,CACL,MAAOH,EAAO,SAAW,EACzB,OAAAA,CAAA,CAEJ,CAKA,OAAO,iBACLxB,EACAM,EAMA,CACA,MAAMsB,EAAa,KAAK,qBAAqB5B,EAAWM,CAAQ,EAEhE,MAAO,CACL,cAAeN,EAAU,OACzB,aAAcM,EAAS,OACvB,cAAeN,EAAU,IAAK6B,GAAMA,EAAE,IAAI,EAC1C,SAAUD,EAAW,MAAA,CAEzB,CAMA,aAAqB,iBAAiBtB,EAAwE,CAC5G,MAAMwB,EAAgC,CAAA,EAGhCC,EAAcC,GAAkD,CAChEA,EAAG,gBAAkB,QACvBF,EAAc,KAAKE,CAAkB,EAC5BA,EAAG,gBAAkB,SAAW,aAAcA,GACtDA,EAAoB,SAAS,QAASC,GAAUF,EAAWE,CAAkD,CAAC,CAEnH,EAEA3B,EAAS,QAAQyB,CAAU,EAG3B,MAAMG,EAAeJ,EAAc,IAAKP,GAC/B,IAAI,QAAeH,GAAY,CACpC,GAAIG,EAAI,YACNH,EAAA,UACSG,EAAI,aAAc,CAE3B,MAAMY,EAAQZ,EAAI,aACZa,EAAS,IAAM,CACnBD,EAAM,oBAAoB,OAAQC,CAAM,EACxCD,EAAM,oBAAoB,QAASE,CAAO,EAC1CjB,EAAA,CACF,EACMiB,EAAU,IAAM,CACpBF,EAAM,oBAAoB,OAAQC,CAAM,EACxCD,EAAM,oBAAoB,QAASE,CAAO,EAC1CjB,EAAA,CACF,EACAe,EAAM,iBAAiB,OAAQC,CAAM,EACrCD,EAAM,iBAAiB,QAASE,CAAO,CACzC,MACEjB,EAAA,CAEJ,CAAC,CACF,EAED,MAAM,QAAQ,IAAIc,CAAY,CAChC,CACF,EAnVEtC,EAAwB,mBAAqB,CAAC,QAAS,OAAO,EADzD,IAAM0C,EAAN1C"}