@snowcone-app/canvas 0.17.0 → 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{CanvasStateV1-C6i6vU6p.js → CanvasStateV1-BG2hEc3-.js} +3 -3
- package/dist/{CanvasStateV1-C6i6vU6p.js.map → CanvasStateV1-BG2hEc3-.js.map} +1 -1
- package/dist/EditorCanvasImpl-DgXvuWXX.js +70 -0
- package/dist/EditorCanvasImpl-DgXvuWXX.js.map +1 -0
- package/dist/EditorContext-CGkfmbgo.js +1178 -0
- package/dist/EditorContext-CGkfmbgo.js.map +1 -0
- package/dist/{ElementFactory-C05JJkRp.js → ElementFactory-CuHSAPfg.js} +1469 -710
- package/dist/ElementFactory-CuHSAPfg.js.map +1 -0
- package/dist/{HybridHistoryManager-Bht98XRv.js → FontAnalyzer-CLv7_msL.js} +2104 -2903
- package/dist/FontAnalyzer-CLv7_msL.js.map +1 -0
- package/dist/{ImportManager-kRYfIX-D.js → ImportManager-C_wBjWaV.js} +147 -147
- package/dist/{ImportManager-kRYfIX-D.js.map → ImportManager-C_wBjWaV.js.map} +1 -1
- package/dist/SnowconeCanvas-wdckG-6O.js +1179 -0
- package/dist/SnowconeCanvas-wdckG-6O.js.map +1 -0
- package/dist/{UnifiedFontService-BAtqqkU4.js → UnifiedFontService-Dsu5cwfT.js} +141 -141
- package/dist/UnifiedFontService-Dsu5cwfT.js.map +1 -0
- package/dist/advanced.mjs +10 -10
- package/dist/components/editor/RootInternals.d.ts +7 -0
- package/dist/components/editor/designStateStore.d.ts +1 -1
- package/dist/components/embed/EmbedRoot.d.ts +23 -0
- package/dist/components/embed/SnowconeCanvas.d.ts +13 -0
- package/dist/components/embed/kernel.d.ts +114 -0
- package/dist/contexts/BoundLayerGuardContext.d.ts +36 -0
- package/dist/core/GroupElement.d.ts +0 -5
- package/dist/core/TextElement.d.ts +8 -3
- package/dist/core/paint-registry.d.ts +42 -0
- package/dist/core/rich-text-layout.d.ts +28 -0
- package/dist/{editorErrors-DbIEtCTt.js → editorErrors-BY4Pdg7a.js} +2 -2
- package/dist/{editorErrors-DbIEtCTt.js.map → editorErrors-BY4Pdg7a.js.map} +1 -1
- package/dist/{embed-Bdj4PKUA.js → embed-32ZVWfmj.js} +209 -200
- package/dist/embed-32ZVWfmj.js.map +1 -0
- package/dist/embed.mjs +21 -22
- package/dist/embed.mjs.map +1 -1
- package/dist/index.mjs +7 -7
- package/dist/internals.mjs +93 -93
- package/dist/rendering/element-painters.d.ts +16 -0
- package/dist/rendering/rich-text-renderer.d.ts +3 -28
- package/dist/{template-fields-GOM4MNfq.js → template-fields-Z9x13sjM.js} +32 -33
- package/dist/{template-fields-GOM4MNfq.js.map → template-fields-Z9x13sjM.js.map} +1 -1
- package/dist/testing.mjs +7 -7
- package/dist/transforms/ArchTransform.d.ts +0 -1
- package/dist/transforms/AscendTransform.d.ts +0 -1
- package/dist/transforms/CircleTransform.d.ts +0 -1
- package/dist/transforms/FlagTransform.d.ts +0 -1
- package/dist/transforms/LeanTransform.d.ts +0 -1
- package/dist/transforms/WaveTransform.d.ts +0 -1
- package/dist/{usePieceGuideBundle-CGERAQJl.js → usePieceGuideBundle-C1ipFnZd.js} +2 -2
- package/dist/{usePieceGuideBundle-CGERAQJl.js.map → usePieceGuideBundle-C1ipFnZd.js.map} +1 -1
- package/dist/{validation-DEd6EOCP.js → validation-C795COGQ.js} +4803 -4791
- package/dist/validation-C795COGQ.js.map +1 -0
- package/dist/vendor/ui/primitives/kbd.d.ts +1 -1
- package/dist/workers/export-worker.bundle.string.d.ts +1 -1
- package/package.json +7 -4
- package/dist/EditorCanvasImpl-DkgE5-C2.js +0 -68
- package/dist/EditorCanvasImpl-DkgE5-C2.js.map +0 -1
- package/dist/EditorContext-CyanYzo2.js +0 -1131
- package/dist/EditorContext-CyanYzo2.js.map +0 -1
- package/dist/ElementFactory-C05JJkRp.js.map +0 -1
- package/dist/HybridHistoryManager-Bht98XRv.js.map +0 -1
- package/dist/SnowconeCanvas-C3eZ9PP8.js +0 -1047
- package/dist/SnowconeCanvas-C3eZ9PP8.js.map +0 -1
- package/dist/UnifiedFontService-BAtqqkU4.js.map +0 -1
- package/dist/editorError-DMENTZ-3.js +0 -19
- package/dist/editorError-DMENTZ-3.js.map +0 -1
- package/dist/embed-Bdj4PKUA.js.map +0 -1
- package/dist/validation-DEd6EOCP.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UnifiedFontService-Dsu5cwfT.js","sources":["../src/icons/icon-data.ts","../src/icons/registry.ts","../src/utils/ElementPreviewRenderer.ts","../src/hooks/useLayers.ts","../src/hooks/useArtboards.ts","../src/hooks/useExport.ts","../src/services/imageSearch.ts","../src/contexts/CanvasServicesContext.tsx","../src/utils/GoogleFontsService.ts","../src/utils/UnifiedFontService.ts"],"sourcesContent":["// AUTO-GENERATED FILE - DO NOT EDIT\n// Generated by: pnpm generate:icons\n// Icons included: 93\n// Approximate size: 34.2 KB\n//\n// To regenerate this file after adding new icons:\n// pnpm generate:icons\n\nimport type { IconifyIcon } from '@iconify/react';\n\nexport const canvasIcons: Record<string, IconifyIcon> = {\n \"eos-icons:loading\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M12 2A10 10 0 1 0 22 12A10 10 0 0 0 12 2Zm0 18a8 8 0 1 1 8-8A8 8 0 0 1 12 20Z\\\" opacity=\\\".5\\\"/><path fill=\\\"currentColor\\\" d=\\\"M20 12h2A10 10 0 0 0 12 2V4A8 8 0 0 1 20 12Z\\\"><animateTransform attributeName=\\\"transform\\\" dur=\\\"1s\\\" from=\\\"0 12 12\\\" repeatCount=\\\"indefinite\\\" to=\\\"360 12 12\\\" type=\\\"rotate\\\"/></path>\",\n \"width\": 24,\n \"height\": 24\n },\n \"fa6-solid:icons\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M500.3 7.3c7.4 6 11.7 15.1 11.7 24.7v144c0 26.5-28.7 48-64 48s-64-21.5-64-48s28.7-48 64-48V71l-96 19.2V208c0 26.5-28.7 48-64 48s-64-21.5-64-48s28.7-48 64-48V64c0-15.3 10.8-28.4 25.7-31.4l160-32c9.4-1.9 19.1.6 26.6 6.6zM74.7 304l11.8-17.8c5.9-8.9 15.9-14.2 26.6-14.2h61.7c10.7 0 20.7 5.3 26.6 14.2l11.9 17.8H240c26.5 0 48 21.5 48 48v112c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V352c0-26.5 21.5-48 48-48zM192 408a48 48 0 1 0-96 0a48 48 0 1 0 96 0m286.7-129.7L440.3 368H496c6.7 0 12.6 4.1 15 10.4s.6 13.3-4.4 17.7l-128 112c-5.6 4.9-13.9 5.3-19.9.9s-8.2-12.4-5.3-19.2l38.3-89.8H336c-6.7 0-12.6-4.1-15-10.4s-.6-13.3 4.4-17.7l128-112c5.6-4.9 13.9-5.3 19.9-.9s8.2 12.4 5.3 19.2zm-339-59.2c-6.5 6.5-17 6.5-23 0l-96.8-99.9c-28-29-26.5-76.9 5-103.9c27-23.5 68.4-19 93.4 6.5l10 10.5l9.5-10.5c25-25.5 65.9-30 93.9-6.5c31 27 32.5 74.9 4.5 103.9l-96.4 99.9z\\\"/>\",\n \"width\": 512,\n \"height\": 512\n },\n \"gravity-ui:arrow-down-to-square\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M8.53 11.78a.75.75 0 0 1-1.06 0l-2.5-2.5a.75.75 0 0 1 1.06-1.06l1.22 1.22V1.75a.75.75 0 0 1 1.5 0v7.69l1.22-1.22a.75.75 0 1 1 1.06 1.06zM4.25 4a.75.75 0 1 1 0 1.5H4A1.5 1.5 0 0 0 2.5 7v5A1.5 1.5 0 0 0 4 13.5h8a1.5 1.5 0 0 0 1.5-1.5V7A1.5 1.5 0 0 0 12 5.5h-.25a.75.75 0 0 1 0-1.5H12a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:arrow-left\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M14.75 8a.75.75 0 0 1-.75.75H3.81l2.72 2.72a.75.75 0 1 1-1.06 1.06l-4-4a.75.75 0 0 1 0-1.06l4-4a.75.75 0 0 1 1.06 1.06L3.81 7.25H14a.75.75 0 0 1 .75.75\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:arrow-rotate-left\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M8 1.5a6.5 6.5 0 1 1-6.445 7.348a.75.75 0 1 1 1.487-.194A5.001 5.001 0 1 0 4.43 4.5h1.32a.75.75 0 0 1 0 1.5h-3A.75.75 0 0 1 2 5.25v-3a.75.75 0 0 1 1.5 0v1.06A6.48 6.48 0 0 1 8 1.5\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:bars\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M1.25 3.25A.75.75 0 0 1 2 2.5h12A.75.75 0 0 1 14 4H2a.75.75 0 0 1-.75-.75m0 4.75A.75.75 0 0 1 2 7.25h12a.75.75 0 0 1 0 1.5H2A.75.75 0 0 1 1.25 8M2 12a.75.75 0 0 0 0 1.5h12a.75.75 0 0 0 0-1.5z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:bold\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M4.25 2.25A.75.75 0 0 0 3.5 3v10c0 .414.336.75.75.75H9.5a3.25 3.25 0 0 0 1.477-6.146A3.25 3.25 0 0 0 8.5 2.25zm3.5 5a1.75 1.75 0 1 0 0-3.5h-2v3.5zm-2 1.5v3.5h3a1.75 1.75 0 1 0 0-3.5z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:check\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M13.488 3.43a.75.75 0 0 1 .081 1.058l-6 7a.75.75 0 0 1-1.1.042l-3.5-3.5A.75.75 0 0 1 4.03 6.97l2.928 2.927l5.473-6.385a.75.75 0 0 1 1.057-.081\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:chevron-down\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M2.97 5.47a.75.75 0 0 1 1.06 0L8 9.44l3.97-3.97a.75.75 0 1 1 1.06 1.06l-4.5 4.5a.75.75 0 0 1-1.06 0l-4.5-4.5a.75.75 0 0 1 0-1.06\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:chevron-right\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M5.47 13.03a.75.75 0 0 1 0-1.06L9.44 8L5.47 4.03a.75.75 0 0 1 1.06-1.06l4.5 4.5a.75.75 0 0 1 0 1.06l-4.5 4.5a.75.75 0 0 1-1.06 0\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:chevron-up\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M13.03 10.53a.75.75 0 0 1-1.06 0L8 6.56l-3.97 3.97a.75.75 0 1 1-1.06-1.06l4.5-4.5a.75.75 0 0 1 1.06 0l4.5 4.5a.75.75 0 0 1 0 1.06\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:circle-fill\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:copy\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M12 2.5H8A1.5 1.5 0 0 0 6.5 4v1H8a3 3 0 0 1 3 3v1.5h1A1.5 1.5 0 0 0 13.5 8V4A1.5 1.5 0 0 0 12 2.5M11 11h1a3 3 0 0 0 3-3V4a3 3 0 0 0-3-3H8a3 3 0 0 0-3 3v1H4a3 3 0 0 0-3 3v4a3 3 0 0 0 3 3h4a3 3 0 0 0 3-3zM4 6.5h4A1.5 1.5 0 0 1 9.5 8v4A1.5 1.5 0 0 1 8 13.5H4A1.5 1.5 0 0 1 2.5 12V8A1.5 1.5 0 0 1 4 6.5\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:italic\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M7.25 2a.75.75 0 0 0 0 1.5h1.317l-2.7 9H4.25a.75.75 0 1 0 0 1.5h4.5a.75.75 0 0 0 0-1.5H7.433l2.7-9h1.617a.75.75 0 0 0 0-1.5z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:layers\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"m2.789 5.283l4.037-2.02A2.5 2.5 0 0 1 7.944 3h.112c.388 0 .77.09 1.118.264l4.037 2.019a.522.522 0 0 1 0 .934l-4.037 2.02a2.5 2.5 0 0 1-1.118.263h-.112a2.5 2.5 0 0 1-1.118-.264L2.79 6.217a.523.523 0 0 1 0-.934M1 5.75c0-.766.433-1.466 1.118-1.809l4.037-2.019a4 4 0 0 1 1.79-.422h.11a4 4 0 0 1 1.79.422l4.037 2.019a2.023 2.023 0 0 1 0 3.618l-.882.44l.882.442a2.023 2.023 0 0 1 0 3.618l-4.037 2.019a4 4 0 0 1-1.79.422h-.11a4 4 0 0 1-1.79-.422l-4.037-2.02a2.023 2.023 0 0 1 0-3.617L3 8l-.882-.441A2.02 2.02 0 0 1 1 5.75m3.677 3.088l-1.888.945a.523.523 0 0 0 0 .934l4.037 2.019A2.5 2.5 0 0 0 7.944 13h.112a2.5 2.5 0 0 0 1.118-.264l4.037-2.019a.523.523 0 0 0 0-.934l-1.888-.945l-1.478.74a4 4 0 0 1-1.79.422h-.11a4 4 0 0 1-1.79-.422z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:magic-wand\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"m11.1 5.894l-.412.903l.671.732l1.356 1.48l-1.994-.227l-.986-.113l-.49.864l-.987 1.747l-.4-1.967l-.198-.972l-.973-.198l-1.966-.4l1.746-.989l.864-.489l-.112-.986l-.227-1.994L8.47 4.641l.732.67l.903-.411l1.826-.832zM7.02 1.276l2.465 2.26l3.043-1.387c.842-.384 1.708.483 1.325 1.324l-1.387 3.043l2.259 2.465c.625.682.069 1.774-.85 1.67l-3.323-.38l-1.646 2.911c-.456.805-1.666.613-1.85-.293l-.667-3.277l-3.277-.666c-.906-.185-1.098-1.395-.293-1.85l2.91-1.647l-.378-3.322c-.105-.92.987-1.476 1.669-.85M5.53 11.53a.75.75 0 1 0-1.06-1.06l-3.5 3.5a.75.75 0 1 0 1.06 1.06z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:magnifier\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M11.5 7a4.5 4.5 0 1 1-9 0a4.5 4.5 0 0 1 9 0m-.82 4.74a6 6 0 1 1 1.06-1.06l2.79 2.79a.75.75 0 1 1-1.06 1.06z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:minus\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M1.75 8a.75.75 0 0 1 .75-.75h11a.75.75 0 0 1 0 1.5h-11A.75.75 0 0 1 1.75 8\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:pencil\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M11.423 1A3.577 3.577 0 0 1 15 4.577c0 .27-.108.53-.3.722l-.528.529l-1.971 1.971l-5.059 5.059a3 3 0 0 1-1.533.82l-2.638.528a1 1 0 0 1-1.177-1.177l.528-2.638a3 3 0 0 1 .82-1.533l5.059-5.059l2.5-2.5c.191-.191.451-.299.722-.299m-2.31 4.009l-4.91 4.91a1.5 1.5 0 0 0-.41.766l-.38 1.903l1.902-.38a1.5 1.5 0 0 0 .767-.41l4.91-4.91a2.08 2.08 0 0 0-1.88-1.88m3.098.658a3.6 3.6 0 0 0-1.878-1.879l1.28-1.28c.995.09 1.788.884 1.878 1.88z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:picture\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M11.5 3h-7A1.5 1.5 0 0 0 3 4.5v5.027l.962-.7a1.75 1.75 0 0 1 2.079.016l.928.696l2.368-2.03a1.75 1.75 0 0 1 2.325.043L13 8.787V4.5A1.5 1.5 0 0 0 11.5 3m3 7.498V4.5a3 3 0 0 0-3-3h-7a3 3 0 0 0-3 3v7a3 3 0 0 0 3 3h7a3 3 0 0 0 3-3zm-1.5.33l-2.355-2.174a.25.25 0 0 0-.332-.006L7.488 11.07l-.457.392l-.481-.361l-1.41-1.057a.25.25 0 0 0-.296-.002L3 11.381v.119A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5zM7.5 6a1.5 1.5 0 1 1-3 0a1.5 1.5 0 0 1 3 0\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:plus\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M8 1.75a.75.75 0 0 1 .75.75v4.75h4.75a.75.75 0 0 1 0 1.5H8.75v4.75a.75.75 0 0 1-1.5 0V8.75H2.5a.75.75 0 0 1 0-1.5h4.75V2.5A.75.75 0 0 1 8 1.75\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:scissors\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M4.5 6a1.5 1.5 0 1 0 0-3a1.5 1.5 0 0 0 0 3m-3-1.5a3 3 0 0 0 4.524 2.585L6.939 8l-.915.915a3 3 0 1 0 1.06 1.06L8.122 8.94l5.501 3.209a.75.75 0 1 0 .756-1.296L9.488 8l4.89-2.852a.75.75 0 0 0-.756-1.296l-5.5 3.209l-1.037-1.037A3 3 0 1 0 1.5 4.5m3 5.5a1.5 1.5 0 1 1 0 3a1.5 1.5 0 0 1 0-3\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:sparkles\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M13 10a.75.75 0 0 1 .725.556a2.37 2.37 0 0 0 1.72 1.72a.75.75 0 0 1 0 1.449a2.37 2.37 0 0 0-1.72 1.72a.75.75 0 0 1-1.45 0a2.37 2.37 0 0 0-1.72-1.72a.75.75 0 0 1 0-1.45a2.37 2.37 0 0 0 1.72-1.72l.043-.117A.75.75 0 0 1 13 10M7 0a1.5 1.5 0 0 1 1.48 1.253c.242 1.455.696 2.364 1.3 2.968c.603.603 1.512 1.057 2.967 1.3a1.5 1.5 0 0 1 0 2.958c-1.455.243-2.364.697-2.968 1.3c-.603.604-1.057 1.513-1.3 2.968a1.5 1.5 0 0 1-2.958 0c-.243-1.455-.697-2.364-1.3-2.968c-.604-.603-1.513-1.057-2.968-1.3a1.5 1.5 0 0 1 0-2.958c1.455-.243 2.364-.697 2.968-1.3c.603-.604 1.057-1.513 1.3-2.968l.028-.133A1.5 1.5 0 0 1 7 0m0 1.5C6.45 4.8 4.8 6.45 1.5 7c3.3.55 4.95 2.2 5.5 5.5c.55-3.3 2.2-4.95 5.5-5.5C9.2 6.45 7.55 4.8 7 1.5\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:text\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M3.279 2.544A.75.75 0 0 1 4 2h8a.75.75 0 0 1 .721.544l.5 1.75a.75.75 0 1 1-1.442.412L11.434 3.5H8.75l-.004 9H9.5a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1 0-1.5h.746l.004-9H4.566L4.22 4.706a.75.75 0 1 1-1.442-.412z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:text-align-center\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M2.75 2a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zm0 7a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zm2 3.5a.75.75 0 0 0 0 1.5h6.5a.75.75 0 0 0 0-1.5zM4 6.25a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 0 1.5h-6.5A.75.75 0 0 1 4 6.25\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:text-align-justify\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M2.75 2a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zM2 6.25a.75.75 0 0 1 .75-.75h10.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 6.25M2.75 9a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zm0 3.5a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:text-align-left\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M2.75 2a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zm0 7a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zm0 3.5a.75.75 0 0 0 0 1.5h6.5a.75.75 0 0 0 0-1.5zM2 6.25a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 0 1.5h-6.5A.75.75 0 0 1 2 6.25\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:text-align-right\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M2.75 2a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zM6 6.25a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 0 1.5h-6.5A.75.75 0 0 1 6 6.25M2.75 9a.75.75 0 0 0 0 1.5h10.5a.75.75 0 0 0 0-1.5zm4 3.5a.75.75 0 0 0 0 1.5h6.5a.75.75 0 0 0 0-1.5z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"gravity-ui:underline\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M5 2.75a.75.75 0 0 0-1.5 0V7a4.5 4.5 0 0 0 9 0V2.75a.75.75 0 0 0-1.5 0V7a3 3 0 0 1-6 0zm-.75 9.75a.75.75 0 0 0 0 1.5h7.5a.75.75 0 0 0 0-1.5z\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"healthicons:polygon\": {\n \"body\": \"<path fill=\\\"currentColor\\\" fill-rule=\\\"evenodd\\\" d=\\\"M28 10c0 .507-.094.992-.266 1.438l7.696 5.497a4 4 0 1 1 2.706 7.063l-2.32 10.437A4 4 0 1 1 30.126 39H17.874A4.002 4.002 0 0 1 10 38a4 4 0 0 1 2.184-3.565l-2.32-10.437a4 4 0 1 1 2.706-7.063l7.696-5.497A4 4 0 1 1 28 10m-6.57 3.065l-7.696 5.497a4 4 0 0 1-1.917 5.003l2.319 10.437A4 4 0 0 1 17.874 37h12.252a4 4 0 0 1 3.738-2.998l2.32-10.437a4 4 0 0 1-1.918-5.003l-7.695-5.497A3.98 3.98 0 0 1 24 14a3.98 3.98 0 0 1-2.57-.935\\\" clip-rule=\\\"evenodd\\\"/>\",\n \"width\": 48,\n \"height\": 48\n },\n \"heroicons:swatch\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"1.5\\\" d=\\\"M4.098 19.902a3.75 3.75 0 0 0 5.304 0l6.401-6.402M6.75 21A3.75 3.75 0 0 1 3 17.25V4.125C3 3.504 3.504 3 4.125 3h5.25c.621 0 1.125.504 1.125 1.125v4.072M6.75 21a3.75 3.75 0 0 0 3.75-3.75V8.197M6.75 21h13.125c.621 0 1.125-.504 1.125-1.125v-5.25c0-.621-.504-1.125-1.125-1.125h-4.072M10.5 8.197l2.88-2.88a1.124 1.124 0 0 1 1.59 0l3.712 3.713c.44.44.44 1.152 0 1.59l-2.879 2.88M6.75 17.25h.008v.008H6.75z\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"hugeicons:layer-bring-forward\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"1.5\\\" d=\\\"m15.89 11.5l3.397 1.56C21.096 13.892 22 14.308 22 15s-.904 1.109-2.713 1.94l-4.893 2.247c-1.18.542-1.77.813-2.394.813s-1.214-.271-2.394-.813l-4.893-2.248C2.904 16.11 2 15.693 2 15s.904-1.109 2.713-1.94L8.11 11.5m3.89-7V15m3-8c-.59-.607-2.16-3-3-3S9.59 6.393 9 7\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"hugeicons:layer-send-backward\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"1.5\\\" d=\\\"m15.89 12.5l3.397-1.56C21.096 10.108 22 9.692 22 9s-.904-1.109-2.713-1.94l-4.893-2.247C13.214 4.271 12.624 4 12 4s-1.214.271-2.394.813L4.713 7.061C2.904 7.89 2 8.307 2 9s.904 1.109 2.713 1.94L8.11 12.5m3.89 7V9m3 8c-.59.607-2.16 3-3 3s-2.41-2.393-3-3\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:a-large-small\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"m15 16l2.536-7.328a1.02 1.02 1 0 1 1.928 0L22 16m-6.303-2h5.606M2 16l4.039-9.69a.5.5 0 0 1 .923 0L11 16m-7.696-3h6.392\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:aperture\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\"/><path d=\\\"m14.31 8l5.74 9.94M9.69 8h11.48M7.38 12l5.74-9.94M9.69 16L3.95 6.06M14.31 16H2.83m13.79-4l-5.74 9.94\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:arrow-left\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"m12 19l-7-7l7-7m7 7H5\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:arrow-up-from-dot\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"m5 9l7-7l7 7m-7 7V2\\\"/><circle cx=\\\"12\\\" cy=\\\"21\\\" r=\\\"1\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:blend\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><circle cx=\\\"9\\\" cy=\\\"9\\\" r=\\\"7\\\"/><circle cx=\\\"15\\\" cy=\\\"15\\\" r=\\\"7\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:case-upper\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M15 11h4.5a1 1 0 0 1 0 5h-4a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h3a1 1 0 0 1 0 5M2 16l4.039-9.69a.5.5 0 0 1 .923 0L11 16m-7.696-3h6.392\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:circle\": {\n \"body\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:circle-dashed\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M10.1 2.182a10 10 0 0 1 3.8 0m0 19.636a10 10 0 0 1-3.8 0m7.509-18.097a10 10 0 0 1 2.69 2.7M2.182 13.9a10 10 0 0 1 0-3.8m18.097 7.509a10 10 0 0 1-2.7 2.69M21.818 10.1a10 10 0 0 1 0 3.8M3.721 6.391a10 10 0 0 1 2.7-2.69m-.03 16.578a10 10 0 0 1-2.69-2.7\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:cloud\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:copy\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><rect width=\\\"14\\\" height=\\\"14\\\" x=\\\"8\\\" y=\\\"8\\\" rx=\\\"2\\\" ry=\\\"2\\\"/><path d=\\\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:credit-card\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><rect width=\\\"20\\\" height=\\\"14\\\" x=\\\"2\\\" y=\\\"5\\\" rx=\\\"2\\\"/><path d=\\\"M2 10h20\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:crop\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M6 2v14a2 2 0 0 0 2 2h14\\\"/><path d=\\\"M18 22V8a2 2 0 0 0-2-2H2\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:ellipsis-vertical\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"1\\\"/><circle cx=\\\"12\\\" cy=\\\"5\\\" r=\\\"1\\\"/><circle cx=\\\"12\\\" cy=\\\"19\\\" r=\\\"1\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:flag\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c3 0 5 2 7.333 2q2 0 3.067-.8A1 1 0 0 1 20 4v10a1 1 0 0 1-.4.8A6 6 0 0 1 16 16c-3 0-5-2-8-2a6 6 0 0 0-4 1.528\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:flip-horizontal-2\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"m3 7l5 5l-5 5zm18 0l-5 5l5 5zm-9 13v2m0-8v2m0-8v2m0-8v2\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:flip-vertical-2\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"m17 3l-5 5l-5-5zm0 18l-5-5l-5 5zM4 12H2m8 0H8m8 0h-2m8 0h-2\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:folder-open\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"m6 14l1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:folder-plus\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M12 10v6m-3-3h6m5 7a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:grid-2x2\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M12 3v18m-9-9h18\\\"/><rect width=\\\"18\\\" height=\\\"18\\\" x=\\\"3\\\" y=\\\"3\\\" rx=\\\"2\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:grid-3x3\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><rect width=\\\"18\\\" height=\\\"18\\\" x=\\\"3\\\" y=\\\"3\\\" rx=\\\"2\\\"/><path d=\\\"M3 9h18M3 15h18M9 3v18m6-18v18\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:grip-vertical\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><circle cx=\\\"9\\\" cy=\\\"12\\\" r=\\\"1\\\"/><circle cx=\\\"9\\\" cy=\\\"5\\\" r=\\\"1\\\"/><circle cx=\\\"9\\\" cy=\\\"19\\\" r=\\\"1\\\"/><circle cx=\\\"15\\\" cy=\\\"12\\\" r=\\\"1\\\"/><circle cx=\\\"15\\\" cy=\\\"5\\\" r=\\\"1\\\"/><circle cx=\\\"15\\\" cy=\\\"19\\\" r=\\\"1\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:hexagon\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:image\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><rect width=\\\"18\\\" height=\\\"18\\\" x=\\\"3\\\" y=\\\"3\\\" rx=\\\"2\\\" ry=\\\"2\\\"/><circle cx=\\\"9\\\" cy=\\\"9\\\" r=\\\"2\\\"/><path d=\\\"m21 15l-3.086-3.086a2 2 0 0 0-2.828 0L6 21\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:italic\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M19 4h-9m4 16H5M15 4L9 20\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:layout-grid\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><rect width=\\\"7\\\" height=\\\"7\\\" x=\\\"3\\\" y=\\\"3\\\" rx=\\\"1\\\"/><rect width=\\\"7\\\" height=\\\"7\\\" x=\\\"14\\\" y=\\\"3\\\" rx=\\\"1\\\"/><rect width=\\\"7\\\" height=\\\"7\\\" x=\\\"14\\\" y=\\\"14\\\" rx=\\\"1\\\"/><rect width=\\\"7\\\" height=\\\"7\\\" x=\\\"3\\\" y=\\\"14\\\" rx=\\\"1\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:lightbulb\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M15 14c.2-1 .7-1.7 1.5-2.5c1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5c.7.7 1.3 1.5 1.5 2.5m0 4h6m-5 4h4\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:loader-circle\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M21 12a9 9 0 1 1-6.219-8.56\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:minus\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M5 12h14\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:moon\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:move-vertical\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M12 2v20m-4-4l4 4l4-4M8 6l4-4l4 4\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:paint-bucket\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M11 7L6 2m12.992 10H2.041m19.104 6.38A3.34 3.34 0 0 1 20 16.5a3.3 3.3 0 0 1-1.145 1.88c-.575.46-.855 1.02-.855 1.595A2 2 0 0 0 20 22a2 2 0 0 0 2-2.025c0-.58-.285-1.13-.855-1.595M8.5 4.5l2.148-2.148a1.205 1.205 0 0 1 1.704 0l7.296 7.296a1.205 1.205 0 0 1 0 1.704l-7.592 7.592a3.615 3.615 0 0 1-5.112 0l-3.888-3.888a3.615 3.615 0 0 1 0-5.112L5.67 7.33\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:palette\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M12 22a1 1 0 0 1 0-20a10 9 0 0 1 10 9a5 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\\\"/><circle cx=\\\"13.5\\\" cy=\\\"6.5\\\" r=\\\".5\\\" fill=\\\"currentColor\\\"/><circle cx=\\\"17.5\\\" cy=\\\"10.5\\\" r=\\\".5\\\" fill=\\\"currentColor\\\"/><circle cx=\\\"6.5\\\" cy=\\\"12.5\\\" r=\\\".5\\\" fill=\\\"currentColor\\\"/><circle cx=\\\"8.5\\\" cy=\\\"7.5\\\" r=\\\".5\\\" fill=\\\"currentColor\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:pen-line\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M13 21h8m.174-14.188a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:pen-tool\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\\\"/><path d=\\\"m18 13l-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18M2.3 2.3l7.286 7.286\\\"/><circle cx=\\\"11\\\" cy=\\\"11\\\" r=\\\"2\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:redo-2\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"m15 14l5-5l-5-5\\\"/><path d=\\\"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:rotate-ccw\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M3 12a9 9 0 1 0 9-9a9.75 9.75 0 0 0-6.74 2.74L3 8\\\"/><path d=\\\"M3 3v5h5\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:rotate-cw\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\\\"/><path d=\\\"M21 3v5h-5\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:scissors\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><circle cx=\\\"6\\\" cy=\\\"6\\\" r=\\\"3\\\"/><path d=\\\"M8.12 8.12L12 12m8-8L8.12 15.88\\\"/><circle cx=\\\"6\\\" cy=\\\"18\\\" r=\\\"3\\\"/><path d=\\\"M14.8 14.8L20 20\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:settings\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M9.671 4.136a2.34 2.34 0 0 1 4.659 0a2.34 2.34 0 0 0 3.319 1.915a2.34 2.34 0 0 1 2.33 4.033a2.34 2.34 0 0 0 0 3.831a2.34 2.34 0 0 1-2.33 4.033a2.34 2.34 0 0 0-3.319 1.915a2.34 2.34 0 0 1-4.659 0a2.34 2.34 0 0 0-3.32-1.915a2.34 2.34 0 0 1-2.33-4.033a2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915\\\"/><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"3\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:shapes\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><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\\\"/><rect width=\\\"7\\\" height=\\\"7\\\" x=\\\"3\\\" y=\\\"14\\\" rx=\\\"1\\\"/><circle cx=\\\"17.5\\\" cy=\\\"17.5\\\" r=\\\"3.5\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:sparkles\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594zM20 2v4m2-2h-4\\\"/><circle cx=\\\"4\\\" cy=\\\"20\\\" r=\\\"2\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:square\": {\n \"body\": \"<rect width=\\\"18\\\" height=\\\"18\\\" x=\\\"3\\\" y=\\\"3\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" rx=\\\"2\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:square-round-corner\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M21 11a8 8 0 0 0-8-8m8 12v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:stamp\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M14 13V8.5C14 7 15 7 15 5a3 3 0 0 0-6 0c0 2 1 2 1 3.5V13m10 2.5a2.5 2.5 0 0 0-2.5-2.5h-11A2.5 2.5 0 0 0 4 15.5V17a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1zM5 22h14\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:star\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.12 2.12 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.12 2.12 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.12 2.12 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.12 2.12 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.12 2.12 0 0 0 1.597-1.16z\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:sun\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"4\\\"/><path d=\\\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:text-cursor\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M17 22h-1a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1M7 22h1a4 4 0 0 0 4-4M7 2h1a4 4 0 0 1 4 4\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:trash\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:trending-up\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M16 7h6v6\\\"/><path d=\\\"m22 7l-8.5 8.5l-5-5L2 17\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:triangle\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M13.73 4a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:type\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M12 4v16M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2M9 20h6\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:undo-2\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M9 14L4 9l5-5\\\"/><path d=\\\"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:venetian-mask\": {\n \"body\": \"<g fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\"><path d=\\\"M18 11c-1.5 0-2.5.5-3 2\\\"/><path d=\\\"M4 6a2 2 0 0 0-2 2v4a5 5 0 0 0 5 5a8 8 0 0 1 5 2a8 8 0 0 1 5-2a5 5 0 0 0 5-5V8a2 2 0 0 0-2-2h-3a8 8 0 0 0-5 2a8 8 0 0 0-5-2z\\\"/><path d=\\\"M6 11c1.5 0 2.5.5 3 2\\\"/></g>\",\n \"width\": 24,\n \"height\": 24\n },\n \"lucide:waves\": {\n \"body\": \"<path fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"2\\\" d=\\\"M2 6c.6.5 1.2 1 2.5 1C7 7 7 5 9.5 5c2.6 0 2.4 2 5 2c2.5 0 2.5-2 5-2c1.3 0 1.9.5 2.5 1M2 12c.6.5 1.2 1 2.5 1c2.5 0 2.5-2 5-2c2.6 0 2.4 2 5 2c2.5 0 2.5-2 5-2c1.3 0 1.9.5 2.5 1M2 18c.6.5 1.2 1 2.5 1c2.5 0 2.5-2 5-2c2.6 0 2.4 2 5 2c2.5 0 2.5-2 5-2c1.3 0 1.9.5 2.5 1\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"material-symbols:award-star-outline\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M9.075 16.25L12 14.475l2.925 1.775l-.775-3.325l2.6-2.25l-3.425-.275L12 7.25l-1.325 3.15l-3.425.275l2.6 2.25zM12 23.3L8.65 20H4v-4.65L.7 12L4 8.65V4h4.65L12 .7L15.35 4H20v4.65L23.3 12L20 15.35V20h-4.65zm0-2.8l2.5-2.5H18v-3.5l2.5-2.5L18 9.5V6h-3.5L12 3.5L9.5 6H6v3.5L3.5 12L6 14.5V18h3.5zm0-8.5\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"mdi:cube-outline\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M21 16.5c0 .38-.21.71-.53.88l-7.9 4.44c-.16.12-.36.18-.57.18s-.41-.06-.57-.18l-7.9-4.44A.99.99 0 0 1 3 16.5v-9c0-.38.21-.71.53-.88l7.9-4.44c.16-.12.36-.18.57-.18s.41.06.57.18l7.9 4.44c.32.17.53.5.53.88zM12 4.15L6.04 7.5L12 10.85l5.96-3.35zM5 15.91l6 3.38v-6.71L5 9.21zm14 0v-6.7l-6 3.37v6.71z\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"mdi:format-color-fill\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M19 11.5s-2 2.17-2 3.5a2 2 0 0 0 2 2a2 2 0 0 0 2-2c0-1.33-2-3.5-2-3.5M5.21 10L10 5.21L14.79 10m1.77-1.06L7.62 0L6.21 1.41l2.38 2.38l-5.15 5.15c-.59.56-.59 1.53 0 2.12l5.5 5.5c.29.29.68.44 1.06.44s.77-.15 1.06-.44l5.5-5.5c.59-.59.59-1.56 0-2.12\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"mdi:image-remove\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M13.3 21H5c-1.1 0-2-.9-2-2V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2v8.3c-.6-.2-1.3-.3-2-.3c-1.1 0-2.2.3-3.1.9L14.5 12L11 16.5l-2.5-3L5 18h8.1c-.1.3-.1.7-.1 1c0 .7.1 1.4.3 2m7.1-2l2.1 2.1l-1.4 1.4l-2.1-2.1l-2.1 2.1l-1.4-1.4l2.1-2.1l-2.1-2.1l1.4-1.4l2.1 2.1l2.1-2.1l1.4 1.4z\\\"/>\",\n \"width\": 24,\n \"height\": 24\n },\n \"ph:monitor-fill\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M232 64v112a24 24 0 0 1-24 24H48a24 24 0 0 1-24-24V64a24 24 0 0 1 24-24h160a24 24 0 0 1 24 24m-72 152H96a8 8 0 0 0 0 16h64a8 8 0 0 0 0-16\\\"/>\",\n \"width\": 256,\n \"height\": 256\n },\n \"radix-icons:font-size\": {\n \"body\": \"<path fill=\\\"currentColor\\\" d=\\\"M2.5 2.1a.4.4 0 0 1 .283.117l2 2l.05.064a.4.4 0 0 1-.05.503a.4.4 0 0 1-.503.05l-.063-.05L2.9 3.467v8.067l1.317-1.317a.4.4 0 0 1 .566.566l-2 2a.4.4 0 0 1-.566 0l-2-2l-.051-.063a.4.4 0 0 1 .554-.554l.063.051l1.316 1.316V3.467L.783 4.784a.401.401 0 0 1-.566-.567l2-2l.061-.05A.4.4 0 0 1 2.5 2.1m5.47 9.64a.501.501 0 0 1-.94-.34zm2.53-8.99a.5.5 0 0 1 .47.33l3 8.32a.5.5 0 0 1-.94.34l-.983-2.724H8.953l-.982 2.724l-.471-.17l-.47-.17l3-8.32l.031-.07a.5.5 0 0 1 .439-.26M9.259 8.166h2.482L10.5 4.725z\\\"/>\",\n \"width\": 15,\n \"height\": 15\n }\n};\n","/**\n * Icon Registry - Registers only the icons actually used in the canvas package\n *\n * This ensures icons work when the canvas package is bundled and used in\n * consuming applications (like Next.js) where CDN icon loading may fail.\n *\n * Icons are auto-generated by scripts/generate-icons.ts which scans the source\n * files and extracts only the SVG data for icons that are actually used.\n * This dramatically reduces bundle size compared to bundling entire icon sets.\n *\n * To regenerate after adding new icons:\n * pnpm generate:icons\n *\n * ## SSR safety (load-bearing)\n *\n * `@iconify/react` is a *browser* dependency: importing it can evaluate\n * browser-only globals (e.g. `window`) at module-evaluation time. Because the\n * package barrels (`api/stable.ts`, `api/advanced.ts`, `components/embed`) call\n * {@link ensureIconsRegistered} as a top-level side effect, a *static*\n * `import '@iconify/react'` in this file would run iconify the instant any\n * consumer `import`s `@snowcone-app/canvas` — crashing Next.js App Router /\n * any SSR/RSC context with `ReferenceError: window is not defined` even for a\n * pure server-only import of `serializeStateForServer`.\n *\n * To keep the barrel side-effect-free w.r.t. browser globals, iconify is loaded\n * via a *dynamic* `import()` that only runs in a browser. On the server\n * {@link ensureIconsRegistered} is a no-op; in the browser it registers icons\n * asynchronously on first call. The `Icon` component reads icon data lazily, so\n * registration completing on the first client microtask is fine.\n *\n * @see https://iconify.design/docs/icons/json.html\n */\n\nimport { canvasIcons } from './icon-data.js';\n\n/** True only in a real browser/DOM context. */\nconst isBrowser = typeof window !== 'undefined';\n\n/**\n * Registers all icons used in the canvas package.\n *\n * Loads `@iconify/react` via dynamic `import()` so the module is never touched\n * during server-side module evaluation. No-op (resolves immediately) outside a\n * browser.\n *\n * This registers only the ~100-150 icons actually used, rather than ~20,000+\n * icons from the full icon sets.\n */\nexport async function registerCanvasIcons(): Promise<void> {\n if (!isBrowser) return;\n const { addIcon } = await import('@iconify/react');\n for (const [name, data] of Object.entries(canvasIcons)) {\n addIcon(name, data);\n }\n}\n\n// Track registration so we only kick it off once.\nlet registrationStarted = false;\n\n/**\n * Ensures icons are registered exactly once.\n *\n * Safe to call at module-evaluation time and on the server: on the server it\n * does nothing; in the browser it kicks off async registration on the first\n * call. Subsequent calls are no-ops.\n */\nexport function ensureIconsRegistered(): void {\n if (registrationStarted || !isBrowser) return;\n registrationStarted = true;\n // Fire-and-forget: registration runs on the first client microtask. Swallow\n // failures so a transient iconify load error never takes down the editor.\n void registerCanvasIcons().catch(() => {\n // Allow a retry on a later call if the dynamic import failed.\n registrationStarted = false;\n });\n}\n","/**\n * ElementPreviewRenderer - Generates thumbnail previews for layer panel\n * Creates small canvas thumbnails of elements for display in the layers panel\n * Uses the element's actual renderContent method for accurate previews\n */\n\n// Element painting goes through the paint registry (P1 element/renderer\n// split); importing the painters here guarantees they are installed before\n// any element.render() this module drives.\nimport '../rendering/element-painters.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\nimport { createLogger } from './logger';\n\nconst logger = createLogger('ElementPreviewRenderer');\n\ntype LayerElement = TextElement | ImageElement | GroupElement | ShapeElement | PathElement;\n\nexport interface PreviewOptions {\n width?: number;\n height?: number;\n padding?: number;\n backgroundColor?: string;\n}\n\nconst DEFAULT_OPTIONS: Required<PreviewOptions> = {\n width: 40,\n height: 40,\n padding: 4,\n backgroundColor: 'transparent',\n};\n\n/**\n * Generate a thumbnail preview for an element\n * Returns a data URL that can be used as an image src\n * Uses the element's actual renderContent method for accurate representation\n */\nexport function generateElementPreview(\n element: LayerElement,\n options: PreviewOptions = {}\n): string {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n // Create a small canvas for the thumbnail\n const canvas = document.createElement('canvas');\n canvas.width = opts.width;\n canvas.height = opts.height;\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n return '';\n }\n\n // Clear with background\n if (opts.backgroundColor !== 'transparent') {\n ctx.fillStyle = opts.backgroundColor;\n ctx.fillRect(0, 0, opts.width, opts.height);\n }\n\n // Save context state\n ctx.save();\n\n try {\n // Use actual element rendering for accurate preview\n if (element instanceof GroupElement) {\n renderGroupPreview(ctx, element, opts);\n } else {\n renderElementUsingActualRenderer(ctx, element, opts);\n }\n } catch (error) {\n logger.warn('Failed to generate preview:', error);\n }\n\n // Restore context state\n ctx.restore();\n\n // Return data URL\n return canvas.toDataURL('image/png');\n}\n\n/**\n * Render element using its actual render method\n * This ensures the preview matches exactly what's on the canvas\n */\nfunction renderElementUsingActualRenderer(\n ctx: CanvasRenderingContext2D,\n element: LayerElement,\n opts: Required<PreviewOptions>\n): void {\n // Get the element's bounding box\n const bbox = element.getBoundingBox?.() || { x: 0, y: 0, width: 100, height: 100 };\n const elementWidth = bbox.width;\n const elementHeight = bbox.height;\n\n if (elementWidth === 0 || elementHeight === 0) {\n // Fallback for empty elements\n renderFallbackPreview(ctx, element, opts);\n return;\n }\n\n // Calculate scale to fit in preview with padding\n const availableWidth = opts.width - opts.padding * 2;\n const availableHeight = opts.height - opts.padding * 2;\n const scale = Math.min(\n availableWidth / elementWidth,\n availableHeight / elementHeight,\n 1 // Don't scale up, only down\n );\n\n // Calculate centered position\n const scaledWidth = elementWidth * scale;\n const scaledHeight = elementHeight * scale;\n const offsetX = opts.padding + (availableWidth - scaledWidth) / 2;\n const offsetY = opts.padding + (availableHeight - scaledHeight) / 2;\n\n // Apply transformations for preview\n ctx.save();\n ctx.translate(offsetX - bbox.x * scale, offsetY - bbox.y * scale);\n ctx.scale(scale, scale);\n\n // Render the element using its actual render method\n // Elements have render(ctx, isSelected, isHovered) method\n if (typeof element.render === 'function') {\n element.render(ctx, false, false);\n } else {\n // Fallback if no render method\n renderFallbackPreview(ctx, element, opts);\n }\n\n ctx.restore();\n}\n\n/**\n * Fallback preview renderer for elements without render method\n */\nfunction renderFallbackPreview(\n ctx: CanvasRenderingContext2D,\n element: LayerElement,\n opts: Required<PreviewOptions>\n): void {\n // Draw placeholder\n ctx.fillStyle = '#888888';\n ctx.font = '10px Arial';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n\n const label = element.transformType || 'Element';\n ctx.fillText(label, opts.width / 2, opts.height / 2);\n}\n\n/**\n * Render group element preview\n */\nfunction renderGroupPreview(\n ctx: CanvasRenderingContext2D,\n element: GroupElement,\n opts: Required<PreviewOptions>\n): void {\n // Draw a simple folder/group icon\n const availableWidth = opts.width - opts.padding * 2;\n const availableHeight = opts.height - opts.padding * 2;\n const x = opts.padding;\n const y = opts.padding;\n\n ctx.fillStyle = '#888888';\n ctx.strokeStyle = '#666666';\n ctx.lineWidth = 1;\n\n // Draw folder shape\n const folderHeight = availableHeight * 0.7;\n const folderY = y + availableHeight * 0.3;\n const tabWidth = availableWidth * 0.4;\n const tabHeight = availableHeight * 0.2;\n\n // Draw folder body\n ctx.fillRect(x, folderY, availableWidth, folderHeight);\n\n // Draw folder tab\n ctx.fillRect(x, folderY - tabHeight, tabWidth, tabHeight);\n\n // Optional: Draw children count if group has children\n if (element.children && element.children.length > 0) {\n ctx.fillStyle = '#FFFFFF';\n ctx.font = 'bold 10px Arial';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(\n element.children.length.toString(),\n x + availableWidth / 2,\n folderY + folderHeight / 2\n );\n }\n}\n","/**\n * useLayers - Hook for accessing layer data with hierarchy and operations\n * Provides layer tree with preview images for custom layer panels\n */\n\nimport { useMemo, useCallback, useRef, useState, useEffect } from 'react';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { generateElementPreview } from '../utils/ElementPreviewRenderer.js';\nimport { createLogger } from '../utils/logger.js';\nimport type { EditorElement } from '../contexts/EditorContext.js';\nimport type { TransformType } from '../types/index.js';\nimport type { ArtboardManager } from '../core/ArtboardManager.js';\n\nconst log = createLogger('Layers');\n\n/** Debounce window for autoRefreshPreviews so rapid edits coalesce. */\nconst AUTO_REFRESH_PREVIEWS_DEBOUNCE_MS = 150;\n\nexport interface LayerInfo {\n id: string;\n name: string;\n type: TransformType;\n visible: boolean;\n locked: boolean;\n isSelected: boolean;\n isGroup: boolean;\n depth: number;\n parentId: string | null;\n children?: LayerInfo[];\n\n // Preview image generation (implemented in Sprint 2)\n previewUrl: string | null; // Data URL for thumbnail\n refreshPreview: () => Promise<void>;\n}\n\nexport interface UseLayersOptions {\n artboardId?: string | null; // Filter by artboard (default: active)\n includeHidden?: boolean; // Include hidden layers (default: true)\n previewSize?: number; // Preview thumbnail size (default: 64)\n previewBackgroundColor?: string; // Preview background color (default: the artboard's backgroundColor, falling back to transparent)\n autoRefreshPreviews?: boolean; // Auto-regenerate previews when elements change (default: false)\n}\n\nexport interface UseLayersReturn {\n // Hierarchical layer tree\n layers: LayerInfo[];\n flatLayers: LayerInfo[]; // Flat list for simple rendering\n\n // Selection\n selectedLayers: LayerInfo[];\n selectLayer: (id: string, addToSelection?: boolean) => void;\n selectMultipleLayers: (ids: string[]) => void;\n clearSelection: () => void;\n\n // Operations\n toggleVisibility: (id: string) => void;\n toggleLock: (id: string) => void;\n renameLayer: (id: string, name: string) => void;\n deleteLayer: (id: string) => void;\n duplicateLayer: (id: string) => void;\n reorderLayers: (fromIndex: number, toIndex: number) => void;\n reorderById: (draggedId: string, targetId: string, position: 'before' | 'after') => void;\n reorderWithinGroup: (draggedId: string, targetId: string, position: 'before' | 'after', groupId: string) => void;\n moveLayerForward: (id: string) => void;\n moveLayerBackward: (id: string) => void;\n groupLayers: (ids: string[]) => void;\n ungroupLayer: (id: string) => void;\n addToGroup: (elementId: string, groupId: string) => void;\n removeFromGroup: (elementId: string, targetId?: string, position?: 'before' | 'after') => void;\n createEmptyGroup: () => void;\n findElementById: (id: string) => EditorElement | null;\n findParentGroup: (id: string) => GroupElement | null;\n\n // Preview management (implemented in Sprint 2)\n generateAllPreviews: (size?: number) => Promise<void>;\n clearPreviewCache: () => void;\n\n // Artboard filtering\n artboardId: string | null; // Current artboard\n artboardManager: ArtboardManager; // Access to artboard manager for advanced use cases\n layerCount: number;\n}\n\n/**\n * Generate preview image for an element (async wrapper for shared utility)\n * Uses the shared ElementPreviewRenderer for consistency\n */\nasync function generateElementPreviewAsync(\n element: EditorElement,\n size: number = 64,\n backgroundColor: string = 'transparent'\n): Promise<string | null> {\n try {\n // Use shared preview renderer for consistency with main LayersPanel\n const preview = generateElementPreview(element, {\n width: size,\n height: size,\n padding: 8,\n backgroundColor,\n });\n return preview || null;\n } catch (error) {\n log.error('Failed to generate preview:', error);\n return null;\n }\n}\n\n/**\n * Build hierarchical layer tree from flat element list\n */\nfunction buildLayerTree(\n elements: EditorElement[],\n selectedId: string | null,\n multiSelection: string[],\n previewCache: Map<string, string | null>,\n generatePreview: (id: string) => Promise<void>,\n depth: number = 0,\n parentId: string | null = null\n): LayerInfo[] {\n // Find elements at this level.\n // At depth > 0, `elements` is already the direct children array from\n // GroupElement.children — no filtering needed.\n // At depth 0 (top level), filter to elements that aren't nested in a group.\n const layersAtLevel = depth > 0 ? elements : elements.filter(el => {\n const elParentId = (el as unknown as Record<string, unknown>).parentId as string | null ?? null;\n if (el instanceof GroupElement) {\n return elParentId === null;\n }\n return elParentId === null;\n });\n\n return layersAtLevel.map(element => {\n const isGroup = element instanceof GroupElement;\n const isSelected = selectedId === element.id || multiSelection.includes(element.id);\n\n const layerInfo: LayerInfo = {\n id: element.id,\n name: element.name || `Layer ${element.id.slice(0, 8)}`,\n type: element.transformType,\n visible: element.visible ?? true,\n locked: element.locked ?? false,\n isSelected,\n isGroup,\n depth,\n parentId,\n previewUrl: previewCache.get(element.id) || null,\n refreshPreview: async () => {\n await generatePreview(element.id);\n },\n };\n\n // Recursively build children for groups\n if (isGroup && element instanceof GroupElement) {\n layerInfo.children = buildLayerTree(\n element.children,\n selectedId,\n multiSelection,\n previewCache,\n generatePreview,\n depth + 1,\n element.id\n );\n }\n\n return layerInfo;\n });\n}\n\n/**\n * Flatten hierarchical layer tree\n */\nfunction flattenLayerTree(layers: LayerInfo[]): LayerInfo[] {\n const result: LayerInfo[] = [];\n for (const layer of layers) {\n result.push(layer);\n if (layer.children) {\n result.push(...flattenLayerTree(layer.children));\n }\n }\n return result;\n}\n\n/**\n * Hook for accessing layer data and operations\n * Must be used within EditorProvider\n *\n * @example\n * ```tsx\n * function CustomLayersPanel() {\n * const { layers, selectLayer, toggleVisibility, deleteLayer } = useLayers({\n * previewSize: 80,\n * autoRefreshPreviews: true\n * });\n *\n * return (\n * <div className=\"layers-panel\">\n * {layers.map(layer => (\n * <div\n * key={layer.id}\n * className={layer.isSelected ? 'selected' : ''}\n * style={{ paddingLeft: layer.depth * 20 }}\n * >\n * {layer.previewUrl && (\n * <img src={layer.previewUrl} alt={layer.name} width={40} />\n * )}\n * <span onClick={() => selectLayer(layer.id)}>{layer.name}</span>\n * <button onClick={() => toggleVisibility(layer.id)}>\n * {layer.visible ? '👁' : '🚫'}\n * </button>\n * <button onClick={() => deleteLayer(layer.id)}>🗑</button>\n * </div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useLayers(options: UseLayersOptions = {}): UseLayersReturn {\n const {\n artboardId: filterArtboardId,\n includeHidden = true,\n previewSize = 64,\n previewBackgroundColor,\n autoRefreshPreviews = false,\n } = options;\n\n const {\n elements,\n selectedId,\n multiSelection,\n artboardManager,\n handleSelectionChange,\n handleElementUpdate,\n setMultiSelection,\n executeAddElement,\n executeRemoveElement,\n executeReorderElement,\n } = useEditor();\n\n // Preview cache and version for triggering re-renders\n const previewCache = useRef<Map<string, string | null>>(new Map());\n const [previewVersion, setPreviewVersion] = useState(0);\n\n // Determine which artboard to filter by\n const activeArtboardId = artboardManager.getActiveArtboardId();\n const effectiveArtboardId = filterArtboardId !== undefined ? filterArtboardId : activeArtboardId;\n\n // Resolve the preview background. An explicit option always wins (including\n // explicit 'transparent'); otherwise default to the artboard's own\n // backgroundColor so dark layers stay visible as thumbnails on dark UIs.\n const effectiveArtboard = effectiveArtboardId\n ? artboardManager.getArtboard?.(effectiveArtboardId)\n : null;\n const resolvedPreviewBackgroundColor =\n previewBackgroundColor ?? effectiveArtboard?.backgroundColor ?? 'transparent';\n\n // Generate preview for a specific element\n const generatePreview = useCallback(async (elementId: string) => {\n const element = elements.find(el => el.id === elementId);\n if (!element) return;\n\n const preview = await generateElementPreviewAsync(element, previewSize, resolvedPreviewBackgroundColor);\n previewCache.current.set(elementId, preview);\n // Trigger re-render by updating version\n setPreviewVersion(v => v + 1);\n }, [elements, previewSize, resolvedPreviewBackgroundColor]);\n\n // Filter elements by artboard\n const filteredElements = useMemo(() => {\n let filtered = elements;\n\n // Filter by artboard using ArtboardManager\n if (effectiveArtboardId) {\n const elementIds = artboardManager.getElementsOnArtboard(effectiveArtboardId);\n filtered = filtered.filter(el => elementIds.includes(el.id));\n }\n\n // Filter hidden elements if needed\n if (!includeHidden) {\n filtered = filtered.filter(el => el.visible !== false);\n }\n\n return filtered;\n }, [elements, effectiveArtboardId, includeHidden, artboardManager]);\n\n // Build hierarchical layer tree\n const layers = useMemo(() => {\n return buildLayerTree(\n filteredElements,\n selectedId,\n multiSelection,\n previewCache.current,\n generatePreview\n );\n }, [filteredElements, selectedId, multiSelection, generatePreview, previewVersion]);\n\n // Flatten layer tree\n const flatLayers = useMemo(() => {\n return flattenLayerTree(layers);\n }, [layers]);\n\n // Get selected layers\n const selectedLayers = useMemo(() => {\n return flatLayers.filter(layer => layer.isSelected);\n }, [flatLayers]);\n\n // Select layer\n const selectLayer = useCallback((id: string, addToSelection: boolean = false) => {\n if (addToSelection) {\n // Add to multi-selection\n if (multiSelection.includes(id)) {\n // Deselect if already selected\n setMultiSelection(multiSelection.filter(sid => sid !== id));\n } else {\n // Add to selection\n setMultiSelection([...multiSelection, id]);\n }\n } else {\n // Single selection\n handleSelectionChange(id);\n }\n }, [multiSelection, setMultiSelection, handleSelectionChange]);\n\n // Select multiple layers\n const selectMultipleLayers = useCallback((ids: string[]) => {\n setMultiSelection(ids);\n }, [setMultiSelection]);\n\n // Clear selection\n const clearSelection = useCallback(() => {\n handleSelectionChange(null);\n setMultiSelection([]);\n }, [handleSelectionChange, setMultiSelection]);\n\n // Toggle visibility\n const toggleVisibility = useCallback((id: string) => {\n const element = elements.find(el => el.id === id);\n if (!element) return;\n\n const updated = element.clone();\n updated.visible = !(element.visible ?? true);\n handleElementUpdate(updated);\n }, [elements, handleElementUpdate]);\n\n // Toggle lock\n const toggleLock = useCallback((id: string) => {\n const element = elements.find(el => el.id === id);\n if (!element) return;\n\n const updated = element.clone();\n updated.locked = !(element.locked ?? false);\n handleElementUpdate(updated);\n }, [elements, handleElementUpdate]);\n\n // Rename layer\n const renameLayer = useCallback((id: string, name: string) => {\n const element = elements.find(el => el.id === id);\n if (!element) return;\n\n const updated = element.clone();\n updated.name = name;\n handleElementUpdate(updated);\n }, [elements, handleElementUpdate]);\n\n // Delete layer\n const deleteLayer = useCallback((id: string) => {\n const element = elements.find(el => el.id === id);\n if (!element) {\n log.warn(`Element ${id} not found for deletion`);\n return;\n }\n\n executeRemoveElement(element);\n\n // Clear selection if deleted element was selected\n if (selectedId === id || multiSelection.includes(id)) {\n handleSelectionChange(null);\n setMultiSelection(multiSelection.filter(sid => sid !== id));\n }\n }, [elements, executeRemoveElement, selectedId, multiSelection, handleSelectionChange, setMultiSelection]);\n\n // Duplicate layer\n const duplicateLayer = useCallback((id: string) => {\n const element = elements.find(el => el.id === id);\n if (!element) {\n log.warn(`Element ${id} not found for duplication`);\n return;\n }\n\n // Clone the element and reconstruct with a new ID\n const cloned = element.clone();\n const json = cloned.toJSON();\n // Remove old ID so constructor generates a new one\n delete (json as Record<string, unknown>).id;\n // Reconstruct to get a new ID\n const Constructor = element.constructor as new (config: Record<string, unknown>) => EditorElement;\n const clonedWithNewId = new Constructor(json as Record<string, unknown>);\n\n // Offset position slightly so it's visible\n clonedWithNewId.x = element.x + 20;\n clonedWithNewId.y = element.y + 20;\n\n // Get artboard for this element\n const artboardId = artboardManager.getArtboardIdForElement(id);\n if (!artboardId) {\n log.warn(`Element ${id} not associated with any artboard`);\n return;\n }\n\n // Add cloned element after the original\n executeAddElement(clonedWithNewId, artboardId, id);\n\n // Select the duplicated element\n handleSelectionChange(clonedWithNewId.id);\n }, [elements, artboardManager, executeAddElement, handleSelectionChange]);\n\n // Reorder layers\n const reorderLayers = useCallback((fromIndex: number, toIndex: number) => {\n if (fromIndex === toIndex) return;\n if (fromIndex < 0 || fromIndex >= filteredElements.length) {\n log.warn(`Invalid fromIndex: ${fromIndex}`);\n return;\n }\n if (toIndex < 0 || toIndex >= filteredElements.length) {\n log.warn(`Invalid toIndex: ${toIndex}`);\n return;\n }\n\n const draggedElement = filteredElements[fromIndex];\n const targetElement = filteredElements[toIndex];\n\n // Determine position based on direction\n const position = fromIndex < toIndex ? 'after' : 'before';\n\n executeReorderElement(draggedElement.id, targetElement.id, position);\n }, [filteredElements, executeReorderElement]);\n\n // Move layer one position forward (toward front/top of stack)\n // In the element array, higher index = rendered on top = \"forward\"\n const moveLayerForward = useCallback((id: string) => {\n const index = flatLayers.findIndex(l => l.id === id);\n if (index < 0) {\n log.warn(`Layer ${id} not found`);\n return;\n }\n if (index >= flatLayers.length - 1) {\n // Already at the front (last in array = top of stack)\n return;\n }\n reorderLayers(index, index + 1);\n }, [flatLayers, reorderLayers]);\n\n // Move layer one position backward (toward back/bottom of stack)\n // In the element array, lower index = rendered first = \"backward\"\n const moveLayerBackward = useCallback((id: string) => {\n const index = flatLayers.findIndex(l => l.id === id);\n if (index < 0) {\n log.warn(`Layer ${id} not found`);\n return;\n }\n if (index <= 0) {\n // Already at the back (first in array = bottom of stack)\n return;\n }\n reorderLayers(index, index - 1);\n }, [flatLayers, reorderLayers]);\n\n // Group layers\n const groupLayers = useCallback((ids: string[]) => {\n if (ids.length < 2) {\n log.warn('Need at least 2 elements to create a group');\n return;\n }\n\n // Find all elements to group (filter out ShapeElements - they can't be grouped)\n const elementsToGroup = elements.filter(el =>\n ids.includes(el.id) && el.transformType !== 'shape'\n ) as (TextElement | ImageElement | GroupElement)[];\n\n if (elementsToGroup.length < 2) {\n log.warn('Need at least 2 groupable elements (shapes cannot be grouped)');\n return;\n }\n\n // All elements must be on the same artboard\n const artboardIds = elementsToGroup.map(el => artboardManager.getArtboardIdForElement(el.id));\n const uniqueArtboardIds = [...new Set(artboardIds)];\n if (uniqueArtboardIds.length !== 1 || !uniqueArtboardIds[0]) {\n log.warn('All elements must be on the same artboard to group');\n return;\n }\n const artboardId = uniqueArtboardIds[0];\n\n // Calculate group bounding box\n const bboxes = elementsToGroup.map(el => el.getBoundingBox()).filter(Boolean);\n if (bboxes.length === 0) {\n log.warn('Could not calculate bounding boxes for group');\n return;\n }\n\n const minX = Math.min(...bboxes.map(b => b!.x));\n const minY = Math.min(...bboxes.map(b => b!.y));\n\n // Create group element\n const group = new GroupElement({\n x: minX,\n y: minY,\n });\n\n // Set children manually (GroupElement constructor accepts instances but type is for configs)\n group.children = elementsToGroup.map(el => {\n const clone = el.clone() as TextElement | ImageElement | GroupElement;\n // Convert to relative positioning\n clone.x = el.x - minX;\n clone.y = el.y - minY;\n return clone;\n });\n\n // Remove individual elements and add group\n elementsToGroup.forEach(el => executeRemoveElement(el));\n executeAddElement(group, artboardId);\n\n // Select the new group\n handleSelectionChange(group.id);\n setMultiSelection([]);\n }, [elements, artboardManager, executeRemoveElement, executeAddElement, handleSelectionChange, setMultiSelection]);\n\n // Ungroup layer\n const ungroupLayer = useCallback((id: string) => {\n const element = elements.find(el => el.id === id);\n if (!element) {\n log.warn(`Element ${id} not found for ungrouping`);\n return;\n }\n\n if (!(element instanceof GroupElement)) {\n log.warn(`Element ${id} is not a group`);\n return;\n }\n\n const group = element as GroupElement;\n if (!group.children || group.children.length === 0) {\n log.warn(`Group ${id} has no children`);\n return;\n }\n\n // Get artboard for this group\n const artboardId = artboardManager.getArtboardIdForElement(id);\n if (!artboardId) {\n log.warn(`Group ${id} not associated with any artboard`);\n return;\n }\n\n // Extract children and convert to absolute positioning\n const extractedChildren = group.children.map(child => {\n const clone = child.clone();\n clone.x = child.x + group.x;\n clone.y = child.y + group.y;\n return clone;\n });\n\n // Remove group and add children\n executeRemoveElement(group);\n extractedChildren.forEach(child => executeAddElement(child, artboardId));\n\n // Select first extracted child\n if (extractedChildren.length > 0) {\n handleSelectionChange(extractedChildren[0].id);\n }\n setMultiSelection([]);\n }, [elements, artboardManager, executeRemoveElement, executeAddElement, handleSelectionChange, setMultiSelection]);\n\n // Generate all previews\n const generateAllPreviews = useCallback(async (size: number = previewSize) => {\n\n // Generate previews for all elements, including group children\n const generateForElements = async (elements: EditorElement[]) => {\n for (const element of elements) {\n const preview = await generateElementPreviewAsync(element, size, resolvedPreviewBackgroundColor);\n previewCache.current.set(element.id, preview);\n // Recurse into group children\n if (element instanceof GroupElement && element.children.length > 0) {\n await generateForElements(element.children as unknown as EditorElement[]);\n }\n }\n };\n await generateForElements(filteredElements);\n\n // Trigger re-render by updating version\n setPreviewVersion(v => v + 1);\n }, [previewSize, resolvedPreviewBackgroundColor, filteredElements]);\n\n // Auto-refresh previews: regenerate whenever the elements (or preview\n // settings) change. `generateAllPreviews` gets a new identity exactly when\n // `filteredElements`, `previewSize`, or the resolved background change, so\n // it doubles as the version key. Debounced so rapid edits (drag, typing)\n // coalesce into one regeneration.\n useEffect(() => {\n if (!autoRefreshPreviews) return;\n\n const timer = setTimeout(() => {\n void generateAllPreviews();\n }, AUTO_REFRESH_PREVIEWS_DEBOUNCE_MS);\n\n return () => clearTimeout(timer);\n }, [autoRefreshPreviews, generateAllPreviews]);\n\n // Clear preview cache\n const clearPreviewCache = useCallback(() => {\n previewCache.current.clear();\n }, []);\n\n // ── ID-based helpers for drag-drop ─────────────────────────────────────\n\n /** Reorder by element IDs (wraps executeReorderElement) */\n const reorderById = useCallback(\n (draggedId: string, targetId: string, position: 'before' | 'after') => {\n executeReorderElement(draggedId, targetId, position);\n },\n [executeReorderElement]\n );\n\n /** Reorder children within a group */\n const reorderWithinGroup = useCallback(\n (draggedId: string, targetId: string, position: 'before' | 'after', groupId: string) => {\n const group = elements.find(el => el.id === groupId);\n if (!group || !(group instanceof GroupElement)) {\n log.warn(`Group ${groupId} not found for reorder`);\n return;\n }\n\n const newGroup = group.clone() as GroupElement;\n const draggedIndex = newGroup.children.findIndex(c => c.id === draggedId);\n const targetIndex = newGroup.children.findIndex(c => c.id === targetId);\n if (draggedIndex === -1 || targetIndex === -1) {\n log.warn(`Children not found in group for reorder: ${draggedId}, ${targetId}`);\n return;\n }\n\n // Remove dragged child and re-insert at target position\n const [dragged] = newGroup.children.splice(draggedIndex, 1);\n const newTargetIndex = newGroup.children.findIndex(c => c.id === targetId);\n const insertIndex = position === 'before' ? newTargetIndex : newTargetIndex + 1;\n newGroup.children.splice(insertIndex, 0, dragged);\n\n handleElementUpdate(newGroup);\n },\n [elements, handleElementUpdate]\n );\n\n /** Find an element by ID */\n const findElementById = useCallback(\n (id: string): EditorElement | null => {\n // Check top-level elements\n for (const el of elements) {\n if (el.id === id) return el;\n // Check group children\n if (el instanceof GroupElement) {\n const child = el.children.find(c => c.id === id);\n if (child) return child as unknown as EditorElement;\n }\n }\n return null;\n },\n [elements]\n );\n\n /** Find the parent group of an element */\n const findParentGroup = useCallback(\n (id: string): GroupElement | null => {\n for (const el of elements) {\n if (el instanceof GroupElement) {\n if (el.children.some(child => child.id === id)) {\n return el;\n }\n }\n }\n return null;\n },\n [elements]\n );\n\n /** Add an element into a group */\n const addToGroup = useCallback(\n (elementId: string, groupId: string) => {\n const element = elements.find(el => el.id === elementId);\n const group = elements.find(el => el.id === groupId);\n if (!element || !group || !(group instanceof GroupElement)) {\n log.warn(`Cannot add ${elementId} to group ${groupId}`);\n return;\n }\n\n const artboardId = artboardManager.getArtboardIdForElement(elementId);\n if (!artboardId) return;\n\n // Clone group and add element as child.\n // Children in a GroupElement use WORLD coordinates (not relative to group center).\n // addChild() calls updateBoundsFromChildren() which recalculates group.x/y\n // to the center of the bounding box, but children positions stay unchanged.\n const newGroup = group.clone() as GroupElement;\n const childClone = element.clone() as TextElement | ImageElement | GroupElement;\n childClone.x = element.x;\n childClone.y = element.y;\n newGroup.addChild(childClone);\n\n // Remove original element and update group\n executeRemoveElement(element);\n handleElementUpdate(newGroup);\n },\n [elements, artboardManager, executeRemoveElement, handleElementUpdate]\n );\n\n /** Remove an element from its parent group (promote to top level).\n * Optional targetId + position specify where to insert in the top-level array.\n * Without them, inserts before the group (= below it visually). */\n const removeFromGroup = useCallback(\n (elementId: string, targetId?: string, position?: 'before' | 'after') => {\n const parentGroup = findParentGroup(elementId);\n if (!parentGroup) {\n log.warn(`Element ${elementId} is not inside a group`);\n return;\n }\n\n const child = parentGroup.children.find(c => c.id === elementId);\n if (!child) return;\n\n const artboardId = artboardManager.getArtboardIdForElement(parentGroup.id!);\n if (!artboardId) return;\n\n // Clone the child — children already use world coordinates, no conversion needed\n const promoted = child.clone();\n\n // Update group without this child\n const newGroup = parentGroup.clone() as GroupElement;\n newGroup.removeChild(elementId);\n\n handleElementUpdate(newGroup);\n\n // Insert at the specified position, or default to before the group\n if (targetId && position) {\n // position is already in array terms (inverted by caller)\n const insertAfter = position === 'after' ? targetId : undefined;\n const insertBefore = position === 'before' ? targetId : undefined;\n executeAddElement(promoted, artboardId, insertAfter, insertBefore);\n } else {\n // Default: insert before the group in array = below it visually\n executeAddElement(promoted, artboardId, undefined, parentGroup.id!);\n }\n handleSelectionChange(promoted.id);\n },\n [findParentGroup, artboardManager, executeRemoveElement, handleElementUpdate, executeAddElement, handleSelectionChange]\n );\n\n /** Create an empty group on the active artboard */\n const createEmptyGroup = useCallback(() => {\n const artboardId = artboardManager.getActiveArtboardId();\n if (!artboardId) {\n log.warn('No active artboard for creating a group');\n return;\n }\n\n const group = new GroupElement({\n x: 0,\n y: 0,\n name: 'New Group',\n });\n\n executeAddElement(group, artboardId);\n handleSelectionChange(group.id);\n }, [artboardManager, executeAddElement, handleSelectionChange]);\n\n return {\n layers,\n flatLayers,\n selectedLayers,\n selectLayer,\n selectMultipleLayers,\n clearSelection,\n toggleVisibility,\n toggleLock,\n renameLayer,\n deleteLayer,\n duplicateLayer,\n reorderLayers,\n reorderById,\n reorderWithinGroup,\n moveLayerForward,\n moveLayerBackward,\n groupLayers,\n ungroupLayer,\n addToGroup,\n removeFromGroup,\n createEmptyGroup,\n findElementById,\n findParentGroup,\n generateAllPreviews,\n clearPreviewCache,\n artboardId: effectiveArtboardId,\n artboardManager,\n layerCount: flatLayers.length,\n };\n}\n","/**\n * useArtboards - Hook for accessing artboard data and operations\n * Provides simplified interface for managing artboards in embed contexts\n */\n\nimport { useMemo, useCallback } from 'react';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport { createLogger } from '../utils/logger.js';\nimport type { ArtboardElement } from '../core/ArtboardElement.js';\nimport type { ClipShape, ArtboardDistressTexture } from '../types/index.js';\n\nconst logger = createLogger('useArtboards');\n\nexport interface ArtboardInfo {\n id: string;\n name: string;\n x: number;\n y: number;\n width: number;\n height: number;\n backgroundColor: string;\n clipShape?: ClipShape;\n isActive: boolean;\n elementCount: number;\n}\n\nexport interface UseArtboardsReturn {\n // All artboards\n artboards: ArtboardElement[];\n\n // Artboard info (simplified for external consumption)\n artboardsInfo: ArtboardInfo[];\n\n // Active artboard\n activeArtboard: ArtboardElement | null;\n activeArtboardId: string | null;\n activeArtboardInfo: ArtboardInfo | null;\n\n // Operations\n createArtboard: (width?: number, height?: number, config?: Partial<{\n name: string;\n x: number;\n y: number;\n backgroundColor: string;\n exportBackground: boolean;\n clipShape: ClipShape;\n }>) => void;\n deleteArtboard: (artboardId: string) => void;\n duplicateArtboard: (artboardId: string) => void;\n renameArtboard: (artboardId: string, newName: string) => void;\n updateArtboard: (artboardId: string, updates: Partial<{\n name: string;\n width: number;\n height: number;\n backgroundColor: string;\n clipShape: ClipShape;\n distressTexture: ArtboardDistressTexture | undefined;\n }>) => void;\n selectArtboard: (artboardId: string) => void;\n reorderArtboards: (fromIndex: number, toIndex: number) => void;\n\n // Count\n count: number;\n}\n\n/**\n * Hook to access artboard data and operations\n * Must be used within EditorProvider\n *\n * @example\n * ```tsx\n * function ArtboardSwitcher() {\n * const { artboardsInfo, selectArtboard, createArtboard } = useArtboards();\n *\n * return (\n * <div>\n * {artboardsInfo.map(ab => (\n * <button\n * key={ab.id}\n * onClick={() => selectArtboard(ab.id)}\n * className={ab.isActive ? 'active' : ''}\n * >\n * {ab.name} ({ab.width}×{ab.height})\n * </button>\n * ))}\n * <button onClick={() => createArtboard(1200, 1200)}>\n * + New Artboard\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport const useArtboards = (): UseArtboardsReturn => {\n const {\n artboards,\n artboardManager,\n refreshArtboards,\n setSelectedId,\n setMultiSelection,\n } = useEditor();\n\n const activeArtboardId = artboardManager.getActiveArtboardId();\n const activeArtboard = artboardManager.getActiveArtboard();\n\n // Convert artboards to simplified info objects\n const artboardsInfo = useMemo(() => {\n return artboards.map((artboard) => {\n // Count elements that belong to this artboard using ArtboardManager\n const elementIds = artboardManager.getElementsOnArtboard(artboard.id);\n const elementCount = elementIds.length;\n\n return {\n id: artboard.id,\n name: artboard.name,\n x: artboard.x,\n y: artboard.y,\n width: artboard.width,\n height: artboard.height,\n backgroundColor: artboard.backgroundColor,\n clipShape: artboard.clipShape,\n isActive: artboard.id === activeArtboardId,\n elementCount,\n };\n });\n }, [artboards, artboardManager, activeArtboardId]);\n\n // Active artboard info\n const activeArtboardInfo = useMemo(() => {\n if (!activeArtboard) return null;\n const elementIds = artboardManager.getElementsOnArtboard(activeArtboard.id);\n const elementCount = elementIds.length;\n return {\n id: activeArtboard.id,\n name: activeArtboard.name,\n x: activeArtboard.x,\n y: activeArtboard.y,\n width: activeArtboard.width,\n height: activeArtboard.height,\n backgroundColor: activeArtboard.backgroundColor,\n clipShape: activeArtboard.clipShape,\n isActive: true,\n elementCount,\n };\n }, [activeArtboard, artboardManager]);\n\n // Create new artboard\n const createArtboard = useCallback((\n width = 1200,\n height = 1200,\n config?: Partial<{\n name: string;\n x: number;\n y: number;\n backgroundColor: string;\n exportBackground: boolean;\n clipShape: ClipShape;\n }>\n ) => {\n // Build complete config object\n const artboardConfig = {\n width,\n height,\n ...config,\n };\n\n artboardManager.createArtboard(artboardConfig);\n refreshArtboards();\n }, [artboardManager, refreshArtboards]);\n\n // Delete artboard\n const deleteArtboard = useCallback((artboardId: string) => {\n artboardManager.deleteArtboard(artboardId);\n refreshArtboards();\n }, [artboardManager, refreshArtboards]);\n\n // Duplicate artboard\n const duplicateArtboard = useCallback((artboardId: string) => {\n const artboard = artboards.find(ab => ab.id === artboardId);\n if (!artboard) {\n logger.warn(`[useArtboards] Artboard ${artboardId} not found`);\n return;\n }\n\n // Create new artboard with same properties (including clipShape)\n artboardManager.createArtboard({\n width: artboard.width,\n height: artboard.height,\n name: `${artboard.name} Copy`,\n backgroundColor: artboard.backgroundColor,\n clipShape: artboard.clipShape,\n });\n\n // Note: Elements are not duplicated - only the artboard itself\n // To duplicate elements, use element operations separately\n\n refreshArtboards();\n }, [artboards, artboardManager, refreshArtboards]);\n\n // Rename artboard\n const renameArtboard = useCallback((artboardId: string, newName: string) => {\n const artboard = artboards.find(ab => ab.id === artboardId);\n if (!artboard) {\n logger.warn(`[useArtboards] Artboard ${artboardId} not found`);\n return;\n }\n\n artboard.name = newName;\n refreshArtboards();\n }, [artboards, refreshArtboards]);\n\n // Update artboard properties\n const updateArtboard = useCallback((\n artboardId: string,\n updates: Partial<{\n name: string;\n width: number;\n height: number;\n backgroundColor: string;\n clipShape: ClipShape;\n distressTexture: ArtboardDistressTexture | undefined;\n }>\n ) => {\n const artboard = artboards.find(ab => ab.id === artboardId);\n if (!artboard) {\n logger.warn(`[useArtboards] Artboard ${artboardId} not found`);\n return;\n }\n\n if (updates.name !== undefined) artboard.name = updates.name;\n if (updates.width !== undefined) artboard.width = updates.width;\n if (updates.height !== undefined) artboard.height = updates.height;\n if (updates.backgroundColor !== undefined) artboard.backgroundColor = updates.backgroundColor;\n if (updates.clipShape !== undefined) artboard.clipShape = updates.clipShape;\n if ('distressTexture' in updates) artboard.distressTexture = updates.distressTexture ? { ...updates.distressTexture } : undefined;\n\n refreshArtboards();\n }, [artboards, refreshArtboards]);\n\n // Select artboard - also clears selection to avoid stale element references\n const selectArtboard = useCallback((artboardId: string) => {\n // Clear selection before switching artboards\n // This prevents issues where selected elements from the previous artboard\n // remain visually selected on the new artboard\n setSelectedId(null);\n setMultiSelection([]);\n\n artboardManager.setActiveArtboard(artboardId);\n refreshArtboards();\n }, [artboardManager, refreshArtboards, setSelectedId, setMultiSelection]);\n\n // Reorder artboards\n const reorderArtboards = useCallback((fromIndex: number, toIndex: number) => {\n if (fromIndex === toIndex) return;\n if (fromIndex < 0 || fromIndex >= artboards.length) return;\n if (toIndex < 0 || toIndex >= artboards.length) return;\n\n const reordered = [...artboards];\n const [moved] = reordered.splice(fromIndex, 1);\n reordered.splice(toIndex, 0, moved);\n\n artboardManager.reorderArtboards(fromIndex, toIndex);\n refreshArtboards();\n }, [artboards, artboardManager, refreshArtboards]);\n\n return {\n artboards,\n artboardsInfo,\n activeArtboard,\n activeArtboardId,\n activeArtboardInfo,\n createArtboard,\n deleteArtboard,\n duplicateArtboard,\n renameArtboard,\n updateArtboard,\n selectArtboard,\n reorderArtboards,\n count: artboards.length,\n };\n};\n","/**\n * useExport - Hook for exporting artboards to images\n * Supports single export and continuous export (Sprint 2) for live mockup updates\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\nimport { useEditor } from '../contexts/EditorContext.js';\nimport { ExportManager } from '../utils/ExportManager.js';\nimport { createLogger } from '../utils/logger.js';\nimport type { ExportImageOptions } from '../utils/ExportManager.js';\n\nconst logger = createLogger('useExport');\n\nexport interface ExportProgress {\n artboardId: string;\n artboardName: string;\n status: 'pending' | 'rendering' | 'complete' | 'error';\n progress: number; // 0-100\n dataUrl?: string;\n error?: Error;\n timestamp: number;\n}\n\nexport interface ContinuousExportOptions {\n artboardIds?: string[]; // Default: all artboards\n interval?: number; // Milliseconds (default: 500)\n scale?: number; // Resolution multiplier (default: 3)\n format?: 'png' | 'jpg';\n onChange?: (results: Record<string, string>) => void; // Callback with new exports\n}\n\nexport interface UseExportReturn {\n // Single export\n exportArtboard: (\n artboardId: string,\n options?: ExportImageOptions\n ) => Promise<string>; // Returns data URL\n\n exportArtboardAsBlob: (\n artboardId: string,\n options?: ExportImageOptions\n ) => Promise<Blob>; // Returns Blob (more efficient for uploads)\n\n exportAllArtboards: (\n options?: ExportImageOptions\n ) => Promise<Record<string, string>>; // artboardId -> data URL\n\n exportAllArtboardsAsBlobs: (\n options?: ExportImageOptions\n ) => Promise<Record<string, Blob>>; // artboardId -> Blob\n\n // Continuous export (Sprint 2)\n startContinuousExport: (options: ContinuousExportOptions) => void;\n stopContinuousExport: () => void;\n\n // State\n isExporting: boolean;\n isContinuousExporting: boolean;\n progress: ExportProgress[];\n latestExports: Record<string, string>; // artboardId -> data URL\n\n // Worker stats\n supportsWorkerExport: boolean;\n workerStats: {\n totalExports: number;\n avgExportTime: number;\n isWorkerActive: boolean;\n };\n}\n\n/**\n * Hook for exporting artboards to images\n * Must be used within EditorProvider\n *\n * @example Single Export\n * ```tsx\n * function ExportButton() {\n * const { exportArtboard, isExporting } = useExport();\n * const { activeArtboardId } = useArtboards();\n *\n * const handleExport = async () => {\n * if (!activeArtboardId) return;\n * const dataUrl = await exportArtboard(activeArtboardId, {\n * scale: 3,\n * format: 'png'\n * });\n * // Download or display dataUrl\n * };\n *\n * return (\n * <button onClick={handleExport} disabled={isExporting}>\n * {isExporting ? 'Exporting...' : 'Export'}\n * </button>\n * );\n * }\n * ```\n *\n * @example Continuous Export (Sprint 2)\n * ```tsx\n * function LiveMockupPreview() {\n * const { startContinuousExport, stopContinuousExport, latestExports } = useExport();\n * const { artboardsInfo } = useArtboards();\n *\n * useEffect(() => {\n * startContinuousExport({\n * interval: 500,\n * scale: 3,\n * onChange: (exports) => {\n * // Send to mockup API\n * Object.entries(exports).forEach(([artboardId, dataUrl]) => {\n * const artboard = artboardsInfo.find(a => a.id === artboardId);\n * sendToMockupAPI(artboard.name, dataUrl);\n * });\n * }\n * });\n *\n * return () => stopContinuousExport();\n * }, []);\n *\n * return <div>Mockup preview...</div>;\n * }\n * ```\n */\nexport function useExport(): UseExportReturn {\n const {\n artboards,\n artboardManager,\n elements,\n canvasRef,\n } = useEditor();\n\n const [isExporting, setIsExporting] = useState(false);\n const [isContinuousExporting, setIsContinuousExporting] = useState(false);\n const [progress, setProgress] = useState<ExportProgress[]>([]);\n const [latestExports, setLatestExports] = useState<Record<string, string>>({});\n const [workerStats, setWorkerStats] = useState({\n totalExports: 0,\n avgExportTime: 0,\n isWorkerActive: false,\n });\n\n // Continuous export loop control\n // Each startContinuousExport call bumps the generation; any running loop\n // from a previous call sees the mismatch and exits without exporting again.\n const continuousExportGeneration = useRef(0);\n const continuousExportOptions = useRef<ContinuousExportOptions | null>(null);\n\n // Check if worker export is supported\n const supportsWorkerExport = ExportManager.supportsWorkerExport();\n\n /**\n * Export a single artboard\n */\n const exportArtboard = useCallback(async (\n artboardId: string,\n options: ExportImageOptions = {}\n ): Promise<string> => {\n const artboard = artboards.find(ab => ab.id === artboardId);\n if (!artboard) {\n throw new Error(`[useExport] Artboard ${artboardId} not found`);\n }\n\n if (!canvasRef.current) {\n throw new Error('[useExport] Canvas ref not available');\n }\n\n setIsExporting(true);\n\n // Add progress tracking\n const progressEntry: ExportProgress = {\n artboardId,\n artboardName: artboard.name,\n status: 'rendering',\n progress: 0,\n timestamp: Date.now(),\n };\n setProgress(prev => [...prev, progressEntry]);\n\n try {\n const startTime = Date.now();\n\n // Read elements fresh via ref — not from closure (which can be stale)\n const currentElements = elementsRef.current;\n const elementIds = artboardManager.getElementsOnArtboard(artboardId);\n const artboardElements = currentElements.filter(el => elementIds.includes(el.id));\n\n // Export using ExportManager (use exportArtboardToDataURL which returns string)\n const dataUrl = await ExportManager.exportArtboardToDataURL(\n artboard,\n artboardElements,\n canvasRef.current!,\n {\n format: options.format || 'png',\n scale: options.scale || 3,\n transparentBackground: options.transparentBackground ?? true,\n ...options,\n }\n );\n\n const exportTime = Date.now() - startTime;\n\n // Update progress\n setProgress(prev => prev.map(p =>\n p.artboardId === artboardId\n ? { ...p, status: 'complete', progress: 100, dataUrl, timestamp: Date.now() }\n : p\n ) as ExportProgress[]);\n\n // Update latest exports\n setLatestExports(prev => ({ ...prev, [artboardId]: dataUrl }));\n\n // Update worker stats\n setWorkerStats(prev => ({\n totalExports: prev.totalExports + 1,\n avgExportTime: (prev.avgExportTime * prev.totalExports + exportTime) / (prev.totalExports + 1),\n isWorkerActive: supportsWorkerExport,\n }));\n\n return dataUrl;\n } catch (error) {\n // Update progress with error\n setProgress(prev => prev.map(p =>\n p.artboardId === artboardId\n ? { ...p, status: 'error', error: error as Error, timestamp: Date.now() }\n : p\n ));\n throw error;\n } finally {\n setIsExporting(false);\n }\n }, [artboards, artboardManager, elements, canvasRef, supportsWorkerExport]);\n\n /**\n * Export all artboards in PARALLEL for maximum performance\n */\n const exportAllArtboards = useCallback(async (\n options: ExportImageOptions = {}\n ): Promise<Record<string, string>> => {\n setIsExporting(true);\n\n try {\n // Export ALL artboards in parallel using Promise.all\n const exportPromises = artboards.map(async (artboard) => {\n const dataUrl = await exportArtboard(artboard.id, options);\n return { id: artboard.id, dataUrl };\n });\n\n const exportResults = await Promise.all(exportPromises);\n\n // Convert array to record\n const results: Record<string, string> = {};\n for (const { id, dataUrl } of exportResults) {\n results[id] = dataUrl;\n }\n\n return results;\n } finally {\n setIsExporting(false);\n }\n }, [artboards, exportArtboard]);\n\n /**\n * Export a single artboard as Blob (more efficient for uploads)\n */\n // Ref to always read the latest elements — avoids stale closure in export callbacks.\n // Without this, the export callback captures `elements` from the render when the\n // callback was created, which can be 1-2 renders behind the actual current state.\n const elementsRef = useRef(elements);\n elementsRef.current = elements;\n\n const exportArtboardAsBlob = useCallback(async (\n artboardId: string,\n options: ExportImageOptions = {}\n ): Promise<Blob> => {\n const artboard = artboards.find(ab => ab.id === artboardId);\n if (!artboard) {\n throw new Error(`[useExport] Artboard ${artboardId} not found`);\n }\n\n if (!canvasRef.current) {\n throw new Error('[useExport] Canvas ref not available');\n }\n\n setIsExporting(true);\n\n try {\n // Read elements fresh via ref — not from closure (which can be stale)\n const currentElements = elementsRef.current;\n const elementIds = artboardManager.getElementsOnArtboard(artboardId);\n const artboardElements = currentElements.filter(el => elementIds.includes(el.id));\n\n // Export using ExportManager blob method\n const blob = await ExportManager.exportArtboardToBlob(\n artboard,\n artboardElements,\n canvasRef.current!,\n {\n format: options.format || 'png',\n scale: options.scale || 3,\n transparentBackground: options.transparentBackground ?? true,\n ...options,\n }\n );\n\n return blob;\n } finally {\n setIsExporting(false);\n }\n }, [artboards, artboardManager, elements, canvasRef]);\n\n /**\n * Export all artboards as Blobs in PARALLEL for maximum performance\n */\n const exportAllArtboardsAsBlobs = useCallback(async (\n options: ExportImageOptions = {}\n ): Promise<Record<string, Blob>> => {\n setIsExporting(true);\n\n try {\n // Export ALL artboards in parallel using Promise.all\n const exportPromises = artboards.map(async (artboard) => {\n const blob = await exportArtboardAsBlob(artboard.id, options);\n return { id: artboard.id, blob };\n });\n\n const exportResults = await Promise.all(exportPromises);\n\n // Convert array to record\n const results: Record<string, Blob> = {};\n for (const { id, blob } of exportResults) {\n results[id] = blob;\n }\n\n return results;\n } finally {\n setIsExporting(false);\n }\n }, [artboards, exportArtboardAsBlob]);\n\n /**\n * Stop continuous export (Sprint 2)\n */\n const stopContinuousExport = useCallback(() => {\n // Bump generation so any in-flight loop exits after its current export\n continuousExportGeneration.current++;\n setIsContinuousExporting(false);\n continuousExportOptions.current = null;\n }, []);\n\n /**\n * Start continuous export\n * Exports artboards at a specified interval for live mockup updates.\n * Uses a promise-based loop so a new export only starts after the previous\n * one completes, preventing unbounded queue buildup when exports are slow.\n */\n const startContinuousExport = useCallback((options: ContinuousExportOptions) => {\n // Invalidate any existing loop by bumping the generation counter\n continuousExportGeneration.current++;\n const myGeneration = continuousExportGeneration.current;\n\n // Store options\n continuousExportOptions.current = options;\n setIsContinuousExporting(true);\n\n const {\n artboardIds,\n interval = 500,\n scale = 3,\n format = 'png',\n onChange,\n } = options;\n\n // Determine which artboards to export\n const targetArtboards = artboardIds\n ? artboards.filter(ab => artboardIds.includes(ab.id))\n : artboards;\n\n // Returns true only while this particular loop instance is still active\n const isCurrentGeneration = () =>\n continuousExportGeneration.current === myGeneration;\n\n // Export function - exports ALL artboards in PARALLEL\n const performExport = async () => {\n try {\n const exportPromises = targetArtboards.map(async (artboard) => {\n const dataUrl = await exportArtboard(artboard.id, {\n scale,\n format,\n transparentBackground: true,\n });\n return { id: artboard.id, dataUrl };\n });\n\n const exportResults = await Promise.all(exportPromises);\n\n const results: Record<string, string> = {};\n for (const { id, dataUrl } of exportResults) {\n results[id] = dataUrl;\n }\n\n setLatestExports(prev => ({ ...prev, ...results }));\n\n if (onChange) {\n onChange(results);\n }\n } catch (error) {\n logger.error('[useExport] Continuous export error:', error);\n }\n };\n\n // Promise-based scheduling: perform export, wait for interval, repeat.\n // This guarantees no new export starts until the previous one finishes,\n // eliminating queue buildup when exports take longer than the interval.\n const runLoop = async () => {\n await performExport();\n while (isCurrentGeneration()) {\n await new Promise<void>(resolve => setTimeout(resolve, interval));\n if (!isCurrentGeneration()) break;\n await performExport();\n }\n };\n\n runLoop();\n }, [artboards, exportArtboard]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n stopContinuousExport();\n };\n }, [stopContinuousExport]);\n\n return {\n exportArtboard,\n exportArtboardAsBlob,\n exportAllArtboards,\n exportAllArtboardsAsBlobs,\n startContinuousExport,\n stopContinuousExport,\n isExporting,\n isContinuousExporting,\n progress,\n latestExports,\n supportsWorkerExport,\n workerStats,\n };\n}\n","/**\n * imageSearch — wire-contract types + proxy clients for the Image Browser's\n * privileged services (stock-image search, AI image generation).\n *\n * The canvas package NEVER talks to image/AI vendors directly and NEVER sees a\n * vendor API key. Instead, the embedder hosts same-origin proxy routes (the\n * `grantUrl` pattern) and hands their URLs to the canvas via the `services`\n * prop on `SnowconeCanvas` / `RealtimeEmbed`. Vendor keys live on the\n * embedder's server, behind those routes.\n *\n * Wire contract for `{imageSearchUrl}` (a www/Next route and an SDK server\n * handler are built against this exact shape — do not deviate):\n *\n * ```\n * GET {imageSearchUrl}?query=<string, may be empty>&page=<1-based int>&perPage=<int, default 30>\n * → 200 ImageSearchResponse\n * Empty query = featured/popular feed.\n * Errors: non-2xx with JSON { error: string }.\n *\n * POST {imageSearchUrl} body: { action: 'track-select', id, source, downloadLocation? }\n * → 200 { ok: true }\n * ```\n *\n * Wire contract for `{generateUrl}` (matches the existing www\n * `/api/generate-image` route):\n *\n * ```\n * POST {generateUrl} body: { prompt, width?, height?, numberResults? }\n * → 200 { images: Array<{ imageUrl: string }> }\n * Errors: non-2xx with JSON { error: string } (or { message }).\n * ```\n *\n * Wire contract for `{bgRemoveUrl}` (matches the existing www `/api/bg-remove`\n * route):\n *\n * ```\n * POST {bgRemoveUrl} body: { imageUrl: string (http(s) only) }\n * → 200 { imageUrl: string } (the background-removed image URL)\n * Errors: non-2xx with JSON { error: string } (or { message }).\n * ```\n */\n\n/** A single stock-image result, source-agnostic. */\nexport interface ImageSearchResult {\n /** Globally unique id, e.g. \"unsplash-abc123\". */\n id: string;\n /** Which upstream source produced this result. */\n source: 'unsplash' | 'pixabay';\n /** Intrinsic pixel width of the full image. */\n width: number;\n /** Intrinsic pixel height of the full image. */\n height: number;\n /** Alt text / description, when the source provides one. */\n alt: string | null;\n /** Renditions, smallest → largest. */\n urls: {\n thumb: string;\n small: string;\n regular: string;\n full: string;\n };\n /** Credit for the photographer/creator (display per source guidelines). */\n attribution: {\n name: string;\n username?: string;\n profileUrl?: string;\n sourceUrl?: string;\n };\n /**\n * Unsplash `download_location` — echoed back on track-select so the server\n * can trigger the download event (Unsplash API guideline when a photo is\n * actually used).\n */\n downloadLocation?: string;\n}\n\n/** Response shape for an image search page. */\nexport interface ImageSearchResponse {\n results: ImageSearchResult[];\n /** The 1-based page these results belong to. */\n page: number;\n /** Whether another page is available. */\n hasMore: boolean;\n}\n\n/** Parameters for one search page. Empty query = featured/popular feed. */\nexport interface ImageSearchParams {\n query: string;\n /** 1-based page number. */\n page: number;\n /** Results per page (default 30). */\n perPage?: number;\n}\n\n/**\n * Provider interface the Image Browser's search tab consumes. Usually created\n * from a URL via {@link createProxyImageSearch}; pass a custom implementation\n * through `services.imageSearch` for full control.\n */\nexport interface ImageSearchProvider {\n search(params: ImageSearchParams): Promise<ImageSearchResponse>;\n /**\n * Called (fire-and-forget) when a user selects a result. Implementations\n * should report usage upstream where required (e.g. Unsplash\n * `download_location`). Errors are ignored by the caller.\n */\n trackSelect?(result: ImageSearchResult): void | Promise<void>;\n}\n\n/** Parameters for an AI image generation request. */\nexport interface GenerateParams {\n prompt: string;\n width?: number;\n height?: number;\n numberResults?: number;\n}\n\n/** Response shape for an AI image generation request. */\nexport interface GenerateResponse {\n images: Array<{ imageUrl: string }>;\n}\n\n/**\n * Provider interface the Image Browser's \"remove background\" button consumes.\n * Given an image URL (the placed element's `imageUrl`), resolve to the\n * background-removed image URL. Usually created from a URL via\n * {@link createProxyBgRemove}; the server behind that URL holds the vendor key\n * and spends the per-op budget.\n */\nexport type BgRemoveProvider = (imageUrl: string) => Promise<string>;\n\n/**\n * Provider interface the Image Browser's AI tab consumes. Usually created from\n * a URL via {@link createProxyGenerate}; the server behind that URL picks the\n * model and holds the vendor key.\n */\nexport interface GenerateProvider {\n generate(params: GenerateParams): Promise<GenerateResponse>;\n}\n\n/** Extract a human-readable error from a proxy response, without ever leaking\n * internals. Prefers JSON `{ error }` then `{ message }`. */\nasync function readProxyError(response: Response, fallback: string): Promise<string> {\n try {\n const data: unknown = await response.json();\n if (data && typeof data === 'object') {\n const obj = data as { error?: unknown; message?: unknown };\n if (typeof obj.error === 'string' && obj.error) return obj.error;\n if (typeof obj.message === 'string' && obj.message) return obj.message;\n }\n } catch {\n // non-JSON body — fall through\n }\n return fallback;\n}\n\n/**\n * Create an {@link ImageSearchProvider} backed by a same-origin proxy route.\n *\n * @param url The embedder-hosted route implementing the image-search wire\n * contract. Host this URL on your server; your vendor keys live there.\n */\nexport function createProxyImageSearch(url: string): ImageSearchProvider {\n return {\n async search({ query, page, perPage = 30 }: ImageSearchParams): Promise<ImageSearchResponse> {\n const params = new URLSearchParams({\n query,\n page: String(page),\n perPage: String(perPage),\n });\n const sep = url.includes('?') ? '&' : '?';\n const response = await fetch(`${url}${sep}${params.toString()}`, {\n method: 'GET',\n credentials: 'same-origin',\n });\n if (!response.ok) {\n throw new Error(await readProxyError(response, `Image search failed (${response.status})`));\n }\n return (await response.json()) as ImageSearchResponse;\n },\n\n trackSelect(result: ImageSearchResult): void {\n // Fire-and-forget — selection must never block or surface errors.\n void fetch(url, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: 'track-select',\n id: result.id,\n source: result.source,\n ...(result.downloadLocation ? { downloadLocation: result.downloadLocation } : {}),\n }),\n }).catch(() => undefined);\n },\n };\n}\n\n/**\n * Create a {@link GenerateProvider} backed by a same-origin proxy route\n * (e.g. the www `/api/generate-image` route).\n *\n * @param url The embedder-hosted route. Host this URL on your server; your\n * vendor keys live there and the server picks the model.\n */\nexport function createProxyGenerate(url: string): GenerateProvider {\n return {\n async generate({ prompt, width, height, numberResults }: GenerateParams): Promise<GenerateResponse> {\n const response = await fetch(url, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ prompt, width, height, numberResults }),\n });\n if (!response.ok) {\n throw new Error(await readProxyError(response, `Image generation failed (${response.status})`));\n }\n const data = (await response.json()) as { images?: Array<{ imageUrl: string }>; imageUrl?: string };\n const images = data.images ?? (data.imageUrl ? [{ imageUrl: data.imageUrl }] : []);\n return { images };\n },\n };\n}\n\n/**\n * Unwrap a CORS-proxy form (`/api/image-proxy?url=<encoded>`) back to the\n * original URL. Placed canvas elements usually carry the proxy form so the\n * browser can read their pixels for export; the embedder's server can't fetch a\n * relative URL, so the bg-remove proxy needs the original. Same logic as www's\n * `deproxyImageUrl`, inlined so the canvas package has no app dependency.\n */\nfunction deproxyImageUrl(url: string): string {\n const marker = '/api/image-proxy?url=';\n if (!url || !url.startsWith(marker)) return url;\n try {\n return decodeURIComponent(url.slice(marker.length));\n } catch {\n return url;\n }\n}\n\n/**\n * Create a {@link BgRemoveProvider} backed by a same-origin proxy route\n * (e.g. the www `/api/bg-remove` route).\n *\n * The provider deproxies a `/api/image-proxy?url=…` source back to its original\n * URL, then rejects anything that isn't an `http(s)` URL — `data:` / `blob:`\n * sources (in-progress uploads) have no server-fetchable URL — before POSTing\n * `{ imageUrl }` and returning the `{ imageUrl }` it gets back.\n *\n * @param url The embedder-hosted route. Host this URL on your server; your\n * vendor key lives there and the server spends the per-op budget.\n */\nexport function createProxyBgRemove(url: string): BgRemoveProvider {\n return async function removeBackground(imageUrl: string): Promise<string> {\n // Placed elements usually carry the CORS proxy form\n // (/api/image-proxy?url=…) — the server can't fetch a relative URL, so send\n // the original. data:/blob: sources (in-progress uploads) have no\n // server-fetchable URL at all.\n const sourceUrl = deproxyImageUrl(imageUrl);\n if (!/^https?:\\/\\//.test(sourceUrl)) {\n throw new Error(\"Background removal isn't available for this image yet\");\n }\n const response = await fetch(url, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ imageUrl: sourceUrl }),\n });\n const data = (await response.json().catch(() => null)) as\n | { imageUrl?: string; error?: string; message?: string }\n | null;\n if (!response.ok || !data?.imageUrl) {\n throw new Error(data?.error || data?.message || `Background removal failed (${response.status})`);\n }\n return data.imageUrl;\n };\n}\n","'use client';\n\n/**\n * CanvasServicesContext — privileged-service wiring for the editor chrome.\n *\n * The Image Browser's search / AI / vector tabs need server-held vendor keys.\n * The canvas package never reads those keys; the embedder hosts same-origin\n * proxy routes (the `grantUrl` pattern) and passes their URLs — or full\n * provider implementations — through the `services` prop on `SnowconeCanvas`\n * or `RealtimeEmbed`. Tabs whose service isn't configured simply don't render.\n */\n\nimport React, { createContext, useContext, useMemo, type ReactNode } from 'react';\nimport {\n createProxyBgRemove,\n createProxyGenerate,\n createProxyImageSearch,\n type GenerateProvider,\n type ImageSearchProvider,\n} from '../services/imageSearch.js';\n\n/**\n * A vector/icon search result (dev-playground surface; no public wire\n * contract yet — typed loosely on purpose).\n */\nexport interface VectorSearchResult {\n id: string;\n /** The search term / icon name. */\n term: string;\n urls: {\n preview: string;\n svg?: string;\n png?: string;\n };\n uploader: { name: string };\n /** Final URL to insert when selected (already proxied if needed). Falls back\n * to `urls.svg` then `urls.png`. */\n selectUrl?: string;\n}\n\n/** Vector/icon search provider (dev-playground only for now). */\nexport interface VectorSearchProvider {\n /** Empty query = featured icons. `nextPage` is an opaque pagination token. */\n search(params: { query: string; nextPage?: string | null }): Promise<{\n results: VectorSearchResult[];\n nextPage: string | null;\n }>;\n}\n\n/**\n * Privileged services available to the editor chrome. All optional — an\n * unconfigured service hides its UI entirely.\n *\n * Shorthand URL props create proxy providers; explicit provider objects win\n * over their URL shorthand.\n */\nexport interface CanvasServices {\n /**\n * URL of your image-search proxy route (see `createProxyImageSearch` for the\n * wire contract). Host this URL on your server; your stock-image vendor keys\n * (Unsplash, Pixabay, …) live there.\n */\n imageSearchUrl?: string;\n /**\n * URL of your AI-generation proxy route (`POST { prompt, width?, height?,\n * numberResults? }` → `{ images: [{ imageUrl }] }`). Host this URL on your\n * server; your AI vendor keys live there and the server picks the model.\n */\n generateUrl?: string;\n /** Advanced override: full image-search provider. Wins over `imageSearchUrl`. */\n imageSearch?: ImageSearchProvider;\n /** Advanced override: full generation provider. Wins over `generateUrl`. */\n generate?: GenerateProvider;\n /** Vector/icon search provider (dev playground only — no wire contract yet). */\n vectors?: VectorSearchProvider;\n /**\n * URL of your background-removal proxy route (`POST { imageUrl }` →\n * `{ imageUrl }`; see `createProxyBgRemove` for the wire contract). Host this\n * URL on your server; your bg-remove vendor key lives there.\n */\n bgRemoveUrl?: string;\n /**\n * Advanced override: full background-removal provider. Given an image URL\n * (or data URL), resolve to the processed image URL/data URL. Wins over\n * `bgRemoveUrl`.\n */\n removeBackground?: (imageUrl: string) => Promise<string>;\n}\n\n/** The resolved providers consumers actually use. */\nexport interface ResolvedCanvasServices {\n imageSearch?: ImageSearchProvider;\n generate?: GenerateProvider;\n vectors?: VectorSearchProvider;\n removeBackground?: (imageUrl: string) => Promise<string>;\n}\n\nconst EMPTY_SERVICES: ResolvedCanvasServices = {};\n\nconst CanvasServicesContext = createContext<ResolvedCanvasServices>(EMPTY_SERVICES);\n\nexport interface CanvasServicesProviderProps {\n services?: CanvasServices;\n children?: ReactNode;\n}\n\n/**\n * Provides resolved service providers to the editor chrome. `SnowconeCanvas`\n * and `RealtimeEmbed` mount this automatically when given a `services` prop;\n * use it directly only when composing the lower-level pieces yourself.\n */\nexport function CanvasServicesProvider({ services, children }: CanvasServicesProviderProps): React.ReactElement {\n const value = useMemo<ResolvedCanvasServices>(() => {\n if (!services) return EMPTY_SERVICES;\n return {\n imageSearch:\n services.imageSearch ??\n (services.imageSearchUrl ? createProxyImageSearch(services.imageSearchUrl) : undefined),\n generate:\n services.generate ?? (services.generateUrl ? createProxyGenerate(services.generateUrl) : undefined),\n vectors: services.vectors,\n removeBackground:\n services.removeBackground ??\n (services.bgRemoveUrl ? createProxyBgRemove(services.bgRemoveUrl) : undefined),\n };\n // Keyed on the FIELD values (not the object identity) so an embedder\n // passing an inline `services={{ imageSearchUrl: '/api/…' }}` — the natural\n // way to write it — doesn't mint new providers on every render. Same\n // reasoning as RealtimeEmbed's productKey.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n services?.imageSearch,\n services?.imageSearchUrl,\n services?.generate,\n services?.generateUrl,\n services?.vectors,\n services?.bgRemoveUrl,\n services?.removeBackground,\n ]);\n\n return <CanvasServicesContext.Provider value={value}>{children}</CanvasServicesContext.Provider>;\n}\n\n/**\n * Read the resolved canvas services. Safe to call anywhere — outside a\n * provider it returns an empty object (every service-gated UI hides).\n */\nexport function useCanvasServices(): ResolvedCanvasServices {\n return useContext(CanvasServicesContext);\n}\n","/**\n * Service for fetching and managing all Google Fonts\n */\n\nimport { createLogger } from './logger';\n\nconst logger = createLogger('GoogleFontsService');\n\nexport interface GoogleFontMetadata {\n family: string;\n category: string;\n subsets?: string[];\n variants?: string[];\n version?: string;\n lastModified?: string;\n popularity?: number;\n}\n\nlet allGoogleFonts: GoogleFontMetadata[] = [];\nlet fetchPromise: Promise<GoogleFontMetadata[]> | null = null;\n\n/**\n * Fetch all Google Fonts from metadata endpoint\n * Results are cached after first fetch\n */\nexport async function fetchAllGoogleFonts(): Promise<GoogleFontMetadata[]> {\n // Return cached if available\n if (allGoogleFonts.length > 0) {\n return allGoogleFonts;\n }\n\n // Return existing promise if fetch in progress\n if (fetchPromise) {\n return fetchPromise;\n }\n\n // Start new fetch - Use local static file\n fetchPromise = fetch('/google-fonts.json')\n .then((response) => {\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n return response.json();\n })\n .then((data) => {\n\n // Handle font array format\n if (Array.isArray(data)) {\n allGoogleFonts = data.map((font: Record<string, unknown>) => ({\n family: font.family as string,\n category: (font.category as string) || 'sans-serif',\n subsets: (font.subsets as string[]) || [],\n variants: (font.variants as string[]) || [],\n popularity: font.popularity as number | undefined,\n }));\n } else {\n logger.error('Unexpected API response structure:', data);\n }\n return allGoogleFonts;\n })\n .catch((error) => {\n logger.error('Error fetching Google Fonts:', error);\n fetchPromise = null; // Reset promise on error so it can be retried\n return [];\n });\n\n return fetchPromise;\n}\n\n/**\n * Get all Google Fonts (uses cache if available)\n */\nexport function getAllGoogleFonts(): GoogleFontMetadata[] {\n return allGoogleFonts;\n}\n\n/**\n * Check if fonts have been loaded\n */\nexport function isFontsLoaded(): boolean {\n return allGoogleFonts.length > 0;\n}\n\n/**\n * Search Google Fonts by name\n */\nexport function searchGoogleFonts(query: string): GoogleFontMetadata[] {\n if (!query) return allGoogleFonts;\n\n const searchTerm = query.toLowerCase();\n return allGoogleFonts.filter((font) => font.family.toLowerCase().includes(searchTerm));\n}\n\n/**\n * Filter Google Fonts by category\n */\nexport function filterGoogleFontsByCategory(category: string): GoogleFontMetadata[] {\n if (!category || category === 'all') return allGoogleFonts;\n\n return allGoogleFonts.filter((font) => font.category.toLowerCase() === category.toLowerCase());\n}\n\n/**\n * Map Google Fonts category to our internal categories\n */\nexport function mapGoogleCategory(googleCategory: string): string {\n const mapping: Record<string, string> = {\n 'sans serif': 'sans-serif',\n serif: 'serif',\n display: 'display',\n handwriting: 'script',\n monospace: 'monospace',\n };\n\n return mapping[googleCategory.toLowerCase()] || 'display';\n}\n","/**\n * UnifiedFontService - System fonts + Google Fonts\n *\n * Features:\n * - Dual search strategy: text search + category filtering\n * - Font deduplication (by family name)\n * - Unified font loading (Google CSS link injection)\n *\n * Fonts the picker exposes must be on Google Fonts so they render\n * identically across iOS, macOS, Windows, Android, and ChromeOS.\n */\n\nimport { FontCategory, FontDefinition, TSHIRT_FONTS } from '../fonts/google-fonts.js';\nimport {\n fetchAllGoogleFonts,\n getAllGoogleFonts,\n isFontsLoaded as isGoogleFontsLoaded,\n GoogleFontMetadata,\n mapGoogleCategory,\n} from './GoogleFontsService.js';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('UnifiedFontService');\n\n// ============================================================================\n// UnifiedFontService Class\n// ============================================================================\n\nclass UnifiedFontServiceClass {\n // Search result cache\n private searchCache: Map<string, FontDefinition[]> = new Map();\n\n // Track preview font links for cleanup (prevents iOS Safari memory crashes)\n // With text= parameter, each preview font is ~0.1KB (not 50KB), so we can keep many loaded\n // Cleanup happens when drawer closes via clearPreviewFonts()\n private previewFontLinks: Set<string> = new Set();\n\n // ========================================\n // Initialization\n // ========================================\n\n /**\n * Initialize Google Fonts\n */\n async initialize(): Promise<void> {\n try {\n await fetchAllGoogleFonts();\n } catch (error) {\n logger.error('Failed to initialize UnifiedFontService:', error);\n // Graceful degradation: Continue even if Google Fonts fail\n }\n }\n\n /**\n * Check if fonts are loaded\n */\n isFontsLoaded(): boolean {\n return isGoogleFontsLoaded();\n }\n\n // ========================================\n // Font Retrieval\n // ========================================\n\n /**\n * Get all fonts.\n * Returns system fonts + Google Fonts (deduplicated)\n */\n getAllFonts(): FontDefinition[] {\n const systemFonts = TSHIRT_FONTS.filter(f => !f.googleFont);\n const googleFonts = this.mapGoogleFonts(getAllGoogleFonts());\n\n return this.mergeFonts([...systemFonts, ...googleFonts]);\n }\n\n /**\n * Get recommended fonts (TSHIRT_FONTS curated list)\n */\n getRecommendedFonts(): FontDefinition[] {\n return TSHIRT_FONTS;\n }\n\n // ========================================\n // Dual Search Strategy\n // ========================================\n\n /**\n * Search fonts by name (text search)\n */\n async searchFontsByName(query: string): Promise<FontDefinition[]> {\n if (!query.trim()) {\n return this.getAllFonts();\n }\n\n // Check cache\n const cacheKey = `search:${query.toLowerCase()}`;\n if (this.searchCache.has(cacheKey)) {\n return this.searchCache.get(cacheKey)!;\n }\n\n const normalizedQuery = query.toLowerCase().trim();\n\n // Search Google Fonts (client-side filter)\n const googleResults = getAllGoogleFonts()\n .filter((f) => f.family.toLowerCase().includes(normalizedQuery))\n .map((f) => this.mapGoogleFont(f));\n\n // Merge and deduplicate\n const results = this.mergeFonts(googleResults);\n\n // Cache results\n this.searchCache.set(cacheKey, results);\n\n return results;\n }\n\n /**\n * Filter fonts by category\n */\n async filterFontsByCategory(category: FontCategory): Promise<FontDefinition[]> {\n if (category === 'system') {\n // System fonts only\n return TSHIRT_FONTS.filter((f) => !f.googleFont);\n }\n\n // Check cache\n const cacheKey = `category:${category}`;\n if (this.searchCache.has(cacheKey)) {\n return this.searchCache.get(cacheKey)!;\n }\n\n // Filter Google Fonts (client-side)\n const googleResults = getAllGoogleFonts()\n .filter((f) => {\n const mappedCategory = mapGoogleCategory(f.category);\n return mappedCategory === category;\n })\n .map((f) => this.mapGoogleFont(f));\n\n // Merge and deduplicate\n const results = this.mergeFonts(googleResults);\n\n // Cache results\n this.searchCache.set(cacheKey, results);\n\n return results;\n }\n\n /**\n * Combined search: text search + category filter\n * Option A: Search overrides category (simpler UX)\n */\n async searchAndFilterFonts(\n query: string,\n category: FontCategory | 'all'\n ): Promise<FontDefinition[]> {\n if (query.trim()) {\n // Search overrides category\n return this.searchFontsByName(query);\n } else if (category !== 'all') {\n // Category filter\n return this.filterFontsByCategory(category);\n } else {\n // Show all\n return this.getAllFonts();\n }\n }\n\n // ========================================\n // Font Loading\n // ========================================\n\n /**\n * Load a font. All exposed fonts are Google fonts; the picker no\n * longer offers true \"system\" fonts that aren't on Google Fonts\n * because Android lacks them and we'd render inconsistently across\n * platforms.\n */\n async loadFont(font: FontDefinition): Promise<void> {\n try {\n if (font.googleFont) {\n this.loadGoogleFont(font.name);\n }\n } catch (error) {\n logger.error(`Failed to load font ${font.name}:`, error);\n }\n }\n\n /**\n * Load a Google Font by family name alone (full font, link injection).\n * For callers that only have a family string — e.g. `useFontBinding`\n * applying a template's designer-curated font option — not a full\n * {@link FontDefinition}. Idempotent per family.\n */\n loadGoogleFontByName(fontName: string): void {\n this.loadGoogleFont(fontName);\n }\n\n /**\n * Load Google Font via CSS link injection (full font)\n */\n private loadGoogleFont(fontName: string): void {\n // Check if font is already loaded\n const linkId = `font-${fontName.replace(/\\s+/g, '-').toLowerCase()}`;\n if (document.getElementById(linkId)) return;\n\n // Create link element\n const link = document.createElement('link');\n link.id = linkId;\n link.rel = 'stylesheet';\n link.href = `https://fonts.googleapis.com/css2?family=${fontName.replace(/\\s+/g, '+')}:wght@400;700&display=swap`;\n document.head.appendChild(link);\n }\n\n /**\n * Load Google Font with only specific characters (for previews)\n * Uses the text= parameter to load minimal glyphs (~99.9% smaller than full font)\n * See: https://developers.google.com/fonts/docs/getting_started#optimizing_your_font_requests\n *\n * @param fontName - Font family name\n * @param text - Text to render (only these characters will be loaded)\n */\n loadGoogleFontForPreview(fontName: string, text: string): void {\n // Encode text for URL (handles spaces, international characters, etc.)\n const encodedText = encodeURIComponent(text);\n // Use simple link ID based on font name only - we just need the font loaded\n // for preview, the exact characters don't matter for the ID\n const linkId = `font-preview-${fontName.replace(/\\s+/g, '-').toLowerCase()}`;\n\n // Check if already loaded\n if (document.getElementById(linkId)) return;\n\n // No eviction during browsing - with text= parameter each font is ~0.1KB\n // Cleanup happens when drawer closes via clearPreviewFonts()\n\n // Create link element with text= parameter for minimal glyph loading\n const link = document.createElement('link');\n link.id = linkId;\n link.rel = 'stylesheet';\n // Use text= parameter - only loads glyphs needed for the preview text\n link.href = `https://fonts.googleapis.com/css2?family=${fontName.replace(/\\s+/g, '+')}&display=swap&text=${encodedText}`;\n document.head.appendChild(link);\n this.previewFontLinks.add(linkId);\n }\n\n /**\n * Clear all preview font links from DOM\n * Call this when closing the font browser to free memory\n */\n clearPreviewFonts(): void {\n this.previewFontLinks.forEach((linkId) => {\n const link = document.getElementById(linkId);\n if (link) {\n link.remove();\n }\n });\n this.previewFontLinks.clear();\n }\n\n /**\n * Get count of loaded preview fonts\n */\n getPreviewFontCount(): number {\n return this.previewFontLinks.size;\n }\n\n // ========================================\n // Font Mapping & Merging\n // ========================================\n\n /**\n * Map Google Font metadata to FontDefinition\n */\n private mapGoogleFont(googleFont: GoogleFontMetadata): FontDefinition {\n return {\n name: googleFont.family,\n category: mapGoogleCategory(googleFont.category) as FontCategory,\n googleFont: true,\n source: 'google',\n weights: googleFont.variants\n ?.map((v) => {\n // Map variant strings like \"regular\", \"700\", \"700italic\" to numbers\n const match = v.match(/\\d+/);\n if (match) return parseInt(match[0], 10);\n if (v === 'regular') return 400;\n return null;\n })\n .filter((w): w is number => w !== null) || [400],\n };\n }\n\n /**\n * Map Google Fonts array to FontDefinitions\n */\n private mapGoogleFonts(googleFonts: GoogleFontMetadata[]): FontDefinition[] {\n return googleFonts.map((f) => this.mapGoogleFont(f));\n }\n\n /**\n * Merge fonts from multiple sources and deduplicate by family name\n */\n private mergeFonts(fonts: FontDefinition[]): FontDefinition[] {\n const fontMap = new Map<string, FontDefinition>();\n\n fonts.forEach((font) => {\n const key = font.name.toLowerCase().trim();\n\n // First occurrence wins\n if (!fontMap.has(key)) {\n fontMap.set(key, font);\n }\n });\n\n // Sort alphabetically\n return Array.from(fontMap.values()).sort((a, b) => a.name.localeCompare(b.name));\n }\n\n // ========================================\n // Cache Management\n // ========================================\n\n /**\n * Clear search cache\n */\n clearSearchCache(): void {\n this.searchCache.clear();\n }\n\n /**\n * Clear all caches\n */\n clearAllCaches(): void {\n this.clearSearchCache();\n }\n\n // ========================================\n // Stats & Debugging\n // ========================================\n\n /**\n * Get service stats for debugging\n */\n getStats() {\n const allFonts = this.getAllFonts();\n const googleFonts = allFonts.filter((f) => f.googleFont);\n const systemFonts = allFonts.filter((f) => !f.googleFont);\n\n return {\n initialized: this.isFontsLoaded(),\n totalFonts: allFonts.length,\n googleFontsCount: googleFonts.length,\n systemFontsCount: systemFonts.length,\n searchCacheSize: this.searchCache.size,\n };\n }\n}\n\n// Export singleton instance\nexport const UnifiedFontService = new UnifiedFontServiceClass();\n"],"names":["canvasIcons","isBrowser","registerCanvasIcons","addIcon","name","data","registrationStarted","ensureIconsRegistered","logger","createLogger","DEFAULT_OPTIONS","generateElementPreview","element","options","opts","canvas","ctx","GroupElement","renderGroupPreview","renderElementUsingActualRenderer","error","bbox","_a","elementWidth","elementHeight","renderFallbackPreview","availableWidth","availableHeight","scale","scaledWidth","scaledHeight","offsetX","offsetY","label","x","y","folderHeight","folderY","tabWidth","tabHeight","log","AUTO_REFRESH_PREVIEWS_DEBOUNCE_MS","generateElementPreviewAsync","size","backgroundColor","buildLayerTree","elements","selectedId","multiSelection","previewCache","generatePreview","depth","parentId","el","elParentId","isGroup","isSelected","layerInfo","flattenLayerTree","layers","result","layer","useLayers","filterArtboardId","includeHidden","previewSize","previewBackgroundColor","autoRefreshPreviews","artboardManager","handleSelectionChange","handleElementUpdate","setMultiSelection","executeAddElement","executeRemoveElement","executeReorderElement","useEditor","useRef","previewVersion","setPreviewVersion","useState","activeArtboardId","effectiveArtboardId","effectiveArtboard","resolvedPreviewBackgroundColor","useCallback","elementId","preview","v","filteredElements","useMemo","filtered","elementIds","flatLayers","selectedLayers","selectLayer","id","addToSelection","sid","selectMultipleLayers","ids","clearSelection","toggleVisibility","updated","toggleLock","renameLayer","deleteLayer","duplicateLayer","json","Constructor","clonedWithNewId","artboardId","reorderLayers","fromIndex","toIndex","draggedElement","targetElement","position","moveLayerForward","index","l","moveLayerBackward","groupLayers","elementsToGroup","artboardIds","uniqueArtboardIds","bboxes","minX","b","minY","group","clone","ungroupLayer","extractedChildren","child","generateAllPreviews","generateForElements","useEffect","timer","clearPreviewCache","reorderById","draggedId","targetId","reorderWithinGroup","groupId","newGroup","draggedIndex","c","targetIndex","dragged","newTargetIndex","insertIndex","findElementById","findParentGroup","addToGroup","childClone","removeFromGroup","parentGroup","promoted","createEmptyGroup","useArtboards","artboards","refreshArtboards","setSelectedId","activeArtboard","artboardsInfo","artboard","elementCount","activeArtboardInfo","createArtboard","width","height","config","artboardConfig","deleteArtboard","duplicateArtboard","ab","renameArtboard","newName","updateArtboard","updates","selectArtboard","reorderArtboards","useExport","canvasRef","isExporting","setIsExporting","isContinuousExporting","setIsContinuousExporting","progress","setProgress","latestExports","setLatestExports","workerStats","setWorkerStats","continuousExportGeneration","continuousExportOptions","supportsWorkerExport","ExportManager","exportArtboard","progressEntry","prev","startTime","currentElements","elementsRef","artboardElements","dataUrl","exportTime","p","exportAllArtboards","exportPromises","exportResults","results","exportArtboardAsBlob","exportAllArtboardsAsBlobs","blob","stopContinuousExport","startContinuousExport","myGeneration","interval","format","onChange","targetArtboards","isCurrentGeneration","performExport","resolve","readProxyError","response","fallback","obj","createProxyImageSearch","url","query","page","perPage","params","sep","createProxyGenerate","prompt","numberResults","deproxyImageUrl","marker","createProxyBgRemove","imageUrl","sourceUrl","EMPTY_SERVICES","CanvasServicesContext","createContext","CanvasServicesProvider","services","children","value","jsx","useCanvasServices","useContext","allGoogleFonts","fetchPromise","fetchAllGoogleFonts","font","getAllGoogleFonts","isFontsLoaded","mapGoogleCategory","googleCategory","UnifiedFontServiceClass","isGoogleFontsLoaded","systemFonts","TSHIRT_FONTS","f","googleFonts","cacheKey","normalizedQuery","googleResults","category","fontName","linkId","link","text","encodedText","googleFont","match","w","fonts","fontMap","key","a","allFonts","UnifiedFontService"],"mappings":"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"}
|
package/dist/advanced.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { e as te } from "./UnifiedFontService-
|
|
2
|
-
import { D as re, T as D, a as M, B as ne, b as I, r as se, v as ae, c as oe, d as ie, e as ce, f as le } from "./validation-
|
|
3
|
-
import { g as ot, h as it, i as ct, j as lt, k as dt, l as ut, m as mt, n as ft, o as ht, p as pt, q as xt, s as gt, t as bt, u as yt, F as vt, w as wt, G as St, I as Ct, x as Et, y as Tt, K as $t, z as kt, L as At, H as Ft, J as Pt, N as Nt, O as Rt, Q as Bt, S as Dt, R as Mt, U as It, V as zt, W as Ot, X as Lt, Y as Wt, Z as Kt, _ as _t, $ as Gt, a0 as Ut, a1 as jt, a2 as Jt, a3 as qt, a4 as Vt, a5 as Xt, a6 as Yt, a7 as Zt, a8 as Ht, a9 as Qt, aa as er, ab as tr, ac as rr, ad as nr, ae as sr, af as ar } from "./validation-
|
|
4
|
-
import { u as q } from "./EditorContext-
|
|
5
|
-
import { E as ir, P as cr, p as lr, s as dr, b as ur, c as mr, d as fr, e as hr, f as pr, a as xr } from "./EditorContext-
|
|
1
|
+
import { e as te } from "./UnifiedFontService-Dsu5cwfT.js";
|
|
2
|
+
import { D as re, T as D, a as M, B as ne, b as I, r as se, v as ae, c as oe, d as ie, e as ce, f as le } from "./validation-C795COGQ.js";
|
|
3
|
+
import { g as ot, h as it, i as ct, j as lt, k as dt, l as ut, m as mt, n as ft, o as ht, p as pt, q as xt, s as gt, t as bt, u as yt, F as vt, w as wt, G as St, I as Ct, x as Et, y as Tt, K as $t, z as kt, L as At, H as Ft, J as Pt, N as Nt, O as Rt, Q as Bt, S as Dt, R as Mt, U as It, V as zt, W as Ot, X as Lt, Y as Wt, Z as Kt, _ as _t, $ as Gt, a0 as Ut, a1 as jt, a2 as Jt, a3 as qt, a4 as Vt, a5 as Xt, a6 as Yt, a7 as Zt, a8 as Ht, a9 as Qt, aa as er, ab as tr, ac as rr, ad as nr, ae as sr, af as ar } from "./validation-C795COGQ.js";
|
|
4
|
+
import { u as q } from "./EditorContext-CGkfmbgo.js";
|
|
5
|
+
import { E as ir, P as cr, p as lr, s as dr, b as ur, c as mr, d as fr, e as hr, f as pr, a as xr } from "./EditorContext-CGkfmbgo.js";
|
|
6
6
|
import { T as br, u as yr } from "./ThemeContext-Rjz25x9X.js";
|
|
7
|
-
import { c as de, G as ue, F as me, g as fe, r as he, u as pe } from "./
|
|
8
|
-
import { A as wr, B as Sr, I as Cr, P as Er, R as Tr, S as $r, T as kr, h as Ar, a as Fr, b as Pr, i as Nr, d as Rr, e as Br, f as Dr, j as Mr, k as Ir, l as zr, m as Or, n as Lr, o as Wr, p as Kr, q as _r, s as Gr, t as Ur, v as jr, w as Jr, x as qr } from "./
|
|
9
|
-
import { I as xe } from "./ImportManager-
|
|
10
|
-
import { i as Xr, a as Yr, b as Zr, c as Hr, d as Qr } from "./ImportManager-
|
|
7
|
+
import { c as de, G as ue, F as me, g as fe, r as he, u as pe } from "./FontAnalyzer-CLv7_msL.js";
|
|
8
|
+
import { A as wr, B as Sr, I as Cr, P as Er, R as Tr, S as $r, T as kr, h as Ar, a as Fr, b as Pr, i as Nr, d as Rr, e as Br, f as Dr, j as Mr, k as Ir, l as zr, m as Or, n as Lr, o as Wr, p as Kr, q as _r, s as Gr, t as Ur, v as jr, w as Jr, x as qr } from "./FontAnalyzer-CLv7_msL.js";
|
|
9
|
+
import { I as xe } from "./ImportManager-C_wBjWaV.js";
|
|
10
|
+
import { i as Xr, a as Yr, b as Zr, c as Hr, d as Qr } from "./ImportManager-C_wBjWaV.js";
|
|
11
11
|
import { useState as A, useCallback as y, useEffect as V, useMemo as X, useRef as B, memo as ge } from "react";
|
|
12
12
|
import { e as be, c as ye } from "./compose-DtQL_oit.js";
|
|
13
13
|
import { jsxs as b, jsx as o, Fragment as ve } from "react/jsx-runtime";
|
|
14
|
-
import { P as tn, p as rn, u as nn } from "./usePieceGuideBundle-
|
|
14
|
+
import { P as tn, p as rn, u as nn } from "./usePieceGuideBundle-C1ipFnZd.js";
|
|
15
15
|
import { Icon as Y } from "./iconify-D6eVIEy4.js";
|
|
16
16
|
const ze = ({
|
|
17
17
|
title: e,
|
|
@@ -36,6 +36,13 @@ export declare class EditorPartsRegistry {
|
|
|
36
36
|
/** Mounted TextField registrations — Buy's required-layer list (C2/C3).
|
|
37
37
|
* Unmounted (incl. conditionally hidden) fields are absent by construction. */
|
|
38
38
|
getTextFields(): TextFieldRegistration[];
|
|
39
|
+
/** Bound-layer lookup for the mutation guard (ADR-0085 §3 /
|
|
40
|
+
* `E_BOUND_LAYER_MUTATION`): a layer is bound while ANY mounted
|
|
41
|
+
* `Editor.TextField` carries its name. Satisfies `BoundLayerGuard`
|
|
42
|
+
* structurally (subscribe/getVersion above). */
|
|
43
|
+
getBoundLayer(name: string): {
|
|
44
|
+
part: string;
|
|
45
|
+
} | null;
|
|
39
46
|
registerCanvasBridge(bridge: CanvasBridge): () => void;
|
|
40
47
|
getCanvasBridge(): CanvasBridge | null;
|
|
41
48
|
private bump;
|
|
@@ -39,7 +39,7 @@ export declare class DesignStateStore {
|
|
|
39
39
|
*/
|
|
40
40
|
updateTextLayer(name: string, text: string): void;
|
|
41
41
|
/** ≥1 element with visible content (completeness rule C4): non-empty text,
|
|
42
|
-
* an image with a URL, or a shape. */
|
|
42
|
+
* an image with a URL, or a shape. Hidden elements don't count. */
|
|
43
43
|
hasRenderableElement(): boolean;
|
|
44
44
|
private emit;
|
|
45
45
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
import { CanvasServices } from '../../contexts/CanvasServicesContext.js';
|
|
3
|
+
export interface EmbedRootProps {
|
|
4
|
+
/** Inherit the host app's theme instead of managing document-level theme. */
|
|
5
|
+
inheritTheme?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Skip mounting an `EditorProvider` — an ancestor (an `<Editor.Root>`, or a
|
|
8
|
+
* host-managed provider for shared mobile/desktop layouts) already provides
|
|
9
|
+
* the editor document.
|
|
10
|
+
*/
|
|
11
|
+
externalProvider?: boolean;
|
|
12
|
+
/** Privileged-service wiring (Image Browser search / AI generation). */
|
|
13
|
+
services?: CanvasServices;
|
|
14
|
+
/** Forwarded to `EditorProvider` (fitToArtboard fill fraction). */
|
|
15
|
+
viewPadding?: number;
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Provider shell for the embeddable canvas. `SnowconeCanvas` is
|
|
20
|
+
* `<EmbedRoot><KitLayout/></EmbedRoot>` plus the kernel hooks; custom layouts
|
|
21
|
+
* can reuse the same shell.
|
|
22
|
+
*/
|
|
23
|
+
export declare function EmbedRoot({ inheritTheme, externalProvider, services, viewPadding, children, }: EmbedRootProps): React.ReactElement;
|
|
@@ -719,6 +719,19 @@ export interface SnowconeCanvasProps {
|
|
|
719
719
|
* @default false
|
|
720
720
|
*/
|
|
721
721
|
externalProvider?: boolean;
|
|
722
|
+
/**
|
|
723
|
+
* Rebuild the editor document from scratch on mount: clear all artboards
|
|
724
|
+
* and elements before applying `artboards`/`initialElements`. Used by
|
|
725
|
+
* `Editor.Canvas` (P1 inversion): the editor document lives at
|
|
726
|
+
* `Editor.Root` and OUTLIVES Canvas mounts, so a remount must reflect the
|
|
727
|
+
* live seed instead of accreting onto the previous mount's document. The
|
|
728
|
+
* legacy `externalProvider` persistence semantics (mobile/desktop layout
|
|
729
|
+
* switch) are unchanged when this is false.
|
|
730
|
+
*
|
|
731
|
+
* @internal
|
|
732
|
+
* @default false
|
|
733
|
+
*/
|
|
734
|
+
resetDocumentOnMount?: boolean;
|
|
722
735
|
/**
|
|
723
736
|
* CSS class name for the container.
|
|
724
737
|
*/
|