@biela.dev/devices 1.5.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/android/index.cjs +21 -21
- package/dist/android/index.d.cts +75 -75
- package/dist/android/index.d.ts +75 -75
- package/dist/android/index.js +1 -1
- package/dist/{chunk-QQFC4CAP.js → chunk-76PRN3YN.js} +216 -216
- package/dist/chunk-76PRN3YN.js.map +1 -0
- package/dist/chunk-E2ICKMKH.js +2038 -0
- package/dist/chunk-E2ICKMKH.js.map +1 -0
- package/dist/{chunk-BXBG5BY7.cjs → chunk-FOTZN6UL.cjs} +216 -216
- package/dist/chunk-FOTZN6UL.cjs.map +1 -0
- package/dist/chunk-HF6B72Z5.cjs +2065 -0
- package/dist/chunk-HF6B72Z5.cjs.map +1 -0
- package/dist/index.cjs +79 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/ios/index.cjs +33 -25
- package/dist/ios/index.d.cts +37 -53
- package/dist/ios/index.d.ts +37 -53
- package/dist/ios/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-BXBG5BY7.cjs.map +0 -1
- package/dist/chunk-DGX4WRAK.js +0 -1749
- package/dist/chunk-DGX4WRAK.js.map +0 -1
- package/dist/chunk-OI46UKOY.cjs +0 -1774
- package/dist/chunk-OI46UKOY.cjs.map +0 -1
- package/dist/chunk-QQFC4CAP.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/custom/device-registry.ts","../src/registry.ts","../src/contract.ts","../src/svg/parse-dimensions.ts","../src/svg/normalize.ts","../src/svg/parse-contract.ts","../src/svg/validate.ts","../src/svg/scope-ids.ts","../src/svg/auto-detect-zones.ts"],"names":["IPHONE_17_PRO_MAX_META","IPHONE_17_PRO_META","IPHONE_AIR_META","IPHONE_16_META","IPHONE_16E_META","IPHONE_SE_3_META","GALAXY_S25_ULTRA_META","GALAXY_S25_META","GALAXY_S25_EDGE_META","PIXEL_9_PRO_XL_META","PIXEL_9_PRO_META","IPHONE_17_PRO_MAX_LAYOUT","IPHONE_17_PRO_LAYOUT","IPHONE_AIR_LAYOUT","IPHONE_16_LAYOUT","IPHONE_16E_LAYOUT","IPHONE_SE_3_LAYOUT","GALAXY_S25_ULTRA_LAYOUT","GALAXY_S25_LAYOUT","GALAXY_S25_EDGE_LAYOUT","PIXEL_9_PRO_XL_LAYOUT","PIXEL_9_PRO_LAYOUT"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Custom device registry — stores user-imported devices in localStorage.\n *\n * Provides CRUD operations for custom devices, persistence, and export/import.\n * Custom devices are stored alongside built-in devices but tracked separately.\n */\n\nimport type { RegisteredDevice, DeviceMeta, DeviceLayoutContract } from \"../types\";\n\nconst STORAGE_KEY = \"bielaframe-custom-devices\";\n\nexport class DeviceRegistry {\n private devices: Map<string, RegisteredDevice> = new Map();\n private storage: Storage | null;\n\n constructor(storage?: Storage | null) {\n this.storage = storage ?? (typeof localStorage !== \"undefined\" ? localStorage : null);\n this.load();\n }\n\n /** Register or update a custom device */\n register(device: RegisteredDevice): void {\n this.devices.set(device.meta.id, {\n ...device,\n source: \"custom\",\n registeredAt: device.registeredAt || new Date().toISOString(),\n });\n this.save();\n }\n\n /** Get a custom device by ID */\n get(deviceId: string): RegisteredDevice | undefined {\n return this.devices.get(deviceId);\n }\n\n /** Get the metadata for a custom device */\n getMeta(deviceId: string): DeviceMeta | undefined {\n return this.devices.get(deviceId)?.meta;\n }\n\n /** Get the contract for a custom device */\n getContract(deviceId: string): DeviceLayoutContract | undefined {\n return this.devices.get(deviceId)?.contract;\n }\n\n /** List all custom devices */\n list(): RegisteredDevice[] {\n return Array.from(this.devices.values());\n }\n\n /** List all custom device IDs */\n listIds(): string[] {\n return Array.from(this.devices.keys());\n }\n\n /** Check if a custom device exists */\n has(deviceId: string): boolean {\n return this.devices.has(deviceId);\n }\n\n /** Remove a custom device */\n remove(deviceId: string): boolean {\n const deleted = this.devices.delete(deviceId);\n if (deleted) this.save();\n return deleted;\n }\n\n /** Remove all custom devices */\n clear(): void {\n this.devices.clear();\n this.save();\n }\n\n /** Get the number of custom devices */\n get size(): number {\n return this.devices.size;\n }\n\n /** Export all custom devices as a JSON string */\n exportAll(): string {\n const entries = Array.from(this.devices.entries());\n return JSON.stringify(entries, null, 2);\n }\n\n /** Import custom devices from a JSON string (merges with existing) */\n importAll(json: string): { imported: number; skipped: string[] } {\n const entries: [string, RegisteredDevice][] = JSON.parse(json);\n const skipped: string[] = [];\n let imported = 0;\n\n for (const [id, device] of entries) {\n if (this.devices.has(id)) {\n skipped.push(id);\n continue;\n }\n this.devices.set(id, { ...device, source: \"custom\" });\n imported++;\n }\n\n if (imported > 0) this.save();\n return { imported, skipped };\n }\n\n /** Import and overwrite existing entries */\n importAllOverwrite(json: string): number {\n const entries: [string, RegisteredDevice][] = JSON.parse(json);\n for (const [id, device] of entries) {\n this.devices.set(id, { ...device, source: \"custom\" });\n }\n this.save();\n return entries.length;\n }\n\n // ─── Persistence ───\n\n private load(): void {\n if (!this.storage) return;\n try {\n const raw = this.storage.getItem(STORAGE_KEY);\n if (raw) {\n const entries: [string, RegisteredDevice][] = JSON.parse(raw);\n this.devices = new Map(entries);\n }\n } catch {\n // Corrupted storage — start fresh\n this.devices = new Map();\n }\n }\n\n private save(): void {\n const json = JSON.stringify(Array.from(this.devices.entries()));\n if (this.storage) {\n try { this.storage.setItem(STORAGE_KEY, json); } catch { /* ignore */ }\n }\n // Fire-and-forget write to disk via dev server API\n if (typeof fetch !== \"undefined\") {\n fetch(\"/api/storage/custom-devices\", {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: json,\n }).catch(() => { /* dev server may be unavailable */ });\n }\n }\n}\n\n/** Singleton instance for the app */\nlet _defaultRegistry: DeviceRegistry | null = null;\n\nexport function getDeviceRegistry(): DeviceRegistry {\n if (!_defaultRegistry) {\n _defaultRegistry = new DeviceRegistry();\n }\n return _defaultRegistry;\n}\n\n/** Reset the singleton (for testing) */\nexport function resetDeviceRegistry(): void {\n _defaultRegistry = null;\n}\n","import type { DeviceMeta } from \"./types\";\nimport type { DeviceLayoutData } from \"./contract-types\";\nimport { getDeviceRegistry } from \"./custom/device-registry\";\n\n// iPhone 17 series (latest gen representatives)\nimport { IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_LAYOUT } from \"./ios/iphone-17-pro-max/metadata\";\nimport { IPHONE_17_PRO_META, IPHONE_17_PRO_LAYOUT } from \"./ios/iphone-17-pro/metadata\";\nimport { IPHONE_AIR_META, IPHONE_AIR_LAYOUT } from \"./ios/iphone-air/metadata\";\n\n// iPhone 16 series (unique screen classes only)\nimport { IPHONE_16_META, IPHONE_16_LAYOUT } from \"./ios/iphone-16/metadata\";\nimport { IPHONE_16E_META, IPHONE_16E_LAYOUT } from \"./ios/iphone-16e/metadata\";\n\n// iPhone SE\nimport { IPHONE_SE_3_META, IPHONE_SE_3_LAYOUT } from \"./ios/iphone-se-3/metadata\";\n\n// Galaxy S25 series\nimport { GALAXY_S25_ULTRA_META, GALAXY_S25_ULTRA_LAYOUT } from \"./android/galaxy-s25-ultra/metadata\";\nimport { GALAXY_S25_META, GALAXY_S25_LAYOUT } from \"./android/galaxy-s25/metadata\";\nimport { GALAXY_S25_EDGE_META, GALAXY_S25_EDGE_LAYOUT } from \"./android/galaxy-s25-edge/metadata\";\n\n// Pixel 9 series\nimport { PIXEL_9_PRO_XL_META, PIXEL_9_PRO_XL_LAYOUT } from \"./android/pixel-9-pro-xl/metadata\";\nimport { PIXEL_9_PRO_META, PIXEL_9_PRO_LAYOUT } from \"./android/pixel-9-pro/metadata\";\n\n/**\n * Built-in device metadata registry — 11 devices.\n *\n * Curated to cover every unique screen class (logical resolution).\n * Duplicate resolutions across generations are represented by the latest model.\n *\n * ALL DIMENSIONS VERIFIED:\n *\n * iPhone 17 Pro Max: 440×956pt @3x (covers iPhone 16 Pro Max)\n * iPhone 17 Pro: 402×874pt @3x (covers iPhone 16 Pro, iPhone 17)\n * iPhone Air: 420×912pt @3x (unique new size class)\n * iPhone 16: 393×852pt @3x (base Dynamic Island)\n * iPhone 16e: 390×844pt @3x (notch, unique width)\n * iPhone SE 3: 375×667pt @2x (legacy home-button form factor)\n * Galaxy S25 Ultra: 384×824dp @3.75x (covers S24 Ultra)\n * Galaxy S25: 360×780dp @3x (covers S24)\n * Galaxy S25 Edge: 382×824dp @3.75x (unique narrow form factor)\n * Pixel 9 Pro: 393×851dp @3x (covers Pixel 9, S25+)\n * Pixel 9 Pro XL: 448×968dp @3x (largest Android)\n */\nexport const BUILTIN_DEVICES: Record<string, DeviceMeta> = {\n // iPhone (latest gen per screen class)\n \"iphone-17-pro-max\": IPHONE_17_PRO_MAX_META,\n \"iphone-17-pro\": IPHONE_17_PRO_META,\n \"iphone-air\": IPHONE_AIR_META,\n \"iphone-16\": IPHONE_16_META,\n \"iphone-16e\": IPHONE_16E_META,\n \"iphone-se-3\": IPHONE_SE_3_META,\n // Android\n \"galaxy-s25-ultra\": GALAXY_S25_ULTRA_META,\n \"galaxy-s25\": GALAXY_S25_META,\n \"galaxy-s25-edge\": GALAXY_S25_EDGE_META,\n \"pixel-9-pro-xl\": PIXEL_9_PRO_XL_META,\n \"pixel-9-pro\": PIXEL_9_PRO_META,\n};\n\nexport const DEVICE_LAYOUTS: Record<string, DeviceLayoutData> = {\n // iPhone\n \"iphone-17-pro-max\": IPHONE_17_PRO_MAX_LAYOUT,\n \"iphone-17-pro\": IPHONE_17_PRO_LAYOUT,\n \"iphone-air\": IPHONE_AIR_LAYOUT,\n \"iphone-16\": IPHONE_16_LAYOUT,\n \"iphone-16e\": IPHONE_16E_LAYOUT,\n \"iphone-se-3\": IPHONE_SE_3_LAYOUT,\n // Android\n \"galaxy-s25-ultra\": GALAXY_S25_ULTRA_LAYOUT,\n \"galaxy-s25\": GALAXY_S25_LAYOUT,\n \"galaxy-s25-edge\": GALAXY_S25_EDGE_LAYOUT,\n \"pixel-9-pro-xl\": PIXEL_9_PRO_XL_LAYOUT,\n \"pixel-9-pro\": PIXEL_9_PRO_LAYOUT,\n};\n\n/**\n * Look up device metadata — checks built-in first, then custom registry.\n */\nexport function getDeviceMetadata(deviceId: string): DeviceMeta {\n const builtin = BUILTIN_DEVICES[deviceId];\n if (builtin) return builtin;\n\n // Check custom registry\n const custom = getDeviceRegistry().getMeta(deviceId);\n if (custom) return custom;\n\n throw new Error(\n `Device \"${deviceId}\" not found in built-in library or custom registry. ` +\n `Available devices: ${getAllDeviceIds().join(\", \") || \"(none yet)\"}`,\n );\n}\n\n/**\n * Get all device IDs — built-in + custom.\n */\nexport function getAllDeviceIds(): string[] {\n return [\n ...Object.keys(BUILTIN_DEVICES),\n ...getDeviceRegistry().listIds(),\n ];\n}\n","import type { DeviceLayoutContract, DeviceMeta, SafeAreaInsets, ContentRect } from \"./types\";\nimport { DEVICE_LAYOUTS } from \"./registry\";\nimport { getDeviceRegistry } from \"./custom/device-registry\";\n\nexport type { DeviceLayoutData } from \"./contract-types\";\n\n/** Derive the content zone from screen dimensions and safe area insets */\nexport function deriveContentZone(\n screenWidth: number,\n screenHeight: number,\n safeArea: SafeAreaInsets,\n): ContentRect {\n return {\n x: safeArea.left,\n y: safeArea.top,\n width: screenWidth - safeArea.left - safeArea.right,\n height: screenHeight - safeArea.top - safeArea.bottom,\n };\n}\n\n/** Build CSS variables from device data at REAL unscaled values */\nexport function buildCSSVariables(\n screen: DeviceMeta[\"screen\"],\n safeArea: SafeAreaInsets,\n statusBar: DeviceLayoutContract[\"statusBar\"],\n homeIndicator: DeviceLayoutContract[\"homeIndicator\"],\n hardwareOverlays: DeviceLayoutContract[\"hardwareOverlays\"],\n): DeviceLayoutContract[\"cssVariables\"] {\n const vars: DeviceLayoutContract[\"cssVariables\"] = {\n \"--device-width\": `${screen.width}px`,\n \"--device-height\": `${screen.height}px`,\n \"--safe-top\": `${safeArea.top}px`,\n \"--safe-bottom\": `${safeArea.bottom}px`,\n \"--safe-left\": `${safeArea.left}px`,\n \"--safe-right\": `${safeArea.right}px`,\n \"--status-bar-height\": `${statusBar.height}px`,\n \"--home-indicator-height\": `${homeIndicator.height}px`,\n \"--corner-radius\": `${screen.cornerRadius}px`,\n };\n\n if (hardwareOverlays.type !== \"none\") {\n vars[\"--island-width\"] = `${hardwareOverlays.portrait.width}px`;\n vars[\"--island-height\"] = `${hardwareOverlays.portrait.height}px`;\n }\n\n return vars;\n}\n\n/** Build the human-readable AI prompt constraints string */\nexport function buildAIPromptConstraints(\n contract: Omit<DeviceLayoutContract, \"aiPromptConstraints\">,\n): string {\n const sa = contract.safeArea.portrait;\n const cz = contract.contentZone.portrait;\n const overlay = contract.hardwareOverlays;\n\n const lines = [\n `Device: ${contract.device.name} (${contract.device.platform})`,\n `Screen: ${contract.screen.width}×${contract.screen.height} logical points`,\n `Content Zone: ${cz.x},${cz.y} → ${cz.width}×${cz.height}pt`,\n `Safe Area: top ${sa.top}pt, bottom ${sa.bottom}pt, left ${sa.left}pt, right ${sa.right}pt`,\n `Corner Radius: ${contract.screen.cornerRadius}pt`,\n ];\n\n if (overlay.type === \"dynamic-island\") {\n lines.push(\n `Hardware: Dynamic Island (pill) — ${overlay.portrait.width}×${overlay.portrait.height}pt at y=${overlay.portrait.y}`,\n );\n } else if (overlay.type === \"punch-hole\") {\n lines.push(\n `Hardware: Punch-hole camera (circle) — ${overlay.portrait.width}pt diameter at center top`,\n );\n }\n\n lines.push(\n `IMPORTANT: DO NOT render a status bar time/clock — BielaFrame renders a live clock overlay automatically.`,\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Get the full Device Layout Contract for a device.\n * This is the single source of truth that feeds both CSS variables and AI prompts.\n */\nexport function getDeviceContract(\n deviceId: string,\n orientation: \"portrait\" | \"landscape\" = \"portrait\",\n): DeviceLayoutContract {\n const layout = DEVICE_LAYOUTS[deviceId];\n if (!layout) {\n // Check custom registry — custom devices store a pre-computed contract\n const customContract = getDeviceRegistry().getContract(deviceId);\n if (customContract) return customContract;\n\n throw new Error(\n `Device layout \"${deviceId}\" not found. Available: ${Object.keys(DEVICE_LAYOUTS).join(\", \") || \"(none)\"}`,\n );\n }\n\n const { meta, safeArea, hardwareOverlays, statusBar, homeIndicator, hardwareButtons } = layout;\n\n const contentZone = {\n portrait: deriveContentZone(meta.screen.width, meta.screen.height, safeArea.portrait),\n landscape: deriveContentZone(meta.screen.height, meta.screen.width, safeArea.landscape),\n };\n\n const cssVariables = buildCSSVariables(\n meta.screen,\n safeArea[orientation],\n statusBar,\n homeIndicator,\n hardwareOverlays,\n );\n\n const partialContract = {\n device: {\n id: meta.id,\n name: meta.name,\n platform: meta.platform,\n year: meta.year,\n },\n screen: meta.screen,\n safeArea,\n hardwareOverlays,\n statusBar,\n homeIndicator,\n hardwareButtons,\n contentZone,\n cssVariables,\n };\n\n return {\n ...partialContract,\n aiPromptConstraints: buildAIPromptConstraints(partialContract),\n };\n}\n","/**\n * Extract the native coordinate space from an SVG string.\n *\n * Priority: viewBox → width/height attributes → fallback (390×844).\n * This tells us what coordinate space the SVG was authored in,\n * which may differ from the device's logical point dimensions.\n */\n\nexport interface SVGNativeDimensions {\n width: number;\n height: number;\n hasViewBox: boolean;\n source: \"viewBox\" | \"widthHeight\" | \"fallback\";\n}\n\nexport function parseSVGNativeDimensions(svgString: string): SVGNativeDimensions {\n // Extract <svg ...> tag attributes via regex (no DOM dependency for Node/test compatibility)\n const svgTagMatch = svgString.match(/<svg\\b[^>]*>/i);\n if (!svgTagMatch) {\n throw new Error(\"No <svg> element found in the provided string\");\n }\n const svgTag = svgTagMatch[0];\n\n // Priority 1: viewBox — most reliable\n const viewBoxMatch = svgTag.match(/viewBox\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (viewBoxMatch) {\n const parts = viewBoxMatch[1]!.trim().split(/[\\s,]+/).map(Number);\n if (parts.length >= 4) {\n const w = parts[2]!;\n const h = parts[3]!;\n if (!isNaN(w) && !isNaN(h) && w > 0 && h > 0) {\n return { width: w, height: h, hasViewBox: true, source: \"viewBox\" };\n }\n }\n }\n\n // Priority 2: width + height attributes\n const widthMatch = svgTag.match(/\\bwidth\\s*=\\s*[\"']?(\\d+\\.?\\d*)/i);\n const heightMatch = svgTag.match(/\\bheight\\s*=\\s*[\"']?(\\d+\\.?\\d*)/i);\n if (widthMatch && heightMatch) {\n const w = parseFloat(widthMatch[1]!);\n const h = parseFloat(heightMatch[1]!);\n if (w > 0 && h > 0) {\n return { width: w, height: h, hasViewBox: false, source: \"widthHeight\" };\n }\n }\n\n // Priority 3: fallback\n console.warn(\"[BielaFrame] SVG has no viewBox or width/height. Falling back to 390×844.\");\n return { width: 390, height: 844, hasViewBox: false, source: \"fallback\" };\n}\n","/**\n * Normalize an SVG to the canonical logical-point coordinate space.\n *\n * Takes an SVG that may be authored at physical pixels (e.g., 1206×2622 for iPhone 16 Pro at 3x)\n * and rewrites it to logical points (402×874). Also rescales all data-zone element coordinates.\n */\n\nimport { parseSVGNativeDimensions } from \"./parse-dimensions\";\n\nexport interface NormalizationResult {\n normalizedSVG: string;\n scaleFactors: { x: number; y: number };\n aspectRatioWarning: string | null;\n wasAlreadyNormalized: boolean;\n nativeDimensions: { width: number; height: number };\n}\n\nexport function normalizeSVGToLogicalPoints(\n svgString: string,\n targetWidth: number,\n targetHeight: number,\n): NormalizationResult {\n const native = parseSVGNativeDimensions(svgString);\n const scaleX = targetWidth / native.width;\n const scaleY = targetHeight / native.height;\n\n // Aspect ratio check\n const nativeAspect = native.width / native.height;\n const targetAspect = targetWidth / targetHeight;\n const diff = Math.abs(nativeAspect - targetAspect) / targetAspect;\n const aspectRatioWarning = diff > 0.02\n ? `SVG aspect ratio (${nativeAspect.toFixed(3)}) differs from declared device (${targetAspect.toFixed(3)}) by ${(diff * 100).toFixed(1)}%. Wrong SVG?`\n : null;\n\n // Already normalized — no transform needed\n if (Math.abs(scaleX - 1) < 0.001 && Math.abs(scaleY - 1) < 0.001) {\n return {\n normalizedSVG: svgString,\n scaleFactors: { x: 1, y: 1 },\n aspectRatioWarning,\n wasAlreadyNormalized: true,\n nativeDimensions: { width: native.width, height: native.height },\n };\n }\n\n let result = svgString;\n\n // Rewrite the <svg> tag's viewBox, width, height\n result = result.replace(\n /<svg\\b([^>]*)>/i,\n (_match, attrs: string) => {\n // Replace or add viewBox\n if (/viewBox/i.test(attrs)) {\n attrs = attrs.replace(/viewBox\\s*=\\s*[\"'][^\"']*[\"']/i, `viewBox=\"0 0 ${targetWidth} ${targetHeight}\"`);\n } else {\n attrs += ` viewBox=\"0 0 ${targetWidth} ${targetHeight}\"`;\n }\n\n // Replace width/height\n if (/\\bwidth\\s*=/i.test(attrs)) {\n attrs = attrs.replace(/\\bwidth\\s*=\\s*[\"']?\\d+\\.?\\d*[\"']?/i, `width=\"${targetWidth}\"`);\n } else {\n attrs += ` width=\"${targetWidth}\"`;\n }\n if (/\\bheight\\s*=/i.test(attrs)) {\n attrs = attrs.replace(/\\bheight\\s*=\\s*[\"']?\\d+\\.?\\d*[\"']?/i, `height=\"${targetHeight}\"`);\n } else {\n attrs += ` height=\"${targetHeight}\"`;\n }\n\n return `<svg${attrs}>`;\n },\n );\n\n // Rescale data-zone element coordinates\n const xAttrs = [\"x\", \"cx\", \"width\", \"rx\"];\n const yAttrs = [\"y\", \"cy\", \"height\", \"ry\"];\n const allAttrs = [...xAttrs, ...yAttrs];\n\n result = result.replace(\n /data-zone\\s*=\\s*[\"'][^\"']*[\"'][^>]*/gi,\n (elementContent) => {\n let updated = elementContent;\n for (const attr of allAttrs) {\n const regex = new RegExp(`\\\\b${attr}\\\\s*=\\\\s*[\"'](\\\\d+\\\\.?\\\\d*)[\"']`, \"gi\");\n updated = updated.replace(regex, (_, val: string) => {\n const num = parseFloat(val);\n const scale = xAttrs.includes(attr) ? scaleX : scaleY;\n return `${attr}=\"${(num * scale).toFixed(2)}\"`;\n });\n }\n return updated;\n },\n );\n\n return {\n normalizedSVG: result,\n scaleFactors: { x: scaleX, y: scaleY },\n aspectRatioWarning,\n wasAlreadyNormalized: false,\n nativeDimensions: { width: native.width, height: native.height },\n };\n}\n","/**\n * Parse an SVG with data-zone annotations into a DeviceLayoutContract.\n *\n * Reads `data-zone` attributes on SVG elements to extract:\n * - screen-area → screen dimensions\n * - safe-area-top / safe-area-bottom → safe area insets\n * - hardware-overlay → Dynamic Island / notch / punch-hole rect\n * - status-bar → status bar zone\n * - home-indicator → home indicator zone\n */\n\nimport type {\n DeviceLayoutContract,\n DeviceMeta,\n SafeAreaInsets,\n HardwareOverlayType,\n OverlayRect,\n} from \"../types\";\nimport { deriveContentZone, buildCSSVariables, buildAIPromptConstraints } from \"../contract\";\n\nexport interface ParsedZone {\n zone: string;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Extract all data-zone elements and their bounding attributes from SVG markup.\n */\nexport function extractZones(svgString: string): ParsedZone[] {\n const zones: ParsedZone[] = [];\n const regex = /data-zone\\s*=\\s*[\"']([^\"']+)[\"'][^>]*/gi;\n let match;\n\n while ((match = regex.exec(svgString)) !== null) {\n const zoneName = match[1]!;\n const element = match[0];\n\n const x = parseAttr(element, \"x\") ?? parseAttr(element, \"cx\") ?? 0;\n const y = parseAttr(element, \"y\") ?? parseAttr(element, \"cy\") ?? 0;\n const width = parseAttr(element, \"width\") ?? 0;\n const height = parseAttr(element, \"height\") ?? 0;\n\n zones.push({ zone: zoneName, x, y, width, height });\n }\n\n return zones;\n}\n\nfunction parseAttr(element: string, attr: string): number | null {\n const re = new RegExp(`\\\\b${attr}\\\\s*=\\\\s*[\"'](\\\\d+\\\\.?\\\\d*)[\"']`, \"i\");\n const m = element.match(re);\n return m ? parseFloat(m[1]!) : null;\n}\n\nexport interface ParseSVGContractOptions {\n /** Device metadata (id, name, platform, year, screen info) */\n meta: DeviceMeta;\n /** Hardware overlay type if known */\n overlayType?: HardwareOverlayType;\n /** Override overlay shape */\n overlayShape?: OverlayRect[\"shape\"];\n /** Status bar style override */\n statusBarStyle?: DeviceLayoutContract[\"statusBar\"][\"style\"];\n /** Home indicator type override */\n homeIndicatorType?: DeviceLayoutContract[\"homeIndicator\"][\"type\"];\n}\n\n/**\n * Build a full DeviceLayoutContract from a normalized SVG with data-zone annotations.\n */\nexport function parseSVGToContract(\n normalizedSVG: string,\n options: ParseSVGContractOptions,\n): DeviceLayoutContract {\n const { meta } = options;\n const zones = extractZones(normalizedSVG);\n const zoneMap = new Map(zones.map((z) => [z.zone, z]));\n\n // Screen area — use explicit zone or fall back to meta dimensions\n const screenZone = zoneMap.get(\"screen-area\");\n const screenWidth = screenZone?.width ?? meta.screen.width;\n const screenHeight = screenZone?.height ?? meta.screen.height;\n\n // Safe area insets\n const safeTop = zoneMap.get(\"safe-area-top\");\n const safeBottom = zoneMap.get(\"safe-area-bottom\");\n const safeLeft = zoneMap.get(\"safe-area-left\");\n const safeRight = zoneMap.get(\"safe-area-right\");\n\n const portraitSafeArea: SafeAreaInsets = {\n top: safeTop?.height ?? (meta.platform === \"ios\" ? 59 : 36),\n bottom: safeBottom?.height ?? (meta.platform === \"ios\" ? 34 : 0),\n left: safeLeft?.width ?? 0,\n right: safeRight?.width ?? 0,\n };\n\n // Landscape safe area (swap left/right for insets, reduce top/bottom)\n const landscapeSafeArea: SafeAreaInsets = {\n top: Math.min(portraitSafeArea.top, 21),\n bottom: Math.min(portraitSafeArea.bottom, 21),\n left: portraitSafeArea.top,\n right: portraitSafeArea.bottom,\n };\n\n // Hardware overlay\n const overlayZone = zoneMap.get(\"hardware-overlay\");\n const overlayType: HardwareOverlayType = options.overlayType\n ?? (overlayZone ? guessOverlayType(overlayZone, meta.platform) : \"none\");\n\n const overlayPortrait: OverlayRect = overlayZone\n ? {\n x: overlayZone.x,\n y: overlayZone.y,\n width: overlayZone.width,\n height: overlayZone.height,\n shape: options.overlayShape ?? guessOverlayShape(overlayType),\n }\n : { x: 0, y: 0, width: 0, height: 0, shape: \"pill\" };\n\n // Status bar\n const statusBarZone = zoneMap.get(\"status-bar\");\n const statusBarHeight = statusBarZone?.height ?? portraitSafeArea.top;\n const statusBarStyle = options.statusBarStyle\n ?? (overlayType === \"dynamic-island\" ? \"dynamic-island\"\n : overlayType === \"notch\" ? \"notch\"\n : \"fullwidth\");\n\n // Home indicator\n const homeZone = zoneMap.get(\"home-indicator\");\n const homeType = options.homeIndicatorType\n ?? (meta.platform === \"ios\" ? \"swipe-bar\" : \"gestureline\");\n const homeHeight = homeZone?.height ?? portraitSafeArea.bottom;\n\n const statusBar: DeviceLayoutContract[\"statusBar\"] = {\n height: statusBarHeight,\n style: statusBarStyle,\n hasTime: true,\n hasBattery: true,\n hasSignal: true,\n };\n\n const homeIndicator: DeviceLayoutContract[\"homeIndicator\"] = {\n type: homeType,\n height: homeHeight,\n width: homeZone?.width,\n visible: homeHeight > 0,\n };\n\n const contentZone = {\n portrait: deriveContentZone(screenWidth, screenHeight, portraitSafeArea),\n landscape: deriveContentZone(screenHeight, screenWidth, landscapeSafeArea),\n };\n\n const cssVariables = buildCSSVariables(\n meta.screen,\n portraitSafeArea,\n statusBar,\n homeIndicator,\n { type: overlayType, portrait: overlayPortrait },\n );\n\n const partialContract = {\n device: {\n id: meta.id,\n name: meta.name,\n platform: meta.platform,\n year: meta.year,\n },\n screen: meta.screen,\n safeArea: {\n portrait: portraitSafeArea,\n landscape: landscapeSafeArea,\n },\n hardwareOverlays: {\n type: overlayType,\n portrait: overlayPortrait,\n },\n statusBar,\n homeIndicator,\n contentZone,\n cssVariables,\n };\n\n return {\n ...partialContract,\n aiPromptConstraints: buildAIPromptConstraints(partialContract),\n };\n}\n\nfunction guessOverlayType(zone: ParsedZone, platform: \"ios\" | \"android\"): HardwareOverlayType {\n if (platform === \"ios\") {\n // Dynamic Island: wider than tall, relatively small\n if (zone.width > zone.height * 2) return \"dynamic-island\";\n // Notch: wider than tall but taller than DI\n if (zone.width > zone.height) return \"notch\";\n return \"dynamic-island\";\n }\n // Android: typically punch-hole (circular) or pill-cutout\n if (Math.abs(zone.width - zone.height) < 4) return \"punch-hole\";\n return \"pill-cutout\";\n}\n\nfunction guessOverlayShape(type: HardwareOverlayType): OverlayRect[\"shape\"] {\n switch (type) {\n case \"dynamic-island\": return \"pill\";\n case \"notch\": return \"rectangle\";\n case \"punch-hole\": return \"circle\";\n case \"pill-cutout\": return \"pill\";\n default: return \"pill\";\n }\n}\n","/**\n * Pre-registration validation for normalized SVGs.\n *\n * Checks that the normalization result is sane before registering a custom device.\n */\n\nimport type { NormalizationResult } from \"./normalize\";\nimport { extractZones } from \"./parse-contract\";\n\nexport interface ValidationResult {\n passed: boolean;\n warnings: string[];\n errors: string[];\n}\n\n/**\n * Validate a normalized SVG before registration.\n */\nexport function validateNormalizedSVG(\n result: NormalizationResult,\n targetWidth: number,\n targetHeight: number,\n): ValidationResult {\n const warnings: string[] = [];\n const errors: string[] = [];\n\n // 1. Aspect ratio warning\n if (result.aspectRatioWarning) {\n warnings.push(result.aspectRatioWarning);\n }\n\n // 2. Extreme scale factors (> 5x likely means wrong SVG dimensions)\n const maxScale = Math.max(result.scaleFactors.x, result.scaleFactors.y);\n if (maxScale > 5) {\n warnings.push(\n `Scale factor is ${maxScale.toFixed(1)}x — the SVG may be authored at a much larger coordinate space than expected. Verify the SVG dimensions.`,\n );\n }\n\n // 3. Very small scale factors (< 0.1x means SVG is tiny)\n const minScale = Math.min(result.scaleFactors.x, result.scaleFactors.y);\n if (minScale > 0 && minScale < 0.1) {\n warnings.push(\n `Scale factor is ${minScale.toFixed(3)}x — the SVG appears to be very small. Verify you're using the correct export size.`,\n );\n }\n\n // 4. Check that native dimensions are positive\n if (result.nativeDimensions.width <= 0 || result.nativeDimensions.height <= 0) {\n errors.push(\"SVG has zero or negative dimensions. Check the viewBox or width/height attributes.\");\n }\n\n // 5. Check for required zones in the normalized SVG\n const zones = extractZones(result.normalizedSVG);\n const zoneNames = new Set(zones.map((z) => z.zone));\n\n if (!zoneNames.has(\"screen-area\")) {\n warnings.push(\n 'No \"screen-area\" data-zone found. The screen region will use the full device dimensions.',\n );\n }\n\n // 6. Check that target dimensions are reasonable\n if (targetWidth < 100 || targetHeight < 100) {\n errors.push(\n `Target dimensions ${targetWidth}×${targetHeight} are unusually small. Expected logical device dimensions (e.g., 390×844).`,\n );\n }\n\n if (targetWidth > 1500 || targetHeight > 3000) {\n warnings.push(\n `Target dimensions ${targetWidth}×${targetHeight} are unusually large. Expected logical points, not physical pixels.`,\n );\n }\n\n // 7. Scale factor X vs Y divergence (non-uniform scaling)\n if (result.scaleFactors.x > 0 && result.scaleFactors.y > 0) {\n const scaleDiff = Math.abs(result.scaleFactors.x - result.scaleFactors.y) /\n Math.max(result.scaleFactors.x, result.scaleFactors.y);\n if (scaleDiff > 0.05) {\n warnings.push(\n `Non-uniform scaling: X=${result.scaleFactors.x.toFixed(3)}, Y=${result.scaleFactors.y.toFixed(3)}. The SVG aspect ratio may not match the target device.`,\n );\n }\n }\n\n return {\n passed: errors.length === 0,\n warnings,\n errors,\n };\n}\n","/**\n * Scope all SVG IDs to a device-specific prefix to prevent collisions\n * when multiple device frames are rendered on the same page.\n *\n * Rewrites:\n * - id=\"foo\" → id=\"deviceId__foo\"\n * - url(#foo) → url(#deviceId__foo)\n * - href=\"#foo\" → href=\"#deviceId__foo\"\n * - xlink:href=\"#foo\" → xlink:href=\"#deviceId__foo\"\n */\nexport function scopeSVGIds(svgString: string, deviceId: string): string {\n // Collect all IDs in the SVG\n const ids: string[] = [];\n const idRegex = /\\bid\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let match;\n while ((match = idRegex.exec(svgString)) !== null) {\n ids.push(match[1]!);\n }\n\n if (ids.length === 0) return svgString;\n\n let result = svgString;\n const prefix = `${deviceId}__`;\n\n // Replace each ID and all its references\n for (const id of ids) {\n const escapedId = id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n // id=\"...\" declarations\n result = result.replace(\n new RegExp(`\\\\bid\\\\s*=\\\\s*[\"']${escapedId}[\"']`, \"g\"),\n `id=\"${prefix}${id}\"`,\n );\n\n // url(#...) references\n result = result.replace(\n new RegExp(`url\\\\(\\\\s*#${escapedId}\\\\s*\\\\)`, \"g\"),\n `url(#${prefix}${id})`,\n );\n\n // href=\"#...\" references\n result = result.replace(\n new RegExp(`href\\\\s*=\\\\s*[\"']#${escapedId}[\"']`, \"g\"),\n `href=\"#${prefix}${id}\"`,\n );\n }\n\n return result;\n}\n","/**\n * Auto-detect device zones from SVG structure.\n *\n * Two-pass approach:\n * 1. Name-based: scan element IDs/classes/data-attributes for known keywords\n * 2. Geometric heuristics: analyze ALL rects by size, position, fill, and corner radius\n * to identify screen area, dynamic island, phone body, and side buttons\n *\n * The geometric pass is critical for real-world Figma SVGs that use auto-generated\n * IDs like \"clip0_44_55\" with no semantic naming.\n */\n\nexport interface DetectedZone {\n id: string;\n /** The zone type we inferred */\n type: ZoneType;\n /** The SVG element's original id/name that matched */\n sourceLabel: string;\n /** Which keyword matched */\n matchedKeyword: string;\n /** Confidence: \"high\" for exact keyword match, \"medium\" for partial */\n confidence: \"high\" | \"medium\";\n /** Bounding box in SVG coordinate space */\n x: number;\n y: number;\n width: number;\n height: number;\n /** Corner radius (from SVG rx attribute), only for screen-area zones */\n rx?: number;\n}\n\nexport type ZoneType =\n | \"screen-area\"\n | \"hardware-overlay\"\n | \"safe-area-top\"\n | \"safe-area-bottom\"\n | \"safe-area-left\"\n | \"safe-area-right\"\n | \"status-bar\"\n | \"home-indicator\"\n | \"hardware-button\";\n\n/**\n * Result of analyzing the SVG geometry — includes both zones and structural info.\n */\nexport interface SVGAnalysis {\n /** Detected zones for the Zone Tagger */\n zones: DetectedZone[];\n /** Phone body bounding rect (largest rounded rect), if found */\n phoneBody: { x: number; y: number; width: number; height: number; rx: number } | null;\n /** Rects identified as external side buttons */\n sideButtons: { x: number; y: number; width: number; height: number }[];\n /** All extracted rects for debugging */\n allRects: RectInfo[];\n}\n\n/** Internal rect representation with fill/rx info */\ninterface RectInfo {\n x: number;\n y: number;\n width: number;\n height: number;\n rx: number;\n fill: string | null;\n id: string | null;\n}\n\n/** Keywords that map to zone types — ordered by priority (first match wins per zone type) */\nconst ZONE_KEYWORDS: { type: ZoneType; keywords: string[]; highConfidence: string[] }[] = [\n {\n type: \"screen-area\",\n keywords: [\"screen\", \"display\", \"viewport\", \"content-area\", \"screen-area\", \"screenarea\"],\n highConfidence: [\"screen\", \"screen-area\", \"display\"],\n },\n {\n type: \"hardware-overlay\",\n keywords: [\n \"island\", \"dynamic-island\", \"dynamicisland\", \"dynamic_island\",\n \"notch\", \"cutout\", \"punch-hole\", \"punchhole\", \"punch_hole\",\n \"camera\", \"faceid\", \"face-id\", \"truedepth\", \"sensor\",\n \"pill\", \"camera-housing\",\n ],\n highConfidence: [\"island\", \"dynamic-island\", \"notch\", \"cutout\", \"punch-hole\"],\n },\n {\n type: \"safe-area-top\",\n keywords: [\"safe-area-top\", \"safe-top\", \"safeareatop\", \"status-area\", \"top-inset\"],\n highConfidence: [\"safe-area-top\", \"safe-top\"],\n },\n {\n type: \"safe-area-bottom\",\n keywords: [\"safe-area-bottom\", \"safe-bottom\", \"safeareabottom\", \"bottom-inset\"],\n highConfidence: [\"safe-area-bottom\", \"safe-bottom\"],\n },\n {\n type: \"status-bar\",\n keywords: [\"status-bar\", \"statusbar\", \"status_bar\", \"status\"],\n highConfidence: [\"status-bar\", \"statusbar\"],\n },\n {\n type: \"home-indicator\",\n keywords: [\n \"home-indicator\", \"homeindicator\", \"home_indicator\",\n \"home-bar\", \"homebar\", \"swipe-bar\", \"swipebar\",\n \"gesture-bar\", \"gesturebar\", \"bottom-bar\",\n ],\n highConfidence: [\"home-indicator\", \"home-bar\", \"swipe-bar\", \"gesture-bar\"],\n },\n {\n type: \"hardware-button\",\n keywords: [\n \"volume-up\", \"volume_up\", \"volumeup\", \"vol-up\",\n \"volume-down\", \"volume_down\", \"volumedown\", \"vol-down\",\n \"power\", \"power-button\", \"side-button\", \"sidebutton\",\n \"action-button\", \"action_button\", \"actionbutton\",\n \"mute\", \"silent\", \"ringer\",\n \"hardware-button\", \"hardwarebutton\", \"hw-button\",\n ],\n highConfidence: [\"volume-up\", \"volume-down\", \"power\", \"action-button\", \"side-button\"],\n },\n];\n\n/**\n * Auto-detect zones using both name-based and geometric approaches.\n * Falls back to geometric heuristics when name-based detection finds nothing.\n */\nexport function autoDetectZones(svgString: string): DetectedZone[] {\n // First try name-based detection (works with well-named SVGs)\n const nameBasedZones = detectByNames(svgString);\n if (nameBasedZones.length > 0) return nameBasedZones;\n\n // Fall back to geometric heuristics (works with Figma exports)\n const analysis = analyzeSVGGeometry(svgString);\n return analysis.zones;\n}\n\n/**\n * Full SVG analysis — returns zones plus structural info (phone body, side buttons).\n * Used by the Registration Wizard for bezel calculation and button handling.\n */\nexport function analyzeSVGGeometry(svgString: string): SVGAnalysis {\n const rects = extractAllRects(svgString);\n const viewBox = extractViewBox(svgString);\n\n const svgW = viewBox?.w ?? 0;\n const svgH = viewBox?.h ?? 0;\n const svgArea = svgW * svgH;\n\n if (svgArea === 0) {\n return { zones: [], phoneBody: null, sideButtons: [], allRects: rects };\n }\n\n // ── Step 1: Find the phone body (largest rounded rect covering most of the SVG) ──\n const phoneBody = findPhoneBody(rects, svgW, svgH);\n\n // ── Step 2: Find the screen area (largest white/light filled rect inside phone body) ──\n let screenRect = findScreenArea(rects, phoneBody, svgW, svgH);\n\n // If no screen rect found, try to detect from path cutouts (Figma ring paths)\n if (!screenRect) {\n const pathCutout = findPathCutoutScreen(svgString, svgW, svgH);\n if (pathCutout) {\n screenRect = pathCutout;\n }\n }\n\n // If no screen rect found but we have a phone body, synthesize a screen area\n // from the body with a small bezel inset (common in SVGs where body = screen background)\n if (!screenRect && phoneBody) {\n const insetRatio = 0.043; // ~4.3% inset typical for iPhone body-to-screen ratio\n const insetX = Math.round(phoneBody.width * insetRatio);\n const insetY = Math.round(phoneBody.height * (insetRatio * 0.5)); // less vertical inset\n screenRect = {\n x: phoneBody.x + insetX,\n y: phoneBody.y + insetY,\n width: phoneBody.width - insetX * 2,\n height: phoneBody.height - insetY * 2,\n rx: Math.max(phoneBody.rx - insetX, 20),\n fill: \"synthetic\",\n id: null,\n };\n }\n\n // ── Step 3: Find Dynamic Island (small pill-shaped black rect near top of screen) ──\n const islandRect = findDynamicIsland(rects, screenRect);\n\n // ── Step 4: Identify side buttons (small rects outside the phone body) ──\n const sideButtons = findSideButtons(rects, phoneBody);\n\n // ── Build detected zones ──\n const zones: DetectedZone[] = [];\n const now = Date.now();\n\n if (screenRect) {\n const isSynthetic = screenRect.fill === \"synthetic\";\n zones.push({\n id: `auto-screen-area-${now}`,\n type: \"screen-area\",\n sourceLabel: isSynthetic ? \"geometric: inferred from body\" : \"geometric: largest white rect\",\n matchedKeyword: \"geometry\",\n confidence: isSynthetic ? \"medium\" : \"high\",\n x: screenRect.x,\n y: screenRect.y,\n width: screenRect.width,\n height: screenRect.height,\n rx: screenRect.rx > 0 ? screenRect.rx : undefined,\n });\n }\n\n if (islandRect) {\n zones.push({\n id: `auto-hardware-overlay-${now}`,\n type: \"hardware-overlay\",\n sourceLabel: \"geometric: pill near top\",\n matchedKeyword: \"geometry\",\n confidence: \"medium\",\n x: islandRect.x,\n y: islandRect.y,\n width: islandRect.width,\n height: islandRect.height,\n });\n }\n\n return {\n zones,\n phoneBody: phoneBody\n ? { x: phoneBody.x, y: phoneBody.y, width: phoneBody.width, height: phoneBody.height, rx: phoneBody.rx }\n : null,\n sideButtons: sideButtons.map(r => ({ x: r.x, y: r.y, width: r.width, height: r.height })),\n allRects: rects,\n };\n}\n\n// ── Geometric detection helpers ──\n\nfunction findPhoneBody(\n rects: RectInfo[],\n svgW: number,\n svgH: number,\n): RectInfo | null {\n // The phone body is typically the largest rect with significant corner radius\n // covering a large portion of the SVG area\n const svgArea = svgW * svgH;\n const candidates = rects\n .filter(r => {\n const area = r.width * r.height;\n // Must cover at least 30% of SVG area\n if (area < svgArea * 0.3) return false;\n // Must have rounded corners (rx >= 20 in typical phone SVGs)\n if (r.rx < 20) return false;\n // Must be tall (phone form factor: h > w * 1.5)\n if (r.height < r.width * 1.3) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n return candidates[0] ?? null;\n}\n\nfunction findScreenArea(\n rects: RectInfo[],\n phoneBody: RectInfo | null,\n svgW: number,\n svgH: number,\n): RectInfo | null {\n const refRect = phoneBody ?? { x: 0, y: 0, width: svgW, height: svgH };\n\n // Look for a large rect with a light fill (white, #fff, etc.) inside the phone body\n const candidates = rects\n .filter(r => {\n // Must be inside or mostly overlapping the phone body\n if (!isInsideRect(r, refRect, 0.05)) return false;\n // Must cover at least 50% of the phone body area\n const bodyArea = refRect.width * refRect.height;\n const area = r.width * r.height;\n if (area < bodyArea * 0.5) return false;\n // Must be smaller than the phone body\n if (area >= bodyArea * 0.98) return false;\n // Should have a light fill (white, light grey) — screen area in Figma exports\n if (!isLightFill(r.fill)) return false;\n // Must have rounded corners\n if (r.rx < 10) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n if (candidates[0]) return candidates[0];\n\n // Fallback: if no light-fill rect found, look for the largest rect inside the body\n // that isn't the body itself (some SVGs use a transparent/none screen rect)\n const fallbackCandidates = rects\n .filter(r => {\n if (!isInsideRect(r, refRect, 0.05)) return false;\n const bodyArea = refRect.width * refRect.height;\n const area = r.width * r.height;\n if (area < bodyArea * 0.5) return false;\n if (area >= bodyArea * 0.98) return false;\n if (r.rx < 10) return false;\n // Skip dark fills that are likely the body background\n if (isDarkFill(r.fill) && r.fill !== \"none\" && r.fill !== null) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n return fallbackCandidates[0] ?? null;\n}\n\nfunction findDynamicIsland(\n rects: RectInfo[],\n screenRect: RectInfo | null,\n): RectInfo | null {\n if (!screenRect) return null;\n\n const candidates = rects\n .filter(r => {\n // Must be small relative to screen (< 15% of screen width)\n if (r.width > screenRect.width * 0.5) return false;\n if (r.width < screenRect.width * 0.05) return false;\n // Must be pill-shaped: width > height, both > 0, with rounded corners\n if (r.width <= r.height) return false;\n const ratio = r.width / r.height;\n if (ratio < 1.5 || ratio > 8) return false;\n if (r.rx < 5) return false;\n // Must be near the top of the screen area (top 10%)\n const topThreshold = screenRect.y + screenRect.height * 0.10;\n if (r.y > topThreshold) return false;\n if (r.y < screenRect.y) return false;\n // Must be roughly centered horizontally in the screen\n const rCenterX = r.x + r.width / 2;\n const screenCenterX = screenRect.x + screenRect.width / 2;\n const maxOffCenter = screenRect.width * 0.25;\n if (Math.abs(rCenterX - screenCenterX) > maxOffCenter) return false;\n // Must have dark fill (black)\n if (!isDarkFill(r.fill)) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n return candidates[0] ?? null;\n}\n\nfunction findSideButtons(\n rects: RectInfo[],\n phoneBody: RectInfo | null,\n): RectInfo[] {\n if (!phoneBody) return [];\n\n return rects.filter(r => {\n // Must be a small rect\n const area = r.width * r.height;\n const bodyArea = phoneBody.width * phoneBody.height;\n if (area > bodyArea * 0.02) return false; // < 2% of body\n if (area < 10) return false; // not a tiny artifact\n\n // Must be outside the phone body on the left or right edge\n const isOutsideLeft = r.x + r.width < phoneBody.x + phoneBody.width * 0.05;\n const isOutsideRight = r.x > phoneBody.x + phoneBody.width * 0.95;\n\n if (!isOutsideLeft && !isOutsideRight) return false;\n\n // Must be vertically within the phone body range\n if (r.y + r.height < phoneBody.y) return false;\n if (r.y > phoneBody.y + phoneBody.height) return false;\n\n // Should be elongated vertically (button-shaped) or small square\n // Buttons are typically taller than wide\n return true;\n });\n}\n\n/**\n * Classify detected side buttons into specific hardware button types.\n *\n * Classification strategy based on real device button placement:\n * - LEFT side (iOS): action button (top), volume up (middle-top), volume down (middle-bottom)\n * - LEFT side (Android): volume up (top), volume down (bottom)\n * - RIGHT side: power button (top/middle), camera control (lower, if present)\n *\n * Uses vertical position and size to distinguish buttons.\n */\nexport interface ClassifiedButton {\n type: \"volume-up\" | \"volume-down\" | \"power\" | \"action\" | \"camera\";\n side: \"left\" | \"right\";\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport function classifySideButtons(\n sideButtons: { x: number; y: number; width: number; height: number }[],\n phoneBody: { x: number; y: number; width: number; height: number } | null,\n): ClassifiedButton[] {\n if (!phoneBody || sideButtons.length === 0) return [];\n\n const bodyMidX = phoneBody.x + phoneBody.width / 2;\n const classified: ClassifiedButton[] = [];\n\n // Split buttons by side\n const leftButtons = sideButtons\n .filter(b => (b.x + b.width / 2) < bodyMidX)\n .sort((a, b) => a.y - b.y); // top to bottom\n\n const rightButtons = sideButtons\n .filter(b => (b.x + b.width / 2) >= bodyMidX)\n .sort((a, b) => a.y - b.y); // top to bottom\n\n // ── Classify left side buttons ──\n // Find pairs of similarly-sized buttons close together (volume up/down)\n if (leftButtons.length >= 2) {\n // Find the best volume pair: two buttons closest in size and vertically adjacent\n let bestPairI = -1;\n let bestPairJ = -1;\n let bestScore = Infinity;\n\n for (let i = 0; i < leftButtons.length; i++) {\n for (let j = i + 1; j < leftButtons.length; j++) {\n const a = leftButtons[i]!, b = leftButtons[j]!;\n const areaA = a.width * a.height;\n const areaB = b.width * b.height;\n const sizeDiff = Math.abs(areaA - areaB) / Math.max(areaA, areaB);\n const gap = b.y - (a.y + a.height);\n // Volume buttons: similar size, small gap between them\n if (sizeDiff < 0.5 && gap < a.height * 3 && gap > -a.height) {\n const score = sizeDiff * 100 + Math.abs(gap);\n if (score < bestScore) {\n bestScore = score;\n bestPairI = i;\n bestPairJ = j;\n }\n }\n }\n }\n\n if (bestPairI >= 0 && bestPairJ >= 0) {\n classified.push({\n type: \"volume-up\",\n side: \"left\",\n ...leftButtons[bestPairI]!,\n });\n classified.push({\n type: \"volume-down\",\n side: \"left\",\n ...leftButtons[bestPairJ]!,\n });\n\n // Remaining left buttons: classify as action button\n for (let i = 0; i < leftButtons.length; i++) {\n if (i !== bestPairI && i !== bestPairJ) {\n classified.push({\n type: \"action\",\n side: \"left\",\n ...leftButtons[i]!,\n });\n }\n }\n } else {\n // Can't find a volume pair — just assign top two as volume\n classified.push({ type: \"volume-up\", side: \"left\", ...leftButtons[0]! });\n classified.push({ type: \"volume-down\", side: \"left\", ...leftButtons[1]! });\n for (let i = 2; i < leftButtons.length; i++) {\n classified.push({ type: \"action\", side: \"left\", ...leftButtons[i]! });\n }\n }\n } else if (leftButtons.length === 1) {\n // Single left button — assume volume up (or it could be a sim tray, skip)\n classified.push({ type: \"volume-up\", side: \"left\", ...leftButtons[0]! });\n }\n\n // ── Classify right side buttons ──\n if (rightButtons.length >= 2) {\n // Power button is usually the larger one or higher up\n // Camera control is lower and often smaller or circular\n const sorted = [...rightButtons].sort((a, b) => a.y - b.y);\n classified.push({ type: \"power\", side: \"right\", ...sorted[0]! });\n for (let i = 1; i < sorted.length; i++) {\n classified.push({ type: \"camera\", side: \"right\", ...sorted[i]! });\n }\n } else if (rightButtons.length === 1) {\n classified.push({ type: \"power\", side: \"right\", ...rightButtons[0]! });\n }\n\n return classified;\n}\n\n// ── Path cutout detection ──\n// Many Figma SVGs use <path> elements with two subpaths (M...Z M...Z) to create\n// a ring shape for the phone bezel. The inner cutout defines the screen area.\n\nfunction findPathCutoutScreen(\n svgString: string,\n svgW: number,\n svgH: number,\n): RectInfo | null {\n const svgArea = svgW * svgH;\n // Find <path> elements with a fill (not inside defs/mask/filter)\n const pathRegex = /<path\\b([^>]*?)\\/>/gi;\n let match;\n const candidates: { inner: { x: number; y: number; w: number; h: number }; rx: number; fill: string }[] = [];\n\n while ((match = pathRegex.exec(svgString)) !== null) {\n const attrs = match[1]!;\n // Skip paths inside non-visual parents\n const preceding = svgString.slice(0, match.index);\n if (isInsideNonVisualParent(preceding)) continue;\n\n const fill = getAttrValue(attrs, \"fill\");\n // Skip dark fills and unfilled paths (these aren't bezel rings)\n if (!fill || isDarkFill(fill)) continue;\n // Skip gradient/url fills\n if (fill.startsWith(\"url(\")) continue;\n\n const d = getAttrValue(attrs, \"d\");\n if (!d) continue;\n\n // Split path into subpaths at Z (case insensitive)\n const subpaths = d.split(/[Zz]/).filter(s => s.trim().length > 0);\n if (subpaths.length < 2) continue;\n\n // Extract bounding boxes of outer (first) and inner (second) subpaths\n const outerBB = subpathBBox(subpaths[0]!);\n const innerBB = subpathBBox(subpaths[1]!);\n\n if (!outerBB || !innerBB) continue;\n\n // The outer should cover most of the SVG area\n const outerArea = outerBB.w * outerBB.h;\n if (outerArea < svgArea * 0.3) continue;\n\n // The inner should be smaller than the outer but still substantial\n const innerArea = innerBB.w * innerBB.h;\n if (innerArea < outerArea * 0.5 || innerArea >= outerArea * 0.98) continue;\n\n // The inner should be phone-shaped (taller than wide)\n if (innerBB.h < innerBB.w * 1.3) continue;\n\n // The inner should be inside the outer\n if (innerBB.x < outerBB.x || innerBB.y < outerBB.y) continue;\n if (innerBB.x + innerBB.w > outerBB.x + outerBB.w + 5) continue;\n if (innerBB.y + innerBB.h > outerBB.y + outerBB.h + 5) continue;\n\n // Estimate corner radius from the bezel width (~proportion of inner size)\n const estimatedRx = Math.round(Math.min(innerBB.w, innerBB.h) * 0.04);\n\n candidates.push({ inner: innerBB, rx: Math.max(estimatedRx, 20), fill });\n }\n\n if (candidates.length === 0) return null;\n\n // Pick the candidate with the largest inner area\n candidates.sort((a, b) => (b.inner.w * b.inner.h) - (a.inner.w * a.inner.h));\n const best = candidates[0]!;\n\n return {\n x: best.inner.x,\n y: best.inner.y,\n width: best.inner.w,\n height: best.inner.h,\n rx: best.rx,\n fill: \"path-cutout\",\n id: null,\n };\n}\n\n/** Extract bounding box from a single subpath by parsing SVG path commands */\nfunction subpathBBox(subpath: string): { x: number; y: number; w: number; h: number } | null {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n let curX = 0, curY = 0;\n\n function addPoint(x: number, y: number) {\n if (!isFinite(x) || !isFinite(y)) return;\n minX = Math.min(minX, x); minY = Math.min(minY, y);\n maxX = Math.max(maxX, x); maxY = Math.max(maxY, y);\n curX = x; curY = y;\n }\n\n // Tokenize: split into commands and numbers\n const tokens = subpath.match(/[MmLlHhVvCcSsQqTtAaZz]|-?\\d+\\.?\\d*(?:e[+-]?\\d+)?/gi);\n if (!tokens || tokens.length < 3) return null;\n\n const toks = tokens;\n let i = 0;\n function nextNum(): number { return i < toks.length ? parseFloat(toks[i++]!) : 0; }\n\n while (i < toks.length) {\n const cmd = toks[i]!;\n if (/^[A-Za-z]$/.test(cmd)) {\n i++;\n switch (cmd) {\n case \"M\": case \"L\": addPoint(nextNum(), nextNum()); break;\n case \"m\": case \"l\": addPoint(curX + nextNum(), curY + nextNum()); break;\n case \"H\": addPoint(nextNum(), curY); break;\n case \"h\": addPoint(curX + nextNum(), curY); break;\n case \"V\": addPoint(curX, nextNum()); break;\n case \"v\": addPoint(curX, curY + nextNum()); break;\n case \"C\": { nextNum(); nextNum(); nextNum(); nextNum(); addPoint(nextNum(), nextNum()); break; }\n case \"c\": { nextNum(); nextNum(); nextNum(); nextNum(); addPoint(curX + nextNum(), curY + nextNum()); break; }\n case \"S\": case \"Q\": { nextNum(); nextNum(); addPoint(nextNum(), nextNum()); break; }\n case \"s\": case \"q\": { nextNum(); nextNum(); addPoint(curX + nextNum(), curY + nextNum()); break; }\n case \"T\": addPoint(nextNum(), nextNum()); break;\n case \"t\": addPoint(curX + nextNum(), curY + nextNum()); break;\n case \"A\": { nextNum(); nextNum(); nextNum(); nextNum(); nextNum(); addPoint(nextNum(), nextNum()); break; }\n case \"a\": { nextNum(); nextNum(); nextNum(); nextNum(); nextNum(); addPoint(curX + nextNum(), curY + nextNum()); break; }\n default: break;\n }\n } else {\n i++; // skip unexpected tokens\n }\n }\n\n if (!isFinite(minX) || maxX - minX < 10 || maxY - minY < 10) return null;\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\n}\n\n// ── Fill color analysis ──\n\nfunction isLightFill(fill: string | null): boolean {\n if (!fill) return false;\n const f = fill.toLowerCase().trim();\n if (f === \"white\" || f === \"#fff\" || f === \"#ffffff\") return true;\n if (f === \"rgb(255,255,255)\" || f === \"rgb(255, 255, 255)\") return true;\n // Check hex colors — if all components > 0xCC, it's \"light\"\n const hex6 = f.match(/^#([0-9a-f]{6})$/);\n if (hex6) {\n const r = parseInt(hex6[1]!.slice(0, 2), 16);\n const g = parseInt(hex6[1]!.slice(2, 4), 16);\n const b = parseInt(hex6[1]!.slice(4, 6), 16);\n return r > 200 && g > 200 && b > 200;\n }\n return false;\n}\n\nfunction isDarkFill(fill: string | null): boolean {\n if (!fill) return false;\n const f = fill.toLowerCase().trim();\n if (f === \"black\" || f === \"#000\" || f === \"#000000\") return true;\n if (f.startsWith(\"rgb(0\") || f === \"rgb(0,0,0)\" || f === \"rgb(0, 0, 0)\") return true;\n const hex6 = f.match(/^#([0-9a-f]{6})$/);\n if (hex6) {\n const r = parseInt(hex6[1]!.slice(0, 2), 16);\n const g = parseInt(hex6[1]!.slice(2, 4), 16);\n const b = parseInt(hex6[1]!.slice(4, 6), 16);\n return r < 50 && g < 50 && b < 50;\n }\n return false;\n}\n\n// ── Geometry helpers ──\n\n/** Check if rect `inner` is (mostly) inside `outer`, with tolerance as fraction */\nfunction isInsideRect(\n inner: RectInfo,\n outer: { x: number; y: number; width: number; height: number },\n tolerance: number,\n): boolean {\n const tolX = outer.width * tolerance;\n const tolY = outer.height * tolerance;\n return (\n inner.x >= outer.x - tolX &&\n inner.y >= outer.y - tolY &&\n inner.x + inner.width <= outer.x + outer.width + tolX &&\n inner.y + inner.height <= outer.y + outer.height + tolY\n );\n}\n\n// ── SVG parsing helpers ──\n\nfunction extractViewBox(svgString: string): { x: number; y: number; w: number; h: number } | null {\n const vbMatch = svgString.match(/<svg\\b[^>]*viewBox\\s*=\\s*[\"']([^\"']*)[\"']/i);\n if (vbMatch) {\n const parts = vbMatch[1]!.trim().split(/[\\s,]+/).map(Number);\n if (parts.length >= 4 && parts.every(n => isFinite(n))) {\n return { x: parts[0]!, y: parts[1]!, w: parts[2]!, h: parts[3]! };\n }\n }\n // Fallback to width/height attributes\n const wMatch = svgString.match(/<svg\\b[^>]*\\bwidth\\s*=\\s*[\"']?(\\d+\\.?\\d*)[\"']?/i);\n const hMatch = svgString.match(/<svg\\b[^>]*\\bheight\\s*=\\s*[\"']?(\\d+\\.?\\d*)[\"']?/i);\n if (wMatch && hMatch) {\n return { x: 0, y: 0, w: parseFloat(wMatch[1]!), h: parseFloat(hMatch[1]!) };\n }\n return null;\n}\n\n/**\n * Extract ALL <rect> elements from SVG, regardless of whether they have names.\n * This is the key difference from `extractSVGElements` which only returns named elements.\n */\nfunction extractAllRects(svgString: string): RectInfo[] {\n const rects: RectInfo[] = [];\n const regex = /<rect\\b([^>]*?)(?:\\/>|>[^<]*<\\/rect>)/gi;\n let match;\n\n while ((match = regex.exec(svgString)) !== null) {\n const attrs = match[1]!;\n\n // Skip rects inside <defs>, <clipPath>, <mask>, <filter> — they're not visual\n const preceding = svgString.slice(0, match.index);\n if (isInsideNonVisualParent(preceding)) continue;\n\n const x = getNumAttr(attrs, \"x\");\n const y = getNumAttr(attrs, \"y\");\n const width = getNumAttr(attrs, \"width\");\n const height = getNumAttr(attrs, \"height\");\n\n // Skip zero-size rects\n if (width <= 0 || height <= 0) continue;\n\n // Handle transform=\"matrix(-1 0 0 1 X Y)\" which mirrors the rect\n const transformedPos = applyTransformToRect(attrs, x, y, width, height);\n\n const rx = Math.max(getNumAttr(attrs, \"rx\"), getNumAttr(attrs, \"ry\"));\n const fill = getAttrValue(attrs, \"fill\");\n const id = getAttrValue(attrs, \"id\");\n\n rects.push({\n x: transformedPos.x,\n y: transformedPos.y,\n width: transformedPos.width,\n height: transformedPos.height,\n rx,\n fill,\n id,\n });\n }\n\n return rects;\n}\n\n/**\n * Check if the current position in the SVG is inside a non-visual parent like\n * <defs>, <clipPath>, <mask>, or <filter>.\n */\nfunction isInsideNonVisualParent(preceding: string): boolean {\n const nonVisualTags = [\"defs\", \"clipPath\", \"mask\", \"filter\"];\n for (const tag of nonVisualTags) {\n const openCount = countOccurrences(preceding, `<${tag}`);\n const closeCount = countOccurrences(preceding, `</${tag}`);\n if (openCount > closeCount) return true;\n }\n return false;\n}\n\nfunction countOccurrences(str: string, substr: string): number {\n let count = 0;\n let pos = 0;\n while ((pos = str.indexOf(substr, pos)) !== -1) {\n count++;\n pos += substr.length;\n }\n return count;\n}\n\n/**\n * Apply a simple SVG transform (matrix) to a rect's position.\n * Handles the common Figma pattern: transform=\"matrix(-1 0 0 1 X Y)\"\n */\nfunction applyTransformToRect(\n attrs: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): { x: number; y: number; width: number; height: number } {\n const transformAttr = getAttrValue(attrs, \"transform\");\n if (!transformAttr) return { x, y, width, height };\n\n // Handle matrix(-1 0 0 1 tx ty) — horizontal mirror\n const matrixMatch = transformAttr.match(\n /matrix\\(\\s*(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s*\\)/,\n );\n if (matrixMatch) {\n const a = parseFloat(matrixMatch[1]!);\n const d = parseFloat(matrixMatch[4]!);\n const tx = parseFloat(matrixMatch[5]!);\n const ty = parseFloat(matrixMatch[6]!);\n\n if (a === -1 && d === 1) {\n // Horizontal mirror: new x = tx - x - width\n return { x: tx - x - width, y: y + ty, width, height };\n }\n if (a === 1 && d === -1) {\n // Vertical mirror: new y = ty - y - height\n return { x: x + tx, y: ty - y - height, width, height };\n }\n // General translation\n if (a === 1 && d === 1) {\n return { x: x + tx, y: y + ty, width, height };\n }\n }\n\n return { x, y, width, height };\n}\n\n// ── Name-based detection (original approach) ──\n\nfunction detectByNames(svgString: string): DetectedZone[] {\n const detected: DetectedZone[] = [];\n const usedTypes = new Set<ZoneType>();\n const elements = extractSVGElements(svgString);\n\n for (const el of elements) {\n const identifiers = [\n el.id, el.className, el.dataName, el.dataZone, el.ariaLabel,\n ].filter(Boolean).map(s => s!.toLowerCase());\n\n for (const zoneConfig of ZONE_KEYWORDS) {\n if (usedTypes.has(zoneConfig.type)) continue;\n\n for (const keyword of zoneConfig.keywords) {\n const matched = identifiers.some(ident =>\n ident === keyword ||\n ident.includes(keyword) ||\n ident.replace(/[_\\s]/g, \"-\").includes(keyword),\n );\n\n if (matched) {\n const confidence = zoneConfig.highConfidence.some(hk =>\n identifiers.some(ident => ident === hk || ident.includes(hk)),\n ) ? \"high\" as const : \"medium\" as const;\n\n detected.push({\n id: `auto-${zoneConfig.type}-${Date.now()}`,\n type: zoneConfig.type,\n sourceLabel: el.id || el.dataName || el.className || el.ariaLabel || \"unknown\",\n matchedKeyword: keyword,\n confidence,\n x: el.x, y: el.y, width: el.width, height: el.height,\n });\n\n usedTypes.add(zoneConfig.type);\n break;\n }\n }\n }\n }\n\n return detected;\n}\n\n// ── Element parsing for name-based detection ──\n\ninterface SVGElementInfo {\n tag: string;\n id: string | null;\n className: string | null;\n dataName: string | null;\n dataZone: string | null;\n ariaLabel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nfunction extractSVGElements(svgString: string): SVGElementInfo[] {\n const elements: SVGElementInfo[] = [];\n const tagRegex = /<(rect|g|path|circle|ellipse|use|foreignObject|image)\\b([^>]*?)(?:\\/>|>)/gi;\n let match;\n\n while ((match = tagRegex.exec(svgString)) !== null) {\n const tag = match[1]!.toLowerCase();\n const attrs = match[2]!;\n\n const id = getAttrValue(attrs, \"id\");\n const className = getAttrValue(attrs, \"class\");\n const dataName = getAttrValue(attrs, \"data-name\");\n const dataZone = getAttrValue(attrs, \"data-zone\");\n const ariaLabel = getAttrValue(attrs, \"aria-label\");\n\n if (!id && !className && !dataName && !dataZone && !ariaLabel) continue;\n\n const bbox = extractBBox(tag, attrs);\n elements.push({ tag, id, className, dataName, dataZone, ariaLabel, ...bbox });\n }\n\n return elements;\n}\n\nfunction getAttrValue(attrs: string, name: string): string | null {\n const re = new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']([^\"']*)[\"']`, \"i\");\n const m = attrs.match(re);\n return m ? m[1]! : null;\n}\n\nfunction getNumAttr(attrs: string, name: string): number {\n const re = new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']([\\\\d.]+)[\"']`, \"i\");\n const m = attrs.match(re);\n return m ? parseFloat(m[1]!) : 0;\n}\n\nfunction extractBBox(\n tag: string,\n attrs: string,\n): { x: number; y: number; width: number; height: number } {\n switch (tag) {\n case \"rect\":\n case \"foreignobject\":\n case \"image\":\n return {\n x: getNumAttr(attrs, \"x\"),\n y: getNumAttr(attrs, \"y\"),\n width: getNumAttr(attrs, \"width\"),\n height: getNumAttr(attrs, \"height\"),\n };\n\n case \"circle\": {\n const cx = getNumAttr(attrs, \"cx\");\n const cy = getNumAttr(attrs, \"cy\");\n const r = getNumAttr(attrs, \"r\");\n return { x: cx - r, y: cy - r, width: r * 2, height: r * 2 };\n }\n\n case \"ellipse\": {\n const cx = getNumAttr(attrs, \"cx\");\n const cy = getNumAttr(attrs, \"cy\");\n const rx = getNumAttr(attrs, \"rx\");\n const ry = getNumAttr(attrs, \"ry\");\n return { x: cx - rx, y: cy - ry, width: rx * 2, height: ry * 2 };\n }\n\n case \"path\":\n return extractPathBBox(attrs);\n\n case \"g\":\n case \"use\":\n return {\n x: getNumAttr(attrs, \"x\"),\n y: getNumAttr(attrs, \"y\"),\n width: getNumAttr(attrs, \"width\"),\n height: getNumAttr(attrs, \"height\"),\n };\n\n default:\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n}\n\nfunction extractPathBBox(\n attrs: string,\n): { x: number; y: number; width: number; height: number } {\n const dAttr = getAttrValue(attrs, \"d\");\n if (!dAttr) return { x: 0, y: 0, width: 0, height: 0 };\n\n const nums = dAttr.match(/-?\\d+\\.?\\d*/g);\n if (!nums || nums.length < 4) return { x: 0, y: 0, width: 0, height: 0 };\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = 0; i < nums.length - 1; i += 2) {\n const x = parseFloat(nums[i]!);\n const y = parseFloat(nums[i + 1]!);\n if (isFinite(x) && isFinite(y)) {\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n }\n }\n\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Get a list of all identifiable SVG element names for UI display.\n */\nexport function listSVGLayerNames(svgString: string): { tag: string; name: string }[] {\n const elements = extractSVGElements(svgString);\n return elements.map(el => ({\n tag: el.tag,\n name: el.id || el.dataName || el.className || el.ariaLabel || `<${el.tag}>`,\n }));\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/custom/device-registry.ts","../src/registry.ts","../src/contract.ts","../src/svg/parse-dimensions.ts","../src/svg/normalize.ts","../src/svg/parse-contract.ts","../src/svg/validate.ts","../src/svg/scope-ids.ts","../src/svg/auto-detect-zones.ts"],"names":["IPHONE_17_PRO_MAX_META","IPHONE_17_PRO_META","IPHONE_AIR_META","IPHONE_16_META","IPHONE_16E_META","IPHONE_SE_3_META","GALAXY_S25_ULTRA_META","GALAXY_S25_META","GALAXY_S25_EDGE_META","PIXEL_9_PRO_XL_META","PIXEL_9_PRO_META","IPHONE_17_PRO_MAX_LAYOUT","IPHONE_17_PRO_LAYOUT","IPHONE_AIR_LAYOUT","IPHONE_16_LAYOUT","IPHONE_16E_LAYOUT","IPHONE_SE_3_LAYOUT","GALAXY_S25_ULTRA_LAYOUT","GALAXY_S25_LAYOUT","GALAXY_S25_EDGE_LAYOUT","PIXEL_9_PRO_XL_LAYOUT","PIXEL_9_PRO_LAYOUT"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Custom device registry — stores user-imported devices in localStorage.\n *\n * Provides CRUD operations for custom devices, persistence, and export/import.\n * Custom devices are stored alongside built-in devices but tracked separately.\n */\n\nimport type { RegisteredDevice, DeviceMeta, DeviceLayoutContract } from \"../types\";\n\nconst STORAGE_KEY = \"bielaframe-custom-devices\";\n\nexport class DeviceRegistry {\n private devices: Map<string, RegisteredDevice> = new Map();\n private storage: Storage | null;\n\n constructor(storage?: Storage | null) {\n this.storage = storage ?? (typeof localStorage !== \"undefined\" ? localStorage : null);\n this.load();\n }\n\n /** Register or update a custom device */\n register(device: RegisteredDevice): void {\n this.devices.set(device.meta.id, {\n ...device,\n source: \"custom\",\n registeredAt: device.registeredAt || new Date().toISOString(),\n });\n this.save();\n }\n\n /** Get a custom device by ID */\n get(deviceId: string): RegisteredDevice | undefined {\n return this.devices.get(deviceId);\n }\n\n /** Get the metadata for a custom device */\n getMeta(deviceId: string): DeviceMeta | undefined {\n return this.devices.get(deviceId)?.meta;\n }\n\n /** Get the contract for a custom device */\n getContract(deviceId: string): DeviceLayoutContract | undefined {\n return this.devices.get(deviceId)?.contract;\n }\n\n /** List all custom devices */\n list(): RegisteredDevice[] {\n return Array.from(this.devices.values());\n }\n\n /** List all custom device IDs */\n listIds(): string[] {\n return Array.from(this.devices.keys());\n }\n\n /** Check if a custom device exists */\n has(deviceId: string): boolean {\n return this.devices.has(deviceId);\n }\n\n /** Remove a custom device */\n remove(deviceId: string): boolean {\n const deleted = this.devices.delete(deviceId);\n if (deleted) this.save();\n return deleted;\n }\n\n /** Remove all custom devices */\n clear(): void {\n this.devices.clear();\n this.save();\n }\n\n /** Get the number of custom devices */\n get size(): number {\n return this.devices.size;\n }\n\n /** Export all custom devices as a JSON string */\n exportAll(): string {\n const entries = Array.from(this.devices.entries());\n return JSON.stringify(entries, null, 2);\n }\n\n /** Import custom devices from a JSON string (merges with existing) */\n importAll(json: string): { imported: number; skipped: string[] } {\n const entries: [string, RegisteredDevice][] = JSON.parse(json);\n const skipped: string[] = [];\n let imported = 0;\n\n for (const [id, device] of entries) {\n if (this.devices.has(id)) {\n skipped.push(id);\n continue;\n }\n this.devices.set(id, { ...device, source: \"custom\" });\n imported++;\n }\n\n if (imported > 0) this.save();\n return { imported, skipped };\n }\n\n /** Import and overwrite existing entries */\n importAllOverwrite(json: string): number {\n const entries: [string, RegisteredDevice][] = JSON.parse(json);\n for (const [id, device] of entries) {\n this.devices.set(id, { ...device, source: \"custom\" });\n }\n this.save();\n return entries.length;\n }\n\n // ─── Persistence ───\n\n private load(): void {\n if (!this.storage) return;\n try {\n const raw = this.storage.getItem(STORAGE_KEY);\n if (raw) {\n const entries: [string, RegisteredDevice][] = JSON.parse(raw);\n this.devices = new Map(entries);\n }\n } catch {\n // Corrupted storage — start fresh\n this.devices = new Map();\n }\n }\n\n private save(): void {\n const json = JSON.stringify(Array.from(this.devices.entries()));\n if (this.storage) {\n try { this.storage.setItem(STORAGE_KEY, json); } catch { /* ignore */ }\n }\n // Fire-and-forget write to disk via dev server API\n if (typeof fetch !== \"undefined\") {\n fetch(\"/api/storage/custom-devices\", {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: json,\n }).catch(() => { /* dev server may be unavailable */ });\n }\n }\n}\n\n/** Singleton instance for the app */\nlet _defaultRegistry: DeviceRegistry | null = null;\n\nexport function getDeviceRegistry(): DeviceRegistry {\n if (!_defaultRegistry) {\n _defaultRegistry = new DeviceRegistry();\n }\n return _defaultRegistry;\n}\n\n/** Reset the singleton (for testing) */\nexport function resetDeviceRegistry(): void {\n _defaultRegistry = null;\n}\n","import type { DeviceMeta } from \"./types\";\nimport type { DeviceLayoutData } from \"./contract-types\";\nimport { getDeviceRegistry } from \"./custom/device-registry\";\n\n// iPhone 17 series (latest gen representatives)\nimport { IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_LAYOUT } from \"./ios/iphone-17-pro-max/metadata\";\nimport { IPHONE_17_PRO_META, IPHONE_17_PRO_LAYOUT } from \"./ios/iphone-17-pro/metadata\";\nimport { IPHONE_AIR_META, IPHONE_AIR_LAYOUT } from \"./ios/iphone-air/metadata\";\n\n// iPhone 16 series (unique screen classes only)\nimport { IPHONE_16_META, IPHONE_16_LAYOUT } from \"./ios/iphone-16/metadata\";\nimport { IPHONE_16E_META, IPHONE_16E_LAYOUT } from \"./ios/iphone-16e/metadata\";\n\n// iPhone SE\nimport { IPHONE_SE_3_META, IPHONE_SE_3_LAYOUT } from \"./ios/iphone-se-3/metadata\";\n\n// Galaxy S25 series\nimport { GALAXY_S25_ULTRA_META, GALAXY_S25_ULTRA_LAYOUT } from \"./android/galaxy-s25-ultra/metadata\";\nimport { GALAXY_S25_META, GALAXY_S25_LAYOUT } from \"./android/galaxy-s25/metadata\";\nimport { GALAXY_S25_EDGE_META, GALAXY_S25_EDGE_LAYOUT } from \"./android/galaxy-s25-edge/metadata\";\n\n// Pixel 9 series\nimport { PIXEL_9_PRO_XL_META, PIXEL_9_PRO_XL_LAYOUT } from \"./android/pixel-9-pro-xl/metadata\";\nimport { PIXEL_9_PRO_META, PIXEL_9_PRO_LAYOUT } from \"./android/pixel-9-pro/metadata\";\n\n/**\n * Built-in device metadata registry — 11 devices.\n *\n * Curated to cover every unique screen class (logical resolution).\n * Duplicate resolutions across generations are represented by the latest model.\n *\n * ALL DIMENSIONS VERIFIED:\n *\n * iPhone 17 Pro Max: 440×956pt @3x (covers iPhone 16 Pro Max)\n * iPhone 17 Pro: 402×874pt @3x (covers iPhone 16 Pro, iPhone 17)\n * iPhone Air: 420×912pt @3x (unique new size class)\n * iPhone 16: 393×852pt @3x (base Dynamic Island)\n * iPhone 16e: 390×844pt @3x (notch, unique width)\n * iPhone SE 3: 375×667pt @2x (legacy home-button form factor)\n * Galaxy S25 Ultra: 384×824dp @3.75x (covers S24 Ultra)\n * Galaxy S25: 360×780dp @3x (covers S24)\n * Galaxy S25 Edge: 382×824dp @3.75x (unique narrow form factor)\n * Pixel 9 Pro: 393×851dp @3x (covers Pixel 9, S25+)\n * Pixel 9 Pro XL: 448×968dp @3x (largest Android)\n */\nexport const BUILTIN_DEVICES: Record<string, DeviceMeta> = {\n // iPhone (latest gen per screen class)\n \"iphone-17-pro-max\": IPHONE_17_PRO_MAX_META,\n \"iphone-17-pro\": IPHONE_17_PRO_META,\n \"iphone-air\": IPHONE_AIR_META,\n \"iphone-16\": IPHONE_16_META,\n \"iphone-16e\": IPHONE_16E_META,\n \"iphone-se-3\": IPHONE_SE_3_META,\n // Android\n \"galaxy-s25-ultra\": GALAXY_S25_ULTRA_META,\n \"galaxy-s25\": GALAXY_S25_META,\n \"galaxy-s25-edge\": GALAXY_S25_EDGE_META,\n \"pixel-9-pro-xl\": PIXEL_9_PRO_XL_META,\n \"pixel-9-pro\": PIXEL_9_PRO_META,\n};\n\nexport const DEVICE_LAYOUTS: Record<string, DeviceLayoutData> = {\n // iPhone\n \"iphone-17-pro-max\": IPHONE_17_PRO_MAX_LAYOUT,\n \"iphone-17-pro\": IPHONE_17_PRO_LAYOUT,\n \"iphone-air\": IPHONE_AIR_LAYOUT,\n \"iphone-16\": IPHONE_16_LAYOUT,\n \"iphone-16e\": IPHONE_16E_LAYOUT,\n \"iphone-se-3\": IPHONE_SE_3_LAYOUT,\n // Android\n \"galaxy-s25-ultra\": GALAXY_S25_ULTRA_LAYOUT,\n \"galaxy-s25\": GALAXY_S25_LAYOUT,\n \"galaxy-s25-edge\": GALAXY_S25_EDGE_LAYOUT,\n \"pixel-9-pro-xl\": PIXEL_9_PRO_XL_LAYOUT,\n \"pixel-9-pro\": PIXEL_9_PRO_LAYOUT,\n};\n\n/**\n * Look up device metadata — checks built-in first, then custom registry.\n */\nexport function getDeviceMetadata(deviceId: string): DeviceMeta {\n const builtin = BUILTIN_DEVICES[deviceId];\n if (builtin) return builtin;\n\n // Check custom registry\n const custom = getDeviceRegistry().getMeta(deviceId);\n if (custom) return custom;\n\n throw new Error(\n `Device \"${deviceId}\" not found in built-in library or custom registry. ` +\n `Available devices: ${getAllDeviceIds().join(\", \") || \"(none yet)\"}`,\n );\n}\n\n/**\n * Get all device IDs — built-in + custom.\n */\nexport function getAllDeviceIds(): string[] {\n return [\n ...Object.keys(BUILTIN_DEVICES),\n ...getDeviceRegistry().listIds(),\n ];\n}\n","import type { DeviceLayoutContract, DeviceMeta, SafeAreaInsets, ContentRect } from \"./types\";\nimport { DEVICE_LAYOUTS } from \"./registry\";\nimport { getDeviceRegistry } from \"./custom/device-registry\";\n\nexport type { DeviceLayoutData } from \"./contract-types\";\n\n/** Derive the content zone from screen dimensions and safe area insets */\nexport function deriveContentZone(\n screenWidth: number,\n screenHeight: number,\n safeArea: SafeAreaInsets,\n): ContentRect {\n return {\n x: safeArea.left,\n y: safeArea.top,\n width: screenWidth - safeArea.left - safeArea.right,\n height: screenHeight - safeArea.top - safeArea.bottom,\n };\n}\n\n/** Build CSS variables from device data at REAL unscaled values */\nexport function buildCSSVariables(\n screen: DeviceMeta[\"screen\"],\n safeArea: SafeAreaInsets,\n statusBar: DeviceLayoutContract[\"statusBar\"],\n homeIndicator: DeviceLayoutContract[\"homeIndicator\"],\n hardwareOverlays: DeviceLayoutContract[\"hardwareOverlays\"],\n): DeviceLayoutContract[\"cssVariables\"] {\n const vars: DeviceLayoutContract[\"cssVariables\"] = {\n \"--device-width\": `${screen.width}px`,\n \"--device-height\": `${screen.height}px`,\n \"--safe-top\": `${safeArea.top}px`,\n \"--safe-bottom\": `${safeArea.bottom}px`,\n \"--safe-left\": `${safeArea.left}px`,\n \"--safe-right\": `${safeArea.right}px`,\n \"--status-bar-height\": `${statusBar.height}px`,\n \"--home-indicator-height\": `${homeIndicator.height}px`,\n \"--corner-radius\": `${screen.cornerRadius}px`,\n };\n\n if (hardwareOverlays.type !== \"none\") {\n vars[\"--island-width\"] = `${hardwareOverlays.portrait.width}px`;\n vars[\"--island-height\"] = `${hardwareOverlays.portrait.height}px`;\n }\n\n return vars;\n}\n\n/** Build the human-readable AI prompt constraints string */\nexport function buildAIPromptConstraints(\n contract: Omit<DeviceLayoutContract, \"aiPromptConstraints\">,\n): string {\n const sa = contract.safeArea.portrait;\n const cz = contract.contentZone.portrait;\n const overlay = contract.hardwareOverlays;\n\n const lines = [\n `Device: ${contract.device.name} (${contract.device.platform})`,\n `Screen: ${contract.screen.width}×${contract.screen.height} logical points`,\n `Content Zone: ${cz.x},${cz.y} → ${cz.width}×${cz.height}pt`,\n `Safe Area: top ${sa.top}pt, bottom ${sa.bottom}pt, left ${sa.left}pt, right ${sa.right}pt`,\n `Corner Radius: ${contract.screen.cornerRadius}pt`,\n ];\n\n if (overlay.type === \"dynamic-island\") {\n lines.push(\n `Hardware: Dynamic Island (pill) — ${overlay.portrait.width}×${overlay.portrait.height}pt at y=${overlay.portrait.y}`,\n );\n } else if (overlay.type === \"punch-hole\") {\n lines.push(\n `Hardware: Punch-hole camera (circle) — ${overlay.portrait.width}pt diameter at center top`,\n );\n }\n\n lines.push(\n `IMPORTANT: DO NOT render a status bar time/clock — BielaFrame renders a live clock overlay automatically.`,\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Get the full Device Layout Contract for a device.\n * This is the single source of truth that feeds both CSS variables and AI prompts.\n */\nexport function getDeviceContract(\n deviceId: string,\n orientation: \"portrait\" | \"landscape\" = \"portrait\",\n): DeviceLayoutContract {\n const layout = DEVICE_LAYOUTS[deviceId];\n if (!layout) {\n // Check custom registry — custom devices store a pre-computed contract\n const customContract = getDeviceRegistry().getContract(deviceId);\n if (customContract) return customContract;\n\n throw new Error(\n `Device layout \"${deviceId}\" not found. Available: ${Object.keys(DEVICE_LAYOUTS).join(\", \") || \"(none)\"}`,\n );\n }\n\n const { meta, safeArea, hardwareOverlays, statusBar, homeIndicator, hardwareButtons } = layout;\n\n const contentZone = {\n portrait: deriveContentZone(meta.screen.width, meta.screen.height, safeArea.portrait),\n landscape: deriveContentZone(meta.screen.height, meta.screen.width, safeArea.landscape),\n };\n\n const cssVariables = buildCSSVariables(\n meta.screen,\n safeArea[orientation],\n statusBar,\n homeIndicator,\n hardwareOverlays,\n );\n\n const partialContract = {\n device: {\n id: meta.id,\n name: meta.name,\n platform: meta.platform,\n year: meta.year,\n },\n screen: meta.screen,\n safeArea,\n hardwareOverlays,\n statusBar,\n homeIndicator,\n hardwareButtons,\n contentZone,\n cssVariables,\n };\n\n return {\n ...partialContract,\n aiPromptConstraints: buildAIPromptConstraints(partialContract),\n };\n}\n","/**\n * Extract the native coordinate space from an SVG string.\n *\n * Priority: viewBox → width/height attributes → fallback (390×844).\n * This tells us what coordinate space the SVG was authored in,\n * which may differ from the device's logical point dimensions.\n */\n\nexport interface SVGNativeDimensions {\n width: number;\n height: number;\n hasViewBox: boolean;\n source: \"viewBox\" | \"widthHeight\" | \"fallback\";\n}\n\nexport function parseSVGNativeDimensions(svgString: string): SVGNativeDimensions {\n // Extract <svg ...> tag attributes via regex (no DOM dependency for Node/test compatibility)\n const svgTagMatch = svgString.match(/<svg\\b[^>]*>/i);\n if (!svgTagMatch) {\n throw new Error(\"No <svg> element found in the provided string\");\n }\n const svgTag = svgTagMatch[0];\n\n // Priority 1: viewBox — most reliable\n const viewBoxMatch = svgTag.match(/viewBox\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (viewBoxMatch) {\n const parts = viewBoxMatch[1]!.trim().split(/[\\s,]+/).map(Number);\n if (parts.length >= 4) {\n const w = parts[2]!;\n const h = parts[3]!;\n if (!isNaN(w) && !isNaN(h) && w > 0 && h > 0) {\n return { width: w, height: h, hasViewBox: true, source: \"viewBox\" };\n }\n }\n }\n\n // Priority 2: width + height attributes\n const widthMatch = svgTag.match(/\\bwidth\\s*=\\s*[\"']?(\\d+\\.?\\d*)/i);\n const heightMatch = svgTag.match(/\\bheight\\s*=\\s*[\"']?(\\d+\\.?\\d*)/i);\n if (widthMatch && heightMatch) {\n const w = parseFloat(widthMatch[1]!);\n const h = parseFloat(heightMatch[1]!);\n if (w > 0 && h > 0) {\n return { width: w, height: h, hasViewBox: false, source: \"widthHeight\" };\n }\n }\n\n // Priority 3: fallback\n console.warn(\"[BielaFrame] SVG has no viewBox or width/height. Falling back to 390×844.\");\n return { width: 390, height: 844, hasViewBox: false, source: \"fallback\" };\n}\n","/**\n * Normalize an SVG to the canonical logical-point coordinate space.\n *\n * Takes an SVG that may be authored at physical pixels (e.g., 1206×2622 for iPhone 16 Pro at 3x)\n * and rewrites it to logical points (402×874). Also rescales all data-zone element coordinates.\n */\n\nimport { parseSVGNativeDimensions } from \"./parse-dimensions\";\n\nexport interface NormalizationResult {\n normalizedSVG: string;\n scaleFactors: { x: number; y: number };\n aspectRatioWarning: string | null;\n wasAlreadyNormalized: boolean;\n nativeDimensions: { width: number; height: number };\n}\n\nexport function normalizeSVGToLogicalPoints(\n svgString: string,\n targetWidth: number,\n targetHeight: number,\n): NormalizationResult {\n const native = parseSVGNativeDimensions(svgString);\n const scaleX = targetWidth / native.width;\n const scaleY = targetHeight / native.height;\n\n // Aspect ratio check\n const nativeAspect = native.width / native.height;\n const targetAspect = targetWidth / targetHeight;\n const diff = Math.abs(nativeAspect - targetAspect) / targetAspect;\n const aspectRatioWarning = diff > 0.02\n ? `SVG aspect ratio (${nativeAspect.toFixed(3)}) differs from declared device (${targetAspect.toFixed(3)}) by ${(diff * 100).toFixed(1)}%. Wrong SVG?`\n : null;\n\n // Already normalized — no transform needed\n if (Math.abs(scaleX - 1) < 0.001 && Math.abs(scaleY - 1) < 0.001) {\n return {\n normalizedSVG: svgString,\n scaleFactors: { x: 1, y: 1 },\n aspectRatioWarning,\n wasAlreadyNormalized: true,\n nativeDimensions: { width: native.width, height: native.height },\n };\n }\n\n let result = svgString;\n\n // Rewrite the <svg> tag's viewBox, width, height\n result = result.replace(\n /<svg\\b([^>]*)>/i,\n (_match, attrs: string) => {\n // Replace or add viewBox\n if (/viewBox/i.test(attrs)) {\n attrs = attrs.replace(/viewBox\\s*=\\s*[\"'][^\"']*[\"']/i, `viewBox=\"0 0 ${targetWidth} ${targetHeight}\"`);\n } else {\n attrs += ` viewBox=\"0 0 ${targetWidth} ${targetHeight}\"`;\n }\n\n // Replace width/height\n if (/\\bwidth\\s*=/i.test(attrs)) {\n attrs = attrs.replace(/\\bwidth\\s*=\\s*[\"']?\\d+\\.?\\d*[\"']?/i, `width=\"${targetWidth}\"`);\n } else {\n attrs += ` width=\"${targetWidth}\"`;\n }\n if (/\\bheight\\s*=/i.test(attrs)) {\n attrs = attrs.replace(/\\bheight\\s*=\\s*[\"']?\\d+\\.?\\d*[\"']?/i, `height=\"${targetHeight}\"`);\n } else {\n attrs += ` height=\"${targetHeight}\"`;\n }\n\n return `<svg${attrs}>`;\n },\n );\n\n // Rescale data-zone element coordinates\n const xAttrs = [\"x\", \"cx\", \"width\", \"rx\"];\n const yAttrs = [\"y\", \"cy\", \"height\", \"ry\"];\n const allAttrs = [...xAttrs, ...yAttrs];\n\n result = result.replace(\n /data-zone\\s*=\\s*[\"'][^\"']*[\"'][^>]*/gi,\n (elementContent) => {\n let updated = elementContent;\n for (const attr of allAttrs) {\n const regex = new RegExp(`\\\\b${attr}\\\\s*=\\\\s*[\"'](\\\\d+\\\\.?\\\\d*)[\"']`, \"gi\");\n updated = updated.replace(regex, (_, val: string) => {\n const num = parseFloat(val);\n const scale = xAttrs.includes(attr) ? scaleX : scaleY;\n return `${attr}=\"${(num * scale).toFixed(2)}\"`;\n });\n }\n return updated;\n },\n );\n\n return {\n normalizedSVG: result,\n scaleFactors: { x: scaleX, y: scaleY },\n aspectRatioWarning,\n wasAlreadyNormalized: false,\n nativeDimensions: { width: native.width, height: native.height },\n };\n}\n","/**\n * Parse an SVG with data-zone annotations into a DeviceLayoutContract.\n *\n * Reads `data-zone` attributes on SVG elements to extract:\n * - screen-area → screen dimensions\n * - safe-area-top / safe-area-bottom → safe area insets\n * - hardware-overlay → Dynamic Island / notch / punch-hole rect\n * - status-bar → status bar zone\n * - home-indicator → home indicator zone\n */\n\nimport type {\n DeviceLayoutContract,\n DeviceMeta,\n SafeAreaInsets,\n HardwareOverlayType,\n OverlayRect,\n} from \"../types\";\nimport { deriveContentZone, buildCSSVariables, buildAIPromptConstraints } from \"../contract\";\n\nexport interface ParsedZone {\n zone: string;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Extract all data-zone elements and their bounding attributes from SVG markup.\n */\nexport function extractZones(svgString: string): ParsedZone[] {\n const zones: ParsedZone[] = [];\n const regex = /data-zone\\s*=\\s*[\"']([^\"']+)[\"'][^>]*/gi;\n let match;\n\n while ((match = regex.exec(svgString)) !== null) {\n const zoneName = match[1]!;\n const element = match[0];\n\n const x = parseAttr(element, \"x\") ?? parseAttr(element, \"cx\") ?? 0;\n const y = parseAttr(element, \"y\") ?? parseAttr(element, \"cy\") ?? 0;\n const width = parseAttr(element, \"width\") ?? 0;\n const height = parseAttr(element, \"height\") ?? 0;\n\n zones.push({ zone: zoneName, x, y, width, height });\n }\n\n return zones;\n}\n\nfunction parseAttr(element: string, attr: string): number | null {\n const re = new RegExp(`\\\\b${attr}\\\\s*=\\\\s*[\"'](\\\\d+\\\\.?\\\\d*)[\"']`, \"i\");\n const m = element.match(re);\n return m ? parseFloat(m[1]!) : null;\n}\n\nexport interface ParseSVGContractOptions {\n /** Device metadata (id, name, platform, year, screen info) */\n meta: DeviceMeta;\n /** Hardware overlay type if known */\n overlayType?: HardwareOverlayType;\n /** Override overlay shape */\n overlayShape?: OverlayRect[\"shape\"];\n /** Status bar style override */\n statusBarStyle?: DeviceLayoutContract[\"statusBar\"][\"style\"];\n /** Home indicator type override */\n homeIndicatorType?: DeviceLayoutContract[\"homeIndicator\"][\"type\"];\n}\n\n/**\n * Build a full DeviceLayoutContract from a normalized SVG with data-zone annotations.\n */\nexport function parseSVGToContract(\n normalizedSVG: string,\n options: ParseSVGContractOptions,\n): DeviceLayoutContract {\n const { meta } = options;\n const zones = extractZones(normalizedSVG);\n const zoneMap = new Map(zones.map((z) => [z.zone, z]));\n\n // Screen area — use explicit zone or fall back to meta dimensions\n const screenZone = zoneMap.get(\"screen-area\");\n const screenWidth = screenZone?.width ?? meta.screen.width;\n const screenHeight = screenZone?.height ?? meta.screen.height;\n\n // Safe area insets\n const safeTop = zoneMap.get(\"safe-area-top\");\n const safeBottom = zoneMap.get(\"safe-area-bottom\");\n const safeLeft = zoneMap.get(\"safe-area-left\");\n const safeRight = zoneMap.get(\"safe-area-right\");\n\n const portraitSafeArea: SafeAreaInsets = {\n top: safeTop?.height ?? (meta.platform === \"ios\" ? 59 : 36),\n bottom: safeBottom?.height ?? (meta.platform === \"ios\" ? 34 : 0),\n left: safeLeft?.width ?? 0,\n right: safeRight?.width ?? 0,\n };\n\n // Landscape safe area (swap left/right for insets, reduce top/bottom)\n const landscapeSafeArea: SafeAreaInsets = {\n top: Math.min(portraitSafeArea.top, 21),\n bottom: Math.min(portraitSafeArea.bottom, 21),\n left: portraitSafeArea.top,\n right: portraitSafeArea.bottom,\n };\n\n // Hardware overlay\n const overlayZone = zoneMap.get(\"hardware-overlay\");\n const overlayType: HardwareOverlayType = options.overlayType\n ?? (overlayZone ? guessOverlayType(overlayZone, meta.platform) : \"none\");\n\n const overlayPortrait: OverlayRect = overlayZone\n ? {\n x: overlayZone.x,\n y: overlayZone.y,\n width: overlayZone.width,\n height: overlayZone.height,\n shape: options.overlayShape ?? guessOverlayShape(overlayType),\n }\n : { x: 0, y: 0, width: 0, height: 0, shape: \"pill\" };\n\n // Status bar\n const statusBarZone = zoneMap.get(\"status-bar\");\n const statusBarHeight = statusBarZone?.height ?? portraitSafeArea.top;\n const statusBarStyle = options.statusBarStyle\n ?? (overlayType === \"dynamic-island\" ? \"dynamic-island\"\n : overlayType === \"notch\" ? \"notch\"\n : \"fullwidth\");\n\n // Home indicator\n const homeZone = zoneMap.get(\"home-indicator\");\n const homeType = options.homeIndicatorType\n ?? (meta.platform === \"ios\" ? \"swipe-bar\" : \"gestureline\");\n const homeHeight = homeZone?.height ?? portraitSafeArea.bottom;\n\n const statusBar: DeviceLayoutContract[\"statusBar\"] = {\n height: statusBarHeight,\n style: statusBarStyle,\n hasTime: true,\n hasBattery: true,\n hasSignal: true,\n };\n\n const homeIndicator: DeviceLayoutContract[\"homeIndicator\"] = {\n type: homeType,\n height: homeHeight,\n width: homeZone?.width,\n visible: homeHeight > 0,\n };\n\n const contentZone = {\n portrait: deriveContentZone(screenWidth, screenHeight, portraitSafeArea),\n landscape: deriveContentZone(screenHeight, screenWidth, landscapeSafeArea),\n };\n\n const cssVariables = buildCSSVariables(\n meta.screen,\n portraitSafeArea,\n statusBar,\n homeIndicator,\n { type: overlayType, portrait: overlayPortrait },\n );\n\n const partialContract = {\n device: {\n id: meta.id,\n name: meta.name,\n platform: meta.platform,\n year: meta.year,\n },\n screen: meta.screen,\n safeArea: {\n portrait: portraitSafeArea,\n landscape: landscapeSafeArea,\n },\n hardwareOverlays: {\n type: overlayType,\n portrait: overlayPortrait,\n },\n statusBar,\n homeIndicator,\n contentZone,\n cssVariables,\n };\n\n return {\n ...partialContract,\n aiPromptConstraints: buildAIPromptConstraints(partialContract),\n };\n}\n\nfunction guessOverlayType(zone: ParsedZone, platform: \"ios\" | \"android\"): HardwareOverlayType {\n if (platform === \"ios\") {\n // Dynamic Island: wider than tall, relatively small\n if (zone.width > zone.height * 2) return \"dynamic-island\";\n // Notch: wider than tall but taller than DI\n if (zone.width > zone.height) return \"notch\";\n return \"dynamic-island\";\n }\n // Android: typically punch-hole (circular) or pill-cutout\n if (Math.abs(zone.width - zone.height) < 4) return \"punch-hole\";\n return \"pill-cutout\";\n}\n\nfunction guessOverlayShape(type: HardwareOverlayType): OverlayRect[\"shape\"] {\n switch (type) {\n case \"dynamic-island\": return \"pill\";\n case \"notch\": return \"rectangle\";\n case \"punch-hole\": return \"circle\";\n case \"pill-cutout\": return \"pill\";\n default: return \"pill\";\n }\n}\n","/**\n * Pre-registration validation for normalized SVGs.\n *\n * Checks that the normalization result is sane before registering a custom device.\n */\n\nimport type { NormalizationResult } from \"./normalize\";\nimport { extractZones } from \"./parse-contract\";\n\nexport interface ValidationResult {\n passed: boolean;\n warnings: string[];\n errors: string[];\n}\n\n/**\n * Validate a normalized SVG before registration.\n */\nexport function validateNormalizedSVG(\n result: NormalizationResult,\n targetWidth: number,\n targetHeight: number,\n): ValidationResult {\n const warnings: string[] = [];\n const errors: string[] = [];\n\n // 1. Aspect ratio warning\n if (result.aspectRatioWarning) {\n warnings.push(result.aspectRatioWarning);\n }\n\n // 2. Extreme scale factors (> 5x likely means wrong SVG dimensions)\n const maxScale = Math.max(result.scaleFactors.x, result.scaleFactors.y);\n if (maxScale > 5) {\n warnings.push(\n `Scale factor is ${maxScale.toFixed(1)}x — the SVG may be authored at a much larger coordinate space than expected. Verify the SVG dimensions.`,\n );\n }\n\n // 3. Very small scale factors (< 0.1x means SVG is tiny)\n const minScale = Math.min(result.scaleFactors.x, result.scaleFactors.y);\n if (minScale > 0 && minScale < 0.1) {\n warnings.push(\n `Scale factor is ${minScale.toFixed(3)}x — the SVG appears to be very small. Verify you're using the correct export size.`,\n );\n }\n\n // 4. Check that native dimensions are positive\n if (result.nativeDimensions.width <= 0 || result.nativeDimensions.height <= 0) {\n errors.push(\"SVG has zero or negative dimensions. Check the viewBox or width/height attributes.\");\n }\n\n // 5. Check for required zones in the normalized SVG\n const zones = extractZones(result.normalizedSVG);\n const zoneNames = new Set(zones.map((z) => z.zone));\n\n if (!zoneNames.has(\"screen-area\")) {\n warnings.push(\n 'No \"screen-area\" data-zone found. The screen region will use the full device dimensions.',\n );\n }\n\n // 6. Check that target dimensions are reasonable\n if (targetWidth < 100 || targetHeight < 100) {\n errors.push(\n `Target dimensions ${targetWidth}×${targetHeight} are unusually small. Expected logical device dimensions (e.g., 390×844).`,\n );\n }\n\n if (targetWidth > 1500 || targetHeight > 3000) {\n warnings.push(\n `Target dimensions ${targetWidth}×${targetHeight} are unusually large. Expected logical points, not physical pixels.`,\n );\n }\n\n // 7. Scale factor X vs Y divergence (non-uniform scaling)\n if (result.scaleFactors.x > 0 && result.scaleFactors.y > 0) {\n const scaleDiff = Math.abs(result.scaleFactors.x - result.scaleFactors.y) /\n Math.max(result.scaleFactors.x, result.scaleFactors.y);\n if (scaleDiff > 0.05) {\n warnings.push(\n `Non-uniform scaling: X=${result.scaleFactors.x.toFixed(3)}, Y=${result.scaleFactors.y.toFixed(3)}. The SVG aspect ratio may not match the target device.`,\n );\n }\n }\n\n return {\n passed: errors.length === 0,\n warnings,\n errors,\n };\n}\n","/**\n * Scope all SVG IDs to a device-specific prefix to prevent collisions\n * when multiple device frames are rendered on the same page.\n *\n * Rewrites:\n * - id=\"foo\" → id=\"deviceId__foo\"\n * - url(#foo) → url(#deviceId__foo)\n * - href=\"#foo\" → href=\"#deviceId__foo\"\n * - xlink:href=\"#foo\" → xlink:href=\"#deviceId__foo\"\n */\nexport function scopeSVGIds(svgString: string, deviceId: string): string {\n // Collect all IDs in the SVG\n const ids: string[] = [];\n const idRegex = /\\bid\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let match;\n while ((match = idRegex.exec(svgString)) !== null) {\n ids.push(match[1]!);\n }\n\n if (ids.length === 0) return svgString;\n\n let result = svgString;\n const prefix = `${deviceId}__`;\n\n // Replace each ID and all its references\n for (const id of ids) {\n const escapedId = id.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n // id=\"...\" declarations\n result = result.replace(\n new RegExp(`\\\\bid\\\\s*=\\\\s*[\"']${escapedId}[\"']`, \"g\"),\n `id=\"${prefix}${id}\"`,\n );\n\n // url(#...) references\n result = result.replace(\n new RegExp(`url\\\\(\\\\s*#${escapedId}\\\\s*\\\\)`, \"g\"),\n `url(#${prefix}${id})`,\n );\n\n // href=\"#...\" references\n result = result.replace(\n new RegExp(`href\\\\s*=\\\\s*[\"']#${escapedId}[\"']`, \"g\"),\n `href=\"#${prefix}${id}\"`,\n );\n }\n\n return result;\n}\n","/**\n * Auto-detect device zones from SVG structure.\n *\n * Two-pass approach:\n * 1. Name-based: scan element IDs/classes/data-attributes for known keywords\n * 2. Geometric heuristics: analyze ALL rects by size, position, fill, and corner radius\n * to identify screen area, dynamic island, phone body, and side buttons\n *\n * The geometric pass is critical for real-world Figma SVGs that use auto-generated\n * IDs like \"clip0_44_55\" with no semantic naming.\n */\n\nexport interface DetectedZone {\n id: string;\n /** The zone type we inferred */\n type: ZoneType;\n /** The SVG element's original id/name that matched */\n sourceLabel: string;\n /** Which keyword matched */\n matchedKeyword: string;\n /** Confidence: \"high\" for exact keyword match, \"medium\" for partial */\n confidence: \"high\" | \"medium\";\n /** Bounding box in SVG coordinate space */\n x: number;\n y: number;\n width: number;\n height: number;\n /** Corner radius (from SVG rx attribute), only for screen-area zones */\n rx?: number;\n}\n\nexport type ZoneType =\n | \"screen-area\"\n | \"hardware-overlay\"\n | \"safe-area-top\"\n | \"safe-area-bottom\"\n | \"safe-area-left\"\n | \"safe-area-right\"\n | \"status-bar\"\n | \"home-indicator\"\n | \"hardware-button\";\n\n/**\n * Result of analyzing the SVG geometry — includes both zones and structural info.\n */\nexport interface SVGAnalysis {\n /** Detected zones for the Zone Tagger */\n zones: DetectedZone[];\n /** Phone body bounding rect (largest rounded rect), if found */\n phoneBody: { x: number; y: number; width: number; height: number; rx: number } | null;\n /** Rects identified as external side buttons */\n sideButtons: { x: number; y: number; width: number; height: number }[];\n /** All extracted rects for debugging */\n allRects: RectInfo[];\n}\n\n/** Internal rect representation with fill/rx info */\ninterface RectInfo {\n x: number;\n y: number;\n width: number;\n height: number;\n rx: number;\n fill: string | null;\n id: string | null;\n}\n\n/** Keywords that map to zone types — ordered by priority (first match wins per zone type) */\nconst ZONE_KEYWORDS: { type: ZoneType; keywords: string[]; highConfidence: string[] }[] = [\n {\n type: \"screen-area\",\n keywords: [\"screen\", \"display\", \"viewport\", \"content-area\", \"screen-area\", \"screenarea\"],\n highConfidence: [\"screen\", \"screen-area\", \"display\"],\n },\n {\n type: \"hardware-overlay\",\n keywords: [\n \"island\", \"dynamic-island\", \"dynamicisland\", \"dynamic_island\",\n \"notch\", \"cutout\", \"punch-hole\", \"punchhole\", \"punch_hole\",\n \"camera\", \"faceid\", \"face-id\", \"truedepth\", \"sensor\",\n \"pill\", \"camera-housing\",\n ],\n highConfidence: [\"island\", \"dynamic-island\", \"notch\", \"cutout\", \"punch-hole\"],\n },\n {\n type: \"safe-area-top\",\n keywords: [\"safe-area-top\", \"safe-top\", \"safeareatop\", \"status-area\", \"top-inset\"],\n highConfidence: [\"safe-area-top\", \"safe-top\"],\n },\n {\n type: \"safe-area-bottom\",\n keywords: [\"safe-area-bottom\", \"safe-bottom\", \"safeareabottom\", \"bottom-inset\"],\n highConfidence: [\"safe-area-bottom\", \"safe-bottom\"],\n },\n {\n type: \"status-bar\",\n keywords: [\"status-bar\", \"statusbar\", \"status_bar\", \"status\"],\n highConfidence: [\"status-bar\", \"statusbar\"],\n },\n {\n type: \"home-indicator\",\n keywords: [\n \"home-indicator\", \"homeindicator\", \"home_indicator\",\n \"home-bar\", \"homebar\", \"swipe-bar\", \"swipebar\",\n \"gesture-bar\", \"gesturebar\", \"bottom-bar\",\n ],\n highConfidence: [\"home-indicator\", \"home-bar\", \"swipe-bar\", \"gesture-bar\"],\n },\n {\n type: \"hardware-button\",\n keywords: [\n \"volume-up\", \"volume_up\", \"volumeup\", \"vol-up\",\n \"volume-down\", \"volume_down\", \"volumedown\", \"vol-down\",\n \"power\", \"power-button\", \"side-button\", \"sidebutton\",\n \"action-button\", \"action_button\", \"actionbutton\",\n \"mute\", \"silent\", \"ringer\",\n \"hardware-button\", \"hardwarebutton\", \"hw-button\",\n ],\n highConfidence: [\"volume-up\", \"volume-down\", \"power\", \"action-button\", \"side-button\"],\n },\n];\n\n/**\n * Auto-detect zones using both name-based and geometric approaches.\n * Falls back to geometric heuristics when name-based detection finds nothing.\n */\nexport function autoDetectZones(svgString: string): DetectedZone[] {\n // First try name-based detection (works with well-named SVGs)\n const nameBasedZones = detectByNames(svgString);\n if (nameBasedZones.length > 0) return nameBasedZones;\n\n // Fall back to geometric heuristics (works with Figma exports)\n const analysis = analyzeSVGGeometry(svgString);\n return analysis.zones;\n}\n\n/**\n * Full SVG analysis — returns zones plus structural info (phone body, side buttons).\n * Used by the Registration Wizard for bezel calculation and button handling.\n */\nexport function analyzeSVGGeometry(svgString: string): SVGAnalysis {\n const rects = extractAllRects(svgString);\n const viewBox = extractViewBox(svgString);\n\n const svgW = viewBox?.w ?? 0;\n const svgH = viewBox?.h ?? 0;\n const svgArea = svgW * svgH;\n\n if (svgArea === 0) {\n return { zones: [], phoneBody: null, sideButtons: [], allRects: rects };\n }\n\n // ── Step 1: Find the phone body (largest rounded rect covering most of the SVG) ──\n const phoneBody = findPhoneBody(rects, svgW, svgH);\n\n // ── Step 2: Find the screen area (largest white/light filled rect inside phone body) ──\n let screenRect = findScreenArea(rects, phoneBody, svgW, svgH);\n\n // If no screen rect found, try to detect from path cutouts (Figma ring paths)\n if (!screenRect) {\n const pathCutout = findPathCutoutScreen(svgString, svgW, svgH);\n if (pathCutout) {\n screenRect = pathCutout;\n }\n }\n\n // If no screen rect found but we have a phone body, synthesize a screen area\n // from the body with a small bezel inset (common in SVGs where body = screen background)\n if (!screenRect && phoneBody) {\n const insetRatio = 0.043; // ~4.3% inset typical for iPhone body-to-screen ratio\n const insetX = Math.round(phoneBody.width * insetRatio);\n const insetY = Math.round(phoneBody.height * (insetRatio * 0.5)); // less vertical inset\n screenRect = {\n x: phoneBody.x + insetX,\n y: phoneBody.y + insetY,\n width: phoneBody.width - insetX * 2,\n height: phoneBody.height - insetY * 2,\n rx: Math.max(phoneBody.rx - insetX, 20),\n fill: \"synthetic\",\n id: null,\n };\n }\n\n // ── Step 3: Find Dynamic Island (small pill-shaped black rect near top of screen) ──\n const islandRect = findDynamicIsland(rects, screenRect);\n\n // ── Step 4: Identify side buttons (small rects outside the phone body) ──\n const sideButtons = findSideButtons(rects, phoneBody);\n\n // ── Build detected zones ──\n const zones: DetectedZone[] = [];\n const now = Date.now();\n\n if (screenRect) {\n const isSynthetic = screenRect.fill === \"synthetic\";\n zones.push({\n id: `auto-screen-area-${now}`,\n type: \"screen-area\",\n sourceLabel: isSynthetic ? \"geometric: inferred from body\" : \"geometric: largest white rect\",\n matchedKeyword: \"geometry\",\n confidence: isSynthetic ? \"medium\" : \"high\",\n x: screenRect.x,\n y: screenRect.y,\n width: screenRect.width,\n height: screenRect.height,\n rx: screenRect.rx > 0 ? screenRect.rx : undefined,\n });\n }\n\n if (islandRect) {\n zones.push({\n id: `auto-hardware-overlay-${now}`,\n type: \"hardware-overlay\",\n sourceLabel: \"geometric: pill near top\",\n matchedKeyword: \"geometry\",\n confidence: \"medium\",\n x: islandRect.x,\n y: islandRect.y,\n width: islandRect.width,\n height: islandRect.height,\n });\n }\n\n return {\n zones,\n phoneBody: phoneBody\n ? { x: phoneBody.x, y: phoneBody.y, width: phoneBody.width, height: phoneBody.height, rx: phoneBody.rx }\n : null,\n sideButtons: sideButtons.map(r => ({ x: r.x, y: r.y, width: r.width, height: r.height })),\n allRects: rects,\n };\n}\n\n// ── Geometric detection helpers ──\n\nfunction findPhoneBody(\n rects: RectInfo[],\n svgW: number,\n svgH: number,\n): RectInfo | null {\n // The phone body is typically the largest rect with significant corner radius\n // covering a large portion of the SVG area\n const svgArea = svgW * svgH;\n const candidates = rects\n .filter(r => {\n const area = r.width * r.height;\n // Must cover at least 30% of SVG area\n if (area < svgArea * 0.3) return false;\n // Must have rounded corners (rx >= 20 in typical phone SVGs)\n if (r.rx < 20) return false;\n // Must be tall (phone form factor: h > w * 1.5)\n if (r.height < r.width * 1.3) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n return candidates[0] ?? null;\n}\n\nfunction findScreenArea(\n rects: RectInfo[],\n phoneBody: RectInfo | null,\n svgW: number,\n svgH: number,\n): RectInfo | null {\n const refRect = phoneBody ?? { x: 0, y: 0, width: svgW, height: svgH };\n\n // Look for a large rect with a light fill (white, #fff, etc.) inside the phone body\n const candidates = rects\n .filter(r => {\n // Must be inside or mostly overlapping the phone body\n if (!isInsideRect(r, refRect, 0.05)) return false;\n // Must cover at least 50% of the phone body area\n const bodyArea = refRect.width * refRect.height;\n const area = r.width * r.height;\n if (area < bodyArea * 0.5) return false;\n // Must be smaller than the phone body\n if (area >= bodyArea * 0.98) return false;\n // Should have a light fill (white, light grey) — screen area in Figma exports\n if (!isLightFill(r.fill)) return false;\n // Must have rounded corners\n if (r.rx < 10) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n if (candidates[0]) return candidates[0];\n\n // Fallback: if no light-fill rect found, look for the largest filled rect inside the body\n // that isn't the body itself (some SVGs use a mid-tone or transparent screen rect)\n const fallbackCandidates = rects\n .filter(r => {\n if (!isInsideRect(r, refRect, 0.05)) return false;\n const bodyArea = refRect.width * refRect.height;\n const area = r.width * r.height;\n if (area < bodyArea * 0.5) return false;\n if (area >= bodyArea * 0.98) return false;\n if (r.rx < 10) return false;\n // Skip rects with no fill — these are stroke-only decorative elements (bezels, borders)\n if (!r.fill || r.fill === \"none\") return false;\n // Skip gradient/url fills — these are decorative effects\n if (r.fill.startsWith(\"url(\")) return false;\n // Skip dark fills that are likely the body background\n if (isDarkFill(r.fill)) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n return fallbackCandidates[0] ?? null;\n}\n\nfunction findDynamicIsland(\n rects: RectInfo[],\n screenRect: RectInfo | null,\n): RectInfo | null {\n if (!screenRect) return null;\n\n const candidates = rects\n .filter(r => {\n // Must be small relative to screen (< 15% of screen width)\n if (r.width > screenRect.width * 0.5) return false;\n if (r.width < screenRect.width * 0.05) return false;\n // Must be pill-shaped: width > height, both > 0, with rounded corners\n if (r.width <= r.height) return false;\n const ratio = r.width / r.height;\n if (ratio < 1.5 || ratio > 8) return false;\n if (r.rx < 5) return false;\n // Must be near the top of the screen area (top 10%)\n const topThreshold = screenRect.y + screenRect.height * 0.10;\n if (r.y > topThreshold) return false;\n if (r.y < screenRect.y) return false;\n // Must be roughly centered horizontally in the screen\n const rCenterX = r.x + r.width / 2;\n const screenCenterX = screenRect.x + screenRect.width / 2;\n const maxOffCenter = screenRect.width * 0.25;\n if (Math.abs(rCenterX - screenCenterX) > maxOffCenter) return false;\n // Must have dark fill (black)\n if (!isDarkFill(r.fill)) return false;\n return true;\n })\n .sort((a, b) => (b.width * b.height) - (a.width * a.height));\n\n return candidates[0] ?? null;\n}\n\nfunction findSideButtons(\n rects: RectInfo[],\n phoneBody: RectInfo | null,\n): RectInfo[] {\n if (!phoneBody) return [];\n\n return rects.filter(r => {\n // Must be a small rect\n const area = r.width * r.height;\n const bodyArea = phoneBody.width * phoneBody.height;\n if (area > bodyArea * 0.02) return false; // < 2% of body\n if (area < 10) return false; // not a tiny artifact\n\n // Must be outside the phone body on the left or right edge\n const isOutsideLeft = r.x + r.width < phoneBody.x + phoneBody.width * 0.05;\n const isOutsideRight = r.x > phoneBody.x + phoneBody.width * 0.95;\n\n if (!isOutsideLeft && !isOutsideRight) return false;\n\n // Must be vertically within the phone body range\n if (r.y + r.height < phoneBody.y) return false;\n if (r.y > phoneBody.y + phoneBody.height) return false;\n\n // Should be elongated vertically (button-shaped) or small square\n // Buttons are typically taller than wide\n return true;\n });\n}\n\n/**\n * Classify detected side buttons into specific hardware button types.\n *\n * Classification strategy based on real device button placement:\n * - LEFT side (iOS): action button (top), volume up (middle-top), volume down (middle-bottom)\n * - LEFT side (Android): volume up (top), volume down (bottom)\n * - RIGHT side: power button (top/middle), camera control (lower, if present)\n *\n * Uses vertical position and size to distinguish buttons.\n */\nexport interface ClassifiedButton {\n type: \"volume-up\" | \"volume-down\" | \"power\" | \"action\" | \"camera\";\n side: \"left\" | \"right\";\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport function classifySideButtons(\n sideButtons: { x: number; y: number; width: number; height: number }[],\n phoneBody: { x: number; y: number; width: number; height: number } | null,\n): ClassifiedButton[] {\n if (!phoneBody || sideButtons.length === 0) return [];\n\n const bodyMidX = phoneBody.x + phoneBody.width / 2;\n const classified: ClassifiedButton[] = [];\n\n // Split buttons by side\n const leftButtons = sideButtons\n .filter(b => (b.x + b.width / 2) < bodyMidX)\n .sort((a, b) => a.y - b.y); // top to bottom\n\n const rightButtons = sideButtons\n .filter(b => (b.x + b.width / 2) >= bodyMidX)\n .sort((a, b) => a.y - b.y); // top to bottom\n\n // ── Classify left side buttons ──\n // Find pairs of similarly-sized buttons close together (volume up/down)\n if (leftButtons.length >= 2) {\n // Find the best volume pair: two buttons closest in size and vertically adjacent\n let bestPairI = -1;\n let bestPairJ = -1;\n let bestScore = Infinity;\n\n for (let i = 0; i < leftButtons.length; i++) {\n for (let j = i + 1; j < leftButtons.length; j++) {\n const a = leftButtons[i]!, b = leftButtons[j]!;\n const areaA = a.width * a.height;\n const areaB = b.width * b.height;\n const sizeDiff = Math.abs(areaA - areaB) / Math.max(areaA, areaB);\n const gap = b.y - (a.y + a.height);\n // Volume buttons: similar size, small gap between them\n if (sizeDiff < 0.5 && gap < a.height * 3 && gap > -a.height) {\n const score = sizeDiff * 100 + Math.abs(gap);\n if (score < bestScore) {\n bestScore = score;\n bestPairI = i;\n bestPairJ = j;\n }\n }\n }\n }\n\n if (bestPairI >= 0 && bestPairJ >= 0) {\n classified.push({\n type: \"volume-up\",\n side: \"left\",\n ...leftButtons[bestPairI]!,\n });\n classified.push({\n type: \"volume-down\",\n side: \"left\",\n ...leftButtons[bestPairJ]!,\n });\n\n // Remaining left buttons: classify as action button\n for (let i = 0; i < leftButtons.length; i++) {\n if (i !== bestPairI && i !== bestPairJ) {\n classified.push({\n type: \"action\",\n side: \"left\",\n ...leftButtons[i]!,\n });\n }\n }\n } else {\n // Can't find a volume pair — just assign top two as volume\n classified.push({ type: \"volume-up\", side: \"left\", ...leftButtons[0]! });\n classified.push({ type: \"volume-down\", side: \"left\", ...leftButtons[1]! });\n for (let i = 2; i < leftButtons.length; i++) {\n classified.push({ type: \"action\", side: \"left\", ...leftButtons[i]! });\n }\n }\n } else if (leftButtons.length === 1) {\n // Single left button — assume volume up (or it could be a sim tray, skip)\n classified.push({ type: \"volume-up\", side: \"left\", ...leftButtons[0]! });\n }\n\n // ── Classify right side buttons ──\n if (rightButtons.length >= 2) {\n // Power button is usually the larger one or higher up\n // Camera control is lower and often smaller or circular\n const sorted = [...rightButtons].sort((a, b) => a.y - b.y);\n classified.push({ type: \"power\", side: \"right\", ...sorted[0]! });\n for (let i = 1; i < sorted.length; i++) {\n classified.push({ type: \"camera\", side: \"right\", ...sorted[i]! });\n }\n } else if (rightButtons.length === 1) {\n classified.push({ type: \"power\", side: \"right\", ...rightButtons[0]! });\n }\n\n return classified;\n}\n\n// ── Path cutout detection ──\n// Many Figma SVGs use <path> elements with two subpaths (M...Z M...Z) to create\n// a ring shape for the phone bezel. The inner cutout defines the screen area.\n\nfunction findPathCutoutScreen(\n svgString: string,\n svgW: number,\n svgH: number,\n): RectInfo | null {\n const svgArea = svgW * svgH;\n // Find <path> elements with a fill (not inside defs/mask/filter)\n const pathRegex = /<path\\b([^>]*?)\\/>/gi;\n let match;\n const candidates: { inner: { x: number; y: number; w: number; h: number }; rx: number; fill: string }[] = [];\n\n while ((match = pathRegex.exec(svgString)) !== null) {\n const attrs = match[1]!;\n // Skip paths inside non-visual parents\n const preceding = svgString.slice(0, match.index);\n if (isInsideNonVisualParent(preceding)) continue;\n\n const fill = getAttrValue(attrs, \"fill\");\n // Skip dark fills and unfilled paths (these aren't bezel rings)\n if (!fill || isDarkFill(fill)) continue;\n // Skip gradient/url fills\n if (fill.startsWith(\"url(\")) continue;\n\n const d = getAttrValue(attrs, \"d\");\n if (!d) continue;\n\n // Split path into subpaths at Z (case insensitive)\n const subpaths = d.split(/[Zz]/).filter(s => s.trim().length > 0);\n if (subpaths.length < 2) continue;\n\n // Extract bounding boxes of outer (first) and inner (second) subpaths\n const outerBB = subpathBBox(subpaths[0]!);\n const innerBB = subpathBBox(subpaths[1]!);\n\n if (!outerBB || !innerBB) continue;\n\n // The outer should cover most of the SVG area\n const outerArea = outerBB.w * outerBB.h;\n if (outerArea < svgArea * 0.3) continue;\n\n // The inner should be smaller than the outer but still substantial\n const innerArea = innerBB.w * innerBB.h;\n if (innerArea < outerArea * 0.5 || innerArea >= outerArea * 0.98) continue;\n\n // The inner should be phone-shaped (taller than wide)\n if (innerBB.h < innerBB.w * 1.3) continue;\n\n // The inner should be inside the outer\n if (innerBB.x < outerBB.x || innerBB.y < outerBB.y) continue;\n if (innerBB.x + innerBB.w > outerBB.x + outerBB.w + 5) continue;\n if (innerBB.y + innerBB.h > outerBB.y + outerBB.h + 5) continue;\n\n // Estimate corner radius from the bezel width (~proportion of inner size)\n const estimatedRx = Math.round(Math.min(innerBB.w, innerBB.h) * 0.04);\n\n candidates.push({ inner: innerBB, rx: Math.max(estimatedRx, 20), fill });\n }\n\n if (candidates.length === 0) return null;\n\n // Pick the candidate with the largest inner area\n candidates.sort((a, b) => (b.inner.w * b.inner.h) - (a.inner.w * a.inner.h));\n const best = candidates[0]!;\n\n return {\n x: best.inner.x,\n y: best.inner.y,\n width: best.inner.w,\n height: best.inner.h,\n rx: best.rx,\n fill: \"path-cutout\",\n id: null,\n };\n}\n\n/** Extract bounding box from a single subpath by parsing SVG path commands */\nfunction subpathBBox(subpath: string): { x: number; y: number; w: number; h: number } | null {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n let curX = 0, curY = 0;\n\n function addPoint(x: number, y: number) {\n if (!isFinite(x) || !isFinite(y)) return;\n minX = Math.min(minX, x); minY = Math.min(minY, y);\n maxX = Math.max(maxX, x); maxY = Math.max(maxY, y);\n curX = x; curY = y;\n }\n\n // Tokenize: split into commands and numbers\n const tokens = subpath.match(/[MmLlHhVvCcSsQqTtAaZz]|-?\\d+\\.?\\d*(?:e[+-]?\\d+)?/gi);\n if (!tokens || tokens.length < 3) return null;\n\n const toks = tokens;\n let i = 0;\n function nextNum(): number { return i < toks.length ? parseFloat(toks[i++]!) : 0; }\n\n while (i < toks.length) {\n const cmd = toks[i]!;\n if (/^[A-Za-z]$/.test(cmd)) {\n i++;\n switch (cmd) {\n case \"M\": case \"L\": addPoint(nextNum(), nextNum()); break;\n case \"m\": case \"l\": addPoint(curX + nextNum(), curY + nextNum()); break;\n case \"H\": addPoint(nextNum(), curY); break;\n case \"h\": addPoint(curX + nextNum(), curY); break;\n case \"V\": addPoint(curX, nextNum()); break;\n case \"v\": addPoint(curX, curY + nextNum()); break;\n case \"C\": { nextNum(); nextNum(); nextNum(); nextNum(); addPoint(nextNum(), nextNum()); break; }\n case \"c\": { nextNum(); nextNum(); nextNum(); nextNum(); addPoint(curX + nextNum(), curY + nextNum()); break; }\n case \"S\": case \"Q\": { nextNum(); nextNum(); addPoint(nextNum(), nextNum()); break; }\n case \"s\": case \"q\": { nextNum(); nextNum(); addPoint(curX + nextNum(), curY + nextNum()); break; }\n case \"T\": addPoint(nextNum(), nextNum()); break;\n case \"t\": addPoint(curX + nextNum(), curY + nextNum()); break;\n case \"A\": { nextNum(); nextNum(); nextNum(); nextNum(); nextNum(); addPoint(nextNum(), nextNum()); break; }\n case \"a\": { nextNum(); nextNum(); nextNum(); nextNum(); nextNum(); addPoint(curX + nextNum(), curY + nextNum()); break; }\n default: break;\n }\n } else {\n i++; // skip unexpected tokens\n }\n }\n\n if (!isFinite(minX) || maxX - minX < 10 || maxY - minY < 10) return null;\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\n}\n\n// ── Fill color analysis ──\n\nfunction isLightFill(fill: string | null): boolean {\n if (!fill) return false;\n const f = fill.toLowerCase().trim();\n if (f === \"white\" || f === \"#fff\" || f === \"#ffffff\") return true;\n if (f === \"rgb(255,255,255)\" || f === \"rgb(255, 255, 255)\") return true;\n // Check hex colors — if all components > 0xCC, it's \"light\"\n const hex6 = f.match(/^#([0-9a-f]{6})$/);\n if (hex6) {\n const r = parseInt(hex6[1]!.slice(0, 2), 16);\n const g = parseInt(hex6[1]!.slice(2, 4), 16);\n const b = parseInt(hex6[1]!.slice(4, 6), 16);\n return r > 200 && g > 200 && b > 200;\n }\n return false;\n}\n\nfunction isDarkFill(fill: string | null): boolean {\n if (!fill) return false;\n const f = fill.toLowerCase().trim();\n if (f === \"black\" || f === \"#000\" || f === \"#000000\") return true;\n if (f.startsWith(\"rgb(0\") || f === \"rgb(0,0,0)\" || f === \"rgb(0, 0, 0)\") return true;\n const hex6 = f.match(/^#([0-9a-f]{6})$/);\n if (hex6) {\n const r = parseInt(hex6[1]!.slice(0, 2), 16);\n const g = parseInt(hex6[1]!.slice(2, 4), 16);\n const b = parseInt(hex6[1]!.slice(4, 6), 16);\n return r < 50 && g < 50 && b < 50;\n }\n return false;\n}\n\n// ── Geometry helpers ──\n\n/** Check if rect `inner` is (mostly) inside `outer`, with tolerance as fraction */\nfunction isInsideRect(\n inner: RectInfo,\n outer: { x: number; y: number; width: number; height: number },\n tolerance: number,\n): boolean {\n const tolX = outer.width * tolerance;\n const tolY = outer.height * tolerance;\n return (\n inner.x >= outer.x - tolX &&\n inner.y >= outer.y - tolY &&\n inner.x + inner.width <= outer.x + outer.width + tolX &&\n inner.y + inner.height <= outer.y + outer.height + tolY\n );\n}\n\n// ── SVG parsing helpers ──\n\nfunction extractViewBox(svgString: string): { x: number; y: number; w: number; h: number } | null {\n const vbMatch = svgString.match(/<svg\\b[^>]*viewBox\\s*=\\s*[\"']([^\"']*)[\"']/i);\n if (vbMatch) {\n const parts = vbMatch[1]!.trim().split(/[\\s,]+/).map(Number);\n if (parts.length >= 4 && parts.every(n => isFinite(n))) {\n return { x: parts[0]!, y: parts[1]!, w: parts[2]!, h: parts[3]! };\n }\n }\n // Fallback to width/height attributes\n const wMatch = svgString.match(/<svg\\b[^>]*\\bwidth\\s*=\\s*[\"']?(\\d+\\.?\\d*)[\"']?/i);\n const hMatch = svgString.match(/<svg\\b[^>]*\\bheight\\s*=\\s*[\"']?(\\d+\\.?\\d*)[\"']?/i);\n if (wMatch && hMatch) {\n return { x: 0, y: 0, w: parseFloat(wMatch[1]!), h: parseFloat(hMatch[1]!) };\n }\n return null;\n}\n\n/**\n * Extract ALL <rect> elements from SVG, regardless of whether they have names.\n * This is the key difference from `extractSVGElements` which only returns named elements.\n */\nfunction extractAllRects(svgString: string): RectInfo[] {\n const rects: RectInfo[] = [];\n const regex = /<rect\\b([^>]*?)(?:\\/>|>[^<]*<\\/rect>)/gi;\n let match;\n\n while ((match = regex.exec(svgString)) !== null) {\n const attrs = match[1]!;\n\n // Skip rects inside <defs>, <clipPath>, <mask>, <filter> — they're not visual\n const preceding = svgString.slice(0, match.index);\n if (isInsideNonVisualParent(preceding)) continue;\n\n const x = getNumAttr(attrs, \"x\");\n const y = getNumAttr(attrs, \"y\");\n const width = getNumAttr(attrs, \"width\");\n const height = getNumAttr(attrs, \"height\");\n\n // Skip zero-size rects\n if (width <= 0 || height <= 0) continue;\n\n // Handle transform=\"matrix(-1 0 0 1 X Y)\" which mirrors the rect\n const transformedPos = applyTransformToRect(attrs, x, y, width, height);\n\n const rx = Math.max(getNumAttr(attrs, \"rx\"), getNumAttr(attrs, \"ry\"));\n const fill = getAttrValue(attrs, \"fill\");\n const id = getAttrValue(attrs, \"id\");\n\n rects.push({\n x: transformedPos.x,\n y: transformedPos.y,\n width: transformedPos.width,\n height: transformedPos.height,\n rx,\n fill,\n id,\n });\n }\n\n return rects;\n}\n\n/**\n * Check if the current position in the SVG is inside a non-visual parent like\n * <defs>, <clipPath>, <mask>, or <filter>.\n */\nfunction isInsideNonVisualParent(preceding: string): boolean {\n const nonVisualTags = [\"defs\", \"clipPath\", \"mask\", \"filter\"];\n for (const tag of nonVisualTags) {\n const openCount = countOccurrences(preceding, `<${tag}`);\n const closeCount = countOccurrences(preceding, `</${tag}`);\n if (openCount > closeCount) return true;\n }\n return false;\n}\n\nfunction countOccurrences(str: string, substr: string): number {\n let count = 0;\n let pos = 0;\n while ((pos = str.indexOf(substr, pos)) !== -1) {\n count++;\n pos += substr.length;\n }\n return count;\n}\n\n/**\n * Apply a simple SVG transform (matrix) to a rect's position.\n * Handles the common Figma pattern: transform=\"matrix(-1 0 0 1 X Y)\"\n */\nfunction applyTransformToRect(\n attrs: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): { x: number; y: number; width: number; height: number } {\n const transformAttr = getAttrValue(attrs, \"transform\");\n if (!transformAttr) return { x, y, width, height };\n\n // Handle matrix(-1 0 0 1 tx ty) — horizontal mirror\n const matrixMatch = transformAttr.match(\n /matrix\\(\\s*(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s+(-?[\\d.]+)\\s*\\)/,\n );\n if (matrixMatch) {\n const a = parseFloat(matrixMatch[1]!);\n const d = parseFloat(matrixMatch[4]!);\n const tx = parseFloat(matrixMatch[5]!);\n const ty = parseFloat(matrixMatch[6]!);\n\n if (a === -1 && d === 1) {\n // Horizontal mirror: new x = tx - x - width\n return { x: tx - x - width, y: y + ty, width, height };\n }\n if (a === 1 && d === -1) {\n // Vertical mirror: new y = ty - y - height\n return { x: x + tx, y: ty - y - height, width, height };\n }\n // General translation\n if (a === 1 && d === 1) {\n return { x: x + tx, y: y + ty, width, height };\n }\n }\n\n return { x, y, width, height };\n}\n\n// ── Name-based detection (original approach) ──\n\nfunction detectByNames(svgString: string): DetectedZone[] {\n const detected: DetectedZone[] = [];\n const usedTypes = new Set<ZoneType>();\n const elements = extractSVGElements(svgString);\n\n for (const el of elements) {\n const identifiers = [\n el.id, el.className, el.dataName, el.dataZone, el.ariaLabel,\n ].filter(Boolean).map(s => s!.toLowerCase());\n\n for (const zoneConfig of ZONE_KEYWORDS) {\n if (usedTypes.has(zoneConfig.type)) continue;\n\n for (const keyword of zoneConfig.keywords) {\n const matched = identifiers.some(ident =>\n ident === keyword ||\n ident.includes(keyword) ||\n ident.replace(/[_\\s]/g, \"-\").includes(keyword),\n );\n\n if (matched) {\n const confidence = zoneConfig.highConfidence.some(hk =>\n identifiers.some(ident => ident === hk || ident.includes(hk)),\n ) ? \"high\" as const : \"medium\" as const;\n\n detected.push({\n id: `auto-${zoneConfig.type}-${Date.now()}`,\n type: zoneConfig.type,\n sourceLabel: el.id || el.dataName || el.className || el.ariaLabel || \"unknown\",\n matchedKeyword: keyword,\n confidence,\n x: el.x, y: el.y, width: el.width, height: el.height,\n });\n\n usedTypes.add(zoneConfig.type);\n break;\n }\n }\n }\n }\n\n return detected;\n}\n\n// ── Element parsing for name-based detection ──\n\ninterface SVGElementInfo {\n tag: string;\n id: string | null;\n className: string | null;\n dataName: string | null;\n dataZone: string | null;\n ariaLabel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nfunction extractSVGElements(svgString: string): SVGElementInfo[] {\n const elements: SVGElementInfo[] = [];\n const tagRegex = /<(rect|g|path|circle|ellipse|use|foreignObject|image)\\b([^>]*?)(?:\\/>|>)/gi;\n let match;\n\n while ((match = tagRegex.exec(svgString)) !== null) {\n const tag = match[1]!.toLowerCase();\n const attrs = match[2]!;\n\n const id = getAttrValue(attrs, \"id\");\n const className = getAttrValue(attrs, \"class\");\n const dataName = getAttrValue(attrs, \"data-name\");\n const dataZone = getAttrValue(attrs, \"data-zone\");\n const ariaLabel = getAttrValue(attrs, \"aria-label\");\n\n if (!id && !className && !dataName && !dataZone && !ariaLabel) continue;\n\n const bbox = extractBBox(tag, attrs);\n elements.push({ tag, id, className, dataName, dataZone, ariaLabel, ...bbox });\n }\n\n return elements;\n}\n\nfunction getAttrValue(attrs: string, name: string): string | null {\n const re = new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']([^\"']*)[\"']`, \"i\");\n const m = attrs.match(re);\n return m ? m[1]! : null;\n}\n\nfunction getNumAttr(attrs: string, name: string): number {\n const re = new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']([\\\\d.]+)[\"']`, \"i\");\n const m = attrs.match(re);\n return m ? parseFloat(m[1]!) : 0;\n}\n\nfunction extractBBox(\n tag: string,\n attrs: string,\n): { x: number; y: number; width: number; height: number } {\n switch (tag) {\n case \"rect\":\n case \"foreignobject\":\n case \"image\":\n return {\n x: getNumAttr(attrs, \"x\"),\n y: getNumAttr(attrs, \"y\"),\n width: getNumAttr(attrs, \"width\"),\n height: getNumAttr(attrs, \"height\"),\n };\n\n case \"circle\": {\n const cx = getNumAttr(attrs, \"cx\");\n const cy = getNumAttr(attrs, \"cy\");\n const r = getNumAttr(attrs, \"r\");\n return { x: cx - r, y: cy - r, width: r * 2, height: r * 2 };\n }\n\n case \"ellipse\": {\n const cx = getNumAttr(attrs, \"cx\");\n const cy = getNumAttr(attrs, \"cy\");\n const rx = getNumAttr(attrs, \"rx\");\n const ry = getNumAttr(attrs, \"ry\");\n return { x: cx - rx, y: cy - ry, width: rx * 2, height: ry * 2 };\n }\n\n case \"path\":\n return extractPathBBox(attrs);\n\n case \"g\":\n case \"use\":\n return {\n x: getNumAttr(attrs, \"x\"),\n y: getNumAttr(attrs, \"y\"),\n width: getNumAttr(attrs, \"width\"),\n height: getNumAttr(attrs, \"height\"),\n };\n\n default:\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n}\n\nfunction extractPathBBox(\n attrs: string,\n): { x: number; y: number; width: number; height: number } {\n const dAttr = getAttrValue(attrs, \"d\");\n if (!dAttr) return { x: 0, y: 0, width: 0, height: 0 };\n\n const nums = dAttr.match(/-?\\d+\\.?\\d*/g);\n if (!nums || nums.length < 4) return { x: 0, y: 0, width: 0, height: 0 };\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = 0; i < nums.length - 1; i += 2) {\n const x = parseFloat(nums[i]!);\n const y = parseFloat(nums[i + 1]!);\n if (isFinite(x) && isFinite(y)) {\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n }\n }\n\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Get a list of all identifiable SVG element names for UI display.\n */\nexport function listSVGLayerNames(svgString: string): { tag: string; name: string }[] {\n const elements = extractSVGElements(svgString);\n return elements.map(el => ({\n tag: el.tag,\n name: el.id || el.dataName || el.className || el.ariaLabel || `<${el.tag}>`,\n }));\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { D as DeviceMeta, a as DeviceLayoutData, b as DeviceLayoutContract, S as SafeAreaInsets, C as ContentRect, H as HardwareOverlayType, O as OverlayRect, R as RegisteredDevice } from './contract-types-Cw1rmF3b.cjs';
|
|
2
2
|
export { c as DeviceCSSVariables, d as DeviceFrameInfo, e as SVGCropRect, f as SVGScreenRect } from './contract-types-Cw1rmF3b.cjs';
|
|
3
|
-
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_META, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './ios/index.cjs';
|
|
3
|
+
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_SCREEN_RECT, IPHONE_17_PRO_META, IPHONE_17_PRO_SCREEN_RECT, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './ios/index.cjs';
|
|
4
4
|
export { GALAXY_S25_EDGE_FRAME, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_EDGE_META, GALAXY_S25_FRAME, GALAXY_S25_LAYOUT, GALAXY_S25_META, GALAXY_S25_ULTRA_FRAME, GALAXY_S25_ULTRA_LAYOUT, GALAXY_S25_ULTRA_META, GalaxyS25EdgeSVG, GalaxyS25SVG, GalaxyS25UltraSVG, PIXEL_9_PRO_FRAME, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_META, PIXEL_9_PRO_XL_FRAME, PIXEL_9_PRO_XL_LAYOUT, PIXEL_9_PRO_XL_META, Pixel9ProSVG, Pixel9ProXLSVG } from './android/index.cjs';
|
|
5
5
|
import 'react/jsx-runtime';
|
|
6
6
|
|