storeshot 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/CONTRIBUTING.md +75 -0
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/SECURITY.md +25 -0
- package/THIRD_PARTY_LICENSES.txt +668 -0
- package/THIRD_PARTY_NOTICES.md +93 -0
- package/dist/cli.js +1458 -0
- package/dist/cli.js.map +1 -0
- package/dist/ui/artwork/tabler/LICENSE +21 -0
- package/dist/ui/artwork/tabler/README.md +23 -0
- package/dist/ui/artwork/tabler/filled/grid-pattern.svg +13 -0
- package/dist/ui/artwork/tabler/filled/laurel-wreath-1.svg +13 -0
- package/dist/ui/artwork/tabler/filled/laurel-wreath-2.svg +13 -0
- package/dist/ui/artwork/tabler/filled/laurel-wreath-3.svg +13 -0
- package/dist/ui/artwork/tabler/filled/laurel-wreath.svg +13 -0
- package/dist/ui/artwork/tabler/filled/sparkles.svg +15 -0
- package/dist/ui/artwork/tabler/filled/stars.svg +15 -0
- package/dist/ui/artwork/tabler/outline/scribble.svg +19 -0
- package/dist/ui/artwork/tabler/outline/underline.svg +20 -0
- package/dist/ui/assets/AssetsView-D0lbK5rm.js +1 -0
- package/dist/ui/assets/SetEditor-BBUlgGT0.js +440 -0
- package/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/ui/assets/index-DPDaBFld.js +10 -0
- package/dist/ui/assets/index-DfZBqsD3.css +2 -0
- package/dist/ui/assets/shared-BiRg4I01.js +1 -0
- package/dist/ui/index.html +14 -0
- package/dist/ui/licenses/geist-OFL-1.1.txt +93 -0
- package/dist/ui/mockup-bundles/frameup-free/LICENSE +21 -0
- package/dist/ui/mockup-bundles/frameup-free/README.md +12 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/imac-pro.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/imac-retina.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/imac.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-air-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-air-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-air-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-mini-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-mini-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-mini-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-11-silver-landscape.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-11-silver-portrait.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-11-space-gray-landscape.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-11-space-gray-portrait.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-13-silver-landscape.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-13-silver-portrait.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-13-space-gray-landscape.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-pro-13-space-gray-portrait.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/ipad-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-black.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-green.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-max-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-max-midnight-green.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-max-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-max-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-midnight-green.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-pro-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-purple.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-red.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-white.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-11-yellow.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-13-pro-max.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-13-pro.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-14-pro-max-no-cutout.svg +4 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-14-pro-max.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-14-pro-no-cutout.svg +4 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-14-pro.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-15-pro-max-no-cutout.svg +4 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-15-pro-max.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-15-pro-no-cutout.svg +4 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-15-pro.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-16-pro-max-no-cutout.svg +10 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-16-pro-max.svg +11 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-16-pro-no-cutout.svg +4 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-16-pro.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-17-pro-max-no-cutout.svg +4 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-17-pro-max.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-17-pro-no-cutout.svg +4 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-17-pro.svg +5 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5c-blue.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5c-green.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5c-red.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5c-white.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5c-yellow.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5s-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5s-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-5s-space-gray.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-plus-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-plus-rose-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-plus-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-plus-space-gray.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-rose-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-6s-space-gray.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-jet-black.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-matte-black.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-plus-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-plus-jet-black.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-plus-matte-black.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-plus-rose-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-plus-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-rose-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-7-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-8-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-8-plus-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-8-plus-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-8-plus-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-8-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-8-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-se-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-se-rose-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-se-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-se-space-gray.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-x-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-x-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xr-blue.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xr-coral.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xr-red.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xr-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xr-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xr-yellow.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xs-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xs-max-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xs-max-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xs-max-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xs-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/iphone-xs-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-air-13-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-air-13-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-air-13-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-gold.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-pro-13-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-pro-13-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-pro-15-silver.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-pro-15-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/macbook-space-grey.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/pro-display-xdr.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/assets/thunderbolt-display.png +0 -0
- package/dist/ui/mockup-bundles/frameup-free/storeshot-mockups.json +2279 -0
- package/docs/mockup-bundles.md +104 -0
- package/docs/releasing.md +155 -0
- package/package.json +85 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/server.ts","../src/project-store.ts","../src/device-mockups.ts","../src/image-metadata.ts","../src/screenshot-area.ts","../src/shared.ts"],"sourcesContent":["import path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { Command, Option } from \"commander\"\nimport open from \"open\"\n\nimport { startServer } from \"./server.js\"\n\nconst sourceFile = fileURLToPath(import.meta.url)\nconst packageRoot = path.resolve(path.dirname(sourceFile), \"..\")\nconst isSourceExecution = path.extname(sourceFile) === \".ts\"\n\nconst program = new Command()\n .name(\"storeshot\")\n .description(\"Manage app store screenshots locally\")\n .version(\"0.1.0\")\n\nprogram\n .command(\"dev\")\n .description(\"Open a StoreShot workspace for a local directory\")\n .argument(\"[directory]\", \"project directory\", \".\")\n .addOption(new Option(\"-p, --port <port>\", \"local server port\").default(\"4173\"))\n .addOption(new Option(\"--host <host>\", \"local server host\").default(\"127.0.0.1\"))\n .option(\"--no-open\", \"do not open a browser\")\n .action(async (directory: string, options: { port: string; host: string; open: boolean }) => {\n const port = Number(options.port)\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(\"Port must be an integer between 1 and 65535\")\n }\n\n const projectDirectory = path.resolve(directory)\n const service = await startServer({\n host: options.host,\n port,\n packageRoot,\n projectDirectory,\n useVite: isSourceExecution,\n })\n const url = `http://${options.host}:${port}`\n\n console.log(`\\n StoreShot is ready at ${url}`)\n console.log(` Project: ${service.store.root}\\n`)\n\n if (options.open) await open(url)\n\n const shutdown = async () => {\n await service.close()\n process.exit(0)\n }\n process.once(\"SIGINT\", shutdown)\n process.once(\"SIGTERM\", shutdown)\n })\n\nprogram.parseAsync().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error)\n console.error(`storeshot: ${message}`)\n process.exitCode = 1\n})\n","import { createReadStream } from \"node:fs\"\nimport { readFile, stat } from \"node:fs/promises\"\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport path from \"node:path\"\n\nimport type { ViteDevServer } from \"vite\"\n\nimport { DuplicateAssetError, ProjectStore } from \"./project-store.js\"\nimport type { StoreShotConfig, AssetCategory, CreateSetInput, ScreenshotSet, UpdateAssetMetadataInput, UpdateSetMetadataInput } from \"./shared.js\"\n\nconst MAX_REQUEST_BYTES = 25 * 1024 * 1024\n\ninterface StartServerOptions {\n host: string\n port: number\n packageRoot: string\n projectDirectory: string\n useVite: boolean\n}\n\nexport async function startServer(options: StartServerOptions) {\n const store = new ProjectStore(options.projectDirectory)\n await store.initialize()\n\n let vite: ViteDevServer | undefined\n if (options.useVite) {\n const { createServer: createViteServer } = await import(\"vite\")\n vite = await createViteServer({\n configFile: path.join(options.packageRoot, \"vite.config.ts\"),\n server: { middlewareMode: true },\n appType: \"spa\",\n })\n }\n\n const server = createServer(async (request, response) => {\n try {\n if ((request.url ?? \"\").startsWith(\"/api/\")) assertAllowedBrowserRequest(request, options.host)\n if (await handleApiRequest(request, response, store)) return\n if (vite) {\n vite.middlewares(request, response)\n return\n }\n await serveBuiltFrontend(request, response, path.join(options.packageRoot, \"dist/ui\"))\n } catch (error) {\n const failure = httpFailureFor(error, request)\n if (failure.status >= 500) console.error(error)\n if (!response.headersSent) sendJson(response, failure.status, { error: failure.message, ...(failure.code ? { code: failure.code } : {}) })\n else response.end()\n }\n })\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(options.port, options.host, resolve)\n })\n\n return {\n store,\n port: (server.address() as AddressInfo).port,\n close: async () => {\n await vite?.close()\n await new Promise<void>((resolve, reject) => {\n server.close((error) => (error ? reject(error) : resolve()))\n })\n },\n }\n}\n\nasync function handleApiRequest(\n request: IncomingMessage,\n response: ServerResponse,\n store: ProjectStore,\n): Promise<boolean> {\n const url = new URL(request.url ?? \"/\", \"http://localhost\")\n\n if (request.method === \"GET\" && url.pathname === \"/api/project\") {\n sendJson(response, 200, await store.readProject())\n return true\n }\n\n if (request.method === \"GET\" && url.pathname === \"/api/mockup-bundles\") {\n sendJson(response, 200, await store.listMockupCatalog())\n return true\n }\n\n const mockupBundleImportFileMatch = url.pathname.match(/^\\/api\\/mockup-bundle-imports\\/([^/]+)\\/([^/]+)\\/files\\/(.+)$/)\n if (request.method === \"PUT\" && mockupBundleImportFileMatch) {\n const importId = decodeURIComponent(mockupBundleImportFileMatch[1])\n const bundleId = decodeURIComponent(mockupBundleImportFileMatch[2])\n const relativePath = mockupBundleImportFileMatch[3].split(\"/\").map(decodeURIComponent).join(\"/\")\n await store.writeMockupBundleImportFile(importId, bundleId, relativePath, await readBody(request))\n response.writeHead(204).end()\n return true\n }\n\n const mockupBundleImportMatch = url.pathname.match(/^\\/api\\/mockup-bundle-imports\\/([^/]+)\\/([^/]+)$/)\n if (request.method === \"PUT\" && mockupBundleImportMatch) {\n const importId = decodeURIComponent(mockupBundleImportMatch[1])\n const bundleId = decodeURIComponent(mockupBundleImportMatch[2])\n await store.commitMockupBundleImport(importId, bundleId, await readJsonBody(request))\n sendJson(response, 200, await store.listMockupCatalog())\n return true\n }\n\n const mockupBundleImportDiscardMatch = url.pathname.match(/^\\/api\\/mockup-bundle-imports\\/([^/]+)$/)\n if (request.method === \"DELETE\" && mockupBundleImportDiscardMatch) {\n await store.discardMockupBundleImport(decodeURIComponent(mockupBundleImportDiscardMatch[1]))\n response.writeHead(204).end()\n return true\n }\n\n const mockupBundleMatch = url.pathname.match(/^\\/api\\/mockup-bundles\\/([^/]+)$/)\n if (request.method === \"PUT\" && mockupBundleMatch) {\n const bundleId = decodeURIComponent(mockupBundleMatch[1])\n await store.writeMockupBundleManifest(bundleId, await readJsonBody(request))\n sendJson(response, 200, await store.listMockupCatalog())\n return true\n }\n\n const mockupBundleFileMatch = url.pathname.match(/^\\/api\\/mockup-bundle-files\\/([^/]+)\\/(.+)$/)\n if (mockupBundleFileMatch) {\n const bundleId = decodeURIComponent(mockupBundleFileMatch[1])\n const relativePath = mockupBundleFileMatch[2].split(\"/\").map(decodeURIComponent).join(\"/\")\n if (request.method === \"PUT\") {\n await store.writeMockupBundleFile(bundleId, relativePath, await readBody(request))\n response.writeHead(204).end()\n return true\n }\n if (request.method === \"GET\") {\n const target = await store.resolveExistingMockupBundleFile(bundleId, relativePath)\n const metadata = await stat(target)\n response.writeHead(200, {\n \"Content-Type\": contentTypeFor(target),\n \"Content-Length\": metadata.size,\n \"Cache-Control\": \"no-store\",\n \"X-Content-Type-Options\": \"nosniff\",\n ...(path.extname(target).toLowerCase() === \".svg\" ? { \"Content-Security-Policy\": \"default-src 'none'; style-src 'unsafe-inline'; sandbox\" } : {}),\n })\n createReadStream(target).pipe(response)\n return true\n }\n }\n\n if (request.method === \"PATCH\" && url.pathname === \"/api/config\") {\n const config = await store.writeConfig((await readJsonBody(request)) as StoreShotConfig)\n sendJson(response, 200, config)\n return true\n }\n\n if (request.method === \"POST\" && url.pathname === \"/api/assets\") {\n const category = url.searchParams.get(\"category\")\n const filename = url.searchParams.get(\"filename\")\n if (!category || !filename) {\n sendJson(response, 400, { error: \"A category and filename are required\" })\n return true\n }\n let replaced = false\n try {\n const result = await store.addAsset(category, filename, await readBody(request))\n replaced = result.replaced\n } catch (error) {\n if (error instanceof DuplicateAssetError) {\n sendJson(response, 409, { error: error.message, code: \"DUPLICATE_ASSET\" })\n return true\n }\n throw error\n }\n sendJson(response, replaced ? 200 : 201, { replaced })\n return true\n }\n\n const assetMatch = url.pathname.match(/^\\/api\\/assets\\/([^/]+)\\/([^/]+)$/)\n if (assetMatch) {\n const category = decodeURIComponent(assetMatch[1]) as AssetCategory\n const filename = decodeURIComponent(assetMatch[2])\n if (request.method === \"GET\") {\n const target = await store.resolveExistingAsset(category, filename)\n const metadata = await stat(target)\n response.writeHead(200, {\n \"Content-Type\": contentTypeFor(target),\n \"Content-Length\": metadata.size,\n \"Cache-Control\": \"no-store\",\n \"X-Content-Type-Options\": \"nosniff\",\n ...(path.extname(target).toLowerCase() === \".svg\" ? { \"Content-Security-Policy\": \"default-src 'none'; style-src 'unsafe-inline'; sandbox\" } : {}),\n })\n createReadStream(target).pipe(response)\n return true\n }\n\n if (request.method === \"DELETE\") {\n await store.deleteAsset(category, filename)\n response.writeHead(204).end()\n return true\n }\n\n if (request.method === \"PATCH\") {\n await store.updateAssetMetadata(category, filename, (await readJsonBody(request)) as UpdateAssetMetadataInput)\n sendJson(response, 200, await store.readProject())\n return true\n }\n }\n\n if (request.method === \"POST\" && url.pathname === \"/api/sets\") {\n const set = await store.createSet((await readJsonBody(request)) as CreateSetInput)\n sendJson(response, 201, set)\n return true\n }\n\n const duplicateSetMatch = url.pathname.match(/^\\/api\\/sets\\/([^/]+)\\/duplicate$/)\n if (request.method === \"POST\" && duplicateSetMatch) {\n const set = await store.duplicateSet(decodeURIComponent(duplicateSetMatch[1]))\n sendJson(response, 201, set)\n return true\n }\n\n const setMatch = url.pathname.match(/^\\/api\\/sets\\/([^/]+)$/)\n if (setMatch) {\n const id = decodeURIComponent(setMatch[1])\n if (request.method === \"PATCH\") {\n const set = await store.updateSetMetadata(id, (await readJsonBody(request)) as UpdateSetMetadataInput)\n sendJson(response, 200, set)\n return true\n }\n if (request.method === \"PUT\") {\n const set = await store.writeSet(id, (await readJsonBody(request)) as ScreenshotSet)\n sendJson(response, 200, set)\n return true\n }\n if (request.method === \"DELETE\") {\n await store.deleteSet(id)\n response.writeHead(204).end()\n return true\n }\n }\n\n if (url.pathname.startsWith(\"/api/\")) {\n sendJson(response, 404, { error: \"Not found\" })\n return true\n }\n return false\n}\n\nasync function serveBuiltFrontend(request: IncomingMessage, response: ServerResponse, uiDirectory: string) {\n const url = new URL(request.url ?? \"/\", \"http://localhost\")\n const relativePath = url.pathname === \"/\" ? \"index.html\" : decodeURIComponent(url.pathname.slice(1))\n const candidate = path.resolve(uiDirectory, relativePath)\n const safeRoot = `${path.resolve(uiDirectory)}${path.sep}`\n const target = candidate.startsWith(safeRoot) ? candidate : path.join(uiDirectory, \"index.html\")\n\n try {\n const metadata = await stat(target)\n if (!metadata.isFile()) throw new Error(\"Not a file\")\n const body = await readFile(target)\n response.writeHead(200, { \"Content-Type\": contentTypeFor(target), \"Content-Length\": body.length })\n response.end(body)\n } catch {\n const body = await readFile(path.join(uiDirectory, \"index.html\"))\n response.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" })\n response.end(body)\n }\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<unknown> {\n const contentType = request.headers[\"content-type\"]?.split(\";\", 1)[0]?.trim().toLowerCase()\n if (contentType !== \"application/json\") throw new HttpError(415, \"Request body must use application/json\")\n const body = await readBody(request)\n try {\n return JSON.parse(body.toString(\"utf8\"))\n } catch {\n throw new HttpError(400, \"Request body must be valid JSON\")\n }\n}\n\nasync function readBody(request: IncomingMessage): Promise<Buffer> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += buffer.length\n if (size > MAX_REQUEST_BYTES) throw new HttpError(413, \"Request is larger than 25 MB\")\n chunks.push(buffer)\n }\n return Buffer.concat(chunks)\n}\n\nclass HttpError extends Error {\n constructor(readonly status: number, message: string, readonly code?: string) {\n super(message)\n }\n}\n\nfunction assertAllowedBrowserRequest(request: IncomingMessage, configuredHost: string): void {\n const host = request.headers.host\n if (!host) throw new HttpError(400, \"A Host header is required\")\n\n let hostUrl: URL\n try {\n hostUrl = new URL(`http://${host}`)\n } catch {\n throw new HttpError(400, \"The Host header is invalid\")\n }\n const configuredHostname = normalizedHostname(configuredHost)\n if (!isLoopbackHostname(hostUrl.hostname) && hostUrl.hostname !== configuredHostname) {\n throw new HttpError(403, \"This StoreShot server does not accept requests for that host\")\n }\n\n const origin = request.headers.origin\n if (!origin) return\n let originUrl: URL\n try {\n originUrl = new URL(origin)\n } catch {\n throw new HttpError(403, \"The request origin is invalid\")\n }\n if ((originUrl.protocol !== \"http:\" && originUrl.protocol !== \"https:\") || originUrl.host !== host) {\n throw new HttpError(403, \"Cross-origin API requests are not allowed\")\n }\n}\n\nfunction normalizedHostname(host: string): string {\n try {\n return new URL(`http://${host}`).hostname\n } catch {\n return host.replace(/^\\[|\\]$/g, \"\")\n }\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n return hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"::1\"\n}\n\nfunction httpFailureFor(error: unknown, request: IncomingMessage): HttpError {\n if (error instanceof HttpError) return error\n if (error instanceof DuplicateAssetError) return new HttpError(409, error.message, \"DUPLICATE_ASSET\")\n const code = (error as NodeJS.ErrnoException | undefined)?.code\n if (code === \"ENOENT\") return new HttpError(404, \"The requested project file was not found\")\n if (code === \"EACCES\" || code === \"EPERM\") return new HttpError(403, \"StoreShot cannot access that project file\")\n if (isMutation(request) && error instanceof Error && !code) return new HttpError(400, error.message)\n return new HttpError(500, \"StoreShot could not complete the request\")\n}\n\nfunction isMutation(request: IncomingMessage): boolean {\n return request.method === \"POST\" || request.method === \"PUT\" || request.method === \"PATCH\" || request.method === \"DELETE\"\n}\n\nfunction sendJson(response: ServerResponse, status: number, value: unknown) {\n const body = JSON.stringify(value)\n response.writeHead(status, {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Content-Length\": Buffer.byteLength(body),\n })\n response.end(body)\n}\n\nfunction contentTypeFor(filename: string): string {\n switch (path.extname(filename).toLowerCase()) {\n case \".html\": return \"text/html; charset=utf-8\"\n case \".js\": return \"text/javascript; charset=utf-8\"\n case \".css\": return \"text/css; charset=utf-8\"\n case \".png\": return \"image/png\"\n case \".jpg\":\n case \".jpeg\": return \"image/jpeg\"\n case \".webp\": return \"image/webp\"\n case \".svg\": return \"image/svg+xml\"\n case \".md\":\n case \".txt\": return \"text/plain; charset=utf-8\"\n default: return \"application/octet-stream\"\n }\n}\n","import { createHash, randomUUID } from \"node:crypto\"\nimport { constants } from \"node:fs\"\nimport { access, lstat, mkdir, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport {\n MOCKUP_BUNDLE_FILENAME,\n bundleAssetPaths,\n emptyDeviceMockupCatalog,\n isSafeBundlePath,\n mergeDeviceMockupCatalogs,\n parseMockupBundleManifest,\n resolveMockupBundle,\n type DeviceMockupCatalog,\n type MockupBundleManifest,\n} from \"./device-mockups.js\"\nimport { detectScreenshotDeviceType, readImageMetadata } from \"./image-metadata.js\"\nimport { cloneScreenshotArea } from \"./screenshot-area.js\"\n\nimport {\n ASSET_CATEGORIES,\n type StoreShotConfig,\n type StoreShotProject,\n type Asset,\n type AssetCategory,\n type CanvasElement,\n type CreateSetInput,\n type FontWeight,\n type ImageElementSource,\n type ScreenshotArea,\n type ScreenshotSet,\n SCREENSHOT_DEVICE_TYPES,\n type ScreenshotDeviceType,\n type UpdateAssetMetadataInput,\n type UpdateSetMetadataInput,\n} from \"./shared.js\"\n\nexport const CONFIG_FILENAME = \"storeshot.json\"\nexport const ASSETS_DIRECTORY = \"assets\"\nexport const SETS_DIRECTORY = \"sets\"\nexport const ASSET_METADATA_FILENAME = \".storeshot-metadata.json\"\nexport const MOCKUP_BUNDLES_DIRECTORY = \"mockup-bundles\"\nconst MOCKUP_IMPORTS_DIRECTORY = \".imports\"\n\nconst supportedExtensions = new Set([\".png\", \".jpg\", \".jpeg\", \".webp\", \".svg\"])\nconst supportedMockupBundleExtensions = new Set([\".jpeg\", \".jpg\", \".md\", \".png\", \".svg\", \".txt\", \".webp\"])\nconst safeIdentifierPattern = /^[a-z0-9][a-z0-9-]*$/\nconst hexColorPattern = /^#[0-9a-f]{6}$/i\n\nexport class ProjectStore {\n readonly root: string\n readonly configPath: string\n readonly assetsPath: string\n readonly setsPath: string\n readonly mockupBundlesPath: string\n readonly mockupImportsPath: string\n private readonly operations = new Map<string, Promise<void>>()\n private readonly assetHashes = new Map<string, { hash: string; mtimeMs: number; size: number }>()\n\n constructor(directory: string) {\n this.root = path.resolve(directory)\n this.configPath = path.join(this.root, CONFIG_FILENAME)\n this.assetsPath = path.join(this.root, ASSETS_DIRECTORY)\n this.setsPath = path.join(this.root, SETS_DIRECTORY)\n this.mockupBundlesPath = path.join(this.root, MOCKUP_BUNDLES_DIRECTORY)\n this.mockupImportsPath = path.join(this.mockupBundlesPath, MOCKUP_IMPORTS_DIRECTORY)\n }\n\n async initialize(): Promise<void> {\n await mkdir(this.root, { recursive: true })\n await this.assertManagedDirectory(this.root)\n await this.ensureManagedDirectory(this.assetsPath, this.root)\n await this.ensureManagedDirectory(this.setsPath, this.root)\n await this.ensureManagedDirectory(this.mockupBundlesPath, this.root)\n await rm(this.mockupImportsPath, { recursive: true, force: true })\n await this.ensureManagedDirectory(this.mockupImportsPath, this.mockupBundlesPath)\n for (const category of ASSET_CATEGORIES) {\n await this.ensureManagedDirectory(path.join(this.assetsPath, category), this.assetsPath)\n }\n\n try {\n await access(this.configPath, constants.F_OK)\n } catch {\n await this.writeConfig({\n version: 1,\n appName: path.basename(this.root),\n platforms: [\"ios\"],\n })\n }\n }\n\n async readProject(): Promise<StoreShotProject> {\n const [config, assets, sets] = await Promise.all([this.readConfig(), this.listAssets(), this.listSets()])\n return { directory: this.root, config, assets, sets }\n }\n\n async readConfig(): Promise<StoreShotConfig> {\n const value: unknown = JSON.parse(await this.readManagedFile(this.configPath, this.root, \"utf8\"))\n return parseConfig(value)\n }\n\n async writeConfig(config: StoreShotConfig): Promise<StoreShotConfig> {\n const value = parseConfig(config)\n await this.runExclusive(this.configPath, async () => {\n await this.assertSafeWriteTarget(this.configPath, this.root)\n await writeJson(this.configPath, value)\n })\n return value\n }\n\n async listAssets(): Promise<Record<AssetCategory, Asset[]>> {\n const entries = await Promise.all(\n ASSET_CATEGORIES.map(async (category) => [category, await this.listAssetsInCategory(category)] as const),\n )\n return Object.fromEntries(entries) as Record<AssetCategory, Asset[]>\n }\n\n async deleteAsset(category: AssetCategory, filename: string): Promise<void> {\n const target = await this.resolveExistingAsset(category, filename)\n await this.runExclusive(target, async () => unlink(target))\n this.assetHashes.delete(target)\n await this.updateAssetMetadataFile((metadata) => {\n delete metadata[`${category}/${filename}`]\n })\n }\n\n async updateAssetMetadata(category: AssetCategory, filename: string, input: UpdateAssetMetadataInput): Promise<void> {\n await this.resolveExistingAsset(category, filename)\n if (category !== \"screenshots\") throw new Error(\"Device type can only be set for raw screenshots\")\n const deviceType = input.deviceType\n if (deviceType !== null && !SCREENSHOT_DEVICE_TYPES.includes(deviceType)) throw new Error(\"Unsupported screenshot device type\")\n await this.updateAssetMetadataFile((metadata) => {\n const id = `${category}/${filename}`\n if (deviceType === null) delete metadata[id]\n else metadata[id] = { deviceType }\n })\n }\n\n async addAsset(category: string, filename: string, contents: Buffer): Promise<{ replaced: boolean }> {\n const target = this.resolveAsset(category, filename)\n assertValidImage(filename, contents)\n return this.runExclusive(\"asset-catalog\", async () => {\n await this.assertSafeWriteTarget(target, path.dirname(target))\n const incomingHash = hash(contents)\n const replaced = await access(target, constants.F_OK).then(() => true).catch(() => false)\n\n for (const assetCategory of ASSET_CATEGORIES) {\n const directory = path.join(this.assetsPath, assetCategory)\n const entries = await readdir(directory, { withFileTypes: true })\n for (const entry of entries) {\n if (!entry.isFile() || !supportedExtensions.has(path.extname(entry.name).toLowerCase())) continue\n const existingPath = path.join(directory, entry.name)\n if (existingPath === target) continue\n if (await this.hashAsset(existingPath, directory) === incomingHash) {\n throw new DuplicateAssetError(`${assetCategory}/${entry.name}`)\n }\n }\n }\n\n await writeFileAtomically(target, contents)\n const metadata = await stat(target)\n this.assetHashes.set(target, { hash: incomingHash, mtimeMs: metadata.mtimeMs, size: metadata.size })\n return { replaced }\n })\n }\n\n resolveAsset(category: string, filename: string): string {\n if (!isAssetCategory(category)) throw new Error(\"Unsupported asset category\")\n\n const safeName = path.basename(filename)\n const extension = path.extname(safeName).toLowerCase()\n if (safeName !== filename || !supportedExtensions.has(extension)) {\n throw new Error(\"Unsupported asset filename\")\n }\n\n return path.join(this.assetsPath, category, safeName)\n }\n\n async resolveExistingAsset(category: string, filename: string): Promise<string> {\n const target = this.resolveAsset(category, filename)\n await this.assertRegularFile(target)\n const resolved = await realpath(target)\n await this.assertContained(resolved, path.join(this.assetsPath, category))\n return resolved\n }\n\n async listSets(): Promise<ScreenshotSet[]> {\n const entries = await readdir(this.setsPath, { withFileTypes: true })\n const sets = await Promise.all(\n entries\n .filter((entry) => entry.isFile() && path.extname(entry.name) === \".json\")\n .map(async (entry) => parseSet(JSON.parse(await this.readManagedFile(path.join(this.setsPath, entry.name), this.setsPath, \"utf8\")))),\n )\n return sets.sort((a, b) => a.createdAt.localeCompare(b.createdAt))\n }\n\n async createSet(input: CreateSetInput): Promise<ScreenshotSet> {\n const value = parseCreateSetInput(input)\n const now = new Date().toISOString()\n const id = `${slugify(value.name)}-${randomUUID().slice(0, 8)}`\n const areaId = `area-${randomUUID()}`\n const set: ScreenshotSet = {\n version: 1,\n id,\n name: value.name,\n locale: value.locale,\n device: value.device,\n canvas: { width: value.width, height: value.height },\n areas: [\n {\n id: areaId,\n name: \"Screenshot 1\",\n background: \"#245f4a\",\n elements: [\n {\n id: `element-${randomUUID()}`,\n type: \"text\",\n text: \"Your headline\",\n x: Math.round(value.width * 0.08),\n y: Math.round(value.height * 0.07),\n width: Math.round(value.width * 0.84),\n height: Math.round(value.height * 0.2),\n rotation: 0,\n opacity: 1,\n fontFamily: \"Geist Variable\",\n fontSize: Math.max(48, Math.round(value.width * 0.09)),\n fontWeight: 700,\n color: \"#ffffff\",\n textAlign: \"center\",\n },\n ],\n },\n ],\n createdAt: now,\n updatedAt: now,\n }\n const target = this.resolveSet(id)\n await this.runExclusive(target, async () => {\n await this.assertSafeWriteTarget(target, this.setsPath)\n await writeJson(target, set)\n })\n return set\n }\n\n async duplicateSet(id: string): Promise<ScreenshotSet> {\n const source = await this.readSet(id)\n const existingSets = await this.listSets()\n const name = duplicateName(source.name, existingSets.map((set) => set.name))\n const now = new Date().toISOString()\n const duplicate: ScreenshotSet = {\n ...structuredClone(source),\n id: `${slugify(name)}-${randomUUID().slice(0, 8)}`,\n name,\n areas: source.areas.map((area) => cloneScreenshotArea(area, { idFactory: randomUUID })),\n createdAt: now,\n updatedAt: now,\n }\n const target = this.resolveSet(duplicate.id)\n await this.runExclusive(target, async () => {\n await this.assertSafeWriteTarget(target, this.setsPath)\n await writeJson(target, duplicate)\n })\n return duplicate\n }\n\n async writeSet(id: string, set: ScreenshotSet): Promise<ScreenshotSet> {\n if (id !== set.id) throw new Error(\"Set id cannot be changed\")\n const target = this.resolveSet(id)\n return this.runExclusive(target, async () => {\n const value = parseSet({ ...set, updatedAt: new Date().toISOString() })\n await this.assertSafeWriteTarget(target, this.setsPath)\n await writeJson(target, value)\n return value\n })\n }\n\n async updateSetMetadata(id: string, input: UpdateSetMetadataInput): Promise<ScreenshotSet> {\n const metadata = parseSetMetadataInput(input)\n const target = this.resolveSet(id)\n return this.runExclusive(target, async () => {\n const current = parseSet(JSON.parse(await this.readManagedFile(target, this.setsPath, \"utf8\")))\n const value = parseSet({ ...current, ...metadata, updatedAt: new Date().toISOString() })\n await writeJson(target, value)\n return value\n })\n }\n\n async deleteSet(id: string): Promise<void> {\n const target = this.resolveSet(id)\n await this.runExclusive(target, async () => {\n await this.assertRegularFile(target)\n await unlink(target)\n })\n }\n\n async listMockupCatalog(): Promise<DeviceMockupCatalog> {\n const entries = await readdir(this.mockupBundlesPath, { withFileTypes: true })\n const catalogs = (await Promise.all(entries\n .filter((entry) => entry.isDirectory() && safeIdentifierPattern.test(entry.name))\n .map(async (entry) => {\n const manifestPath = path.join(this.mockupBundlesPath, entry.name, MOCKUP_BUNDLE_FILENAME)\n let contents: string\n try {\n contents = await this.readManagedFile(manifestPath, path.dirname(manifestPath), \"utf8\")\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined\n throw error\n }\n const manifest = parseMockupBundleManifest(JSON.parse(contents))\n if (manifest.id !== entry.name) throw new Error(`Mockup bundle folder ${entry.name} does not match manifest id ${manifest.id}`)\n return resolveMockupBundle(\n manifest,\n `/api/mockup-bundle-files/${encodeURIComponent(manifest.id)}/`,\n \"project\",\n )\n }))).filter((catalog): catalog is DeviceMockupCatalog => catalog !== undefined)\n return catalogs.length > 0 ? mergeDeviceMockupCatalogs(...catalogs) : emptyDeviceMockupCatalog()\n }\n\n async writeMockupBundleManifest(bundleId: string, input: unknown): Promise<MockupBundleManifest> {\n if (!safeIdentifierPattern.test(bundleId)) throw new Error(\"Unsupported mockup bundle id\")\n if (bundleId === \"frameup-free\") throw new Error(\"frameup-free is reserved for StoreShot's built-in bundle\")\n const manifest = parseMockupBundleManifest(input)\n if (manifest.id !== bundleId) throw new Error(\"Mockup bundle id cannot be changed\")\n const bundleDirectory = path.join(this.mockupBundlesPath, bundleId)\n await this.ensureManagedDirectory(bundleDirectory, this.mockupBundlesPath)\n await Promise.all(bundleAssetPaths(manifest).map(async (relativePath) => {\n await this.resolveExistingMockupBundleFile(bundleId, relativePath)\n }))\n const manifestPath = path.join(bundleDirectory, MOCKUP_BUNDLE_FILENAME)\n await this.runExclusive(manifestPath, async () => writeJson(manifestPath, manifest))\n return manifest\n }\n\n async writeMockupBundleFile(bundleId: string, relativePath: string, contents: Buffer): Promise<void> {\n if (bundleId === \"frameup-free\") throw new Error(\"frameup-free is reserved for StoreShot's built-in bundle\")\n const target = this.resolveMockupBundleFile(bundleId, relativePath)\n if (isImageFile(relativePath)) assertValidImage(relativePath, contents)\n await this.ensureManagedDirectory(path.dirname(target), this.mockupBundlesPath)\n await this.assertSafeWriteTarget(target, path.dirname(target))\n await this.runExclusive(target, async () => writeFileAtomically(target, contents))\n }\n\n async writeMockupBundleImportFile(importId: string, bundleId: string, relativePath: string, contents: Buffer): Promise<void> {\n this.assertMockupImportId(importId)\n this.resolveMockupBundleFile(bundleId, relativePath)\n if (isImageFile(relativePath)) assertValidImage(relativePath, contents)\n const bundleDirectory = path.join(this.mockupImportsPath, importId, bundleId)\n const target = path.resolve(bundleDirectory, relativePath)\n if (!target.startsWith(`${bundleDirectory}${path.sep}`)) throw new Error(\"Mockup bundle file is outside the import\")\n await this.ensureManagedDirectory(path.dirname(target), this.mockupImportsPath)\n await this.assertSafeWriteTarget(target, path.dirname(target))\n await this.runExclusive(target, async () => writeFileAtomically(target, contents))\n }\n\n async commitMockupBundleImport(importId: string, bundleId: string, input: unknown): Promise<MockupBundleManifest> {\n this.assertMockupImportId(importId)\n if (!safeIdentifierPattern.test(bundleId)) throw new Error(\"Unsupported mockup bundle id\")\n if (bundleId === \"frameup-free\") throw new Error(\"frameup-free is reserved for StoreShot's built-in bundle\")\n const manifest = parseMockupBundleManifest(input)\n if (manifest.id !== bundleId) throw new Error(\"Mockup bundle id cannot be changed\")\n\n const importDirectory = path.join(this.mockupImportsPath, importId)\n const stagedBundle = path.join(importDirectory, bundleId)\n await this.assertManagedDirectory(stagedBundle)\n await Promise.all(bundleAssetPaths(manifest).map(async (relativePath) => {\n const target = path.resolve(stagedBundle, relativePath)\n if (!target.startsWith(`${stagedBundle}${path.sep}`)) throw new Error(\"Mockup bundle file is outside the import\")\n await this.readManagedFile(target, stagedBundle)\n }))\n await writeJson(path.join(stagedBundle, MOCKUP_BUNDLE_FILENAME), manifest)\n\n const finalBundle = path.join(this.mockupBundlesPath, bundleId)\n const backupBundle = path.join(this.mockupBundlesPath, `.${bundleId}.${randomUUID()}.backup`)\n await this.runExclusive(`mockup-bundle:${bundleId}`, async () => {\n let hasBackup = false\n try {\n const metadata = await lstat(finalBundle)\n if (!metadata.isDirectory() || metadata.isSymbolicLink()) throw new Error(\"Mockup bundle must be a regular directory\")\n await rename(finalBundle, backupBundle)\n hasBackup = true\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error\n }\n\n try {\n await rename(stagedBundle, finalBundle)\n } catch (error) {\n if (hasBackup) await rename(backupBundle, finalBundle)\n throw error\n }\n if (hasBackup) await rm(backupBundle, { recursive: true, force: true }).catch(() => undefined)\n await rm(importDirectory, { recursive: true, force: true }).catch(() => undefined)\n })\n return manifest\n }\n\n async discardMockupBundleImport(importId: string): Promise<void> {\n this.assertMockupImportId(importId)\n const target = path.join(this.mockupImportsPath, importId)\n const relative = path.relative(this.mockupImportsPath, target)\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) throw new Error(\"Mockup import is outside the project boundary\")\n await rm(target, { recursive: true, force: true })\n }\n\n resolveMockupBundleFile(bundleId: string, relativePath: string): string {\n if (!safeIdentifierPattern.test(bundleId)) throw new Error(\"Unsupported mockup bundle id\")\n if (!isSafeBundlePath(relativePath) || relativePath === MOCKUP_BUNDLE_FILENAME) {\n throw new Error(\"Unsupported mockup bundle file path\")\n }\n const extension = path.extname(relativePath).toLowerCase()\n if (path.basename(relativePath) !== \"LICENSE\" && !supportedMockupBundleExtensions.has(extension)) {\n throw new Error(\"Unsupported mockup bundle file type\")\n }\n const bundleRoot = path.join(this.mockupBundlesPath, bundleId)\n const target = path.resolve(bundleRoot, relativePath)\n if (!target.startsWith(`${bundleRoot}${path.sep}`)) throw new Error(\"Mockup bundle file is outside the bundle\")\n return target\n }\n\n async resolveExistingMockupBundleFile(bundleId: string, relativePath: string): Promise<string> {\n const bundleRoot = await realpath(path.join(this.mockupBundlesPath, bundleId))\n await this.assertContained(bundleRoot, this.mockupBundlesPath)\n await this.assertRegularFile(this.resolveMockupBundleFile(bundleId, relativePath))\n const target = await realpath(this.resolveMockupBundleFile(bundleId, relativePath))\n if (!target.startsWith(`${bundleRoot}${path.sep}`)) throw new Error(\"Mockup bundle file is outside the bundle\")\n return target\n }\n\n private async listAssetsInCategory(category: AssetCategory): Promise<Asset[]> {\n const directory = path.join(this.assetsPath, category)\n const entries = await readdir(directory, { withFileTypes: true })\n const files = entries\n .filter((entry) => entry.isFile() && supportedExtensions.has(path.extname(entry.name).toLowerCase()))\n .sort((a, b) => a.name.localeCompare(b.name))\n\n const assetMetadata = await this.readAssetMetadata()\n return Promise.all(\n files.map(async (file) => {\n const filename = path.join(directory, file.name)\n const [metadata, contents] = await Promise.all([stat(filename), this.readManagedFile(filename, directory)])\n const dimensions = readImageMetadata(contents)\n const detectedDeviceType = category === \"screenshots\" && dimensions\n ? detectScreenshotDeviceType(dimensions.width, dimensions.height)\n : undefined\n const deviceTypeOverride = assetMetadata[`${category}/${file.name}`]?.deviceType\n return {\n id: `${category}/${file.name}`,\n category,\n name: file.name,\n url: `/api/assets/${category}/${encodeURIComponent(file.name)}?v=${Math.trunc(metadata.mtimeMs)}`,\n size: metadata.size,\n modifiedAt: metadata.mtime.toISOString(),\n ...(dimensions ?? {}),\n ...(detectedDeviceType ? {\n detectedDeviceType,\n deviceTypeOverride,\n deviceType: deviceTypeOverride ?? detectedDeviceType,\n } : {}),\n }\n }),\n )\n }\n\n private async readAssetMetadata(): Promise<AssetMetadata> {\n const target = path.join(this.assetsPath, ASSET_METADATA_FILENAME)\n try {\n const value: unknown = JSON.parse(await this.readManagedFile(target, this.assetsPath, \"utf8\"))\n if (!isRecord(value) || value.version !== 1 || !isRecord(value.assets)) return {}\n return Object.fromEntries(Object.entries(value.assets).flatMap(([id, entry]) => {\n if (!isRecord(entry) || !SCREENSHOT_DEVICE_TYPES.includes(entry.deviceType as ScreenshotDeviceType)) return []\n return [[id, { deviceType: entry.deviceType as ScreenshotDeviceType }]]\n }))\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return {}\n throw error\n }\n }\n\n private async writeAssetMetadata(assets: AssetMetadata): Promise<void> {\n const target = path.join(this.assetsPath, ASSET_METADATA_FILENAME)\n await this.assertSafeWriteTarget(target, this.assetsPath)\n await writeJson(target, { version: 1, assets })\n }\n\n private async updateAssetMetadataFile(update: (metadata: AssetMetadata) => void): Promise<void> {\n const target = path.join(this.assetsPath, ASSET_METADATA_FILENAME)\n await this.runExclusive(target, async () => {\n const metadata = await this.readAssetMetadata()\n update(metadata)\n await this.writeAssetMetadata(metadata)\n })\n }\n\n private async hashAsset(filename: string, boundary: string): Promise<string> {\n const metadata = await stat(filename)\n const cached = this.assetHashes.get(filename)\n if (cached && cached.mtimeMs === metadata.mtimeMs && cached.size === metadata.size) return cached.hash\n const value = hash(await this.readManagedFile(filename, boundary))\n this.assetHashes.set(filename, { hash: value, mtimeMs: metadata.mtimeMs, size: metadata.size })\n return value\n }\n\n private async readSet(id: string): Promise<ScreenshotSet> {\n const target = this.resolveSet(id)\n return parseSet(JSON.parse(await this.readManagedFile(target, this.setsPath, \"utf8\")))\n }\n\n private async runExclusive<T>(key: string, operation: () => Promise<T>): Promise<T> {\n const previous = this.operations.get(key) ?? Promise.resolve()\n const result = previous.catch(() => undefined).then(operation)\n const tail = result.then(() => undefined, () => undefined)\n this.operations.set(key, tail)\n try {\n return await result\n } finally {\n if (this.operations.get(key) === tail) this.operations.delete(key)\n }\n }\n\n private async assertManagedDirectory(directory: string): Promise<void> {\n const metadata = await lstat(directory)\n if (!metadata.isDirectory() || metadata.isSymbolicLink()) {\n throw new Error(`${path.relative(this.root, directory) || \".\"} must be a regular project directory`)\n }\n await this.assertContained(await realpath(directory), this.root, true)\n }\n\n private async ensureManagedDirectory(directory: string, boundary: string): Promise<void> {\n await this.assertManagedDirectory(boundary)\n const relative = path.relative(boundary, directory)\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) throw new Error(\"Directory is outside the project boundary\")\n let current = boundary\n for (const segment of relative.split(path.sep).filter(Boolean)) {\n current = path.join(current, segment)\n try {\n await mkdir(current)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error\n }\n const metadata = await lstat(current)\n if (!metadata.isDirectory() || metadata.isSymbolicLink()) throw new Error(\"Project directories cannot be symbolic links\")\n }\n await this.assertContained(await realpath(directory), boundary, true)\n }\n\n private async assertSafeWriteTarget(target: string, boundary: string): Promise<void> {\n await this.assertManagedDirectory(boundary)\n const relative = path.relative(boundary, target)\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) throw new Error(\"File is outside the project boundary\")\n try {\n const metadata = await lstat(target)\n if (metadata.isSymbolicLink() || !metadata.isFile()) throw new Error(\"Project files must be regular files\")\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error\n }\n }\n\n private async readManagedFile(filename: string, boundary: string): Promise<Buffer>\n private async readManagedFile(filename: string, boundary: string, encoding: BufferEncoding): Promise<string>\n private async readManagedFile(filename: string, boundary: string, encoding?: BufferEncoding): Promise<Buffer | string> {\n await this.assertRegularFile(filename)\n await this.assertContained(await realpath(filename), boundary)\n return encoding ? readFile(filename, encoding) : readFile(filename)\n }\n\n private async assertRegularFile(filename: string): Promise<void> {\n const metadata = await lstat(filename)\n if (!metadata.isFile() || metadata.isSymbolicLink()) throw new Error(\"Project files must be regular files\")\n }\n\n private async assertContained(candidate: string, boundary: string, allowEqual = false): Promise<void> {\n const resolvedBoundary = await realpath(boundary)\n if ((allowEqual && candidate === resolvedBoundary) || candidate.startsWith(`${resolvedBoundary}${path.sep}`)) return\n throw new Error(\"File is outside the project boundary\")\n }\n\n private assertMockupImportId(importId: string): void {\n if (!safeIdentifierPattern.test(importId)) throw new Error(\"Unsupported mockup import id\")\n }\n\n private resolveSet(id: string): string {\n if (!safeIdentifierPattern.test(id)) throw new Error(\"Unsupported set id\")\n return path.join(this.setsPath, `${id}.json`)\n }\n}\n\ntype AssetMetadata = Record<string, { deviceType: ScreenshotDeviceType }>\n\nexport class DuplicateAssetError extends Error {\n constructor(readonly existingAssetId: string) {\n super(`This file is already in the asset catalog as ${existingAssetId}`)\n }\n}\n\nfunction hash(contents: Buffer): string {\n return createHash(\"sha256\").update(contents).digest(\"hex\")\n}\n\nfunction parseConfig(value: unknown): StoreShotConfig {\n if (!isRecord(value)) throw new Error(\"storeshot.json must contain a JSON object\")\n\n const appName = readString(value.appName, \"appName\")\n const platforms = Array.isArray(value.platforms)\n ? value.platforms.filter((platform): platform is \"ios\" | \"android\" => platform === \"ios\" || platform === \"android\")\n : []\n if (platforms.length === 0) throw new Error(\"platforms must include ios or android\")\n\n return { version: 1, appName, platforms: [...new Set(platforms)] }\n}\n\nfunction parseCreateSetInput(value: unknown): CreateSetInput {\n if (!isRecord(value)) throw new Error(\"Set details must be an object\")\n return {\n name: readString(value.name, \"Set name\"),\n locale: readString(value.locale, \"Locale\"),\n device: readString(value.device, \"Device\"),\n width: readDimension(value.width, \"Canvas width\"),\n height: readDimension(value.height, \"Canvas height\"),\n }\n}\n\nfunction duplicateName(sourceName: string, existingNames: string[]): string {\n const names = new Set(existingNames.map((name) => name.toLocaleLowerCase()))\n const baseName = `${sourceName} copy`\n if (!names.has(baseName.toLocaleLowerCase())) return baseName\n\n let copyNumber = 2\n while (names.has(`${baseName} ${copyNumber}`.toLocaleLowerCase())) copyNumber += 1\n return `${baseName} ${copyNumber}`\n}\n\nfunction parseSetMetadataInput(value: unknown): UpdateSetMetadataInput {\n if (!isRecord(value)) throw new Error(\"Set settings must be an object\")\n return {\n name: readString(value.name, \"Set name\"),\n locale: readString(value.locale, \"Locale\"),\n device: readString(value.device, \"Device\"),\n }\n}\n\nfunction parseSet(value: unknown): ScreenshotSet {\n if (!isRecord(value)) throw new Error(\"Set file must contain an object\")\n\n const id = readString(value.id, \"Set id\")\n if (!safeIdentifierPattern.test(id)) throw new Error(\"Set id is invalid\")\n if (!isRecord(value.canvas)) throw new Error(\"Set canvas is invalid\")\n if (!Array.isArray(value.areas) || value.areas.length === 0) throw new Error(\"A set needs at least one screenshot area\")\n\n return {\n version: 1,\n id,\n name: readString(value.name, \"Set name\"),\n locale: readString(value.locale, \"Locale\"),\n device: readString(value.device, \"Device\"),\n canvas: {\n width: readDimension(value.canvas.width, \"Canvas width\"),\n height: readDimension(value.canvas.height, \"Canvas height\"),\n },\n areas: value.areas.map(parseArea),\n createdAt: readString(value.createdAt, \"Created time\"),\n updatedAt: readString(value.updatedAt, \"Updated time\"),\n }\n}\n\nfunction parseArea(value: unknown): ScreenshotArea {\n if (!isRecord(value)) throw new Error(\"Screenshot area is invalid\")\n const background = readString(value.background, \"Area background\")\n if (!hexColorPattern.test(background)) throw new Error(\"Area background must be a hex color\")\n if (!Array.isArray(value.elements)) throw new Error(\"Area elements must be an array\")\n return {\n id: readString(value.id, \"Area id\"),\n name: readString(value.name, \"Area name\"),\n background,\n elements: value.elements.map(parseElement),\n }\n}\n\nfunction parseImageSource(value: unknown, legacyAssetId?: unknown): ImageElementSource {\n if (isRecord(value)) {\n if (value.kind === \"builtin\") return { kind: \"builtin\", id: readString(value.id, \"Built-in artwork id\") }\n if (value.kind === \"asset\") return { kind: \"asset\", assetId: readString(value.assetId, \"Asset id\") }\n throw new Error(\"Image source type is invalid\")\n }\n if (legacyAssetId !== undefined) return { kind: \"asset\", assetId: readString(legacyAssetId, \"Asset id\") }\n throw new Error(\"Image source is invalid\")\n}\n\nfunction parseElement(value: unknown): CanvasElement {\n if (!isRecord(value)) throw new Error(\"Canvas element is invalid\")\n const base = {\n id: readString(value.id, \"Element id\"),\n x: readNumber(value.x, \"Element x\"),\n y: readNumber(value.y, \"Element y\"),\n width: readDimension(value.width, \"Element width\"),\n height: readDimension(value.height, \"Element height\"),\n rotation: readNumber(value.rotation, \"Element rotation\"),\n opacity: readOptionalRange(value.opacity, 1, 0, 1, \"Element opacity\"),\n }\n\n if (value.type === \"image\") {\n if (value.fit !== \"contain\" && value.fit !== \"cover\") throw new Error(\"Image fit is invalid\")\n const source = parseImageSource(value.source, value.assetId)\n const fill = value.fill === undefined ? undefined : readString(value.fill, \"Image fill\")\n if (fill !== undefined && !hexColorPattern.test(fill)) throw new Error(\"Image fill must be a hex color\")\n return { ...base, type: \"image\", source, fit: value.fit, ...(fill === undefined ? {} : { fill }) }\n }\n\n if (value.type === \"mockup\") {\n return {\n ...base,\n type: \"mockup\",\n mockupId: readString(value.mockupId, \"Device mockup id\"),\n assetId: readString(value.assetId, \"Asset id\"),\n }\n }\n\n if (value.type === \"element\") {\n const source = parseImageSource(value.source)\n const fill = value.fill === undefined ? undefined : readString(value.fill, \"Image fill\")\n if (fill !== undefined && !hexColorPattern.test(fill)) throw new Error(\"Image fill must be a hex color\")\n return {\n ...base,\n type: \"image\",\n source,\n fit: \"contain\",\n ...(fill === undefined ? {} : { fill }),\n }\n }\n\n if (value.type === \"text\") {\n const fontWeight = Number(value.fontWeight)\n if (!Number.isInteger(fontWeight) || fontWeight < 100 || fontWeight > 900 || fontWeight % 100 !== 0) {\n throw new Error(\"Text weight is invalid\")\n }\n if (value.textAlign !== \"left\" && value.textAlign !== \"center\" && value.textAlign !== \"right\") {\n throw new Error(\"Text alignment is invalid\")\n }\n const color = readString(value.color, \"Text color\")\n if (!hexColorPattern.test(color)) throw new Error(\"Text color must be a hex color\")\n const lineHeight = value.lineHeight === undefined\n ? undefined\n : readDimension(value.lineHeight, \"Text line height\")\n return {\n ...base,\n type: \"text\",\n text: typeof value.text === \"string\" ? value.text : \"\",\n fontFamily: readOptionalString(value.fontFamily, \"Geist Variable\"),\n fontSize: readDimension(value.fontSize, \"Font size\"),\n fontWeight: fontWeight as FontWeight,\n ...(lineHeight === undefined ? {} : { lineHeight }),\n color,\n textAlign: value.textAlign,\n }\n }\n\n if (value.type === \"shape\") {\n if (value.shape !== \"rectangle\") throw new Error(\"Shape type is invalid\")\n const fill = readString(value.fill, \"Shape fill\")\n if (!hexColorPattern.test(fill)) throw new Error(\"Shape fill must be a hex color\")\n return {\n ...base,\n type: \"shape\",\n shape: value.shape,\n fill,\n cornerRadius: readOptionalRange(value.cornerRadius, 0, 0, 10_000, \"Shape corner radius\"),\n }\n }\n\n throw new Error(\"Unsupported canvas element type\")\n}\n\nfunction readString(value: unknown, name: string): string {\n const result = typeof value === \"string\" ? value.trim() : \"\"\n if (!result) throw new Error(`${name} must be a non-empty string`)\n return result\n}\n\nfunction readNumber(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) throw new Error(`${name} must be a number`)\n return value\n}\n\nfunction readOptionalRange(value: unknown, fallback: number, min: number, max: number, name: string): number {\n if (value === undefined) return fallback\n const result = readNumber(value, name)\n if (result < min || result > max) throw new Error(`${name} is outside the supported range`)\n return result\n}\n\nfunction readOptionalString(value: unknown, fallback: string): string {\n return typeof value === \"string\" && value.trim() ? value.trim() : fallback\n}\n\nfunction readDimension(value: unknown, name: string): number {\n const result = readNumber(value, name)\n if (result <= 0 || result > 20_000) throw new Error(`${name} is outside the supported range`)\n return result\n}\n\nfunction isAssetCategory(value: string): value is AssetCategory {\n return ASSET_CATEGORIES.includes(value as AssetCategory)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction slugify(value: string): string {\n const result = value\n .normalize(\"NFKD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n return result || \"set\"\n}\n\nasync function writeJson(filename: string, value: unknown): Promise<void> {\n await writeFileAtomically(filename, `${JSON.stringify(value, null, 2)}\\n`)\n}\n\nasync function writeFileAtomically(filename: string, contents: Buffer | string): Promise<void> {\n const temporary = path.join(path.dirname(filename), `.${path.basename(filename)}.${randomUUID()}.tmp`)\n try {\n await writeFile(temporary, contents, { flag: \"wx\" })\n await rename(temporary, filename)\n } finally {\n await unlink(temporary).catch((error: NodeJS.ErrnoException) => {\n if (error.code !== \"ENOENT\") throw error\n })\n }\n}\n\nfunction isImageFile(filename: string): boolean {\n return supportedExtensions.has(path.extname(filename).toLowerCase())\n}\n\nfunction assertValidImage(filename: string, contents: Buffer): void {\n if (!isImageFile(filename) || !readImageMetadata(contents)) throw new Error(\"The uploaded file is not a valid supported image\")\n}\n","export const MOCKUP_BUNDLE_FILENAME = \"storeshot-mockups.json\"\nexport const MOCKUP_BUNDLE_FORMAT = \"storeshot-mockup-bundle\"\n\nexport interface Point {\n x: number\n y: number\n}\n\nexport type DevicePlatform = \"iphone\" | \"ipad\" | \"mac\" | \"watch\"\nexport type DeviceMockupStyle =\n | \"3d\"\n | \"colored\"\n | \"colored-3d\"\n | \"handheld\"\n | \"handheld-dim\"\n | \"handheld-silhouette\"\n | \"handheld-styles\"\n | \"standard\"\n | \"textured\"\n\nexport type ProjectiveTransform = readonly [\n readonly [number, number, number],\n readonly [number, number, number],\n readonly [number, number, number],\n]\n\nexport interface RectMockupScreen {\n kind: \"rect\"\n x: number\n y: number\n width: number\n height: number\n cornerRadius: number\n}\n\nexport interface PerspectiveMockupScreen {\n kind: \"projective\"\n /** Maps normalized screenshot coordinates into normalized frame coordinates. */\n transform: ProjectiveTransform\n /** Elliptical source-image corner radius, normalized to the screenshot plane. */\n sourceCornerRadius: Point\n}\n\nexport type MockupScreen = PerspectiveMockupScreen | RectMockupScreen\n\nexport interface MockupBundleLicense {\n name: string\n url?: string\n file?: string\n}\n\nexport interface MockupBundleSource {\n name?: string\n url: string\n revision?: string\n}\n\n/** Portable, folder-based StoreShot device mockup definition. */\nexport interface MockupBundleEntry {\n id: string\n groupId: string\n groupName: string\n name: string\n description: string\n platform: DevicePlatform\n style: DeviceMockupStyle\n frame: string\n thumbnail?: string\n width: number\n height: number\n screen: MockupScreen\n}\n\nexport interface MockupBundleManifest {\n format: typeof MOCKUP_BUNDLE_FORMAT\n version: 1\n id: string\n name: string\n author: string\n license: MockupBundleLicense\n source?: MockupBundleSource\n mockups: MockupBundleEntry[]\n}\n\ninterface DeviceMockupBase {\n id: string\n bundleId: string\n groupId: string\n name: string\n description: string\n platform: DevicePlatform\n style: DeviceMockupStyle\n frameUrl: string\n thumbnailUrl: string\n width: number\n height: number\n}\n\nexport interface DeviceMockup extends DeviceMockupBase {\n screen: MockupScreen\n}\n\nexport interface DeviceMockupGroup {\n id: string\n bundleId: string\n name: string\n platform: DevicePlatform\n style: DeviceMockupStyle\n thumbnailUrl: string\n count: number\n}\n\nexport interface MockupBundleSummary {\n id: string\n name: string\n author: string\n license: MockupBundleLicense\n source?: MockupBundleSource\n mockupCount: number\n origin: \"built-in\" | \"project\"\n}\n\nexport interface DeviceMockupCatalog {\n bundles: MockupBundleSummary[]\n groups: DeviceMockupGroup[]\n mockups: DeviceMockup[]\n}\n\nconst identifierPattern = /^[a-z0-9][a-z0-9-]*$/\nconst styles = new Set<DeviceMockupStyle>([\n \"3d\",\n \"colored\",\n \"colored-3d\",\n \"handheld\",\n \"handheld-dim\",\n \"handheld-silhouette\",\n \"handheld-styles\",\n \"standard\",\n \"textured\",\n])\nconst platforms = new Set<DevicePlatform>([\"iphone\", \"ipad\", \"mac\", \"watch\"])\nconst frameExtensions = new Set([\".jpeg\", \".jpg\", \".png\", \".svg\", \".webp\"])\n\nexport function emptyDeviceMockupCatalog(): DeviceMockupCatalog {\n return { bundles: [], groups: [], mockups: [] }\n}\n\nexport function parseMockupBundleManifest(value: unknown): MockupBundleManifest {\n if (!isRecord(value)) throw new Error(`${MOCKUP_BUNDLE_FILENAME} must contain a JSON object`)\n if (value.format !== MOCKUP_BUNDLE_FORMAT || value.version !== 1) {\n throw new Error(\"Unsupported StoreShot mockup bundle format\")\n }\n if (!Array.isArray(value.mockups) || value.mockups.length === 0) {\n throw new Error(\"A mockup bundle must contain at least one mockup\")\n }\n\n const id = readIdentifier(value.id, \"Bundle id\")\n const mockups = value.mockups.map(parseMockupEntry)\n const entryIds = new Set<string>()\n for (const mockup of mockups) {\n if (entryIds.has(mockup.id)) throw new Error(`Duplicate mockup id: ${mockup.id}`)\n entryIds.add(mockup.id)\n }\n\n return {\n format: MOCKUP_BUNDLE_FORMAT,\n version: 1,\n id,\n name: readString(value.name, \"Bundle name\"),\n author: readString(value.author, \"Bundle author\"),\n license: parseLicense(value.license),\n ...(value.source === undefined ? {} : { source: parseSource(value.source) }),\n mockups,\n }\n}\n\nexport function resolveMockupBundle(\n manifest: MockupBundleManifest,\n baseUrl: string,\n origin: MockupBundleSummary[\"origin\"],\n): DeviceMockupCatalog {\n const bundlePrefix = `${manifest.id}/`\n const mockups: DeviceMockup[] = manifest.mockups.map((entry) => ({\n ...entry,\n id: `${bundlePrefix}${entry.id}`,\n bundleId: manifest.id,\n groupId: `${bundlePrefix}${entry.groupId}`,\n frameUrl: `${baseUrl}${encodeBundlePath(entry.frame)}`,\n thumbnailUrl: `${baseUrl}${encodeBundlePath(entry.thumbnail ?? entry.frame)}`,\n }))\n\n const groupEntries = new Map<string, DeviceMockup[]>()\n for (const mockup of mockups) {\n const entries = groupEntries.get(mockup.groupId) ?? []\n entries.push(mockup)\n groupEntries.set(mockup.groupId, entries)\n }\n\n return {\n bundles: [{\n id: manifest.id,\n name: manifest.name,\n author: manifest.author,\n license: manifest.license,\n ...(manifest.source ? { source: manifest.source } : {}),\n mockupCount: mockups.length,\n origin,\n }],\n groups: [...groupEntries.entries()].map(([id, entries]) => ({\n id,\n bundleId: manifest.id,\n name: manifest.mockups.find((entry) => `${bundlePrefix}${entry.groupId}` === id)?.groupName ?? entries[0].name,\n platform: entries[0].platform,\n style: entries[0].style,\n thumbnailUrl: entries[0].thumbnailUrl,\n count: entries.length,\n })),\n mockups,\n }\n}\n\nexport function mergeDeviceMockupCatalogs(...catalogs: DeviceMockupCatalog[]): DeviceMockupCatalog {\n const result = emptyDeviceMockupCatalog()\n const bundleIds = new Set<string>()\n const groupIds = new Set<string>()\n const mockupIds = new Set<string>()\n\n for (const catalog of catalogs) {\n for (const bundle of catalog.bundles) {\n if (bundleIds.has(bundle.id)) continue\n bundleIds.add(bundle.id)\n result.bundles.push(bundle)\n }\n for (const group of catalog.groups) {\n if (groupIds.has(group.id)) continue\n groupIds.add(group.id)\n result.groups.push(group)\n }\n for (const mockup of catalog.mockups) {\n if (mockupIds.has(mockup.id)) continue\n mockupIds.add(mockup.id)\n result.mockups.push(mockup)\n }\n }\n return result\n}\n\nexport function deviceMockupById(catalog: DeviceMockupCatalog, id: string): DeviceMockup | undefined {\n return catalog.mockups.find((mockup) => mockup.id === id)\n}\n\nexport function bundleAssetPaths(manifest: MockupBundleManifest): string[] {\n const paths = new Set<string>()\n if (manifest.license.file) paths.add(manifest.license.file)\n for (const mockup of manifest.mockups) {\n paths.add(mockup.frame)\n if (mockup.thumbnail) paths.add(mockup.thumbnail)\n }\n return [...paths]\n}\n\nexport function isSafeBundlePath(value: string): boolean {\n if (!value || value.startsWith(\"/\") || value.includes(\"\\\\\")) return false\n const parts = value.split(\"/\")\n return parts.every((part) => part.length > 0 && part !== \".\" && part !== \"..\")\n}\n\nfunction parseMockupEntry(value: unknown): MockupBundleEntry {\n if (!isRecord(value)) throw new Error(\"Mockup entry must be an object\")\n const platform = readString(value.platform, \"Mockup platform\") as DevicePlatform\n const style = readString(value.style, \"Mockup style\") as DeviceMockupStyle\n if (!platforms.has(platform)) throw new Error(`Unsupported mockup platform: ${platform}`)\n if (!styles.has(style)) throw new Error(`Unsupported mockup style: ${style}`)\n const frame = readFramePath(value.frame, \"Mockup frame\")\n const thumbnail = value.thumbnail === undefined ? undefined : readFramePath(value.thumbnail, \"Mockup thumbnail\")\n return {\n id: readIdentifier(value.id, \"Mockup id\"),\n groupId: readIdentifier(value.groupId, \"Mockup group id\"),\n groupName: readString(value.groupName, \"Mockup group name\"),\n name: readString(value.name, \"Mockup name\"),\n description: readString(value.description, \"Mockup description\"),\n platform,\n style,\n frame,\n ...(thumbnail ? { thumbnail } : {}),\n width: readDimension(value.width, \"Mockup width\"),\n height: readDimension(value.height, \"Mockup height\"),\n screen: parseScreen(value.screen),\n }\n}\n\nfunction parseScreen(value: unknown): MockupScreen {\n if (!isRecord(value)) throw new Error(\"Mockup screen must be an object\")\n if (value.kind === \"rect\") {\n return {\n kind: \"rect\",\n x: readNumber(value.x, \"Screen x\"),\n y: readNumber(value.y, \"Screen y\"),\n width: readDimension(value.width, \"Screen width\"),\n height: readDimension(value.height, \"Screen height\"),\n cornerRadius: readNonNegative(value.cornerRadius, \"Screen corner radius\"),\n }\n }\n if (value.kind === \"projective\") {\n if (!Array.isArray(value.transform) || value.transform.length !== 3) throw new Error(\"Projective transform must have three rows\")\n const transform = value.transform.map((row) => {\n if (!Array.isArray(row) || row.length !== 3) throw new Error(\"Each projective transform row must have three numbers\")\n return row.map((entry) => readNumber(entry, \"Projective transform value\")) as [number, number, number]\n }) as [\n [number, number, number],\n [number, number, number],\n [number, number, number],\n ]\n if (!isRecord(value.sourceCornerRadius)) throw new Error(\"Projective source corner radius must be an object\")\n return {\n kind: \"projective\",\n transform,\n sourceCornerRadius: {\n x: readNonNegative(value.sourceCornerRadius.x, \"Source corner radius x\"),\n y: readNonNegative(value.sourceCornerRadius.y, \"Source corner radius y\"),\n },\n }\n }\n throw new Error(\"Unsupported mockup screen geometry\")\n}\n\nfunction parseLicense(value: unknown): MockupBundleLicense {\n if (!isRecord(value)) throw new Error(\"Bundle license must be an object\")\n const file = value.file === undefined ? undefined : readBundlePath(value.file, \"License file\")\n return {\n name: readString(value.name, \"License name\"),\n ...(value.url === undefined ? {} : { url: readString(value.url, \"License URL\") }),\n ...(file ? { file } : {}),\n }\n}\n\nfunction parseSource(value: unknown): MockupBundleSource {\n if (!isRecord(value)) throw new Error(\"Bundle source must be an object\")\n return {\n ...(value.name === undefined ? {} : { name: readString(value.name, \"Source name\") }),\n url: readString(value.url, \"Source URL\"),\n ...(value.revision === undefined ? {} : { revision: readString(value.revision, \"Source revision\") }),\n }\n}\n\nfunction readFramePath(value: unknown, name: string): string {\n const result = readBundlePath(value, name)\n const extensionIndex = result.lastIndexOf(\".\")\n const extension = extensionIndex >= 0 ? result.slice(extensionIndex).toLowerCase() : \"\"\n if (!frameExtensions.has(extension)) throw new Error(`${name} has an unsupported file type`)\n return result\n}\n\nfunction readBundlePath(value: unknown, name: string): string {\n const result = readString(value, name)\n if (!isSafeBundlePath(result)) throw new Error(`${name} must be a relative path inside the bundle`)\n return result\n}\n\nfunction readIdentifier(value: unknown, name: string): string {\n const result = readString(value, name)\n if (!identifierPattern.test(result)) throw new Error(`${name} must use lowercase letters, numbers, and hyphens`)\n return result\n}\n\nfunction readString(value: unknown, name: string): string {\n const result = typeof value === \"string\" ? value.trim() : \"\"\n if (!result) throw new Error(`${name} must be a non-empty string`)\n return result\n}\n\nfunction readNumber(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) throw new Error(`${name} must be a number`)\n return value\n}\n\nfunction readDimension(value: unknown, name: string): number {\n const result = readNumber(value, name)\n if (result <= 0 || result > 20_000) throw new Error(`${name} is outside the supported range`)\n return result\n}\n\nfunction readNonNegative(value: unknown, name: string): number {\n const result = readNumber(value, name)\n if (result < 0 || result > 20_000) throw new Error(`${name} is outside the supported range`)\n return result\n}\n\nfunction encodeBundlePath(value: string): string {\n return value.split(\"/\").map(encodeURIComponent).join(\"/\")\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n","import type { DetectedScreenshotDeviceType } from \"./shared.js\"\n\nexport interface ImageMetadata {\n width: number\n height: number\n}\n\nexport function readImageMetadata(contents: Buffer): ImageMetadata | undefined {\n return readPngMetadata(contents) ?? readJpegMetadata(contents) ?? readWebpMetadata(contents) ?? readSvgMetadata(contents)\n}\n\nfunction readSvgMetadata(contents: Buffer): ImageMetadata | undefined {\n const source = contents.subarray(0, 64 * 1024).toString(\"utf8\")\n const svg = source.match(/<svg\\b[^>]*>/i)?.[0]\n if (!svg) return undefined\n\n const width = readSvgLength(svg, \"width\")\n const height = readSvgLength(svg, \"height\")\n if (width && height) return validDimensions(width, height)\n\n const viewBox = svg.match(/\\bviewBox\\s*=\\s*[\"']\\s*([-+\\d.e]+)[\\s,]+([-+\\d.e]+)[\\s,]+([-+\\d.e]+)[\\s,]+([-+\\d.e]+)\\s*[\"']/i)\n if (!viewBox) return undefined\n return validDimensions(Number(viewBox[3]), Number(viewBox[4]))\n}\n\nfunction readSvgLength(svg: string, attribute: \"height\" | \"width\"): number | undefined {\n const match = svg.match(new RegExp(`\\\\b${attribute}\\\\s*=\\\\s*[\"']\\\\s*([-+\\\\d.e]+)`, \"i\"))\n const value = match ? Number(match[1]) : NaN\n return Number.isFinite(value) && value > 0 ? value : undefined\n}\n\nexport function detectScreenshotDeviceType(width: number, height: number): DetectedScreenshotDeviceType {\n const shortSide = Math.min(width, height)\n const longSide = Math.max(width, height)\n const ratio = longSide / shortSide\n const dimensions = `${shortSide}x${longSide}`\n\n if (WATCH_SCREENSHOT_DIMENSIONS.has(dimensions)) return \"watch\"\n if (IPAD_SCREENSHOT_DIMENSIONS.has(dimensions)) return \"ipad\"\n if (IPHONE_SCREENSHOT_DIMENSIONS.has(dimensions) && (height > width || longSide >= 2_200)) return \"iphone\"\n if (longSide <= 700 && ratio <= 1.4) return \"watch\"\n if (shortSide >= 1_400 && ratio >= 1.25 && ratio <= 1.45) return \"ipad\"\n if (height > width && ratio >= 1.65) return \"iphone\"\n if (width > height && ratio >= 1.45) return \"mac\"\n if (shortSide >= 1_000 && ratio >= 1.25 && ratio <= 1.45) return \"ipad\"\n return \"unknown\"\n}\n\nconst IPHONE_SCREENSHOT_DIMENSIONS = new Set([\n \"640x1136\", \"750x1334\", \"828x1792\", \"1080x1920\", \"1125x2436\", \"1170x2532\",\n \"1179x2556\", \"1206x2622\", \"1242x2208\", \"1242x2688\", \"1284x2778\", \"1290x2796\", \"1320x2868\",\n])\nconst IPAD_SCREENSHOT_DIMENSIONS = new Set([\n \"1536x2048\", \"1668x2224\", \"1668x2388\", \"2048x2732\", \"2064x2752\",\n])\nconst WATCH_SCREENSHOT_DIMENSIONS = new Set([\n \"368x448\", \"396x484\", \"416x496\", \"422x514\",\n])\n\nfunction readPngMetadata(contents: Buffer): ImageMetadata | undefined {\n if (contents.length < 24 || contents.toString(\"ascii\", 1, 4) !== \"PNG\") return undefined\n return validDimensions(contents.readUInt32BE(16), contents.readUInt32BE(20))\n}\n\nfunction readJpegMetadata(contents: Buffer): ImageMetadata | undefined {\n if (contents.length < 4 || contents[0] !== 0xff || contents[1] !== 0xd8) return undefined\n let offset = 2\n while (offset + 8 < contents.length) {\n if (contents[offset] !== 0xff) {\n offset += 1\n continue\n }\n const marker = contents[offset + 1]\n offset += 2\n if (marker === 0xd8 || marker === 0xd9) continue\n if (offset + 2 > contents.length) return undefined\n const length = contents.readUInt16BE(offset)\n if (length < 2 || offset + length > contents.length) return undefined\n if (isJpegStartOfFrame(marker) && length >= 7) {\n return validDimensions(contents.readUInt16BE(offset + 5), contents.readUInt16BE(offset + 3))\n }\n offset += length\n }\n return undefined\n}\n\nfunction isJpegStartOfFrame(marker: number): boolean {\n return marker >= 0xc0 && marker <= 0xcf && ![0xc4, 0xc8, 0xcc].includes(marker)\n}\n\nfunction readWebpMetadata(contents: Buffer): ImageMetadata | undefined {\n if (contents.length < 30 || contents.toString(\"ascii\", 0, 4) !== \"RIFF\" || contents.toString(\"ascii\", 8, 12) !== \"WEBP\") return undefined\n const type = contents.toString(\"ascii\", 12, 16)\n if (type === \"VP8X\") {\n return validDimensions(readUInt24LE(contents, 24) + 1, readUInt24LE(contents, 27) + 1)\n }\n if (type === \"VP8 \" && contents.length >= 30 && contents[23] === 0x9d && contents[24] === 0x01 && contents[25] === 0x2a) {\n return validDimensions(contents.readUInt16LE(26) & 0x3fff, contents.readUInt16LE(28) & 0x3fff)\n }\n if (type === \"VP8L\" && contents.length >= 25 && contents[20] === 0x2f) {\n const bits = contents.readUInt32LE(21)\n return validDimensions((bits & 0x3fff) + 1, ((bits >>> 14) & 0x3fff) + 1)\n }\n return undefined\n}\n\nfunction readUInt24LE(contents: Buffer, offset: number): number {\n return contents[offset] | (contents[offset + 1] << 8) | (contents[offset + 2] << 16)\n}\n\nfunction validDimensions(width: number, height: number): ImageMetadata | undefined {\n return width > 0 && height > 0 ? { width, height } : undefined\n}\n","import type { CanvasElement, ScreenshotArea } from \"./shared.js\"\n\nexport type IdFactory = () => string\n\ninterface CloneElementOptions {\n idFactory?: IdFactory\n offsetX?: number\n offsetY?: number\n}\n\ninterface CloneAreaOptions {\n idFactory?: IdFactory\n name?: string\n}\n\nconst defaultIdFactory: IdFactory = () => globalThis.crypto.randomUUID()\n\nexport function cloneCanvasElement(\n element: CanvasElement,\n { idFactory = defaultIdFactory, offsetX = 0, offsetY = 0 }: CloneElementOptions = {},\n): CanvasElement {\n return {\n ...structuredClone(element),\n id: `element-${idFactory()}`,\n x: element.x + offsetX,\n y: element.y + offsetY,\n }\n}\n\nexport function cloneScreenshotArea(\n area: ScreenshotArea,\n { idFactory = defaultIdFactory, name = area.name }: CloneAreaOptions = {},\n): ScreenshotArea {\n return {\n ...structuredClone(area),\n id: `area-${idFactory()}`,\n name,\n elements: area.elements.map((element) => cloneCanvasElement(element, { idFactory })),\n }\n}\n","export const ASSET_CATEGORIES = [\"screenshots\", \"brand\", \"logos\", \"other\"] as const\n\nexport type AssetCategory = (typeof ASSET_CATEGORIES)[number]\n\nexport const SCREENSHOT_DEVICE_TYPES = [\"iphone\", \"ipad\", \"mac\", \"watch\"] as const\nexport type ScreenshotDeviceType = (typeof SCREENSHOT_DEVICE_TYPES)[number]\nexport type DetectedScreenshotDeviceType = ScreenshotDeviceType | \"unknown\"\n\nexport interface StoreShotConfig {\n version: 1\n appName: string\n platforms: Array<\"ios\" | \"android\">\n}\n\nexport interface Asset {\n id: string\n category: AssetCategory\n name: string\n url: string\n size: number\n modifiedAt: string\n width?: number\n height?: number\n /** The dimension-based classification before a user override is applied. */\n detectedDeviceType?: DetectedScreenshotDeviceType\n /** An explicit local catalog override. */\n deviceTypeOverride?: ScreenshotDeviceType\n /** The effective type used for mockup recommendations. */\n deviceType?: DetectedScreenshotDeviceType\n}\n\nexport interface UpdateAssetMetadataInput {\n deviceType: ScreenshotDeviceType | null\n}\n\ninterface CanvasElementBase {\n id: string\n x: number\n y: number\n width: number\n height: number\n rotation: number\n opacity: number\n}\n\nexport type ImageElementSource =\n | { kind: \"builtin\"; id: string }\n | { kind: \"asset\"; assetId: string }\n\n/** A project image or built-in vector artwork placed on a screenshot. */\nexport interface ImageElement extends CanvasElementBase {\n type: \"image\"\n source: ImageElementSource\n fit: \"contain\" | \"cover\"\n /** Replaces the visible pixels while preserving their alpha. Omit to use the source colors. */\n fill?: string\n}\n\nexport interface DeviceMockupElement extends CanvasElementBase {\n type: \"mockup\"\n mockupId: string\n assetId: string\n}\n\nexport type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900\nexport const DEFAULT_TEXT_LINE_HEIGHT_RATIO = 1.05\n\nexport interface TextElement extends CanvasElementBase {\n type: \"text\"\n text: string\n fontFamily: string\n fontSize: number\n fontWeight: FontWeight\n /** Absolute line height in canvas pixels. When omitted, the renderer derives it from the font size. */\n lineHeight?: number\n color: string\n textAlign: \"left\" | \"center\" | \"right\"\n}\n\nexport interface ShapeElement extends CanvasElementBase {\n type: \"shape\"\n shape: \"rectangle\"\n fill: string\n cornerRadius: number\n}\n\nexport type CanvasElement = DeviceMockupElement | ImageElement | ShapeElement | TextElement\n\nexport interface ScreenshotArea {\n id: string\n name: string\n background: string\n elements: CanvasElement[]\n}\n\nexport interface ScreenshotSet {\n version: 1\n id: string\n name: string\n locale: string\n device: string\n canvas: {\n width: number\n height: number\n }\n areas: ScreenshotArea[]\n createdAt: string\n updatedAt: string\n}\n\nexport interface CreateSetInput {\n name: string\n locale: string\n device: string\n width: number\n height: number\n}\n\nexport interface UpdateSetMetadataInput {\n name: string\n locale: string\n device: string\n}\n\nexport interface StoreShotProject {\n directory: string\n config: StoreShotConfig\n assets: Record<AssetCategory, Asset[]>\n sets: ScreenshotSet[]\n}\n"],"mappings":"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","names":["path","readFile","stat","path","isRecord","readString","platforms","readDimension","readNumber","path","stat","readFile","path"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2026 Paweł Kuna
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Tabler Icons artwork
|
|
2
|
+
|
|
3
|
+
This directory contains selected SVG artwork from
|
|
4
|
+
[Tabler Icons](https://github.com/tabler/tabler-icons) at revision
|
|
5
|
+
`6d128ed935d4546607b1e4d5d08c8b27bdbe7758`.
|
|
6
|
+
|
|
7
|
+
Tabler Icons is Copyright (c) 2020-2026 Paweł Kuna and distributed under the
|
|
8
|
+
MIT License. The complete license text is in `LICENSE`.
|
|
9
|
+
|
|
10
|
+
Selected upstream files:
|
|
11
|
+
|
|
12
|
+
- `icons/filled/grid-pattern.svg`
|
|
13
|
+
- `icons/filled/laurel-wreath.svg`
|
|
14
|
+
- `icons/filled/laurel-wreath-1.svg`
|
|
15
|
+
- `icons/filled/laurel-wreath-2.svg`
|
|
16
|
+
- `icons/filled/laurel-wreath-3.svg`
|
|
17
|
+
- `icons/filled/sparkles.svg`
|
|
18
|
+
- `icons/filled/stars.svg`
|
|
19
|
+
- `icons/outline/scribble.svg`
|
|
20
|
+
- `icons/outline/underline.svg`
|
|
21
|
+
|
|
22
|
+
The files are copied without semantic changes. StoreShot applies user-selected
|
|
23
|
+
colors at render time.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
unicode: "100c2"
|
|
3
|
+
version: "3.24"
|
|
4
|
+
-->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="24"
|
|
8
|
+
height="24"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
fill="currentColor"
|
|
11
|
+
>
|
|
12
|
+
<path d="M18 3a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12a3 3 0 0 1 3 -3zm-4 4a1 1 0 0 0 -1 1v1h-2v-1a1 1 0 0 0 -.883 -.993l-.117 -.007a1 1 0 0 0 -1 1v1h-1a1 1 0 0 0 -.993 .883l-.007 .117a1 1 0 0 0 1 1h1v2h-1a1 1 0 0 0 -.993 .883l-.007 .117a1 1 0 0 0 1 1h1v1a1 1 0 0 0 .883 .993l.117 .007a1 1 0 0 0 1 -1v-1h2v1a1 1 0 0 0 .883 .993l.117 .007a1 1 0 0 0 1 -1v-1h1a1 1 0 0 0 .993 -.883l.007 -.117a1 1 0 0 0 -1 -1h-1v-2h1a1 1 0 0 0 .993 -.883l.007 -.117a1 1 0 0 0 -1 -1h-1v-1a1 1 0 0 0 -.883 -.993zm-1 4v2h-2v-2z" />
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
unicode: "10169"
|
|
3
|
+
version: "3.33"
|
|
4
|
+
-->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="24"
|
|
8
|
+
height="24"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
fill="currentColor"
|
|
11
|
+
>
|
|
12
|
+
<path d="M16.956 2.057c.355 .124 .829 .375 1.303 .796a3.77 3.77 0 0 1 1.246 2.204c.173 .989 -.047 1.894 -.519 2.683l-.123 .194q -.097 .147 -.196 .272q .066 .234 .117 .471q .26 -.178 .545 -.307c.851 -.389 1.727 -.442 2.527 -.306q .226 .04 .346 .076a1 1 0 0 1 .689 .712l.029 .13q .015 .08 .03 .18a4.45 4.45 0 0 1 -.324 2.496a3.94 3.94 0 0 1 -1.71 1.85l-.242 .12a4.23 4.23 0 0 1 -2.234 .349a9 9 0 0 1 -.443 1.023c.37 .016 .748 .093 1.128 .24c.732 .28 1.299 .758 1.711 1.367a3.95 3.95 0 0 1 .654 1.613a1 1 0 0 1 -.356 .917a3.8 3.8 0 0 1 -.716 .443c-.933 .455 -1.978 .588 -3.043 .179l-.032 -.015l-.205 -.086a3.6 3.6 0 0 1 -1.33 -1.069l-.143 -.197a4 4 0 0 1 -.26 -.433a6 6 0 0 1 -.927 .511q .18 .262 .337 .56a7.4 7.4 0 0 1 .66 1.747a1 1 0 0 1 -1.95 .444l-.028 -.11a6 6 0 0 0 -.449 -1.143c-.342 -.645 -.71 -.968 -1.048 -.968s-.706 .323 -1.048 .969a5.6 5.6 0 0 0 -.367 .874l-.082 .269l-.028 .11a1 1 0 0 1 -1.95 -.444a7.3 7.3 0 0 1 .66 -1.747q .158 -.298 .337 -.561a6.4 6.4 0 0 1 -.93 -.508a4 4 0 0 1 -.256 .43c-.366 .541 -.855 .98 -1.473 1.267l-.238 .1c-.994 .382 -1.97 .292 -2.855 -.091l-.188 -.087a3.8 3.8 0 0 1 -.716 -.443a1 1 0 0 1 -.356 -.917a3.95 3.95 0 0 1 .654 -1.613a3.6 3.6 0 0 1 1.71 -1.368c.38 -.146 .758 -.223 1.13 -.24a9 9 0 0 1 -.445 -1.023a4.23 4.23 0 0 1 -2.233 -.348a4 4 0 0 1 -.916 -.587l-.207 -.191a4 4 0 0 1 -.724 -.977l-.105 -.216a4.45 4.45 0 0 1 -.265 -2.806a1 1 0 0 1 .69 -.712q .119 -.036 .345 -.076c.801 -.135 1.678 -.082 2.53 .308q .283 .129 .545 .304q .048 -.235 .112 -.47a5 5 0 0 1 -.194 -.272c-.556 -.832 -.83 -1.806 -.642 -2.877l.05 -.242a3.75 3.75 0 0 1 1.027 -1.803l.169 -.159a4 4 0 0 1 1.303 -.796a1 1 0 0 1 .975 .178c.2 .168 .462 .446 .719 .83c.556 .833 .83 1.807 .642 2.878a3.77 3.77 0 0 1 -1.246 2.204c-.303 .27 -.607 .47 -.879 .61a7.5 7.5 0 0 0 -.255 1.971c0 3.502 2.285 6.272 5 6.272s5 -2.77 5 -6.276a7.6 7.6 0 0 0 -.253 -1.967a4.3 4.3 0 0 1 -.881 -.61a3.77 3.77 0 0 1 -1.246 -2.204c-.188 -1.07 .086 -2.045 .642 -2.877c.257 -.385 .52 -.663 .72 -.831a1 1 0 0 1 .974 -.178m-3.956 5.943v6a1 1 0 0 1 -2 0v-4.002h-.059a1 1 0 0 1 -.554 -.208l-.094 -.083a1 1 0 0 1 0 -1.414l1 -1c.63 -.63 1.707 -.184 1.707 .707" />
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
unicode: "10168"
|
|
3
|
+
version: "3.33"
|
|
4
|
+
-->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="24"
|
|
8
|
+
height="24"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
fill="currentColor"
|
|
11
|
+
>
|
|
12
|
+
<path d="M16.956 2.057c.355 .124 .829 .375 1.303 .796a3.77 3.77 0 0 1 1.246 2.204c.173 .989 -.047 1.894 -.519 2.683l-.123 .194q -.097 .147 -.196 .272q .066 .234 .117 .471q .26 -.178 .545 -.307c.851 -.389 1.727 -.442 2.527 -.306q .226 .04 .346 .076a1 1 0 0 1 .689 .712l.029 .13q .015 .08 .03 .18a4.45 4.45 0 0 1 -.324 2.496a3.94 3.94 0 0 1 -1.71 1.85l-.242 .12a4.23 4.23 0 0 1 -2.234 .349a9 9 0 0 1 -.443 1.023c.37 .016 .748 .093 1.128 .24c.732 .28 1.299 .758 1.711 1.367a3.95 3.95 0 0 1 .654 1.613a1 1 0 0 1 -.356 .917a3.8 3.8 0 0 1 -.716 .443c-.933 .455 -1.978 .588 -3.043 .179l-.032 -.015l-.205 -.086a3.6 3.6 0 0 1 -1.33 -1.069l-.143 -.197a4 4 0 0 1 -.26 -.433a6 6 0 0 1 -.927 .511q .18 .262 .337 .56a7.4 7.4 0 0 1 .66 1.747a1 1 0 0 1 -1.95 .444l-.028 -.11a6 6 0 0 0 -.449 -1.143c-.342 -.645 -.71 -.968 -1.048 -.968s-.706 .323 -1.048 .969a5.6 5.6 0 0 0 -.367 .874l-.082 .269l-.028 .11a1 1 0 0 1 -1.95 -.444a7.3 7.3 0 0 1 .66 -1.747q .158 -.298 .337 -.561a6.4 6.4 0 0 1 -.93 -.508a4 4 0 0 1 -.256 .43c-.366 .541 -.855 .98 -1.473 1.267l-.238 .1c-.994 .382 -1.97 .292 -2.855 -.091l-.188 -.087a3.8 3.8 0 0 1 -.716 -.443a1 1 0 0 1 -.356 -.917a3.95 3.95 0 0 1 .654 -1.613a3.6 3.6 0 0 1 1.71 -1.368c.38 -.146 .758 -.223 1.13 -.24a9 9 0 0 1 -.445 -1.023a4.23 4.23 0 0 1 -2.233 -.348a4 4 0 0 1 -.916 -.587l-.207 -.191a4 4 0 0 1 -.724 -.977l-.105 -.216a4.45 4.45 0 0 1 -.265 -2.806a1 1 0 0 1 .69 -.712q .119 -.036 .345 -.076c.801 -.135 1.678 -.082 2.53 .308q .283 .129 .545 .304q .048 -.235 .112 -.47a5 5 0 0 1 -.194 -.272c-.556 -.832 -.83 -1.806 -.642 -2.877l.05 -.242a3.75 3.75 0 0 1 1.027 -1.803l.169 -.159a4 4 0 0 1 1.303 -.796a1 1 0 0 1 .975 .178c.2 .168 .462 .446 .719 .83c.556 .833 .83 1.807 .642 2.878a3.77 3.77 0 0 1 -1.246 2.204c-.303 .27 -.607 .47 -.879 .61a7.5 7.5 0 0 0 -.255 1.971c0 3.502 2.285 6.272 5 6.272s5 -2.77 5 -6.276a7.6 7.6 0 0 0 -.253 -1.967a4.3 4.3 0 0 1 -.881 -.61a3.77 3.77 0 0 1 -1.246 -2.204c-.188 -1.07 .086 -2.045 .642 -2.877c.257 -.385 .52 -.663 .72 -.831a1 1 0 0 1 .974 -.178m-4.356 4.943a2 2 0 0 1 2 2v1a2 2 0 0 1 -2 2h-1v1h2a1 1 0 0 1 0 2h-2a2 2 0 0 1 -2 -2v-1a2 2 0 0 1 2 -2h1v-1h-2a1 1 0 0 1 0 -2z" />
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
unicode: "10167"
|
|
3
|
+
version: "3.33"
|
|
4
|
+
-->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="24"
|
|
8
|
+
height="24"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
fill="currentColor"
|
|
11
|
+
>
|
|
12
|
+
<path d="M16.956 2.057c.355 .124 .829 .375 1.303 .796a3.77 3.77 0 0 1 1.246 2.204c.173 .989 -.047 1.894 -.519 2.683l-.123 .194q -.097 .147 -.196 .272q .066 .234 .117 .471q .26 -.178 .545 -.307c.851 -.389 1.727 -.442 2.527 -.306q .226 .04 .346 .076a1 1 0 0 1 .689 .712l.029 .13q .015 .08 .03 .18a4.45 4.45 0 0 1 -.324 2.496a3.94 3.94 0 0 1 -1.71 1.85l-.242 .12a4.23 4.23 0 0 1 -2.234 .349a9 9 0 0 1 -.443 1.023c.37 .016 .748 .093 1.128 .24c.732 .28 1.299 .758 1.711 1.367a3.95 3.95 0 0 1 .654 1.613a1 1 0 0 1 -.356 .917a3.8 3.8 0 0 1 -.716 .443c-.933 .455 -1.978 .588 -3.043 .179l-.032 -.015l-.205 -.086a3.6 3.6 0 0 1 -1.33 -1.069l-.143 -.197a4 4 0 0 1 -.26 -.433a6 6 0 0 1 -.927 .511q .18 .262 .337 .56a7.4 7.4 0 0 1 .66 1.747a1 1 0 0 1 -1.95 .444l-.028 -.11a6 6 0 0 0 -.449 -1.143c-.342 -.645 -.71 -.968 -1.048 -.968s-.706 .323 -1.048 .969a5.6 5.6 0 0 0 -.367 .874l-.082 .269l-.028 .11a1 1 0 0 1 -1.95 -.444a7.3 7.3 0 0 1 .66 -1.747q .158 -.298 .337 -.561a6.4 6.4 0 0 1 -.93 -.508a4 4 0 0 1 -.256 .43c-.366 .541 -.855 .98 -1.473 1.267l-.238 .1c-.994 .382 -1.97 .292 -2.855 -.091l-.188 -.087a3.8 3.8 0 0 1 -.716 -.443a1 1 0 0 1 -.356 -.917a3.95 3.95 0 0 1 .654 -1.613a3.6 3.6 0 0 1 1.71 -1.368c.38 -.146 .758 -.223 1.13 -.24a9 9 0 0 1 -.445 -1.023a4.23 4.23 0 0 1 -2.233 -.348a4 4 0 0 1 -.916 -.587l-.207 -.191a4 4 0 0 1 -.724 -.977l-.105 -.216a4.45 4.45 0 0 1 -.265 -2.806a1 1 0 0 1 .69 -.712q .119 -.036 .345 -.076c.801 -.135 1.678 -.082 2.53 .308q .283 .129 .545 .304q .048 -.235 .112 -.47a5 5 0 0 1 -.194 -.272c-.556 -.832 -.83 -1.806 -.642 -2.877l.05 -.242a3.75 3.75 0 0 1 1.027 -1.803l.169 -.159a4 4 0 0 1 1.303 -.796a1 1 0 0 1 .975 .178c.2 .168 .462 .446 .719 .83c.556 .833 .83 1.807 .642 2.878a3.77 3.77 0 0 1 -1.246 2.204c-.303 .27 -.607 .47 -.879 .61a7.5 7.5 0 0 0 -.255 1.971c0 3.502 2.285 6.272 5 6.272s5 -2.77 5 -6.276a7.6 7.6 0 0 0 -.253 -1.967a4.3 4.3 0 0 1 -.881 -.61a3.77 3.77 0 0 1 -1.246 -2.204c-.188 -1.07 .086 -2.045 .642 -2.877c.257 -.385 .52 -.663 .72 -.831a1 1 0 0 1 .974 -.178m-4.956 4.943a2.5 2.5 0 0 1 2.125 3.817l-.125 .183l.019 .024c.273 .372 .445 .823 .477 1.312l.005 .164a2.5 2.5 0 0 1 -2.501 2.5h-1.5a1 1 0 0 1 0 -2h1.5a.5 .5 0 1 0 0 -1h-1l-.133 -.007c-1.199 -.129 -1.154 -1.993 .133 -1.993h1l.09 -.008a.5 .5 0 0 0 -.09 -.992h-1.5a1 1 0 1 1 0 -2z" />
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
unicode: "100c0"
|
|
3
|
+
version: "3.24"
|
|
4
|
+
-->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="24"
|
|
8
|
+
height="24"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
fill="currentColor"
|
|
11
|
+
>
|
|
12
|
+
<path d="M16.956 2.057c.355 .124 .829 .375 1.303 .796a3.77 3.77 0 0 1 1.246 2.204c.173 .989 -.047 1.894 -.519 2.683l-.123 .194q -.097 .147 -.196 .272q .066 .234 .117 .471q .26 -.178 .545 -.307c.851 -.389 1.727 -.442 2.527 -.306q .226 .04 .346 .076a1 1 0 0 1 .689 .712l.029 .13q .015 .08 .03 .18a4.45 4.45 0 0 1 -.324 2.496a3.94 3.94 0 0 1 -1.71 1.85l-.242 .12a4.23 4.23 0 0 1 -2.234 .349a9 9 0 0 1 -.443 1.023c.37 .016 .748 .093 1.128 .24c.732 .28 1.299 .758 1.711 1.367a3.95 3.95 0 0 1 .654 1.613a1 1 0 0 1 -.356 .917a3.8 3.8 0 0 1 -.716 .443c-.933 .455 -1.978 .588 -3.043 .179l-.032 -.015l-.205 -.086a3.6 3.6 0 0 1 -1.33 -1.069l-.143 -.197a4 4 0 0 1 -.26 -.433a6 6 0 0 1 -.927 .511q .18 .262 .337 .56a7.4 7.4 0 0 1 .66 1.747a1 1 0 0 1 -1.95 .444l-.028 -.11a6 6 0 0 0 -.449 -1.143c-.342 -.645 -.71 -.968 -1.048 -.968s-.706 .323 -1.048 .969a5.6 5.6 0 0 0 -.367 .874l-.082 .269l-.028 .11a1 1 0 0 1 -1.95 -.444a7.3 7.3 0 0 1 .66 -1.747q .158 -.298 .337 -.561a6.4 6.4 0 0 1 -.93 -.508a4 4 0 0 1 -.256 .43c-.366 .541 -.855 .98 -1.473 1.267l-.238 .1c-.994 .382 -1.97 .292 -2.855 -.091l-.188 -.087a3.8 3.8 0 0 1 -.716 -.443a1 1 0 0 1 -.356 -.917a3.95 3.95 0 0 1 .654 -1.613a3.6 3.6 0 0 1 1.71 -1.368c.38 -.146 .758 -.223 1.13 -.24a9 9 0 0 1 -.445 -1.023a4.23 4.23 0 0 1 -2.233 -.348a4 4 0 0 1 -.916 -.587l-.207 -.191a4 4 0 0 1 -.724 -.977l-.105 -.216a4.45 4.45 0 0 1 -.265 -2.806a1 1 0 0 1 .69 -.712q .119 -.036 .345 -.076c.801 -.135 1.678 -.082 2.53 .308q .283 .129 .545 .304q .048 -.235 .112 -.47a5 5 0 0 1 -.194 -.272c-.556 -.832 -.83 -1.806 -.642 -2.877l.05 -.242a3.75 3.75 0 0 1 1.027 -1.803l.169 -.159a4 4 0 0 1 1.303 -.796a1 1 0 0 1 .975 .178c.2 .168 .462 .446 .719 .83c.556 .833 .83 1.807 .642 2.878a3.77 3.77 0 0 1 -1.246 2.204c-.303 .27 -.607 .47 -.879 .61a7.5 7.5 0 0 0 -.255 1.971c0 3.502 2.285 6.272 5 6.272s5 -2.77 5 -6.276a7.6 7.6 0 0 0 -.253 -1.967a4.3 4.3 0 0 1 -.881 -.61a3.77 3.77 0 0 1 -1.246 -2.204c-.188 -1.07 .086 -2.045 .642 -2.877c.257 -.385 .52 -.663 .72 -.831a1 1 0 0 1 .974 -.178" />
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
version: "3.37"
|
|
3
|
+
unicode: "101b2"
|
|
4
|
+
-->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="24"
|
|
8
|
+
height="24"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
fill="currentColor"
|
|
11
|
+
>
|
|
12
|
+
<path d="M16 19a1 1 0 0 1 0 -2a1 1 0 0 0 1 -1c0 -1.333 2 -1.333 2 0a1 1 0 0 0 1 1c1.333 0 1.333 2 0 2a1 1 0 0 0 -1 1c0 1.333 -2 1.333 -2 0a1 1 0 0 0 -1 -1" />
|
|
13
|
+
<path d="M3 11a5 5 0 0 0 5 -5c0 -1.333 2 -1.333 2 0a5 5 0 0 0 5 5c1.333 0 1.333 2 0 2a5 5 0 0 0 -5 5a1 1 0 0 1 -2 0a5 5 0 0 0 -5 -5c-1.333 0 -1.333 -2 0 -2" />
|
|
14
|
+
<path d="M16 7a1 1 0 0 1 0 -2a1 1 0 0 0 1 -1c0 -1.333 2 -1.333 2 0a1 1 0 0 0 1 1c1.333 0 1.333 2 0 2a1 1 0 0 0 -1 1c0 1.333 -2 1.333 -2 0a1 1 0 0 0 -1 -1" />
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
version: "2.0"
|
|
3
|
+
unicode: "f6a8"
|
|
4
|
+
-->
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width="24"
|
|
8
|
+
height="24"
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
fill="currentColor"
|
|
11
|
+
>
|
|
12
|
+
<path d="M17.657 12.007a1.39 1.39 0 0 0 -1.103 .765l-.855 1.723l-1.907 .277c-.52 .072 -.96 .44 -1.124 .944l-.038 .14c-.1 .465 .046 .954 .393 1.29l1.377 1.337l-.326 1.892a1.393 1.393 0 0 0 2.018 1.465l1.708 -.895l1.708 .896a1.388 1.388 0 0 0 1.462 -.105l.112 -.09a1.39 1.39 0 0 0 .442 -1.272l-.325 -1.891l1.38 -1.339c.38 -.371 .516 -.924 .352 -1.427l-.051 -.134a1.39 1.39 0 0 0 -1.073 -.81l-1.907 -.278l-.853 -1.722a1.393 1.393 0 0 0 -1.247 -.773l-.143 .007z" />
|
|
13
|
+
<path d="M6.057 12.007a1.39 1.39 0 0 0 -1.103 .765l-.855 1.723l-1.907 .277c-.52 .072 -.96 .44 -1.124 .944l-.038 .14c-.1 .465 .046 .954 .393 1.29l1.377 1.337l-.326 1.892a1.393 1.393 0 0 0 2.018 1.465l1.708 -.895l1.708 .896a1.388 1.388 0 0 0 1.462 -.105l.112 -.09a1.39 1.39 0 0 0 .442 -1.272l-.324 -1.891l1.38 -1.339c.38 -.371 .516 -.924 .352 -1.427l-.051 -.134a1.39 1.39 0 0 0 -1.073 -.81l-1.908 -.279l-.853 -1.722a1.393 1.393 0 0 0 -1.247 -.772l-.143 .007z" />
|
|
14
|
+
<path d="M11.857 2.007a1.39 1.39 0 0 0 -1.103 .765l-.855 1.723l-1.907 .277c-.52 .072 -.96 .44 -1.124 .944l-.038 .14c-.1 .465 .046 .954 .393 1.29l1.377 1.337l-.326 1.892a1.393 1.393 0 0 0 2.018 1.465l1.708 -.894l1.709 .896a1.388 1.388 0 0 0 1.462 -.105l.112 -.09a1.39 1.39 0 0 0 .442 -1.272l-.325 -1.892l1.38 -1.339c.38 -.371 .516 -.924 .352 -1.427l-.051 -.134a1.39 1.39 0 0 0 -1.073 -.81l-1.908 -.279l-.853 -1.722a1.393 1.393 0 0 0 -1.247 -.772l-.143 .007z" />
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
tags: [kid, doodle, draw, drawing, scribble, typography, writing, font, character, word]
|
|
3
|
+
category: Text
|
|
4
|
+
version: "1.61"
|
|
5
|
+
unicode: "f0a3"
|
|
6
|
+
-->
|
|
7
|
+
<svg
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
width="24"
|
|
10
|
+
height="24"
|
|
11
|
+
viewBox="0 0 24 24"
|
|
12
|
+
fill="none"
|
|
13
|
+
stroke="currentColor"
|
|
14
|
+
stroke-width="2"
|
|
15
|
+
stroke-linecap="round"
|
|
16
|
+
stroke-linejoin="round"
|
|
17
|
+
>
|
|
18
|
+
<path d="M3 15c2 3 4 4 7 4s7 -3 7 -7s-3 -7 -6 -7s-5 1.5 -5 4s2 5 6 5s8.408 -2.453 10 -5" />
|
|
19
|
+
</svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
tags: [underscore, emphasis, horizontal, typography, underline, writing, font, character, word]
|
|
3
|
+
category: Text
|
|
4
|
+
version: "1.1"
|
|
5
|
+
unicode: "eba2"
|
|
6
|
+
-->
|
|
7
|
+
<svg
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
width="24"
|
|
10
|
+
height="24"
|
|
11
|
+
viewBox="0 0 24 24"
|
|
12
|
+
fill="none"
|
|
13
|
+
stroke="currentColor"
|
|
14
|
+
stroke-width="2"
|
|
15
|
+
stroke-linecap="round"
|
|
16
|
+
stroke-linejoin="round"
|
|
17
|
+
>
|
|
18
|
+
<path d="M7 5v5a5 5 0 0 0 10 0v-5" />
|
|
19
|
+
<path d="M5 19h14" />
|
|
20
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,i as t,r as n,t as r}from"./shared-BiRg4I01.js";import{$n as i,Dr as a,En as o,Gn as s,I as c,Jt as l,Mr as u,N as d,Nr as f,On as p,P as m,Qn as h,R as g,Sr as _,Xn as v,Yn as y,Yt as b,Zn as x,_ as S,_n as C,_r as w,_t as T,ar as E,br as D,cr as O,dr as k,f as A,g as j,gn as M,gr as N,gt as ee,h as P,hr as F,ht as I,ir as L,it as R,jr as z,kr as te,m as ne,mn as B,mt as re,p as ie,qt as V,rr as ae,sr as H,v as oe,vr as U,vt as se,wr as ce,xr as W,y as le,yr as ue,z as de,zn as fe}from"./index-DPDaBFld.js";var G=z(`badge-check`,[[`path`,{d:`M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z`,key:`3c2336`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]),pe=z(`circle-question-mark`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),me=z(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),he=z(`monitor`,[[`rect`,{width:`20`,height:`14`,x:`2`,y:`3`,rx:`2`,key:`48i651`}],[`line`,{x1:`8`,x2:`16`,y1:`21`,y2:`21`,key:`1svkeh`}],[`line`,{x1:`12`,x2:`12`,y1:`17`,y2:`21`,key:`vw1qmm`}]]),ge=z(`palette`,[[`path`,{d:`M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z`,key:`e79jfc`}],[`circle`,{cx:`13.5`,cy:`6.5`,r:`.5`,fill:`currentColor`,key:`1okk4w`}],[`circle`,{cx:`17.5`,cy:`10.5`,r:`.5`,fill:`currentColor`,key:`f64h9f`}],[`circle`,{cx:`6.5`,cy:`12.5`,r:`.5`,fill:`currentColor`,key:`qy21gx`}],[`circle`,{cx:`8.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`fotxhn`}]]),_e=z(`shapes`,[[`path`,{d:`M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z`,key:`1bo67w`}],[`rect`,{x:`3`,y:`14`,width:`7`,height:`7`,rx:`1`,key:`1bkyp8`}],[`circle`,{cx:`17.5`,cy:`17.5`,r:`3.5`,key:`w3z12y`}]]),ve=z(`tablet`,[[`rect`,{width:`16`,height:`20`,x:`4`,y:`2`,rx:`2`,ry:`2`,key:`76otgf`}],[`line`,{x1:`12`,x2:`12.01`,y1:`18`,y2:`18`,key:`1dp563`}]]),ye=z(`upload`,[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]),be=z(`watch`,[[`path`,{d:`M12 10v2.2l1.6 1`,key:`n3r21l`}],[`path`,{d:`m16.13 7.66-.81-4.05a2 2 0 0 0-2-1.61h-2.68a2 2 0 0 0-2 1.61l-.78 4.05`,key:`18k57s`}],[`path`,{d:`m7.88 16.36.8 4a2 2 0 0 0 2 1.61h2.72a2 2 0 0 0 2-1.61l.81-4.05`,key:`16ny36`}],[`circle`,{cx:`12`,cy:`12`,r:`6`,key:`1vlfrh`}]]),K=f(u(),1);function xe(e){let{open:t,defaultOpen:n,onOpenChange:r,disabled:i}=e,[a,c]=R({controlled:t,default:n,name:`Collapsible`,state:`open`}),{mounted:l,setMounted:u,transitionStatus:d}=b(a,!0,!0),f=o(),[m,h]=K.useState(),g=m??f,_=O(e=>{let t=!a,n=p(s,e.nativeEvent);r(t,n),!n.isCanceled&&c(t)});return K.useMemo(()=>({disabled:i,handleTrigger:_,mounted:l,open:a,panelId:g,setMounted:u,setOpen:c,setPanelIdState:h,transitionStatus:d}),[i,_,l,a,g,u,c,h,d])}var Se=K.createContext(void 0);function Ce(){let e=K.useContext(Se);if(e===void 0)throw Error(E(15));return e}var q=function(e){return e.open=`data-open`,e.closed=`data-closed`,e[e.startingStyle=y.startingStyle]=`startingStyle`,e[e.endingStyle=y.endingStyle]=`endingStyle`,e}({}),we=function(e){return e.panelOpen=`data-panel-open`,e}({}),Te={[q.open]:``},Ee={[q.closed]:``},De={open(e){return e?{[we.panelOpen]:``}:null}},Oe={open(e){return e?Te:Ee}},J={height:void 0,width:void 0};function ke(e){let{externalRef:t,hiddenUntilFound:n,id:r,keepMounted:i,mounted:a,onOpenChange:o,open:s,setMounted:c,setOpen:u,transitionStatus:d}=e,f=K.useRef(null),m=K.useRef(null),[h,g]=K.useState(J),_=K.useRef(J),v=K.useRef(!1),y=K.useRef(s),b=K.useRef(!1),[x,S]=K.useState(!1),w=K.useRef(null),T=ae(t,f),E=M({mounted:a,open:s}),D=l(f,!1,!1),k=!s&&!a,A=x?`idle`:d,j=s&&(y.current||b.current),N=!s&&a&&m.current===`css-animation`&&h.height===void 0&&h.width===void 0?_.current:h,ee=n&&k&&m.current!==`css-animation`,P=O((e,t=!0)=>{t&&(_.current=e),g(e)}),F=O(()=>{w.current?.(),w.current=null}),I=O(e=>{F(),w.current=()=>{w.current=null,e()}}),L=O(()=>{s&&a&&m.current===`css-animation`&&(b.current=!0)});H(()=>{!x||d===`starting`||S(!1)},[x,d]),K.useEffect(()=>()=>{L(),F()},[L,F]),H(()=>{let e=f.current;if(!e)return;!s&&w.current&&F();let t=Ae(e,j);if(m.current=t,s&&d===`idle`&&y.current&&t===`css-animation`){_.current=Y(e);return}if(s&&d===`starting`){let n=v.current;if(v.current=!1,t===`none`){P(Y(e)),S(!0);return}if(t===`css-transition`){let t=Me(e);if(P(Y(e)),!n)return t;let r=X(e,`transition-duration`,`0s`);return I(r),S(!0),t}if(t===`css-animation`){if(P(Y(e)),!n){X(e,`animation-name`,`none`)();return}let t=X(e,`animation-name`,`none`),r=X(e,`animation-duration`,`0s`);t(),I(r),S(!0);return}}if(!s&&a&&(d===`idle`||d===`starting`)){if(y.current=!1,b.current=!1,t===`none`){P(J,!1),c(!1);return}P(Y(e));return}if(d!==`ending`)return;if(t===`none`){c(!1);return}let n=Y(e);if(!((n.height??0)>0||(n.width??0)>0)){c(!1);return}P(n),t===`css-animation`&&X(e,`animation-name`,`none`)()},[a,s,F,P,c,I,j,d]),V({enabled:s&&a&&A===`idle`,open:!0,ref:f,onComplete(){s&&P(J,!1)}}),K.useEffect(()=>{if(s||!a||A!==`ending`||!f.current)return;let e=new AbortController,t=-1;function n(){E.current.open||(c(!1),P(J,!1))}return t=B.request(()=>{e.signal.aborted||D(n,e.signal)}),()=>{B.cancel(t),e.abort()}},[E,a,s,A,D,P,c]),H(()=>{let e=f.current;!e||!n||!k||e.setAttribute(`hidden`,`until-found`)},[k,n]),K.useEffect(function(){let e=f.current;if(!e)return;function t(e){let t=p(fe,e);o(!0,t),!t.isCanceled&&(v.current=!0,u(!0))}return C(e,`beforematch`,t)},[o,u]);let R=i||n||a||s;return{height:N.height,props:{...ee?{[q.startingStyle]:``}:void 0,hidden:k,id:r},ref:T,shouldPreventOpenAnimation:j,shouldRender:R,transitionStatus:A,width:N.width}}function Y(e){return{height:e.scrollHeight,width:e.scrollWidth}}function Ae(e,t=!1){let n=k(e).getComputedStyle(e),r=(n.animationName.split(`,`).map(e=>e.trim()).some(e=>e!==``&&e!==`none`)||t)&&je(n.animationDuration),i=je(n.transitionDuration);return r&&i||i?`css-transition`:r?`css-animation`:`none`}function je(e){return e.split(`,`).map(e=>e.trim()).some(e=>e!==``&&Number.parseFloat(e)>0)}function X(e,t,n){let r=e.style.getPropertyValue(t),i=e.style.getPropertyPriority(t);return e.style.setProperty(t,n),()=>{if(r===``){e.style.removeProperty(t);return}e.style.setProperty(t,r,i)}}function Me(e){let t={"justify-content":e.style.justifyContent,"align-items":e.style.alignItems,"align-content":e.style.alignContent,"justify-items":e.style.justifyItems};Object.keys(t).forEach(t=>{e.style.setProperty(t,`initial`,`important`)});function n(){Object.entries(t).forEach(([t,n])=>{if(n===``){e.style.removeProperty(t);return}e.style.setProperty(t,n)})}let r=B.request(n);return()=>{B.cancel(r),n()}}var Ne={...Oe,...v},Z=w(),Pe=K.forwardRef(function(e,t){let{render:n,className:r,defaultOpen:i=!1,disabled:a=!1,onOpenChange:o,open:s,style:c,...l}=e,u=O(o),d=xe({open:s,defaultOpen:i,onOpenChange:u,disabled:a}),f=K.useMemo(()=>({open:d.open,disabled:d.disabled,transitionStatus:d.transitionStatus}),[d.open,d.disabled,d.transitionStatus]),p=K.useMemo(()=>({...d,onOpenChange:u,state:f}),[d,u,f]),m=h(`div`,e,{state:f,ref:t,props:l,stateAttributesMapping:Ne});return(0,Z.jsx)(Se.Provider,{value:p,children:m})}),Fe={...De,...v},Ie=K.forwardRef(function(e,t){let{panelId:n,open:r,handleTrigger:i,state:a,disabled:o}=Ce(),{className:s,disabled:c=o,render:l,nativeButton:u=!0,style:d,...f}=e,{getButtonProps:p,buttonRef:m}=L({disabled:c,focusableWhenDisabled:!0,native:u});return h(`button`,e,{state:a,ref:[t,m],props:[{"aria-controls":r?n:void 0,"aria-expanded":r,onClick:i},f,p],stateAttributesMapping:Fe})}),Le=function(e){return e.collapsiblePanelHeight=`--collapsible-panel-height`,e.collapsiblePanelWidth=`--collapsible-panel-width`,e}({}),Re=K.forwardRef(function(e,t){let{className:n,hiddenUntilFound:r,keepMounted:a,render:o,id:s,style:c,...l}=e,{mounted:u,onOpenChange:d,open:f,panelId:p,setMounted:m,setPanelIdState:g,setOpen:_,state:v,transitionStatus:y}=Ce(),b=r??!1,x=a??!1;H(()=>{if(s)return g(s),()=>{g(void 0)}},[s,g]);let{height:S,props:C,ref:w,shouldPreventOpenAnimation:T,shouldRender:E,transitionStatus:D,width:O}=ke({externalRef:t,hiddenUntilFound:b,id:p,keepMounted:x,mounted:u,onOpenChange:d,open:f,setMounted:m,setOpen:_,transitionStatus:y}),k={...v,transitionStatus:D},A=i(c,k),j=h(`div`,{...e,style:void 0},{state:k,ref:w,props:[C,{style:{[Le.collapsiblePanelHeight]:S===void 0?`auto`:`${S}px`,[Le.collapsiblePanelWidth]:O===void 0?`auto`:`${O}px`}},l,A?{style:A}:void 0,T?{style:{animationName:`none`}}:void 0],stateAttributesMapping:Ne});return E?j:null});function ze({className:e,size:t=`default`,...n}){return(0,Z.jsx)(`div`,{"data-slot":`card`,"data-size":t,className:U(`group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl`,e),...n})}function Be({className:e,...t}){return(0,Z.jsx)(`div`,{"data-slot":`card-header`,className:U(`group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)`,e),...t})}function Ve({className:e,...t}){return(0,Z.jsx)(`div`,{"data-slot":`card-title`,className:U(`font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm`,e),...t})}function He({className:e,...t}){return(0,Z.jsx)(`div`,{"data-slot":`card-description`,className:U(`text-sm text-muted-foreground`,e),...t})}function Ue({className:e,...t}){return(0,Z.jsx)(`div`,{"data-slot":`card-content`,className:U(`px-(--card-spacing)`,e),...t})}var We=Pe;function Ge({className:e,...t}){return(0,Z.jsx)(Ie,{"data-slot":`collapsible-trigger`,className:U(e),...t})}function Ke({className:e,...t}){return(0,Z.jsx)(Re,{"data-slot":`collapsible-content`,className:U(e),...t})}var Q={screenshots:{label:`Raw screenshots`,description:`Unframed captures from your app`,icon:a},brand:{label:`Brand assets`,description:`Photography, illustrations, and artwork`,icon:ge},logos:{label:`Logos`,description:`App marks and partner logos`,icon:G},other:{label:`Other`,description:`Reusable supporting imagery`,icon:_e}},qe=/\.(png|jpe?g|webp|svg)$/i,$={iphone:`iPhone`,ipad:`iPad`,mac:`Mac`,watch:`Watch`},Je=[`iphone`,`ipad`,`mac`,`watch`,`unknown`],Ye={iphone:`1290 / 2796`,ipad:`3 / 4`,mac:`16 / 10`,watch:`422 / 514`,unknown:`4 / 3`};function Xe({project:t,onProjectChange:i}){let[a,o]=(0,K.useState)(`screenshots`),[s,l]=(0,K.useState)(!1),[u,f]=(0,K.useState)(null),[p,h]=(0,K.useState)(null),[v,y]=(0,K.useState)(!1),[b,C]=(0,K.useState)(null),[w,E]=(0,K.useState)(null),[O,k]=(0,K.useState)(()=>new Set),M=(0,K.useRef)(0),L=(0,K.useRef)(null),R=t.assets[a],z=a===`screenshots`?Je.map(e=>({id:e,label:e===`unknown`?`Unknown device`:$[e],assets:R.filter(t=>(t.deviceType??`unknown`)===e)})).filter(e=>e.assets.length>0):[{id:a,label:null,assets:R}];async function B(e){let t=Array.from(e.target.files??[]);e.target.value=``,await V(t)}async function V(e){if(e.length===0)return;let n=e.filter(e=>qe.test(e.name)),r=e.length-n.length;l(!0),f(null),h(null);let o=0,s=0,c=0,u=new Set(t.assets[a].map(e=>e.name)),d=[];try{for(let e of n)try{await _(`/api/assets?category=${a}&filename=${encodeURIComponent(e.name)}`,{method:`POST`,headers:{"Content-Type":e.type||`application/octet-stream`},body:e}),u.has(e.name)?s+=1:o+=1,u.add(e.name)}catch(t){t instanceof ue&&t.code===`DUPLICATE_ASSET`?c+=1:d.push(`${e.name}: ${W(t)}`)}(o>0||s>0)&&i(await _(`/api/project`));let e=[o>0?`Added ${o} ${o===1?`asset`:`assets`}.`:``,s>0?`Replaced ${s} ${s===1?`asset`:`assets`}.`:``,c>0?`Skipped ${c} ${c===1?`duplicate`:`duplicates`}.`:``,r>0?`Ignored ${r} unsupported ${r===1?`file`:`files`}.`:``].filter(Boolean).join(` `);e&&h(e),d.length>0&&f(d.join(` `))}finally{l(!1)}}function ae(e){e.dataTransfer.types.includes(`Files`)&&(e.preventDefault(),M.current+=1,y(!0))}function H(e){e.dataTransfer.types.includes(`Files`)&&(e.preventDefault(),M.current=Math.max(0,M.current-1),M.current===0&&y(!1))}function fe(e){e.dataTransfer.types.includes(`Files`)&&(e.preventDefault(),e.dataTransfer.dropEffect=`copy`)}async function G(e){if(e.preventDefault(),M.current=0,y(!1),!s)try{await V(await Qe(e.dataTransfer))}catch(e){f(W(e))}}async function pe(e){l(!0);try{await _(`/api/assets/${e.category}/${encodeURIComponent(e.name)}`,{method:`DELETE`}),i(await _(`/api/project`)),E(null)}catch(e){f(W(e))}finally{l(!1)}}async function he(e,t){l(!0),f(null);try{let n=await _(`/api/assets/${e.category}/${encodeURIComponent(e.name)}`,{method:`PATCH`,body:JSON.stringify({deviceType:t===`auto`?null:t})});i(n),C(t=>t?.id===e.id?n.assets.screenshots.find(t=>t.id===e.id)??null:t)}catch(e){f(W(e))}finally{l(!1)}}return(0,Z.jsxs)(`div`,{className:`relative h-full overflow-auto`,onDragEnter:ae,onDragLeave:H,onDragOver:fe,onDrop:G,children:[(0,Z.jsxs)(`div`,{className:`mx-auto max-w-7xl space-y-6 p-8`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-4`,children:[(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`p`,{className:`mb-1 text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground`,children:`Project library`}),(0,Z.jsx)(`h1`,{className:`text-2xl font-semibold tracking-tight`,children:`Asset catalog`}),(0,Z.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`Source files stay reusable and separate from the final screenshot sets.`})]}),(0,Z.jsx)(`input`,{ref:L,className:`hidden`,type:`file`,multiple:!0,accept:`image/png,image/jpeg,image/webp,image/svg+xml`,onChange:B}),(0,Z.jsxs)(x,{disabled:s,onClick:()=>L.current?.click(),children:[(0,Z.jsx)(ye,{className:`size-4`}),`Add to `,Q[a].label.toLowerCase()]})]}),(0,Z.jsx)(`div`,{className:`grid grid-cols-2 gap-2 lg:grid-cols-4`,children:r.map(e=>{let n=Q[e],r=n.icon,i=a===e;return(0,Z.jsxs)(x,{"aria-pressed":i,className:U(`h-11 w-full flex-row justify-start gap-2 rounded-lg px-2.5 text-left`,i&&`border-foreground/50 bg-muted/40 hover:border-foreground/50 hover:bg-muted/40`),type:`button`,variant:`outline`,onClick:()=>o(e),children:[(0,Z.jsx)(`span`,{className:U(`grid size-7 shrink-0 place-items-center rounded-md bg-muted text-muted-foreground`,i&&`bg-foreground text-background`),children:(0,Z.jsx)(r,{className:`size-3.5`})}),(0,Z.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-xs font-semibold`,children:n.label}),(0,Z.jsx)(A,{className:`h-5 px-1.5 text-[10px]`,variant:`secondary`,children:t.assets[e].length})]},e)})}),p&&(0,Z.jsx)(F,{role:`status`,variant:`muted`,children:(0,Z.jsx)(N,{children:p})}),u&&(0,Z.jsx)(F,{variant:`destructive`,children:(0,Z.jsx)(N,{children:u})}),(0,Z.jsxs)(ze,{className:`relative overflow-hidden`,children:[v&&(0,Z.jsx)(`div`,{className:`pointer-events-none absolute inset-0 z-10 grid place-items-center border-2 border-dashed border-primary bg-background/90 backdrop-blur-sm`,children:(0,Z.jsxs)(`div`,{className:`text-center`,children:[(0,Z.jsx)(`span`,{className:`mx-auto mb-3 grid size-12 place-items-center rounded-full bg-primary text-primary-foreground`,children:(0,Z.jsx)(ye,{className:`size-5`})}),(0,Z.jsx)(`p`,{className:`font-semibold`,children:`Drop files or folders here`}),(0,Z.jsxs)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:[`Supported images will be added to `,Q[a].label.toLowerCase(),`.`]})]})}),(0,Z.jsxs)(Be,{children:[(0,Z.jsx)(Ve,{children:Q[a].label}),(0,Z.jsxs)(He,{children:[Q[a].description,`. Add files or drop a folder; PNG, JPEG, WebP, and SVG up to 25 MB.`]})]}),(0,Z.jsx)(Ue,{children:R.length===0?(0,Z.jsxs)(x,{className:`h-auto min-h-72 w-full flex-col gap-3 rounded-xl border-dashed bg-muted/20 text-center whitespace-normal hover:bg-muted/40`,type:`button`,variant:`outline`,onClick:()=>L.current?.click(),children:[(0,Z.jsx)(`span`,{className:`grid size-12 place-items-center rounded-full border bg-background shadow-sm`,children:(0,Z.jsx)(e,{className:`size-5 text-muted-foreground`})}),(0,Z.jsxs)(`span`,{className:`text-sm font-medium`,children:[`Add your first `,Q[a].label.toLowerCase()]}),(0,Z.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Choose files or drop files and folders anywhere on this page.`})]}):(0,Z.jsx)(`div`,{className:`space-y-7`,children:z.map(e=>(0,Z.jsx)(`section`,{"aria-labelledby":e.label?`asset-group-${e.id}`:void 0,children:(0,Z.jsxs)(We,{open:!O.has(e.id),onOpenChange:t=>k(n=>{let r=new Set(n);return t?r.delete(e.id):r.add(e.id),r}),children:[e.label&&(0,Z.jsxs)(Ge,{className:`mb-3 flex w-full items-center gap-2 rounded-md py-1 text-left outline-none hover:text-foreground/70 focus-visible:ring-2 focus-visible:ring-ring [&[data-panel-open]>svg]:rotate-180`,id:`asset-group-${e.id}`,children:[(0,Z.jsx)(`span`,{className:`text-sm font-semibold`,children:e.label}),(0,Z.jsx)(A,{className:`h-5 px-2 text-[11px]`,variant:`secondary`,children:e.assets.length}),(0,Z.jsx)(te,{className:`ml-auto size-4 text-muted-foreground transition-transform`})]}),(0,Z.jsx)(Ke,{children:(0,Z.jsx)(`div`,{className:U(`grid gap-4`,a===`screenshots`?`grid-cols-[repeat(auto-fill,minmax(9rem,1fr))]`:`sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4`),children:e.assets.map(e=>(0,Z.jsxs)(`article`,{className:`group overflow-hidden rounded-xl border bg-background`,children:[(0,Z.jsxs)(x,{"aria-label":`Preview ${e.name}`,className:`relative grid h-auto w-full place-items-center overflow-hidden rounded-none bg-[linear-gradient(45deg,#f4f4f5_25%,transparent_25%),linear-gradient(-45deg,#f4f4f5_25%,transparent_25%),linear-gradient(45deg,transparent_75%,#f4f4f5_75%),linear-gradient(-45deg,transparent_75%,#f4f4f5_75%)] bg-[length:20px_20px] bg-[position:0_0,0_10px,10px_-10px,-10px_0px] p-0 hover:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset active:translate-y-0`,style:{aspectRatio:a===`screenshots`?Ye[e.deviceType??`unknown`]:`4 / 3`},type:`button`,variant:`ghost`,onClick:()=>C(e),children:[(0,Z.jsx)(`img`,{className:`h-full w-full object-contain`,src:e.url,alt:e.name}),(0,Z.jsxs)(`span`,{className:`absolute inset-0 grid place-items-center bg-black/0 opacity-0 transition-all group-hover:bg-black/20 group-hover:opacity-100 group-focus-within:bg-black/20 group-focus-within:opacity-100`,children:[(0,Z.jsx)(`span`,{className:`grid size-10 place-items-center rounded-full bg-background/90 shadow-sm`,children:(0,Z.jsx)(me,{className:`size-4`})}),(0,Z.jsxs)(`span`,{className:`absolute bottom-2 left-2 rounded-md bg-black/70 px-2 py-1 text-[10px] font-medium text-white shadow-sm backdrop-blur-sm`,children:[e.width&&e.height?`${e.width} × ${e.height} · `:``,D(e.size)]})]})]}),(0,Z.jsxs)(`div`,{className:`flex items-center justify-between gap-1.5 px-2 py-1.5`,children:[(0,Z.jsx)(`div`,{className:`min-w-0`,children:(0,Z.jsx)(`p`,{className:`truncate text-xs font-medium`,title:e.name,children:e.name})}),(0,Z.jsxs)(`div`,{className:`flex shrink-0 items-center gap-0.5`,children:[a===`screenshots`&&(0,Z.jsxs)(d,{disabled:s,value:e.deviceTypeOverride??`auto`,onValueChange:t=>{t!==null&&he(e,t)},children:[(0,Z.jsx)(g,{"aria-label":`Device type for ${e.name}`,className:`justify-center border-0 bg-transparent text-muted-foreground hover:bg-muted hover:text-foreground [&>svg:last-child]:hidden`,title:e.deviceType&&e.deviceType!==`unknown`?$[e.deviceType]:`Unknown device`,size:`icon-xs`,children:(0,Z.jsx)(de,{children:(0,Z.jsx)(Ze,{deviceType:e.deviceType??`unknown`})})}),(0,Z.jsxs)(m,{children:[(0,Z.jsxs)(c,{value:`auto`,children:[`Auto · `,e.detectedDeviceType&&e.detectedDeviceType!==`unknown`?$[e.detectedDeviceType]:`Unknown`]}),n.map(e=>(0,Z.jsx)(c,{value:e,children:$[e]},e))]})]}),(0,Z.jsx)(x,{"aria-label":`Delete ${e.name}`,className:`text-muted-foreground hover:text-foreground`,disabled:s,size:`icon-xs`,variant:`ghost`,onClick:()=>E(e),children:(0,Z.jsx)(ce,{className:`size-3.5`})})]})]})]},e.id))})})]})},e.id))})})]})]}),(0,Z.jsx)(re,{open:!!b,onOpenChange:e=>{e||C(null)},children:b&&(0,Z.jsxs)(I,{className:`h-[calc(100vh-2rem)] max-w-7xl grid-rows-[auto_minmax(0,1fr)] gap-0 overflow-hidden p-0`,children:[(0,Z.jsxs)(T,{className:`border-b px-4 py-3 pr-14`,children:[(0,Z.jsx)(se,{className:`truncate text-sm`,children:b.name}),(0,Z.jsxs)(ee,{className:`text-xs`,children:[Q[b.category].label,` · `,D(b.size)]})]}),(0,Z.jsx)(`div`,{className:`relative min-h-0 overflow-hidden bg-black/85 p-4`,children:(0,Z.jsx)(`img`,{className:`size-full object-contain`,src:b.url,alt:b.name})})]})}),(0,Z.jsx)(ie,{open:!!w,onOpenChange:e=>{!e&&!s&&E(null)},children:(0,Z.jsxs)(P,{children:[(0,Z.jsxs)(oe,{children:[(0,Z.jsx)(le,{children:`Delete this asset?`}),(0,Z.jsxs)(j,{children:[w?.name,` will be removed from the local asset catalog. Existing canvas layers that use it will no longer render.`]})]}),(0,Z.jsxs)(S,{children:[(0,Z.jsx)(ne,{render:(0,Z.jsx)(x,{disabled:s,variant:`outline`}),children:`Cancel`}),(0,Z.jsx)(x,{disabled:s||!w,variant:`destructive`,onClick:()=>{w&&pe(w)},children:`Delete asset`})]})]})})]})}function Ze({deviceType:e}){let n={iphone:t,ipad:ve,mac:he,watch:be,unknown:pe}[e];return(0,Z.jsx)(n,{className:`size-3.5`})}async function Qe(e){let t=Array.from(e.items).map(e=>e.webkitGetAsEntry?.()).filter(e=>!!e);return t.length===0?Array.from(e.files):(await Promise.all(t.map($e))).flat()}async function $e(e){if(e.isFile){let t=e;return[await new Promise((e,n)=>t.file(e,n))]}if(!e.isDirectory)return[];let t=e.createReader(),n=[];for(;;){let e=await new Promise((e,n)=>t.readEntries(e,n));if(e.length===0)break;n.push(...e)}return(await Promise.all(n.map($e))).flat()}export{Xe as AssetsView};
|